From f588fa8dffb5a8956a78e1d8000268a581c15f17 Mon Sep 17 00:00:00 2001 From: ht Date: Fri, 22 Aug 2025 10:13:42 +0800 Subject: [PATCH] update Signed-off-by: ht --- data_object/bundle.json | 14 +- .../include/cloud_db_proxy.h | 6 +- .../collaboration_edit/include/db_store.h | 8 +- .../collaboration_edit/src/cloud_db_proxy.cpp | 48 +- .../collaboration_edit/src/db_store.cpp | 24 + .../src/db_store_manager.cpp | 2 + .../include/adaptor/asset_change_timer.h | 2 +- .../include/adaptor/client_adaptor.h | 3 + .../adaptor/distributed_objectstore_impl.h | 13 + .../adaptor/flat_object_storage_engine.h | 6 + .../include/adaptor/flat_object_store.h | 15 +- .../innerkitsimpl/include/adaptor/hitrace.h | 4 +- .../include/adaptor/object_callback_impl.h | 9 + .../include/adaptor/object_service.h | 2 + .../include/adaptor/object_storage_engine.h | 6 + .../innerkitsimpl/include/common/bytes.h | 1 + .../include/common/common_types.h | 5 +- .../innerkitsimpl/include/common/logger.h | 4 +- .../include/common/object_radar_reporter.h | 3 + .../include/communicator/block_data.h | 63 + .../communicator/communication_provider.h | 2 - .../include/communicator/softbus_adapter.h | 1 - .../include/communicator/task_scheduler.h | 207 + ...uteddata_object_store_ipc_interface_code.h | 6 +- .../innerkitsimpl/include/object_callback.h | 5 + .../include/object_callback_stub.h | 10 + .../innerkitsimpl/include/object_service.h | 3 + .../include/object_service_proxy.h | 3 + .../src/adaptor/asset_change_timer.cpp | 16 +- .../src/adaptor/client_adaptor.cpp | 5 +- .../adaptor/distributed_object_store_impl.cpp | 35 +- .../adaptor/flat_object_storage_engine.cpp | 54 +- .../src/adaptor/flat_object_store.cpp | 87 +- .../src/adaptor/object_callback_impl.cpp | 9 +- .../src/communicator/dev_manager.cpp | 12 +- .../communicator/softbus_adapter_standard.cpp | 43 +- .../src/object_callback_stub.cpp | 22 + .../src/object_radar_reporter.cpp | 4 - .../src/object_service_proxy.cpp | 75 +- .../test/fuzztest/objectstore_fuzzer/BUILD.gn | 9 +- .../objectstore_fuzzer/objectstore_fuzzer.cpp | 499 +- .../innerkitsimpl/test/unittest/BUILD.gn | 53 +- .../test/unittest/src/client_adaptor_test.cpp | 1 - .../test/unittest/src/communicator_test.cpp | 58 +- .../distributed_object_store_impl_test.cpp | 16 + .../src/object_callback_stub_test.cpp | 48 + .../src/object_service_proxy_test.cpp | 30 + .../test/unittest/src/object_store_test.cpp | 327 +- .../test/unittest/src/task_scheduler_test.cpp | 267 + .../jskitsimpl/collaboration_edit/BUILD.gn | 6 +- .../include/napi_async_call.h | 169 +- .../include/napi_collaboration_edit_object.h | 1 - .../src/napi_async_call.cpp | 18 + .../collaboration_edit/src/napi_cloud_db.cpp | 17 +- .../src/napi_collaboration_edit_object.cpp | 73 +- .../collaboration_edit/src/napi_edit_unit.cpp | 7 +- .../collaboration_edit/src/napi_node.cpp | 7 +- .../collaboration_edit/src/napi_text.cpp | 7 +- .../src/napi_undo_manager.cpp | 7 +- .../src/main/ets/Application/AbilityStage.ts | 4 +- .../entry/src/main/ets/test/EditUnit.ets | 6 +- .../entry/src/main/ets/test/List.test.ets | 14 +- .../entry/src/main/ets/test/Node.ets | 16 +- .../entry/src/main/ets/test/RunTest.ets | 651 + .../entry/src/main/ets/test/SetCloudDb.ets | 10 +- .../entry/src/main/ets/test/Text.ets | 2 +- .../entry/src/main/ets/test/UndoRedo.ets | 6 +- .../jskitsimpl/include/adaptor/js_common.h | 1 + .../include/adaptor/js_distributedobject.h | 4 +- .../include/adaptor/js_object_wrapper.h | 4 +- .../jskitsimpl/include/adaptor/js_watcher.h | 38 +- .../include/adaptor/progress_notifier_impl.h | 38 + .../jskitsimpl/include/common/napi_queue.h | 5 +- .../jskitsimpl/include/common/uv_queue.h | 4 +- .../src/adaptor/js_distributedobject.cpp | 5 +- .../src/adaptor/js_distributedobjectstore.cpp | 52 +- .../src/adaptor/js_object_wrapper.cpp | 5 +- .../jskitsimpl/src/adaptor/js_watcher.cpp | 157 +- .../src/adaptor/progress_notifier_impl.cpp | 77 + .../jskitsimpl/src/common/js_util.cpp | 5 +- .../jskitsimpl/src/common/napi_queue.cpp | 4 +- .../jskitsimpl/src/common/object_error.cpp | 3 +- .../jskitsimpl/src/common/uv_queue.cpp | 49 +- data_object/interfaces/innerkits/BUILD.gn | 5 +- .../interfaces/innerkits/distributed_object.h | 3 +- .../innerkits/distributed_objectstore.h | 22 + .../interfaces/innerkits/object_types.h | 1 - data_object/interfaces/jskits/BUILD.gn | 7 +- .../jskits/distributed_data_object.js | 137 +- data_share/CMakeLists.txt | 2 + data_share/CODEOWNERS | 4 +- data_share/README_zh.md | 4 +- data_share/bundle.json | 49 +- data_share/cfi_blocklist.txt | 2 + data_share/datashare.gni | 4 + .../cj/ffi/data_share_predicates/BUILD.gn | 1 + data_share/frameworks/js/ani/BUILD.gn | 23 + .../js/ani/common/include/ani_util_class.h | 215 + .../js/ani/common/include/ani_util_common.h | 187 + .../ani/common/include/ani_util_native_ptr.h | 129 + .../js/ani/common/include/ani_utils.h | 198 + .../include/datashare_predicates_cleaner.h | 65 + .../js/ani/common/src/ani_utils.cpp | 596 + .../frameworks/js/ani/dataShare/BUILD.gn | 145 + .../dataShare/ets/@ohos.data.dataShare.ets | 228 + .../ets/@ohos.data.dataSharePredicates.ets | 98 + .../dataShare/include/ani_datashare_helper.h | 26 + .../include/ani_datashare_inner_observer.h | 59 + .../include/ani_datashare_observer.h | 36 + .../dataShare/src/ani_datashare_helper.cpp | 683 + .../src/ani_datashare_inner_observer.cpp | 334 + .../dataShare/src/ani_datashare_observer.cpp | 39 + .../dataShare/src/data_share_predicates.cpp | 431 + .../js/ani/dataShareResultSet/BUILD.gn | 71 + .../ets/@ohos.data.DataShareResultSet.ets | 50 + .../src/data_share_result_set.cpp | 171 + .../js/napi/common/include/datashare_error.h | 1 + .../common/include/datashare_error_impl.h | 7 + .../napi/common/include/datashare_js_utils.h | 15 +- .../common/include/napi_callbacks_manager.h | 94 + .../napi/common/src/datashare_error_impl.cpp | 15 +- .../js/napi/common/src/datashare_js_utils.cpp | 323 +- .../common/src/datashare_predicates_proxy.cpp | 15 +- .../common/src/datashare_result_set_proxy.cpp | 6 +- .../frameworks/js/napi/dataShare/BUILD.gn | 3 + .../dataShare/include/napi_dataproxy_handle.h | 109 + .../dataShare/include/napi_datashare_helper.h | 2 + .../include/napi_datashare_inner_observer.h | 10 + .../dataShare/src/napi_dataproxy_handle.cpp | 429 + .../src/napi_datashare_const_properties.cpp | 25 + .../dataShare/src/napi_datashare_helper.cpp | 73 +- .../src/napi_datashare_inner_observer.cpp | 58 + .../dataShare/src/native_datashare_module.cpp | 2 + .../js/napi/observer/include/napi_observer.h | 21 +- .../include/napi_subscriber_manager.h | 38 + .../js/napi/observer/src/napi_observer.cpp | 103 +- .../observer/src/napi_subscriber_manager.cpp | 104 +- .../native/common/include/call_reporter.h | 12 +- .../native/common/include/callbacks_manager.h | 169 +- .../native/common/include/datashare_common.h | 32 + .../common/include/datashare_itypes_utils.h | 68 + ...ibuteddata_data_share_ipc_interface_code.h | 11 +- .../native/common/include/hitrace.h | 4 +- .../common/include/idata_share_service.h | 16 + .../native/common/include/idatashare.h | 10 + .../native/common/include/serializable.h | 266 + .../native/common/src/call_reporter.cpp | 83 +- .../common/src/datashare_itypes_utils.cpp | 248 + .../common/src/datashare_predicates.cpp | 32 + .../common/src/datashare_result_set.cpp | 26 +- .../native/common/src/serializable.cpp | 234 + .../native/common/src/shared_block.cpp | 2 +- .../controller/common/general_controller.h | 27 +- .../provider/include/ext_special_controller.h | 2 + .../general_controller_provider_impl.h | 11 +- .../provider/src/ext_special_controller.cpp | 15 + .../src/general_controller_provider_impl.cpp | 79 +- .../include/general_controller_service_impl.h | 28 +- .../src/general_controller_service_impl.cpp | 124 +- .../consumer/include/datashare_connection.h | 18 +- .../consumer/include/datashare_helper_impl.h | 34 + .../native/consumer/include/datashare_proxy.h | 14 + .../native/consumer/src/dataproxy_handle.cpp | 103 + .../consumer/src/datashare_connection.cpp | 72 +- .../native/consumer/src/datashare_helper.cpp | 45 +- .../consumer/src/datashare_helper_impl.cpp | 169 +- .../native/consumer/src/datashare_proxy.cpp | 123 +- .../native/dfx/include/hiview_datashare.h | 46 + .../native/dfx/src/hiview_datashare.cpp | 97 + .../include/data_share_called_config.h | 14 +- .../permission/include/data_share_config.h | 71 + .../src/data_share_called_config.cpp | 108 +- .../permission/src/data_share_config.cpp | 127 + .../permission/src/data_share_permission.cpp | 255 +- .../provider/include/datashare_ext_ability.h | 31 + .../native/provider/include/datashare_stub.h | 13 + .../provider/include/datashare_stub_impl.h | 2 + .../include/js_datashare_ext_ability.h | 9 + .../provider/src/datashare_ext_ability.cpp | 19 +- .../native/provider/src/datashare_stub.cpp | 127 +- .../provider/src/datashare_stub_impl.cpp | 100 +- .../provider/src/datashare_uv_queue.cpp | 8 +- .../provider/src/js_datashare_ext_ability.cpp | 55 +- .../src/js_datashare_ext_ability_context.cpp | 8 +- .../proxy/include/data_proxy_observer.h | 5 + .../proxy/include/data_proxy_observer_stub.h | 14 + .../proxy/include/data_share_manager_impl.h | 2 +- .../proxy/include/data_share_service_proxy.h | 16 +- .../include/proxy_data_subscriber_manager.h | 89 + .../native/proxy/src/ams_mgr_proxy.cpp | 2 +- .../proxy/src/data_proxy_observer_stub.cpp | 48 +- .../proxy/src/data_share_manager_impl.cpp | 10 +- .../proxy/src/data_share_service_proxy.cpp | 148 +- .../src/proxy_data_subscriber_manager.cpp | 185 + .../src/published_data_subscriber_manager.cpp | 47 +- .../proxy/src/rdb_subscriber_manager.cpp | 36 +- data_share/interfaces/inner_api/BUILD.gn | 19 +- .../interfaces/inner_api/common/BUILD.gn | 30 + .../common/include/dataproxy_handle_common.h | 114 + .../common/include/datashare_errno.h | 72 + .../common/include/datashare_observer.h | 1 + .../include/datashare_operation_statement.h | 4 + .../common/include/datashare_option.h | 25 + .../common/include/datashare_predicates.h | 11 + .../consumer/include/dataproxy_handle.h | 60 + .../consumer/include/datashare_helper.h | 76 +- .../consumer/include/datashare_result_set.h | 7 +- .../consumer/libdatashare_consumer.map | 1 + .../include/data_share_permission.h | 38 +- .../test/ets/data_share_ets/AppScope/app.json | 21 + .../resources/base/element/string.json | 8 + .../test/ets/data_share_ets/BUILD.gn | 33 +- data_share/test/ets/data_share_ets/Test.json | 27 + .../src/main/ets/Application/AbilityStage.ts | 22 + .../DataShareExtAbility.ts | 194 + .../src/main/ets/MainAbility/MainAbility.ts | 51 + .../ets/MainAbility/pages/index/index.ets | 57 + .../ets/MainAbility/pages/second/second.ets | 43 + .../src/main/ets/TestAbility/TestAbility.ts | 44 + .../src/main/ets/TestAbility/pages/index.ets | 48 + .../ets/TestRunner/OpenHarmonyTestRunner.ts | 71 + .../entry/src/main/ets/test/List.test.ets | 11 +- .../main/ets/test/dataSharePredicate.test.ets | 352 + .../main/ets/test/dataShareSubscribe.test.ets | 615 + .../data_share_ets/entry/src/main/module.json | 92 + .../main/resources/base/element/string.json | 44 + .../src/main/resources/base/media/icon.png | Bin 0 -> 15458 bytes .../resources/base/profile/form_config.json | 6 + .../resources/base/profile/form_config1.txt | 1 + .../main/resources/base/profile/invalid.txt | 5 + .../resources/base/profile/main_pages.json | 6 + .../base/profile/shortcuts_config.json | 6 + .../src/main/resources/base/profile/test.json | 4 + .../signature/openharmony_sx.p7b | Bin 0 -> 3623 bytes .../src => data_share/test/fuzztest}/BUILD.gn | 22 +- .../fuzztest/datasharehelp_fuzzer/BUILD.gn | 78 + .../datasharehelp_fuzzer}/corpus/init | 2 +- .../datasharehelp_fuzzer.cpp | 489 + .../datasharehelp_fuzzer.h | 21 + .../datasharehelp_fuzzer}/project.xml | 18 +- data_share/test/native/BUILD.gn | 551 +- .../DataShareClient/AppScope/app.json5 | 24 + .../resources/base/element/string.json | 8 + .../resources/base/media/app_icon.png | Bin 0 -> 6790 bytes .../main/ets/entryability/EntryAbility.ets | 45 + .../entry/src/main/ets/pages/Index.ets | 520 + .../src/main/ets/pages/myClient.test.ets | 452 + .../entry/src/main/module.json5 | 57 + .../main/resources/base/element/color.json | 8 + .../main/resources/base/element/string.json | 16 + .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../main/resources/base/media/startlcon.png | Bin 0 -> 6790 bytes .../resources/base/profile/main_pages.json | 5 + .../main/resources/en_US/element/string.json | 16 + .../main/resources/zh_CN/element/string.json | 16 + .../src/ohosTest/ets/test/Ability.test.ets | 35 + .../entry/src/ohosTest/ets/test/List.test.ets | 5 + .../ohosTest/ets/testability/TestAbility.ets | 50 + .../ohosTest/ets/testability/pages/Index.ets | 17 + .../ets/testrunner/OpenHarmonyTestRunner.ets | 47 + .../entry/src/ohosTest/module.json5 | 52 + .../resources/base/element/color.json | 8 + .../resources/base/element/string.json | 16 + .../ohosTest/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../resources/base/profile/test_pages.json | 5 + .../entry/src/test/List.test.ets | 5 + .../entry/src/test/LocalUnit.test.ets | 33 + .../hvigor/hvigor-config.json5 | 39 +- .../DataShareClient/sign/openharmony_sx.p7b | Bin 0 -> 3629 bytes .../DataShareService/AppScope/app.json5 | 28 + .../resources/base/element/string.json | 8 + .../resources/base/media/app_icon.png | Bin 0 -> 6790 bytes .../DataShareExtAbility.ts | 41 + .../main/ets/entryability/EntryAbility.ets | 72 + .../entry/src/main/ets/pages/Index.ets | 364 + .../src/main/ets/pages/myServer.test.ets | 375 + .../entry/src/main/module.json5 | 81 + .../main/resources/base/element/color.json | 8 + .../main/resources/base/element/string.json | 16 + .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../main/resources/base/media/startlcon.png | Bin 0 -> 6790 bytes .../resources/base/profile/main_pages.json | 5 + .../src/main/resources/base/profile/test.json | 5 + .../main/resources/en_US/element/string.json | 16 + .../main/resources/zh_CN/element/string.json | 16 + .../src/ohosTest/ets/test/Ability.test.ets | 35 + .../entry/src/ohosTest/ets/test/List.test.ets | 5 + .../ohosTest/ets/testability/TestAbility.ets | 50 + .../ohosTest/ets/testability/pages/Index.ets | 17 + .../ets/testrunner/OpenHarmonyTestRunner.ets | 47 + .../entry/src/ohosTest/module.json5 | 52 + .../resources/base/element/color.json | 8 + .../resources/base/element/string.json | 16 + .../ohosTest/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../resources/base/profile/test_pages.json | 5 + .../entry/src/test/List.test.ets | 5 + .../entry/src/test/LocalUnit.test.ets | 33 + .../hvigor/hvigor-config.json5 | 32 + .../DataShareService/sign/openharmony_sx.p7b | Bin 0 -> 3629 bytes .../entry/src/main/module.json | 31 +- .../AppScope/app.json5 | 24 + .../resources/base/element/string.json | 8 + .../resources/base/media/app_icon.png | Bin 0 -> 6790 bytes .../main/ets/entryability/EntryAbility.ets | 40 + .../entry/src/main/ets/pages/Index.ets | 362 + .../src/main/ets/pages/myClient.test.ets | 396 + .../entry/src/main/module.json5 | 57 + .../main/resources/base/element/color.json | 8 + .../main/resources/base/element/string.json | 16 + .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../main/resources/base/media/startlcon.png | Bin 0 -> 6790 bytes .../resources/base/profile/main_pages.json | 5 + .../main/resources/en_US/element/string.json | 16 + .../main/resources/zh_CN/element/string.json | 16 + .../sign/openharmony_sx.p7b | Bin 0 -> 3629 bytes .../native/resource/ohos_test/ohos_test.xml | 48 + .../native/resource/ohos_test_new/BUILD.gn | 10 +- .../resource/ohos_test_new/ohos_test_new.xml | 126 + .../AppScope/app.json5 | 24 + .../resources/base/element/string.json | 8 + .../resources/base/media/app_icon.png | Bin 0 -> 6790 bytes .../entry/src/main/AssetUtil.ets | 314 + .../entry/src/main/ets/FileUtil.ets | 27 + .../main/ets/entryability/EntryAbility.ets | 63 + .../entrybackupability/EntryBackupAbility.ets | 12 + .../entry/src/main/ets/pages/DataShare.ets | 60 + .../entry/src/main/ets/pages/Index.ets | 116 + .../entry/src/main/ets/pages/SystemApi.ets | 88 + .../entry/src/main/module.json5 | 100 + .../main/resources/base/element/color.json | 8 + .../main/resources/base/element/string.json | 16 + .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../main/resources/base/media/startlcon.png | Bin 0 -> 6790 bytes .../resources/base/profile/main_pages.json | 5 + .../main/resources/en_US/element/string.json | 16 + .../main/resources/zh_CN/element/string.json | 16 + .../sign/openharmony_sx.p7b | Bin 0 -> 3629 bytes .../dataproxy_handle_test.cpp | 670 + .../datashare_threshold_test.cpp | 762 + .../datashare_itypes_utils_test.cpp | 225 + .../proxydatas_with_permission_test.cpp | 797 +- .../long_time/concurrent_test/BUILD.gn | 52 + .../concurrent_subscriber_test.cpp | 501 + .../include/mediadatashare_unit_test.h | 2 +- .../src/abnormal_branch_test.cpp | 1090 +- .../src/controller_test.cpp | 1228 +- .../src/datashare_block_writer_impl_test.cpp | 193 + .../src/datashare_common_test.cpp | 725 + .../src/datashare_connection_test.cpp | 345 + .../src/datashare_helper_impl_test.cpp | 662 + .../src/datashare_helper_test.cpp | 254 + .../src/datashare_proxy_test.cpp | 221 + .../src/datashare_stub_test.cpp | 258 + .../src/errorcode_test.cpp | 68 +- .../mediadatashare_test/src/join_test.cpp | 86 +- .../src/mediadatashare_unit_test.cpp | 1419 +- .../src/permission_test.cpp | 360 +- .../src/shared_block_test.cpp | 549 + .../src/slientaccess_test.cpp | 815 +- .../src/slientswitch_test.cpp | 360 +- .../src/uri_utils_test.cpp | 314 + .../src/valueproxy_test.cpp | 27 + .../mock/ikvstore_data_service_mock.h | 36 + .../test/unittest/native}/BUILD.gn | 28 +- .../test/unittest/native/common/BUILD.gn | 235 + .../src/datashare_abs_result_set_test.cpp | 235 + .../src/datashare_block_writer_impl_test.cpp | 193 + .../common/src/datashare_result_set_test.cpp | 169 + .../datashare_valuebucket_convert_test.cpp | 50 + .../src/ishared_result_set_stub_test.cpp | 276 + .../test/unittest/native/consumer/BUILD.gn | 275 + .../include/ikvstore_data_service_mock.h | 36 + .../src/datashare_connection_test.cpp | 279 + .../src/datashare_helper_impl_test.cpp | 293 + .../consumer/src/datashare_helper_test.cpp | 227 + .../consumer/src/datashare_proxy_test.cpp | 191 + .../test/unittest/native/provider/BUILD.gn | 92 + .../provider/src/datashare_stub_test.cpp | 228 + datamgr_service/BUILD.gn | 2 + datamgr_service/bundle.json | 3 + datamgr_service/datamgr_service.gni | 2 + .../adapter/CMakeLists.txt | 19 +- .../adapter/account/BUILD.gn | 5 +- .../src/account_delegate_default_impl.cpp | 24 +- .../src/account_delegate_default_impl.h | 3 + .../account/src/account_delegate_impl.h | 2 +- .../adapter/account/test/BUILD.gn | 2 +- .../crypto => adapter/bundle_mgr}/BUILD.gn | 27 +- .../adapter/bundle_mgr/bundle_mgr_adapter.cpp | 110 + .../adapter/bundle_mgr/bundle_mgr_adapter.h | 58 + .../adapter/bundle_mgr/test/BUILD.gn | 42 + .../bundle_mgr/test/bundle_mgr_client.h | 191 + .../bundle_mgr/test/bundle_mgr_test.cpp | 49 +- .../adapter/communicator/BUILD.gn | 19 +- .../communicator/src/app_pipe_handler.cpp | 36 +- .../communicator/src/app_pipe_handler.h | 18 +- .../adapter/communicator/src/app_pipe_mgr.cpp | 71 +- .../adapter/communicator/src/app_pipe_mgr.h | 2 +- .../src/communication_provider_impl.cpp | 5 +- .../src/communication_provider_impl.h | 2 +- .../communicator/src/communicator_context.cpp | 7 +- .../src/device_manager_adapter.cpp | 50 +- .../src/process_communicator_impl.cpp | 27 +- .../communicator/src/softbus_adapter.h | 30 +- .../src/softbus_adapter_standard.cpp | 318 +- .../communicator/src/softbus_client.cpp | 116 +- .../adapter/communicator/src/softbus_client.h | 43 +- .../adapter/communicator/test/BUILD.gn | 128 +- .../fuzztest/softbusadapter_fuzzer/BUILD.gn | 15 +- .../softbusadapter_fuzzer.cpp | 21 +- .../mock/device_manager/device_manager.cpp | 145 + .../test/mock/device_manager/device_manager.h | 50 + .../device_manager/device_manager_callback.h | 37 + .../test/mock/device_manager/dm_device_info.h | 75 + .../test/mock/softbus/data_level.cpp | 46 +- .../test/mock/softbus/data_level.h | 42 + .../test/mock/softbus/inner_socket.cpp | 29 + .../test/mock/softbus/inner_socket.h | 23 + .../communicator/test/mock/softbus/socket.cpp | 116 + .../communicator/test/mock/softbus/socket.h | 98 + .../test/mock/softbus/softbus_error_code.h | 25 + .../unittest/app_pipe_mgr_service_test.cpp | 496 +- .../unittest/device_manager_adapter_test.cpp | 14 + .../process_communicator_impl_test.cpp | 981 +- .../softbus_adapter_standard_test.cpp | 1120 +- .../test/unittest/softbus_client_test.cpp | 560 +- .../adapter/dfx/BUILD.gn | 14 +- .../dfx/src/fault/cloud_sync_fault_impl.h | 6 +- .../dfx/src/fault/communication_fault_impl.h | 6 +- .../dfx/src/fault/database_fault_impl.h | 4 +- .../dfx/src/fault/runtime_fault_impl.h | 6 +- .../dfx/src/fault/service_fault_impl.h | 6 +- .../adapter/dfx/src/hiview_adapter.cpp | 19 +- .../adapter/dfx/src/reporter_impl.cpp | 2 +- .../api_performance_statistic_impl.h | 7 +- .../src/statistic/traffic_statistic_impl.h | 4 +- .../dfx/src/statistic/visit_statistic_impl.h | 4 +- .../adapter/dfx/test/BUILD.gn | 10 +- .../unittest/distributeddata_dfx_mst_test.cpp | 2 +- .../unittest/distributeddata_dfx_ut_test.cpp | 2 +- .../test/unittest/fake/hiview/fake_hiview.cpp | 2 +- .../test/unittest/hiview_adapter_dfx_test.cpp | 4 +- .../include/communicator/commu_types.h | 29 +- .../communicator/communication_provider.h | 2 +- .../communicator/communicator_context.h | 1 - .../communicator/device_manager_adapter.h | 6 +- .../communicator/process_communicator_impl.h | 9 +- .../include/communicator/route_head_handler.h | 3 +- .../adapter/network/BUILD.gn | 21 +- .../src/network_delegate_default_impl.cpp | 4 + .../src/network_delegate_default_impl.h | 2 +- .../src/network_delegate_normal_impl.cpp | 46 +- .../src/network_delegate_normal_impl.h | 5 + .../networkdelegatenormalimpl_fuzzer/BUILD.gn | 67 + .../corpus/init | 2 +- .../networkdelegatenormalimpl_fuzzer.cpp | 89 + .../networkdelegatenormalimpl_fuzzer.h | 11 +- .../project.xml | 20 +- .../network_delegate_normal_impl_test.cpp | 2 +- .../network/test/network_delegate_test.cpp | 2 +- .../adapter/schema_helper/BUILD.gn | 6 +- .../{src => }/get_schema_helper.cpp | 2 +- .../schema_helper/get_schema_helper.h | 0 .../adapter/screenlock/BUILD.gn | 18 +- .../screenlock/{src => }/screen_lock.cpp | 10 +- .../{include => }/screenlock/screen_lock.h | 0 .../adapter/screenlock/test/BUILD.gn | 21 +- .../test/fuzztest/screenlock_fuzzer/BUILD.gn | 56 + .../fuzztest/screenlock_fuzzer/corpus/init | 9 +- .../fuzztest/screenlock_fuzzer/project.xml | 25 + .../screenlock_fuzzer/screenlock_fuzzer.cpp | 106 + .../screenlock_fuzzer/screenlock_fuzzer.h | 10 +- .../screenlock/test/screen_lock_test.cpp | 62 +- .../adapter/test/BUILD.gn | 16 +- .../adapter/utils/BUILD.gn | 7 +- .../distributeddataservice/app/BUILD.gn | 11 +- .../distributeddataservice/app/CMakeLists.txt | 1 + .../app/distributed_data.cfg | 2 +- .../app/src/checker/BUILD.gn | 8 +- .../app/src/checker/bundle_checker.cpp | 36 +- .../app/src/checker/bundle_checker.h | 8 +- .../app/src/feature_stub_impl.cpp | 8 + .../app/src/feature_stub_impl.h | 1 + .../app/src/installer/BUILD.gn | 6 +- .../app/src/installer/installer_impl.cpp | 9 +- .../app/src/kvstore_account_observer.h | 2 +- .../app/src/kvstore_data_service.cpp | 363 +- .../app/src/kvstore_data_service.h | 28 +- .../app/src/kvstore_data_service_stub.cpp | 20 +- .../app/src/kvstore_data_service_stub.h | 2 + .../app/src/kvstore_meta_manager.cpp | 155 +- .../app/src/kvstore_meta_manager.h | 9 +- .../route_head_handler_impl.cpp | 237 +- .../session_manager/route_head_handler_impl.h | 21 +- .../src/session_manager/session_manager.cpp | 34 +- .../app/src/session_manager/session_manager.h | 9 +- .../src/session_manager/upgrade_manager.cpp | 41 +- .../app/src/session_manager/upgrade_manager.h | 11 +- .../distributeddataservice/app/test/BUILD.gn | 314 +- .../fuzztest/dataservicestub_fuzzer/BUILD.gn | 8 +- .../dataservicestub_fuzzer.cpp | 17 +- .../capability/device_manager_adapter.cpp | 30 + .../mock/capability/device_manager_adapter.h | 36 + .../capability/metadata/meta_data_manager.cpp | 84 + .../capability/metadata/meta_data_manager.h | 58 +- .../app/test/unittest/bundle_checker_test.cpp | 118 + .../test/unittest/feature_stub_impl_test.cpp | 38 +- .../unittest/kvstore_data_service_test.cpp | 363 +- .../kvstore_meta_manager_update_key_test.cpp | 337 + .../unittest/route_head_handler_impl_test.cpp | 240 + .../app/test/unittest/security_test.cpp | 206 + .../app/test/unittest/sensitive_test.cpp | 138 + .../test/unittest/session_manager_test.cpp | 846 +- .../test/unittest/upgrade_manager_test.cpp | 141 + .../distributeddataservice/framework/BUILD.gn | 25 +- .../framework/CMakeLists.txt | 9 +- .../app_access_check_config_manager.cpp | 45 + .../framework/account/account_delegate.cpp | 2 +- .../app_id_mapping_config_manager.cpp | 9 + .../framework/checker/checker_manager.cpp | 20 + .../framework/cloud/cloud_db.cpp | 8 +- .../framework/cloud/cloud_server.cpp | 5 + .../framework/cloud/schema_meta.cpp | 2 + .../communication/connect_manager.cpp | 5 +- .../crypto}/crypto_manager.cpp | 236 +- .../device_manager_delegate.cpp | 36 + .../device_sync_app_manager.cpp | 47 + .../framework/directory/directory_manager.cpp | 62 +- .../framework/feature/feature_system.cpp | 4 + .../app_access_check_config_manager.h | 39 + .../include/account/account_delegate.h | 2 +- .../app_id_mapping_config_manager.h | 2 +- .../include/changeevent/remote_change_event.h | 2 +- .../include/checker/checker_manager.h | 5 + .../framework/include/cloud/cloud_db.h | 4 +- .../framework/include/cloud/cloud_server.h | 1 + .../framework/include/cloud/schema_meta.h | 6 +- .../include/communication/connect_manager.h | 3 +- .../include/crypto}/crypto_manager.h | 87 +- .../device_manager/device_manager_delegate.h | 35 + .../device_manager/device_manager_types.h | 31 + .../device_sync_app/device_sync_app_manager.h | 39 + .../framework/include/dfx/dfx_types.h | 1 + .../include/directory/directory_manager.h | 8 +- .../include/feature/feature_system.h | 1 + .../include/metadata/capability_meta_data.h | 8 +- .../include/metadata/device_meta_data.h | 1 - .../include/metadata/meta_data_manager.h | 43 +- .../include/metadata/object_user_meta_data.h | 40 +- .../include/metadata/secret_key_meta_data.h | 2 + .../include/metadata/store_meta_data.h | 56 +- .../include/metadata/version_meta_data.h | 4 +- .../include/network/network_delegate.h | 4 +- .../include/serializable/serializable.h | 1 + .../framework/include/snapshot/snapshot.h | 4 - .../framework/include/store/auto_cache.h | 24 +- .../framework/include/store/general_store.h | 4 +- .../framework/include/store/general_value.h | 2 + .../framework/include/store/store_info.h | 1 + .../framework/include/thread/thread_manager.h | 2 +- .../framework/include/utils/constant.h | 14 + .../metadata/capability_meta_data.cpp | 14 + .../framework/metadata/device_meta_data.cpp | 2 - .../framework/metadata/meta_data_manager.cpp | 101 +- .../metadata/object_user_meta_data.cpp | 35 + .../metadata/secret_key_meta_data.cpp | 3 + .../framework/metadata/store_meta_data.cpp | 126 +- .../framework/serializable/serializable.cpp | 13 +- .../framework/store/auto_cache.cpp | 42 +- .../framework/test/BUILD.gn | 199 +- .../app_id_mapping_config_manager_test.cpp | 64 + .../framework/test/cloud_test.cpp | 17 +- .../framework/test/connect_manager_test.cpp | 70 + .../test/device_sync_app_manager_test.cpp | 98 + .../framework/test/fuzztest/BUILD.gn | 25 + .../fuzztest/screenmanager_fuzzer/BUILD.gn | 55 + .../fuzztest/screenmanager_fuzzer/corpus/init | 16 + .../fuzztest/screenmanager_fuzzer/project.xml | 25 + .../screenmanager_fuzzer.cpp | 30 +- .../screenmanager_fuzzer.h | 21 + .../fuzztest/storedebuginfo_fuzzer/BUILD.gn | 56 + .../storedebuginfo_fuzzer/corpus/init | 16 + .../storedebuginfo_fuzzer/project.xml | 25 + .../storedebuginfo_fuzzer.cpp | 55 + .../storedebuginfo_fuzzer.h | 21 + .../framework/test/meta_data_manager_test.cpp | 153 +- .../framework/test/meta_data_test.cpp | 103 +- .../framework/test/mock/db_store_mock.cpp | 375 + .../framework/test/mock/db_store_mock.h | 134 + .../framework/test/screen_manager_test.cpp | 52 + .../framework/test/serializable_test.cpp | 303 + .../framework/test/store_test.cpp | 58 + .../framework/utils/anonymous.cpp | 2 +- .../framework/utils/constant.cpp | 1 - .../framework/utils/corrupt_reporter.cpp | 8 +- .../rust/connect_adapter/BUILD.gn | 10 +- .../rust/connect_adapter/src/connect.cpp | 1 - .../rust/extension/BUILD.gn | 10 +- .../rust/extension/cloud_db_impl.cpp | 8 +- .../rust/extension/cloud_db_impl.h | 2 +- .../rust/extension/cloud_server_impl.cpp | 14 +- .../rust/extension/cloud_server_impl.h | 1 + .../rust/extension/extension_util.cpp | 15 + .../rust/extension/extension_util.h | 1 + .../distributeddataservice/rust/test/BUILD.gn | 65 + .../test/unittest/extension_util_test.cpp | 196 + .../rust/ylong_cloud_extension/BUILD.gn | 2 +- .../distributeddataservice/service/BUILD.gn | 18 +- .../service/CMakeLists.txt | 3 +- .../service/backup/BUILD.gn | 4 +- .../service/backup/include/backup_manager.h | 2 +- .../service/backup/src/backup_manager.cpp | 56 +- .../service/bootstrap/BUILD.gn | 4 +- .../service/bootstrap/include/bootstrap.h | 4 +- .../service/bootstrap/src/bootstrap.cpp | 37 +- .../service/cloud/BUILD.gn | 6 +- .../service/cloud/cloud_data_translate.cpp | 2 +- .../service/cloud/cloud_notifier_proxy.cpp | 59 + .../service/cloud/cloud_notifier_proxy.h | 41 + .../service/cloud/cloud_service_impl.cpp | 293 +- .../service/cloud/cloud_service_impl.h | 25 +- .../service/cloud/cloud_service_stub.cpp | 27 + .../service/cloud/cloud_service_stub.h | 2 + .../service/cloud/cloud_types_util.cpp | 12 + .../service/cloud/cloud_types_util.h | 7 + .../service/cloud/sync_manager.cpp | 277 +- .../service/cloud/sync_manager.h | 34 +- .../service/common/BUILD.gn | 4 +- .../service/common/xcollie.h | 5 +- .../service/config/BUILD.gn | 6 +- .../service/config/include/config_factory.h | 3 + .../include/model/app_access_check_config.h | 35 + .../config/include/model/datashare_config.h | 30 + .../model/device_sync_app_white_list_config.h | 37 + .../config/include/model/directory_config.h | 5 + .../config/include/model/global_config.h | 6 + .../service/config/src/config_factory.cpp | 15 + .../src/model/app_access_check_config.cpp | 46 + .../config/src/model/datashare_config.cpp | 32 + .../device_sync_app_white_list_config.cpp | 45 + .../config/src/model/directory_config.cpp | 19 +- .../config/src/model/global_config.cpp | 9 + .../service/data_share/BUILD.gn | 19 +- .../data_share/common/bundle_mgr_proxy.cpp | 24 +- .../data_share/common/bundle_mgr_proxy.h | 19 +- .../data_share/common/common_utils.cpp | 64 + .../service/data_share/common/common_utils.h | 41 + .../service/data_share/common/context.h | 10 +- .../service/data_share/common/db_delegate.cpp | 38 +- .../service/data_share/common/db_delegate.h | 9 +- .../common/extension_ability_manager.cpp | 2 +- .../common/extension_connect_adaptor.cpp | 2 +- .../data_share/common/extension_mgr_proxy.cpp | 2 +- .../service/data_share/common/kv_delegate.cpp | 57 +- .../service/data_share/common/kv_delegate.h | 3 + .../data_share/common/proxy_data_manager.cpp | 490 + .../data_share/common/proxy_data_manager.h | 101 + .../data_share/common/rdb_delegate.cpp | 79 +- .../service/data_share/common/rdb_delegate.h | 23 +- .../data_share/common/scheduler_manager.cpp | 46 +- .../data_share/common/scheduler_manager.h | 1 + .../common/{uri_utils.cpp => utils.cpp} | 28 +- .../common/{uri_utils.h => utils.h} | 19 +- .../data_share/data/published_data.cpp | 19 +- .../data_share/data_provider_config.cpp | 36 +- .../service/data_share/data_provider_config.h | 4 +- .../service/data_share/data_proxy_observer.h | 7 + .../data_share/data_share_db_config.cpp | 26 +- .../service/data_share/data_share_db_config.h | 2 +- .../data_share/data_share_obs_proxy.cpp | 28 +- .../service/data_share/data_share_obs_proxy.h | 11 + .../data_share/data_share_profile_config.cpp | 81 +- .../data_share/data_share_profile_config.h | 22 + .../data_share/data_share_service_impl.cpp | 284 +- .../data_share/data_share_service_impl.h | 25 +- .../data_share/data_share_service_stub.cpp | 160 +- .../data_share/data_share_service_stub.h | 15 +- .../data_share/data_share_silent_config.cpp | 4 +- .../data_share/dfx/hiview_fault_adapter.h | 1 + .../service/data_share/idata_share_service.h | 18 +- ...d_config_from_data_proxy_node_strategy.cpp | 14 +- ...g_from_data_share_bundle_info_strategy.cpp | 10 +- .../general/check_is_data_proxy_strategy.cpp | 2 +- .../general/load_config_common_strategy.cpp | 5 +- .../load_config_data_info_strategy.cpp | 24 +- .../strategies/get_data_strategy.cpp | 8 +- .../strategies/publish_strategy.cpp | 10 +- .../strategies/rdb_notify_strategy.cpp | 4 +- .../strategies/subscribe_strategy.cpp | 4 +- .../strategies/template_strategy.cpp | 4 +- .../proxy_data_subscriber_manager.cpp | 165 + .../proxy_data_subscriber_manager.h | 63 + .../published_data_subscriber_manager.cpp | 42 +- .../published_data_subscriber_manager.h | 11 +- .../rdb_subscriber_manager.cpp | 64 +- .../rdb_subscriber_manager.h | 3 +- .../data_share/sys_event_subscriber.cpp | 73 +- .../service/data_share/sys_event_subscriber.h | 17 +- .../service/dumper/BUILD.gn | 2 - .../service/kvdb/BUILD.gn | 2 - .../service/kvdb/auth_delegate.cpp | 3 - .../service/kvdb/auth_delegate.h | 4 +- .../service/kvdb/kvdb_exporter.cpp | 8 +- .../service/kvdb/kvdb_general_store.cpp | 85 +- .../service/kvdb/kvdb_service_impl.cpp | 210 +- .../service/kvdb/kvdb_service_impl.h | 5 + .../service/kvdb/kvdb_service_stub.cpp | 21 +- .../service/kvdb/kvdb_service_stub.h | 1 + .../service/kvdb/query_helper.cpp | 3 +- .../service/matrix/BUILD.gn | 3 +- .../service/object/BUILD.gn | 5 +- .../object/include/object_asset_loader.h | 2 +- .../object/include/object_asset_machine.h | 4 - .../object/include/object_callback_proxy.h | 14 + .../object/include/object_data_listener.h | 3 + .../service/object/include/object_manager.h | 57 +- .../object/include/object_service_impl.h | 9 +- .../object/include/object_service_stub.h | 4 + .../object/src/object_asset_loader.cpp | 31 +- .../object/src/object_asset_machine.cpp | 26 +- .../object/src/object_callback_proxy.cpp | 38 +- .../object/src/object_data_listener.cpp | 43 +- .../service/object/src/object_manager.cpp | 509 +- .../object/src/object_service_impl.cpp | 147 +- .../object/src/object_service_stub.cpp | 42 +- .../service/permission/BUILD.gn | 3 - .../permission/src/permit_delegate.cpp | 6 +- .../service/rdb/BUILD.gn | 3 - .../service/rdb/cache_cursor.cpp | 4 +- .../service/rdb/rdb_asset_loader.cpp | 12 +- .../service/rdb/rdb_asset_loader.h | 7 +- .../service/rdb/rdb_cloud.cpp | 19 +- .../service/rdb/rdb_cloud.h | 7 +- .../service/rdb/rdb_general_store.cpp | 190 +- .../service/rdb/rdb_general_store.h | 9 +- .../service/rdb/rdb_schema_config.cpp | 3 +- .../service/rdb/rdb_service_impl.cpp | 615 +- .../service/rdb/rdb_service_impl.h | 76 +- .../service/rdb/rdb_service_stub.cpp | 8 +- .../service/test/BUILD.gn | 1181 +- .../service/test/auth_delegate_mock_test.cpp | 2 +- .../test/backup_manager_service_test.cpp | 175 +- .../service/test/cloud_data_mock_test.cpp | 403 + .../service/test/cloud_data_test.cpp | 538 +- .../service/test/cloud_service_impl_test.cpp | 430 +- .../service/test/crypto_manager_test.cpp | 455 +- .../service/test/data_proxy_handle_test.cpp | 494 + .../service/test/data_share_common_test.cpp | 520 + .../data_share_scheduler_manager_test.cpp | 160 + .../test/data_share_service_impl_test.cpp | 146 +- .../data_share_subscriber_managers_test.cpp | 6 +- .../data_share_sys_event_subscriber_test.cpp | 67 + .../test/data_share_uri_utils_test.cpp | 55 +- .../service/test/directory_manager_test.cpp | 75 +- .../service/test/fuzztest/BUILD.gn | 17 +- .../fuzztest/cloudservicestub_fuzzer/BUILD.gn | 74 +- .../cloudservicestub_fuzzer.cpp | 31 +- .../datashareserviceimpl_fuzzer/BUILD.gn | 151 + .../datashareserviceimpl_fuzzer/corpus/init | 16 + .../datashareserviceimpl_fuzzer.cpp | 399 + .../datashareserviceimpl_fuzzer.h | 21 + .../datashareserviceimpl_fuzzer/project.xml | 25 + .../datashareservicestub_fuzzer/BUILD.gn | 15 +- .../datashareservicestub_fuzzer.cpp | 57 +- .../datasharesubscriber_fuzzer/BUILD.gn | 151 + .../datasharesubscriber_fuzzer/corpus/init | 16 + .../datasharesubscriber_fuzzer.cpp | 96 + .../datasharesubscriber_fuzzer.h | 21 + .../datasharesubscriber_fuzzer/project.xml | 25 + .../test/fuzztest/dumphelper_fuzzer/BUILD.gn | 20 +- .../dumphelper_fuzzer/dumphelper_fuzzer.cpp | 15 +- .../fuzztest/kvdbservicestub_fuzzer/BUILD.gn | 18 +- .../kvdbservicestub_fuzzer.cpp | 18 +- .../fuzztest/objectserviceimp_fuzzer/BUILD.gn | 74 + .../objectserviceimp_fuzzer/corpus/init | 16 + .../objectserviceimp_fuzzer.cpp | 171 + .../objectserviceimp_fuzzer.h | 21 + .../objectserviceimp_fuzzer/project.xml | 25 + .../objectservicelistener_fuzzer/BUILD.gn | 64 + .../objectservicelistener_fuzzer/corpus/init | 16 + .../objectservicelistener_fuzzer.cpp | 62 + .../objectservicelistener_fuzzer.h | 21 + .../objectservicelistener_fuzzer/project.xml | 25 + .../objectservicestub_fuzzer/BUILD.gn | 20 +- .../objectservicestub_fuzzer.cpp | 17 +- .../fuzztest/rdbresultsetstub_fuzzer/BUILD.gn | 15 +- .../rdbresultsetstub_fuzzer.cpp | 21 +- .../fuzztest/rdbservicestub_fuzzer/BUILD.gn | 52 +- .../rdbservicestub_fuzzer.cpp | 17 +- .../fuzztest/syncstrategies_fuzzer/BUILD.gn | 67 + .../syncstrategies_fuzzer/corpus/init | 16 + .../syncstrategies_fuzzer/project.xml | 25 + .../syncstrategies_fuzzer.cpp | 78 + .../syncstrategies_fuzzer.h | 21 + .../test/fuzztest/udmfservice_fuzzer/BUILD.gn | 10 +- .../udmfservice_fuzzer/udmfservice_fuzzer.cpp | 744 +- .../service/test/kv_dalegate_test.cpp | 461 +- .../test/kvdb_general_store_abnormal_test.cpp | 13 +- .../service/test/kvdb_general_store_test.cpp | 281 +- .../service/test/kvdb_service_impl_test.cpp | 250 +- .../test/kvdb_service_password_test.cpp | 201 + .../test/kvdb_service_stub_unittest.cpp | 136 +- .../service/test/kvdb_service_test.cpp | 2 +- .../service/test/meta_data_test.cpp | 9 +- .../service/test/mock/BUILD.gn | 11 + .../service/test/mock/access_token_mock.cpp | 16 + .../service/test/mock/access_token_mock.h | 4 + .../test/mock/account_delegate_mock.cpp | 2 +- .../service/test/mock/account_delegate_mock.h | 7 +- .../service/test/mock/auth_delegate_mock.cpp | 26 + .../service/test/mock/auth_delegate_mock.h | 38 + .../service/test/mock/checker_mock.cpp | 2 +- .../service/test/mock/cloud_db_mock.h | 51 + .../service/test/mock/config_factory_mock.cpp | 5 + .../service/test/mock/cursor_mock.h | 18 + .../service/test/mock/db_store_mock.cpp | 6 + .../service/test/mock/db_store_mock.h | 2 + .../test/mock/device_manager_adapter_mock.cpp | 34 + .../test/mock/device_manager_adapter_mock.h | 39 +- .../service/test/mock/device_matrix_mock.cpp | 29 + .../service/test/mock/device_matrix_mock.h | 37 + .../distributed_file_daemon_manager_mock.cpp | 45 + .../distributed_file_daemon_manager_mock.h | 122 + .../service/test/mock/general_store_mock.cpp | 18 +- .../test/mock/general_watcher_mock.cpp | 26 +- .../service/test/mock/general_watcher_mock.h | 14 +- .../kv_store_nb_delegate_corruption_mock.cpp | 353 + .../kv_store_nb_delegate_corruption_mock.h | 115 + .../test/mock/kv_store_nb_delegate_mock.cpp | 11 + .../test/mock/kv_store_nb_delegate_mock.h | 3 + .../test/mock/meta_data_manager_mock.cpp | 29 +- .../test/mock/meta_data_manager_mock.h | 25 +- .../test/mock/network_delegate_mock.cpp | 5 + .../service/test/mock/network_delegate_mock.h | 1 + .../test/mock/preprocess_utils_mock.cpp | 192 + .../service/test/mock/preprocess_utils_mock.h | 53 + .../mock/relational_store_delegate_mock.h | 191 + .../mock/relational_store_manager_mock.cpp | 43 + .../service/test/mock/user_delegate_mock.cpp | 2 +- .../service/test/object_asset_loader_test.cpp | 96 +- .../test/object_asset_machine_test.cpp | 70 +- .../service/test/object_manager_mock_test.cpp | 522 + .../service/test/object_manager_test.cpp | 1007 +- .../service/test/object_service_impl_test.cpp | 62 +- .../service/test/object_service_stub_test.cpp | 6 + .../service/test/object_snapshot_test.cpp | 18 +- .../service/test/ohos_test/BUILD.gn | 21 + .../service/test/ohos_test/ohos_test.xml | 28 + .../test/permit_delegate_mock_test.cpp | 15 +- .../service/test/rdb_asset_loader_test.cpp | 350 +- .../service/test/rdb_cloud_test.cpp | 296 +- .../service/test/rdb_general_store_test.cpp | 676 +- .../service/test/rdb_service_impl_test.cpp | 2464 ++ .../test/rdb_service_impl_token_test.cpp | 351 + .../service/test/testCloud/AppScope/app.json | 13 + .../resources/base/element/string.json | 8 + .../resources/base/media/app_icon.png | Bin 0 -> 6790 bytes .../service/test/testCloud/BUILD.gn | 44 + .../main/ets/Application/MyAbilityStage.ts | 22 + .../src/main/ets/MainAbility/MainAbility.ts | 55 + .../entry/src/main/ets/pages/index.ets | 31 + .../test/testCloud/entry/src/main/module.json | 40 + .../main/resources/base/element/color.json | 8 + .../main/resources/base/element/string.json | 16 + .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../resources/base/profile/main_pages.json | 5 + .../rawfile/arkdata/cloud/cloud_schema.json | 6 + .../testCloud/signature/openharmony_sx.p7b | Bin 0 -> 3529 bytes .../test/udmf_db_corruption_mock_test.cpp | 387 + .../test/udmf_preprocess_utils_mock_test.cpp | 132 + .../test/udmf_preprocess_utils_test.cpp | 193 + .../service/test/udmf_run_time_store_test.cpp | 212 +- .../test/udmf_service_impl_mock_test.cpp | 140 + .../service/test/udmf_service_impl_test.cpp | 463 +- .../test/unittest/cloud/cloud_data_test.cpp | 2 +- .../service/test/user_delegate_mock_test.cpp | 59 +- .../service/test/value_proxy_test.cpp | 54 +- .../service/udmf/BUILD.gn | 23 +- .../udmf/lifecycle/lifecycle_manager.cpp | 3 + .../udmf/lifecycle/lifecycle_policy.cpp | 16 +- .../service/udmf/lifecycle/lifecycle_policy.h | 2 + .../service/udmf/permission/checker_manager.h | 4 +- .../permission/uri_permission_manager.cpp | 2 +- .../service/udmf/preprocess/data_handler.cpp | 4 +- .../udmf/preprocess/preprocess_utils.cpp | 142 +- .../udmf/preprocess/preprocess_utils.h | 9 +- .../udmf/preprocess/udmf_notifier_proxy.cpp | 85 + .../udmf/preprocess/udmf_notifier_proxy.h | 48 + .../service/udmf/store/runtime_store.cpp | 152 +- .../service/udmf/store/runtime_store.h | 9 +- .../service/udmf/store/store.h | 2 +- .../udmf/store/store_account_observer.cpp | 47 - .../service/udmf/store/store_cache.cpp | 27 +- .../service/udmf/store/store_cache.h | 2 + .../service/udmf/udmf_service_impl.cpp | 666 +- .../service/udmf/udmf_service_impl.h | 39 +- .../service/udmf/udmf_service_stub.cpp | 61 + .../service/udmf/udmf_service_stub.h | 8 +- .../api/@ohos.data.UdmfComponents.d.ets | 112 + .../api/@ohos.data.ValuesBucket.d.ts | 10 + interface_sdk/api/@ohos.data.cloudData.d.ts | 38 + .../api/@ohos.data.cloudExtension.d.ts | 1 + interface_sdk/api/@ohos.data.dataShare.d.ts | 122 +- .../api/@ohos.data.dataSharePredicates.d.ts | 143 +- .../api/@ohos.data.distributedDataObject.d.ts | 114 +- .../api/@ohos.data.distributedKVStore.d.ts | 347 +- interface_sdk/api/@ohos.data.graphStore.d.ts | 551 + .../api/@ohos.data.intelligence.d.ts | 271 + interface_sdk/api/@ohos.data.preferences.d.ts | 804 +- .../api/@ohos.data.relationalStore.d.ts | 2000 +- .../api/@ohos.data.sendablePreferences.d.ets | 174 +- .../api/@ohos.data.unifiedDataChannel.d.ts | 645 +- .../api/@ohos.data.uniformDataStruct.d.ts | 263 +- .../api/@ohos.data.uniformTypeDescriptor.d.ts | 84 +- kv_store/CODEOWNERS | 6 +- kv_store/bundle.json | 44 +- kv_store/databaseutils/include/acl.h | 1 + kv_store/databaseutils/src/acl.cpp | 20 +- kv_store/databaseutils/test/BUILD.gn | 85 +- kv_store/databaseutils/test/acl_test.cpp | 24 +- .../databaseutils/test/bool_virtual_test.cpp | 540 - .../test/data_query_virtual_test.cpp | 1184 - .../datamgr_service_proxy_virtual_test.cpp | 324 - .../delegate_mgr_callback_virtual_test.cpp | 125 - ...stributed_kv_data_manager_vritual_test.cpp | 863 - .../test/kv_utils_virtual_test.cpp | 1053 - .../test/kvdb_notifier_virtual_test.cpp | 397 - .../kvstore_datashare_bridge_virtual_test.cpp | 740 - .../local_kv_store_counterfeit_unit_test.cpp | 1962 -- .../test/local_kv_store_sham_test.cpp | 2138 -- .../test/local_kv_store_sham_unit_test.cpp | 1959 -- .../test/local_kv_store_virtual_test.cpp | 2140 -- .../test/local_subscribe_store_sham_test.cpp | 2263 -- .../local_subscribe_store_virtual_test.cpp | 2272 -- .../single_kvstore_client_virtual_test.cpp | 1555 -- .../single_kvstore_query_virtual_test.cpp | 1474 -- .../test/single_store_impl_sham_test.cpp | 2130 -- .../test/single_store_impl_virtual_test.cpp | 2147 -- .../cj/include/distributed_kv_store_ffi.h | 2 + .../cj/include/distributed_kv_store_utils.h | 1 + .../cj/src/distributed_kv_store_ffi.cpp | 177 +- .../cj/src/distributed_kv_store_utils.cpp | 4 + kv_store/frameworks/common/dds_trace.h | 4 +- kv_store/frameworks/common/test/BUILD.gn | 14 +- .../common/test/executor_pool_test.cpp | 4 +- kv_store/frameworks/common/test/pool_test.cpp | 3 +- .../include/kvstore_client_death_observer.h | 31 + .../include/switch_observer_bridge.h | 44 + .../src/distributed_kv_data_manager.cpp | 6 +- .../src/switch_observer_bridge.cpp | 95 + .../distributeddatafwk/test/BUILD.gn | 90 +- .../test/unittest/blob_test.cpp | 22 +- ...stributed_kv_data_manager_encrypt_test.cpp | 60 +- ...ibuted_kv_data_manager_multi_user_test.cpp | 223 + .../distributed_kv_data_manager_test.cpp | 56 +- .../test/unittest/end_point_test.cpp | 1 + .../local_subscribe_device_store_test.cpp | 2 +- .../unittest/local_subscribe_store_test.cpp | 86 +- .../unittest/single_kvstore_client_test.cpp | 72 +- .../unittest/switch_observer_bridge_test.cpp | 87 + .../include/datamgr_service_proxy.h | 4 +- .../distributeddata_ipc_interface_code.h | 1 + .../include/ikvstore_data_service.h | 5 +- .../src/datamgr_service_proxy.cpp | 12 +- .../innerkitsimpl/kvdb/include/kvdb_service.h | 1 + .../kvdb/include/security_manager.h | 44 +- .../kvdb/include/single_store_impl.h | 3 +- .../kvdb/include/store_manager.h | 7 +- .../kvdb/src/kv_hiview_reporter.cpp | 22 +- .../kvdb/src/kvdb_service_client.cpp | 5 +- .../src/process_system_api_adapter_impl.cpp | 4 +- .../kvdb/src/security_manager.cpp | 273 +- .../kvdb/src/single_store_impl.cpp | 17 +- .../innerkitsimpl/kvdb/src/store_factory.cpp | 20 +- .../innerkitsimpl/kvdb/src/store_manager.cpp | 28 +- .../innerkitsimpl/kvdb/src/store_util.cpp | 23 +- .../innerkitsimpl/kvdb/src/task_executor.cpp | 2 +- .../innerkitsimpl/kvdb/test/BUILD.gn | 112 +- .../kvdb/test/backup_manager_test.cpp | 2 +- .../kvdb/test/dev_manager_mock_test.cpp | 10 - .../kvdb/test/kv_hiview_reporter_test.cpp | 93 + .../kvdb/test/mock/include/hisysevent_mock.h | 37 +- .../kvdb/test/mock/src/hisysevent_mock.cpp | 32 + .../kvdb/test/security_manager_test.cpp | 458 +- .../kvdb/test/single_store_impl_mock_test.cpp | 1262 ++ .../kvdb/test/single_store_impl_test.cpp | 154 +- .../kvdb/test/single_store_perf_pc_test.cpp | 4 +- .../test/single_store_perf_phone_test.cpp | 138 +- .../kvdb/test/store_factory_test.cpp | 194 +- .../include/js_const_properties.h | 2 +- .../distributeddata/include/js_util.h | 1 + .../distributeddata/src/js_kv_manager.cpp | 5 +- .../distributeddata/src/js_kv_store.cpp | 2 - .../src/js_single_kv_store.cpp | 2 - .../distributeddata/src/js_util.cpp | 20 +- .../include/js_kv_manager.h | 1 - .../distributedkvstore/include/js_util.h | 1 + .../distributedkvstore/src/entry_point.cpp | 18 +- .../src/js_const_properties.cpp | 32 +- .../src/js_device_kv_store.cpp | 12 + .../distributedkvstore/src/js_error_utils.cpp | 12 +- .../distributedkvstore/src/js_field_node.cpp | 23 +- .../distributedkvstore/src/js_kv_manager.cpp | 8 +- .../distributedkvstore/src/js_schema.cpp | 17 +- .../src/js_single_kv_store.cpp | 37 +- .../distributedkvstore/src/js_util.cpp | 22 +- .../frameworks/libs/distributeddb/BUILD.gn | 104 +- .../common/include/auto_launch.h | 2 +- .../common/include/cloud/cloud_db_constant.h | 2 +- .../common/include/concurrent_adapter.h | 1 + .../distributeddb/common/include/db_common.h | 4 +- .../common/include/db_constant.h | 38 +- .../distributeddb/common/include/db_errno.h | 2 + .../distributeddb/common/include/db_types.h | 1 + .../common/include/json_object.h | 5 +- .../distributeddb/common/include/log_print.h | 3 +- .../common/include/relational/prepared_stmt.h | 3 +- .../relational/relational_row_data_set.h | 2 +- .../relational/relational_schema_object.h | 7 +- .../common/include/relational/table_info.h | 6 + .../common/include/relational/tracker_table.h | 9 +- .../common/include/schema_constant.h | 59 +- .../common/include/schema_utils.h | 2 + .../distributeddb/common/include/version.h | 1 + .../distributeddb/common/src/auto_launch.cpp | 9 +- .../src/cloud/assets_download_manager.cpp | 1 - .../common/src/concurrent_adapter.cpp | 5 + .../distributeddb/common/src/db_common.cpp | 193 +- .../common/src/db_common_client.cpp | 182 + .../distributeddb/common/src/db_constant.cpp | 34 - .../common/src/db_dfx_adapter.cpp | 8 +- .../distributeddb/common/src/json_object.cpp | 49 +- .../distributeddb/common/src/log_print.cpp | 25 +- .../common/src/param_check_utils.cpp | 12 +- .../common/src/param_check_utils_client.cpp | 24 +- .../common/src/platform_specific.cpp | 28 +- .../common/src/relational/prepared_stmt.cpp | 43 +- .../relational/relational_schema_object.cpp | 33 +- .../common/src/relational/table_info.cpp | 34 +- .../common/src/relational/tracker_table.cpp | 40 +- .../common/src/schema_constant.cpp | 35 - .../common/src/schema_negotiate.cpp | 13 +- .../common/src/schema_object.cpp | 2 +- .../distributeddb/common/src/schema_utils.cpp | 85 +- .../common/src/schema_utils_client.cpp | 95 + .../common/src/user_change_monitor.cpp | 1 + .../communicator/include/combine_status.h | 2 + .../include/communicator_aggregator.h | 32 +- .../communicator/include/frame_retainer.h | 2 + .../communicator/include/iadapter.h | 11 +- .../communicator/include/icommunicator.h | 9 +- .../communicator/include/message.h | 14 +- .../communicator/include/network_adapter.h | 2 + .../communicator/include/parse_result.h | 3 + .../include/send_task_scheduler.h | 3 + .../communicator/src/communicator.cpp | 51 +- .../communicator/src/communicator.h | 6 +- .../src/communicator_aggregator.cpp | 218 +- .../communicator/src/communicator_linker.cpp | 4 +- .../communicator/src/frame_retainer.cpp | 4 +- .../communicator/src/network_adapter.cpp | 31 +- .../communicator/src/protocol_proto.cpp | 9 +- .../communicator/src/send_task_scheduler.cpp | 23 + .../libs/distributeddb/distributeddb.gni | 40 +- .../src/common/include/grd_api_manager.h | 8 +- .../src/common/src/grd_api_manager.cpp | 42 +- .../src/executor/base/grd_db_api.cpp | 66 +- .../executor/document/grd_document_api.cpp | 51 +- .../executor/document/grd_resultset_api.cpp | 44 +- .../gaussdb_rd/src/executor/kv/grd_kv_api.cpp | 93 +- .../src/interface/src/document_key.cpp | 14 +- .../src/oh_adapter/src/rd_sqlite_utils.cpp | 2 +- .../gaussdb_rd/test/unittest/BUILD.gn | 32 +- .../libs/distributeddb/include/types_export.h | 5 + .../include/cloud/cloud_store_types.h | 9 + .../include/iprocess_communicator.h | 33 +- .../include/kv_store_delegate_manager.h | 4 +- .../interfaces/include/kv_store_nb_delegate.h | 26 +- .../relational/relational_store_client.h | 15 + .../relational/relational_store_delegate.h | 10 +- .../relational/relational_store_sqlite_ext.h | 14 +- .../interfaces/include/store_types.h | 16 + .../src/kv_store_delegate_manager.cpp | 53 +- .../src/kv_store_nb_delegate_impl.cpp | 131 +- .../src/kv_store_nb_delegate_impl.h | 14 +- .../src/relational/knowledge_source_utils.cpp | 339 + .../src/relational/knowledge_source_utils.h | 55 + .../relational_store_delegate_impl.cpp | 21 +- .../relational_store_delegate_impl.h | 3 +- .../relational/relational_store_manager.cpp | 102 +- .../relational_store_manager_client.cpp | 94 + .../relational_store_sqlite_ext.cpp | 259 +- .../relational/relational_sync_able_storage.h | 20 +- .../src/tokenizer_export_type.h | 8 + .../sqlite_adapter/src/tokenizer_sqlite.cpp | 85 +- .../storage/include/db_properties.h | 3 + .../include/icloud_sync_storage_interface.h | 6 +- .../storage/include/ikvdb_connection.h | 4 +- .../storage/include/isync_interface.h | 2 + .../storage/include/kvdb_manager.h | 2 +- .../storage/include/kvdb_pragma.h | 32 + .../storage/include/kvdb_properties.h | 2 - .../include/relational_store_connection.h | 4 +- .../storage/include/storage_proxy.h | 10 +- .../storage/src/cloud/cloud_storage_utils.cpp | 218 - .../src/cloud/cloud_storage_utils_client.cpp | 248 + .../storage/src/data_transformer.h | 3 +- .../rd_single_ver_natural_store.cpp | 13 + .../gaussdb_rd/rd_single_ver_natural_store.h | 4 + ...rd_single_ver_natural_store_connection.cpp | 2 +- .../rd_single_ver_natural_store_connection.h | 2 +- .../gaussdb_rd/rd_single_ver_result_set.cpp | 2 + .../rd_single_ver_storage_engine.cpp | 28 +- .../gaussdb_rd/rd_single_ver_storage_engine.h | 4 +- .../storage/src/gaussdb_rd/rd_utils.cpp | 1 - .../storage/src/kv/generic_kvdb.cpp | 9 + .../storage/src/kv/generic_kvdb.h | 2 + .../src/kv/generic_kvdb_connection.cpp | 13 +- .../storage/src/kv/generic_kvdb_connection.h | 6 +- .../storage/src/kv/kvdb_manager.cpp | 12 +- .../storage/src/kv/kvdb_properties.cpp | 2 - .../storage/src/kv/sync_able_kvdb.cpp | 30 +- .../storage/src/kv/sync_able_kvdb.h | 6 +- .../src/kv/sync_able_kvdb_connection.cpp | 6 +- .../storage/src/multiver/multi_ver_vacuum.cpp | 2 +- .../operation/single_ver_database_oper.cpp | 33 +- .../src/operation/single_ver_database_oper.h | 2 + .../relational/relational_store_instance.cpp | 22 +- .../relational_sync_able_storage.cpp | 332 +- .../relational_sync_able_storage_extend.cpp | 364 +- .../storage/src/single_ver_natural_store.cpp | 2 +- .../collaboration_log_table_manager.cpp | 5 +- .../relational/log_table_manager_factory.cpp | 15 +- .../relational/log_table_manager_factory.h | 3 +- .../simple_tracker_log_table_manager.cpp | 8 +- .../simple_tracker_log_table_manager.h | 1 - .../sqlite_relational_database_upgrader.cpp | 2 +- .../relational/sqlite_relational_store.cpp | 226 +- .../relational/sqlite_relational_store.h | 22 +- .../sqlite_relational_store_connection.cpp | 16 +- .../sqlite_relational_store_connection.h | 4 +- .../relational/sqlite_relational_utils.cpp | 223 +- .../relational/sqlite_relational_utils.h | 41 +- .../sqlite_relational_utils_client.cpp | 335 + ...qlite_single_relational_storage_engine.cpp | 131 +- .../sqlite_single_relational_storage_engine.h | 14 +- ...single_ver_relational_storage_executor.cpp | 286 +- ...e_single_ver_relational_storage_executor.h | 28 +- ...ver_relational_storage_executor_extend.cpp | 39 +- ...ver_relational_storage_extend_executor.cpp | 158 +- .../sqlite/sqlite_cloud_kv_executor_utils.cpp | 45 +- .../sqlite/sqlite_cloud_kv_executor_utils.h | 5 +- .../src/sqlite/sqlite_cloud_kv_store.cpp | 161 +- .../src/sqlite/sqlite_cloud_kv_store.h | 15 +- .../src/sqlite/sqlite_log_table_manager.cpp | 28 +- .../src/sqlite/sqlite_log_table_manager.h | 6 +- .../src/sqlite/sqlite_meta_executor.cpp | 41 + .../storage/src/sqlite/sqlite_meta_executor.h | 3 + .../src/sqlite/sqlite_query_helper.cpp | 27 +- .../sqlite_single_ver_natural_store.cpp | 49 +- .../sqlite/sqlite_single_ver_natural_store.h | 9 + ...te_single_ver_natural_store_connection.cpp | 73 +- ...lite_single_ver_natural_store_connection.h | 8 +- ...sqlite_single_ver_natural_store_extend.cpp | 71 +- .../sqlite_single_ver_storage_engine.cpp | 126 +- .../sqlite/sqlite_single_ver_storage_engine.h | 19 +- .../sqlite_single_ver_storage_executor.cpp | 2 - .../sqlite_single_ver_storage_executor.h | 4 + ...ite_single_ver_storage_executor_extend.cpp | 11 + .../sqlite_single_ver_storage_executor_sql.h | 2 +- ..._single_ver_storage_executor_subscribe.cpp | 7 +- .../src/sqlite/sqlite_storage_engine.cpp | 2 +- .../storage/src/sqlite/sqlite_utils.cpp | 574 +- .../storage/src/sqlite/sqlite_utils.h | 2 + .../src/sqlite/sqlite_utils_client.cpp | 651 + .../src/sqlite/sqlite_utils_extend.cpp | 60 - .../storage/src/storage_engine.cpp | 216 +- .../storage/src/storage_engine.h | 15 +- .../storage/src/storage_proxy.cpp | 52 +- .../storage/src/sync_able_engine.cpp | 15 +- .../storage/src/sync_able_engine.h | 4 +- .../distributeddb/syncer/include/isyncer.h | 9 +- .../syncer/include/syncer_proxy.h | 6 +- .../syncer/src/cloud/cloud_db_proxy.cpp | 13 + .../syncer/src/cloud/cloud_db_proxy.h | 2 + .../syncer/src/cloud/cloud_sync_utils.cpp | 61 +- .../syncer/src/cloud/cloud_sync_utils.h | 11 + .../syncer/src/cloud/cloud_syncer.cpp | 66 +- .../syncer/src/cloud/cloud_syncer.h | 20 +- .../syncer/src/cloud/cloud_syncer_extend.cpp | 108 +- .../src/cloud/cloud_syncer_extend_extend.cpp | 121 + .../syncer/src/device/ability_sync.cpp | 31 +- .../syncer/src/device/communicator_proxy.cpp | 31 + .../syncer/src/device/communicator_proxy.h | 4 + .../syncer/src/device/generic_syncer.cpp | 46 +- .../syncer/src/device/generic_syncer.h | 16 +- .../syncer/src/device/isync_engine.h | 4 + .../syncer/src/device/isync_task_context.h | 8 +- .../syncer/src/device/meta_data.cpp | 287 +- .../syncer/src/device/meta_data.h | 95 +- .../multiver/multi_ver_sync_state_machine.cpp | 3 +- .../device/query_sync_water_mark_helper.cpp | 124 +- .../src/device/query_sync_water_mark_helper.h | 31 +- .../syncer/src/device/remote_executor.cpp | 8 +- .../syncer/src/device/remote_executor.h | 3 +- .../single_ver_data_message_schedule.cpp | 4 +- .../device/singlever/single_ver_data_packet.h | 7 +- .../device/singlever/single_ver_data_sync.cpp | 93 +- .../device/singlever/single_ver_data_sync.h | 4 +- .../singlever/single_ver_data_sync_utils.cpp | 16 +- .../device/singlever/single_ver_kv_syncer.cpp | 7 +- .../device/singlever/single_ver_kv_syncer.h | 2 +- .../single_ver_relational_syncer.cpp | 35 +- .../singlever/single_ver_relational_syncer.h | 19 +- .../singlever/single_ver_sync_engine.cpp | 2 +- .../single_ver_sync_state_machine.cpp | 29 +- .../singlever/single_ver_sync_state_machine.h | 7 +- .../single_ver_sync_task_context.cpp | 37 +- .../singlever/single_ver_sync_task_context.h | 10 +- .../device/singlever/single_ver_syncer.cpp | 2 +- .../syncer/src/device/sync_engine.cpp | 199 +- .../syncer/src/device/sync_engine.h | 22 +- .../syncer/src/device/sync_task_context.cpp | 21 +- .../syncer/src/device/sync_task_context.h | 5 + .../syncer/src/device/syncer_proxy.cpp | 10 +- .../syncer/src/device/time_sync.cpp | 67 +- .../syncer/src/device/time_sync.h | 13 +- .../syncer/src/sync_operation.cpp | 25 +- .../distributeddb/syncer/src/sync_operation.h | 8 + .../distributeddb/syncer/src/time_helper.cpp | 25 - .../syncer/src/time_helper_client.cpp | 46 + .../libs/distributeddb/test/BUILD.gn | 262 +- .../test/fuzztest/cloudsync_fuzzer/BUILD.gn | 10 +- .../cloudsync_fuzzer/cloudsync_fuzzer.cpp | 97 +- .../test/fuzztest/delegate_fuzzer/BUILD.gn | 17 +- .../delegate_fuzzer/delegate_fuzzer.cpp | 45 +- .../test/fuzztest/fileoper_fuzzer/BUILD.gn | 20 +- .../fileoper_fuzzer/fileoper_fuzzer.cpp | 45 +- .../test/fuzztest/importfile_fuzzer/BUILD.gn | 17 +- .../importfile_fuzzer/importfile_fuzzer.cpp | 23 +- .../iprocesscommunicator_fuzzer/BUILD.gn | 17 +- .../iprocesscommunicator_fuzzer.cpp | 18 +- .../test/fuzztest/json_fuzzer/BUILD.gn | 19 +- .../test/fuzztest/json_fuzzer/json_fuzzer.cpp | 92 +- .../test/fuzztest/jsoninner_fuzzer/BUILD.gn | 19 +- .../jsoninner_fuzzer/jsoninner_fuzzer.cpp | 92 +- .../kvdelegatemanager_fuzzer/BUILD.gn | 17 +- .../kvdelegatemanager_fuzzer.cpp | 52 +- .../fuzztest/kvstoreresultset_fuzzer/BUILD.gn | 17 +- .../kvstoreresultset_fuzzer.cpp | 16 +- .../test/fuzztest/nbdelegate_fuzzer/BUILD.gn | 17 +- .../nbdelegate_fuzzer/nbdelegate_fuzzer.cpp | 84 +- .../test/fuzztest/parseckeck_fuzzer/BUILD.gn | 17 +- .../parseckeck_fuzzer/parseckeck_fuzzer.cpp | 40 +- .../test/fuzztest/query_fuzzer/BUILD.gn | 17 +- .../fuzztest/query_fuzzer/query_fuzzer.cpp | 118 +- .../test/fuzztest/rekey_fuzzer/BUILD.gn | 17 +- .../fuzztest/rekey_fuzzer/rekey_fuzzer.cpp | 53 +- .../relationalstoredelegate_fuzzer/BUILD.gn | 17 +- .../relationalstoredelegate_fuzzer.cpp | 37 +- .../relationalstoremanager_fuzzer/BUILD.gn | 17 +- .../fuzztest/schemadelegate_fuzzer/BUILD.gn | 17 +- .../test/fuzztest/storage_fuzzer/BUILD.gn | 11 +- .../test/fuzztest/storage_fuzzer/project.xml | 2 +- .../storage_fuzzer/storage_fuzzer.cpp | 41 +- .../test/fuzztest/sync_fuzzer/BUILD.gn | 17 +- .../test/fuzztest/sync_fuzzer/sync_fuzzer.cpp | 99 +- .../distributeddb/test/moduletest/BUILD.gn | 234 +- .../include/distributeddb_data_generator.h | 4 +- .../src/distributeddb_constant.cpp | 2 +- .../common/common/basic_unit_test.cpp | 70 +- .../unittest/common/common/basic_unit_test.h | 15 +- .../common/distributeddb_auto_launch_test.cpp | 59 +- .../common/distributeddb_common_test.cpp | 26 +- .../distributeddb_data_compression_test.cpp | 6 +- .../distributeddb_data_generate_unit_test.h | 1 + .../distributeddb_json_precheck_unit_test.cpp | 259 +- .../distributeddb_notification_chain_test.cpp | 8 +- .../common/distributeddb_parcel_unit_test.cpp | 34 +- ...ibuteddb_relational_schema_object_test.cpp | 26 +- .../distributeddb_schema_object_test.cpp | 44 +- .../common/distributeddb_schema_unit_test.cpp | 16 +- .../common/distributeddb_thread_pool_test.cpp | 14 +- .../distributeddb_tools_unit_client_test.cpp | 182 + .../common/distributeddb_tools_unit_test.cpp | 219 +- .../common/distributeddb_tools_unit_test.h | 5 + .../common/common/evloop_timer_unit_test.cpp | 14 +- .../unittest/common/common/kv_general_ut.cpp | 123 +- .../unittest/common/common/kv_general_ut.h | 16 +- .../common/process_communicator_test_stub.h | 15 +- .../common/common/rdb_data_generator.cpp | 67 +- .../common/common/rdb_data_generator.h | 1 + .../common/rdb_data_generator_client.cpp | 84 + .../unittest/common/common/rdb_general_ut.cpp | 311 +- .../unittest/common/common/rdb_general_ut.h | 67 +- .../common/communicator/adapter_stub.cpp | 26 +- .../common/communicator/adapter_stub.h | 7 + .../distributeddb_communicator_deep_test.cpp | 132 +- ...buteddb_communicator_send_receive_test.cpp | 55 +- .../distributeddb_communicator_test.cpp | 85 +- .../communicator/mock_process_communicator.h | 4 +- ...uteddb_cloud_interfaces_reference_test.cpp | 67 +- ..._interfaces_relational_ext_client_test.cpp | 1477 ++ ...b_cloud_interfaces_relational_ext_test.cpp | 247 +- ...ces_relational_remove_device_data_test.cpp | 62 +- ...cloud_interfaces_set_cloud_schema_test.cpp | 40 +- ...tributeddb_interfaces_auto_launch_test.cpp | 20 +- ..._interfaces_data_operation_syncdb_test.cpp | 48 +- ...buteddb_interfaces_data_operation_test.cpp | 102 +- ...teddb_interfaces_database_corrupt_test.cpp | 20 +- ...ddb_interfaces_database_rd_kernel_test.cpp | 20 +- ...distributeddb_interfaces_database_test.cpp | 102 +- ...eddb_interfaces_device_identifier_test.cpp | 63 +- ...teddb_interfaces_encrypt_database_test.cpp | 18 +- ...teddb_interfaces_encrypt_delegate_test.cpp | 40 +- ...b_interfaces_import_and_export_rd_test.cpp | 4 +- ...eddb_interfaces_import_and_export_test.cpp | 36 +- ...stributeddb_interfaces_index_unit_test.cpp | 24 +- .../distributeddb_interfaces_log_test.cpp | 3 +- ...ddb_interfaces_nb_delegate_extend_test.cpp | 20 +- ...nterfaces_nb_delegate_local_batch_test.cpp | 28 +- ...interfaces_nb_delegate_schema_put_test.cpp | 8 +- ...tributeddb_interfaces_nb_delegate_test.cpp | 220 +- ...stributeddb_interfaces_nb_publish_test.cpp | 22 +- ...buteddb_interfaces_nb_transaction_test.cpp | 36 +- ...ributeddb_interfaces_nb_unpublish_test.cpp | 10 +- .../distributeddb_interfaces_query_test.cpp | 6 +- ...uteddb_interfaces_register_syncdb_test.cpp | 76 +- ...stributeddb_interfaces_relational_test.cpp | 190 +- ...terfaces_relational_tracker_table_test.cpp | 148 +- ...teddb_interfaces_resultset_performance.cpp | 2 +- ...nterfaces_schema_database_upgrade_test.cpp | 28 +- ...erfaces_single_version_result_set_test.cpp | 30 +- ...teddb_interfaces_space_management_test.cpp | 12 +- ...terfaces_transaction_optimization_test.cpp | 18 +- ...ddb_interfaces_transaction_syncdb_test.cpp | 40 +- ...tributeddb_interfaces_transaction_test.cpp | 42 +- ...t_process_system_api_adapter_impl_test.cpp | 18 +- ...teddb_cloud_assets_operation_sync_test.cpp | 56 +- .../distributeddb_cloud_check_sync_test.cpp | 146 +- ..._cloud_interfaces_relational_sync_test.cpp | 167 +- .../distributeddb_cloud_meta_data_test.cpp | 5 +- ...istributeddb_cloud_reference_sync_test.cpp | 24 +- ...stributeddb_cloud_save_cloud_data_test.cpp | 36 +- .../distributeddb_cloud_task_merge_test.cpp | 4 +- .../distributeddb_file_package_test.cpp | 16 +- .../distributeddb_multi_ver_vacuum_test.cpp | 20 +- ...distributeddb_query_object_helper_test.cpp | 6 +- .../distributeddb_rdb_collaboration_test.cpp | 230 +- ...relational_cloud_syncable_storage_test.cpp | 110 +- ...ributeddb_relational_encrypted_db_test.cpp | 56 +- ...distributeddb_relational_get_data_test.cpp | 44 +- ...ributeddb_relational_remote_query_test.cpp | 22 +- ...stributeddb_relational_result_set_test.cpp | 78 +- ...uteddb_relational_schema_analysis_test.cpp | 8 +- ...teddb_relational_syncable_storage_test.cpp | 102 + .../distributeddb_sqlite_register_test.cpp | 8 +- .../distributeddb_sqlite_utils_test.cpp | 40 + ...tributeddb_storage_commit_storage_test.cpp | 32 +- ...tributeddb_storage_data_operation_test.cpp | 28 +- .../distributeddb_storage_encrypt_test.cpp | 52 +- ...tributeddb_storage_index_optimize_test.cpp | 10 +- ...emory_rd_single_ver_natural_store_test.cpp | 8 +- ..._memory_single_ver_naturall_store_test.cpp | 58 +- .../distributeddb_storage_query_sync_test.cpp | 58 +- ...eddb_storage_rd_register_observer_test.cpp | 10 +- ...orage_rd_result_and_json_optimize_test.cpp | 8 +- ...orage_rd_single_ver_natural_store_test.cpp | 22 +- ...e_rd_single_ver_natural_store_testcase.cpp | 8 +- ...buteddb_storage_register_conflict_test.cpp | 34 +- ...buteddb_storage_register_observer_test.cpp | 30 +- ...db_storage_resultset_and_json_optimize.cpp | 8 +- ...rage_single_ver_natural_store_testcase.cpp | 66 +- ...uteddb_storage_single_ver_upgrade_test.cpp | 8 +- ...qlite_single_ver_natural_executor_test.cpp | 4 + ...e_sqlite_single_ver_natural_store_test.cpp | 62 +- ..._sqlite_single_ver_storage_engine_test.cpp | 373 + ...ributeddb_storage_subscribe_query_test.cpp | 18 +- ...ibuteddb_storage_transaction_data_test.cpp | 60 +- ...uteddb_storage_transaction_record_test.cpp | 50 +- .../virtual_sqlite_relational_store.cpp | 38 + .../storage/virtual_sqlite_relational_store.h | 36 + .../storage/virtual_sqlite_storage_engine.cpp | 76 + .../storage/virtual_sqlite_storage_engine.h | 41 + .../distracteddb_kv_multi_user_sync_test.cpp | 378 + .../distributeddb_abnormal_kv_sync_test.cpp | 68 + .../kv/distributeddb_basic_kv_test.cpp | 60 + .../kv/distributeddb_kv_compress_test.cpp | 101 + .../kv/distributeddb_kv_data_status_test.cpp | 51 +- .../kv/distributeddb_kv_device_sync_test.cpp | 145 + .../distracteddb_rdb_multi_user_sync_test.cpp | 141 + .../rdb/distributeddb_basic_rdb_test.cpp | 139 +- .../rdb/distributeddb_rdb_compress_test.cpp | 401 + .../distributeddb_rdb_data_status_test.cpp | 428 +- .../rdb/distributeddb_rdb_drop_table_test.cpp | 278 + ...istributeddb_rdb_knowledge_client_test.cpp | 255 + .../rdb/distributeddb_rdb_knowledge_test.cpp | 250 + .../rdb/distributeddb_rdb_upgrade_test.cpp | 148 + .../cloud/cloud_db_sync_utils_client_test.cpp | 32 + .../syncer/cloud/cloud_db_sync_utils_test.cpp | 15 - ...teddb_cloud_async_download_assets_test.cpp | 235 +- .../distributeddb_cloud_kv_syncer_test.cpp | 92 +- .../cloud/distributeddb_cloud_kv_test.cpp | 287 +- .../distributeddb_cloud_kvstore_test.cpp | 7 +- ...cloud_syncer_download_assets_only_test.cpp | 119 +- ...eddb_cloud_syncer_download_assets_test.cpp | 216 +- ...stributeddb_cloud_syncer_download_test.cpp | 58 +- .../distributeddb_cloud_syncer_lock_test.cpp | 98 +- ...ddb_cloud_syncer_progress_manager_test.cpp | 22 +- ...distributeddb_cloud_syncer_upload_test.cpp | 102 +- ...d_table_compound_primary_key_sync_test.cpp | 12 +- ...ud_table_without_primary_key_sync_test.cpp | 24 +- .../mock_icloud_sync_storage_interface.h | 7 +- .../syncer/cloud/virtual_cloud_syncer.cpp | 10 + .../syncer/cloud/virtual_cloud_syncer.h | 4 + .../distributeddb_ability_sync_test.cpp | 24 +- .../distributeddb_anti_dos_sync_test.cpp | 6 +- .../distributeddb_communicator_proxy_test.cpp | 20 +- .../syncer/distributeddb_meta_data_test.cpp | 604 +- .../distributeddb_mock_sync_module_test.cpp | 257 +- .../distributeddb_multi_ver_p2p_sync_test.cpp | 40 +- ...stributeddb_relational_multi_user_test.cpp | 54 +- ...ributeddb_relational_ver_p2p_sync_test.cpp | 204 +- .../distributeddb_single_ver_dlp_test.cpp | 132 +- ...buteddb_single_ver_multi_sub_user_test.cpp | 8 +- ...stributeddb_single_ver_multi_user_test.cpp | 42 +- ...teddb_single_ver_p2p_complex_sync_test.cpp | 58 +- ...db_single_ver_p2p_permission_sync_test.cpp | 42 +- ...buteddb_single_ver_p2p_query_sync_test.cpp | 250 +- ...uteddb_single_ver_p2p_simple_sync_test.cpp | 5 +- ...ddb_single_ver_p2p_subscribe_sync_test.cpp | 3 + ...buteddb_single_ver_p2p_sync_check_test.cpp | 188 +- ...stributeddb_syncer_device_manager_test.cpp | 8 +- .../syncer/distributeddb_time_sync_test.cpp | 68 +- .../common/syncer/generic_virtual_device.cpp | 3 +- .../common/syncer/generic_virtual_device.h | 1 + .../common/syncer/kv_virtual_device.cpp | 6 + .../common/syncer/kv_virtual_device.h | 2 + .../common/syncer/mock_communicator.h | 2 + .../unittest/common/syncer/mock_meta_data.h | 6 +- .../common/syncer/mock_single_ver_data_sync.h | 6 + .../syncer/mock_single_ver_state_machine.h | 10 + .../unittest/common/syncer/mock_sync_engine.h | 9 +- .../unittest/common/syncer/mock_time_sync.h | 2 +- .../common/syncer/virtual_communicator.cpp | 24 +- .../common/syncer/virtual_communicator.h | 15 +- .../virtual_communicator_aggregator.cpp | 11 + .../syncer/virtual_communicator_aggregator.h | 2 + ...rtual_relational_ver_sync_db_interface.cpp | 13 + ...virtual_relational_ver_sync_db_interface.h | 2 + .../virtual_single_ver_sync_db_Interface.cpp | 16 + .../virtual_single_ver_sync_db_Interface.h | 2 + .../syncer/virtual_time_sync_communicator.cpp | 10 + .../syncer/virtual_time_sync_communicator.h | 3 + .../common/tokenizer/sqlite_adapter_test.cpp | 349 + .../innerkits/distributeddata/BUILD.gn | 61 +- .../distributeddata/include/executor.h | 6 +- .../distributeddata/include/executor_pool.h | 4 +- .../innerkits/distributeddata/include/pool.h | 10 +- .../distributeddata/include/single_kvstore.h | 21 + .../jskits/distributedkvstore/BUILD.gn | 1 + kv_store/kvstoremock/distributeddb/BUILD.gn | 3 - .../adapter/autils/constant.h | 1 - .../innerkitsimpl/kvdb/src/store_factory.cpp | 3 +- .../innerkitsimpl/kvdb/src/store_manager.cpp | 5 +- .../innerkitsimpl/kvdb/src/store_util.cpp | 12 +- .../distributeddata/src/js_util.cpp | 24 +- .../innerkits/distributeddata/BUILD.gn | 1 - .../jskits/distributeddata/BUILD.gn | 7 +- .../jskits/distributedkvstore/BUILD.gn | 9 +- .../single_kvstore_client/BUILD.gn | 5 +- .../test/fuzztest/blob_fuzzer/blob_fuzzer.cpp | 30 +- .../devicekvstore_fuzzer.cpp | 138 +- .../distributedkvdatamanager_fuzzer.cpp | 80 +- .../distributedkvdataservice_fuzzer.cpp | 275 - .../test/fuzztest/jsonservice_fuzzer/BUILD.gn | 147 - .../jsonservice_fuzzer/jsonservice_fuzzer.cpp | 1671 -- kv_store/test/fuzztest/kvsync_fuzzer/BUILD.gn | 130 - .../fuzztest/kvsync_fuzzer/kvsync_fuzzer.cpp | 561 - .../test/fuzztest/kvsync_fuzzer/project.xml | 25 - .../BUILD.gn | 18 +- .../test/fuzztest/kvutil_fuzzer/corpus/init | 16 + .../fuzztest/kvutil_fuzzer/kvutil_fuzzer.cpp | 181 + .../fuzztest/kvutil_fuzzer/kvutil_fuzzer.h | 22 + .../test/fuzztest/kvutil_fuzzer}/project.xml | 2 +- .../singlekvstore_fuzzer.cpp | 185 +- .../singlekvstorestub_fuzzer.cpp | 545 - .../taskscheduler_fuzzer.cpp | 19 +- .../typesutil_fuzzer/typesutil_fuzzer.cpp | 95 +- .../DeviceKvStoreKVPromiseJsTest.js | 2 +- .../KvManagerKVPromiseJsTest.js | 67 +- .../SingleKvStoreKVPromiseJsTest.js | 2 +- .../KvManagerDataPromiseJsTest.js | 4 +- .../SingleKvStoreDataPromiseJsTest.js | 2 +- mock/CMakeLists.txt | 4 +- .../include/dataobs_mgr_changeinfo.h | 10 +- .../include/dataobs_mgr_client.h | 45 +- .../include/dataobs_mgr_interface.h | 222 +- .../include/accesstoken_kit.h | 6 + .../appexecfwk_base/include/hap_module_info.h | 188 +- .../include/bundlemgr/bundle_mgr_interface.h | 6 + .../softbus_client/include/transport/socket.h | 622 +- .../include/transport/trans_type.h | 379 +- .../include/asset/i_asset_recv_callback.h | 3 + .../include/file_mount_manager.h | 47 + .../hitrace_meter/include/hitrace_meter.h | 326 +- .../hitrace_meter/include/hitrace_meter_c.h | 51 + .../huks/libhukssdk/include/hks_type_enum.h | 25 +- .../image_native/include/media_errors.h | 171 + .../image_native/include/modules.h | 25 + .../global_resmgr/include/resource_manager.h | 2 +- .../inner_api/concurrent_task_client.h | 135 + .../inner_api/concurrent_task_type.h | 98 + .../interfaces/inner_api/qos.h | 70 +- .../interfaces/kits/c/qos.h | 114 + mock/sqlite/BUILD.gn | 18 + mock/sqlite/bundle.json | 10 +- mock/sqlite/include/sqlite3.h | 208 +- mock/sqlite/include/sqlite3ext.h | 8 +- mock/sqlite/include/sqlite3sym.h | 33 + mock/sqlite/include/sqlite3tokenizer.h | 6 +- ...atch => 0001-History-features-on-OH.patch} | 938 +- ...tch => 0002-Enable-and-optimize-ICU.patch} | 177 +- ...tch => 0003-Busy-debug-and-log-dump.patch} | 951 +- ...patch => 0004-Support-meta-recovery.patch} | 200 +- ...ty-report-corruption-and-check-page.patch} | 1596 +- ...dd-extention-cksumvfs-and-check-page.patch | 1079 - mock/sqlite/patch/0006-Support-Binlog.patch | 1593 ++ ...h => 0007-Bugfix-on-current-version.patch} | 21 +- mock/sqlite/sqlite.gni | 2 + mock/sqlite/src/shell.c | 2059 +- mock/sqlite/src/sqlite3.c | 18532 +++++++--------- mock/sqlite/src/sqlite3icu.c | 47 +- mock/src/mock_aa_fwk.cpp | 55 +- mock/src/mock_access_token.cpp | 4 + mock/src/mock_bundle_manager.cpp | 49 + mock/src/mock_context.cpp | 112 + mock/src/mock_resouce_manager.cpp | 85 +- mock/src/mock_soft_bus.cpp | 20 + mock/src/mock_trace.cpp | 2 + preferences/bundle.json | 8 +- preferences/frameworks/cj/BUILD.gn | 1 + .../include/preferences_error.h} | 0 .../src/preferences_error.cpp} | 2 +- .../js/ani/common/include/ani_utils.h | 266 + .../js/ani/common/include/js_ani_ability.h | 41 + .../js/ani/common/src/js_ani_ability.cpp | 68 + .../frameworks/js/ani/preferences/BUILD.gn | 80 + .../ets/@ohos.data.preferences.ets | 490 + .../ani/preferences/src/ani_preferences.cpp | 781 + .../frameworks/js/napi/common/BUILD.gn | 4 +- .../js/napi/common/include/js_ability.h | 2 +- .../js/napi/common/include/js_common_utils.h | 2 +- .../napi/common/include/js_sendable_utils.h | 2 +- .../js/napi/common/include/napi_async_call.h | 2 +- .../mock/cross_platform/include/js_ability.h | 2 +- .../js/napi/common/mock/include/js_ability.h | 2 +- .../js/napi/common/src/js_sendable_utils.cpp | 2 +- .../frameworks/js/napi/preferences/BUILD.gn | 3 +- .../napi/preferences/src/napi_preferences.cpp | 2 +- .../js/napi/sendable_preferences/BUILD.gn | 1 + .../src/napi_preferences.cpp | 7 +- .../js/napi/system_storage/BUILD.gn | 2 + .../native/include/preferences_base.h | 2 + .../native/include/preferences_impl.h | 3 + .../native/include/preferences_utils.h | 46 +- .../platform/src/preferences_db_adapter.cpp | 4 - .../platform/src/preferences_file_lock.cpp | 7 +- .../frameworks/native/src/base64_helper.cpp | 15 +- .../native/src/preferences_base.cpp | 46 +- .../native/src/preferences_enhance_impl.cpp | 30 +- .../native/src/preferences_helper.cpp | 9 +- .../native/src/preferences_impl.cpp | 26 +- .../native/src/preferences_utils.cpp | 6 +- .../native/src/preferences_xml_utils.cpp | 53 +- .../frameworks/ndk/src/oh_preferences.cpp | 20 +- preferences/interfaces/inner_api/BUILD.gn | 8 +- preferences/interfaces/ndk/BUILD.gn | 1 + .../js/performance/preferences/src/BUILD.gn | 2 +- .../src/PreferencesSyncJsunit.test.js | 2 +- .../ets/test/StagePreferencesSynctest.ets | 354 +- preferences/test/native/BUILD.gn | 10 +- .../fuzztest/dbpreferences_fuzzer/BUILD.gn | 55 + .../fuzztest/dbpreferences_fuzzer/corpus/init | 16 + .../dbpreferences_fuzzer.cpp | 301 + .../dbpreferences_fuzzer.h | 22 + .../dbpreferences_fuzzer}/project.xml | 2 +- .../fuzztest/preferences_fuzzer/BUILD.gn | 2 +- .../preferences_fuzzer/preferences_fuzzer.cpp | 342 +- .../native/unittest/base64_helper_test.cpp | 8 +- .../native/unittest/preferences_file_test.cpp | 16 +- .../unittest/preferences_helper_test.cpp | 12 +- .../test/native/unittest/preferences_test.cpp | 304 +- .../unittest/preferences_xml_utils_test.cpp | 61 +- preferences/test/ndk/BUILD.gn | 12 +- .../gskvndkpreferences_fuzzer/BUILD.gn | 70 + .../gskvndkpreferences_fuzzer/corpus/init | 16 + .../gskvndkpreferences_fuzzer.cpp | 264 + .../gskvndkpreferences_fuzzer.h | 22 + .../gskvndkpreferences_fuzzer}/project.xml | 2 +- .../fuzztest/ndkpreferences_fuzzer/BUILD.gn | 70 + .../ndkpreferences_fuzzer/corpus/init | 16 + .../ndkpreferences_fuzzer.cpp | 215 + .../ndkpreferences_fuzzer.h | 22 + .../ndkpreferences_fuzzer}/project.xml | 2 +- .../test/ndk/mock/application_context.cpp | 1 - .../preferences_ndk_storage_type_test.cpp | 14 +- .../ndk/unittest/preferences_ndk_test.cpp | 32 +- .../unittest/preferences_ndk_value_test.cpp | 16 +- relational_store/CMakeLists.txt | 40 +- relational_store/CODEOWNERS | 4 +- relational_store/OAT.xml | 71 + relational_store/bundle.json | 58 +- relational_store/frameworks/cj/BUILD.gn | 1 + .../cj/include/relational_store_ffi.h | 4 +- ...relational_store_impl_rdbpredicatesproxy.h | 24 + .../include/relational_store_impl_rdbstore.h | 27 +- .../relational_store_impl_resultsetproxy.h | 4 + .../cj/include/relational_store_utils.h | 99 +- .../cj/src/relational_store_ffi.cpp | 377 +- ...lational_store_impl_rdbpredicatesproxy.cpp | 224 + .../cj/src/relational_store_impl_rdbstore.cpp | 395 +- .../relational_store_impl_resultsetproxy.cpp | 128 + .../cj/src/relational_store_utils.cpp | 324 + .../common/include/delay_actuator.h | 200 + .../frameworks/common/include/logger.h | 14 - .../js/ani/relationalstore}/BUILD.gn | 111 +- .../ets/@ohos.data.relationalStore.ets | 393 + .../relationalstore/include/ani_rdb_error.h | 51 + .../include/ani_rdb_predicates.h | 37 + .../relationalstore/include/ani_rdb_store.h | 36 + .../include/ani_rdb_store_helper.h | 31 + .../relationalstore/include/ani_result_set.h | 36 + .../ani/relationalstore/include/ani_utils.h | 297 + .../ani/relationalstore/src/ani_rdb_entry.cpp | 75 + .../ani/relationalstore/src/ani_rdb_error.cpp | 178 + .../src/ani_rdb_predicates.cpp | 86 + .../ani/relationalstore/src/ani_rdb_store.cpp | 322 + .../src/ani_rdb_store_helper.cpp | 125 + .../relationalstore/src/ani_result_set.cpp | 141 + .../js/ani/relationalstore/src/ani_utils.cpp | 636 + .../frameworks/js/napi/cloud_data/BUILD.gn | 8 +- .../napi/cloud_data/include/js_cloud_utils.h | 9 + .../js/napi/cloud_data/include/js_config.h | 15 + .../js/napi/cloud_data/src/js_cloud_utils.cpp | 45 + .../js/napi/cloud_data/src/js_config.cpp | 99 +- .../js/napi/cloud_data/src/js_error_utils.cpp | 3 +- .../js/napi/cloud_extension/BUILD.gn | 1 - .../js/napi/common/include/js_uv_queue.h | 6 +- .../mock/include/mock.h} | 18 +- .../common/mock/include/napi_async_proxy.h | 84 +- .../js/napi/common/mock/src/js_ability.cpp | 4 +- .../js/napi/common/mock/src/mock.cpp | 72 + .../js/napi/common/src/js_sendable_utils.cpp | 13 +- .../js/napi/common/src/js_utils.cpp | 7 +- .../js/napi/common/src/js_uv_queue.cpp | 122 +- .../frameworks/js/napi/dataability/BUILD.gn | 1 + .../dataability/include/napi_async_proxy.h | 178 - .../include/napi_data_ability_predicates.h | 5 +- .../src/napi_data_ability_predicates.cpp | 15 +- .../dataability/src/napi_predicates_utils.cpp | 6 +- .../js/napi/graphstore/include/gdb_common.h | 59 - .../js/napi/graphstore/include/js_proxy.h | 62 - .../napi/graphstore/include/napi_async_call.h | 108 - .../graphstore/include/napi_gdb_context.h | 80 - .../napi/graphstore/include/napi_gdb_error.h | 179 - .../graphstore/include/napi_gdb_js_utils.h | 80 - .../napi/graphstore/include/napi_gdb_store.h | 69 - .../napi/graphstore/src/napi_async_call.cpp | 247 - .../src/napi_gdb_const_properties.cpp | 51 - .../js/napi/graphstore/src/napi_gdb_error.cpp | 60 - .../napi/graphstore/src/napi_gdb_js_utils.cpp | 189 - .../js/napi/graphstore/src/napi_gdb_store.cpp | 301 - .../graphstore/src/napi_gdb_store_helper.cpp | 109 - .../graphstore/src/napi_gdb_transaction.cpp | 252 - .../frameworks/js/napi/rdb/BUILD.gn | 17 +- .../js/napi/rdb/include/napi_rdb_error.h | 13 - .../rdb/include/napi_rdb_store_observer.h | 18 +- .../js/napi/rdb/src/napi_async_call.cpp | 13 +- .../js/napi/rdb/src/napi_rdb_predicates.cpp | 5 +- .../js/napi/rdb/src/napi_rdb_store.cpp | 24 +- .../napi/rdb/src/napi_rdb_store_observer.cpp | 41 +- .../js/napi/rdb/src/napi_result_set.cpp | 3 + .../js/napi/rdb/src/napi_uv_queue.cpp | 87 - .../js/napi/relationalstore/BUILD.gn | 47 +- .../include/napi_rdb_context.h | 61 +- .../relationalstore/include/napi_rdb_error.h | 8 +- .../include/napi_rdb_js_utils.h | 8 + ...api_uv_queue.h => napi_rdb_log_observer.h} | 41 +- .../include/napi_rdb_predicates.h | 1 + .../include/napi_rdb_statistics_observer.h | 14 + .../relationalstore/include/napi_rdb_store.h | 25 +- .../mock/include/napi_rdb_store.h | 49 +- .../relationalstore/src/napi_async_call.cpp | 12 + .../relationalstore/src/napi_rdb_context.cpp | 358 + .../relationalstore/src/napi_rdb_error.cpp | 20 +- .../relationalstore/src/napi_rdb_js_utils.cpp | 34 + .../src/napi_rdb_log_observer.cpp | 65 + .../src/napi_rdb_predicates.cpp | 42 +- .../src/napi_rdb_statistics_observer.cpp | 45 + .../relationalstore/src/napi_rdb_store.cpp | 1111 +- .../src/napi_rdb_store_helper.cpp | 231 +- .../relationalstore/src/napi_result_set.cpp | 39 +- .../relationalstore/src/napi_transaction.cpp | 13 +- .../relationalstore/src/napi_uv_queue.cpp | 89 - .../js/napi/sendablerelationalstore/BUILD.gn | 1 + .../src/napi_rdb_store_convert_utils.cpp | 65 + .../native/appdatafwk/src/serializable.cpp | 16 + .../native/appdatafwk/src/shared_block.cpp | 18 +- .../cloud_data/include/cloud_notifier_stub.h | 53 + .../cloud_data/include/cloud_service_proxy.h | 11 + .../cloud_data/include/cloud_types_util.h | 7 + .../native/cloud_data/src/cloud_manager.cpp | 7 +- .../cloud_data/src/cloud_notifier_stub.cpp | 79 + .../cloud_data/src/cloud_service_proxy.cpp | 71 + .../cloud_data/src/cloud_types_util.cpp | 11 + .../native/dfx/include/rdb_dfx_errno.h | 52 + .../dfx/include/rdb_fault_hiview_reporter.h | 13 +- .../dfx/src/rdb_fault_hiview_reporter.cpp | 97 +- .../native/dfx/src/rdb_radar_reporter.cpp | 15 +- .../native/dfx/src/rdb_stat_reporter.cpp | 4 +- .../frameworks/native/dlopen_rdb/BUILD.gn | 52 + .../native/dlopen_rdb/dlopen_rdb.cpp | 177 + .../frameworks/native/dlopen_rdb/dlopen_rdb.h | 15 +- .../native/gdb/adapter/include/grd_adapter.h | 64 - .../gdb/adapter/include/grd_adapter_manager.h | 77 - .../native/gdb/adapter/src/grd_adapter.cpp | 388 - .../gdb/adapter/src/grd_adapter_manager.cpp | 69 - .../native/gdb/include/connection.h | 44 - .../native/gdb/include/connection_pool.h | 121 - .../native/gdb/include/db_store_impl.h | 50 - .../native/gdb/include/db_store_manager.h | 54 - .../native/gdb/include/full_result.h | 45 - .../frameworks/native/gdb/include/gdb_utils.h | 41 - .../native/gdb/include/graph_connection.h | 55 - .../native/gdb/include/graph_statement.h | 52 - .../frameworks/native/gdb/include/statement.h | 55 - .../frameworks/native/gdb/src/connection.cpp | 62 - .../native/gdb/src/connection_pool.cpp | 475 - .../native/gdb/src/db_store_impl.cpp | 187 - .../native/gdb/src/db_store_manager.cpp | 182 - .../frameworks/native/gdb/src/edge.cpp | 104 - .../frameworks/native/gdb/src/full_result.cpp | 73 - .../frameworks/native/gdb/src/gdb_utils.cpp | 186 - .../native/gdb/src/graph_connection.cpp | 170 - .../native/gdb/src/graph_statement.cpp | 200 - .../frameworks/native/gdb/src/path.cpp | 111 - .../native/gdb/src/path_segment.cpp | 94 - .../native/gdb/src/store_config.cpp | 196 - .../frameworks/native/gdb/src/trans_db.cpp | 100 - .../native/gdb/src/transaction_impl.cpp | 180 - .../frameworks/native/gdb/src/vertex.cpp | 122 - .../frameworks/native/icu/BUILD.gn | 1 + .../native/icu/include/icu_collect.h | 2 +- .../frameworks/native/icu/src/icu_collect.cpp | 27 +- .../native/obs_mgr_adapter/BUILD.gn | 50 + .../obs_mgr_adapter/obs_mgr_adapter.cpp | 299 + .../native/obs_mgr_adapter/obs_mgr_adapter.h | 21 + .../native/rdb/include/connection.h | 25 +- .../native/rdb/include/connection_pool.h | 17 +- .../native/rdb/include/delay_notify.h | 2 +- .../native/rdb/include/global_resource.h | 38 + .../native/rdb/include/grd_api_manager.h | 4 +- .../native/rdb/include/grd_type_export.h | 34 +- .../native/rdb/include/irdb_service.h | 4 +- .../include/knowledge_schema_helper.h} | 62 +- .../native/rdb/include/rd_connection.h | 24 +- .../native/rdb/include/rd_statement.h | 1 + .../frameworks/native/rdb/include/rd_utils.h | 19 +- .../native/rdb/include/rdb_icu_manager.h | 45 + .../native/rdb/include/rdb_manager_impl.h | 11 +- .../native/rdb/include/rdb_obs_manager.h | 52 + .../native/rdb/include/rdb_perfStat.h | 82 + .../native/rdb/include/rdb_security_manager.h | 60 +- .../native/rdb/include/rdb_service_proxy.h | 15 +- .../native/rdb/include/rdb_sql_log.h | 50 + .../native/rdb/include/rdb_sql_statistic.h | 1 - .../native/rdb/include/rdb_store_impl.h | 122 +- .../native/rdb/include/rdb_store_manager.h | 14 +- .../native/rdb/include/share_block.h | 7 +- .../native/rdb/include/sqlite_connection.h | 67 +- .../native/rdb/include/sqlite_errno.h | 47 +- .../native/rdb/include/sqlite_sql_builder.h | 15 +- .../native/rdb/include/sqlite_statement.h | 4 +- .../native/rdb/include/sqlite_utils.h | 24 +- .../frameworks/native/rdb/include/statement.h | 2 + .../native/rdb/include/string_utils.h | 1 + .../rdb/include/suspender.h} | 44 +- .../frameworks/native/rdb/include/trans_db.h | 20 +- .../native/rdb/include/transaction_impl.h | 24 +- .../native/rdb/mock/include/rdb_store_impl.h | 67 +- .../native/rdb/mock/include/task_executor.h | 90 - .../mock/src/rdb_fault_hiview_reporter.cpp | 17 +- .../native/rdb/mock/src/task_executor.cpp | 23 +- .../native/rdb/src/abs_predicates.cpp | 31 +- .../native/rdb/src/abs_rdb_predicates.cpp | 10 + .../native/rdb/src/abs_result_set.cpp | 5 +- .../native/rdb/src/cache_result_set.cpp | 3 + .../frameworks/native/rdb/src/connection.cpp | 17 +- .../native/rdb/src/connection_pool.cpp | 144 +- .../native/rdb/src/delay_notify.cpp | 12 +- .../native/rdb/src/global_resource.cpp | 52 + .../native/rdb/src/grd_api_manager.cpp | 3 +- .../rdb/src/knowledge_schema_helper.cpp | 200 + .../native/rdb/src/rd_connection.cpp | 79 +- .../native/rdb/src/rd_statement.cpp | 5 + .../frameworks/native/rdb/src/rd_utils.cpp | 59 +- .../frameworks/native/rdb/src/rdb_helper.cpp | 42 +- .../native/rdb/src/rdb_icu_manager.cpp | 90 + .../native/rdb/src/rdb_manager_impl.cpp | 88 +- .../native/rdb/src/rdb_obs_manager.cpp | 146 + .../native/rdb/src/rdb_perfStat.cpp | 267 + .../native/rdb/src/rdb_security_manager.cpp | 708 +- .../native/rdb/src/rdb_service_proxy.cpp | 59 +- .../frameworks/native/rdb/src/rdb_sql_log.cpp | 106 + .../native/rdb/src/rdb_sql_statistic.cpp | 5 - .../native/rdb/src/rdb_sql_utils.cpp | 131 +- .../frameworks/native/rdb/src/rdb_store.cpp | 101 +- .../native/rdb/src/rdb_store_config.cpp | 59 +- .../native/rdb/src/rdb_store_impl.cpp | 1033 +- .../native/rdb/src/rdb_store_manager.cpp | 199 +- .../frameworks/native/rdb/src/share_block.cpp | 3 +- .../native/rdb/src/sqlite_connection.cpp | 730 +- .../native/rdb/src/sqlite_global_config.cpp | 15 +- .../rdb/src/sqlite_shared_result_set.cpp | 16 +- .../native/rdb/src/sqlite_sql_builder.cpp | 235 +- .../native/rdb/src/sqlite_statement.cpp | 94 +- .../native/rdb/src/sqlite_utils.cpp | 339 +- .../native/rdb/src/step_result_set.cpp | 7 +- .../native/rdb/src/string_utils.cpp | 22 +- .../rdb/src/suspender.cpp} | 58 +- .../native/rdb/src/task_executor.cpp | 34 +- .../frameworks/native/rdb/src/trans_db.cpp | 153 +- .../frameworks/native/rdb/src/transaction.cpp | 70 +- .../native/rdb/src/transaction_impl.cpp | 85 +- .../native/rdb/src/values_bucket.cpp | 5 + .../native/rdb/src/values_buckets.cpp | 40 + .../frameworks/native/rdb_crypt/BUILD.gn | 46 + .../rdb_crypt/relational_store_crypt.cpp | 385 + .../native/rdb_crypt/relational_store_crypt.h | 44 + .../interfaces/inner_api/appdatafwk/BUILD.gn | 11 +- .../appdatafwk/include/serializable.h | 2 + .../appdatafwk/include/shared_block.h | 25 +- .../cloud_data/include/cloud_notifier.h | 29 + .../cloud_data/include/cloud_service.h | 12 + .../interfaces/inner_api/dataability/BUILD.gn | 5 +- .../include/data_ability_predicates.h | 4 +- .../inner_api/gdb/include/gdb_errors.h | 102 - .../inner_api/gdb/include/gdb_store.h | 33 - .../inner_api/gdb/include/gdb_store_config.h | 102 - .../interfaces/inner_api/gdb/include/path.h | 62 - .../inner_api/gdb/include/path_segment.h | 56 - .../interfaces/inner_api/gdb/include/vertex.h | 58 - .../interfaces/inner_api/rdb/BUILD.gn | 67 +- .../inner_api/rdb/include/abs_predicates.h | 7 +- .../rdb/include/abs_rdb_predicates.h | 11 +- .../inner_api/rdb/include/cache_result_set.h | 4 + ...data_relational_store_ipc_interface_code.h | 6 + .../inner_api/rdb/include/knowledge_types.h | 102 + .../inner_api/rdb/include/rdb_common.h | 3 +- .../inner_api/rdb/include/rdb_errno.h | 42 +- .../inner_api/rdb/include/rdb_helper.h | 20 + .../inner_api/rdb/include/rdb_open_callback.h | 5 + .../inner_api/rdb/include/rdb_service.h | 10 +- .../inner_api/rdb/include/rdb_sql_utils.h | 24 + .../inner_api/rdb/include/rdb_store.h | 110 +- .../inner_api/rdb/include/rdb_store_config.h | 82 +- .../inner_api/rdb/include/rdb_types.h | 31 +- .../inner_api}/rdb/include/task_executor.h | 16 +- .../inner_api/rdb/include/transaction.h | 74 +- .../inner_api/rdb/include/values_bucket.h | 8 + .../inner_api/rdb/include/values_buckets.h | 6 + .../rdb/mock/include/rdb_store_config.h | 75 +- .../rdb/mock/include/values_bucket.h | 8 + .../rdb_data_ability_adapter/BUILD.gn | 10 +- .../inner_api/rdb_data_share_adapter/BUILD.gn | 6 +- .../include/rdb_utils.h | 2 +- .../graphstore => interfaces/ndk}/BUILD.gn | 61 +- .../interfaces/ndk/include/oh_data_value.h | 5 +- .../interfaces/ndk/include/oh_data_values.h | 5 +- .../ndk/include/oh_data_values_buckets.h | 4 +- .../interfaces/ndk/include/oh_predicates.h | 60 +- .../ndk/include/oh_rdb_crypto_param.h | 227 + .../ndk/include/oh_rdb_transaction.h | 71 +- .../interfaces/ndk/include/relational_store.h | 214 +- .../ndk/relational_store_inner_types.h | 42 + .../interfaces/ndk/src/oh_data_define.h | 9 + .../interfaces/ndk/src/oh_data_value.cpp | 2 +- .../interfaces/ndk/src/oh_data_values.cpp | 2 +- .../ndk/src/oh_data_values_buckets.cpp | 2 +- .../ndk/src/oh_rdb_crypto_param.cpp | 112 + .../interfaces/ndk/src/oh_rdb_transaction.cpp | 54 +- .../ndk/src/relational_predicates.cpp | 58 + .../ndk/src/relational_predicates_objects.cpp | 1 + .../interfaces/ndk/src/relational_store.cpp | 237 +- .../{ndk/src => rdb_ndk_utils}/BUILD.gn | 35 +- .../rdb_ndk_utils/include/rdb_ndk_utils.h | 25 + .../rdb_ndk_utils/src/rdb_ndk_utils.cpp | 90 + .../native/rdb/{ => common}/concurrent_map.h | 0 .../rdbmock/frameworks/native/rdb/file_ex.h | 2 +- .../native/rdb/relational_store_client.h | 15 + .../rdbmock/frameworks/native/rdb/sys/file.h | 4 + .../rdbmock/frameworks/native/win32/dlfcn.cpp | 5 + .../rdbmock/frameworks/native/win32/dlfcn.h | 1 + relational_store/relational_store.gni | 13 +- .../test/ets/cloud_data/AppScope/app.json | 21 + .../resources/base/element/string.json | 8 + relational_store/test/ets/cloud_data/BUILD.gn | 48 + .../test/ets/cloud_data/Test.json | 26 + .../src/main/ets/Application/AbilityStage.ts | 22 + .../src/main/ets/MainAbility/MainAbility.ts | 50 + .../ets/MainAbility/pages/index/index.ets | 57 + .../src/main/ets/TestAbility/TestAbility.ts | 43 + .../src/main/ets/TestAbility/pages/index.ets | 48 + .../ets/TestRunner/OpenHarmonyTestRunner.ts | 71 + .../main/ets/test/CloudConfigEtsTest.test.ets | 510 + .../entry/src/main/ets/test/List.test.ets | 20 + .../ets/cloud_data/entry/src/main/module.json | 62 + .../main/resources/base/element/string.json | 44 + .../src/main/resources/base/media/icon.png | Bin 0 -> 15458 bytes .../resources/base/profile/form_config.json | 6 + .../resources/base/profile/form_config1.txt | 1 + .../main/resources/base/profile/invalid.txt | 3 + .../resources/base/profile/main_pages.json | 5 + .../base/profile/shortcuts_config.json | 5 + .../cloud_data/signature}/openharmony_sx.p7b | Bin 3437 -> 3563 bytes .../ets/relational_store/AppScope/app.json | 21 + .../resources/base/element/string.json | 8 + .../test/ets/relational_store/BUILD.gn | 48 + .../test/ets/relational_store/Test.json | 27 + .../src/main/ets/Application/AbilityStage.ts | 22 + .../src/main/ets/MainAbility/MainAbility.ts | 49 + .../ets/MainAbility/pages/index/index.ets | 57 + .../src/main/ets/TestAbility/TestAbility.ts | 43 + .../src/main/ets/TestAbility/pages/index.ets | 48 + .../ets/TestRunner/OpenHarmonyTestRunner.ts | 71 + .../entry/src/main/ets/test/List.test.ets | 46 + .../src/main/ets/test/RdbGroupIdEts.test.ets | 267 + .../src/main/ets/test/RdbOnErrorLog.test.ets | 309 + .../ets/test/RdbPredicatesPerfEts.test.ets} | 83 +- .../main/ets/test/RdbStoreExecuteSql.test.ets | 84 + .../test/RdbStoreTransInsertJsunit.test.ets | 947 + .../ets/test/RdbStoreTransJsunit.test.ets | 1988 ++ .../ets/test/RdbStoreTransaction.test.ets | 2729 +++ .../ets/test/RdbstoreCustomTokenizerEts.ets | 350 + .../test/RdbstoreGetRowForFlutterEts.test.ets | 306 + .../ets/test/RdbstoreGetSqlInfoEts.test.ets | 727 + .../RdbstoreGetValueForFlutterEts.test.ets | 299 + .../ets/test/RdbstorePerfStatEts.test.ets | 671 + .../ets/test/RdbstorePredicatesEts.test.ets | 369 + .../main/ets/test/RdbstoreRekeyEts.test.ets | 862 + .../ets/test/RdbstoreSetLocaleEts.test.ets | 226 + .../test/RdbstoreTransactionJsunit.test.ets | 339 + .../ets/test/RelationalStoreEtsTest.test.ets | 97 + .../entry/src/main/module.json | 74 + .../main/resources/base/element/string.json | 44 + .../src/main/resources/base/media/icon.png | Bin 0 -> 15458 bytes .../resources/base/profile/form_config.json | 5 + .../resources/base/profile/form_config1.txt | 1 + .../main/resources/base/profile/invalid.txt | 3 + .../resources/base/profile/main_pages.json | 5 + .../base/profile/shortcuts_config.json | 5 + .../signature}/openharmony_sx.p7b | Bin 3437 -> 3500 bytes .../performance/src/GdbStorePromisePerf.js | 130 - .../test/js/gdb/unittest/config.json | 64 - .../src/GdbStoreGdbStoreJsunit.test.js | 422 - .../src/GdbStoreReadWriteJsunit.test.js | 936 - .../src/RdbStoreDistributedJsunit.test.js | 6 +- ...oreCreateDeleteWithFAContextJsunit.test.js | 10 +- .../unittest/src/RdbstoreDeleteJsunit.test.js | 10 +- .../src/RdbstoreEncryptionJsunit.test.js | 14 +- ...bstorePredicatesComplexFiledJsunit.test.js | 8 +- .../src/RdbstoreStoreExcuteSqlJsunit.test.js | 10 +- .../unittest/src/RdbstoreUpdateJsunit.test.js | 38 +- .../unittest/src/RdbStoreDataChange.test.js | 64 + .../src/RdbStoreRdExecuteJsunit.test.js | 272 + .../src/RdbStoreReadOnlyJsunit.test.js | 2 + .../src/RdbStoreResultSetJsunit.test.js | 182 - .../src/RdbStoreStatisticsJsunit.test.js | 3 +- .../src/RdbStoreTransInsertJsunit.test.js | 945 - .../unittest/src/RdbStoreTransJsunit.test.js | 1986 -- .../unittest/src/RdbStoreTransaction.test.js | 2239 -- .../RdbstoreConcurrentQueryWithCrud.test.js | 63 +- .../src/RdbstoreEncryptionJsunit.test.js | 2 +- .../src/RdbstoreRdbstoreJsunit.test.js | 4 +- .../src/RdbstoreTransactionJsunit.test.js | 288 - .../test/native/appdatafwk/BUILD.gn | 8 +- .../appdatafwk/unittest/serializable_test.cpp | 137 + .../test/native/clouddata/BUILD.gn | 18 +- .../cloudnotifierstub_fuzzer/BUILD.gn | 60 + .../cloudnotifierstub_fuzzer.cpp} | 63 +- .../cloudnotifierstub_fuzzer.h | 21 + .../cloudnotifierstub_fuzzer/corpus/init | 14 + .../cloudnotifierstub_fuzzer/project.xml | 25 + .../clouddata/unittest/cloud_data_test.cpp | 299 +- .../test/native/dataability/BUILD.gn | 7 +- relational_store/test/native/gdb/BUILD.gn | 221 - .../test/native/gdb/mock/grd_adapter.cpp | 407 - .../test/native/gdb/mock/grd_adapter.h | 73 - .../native/gdb/unittest/gdb_adapt_test.cpp | 210 - .../native/gdb/unittest/gdb_encrypt_test.cpp | 460 - .../native/gdb/unittest/gdb_execute_test.cpp | 2043 -- .../native/gdb/unittest/gdb_function_test.cpp | 204 - .../gdb/unittest/gdb_grd_adapter_test.cpp | 455 - .../native/gdb/unittest/gdb_grdapi_test.cpp | 187 - .../gdb/unittest/gdb_multi_thread_test.cpp | 342 - .../native/gdb/unittest/gdb_query_test.cpp | 646 - .../gdb/unittest/gdb_transaction_test.cpp | 802 - relational_store/test/native/rdb/BUILD.gn | 322 +- .../rdb_store_impl_test/BUILD.gn | 48 +- .../fuzztest/abspredicates_fuzzer/BUILD.gn | 64 + .../abspredicates_fuzzer.cpp | 322 + .../abspredicates_fuzzer.h | 21 + .../corpus/init | 2 +- .../fuzztest/abspredicates_fuzzer/project.xml | 25 + .../fuzztest/absrdbpredicates_fuzzer/BUILD.gn | 63 + .../absrdbpredicates_fuzzer.cpp | 232 + .../absrdbpredicates_fuzzer.h | 21 + .../absrdbpredicates_fuzzer}/corpus/init | 2 +- .../absrdbpredicates_fuzzer/project.xml | 25 + .../rdb/fuzztest/absresultset_fuzzer/BUILD.gn | 63 + .../absresultset_fuzzer.cpp | 293 + .../absresultset_fuzzer/absresultset_fuzzer.h | 21 + .../fuzztest/absresultset_fuzzer}/corpus/init | 2 +- .../fuzztest/absresultset_fuzzer/project.xml | 25 + .../abssharedresultset_fuzzer/BUILD.gn | 67 + .../abssharedresultset_fuzzer.cpp | 156 + .../abssharedresultset_fuzzer.h | 21 + .../abssharedresultset_fuzzer}/corpus/init | 2 +- .../abssharedresultset_fuzzer/project.xml | 25 + .../big_integer_test_ut2fuzz/BUILD.gn | 63 + .../big_integer_test_ut2fuzz.cpp | 76 + .../big_integer_test_ut2fuzz.h | 21 + .../big_integer_test_ut2fuzz/corpus/init | 14 + .../big_integer_test_ut2fuzz/project.xml | 25 + .../cache_result_set_test_ut2fuzz/BUILD.gn | 63 + .../cache_result_set_test_ut2fuzz.cpp | 393 + .../cache_result_set_test_ut2fuzz.h | 21 + .../cache_result_set_test_ut2fuzz/corpus/init | 14 + .../cache_result_set_test_ut2fuzz/project.xml | 25 + .../BUILD.gn | 54 +- .../cloud_data_test_ut2fuzz.cpp | 300 + .../cloud_data_test_ut2fuzz.h | 21 + .../cloud_data_test_ut2fuzz/corpus/init | 14 + .../cloud_data_test_ut2fuzz/project.xml | 25 + .../fuzztest/connection_test_ut2fuzz/BUILD.gn | 62 + .../connection_test_ut2fuzz.cpp} | 36 +- .../connection_test_ut2fuzz.h | 21 + .../connection_test_ut2fuzz/corpus/init | 14 + .../connection_test_ut2fuzz/project.xml | 25 + .../rdb_attach_test_ut2fuzz}/BUILD.gn | 26 +- .../rdb_attach_test_ut2fuzz/corpus/init | 14 + .../rdb_attach_test_ut2fuzz/project.xml | 25 + .../rdb_attach_test_ut2fuzz.cpp | 208 + .../rdb_attach_test_ut2fuzz.h | 21 + .../fuzztest/rdb_bigint_test_ut2fuzz/BUILD.gn | 63 + .../rdb_bigint_test_ut2fuzz/corpus/init | 14 + .../rdb_bigint_test_ut2fuzz/project.xml | 25 + .../rdb_bigint_test_ut2fuzz.cpp | 76 + .../rdb_bigint_test_ut2fuzz.h | 21 + .../rdb_callback_icu_test_ut2fuzz/BUILD.gn | 59 + .../rdb_callback_icu_test_ut2fuzz/corpus/init | 14 + .../rdb_callback_icu_test_ut2fuzz/project.xml | 25 + .../rdb_callback_icu_test_ut2fuzz.cpp | 134 + .../rdb_callback_icu_test_ut2fuzz.h | 21 + .../rdb_corrupt_test_ut2fuzz/BUILD.gn | 59 + .../rdb_corrupt_test_ut2fuzz/corpus/init | 14 + .../rdb_corrupt_test_ut2fuzz/project.xml | 25 + .../rdb_corrupt_test_ut2fuzz.cpp | 129 + .../rdb_corrupt_test_ut2fuzz.h | 21 + .../rdb_delete_test_ut2fuzz}/BUILD.gn | 33 +- .../rdb_delete_test_ut2fuzz/corpus/init | 14 + .../rdb_delete_test_ut2fuzz/project.xml | 25 + .../rdb_delete_test_ut2fuzz.cpp | 233 + .../rdb_delete_test_ut2fuzz.h | 21 + .../rdb_distributed_test_ut2fuzz/BUILD.gn | 59 + .../rdb_distributed_test_ut2fuzz/corpus/init | 14 + .../rdb_distributed_test_ut2fuzz/project.xml | 25 + .../rdb_distributed_test_ut2fuzz.cpp | 123 + .../rdb_distributed_test_ut2fuzz.h | 21 + .../rdb_double_write_test_ut2fuzz/BUILD.gn | 59 + .../rdb_double_write_test_ut2fuzz/corpus/init | 14 + .../rdb_double_write_test_ut2fuzz/project.xml | 25 + .../rdb_double_write_test_ut2fuzz.cpp | 210 + .../rdb_double_write_test_ut2fuzz.h | 21 + .../rdb/fuzztest/rdbhelper_fuzzer/BUILD.gn | 60 + .../rdb/fuzztest/rdbhelper_fuzzer/corpus/init | 16 + .../rdb/fuzztest/rdbhelper_fuzzer/project.xml | 26 + .../rdbhelper_fuzzer/rdbhelper_fuzzer.cpp | 124 + .../rdbhelper_fuzzer/rdbhelper_fuzzer.h | 21 + .../rdb/fuzztest/rdbimpl_fuzzer/BUILD.gn | 29 +- .../rdb/fuzztest/rdbimpl_fuzzer/corpus/init | 2 +- .../rdb/fuzztest/rdbimpl_fuzzer/project.xml | 2 +- .../rdbimpl_fuzzer/rdbimpl_fuzzer.cpp | 67 +- .../fuzztest/rdbimpl_fuzzer/rdbimpl_fuzzer.h | 2 +- .../fuzztest/rdbpredicates_fuzzer/BUILD.gn | 63 + .../fuzztest/rdbpredicates_fuzzer/corpus/init | 14 + .../fuzztest/rdbpredicates_fuzzer/project.xml | 25 + .../rdbpredicates_fuzzer.cpp | 91 + .../rdbpredicates_fuzzer.h | 21 + .../rdb/fuzztest/rdbrdutils_fuzzer/BUILD.gn | 61 +- .../fuzztest/rdbrdutils_fuzzer/corpus/init | 14 + .../fuzztest/rdbrdutils_fuzzer/project.xml | 25 + .../rdbrdutils_fuzzer/rdbrdutils_fuzzer.cpp | 132 + .../rdbrdutils_fuzzer/rdbrdutils_fuzzer.h | 21 + .../rddbopen_fuzzer/rddbopen_fuzzer.cpp | 118 - .../transfergrderrno_fuzzer/BUILD.gn | 78 - .../transfergrderrno_fuzzer/corpus/init | 14 - .../transfergrderrno_fuzzer/project.xml | 25 - .../transfergrderrno_fuzzer.h | 21 - .../transfergrdtypetocoltype_fuzzer/BUILD.gn | 78 - .../project.xml | 25 - .../transfergrdtypetocoltype_fuzzer.h | 21 - .../rdb/fuzztest/rdbsqlutils_fuzzer/BUILD.gn | 63 + .../fuzztest/rdbsqlutils_fuzzer/corpus/init | 14 + .../fuzztest/rdbsqlutils_fuzzer/project.xml | 25 + .../rdbsqlutils_fuzzer/rdbsqlutils_fuzzer.cpp | 162 + .../rdbsqlutils_fuzzer/rdbsqlutils_fuzzer.h | 21 + .../rdb/fuzztest/rdbstore_fuzzer/BUILD.gn | 12 +- .../rdb/fuzztest/rdbstore_fuzzer/corpus/init | 2 +- .../rdb/fuzztest/rdbstore_fuzzer/project.xml | 2 +- .../rdbstore_fuzzer/rdbstore_fuzzer.cpp | 375 +- .../rdbstore_fuzzer/rdbstore_fuzzer.h | 2 +- .../rdb/fuzztest/rdstatement_fuzzer/BUILD.gn | 42 +- .../fuzztest/rdstatement_fuzzer/corpus/init | 2 +- .../fuzztest/rdstatement_fuzzer/project.xml | 2 +- .../rdstatement_fuzzer/rdstatement_fuzzer.cpp | 8 +- .../rdstatement_fuzzer/rdstatement_fuzzer.h | 2 +- .../rdb/fuzztest/returning_fuzzer/BUILD.gn | 64 + .../rdb/fuzztest/returning_fuzzer/corpus/init | 16 + .../rdb/fuzztest/returning_fuzzer/project.xml | 26 + .../returning_fuzzer/returning_fuzzer.cpp | 317 + .../returning_fuzzer/returning_fuzzer.h | 21 + .../BUILD.gn | 36 +- .../fuzztest/sharedblock_fuzzer/corpus/init | 14 + .../fuzztest/sharedblock_fuzzer/project.xml | 25 + .../sharedblock_fuzzer/sharedblock_fuzzer.cpp | 159 + .../sharedblock_fuzzer/sharedblock_fuzzer.h | 21 + .../rdb/fuzztest/storeconfig_fuzzer/BUILD.gn | 63 + .../fuzztest/storeconfig_fuzzer/corpus/init | 14 + .../fuzztest/storeconfig_fuzzer/project.xml | 25 + .../storeconfig_fuzzer/storeconfig_fuzzer.cpp | 202 + .../storeconfig_fuzzer/storeconfig_fuzzer.h | 21 + .../rdb/fuzztest/transaction_fuzzer/BUILD.gn | 64 + .../fuzztest/transaction_fuzzer/corpus/init | 14 + .../fuzztest/transaction_fuzzer/project.xml | 25 + .../transaction_fuzzer/transaction_fuzzer.cpp | 115 + .../transaction_fuzzer/transaction_fuzzer.h | 21 + .../rdb/fuzztest/transdb_fuzzer/BUILD.gn | 67 + .../rdb/fuzztest/transdb_fuzzer/corpus/init | 1 + .../rdb/fuzztest/transdb_fuzzer/project.xml | 25 + .../transdb_fuzzer/transdb_fuzzer.cpp | 134 + .../fuzztest/transdb_fuzzer/transdb_fuzzer.h | 21 + .../rdb/fuzztest/valueobject_fuzzer/BUILD.gn | 63 + .../fuzztest/valueobject_fuzzer/corpus/init | 14 + .../fuzztest/valueobject_fuzzer/project.xml | 25 + .../valueobject_fuzzer/valueobject_fuzzer.cpp | 168 + .../valueobject_fuzzer/valueobject_fuzzer.h | 21 + .../rdb/fuzztest/valuesbucket_fuzzer/BUILD.gn | 63 + .../fuzztest/valuesbucket_fuzzer/corpus/init | 14 + .../fuzztest/valuesbucket_fuzzer/project.xml | 25 + .../valuesbucket_fuzzer.cpp | 157 + .../valuesbucket_fuzzer/valuesbucket_fuzzer.h | 21 + .../fuzztest/valuesbuckets_fuzzer/BUILD.gn | 63 + .../fuzztest/valuesbuckets_fuzzer/corpus/init | 14 + .../fuzztest/valuesbuckets_fuzzer/project.xml | 25 + .../valuesbuckets_fuzzer.cpp | 107 + .../valuesbuckets_fuzzer.h | 21 + .../test/native/rdb/mock/connection_mock.h | 74 + .../rdb/mock/dataobs_mgr_client_mock.cpp | 35 + .../rdb/mock/dataobs_mgr_client_mock.h} | 42 +- .../native/rdb/mock/rdb_manager_impl_mock.cpp | 39 + .../native/rdb/mock/rdb_manager_impl_mock.h | 38 + .../test/native/rdb/mock/rdb_service_mock.h | 91 + .../test/native/rdb/mock/statement_mock.h | 51 + .../native/rdb/unittest/connection_test.cpp | 214 +- .../rdb/unittest/delay_actuator_test.cpp | 220 + .../native/rdb/unittest/delay_notify_test.cpp | 94 + .../rdb/unittest/dynamic_load_test/BUILD.gn | 151 + .../dynamic_load_test/dynamic_load_test.cpp | 348 + .../unittest/mock_obs_manage_test/BUILD.gn | 156 + .../global_resource_test.cpp | 66 + .../mock_global_resource.cpp | 35 + .../mock_global_resource.h | 41 + .../native/rdb/unittest/mockservice/BUILD.gn | 154 + .../mockservice/rdb_store_impl_test.cpp | 1853 ++ .../multiThread/rdb_connection_rd_test.cpp | 2 +- .../multiThread/rdb_connection_test.cpp | 2 +- .../rdb_store_multiprocess_createDB_test.cpp | 2 +- .../native/rdb/unittest/rd_utils_test.cpp | 145 + .../rdb/unittest/rdb_callback_icu_test.cpp | 166 + .../rdb_concurrent_querywithcurd_test.cpp | 488 + .../native/rdb/unittest/rdb_corrupt_test.cpp | 18 + .../native/rdb/unittest/rdb_delete_test.cpp | 326 +- .../rdb/unittest/rdb_distributed_test.cpp | 4 +- .../unittest/rdb_double_write_binlog_test.cpp | 1460 ++ .../rdb_double_write_concurrent_test.cpp | 2 +- .../rdb/unittest/rdb_double_write_test.cpp | 2959 ++- .../rdb/unittest/rdb_encrypt_decrypt_test.cpp | 151 +- .../rdb/unittest/rdb_encrypt_upgrade_test.cpp | 460 + .../rdb_error_log_test/get_rdb_store_test.cpp | 594 + .../rdb_error_log_test/rdb_error_log_test.cpp | 387 + .../rdb_error_log_test/rdb_perfStat_test.cpp | 436 + .../rdb/unittest/rdb_execute_rd_test.cpp | 445 +- .../native/rdb/unittest/rdb_execute_test.cpp | 418 +- .../native/rdb/unittest/rdb_helper_test.cpp | 28 +- .../native/rdb/unittest/rdb_insert_test.cpp | 806 +- .../rdb/unittest/rdb_memory_db_test.cpp | 12 +- .../rdb/unittest/rdb_predicates_test.cpp | 130 +- .../rdb/unittest/rdb_read_only_test.cpp | 17 +- .../unittest/rdb_security_manager_test.cpp | 44 + .../rdb/unittest/rdb_service_proxy_test.cpp | 62 + .../rdb/unittest/rdb_sql_utils_test.cpp | 173 +- .../rdb_sqlite_shared_result_set_test.cpp | 57 +- .../rdb/unittest/rdb_step_result_set_test.cpp | 8 +- .../rdb_store_backup_restore_test.cpp | 2 +- .../rdb/unittest/rdb_store_config_test.cpp | 33 + .../rdb/unittest/rdb_store_impl_test.cpp | 443 +- .../rdb/unittest/rdb_store_rekey_test.cpp | 720 +- .../rdb/unittest/rdb_store_subscribe_test.cpp | 280 +- .../native/rdb/unittest/rdb_update_test.cpp | 434 +- .../native/rdb/unittest/rdb_utils_test.cpp | 18 + .../unittest/sqlite_statement_test/BUILD.gn | 153 + .../mock_shared_block_test.cpp | 265 + .../sqlite_statement_test.cpp | 128 + .../native/rdb/unittest/sqlite_utils_test.cpp | 189 +- .../native/rdb/unittest/transaction_test.cpp | 1476 +- .../native/rdb_data_ability_adapter/BUILD.gn | 11 +- .../native/rdb_data_share_adapter/BUILD.gn | 30 +- .../unittest/rdb_data_share_adapter_test.cpp | 1312 +- relational_store/test/ndk/BUILD.gn | 32 +- .../ndk/fuzztest/dataasset_fuzzer/BUILD.gn | 69 + .../ndk/fuzztest/dataasset_fuzzer/corpus/init | 14 + .../dataasset_fuzzer/dataasset_fuzzer.cpp | 257 + .../dataasset_fuzzer/dataasset_fuzzer.h | 21 + .../ndk/fuzztest/dataasset_fuzzer/project.xml | 25 + .../ndk/fuzztest/datavalue_fuzzer/BUILD.gn | 70 + .../ndk/fuzztest/datavalue_fuzzer/corpus/init | 14 + .../datavalue_fuzzer/datavalue_fuzzer.cpp | 282 + .../datavalue_fuzzer/datavalue_fuzzer.h | 21 + .../ndk/fuzztest/datavalue_fuzzer/project.xml | 25 + .../ndk/fuzztest/oh_cursor_fuzzer/BUILD.gn | 69 + .../ndk/fuzztest/oh_cursor_fuzzer/corpus/init | 14 + .../oh_cursor_fuzzer/oh_cursor_fuzzer.cpp | 261 + .../oh_cursor_fuzzer/oh_cursor_fuzzer.h | 21 + .../ndk/fuzztest/oh_cursor_fuzzer/project.xml | 25 + .../fuzztest/oh_data_value_fuzzer/BUILD.gn | 69 + .../fuzztest/oh_data_value_fuzzer/corpus/init | 14 + .../oh_data_value_fuzzer.cpp | 422 + .../oh_data_value_fuzzer.h | 21 + .../fuzztest/oh_data_value_fuzzer/project.xml | 25 + .../oh_data_values_buckets_fuzzer/BUILD.gn | 69 + .../oh_data_values_buckets_fuzzer/corpus/init | 14 + .../oh_data_values_buckets_fuzzer.cpp | 125 + .../oh_data_values_buckets_fuzzer.h | 21 + .../oh_data_values_buckets_fuzzer/project.xml | 25 + .../fuzztest/oh_data_values_fuzzer/BUILD.gn | 69 + .../oh_data_values_fuzzer/corpus/init | 14 + .../oh_data_values_fuzzer.cpp | 550 + .../oh_data_values_fuzzer.h | 21 + .../oh_data_values_fuzzer/project.xml | 25 + .../fuzztest/oh_predicates_fuzzer/BUILD.gn | 69 + .../fuzztest/oh_predicates_fuzzer/corpus/init | 14 + .../oh_predicates_fuzzer.cpp | 489 + .../oh_predicates_fuzzer.h | 21 + .../fuzztest/oh_predicates_fuzzer/project.xml | 25 + .../oh_rdb_crypto_param_fuzzer/BUILD.gn | 69 + .../oh_rdb_crypto_param_fuzzer/corpus/init | 14 + .../oh_rdb_crypto_param_fuzzer.cpp | 125 + .../oh_rdb_crypto_param_fuzzer.h | 21 + .../oh_rdb_crypto_param_fuzzer/project.xml | 25 + .../ndk/fuzztest/ohpredicates_fuzzer/BUILD.gn | 69 + .../fuzztest/ohpredicates_fuzzer/corpus/init | 14 + .../ohpredicates_fuzzer.cpp | 52 + .../ohpredicates_fuzzer/ohpredicates_fuzzer.h | 21 + .../fuzztest/ohpredicates_fuzzer/project.xml | 25 + .../fuzztest/ohrdbtransaction_fuzzer/BUILD.gn | 70 + .../ohrdbtransaction_fuzzer/corpus/init | 14 + .../ohrdbtransaction_fuzzer.cpp | 205 + .../ohrdbtransaction_fuzzer.h | 21 + .../ohrdbtransaction_fuzzer/project.xml | 25 + .../fuzztest/relationalstore_fuzzer/BUILD.gn | 72 + .../relationalstore_fuzzer/corpus/init | 14 + .../relationalstore_fuzzer/project.xml | 25 + .../relationalstore_fuzzer.cpp | 428 + .../relationalstore_fuzzer.h | 21 + .../relationalstorecapi_fuzzer/BUILD.gn | 69 + .../relationalstorecapi_fuzzer/corpus/init | 14 + .../relationalstorecapi_fuzzer/project.xml | 25 + .../relationalstorecapi_fuzzer.cpp | 526 + .../relationalstorecapi_fuzzer.h | 21 + .../ndk/fuzztest/valuebucket_fuzzer/BUILD.gn | 70 + .../fuzztest/valuebucket_fuzzer/corpus/init | 14 + .../fuzztest/valuebucket_fuzzer/project.xml | 25 + .../valuebucket_fuzzer/valuebucket_fuzzer.cpp | 177 + .../valuebucket_fuzzer/valuebucket_fuzzer.h | 21 + .../ndk/fuzztest/valueobject_fuzzer/BUILD.gn | 70 + .../fuzztest/valueobject_fuzzer/corpus/init | 14 + .../fuzztest/valueobject_fuzzer/project.xml | 25 + .../valueobject_fuzzer/valueobject_fuzzer.cpp | 108 + .../valueobject_fuzzer/valueobject_fuzzer.h | 21 + .../ndk/unittest/rdb_crypto_param_test.cpp | 216 + .../test/ndk/unittest/rdb_cursor_test.cpp | 10 +- .../ndk/unittest/rdb_performance_test.cpp | 376 + .../ndk/unittest/rdb_predicates_pref_test.cpp | 71 + .../test/ndk/unittest/rdb_predicates_test.cpp | 371 +- .../ndk/unittest/rdb_store_configv2_test.cpp | 324 +- .../test/ndk/unittest/rdb_store_test.cpp | 213 +- .../unittest/rdb_transaction_capi_test.cpp | 547 + test/CMakeLists.txt | 49 +- udmf/BUILD.gn | 9 +- udmf/CMakeLists.txt | 2 + udmf/CODEOWNERS | 4 +- udmf/adapter/BUILD.gn | 38 +- udmf/adapter/arkui_x_udmf.gni | 3 + .../client/preset_type_descriptors.cpp | 3346 +++ .../innerkitsimpl/client/utd_client.cpp | 259 +- .../innerkitsimpl/client/utd_client.h | 2 +- .../innerkitsimpl/common/unified_meta.cpp | 104 +- udmf/bundle.json | 39 +- udmf/conf/BUILD.gn | 22 + udmf/conf/uniform_data_types.json | 6580 ++++++ udmf/framework/common/concurrent_map.h | 305 + .../common/custom_utd_json_parser.cpp | 71 +- .../framework/common/custom_utd_json_parser.h | 8 +- udmf/framework/common/custom_utd_store.cpp | 113 +- udmf/framework/common/custom_utd_store.h | 9 +- udmf/framework/common/graph.cpp | 8 +- udmf/framework/common/graph.h | 23 +- udmf/framework/common/itypes_util.h | 603 + udmf/framework/common/tlv_object.cpp | 9 +- udmf/framework/common/tlv_object.h | 12 +- udmf/framework/common/tlv_tag.h | 13 + udmf/framework/common/tlv_util.cpp | 160 +- udmf/framework/common/tlv_util.h | 68 + udmf/framework/common/udmf_copy_file.cpp | 2 +- udmf/framework/common/udmf_executor.cpp | 38 + udmf/framework/common/udmf_executor.h | 39 + udmf/framework/common/udmf_radar_reporter.cpp | 38 + udmf/framework/common/udmf_radar_reporter.h | 8 +- udmf/framework/common/udmf_types_util.cpp | 127 +- udmf/framework/common/udmf_types_util.h | 13 + udmf/framework/common/udmf_utils.cpp | 51 +- udmf/framework/common/udmf_utils.h | 8 +- udmf/framework/common/unittest/BUILD.gn | 83 +- .../unittest/mock/file_copy_manager_mock.cpp | 148 + .../unittest/mock/message_parcel_mock.cpp | 253 + .../unittest/mock/message_parcel_mock.h | 94 + .../common/unittest/mock/tlv_util_mock.cpp | 18 +- .../common/unittest/tlv_util_test.cpp | 448 +- .../common/unittest/udmf_copy_file_test.cpp | 150 + .../udmf_types_util_abnormal_test.cpp | 27 +- .../unittest/udmf_types_util_mock_test.cpp | 275 + .../common/unittest/udmf_types_util_test.cpp | 27 + .../common/unittest/utd_cfgs_checker_test.cpp | 2 +- udmf/framework/common/utd_cfgs_checker.cpp | 46 +- udmf/framework/common/utd_cfgs_checker.h | 1 + udmf/framework/common/utd_common.h | 16 +- udmf/framework/common/utd_graph.cpp | 6 +- udmf/framework/common/utd_graph.h | 1 - .../client/udmf_async_client.cpp | 92 +- .../innerkitsimpl/client/udmf_client.cpp | 183 +- .../innerkitsimpl/client/utd_client.cpp | 229 +- .../innerkitsimpl/common/unified_key.cpp | 81 +- .../innerkitsimpl/common/unified_meta.cpp | 130 +- .../convert/data_params_conversion.cpp | 49 +- .../convert/ndk_data_conversion.cpp | 77 +- .../innerkitsimpl/convert/udmf_conversion.cpp | 2 + .../data/application_defined_record.cpp | 1 - udmf/framework/innerkitsimpl/data/audio.cpp | 16 +- udmf/framework/innerkitsimpl/data/file.cpp | 23 +- .../innerkitsimpl/data/flexible_type.cpp | 27 +- udmf/framework/innerkitsimpl/data/folder.cpp | 16 +- udmf/framework/innerkitsimpl/data/html.cpp | 1 - udmf/framework/innerkitsimpl/data/image.cpp | 16 +- udmf/framework/innerkitsimpl/data/link.cpp | 1 - .../innerkitsimpl/data/plain_text.cpp | 1 - .../data/preset_type_descriptors.cpp | 3335 +-- .../data/preset_type_descriptors.h | 4 +- .../data/system_defined_appitem.cpp | 1 - .../data/system_defined_form.cpp | 1 - .../data/system_defined_pixelmap.cpp | 71 +- .../data/system_defined_record.cpp | 1 - udmf/framework/innerkitsimpl/data/text.cpp | 1 - .../innerkitsimpl/data/type_descriptor.cpp | 20 +- .../innerkitsimpl/data/unified_data.cpp | 24 +- .../data/unified_data_helper.cpp | 86 +- .../data/unified_html_record_process.cpp | 16 +- .../innerkitsimpl/data/unified_record.cpp | 84 +- udmf/framework/innerkitsimpl/data/video.cpp | 16 +- .../innerkitsimpl/dynamic/pixelmap_loader.cpp | 177 + .../dynamic/pixelmap_wrapper.cpp | 104 + .../distributeddata_udmf_ipc_interface_code.h | 10 + .../innerkitsimpl/service/iudmf_notifier.h | 37 +- .../service/progress_callback.cpp | 14 +- .../service/udmf_notifier_stub.cpp | 96 + .../service/udmf_notifier_stub.h | 87 +- .../innerkitsimpl/service/udmf_service.h | 6 + .../service/udmf_service_client.cpp | 43 +- .../service/udmf_service_client.h | 5 + .../service/udmf_service_proxy.cpp | 52 + .../service/udmf_service_proxy.h | 5 + .../test/fuzztest/udmfclient_fuzzer/BUILD.gn | 2 + .../udmfclient_fuzzer/udmf_client_fuzzer.cpp | 267 +- .../test/fuzztest/utdclient_fuzzer/BUILD.gn | 2 +- .../utdclient_fuzzer/utd_client_fuzzer.cpp | 71 +- .../innerkitsimpl/test/unittest/BUILD.gn | 208 +- .../test/unittest/custom_utd_store_test.cpp | 282 +- .../test/unittest/graph_test.cpp | 2 +- .../mock/include/udmf_service_client_mock.h | 8 + .../mock/udmf_service_client_mock.cpp | 29 + .../unittest/ndk_data_conversion_test.cpp | 69 +- .../unittest/preset_type_descriptor_test.cpp | 69 + .../unittest/system_defined_form_test.cpp | 84 + .../unittest/system_defined_pixelmap_test.cpp | 252 +- .../test/unittest/udmf_async_client_test.cpp | 431 +- .../unittest/udmf_client_abnormal_test.cpp | 1 + .../unittest/udmf_client_file_manger_test.cpp | 2159 ++ .../udmf_client_hap_permission_test.cpp | 65 +- .../test/unittest/udmf_client_test.cpp | 1189 +- .../test/unittest/udmf_delay_data_test.cpp | 717 + .../unittest/unified_data_helper_test.cpp | 66 + .../test/unittest/unified_data_test.cpp | 197 +- .../test/unittest/unified_key_test.cpp | 339 + .../test/unittest/unified_meta_test.cpp | 342 +- .../test/unittest/unified_record_test.cpp | 47 +- .../test/unittest/utd_client_test.cpp | 663 + .../unittest/utd_concurrent_update_test.cpp | 162 + .../jskitsimpl/common/napi_data_utils.cpp | 134 + .../jskitsimpl/common/napi_error_utils.cpp | 3 +- .../jskitsimpl/common/napi_queue.cpp | 7 +- .../jskitsimpl/data/data_load_params_napi.cpp | 116 + .../jskitsimpl/data/get_data_params_napi.cpp | 7 + .../data/unified_data_channel_napi.cpp | 126 +- .../jskitsimpl/data/unified_data_napi.cpp | 103 +- .../intelligence/aip_napi_error.cpp | 46 +- .../intelligence/aip_napi_utils.cpp | 138 +- .../intelligence/i_aip_core_manager_impl.cpp | 42 +- .../intelligence/image_embedding_napi.cpp | 34 +- .../jskitsimpl/intelligence/js_ability.cpp | 9 + .../native_module_intelligence.cpp | 1 - .../intelligence/native_module_rag.cpp | 50 + .../intelligence/rag_agent_chatllm_napi.cpp | 63 + .../intelligence/rag_chatllm_impl.cpp | 356 + .../intelligence/rag_session_napi.cpp | 625 + .../intelligence/retrieval_napi.cpp | 370 - .../intelligence/text_embedding_napi.cpp | 66 +- .../framework/jskitsimpl/test}/BUILD.gn | 14 +- .../stage_unittest/udmf/src/AppScope/app.json | 21 + .../resources/base/element/string.json | 8 + .../unittest/stage_unittest/udmf/src/BUILD.gn | 48 + .../stage_unittest/udmf/src/Test.json | 27 + .../src/main/ets/Application/AbilityStage.ts | 23 + .../src/main/ets/MainAbility/MainAbility.ts | 50 + .../ets/MainAbility/pages/index/index.ets | 55 + .../ets/MainAbility/pages/second/second.ets | 43 + .../src/main/ets/TestAbility/TestAbility.ts | 43 + .../src/main/ets/TestAbility/pages/index.ets | 48 + .../ets/TestRunner/OpenHarmonyTestRunner.ts | 72 + .../src/entry/src/main/ets/test/List.test.ets | 24 + .../main/ets/test/StageUdmfCallBacktest.ets | 220 + .../main/ets/test/StageUdmfFileMangertest.ets | 1348 ++ .../main/ets/test/StageUdmfPromisetest.ets | 64 + .../udmf/src/entry/src/main/module.json | 77 +- .../main/resources/base/element/string.json | 24 + .../resources/base/profile/form_config.json | 6 + .../resources/base/profile/form_config1.txt | 1 + .../resources/base/profile/main_pages.json | 6 + .../base/profile/shortcuts_config.json | 6 + .../udmf/src/signature/openharmony_sx.p7b | Bin 0 -> 3500 bytes .../jskitsimpl/unittest/AipRdbJsTest.js | 981 - udmf/framework/jskitsimpl/unittest/BUILD.gn | 2 +- .../unittest/UdmfIntelligenceJsTest.js | 507 + .../jskitsimpl/unittest/UdmfJsTest.js | 292 +- .../jskitsimpl/unittest/UdmfPromiseJsTest.js | 51 + .../ndkimpl/data/data_provider_impl.cpp | 3 +- udmf/framework/ndkimpl/data/udmf.cpp | 561 +- .../framework/ndkimpl/data/udmf_capi_common.h | 50 +- udmf/framework/ndkimpl/data/uds.cpp | 12 +- udmf/framework/ndkimpl/data/utd.cpp | 11 +- udmf/framework/ndkimpl/udmf_fuzzer/BUILD.gn | 68 + .../framework/ndkimpl/udmf_fuzzer/corpus/init | 7 +- .../framework/ndkimpl/udmf_fuzzer/project.xml | 25 + .../ndkimpl/udmf_fuzzer/udmf_fuzzer.cpp | 242 + .../ndkimpl/udmf_fuzzer/udmf_fuzzer.h | 10 +- udmf/framework/ndkimpl/unittest/BUILD.gn | 8 +- udmf/framework/ndkimpl/unittest/udmf_test.cpp | 1497 +- udmf/interfaces/ani/BUILD.gn | 131 + .../ani/ets/@ohos.data.unifiedDataChannel.ets | 112 + .../ets/@ohos.data.uniformTypeDescriptor.ets | 19 + .../ani/native/include/ani_util_class.h | 122 + .../ani/native/include/ani_util_common.h | 172 + .../ani/native/include/ani_util_native_ptr.h | 79 + .../interfaces/ani/native/include/ani_utils.h | 455 + .../native/include/unifieddatachannel_ani.h | 51 +- .../ani/native/src/unifieddatachannel_ani.cpp | 423 + .../native/src/uniformTypeDescriptor_ani.cpp | 135 + udmf/interfaces/cj/BUILD.gn | 3 + udmf/interfaces/cj/include/unified_data_ffi.h | 19 +- .../interfaces/cj/include/unified_data_impl.h | 54 +- .../cj/include/unified_data_parameter_parse.h | 28 +- .../cj/include/unified_record_ffi.h | 42 +- .../cj/include/unified_record_impl.h | 120 +- udmf/interfaces/cj/include/utils.h | 1 + .../cj/src/unified_data_channel_ffi.cpp | 174 + udmf/interfaces/cj/src/unified_data_ffi.cpp | 164 +- udmf/interfaces/cj/src/unified_data_impl.cpp | 141 +- .../cj/src/unified_data_parameter_parse.cpp | 234 + udmf/interfaces/cj/src/unified_record_ffi.cpp | 304 +- .../interfaces/cj/src/unified_record_impl.cpp | 538 +- udmf/interfaces/cj/src/utils.cpp | 25 +- udmf/interfaces/components/UdmfComponents.js | 613 +- .../components/source/UdmfComponents.ets | 25 +- udmf/interfaces/components/udmfcomponents.cpp | 9 +- udmf/interfaces/innerkits/BUILD.gn | 48 +- udmf/interfaces/innerkits/aipcore/BUILD.gn | 35 + .../aipcore}/i_aip_core_manager.h | 60 +- .../innerkits/client/udmf_async_client.h | 8 +- .../interfaces/innerkits/client/udmf_client.h | 11 +- udmf/interfaces/innerkits/client/utd_client.h | 15 +- .../innerkits/common/async_task_params.h | 11 +- udmf/interfaces/innerkits/common/error_code.h | 15 +- .../innerkits/common/progress_queue.h | 2 +- .../interfaces/innerkits/common/unified_key.h | 6 +- .../innerkits/common/unified_meta.h | 76 +- .../innerkits/common/unified_types.h | 50 +- .../convert/data_params_conversion.h | 2 + .../innerkits/convert/ndk_data_conversion.h | 12 +- .../data/application_defined_record.h | 2 +- udmf/interfaces/innerkits/data/audio.h | 1 + udmf/interfaces/innerkits/data/file.h | 3 +- .../interfaces/innerkits/data/flexible_type.h | 2 + udmf/interfaces/innerkits/data/folder.h | 1 + udmf/interfaces/innerkits/data/html.h | 1 - udmf/interfaces/innerkits/data/image.h | 1 + udmf/interfaces/innerkits/data/link.h | 1 - udmf/interfaces/innerkits/data/plain_text.h | 1 - .../innerkits/data/system_defined_appitem.h | 1 - .../innerkits/data/system_defined_pixelmap.h | 5 +- .../innerkits/data/system_defined_record.h | 2 +- udmf/interfaces/innerkits/data/text.h | 2 +- .../innerkits/data/type_descriptor.h | 7 +- udmf/interfaces/innerkits/data/unified_data.h | 4 +- .../innerkits/data/unified_data_helper.h | 4 + .../innerkits/data/unified_data_properties.h | 4 +- .../innerkits/data/unified_record.h | 10 +- udmf/interfaces/innerkits/data/video.h | 1 + .../innerkits/dynamic/pixelmap_loader.h | 65 + .../innerkits/dynamic/pixelmap_wrapper.h | 36 + udmf/interfaces/jskits/BUILD.gn | 72 +- .../jskits/common/napi_data_utils.h | 15 + .../jskits/data/data_load_params_napi.h | 47 +- .../jskits/data/unified_data_channel_napi.h | 5 + .../jskits/data/unified_data_napi.h | 2 + .../jskits/intelligence/aip_napi_error.h | 70 +- .../jskits/intelligence/aip_napi_utils.h | 9 + .../interfaces/jskits/intelligence}/hitrace.h | 12 +- .../intelligence/i_aip_core_manager_impl.h | 12 +- .../jskits/intelligence/js_ability.h | 2 + .../jskits/intelligence/napi_trace.h | 12 +- .../intelligence/native_module_intelligence.h | 1 - .../jskits/intelligence/native_module_rag.h | 22 + .../intelligence/rag_agent_chatllm_napi.h | 34 +- .../jskits/intelligence/rag_chatllm_impl.h | 76 + .../{retrieval_napi.h => rag_session_napi.h} | 90 +- udmf/interfaces/ndk/BUILD.gn | 2 + udmf/interfaces/ndk/data/data_provider_impl.h | 2 +- udmf/interfaces/ndk/data/udmf.h | 356 +- utils_native/CMakeLists.txt | 1 + utils_native/base/include/cJSON.h | 158 +- utils_native/base/src/cJSON.c | 1423 +- 2571 files changed, 208817 insertions(+), 97071 deletions(-) create mode 100644 data_object/frameworks/innerkitsimpl/include/communicator/block_data.h create mode 100644 data_object/frameworks/innerkitsimpl/include/communicator/task_scheduler.h create mode 100644 data_object/frameworks/innerkitsimpl/test/unittest/src/task_scheduler_test.cpp create mode 100644 data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/RunTest.ets create mode 100644 data_object/frameworks/jskitsimpl/include/adaptor/progress_notifier_impl.h create mode 100644 data_object/frameworks/jskitsimpl/src/adaptor/progress_notifier_impl.cpp create mode 100644 data_share/cfi_blocklist.txt create mode 100644 data_share/frameworks/js/ani/BUILD.gn create mode 100644 data_share/frameworks/js/ani/common/include/ani_util_class.h create mode 100644 data_share/frameworks/js/ani/common/include/ani_util_common.h create mode 100644 data_share/frameworks/js/ani/common/include/ani_util_native_ptr.h create mode 100644 data_share/frameworks/js/ani/common/include/ani_utils.h create mode 100644 data_share/frameworks/js/ani/common/include/datashare_predicates_cleaner.h create mode 100644 data_share/frameworks/js/ani/common/src/ani_utils.cpp create mode 100644 data_share/frameworks/js/ani/dataShare/BUILD.gn create mode 100644 data_share/frameworks/js/ani/dataShare/ets/@ohos.data.dataShare.ets create mode 100644 data_share/frameworks/js/ani/dataShare/ets/@ohos.data.dataSharePredicates.ets create mode 100644 data_share/frameworks/js/ani/dataShare/include/ani_datashare_helper.h create mode 100644 data_share/frameworks/js/ani/dataShare/include/ani_datashare_inner_observer.h create mode 100644 data_share/frameworks/js/ani/dataShare/include/ani_datashare_observer.h create mode 100644 data_share/frameworks/js/ani/dataShare/src/ani_datashare_helper.cpp create mode 100644 data_share/frameworks/js/ani/dataShare/src/ani_datashare_inner_observer.cpp create mode 100644 data_share/frameworks/js/ani/dataShare/src/ani_datashare_observer.cpp create mode 100644 data_share/frameworks/js/ani/dataShare/src/data_share_predicates.cpp create mode 100644 data_share/frameworks/js/ani/dataShareResultSet/BUILD.gn create mode 100644 data_share/frameworks/js/ani/dataShareResultSet/ets/@ohos.data.DataShareResultSet.ets create mode 100644 data_share/frameworks/js/ani/dataShareResultSet/src/data_share_result_set.cpp create mode 100644 data_share/frameworks/js/napi/dataShare/include/napi_dataproxy_handle.h create mode 100644 data_share/frameworks/js/napi/dataShare/src/napi_dataproxy_handle.cpp create mode 100644 data_share/frameworks/native/common/include/datashare_common.h create mode 100644 data_share/frameworks/native/common/include/serializable.h create mode 100644 data_share/frameworks/native/common/src/datashare_predicates.cpp create mode 100644 data_share/frameworks/native/common/src/serializable.cpp create mode 100644 data_share/frameworks/native/consumer/src/dataproxy_handle.cpp create mode 100644 data_share/frameworks/native/dfx/include/hiview_datashare.h create mode 100644 data_share/frameworks/native/dfx/src/hiview_datashare.cpp create mode 100644 data_share/frameworks/native/permission/include/data_share_config.h create mode 100644 data_share/frameworks/native/permission/src/data_share_config.cpp create mode 100644 data_share/frameworks/native/proxy/include/proxy_data_subscriber_manager.h create mode 100644 data_share/frameworks/native/proxy/src/proxy_data_subscriber_manager.cpp create mode 100644 data_share/interfaces/inner_api/common/include/dataproxy_handle_common.h create mode 100644 data_share/interfaces/inner_api/common/include/datashare_option.h create mode 100644 data_share/interfaces/inner_api/consumer/include/dataproxy_handle.h create mode 100644 data_share/test/ets/data_share_ets/AppScope/app.json create mode 100644 data_share/test/ets/data_share_ets/AppScope/resources/base/element/string.json rename relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/corpus/init => data_share/test/ets/data_share_ets/BUILD.gn (39%) create mode 100644 data_share/test/ets/data_share_ets/Test.json create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/ets/Application/AbilityStage.ts create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/ets/DataShareExtensionAbility/DataShareExtAbility.ts create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/MainAbility.ts create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/pages/index/index.ets create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/pages/second/second.ets create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/ets/TestAbility/TestAbility.ts create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/ets/TestAbility/pages/index.ets create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts rename relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/rddbopen_fuzzer.h => data_share/test/ets/data_share_ets/entry/src/main/ets/test/List.test.ets (71%) create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/ets/test/dataSharePredicate.test.ets create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/ets/test/dataShareSubscribe.test.ets create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/module.json create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/resources/base/element/string.json create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/resources/base/media/icon.png create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/form_config.json create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/form_config1.txt create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/invalid.txt create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/main_pages.json create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/shortcuts_config.json create mode 100644 data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/test.json create mode 100644 data_share/test/ets/data_share_ets/signature/openharmony_sx.p7b rename {relational_store/test/js/gdb/unittest/src => data_share/test/fuzztest}/BUILD.gn (65%) create mode 100644 data_share/test/fuzztest/datasharehelp_fuzzer/BUILD.gn rename {kv_store/test/fuzztest/distributedkvdataservice_fuzzer => data_share/test/fuzztest/datasharehelp_fuzzer}/corpus/init (92%) create mode 100644 data_share/test/fuzztest/datasharehelp_fuzzer/datasharehelp_fuzzer.cpp create mode 100644 data_share/test/fuzztest/datasharehelp_fuzzer/datasharehelp_fuzzer.h rename {relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer => data_share/test/fuzztest/datasharehelp_fuzzer}/project.xml (64%) create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/app.json5 create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/resources/base/element/string.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/resources/base/media/app_icon.png create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/entryability/EntryAbility.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/pages/Index.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/pages/myClient.test.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/module.json5 create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/element/color.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/element/string.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/media/icon.png create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/media/startlcon.png create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/profile/main_pages.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/en_US/element/string.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/zh_CN/element/string.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/test/Ability.test.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/test/List.test.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testability/TestAbility.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testability/pages/Index.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/module.json5 create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/element/color.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/element/string.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/media/icon.png create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/profile/test_pages.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/test/List.test.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/test/LocalUnit.test.ets rename relational_store/frameworks/native/gdb/src/db_helper.cpp => data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/hvigor/hvigor-config.json5 (35%) create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/sign/openharmony_sx.p7b create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/AppScope/app.json5 create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/AppScope/resources/base/element/string.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/AppScope/resources/base/media/app_icon.png create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/DataShareExtAbility/DataShareExtAbility.ts create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/entryability/EntryAbility.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/pages/Index.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/pages/myServer.test.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/module.json5 create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/element/color.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/element/string.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/media/icon.png create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/media/startlcon.png create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/profile/main_pages.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/profile/test.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/en_US/element/string.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/zh_CN/element/string.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/test/Ability.test.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/test/List.test.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testability/TestAbility.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testability/pages/Index.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/module.json5 create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/element/color.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/element/string.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/media/icon.png create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/profile/test_pages.json create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/test/List.test.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/test/LocalUnit.test.ets create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/hvigor/hvigor-config.json5 create mode 100644 data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/sign/openharmony_sx.p7b create mode 100644 data_share/test/native/resource/datashareclient_normal_bundle/AppScope/app.json5 create mode 100644 data_share/test/native/resource/datashareclient_normal_bundle/AppScope/resources/base/element/string.json create mode 100644 data_share/test/native/resource/datashareclient_normal_bundle/AppScope/resources/base/media/app_icon.png create mode 100644 data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/entryability/EntryAbility.ets create mode 100644 data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/pages/Index.ets create mode 100644 data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/pages/myClient.test.ets create mode 100644 data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/module.json5 create mode 100644 data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/element/color.json create mode 100644 data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/element/string.json create mode 100644 data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/media/icon.png create mode 100644 data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/media/startlcon.png create mode 100644 data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/profile/main_pages.json create mode 100644 data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/en_US/element/string.json create mode 100644 data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/zh_CN/element/string.json create mode 100644 data_share/test/native/resource/datashareclient_normal_bundle/sign/openharmony_sx.p7b rename relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/corpus/init => data_share/test/native/resource/ohos_test_new/BUILD.gn (69%) create mode 100644 data_share/test/native/resource/ohos_test_new/ohos_test_new.xml create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/AppScope/app.json5 create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/AppScope/resources/base/element/string.json create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/AppScope/resources/base/media/app_icon.png create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/AssetUtil.ets create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/FileUtil.ets create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/entryability/EntryAbility.ets create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/DataShare.ets create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/Index.ets create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/SystemApi.ets create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/module.json5 create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/element/color.json create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/element/string.json create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/media/icon.png create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/media/startlcon.png create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/profile/main_pages.json create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/en_US/element/string.json create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/zh_CN/element/string.json create mode 100644 data_share/test/native/resource/systemapp_verify_bundle/sign/openharmony_sx.p7b create mode 100644 data_share/test/native/unittest/dataproxy_handle_test/dataproxy_handle_test.cpp create mode 100644 data_share/test/native/unittest/datashare_access_threshold_test/datashare_threshold_test.cpp create mode 100644 data_share/test/native/unittest/datashare_common_test/datashare_itypes_utils_test.cpp create mode 100644 data_share/test/native/unittest/long_time/concurrent_test/BUILD.gn create mode 100644 data_share/test/native/unittest/long_time/concurrent_test/concurrent_subscriber_test.cpp create mode 100644 data_share/test/native/unittest/mediadatashare_test/src/datashare_block_writer_impl_test.cpp create mode 100644 data_share/test/native/unittest/mediadatashare_test/src/datashare_common_test.cpp create mode 100644 data_share/test/native/unittest/mediadatashare_test/src/datashare_connection_test.cpp create mode 100644 data_share/test/native/unittest/mediadatashare_test/src/datashare_helper_impl_test.cpp create mode 100644 data_share/test/native/unittest/mediadatashare_test/src/datashare_helper_test.cpp create mode 100644 data_share/test/native/unittest/mediadatashare_test/src/datashare_proxy_test.cpp create mode 100644 data_share/test/native/unittest/mediadatashare_test/src/datashare_stub_test.cpp create mode 100644 data_share/test/native/unittest/mediadatashare_test/src/shared_block_test.cpp create mode 100644 data_share/test/native/unittest/mediadatashare_test/src/uri_utils_test.cpp create mode 100644 data_share/test/native/unittest/mock/ikvstore_data_service_mock.h rename {relational_store/test/js/gdb => data_share/test/unittest/native}/BUILD.gn (58%) create mode 100644 data_share/test/unittest/native/common/BUILD.gn create mode 100644 data_share/test/unittest/native/common/src/datashare_abs_result_set_test.cpp create mode 100644 data_share/test/unittest/native/common/src/datashare_block_writer_impl_test.cpp create mode 100644 data_share/test/unittest/native/common/src/datashare_result_set_test.cpp create mode 100644 data_share/test/unittest/native/common/src/datashare_valuebucket_convert_test.cpp create mode 100644 data_share/test/unittest/native/common/src/ishared_result_set_stub_test.cpp create mode 100644 data_share/test/unittest/native/consumer/BUILD.gn create mode 100644 data_share/test/unittest/native/consumer/include/ikvstore_data_service_mock.h create mode 100644 data_share/test/unittest/native/consumer/src/datashare_connection_test.cpp create mode 100644 data_share/test/unittest/native/consumer/src/datashare_helper_impl_test.cpp create mode 100644 data_share/test/unittest/native/consumer/src/datashare_helper_test.cpp create mode 100644 data_share/test/unittest/native/consumer/src/datashare_proxy_test.cpp create mode 100644 data_share/test/unittest/native/provider/BUILD.gn create mode 100644 data_share/test/unittest/native/provider/src/datashare_stub_test.cpp rename datamgr_service/services/distributeddataservice/{service/crypto => adapter/bundle_mgr}/BUILD.gn (71%) create mode 100644 datamgr_service/services/distributeddataservice/adapter/bundle_mgr/bundle_mgr_adapter.cpp create mode 100644 datamgr_service/services/distributeddataservice/adapter/bundle_mgr/bundle_mgr_adapter.h create mode 100644 datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/BUILD.gn create mode 100644 datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/bundle_mgr_client.h rename relational_store/interfaces/inner_api/gdb/include/result.h => datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/bundle_mgr_test.cpp (41%) create mode 100644 datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager.cpp create mode 100644 datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager.h create mode 100644 datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager_callback.h create mode 100644 datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/dm_device_info.h rename relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/transfergrdtypetocoltype_fuzzer.cpp => datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/data_level.cpp (43%) create mode 100644 datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/data_level.h create mode 100644 datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/inner_socket.cpp create mode 100644 datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/inner_socket.h create mode 100644 datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/socket.cpp create mode 100644 datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/socket.h create mode 100644 datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/softbus_error_code.h create mode 100644 datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/BUILD.gn rename {kv_store/test/fuzztest/singlekvstorestub_fuzzer => datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer}/corpus/init (92%) create mode 100644 datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/networkdelegatenormalimpl_fuzzer.cpp rename kv_store/test/fuzztest/distributedkvdataservice_fuzzer/distributedkvdataservice_fuzzer.h => datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/networkdelegatenormalimpl_fuzzer.h (70%) rename {kv_store/test/fuzztest/jsonservice_fuzzer => datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer}/project.xml (63%) rename datamgr_service/services/distributeddataservice/adapter/schema_helper/{src => }/get_schema_helper.cpp (98%) rename datamgr_service/services/distributeddataservice/adapter/{include => }/schema_helper/get_schema_helper.h (100%) rename datamgr_service/services/distributeddataservice/adapter/screenlock/{src => }/screen_lock.cpp (94%) rename datamgr_service/services/distributeddataservice/adapter/{include => }/screenlock/screen_lock.h (100%) create mode 100644 datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/BUILD.gn rename kv_store/test/fuzztest/jsonservice_fuzzer/jsonservice_fuzzer.h => datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/corpus/init (78%) create mode 100644 datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/project.xml create mode 100644 datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/screenlock_fuzzer.cpp rename relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/rddbrepair_fuzzer.h => datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/screenlock_fuzzer.h (76%) create mode 100644 datamgr_service/services/distributeddataservice/app/test/mock/capability/device_manager_adapter.cpp create mode 100644 datamgr_service/services/distributeddataservice/app/test/mock/capability/device_manager_adapter.h create mode 100644 datamgr_service/services/distributeddataservice/app/test/mock/capability/metadata/meta_data_manager.cpp rename relational_store/frameworks/native/gdb/include/rdb_fault_hiview_reporter.h => datamgr_service/services/distributeddataservice/app/test/mock/capability/metadata/meta_data_manager.h (35%) create mode 100644 datamgr_service/services/distributeddataservice/app/test/unittest/bundle_checker_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_meta_manager_update_key_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/app/test/unittest/route_head_handler_impl_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/app/test/unittest/security_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/app/test/unittest/sensitive_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/app/test/unittest/upgrade_manager_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/access_check/app_access_check_config_manager.cpp rename datamgr_service/services/distributeddataservice/{service/crypto/src => framework/crypto}/crypto_manager.cpp (62%) create mode 100644 datamgr_service/services/distributeddataservice/framework/device_manager/device_manager_delegate.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/device_sync_app/device_sync_app_manager.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/include/access_check/app_access_check_config_manager.h rename datamgr_service/services/distributeddataservice/{service/crypto/include => framework/include/crypto}/crypto_manager.h (53%) create mode 100644 datamgr_service/services/distributeddataservice/framework/include/device_manager/device_manager_delegate.h create mode 100644 datamgr_service/services/distributeddataservice/framework/include/device_manager/device_manager_types.h create mode 100644 datamgr_service/services/distributeddataservice/framework/include/device_sync_app/device_sync_app_manager.h rename relational_store/test/native/gdb/unittest/gdb_store_config_test.cpp => datamgr_service/services/distributeddataservice/framework/include/metadata/object_user_meta_data.h (49%) create mode 100644 datamgr_service/services/distributeddataservice/framework/metadata/object_user_meta_data.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/test/app_id_mapping_config_manager_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/test/connect_manager_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/test/device_sync_app_manager_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/test/fuzztest/BUILD.gn create mode 100644 datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/BUILD.gn create mode 100644 datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/corpus/init create mode 100644 datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/project.xml rename relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/rddbrepair_fuzzer.cpp => datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/screenmanager_fuzzer.cpp (53%) create mode 100644 datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/screenmanager_fuzzer.h create mode 100644 datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/BUILD.gn create mode 100644 datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/corpus/init create mode 100644 datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/project.xml create mode 100644 datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/storedebuginfo_fuzzer.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/storedebuginfo_fuzzer.h create mode 100644 datamgr_service/services/distributeddataservice/framework/test/mock/db_store_mock.cpp create mode 100644 datamgr_service/services/distributeddataservice/framework/test/mock/db_store_mock.h create mode 100644 datamgr_service/services/distributeddataservice/framework/test/screen_manager_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/rust/test/BUILD.gn create mode 100644 datamgr_service/services/distributeddataservice/rust/test/unittest/extension_util_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/cloud/cloud_notifier_proxy.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/cloud/cloud_notifier_proxy.h create mode 100644 datamgr_service/services/distributeddataservice/service/config/include/model/app_access_check_config.h create mode 100644 datamgr_service/services/distributeddataservice/service/config/include/model/datashare_config.h create mode 100644 datamgr_service/services/distributeddataservice/service/config/include/model/device_sync_app_white_list_config.h create mode 100644 datamgr_service/services/distributeddataservice/service/config/src/model/app_access_check_config.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/config/src/model/datashare_config.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/config/src/model/device_sync_app_white_list_config.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/data_share/common/common_utils.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/data_share/common/common_utils.h create mode 100644 datamgr_service/services/distributeddataservice/service/data_share/common/proxy_data_manager.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/data_share/common/proxy_data_manager.h rename datamgr_service/services/distributeddataservice/service/data_share/common/{uri_utils.cpp => utils.cpp} (86%) rename datamgr_service/services/distributeddataservice/service/data_share/common/{uri_utils.h => utils.h} (78%) create mode 100644 datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.h create mode 100644 datamgr_service/services/distributeddataservice/service/test/cloud_data_mock_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/data_proxy_handle_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/data_share_scheduler_manager_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/data_share_sys_event_subscriber_test.cpp rename relational_store/frameworks/native/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp => datamgr_service/services/distributeddataservice/service/test/data_share_uri_utils_test.cpp (34%) create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/BUILD.gn create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/corpus/init create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/datashareserviceimpl_fuzzer.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/datashareserviceimpl_fuzzer.h create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/project.xml create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/BUILD.gn create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/corpus/init create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/datasharesubscriber_fuzzer.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/datasharesubscriber_fuzzer.h create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/project.xml create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/BUILD.gn create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/corpus/init create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/objectserviceimp_fuzzer.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/objectserviceimp_fuzzer.h create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/project.xml create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/BUILD.gn create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/corpus/init create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/objectservicelistener_fuzzer.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/objectservicelistener_fuzzer.h create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/project.xml create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/BUILD.gn create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/corpus/init create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/project.xml create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/syncstrategies_fuzzer.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/syncstrategies_fuzzer.h create mode 100644 datamgr_service/services/distributeddataservice/service/test/kvdb_service_password_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/mock/auth_delegate_mock.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/mock/auth_delegate_mock.h create mode 100644 datamgr_service/services/distributeddataservice/service/test/mock/cloud_db_mock.h create mode 100644 datamgr_service/services/distributeddataservice/service/test/mock/device_matrix_mock.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/mock/device_matrix_mock.h create mode 100644 datamgr_service/services/distributeddataservice/service/test/mock/distributed_file_daemon_manager_mock.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/mock/distributed_file_daemon_manager_mock.h create mode 100644 datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_corruption_mock.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_corruption_mock.h create mode 100644 datamgr_service/services/distributeddataservice/service/test/mock/preprocess_utils_mock.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/mock/preprocess_utils_mock.h create mode 100644 datamgr_service/services/distributeddataservice/service/test/mock/relational_store_delegate_mock.h create mode 100644 datamgr_service/services/distributeddataservice/service/test/mock/relational_store_manager_mock.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/object_manager_mock_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/ohos_test/BUILD.gn create mode 100644 datamgr_service/services/distributeddataservice/service/test/ohos_test/ohos_test.xml create mode 100644 datamgr_service/services/distributeddataservice/service/test/rdb_service_impl_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/rdb_service_impl_token_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/app.json create mode 100644 datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/resources/base/element/string.json create mode 100644 datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/resources/base/media/app_icon.png create mode 100644 datamgr_service/services/distributeddataservice/service/test/testCloud/BUILD.gn create mode 100644 datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/ets/Application/MyAbilityStage.ts create mode 100644 datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/ets/MainAbility/MainAbility.ts create mode 100644 datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/ets/pages/index.ets create mode 100644 datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/module.json create mode 100644 datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/element/color.json create mode 100644 datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/element/string.json create mode 100644 datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/media/icon.png create mode 100644 datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/profile/main_pages.json create mode 100644 datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/rawfile/arkdata/cloud/cloud_schema.json create mode 100644 datamgr_service/services/distributeddataservice/service/test/testCloud/signature/openharmony_sx.p7b create mode 100644 datamgr_service/services/distributeddataservice/service/test/udmf_db_corruption_mock_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/udmf_preprocess_utils_mock_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/udmf_preprocess_utils_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/test/udmf_service_impl_mock_test.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/udmf/preprocess/udmf_notifier_proxy.cpp create mode 100644 datamgr_service/services/distributeddataservice/service/udmf/preprocess/udmf_notifier_proxy.h delete mode 100644 datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.cpp create mode 100644 interface_sdk/api/@ohos.data.UdmfComponents.d.ets create mode 100644 interface_sdk/api/@ohos.data.graphStore.d.ts create mode 100644 interface_sdk/api/@ohos.data.intelligence.d.ts delete mode 100644 kv_store/databaseutils/test/bool_virtual_test.cpp delete mode 100644 kv_store/databaseutils/test/data_query_virtual_test.cpp delete mode 100644 kv_store/databaseutils/test/datamgr_service_proxy_virtual_test.cpp delete mode 100644 kv_store/databaseutils/test/delegate_mgr_callback_virtual_test.cpp delete mode 100644 kv_store/databaseutils/test/distributed_kv_data_manager_vritual_test.cpp delete mode 100644 kv_store/databaseutils/test/kv_utils_virtual_test.cpp delete mode 100644 kv_store/databaseutils/test/kvdb_notifier_virtual_test.cpp delete mode 100644 kv_store/databaseutils/test/kvstore_datashare_bridge_virtual_test.cpp delete mode 100644 kv_store/databaseutils/test/local_kv_store_counterfeit_unit_test.cpp delete mode 100644 kv_store/databaseutils/test/local_kv_store_sham_test.cpp delete mode 100644 kv_store/databaseutils/test/local_kv_store_sham_unit_test.cpp delete mode 100644 kv_store/databaseutils/test/local_kv_store_virtual_test.cpp delete mode 100644 kv_store/databaseutils/test/local_subscribe_store_sham_test.cpp delete mode 100644 kv_store/databaseutils/test/local_subscribe_store_virtual_test.cpp delete mode 100644 kv_store/databaseutils/test/single_kvstore_client_virtual_test.cpp delete mode 100644 kv_store/databaseutils/test/single_kvstore_query_virtual_test.cpp delete mode 100644 kv_store/databaseutils/test/single_store_impl_sham_test.cpp delete mode 100644 kv_store/databaseutils/test/single_store_impl_virtual_test.cpp create mode 100644 kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/kvstore_client_death_observer.h create mode 100644 kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/switch_observer_bridge.h create mode 100644 kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/switch_observer_bridge.cpp create mode 100644 kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_multi_user_test.cpp create mode 100644 kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/switch_observer_bridge_test.cpp create mode 100644 kv_store/frameworks/innerkitsimpl/kvdb/test/kv_hiview_reporter_test.cpp rename relational_store/interfaces/inner_api/gdb/include/gdb_helper.h => kv_store/frameworks/innerkitsimpl/kvdb/test/mock/include/hisysevent_mock.h (49%) create mode 100644 kv_store/frameworks/innerkitsimpl/kvdb/test/mock/src/hisysevent_mock.cpp create mode 100644 kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_mock_test.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/common/src/db_common_client.cpp delete mode 100644 kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp rename relational_store/frameworks/native/gdb/src/transaction.cpp => kv_store/frameworks/libs/distributeddb/common/src/param_check_utils_client.cpp (57%) create mode 100644 kv_store/frameworks/libs/distributeddb/common/src/schema_utils_client.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/interfaces/src/relational/knowledge_source_utils.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/interfaces/src/relational/knowledge_source_utils.h create mode 100644 kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager_client.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils_client.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils_client.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_client.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend_extend.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/syncer/src/time_helper_client.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_client_test.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator_client.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_client_test.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_relational_store.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_relational_store.h create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_storage_engine.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_storage_engine.h create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distracteddb_kv_multi_user_sync_test.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_abnormal_kv_sync_test.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_compress_test.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_device_sync_test.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distracteddb_rdb_multi_user_sync_test.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_compress_test.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_drop_table_test.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_knowledge_client_test.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_knowledge_test.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_client_test.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/tokenizer/sqlite_adapter_test.cpp delete mode 100644 kv_store/test/fuzztest/distributedkvdataservice_fuzzer/distributedkvdataservice_fuzzer.cpp delete mode 100644 kv_store/test/fuzztest/jsonservice_fuzzer/BUILD.gn delete mode 100644 kv_store/test/fuzztest/jsonservice_fuzzer/jsonservice_fuzzer.cpp delete mode 100644 kv_store/test/fuzztest/kvsync_fuzzer/BUILD.gn delete mode 100644 kv_store/test/fuzztest/kvsync_fuzzer/kvsync_fuzzer.cpp delete mode 100644 kv_store/test/fuzztest/kvsync_fuzzer/project.xml rename kv_store/test/fuzztest/{singlekvstorestub_fuzzer => kvutil_fuzzer}/BUILD.gn (82%) create mode 100644 kv_store/test/fuzztest/kvutil_fuzzer/corpus/init create mode 100644 kv_store/test/fuzztest/kvutil_fuzzer/kvutil_fuzzer.cpp create mode 100644 kv_store/test/fuzztest/kvutil_fuzzer/kvutil_fuzzer.h rename {relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer => kv_store/test/fuzztest/kvutil_fuzzer}/project.xml (95%) delete mode 100644 kv_store/test/fuzztest/singlekvstorestub_fuzzer/singlekvstorestub_fuzzer.cpp create mode 100644 mock/innerkits/filemanagement/dfs_service/frameworks/native/distributed_file_inner/include/file_mount_manager.h create mode 100644 mock/innerkits/hitrace_native/hitrace_meter/include/hitrace_meter_c.h create mode 100644 mock/innerkits/multimedia_image_standard/image_native/include/media_errors.h create mode 100644 mock/innerkits/multimedia_image_standard/image_native/include/modules.h create mode 100644 mock/innerkits/resourceschedule_qos_manager/interfaces/inner_api/concurrent_task_client.h create mode 100644 mock/innerkits/resourceschedule_qos_manager/interfaces/inner_api/concurrent_task_type.h rename relational_store/interfaces/inner_api/gdb/include/edge.h => mock/innerkits/resourceschedule_qos_manager/interfaces/inner_api/qos.h (31%) create mode 100644 mock/innerkits/resourceschedule_qos_manager/interfaces/kits/c/qos.h rename mock/sqlite/patch/{0001-BaselineWithHistoryOH.patch => 0001-History-features-on-OH.patch} (77%) rename mock/sqlite/patch/{0004-Enable-and-optimize-ICU.patch => 0002-Enable-and-optimize-ICU.patch} (92%) rename mock/sqlite/patch/{0002-busy-debug.patch => 0003-Busy-debug-and-log-dump.patch} (42%) rename mock/sqlite/patch/{0003-suport-meta-recovery.patch => 0004-Support-meta-recovery.patch} (89%) rename mock/sqlite/patch/{0005-Report-corruption-when-runtime-decteted.patch => 0005-Enhance-dfx-ability-report-corruption-and-check-page.patch} (54%) delete mode 100644 mock/sqlite/patch/0006-Add-extention-cksumvfs-and-check-page.patch create mode 100644 mock/sqlite/patch/0006-Support-Binlog.patch rename mock/sqlite/patch/{0007-BugFix-CurrVersion.patch => 0007-Bugfix-on-current-version.patch} (76%) rename preferences/frameworks/{js/napi/common/include/napi_preferences_error.h => common/include/preferences_error.h} (100%) rename preferences/frameworks/{js/napi/common/src/napi_preferences_error.cpp => common/src/preferences_error.cpp} (98%) create mode 100644 preferences/frameworks/js/ani/common/include/ani_utils.h create mode 100644 preferences/frameworks/js/ani/common/include/js_ani_ability.h create mode 100644 preferences/frameworks/js/ani/common/src/js_ani_ability.cpp create mode 100644 preferences/frameworks/js/ani/preferences/BUILD.gn create mode 100644 preferences/frameworks/js/ani/preferences/ets/@ohos.data.preferences.ets create mode 100644 preferences/frameworks/js/ani/preferences/src/ani_preferences.cpp create mode 100644 preferences/test/native/fuzztest/dbpreferences_fuzzer/BUILD.gn create mode 100644 preferences/test/native/fuzztest/dbpreferences_fuzzer/corpus/init create mode 100644 preferences/test/native/fuzztest/dbpreferences_fuzzer/dbpreferences_fuzzer.cpp create mode 100644 preferences/test/native/fuzztest/dbpreferences_fuzzer/dbpreferences_fuzzer.h rename {kv_store/test/fuzztest/distributedkvdataservice_fuzzer => preferences/test/native/fuzztest/dbpreferences_fuzzer}/project.xml (95%) create mode 100644 preferences/test/ndk/fuzztest/gskvndkpreferences_fuzzer/BUILD.gn create mode 100644 preferences/test/ndk/fuzztest/gskvndkpreferences_fuzzer/corpus/init create mode 100644 preferences/test/ndk/fuzztest/gskvndkpreferences_fuzzer/gskvndkpreferences_fuzzer.cpp create mode 100644 preferences/test/ndk/fuzztest/gskvndkpreferences_fuzzer/gskvndkpreferences_fuzzer.h rename {kv_store/test/fuzztest/singlekvstorestub_fuzzer => preferences/test/ndk/fuzztest/gskvndkpreferences_fuzzer}/project.xml (95%) create mode 100644 preferences/test/ndk/fuzztest/ndkpreferences_fuzzer/BUILD.gn create mode 100644 preferences/test/ndk/fuzztest/ndkpreferences_fuzzer/corpus/init create mode 100644 preferences/test/ndk/fuzztest/ndkpreferences_fuzzer/ndkpreferences_fuzzer.cpp create mode 100644 preferences/test/ndk/fuzztest/ndkpreferences_fuzzer/ndkpreferences_fuzzer.h rename {relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer => preferences/test/ndk/fuzztest/ndkpreferences_fuzzer}/project.xml (95%) create mode 100644 relational_store/OAT.xml create mode 100644 relational_store/frameworks/common/include/delay_actuator.h rename relational_store/{interfaces/inner_api/gdb => frameworks/js/ani/relationalstore}/BUILD.gn (30%) create mode 100644 relational_store/frameworks/js/ani/relationalstore/ets/@ohos.data.relationalStore.ets create mode 100644 relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_error.h create mode 100644 relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_predicates.h create mode 100644 relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_store.h create mode 100644 relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_store_helper.h create mode 100644 relational_store/frameworks/js/ani/relationalstore/include/ani_result_set.h create mode 100644 relational_store/frameworks/js/ani/relationalstore/include/ani_utils.h create mode 100644 relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_entry.cpp create mode 100644 relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_error.cpp create mode 100644 relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_predicates.cpp create mode 100644 relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_store.cpp create mode 100644 relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_store_helper.cpp create mode 100644 relational_store/frameworks/js/ani/relationalstore/src/ani_result_set.cpp create mode 100644 relational_store/frameworks/js/ani/relationalstore/src/ani_utils.cpp rename relational_store/frameworks/js/napi/{graphstore/include/napi_gdb_const_properties.h => common/mock/include/mock.h} (68%) create mode 100644 relational_store/frameworks/js/napi/common/mock/src/mock.cpp delete mode 100644 relational_store/frameworks/js/napi/dataability/include/napi_async_proxy.h delete mode 100644 relational_store/frameworks/js/napi/graphstore/include/gdb_common.h delete mode 100644 relational_store/frameworks/js/napi/graphstore/include/js_proxy.h delete mode 100644 relational_store/frameworks/js/napi/graphstore/include/napi_async_call.h delete mode 100644 relational_store/frameworks/js/napi/graphstore/include/napi_gdb_context.h delete mode 100644 relational_store/frameworks/js/napi/graphstore/include/napi_gdb_error.h delete mode 100644 relational_store/frameworks/js/napi/graphstore/include/napi_gdb_js_utils.h delete mode 100644 relational_store/frameworks/js/napi/graphstore/include/napi_gdb_store.h delete mode 100644 relational_store/frameworks/js/napi/graphstore/src/napi_async_call.cpp delete mode 100644 relational_store/frameworks/js/napi/graphstore/src/napi_gdb_const_properties.cpp delete mode 100644 relational_store/frameworks/js/napi/graphstore/src/napi_gdb_error.cpp delete mode 100644 relational_store/frameworks/js/napi/graphstore/src/napi_gdb_js_utils.cpp delete mode 100644 relational_store/frameworks/js/napi/graphstore/src/napi_gdb_store.cpp delete mode 100644 relational_store/frameworks/js/napi/graphstore/src/napi_gdb_store_helper.cpp delete mode 100644 relational_store/frameworks/js/napi/graphstore/src/napi_gdb_transaction.cpp delete mode 100644 relational_store/frameworks/js/napi/rdb/src/napi_uv_queue.cpp rename relational_store/frameworks/js/napi/relationalstore/include/{napi_uv_queue.h => napi_rdb_log_observer.h} (50%) create mode 100644 relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_context.cpp create mode 100644 relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_log_observer.cpp delete mode 100644 relational_store/frameworks/js/napi/relationalstore/src/napi_uv_queue.cpp create mode 100644 relational_store/frameworks/native/cloud_data/include/cloud_notifier_stub.h create mode 100644 relational_store/frameworks/native/cloud_data/src/cloud_notifier_stub.cpp create mode 100644 relational_store/frameworks/native/dlopen_rdb/BUILD.gn create mode 100644 relational_store/frameworks/native/dlopen_rdb/dlopen_rdb.cpp rename kv_store/test/fuzztest/singlekvstorestub_fuzzer/singlekvstorestub_fuzzer.h => relational_store/frameworks/native/dlopen_rdb/dlopen_rdb.h (74%) delete mode 100644 relational_store/frameworks/native/gdb/adapter/include/grd_adapter.h delete mode 100644 relational_store/frameworks/native/gdb/adapter/include/grd_adapter_manager.h delete mode 100644 relational_store/frameworks/native/gdb/adapter/src/grd_adapter.cpp delete mode 100644 relational_store/frameworks/native/gdb/adapter/src/grd_adapter_manager.cpp delete mode 100644 relational_store/frameworks/native/gdb/include/connection.h delete mode 100644 relational_store/frameworks/native/gdb/include/connection_pool.h delete mode 100644 relational_store/frameworks/native/gdb/include/db_store_impl.h delete mode 100644 relational_store/frameworks/native/gdb/include/db_store_manager.h delete mode 100644 relational_store/frameworks/native/gdb/include/full_result.h delete mode 100644 relational_store/frameworks/native/gdb/include/gdb_utils.h delete mode 100644 relational_store/frameworks/native/gdb/include/graph_connection.h delete mode 100644 relational_store/frameworks/native/gdb/include/graph_statement.h delete mode 100644 relational_store/frameworks/native/gdb/include/statement.h delete mode 100644 relational_store/frameworks/native/gdb/src/connection.cpp delete mode 100644 relational_store/frameworks/native/gdb/src/connection_pool.cpp delete mode 100644 relational_store/frameworks/native/gdb/src/db_store_impl.cpp delete mode 100644 relational_store/frameworks/native/gdb/src/db_store_manager.cpp delete mode 100644 relational_store/frameworks/native/gdb/src/edge.cpp delete mode 100644 relational_store/frameworks/native/gdb/src/full_result.cpp delete mode 100644 relational_store/frameworks/native/gdb/src/gdb_utils.cpp delete mode 100644 relational_store/frameworks/native/gdb/src/graph_connection.cpp delete mode 100644 relational_store/frameworks/native/gdb/src/graph_statement.cpp delete mode 100644 relational_store/frameworks/native/gdb/src/path.cpp delete mode 100644 relational_store/frameworks/native/gdb/src/path_segment.cpp delete mode 100644 relational_store/frameworks/native/gdb/src/store_config.cpp delete mode 100644 relational_store/frameworks/native/gdb/src/trans_db.cpp delete mode 100644 relational_store/frameworks/native/gdb/src/transaction_impl.cpp delete mode 100644 relational_store/frameworks/native/gdb/src/vertex.cpp create mode 100644 relational_store/frameworks/native/obs_mgr_adapter/BUILD.gn create mode 100644 relational_store/frameworks/native/obs_mgr_adapter/obs_mgr_adapter.cpp create mode 100644 relational_store/frameworks/native/obs_mgr_adapter/obs_mgr_adapter.h create mode 100644 relational_store/frameworks/native/rdb/include/global_resource.h rename relational_store/frameworks/native/{gdb/include/transaction_impl.h => rdb/include/knowledge_schema_helper.h} (38%) create mode 100644 relational_store/frameworks/native/rdb/include/rdb_icu_manager.h create mode 100644 relational_store/frameworks/native/rdb/include/rdb_obs_manager.h create mode 100644 relational_store/frameworks/native/rdb/include/rdb_perfStat.h create mode 100644 relational_store/frameworks/native/rdb/include/rdb_sql_log.h rename relational_store/frameworks/{js/napi/graphstore/include/napi_gdb_transaction.h => native/rdb/include/suspender.h} (33%) delete mode 100644 relational_store/frameworks/native/rdb/mock/include/task_executor.h create mode 100644 relational_store/frameworks/native/rdb/src/global_resource.cpp create mode 100644 relational_store/frameworks/native/rdb/src/knowledge_schema_helper.cpp create mode 100644 relational_store/frameworks/native/rdb/src/rdb_icu_manager.cpp create mode 100644 relational_store/frameworks/native/rdb/src/rdb_obs_manager.cpp create mode 100644 relational_store/frameworks/native/rdb/src/rdb_perfStat.cpp create mode 100644 relational_store/frameworks/native/rdb/src/rdb_sql_log.cpp rename relational_store/frameworks/{js/napi/graphstore/src/entry_point.cpp => native/rdb/src/suspender.cpp} (37%) create mode 100644 relational_store/frameworks/native/rdb_crypt/BUILD.gn create mode 100644 relational_store/frameworks/native/rdb_crypt/relational_store_crypt.cpp create mode 100644 relational_store/frameworks/native/rdb_crypt/relational_store_crypt.h create mode 100644 relational_store/interfaces/inner_api/cloud_data/include/cloud_notifier.h delete mode 100644 relational_store/interfaces/inner_api/gdb/include/gdb_errors.h delete mode 100644 relational_store/interfaces/inner_api/gdb/include/gdb_store.h delete mode 100644 relational_store/interfaces/inner_api/gdb/include/gdb_store_config.h delete mode 100644 relational_store/interfaces/inner_api/gdb/include/path.h delete mode 100644 relational_store/interfaces/inner_api/gdb/include/path_segment.h delete mode 100644 relational_store/interfaces/inner_api/gdb/include/vertex.h create mode 100644 relational_store/interfaces/inner_api/rdb/include/knowledge_types.h rename relational_store/{frameworks/native => interfaces/inner_api}/rdb/include/task_executor.h (79%) rename relational_store/{frameworks/js/napi/graphstore => interfaces/ndk}/BUILD.gn (38%) create mode 100644 relational_store/interfaces/ndk/include/oh_rdb_crypto_param.h create mode 100644 relational_store/interfaces/ndk/relational_store_inner_types.h create mode 100644 relational_store/interfaces/ndk/src/oh_rdb_crypto_param.cpp rename relational_store/interfaces/{ndk/src => rdb_ndk_utils}/BUILD.gn (65%) create mode 100644 relational_store/interfaces/rdb_ndk_utils/include/rdb_ndk_utils.h create mode 100644 relational_store/interfaces/rdb_ndk_utils/src/rdb_ndk_utils.cpp rename relational_store/rdbmock/frameworks/native/rdb/{ => common}/concurrent_map.h (100%) create mode 100644 relational_store/test/ets/cloud_data/AppScope/app.json create mode 100644 relational_store/test/ets/cloud_data/AppScope/resources/base/element/string.json create mode 100644 relational_store/test/ets/cloud_data/BUILD.gn create mode 100644 relational_store/test/ets/cloud_data/Test.json create mode 100644 relational_store/test/ets/cloud_data/entry/src/main/ets/Application/AbilityStage.ts create mode 100644 relational_store/test/ets/cloud_data/entry/src/main/ets/MainAbility/MainAbility.ts create mode 100644 relational_store/test/ets/cloud_data/entry/src/main/ets/MainAbility/pages/index/index.ets create mode 100644 relational_store/test/ets/cloud_data/entry/src/main/ets/TestAbility/TestAbility.ts create mode 100644 relational_store/test/ets/cloud_data/entry/src/main/ets/TestAbility/pages/index.ets create mode 100644 relational_store/test/ets/cloud_data/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts create mode 100644 relational_store/test/ets/cloud_data/entry/src/main/ets/test/CloudConfigEtsTest.test.ets create mode 100644 relational_store/test/ets/cloud_data/entry/src/main/ets/test/List.test.ets create mode 100644 relational_store/test/ets/cloud_data/entry/src/main/module.json create mode 100644 relational_store/test/ets/cloud_data/entry/src/main/resources/base/element/string.json create mode 100644 relational_store/test/ets/cloud_data/entry/src/main/resources/base/media/icon.png create mode 100644 relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/form_config.json create mode 100644 relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/form_config1.txt create mode 100644 relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/invalid.txt create mode 100644 relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/main_pages.json create mode 100644 relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/shortcuts_config.json rename relational_store/test/{js/gdb/performance => ets/cloud_data/signature}/openharmony_sx.p7b (50%) create mode 100644 relational_store/test/ets/relational_store/AppScope/app.json create mode 100644 relational_store/test/ets/relational_store/AppScope/resources/base/element/string.json create mode 100644 relational_store/test/ets/relational_store/BUILD.gn create mode 100644 relational_store/test/ets/relational_store/Test.json create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/Application/AbilityStage.ts create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/MainAbility/MainAbility.ts create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/MainAbility/pages/index/index.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/TestAbility/TestAbility.ts create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/TestAbility/pages/index.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/List.test.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbGroupIdEts.test.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbOnErrorLog.test.ets rename relational_store/test/{js/gdb/performance/src/GdbHelperPromisePerf.js => ets/relational_store/entry/src/main/ets/test/RdbPredicatesPerfEts.test.ets} (30%) create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreExecuteSql.test.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransInsertJsunit.test.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransJsunit.test.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransaction.test.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreCustomTokenizerEts.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetRowForFlutterEts.test.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetSqlInfoEts.test.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetValueForFlutterEts.test.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstorePerfStatEts.test.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstorePredicatesEts.test.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreRekeyEts.test.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreSetLocaleEts.test.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreTransactionJsunit.test.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/ets/test/RelationalStoreEtsTest.test.ets create mode 100644 relational_store/test/ets/relational_store/entry/src/main/module.json create mode 100644 relational_store/test/ets/relational_store/entry/src/main/resources/base/element/string.json create mode 100644 relational_store/test/ets/relational_store/entry/src/main/resources/base/media/icon.png create mode 100644 relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/form_config.json create mode 100644 relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/form_config1.txt create mode 100644 relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/invalid.txt create mode 100644 relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/main_pages.json create mode 100644 relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/shortcuts_config.json rename relational_store/test/{js/gdb/unittest => ets/relational_store/signature}/openharmony_sx.p7b (50%) delete mode 100644 relational_store/test/js/gdb/performance/src/GdbStorePromisePerf.js delete mode 100644 relational_store/test/js/gdb/unittest/config.json delete mode 100644 relational_store/test/js/gdb/unittest/src/GdbStoreGdbStoreJsunit.test.js delete mode 100644 relational_store/test/js/gdb/unittest/src/GdbStoreReadWriteJsunit.test.js delete mode 100644 relational_store/test/js/relationalstore/unittest/src/RdbStoreTransInsertJsunit.test.js delete mode 100644 relational_store/test/js/relationalstore/unittest/src/RdbStoreTransJsunit.test.js delete mode 100644 relational_store/test/js/relationalstore/unittest/src/RdbStoreTransaction.test.js delete mode 100644 relational_store/test/js/relationalstore/unittest/src/RdbstoreTransactionJsunit.test.js create mode 100644 relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/BUILD.gn rename relational_store/test/native/{gdb/fuzztest/gdbstore_fuzzer/gdbstore_fuzzer.cpp => clouddata/fuzztest/cloudnotifierstub_fuzzer/cloudnotifierstub_fuzzer.cpp} (40%) create mode 100644 relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/cloudnotifierstub_fuzzer.h create mode 100644 relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/corpus/init create mode 100644 relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/project.xml delete mode 100644 relational_store/test/native/gdb/BUILD.gn delete mode 100644 relational_store/test/native/gdb/mock/grd_adapter.cpp delete mode 100644 relational_store/test/native/gdb/mock/grd_adapter.h delete mode 100644 relational_store/test/native/gdb/unittest/gdb_adapt_test.cpp delete mode 100644 relational_store/test/native/gdb/unittest/gdb_encrypt_test.cpp delete mode 100644 relational_store/test/native/gdb/unittest/gdb_execute_test.cpp delete mode 100644 relational_store/test/native/gdb/unittest/gdb_function_test.cpp delete mode 100644 relational_store/test/native/gdb/unittest/gdb_grd_adapter_test.cpp delete mode 100644 relational_store/test/native/gdb/unittest/gdb_grdapi_test.cpp delete mode 100644 relational_store/test/native/gdb/unittest/gdb_multi_thread_test.cpp delete mode 100644 relational_store/test/native/gdb/unittest/gdb_query_test.cpp delete mode 100644 relational_store/test/native/gdb/unittest/gdb_transaction_test.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/abspredicates_fuzzer.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/abspredicates_fuzzer.h rename relational_store/test/native/rdb/fuzztest/{rdbrdutils_fuzzer/rddbopen_fuzzer => abspredicates_fuzzer}/corpus/init (92%) create mode 100644 relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/absrdbpredicates_fuzzer.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/absrdbpredicates_fuzzer.h rename {kv_store/test/fuzztest/jsonservice_fuzzer => relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer}/corpus/init (92%) create mode 100644 relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/absresultset_fuzzer.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/absresultset_fuzzer.h rename {kv_store/test/fuzztest/kvsync_fuzzer => relational_store/test/native/rdb/fuzztest/absresultset_fuzzer}/corpus/init (92%) create mode 100644 relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/abssharedresultset_fuzzer.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/abssharedresultset_fuzzer.h rename relational_store/test/native/{gdb/fuzztest/gdbstore_fuzzer => rdb/fuzztest/abssharedresultset_fuzzer}/corpus/init (92%) create mode 100644 relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/big_integer_test_ut2fuzz.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/big_integer_test_ut2fuzz.h create mode 100644 relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/cache_result_set_test_ut2fuzz.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/cache_result_set_test_ut2fuzz.h create mode 100644 relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/project.xml rename relational_store/test/native/rdb/fuzztest/{rdbrdutils_fuzzer/rddbrepair_fuzzer => cloud_data_test_ut2fuzz}/BUILD.gn (49%) create mode 100644 relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/cloud_data_test_ut2fuzz.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/cloud_data_test_ut2fuzz.h create mode 100644 relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/BUILD.gn rename relational_store/test/native/rdb/fuzztest/{rdbrdutils_fuzzer/transfergrderrno_fuzzer/transfergrderrno_fuzzer.cpp => connection_test_ut2fuzz/connection_test_ut2fuzz.cpp} (50%) create mode 100644 relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/connection_test_ut2fuzz.h create mode 100644 relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/project.xml rename relational_store/test/native/{gdb/fuzztest/gdbstore_fuzzer => rdb/fuzztest/rdb_attach_test_ut2fuzz}/BUILD.gn (69%) create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/rdb_attach_test_ut2fuzz.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/rdb_attach_test_ut2fuzz.h create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/rdb_bigint_test_ut2fuzz.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/rdb_bigint_test_ut2fuzz.h create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/rdb_callback_icu_test_ut2fuzz.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/rdb_callback_icu_test_ut2fuzz.h create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/rdb_corrupt_test_ut2fuzz.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/rdb_corrupt_test_ut2fuzz.h rename {kv_store/test/fuzztest/distributedkvdataservice_fuzzer => relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz}/BUILD.gn (63%) create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/rdb_delete_test_ut2fuzz.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/rdb_delete_test_ut2fuzz.h create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/rdb_distributed_test_ut2fuzz.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/rdb_distributed_test_ut2fuzz.h create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/rdb_double_write_test_ut2fuzz.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/rdb_double_write_test_ut2fuzz.h create mode 100644 relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/rdbhelper_fuzzer.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/rdbhelper_fuzzer.h create mode 100644 relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/rdbpredicates_fuzzer.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/rdbpredicates_fuzzer.h create mode 100644 relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rdbrdutils_fuzzer.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rdbrdutils_fuzzer.h delete mode 100644 relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/rddbopen_fuzzer.cpp delete mode 100644 relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/BUILD.gn delete mode 100644 relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/corpus/init delete mode 100644 relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/project.xml delete mode 100644 relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/transfergrderrno_fuzzer.h delete mode 100644 relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/BUILD.gn delete mode 100644 relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/project.xml delete mode 100644 relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/transfergrdtypetocoltype_fuzzer.h create mode 100644 relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/rdbsqlutils_fuzzer.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/rdbsqlutils_fuzzer.h create mode 100644 relational_store/test/native/rdb/fuzztest/returning_fuzzer/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/returning_fuzzer/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/returning_fuzzer/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/returning_fuzzer/returning_fuzzer.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/returning_fuzzer/returning_fuzzer.h rename relational_store/test/native/rdb/fuzztest/{rdbrdutils_fuzzer/rddbopen_fuzzer => sharedblock_fuzzer}/BUILD.gn (50%) create mode 100644 relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/sharedblock_fuzzer.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/sharedblock_fuzzer.h create mode 100644 relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/storeconfig_fuzzer.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/storeconfig_fuzzer.h create mode 100644 relational_store/test/native/rdb/fuzztest/transaction_fuzzer/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/transaction_fuzzer/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/transaction_fuzzer/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/transaction_fuzzer/transaction_fuzzer.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/transaction_fuzzer/transaction_fuzzer.h create mode 100644 relational_store/test/native/rdb/fuzztest/transdb_fuzzer/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/transdb_fuzzer/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/transdb_fuzzer/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/transdb_fuzzer/transdb_fuzzer.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/transdb_fuzzer/transdb_fuzzer.h create mode 100644 relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/valueobject_fuzzer.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/valueobject_fuzzer.h create mode 100644 relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/valuesbucket_fuzzer.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/valuesbucket_fuzzer.h create mode 100644 relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/BUILD.gn create mode 100644 relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/corpus/init create mode 100644 relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/project.xml create mode 100644 relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/valuesbuckets_fuzzer.cpp create mode 100644 relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/valuesbuckets_fuzzer.h create mode 100644 relational_store/test/native/rdb/mock/connection_mock.h create mode 100644 relational_store/test/native/rdb/mock/dataobs_mgr_client_mock.cpp rename relational_store/{frameworks/native/rdb_device_manager_adapter/include/rdb_device_manager_adapter.h => test/native/rdb/mock/dataobs_mgr_client_mock.h} (42%) create mode 100644 relational_store/test/native/rdb/mock/rdb_manager_impl_mock.cpp create mode 100644 relational_store/test/native/rdb/mock/rdb_manager_impl_mock.h create mode 100644 relational_store/test/native/rdb/mock/rdb_service_mock.h create mode 100644 relational_store/test/native/rdb/mock/statement_mock.h create mode 100644 relational_store/test/native/rdb/unittest/delay_actuator_test.cpp create mode 100644 relational_store/test/native/rdb/unittest/delay_notify_test.cpp create mode 100644 relational_store/test/native/rdb/unittest/dynamic_load_test/BUILD.gn create mode 100644 relational_store/test/native/rdb/unittest/dynamic_load_test/dynamic_load_test.cpp create mode 100644 relational_store/test/native/rdb/unittest/mock_obs_manage_test/BUILD.gn create mode 100644 relational_store/test/native/rdb/unittest/mock_obs_manage_test/global_resource_test.cpp create mode 100644 relational_store/test/native/rdb/unittest/mock_obs_manage_test/mock_global_resource.cpp create mode 100644 relational_store/test/native/rdb/unittest/mock_obs_manage_test/mock_global_resource.h create mode 100644 relational_store/test/native/rdb/unittest/mockservice/BUILD.gn create mode 100644 relational_store/test/native/rdb/unittest/mockservice/rdb_store_impl_test.cpp create mode 100644 relational_store/test/native/rdb/unittest/rdb_callback_icu_test.cpp create mode 100644 relational_store/test/native/rdb/unittest/rdb_concurrent_querywithcurd_test.cpp create mode 100644 relational_store/test/native/rdb/unittest/rdb_double_write_binlog_test.cpp create mode 100644 relational_store/test/native/rdb/unittest/rdb_encrypt_upgrade_test.cpp create mode 100644 relational_store/test/native/rdb/unittest/rdb_error_log_test/get_rdb_store_test.cpp create mode 100644 relational_store/test/native/rdb/unittest/rdb_error_log_test/rdb_error_log_test.cpp create mode 100644 relational_store/test/native/rdb/unittest/rdb_error_log_test/rdb_perfStat_test.cpp create mode 100644 relational_store/test/native/rdb/unittest/rdb_service_proxy_test.cpp create mode 100644 relational_store/test/native/rdb/unittest/sqlite_statement_test/BUILD.gn create mode 100644 relational_store/test/native/rdb/unittest/sqlite_statement_test/mock_shared_block_test.cpp create mode 100644 relational_store/test/native/rdb/unittest/sqlite_statement_test/sqlite_statement_test.cpp create mode 100644 relational_store/test/ndk/fuzztest/dataasset_fuzzer/BUILD.gn create mode 100644 relational_store/test/ndk/fuzztest/dataasset_fuzzer/corpus/init create mode 100644 relational_store/test/ndk/fuzztest/dataasset_fuzzer/dataasset_fuzzer.cpp create mode 100644 relational_store/test/ndk/fuzztest/dataasset_fuzzer/dataasset_fuzzer.h create mode 100644 relational_store/test/ndk/fuzztest/dataasset_fuzzer/project.xml create mode 100644 relational_store/test/ndk/fuzztest/datavalue_fuzzer/BUILD.gn create mode 100644 relational_store/test/ndk/fuzztest/datavalue_fuzzer/corpus/init create mode 100644 relational_store/test/ndk/fuzztest/datavalue_fuzzer/datavalue_fuzzer.cpp create mode 100644 relational_store/test/ndk/fuzztest/datavalue_fuzzer/datavalue_fuzzer.h create mode 100644 relational_store/test/ndk/fuzztest/datavalue_fuzzer/project.xml create mode 100644 relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/BUILD.gn create mode 100644 relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/corpus/init create mode 100644 relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/oh_cursor_fuzzer.cpp create mode 100644 relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/oh_cursor_fuzzer.h create mode 100644 relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/project.xml create mode 100644 relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/BUILD.gn create mode 100644 relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/corpus/init create mode 100644 relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/oh_data_value_fuzzer.cpp create mode 100644 relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/oh_data_value_fuzzer.h create mode 100644 relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/project.xml create mode 100644 relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/BUILD.gn create mode 100644 relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/corpus/init create mode 100644 relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/oh_data_values_buckets_fuzzer.cpp create mode 100644 relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/oh_data_values_buckets_fuzzer.h create mode 100644 relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/project.xml create mode 100644 relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/BUILD.gn create mode 100644 relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/corpus/init create mode 100644 relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/oh_data_values_fuzzer.cpp create mode 100644 relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/oh_data_values_fuzzer.h create mode 100644 relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/project.xml create mode 100644 relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/BUILD.gn create mode 100644 relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/corpus/init create mode 100644 relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/oh_predicates_fuzzer.cpp create mode 100644 relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/oh_predicates_fuzzer.h create mode 100644 relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/project.xml create mode 100644 relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/BUILD.gn create mode 100644 relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/corpus/init create mode 100644 relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/oh_rdb_crypto_param_fuzzer.cpp create mode 100644 relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/oh_rdb_crypto_param_fuzzer.h create mode 100644 relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/project.xml create mode 100644 relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/BUILD.gn create mode 100644 relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/corpus/init create mode 100644 relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/ohpredicates_fuzzer.cpp create mode 100644 relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/ohpredicates_fuzzer.h create mode 100644 relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/project.xml create mode 100644 relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/BUILD.gn create mode 100644 relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/corpus/init create mode 100644 relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/ohrdbtransaction_fuzzer.cpp create mode 100644 relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/ohrdbtransaction_fuzzer.h create mode 100644 relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/project.xml create mode 100644 relational_store/test/ndk/fuzztest/relationalstore_fuzzer/BUILD.gn create mode 100644 relational_store/test/ndk/fuzztest/relationalstore_fuzzer/corpus/init create mode 100644 relational_store/test/ndk/fuzztest/relationalstore_fuzzer/project.xml create mode 100644 relational_store/test/ndk/fuzztest/relationalstore_fuzzer/relationalstore_fuzzer.cpp create mode 100644 relational_store/test/ndk/fuzztest/relationalstore_fuzzer/relationalstore_fuzzer.h create mode 100644 relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/BUILD.gn create mode 100644 relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/corpus/init create mode 100644 relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/project.xml create mode 100644 relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/relationalstorecapi_fuzzer.cpp create mode 100644 relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/relationalstorecapi_fuzzer.h create mode 100644 relational_store/test/ndk/fuzztest/valuebucket_fuzzer/BUILD.gn create mode 100644 relational_store/test/ndk/fuzztest/valuebucket_fuzzer/corpus/init create mode 100644 relational_store/test/ndk/fuzztest/valuebucket_fuzzer/project.xml create mode 100644 relational_store/test/ndk/fuzztest/valuebucket_fuzzer/valuebucket_fuzzer.cpp create mode 100644 relational_store/test/ndk/fuzztest/valuebucket_fuzzer/valuebucket_fuzzer.h create mode 100644 relational_store/test/ndk/fuzztest/valueobject_fuzzer/BUILD.gn create mode 100644 relational_store/test/ndk/fuzztest/valueobject_fuzzer/corpus/init create mode 100644 relational_store/test/ndk/fuzztest/valueobject_fuzzer/project.xml create mode 100644 relational_store/test/ndk/fuzztest/valueobject_fuzzer/valueobject_fuzzer.cpp create mode 100644 relational_store/test/ndk/fuzztest/valueobject_fuzzer/valueobject_fuzzer.h create mode 100644 relational_store/test/ndk/unittest/rdb_crypto_param_test.cpp create mode 100644 relational_store/test/ndk/unittest/rdb_performance_test.cpp create mode 100644 relational_store/test/ndk/unittest/rdb_predicates_pref_test.cpp create mode 100644 udmf/adapter/framework/innerkitsimpl/client/preset_type_descriptors.cpp create mode 100644 udmf/conf/BUILD.gn create mode 100644 udmf/conf/uniform_data_types.json create mode 100644 udmf/framework/common/concurrent_map.h create mode 100644 udmf/framework/common/itypes_util.h create mode 100644 udmf/framework/common/udmf_executor.cpp create mode 100644 udmf/framework/common/udmf_executor.h create mode 100644 udmf/framework/common/unittest/mock/file_copy_manager_mock.cpp create mode 100644 udmf/framework/common/unittest/mock/message_parcel_mock.cpp create mode 100644 udmf/framework/common/unittest/mock/message_parcel_mock.h create mode 100644 udmf/framework/common/unittest/udmf_copy_file_test.cpp create mode 100644 udmf/framework/common/unittest/udmf_types_util_mock_test.cpp create mode 100644 udmf/framework/innerkitsimpl/dynamic/pixelmap_loader.cpp create mode 100644 udmf/framework/innerkitsimpl/dynamic/pixelmap_wrapper.cpp rename datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.h => udmf/framework/innerkitsimpl/service/iudmf_notifier.h (50%) create mode 100644 udmf/framework/innerkitsimpl/service/udmf_notifier_stub.cpp rename relational_store/interfaces/inner_api/gdb/include/gdb_transaction.h => udmf/framework/innerkitsimpl/service/udmf_notifier_stub.h (32%) create mode 100644 udmf/framework/innerkitsimpl/test/unittest/preset_type_descriptor_test.cpp create mode 100644 udmf/framework/innerkitsimpl/test/unittest/udmf_client_file_manger_test.cpp create mode 100644 udmf/framework/innerkitsimpl/test/unittest/udmf_delay_data_test.cpp create mode 100644 udmf/framework/innerkitsimpl/test/unittest/unified_key_test.cpp create mode 100644 udmf/framework/innerkitsimpl/test/unittest/utd_concurrent_update_test.cpp create mode 100644 udmf/framework/jskitsimpl/data/data_load_params_napi.cpp create mode 100644 udmf/framework/jskitsimpl/intelligence/native_module_rag.cpp create mode 100644 udmf/framework/jskitsimpl/intelligence/rag_agent_chatllm_napi.cpp create mode 100644 udmf/framework/jskitsimpl/intelligence/rag_chatllm_impl.cpp create mode 100644 udmf/framework/jskitsimpl/intelligence/rag_session_napi.cpp delete mode 100644 udmf/framework/jskitsimpl/intelligence/retrieval_napi.cpp rename {relational_store/test/js/gdb/performance/src => udmf/framework/jskitsimpl/test}/BUILD.gn (68%) create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/AppScope/app.json create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/AppScope/resources/base/element/string.json create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/BUILD.gn create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/Test.json create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/Application/AbilityStage.ts create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/MainAbility.ts create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/pages/index/index.ets create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/pages/second/second.ets create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestAbility/TestAbility.ts create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestAbility/pages/index.ets create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/List.test.ets create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfCallBacktest.ets create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfFileMangertest.ets create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfPromisetest.ets rename relational_store/test/js/gdb/performance/config.json => udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/module.json (34%) create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/element/string.json create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/form_config.json create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/form_config1.txt create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/main_pages.json create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/shortcuts_config.json create mode 100644 udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/signature/openharmony_sx.p7b delete mode 100644 udmf/framework/jskitsimpl/unittest/AipRdbJsTest.js create mode 100644 udmf/framework/jskitsimpl/unittest/UdmfIntelligenceJsTest.js create mode 100644 udmf/framework/ndkimpl/udmf_fuzzer/BUILD.gn rename kv_store/test/fuzztest/kvsync_fuzzer/kvsync_fuzzer.h => udmf/framework/ndkimpl/udmf_fuzzer/corpus/init (83%) create mode 100644 udmf/framework/ndkimpl/udmf_fuzzer/project.xml create mode 100644 udmf/framework/ndkimpl/udmf_fuzzer/udmf_fuzzer.cpp rename relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/gdbstore_fuzzer.h => udmf/framework/ndkimpl/udmf_fuzzer/udmf_fuzzer.h (76%) create mode 100644 udmf/interfaces/ani/BUILD.gn create mode 100644 udmf/interfaces/ani/ets/@ohos.data.unifiedDataChannel.ets create mode 100644 udmf/interfaces/ani/ets/@ohos.data.uniformTypeDescriptor.ets create mode 100644 udmf/interfaces/ani/native/include/ani_util_class.h create mode 100644 udmf/interfaces/ani/native/include/ani_util_common.h create mode 100644 udmf/interfaces/ani/native/include/ani_util_native_ptr.h create mode 100644 udmf/interfaces/ani/native/include/ani_utils.h rename relational_store/frameworks/native/gdb/include/trans_db.h => udmf/interfaces/ani/native/include/unifieddatachannel_ani.h (43%) create mode 100644 udmf/interfaces/ani/native/src/unifieddatachannel_ani.cpp create mode 100644 udmf/interfaces/ani/native/src/uniformTypeDescriptor_ani.cpp rename relational_store/frameworks/js/napi/graphstore/include/napi_gdb_store_helper.h => udmf/interfaces/cj/include/unified_data_parameter_parse.h (54%) create mode 100644 udmf/interfaces/cj/src/unified_data_channel_ffi.cpp create mode 100644 udmf/interfaces/cj/src/unified_data_parameter_parse.cpp create mode 100644 udmf/interfaces/innerkits/aipcore/BUILD.gn rename udmf/interfaces/{jskits/intelligence => innerkits/aipcore}/i_aip_core_manager.h (84%) create mode 100644 udmf/interfaces/innerkits/dynamic/pixelmap_loader.h create mode 100644 udmf/interfaces/innerkits/dynamic/pixelmap_wrapper.h rename relational_store/frameworks/js/napi/rdb/include/napi_uv_queue.h => udmf/interfaces/jskits/data/data_load_params_napi.h (44%) rename {relational_store/frameworks/native/gdb/include => udmf/interfaces/jskits/intelligence}/hitrace.h (71%) rename relational_store/frameworks/native/gdb/include/db_trace.h => udmf/interfaces/jskits/intelligence/napi_trace.h (70%) create mode 100644 udmf/interfaces/jskits/intelligence/native_module_rag.h rename preferences/frameworks/native/include/hitrace.h => udmf/interfaces/jskits/intelligence/rag_agent_chatllm_napi.h (55%) create mode 100644 udmf/interfaces/jskits/intelligence/rag_chatllm_impl.h rename udmf/interfaces/jskits/intelligence/{retrieval_napi.h => rag_session_napi.h} (31%) diff --git a/data_object/bundle.json b/data_object/bundle.json index 5af3608a..ff06c9e8 100644 --- a/data_object/bundle.json +++ b/data_object/bundle.json @@ -3,9 +3,9 @@ "version": "3.1.0", "description": "The distributed data object management framework is an object-oriented in-memory data management framework", "homePage": "https://gitee.com/openharmony", - "license": "Apache V2", - "repository": "https://gitee.com/openharmony/distributeddatamgr_data_object ", - "domain": "ohos", + "license": "Apache-2.0", + "repository": "https://gitee.com/openharmony/distributeddatamgr_data_object", + "domain": "os", "language": "", "publishAs": "code-segment", "private": false, @@ -61,12 +61,14 @@ "dmsfwk", "hisysevent" ], - "third_party": [] + "third_party": [ + "ffmpeg", + "libexif" + ] }, "build": { "sub_component": [ - "//foundation/distributeddatamgr/data_object/interfaces/jskits:build_module", - "//foundation/distributeddatamgr/data_object/frameworks/jskitsimpl/collaboration_edit:collaborationeditobject" + "//foundation/distributeddatamgr/data_object/interfaces/jskits:build_module" ], "inner_kits": [ { diff --git a/data_object/frameworks/innerkitsimpl/collaboration_edit/include/cloud_db_proxy.h b/data_object/frameworks/innerkitsimpl/collaboration_edit/include/cloud_db_proxy.h index 20a378e9..db878ba4 100644 --- a/data_object/frameworks/innerkitsimpl/collaboration_edit/include/cloud_db_proxy.h +++ b/data_object/frameworks/innerkitsimpl/collaboration_edit/include/cloud_db_proxy.h @@ -26,7 +26,7 @@ typedef struct ExtendRecordField { GRD_CloudFieldTypeE type; std::string fieldName; std::string fieldValue_str; - const void *valuePtr; + const void *valuePtr = nullptr; uint32_t valueLen; } ExtendRecordFieldT; @@ -34,6 +34,7 @@ typedef void (*ExtendFieldParser)(CloudParamsAdapterT &extend, ExtendRecordField class CloudDbProxy { public: + ~CloudDbProxy(); static int32_t BatchInsert(void *cloudDB, GRD_CloudParamsT *cloudParams); static int32_t Query(void *cloudDB, GRD_CloudParamsT *cloudParams); static int32_t DownloadAsset(void *cloudDB, const char *equipId, char *path); @@ -63,8 +64,9 @@ private: static int32_t ParseExtendField(CloudParamsAdapterT &extend, uint32_t index, GRD_CloudRecordT *records, uint32_t maxRecordSize); static void FreeExtendFields(GRD_CloudFieldT *fields, uint8_t fieldSize); + static int64_t GetCursorValue(GRD_CloudFieldT &field); - NapiCloudDb *napiCloudDb_; + NapiCloudDb *napiCloudDb_ = nullptr; }; } // namespace OHOS::CollaborationEdit #endif // COLLABORATION_EDIT_CLOUD_DB_PROXY_H diff --git a/data_object/frameworks/innerkitsimpl/collaboration_edit/include/db_store.h b/data_object/frameworks/innerkitsimpl/collaboration_edit/include/db_store.h index 0c1e798d..c199a592 100644 --- a/data_object/frameworks/innerkitsimpl/collaboration_edit/include/db_store.h +++ b/data_object/frameworks/innerkitsimpl/collaboration_edit/include/db_store.h @@ -16,6 +16,7 @@ #ifndef COLLABORATION_EDIT_DB_STORE_H #define COLLABORATION_EDIT_DB_STORE_H +#include "cloud_db_proxy.h" #include "db_store_config.h" #include "grd_type_export.h" @@ -33,10 +34,15 @@ public: int WriteUpdate(const char *equipId, const uint8_t *data, uint32_t size, const std::string &watermark); int GetRelativePos(const char *tableName, const char *nodeSize, uint32_t pos, std::string &relPos); int GetAbsolutePos(const char *tableName, const char *relPos, const char *nodeSize, uint32_t *pos); + void SetCloudDbProxy(CloudDbProxy* proxy, GRD_ICloudDBT *cloudDB); + GRD_ICloudDBT *GetCloudDB(); + void FreeCloudDB(); private: - GRD_DB *db_; + GRD_DB *db_ = nullptr; std::string name_; std::shared_ptr localId_; + CloudDbProxy* proxy_ = nullptr; + GRD_ICloudDBT *cloudDB_ = nullptr; }; } // namespace OHOS::CollaborationEdit #endif // COLLABORATION_EDIT_DB_STORE_H diff --git a/data_object/frameworks/innerkitsimpl/collaboration_edit/src/cloud_db_proxy.cpp b/data_object/frameworks/innerkitsimpl/collaboration_edit/src/cloud_db_proxy.cpp index 0da7cca9..f2670706 100644 --- a/data_object/frameworks/innerkitsimpl/collaboration_edit/src/cloud_db_proxy.cpp +++ b/data_object/frameworks/innerkitsimpl/collaboration_edit/src/cloud_db_proxy.cpp @@ -43,6 +43,8 @@ const std::string CURSOR = "cursor"; const std::string SYNC_LOG_EVENT = "syncLogEvent"; const std::string TIMESTAMP = "timestamp"; +constexpr int CURSOR_BASE = 10; + static const std::map PREDICATE_MAP = { {GRD_QUERY_CONDITION_TYPE_EQUAL_TO, EQUAL_TO}, {GRD_QUERY_CONDITION_TYPE_NOT_EQUAL_TO, NOT_EQUAL_TO}, @@ -59,6 +61,14 @@ static const std::map QRY_RSP_PARSER_MAP = { {QRY_RSP_CURSOR_IDX, CloudDbProxy::CursorParseFunc} }; +CloudDbProxy::~CloudDbProxy() +{ + if (napiCloudDb_ != nullptr) { + delete napiCloudDb_; + napiCloudDb_ = nullptr; + } +} + void CloudDbProxy::SetNapiCloudDb(NapiCloudDb *napiCloudDb) { napiCloudDb_ = napiCloudDb; @@ -254,14 +264,11 @@ int32_t CloudDbProxy::GetQueryParams(GRD_CloudParamsT *cloudParams, std::vector< queryConditions.push_back(condition); continue; } - std::string tmpString; - tmpString.resize(field.valueLen); - errno_t errNo = memcpy_s(&tmpString[0], field.valueLen, field.value, field.valueLen); - if (errNo != EOK) { - LOG_ERROR("copy cursor value wrong"); - return E_MEMORY_OPERATION_ERROR; + condition.fieldValue_num = GetCursorValue(field); + if (condition.fieldValue_num < 0) { + queryConditions.clear(); + return E_INVALID_ARGS; } - condition.fieldValue_num = std::stoi(tmpString); } else if (condition.fieldName == EQUIP_ID) { condition.fieldValue_str = std::string(static_cast(field.value)); } else { @@ -274,6 +281,33 @@ int32_t CloudDbProxy::GetQueryParams(GRD_CloudParamsT *cloudParams, std::vector< return E_OK; } +int64_t CloudDbProxy::GetCursorValue(GRD_CloudFieldT &field) +{ + int64_t cursor = -1; + if (field.value == nullptr) { + LOG_ERROR("field value is null"); + return cursor; + } + std::string tmpString; + tmpString.resize(field.valueLen); + errno_t errNo = memcpy_s(&tmpString[0], field.valueLen, field.value, field.valueLen); + if (errNo != EOK) { + LOG_ERROR("copy cursor value wrong"); + return cursor; + } + errno = 0; + cursor = std::strtol(tmpString.c_str(), nullptr, CURSOR_BASE); + if (errno == EINVAL) { + LOG_ERROR("cursor field is not integer"); + cursor = -1; + } + if (errno == ERANGE) { + LOG_ERROR("cursor is too long"); + cursor = -1; + } + return cursor; +} + void CloudDbProxy::CursorParseFunc(CloudParamsAdapterT &extend, ExtendRecordFieldT &destField) { destField.type = GRD_CLOUD_FIELD_TYPE_STRING; diff --git a/data_object/frameworks/innerkitsimpl/collaboration_edit/src/db_store.cpp b/data_object/frameworks/innerkitsimpl/collaboration_edit/src/db_store.cpp index 7e9dde5c..ad5327b4 100644 --- a/data_object/frameworks/innerkitsimpl/collaboration_edit/src/db_store.cpp +++ b/data_object/frameworks/innerkitsimpl/collaboration_edit/src/db_store.cpp @@ -36,6 +36,19 @@ DBStore::DBStore(GRD_DB *db, std::string name) : db_(db), name_(name) DBStore::~DBStore() {} +void DBStore::FreeCloudDB() +{ + if (cloudDB_ != nullptr) { + free(cloudDB_->assetLoader); + free(cloudDB_); + cloudDB_ = nullptr; + } + if (proxy_ != nullptr) { + delete proxy_; + proxy_ = nullptr; + } +} + std::string DBStore::GetLocalId() { if (localId_) { @@ -95,6 +108,17 @@ GRD_DB *DBStore::GetDB() return db_; } +GRD_ICloudDBT* DBStore::GetCloudDB() +{ + return cloudDB_; +} + +void DBStore::SetCloudDbProxy(CloudDbProxy *proxy, GRD_ICloudDBT *cloudDB) +{ + proxy_ = proxy; + cloudDB_ = cloudDB; +} + int DBStore::ApplyUpdate(std::string &applyInfo) { char *retStr = nullptr; diff --git a/data_object/frameworks/innerkitsimpl/collaboration_edit/src/db_store_manager.cpp b/data_object/frameworks/innerkitsimpl/collaboration_edit/src/db_store_manager.cpp index 3cd0e16b..955be6fc 100644 --- a/data_object/frameworks/innerkitsimpl/collaboration_edit/src/db_store_manager.cpp +++ b/data_object/frameworks/innerkitsimpl/collaboration_edit/src/db_store_manager.cpp @@ -109,6 +109,7 @@ int DBStoreManager::DeleteDBStore(const DBStoreConfig &config) LOG_ERROR("[DeleteDBStore] db close go wrong, err = %{public}d", errCode); return -1; } + dbStorePtr->FreeCloudDB(); } int ret = RemoveDir(dbPath.c_str()); if (ret != 0) { @@ -204,6 +205,7 @@ int DBStoreManager::SetCloudDb(std::shared_ptr dbStore, NapiCloudDb *na delete cloudDbProxy; return -1; } + dbStore->SetCloudDbProxy(cloudDbProxy, cloudDB); return 0; } diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/asset_change_timer.h b/data_object/frameworks/innerkitsimpl/include/adaptor/asset_change_timer.h index fd45e258..9ccff883 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/asset_change_timer.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/asset_change_timer.h @@ -30,7 +30,7 @@ private: ~AssetChangeTimer() = default; AssetChangeTimer(const AssetChangeTimer &) = delete; AssetChangeTimer &operator=(const AssetChangeTimer &) = delete; - AssetChangeTimer(FlatObjectStore *flatObjectStore); + explicit AssetChangeTimer(FlatObjectStore *flatObjectStore); void StartTimer(const std::string &sessionId, const std::string &assetKey, std::shared_ptr watcher); void StopTimer(const std::string &sessionId, const std::string &assetKey); std::function ProcessTask( diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/client_adaptor.h b/data_object/frameworks/innerkitsimpl/include/adaptor/client_adaptor.h index 6fa8b1c6..46e1d7fe 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/client_adaptor.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/client_adaptor.h @@ -33,6 +33,9 @@ private: void OnRemoteDied(const wptr &remote) override; }; + static constexpr int32_t DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID = 1301; + static constexpr int32_t GET_SA_RETRY_TIMES = 3; + static constexpr int32_t RETRY_INTERVAL = 1; static std::shared_ptr distributedDataMgr_; static std::shared_ptr GetDistributedDataManager(); static std::mutex mutex_; diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/distributed_objectstore_impl.h b/data_object/frameworks/innerkitsimpl/include/adaptor/distributed_objectstore_impl.h index a191f6c3..829b336d 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/distributed_objectstore_impl.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/distributed_objectstore_impl.h @@ -38,7 +38,9 @@ public: uint32_t Watch(DistributedObject *object, std::shared_ptr watcher) override; uint32_t UnWatch(DistributedObject *object) override; uint32_t SetStatusNotifier(std::shared_ptr notifier) override; + uint32_t SetProgressNotifier(std::shared_ptr notifier) override; void NotifyCachedStatus(const std::string &sessionId) override; + void NotifyProgressStatus(const std::string &sessionId) override; private: DistributedObject *CacheObject(const std::string &sessionId, FlatObjectStore *flatObjectStore); @@ -59,6 +61,17 @@ public: private: std::shared_ptr notifier; }; + +class ProgressNotifierProxy : public ProgressWatcher { +public: + virtual ~ProgressNotifierProxy(); + ProgressNotifierProxy(const std::shared_ptr ¬ifier); + void OnChanged(const std::string &sessionId, int32_t progress) override; + +private: + std::shared_ptr notifier; +}; + class WatcherProxy : public FlatObjectWatcher { public: using AssetChangeCallback = std::function watcher) override; uint32_t UnRegisterObserver(const std::string &key) override; uint32_t SetStatusNotifier(std::shared_ptr watcher) override; + uint32_t SetProgressNotifier(std::shared_ptr watcher) override; uint32_t SyncAllData(const std::string &sessionId, const std::vector &deviceIds, const std::function &)> &onComplete); void OnComplete(const std::string &key, const std::map &devices, @@ -42,13 +43,18 @@ public: bool isOpened_ = false; void NotifyStatus(const std::string &sessionId, const std::string &deviceId, const std::string &status); void NotifyChange(const std::string &sessionId, const std::map> &changedData); + bool NotifyProgress(const std::string &sessionId, int32_t progress); + private: + constexpr static const char *DISTRIBUTED_DATASYNC = "ohos.permission.DISTRIBUTED_DATASYNC"; std::mutex operationMutex_{}; std::mutex watcherMutex_{}; + std::mutex progressMutex_{}; std::shared_ptr storeManager_; std::map delegates_; std::map> observerMap_; std::shared_ptr statusWatcher_ = nullptr; + std::shared_ptr progressWatcher_ = nullptr; }; } // namespace OHOS::ObjectStore #endif diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/flat_object_store.h b/data_object/frameworks/innerkitsimpl/include/adaptor/flat_object_store.h index e06449fd..71d74cb9 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/flat_object_store.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/flat_object_store.h @@ -41,6 +41,9 @@ public: int32_t SubscribeDataChange(const std::string &bundleName, const std::string &sessionId, std::function> &data, bool allReady)> &callback); int32_t UnregisterDataChange(const std::string &bundleName, const std::string &sessionId); + int32_t SubscribeProgressChange( + const std::string &bundleName, const std::string &sessionId, std::function &callback); + int32_t UnregisterProgressChange(const std::string &bundleName, const std::string &sessionId); int32_t DeleteSnapshot(const std::string &bundleName, const std::string &sessionId); bool IsContinue(); private: @@ -50,6 +53,7 @@ private: int32_t RevokeSaveObject( const std::string &bundleName, const std::string &sessionId, const std::function &callback); std::mutex mutex_; + static constexpr uint32_t WAIT_TIME = 5; }; class FlatObjectStore { @@ -60,15 +64,17 @@ public: uint32_t CreateObject(const std::string &sessionId); void ResumeObject(const std::string &sessionId); void SubscribeDataChange(const std::string &sessionId); + void SubscribeProgressChange(const std::string &sessionId); uint32_t Delete(const std::string &objectId); uint32_t Watch(const std::string &objectId, std::shared_ptr watcher); uint32_t UnWatch(const std::string &objectId); uint32_t SetStatusNotifier(std::shared_ptr sharedPtr); + uint32_t SetProgressNotifier(std::shared_ptr sharedPtr); uint32_t Save(const std::string &sessionId, const std::string &deviceId); uint32_t RevokeSave(const std::string &sessionId); void CheckRetrieveCache(const std::string &sessionId); - void FilterData(const std::string &sessionId, - std::map> &data); + void CheckProgressCache(const std::string &sessionId); + void FilterData(const std::string &sessionId, std::map> &data); uint32_t PutDouble(const std::string &sessionId, const std::string &key, double value); uint32_t PutBoolean(const std::string &sessionId, const std::string &key, bool value); uint32_t PutString(const std::string &sessionId, const std::string &key, const std::string &value); @@ -83,10 +89,13 @@ private: uint32_t Put(const std::string &sessionId, const std::string &key, std::vector value); uint32_t Get(const std::string &sessionId, const std::string &key, Bytes &value); + static constexpr const char* DISTRIBUTED_DATASYNC = "ohos.permission.DISTRIBUTED_DATASYNC"; std::shared_ptr storageEngine_; - CacheManager *cacheManager_; + CacheManager *cacheManager_ = nullptr; std::mutex mutex_; + std::mutex progressInfoMutex_; std::vector retrievedCache_ {}; + std::map progressInfoCache_; std::string bundleName_; }; } // namespace OHOS::ObjectStore diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/hitrace.h b/data_object/frameworks/innerkitsimpl/include/adaptor/hitrace.h index 447ff538..5c2dd287 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/hitrace.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/hitrace.h @@ -23,12 +23,12 @@ class DataObjectHiTrace final { public: inline DataObjectHiTrace(const std::string &value) { - StartTrace(HITRACE_TAG_DISTRIBUTEDDATA, value); + StartTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_TAG_DISTRIBUTEDDATA, value.c_str(), ""); } inline ~DataObjectHiTrace() { - FinishTrace(HITRACE_TAG_DISTRIBUTEDDATA); + FinishTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_TAG_DISTRIBUTEDDATA); } }; } // namespace ObjectStore diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/object_callback_impl.h b/data_object/frameworks/innerkitsimpl/include/adaptor/object_callback_impl.h index f61b0594..16f50d09 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/object_callback_impl.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/object_callback_impl.h @@ -58,6 +58,15 @@ public: private: const std::function> &, bool)> callback_; }; + +class ObjectProgressCallback : public ObjectProgressCallbackStub { +public: + ObjectProgressCallback(const std::function &callback); + void Completed(int32_t progress) override; + +private: + const std::function callback_; +}; } // namespace ObjectStore } // namespace OHOS diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/object_service.h b/data_object/frameworks/innerkitsimpl/include/adaptor/object_service.h index 3898d718..0385d6b5 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/object_service.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/object_service.h @@ -28,6 +28,8 @@ public: const std::string &bundleName, const std::string &sessionId, sptr callback) = 0; virtual int32_t RegisterDataObserver( const std::string &bundleName, const std::string &sessionId, sptr callback) = 0; + virtual int32_t RegisterProgressObserver( + const std::string &bundleName, const std::string &sessionId, sptr callback) = 0; }; } // namespace OHOS::ObjectStore #endif diff --git a/data_object/frameworks/innerkitsimpl/include/adaptor/object_storage_engine.h b/data_object/frameworks/innerkitsimpl/include/adaptor/object_storage_engine.h index 7678e601..8b6d5ac5 100644 --- a/data_object/frameworks/innerkitsimpl/include/adaptor/object_storage_engine.h +++ b/data_object/frameworks/innerkitsimpl/include/adaptor/object_storage_engine.h @@ -38,6 +38,11 @@ public: const std::string &sessionId, const std::string &networkId, const std::string &onlineStatus) = 0; }; +class ProgressWatcher { +public: + virtual void OnChanged(const std::string &sessionId, int32_t progress) = 0; +}; + class ObjectStorageEngine { public: ObjectStorageEngine(const ObjectStorageEngine &) = delete; @@ -58,6 +63,7 @@ public: virtual uint32_t RegisterObserver(const std::string &key, std::shared_ptr watcher) = 0; virtual uint32_t UnRegisterObserver(const std::string &key) = 0; virtual uint32_t SetStatusNotifier(std::shared_ptr watcher) = 0; + virtual uint32_t SetProgressNotifier(std::shared_ptr watcher) = 0; }; } // namespace OHOS::ObjectStore #endif \ No newline at end of file diff --git a/data_object/frameworks/innerkitsimpl/include/common/bytes.h b/data_object/frameworks/innerkitsimpl/include/common/bytes.h index ecfcbc25..2648f531 100644 --- a/data_object/frameworks/innerkitsimpl/include/common/bytes.h +++ b/data_object/frameworks/innerkitsimpl/include/common/bytes.h @@ -15,6 +15,7 @@ #ifndef BYTES_H #define BYTES_H + #include #include diff --git a/data_object/frameworks/innerkitsimpl/include/common/common_types.h b/data_object/frameworks/innerkitsimpl/include/common/common_types.h index 67d4e2e7..50dbc05c 100644 --- a/data_object/frameworks/innerkitsimpl/include/common/common_types.h +++ b/data_object/frameworks/innerkitsimpl/include/common/common_types.h @@ -13,12 +13,11 @@ * limitations under the License. */ -#ifndef OHOS_DATA_OBJECT_COMMON_TYPES_H -#define OHOS_DATA_OBJECT_COMMON_TYPES_H +#ifndef OHOS_COMMON_TYPES_H +#define OHOS_COMMON_TYPES_H #include #include #include -#include namespace OHOS::CommonType { struct AssetValue { enum Status : int32_t { diff --git a/data_object/frameworks/innerkitsimpl/include/common/logger.h b/data_object/frameworks/innerkitsimpl/include/common/logger.h index ef712797..ae209ff8 100644 --- a/data_object/frameworks/innerkitsimpl/include/common/logger.h +++ b/data_object/frameworks/innerkitsimpl/include/common/logger.h @@ -70,10 +70,8 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() } // namespace OHOS::ObjectStore #else -#include -#include -#define __FILE_NAME__ __FILE__ +#define __FILE_NAME__ __FILE__ #define LOG_DEBUG(fmt, ...) \ printf("[D][ObjectStore]%s:%d %s: " fmt "\n", __FILE_NAME__, __LINE__, __FUNCTION__, ##__VA_ARGS__) #define LOG_ERROR(fmt, ...) \ diff --git a/data_object/frameworks/innerkitsimpl/include/common/object_radar_reporter.h b/data_object/frameworks/innerkitsimpl/include/common/object_radar_reporter.h index ea4922fc..0803b5ff 100644 --- a/data_object/frameworks/innerkitsimpl/include/common/object_radar_reporter.h +++ b/data_object/frameworks/innerkitsimpl/include/common/object_radar_reporter.h @@ -64,6 +64,9 @@ enum ErrorCode : int32_t { GETKV_FAILED = OFFSET + 6, DB_NOT_INIT = OFFSET + 7, }; +constexpr char DOMAIN[] = "DISTDATAMGR"; +constexpr char EVENT_NAME[] = "DISTRIBUTED_DATA_OBJECT_BEHAVIOR"; +constexpr char ORG_PKG[] = "distributeddata"; class API_EXPORT RadarReporter { public: diff --git a/data_object/frameworks/innerkitsimpl/include/communicator/block_data.h b/data_object/frameworks/innerkitsimpl/include/communicator/block_data.h new file mode 100644 index 00000000..faee9187 --- /dev/null +++ b/data_object/frameworks/innerkitsimpl/include/communicator/block_data.h @@ -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. + */ +#ifndef OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_BLOCK_DATA_H +#define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_BLOCK_DATA_H +#include +#include + +namespace OHOS { +template +class BlockData { +public: + explicit BlockData(uint32_t interval, const T &invalid = T()) : INTERVAL(interval), data_(invalid) {} + + ~BlockData() {} + + void SetValue(const T &data) + { + std::lock_guard lock(mutex_); + data_ = data; + isSet_ = true; + cv_.notify_one(); + } + + T GetValue() + { + std::unique_lock lock(mutex_); + cv_.wait_for(lock, Dur(INTERVAL), [this]() { + return isSet_; + }); + T data = data_; + cv_.notify_one(); + return data; + } + + void Clear(const T &invalid = T()) + { + std::lock_guard lock(mutex_); + isSet_ = false; + data_ = invalid; + cv_.notify_one(); + } + +private: + bool isSet_ = false; + const uint32_t INTERVAL; + T data_; + std::mutex mutex_; + std::condition_variable cv_; +}; +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_BLOCK_DATA_H \ No newline at end of file diff --git a/data_object/frameworks/innerkitsimpl/include/communicator/communication_provider.h b/data_object/frameworks/innerkitsimpl/include/communicator/communication_provider.h index e91f6b27..d5540868 100644 --- a/data_object/frameworks/innerkitsimpl/include/communicator/communication_provider.h +++ b/data_object/frameworks/innerkitsimpl/include/communicator/communication_provider.h @@ -15,8 +15,6 @@ #ifndef DISTRIBUTEDDATA_COMMUNICATION_PROVIDER_H #define DISTRIBUTEDDATA_COMMUNICATION_PROVIDER_H - -#include #include #include "app_data_change_listener.h" diff --git a/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h b/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h index a4be9d58..0ddbb02a 100644 --- a/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h +++ b/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h @@ -41,7 +41,6 @@ public: DeviceInfo GetLocalBasicInfo() const; // get all remote connected device's node information; std::vector GetRemoteNodesBasicInfo() const; - static std::string ToBeAnonymous(const std::string &name); // add DataChangeListener to watch data change; Status StartWatchDataChange(const AppDataChangeListener *observer, const PipeInfo &pipeInfo); diff --git a/data_object/frameworks/innerkitsimpl/include/communicator/task_scheduler.h b/data_object/frameworks/innerkitsimpl/include/communicator/task_scheduler.h new file mode 100644 index 00000000..f46da8c9 --- /dev/null +++ b/data_object/frameworks/innerkitsimpl/include/communicator/task_scheduler.h @@ -0,0 +1,207 @@ +/* + * 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 OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_TASK_SCHEDULER_H +#define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_TASK_SCHEDULER_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace OHOS { +class TaskScheduler { +public: + using TaskId = uint64_t; + using Time = std::chrono::steady_clock::time_point; + using Duration = std::chrono::steady_clock::duration; + using Clock = std::chrono::steady_clock; + using Task = std::function; + inline static constexpr TaskId INVALID_TASK_ID = static_cast(0l); + inline static constexpr Duration INVALID_INTERVAL = std::chrono::milliseconds(0); + inline static constexpr uint64_t UNLIMITED_TIMES = std::numeric_limits::max(); + TaskScheduler(size_t capacity, const std::string &name) + { + capacity_ = capacity; + isRunning_ = true; + taskId_ = INVALID_TASK_ID; + running_ = InnerTask(); + thread_ = std::make_unique([this, name]() { + auto realName = std::string("scheduler_") + name; + pthread_setname_np(pthread_self(), realName.c_str()); + Loop(); + }); + } + TaskScheduler(const std::string &name) : TaskScheduler(std::numeric_limits::max(), name) {} + TaskScheduler(size_t capacity = std::numeric_limits::max()) : TaskScheduler(capacity, "") {} + ~TaskScheduler() + { + isRunning_ = false; + Clean(); + Execute([]() {}); + thread_->join(); + } + // execute task at specific time + TaskId At(const Time &begin, Task task, Duration interval = INVALID_INTERVAL, uint64_t times = UNLIMITED_TIMES) + { + std::unique_lock lock(mutex_); + if (tasks_.size() >= capacity_) { + return INVALID_TASK_ID; + } + InnerTask innerTask; + innerTask.times = times; + innerTask.taskId = GenTaskId(); + innerTask.interval = interval; + innerTask.exec = std::move(task); + auto it = tasks_.insert({ begin, innerTask}); + if (it == tasks_.begin()) { + condition_.notify_one(); + } + indexes_[innerTask.taskId] = it; + return innerTask.taskId; + } + TaskId Reset(TaskId taskId, const Duration &interval) + { + std::unique_lock lock(mutex_); + if (running_.taskId == taskId && running_.interval != INVALID_INTERVAL) { + running_.interval = interval; + return running_.taskId; + } + auto index = indexes_.find(taskId); + if (index == indexes_.end()) { + return INVALID_TASK_ID; + } + auto &innerTask = index->second->second; + if (innerTask.interval != INVALID_INTERVAL) { + innerTask.interval = interval; + } + auto it = tasks_.insert({ std::chrono::steady_clock::now() + interval, std::move(innerTask) }); + if (it == tasks_.begin() || index->second == tasks_.begin()) { + condition_.notify_one(); + } + tasks_.erase(index->second); + indexes_[taskId] = it; + return taskId; + } + void Clean() + { + std::unique_lock lock(mutex_); + indexes_.clear(); + tasks_.clear(); + } + // execute task periodically with duration + TaskId Every(Duration interval, Task task) + { + return At(std::chrono::steady_clock::now() + interval, task, interval); + } + // remove task in SchedulerTask + void Remove(TaskId taskId, bool wait = false) + { + std::unique_lock lock(mutex_); + cond_.wait(lock, [this, taskId, wait]() { + return (!wait || running_.taskId != taskId); + }); + auto index = indexes_.find(taskId); + if (index == indexes_.end()) { + return; + } + tasks_.erase(index->second); + indexes_.erase(index); + condition_.notify_one(); + } + // execute task periodically with duration after delay + TaskId Every(Duration delay, Duration interval, Task task) + { + return At(std::chrono::steady_clock::now() + delay, task, interval); + } + // execute task for some times periodically with duration after delay + TaskId Every(int32_t times, Duration delay, Duration interval, Task task) + { + return At(std::chrono::steady_clock::now() + delay, task, interval, times); + } + TaskId Execute(Task task) + { + return At(std::chrono::steady_clock::now(), std::move(task)); + } +private: + struct InnerTask { + TaskId taskId = INVALID_TASK_ID; + Duration interval = INVALID_INTERVAL; + uint64_t times = UNLIMITED_TIMES; + std::function exec; + }; + void Loop() + { + while (isRunning_) { + std::function exec; + { + std::unique_lock lock(mutex_); + condition_.wait(lock, [this] { + return !tasks_.empty(); + }); + if (tasks_.begin()->first > std::chrono::steady_clock::now()) { + auto time = tasks_.begin()->first; + condition_.wait_until(lock, time); + continue; + } + auto it = tasks_.begin(); + running_ = it->second; + exec = running_.exec; + indexes_.erase(running_.taskId); + tasks_.erase(it); + running_.times--; + } + if (exec) { + exec(); + } + { + std::unique_lock lock(mutex_); + if (running_.interval != INVALID_INTERVAL && running_.times > 0) { + auto it = tasks_.insert({ std::chrono::steady_clock::now() + running_.interval, running_ }); + indexes_[running_.taskId] = it; + } + running_ = InnerTask(); + cond_.notify_all(); + } + } + } + + TaskId GenTaskId() + { + auto taskId = ++taskId_; + if (taskId == INVALID_TASK_ID) { + return ++taskId_; + } + return taskId; + } + + volatile bool isRunning_; + size_t capacity_; + std::multimap tasks_; + std::map indexes_; + InnerTask running_; + std::mutex mutex_; + std::unique_ptr thread_; + std::condition_variable condition_; + std::condition_variable cond_; + std::atomic taskId_; +}; +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_TASK_SCHEDULER_H diff --git a/data_object/frameworks/innerkitsimpl/include/distributeddata_object_store_ipc_interface_code.h b/data_object/frameworks/innerkitsimpl/include/distributeddata_object_store_ipc_interface_code.h index 0523098b..1d3d3f04 100644 --- a/data_object/frameworks/innerkitsimpl/include/distributeddata_object_store_ipc_interface_code.h +++ b/data_object/frameworks/innerkitsimpl/include/distributeddata_object_store_ipc_interface_code.h @@ -30,6 +30,8 @@ enum class ObjectServiceInterfaceCode : int8_t { OBJECTSTORE_BIND_ASSET_STORE, OBJECTSTORE_DELETE_SNAPSHOT, OBJECTSTORE_IS_CONTINUE, + OBJECTSTORE_REGISTER_PROGRESS, + OBJECTSTORE_UNREGISTER_PROGRESS, OBJECTSTORE_SERVICE_CMD_MAX }; @@ -37,7 +39,7 @@ enum class KvStoreServiceInterfaceCode : int8_t { GET_FEATURE_INTERFACE = 0, REGISTERCLIENTDEATHOBSERVER, }; -} -} // namespace OHOS +} // namespace ObjectStoreService +} // namespace OHOS::DistributedObject #endif // DISTRIBUTEDDATA_OBJECT_STORE_IPC_INTERFACE_H \ No newline at end of file diff --git a/data_object/frameworks/innerkitsimpl/include/object_callback.h b/data_object/frameworks/innerkitsimpl/include/object_callback.h index 9279a0ad..3e6787bf 100644 --- a/data_object/frameworks/innerkitsimpl/include/object_callback.h +++ b/data_object/frameworks/innerkitsimpl/include/object_callback.h @@ -43,6 +43,11 @@ class IObjectChangeCallback { public: virtual void Completed(const std::map> &results, bool allReady) = 0; }; + +class IObjectProgressCallback { +public: + virtual void Completed(int32_t progress) = 0; +}; } // namespace DistributedObject } // namespace OHOS diff --git a/data_object/frameworks/innerkitsimpl/include/object_callback_stub.h b/data_object/frameworks/innerkitsimpl/include/object_callback_stub.h index 8a7c7109..d446132f 100644 --- a/data_object/frameworks/innerkitsimpl/include/object_callback_stub.h +++ b/data_object/frameworks/innerkitsimpl/include/object_callback_stub.h @@ -59,6 +59,16 @@ class ObjectChangeCallbackStub : public IRemoteStub public: int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; }; + +class ObjectProgressCallbackBroker : public IObjectProgressCallback, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedObject.IObjectProgressCallback"); +}; + +class ObjectProgressCallbackStub : public IRemoteStub { +public: + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +}; } // namespace DistributedObject } // namespace OHOS diff --git a/data_object/frameworks/innerkitsimpl/include/object_service.h b/data_object/frameworks/innerkitsimpl/include/object_service.h index d59cc95b..78a0b13c 100644 --- a/data_object/frameworks/innerkitsimpl/include/object_service.h +++ b/data_object/frameworks/innerkitsimpl/include/object_service.h @@ -31,6 +31,9 @@ public: virtual int32_t RegisterDataObserver( const std::string &bundleName, const std::string &sessionId, sptr callback) = 0; virtual int32_t UnregisterDataChangeObserver(const std::string &bundleName, const std::string &sessionId) = 0; + virtual int32_t RegisterProgressObserver( + const std::string &bundleName, const std::string &sessionId, sptr callback) = 0; + virtual int32_t UnregisterProgressObserver(const std::string &bundleName, const std::string &sessionId) = 0; virtual int32_t OnAssetChanged(const std::string &bundleName, const std::string &sessionId, const std::string &deviceId, const ObjectStore::Asset &assetValue) = 0; virtual int32_t BindAssetStore(const std::string &bundleName, const std::string &sessionId, diff --git a/data_object/frameworks/innerkitsimpl/include/object_service_proxy.h b/data_object/frameworks/innerkitsimpl/include/object_service_proxy.h index 724aa688..6403bc68 100644 --- a/data_object/frameworks/innerkitsimpl/include/object_service_proxy.h +++ b/data_object/frameworks/innerkitsimpl/include/object_service_proxy.h @@ -34,6 +34,9 @@ public: int32_t RegisterDataObserver(const std::string &bundleName, const std::string &sessionId, sptr callback) override; int32_t UnregisterDataChangeObserver(const std::string &bundleName, const std::string &sessionId) override; + int32_t RegisterProgressObserver(const std::string &bundleName, const std::string &sessionId, + sptr callback) override; + int32_t UnregisterProgressObserver(const std::string &bundleName, const std::string &sessionId) override; int32_t OnAssetChanged(const std::string &bundleName, const std::string &sessionId, const std::string &deviceId, const ObjectStore::Asset &assetValue) override; diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/asset_change_timer.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/asset_change_timer.cpp index c65ad97c..8ded3967 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/asset_change_timer.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/asset_change_timer.cpp @@ -15,6 +15,7 @@ #define LOG_TAG "AssetChangeTimer" #include "asset_change_timer.h" +#include "anonymous.h" #include "client_adaptor.h" #include "logger.h" #include "objectstore_errors.h" @@ -38,10 +39,9 @@ AssetChangeTimer *AssetChangeTimer::GetInstance(FlatObjectStore *flatObjectStore return instance; } -AssetChangeTimer::AssetChangeTimer(FlatObjectStore *flatObjectStore) +AssetChangeTimer::AssetChangeTimer(FlatObjectStore *flatObjectStore) : flatObjectStore_(flatObjectStore) { - flatObjectStore_ = flatObjectStore; - executor_ = std::make_shared(MAX_THREADS, MIN_THREADS); + executor_ = std::make_shared(MAX_THREADS, MIN_THREADS, "OBJECT_TASK"); } void AssetChangeTimer::OnAssetChanged( @@ -67,13 +67,13 @@ std::function AssetChangeTimer::ProcessTask( const std::string &sessionId, const std::string &assetKey, std::shared_ptr watcher) { return [=]() { - LOG_DEBUG("Start working on a task, sessionId: %{public}s, assetKey: %{public}s", sessionId.c_str(), - assetKey.c_str()); + LOG_DEBUG("Start working on a task, sessionId: %{public}s, assetKey: %{public}s", + Anonymous::Change(sessionId).c_str(), assetKey.c_str()); StopTimer(sessionId, assetKey); uint32_t status = HandleAssetChanges(sessionId, assetKey); if (status == SUCCESS) { LOG_DEBUG("Asset change task end, start callback, sessionId: %{public}s, assetKey: %{public}s", - sessionId.c_str(), assetKey.c_str()); + Anonymous::Change(sessionId).c_str(), assetKey.c_str()); watcher->OnChanged(sessionId, { assetKey }); } }; @@ -92,7 +92,7 @@ uint32_t AssetChangeTimer::HandleAssetChanges(const std::string &sessionId, cons Asset assetValue; if (!GetAssetValue(sessionId, assetKey, assetValue)) { LOG_ERROR("GetAssetValue assetValue is not complete, sessionId: %{public}s, assetKey: %{public}s", - sessionId.c_str(), assetKey.c_str()); + Anonymous::Change(sessionId).c_str(), assetKey.c_str()); return ERR_DB_GET_FAIL; } @@ -111,7 +111,7 @@ uint32_t AssetChangeTimer::HandleAssetChanges(const std::string &sessionId, cons int32_t res = proxy->OnAssetChanged(flatObjectStore_->GetBundleName(), sessionId, deviceId, assetValue); if (res != SUCCESS) { LOG_ERROR("OnAssetChanged failed status: %{public}d, sessionId: %{public}s, assetKey: %{public}s", status, - sessionId.c_str(), assetKey.c_str()); + Anonymous::Change(sessionId).c_str(), assetKey.c_str()); } return res; } diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/client_adaptor.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/client_adaptor.cpp index 633d44ff..9b3c689f 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/client_adaptor.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/client_adaptor.cpp @@ -25,9 +25,6 @@ namespace OHOS::ObjectStore { std::shared_ptr ClientAdaptor::distributedDataMgr_ = nullptr; std::mutex ClientAdaptor::mutex_; -static constexpr int32_t DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID = 1301; -static constexpr int32_t GET_SA_RETRY_TIMES = 3; -static constexpr int32_t RETRY_INTERVAL = 1; using KvStoreCode = OHOS::DistributedObject::ObjectStoreService::KvStoreServiceInterfaceCode; @@ -187,7 +184,7 @@ uint32_t ObjectStoreDataServiceProxy::RegisterClientDeathObserver( int32_t error = remoteObject->SendRequest(static_cast(KvStoreCode::REGISTERCLIENTDEATHOBSERVER), data, reply, mo); if (error != 0) { - LOG_WARN("failed during IPC. errCode %d", error); + LOG_WARN("failed during IPC. errCode %{public}d", error); return ERR_IPC; } return static_cast(reply.ReadInt32()); diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_store_impl.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_store_impl.cpp index 22cf1f78..fb6ddd89 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_store_impl.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/distributed_object_store_impl.cpp @@ -13,8 +13,8 @@ * limitations under the License. */ -#include #include +#include #include "hitrace.h" #include "distributed_object_impl.h" @@ -199,15 +199,26 @@ uint32_t DistributedObjectStoreImpl::SetStatusNotifier(std::shared_ptrSetStatusNotifier(watcherProxy); } -void DistributedObjectStoreImpl::NotifyCachedStatus(const std::string &sessionId) +uint32_t DistributedObjectStoreImpl::SetProgressNotifier(std::shared_ptr notifier) { if (flatObjectStore_ == nullptr) { - LOG_ERROR("NotifyCachedStatus sync flatObjectStore err "); - return; + LOG_ERROR("flatObjectStore_ is nullptr"); + return ERR_NULL_OBJECTSTORE; } + std::shared_ptr watcherProxy = std::make_shared(notifier); + return flatObjectStore_->SetProgressNotifier(watcherProxy); +} + +void DistributedObjectStoreImpl::NotifyCachedStatus(const std::string &sessionId) +{ flatObjectStore_->CheckRetrieveCache(sessionId); } +void DistributedObjectStoreImpl::NotifyProgressStatus(const std::string &sessionId) +{ + flatObjectStore_->CheckProgressCache(sessionId); +} + WatcherProxy::WatcherProxy(const std::shared_ptr objectWatcher, const std::string &sessionId) : FlatObjectWatcher(sessionId), objectWatcher_(objectWatcher) { @@ -307,4 +318,20 @@ StatusNotifierProxy::~StatusNotifierProxy() LOG_ERROR("destroy"); notifier = nullptr; } + +void ProgressNotifierProxy::OnChanged(const std::string &sessionId, int32_t progress) +{ + if (notifier != nullptr) { + notifier->OnChanged(sessionId, progress); + } +} + +ProgressNotifierProxy::ProgressNotifierProxy(const std::shared_ptr ¬ifier) : notifier(notifier) +{ +} + +ProgressNotifierProxy::~ProgressNotifierProxy() +{ + notifier = nullptr; +} } // namespace OHOS::ObjectStore diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_storage_engine.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_storage_engine.cpp index 91123488..58c7fc34 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_storage_engine.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_storage_engine.cpp @@ -14,6 +14,7 @@ */ #include "flat_object_storage_engine.h" +#include "anonymous.h" #include "accesstoken_kit.h" #include "ipc_skeleton.h" #include "objectstore_errors.h" @@ -23,8 +24,6 @@ #include "object_radar_reporter.h" namespace OHOS::ObjectStore { -constexpr static const char *DISTRIBUTED_DATASYNC = "ohos.permission.DISTRIBUTED_DATASYNC"; - FlatObjectStorageEngine::~FlatObjectStorageEngine() { if (!isOpened_) { @@ -99,7 +98,7 @@ uint32_t FlatObjectStorageEngine::CreateTable(const std::string &key) { std::lock_guard lock(operationMutex_); if (delegates_.count(key) != 0) { - LOG_ERROR("FlatObjectStorageEngine::CreateTable %{public}s already created", key.c_str()); + LOG_ERROR("table: %{public}s already created", Anonymous::Change(key).c_str()); RadarReporter::ReportStateError(std::string(__FUNCTION__), CREATE, CREATE_TABLE, RADAR_FAILED, DUPLICATE_CREATE, FINISHED); return ERR_EXIST; @@ -116,7 +115,7 @@ uint32_t FlatObjectStorageEngine::CreateTable(const std::string &key) LOG_INFO("create table result %{public}d", status); }); if (status != DistributedDB::DBStatus::OK || kvStore == nullptr) { - LOG_ERROR("FlatObjectStorageEngine::CreateTable %{public}s getkvstore fail[%{public}d]", key.c_str(), status); + LOG_ERROR("GetKvStore fail[%{public}d], store:%{public}s", status, Anonymous::Change(key).c_str()); RadarReporter::ReportStateError(std::string(__FUNCTION__), CREATE, CREATE_TABLE, RADAR_FAILED, status, FINISHED); return ERR_DB_GETKV_FAIL; @@ -126,12 +125,12 @@ uint32_t FlatObjectStorageEngine::CreateTable(const std::string &key) LOG_INFO("start Pragma"); status = kvStore->Pragma(DistributedDB::AUTO_SYNC, data); if (status != DistributedDB::DBStatus::OK) { - LOG_ERROR("FlatObjectStorageEngine::CreateTable %{public}s Pragma fail[%{public}d]", key.c_str(), status); + LOG_ERROR("Set Pragma fail[%{public}d], store:%{public}s", status, Anonymous::Change(key).c_str()); RadarReporter::ReportStateError(std::string(__FUNCTION__), CREATE, CREATE_TABLE, RADAR_FAILED, status, FINISHED); return ERR_DB_GETKV_FAIL; } - LOG_INFO("create table %{public}s success", key.c_str()); + LOG_INFO("create table %{public}s success", Anonymous::Change(key).c_str()); { std::lock_guard lock(operationMutex_); delegates_.insert_or_assign(key, kvStore); @@ -361,8 +360,8 @@ uint32_t FlatObjectStorageEngine::SetStatusNotifier(std::shared_ptr &devices) { for (auto item : devices) { LOG_INFO("%{public}s pull data result %{public}d in device %{public}s", - SoftBusAdapter::ToBeAnonymous(storeId).c_str(), item.second, - SoftBusAdapter::ToBeAnonymous(SoftBusAdapter::GetInstance()->ToNodeID(item.first)).c_str()); + Anonymous::Change(storeId).c_str(), item.second, + Anonymous::Change(SoftBusAdapter::GetInstance()->ToNodeID(item.first)).c_str()); } if (statusWatcher_ != nullptr) { for (auto item : devices) { @@ -383,13 +382,24 @@ uint32_t FlatObjectStorageEngine::SetStatusNotifier(std::shared_ptr watcher) +{ + if (!isOpened_) { + LOG_ERROR("FlatObjectStorageEngine::SetProgressNotifier has not init"); + return ERR_DB_NOT_INIT; + } + std::lock_guard lock(progressMutex_); + progressWatcher_ = watcher; + return SUCCESS; +} + uint32_t FlatObjectStorageEngine::SyncAllData(const std::string &sessionId, const std::vector &deviceIds, const std::function &)> &onComplete) { LOG_INFO("start"); std::lock_guard lock(operationMutex_); if (delegates_.count(sessionId) == 0) { - LOG_ERROR("FlatObjectStorageEngine::SyncAllData %{public}s already deleted", sessionId.c_str()); + LOG_ERROR("%{public}s already deleted", Anonymous::Change(sessionId).c_str()); return ERR_DB_NOT_EXIST; } DistributedDB::KvStoreNbDelegate *kvstore = delegates_.at(sessionId); @@ -397,28 +407,28 @@ uint32_t FlatObjectStorageEngine::SyncAllData(const std::string &sessionId, cons LOG_INFO("single device,no need sync"); return ERR_SINGLE_DEVICE; } - LOG_INFO("start sync %{public}s", sessionId.c_str()); + LOG_INFO("start sync %{public}s", Anonymous::Change(sessionId).c_str()); DistributedDB::DBStatus status = kvstore->Sync(deviceIds, DistributedDB::SyncMode::SYNC_MODE_PULL_ONLY, onComplete); if (status != DistributedDB::DBStatus::OK) { LOG_ERROR("FlatObjectStorageEngine::UnRegisterObserver unRegister err %{public}d", status); return ERR_UNRIGSTER; } - LOG_INFO("end sync %{public}s", sessionId.c_str()); + LOG_INFO("end sync %{public}s", Anonymous::Change(sessionId).c_str()); return SUCCESS; } uint32_t FlatObjectStorageEngine::GetItems(const std::string &key, std::map> &data) { if (!isOpened_) { - LOG_ERROR("FlatObjectStorageEngine::GetItems %{public}s not init", key.c_str()); + LOG_ERROR("GetItems %{public}s not init", Anonymous::Change(key).c_str()); return ERR_DB_NOT_INIT; } std::lock_guard lock(operationMutex_); if (delegates_.count(key) == 0) { - LOG_ERROR("FlatObjectStorageEngine::GetItems %{public}s not exist", key.c_str()); + LOG_ERROR("GetItems %{public}s not exist", Anonymous::Change(key).c_str()); return ERR_DB_NOT_EXIST; } - LOG_INFO("start Get %{public}s", key.c_str()); + LOG_INFO("start Get %{public}s", Anonymous::Change(key).c_str()); std::vector entries; DistributedDB::DBStatus status = delegates_.at(key)->GetEntries(StringUtils::StrToBytes(""), entries); if (status != DistributedDB::DBStatus::OK) { @@ -428,7 +438,7 @@ uint32_t FlatObjectStorageEngine::GetItems(const std::string &key, std::mapOnChanged(sessionId, deviceId, status); } -void FlatObjectStorageEngine::NotifyChange(const std::string &sessionId, - const std::map> &changedData) +bool FlatObjectStorageEngine::NotifyProgress(const std::string &sessionId, int32_t progress) +{ + std::lock_guard lock(progressMutex_); + if (progressWatcher_ == nullptr) { + return false; + } + progressWatcher_->OnChanged(sessionId, progress); + return true; +} + +void FlatObjectStorageEngine::NotifyChange( + const std::string &sessionId, const std::map> &changedData) { std::lock_guard lock(operationMutex_); if (observerMap_.count(sessionId) == 0) { diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_store.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_store.cpp index 4d257080..26fadf8a 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_store.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/flat_object_store.cpp @@ -25,9 +25,6 @@ #include "string_utils.h" namespace OHOS::ObjectStore { -static constexpr uint32_t WAIT_TIME = 5; -static constexpr const char* DISTRIBUTED_DATASYNC = "ohos.permission.DISTRIBUTED_DATASYNC"; - FlatObjectStore::FlatObjectStore(const std::string &bundleName) { bundleName_ = bundleName; @@ -69,6 +66,7 @@ uint32_t FlatObjectStore::CreateObject(const std::string &sessionId) } SubscribeDataChange(sessionId); ResumeObject(sessionId); + SubscribeProgressChange(sessionId); return SUCCESS; } @@ -122,6 +120,18 @@ void FlatObjectStore::SubscribeDataChange(const std::string &sessionId) cacheManager_->SubscribeDataChange(bundleName_, sessionId, remoteResumeCallback); } +void FlatObjectStore::SubscribeProgressChange(const std::string &sessionId) +{ + std::function remoteResumeCallback = [sessionId, this](int32_t progress) { + LOG_INFO("asset progress = %{public}d", progress); + if (!storageEngine_->NotifyProgress(sessionId, progress)) { + std::lock_guard lck(progressInfoMutex_); + progressInfoCache_.insert_or_assign(sessionId, progress); + } + }; + cacheManager_->SubscribeProgressChange(bundleName_, sessionId, remoteResumeCallback); +} + uint32_t FlatObjectStore::Delete(const std::string &sessionId) { if (!storageEngine_->isOpened_ && storageEngine_->Open(bundleName_) != SUCCESS) { @@ -135,6 +145,7 @@ uint32_t FlatObjectStore::Delete(const std::string &sessionId) } cacheManager_->UnregisterDataChange(bundleName_, sessionId); cacheManager_->DeleteSnapshot(bundleName_, sessionId); + cacheManager_->UnregisterProgressChange(bundleName_, sessionId); return SUCCESS; } @@ -191,6 +202,14 @@ uint32_t FlatObjectStore::SetStatusNotifier(std::shared_ptr notif return storageEngine_->SetStatusNotifier(notifier); } +uint32_t FlatObjectStore::SetProgressNotifier(std::shared_ptr notifier) +{ + if (!storageEngine_->isOpened_ && storageEngine_->Open(bundleName_) != SUCCESS) { + LOG_ERROR("FlatObjectStore::DB has not inited"); + return ERR_DB_NOT_INIT; + } + return storageEngine_->SetProgressNotifier(notifier); +} uint32_t FlatObjectStore::Save(const std::string &sessionId, const std::string &deviceId) { RadarReporter::ReportStateStart(std::string(__FUNCTION__), SAVE, SAVE_TO_SERVICE, IDLE, START, bundleName_); @@ -245,8 +264,19 @@ void FlatObjectStore::CheckRetrieveCache(const std::string &sessionId) } } -void FlatObjectStore::FilterData(const std::string &sessionId, - std::map> &data) +void FlatObjectStore::CheckProgressCache(const std::string &sessionId) +{ + std::lock_guard lck(progressInfoMutex_); + auto it = progressInfoCache_.find(sessionId); + if (it != progressInfoCache_.end()) { + auto ret = storageEngine_->NotifyProgress(sessionId, it->second); + if (ret) { + progressInfoCache_.erase(sessionId); + } + } +} + +void FlatObjectStore::FilterData(const std::string &sessionId, std::map> &data) { std::map> allData {}; storageEngine_->GetItems(sessionId, allData); @@ -445,7 +475,7 @@ int32_t CacheManager::SaveObject(const std::string &bundleName, const std::strin int32_t status = proxy->ObjectStoreSave( bundleName, sessionId, deviceId, objectData, objectSaveCallback->AsObject().GetRefPtr()); if (status != SUCCESS) { - LOG_ERROR("object save failed code=%d.", static_cast(status)); + LOG_ERROR("object save failed code=%{public}d.", static_cast(status)); RadarReporter::ReportStateError(std::string(__FUNCTION__), SAVE, SAVE_TO_SERVICE, RADAR_FAILED, IPC_ERROR, FINISHED); } else { @@ -471,7 +501,7 @@ int32_t CacheManager::RevokeSaveObject( int32_t status = proxy->ObjectStoreRevokeSave( bundleName, sessionId, objectRevokeSaveCallback->AsObject().GetRefPtr()); if (status != SUCCESS) { - LOG_ERROR("object revoke save failed code=%d.", static_cast(status)); + LOG_ERROR("object revoke save failed code=%{public}d.", static_cast(status)); } LOG_INFO("object revoke save successful"); return status; @@ -493,7 +523,7 @@ int32_t CacheManager::ResumeObject(const std::string &bundleName, const std::str int32_t status = proxy->ObjectStoreRetrieve( bundleName, sessionId, objectRetrieveCallback->AsObject().GetRefPtr()); if (status != SUCCESS) { - LOG_ERROR("object resume failed code=%d.", static_cast(status)); + LOG_ERROR("object resume failed code=%{public}d.", static_cast(status)); } LOG_INFO("object resume successful"); return status; @@ -516,12 +546,32 @@ int32_t CacheManager::SubscribeDataChange(const std::string &bundleName, const s int32_t status = proxy->RegisterDataObserver( bundleName, sessionId, objectRemoteResumeCallback->AsObject().GetRefPtr()); if (status != SUCCESS) { - LOG_ERROR("object remote resume failed code=%d.", static_cast(status)); + LOG_ERROR("object remote resume failed code=%{public}d.", static_cast(status)); } LOG_INFO("object remote resume successful"); return status; } +int32_t CacheManager::SubscribeProgressChange( + const std::string &bundleName, const std::string &sessionId, std::function &callback) +{ + sptr proxy = ClientAdaptor::GetObjectService(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr."); + return ERR_NULL_PTR; + } + sptr objectRemoteResumeCallback = new (std::nothrow) ObjectProgressCallback(callback); + if (objectRemoteResumeCallback == nullptr) { + LOG_ERROR("CacheManager::SubscribeProgressChange no memory for ObjectProgressCallback malloc!"); + return ERR_NULL_PTR; + } + int32_t status = + proxy->RegisterProgressObserver(bundleName, sessionId, objectRemoteResumeCallback->AsObject().GetRefPtr()); + if (status != SUCCESS) { + LOG_ERROR("object remote resume failed code=%{public}d.", static_cast(status)); + } + return status; +} int32_t CacheManager::UnregisterDataChange(const std::string &bundleName, const std::string &sessionId) { sptr proxy = ClientAdaptor::GetObjectService(); @@ -531,12 +581,27 @@ int32_t CacheManager::UnregisterDataChange(const std::string &bundleName, const } int32_t status = proxy->UnregisterDataChangeObserver(bundleName, sessionId); if (status != SUCCESS) { - LOG_ERROR("object remote resume failed code=%d.", static_cast(status)); + LOG_ERROR("object remote resume failed code=%{public}d.", static_cast(status)); } LOG_INFO("object unregister data change observer successful"); return status; } +int32_t CacheManager::UnregisterProgressChange(const std::string &bundleName, const std::string &sessionId) +{ + sptr proxy = ClientAdaptor::GetObjectService(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr."); + return ERR_NULL_PTR; + } + int32_t status = proxy->UnregisterProgressObserver(bundleName, sessionId); + if (status != SUCCESS) { + LOG_ERROR("object remote resume failed code=%{public}d.", static_cast(status)); + } + LOG_INFO("object unregister progress change observer successful"); + return status; +} + int32_t CacheManager::DeleteSnapshot(const std::string &bundleName, const std::string &sessionId) { sptr proxy = ClientAdaptor::GetObjectService(); @@ -546,7 +611,7 @@ int32_t CacheManager::DeleteSnapshot(const std::string &bundleName, const std::s } int32_t status = proxy->DeleteSnapshot(bundleName, sessionId); if (status != SUCCESS) { - LOG_ERROR("object delete snapshot failed code=%d.", static_cast(status)); + LOG_ERROR("object delete snapshot failed code=%{public}d.", static_cast(status)); } LOG_INFO("object delete snapshot successful"); return status; diff --git a/data_object/frameworks/innerkitsimpl/src/adaptor/object_callback_impl.cpp b/data_object/frameworks/innerkitsimpl/src/adaptor/object_callback_impl.cpp index 9cf4d9a5..3a168cb3 100644 --- a/data_object/frameworks/innerkitsimpl/src/adaptor/object_callback_impl.cpp +++ b/data_object/frameworks/innerkitsimpl/src/adaptor/object_callback_impl.cpp @@ -55,4 +55,11 @@ ObjectChangeCallback::ObjectChangeCallback( : callback_(callback) { } -} // namespace OHOS::DistributedKv +void ObjectProgressCallback::Completed(int32_t progress) +{ + callback_(progress); +} +ObjectProgressCallback::ObjectProgressCallback(const std::function &callback) : callback_(callback) +{ +} +} // namespace OHOS::ObjectStore diff --git a/data_object/frameworks/innerkitsimpl/src/communicator/dev_manager.cpp b/data_object/frameworks/innerkitsimpl/src/communicator/dev_manager.cpp index 94522125..3b33264c 100644 --- a/data_object/frameworks/innerkitsimpl/src/communicator/dev_manager.cpp +++ b/data_object/frameworks/innerkitsimpl/src/communicator/dev_manager.cpp @@ -16,6 +16,7 @@ #include +#include "anonymous.h" #include "device_manager.h" #include "softbus_adapter.h" @@ -42,7 +43,7 @@ private: void DMStateCallback::OnDeviceOnline(const DmDeviceInfo &deviceInfo) { std::string uuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(deviceInfo.networkId)); - LOG_INFO("[Online] id:%{public}s, name:%{public}s, typeId:%{public}d", SoftBusAdapter::ToBeAnonymous(uuid).c_str(), + LOG_INFO("[Online] id:%{public}s, name:%{public}s, typeId:%{public}d", Anonymous::Change(uuid).c_str(), deviceInfo.deviceName, deviceInfo.deviceTypeId); NotifyAll(deviceInfo, DeviceChangeType::DEVICE_ONLINE); } @@ -50,16 +51,15 @@ void DMStateCallback::OnDeviceOnline(const DmDeviceInfo &deviceInfo) void DMStateCallback::OnDeviceOffline(const DmDeviceInfo &deviceInfo) { std::string uuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(deviceInfo.networkId)); - LOG_INFO("[Offline] id:%{public}s, name:%{public}s, typeId:%{public}d", - SoftBusAdapter::ToBeAnonymous(uuid).c_str(), deviceInfo.deviceName, deviceInfo.deviceTypeId); + LOG_INFO("[Offline] id:%{public}s, name:%{public}s, typeId:%{public}d", Anonymous::Change(uuid).c_str(), + deviceInfo.deviceName, deviceInfo.deviceTypeId); NotifyAll(deviceInfo, DeviceChangeType::DEVICE_OFFLINE); } void DMStateCallback::OnDeviceChanged(const DmDeviceInfo &deviceInfo) { std::string uuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(deviceInfo.networkId)); - LOG_INFO("[InfoChange] id:%{public}s, name:%{public}s", SoftBusAdapter::ToBeAnonymous(uuid).c_str(), - deviceInfo.deviceName); + LOG_INFO("[InfoChange] id:%{public}s, name:%{public}s", Anonymous::Change(uuid).c_str(), deviceInfo.deviceName); } void DMStateCallback::OnDeviceReady(const DmDeviceInfo &deviceInfo) @@ -139,7 +139,7 @@ std::string DevManager::GetUuidByNodeId(const std::string &nodeId) const int32_t ret = DistributedHardware::DeviceManager::GetInstance().GetEncryptedUuidByNetworkId( "ohos.objectstore", nodeId.c_str(), uuid); if (ret != DM_OK) { - LOG_WARN("GetEncryptedUuidByNetworkId error, nodeId:%{public}s", SoftBusAdapter::ToBeAnonymous(nodeId).c_str()); + LOG_WARN("GetEncryptedUuidByNetworkId error, nodeId:%{public}s", Anonymous::Change(nodeId).c_str()); return ""; } return uuid; diff --git a/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp b/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp index 04f9c381..d0f845fd 100644 --- a/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp +++ b/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp @@ -25,16 +25,11 @@ namespace OHOS { namespace ObjectStore { -constexpr int32_t HEAD_SIZE = 3; -constexpr int32_t END_SIZE = 3; -constexpr int32_t MIN_SIZE = HEAD_SIZE + END_SIZE + 3; -constexpr const char *REPLACE_CHAIN = "***"; -constexpr const char *DEFAULT_ANONYMOUS = "******"; constexpr int32_t SOFTBUS_OK = 0; constexpr int32_t INVALID_SOCKET_ID = 0; constexpr size_t TASK_CAPACITY_MAX = 15; constexpr const char *PKG_NAME = "ohos.objectstore"; -SoftBusAdapter *AppDataListenerWrap::softBusAdapter_; +SoftBusAdapter *AppDataListenerWrap::softBusAdapter_ = nullptr; std::shared_ptr SoftBusAdapter::instance_; SoftBusAdapter::SoftBusAdapter() @@ -59,6 +54,16 @@ SoftBusAdapter::~SoftBusAdapter() taskQueue_->Clean(); taskQueue_ = nullptr; } + std::lock_guard lock(deviceDataLock_); + for (auto &deviceData : dataCaches_) { + for (auto &bytesMsg : deviceData.second) { + if (bytesMsg.ptr != nullptr) { + delete[] bytesMsg.ptr; + bytesMsg.ptr = nullptr; + } + } + } + dataCaches_.clear(); sockets_.clear(); } @@ -111,7 +116,7 @@ void SoftBusAdapter::NotifyAll(const DeviceInfo &deviceInfo, const DeviceChangeT } LOG_DEBUG("high"); std::string uuid = DevManager::GetInstance()->GetUuidByNodeId(deviceInfo.deviceId); - LOG_DEBUG("[Notify] to DB from: %{public}s, type:%{public}hhd", ToBeAnonymous(uuid).c_str(), type); + LOG_DEBUG("[Notify] to DB from: %{public}s, type:%{public}hhd", Anonymous::Change(uuid).c_str(), type); UpdateRelationship(deviceInfo.deviceId, type); for (const auto &device : listeners) { if (device == nullptr) { @@ -193,7 +198,7 @@ DeviceInfo SoftBusAdapter::GetLocalDevice() return DeviceInfo(); } std::string uuid = DevManager::GetInstance()->GetUuidByNodeId(std::string(info.networkId)); - LOG_DEBUG("[LocalDevice] id:%{private}s, name:%{private}s, type:%{private}d", ToBeAnonymous(uuid).c_str(), + LOG_DEBUG("[LocalDevice] id:%{public}s, name:%{public}s, type:%{public}d", Anonymous::Change(uuid).c_str(), info.deviceName, info.deviceTypeId); localInfo_ = { uuid, std::string(info.deviceName), std::to_string(info.deviceTypeId) }; return localInfo_; @@ -208,9 +213,8 @@ DeviceInfo SoftBusAdapter::GetLocalBasicInfo() const LOG_ERROR("GetLocalNodeDeviceInfo error"); return DeviceInfo(); } - LOG_DEBUG("[LocalBasicInfo] networkId:%{private}s, name:%{private}s, " - "type:%{private}d", - ToBeAnonymous(std::string(info.networkId)).c_str(), info.deviceName, info.deviceTypeId); + LOG_DEBUG("[LocalBasicInfo] networkId:%{public}s, name:%{public}s, type:%{public}d", + Anonymous::Change(std::string(info.networkId)).c_str(), info.deviceName, info.deviceTypeId); DeviceInfo localInfo = { std::string(info.networkId), std::string(info.deviceName), std::to_string(info.deviceTypeId) }; return localInfo; @@ -301,19 +305,6 @@ std::string SoftBusAdapter::ToNodeID(const std::string &nodeId) const return networkId; } -std::string SoftBusAdapter::ToBeAnonymous(const std::string &name) -{ - if (name.length() <= HEAD_SIZE) { - return DEFAULT_ANONYMOUS; - } - - if (name.length() < MIN_SIZE) { - return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN); - } - - return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE)); -} - std::shared_ptr SoftBusAdapter::GetInstance() { static std::once_flag onceFlag; @@ -561,7 +552,7 @@ void SoftBusAdapter::NotifyDataListeners( auto it = dataChangeListeners_.find(pipeInfo.pipeId); if (it != dataChangeListeners_.end()) { LOG_DEBUG("ready to notify, pipeName:%{public}s, deviceId:%{public}s.", pipeInfo.pipeId.c_str(), - ToBeAnonymous(deviceId).c_str()); + Anonymous::Change(deviceId).c_str()); DeviceInfo deviceInfo = { deviceId, "", "" }; it->second->OnMessage(deviceInfo, ptr, size, pipeInfo); return; @@ -606,7 +597,7 @@ void AppDataListenerWrap::OnServerBind(int32_t socket, PeerSocketInfo info) { softBusAdapter_->OnBind(socket, info); LOG_INFO("Server on bind, socket: %{public}d, peer networkId: %{public}s", socket, - SoftBusAdapter::ToBeAnonymous(info.networkId).c_str()); + Anonymous::Change(info.networkId).c_str()); } void AppDataListenerWrap::OnServerShutdown(int32_t socket, ShutdownReason reason) diff --git a/data_object/frameworks/innerkitsimpl/src/object_callback_stub.cpp b/data_object/frameworks/innerkitsimpl/src/object_callback_stub.cpp index 754be02c..e81f0a18 100644 --- a/data_object/frameworks/innerkitsimpl/src/object_callback_stub.cpp +++ b/data_object/frameworks/innerkitsimpl/src/object_callback_stub.cpp @@ -110,5 +110,27 @@ int ObjectChangeCallbackStub::OnRemoteRequest( } return IPCObjectStub::OnRemoteRequest(code, data, reply, option); } + +int ObjectProgressCallbackStub::OnRemoteRequest( + uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + ZLOGI("code:%{public}u, callingPid:%{public}d", code, IPCSkeleton::GetCallingPid()); + auto localDescriptor = GetDescriptor(); + auto remoteDescriptor = data.ReadInterfaceToken(); + if (remoteDescriptor != localDescriptor) { + ZLOGE("interface token is not equal"); + return -1; + } + if (code == COMPLETED) { + int32_t progress; + if (!ITypesUtil::Unmarshal(data, progress)) { + ZLOGE("Unmarshal failed"); + return -1; + } + Completed(progress); + return 0; + } + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} } // namespace DistributedObject } // namespace OHOS diff --git a/data_object/frameworks/innerkitsimpl/src/object_radar_reporter.cpp b/data_object/frameworks/innerkitsimpl/src/object_radar_reporter.cpp index e363a8fb..319a6b46 100644 --- a/data_object/frameworks/innerkitsimpl/src/object_radar_reporter.cpp +++ b/data_object/frameworks/innerkitsimpl/src/object_radar_reporter.cpp @@ -17,10 +17,6 @@ namespace OHOS::ObjectStore { using namespace ObjectStore; -constexpr char DOMAIN[] = "DISTDATAMGR"; -constexpr char EVENT_NAME[] = "DISTRIBUTED_DATA_OBJECT_BEHAVIOR"; -constexpr char ORG_PKG[] = "distributeddata"; - void RadarReporter::ReportStateFinished(std::string func, int32_t scene, int32_t stage, int32_t stageRes, int32_t state) { struct HiSysEventParam params[] = { diff --git a/data_object/frameworks/innerkitsimpl/src/object_service_proxy.cpp b/data_object/frameworks/innerkitsimpl/src/object_service_proxy.cpp index 934b0333..d3b6fb6e 100644 --- a/data_object/frameworks/innerkitsimpl/src/object_service_proxy.cpp +++ b/data_object/frameworks/innerkitsimpl/src/object_service_proxy.cpp @@ -53,7 +53,7 @@ int32_t ObjectServiceProxy::ObjectStoreSave(const std::string &bundleName, const } int32_t error = remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_SAVE), data, reply, mo); if (error != 0) { - ZLOGE("SendRequest returned %d", error); + ZLOGE("SendRequest returned %{public}d", error); return ERR_IPC; } return reply.ReadInt32(); @@ -85,7 +85,7 @@ int32_t ObjectServiceProxy::OnAssetChanged(const std::string &bundleName, const int32_t error = remoteObject->SendRequest( static_cast(ObjectCode::OBJECTSTORE_ON_ASSET_CHANGED), data, reply, mo); if (error != 0) { - ZLOGE("SendRequest returned %d", error); + ZLOGE("SendRequest returned %{public}d", error); return ERR_IPC; } return reply.ReadInt32(); @@ -115,7 +115,7 @@ int32_t ObjectServiceProxy::ObjectStoreRevokeSave( int32_t error = remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_REVOKE_SAVE), data, reply, mo); if (error != 0) { - ZLOGE("SendRequest returned %d", error); + ZLOGE("SendRequest returned %{public}d", error); return ERR_IPC; } return reply.ReadInt32(); @@ -145,7 +145,7 @@ int32_t ObjectServiceProxy::ObjectStoreRetrieve( int32_t error = remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_RETRIEVE), data, reply, mo); if (error != 0) { - ZLOGE("SendRequest returned %d", error); + ZLOGE("SendRequest returned %{public}d", error); return ERR_IPC; } return reply.ReadInt32(); @@ -175,7 +175,7 @@ int32_t ObjectServiceProxy::RegisterDataObserver(const std::string &bundleName, int32_t error = remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_REGISTER_OBSERVER), data, reply, mo); if (error != 0) { - ZLOGE("SendRequest returned %d", error); + ZLOGE("SendRequest returned %{public}d", error); return ERR_IPC; } return reply.ReadInt32(); @@ -204,12 +204,71 @@ int32_t ObjectServiceProxy::UnregisterDataChangeObserver(const std::string &bund int32_t error = remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_UNREGISTER_OBSERVER), data, reply, mo); if (error != 0) { - ZLOGE("SendRequest returned %d", error); + ZLOGE("SendRequest returned %{public}d", error); return ERR_IPC; } return reply.ReadInt32(); } +int32_t ObjectServiceProxy::RegisterProgressObserver(const std::string &bundleName, + const std::string &sessionId, sptr callback) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(ObjectServiceProxy::GetDescriptor())) { + ZLOGE("write descriptor failed"); + return ERR_IPC; + } + + if (!ITypesUtil::Marshal(data, bundleName, sessionId, callback)) { + ZLOGE("Marshalling failed, bundleName = %{public}s", bundleName.c_str()); + return ERR_IPC; + } + + MessageParcel reply; + MessageOption mo { MessageOption::TF_SYNC }; + sptr remoteObject = Remote(); + if (remoteObject == nullptr) { + LOG_ERROR("RegisterProgressObserver remoteObject is nullptr."); + return ERR_IPC; + } + int32_t error = + remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_REGISTER_PROGRESS), data, reply, mo); + if (error != 0) { + ZLOGE("SendRequest returned %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + +int32_t ObjectServiceProxy::UnregisterProgressObserver(const std::string &bundleName, const std::string &sessionId) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(ObjectServiceProxy::GetDescriptor())) { + ZLOGE("write descriptor failed"); + return ERR_IPC; + } + + if (!ITypesUtil::Marshal(data, bundleName, sessionId)) { + ZLOGE("Marshalling failed, bundleName = %{public}s", bundleName.c_str()); + return ERR_IPC; + } + + MessageParcel reply; + MessageOption mo { MessageOption::TF_SYNC }; + sptr remoteObject = Remote(); + if (remoteObject == nullptr) { + LOG_ERROR("UnregisterProgressObserver remoteObject is nullptr."); + return ERR_IPC; + } + int32_t error = + remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_UNREGISTER_PROGRESS), data, reply, mo); + if (error != 0) { + ZLOGE("SendRequest returned %{public}d", error); + return error; + } + return reply.ReadInt32(); +} + int32_t ObjectServiceProxy::BindAssetStore(const std::string &bundleName, const std::string &sessionId, Asset &asset, AssetBindInfo &bindInfo) { @@ -234,7 +293,7 @@ int32_t ObjectServiceProxy::BindAssetStore(const std::string &bundleName, const int32_t error = remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_BIND_ASSET_STORE), data, reply, mo); if (error != 0) { - ZLOGE("SendRequest returned %d", error); + ZLOGE("SendRequest returned %{public}d", error); return ERR_IPC; } return reply.ReadInt32(); @@ -263,7 +322,7 @@ int32_t ObjectServiceProxy::DeleteSnapshot(const std::string &bundleName, const int32_t error = remoteObject->SendRequest(static_cast(ObjectCode::OBJECTSTORE_DELETE_SNAPSHOT), data, reply, mo); if (error != 0) { - ZLOGE("SendRequest returned %d", error); + ZLOGE("SendRequest returned %{public}d", error); return ERR_IPC; } return reply.ReadInt32(); diff --git a/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/BUILD.gn b/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/BUILD.gn index 42477193..51c578a0 100644 --- a/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/BUILD.gn +++ b/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/BUILD.gn @@ -36,10 +36,15 @@ ohos_fuzztest("ObjectStoreFuzzTest") { configs = [ ":module_private_config" ] deps = [ "//foundation/distributeddatamgr/data_object/interfaces/innerkits:distributeddataobject_static", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", ] - external_deps = [ "hilog:libhilog" ] + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "access_token:libtokensetproc_shared", + "hilog:libhilog", + "kv_store:distributeddb", + ] } ############################################################################### diff --git a/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/objectstore_fuzzer.cpp b/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/objectstore_fuzzer.cpp index d75d55a2..530cf479 100644 --- a/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/objectstore_fuzzer.cpp +++ b/data_object/frameworks/innerkitsimpl/test/fuzztest/objectstore_fuzzer/objectstore_fuzzer.cpp @@ -15,12 +15,18 @@ #include "objectstore_fuzzer.h" +#include +#include #include #include + +#include "accesstoken_kit.h" #include "distributed_object.h" #include "distributed_objectstore.h" #include "flat_object_storage_engine.h" +#include "nativetoken_kit.h" #include "objectstore_errors.h" +#include "token_setproc.h" using namespace OHOS::ObjectStore; namespace OHOS { @@ -28,20 +34,61 @@ static DistributedObject *object_ = nullptr; static DistributedObjectStore *objectStore_ = nullptr; constexpr const char *SESSIONID = "123456"; constexpr const char *TABLESESSIONID = "654321"; +constexpr const char *BUNDLENAME = "com.example.myapplication"; +bool g_hasPermission = false; class TableWatcherImpl : public TableWatcher { public: - explicit TableWatcherImpl(const std::string &sessionId) : TableWatcher(sessionId) {} - void OnChanged( - const std::string &sessionid, const std::vector &changedData, bool enableTransfer) override; + explicit TableWatcherImpl(const std::string &sessionId) : TableWatcher(sessionId) + { + } + void OnChanged(const std::string &sessionid, const std::vector &changedData, + bool enableTransfer) override; virtual ~TableWatcherImpl(); }; -TableWatcherImpl::~TableWatcherImpl() {} -void TableWatcherImpl::OnChanged( - const std::string &sessionid, const std::vector &changedData, bool enableTransfer) {} +TableWatcherImpl::~TableWatcherImpl() +{ +} +void TableWatcherImpl::OnChanged(const std::string &sessionid, const std::vector &changedData, + bool enableTransfer) +{ +} + +class TestObjectWatcher : public ObjectWatcher { +public: + void OnChanged(const std::string &sessionid, const std::vector &changedData) override + { + } + virtual ~TestObjectWatcher() + { + } +}; + +class TestStatusNotifier : public StatusNotifier { +public: + void OnChanged(const std::string &sessionId, const std::string &networkId, const std::string &onlineStatus) override + { + } + virtual ~TestStatusNotifier() + { + } +}; + +std::string FilterSessionId(const std::string &input) +{ + std::string result; + std::copy_if(input.begin(), input.end(), std::back_inserter(result), [](char c) { + // Reservations: Numbers (0-9), letters (a-z, A-Z), underscores (_) + return std::isalnum(static_cast(c)) || c == '_'; + }); + if (result.empty()) { + result = "default_session_id"; + } + return result; +} uint32_t SetUpTestCase() { - std::string bundleName = "com.example.myapplication"; + std::string bundleName = BUNDLENAME; DistributedObjectStore *objectStore = nullptr; DistributedObject *object = nullptr; objectStore = DistributedObjectStore::GetInstance(bundleName); @@ -59,330 +106,380 @@ uint32_t SetUpTestCase() } } -bool PutDoubleFuzz(const uint8_t *data, size_t size) +void FuzzTestGetPermission() +{ + if (!g_hasPermission) { + uint64_t tokenId; + constexpr int perNum = 1; + const char *perms[perNum] = { "ohos.permission.DISTRIBUTED_DATASYNC" }; + + NativeTokenInfoParams infoInstance = { + .dcapsNum = 0, + .permsNum = 1, + .aclsNum = 0, + .dcaps = nullptr, + .perms = perms, + .acls = nullptr, + .processName = "objectfuzztest", + .aplStr = "normal", + }; + tokenId = GetAccessTokenId(&infoInstance); + SetSelfTokenID(tokenId); + OHOS::Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo(); + g_hasPermission = true; + } +} + +bool PutDoubleFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - double sval = static_cast(size); - std::string skey(data, data + size); - uint32_t ret = object_->PutDouble(skey, sval); - if (!ret) { - result = true; - } + double sval = provider.ConsumeFloatingPoint(); + std::string skey = provider.ConsumeRandomLengthString(10); + object_->PutDouble(skey, sval); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool PutBooleanFuzz(const uint8_t *data, size_t size) +bool PutBooleanFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - std::string skey(data, data + size); - uint32_t ret = object_->PutBoolean(skey, true); - if (!ret) { - result = true; - } - ret = object_->PutBoolean(skey, false); - if (ret != SUCCESS) { - result = false; - } + std::string skey = provider.ConsumeRandomLengthString(10); + bool val = provider.ConsumeBool(); + object_->PutBoolean(skey, val); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool PutStringFuzz(const uint8_t *data, size_t size) +bool PutStringFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - std::string skey(data, data + size); - std::string sval(data, data + size); - uint32_t ret = object_->PutString(skey, sval); - if (!ret) { - result = true; - } + std::string skey = provider.ConsumeRandomLengthString(10); + std::string sval = provider.ConsumeRandomLengthString(10); + object_->PutString(skey, sval); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool PutComplexFuzz(const uint8_t *data, size_t size) +bool PutComplexFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - size_t sum = 10; - std::string skey(data, data + size); + size_t sum = provider.ConsumeIntegralInRange(0, 100); + std::string skey = provider.ConsumeRandomLengthString(10); std::vector value; for (size_t i = 0; i < sum; i++) { - value.push_back(*data + i); - } - uint32_t ret = object_->PutComplex(skey, value); - if (!ret) { - result = true; + uint8_t val = 0; + value.push_back(val); } + object_->PutComplex(skey, value); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool GetDoubleFuzz(const uint8_t *data, size_t size) +bool GetDoubleFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - double sval = static_cast(size); - double val; - std::string skey(data, data + size); - if (SUCCESS == object_->PutDouble(skey, sval)) { - uint32_t ret = object_->GetDouble(skey, val); - if (!ret) { - result = true; - } - } + double sval = provider.ConsumeFloatingPoint(); + std::string skey = provider.ConsumeRandomLengthString(10); + object_->PutDouble(skey, sval); + double val = 0; + object_->GetDouble(skey, val); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool GetBooleanFuzz(const uint8_t *data, size_t size) +bool GetBooleanFuzz(FuzzedDataProvider &provider) { - bool val, result = false; if (SUCCESS != SetUpTestCase()) { return false; } - std::string skey(data, data + size); - if (SUCCESS == object_->PutBoolean(skey, true)) { - uint32_t ret = object_->GetBoolean(skey, val); - if (!ret) { - result = true; - } - } + std::string skey = provider.ConsumeRandomLengthString(10); + bool value = provider.ConsumeBool(); + object_->PutBoolean(skey, value); + bool val = false; + object_->GetBoolean(skey, val); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool GetStringFuzz(const uint8_t *data, size_t size) +bool GetStringFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - std::string skey(data, data + size); - std::string sval(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(10); + std::string sval = provider.ConsumeRandomLengthString(10); std::string val; - if (SUCCESS == object_->PutString(skey, sval)) { - uint32_t ret = object_->GetString(skey, val); - if (!ret) { - result = true; - } - } + object_->PutString(skey, sval); + object_->GetString(skey, val); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool GetComplexFuzz(const uint8_t *data, size_t size) +bool GetComplexFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - size_t sum = 10; - std::string skey(data, data + size); + + size_t sum = provider.ConsumeIntegralInRange(0, 10); + std::string skey = provider.ConsumeRandomLengthString(10); std::vector svalue; std::vector val; for (size_t i = 0; i < sum; i++) { - svalue.push_back(*data + i); - } - if (SUCCESS == object_->PutComplex(skey, svalue)) { - uint32_t ret = object_->GetComplex(skey, val); - if (!ret) { - result = true; - } + uint8_t val = 0; + svalue.push_back(val); } + object_->PutComplex(skey, svalue); + object_->GetComplex(skey, val); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool GetTypeFuzz(const uint8_t *data, size_t size) +bool GetTypeFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - std::string skey(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(10); Type val; - uint32_t ret = object_->GetType(skey, val); - if (!ret) { - result = true; - } + object_->GetType(skey, val); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool SaveFuzz(const uint8_t *data, size_t size) +bool SaveFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - std::string skey(data, data + size); - uint32_t ret = object_->Save(skey); - if (!ret) { - result = true; - } + std::string skey = provider.ConsumeRandomLengthString(10); + object_->Save(skey); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool SaveAndRevokeSaveFuzz(const uint8_t *data, size_t size) +bool SaveAndRevokeSaveFuzz(FuzzedDataProvider &provider) { - bool result = false; if (SUCCESS != SetUpTestCase()) { return false; } - std::string skey(data, data + size); - if (SUCCESS == object_->PutDouble(skey, static_cast(size))) { - uint32_t ret = object_->Save(skey); - if (!ret) { - result = false; - } - - if (object_->RevokeSave()) { - return false; - } - result = true; - } + std::string skey = provider.ConsumeRandomLengthString(10); + double sval = provider.ConsumeFloatingPoint(); + object_->PutDouble(skey, sval); + object_->Save(skey); + object_->RevokeSave(); objectStore_->DeleteObject(SESSIONID); - return result; + return true; } -bool CreateObjectV9Fuzz(const uint8_t *data, size_t size) +bool CreateObjectV9Fuzz(FuzzedDataProvider &provider) { - bool result = false; - std::string bundleName = "com.example.myapplication"; - DistributedObject *object = nullptr; + std::string bundleName = provider.ConsumeRandomLengthString(10); objectStore_ = DistributedObjectStore::GetInstance(bundleName); - uint32_t status = 0; - std::string skey(data, data + size); if (objectStore_ == nullptr) { return false; } - object = objectStore_->CreateObject(skey, status); - if (object == nullptr || status != SUCCESS) { - return false; - } - double val = static_cast(size); - if (SUCCESS == object->PutDouble(skey, val)) { - double getResult; - if (object->GetDouble(skey, getResult)) { - result = true; - } + uint32_t status = provider.ConsumeIntegral(); + std::string skey = FilterSessionId(provider.ConsumeRandomLengthString(10)); + auto object = objectStore_->CreateObject(skey, status); + if (object != nullptr) { + double val = provider.ConsumeFloatingPoint(); + object->PutDouble(skey, val); + double getResult = 0; + object->GetDouble(skey, getResult); } objectStore_->DeleteObject(skey); - return result; + return true; } -bool GetFuzz(const uint8_t *data, size_t size) +bool GetFuzz(FuzzedDataProvider &provider) { - std::string bundleName = "default1"; + std::string bundleName = provider.ConsumeRandomLengthString(10); objectStore_ = DistributedObjectStore::GetInstance(bundleName); if (objectStore_ == nullptr) { return false; } - uint32_t status = 0; - DistributedObject *object = objectStore_->CreateObject(SESSIONID, status); - if (object == nullptr) { - return false; - } - - DistributedObject *object2 = nullptr; - std::string skey(data, data + size); - if (!objectStore_->Get(skey, &object2)) { - return false; - } - - if (object != object2) { - return false; - } - objectStore_->DeleteObject(SESSIONID); + uint32_t status = provider.ConsumeIntegral(); + std::string skey = FilterSessionId(provider.ConsumeRandomLengthString(10)); + objectStore_->CreateObject(skey, status); + DistributedObject *object = nullptr; + objectStore_->Get(skey, &object); + objectStore_->DeleteObject(skey); return true; } -bool GetTableFuzz(const uint8_t *data, size_t size) +bool GetTableFuzz(FuzzedDataProvider &provider) { - bool result = false; - std::string skey(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(10); std::shared_ptr storageEngine = std::make_shared(); - storageEngine->Open("com.myapplication"); + storageEngine->Open(BUNDLENAME); storageEngine->CreateTable(TABLESESSIONID); std::map tableResult; - uint32_t ret = storageEngine->GetTable(skey, tableResult); - if (ret != SUCCESS) { - result = false; - } + storageEngine->GetTable(skey, tableResult); storageEngine->DeleteTable(TABLESESSIONID); - return result; + return true; } -bool NotifyStatusAndNotifyChangeFuzz(const uint8_t *data, size_t size) +bool NotifyStatusAndNotifyChangeFuzz(FuzzedDataProvider &provider) { std::shared_ptr storageEngine = std::make_shared(); - storageEngine->Open("com.example.myapplication"); - uint32_t ret = storageEngine->CreateTable(TABLESESSIONID); - if (ret != SUCCESS) { - return false; - } + storageEngine->Open(BUNDLENAME); + storageEngine->CreateTable(TABLESESSIONID); std::map> filteredData; - std::string skey(data, data + size); + std::string skey = FilterSessionId(provider.ConsumeRandomLengthString(10)); storageEngine->NotifyChange(skey, filteredData); storageEngine->NotifyStatus(skey, skey, skey); storageEngine->DeleteTable(TABLESESSIONID); return true; } -bool RegisterObserverAndUnRegisterObserverFuzz(const uint8_t *data, size_t size) +bool RegisterObserverAndUnRegisterObserverFuzz(FuzzedDataProvider &provider) { - bool result = true; std::shared_ptr storageEngine = std::make_shared(); - storageEngine->Open("com.example.myapplication"); - std::string skey(data, data + size); + storageEngine->Open(BUNDLENAME); + std::string skey = provider.ConsumeRandomLengthString(10); auto tableWatcherPtr = std::make_shared(SESSIONID); - uint32_t ret = storageEngine->RegisterObserver(skey, tableWatcherPtr); - if (ret != SUCCESS) { - result = false; + storageEngine->RegisterObserver(skey, tableWatcherPtr); + storageEngine->UnRegisterObserver(skey); + return true; +} + +bool BindAssetStoreFuzz(FuzzedDataProvider &provider) +{ + std::string bundleName = provider.ConsumeRandomLengthString(10); + objectStore_ = DistributedObjectStore::GetInstance(bundleName); + if (objectStore_ == nullptr) { + return false; } - ret = storageEngine->UnRegisterObserver(skey); - if (ret != SUCCESS) { - result = false; + uint32_t status = provider.ConsumeIntegral(); + std::string skey = FilterSessionId(provider.ConsumeRandomLengthString(10)); + auto object = objectStore_->CreateObject(skey, status); + if (object == nullptr) { + return false; } - return result; + AssetBindInfo bindInfo = { .storeName = provider.ConsumeRandomLengthString(10), + .tableName = provider.ConsumeRandomLengthString(10), + .primaryKey = { { "data1", 123 }, { "data2", "test1" } }, + .field = provider.ConsumeRandomLengthString(10), + .assetName = provider.ConsumeRandomLengthString(10) }; + object->BindAssetStore(skey, bindInfo); + objectStore_->DeleteObject(skey); + return true; +} + +bool GetSessionIdFuzz(FuzzedDataProvider &provider) +{ + std::string bundleName = provider.ConsumeRandomLengthString(10); + objectStore_ = DistributedObjectStore::GetInstance(bundleName); + if (objectStore_ == nullptr) { + return false; + } + uint32_t status = provider.ConsumeIntegral(); + std::string skey = FilterSessionId(provider.ConsumeRandomLengthString(10)); + auto object = objectStore_->CreateObject(skey, status); + if (object != nullptr) { + object->GetSessionId(); + } + objectStore_->DeleteObject(skey); + return true; +} + +bool WatchAndUnWatchFuzz(FuzzedDataProvider &provider) +{ + std::string bundleName = provider.ConsumeRandomLengthString(10); + objectStore_ = DistributedObjectStore::GetInstance(bundleName); + if (objectStore_ == nullptr) { + return false; + } + std::string skey = FilterSessionId(provider.ConsumeRandomLengthString(10)); + auto object = objectStore_->CreateObject(skey); + if (object == nullptr) { + return false; + } + objectStore_->Watch(object, std::make_shared()); + double sval = provider.ConsumeFloatingPoint(); + object->PutDouble(skey, sval); + objectStore_->UnWatch(object); + objectStore_->DeleteObject(skey); + return true; +} + +bool StatusNotifierFuzz(FuzzedDataProvider &provider) +{ + std::string bundleName = provider.ConsumeRandomLengthString(10); + objectStore_ = DistributedObjectStore::GetInstance(bundleName); + if (objectStore_ == nullptr) { + return false; + } + std::string skey = FilterSessionId(provider.ConsumeRandomLengthString(10)); + auto object = objectStore_->CreateObject(skey); + if (object == nullptr) { + return false; + } + objectStore_->SetStatusNotifier(std::make_shared()); + objectStore_->NotifyCachedStatus(skey); + objectStore_->DeleteObject(skey); + return true; } + +bool RandomSessionIdFuzz(FuzzedDataProvider &provider) +{ + std::string bundleName = provider.ConsumeRandomLengthString(10); + objectStore_ = DistributedObjectStore::GetInstance(bundleName); + if (objectStore_ == nullptr) { + return false; + } + std::string skey = provider.ConsumeRandomLengthString(); + auto object = objectStore_->CreateObject(skey); + if (object == nullptr) { + return false; + } + objectStore_->DeleteObject(skey); + return true; +} +} // namespace OHOS + +extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) +{ + OHOS::FuzzTestGetPermission(); + return 0; } /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - OHOS::PutDoubleFuzz(data, size); - OHOS::PutBooleanFuzz(data, size); - OHOS::PutStringFuzz(data, size); - OHOS::PutComplexFuzz(data, size); - OHOS::GetDoubleFuzz(data, size); - OHOS::GetBooleanFuzz(data, size); - OHOS::GetStringFuzz(data, size); - OHOS::GetComplexFuzz(data, size); - OHOS::GetTypeFuzz(data, size); - OHOS::SaveFuzz(data, size); - OHOS::SaveAndRevokeSaveFuzz(data, size); - OHOS::CreateObjectV9Fuzz(data, size); - OHOS::GetFuzz(data, size); - OHOS::GetTableFuzz(data, size); - OHOS::NotifyStatusAndNotifyChangeFuzz(data, size); - OHOS::RegisterObserverAndUnRegisterObserverFuzz(data, size); + FuzzedDataProvider provider(data, size); + OHOS::PutDoubleFuzz(provider); + OHOS::PutBooleanFuzz(provider); + OHOS::PutStringFuzz(provider); + OHOS::PutComplexFuzz(provider); + OHOS::GetDoubleFuzz(provider); + OHOS::GetBooleanFuzz(provider); + OHOS::GetStringFuzz(provider); + OHOS::GetComplexFuzz(provider); + OHOS::GetTypeFuzz(provider); + OHOS::SaveFuzz(provider); + OHOS::SaveAndRevokeSaveFuzz(provider); + OHOS::CreateObjectV9Fuzz(provider); + OHOS::GetFuzz(provider); + OHOS::GetTableFuzz(provider); + OHOS::NotifyStatusAndNotifyChangeFuzz(provider); + OHOS::RegisterObserverAndUnRegisterObserverFuzz(provider); + OHOS::BindAssetStoreFuzz(provider); + OHOS::GetSessionIdFuzz(provider); + OHOS::WatchAndUnWatchFuzz(provider); + OHOS::StatusNotifierFuzz(provider); + OHOS::RandomSessionIdFuzz(provider); /* Run your code on data */ return 0; } \ No newline at end of file diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/BUILD.gn b/data_object/frameworks/innerkitsimpl/test/unittest/BUILD.gn index 4f3f4b89..eeb8c363 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/BUILD.gn +++ b/data_object/frameworks/innerkitsimpl/test/unittest/BUILD.gn @@ -38,14 +38,17 @@ config("module_private_config") { common_external_deps = [ "ability_base:want", "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "access_token:libtoken_setproc", "bundle_framework:appexecfwk_core", "c_utils:utils", + "cJSON:cjson", "device_manager:devicemanagersdk", "dmsfwk:distributed_sdk", "dsoftbus:softbus_client", "ffmpeg:libohosffmpeg", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", @@ -83,10 +86,12 @@ ohos_unittest("NativeObjectStoreTest") { external_deps = common_external_deps + defines = [ + "private=public", + ] + deps = [ "//foundation/distributeddatamgr/data_object/interfaces/innerkits:distributeddataobject_static", - "//third_party/googletest:gmock", - "//third_party/googletest:gtest_main", ] } @@ -99,8 +104,8 @@ ohos_unittest("ObjectTypesUtilTest") { ] configs = [ ":module_private_config" ] - external_deps = common_external_deps deps = [ "${data_object_base_path}/interfaces/innerkits:distributeddataobject_static" ] + external_deps = common_external_deps } ohos_unittest("ObjectServiceProxyTest") { @@ -113,8 +118,8 @@ ohos_unittest("ObjectServiceProxyTest") { ] configs = [ ":module_private_config" ] - external_deps = common_external_deps deps = [ "${data_object_base_path}/interfaces/innerkits:distributeddataobject_static" ] + external_deps = common_external_deps } ohos_unittest("ObjectCallbackStubTest") { @@ -155,6 +160,7 @@ ohos_unittest("AssetChangeTimerTest") { "${data_object_base_path}/frameworks/jskitsimpl/src/adaptor/notifier_impl.cpp", "${data_object_base_path}/frameworks/jskitsimpl/src/common/js_util.cpp", "${data_object_base_path}/frameworks/jskitsimpl/src/common/uv_queue.cpp", + "${data_object_base_path}/frameworks/jskitsimpl/src/adaptor/progress_notifier_impl.cpp", ] cflags_cc = [ "-DHILOG_ENABLE" ] @@ -190,14 +196,32 @@ ohos_unittest("ClientAdaptorTest") { "private = public", "protected = public", ] - deps = [ "${data_object_base_path}/interfaces/innerkits:distributeddataobject_static" ] } ohos_unittest("DistributedObjectStoreImplTest") { module_out_path = module_output_path sources = [ + "${data_object_base_path}/frameworks/innerkitsimpl/src/adaptor/asset_change_timer.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/adaptor/client_adaptor.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/adaptor/distributed_object_impl.cpp", "${data_object_base_path}/frameworks/innerkitsimpl/src/adaptor/distributed_object_store_impl.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/adaptor/flat_object_storage_engine.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/adaptor/flat_object_store.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/adaptor/object_callback_impl.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/app_device_handler.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/app_pipe_handler.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/app_pipe_mgr.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/ark_communication_provider.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/communication_provider.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/communication_provider_impl.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/dev_manager.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/process_communicator_impl.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/object_callback_stub.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/object_radar_reporter.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/object_service_proxy.cpp", + "${data_object_base_path}/frameworks/innerkitsimpl/src/object_types_util.cpp", "${data_object_base_path}/frameworks/innerkitsimpl/test/unittest/src/distributed_object_store_impl_test.cpp", ] @@ -211,7 +235,6 @@ ohos_unittest("DistributedObjectStoreImplTest") { "private = public", "protected = public", ] - deps = [ "${data_object_base_path}/interfaces/innerkits:distributeddataobject_static" ] } ohos_unittest("FlatObjectStoreTest") { @@ -278,6 +301,21 @@ ohos_unittest("AppDeviceHandlerTest") { deps = [ "${data_object_base_path}/interfaces/innerkits:distributeddataobject_static" ] } +ohos_unittest("ObjectTaskSchedulerTest") { + module_out_path = module_output_path + + sources = [ "${data_object_base_path}/frameworks/innerkitsimpl/test/unittest/src/task_scheduler_test.cpp", ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "c_utils:utils", + "googletest:gtest", + "hilog:libhilog", + ] + +} + group("unittest") { testonly = true deps = [] @@ -292,5 +330,6 @@ group("unittest") { ":ObjectCallbackStubTest", ":ObjectServiceProxyTest", ":ObjectTypesUtilTest", + ":ObjectTaskSchedulerTest", ] } diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/client_adaptor_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/client_adaptor_test.cpp index db0b1a06..039fc515 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/src/client_adaptor_test.cpp +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/client_adaptor_test.cpp @@ -106,6 +106,5 @@ HWTEST_F(ClientAdaptorTest, RegisterClientDeathListener_002, TestSize.Level1) sptr remoteObject = new IPCObjectStub(); uint32_t ret = clientAdaptor.RegisterClientDeathListener(appId, remoteObject); EXPECT_EQ(ret, SUCCESS); - delete remoteObject; } } diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/communicator_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/communicator_test.cpp index 31fbf902..8945aefa 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/src/communicator_test.cpp +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/communicator_test.cpp @@ -37,10 +37,6 @@ using namespace OHOS::Security::AccessToken; using namespace OHOS::ObjectStore; namespace { -constexpr int32_t HEAD_SIZE = 3; -constexpr const char *REPLACE_CHAIN = "***"; -constexpr const char *DEFAULT_ANONYMOUS = "******"; - class NativeCommunicatorTest : public testing::Test { public: static void SetUpTestCase(void); @@ -305,32 +301,6 @@ HWTEST_F(NativeCommunicatorTest, SoftBusAdapter_StopWatchDataChange_002, TestSiz EXPECT_EQ(Status::ERROR, ret); } -/** - * @tc.name: SoftBusAdapter_ToBeAnonymous_001 - * @tc.desc: test SoftBusAdapter ToBeAnonymous. - * @tc.type: FUNC - */ -HWTEST_F(NativeCommunicatorTest, SoftBusAdapter_ToBeAnonymous_001, TestSize.Level1) -{ - std::string name = "na"; - SoftBusAdapter softBusAdapter; - auto ret = softBusAdapter.ToBeAnonymous(name); - EXPECT_EQ(DEFAULT_ANONYMOUS, ret); -} - -/** - * @tc.name: SoftBusAdapter_ToBeAnonymous_002 - * @tc.desc: test SoftBusAdapter ToBeAnonymous. - * @tc.type: FUNC - */ -HWTEST_F(NativeCommunicatorTest, SoftBusAdapter_ToBeAnonymous_002, TestSize.Level1) -{ - std::string name = "name"; - SoftBusAdapter softBusAdapter; - auto ret = softBusAdapter.ToBeAnonymous(name); - EXPECT_EQ(name.substr(0, HEAD_SIZE) + REPLACE_CHAIN, ret); -} - /** * @tc.name: SoftBusAdapter_GetLocalBasicInfo_001 * @tc.desc: test SoftBusAdapter GetLocalBasicInfo. @@ -569,4 +539,32 @@ HWTEST_F(NativeCommunicatorTest, DevManager_GetLocalDevice_001, TestSize.Level1) DevManager::DetailInfo detailInfo = devManager->GetLocalDevice(); EXPECT_EQ(detailInfo.networkId, ""); } + +/** +* @tc.name: DestructedSoftBusAdapter001 +* @tc.desc: Test that the destructor cleans the dataCaches when bytesMsg.ptr is not nullptr. +* @tc.type: FUNC +*/ +HWTEST_F(NativeCommunicatorTest, DestructedSoftBusAdapter001, TestSize.Level1) +{ + auto softBusAdapter = std::make_shared(); + uint32_t length = 10; + uint8_t *data = new uint8_t[length]; + SoftBusAdapter::BytesMsg bytesMsg = { data, length }; + softBusAdapter->dataCaches_["device1"] = { bytesMsg }; + EXPECT_FALSE(softBusAdapter->dataCaches_.empty()); +} + +/** +* @tc.name: DestructedSoftBusAdapter002 +* @tc.desc: Test that the destructor does not clean the dataCaches when bytesMsg.ptr is nullptr. +* @tc.type: FUNC +*/ +HWTEST_F(NativeCommunicatorTest, DestructedSoftBusAdapter002, TestSize.Level1) +{ + auto softBusAdapter = std::make_shared(); + SoftBusAdapter::BytesMsg bytesMsg = { nullptr, 0 }; + softBusAdapter->dataCaches_["device2"] = { bytesMsg }; + EXPECT_FALSE(softBusAdapter->dataCaches_.empty()); +} } diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/distributed_object_store_impl_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/distributed_object_store_impl_test.cpp index 6d2791d3..4892a2a2 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/src/distributed_object_store_impl_test.cpp +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/distributed_object_store_impl_test.cpp @@ -96,4 +96,20 @@ HWTEST_F(DistributedObjectStoreImplTest, FindChangedAssetKey_001, TestSize.Level bool ret = watcherProxy.FindChangedAssetKey(changedKey, assetKey); EXPECT_EQ(ret, false); } + +/** + * @tc.name: SetProgressNotifier001 + * @tc.desc: test SetProgressNotifier. + * @tc.type: FUNC + */ + +HWTEST_F(DistributedObjectStoreImplTest, SetProgressNotifier001, TestSize.Level1) +{ + std::string bundleName = "default"; + std::string sessionId = "123456"; + auto objectStore = new DistributedObjectStoreImpl(nullptr); + auto progressNotifierPtr = std::shared_ptr(); + bool ret = objectStore->SetProgressNotifier(progressNotifierPtr); + EXPECT_EQ(ret, true); +} } diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/object_callback_stub_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/object_callback_stub_test.cpp index 548ce8fd..75753ad6 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/src/object_callback_stub_test.cpp +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/object_callback_stub_test.cpp @@ -75,4 +75,52 @@ HWTEST_F(ObjectCallbackStubTest, OnRemoteRequest_001, TestSize.Level1) int ret = objectChangeCallback.OnRemoteRequest(code, data, reply, option); EXPECT_EQ(ret, -1); } + +/** + * @tc.name: OnRemoteRequest_002 + * @tc.desc: Abnormal test for OnRemoteRequest, code is 0 + * @tc.type: FUNC + */ + +HWTEST_F(ObjectCallbackStubTest, OnRemoteRequest_002, TestSize.Level1) +{ + uint32_t code = 0; + OHOS::MessageParcel data; + OHOS::MessageParcel reply; + OHOS::MessageOption option; + const std::function callback; + ObjectProgressCallback objectProgressCallback(callback); + OHOS::IPCObjectStub objectStub; + int ret = objectProgressCallback.OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(ret, -1); + std::u16string dataObjectInterfaceToken = u"OHOS.DistributedObject.IObjectProgressCallback"; + data.WriteInterfaceToken(dataObjectInterfaceToken); + ret = objectProgressCallback.OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(ret, -1); +} + +/** + * @tc.name: OnRemoteRequest_003 + * @tc.desc: OnRemoteRequest test + * @tc.type: FUNC + */ + +HWTEST_F(ObjectCallbackStubTest, OnRemoteRequest_003, TestSize.Level1) +{ + uint32_t code = 0; + OHOS::MessageParcel data; + OHOS::MessageParcel reply; + OHOS::MessageOption option; + const std::function callback; + ObjectProgressCallback objectProgressCallback(callback); + OHOS::IPCObjectStub objectStub; + std::u16string dataObjectInterfaceToken = u"OHOS.DistributedObject.IObjectProgressCallback"; + data.WriteInterfaceToken(dataObjectInterfaceToken); + uint32_t code_1 = 1; + auto ret = objectProgressCallback.OnRemoteRequest(code_1, data, reply, option); + int32_t progress = 100; + OHOS::ITypesUtil::Marshal(data, progress); + ret = objectProgressCallback.OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(ret, -1); +} } diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/object_service_proxy_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/object_service_proxy_test.cpp index 4d736b42..fd8896c3 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/src/object_service_proxy_test.cpp +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/object_service_proxy_test.cpp @@ -117,4 +117,34 @@ HWTEST_F(ObjectServiceProxyTest, BindAssetStore_001, TestSize.Level1) int32_t ret = objectServiceProxy.BindAssetStore(bundleName, sessionId, asset, bindInfo); EXPECT_EQ(ret, OHOS::ObjectStore::ERR_IPC); } + +/** + * @tc.name: RegisterProgressObserver_001 + * @tc.desc: Abnormal test for RegisterProgressObserver, impl is nullptr + * @tc.type: FUNC + */ +HWTEST_F(ObjectServiceProxyTest, RegisterProgressObserver_001, TestSize.Level1) +{ + string bundleName = "com.example.myapplication"; + string sessionId = "123456"; + sptr impl; + ObjectServiceProxy objectServiceProxy(impl); + int32_t ret = objectServiceProxy.RegisterProgressObserver(bundleName, sessionId, impl); + EXPECT_EQ(ret, OHOS::ObjectStore::ERR_IPC); +} + +/** + * @tc.name: UnregisterProgressObserver_001 + * @tc.desc: Abnormal test for UnregisterProgressObserver, impl is nullptr + * @tc.type: FUNC + */ +HWTEST_F(ObjectServiceProxyTest, UnregisterProgressObserver_001, TestSize.Level1) +{ + string bundleName = "com.example.myapplication"; + string sessionId = "123456"; + sptr impl; + ObjectServiceProxy objectServiceProxy(impl); + int32_t ret = objectServiceProxy.UnregisterProgressObserver(bundleName, sessionId); + EXPECT_EQ(ret, OHOS::ObjectStore::ERR_IPC); +} } diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/object_store_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/object_store_test.cpp index 55c04bdc..d14b8861 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/src/object_store_test.cpp +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/object_store_test.cpp @@ -28,6 +28,7 @@ #include "nativetoken_kit.h" #include "object_storage_engine.h" #include "objectstore_errors.h" +#include "store_errno.h" #include "token_setproc.h" using namespace testing::ext; @@ -69,6 +70,18 @@ void StatusNotifierImpl::OnChanged(const std::string &sessionId, { } +class ProgressNotifierImpl : public ProgressWatcher { +public: +void OnChanged(const std::string &sessionId, int32_t progress) override; +virtual ~ProgressNotifierImpl(); +}; +ProgressNotifierImpl::~ProgressNotifierImpl() +{ +} + +void ProgressNotifierImpl::OnChanged(const std::string &sessionId, int32_t progress) +{ +} void GrantPermissionNative() { const char **perms = new const char *[3]; @@ -129,10 +142,10 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStore_Create_Destroy_001, TestS std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = objectStore->DeleteObject(sessionId); EXPECT_EQ(SUCCESS, ret); @@ -163,10 +176,10 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStore_Create_Destroy_003, TestS std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); DistributedObject *object2 = objectStore->CreateObject(sessionId); EXPECT_EQ(nullptr, object2); @@ -185,11 +198,11 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStore_Create_Destroy_004, TestS std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); uint32_t status = -1; DistributedObject *object = objectStore->CreateObject(sessionId, status); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); EXPECT_EQ(SUCCESS, status); uint32_t ret = objectStore->DeleteObject(sessionId); @@ -206,7 +219,7 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStoreImpl_CreateObject_001, Tes std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(""); EXPECT_EQ(nullptr, object); @@ -240,7 +253,7 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStoreImpl_CreateObject_003, Tes std::string bundleName = "default"; std::string sessionId = ""; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); uint32_t status = -1; DistributedObject *object = objectStore->CreateObject(sessionId, status); @@ -261,10 +274,10 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStoreImpl_Get_001, TestSize.Lev std::string bundleName = "default"; std::string sessionId = "sessionId"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); DistributedObject *Object1 = nullptr; uint32_t status = objectStore->Get("", &Object1); @@ -312,10 +325,10 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStoreImpl_Watch_002, TestSize.L std::string bundleName = "default"; std::string sessionId = "sessionId"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); std::shared_ptr watcher = std::make_shared(); uint32_t status = objectStore->Watch(object, watcher); @@ -353,10 +366,10 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStore_Get_001, TestSize.Level1) std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); DistributedObject *object2 = nullptr; uint32_t ret = objectStore->Get(sessionId, &object2); @@ -377,10 +390,10 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStore_Watch_UnWatch_001, TestSi std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); auto watcherPtr = std::shared_ptr(); uint32_t ret = objectStore->Watch(object, watcherPtr); @@ -403,9 +416,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObjectStore_SetStatusNotifier_001, Te std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); auto notifierPtr = std::shared_ptr(); uint32_t ret = objectStore->SetStatusNotifier(notifierPtr); @@ -426,9 +439,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_Double_001, TestSize.Level1) std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = object->PutDouble("salary", SALARY); EXPECT_EQ(ret, 0); @@ -452,9 +465,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetDouble_001, TestSize.Level1 std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); double value = 0.0; uint32_t ret = object->GetDouble("salary", value); @@ -475,9 +488,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_Boolean_001, TestSize.Level1) std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = object->PutBoolean("isTrue", true); EXPECT_EQ(SUCCESS, ret); @@ -501,9 +514,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetBoolean_001, TestSize.Level std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); bool value = false; uint32_t ret = object->GetBoolean("isTrue", value); @@ -524,9 +537,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_String_001, TestSize.Level1) std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = object->PutString("name", "zhangsan"); EXPECT_EQ(SUCCESS, ret); @@ -550,9 +563,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetString_001, TestSize.Level1 std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); std::string value = ""; uint32_t ret = object->GetString("name", value); @@ -573,9 +586,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetSessionId_001, TestSize.Lev std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); std::string getSessionId = object->GetSessionId(); EXPECT_EQ(sessionId, getSessionId); uint32_t ret = objectStore->DeleteObject(sessionId); @@ -592,9 +605,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_PutComplex_001, TestSize.Level std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); std::vector value = {'z', 'h'}; uint32_t ret = object->PutComplex("name", value); @@ -613,9 +626,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetComplex_001, TestSize.Level std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); std::vector value = {'z', 'h'}; uint32_t ret = object->PutComplex("name", value); @@ -636,9 +649,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetComplex_002, TestSize.Level std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); std::vector value = {'z', 'h'}; uint32_t ret = object->GetComplex("name", value); @@ -657,9 +670,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_SetAsset_001, TestSize.Level1) std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = object->PutString("attachment.name", "1.txt"); EXPECT_EQ(SUCCESS, ret); @@ -687,9 +700,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_TestSetSessionId_001, TestSize { auto testSetSessionId = [] (std::string bundleName, std::string sessionId) { DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = objectStore->DeleteObject(sessionId); EXPECT_EQ(SUCCESS, ret); @@ -712,9 +725,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetType_001, TestSize.Level1) std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = object->PutString("name", "zhangsan"); EXPECT_EQ(SUCCESS, ret); @@ -749,9 +762,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_GetType_002, TestSize.Level1) std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); Type type; uint32_t ret = object->GetType("name", type); @@ -772,9 +785,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_Save_RevokeSave_001, TestSize. std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = object->PutString("name", "zhangsan"); @@ -802,9 +815,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_Save_RevokeSave_002, TestSize. { auto testSaveAndRevokeSave = [](std::string bundleName, std::string sessionId) { DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = object->PutString("name", "zhangsan"); EXPECT_EQ(SUCCESS, ret); @@ -839,9 +852,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_Save_RevokeSave_003, TestSize. std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = object->RevokeSave(); EXPECT_EQ(SUCCESS, ret); @@ -1226,7 +1239,7 @@ HWTEST_F(NativeObjectStoreTest, CacheManager_Save_001, TestSize.Level1) std::map> objectData; CacheManager cacheManager; auto ret = cacheManager.Save(bundleName, sessionId, deviceId, objectData); - EXPECT_EQ(OBJECT_PERMISSION_DENIED, ret); + EXPECT_EQ(OHOS::DistributedKv::Status::INVALID_ARGUMENT, ret); } /** @@ -1240,7 +1253,7 @@ HWTEST_F(NativeObjectStoreTest, CacheManager_RevokeSave_001, TestSize.Level1) std::string sessionId = ""; CacheManager cacheManager; auto ret = cacheManager.RevokeSave(bundleName, sessionId); - EXPECT_EQ(OBJECT_PERMISSION_DENIED, ret); + EXPECT_EQ(SUCCESS, ret); } /** @@ -1256,7 +1269,7 @@ HWTEST_F(NativeObjectStoreTest, CacheManager_ResumeObject_001, TestSize.Level1) std::function> &data, bool allReady)> callback = [](const std::map> &data, bool allReady) {}; auto ret = cacheManager.ResumeObject(bundleName, sessionId, callback); - EXPECT_EQ(OBJECT_PERMISSION_DENIED, ret); + EXPECT_EQ(OHOS::DistributedKv::Status::KEY_NOT_FOUND, ret); } /** @@ -1272,7 +1285,7 @@ HWTEST_F(NativeObjectStoreTest, CacheManager_SubscribeDataChange_001, TestSize.L std::function> &data, bool allReady)> callback = [](const std::map> &data, bool allReady) {}; auto ret = cacheManager.SubscribeDataChange(bundleName, sessionId, callback); - EXPECT_EQ(OBJECT_PERMISSION_DENIED, ret); + EXPECT_EQ(SUCCESS, ret); } /** @@ -1286,7 +1299,7 @@ HWTEST_F(NativeObjectStoreTest, CacheManager_UnregisterDataChange_001, TestSize. std::string sessionId = ""; CacheManager cacheManager; auto ret = cacheManager.UnregisterDataChange(bundleName, sessionId); - EXPECT_EQ(OBJECT_PERMISSION_DENIED, ret); + EXPECT_EQ(SUCCESS, ret); } /** @@ -1311,10 +1324,10 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_NotifyCachedStatus_001, TestSi std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); uint32_t status = 0; DistributedObject *object = objectStore->CreateObject(sessionId, status); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); EXPECT_EQ(SUCCESS, status); objectStore->NotifyCachedStatus(sessionId); uint32_t ret = objectStore->DeleteObject(sessionId); @@ -1331,9 +1344,9 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_UnWatch_001, TestSize.Level1) std::string bundleName = "default"; std::string sessionId = "123456"; DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); - EXPECT_NE(nullptr, objectStore); + ASSERT_NE(nullptr, objectStore); DistributedObject *object = objectStore->CreateObject(sessionId); - EXPECT_NE(nullptr, object); + ASSERT_NE(nullptr, object); uint32_t ret = objectStore->UnWatch(nullptr); EXPECT_EQ(ERR_NULL_OBJECT, ret); ret = objectStore->DeleteObject(sessionId); @@ -1669,4 +1682,196 @@ HWTEST_F(NativeObjectStoreTest, DistributedObject_UpdateItem_002, TestSize.Level ret = storageEngine->DeleteTable(sessionId); EXPECT_EQ(SUCCESS, ret); } + +/** + * @tc.name: DistributedObjectStore_SetProgressNotifier_001 + * @tc.desc: test DistributedObjectStore SetProgressNotifier. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, DistributedObjectStore_SetProgressNotifier_001, TestSize.Level1) +{ + std::string bundleName = "default"; + std::string sessionId = "123456"; + DistributedObjectStore *objectStore = DistributedObjectStore::GetInstance(bundleName); + ASSERT_NE(nullptr, objectStore); + DistributedObject *object = objectStore->CreateObject(sessionId); + ASSERT_NE(nullptr, object); + objectStore->NotifyProgressStatus(sessionId); + auto progressNotifierPtr = std::shared_ptr(); + auto ret = objectStore->SetProgressNotifier(progressNotifierPtr); + EXPECT_EQ(ret, 0); +} + +/** + * @tc.name: DistributedObject_SetProgressNotifier_002 + * @tc.desc: test FlatObjectStorageEngine SetProgressNotifier. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, DistributedObject_SetProgressNotifier_002, TestSize.Level1) +{ + std::string bundleName = "default"; + std::string sessionId = "123456"; + std::shared_ptr storageEngine = std::make_shared(); + storageEngine->isOpened_ = true; + auto progressNotifier = std::make_shared(); + uint32_t ret = storageEngine->SetProgressNotifier(progressNotifier); + EXPECT_EQ(SUCCESS, ret); +} + +/** + * @tc.name: DistributedObject_SetProgressNotifier_003 + * @tc.desc: test FlatObjectStorageEngine SetProgressNotifier, storageEngine is not open. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, DistributedObject_SetProgressNotifier_003, TestSize.Level1) +{ + std::shared_ptr storageEngine = std::make_shared(); + auto progressNotifier = std::make_shared(); + storageEngine->isOpened_ = false; + uint32_t ret = storageEngine->SetProgressNotifier(progressNotifier); + EXPECT_EQ(ERR_DB_NOT_INIT, ret); +} + +/** + * @tc.name: DistributedObject_NotifyProgress_001 + * @tc.desc: test FlatObjectStorageEngine NotifyProgress. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, DistributedObject_NotifyProgress_001, TestSize.Level1) +{ + std::shared_ptr storageEngine = std::make_shared(); + std::string sessionId = "123456"; + int32_t progress = 100; + auto ret = storageEngine->NotifyProgress(sessionId, progress); + EXPECT_EQ(ret, false); + auto progressNotifier = std::make_shared(); + storageEngine->isOpened_ = true; + ret = storageEngine->SetProgressNotifier(progressNotifier); + ret = storageEngine->NotifyProgress(sessionId, progress); + EXPECT_EQ(ret, true); +} + +/** + * @tc.name: CacheManager_SubscribeProgressChange_001 + * @tc.desc: test CacheManager SubscribeProgressChange. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, CacheManager_SubscribeProgressChange_001, TestSize.Level1) +{ + std::string bundleName = ""; + std::string sessionId = ""; + CacheManager cacheManager; + std::function callback = [sessionId, this](int32_t progress) {}; + auto ret = cacheManager.SubscribeProgressChange(bundleName, sessionId, callback); + EXPECT_EQ(SUCCESS, ret); +} + +/** + * @tc.name: CacheManager_UnregisterProgressChange_001 + * @tc.desc: test CacheManager UnregisterProgressChange. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, CacheManager_UnregisterProgressChange_001, TestSize.Level1) +{ + std::string bundleName = ""; + std::string sessionId = ""; + CacheManager cacheManager; + auto ret = cacheManager.UnregisterProgressChange(bundleName, sessionId); + EXPECT_EQ(SUCCESS, ret); +} + +/** + * @tc.name: FlatObjectStore_CheckProgressCache_001 + * @tc.desc: test FlatObjectStore CheckProgressCache. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, FlatObjectStore_CheckProgressCache_001, TestSize.Level1) +{ + std::string sessionId = "session001"; + std::string bundleName = "default001"; + std::shared_ptr flatObjectStore = std::make_shared(bundleName); + uint32_t ret = flatObjectStore->CreateObject(sessionId); + EXPECT_EQ(SUCCESS, ret); + flatObjectStore->CheckProgressCache(sessionId); + flatObjectStore->SubscribeProgressChange(sessionId); + flatObjectStore->CheckProgressCache(sessionId); + int32_t progress = 100; + flatObjectStore->progressInfoCache_[sessionId] = progress; + flatObjectStore->CheckProgressCache(sessionId); + auto progressNotifier = std::make_shared(); + std::shared_ptr storageEngine = std::make_shared(); + storageEngine->isOpened_ = true; + ret = storageEngine->SetProgressNotifier(progressNotifier); + ret = storageEngine->NotifyProgress(sessionId, progress); + EXPECT_EQ(ret, true); + flatObjectStore->CheckProgressCache(sessionId); + ret = flatObjectStore->Delete(sessionId); + EXPECT_EQ(SUCCESS, ret); +} + +/** + * @tc.name: FlatObjectStore_SubscribeProgressChange_001 + * @tc.desc: test FlatObjectStore SubscribeProgressChange. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, FlatObjectStore_SubscribeProgressChange_001, TestSize.Level1) +{ + std::string sessionId = "session001"; + std::string bundleName = "default001"; + std::shared_ptr flatObjectStore = std::make_shared(bundleName); + uint32_t ret = flatObjectStore->CreateObject(sessionId); + EXPECT_EQ(SUCCESS, ret); + flatObjectStore->SubscribeProgressChange(sessionId); + ret = flatObjectStore->Delete(sessionId); + EXPECT_EQ(SUCCESS, ret); +} + +/** + * @tc.name: FlatObjectStore_SetProgressNotifier_001 + * @tc.desc: test FlatObjectStore SetProgressNotifier. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, FlatObjectStore_SetProgressNotifier_001, TestSize.Level1) +{ + std::string sessionId = "session001"; + std::string bundleName = "default001"; + std::shared_ptr flatObjectStore = std::make_shared(bundleName); + uint32_t ret = flatObjectStore->CreateObject(sessionId); + EXPECT_EQ(SUCCESS, ret); + auto progressNotifier = std::make_shared(); + std::shared_ptr storageEngine = std::make_shared(); + flatObjectStore->storageEngine_->isOpened_ = true; + flatObjectStore->SetProgressNotifier(progressNotifier); + flatObjectStore->storageEngine_->isOpened_ = false; + flatObjectStore->SetProgressNotifier(progressNotifier); + ret = flatObjectStore->Delete(sessionId); + EXPECT_EQ(SUCCESS, ret); +} + +/** + * @tc.name: FlatObjectStore_SetProgressNotifier_002 + * @tc.desc: test FlatObjectStore SetProgressNotifier,storageEngine is not open. + * @tc.type: FUNC + */ +HWTEST_F(NativeObjectStoreTest, FlatObjectStore_SetProgressNotifier_002, TestSize.Level1) +{ + std::string sessionId = "session001"; + std::string bundleName = "default001"; + std::shared_ptr flatObjectStore = std::make_shared(bundleName); + uint32_t ret = flatObjectStore->CreateObject(sessionId); + EXPECT_EQ(SUCCESS, ret); + auto progressNotifier = std::make_shared(); + std::shared_ptr storageEngine = std::make_shared(); + auto notifier = std::shared_ptr(); + std::shared_ptr progressNotifierProxy = std::make_shared(notifier); + int32_t progress = 100; + progressNotifierProxy->OnChanged(sessionId, progress); + progressNotifierProxy->notifier = notifier; + progressNotifierProxy->OnChanged(sessionId, progress); + storageEngine->isOpened_ = false; + flatObjectStore->SetProgressNotifier(progressNotifier); + EXPECT_EQ(SUCCESS, ret); + ret = flatObjectStore->Delete(sessionId); + EXPECT_EQ(SUCCESS, ret); +} } // namespace diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/task_scheduler_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/task_scheduler_test.cpp new file mode 100644 index 00000000..11f7f4e0 --- /dev/null +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/task_scheduler_test.cpp @@ -0,0 +1,267 @@ +/* + * 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_scheduler.h" + +#include + +#include "block_data.h" +namespace OHOS::Test { +using namespace testing::ext; +using namespace OHOS; +using duration = std::chrono::steady_clock::duration; +class TaskSchedulerTest : public testing::Test { +public: + static constexpr uint32_t SHORT_INTERVAL = 100; // ms + static constexpr uint32_t LONG_INTERVAL = 1; // s + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() { } +}; + +/** + * @tc.name: At + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: ht + */ +HWTEST_F(TaskSchedulerTest, At, TestSize.Level0) +{ + TaskScheduler taskScheduler("atTest"); + auto expiredTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(SHORT_INTERVAL); + int testData = 10; + auto blockData = std::make_shared>(LONG_INTERVAL, testData); + auto atTaskId1 = taskScheduler.At(expiredTime, [blockData]() { + int testData = 11; + blockData->SetValue(testData); + }); + ASSERT_EQ(blockData->GetValue(), 11); + blockData->Clear(); + expiredTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(SHORT_INTERVAL); + auto atTaskId2 = taskScheduler.At(expiredTime, [blockData]() { + int testData = 12; + blockData->SetValue(testData); + }); + ASSERT_EQ(blockData->GetValue(), 12); + ASSERT_NE(atTaskId1, atTaskId2); +} + +/** + * @tc.name: Every + * @tc.desc:execute task periodically with duration + * @tc.type: FUNC + * @tc.require: + * @tc.author: ht + */ +HWTEST_F(TaskSchedulerTest, ExecuteDuration, TestSize.Level0) +{ + TaskScheduler taskScheduler("everyTest"); + auto blockData = std::make_shared>(LONG_INTERVAL, 0); + int testData = 0; + taskScheduler.Every(std::chrono::milliseconds(SHORT_INTERVAL), [blockData, &testData]() { + testData++; + blockData->SetValue(testData); + }); + for (int i = 1; i < 10; ++i) { + ASSERT_EQ(blockData->GetValue(), i); + blockData->Clear(0); + } +} + +/** + * @tc.name: Reset + * @tc.desc: Reset before task execution and the task is tasks_.begin() or not + * @tc.type: FUNC + * @tc.require: + * @tc.author: ht + */ +HWTEST_F(TaskSchedulerTest, Reset1, TestSize.Level0) +{ + TaskScheduler taskScheduler("reset1Test"); + auto expiredTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(SHORT_INTERVAL); + auto atTaskId1 = taskScheduler.At(expiredTime, []() {}); + ASSERT_EQ(atTaskId1, 1); + expiredTime += std::chrono::milliseconds(LONG_INTERVAL); + auto atTaskId2 = taskScheduler.At(expiredTime, []() {}); + ASSERT_EQ(atTaskId2, 2); + + auto resetTaskId1 = taskScheduler.Reset(atTaskId1, std::chrono::milliseconds(SHORT_INTERVAL)); + ASSERT_EQ(resetTaskId1, atTaskId1); + + auto resetTaskId2 = taskScheduler.Reset(atTaskId2, std::chrono::milliseconds(SHORT_INTERVAL)); + ASSERT_EQ(resetTaskId2, atTaskId2); +} + +/** + * @tc.name: Reset + * @tc.desc: Reset during task execution + * @tc.type: FUNC + * @tc.require: + * @tc.author: ht + */ +HWTEST_F(TaskSchedulerTest, Reset2, TestSize.Level0) +{ + TaskScheduler taskScheduler("reset2Test"); + int testData = 10; + auto blockData = std::make_shared>(LONG_INTERVAL, testData); + auto expiredTime = std::chrono::steady_clock::now(); + auto atTaskId = taskScheduler.At(expiredTime, [blockData]() { + blockData->GetValue(); + }); + ASSERT_EQ(atTaskId, 1); + std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_INTERVAL)); + auto resetTaskId = taskScheduler.Reset(atTaskId, std::chrono::milliseconds(0)); + ASSERT_EQ(resetTaskId, TaskScheduler::INVALID_TASK_ID); + blockData->SetValue(testData); +} + +/** + * @tc.name: Reset + * @tc.desc: Reset after task execution + * @tc.type: FUNC + * @tc.require: + * @tc.author: ht + */ +HWTEST_F(TaskSchedulerTest, Reset3, TestSize.Level0) +{ + TaskScheduler taskScheduler("reset3Test"); + auto expiredTime = std::chrono::steady_clock::now(); + int testData = 10; + auto blockData = std::make_shared>(LONG_INTERVAL, testData); + auto atTaskId = taskScheduler.At(expiredTime, [blockData]() { + blockData->GetValue(); + }); + ASSERT_EQ(atTaskId, 1); + blockData->SetValue(testData); + blockData->SetValue(testData); + ASSERT_EQ(blockData->GetValue(), testData); + std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_INTERVAL)); + auto resetTaskId = taskScheduler.Reset(atTaskId, std::chrono::milliseconds(0)); + ASSERT_EQ(resetTaskId, TaskScheduler::INVALID_TASK_ID); +} + +/** + * @tc.name: Every + * @tc.desc: execute task for some times periodically with duration. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zuojiangjiang + */ +HWTEST_F(TaskSchedulerTest, EveryExecuteTimes, TestSize.Level0) +{ + TaskScheduler taskScheduler("everyTimes"); + auto blockData = std::make_shared>(LONG_INTERVAL, 0); + int testData = 0; + int times = 5; + auto taskId = taskScheduler.Every(times, std::chrono::milliseconds(0), std::chrono::milliseconds(SHORT_INTERVAL), + [blockData, times, &testData]() { + testData++; + if (testData < times) { + blockData->Clear(testData); + return; + } + blockData->SetValue(testData); + }); + ASSERT_EQ(blockData->GetValue(), times); + auto resetId = taskScheduler.Reset(taskId, std::chrono::milliseconds(SHORT_INTERVAL)); + ASSERT_EQ(resetId, TaskScheduler::INVALID_TASK_ID); + ASSERT_EQ(blockData->GetValue(), times); +} + +/** + * @tc.name: Remove + * @tc.desc: remove task before execute. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zuojiangjiang + */ +HWTEST_F(TaskSchedulerTest, RemoveBeforeExecute, TestSize.Level0) +{ + TaskScheduler taskScheduler("RemoveBeforeExecute"); + auto expiredTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(SHORT_INTERVAL); + auto blockData = std::make_shared>(LONG_INTERVAL, 0); + int testData = 0; + auto taskId = taskScheduler.At( + expiredTime, + [blockData, testData]() { + int tmpData = testData + 1; + blockData->SetValue(tmpData); + }, + std::chrono::milliseconds(SHORT_INTERVAL)); + taskScheduler.Remove(taskId); + auto resetId = taskScheduler.Reset(taskId, std::chrono::milliseconds(SHORT_INTERVAL)); + ASSERT_EQ(resetId, TaskScheduler::INVALID_TASK_ID); + ASSERT_EQ(blockData->GetValue(), testData); +} + +/** + * @tc.name: Remove + * @tc.desc: remove task during execute, and waiting. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zuojiangjiang + */ +HWTEST_F(TaskSchedulerTest, RemoveWaitExecute, TestSize.Level0) +{ + TaskScheduler taskScheduler("RemoveWaitExecute"); + auto expiredTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(0); + auto blockDataTest = std::make_shared>(LONG_INTERVAL, 0); + auto blockDataWait = std::make_shared>(LONG_INTERVAL, 0); + int testData = 1; + auto taskId = taskScheduler.At( + expiredTime, + [blockDataTest, blockDataWait, &testData]() { + blockDataTest->SetValue(testData); + blockDataWait->GetValue(); + int tmpData = testData + 1; + blockDataTest->SetValue(tmpData); + }, + std::chrono::milliseconds(SHORT_INTERVAL)); + ASSERT_EQ(blockDataTest->GetValue(), testData); + auto resetId = taskScheduler.Reset(taskId, std::chrono::milliseconds(SHORT_INTERVAL)); + ASSERT_EQ(taskId, resetId); + taskScheduler.Remove(taskId, true); + ASSERT_EQ(blockDataTest->GetValue(), testData + 1); +} + +/** + * @tc.name: Remove + * @tc.desc: remove task during execute, but no wait. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zuojiangjiang + */ +HWTEST_F(TaskSchedulerTest, RemoveNoWaitExecute, TestSize.Level0) +{ + TaskScheduler taskScheduler("RemoveNoWaitExecute"); + auto expiredTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(0); + auto blockDataTest = std::make_shared>(LONG_INTERVAL, 0); + auto blockDataWait = std::make_shared>(LONG_INTERVAL, 0); + int testData = 1; + auto taskId = taskScheduler.At(expiredTime, [blockDataTest, blockDataWait, &testData]() { + blockDataTest->SetValue(testData); + blockDataWait->GetValue(); + int tmpData = testData + 1; + blockDataTest->SetValue(tmpData); + }); + ASSERT_EQ(blockDataTest->GetValue(), testData); + blockDataTest->Clear(0); + taskScheduler.Remove(taskId); + blockDataWait->SetValue(testData); + ASSERT_EQ(blockDataTest->GetValue(), testData + 1); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/BUILD.gn b/data_object/frameworks/jskitsimpl/collaboration_edit/BUILD.gn index 0a942f35..43d8e1e5 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/BUILD.gn +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/BUILD.gn @@ -16,7 +16,11 @@ import("//build/ohos/ace/ace.gni") config("collaboration_edit_config") { visibility = [ ":*" ] - cflags = [ "-DHILOG_ENABLE" ] + cflags = [ + "-DHILOG_ENABLE", + "-fvisibility=hidden", + "-Oz", + ] include_dirs = [ "include", diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/include/napi_async_call.h b/data_object/frameworks/jskitsimpl/collaboration_edit/include/napi_async_call.h index 10dc29be..b216c0ca 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/include/napi_async_call.h +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/include/napi_async_call.h @@ -1,83 +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. - */ -#ifndef DATA_OBJ_NAPI_ASYNC_CALL_H -#define DATA_OBJ_NAPI_ASYNC_CALL_H - -#include - -#include "db_store.h" -#include "napi_errno.h" -#include "napi_utils.h" -#include "napi/native_api.h" -#include "napi/native_common.h" -#include "rd_type.h" - -namespace OHOS::CollaborationEdit { -struct ProgressDetailT { - ProgressCode code; -}; - -struct SyncCallbackParamT { - std::promise promise; - ProgressDetailT detail; -}; - -using InputAction = std::function; -using OutputAction = std::function; -using ExecuteAction = std::function; - -constexpr const char *SYNC_FUNCTION_NAME = "CollaborationAsyncCall"; -constexpr std::chrono::seconds TIME_THRESHOLD = std::chrono::seconds(30); - -class SyncContext { -public: - int SetAll(napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output); - void ReleaseInnerReference(); - virtual ~SyncContext(); - - napi_env env_ = nullptr; - napi_ref self_ = nullptr; - void *boundObj = nullptr; // unwrapped collaborationEdit object - const char *fun = nullptr; // function name in napi queue - - napi_async_work work_ = nullptr; - napi_value result_ = nullptr; - - int execCode_ = OK; - OutputAction output_ = nullptr; - ExecuteAction exec_ = nullptr; - std::shared_ptr keep_; // keep self alive - - uint64_t syncId = 0u; - std::mutex callbackMutex_; - napi_threadsafe_function callback_ = nullptr; - - int32_t syncMode_; - std::shared_ptr dbStore_ = nullptr; -}; - -class AsyncCall final { -public: - static int Call(napi_env env, std::shared_ptr context, const char *fun); - static void CloudSyncCallback(napi_env env, napi_value js_cb, void *context, void *data); - -private: - static void OnExecute(napi_env env, void *data); - static void OnComplete(napi_env env, void *data); - static void OnReturn(napi_env env, napi_status status, void *data); - static void OnComplete(napi_env env, napi_status status, void *data); -}; -} // namespace OHOS::CollaborationEdit -#endif \ 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. + */ +#ifndef DATA_OBJ_NAPI_ASYNC_CALL_H +#define DATA_OBJ_NAPI_ASYNC_CALL_H + +#include + +#include "db_store.h" +#include "napi_errno.h" +#include "napi_utils.h" +#include "napi/native_api.h" +#include "napi/native_common.h" +#include "rd_type.h" + +namespace OHOS::CollaborationEdit { +using InputAction = std::function; +using OutputAction = std::function; +using ExecuteAction = std::function; + +constexpr const char *SYNC_FUNCTION_NAME = "CollaborationAsyncCall"; +constexpr std::chrono::seconds TIME_THRESHOLD = std::chrono::seconds(30); + +class SyncContext { +public: + int SetAll(napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output); + void ReleaseInnerReference(); + void Release(); + virtual ~SyncContext(); + + napi_env env_ = nullptr; + napi_ref self_ = nullptr; + void *boundObj = nullptr; // unwrapped collaborationEdit object + const char *fun = nullptr; // function name in napi queue + + napi_async_work work_ = nullptr; + napi_value result_ = nullptr; + + int execCode_ = OK; + OutputAction output_ = nullptr; + ExecuteAction exec_ = nullptr; + std::shared_ptr keep_; // keep self alive + + uint64_t syncId = 0u; + std::mutex callbackMutex_; + napi_threadsafe_function callback_ = nullptr; + + int32_t syncMode_; + std::shared_ptr dbStore_ = nullptr; +}; + +struct ProgressDetailT { + ProgressCode code; +}; + +struct SyncCallbackParamT { + std::promise promise; + ProgressDetailT detail; + std::shared_ptr syncContext; +}; + +class AsyncCall final { +public: + static int Call(napi_env env, std::shared_ptr context, const char *fun); + static void CloudSyncCallback(napi_env env, napi_value js_cb, void *context, void *data); + +private: + static void OnExecute(napi_env env, void *data); + static void OnComplete(napi_env env, void *data); + static void OnReturn(napi_env env, napi_status status, void *data); + static void OnComplete(napi_env env, napi_status status, void *data); + static void ReleaseSyncContext(std::shared_ptr syncContext); +}; +} // namespace OHOS::CollaborationEdit +#endif diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/include/napi_collaboration_edit_object.h b/data_object/frameworks/jskitsimpl/collaboration_edit/include/napi_collaboration_edit_object.h index d7be9b21..fd6aba04 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/include/napi_collaboration_edit_object.h +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/include/napi_collaboration_edit_object.h @@ -43,7 +43,6 @@ private: static napi_value Initialize(napi_env env, napi_callback_info info); static napi_status CreateHandlerFunc(napi_env env, std::vector &cloudDbFunc, NapiCloudDb *napiCloudDb); - static void ReleaseHandlerFunc(NapiCloudDb *napiCloudDb); static napi_value GetEditUnit(napi_env env, napi_callback_info info); static napi_value GetUndoRedoManager(napi_env env, napi_callback_info info); static napi_value DeleteUndoRedoManager(napi_env env, napi_callback_info info); diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_async_call.cpp b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_async_call.cpp index 0ed5c8de..26e78807 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_async_call.cpp +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_async_call.cpp @@ -57,6 +57,9 @@ void SyncContext::ReleaseInnerReference() } SyncContext::~SyncContext() +{} + +void SyncContext::Release() { LOG_DEBUG("SyncContext freed."); if (env_ == nullptr) { @@ -140,6 +143,8 @@ void AsyncCall::CloudSyncCallback(napi_env env, napi_value js_cb, void *context, napi_status status = napi_create_object(env, ¶m); if (status != napi_ok) { LOG_ERROR("create param object wrong, status: %{public}" PRIi32, static_cast(status)); + ReleaseSyncContext(callbackParam->syncContext); + callbackParam->syncContext.reset(); callbackParam->promise.set_value(0); return; } @@ -149,6 +154,8 @@ void AsyncCall::CloudSyncCallback(napi_env env, napi_value js_cb, void *context, status = napi_set_named_property(env, param, "code", pCode); if (status != napi_ok) { LOG_ERROR("set named property wrong, status: %{public}" PRIi32, static_cast(status)); + ReleaseSyncContext(callbackParam->syncContext); + callbackParam->syncContext.reset(); callbackParam->promise.set_value(0); return; } @@ -164,6 +171,17 @@ void AsyncCall::CloudSyncCallback(napi_env env, napi_value js_cb, void *context, if (status != napi_ok) { LOG_ERROR("napi call js function wrong, status: %{public}" PRIi32, static_cast(status)); } + // need to release sync context in js thread + ReleaseSyncContext(callbackParam->syncContext); + callbackParam->syncContext.reset(); callbackParam->promise.set_value(0); } + +void AsyncCall::ReleaseSyncContext(std::shared_ptr syncContext) +{ + if (syncContext == nullptr) { + return; + } + syncContext->Release(); +} } // namespace CollaborationEdit diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_cloud_db.cpp b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_cloud_db.cpp index c6059300..86c4539a 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_cloud_db.cpp +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_cloud_db.cpp @@ -57,7 +57,22 @@ struct QueryInfo { NapiCloudDb::NapiCloudDb() {} -NapiCloudDb::~NapiCloudDb() {} +NapiCloudDb::~NapiCloudDb() +{ + napi_release_threadsafe_function(batchInsertInnerFunc_, napi_tsfn_release); + napi_release_threadsafe_function(queryInnerFunc_, napi_tsfn_release); + napi_release_threadsafe_function(downloadAssetInnerFunc_, napi_tsfn_release); + napi_release_threadsafe_function(uploadAssetInnerFunc_, napi_tsfn_release); + napi_release_threadsafe_function(deleteAssetInnerFunc_, napi_tsfn_release); + napi_release_threadsafe_function(deleteLocalAssetInnerFunc_, napi_tsfn_release); + + batchInsertInnerFunc_ = nullptr; + queryInnerFunc_ = nullptr; + downloadAssetInnerFunc_ = nullptr; + uploadAssetInnerFunc_ = nullptr; + deleteAssetInnerFunc_ = nullptr; + deleteLocalAssetInnerFunc_ = nullptr; +} int32_t NapiCloudDb::BatchInsert(const std::vector &cloudParamsAdapter) { diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_collaboration_edit_object.cpp b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_collaboration_edit_object.cpp index 6370df8a..4a580fdd 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_collaboration_edit_object.cpp +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_collaboration_edit_object.cpp @@ -57,7 +57,6 @@ napi_value CollaborationEditObject::Initialize(napi_env env, napi_callback_info ContextParam context; napi_status status = NapiUtils::GetValue(env, argv[0], context); ASSERT_THROW_BASE(env, status == napi_ok, Status::INVALID_ARGUMENT, "read context param go wrong", self); - ASSERT_THROW_BASE(env, context.isSystemApp, Status::NOT_SYSTEM_APP, "Not a system app", self); std::string docName; status = NapiUtils::GetNamedProperty(env, argv[1], "name", docName); ASSERT_THROW_BASE(env, status == napi_ok, Status::INVALID_ARGUMENT, "read docName param go wrong", self); @@ -77,7 +76,12 @@ napi_value CollaborationEditObject::Initialize(napi_env env, napi_callback_info CollaborationEditObject *editObject = reinterpret_cast(data); delete editObject; }; - napi_wrap(env, self, editObject, finalize, nullptr, nullptr); + status = napi_wrap(env, self, editObject, finalize, nullptr, nullptr); + if (status != napi_ok) { + LOG_ERROR("napi_wrap failed. code:%{public}d", status); + delete editObject; + return nullptr; + } return self; } @@ -198,6 +202,22 @@ napi_value CollaborationEditObject::SetCloudDb(napi_env env, napi_callback_info napi_value self = nullptr; NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); + CollaborationEditObject *editObject = nullptr; + napi_status status = napi_unwrap(env, self, reinterpret_cast(&editObject)); + if (status != napi_ok) { + ThrowNapiError(env, Status::INTERNAL_ERROR, "unwrap editObject go wrong."); + return nullptr; + } + std::shared_ptr dbStore = editObject->GetDBStore(); + if (dbStore == nullptr) { + ThrowNapiError(env, Status::INVALID_ARGUMENT, "dbStore is null."); + return nullptr; + } + if (dbStore->GetCloudDB() != nullptr) { + LOG_INFO("cloudDB already set"); + return nullptr; + } + std::vector cloudDbFunc; int ret = Parser::ParseCloudDbFields(env, argv[0], cloudDbFunc); if (ret != OK) { @@ -206,25 +226,15 @@ napi_value CollaborationEditObject::SetCloudDb(napi_env env, napi_callback_info } NapiCloudDb *napiCloudDb = new (std::nothrow) NapiCloudDb(); ASSERT_THROW(env, napiCloudDb != nullptr, Status::INTERNAL_ERROR, "new cloud db instance go wrong."); - napi_status status = CollaborationEditObject::CreateHandlerFunc(env, cloudDbFunc, napiCloudDb); + status = CollaborationEditObject::CreateHandlerFunc(env, cloudDbFunc, napiCloudDb); if (status != napi_ok) { - ReleaseHandlerFunc(napiCloudDb); delete napiCloudDb; ThrowNapiError(env, Status::INTERNAL_ERROR, "create handler func go wrong."); return nullptr; } - CollaborationEditObject *editObject = nullptr; - status = napi_unwrap(env, self, reinterpret_cast(&editObject)); - if (status != napi_ok) { - ReleaseHandlerFunc(napiCloudDb); - delete napiCloudDb; - ThrowNapiError(env, Status::INTERNAL_ERROR, "unwrap editObject go wrong."); - return nullptr; - } - ret = DBStoreManager::GetInstance().SetCloudDb(editObject->GetDBStore(), napiCloudDb); + ret = DBStoreManager::GetInstance().SetCloudDb(dbStore, napiCloudDb); if (ret != 0) { - ReleaseHandlerFunc(napiCloudDb); delete napiCloudDb; ThrowNapiError(env, ret, "set cloud db go wrong."); } @@ -278,27 +288,6 @@ napi_status CollaborationEditObject::CreateHandlerFunc(napi_env env, std::vector return napi_ok; } -void CollaborationEditObject::ReleaseHandlerFunc(NapiCloudDb *napiCloudDb) -{ - if (napiCloudDb == nullptr) { - return; - } - napi_release_threadsafe_function(napiCloudDb->batchInsertInnerFunc_, napi_tsfn_release); - napi_release_threadsafe_function(napiCloudDb->queryInnerFunc_, napi_tsfn_release); - napi_release_threadsafe_function(napiCloudDb->downloadAssetInnerFunc_, napi_tsfn_release); - napi_release_threadsafe_function(napiCloudDb->uploadAssetInnerFunc_, napi_tsfn_release); - napi_release_threadsafe_function(napiCloudDb->deleteAssetInnerFunc_, napi_tsfn_release); - napi_release_threadsafe_function(napiCloudDb->deleteLocalAssetInnerFunc_, napi_tsfn_release); - - napiCloudDb->batchInsertInnerFunc_ = nullptr; - napiCloudDb->queryInnerFunc_ = nullptr; - napiCloudDb->downloadAssetInnerFunc_ = nullptr; - napiCloudDb->downloadAssetInnerFunc_ = nullptr; - napiCloudDb->uploadAssetInnerFunc_ = nullptr; - napiCloudDb->deleteAssetInnerFunc_ = nullptr; - napiCloudDb->deleteLocalAssetInnerFunc_ = nullptr; -} - napi_value CollaborationEditObject::Delete(napi_env env, napi_callback_info info) { size_t argc = 2; @@ -308,7 +297,6 @@ napi_value CollaborationEditObject::Delete(napi_env env, napi_callback_info info ContextParam context; napi_status status = NapiUtils::GetValue(env, argv[0], context); ASSERT_THROW_BASE(env, status == napi_ok, Status::INVALID_ARGUMENT, "read context param go wrong", self); - ASSERT_THROW_BASE(env, context.isSystemApp, Status::NOT_SYSTEM_APP, "Not a system app", self); std::string docName; status = NapiUtils::GetNamedProperty(env, argv[1], "name", docName); ASSERT_THROW_BASE(env, status == napi_ok, Status::INVALID_ARGUMENT, "read docName param go wrong", self); @@ -328,7 +316,7 @@ int CollaborationEditObject::ParseCloudSyncMode(const napi_env env, const napi_v int32_t mode = 0; napi_status status = NapiUtils::GetValue(env, arg, mode); if (status != napi_ok || mode < 0 || mode > SyncMode::PULL_PUSH) { - LOG_ERROR("CloudSync parse syncMode go wrong, mode: %d", mode); + LOG_ERROR("CloudSync parse syncMode go wrong, mode: %{public}d", mode); return ERR; } context->syncMode_ = mode; @@ -468,9 +456,10 @@ void CollaborationEditObject::SyncCallbackFunc(GRD_SyncProcessT *syncProcess) return; } napi_threadsafe_function js_cb = context->callback_; + context->callback_ = nullptr; + context->ReleaseInnerReference(); if (js_cb == nullptr) { LOG_ERROR("callback is null"); - context->ReleaseInnerReference(); return; } @@ -478,20 +467,18 @@ void CollaborationEditObject::SyncCallbackFunc(GRD_SyncProcessT *syncProcess) if (ret != napi_ok) { LOG_ERROR("acquire thread safe function failed, ret: %{public}d", static_cast(ret)); napi_release_threadsafe_function(js_cb, napi_tsfn_release); - context->callback_ = nullptr; - context->ReleaseInnerReference(); return; } SyncCallbackParamT param = {}; param.detail.code = CollaborationEditObject::GetProgressCode(syncProcess->errCode); + param.syncContext = context; + context.reset(); std::future future = param.promise.get_future(); ret = napi_call_threadsafe_function(js_cb, ¶m, napi_tsfn_blocking); if (ret != napi_ok) { LOG_ERROR("call function go wrong, ret=%{public}d", static_cast(ret)); napi_release_threadsafe_function(js_cb, napi_tsfn_release); - context->callback_ = nullptr; - context->ReleaseInnerReference(); return; } std::future_status fstatus = future.wait_for(std::chrono::duration_cast(TIME_THRESHOLD)); @@ -502,8 +489,6 @@ void CollaborationEditObject::SyncCallbackFunc(GRD_SyncProcessT *syncProcess) } napi_release_threadsafe_function(js_cb, napi_tsfn_release); - context->callback_ = nullptr; - context->ReleaseInnerReference(); LOG_INFO("syncCallback end"); } diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_edit_unit.cpp b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_edit_unit.cpp index 183d849a..237d07ea 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_edit_unit.cpp +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_edit_unit.cpp @@ -49,7 +49,12 @@ napi_value EditUnit::Initialize(napi_env env, napi_callback_info info) EditUnit *editUnit = reinterpret_cast(data); delete editUnit; }; - napi_wrap(env, self, editUnit, finalize, nullptr, nullptr); + status = napi_wrap(env, self, editUnit, finalize, nullptr, nullptr); + if (status != napi_ok) { + LOG_ERROR("napi_wrap failed. code:%{public}d", status); + delete editUnit; + return nullptr; + } return self; } diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_node.cpp b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_node.cpp index 685339af..cf928ecc 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_node.cpp +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_node.cpp @@ -84,7 +84,12 @@ napi_value Node::New(napi_env env, napi_callback_info info) Node *node = reinterpret_cast(data); delete node; }; - napi_wrap(env, self, node, finalize, nullptr, nullptr); + napi_status status = napi_wrap(env, self, node, finalize, nullptr, nullptr); + if (status != napi_ok) { + LOG_ERROR("napi_wrap failed. code:%{public}d", status); + delete node; + return nullptr; + } return self; } diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_text.cpp b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_text.cpp index 69579ebd..5fad6b83 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_text.cpp +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_text.cpp @@ -69,7 +69,12 @@ napi_value Text::New(napi_env env, napi_callback_info info) Text *text = reinterpret_cast(data); delete text; }; - napi_wrap(env, self, text, finalize, nullptr, nullptr); + napi_status status = napi_wrap(env, self, text, finalize, nullptr, nullptr); + if (status != napi_ok) { + LOG_ERROR("napi_wrap failed. code:%{public}d", status); + delete text; + return nullptr; + } return self; } diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_undo_manager.cpp b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_undo_manager.cpp index f8b4a21d..ea5cdefa 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_undo_manager.cpp +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/src/napi_undo_manager.cpp @@ -53,7 +53,12 @@ napi_value UndoManager::Initialize(napi_env env, napi_callback_info info) UndoManager *undoManager = reinterpret_cast(data); delete undoManager; }; - napi_wrap(env, self, undoManager, finalize, nullptr, nullptr); + status = napi_wrap(env, self, undoManager, finalize, nullptr, nullptr); + if (status != napi_ok) { + LOG_ERROR("napi_wrap failed. code:%{public}d", status); + delete undoManager; + return nullptr; + } return self; } diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/Application/AbilityStage.ts b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/Application/AbilityStage.ts index 13d01e24..69cecf24 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/Application/AbilityStage.ts +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/Application/AbilityStage.ts @@ -12,12 +12,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import AbilityStage from "@ohos.app.ability.AbilityStage" +import AbilityStage from "@ohos.app.ability.AbilityStage"; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; export default class MyAbilityStage extends AbilityStage { onCreate() { console.log('[Demo] MyAbilityStage onCreate'); globalThis.stageOnCreateRun = 1; globalThis.stageContext = this.context; + globalThis.abilityContext = this.context; } } diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/EditUnit.ets b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/EditUnit.ets index a3df06da..7f5e202a 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/EditUnit.ets +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/EditUnit.ets @@ -62,7 +62,7 @@ export default function collaborationEditUnitTest() { * 1. getEditUnit by empty input string * 2. check 401 error code */ - it("CollaborationEdit_EditUnit_0001", Level.LEVEL0, () => { + it("CollaborationEdit_EditUnit_0001", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_EditUnit_0001 Start*****************"); expect(editObject !== undefined).assertTrue(); let editUnit: collaboration_edit.EditUnit | undefined; @@ -83,7 +83,7 @@ export default function collaborationEditUnitTest() { * 1. check EditUnit.getName * 2. insert null node array and check 401 error code */ - it("CollaborationEdit_EditUnit_0002", Level.LEVEL0, () => { + it("CollaborationEdit_EditUnit_0002", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_EditUnit_0002 Start*****************"); expect(editUnit !== undefined).assertTrue(); expect(EDIT_UNIT_NAME).assertEqual(editUnit?.getName()); @@ -107,7 +107,7 @@ export default function collaborationEditUnitTest() { * 4. EditUnit.getChildren and check result * 5. EditUnit.getJsonResult and check result */ - it("CollaborationEdit_EditUnit_0003", Level.LEVEL0, () => { + it("CollaborationEdit_EditUnit_0003", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_EditUnit_0003 Start*****************"); expect(editUnit !== undefined).assertTrue(); try { diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/List.test.ets b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/List.test.ets index 1da6e6c6..8c333c4e 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/List.test.ets +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/List.test.ets @@ -13,18 +13,8 @@ * limitations under the License. */ -import collaborationGetEditObjectTest from './GetEditObject.ets'; -import collaborationEditUnitTest from './EditUnit.ets'; -import collaborationNodeTest from './Node.ets'; -import collaborationTextTest from './Text.ets'; -import collaborationUndoRedoTest from './UndoRedo.ets'; -import collaborationSetCloudDbTest from './SetCloudDb.ets'; +import collaborationrunTextTest from './RunTest.ets'; export default function testsuite() { - collaborationGetEditObjectTest(); - collaborationEditUnitTest(); - collaborationNodeTest(); - collaborationTextTest(); - collaborationUndoRedoTest(); - collaborationSetCloudDbTest(); + collaborationrunTextTest(); } diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/Node.ets b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/Node.ets index 6bb407a8..32b0a865 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/Node.ets +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/Node.ets @@ -107,7 +107,7 @@ export default function collaborationNodeTest() { * 6. delete the first child * 7. again check result by getChildren and getJsonResult */ - it("CollaborationEdit_Node_0002", Level.LEVEL0, () => { + it("CollaborationEdit_Node_0002", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Node_0002 Start*****************"); expect(editUnit !== undefined).assertTrue(); try { @@ -159,7 +159,7 @@ export default function collaborationNodeTest() { * 6. delete the second child * 7. again check result by getChildren and getJsonResult */ - it("CollaborationEdit_Node_0003", Level.LEVEL0, () => { + it("CollaborationEdit_Node_0003", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Node_0003 Start*****************"); expect(editUnit !== undefined).assertTrue(); try { @@ -210,7 +210,7 @@ export default function collaborationNodeTest() { * 4. getChildren if start and end are out of range * 5. check error code */ - it("CollaborationEdit_Node_0004", Level.LEVEL0, () => { + it("CollaborationEdit_Node_0004", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Node_0004 Start*****************"); expect(editUnit !== undefined).assertTrue(); let errCode: string = ""; @@ -244,7 +244,7 @@ export default function collaborationNodeTest() { * 2. call getId/setAttributes of the node * 3. check the invalid operation error code */ - it("CollaborationEdit_Node_0005", Level.LEVEL0, () => { + it("CollaborationEdit_Node_0005", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Node_0005 Start*****************"); let node = new collaboration_edit.Node("p1"); let errCode: string = ""; @@ -280,7 +280,7 @@ export default function collaborationNodeTest() { * 5. getChildren - start is negative * 6. getChildren - start is greater than end */ - it("CollaborationEdit_Node_0006", 0, async () => { + it("CollaborationEdit_Node_0006", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Node_0006 Start*****************"); let node: collaboration_edit.Node | undefined = undefined; try { @@ -341,7 +341,7 @@ export default function collaborationNodeTest() { console.log(TAG + "*****************CollaborationEdit_Node_0006 End*****************"); }) - it("CollaborationEdit_Node_0007", Level.LEVEL0, () => { + it("CollaborationEdit_Node_0007", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Node_0007 Start*****************"); expect(editUnit !== undefined).assertTrue(); try { @@ -372,7 +372,7 @@ export default function collaborationNodeTest() { console.log(TAG + "*****************CollaborationEdit_Node_0007 End*****************"); }) - it("CollaborationEdit_Node_0008", Level.LEVEL0, () => { + it("CollaborationEdit_Node_0008", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Node_0008 Start*****************"); expect(editUnit !== undefined).assertTrue(); try { @@ -395,7 +395,7 @@ export default function collaborationNodeTest() { console.log(TAG + "*****************CollaborationEdit_Node_0008 End*****************"); }) - it("CollaborationEdit_Node_0009", Level.LEVEL0, () => { + it("CollaborationEdit_Node_0009", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Node_0009 Start*****************"); expect(editUnit !== undefined).assertTrue(); try { diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/RunTest.ets b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/RunTest.ets new file mode 100644 index 00000000..1ab45814 --- /dev/null +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/RunTest.ets @@ -0,0 +1,651 @@ +/* + * 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 { describe, beforeEach, afterEach, beforeAll, it, afterAll, expect, Level } from '@ohos/hypium' +import common from '@ohos.app.ability.common'; +import commonType from '@ohos.data.commonType'; +import DataObject from '@ohos.data.distributedDataObject'; +import abilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import UIAbility from '@ohos.app.ability.UIAbility'; + + +const TAG = "[CollaborationEdit_JsTest_Text]" +let context: common.Context = globalThis.abilityContext; + + +class Note { + title: string | undefined + text: string | undefined + attachment: commonType.Asset | undefined + + constructor(title: string | undefined, text: string | undefined, + attachment: commonType.Asset | undefined) { + this.title = title; + this.text = text; + this.attachment = attachment; + } +} + +let attachment: commonType.Asset = { + name: 'test_img.jpg', + uri: 'file://com.example.myapplication/data/storage/el2/distributedfiles/dir/test_img.jpg', + path: '/dir/test_img.jpg', + createTime: '2024-01-02 10:00:00', + modifyTime: '2024-01-02 10:00:00', + size: '5', + status: commonType.AssetStatus.ASSET_NORMAL +} + +const bindInfo: DataObject.BindInfo = { + storeName: 'notepad', + tableName: 'note_t', + primaryKey: { + 'uuid': '00000000-0000-0000-0000-000000000000' + }, + field: 'attachment', + assetName: attachment.name as string +} + +let note: Note = new Note('test', 'test', attachment); + +function statusCallBack(sessionId: string, networkId: string, status: string) { +} + +function changeCallBack(sessionId: string, fields: Array) { +} + +function progressCallBack(sessionId: string, progress: number) { +} + +let sleep = (ms:number) => { + return new Promise(resolve => setTimeout(resolve, ms)); +} +export default function collaborationrunTextTest() { + describe('collaborationrunTextTest', () => { + beforeAll(async(done:Function) => { + + let abilityDelegator:abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator() + try{ + abilityDelegator.addAbilityMonitor({ + abilityName: "EntryAbility", + moduleName:"entry", + onAbilityCreate: (abilitys : UIAbility) : void => { + context = abilitys.context; + // hilog.info(domain, tag, '%{public}s', 'onAbilityCreate end'); + + }, + }, (err) : void => { + + }); + } catch (err){ + } + + abilityDelegator.executeShellCommand("aa start -a EntryAbility -b com.example.myapplication") + await sleep(2000) + + done(); + }) + + beforeEach(() => { + + }) + + afterEach(() => { + }) + + afterAll(() => { + }) + + /** + * @tc.number : CollaborationEdit_Text_0001 + * @tc.name : Monitor data changes + * @tc.desc : Test the interface function for monitoring data changes + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0001', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("change", changeCallBack); + expect(true).assertTrue() + + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + + /** + * @tc.number : CollaborationEdit_Text_0002 + * @tc.name : Monitor data changes + * @tc.desc : Test the interface function for monitoring data changes, callback is closure + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + + it('CollaborationEdit_Text_0002', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("change", () => { + }); + expect(true).assertTrue() + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0003 + * @tc.name : Remove monitoring of data changes + * @tc.desc : Test the interface function for remove monitoring of data changes + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0003', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("change",changeCallBack); + g_object.off("change", changeCallBack); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0004 + * @tc.name : Remove monitoring of data changes + * @tc.desc : Test the interface function for remove of all data changes + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0004', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("change",changeCallBack); + g_object.off("change"); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0005 + * @tc.name : Monitor data object online/offline + * @tc.desc : Test the interface function for monitoring of data object online/offline + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0005', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("status", statusCallBack); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0006 + * @tc.name : Monitor data object online/offline + * @tc.desc : Test the interface function for monitoring of data object online/offline , no callback + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0006', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("status", null); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + + /** + * @tc.number : CollaborationEdit_Text_0007 + * @tc.name : Remove monitor of data object online/offline + * @tc.desc : Test the interface function for removing monitor of data object online/offline + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + + it('CollaborationEdit_Text_0007', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("status",statusCallBack); + g_object.off("status", statusCallBack); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0008 + * @tc.name : Remove monitor of data object online/offline + * @tc.desc : Test the interface function for removing monitor of all data object online/offline + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0008', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("status",statusCallBack); + g_object.off("status"); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0010 + * @tc.name : Set a single asset + * @tc.desc : Test the interface function for setting a single asset, property parameter is null + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0010', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + let uri = "file:1.txt"; + g_object.setAsset(null, uri); + } catch (err) { + expect(err.code == 15400002).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0011 + * @tc.name : Set a single asset + * @tc.desc : Test the interface function for setting a single asset, property parameter is empty string + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0011', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + let uri = "file:1.txt"; + g_object.setAsset("", uri); + } catch (err) { + expect(err.code == 15400002).assertEqual(true); + } + }) + + + /** + * @tc.number : CollaborationEdit_Text_0012 + * @tc.name : Set a single asset + * @tc.desc : Test the interface function for setting a single asset, uri is null + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0012', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + let uri = ""; + g_object.setAsset("file", uri); + } catch (err) { + expect(err.code == 15400002).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0014 + * @tc.name : Set a single asset + * @tc.desc : Test the interface function for setting asset array, property parameter is null + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0014', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + let uris = ["file:1.txt"]; + g_object.setAssets(null, uris); + } catch (err) { + expect(err.code == 15400002).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0015 + * @tc.name : Set a single asset + * @tc.desc : Test the interface function for setting asset array, property parameter is empty string + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0015', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + let uris = ["file:1.txt"]; + g_object.setAssets("", uris); + } catch (err) { + expect(err.code == 15400002).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0016 + * @tc.name : Set a single asset + * @tc.desc : Test the interface function for setting asset array, asset array is empty + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0016', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.setAssets("file", []); + } catch (err) { + expect(err.code == 15400002).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0017 + * @tc.name : Set a single asset + * @tc.desc : Test the interface function for setting asset array, number of asset more than 50 + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0017', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + const uris: string[] = []; + for (let index = 0; index < 55; index++) { + let uri = `file${index + 1}:${index + 1}.txt`; + uris.push(uri); + } + g_object.setAssets("file", uris); + } catch (err) { + expect(err.code == 15400002).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0017 + * @tc.name : Set a single asset + * @tc.desc : Test the interface function for setting asset array, apart of assets are invalid + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0018', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + let uris = ["file:1.txt", null]; + g_object.setAssets("file", uris); + } catch (err) { + expect(err.code == 15400002).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0019 + * @tc.name : Monitor asset progress + * @tc.desc : Test the interface function for monitoring asset progress + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0019', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged", progressCallBack); + expect(true).assertTrue() + + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + + /** + * @tc.number : CollaborationEdit_Text_0020 + * @tc.name : Monitor asset progress + * @tc.desc : Test the interface function for monitoring asset progress, callback is closure + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + + it('CollaborationEdit_Text_0020', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged", () => { + }); + expect(true).assertTrue() + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0021 + * @tc.name : Remove monitoring of asset progress + * @tc.desc : Test the interface function for remove monitoring of asset progress + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0021', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged",progressCallBack); + g_object.off("progressChanged", progressCallBack); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0022 + * @tc.name : Remove monitoring of asset progress + * @tc.desc : Test the interface function for remove of all asset progress + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0022', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged",progressCallBack); + g_object.off("progressChanged"); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0023 + * @tc.name : Monitor data object online/offline + * @tc.desc : Test the interface function for monitoring of data object online/offline + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0023', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged", progressCallBack); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0024 + * @tc.name : Monitor data object online/offline + * @tc.desc : Test the interface function for monitoring of data object online/offline , no callback + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0024', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged", null); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + + /** + * @tc.number : CollaborationEdit_Text_0025 + * @tc.name : Remove monitor of data object online/offline + * @tc.desc : Test the interface function for removing monitor of data object online/offline + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + + it('CollaborationEdit_Text_0025', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged",progressCallBack); + g_object.off("progressChanged", progressCallBack); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0026 + * @tc.name : Remove monitor of data object online/offline + * @tc.desc : Test the interface function for removing monitor of all data object online/offline + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0026', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged",progressCallBack); + g_object.off("progressChanged"); + expect(true).assertTrue(); + } catch (err) { + expect(err.code == 401).assertEqual(true); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0027 + * @tc.name : Remove monitor of data object + * @tc.desc : Test the interface function for removing monitor of all data object + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0027', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged",()=>{}); + g_object.on("progressChanged",progressCallBack); + g_object.off("progressChanged",()=>{}); + } catch (err) { + expect().assertFail(); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0028 + * @tc.name : Remove monitor of data object + * @tc.desc : Test the interface function for removing monitor of all data object + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0028', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged",progressCallBack); + g_object.on("progressChanged",progressCallBack); + g_object.off("progressChanged",()=>{}); + } catch (err) { + expect().assertFail(); + } + }) + + /** + * @tc.number : CollaborationEdit_Text_0029 + * @tc.name : Remove monitor of data object + * @tc.desc : Test the interface function for removing monitor of all data object + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 1 + */ + + it('CollaborationEdit_Text_0029', Level.LEVEL1, () => { + try { + let g_object: DataObject.DataObject = DataObject.create(context, note); + g_object.on("progressChanged",progressCallBack); + g_object.on("progressChanged",progressCallBack); + g_object.off("progressChanged",undefined); + } catch (err) { + expect().assertFail(); + } + }) + }) +} \ No newline at end of file diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/SetCloudDb.ets b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/SetCloudDb.ets index 3fa52a73..e93a4d22 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/SetCloudDb.ets +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/SetCloudDb.ets @@ -20,7 +20,7 @@ import common from '@ohos.app.ability.common'; import CloudDbMock from "./CloudDbMock"; import TestUtils from './TestUtils'; -const TAG = "[CollaborationEdit_JsTest_UndoRedo]" +const TAG = "[CollaborationEdit_JsTest_SetCloudDb]" const DOC_CONFIG_A: collaboration_edit.CollaborationConfig = {name: "doc_test_A"} const DOC_CONFIG_B: collaboration_edit.CollaborationConfig = {name: "doc_test_B"} let context: common.UIAbilityContext = globalThis.abilityContext; @@ -206,7 +206,7 @@ export default function collaborationSetCloudDbTest() { * 2. equip A push to cloud * 3. verify cloud record */ - it("CollaborationEdit_SetCloudDb_0002", 0, async () => { + it("CollaborationEdit_SetCloudDb_0002", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_SetCloudDb_002 Start*****************"); try { expect(editObject_A !== undefined).assertTrue(); @@ -247,7 +247,7 @@ export default function collaborationSetCloudDbTest() { * 5. equip B delete asset node, then sync * 6. equip A reads updated data */ - it("CollaborationEdit_SetCloudDb_0003", 0, async () => { + it("CollaborationEdit_SetCloudDb_0003", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_SetCloudDb_003 Start*****************"); try { expect(editObject_A !== undefined).assertTrue(); @@ -366,7 +366,7 @@ export default function collaborationSetCloudDbTest() { * 3. write cloud records to equip B * 4. equip B contains equip A's data */ - it("CollaborationEdit_SetCloudDb_0005", 0, async () => { + it("CollaborationEdit_SetCloudDb_0005", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_SetCloudDb_005 Start*****************"); try { expect(editObject_A !== undefined).assertTrue(); @@ -413,7 +413,7 @@ export default function collaborationSetCloudDbTest() { * 1. equip A insert 1 node and push to cloud * 2. get CLOUD_NOT_SET error code in callback */ - it("CollaborationEdit_SetCloudDb_0006", 0, async () => { + it("CollaborationEdit_SetCloudDb_0006", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_SetCloudDb_006 Start*****************"); try { expect(editObject_A !== undefined).assertTrue(); diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/Text.ets b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/Text.ets index 75f1d31b..396f3733 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/Text.ets +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/Text.ets @@ -66,7 +66,7 @@ export default function collaborationTextTest() { * 5. format some characters and check result by getJsonResult * 6. delete some characters and check result by getPlainText and getJsonResult */ - it("CollaborationEdit_Text_0001", Level.LEVEL0, () => { + it("CollaborationEdit_Text_0001", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_Text_0001 Start*****************"); expect(editUnit !== undefined).assertTrue(); try { diff --git a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/UndoRedo.ets b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/UndoRedo.ets index aae7d63e..c0ba2ade 100644 --- a/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/UndoRedo.ets +++ b/data_object/frameworks/jskitsimpl/collaboration_edit/test/unittest/collaboration_edit_js_test/entry/src/main/ets/test/UndoRedo.ets @@ -64,7 +64,7 @@ export default function collaborationUndoRedoTest() { * 1. editUnitName is any non-empty string * 2. captureTimeout is float */ - it("CollaborationEdit_UndoRedo_0001", Level.LEVEL0, () => { + it("CollaborationEdit_UndoRedo_0001", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_UndoRedo_0001 Start*****************"); expect(editUnit !== undefined).assertTrue(); let undoManager: collaboration_edit.UndoRedoManager | undefined; @@ -83,7 +83,7 @@ export default function collaborationUndoRedoTest() { * @tc.desc * 1. captureTimeout is negative, then check 401 error code */ - it("CollaborationEdit_UndoRedo_0002", Level.LEVEL0, () => { + it("CollaborationEdit_UndoRedo_0002", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_UndoRedo_0002 Start*****************"); expect(editUnit !== undefined).assertTrue(); let undoManager: collaboration_edit.UndoRedoManager | undefined; @@ -282,7 +282,7 @@ export default function collaborationUndoRedoTest() { * 1. get undo redo manager * 2. delete undo redo manager */ - it("CollaborationEdit_UndoRedo_0006", 0, async () => { + it("CollaborationEdit_UndoRedo_0006", Level.LEVEL0, async () => { console.log(TAG + "*****************CollaborationEdit_UndoRedo_0006 Start*****************"); expect(editUnit !== undefined).assertTrue(); let undoManager: collaboration_edit.UndoRedoManager | undefined; diff --git a/data_object/frameworks/jskitsimpl/include/adaptor/js_common.h b/data_object/frameworks/jskitsimpl/include/adaptor/js_common.h index b4d3d348..678e3df9 100644 --- a/data_object/frameworks/jskitsimpl/include/adaptor/js_common.h +++ b/data_object/frameworks/jskitsimpl/include/adaptor/js_common.h @@ -20,6 +20,7 @@ class Constants { public: static constexpr const char *CHANGE = "change"; static constexpr const char *STATUS = "status"; + static constexpr const char *PROGRESS = "progressChanged"; }; #define OBJECT_REVT_NOTHING diff --git a/data_object/frameworks/jskitsimpl/include/adaptor/js_distributedobject.h b/data_object/frameworks/jskitsimpl/include/adaptor/js_distributedobject.h index c0b6f0b5..951665b6 100644 --- a/data_object/frameworks/jskitsimpl/include/adaptor/js_distributedobject.h +++ b/data_object/frameworks/jskitsimpl/include/adaptor/js_distributedobject.h @@ -19,8 +19,8 @@ #include "js_object_wrapper.h" namespace OHOS::ObjectStore { struct ConstructContext { - DistributedObjectStore *objectStore; - DistributedObject *object; + DistributedObjectStore *objectStore = nullptr; + DistributedObject *object = nullptr; }; class JSDistributedObject { diff --git a/data_object/frameworks/jskitsimpl/include/adaptor/js_object_wrapper.h b/data_object/frameworks/jskitsimpl/include/adaptor/js_object_wrapper.h index 3730ec8b..cf56d94e 100644 --- a/data_object/frameworks/jskitsimpl/include/adaptor/js_object_wrapper.h +++ b/data_object/frameworks/jskitsimpl/include/adaptor/js_object_wrapper.h @@ -34,8 +34,8 @@ public: std::string GetObjectId(); private: - DistributedObjectStore *objectStore_; - DistributedObject *object_; + DistributedObjectStore *objectStore_ = nullptr; + DistributedObject *object_ = nullptr; std::shared_ptr watcher_ = nullptr; std::shared_mutex watchMutex_{}; std::mutex mutex_; diff --git a/data_object/frameworks/jskitsimpl/include/adaptor/js_watcher.h b/data_object/frameworks/jskitsimpl/include/adaptor/js_watcher.h index f3782796..81e46dff 100644 --- a/data_object/frameworks/jskitsimpl/include/adaptor/js_watcher.h +++ b/data_object/frameworks/jskitsimpl/include/adaptor/js_watcher.h @@ -48,7 +48,7 @@ public: virtual void Clear(napi_env env); EventHandler *Find(napi_env env, napi_value handler); - EventHandler *handlers_; + EventHandler *handlers_ = nullptr; }; class ChangeEventListener : public EventListener { @@ -63,8 +63,8 @@ public: void Clear(napi_env env) override; private: bool isWatched_ = false; - DistributedObjectStore *objectStore_; - DistributedObject *object_; + DistributedObjectStore *objectStore_ = nullptr; + DistributedObject *object_ = nullptr; std::weak_ptr watcher_; }; @@ -81,6 +81,20 @@ private: std::string sessionId_; }; +class ProgressEventListener : public EventListener { +public: + ProgressEventListener(std::weak_ptr watcher, const std::string &sessionId); + bool Add(napi_env env, napi_value handler) override; + + bool Del(napi_env env, napi_value handler) override; + + void Clear(napi_env env) override; + +private: + std::weak_ptr watcher_; + std::string sessionId_; +}; + class JSWatcher : public UvQueue { public: JSWatcher(const napi_env env, DistributedObjectStore *objectStore, DistributedObject *object); @@ -95,9 +109,13 @@ public: void Emit(const char *type, const std::string &sessionId, const std::string &networkId, const std::string &status); + void Emit(const char *type, const std::string &sessionId, int32_t progress); + bool IsEmpty(); - void SetListener(ChangeEventListener *changeEventListener, StatusEventListener *statusEventListener); + void SetListener(ChangeEventListener *changeEventListener, StatusEventListener *statusEventListener, + ProgressEventListener *progressEventListener); + private: struct ChangeArgs { ChangeArgs(const napi_ref callback, const std::string &sessionId, const std::vector &changeData); @@ -113,12 +131,20 @@ private: const std::string networkId_; const std::string status_; }; + struct ProgressArgs { + ProgressArgs(const napi_ref callback, const std::string &sessionId, int32_t progress); + napi_ref callback_; + const std::string sessionId_; + int32_t progress_ = 0; + }; EventListener *Find(const char *type); static void ProcessChange(napi_env env, std::list &args); static void ProcessStatus(napi_env env, std::list &args); + static void ProcessProgress(napi_env env, std::list &args); napi_env env_; - ChangeEventListener *changeEventListener_; - StatusEventListener *statusEventListener_; + ChangeEventListener *changeEventListener_ = nullptr; + StatusEventListener *statusEventListener_ = nullptr; + ProgressEventListener *progressEventListener_ = nullptr; }; class WatcherImpl : public ObjectWatcher { diff --git a/data_object/frameworks/jskitsimpl/include/adaptor/progress_notifier_impl.h b/data_object/frameworks/jskitsimpl/include/adaptor/progress_notifier_impl.h new file mode 100644 index 00000000..9867745c --- /dev/null +++ b/data_object/frameworks/jskitsimpl/include/adaptor/progress_notifier_impl.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 PROGRESS_NOTIFIER_IMPL_H +#define PROGRESS_NOTIFIER_IMPL_H + +#include "js_watcher.h" +#include + +namespace OHOS::ObjectStore { +class ProgressNotifierImpl : public ProgressNotifier { +public: + static std::shared_ptr GetInstance(); + virtual ~ProgressNotifierImpl(); + + void AddWatcher(const std::string &sessionId, std::weak_ptr watcher); + void DelWatcher(const std::string &sessionId); + void OnChanged(const std::string &sessionId, int32_t progress) override; + +private: + std::mutex mutex_; + std::map> watchers_; +}; +} // namespace OHOS::ObjectStore + +#endif // PROGRESS_NOTIFIER_IMPL_H \ No newline at end of file diff --git a/data_object/frameworks/jskitsimpl/include/common/napi_queue.h b/data_object/frameworks/jskitsimpl/include/common/napi_queue.h index 2e5b0d9b..c177f269 100644 --- a/data_object/frameworks/jskitsimpl/include/common/napi_queue.h +++ b/data_object/frameworks/jskitsimpl/include/common/napi_queue.h @@ -14,9 +14,8 @@ */ #ifndef NAPI_QUEUE_H #define NAPI_QUEUE_H -#include + #include -#include #include "napi/native_node_api.h" #include "object_error.h" @@ -25,7 +24,7 @@ namespace OHOS::ObjectStore { using NapiCbInfoParser = std::function; using NapiAsyncExecute = std::function; using NapiAsyncComplete = std::function; - +static constexpr size_t ARGC_MAX = 6; struct ContextBase { virtual ~ContextBase(); void GetCbInfo( diff --git a/data_object/frameworks/jskitsimpl/include/common/uv_queue.h b/data_object/frameworks/jskitsimpl/include/common/uv_queue.h index 7cc84ff5..d72fc4b7 100644 --- a/data_object/frameworks/jskitsimpl/include/common/uv_queue.h +++ b/data_object/frameworks/jskitsimpl/include/common/uv_queue.h @@ -16,8 +16,8 @@ #define UV_QUEUE_H #include #include -#include #include +#include #include "napi/native_node_api.h" @@ -28,7 +28,7 @@ public: UvQueue(napi_env env); virtual ~UvQueue(); - void CallFunction(Process process, void *argv); + bool CallFunction(Process process, void *argv); private: struct UvEntry { diff --git a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp index 96aedc2d..6ac158bb 100644 --- a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp +++ b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp @@ -16,7 +16,6 @@ #include "js_distributedobject.h" #include - #include "js_common.h" #include "js_util.h" #include "logger.h" @@ -309,7 +308,9 @@ napi_value JSDistributedObject::GetSaveResultCons( napi_env env, std::string &sessionId, double version, std::string deviceId) { const char *objectName = "SaveResult"; - napi_value napiSessionId, napiVersion, napiDeviceId; + napi_value napiSessionId; + napi_value napiVersion; + napi_value napiDeviceId; napi_value result; napi_status status = JSUtil::SetValue(env, sessionId, napiSessionId); diff --git a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp index 2ea6174d..298a7530 100644 --- a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp +++ b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp @@ -17,6 +17,7 @@ #include +#include "application_context.h" #include "accesstoken_kit.h" #include "js_ability.h" #include "js_common.h" @@ -27,9 +28,11 @@ #include "objectstore_errors.h" namespace OHOS::ObjectStore { -constexpr size_t TYPE_SIZE = 10; +constexpr size_t TYPE_SIZE = 20; +constexpr size_t PARAM_COUNT_MAX = 3; static ConcurrentMap> g_statusCallBacks; static ConcurrentMap> g_changeCallBacks; +static ConcurrentMap> g_progressCallBacks; bool JSDistributedObjectStore::AddCallback(napi_env env, ConcurrentMap> &callbacks, const std::string &objectId, napi_value callback) { @@ -137,6 +140,7 @@ napi_value JSDistributedObjectStore::NewDistributedObject( RestoreWatchers(env, objectWrapper, objectId); objectStore->NotifyCachedStatus(object->GetSessionId()); + objectStore->NotifyProgressStatus(object->GetSessionId()); NOT_MATCH_RETURN_NULL(status == napi_ok); return result; } @@ -214,6 +218,7 @@ napi_value JSDistributedObjectStore::JSDestroyObjectSync(napi_env env, napi_call objectWrapper->DeleteWatch(env, Constants::CHANGE); objectWrapper->DeleteWatch(env, Constants::STATUS); + objectWrapper->DeleteWatch(env, Constants::PROGRESS); objectInfo->DeleteObject(objectWrapper->GetObject()->GetSessionId()); objectWrapper->DestroyObject(); return nullptr; @@ -330,9 +335,9 @@ bool JSDistributedObjectStore::GetBundleNameWithContext(napi_env env, napi_value std::string JSDistributedObjectStore::GetBundleName(napi_env env) { static std::string bundleName; -// if (bundleName.empty()) { -// bundleName = AbilityRuntime::Context::GetApplicationContext()->GetBundleName(); -// } + if (bundleName.empty()) { + bundleName = AbilityRuntime::Context::GetApplicationContext()->GetBundleName(); + } return bundleName; } @@ -370,6 +375,21 @@ void JSDistributedObjectStore::RestoreWatchers(napi_env env, JSObjectWrapper *wr if (!watchResult) { LOG_INFO("no status %{public}s", objectId.c_str()); } + watchResult = + g_progressCallBacks.ComputeIfPresent(objectId, [&](const std::string &key, std::list &lists) { + for (auto callback : lists) { + status = napi_get_reference_value(env, callback, &callbackValue); + if (status != napi_ok) { + LOG_ERROR("error! %{public}d", status); + continue; + } + wrapper->AddWatch(env, Constants::PROGRESS, callbackValue); + } + return true; + }); + if (!watchResult) { + LOG_INFO("no status %{public}s", objectId.c_str()); + } } // function recordCallback(version: number, type: 'change', objectId: string, @@ -409,9 +429,11 @@ napi_value JSDistributedObjectStore::JSRecordCallback(napi_env env, napi_callbac bool addResult = true; if (!strcmp(Constants::CHANGE, type)) { - addResult = AddCallback(env, g_changeCallBacks, objectId, argv[3]); + addResult = AddCallback(env, g_changeCallBacks, objectId, argv[PARAM_COUNT_MAX]); } else if (!strcmp(Constants::STATUS, type)) { - addResult = AddCallback(env, g_statusCallBacks, objectId, argv[3]); + addResult = AddCallback(env, g_statusCallBacks, objectId, argv[PARAM_COUNT_MAX]); + } else if (!strcmp(Constants::PROGRESS, type)) { + addResult = AddCallback(env, g_progressCallBacks, objectId, argv[PARAM_COUNT_MAX]); } NAPI_ASSERT_ERRCODE_V9(env, addResult, version, innerError); napi_value result = nullptr; @@ -456,6 +478,8 @@ napi_value JSDistributedObjectStore::JSDeleteCallback(napi_env env, napi_callbac delResult = DelCallback(env, g_changeCallBacks, objectId); } else if (!strcmp(Constants::STATUS, type)) { delResult = DelCallback(env, g_statusCallBacks, objectId); + } else if (!strcmp(Constants::PROGRESS, type)) { + delResult = DelCallback(env, g_progressCallBacks, objectId); } } else { napi_valuetype callbackType = napi_undefined; @@ -463,9 +487,11 @@ napi_value JSDistributedObjectStore::JSDeleteCallback(napi_env env, napi_callbac NAPI_ASSERT_ERRCODE_V9(env, status == napi_ok && callbackType == napi_function, version, std::make_shared("callback", "function")); if (!strcmp(Constants::CHANGE, type)) { - delResult = DelCallback(env, g_changeCallBacks, objectId, argv[3]); + delResult = DelCallback(env, g_changeCallBacks, objectId, argv[PARAM_COUNT_MAX]); } else if (!strcmp(Constants::STATUS, type)) { - delResult = DelCallback(env, g_statusCallBacks, objectId, argv[3]); + delResult = DelCallback(env, g_statusCallBacks, objectId, argv[PARAM_COUNT_MAX]); + } else if (!strcmp(Constants::PROGRESS, type)) { + delResult = DelCallback(env, g_progressCallBacks, objectId, argv[PARAM_COUNT_MAX]); } } NAPI_ASSERT_ERRCODE_V9(env, delResult, version, innerError); @@ -488,11 +514,11 @@ napi_value JSDistributedObjectStore::JSEquenceNum(napi_env env, napi_callback_in // don't create distributed data object while this application is sandbox bool JSDistributedObjectStore::IsSandBox() { -// int32_t dlpFlag = Security::AccessToken::AccessTokenKit::GetHapDlpFlag( -// AbilityRuntime::Context::GetApplicationContext()->GetApplicationInfo()->accessTokenId); -// if (dlpFlag != 0) { -// return true; -// } + int32_t dlpFlag = Security::AccessToken::AccessTokenKit::GetHapDlpFlag( + AbilityRuntime::Context::GetApplicationContext()->GetApplicationInfo()->accessTokenId); + if (dlpFlag != 0) { + return true; + } return false; } } // namespace OHOS::ObjectStore diff --git a/data_object/frameworks/jskitsimpl/src/adaptor/js_object_wrapper.cpp b/data_object/frameworks/jskitsimpl/src/adaptor/js_object_wrapper.cpp index cfa505f8..b6331a36 100644 --- a/data_object/frameworks/jskitsimpl/src/adaptor/js_object_wrapper.cpp +++ b/data_object/frameworks/jskitsimpl/src/adaptor/js_object_wrapper.cpp @@ -12,10 +12,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #include "js_object_wrapper.h" -#include #include "logger.h" namespace OHOS::ObjectStore { JSObjectWrapper::JSObjectWrapper(DistributedObjectStore *objectStore, DistributedObject *object) @@ -46,7 +46,8 @@ bool JSObjectWrapper::AddWatch(napi_env env, const char *type, napi_value handle std::weak_ptr watcher = watcher_; auto changeEventListener = new ChangeEventListener(watcher, objectStore_, object_); auto statusEventListener = new StatusEventListener(watcher, object_->GetSessionId()); - watcher_->SetListener(changeEventListener, statusEventListener); + auto progressEventListener = new ProgressEventListener(watcher, object_->GetSessionId()); + watcher_->SetListener(changeEventListener, statusEventListener, progressEventListener); } return watcher_->On(type, handler); } diff --git a/data_object/frameworks/jskitsimpl/src/adaptor/js_watcher.cpp b/data_object/frameworks/jskitsimpl/src/adaptor/js_watcher.cpp index ee612ca0..d738b850 100644 --- a/data_object/frameworks/jskitsimpl/src/adaptor/js_watcher.cpp +++ b/data_object/frameworks/jskitsimpl/src/adaptor/js_watcher.cpp @@ -13,20 +13,19 @@ * limitations under the License. */ -#include "js_watcher.h" - -#include - +#include #include "anonymous.h" #include "js_common.h" #include "js_util.h" #include "logger.h" #include "notifier_impl.h" #include "objectstore_errors.h" +#include "progress_notifier_impl.h" namespace OHOS::ObjectStore { JSWatcher::JSWatcher(const napi_env env, DistributedObjectStore *objectStore, DistributedObject *object) - : UvQueue(env), env_(env), changeEventListener_(nullptr), statusEventListener_(nullptr) + : UvQueue(env), env_(env), changeEventListener_(nullptr), statusEventListener_(nullptr), + progressEventListener_(nullptr) { } @@ -34,8 +33,10 @@ JSWatcher::~JSWatcher() { delete changeEventListener_; delete statusEventListener_; + delete progressEventListener_; changeEventListener_ = nullptr; statusEventListener_ = nullptr; + progressEventListener_ = nullptr; } bool JSWatcher::On(const char *type, napi_value handler) @@ -78,9 +79,11 @@ void JSWatcher::ProcessChange(napi_env env, std::list &args) NOT_MATCH_GOTO_ERROR(status == napi_ok); JSUtil::SetValue(env, changeArgs->changeData_, param[1]); NOT_MATCH_GOTO_ERROR(status == napi_ok); - LOG_INFO("start %{public}s, %{public}zu", changeArgs->sessionId_.c_str(), changeArgs->changeData_.size()); + LOG_INFO("start %{public}s, %{public}zu", Anonymous::Change(changeArgs->sessionId_).c_str(), + changeArgs->changeData_.size()); status = napi_call_function(env, global, callback, ARGV_SIZE, param, &result); - LOG_INFO("end %{public}s, %{public}zu", changeArgs->sessionId_.c_str(), changeArgs->changeData_.size()); + LOG_INFO("end %{public}s, %{public}zu", Anonymous::Change(changeArgs->sessionId_).c_str(), + changeArgs->changeData_.size()); NOT_MATCH_GOTO_ERROR(status == napi_ok); } ERROR: @@ -96,7 +99,7 @@ void JSWatcher::Emit(const char *type, const std::string &sessionId, const std:: LOG_ERROR("empty change"); return; } - LOG_INFO("start %{public}s, %{public}s", sessionId.c_str(), changeData.at(0).c_str()); + LOG_INFO("start %{public}s, %{public}s", Anonymous::Change(sessionId).c_str(), changeData.at(0).c_str()); EventListener *listener = Find(type); if (listener == nullptr) { LOG_ERROR("error type %{public}s", type); @@ -109,7 +112,10 @@ void JSWatcher::Emit(const char *type, const std::string &sessionId, const std:: LOG_ERROR("JSWatcher::Emit no memory for changeArgs malloc!"); return; } - CallFunction(ProcessChange, changeArgs); + if (!CallFunction(ProcessChange, changeArgs)) { + delete changeArgs; + changeArgs = nullptr; + } } } @@ -121,6 +127,9 @@ EventListener *JSWatcher::Find(const char *type) if (!strcmp(Constants::STATUS, type)) { return statusEventListener_; } + if (!strcmp(Constants::PROGRESS, type)) { + return progressEventListener_; + } return nullptr; } @@ -143,10 +152,10 @@ void JSWatcher::ProcessStatus(napi_env env, std::list &args) NOT_MATCH_GOTO_ERROR(status == napi_ok); status = JSUtil::SetValue(env, statusArgs->status_, param[2]); NOT_MATCH_GOTO_ERROR(status == napi_ok); - LOG_INFO("start %{public}s, %{public}s, %{public}s", statusArgs->sessionId_.c_str(), + LOG_INFO("start %{public}s, %{public}s, %{public}s", Anonymous::Change(statusArgs->sessionId_).c_str(), Anonymous::Change(statusArgs->networkId_).c_str(), statusArgs->status_.c_str()); status = napi_call_function(env, global, callback, ARGV_SIZE, param, &result); - LOG_INFO("end %{public}s, %{public}s, %{public}s", statusArgs->sessionId_.c_str(), + LOG_INFO("end %{public}s, %{public}s, %{public}s", Anonymous::Change(statusArgs->sessionId_).c_str(), Anonymous::Change(statusArgs->networkId_).c_str(), statusArgs->status_.c_str()); NOT_MATCH_GOTO_ERROR(status == napi_ok); } @@ -163,10 +172,12 @@ void JSWatcher::Emit( const char *type, const std::string &sessionId, const std::string &networkId, const std::string &status) { if (sessionId.empty() || networkId.empty()) { - LOG_ERROR("empty %{public}s %{public}s", sessionId.c_str(), Anonymous::Change(networkId).c_str()); + LOG_ERROR("empty %{public}s %{public}s", Anonymous::Change(sessionId).c_str(), + Anonymous::Change(networkId).c_str()); return; } - LOG_INFO("status change %{public}s %{public}s", sessionId.c_str(), Anonymous::Change(networkId).c_str()); + LOG_INFO("status change %{public}s %{public}s", Anonymous::Change(sessionId).c_str(), + Anonymous::Change(networkId).c_str()); EventListener *listener = Find(type); if (listener == nullptr) { LOG_ERROR("error type %{public}s", type); @@ -179,23 +190,88 @@ void JSWatcher::Emit( LOG_ERROR("JSWatcher::Emit no memory for StatusArgs malloc!"); return; } - CallFunction(ProcessStatus, changeArgs); + if (!CallFunction(ProcessStatus, changeArgs)) { + delete changeArgs; + changeArgs = nullptr; + } + } + return; +} + +void JSWatcher::ProcessProgress(napi_env env, std::list &args) +{ + constexpr static int8_t ARGV_SIZE = 2; + napi_value callback = nullptr; + napi_value global = nullptr; + napi_value param[ARGV_SIZE]; + napi_value result; + napi_status status = napi_get_global(env, &global); + NOT_MATCH_GOTO_ERROR(status == napi_ok); + for (auto item : args) { + ProgressArgs *progressArgs = static_cast(item); + status = napi_get_reference_value(env, progressArgs->callback_, &callback); + NOT_MATCH_GOTO_ERROR(status == napi_ok); + status = JSUtil::SetValue(env, progressArgs->sessionId_, param[0]); + NOT_MATCH_GOTO_ERROR(status == napi_ok); + status = JSUtil::SetValue(env, static_cast(progressArgs->progress_), param[1]); + NOT_MATCH_GOTO_ERROR(status == napi_ok); + LOG_INFO("start %{public}s, %{public}d", Anonymous::Change(progressArgs->sessionId_).c_str(), + progressArgs->progress_); + status = napi_call_function(env, global, callback, ARGV_SIZE, param, &result); + LOG_INFO("end %{public}s, %{public}d", Anonymous::Change(progressArgs->sessionId_).c_str(), + progressArgs->progress_); + NOT_MATCH_GOTO_ERROR(status == napi_ok); + } +ERROR: + LOG_DEBUG("do clear"); + for (auto item : args) { + ProgressArgs *progressArgs = static_cast(item); + delete progressArgs; + } + args.clear(); +} + +void JSWatcher::Emit(const char *type, const std::string &sessionId, int32_t progress) +{ + if (sessionId.empty()) { + LOG_ERROR("empty sessionId %{public}s", Anonymous::Change(sessionId).c_str()); + return; + } + LOG_INFO("progress change %{public}s %{public}d", Anonymous::Change(sessionId).c_str(), progress); + EventListener *listener = Find(type); + if (listener == nullptr) { + LOG_ERROR("error type %{public}s", type); + return; + } + + for (EventHandler *handler = listener->handlers_; handler != nullptr; handler = handler->next) { + ProgressArgs *progressArgs = new (std::nothrow) ProgressArgs(handler->callbackRef, sessionId, progress); + if (progressArgs == nullptr) { + LOG_ERROR("JSWatcher::Emit no memory for ProgressArgs malloc!"); + return; + } + if (!CallFunction(ProcessProgress, progressArgs)) { + delete progressArgs; + progressArgs = nullptr; + } } return; } bool JSWatcher::IsEmpty() { - if (changeEventListener_->IsEmpty() && statusEventListener_->IsEmpty()) { + if (changeEventListener_->IsEmpty() && statusEventListener_->IsEmpty() && progressEventListener_->IsEmpty()) { return true; } return false; } -void JSWatcher::SetListener(ChangeEventListener *changeEventListener, StatusEventListener *statusEventListener) +void JSWatcher::SetListener(ChangeEventListener *changeEventListener, StatusEventListener *statusEventListener, + ProgressEventListener *progressEventListener) { changeEventListener_ = changeEventListener; statusEventListener_ = statusEventListener; + progressEventListener_ = progressEventListener; } EventHandler *EventListener::Find(napi_env env, napi_value handler) @@ -301,9 +377,9 @@ bool ChangeEventListener::Add(napi_env env, napi_value handler) std::shared_ptr watcher = std::make_shared(watcher_); uint32_t ret = objectStore_->Watch(object_, watcher); if (ret != SUCCESS) { - LOG_ERROR("Watch %{public}s error", object_->GetSessionId().c_str()); + LOG_ERROR("Watch %{public}s error", Anonymous::Change(object_->GetSessionId()).c_str()); } else { - LOG_INFO("Watch %{public}s success", object_->GetSessionId().c_str()); + LOG_INFO("Watch %{public}s success", Anonymous::Change(object_->GetSessionId()).c_str()); isWatched_ = true; } } @@ -316,9 +392,9 @@ bool ChangeEventListener::Del(napi_env env, napi_value handler) if (isEmpty && isWatched_ && object_ != nullptr) { uint32_t ret = objectStore_->UnWatch(object_); if (ret != SUCCESS) { - LOG_ERROR("UnWatch %{public}s error", object_->GetSessionId().c_str()); + LOG_ERROR("UnWatch %{public}s error", Anonymous::Change(object_->GetSessionId()).c_str()); } else { - LOG_INFO("UnWatch %{public}s success", object_->GetSessionId().c_str()); + LOG_INFO("UnWatch %{public}s success", Anonymous::Change(object_->GetSessionId()).c_str()); isWatched_ = false; } } @@ -331,9 +407,9 @@ void ChangeEventListener::Clear(napi_env env) if (isWatched_ && object_ != nullptr) { uint32_t ret = objectStore_->UnWatch(object_); if (ret != SUCCESS) { - LOG_ERROR("UnWatch %{public}s error", object_->GetSessionId().c_str()); + LOG_ERROR("UnWatch %{public}s error", Anonymous::Change(object_->GetSessionId()).c_str()); } else { - LOG_INFO("UnWatch %{public}s success", object_->GetSessionId().c_str()); + LOG_INFO("UnWatch %{public}s success", Anonymous::Change(object_->GetSessionId()).c_str()); isWatched_ = false; } } @@ -347,7 +423,7 @@ ChangeEventListener::ChangeEventListener( bool StatusEventListener::Add(napi_env env, napi_value handler) { - LOG_INFO("Add status watch %{public}s", sessionId_.c_str()); + LOG_INFO("Add status watch %{public}s", Anonymous::Change(sessionId_).c_str()); NotifierImpl::GetInstance()->AddWatcher(sessionId_, watcher_); return EventListener::Add(env, handler); } @@ -355,7 +431,7 @@ bool StatusEventListener::Add(napi_env env, napi_value handler) bool StatusEventListener::Del(napi_env env, napi_value handler) { if (EventListener::Del(env, handler)) { - LOG_INFO("Del status watch %{public}s", sessionId_.c_str()); + LOG_INFO("Del status watch %{public}s", Anonymous::Change(sessionId_).c_str()); NotifierImpl::GetInstance()->DelWatcher(sessionId_); return true; } @@ -373,6 +449,34 @@ StatusEventListener::StatusEventListener(std::weak_ptr watcher, const { } +bool ProgressEventListener::Add(napi_env env, napi_value handler) +{ + LOG_INFO("Add progress watch %{public}s", Anonymous::Change(sessionId_).c_str()); + ProgressNotifierImpl::GetInstance()->AddWatcher(sessionId_, watcher_); + return EventListener::Add(env, handler); +} + +bool ProgressEventListener::Del(napi_env env, napi_value handler) +{ + if (EventListener::Del(env, handler)) { + LOG_INFO("Del progress watch %{public}s", Anonymous::Change(sessionId_).c_str()); + ProgressNotifierImpl::GetInstance()->DelWatcher(sessionId_); + return true; + } + return false; +} + +void ProgressEventListener::Clear(napi_env env) +{ + ProgressNotifierImpl::GetInstance()->DelWatcher(sessionId_); + EventListener::Clear(env); +} + +ProgressEventListener::ProgressEventListener(std::weak_ptr watcher, const std::string &sessionId) + : watcher_(watcher), sessionId_(sessionId) +{ +} + JSWatcher::ChangeArgs::ChangeArgs( const napi_ref callback, const std::string &sessionId, const std::vector &changeData) : callback_(callback), sessionId_(sessionId), changeData_(changeData) @@ -384,4 +488,9 @@ JSWatcher::StatusArgs::StatusArgs( : callback_(callback), sessionId_(sessionId), networkId_(networkId), status_(status) { } + +JSWatcher::ProgressArgs::ProgressArgs(const napi_ref callback, const std::string &sessionId, int32_t progress) + : callback_(callback), sessionId_(sessionId), progress_(progress) +{ +} } // namespace OHOS::ObjectStore diff --git a/data_object/frameworks/jskitsimpl/src/adaptor/progress_notifier_impl.cpp b/data_object/frameworks/jskitsimpl/src/adaptor/progress_notifier_impl.cpp new file mode 100644 index 00000000..a1c7286d --- /dev/null +++ b/data_object/frameworks/jskitsimpl/src/adaptor/progress_notifier_impl.cpp @@ -0,0 +1,77 @@ +/* + * 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_notifier_impl.h" + +#include "anonymous.h" +#include "logger.h" +#include "objectstore_errors.h" + +namespace OHOS::ObjectStore { + +std::shared_ptr ProgressNotifierImpl::GetInstance() +{ + static std::shared_ptr instance; + static std::mutex instanceLock; + std::lock_guard lockGuard(instanceLock); + if (instance == nullptr) { + instance = std::make_shared(); + DistributedObjectStore *storeInstance = DistributedObjectStore::GetInstance(); + if (storeInstance == nullptr) { + LOG_ERROR("Get store instance nullptr"); + return instance; + } + auto ret = storeInstance->SetProgressNotifier(instance); + if (ret != SUCCESS) { + LOG_ERROR("SetProgressNotifier %{public}d error", ret); + } else { + LOG_INFO("SetProgressNotifier success"); + } + } + return instance; +} + +void ProgressNotifierImpl::AddWatcher(const std::string &sessionId, std::weak_ptr watcher) +{ + std::lock_guard lock(mutex_); + watchers_.insert_or_assign(sessionId, watcher); +} + +void ProgressNotifierImpl::DelWatcher(const std::string &sessionId) +{ + std::lock_guard lock(mutex_); + watchers_.erase(sessionId); +} + +void ProgressNotifierImpl::OnChanged(const std::string &sessionId, int32_t progress) +{ + std::lock_guard lock(mutex_); + if (watchers_.count(sessionId) != 0) { + LOG_INFO("start emit %{public}s %{public}d", Anonymous::Change(sessionId).c_str(), progress); + std::shared_ptr lockedWatcher = watchers_.at(sessionId).lock(); + if (lockedWatcher) { + lockedWatcher->Emit("progressChanged", sessionId, progress); + LOG_INFO("end emit %{public}s %{public}d", Anonymous::Change(sessionId).c_str(), progress); + } else { + LOG_ERROR("watcher expired"); + } + } +} + +ProgressNotifierImpl::~ProgressNotifierImpl() +{ +} + +} // namespace OHOS::ObjectStore diff --git a/data_object/frameworks/jskitsimpl/src/common/js_util.cpp b/data_object/frameworks/jskitsimpl/src/common/js_util.cpp index f3360b46..51d04369 100644 --- a/data_object/frameworks/jskitsimpl/src/common/js_util.cpp +++ b/data_object/frameworks/jskitsimpl/src/common/js_util.cpp @@ -19,7 +19,7 @@ #include "logger.h" namespace OHOS::ObjectStore { -constexpr int32_t STR_MAX_LENGTH = 4096; +constexpr int32_t STR_MAX_LENGTH = 500 * 1024; constexpr size_t STR_TAIL_LENGTH = 1; /* napi_value <-> bool */ @@ -75,7 +75,8 @@ napi_status JSUtil::GetValue(napi_env env, napi_value in, std::string &out) { size_t maxLen = STR_MAX_LENGTH; napi_status status = napi_get_value_string_utf8(env, in, NULL, 0, &maxLen); - if (status != napi_ok || maxLen <= 0) { + if (status != napi_ok || maxLen <= 0 || maxLen > STR_MAX_LENGTH) { + LOG_ERROR("napi_get_value_string_utf8 failed! status=%{public}d, maxLen=%{public}zu", status, maxLen); return napi_generic_failure; } char *buf = new (std::nothrow) char[maxLen + STR_TAIL_LENGTH]; diff --git a/data_object/frameworks/jskitsimpl/src/common/napi_queue.cpp b/data_object/frameworks/jskitsimpl/src/common/napi_queue.cpp index ad348191..50722f42 100644 --- a/data_object/frameworks/jskitsimpl/src/common/napi_queue.cpp +++ b/data_object/frameworks/jskitsimpl/src/common/napi_queue.cpp @@ -19,8 +19,6 @@ #include "logger.h" namespace OHOS::ObjectStore { -static constexpr size_t ARGC_MAX = 6; - ContextBase::~ContextBase() { LOG_DEBUG("no memory leak after callback or promise[resolved/rejected]"); @@ -72,7 +70,7 @@ napi_value NapiQueue::AsyncWork(napi_env env, std::shared_ptr conte { AsyncContext *aCtx = new (std::nothrow) AsyncContext; if (aCtx == nullptr) { - LOG_ERROR("create aysnc context failed"); + LOG_ERROR("create async context failed"); return nullptr; } aCtx->ctxt = std::move(contextBase); diff --git a/data_object/frameworks/jskitsimpl/src/common/object_error.cpp b/data_object/frameworks/jskitsimpl/src/common/object_error.cpp index 3440ca83..08a01865 100644 --- a/data_object/frameworks/jskitsimpl/src/common/object_error.cpp +++ b/data_object/frameworks/jskitsimpl/src/common/object_error.cpp @@ -55,7 +55,8 @@ int DatabaseError::GetCode() std::string DatabaseError::GetMessage() { - return "Failed to create the in-memory database."; + return "Failed to create the in-memory database. The possible reason is that other distributed data object" + " has already set the same sessionId."; } int PermissionError::GetCode() diff --git a/data_object/frameworks/jskitsimpl/src/common/uv_queue.cpp b/data_object/frameworks/jskitsimpl/src/common/uv_queue.cpp index bad83162..82a617f7 100644 --- a/data_object/frameworks/jskitsimpl/src/common/uv_queue.cpp +++ b/data_object/frameworks/jskitsimpl/src/common/uv_queue.cpp @@ -12,9 +12,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "uv_queue.h" - #include + +#include "uv_queue.h" #include "logger.h" namespace OHOS::ObjectStore { @@ -46,38 +46,41 @@ void UvQueue::ExecUvWork(UvEntry *entry) entry = nullptr; } -void UvQueue::CallFunction(Process process, void *argv) +bool UvQueue::CallFunction(Process process, void *argv) { if (process == nullptr || argv == nullptr) { LOG_ERROR("nullptr"); - return; + return false; } - auto *uvEntry = new (std::nothrow)UvEntry { weak_from_this() }; + auto *uvEntry = new (std::nothrow) UvEntry{ weak_from_this() }; if (uvEntry == nullptr) { LOG_ERROR("no memory for UvEntry"); - return; + return false; } + auto rollbackAddition = [this, process, argv]() { + std::unique_lock lock(mutex_); + auto it = args_.find(process); + if (it != args_.end() && !it->second.empty()) { + it->second.pop_back(); + if (it->second.empty()) { + args_.erase(it); + } + } + }; { std::unique_lock cacheLock(mutex_); - if (args_.count(process) != 0) { - std::list newData = args_.at(process); - newData.push_back(argv); - args_.insert_or_assign(process, newData); - } else { - std::list data; - data.push_back(argv); - args_.insert_or_assign(process, data); - } + auto &processList = args_[process]; + processList.push_back(argv); } - auto task = [uvEntry]() { - UvQueue::ExecUvWork(uvEntry); - }; - if (napi_send_event(env_, task, napi_eprio_high) != 0) { - if (uvEntry != nullptr) { - delete uvEntry; - uvEntry = nullptr; - } + auto task = [uvEntry]() { UvQueue::ExecUvWork(uvEntry); }; + auto ret = napi_send_event(env_, task, napi_eprio_high); + if (ret != 0) { + LOG_ERROR("napi_send_event failed, ret: %{public}d.", ret); + rollbackAddition(); + delete uvEntry; + return false; } + return true; } } // namespace OHOS::ObjectStore diff --git a/data_object/interfaces/innerkits/BUILD.gn b/data_object/interfaces/innerkits/BUILD.gn index 8dcded7c..b791b275 100644 --- a/data_object/interfaces/innerkits/BUILD.gn +++ b/data_object/interfaces/innerkits/BUILD.gn @@ -15,10 +15,7 @@ import("//foundation/distributeddatamgr/data_object/data_object.gni") config("objectstore_config") { visibility = [ ":*" ] - cflags = [ - "-DHILOG_ENABLE", - "-Oz", - ] + cflags = [ "-DHILOG_ENABLE" ] include_dirs = [ "../../frameworks/innerkitsimpl/include/adaptor", diff --git a/data_object/interfaces/innerkits/distributed_object.h b/data_object/interfaces/innerkits/distributed_object.h index a17b0597..edc43778 100644 --- a/data_object/interfaces/innerkits/distributed_object.h +++ b/data_object/interfaces/innerkits/distributed_object.h @@ -15,8 +15,7 @@ #ifndef DISTRIBUTED_OBJECT_H #define DISTRIBUTED_OBJECT_H -#include -#include + #include #include #include "object_types.h" diff --git a/data_object/interfaces/innerkits/distributed_objectstore.h b/data_object/interfaces/innerkits/distributed_objectstore.h index 305a4772..0b21c196 100644 --- a/data_object/interfaces/innerkits/distributed_objectstore.h +++ b/data_object/interfaces/innerkits/distributed_objectstore.h @@ -16,6 +16,7 @@ #ifndef DISTRIBUTED_OBJECTSTORE_H #define DISTRIBUTED_OBJECTSTORE_H #include +#include #include "distributed_object.h" @@ -25,6 +26,10 @@ public: virtual void OnChanged( const std::string &sessionId, const std::string &networkId, const std::string &onlineStatus) = 0; }; +class ProgressNotifier { +public: + virtual void OnChanged(const std::string &sessionId, int32_t progress) = 0; +}; class DistributedObjectStore { public: virtual ~DistributedObjectStore(){}; @@ -112,6 +117,23 @@ public: * */ virtual void NotifyCachedStatus(const std::string &sessionId) = 0; + + /** + * @brief Set listening for progress. + * + * @param notifier Indicates callback function for progress. + * + * @return Returns 0 for success, others for failure. + */ + virtual uint32_t SetProgressNotifier(std::shared_ptr notifier) = 0; + + /** + * @brief Notify the status of the progress from the cached callback function according to the sessionId. + * + * @param sessionId Indicates the sessionId. + * + */ + virtual void NotifyProgressStatus(const std::string &sessionId) = 0; }; } // namespace OHOS::ObjectStore diff --git a/data_object/interfaces/innerkits/object_types.h b/data_object/interfaces/innerkits/object_types.h index 93286743..093fb636 100644 --- a/data_object/interfaces/innerkits/object_types.h +++ b/data_object/interfaces/innerkits/object_types.h @@ -16,7 +16,6 @@ #ifndef OHOS_OBJECT_ASSET_VALUE_H #define OHOS_OBJECT_ASSET_VALUE_H -#include #include "common_types.h" namespace OHOS { diff --git a/data_object/interfaces/jskits/BUILD.gn b/data_object/interfaces/jskits/BUILD.gn index bbca12dd..374b6e54 100644 --- a/data_object/interfaces/jskits/BUILD.gn +++ b/data_object/interfaces/jskits/BUILD.gn @@ -32,10 +32,7 @@ es2abc_gen_abc("gen_distributed_data_object_abc") { config("objectstore_config") { visibility = [ ":*" ] - cflags = [ - "-DHILOG_ENABLE", - "-Oz", - ] + cflags = [ "-DHILOG_ENABLE" ] include_dirs = [ "../../frameworks/jskitsimpl/include/adaptor", @@ -96,6 +93,7 @@ ohos_shared_library("distributeddataobject") { "../../frameworks/jskitsimpl/src/common/napi_queue.cpp", "../../frameworks/jskitsimpl/src/common/object_error.cpp", "../../frameworks/jskitsimpl/src/common/uv_queue.cpp", + "../../frameworks/jskitsimpl/src/adaptor/progress_notifier_impl.cpp", ] configs = [ ":objectstore_config" ] @@ -114,6 +112,7 @@ ohos_shared_library("distributeddataobject") { "bounds_checking_function:libsec_shared", "common_event_service:cesfwk_innerkits", "hilog:libhilog", + "ipc:ipc_single", "kv_store:distributeddata_inner", "kv_store:distributeddb", "libuv:uv", diff --git a/data_object/interfaces/jskits/distributed_data_object.js b/data_object/interfaces/jskits/distributed_data_object.js index e707ebb2..a021eaaf 100644 --- a/data_object/interfaces/jskits/distributed_data_object.js +++ b/data_object/interfaces/jskits/distributed_data_object.js @@ -14,6 +14,7 @@ */ const distributedObject = requireInternal('data.distributedDataObject'); +const fs = requireInternal('file.fs'); const SESSION_ID = '__sessionId'; const VERSION = '__version'; const COMPLEX_TYPE = '[COMPLEX]'; @@ -27,6 +28,12 @@ const SDK_VERSION_8 = 8; const SDK_VERSION_9 = 9; const SESSION_ID_REGEX = /^\w+$/; const SESSION_ID_MAX_LENGTH = 128; +const ASSETS_MAX_NUMBER = 50; +const HEAD_SIZE = 3; +const END_SIZE = 3; +const MIN_SIZE = HEAD_SIZE + END_SIZE + 3; +const REPLACE_CHAIN = '***'; +const DEFAULT_ANONYMOUS = '******'; class Distributed { constructor(obj) { @@ -305,15 +312,28 @@ function leaveSession(version, obj) { delete obj[SESSION_ID]; } +function toBeAnonymous(name) { + if (name == null || name === undefined || name === '') { + return ''; + } + if (name.length <= HEAD_SIZE) { + return DEFAULT_ANONYMOUS; + } + if (name.length < MIN_SIZE) { + return name.substring(0, HEAD_SIZE) + REPLACE_CHAIN; + } + return name.substring(0, HEAD_SIZE) + REPLACE_CHAIN + name.substring(name.length - END_SIZE); +} + function onWatch(version, type, obj, callback) { - console.info('start on ' + obj[SESSION_ID]); + console.info('start on ' + toBeAnonymous(obj[SESSION_ID])); if (obj[SESSION_ID] != null && obj[SESSION_ID] !== undefined && obj[SESSION_ID].length > 0) { distributedObject.on(version, type, obj, callback); } } function offWatch(version, type, obj, callback = undefined) { - console.info('start off ' + obj[SESSION_ID] + ' ' + callback); + console.info('start off ' + toBeAnonymous(obj[SESSION_ID]) + ' ' + callback); if (obj[SESSION_ID] != null && obj[SESSION_ID] !== undefined && obj[SESSION_ID].length > 0) { if (callback !== undefined || callback != null) { distributedObject.off(version, type, obj, callback); @@ -343,6 +363,55 @@ function newDistributedV9(context, obj) { return new DistributedV9(obj, context); } +function appendPropertyToObj(result, obj) { + result.__proxy = Object.assign(result.__proxy, obj); + Object.keys(obj).forEach(key => { + Object.defineProperty(result, key, { + enumerable: true, + configurable: true, + get: function () { + return result.__proxy[key]; + }, + set: function (newValue) { + result.__proxy[key] = newValue; + } + }); + }); +} + +function getDefaultAsset(uri, distributedDir) { + if (uri == null) { + throw { + code: 15400002, + message: 'The asset uri to be set is null.' + }; + } + const fileName = uri.substring(uri.lastIndexOf('/') + 1); + const filePath = distributedDir + '/' + fileName; + let stat; + try { + stat = fs.statSync(filePath); + return { + name: fileName, + uri: uri, + path: filePath, + createTime: stat.ctime.toString(), + modifyTime: stat.mtime.toString(), + size: stat.size.toString() + }; + } catch (error) { + console.error(error); + return { + name: '', + uri: '', + path: '', + createTime: 0, + modifyTime: 0, + size: 0 + }; + } +} + class DistributedV9 { constructor(obj, context) { @@ -430,6 +499,70 @@ class DistributedV9 { return this.__proxy.bindAssetStore(assetkey, bindInfo, callback); } + setAsset(assetKey, uri) { + if (this.__proxy[SESSION_ID] != null && this.__proxy[SESSION_ID] !== '') { + throw { + code: 15400003, + message: 'SessionId has been set, and asset cannot be set.' + }; + } + if (!assetKey || !uri) { + throw { + code: 15400002, + message: 'The property or uri of the asset is invalid.' + }; + } + + let assetObj = {}; + const distributedDir = this.__context.distributedFilesDir; + const asset = getDefaultAsset(uri, distributedDir); + assetObj[assetKey] = [asset]; + assetObj[assetKey + '0'] = asset; + appendPropertyToObj(this, assetObj); + return Promise.resolve(); + } + + setAssets(assetsKey, uris) { + if (this.__proxy[SESSION_ID] != null && this.__proxy[SESSION_ID] !== '') { + throw { + code: 15400003, + message: 'SessionId has been set, and assets cannot be set.' + }; + } + if (!assetsKey) { + throw { + code: 15400002, + message: 'The property of the assets is invalid.' + }; + } + if (!Array.isArray(uris) || uris.length <= 0 || uris.length > ASSETS_MAX_NUMBER) { + throw { + code: 15400002, + message: 'The uri array of the set assets is not an array or the length is invalid.' + }; + } + for (let index = 0; index < uris.length; index++) { + if (!uris[index]) { + throw { + code: 15400002, + message: 'Uri in assets array is invalid.' + }; + } + } + + let assetObj = {}; + let assets = []; + const distributedDir = this.__context.distributedFilesDir; + for (let index = 0; index < uris.length; index++) { + const asset = getDefaultAsset(uris[index], distributedDir); + assets.push(asset); + assetObj[assetsKey + index] = asset; + } + assetObj[assetsKey] = assets; + appendPropertyToObj(this, assetObj); + return Promise.resolve(); + } + __context; __proxy; __objectId; diff --git a/data_share/CMakeLists.txt b/data_share/CMakeLists.txt index 7f729357..5e7abaf5 100644 --- a/data_share/CMakeLists.txt +++ b/data_share/CMakeLists.txt @@ -18,6 +18,7 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/common/src da aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/consumer/controller/provider/src data_share_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/consumer/controller/service/src data_share_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/consumer/src data_share_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/dfx/src data_share_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/permission/src data_share_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/provider/src data_share_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/proxy/src data_share_src) @@ -30,6 +31,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/consumer/contr include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/consumer/controller/provider/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/consumer/controller/service/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/consumer/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/dfx/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/permission/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/provider/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/proxy/include) diff --git a/data_share/CODEOWNERS b/data_share/CODEOWNERS index f59cc39e..2d35b09c 100644 --- a/data_share/CODEOWNERS +++ b/data_share/CODEOWNERS @@ -13,5 +13,5 @@ # any change to # frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h -# needs to be reviewed by @leonchan5 -frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h @leonchan5 \ No newline at end of file +# needs to be reviewed by @leonchan5 liubao6@huawei.com +frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h @leonchan5 liubao6@huawei.com \ No newline at end of file diff --git a/data_share/README_zh.md b/data_share/README_zh.md index 6bc5b6ea..9bc85fa1 100644 --- a/data_share/README_zh.md +++ b/data_share/README_zh.md @@ -48,8 +48,8 @@ │   │   └── napi # NAPI代码存放目录 │   │   ├── common # 公用NAPI代码存放目录 │   │   ├── dataShare # 客户端NAPI代码存放目录 -│   │   ├── datashare_ext_ability # DataShareExtentionAbility模块JS代码存放目录 -│   │   └── datashare_ext_ability_context # DataShareExtentionAbilityContext模块JS代码存放目录 +│   │   ├── datashare_ext_ability # DataShareextensionAbility模块JS代码存放目录 +│   │   └── datashare_ext_ability_context # DataShareextensionAbilityContext模块JS代码存放目录 │   └── native │   ├── common │   ├── consumer diff --git a/data_share/bundle.json b/data_share/bundle.json index cdf40346..04a21151 100644 --- a/data_share/bundle.json +++ b/data_share/bundle.json @@ -64,6 +64,7 @@ "libuv", "napi", "relational_store", + "runtime_core", "samgr" ], "third_party": [] @@ -79,7 +80,8 @@ "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common:datashare_common", "//foundation/distributeddatamgr/data_share/interfaces/inner_api:datashare_ext_ability_module", "//foundation/distributeddatamgr/data_share/frameworks/js/napi:datashare_napi_packages", - "//foundation/distributeddatamgr/data_share/frameworks/cj/ffi:datashare_cj_ffi_packages" + "//foundation/distributeddatamgr/data_share/frameworks/cj/ffi:datashare_cj_ffi_packages", + "//foundation/distributeddatamgr/data_share/frameworks/js/ani:datashare_ani_packages" ], "service_group": [ ] @@ -101,6 +103,7 @@ "header": { "header_files": [ "datashare_helper.h", + "dataproxy_handle.h", "datashare_result_set.h" ], "header_base": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/consumer/include" @@ -139,11 +142,53 @@ ], "header_base": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common/include" } + }, + { + "name": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common:datashare_common_lite", + "header": { + "header_files": [ + "datashare_abs_predicates.h", + "datashare_predicates_def.h", + "datashare_predicates_object.h" + ], + "header_base": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common/include" + } + }, + { + "name": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common:datashare_common_lite", + "header": { + "header_files": [ + "result_set_bridge.h" + ], + "header_base": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/provider/include" + } + }, + { + "name": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common:datashare_common_lite", + "header": { + "header_files": [ + "datashare_result_set.h" + ], + "header_base": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/consumer/include" + } + }, + { + "name": "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common:datashare_common_lite", + "header": { + "header_files": [ + "datashare_radar_reporter.h", + "ishared_result_set.h" + ], + "header_base": "//foundation/distributeddatamgr/data_share/frameworks/native/common/include" + } } ], "test": [ "//foundation/distributeddatamgr/data_share/test/native:unittest", - "//foundation/distributeddatamgr/data_share/test/js/data_share:unittest" + "//foundation/distributeddatamgr/data_share/test/js/data_share:unittest", + "//foundation/distributeddatamgr/data_share/test/unittest/native:unittest", + "//foundation/distributeddatamgr/data_share/test/ets/data_share_ets:stage_unittest", + "//foundation/distributeddatamgr/data_share/test/fuzztest:fuzztest" ] } } diff --git a/data_share/cfi_blocklist.txt b/data_share/cfi_blocklist.txt new file mode 100644 index 00000000..fddb4e5f --- /dev/null +++ b/data_share/cfi_blocklist.txt @@ -0,0 +1,2 @@ +src:*/third_party/googletest/googletest/include/gtest/* +src:*/third_party/googletest/googlemock/include/gmock/* \ No newline at end of file diff --git a/data_share/datashare.gni b/data_share/datashare.gni index c825769d..3bdbbb59 100644 --- a/data_share/datashare.gni +++ b/data_share/datashare.gni @@ -20,6 +20,7 @@ datashare_common_napi_path = "${datashare_base_path}/frameworks/js/napi/common" datashare_napi_path = "${datashare_base_path}/frameworks/js/napi" datashare_cj_ffi_path = "${datashare_base_path}/frameworks/cj/ffi" +datashare_ani_path = "${datashare_base_path}/frameworks/js/ani" datashare_innerapi_path = "${datashare_base_path}/interfaces/inner_api" @@ -32,6 +33,9 @@ datashare_native_consumer_path = datashare_native_permission_path = "${datashare_base_path}/frameworks/native/permission" +datashare_native_dfx_path = + "${datashare_base_path}/frameworks/native/dfx" + datashare_native_proxy_path = "${datashare_base_path}/frameworks/native/proxy" foundation_path = "//foundation" diff --git a/data_share/frameworks/cj/ffi/data_share_predicates/BUILD.gn b/data_share/frameworks/cj/ffi/data_share_predicates/BUILD.gn index 718abfce..7aae918a 100644 --- a/data_share/frameworks/cj/ffi/data_share_predicates/BUILD.gn +++ b/data_share/frameworks/cj/ffi/data_share_predicates/BUILD.gn @@ -46,6 +46,7 @@ ohos_shared_library("cj_data_share_predicates_ffi") { external_deps = [ "c_utils:utils", "hilog:libhilog", + "ipc:ipc_single", "napi:ace_napi", "napi:cj_bind_ffi", "napi:cj_bind_native", diff --git a/data_share/frameworks/js/ani/BUILD.gn b/data_share/frameworks/js/ani/BUILD.gn new file mode 100644 index 00000000..f05a81c8 --- /dev/null +++ b/data_share/frameworks/js/ani/BUILD.gn @@ -0,0 +1,23 @@ +# 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/ohos.gni") +import("//foundation/distributeddatamgr/data_share/datashare.gni") + +group("datashare_ani_packages") { + deps = [ + "${datashare_ani_path}/dataShare:data_share", + "${datashare_ani_path}/dataShare:data_share_predicates", + "${datashare_ani_path}/dataShareResultSet:datashareresultset", + ] +} diff --git a/data_share/frameworks/js/ani/common/include/ani_util_class.h b/data_share/frameworks/js/ani/common/include/ani_util_class.h new file mode 100644 index 00000000..98a830f8 --- /dev/null +++ b/data_share/frameworks/js/ani/common/include/ani_util_class.h @@ -0,0 +1,215 @@ +/* + * 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 ANI_UTIL_CLASS_H +#define ANI_UTIL_CLASS_H + +#include + +#include + +#include "ani_util_common.h" + +class AniTypeFinder { +public: + AniTypeFinder(ani_env* env) : env_(env) + { + } + + Expected FindNamespace(const char* nsName) + { + ani_namespace ns; + if (env_ == nullptr) { + return ANI_ERROR; + } + + ani_status status = env_->FindNamespace(nsName, &ns); + if (ANI_OK != status) { + return status; + } + return ns; + } + + template + Expected FindNamespace(const char* firstNs, const char* nextNs, Names... restNs) + { + ani_namespace ns; + if (env_ == nullptr) { + return ANI_ERROR; + } + + ani_status status = env_->FindNamespace(firstNs, &ns); + if (ANI_OK != status) { + return status; + } + return FindNamespace(ns, nextNs, restNs...); + } + + Expected FindClass(const char* clsName) + { + ani_class cls; + if (env_ == nullptr) { + return ANI_ERROR; + } + + ani_status status = env_->FindClass(clsName, &cls); + if (ANI_OK != status) { + return status; + } + return cls; + } + + Expected FindClass(const char* nsName, const char* clsName) + { + auto ns = FindNamespace(nsName, clsName); + if (!ns.has_value()) { + return ns.error(); + } + return FindClass(ns.value(), clsName); + } + + template + Expected FindClass(const char* firstNs, const char* secondNs, Names... restNs, + const char* clsName) + { + auto ns = FindNamespace(firstNs, secondNs, restNs...); + if (!ns.has_value()) { + return ns.error(); + } + return FindClass(ns.value(), clsName); + } + + Expected FindClass(ani_namespace ns, const char* clsName) + { + ani_class cls; + if (env_ == nullptr) { + return ANI_ERROR; + } + + ani_status status = env_->Namespace_FindClass(ns, clsName, &cls); + if (ANI_OK != status) { + return status; + } + return cls; + } + + Expected FindEnum(ani_namespace ns, const char* enumName) + { + ani_enum aniEnum{}; + if (env_ == nullptr) { + return ANI_ERROR; + } + + ani_status status = env_->Namespace_FindEnum(ns, enumName, &aniEnum); + if (ANI_OK != status) { + return status; + } + return aniEnum; + } + +private: + template + Expected FindNamespace(ani_namespace currentNs, const char *nextNs, Names... restNs) + { + ani_namespace ns; + if (env_ == nullptr) { + return ANI_ERROR; + } + + ani_status status = env_->Namespace_FindNamespace(currentNs, nextNs, &ns); + if (ANI_OK != status) { + return status; + } + return FindNamespace(ns, restNs...); + } + + Expected FindNamespace(ani_namespace currentNs) + { + return currentNs; + } + +private: + ani_env* env_ = nullptr; +}; + + +class AniObjectFactory { +public: + AniObjectFactory(ani_env *env) + : env_(env) + { + } + + Expected Create(const char* clsName, ...) + { + auto cls = AniTypeFinder(env_).FindClass(clsName); + if (!cls.has_value()) { + return cls.error(); + } + + va_list args; + va_start(args, clsName); + auto obj = CreateV(cls.value(), args); + va_end(args); + return obj; + } + + template + Expected Create(const char* nsName, Names... restNs, const char* clsName, ...) + { + auto cls = AniTypeFinder(env_).FindClass(nsName, restNs..., clsName); + if (!cls.has_value()) { + return cls.error(); + } + + va_list args; + va_start(args, clsName); + auto obj = CreateV(cls.value(), args); + va_end(args); + return obj; + } + + Expected Create(ani_class cls, ...) + { + va_list args; + va_start(args, cls); + auto obj = CreateV(cls, args); + va_end(args); + return obj; + } + +private: + Expected CreateV(ani_class cls, va_list args) + { + ani_method ctor; + if (env_ == nullptr) { + return ANI_ERROR; + } + ani_status status = env_->Class_FindMethod(cls, "", nullptr, &ctor); + if (ANI_OK != status) { + return status; + } + + ani_object obj; + status = env_->Object_New_V(cls, ctor, &obj, args); + if (ANI_OK != status) { + return status; + } + return obj; + } + +private: + ani_env *env_ = nullptr; +}; +#endif // ANI_UTIL_CLASS_H \ No newline at end of file diff --git a/data_share/frameworks/js/ani/common/include/ani_util_common.h b/data_share/frameworks/js/ani/common/include/ani_util_common.h new file mode 100644 index 00000000..a535aadf --- /dev/null +++ b/data_share/frameworks/js/ani/common/include/ani_util_common.h @@ -0,0 +1,187 @@ +/* + * 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 ANI_UTIL_COMMON_H +#define ANI_UTIL_COMMON_H + +#include +#include +#include +#include +#include + +template +class Expected { +public: + Expected(const T &value) + : data_(value), has_value_(true) + { + } + + Expected(T &&value) + : data_(std::move(value)), has_value_(true) + { + } + + Expected(const E &error) + : data_(error), has_value_(false) + { + } + + Expected(E &&error) + : data_(std::move(error)), has_value_(false) + { + } + + bool has_value() const noexcept + { + return has_value_; + } + + explicit operator bool() const noexcept + { + return has_value(); + } + + T &value() & + { + if (!has_value()) { + std::terminate(); + } + return std::get(data_); + } + + const T &value() const & + { + if (!has_value()) { + std::terminate(); + } + return std::get(data_); + } + + T &&value() && + { + if (!has_value()) { + std::terminate(); + } + return std::get(std::move(data_)); + } + + E &error() & + { + if (has_value()) { + std::terminate(); + } + return std::get(data_); + } + + const E &error() const & + { + if (has_value()) { + std::terminate(); + } + return std::get(data_); + } + + E &&error() && + { + if (has_value()) { + std::terminate(); + } + return std::get(std::move(data_)); + } + + T &operator*() & + { + return value(); + } + + const T &operator*() const & + { + return value(); + } + + T &&operator*() && + { + return std::move(*this).value(); + } + + T *operator->() + { + return &value(); + } + + const T *operator->() const + { + return &value(); + } + + template + T value_or(U &&default_value) const & + { + return has_value() ? value() : static_cast(std::forward(default_value)); + } + + template + T value_or(U &&default_value) && + { + return has_value() ? std::move(*this).value() : static_cast(std::forward(default_value)); + } + +private: + std::variant data_; + bool has_value_; +}; + +template +class FinalAction { +public: + explicit FinalAction(F func) : func_(std::move(func)) + { + } + + ~FinalAction() noexcept(noexcept(func_())) + { + if (!dismissed_) { + func_(); + } + } + + FinalAction(const FinalAction&) = delete; + FinalAction& operator=(const FinalAction&) = delete; + + FinalAction(FinalAction&& other) noexcept + : func_(std::move(other.func_)), + dismissed_(other.dismissed_) + { + other.dismissed_ = true; + } + + void dismiss() noexcept + { + dismissed_ = true; + } + +private: + F func_; + bool dismissed_ = false; +}; + +template +inline FinalAction finally(F&& func) +{ + return FinalAction(std::forward(func)); +} + +#endif // ANI_UTIL_COMMON_H \ No newline at end of file diff --git a/data_share/frameworks/js/ani/common/include/ani_util_native_ptr.h b/data_share/frameworks/js/ani/common/include/ani_util_native_ptr.h new file mode 100644 index 00000000..1b65adfd --- /dev/null +++ b/data_share/frameworks/js/ani/common/include/ani_util_native_ptr.h @@ -0,0 +1,129 @@ +/* + * 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 ANI_UTIL_OBJECT_H +#define ANI_UTIL_OBJECT_H + +#include + +#include +#include + +class NativeObject { +public: + virtual ~NativeObject() = default; +}; + + +template +class SharedPtrHolder : public NativeObject { +public: + SharedPtrHolder(const std::shared_ptr &sptr) : sptr_(sptr) + { + } + + std::shared_ptr Get() + { + return sptr_; + } + + std::shared_ptr GetOrDefault() + { + if (!sptr_) { + sptr_ = std::make_shared(); + } + return sptr_; + } + +private: + std::shared_ptr sptr_; +}; + + +class NativePtrWrapper { +public: + NativePtrWrapper(ani_env *env, ani_object object, const char* propName = "nativePtr") + : env_(env), obj_(object), propName_(propName) + { + } + + template + ani_status Wrap(T* nativePtr) + { + return env_->Object_SetFieldByName_Long(obj_, propName_.c_str(), reinterpret_cast(nativePtr)); + } + + template + T* Unwrap() + { + ani_long nativePtr; + if (env_ == nullptr) { + return nullptr; + } + + if (ANI_OK != env_->Object_GetFieldByName_Long(obj_, propName_.c_str(), &nativePtr)) { + return nullptr; + } + return reinterpret_cast(nativePtr); + } + +private: + ani_env *env_ = nullptr; + ani_object obj_ = nullptr; + std::string propName_; +}; + + +class NativePtrCleaner { +public: + static void Clean([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) + { + ani_long ptr = 0; + if (env == nullptr) { + return; + } + + if (ANI_OK != env->Object_GetFieldByName_Long(object, "targetPtr", &ptr)) { + return; + } + delete reinterpret_cast(ptr); + } + + NativePtrCleaner(ani_env *env) + : env_(env) + { + } + + ani_status Bind(ani_class cls) + { + std::array methods = { + ani_native_function { "clean", nullptr, reinterpret_cast(NativePtrCleaner::Clean) }, + }; + + if (env_ == nullptr) { + return (ani_status)ANI_ERROR; + } + + if (ANI_OK != env_->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + return (ani_status)ANI_ERROR; + }; + + return ANI_OK; + } + +private: + ani_env *env_ = nullptr; +}; + +#endif // ANI_UTIL_OBJECT_H \ No newline at end of file diff --git a/data_share/frameworks/js/ani/common/include/ani_utils.h b/data_share/frameworks/js/ani/common/include/ani_utils.h new file mode 100644 index 00000000..7a4384a2 --- /dev/null +++ b/data_share/frameworks/js/ani/common/include/ani_utils.h @@ -0,0 +1,198 @@ +/* + * 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 ANI_UTILS_H +#define ANI_UTILS_H + +#include +#include +#include +#include +#include +#include +#include "ani_util_class.h" +#include "ani_util_native_ptr.h" + +namespace OHOS { +namespace DataShare { +class AniObjectUtils { +public: + static ani_object Create(ani_env *env, const char* nsName, const char* clsName, ...); + static ani_object Create(ani_env *env, const char* clsName, ...); + static ani_object Create(ani_env *env, ani_class cls, ...); + static ani_object From(ani_env *env, bool value); + template + static ani_status Wrap(ani_env *env, ani_object object, T* nativePtr, const char* propName = "nativePtr") + { + if (env == nullptr) { + return ANI_ERROR; + } + + if (nativePtr == nullptr) { + return ANI_ERROR; + } + return env->Object_SetFieldByName_Long(object, propName, reinterpret_cast(nativePtr)); + } + + template + static T* Unwrap(ani_env *env, ani_object object, const char* propName = "nativePtr") + { + if (env == nullptr) { + return nullptr; + } + + ani_long nativePtr; + if (ANI_OK != env->Object_GetFieldByName_Long(object, propName, &nativePtr)) { + return nullptr; + } + + return reinterpret_cast(nativePtr); + } +}; + +class AniStringUtils { +public: + static std::string ToStd(ani_env *env, ani_string ani_str); + static ani_string ToAni(ani_env* env, const std::string& str); +}; + +class UnionAccessor { +public: + UnionAccessor(ani_env *env, ani_object &obj); + bool IsInstanceOf(const std::string& cls_name); + bool IsInstanceOf(const std::string& cls_name, ani_object obj); + template bool IsInstanceOfType(); + template bool TryConvert(T &value); + template bool TryConvertArray(std::vector &value); + +private: + ani_env *env_; + ani_object obj_; +}; +class OptionalAccessor { +public: + OptionalAccessor(ani_env *env, ani_object &obj); + bool IsUndefined(); + bool IsNull(); + template std::optional Convert(); + +private: + ani_env *env_; + ani_object obj_; +}; + +template +struct Converter { + static std::string convert(const T& value) + { + std::ostringstream oss; + oss << value; + return oss.str(); + } +}; + +template<> +struct Converter { + static std::string convert(const bool& value) + { + return value ? "true" : "false"; + } +}; + + +template<> +struct Converter { + static std::string convert(const double& value) + { + std::ostringstream buf; + buf << value; + std::string str = buf.str(); + return str; + } +}; + +template +std::vector convertVector(const std::vector& input) +{ + std::vector result; + result.reserve(input.size()); + + for (const auto& elem : input) { + result.push_back(Converter::convert(elem)); + } + return result; +} + +template using convertCallback = bool(*)(ani_env*, ani_ref&, ani_ref&, std::shared_ptr); + +template +bool forEachMapEntry(ani_env *env, ani_object map_object, F &&callback, std::shared_ptr records) +{ + if (env == nullptr) { + return false; + } + ani_ref iter; + if (ANI_OK != env->Object_CallMethodByName_Ref(map_object, "$_iterator", nullptr, &iter)) { + std::cout << "Failed to get keys iterator" << std::endl; + return false; + } + + ani_ref next; + ani_boolean done; + while (ANI_OK == env->Object_CallMethodByName_Ref(static_cast(iter), "next", nullptr, &next)) { + if (ANI_OK != env->Object_GetFieldByName_Boolean(static_cast(next), "done", &done)) { + std::cout << "Failed to check iterator done" << std::endl; + return false; + } + + if (done) { + std::cout << "[forEachMapEntry] done break" << std::endl; + return true; + } + + ani_ref key_value; + if (ANI_OK != env->Object_GetFieldByName_Ref(static_cast(next), "value", &key_value)) { + std::cout << "Failed to get key value" << std::endl; + return false; + } + + ani_ref ani_key; + if (ANI_OK != env->TupleValue_GetItem_Ref(static_cast(key_value), 0, &ani_key)) { + std::cout << "Failed to get key value" << std::endl; + return false; + } + + ani_ref ani_val; + if (ANI_OK != env->TupleValue_GetItem_Ref(static_cast(key_value), 1, &ani_val)) { + std::cout << "Failed to get key value" << std::endl; + return false; + } + + if (!callback(env, ani_key, ani_val, records)) { + return false; + } + } + + std::cout << "Failed to get next key" << std::endl; + return false; +} + +ani_object DoubleToObject(ani_env *env, double value); +ani_object BoolToObject(ani_env *env, bool value); +ani_object StringToObject(ani_env *env, std::string value); +ani_object Uint8ArrayToObject(ani_env *env, const std::vector &values); +} +} +#endif // ANI_UTILS_H diff --git a/data_share/frameworks/js/ani/common/include/datashare_predicates_cleaner.h b/data_share/frameworks/js/ani/common/include/datashare_predicates_cleaner.h new file mode 100644 index 00000000..261c70c5 --- /dev/null +++ b/data_share/frameworks/js/ani/common/include/datashare_predicates_cleaner.h @@ -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. + */ + +#ifndef DATASHARE_PREDICATES_CLEANER_H +#define DATASHARE_PREDICATES_CLEANER_H + +#include + +#include +#include +#include "datashare_predicates.h" + +class DataSharePredicatesCleaner { + public: + static void Clean([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) + { + ani_long ptr = 0; + if (env == nullptr) { + return; + } + if (ANI_OK != env->Object_GetFieldByName_Long(object, "targetPtr", &ptr)) { + return; + } + delete reinterpret_cast(ptr); + } + + DataSharePredicatesCleaner(ani_env *env) + : env_(env) + { + } + + ani_status Bind(ani_class cls) + { + std::array methods = { + ani_native_function { "clean", nullptr, reinterpret_cast(DataSharePredicatesCleaner::Clean) }, + }; + + if (env_ == nullptr) { + return static_cast(ANI_ERROR); + } + + if (ANI_OK != env_->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + return static_cast(ANI_ERROR); + }; + + return ANI_OK; + } + + private: + ani_env *env_ = nullptr; + }; + +#endif // DATASHARE_PREDICATES_CLEANER_H \ No newline at end of file diff --git a/data_share/frameworks/js/ani/common/src/ani_utils.cpp b/data_share/frameworks/js/ani/common/src/ani_utils.cpp new file mode 100644 index 00000000..d4fddcf9 --- /dev/null +++ b/data_share/frameworks/js/ani/common/src/ani_utils.cpp @@ -0,0 +1,596 @@ +/* + * 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 "datashare_log.h" +#include "ani_utils.h" + +namespace OHOS::DataShare { +ani_object AniObjectUtils::Create(ani_env *env, const char* nsName, const char* clsName, ...) +{ + ani_object nullobj{}; + if (env == nullptr) { + return nullobj; + } + ani_namespace ns; + if (ANI_OK != env->FindNamespace(nsName, &ns)) { + LOG_ERROR("[ANI] Not found namespace %{public}s", nsName); + return nullobj; + } + + ani_class cls; + if (ANI_OK != env->Namespace_FindClass(ns, clsName, &cls)) { + LOG_ERROR("[ANI] Not found class %{public}s", clsName); + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + LOG_ERROR("[ANI] Not found for class %{public}s", clsName); + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + LOG_ERROR("[ANI] Failed to Object_New for class %{public}s", clsName); + return nullobj; + } + + return obj; +} + + +ani_object AniObjectUtils::Create(ani_env *env, const char* clsName, ...) +{ + ani_object nullobj{}; + if (env == nullptr) { + return nullobj; + } + ani_class cls; + if (ANI_OK != env->FindClass(clsName, &cls)) { + LOG_ERROR("[ANI] Not found class %{public}s", clsName); + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + LOG_ERROR("[ANI] Not found for class %{public}s", clsName); + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + LOG_ERROR("[ANI] Failed to Object_New for class %{public}s", clsName); + return nullobj; + } + + return obj; +} + +ani_object AniObjectUtils::Create(ani_env *env, ani_class cls, ...) +{ + ani_object nullobj{}; + if (env == nullptr) { + return nullobj; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + LOG_ERROR("[ANI] Not found for class"); + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, cls); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + LOG_ERROR("[ANI] Failed to Object_New for class"); + return nullobj; + } + + return obj; +} + +ani_object AniObjectUtils::From(ani_env *env, bool value) +{ + return Create(env, "Lstd/core/Boolean;", static_cast(value)); +} + +std::string AniStringUtils::ToStd(ani_env *env, ani_string ani_str) +{ + ani_size strSize; + env->String_GetUTF8Size(ani_str, &strSize); + + std::vector buffer(strSize + 1); // +1 for null terminator + char* utf8_buffer = buffer.data(); + + //String_GetUTF8 Supportted by https://gitee.com/openharmony/arkcompiler_runtime_core/pulls/3416 + ani_size bytes_written = 0; + env->String_GetUTF8(ani_str, utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + + return content; +} + +ani_string AniStringUtils::ToAni(ani_env* env, const std::string& str) +{ + ani_string aniStr = nullptr; + if (ANI_OK != env->String_NewUTF8(str.data(), str.size(), &aniStr)) { + LOG_ERROR("[ANI] Unsupported ANI_VERSION_1"); + return nullptr; + } + + return aniStr; +} + +UnionAccessor::UnionAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) +{ +} + +bool UnionAccessor::IsInstanceOf(const std::string& clsName) +{ + ani_class cls; + env_->FindClass(clsName.c_str(), &cls); + + ani_boolean ret; + env_->Object_InstanceOf(obj_, cls, &ret); + + return ret; +} + +bool UnionAccessor::IsInstanceOf(const std::string& clsName, ani_object obj) +{ + ani_class cls; + env_->FindClass(clsName.c_str(), &cls); + + ani_boolean ret; + env_->Object_InstanceOf(obj, cls, &ret); + return ret; +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Boolean;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Int;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Double;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/String;"); +} + +template<> +bool UnionAccessor::TryConvert(bool &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_boolean aniValue; + auto ret = env_->Object_CallMethodByName_Boolean(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + + value = static_cast(aniValue); + + return true; +} + +template<> +bool UnionAccessor::TryConvert(int &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_int aniValue; + auto ret = env_->Object_CallMethodByName_Int(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + + value = static_cast(aniValue); + + return true; +} + +template<> +bool UnionAccessor::TryConvert(double &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + + value = static_cast(aniValue); + + return true; +} + +template<> +bool UnionAccessor::TryConvert(std::string &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + value = AniStringUtils::ToStd(env_, static_cast(obj_)); + + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_GetPropertyByName_Ref failed"); + return false; + } + + if (!IsInstanceOf("Lstd/core/Boolean;", static_cast(ref))) { + LOG_ERROR("Not found 'Lstd/core/Boolean;'"); + return false; + } + + ani_boolean val; + if (ANI_OK != env_->Object_CallMethodByName_Boolean(static_cast(ref), "unboxed", nullptr, &val)) { + LOG_ERROR("Object_CallMethodByName_Double unbox failed"); + return false; + } + + value.push_back(static_cast(val)); + } + + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_GetPropertyByName_Ref failed"); + return false; + } + + if (!IsInstanceOf("Lstd/core/Int;", static_cast(ref))) { + LOG_ERROR("Not found 'Lstd/core/Double;'"); + return false; + } + + ani_int intValue; + if (ANI_OK != env_->Object_CallMethodByName_Int(static_cast(ref), "unboxed", nullptr, &intValue)) { + LOG_ERROR("Object_CallMethodByName_Double unbox failed"); + return false; + } + + value.push_back(static_cast(intValue)); + } + + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_GetPropertyByName_Ref failed"); + return false; + } + + if (!IsInstanceOf("Lstd/core/Double;", static_cast(ref))) { + LOG_ERROR("Not found 'Lstd/core/Double;'"); + return false; + } + + ani_double val; + if (ANI_OK != env_->Object_CallMethodByName_Double(static_cast(ref), "unboxed", nullptr, &val)) { + LOG_ERROR("Object_CallMethodByName_Double unbox failed"); + return false; + } + + value.push_back(static_cast(val)); + } + + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + LOG_INFO("TryConvertArray std::vector"); + ani_ref buffer; + if (ANI_OK != env_->Object_GetFieldByName_Ref(obj_, "buffer", &buffer)) { + LOG_INFO("Object_GetFieldByName_Ref failed"); + return false; + } + + void* data; + size_t length; + if (ANI_OK != env_->ArrayBuffer_GetInfo(static_cast(buffer), &data, &length)) { + LOG_ERROR("ArrayBuffer_GetInfo failed"); + return false; + } + + LOG_INFO("Length of buffer is %{public}zu", length); + for (size_t i = 0; i < length; i++) { + value.push_back(static_cast(data)[i]); + } + + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + + if (!IsInstanceOf("Lstd/core/String;", static_cast(ref))) { + LOG_ERROR("Not found 'Lstd/core/String;'"); + return false; + } + + value.push_back(AniStringUtils::ToStd(env_, static_cast(ref))); + } + + return true; +} + +OptionalAccessor::OptionalAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) +{ +} + +bool OptionalAccessor::IsUndefined() +{ + ani_boolean isUndefined; + env_->Reference_IsUndefined(obj_, &isUndefined); + + return isUndefined; +} + +bool OptionalAccessor::IsNull() +{ + ani_boolean isNull; + env_->Reference_IsNull(obj_, &isNull); + + return isNull; +} + +template<> +std::optional OptionalAccessor::Convert() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_boolean aniValue; + auto ret = env_->Object_CallMethodByName_Boolean(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return std::nullopt; + } + + auto value = static_cast(aniValue); + + return value; +} + +template<> +std::optional OptionalAccessor::Convert() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "doubleValue", nullptr, &aniValue); + if (ret != ANI_OK) { + return std::nullopt; + } + + auto value = static_cast(aniValue); + + return value; +} + +template<> +std::optional OptionalAccessor::Convert() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_size strSize; + env_->String_GetUTF8Size(static_cast(obj_), &strSize); + + std::vector buffer(strSize + 1); + char* utf8_buffer = buffer.data(); + + ani_size bytes_written = 0; + env_->String_GetUTF8(static_cast(obj_), utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + + return content; +} + +ani_object DoubleToObject(ani_env *env, double value) +{ + ani_object aniObject = nullptr; + ani_double doubleValue = static_cast(value); + const char *className = "Lstd/core/Double;"; + ani_class aniClass; + if (ANI_OK != env->FindClass(className, &aniClass)) { + LOG_ERROR("Not found '%{public}s'.", className); + return aniObject; + } + ani_method personInfoCtor; + if (ANI_OK != env->Class_FindMethod(aniClass, "", "D:V", &personInfoCtor)) { + LOG_ERROR("Class_GetMethod Failed '%{public}s .'", className); + return aniObject; + } + + if (ANI_OK != env->Object_New(aniClass, personInfoCtor, &aniObject, doubleValue)) { + LOG_ERROR("Object_New Failed '%{public}s. ", className); + return aniObject; + } + return aniObject; +} + +ani_object BoolToObject(ani_env *env, bool value) +{ + ani_object aniObject = nullptr; + ani_boolean boolValue = static_cast(value); + const char *className = "Lstd/core/Boolean;"; + ani_class aniClass; + if (ANI_OK != env->FindClass(className, &aniClass)) { + LOG_ERROR("Not found '%{public}s.'", className); + return aniObject; + } + + ani_method personInfoCtor; + if (ANI_OK != env->Class_FindMethod(aniClass, "", "Z:V", &personInfoCtor)) { + LOG_ERROR("Class_GetMethod Failed '%{public}s' .", className); + return aniObject; + } + + if (ANI_OK != env->Object_New(aniClass, personInfoCtor, &aniObject, boolValue)) { + LOG_ERROR("Object_New Failed '%{public}s' .", className); + } + + return aniObject; +} + +ani_object StringToObject(ani_env *env, std::string value) +{ + return static_cast(AniStringUtils::ToAni(env, value)); +} + +ani_object Uint8ArrayToObject(ani_env *env, const std::vector &values) +{ + ani_object aniObject = nullptr; + ani_class arrayClass; + if (values.size() == 0) { + LOG_ERROR("values is empty"); + return aniObject; + } + ani_status retCode = env->FindClass("Lescompat/Uint8Array;", &arrayClass); + if (retCode != ANI_OK) { + LOG_ERROR("Failed: env->FindClass()"); + return aniObject; + } + + ani_method arrayCtor; + retCode = env->Class_FindMethod(arrayClass, "", "I:V", &arrayCtor); + if (retCode != ANI_OK) { + LOG_ERROR("Failed: env->Class_FindMethod()"); + return aniObject; + } + + auto valueSize = values.size(); + retCode = env->Object_New(arrayClass, arrayCtor, &aniObject, valueSize); + if (retCode != ANI_OK) { + LOG_ERROR("Failed: env->Object_New()"); + return aniObject; + } + + ani_ref buffer; + env->Object_GetFieldByName_Ref(aniObject, "buffer", &buffer); + void *bufData; + size_t bufLength; + retCode = env->ArrayBuffer_GetInfo(static_cast(buffer), &bufData, &bufLength); + if (retCode != ANI_OK) { + LOG_INFO("Failed: env->ArrayBuffer_GetInfo()"); + } + + auto ret = memcpy_s(bufData, bufLength, values.data(), values.size()); + if (ret != 0) { + return nullptr; + } + + return aniObject; +} // namespace DataShare +} // namespace OHOS diff --git a/data_share/frameworks/js/ani/dataShare/BUILD.gn b/data_share/frameworks/js/ani/dataShare/BUILD.gn new file mode 100644 index 00000000..9544c5d8 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/BUILD.gn @@ -0,0 +1,145 @@ +# 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/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/distributeddatamgr/data_share/datashare.gni") + +ohos_shared_library("datashare_ani") { + branch_protector_ret = "pac_ret" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + sources = [ + "src/ani_datashare_helper.cpp", + "src/ani_datashare_inner_observer.cpp", + "src/ani_datashare_observer.cpp", + "${datashare_ani_path}/common/src/ani_utils.cpp", + ] + + include_dirs = [ + "include/", + "${datashare_base_path}/interfaces/inner_api/common/include", + "${datashare_ani_path}/common/include", + ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer", + "${datashare_innerapi_path}/common:datashare_common", + ] + + external_deps = [ + "ability_runtime:ani_base_context", + "ability_runtime:ani_common", + "ability_runtime:app_context", + "access_token:libtokenid_sdk", + "c_utils:utils", + "hilog:libhilog", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "runtime_core:ani", + ] + + subsystem_name = "distributeddatamgr" + part_name = "data_share" + output_extension = "so" +} + +generate_static_abc("datashare_abc") { + base_url = "ets" + files = [ "ets/@ohos.data.dataShare.ets" ] + dst_file = "$target_out_dir/datashare.abc" + out_puts = [ "$target_out_dir/datashare.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/datashare.abc" +} + +ohos_prebuilt_etc("datashare_abc_etc") { + source = "$target_out_dir/datashare.abc" + module_install_dir = "framework" + subsystem_name = "distributeddatamgr" + part_name = "data_share" + deps = [ ":datashare_abc" ] +} + +group("data_share") { + deps = [ + ":datashare_ani", + ":datashare_abc_etc", + ] +} + +ohos_shared_library("datasharepredicates_ani") { + sanitize = { + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + sources = [ + "src/data_share_predicates.cpp", + "${datashare_ani_path}/common/src/ani_utils.cpp", + ] + + include_dirs = [ + "include", + "${datashare_common_native_path}/include", + "${datashare_ani_path}/common/include", + ] + + deps = [ "${datashare_innerapi_path}/common:datashare_common" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "runtime_core:ani", + ] + + subsystem_name = "distributeddatamgr" + part_name = "data_share" + output_extension = "so" +} + +generate_static_abc("data_share_predicates_abc") { + base_url = "ets" + files = [ "ets/@ohos.data.dataSharePredicates.ets" ] + dst_file = "$target_out_dir/data_share_predicates.abc" + out_puts = [ "$target_out_dir/data_share_predicates.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/data_share_predicates.abc" +} + +ohos_prebuilt_etc("data_share_predicates_abc_etc") { + source = "$target_out_dir/data_share_predicates.abc" + module_install_dir = "framework" + subsystem_name = "distributeddatamgr" + part_name = "data_share" + deps = [ ":data_share_predicates_abc" ] +} + +group("data_share_predicates") { + deps = [ + ":data_share_predicates_abc_etc", + ":datasharepredicates_ani", + ] +} diff --git a/data_share/frameworks/js/ani/dataShare/ets/@ohos.data.dataShare.ets b/data_share/frameworks/js/ani/dataShare/ets/@ohos.data.dataShare.ets new file mode 100644 index 00000000..9e66a417 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/ets/@ohos.data.dataShare.ets @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * @kit ArkData + */ + +import hilog from '@ohos.hilog' +import { BusinessError } from '@ohos.base' +import type { AsyncCallback } from '@ohos.base' +import Context from 'application.Context' +import DataShareResultSet from '@ohos.data.DataShareResultSet' +import dataSharePredicates from '@ohos.data.dataSharePredicates' +import { ValuesBucket } from '@ohos.data.ValuesBucket' + +export namespace dataShare { + loadLibrary("datashare_ani") + + export interface DataShareHelperOptions { + isProxy?: boolean; + } + + enum ChangeType { + INSERT = 0, + DELETE, + UPDATE + } + + export enum SubscriptionType { + SUBSCRIPTION_TYPE_EXACT_URI = 0, + } + + export interface ChangeInfo { + type: ChangeType + uri: string + values: Array + } + + export interface DataShareHelper { + on(type: 'dataChange', uri: string, callback: AsyncCallback): void + off(type: 'dataChange', uri: string, callback?: AsyncCallback): void + on(event: 'dataChange', type: SubscriptionType, uri: string, callback: AsyncCallback): void + off(event: 'dataChange', type: SubscriptionType, uri: string, callback?: AsyncCallback): void + query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array, callback: AsyncCallback): void + query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array): Promise + update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket, callback: AsyncCallback): void + update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket): Promise + } + + export native function create(context: Context, uri: string, options?: DataShareHelperOptions): DataShareHelper + + export function createDataShareHelper(context: Context, uri: string, callback: AsyncCallback): void { + let p = taskpool.execute(create, context, uri, undefined) + p.then((e: NullishType) => { + let r = e as DataShareHelper + let err: BusinessError + callback(err, r) + }).catch((error: NullishType) => { + let r = new DataShareHelperInner(0) + let err = error as BusinessError + hilog.error(0x0000, 'DataShareHelper', "create failed:" + err) + callback(err, r) + }) + } + + export function createDataShareHelper(context: Context, uri: string, options: DataShareHelperOptions, callback: AsyncCallback): void { + let p = taskpool.execute(create, context, uri, options) + p.then((e: NullishType) => { + let r = e as DataShareHelper + let err: BusinessError + callback(err, r) + }).catch((error: NullishType) => { + let r = new DataShareHelperInner(0) + let err = error as BusinessError + hilog.error(0x0000, 'DataShareHelper', "create failed:" + err) + callback(err, r) + }) + } + + export function createDataShareHelper(context: Context, uri: string, options?: DataShareHelperOptions): Promise { + console.println("createDataShareHelper enter") + return new Promise((resolve: (v: DataShareHelper) => void, reject: (error: Error) => void) => { + let p = taskpool.execute(create, context, uri, options) + p.then((e: NullishType) => { + let r = e as DataShareHelper + resolve(r) + }).catch((e: Error): void => { + hilog.error(0x0000, 'DataShareHelper', "create failed:" + e) + reject(e) + }) + }) + } + + class ChangeInfoInner implements ChangeInfo { + type: ChangeType + uri: string + values: Array + } + + class Cleaner { + static callback(cleaner: Cleaner): void { + console.println("enter Cleaner.callback"); + cleaner.clean() + } + + constructor(targetPtr: long) { + this.targetPtr = targetPtr + } + + native clean(): void + + private targetPtr: long = 0 + } + + class FinalizationAgent { + constructor(obj: T, ptr: long) { + this.register(obj, ptr); + } + + register(obj: T, ptr: long): void { + this.unregisterToken = {}; + this.cleaner = new Cleaner(ptr); + finalizer.register(obj, this.cleaner!, this.unregisterToken); + } + + unregister(): void { + finalizer.unregister(this.unregisterToken); + } + + private cleaner: Cleaner | null = null; + private unregisterToken: object; + } + + let finalizer = new FinalizationRegistry(Cleaner.callback) + + class DataShareHelperInner implements DataShareHelper { + private nativePtr: long = 0 + private fzAgent: FinalizationAgent; + private onCallback: AsyncCallback = () => {} + private offCallback?: AsyncCallback + private onEventCallback: AsyncCallback = () => {} + private offEventCallback?: AsyncCallback + + constructor(nativePtr:long) { + hilog.info(0x0000, 'DataShareHelper', "in constructor, context :" + nativePtr) + this.nativePtr = nativePtr + this.fzAgent = new FinalizationAgent(this, this.nativePtr); + } + + unregisterCleaner(): void { + this.fzAgent.unregister(); + } + + getNativePtr(): long { + return this.nativePtr + } + + native on(type: 'dataChange', uri: string, callback: AsyncCallback): void + native off(type: 'dataChange', uri: string, callback?: AsyncCallback): void + native on(event: 'dataChange', type: SubscriptionType, uri: string, callback: AsyncCallback): void + native off(event: 'dataChange', type: SubscriptionType, uri: string, callback?: AsyncCallback): void + native ani_query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array): DataShareResultSet + native ani_update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket): number + + query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array, callback: AsyncCallback): void { + let p = taskpool.execute(this.ani_query, uri, predicates, columns) + p.then((e: NullishType) => { + let r = e as DataShareResultSet + let err: BusinessError + callback(err, r) + }).catch((error: NullishType) => { + let err = error as BusinessError + hilog.error(0x0000, 'DataShareHelper', "query failed:" + err) + }) + } + + query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array): Promise { + return new Promise((resolve: (v: DataShareResultSet) => void, reject: (error: Error) => void) => { + let p = taskpool.execute(this.ani_query, uri, predicates, columns) + p.then((e: NullishType) => { + let r = e as DataShareResultSet + resolve(r) + }).catch((e: Error): void => { + hilog.error(0x0000, 'DataShareHelper', "query failed:" + e) + reject(e) + }) + }) + } + + update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket, callback: AsyncCallback): void { + let p = taskpool.execute(this.ani_update, uri, predicates, value) + p.then((e: NullishType) => { + let r = e as number + let err: BusinessError + callback(err, r) + }).catch((error: NullishType) => { + let err = error as BusinessError + hilog.error(0x0000, 'DataShareHelper', "create failed:" + err) + }) + } + + update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket): Promise { + return new Promise((resolve: (v: number) => void, reject: (error: Error) => void) => { + let p = taskpool.execute(this.ani_update, uri, predicates, value) + p.then((e: NullishType) => { + let r = e as number + resolve(r) + }).catch((e: Error): void => { + hilog.error(0x0000, 'DataShareHelper', "update failed:" + e) + reject(e) + }) + }) + } + } +} diff --git a/data_share/frameworks/js/ani/dataShare/ets/@ohos.data.dataSharePredicates.ets b/data_share/frameworks/js/ani/dataShare/ets/@ohos.data.dataSharePredicates.ets new file mode 100644 index 00000000..91623f45 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/ets/@ohos.data.dataSharePredicates.ets @@ -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. + */ + +import { ValueType } from "@ohos.data.ValuesBucket" + +export default namespace dataSharePredicates{ + +class Cleaner { + static callback(cleaner: Cleaner): void { + console.println("enter Cleaner.callback"); + cleaner.clean() + } + + constructor(targetPtr: long) { + this.targetPtr = targetPtr + } + + native clean(): void + + private targetPtr: long = 0 +} + +class FinalizationAgent { + constructor(obj: T, ptr: long) { + this.register(obj, ptr); + } + + register(obj: T, ptr: long): void { + this.unregisterToken = {}; + this.cleaner = new Cleaner(ptr); + finalizer.register(obj, this.cleaner!, this.unregisterToken); + } + + unregister(): void { + finalizer.unregister(this.unregisterToken); + } + + private cleaner: Cleaner | null = null; + private unregisterToken: object; +} + +let finalizer = new FinalizationRegistry(Cleaner.callback) + +export class DataSharePredicates{ + static { loadLibrary("datasharepredicates_ani") } + private nativePtr:long = 0; + private fzAgent: FinalizationAgent; + + constructor() { + console.log("enter constructor") + if (this.nativePtr == 0) { + console.log("start create") + this.nativePtr = DataSharePredicates.create(); + console.log("stop create") + } + this.fzAgent = new FinalizationAgent(this, this.nativePtr); + } + + unregisterCleaner(): void { + this.fzAgent.unregister(); + } + + getNativePtr():long { + return this.nativePtr; + } + native static create(): long; + native equalTo(field: string, value: ValueType):DataSharePredicates; + native notEqualTo(field: string, value: ValueType):DataSharePredicates; + native orderByDesc(field: string):DataSharePredicates; + native orderByAsc(field: string):DataSharePredicates; + native and():DataSharePredicates; + native limit(total: number, offset: number):DataSharePredicates; + native lessThan(field: string, value: ValueType): DataSharePredicates; + native like(field: string, value: string): DataSharePredicates; + native endWrap(): DataSharePredicates; + native greaterThanOrEqualTo(field: string, value: ValueType): DataSharePredicates; + native contains(field: string, value: string): DataSharePredicates; + native or(): DataSharePredicates; + native beginWrap(): DataSharePredicates; + native greaterThan(field: string, value: ValueType): DataSharePredicates; + native groupBy(fields:Array): DataSharePredicates; + native in(field: string, value: Array): DataSharePredicates; + native notIn(field: string, value: Array): DataSharePredicates; +} +} diff --git a/data_share/frameworks/js/ani/dataShare/include/ani_datashare_helper.h b/data_share/frameworks/js/ani/dataShare/include/ani_datashare_helper.h new file mode 100644 index 00000000..0350fe7f --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/include/ani_datashare_helper.h @@ -0,0 +1,26 @@ +/* + * 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 ANI_DATASHARE_HELPER_H +#define ANI_DATASHARE_HELPER_H + +#include "datashare_helper.h" +#include "ani_datashare_observer.h" + +namespace OHOS { +namespace DataShare { +} // namespace DataShare +} // namespace OHOS +#endif /* ANI_DATASHARE_HELPER_H */ diff --git a/data_share/frameworks/js/ani/dataShare/include/ani_datashare_inner_observer.h b/data_share/frameworks/js/ani/dataShare/include/ani_datashare_inner_observer.h new file mode 100644 index 00000000..8afcb819 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/include/ani_datashare_inner_observer.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 ANI_DATASHARE_INNER_OBSERVER_H +#define ANI_DATASHARE_INNER_OBSERVER_H + +#include + +#include "datashare_log.h" +#include "datashare_helper.h" + +namespace OHOS { +namespace DataShare { +class ANIInnerObserver : public std::enable_shared_from_this { +public: + ANIInnerObserver(ani_vm *vm, ani_ref callback); + virtual ~ANIInnerObserver(); + void OnChange(const DataShareObserver::ChangeInfo &changeInfo = {}, bool isNotifyDetails = false); + ani_ref GetCallback(); + +private: + ani_object GetNewChangeInfo(ani_env *env); + ani_enum_item GetEnumItem(ani_env *env, int32_t type); + ani_object Convert2TSValue(ani_env *env, const std::monostate &value = {}); + ani_object Convert2TSValue(ani_env *env, int64_t value); + ani_object Convert2TSValue(ani_env *env, double value); + ani_object Convert2TSValue(ani_env *env, bool value); + ani_object Convert2TSValue(ani_env *env, const std::string &value); + ani_object Convert2TSValue(ani_env *env, const std::vector &values); + template + ani_object Convert2TSValue(ani_env *env, const std::variant &value); + ani_object Convert2TSValue(ani_env *env, const DataShareValuesBucket &valueBucket); + template + ani_object Convert2TSValue(ani_env *env, const std::vector &values); + ani_object Convert2TSValue(ani_env *env, const DataShareObserver::ChangeInfo& changeInfo); + template + ani_object ReadVariant(ani_env *env, size_t step, size_t index, const _VTp &value); + template + ani_object ReadVariant(ani_env *env, size_t step, size_t index, const _VTp &value); + +private: + ani_vm *vm_; + ani_ref callback_; +}; +} // namespace DataShare +} // namespace OHOS +#endif //ANI_DATASHARE_INNER_OBSERVER_H \ No newline at end of file diff --git a/data_share/frameworks/js/ani/dataShare/include/ani_datashare_observer.h b/data_share/frameworks/js/ani/dataShare/include/ani_datashare_observer.h new file mode 100644 index 00000000..d1370ae8 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/include/ani_datashare_observer.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 ANI_DATASHARE_OBSERVER_H +#define ANI_DATASHARE_OBSERVER_H + +#include "data_ability_observer_stub.h" +#include "ani_datashare_inner_observer.h" + +namespace OHOS { +namespace DataShare { +class ANIDataShareObserver : public AAFwk::DataAbilityObserverStub, + public DataShareObserver { +public: + explicit ANIDataShareObserver(const std::shared_ptr observer) : observer_(observer){}; + virtual ~ANIDataShareObserver(); + void OnChange() override; + void OnChange(const ChangeInfo &changeInfo) override; + std::shared_ptr observer_ = nullptr; +}; +} // namespace DataShare +} // namespace OHOS +#endif /* ANI_DATASHARE_OBSERVER_H */ + \ No newline at end of file diff --git a/data_share/frameworks/js/ani/dataShare/src/ani_datashare_helper.cpp b/data_share/frameworks/js/ani/dataShare/src/ani_datashare_helper.cpp new file mode 100644 index 00000000..2cd08804 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/src/ani_datashare_helper.cpp @@ -0,0 +1,683 @@ +/* + * 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 "uri.h" +#include "ani_utils.h" +#include "datashare_predicates.h" +#include "datashare_template.h" +#include "ani_base_context.h" +#include "ani_datashare_helper.h" +#include "datashare_business_error.h" +#include "ipc_skeleton.h" +#include "tokenid_kit.h" + +using namespace OHOS; +using namespace OHOS::DataShare; +using namespace OHOS::Security::AccessToken; +using Uri = OHOS::Uri; + +static constexpr int EXCEPTION_SYSTEMAPP_CHECK = 202; +static std::map>> observerMap_; + +static bool IsSystemApp() +{ + uint64_t tokenId = IPCSkeleton::GetSelfTokenID(); + return TokenIdKit::IsSystemAppByFullTokenID(tokenId); +} + +static void ThrowBusinessError(ani_env *env, int errCode, std::string&& errMsg) +{ + LOG_DEBUG("Begin ThrowBusinessError."); + static const char *errorClsName = "L@ohos/base/BusinessError;"; + ani_class cls {}; + if (ANI_OK != env->FindClass(errorClsName, &cls)) { + LOG_ERROR("find class BusinessError %{public}s failed", errorClsName); + return; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", ":V", &ctor)) { + LOG_ERROR("find method BusinessError.constructor failed"); + return; + } + ani_object errorObject; + if (ANI_OK != env->Object_New(cls, ctor, &errorObject)) { + LOG_ERROR("create BusinessError object failed"); + return; + } + ani_double aniErrCode = static_cast(errCode); + ani_string errMsgStr; + if (ANI_OK != env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &errMsgStr)) { + LOG_ERROR("convert errMsg to ani_string failed"); + return; + } + if (ANI_OK != env->Object_SetFieldByName_Double(errorObject, "code", aniErrCode)) { + LOG_ERROR("set error code failed"); + return; + } + if (ANI_OK != env->Object_SetPropertyByName_Ref(errorObject, "message", errMsgStr)) { + LOG_ERROR("set error message failed"); + return; + } + env->ThrowError(static_cast(errorObject)); + return; +} + +static bool getNameSpace(ani_env *env, ani_namespace &ns) +{ + const char *spaceName = "L@ohos/data/dataShare/dataShare;"; + if (ANI_OK != env->FindNamespace(spaceName, &ns)) { + LOG_ERROR("Not found space name '%{public}s'", spaceName); + return false; + } + + return true; +} + +static bool getClass(ani_env *env, ani_class &cls) +{ + ani_namespace ns; + if (!getNameSpace(env, ns)) { + return false; + } + + const char *className = "LDataShareHelperInner;"; + if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) { + LOG_ERROR("Not found class name '%{public}s'", className); + return false; + } + + return true; +} + +static bool getUri(ani_env *env, ani_string uri, std::string &strUri) +{ + strUri = AniStringUtils::ToStd(env, uri); + if (strUri.empty()) { + LOG_ERROR("uri is empty"); + return false; + } + + return true; +} + +static bool getType(ani_env *env, ani_string type, std::string &strType) +{ + strType = AniStringUtils::ToStd(env, type); + if (strType.empty()) { + LOG_ERROR("type is empty"); + return false; + } + + return true; +} + +static bool getEvent(ani_env *env, ani_string event, std::string &strEvent) +{ + strEvent = AniStringUtils::ToStd(env, event); + if (strEvent.empty()) { + LOG_ERROR("event is empty"); + return false; + } + + return true; +} + +static bool getDataShareHelper(ani_env *env, ani_object object, DataShareHelper *&helper) +{ + ani_long nativePtr; + if (ANI_OK != env->Object_GetFieldByName_Long(object, "nativePtr", &nativePtr)) { + LOG_ERROR("nativePtr is nullptr"); + return false; + } + + auto helperHolder = reinterpret_cast *>(nativePtr); + if (helperHolder == nullptr) { + LOG_ERROR("SharedPtrHolder is nullptr"); + return false; + } + + helper = helperHolder->Get().get(); + if (helper == nullptr) { + LOG_ERROR("DataShareHelper is nullptr"); + return false; + } + + return true; +} + +static ani_status GetIsProxy(ani_env *env, ani_object options, bool &isProxy) +{ + ani_ref proxyObj; + ani_status result = env->Object_GetPropertyByName_Ref(options, "isProxy", &proxyObj); + if (ANI_OK != result) { + LOG_ERROR("options Failed to get property named type: %{public}d", result); + return result; + } + + ani_boolean isUndefined; + result = env->Reference_IsUndefined(static_cast(proxyObj), &isUndefined); + if (ANI_OK != result) { + LOG_ERROR("options Object_GetFieldByName_Ref isProxyField Failed"); + return result; + } + + if (isUndefined) { + LOG_ERROR("options isProxyField is Undefined Now"); + isProxy = false; + return ANI_OK; + } + + ani_boolean proxy; + result = env->Object_CallMethodByName_Boolean(static_cast(proxyObj), "unboxed", nullptr, &proxy); + if (ANI_OK != result) { + LOG_ERROR("options Failed to get property named isProxy: %{public}d", result); + return result; + } + + isProxy = proxy; + return ANI_OK; +} + +static std::shared_ptr CreateDataShareHelper(ani_env *env, ani_object options, std::string &strUri, + std::shared_ptr &ctx) +{ + bool isProxy = false; + if (GetIsProxy(env, options, isProxy) != ANI_OK) { + LOG_ERROR("Get isProxy Failed"); + return nullptr; + } + CreateOptions opts = { + isProxy, + ctx->GetToken(), + Uri(strUri).GetScheme() == "datashareproxy", + }; + + return DataShareHelper::Creator(strUri, opts); +} + +static ani_object ANI_Create([[maybe_unused]] ani_env *env, ani_object context, ani_string uri, ani_object options) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return nullptr; + } + + if (!IsSystemApp()) { + ThrowBusinessError(env, EXCEPTION_SYSTEMAPP_CHECK, "not system app"); + } + + std::string strUri; + ani_class cls; + if (!getUri(env, uri, strUri) || !getClass(env, cls)) { + return nullptr; + } + + ani_boolean isUndefined; + if (ANI_OK != env->Reference_IsUndefined(options, &isUndefined)) { + LOG_ERROR("Get is undefined Failed"); + return nullptr; + } + + auto ctx = AbilityRuntime::GetStageModeContext(env, context); + if (ctx == nullptr) { + LOG_ERROR("Get Context Failed"); + return nullptr; + } + std::shared_ptr dataShareHelper; + if (isUndefined) { + dataShareHelper = DataShareHelper::Creator(ctx->GetToken(), strUri); + } else { + dataShareHelper = CreateDataShareHelper(env, options, strUri, ctx); + } + + if (dataShareHelper == nullptr) { + LOG_ERROR("Create Object DataShareHelper is null"); + return nullptr; + } + + auto shareptrData = new (std::nothrow) SharedPtrHolder(dataShareHelper); + if (shareptrData == nullptr) { + LOG_ERROR("Create Object SharedPtrHolder is null"); + return nullptr; + } + + const char *spaceName = "L@ohos/data/dataShare/dataShare;"; + const char *className = "LDataShareHelperInner;"; + ani_object dataShareObj = AniObjectUtils::Create(env, spaceName, className, + reinterpret_cast(shareptrData)); + + return dataShareObj; +} + +static void ANI_OnType([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_string type, ani_string uri, ani_object callback) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return; + } + std::string strType; + std::string strUri; + DataShareHelper *helper = nullptr; + if (!getType(env, type, strType) || !getUri(env, uri, strUri) || !getDataShareHelper(env, object, helper)) { + return; + } + + ani_ref callbackRef; + if (ANI_OK != env->GlobalReference_Create(callback, &callbackRef)) { + LOG_ERROR("Create callback failed"); + return; + } + + if (strType == "dataChange") { + observerMap_.try_emplace(strUri); + + auto &list = observerMap_.find(strUri)->second; + for (auto &it : list) { + if (callbackRef == it->observer_->GetCallback()) { + LOG_ERROR("The observer has already subscribed."); + return; + } + } + + ani_vm *vm = nullptr; + if (ANI_OK != env->GetVM(&vm)) { + LOG_ERROR("GetVM failed."); + return; + } + + auto innerObserver = std::make_shared(vm, callbackRef); + sptr observer(new (std::nothrow) ANIDataShareObserver(innerObserver)); + if (observer == nullptr) { + LOG_ERROR("observer is nullptr"); + return; + } + + helper->RegisterObserver(Uri(strUri), observer); + list.push_back(observer); + } +} + +static void DataChangeOffEvent(ani_env *env, ani_ref &callbackRef, std::string &strUri, DataShareHelper *&helper) +{ + auto obs = observerMap_.find(strUri); + if (obs == observerMap_.end()) { + LOG_ERROR("this uri hasn't been registered"); + return; + } + + auto &list = obs->second; + auto it = list.begin(); + while (it != list.end()) { + ani_boolean isEquals = false; + if (ANI_OK != env->Reference_StrictEquals(callbackRef, (*it)->observer_->GetCallback(), &isEquals)) { + LOG_ERROR("%{public}s: check observer equal failed!", __func__); + return; + } + + if (callbackRef != nullptr && !isEquals) { + ++it; + continue; + } + + helper->UnregisterObserverExt(Uri(strUri), + std::shared_ptr((*it).GetRefPtr(), [holder = *it](const auto*) {})); + it = list.erase(it); + } + + if (list.empty()) { + observerMap_.erase(strUri); + } +} + +static void DataChangeOffType(ani_env *env, ani_ref &callbackRef, std::string &strUri, DataShareHelper *&helper) +{ + auto obs = observerMap_.find(strUri); + if (obs == observerMap_.end()) { + LOG_ERROR("this uri hasn't been registered"); + return; + } + + auto &list = obs->second; + auto it = list.begin(); + while (it != list.end()) { + ani_boolean isEquals = false; + if (ANI_OK != env->Reference_StrictEquals(callbackRef, (*it)->observer_->GetCallback(), &isEquals)) { + LOG_ERROR("%{public}s: check observer equal failed!", __func__); + return; + } + + if (callbackRef != nullptr && !isEquals) { + ++it; + continue; + } + + helper->UnregisterObserver(Uri(strUri), *it); + it = list.erase(it); + } + + if (list.empty()) { + observerMap_.erase(strUri); + } +} + +static void ANI_OffType([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_string type, ani_string uri, ani_object callback) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return; + } + std::string strType; + std::string strUri; + DataShareHelper *helper = nullptr; + if (!getType(env, type, strType) || !getUri(env, uri, strUri) || !getDataShareHelper(env, object, helper)) { + return; + } + + ani_boolean isUndefined; + if (ANI_OK != env->Reference_IsUndefined(callback, &isUndefined)) { + LOG_ERROR("Call Reference_IsUndefined failed"); + return; + } + + ani_ref callbackRef; + if (isUndefined) { + LOG_ERROR("%{public}s: callback is undefined", __func__); + callbackRef = nullptr; + } else { + if (ANI_OK != env->GlobalReference_Create(callback, &callbackRef)) { + LOG_ERROR("Create callback failed"); + return; + } + } + + if (strType == "dataChange") { + DataChangeOffType(env, callbackRef, strUri, helper); + } +} + +static void ANI_OnEvent([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_string event, ani_enum_item subscriptionType, ani_string uri, ani_object callback) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return; + } + std::string strEvent; + std::string strUri; + DataShareHelper *helper = nullptr; + if (!getEvent(env, event, strEvent) || !getUri(env, uri, strUri) || !getDataShareHelper(env, object, helper)) { + return; + } + + ani_ref callbackRef; + if (ANI_OK != env->GlobalReference_Create(callback, &callbackRef)) { + LOG_ERROR("Create callback failed"); + return; + } + + if (strEvent == "dataChange") { + observerMap_.try_emplace(strUri); + + auto &list = observerMap_.find(strUri)->second; + for (auto &it : list) { + if (callbackRef == it->observer_->GetCallback()) { + LOG_ERROR("The observer has already subscribed."); + return; + } + } + + ani_vm *vm = nullptr; + if (ANI_OK != env->GetVM(&vm)) { + LOG_ERROR("GetVM failed."); + return; + } + + auto innerObserver = std::make_shared(vm, callbackRef); + sptr observer(new (std::nothrow) ANIDataShareObserver(innerObserver)); + if (observer == nullptr) { + LOG_ERROR("observer is nullptr"); + return; + } + + helper->RegisterObserverExt(Uri(strUri), + std::shared_ptr(observer.GetRefPtr(), [holder = observer](const auto*) {}), false); + list.push_back(observer); + } +} + +static void ANI_OffEvent([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_string event, ani_enum_item subscriptionType, ani_string uri, ani_object callback) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return; + } + std::string strEvent; + std::string strUri; + DataShareHelper *helper = nullptr; + if (!getEvent(env, event, strEvent) || !getUri(env, uri, strUri) || !getDataShareHelper(env, object, helper)) { + return; + } + + ani_boolean isUndefined; + if (ANI_OK != env->Reference_IsUndefined(callback, &isUndefined)) { + LOG_ERROR("Call Reference_IsUndefined failed"); + return; + } + + ani_ref callbackRef; + if (isUndefined) { + LOG_ERROR("%{public}s: callback is undefined", __func__); + callbackRef = nullptr; + } else { + if (ANI_OK != env->GlobalReference_Create(callback, &callbackRef)) { + LOG_ERROR("Create callback failed"); + return; + } + } + + if (strEvent == "dataChange") { + DataChangeOffEvent(env, callbackRef, strUri, helper); + } +} + +static ani_object ANI_Query([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_string uri, ani_object predicates, ani_object columns) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return nullptr; + } + std::string strUri; + ani_class cls; + DataShareHelper *helper = nullptr; + if (!getUri(env, uri, strUri) || !getClass(env, cls) || !getDataShareHelper(env, object, helper)) { + return nullptr; + } + + auto pred = AniObjectUtils::Unwrap(env, predicates); + if (pred == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr : %{public}d", pred == nullptr); + return nullptr; + } + + std::vector strings; + if (!UnionAccessor(env, columns).TryConvertArray(strings)) { + LOG_ERROR("TryConvertArray columns Failed"); + return nullptr; + } + + Uri uriObj(strUri); + DatashareBusinessError businessError; + auto resultObject = helper->Query(uriObj, *pred, strings, &businessError); + if (resultObject == nullptr) { + LOG_ERROR("query failed, result is null!"); + return nullptr; + } + + if (businessError.GetCode() != 0) { + LOG_ERROR("query failed, errorCode : %{public}d", businessError.GetCode()); + return nullptr; + } + + auto shareptrData = new (std::nothrow) SharedPtrHolder(resultObject); + if (shareptrData == nullptr) { + LOG_ERROR("Create Object SharedPtrHolder is null"); + return nullptr; + } + + const char *className = "L@ohos/data/DataShareResultSet/DataShareResultSetImpl;"; + ani_object resultSetObj = AniObjectUtils::Create(env, className, + reinterpret_cast(shareptrData)); + + return resultSetObj; +} + +using BucketMap = std::map; +using BucketPtr = std::shared_ptr; +using CallbackType = convertCallback; + +auto g_convertValuesBucket = [](ani_env *env, ani_ref &ani_key, ani_ref &object, BucketPtr records) { + auto key = AniStringUtils::ToStd(env, static_cast(ani_key)); + auto unionObject = static_cast(object); + UnionAccessor unionAccessor(env, unionObject); + if (unionAccessor.IsInstanceOf("Lstd/core/Double;")) { + double value; + unionAccessor.TryConvert(value); + records->emplace(key, value); + return true; + } + + if (unionAccessor.IsInstanceOf("Lstd/core/String;")) { + std::string value; + unionAccessor.TryConvert(value); + records->emplace(key, value); + return true; + } + + if (unionAccessor.IsInstanceOf("Lstd/core/Boolean;")) { + bool value; + unionAccessor.TryConvert(value); + records->emplace(key, value); + return true; + } + + std::vector arrayUint8Values; + if (unionAccessor.TryConvertArray(arrayUint8Values)) { + records->emplace(key, arrayUint8Values); + return true; + } + + if (OptionalAccessor(env, unionObject).IsNull()) { + records->emplace(key, nullptr); + return true; + } + + LOG_ERROR("Unexpected object type"); + return false; +}; + +static ani_double ANI_Update([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_string uri, ani_object predicates, ani_object value) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return ani_double(DATA_SHARE_ERROR); + } + std::string strUri; + ani_class cls; + DataShareHelper *helper = nullptr; + if (!getUri(env, uri, strUri) || !getClass(env, cls) || !getDataShareHelper(env, object, helper)) { + return ani_double(DATA_SHARE_ERROR); + } + + auto pred = AniObjectUtils::Unwrap(env, predicates); + if (pred == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr : %{public}d", pred == nullptr); + return ani_double(DATA_SHARE_ERROR); + } + + auto bucket = std::make_shared(); + if (!forEachMapEntry(env, value, g_convertValuesBucket, bucket)) { + LOG_ERROR("Is bucket null: %{public}d", bucket->empty()); + return ani_double(DATA_SHARE_ERROR); + } + + Uri uriObj(strUri); + DataShareValuesBucket dataShareValuesBucket(*bucket); + + return static_cast(helper->Update(uriObj, *pred, dataShareValuesBucket)); +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + LOG_ERROR("Unsupported ANI_VERSION_1"); + return ANI_ERROR; + } + + ani_namespace ns; + if (!getNameSpace(env, ns)) { + return ANI_ERROR; + } + + std::array functions = { + ani_native_function {"create", nullptr, reinterpret_cast(ANI_Create)}, + }; + + if (ANI_OK != env->Namespace_BindNativeFunctions(ns, functions.data(), functions.size())) { + LOG_ERROR("Cannot bind native functions to namespace"); + return ANI_ERROR; + } + + std::array methods = { + ani_native_function {"on", "Lstd/core/String;Lstd/core/String;Lstd/core/Function2;:V", + reinterpret_cast(ANI_OnType)}, + ani_native_function {"off", "Lstd/core/String;Lstd/core/String;Lstd/core/Function2;:V", + reinterpret_cast(ANI_OffType)}, + ani_native_function {"on", + "Lstd/core/String;L@ohos/data/dataShare/dataShare/SubscriptionType;Lstd/core/String;Lstd/core/Function2;:V", + reinterpret_cast(ANI_OnEvent)}, + ani_native_function {"off", + "Lstd/core/String;L@ohos/data/dataShare/dataShare/SubscriptionType;Lstd/core/String;Lstd/core/Function2;:V", + reinterpret_cast(ANI_OffEvent)}, + ani_native_function {"ani_query", nullptr, reinterpret_cast(ANI_Query)}, + ani_native_function {"ani_update", nullptr, reinterpret_cast(ANI_Update)}, + }; + + ani_class cls; + if (!getClass(env, cls)) { + return ANI_ERROR; + } + + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + LOG_ERROR("Cannot bind native methods to class"); + return ANI_ERROR; + } + + static const char *cleanerName = "LCleaner;"; + auto cleanerCls = AniTypeFinder(env).FindClass(ns, cleanerName); + NativePtrCleaner(env).Bind(cleanerCls.value()); + + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/data_share/frameworks/js/ani/dataShare/src/ani_datashare_inner_observer.cpp b/data_share/frameworks/js/ani/dataShare/src/ani_datashare_inner_observer.cpp new file mode 100644 index 00000000..b81867b9 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/src/ani_datashare_inner_observer.cpp @@ -0,0 +1,334 @@ +/* + * 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 "ani_utils.h" +#include "datashare_valuebucket_convert.h" +#include "ani_datashare_observer.h" + +namespace OHOS { +namespace DataShare { +using namespace std::chrono; +ANIInnerObserver::ANIInnerObserver(ani_vm *vm, ani_ref callback) : vm_(vm), callback_(callback) +{ +} + +ANIInnerObserver::~ANIInnerObserver() +{ + vm_->DetachCurrentThread(); +} + +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, const std::monostate &value) +{ + (void)env; + (void)value; + return nullptr; +} + +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, const std::string &value) +{ + return StringToObject(env, value); +} + +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, const std::vector &values) +{ + return Uint8ArrayToObject(env, values); +} + +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, int64_t value) +{ + return DoubleToObject(env, value); +} + +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, double value) +{ + return DoubleToObject(env, value); +} + +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, bool value) +{ + return BoolToObject(env, value); +} + +template +ani_object ANIInnerObserver::ReadVariant(ani_env *env, size_t step, size_t index, const _VTp &value) +{ + return nullptr; +} + +template +ani_object ANIInnerObserver::ReadVariant(ani_env *env, size_t step, size_t index, const _VTp &value) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return nullptr; + } + if (step == index) { + auto *realValue = std::get_if<_First>(&value); + if (realValue == nullptr) { + return nullptr; + } + + return Convert2TSValue(env, *realValue); + } + + return ReadVariant<_VTp, _Rest...>(env, step + 1, index, value); +} + +template +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, const std::variant &value) +{ + return ReadVariant(env, 0, value.index(), value); +} + +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, const DataShareValuesBucket &valueBucket) +{ + ani_object valuesBucketList = nullptr; + static const char *className = "Lescompat/Record;"; + + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + LOG_ERROR("Not found '%{public}s'.", className); + return valuesBucketList; + } + + ani_method aniCtor; + if (ANI_OK != env->Class_FindMethod(cls, "", ":V", &aniCtor)) { + LOG_ERROR("Class_GetMethod Failed '%{public}s'.", className); + return valuesBucketList; + } + + if (ANI_OK != env->Object_New(cls, aniCtor, &valuesBucketList)) { + LOG_ERROR("Object_New Failed '%{public}s'.", className); + return valuesBucketList; + } + + ani_method setter; + if (ANI_OK != env->Class_FindMethod(cls, "$_set", nullptr, &setter)) { + LOG_ERROR("Class_GetMethod set Failed '%{public}s'.", className); + return valuesBucketList; + } + + const auto &valuesMap = valueBucket.valuesMap; + for (auto& value : valuesMap) { + ani_string aniKey = AniStringUtils::ToAni(env, value.first); + ani_object aniObjVal = Convert2TSValue(env, value.second); + if (ANI_OK != env->Object_CallMethod_Void(valuesBucketList, setter, aniKey, aniObjVal)) { + LOG_ERROR("Object_CallMethodByName_Void $_set Faild "); + break; + } + } + + return valuesBucketList; +} + +template +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, const std::vector &values) +{ + ani_class arrayCls; + if (ANI_OK != env->FindClass("Lescompat/Array;", &arrayCls)) { + LOG_ERROR("FindClass Lescompat/Array; Failed"); + return nullptr; + } + + ani_method arrayCtor; + if (ANI_OK != env->Class_FindMethod(arrayCls, "", "I:V", &arrayCtor)) { + LOG_ERROR("Class_FindMethod Failed"); + return nullptr; + } + + ani_object arrayObj; + if (ANI_OK != env->Object_New(arrayCls, arrayCtor, &arrayObj, values.size())) { + LOG_ERROR("Object_New Array Faild"); + return nullptr; + } + + ani_size index = 0; + for (auto value : values) { + if (ANI_OK != env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, + Convert2TSValue(env, value))) { + LOG_ERROR("Object_CallMethodByName_Void $_set Faild "); + break; + } + + index++; + } + + return arrayObj; +} + +ani_enum_item ANIInnerObserver::GetEnumItem(ani_env *env, int32_t type) +{ + ani_namespace ns; + static const char *namespaceName = "L@ohos/data/dataShare/dataShare;"; + if (ANI_OK != env->FindNamespace(namespaceName, &ns)) { + LOG_ERROR("Not found '%{public}s'", namespaceName); + return nullptr; + } + + ani_enum aniEnum{}; + const char *enumName = "LChangeType;"; + if (ANI_OK != env->Namespace_FindEnum(ns, enumName, &aniEnum)) { + LOG_ERROR("Not found '%{public}s'", enumName); + return nullptr; + } + + int32_t index = 0U; + ani_enum_item enumItem{}; + while (ANI_OK == env->Enum_GetEnumItemByIndex(aniEnum, index++, &enumItem)) { + ani_int intValue = -1; + if (ANI_OK != env->EnumItem_GetValue_Int(enumItem, &intValue)) { + LOG_ERROR("EnumItem_GetValue_Int failed."); + return nullptr; + } + + if (intValue == type) { + return enumItem; + } + } + + LOG_ERROR("Get enumItem by %{public}d failed.", type); + return nullptr; +} + +ani_object ANIInnerObserver::GetNewChangeInfo(ani_env *env) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr %{public}s", __func__); + return nullptr; + } + ani_namespace ns; + const char *spaceName = "L@ohos/data/dataShare/dataShare;"; + if (ANI_OK != env->FindNamespace(spaceName, &ns)) { + LOG_ERROR("Not found space name '%{public}s'", spaceName); + return nullptr; + } + + ani_class cls; + const char *className = "LChangeInfoInner;"; + if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) { + LOG_ERROR("Not found class name '%{public}s'", className); + return nullptr; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + LOG_ERROR("Get ctor Failed"); + return nullptr; + } + + ani_object object; + if (ANI_OK != env->Object_New(cls, ctor, &object)) { + LOG_ERROR("Create GetNewChangeInfo Object Failed"); + return nullptr; + } + + return object; +} + +ani_object ANIInnerObserver::Convert2TSValue(ani_env *env, const DataShareObserver::ChangeInfo& changeInfo) +{ + ani_object infoObj = GetNewChangeInfo(env); + if (infoObj == nullptr) { + LOG_ERROR("Create ts new ChangeInfo object failed!"); + return nullptr; + } + + ani_enum_item aniType = GetEnumItem(env, ANIDataShareObserver::UPDATE); + if (aniType == nullptr) { + LOG_ERROR("GetEnumItem failed"); + return nullptr; + } + + ani_status status = env->Object_SetPropertyByName_Ref(infoObj, "type", aniType); + if (ANI_OK != status) { + LOG_ERROR("Object_SetFieldByName_Int failed status : %{public}d", status); + return nullptr; + } + + ani_string uri; + env->String_NewUTF8(changeInfo.uris_.front().ToString().c_str(), changeInfo.uris_.front().ToString().size(), &uri); + status = env->Object_SetPropertyByName_Ref(infoObj, "uri", uri); + if (ANI_OK != status) { + LOG_ERROR("Object_SetPropertyByName_Ref failed status : %{public}d", status); + return nullptr; + } + + auto &valBucket = const_cast(changeInfo); + std::vector VBuckets = ValueProxy::Convert(std::move(valBucket.valueBuckets_)); + ani_object valueBuckets = Convert2TSValue(env, VBuckets); + status = env->Object_SetPropertyByName_Ref(infoObj, "values", valueBuckets); + if (ANI_OK != status) { + LOG_ERROR("Object_SetPropertyByName_Ref failed status : %{public}d", status); + return nullptr; + } + + return infoObj; +} + +void ANIInnerObserver::OnChange(const DataShareObserver::ChangeInfo& changeInfo, bool isNotifyDetails) +{ + auto time = static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); + LOG_INFO("ANIInnerObserver datashare callback start, times %{public}" PRIu64 ".", time); + if (callback_ == nullptr) { + LOG_ERROR("callback_ is nullptr"); + return; + } + + ani_env *env = nullptr; + ani_options aniArgs {0, nullptr}; + if (ANI_ERROR == vm_->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env)) { + if (ANI_OK != vm_->GetEnv(ANI_VERSION_1, &env)) { + LOG_ERROR("GetEnv failed"); + return; + } + } + + ani_ref result; + auto fnObj = reinterpret_cast(callback_); + if (fnObj == nullptr) { + LOG_ERROR("%{public}s: fnObj == nullptr", __func__); + return; + } + + std::vector args = { nullptr }; + if (isNotifyDetails) { + auto argsObj = Convert2TSValue(env, changeInfo); + if (argsObj == nullptr) { + LOG_ERROR("%{public}s: argsObj is null", __func__); + return; + } + + args.push_back(argsObj); + } + + ani_status callStatus = env->FunctionalObject_Call(fnObj, args.size(), args.data(), &result); + if (ANI_OK != callStatus) { + LOG_ERROR("ani_call_function failed status : %{public}d", callStatus); + return; + } + + LOG_INFO("ANIInnerObserver datashare callback end, times %{public}" PRIu64 ".", time); +} + +ani_ref ANIInnerObserver::GetCallback() +{ + return callback_; +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/js/ani/dataShare/src/ani_datashare_observer.cpp b/data_share/frameworks/js/ani/dataShare/src/ani_datashare_observer.cpp new file mode 100644 index 00000000..c2e8c761 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/src/ani_datashare_observer.cpp @@ -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. + */ +#define LOG_TAG "ANIDataShareObserver" + +#include "ani_datashare_observer.h" + +#include "adaptor.h" +#include +#include "datashare_log.h" + +namespace OHOS { +namespace DataShare { +ANIDataShareObserver::~ANIDataShareObserver() {} + +void ANIDataShareObserver::OnChange() +{ + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); + observer_->OnChange(); +} + +void ANIDataShareObserver::OnChange(const ChangeInfo &changeInfo) +{ + LOG_DEBUG("ANIDataShareObserver ChangeInfo Start"); + observer_->OnChange(changeInfo, true); +} +} // namespace DataShare +} // namespace OHOS diff --git a/data_share/frameworks/js/ani/dataShare/src/data_share_predicates.cpp b/data_share/frameworks/js/ani/dataShare/src/data_share_predicates.cpp new file mode 100644 index 00000000..04a2df09 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShare/src/data_share_predicates.cpp @@ -0,0 +1,431 @@ +/* + * 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 "ani_utils.h" +#include "datashare_log.h" +#include "datashare_predicates_cleaner.h" + +using namespace OHOS::DataShare; + +static DataSharePredicates* unwrapp(ani_env *env, ani_object object) +{ + DataSharePredicates *holder = AniObjectUtils::Unwrap(env, object); + if (holder == nullptr) { + LOG_ERROR("holder is nullptr"); + return nullptr; + } + return holder; +} + +static ani_long Create([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class clazz) +{ + auto holder = new DataSharePredicates(); + return reinterpret_cast(holder); +} + +static ani_object EqualTo([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_string field, + ani_object value) +{ + auto stringContentOne = AniStringUtils::ToStd(env, field); + + auto dataSharePredicates = unwrapp(env, object); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + UnionAccessor unionAccessor(env, value); + double fValue = 0.0; + if (unionAccessor.TryConvert(fValue)) { + dataSharePredicates->EqualTo(stringContentOne, fValue); + } + + std::string strValue = ""; + if (unionAccessor.TryConvert(strValue)) { + dataSharePredicates->EqualTo(stringContentOne, strValue); + } + + bool boolValue = false; + if (unionAccessor.TryConvert(boolValue)) { + dataSharePredicates->EqualTo(stringContentOne, boolValue); + } + + return object; +} + +static ani_object NotEqualTo([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_string field, + ani_object value) +{ + auto stringContentOne = AniStringUtils::ToStd(env, field); + + auto dataSharePredicates = unwrapp(env, object); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + UnionAccessor unionAccessor(env, value); + double fValue = 0.0; + if (unionAccessor.TryConvert(fValue)) { + dataSharePredicates->NotEqualTo(stringContentOne, fValue); + } + + std::string strValue = ""; + if (unionAccessor.TryConvert(strValue)) { + dataSharePredicates->NotEqualTo(stringContentOne, strValue); + } + + bool boolValue = false; + if (unionAccessor.TryConvert(boolValue)) { + dataSharePredicates->NotEqualTo(stringContentOne, boolValue); + } + return object; +} + +static ani_object OrderByDesc([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_string field) +{ + auto stringContent = AniStringUtils::ToStd(env, field); + auto dataSharePredicates = unwrapp(env, object); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->OrderByDesc(stringContent); + return object; +} + +static ani_object OrderByAsc([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_string field) +{ + auto stringContent = AniStringUtils::ToStd(env, field); + auto dataSharePredicates = unwrapp(env, object); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->OrderByAsc(stringContent); + return object; +} + +static ani_object And([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) +{ + auto dataSharePredicates = unwrapp(env, object); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->And(); + return object; +} + +static ani_object Limit([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, ani_double total, + ani_double offset) +{ + auto dataSharePredicates = unwrapp(env, object); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->Limit(total, offset); + return object; +} + +static ani_object LessThan([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_string field, + ani_object value) +{ + auto fieldStr = AniStringUtils::ToStd(env, field); + + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + UnionAccessor unionAccessor(env, value); + double fValue = 0.0; + if (unionAccessor.TryConvert(fValue)) { + dataSharePredicates->LessThan(fieldStr, fValue); + } + + std::string strValue = ""; + if (unionAccessor.TryConvert(strValue)) { + dataSharePredicates->LessThan(fieldStr, strValue); + } + + bool boolValue = false; + if (unionAccessor.TryConvert(boolValue)) { + dataSharePredicates->LessThan(fieldStr, boolValue); + } + return obj; +} + +static ani_object Like([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_string field, + ani_string value) +{ + auto fieldStr = AniStringUtils::ToStd(env, field); + auto valueStr = AniStringUtils::ToStd(env, value); + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->Like(fieldStr, valueStr); + return obj; +} + +static ani_object EndWrap([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj) +{ + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->EndWrap(); + return obj; +} + +static ani_object GreaterThanOrEqualTo([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, + ani_string field, ani_object value) +{ + auto fieldStr = AniStringUtils::ToStd(env, field); + + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + UnionAccessor unionAccessor(env, value); + double fValue = 0.0; + if (unionAccessor.TryConvert(fValue)) { + std::cout << "Double value is " << fValue << std::endl; + dataSharePredicates->GreaterThanOrEqualTo(fieldStr, fValue); + } + + std::string strValue = ""; + if (unionAccessor.TryConvert(strValue)) { + std::cout << "String value is " << strValue << std::endl; + dataSharePredicates->GreaterThanOrEqualTo(fieldStr, strValue); + } + + bool boolValue = false; + if (unionAccessor.TryConvert(boolValue)) { + std::cout << "Boolean value is " << boolValue << std::endl; + dataSharePredicates->GreaterThanOrEqualTo(fieldStr, boolValue); + } + return obj; +} + +static ani_object Contains([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_string field, + ani_string value) +{ + auto fieldStr = AniStringUtils::ToStd(env, field); + auto valueStr = AniStringUtils::ToStd(env, value); + + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->Contains(fieldStr, valueStr); + return obj; +} + +static ani_object Or([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj) +{ + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->Or(); + return obj; +} + +static ani_object BeginWrap([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj) +{ + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->BeginWrap(); + return obj; +} + +static ani_object GreaterThan([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_string field, + ani_object value) +{ + auto fieldStr = AniStringUtils::ToStd(env, field); + + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + UnionAccessor unionAccessor(env, value); + ani_double valueD = 0.0; + if (unionAccessor.TryConvert(valueD)) { + dataSharePredicates->GreaterThan(fieldStr, static_cast(valueD)); + } + + ani_string strValue = nullptr; + if (unionAccessor.IsInstanceOf("Lstd/core/String;")) { + dataSharePredicates->GreaterThan(fieldStr, AniStringUtils::ToStd(env, strValue)); + } + + ani_boolean boolValue = 0; + if (unionAccessor.IsInstanceOf("Lstd/core/Boolean;")) { + if (ANI_OK != env->Object_CallMethodByName_Boolean(value, "unboxed", nullptr, &boolValue)) { + dataSharePredicates->GreaterThan(fieldStr, static_cast(boolValue)); + } + } + + return obj; +} + +static ani_object GroupBy([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_object arrayObj) +{ + ani_double length; + + if (ANI_OK != env->Object_GetPropertyByName_Double(arrayObj, "length", &length)) { + return obj; + } + + std::vector strings; + for (int i = 0; i < int(length); i++) { + ani_ref stringEntryRef; + if (ANI_OK != env->Object_CallMethodByName_Ref(arrayObj, "$_get", "I:Lstd/core/Object;", &stringEntryRef, + (ani_int)i)) { + return obj; + } + strings.emplace_back(AniStringUtils::ToStd(env, static_cast(stringEntryRef))); + } + + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + dataSharePredicates->GroupBy(strings); + return obj; +} + +static ani_object In([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_string fieldStr, + ani_object arrayObj) +{ + UnionAccessor unionAccessor(env, arrayObj); + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + auto stringContent = AniStringUtils::ToStd(env, static_cast(fieldStr)); + std::vector arrayDoubleValues = {}; + if (unionAccessor.TryConvertArray(arrayDoubleValues) && arrayDoubleValues.size() > 0) { + std::vector values = convertVector(arrayDoubleValues); + dataSharePredicates->In(stringContent, values); + } + std::vector arrayStringValues = {}; + if (unionAccessor.TryConvertArray(arrayStringValues) && arrayStringValues.size() > 0) { + dataSharePredicates->In(stringContent, arrayStringValues); + } + std::vector arrayBoolValues = {}; + if (unionAccessor.TryConvertArray(arrayBoolValues) && arrayBoolValues.size() > 0) { + std::vector values = convertVector(arrayBoolValues); + dataSharePredicates->In(stringContent, values); + } + return obj; +} + +static ani_object NotIn([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_string fieldStr, + ani_object arrayObj) +{ + UnionAccessor unionAccessor(env, arrayObj); + auto dataSharePredicates = unwrapp(env, obj); + if (dataSharePredicates == nullptr) { + LOG_ERROR("dataSharePredicates is nullptr"); + return nullptr; + } + auto stringContent = AniStringUtils::ToStd(env, static_cast(fieldStr)); + std::vector arrayDoubleValues = {}; + if (unionAccessor.TryConvertArray(arrayDoubleValues) && arrayDoubleValues.size() > 0) { + std::vector values = convertVector(arrayDoubleValues); + dataSharePredicates->NotIn(stringContent, values); + } + std::vector arrayStringValues = {}; + if (unionAccessor.TryConvertArray(arrayStringValues) && arrayStringValues.size() > 0) { + dataSharePredicates->NotIn(stringContent, arrayStringValues); + } + std::vector arrayBoolValues = {}; + if (unionAccessor.TryConvertArray(arrayBoolValues) && arrayBoolValues.size() > 0) { + std::vector values = convertVector(arrayBoolValues); + dataSharePredicates->NotIn(stringContent, values); + } + return obj; +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + LOG_INFO("ANI_Constructor enter "); + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + std::cerr << "Unsupported ANI_VERSION_1" << std::endl; + return ANI_ERROR; + } + ani_namespace ns; + if (env->FindNamespace("L@ohos/data/dataSharePredicates/dataSharePredicates;", &ns) != ANI_OK) { + LOG_ERROR("Namespace not found"); + return ANI_ERROR; + }; + + ani_class cls; + static const char *className = "LDataSharePredicates;"; + if (env->Namespace_FindClass(ns, className, &cls) != ANI_OK) { + LOG_ERROR("Class not found"); + return ANI_ERROR; + } + + std::array methods = { + ani_native_function {"create", nullptr, reinterpret_cast(Create) }, + ani_native_function {"equalTo", nullptr, reinterpret_cast(EqualTo)}, + ani_native_function {"notEqualTo", nullptr, reinterpret_cast(NotEqualTo)}, + ani_native_function {"orderByDesc", nullptr, reinterpret_cast(OrderByDesc)}, + ani_native_function {"orderByAsc", nullptr, reinterpret_cast(OrderByAsc)}, + ani_native_function {"and", nullptr, reinterpret_cast(And)}, + ani_native_function {"limit", nullptr, reinterpret_cast(Limit)}, + ani_native_function {"lessThan", nullptr, reinterpret_cast(LessThan)}, + ani_native_function {"like", nullptr, reinterpret_cast(Like)}, + ani_native_function {"endWrap", nullptr, reinterpret_cast(EndWrap)}, + ani_native_function {"greaterThanOrEqualTo", nullptr, reinterpret_cast(GreaterThanOrEqualTo)}, + ani_native_function {"contains", nullptr, reinterpret_cast(Contains)}, + ani_native_function {"or", nullptr, reinterpret_cast(Or)}, + ani_native_function {"beginWrap", nullptr, reinterpret_cast(BeginWrap)}, + ani_native_function {"greaterThan", nullptr, reinterpret_cast(GreaterThan)}, + ani_native_function {"groupBy", nullptr, reinterpret_cast(GroupBy)}, + ani_native_function {"in", nullptr, reinterpret_cast(In)}, + ani_native_function {"notIn", nullptr, reinterpret_cast(NotIn)}, + }; + + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + LOG_ERROR("Cannot bind native methods to %{public}s", className); + return ANI_ERROR; + }; + + static const char *cleanerName = "LCleaner;"; + auto cleanerCls = AniTypeFinder(env).FindClass(ns, cleanerName); + DataSharePredicatesCleaner(env).Bind(cleanerCls.value()); + + *result = ANI_VERSION_1; + return ANI_OK; +} diff --git a/data_share/frameworks/js/ani/dataShareResultSet/BUILD.gn b/data_share/frameworks/js/ani/dataShareResultSet/BUILD.gn new file mode 100644 index 00000000..e0ef7871 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShareResultSet/BUILD.gn @@ -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. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/distributeddatamgr/data_share/datashare.gni") + +ohos_shared_library("data_share_result_set") { + sanitize = { + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + sources = [ + "${datashare_ani_path}/common/src/ani_utils.cpp", + "./src/data_share_result_set.cpp" + ] + include_dirs = [ + "${datashare_ani_path}/common/include", + "${datashare_innerapi_path}/consumer/include", + "${datashare_innerapi_path}/provider/include", + "${datashare_common_native_path}/include", + ] + deps = [ "${datashare_innerapi_path}/common:datashare_common" ] + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "runtime_core:ani", + ] + subsystem_name = "distributeddatamgr" + part_name = "data_share" + output_extension = "so" +} + +generate_static_abc("data_share_result_set_abc") { + base_url = "./ets" + files = [ "./ets/@ohos.data.DataShareResultSet.ets" ] + dst_file = "$target_out_dir/data_share_result_set.abc" + out_puts = [ "$target_out_dir/data_share_result_set.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/data_share_result_set.abc" +} + +ohos_prebuilt_etc("data_share_result_set_abc_etc") { + source = "$target_out_dir/data_share_result_set.abc" + module_install_dir = "framework" + subsystem_name = "distributeddatamgr" + part_name = "data_share" + deps = [ ":data_share_result_set_abc" ] +} + +group("datashareresultset") { + deps = [ + ":data_share_result_set", + ":data_share_result_set_abc_etc", + ] +} diff --git a/data_share/frameworks/js/ani/dataShareResultSet/ets/@ohos.data.DataShareResultSet.ets b/data_share/frameworks/js/ani/dataShareResultSet/ets/@ohos.data.DataShareResultSet.ets new file mode 100644 index 00000000..5443da00 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShareResultSet/ets/@ohos.data.DataShareResultSet.ets @@ -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. + */ + + + +export default interface DataShareResultSet { + close(): void + getColumnIndex(columnName: string): number; + getString(columnIndex: number): string; + goToFirstRow(): boolean; + rowCount:number; +} + +class DataShareResultSetImpl implements DataShareResultSet { + + static {loadLibrary("data_share_result_set")} + private nativePtr: long = 0; + + private clearNativePtr(): void { + this.nativePtr = 0; + } + + constructor(nativePtr: long) { + this.nativePtr = nativePtr; + } + native close(): void; + native getColumnIndex(columnName: string): number; + native getString(columnIndex: number): string; + native goToFirstRow(): boolean; + native getRowCount(): number; + get rowCount(): number { + return this.getRowCount(); + } + + set rowCount(value: number) { + this.rowCount = value; + } +} diff --git a/data_share/frameworks/js/ani/dataShareResultSet/src/data_share_result_set.cpp b/data_share/frameworks/js/ani/dataShareResultSet/src/data_share_result_set.cpp new file mode 100644 index 00000000..ada79057 --- /dev/null +++ b/data_share/frameworks/js/ani/dataShareResultSet/src/data_share_result_set.cpp @@ -0,0 +1,171 @@ +/* + * 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 "datashare_errno.h" +#include "datashare_log.h" +#include "datashare_result_set.h" + +using namespace OHOS::DataShare; + +static std::shared_ptr GetResultSet(ani_env *env, ani_object obj) +{ + auto holder = AniObjectUtils::Unwrap>(env, obj); + if (holder == nullptr) { + LOG_ERROR("SharedPtrHolder is NULL"); + return nullptr; + } + if (holder->Get() == nullptr) { + LOG_ERROR("Holder shared_ptr is NULL"); + return nullptr; + } + + return holder->Get(); +} + +static void Close([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj) +{ + static const char *className = "L@ohos/data/DataShareResultSet/DataShareResultSetImpl;"; + auto classObj = GetResultSet(env, obj); + if (classObj == nullptr) { + LOG_ERROR("DataShareResultSet is NULL"); + return; + } + int errCode = classObj->Close(); + if (errCode != E_OK) { + LOG_ERROR("failed code:%{public}d", errCode); + } + ani_class cls; + if (ANI_OK != env->FindClass(className, &cls)) { + LOG_ERROR("[ANI] Not found class %{public}s", className); + return; + } + + ani_method setNaptr; + if (ANI_OK != env->Class_FindMethod(cls, "clearNativePtr", nullptr, &setNaptr)) { + LOG_ERROR("[ANI] Not found clearNativePtr for class %{public}s", className); + return; + } + + if (ANI_OK != env->Object_CallMethod_Void(obj, setNaptr)) { + LOG_ERROR("[ANI] Object_CallMethod_Void failed"); + return; + } + return; +} + +static ani_double GetColumnIndex([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_string columnName) +{ + int32_t columnIndex = -1; + if (columnName == nullptr) { + return static_cast(columnIndex); + } + auto columnNameStr = AniStringUtils::ToStd(env, columnName); + + auto classObj = GetResultSet(env, obj); + if (classObj == nullptr) { + LOG_ERROR("DataShareResultSet is NULL"); + return static_cast(columnIndex); + } + int errCode = classObj->GetColumnIndex(columnNameStr, columnIndex); + if (errCode != E_OK) { + auto time = static_cast(std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count()); + LOG_ERROR("failed code:%{public}d columnIndex: %{public}d. times %{public}" PRIu64 ".", errCode, columnIndex, + time); + } + return static_cast(columnIndex); +} + +static ani_string GetString([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj, ani_double columnIndex) +{ + std::string value; + double columnIndexD = static_cast(columnIndex); + auto classObj = GetResultSet(env, obj); + if (classObj == nullptr) { + LOG_ERROR("DataShareResultSet is NULL"); + return nullptr; + } + classObj->GetString(columnIndexD, value); + return AniStringUtils::ToAni(env, value); +} + +static bool GoToFirstRow([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj) +{ + auto classObj = GetResultSet(env, obj); + if (classObj == nullptr) { + LOG_ERROR("DataShareResultSet is NULL"); + return false; + } + + int errCode = classObj->GoToFirstRow(); + if (errCode != E_OK) { + LOG_ERROR("failed code:%{public}d", errCode); + return false; + } + return true; +} + +static ani_double GetRowCount([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj) +{ + int32_t count = -1; + auto classObj = GetResultSet(env, obj); + if (classObj == nullptr) { + LOG_ERROR("DataShareResultSet is NULL"); + return static_cast(count); + } + classObj->GetRowCount(count); + return static_cast(count); +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + LOG_INFO("enter ANI_Constructor func"); + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + LOG_ERROR("Unsupported ANI_VERSION_1"); + return ANI_ERROR; + } + + ani_class cls; + static const char *className = "L@ohos/data/DataShareResultSet/DataShareResultSetImpl;"; + if (ANI_OK != env->FindClass(className, &cls)) { + LOG_ERROR("Not found class:%{public}s", className); + return ANI_ERROR; + } + + std::array methods = { + ani_native_function {"close", nullptr, reinterpret_cast(Close)}, + ani_native_function {"getColumnIndex", nullptr, reinterpret_cast(GetColumnIndex)}, + ani_native_function {"getString", nullptr, reinterpret_cast(GetString)}, + ani_native_function {"goToFirstRow", nullptr, reinterpret_cast(GoToFirstRow)}, + ani_native_function {"getRowCount", nullptr, reinterpret_cast(GetRowCount)}, + }; + + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + LOG_ERROR("Cannot bind native methods to {%public}s", className); + return ANI_ERROR; + }; + + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/data_share/frameworks/js/napi/common/include/datashare_error.h b/data_share/frameworks/js/napi/common/include/datashare_error.h index 44855d27..cf537a37 100644 --- a/data_share/frameworks/js/napi/common/include/datashare_error.h +++ b/data_share/frameworks/js/napi/common/include/datashare_error.h @@ -29,6 +29,7 @@ public: static const int EXCEPTION_URI_NOT_EXIST = 15700011; static const int EXCEPTION_DATA_AREA_NOT_EXIST = 15700012; static const int EXCEPTION_HELPER_CLOSED = 15700013; + static const int EXCEPTION_PROXY_PARAMETER_CHECK = 15700014; virtual ~Error() {}; virtual std::string GetMessage() const = 0; virtual int GetCode() const = 0; diff --git a/data_share/frameworks/js/napi/common/include/datashare_error_impl.h b/data_share/frameworks/js/napi/common/include/datashare_error_impl.h index f98ba0fc..e948be3d 100644 --- a/data_share/frameworks/js/napi/common/include/datashare_error_impl.h +++ b/data_share/frameworks/js/napi/common/include/datashare_error_impl.h @@ -39,6 +39,13 @@ private: std::string wantNum; }; +class DataProxyHandleParamError : public Error { +public: + DataProxyHandleParamError() = default; + std::string GetMessage() const override; + int GetCode() const override; +}; + class DataShareHelperInitError : public Error { public: DataShareHelperInitError() = default; diff --git a/data_share/frameworks/js/napi/common/include/datashare_js_utils.h b/data_share/frameworks/js/napi/common/include/datashare_js_utils.h index 406c3ccf..2daab378 100644 --- a/data_share/frameworks/js/napi/common/include/datashare_js_utils.h +++ b/data_share/frameworks/js/napi/common/include/datashare_js_utils.h @@ -27,6 +27,7 @@ #include "datashare_template.h" #include "datashare_value_object.h" #include "napi/native_api.h" +#include "dataproxy_handle_common.h" #define NAPI_ASSERT_ERRCODE(env, assertion, error) \ do { \ @@ -85,6 +86,7 @@ public: static int32_t Convert2Value(napi_env env, napi_value input, DataShareValuesBucket &valueBucket); static int32_t Convert2Value(napi_env env, napi_value input, UpdateOperation &operation); static int32_t Convert2Value(napi_env env, napi_value input, DataShareObserver::ChangeInfo &changeInfo); + static int32_t Convert2Value(napi_env env, napi_value input, DataProxyType &proxyType); static std::string Convert2String(napi_env env, napi_value jsStr, size_t max = DEFAULT_BUF_SIZE); static std::vector Convert2StrVector(napi_env env, napi_value value, size_t strMax); static std::vector Convert2U8Vector(napi_env env, napi_value jsValue); @@ -94,6 +96,7 @@ public: static Template Convert2Template(napi_env env, napi_value value); static TemplateId Convert2TemplateId(napi_env env, napi_value value); static Data Convert2PublishedData(napi_env env, napi_value value); + static std::vector Convert2ProxyData(napi_env env, napi_value value); static napi_value Convert2JSValue(napi_env env, const std::monostate &value = {}); static napi_value Convert2JSValue(napi_env env, const std::vector &value); @@ -114,6 +117,12 @@ public: static napi_value Convert2JSValue(napi_env env, PublishedDataChangeNode &changeNode); static napi_value Convert2JSValue(napi_env env, const OperationResult &results); static napi_value Convert2JSValue(napi_env env, const std::vector &results); + static napi_value Convert2JSValue(napi_env env, const DataProxyResult &result); + static napi_value Convert2JSValue(napi_env env, const std::vector &results); + static napi_value Convert2JSValue(napi_env env, const DataProxyGetResult &result); + static napi_value Convert2JSValue(napi_env env, const std::vector &results); + static napi_value Convert2JSValue(napi_env env, const DataShareValueObject &valueObject); + static napi_value Convert2JSValue(napi_env env, const DataProxyChangeInfo &changeInfo); static napi_value Convert2JSValue(napi_env env, const DataShareValuesBucket &valueBucket); static std::vector ConvertU8Vector(napi_env env, napi_value jsValue); static napi_value Convert2JSValue(napi_env env, const DataShareObserver::ChangeInfo &changeInfo); @@ -128,6 +137,10 @@ public: std::vector &predicates); static bool UnwrapStringByPropertyName(napi_env env, napi_value jsObject, const char *propertyName, std::string &value); + static bool UnwrapDataProxyValue(napi_env env, napi_value jsObject, DataProxyValue &value, bool &isValueUndefined); + static bool UnwrapProxyDataItem(napi_env env, napi_value jsObject, DataShareProxyData &proxyData); + static bool UnwrapProxyDataItemVector(napi_env env, napi_value value, std::vector &proxyDatas); + static bool UnwrapDataProxyConfig(napi_env env, napi_value value, DataProxyConfig &config); static bool IsArrayForNapiValue(napi_env env, napi_value param, uint32_t &arraySize); private: template @@ -156,7 +169,7 @@ private: template napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const std::variant &value) { - return ReadVariant(env, 0, value.index(), value); + return ReadVariant(env, 0, static_cast(value.index()), value); } template diff --git a/data_share/frameworks/js/napi/common/include/napi_callbacks_manager.h b/data_share/frameworks/js/napi/common/include/napi_callbacks_manager.h index 1cf38af5..0b7190ac 100644 --- a/data_share/frameworks/js/napi/common/include/napi_callbacks_manager.h +++ b/data_share/frameworks/js/napi/common/include/napi_callbacks_manager.h @@ -21,6 +21,7 @@ #include "datashare_errno.h" #include "datashare_template.h" +#include "dataproxy_handle_common.h" namespace OHOS::DataShare { template @@ -31,11 +32,20 @@ public: std::function &, const std::shared_ptr &observer, std::vector &)>); + std::vector AddObservers(const std::vector &keys, const std::shared_ptr observer, + std::function &, const std::shared_ptr &observer, + std::vector &)>); + std::vector DelObservers(const std::vector &keys, const std::shared_ptr observer = nullptr, std::function &, const std::shared_ptr &observer, std::vector &)> processOnLastDel = NapiCallbacksManager::DefaultProcess); + std::vector DelObservers(const std::vector &keys, + const std::shared_ptr observer, + std::function &, const std::shared_ptr &observer, + std::vector &)> processOnLastDel); + std::vector> GetEnabledObservers(const Key &); int GetEnabledSubscriberSize(); @@ -93,6 +103,35 @@ std::vector NapiCallbacksManager::AddObservers( return result; } +template +std::vector NapiCallbacksManager::AddObservers( + const std::vector &keys, const std::shared_ptr observer, + std::function &, const std::shared_ptr &observer, + std::vector &)> processOnFirstAdd) +{ + std::vector result; + std::vector firstRegisterKey; + { + std::lock_guard lck(mutex_); + for (auto &key : keys) { + std::vector> enabledObservers = GetEnabledObservers(key); + if (enabledObservers.empty()) { + callbacks_[key].emplace_back(ObserverNode(observer)); + firstRegisterKey.emplace_back(key); + continue; + } + if (IsRegistered(*observer, callbacks_[key])) { + result.emplace_back(static_cast(key), SUCCESS); + continue; + } + callbacks_[key].emplace_back(observer); + result.emplace_back(key, SUCCESS); + } + } + processOnFirstAdd(firstRegisterKey, observer, result); + return result; +} + template bool NapiCallbacksManager::IsRegistered(const Observer &observer, const std::vector &observers) @@ -160,6 +199,61 @@ std::vector NapiCallbacksManager::DelObservers( return result; } +template +std::vector NapiCallbacksManager::DelObservers( + const std::vector &keys, const std::shared_ptr observer, + std::function &, const std::shared_ptr &, std::vector &)> + processOnLastDel) +{ + std::vector result; + std::vector lastDelKeys; + { + std::lock_guard lck(mutex_); + if (keys.empty() && observer == nullptr) { + for (auto &it : callbacks_) { + lastDelKeys.emplace_back(it.first); + } + callbacks_.clear(); + } + for (auto &key : keys) { + auto it = callbacks_.find(key); + if (it == callbacks_.end()) { + result.emplace_back(key, URI_NOT_EXIST); + continue; + } + if (observer == nullptr) { + callbacks_.erase(key); + lastDelKeys.emplace_back(key); + continue; + } + if (!IsRegistered(*observer, it->second)) { + result.emplace_back(key, URI_NOT_EXIST); + continue; + } + std::vector &callbacks = it->second; + auto callbackIt = callbacks.begin(); + while (callbackIt != callbacks.end()) { + if (!(*(callbackIt->observer_) == *observer)) { + callbackIt++; + continue; + } + callbackIt = callbacks.erase(callbackIt); + } + if (!it->second.empty()) { + result.emplace_back(key, SUCCESS); + continue; + } + callbacks_.erase(key); + lastDelKeys.emplace_back(key); + } + if (lastDelKeys.empty()) { + return result; + } + } + processOnLastDel(lastDelKeys, observer, result); + return result; +} + template std::vector> NapiCallbacksManager::GetEnabledObservers(const Key &inputKey) { diff --git a/data_share/frameworks/js/napi/common/src/datashare_error_impl.cpp b/data_share/frameworks/js/napi/common/src/datashare_error_impl.cpp index 93a46c73..913bf6b7 100644 --- a/data_share/frameworks/js/napi/common/src/datashare_error_impl.cpp +++ b/data_share/frameworks/js/napi/common/src/datashare_error_impl.cpp @@ -14,6 +14,7 @@ */ #include "datashare_error_impl.h" +#include namespace OHOS { namespace DataShare { @@ -37,6 +38,17 @@ int ParametersNumError::GetCode() const return EXCEPTION_PARAMETER_CHECK; } +std::string DataProxyHandleParamError::GetMessage() const +{ + return "Parameter error. Possible causes: 1.The size of parameter is over limit; " + "2.The length of array is over limit; 3.The format of uri is incorrect."; +} + +int DataProxyHandleParamError::GetCode() const +{ + return EXCEPTION_PROXY_PARAMETER_CHECK; +} + std::string DataShareHelperInitError::GetMessage() const { return "The DataShareHelper is not initialized successfully."; @@ -49,7 +61,8 @@ int DataShareHelperInitError::GetCode() const std::string InnerError::GetMessage() const { - return "Inner error."; + return "Inner error. Possible causes: 1.The internal status is abnormal; 2.The interface is incorrectly used; " + "3.Permission configuration error; 4.A system error."; } int InnerError::GetCode() const diff --git a/data_share/frameworks/js/napi/common/src/datashare_js_utils.cpp b/data_share/frameworks/js/napi/common/src/datashare_js_utils.cpp index 3b0471bf..8dbaf805 100644 --- a/data_share/frameworks/js/napi/common/src/datashare_js_utils.cpp +++ b/data_share/frameworks/js/napi/common/src/datashare_js_utils.cpp @@ -14,10 +14,15 @@ */ #include "datashare_js_utils.h" +#include +#include "dataproxy_handle_common.h" #include "datashare_log.h" #include "datashare_predicates_proxy.h" +#include "datashare_string_utils.h" #include "datashare_valuebucket_convert.h" +#include "js_native_api.h" +#include "js_native_api_types.h" #include "napi/native_common.h" #include "napi_datashare_values_bucket.h" #include "securec.h" @@ -67,7 +72,6 @@ std::vector DataShareJSUtils::Convert2U8Vector(napi_env env, napi_value if (!isTypedArray) { napi_is_arraybuffer(env, input_array, &isArrayBuffer); if (!isArrayBuffer) { - LOG_ERROR("unknow type"); return {}; } } @@ -303,6 +307,39 @@ std::string DataShareJSUtils::UnwrapStringFromJS(napi_env env, napi_value param, return value; } +napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const DataShareValueObject &valueObject) +{ + napi_value jsValue = nullptr; + switch (valueObject.value.index()) { + case DataShareValueObjectType::TYPE_INT: { + int64_t val = std::get(valueObject.value); + jsValue = Convert2JSValue(env, val); + break; + } + case DataShareValueObjectType::TYPE_DOUBLE: { + double val = std::get(valueObject.value); + jsValue = Convert2JSValue(env, val); + break; + } + case DataShareValueObjectType::TYPE_STRING: { + std::string val = std::get(valueObject.value); + jsValue = Convert2JSValue(env, val); + break; + } + case DataShareValueObjectType::TYPE_BOOL: { + bool val = std::get(valueObject.value); + jsValue = Convert2JSValue(env, val); + break; + } + default: { + LOG_ERROR("Marshal ValueObject: unknown typeId"); + return nullptr; + } + } + + return jsValue; +} + napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const DataShareValuesBucket &valueBucket) { napi_value res = NewInstance(env, valueBucket); @@ -498,6 +535,117 @@ napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const std::vector &results) +{ + napi_value jsValue; + napi_status status = napi_create_array_with_length(env, results.size(), &jsValue); + if (status != napi_ok) { + return nullptr; + } + + for (size_t i = 0; i < results.size(); ++i) { + napi_set_element(env, jsValue, i, Convert2JSValue(env, results[i])); + } + return jsValue; +} + +napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const DataProxyGetResult &result) +{ + napi_value jsDataProxyGetResult = nullptr; + napi_create_object(env, &jsDataProxyGetResult); + + napi_value uri = Convert2JSValue(env, result.uri_); + if (uri == nullptr) { + return nullptr; + } + + napi_value errCode = Convert2JSValue(env, result.result_); + if (errCode == nullptr) { + return nullptr; + } + + // when failed to get proxyData, value and allowList in getResult is undefined + napi_value value = nullptr; + if (result.result_ == SUCCESS) { + value = Convert2JSValue(env, result.value_); + if (value == nullptr) { + return nullptr; + } + } + + napi_value allowList = nullptr; + if (result.result_ == SUCCESS) { + allowList = Convert2JSValue(env, result.allowList_); + if (allowList == nullptr) { + return nullptr; + } + } + + napi_set_named_property(env, jsDataProxyGetResult, "uri", uri); + napi_set_named_property(env, jsDataProxyGetResult, "result", errCode); + napi_set_named_property(env, jsDataProxyGetResult, "value", value); + napi_set_named_property(env, jsDataProxyGetResult, "allowList", allowList); + return jsDataProxyGetResult; +} + +napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const std::vector &results) +{ + napi_value jsValue; + napi_status status = napi_create_array_with_length(env, results.size(), &jsValue); + if (status != napi_ok) { + return nullptr; + } + + for (size_t i = 0; i < results.size(); ++i) { + napi_set_element(env, jsValue, i, Convert2JSValue(env, results[i])); + } + return jsValue; +} + +napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const DataProxyChangeInfo &changeInfo) +{ + napi_value jsDataProxyChangeInfo = nullptr; + napi_create_object(env, &jsDataProxyChangeInfo); + + napi_value type = nullptr; + type = Convert2JSValue(env, changeInfo.changeType_); + if (type == nullptr) { + return nullptr; + } + napi_value uri = nullptr; + uri = Convert2JSValue(env, changeInfo.uri_); + if (uri == nullptr) { + return nullptr; + } + napi_value value = Convert2JSValue(env, changeInfo.value_); + if (value == nullptr) { + return nullptr; + } + napi_set_named_property(env, jsDataProxyChangeInfo, "type", type); + napi_set_named_property(env, jsDataProxyChangeInfo, "uri", uri); + napi_set_named_property(env, jsDataProxyChangeInfo, "value", value); + return jsDataProxyChangeInfo; +} + bool DataShareJSUtils::UnwrapTemplatePredicates(napi_env env, napi_value jsPredicates, std::vector &predicates) { @@ -666,6 +814,171 @@ bool DataShareJSUtils::UnwrapPublishedDataItemVector(napi_env env, napi_value va return true; } +bool DataShareJSUtils::UnwrapDataProxyValue(napi_env env, napi_value jsObject, + DataProxyValue &value, bool &isValueUndefined) +{ + napi_valuetype valueType = napi_undefined; + napi_typeof(env, jsObject, &valueType); + if (valueType != napi_object) { + LOG_ERROR("UnwrapDataProxyValue error, value is not object"); + return false; + } + + std::string keyStr = "value"; + napi_value jsDataKey = Convert2JSValue(env, keyStr); + napi_value jsDataValue = nullptr; + napi_get_property(env, jsObject, jsDataKey, &jsDataValue); + napi_typeof(env, jsDataValue, &valueType); + switch (valueType) { + case napi_number: { + double valueNumber; + napi_get_value_double(env, jsDataValue, &valueNumber); + value = valueNumber; + break; + } + case napi_string: { + value = Convert2String(env, jsDataValue); + break; + } + case napi_boolean: { + bool valueBool; + napi_get_value_bool(env, jsDataValue, &valueBool); + value = valueBool; + break; + } + case napi_undefined: { + value = ""; + isValueUndefined = true; + break; + } + case napi_null: { + value = ""; + isValueUndefined = true; + break; + } + default: { + LOG_ERROR("Convert dataValue failed, type is %{public}d", valueType); + return false; + } + } + return true; +} + +bool DataShareJSUtils::UnwrapProxyDataItem(napi_env env, napi_value jsObject, DataShareProxyData &proxyData) +{ + napi_valuetype valueType = napi_undefined; + napi_typeof(env, jsObject, &valueType); + if (valueType != napi_object) { + LOG_ERROR("UnwrapPublishedDataItem error, value is not object"); + return false; + } + + if (!UnwrapStringByPropertyName(env, jsObject, "uri", proxyData.uri_)) { + LOG_ERROR("Convert uri failed"); + return false; + } + + bool isValueUndefined = false; + if (!UnwrapDataProxyValue(env, jsObject, proxyData.value_, isValueUndefined)) { + LOG_ERROR("Convert dataproxy value failed"); + return false; + } + proxyData.isValueUndefined = isValueUndefined; + + std::string keyStr = "allowList"; + napi_value jsDataKey = Convert2JSValue(env, keyStr); + napi_value jsDataValue = nullptr; + napi_get_property(env, jsObject, jsDataKey, &jsDataValue); + napi_typeof(env, jsDataValue, &valueType); + if (valueType != napi_object) { + if (valueType == napi_undefined || valueType == napi_null) { + proxyData.isAllowListUndefined = true; + } else { + LOG_ERROR("Convert allowList failed"); + return false; + } + } + Convert2Value(env, jsDataValue, proxyData.allowList_); + auto it = proxyData.allowList_.begin(); + while (it != proxyData.allowList_.end()) { + if (it->size() > APPIDENTIFIER_MAX_SIZE) { + LOG_WARN("appIdentifier is over limit"); + it = proxyData.allowList_.erase(it); + } else { + it++; + } + } + if (proxyData.allowList_.size() > ALLOW_LIST_MAX_COUNT) { + LOG_WARN("ProxyData's allowList is over limit, uri: %{public}s", + DataShareStringUtils::Anonymous(proxyData.uri_).c_str()); + proxyData.allowList_.resize(ALLOW_LIST_MAX_COUNT); + } + return true; +} + +bool DataShareJSUtils::UnwrapProxyDataItemVector(napi_env env, napi_value value, + std::vector &proxyDatas) +{ + uint32_t arraySize = 0; + if (!IsArrayForNapiValue(env, value, arraySize)) { + LOG_ERROR("IsArrayForNapiValue is false"); + return false; + } + + for (uint32_t i = 0; i < arraySize; i++) { + napi_value jsValue = nullptr; + if (napi_get_element(env, value, i, &jsValue) != napi_ok) { + LOG_ERROR("napi_get_element is false"); + return false; + } + + DataShareProxyData proxyDataItem; + if (!UnwrapProxyDataItem(env, jsValue, proxyDataItem)) { + LOG_ERROR("UnwrapPublishedDataItem failed"); + return false; + } + proxyDatas.emplace_back(std::move(proxyDataItem)); + } + return true; +} + +std::vector DataShareJSUtils::Convert2ProxyData(napi_env env, napi_value value) +{ + napi_valuetype valueType = napi_undefined; + napi_typeof(env, value, &valueType); + if (valueType != napi_object) { + LOG_ERROR("Convert2PublishedData error, value is not object"); + return {}; + } + std::vector proxyDatas; + if (!UnwrapProxyDataItemVector(env, value, proxyDatas)) { + LOG_ERROR("UnwrapPublishedDataItems failed"); + return {}; + } + return proxyDatas; +} + +bool DataShareJSUtils::UnwrapDataProxyConfig(napi_env env, napi_value value, DataProxyConfig &config) +{ + napi_value jsResult = nullptr; + napi_status status = napi_get_named_property(env, value, "type", &jsResult); + if ((status != napi_ok) || (jsResult == nullptr)) { + LOG_ERROR("Convert DataProxyType failed"); + return false; + } + napi_valuetype valueType = napi_undefined; + napi_typeof(env, jsResult, &valueType); + if (valueType != napi_number) { + LOG_ERROR("Convert DataProxyType error, value is not number"); + return false; + } + if (Convert2Value(env, jsResult, config.type_) != napi_ok) { + LOG_ERROR("Convert DataProxyType failed"); + return false; + } + return true; +} + Data DataShareJSUtils::Convert2PublishedData(napi_env env, napi_value value) { napi_valuetype valueType = napi_undefined; @@ -799,6 +1112,14 @@ int32_t DataShareJSUtils::Convert2Value(napi_env env, napi_value input, DataShar return napi_ok; } +int32_t DataShareJSUtils::Convert2Value(napi_env env, napi_value input, DataProxyType &proxyType) +{ + uint32_t number = 0; + napi_status status = napi_get_value_uint32(env, input, &number); + proxyType = static_cast(number); + return status; +} + napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const DataShareObserver::ChangeInfo &changeInfo) { napi_value napiValue = nullptr; diff --git a/data_share/frameworks/js/napi/common/src/datashare_predicates_proxy.cpp b/data_share/frameworks/js/napi/common/src/datashare_predicates_proxy.cpp index e748ff4f..0373e926 100644 --- a/data_share/frameworks/js/napi/common/src/datashare_predicates_proxy.cpp +++ b/data_share/frameworks/js/napi/common/src/datashare_predicates_proxy.cpp @@ -15,8 +15,8 @@ #include "datashare_predicates_proxy.h" -#include #include +#include #include "datashare_log.h" #include "datashare_js_utils.h" @@ -218,6 +218,9 @@ napi_value DataSharePredicatesProxy::EqualTo(napi_env env, napi_callback_info in napi_get_cb_info(env, info, &argc, args, &thiz, nullptr); NAPI_ASSERT(env, argc > 1, "Invalid argvs!"); std::string field = DataShareJSUtils::Convert2String(env, args[0], DataShareJSUtils::DEFAULT_BUF_SIZE); + if (field.empty()) { + LOG_WARN("The field is empty."); + } napi_valuetype valueType = napi_undefined; napi_status status = napi_typeof(env, args[1], &valueType); if (status != napi_ok) { @@ -248,6 +251,7 @@ napi_value DataSharePredicatesProxy::EqualTo(napi_env env, napi_callback_info in break; } default: + LOG_ERROR("Invalid argument! Wrong argument Type"); break; } return thiz; @@ -687,6 +691,9 @@ napi_value DataSharePredicatesProxy::OrderByAsc(napi_env env, napi_callback_info napi_get_cb_info(env, info, &argc, args, &thiz, nullptr); NAPI_ASSERT(env, argc > 0, "Invalid argvs!"); std::string field = DataShareJSUtils::Convert2String(env, args[0], DataShareJSUtils::DEFAULT_BUF_SIZE); + if (field.empty()) { + LOG_WARN("The field is empty."); + } auto nativePredicates = GetNativePredicates(env, info); if (nativePredicates == nullptr) { LOG_ERROR("GetNativePredicates failed."); @@ -704,6 +711,9 @@ napi_value DataSharePredicatesProxy::OrderByDesc(napi_env env, napi_callback_inf napi_get_cb_info(env, info, &argc, args, &thiz, nullptr); NAPI_ASSERT(env, argc > 0, "Invalid argvs!"); std::string field = DataShareJSUtils::Convert2String(env, args[0], DataShareJSUtils::DEFAULT_BUF_SIZE); + if (field.empty()) { + LOG_WARN("The field is empty."); + } auto nativePredicates = GetNativePredicates(env, info); if (nativePredicates == nullptr) { LOG_ERROR("GetNativePredicates failed."); @@ -789,6 +799,9 @@ napi_value DataSharePredicatesProxy::In(napi_env env, napi_callback_info info) napi_get_cb_info(env, info, &argc, args, &thiz, nullptr); NAPI_ASSERT(env, argc > 1, "Invalid argvs!"); std::string field = DataShareJSUtils::Convert2String(env, args[0], DataShareJSUtils::DEFAULT_BUF_SIZE); + if (field.empty()) { + LOG_WARN("The field is empty."); + } std::vector values = DataShareJSUtils::Convert2StrVector(env, args[1], DataShareJSUtils::DEFAULT_BUF_SIZE); auto nativePredicates = GetNativePredicates(env, info); diff --git a/data_share/frameworks/js/napi/common/src/datashare_result_set_proxy.cpp b/data_share/frameworks/js/napi/common/src/datashare_result_set_proxy.cpp index 14e53a8f..e762fc78 100644 --- a/data_share/frameworks/js/napi/common/src/datashare_result_set_proxy.cpp +++ b/data_share/frameworks/js/napi/common/src/datashare_result_set_proxy.cpp @@ -398,10 +398,8 @@ napi_value DataShareResultSetProxy::GetColumnIndex(napi_env env, napi_callback_i if (innerResultSet != nullptr) { int errCode = innerResultSet->GetColumnIndex(columnName, columnIndex); if (errCode != E_OK) { - auto time = static_cast(duration_cast( - system_clock::now().time_since_epoch()).count()); - LOG_ERROR("failed code:%{public}d columnIndex: %{public}d. times %{public}" PRIu64 ".", - errCode, columnIndex, time); + LOG_ERROR("code:%{public}d idx: %{public}d.", + errCode, columnIndex); } } else { LOG_ERROR("GetInnerResultSet failed."); diff --git a/data_share/frameworks/js/napi/dataShare/BUILD.gn b/data_share/frameworks/js/napi/dataShare/BUILD.gn index 6a2e9ef4..c7f7d6ed 100644 --- a/data_share/frameworks/js/napi/dataShare/BUILD.gn +++ b/data_share/frameworks/js/napi/dataShare/BUILD.gn @@ -32,6 +32,7 @@ ohos_shared_library("datashare_jscommon") { "${datashare_common_napi_path}/src/datashare_js_utils.cpp", "${datashare_common_napi_path}/src/datashare_predicates_proxy.cpp", "${datashare_common_napi_path}/src/napi_datashare_values_bucket.cpp", + "${datashare_common_native_path}/src/datashare_string_utils.cpp", ] deps = [ "${datashare_innerapi_path}/common:datashare_common" ] @@ -74,9 +75,11 @@ ohos_shared_library("datashare") { sources = [ "${datashare_common_napi_path}/src/datashare_error_impl.cpp", "${datashare_common_napi_path}/src/datashare_result_set_proxy.cpp", + "${datashare_common_native_path}/src/datashare_string_utils.cpp", "${datashare_napi_path}/dataShare/src/async_call.cpp", "${datashare_napi_path}/dataShare/src/napi_datashare_const_properties.cpp", "${datashare_napi_path}/dataShare/src/napi_datashare_helper.cpp", + "${datashare_napi_path}/dataShare/src/napi_dataproxy_handle.cpp", "${datashare_napi_path}/dataShare/src/napi_datashare_inner_observer.cpp", "${datashare_napi_path}/dataShare/src/napi_datashare_observer.cpp", "${datashare_napi_path}/dataShare/src/native_datashare_module.cpp", diff --git a/data_share/frameworks/js/napi/dataShare/include/napi_dataproxy_handle.h b/data_share/frameworks/js/napi/dataShare/include/napi_dataproxy_handle.h new file mode 100644 index 00000000..1bdc423e --- /dev/null +++ b/data_share/frameworks/js/napi/dataShare/include/napi_dataproxy_handle.h @@ -0,0 +1,109 @@ +/* + * 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 NAPI_DATAPROXY_HANDLE_H +#define NAPI_DATAPROXY_HANDLE_H + +#include "async_call.h" +#include "dataproxy_handle.h" +#include "data_share_common.h" +#include "hap_module_info.h" +#include "dataproxy_handle_common.h" +#include "napi_datashare_observer.h" +#include "napi_subscriber_manager.h" + +namespace OHOS { +namespace DataShare { +class NapiDataProxyHandle { +public: + static napi_value Napi_CreateDataProxyHandle(napi_env env, napi_callback_info info); + static napi_value Napi_Publish(napi_env env, napi_callback_info info); + static napi_value Napi_Delete(napi_env env, napi_callback_info info); + static napi_value Napi_Get(napi_env env, napi_callback_info info); + static napi_value Napi_On(napi_env env, napi_callback_info info); + static napi_value Napi_Off(napi_env env, napi_callback_info info); +private: + static napi_value GetConstructor(napi_env env); + static napi_value Initialize(napi_env env, napi_callback_info info); + static napi_value Napi_SubscribeProxyData(napi_env env, size_t argc, napi_value *argv, napi_value self); + static napi_value Napi_UnSubscribeProxyData(napi_env env, size_t argc, napi_value *argv, napi_value self); + std::vector SubscribeProxyData(napi_env env, const std::vector &uris, + napi_value callback, std::shared_ptr handle); + std::vector UnsubscribeProxyData(napi_env env, const std::vector &uris, + napi_value callback, std::shared_ptr handle); + void SetHandle(std::shared_ptr dataProxyHandle); + std::shared_ptr GetHandle(); + static bool CheckIsParameterExceed(const std::vector &proxyDatas); + static bool CheckIsParameterExceed(const std::vector &uris); + std::shared_ptr dataProxyHandle_ = nullptr; + std::shared_mutex mutex_; + std::shared_ptr jsProxyDataObsManager_ = nullptr; + + struct HandleContextInfo : public AsyncCall::Context { + napi_env env = nullptr; + napi_ref ref = nullptr; + bool isStageMode = true; + std::string strUri; + std::shared_ptr dataProxyHandle = nullptr; + + HandleContextInfo() : Context(nullptr, nullptr) {}; + HandleContextInfo(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; + ~HandleContextInfo() + { + if (env != nullptr && ref != nullptr) { + napi_delete_reference(env, ref); + } + } + }; + + struct ContextInfo : public AsyncCall::Context { + NapiDataProxyHandle *proxy = nullptr; + napi_status status = napi_generic_failure; + + DatashareBusinessError businessError; + std::vector proxyDatas; + DataProxyConfig config; + std::string bundleName; + std::vector uris; + std::vector proxyResult; + std::vector proxyGetResult; + int32_t resultNumber = 0; + + ContextInfo() : Context(nullptr, nullptr) + { + config.type_ = DataProxyType::SHARED_CONFIG; + }; + ContextInfo(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; + virtual ~ContextInfo() {}; + + napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override + { + NAPI_ASSERT_BASE(env, self != nullptr, "self is nullptr", napi_invalid_arg); + NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast(&proxy)), napi_invalid_arg); + NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no native upload task", napi_invalid_arg); + return Context::operator()(env, argc, argv, self); + } + napi_status operator()(napi_env env, napi_value *result) override + { + if (status != napi_ok) { + return status; + } + return Context::operator()(env, result); + } + }; +}; +} // namespace DataShare +} // namespace OHOS +#endif /* NAPI_DATAPROXY_HANDLE_H */ \ No newline at end of file diff --git a/data_share/frameworks/js/napi/dataShare/include/napi_datashare_helper.h b/data_share/frameworks/js/napi/dataShare/include/napi_datashare_helper.h index 8ab5c249..e4f01728 100644 --- a/data_share/frameworks/js/napi/dataShare/include/napi_datashare_helper.h +++ b/data_share/frameworks/js/napi/dataShare/include/napi_datashare_helper.h @@ -142,6 +142,8 @@ private: static void Notify(const std::shared_ptr context, std::shared_ptr helper); static void ExecuteCreator(std::shared_ptr ctxInfo); + static napi_status ValidateCreateParam(napi_env env, size_t argc, napi_value *argv, + std::shared_ptr ctxInfo); }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/js/napi/dataShare/include/napi_datashare_inner_observer.h b/data_share/frameworks/js/napi/dataShare/include/napi_datashare_inner_observer.h index 1f8abe2c..c5f0d6ff 100644 --- a/data_share/frameworks/js/napi/dataShare/include/napi_datashare_inner_observer.h +++ b/data_share/frameworks/js/napi/dataShare/include/napi_datashare_inner_observer.h @@ -28,8 +28,10 @@ namespace DataShare { class NAPIInnerObserver : public std::enable_shared_from_this { public: NAPIInnerObserver(napi_env env, napi_value callback); + ~NAPIInnerObserver(); void OnChange(const DataShareObserver::ChangeInfo &changeInfo = {}, bool isNotifyDetails = false); void DeleteReference(); + void RegisterEnvCleanHook(); napi_ref GetCallback(); protected: @@ -40,10 +42,18 @@ protected: ObserverWorker(std::shared_ptr observerIn, DataShareObserver::ChangeInfo resultIn = {}) : observer_(observerIn), result_(resultIn) {} }; + + struct ObserverEnvHookWorker { + std::weak_ptr observer_; + ObserverEnvHookWorker(std::shared_ptr observerIn): observer_(observerIn) {} + }; static void OnComplete(ObserverWorker* observerWorker); + static void CleanEnv(void *obj); napi_env env_ = nullptr; napi_ref ref_ = nullptr; uv_loop_s *loop_ = nullptr; + std::mutex envMutex_{}; + ObserverEnvHookWorker* observerEnvHookWorker_ = nullptr;; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/js/napi/dataShare/src/napi_dataproxy_handle.cpp b/data_share/frameworks/js/napi/dataShare/src/napi_dataproxy_handle.cpp new file mode 100644 index 00000000..dac70e65 --- /dev/null +++ b/data_share/frameworks/js/napi/dataShare/src/napi_dataproxy_handle.cpp @@ -0,0 +1,429 @@ +/* + * 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_dataproxy_handle.h" +#include "dataproxy_handle_common.h" +#include "datashare_error_impl.h" +#include "datashare_js_utils.h" +#include "datashare_log.h" +#include "datashare_string_utils.h" +#include "js_native_api_types.h" + +namespace OHOS { +namespace DataShare { +static thread_local napi_ref constructor_ = nullptr; +static constexpr int MAX_ARGC = 4; +using DataProxyHandle = OHOS::DataShare::DataProxyHandle; +napi_value NapiDataProxyHandle::GetConstructor(napi_env env) +{ + napi_value cons = nullptr; + if (constructor_ != nullptr) { + napi_status status = napi_get_reference_value(env, constructor_, &cons); + if (status != napi_ok) { + LOG_ERROR("napi get reference value failed. napi_status: %{public}d", status); + } + return cons; + } + napi_property_descriptor clzDes[] = { + DECLARE_NAPI_FUNCTION("publish", Napi_Publish), + DECLARE_NAPI_FUNCTION("delete", Napi_Delete), + DECLARE_NAPI_FUNCTION("get", Napi_Get), + DECLARE_NAPI_FUNCTION("on", Napi_On), + DECLARE_NAPI_FUNCTION("off", Napi_Off), + }; + NAPI_CALL(env, napi_define_class(env, "DataProxyHandle", NAPI_AUTO_LENGTH, Initialize, nullptr, + sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons)); + napi_status status = napi_create_reference(env, cons, 1, &constructor_); + if (status != napi_ok) { + LOG_ERROR("napi create reference failed. napi_status: %{public}d", status); + } + return cons; +} + +napi_value NapiDataProxyHandle::Initialize(napi_env env, napi_callback_info info) +{ + LOG_INFO("Start"); + napi_value self = nullptr; + size_t argc = ARGS_MAX_COUNT; + napi_value argv[ARGS_MAX_COUNT] = {nullptr}; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); + + auto *proxy = new (std::nothrow) NapiDataProxyHandle(); + if (proxy == nullptr) { + return nullptr; + } + auto finalize = [](napi_env env, void *data, void *hint) { + NapiDataProxyHandle *proxy = reinterpret_cast(data); + delete proxy; + }; + if (napi_wrap(env, self, proxy, finalize, nullptr, nullptr) != napi_ok) { + finalize(env, proxy, nullptr); + return nullptr; + } + return self; +} + +napi_value NapiDataProxyHandle::Napi_CreateDataProxyHandle(napi_env env, napi_callback_info info) +{ + auto ctxInfo = std::make_shared(); + auto input = [ctxInfo](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + napi_value handleProxy = nullptr; + napi_status status = napi_new_instance(env, GetConstructor(env), argc, argv, &handleProxy); + if (status != napi_ok) { + LOG_ERROR("napi new instance failed. napi_status: %{public}d", status); + } + NAPI_ASSERT_CALL_ERRCODE(env, handleProxy != nullptr && status == napi_ok, + ctxInfo->error = std::make_shared(), napi_generic_failure); + napi_create_reference(env, handleProxy, 1, &(ctxInfo->ref)); + ctxInfo->env = env; + return napi_ok; + }; + auto output = [ctxInfo](napi_env env, napi_value *result) -> napi_status { + NAPI_ASSERT_CALL_ERRCODE(env, ctxInfo->dataProxyHandle != nullptr, + ctxInfo->error = std::make_shared(), napi_generic_failure); + napi_status status = napi_get_reference_value(env, ctxInfo->ref, result); + NAPI_ASSERT_CALL_ERRCODE(env, result != nullptr, + ctxInfo->error = std::make_shared(), napi_generic_failure); + NapiDataProxyHandle *proxy = nullptr; + status = napi_unwrap(env, *result, reinterpret_cast(&proxy)); + NAPI_ASSERT_CALL_ERRCODE(env, proxy != nullptr, ctxInfo->error = std::make_shared(), + status); + proxy->jsProxyDataObsManager_ = std::make_shared(ctxInfo->dataProxyHandle); + proxy->SetHandle(std::move(ctxInfo->dataProxyHandle)); + return status; + }; + auto exec = [ctxInfo](AsyncCall::Context *ctx) { + auto ret = DataProxyHandle::Create(); + ctxInfo->dataProxyHandle = ret.second; + }; + ctxInfo->SetAction(std::move(input), std::move(output)); + AsyncCall asyncCall(env, info, ctxInfo); + return asyncCall.Call(env, exec); +} + +bool NapiDataProxyHandle::CheckIsParameterExceed(const std::vector &proxyDatas) +{ + if (proxyDatas.size() > PROXY_DATA_MAX_COUNT || proxyDatas.empty()) { + return false; + } + for (const auto &data : proxyDatas) { + // value's limit is 4096 bytes + if (data.value_.index() == DataProxyValueType::VALUE_STRING) { + std::string valStr = std::get(data.value_); + if (valStr.size() > VALUE_MAX_SIZE) { + LOG_ERROR("ProxyData's value is over limit, uri: %{public}s", + DataShareStringUtils::Anonymous(data.uri_).c_str()); + return false; + } + } + if (data.uri_.size() > URI_MAX_SIZE) { + LOG_ERROR("the size of uri %{public}s is over limit", DataShareStringUtils::Anonymous(data.uri_).c_str()); + return false; + } + } + return true; +} + +bool NapiDataProxyHandle::CheckIsParameterExceed(const std::vector &uris) +{ + for (const auto &uri : uris) { + if (uri.size() > URI_MAX_SIZE) { + LOG_ERROR("the size of uri %{public}s is over limit", DataShareStringUtils::Anonymous(uri).c_str()); + return false; + } + } + return true; +} + +napi_value NapiDataProxyHandle::Napi_Publish(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + if (argc != 2) { + context->error = std::make_shared("2"); + return napi_invalid_arg; + } + napi_valuetype valueType; + NAPI_CALL_BASE(env, napi_typeof(env, argv[0], &valueType), napi_invalid_arg); + + NAPI_ASSERT_CALL_ERRCODE(env, valueType == napi_object, + context->error = std::make_shared("proxyData", "Array"), napi_invalid_arg); + context->proxyDatas = DataShareJSUtils::Convert2ProxyData(env, argv[0]); + NAPI_ASSERT_CALL_ERRCODE(env, CheckIsParameterExceed(context->proxyDatas), context->error = + std::make_shared(), napi_invalid_arg); + NAPI_CALL_BASE(env, napi_typeof(env, argv[1], &valueType), napi_invalid_arg); + NAPI_ASSERT_CALL_ERRCODE(env, valueType == napi_object, + context->error = std::make_shared("config", "DataProxyConfig"), napi_invalid_arg); + DataShareJSUtils::UnwrapDataProxyConfig(env, argv[1], context->config); + return napi_ok; + }; + auto output = [context](napi_env env, napi_value *result) -> napi_status { + NAPI_ASSERT_BASE(env, context->status == napi_ok, "exec failed", napi_generic_failure); + *result = DataShareJSUtils::Convert2JSValue(env, context->proxyResult); + context->proxyResult.clear(); + return napi_ok; + }; + auto exec = [context](AsyncCall::Context *ctx) { + auto handle = context->proxy->GetHandle(); + NAPI_ASSERT_CALL_ERRCODE(env, handle != nullptr, + context->error = std::make_shared(), napi_generic_failure); + + context->proxyResult = handle->PublishProxyData(context->proxyDatas, context->config); + context->status = napi_ok; + return napi_ok; + }; + context->SetAction(std::move(input), std::move(output)); + AsyncCall asyncCall(env, info, context); + return asyncCall.Call(env, exec); +} + +napi_value NapiDataProxyHandle::Napi_Delete(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + if (argc != 2) { + context->error = std::make_shared("2"); + return napi_invalid_arg; + } + + napi_valuetype valueType; + NAPI_CALL_BASE(env, napi_typeof(env, argv[0], &valueType), napi_invalid_arg); + NAPI_ASSERT_CALL_ERRCODE(env, valueType == napi_object, + context->error = std::make_shared("uris", "Array"), napi_invalid_arg); + context->uris = + DataShareJSUtils::Convert2StrVector(env, argv[0], DataShareJSUtils::DEFAULT_BUF_SIZE); + NAPI_ASSERT_CALL_ERRCODE(env, !(context->uris.empty()), + context->error = std::make_shared("uris", "not empty"), napi_invalid_arg); + NAPI_ASSERT_CALL_ERRCODE(env, context->uris.size() <= URI_MAX_COUNT && + CheckIsParameterExceed(context->uris), context->error = + std::make_shared(), napi_invalid_arg); + NAPI_CALL_BASE(env, napi_typeof(env, argv[1], &valueType), napi_invalid_arg); + NAPI_ASSERT_CALL_ERRCODE(env, valueType == napi_object, + context->error = std::make_shared("config", "DataProxyConfig"), napi_invalid_arg); + if (!DataShareJSUtils::UnwrapDataProxyConfig(env, argv[1], context->config)) { + context->error = std::make_shared("config", "DataProxyConfig"); + return napi_invalid_arg; + } + return napi_ok; + }; + auto output = [context](napi_env env, napi_value *result) -> napi_status { + NAPI_ASSERT_BASE(env, context->status == napi_ok, "exec failed", napi_generic_failure); + *result = DataShareJSUtils::Convert2JSValue(env, context->proxyResult); + context->proxyResult.clear(); + return napi_ok; + }; + auto exec = [context](AsyncCall::Context *ctx) { + auto handle = context->proxy->GetHandle(); + NAPI_ASSERT_CALL_ERRCODE(env, handle != nullptr, + context->error = std::make_shared(), napi_generic_failure); + + context->proxyResult = handle->DeleteProxyData(context->uris, context->config); + context->status = napi_ok; + return napi_ok; + }; + context->SetAction(std::move(input), std::move(output)); + AsyncCall asyncCall(env, info, context); + return asyncCall.Call(env, exec); +} + +napi_value NapiDataProxyHandle::Napi_Get(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + if (argc != 2) { + context->error = std::make_shared("2"); + return napi_invalid_arg; + } + + napi_valuetype valueType; + NAPI_CALL_BASE(env, napi_typeof(env, argv[0], &valueType), napi_invalid_arg); + NAPI_ASSERT_CALL_ERRCODE(env, valueType == napi_object, + context->error = std::make_shared("uris", "Array"), napi_invalid_arg); + context->uris = + DataShareJSUtils::Convert2StrVector(env, argv[0], DataShareJSUtils::DEFAULT_BUF_SIZE); + NAPI_ASSERT_CALL_ERRCODE(env, !(context->uris.empty()), + context->error = std::make_shared("uris", "not empty"), napi_invalid_arg); + NAPI_ASSERT_CALL_ERRCODE(env, context->uris.size() <= URI_MAX_COUNT && + CheckIsParameterExceed(context->uris), context->error = + std::make_shared(), napi_invalid_arg); + if (!DataShareJSUtils::UnwrapDataProxyConfig(env, argv[1], context->config)) { + context->error = std::make_shared("config", "DataProxyConfig"); + return napi_invalid_arg; + } + return napi_ok; + }; + auto output = [context](napi_env env, napi_value *result) -> napi_status { + NAPI_ASSERT_BASE(env, context->status == napi_ok, "exec failed", napi_generic_failure); + *result = DataShareJSUtils::Convert2JSValue(env, context->proxyGetResult); + context->proxyResult.clear(); + return napi_ok; + }; + auto exec = [context](AsyncCall::Context *ctx) { + auto handle = context->proxy->GetHandle(); + NAPI_ASSERT_CALL_ERRCODE(env, handle != nullptr, + context->error = std::make_shared(), napi_generic_failure); + + context->proxyGetResult = handle->GetProxyData(context->uris, context->config); + context->status = napi_ok; + return napi_ok; + }; + context->SetAction(std::move(input), std::move(output)); + AsyncCall asyncCall(env, info, context); + return asyncCall.Call(env, exec); +} + +napi_value NapiDataProxyHandle::Napi_On(napi_env env, napi_callback_info info) +{ + napi_value self = nullptr; + size_t argc = MAX_ARGC; + napi_value argv[MAX_ARGC] = { nullptr }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); + std::shared_ptr error = nullptr; + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, argc == ARGS_FOUR, + error = std::make_shared("4"), error, nullptr); + napi_valuetype valueType; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_string, + error = std::make_shared("event", "string"), error, nullptr); + std::string type = DataShareJSUtils::Convert2String(env, argv[0]); + if (type == "dataChange") { + return Napi_SubscribeProxyData(env, argc, argv, self); + } + LOG_ERROR("wrong register type : %{public}s", type.c_str()); + return nullptr; +} + +napi_value NapiDataProxyHandle::Napi_Off(napi_env env, napi_callback_info info) +{ + napi_value self = nullptr; + size_t argc = MAX_ARGC; + napi_value argv[MAX_ARGC] = { nullptr }; + std::shared_ptr error = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, argc == ARGS_THREE || argc == ARGS_FOUR, + error = std::make_shared("3 or 4"), error, nullptr); + + napi_valuetype valueType; + NAPI_CALL(env, napi_typeof(env, argv[0], &valueType)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_string, + error = std::make_shared("event", "string"), error, nullptr); + std::string type = DataShareJSUtils::Convert2String(env, argv[0]); + if (type == "dataChange") { + return Napi_UnSubscribeProxyData(env, argc, argv, self); + } + LOG_ERROR("wrong register type : %{public}s", type.c_str()); + return nullptr; +} + +void NapiDataProxyHandle::NapiDataProxyHandle::SetHandle(std::shared_ptr dataProxyHandle) +{ + std::unique_lock lock(mutex_); + dataProxyHandle_ = std::move(dataProxyHandle); +} + +std::shared_ptr NapiDataProxyHandle::GetHandle() +{ + std::shared_lock lock(mutex_); + return dataProxyHandle_; +} + +napi_value NapiDataProxyHandle::Napi_SubscribeProxyData(napi_env env, size_t argc, napi_value *argv, napi_value self) +{ + std::vector results; + napi_value jsResults = DataShareJSUtils::Convert2JSValue(env, results); + std::shared_ptr error = nullptr; + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, argc == ARGS_FOUR, error = std::make_shared("4"), error, + jsResults); + + NapiDataProxyHandle *proxy = nullptr; + NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast(&proxy)), jsResults); + NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataProxyHandle instance", jsResults); + auto handle = proxy->GetHandle(); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, handle != nullptr, error = std::make_shared(), error, + jsResults); + + napi_valuetype valueType; + NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valueType)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_object, + error = std::make_shared("uris", "Array"), error, jsResults); + std::vector uris = + DataShareJSUtils::Convert2StrVector(env, argv[PARAM1], DataShareJSUtils::DEFAULT_BUF_SIZE); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, !(uris.empty()), + error = std::make_shared("uris", "not empty"), error, jsResults); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, uris.size() <= URI_MAX_COUNT && + CheckIsParameterExceed(uris), error = std::make_shared(), error, jsResults); + + NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_object, + error = std::make_shared("config", "DataProxyConfig"), error, jsResults); + DataProxyConfig config; + DataShareJSUtils::UnwrapDataProxyConfig(env, argv[PARAM2], config); + + NAPI_CALL(env, napi_typeof(env, argv[PARAM3], &valueType)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_function, + error = std::make_shared("callback", "function"), error, jsResults); + + if (proxy->jsProxyDataObsManager_ == nullptr) { + LOG_ERROR("proxy->jsManager_ is nullptr"); + return jsResults; + } + results = proxy->jsProxyDataObsManager_->AddObservers(env, argv[PARAM3], uris); + return DataShareJSUtils::Convert2JSValue(env, results); +} + +napi_value NapiDataProxyHandle::Napi_UnSubscribeProxyData(napi_env env, size_t argc, napi_value *argv, napi_value self) +{ + std::vector results; + napi_value jsResults = DataShareJSUtils::Convert2JSValue(env, results); + std::shared_ptr error = nullptr; + NapiDataProxyHandle* proxy = nullptr; + napi_valuetype valueType; + NAPI_CALL_BASE(env, napi_unwrap(env, self, reinterpret_cast(&proxy)), nullptr); + NAPI_ASSERT_BASE(env, proxy != nullptr, "there is no NapiDataProxyHandle instance", nullptr); + auto handle = proxy->GetHandle(); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, handle != nullptr, error = std::make_shared(), error, + nullptr); + NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valueType)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_object, + error = std::make_shared("uris", "Array"), error, nullptr); + auto uris = DataShareJSUtils::Convert2StrVector(env, argv[PARAM1], DataShareJSUtils::DEFAULT_BUF_SIZE); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, !(uris.empty()), + error = std::make_shared("uris", "not empty"), error, jsResults); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, uris.size() <= URI_MAX_COUNT && + CheckIsParameterExceed(uris), error = std::make_shared(), error, jsResults); + + NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valueType)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, valueType == napi_object, + error = std::make_shared("config", "DataProxyConfig"), error, jsResults); + DataProxyConfig config; + DataShareJSUtils::UnwrapDataProxyConfig(env, argv[PARAM2], config); + if (proxy->jsProxyDataObsManager_ == nullptr) { + LOG_ERROR("proxy->jsManager_ is nullptr"); + return jsResults; + } + + if (argc == ARGS_FOUR) { + NAPI_CALL(env, napi_typeof(env, argv[PARAM3], &valueType)); + NAPI_ASSERT_CALL_ERRCODE_SYNC(env, + valueType == napi_function || valueType == napi_undefined || valueType == napi_null, + error = std::make_shared("callback", "function"), error, nullptr); + results = proxy->jsProxyDataObsManager_->DelObservers(env, argv[PARAM3], uris); + } + + results = proxy->jsProxyDataObsManager_->DelObservers(env, nullptr, uris); + return DataShareJSUtils::Convert2JSValue(env, results); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_const_properties.cpp b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_const_properties.cpp index 588347ff..d20b1b07 100644 --- a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_const_properties.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_const_properties.cpp @@ -20,6 +20,7 @@ #include #include "datashare_helper.h" +#include "dataproxy_handle_common.h" #include "napi_base_context.h" #include "napi_common_util.h" @@ -54,11 +55,35 @@ static napi_value ExportSubscriptionType(napi_env env) napi_object_freeze(env, SubscriptionType); return SubscriptionType; } + +static napi_value ExportDataProxyType(napi_env env) +{ + napi_value dataProxyType = nullptr; + napi_create_object(env, &dataProxyType); + SetNamedProperty(env, dataProxyType, "SHARED_CONFIG", static_cast(DataProxyType::SHARED_CONFIG)); + napi_object_freeze(env, dataProxyType); + return dataProxyType; +} + +static napi_value ExportDataProxyErrorCode(napi_env env) +{ + napi_value dataProxyErrorCode = nullptr; + napi_create_object(env, &dataProxyErrorCode); + SetNamedProperty(env, dataProxyErrorCode, "SUCCESS", static_cast(DataProxyErrorCode::SUCCESS)); + SetNamedProperty(env, dataProxyErrorCode, "URI_NOT_EXIST", static_cast(DataProxyErrorCode::URI_NOT_EXIST)); + SetNamedProperty(env, dataProxyErrorCode, "NO_PERMISSION", static_cast(DataProxyErrorCode::NO_PERMISSION)); + SetNamedProperty(env, dataProxyErrorCode, "OVER_LIMIT", static_cast(DataProxyErrorCode::OVER_LIMIT)); + napi_object_freeze(env, dataProxyErrorCode); + return dataProxyErrorCode; +} + napi_status InitConstProperties(napi_env env, napi_value exports) { const napi_property_descriptor properties[] = { DECLARE_NAPI_PROPERTY("ChangeType", ExportChangeType(env)), DECLARE_NAPI_PROPERTY("SubscriptionType", ExportSubscriptionType(env)), + DECLARE_NAPI_PROPERTY("DataProxyType", ExportDataProxyType(env)), + DECLARE_NAPI_PROPERTY("DataProxyErrorCode", ExportDataProxyErrorCode(env)), }; size_t count = sizeof(properties) / sizeof(properties[0]); diff --git a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp index 531c5a8d..5774c506 100644 --- a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp @@ -154,30 +154,47 @@ void NapiDataShareHelper::ExecuteCreator(std::shared_ptr ctxI } } +napi_status NapiDataShareHelper::ValidateCreateParam(napi_env env, size_t argc, napi_value *argv, + std::shared_ptr ctxInfo) +{ + NAPI_ASSERT_CALL_ERRCODE(env, IsSystemApp(), + ctxInfo->error = std::make_shared(EXCEPTION_SYSTEMAPP_CHECK, "not system app"), + napi_generic_failure); + // Check the number of arguments given to match CreateDataShareHelper founction with 2 or 3 or 4 args. + NAPI_ASSERT_CALL_ERRCODE(env, argc == 2 || argc == 3 || argc == 4, + ctxInfo->error = std::make_shared("2 or 3 or 4"), napi_invalid_arg); + ctxInfo->contextS = OHOS::AbilityRuntime::GetStageModeContext(env, argv[0]); + NAPI_ASSERT_CALL_ERRCODE(env, ctxInfo->contextS != nullptr, + ctxInfo->error = std::make_shared("contextS", "not nullptr"), napi_invalid_arg); + NAPI_ASSERT_CALL_ERRCODE(env, GetUri(env, argv[1], ctxInfo->strUri), + ctxInfo->error = std::make_shared("uri", "string"), napi_invalid_arg); + Uri uri(ctxInfo->strUri); + // If there is more then 2 napi args, then the third arg options and uri format needs to be checked. + if (argc != 2) { + // The napi input argument at index 2 is optional config. + NAPI_ASSERT_CALL_ERRCODE(env, GetOptions(env, argv[2], ctxInfo->options, uri), + ctxInfo->error = std::make_shared("option", "CreateOption"), napi_invalid_arg); + } else { + NAPI_ASSERT_CALL_ERRCODE(env, uri.GetScheme() != "datashareproxy", + ctxInfo->error = std::make_shared("3 or 4"), napi_invalid_arg); + } + return napi_ok; +} + napi_value NapiDataShareHelper::Napi_CreateDataShareHelper(napi_env env, napi_callback_info info) { auto ctxInfo = std::make_shared(); auto input = [ctxInfo](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { - NAPI_ASSERT_CALL_ERRCODE(env, IsSystemApp(), - ctxInfo->error = std::make_shared(EXCEPTION_SYSTEMAPP_CHECK, "not system app"), - napi_generic_failure); - NAPI_ASSERT_CALL_ERRCODE(env, argc == 2 || argc == 3 || argc == 4, - ctxInfo->error = std::make_shared("2 or 3 or 4"), napi_invalid_arg); - ctxInfo->contextS = OHOS::AbilityRuntime::GetStageModeContext(env, argv[0]); - NAPI_ASSERT_CALL_ERRCODE(env, ctxInfo->contextS != nullptr, - ctxInfo->error = std::make_shared("contextS", "not nullptr"), napi_invalid_arg); - NAPI_ASSERT_CALL_ERRCODE(env, GetUri(env, argv[1], ctxInfo->strUri), - ctxInfo->error = std::make_shared("uri", "string"), napi_invalid_arg); - Uri uri(ctxInfo->strUri); - if (argc != 2) { - NAPI_ASSERT_CALL_ERRCODE(env, GetOptions(env, argv[2], ctxInfo->options, uri), - ctxInfo->error = std::make_shared("option", "CreateOption"), napi_invalid_arg); - } else { - NAPI_ASSERT_CALL_ERRCODE(env, uri.GetScheme() != "datashareproxy", - ctxInfo->error = std::make_shared("3 or 4"), napi_invalid_arg); + napi_status status = ValidateCreateParam(env, argc, argv, ctxInfo); + if (status != napi_ok) { + return status; } napi_value helperProxy = nullptr; - napi_status status = napi_new_instance(env, GetConstructor(env), argc, argv, &helperProxy); + status = napi_new_instance(env, GetConstructor(env), argc, argv, &helperProxy); + if (status != napi_ok) { + LOG_ERROR("napi new instance failed. napi_status: %{public}d uri: %{public}s", + status, ctxInfo->strUri.c_str()); + } NAPI_ASSERT_CALL_ERRCODE(env, helperProxy != nullptr && status == napi_ok, ctxInfo->error = std::make_shared(), napi_generic_failure); napi_create_reference(env, helperProxy, 1, &(ctxInfo->ref)); @@ -211,7 +228,10 @@ napi_value NapiDataShareHelper::GetConstructor(napi_env env) { napi_value cons = nullptr; if (constructor_ != nullptr) { - napi_get_reference_value(env, constructor_, &cons); + napi_status status = napi_get_reference_value(env, constructor_, &cons); + if (status != napi_ok) { + LOG_ERROR("napi get reference value failed. napi_status: %{public}d", status); + } return cons; } napi_property_descriptor clzDes[] = { @@ -234,7 +254,10 @@ napi_value NapiDataShareHelper::GetConstructor(napi_env env) }; NAPI_CALL(env, napi_define_class(env, "DataShareHelper", NAPI_AUTO_LENGTH, Initialize, nullptr, sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons)); - napi_create_reference(env, cons, 1, &constructor_); + napi_status status = napi_create_reference(env, cons, 1, &constructor_); + if (status != napi_ok) { + LOG_ERROR("napi create reference failed. napi_status: %{public}d", status); + } return cons; } @@ -629,7 +652,7 @@ void NapiDataShareHelper::Notify(const std::shared_ptrerror = std::make_shared("uri", "not empty"); return; } - helper->NotifyChangeExt(context->changeInfo); + helper->NotifyChangeExt(context->changeInfo, true); context->status = napi_ok; return; } @@ -1039,6 +1062,7 @@ void NapiDataShareHelper::RegisteredObserver(napi_env env, const std::string &ur return; } auto innerObserver = std::make_shared(env, callback); + innerObserver->RegisterEnvCleanHook(); sptr observer(new (std::nothrow) NAPIDataShareObserver(innerObserver)); if (observer == nullptr) { LOG_ERROR("observer is nullptr"); @@ -1048,7 +1072,8 @@ void NapiDataShareHelper::RegisteredObserver(napi_env env, const std::string &ur helper->RegisterObserver(Uri(uri), observer); } else { helper->RegisterObserverExt(Uri(uri), - std::shared_ptr(observer.GetRefPtr(), [holder = observer](const auto*) {}), false); + std::shared_ptr(observer.GetRefPtr(), [holder = observer](const auto*) {}), + false, true); } list.push_back(observer); } @@ -1073,7 +1098,7 @@ void NapiDataShareHelper::UnRegisteredObserver(napi_env env, const std::string & helper->UnregisterObserver(Uri(uri), *it); } else { helper->UnregisterObserverExt(Uri(uri), - std::shared_ptr((*it).GetRefPtr(), [holder = *it](const auto*) {})); + std::shared_ptr((*it).GetRefPtr(), [holder = *it](const auto*) {}), true); } (*it)->observer_->DeleteReference(); it = list.erase(it); @@ -1100,7 +1125,7 @@ void NapiDataShareHelper::UnRegisteredObserver(napi_env env, const std::string & helper->UnregisterObserver(Uri(uri), *it); } else { helper->UnregisterObserverExt(Uri(uri), - std::shared_ptr((*it).GetRefPtr(), [holder = *it](const auto*) {})); + std::shared_ptr((*it).GetRefPtr(), [holder = *it](const auto*) {}), true); } (*it)->observer_->DeleteReference(); it = list.erase(it); diff --git a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_inner_observer.cpp b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_inner_observer.cpp index 3b02fd5c..e4cf6fec 100644 --- a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_inner_observer.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_inner_observer.cpp @@ -31,6 +31,36 @@ NAPIInnerObserver::NAPIInnerObserver(napi_env env, napi_value callback) napi_get_uv_event_loop(env, &loop_); } +NAPIInnerObserver::~NAPIInnerObserver() +{ + if (env_ == nullptr) { + LOG_ERROR("env_ is nullptr"); + return; + } + // SAFETY: observerEnvHookWorker will not be accessed in napi_remove_env_cleanup_hook + auto task = [env = env_, observerEnvHookWorker = observerEnvHookWorker_]() { + napi_remove_env_cleanup_hook(env, &CleanEnv, observerEnvHookWorker); + }; + int ret = napi_send_event(env_, task, napi_eprio_immediate); + if (ret != 0) { + LOG_ERROR("napi_send_event failed: %{public}d", ret); + } + if (observerEnvHookWorker_ != nullptr) { + delete observerEnvHookWorker_; + observerEnvHookWorker_ = nullptr; + } +} + +void NAPIInnerObserver::RegisterEnvCleanHook() +{ + observerEnvHookWorker_ = new (std::nothrow) ObserverEnvHookWorker(shared_from_this()); + if (observerEnvHookWorker_ == nullptr) { + LOG_ERROR("Failed to create observerEnvHookWorker_"); + return; + } + napi_add_env_cleanup_hook(env_, &CleanEnv, observerEnvHookWorker_); +} + void NAPIInnerObserver::OnComplete(ObserverWorker* observerWorker) { LOG_DEBUG("napi_send_event start"); @@ -40,6 +70,12 @@ void NAPIInnerObserver::OnComplete(ObserverWorker* observerWorker) delete observerWorker; return; } + std::lock_guard lck(observer->envMutex_); + if (observer->env_ == nullptr) { + LOG_ERROR("innerWorker->observer_->env_ is nullptr"); + delete observerWorker; + return; + } napi_handle_scope scope = nullptr; napi_open_handle_scope(observer->env_, &scope); if (scope == nullptr) { @@ -74,6 +110,12 @@ void NAPIInnerObserver::OnChange(const DataShareObserver::ChangeInfo& changeInfo LOG_ERROR("ref_ is nullptr"); return; } + std::lock_guard lck(envMutex_); + if (env_ == nullptr) { + LOG_ERROR("env_ is nullptr"); + return; + } + ObserverWorker* observerWorker = new (std::nothrow) ObserverWorker(shared_from_this(), changeInfo); if (observerWorker == nullptr) { LOG_ERROR("Failed to create observerWorker"); @@ -103,5 +145,21 @@ napi_ref NAPIInnerObserver::GetCallback() { return ref_; } + +void NAPIInnerObserver::CleanEnv(void *obj) +{ + LOG_INFO("Napi env cleanup hook is executed, env is about to exit"); + auto observerEnvHookWorker = reinterpret_cast(obj); + // Prevent concurrency with NAPIInnerObserver destructors + auto observer = observerEnvHookWorker->observer_.lock(); + if (observer == nullptr) { + LOG_ERROR("observer is nullptr"); + return; + } + std::lock_guard lck(observer->envMutex_); + observer->DeleteReference(); + observer->env_ = nullptr; +} + } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/js/napi/dataShare/src/native_datashare_module.cpp b/data_share/frameworks/js/napi/dataShare/src/native_datashare_module.cpp index 13485c21..802c0278 100644 --- a/data_share/frameworks/js/napi/dataShare/src/native_datashare_module.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/native_datashare_module.cpp @@ -18,6 +18,7 @@ #include "napi/native_node_api.h" #include "napi_datashare_const_properties.h" #include "napi_datashare_helper.h" +#include "napi_dataproxy_handle.h" namespace OHOS { namespace DataShare { @@ -31,6 +32,7 @@ static napi_value Init(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("createDataShareHelper", NapiDataShareHelper::Napi_CreateDataShareHelper), DECLARE_NAPI_FUNCTION("enableSilentProxy", NapiDataShareHelper::EnableSilentProxy), DECLARE_NAPI_FUNCTION("disableSilentProxy", NapiDataShareHelper::DisableSilentProxy), + DECLARE_NAPI_FUNCTION("createDataProxyHandle", NapiDataProxyHandle::Napi_CreateDataProxyHandle), }; napi_status status = napi_define_properties(env, exports, sizeof(desc) / sizeof(napi_property_descriptor), desc); LOG_DEBUG("napi_define_properties status : %{public}d", status); diff --git a/data_share/frameworks/js/napi/observer/include/napi_observer.h b/data_share/frameworks/js/napi/observer/include/napi_observer.h index d5d2cca2..5edc516f 100644 --- a/data_share/frameworks/js/napi/observer/include/napi_observer.h +++ b/data_share/frameworks/js/napi/observer/include/napi_observer.h @@ -22,12 +22,14 @@ #include "napi/native_api.h" #include "napi/native_common.h" #include "napi/native_node_api.h" +#include "dataproxy_handle_common.h" namespace OHOS { namespace DataShare { -class NapiObserver { +class NapiObserver : public std::enable_shared_from_this { public: NapiObserver(napi_env env, napi_value callback); + void RegisterEnvCleanHook(); virtual ~NapiObserver(); virtual bool operator==(const NapiObserver &rhs) const; virtual bool operator!=(const NapiObserver &rhs) const; @@ -38,23 +40,36 @@ protected: std::function getParam; explicit ObserverWorker(std::shared_ptr observerIn) : observer_(observerIn) {} }; + struct ObserverEnvHookWorker { + std::weak_ptr observer_; + ObserverEnvHookWorker(std::shared_ptr observerIn): observer_(observerIn) {} + }; static void CallbackFunc(ObserverWorker *observerWorker); + static void CleanEnv(void *obj); napi_env env_ = nullptr; napi_ref ref_ = nullptr; uv_loop_s *loop_ = nullptr; + std::unique_ptr envMutexPtr_; + ObserverEnvHookWorker* observerEnvHookWorker_ = nullptr; }; -class NapiRdbObserver final: public NapiObserver, public std::enable_shared_from_this { +class NapiRdbObserver final: public NapiObserver { public: NapiRdbObserver(napi_env env, napi_value callback) : NapiObserver(env, callback) {}; void OnChange(const RdbChangeNode &changeNode); }; -class NapiPublishedObserver final: public NapiObserver, public std::enable_shared_from_this { +class NapiPublishedObserver final: public NapiObserver { public: NapiPublishedObserver(napi_env env, napi_value callback) : NapiObserver(env, callback) {}; void OnChange(PublishedDataChangeNode &changeNode); }; + +class NapiProxyDataObserver final: public NapiObserver { +public: + NapiProxyDataObserver(napi_env env, napi_value callback) : NapiObserver(env, callback) {}; + void OnChange(const std::vector &changeNode); +}; } // namespace DataShare } // namespace OHOS #endif //NAPI_RDB_OBSERVER_H diff --git a/data_share/frameworks/js/napi/observer/include/napi_subscriber_manager.h b/data_share/frameworks/js/napi/observer/include/napi_subscriber_manager.h index 3c06ef06..552c9236 100644 --- a/data_share/frameworks/js/napi/observer/include/napi_subscriber_manager.h +++ b/data_share/frameworks/js/napi/observer/include/napi_subscriber_manager.h @@ -26,6 +26,8 @@ #include "napi/native_common.h" #include "napi/native_node_api.h" #include "napi_observer.h" +#include "dataproxy_handle.h" +#include "dataproxy_handle_common.h" namespace OHOS { namespace DataShare { @@ -117,6 +119,42 @@ private: std::weak_ptr dataShareHelper_; ConcurrentMap lastChangeNodeMap_; }; + +struct NapiProxyDataObserverMapKey { + std::string uri_; + NapiProxyDataObserverMapKey(const std::string &uri) : uri_(uri) {}; + bool operator==(const NapiProxyDataObserverMapKey &node) const + { + return uri_ == node.uri_; + } + bool operator!=(const NapiProxyDataObserverMapKey &node) const + { + return !(node == *this); + } + bool operator<(const NapiProxyDataObserverMapKey &node) const + { + return uri_ < node.uri_; + } + operator std::string() const + { + return uri_; + } +}; + +class NapiProxyDataSubscriberManager : public NapiCallbacksManager { +public: + using Key = NapiProxyDataObserverMapKey; + using Observer = NapiProxyDataObserver; + using BaseCallbacks = NapiCallbacksManager; + explicit NapiProxyDataSubscriberManager(std::weak_ptr dataProxyHandle) + : dataProxyHandle_(dataProxyHandle){}; + std::vector AddObservers(napi_env env, napi_value callback, const std::vector &uris); + std::vector DelObservers(napi_env env, napi_value callback, const std::vector &uris); + void Emit(const std::vector &changeNode); + +private: + std::weak_ptr dataProxyHandle_; +}; } // namespace DataShare } // namespace OHOS #endif //NAPI_RDB_SUBSCRIBER_MANAGER_H diff --git a/data_share/frameworks/js/napi/observer/src/napi_observer.cpp b/data_share/frameworks/js/napi/observer/src/napi_observer.cpp index 3b5fbfcf..c99a4410 100644 --- a/data_share/frameworks/js/napi/observer/src/napi_observer.cpp +++ b/data_share/frameworks/js/napi/observer/src/napi_observer.cpp @@ -15,6 +15,7 @@ #include "napi_observer.h" +#include "dataproxy_handle_common.h" #include "datashare_js_utils.h" #include "datashare_log.h" @@ -22,6 +23,7 @@ namespace OHOS { namespace DataShare { NapiObserver::NapiObserver(napi_env env, napi_value callback) : env_(env) { + envMutexPtr_ = std::make_unique(); napi_create_reference(env, callback, 1, &ref_); napi_get_uv_event_loop(env, &loop_); } @@ -30,11 +32,17 @@ void NapiObserver::CallbackFunc(ObserverWorker *observerWorker) { LOG_DEBUG("ObsCallbackFunc start"); std::shared_ptr observer = observerWorker->observer_.lock(); - if (observer == nullptr || observer->ref_ == nullptr) { + if (observer == nullptr || observer->ref_ == nullptr || observer->envMutexPtr_ == nullptr) { LOG_ERROR("rdbObserver->ref_ is nullptr"); delete observerWorker; return; } + std::lock_guard lck(*observer->envMutexPtr_); + if (observer->env_ == nullptr) { + LOG_ERROR("rdbObserver->env_ is nullptr"); + delete observerWorker; + return; + } napi_handle_scope scope = nullptr; napi_open_handle_scope(observer->env_, &scope); if (scope == nullptr) { @@ -61,9 +69,15 @@ void NapiObserver::CallbackFunc(ObserverWorker *observerWorker) NapiObserver::~NapiObserver() { + if (env_ == nullptr) { + LOG_ERROR("env_ is nullptr"); + return; + } + if (ref_ != nullptr) { - auto task = [env = env_, ref = ref_]() { + auto task = [env = env_, ref = ref_, observerEnvHookWorker = observerEnvHookWorker_]() { napi_delete_reference(env, ref); + napi_remove_env_cleanup_hook(env, &CleanEnv, observerEnvHookWorker); }; int ret = napi_send_event(env_, task, napi_eprio_immediate); if (ret != 0) { @@ -71,6 +85,10 @@ NapiObserver::~NapiObserver() } ref_ = nullptr; } + if (observerEnvHookWorker_ != nullptr) { + delete observerEnvHookWorker_; + observerEnvHookWorker_ = nullptr; + } } bool NapiObserver::operator==(const NapiObserver &rhs) const @@ -95,11 +113,45 @@ bool NapiObserver::operator!=(const NapiObserver &rhs) const return !(rhs == *this); } +void NapiObserver::RegisterEnvCleanHook() +{ + observerEnvHookWorker_ = new (std::nothrow) ObserverEnvHookWorker(shared_from_this()); + if (observerEnvHookWorker_ == nullptr) { + LOG_ERROR("Failed to create observerEnvHookWorker_"); + return; + } + napi_add_env_cleanup_hook(env_, &CleanEnv, observerEnvHookWorker_); +} + +void NapiObserver::CleanEnv(void *obj) +{ + LOG_INFO("Napi env cleanup hook is executed, env is about to exit"); + auto observerEnvHookWorker = reinterpret_cast(obj); + // Prevent concurrency with NAPIInnerObserver destructors + auto observer = observerEnvHookWorker->observer_.lock(); + if (observer == nullptr || observer->envMutexPtr_ == nullptr) { + LOG_ERROR("observer or observer->envMutexPtr_ is nullptr"); + delete observerEnvHookWorker; + return; + } + std::lock_guard lck(*observer->envMutexPtr_); + if (observer->ref_ != nullptr) { + napi_delete_reference(observer->env_, observer->ref_); + observer->ref_ = nullptr; + } + observer->env_ = nullptr; +} + void NapiRdbObserver::OnChange(const RdbChangeNode &changeNode) { LOG_DEBUG("NapiRdbObserver onchange Start"); - if (ref_ == nullptr) { - LOG_ERROR("ref_ is nullptr"); + if (ref_ == nullptr || envMutexPtr_ == nullptr) { + LOG_ERROR("ref_ or envMutexPtr_ is nullptr"); + return; + } + std::lock_guard lck(*envMutexPtr_); + if (env_ == nullptr) { + LOG_ERROR("env_ is nullptr"); return; } ObserverWorker *observerWorker = new (std::nothrow) ObserverWorker(shared_from_this()); @@ -125,8 +177,13 @@ void NapiRdbObserver::OnChange(const RdbChangeNode &changeNode) void NapiPublishedObserver::OnChange(PublishedDataChangeNode &changeNode) { LOG_DEBUG("NapiPublishedObserver onchange Start"); - if (ref_ == nullptr) { - LOG_ERROR("ref_ is nullptr"); + if (ref_ == nullptr || envMutexPtr_ == nullptr) { + LOG_ERROR("ref_ or envMutexPtr_ is nullptr"); + return; + } + std::lock_guard lck(*envMutexPtr_); + if (env_ == nullptr) { + LOG_ERROR("env_ is nullptr"); return; } ObserverWorker *observerWorker = new (std::nothrow) ObserverWorker(shared_from_this()); @@ -149,5 +206,39 @@ void NapiPublishedObserver::OnChange(PublishedDataChangeNode &changeNode) } LOG_DEBUG("NapiRdbObserver onchange End: %{public}d", ret); } + +void NapiProxyDataObserver::OnChange(const std::vector &changeNode) +{ + LOG_INFO("NapiProxyDataObserver onchange Start"); + if (ref_ == nullptr || envMutexPtr_ == nullptr) { + LOG_ERROR("ref_ or envMutexPtr_ is nullptr"); + return; + } + std::lock_guard lck(*envMutexPtr_); + if (env_ == nullptr) { + LOG_ERROR("env_ is nullptr"); + return; + } + ObserverWorker *observerWorker = new (std::nothrow) ObserverWorker(shared_from_this()); + if (observerWorker == nullptr) { + LOG_ERROR("Failed to create observerWorker"); + return; + } + std::shared_ptr> node = + std::make_shared>(std::move(changeNode)); + observerWorker->getParam = [node](napi_env env) { + return DataShareJSUtils::Convert2JSValue(env, *node); + }; + + auto task = [observerWorker]() { + NapiObserver::CallbackFunc(observerWorker); + }; + int ret = napi_send_event(env_, task, napi_eprio_immediate); + if (ret != 0) { + LOG_ERROR("napi_send_event failed: %{public}d", ret); + delete observerWorker; + } + LOG_INFO("NapiProxyDataObserver onchange End: %{public}d", ret); +} } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/js/napi/observer/src/napi_subscriber_manager.cpp b/data_share/frameworks/js/napi/observer/src/napi_subscriber_manager.cpp index 493d4544..34a0af83 100644 --- a/data_share/frameworks/js/napi/observer/src/napi_subscriber_manager.cpp +++ b/data_share/frameworks/js/napi/observer/src/napi_subscriber_manager.cpp @@ -14,7 +14,10 @@ */ #include "napi_subscriber_manager.h" +#include +#include +#include "dataproxy_handle_common.h" #include "datashare_log.h" namespace OHOS { @@ -32,8 +35,10 @@ std::vector NapiRdbSubscriberManager::AddObservers(napi_env env std::for_each(uris.begin(), uris.end(), [&keys, &templateId](auto &uri) { keys.emplace_back(uri, templateId); }); + auto rdbObserver = std::make_shared(env, callback); + rdbObserver->RegisterEnvCleanHook(); return BaseCallbacks::AddObservers( - keys, std::make_shared(env, callback), + keys, rdbObserver, [this](const std::vector &localRegisterKeys, const std::shared_ptr observer) { Emit(localRegisterKeys, observer); }, @@ -133,8 +138,10 @@ std::vector NapiPublishedSubscriberManager::AddObservers(napi_e std::for_each(uris.begin(), uris.end(), [&keys, &subscriberId](auto &uri) { keys.emplace_back(uri, subscriberId); }); + auto publishedObserver = std::make_shared(env, callback); + publishedObserver->RegisterEnvCleanHook(); return BaseCallbacks::AddObservers( - keys, std::make_shared(env, callback), + keys, publishedObserver, [this](const std::vector &localRegisterKeys, const std::shared_ptr observer) { Emit(localRegisterKeys, observer); }, @@ -239,5 +246,98 @@ void NapiPublishedSubscriberManager::Emit(const std::vector &keys, const st } observer->OnChange(node); } + +std::vector NapiProxyDataSubscriberManager::AddObservers(napi_env env, napi_value callback, + const std::vector &uris) +{ + std::vector result = {}; + auto dataProxyHandle = dataProxyHandle_.lock(); + if (dataProxyHandle == nullptr) { + LOG_ERROR("dataProxyHandle is nullptr"); + return result; + } + + std::vector keys; + std::for_each(uris.begin(), uris.end(), [&keys](auto &uri) { + keys.emplace_back(uri); + }); + auto proxyDataObserver = std::make_shared(env, callback); + proxyDataObserver->RegisterEnvCleanHook(); + return BaseCallbacks::AddObservers( + keys, proxyDataObserver, + [&dataProxyHandle, this](const std::vector &firstAddKeys, + const std::shared_ptr observer, std::vector &opResult) { + std::vector firstAddUris; + std::for_each(firstAddKeys.begin(), firstAddKeys.end(), [&firstAddUris](auto &result) { + firstAddUris.emplace_back(result); + }); + if (firstAddUris.empty()) { + return; + } + auto subResults = dataProxyHandle->SubscribeProxyData(firstAddUris, + [this](const std::vector &changeInfo) { + Emit(changeInfo); + }); + std::vector failedKeys; + for (auto &subResult : subResults) { + opResult.emplace_back(subResult); + if (subResult.result_ != SUCCESS) { + failedKeys.emplace_back(subResult.uri_); + LOG_WARN("registered failed, uri is %{public}s", subResult.uri_.c_str()); + } + } + if (failedKeys.size() > 0) { + BaseCallbacks::DelObservers(failedKeys, observer); + } + }); +} + +std::vector NapiProxyDataSubscriberManager::DelObservers(napi_env env, napi_value callback, + const std::vector &uris) +{ + std::vector result = {}; + auto dataProxyHandle = dataProxyHandle_.lock(); + if (dataProxyHandle == nullptr) { + LOG_ERROR("dataProxyHandle is nullptr"); + return result; + } + + std::vector keys; + std::for_each(uris.begin(), uris.end(), [&keys](auto &uri) { + keys.emplace_back(uri); + }); + return BaseCallbacks::DelObservers(keys, callback == nullptr ? nullptr : std::make_shared(env, callback), + [&dataProxyHandle, &callback, &uris, this](const std::vector &lastDelKeys, + const std::shared_ptr &observer, std::vector &opResult) { + std::vector lastDelUris; + std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [&lastDelUris, this](auto &result) { + lastDelUris.emplace_back(result); + }); + if (lastDelUris.empty()) { + return; + } + auto unsubResult = dataProxyHandle->UnsubscribeProxyData(lastDelUris); + opResult.insert(opResult.end(), unsubResult.begin(), unsubResult.end()); + }); +} + +void NapiProxyDataSubscriberManager::Emit(const std::vector &changeInfo) +{ + std::map, std::vector> results; + for (const auto &info : changeInfo) { + Key key(info.uri_); + auto callbacks = BaseCallbacks::GetEnabledObservers(key); + if (callbacks.empty()) { + LOG_WARN("emit but nobody subscribe"); + continue; + } + for (const auto &obs : callbacks) { + results[obs].emplace_back(info); + } + } + for (const auto &[callback, infos] : results) { + callback->OnChange(infos); + } +} } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/common/include/call_reporter.h b/data_share/frameworks/native/common/include/call_reporter.h index 52b83e91..f40f84ed 100644 --- a/data_share/frameworks/native/common/include/call_reporter.h +++ b/data_share/frameworks/native/common/include/call_reporter.h @@ -26,13 +26,21 @@ public: DataShareCallReporter() = default; struct CallInfo { int count = 0; + // total count for silent access threshold + int totalCount = 0; std::chrono::system_clock::time_point firstTime; + // start time of ervery 30s + std::chrono::system_clock::time_point startTime; + // print err log only once by using flag + bool logPrintFlag = false; }; - void Count(const std::string &funcName, const std::string &uri); + bool Count(const std::string &funcName, const std::string &uri); private: - ConcurrentMap callCounts; + ConcurrentMap callCounts_; static constexpr int RESET_COUNT_THRESHOLD = 100; + static constexpr int ACCESS_COUNT_THRESHOLD = 3000; // silent access threshold static constexpr std::chrono::milliseconds TIME_THRESHOLD = std::chrono::milliseconds(30000); + void UpdateCallCounts(const std::string &funcName, int &overCount, int64_t &firstCallTime, bool &isOverThreshold); }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/common/include/callbacks_manager.h b/data_share/frameworks/native/common/include/callbacks_manager.h index 3c7fcd3f..3a399831 100644 --- a/data_share/frameworks/native/common/include/callbacks_manager.h +++ b/data_share/frameworks/native/common/include/callbacks_manager.h @@ -22,6 +22,7 @@ #include "datashare_errno.h" #include "datashare_log.h" #include "datashare_template.h" +#include "dataproxy_handle_common.h" namespace OHOS::DataShare { template @@ -40,31 +41,49 @@ public: std::function &, const std::shared_ptr &observer, std::vector &)>); + std::vector AddObservers(const std::vector &keys, void *subscriber, + const std::shared_ptr observer, + std::function &, const std::shared_ptr &observer, + std::vector &)>); + std::vector DelObservers(const std::vector &keys, void *subscriber, std::function &, std::vector &)> processOnLastDel = CallbacksManager::DefaultProcess); + std::vector DelProxyDataObservers(const std::vector &keys, void *subscriber, + std::function &, std::vector &)> processOnLastDel = + CallbacksManager::ProxyDataDefaultProcess); + std::vector DelObservers(void *subscriber, std::function &, std::vector &)> processOnLastDel = CallbacksManager::DefaultProcess); + std::vector DelObservers(void *subscriber, + std::function &, std::vector &)> processOnLastDel); + std::vector EnableObservers(const std::vector &keys, void *subscriber, - std::function> &)> processOnLocalEnabled, - std::function &, std::vector &)>); + std::function> &)> processOnLocalEnabled = + CallbacksManager::DefaultProcessOnLocalEnabled, + std::function &, std::vector &)> processOnFirstAdd = + CallbacksManager::DefaultProcess); std::vector DisableObservers(const std::vector &keys, void *subscriber, std::function &, std::vector &)> processOnLastDel = CallbacksManager::DefaultProcess); std::vector> GetEnabledObservers(const Key &); + std::vector> GetObserversAndSetNotifiedOn(const Key &); int GetAllSubscriberSize(); int GetAllSubscriberSize(const Key &key); std::vector GetKeys(); void SetObserversNotifiedOnEnabled(const Key &key); + bool IsObserversNotifiedOnEnabled(const Key &key, std::shared_ptr &observer); private: static void DefaultProcess(const std::vector &, std::vector &){}; + static void ProxyDataDefaultProcess(const std::vector &, std::vector &){}; + static void DefaultProcessOnLocalEnabled(std::map> &){}; struct ObserverNode { std::shared_ptr observer_; bool enabled_; @@ -79,7 +98,10 @@ private: }; void DelLocalObservers(const Key &key, void *subscriber, std::vector &lastDelKeys, std::vector &result); + void DelLocalObservers(const Key &key, void *subscriber, std::vector &lastDelKeys, + std::vector &result); void DelLocalObservers(void *subscriber, std::vector &lastDelKeys, std::vector &result); + void DelLocalObservers(void *subscriber, std::vector &lastDelKeys, std::vector &result); std::recursive_mutex mutex_{}; std::map> callbacks_; }; @@ -115,6 +137,23 @@ std::vector CallbacksManager::AddObservers(const return result; } +template +std::vector CallbacksManager::AddObservers(const std::vector &keys, + void *subscriber, const std::shared_ptr observer, + std::function &, + const std::shared_ptr &observer, std::vector &)> processOnFirstAdd) +{ + std::vector result; + { + std::lock_guard lck(mutex_); + for (auto &key : keys) { + callbacks_[key].emplace_back(observer, subscriber); + } + } + processOnFirstAdd(keys, observer, result); + return result; +} + template std::vector CallbacksManager::GetKeys() { @@ -137,6 +176,15 @@ void CallbacksManager::DelLocalObservers(void *subscriber, std::v } } +template +void CallbacksManager::DelLocalObservers(void *subscriber, std::vector &lastDelKeys, + std::vector &result) +{ + for (auto &it : callbacks_) { + DelLocalObservers(it.first, subscriber, lastDelKeys, result); + } +} + template void CallbacksManager::DelLocalObservers(const Key &key, void *subscriber, std::vector &lastDelKeys, std::vector &result) @@ -162,6 +210,31 @@ void CallbacksManager::DelLocalObservers(const Key &key, void *su lastDelKeys.emplace_back(key); } +template +void CallbacksManager::DelLocalObservers(const Key &key, void *subscriber, + std::vector &lastDelKeys, std::vector &result) +{ + auto it = callbacks_.find(key); + if (it == callbacks_.end()) { + result.emplace_back(key, INNER_ERROR); + return; + } + std::vector &callbacks = it->second; + auto callbackIt = callbacks.begin(); + while (callbackIt != callbacks.end()) { + if (callbackIt->subscriber_ != subscriber) { + callbackIt++; + continue; + } + callbackIt = callbacks.erase(callbackIt); + } + if (!it->second.empty()) { + result.emplace_back(key, INNER_ERROR); + return; + } + lastDelKeys.emplace_back(key); +} + template std::vector CallbacksManager::DelObservers(void *subscriber, std::function &, std::vector &)> processOnLastDel) @@ -204,6 +277,48 @@ std::vector CallbacksManager::DelObservers(const return result; } +template +std::vector CallbacksManager::DelObservers(void *subscriber, + std::function &, std::vector &)> processOnLastDel) +{ + std::vector result; + std::vector lastDelKeys; + { + std::lock_guard lck(mutex_); + DelLocalObservers(subscriber, lastDelKeys, result); + if (lastDelKeys.empty()) { + return result; + } + for (auto &key : lastDelKeys) { + callbacks_.erase(key); + } + } + processOnLastDel(lastDelKeys, result); + return result; +} + +template +std::vector CallbacksManager::DelProxyDataObservers(const std::vector &keys, + void *subscriber, std::function &, std::vector &)> processOnLastDel) +{ + std::vector result; + std::vector lastDelKeys; + { + std::lock_guard lck(mutex_); + for (auto &key : keys) { + DelLocalObservers(key, subscriber, lastDelKeys, result); + } + if (lastDelKeys.empty()) { + return result; + } + for (auto &key : lastDelKeys) { + callbacks_.erase(key); + } + } + processOnLastDel(lastDelKeys, result); + return result; +} + template std::vector> CallbacksManager::GetEnabledObservers(const Key &inputKey) { @@ -221,6 +336,34 @@ std::vector> CallbacksManager::GetEnabl return results; } +template +std::vector> CallbacksManager::GetObserversAndSetNotifiedOn( + const Key &inputKey) +{ + std::lock_guard lck(mutex_); + auto it = callbacks_.find(inputKey); + if (it == callbacks_.end()) { + return std::vector>(); + } + std::vector> results; + uint32_t num = 0; + std::vector &callbacks = it->second; + for (auto &value : callbacks) { + if ((value.enabled_ && value.observer_ != nullptr)) { + results.emplace_back(value.observer_); + // if get this enabled observer and notify, it's isNotifyOnEnabled flag should be reset to false + value.isNotifyOnEnabled_ = false; + } else { + num++; + value.isNotifyOnEnabled_ = true; + } + } + if (num > 0) { + LOG_INFO("total %{public}zu, not refreshed %{public}u", callbacks.size(), num); + } + return results; +} + template std::vector CallbacksManager::EnableObservers( const std::vector &keys, void *subscriber, @@ -293,7 +436,10 @@ std::vector CallbacksManager::DisableObservers(c bool hasDisabled = false; for (auto &item : callbacks_[key]) { if (item.subscriber_ == subscriber) { - item.enabled_ = false; + if (item.enabled_) { + item.enabled_ = false; + item.isNotifyOnEnabled_ = false; + } hasDisabled = true; } } @@ -355,5 +501,22 @@ void CallbacksManager::SetObserversNotifiedOnEnabled(const Key &k LOG_INFO("total %{public}zu, not refreshed %{public}u", callbacks.size(), num); } } + +template +bool CallbacksManager::IsObserversNotifiedOnEnabled(const Key &key, std::shared_ptr &observer) +{ + std::lock_guard lck(mutex_); + auto it = callbacks_.find(key); + if (it == callbacks_.end()) { + return false; + } + std::vector &callbacks = it->second; + for (auto &node : callbacks) { + if (node.observer_ == observer) { + return node.isNotifyOnEnabled_; + } + } + return false; +} } // namespace OHOS::DataShare #endif // DATA_SHARE_CALLBACKS_MANAGER_H diff --git a/data_share/frameworks/native/common/include/datashare_common.h b/data_share/frameworks/native/common/include/datashare_common.h new file mode 100644 index 00000000..8f0324a7 --- /dev/null +++ b/data_share/frameworks/native/common/include/datashare_common.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 DATASHARE_COMMON_H +#define DATASHARE_COMMON_H + +#include "datashare_option.h" + +namespace OHOS::DataShare { +constexpr int MAX_THREADS = 2; +constexpr int MIN_THREADS = 0; +constexpr const char *DATASHARE_EXECUTOR_NAME = "DShare_Executor"; + +struct UriInfo { + std::string uri; + std::string extUri; + DataShareOption option; +}; +} +#endif // DATASHARE_COMMON_H \ No newline at end of file diff --git a/data_share/frameworks/native/common/include/datashare_itypes_utils.h b/data_share/frameworks/native/common/include/datashare_itypes_utils.h index 61c566dd..1475a72b 100644 --- a/data_share/frameworks/native/common/include/datashare_itypes_utils.h +++ b/data_share/frameworks/native/common/include/datashare_itypes_utils.h @@ -16,9 +16,12 @@ #ifndef DATASHARE_COMMON_ITYPES_UTIL_H #define DATASHARE_COMMON_ITYPES_UTIL_H +#include "dataproxy_handle_common.h" #include "datashare_operation_statement.h" +#include "datashare_common.h" #include "datashare_predicates.h" #include "datashare_template.h" +#include "datashare_value_object.h" #include "datashare_values_bucket.h" #include "itypes_util.h" #include "uri.h" @@ -40,6 +43,17 @@ using ExecResult = DataShare::ExecResult; using ExecResultSet = DataShare::ExecResultSet; using UpdateOperation = DataShare::UpdateOperation; using BatchUpdateResult = DataShare::BatchUpdateResult; +using DataShareProxyData = DataShare::DataShareProxyData; +using DataProxyConfig = DataShare::DataProxyConfig; +using DataProxyType = DataShare::DataProxyType; +using DataProxyResult = DataShare::DataProxyResult; +using DataProxyErrorCode = DataShare::DataProxyErrorCode; +using DataShareValueObject = DataShare::DataShareValueObject; +using DataProxyValue = DataShare::DataProxyValue; +using DataProxyGetResult = DataShare::DataProxyGetResult; +using DataProxyChangeInfo = DataShare::DataProxyChangeInfo; +using UriInfo = DataShare::UriInfo; +using RegisterOption = DataShare::RegisterOption; template<> bool Marshalling(const BatchUpdateResult &result, MessageParcel &parcel); @@ -159,5 +173,59 @@ bool UnmarshalPredicates(Predicates &predicates, MessageParcel &parcel); bool MarshalValuesBucketVec(const std::vector &values, MessageParcel &parcel); bool UnmarshalValuesBucketVec(std::vector &values, MessageParcel &parcel); + +template<> +bool Marshalling(const DataShareProxyData &proxyData, MessageParcel &parcel); + +template<> +bool Unmarshalling(DataShareProxyData &proxyData, MessageParcel &parcel); + +template<> +bool Marshalling(const DataProxyConfig &proxyData, MessageParcel &parcel); + +template<> +bool Unmarshalling(DataProxyConfig &proxyData, MessageParcel &parcel); + +template<> +bool Marshalling(const DataProxyResult &result, MessageParcel &parcel); + +template<> +bool Unmarshalling(DataProxyResult &result, MessageParcel &parcel); + +template<> +bool Marshalling(const DataShareValueObject &result, MessageParcel &parcel); + +template<> +bool Unmarshalling(DataShareValueObject &result, MessageParcel &parcel); + +template<> +bool Marshalling(const DataProxyValue &result, MessageParcel &parcel); + +template<> +bool Unmarshalling(DataProxyValue &result, MessageParcel &parcel); + +template<> +bool Marshalling(const DataProxyGetResult &result, MessageParcel &parcel); + +template<> +bool Unmarshalling(DataProxyGetResult &result, MessageParcel &parcel); + +template<> +bool Marshalling(const DataProxyChangeInfo &result, MessageParcel &parcel); + +template<> +bool Unmarshalling(DataProxyChangeInfo &result, MessageParcel &parcel); + +template<> +bool Marshalling(const UriInfo &result, MessageParcel &parcel); + +template<> +bool Unmarshalling(UriInfo &result, MessageParcel &parcel); + +template<> +bool Marshalling(const RegisterOption &option, MessageParcel &parcel); + +template<> +bool Unmarshalling(RegisterOption &option, MessageParcel &parcel); } #endif diff --git a/data_share/frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h b/data_share/frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h index 2b35d14c..87783892 100644 --- a/data_share/frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h +++ b/data_share/frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h @@ -41,7 +41,11 @@ enum class IDataShareInterfaceCode { CMD_INSERT_EX, CMD_UPDATE_EX, CMD_DELETE_EX, - CMD_USER_DEFINE_FUNC + CMD_USER_DEFINE_FUNC, + CMD_REGISTER_OBSERVEREXT_PROVIDER, + CMD_UNREGISTER_OBSERVEREXT_PROVIDER, + CMD_NOTIFY_CHANGEEXT_PROVIDER, + CMD_OPEN_FILE_WITH_ERR_CODE, }; enum class ISharedResultInterfaceCode { @@ -99,6 +103,11 @@ enum class DataShareServiceInterfaceCode { DATA_SHARE_SERVICE_CMD_INSERTEX, DATA_SHARE_SERVICE_CMD_DELETEEX, DATA_SHARE_SERVICE_CMD_UPDATEEX, + DATA_SHARE_SERVICE_CMD_PROXY_PUBLISH, + DATA_SHARE_SERVICE_CMD_PROXY_DELETE, + DATA_SHARE_SERVICE_CMD_PROXY_GET, + DATA_SHARE_SERVICE_CMD_SUBSCRIBE_PROXY_DATA, + DATA_SHARE_SERVICE_CMD_UNSUBSCRIBE_PROXY_DATA, DATA_SHARE_SERVICE_CMD_MAX, DATA_SHARE_SERVICE_CMD_QUERY_SYSTEM = DATA_SHARE_CMD_SYSTEM_CODE, DATA_SHARE_SERVICE_CMD_ADD_TEMPLATE_SYSTEM, diff --git a/data_share/frameworks/native/common/include/hitrace.h b/data_share/frameworks/native/common/include/hitrace.h index 11a09b7f..053c1bb0 100644 --- a/data_share/frameworks/native/common/include/hitrace.h +++ b/data_share/frameworks/native/common/include/hitrace.h @@ -26,12 +26,12 @@ class HiTrace final { public: inline HiTrace(const std::string &value) { - StartTrace(HITRACE_TAG_DISTRIBUTEDDATA, value); + StartTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_TAG_DISTRIBUTEDDATA, value.c_str(), ""); } inline ~HiTrace() { - FinishTrace(HITRACE_TAG_DISTRIBUTEDDATA); + FinishTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_TAG_DISTRIBUTEDDATA); } }; } // namespace DataShare diff --git a/data_share/frameworks/native/common/include/idata_share_service.h b/data_share/frameworks/native/common/include/idata_share_service.h index 538e1c0f..deb8c21a 100644 --- a/data_share/frameworks/native/common/include/idata_share_service.h +++ b/data_share/frameworks/native/common/include/idata_share_service.h @@ -22,12 +22,14 @@ #include "datashare_errno.h" #include "data_proxy_observer.h" #include "datashare_business_error.h" +#include "datashare_common.h" #include "datashare_predicates.h" #include "datashare_result_set.h" #include "datashare_template.h" #include "datashare_values_bucket.h" #include "distributeddata_data_share_ipc_interface_code.h" #include "uri.h" +#include "dataproxy_handle_common.h" namespace OHOS::DataShare { class IDataShareService : public IRemoteBroker { @@ -97,6 +99,20 @@ public: virtual std::pair DeleteEx(const Uri &uri, const Uri &extUri, const DataSharePredicates &predicates) = 0; + + virtual std::vector PublishProxyData(const std::vector &proxyData, + const DataProxyConfig &proxyConfig) = 0; + + virtual std::vector DeleteProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) = 0; + + virtual std::vector GetProxyData(const std::vector uris, + const DataProxyConfig &proxyConfig) = 0; + + virtual std::vector SubscribeProxyData(const std::vector &uris, + const sptr &observer) = 0; + + virtual std::vector UnsubscribeProxyData(const std::vector &uris) = 0; }; } // namespace OHOS::DataShare #endif diff --git a/data_share/frameworks/native/common/include/idatashare.h b/data_share/frameworks/native/common/include/idatashare.h index a5300a02..a64a3941 100644 --- a/data_share/frameworks/native/common/include/idatashare.h +++ b/data_share/frameworks/native/common/include/idatashare.h @@ -18,6 +18,7 @@ #include +#include "data_ability_observer_interface.h" #include "datashare_business_error.h" #include "datashare_operation_statement.h" #include "datashare_predicates.h" @@ -32,6 +33,7 @@ class IDataAbilityObserver; } namespace DataShare { +using ChangeInfo = AAFwk::ChangeInfo; class IDataShare : public IRemoteBroker { public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DataShare.IDataShare"); @@ -66,6 +68,14 @@ public: virtual bool NotifyChange(const Uri &uri) = 0; + virtual int RegisterObserverExtProvider(const Uri &uri, const sptr &dataObserver, + bool isDescendants, RegisterOption option) = 0; + + virtual int UnregisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver) = 0; + + virtual int NotifyChangeExtProvider(const ChangeInfo &changeInfo) = 0; + virtual Uri NormalizeUri(const Uri &uri) = 0; virtual Uri DenormalizeUri(const Uri &uri) = 0; diff --git a/data_share/frameworks/native/common/include/serializable.h b/data_share/frameworks/native/common/include/serializable.h new file mode 100644 index 00000000..49f3083f --- /dev/null +++ b/data_share/frameworks/native/common/include/serializable.h @@ -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. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_SERIALIZABLE_H +#define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_SERIALIZABLE_H +#include +#include +#include "visibility.h" +#ifndef JSON_NOEXCEPTION +#define JSON_NOEXCEPTION +#endif +#include +#include +namespace OHOS { +namespace DataShare { +#ifndef GET_NAME +#define GET_NAME(value) #value +#endif +struct Serializable { +public: + using json = nlohmann::json; + using size_type = nlohmann::json::size_type; + using error_handler_t = nlohmann::detail::error_handler_t; + + API_EXPORT json Marshall() const; + template + static std::string Marshall(T &values) + { + json root; + SetValue(root, values); + return root.dump(-1, ' ', false, error_handler_t::replace); + } + + API_EXPORT bool Unmarshall(const std::string &jsonStr); + template + static bool Unmarshall(const std::string &body, T &values) + { + return GetValue(ToJson(body), "", values); + } + API_EXPORT static json ToJson(const std::string &jsonStr); + API_EXPORT static bool IsJson(const std::string &jsonStr); + virtual bool Marshal(json &node) const = 0; + virtual bool Unmarshal(const json &node) = 0; + API_EXPORT static bool GetValue(const json &node, const std::string &name, std::string &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, uint32_t &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, int32_t &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, int64_t &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, uint64_t &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, uint16_t &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, bool &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, std::vector &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, Serializable &value); + API_EXPORT static bool SetValue(json &node, const std::string &value); + API_EXPORT static bool SetValue(json &node, const uint32_t &value); + API_EXPORT static bool SetValue(json &node, const int32_t &value); + API_EXPORT static bool SetValue(json &node, const int64_t &value); + API_EXPORT static bool SetValue(json &node, const double &value); + API_EXPORT static bool SetValue(json &node, const uint64_t &value); + API_EXPORT static bool SetValue(json &node, const uint16_t &value); + // Use bool & to forbid the const T * auto convert to bool, const bool will convert to const uint32_t &value; + template + API_EXPORT static std::enable_if_t, bool> SetValue(json &node, const T &value) + { + node = static_cast(value); + return true; + } + + API_EXPORT static bool SetValue(json &node, const std::vector &value); + API_EXPORT static bool SetValue(json &node, const Serializable &value); + + template + API_EXPORT static bool SetValue(json &node, const std::variant<_Types...> &input); + + template + API_EXPORT static bool GetValue(const json &node, const std::string &name, std::variant<_Types...> &value); +protected: + API_EXPORT ~Serializable() = default; + + template + static bool GetValue(const json &node, const std::string &name, std::vector &values); + + template + static bool SetValue(json &node, const std::vector &values); + + template + static bool GetValue(const json &node, const std::string &name, std::map &values); + + template + static bool SetValue(json &node, const std::map &values); + + template + static bool GetValue(const json &node, const std::string &name, T *&value); + + template + static bool SetValue(json &node, const T *value); + + template + static bool ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output); + + template + static bool ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output); + + template + static bool WriteVariant(json &node, uint32_t step, const _InTp &input); + + template + static bool WriteVariant(json &node, uint32_t step, const _InTp &input); + API_EXPORT static const json &GetSubNode(const json &node, const std::string &name); +}; + +template +bool Serializable::GetValue(const json &node, const std::string &name, std::vector &values) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_array()) { + return false; + } + bool result = true; + values.resize(subNode.size()); + for (size_type i = 0; i < subNode.size(); ++i) { + result = GetValue(subNode[i], "", values[i]) && result; + } + return result; +} + +template +bool Serializable::SetValue(json &node, const std::vector &values) +{ + bool result = true; + size_type i = 0; + node = json::value_t::array; + for (const auto &value : values) { + result = SetValue(node[i], value) && result; + i++; + } + return result; +} + +template +bool Serializable::GetValue(const json &node, const std::string &name, std::map &values) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_object()) { + return false; + } + bool result = true; + for (auto object = subNode.begin(); object != subNode.end(); ++object) { + result = GetValue(object.value(), "", values[object.key()]) && result; + } + return result; +} + +template +bool Serializable::SetValue(json &node, const std::map &values) +{ + bool result = true; + node = json::value_t::object; + for (const auto &[key, value] : values) { + result = SetValue(node[key], value) && result; + } + return result; +} + +template +bool Serializable::GetValue(const json &node, const std::string &name, T *&value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null()) { + return false; + } + value = new(std::nothrow) T(); + if (value == nullptr) { + return false; + } + bool result = GetValue(subNode, "", *value); + if (!result) { + delete value; + value = nullptr; + } + return result; +} + +template +bool Serializable::SetValue(json &node, const T *value) +{ + if (value == nullptr) { + return false; + } + return SetValue(node, *value); +} + +template +bool Serializable::SetValue(json &node, const std::variant<_Types...> &input) +{ + bool ret = SetValue(node[GET_NAME(type)], input.index()); + if (!ret) { + return ret; + } + return WriteVariant(node[GET_NAME(value)], 0, input); +} + +template +bool Serializable::GetValue(const json &node, const std::string &name, std::variant<_Types...> &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null()) { + return false; + } + uint32_t index; + bool ret = GetValue(subNode, GET_NAME(type), index); + if (!ret) { + return ret; + } + + return Serializable::ReadVariant(subNode, GET_NAME(value), 0, index, value); +} + +template +bool Serializable::WriteVariant(json &node, uint32_t step, const _InTp &input) +{ + return false; +} + +template +bool Serializable::ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output) +{ + if (step == index) { + _First result; + if (!Serializable::GetValue(node, name, result)) { + return false; + } + output = result; + return true; + } + return Serializable::ReadVariant<_OutTp, _Rest...>(node, name, step + 1, index, output); +} + +template +bool Serializable::WriteVariant(json &node, uint32_t step, const _InTp &input) +{ + if (step == input.index()) { + return Serializable::SetValue(node, std::get<_First>(input)); + } + return WriteVariant<_InTp, _Rest...>(node, step + 1, input); +} + +template +bool Serializable::ReadVariant(const json &node, const std::string &name, uint32_t step, uint32_t index, _OutTp &output) +{ + return false; +} +} // namespace DistributedData +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_SERIALIZABLE_H diff --git a/data_share/frameworks/native/common/src/call_reporter.cpp b/data_share/frameworks/native/common/src/call_reporter.cpp index af25b9e6..bf7bc657 100644 --- a/data_share/frameworks/native/common/src/call_reporter.cpp +++ b/data_share/frameworks/native/common/src/call_reporter.cpp @@ -21,20 +21,62 @@ namespace OHOS { namespace DataShare { -void DataShareCallReporter::Count(const std::string &funcName, const std::string &uri) +// count the func call and check if the funcCount exceeds the threshold +bool DataShareCallReporter::Count(const std::string &funcName, const std::string &uri) { int overCount = 0; int64_t firstCallTime = 0; - callCounts.Compute(funcName, [&overCount, &firstCallTime](auto &key, CallInfo &callInfo) { - auto callCount = callInfo.count; + // isOverThreshold means that the call count of the funcName over threshold, true means exceeded + // if exceeds the threshold, the current 30s time window will return 'true' + // and the funcCount will be reseted in the next 30s time window + bool isOverThreshold = false; + + UpdateCallCounts(funcName, overCount, firstCallTime, isOverThreshold); + + int64_t now = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count(); + if (overCount > 0) { + LOG_WARN("Call the threshold, func: %{public}s, first:%{public}" PRIi64 "ms, now:%{public}" PRIi64 + "ms, uri:%{public}s", funcName.c_str(), firstCallTime, now, DataShareStringUtils::Anonymous(uri).c_str()); + } + if (overCount > 1) { + LOG_WARN("Call too frequently, func: %{public}s, first:%{public}" PRIi64 "ms, now:%{public}" PRIi64 + "ms, uri:%{public}s", funcName.c_str(), firstCallTime, now, DataShareStringUtils::Anonymous(uri).c_str()); + } + // error log for over threshold and only print once + if (isOverThreshold) { + callCounts_.Compute(funcName, [funcName, now, uri](auto &key, CallInfo &callInfo) { + if (!callInfo.logPrintFlag) { + int64_t thresholdStartTime = std::chrono::duration_cast( + callInfo.startTime.time_since_epoch()).count(); + + callInfo.logPrintFlag = true; + LOG_ERROR("Over threshold, func: %{public}s, first:%{public}" PRIi64 "ms, now:%{public}" PRIi64 + "ms, uri:%{public}s", funcName.c_str(), thresholdStartTime, now, + DataShareStringUtils::Anonymous(uri).c_str()); + } + return true; + }); + } + return isOverThreshold; +} + +void DataShareCallReporter::UpdateCallCounts(const std::string &funcName, int &overCount, int64_t &firstCallTime, + bool &isOverThreshold) +{ + callCounts_.Compute(funcName, [&overCount, &firstCallTime, &isOverThreshold](auto &key, CallInfo &callInfo) { + int callCount = callInfo.count; + // totalCallCount is the call count of funcName in 30s + int totalCallCount = callInfo.totalCount; + std::chrono::system_clock::time_point nowTimeStamp = std::chrono::system_clock::now(); + int64_t now = std::chrono::duration_cast( + nowTimeStamp.time_since_epoch()).count(); if (callCount == 0) { - callInfo.firstTime = std::chrono::system_clock::now(); + callInfo.firstTime = nowTimeStamp; } if (++callCount % RESET_COUNT_THRESHOLD == 0) { int64_t first = std::chrono::duration_cast( callInfo.firstTime.time_since_epoch()).count(); - int64_t now = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count(); ++overCount; firstCallTime = first; if (now - first <= TIME_THRESHOLD.count()) { @@ -43,18 +85,27 @@ void DataShareCallReporter::Count(const std::string &funcName, const std::string callCount = 0; } callInfo.count = callCount; + + // update access control count + if (totalCallCount == 0) { + callInfo.startTime = nowTimeStamp; + } + int64_t thresholdStartTime = std::chrono::duration_cast( + callInfo.startTime.time_since_epoch()).count(); + // reset callInfo when time >= 30s + if (now - thresholdStartTime >= TIME_THRESHOLD.count()) { + callInfo.startTime = nowTimeStamp; + callInfo.totalCount = 0; + callInfo.logPrintFlag = false; + totalCallCount = 0; + } + // isOverThreshold return true when callCount >= 3000 in 30s + if (++totalCallCount >= ACCESS_COUNT_THRESHOLD) { + isOverThreshold = true; + } + callInfo.totalCount = totalCallCount; return true; }); - int64_t now = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count(); - if (overCount > 0) { - LOG_WARN("Call the threshold, func: %{public}s, first:%{public}" PRIi64 "ms, now:%{public}" PRIi64 - "ms, uri:%{public}s", funcName.c_str(), firstCallTime, now, DataShareStringUtils::Anonymous(uri).c_str()); - } - if (overCount > 1) { - LOG_WARN("Call too frequently, func: %{public}s, first:%{public}" PRIi64 "ms, now:%{public}" PRIi64 - "ms, uri:%{public}s", funcName.c_str(), firstCallTime, now, DataShareStringUtils::Anonymous(uri).c_str()); - } } } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/common/src/datashare_itypes_utils.cpp b/data_share/frameworks/native/common/src/datashare_itypes_utils.cpp index a59643b7..47f231f3 100644 --- a/data_share/frameworks/native/common/src/datashare_itypes_utils.cpp +++ b/data_share/frameworks/native/common/src/datashare_itypes_utils.cpp @@ -18,7 +18,11 @@ #include #include #include +#include +#include "dataproxy_handle_common.h" #include "datashare_log.h" +#include "datashare_value_object.h" +#include "itypes_util.h" namespace OHOS::ITypesUtil { using namespace OHOS::DataShare; @@ -296,6 +300,237 @@ bool Unmarshalling(ExecResultSet &execResultSet, MessageParcel &parcel) return ITypesUtil::Unmarshal(parcel, execResultSet.results); } +template<> +bool Marshalling(const DataShareProxyData &proxyData, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, proxyData.uri_, + proxyData.value_, proxyData.isValueUndefined, proxyData.allowList_, proxyData.isAllowListUndefined); +} + +template<> +bool Unmarshalling(DataShareProxyData &proxyData, MessageParcel &parcel) +{ + return ITypesUtil::Unmarshal(parcel, proxyData.uri_, + proxyData.value_, proxyData.isValueUndefined, proxyData.allowList_, proxyData.isAllowListUndefined); +} + +template<> +bool Marshalling(const DataProxyConfig &config, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, static_cast(config.type_)); +} + +template<> +bool Unmarshalling(DataProxyConfig &config, MessageParcel &parcel) +{ + int type; + if (!ITypesUtil::Unmarshalling(type, parcel)) { + return false; + } + config.type_ = static_cast(type); + return true; +} + +template<> +bool Marshalling(const DataProxyResult &result, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, static_cast(result.result_), result.uri_); +} + +template<> +bool Unmarshalling(DataProxyResult &result, MessageParcel &parcel) +{ + int errorCode; + if (!ITypesUtil::Unmarshalling(errorCode, parcel)) { + return false; + } + result.result_ = static_cast(errorCode); + return ITypesUtil::Unmarshal(parcel, result.uri_); +} + +template<> +bool Marshalling(const DataShareValueObject &value, MessageParcel &parcel) +{ + if (!ITypesUtil::Marshal(parcel, value.value.index())) { + return false; + } + switch (value.value.index()) { + case DataShareValueObjectType::TYPE_INT: { + return ITypesUtil::Marshal(parcel, std::get(value.value)); + } + case DataShareValueObjectType::TYPE_DOUBLE: { + return ITypesUtil::Marshal(parcel, std::get(value.value)); + } + case DataShareValueObjectType::TYPE_STRING: { + return ITypesUtil::Marshal(parcel, std::get(value.value)); + } + case DataShareValueObjectType::TYPE_BOOL: { + return ITypesUtil::Marshal(parcel, std::get(value.value)); + } + default: { + LOG_ERROR("Marshal ValueObject: unknown typeId"); + return false; + } + } +} + +template<> +bool Unmarshalling(DataShareValueObject &value, MessageParcel &parcel) +{ + int32_t index; + if (!ITypesUtil::Unmarshal(parcel, index)) { + return false; + } + bool ret = true; + switch (index) { + case static_cast(DataShareValueObjectType::TYPE_INT): { + int64_t val; + ret = ITypesUtil::Unmarshal(parcel, val); + value = val; + break; + } + case static_cast(DataShareValueObjectType::TYPE_DOUBLE): { + double val; + ret = ITypesUtil::Unmarshal(parcel, val); + value = val; + break; + } + case static_cast(DataShareValueObjectType::TYPE_STRING): { + std::string val; + ret = ITypesUtil::Unmarshal(parcel, val); + value = val; + break; + } + case static_cast(DataShareValueObjectType::TYPE_BOOL): { + bool val; + ret = ITypesUtil::Unmarshal(parcel, val); + value = val; + break; + } + default: { + LOG_ERROR("Unmarshal ValueObject: unknown typeId"); + ret = false; + } + } + return ret; +} + +template<> +bool Marshalling(const DataProxyValue &value, MessageParcel &parcel) +{ + int32_t index = value.index(); + if (!ITypesUtil::Marshal(parcel, index)) { + return false; + } + switch (value.index()) { + case static_cast(DataProxyValueType::VALUE_INT): { + return ITypesUtil::Marshal(parcel, std::get(value)); + } + case static_cast(DataProxyValueType::VALUE_DOUBLE): { + return ITypesUtil::Marshal(parcel, std::get(value)); + } + case static_cast(DataProxyValueType::VALUE_STRING): { + return ITypesUtil::Marshal(parcel, std::get(value)); + } + case static_cast(DataProxyValueType::VALUE_BOOL): { + return ITypesUtil::Marshal(parcel, std::get(value)); + } + default: { + LOG_ERROR("Marshal ValueObject: unknown typeId"); + return false; + } + } +} + +template<> +bool Unmarshalling(DataProxyValue &value, MessageParcel &parcel) +{ + int32_t index; + if (!ITypesUtil::Unmarshal(parcel, index)) { + return false; + } + bool ret = true; + switch (index) { + case static_cast(DataProxyValueType::VALUE_INT): { + int64_t val; + ret = ITypesUtil::Unmarshal(parcel, val); + value = val; + break; + } + case static_cast(DataProxyValueType::VALUE_DOUBLE): { + double val; + ret = ITypesUtil::Unmarshal(parcel, val); + value = val; + break; + } + case static_cast(DataProxyValueType::VALUE_STRING): { + std::string val; + ret = ITypesUtil::Unmarshal(parcel, val); + value = val; + break; + } + case static_cast(DataProxyValueType::VALUE_BOOL): { + bool val; + ret = ITypesUtil::Unmarshal(parcel, val); + value = val; + break; + } + default: { + LOG_ERROR("Unmarshal DataProxyValue: unknown typeId"); + ret = false; + } + } + return ret; +} + +template<> +bool Marshalling(const DataProxyGetResult &result, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, static_cast(result.result_), + result.uri_, result.value_, result.allowList_); +} + +template<> +bool Unmarshalling(DataProxyGetResult &result, MessageParcel &parcel) +{ + int errorCode; + if (!ITypesUtil::Unmarshalling(errorCode, parcel)) { + return false; + } + result.result_ = static_cast(errorCode); + return ITypesUtil::Unmarshal(parcel, result.uri_, result.value_, result.allowList_); +} + +template<> +bool Marshalling(const DataProxyChangeInfo &changeInfo, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, static_cast(changeInfo.changeType_), + changeInfo.uri_, changeInfo.value_); +} + +template<> +bool Unmarshalling(DataProxyChangeInfo &changeInfo, MessageParcel &parcel) +{ + int errorCode; + if (!ITypesUtil::Unmarshalling(errorCode, parcel)) { + return false; + } + changeInfo.changeType_ = static_cast(errorCode); + return ITypesUtil::Unmarshal(parcel, changeInfo.uri_, changeInfo.value_); +} + +template<> +bool Marshalling(const UriInfo &result, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, result.uri, result.extUri, result.option.timeout); +} + +template<> +bool Unmarshalling(UriInfo &result, MessageParcel &parcel) +{ + return ITypesUtil::Unmarshal(parcel, result.uri, result.extUri, result.option.timeout); +} + template bool MarshalBasicTypeToBuffer(std::ostringstream &oss, const T &value) { @@ -974,4 +1209,17 @@ bool UnmarshalValuesBucketVec(std::vector &values, Messag std::istringstream iss(std::string(buffer, length)); return UnmarshalValuesBucketVecToBuffer(iss, values); } + +template<> +bool Marshalling(const RegisterOption &option, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, option.isReconnect); +} + +template<> +bool Unmarshalling(RegisterOption &option, MessageParcel &parcel) +{ + return ITypesUtil::Unmarshal(parcel, option.isReconnect); +} + } // namespace OHOS::ITypesUtil \ No newline at end of file diff --git a/data_share/frameworks/native/common/src/datashare_predicates.cpp b/data_share/frameworks/native/common/src/datashare_predicates.cpp new file mode 100644 index 00000000..32f69212 --- /dev/null +++ b/data_share/frameworks/native/common/src/datashare_predicates.cpp @@ -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. + */ + +#include "datashare_predicates.h" +#include "datashare_itypes_utils.h" + +namespace OHOS { +namespace DataShare { + +bool DataSharePredicates::Unmarshal(DataSharePredicates &predicates, MessageParcel &parcel) +{ + return ITypesUtil::UnmarshalPredicates(predicates, parcel); +} + +bool DataSharePredicates::Marshal(const DataSharePredicates &predicates, MessageParcel &parcel) +{ + return ITypesUtil::MarshalPredicates(predicates, parcel); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/common/src/datashare_result_set.cpp b/data_share/frameworks/native/common/src/datashare_result_set.cpp index 19674183..f1368749 100644 --- a/data_share/frameworks/native/common/src/datashare_result_set.cpp +++ b/data_share/frameworks/native/common/src/datashare_result_set.cpp @@ -16,8 +16,6 @@ #include #include -#include -#include #include "adaptor.h" #include "datashare_block_writer_impl.h" @@ -26,13 +24,14 @@ #include "parcel.h" #include "shared_block.h" #include "string_ex.h" +#include "ishared_result_set.h" namespace OHOS { namespace DataShare { namespace { - // The default position of the cursor - static const int INITIAL_POS = -1; - static const size_t DEFAULT_SHARE_BLOCK_SIZE = 2 * 1024 * 1024; +// The default position of the cursor +static const int INITIAL_POS = -1; +static const size_t DEFAULT_SHARE_BLOCK_SIZE = 2 * 1024 * 1024; } // namespace int DataShareResultSet::blockId_ = 0; DataShareResultSet::DataShareResultSet() @@ -462,5 +461,18 @@ bool DataShareResultSet::Unmarshalling(MessageParcel &parcel) } return true; } -} // namespace DataShare -} // namespace OHOS \ No newline at end of file + +bool DataShareResultSet::Marshal(const std::shared_ptr resultSet, MessageParcel &parcel) +{ + if (resultSet == nullptr || !DataShare::ISharedResultSet::WriteToParcel(resultSet, parcel)) { + return false; + } + return true; +} + +std::shared_ptr DataShareResultSet::Unmarshal(MessageParcel &parcel) +{ + return DataShare::ISharedResultSet::ReadFromParcel(parcel); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/common/src/serializable.cpp b/data_share/frameworks/native/common/src/serializable.cpp new file mode 100644 index 00000000..31f58670 --- /dev/null +++ b/data_share/frameworks/native/common/src/serializable.cpp @@ -0,0 +1,234 @@ +/* + * 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 "serializable.h" +namespace OHOS { +namespace DataShare { +Serializable::json Serializable::Marshall() const +{ + json root; + Marshal(root); + return root; +} + +bool Serializable::Unmarshall(const std::string &jsonStr) +{ + json jsonObj = json::parse(jsonStr, nullptr, false); + if (jsonObj.is_discarded()) { + // if the string size is less than 1, means the string is invalid. + if (jsonStr.empty()) { + return false; + } + jsonObj = json::parse(jsonStr.substr(1), nullptr, false); // drop first char to adapt A's value; + if (jsonObj.is_discarded()) { + return false; + } + } + return Unmarshal(jsonObj); +} + +Serializable::json Serializable::ToJson(const std::string &jsonStr) +{ + json jsonObj = json::parse(jsonStr, nullptr, false); + if (jsonObj.is_discarded()) { + // if the string size is less than 1, means the string is invalid. + if (jsonStr.empty()) { + return {}; + } + jsonObj = json::parse(jsonStr.substr(1), nullptr, false); // drop first char to adapt A's value; + if (jsonObj.is_discarded()) { + return {}; + } + } + return jsonObj; +} + +bool Serializable::IsJson(const std::string &jsonStr) +{ + if (!json::accept(jsonStr)) { + return json::accept(jsonStr.begin() + 1, jsonStr.end()); + } + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, std::string &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_string()) { + return false; + } + value = subNode; + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, uint32_t &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_number_unsigned()) { + return false; + } + subNode.get_to(value); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, int32_t &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_number_integer()) { + return false; + } + subNode.get_to(value); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, int64_t &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_number_integer()) { + return false; + } + subNode.get_to(value); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, uint64_t &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_number_unsigned()) { + return false; + } + subNode.get_to(value); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, uint16_t &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_number_unsigned()) { + return false; + } + subNode.get_to(value); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, bool &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_boolean()) { + subNode.get_to(value); + return true; + } + + if (subNode.is_number_unsigned()) { + uint32_t number = 0; + subNode.get_to(number); + value = number != 0; + return true; + } + + return false; +} + +bool Serializable::GetValue(const json &node, const std::string &name, std::vector &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_array()) { + return false; + } + value = std::vector(subNode); + return true; +} + +bool Serializable::GetValue(const json &node, const std::string &name, Serializable &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_object()) { + return false; + } + return value.Unmarshal(subNode); +} + +bool Serializable::SetValue(json &node, const std::string &value) +{ + node = value; + return true; +} + +bool Serializable::SetValue(json &node, const uint32_t &value) +{ + node = value; + return true; +} + +bool Serializable::SetValue(json &node, const int32_t &value) +{ + node = value; + return true; +} + +bool Serializable::SetValue(json &node, const int64_t &value) +{ + node = value; + return true; +} + +bool Serializable::SetValue(json &node, const double &value) +{ + node = value; + return true; +} + +bool Serializable::SetValue(json &node, const uint64_t &value) +{ + node = value; + return true; +} + +bool Serializable::SetValue(json &node, const uint16_t &value) +{ + node = value; + return true; +} + +bool Serializable::SetValue(json &node, const std::vector &value) +{ + node = value; + return true; +} + +bool Serializable::SetValue(json &node, const Serializable &value) +{ + return value.Marshal(node); +} + +const Serializable::json &Serializable::GetSubNode(const json &node, const std::string &name) +{ + static const json jsonNull = json::value_t::null; + if (node.is_discarded() || node.is_null()) { + return jsonNull; + } + + if (name.empty()) { + return node; + } + + auto it = node.find(name); + if (it == node.end()) { + return jsonNull; + } + return *it; +} +} // namespace DistributedData +} // namespace OHOS diff --git a/data_share/frameworks/native/common/src/shared_block.cpp b/data_share/frameworks/native/common/src/shared_block.cpp index 2264f2ad..10d5e60c 100644 --- a/data_share/frameworks/native/common/src/shared_block.cpp +++ b/data_share/frameworks/native/common/src/shared_block.cpp @@ -66,7 +66,7 @@ bool SharedBlock::Init() int SharedBlock::CreateSharedBlock(const std::string &name, size_t size, sptr ashmem, SharedBlock *&outSharedBlock) { - outSharedBlock = new SharedBlock(name, ashmem, size, false); + outSharedBlock = new (std::nothrow)SharedBlock(name, ashmem, size, false); if (outSharedBlock == nullptr) { LOG_ERROR("CreateSharedBlock: new SharedBlock error."); return SHARED_BLOCK_BAD_VALUE; diff --git a/data_share/frameworks/native/consumer/controller/common/general_controller.h b/data_share/frameworks/native/consumer/controller/common/general_controller.h index 6a554b17..9af3945b 100644 --- a/data_share/frameworks/native/consumer/controller/common/general_controller.h +++ b/data_share/frameworks/native/consumer/controller/common/general_controller.h @@ -19,6 +19,7 @@ #include #include +#include "data_ability_observer_interface.h" #include "datashare_business_error.h" #include "datashare_errno.h" #include "datashare_predicates.h" @@ -32,6 +33,7 @@ class IDataAbilityObserver; } namespace DataShare { +using ChangeInfo = AAFwk::ChangeInfo; class GeneralController { public: virtual ~GeneralController() = default; @@ -43,7 +45,7 @@ public: virtual int Delete(const Uri &uri, const DataSharePredicates &predicates) = 0; virtual std::shared_ptr Query(const Uri &uri, const DataSharePredicates &predicates, - std::vector &columns, DatashareBusinessError &businessError) = 0; + std::vector &columns, DatashareBusinessError &businessError, DataShareOption &option) = 0; virtual int RegisterObserver(const Uri &uri, const sptr &dataObserver) = 0; @@ -51,6 +53,29 @@ public: virtual void NotifyChange(const Uri &uri) = 0; + /** + * Registers an observer specified by the given Uri to the provider. This function is supported only when using + * non-silent DataShareHelper, and there is no default implemention in the provider side. It needs to be handled by + * the user. Otherwise, the provider side will do nothing but simply return error. + */ + virtual int RegisterObserverExtProvider(const Uri &uri, const sptr &dataObserver, + bool isDescendants) = 0; + + /** + * Deregisters an observer specified by the given Uri to the provider. This function is supported only when using + * non-silent DataShareHelper, and there is no default implemention in the provider side. It needs to be handled by + * the user. Otherwise, the provider side will do nothing but simply return error. + */ + virtual int UnregisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver) = 0; + + /** + * Notifies the registered observers of a change to the data resource specified by Uris. This function is supported + * only when using non-silent DataShareHelper, and there is no default implemention in the provider side. It needs + * to be handled by the user. Otherwise, the provider side will do nothing but simply return true. + */ + virtual int NotifyChangeExtProvider(const ChangeInfo &changeInfo) = 0; + virtual std::pair InsertEx(const Uri &uri, const DataShareValuesBucket &value) = 0; virtual std::pair UpdateEx( diff --git a/data_share/frameworks/native/consumer/controller/provider/include/ext_special_controller.h b/data_share/frameworks/native/consumer/controller/provider/include/ext_special_controller.h index 547a9186..028378b2 100644 --- a/data_share/frameworks/native/consumer/controller/provider/include/ext_special_controller.h +++ b/data_share/frameworks/native/consumer/controller/provider/include/ext_special_controller.h @@ -31,6 +31,8 @@ public: int OpenFile(const Uri &uri, const std::string &mode); + int OpenFileWithErrCode(const Uri &uri, const std::string &mode, int32_t &errCode); + int OpenRawFile(const Uri &uri, const std::string &mode); int BatchUpdate(const UpdateOperations &operations, std::vector &results); diff --git a/data_share/frameworks/native/consumer/controller/provider/include/general_controller_provider_impl.h b/data_share/frameworks/native/consumer/controller/provider/include/general_controller_provider_impl.h index 04031a89..c2b9ce3e 100644 --- a/data_share/frameworks/native/consumer/controller/provider/include/general_controller_provider_impl.h +++ b/data_share/frameworks/native/consumer/controller/provider/include/general_controller_provider_impl.h @@ -17,6 +17,7 @@ #define GENERAL_CONTROLLER_PORVIDER_IMPL_H #include "datashare_connection.h" +#include "datashare_option.h" #include "general_controller.h" namespace OHOS { @@ -25,6 +26,7 @@ class IDataAbilityObserver; } namespace DataShare { +using ChangeInfo = AAFwk::ChangeInfo; class GeneralControllerProviderImpl : public GeneralController { public: GeneralControllerProviderImpl(std::shared_ptr connection, @@ -39,7 +41,7 @@ public: int Delete(const Uri &uri, const DataSharePredicates &predicates) override; std::shared_ptr Query(const Uri &uri, const DataSharePredicates &predicates, - std::vector &columns, DatashareBusinessError &businessError) override; + std::vector &columns, DatashareBusinessError &businessError, DataShareOption &option) override; int RegisterObserver(const Uri &uri, const sptr &dataObserver) override; @@ -54,6 +56,13 @@ public: std::pair DeleteEx(const Uri &uri, const DataSharePredicates &predicates) override; + int RegisterObserverExtProvider(const Uri &uri, const sptr &dataObserver, + bool isDescendants) override; + + int UnregisterObserverExtProvider(const Uri &uri, const sptr &dataObserver) override; + + int NotifyChangeExtProvider(const ChangeInfo &changeInfo) override; + private: std::shared_ptr connection_ = nullptr; sptr token_ = {}; diff --git a/data_share/frameworks/native/consumer/controller/provider/src/ext_special_controller.cpp b/data_share/frameworks/native/consumer/controller/provider/src/ext_special_controller.cpp index 97781b3b..0fd6780d 100644 --- a/data_share/frameworks/native/consumer/controller/provider/src/ext_special_controller.cpp +++ b/data_share/frameworks/native/consumer/controller/provider/src/ext_special_controller.cpp @@ -34,6 +34,21 @@ int ExtSpecialController::OpenFile(const Uri &uri, const std::string &mode) return proxy->OpenFile(uri, mode); } +int ExtSpecialController::OpenFileWithErrCode(const Uri &uri, const std::string &mode, int32_t &errCode) +{ + auto connection = connection_; + if (connection == nullptr) { + LOG_ERROR("connection is nullptr"); + return INVALID_VALUE; + } + auto proxy = connection->GetDataShareProxy(uri_, token_); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return INVALID_VALUE; + } + return proxy->OpenFileWithErrCode(uri, mode, errCode); +} + int ExtSpecialController::OpenRawFile(const Uri &uri, const std::string &mode) { auto connection = connection_; diff --git a/data_share/frameworks/native/consumer/controller/provider/src/general_controller_provider_impl.cpp b/data_share/frameworks/native/consumer/controller/provider/src/general_controller_provider_impl.cpp index fa19b05c..d15f60e9 100644 --- a/data_share/frameworks/native/consumer/controller/provider/src/general_controller_provider_impl.cpp +++ b/data_share/frameworks/native/consumer/controller/provider/src/general_controller_provider_impl.cpp @@ -115,8 +115,10 @@ std::pair GeneralControllerProviderImpl::DeleteEx(const Uri &u } std::shared_ptr GeneralControllerProviderImpl::Query(const Uri &uri, - const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError &businessError) + const DataSharePredicates &predicates, std::vector &columns, + DatashareBusinessError &businessError, DataShareOption &option) { + (void)option; auto connection = connection_; if (connection == nullptr) { LOG_ERROR("connection is nullptr"); @@ -143,7 +145,8 @@ int GeneralControllerProviderImpl::RegisterObserver(const Uri &uri, LOG_ERROR("proxy is nullptr"); return E_PROVIDER_NOT_CONNECTED; } - int ret = proxy->RegisterObserver(uri, dataObserver); + // the non-silent proxy's RegisterObserver returns bool while this function returns int and 0 means ok + int ret = proxy->RegisterObserver(uri, dataObserver) ? E_OK : E_REGISTER_ERROR; LOG_INFO("Register non-silent observer ret: %{public}d, uri: %{public}s", ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); return ret; @@ -162,7 +165,8 @@ int GeneralControllerProviderImpl::UnregisterObserver(const Uri &uri, LOG_ERROR("proxy is nullptr"); return E_PROVIDER_NOT_CONNECTED; } - int ret = proxy->UnregisterObserver(uri, dataObserver); + // the non-silent proxy's UnregisterObserver returns bool while this function returns int and 0 means ok + int ret = proxy->UnregisterObserver(uri, dataObserver) ? E_OK : E_REGISTER_ERROR; LOG_INFO("Unregister non-silent observer ret: %{public}d, uri: %{public}s", ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); return ret; @@ -183,6 +187,75 @@ void GeneralControllerProviderImpl::NotifyChange(const Uri &uri) proxy->NotifyChange(uri); } +// This function is supported only when using non-silent DataShareHelper +int GeneralControllerProviderImpl::RegisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver, bool isDescendants) +{ + auto connection = connection_; + if (connection == nullptr) { + LOG_ERROR("connection is nullptr"); + return E_PROVIDER_CONN_NULL; + } + auto proxy = connection->GetDataShareProxy(uri_, token_); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return E_PROVIDER_NOT_CONNECTED; + } + // the non-silent proxy's RegisterObserverExtProvider returns int and 0 means ok + int ret = proxy->RegisterObserverExtProvider(uri, dataObserver, isDescendants, { false }); + LOG_INFO("Register non-silent observerExt provider ret: %{public}d, uri: %{public}s", ret, + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + // store the observer when successfully registered. + if (ret == E_OK) { + connection->UpdateObserverExtsProviderMap(uri, dataObserver, isDescendants); + } + return ret; +} + +// This function is supported only when using non-silent DataShareHelper +int GeneralControllerProviderImpl::UnregisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver) +{ + auto connection = connection_; + if (connection == nullptr) { + LOG_ERROR("connection is nullptr"); + return E_PROVIDER_CONN_NULL; + } + auto proxy = connection->GetDataShareProxy(uri_, token_); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return E_PROVIDER_NOT_CONNECTED; + } + // the non-silent proxy's UnregisterObserverExtProvider returns int and 0 means ok + int ret = proxy->UnregisterObserverExtProvider(uri, dataObserver); + LOG_INFO("Unregister non-silent observerExt provider ret: %{public}d, uri: %{public}s", ret, + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + // remove the observer from storage when successfully unregistered. + if (ret == E_OK) { + connection->DeleteObserverExtsProviderMap(uri, dataObserver); + } + return ret; +} + +// This function is supported only when using non-silent DataShareHelper +int GeneralControllerProviderImpl::NotifyChangeExtProvider(const ChangeInfo &changeInfo) +{ + auto connection = connection_; + if (connection == nullptr) { + LOG_ERROR("connection is nullptr"); + return E_PROVIDER_CONN_NULL; + } + auto proxy = connection->GetDataShareProxy(uri_, token_); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return E_PROVIDER_NOT_CONNECTED; + } + // the non-silent proxy's NotifyChangeExtProvider returns int and 0 means ok + int ret = proxy->NotifyChangeExtProvider(changeInfo); + LOG_INFO("NotifyChangeExtProvider ret: %{public}d", ret); + return ret; +} + GeneralControllerProviderImpl::GeneralControllerProviderImpl(std::shared_ptr connection, const Uri &uri, const sptr &token) : connection_(connection), token_(token), uri_(uri) { diff --git a/data_share/frameworks/native/consumer/controller/service/include/general_controller_service_impl.h b/data_share/frameworks/native/consumer/controller/service/include/general_controller_service_impl.h index d4e9a918..f1c752db 100644 --- a/data_share/frameworks/native/consumer/controller/service/include/general_controller_service_impl.h +++ b/data_share/frameworks/native/consumer/controller/service/include/general_controller_service_impl.h @@ -20,6 +20,7 @@ #include "concurrent_map.h" #include "data_share_manager_impl.h" +#include "executor_pool.h" #include "general_controller.h" #include "uri.h" @@ -29,6 +30,18 @@ class IDataAbilityObserver; } namespace DataShare { +using ChangeInfo = AAFwk::ChangeInfo; + +struct TimedQueryResult { + bool isFinish_; + DatashareBusinessError businessError_; + std::shared_ptr resultSet_; + + explicit TimedQueryResult(bool isFinish, DatashareBusinessError businessError, + std::shared_ptr resultSet) : isFinish_(isFinish), + businessError_(businessError), resultSet_(resultSet) {} +}; + class GeneralControllerServiceImpl : public GeneralController { public: GeneralControllerServiceImpl(const std::string &ext); @@ -42,7 +55,7 @@ public: int Delete(const Uri &uri, const DataSharePredicates &predicates) override; std::shared_ptr Query(const Uri &uri, const DataSharePredicates &predicates, - std::vector &columns, DatashareBusinessError &businessError) override; + std::vector &columns, DatashareBusinessError &businessError, DataShareOption &option) override; int RegisterObserver(const Uri &uri, const sptr &dataObserver) override; @@ -50,6 +63,13 @@ public: void NotifyChange(const Uri &uri) override; + int RegisterObserverExtProvider(const Uri &uri, const sptr &dataObserver, + bool isDescendants) override; + + int UnregisterObserverExtProvider(const Uri &uri, const sptr &dataObserver) override; + + int NotifyChangeExtProvider(const ChangeInfo &changeInfo) override; + std::pair InsertEx(const Uri &uri, const DataShareValuesBucket &value) override; std::pair UpdateEx( @@ -62,10 +82,16 @@ private: void SetRegisterCallback(); + std::pair, DatashareBusinessError> TimedQuery( + std::shared_ptr proxy, const UriInfo ¶mSet, + const DataSharePredicates &predicates, const std::vector &columns); + ConcurrentMap, std::list> observers_; std::string extUri_; + std::shared_ptr pool_; + static constexpr int MAX_RETRY_COUNT = 3; static constexpr int RANDOM_MIN = 50; diff --git a/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp b/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp index 5b3a7064..41fdbfb0 100644 --- a/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp +++ b/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp @@ -16,6 +16,8 @@ #include "general_controller_service_impl.h" #include +#include "block_data.h" +#include "datashare_common.h" #include "dataobs_mgr_client.h" #include "dataobs_mgr_errors.h" #include "datashare_log.h" @@ -26,6 +28,7 @@ namespace DataShare { GeneralControllerServiceImpl::GeneralControllerServiceImpl(const std::string &ext) { extUri_ = ext; + pool_ = std::make_shared(MAX_THREADS, MIN_THREADS, DATASHARE_EXECUTOR_NAME); } GeneralControllerServiceImpl::~GeneralControllerServiceImpl() @@ -41,7 +44,10 @@ int GeneralControllerServiceImpl::Insert(const Uri &uri, const DataShareValuesBu LOG_ERROR("Manager is nullptr"); return DATA_SHARE_ERROR; } - manager->SetCallCount(__FUNCTION__, uri.ToString()); + // the ret of SetCallCount indicates whether the current call exceeds the access threshold, true means excced + if (manager->SetCallCount(__FUNCTION__, uri.ToString())) { + return DATA_SHARE_ERROR; + } auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); @@ -58,7 +64,10 @@ int GeneralControllerServiceImpl::Update(const Uri &uri, const DataSharePredicat LOG_ERROR("Manager is nullptr"); return DATA_SHARE_ERROR; } - manager->SetCallCount(__FUNCTION__, uri.ToString()); + // the ret of SetCallCount indicates whether the current call exceeds the access threshold, true means excced + if (manager->SetCallCount(__FUNCTION__, uri.ToString())) { + return DATA_SHARE_ERROR; + } auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); @@ -74,7 +83,10 @@ int GeneralControllerServiceImpl::Delete(const Uri &uri, const DataSharePredicat LOG_ERROR("Manager is nullptr"); return DATA_SHARE_ERROR; } - manager->SetCallCount(__FUNCTION__, uri.ToString()); + // the ret of SetCallCount indicates whether the current call exceeds the access threshold, true means excced + if (manager->SetCallCount(__FUNCTION__, uri.ToString())) { + return DATA_SHARE_ERROR; + } auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); @@ -90,7 +102,10 @@ std::pair GeneralControllerServiceImpl::InsertEx(const Uri &ur LOG_ERROR("Manager is nullptr"); return std::make_pair(DATA_SHARE_ERROR, 0); } - manager->SetCallCount(__FUNCTION__, uri.ToString()); + // the ret of SetCallCount indicates whether the current call exceeds the access threshold, true means excced + if (manager->SetCallCount(__FUNCTION__, uri.ToString())) { + return std::make_pair(DATA_SHARE_ERROR, 0); + } auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); @@ -107,7 +122,10 @@ std::pair GeneralControllerServiceImpl::UpdateEx( LOG_ERROR("Manager is nullptr"); return std::make_pair(DATA_SHARE_ERROR, 0); } - manager->SetCallCount(__FUNCTION__, uri.ToString()); + // the ret of SetCallCount indicates whether the current call exceeds the access threshold, true means excced + if (manager->SetCallCount(__FUNCTION__, uri.ToString())) { + return std::make_pair(DATA_SHARE_ERROR, 0); + } auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); @@ -124,7 +142,10 @@ std::pair GeneralControllerServiceImpl::DeleteEx(const Uri &ur LOG_ERROR("Manager is nullptr"); return std::make_pair(DATA_SHARE_ERROR, 0); } - manager->SetCallCount(__FUNCTION__, uri.ToString()); + // the ret of SetCallCount indicates whether the current call exceeds the access threshold, true means excced + if (manager->SetCallCount(__FUNCTION__, uri.ToString())) { + return std::make_pair(DATA_SHARE_ERROR, 0); + } auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); @@ -134,19 +155,36 @@ std::pair GeneralControllerServiceImpl::DeleteEx(const Uri &ur } std::shared_ptr GeneralControllerServiceImpl::Query(const Uri &uri, - const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError &businessError) + const DataSharePredicates &predicates, std::vector &columns, + DatashareBusinessError &businessError, DataShareOption &option) { auto manager = DataShareManagerImpl::GetInstance(); if (manager == nullptr) { LOG_ERROR("Manager is nullptr"); return nullptr; } - manager->SetCallCount(__FUNCTION__, uri.ToString()); + // the ret of SetCallCount indicates whether the current call exceeds the access threshold, true means excced + if (manager->SetCallCount(__FUNCTION__, uri.ToString())) { + return nullptr; + } auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return nullptr; } + + if (option.timeout > 0) { + UriInfo uriInfo = { + .uri = uri.ToString(), + .extUri = extUri_, + .option = { .timeout = option.timeout }, + }; + + auto [resultSet, err] = TimedQuery(proxy, uriInfo, predicates, columns); + businessError = err; + return resultSet; + } + auto resultSet = proxy->Query(uri, Uri(extUri_), predicates, columns, businessError); int retryCount = 0; while (resultSet == nullptr && businessError.GetCode() == E_RESULTSET_BUSY && retryCount++ < MAX_RETRY_COUNT) { @@ -172,7 +210,8 @@ int GeneralControllerServiceImpl::RegisterObserver(const Uri &uri, LOG_ERROR("get DataObsMgrClient failed"); return E_DATA_OBS_NOT_READY; } - ErrCode ret = obsMgrClient->RegisterObserver(uri, dataObserver); + bool isSystem = DataShareServiceProxy::IsSystem(); + ErrCode ret = obsMgrClient->RegisterObserver(uri, dataObserver, -1, AAFwk::DataObsOption(isSystem)); LOG_INFO("Register silent observer ret: %{public}d, uri: %{public}s", ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); return ret; @@ -186,7 +225,8 @@ int GeneralControllerServiceImpl::UnregisterObserver(const Uri &uri, LOG_ERROR("get DataObsMgrClient failed"); return E_DATA_OBS_NOT_READY; } - ErrCode ret = obsMgrClient->UnregisterObserver(uri, dataObserver); + bool isSystem = DataShareServiceProxy::IsSystem(); + ErrCode ret = obsMgrClient->UnregisterObserver(uri, dataObserver, -1, AAFwk::DataObsOption(isSystem)); LOG_INFO("Unregister silent observer ret: %{public}d, uri: %{public}s", ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); return ret; @@ -202,6 +242,26 @@ void GeneralControllerServiceImpl::NotifyChange(const Uri &uri) proxy->Notify(uri.ToString()); } +// This function is supported only when using non-silent DataShareHelper +int GeneralControllerServiceImpl::RegisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver, bool isDescendants) +{ + return DATA_SHARE_ERROR; +} + +// This function is supported only when using non-silent DataShareHelper +int GeneralControllerServiceImpl::UnregisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver) +{ + return DATA_SHARE_ERROR; +} + +// This function is supported only when using non-silent DataShareHelper +int GeneralControllerServiceImpl::NotifyChangeExtProvider(const ChangeInfo &changeInfo) +{ + return DATA_SHARE_ERROR; +} + void GeneralControllerServiceImpl::SetRegisterCallback() { auto manager = DataShareManagerImpl::GetInstance(); @@ -227,5 +287,49 @@ void GeneralControllerServiceImpl::ReRegisterObserver() return false; }); } + +std::pair, DatashareBusinessError> GeneralControllerServiceImpl::TimedQuery( + std::shared_ptr proxy, const UriInfo &uriInfo, + const DataSharePredicates &predicates, const std::vector &columns) +{ + DatashareBusinessError businessError; + if (pool_ == nullptr) { + LOG_ERROR("pool is nullptr"); + businessError.SetCode(E_EXECUTOR_POOL_IS_NULL); + businessError.SetMessage("pool is nullptr"); + return std::make_pair(nullptr, businessError); + } + + auto timedQueryResult = std::make_shared>( + uriInfo.option.timeout, TimedQueryResult{false, DatashareBusinessError(), nullptr}); + + auto task = [proxy, uriInfo, predicates, columns, timedQueryResult]() { + DatashareBusinessError businessError; + auto ncolumns = columns; + auto resultSet = proxy->Query(Uri(uriInfo.uri), Uri(uriInfo.extUri), predicates, + ncolumns, businessError); + int retryCount = 0; + while (resultSet == nullptr && businessError.GetCode() == E_RESULTSET_BUSY && retryCount++ < MAX_RETRY_COUNT) { + LOG_ERROR("resultSet busy retry, uri: %{public}s", DataShareStringUtils::Anonymous(uriInfo.uri).c_str()); + std::this_thread::sleep_for(std::chrono::milliseconds( + DataShareStringUtils::GetRandomNumber(RANDOM_MIN, RANDOM_MAX))); + resultSet = proxy->Query(Uri(uriInfo.uri), Uri(uriInfo.extUri), predicates, + ncolumns, businessError); + } + + timedQueryResult->SetValue(TimedQueryResult{true, businessError, std::move(resultSet)}); + }; + auto taskId = pool_->Execute(task); + auto res = timedQueryResult->GetValue(); + if (!res.isFinish_) { + LOG_ERROR("query time out, waited time: %{public}d, uri: %{public}s", uriInfo.option.timeout, + DataShareStringUtils::Anonymous(uriInfo.uri).c_str()); + pool_->Remove(taskId); + businessError.SetCode(E_TIMEOUT_ERROR); + businessError.SetMessage("query time out"); + return std::make_pair(nullptr, businessError); + } + return std::make_pair(res.resultSet_, res.businessError_); +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/consumer/include/datashare_connection.h b/data_share/frameworks/native/consumer/include/datashare_connection.h index 6e1fa996..5748f412 100644 --- a/data_share/frameworks/native/consumer/include/datashare_connection.h +++ b/data_share/frameworks/native/consumer/include/datashare_connection.h @@ -21,8 +21,8 @@ #include #include "ability_connect_callback_stub.h" +#include "data_ability_observer_interface.h" #include "datashare_proxy.h" -#include "event_handler.h" #include "executor_pool.h" #include "want.h" @@ -73,6 +73,11 @@ public: void SetConnectInvalid(); + void UpdateObserverExtsProviderMap(const Uri &uri, const sptr &dataObserver, + bool isDescendants); + + void DeleteObserverExtsProviderMap(const Uri &uri, const sptr &dataObserver); + private: struct DataShareConnectionInfo { int count = 0; @@ -81,13 +86,13 @@ private: }; struct ConnectCondition { std::condition_variable condition; - std::mutex mutex; }; std::shared_ptr ConnectDataShareExtAbility(const Uri &uri, const sptr &token); std::shared_ptr GetDataShareProxy(); ErrCode Disconnect(); void ReconnectExtAbility(const std::string &uri); void DelayConnectExtAbility(const std::string &uri); + void ReRegisterObserverExtProvider(); std::mutex mutex_{}; std::shared_ptr dataShareProxy_; ConnectCondition condition_; @@ -101,7 +106,16 @@ private: static constexpr std::chrono::milliseconds MAX_RECONNECT_TIME_INTERVAL = std::chrono::milliseconds(70000); std::shared_ptr pool_; DataShareConnectionInfo reConnects_; + struct Param { + Param(const Uri &uri, bool isDescendants) : uri(uri), isDescendants(isDescendants){}; + Uri uri; + bool isDescendants; + }; + // Store observers that have been successfully registered, allowing them to be re-registered during reconnection. + ConcurrentMap, std::list> observerExtsProvider_; int32_t waitTime_ = 0; + // An atomic variable used to identify the re-registration status. + std::atomic isReconnect_ = false; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/consumer/include/datashare_helper_impl.h b/data_share/frameworks/native/consumer/include/datashare_helper_impl.h index d26fc000..51bb7c92 100644 --- a/data_share/frameworks/native/consumer/include/datashare_helper_impl.h +++ b/data_share/frameworks/native/consumer/include/datashare_helper_impl.h @@ -16,6 +16,8 @@ #ifndef DATA_SHARE_HELPER_IMPL_H #define DATA_SHARE_HELPER_IMPL_H +#include "concurrent_map.h" +#include "data_ability_observer_stub.h" #include "datashare_helper.h" #include "ext_special_controller.h" #include "general_controller.h" @@ -23,6 +25,26 @@ #include "published_data_controller.h" namespace OHOS::DataShare { +class ObserverImpl : public AAFwk::DataAbilityObserverStub { +public: + explicit ObserverImpl(const std::shared_ptr dataShareObserver) + : dataShareObserver_(dataShareObserver){}; + void OnChange(); + void OnChangeExt(const AAFwk::ChangeInfo &info); + static DataShareObserver::ChangeInfo ConvertInfo(const AAFwk::ChangeInfo &info); + static AAFwk::ChangeInfo ConvertInfo(const DataShareObserver::ChangeInfo &info); + static sptr GetObserver(const Uri& uri, const std::shared_ptr &observer); + static bool FindObserver(const Uri& uri, const std::shared_ptr &observer); + static bool DeleteObserver(const Uri& uri, const std::shared_ptr &observer); +private: + struct ObserverParam { + sptr obs_; + std::list uris_; + }; + std::shared_ptr dataShareObserver_; + static ConcurrentMap observers_; +}; + class DataShareHelperImpl : public DataShareHelper { public: DataShareHelperImpl(const Uri &uri, const sptr &token, @@ -37,6 +59,8 @@ public: int OpenFile(Uri &uri, const string &mode) override; + int OpenFileWithErrCode(Uri &uri, const string &mode, int32_t &errCode) override; + int OpenRawFile(Uri &uri, const string &mode) override; int Insert(Uri &uri, const DataShareValuesBucket &value) override; @@ -52,6 +76,9 @@ public: std::shared_ptr Query(Uri &uri, const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError *businessError) override; + std::shared_ptr Query(Uri &uri, const DataSharePredicates &predicates, + std::vector &columns, DataShareOption &option, DatashareBusinessError *businessError) override; + string GetType(Uri &uri) override; int BatchInsert(Uri &uri, const std::vector &values) override; @@ -64,6 +91,13 @@ public: void NotifyChange(const Uri &uri) override; + int RegisterObserverExtProvider(const Uri &uri, std::shared_ptr dataObserver, + bool isDescendants) override; + + int UnregisterObserverExtProvider(const Uri &uri, std::shared_ptr dataObserver) override; + + void NotifyChangeExtProvider(const DataShareObserver::ChangeInfo &changeInfo) override; + Uri NormalizeUri(Uri &uri) override; Uri DenormalizeUri(Uri &uri) override; diff --git a/data_share/frameworks/native/consumer/include/datashare_proxy.h b/data_share/frameworks/native/consumer/include/datashare_proxy.h index 0a696e1a..f630763e 100644 --- a/data_share/frameworks/native/consumer/include/datashare_proxy.h +++ b/data_share/frameworks/native/consumer/include/datashare_proxy.h @@ -19,10 +19,13 @@ #include #include +#include "concurrent_map.h" +#include "dataobs_mgr_changeinfo.h" #include "idatashare.h" namespace OHOS { namespace DataShare { +using ChangeInfo = AAFwk::ChangeInfo; class DataShareProxy final : public IRemoteProxy { public: explicit DataShareProxy(const sptr& remote) : IRemoteProxy(remote) {} @@ -33,6 +36,8 @@ public: virtual int OpenFile(const Uri &uri, const std::string &mode) override; + int OpenFileWithErrCode(const Uri &uri, const std::string &mode, int32_t &errCode); + virtual int OpenRawFile(const Uri &uri, const std::string &mode) override; virtual int Insert(const Uri &uri, const DataShareValuesBucket &value) override; @@ -61,6 +66,14 @@ public: virtual bool NotifyChange(const Uri &uri) override; + virtual int RegisterObserverExtProvider(const Uri &uri, const sptr &dataObserver, + bool isDescendants, RegisterOption option) override; + + virtual int UnregisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver) override; + + virtual int NotifyChangeExtProvider(const ChangeInfo &changeInfo) override; + virtual Uri NormalizeUri(const Uri &uri) override; virtual Uri DenormalizeUri(const Uri &uri) override; @@ -77,6 +90,7 @@ public: private: bool CheckSize(const UpdateOperations &operations); + int OpenFileInner(const Uri &uri, const std::string &mode, uint32_t requestCode, int32_t &errCode); static inline BrokerDelegator delegator_; static const size_t MTU_SIZE = 921600; // 900k static const size_t MAX_SIZE = 4000; diff --git a/data_share/frameworks/native/consumer/src/dataproxy_handle.cpp b/data_share/frameworks/native/consumer/src/dataproxy_handle.cpp new file mode 100644 index 00000000..85fb58ca --- /dev/null +++ b/data_share/frameworks/native/consumer/src/dataproxy_handle.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "DataProxyHandle" + +#include +#include "dataproxy_handle.h" + +#include "adaptor.h" +#include "datashare_errno.h" +#include "datashare_log.h" +#include "data_share_manager_impl.h" +#include "proxy_data_subscriber_manager.h" + +namespace OHOS { +namespace DataShare { + +std::pair> DataProxyHandle::Create() +{ + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); + auto manager = DataShareManagerImpl::GetInstance(); + if (manager == nullptr) { + LOG_ERROR("Manager is nullptr"); + return std::make_pair(E_ERROR, nullptr); + } + if (DataShareManagerImpl::GetServiceProxy() == nullptr) { + LOG_ERROR("Service proxy is nullptr."); + return std::make_pair(E_ERROR, nullptr); + } + auto handler = std::make_shared(); + if (handler != nullptr) { + return std::make_pair(E_OK, handler); + } + return std::make_pair(E_ERROR, nullptr); +} + +std::vector DataProxyHandle::PublishProxyData( + const std::vector &proxyData, const DataProxyConfig &proxyConfig) +{ + auto proxy = DataShareManagerImpl::GetServiceProxy(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return std::vector(); + } + return proxy->PublishProxyData(proxyData, proxyConfig); +} + +std::vector DataProxyHandle::DeleteProxyData( + const std::vector &uris, const DataProxyConfig &proxyConfig) +{ + auto proxy = DataShareManagerImpl::GetServiceProxy(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return std::vector(); + } + return proxy->DeleteProxyData(uris, proxyConfig); +} + +std::vector DataProxyHandle::GetProxyData( + const std::vector uris, const DataProxyConfig &proxyConfig) +{ + auto proxy = DataShareManagerImpl::GetServiceProxy(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return std::vector(); + } + return proxy->GetProxyData(uris, proxyConfig); +} + +std::vector DataProxyHandle::SubscribeProxyData(const std::vector &uris, + const std::function &changeNode)> &callback) +{ + auto proxy = DataShareManagerImpl::GetServiceProxy(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return std::vector(); + } + return ProxyDataSubscriberManager::GetInstance().AddObservers(this, proxy, uris, callback); +} + +std::vector DataProxyHandle::UnsubscribeProxyData(const std::vector &uris) +{ + auto proxy = DataShareManagerImpl::GetServiceProxy(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return std::vector(); + } + return ProxyDataSubscriberManager::GetInstance().DelObservers(this, proxy, uris); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/consumer/src/datashare_connection.cpp b/data_share/frameworks/native/consumer/src/datashare_connection.cpp index a6080c1e..6a3419bc 100644 --- a/data_share/frameworks/native/consumer/src/datashare_connection.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_connection.cpp @@ -13,9 +13,11 @@ * limitations under the License. */ +#include #include "datashare_connection.h" #include "ams_mgr_proxy.h" +#include "datashare_common.h" #include "datashare_errno.h" #include "datashare_log.h" #include "datashare_proxy.h" @@ -25,6 +27,7 @@ namespace OHOS { namespace DataShare { using namespace AppExecFwk; +const std::chrono::milliseconds TIME_THRESHOLD = std::chrono::milliseconds(200); /** * @brief This method is called back to receive the connection result after an ability calls the * ConnectAbility method to connect it to an extension ability. @@ -57,6 +60,11 @@ void DataShareConnection::OnAbilityConnectDone( DataShareStringUtils::Change(element.GetURI()).c_str(), resultCode); Disconnect(); } + // re-register when re-connect successed + if (isReconnect_.load()) { + ReRegisterObserverExtProvider(); + isReconnect_.store(false); + } } /** @@ -85,7 +93,7 @@ void DataShareConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName if (pool_ == nullptr) { std::lock_guard lock(mutex_); if (pool_ == nullptr) { - pool_ = std::make_shared(MAX_THREADS, MIN_THREADS); + pool_ = std::make_shared(MAX_THREADS, MIN_THREADS, DATASHARE_EXECUTOR_NAME); } } ReconnectExtAbility(uri); @@ -107,6 +115,8 @@ void DataShareConnection::ReconnectExtAbility(const std::string &uri) reConnects_.count = 1; reConnects_.firstTime = std::chrono::duration_cast(curr).count(); reConnects_.prevTime = std::chrono::duration_cast(curr).count(); + // set status true + isReconnect_.store(true); } return; } @@ -145,6 +155,7 @@ void DataShareConnection::DelayConnectExtAbility(const std::string &uri) selfSharedPtr->reConnects_.count++; selfSharedPtr->reConnects_.prevTime = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()).count(); + selfSharedPtr->isReconnect_.store(true); } } }); @@ -156,6 +167,49 @@ void DataShareConnection::DelayConnectExtAbility(const std::string &uri) return; } +// store observer when it was successfully registered +void DataShareConnection::UpdateObserverExtsProviderMap(const Uri &uri, + const sptr &dataObserver, bool isDescendants) +{ + observerExtsProvider_.Compute(dataObserver, [&uri, isDescendants](const auto &key, auto &value) { + value.emplace_back(uri, isDescendants); + return true; + }); +} + +// remove observer when it was successfully unregistered +void DataShareConnection::DeleteObserverExtsProviderMap(const Uri &uri, + const sptr &dataObserver) +{ + observerExtsProvider_.Compute(dataObserver, [&uri](const auto &key, auto &value) { + value.remove_if([&uri](const auto ¶m) { + return uri == param.uri; + }); + return !value.empty(); + }); +} + +// re-register observer by dataShareProxy +void DataShareConnection::ReRegisterObserverExtProvider() +{ + LOG_INFO("ReRegisterObserverExtProvider start"); + decltype(observerExtsProvider_) observerExtsProvider(std::move(observerExtsProvider_)); + observerExtsProvider_.Clear(); + observerExtsProvider.ForEach([this](const auto &key, const auto &value) { + for (const auto ¶m : value) { + auto ret = dataShareProxy_->RegisterObserverExtProvider(param.uri, key, param.isDescendants, { true }); + if (ret != E_OK) { + LOG_ERROR( + "RegisterObserverExt failed, param.uri:%{public}s, ret:%{public}d, param.isDescendants:%{public}d", + DataShareStringUtils::Anonymous(param.uri.ToString()).c_str(), ret, param.isDescendants + ); + } else { + UpdateObserverExtsProviderMap(param.uri, key, param.isDescendants); + } + } + return false; + }); +} /** * @brief connect remote ability of DataShareExtAbility. */ @@ -181,14 +235,26 @@ std::shared_ptr DataShareConnection::ConnectDataShareExtAbility( if (ret != ERR_OK) { return nullptr; } - std::unique_lock condLock(condition_.mutex); + std::unique_lock condLock(mutex_); + std::shared_ptr proxy = dataShareProxy_; + if (proxy != nullptr) { + return proxy; + } + auto start = std::chrono::steady_clock::now(); if (condition_.condition.wait_for(condLock, std::chrono::seconds(waitTime_), [this] { return dataShareProxy_ != nullptr; })) { + auto finish = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(finish - start); + if (duration >= TIME_THRESHOLD) { + int64_t milliseconds = duration.count(); + LOG_WARN("over time connecting ability, uri:%{public}s, time:%{public}" PRIi64 "ms", + DataShareStringUtils::Change(reqUri).c_str(), milliseconds); + } LOG_DEBUG("connect ability ended successfully uri:%{public}s", DataShareStringUtils::Change(reqUri).c_str()); } else { LOG_WARN("connect timeout uri:%{public}s", DataShareStringUtils::Change(reqUri).c_str()); } - return GetDataShareProxy(); + return dataShareProxy_; } /** diff --git a/data_share/frameworks/native/consumer/src/datashare_helper.cpp b/data_share/frameworks/native/consumer/src/datashare_helper.cpp index f0243cb7..ef1dfa55 100644 --- a/data_share/frameworks/native/consumer/src/datashare_helper.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_helper.cpp @@ -18,9 +18,6 @@ #include "datashare_helper_impl.h" #include "adaptor.h" -#include "concurrent_map.h" -#include "data_ability_observer_interface.h" -#include "data_ability_observer_stub.h" #include "dataobs_mgr_client.h" #include "datashare_errno.h" #include "datashare_log.h" @@ -33,25 +30,6 @@ namespace { static constexpr const char *DATA_SHARE_PREFIX = "datashare:///"; static constexpr const char *FILE_PREFIX = "file://"; } // namespace -class ObserverImpl : public AAFwk::DataAbilityObserverStub { -public: - explicit ObserverImpl(const std::shared_ptr dataShareObserver) - : dataShareObserver_(dataShareObserver){}; - void OnChange(); - void OnChangeExt(const AAFwk::ChangeInfo &info); - static DataShareObserver::ChangeInfo ConvertInfo(const AAFwk::ChangeInfo &info); - static AAFwk::ChangeInfo ConvertInfo(const DataShareObserver::ChangeInfo &info); - static sptr GetObserver(const Uri& uri, const std::shared_ptr &observer); - static bool FindObserver(const Uri& uri, const std::shared_ptr &observer); - static bool DeleteObserver(const Uri& uri, const std::shared_ptr &observer); -private: - struct ObserverParam { - sptr obs_; - std::list uris_; - }; - std::shared_ptr dataShareObserver_; - static ConcurrentMap observers_; -}; ConcurrentMap ObserverImpl::observers_; @@ -82,7 +60,6 @@ std::shared_ptr DataShareHelper::Creator(const sptr helper = nullptr; @@ -111,8 +88,12 @@ std::shared_ptr DataShareHelper::Creator(const string &strUri, LOG_ERROR("token is nullptr"); return nullptr; } - return options.isProxy_ ? CreateServiceHelper("", bundleName, isSystem) - : CreateExtHelper(uri, options.token_, waitTime, isSystem); + if (options.isProxy_) { + int ret = GetSilentProxyStatus(strUri, isSystem); + return (ret == E_OK || ret == E_METADATA_NOT_EXISTS) ? CreateServiceHelper("", bundleName, isSystem) : nullptr; + } else { + return CreateExtHelper(uri, options.token_, waitTime, isSystem); + } } std::pair> DataShareHelper::Create(const sptr &token, @@ -219,7 +200,7 @@ std::shared_ptr DataShareHelper::CreateExtHelper(Uri &uri, cons * @param isDescendants, Indicates the Whether to note the change of descendants. */ void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptr dataObserver, - bool isDescendants) + bool isDescendants, bool isSystem) { if (dataObserver == nullptr) { LOG_ERROR("dataObserver is nullptr"); @@ -235,7 +216,7 @@ void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptrRegisterObserverExt(uri, obs, isDescendants); + ErrCode ret = obsMgrClient->RegisterObserverExt(uri, obs, isDescendants, AAFwk::DataObsOption(isSystem)); if (ret != ERR_OK) { ObserverImpl::DeleteObserver(uri, dataObserver); } @@ -249,7 +230,8 @@ void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptr dataObserver) +void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptr dataObserver, + bool isSystem) { if (dataObserver == nullptr) { LOG_ERROR("dataObserver is nullptr"); @@ -271,7 +253,7 @@ void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptrUnregisterObserverExt(uri, obs); + ErrCode ret = obsMgrClient->UnregisterObserverExt(uri, obs, AAFwk::DataObsOption(isSystem)); LOG_INFO("Unregister observerExt, ret:%{public}d, uri:%{public}s", ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); if (ret != ERR_OK) { @@ -285,7 +267,7 @@ void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptrNotifyChangeExt(ObserverImpl::ConvertInfo(changeInfo)); + ErrCode ret = obsMgrClient->NotifyChangeExt(ObserverImpl::ConvertInfo(changeInfo), + AAFwk::DataObsOption(isSystem)); LOG_INFO("Notify changeExt, ret:%{public}d", ret); } diff --git a/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp b/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp index a205f452..7674e001 100644 --- a/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp @@ -13,17 +13,16 @@ * limitations under the License. */ #define LOG_TAG "DataShareHelperImpl" - +#include #include "datashare_helper_impl.h" #include "adaptor.h" -#include "concurrent_map.h" -#include "data_ability_observer_interface.h" #include "dataobs_mgr_client.h" #include "datashare_log.h" +#include "datashare_string_utils.h" #include "datashare_radar_reporter.h" #include "datashare_result_set.h" - +#include "datashare_string_utils.h" #include "general_controller_provider_impl.h" #include "general_controller_service_impl.h" @@ -85,6 +84,16 @@ int DataShareHelperImpl::OpenFile(Uri &uri, const std::string &mode) return extSpCtl->OpenFile(uri, mode); } +int DataShareHelperImpl::OpenFileWithErrCode(Uri &uri, const std::string &mode, int32_t &errCode) +{ + auto extSpCtl = extSpCtl_; + if (extSpCtl == nullptr) { + LOG_ERROR("extSpCtl is nullptr"); + return DATA_SHARE_ERROR; + } + return extSpCtl->OpenFileWithErrCode(uri, mode, errCode); +} + int DataShareHelperImpl::OpenRawFile(Uri &uri, const std::string &mode) { auto extSpCtl = extSpCtl_; @@ -212,6 +221,26 @@ std::pair DataShareHelperImpl::DeleteEx(Uri &uri, const DataSh std::shared_ptr DataShareHelperImpl::Query(Uri &uri, const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError *businessError) +{ + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); + auto generalCtl = generalCtl_; + if (generalCtl == nullptr) { + LOG_ERROR("generalCtl is nullptr"); + return nullptr; + } + DataShareOption option; + DatashareBusinessError error; + DataShareServiceProxy::SetSystem(isSystem_); + auto resultSet = generalCtl->Query(uri, predicates, columns, error, option); + DataShareServiceProxy::CleanSystem(); + if (businessError != nullptr) { + *businessError = error; + } + return resultSet; +} + +std::shared_ptr DataShareHelperImpl::Query(Uri &uri, const DataSharePredicates &predicates, + std::vector &columns, DataShareOption &option, DatashareBusinessError *businessError) { DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); auto generalCtl = generalCtl_; @@ -221,7 +250,7 @@ std::shared_ptr DataShareHelperImpl::Query(Uri &uri, const D } DatashareBusinessError error; DataShareServiceProxy::SetSystem(isSystem_); - auto resultSet = generalCtl->Query(uri, predicates, columns, error); + auto resultSet = generalCtl->Query(uri, predicates, columns, error, option); DataShareServiceProxy::CleanSystem(); if (businessError != nullptr) { *businessError = error; @@ -275,7 +304,10 @@ int DataShareHelperImpl::RegisterObserver(const Uri &uri, const sptrRegisterObserver(uri, dataObserver); + DataShareServiceProxy::SetSystem(isSystem_); + int ret = generalCtl->RegisterObserver(uri, dataObserver); + DataShareServiceProxy::CleanSystem(); + return ret; } int DataShareHelperImpl::UnregisterObserver(const Uri &uri, const sptr &dataObserver) @@ -293,7 +325,10 @@ int DataShareHelperImpl::UnregisterObserver(const Uri &uri, const sptrUnregisterObserver(uri, dataObserver); + DataShareServiceProxy::SetSystem(isSystem_); + int ret = generalCtl->UnregisterObserver(uri, dataObserver); + DataShareServiceProxy::CleanSystem(); + return ret; } void DataShareHelperImpl::NotifyChange(const Uri &uri) @@ -310,6 +345,102 @@ void DataShareHelperImpl::NotifyChange(const Uri &uri) return; } +/** + * Registers an observer to DataObsMgr specified by the given Uri. Only non-silent is supported, and there is no + * default implemention for the provider. It needs to be handled by the user. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the DataShareObserver object. + * @param isDescendants, Indicates the Whether to note the change of descendants. + */ +int DataShareHelperImpl::RegisterObserverExtProvider(const Uri &uri, std::shared_ptr dataObserver, + bool isDescendants) +{ + if (dataObserver == nullptr) { + LOG_ERROR("dataObserver is nullptr"); + return E_NULL_OBSERVER; + } + sptr obs = ObserverImpl::GetObserver(uri, dataObserver); + if (obs == nullptr) { + LOG_ERROR("new ObserverImpl failed"); + return E_NULL_OBSERVER; + } + auto generalCtl = generalCtl_; + if (generalCtl == nullptr) { + LOG_ERROR("generalCtl is nullptr"); + return E_HELPER_DIED; + } + DataShareServiceProxy::SetSystem(isSystem_); + // only support non-silent access + ErrCode ret = generalCtl->RegisterObserverExtProvider(uri, obs, isDescendants); + DataShareServiceProxy::CleanSystem(); + LOG_INFO("Register observerExt, ret:%{public}d, uri:%{public}s", + ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + if (ret != E_OK) { + ObserverImpl::DeleteObserver(uri, dataObserver); + } + return ret; +} + +/** + * Deregisters an observer used for DataObsMgr specified by the given Uri. Only non-silent is supported, and there is + * no default implemention for the provider. It needs to be handled by the user. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the DataShareObserver object. + */ +int DataShareHelperImpl::UnregisterObserverExtProvider(const Uri &uri, std::shared_ptr dataObserver) +{ + if (dataObserver == nullptr) { + LOG_ERROR("dataObserver is nullptr"); + return E_NULL_OBSERVER; + } + if (!ObserverImpl::FindObserver(uri, dataObserver)) { + LOG_ERROR("observer not exit!"); + return E_NULL_OBSERVER; + } + sptr obs = ObserverImpl::GetObserver(uri, dataObserver); + if (obs == nullptr) { + LOG_ERROR("new ObserverImpl failed"); + return E_NULL_OBSERVER; + } + auto generalCtl = generalCtl_; + if (generalCtl == nullptr) { + LOG_ERROR("generalCtl is nullptr"); + return E_HELPER_DIED; + } + DataShareServiceProxy::SetSystem(isSystem_); + // only support non-silent access + ErrCode ret = generalCtl->UnregisterObserverExtProvider(uri, obs); + DataShareServiceProxy::CleanSystem(); + if (ret != E_OK) { + return ret; + } + ObserverImpl::DeleteObserver(uri, dataObserver); + return E_OK; +} + +/** + * Notifies the registered observers of a change to the data resource specified by Uris. Only non-silent is supported, + * and there is no default implemention for the provider. It needs to be handled by the user. + * + * @param changeInfo Indicates the info of the data to operate. + */ +void DataShareHelperImpl::NotifyChangeExtProvider(const DataShareObserver::ChangeInfo &changeInfo) +{ + auto generalCtl = generalCtl_; + if (generalCtl == nullptr) { + LOG_ERROR("extSpCtl is nullptr"); + return; + } + DataShareServiceProxy::SetSystem(isSystem_); + // only support non-silent access + ErrCode ret = generalCtl->NotifyChangeExtProvider(ObserverImpl::ConvertInfo(changeInfo)); + DataShareServiceProxy::CleanSystem(); + LOG_INFO("Notify changeExt, ret:%{public}d", ret); + return; +} + Uri DataShareHelperImpl::NormalizeUri(Uri &uri) { DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); @@ -432,6 +563,12 @@ std::vector DataShareHelperImpl::EnableRdbSubs(const std::vecto const TemplateId &templateId) { LOG_DEBUG("Start EnableSubscribeRdbData"); + std::string uriAll = ""; + for (auto uri : uris) { + uriAll += (DataShareStringUtils::Anonymous(uri) + ","); + } + LOG_INFO("uri is %{public}s bundleName is %{public}s, subscriberId is %{public}" PRId64 "", + DataShareStringUtils::Anonymous(uriAll).c_str(), templateId.bundleName_.c_str(), templateId.subscriberId_); auto persistentDataCtl = persistentDataCtl_; if (persistentDataCtl == nullptr) { LOG_ERROR("persistentDataCtl is nullptr"); @@ -447,6 +584,12 @@ std::vector DataShareHelperImpl::DisableRdbSubs(const std::vect const TemplateId &templateId) { LOG_DEBUG("Start DisableSubscribeRdbData"); + std::string uriAll = ""; + for (auto uri : uris) { + uriAll += (DataShareStringUtils::Anonymous(uri) + ","); + } + LOG_INFO("uri is %{public}s bundleName is %{public}s, subscriberId is %{public}" PRId64 "", + DataShareStringUtils::Anonymous(uriAll).c_str(), templateId.bundleName_.c_str(), templateId.subscriberId_); auto persistentDataCtl = persistentDataCtl_; if (persistentDataCtl == nullptr) { LOG_ERROR("persistentDataCtl is nullptr"); @@ -498,6 +641,12 @@ std::vector DataShareHelperImpl::EnablePubSubs(const std::vecto int64_t subscriberId) { LOG_DEBUG("Start enablePubSubs"); + std::string uriAll = ""; + for (auto uri : uris) { + uriAll += (DataShareStringUtils::Anonymous(uri) + ","); + } + LOG_INFO("uri is %{public}s subscriberId is %{public}" PRId64 "", + DataShareStringUtils::Anonymous(uriAll).c_str(), subscriberId); auto publishedDataCtl = publishedDataCtl_; if (publishedDataCtl == nullptr) { LOG_ERROR("publishedDataCtl is nullptr"); @@ -513,6 +662,12 @@ std::vector DataShareHelperImpl::DisablePubSubs(const std::vect int64_t subscriberId) { LOG_DEBUG("Start disablePubSubs"); + std::string uriAll = ""; + for (auto uri : uris) { + uriAll += (DataShareStringUtils::Anonymous(uri) + ","); + } + LOG_INFO("uri is %{public}s subscriberId is %{public}" PRId64 "", + DataShareStringUtils::Anonymous(uriAll).c_str(), subscriberId); auto publishedDataCtl = publishedDataCtl_; if (publishedDataCtl == nullptr) { LOG_ERROR("publishedDataCtl is nullptr"); diff --git a/data_share/frameworks/native/consumer/src/datashare_proxy.cpp b/data_share/frameworks/native/consumer/src/datashare_proxy.cpp index 8ce36b32..37bddd73 100644 --- a/data_share/frameworks/native/consumer/src/datashare_proxy.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_proxy.cpp @@ -67,7 +67,7 @@ std::vector DataShareProxy::GetFileTypes(const Uri &uri, const std: return types; } -int DataShareProxy::OpenFile(const Uri &uri, const std::string &mode) +int DataShareProxy::OpenFileInner(const Uri &uri, const std::string &mode, uint32_t requestCode, int32_t &errCode) { int fd = -1; MessageParcel data; @@ -88,10 +88,10 @@ int DataShareProxy::OpenFile(const Uri &uri, const std::string &mode) MessageParcel reply; MessageOption option; - int32_t err = Remote()->SendRequest( - static_cast(IDataShareInterfaceCode::CMD_OPEN_FILE), data, reply, option); + int32_t err = Remote()->SendRequest(requestCode, data, reply, option); if (err != E_OK) { LOG_ERROR("OpenFile fail to SendRequest. err: %{public}d", err); + errCode = err; return fd; } @@ -104,6 +104,19 @@ int DataShareProxy::OpenFile(const Uri &uri, const std::string &mode) return fd; } +int DataShareProxy::OpenFile(const Uri &uri, const std::string &mode) +{ + int32_t errCode = 0; + uint32_t requestCode = static_cast(IDataShareInterfaceCode::CMD_OPEN_FILE); + return OpenFileInner(uri, mode, requestCode, errCode); +} + +int DataShareProxy::OpenFileWithErrCode(const Uri &uri, const std::string &mode, int32_t &errCode) +{ + uint32_t requestCode = static_cast(IDataShareInterfaceCode::CMD_OPEN_FILE_WITH_ERR_CODE); + return OpenFileInner(uri, mode, requestCode, errCode); +} + int DataShareProxy::OpenRawFile(const Uri &uri, const std::string &mode) { int fd = -1; @@ -246,8 +259,8 @@ int DataShareProxy::BatchUpdate(const UpdateOperations &operations, std::vector< int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_BATCH_UPDATE), data, reply, option); if (err != E_OK) { - LOG_ERROR("fail to SendRequest. err: %{public}d", err); - return err; + LOG_ERROR("BatchUpdate fail to SendRequest. err: %{public}d", err); + return err == PERMISSION_ERR ? PERMISSION_ERR_CODE : ret; } if (!ITypesUtil::Unmarshal(reply, results)) { LOG_ERROR("fail to Unmarshal result"); @@ -385,14 +398,17 @@ std::shared_ptr DataShareProxy::Query(const Uri &uri, const MessageParcel data; if (!data.WriteInterfaceToken(DataShareProxy::GetDescriptor())) { LOG_ERROR("WriteInterfaceToken failed"); + businessError.SetCode(E_WRITE_TO_PARCE_ERROR); return nullptr; } if (!ITypesUtil::Marshal(data, uri, columns)) { LOG_ERROR("Marshalling uri and columns to data failed"); + businessError.SetCode(E_MARSHAL_ERROR); return nullptr; } if (!ITypesUtil::MarshalPredicates(predicates, data)) { LOG_ERROR("Marshalling predicates to shared-memory failed"); + businessError.SetCode(E_MARSHAL_ERROR); return nullptr; } MessageParcel reply; @@ -400,12 +416,13 @@ std::shared_ptr DataShareProxy::Query(const Uri &uri, const int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_QUERY), data, reply, option); auto result = ISharedResultSet::ReadFromParcel(reply); - businessError.SetCode(reply.ReadInt32()); - businessError.SetMessage(reply.ReadString()); if (err != E_OK) { LOG_ERROR("Query fail to SendRequest. err: %{public}d", err); + businessError.SetCode(err); return nullptr; } + businessError.SetCode(reply.ReadInt32()); + businessError.SetMessage(reply.ReadString()); return result; } @@ -524,7 +541,8 @@ bool DataShareProxy::RegisterObserver(const Uri &uri, const sptr &dataObserver) @@ -547,7 +565,8 @@ bool DataShareProxy::UnregisterObserver(const Uri &uri, const sptr &dataObserver, + bool isDescendants, RegisterOption registerOption) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(DataShareProxy::GetDescriptor())) { + LOG_ERROR("WriteInterfaceToken failed"); + return E_WRITE_TO_PARCE_ERROR; + } + + if (!ITypesUtil::Marshal(data, uri, dataObserver->AsObject(), isDescendants, registerOption)) { + LOG_ERROR("fail to Marshalling"); + return E_MARSHAL_ERROR; + } + + MessageParcel reply; + MessageOption option; + int32_t result = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_REGISTER_OBSERVEREXT_PROVIDER), data, reply, option); + if (result != ERR_NONE) { + LOG_ERROR("SendRequest error, result=%{public}d", result); + return DATA_SHARE_ERROR; + } + // the stub write int value to reply + return reply.ReadInt32(); +} + +// send IPC request, and there is no default implemention for the provider. It needs to be handled by the user. +int DataShareProxy::UnregisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(DataShareProxy::GetDescriptor())) { + LOG_ERROR("WriteInterfaceToken failed"); + return E_WRITE_TO_PARCE_ERROR; + } + + if (!ITypesUtil::Marshal(data, uri, dataObserver->AsObject())) { + LOG_ERROR("fail to Marshalling"); + return E_MARSHAL_ERROR; + } + + MessageParcel reply; + MessageOption option; + int32_t result = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_UNREGISTER_OBSERVEREXT_PROVIDER), data, reply, option); + if (result != ERR_NONE) { + LOG_ERROR("SendRequest error, result=%{public}d", result); + return DATA_SHARE_ERROR; + } + // the stub writeint value to reply + return reply.ReadInt32(); +} + +// send IPC request, and there is no default implemention for the provider. It needs to be handled by the user. +int DataShareProxy::NotifyChangeExtProvider(const ChangeInfo &changeInfo) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(DataShareProxy::GetDescriptor())) { + LOG_ERROR("WriteInterfaceToken failed"); + return E_WRITE_TO_PARCE_ERROR; + } + if (!ChangeInfo::Marshalling(changeInfo, data)) { + LOG_ERROR("changeInfo marshalling failed, changeType:%{public}ud, num:%{public}zu," + "null data:%{public}d, size:%{public}ud", + changeInfo.changeType_, changeInfo.uris_.size(), changeInfo.data_ == nullptr, changeInfo.size_); + return E_MARSHAL_ERROR; + } + + MessageParcel reply; + MessageOption option; + int32_t result = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_NOTIFY_CHANGEEXT_PROVIDER), data, reply, option); + if (result != ERR_NONE) { + LOG_ERROR("SendRequest error, result=%{public}d", result); + return DATA_SHARE_ERROR; + } + // the stub write int value to reply + return reply.ReadInt32(); +} + Uri DataShareProxy::NormalizeUri(const Uri &uri) { MessageParcel data; @@ -643,15 +743,14 @@ bool DataShareProxy::CheckSize(const UpdateOperations &operations) } return true; } + int32_t DataShareProxy::UserDefineFunc( MessageParcel &data, MessageParcel &reply, MessageOption &option) { - int32_t errCode = -1; int32_t err = Remote()->SendRequest( static_cast(IDataShareInterfaceCode::CMD_USER_DEFINE_FUNC), data, reply, option); if (err != E_OK) { - LOG_ERROR("UserDefineFunc fail to SendRequest. err: %{public}d", err); - return err == PERMISSION_ERR ? PERMISSION_ERR_CODE : errCode; + LOG_ERROR("UserDefineFunc SendRequest fails. err: %{public}d", err); } return err; } diff --git a/data_share/frameworks/native/dfx/include/hiview_datashare.h b/data_share/frameworks/native/dfx/include/hiview_datashare.h new file mode 100644 index 00000000..a3f5b7df --- /dev/null +++ b/data_share/frameworks/native/dfx/include/hiview_datashare.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 DATASHARESERVICE_HIVIEW_ADAPTER_H +#define DATASHARESERVICE_HIVIEW_ADAPTER_H + +#include "executor_pool.h" +#include "hisysevent_c.h" + +namespace OHOS { +namespace DataShare { + +struct DataShareFaultInfo { + std::string faultType; + std::string bundleName; + std::string moduleName; + std::string storeName; + std::string businessType; + int32_t errorCode; + std::string appendix; +}; + +class HiViewFaultAdapter { +public: + static constexpr const char* extensionFailed = "EXT_FAILED"; + static constexpr const char* silentFailed = "SILENT_FAILED"; + static constexpr const char* trustsFailed = "TRUSTS_FAILED"; + static void ReportDataFault(const DataShareFaultInfo &faultInfo); + static std::pair GetCallingName(uint32_t callingTokenid); +}; + +} // namespace DataShare +} // namespace OHOS +#endif // DATASHARESERVICE_HIVIEW_ADAPTER_H \ No newline at end of file diff --git a/data_share/frameworks/native/dfx/src/hiview_datashare.cpp b/data_share/frameworks/native/dfx/src/hiview_datashare.cpp new file mode 100644 index 00000000..f73cc875 --- /dev/null +++ b/data_share/frameworks/native/dfx/src/hiview_datashare.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. +*/ +#define LOG_TAG "HiViewAdapter" + +#include "hiview_datashare.h" + +#include +#include +#include +#include "access_token.h" +#include "accesstoken_kit.h" +#include "log_print.h" + +namespace OHOS { +namespace DataShare { + +using namespace std::chrono; + +namespace { + constexpr char DOMAIN[] = "DISTDATAMGR"; + constexpr const char *EVENT_NAME = "DISTRIBUTED_DATA_SHARE_FAULT"; + constexpr const size_t PARAMS_SIZE = 8; + // digits for milliseconds + constexpr uint8_t MILLSECOND_DIGIT = 3; +} + +void HiViewFaultAdapter::ReportDataFault(const DataShareFaultInfo &faultInfo) +{ + auto now = std::chrono::system_clock::now(); + auto t = std::chrono::system_clock::to_time_t(now); + std::stringstream ss; + ss << std::put_time(std::localtime(&t), "%F %T"); + // get milliseconds + auto ms = std::chrono::duration_cast(now.time_since_epoch()) % 1000; + ss << '.' << std::setfill('0') << std::setw(MILLSECOND_DIGIT) << ms.count(); + auto time = ss.str(); + HiSysEventParam faultTime = { .name = "FAULT_TIME", .t = HISYSEVENT_STRING, + .v = { .s = const_cast(time.c_str()) }, .arraySize = 0 }; + HiSysEventParam faultType = { .name = "FAULT_TYPE", .t = HISYSEVENT_STRING, + .v = { .s = const_cast(faultInfo.faultType.c_str()) }, .arraySize = 0 }; + HiSysEventParam bundleName = { .name = "BUNDLE_NAME", .t = HISYSEVENT_STRING, + .v = { .s = const_cast(faultInfo.bundleName.c_str()) }, .arraySize = 0 }; + HiSysEventParam moduleName = { .name = "MODULE_NAME", .t = HISYSEVENT_STRING, + .v = { .s = const_cast(faultInfo.moduleName.c_str()) }, .arraySize = 0 }; + HiSysEventParam storeName = { .name = "STORE_NAME", .t = HISYSEVENT_STRING, + .v = { .s = const_cast(faultInfo.storeName.c_str()) }, .arraySize = 0 }; + HiSysEventParam businessType = { .name = "BUSINESS_TYPE", .t = HISYSEVENT_STRING, + .v = { .s = const_cast(faultInfo.businessType.c_str()) }, .arraySize = 0 }; + HiSysEventParam errorCode = { .name = "ERROR_CODE", .t = HISYSEVENT_INT32, + .v = { .i32 = faultInfo.errorCode }, .arraySize = 0 }; + HiSysEventParam appendix = { .name = "APPENDIX", .t = HISYSEVENT_STRING, + .v = { .s = const_cast(faultInfo.appendix.c_str()) }, .arraySize = 0 }; + HiSysEventParam params[] = { faultTime, faultType, bundleName, moduleName, + storeName, businessType, errorCode, appendix }; + int res = OH_HiSysEvent_Write(DOMAIN, EVENT_NAME, HISYSEVENT_FAULT, params, PARAMS_SIZE); + if (res != 0) { + ZLOGI("OH_HiSysEvent_Write fail, res = %{public}d", res); + } +} + +std::pair HiViewFaultAdapter::GetCallingName(uint32_t callingTokenid) +{ + std::string callingName; + auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(callingTokenid); + int result = -1; + if (tokenType == Security::AccessToken::TOKEN_HAP) { + Security::AccessToken::HapTokenInfo tokenInfo; + result = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(callingTokenid, tokenInfo); + if (result == Security::AccessToken::RET_SUCCESS) { + callingName = tokenInfo.bundleName; + } + } else if (tokenType == Security::AccessToken::TOKEN_NATIVE || tokenType == Security::AccessToken::TOKEN_SHELL) { + Security::AccessToken::NativeTokenInfo tokenInfo; + result = Security::AccessToken::AccessTokenKit::GetNativeTokenInfo(callingTokenid, tokenInfo); + if (result == Security::AccessToken::RET_SUCCESS) { + callingName = tokenInfo.processName; + } + } else { + ZLOGE("tokenType is invalid, tokenType:%{public}d, Tokenid:%{public}x", tokenType, callingTokenid); + } + return std::make_pair(callingName, result); +} + +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/permission/include/data_share_called_config.h b/data_share/frameworks/native/permission/include/data_share_called_config.h index c265c3f2..4000536b 100644 --- a/data_share/frameworks/native/permission/include/data_share_called_config.h +++ b/data_share/frameworks/native/permission/include/data_share_called_config.h @@ -32,19 +32,25 @@ public: struct ProviderInfo { std::string uri; + std::string schema; std::string bundleName; std::string moduleName; std::string readPermission; std::string writePermission; int32_t currentUserId = -1; + bool isExtension = false; }; - std::pair GetProviderInfo(uint32_t tokenId); + std::pair GetProviderInfo(int32_t user); + static std::pair GetBundleInfoFromBMS(std::string bundleName, int32_t user); + static std::pair GetExtensionInfoFromBMS(std::string &uri, int32_t user); + static int32_t GetUserByToken(uint32_t tokenId); + std::string BundleName(); private: int GetFromProxyData(); - int32_t GetUserByToken(uint32_t tokenId); - std::pair GetBundleInfoFromBMS(); - ProviderInfo providerInfo_; static constexpr const char *PROXY_URI_SCHEMA = "datashareproxy"; + static constexpr const char *PROXY_URI_SCHEMA_SEPARATOR = "datashareproxy://"; + static constexpr const char *EXT_URI_SCHEMA_SEPARATOR = "datashare://"; + ProviderInfo providerInfo_; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/permission/include/data_share_config.h b/data_share/frameworks/native/permission/include/data_share_config.h new file mode 100644 index 00000000..ffd252c5 --- /dev/null +++ b/data_share/frameworks/native/permission/include/data_share_config.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2021 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 OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_CONFIG_FACTORY_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_CONFIG_FACTORY_H +#include +#include +#include +#include "serializable.h" +#include "visibility.h" +namespace OHOS { +namespace DataShare { + +class DataShareConfig final : public Serializable { +public: + struct Bundle final : public Serializable { + std::string name; + std::string appIdentifier; + bool Marshal(Serializable::json &node) const override; + bool Unmarshal(const Serializable::json &node) override; + }; + struct ConsumerProvider final : public Serializable { + std::vector consumer; + Bundle provider; + bool Marshal(Serializable::json &node) const override; + bool Unmarshal(const Serializable::json &node) override; + }; + bool Marshal(Serializable::json &node) const override; + bool Unmarshal(const Serializable::json &node) override; + std::vector dataShareExtNames; + std::vector uriTrusts; + std::vector extensionObsTrusts; +}; + +class GlobalConfig final : public Serializable { +public: + DataShareConfig *dataShare = nullptr; + ~GlobalConfig(); + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; +}; + +class ConfigFactory { +public: + API_EXPORT static ConfigFactory &GetInstance(); + API_EXPORT int32_t Initialize(); + API_EXPORT DataShareConfig *GetDataShareConfig(); +private: + static constexpr const char *CONF_PATH = "/system/etc/distributeddata/conf"; + ConfigFactory(); + ~ConfigFactory(); + + std::string file_; + GlobalConfig config_; + bool isInited = false; +}; +} // namespace DistributedData +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_CONFIG_FACTORY_H \ No newline at end of file diff --git a/data_share/frameworks/native/permission/src/data_share_called_config.cpp b/data_share/frameworks/native/permission/src/data_share_called_config.cpp index 3b3631d3..a2a04dd7 100644 --- a/data_share/frameworks/native/permission/src/data_share_called_config.cpp +++ b/data_share/frameworks/native/permission/src/data_share_called_config.cpp @@ -25,8 +25,11 @@ #include "datashare_errno.h" #include "datashare_log.h" #include "datashare_string_utils.h" +#include "data_share_permission.h" +#include "hiview_datashare.h" #include "if_system_ability_manager.h" #include "iservice_registry.h" +#include "ipc_skeleton.h" #include "system_ability_definition.h" namespace OHOS::DataShare { @@ -35,6 +38,23 @@ using namespace OHOS::Security::AccessToken; DataShareCalledConfig::DataShareCalledConfig(const std::string &uri) { providerInfo_.uri = uri; + Uri uriTemp(providerInfo_.uri); + providerInfo_.schema = uriTemp.GetScheme(); + auto isProxyData = PROXY_URI_SCHEMA == providerInfo_.schema; + std::string bundleName = uriTemp.GetAuthority(); + if (!isProxyData) { + std::vector pathSegments; + uriTemp.GetPathSegments(pathSegments); + if (pathSegments.size() != 0) { + bundleName = pathSegments[0]; + } + } + providerInfo_.bundleName = bundleName; +} + +std::string DataShareCalledConfig::BundleName() +{ + return providerInfo_.bundleName; } int32_t DataShareCalledConfig::GetUserByToken(uint32_t tokenId) @@ -46,8 +66,8 @@ int32_t DataShareCalledConfig::GetUserByToken(uint32_t tokenId) HapTokenInfo tokenInfo; auto result = AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo); if (result != RET_SUCCESS) { - LOG_ERROR("Get user failed!token:0x%{public}x, result:%{public}d, uri:%{public}s", - tokenId, result, DataShareStringUtils::Anonymous(providerInfo_.uri).c_str()); + LOG_ERROR("Get user failed!token:0x%{public}x, result:%{public}d", + tokenId, result); return -1; } return tokenInfo.userID; @@ -55,7 +75,7 @@ int32_t DataShareCalledConfig::GetUserByToken(uint32_t tokenId) int DataShareCalledConfig::GetFromProxyData() { - auto [success, bundleInfo] = GetBundleInfoFromBMS(); + auto [success, bundleInfo] = GetBundleInfoFromBMS(providerInfo_.bundleName, providerInfo_.currentUserId); if (!success) { LOG_ERROR("Get bundleInfo failed! bundleName:%{public}s, userId:%{public}d, uri:%{public}s", providerInfo_.bundleName.c_str(), providerInfo_.currentUserId, @@ -68,9 +88,14 @@ int DataShareCalledConfig::GetFromProxyData() if (schemePos != uriWithoutQuery.npos) { uriWithoutQuery.replace(schemePos, Constants::PARAM_URI_SEPARATOR_LEN, Constants::URI_SEPARATOR); } + schemePos = uriWithoutQuery.find(EXT_URI_SCHEMA_SEPARATOR); + if (schemePos != uriWithoutQuery.npos) { + uriWithoutQuery.replace(schemePos, strlen(EXT_URI_SCHEMA_SEPARATOR), PROXY_URI_SCHEMA_SEPARATOR); + } for (auto &hapModuleInfo : bundleInfo.hapModuleInfos) { for (auto &data : hapModuleInfo.proxyDatas) { - if (data.uri != uriWithoutQuery) { + if (data.uri.length() > uriWithoutQuery.length() || + uriWithoutQuery.compare(0, data.uri.length(), data.uri) != 0) { continue; } providerInfo_.readPermission = std::move(data.requiredReadPermission); @@ -79,53 +104,78 @@ int DataShareCalledConfig::GetFromProxyData() return E_OK; } } + LOG_ERROR("E_URI_NOT_EXIST uriWithoutQuery %{public}s", uriWithoutQuery.c_str()); return E_URI_NOT_EXIST; } -std::pair DataShareCalledConfig::GetProviderInfo(uint32_t tokenId) +std::pair DataShareCalledConfig::GetProviderInfo(int32_t user) { - Uri uriTemp(providerInfo_.uri); - auto isProxyData = PROXY_URI_SCHEMA == uriTemp.GetScheme(); - std::string bundleName = uriTemp.GetAuthority(); - if (!isProxyData) { - std::vector pathSegments; - uriTemp.GetPathSegments(pathSegments); - if (pathSegments.size() != 0) { - bundleName = pathSegments[0]; - } - } - if (bundleName.empty()) { - LOG_ERROR("BundleName not exist!, tokenId:0x%{public}x, uri:%{public}s", - tokenId, DataShareStringUtils::Anonymous(providerInfo_.uri).c_str()); + if (providerInfo_.bundleName.empty()) { + LOG_ERROR("BundleName not exist!, user:%{public}d, uri:%{public}s", + user, DataShareStringUtils::Anonymous(providerInfo_.uri).c_str()); return std::make_pair(E_BUNDLE_NAME_NOT_EXIST, DataShareCalledConfig::ProviderInfo{}); } - providerInfo_.bundleName = bundleName; - providerInfo_.currentUserId = GetUserByToken(tokenId); + providerInfo_.currentUserId = user; auto ret = GetFromProxyData(); if (ret != E_OK) { - LOG_ERROR("Failed! isProxyData:%{public}d,ret:%{public}d,tokenId:0x%{public}x,uri:%{public}s", - isProxyData, ret, tokenId, DataShareStringUtils::Anonymous(providerInfo_.uri).c_str()); + LOG_ERROR("GetFromProxyData Failed! ret:%{public}d,user:%{public}d,uri:%{public}s", + ret, user, providerInfo_.uri.c_str()); } return std::make_pair(ret, providerInfo_); } -std::pair DataShareCalledConfig::GetBundleInfoFromBMS() +std::pair DataShareCalledConfig::GetBundleInfoFromBMS(std::string bundleName, int32_t user) { BundleInfo bundleInfo; auto bmsHelper = DelayedSingleton::GetInstance(); if (bmsHelper == nullptr) { LOG_ERROR("BmsHelper is nullptr!.uri: %{public}s", - DataShareStringUtils::Anonymous(providerInfo_.uri).c_str()); + DataShareStringUtils::Anonymous(bundleName).c_str()); return std::make_pair(false, bundleInfo); } - bool ret = bmsHelper->GetBundleInfo(providerInfo_.bundleName, - BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo, providerInfo_.currentUserId); + + if (user == 0) { + user = Constants::ANY_USERID; + } + // because BMS and obs are in the same process. + // set IPCSkeleton tokenid to this process's tokenid. + // otherwise BMS may check permission failed. + std::string identity = IPCSkeleton::ResetCallingIdentity(); + bool ret = bmsHelper->GetBundleInfo(bundleName, + BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo, user); + IPCSkeleton::SetCallingIdentity(identity); if (!ret) { - LOG_ERROR("Get BundleInfo failed! bundleName:%{public}s, userId:%{public}d,uri:%{public}s", - providerInfo_.bundleName.c_str(), providerInfo_.currentUserId, - DataShareStringUtils::Anonymous(providerInfo_.uri).c_str()); + LOG_ERROR("Get BundleInfo failed! bundleName:%{public}s, userId:%{public}d", + bundleName.c_str(), user); return std::make_pair(false, bundleInfo); } return std::make_pair(true, bundleInfo); } + +std::pair DataShareCalledConfig::GetExtensionInfoFromBMS(std::string &uri, int32_t user) +{ + ExtensionAbilityInfo info; + auto bmsHelper = DelayedSingleton::GetInstance(); + if (bmsHelper == nullptr) { + LOG_ERROR("BmsHelper is nullptr!.uri: %{public}s", + DataShareStringUtils::Anonymous(uri).c_str()); + return std::make_pair(false, info); + } + + if (user == 0) { + user = Constants::ANY_USERID; + } + // because BMS and obs are in the same process. + // set IPCSkeleton tokenid to this process's tokenid. + // otherwise BMS may check permission failed. + std::string identity = IPCSkeleton::ResetCallingIdentity(); + bool ret = bmsHelper->QueryExtensionAbilityInfoByUri(uri, user, info); + IPCSkeleton::SetCallingIdentity(identity); + if (!ret) { + LOG_ERROR("QueryExtensionAbilityInfoByUri failed! uri:%{public}s, userId:%{public}d", + uri.c_str(), user); + return std::make_pair(false, info); + } + return std::make_pair(true, info); +} } // namespace OHOS::DataShare \ No newline at end of file diff --git a/data_share/frameworks/native/permission/src/data_share_config.cpp b/data_share/frameworks/native/permission/src/data_share_config.cpp new file mode 100644 index 00000000..42cc4e9c --- /dev/null +++ b/data_share/frameworks/native/permission/src/data_share_config.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2021 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 "data_share_config.h" +#include "datashare_log.h" +namespace OHOS { +namespace DataShare { +ConfigFactory::ConfigFactory() : file_(std::string(CONF_PATH) + "/config.json") +{ +} + +ConfigFactory::~ConfigFactory() +{ +} + +ConfigFactory &ConfigFactory::GetInstance() +{ + static std::mutex mutex; + static ConfigFactory factory; + if (factory.isInited) { + return factory; + } + std::lock_guard lock(mutex); + factory.Initialize(); + return factory; +} + +int32_t ConfigFactory::Initialize() +{ + std::string jsonStr; + std::ifstream fin(file_); + if (!fin.is_open()) { + LOG_ERROR("ConfigFactory open file failed"); + return -1; + } + while (fin.good()) { + std::string line; + std::getline(fin, line); + jsonStr += line; + } + config_.Unmarshall(jsonStr); + isInited = true; + return 0; +} + +DataShareConfig *ConfigFactory::GetDataShareConfig() +{ + return config_.dataShare; +} + +bool DataShareConfig::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(dataShareExtNames)], dataShareExtNames); + SetValue(node[GET_NAME(uriTrusts)], uriTrusts); + SetValue(node[GET_NAME(extensionObsTrusts)], extensionObsTrusts); + return true; +} + +bool DataShareConfig::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(dataShareExtNames), dataShareExtNames); + GetValue(node, GET_NAME(uriTrusts), uriTrusts); + GetValue(node, GET_NAME(extensionObsTrusts), extensionObsTrusts); + return true; +} + +bool DataShareConfig::ConsumerProvider::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(consumer)], consumer); + SetValue(node[GET_NAME(provider)], provider); + return true; +} + +bool DataShareConfig::ConsumerProvider::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(consumer), consumer); + GetValue(node, GET_NAME(provider), provider); + return true; +} + +bool DataShareConfig::Bundle::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(name)], name); + SetValue(node[GET_NAME(appIdentifier)], appIdentifier); + return true; +} + +bool DataShareConfig::Bundle::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(name), name); + GetValue(node, GET_NAME(appIdentifier), appIdentifier); + return true; +} + +bool GlobalConfig::Marshal(json &node) const +{ + SetValue(node[GET_NAME(dataShare)], dataShare); + return true; +} + +bool GlobalConfig::Unmarshal(const json &node) +{ + GetValue(node, GET_NAME(dataShare), dataShare); + return true; +} + +GlobalConfig::~GlobalConfig() +{ + if (dataShare != nullptr) { + delete dataShare; + } +} +} // namespace DistributedData +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/permission/src/data_share_permission.cpp b/data_share/frameworks/native/permission/src/data_share_permission.cpp index b0862a22..896ffafd 100644 --- a/data_share/frameworks/native/permission/src/data_share_permission.cpp +++ b/data_share/frameworks/native/permission/src/data_share_permission.cpp @@ -12,20 +12,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "datashare_uri_utils.h" #define LOG_TAG "DataSharePermission" #include "data_share_permission.h" #include +#include "access_token.h" +#include "bundle_mgr_helper.h" #include "data_share_called_config.h" #include "datashare_errno.h" #include "datashare_log.h" #include "datashare_string_utils.h" +#include "data_share_config.h" +#include "hiview_datashare.h" +#include "ipc_skeleton.h" namespace OHOS { namespace DataShare { using namespace AppExecFwk; +static constexpr const char *NO_PERMISSION = "noPermission"; int DataSharePermission::VerifyPermission(Security::AccessToken::AccessTokenID tokenID, const Uri &uri, bool isRead) { if (uri.ToString().empty()) { @@ -33,7 +40,8 @@ int DataSharePermission::VerifyPermission(Security::AccessToken::AccessTokenID t return ERR_INVALID_VALUE; } DataShareCalledConfig calledConfig(uri.ToString()); - auto [errCode, providerInfo] = calledConfig.GetProviderInfo(tokenID); + int32_t user = DataShareCalledConfig::GetUserByToken(tokenID); + auto [errCode, providerInfo] = calledConfig.GetProviderInfo(user); if (errCode != E_OK) { LOG_ERROR("ProviderInfo failed! token:0x%{public}x, errCode:%{public}d,uri:%{public}s", tokenID, errCode, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); @@ -54,5 +62,250 @@ int DataSharePermission::VerifyPermission(Security::AccessToken::AccessTokenID t } return E_OK; } + +bool IsInUriTrusts(Uri &uri) +{ + auto config = ConfigFactory::GetInstance().GetDataShareConfig(); + if (config == nullptr) { + LOG_ERROR("GetDataShareConfig null"); + return false; + } + std::string uriStr = uri.ToString(); + for (std::string& item : config->uriTrusts) { + if (item.length() > uriStr.length() || + uriStr.compare(0, item.length(), item) != 0) { + continue; + } + return true; + } + return false; +} + +bool CheckAppIdentifier(std::string &name, std::string &appIdentifier) +{ + auto [isSuccess, bundleInfo] = DataShareCalledConfig::GetBundleInfoFromBMS(name, 0); + if (!isSuccess) { + return false; + } + if (bundleInfo.signatureInfo.appIdentifier == appIdentifier) { + return true; + } + return false; +} + +bool IsInExtensionTrusts(std::string& consumer, std::string& provider) +{ + auto config = ConfigFactory::GetInstance().GetDataShareConfig(); + if (config == nullptr) { + LOG_ERROR("GetDataShareConfig is null"); + return false; + } + std::string appIdentifier; + for (DataShareConfig::ConsumerProvider& item : config->extensionObsTrusts) { + if (item.provider.name != provider) { + continue; + } + if (!CheckAppIdentifier(item.provider.name, item.provider.appIdentifier)) { + return false; + } + for (auto item : item.consumer) { + if (item.name == consumer) { + appIdentifier = item.appIdentifier; + break; + } + } + } + if (consumer == provider) { + return true; + } + if (CheckAppIdentifier(consumer, appIdentifier)) { + return true; + } + return false; +} + +int32_t DataSharePermission::UriIsTrust(Uri &uri) +{ + std::string schema = uri.GetScheme(); + if (schema == SCHEMA_PREFERENCE || schema == SCHEMA_RDB || schema == SCHEMA_FILE) { + return E_OK; + } + if (IsInUriTrusts(uri)) { + return E_OK; + } + if (!schema.empty() && schema != SCHEMA_DATASHARE && schema != SCHEMA_DATASHARE_PROXY) { + LOG_ERROR("invalid uri %{public}s, schema %{public}s", + uri.ToString().c_str(), uri.GetScheme().c_str()); + return E_DATASHARE_INVALID_URI; + } + return E_ERROR; +} + +std::pair DataSharePermission::GetExtensionUriPermission(Uri &uri, + int32_t user, bool isRead) +{ + std::string uriStr = uri.ToString(); + std::string permission; + auto [isSuccess, extensionInfo] = DataShareCalledConfig::GetExtensionInfoFromBMS(uriStr, user); + if (isSuccess) { + permission = isRead ? extensionInfo.readPermission : extensionInfo.writePermission; + LOG_ERROR("GetExtensionUriPermission uri %{public}s %{public}s %{public}s", + extensionInfo.uri.c_str(), extensionInfo.readPermission.c_str(), extensionInfo.writePermission.c_str()); + return std::make_pair(E_OK, permission); + } + return std::make_pair(E_URI_NOT_EXIST, ""); +} + +std::pair DataSharePermission::GetUriPermission(Uri &uri, int32_t user, bool isRead, bool isExtension) +{ + std::string uriStr = uri.ToString(); + if (uriStr.empty()) { + return std::make_pair(E_EMPTY_URI, ""); + } + int32_t ret = UriIsTrust(uri); + if (ret == E_OK) { + return std::make_pair(E_OK, NO_PERMISSION); + } else if (ret == E_DATASHARE_INVALID_URI) { + return std::make_pair(E_DATASHARE_INVALID_URI, ""); + } + std::string permission; + if (isExtension) { + std::tie(ret, permission) = GetExtensionUriPermission(uri, user, isRead); + } else { + std::tie(ret, permission) = GetSilentUriPermission(uri, user, isRead); + } + if (ret == E_OK) { + return std::make_pair(E_OK, permission); + } + return std::make_pair(ret, ""); +} + +void DataSharePermission::ReportExcuteFault(int32_t errCode, std::string &consumer, std::string &provider) +{ + DataShareFaultInfo faultInfo = {HiViewFaultAdapter::trustsFailed, consumer, provider, + "", "", errCode, ""}; + HiViewFaultAdapter::ReportDataFault(faultInfo); +} + +void DataSharePermission::ReportExtensionFault(int32_t errCode, uint32_t tokenId, + std::string &uri, std::string &bussinessType) +{ + auto [bundleName, ret] = HiViewFaultAdapter::GetCallingName(tokenId); + DataShareFaultInfo faultInfo = {HiViewFaultAdapter::extensionFailed, bundleName, "", + "", bussinessType, errCode, uri}; + HiViewFaultAdapter::ReportDataFault(faultInfo); +} + +std::pair DataSharePermission::GetSilentUriPermission(Uri &uri, int32_t user, bool isRead) +{ + std::string uriStr = uri.ToString(); + DataShareCalledConfig calledConfig(uriStr); + + auto [errCode, providerInfo] = calledConfig.GetProviderInfo(user); + if (errCode != E_OK) { + LOG_ERROR("ProviderInfo failed! user:%{public}d, errCode:%{public}d,uri:%{public}s", user, + errCode, uri.ToString().c_str()); + return std::make_pair(errCode, ""); + } + auto permission = isRead ? providerInfo.readPermission : providerInfo.writePermission; + return std::make_pair(E_OK, permission); +} + +int DataSharePermission::CheckExtensionTrusts(uint32_t consumerToken, uint32_t providerToken) +{ + auto [consumer, ret1] = HiViewFaultAdapter::GetCallingName(consumerToken); + auto [provider, ret2] = HiViewFaultAdapter::GetCallingName(providerToken); + if (ret1 != E_OK || ret2 != E_OK) { + LOG_ERROR("GetCallingName failed, consumer %{public}d %{public}s provider %{public}d " + "%{public}s", consumerToken, consumer.c_str(), providerToken, provider.c_str()); + return E_GET_CALLER_NAME_FAILED; + } + if (IsInExtensionTrusts(consumer, provider)) { + return E_OK; + } + LOG_ERROR("CheckExtensionTrusts failed, consumer %{public}d %{public}s provider %{public}d " + "%{public}s", consumerToken, consumer.c_str(), providerToken, provider.c_str()); + ReportExcuteFault(E_NOT_IN_TRUSTS, consumer, provider); + return E_NOT_IN_TRUSTS; +} + +bool DataSharePermission::VerifyPermission(uint32_t tokenID, std::string &permission) +{ + if (permission.empty() || permission == NO_PERMISSION) { + return true; + } + int status = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenID, permission); + if (status != Security::AccessToken::PermissionState::PERMISSION_GRANTED) { + return false; + } + return true; +} + +bool DataSharePermission::VerifyPermission(Uri &uri, uint32_t tokenID, std::string &permission, bool isExtension) +{ + if (permission == NO_PERMISSION) { + return true; + } + + std::string uriStr = uri.ToString(); + DataShareCalledConfig calledConfig(uriStr); + std::string providerName = calledConfig.BundleName(); + + auto [callingName, ret] = HiViewFaultAdapter::GetCallingName(tokenID); + if (ret != E_OK) { + LOG_WARN("GetCallingName failed, ret %{public}d", ret); + } + if (permission.empty() && isExtension) { + return true; + } + + if (permission.empty() && !isExtension) { + LOG_INFO("Permission empty! token: %{public}d", tokenID); + Security::AccessToken::HapTokenInfo tokenInfo; + auto result = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenID, tokenInfo); + if (result == Security::AccessToken::RET_SUCCESS && tokenInfo.bundleName == providerName) { + return true; + } + LOG_ERROR("Permission denied! uri %{public}s callingName %{public}s token %{public}d", + uri.ToString().c_str(), providerName.c_str(), tokenID); + return false; + } + + int status = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenID, permission); + if (status != Security::AccessToken::PermissionState::PERMISSION_GRANTED) { + return false; + } + return true; +} + +int32_t DataSharePermission::IsExtensionValid(uint32_t tokenId, uint32_t fullToken, int32_t user) +{ + Security::AccessToken::ATokenTypeEnum tokenType = + Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId); + if (tokenType != Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) { + return E_NOT_HAP; + } + if (Security::AccessToken::AccessTokenKit::IsSystemAppByFullTokenID(fullToken)) { + return E_OK; + } + auto [bundleName, ret] = HiViewFaultAdapter::GetCallingName(tokenId); + if (ret != 0) { + return ret; + } + + auto [success, bundleInfo] = DataShareCalledConfig::GetBundleInfoFromBMS(bundleName, user); + if (!success) { + LOG_ERROR("Get bundleInfo failed! bundleName:%{public}s, userId:%{public}d", + bundleName.c_str(), user); + return E_GET_BUNDLEINFO_FAILED; + } + for (auto &item : bundleInfo.extensionInfos) { + if (item.type == AppExecFwk::ExtensionAbilityType::DATASHARE) { + return E_OK; + } + } + return E_NOT_DATASHARE_EXTENSION; +} + } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/provider/include/datashare_ext_ability.h b/data_share/frameworks/native/provider/include/datashare_ext_ability.h index 46528426..9e69e2d1 100644 --- a/data_share/frameworks/native/provider/include/datashare_ext_ability.h +++ b/data_share/frameworks/native/provider/include/datashare_ext_ability.h @@ -18,6 +18,7 @@ #include #include "extension_base.h" +#include "data_ability_observer_interface.h" #include "datashare_business_error.h" #include "datashare_values_bucket.h" #include "datashare_predicates.h" @@ -36,6 +37,7 @@ using namespace AbilityRuntime; class DataShareExtAbilityContext; class DataShareExtAbility; using CreatorFunc = std::function& runtime)>; +using ChangeInfo = AAFwk::ChangeInfo; /** * @brief Basic datashare extension ability components. */ @@ -223,6 +225,35 @@ public: */ virtual bool NotifyChange(const Uri &uri); + /** + * @brief Registers an observer to DataObsMgr specified by the given Uri. + * Return true, need override by users. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ + virtual bool RegisterObserverExtProvider(const Uri &uri, const sptr &dataObserver, + bool isDescendants); + + /** + * @brief Deregisters an observer used for DataObsMgr specified by the given Uri. + * Return true, need override by users. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + */ + virtual bool UnregisterObserverExtProvider(const Uri &uri, const sptr &dataObserver); + + /** + * @brief Notifies the registered observers of a change to the data resource specified by Uri. + * Return true, need override by users. + * + * @param uri, Indicates the path of the data to operate. + * + * @return Return true if success. otherwise return false. + */ + virtual bool NotifyChangeExtProvider(const ChangeInfo changeInfo); + /** * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if diff --git a/data_share/frameworks/native/provider/include/datashare_stub.h b/data_share/frameworks/native/provider/include/datashare_stub.h index 5e91786a..8137c924 100644 --- a/data_share/frameworks/native/provider/include/datashare_stub.h +++ b/data_share/frameworks/native/provider/include/datashare_stub.h @@ -34,6 +34,7 @@ public: private: ErrCode CmdGetFileTypes(MessageParcel &data, MessageParcel &reply); ErrCode CmdOpenFile(MessageParcel &data, MessageParcel &reply); + ErrCode CmdOpenFileWithErrCode(MessageParcel &data, MessageParcel &reply); ErrCode CmdOpenRawFile(MessageParcel &data, MessageParcel &reply); ErrCode CmdInsert(MessageParcel &data, MessageParcel &reply); ErrCode CmdUpdate(MessageParcel &data, MessageParcel &reply); @@ -53,6 +54,10 @@ private: ErrCode CmdUpdateEx(MessageParcel &data, MessageParcel &reply); ErrCode CmdDeleteEx(MessageParcel &data, MessageParcel &reply); ErrCode CmdUserDefineFunc(MessageParcel &data, MessageParcel &reply, MessageOption &option); + ErrCode CmdRegisterObserverExtProvider(MessageParcel &data, MessageParcel &reply); + ErrCode CmdUnregisterObserverExtProvider(MessageParcel &data, MessageParcel &reply); + ErrCode CmdNotifyChangeExtProvider(MessageParcel &data, MessageParcel &reply); + ErrCode OpenFileInner(MessageParcel &data, MessageParcel &reply, int &fd); virtual int ExecuteBatch(const std::vector &statements, ExecResultSet &result) override; virtual int InsertExt(const Uri &uri, const DataShareValuesBucket &value, std::string &result) override; @@ -63,6 +68,14 @@ private: virtual std::pair DeleteEx(const Uri &uri, const DataSharePredicates &predicates) override; virtual int32_t UserDefineFunc( MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + // default return true, need override by users + virtual int RegisterObserverExtProvider(const Uri &uri, const sptr &dataObserver, + bool isDescendants, RegisterOption option) override; + // default return true, need override by users + virtual int UnregisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver) override; + // default return true, need override by users + virtual int NotifyChangeExtProvider(const ChangeInfo &changeInfo) override; using RequestFuncType = int (DataShareStub::*)(MessageParcel &data, MessageParcel &reply); std::map stubFuncMap_; diff --git a/data_share/frameworks/native/provider/include/datashare_stub_impl.h b/data_share/frameworks/native/provider/include/datashare_stub_impl.h index 42b4cc32..c77b620c 100644 --- a/data_share/frameworks/native/provider/include/datashare_stub_impl.h +++ b/data_share/frameworks/native/provider/include/datashare_stub_impl.h @@ -74,6 +74,8 @@ public: std::pair DeleteEx(const Uri &uri, const DataSharePredicates &predicates) override; + static int32_t GetCallingUserId(); + private: std::shared_ptr GetOwner(); bool CheckCallingPermission(const std::string &permission); diff --git a/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h b/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h index 06582fe5..de803be4 100644 --- a/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h +++ b/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h @@ -270,6 +270,15 @@ public: */ bool NotifyChange(const Uri &uri) override; + /** + * @brief Notifies the registered observers of a change to the data resource specified by Uri. + * + * @param uri, Indicates the path of the data to operate. + * + * @return Return true if success. otherwise return false. + */ + bool NotifyChangeWithUser(const Uri &uri, int32_t userId); + /** * @brief Converts the given uri that refer to the Data ability into a normalized URI. A normalized URI can be used * across devices, persisted, backed up, and restored. It can refer to the same item in the Data ability even if diff --git a/data_share/frameworks/native/provider/src/datashare_ext_ability.cpp b/data_share/frameworks/native/provider/src/datashare_ext_ability.cpp index 284d49be..c2e49011 100644 --- a/data_share/frameworks/native/provider/src/datashare_ext_ability.cpp +++ b/data_share/frameworks/native/provider/src/datashare_ext_ability.cpp @@ -49,7 +49,7 @@ DataShareExtAbility* DataShareExtAbility::Create(const std::unique_ptr& return JsDataShareExtAbility::Create(runtime); default: - return new DataShareExtAbility(); + return new (std::nothrow)DataShareExtAbility(); } } @@ -140,6 +140,23 @@ bool DataShareExtAbility::NotifyChange(const Uri &uri) return true; } +bool DataShareExtAbility::RegisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver, bool isDescendants) +{ + return true; +} + +bool DataShareExtAbility::UnregisterObserverExtProvider(const Uri &uri, + const sptr &dataObserver) +{ + return true; +} + +bool DataShareExtAbility::NotifyChangeExtProvider(const ChangeInfo changeInfo) +{ + return true; +} + Uri DataShareExtAbility::NormalizeUri(const Uri &uri) { Uri urivalue(""); diff --git a/data_share/frameworks/native/provider/src/datashare_stub.cpp b/data_share/frameworks/native/provider/src/datashare_stub.cpp index 2f1466dc..be1b6dde 100644 --- a/data_share/frameworks/native/provider/src/datashare_stub.cpp +++ b/data_share/frameworks/native/provider/src/datashare_stub.cpp @@ -37,6 +37,8 @@ DataShareStub::DataShareStub() { stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_GET_FILE_TYPES)] = &DataShareStub::CmdGetFileTypes; stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_OPEN_FILE)] = &DataShareStub::CmdOpenFile; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_OPEN_FILE_WITH_ERR_CODE)] = + &DataShareStub::CmdOpenFileWithErrCode; stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_OPEN_RAW_FILE)] = &DataShareStub::CmdOpenRawFile; stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_INSERT)] = &DataShareStub::CmdInsert; stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_UPDATE)] = &DataShareStub::CmdUpdate; @@ -58,6 +60,12 @@ DataShareStub::DataShareStub() stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_INSERT_EX)] = &DataShareStub::CmdInsertEx; stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_UPDATE_EX)] = &DataShareStub::CmdUpdateEx; stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_DELETE_EX)] = &DataShareStub::CmdDeleteEx; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_REGISTER_OBSERVEREXT_PROVIDER)] = + &DataShareStub::CmdRegisterObserverExtProvider; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_UNREGISTER_OBSERVEREXT_PROVIDER)] = + &DataShareStub::CmdUnregisterObserverExtProvider; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_NOTIFY_CHANGEEXT_PROVIDER)] = + &DataShareStub::CmdNotifyChangeExtProvider; } DataShareStub::~DataShareStub() @@ -122,7 +130,7 @@ ErrCode DataShareStub::CmdGetFileTypes(MessageParcel &data, MessageParcel &reply return E_OK; } -ErrCode DataShareStub::CmdOpenFile(MessageParcel &data, MessageParcel &reply) +ErrCode DataShareStub::OpenFileInner(MessageParcel &data, MessageParcel &reply, int &fd) { Uri uri(""); std::string mode; @@ -134,7 +142,18 @@ ErrCode DataShareStub::CmdOpenFile(MessageParcel &data, MessageParcel &reply) LOG_ERROR("mode is nullptr"); return ERR_INVALID_VALUE; } - int fd = OpenFile(uri, mode); + fd = OpenFile(uri, mode); + return E_OK; +} + +ErrCode DataShareStub::CmdOpenFile(MessageParcel &data, MessageParcel &reply) +{ + int fd = -1; + int ret = OpenFileInner(data, reply, fd); + if (ret != E_OK) { + return ret; + } + if (fd < 0) { return ERR_INVALID_DATA; } @@ -147,6 +166,26 @@ ErrCode DataShareStub::CmdOpenFile(MessageParcel &data, MessageParcel &reply) return E_OK; } +ErrCode DataShareStub::CmdOpenFileWithErrCode(MessageParcel &data, MessageParcel &reply) +{ + int fd = -1; + int ret = OpenFileInner(data, reply, fd); + if (ret != E_OK) { + return ret; + } + + if (fd < 0) { + return fd; + } + if (!reply.WriteFileDescriptor(fd)) { + LOG_ERROR("fail to WriteFileDescriptor fd"); + close(fd); + return ERR_INVALID_VALUE; + } + close(fd); + return E_OK; +} + ErrCode DataShareStub::CmdOpenRawFile(MessageParcel &data, MessageParcel &reply) { Uri uri(""); @@ -219,9 +258,12 @@ ErrCode DataShareStub::CmdBatchUpdate(OHOS::MessageParcel &data, OHOS::MessagePa } std::vector results; int ret = BatchUpdate(updateOperations, results); - if (ret != E_OK) { + if (ret == DEFAULT_NUMBER) { LOG_ERROR("BatchUpdate inner error, ret is %{public}d.", ret); - return ret; + return ERR_INVALID_VALUE; + } else if (ret == PERMISSION_ERROR_NUMBER) { + LOG_ERROR("BatchUpdate permission error"); + return ERR_PERMISSION_DENIED; } if (!ITypesUtil::Marshal(reply, results)) { LOG_ERROR("marshalling updateOperations is failed"); @@ -460,6 +502,68 @@ ErrCode DataShareStub::CmdNotifyChange(MessageParcel &data, MessageParcel &reply return E_OK; } +ErrCode DataShareStub::CmdRegisterObserverExtProvider(MessageParcel &data, MessageParcel &reply) +{ + Uri uri(""); + sptr observer; + bool isDescendants = false; + RegisterOption option; + if (!ITypesUtil::Unmarshal(data, uri, observer, isDescendants, option)) { + LOG_ERROR("Unmarshalling uri and observer failed"); + return ERR_INVALID_VALUE; + } + auto obServer = iface_cast(observer); + if (obServer == nullptr) { + LOG_ERROR("obServer is nullptr"); + return ERR_INVALID_VALUE; + } + + int ret = RegisterObserverExtProvider(uri, obServer, isDescendants, option); + if (!reply.WriteInt32(ret)) { + LOG_ERROR("fail to WriteInt32 ret"); + return ERR_INVALID_VALUE; + } + return E_OK; +} + +ErrCode DataShareStub::CmdUnregisterObserverExtProvider(MessageParcel &data, MessageParcel &reply) +{ + Uri uri(""); + sptr observer; + if (!ITypesUtil::Unmarshal(data, uri, observer)) { + LOG_ERROR("Unmarshalling uri and observer failed"); + return ERR_INVALID_VALUE; + } + auto obServer = iface_cast(observer); + if (obServer == nullptr) { + LOG_ERROR("obServer is nullptr"); + return ERR_INVALID_VALUE; + } + + int ret = UnregisterObserverExtProvider(uri, obServer); + if (!reply.WriteInt32(ret)) { + LOG_ERROR("fail to WriteInt32 ret"); + return ERR_INVALID_VALUE; + } + return E_OK; +} + +ErrCode DataShareStub::CmdNotifyChangeExtProvider(MessageParcel &data, MessageParcel &reply) +{ + ChangeInfo changeInfo; + if (!ChangeInfo::Unmarshalling(changeInfo, data)) { + LOG_ERROR("Failed to unmarshall changeInfo."); + return ERR_INVALID_VALUE; + } + + int ret = NotifyChangeExtProvider(changeInfo); + if (!reply.WriteInt32(ret)) { + LOG_ERROR("fail to WriteInt32 ret"); + return ERR_INVALID_VALUE; + } + return E_OK; +} + ErrCode DataShareStub::CmdNormalizeUri(MessageParcel &data, MessageParcel &reply) { Uri uri(""); @@ -566,5 +670,20 @@ int32_t DataShareStub::UserDefineFunc( LOG_ERROR("UserDefineFunc excuted."); return 0; } + +int DataShareStub::RegisterObserverExtProvider(const Uri &uri, const sptr &dataObserver, + bool isDescendants, RegisterOption option) +{ + return 0; +} + +int DataShareStub::UnregisterObserverExtProvider(const Uri &uri, const sptr &dataObserver) +{ + return 0; +} +int DataShareStub::NotifyChangeExtProvider(const ChangeInfo &changeInfo) +{ + return 0; +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp b/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp index 49dafcef..95d5b0fb 100644 --- a/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp +++ b/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp @@ -14,11 +14,17 @@ */ #include "datashare_stub_impl.h" -#include +#include #include "accesstoken_kit.h" +#include "bundle_constants.h" +#include "bundle_mgr_helper.h" +#include "dataobs_mgr_client.h" +#include "data_share_config.h" +#include "datashare_errno.h" #include "datashare_log.h" #include "datashare_string_utils.h" +#include "hiview_datashare.h" #include "ipc_skeleton.h" namespace OHOS { @@ -35,14 +41,30 @@ std::shared_ptr DataShareStubImpl::GetOwner() return extension_; } +int CheckTrusts(uint32_t consumerToken, uint32_t providerToken) +{ + auto obsMgrClient = AAFwk::DataObsMgrClient::GetInstance(); + if (obsMgrClient == nullptr) { + LOG_ERROR("obsMgrClient is nullptr"); + return E_DATA_OBS_NOT_READY; + } + ErrCode ret = obsMgrClient->CheckTrusts(consumerToken, providerToken); + if (ret != E_OK) { + LOG_ERROR("CheckTrusts error return %{public}d", ret); + return ret; + } + return E_OK; +} + bool DataShareStubImpl::CheckCallingPermission(const std::string &permission) { - if (!permission.empty() && AccessTokenKit::VerifyAccessToken(IPCSkeleton::GetCallingTokenID(), permission) - != AppExecFwk::Constants::PERMISSION_GRANTED) { - LOG_ERROR("permission not granted."); - return false; + uint32_t token = IPCSkeleton::GetCallingTokenID(); + if (permission.empty() || AccessTokenKit::VerifyAccessToken(token, permission) + == AppExecFwk::Constants::PERMISSION_GRANTED) { + return true; } - return true; + LOG_WARN("permission not granted. permission %{public}s, token %{public}d", permission.c_str(), token); + return false; } std::vector DataShareStubImpl::GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) @@ -210,24 +232,25 @@ int DataShareStubImpl::BatchUpdate(const UpdateOperations &operations, std::vect return PERMISSION_ERROR_NUMBER; } auto result = std::make_shared(); - std::shared_ptr ret = std::make_shared(0); - std::function syncTaskFunc = [extension, ret, operations, info, result]() { + int ret = 0; + std::function syncTaskFunc = [extension, operations, info, result]() { extension->SetCallingInfo(info); extension->InitResult(result); std::vector tmp; - *ret = extension->BatchUpdate(operations, tmp); + extension->BatchUpdate(operations, tmp); }; - std::function getRetFunc = [&results, result]() -> bool { + std::function getRetFunc = [&results, result, &ret]() -> bool { if (result == nullptr) { return false; } bool isRecvReply = result->GetRecvReply(); result->GetResult(results); + result->GetResult(ret); return isRecvReply; }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); - return *ret; + return ret; } int DataShareStubImpl::Delete(const Uri &uri, const DataSharePredicates &predicates) @@ -480,16 +503,34 @@ int DataShareStubImpl::BatchInsert(const Uri &uri, const std::vector &dataObserver) { auto extension = GetOwner(); if (extension == nullptr) { return false; } - if (!CheckCallingPermission(extension->abilityInfo_->readPermission)) { - LOG_ERROR("Register observer check permission failed. uri: %{public}s", - DataShareStringUtils::Anonymous(uri.ToString()).c_str()); - return false; + int32_t callingToken = IPCSkeleton::GetCallingTokenID(); + bool isSuccess = CheckCallingPermission(extension->abilityInfo_->readPermission); + if (!isSuccess) { + int selfToken = IPCSkeleton::GetSelfTokenID(); + if (CheckTrusts(callingToken, selfToken) != E_OK) { + LOG_ERROR("Register observer check permission failed. uri: %{public}s, token:%{public}d", + DataShareStringUtils::Anonymous(uri.ToString()).c_str(), callingToken); + // just log + } } return extension->RegisterObserver(uri, dataObserver); } @@ -500,11 +541,17 @@ bool DataShareStubImpl::UnregisterObserver(const Uri &uri, const sptrabilityInfo_->readPermission)) { - LOG_ERROR("UnRegister observer check permission failed. uri: %{public}s", - DataShareStringUtils::Anonymous(uri.ToString()).c_str()); - return false; + int32_t callingToken = IPCSkeleton::GetCallingTokenID(); + bool isSuccess = CheckCallingPermission(extension->abilityInfo_->readPermission); + if (!isSuccess) { + int selfToken = IPCSkeleton::GetSelfTokenID(); + if (CheckTrusts(callingToken, selfToken) != E_OK) { + LOG_ERROR("UnRegister observer check permission failed. uri: %{public}s, token:%{public}d", + DataShareStringUtils::Anonymous(uri.ToString()).c_str(), callingToken); + // just log + } } + return extension->UnregisterObserver(uri, dataObserver); } @@ -516,9 +563,20 @@ bool DataShareStubImpl::NotifyChange(const Uri &uri) if (extension == nullptr) { return *ret; } + int32_t callingToken = IPCSkeleton::GetCallingTokenID(); + bool isSuccess = CheckCallingPermission(extension->abilityInfo_->writePermission); + if (!isSuccess) { + int selfToken = IPCSkeleton::GetSelfTokenID(); + if (CheckTrusts(callingToken, selfToken) != E_OK) { + LOG_ERROR("extension NotifyChange check permission failed. uri: %{public}s token %{public}d", + uri.ToString().c_str(), IPCSkeleton::GetCallingTokenID()); + // just log + } + } - std::function syncTaskFunc = [extension, ret, uri]() { - *ret = extension->NotifyChange(uri); + int32_t callingUserId = GetCallingUserId(); + std::function syncTaskFunc = [extension, ret, uri, callingUserId]() { + *ret = extension->NotifyChangeWithUser(uri, callingUserId); }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc); diff --git a/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp b/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp index 638125c3..788fc195 100644 --- a/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp +++ b/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp @@ -52,7 +52,11 @@ void DataShareUvQueue::LambdaForWork(TaskEntry* taskEntry) void DataShareUvQueue::SyncCall(NapiVoidFunc func, NapiBoolFunc retFunc) { - auto *taskEntry = new TaskEntry {env_, std::move(func), false, {}, {}, std::atomic(1)}; + auto *taskEntry = new (std::nothrow)TaskEntry {env_, std::move(func), false, {}, {}, std::atomic(1)}; + if (taskEntry == nullptr) { + LOG_ERROR("invalid taskEntry."); + return; + } { std::unique_lock lock(taskEntry->mutex); taskEntry->count.fetch_add(1); @@ -69,7 +73,7 @@ void DataShareUvQueue::SyncCall(NapiVoidFunc func, NapiBoolFunc retFunc) [taskEntry] { return taskEntry->done; })) { auto time = static_cast(duration_cast( system_clock::now().time_since_epoch()).count()); - LOG_INFO("function ended successfully. times %{public}" PRIu64 ".", time); + LOG_WARN("function ended successfully. times %{public}" PRIu64 ".", time); } } CheckFuncAndExec(retFunc); diff --git a/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp b/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp index 9260f69e..a3691030 100644 --- a/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp +++ b/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp @@ -23,6 +23,7 @@ #include "datashare_stub_impl.h" #include "ikvstore_data_service.h" #include "idata_share_service.h" +#include "ipc_skeleton.h" #include "iservice_registry.h" #include "js_datashare_ext_ability_context.h" #include "js_proxy.h" @@ -64,6 +65,7 @@ void JsResult::SetAsyncResult(napi_env env, DatashareBusinessError &businessErro napi_unwrap(env, result, reinterpret_cast(&proxy)); if (proxy == nullptr) { if (UnwrapBatchUpdateResult(env, result, updateResults_)) { + callbackResultNumber_ = E_OK; isRecvReply_ = true; return; } @@ -120,7 +122,7 @@ using DataObsMgrClient = OHOS::AAFwk::DataObsMgrClient; JsDataShareExtAbility* JsDataShareExtAbility::Create(const std::unique_ptr& runtime) { - return new JsDataShareExtAbility(static_cast(*runtime)); + return new (std::nothrow)JsDataShareExtAbility(static_cast(*runtime)); } JsDataShareExtAbility::JsDataShareExtAbility(JsRuntime& jsRuntime) : jsRuntime_(jsRuntime) {} @@ -175,11 +177,15 @@ void JsDataShareExtAbility::Init(const std::shared_ptr &reco contextObj = contextRef->GetNapiValue(); context->Bind(jsRuntime_, contextRef.release()); napi_set_named_property(env, obj, "context", contextObj); - napi_wrap(env, contextObj, new std::weak_ptr(context), + napi_status status = napi_wrap(env, contextObj, new (std::nothrow)std::weak_ptr(context), [](napi_env, void *data, void *) { LOG_INFO("Finalizer for weak_ptr datashare extension ability context is called"); delete static_cast*>(data); }, nullptr, nullptr); + if (status != napi_ok) { + LOG_ERROR("napi_wrap failed. code:%{public}d", status); + return; + } } void JsDataShareExtAbility::OnStart(const AAFwk::Want &want) @@ -315,13 +321,17 @@ napi_value JsDataShareExtAbility::CallObjectMethod( args[i] = argv[i]; } - napi_create_function(env, ASYNC_CALLBACK_NAME, CALLBACK_LENGTH, - JsDataShareExtAbility::AsyncCallbackWithContext, point, &args[argc]); + if (napi_create_function(env, ASYNC_CALLBACK_NAME, CALLBACK_LENGTH, + JsDataShareExtAbility::AsyncCallbackWithContext, point, &args[argc]) != napi_ok) { + LOG_ERROR("napi_create_function error."); + delete point; + delete []args; + return nullptr; + } napi_value callResult = nullptr; napi_call_function(env, obj, method, count, args, &callResult); auto result = handleEscape.Escape(callResult); - napi_add_finalizer(env, args[argc], point, - [](napi_env env, void* point, void* finalize_hint) { + napi_add_finalizer(env, args[argc], point, [](napi_env env, void* point, void* finalize_hint) { delete static_cast(point); }, nullptr, nullptr); delete []args; @@ -414,8 +424,13 @@ int32_t JsDataShareExtAbility::InitAsyncCallParams(size_t argc, napi_env &env, n } point->result = std::move(result_); - napi_create_function(env, ASYNC_CALLBACK_NAME, CALLBACK_LENGTH, + napi_status status = napi_create_function(env, ASYNC_CALLBACK_NAME, CALLBACK_LENGTH, JsDataShareExtAbility::AsyncCallback, point, &args[argc]); + if (status != napi_ok) { + LOG_ERROR("napi_create_function error: %{public}d.", status); + delete point; + return E_ERROR; + } napi_add_finalizer(env, args[argc], point, [](napi_env env, void* point, void* finalize_hint) { delete static_cast(point); @@ -808,7 +823,12 @@ bool JsDataShareExtAbility::RegisterObserver(const Uri &uri, const sptrRegisterObserver(uri, dataObserver); + int32_t callingUserId = DataShareStubImpl::GetCallingUserId(); + uint32_t token = IPCSkeleton::GetCallingTokenID(); + DataObsOption opt; + opt.SetFirstCallerTokenID(token); + Uri innerUri = uri; + ErrCode ret = obsMgrClient->RegisterObserverFromExtension(innerUri, dataObserver, callingUserId); if (ret != ERR_OK) { LOG_ERROR("obsMgrClient->RegisterObserver error return %{public}d", ret); return false; @@ -825,7 +845,8 @@ bool JsDataShareExtAbility::UnregisterObserver(const Uri &uri, const sptrUnregisterObserver(uri, dataObserver); + int32_t callingUserId = DataShareStubImpl::GetCallingUserId(); + ErrCode ret = obsMgrClient->UnregisterObserver(uri, dataObserver, callingUserId); if (ret != ERR_OK) { LOG_ERROR("obsMgrClient->UnregisterObserver error return %{public}d", ret); return false; @@ -850,6 +871,22 @@ bool JsDataShareExtAbility::NotifyChange(const Uri &uri) return true; } +bool JsDataShareExtAbility::NotifyChangeWithUser(const Uri &uri, int32_t userId) +{ + auto obsMgrClient = DataObsMgrClient::GetInstance(); + if (obsMgrClient == nullptr) { + LOG_ERROR("obsMgrClient is nullptr"); + return false; + } + Uri innerUri = uri; + ErrCode ret = obsMgrClient->NotifyChangeFromExtension(innerUri, userId); + if (ret != ERR_OK) { + LOG_ERROR("obsMgrClient->NotifyChange error return %{public}d", ret); + return false; + } + return true; +} + Uri JsDataShareExtAbility::NormalizeUri(const Uri &uri) { auto ret = DataShareExtAbility::NormalizeUri(uri); diff --git a/data_share/frameworks/native/provider/src/js_datashare_ext_ability_context.cpp b/data_share/frameworks/native/provider/src/js_datashare_ext_ability_context.cpp index 0aa892b0..7073d5a9 100644 --- a/data_share/frameworks/native/provider/src/js_datashare_ext_ability_context.cpp +++ b/data_share/frameworks/native/provider/src/js_datashare_ext_ability_context.cpp @@ -53,7 +53,13 @@ napi_value CreateJsDataShareExtAbilityContext(napi_env env, LOG_DEBUG("CreateJsDataShareExtAbilityContext begin"); napi_value objValue = CreateJsExtensionContext(env, context); std::unique_ptr jsContext = std::make_unique(context); - napi_wrap(env, objValue, jsContext.release(), JsDataShareExtAbilityContext::Finalizer, nullptr, nullptr); + napi_status status = napi_wrap(env, objValue, jsContext.release(), JsDataShareExtAbilityContext::Finalizer, + nullptr, nullptr); + if (status != napi_ok) { + LOG_ERROR("napi_wrap failed. code:%{public}d", status); + jsContext.release(); + return nullptr; + } return objValue; } } // namespace DataShare diff --git a/data_share/frameworks/native/proxy/include/data_proxy_observer.h b/data_share/frameworks/native/proxy/include/data_proxy_observer.h index 8de56535..1b7477f1 100644 --- a/data_share/frameworks/native/proxy/include/data_proxy_observer.h +++ b/data_share/frameworks/native/proxy/include/data_proxy_observer.h @@ -29,6 +29,11 @@ class IDataProxyPublishedDataObserver : public OHOS::IRemoteBroker { public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DataShare.IDataProxyPublishedDataObserver"); }; + +class IProxyDataObserver : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DataShare.IProxyDataObserver"); +}; } // namespace DataShare } // namespace OHOS #endif // DATA_PROXY_OBSERVER_H diff --git a/data_share/frameworks/native/proxy/include/data_proxy_observer_stub.h b/data_share/frameworks/native/proxy/include/data_proxy_observer_stub.h index 9de980ae..63f1890e 100644 --- a/data_share/frameworks/native/proxy/include/data_proxy_observer_stub.h +++ b/data_share/frameworks/native/proxy/include/data_proxy_observer_stub.h @@ -17,6 +17,7 @@ #define DATA_PROXY_OBSERVER_STUB_H #include "data_proxy_observer.h" +#include "dataproxy_handle_common.h" #include "datashare_template.h" #include "iremote_stub.h" @@ -50,6 +51,19 @@ private: std::mutex mutex_; PublishedDataCallback callback_; }; + +using ProxyDataCallback = std::function &changeInfo)>; +class ProxyDataObserverStub : public IRemoteStub { +public: + virtual ~ProxyDataObserverStub(); + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; + explicit ProxyDataObserverStub(ProxyDataCallback callback) : callback_(callback){}; + void OnChangeFromProxyData(std::vector &changeInfo); + void ClearCallback(); +private: + std::mutex mutex_; + ProxyDataCallback callback_; +}; } // namespace DataShare } // namespace OHOS #endif //DATA_PROXY_OBSERVER_STUB_H diff --git a/data_share/frameworks/native/proxy/include/data_share_manager_impl.h b/data_share/frameworks/native/proxy/include/data_share_manager_impl.h index 8ff96ca2..a4ad397a 100644 --- a/data_share/frameworks/native/proxy/include/data_share_manager_impl.h +++ b/data_share/frameworks/native/proxy/include/data_share_manager_impl.h @@ -90,7 +90,7 @@ public: void OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId); - void SetCallCount(const std::string &funcName, const std::string &uri); + bool SetCallCount(const std::string &funcName, const std::string &uri); private: DataShareManagerImpl(); diff --git a/data_share/frameworks/native/proxy/include/data_share_service_proxy.h b/data_share/frameworks/native/proxy/include/data_share_service_proxy.h index 75f1d3d1..b010a5c2 100644 --- a/data_share/frameworks/native/proxy/include/data_share_service_proxy.h +++ b/data_share/frameworks/native/proxy/include/data_share_service_proxy.h @@ -23,7 +23,7 @@ #include "idata_share_service.h" namespace OHOS::DataShare { -class DataShareServiceProxy final : public IRemoteProxy { +class DataShareServiceProxy : public IRemoteProxy { public: explicit DataShareServiceProxy(const sptr &object); int Insert(const Uri &uri, const Uri &extUri, const DataShareValuesBucket &valuesBucket) override; @@ -90,6 +90,20 @@ public: static void SetSystem(bool isSystem); + std::vector PublishProxyData( + const std::vector &proxyData, const DataProxyConfig &proxyConfig) override; + + std::vector DeleteProxyData( + const std::vector &uris, const DataProxyConfig &proxyConfig) override; + + std::vector GetProxyData( + const std::vector uris, const DataProxyConfig &proxyConfig) override; + + std::vector SubscribeProxyData(const std::vector &uris, + const sptr &observer) override; + + std::vector UnsubscribeProxyData(const std::vector &uris) override; + static bool IsSystem(); static bool& GetSystem(); diff --git a/data_share/frameworks/native/proxy/include/proxy_data_subscriber_manager.h b/data_share/frameworks/native/proxy/include/proxy_data_subscriber_manager.h new file mode 100644 index 00000000..6a5d7fde --- /dev/null +++ b/data_share/frameworks/native/proxy/include/proxy_data_subscriber_manager.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PROXY_DATA_SUBSCRIBER_MANAGER_H +#define PROXY_DATA_SUBSCRIBER_MANAGER_H +#include + +#include "callbacks_manager.h" +#include "concurrent_map.h" +#include "data_proxy_observer.h" +#include "data_proxy_observer_stub.h" +#include "dataproxy_handle.h" +#include "dataproxy_handle_common.h" +#include "idatashare.h" +#include "iremote_stub.h" +#include "data_share_service_proxy.h" + +namespace OHOS { +namespace DataShare { +struct ProxyDataObserverMapKey { + std::string uri_; + ProxyDataObserverMapKey(const std::string &uri) : uri_(uri) {}; + bool operator==(const ProxyDataObserverMapKey &node) const + { + return uri_ == node.uri_; + } + bool operator!=(const ProxyDataObserverMapKey &node) const + { + return !(node == *this); + } + bool operator<(const ProxyDataObserverMapKey &node) const + { + return uri_ < node.uri_; + } + operator std::string() const + { + return uri_; + } +}; + +class ProxyDataObserver { +public: + explicit ProxyDataObserver(const ProxyDataCallback &callback); + void OnChange(std::vector &changeNode); + bool operator==(const ProxyDataObserver &rhs) const; + bool operator!=(const ProxyDataObserver &rhs) const; + +private: + ProxyDataCallback callback_; +}; + +class ProxyDataSubscriberManager : public CallbacksManager { +public: + using Key = ProxyDataObserverMapKey; + using Observer = ProxyDataObserver; + using BaseCallbacks = CallbacksManager; + static ProxyDataSubscriberManager &GetInstance(); + + std::vector AddObservers(void *subscriber, std::shared_ptr proxy, + const std::vector &uris, const ProxyDataCallback &callback); + std::vector DelObservers(void *subscriber, std::shared_ptr proxy, + const std::vector &uris); + std::vector DelObservers(void *subscriber, std::shared_ptr proxy); + + void RecoverObservers(std::shared_ptr proxy); + void Emit(std::vector &changeInfo); + +private: + void Emit(const std::vector &keys, const std::shared_ptr &observer); + ProxyDataSubscriberManager(); + std::map> callbacks_; + sptr serviceCallback_; + std::recursive_mutex mutex_{}; +}; +} // namespace DataShare +} // namespace OHOS +#endif //PROXY_DATA_SUBSCRIBER_MANAGER_H diff --git a/data_share/frameworks/native/proxy/src/ams_mgr_proxy.cpp b/data_share/frameworks/native/proxy/src/ams_mgr_proxy.cpp index 35af1653..25bc0e04 100644 --- a/data_share/frameworks/native/proxy/src/ams_mgr_proxy.cpp +++ b/data_share/frameworks/native/proxy/src/ams_mgr_proxy.cpp @@ -52,7 +52,7 @@ AmsMgrProxy* AmsMgrProxy::GetInstance() if (proxy != nullptr) { return proxy; } - proxy = new AmsMgrProxy(); + proxy = new (std::nothrow)AmsMgrProxy(); if (proxy == nullptr) { LOG_ERROR("new proxy failed"); } diff --git a/data_share/frameworks/native/proxy/src/data_proxy_observer_stub.cpp b/data_share/frameworks/native/proxy/src/data_proxy_observer_stub.cpp index d2d1981b..f970e4a6 100644 --- a/data_share/frameworks/native/proxy/src/data_proxy_observer_stub.cpp +++ b/data_share/frameworks/native/proxy/src/data_proxy_observer_stub.cpp @@ -15,11 +15,13 @@ #include "data_proxy_observer_stub.h" +#include "dataproxy_handle_common.h" #include "datashare_itypes_utils.h" #include "datashare_log.h" namespace OHOS { namespace DataShare { +static constexpr int MAX_VEC_SIZE = 1024; static constexpr int REQUEST_CODE = 0; int RdbObserverStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { @@ -84,7 +86,10 @@ int RdbObserverStub::DeserializeDataFromAshmem(RdbChangeNode &changeNode) return E_ERROR; } int vecLen = *vecLenRead; - + if (vecLen > MAX_VEC_SIZE || vecLen < 0) { + LOG_ERROR("vecLen is invalid: %{public}d", vecLen); + return E_ERROR; + } // Read data for (int i = 0; i < vecLen; i++) { const int *dataLenRead; @@ -193,5 +198,46 @@ PublishedDataObserverStub::~PublishedDataObserverStub() { ClearCallback(); } + +int ProxyDataObserverStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, + MessageOption &option) +{ + std::u16string descriptor = PublishedDataObserverStub::GetDescriptor(); + std::u16string remoteDescriptor = data.ReadInterfaceToken(); + if (descriptor != remoteDescriptor) { + LOG_ERROR("local descriptor is not equal to remote"); + return ERR_INVALID_STATE; + } + if (code != REQUEST_CODE) { + LOG_ERROR("not support code:%u", code); + return ERR_INVALID_STATE; + } + std::vector changeInfo; + if (!ITypesUtil::Unmarshal(data, changeInfo)) { + LOG_ERROR("Unmarshalling is nullptr"); + return ERR_INVALID_VALUE; + } + OnChangeFromProxyData(changeInfo); + return ERR_OK; +} + +void ProxyDataObserverStub::OnChangeFromProxyData(std::vector &changeInfo) +{ + std::lock_guard lock(mutex_); + if (callback_) { + callback_(changeInfo); + } +} + +void ProxyDataObserverStub::ClearCallback() +{ + std::lock_guard lock(mutex_); + callback_ = nullptr; +} + +ProxyDataObserverStub::~ProxyDataObserverStub() +{ + ClearCallback(); +} } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp b/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp index 1cb704af..802a4606 100644 --- a/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp +++ b/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp @@ -24,6 +24,7 @@ #include "iservice_registry.h" #include "system_ability_definition.h" #include "rdb_subscriber_manager.h" +#include "proxy_data_subscriber_manager.h" #include "published_data_subscriber_manager.h" namespace OHOS { @@ -38,7 +39,7 @@ DataShareManagerImpl* DataShareManagerImpl::GetInstance() if (manager_ != nullptr) { return manager_; } - manager_ = new DataShareManagerImpl(); + manager_ = new (std::nothrow)DataShareManagerImpl(); if (manager_ == nullptr) { LOG_ERROR("DataShareManagerImpl: GetInstance failed"); } @@ -47,7 +48,7 @@ DataShareManagerImpl* DataShareManagerImpl::GetInstance() LOG_ERROR("Failed to get saMgrProxy."); return manager_; } - sptr callback(new DataShareClientStatusChangeStub(manager_)); + sptr callback(new (std::nothrow)DataShareClientStatusChangeStub(manager_)); saManager->SubscribeSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID, callback); return manager_; } @@ -130,6 +131,7 @@ DataShareManagerImpl::DataShareManagerImpl() LOG_INFO("RecoverObs start"); RdbSubscriberManager::GetInstance().RecoverObservers(proxy); PublishedDataSubscriberManager::GetInstance().RecoverObservers(proxy); + ProxyDataSubscriberManager::GetInstance().RecoverObservers(proxy); }); } @@ -219,9 +221,9 @@ void DataShareManagerImpl::OnAddSystemAbility(int32_t systemAbilityId, const std } } -void DataShareManagerImpl::SetCallCount(const std::string &funcName, const std::string &uri) +bool DataShareManagerImpl::SetCallCount(const std::string &funcName, const std::string &uri) { - dataShareCallReporter_.Count(funcName, uri); + return dataShareCallReporter_.Count(funcName, uri); } } } diff --git a/data_share/frameworks/native/proxy/src/data_share_service_proxy.cpp b/data_share/frameworks/native/proxy/src/data_share_service_proxy.cpp index ff0a2859..086e73b9 100644 --- a/data_share/frameworks/native/proxy/src/data_share_service_proxy.cpp +++ b/data_share/frameworks/native/proxy/src/data_share_service_proxy.cpp @@ -17,6 +17,7 @@ #include #include "data_ability_observer_interface.h" +#include "dataproxy_handle_common.h" #include "datashare_errno.h" #include "datashare_itypes_utils.h" #include "datashare_log.h" @@ -201,11 +202,13 @@ std::shared_ptr DataShareServiceProxy::Query(const Uri &uri, MessageParcel data; if (!data.WriteInterfaceToken(IDataShareService::GetDescriptor())) { LOG_ERROR("WriteInterfaceToken failed!"); + businessError.SetCode(E_WRITE_TO_PARCE_ERROR); return nullptr; } if (!ITypesUtil::Marshal(data, uriStr, extUri.ToString(), predicates, columns)) { LOG_ERROR("Write to message parcel failed!"); + businessError.SetCode(E_MARSHAL_ERROR); return nullptr; } @@ -215,12 +218,13 @@ std::shared_ptr DataShareServiceProxy::Query(const Uri &uri, CastIPCCode(InterfaceCode::DATA_SHARE_SERVICE_CMD_QUERY), data, reply, option); auto result = ISharedResultSet::ReadFromParcel(reply); - businessError.SetCode(reply.ReadInt32()); if (err != NO_ERROR) { LOG_ERROR("Query fail to sendRequest. uri: %{public}s, err: %{public}d", DataShareStringUtils::Anonymous(uriStr).c_str(), err); + businessError.SetCode(err); return nullptr; } + businessError.SetCode(reply.ReadInt32()); return result; } @@ -691,5 +695,147 @@ int DataShareServiceProxy::UnRegisterObserver(const Uri &uri, const sptr DataShareServiceProxy::PublishProxyData( + const std::vector &proxyDatas, const DataProxyConfig &proxyConfig) +{ + std::vector results; + MessageParcel parcel; + if (!parcel.WriteInterfaceToken(IDataShareService::GetDescriptor())) { + LOG_ERROR("Write descriptor failed!"); + return results; + } + if (!ITypesUtil::Marshal(parcel, proxyDatas, proxyConfig)) { + LOG_ERROR("Marshal failed!"); + return results; + } + + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_PROXY_PUBLISH), parcel, reply, option); + if (err != NO_ERROR) { + LOG_ERROR("PublishProxyData fail to sendRequest. err: %{public}d", err); + return results; + } + + ITypesUtil::Unmarshal(reply, results); + return results; +} + +std::vector DataShareServiceProxy::DeleteProxyData( + const std::vector &uris, const DataProxyConfig &proxyConfig) +{ + std::vector results; + MessageParcel parcel; + if (!parcel.WriteInterfaceToken(IDataShareService::GetDescriptor())) { + LOG_ERROR("Write descriptor failed!"); + return results; + } + if (!ITypesUtil::Marshal(parcel, uris, proxyConfig)) { + LOG_ERROR("Marshal failed!"); + return results; + } + + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_PROXY_DELETE), parcel, reply, option); + if (err != NO_ERROR) { + LOG_ERROR("DeleteProxyData fail to sendRequest. err: %{public}d", err); + return results; + } + + ITypesUtil::Unmarshal(reply, results); + return results; +} + +std::vector DataShareServiceProxy::GetProxyData(const std::vector uris, + const DataProxyConfig &proxyConfig) +{ + std::vector results; + MessageParcel parcel; + if (!parcel.WriteInterfaceToken(IDataShareService::GetDescriptor())) { + LOG_ERROR("Write descriptor failed!"); + return results; + } + if (!ITypesUtil::Marshal(parcel, uris, proxyConfig)) { + LOG_ERROR("Marshal failed!"); + return results; + } + + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_PROXY_GET), parcel, reply, option); + if (err != NO_ERROR) { + LOG_ERROR("GetProxyData fail to sendRequest. err: %{public}d", err); + return results; + } + + ITypesUtil::Unmarshal(reply, results); + return results; +} + +std::vector DataShareServiceProxy::SubscribeProxyData(const std::vector &uris, + const sptr &observer) +{ + std::vector results; + if (observer == nullptr) { + LOG_ERROR("Observer is nullptr"); + return results; + } + MessageParcel data; + if (!data.WriteInterfaceToken(IDataShareService::GetDescriptor())) { + LOG_ERROR("Write descriptor failed!"); + return results; + } + + if (!ITypesUtil::Marshal(data, uris)) { + LOG_ERROR("Write to message parcel failed!"); + return results; + } + if (!data.WriteRemoteObject(observer->AsObject())) { + LOG_ERROR("Failed to write parcelable dataObserver "); + return results; + } + + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_SUBSCRIBE_PROXY_DATA), data, reply, option); + if (err != NO_ERROR) { + LOG_ERROR("SubscribeRdbData fail to sendRequest. err: %{public}d", err); + return results; + } + ITypesUtil::Unmarshal(reply, results); + return results; +} + +std::vector DataShareServiceProxy::UnsubscribeProxyData(const std::vector &uris) +{ + std::vector results; + MessageParcel data; + if (!data.WriteInterfaceToken(IDataShareService::GetDescriptor())) { + LOG_ERROR("Write descriptor failed!"); + return results; + } + + if (!ITypesUtil::Marshal(data, uris)) { + LOG_ERROR("Write to message parcel failed!"); + return results; + } + + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_UNSUBSCRIBE_PROXY_DATA), data, reply, option); + if (err != NO_ERROR) { + LOG_ERROR("Fail to sendRequest. err: %{public}d", err); + return results; + } + ITypesUtil::Unmarshal(reply, results); + return results; +} } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/proxy/src/proxy_data_subscriber_manager.cpp b/data_share/frameworks/native/proxy/src/proxy_data_subscriber_manager.cpp new file mode 100644 index 00000000..b10bb457 --- /dev/null +++ b/data_share/frameworks/native/proxy/src/proxy_data_subscriber_manager.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "proxy_data_subscriber_manager.h" + +#include + +#include "data_proxy_observer_stub.h" +#include "dataproxy_handle_common.h" +#include "datashare_log.h" +#include "datashare_string_utils.h" + +namespace OHOS { +namespace DataShare { +std::vector ProxyDataSubscriberManager::AddObservers(void *subscriber, + std::shared_ptr proxy, const std::vector &uris, + const ProxyDataCallback &callback) +{ + std::vector result = {}; + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return result; + } + std::vector keys; + std::for_each(uris.begin(), uris.end(), [&keys](auto &uri) { + keys.emplace_back(uri); + }); + return BaseCallbacks::AddObservers( + keys, subscriber, std::make_shared(callback), + [&proxy, subscriber, this](const std::vector &firstAddKeys, + const std::shared_ptr observer, std::vector &opResult) { + std::vector firstAddUris; + std::for_each(firstAddKeys.begin(), firstAddKeys.end(), [&firstAddUris](auto &result) { + firstAddUris.emplace_back(result); + }); + if (firstAddUris.empty()) { + return; + } + + auto subResults = proxy->SubscribeProxyData(firstAddUris, serviceCallback_); + std::vector failedKeys; + for (auto &subResult : subResults) { + opResult.emplace_back(subResult); + if (subResult.result_ != SUCCESS) { + failedKeys.emplace_back(subResult.uri_); + LOG_WARN("registered failed, uri is %{public}s, errCode", + DataShareStringUtils::Anonymous(subResult.uri_).c_str()); + } + } + + if (failedKeys.size() > 0) { + BaseCallbacks::DelProxyDataObservers(failedKeys, subscriber); + } + }); +} + +std::vector ProxyDataSubscriberManager::DelObservers(void *subscriber, + std::shared_ptr proxy) +{ + std::vector result = {}; + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return result; + } + return BaseCallbacks::DelObservers(subscriber, + [&proxy, this](const std::vector &lastDelKeys, std::vector &opResult) { + // delete all obs by subscriber + std::vector uris; + std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [&uris](const Key &key) { + uris.emplace_back(key.uri_); + }); + auto results = proxy->UnsubscribeProxyData(uris); + opResult.insert(opResult.end(), results.begin(), results.end()); + }); +} + +std::vector ProxyDataSubscriberManager::DelObservers(void *subscriber, + std::shared_ptr proxy, const std::vector &uris) +{ + std::vector result = {}; + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return result; + } + if (uris.empty()) { + return DelObservers(subscriber, proxy); + } + + std::vector keys; + std::for_each(uris.begin(), uris.end(), [&keys](auto &uri) { + keys.emplace_back(uri); + }); + return BaseCallbacks::DelProxyDataObservers(keys, subscriber, + [&proxy, this](const std::vector &lastDelKeys, std::vector &opResult) { + std::vector lastDelUris; + std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [&lastDelUris, this](auto &result) { + lastDelUris.emplace_back(result); + }); + if (lastDelUris.empty()) { + return; + } + auto unsubResult = proxy->UnsubscribeProxyData(lastDelUris); + opResult.insert(opResult.end(), unsubResult.begin(), unsubResult.end()); + }); +} + +void ProxyDataSubscriberManager::RecoverObservers(std::shared_ptr proxy) +{ + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return; + } + + std::vector uris; + std::vector keys = CallbacksManager::GetKeys(); + for (const auto& key : keys) { + uris.emplace_back(key.uri_); + } + auto results = proxy->SubscribeProxyData(uris, serviceCallback_); + for (const auto& result : results) { + if (result.result_ != SUCCESS) { + LOG_WARN("RecoverObservers failed, uri is %{public}s, errCode is %{public}d", + DataShareStringUtils::Anonymous(result.uri_).c_str(), result.result_); + } + } +} + +void ProxyDataSubscriberManager::Emit(std::vector &changeInfo) +{ + std::map, std::vector> results; + for (auto &data : changeInfo) { + ProxyDataObserverMapKey key(data.uri_); + auto callbacks = BaseCallbacks::GetEnabledObservers(key); + for (auto const &obs : callbacks) { + results[obs].emplace_back(data.changeType_, data.uri_, data.value_); + } + } + for (auto &[callback, node] : results) { + callback->OnChange(node); + } +} + +ProxyDataSubscriberManager &ProxyDataSubscriberManager::GetInstance() +{ + static ProxyDataSubscriberManager manager; + return manager; +} + +ProxyDataSubscriberManager::ProxyDataSubscriberManager() +{ + serviceCallback_ = new ProxyDataObserverStub([this](std::vector &changeInfo) { + Emit(changeInfo); + }); +} + +ProxyDataObserver::ProxyDataObserver(const ProxyDataCallback &callback) : callback_(callback) {} + +void ProxyDataObserver::OnChange(std::vector &changeInfo) +{ + callback_(changeInfo); +} + +bool ProxyDataObserver::operator==(const ProxyDataObserver &rhs) const +{ + return false; +} + +bool ProxyDataObserver::operator!=(const ProxyDataObserver &rhs) const +{ + return !(rhs == *this); +} +} // namespace DataShare +} // namespace OHOS diff --git a/data_share/frameworks/native/proxy/src/published_data_subscriber_manager.cpp b/data_share/frameworks/native/proxy/src/published_data_subscriber_manager.cpp index 9ecc1866..08e7f812 100644 --- a/data_share/frameworks/native/proxy/src/published_data_subscriber_manager.cpp +++ b/data_share/frameworks/native/proxy/src/published_data_subscriber_manager.cpp @@ -56,7 +56,8 @@ std::vector PublishedDataSubscriberManager::AddObservers(void * opResult.emplace_back(subResult); if (subResult.errCode_ != E_OK) { failedKeys.emplace_back(subResult.key_, subscriberId); - LOG_WARN("registered failed, uri is %{public}s", subResult.key_.c_str()); + LOG_WARN("registered failed, uri is %{public}s", + DataShareStringUtils::Anonymous(subResult.key_).c_str()); } } if (failedKeys.size() > 0) { @@ -147,7 +148,8 @@ std::vector PublishedDataSubscriberManager::EnableObservers(voi opResult.emplace_back(subResult); if (subResult.errCode_ != E_OK) { failedKeys.emplace_back(subResult.key_, subscriberId); - LOG_WARN("registered failed, uri is %{public}s", subResult.key_.c_str()); + LOG_WARN("registered failed, uri is %{public}s", + DataShareStringUtils::Anonymous(subResult.key_).c_str()); } } if (failedKeys.size() > 0) { @@ -168,7 +170,7 @@ std::vector PublishedDataSubscriberManager::DisableObservers(vo keys.emplace_back(uri, subscriberId); }); return BaseCallbacks::DisableObservers(keys, subscriber, - [&proxy, &subscriberId, this](const std::vector &lastDisabledKeys, + [&proxy, &subscriberId, subscriber, this](const std::vector &lastDisabledKeys, std::vector &opResult) { std::vector lastDisabledUris; std::for_each(lastDisabledKeys.begin(), lastDisabledKeys.end(), [&lastDisabledUris](auto &result) { @@ -179,7 +181,18 @@ std::vector PublishedDataSubscriberManager::DisableObservers(vo } auto results = proxy->DisableSubscribePublishedData(lastDisabledUris, subscriberId); - opResult.insert(opResult.end(), results.begin(), results.end()); + std::vector failedKeys; + for (auto &result : results) { + opResult.emplace_back(result); + if (result.errCode_ != E_OK) { + failedKeys.emplace_back(result.key_, subscriberId); + LOG_WARN("DisableObservers failed, uri is %{public}s, errCode is %{public}d", + DataShareStringUtils::Anonymous(result.key_).c_str(), result.errCode_); + } + } + if (failedKeys.size() > 0) { + BaseCallbacks::EnableObservers(failedKeys, subscriber); + } }); } @@ -200,7 +213,7 @@ void PublishedDataSubscriberManager::RecoverObservers(std::shared_ptr, PublishedDataChangeNode> results; for (auto &data : changeNode.datas_) { PublishedObserverMapKey key(data.key_, data.subscriberId_); + // Still set observer was notified flag and store data if there is no enabled observer. + BaseCallbacks::SetObserversNotifiedOnEnabled(key); auto callbacks = BaseCallbacks::GetEnabledObservers(key); - if (callbacks.empty()) { - LOG_WARN("%{private}s nobody subscribe, but still notify", data.key_.c_str()); - continue; - } lastChangeNodeMap_.Compute(key, [&data, &changeNode](const Key &, PublishedDataChangeNode &value) { + value.datas_.clear(); value.datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); value.ownerBundleName_ = changeNode.ownerBundleName_; return true; }); + + if (callbacks.empty()) { + LOG_WARN("%{public}s nobody subscribe, but still notify", + DataShareStringUtils::Anonymous(data.key_).c_str()); + continue; + } for (auto const &obs : callbacks) { results[obs].datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); } - BaseCallbacks::SetObserversNotifiedOnEnabled(key); } for (auto &[callback, node] : results) { node.ownerBundleName_ = changeNode.ownerBundleName_; @@ -268,7 +278,6 @@ void PublishedDataSubscriberManager::EmitOnEnable(std::map RdbSubscriberManager::AddObservers(void *subscriber opResult.emplace_back(subResult); if (subResult.errCode_ != E_OK) { failedKeys.emplace_back(subResult.key_, templateId); - LOG_WARN("registered failed, uri is %{public}s", subResult.key_.c_str()); + LOG_WARN("registered failed, uri is %{public}s", + DataShareStringUtils::Anonymous(subResult.key_).c_str()); } } if (!failedKeys.empty()) { @@ -156,7 +157,8 @@ std::vector RdbSubscriberManager::EnableObservers(void *subscri opResult.emplace_back(subResult); if (subResult.errCode_ != E_OK) { failedKeys.emplace_back(subResult.key_, templateId); - LOG_WARN("registered failed, uri is %{public}s", subResult.key_.c_str()); + LOG_WARN("registered failed, uri is %{public}s", + DataShareStringUtils::Anonymous(subResult.key_).c_str()); } } if (!failedKeys.empty()) { @@ -177,7 +179,8 @@ std::vector RdbSubscriberManager::DisableObservers(void *subscr keys.emplace_back(uri, templateId); }); return BaseCallbacks::DisableObservers(keys, subscriber, - [&proxy, &templateId, this](const std::vector &lastDisabledKeys, std::vector &opResult) { + [&proxy, subscriber, &templateId, this](const std::vector &lastDisabledKeys, + std::vector &opResult) { std::vector lastDisabledUris; std::for_each(lastDisabledKeys.begin(), lastDisabledKeys.end(), [&lastDisabledUris](auto &result) { lastDisabledUris.emplace_back(result); @@ -187,7 +190,18 @@ std::vector RdbSubscriberManager::DisableObservers(void *subscr } auto results = proxy->DisableSubscribeRdbData(lastDisabledUris, templateId); - opResult.insert(opResult.end(), results.begin(), results.end()); + std::vector failedKeys; + for (auto &result : results) { + opResult.emplace_back(result); + if (result.errCode_ != E_OK) { + failedKeys.emplace_back(result.key_, templateId); + LOG_WARN("DisableObservers failed, uri is %{public}s, errCode is %{public}d", + DataShareStringUtils::Anonymous(result.key_).c_str(), result.errCode_); + } + } + if (!failedKeys.empty()) { + BaseCallbacks::EnableObservers(failedKeys, subscriber); + } }); } @@ -206,8 +220,8 @@ void RdbSubscriberManager::RecoverObservers(std::shared_ptrSubscribeRdbData(uris, templateId, serviceCallback_); for (const auto& result : results) { if (result.errCode_ != E_OK) { - LOG_WARN("RecoverObservers failed, uri is %{public}s, errCode is %{public}d", result.key_.c_str(), - result.errCode_); + LOG_WARN("RecoverObservers failed, uri is %{public}s, errCode is %{public}d", + DataShareStringUtils::Anonymous(result.key_).c_str(), result.errCode_); } } } @@ -217,7 +231,7 @@ void RdbSubscriberManager::Emit(const RdbChangeNode &changeNode) { RdbObserverMapKey key(changeNode.uri_, changeNode.templateId_); lastChangeNodeMap_.InsertOrAssign(key, changeNode); - auto callbacks = BaseCallbacks::GetEnabledObservers(key); + auto callbacks = BaseCallbacks::GetObserversAndSetNotifiedOn(key); for (auto &obs : callbacks) { if (obs != nullptr) { LOG_INFO("Client send data to form, uri is %{public}s, subscriberId is %{public}" PRId64, @@ -225,7 +239,6 @@ void RdbSubscriberManager::Emit(const RdbChangeNode &changeNode) obs->OnChange(changeNode); } } - BaseCallbacks::SetObserversNotifiedOnEnabled(key); } void RdbSubscriberManager::Emit(const std::vector &keys, const std::shared_ptr &observer) @@ -258,8 +271,9 @@ void RdbSubscriberManager::EmitOnEnable(std::mapOnChange(node); } } diff --git a/data_share/interfaces/inner_api/BUILD.gn b/data_share/interfaces/inner_api/BUILD.gn index 7452123b..0c62798f 100644 --- a/data_share/interfaces/inner_api/BUILD.gn +++ b/data_share/interfaces/inner_api/BUILD.gn @@ -59,6 +59,7 @@ datashare_consumer_sources = [ "${datashare_native_consumer_path}/src/datashare_connection.cpp", "${datashare_native_consumer_path}/src/datashare_helper.cpp", "${datashare_native_consumer_path}/src/datashare_helper_impl.cpp", + "${datashare_native_consumer_path}/src/dataproxy_handle.cpp", "${datashare_native_consumer_path}/src/datashare_proxy.cpp", "${datashare_native_proxy_path}/src/ams_mgr_proxy.cpp", "${datashare_native_proxy_path}/src/data_proxy_observer_stub.cpp", @@ -67,6 +68,7 @@ datashare_consumer_sources = [ "${datashare_native_proxy_path}/src/idata_share_client_death_observer.cpp", "${datashare_native_proxy_path}/src/published_data_subscriber_manager.cpp", "${datashare_native_proxy_path}/src/rdb_subscriber_manager.cpp", + "${datashare_native_proxy_path}/src/proxy_data_subscriber_manager.cpp", ] datashare_consumer_external_deps = [ @@ -89,6 +91,7 @@ config("permission_config") { visibility = [ ":*" ] include_dirs = [ "common/include", + "dfx/include", "permission/include", "${datashare_common_native_path}/include", "${datashare_native_permission_path}/include", @@ -145,12 +148,15 @@ ohos_shared_library("datashare_permission") { cfi_cross_dso = true debug = false } - include_dirs = [] + include_dirs = [ "${datashare_native_dfx_path}/include" ] sources = [ "${datashare_common_native_path}/src/datashare_string_utils.cpp", + "${datashare_common_native_path}/src/serializable.cpp", "${datashare_native_permission_path}/src/data_share_called_config.cpp", "${datashare_native_permission_path}/src/data_share_permission.cpp", + "${datashare_native_permission_path}/src/data_share_config.cpp", + "${datashare_native_dfx_path}/src/hiview_datashare.cpp", ] configs = [ ":permission_config" ] public_configs = [ ":permission_public_config" ] @@ -168,6 +174,8 @@ ohos_shared_library("datashare_permission") { "bundle_framework:libappexecfwk_common", "c_utils:utils", "common_event_service:cesfwk_innerkits", + "hisysevent:libhisysevent", + "kv_store:distributeddata_inner", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -186,10 +194,15 @@ ohos_shared_library("datashare_provider") { cfi_cross_dso = true debug = false } - include_dirs = [ "${datashare_common_napi_path}/include" ] + include_dirs = [ + "${datashare_common_napi_path}/include", + "${datashare_native_dfx_path}/include", + "${datashare_native_permission_path}/include", + ] sources = [ "${datashare_common_native_path}/src/datashare_string_utils.cpp", + "${datashare_common_native_path}/src/serializable.cpp", "${datashare_native_provider_path}/src/datashare_ext_ability.cpp", "${datashare_native_provider_path}/src/datashare_ext_ability_context.cpp", "${datashare_native_provider_path}/src/datashare_stub.cpp", @@ -197,6 +210,8 @@ ohos_shared_library("datashare_provider") { "${datashare_native_provider_path}/src/datashare_uv_queue.cpp", "${datashare_native_provider_path}/src/js_datashare_ext_ability.cpp", "${datashare_native_provider_path}/src/js_datashare_ext_ability_context.cpp", + "${datashare_native_permission_path}/src/data_share_config.cpp", + "${datashare_native_dfx_path}/src/hiview_datashare.cpp", ] configs = [ ":ability_config" ] public_configs = [ ":datashare_public_config" ] diff --git a/data_share/interfaces/inner_api/common/BUILD.gn b/data_share/interfaces/inner_api/common/BUILD.gn index dd28c64e..ad3f4626 100644 --- a/data_share/interfaces/inner_api/common/BUILD.gn +++ b/data_share/interfaces/inner_api/common/BUILD.gn @@ -42,6 +42,7 @@ datashare_common_sources = [ "${datashare_common_native_path}/src/datashare_abs_result_set.cpp", "${datashare_common_native_path}/src/datashare_block_writer_impl.cpp", "${datashare_common_native_path}/src/datashare_itypes_utils.cpp", + "${datashare_common_native_path}/src/datashare_predicates.cpp", "${datashare_common_native_path}/src/datashare_result_set.cpp", "${datashare_common_native_path}/src/datashare_template.cpp", "${datashare_common_native_path}/src/datashare_valuebucket_convert.cpp", @@ -59,6 +60,7 @@ datashare_common_external_deps = [ "hisysevent:libhisysevent", "hitrace:hitrace_meter", "hitrace:libhitracechain", + "ipc:ipc_core", "ipc:ipc_single", "kv_store:distributeddata_inner", ] @@ -119,3 +121,31 @@ ohos_static_library("datashare_common_static") { subsystem_name = "distributeddatamgr" part_name = "data_share" } + +config("datashare_common_lite_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${datashare_base_path}/interfaces/inner_api/common/include", + "${datashare_base_path}/interfaces/inner_api/provider/include", + "${datashare_base_path}/interfaces/inner_api/consumer/include", + "${datashare_base_path}/frameworks/native/common/include", + ] +} + +ohos_static_library("datashare_common_lite") { + branch_protector_ret = "pac_ret" + sanitize = { + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + configs = [ ":ability_config" ] + public_configs = [ ":datashare_common_lite_config" ] + + subsystem_name = "distributeddatamgr" + part_name = "data_share" +} diff --git a/data_share/interfaces/inner_api/common/include/dataproxy_handle_common.h b/data_share/interfaces/inner_api/common/include/dataproxy_handle_common.h new file mode 100644 index 00000000..b609547f --- /dev/null +++ b/data_share/interfaces/inner_api/common/include/dataproxy_handle_common.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2022 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 DATASHARE_PROXY_COMMON_H +#define DATASHARE_PROXY_COMMON_H + +#include "datashare_observer.h" + +namespace OHOS { +namespace DataShare { +static constexpr int32_t URI_MAX_SIZE = 256; +static constexpr int32_t VALUE_MAX_SIZE = 4096; +static constexpr int32_t APPIDENTIFIER_MAX_SIZE = 128; +static constexpr int32_t URI_MAX_COUNT = 32; +static constexpr int32_t PROXY_DATA_MAX_COUNT = 32; +static constexpr int32_t ALLOW_LIST_MAX_COUNT = 256; +constexpr const char* ALLOW_ALL = "all"; +constexpr const char* DATA_PROXY_SCHEMA = "datashareproxy://"; + +enum DataProxyErrorCode { + SUCCESS = 0, + URI_NOT_EXIST, + NO_PERMISSION, + OVER_LIMIT, + INNER_ERROR, +}; + +/** + * @brief DataProxy Value Type . + */ +enum DataProxyValueType : int32_t { + /** DataProxy Value Types is int.*/ + VALUE_INT = 0, + /** DataProxy Value Types is double.*/ + VALUE_DOUBLE, + /** DataProxy Value Types is string.*/ + VALUE_STRING, + /** DataProxy Value Types is bool.*/ + VALUE_BOOL, +}; + +using DataProxyValue = std::variant; + +enum DataProxyType { + SHARED_CONFIG = 0, +}; + +struct DataProxyConfig { + DataProxyType type_; +}; + +struct DataShareProxyData { + /** + * @brief Constructor. + */ + DataShareProxyData() = default; + + /** + * @brief Destructor. + */ + ~DataShareProxyData() = default; + + DataShareProxyData(const std::string &uri, const DataProxyValue &value, + const std::vector &allowList = {}) : uri_(uri), value_(value), allowList_(allowList) {} + + std::string uri_; + DataProxyValue value_ = ""; + std::vector allowList_; + bool isValueUndefined = false; + bool isAllowListUndefined = false; +}; + +struct DataProxyResult { + DataProxyResult() = default; + DataProxyResult(const std::string &uri, const DataProxyErrorCode &result) : uri_(uri), result_(result) {} + std::string uri_; + DataProxyErrorCode result_; +}; + +struct DataProxyGetResult { + DataProxyGetResult() = default; + DataProxyGetResult(const std::string &uri, const DataProxyErrorCode &result, + const DataProxyValue &value = {}, const std::vector allowList = {}) + : uri_(uri), result_(result), value_(value), allowList_(allowList) {} + std::string uri_; + DataProxyErrorCode result_; + DataProxyValue value_; + std::vector allowList_; +}; + +struct DataProxyChangeInfo { + DataProxyChangeInfo() = default; + DataProxyChangeInfo(const DataShareObserver::ChangeType &changeType, + const std::string &uri, const DataProxyValue &value) + : changeType_(changeType), uri_(uri), value_(value) {} + DataShareObserver::ChangeType changeType_ = DataShareObserver::INVAILD; + std::string uri_; + DataProxyValue value_; +}; +} // namespace DataShare +} // namespace OHOS +#endif // DATASHARE_PROXY_COMMON_H \ No newline at end of file diff --git a/data_share/interfaces/inner_api/common/include/datashare_errno.h b/data_share/interfaces/inner_api/common/include/datashare_errno.h index d0e4bb04..090d50ff 100644 --- a/data_share/interfaces/inner_api/common/include/datashare_errno.h +++ b/data_share/interfaces/inner_api/common/include/datashare_errno.h @@ -16,6 +16,7 @@ #ifndef DATASHARE_ERRNO_H #define DATASHARE_ERRNO_H +#include "errors.h" namespace OHOS { namespace DataShare { /** @@ -193,6 +194,77 @@ constexpr int E_INVALID_USER_ID = (E_BASE + 68); * @brief The error code for not system app. */ constexpr int E_NOT_SYSTEM_APP = (E_BASE + 69); + +/** +* @brief The error code for register observer inner error. +*/ +constexpr int E_REGISTER_ERROR = (E_BASE + 70); + +/** +* @brief The error code for notify change inner error. +*/ +constexpr int E_NOTIFYCHANGE_ERROR = (E_BASE + 71); + +/** +* @brief The error code for timeout inner error. +*/ +constexpr int E_TIMEOUT_ERROR = (E_BASE + 72); + +/** +* @brief This error code indicates that the timeout interface is busy. +*/ +constexpr int E_ERROR_OVER_LIMIT_TASK = (E_BASE + 73); + +/** +* @brief The error code for pool is null. +*/ +constexpr int E_EXECUTOR_POOL_IS_NULL = (E_BASE + 74); + +/** +* @brief The error code for not hap. +*/ +constexpr int E_NOT_HAP = (E_BASE + 75); + +/** +* @brief The error code for get bundle info failed. +*/ +constexpr int E_GET_BUNDLEINFO_FAILED = (E_BASE + 76); + +/** +* @brief The error code for not datashare extension. +*/ +constexpr int E_NOT_DATASHARE_EXTENSION = (E_BASE + 77); + +/** +* @brief The error code for invalid uri. +*/ +constexpr int E_DATASHARE_INVALID_URI = (E_BASE + 78); + +/** +* @brief The error code for verify failed. +*/ +constexpr int E_VERIFY_FAILED = (E_BASE + 79); + +/** +* @brief The error code for permission denied. +*/ +constexpr int E_DATASHARE_PERMISSION_DENIED = (E_BASE + 80); + +/** +* @brief The error code for empty uri. +*/ +constexpr int E_EMPTY_URI = (E_BASE + 81); + +/** +* @brief The error code for uri not trust. +*/ +constexpr int E_NOT_IN_TRUSTS = (E_BASE + 82); + +/** +* @brief The error code for get caller failed. +*/ +constexpr int E_GET_CALLER_NAME_FAILED = (E_BASE + 83); + } // namespace DataShare } // namespace OHOS diff --git a/data_share/interfaces/inner_api/common/include/datashare_observer.h b/data_share/interfaces/inner_api/common/include/datashare_observer.h index dbfce03e..25e19bd4 100644 --- a/data_share/interfaces/inner_api/common/include/datashare_observer.h +++ b/data_share/interfaces/inner_api/common/include/datashare_observer.h @@ -19,6 +19,7 @@ #include #include #include +#include #include "uri.h" diff --git a/data_share/interfaces/inner_api/common/include/datashare_operation_statement.h b/data_share/interfaces/inner_api/common/include/datashare_operation_statement.h index a4688bca..90de3c0c 100644 --- a/data_share/interfaces/inner_api/common/include/datashare_operation_statement.h +++ b/data_share/interfaces/inner_api/common/include/datashare_operation_statement.h @@ -61,6 +61,10 @@ struct ExecResultSet { ExecErrorCode errorCode; std::vector results; }; + +struct RegisterOption { + bool isReconnect; +}; } } #endif // DATASHARE_OPERATION_STATEMENT_H diff --git a/data_share/interfaces/inner_api/common/include/datashare_option.h b/data_share/interfaces/inner_api/common/include/datashare_option.h new file mode 100644 index 00000000..fb94c0d4 --- /dev/null +++ b/data_share/interfaces/inner_api/common/include/datashare_option.h @@ -0,0 +1,25 @@ +/* + * 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 DATASHARE_OPTION_H +#define DATASHARE_OPTION_H + +namespace OHOS::DataShare { + +struct DataShareOption { + uint32_t timeout = 0; +}; +} +#endif // DATASHARE_OPTION_H diff --git a/data_share/interfaces/inner_api/common/include/datashare_predicates.h b/data_share/interfaces/inner_api/common/include/datashare_predicates.h index 69350d5d..ce00c068 100644 --- a/data_share/interfaces/inner_api/common/include/datashare_predicates.h +++ b/data_share/interfaces/inner_api/common/include/datashare_predicates.h @@ -22,6 +22,7 @@ #include "datashare_errno.h" #include "datashare_predicates_object.h" #include "datashare_predicates_objects.h" +#include "message_parcel.h" namespace OHOS { namespace DataShare { @@ -559,6 +560,16 @@ public: settingMode_ = settingMode; } + /** + * @brief The following four functions are used for serializing and deserializing objects + * to and from shared memory during Query and BatchInsert operations, + * which has a 128M upper limit. The upper limit of other method is 200k. + * Other methods remain unchanged. + */ + static bool Marshal(const DataSharePredicates &predicates, MessageParcel &parcel); + + static bool Unmarshal(DataSharePredicates &predicates, MessageParcel &parcel); + private: void SetOperationList(OperationType operationType, const MutliValue ¶m) { diff --git a/data_share/interfaces/inner_api/consumer/include/dataproxy_handle.h b/data_share/interfaces/inner_api/consumer/include/dataproxy_handle.h new file mode 100644 index 00000000..4b4065c7 --- /dev/null +++ b/data_share/interfaces/inner_api/consumer/include/dataproxy_handle.h @@ -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. + */ + +#ifndef DATAPROXY_HANDLE_H +#define DATAPROXY_HANDLE_H + +#include +#include + +#include "datashare_business_error.h" +#include "datashare_errno.h" +#include "dataproxy_handle_common.h" +#include "datashare_observer.h" + +namespace OHOS { + +namespace DataShare { +class DataProxyHandle : public std::enable_shared_from_this { +public: + /** + * @brief Destructor. + */ + ~DataProxyHandle() = default; + + /** + * @brief Creates a DataProxyHandle instance. + * + * @return Returns the created DataProxyHandle instance. + */ + static std::pair> Create(); + + std::vector PublishProxyData( + const std::vector &proxyData, const DataProxyConfig &proxyConfig); + + std::vector DeleteProxyData( + const std::vector &uris, const DataProxyConfig &proxyConfig); + + static std::vector GetProxyData( + const std::vector uris, const DataProxyConfig &proxyConfig); + + std::vector SubscribeProxyData(const std::vector &uris, + const std::function &changeNode)> &callback); + + std::vector UnsubscribeProxyData(const std::vector &uris); +}; +} // namespace DataShare +} // namespace OHOS +#endif // DATAPROXY_HANDLE_H \ No newline at end of file diff --git a/data_share/interfaces/inner_api/consumer/include/datashare_helper.h b/data_share/interfaces/inner_api/consumer/include/datashare_helper.h index 9d1a7c59..208150b5 100644 --- a/data_share/interfaces/inner_api/consumer/include/datashare_helper.h +++ b/data_share/interfaces/inner_api/consumer/include/datashare_helper.h @@ -22,17 +22,19 @@ #include #include -#include "data_ability_observer_interface.h" +#include "data_ability_observer_stub.h" #include "datashare_business_error.h" #include "datashare_errno.h" #include "datashare_observer.h" #include "datashare_operation_statement.h" +#include "datashare_option.h" #include "datashare_predicates.h" #include "datashare_result_set.h" #include "datashare_template.h" #include "datashare_values_bucket.h" #include "uri.h" + using Uri = OHOS::Uri; namespace OHOS { @@ -125,6 +127,20 @@ public: */ virtual int OpenFile(Uri &uri, const std::string &mode) = 0; + /** + * @brief Opens a file in a specified remote path. + * + * @param uri Indicates the path of the file to open. + * @param mode Indicates the file open mode, which can be "r" for read-only access, "w" for write-only access + * (erasing whatever data is currently in the file), "wt" for write access that truncates any existing file, + * "wa" for write-only access to append to any existing data, "rw" for read and write access on any existing data, + * or "rwt" for read and write access that truncates any existing file. + * @param errCode real error code. + * + * @return Returns the file descriptor. + */ + virtual int OpenFileWithErrCode(Uri &uri, const std::string &mode, int32_t &errCode) = 0; + /** * @brief This is like openFile, open a file that need to be able to return sub-sections of files,often assets * inside of their .hap. @@ -207,6 +223,21 @@ public: virtual std::shared_ptr Query(Uri &uri, const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError *businessError = nullptr) = 0; + /** + * @brief Query records from the database with timeout. + * + * @param uri Indicates the path of data to query. + * @param predicates Indicates filter criteria. You should define the processing logic when this parameter is null. + * @param columns Indicates the columns to query. If this parameter is null, all columns are queried. + * @param option Indicates the query options. The option includes a timeout period, in milliseconds. + * @param businessError Indicates the error by query. + * + * @return Returns the query result. + */ + virtual std::shared_ptr Query(Uri &uri, const DataSharePredicates &predicates, + std::vector &columns, DataShareOption &option, + DatashareBusinessError *businessError = nullptr) { return nullptr; } + /** * @brief Obtains the MIME type matching the data specified by the URI of the Data share. This method should be * implemented by a Data share. Data abilities supports general data types, including text, HTML, and JPEG. @@ -273,7 +304,20 @@ public: * @param dataObserver, Indicates the IDataAbilityObserver object. * @param isDescendants, Indicates the Whether to note the change of descendants. */ - void RegisterObserverExt(const Uri &uri, std::shared_ptr dataObserver, bool isDescendants); + void RegisterObserverExt(const Uri &uri, std::shared_ptr dataObserver, + bool isDescendants, bool isSystem = false); + + /** + * Registers an observer specified by the given Uri to the provider. This function is supported only when using + * non-silent DataShareHelper, and there is no default implemention in the provider side. It needs to be handled by + * the user. Otherwise, the provider side will do nothing but simply return error. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object. + * @param isDescendants, Indicates the Whether to note the change of descendants. + */ + virtual int RegisterObserverExtProvider(const Uri &uri, std::shared_ptr dataObserver, + bool isDescendants) = 0; /** * Deregisters an observer used for DataObsMgr specified by the given Uri. @@ -281,14 +325,33 @@ public: * @param uri, Indicates the path of the data to operate. * @param dataObserver, Indicates the IDataAbilityObserver object */ - void UnregisterObserverExt(const Uri &uri, std::shared_ptr dataObserver); + void UnregisterObserverExt(const Uri &uri, std::shared_ptr dataObserver, bool isSystem = false); + + /** + * Deregisters an observer specified by the given Uri to the provider. This function is supported only when using + * non-silent DataShareHelper, and there is no default implemention in the provider side. It needs to be handled by + * the user. Otherwise, the provider side will do nothing but simply return error. + * + * @param uri, Indicates the path of the data to operate. + * @param dataObserver, Indicates the IDataAbilityObserver object + */ + virtual int UnregisterObserverExtProvider(const Uri &uri, std::shared_ptr dataObserver) = 0; /** * Notifies the registered observers of a change to the data resource specified by Uris. * * @param changeInfo Indicates the info of the data to operate. */ - void NotifyChangeExt(const DataShareObserver::ChangeInfo &changeInfo); + void NotifyChangeExt(const DataShareObserver::ChangeInfo &changeInfo, bool isSystem = false); + + /** + * Notifies the registered observers of a change to the data resource specified by Uris. This function is supported + * only when using non-silent DataShareHelper, and there is no default implemention in the provider side. It needs + * to be handled by the user. Otherwise, the provider side will do nothing but simply return true. + * + * @param changeInfo Indicates the info of the data to operate. + */ + virtual void NotifyChangeExtProvider(const DataShareObserver::ChangeInfo &changeInfo) = 0; /** * @brief Converts the given uri that refer to the Data share into a normalized URI. A normalized URI can be used @@ -467,12 +530,15 @@ public: * @brief UserDefineFunc supports user-defined serialization of data and deserialization of reply. * It directly passes IPC parameters without any processing. * Through this interface, users can implement their own business logic. + * When implementing user customized logic, it is recommended to not send errCode using return. Instead, use the + * reply parameter to carry the errCode to avoid conflicts with IPC error codes. Return is intended to be used + * only to return the results of the IPC call. * * @param data Data sent from the consumer to the provider * @param reply Data returned from the provider to the consumer, including errCode * @param option The options of IPC call * - * @return Returns int32_t, the errCode of IPC call. + * @return Returns int32_t, the errCode returnd by IPC call to provider. */ virtual int32_t UserDefineFunc(MessageParcel &data, MessageParcel &reply, MessageOption &option); diff --git a/data_share/interfaces/inner_api/consumer/include/datashare_result_set.h b/data_share/interfaces/inner_api/consumer/include/datashare_result_set.h index 9a2a94d4..4f91e774 100644 --- a/data_share/interfaces/inner_api/consumer/include/datashare_result_set.h +++ b/data_share/interfaces/inner_api/consumer/include/datashare_result_set.h @@ -163,6 +163,11 @@ public: bool HasBlock(); std::shared_ptr GetBridge(); + + static bool Marshal(const std::shared_ptr resultSet, MessageParcel &parcel); + + static std::shared_ptr Unmarshal(MessageParcel &parcel); + protected: int CheckState(int columnIndex); void ClosedBlockAndBridge(); @@ -181,7 +186,7 @@ private: int endRowPos_ = -1; // The SharedBlock owned by this DataShareResultSet std::shared_mutex mutex_; - std::shared_ptr sharedBlock_ = nullptr; + std::shared_ptr sharedBlock_ = nullptr; std::shared_ptr blockWriter_ = nullptr; std::shared_ptr bridge_ = nullptr; }; diff --git a/data_share/interfaces/inner_api/consumer/libdatashare_consumer.map b/data_share/interfaces/inner_api/consumer/libdatashare_consumer.map index 19853035..2bca178e 100644 --- a/data_share/interfaces/inner_api/consumer/libdatashare_consumer.map +++ b/data_share/interfaces/inner_api/consumer/libdatashare_consumer.map @@ -14,6 +14,7 @@ 1.0 { global: *DataShareHelper*; + *DataProxyHandle*; *DataShareResultSet*; *DataShareAbsResultSet*; *DataShareSharedResultSet*; diff --git a/data_share/interfaces/inner_api/permission/include/data_share_permission.h b/data_share/interfaces/inner_api/permission/include/data_share_permission.h index 2b03231a..96228f4c 100644 --- a/data_share/interfaces/inner_api/permission/include/data_share_permission.h +++ b/data_share/interfaces/inner_api/permission/include/data_share_permission.h @@ -30,15 +30,49 @@ public: DataSharePermission() = default; ~DataSharePermission() = default; /** - * @brief Verify if tokenId has access perimission to uri. + * @brief Verify if tokenId has access permission to uri. * @param tokenId Unique identification of application. - * @param uri, Indicates the path of data to verify perimission. + * @param uri, Indicates the path of data to verify permission. * @param isRead, Obtain read permission for true and write permission for false. * @return Returns the error code. */ static int VerifyPermission(Security::AccessToken::AccessTokenID tokenId, const Uri &uri, bool isRead); + + static std::pair GetExtensionUriPermission(Uri &uri, + int32_t user, bool isRead); + static std::pair GetDataShareSilentUriPermission(uint32_t tokenId, + int32_t user, std::string &extUri, bool isRead); + + static int CheckExtensionTrusts(uint32_t consumerToken, uint32_t providerToken); + + static void ReportExtensionFault(int32_t errCode, uint32_t tokenId, + std::string &uri, std::string &bussinessType); + + static bool VerifyPermission(uint32_t tokenId, std::string &permission); + + static bool VerifyPermission(Uri &uri, uint32_t tokenId, std::string &permission, bool isExtension); + + static std::pair GetSilentUriPermission(Uri &uri, int32_t user, bool isRead); + + static int32_t UriIsTrust(Uri &uri); + + static std::pair GetUriPermission(Uri &uri, int32_t user, bool isRead, bool isExtension); + + static int32_t IsExtensionValid(uint32_t tokenId, uint32_t fullToken, int32_t user); +private: + + static constexpr const char *SCHEMA_DATASHARE = "datashare"; + static constexpr const char *SCHEMA_DATASHARE_PROXY = "datashareproxy"; + static constexpr const char *SCHEMA_PREFERENCE = "sharepreferences"; + static constexpr const char *SCHEMA_RDB = "rdb"; + static constexpr const char *SCHEMA_FILE = "file"; + + static void ReportExcuteFault(int32_t errCode, std::string &consumer, std::string &provider); + + static int VerifyDataObsPermissionInner(Security::AccessToken::AccessTokenID tokenID, + Uri &uri, bool isRead, bool &isTrust); }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/test/ets/data_share_ets/AppScope/app.json b/data_share/test/ets/data_share_ets/AppScope/app.json new file mode 100644 index 00000000..d2083237 --- /dev/null +++ b/data_share/test/ets/data_share_ets/AppScope/app.json @@ -0,0 +1,21 @@ +{ + "app":{ + "bundleName":"com.example.myapplication", + "vendor":"example", + "versionCode":1000000, + "versionName":"1.0.0", + "debug":false, + "icon":"$media:icon", + "label":"$string:app_name", + "description":"$string:description_application", + "distributedNotificationEnabled":true, + "keepAlive":true, + "singleUser":true, + "minAPIVersion":8, + "targetAPIVersion":8, + "car":{ + "apiCompatibleVersion":8, + "singleUser":false + } + } +} diff --git a/data_share/test/ets/data_share_ets/AppScope/resources/base/element/string.json b/data_share/test/ets/data_share_ets/AppScope/resources/base/element/string.json new file mode 100644 index 00000000..ee69f9a8 --- /dev/null +++ b/data_share/test/ets/data_share_ets/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string":[ + { + "name":"app_name", + "value":"ohosProject" + } + ] +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/corpus/init b/data_share/test/ets/data_share_ets/BUILD.gn similarity index 39% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/corpus/init rename to data_share/test/ets/data_share_ets/BUILD.gn index bc977bd9..42ebd7bf 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/corpus/init +++ b/data_share/test/ets/data_share_ets/BUILD.gn @@ -11,4 +11,35 @@ # See the License for the specific language governing permissions and # limitations under the License. -FUZZ \ No newline at end of file +import("//build/test.gni") + +ohos_js_stage_unittest("ActsDataShareEtsTest") { + hap_profile = "entry/src/main/module.json" + deps = [ + ":stageprejstest_js_assets", + ":stageprejstest_resources", + ] + ets2abc = true + certificate_profile = "signature/openharmony_sx.p7b" + hap_name = "ActsDataShareEtsTest" + subsystem_name = "distributeddatamgr" + part_name = "data_share" + module_out_path = "data_share/data_share/data_share_ets" +} +ohos_app_scope("stageprejstest_app_profile") { + app_profile = "AppScope/app.json" + sources = [ "AppScope/resources" ] +} +ohos_js_assets("stageprejstest_js_assets") { + source_dir = "entry/src/main/ets" +} +ohos_resources("stageprejstest_resources") { + sources = [ "entry/src/main/resources" ] + deps = [ ":stageprejstest_app_profile" ] + hap_profile = "entry/src/main/module.json" +} +group("stage_unittest") { + testonly = true + deps = [] + deps += [ ":ActsDataShareEtsTest" ] +} diff --git a/data_share/test/ets/data_share_ets/Test.json b/data_share/test/ets/data_share_ets/Test.json new file mode 100644 index 00000000..a8d9564b --- /dev/null +++ b/data_share/test/ets/data_share_ets/Test.json @@ -0,0 +1,27 @@ +{ + "description": "Configuration for hjunit demo Tests", + "driver": { + "type": "OHJSUnitTest", + "test-timeout": "180000", + "bundle-name": "com.example.myapplication", + "module-name": "testModule", + "shell-timeout": "600000", + "testcase-timeout": 70000 + }, + "kits": [ + { + "test-file-name": [ + "ActsDataShareEtsTest.hap" + ], + "type": "AppInstallKit", + "cleanup-apps": true + }, + { + "type": "ShellKit", + "teardown-command":[ + "bm uninstall -n com.example.myapplication" + ] + } + ] +} + diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/Application/AbilityStage.ts b/data_share/test/ets/data_share_ets/entry/src/main/ets/Application/AbilityStage.ts new file mode 100644 index 00000000..e0732e91 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/Application/AbilityStage.ts @@ -0,0 +1,22 @@ +// Copyright (c) 2023 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import AbilityStage from "@ohos.app.ability.AbilityStage" + +export default class MyAbilityStage extends AbilityStage { + onCreate() { + console.log('[Demo] MyAbilityStage onCreate'); + globalThis.stageOnCreateRun = 1; + globalThis.stageContext = this.context; + } +} diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/DataShareExtensionAbility/DataShareExtAbility.ts b/data_share/test/ets/data_share_ets/entry/src/main/ets/DataShareExtensionAbility/DataShareExtAbility.ts new file mode 100644 index 00000000..983f1199 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/DataShareExtensionAbility/DataShareExtAbility.ts @@ -0,0 +1,194 @@ +/* + * 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 Extension from '@ohos.application.DataShareExtensionAbility'; +import { UpdateOperation } from '@ohos.application.DataShareExtensionAbility'; +import rdb from '@ohos.data.relationalStore'; +import rpc from '@ohos.rpc'; + +let DB_NAME = "DB00.db"; +let TBL_NAME = "TBL00"; +let DDL_TBL_CREATE = "CREATE TABLE IF NOT EXISTS " ++ TBL_NAME ++ " (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, phoneNumber DOUBLE, isStudent BOOLEAN, Binary BINARY, number INTEGER)"; +let DDL_TABLE_USER_SQL = "CREATE TABLE IF NOT EXISTS user (userId INTEGER PRIMARY KEY AUTOINCREMENT, firstName TEXT, lastName TEXT, age INTEGER , balance DOUBLE NOT NULL)"; +let DDL_TABLE_BOOK_SQL = "CREATE TABLE IF NOT EXISTS book (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, userId INTEGER, FOREIGN KEY (userId) REFERENCES user (userId) ON UPDATE NO ACTION ON DELETE CASCADE)"; +let DDL_TABLE_PERMISSION1_SQL = "CREATE TABLE IF NOT EXISTS permission1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, phoneNumber DOUBLE, isStudent BOOLEAN, Binary BINARY, number INTEGER)"; +let DDL_TABLE_PERMISSION2_SQL = "CREATE TABLE IF NOT EXISTS permission2 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, phoneNumber DOUBLE, isStudent BOOLEAN, Binary BINARY, number INTEGER)"; + +let rdbStore; + +export default class +extends Extension { + async onCreate(want, callback) { + console.log('[ttt] [DataShareTest] DataShareExtAbility onCreate, want:' + want.abilityName); + console.log("[ttt] [DataShareTest] DataShareExtAbility onCreate this.context.databaseDir:" + this.context.databaseDir); + rdbStore = await rdb.getRdbStore(this.context, { name: DB_NAME, securityLevel: rdb.SecurityLevel.S1 }); + console.log('[ttt] [DataShareTest] DataShareExtAbility getRdbStore done'); + await rdbStore.executeSql(DDL_TBL_CREATE, []); + await rdbStore.executeSql(DDL_TABLE_USER_SQL, []); + await rdbStore.executeSql(DDL_TABLE_BOOK_SQL, []); + await rdbStore.executeSql(DDL_TABLE_PERMISSION1_SQL, []); + await rdbStore.executeSql(DDL_TABLE_PERMISSION2_SQL, []); + console.log('[ttt] [DataShareTest] DataShareExtAbility executeSql multiple tables done'); + let err = {"code":0}; + callback(err); + console.log('[ttt] [DataShareTest] DataShareExtAbility onCreate end'); + } + + async insert(uri, value, callback) { + console.info('[ttt] [DataShareTest] [insert] enter'); + if (value == null) { + console.info('[ttt] [DataShareTest] [insert] invalid valueBuckets'); + return; + } + + console.info('[ttt] [DataShareTest] [insert] getCallingTokenId:' + rpc.IPCSkeleton.getCallingTokenId()); + console.info('[ttt] [DataShareTest] [insert] value = ' + value); + console.info('[ttt] [DataShareTest] [insert] value = ' + JSON.stringify(value)); + await rdbStore.insert(TBL_NAME, value, function (err, ret) { + console.info('[ttt] [DataShareTest] [insert] callback ret:' + ret); + + if (callback != undefined) { + callback(err, ret); + } + }); + console.info('[ttt] [DataShareTest] [insert] leave'); + } + + async batchUpdate(operations, callback) { + let recordOps : Record> = operations; + let results : Record> = {}; + for (const [key, values] of Object.entries(recordOps)) { + let result : number[] = []; + for (const value of values) { + await rdbStore.update(TBL_NAME, value.values, value.predicates).then(async (rows) => { + console.info('[ttt] [DataShareTest] [batchUpdate] row count is ' + rows); + result.push(rows); + }).catch((err) => { + console.info("[ttt] [DataShareTest] [batchUpdate] failed, err is " + err); + result.push(-1) + }) + } + results[key] = result; + } + callback(null, results); + } + + async update(uri, predicates, value, callback) { + console.info('[ttt] [DataShareTest] [update] enter'); + if (predicates == null || predicates == undefined) { + console.info('[ttt] [DataShareTest] [update] invalid predicates'); + return; + } + console.info('[ttt] [DataShareTest] [update] values = ' + value); + console.info('[ttt] [DataShareTest] [update] values = ' + JSON.stringify(value)); + console.info('[ttt] [DataShareTest] [update] predicates = ' + predicates); + console.info('[ttt] [DataShareTest] [update] predicates = ' + JSON.stringify(predicates)); + try { + await rdbStore.update(TBL_NAME,value, predicates, function (err, ret) { + console.info('[ttt] [DataShareTest] [update] callback ret:' + ret); + console.info('[ttt] [DataShareTest] [update] callback err:' + err); + if (callback != undefined) { + callback(err, ret); + } + }); + } catch (err) { + console.error('[ttt] [DataShareTest] [update] error' + err); + } + console.info('[ttt] [DataShareTest] [update] leave'); + } + + async delete(uri, predicates, callback) { + console.info('[ttt] [DataShareTest] [delete] enter'); + if (predicates == null || predicates == undefined) { + console.info('[ttt] [DataShareTest] [delete] invalid predicates'); + return; + } + console.info('[ttt] [DataShareTest] [delete] predicates = ' + predicates); + console.info('[ttt] [DataShareTest] [delete] predicates = ' + JSON.stringify(predicates)); + try { + await rdbStore.delete(TBL_NAME,predicates, function (err, ret) { + console.info('[ttt] [DataShareTest] [delete] ret:' + ret); + if (callback != undefined) { + callback(err, ret); + } + }); + } catch (err) { + console.error('[ttt] [DataShareTest] [delete] error' + err); + } + console.info('[ttt] [DataShareTest] [delete] leave'); + } + + async query(uri, predicates, columns, callback) { + console.info('[ttt] [DataShareTest] [query] enter'); + if (predicates == null || predicates == undefined) { + console.info('[ttt] [DataShareTest] [query] invalid predicates'); + } + console.info('[ttt] [DataShareTest] [query] values = ' + columns); + console.info('[ttt] [DataShareTest] [query] values = ' + JSON.stringify(columns)); + console.info('[ttt] [DataShareTest] [query] predicates = ' + predicates); + console.info('[ttt] [DataShareTest] [query] predicates = ' + JSON.stringify(predicates)); + try { + await rdbStore.query(TBL_NAME, predicates, columns, function (err, resultSet) { + console.info('[ttt] [DataShareTest] [query] ret: ' + resultSet); + if (resultSet != undefined) { + console.info('[ttt] [DataShareTest] [query] resultSet.rowCount: ' + resultSet.rowCount); + } + if (callback != undefined) { + callback(err, resultSet); + } + }); + } catch (err) { + console.error(`[ttt] [DataShareTest] [query] error: code: ${err.code}, message: ${err.message} `); + callback(err, undefined); + } + console.info('[ttt] [DataShareTest] [query] leave'); + } + + async batchInsert(uri: string, valueBuckets, callback) { + console.info('[ttt] [DataShareTest] [batchInsert] enter'); + if (valueBuckets == null || valueBuckets.length == undefined) { + console.info('[ttt] [DataShareTest] [batchInsert] invalid valueBuckets'); + return; + } + console.info('[ttt] [DataShareTest] [batchInsert] valueBuckets.length:' + valueBuckets.length); + let resultNum = valueBuckets.length + await rdbStore.batchInsert(TBL_NAME, valueBuckets, function (err, ret) { + console.info('[ttt] [DataShareTest] [batchInsert] callback ret:' + ret); + if (callback != undefined) { + callback(err, ret); + } + }); + + console.info('[ttt] [DataShareTest] [batchInsert] leave'); + } + + async normalizeUri(uri: string, callback) { + console.info('[ttt] [DataShareTest] [normalizeUri] enter'); + let ret = "normalize+" + uri; + let err = {"code":0}; + await callback(err, ret); + console.info('[ttt] [DataShareTest] [normalizeUri] leave, ret:' + ret); + } + + async denormalizeUri(uri: string, callback) { + console.info('[ttt] [DataShareTest] [denormalizeUri] enter'); + let ret = "denormalize+" + uri; + let err = {"code":0}; + await callback(err, ret); + console.info('[ttt] [DataShareTest] [denormalizeUri] leave, ret:' + ret); + } +}; \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/MainAbility.ts b/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/MainAbility.ts new file mode 100644 index 00000000..fc92e47d --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/MainAbility.ts @@ -0,0 +1,51 @@ +// Copyright (c) 2023 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Ability from '@ohos.app.ability.UIAbility' +import common from '@ohos.app.ability.common' + +export default class MainAbility extends Ability { + onCreate(want, launchParam){ + // Ability is creating, initialize resources for this ability + AppStorage.setOrCreate('TestAbilityContext', this.context); + console.log('[Demo] MainAbility onCreate'); + globalThis.abilityWant = want; + } + + onDestroy() { + // Ability is destroying, release resources for this ability + console.log('[Demo] MainAbility onDestroy'); + } + + onWindowStageCreate(windowStage) { + // Main window is created, set main page for this ability + console.log('[Demo] MainAbility onWindowStageCreate'); + globalThis.abilityContext = this.context; + windowStage.setUIContent(this.context, "MainAbility/pages/index/index", null); + } + + onWindowStageDestroy() { + //Main window is destroyed, release UI related resources + console.log('[Demo] MainAbility onWindowStageDestroy'); + } + + onForeground() { + // Ability has brought to foreground + console.log('[Demo] MainAbility onForeground'); + } + + onBackground() { + // Ability has back to background + console.log('[Demo] MainAbility onBackground'); + } +}; \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/pages/index/index.ets b/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/pages/index/index.ets new file mode 100644 index 00000000..10b38297 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/pages/index/index.ets @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022 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 router from '@ohos.router'; + +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' +import { Hypium } from '@ohos/hypium' +import testsuite from '../../../test/List.test' + + +@Entry +@Component +struct Index { + + aboutToAppear(){ + console.info("start run testcase!!!!") + let abilityDelegator: any + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + let abilityDelegatorArguments: any + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + console.info('start run testcase!!!') + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) + } + + build() { + Flex({ direction:FlexDirection.Column, alignItems:ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('Hello World') + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(25) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(() => { + + }) + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/pages/second/second.ets b/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/pages/second/second.ets new file mode 100644 index 00000000..33d9ae45 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/MainAbility/pages/second/second.ets @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2022 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 router from '@system.router'; + +@Entry +@Component +struct Second { + private content: string = "Second Page" + + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text(`${this.content}`) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('back to index') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(() => { + router.back() + }) + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/TestAbility/TestAbility.ts b/data_share/test/ets/data_share_ets/entry/src/main/ets/TestAbility/TestAbility.ts new file mode 100644 index 00000000..f89a5dd5 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/TestAbility/TestAbility.ts @@ -0,0 +1,44 @@ +// Copyright (c) 2023 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import Ability from '@ohos.app.ability.UIAbility' + +export default class TestAbility extends Ability { + onCreate(want, launchParam) { + console.log('TestAbility onCreate'); + AppStorage.SetOrCreate("TestAbilityContext",this.context); + } + + onDestroy() { + console.log('TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage) { + console.log('TestAbility onWindowStageCreate'); + windowStage.setUIContent(this.context, 'TestAbility/pages/index', null); + + globalThis.abilityContext = this.context; + } + + onWindowStageDestroy() { + console.log('TestAbility onWindowStageDestroy'); + } + + onForeground() { + console.log('TestAbility onForeground'); + } + + onBackground() { + console.log('TestAbility onBackground'); + } +}; \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/TestAbility/pages/index.ets b/data_share/test/ets/data_share_ets/entry/src/main/ets/TestAbility/pages/index.ets new file mode 100644 index 00000000..b93567f9 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/TestAbility/pages/index.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022 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 router from '@ohos.router'; + +@Entry +@Component +struct Index { + aboutToAppear() { + console.info('TestAbility index aboutToAppear') + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts b/data_share/test/ets/data_share_ets/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts new file mode 100644 index 00000000..13026c5d --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,71 @@ +// Copyright (c) 2023 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import TestRunner from '@ohos.application.testRunner' +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +function translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s it', + '-s level', '-s testType', '-s size', '-s timeout' + ]) + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams = `${targetParams} ${key} ${parameters[key]}` + } + } + return targetParams.trim() +} + +async function onAbilityCreateCallback() { + console.log('onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + console.info('addAbilityMonitorCallback : ' + JSON.stringify(err)); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + console.info("OpenHarmonyTestRunner OnPrepare "); + } + + async onRun() { + console.log('OpenHarmonyTestRunner onRun run') + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.MainAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a com.example.myapplication.MainAbility' + ' -b ' + abilityDelegatorArguments.bundleName + cmd += ' '+translateParamsToString(abilityDelegatorArguments.parameters) + console.info('cmd : '+ cmd) + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + console.info('executeShellCommand : err : ' + JSON.stringify(err)); + console.info('executeShellCommand : data : ' + d.stdResult); + console.info('executeShellCommand : data : ' + d.exitCode); + }) + console.info('OpenHarmonyTestRunner onRun end'); + } +}; \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/rddbopen_fuzzer.h b/data_share/test/ets/data_share_ets/entry/src/main/ets/test/List.test.ets similarity index 71% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/rddbopen_fuzzer.h rename to data_share/test/ets/data_share_ets/entry/src/main/ets/test/List.test.ets index 6ec5dc5d..c71f850a 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/rddbopen_fuzzer.h +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/test/List.test.ets @@ -13,9 +13,10 @@ * limitations under the License. */ -#ifndef TRANSFERGRDTYPETOCOLTYPE_FUZZER_H -#define TRANSFERGRDTYPETOCOLTYPE_FUZZER_H +import DataSharePredicatesEtsTest from './dataSharePredicate.test.ets'; +import DataShareSubscribeTest from './dataShareSubscribe.test.ets'; -#define FUZZ_PROJECT_NAME "transfergrdtypetocoltype_fuzzer" - -#endif // TRANSFERGRDTYPETOCOLTYPE_FUZZER_H \ No newline at end of file +export default function testsuite() { + DataSharePredicatesEtsTest(); + DataShareSubscribeTest(); +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/test/dataSharePredicate.test.ets b/data_share/test/ets/data_share_ets/entry/src/main/ets/test/dataSharePredicate.test.ets new file mode 100644 index 00000000..1e062b37 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/test/dataSharePredicate.test.ets @@ -0,0 +1,352 @@ + +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level, Size, TestType } from "@ohos/hypium"; +import relationalStore from "@ohos.data.relationalStore"; +import dataSharePredicates from "@ohos.data.dataSharePredicates"; +import common from '@ohos.app.ability.common'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { BusinessError } from "@ohos.base"; + + +const STORE_CONFIG: relationalStore.StoreConfig = { + name: "rdbStore.db", + securityLevel: relationalStore.SecurityLevel.S1 +} +let rdbStore:relationalStore.RdbStore | undefined = undefined; +let table_name = "test"; +let DROP_TBL = "DROP TABLE IF EXISTS " + table_name; +let CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS " + + table_name + + " (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, isStudent BOOLEAN)"; +let TAG = "[dataSharePredicate_test]"; + +const delegator = AbilityDelegatorRegistry.getAbilityDelegator(); +const context = delegator.getAppContext().getApplicationContext(); + +async function generateTable() { + console.info(TAG + 'generateTable') + if (rdbStore != undefined) { + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: relationalStore.ValuesBucket = { + name: "ZhangSan", + age: 20, + 'isStudent': true, + } + await rdbStore.insert("test", valueBucket1) + const valueBucket2: relationalStore.ValuesBucket = { + name: "LiSi", + age: 21, + 'isStudent': true, + } + await rdbStore.insert("test", valueBucket2) + const valueBucket3: relationalStore.ValuesBucket = { + name: "WangWu", + age: 22, + 'isStudent': false, + } + await rdbStore.insert("test", valueBucket3) + const valueBucket4: relationalStore.ValuesBucket = { + name: "SunLiu", + age: 23, + 'isStudent': false, + } + await rdbStore.insert("test", valueBucket4) + const valueBucket5: relationalStore.ValuesBucket = { + name: "MaQi", + age: 24, + 'isStudent': true, + } + await rdbStore.insert("test", valueBucket5) + console.info(TAG + 'generateTable end') + } +} + +async function insertMoreData() { + console.info(TAG + 'insertMoreData') + if (rdbStore != undefined) { + const valueBucket1: relationalStore.ValuesBucket = { + name: "Steven", + age: 17, + 'isStudent': true, + } + await rdbStore.insert("test", valueBucket1) + const valueBucket2: relationalStore.ValuesBucket = { + name: "Jax", + age: 17, + 'isStudent': true, + } + await rdbStore.insert("test", valueBucket2) + const valueBucket3: relationalStore.ValuesBucket = { + name: "Green", + age: 17, + 'isStudent': false, + } + await rdbStore.insert("test", valueBucket3) + const valueBucket4: relationalStore.ValuesBucket = { + name: "List", + age: 14, + 'isStudent': false, + } + await rdbStore.insert("test", valueBucket4) + const valueBucket5: relationalStore.ValuesBucket = { + name: "Alice", + age: 24, + 'isStudent': true, + } + await rdbStore.insert("test", valueBucket5) + const valueBucket6: relationalStore.ValuesBucket = { + name: "Chary", + age: 24, + 'isStudent': true, + } + await rdbStore.insert("test", valueBucket6) + console.info(TAG + 'insertMoreData end') + } +} + +export default function DataSharePredicatesEtsTest() { + describe('DataSharePredicatesEtsTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll'); + await relationalStore.getRdbStore(context, STORE_CONFIG).then(async (store: relationalStore.RdbStore) => { + rdbStore = store; + console.info('ttt Get RdbStore successfully.') + }).catch((err: BusinessError) => { + console.error(`ttt Get RdbStore failed, code is ${err.code},message is ${err.message}`); + }) + }); + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + console.info(TAG + 'createTest data start'); + await generateTable(); + console.info(TAG + 'createTest data end'); + }) + afterEach(async () => { + console.info(TAG + 'afterEach'); + if (rdbStore != undefined) { + await rdbStore.executeSql(DROP_TBL); + } + }) + afterAll(async () => { + console.info(TAG + 'afterAll'); + relationalStore.deleteRdbStore(context, STORE_CONFIG.name).then(() => { + rdbStore = undefined; + console.info(TAG + 'Delete RdbStore successfully.'); + }).catch((err: BusinessError) => { + console.error(TAG + `Delete RdbStore failed, code is ${err.code},message is ${err.message}`); + }) + }); + + + + it('testDataSharePredicate_0001', 0, async () => { + console.log(TAG + "************* testDataSharePredicate_0001 start *************"); + const valueBucket: relationalStore.ValuesBucket = { + 'name': 'Steven', + 'age': 28, + 'isStudent': false, + }; + await rdbStore?.insert(table_name, valueBucket); + try { + let dp = new dataSharePredicates.DataSharePredicates(); + dp.equalTo("age", 28); + let resultSets = await (rdbStore as relationalStore.RdbStore).query(table_name, dp, ["*"]); + console.log(TAG + "rowCount is : " + resultSets.rowCount); + expect(resultSets.goToFirstRow()).assertEqual(true); + const id = resultSets.getLong(resultSets.getColumnIndex("id")); + const name = resultSets.getString(resultSets.getColumnIndex("name")); + const age = resultSets.getLong(resultSets.getColumnIndex("age")); + const isStudent = resultSets.getValue(resultSets.getColumnIndex("isStudent")); + expect(id).assertEqual(6); + expect(name).assertEqual("Steven"); + expect(age).assertEqual(28); + expect(isStudent).assertEqual(0); + + resultSets.close(); + } catch (err) { + console.error(TAG + `Query failed, code is ${err.code},message is ${err.message}`); + } + + console.log(TAG + "************* testDataSharePredicate_0001 end *************"); + }) + + it('testDataSharePredicate_0002', 0, async () => { + console.log(TAG + "************* testDataSharePredicate_0002 start *************"); + const valueBucket: relationalStore.ValuesBucket = { + 'name': 'Steven', + 'age': 20, + 'isStudent': false, + }; + let rowId = await rdbStore?.insert(table_name, valueBucket); + try { + let dp = new dataSharePredicates.DataSharePredicates(); + dp.equalTo("age", 20).orderByAsc("name"); + let resultSets = await (rdbStore as relationalStore.RdbStore).query(table_name, dp, ["*"]); + + expect(resultSets.rowCount).assertEqual(2); + expect(resultSets.goToRow(0)).assertEqual(true); + let id = resultSets.getLong(resultSets.getColumnIndex("id")); + let name = resultSets.getString(resultSets.getColumnIndex("name")); + let age = resultSets.getLong(resultSets.getColumnIndex("age")); + let isStudent = resultSets.getValue(resultSets.getColumnIndex("isStudent")); + expect(id).assertEqual(6); + expect(name).assertEqual("Steven"); + expect(age).assertEqual(20); + expect(isStudent).assertEqual(0); + expect(resultSets.goToNextRow()).assertEqual(true); + id = resultSets.getLong(resultSets.getColumnIndex("id")); + name = resultSets.getString(resultSets.getColumnIndex("name")); + age = resultSets.getLong(resultSets.getColumnIndex("age")); + isStudent = resultSets.getValue(resultSets.getColumnIndex("isStudent")); + expect(id).assertEqual(1); + expect(name).assertEqual("ZhangSan"); + expect(age).assertEqual(20); + expect(isStudent).assertEqual(1); + resultSets.close(); + } catch (err) { + console.error(TAG + `Query failed, code is ${err.code},message is ${err.message}`); + } + + console.log(TAG + "************* testDataSharePredicate_0002 end *************"); + }) + + it('testDataSharePredicate_0003', 0, async () => { + console.log(TAG + "************* testDataSharePredicate_0003 start *************"); + let dp = new dataSharePredicates.DataSharePredicates(); + dp.equalTo("name", "LiSi").and(); + const valueBucket: relationalStore.ValuesBucket = { + 'name': 'Steven', + 'age': 20, + 'isStudent': false, + }; + const valueBucket1: relationalStore.ValuesBucket = { + 'name': 'Steven', + 'age': 24, + 'isStudent': true, + }; + if (rdbStore != undefined) { + await rdbStore.update(table_name, valueBucket, dp); + await rdbStore.insert(table_name, valueBucket1); + } + + try { + dp = new dataSharePredicates.DataSharePredicates(); + dp.equalTo("name", "Steven").and().equalTo("age", 24); + let resultSets = await (rdbStore as relationalStore.RdbStore).query(table_name, dp, ["*"]); + + expect(resultSets.rowCount).assertEqual(1); + expect(resultSets.goToRow(0)).assertEqual(true); + let id = resultSets.getLong(resultSets.getColumnIndex("id")); + let name = resultSets.getString(resultSets.getColumnIndex("name")); + let age = resultSets.getLong(resultSets.getColumnIndex("age")); + let isStudent = resultSets.getValue(resultSets.getColumnIndex("isStudent")); + expect(id).assertEqual(6); + expect(name).assertEqual("Steven"); + expect(age).assertEqual(24); + expect(isStudent).assertEqual(1); + } catch (err) { + console.error(TAG + `Query failed, code is ${err.code},message is ${err.message}`); + } + + console.log(TAG + "************* testDataSharePredicate_0003 end *************"); + }) + + it('testDataSharePredicate_0004', 0, async () => { + console.log(TAG + "************* testDataSharePredicate_0004 start *************"); + try { + let dp = new dataSharePredicates.DataSharePredicates(); + dp.in("isStudent", [true, false]).limit(0, -1); + let resultSets = await (rdbStore as relationalStore.RdbStore).query(table_name, dp, ["*"]); + + expect(resultSets.rowCount).assertEqual(5); + } catch (err) { + console.error(TAG + `Query failed, code is ${err.code},message is ${err.message}`); + } + + console.log(TAG + "************* testDataSharePredicate_0004 end *************"); + }) + + it('testDataSharePredicate_0005', 0, async () => { + console.log(TAG + "************* testDataSharePredicate_0005 start *************"); + if (rdbStore != undefined) { + await insertMoreData; + } + try { + let dp = new dataSharePredicates.DataSharePredicates(); + dp.limit(1, -1); + let resultSets = await (rdbStore as relationalStore.RdbStore).query(table_name, dp, ["*"]); + expect(resultSets.rowCount).assertEqual(1); + expect(resultSets.goToRow(0)).assertEqual(true); + let id = resultSets.getLong(resultSets.getColumnIndex("id")); + let name = resultSets.getString(resultSets.getColumnIndex("name")); + let age = resultSets.getLong(resultSets.getColumnIndex("age")); + let isStudent = resultSets.getValue(resultSets.getColumnIndex("isStudent")); + expect(id).assertEqual(1); + expect(name).assertEqual("ZhangSan"); + expect(age).assertEqual(20); + expect(isStudent).assertEqual(1); + } catch (err) { + console.error(TAG + `Query failed, code is ${err.code},message is ${err.message}`); + } + + console.log(TAG + "************* testDataSharePredicate_0005 end *************"); + }) + + it('testDataSharePredicate_0006', 0, async () => { + console.log(TAG + "************* testDataSharePredicate_0006 start *************"); + if (rdbStore != undefined) { + await insertMoreData; + } + try { + let dp = new dataSharePredicates.DataSharePredicates(); + dp.limit(1, 3); + let resultSets = await (rdbStore as relationalStore.RdbStore).query(table_name, dp, ["*"]); + expect(resultSets.rowCount).assertEqual(1); + expect(resultSets.goToRow(0)).assertEqual(true); + let id = resultSets.getLong(resultSets.getColumnIndex("id")); + let name = resultSets.getString(resultSets.getColumnIndex("name")); + let age = resultSets.getLong(resultSets.getColumnIndex("age")); + let isStudent = resultSets.getValue(resultSets.getColumnIndex("isStudent")); + expect(id).assertEqual(4); + expect(name).assertEqual("SunLiu"); + expect(age).assertEqual(23); + expect(isStudent).assertEqual(0); + } catch (err) { + console.error(TAG + `Query failed, code is ${err.code},message is ${err.message}`); + } + + console.log(TAG + "************* testDataSharePredicate_0006 end *************"); + }) + + it('testDataSharePredicate_0007', 0, async () => { + console.log(TAG + "************* testDataSharePredicate_0007 start *************"); + if (rdbStore != undefined) { + await insertMoreData; + } + try { + let dp = new dataSharePredicates.DataSharePredicates(); + dp.limit(1, 12); + let resultSets = await (rdbStore as relationalStore.RdbStore).query(table_name, dp, ["*"]); + expect(resultSets.rowCount).assertEqual(0); + } catch (err) { + console.error(TAG + `Query failed, code is ${err.code},message is ${err.message}`); + } + + console.log(TAG + "************* testDataSharePredicate_0007 end *************"); + }) + }) +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/ets/test/dataShareSubscribe.test.ets b/data_share/test/ets/data_share_ets/entry/src/main/ets/test/dataShareSubscribe.test.ets new file mode 100644 index 00000000..fd3451df --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/ets/test/dataShareSubscribe.test.ets @@ -0,0 +1,615 @@ + +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level, Size, TestType } from "@ohos/hypium"; +import relationalStore from "@ohos.data.relationalStore"; +import dataSharePredicates from "@ohos.data.dataSharePredicates"; +import common from '@ohos.app.ability.common'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { BusinessError } from "@ohos.base"; +import dataShare from '@ohos.data.dataShare' +import { ValuesBucket } from '@ohos.data.ValuesBucket'; + +let TAG = "[dataShareSubscribeTest_test]"; +let context: common.UIAbilityContext; +let uri1 = ("datashare:///com.example.myapplication/test"); +let uri2 = ("datashareproxy://com.example.myapplication/entry/DB00/TBL00"); +let dataShareHelper: dataShare.DataShareHelper | undefined = undefined +let da = new dataSharePredicates.DataSharePredicates(); +da.equalTo("name", "WangWu"); +let va: ValuesBucket = { + "name": "WangWu", + "age": 20 +} + +let va_change: ValuesBucket = { + "name": "LiSi", + "age": 18 +} +let people: Array = new Array(1); +people[0] = { + name: 'ZhangSan', age: 31 +}; +let changeData: dataShare.ChangeInfo = { + type: dataShare.ChangeType.DELETE, uri: uri1, values: people +}; +let TEST_TIMEOUT = 2000 //means 2000ms.timeout occurs,testcases failed + +export default function DataShareSubscribeTest() { + describe('DataShareSubscribeTest', () => { + beforeAll(async () => { + context = AppStorage.get('TestAbilityContext') as common.UIAbilityContext; + console.info(TAG + 'beforeAll'); + }) + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + }) + afterEach(async () => { + console.info(TAG + 'afterEach'); + }) + afterAll(async () => { + console.info(TAG + 'afterAll'); + }) + + /** + * @tc.name: testNonSilentSubscribe001 + * @tc.desc: test Non-silent subscribe, then notifyChange uri + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: trigger the callback + */ + it('testNonSilentSubscribe001', 0, async (done:Function) => { + console.log(TAG + "************* testNonSilentSubscribe001 start *************"); + const timeoutTimer = setTimeout(() => { + console.log(TAG + "************* testNonSilentSubscribe001 timeout *************"); + try { + expect(false).assertTrue(); + } catch (err) { + done(err); + } + }, TEST_TIMEOUT); + let onCallback: () => void = (): void => { + console.log(TAG + "************* testNonSilentSubscribe001 callback *************"); + clearTimeout(timeoutTimer); + expect(true).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri1); + await dataShareHelper.on("dataChange", uri1, onCallback); + await dataShareHelper.notifyChange(uri1); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testNonSilentSubscribe001 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testNonSilentSubscribe001 end *************"); + }) + + /** + * @tc.name: testNonSilentSubscribe002 + * @tc.desc: test Non-silent subscribe with info, then notifyChange uri + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: trigger the callback with info + */ + it('testNonSilentSubscribe002', 0, async (done:Function) => { + console.log(TAG + "************* testNonSilentSubscribe002 start *************"); + const timeoutTimer = setTimeout(() => { + try { + expect(false).assertTrue(); + } catch (err) { + done(err); + } + }, TEST_TIMEOUT); + let onCallback = (error:BusinessError, ChangeInfo:dataShare.ChangeInfo) => { + console.log(TAG + "************* testNonSilentSubscribe002 callback *************"); + clearTimeout(timeoutTimer); + expect(true).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri1); + await dataShareHelper.on('dataChange', dataShare.SubscriptionType.SUBSCRIPTION_TYPE_EXACT_URI, uri1, onCallback); + await dataShareHelper.notifyChange(changeData); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testNonSilentSubscribe002 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testNonSilentSubscribe002 end *************"); + }) + + /** + * @tc.name: testNonSilentSubscribe003 + * @tc.desc: test Non-silent subscribe then cancel, and then notifyChange uri + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: no trigger the callback + */ + it('testNonSilentSubscribe003', 0, async (done:Function) => { + console.log(TAG + "************* testNonSilentSubscribe003 start *************"); + const timeoutTimer = setTimeout(() => { + expect(true).assertTrue(); + done(); + }, TEST_TIMEOUT); + let onCallback: () => void = (): void => { + console.log(TAG + "************* testNonSilentSubscribe003 callback *************"); + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri1); + await dataShareHelper.on("dataChange", uri1, onCallback); + await dataShareHelper.off("dataChange", uri1, onCallback); + await dataShareHelper.notifyChange(uri1); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testNonSilentSubscribe003 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testNonSilentSubscribe003 end *************"); + }) + + /** + * @tc.name: testNonSilentSubscribe004 + * @tc.desc: test Non-silent subscribe with info then cancel, and then notifyChange uri + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: no trigger the callback + */ + it('testNonSilentSubscribe004', 0, async (done:Function) => { + console.log(TAG + "************* testNonSilentSubscribe004 start *************"); + const timeoutTimer = setTimeout(() => { + expect(true).assertTrue(); + done(); + }, TEST_TIMEOUT); + let onCallback = (error:BusinessError, ChangeInfo:dataShare.ChangeInfo) => { + console.log(TAG + "************* testNonSilentSubscribe004 callback *************"); + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri1); + await dataShareHelper.on('dataChange', dataShare.SubscriptionType.SUBSCRIPTION_TYPE_EXACT_URI, uri1, onCallback); + await dataShareHelper.off('dataChange', dataShare.SubscriptionType.SUBSCRIPTION_TYPE_EXACT_URI, uri1, onCallback); + await dataShareHelper.notifyChange(changeData); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testNonSilentSubscribe004 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testNonSilentSubscribe004 end *************"); + }) + + /** + * @tc.name: testNonSilentSubscribe005 + * @tc.desc: test Non-silent subscribe with info and without info, and then notifyChange uri + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: trigger the callback + */ + it('testNonSilentSubscribe005', 0, async (done:Function) => { + console.log(TAG + "************* testNonSilentSubscribe005 start *************"); + const timeoutTimer = setTimeout(() => { + try { + expect(false).assertTrue(); + } catch (err) { + done(err); + } + }, TEST_TIMEOUT); + let onCallback1: () => void = (): void => { + clearTimeout(timeoutTimer); + console.log(TAG + "************* testNonSilentSubscribe005 callback *************"); + expect(true).assertTrue(); + done(); + } + let onCallback2 = (error:BusinessError, ChangeInfo:dataShare.ChangeInfo) => { + console.log(TAG + "************* testNonSilentSubscribe005 callback *************"); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri1); + await dataShareHelper.on("dataChange", uri1, onCallback1); + await dataShareHelper.on('dataChange', dataShare.SubscriptionType.SUBSCRIPTION_TYPE_EXACT_URI, uri1, onCallback2); + await dataShareHelper.notifyChange(uri1); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testNonSilentSubscribe005 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testNonSilentSubscribe005 end *************"); + }) + + /** + * @tc.name: testNonSilentSubscribe005 + * @tc.desc: test Non-silent subscribe with info and without info, and then notifyChange uri + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: trigger the callback whit info + */ + it('testNonSilentSubscribe006', 0, async (done:Function) => { + console.log(TAG + "************* testNonSilentSubscribe006 start *************"); + const timeoutTimer = setTimeout(() => { + try { + expect(false).assertTrue(); + } catch (err) { + done(err); + } + }, TEST_TIMEOUT); + let onCallback1: () => void = (): void => { + expect(true).assertTrue(); + } + let onCallback2 = (error:BusinessError, ChangeInfo:dataShare.ChangeInfo) => { + clearTimeout(timeoutTimer); + console.error(`**** Observer callback **** type: ${ChangeInfo.type}, uri: ${ChangeInfo.uri},values: ${ChangeInfo.values} `); + expect(ChangeInfo.type).assertEqual(1); + expect(ChangeInfo.uri).assertEqual(uri1); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri1); + await dataShareHelper.on("dataChange", uri1, onCallback1); + await dataShareHelper.on('dataChange', dataShare.SubscriptionType.SUBSCRIPTION_TYPE_EXACT_URI, uri1, onCallback2); + await dataShareHelper.notifyChange(changeData); + } catch (err) { + console.error(`testNonSilentSubscribe006 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + } + console.log(TAG + "************* testNonSilentSubscribe006 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe001 + * @tc.desc: test silent subscribe, and then insert data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: trigger the callback + */ + it('testSilentSubscribe001', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe001 start *************"); + const timeoutTimer = setTimeout(() => { + try { + expect(false).assertTrue(); + } catch (err) { + done(err); + } + }, TEST_TIMEOUT); + let onCallback: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(true).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.on("dataChange", uri2, onCallback); + await dataShareHelper.insert(uri2, va); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe001 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe001 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe002 + * @tc.desc: test silent subscribe, and then update data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: trigger the callback + */ + it('testSilentSubscribe002', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe002 start *************"); + const timeoutTimer = setTimeout(() => { + try { + expect(false).assertTrue(); + } catch (err) { + done(err); + } + }, TEST_TIMEOUT); + let onCallback: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(true).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.insert(uri2, va); + await dataShareHelper.on("dataChange", uri2, onCallback); + await dataShareHelper.update(uri2, da, va); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe002 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe002 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe003 + * @tc.desc: test silent subscribe, and then delete data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: trigger the callback + */ + it('testSilentSubscribe003', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe003 start *************"); + const timeoutTimer = setTimeout(() => { + try { + expect(false).assertTrue(); + } catch (err) { + done(err); + } + }, TEST_TIMEOUT); + let onCallback: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(true).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.insert(uri2, va); + await dataShareHelper.on("dataChange", uri2, onCallback); + await dataShareHelper.delete(uri2, da); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe003 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe003 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe004 + * @tc.desc: test silent subscribe then cancel, and then insert data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: no trigger the callback + */ + it('testSilentSubscribe004', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe004 start *************"); + const timeoutTimer = setTimeout(() => { + expect(true).assertTrue(); + done(); + }, TEST_TIMEOUT); + let onCallback: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.on("dataChange", uri2, onCallback); + await dataShareHelper.off("dataChange", uri2, onCallback); + await dataShareHelper.insert(uri2, va); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe004 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe004 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe005 + * @tc.desc: test silent subscribe then cancel, and then update data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: no trigger the callback + */ + it('testSilentSubscribe005', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe005 start *************"); + const timeoutTimer = setTimeout(() => { + expect(true).assertTrue(); + done(); + }, TEST_TIMEOUT); + let onCallback: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.insert(uri2, va); + await dataShareHelper.on("dataChange", uri2, onCallback); + await dataShareHelper.off("dataChange", uri2, onCallback); + await dataShareHelper.update(uri2, da, va); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe005 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe005 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe006 + * @tc.desc: test silent subscribe then cancel, and then delete data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: no trigger the callback + */ + it('testSilentSubscribe006', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe006 start *************"); + const timeoutTimer = setTimeout(() => { + expect(true).assertTrue(); + done(); + }, TEST_TIMEOUT); + let onCallback: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.insert(uri2, va); + await dataShareHelper.on("dataChange", uri2, onCallback); + await dataShareHelper.off("dataChange", uri2, onCallback); + await dataShareHelper.delete(uri2, da); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe006 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe006 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe007 + * @tc.desc: test silent subscribe whit info and without info then cancel, and then insert data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: no trigger the callback + */ + it('testSilentSubscribe007', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe007 start *************"); + const timeoutTimer = setTimeout(() => { + expect(true).assertTrue(); + done(); + }, TEST_TIMEOUT); + let onCallback1: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + let onCallback2: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.on("dataChange", uri2, onCallback1); + await dataShareHelper.on("dataChange", uri2, onCallback2); + await dataShareHelper.off("dataChange", uri2); + await dataShareHelper.insert(uri2, va); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe007 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe007 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe008 + * @tc.desc: test silent subscribe whit info and without info then cancel, and then updata data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: no trigger the callback + */ + it('testSilentSubscribe008', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe008 start *************"); + const timeoutTimer = setTimeout(() => { + expect(true).assertTrue(); + done(); + }, TEST_TIMEOUT); + let onCallback1: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + let onCallback2: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.insert(uri2, va); + await dataShareHelper.on("dataChange", uri2, onCallback1); + await dataShareHelper.on("dataChange", uri2, onCallback2); + await dataShareHelper.off("dataChange", uri2); + await dataShareHelper.update(uri2, da, va); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe008 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe008 end *************"); + }) + + /** + * @tc.name: testSilentSubscribe009 + * @tc.desc: test silent subscribe whit info and without info then cancel, and then delete data + * @tc.type: FUNC + * @tc.require:issue + * @tc.precon: None + * @tc.experct: no trigger the callback + */ + it('testSilentSubscribe009', 0, async (done:Function) => { + console.log(TAG + "************* testSilentSubscribe009 start *************"); + const timeoutTimer = setTimeout(() => { + expect(true).assertTrue(); + done(); + }, TEST_TIMEOUT); + let onCallback1: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + let onCallback2: () => void = (): void => { + clearTimeout(timeoutTimer); + expect(false).assertTrue(); + done(); + } + try { + dataShareHelper = await dataShare.createDataShareHelper(context, uri2, {isProxy : true}); + await dataShareHelper.insert(uri2, va); + await dataShareHelper.on("dataChange", uri2, onCallback1); + await dataShareHelper.on("dataChange", uri2, onCallback2); + await dataShareHelper.off("dataChange", uri2); + await dataShareHelper.delete(uri2, da); + } catch (err) { + clearTimeout(timeoutTimer); + console.error(`testSilentSubscribe009 false,error: code: ${err.code}, message: ${err.message} `); + expect(false).assertTrue(); + done(); + } + console.log(TAG + "************* testSilentSubscribe009 end *************"); + }) + + }) +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/module.json b/data_share/test/ets/data_share_ets/entry/src/main/module.json new file mode 100644 index 00000000..11028f0a --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/module.json @@ -0,0 +1,92 @@ +{ + "module": { + "name": "testModule", + "type": "entry", + "srcEntrance": "./ets/Application/AbilityStage.ts", + "description": "$string:testModule_entry_dsc", + "mainElement": "com.example.myapplication.MainAbility", + "deviceTypes": [ + "default", + "tablet", + "2in1", + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "uiSyntax": "ets", + "pages": "$profile:main_pages", + "metadata": [ + { + "name": "MetaData1", + "value": "MetaDataValue", + "resource": "$profile:shortcuts_config" + } + ], + "abilities": [ + { + "name": "com.example.myapplication.MainAbility", + "srcEntrance": "./ets/MainAbility/MainAbility.ts", + "description": "$string:testModule_entry_main", + "icon": "$media:icon", + "label": "$string:entry_label", + "visible": true, + "launchType": "singleton", + "orientation": "portrait", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.GET_BUNDLE_INFO", + "reason": "$string:permission_reason", + "usedScene": { + "abilities": [ + "MainAbility" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.READ_CALENDAR", + "reason": "$string:permission_reason", + "usedScene": { + "abilities": [ + "MainAbility" + ], + "when": "inuse" + } + } + ], + "proxyData": [ + { + "uri": "datashareproxy://com.example.myapplication/entry/DB00/TBL00", + "requiredReadPermission": "ohos.permission.GET_BUNDLE_INFO", + "requiredWritePermission": "ohos.permission.GET_BUNDLE_INFO", + "metadata": { + "name": "dataProperties", + "resource": "$profile:test" + } + } + ], + "extensionAbilities": [ + { + "srcEntry": "./ets/DataShareExtensionAbility/DataShareExtAbility.ts", + "name": "DataShareExtAbility", + "icon": "$media:icon", + "description": "$string:description_application", + "type": "dataShare", + "uri": "datashare://com.example.myapplication", + "visible": true + } + ] + } +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/resources/base/element/string.json b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/element/string.json new file mode 100644 index 00000000..a4e9ba5b --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/element/string.json @@ -0,0 +1,44 @@ +{ + "string": [ + { + "name": "testModule_entry_dsc", + "value": "i am an entry for testModule" + }, + { + "name": "testModule_entry_main", + "value": "the testModule entry ability" + }, + { + "name": "entry_label", + "value": "ActsContextTest" + }, + { + "name": "form_description", + "value": "my form" + }, + { + "name": "serviceability_description", + "value": "my whether" + }, + { + "name": "description_application", + "value": "demo for test" + }, + { + "name": "app_name", + "value": "Demo" + }, + { + "name": "form_FormAbility_desc", + "value": "form_description" + }, + { + "name": "form_FormAbility_label", + "value": "form_label" + }, + { + "name": "permission_reason", + "value": "Need permission" + } + ] +} diff --git a/data_share/test/ets/data_share_ets/entry/src/main/resources/base/media/icon.png b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..474a55588fd7216113dd42073aadf254d4dba023 GIT binary patch literal 15458 zcmV-oJe|XdP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXfJNHRMK~#8N)t$?W zZ`*d)f6uD@IOn2&LJ;lP6@!gHh#>Y1!r&0HL_gDqb&`3X(Z=GaQp8SP` z92In5!tr>lHv4nxKS1{J@p1P!+F4$_JksuYcRrnVr_*tFKEi|jF}%m8r`_Y_l6p^% z@+LnCznqL`mDBrry9$FzRWuxkQF=}GpwhbiR|yW zmfjQNx4tFelhpeM=s1qPZ}7VBtuHUqIh+_+IvN7$>(jXIa?55SEAd6rfw_FG^Ciq> zUAOb*d;6XH7UwzzrTnE1QtLJmPK4||=GS#JMbf8dX;2o^T+5qYx7QF%t86tY^M!6V zrngTY z1udv}ju^g5nNRXGgh*Bp3Mrd$sWa|p#az3e^Glh~4OYDwx?a*KW72*IFc`5a72{iM zp*N~%>#A7GyQ5CGc@5sreOI4Vr-jh46-ty$UgtlNS4u^>BKcJpW(i@*S9!$UCqmcd z(U6LQxPK-@LYcI@ROQlUqYfv9)@pP1D z^PGd_#Bn=j?h;(A2YP*^zO{q!-impmO*sshM)pxC{aRnxpLI$OVz(ElViw;?d~N$q$^VbIP>sa0q0)N~6iq!!fI>IcRGDdADCq?$^K61=g>C{IY# z;~=ksR37V9Yzp%@sRJ8ebxt7()agtNj zFX-#JY(~NHNecrS7DT}|J>yQfr$J*Ww>;PMMSj|?ifs>m;mOpS;hB2QJtAw(Aw2S_ zSHe`NtQeUBZN(O=rgRoV{J5F+Ft*YQkw zwtwkXsI}a&=y|SSZxEX3H8VG5pvDb*DypGrx7RHOJ0i^ra2-P!NRFO4D{+Ry>|JXL zGjQaB$9omq%IUE9OgQbqtQMtUxwo448OTeE6JEO(GROhuciWZ5BouJ*L~LTeo;4dtD1t#pnhtSi{UW~!N8lsnLV4AB&!P?*BYDt{H& z%&bDsz7IE15kl1~PvI`8P44N?xzRmdc}}725-w90Fdv0S!A0anyY|dSG}_^L&))LF zz4K+fI-yqH>N0 zgo)+iY3)b8AJt+2Z>KNwTQ-d?GjYyuI%!>DNlTFvDiBBa$CrlyNy#r_Sho8!34uL# zRbE+7I??*TrZGd;$+f!%8_B1Sc*Ia#=XozCRDucxF$H^&J+EfrLzkl0 z&Y3P^^vbm_^GJtcTe;>pe{n4!{EtOfLyv17pOHk&6d)QY28Om{l|N|LJYM(9dcX=m z(`(v2zJ^0${=gPYRc@u!raOd&0;{ZWR``si^fg~l4oL?SD>EgWzMqA-<`?rq(W^EZ zVWn$bq5GX_&GgJOY`!oa&@zRZ&4hiDHmw<(Mk_N)4(+wilna`8P6Sjw)OS?{y0(N(0*);t@8SAl~B`A^+@J zV1RVu>FKY$>KaP3uj?dg$oKga*<{6RD1b)fODgTiZOJR>{Kkeu4uk2y#e!oE4iAlB zYL*V8DT~1MLc{NwyHeClv|$!rLwWSf$b4NexAR)uTBgvUvCBJO=sfB6_1wOZtOXTj zc`5k{U1P}t$8tTmwm1Gq57=?FuXc|tkh+fj*LX~;FJx?f%NC4*45f)%IS75<;}ANX z;gHpyj8K*dUZi4hTt8$GpexJ4q}CPXVyW%DV;NflfVk+qu7f_9k z*}8EIodV}*+31PZmwxv(r&~BEn9C$YJ9U6zg!~5>d$_Pa8+ad7I91;c_0IOtEQZJv zWv~YzHgi=b!-mWfXtn|_JkoD5oK-0qxdz=bc;8A)h$8Ki7uj*~)FIoxTCmM)Lkx$^ zDAapMq>9(D*y56Y3)j_pPZhR{lBnF6$6?8nU&c%yomL(4$90sL@mADWR@cgG>br4< zm7f(4kA&8Grlx|Pqa>B}@VHOlNlK;+Bw%8XPl;5YrIxrI!FgaD+MM$T3TD9_g?p$n0Z^z z(ZK~3V;*H`@3>UjK<`U8)$c<0O1ic7Ev6ocyuLu$qCG4Y{bp{Y=5PB;{k{&5MvzIV zqrB@hYXOE@LmvV6T#B|X4dE6jY+>wEAHh2P=EcesGcpX)dv1+PVs{Q^sw4rG+6 zIMNJ)vc{%SR$PJ)BEf_u+O<&U!M5VQ%rC4^x?<;d{RR~!z6NtUq3;)^4s7W1#)j^v zagl`{s8YEpK6_jhO$@_^<2ryqkqSlOyMV|^!)TC@2*LI`^CDdG%EMG3N_}|VeMXsg zreLRr}}fkU0|;F z*7Y@d*Xq264ee>$vQAr(zQG}~k1UIKZbPoo zBq4|^xF`pLiPaELV00X>9O?5D3Lo=a4w3a>7DQFw_SB8SWLAZInMO&pQ4!LSj~YD6 z@OBztL*L8Ob`EK5=<7MJK_T?^rLFqqOeZgHg&A?6PjVts8H}BcoI;mGT&hNI$*O+_n?-TzQ=5&@FU+ z8%JCG;=yD5GrXl(p=k!g0{xS2uj3r!y6+pk&uJG6J=Xz^8H=fHEN`Geyfj0EZ=)FZ zy@n~1956HJK-yv(s;r3#B|r&&i8b$4=&<8A?%_Ig;+gcpy^8a?q58J3buP@kLYeB# zuvJF4c@1BKR_u&3Y};O=+1J~;*T6d6N2fErzRvXb@UVNhXB&bjsk}B6yjIvbbueQP zP_b352q{pB@qe)PPPC;?V+3uRSYKh6Wh-G{U!Yyu2MUFQ#d`*N-+5JeEfd?K^}L)s zf!p!b7#;VQb6lcB|I})~eU0;~5--2s&h1c7E$a&)Ds*<-L~vtY9Bo zkapu+;9@BYMXVY#B)(0sTH}^k>s8%(pgI{Xf(haf_V8hgi`#C?Ct4y|0|!+}!f3DH z+7lPAq<`@md>3KNVE+qD(Zi^+g|6Fue3yRaI^D*%0Okp7ODn37mjONA%=wvO%5xVQ zTLN#vEcl-WuJzOXZ*iUv#jn9!=WG1ER=&-j$2yn2*1lnGH$&%rZA`Dxw@t4VG%`~H zf9Y}|9;`TQTK9mS3;I0H&4~Yo49$KP^r%W)`Y{~?48zu$u*+BI`E4V#7j8e-FPMdy zlv}aA@EU9d+kG}};U%9{-@sDA#eUW{uhD8bEb>B1V&8Xp-q{fYW8z=#H*jr$*E;_$ z@M<5gC_cd5Lp9u}jyf=BwmQi6V+=lfOKvJ=X!Iyx9EQ#c)`b4 zKvDGyx4pWr^=v#+VuYs=Vk6@e7u4d1!Kpb%RZKw6E3Qj(?^v^!=Q7Om@wg(g?zN8j&sMIKz9iV4 zc4x~y!k!I8Fuzx!iz65Z7T|G~b`%6DdXCfb5(*ml-~nmlifY7JlTJMQPa*T6b2Jn|a6Da6sHJDjm$zW)COz7Nma z@m_;#<#XO^G&--#XB5;;-!C3HD{Omx?S7m8{~l__aQ@jdxtjJ|GzXroXKu&PLYf6O zL+8I%{xz6AQnDcGd_$FMLthRI;Udw+8<#Aotm2N-r zn4jnMT(+Iln*YY{3tt;|=YLVISAuh&+d6O2oXfmkV-9ew;oRt2c{B3U2;nXGKJ=PL z+kCBE*O}|i*TS`N3fp=@=WX+a*XUe>ZQUNzwfq_SemU6@Yx6j~5$H6 zu;u5q_CIgf^3gE!x&`ZZ`D@tq7DaaE&kp4gtA`ZK9SgCgo-bd)9K39^W)8b2Ztif?dvTxo*6ccMW}uCEo;sUVl;Jz`QTk8!jk$#usgAFpX;qo!2ti%EoIA zMVkHHp}Jn%HeC1V*ZXeR_Pxc17mAz<8oHy`I-B#ioy<6wZ?7A!-EZ?6s*Jud5+Ofi zIg%24U0|46NB&xI&1(x=cx_w_ua#fptNCrb2GV;C--2uPXMCZ^x#0Uk%@ZZm8Rh{s z-PZ;=LkmNth%>xspLc-rszbie_3ri@yg8q_KP}()(Q~#Qp0=~MZm{Ry`TmPM=t#Hu zU489s=>2TBdoiZ(0o@KhSeOi}UO~Y%z6~{qQjicKF%WU@&%XNl>2bmm0DGU|9UYQJ zIt}Xefv!Av8x{BN=Cu2Gd$W6gd)&P{lSi}qb$lsPMF`*5ShqX{&_quc4bAJjc<3)rwKDgfRl=YcS(%!j2KHR5(iWb-9aNb?G8LMhadSeDH|Knt=S;nP8H(1& zN0fWH?9K@C{rR-JHUE6v-J*beX^Zyjd}Ckm_f&JNh4UUTNPeCzQt$ckVfXZSzuQ0F z?M}PP?%nZu_k;K6-M6U5)#_s_`j&(uhmE4I^64=5C9bsBI*N}K zw?J1f&}WF>1^N|_l7A5nA3*ZB4$aOKR8BM8isEME=#g#m6;6TbY37x^mW zNFDJ8A-+5BP?n+ZxO@NZu=@ypxZMvV|NN9X@6h&p@CH}PH}L3Hpz z&-EizlqsKw{Ud!pVH_A1bZ*ZY%=kzmdCjL3TR;Ux|Laio?6+n1U0|;JU3!VK27hn$ zvH!)t`Y)fYsGw9{#|fW6=j6i_!N{-zRd9lBtmA9`2@{mm&%C&!9Tt*Q4>++32{U+v zB%SljvqQa3kjcDxE;SV7k9_>u-sgLNNQ77V%WB%@)e}ick3Qwuc`$P!%F}4{?pqXQ zG-%rWD=>c&7=`;wvE)M~E>v|}XfxQpvzf7nK;_d>mvJ|I*}mlUni3KXg*>TQ;Wa+C zP`sf(U*pK5AL`ijs3n63tQnb9xEsH3uNR(H3-O33t3(M!Ies$K*BOeD`ZQ?gt5E94 zLr~XIkGbqlq&LS-@gUL@DQbkt&*=VvP)WEX_2vC+H%P@33eYf`p9-<03Y$FjbI|iZ z4eSPtcQT%AS!knA)wFV5&_dJibO!Tg{66qj{jJhoGlZt$TP)ltSZ@3d)&T)4WbmLs zQ9@TnE!@|KAJPCZs6;;ndgeY$eg$iZ`BAPm9E(X=0-^nhC2|_z%``IH=}`&EdlkoA zy1zuh@0ssz4-dOr^Pf@f<@0X$@CiBedVLOFdCy#x#TG*7fZRPb3MQM-7R0^ zIAS!<`Ito5u8`=*;L(jC@)OF6Dv_#f_5S=Mn=#qfE%V|5Bd`w_4ld@@fc5>3!5`i| zjxS2qn8pZ7QSjG-;%;2qRt}9&UQg?Wt1#$YF^X!l%Cw;BH$B_UZMXe&YvfrLoi94# z4f!&pF?A@XeuG#9wA?J^VE%@7?{LhI?^wv(x=3+RgSCrzkQRTU&XKyu=L_u^u!DxF zClztw8qaw~F=9Q{M+x*HPbWQ)MURo;MCiSRt_z~~w~xDT-|u#R_lJ~bkhZr?L(h4vO)QenY#q;#a8k38h2fY2B{L6z2Ir%cc(bpF`eBC1}zo5tV zI+VvX%5*{vC<^%JS)?IE*KY)t_ zR*T>b!uY_F@jXg>cSgJ}He5gu3f-Tn+?(tf*)O`$_ZqxmrJAh)p7)M2Qw8ka?o1oE z3wn)VzC?=B481U_K;_AK^PaGrh=Cjwf;=5rpxvGf_0WQcY&(WmM)A0=3UW?#zR%Cw zAwUmR$55|!6K+c(j(Zk<(Rv#jS|M+>|E}=0Hr>y`c}T&l2sh9yYiP}im3G-yAXL%$ z&N>R~9oCI5m*w&{{bBdb$K&qXZ*F!UKim>3&zbu?r@TebClppzZ(6Iu ztTLhRH*)S>^|5L1&zRL-lWmH@?+SCtOMZole100m-HU|s&tN`5rWb;toyE#JDARZ) zs39p2w?5AC<=OJN3QDLpt%RWv(g<D^bECi1RPoG4Aau1p0ZiEPC`7 z7}Byu>xh?Z)Gt|(++}OvHD1Wv>}Szz-{0Ud%_n1^LzP142Bl@ai${5sdz6P(pU|?N z<^1b-GF>=l#=}-2Mi6jj{l0fxef|FeX2taNtoY8~qHuUbkXa2Pz&*kdJ?*(+nC=BV zRk?Mcf>)|^agT!AL=On86pJ@q?oi5S6mpM3?h!Z(C-SobrjNTQ>mi|2L?63Hl31ETM82B?t`DXxdR_il|rO35ANsgesKzBF}xG z)tSpwoQfL85d#^*dP1QIhj{YbPXsxwRem4omNA*`GjY}dcJkXN>rul z<$l#NG~r#y0mCE&SE`1}s8(a)+OE2e_e$n%!A$}#c3;4?wk?OouR+s)4b}sLqIY=4 zqQzxph@kWN=OgP>LK0ILgHuz2D^uqg!WF5jPnYh_hR#jy2eT)%je?gR0`__t0N2%C zZ*h+Y(}Z>kVh}#dJbJ{(>e-VT)-G9e-RS)&d{2KWhoq*CHkRFO`C3<0Z^zwynhlbLzWyESf&- z-oJm3m)45avsP0VNI5;imA#fvQS(@Yfuejel4C;VV)vG{FBK2jTDbpoK6fGG9~6Xv z@ZvY=+H+T-d%*9h2+Gp)90RCfx`VmEfL_Uv($2E2!djr6Hbho0vlf`!{j6}U-{x@z zl}g>e^0$9mwNlI7hyyF-sdNWyh%?;zSJOPk^MG8>v6gUy^z+9;voE9q@cHvkvUo9n zh6rE?Osu!12P5`H^V5;px#DUDl9j5x(QuhpDbA4~*M5;wWL@fUwfTru;$x|%6#c12u{xgy;ej~ zAnd5T(9k0>iZe7t-@Ung=esx_j*nwOSJAf~4<2%Qz!0+f_h8d=fTU~zpEFj3Q-{FDp=l%Bf%-+|742%r=bPa8yh&yDAbTV$4Ql$@p(dIdll&zTs(nREi}B!XgNaT+|Tzzd8TRFma?|cb^E%(>x0Ux zeH(KlxL7NLJs^eIt1EC?r1z)<2qX9qLK%XB@mfz6TVd^$Z3K%Ts+D!Fl=J znXrz+d{gg(NcjDLBBNMCZo=(YES-oFj3cXSJuLhv0qDb@s#{K;49(;SEiAz{jY8T7 zE&u7UJzIsiHEQg>XCAJBW!693-=jE|a(O}^G8oYc$ZX72&RZ%(_Dji)4$QeVtH;bw zWdLHAi|J4=1I-ttS0TGXZF{SWmAd!uh@jL6&v3X7%Egy|iarPMu5w*Dv%1Y&dU~!4 zvz%19Kw}&Swn=Vl=u-m}3_RXl7!|X52~ma0d&=!ssAw}om;5}T$0xSjgig26vJehg z)qy$BbXZ!h+XP(3aCSVgUnG=yJwsl$BFRNgyj)>ZS3y?D)e!31#a8n4)+sDHR=v)rE+1GJeN>@z|DFw} zZ!vfu&!mN3N!0@C#~YxZg^=Efnp_!+E~R^c;T(`>LJ#Cup2~IU3{e{n(GVqt8$C&Mbz4y%4(bPNIj; zKSOWyw}dw`>@R@Aw%}oa(7b#XyascA%c1ctnCW)?X+!AMnEJUZXv9eFE&|4@7AEOUf; zBei?;QpYscqQ<3$S79)cacx9#To@(;(n!mQpa(ieI0z3k8R&>BjnR$!gjvvBL67!Y zyp5|^e!(`cky2kG`tdGkTNIwUV%7EC=; zJ)e{|3)+W#P_O!fZY$C$g#Qeu?p-D9+k7gnIFb{+K;FE{i20|kg|$wy19THugnI=A z>xnU!k(Y9a=PvuyqTNaqayjZyJ7aqR(xlPx7yi^=_+i2e<>hq_%jG!t(2mek+4&QT zHUvZ65GRowvU5RGa>#(&c$4#^UaLUOla_)Ve3ai8dr^wz)FVisz~Utf5IvMOX-mEl zAWBkMv<{ysAE^ooP1=Vh=zUUprArm*7`kqZEdr{s)>ZSzzY5%fApcuo0IXEmE3mX3 z(4N`QLotVz>X5U;j}?Cv#R<37h8|=U6dg%9DtkV_MPBhJ^9ZIzT9) z*hcHlUZ;dF-41w}*_(SBDGj~YW;86FKueUjW+kZ_J z)fczpe(-4<>S=7BamfGm`Dyowh4<&IxKTKvcKLCTQZf%7Bqxp1I(-g)t=Ew933^OI zr{)RHi2*(F3JmtsuG`FDdk;5yD|h^bU;Nb{Qr#9{q(h=W3_0BDf&7<8ClLgQd1o$F znkWQzDU+P_@Su33ir}7(iVv<+Zs(wkAcQQ6L}^m)>5`tLH|Bf|7-u`=(I^KOws$VJ zjd=>mJnKo9lnVzLy70P$W}`#~Pn*n-C-UjTr#aG+R7!^;%}^$zKrtzqMKRp~*eX&m zZ$?2w47jC8mx&8O%*c^uRXxm!I^$8{-h&s+ko06qo=%lIfA(+uE_W}%0jNGfT|MVF zkT9U0{cT9{eG?8L42w`(SrszxcvvnIf_V-gYz^Vc`qC*@RTft{EsACEWa|+D7;9l9 zrO+P$Wsswv#{4!y=7IJMaoyxg&Xza3&v%#I|NeYO`ndBCu*EC=l6|M00ok^Y`Wwa75C&bU)X|^(4cbGA z{RgO9SZ>&937TK+t!J->lwQDCUccm86=`{ut$k+9%*_= zQd3ZMl0KCM(~*(OsVUm{mB0Qw7%7zuGlKg(nbq_F%VcI@WJue@A?o589SY;~ufB?DLtP)KdH!i1z3Ro2)J`AVh_tfA*Zs|>nLsuZU1f?T&Ziz@ND zH?FYMy#h^x|MMJHCsBF5KUUEiLOGAuYN0UmD`_OWf7l)WYXO*9(-^0n|J5k z4?f=RzWs2M^T@LvNu`s>@DzojTu`ZxP^)Le)4)8n2VQ*U_i;hbwd#YKo|E7n!4bS}`*<4ol?7`j7&-a+HVn7(mGavG}_} ze_-QJ1m55Hkp`a}obm+0$3YRVzYu=>%=JU|lL>sDiugtV9VX0?TUcHoMmPvBFE4Y= zW$LOR>vE~hk)j|`MUi&-OS*cYb+F#NxlnOquH$w0VQ5zIqSy68^C%;&YZnTxO6w4U zDqx4%#`1`UR)hk~b_nRahP7?wn_|mX!?4@2Qew%-F}nThXr=$nW6ShKD9I~1W7_yk z9yR>YDeio^k2rj~{>}Sa@TMNt-X8H%9|8HxsT1h|WOaqt=2uSwofhK?ri5A+RUNnB z%u`9#gz$@}8Fsm=fzmF35x{rqI-Pq>AKAF*@~0U_6r)^C z31y6~SY1PW@}1r%+V~EuA<>nWMB9Dc+qfLgYZE9>Wj5a8(xQyHniBdsVKZ!JdQT1v zWH3ywLW;uIagjIX9OqUI1g0ZYm=y&FFMr}9FzIVRqfh6$STL#ghE3BhH=HUA@6%4B zBNao7xwqy^1UL9=1<7}VO3;s4_pfs4#w)@hfmC2qyjR;O3Q55`KxOWk! zGBb~(%)GnHwJ&3TW=;ADEq}Uqn%M7td=Kk}KDAqJ?4a}l2Mx0$9?Resi}@N{Gimy= ze8t71ydKckb6&%?t}xdRs^m#fWenC?@2h^L=6{iDI3%qsafUL`rnlle#)i49vGY4^ z6jWx63O-_lbnSE9`lI8{=_;lccwxery@0I`m!31QgcixkNHD{SYF+LpkC;F5f99KR2C#Ur#LZZ;4FUXsdfp3$uk%R z!R#d`;m}~@AcMvb^*h|l!d<%&$sCE?2ba`#LSB>GN9ZG z86mGru+Z_%wlFtVdOeVZ;R&{RbKPt8g>9W{IM?H!<@y@F3E5UK-T~@sUa&F9%J-h@ z&cBAQMW#+??7F7ql`$E_KH9>AkX3CCEL^zNw#cni=2Koi6oHr(7@fy@DAJl17}mX}G77^A=8ACI@@vmHp@RzzX-Y#{Z?qq< z&7bRvgNv#&!>C^oXn58&S4vs+GegsV4Hw0itpr>=W~fBA?n=kXt1l`K%=*A>l*qM? z<$Jz|`dXuJZhP{M;v`lo0qdu8IS9ux@-PpmMNX%3vI>;kfdw?JGSUc)yc~B~CNAw7 zir#C`^|#nZX!aqraytDI5s0OxV?0W)%WbEyg>}5pp0LbSBhN*Z4`@1HgRWO-lq;-o zs?ciHEYu^fQJ10)-STP%FJt(tDBtR4&H8xnRy&Vdd~}kpcnB_z zT-q{_7f4t>9z2LA1do+vj+5++8vQq`uqEijq+vXvd>Dn-wi{?oae?6}Ma&)&A%n_b6hhS(ns%pxit^s9ykF#) zY150JzLy7k?Uv>j!ifT;jyNl(1wTXAQ+RVK3JXnPEcQCx?z0;@Z;Ju>9{iOu=@TbV zuKfcle{&N)7+n2o8P5Oa-~YGB#RU&HqmijD+yac7BeZ+=IBq>$_PV!mS?pKo+<)3e z%n43fQHG-YyB0Zlc^$xZ%^5Pj@3vh72I3bb$oFZ-lW zS!Y}jt*k+_@0wrzWCpwHviu8AaFFh>F?z=!7-Lmg+uC12kAbTqRyPB@Yx)7MjcCzL zIIelrsOFtqesb|l5TepR zqNz_?SGhv0oIEFLA@$a=BxJWD`w&{NwRIgtXsSr_#-Qq&aG$j57Fb^6QOR9bC=;7H zhi}Vmzp<|vm_UutDUJ%H9d8)ktsil&s?jx zW-+X0e3ysa0loN}m;K-QC;u*8SUHM>PPwlNEg`lrvX?=ipD(@^amfk8kMHWiu0M$N zs~vtnN14kaeWcAkkD@fA@|GxErlIXiM#)1c-Ukd#T&C~J2}I}!!hC~f>c?P8IH{j` zrJxibR3BQj|1SLiDqY#Ff^L`v4(M(J=JxrnI;u=LW6)FVuOmy#ZZ(v(|1vbL!Ik1P zO;FG2%iC6@KP~k4Ev{9bk@so;xO;zlv)li@fBx^8vPy|!QD6?l(rS@Xie&;!`1O#$ z(|WfUK0ADPERXc9IX}Jf8BeV`dN1=JiZ%55WvuLnkfm=N2=Ve&)VgN9S4h^fB2*S zm{t*1^Y6!SwE#Vo?o^~5((Txwj*9y;0<{|l?CB5+L~%Y*$@k?@n2PXq3Kg7lLE^ef z5OUh{aEah$K2HorD2>NLTZ2%roF9IYg=FQt*B!E9RaGJq%G7jHFU(t7?VNY$r*gjAb-%-l+KXx zeI9oc39;N8JwJXt@BBdH{0T;dvjY~_sCbRsQCH5l&CVK?{QQ5jdV&W^~B#Xm(fIV9wIXr`^sVtk(r}0v9yWt z?dsdE0?kSZj&Tsd5cg1>k5mU*P^s(Sg$64UMtm$H7u`kl$@#e+c`FT49{HE zIQQ!agbOXZ6;8b9KAcGrMH-{Fb=4ByYS`R3jJpZ(r{roEjFMfNqGmlGZor^PSt ztmp|4($o66U@Ir9RO+1Qq(2CuvhN=5cXxPXg*;FA^&;DVdh(!?&;_#^hV4|QiqY${ zu=-SwZJejAqY(7JwBssglPFq`wY`RNII~&OU@$zIq~E1)$JwE8)kgBe4?P&#k_R_> zRoWy1R6S2t>|1438~Z3T>U-%d;kuy}X#|4To*}|OBtAlH31KLbaT#Wp0f2gv&_6pDLJROKAzruA zrF9|CA$v$1ATP8LZ@g6j5mF7+KAFkMKP#)BxX{8dKHuN(PB*u522I1S{TYId4$weI zF2bZ4<eWjRP5I!zpm_2VZSqUnHo%~8_AkN zw`yec z-0dDE`am`B-K3t6bwI*zy(2{3bVc9tspU6K^2(?~l5LRoL?7qAcwLV-!Y{ zQ9ry#uk8ykl+F zH2dHB(SM+i@;ZM*XvYejUgD8jn(dA-ZJLuA$|4-=NRU)8q&Q#?+w%un08i%y72=$! zcU=gr$zwozmoE|BUG7S0iy#Y5^sC@y*pf&1QGoR>P#sbvjH0z{jqX6^W4%|g9B*8Z z=~=9vt(QK^8zX#$5O0Hi#;75UF{&;U--_u}$gv^@AiYwSWrpHf{d->#Yi$#C8LDZk z0n~wqio}SimeVrBCL;44DL>uz0~a%7I7j;N#b*rOMUK>@?T0c#>o@+DiiC&)$^q@< z>MACRbgr~4PFw^arE6Qy19b-z64db>pS+lrc4UrD_0%4u;DYBTK0tLr#Ga_<%0|J^ zgT!)`k4?aAA_8gZ&`&-_L8gkj__hNVhCJky@M<0F#{2PP2b@C>`RVb{RykN-#T%0I zeAX!;yp)1grEyK8=g0fJmugx5P8h~2UB}|upp|Bm@T^!EQ}~K%H7p&*#f&ew)n``y zA}5hFUYR!+@kTvNnOk2k*NC1FqS0pm8$bF39X||aB{*WX;HotW(&eM5QbKu1mD!?x zuMTH_w`*L-hZ^}VA4_q0C{nr+u zX!;X)j}2>|dd^VcqUK5Rtm7CRxb&p!t0#`fgAX4QMJS3%<-tt8{Dm^xgRLvyLS#U` zio8Vu9|(J%Gxz6b>`x=mXbwyZ@}*(ql}B#m#fJ`2DssqQ3POqgjgt2$k#$V|V2$V6 z{<#fz4bLuqY?smTFMUNmdIKf<-~8SGlI=%ec;mREm@HjRX*f(66cBMz?@ylE&?bsh z@s#R?ew0BbZQ+kp`U46IM6|5~Ez2ZdkB^+RYy~d!Wyw(lOy$cVp#7IeiW&lCzEKw8 zGhArebA>XW(l}@Ks0#88AM#=p=?4tAHNMUh>^}zRVgblcD*zuJeB%NHxA8~7&3F3K zAYd$S$x+vP6FXyZt}- z{r}3!ysV$w#X1$JZl72G@wkTCr@<`VBT++f{`d+4%SsK_oWS!)h$X)7Iw5YwMUI%|DP($<}KZ+-u>XG?b9I5f47B0;%?P3__l;YH& z`92CVO`RCVP#y-H@nJZgr1<2a{xBQ-lIK~pAH?^`km{I01IzdD7@r|t*_4y`9@NA5 zq$<1;c6}R8!%NJeZ{_C?c;3;(Bhvgl9`1TUrhJs+)3eHTVN^Wtf9v1;w`bk-!U80# zPb4Nai`;Q4VyWJmBm(HGVb%x!$o9g(m z@BNm8)L5LW41ks^%nDsO9dc#n{!ihj%?OK8jS5s)q|ox6AsyuMaEws?(61<4>Dl&% z(AowWE}sZbd2$Fpd3X!W{44-|eRU%5z)~*gA?R**Vyu2$E5~BWM~PgBBq$=kqGE67 z`@|=dDkKs@MXyRk(q=Sb__5!7i&kaqd|~>q`yW64akf!;YC=W70<8l5tW13-+~|Y; zkOj7m+O z!5pPf&u5hW8I_=fD zD*;20N{)BIOQ{tj;NRl5w-|ch2}M5c{wK!f>CfqKoBq&WEM66PqkaN5`Y)t8TRI`--F?$f7FyF2*vpx(dgmuRWV_Q&1- Y0jIQKqpXab7ytkO07*qoM6N<$f;yQ2zW@LL literal 0 HcmV?d00001 diff --git a/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/form_config.json b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/form_config.json new file mode 100644 index 00000000..e892d447 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/form_config.json @@ -0,0 +1,6 @@ +{ + "src": [ + "MainAbility/pages/index/index", + "MainAbility/pages/second/second" + ] +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/form_config1.txt b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/form_config1.txt new file mode 100644 index 00000000..32f9ff7d --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/form_config1.txt @@ -0,0 +1 @@ +{"src": ["MainAbility/pages/index/index","MainAbility/pages/second/second"]} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/invalid.txt b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/invalid.txt new file mode 100644 index 00000000..cdca51a1 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/invalid.txt @@ -0,0 +1,5 @@ +{ + "src": [ + "MainAbility/pages/index/index", + "MainAbility/pages/second/second" +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/main_pages.json b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 00000000..02221db6 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,6 @@ +{ + "src": [ + "MainAbility/pages/index/index", + "MainAbility/pages/second/second" + ] +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/shortcuts_config.json b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/shortcuts_config.json new file mode 100644 index 00000000..02221db6 --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/shortcuts_config.json @@ -0,0 +1,6 @@ +{ + "src": [ + "MainAbility/pages/index/index", + "MainAbility/pages/second/second" + ] +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/test.json b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/test.json new file mode 100644 index 00000000..41973bba --- /dev/null +++ b/data_share/test/ets/data_share_ets/entry/src/main/resources/base/profile/test.json @@ -0,0 +1,4 @@ +{ +"path": "DB00/TBL00", +"type": "rdb" +} \ No newline at end of file diff --git a/data_share/test/ets/data_share_ets/signature/openharmony_sx.p7b b/data_share/test/ets/data_share_ets/signature/openharmony_sx.p7b new file mode 100644 index 0000000000000000000000000000000000000000..4109bba52aad41a4ac4fdaf811c8e328d648db26 GIT binary patch literal 3623 zcmcgvdvp_38gCwLEv2PeUb0F{K#D-%PMWkyUDTOm@`6b^A!(aZwoE3IWZKEhG?{dg zAdd|ziij+FR#8C98k6V9aUYq{Fk)3{1+DLI+;Y06?i>Q#Ti|l&M*Va0J`bd)U*(WYQuCLC5rkmo0Jl4 zC?zQYQbtq)gk&qrOH4FDDOwnrO0i+6HvvO!$YNpirU?8q)|kS2iwT(Zl!XCEwJ{Q5 z5VNum#j#;l%INAA>UcrYhnR?vfa@YAi_u(TGMLQM`}9;qViHhYW40J;tD$<)blpG( z35H{+Bm)-opPKFaiCZX@k$SX3ulS;$|J_CJ+oP}l*5*uM@N>Yxb zSAH1oaCs`NxXrocIrv>^ub)UaLaoQvo+jFe^fg@@CJh1F;%@`Un;}}XVt_ zJ|WOdGI>qiw@?Pg2?@x3B;1~5!Z%p)G|i>Lj6EU5iK|DMzo;u$@NbY){~Y90hq^Rs zm0GQ>-5x&(h8NrdZ-IAaX*HVsJU}DGpr}9-&=!=dtsZ0~xJ?m;l@|}{#E#mpH1B_LgjY}V-&b+yk6q-NqS1eN!uXDcUwLHg zGn;*&9#p_|?wqI{3q~&;`M2fWy3v0r-Z;Da^j!;kzQ|v+N$&uqio*z%>c3j8MqRiR z+^NW=+R@sPZ&9DVvOViL@$PT-|LT1H_g}Y`sC+|vreX6yM2+O_er#`1E|l5poOCO8 z{?|-TtYF`58_Hz+z2BeTw6^;bY<2ilRdP_y95Z#Te@uH|jnkFE@_L(fl| zKPP{}Bd={+>IJ84A3rkrv~S$2D(j96g+2P>^_{Pr3kKhtw{Fw@x$j;+9@IKk5{|Xvli1eXT^D;= zFZ;I*FFj2^y!x+>TQ@&g^5KE4n=ZGGx;(jJW#V+@-FK47plfk$q2u$-7`PvdP=Hdd z04E=4;Abe3R0V^OG^Va>DxoQr-|l)uo}qCauxFSH}Z~q zpW1M;>BZH1tF{eW_3rQkbv@%BTsqa1ZP~i<4*jzy-Vn4C*f z-^eYiE_OW%-1lW{-=^?haZBfh^%ucY9o{vWliSCfn6~X5$Jpih5JwcmQSShb#xt+Z z8k)&X?A{pwn4@2b+C9rxUq$E9V~ zy*moN-gBX9+*>D~DEa+?+AWL4rWHpQ|4iK1x$WgY`9R}~A3Qasrv9bw=MS$Nw|?uF zD^`?!`QF+ID=sZr@Zz+JOXrTAdF(rVU^5M{Of82LXi_Jia$SC=skJdbU_F&o3ljUa@MasOr&cH`2mfjxgcKzqXx$aT#pF4RgB&#F0 z2=dOl#71BDWc}rrns&eO`fz1it+Z+U)VjeYZov(x7lAJ1GV={ +#include "datasharehelp_fuzzer.h" +#include "datashare_helper.h" +#include "datashare_helper_impl.h" +#include "datashare_observer.h" + +#include +#include + +using namespace OHOS::DataShare; +namespace OHOS { + +template +class ConditionLock { +public: + explicit ConditionLock() {} + ~ConditionLock() {} +public: + void Notify(const T &data) + { + std::lock_guard lock(mutex_); + data_ = data; + isSet_ = true; + cv_.notify_one(); + } + + T Wait() + { + std::unique_lock lock(mutex_); + cv_.wait_for(lock, std::chrono::seconds(interval), [this]() { return isSet_; }); + T data = data_; + cv_.notify_one(); + return data; + } + + void Clear() + { + std::lock_guard lock(mutex_); + isSet_ = false; + cv_.notify_one(); + } + +private: + bool isSet_ = false; + T data_; + std::mutex mutex_; + std::condition_variable cv_; + static constexpr int64_t interval = 2; +}; + +class DataShareObserverTest : public DataShare::DataShareObserver { +public: + explicit DataShareObserverTest(std::string uri) + { + uri_ = uri; + } + ~DataShareObserverTest() {} + + void OnChange(const ChangeInfo &changeInfo) override + { + changeInfo_ = changeInfo; + data.Notify(changeInfo); + } + + void Clear() + { + changeInfo_.changeType_ = INVAILD; + changeInfo_.uris_.clear(); + changeInfo_.data_ = nullptr; + changeInfo_.size_ = 0; + changeInfo_.valueBuckets_ = {}; + data.Clear(); + } + + ChangeInfo changeInfo_; + ConditionLock data; + std::string uri_; +}; + +void CreateFuzz(FuzzedDataProvider &provider) +{ + sptr token = nullptr; + std::string strUri = provider.ConsumeRandomLengthString(); + std::string extUri = provider.ConsumeRandomLengthString(); + int waitTime = provider.ConsumeIntegral(); + DataShareHelper::Create(token, strUri, extUri, waitTime); +} + +void GetFileTypesFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + std::string mimeTypeFilter = provider.ConsumeRandomLengthString(); + dataShareHelperImpl.GetFileTypes(uri, mimeTypeFilter); +} + +void OpenFileFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + std::string mode = provider.ConsumeRandomLengthString(); + dataShareHelperImpl.OpenFile(uri, mode); +} + +void OpenRawFileFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + std::string mode = provider.ConsumeRandomLengthString(); + dataShareHelperImpl.OpenRawFile(uri, mode); +} + +void InsertExtFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + DataShareValuesBucket value; + std::string result = provider.ConsumeRandomLengthString(); + dataShareHelperImpl.InsertExt(uri, value, result); +} + +void BatchUpdateFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + UpdateOperations operations; + std::vector results = {}; + dataShareHelperImpl.BatchUpdate(operations, results); +} + +void QueryFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + DataSharePredicates predicates; + std::vector bytes; + const std::string bytes1 = provider.ConsumeRandomLengthString(); + const std::string bytes2 = provider.ConsumeRandomLengthString(); + bytes.emplace_back(bytes1); + bytes.emplace_back(bytes2); + DatashareBusinessError businessError; + dataShareHelperImpl.Query(uri, predicates, bytes, &businessError); +} + +void GetTypeFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + dataShareHelperImpl.GetType(uri); +} + +void BatchInsertFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + std::vector values = {}; + dataShareHelperImpl.BatchInsert(uri, values); +} + +void ExecuteBatchFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::vector statements = {}; + ExecResultSet result; + dataShareHelperImpl.ExecuteBatch(statements, result); +} + +void RegisterObserverFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + sptr dataObserver; + dataShareHelperImpl.RegisterObserver(uri, dataObserver); +} + +void UnregisterObserverFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + sptr dataObserver; + dataShareHelperImpl.UnregisterObserver(uri, dataObserver); +} + +void NotifyChangeFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + dataShareHelperImpl.NotifyChange(uri); +} + +void RegisterObserverExtProviderFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + bool isDescendants = provider.ConsumeBool(); + std::string observerUri = provider.ConsumeRandomLengthString(); + std::shared_ptr dataObserver = std::make_shared(observerUri); + dataShareHelperImpl.RegisterObserverExtProvider(uri, dataObserver, isDescendants); +} + +void UnregisterObserverExtProviderFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + std::string observerUri = provider.ConsumeRandomLengthString(); + std::shared_ptr dataObserver = std::make_shared(observerUri); + dataShareHelperImpl.UnregisterObserverExtProvider(uri, dataObserver); +} + +void NotifyChangeExtProviderFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + DataShareObserver::ChangeInfo changeInfo; + // changeInfo.changeType_ = provider.ConsumeEnum(); + dataShareHelperImpl.NotifyChangeExtProvider(changeInfo); +} + +void NormalizeUriFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + dataShareHelperImpl.NormalizeUri(uri); +} + +void DenormalizeUriFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + dataShareHelperImpl.DenormalizeUri(uri); +} + +void AddQueryTemplateFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uri = provider.ConsumeRandomLengthString(); + int64_t subscriberId = provider.ConsumeIntegral(); + Template tpl = Template(); + dataShareHelperImpl.AddQueryTemplate(uri, subscriberId, tpl); +} + +void DelQueryTemplateFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uri = provider.ConsumeRandomLengthString(); + int64_t subscriberId = provider.ConsumeIntegral(); + dataShareHelperImpl.DelQueryTemplate(uri, subscriberId); +} + +void GetPublishedDataFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uri = provider.ConsumeRandomLengthString(); + int64_t subscriberId = provider.ConsumeIntegral(); + dataShareHelperImpl.DelQueryTemplate(uri, subscriberId); +} + +void SubscribeRdbDataFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uri = provider.ConsumeRandomLengthString(); + std::vector uris; + const std::string uri1 = provider.ConsumeRandomLengthString(); + const std::string uei2 = provider.ConsumeRandomLengthString(); + TemplateId templateId; + std::function callback; + dataShareHelperImpl.SubscribeRdbData(uris, templateId, callback); +} + +void UnsubscribeRdbDataFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uri = provider.ConsumeRandomLengthString(); + std::vector uris; + const std::string uri1 = provider.ConsumeRandomLengthString(); + const std::string uei2 = provider.ConsumeRandomLengthString(); + TemplateId templateId; + dataShareHelperImpl.UnsubscribeRdbData(uris, templateId); +} + +void EnableRdbSubsFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uri = provider.ConsumeRandomLengthString(); + std::vector uris; + const std::string uri1 = provider.ConsumeRandomLengthString(); + const std::string uei2 = provider.ConsumeRandomLengthString(); + TemplateId templateId; + dataShareHelperImpl.EnableRdbSubs(uris, templateId); +} + +void DisableRdbSubsFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uri = provider.ConsumeRandomLengthString(); + std::vector uris; + const std::string uri1 = provider.ConsumeRandomLengthString(); + const std::string uei2 = provider.ConsumeRandomLengthString(); + TemplateId templateId; + dataShareHelperImpl.DisableRdbSubs(uris, templateId); +} + +void SubscribePublishedDataFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::vector uris; + const std::string uri1 = provider.ConsumeRandomLengthString(); + const std::string uei2 = provider.ConsumeRandomLengthString(); + int subscriberId = provider.ConsumeIntegral(); + std::function callback; + dataShareHelperImpl.SubscribePublishedData(uris, subscriberId, callback); +} + +void UnsubscribePublishedDataFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::vector uris; + const std::string uri1 = provider.ConsumeRandomLengthString(); + const std::string uei2 = provider.ConsumeRandomLengthString(); + int subscriberId = provider.ConsumeIntegral(); + dataShareHelperImpl.UnsubscribePublishedData(uris, subscriberId); +} + +void EnablePubSubsFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::vector uris; + const std::string uri1 = provider.ConsumeRandomLengthString(); + const std::string uei2 = provider.ConsumeRandomLengthString(); + int subscriberId = provider.ConsumeIntegral(); + dataShareHelperImpl.EnablePubSubs(uris, subscriberId); +} + +void DisablePubSubsFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::vector uris; + const std::string uri1 = provider.ConsumeRandomLengthString(); + const std::string uei2 = provider.ConsumeRandomLengthString(); + int subscriberId = provider.ConsumeIntegral(); + dataShareHelperImpl.DisablePubSubs(uris, subscriberId); +} + +void SetSilentSwitchFuzz(FuzzedDataProvider &provider) +{ + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + bool enable = provider.ConsumeBool(); + bool isSystem = provider.ConsumeBool(); + DataShareHelper::SetSilentSwitch(uri, enable, isSystem); +} + +void InsertExFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + DataShareValuesBucket value; + dataShareHelperImpl.InsertEx(uri, value); +} + +void UpdateExFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + DataSharePredicates predicates; + DataShareValuesBucket value; + dataShareHelperImpl.UpdateEx(uri, predicates, value); +} + +void DeleteExFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + std::string uriString = provider.ConsumeRandomLengthString(); + Uri uri(uriString); + DataSharePredicates predicates; + DataShareValuesBucket value; + dataShareHelperImpl.DeleteEx(uri, predicates); +} + +void UserDefineFuncFuzz(FuzzedDataProvider &provider) +{ + bool isSystem = provider.ConsumeBool(); + DataShareHelperImpl dataShareHelperImpl("datashare://datasharehelperimpl", isSystem); + MessageParcel data; + MessageParcel reply; + MessageOption option; + dataShareHelperImpl.UserDefineFunc(data, reply, option); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::CreateFuzz(provider); + OHOS::GetFileTypesFuzz(provider); + OHOS::OpenFileFuzz(provider); + OHOS::OpenRawFileFuzz(provider); + OHOS::InsertExtFuzz(provider); + OHOS::BatchUpdateFuzz(provider); + OHOS::QueryFuzz(provider); + OHOS::GetTypeFuzz(provider); + OHOS::BatchInsertFuzz(provider); + OHOS::ExecuteBatchFuzz(provider); + OHOS::RegisterObserverFuzz(provider); + OHOS::UnregisterObserverFuzz(provider); + OHOS::NotifyChangeFuzz(provider); + OHOS::RegisterObserverExtProviderFuzz(provider); + OHOS::UnregisterObserverExtProviderFuzz(provider); + OHOS::NotifyChangeExtProviderFuzz(provider); + OHOS::NormalizeUriFuzz(provider); + OHOS::DenormalizeUriFuzz(provider); + OHOS::AddQueryTemplateFuzz(provider); + OHOS::DelQueryTemplateFuzz(provider); + OHOS::GetPublishedDataFuzz(provider); + OHOS::SubscribeRdbDataFuzz(provider); + OHOS::UnsubscribeRdbDataFuzz(provider); + OHOS::EnableRdbSubsFuzz(provider); + OHOS::DisableRdbSubsFuzz(provider); + OHOS::SubscribePublishedDataFuzz(provider); + OHOS::UnsubscribePublishedDataFuzz(provider); + OHOS::EnablePubSubsFuzz(provider); + OHOS::DisablePubSubsFuzz(provider); + OHOS::SetSilentSwitchFuzz(provider); + OHOS::InsertExFuzz(provider); + OHOS::UpdateExFuzz(provider); + OHOS::DeleteExFuzz(provider); + OHOS::UserDefineFuncFuzz(provider); + return 0; +} \ No newline at end of file diff --git a/data_share/test/fuzztest/datasharehelp_fuzzer/datasharehelp_fuzzer.h b/data_share/test/fuzztest/datasharehelp_fuzzer/datasharehelp_fuzzer.h new file mode 100644 index 00000000..70923395 --- /dev/null +++ b/data_share/test/fuzztest/datasharehelp_fuzzer/datasharehelp_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 DATA_SHARE_HELP_FUZZER_H +#define DATA_SHARE_HELP_FUZZER_H + +#define FUZZ_PROJECT_NAME "datasharehelp_fuzzer" + +#endif // DATA_SHARE_HELP_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/project.xml b/data_share/test/fuzztest/datasharehelp_fuzzer/project.xml similarity index 64% rename from relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/project.xml rename to data_share/test/fuzztest/datasharehelp_fuzzer/project.xml index 6d3e765c..a37a23b1 100644 --- a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/project.xml +++ b/data_share/test/fuzztest/datasharehelp_fuzzer/project.xml @@ -1,5 +1,5 @@ - - - - 1000 - - 300 - - 4096 - + + + 1000 + + 300 + + 4096 + \ No newline at end of file diff --git a/data_share/test/native/BUILD.gn b/data_share/test/native/BUILD.gn index d0f24cd3..fb41ffa1 100644 --- a/data_share/test/native/BUILD.gn +++ b/data_share/test/native/BUILD.gn @@ -21,7 +21,16 @@ group("unittest") { deps += [ ":AbnormalBranchTest", ":ControllerTest", + ":DataProxyHandleTest", + ":DataShareAccessThresholdTest", + ":DataShareBlockWriterImplTest", + ":DataShareCommonTest", + ":DataShareConnectionTest", ":DataShareHelperImplTest", + ":DataShareHelperTest", + ":DataShareProxyTest", + ":DataShareStubTest", + ":DatashareItypesUtilsTest", ":ErrorCodeTest", ":JoinTest", ":NativeDataShareTest", @@ -53,23 +62,12 @@ config("permission_config") { } ohos_unittest("NativeDataShareTest") { - module_out_path = "data_share/native_datashare" + module_out_path = "data_share/data_share/inner_tests" visibility = [ ":*" ] include_dirs = [ - "//foundation/ability/ability_runtime/interfaces/inner_api/ability_manager/include", - "//foundation/ability/ability_runtime/interfaces/inner_api/app_manager/include/appmgr", - "//foundation/ability/ability_runtime/interfaces/inner_api/dataobs_manager/include", - "//foundation/ability/ability_runtime/interfaces/kits/native/ability/native", "./unittest/mediadatashare_test/include", - "//base/security/access_token/frameworks/common/include", - "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", - "//foundation/aafwk/standard/interfaces/innerkits/uri/include", - "//commonlibrary/c_utils/base/include", - "//utils/system/safwk/native/include", - "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", - "//third_party/json/include", "${datashare_native_proxy_path}/include", ] @@ -98,7 +96,6 @@ ohos_unittest("NativeDataShareTest") { "hitrace:hitrace_meter", "ipc:ipc_single", "relational_store:rdb_data_ability_adapter", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] @@ -110,16 +107,7 @@ ohos_unittest("NativeDataShareTest") { } ohos_unittest("PermissionTest") { - module_out_path = "data_share/native_datashare" - - include_dirs = [ - "${access_token_path}/frameworks/common/include", - "${base_hiviewdfx_hilog_path}/interfaces/native/innerkits/include", - "${commonlibrary_cutils_path}/base/include", - "${foundation_path}/aafwk/standard/interfaces/innerkits/uri/include", - "${foundation_path}/communication/ipc/interfaces/innerkits/ipc_core/include", - "${utils_system_safwk_path}/native/include", - ] + module_out_path = "data_share/data_share/inner_tests" sources = [ "./unittest/mediadatashare_test/src/permission_test.cpp" ] configs = [ ":permission_config" ] @@ -142,22 +130,12 @@ ohos_unittest("PermissionTest") { "common_event_service:cesfwk_innerkits", "hilog:libhilog", "ipc:ipc_single", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] } ohos_unittest("SlientAccessTest") { - module_out_path = "data_share/native_datashare" - - include_dirs = [ - "//base/security/access_token/frameworks/common/include", - "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", - "//foundation/aafwk/standard/interfaces/innerkits/uri/include", - "//commonlibrary/c_utils/base/include", - "//utils/system/safwk/native/include", - "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", - ] + module_out_path = "data_share/data_share/inner_tests" sources = [ "./unittest/mediadatashare_test/src/slientaccess_test.cpp" ] @@ -179,13 +157,12 @@ ohos_unittest("SlientAccessTest") { "common_event_service:cesfwk_innerkits", "hilog:libhilog", "ipc:ipc_single", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] } ohos_unittest("SlientSwitchTest") { - module_out_path = "data_share/native_datashare" + module_out_path = "data_share/data_share/inner_tests" sources = [ "./unittest/mediadatashare_test/src/slientswitch_test.cpp" ] @@ -206,22 +183,12 @@ ohos_unittest("SlientSwitchTest") { "common_event_service:cesfwk_innerkits", "hilog:libhilog", "ipc:ipc_single", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] } ohos_unittest("ErrorCodeTest") { - module_out_path = "data_share/native_datashare" - - include_dirs = [ - "//base/security/access_token/frameworks/common/include", - "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", - "//foundation/aafwk/standard/interfaces/innerkits/uri/include", - "//commonlibrary/c_utils/base/include", - "//utils/system/safwk/native/include", - "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", - ] + module_out_path = "data_share/data_share/inner_tests" sources = [ "./unittest/mediadatashare_test/src/errorcode_test.cpp" ] @@ -242,22 +209,12 @@ ohos_unittest("ErrorCodeTest") { "common_event_service:cesfwk_innerkits", "hilog:libhilog", "ipc:ipc_single", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] } ohos_unittest("JoinTest") { - module_out_path = "data_share/native_datashare" - - include_dirs = [ - "//base/security/access_token/frameworks/common/include", - "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", - "//foundation/aafwk/standard/interfaces/innerkits/uri/include", - "//commonlibrary/c_utils/base/include", - "//utils/system/safwk/native/include", - "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", - ] + module_out_path = "data_share/data_share/inner_tests" sources = [ "./unittest/mediadatashare_test/src/join_test.cpp" ] @@ -278,22 +235,12 @@ ohos_unittest("JoinTest") { "common_event_service:cesfwk_innerkits", "hilog:libhilog", "ipc:ipc_single", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] } ohos_unittest("ProxyDatasTest") { - module_out_path = "data_share/native_datashare" - - include_dirs = [ - "//base/security/access_token/frameworks/common/include", - "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", - "//foundation/aafwk/standard/interfaces/innerkits/uri/include", - "//commonlibrary/c_utils/base/include", - "//utils/system/safwk/native/include", - "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", - ] + module_out_path = "data_share/data_share/inner_tests" sources = [ "./unittest/datashareproxy_test/proxydatas_with_permission_test.cpp" ] @@ -314,22 +261,14 @@ ohos_unittest("ProxyDatasTest") { "c_utils:utils", "hilog:libhilog", "ipc:ipc_single", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] } ohos_unittest("ControllerTest") { - module_out_path = "data_share/native_datashare" + module_out_path = "data_share/data_share/inner_tests" include_dirs = [ - "${access_token_path}/frameworks/common/include", - "${base_hiviewdfx_hilog_path}/interfaces/native/innerkits/include", - "${foundation_path}/aafwk/standard/interfaces/innerkits/uri/include", - "${commonlibrary_cutils_path}/base/include", - "${utils_system_safwk_path}/native/include", - "${foundation_path}/communication/ipc/interfaces/innerkits/ipc_core/include", - "${thirdparty_json_path}/include", "${datashare_innerapi_path}/consumer/include", "${datashare_native_consumer_path}/controller/common", "${datashare_native_consumer_path}/controller/provider/include", @@ -362,24 +301,34 @@ ohos_unittest("ControllerTest") { "hitrace:hitrace_meter", "ipc:ipc_single", "relational_store:rdb_data_ability_adapter", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] } ohos_unittest("AbnormalBranchTest") { - module_out_path = "data_share/native_datashare" + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "../../cfi_blocklist.txt" + } + + module_out_path = "data_share/data_share/inner_tests" include_dirs = [ - "${access_token_path}/frameworks/common/include", - "${base_hiviewdfx_hilog_path}/interfaces/native/innerkits/include", - "${foundation_path}/aafwk/standard/interfaces/innerkits/uri/include", - "${commonlibrary_cutils_path}/base/include", - "${utils_system_safwk_path}/native/include", - "${foundation_path}/communication/ipc/interfaces/innerkits/ipc_core/include", "//foundation/distributeddatamgr/data_share/frameworks/native/proxy/include/", "//foundation/distributeddatamgr/data_share/frameworks/native/common/include/", "${datashare_native_proxy_path}/include", + "${datashare_base_path}/test/native/unittest/mock", ] sources = [ "./unittest/mediadatashare_test/src/abnormal_branch_test.cpp" ] @@ -401,11 +350,11 @@ ohos_unittest("AbnormalBranchTest") { "access_token:libtoken_setproc", "c_utils:utils", "common_event_service:cesfwk_innerkits", + "googletest:gmock_main", "hilog:libhilog", "hitrace:hitrace_meter", "ipc:ipc_single", "relational_store:rdb_data_ability_adapter", - "safwk:system_ability_fwk", "samgr:samgr_proxy", ] @@ -417,7 +366,7 @@ ohos_unittest("AbnormalBranchTest") { } ohos_unittest("ValueProxyTest") { - module_out_path = "data_share/native_datashare" + module_out_path = "data_share/data_share/inner_tests" include_dirs = [ "${datashare_base_path}/frameworks/native/common/include/" ] @@ -435,7 +384,7 @@ ohos_unittest("ValueProxyTest") { } ohos_unittest("URIUtilsTest") { - module_out_path = "data_share/native_datashare" + module_out_path = "data_share/data_share/inner_tests" include_dirs = [ "${datashare_base_path}/frameworks/native/common/include/" ] @@ -456,7 +405,7 @@ ohos_unittest("URIUtilsTest") { } ohos_unittest("DataShareHelperImplTest") { - module_out_path = "data_share/native_datashare" + module_out_path = "data_share/data_share/inner_tests" include_dirs = [ "${datashare_native_consumer_path}/include", @@ -496,6 +445,7 @@ ohos_unittest("DataShareHelperImplTest") { "${datashare_native_proxy_path}/src/idata_share_client_death_observer.cpp", "${datashare_native_proxy_path}/src/published_data_subscriber_manager.cpp", "${datashare_native_proxy_path}/src/rdb_subscriber_manager.cpp", + "${datashare_native_proxy_path}/src/proxy_data_subscriber_manager.cpp", "./unittest/mediadatashare_test/src/datashare_helper_impl_test.cpp", ] @@ -515,11 +465,11 @@ ohos_unittest("DataShareHelperImplTest") { "hitrace:libhitracechain", "ipc:ipc_single", "ipc:rpc", + "kv_store:distributeddata_inner", + "relational_store:native_appdatafwk", "samgr:samgr_proxy", ] - public_external_deps = [ "kv_store:distributeddata_inner" ] - cflags = [ "-fvisibility=hidden", "-Dprivate=public", @@ -528,7 +478,7 @@ ohos_unittest("DataShareHelperImplTest") { } ohos_unittest("SharedBlockTest") { - module_out_path = "data_share/native_datashare" + module_out_path = "data_share/data_share/inner_tests" include_dirs = [ "${datashare_common_native_path}/include" ] @@ -540,6 +490,146 @@ ohos_unittest("SharedBlockTest") { "c_utils:utils", "googletest:gmock_main", "hilog:libhilog", + "ipc:ipc_single", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DataShareBlockWriterImplTest") { + module_out_path = "data_share/data_share/inner_tests" + + include_dirs = [ + "${datashare_native_consumer_path}/include", + "${datashare_common_native_path}/include", + "${datashare_innerapi_path}/consumer/include", + "${datashare_innerapi_path}/common/include", + "${datashare_innerapi_path}/provider/include", + "${datashare_native_consumer_path}/controller/provider/include", + "${datashare_native_consumer_path}/controller/common", + "${datashare_native_consumer_path}/controller/service/include", + "${datashare_native_proxy_path}/include", + ] + + sources = [ + "./unittest/mediadatashare_test/src/datashare_block_writer_impl_test.cpp", + ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:zuri", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "kv_store:distributeddata_inner", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DataShareHelperTest") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "../../cfi_blocklist.txt" + } + + module_out_path = "data_share/data_share/inner_tests" + + include_dirs = [ + "${datashare_base_path}/frameworks/native/common/include/", + "${datashare_base_path}/test/native/unittest/mock", + ] + + sources = [ "./unittest/mediadatashare_test/src/datashare_helper_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "googletest:gmock_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "ipc:rpc", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DataShareCommonTest") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "../../cfi_blocklist.txt" + } + + module_out_path = "data_share/data_share/inner_tests" + + include_dirs = [ "${datashare_base_path}/frameworks/native/common/include/" ] + + sources = [ "./unittest/mediadatashare_test/src/datashare_common_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "googletest:gmock_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_core", + "ipc:ipc_single", + "ipc:rpc", + "samgr:samgr_proxy", ] cflags = [ @@ -548,3 +638,278 @@ ohos_unittest("SharedBlockTest") { "-Dprotected=public", ] } + +ohos_unittest("DataShareProxyTest") { + module_out_path = "data_share/data_share/inner_tests" + + include_dirs = [ + "${datashare_innerapi_path}/consumer/include", + "${datashare_native_consumer_path}/controller/common", + "${datashare_native_consumer_path}/controller/provider/include", + "${datashare_native_consumer_path}/controller/service/include", + "${datashare_native_consumer_path}/include", + "${datashare_innerapi_path}/common/include", + "${datashare_native_proxy_path}/include", + ] + + sources = [ "./unittest/mediadatashare_test/src/datashare_proxy_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_single", + "relational_store:rdb_data_ability_adapter", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + } +} + +ohos_unittest("DataShareConnectionTest") { + module_out_path = "data_share/data_share/inner_tests" + + include_dirs = [ + "${datashare_innerapi_path}/consumer/include", + "${datashare_native_consumer_path}/controller/common", + "${datashare_native_consumer_path}/controller/provider/include", + "${datashare_native_consumer_path}/controller/service/include", + "${datashare_native_consumer_path}/include", + "${datashare_innerapi_path}/common/include", + "${datashare_native_proxy_path}/include", + ] + + sources = + [ "./unittest/mediadatashare_test/src/datashare_connection_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_single", + "relational_store:rdb_data_ability_adapter", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + } +} + +ohos_unittest("DataShareStubTest") { + module_out_path = "data_share/data_share/inner_tests" + + include_dirs = [ + "${datashare_innerapi_path}/consumer/include", + "${datashare_innerapi_path}/common/include", + "${datashare_native_provider_path}/include", + "${datashare_native_proxy_path}/include", + ] + + sources = [ "./unittest/mediadatashare_test/src/datashare_stub_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}:datashare_provider", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_single", + "ipc:ipc_napi", + "relational_store:rdb_data_ability_adapter", + "samgr:samgr_proxy", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "../../cfi_blocklist.txt" + } + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DatashareItypesUtilsTest") { + module_out_path = "data_share/data_share/inner_tests" + + include_dirs = [ "${datashare_common_native_path}/include" ] + + sources = + [ "./unittest/datashare_common_test/datashare_itypes_utils_test.cpp" ] + + deps = [ "${datashare_innerapi_path}/common:datashare_common_static" ] + + external_deps = [ + "ability_base:zuri", + "c_utils:utils", + "googletest:gmock_main", + "hilog:libhilog", + "ipc:ipc_single", + "kv_store:distributeddata_inner", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DataShareAccessThresholdTest") { + module_out_path = "data_share/data_share/inner_tests" + + sources = [ "./unittest/datashare_access_threshold_test/datashare_threshold_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer", + "${datashare_innerapi_path}/common:datashare_common", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "ipc:ipc_single", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DataProxyHandleTest") { + module_out_path = "data_share/data_share/inner_tests" + + include_dirs = [ "${datashare_base_path}/frameworks/native/common/include/" ] + + sources = [ "./unittest/dataproxy_handle_test/dataproxy_handle_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer", + "${datashare_innerapi_path}/common:datashare_common", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "googletest:gmock_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "ipc:rpc", + "samgr:samgr_proxy", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "../../cfi_blocklist.txt" + } + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/app.json5 b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/app.json5 new file mode 100644 index 00000000..c347ece5 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ +{ + "app": { + "bundleName": "com.acts.ohos.data.datasharetestclient1", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/resources/base/element/string.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/resources/base/element/string.json new file mode 100644 index 00000000..1080233f --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "MyApplication" + } + ] +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/resources/base/media/app_icon.png b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 zcmX|G1ymHk)?T_}Vd;>R?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}y("TestAbilityContext",this.context) + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/pages/Index.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/pages/Index.ets new file mode 100644 index 00000000..054f5d74 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,520 @@ +import { + connectDataShareExtAbility001, + connectDataShareExtAbility002, + disconnectDataShareExtAbility, + onRdb, + offRdb, + queryTest1, + queryTest2, + insertTest1, + insertTest2, + // queryTest, + // insertTest, + updateTest, + deleteTest, + offPublishData, + onPublishData, + getPublishedData, + publishTest, + publishTest2, + publishTest3, + offPublishDataErr1, + offPublishDataErr2, + GetCloneBundleInfoTest, + GetSelfBundleInfoTest +} from './myClient.test' +let result = undefined; +@Entry +@Component +struct Index { + @State message: string = "Main thread message filed" + + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('DataShareClient1 Ability Test') + .fontSize(20) + .fontWeight(FontWeight.Bold) + + Text(`${this.message}`) + .fontSize(25) + .height('15%') + .width('100%') + .textAlign(TextAlign.Center) + + Row() { + Button() { + Text('Connect') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Connect onclick enter') + this.message = 'Connect onclick' + await connectDataShareExtAbility001() + console.info('[ttt] [DataShareClientTest] <> Connect onclick leave') + }) + + Button() { + Text('Disconnect') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Disconnect onclick enter') + this.message = 'Disconnect onclick' + await disconnectDataShareExtAbility() + console.info('[ttt] [DataShareClientTest] <> Disconnect onclick leave') + }) + } + + // Row() { + // Button() { + // Text('Connect1') + // .fontSize(20) + // .fontWeight(FontWeight.Bold) + // }.type(ButtonType.Capsule) + // .margin({ + // top: 8 + // }) + // .width('45%') + // .height('8%') + // .backgroundColor('#0ddffb') + // .onClick(async () => { + // console.info('[ttt] [DataShareClientTest] <> Connect1 onclick enter') + // this.message = 'Connect1 onclick' + // await connectDataShareExtAbility001() + // console.info('[ttt] [DataShareClientTest] <> Connect1 onclick leave') + // }) + // + // Button() { + // Text('Connect2') + // .fontSize(20) + // .fontWeight(FontWeight.Bold) + // }.type(ButtonType.Capsule) + // .margin({ + // top: 8 + // }) + // .width('45%') + // .height('8%') + // .backgroundColor('#0ddffb') + // .onClick(async () => { + // console.info('[ttt] [DataShareClientTest] <> Connect2 onclick enter') + // this.message = 'Connect2 onclick' + // await connectDataShareExtAbility002() + // console.info('[ttt] [DataShareClientTest] <> Connect2 onclick leave') + // }) + // } + + Row() { + Button() { + Text('On') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> addTemplate onclick enter') + this.message = '~ addTemplate onclick' + try { + await onRdb(); + } catch (err) { + console.error('[ttt] [DataAbilityTest] Observer on catch(err)====>:' + err); + } + console.info('[ttt] [DataShareClientTest] <> addTemplate onclick leave') + }) + + Button() { + Text('Off') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Off onclick enter') + this.message = '~ Off onclick' + try { + await offRdb(); + } catch (err) { + console.error('[ttt] [DataAbilityTest] Observer Off catch(err)====>:' + err); + } + console.info('[ttt] [DataShareClientTest] <> Off onclick leave') + }) + // Button() { + // Text('Clone') + // .fontSize(20) + // .fontWeight(FontWeight.Bold) + // }.type(ButtonType.Capsule) + // .margin({ + // top: 8 + // }) + // .width('45%') + // .height('8%') + // .backgroundColor('#0ddffb') + // .onClick(async () => { + // console.info('[ttt] [DataShareClientTest] <> GetCloneBundleInfo onclick enter') + // this.message = '~ Off onclick' + // try { + // await GetCloneBundleInfoTest(); + // } catch (err) { + // console.error('[ttt] [DataAbilityTest] Observer GetCloneBundleInfo catch(err)====>:' + err); + // } + // console.info('[ttt] [DataShareClientTest] <> GetCloneBundleInfo onclick leave') + // }) + + } + + Row() { + Button() { + Text('Query1') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Query1 onclick enter') + this.message = '~ Query1 onclick' + try { + await queryTest1(); + } catch (err) { + console.error('[ttt] [DataAbilityTest] Observer Query1 catch(err)====>:' + err); + } + console.info('[ttt] [DataShareClientTest] <> Query1 onclick leave') + }) + + Button() { + Text('Query2') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Query2 onclick enter') + this.message = '~ Query2 onclick' + try { + await queryTest2(); + } catch (err) { + console.error('[ttt] [DataAbilityTest] Observer Query2 catch(err)====>:' + err); + } + console.info('[ttt] [DataShareClientTest] <> Query2 onclick leave') + }) + } + + Row() { + Button() { + Text('Insert1') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Insert1 onclick enter') + this.message = 'insert1 onclick' + let ret = await insertTest1() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> Insert1 onclick leave') + }) + + Button() { + Text('Insert2') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Insert2 onclick enter') + this.message = 'Insert2 onclick' + let ret = await insertTest2() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> Insert2 onclick leave') + }) + } + + // Row() { + // Button() { + // Text('Query') + // .fontSize(20) + // .fontWeight(FontWeight.Bold) + // }.type(ButtonType.Capsule) + // .margin({ + // top: 8 + // }) + // .width('45%') + // .height('8%') + // .backgroundColor('#0ddffb') + // .onClick(async () => { + // console.info('[ttt] [DataShareServerTest] <> Query onclick enter') + // this.message = 'Query onclick' + // let ret = await queryTest() + // this.message += "\n\n Test Result: " + ret; + // console.info('[ttt] [DataShareServerTest] <> Query onclick leave') + // }) + // + // Button() { + // Text('Insert') + // .fontSize(20) + // .fontWeight(FontWeight.Bold) + // }.type(ButtonType.Capsule) + // .margin({ + // top: 8 + // }) + // .width('45%') + // .height('8%') + // .backgroundColor('#0ddffb') + // .onClick(async () => { + // console.info('[ttt] [DataShareServerTest] <> Insert onclick enter') + // this.message = 'Insert onclick' + // let ret = await insertTest() + // this.message += "\n\n Test Result: " + ret; + // console.info('[ttt] [DataShareServerTest] <> Insert onclick leave') + // }) + // } + + Row() { + Button() { + Text('Update') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Update onclick enter') + this.message = 'Update onclick' + let ret = await updateTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> Update onclick leave') + }) + + Button() { + Text('Delete') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Delete onclick enter') + this.message = 'Delete onclick' + let ret = await deleteTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> Delete onclick leave') + }) + } + + Row() { + Button() { + Text('OffPublishData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> OffPublishData onclick enter') + this.message = 'OffPublishData onclick' + await offPublishData() + console.info('[ttt] [DataShareClientTest] <> OffPublishData onclick leave') + }) + + + Button() { + Text('OnPublishData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> OnPublishData onclick enter') + this.message = 'OnPublishData onclick' + onPublishData() + offPublishData() + console.info('[ttt] [DataShareClientTest] <> OnPublishData onclick leave') + }) + } + + Row() { + Button() { + Text('getPublishedData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> getPublishedData onclick enter') + this.message = 'getPublishedData onclick' + let ret = await getPublishedData() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> getPublishedData onclick leave') + }) + + Button() { + Text('Publish') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> publish onclick enter') + this.message = 'publish onclick' + let ret = await publishTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> publish onclick leave') + }) + } + + + // Row() { + // Button() { + // Text('Publish2.0') + // .fontSize(20) + // .fontWeight(FontWeight.Bold) + // }.type(ButtonType.Capsule) + // .margin({ + // top: 8 + // }) + // .width('45%') + // .height('8%') + // .backgroundColor('#0ddffb') + // .onClick(async () => { + // console.info('[ttt] [DataShareClientTest] <> Publish2.0 onclick enter') + // this.message = 'Publish2.0 onclick' + // let ret = await publishTest2() + // this.message += "\n\n Test Result: " + ret; + // console.info('[ttt] [DataShareClientTest] <> Publish2.0 onclick leave') + // }) + // + // + // Button() { + // Text('Publish3.0') + // .fontSize(20) + // .fontWeight(FontWeight.Bold) + // }.type(ButtonType.Capsule) + // .margin({ + // top: 8 + // }) + // .width('45%') + // .height('8%') + // .backgroundColor('#0ddffb') + // .onClick(async () => { + // console.info('[ttt] [DataShareClientTest] <> Publish3.0 onclick enter') + // this.message = 'Publish3.0 onclick' + // let ret = await publishTest3() + // this.message += "\n\n Test Result: " + ret; + // console.info('[ttt] [DataShareClientTest] <> Publish3.0 onclick leave') + // }) + // } + + Row() { + Button() { + Text('offPublishDataErr1') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> offPublishDataErr1 onclick enter') + this.message = 'offPublishDataErr1 onclick' + await offPublishDataErr1() + console.info('[ttt] [DataShareClientTest] <> offPublishDataErr1 onclick leave') + }) + + + Button() { + Text('offPublishDataErr2') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> offPublishDataErr2 onclick enter') + this.message = 'offPublishDataErr2 onclick' + await offPublishDataErr2() + console.info('[ttt] [DataShareClientTest] <> offPublishDataErr2 onclick leave') + }) + } + + } + .width('100%') + .height('100%') + } +} + diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/pages/myClient.test.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/pages/myClient.test.ets new file mode 100644 index 00000000..35cf84fc --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/ets/pages/myClient.test.ets @@ -0,0 +1,452 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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 dataShare from '@ohos.data.dataShare' +import dataSharePredicates from '@ohos.data.dataSharePredicates' +import { BusinessError } from '@ohos.base'; +import { ValuesBucket } from '@ohos.data.ValuesBucket'; +import rpc from '@ohos.rpc'; +import common from "@ohos.app.ability.common" +import bundleManager from '@ohos.bundle.bundleManager'; + +let cardUri = ("datashareproxy://com.acts.ohos.data.datasharetest/test"); +let cloneUri = ("datashareproxy://com.acts.ohos.data.datasharetest/test?appIndex=abcd"); + +let dsProxyHelper: dataShare.DataShareHelper | undefined = undefined +let dsProxyHelper2: dataShare.DataShareHelper | undefined = undefined + + +let context: common.UIAbilityContext +context = AppStorage.get("TestAbilityContext") as common.UIAbilityContext + +export async function connectDataShareExtAbility001() { + console.log("[ttt] [DataShareClientTest] <> connectDataShareExtAbility1 begin "); + dsProxyHelper = await dataShare.createDataShareHelper(context, cardUri, {isProxy : true}); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> DSHelper1 is null"); + } + console.log("[ttt] [DataShareClientTest] <> dsProxyHelper1 " + JSON.stringify(dsProxyHelper)); +} + +export async function connectDataShareExtAbility002() { + console.log("[ttt] [DataShareClientTest] <> connectDataShareExtAbility2 begin "); + dsProxyHelper2 = await dataShare.createDataShareHelper(context, cloneUri, {isProxy : true}); + if (dsProxyHelper2 == null) { + console.log("[ttt] [DataShareClientTest] <> DSHelper2 is null"); + } + console.log("[ttt] [DataShareClientTest] <> dsProxyHelper2 " + JSON.stringify(dsProxyHelper2)); +} + +export async function disconnectDataShareExtAbility() { + console.log("[ttt] [DataShareClientTest] <> disconnectDataShareExtAbility begin"); + dsProxyHelper = undefined; + console.log("[ttt] [DataShareClientTest] <> disconnectDataShareExtAbility end"); +} + + +export async function onRdb() { + console.log("[ttt] [DataShareClientTest] <> on begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> on end, DSHelper is null"); + return; + } + let template: dataShare.Template = { + predicates: { + "p1": "select name0 as name from TBL00", + "p2": "select name1 as name from TBL00", + }, + scheduler: "select remindTimer(strftime('%s', 'now', '+10 seconds'))" + } + dsProxyHelper.addTemplate(cardUri, "111", template); + let templateId: dataShare.TemplateId = { + subscriberId: "111", bundleNameOfOwner: "com.acts.ohos.data.datasharetestclient" + } + let result: Array = dsProxyHelper.on("rdbDataChange", [cardUri], templateId, onCallback); + console.log("[ttt] [DataShareClientTest] <> on end " + JSON.stringify(result)); +} + +export function onCallback(err:BusinessError, node:dataShare.RdbDataChangeNode) { + console.info("[ttt] [DataShareClientTest] [callback] rdb change ININ"); + // console.info("[ttt] [DataShareClientTest] [callback] " + JSON.stringify(node.uri)); + // console.info("[ttt] [DataShareClientTest] [callback] " + JSON.stringify(node.templateId)); + // console.info("[ttt] [DataShareClientTest] [callback] insert length is " + node.data.length); + for (let i = 0; i < node.data.length; i++) { + // console.info("[ttt] [DataShareClientTest] [callback] " + typeof node.data[i]); + console.info("[ttt] [DataShareClientTest] [callback] " + node.data[i]); + } + +} + +export async function offRdb() { + console.log("[ttt] [DataShareClientTest] <> off begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> off end, DSHelper is null"); + return; + } + let templateId:dataShare.TemplateId = {subscriberId:"111", bundleNameOfOwner:"com.acts.ohos.data.datasharetestclient"} + let result:Array = dsProxyHelper.off("rdbDataChange", [cardUri], templateId); + console.log("[ttt] [DataShareClientTest] <> off end " + JSON.stringify(result)); +} + +export async function queryTest1() { + console.log("[ttt] [DataShareClientTest] <> query1 begin"); + let da = new dataSharePredicates.DataSharePredicates(); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + let count = 0; + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> query1 end, DSHelper1 is null"); + return; + } + let result = await dsProxyHelper.query(cardUri, da, ["*"]); + if (result != undefined) { + count = result.rowCount; + console.log("[ttt] [DataShareClientTest] <> query1 end, result:" + JSON.stringify(result)); + } + console.log("[ttt] [DataShareClientTest] <> query1 end, count222:" + count); + return count; +} + +export async function queryTest2() { + console.log("[ttt] [DataShareClientTest] <> query2 begin"); + let da = new dataSharePredicates.DataSharePredicates(); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + let count = 0; + if (dsProxyHelper2 == null) { + console.log("[ttt] [DataShareClientTest] <> query2 end, DSHelper2 is null"); + return; + } + let result = await dsProxyHelper2.query(cloneUri, da, ["*"]); + if (result != undefined) { + count = result.rowCount; + console.log("[ttt] [DataShareClientTest] <> query2 end, result:" + JSON.stringify(result)); + } + console.log("[ttt] [DataShareClientTest] <> query2 end, count222:" + count); + return count; +} + +export async function insertTest1() { + console.log("[ttt] [DataShareClientTest] <> insert1 begin"); + // dsProxyHelper = await dataShare.createDataShareHelper(context, cardUri, {isProxy : true}); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> insert1 end, DSHelper is null"); + return; + } + + let i = 0; + let ret = 0; + for (i = 0; i < 2; i++) { + let vb: ValuesBucket = { + "name0": "name0" + i, + "name1": "name1" + i, + "name2": "name2" + i, + "name3": "name3" + i, + "name4": "name4" + i, + "name5": "name5" + i, + "name6": "name6" + i, + "name7": "name7" + i, + "name8": "name8" + i, + "name9": "name9" + i, + }; + ret = await dsProxyHelper.insert(cardUri, vb); + console.log("[ttt] [DataShareClientTest] <> insert1 end rowNum is " + ret); + } + return ret; +} + +export async function insertTest2() { + console.log("[ttt] [DataShareClientTest] <> insert2 begin"); + if (dsProxyHelper2 == null) { + console.log("[ttt] [DataShareClientTest] <> insert2 end, DSHelper2 is null"); + return; + } + + let i = 0; + let ret = 0; + for (i = 0; i < 2; i++) { + let vb: ValuesBucket = { + "name0": "name0" + i, + "name1": "name1" + i, + "name2": "name2" + i, + "name3": "name3" + i, + "name4": "name4" + i, + "name5": "name5" + i, + "name6": "name6" + i, + "name7": "name7" + i, + "name8": "name8" + i, + "name9": "name9" + i, + }; + ret = await dsProxyHelper2.insert(cloneUri, vb); + console.log("[ttt] [DataShareClientTest] <> insert2 end rowNum is " + ret); + } + return ret; +} + +export async function updateTest() { + console.log("[ttt] [DataShareClientTest] <> update begin"); + if (dsProxyHelper2 == null) { + console.log("[ttt] [DataShareClientTest] <> update end, DSHelper is null"); + return; + } + console.log("[ttt] [DataShareClientTest] <> update begin RPF666"); + let da = new dataSharePredicates.DataSharePredicates(); + console.log("[ttt] [DataShareClientTest] <> update begin RPF777"); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + let ret = dsProxyHelper2.update(cloneUri, da, { "name0": "ZhangSan" }); + console.log("[ttt] [DataShareClientTest] <> update end, result:" + ret); + return ret; +} + +export async function batchUpdate() { + console.log("[ttt] [DataShareClientTest] <> update begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> update end, DSHelper is null"); + return; + } + + console.log("[ttt] [DataShareClientTest] <> update begin RPF666"); + let da = new dataSharePredicates.DataSharePredicates(); + console.log("[ttt] [DataShareClientTest] <> update begin RPF777"); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + // let ret = dsProxyHelper.update(cardUri, da, { "name0": "ZhangSan" }); + // console.log("[ttt] [DataShareClientTest] <> update end, result:" + ret); + // return ret; +} + +export async function deleteTest() { + console.log("[ttt] [DataShareClientTest] <> delete begin"); + if (dsProxyHelper2 == null) { + console.log("[ttt] [DataShareClientTest] <> delete end, DSHelper is null"); + return; + } + let da = new dataSharePredicates.DataSharePredicates(); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + let ret = await dsProxyHelper2.delete(cloneUri, da); + console.log("[ttt] [DataShareClientTest] <> delete end, result:" + ret); + return ret; +} + +export async function offPublishData() { + console.log("[ttt] [DataShareClientTest] <> offPublishData begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> on end, DSHelper is null"); + return; + } + + try{ + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", "datashareproxy://com.acts.ohos.data.datasharetest/test"]; + let result: Array = dsProxyHelper.off("publishedDataChange", + uris, + "11", onPublishCallback); + console.log("[ttt] [DataShareClientTest] <> off end " + JSON.stringify(result)); + }catch(err){ + console.error(` [ttt] offPublishData error: code: ${err.code}, message: ${err.message} `); + } +} + +export async function offPublishDataErr1() { + console.log("[ttt] [DataShareClientTest] <> offPublishDataErr1 begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> on end, DSHelper is null"); + return; + } + + try{ + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", "datashareproxy://com.acts.ohos.data.datasharetest/test"]; + let result: Array = dsProxyHelper.off("publishedDataChange", + uris, + "11", undefined); + console.log("[ttt] [DataShareClientTest] <> off end " + JSON.stringify(result)); + }catch(err){ + console.error(` [ttt] offPublishDataErr1 error: code: ${err.code}, message: ${err.message} `); + } +} + + +export async function offPublishDataErr2() { + console.log("[ttt] [DataShareClientTest] <> off begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> off end, DSHelper is null"); + return; + } + let templateId:dataShare.TemplateId = {subscriberId:"111", bundleNameOfOwner:"com.acts.ohos.data.datasharetestclient"} + try{ + let result:Array = dsProxyHelper.off("rdbDataChange", [cardUri], templateId,undefined); + console.log("[ttt] [DataShareClientTest] <> off end " + JSON.stringify(result)); + }catch(err){ + console.error(` [ttt] offPublishDataErr2 error: code: ${err.code}, message: ${err.message} `); + } + + +} + +export function onPublishCallback(err:BusinessError, node:dataShare.PublishedDataChangeNode) { + console.info("[ttt] [DataShareClientTest] [callback] publishedData change ININ"); + // console.info("[ttt] [DataShareClientTest] [callback] bundleName " + JSON.stringify(node.bundleName)); + console.info("[ttt] [DataShareClientTest] [callback] data size" + node.data.length); + for (let i = 0; i < node.data.length; i++) { + // console.info("[ttt] [DataShareClientTest] [callback]" + typeof node.data[i].data); + console.info("[ttt] [DataShareClientTest] [callback] data " + i + " " + JSON.stringify(node.data[i])); + } +} + +export async function onPublishData() { + console.log("[ttt] [DataShareClientTest] <> onPublishData begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> on end, DSHelper is null"); + return; + } + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", "datashareproxy://com.acts.ohos.data.datasharetest/test"]; + try { + console.log("[ttt] [DataShareClientTest] <> on begin"); + let result: Array = dsProxyHelper.on("publishedDataChange", uris, "11", onPublishCallback); + console.log("[ttt] [DataShareClientTest] <> on end " + JSON.stringify(result)); + } catch (e) { + console.log("[ttt] [DataShareClientTest] <> on err " + JSON.stringify(e)); + + } +} + +export async function getPublishedData() { + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> getPublishedData end, DSHelper is null"); + return; + } + console.log("[ttt] [DataShareClientTest] <> getPublishedData begin"); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + let ret = publishedData.length; + console.log("[ttt] [DataShareClientTest] <> getPublishedData end dataSize is " + ret); + console.log("[ttt] [DataShareClientTest] <> getPublishedData end data is " + JSON.stringify(publishedData)); + return ret; +} + + +export async function publishTest() { + console.log("[ttt] [DataShareClientTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key: "city", subscriberId: "11", data: "xian" + Math.random()}, + {key: "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key: "empty", subscriberId: "11", data: "nobody sub" + Math.random()}, + {key: "datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub " + Math.random()}]; + + let nums:number[] = [1,2,3]; + try { + // let ashmem = rpc.Ashmem.create("ashmem", (nums.length) * 4); + // console.log("[ttt] [DataShareClientTest] <> " + JSON.stringify(ashmem)); + // ashmem.mapReadWriteAshmem(); + // console.log("[ttt] [DataShareClientTest] <> "); + // console.log("[ttt] [DataShareClientTest] <> " + JSON.stringify(nums)); + // ashmem.writeAshmem(nums, nums.length, 0); + // console.log("[ttt] [DataShareClientTest] <> "); + + console.log("[ttt] [DataShareClientTest] <> data length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest"); + console.log("[ttt] [DataShareClientTest] <> publish end " + JSON.stringify(result)); + // ashmem.closeAshmem(); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareClientTest] <> getPublishedData end " + JSON.stringify(publishedData)); + // for (let i = 0; i < publishedData.length; i++) { + // console.info("[ttt][callback] " + typeof publishedData[i].data); + // if (typeof publishedData[i].data != 'string') { + // let ash:rpc.Ashmem = publishedData[i].data; + // ash.mapReadonlyAshmem(); + // console.info("[ttt][callback] " + JSON.stringify(ash.readAshmem(ash.getAshmemSize()/4, 0))); + // ash.closeAshmem(); + // } + // } + } catch (e) { + console.log("[ttt] [DataShareClientTest] <> publish error " + JSON.stringify(e)); + } +} + +export async function publishTest2() { + console.log("[ttt] [DataShareClientTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key:"city", subscriberId:"11", data:"xianServer22222"}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key:"empty", subscriberId:"11", data:"nobody sub Server"+222222}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub Server"+Math.random()}]; + + let nums:number[] = [1,2,3]; + try { + console.log("[ttt] [DataShareClientTest] <> datasss length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest",2); + console.log("[ttt] [DataShareClientTest] <> publish end " + JSON.stringify(result)); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareClientTest] <> getPublishedData end " + JSON.stringify(publishedData)); + } catch (e) { + console.log("[ttt] [DataShareClientTest] <> publish error " + JSON.stringify(e)); + } +} + +export async function publishTest3() { + console.log("[ttt] [DataShareClientTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key:"city", subscriberId:"11", data:"xianClient3333333"}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key:"empty", subscriberId:"11", data:"nobody sub Client"+33333}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub Server"+Math.random()}]; + + try { + console.log("[ttt] [DataShareClientTest] <> datasss length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest",3); + console.log("[ttt] [DataShareClientTest] <> publish end " + JSON.stringify(result)); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareClientTest] <> getPublishedData end " + JSON.stringify(publishedData)); + } catch (e) { + console.log("[ttt] [DataShareClientTest] <> publish error " + JSON.stringify(e)); + } +} + +export async function GetCloneBundleInfoTest() { + console.log("[ttt] [DataShareClientTest] <> GetCloneBundleInfoTest begin"); + let bundleName = ("com.acts.ohos.data.datasharetest"); + let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_EXTENSION_ABILITY | + bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_HAP_MODULE; + let appIndex = 1; + try { + bundleManager.getAppCloneBundleInfo(bundleName, appIndex, bundleFlags) .then((data) => { + console.log("[ttt] [DataShareClientTest] <> hapModuleInfos is:", JSON.stringify(data)); + }) + } catch (err) { + console.log("[ttt] [DataShareClientTest] <> publish error " + JSON.stringify(err)); + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/module.json5 b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/module.json5 new file mode 100644 index 00000000..211c03c8 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/module.json5 @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ + { + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:icon", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED" + } + ] + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/element/color.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/element/color.json new file mode 100644 index 00000000..82f853ff --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/element/string.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/element/string.json new file mode 100644 index 00000000..7ff16944 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/media/icon.png b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 zcmX|G1ymHk)?T_}Vd;>R?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}yR?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}y { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/test/List.test.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 00000000..5be61a34 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,5 @@ +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testability/TestAbility.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testability/TestAbility.ets new file mode 100644 index 00000000..5f77ecd9 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testability/TestAbility.ets @@ -0,0 +1,50 @@ +import UIAbility from '@ohos.app.ability.UIAbility'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import hilog from '@ohos.hilog'; +import { Hypium } from '@ohos/hypium'; +import testsuite from '../test/List.test'; +import window from '@ohos.window'; +import Want from '@ohos.app.ability.Want'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; + +export default class TestAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate'); + hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? ''); + hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? ''); + let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator; + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs; + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments(); + hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!'); + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite); + } + + onDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate'); + windowStage.loadContent('testability/pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', + JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); + } + + onForeground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); + } + + onBackground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testability/pages/Index.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testability/pages/Index.ets new file mode 100644 index 00000000..24774323 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testability/pages/Index.ets @@ -0,0 +1,17 @@ +@Entry +@Component +struct Index { + @State message: string = 'Hello World'; + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets new file mode 100644 index 00000000..1e10d5b9 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets @@ -0,0 +1,47 @@ +import hilog from '@ohos.hilog'; +import TestRunner from '@ohos.application.testRunner'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import Want from '@ohos.app.ability.Want'; + +let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator | undefined = undefined +let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs | undefined = undefined + +async function onAbilityCreateCallback() { + hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err : Error) { + hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? ''); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare '); + } + + async onRun() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run'); + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + const bundleName = abilityDelegatorArguments.bundleName; + const testAbilityName = 'TestAbility'; + let lMonitor: AbilityDelegatorRegistry.AbilityMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + const want: Want = { + bundleName: bundleName, + abilityName: testAbilityName + }; + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + abilityDelegator.startAbility(want, (err, data) => { + hilog.info(0x0000, 'testTag', 'startAbility : err : %{public}s', JSON.stringify(err) ?? ''); + hilog.info(0x0000, 'testTag', 'startAbility : data : %{public}s',JSON.stringify(data) ?? ''); + }) + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end'); + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/module.json5 b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/module.json5 new file mode 100644 index 00000000..26ca5ed1 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/module.json5 @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ +{ + "module": { + "name": "entry_test", + "type": "feature", + "description": "$string:module_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:test_pages", + "abilities": [ + { + "name": "TestAbility", + "srcEntry": "./ets/testability/TestAbility.ets", + "description": "$string:TestAbility_desc", + "icon": "$media:icon", + "label": "$string:TestAbility_label", + "exported": true, + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ] + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/element/color.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/element/color.json new file mode 100644 index 00000000..82f853ff --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/element/string.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 00000000..039de6a7 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_test_desc", + "value": "test ability description" + }, + { + "name": "TestAbility_desc", + "value": "the test ability" + }, + { + "name": "TestAbility_label", + "value": "test label" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/media/icon.png b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 zcmX|G1ymHk)?T_}Vd;>R?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}y { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/src/db_helper.cpp b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/hvigor/hvigor-config.json5 similarity index 35% rename from relational_store/frameworks/native/gdb/src/db_helper.cpp rename to data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/hvigor/hvigor-config.json5 index 44465920..cc3ef51a 100644 --- a/relational_store/frameworks/native/gdb/src/db_helper.cpp +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/hvigor/hvigor-config.json5 @@ -1,7 +1,7 @@ /* - * Copyright (c) 2024 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 not \tuse 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 @@ -12,24 +12,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include - -#include "gdb_errors.h" -#include "db_store_manager.h" -#include "db_trace.h" -#include "gdb_helper.h" - -namespace OHOS::DistributedDataAip { - -std::shared_ptr GDBHelper::GetDBStore(const StoreConfig &config, int &errCode) { - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - return StoreManager::GetInstance().GetDBStore(config, errCode); + "modelVersion": "5.0.0", + "dependencies": { + "@ohos/hvigor-ohos-online-sign-plugin": "4.0.1", + }, + "execution": { + // "daemon": true, /* Enable daemon compilation. Default: true */ + // "incremental": true, /* Enable incremental compilation. Default: true */ + // "parallel": true, /* Enable parallel compilation. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Default: false */ + } } - -int GDBHelper::DeleteDBStore(const StoreConfig &config) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - return StoreManager::GetInstance().Delete(config.GetFullPath()) ? E_OK : E_ERROR; -} -} // namespace OHOS::DistributedDataAip \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/sign/openharmony_sx.p7b b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareClient/sign/openharmony_sx.p7b new file mode 100644 index 0000000000000000000000000000000000000000..4512fc0e7c36f20aa275736dce5631c304a80dc0 GIT binary patch literal 3629 zcmcgvdvFtV9&a9Pt)&kw0`?S2K#D@jZ_}hrs-nBe<^`K{L((>-T-j_k$+nx_ZFbX5 zgFFn%i3q;6hk)f(;4J8XShzXyb%Nk2qjJoR2Y85`Qx5e!QBg*`-Lyc<=pT+VPG_hBRX{iWlA7egvf40RNASEpObcRy4kbk; zK@;K zhhXS1Eq3YZ7U)<`)Q6}Dmyp+mOctZL#$+&=r)Tvg~vh0}FI86+r% zA_PiaERp2&b$UraCExTN%_%c3?Usb z6hN&h4EI+fOsG8;BjZqKh;5HHI2vLtY{-wcVOBKj1*b6LN-w+#kwOlpE!gDaLk43M z2dLzXkshoKm9RFrOU}XXN_qWQs!`T@Z0#wm4NG0pwILja3z8Mj=IB5rx6R*%1~9}m zm{$y&-NIh6XUgG+n+EF?{3vRXnj1~7V3S)68B8XZ-NytQL28x_jt}}^{ub5=uJA(b z66r|sL4zF-axYwVHxrWUB@F?o(GUBPC^^(!7ov2!g&piQh9Hv13d8s5*87hu|U8AP&4BK{-$6v z>xoA(NZ>k?Aqww+{T$?y0ya3JWbT}Up$;3|7)AV{Sc0TmSi2aQ%>|Ox)pHtZlM&P& zAzY#_4STcRxEX;XW)y)jD`JEtr_xa$@FGYMwbzTOL^8&-u%r*c1$S5?n>%JFEu1IN z5G62Ja#*b$jyagoB1hX09JUcKEH&e<6zmoWP>&mUqs^6^!3!W> zVyt(>5C)5eX+t_`Y!$M!SF1LmuzpaUtJBSsjq=%#(}KcpS)YWwPl6^z*=>YnuHq~EB^8R% z@$Gb$(h@Ae3?;xP=uVoUqLiK_cp^kIv`AC(l5=&ivMtQ>0fDN&=!B+3id8n1qc7UA zBqP%G367)$;gUMLP?sFXC1eW3CvcFYPGg@OMD*~m3NJN8N7R^R-?(y0VGri3i31oZC;t$>VZas>lNYJvch3h2;B(A zD%!%b(qY;PKSji$NnoO4(v+1CH_6p93RTJlR#;&$er%Be0tR4!4D!FJd2Er<0vW2I zArbJuF$n;w29v1#r6lCGM&#*K_y#Wm5Cmm;`Pnw8RYU#IsPZ*Pj<)fz`agSncYX|a z?7QLMV^ddex7RK$>Ykwbbo*_8edxroljE_iwclvo|7t(0p60)6!Ygm};ExuJdE;^8 zyBc=I{&A}}`anIHAg6QlB<(mbX36M(F6-Bg`Fr8|S^dXvS+Mu3+=UzT4p6K(l&Dlc zX|)=4{t|GrA{T4NXh*+IeD?B|wCBj-CwJXe_ku%fKIUu5ja{5;7D9D7m zb~qhtv8&XGGRsHc*U(Z<3iB2s5am6-;D^k z8&&Ou9&LK@;T@H|*RDJ~YERwX@%Jye&6IB0y#6Nrx+8CL+DUYau;GLeV|(W^xs$H;jxRQ?+3@jui3gFyb#jXyUpr4y=8CtZDm$hc>nT`!o2KO6{rg zXTSbHTx#91HSgQ)UsjgCef067KkupCw1{t7eqhn>_??}-Fa6C28ejbI>8UmKyZfJi z{h9JLo4;PZy!7k$x+g9_w|M@G(tRhbFL2+gDkn!2u zKdgc>s=H;7-66khK>Jl0R?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}y("TestAbilityContext",this.context) + this.onCreate1(); + } + + async onCreate1() { + console.log("[ttt] [DataShareTest] DataShareExtAbility onCreate this.context.databaseDir:" + this.context.databaseDir); + let rdbStore = await rdb.getRdbStore(this.context.getApplicationContext(), STORE_CONFIG); + await rdbStore.executeSql(DROP_TBL, []); + await rdbStore.executeSql(DDL_TBL_CREATE, []); + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/pages/Index.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/pages/Index.ets new file mode 100644 index 00000000..722c2e9c --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,364 @@ +import { + connectDataShareExtAbility001, + disconnectDataShareExtAbility, + onRdb, + offRdb, + queryTest, + insertTest, + updateTest, + deleteTest, + offPublishData, + onPublishData, + getPublishedData, + onPublishData3, + publishTest, + publishTest2, + publishTest3 +} from './myServer.test' + +@Entry +@Component +struct Index { + @State message: string = "Main thread message filed" + + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('DataShareServer Ability Test') + .fontSize(20) + .fontWeight(FontWeight.Bold) + + Text(`${this.message}`) + .fontSize(25) + .height('15%') + .width('100%') + .textAlign(TextAlign.Center) + + Row() { + Button() { + Text('Connect') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Connect onclick enter') + this.message = 'Connect onclick' + await connectDataShareExtAbility001() + console.info('[ttt] [DataShareServerTest] <> Connect onclick leave') + }) + + Button() { + Text('Disconnect') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Disconnect onclick enter') + this.message = 'Disconnect onclick' + await disconnectDataShareExtAbility() + console.info('[ttt] [DataShareServerTest] <> Disconnect onclick leave') + }) + } + + Row() { + Button() { + Text('On') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> On onclick enter') + this.message = '~ On onclick' + try { + await onRdb(); + } catch (err) { + console.error('[ttt] [DataAbilityTest] Observer on catch(err)====>:' + err); + } + console.info('[ttt] [DataShareServerTest] <> On onclick leave') + }) + + Button() { + Text('Off') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Off onclick enter') + this.message = '~ Off onclick' + try { + await offRdb(); + } catch (err) { + console.error('[ttt] [DataAbilityTest] Observer Off catch(err)====>:' + err); + } + console.info('[ttt] [DataShareServerTest] <> Off onclick leave') + }) + + } + + Row() { + Button() { + Text('Query') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Query onclick enter') + this.message = 'Query onclick' + let ret = await queryTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> Query onclick leave') + }) + + Button() { + Text('Insert') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Insert onclick enter') + this.message = 'Insert onclick' + let ret = await insertTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> Insert onclick leave') + }) + } + + Row() { + Button() { + Text('Update') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Update onclick enter') + this.message = 'Update onclick' + let ret = await updateTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> Update onclick leave') + }) + + Button() { + Text('Delete') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Delete onclick enter') + this.message = 'Delete onclick' + let ret = await deleteTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> Delete onclick leave') + }) + } + + Row() { + Button() { + Text('OffPublishData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> OffPublishData onclick enter') + this.message = 'OffPublishData onclick' + await offPublishData() + console.info('[ttt] [DataShareServerTest] <> OffPublishData onclick leave') + }) + + Button() { + Text('OnPublishData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> OnPublishData onclick enter') + this.message = 'OnPublishData onclick' + await onPublishData() + console.info('[ttt] [DataShareServerTest] <> OnPublishData onclick leave') + }) + } + + Row() { + Button() { + Text('getPublishedData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> getPublishedData onclick enter') + this.message = 'getPublishedData onclick' + let ret = await getPublishedData() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> getPublishedData onclick leave') + }) + + Button() { + Text('OnPublishData3') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> OnPublishData3 onclick enter') + this.message = 'OnPublishData3 onclick' + await onPublishData3() + console.info('[ttt] [DataShareServerTest] <> OnPublishData3 onclick leave') + }) + } + + Row() { + Button() { + Text('Publish') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> publish onclick enter') + this.message = 'publish onclick' + let ret = await publishTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> publish onclick leave') + }) + + + Button() { + Text('GetFileTypes') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> GetFileTypes onclick enter') + this.message = 'GetFileTypes onclick' + // let ret = await globalThis.getFileTypes() + // this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> GetFileTypes onclick leave') + }) + } + + Row() { + Button() { + Text('Publish2.0') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Publish2.0 onclick enter') + this.message = 'Publish2.0 onclick' + let ret = await publishTest2() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> Publish2.0 onclick leave') + }) + + + Button() { + Text('Publish3.0') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareServerTest] <> Publish3.0 onclick enter') + this.message = 'Publish3.0 onclick' + let ret = await publishTest3() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareServerTest] <> Publish3.0 onclick leave') + }) + } + + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/pages/myServer.test.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/pages/myServer.test.ets new file mode 100644 index 00000000..5ccb02ce --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/ets/pages/myServer.test.ets @@ -0,0 +1,375 @@ +import dataShare from '@ohos.data.dataShare' +import dataSharePredicates from '@ohos.data.dataSharePredicates' +import { BusinessError } from '@ohos.base'; +import { ValuesBucket } from '@ohos.data.ValuesBucket'; +import rpc from '@ohos.rpc'; +import common from "@ohos.app.ability.common" + +let cardUri = ("datashareproxy://com.acts.ohos.data.datasharetest/test"); +let dsProxyHelper: dataShare.DataShareHelper | undefined = undefined +let dsProxyHelper1:dataShare.DataShareHelper; +let context: common.UIAbilityContext +context = AppStorage.get("TestAbilityContext") as common.UIAbilityContext + +export async function connectDataShareExtAbility001() { + console.log("[ttt] [DataShareServerTest] <> connectDataShareExtAbility begin "); + try{ + dsProxyHelper = await dataShare.createDataShareHelper(context, cardUri, {isProxy : true}); + // dsProxyHelper1 = await dataShare.createDataShareHelper(context, cardUri, {isProxy : true}); + console.log("[ttt] [DataShareServerTest] <> dsProxyHelper " + JSON.stringify(dsProxyHelper)); + } catch (e) { + console.log("[ttt] [DataShareServerTest] createDataShareHelper failed :" + e); + } +} + +export async function disconnectDataShareExtAbility() { + console.log("[ttt] [DataShareServerTest] <> disconnectDataShareExtAbility begin"); + dsProxyHelper = undefined; + console.log("[ttt] [DataShareServerTest] <> disconnectDataShareExtAbility end"); +} + +export async function onRdb() { + console.log("[ttt] [DataShareServerTest] <> on begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> on end, DSHelper is null"); + return; + } + let template: dataShare.Template = { + predicates : { + "p1" : "select name0 as name from TBL00", + "p2" : "select name1 as name from TBL00", + }, + scheduler : "select remindTimer(strftime('%s', 'now', '+30 seconds')) from TBL00" + } + dsProxyHelper.addTemplate(cardUri, "111", template); + let templateId:dataShare.TemplateId = {subscriberId:"111", bundleNameOfOwner:"com.acts.ohos.data.datasharetest"} + let result:Array = dsProxyHelper.on("rdbDataChange", [cardUri], templateId, onCallback); + console.log("[ttt] [DataShareServerTest] <> on end " + JSON.stringify(result)); +} + +export function onCallback(err:BusinessError, node:dataShare.RdbDataChangeNode) { + console.info("[ttt] [callback] rdb change ININ"); + // console.info("[ttt][callback] " + JSON.stringify(node.uri)); + // console.info("[ttt][callback] " + JSON.stringify(node.templateId)); + // console.info("[ttt][callback] " + node.data.length); + for (let i = 0; i < node.data.length; i++) { + // console.info("[ttt][callback] " + typeof node.data[i]); + console.info("[ttt][callback] " + node.data[i]); + } +} + +export async function offRdb() { + console.log("[ttt] [DataShareServerTest] <> off begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> off end, DSHelper is null"); + return; + } + let templateId:dataShare.TemplateId = {subscriberId:"111", bundleNameOfOwner:"com.acts.ohos.data.datasharetest"} + let result:Array = dsProxyHelper.off("rdbDataChange", [cardUri], templateId); + console.log("[ttt] [DataShareServerTest] <> off end " + JSON.stringify(result)); +} + +export async function queryTest() { + console.log("[ttt] [DataShareServerTest] <> query begin"); + let da = new dataSharePredicates.DataSharePredicates(); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareServerTest] <> da is null or undefined"); + return; + } + let count = 0; + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> query end, DSHelper is null"); + return; + } + let result = await dsProxyHelper.query(cardUri, da, ["*"]); + if (result != undefined) { + count = result.rowCount; + console.log("[ttt] [DataShareServerTest] <> hanlu query end, result:" + JSON.stringify(result)); + } + console.log("[ttt] [DataShareServerTest] <> query end, count222:" + count); + return count; +} + +export async function insertTest() { + console.log("[ttt] [DataShareServerTest] <> insert begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> insert end, DSHelper is null"); + return; + } + let i = 0; + let ret = 0; + for (i = 0; i < 20; i++) { + let vb: ValuesBucket = { + "name0": "name0" + i, + "name1": "name1" + i, + "name2": "name2" + i, + "name3": "name3" + i, + "name4": "name4" + i, + "name5": "name5" + i, + "name6": "name6" + i, + "name7": "name7" + i, + "name8": "name8" + i, + "name9": "name9" + i, + }; + await dsProxyHelper.insert(cardUri, vb).then((number)=>{ + ret =number; + }).catch((err: BusinessError) => { + console.error(`[ttt] insert error: code: ${err.code}, message: ${err.message} `); + }); + console.log("[ttt] [DataShareServerTest] <> insert ret is " + ret); + console.log("[ttt] [DataShareServerTest] <> insert end " + cardUri); + } + return ret; +} + +export async function updateTest() { + console.log("[ttt] [DataShareServerTest] <> update begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> update end, DSHelper is null"); + return; + } + console.log("[ttt] [DataShareServerTest] <> update begin RPF666"); + let da = new dataSharePredicates.DataSharePredicates(); + console.log("[ttt] [DataShareServerTest] <> update begin RPF777"); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareServerTest] <> da is null or undefined"); + return; + } + let ret = dsProxyHelper.update(cardUri, da, { "name0": "ZhangSan" }); + console.log("[ttt] [DataShareServerTest] <> update end, result:" + ret); + return ret; +} + +export async function deleteTest() { + console.log("[ttt] [DataShareServerTest] <> delete begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> delete end, DSHelper is null"); + return; + } + let da = new dataSharePredicates.DataSharePredicates(); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareServerTest] <> da is null or undefined"); + return; + } + let ret = await dsProxyHelper.delete(cardUri, da); + console.log("[ttt] [DataShareServerTest] <> delete end, result:" + ret); + return ret; +} + +export async function offPublishData() { + console.log("[ttt] [DataShareServerTest] <> offPublishData begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> on end, DSHelper is null"); + return; + } + + try{ + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/test", "key2"]; + let result: Array = dsProxyHelper.off("publishedDataChange", + uris, + "11", onPublishCallback); + console.log("[ttt] [DataShareServerTest] <> off end " + JSON.stringify(result)); + }catch(err){ + console.error(` [ttt] offPublishData error: code: ${err.code}, message: ${err.message} `); + } +} + +export function onPublishCallback(err:BusinessError, node:dataShare.PublishedDataChangeNode) { + console.info("[ttt] [serverCallback] published change ININ"); + console.info("[ttt][serverCallback] bundleName " + JSON.stringify(node.bundleName)); + console.info("[ttt][serverCallback] data size" + node.data.length); + for (let i = 0; i < node.data.length; i++) { + console.info("[ttt][serverCallback] " + typeof node.data[i].data); + // if (typeof node.data[i].data != 'string') { + // let ash:rpc.Ashmem = node.data[i].data; + // ash.mapReadonlyAshmem(); + // console.info("[ttt][serverCallback] " + JSON.stringify(ash.readAshmem(ash.getAshmemSize()/4, 0))); + // + // } + console.info("[ttt][serverCallback] data " + i + " " + JSON.stringify(node.data[i])); + } +} + +export async function onPublishData() { + console.log("[ttt] [DataShareServerTest] <> onPublishData begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> on end, DSHelper is null"); + return; + } + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", "datashareproxy://com.acts.ohos.data.datasharetest/test"]; + try { + console.log("[ttt] [DataShareServerTest] <> on begin"); + let result: Array = dsProxyHelper.on("publishedDataChange", uris, "11", onPublishCallback); + console.log("[ttt] [DataShareServerTest] <> on end " + JSON.stringify(result)); + // return result.length; + } catch (e) { + console.log("[ttt] [DataShareServerTest] <> on err " + JSON.stringify(e)); + + } +} + +export async function getPublishedData() { + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> getPublishedData end, DSHelper is null"); + return; + } + console.log("[ttt] [DataShareServerTest] <> getPublishedData begin"); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + let ret = publishedData.length; + console.log("[ttt] [DataShareServerTest] <> getPublishedData end dataSize is " + ret); + console.log("[ttt] [DataShareServerTest] <> getPublishedData end data is " + JSON.stringify(publishedData)); + return ret; +} + +export async function onPublishData3() { + console.log("[ttt] [DataShareServerTest] <> onPublishData3 begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> on end, DSHelper is null"); + return; + } + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", "datashareproxy://com.acts.ohos.data.datasharetest/test"]; + try { + console.log("[ttt] [DataShareServerTest] <> on begin"); + let result: Array = dsProxyHelper1.on("publishedDataChange", uris, "11", onPublishCallback3); + console.log("[ttt] [DataShareServerTest] <> on end " + JSON.stringify(result)); + // return result.length; + } catch (e) { + console.log("[ttt] [DataShareServerTest] <> on err " + JSON.stringify(e)); + + } +} + +export function onPublishCallback3(err:BusinessError, node:dataShare.PublishedDataChangeNode) { + console.info("[ttt] [callback] server published change ININ 3333"); + console.info("[ttt][callback] bundleName 3333" + JSON.stringify(node.bundleName)); + console.info("[ttt][callback] data size" + node.data.length); + for (let i = 0; i < node.data.length; i++) { + console.info("[ttt][callback] " + typeof node.data[i].data); + // if (typeof node.data[i].data != 'string') { + // let ash:rpc.Ashmem = node.data[i].data; + // ash.mapReadonlyAshmem(); + // console.info("[ttt][callback] " + JSON.stringify(ash.readAshmem(ash.getAshmemSize()/4, 0))); + // + // } + console.info("[ttt][callback] data " + i + " " + JSON.stringify(node.data[i])); + } + +} + +export async function publishTest() { + console.log("[ttt] [DataShareServerTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key:"city", subscriberId:"11", data:"xianServer"+Math.random()}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key:"empty", subscriberId:"11", data:"nobody sub Server"+Math.random()}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub Server"+Math.random()}]; + console.log("[ttt] [DataShareServerTest] <> publish begin"); + + let nums:number[] = [1,2,3]; + try { + let ashmem = rpc.Ashmem.create("ashmem", (nums.length) * 4); + console.log("[ttt] [DataShareServerTest] <> hanlu222 " + JSON.stringify(ashmem)); + ashmem.mapReadWriteAshmem(); + console.log("[ttt] [DataShareServerTest] <> hanlu333"); + //nums.fill(6, 0 ,1024); + console.log("[ttt] [DataShareServerTest] <> hanlu444 " + JSON.stringify(nums)); + ashmem.writeAshmem(nums, nums.length, 0); + console.log("[ttt] [DataShareServerTest] <> hanlu555"); + // data.push({ + // "key" : "key2", + // "data" : ashmem, + // "subscriberId" : "11", + // }); + console.log("[ttt] [DataShareServerTest] <> datasss length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest"); + console.log("[ttt] [DataShareServerTest] <> publish end " + JSON.stringify(result)); + ashmem.closeAshmem(); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareServerTest] <> getPublishedData end " + JSON.stringify(publishedData)); + // for (let i = 0; i < publishedData.length; i++) { + // console.info("[ttt][callback] " + typeof publishedData[i].data); + // if (typeof publishedData[i].data != 'string') { + // let ash:rpc.Ashmem = publishedData[i].data; + // ash.mapReadonlyAshmem(); + // console.info("[ttt][callback] " + JSON.stringify(ash.readAshmem(ash.getAshmemSize()/4, 0))); + // ash.closeAshmem(); + // } + // } + } catch (e) { + console.log("[ttt] [DataShareServerTest] <> publish error " + JSON.stringify(e)); + } +} + +export async function publishTest2() { + console.log("[ttt] [DataShareServerTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key:"city", subscriberId:"11", data:"xianServer22222"}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key:"empty", subscriberId:"11", data:"nobody sub Server"+222222}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub Server"+Math.random()}]; + console.log("[ttt] [DataShareServerTest] <> publish begin"); + + let nums:number[] = [1,2,3]; + try { + let ashmem = rpc.Ashmem.create("ashmem", (nums.length) * 4); + console.log("[ttt] [DataShareServerTest] <> hanlu222 " + JSON.stringify(ashmem)); + ashmem.mapReadWriteAshmem(); + console.log("[ttt] [DataShareServerTest] <> hanlu333"); + //nums.fill(6, 0 ,1024); + console.log("[ttt] [DataShareServerTest] <> hanlu444 " + JSON.stringify(nums)); + ashmem.writeAshmem(nums, nums.length, 0); + console.log("[ttt] [DataShareServerTest] <> hanlu555"); + + console.log("[ttt] [DataShareServerTest] <> datasss length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest",2); + console.log("[ttt] [DataShareServerTest] <> publish end " + JSON.stringify(result)); + ashmem.closeAshmem(); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareServerTest] <> getPublishedData end " + JSON.stringify(publishedData)); + } catch (e) { + console.log("[ttt] [DataShareServerTest] <> publish error " + JSON.stringify(e)); + } +} + +export async function publishTest3() { + console.log("[ttt] [DataShareServerTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareServerTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key:"city", subscriberId:"11", data:"xianServer3333333"}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key:"empty", subscriberId:"11", data:"nobody sub Server"+33333}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub Server"+Math.random()}]; + console.log("[ttt] [DataShareServerTest] <> publish begin"); + + let nums:number[] = [1,2,3]; + try { + let ashmem = rpc.Ashmem.create("ashmem", (nums.length) * 4); + console.log("[ttt] [DataShareServerTest] <> hanlu222 " + JSON.stringify(ashmem)); + ashmem.mapReadWriteAshmem(); + console.log("[ttt] [DataShareServerTest] <> hanlu333"); + //nums.fill(6, 0 ,1024); + console.log("[ttt] [DataShareServerTest] <> hanlu444 " + JSON.stringify(nums)); + ashmem.writeAshmem(nums, nums.length, 0); + console.log("[ttt] [DataShareServerTest] <> hanlu555"); + + console.log("[ttt] [DataShareServerTest] <> datasss length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest",3); + console.log("[ttt] [DataShareServerTest] <> publish end " + JSON.stringify(result)); + ashmem.closeAshmem(); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareServerTest] <> getPublishedData end " + JSON.stringify(publishedData)); + } catch (e) { + console.log("[ttt] [DataShareServerTest] <> publish error " + JSON.stringify(e)); + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/module.json5 b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/module.json5 new file mode 100644 index 00000000..9fda8320 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/module.json5 @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ + { + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:icon", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.GET_BUNDLE_INFO" + } + ], + "extensionAbilities": [ + { + "srcEntrance": "./ets/DataShareExtAbility/DataShareExtAbility.ts", + "name": "DataShareExtAbility", + "icon": "$media:icon", + "type": "dataShare", +// "readPermission": "ohos.permission.GET_BUNDLE_INFO", +// "writePermission": "ohos.permission.GET_BUNDLE_INFO", + "uri": "datashareproxy://com.acts.ohos.data.datasharetest/test", + "exported": true, + } + ], + + "proxyData":[ + { + "uri": "datashareproxy://com.acts.ohos.data.datasharetest/test", + "requiredReadPermission":"ohos.permission.GET_BUNDLE_INFO_PRIVILEGED", + "requiredWritePermission":"ohos.permission.GET_BUNDLE_INFO_PRIVILEGED", + "metadata": { + "name": "dataProperties", + "resource": "$profile:test" + } + } + ] + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/element/color.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/element/color.json new file mode 100644 index 00000000..82f853ff --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/element/string.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/element/string.json new file mode 100644 index 00000000..7ff16944 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/media/icon.png b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 zcmX|G1ymHk)?T_}Vd;>R?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}yR?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}y { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/test/List.test.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 00000000..5be61a34 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,5 @@ +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testability/TestAbility.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testability/TestAbility.ets new file mode 100644 index 00000000..9484761c --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testability/TestAbility.ets @@ -0,0 +1,50 @@ +import UIAbility from '@ohos.app.ability.UIAbility'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import hilog from '@ohos.hilog'; +import { Hypium } from '@ohos/hypium'; +import testsuite from '../test/List.test'; +import window from '@ohos.window'; +import Want from '@ohos.app.ability.Want'; +import AbilityConstant from '@ohos.app.ability.AbilityConstant'; + +export default class TestAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate'); + hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? ''); + hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? ''); + let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator; + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs; + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments(); + hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!'); + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite); + } + + onDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage) { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate'); + windowStage.loadContent('testability/pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', + JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); + } + + onForeground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); + } + + onBackground() { + hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testability/pages/Index.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testability/pages/Index.ets new file mode 100644 index 00000000..24774323 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testability/pages/Index.ets @@ -0,0 +1,17 @@ +@Entry +@Component +struct Index { + @State message: string = 'Hello World'; + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets new file mode 100644 index 00000000..917d27a5 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets @@ -0,0 +1,47 @@ +import hilog from '@ohos.hilog'; +import TestRunner from '@ohos.application.testRunner'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import Want from '@ohos.app.ability.Want'; + +let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator | undefined = undefined +let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs | undefined = undefined + +async function onAbilityCreateCallback() { + hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err : Error) { + hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? ''); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare '); + } + + async onRun() { + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run'); + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + const bundleName = abilityDelegatorArguments.bundleName; + const testAbilityName = 'TestAbility'; + let lMonitor: AbilityDelegatorRegistry.AbilityMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + const want: Want = { + bundleName: bundleName, + abilityName: testAbilityName + }; + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + abilityDelegator.startAbility(want, (err, data) => { + hilog.info(0x0000, 'testTag', 'startAbility : err : %{public}s', JSON.stringify(err) ?? ''); + hilog.info(0x0000, 'testTag', 'startAbility : data : %{public}s',JSON.stringify(data) ?? ''); + }) + hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end'); + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/module.json5 b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/module.json5 new file mode 100644 index 00000000..1634e9b5 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/module.json5 @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ + { + "module": { + "name": "entry_test", + "type": "feature", + "description": "$string:module_test_desc", + "mainElement": "TestAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:test_pages", + "abilities": [ + { + "name": "TestAbility", + "srcEntry": "./ets/testability/TestAbility.ets", + "description": "$string:TestAbility_desc", + "icon": "$media:icon", + "label": "$string:TestAbility_label", + "exported": true, + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:start_window_background", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ] + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/element/color.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/element/color.json new file mode 100644 index 00000000..82f853ff --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/element/string.json b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/element/string.json new file mode 100644 index 00000000..039de6a7 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_test_desc", + "value": "test ability description" + }, + { + "name": "TestAbility_desc", + "value": "the test ability" + }, + { + "name": "TestAbility_label", + "value": "test label" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/media/icon.png b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/entry/src/ohosTest/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 zcmX|G1ymHk)?T_}Vd;>R?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}y { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/hvigor/hvigor-config.json5 b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/hvigor/hvigor-config.json5 new file mode 100644 index 00000000..64952637 --- /dev/null +++ b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/hvigor/hvigor-config.json5 @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ + { + "modelVersion": "5.0.0", + "dependencies": { + "@ohos/hvigor-ohos-online-sign-plugin": "4.0.1", + }, + "execution": { + // "daemon": true, /* Enable daemon compilation. Default: true */ + // "incremental": true, /* Enable incremental compilation. Default: true */ + // "parallel": true, /* Enable parallel compilation. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Default: false */ + } +} diff --git a/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/sign/openharmony_sx.p7b b/data_share/test/native/resource/concurrency_scenario_bundle/DataShareService/sign/openharmony_sx.p7b new file mode 100644 index 0000000000000000000000000000000000000000..4512fc0e7c36f20aa275736dce5631c304a80dc0 GIT binary patch literal 3629 zcmcgvdvFtV9&a9Pt)&kw0`?S2K#D@jZ_}hrs-nBe<^`K{L((>-T-j_k$+nx_ZFbX5 zgFFn%i3q;6hk)f(;4J8XShzXyb%Nk2qjJoR2Y85`Qx5e!QBg*`-Lyc<=pT+VPG_hBRX{iWlA7egvf40RNASEpObcRy4kbk; zK@;K zhhXS1Eq3YZ7U)<`)Q6}Dmyp+mOctZL#$+&=r)Tvg~vh0}FI86+r% zA_PiaERp2&b$UraCExTN%_%c3?Usb z6hN&h4EI+fOsG8;BjZqKh;5HHI2vLtY{-wcVOBKj1*b6LN-w+#kwOlpE!gDaLk43M z2dLzXkshoKm9RFrOU}XXN_qWQs!`T@Z0#wm4NG0pwILja3z8Mj=IB5rx6R*%1~9}m zm{$y&-NIh6XUgG+n+EF?{3vRXnj1~7V3S)68B8XZ-NytQL28x_jt}}^{ub5=uJA(b z66r|sL4zF-axYwVHxrWUB@F?o(GUBPC^^(!7ov2!g&piQh9Hv13d8s5*87hu|U8AP&4BK{-$6v z>xoA(NZ>k?Aqww+{T$?y0ya3JWbT}Up$;3|7)AV{Sc0TmSi2aQ%>|Ox)pHtZlM&P& zAzY#_4STcRxEX;XW)y)jD`JEtr_xa$@FGYMwbzTOL^8&-u%r*c1$S5?n>%JFEu1IN z5G62Ja#*b$jyagoB1hX09JUcKEH&e<6zmoWP>&mUqs^6^!3!W> zVyt(>5C)5eX+t_`Y!$M!SF1LmuzpaUtJBSsjq=%#(}KcpS)YWwPl6^z*=>YnuHq~EB^8R% z@$Gb$(h@Ae3?;xP=uVoUqLiK_cp^kIv`AC(l5=&ivMtQ>0fDN&=!B+3id8n1qc7UA zBqP%G367)$;gUMLP?sFXC1eW3CvcFYPGg@OMD*~m3NJN8N7R^R-?(y0VGri3i31oZC;t$>VZas>lNYJvch3h2;B(A zD%!%b(qY;PKSji$NnoO4(v+1CH_6p93RTJlR#;&$er%Be0tR4!4D!FJd2Er<0vW2I zArbJuF$n;w29v1#r6lCGM&#*K_y#Wm5Cmm;`Pnw8RYU#IsPZ*Pj<)fz`agSncYX|a z?7QLMV^ddex7RK$>Ykwbbo*_8edxroljE_iwclvo|7t(0p60)6!Ygm};ExuJdE;^8 zyBc=I{&A}}`anIHAg6QlB<(mbX36M(F6-Bg`Fr8|S^dXvS+Mu3+=UzT4p6K(l&Dlc zX|)=4{t|GrA{T4NXh*+IeD?B|wCBj-CwJXe_ku%fKIUu5ja{5;7D9D7m zb~qhtv8&XGGRsHc*U(Z<3iB2s5am6-;D^k z8&&Ou9&LK@;T@H|*RDJ~YERwX@%Jye&6IB0y#6Nrx+8CL+DUYau;GLeV|(W^xs$H;jxRQ?+3@jui3gFyb#jXyUpr4y=8CtZDm$hc>nT`!o2KO6{rg zXTSbHTx#91HSgQ)UsjgCef067KkupCw1{t7eqhn>_??}-Fa6C28ejbI>8UmKyZfJi z{h9JLo4;PZy!7k$x+g9_w|M@G(tRhbFL2+gDkn!2u zKdgc>s=H;7-66khK>Jl0R?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}y("TestAbilityContext",this.context) + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + windowStage.loadContent('pages/Index', (err, data) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + }); + } + + onWindowStageDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/pages/Index.ets b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/pages/Index.ets new file mode 100644 index 00000000..1c307e1f --- /dev/null +++ b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,362 @@ +import { + connectDataShareExtAbility001, + disconnectDataShareExtAbility, + onRdb, + offRdb, + queryTest, + insertTest, + updateTest, + deleteTest, + offPublishData, + onPublishData, + getPublishedData, + publishTest, + publishTest2, + publishTest3, + offPublishDataErr1, + offPublishDataErr2, + enable, + disable +} from './myClient.test' + +@Entry +@Component +struct Index { + @State message: string = "Main thread message filed" + + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('DataShareClient1 Ability Test') + .fontSize(20) + .fontWeight(FontWeight.Bold) + + Text(`${this.message}`) + .fontSize(25) + .height('15%') + .width('100%') + .textAlign(TextAlign.Center) + + Row() { + Button() { + Text('Connect') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Connect onclick enter') + this.message = 'Connect onclick' + await connectDataShareExtAbility001() + console.info('[ttt] [DataShareClientTest] <> Connect onclick leave') + }) + + Button() { + Text('Disconnect') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Disconnect onclick enter') + this.message = 'Disconnect onclick' + await disconnectDataShareExtAbility() + console.info('[ttt] [DataShareClientTest] <> Disconnect onclick leave') + }) + } + + Row() { + Button() { + Text('On') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> On onclick enter') + this.message = '~ On onclick' + try { + await onRdb(); + } catch (err) { + console.error('[ttt] [DataAbilityTest] Observer on catch(err)====>:' + err); + } + console.info('[ttt] [DataShareClientTest] <> On onclick leave') + }) + + Button() { + Text('Off') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Off onclick enter') + this.message = '~ Off onclick' + try { + await offRdb(); + } catch (err) { + console.error('[ttt] [DataAbilityTest] Observer Off catch(err)====>:' + err); + } + console.info('[ttt] [DataShareClientTest] <> Off onclick leave') + }) + + } + + Row() { + Button() { + Text('Query') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Query onclick enter') + this.message = 'Query onclick' + let ret = await queryTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> Query onclick leave') + }) + + Button() { + Text('Insert') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Insert onclick enter') + this.message = 'Insert onclick' + let ret = await insertTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> Insert onclick leave') + }) + } + + Row() { + Button() { + Text('Update') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Update onclick enter') + this.message = 'Update onclick' + let ret = await updateTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> Update onclick leave') + }) + + Button() { + Text('Delete') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> Delete onclick enter') + this.message = 'Delete onclick' + let ret = await deleteTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> Delete onclick leave') + }) + } + + Row() { + Button() { + Text('OffPublishData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> OffPublishData onclick enter') + this.message = 'OffPublishData onclick' + await offPublishData() + console.info('[ttt] [DataShareClientTest] <> OffPublishData onclick leave') + }) + + Button() { + Text('OnPublishData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> OnPublishData onclick enter') + this.message = 'OnPublishData onclick' + await onPublishData() + console.info('[ttt] [DataShareClientTest] <> OnPublishData onclick leave') + }) + } + + Row() { + Button() { + Text('getPublishedData') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> getPublishedData onclick enter') + this.message = 'getPublishedData onclick' + let ret = await getPublishedData() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> getPublishedData onclick leave') + }) + + Button() { + Text('Publish') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> publish onclick enter') + this.message = 'publish onclick' + let ret = await publishTest() + this.message += "\n\n Test Result: " + ret; + console.info('[ttt] [DataShareClientTest] <> publish onclick leave') + }) + } + + Row() { + Button() { + Text('offPublishDataErr1') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> offPublishDataErr1 onclick enter') + this.message = 'offPublishDataErr1 onclick' + await offPublishDataErr1() + console.info('[ttt] [DataShareClientTest] <> offPublishDataErr1 onclick leave') + }) + + Button() { + Text('offPublishDataErr2') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> offPublishDataErr2 onclick enter') + this.message = 'offPublishDataErr2 onclick' + await offPublishDataErr2() + console.info('[ttt] [DataShareClientTest] <> offPublishDataErr2 onclick leave') + }) + } + + Row() { + Button() { + Text('enable') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> enable onclick enter') + this.message = 'offPublishDataErr1 onclick' + await enable() + console.info('[ttt] [DataShareClientTest] <> enable onclick leave') + }) + + Button() { + Text('disable') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 8 + }) + .width('45%') + .height('8%') + .backgroundColor('#0ddffb') + .onClick(async () => { + console.info('[ttt] [DataShareClientTest] <> disable onclick enter') + this.message = 'offPublishDataErr2 onclick' + await disable() + console.info('[ttt] [DataShareClientTest] <> disable onclick leave') + }) + } + + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/pages/myClient.test.ets b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/pages/myClient.test.ets new file mode 100644 index 00000000..690a654f --- /dev/null +++ b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/ets/pages/myClient.test.ets @@ -0,0 +1,396 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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 dataShare from '@ohos.data.dataShare' +import dataSharePredicates from '@ohos.data.dataSharePredicates' +import { BusinessError } from '@ohos.base'; +import { ValuesBucket } from '@ohos.data.ValuesBucket'; +import rpc from '@ohos.rpc'; +import common from "@ohos.app.ability.common" + +let cardUri = ("datashareproxy://com.acts.ohos.data.datasharetest/test"); +let dsProxyHelper: dataShare.DataShareHelper | undefined = undefined + + +let context: common.UIAbilityContext +context = AppStorage.get("TestAbilityContext") as common.UIAbilityContext + +export async function connectDataShareExtAbility001() { + try { + console.log("[ttt] [DataShareClientTest] <> connectDataShareExtAbility begin "); + dsProxyHelper = await dataShare.createDataShareHelper(context, cardUri, { isProxy: true }); + console.log("[ttt] [DataShareClientTest] <> dsProxyHelper " + JSON.stringify(dsProxyHelper)); + } + catch(err){ + console.error(` [ttt] createdatashare error: code: ${err.code}, message: ${err.message} `); + } +} + +export async function disconnectDataShareExtAbility() { + console.log("[ttt] [DataShareClientTest] <> disconnectDataShareExtAbility begin"); + dsProxyHelper = undefined; + console.log("[ttt] [DataShareClientTest] <> disconnectDataShareExtAbility end"); +} + +export async function enable() { + try { + + console.log("[ttt] [DataShareClientTest] <> enable begin"); + await dataShare.enableSilentProxy(context, cardUri); + console.log("[ttt] [DataShareClientTest] <> enable end"); + } + catch(err){ + console.error(` [ttt] enable error: code: ${err.code}, message: ${err.message} `); + } +} + +export async function disable() { + try { + console.log("[ttt] [DataShareClientTest] <> disable begin"); + await dataShare.disableSilentProxy(context, cardUri); + console.log("[ttt] [DataShareClientTest] <> disable end"); + } + catch(err){ + console.error(` [ttt] disable error: code: ${err.code}, message: ${err.message} `); + } +} + + +export async function onRdb() { + console.log("[ttt] [DataShareClientTest] <> on begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> on end, DSHelper is null"); + return; + } + let template: dataShare.Template = { + predicates: { + "p1": "select name0 as name from TBL00", + "p2": "select name1 as name from TBL00", + }, + scheduler: "select remindTimer(strftime('%s', 'now', '+10 seconds'))" + } + dsProxyHelper.addTemplate(cardUri, "111", template); + let templateId: dataShare.TemplateId = { + subscriberId: "111", bundleNameOfOwner: "com.acts.ohos.data.datasharetestclient" + } + let result: Array = dsProxyHelper.on("rdbDataChange", [cardUri], templateId, onCallback); + console.log("[ttt] [DataShareClientTest] <> on end " + JSON.stringify(result)); +} + +export function onCallback(err:BusinessError, node:dataShare.RdbDataChangeNode) { + console.info("[ttt] [DataShareClientTest] [callback] rdb change ININ"); + for (let i = 0; i < node.data.length; i++) { + // console.info("[ttt] [DataShareClientTest] [callback] " + typeof node.data[i]); + console.info("[ttt] [DataShareClientTest] [callback] " + node.data[i]); + } + +} + +export async function offRdb() { + console.log("[ttt] [DataShareClientTest] <> off begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> off end, DSHelper is null"); + return; + } + let templateId:dataShare.TemplateId = {subscriberId:"111", bundleNameOfOwner:"com.acts.ohos.data.datasharetestclient"} + let result:Array = dsProxyHelper.off("rdbDataChange", [cardUri], templateId); + console.log("[ttt] [DataShareClientTest] <> off end " + JSON.stringify(result)); +} + +export async function queryTest() { + console.log("[ttt] [DataShareClientTest] <> query begin"); + let da = new dataSharePredicates.DataSharePredicates(); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + let count = 0; + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> query end, DSHelper is null"); + return; + } + let result = await dsProxyHelper.query(cardUri, da, ["*"]); + if (result != undefined) { + count = result.rowCount; + console.log("[ttt] [DataShareClientTest] <> query end, result:" + JSON.stringify(result)); + result.close(); + } + console.log("[ttt] [DataShareClientTest] <> query end, count222:" + count); + return count; +} + +export async function queryTest2() { + console.log("[ttt] [DataShareClientTest] <> query begin"); + let da = new dataSharePredicates.DataSharePredicates(); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + let count = 0; + dsProxyHelper = await dataShare.createDataShareHelper(context, cardUri, {isProxy : true}); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> query end, DSHelper is null"); + return; + } + let result = await dsProxyHelper.query(cardUri, da, ["*"]); + if (result != undefined) { + count = result.rowCount; + console.log("[ttt] [DataShareClientTest] <> query end, result:" + JSON.stringify(result)); + result.close(); + } + console.log("[ttt] [DataShareClientTest] <> query end, count222:" + count); + return count; +} + +export async function insertTest() { + console.log("[ttt] [DataShareClientTest] <> insert begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> insert end, DSHelper is null"); + return; + } + + let i = 0; + let ret = 0; + for (i = 0; i < 2; i++) { + let vb: ValuesBucket = { + "name0": "name0" + i, + "name1": "name1" + i, + "name2": "name2" + i, + "name3": "name3" + i, + "name4": "name4" + i, + "name5": "name5" + i, + "name6": "name6" + i, + "name7": "name7" + i, + "name8": "name8" + i, + "name9": "name9" + i, + }; + ret = await dsProxyHelper.insert(cardUri, vb); + console.log("[ttt] [DataShareClientTest] <> insert end rowNum is " + ret); + } + return ret; +} + +export async function updateTest() { + console.log("[ttt] [DataShareClientTest] <> update begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> update end, DSHelper is null"); + return; + } + console.log("[ttt] [DataShareClientTest] <> update begin RPF666"); + let da = new dataSharePredicates.DataSharePredicates(); + console.log("[ttt] [DataShareClientTest] <> update begin RPF777"); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + let ret = dsProxyHelper.update(cardUri, da, { "name0": "ZhangSan" }); + console.log("[ttt] [DataShareClientTest] <> update end, result:" + ret); + return ret; +} + +export async function batchUpdate() { + console.log("[ttt] [DataShareClientTest] <> update begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> update end, DSHelper is null"); + return; + } + + console.log("[ttt] [DataShareClientTest] <> update begin RPF666"); + let da = new dataSharePredicates.DataSharePredicates(); + console.log("[ttt] [DataShareClientTest] <> update begin RPF777"); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } +} + +export async function deleteTest() { + console.log("[ttt] [DataShareClientTest] <> delete begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> delete end, DSHelper is null"); + return; + } + let da = new dataSharePredicates.DataSharePredicates(); + if (da == null || da == undefined) { + console.log("[ttt] [DataShareClientTest] <> da is null or undefined"); + return; + } + let ret = await dsProxyHelper.delete(cardUri, da); + console.log("[ttt] [DataShareClientTest] <> delete end, result:" + ret); + return ret; +} + +export async function offPublishData() { + console.log("[ttt] [DataShareClientTest] <> offPublishData begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> on end, DSHelper is null"); + return; + } + try{ + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", "datashareproxy://com.acts.ohos.data.datasharetest/test"]; + let result: Array = dsProxyHelper.off("publishedDataChange", + uris, + "11", onPublishCallback); + console.log("[ttt] [DataShareClientTest] <> off end " + JSON.stringify(result)); + }catch(err){ + console.error(` [ttt] offPublishData error: code: ${err.code}, message: ${err.message} `); + } +} + +export async function offPublishDataErr1() { + console.log("[ttt] [DataShareClientTest] <> offPublishDataErr1 begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> on end, DSHelper is null"); + return; + } + + try{ + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", "datashareproxy://com.acts.ohos.data.datasharetest/test"]; + let result: Array = dsProxyHelper.off("publishedDataChange", + uris, + "11", undefined); + console.log("[ttt] [DataShareClientTest] <> off end " + JSON.stringify(result)); + }catch(err){ + console.error(` [ttt] offPublishDataErr1 error: code: ${err.code}, message: ${err.message} `); + } +} + + +export async function offPublishDataErr2() { + console.log("[ttt] [DataShareClientTest] <> off begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> off end, DSHelper is null"); + return; + } + let templateId:dataShare.TemplateId = {subscriberId:"111", bundleNameOfOwner:"com.acts.ohos.data.datasharetestclient"} + try{ + let result:Array = dsProxyHelper.off("rdbDataChange", [cardUri], templateId,undefined); + console.log("[ttt] [DataShareClientTest] <> off end " + JSON.stringify(result)); + }catch(err){ + console.error(` [ttt] offPublishDataErr2 error: code: ${err.code}, message: ${err.message} `); + } +} + +export function onPublishCallback(err:BusinessError, node:dataShare.PublishedDataChangeNode) { + console.info("[ttt] [DataShareClientTest] [callback] publishedData change ININ"); + // console.info("[ttt] [DataShareClientTest] [callback] bundleName " + JSON.stringify(node.bundleName)); + console.info("[ttt] [DataShareClientTest] [callback] data size" + node.data.length); + for (let i = 0; i < node.data.length; i++) { + // console.info("[ttt] [DataShareClientTest] [callback]" + typeof node.data[i].data); + console.info("[ttt] [DataShareClientTest] [callback] data " + i + " " + JSON.stringify(node.data[i])); + } +} + +export async function onPublishData() { + console.log("[ttt] [DataShareClientTest] <> onPublishData begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> on end, DSHelper is null"); + return; + } + let uris:Array = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", "datashareproxy://com.acts.ohos.data.datasharetest/test"]; + try { + console.log("[ttt] [DataShareClientTest] <> on begin"); + let result: Array = dsProxyHelper.on("publishedDataChange", uris, "11", onPublishCallback); + console.log("[ttt] [DataShareClientTest] <> on end " + JSON.stringify(result)); + } catch (e) { + console.log("[ttt] [DataShareClientTest] <> on err " + JSON.stringify(e)); + + } +} + +export async function getPublishedData() { + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> getPublishedData end, DSHelper is null"); + return; + } + console.log("[ttt] [DataShareClientTest] <> getPublishedData begin"); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + let ret = publishedData.length; + console.log("[ttt] [DataShareClientTest] <> getPublishedData end dataSize is " + ret); + console.log("[ttt] [DataShareClientTest] <> getPublishedData end data is " + JSON.stringify(publishedData)); + return ret; +} + + +export async function publishTest() { + console.log("[ttt] [DataShareClientTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key: "city", subscriberId: "11", data: "xian" + Math.random()}, + {key: "datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key: "empty", subscriberId: "11", data: "nobody sub" + Math.random()}, + {key: "datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub " + Math.random()}]; + + let nums:number[] = [1,2,3]; + try { + console.log("[ttt] [DataShareClientTest] <> data length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest"); + console.log("[ttt] [DataShareClientTest] <> publish end " + JSON.stringify(result)); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareClientTest] <> getPublishedData end " + JSON.stringify(publishedData)); + } catch (e) { + console.log("[ttt] [DataShareClientTest] <> publish error " + JSON.stringify(e)); + } +} + +export async function publishTest2() { + console.log("[ttt] [DataShareClientTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key:"city", subscriberId:"11", data:"xianServer22222"}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key:"empty", subscriberId:"11", data:"nobody sub Server"+222222}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub Server"+Math.random()}]; + + let nums:number[] = [1,2,3]; + try { + console.log("[ttt] [DataShareClientTest] <> datasss length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest",2); + console.log("[ttt] [DataShareClientTest] <> publish end " + JSON.stringify(result)); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareClientTest] <> getPublishedData end " + JSON.stringify(publishedData)); + } catch (e) { + console.log("[ttt] [DataShareClientTest] <> publish error " + JSON.stringify(e)); + } +} + +export async function publishTest3() { + console.log("[ttt] [DataShareClientTest] <> publish begin"); + if (dsProxyHelper == null) { + console.log("[ttt] [DataShareClientTest] <> publish end, DSHelper is null"); + return; + } + let data : Array = [ + {key:"city", subscriberId:"11", data:"xianClient3333333"}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/appInfo", subscriberId:"11", data:"appinfo is just a test app"}, + {key:"empty", subscriberId:"11", data:"nobody sub Client"+33333}, + {key:"datashareproxy://com.acts.ohos.data.datasharetest/test", subscriberId:"11", data:"nobody sub Server"+Math.random()}]; + + try { + console.log("[ttt] [DataShareClientTest] <> datasss length is:", data.length); + let result: Array = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetest",3); + console.log("[ttt] [DataShareClientTest] <> publish end " + JSON.stringify(result)); + let publishedData:Array = await dsProxyHelper.getPublishedData("com.acts.ohos.data.datasharetest") + console.log("[ttt] [DataShareClientTest] <> getPublishedData end " + JSON.stringify(publishedData)); + } catch (e) { + console.log("[ttt] [DataShareClientTest] <> publish error " + JSON.stringify(e)); + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/module.json5 b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/module.json5 new file mode 100644 index 00000000..211c03c8 --- /dev/null +++ b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/module.json5 @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ + { + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:icon", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED" + } + ] + } +} diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/element/color.json b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/element/color.json new file mode 100644 index 00000000..82f853ff --- /dev/null +++ b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/element/string.json b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/element/string.json new file mode 100644 index 00000000..7ff16944 --- /dev/null +++ b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/media/icon.png b/data_share/test/native/resource/datashareclient_normal_bundle/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 zcmX|G1ymHk)?T_}Vd;>R?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}yR?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}y-T-j_k$+nx_ZFbX5 zgFFn%i3q;6hk)f(;4J8XShzXyb%Nk2qjJoR2Y85`Qx5e!QBg*`-Lyc<=pT+VPG_hBRX{iWlA7egvf40RNASEpObcRy4kbk; zK@;K zhhXS1Eq3YZ7U)<`)Q6}Dmyp+mOctZL#$+&=r)Tvg~vh0}FI86+r% zA_PiaERp2&b$UraCExTN%_%c3?Usb z6hN&h4EI+fOsG8;BjZqKh;5HHI2vLtY{-wcVOBKj1*b6LN-w+#kwOlpE!gDaLk43M z2dLzXkshoKm9RFrOU}XXN_qWQs!`T@Z0#wm4NG0pwILja3z8Mj=IB5rx6R*%1~9}m zm{$y&-NIh6XUgG+n+EF?{3vRXnj1~7V3S)68B8XZ-NytQL28x_jt}}^{ub5=uJA(b z66r|sL4zF-axYwVHxrWUB@F?o(GUBPC^^(!7ov2!g&piQh9Hv13d8s5*87hu|U8AP&4BK{-$6v z>xoA(NZ>k?Aqww+{T$?y0ya3JWbT}Up$;3|7)AV{Sc0TmSi2aQ%>|Ox)pHtZlM&P& zAzY#_4STcRxEX;XW)y)jD`JEtr_xa$@FGYMwbzTOL^8&-u%r*c1$S5?n>%JFEu1IN z5G62Ja#*b$jyagoB1hX09JUcKEH&e<6zmoWP>&mUqs^6^!3!W> zVyt(>5C)5eX+t_`Y!$M!SF1LmuzpaUtJBSsjq=%#(}KcpS)YWwPl6^z*=>YnuHq~EB^8R% z@$Gb$(h@Ae3?;xP=uVoUqLiK_cp^kIv`AC(l5=&ivMtQ>0fDN&=!B+3id8n1qc7UA zBqP%G367)$;gUMLP?sFXC1eW3CvcFYPGg@OMD*~m3NJN8N7R^R-?(y0VGri3i31oZC;t$>VZas>lNYJvch3h2;B(A zD%!%b(qY;PKSji$NnoO4(v+1CH_6p93RTJlR#;&$er%Be0tR4!4D!FJd2Er<0vW2I zArbJuF$n;w29v1#r6lCGM&#*K_y#Wm5Cmm;`Pnw8RYU#IsPZ*Pj<)fz`agSncYX|a z?7QLMV^ddex7RK$>Ykwbbo*_8edxroljE_iwclvo|7t(0p60)6!Ygm};ExuJdE;^8 zyBc=I{&A}}`anIHAg6QlB<(mbX36M(F6-Bg`Fr8|S^dXvS+Mu3+=UzT4p6K(l&Dlc zX|)=4{t|GrA{T4NXh*+IeD?B|wCBj-CwJXe_ku%fKIUu5ja{5;7D9D7m zb~qhtv8&XGGRsHc*U(Z<3iB2s5am6-;D^k z8&&Ou9&LK@;T@H|*RDJ~YERwX@%Jye&6IB0y#6Nrx+8CL+DUYau;GLeV|(W^xs$H;jxRQ?+3@jui3gFyb#jXyUpr4y=8CtZDm$hc>nT`!o2KO6{rg zXTSbHTx#91HSgQ)UsjgCef067KkupCw1{t7eqhn>_??}-Fa6C28ejbI>8UmKyZfJi z{h9JLo4;PZy!7k$x+g9_w|M@G(tRhbFL2+gDkn!2u zKdgc>s=H;7-66khK>Jl0 @@ -78,4 +81,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/corpus/init b/data_share/test/native/resource/ohos_test_new/BUILD.gn similarity index 69% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/corpus/init rename to data_share/test/native/resource/ohos_test_new/BUILD.gn index bc977bd9..42e1a956 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/corpus/init +++ b/data_share/test/native/resource/ohos_test_new/BUILD.gn @@ -11,4 +11,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -FUZZ \ No newline at end of file +import("//build/ohos.gni") + +ohos_copy("copy_ohos_test_new") { + sources = [ "./ohos_test_new.xml" ] + outputs = [ "$root_out_dir/tests/unittest/data_share/resource/ohos_test_new.xml" ] + + subsystem_name = "distributeddatamgr" + part_name = "data_share" +} \ No newline at end of file diff --git a/data_share/test/native/resource/ohos_test_new/ohos_test_new.xml b/data_share/test/native/resource/ohos_test_new/ohos_test_new.xml new file mode 100644 index 00000000..f1436c7f --- /dev/null +++ b/data_share/test/native/resource/ohos_test_new/ohos_test_new.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/AppScope/app.json5 b/data_share/test/native/resource/systemapp_verify_bundle/AppScope/app.json5 new file mode 100644 index 00000000..c347ece5 --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ +{ + "app": { + "bundleName": "com.acts.ohos.data.datasharetestclient1", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/data_share/test/native/resource/systemapp_verify_bundle/AppScope/resources/base/element/string.json b/data_share/test/native/resource/systemapp_verify_bundle/AppScope/resources/base/element/string.json new file mode 100644 index 00000000..1080233f --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "MyApplication" + } + ] +} diff --git a/data_share/test/native/resource/systemapp_verify_bundle/AppScope/resources/base/media/app_icon.png b/data_share/test/native/resource/systemapp_verify_bundle/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 zcmX|G1ymHk)?T_}Vd;>R?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}y = [ + { + title: titleName, + fileNameExtension: 'jpg', + photoType: photoAccessHelper.PhotoType.IMAGE, + subtype: photoAccessHelper.PhotoSubtype.DEFAULT, + } + ] + try { + let uris = await phAccessHelper.createAssetsForApp(bundleName, appName, appId, configs) + result = uris[0] + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + console.info('SystemCreateAssetForApp End') + return result + } + + async SystemCreateAssetForAppWithMode(titleName: string, appName: string, bundleName: string, appId: string, tokenId: number) { + console.info('SystemCreateAssetForAppWithMode Start') + let result: string | undefined + let configs: Array = [ + { + title: titleName, + fileNameExtension: 'jpg', + photoType: photoAccessHelper.PhotoType.IMAGE, + subtype: photoAccessHelper.PhotoSubtype.DEFAULT, + } + ] + try { + let mode = photoAccessHelper.AuthorizationMode.SHORT_TIME_AUTHORIZATION; + let uris = await phAccessHelper.createAssetsForAppWithMode(bundleName, appName, appId, tokenId, mode, configs) + result = uris[0] + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } + console.info('SystemCreateAssetForAppWithMode End') + return result + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/FileUtil.ets b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/FileUtil.ets new file mode 100644 index 00000000..2e9b779e --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/FileUtil.ets @@ -0,0 +1,27 @@ +import fs from '@ohos.file.fs'; + +export function ReadPhotoData(uri: string) { + console.info('ReadPhotoData:' + uri) + try { + let src = fs.openSync(uri, fs.OpenMode.READ_ONLY) + let data: ArrayBuffer = new ArrayBuffer(100) + fs.readSync(src.fd, data) + fs.closeSync(src) + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } +} + +export function CopyPhotoData(srcUri: string, dstUri: string) { + console.info('CopyPhotoData srcUri: ' + srcUri) + console.info(' => dstUri: ' + dstUri) + try { + let dst = fs.openSync(dstUri, fs.OpenMode.WRITE_ONLY) + let src = fs.openSync(srcUri, fs.OpenMode.READ_ONLY) + fs.copyFileSync(src.fd, dst.fd, 0) + fs.closeSync(src) + fs.closeSync(dst) + } catch (err) { + console.error(`error: ${err.code}, ${err.message}`) + } +} diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/entryability/EntryAbility.ets b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 00000000..c34fa296 --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,63 @@ +import { window } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { abilityAccessCtrl, AbilityConstant, Permissions, UIAbility, Want } from '@kit.AbilityKit'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + const permissions: Array = [ + 'ohos.permission.READ_IMAGEVIDEO','ohos.permission.WRITE_IMAGEVIDEO', + 'ohos.permission.READ_MEDIA','ohos.permission.WRITE_MEDIA', + 'ohos.permission.SHORT_TERM_WRITE_IMAGEVIDEO' + ]; + let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager(); + // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗 + atManager.requestPermissionsFromUser(this.context, permissions).then((data) => { + let grantStatus: Array = data.authResults; + let length: number = grantStatus.length; + for (let i = 0; i < length; i++) { + if (grantStatus[i] === 0) { + // 用户授权,可以继续访问目标操作 + } else { + // 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限 + return; + } + } + // 授权成功 + }).catch((err: BusinessError) => { + console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`); + }) + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 00000000..6995da57 --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,12 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class EntryBackupAbility extends BackupExtensionAbility { +async onBackup() { +hilog.info(0x0000, 'testTag', 'onBackup ok'); +} + +async onRestore(bundleVersion: BundleVersion) { +hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); +} +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/DataShare.ets b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/DataShare.ets new file mode 100644 index 00000000..5ac77d92 --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/DataShare.ets @@ -0,0 +1,60 @@ +import { BusinessError } from '@kit.BasicServicesKit'; +import dataShare from '@ohos.data.dataShare'; +import { dataSharePredicates, ValuesBucket } from '@kit.ArkData'; +import photoAccessHelper from '@ohos.file.photoAccessHelper'; + +let context = getContext(this); + +function DataShareDelete(operation: string, field: string, value: string) { + console.info('DataShareDelete Demo Start:' + operation + ',' + field + '=' + value); + let uri: string = 'datashare:///media/' + operation + '/delete?api_version=10'; + dataShare.createDataShareHelper(context, uri).then((helper: dataShare.DataShareHelper) => { + let predicates = new dataSharePredicates.DataSharePredicates(); + predicates.equalTo(field, value); + helper.delete(uri, predicates); + console.info('DataShareHelper.delete successfully'); + }).catch ((err: BusinessError) => { + console.error(`error: ${err.code}, ${err.message}`); + }) + console.info('DataShareDelete Demo End:'); +} + +function DataShareMove(assetUri: string, oldAlbumId: string, newAlbumId: number) { + console.info('DataShareMove Demo Start: ' + assetUri); + let uri: string = 'datashare:///media/phaccess_photo_operation/batch_update_owner_album_id?api_version=10'; + dataShare.createDataShareHelper(context, uri).then((helper: dataShare.DataShareHelper) => { + let values: ValuesBucket = {}; + let predicates = new dataSharePredicates.DataSharePredicates(); + predicates.equalTo('owner_album_id', oldAlbumId); + predicates.and().in('file_id', [assetUri]); + values['owner_album_id'] = newAlbumId; + helper.update(uri, predicates, values); + console.info('DataShareHelper.update successfully'); + }).catch ((err: BusinessError) => { + console.error(`error: ${err.code}, ${err.message}`); + }) + console.info('DataShareMove Demo End:'); +} + +@Entry +@Component +struct DataShare { + build() { + Row() { + Column() { + Text('DataShare').margin(6).fontWeight(FontWeight.Bold) + + Button("DataShareMoveAsset").margin(6).onClick(()=>{ + DataShareMove('', '11', 13); + }) + + Button('DataShareDeleteAlbum').margin(6).onClick(()=> { + DataShareDelete('phaccess_album_operation', photoAccessHelper.AlbumKeys.ALBUM_NAME, 'test1'); + DataShareDelete('photo_album_v10_operation', photoAccessHelper.AlbumKeys.ALBUM_NAME, 'test2'); + }) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/Index.ets b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/Index.ets new file mode 100644 index 00000000..86850263 --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,116 @@ +import { router } from '@kit.ArkUI' +import { AssetUtil } from '../AssetUtil' +import { CopyPhotoData, ReadPhotoData } from '../FileUtil' +import photoAccessHelper from '@ohos.file.photoAccessHelper' + +let assetUtil: AssetUtil = new AssetUtil() + +@Entry +@Component +struct Index { + build() { + Row() { + Column() { + Text('Public').margin(6).fontWeight(FontWeight.Bold) + + Button('System').margin(6).onClick(() => { + try { + router.pushUrl({ url: 'pages/SystemApi' }) + } catch (err) { + console.error(`failed to ${err.code} ${err.message}`); + } + }) + + Button('DataShare').margin(6).onClick(() => { + try { + router.pushUrl({ url: 'pages/DataShare' }) + } catch (err) { + console.error(`failed to ${err.code} ${err.message}`); + } + }) + + Button('ReadPhotoData').margin(6).onClick(async ()=> { + let uri = 'file://media/Photo/35/IMG_1742786685_034/sys_test3.jpg' + let result = await assetUtil.GetAssets(photoAccessHelper.PhotoKeys.URI, uri) + for (let i = 0; result && i < result.length; i++) { + console.info('GetAssets uri:' + result[i].uri + ' displayName:' + result[i].displayName) + } + ReadPhotoData(uri) + }) + + Button('PublicAssetTest').margin(6).onClick(async () => { + console.info('=======GetAssets All=======') + let result = await assetUtil.GetAssets(photoAccessHelper.PhotoKeys.TITLE, '') + if (!result || result.length <= 0) { + console.error('=======PublicAssetTest======= End') + return + } + + let uris: Array = new Array() + console.info('=======CreateAsset pub_test1=======') + let uri = await assetUtil.CreateAsset('pub_test1') + if (uri) { + uris.push(uri) + } + + console.info('=======CreateAsset pub_test2=======') + uri = await assetUtil.CreateAssetWithShortTermPermission('pub_test2') + if (uri) { + uris.push(uri) + } + + console.info('=======CopyPhotoData=======') + for (let i = 0; i < uris.length; i++) { + CopyPhotoData(result[0].uri, uris[i]) + } + + console.info('=======ReadPhotoData=======') + for (let i = 0; i < uris.length; i++) { + ReadPhotoData(uris[i]) + } + + console.info('=======GetAssets pub_%=======') + result = await assetUtil.GetAssets(photoAccessHelper.PhotoKeys.TITLE, 'pub_%') + for (let i = 0; result && i < result.length; i++) { + await assetUtil.CloneAsset(result[i]) + await assetUtil.ModifyAsset(result[i]) + } + + console.info('=======GetAssets clone_%=======') + result = await assetUtil.GetAssets(photoAccessHelper.PhotoKeys.TITLE, 'clone_%') + if (result) { + await assetUtil.DeleteAssets(result) + } + + console.info('=======GetAssets modify_%=======') + result = await assetUtil.GetAssets(photoAccessHelper.PhotoKeys.TITLE, 'modify_%') + if (result) { + await assetUtil.DeleteAssets(result) + } + + console.info('=======PublicAssetTest======= End') + }) + + Button('PublicAlbumTest').margin(6).onClick(async ()=> { + console.info('=======PublicAlbumTest======= GetAlbums USER_GENERIC') + let result = await assetUtil.GetAlbums(photoAccessHelper.AlbumType.USER, + photoAccessHelper.AlbumSubtype.USER_GENERIC) + for (let i = 0; result && i < result.length; i++) { + await assetUtil.RemoveAlbumAssets(result[i]) + } + + console.info('=======PublicAlbumTest======= GetAlbums TRASH') + result = await assetUtil.GetAlbums(photoAccessHelper.AlbumType.SYSTEM, + photoAccessHelper.AlbumSubtype.TRASH) + for (let i = 0; result && i < result.length; i++) { + console.info('albumName:' + result[i].albumName + ' albumUri:' + result[i].albumUri) + } + + console.info('=======PublicAssetTest======= End') + }) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/SystemApi.ets b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/SystemApi.ets new file mode 100644 index 00000000..f386007a --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/ets/pages/SystemApi.ets @@ -0,0 +1,88 @@ +import { AssetUtil } from '../AssetUtil' +import { CopyPhotoData, ReadPhotoData } from '../FileUtil' +import photoAccessHelper from '@ohos.file.photoAccessHelper' +let assetUtil: AssetUtil = new AssetUtil() + +@Entry +@Component +struct SystemApi { + build() { + Row() { + Column() { + Text('System').margin(6).fontWeight(FontWeight.Bold) + Button('SystemAssetTest').margin(6).onClick(async () => { + console.info('=======GetAssets All=======') + let result = await assetUtil.GetAssets(photoAccessHelper.PhotoKeys.TITLE, '') + if (!result || result.length <= 0) { + console.error('=======SystemAssetTest======= End') + return + } + + let uris: Array = new Array() + console.info('=======SystemCreateAsset sys_test1=======') + let uri = await assetUtil.SystemCreateAsset('sys_test1') + if (uri) { + uris.push(uri) + } + + console.info('=======SystemCreateAsset sys_test2=======') + uri = await assetUtil.SystemCreateAssetSubType('sys_test2', photoAccessHelper.PhotoSubtype.DEFAULT) + if (uri) { + uris.push(uri) + } + + console.info('=======SystemCreateAsset sys_test3=======') + uri = await assetUtil.SystemCreateAssetForApp('sys_test3', 'testAppName', 'testBundleName','testAppId') + if (uri) { + uris.push(uri) + } + + console.info('=======CopyPhotoData=======') + for (let i = 0; i < uris.length; i++) { + CopyPhotoData(result[0].uri, uris[i]) + } + + console.info('=======ReadPhotoData=======') + for (let i = 0; i < uris.length; i++) { + ReadPhotoData(uris[i]) + } + + console.info('=======GetAssets sys_%=======') + result = await assetUtil.GetAssets(photoAccessHelper.PhotoKeys.TITLE, 'sys_%') + for (let i = 0; result && i < result.length; i++) { + await assetUtil.SystemDeleteAsset(result[i]) + } + console.info('=======SystemAssetTest======= End') + }) + + Button('SystemAlbumTest').margin(6).onClick(async ()=> { + console.info('=======SystemRecoverAlbumAssets======= GetAlbums TRASH') + let result = await assetUtil.GetAlbums(photoAccessHelper.AlbumType.SYSTEM, + photoAccessHelper.AlbumSubtype.TRASH) + for (let i = 0; result && i < result.length; i++) { + await assetUtil.SystemRecoverAlbumAssets(result[i]) + } + console.info('=======SystemRecoverAlbumAssets======= END') + + console.info('=======SystemDeleteAlbum======= GetAlbums USER_GENERIC') + result = await assetUtil.GetAlbums(photoAccessHelper.AlbumType.USER, + photoAccessHelper.AlbumSubtype.USER_GENERIC) + for (let i = 0; result && i < result.length; i++) { + await assetUtil.SystemDeleteAlbum(i, result[i]) + } + console.info('=======SystemDeleteAlbum======= END') + + console.info('=======SystemDeleteAlbumAssets======= GetAlbums TRASH') + result = await assetUtil.GetAlbums(photoAccessHelper.AlbumType.SYSTEM, + photoAccessHelper.AlbumSubtype.TRASH) + for (let i = 0; result && i < result.length; i++) { + await assetUtil.SystemDeleteAlbumAssets(result[i]) + } + console.info('=======SystemDeleteAlbumAssets======= END') + }) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/module.json5 b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/module.json5 new file mode 100644 index 00000000..a0cf8c16 --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/module.json5 @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not \tuse 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. + */ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + + "requestPermissions": [ + { + "name" : "ohos.permission.READ_MEDIA", + "reason" : "$string:reason", + "usedScene": { + } + }, + { + "name" : "ohos.permission.WRITE_MEDIA", + "reason" : "$string:reason", + "usedScene": { + } + }, + { + "name" : "ohos.permission.READ_IMAGEVIDEO", + "reason" : "$string:reason", + "usedScene": { + } + }, + { + "name" : "ohos.permission.WRITE_IMAGEVIDEO", + "reason" : "$string:reason", + "usedScene": { + } + }, + { + "name" : "ohos.permission.SHORT_TERM_WRITE_IMAGEVIDEO", + "reason" : "$string:reason", + "usedScene": { + } + } + ], + + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ], + } + ] + } +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/element/color.json b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/element/color.json new file mode 100644 index 00000000..82f853ff --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/element/string.json b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/element/string.json new file mode 100644 index 00000000..7ff16944 --- /dev/null +++ b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + } + ] +} \ No newline at end of file diff --git a/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/media/icon.png b/data_share/test/native/resource/systemapp_verify_bundle/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 zcmX|G1ymHk)?T_}Vd;>R?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}yR?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}y-T-j_k$+nx_ZFbX5 zgFFn%i3q;6hk)f(;4J8XShzXyb%Nk2qjJoR2Y85`Qx5e!QBg*`-Lyc<=pT+VPG_hBRX{iWlA7egvf40RNASEpObcRy4kbk; zK@;K zhhXS1Eq3YZ7U)<`)Q6}Dmyp+mOctZL#$+&=r)Tvg~vh0}FI86+r% zA_PiaERp2&b$UraCExTN%_%c3?Usb z6hN&h4EI+fOsG8;BjZqKh;5HHI2vLtY{-wcVOBKj1*b6LN-w+#kwOlpE!gDaLk43M z2dLzXkshoKm9RFrOU}XXN_qWQs!`T@Z0#wm4NG0pwILja3z8Mj=IB5rx6R*%1~9}m zm{$y&-NIh6XUgG+n+EF?{3vRXnj1~7V3S)68B8XZ-NytQL28x_jt}}^{ub5=uJA(b z66r|sL4zF-axYwVHxrWUB@F?o(GUBPC^^(!7ov2!g&piQh9Hv13d8s5*87hu|U8AP&4BK{-$6v z>xoA(NZ>k?Aqww+{T$?y0ya3JWbT}Up$;3|7)AV{Sc0TmSi2aQ%>|Ox)pHtZlM&P& zAzY#_4STcRxEX;XW)y)jD`JEtr_xa$@FGYMwbzTOL^8&-u%r*c1$S5?n>%JFEu1IN z5G62Ja#*b$jyagoB1hX09JUcKEH&e<6zmoWP>&mUqs^6^!3!W> zVyt(>5C)5eX+t_`Y!$M!SF1LmuzpaUtJBSsjq=%#(}KcpS)YWwPl6^z*=>YnuHq~EB^8R% z@$Gb$(h@Ae3?;xP=uVoUqLiK_cp^kIv`AC(l5=&ivMtQ>0fDN&=!B+3id8n1qc7UA zBqP%G367)$;gUMLP?sFXC1eW3CvcFYPGg@OMD*~m3NJN8N7R^R-?(y0VGri3i31oZC;t$>VZas>lNYJvch3h2;B(A zD%!%b(qY;PKSji$NnoO4(v+1CH_6p93RTJlR#;&$er%Be0tR4!4D!FJd2Er<0vW2I zArbJuF$n;w29v1#r6lCGM&#*K_y#Wm5Cmm;`Pnw8RYU#IsPZ*Pj<)fz`agSncYX|a z?7QLMV^ddex7RK$>Ykwbbo*_8edxroljE_iwclvo|7t(0p60)6!Ygm};ExuJdE;^8 zyBc=I{&A}}`anIHAg6QlB<(mbX36M(F6-Bg`Fr8|S^dXvS+Mu3+=UzT4p6K(l&Dlc zX|)=4{t|GrA{T4NXh*+IeD?B|wCBj-CwJXe_ku%fKIUu5ja{5;7D9D7m zb~qhtv8&XGGRsHc*U(Z<3iB2s5am6-;D^k z8&&Ou9&LK@;T@H|*RDJ~YERwX@%Jye&6IB0y#6Nrx+8CL+DUYau;GLeV|(W^xs$H;jxRQ?+3@jui3gFyb#jXyUpr4y=8CtZDm$hc>nT`!o2KO6{rg zXTSbHTx#91HSgQ)UsjgCef067KkupCw1{t7eqhn>_??}-Fa6C28ejbI>8UmKyZfJi z{h9JLo4;PZy!7k$x+g9_w|M@G(tRhbFL2+gDkn!2u zKdgc>s=H;7-66khK>Jl0 +#include + +#include "accesstoken_kit.h" +#include "dataproxy_handle.h" +#include "dataproxy_handle_common.h" +#include "datashare_log.h" +#include "hap_token_info.h" +#include "token_setproc.h" +#include "datashare_errno.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::Security::AccessToken; +std::string TEST_URI1 = "datashareproxy://com.acts.datasharetest/test1"; +std::string TEST_URI2 = "datashareproxy://com.acts.datasharetest.other/test1"; +std::string TEST_UNUSED_URI = "datashareproxy://com.acts.datasharetest/unused"; +std::atomic_int g_callbackTimes = 0; + +class ProxyHandleTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void ProxyHandleTest::SetUpTestCase(void) +{ + LOG_INFO("SetUpTestCase invoked"); + int sleepTime = 1; + sleep(sleepTime); + + HapInfoParams info = { .userID = 100, + .bundleName = "com.acts.datasharetest", + .instIndex = 0, + .appIDDesc = "com.acts.datasharetest", + .isSystemApp = true }; + HapPolicyParams policy = { .apl = APL_SYSTEM_BASIC, + .domain = "test.domain", + .permList = { { .permissionName = "ohos.permission.GET_BUNDLE_INFO", + .bundleName = "com.acts.datasharetest", + .grantMode = 1, + .availableLevel = APL_SYSTEM_BASIC, + .label = "label", + .labelId = 1, + .description = "com.acts.datasharetest", + .descriptionId = 1 } }, + .permStateList = { { .permissionName = "ohos.permission.GET_BUNDLE_INFO", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } } } }; + AccessTokenKit::AllocHapToken(info, policy); + auto testTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenIDEx( + info.userID, info.bundleName, info.instIndex); + SetSelfTokenID(testTokenId.tokenIDEx); + + LOG_INFO("SetUpTestCase end"); +} + +void ProxyHandleTest::TearDownTestCase(void) +{ + auto tokenId = AccessTokenKit::GetHapTokenID(100, "com.acts.datasharetest", 0); + AccessTokenKit::DeleteToken(tokenId); +} + +void ProxyHandleTest::SetUp(void) +{ +} + +void ProxyHandleTest::TearDown(void) +{ +} + +/** + * @tc.name: ProxyHandleTest_Publish_Test_001 + * @tc.desc: Verify DataProxyHandle successfully publishing string data + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the publish parameters to SHARED_CONFIG type + 3. Prepare string-type test data and publish it + 4. Retrieve the data via the same URI + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data publish operation returns a SUCCESS status code + 3. The retrieved data matches the originally published data + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Publish_Test_001, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Publish_Test_001::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + EXPECT_NE(handle, nullptr); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish and get string + DataProxyValue value = "hello"; + DataShareProxyData data(TEST_URI1, value); + std::vector proxyData; + proxyData.push_back(data); + + LOG_INFO("PublishProxyData::Start"); + auto ret2 = handle->PublishProxyData(proxyData, proxyConfig); + EXPECT_EQ(ret2[0].result_, DataProxyErrorCode::SUCCESS); + + std::vector uris; + uris.push_back(TEST_URI1); + LOG_INFO("GetProxyData::Start"); + auto ret3 = handle->GetProxyData(uris, proxyConfig); + EXPECT_EQ(ret3[0].value_, value); + + LOG_INFO("ProxyHandleTest_Publish_Test_001::End"); +} + +/** + * @tc.name: ProxyHandleTest_Publish_Test_002 + * @tc.desc: Verify DataProxyHandle successfully publishing integer data + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the publish parameters to SHARED_CONFIG type + 3. Prepare integer-type test data and publish it + 4. Retrieve the data via the same URI + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data publish operation returns a SUCCESS status code + 3. The retrieved data matches the originally published data + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Publish_Test_002, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Publish_Test_002::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish and get int + DataProxyValue value = 123456; + DataShareProxyData data(TEST_URI1, value); + std::vector proxyData; + proxyData.push_back(data); + + auto ret2 = handle->PublishProxyData(proxyData, proxyConfig); + EXPECT_EQ(ret2[0].result_, DataProxyErrorCode::SUCCESS); + + std::vector uris; + uris.push_back(TEST_URI1); + auto ret3 = handle->GetProxyData(uris, proxyConfig); + EXPECT_EQ(ret3[0].value_, value); + + LOG_INFO("ProxyHandleTest_Publish_Test_002::End"); +} + +/** + * @tc.name: ProxyHandleTest_Publish_Test_003 + * @tc.desc: Verify DataProxyHandle successfully + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the publish parameters to SHARED_CONFIG type + 3. Prepare double-precision floating-point test data and publish it + 4. Retrieve the data via the same URI + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data publish operation returns a SUCCESS status code + 3. The retrieved data matches the originally published data + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Publish_Test_003, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Publish_Test_003::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish and get double + DataProxyValue value = 123456.123456; + DataShareProxyData data(TEST_URI1, value); + std::vector proxyData; + proxyData.push_back(data); + + auto ret2 = handle->PublishProxyData(proxyData, proxyConfig); + EXPECT_EQ(ret2[0].result_, DataProxyErrorCode::SUCCESS); + + std::vector uris; + uris.push_back(TEST_URI1); + auto ret3 = handle->GetProxyData(uris, proxyConfig); + EXPECT_EQ(ret3[0].value_, value); + + LOG_INFO("ProxyHandleTest_Publish_Test_003::End"); +} + +/** + * @tc.name: ProxyHandleTest_Publish_Test_004 + * @tc.desc: Verify DataProxyHandle successfully publishing boolean data + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the publish parameters to SHARED_CONFIG type + 3. Prepare boolean-type test data and publish it + 4. Retrieve the data via the same URI + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data publish operation returns a SUCCESS status code + 3. The retrieved data matches the originally published data + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Publish_Test_004, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Publish_Test_004::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish and get bool + DataProxyValue value = true; + DataShareProxyData data(TEST_URI1, value); + std::vector proxyData; + proxyData.push_back(data); + + auto ret2 = handle->PublishProxyData(proxyData, proxyConfig); + EXPECT_EQ(ret2[0].result_, DataProxyErrorCode::SUCCESS); + + std::vector uris; + uris.push_back(TEST_URI1); + auto ret3 = handle->GetProxyData(uris, proxyConfig); + EXPECT_EQ(ret3[0].value_, value); + + LOG_INFO("ProxyHandleTest_Publish_Test_004::End"); +} + +/** + * @tc.name: ProxyHandleTest_Publish_Test_005 + * @tc.desc: Verify that DataProxyHandle fails to publish data from another bundlename + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the publish parameters to SHARED_CONFIG type + 3. Prepare test data pointing to another application's bundlename and attempt to publish it + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data publish operation returns a NO_PERMISSION status code + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Publish_Test_005, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Publish_Test_005::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish and get bool + DataProxyValue value = true; + DataShareProxyData data(TEST_URI2, value); + std::vector proxyData; + proxyData.push_back(data); + + // Publish other bundle name, failed because of no permission. + auto ret2 = handle->PublishProxyData(proxyData, proxyConfig); + EXPECT_EQ(ret2[0].result_, DataProxyErrorCode::NO_PERMISSION); + + LOG_INFO("ProxyHandleTest_Publish_Test_005::End"); +} + +/** + * @tc.name: ProxyHandleTest_Delete_Test_001 + * @tc.desc: Verify the functionality of DataProxyHandle successfully deleting published data + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the operation parameters to SHARED_CONFIG type + 3. Publish test data + 4. Verify that the data can be retrieved normally + 5. Delete the published data + 6. Attempt to retrieve the deleted data again + * @tc.expect: + 1. The data publish operation returns a SUCCESS status code + 2. The data retrieval operation returns data that matches the published data + 3. The data deletion operation returns a SUCCESS status code + 4. Attempting to retrieve the data after deletion returns a URI_NOT_EXIST status code + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Delete_Test_001, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Delete_Test_001::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish and get bool + DataProxyValue value = true; + DataShareProxyData data(TEST_URI1, value); + std::vector proxyData; + proxyData.push_back(data); + + auto ret2 = handle->PublishProxyData(proxyData, proxyConfig); + EXPECT_EQ(ret2[0].result_, DataProxyErrorCode::SUCCESS); + + std::vector uris; + uris.push_back(TEST_URI1); + auto ret3 = handle->GetProxyData(uris, proxyConfig); + EXPECT_EQ(ret3[0].value_, value); + + // delete the data success + auto ret4 = handle->DeleteProxyData(uris, proxyConfig); + EXPECT_EQ(ret4[0].result_, DataProxyErrorCode::SUCCESS); + + // get data failed + auto ret5 = handle->GetProxyData(uris, proxyConfig); + EXPECT_EQ(ret5[0].result_, DataProxyErrorCode::URI_NOT_EXIST); + + LOG_INFO("ProxyHandleTest_Delete_Test_001::End"); +} + +/** + * @tc.name: ProxyHandleTest_Delete_Test_002 + * @tc.desc: Verify that DataProxyHandle fails to delete data from another bundlename + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the operation parameters to SHARED_CONFIG type + 3. Attempt to delete test data pointing to another application's bundle name + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data deletion operation returns a NO_PERMISSION status code + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Delete_Test_002, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Delete_Test_002::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + std::vector uris; + uris.push_back(TEST_URI2); + + // delete data of other bundle name, failed because of no permission. + auto ret4 = handle->DeleteProxyData(uris, proxyConfig); + EXPECT_EQ(ret4[0].result_, DataProxyErrorCode::NO_PERMISSION); + + LOG_INFO("ProxyHandleTest_Delete_Test_002::End"); +} + +/** + * @tc.name: ProxyHandleTest_Delete_Test_003 + * @tc.desc: Verify that DataProxyHandle fails to delete unpublished data + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the operation parameters to SHARED_CONFIG type + 3. Attempt to delete unpublished test data + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data deletion operation returns a URI_NOT_EXIST status code + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Delete_Test_003, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Delete_Test_003::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + std::vector uris; + uris.push_back(TEST_UNUSED_URI); + + // delete unpublished data failed + auto ret4 = handle->DeleteProxyData(uris, proxyConfig); + EXPECT_EQ(ret4[0].result_, DataProxyErrorCode::URI_NOT_EXIST); + + LOG_INFO("ProxyHandleTest_Delete_Test_003::End"); +} + +/** + * @tc.name: ProxyHandleTest_Get_Test_001 + * @tc.desc: Verify that DataProxyHandle fails to retrieve unpublished data + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the operation parameters to SHARED_CONFIG type + 3. Attempt to retrieve unpublished test data + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data retrieval operation returns a URI_NOT_EXIST status code + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Get_Test_001, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Get_Test_001::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + std::vector uris; + uris.push_back(TEST_UNUSED_URI); + + // delete unpublished data failed + auto ret4 = handle->GetProxyData(uris, proxyConfig); + EXPECT_EQ(ret4[0].result_, DataProxyErrorCode::URI_NOT_EXIST); + + LOG_INFO("ProxyHandleTest_Get_Test_001::End"); +} + +/** + * @tc.name: ProxyHandleTest_Subscribe_Test_001 + * @tc.desc: Verify the functionality of DataProxyHandle successfully subscribing + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the operation parameters to SHARED_CONFIG type + 3. Publish initial test data + 4. Subscribe to data change events + 5. Update the subscribed data + * @tc.expect: + 1. The data publish operation returns a SUCCESS status code + 2. The data subscription operation returns a SUCCESS status code + 3. The callback function is triggered once after the data is updated + 4. The number of change notifications received by the callback function is correct + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Subscribe_Test_001, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Subscribe_Test_001::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish data first + DataProxyValue value1 = "hello"; + DataShareProxyData data1(TEST_URI1, value1); + std::vector proxyData1; + proxyData1.push_back(data1); + handle->PublishProxyData(proxyData1, proxyConfig); + + std::vector uris; + uris.push_back(TEST_URI1); + // subscribe data + g_callbackTimes = 0; + auto ret4 = handle->SubscribeProxyData(uris, [](const std::vector &changeNode) { + LOG_INFO("ProxyHandleTest_Subscribe_Test_001::CallBack success"); + g_callbackTimes++; + EXPECT_EQ(changeNode.size(), 1); + }); + EXPECT_EQ(ret4[0].result_, DataProxyErrorCode::SUCCESS); + + // publish data and do callback + DataProxyValue value2 = "world"; + DataShareProxyData data2(TEST_URI1, value2); + std::vector proxyData2; + proxyData2.push_back(data2); + handle->PublishProxyData(proxyData2, proxyConfig); + EXPECT_EQ(g_callbackTimes, 1); + LOG_INFO("ProxyHandleTest_Subscribe_Test_001::End"); +} + +/** + * @tc.name: ProxyHandleTest_Subscribe_Test_002 + * @tc.desc: Verify that DataProxyHandle fails to subscribe to unpublished data + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the operation parameters to SHARED_CONFIG type + 3. Attempt to subscribe to unpublished test data + * @tc.expect: + 1. The DataProxyHandle is created successfully + 2. The data subscription operation returns a URI_NOT_EXIST status code + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Subscribe_Test_002, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Subscribe_Test_002::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + std::vector uris; + uris.push_back(TEST_UNUSED_URI); + // subscribe data + g_callbackTimes = 0; + auto ret4 = handle->SubscribeProxyData(uris, [](const std::vector &changeNode) { + LOG_INFO("ProxyHandleTest_Subscribe_Test_002::CallBack success"); + g_callbackTimes++; + EXPECT_EQ(changeNode.size(), 1); + }); + EXPECT_EQ(ret4[0].result_, DataProxyErrorCode::URI_NOT_EXIST); + + LOG_INFO("ProxyHandleTest_Subscribe_Test_002::End"); +} + +/** + * @tc.name: ProxyHandleTest_Unsubscribe_Test_001 + * @tc.desc: Verify the functionality of DataProxyHandle successfully unsubscribing from data changes + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the operation parameters to SHARED_CONFIG type + 3. Publish initial test data + 4. Subscribe to data change events + 5. Update the data to verify that the callback function is triggered + 6. Unsubscribe from the data + 7. Update the data again + * @tc.expect: + 1. The data publish operation returns a SUCCESS status code + 2. The data subscription operation returns a SUCCESS status code + 3. The callback function is triggered after the first data update + 4. The unsubscribe operation is successful + 5. The callback function is not triggered after the second data update + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Unsubscribe_Test_001, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Unsubscribe_Test_001::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish data first + DataProxyValue value1 = "hello"; + DataShareProxyData data1(TEST_URI1, value1); + std::vector proxyData1; + proxyData1.push_back(data1); + handle->PublishProxyData(proxyData1, proxyConfig); + + std::vector uris; + uris.push_back(TEST_URI1); + // subscribe data + g_callbackTimes = 0; + auto ret4 = handle->SubscribeProxyData(uris, [](const std::vector &changeNode) { + LOG_INFO("ProxyHandleTest_Unsubscribe_Test_001::CallBack success"); + g_callbackTimes++; + EXPECT_EQ(changeNode.size(), 1); + }); + EXPECT_EQ(ret4[0].result_, DataProxyErrorCode::SUCCESS); + + // publish data and do callback + DataProxyValue value2 = "world"; + DataShareProxyData data2(TEST_URI1, value2); + std::vector proxyData2; + proxyData2.push_back(data2); + handle->PublishProxyData(proxyData2, proxyConfig); + + // unsubscribe data success + ret4 = handle->UnsubscribeProxyData(uris); + + + // publish data and not do callback + handle->PublishProxyData(proxyData2, proxyConfig); + LOG_INFO("ProxyHandleTest_Unsubscribe_Test_001::End"); +} + +/** + * @tc.name: ProxyHandleTest_Unsubscribe_Test_002 + * @tc.desc: Verify the functionality of DataProxyHandle successfully unsubscribing + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataProxyHandle instance + 2. Configure the operation parameters to SHARED_CONFIG type + 3. Publish initial test data + 4. Subscribe to data change events + 5. Update the data to verify that the callback function is triggered + 6. Call the unsubscribe interface with no parameters to unsubscribe from all subscriptions + 7. Update the data again + * @tc.expect: + 1. The data publish operation returns a SUCCESS status code + 2. The data subscription operation returns a SUCCESS status code + 3. The callback function is triggered after the first data update + 4. The operation to unsubscribe from all subscriptions is successful + 5. The callback function is not triggered after the second data update + */ +HWTEST_F(ProxyHandleTest, ProxyHandleTest_Unsubscribe_Test_002, TestSize.Level0) +{ + LOG_INFO("ProxyHandleTest_Unsubscribe_Test_002::Start"); + auto [ret, handle] = DataShare::DataProxyHandle::Create(); + EXPECT_EQ(ret, E_OK); + + DataProxyConfig proxyConfig; + proxyConfig.type_ = DataProxyType::SHARED_CONFIG; + + // publish data first + DataProxyValue value1 = "hello"; + DataShareProxyData data1(TEST_URI1, value1); + std::vector proxyData1; + proxyData1.push_back(data1); + handle->PublishProxyData(proxyData1, proxyConfig); + + std::vector uris; + uris.push_back(TEST_URI1); + // subscribe data + g_callbackTimes = 0; + auto ret4 = handle->SubscribeProxyData(uris, [](const std::vector &changeNode) { + LOG_INFO("ProxyHandleTest_Unsubscribe_Test_002::CallBack success"); + g_callbackTimes++; + EXPECT_EQ(changeNode.size(), 1); + }); + EXPECT_EQ(ret4[0].result_, DataProxyErrorCode::SUCCESS); + + // publish data and do callback + DataProxyValue value2 = "world"; + DataShareProxyData data2(TEST_URI1, value2); + std::vector proxyData2; + proxyData2.push_back(data2); + handle->PublishProxyData(proxyData2, proxyConfig); + + // unsubscribe all uris success + std::vector emptyUris; + auto ret2 = handle->UnsubscribeProxyData(emptyUris); + + // publish data and not do callback + handle->PublishProxyData(proxyData2, proxyConfig); + LOG_INFO("ProxyHandleTest_Unsubscribe_Test_002::End"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/datashare_access_threshold_test/datashare_threshold_test.cpp b/data_share/test/native/unittest/datashare_access_threshold_test/datashare_threshold_test.cpp new file mode 100644 index 00000000..6ea24c43 --- /dev/null +++ b/data_share/test/native/unittest/datashare_access_threshold_test/datashare_threshold_test.cpp @@ -0,0 +1,762 @@ +/* + * 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 "datashare_helper.h" + +#include + +#include "accesstoken_kit.h" +#include "data_ability_observer_stub.h" +#include "datashare_log.h" +#include "hap_token_info.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "token_setproc.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::Security::AccessToken; +using ChangeInfo = DataShareObserver::ChangeInfo; +constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::string SLIENT_ACCESS_URI = "datashareproxy://com.acts.datasharetest/test?Proxy=true"; +std::string TBL_STU_NAME = "name"; +std::string TBL_STU_AGE = "age"; +std::shared_ptr g_exHelper; + +class DataShareThresholdTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +class IDataShareAbilityObserverTest : public AAFwk::DataAbilityObserverStub { +public: + explicit IDataShareAbilityObserverTest(int code) + { + code_ = code; + } + + ~IDataShareAbilityObserverTest() + {} + + void OnChange() {} + + int code_; +}; + +std::shared_ptr CreateDataShareHelper(int32_t systemAbilityId, std::string uri) +{ + LOG_INFO("CreateDataShareHelper start"); + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saManager == nullptr) { + LOG_ERROR("GetSystemAbilityManager get samgr failed."); + return nullptr; + } + auto remoteObj = saManager->GetSystemAbility(systemAbilityId); + if (remoteObj == nullptr) { + LOG_ERROR("GetSystemAbility service failed."); + return nullptr; + } + return DataShare::DataShareHelper::Creator(remoteObj, uri); +} + + +std::vector GetPermissionStateFulls() +{ + std::vector permissionStateFulls = { + { + .permissionName = "ohos.permission.WRITE_CONTACTS", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + }, + { + .permissionName = "ohos.permission.WRITE_CALL_LOG", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + }, + { + .permissionName = "ohos.permission.GET_BUNDLE_INFO", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + } + }; + return permissionStateFulls; +} + +void DataShareThresholdTest::SetUpTestCase(void) +{ + LOG_INFO("SetUpTestCase invoked"); + auto dataShareHelper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, DATA_SHARE_URI); + ASSERT_TRUE(dataShareHelper != nullptr); + int sleepTime = 3; + sleep(sleepTime); + + HapInfoParams info = { + .userID = 100, + .bundleName = "ohos.datashareclienttest.demo", + .instIndex = 0, + .appIDDesc = "ohos.datashareclienttest.demo" + }; + auto permStateList = GetPermissionStateFulls(); + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.datashareclienttest.demo", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "ohos.datashareclienttest.demo", + .descriptionId = 1 + } + }, + .permStateList = permStateList + }; + AccessTokenKit::AllocHapToken(info, policy); + auto testTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenIDEx( + info.userID, info.bundleName, info.instIndex); + SetSelfTokenID(testTokenId.tokenIDEx); + + g_exHelper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, DATA_SHARE_URI); + ASSERT_TRUE(g_exHelper != nullptr); + LOG_INFO("SetUpTestCase end"); +} + +void DataShareThresholdTest::TearDownTestCase(void) +{ + auto tokenId = AccessTokenKit::GetHapTokenIDEx(100, "ohos.datashareclienttest.demo", 0); + AccessTokenKit::DeleteToken(tokenId.tokenIDEx); + g_exHelper = nullptr; +} + +void DataShareThresholdTest::SetUp(void) {} +void DataShareThresholdTest::TearDown(void) {} + +/** + * @tc.name: Insert_Threshold_Test001 + * @tc.desc: Verify silent access Insert operation behavior when exceeding and not exceeding the threshold + * @tc.type: FUNC + * @tc.require: issueIC8OCN + * @tc.precon: None + * @tc.step: + 1. Create a DataShareHelper instance with silent access configuration + 2. Prepare test data (name and age) in a DataShareValuesBucket + 3. Perform initial Insert operation and verify success + 4. Perform 2998 additional Insert operations (not exceeding threshold) and verify success + 5. Perform 10 more Insert operations (exceeding threshold) and check results + * @tc.expect: + 1. DataShareHelper is created successfully (not nullptr) + 2. All Insert operations before threshold return positive values (success) + 3. All Insert operations after threshold return DATA_SHARE_ERROR(-1) + */ +HWTEST_F(DataShareThresholdTest, Insert_Threshold_Test001, TestSize.Level1) +{ + LOG_INFO("Insert_Threshold_Test001::Start"); + auto helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, SLIENT_ACCESS_URI); + ASSERT_TRUE(helper != nullptr); + + Uri uri(SLIENT_ACCESS_URI); + + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "zhangsan"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 18; + valuesBucket.Put(TBL_STU_AGE, age); + int retVal = helper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal > 0), true); + + DataShare::DataShareValuesBucket valuesBucket1; + std::string value1 = "lisi"; + valuesBucket1.Put(TBL_STU_NAME, value1); + age = 25; + valuesBucket1.Put(TBL_STU_AGE, age); + // not over threshold, insert success + for (int i = 0; i < 2998; i++) { + retVal = helper->Insert(uri, valuesBucket1); + EXPECT_EQ((retVal > 0), true); + } + + // over threshold, insert ret DATA_SHARE_ERROR(-1) + for (int i = 0; i < 10; i++) { + retVal = helper->Insert(uri, valuesBucket1); + EXPECT_EQ(retVal, -1); + } + LOG_INFO("Insert_Threshold_Test001::End"); +} + +/** +* @tc.name: Update_Threshold_Test001 +* @tc.desc: Verify silent access Update operation behavior when exceeding and not exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Create a DataShareHelper instance with silent access configuration + 2. Define update predicates to target specific data + 3. Prepare update data in a DataShareValuesBucket + 4. Perform 2999 Update operations (not exceeding threshold) and verify success + 5. Perform 10 more Update operations (exceeding threshold) and check results +* @tc.expect: + 1. DataShareHelper is created successfully (not nullptr) + 2. All Update operations before threshold return 1 (success) + 3. All Update operations after threshold return DATA_SHARE_ERROR(-1) +*/ +HWTEST_F(DataShareThresholdTest, Update_Threshold_Test001, TestSize.Level1) +{ + LOG_INFO("Update_Threshold_Test001::Start"); + auto helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, SLIENT_ACCESS_URI); + ASSERT_TRUE(helper != nullptr); + + Uri uri(SLIENT_ACCESS_URI); + + DataShare::DataSharePredicates predicates; + std::string selections = TBL_STU_NAME + " = 'zhangsan'"; + predicates.SetWhereClause(selections); + + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put(TBL_STU_AGE, 10); + // not over threshold, update success + for (int i = 0; i < 2999; i++) { + int retVal = helper->Update(uri, predicates, valuesBucket); + EXPECT_EQ(retVal, 1); + } + + // over threshold, update ret DATA_SHARE_ERROR(-1) + for (int i = 0; i < 10; i++) { + int retVal = helper->Update(uri, predicates, valuesBucket); + EXPECT_EQ(retVal, -1); + } + LOG_INFO("Update_Threshold_Test001::End"); +} + +/** +* @tc.name: Query_Threshold_Test001 +* @tc.desc: Verify silent access Query operation behavior when exceeding and not exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Create a DataShareHelper instance with silent access configuration + 2. Define query predicates to target specific data + 3. Perform 2999 Query operations (not exceeding threshold) and verify results + 4. Perform 10 more Query operations (exceeding threshold) and check results +* @tc.expect: + 1. DataShareHelper is created successfully (not nullptr) + 2. All Query operations before threshold return valid result sets with 1 row + 3. All Query operations after threshold return nullptr (DATA_SHARE_ERROR) +*/ +HWTEST_F(DataShareThresholdTest, Query_Threshold_Test001, TestSize.Level1) +{ + LOG_INFO("Query_Threshold_Test001::Start"); + auto helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, SLIENT_ACCESS_URI); + ASSERT_TRUE(helper != nullptr); + + Uri uri(SLIENT_ACCESS_URI); + + DataShare::DataSharePredicates predicates; + predicates.EqualTo(TBL_STU_NAME, "zhangsan"); + vector columns; + int result = 0; + + // not over threshold, query success + for (int i = 0; i < 2999; i++) { + auto resultSet = helper->Query(uri, predicates, columns); + ASSERT_NE(resultSet, nullptr); + resultSet->GetRowCount(result); + EXPECT_EQ(result, 1); + resultSet->Close(); + } + + // over threshold, query ret DATA_SHARE_ERROR(-1) + for (int i = 0; i < 10; i++) { + auto resultSet = helper->Query(uri, predicates, columns); + ASSERT_EQ(resultSet, nullptr); + } + LOG_INFO("Query_Threshold_Test001::End"); +} + +/** +* @tc.name: Delete_Threshold_Test001 +* @tc.desc: Verify silent access Delete operation behavior when exceeding and not exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Create a DataShareHelper instance with silent access configuration + 2. Define delete predicates targeting non-existent data + 3. Perform 2999 Delete operations (not exceeding threshold) and verify results + 4. Perform 10 more Delete operations (exceeding threshold) and check results +* @tc.expect: + 1. DataShareHelper is created successfully (not nullptr) + 2. All Delete operations before threshold return 0 (no data deleted) + 3. All Delete operations after threshold return DATA_SHARE_ERROR(-1) +*/ +HWTEST_F(DataShareThresholdTest, Delete_Threshold_Test001, TestSize.Level1) +{ + LOG_INFO("Delete_Threshold_Test001::Start"); + auto helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, SLIENT_ACCESS_URI); + ASSERT_TRUE(helper != nullptr); + + Uri uri(SLIENT_ACCESS_URI); + + DataShare::DataSharePredicates deletePredicates; + std::string selections = TBL_STU_NAME + " = 'lisan'"; + deletePredicates.SetWhereClause(selections); + + // not over threshold, delete data not exists return 0 + for (int i = 0; i < 2999; i++) { + int retVal = helper->Delete(uri, deletePredicates); + EXPECT_EQ(retVal, 0); + } + + // over threshold, delete ret -1 + for (int i = 0; i < 10; i++) { + int retVal = helper->Delete(uri, deletePredicates); + EXPECT_EQ(retVal, -1); + } + LOG_INFO("Delete_Threshold_Test001::End"); +} + +/** +* @tc.name: InsertEx_Threshold_Test001 +* @tc.desc: Verify silent access InsertEx operation behavior when exceeding and not exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Create a DataShareHelper instance with silent access configuration + 2. Prepare test data (name and age) in a DataShareValuesBucket + 3. Perform 2999 InsertEx operations (not exceeding threshold) and verify success + 4. Perform 10 more InsertEx operations (exceeding threshold) and check results +* @tc.expect: + 1. DataShareHelper is created successfully (not nullptr) + 2. All InsertEx operations before threshold return (0, positive value) indicating success + 3. All InsertEx operations after threshold return (DATA_SHARE_ERROR(-1), 0) +*/ +HWTEST_F(DataShareThresholdTest, InsertEx_Threshold_Test001, TestSize.Level1) +{ + LOG_INFO("InsertEx_Threshold_Test001::Start"); + + auto helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, SLIENT_ACCESS_URI); + ASSERT_TRUE(helper != nullptr); + + Uri uri(SLIENT_ACCESS_URI); + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "lisi"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 25; + valuesBucket.Put(TBL_STU_AGE, age); + // not over threshold, insertEx success + for (int i = 0; i < 2999; i++) { + auto [errCode, retVal] = helper->InsertEx(uri, valuesBucket); + EXPECT_EQ(errCode, 0); + EXPECT_EQ((retVal > 0), true); + } + + // over threshold, insertEx ret pair(DATA_SHARE_ERROR, 0) + for (int i = 0; i < 10; i++) { + auto [errCode, retVal] = helper->InsertEx(uri, valuesBucket); + EXPECT_EQ(errCode, -1); + EXPECT_EQ(retVal, 0); + } + LOG_INFO("InsertEx_Threshold_Test001::End"); +} + +/** +* @tc.name: UpdateEx_Threshold_Test001 +* @tc.desc: Verify silent access UpdateEx operation behavior when exceeding and not exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Create a DataShareHelper instance with silent access configuration + 2. Define update predicates to target specific data + 3. Prepare update data in a DataShareValuesBucket + 4. Perform 2999 UpdateEx operations (not exceeding threshold) and verify success + 5. Perform 10 more UpdateEx operations (exceeding threshold) and check results +* @tc.expect: + 1. DataShareHelper is created successfully (not nullptr) + 2. All UpdateEx operations before threshold return (0, 1) indicating success + 3. All UpdateEx operations after threshold return (DATA_SHARE_ERROR(-1), 0) +*/ +HWTEST_F(DataShareThresholdTest, UpdateEx_Threshold_Test001, TestSize.Level1) +{ + LOG_INFO("UpdateEx_Threshold_Test001::Start"); + + auto helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, SLIENT_ACCESS_URI); + ASSERT_TRUE(helper != nullptr); + + Uri uri(SLIENT_ACCESS_URI); + + DataShare::DataSharePredicates predicates; + std::string selections = TBL_STU_NAME + " = 'zhangsan'"; + predicates.SetWhereClause(selections); + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put(TBL_STU_AGE, 10); + + // not over threshold, updateEx success + for (int i = 0; i < 2999; i++) { + auto [errCode, retVal] = helper->UpdateEx(uri, predicates, valuesBucket); + EXPECT_EQ(errCode, 0); + EXPECT_EQ(retVal, 1); + } + + // over threshold, updateEx ret pair(DATA_SHARE_ERROR, 0) + for (int i = 0; i < 10; i++) { + auto [errCode, retVal] = helper->UpdateEx(uri, predicates, valuesBucket); + EXPECT_EQ(errCode, -1); + EXPECT_EQ(retVal, 0); + } + LOG_INFO("UpdateEx_Threshold_Test001::End"); +} + +/** +* @tc.name: DeleteEx_Threshold_Test001 +* @tc.desc: Verify silent access DeleteEx operation behavior when exceeding and not exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Create a DataShareHelper instance with silent access configuration + 2. Define delete predicates targeting non-existent data + 3. Perform 2999 DeleteEx operations (not exceeding threshold) and verify results + 4. Perform 10 more DeleteEx operations (exceeding threshold) and check results +* @tc.expect: + 1. DataShareHelper is created successfully (not nullptr) + 2. All DeleteEx operations before threshold return (0, 0) indicating no data deleted + 3. All DeleteEx operations after threshold return (DATA_SHARE_ERROR(-1), 0) +*/ +HWTEST_F(DataShareThresholdTest, DeleteEx_Threshold_Test001, TestSize.Level1) +{ + LOG_INFO("DeleteEx_Threshold_Test001::Start"); + + auto helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, SLIENT_ACCESS_URI); + ASSERT_TRUE(helper != nullptr); + + Uri uri(SLIENT_ACCESS_URI); + + DataShare::DataSharePredicates deletePredicates; + std::string selections = TBL_STU_NAME + " = 'lisan'"; + deletePredicates.SetWhereClause(selections); + // not over threshold, deleteEx data not exists return pair(0, 0) + for (int i = 0; i < 2999; i++) { + auto [errCode, retVal] = helper->DeleteEx(uri, deletePredicates); + EXPECT_EQ(errCode, 0); + EXPECT_EQ(retVal, 0); + } + + // over threshold, deleteEx ret pair(DATA_SHARE_ERROR, 0) + for (int i = 0; i < 10; i++) { + auto [errCode, retVal] = helper->DeleteEx(uri, deletePredicates); + EXPECT_EQ(errCode, -1); + EXPECT_EQ(retVal, 0); + } + LOG_INFO("DeleteEx_Threshold_Test001::End"); +} + +/** +* @tc.name: Insert_Threshold_Test002 +* @tc.desc: Verify non-silent access Insert operation behavior when exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Prepare test data (name and age) in a DataShareValuesBucket + 2. Perform 2999 Insert operations (not exceeding threshold) and verify success + 3. Perform 10 more Insert operations (exceeding threshold) and check results +* @tc.expect: + 1. All Insert operations before and after threshold return positive values (success) + 2. No failure occurs when exceeding threshold for non-silent access +*/ +HWTEST_F(DataShareThresholdTest, Insert_Threshold_Test002, TestSize.Level1) +{ + LOG_INFO("Insert_Threshold_Test002::Start"); + + Uri uri(DATA_SHARE_URI); + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "lisi"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 25; + valuesBucket.Put(TBL_STU_AGE, age); + // not over threshold, insert success + for (int i = 0; i < 2999; i++) { + int retVal = g_exHelper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal > 0), true); + } + + // over threshold, insert ret success + for (int i = 0; i < 10; i++) { + int retVal = g_exHelper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal > 0), true); + } + LOG_INFO("Insert_Threshold_Test002::End"); +} + +/** +* @tc.name: Update_Threshold_Test002 +* @tc.desc: Verify non-silent access Update operation behavior when exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Define update predicates to target specific data + 2. Prepare update data in a DataShareValuesBucket + 3. Perform 2999 Update operations (not exceeding threshold) and verify success + 4. Perform 10 more Update operations (exceeding threshold) and check results +* @tc.expect: + 1. All Update operations before and after threshold return 1 (success) + 2. No failure occurs when exceeding threshold for non-silent access +*/ +HWTEST_F(DataShareThresholdTest, Update_Threshold_Test002, TestSize.Level1) +{ + LOG_INFO("Update_Threshold_Test002::Start"); + + Uri uri(DATA_SHARE_URI); + + DataShare::DataSharePredicates predicates; + std::string selections = TBL_STU_NAME + " = 'zhangsan'"; + predicates.SetWhereClause(selections); + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put(TBL_STU_AGE, 10); + // not over threshold, update success + for (int i = 0; i < 2999; i++) { + int retVal = g_exHelper->Update(uri, predicates, valuesBucket); + EXPECT_EQ(retVal, 1); + } + + // over threshold, update success + for (int i = 0; i < 10; i++) { + int retVal = g_exHelper->Update(uri, predicates, valuesBucket); + EXPECT_EQ(retVal, 1); + } + LOG_INFO("Update_Threshold_Test002::End"); +} + +/** +* @tc.name: Query_Threshold_Test002 +* @tc.desc: Verify non-silent access Query operation behavior when exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Define query predicates to target specific data + 2. Perform 2999 Query operations (not exceeding threshold) and verify results + 3. Perform 10 more Query operations (exceeding threshold) and check results +* @tc.expect: + 1. All Query operations before and after threshold return valid result sets with 1 row + 2. No failure occurs when exceeding threshold for non-silent access +*/ +HWTEST_F(DataShareThresholdTest, Query_Threshold_Test002, TestSize.Level1) +{ + LOG_INFO("Query_Threshold_Test002::Start"); + + Uri uri(DATA_SHARE_URI); + DataShare::DataSharePredicates predicates; + predicates.EqualTo(TBL_STU_NAME, "zhangsan"); + vector columns; + int result = 0; + + // not over threshold, query success + for (int i = 0; i < 2999; i++) { + auto resultSet = g_exHelper->Query(uri, predicates, columns); + ASSERT_NE(resultSet, nullptr); + resultSet->GetRowCount(result); + EXPECT_EQ(result, 1); + resultSet->Close(); + } + + // over threshold, query success + for (int i = 0; i < 10; i++) { + auto resultSet = g_exHelper->Query(uri, predicates, columns); + ASSERT_NE(resultSet, nullptr); + resultSet->GetRowCount(result); + EXPECT_EQ(result, 1); + resultSet->Close(); + } + LOG_INFO("Query_Threshold_Test002::End"); +} + +/** +* @tc.name: Delete_Threshold_Test002 +* @tc.desc: Verify non-silent access Delete operation behavior when exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Define delete predicates targeting non-existent data + 2. Perform 2999 Delete operations (not exceeding threshold) and verify results + 3. Perform 10 more Delete operations (exceeding threshold) and check results +* @tc.expect: + 1. All Delete operations before and after threshold return 0 (no data deleted) + 2. No failure occurs when exceeding threshold for non-silent access +*/ +HWTEST_F(DataShareThresholdTest, Delete_Threshold_Test002, TestSize.Level1) +{ + LOG_INFO("Delete_Threshold_Test002::Start"); + + Uri uri(DATA_SHARE_URI); + + DataShare::DataSharePredicates deletePredicates; + std::string selections = TBL_STU_NAME + " = 'lisan'"; + deletePredicates.SetWhereClause(selections); + + // not over threshold, delete data not exists return 0 + for (int i = 0; i < 2999; i++) { + int retVal = g_exHelper->Delete(uri, deletePredicates); + EXPECT_EQ(retVal, 0); + } + + // over threshold, delete data not exists return 0 + for (int i = 0; i < 10; i++) { + int retVal = g_exHelper->Delete(uri, deletePredicates); + EXPECT_EQ(retVal, 0); + } + LOG_INFO("Delete_Threshold_Test002::End"); +} + +/** +* @tc.name: InsertEx_Threshold_Test002 +* @tc.desc: Verify non-silent access InsertEx operation behavior when exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Prepare test data (name and age) in a DataShareValuesBucket + 2. Perform 2999 InsertEx operations (not exceeding threshold) and verify success + 3. Perform 10 more InsertEx operations (exceeding threshold) and check results +* @tc.expect: + 1. All InsertEx operations before and after threshold return (0, positive value) indicating success + 2. No failure occurs when exceeding threshold for non-silent access +*/ +HWTEST_F(DataShareThresholdTest, InsertEx_Threshold_Test002, TestSize.Level1) +{ + LOG_INFO("InsertEx_Threshold_Test002::Start"); + + Uri uri(DATA_SHARE_URI); + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "lisi"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 25; + valuesBucket.Put(TBL_STU_AGE, age); + // not over threshold, insertEx success + for (int i = 0; i < 2999; i++) { + auto [errCode, retVal] = g_exHelper->InsertEx(uri, valuesBucket); + EXPECT_EQ(errCode, 0); + EXPECT_EQ((retVal > 0), true); + } + + // over threshold, insertEx success + for (int i = 0; i < 10; i++) { + auto [errCode, retVal] = g_exHelper->InsertEx(uri, valuesBucket); + EXPECT_EQ(errCode, 0); + EXPECT_EQ((retVal > 0), true); + } + LOG_INFO("InsertEx_Threshold_Test002::End"); +} + +/** +* @tc.name: UpdateEx_Threshold_Test002 +* @tc.desc: Verify non-silent access UpdateEx operation behavior when exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Define update predicates to target specific data + 2. Prepare update data in a DataShareValuesBucket + 3. Perform 2999 UpdateEx operations (not exceeding threshold) and verify success + 4. Perform 10 more UpdateEx operations (exceeding threshold) and check results +* @tc.expect: + 1. All UpdateEx operations before and after threshold return (0, 1) indicating success + 2. No failure occurs when exceeding threshold for non-silent access +*/ +HWTEST_F(DataShareThresholdTest, UpdateEx_Threshold_Test002, TestSize.Level1) +{ + LOG_INFO("UpdateEx_Threshold_Test002::Start"); + + Uri uri(DATA_SHARE_URI); + + DataShare::DataSharePredicates predicates; + std::string selections = TBL_STU_NAME + " = 'zhangsan'"; + predicates.SetWhereClause(selections); + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put(TBL_STU_AGE, 10); + // not over threshold, updateEx sccuess + for (int i = 0; i < 2999; i++) { + auto [errCode, retVal] = g_exHelper->UpdateEx(uri, predicates, valuesBucket); + EXPECT_EQ(errCode, 0); + EXPECT_EQ(retVal, 1); + } + + // over threshold, updateEx ret success + for (int i = 0; i < 10; i++) { + auto [errCode, retVal] = g_exHelper->UpdateEx(uri, predicates, valuesBucket); + EXPECT_EQ(errCode, 0); + EXPECT_EQ(retVal, 1); + } + LOG_INFO("UpdateEx_Threshold_Test002::End"); +} + +/** +* @tc.name: DeleteEx_Threshold_Test002 +* @tc.desc: Verify non-silent access DeleteEx operation behavior when exceeding the threshold +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Define delete predicates targeting non-existent data + 2. Perform 2999 DeleteEx operations (not exceeding threshold) and verify results + 3. Perform 10 more DeleteEx operations (exceeding threshold) and check results +* @tc.expect: + 1. All DeleteEx operations before and after threshold return (0, 0) indicating no data deleted + 2. No failure occurs when exceeding threshold for non-silent access +*/ +HWTEST_F(DataShareThresholdTest, DeleteEx_Threshold_Test002, TestSize.Level1) +{ + LOG_INFO("DeleteEx_Threshold_Test002::Start"); + + Uri uri(DATA_SHARE_URI); + + DataShare::DataSharePredicates deletePredicates; + std::string selections = TBL_STU_NAME + " = 'lisan'"; + deletePredicates.SetWhereClause(selections); + // not over threshold, deleteEx data not exists return pair(0, 0) + for (int i = 0; i < 2999; i++) { + auto [errCode, retVal] = g_exHelper->DeleteEx(uri, deletePredicates); + EXPECT_EQ(errCode, 0); + EXPECT_EQ(retVal, 0); + } + + // over threshold, deleteEx data not exists return pair(0, 0) + for (int i = 0; i < 10; i++) { + auto [errCode, retVal] = g_exHelper->DeleteEx(uri, deletePredicates); + EXPECT_EQ(errCode, 0); + EXPECT_EQ(retVal, 0); + } + LOG_INFO("DeleteEx_Threshold_Test002::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/native/unittest/datashare_common_test/datashare_itypes_utils_test.cpp b/data_share/test/native/unittest/datashare_common_test/datashare_itypes_utils_test.cpp new file mode 100644 index 00000000..1bcde613 --- /dev/null +++ b/data_share/test/native/unittest/datashare_common_test/datashare_itypes_utils_test.cpp @@ -0,0 +1,225 @@ +/* + * 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. + */ +#define LOG_TAG "DatashareItypesUtilsTest" + +#include +#include + +#include "datashare_itypes_utils.h" +#include "log_print.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::DataShare; +using namespace OHOS::ITypesUtil; +class DatashareItypesUtilsTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +RdbChangeNode CreateRdbChangeNode() +{ + TemplateId templateId = TemplateId{123, "com.acts.datasharetest"}; + RdbChangeNode changeNode = RdbChangeNode{ + "datashare:///com.acts.datasharetest", + templateId, + {"deleted", "inserted", "updated"}, + false, + nullptr, + 8 + }; + return changeNode; +} + +bool operator==(const RdbChangeNode node1, const RdbChangeNode node2) +{ + bool firstPart = node1.uri_ == node2.uri_ + && node1.templateId_ == node2.templateId_ + && node1.data_ == node2.data_ + && node1.isSharedMemory_ == node2.isSharedMemory_ + && node1.size_ == node2.size_; + if (node1.memory_ == nullptr && node2.memory_ == nullptr) { + return firstPart && true; + } else if (node1.memory_ != nullptr && node2.memory_ != nullptr) { + return firstPart; + } + return false; +} + +/** + * @tc.name: Marshal_BatchUpdateResult_001 + * @tc.desc: Verify BatchUpdateResult marshal and unmarshal with marshalable data. + * This test case checks if the BatchUpdateResult object can be + * orrectly marshaled and unmarshaled. + * @tc.expect: The test expects that the marshaled and unmarshaled + * BatchUpdateResult objects are equal. + * @tc.step: + * 1. Create a BatchUpdateResult object and set its uri and codes. + * 2. Marshal the BatchUpdateResult object into a MessageParcel. + * 3. Unmarshal the BatchUpdateResult object from the MessageParcel. + * 4. Compare the original and unmarshaled BatchUpdateResult objects. + * @tc.type: FUNC + * @tc.precon: The test requires that the BatchUpdateResult object is initialized. + * @tc.require:issueIBYE9X + */ +HWTEST_F(DatashareItypesUtilsTest, Marshal_BatchUpdateResult_001, TestSize.Level0) +{ + ZLOGI("Marshal_BatchUpdateResult_001 starts"); + // Initialize the BatchUpdateResult object + BatchUpdateResult result; + BatchUpdateResult unmashalResult; + result.uri = "datashare:///com.acts.datasharetest"; + result.codes = {12, 2, 4}; + + MessageParcel parcel; + bool res = ITypesUtil::Marshalling(result, parcel); + EXPECT_TRUE(res); + + res = ITypesUtil::Unmarshalling(unmashalResult, parcel); + EXPECT_TRUE(res); + + // Compare the original and unmarshalled results + EXPECT_EQ(result.uri, unmashalResult.uri); + EXPECT_EQ(result.codes, unmashalResult.codes); + ZLOGI("Marshal_BatchUpdateResult_001 ends"); +} + +/** + * @tc.name: Marshal_RdbChangeNode_001 + * @tc.desc: Test the marshalling function of RdbChangeNode with isSharedMemory_ set to false. + * @tc.expect: The marshalling and unmarshalling process should succeed and the original + * RdbChangeNode object should be equal to the unmarshalled one. + * @tc.step: + * 1. Create a RdbChangeNode object with isSharedMemory_ set to false and a MessageParcel object. + * 2. Use the ITypesUtil::Marshalling function to marshal the RdbChangeNode object into + * the MessageParcel object. + * 3. Use the ITypesUtil::Unmarshalling function to unmarshal the RdbChangeNode object from + * the MessageParcel object. + * 4. Compare the original RdbChangeNode object with the unmarshalled one. + * @tc.type: FUNC + * @tc.precon: The test requires that the BatchUpdateResult object is initialized and isSharedMemory_ + * is set to false. + * @tc.require:issueIBYE9X + */ +HWTEST_F(DatashareItypesUtilsTest, Marshal_RdbChangeNode_001, TestSize.Level0) +{ + ZLOGI("Marshal_RdbChangeNode_001 starts"); + + RdbChangeNode unmashalchangeNode; + MessageParcel parcel; + RdbChangeNode changeNode = CreateRdbChangeNode(); + + bool res = ITypesUtil::Marshalling(changeNode, parcel); + EXPECT_TRUE(res); + res = ITypesUtil::Unmarshalling(unmashalchangeNode, parcel); + EXPECT_TRUE(res); + + EXPECT_TRUE(changeNode == unmashalchangeNode); + ZLOGI("Marshal_RdbChangeNode_001 ends"); +} + +/** + * @tc.name: Marshal_RdbChangeNode_002 + * @tc.desc: Test the marshalling function of RdbChangeNode with isSharedMemory_ set to + * true and memory_ set to nullptr. + * @tc.expect: The test expects the marshalling operation to fail due to the + * memory_ member being set to nullptr. + * @tc.step: + * 1. Create an RdbChangeNode instance and set its isSharedMemory_ flag to true. + * 2: Set the memory_ member of the RdbChangeNode instance to nullptr. + * 3: Attempt to marshalling the RdbChangeNode instance into a MessageParcel using + * the ITypesUtil::Marshalling method. + * 4: Verify that the marshalling operation fails by checking the return value of + * the ITypesUtil::Marshalling method, which should be false. + * @tc.type: FUNC + * @tc.precon: The test requires that the BatchUpdateResult object is initialized, while isSharedMemory_ + * is set to true, and memory_ set to nullptr. + * @tc.require:issueIBYE9X + */ +HWTEST_F(DatashareItypesUtilsTest, Marshal_RdbChangeNode_002, TestSize.Level0) +{ + ZLOGI("Marshal_RdbChangeNode_002 starts"); + + RdbChangeNode unmashalchangeNode; + MessageParcel parcel; + RdbChangeNode changeNode = CreateRdbChangeNode(); + changeNode.isSharedMemory_ = true; + changeNode.memory_ = nullptr; + + bool res = ITypesUtil::Marshalling(changeNode, parcel); + EXPECT_FALSE(res); + ZLOGI("Marshal_RdbChangeNode_002 ends"); +} + +/** + * @tc.name: Marshal_RdbChangeNode_003 + * @tc.desc: Test the marshalling and unmarshalling functionality of RdbChangeNode + * @tc.expect: The marshalling and unmarshalling process should succeed, + * data correctness and consistency should be ensured. + * @tc.step: + * 1. Create a RdbChangeNode object and set isSharedMemory_ flag to true. + * 2. Use CreateAshmem to create a shared memory object and set it to the memory_ member + * of the RdbChangeNode object. + * 3. Use ashmem to write data into the shared memory of the RdbChangeNode object. + * 3. Use the Unmarshalling method of ITypesUtil to deserialize the MessageParcel object + * into another RdbChangeNode object. + * 4. Verify that the original RdbChangeNode object and the deserialized RdbChangeNode objects + * are consistent with each other and the unmarshalling procress is successful. + * 5. Close the ashmem of the RdbChangeNode objects. + * @tc.type: FUNC + * @tc.precon: The test requires that the BatchUpdateResult object is initialized, while isSharedMemory_ + * is set to true, and use CreateAshmem to create a shared memory object to put in memory_. + * @tc.require:issueIBYE9X + */ +HWTEST_F(DatashareItypesUtilsTest, Marshal_RdbChangeNode_003, TestSize.Level0) +{ + ZLOGI("Marshal_RdbChangeNode_003 starts"); + + RdbChangeNode unmashalchangeNode; + MessageParcel parcel; + RdbChangeNode changeNode = CreateRdbChangeNode(); + changeNode.isSharedMemory_ = true; + changeNode.memory_ = Ashmem::CreateAshmem("testd", 8); + bool mapRet = changeNode.memory_->MapReadAndWriteAshmem(); + EXPECT_TRUE(mapRet); + + int32_t data = 123; + bool writeRet = changeNode.memory_->WriteToAshmem(&data, sizeof(data), 0); + EXPECT_TRUE(writeRet); + bool res = ITypesUtil::Marshalling(changeNode, parcel); + EXPECT_TRUE(res); + res = ITypesUtil::Unmarshalling(unmashalchangeNode, parcel); + EXPECT_TRUE(res); + mapRet = unmashalchangeNode.memory_->MapReadAndWriteAshmem(); + EXPECT_TRUE(mapRet); + + auto changeNodeData = changeNode.memory_->ReadFromAshmem(sizeof(data), 0); + EXPECT_NE(changeNodeData, nullptr); + auto unmashalchangeNodeData = unmashalchangeNode.memory_->ReadFromAshmem(sizeof(data), 0); + EXPECT_NE(unmashalchangeNodeData, nullptr); + + int32_t changeNodeValue = *(reinterpret_cast(changeNodeData)); + int32_t unmashalchangeNodeValue = *(reinterpret_cast(unmashalchangeNodeData)); + EXPECT_TRUE(changeNode == unmashalchangeNode && changeNodeValue == unmashalchangeNodeValue); + changeNode.memory_->CloseAshmem(); + unmashalchangeNode.memory_->CloseAshmem(); + ZLOGI("Marshal_RdbChangeNode_003 ends"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/datashareproxy_test/proxydatas_with_permission_test.cpp b/data_share/test/native/unittest/datashareproxy_test/proxydatas_with_permission_test.cpp index 1a5de881..08beecea 100644 --- a/data_share/test/native/unittest/datashareproxy_test/proxydatas_with_permission_test.cpp +++ b/data_share/test/native/unittest/datashareproxy_test/proxydatas_with_permission_test.cpp @@ -31,6 +31,7 @@ using namespace testing::ext; using namespace OHOS::Security::AccessToken; std::string DATA_SHARE_PROXY_URI = "datashareproxy://com.acts.ohos.data.datasharetest/test"; std::shared_ptr dataShareHelper; +std::shared_ptr dataShareHelper2; // for another subscriber std::string TBL_NAME0 = "name0"; std::string TBL_NAME1 = "name1"; constexpr int SUBSCRIBER_ID = 100; @@ -53,7 +54,8 @@ void ProxyDatasTest::SetUpTestCase(void) HapInfoParams info = { .userID = 100, .bundleName = "ohos.datashareproxyclienttest.demo", .instIndex = 0, - .appIDDesc = "ohos.datashareproxyclienttest.demo" }; + .appIDDesc = "ohos.datashareproxyclienttest.demo", + .isSystemApp = true }; HapPolicyParams policy = { .apl = APL_SYSTEM_BASIC, .domain = "test.domain", .permList = { { .permissionName = "ohos.permission.GET_BUNDLE_INFO", @@ -70,14 +72,16 @@ void ProxyDatasTest::SetUpTestCase(void) .grantStatus = { PermissionState::PERMISSION_GRANTED }, .grantFlags = { 1 } } } }; AccessTokenKit::AllocHapToken(info, policy); - auto testTokenId = - Security::AccessToken::AccessTokenKit::GetHapTokenID(info.userID, info.bundleName, info.instIndex); - SetSelfTokenID(testTokenId); + auto testTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenIDEx( + info.userID, info.bundleName, info.instIndex); + SetSelfTokenID(testTokenId.tokenIDEx); CreateOptions options; options.enabled_ = true; dataShareHelper = DataShare::DataShareHelper::Creator(DATA_SHARE_PROXY_URI, options); ASSERT_TRUE(dataShareHelper != nullptr); + dataShareHelper2 = DataShare::DataShareHelper::Creator(DATA_SHARE_PROXY_URI, options); + ASSERT_TRUE(dataShareHelper2 != nullptr); LOG_INFO("SetUpTestCase end"); } @@ -86,6 +90,7 @@ void ProxyDatasTest::TearDownTestCase(void) auto tokenId = AccessTokenKit::GetHapTokenID(100, "ohos.datashareclienttest.demo", 0); AccessTokenKit::DeleteToken(tokenId); dataShareHelper = nullptr; + dataShareHelper2 = nullptr; } void ProxyDatasTest::SetUp(void) @@ -95,7 +100,21 @@ void ProxyDatasTest::TearDown(void) { } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Insert_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_Insert_Test_001 + * @tc.desc: Verify the functionality of DataShareHelper successfully inserting data into the data share proxy + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create a Uri object using the data share proxy URI + 3. Prepare a DataShareValuesBucket and add string data to it + 4. Call the Insert method of DataShareHelper with the Uri and ValuesBucket + * @tc.expect: + 1. The return value of the Insert method is greater than 0, indicating successful data insertion + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Insert_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Insert_Test_001::Start"); auto helper = dataShareHelper; @@ -111,7 +130,23 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Insert_Test_001, TestSize.Level0) LOG_INFO("ProxyDatasTest_Insert_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_QUERY_Test_001, TestSize.Level0) +/** +* @tc.name: ProxyDatasTest_QUERY_Test_001 +* @tc.desc: Verify basic query functionality with specific equality condition +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: Test data containing record with TBL_NAME0 value "wang" exists +* @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI + 3. Create DataSharePredicates with condition: TBL_NAME0 equals "wang" + 4. Execute query with empty columns list + 5. Check the returned result set and its row count +* @tc.expect: + 1. Query returns a non-null result set + 2. Result set contains exactly 1 record (row count = 1) +*/ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_QUERY_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_QUERY_Test_001::Start"); auto helper = dataShareHelper; @@ -127,7 +162,261 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_QUERY_Test_001, TestSize.Level0) LOG_INFO("ProxyDatasTest_QUERY_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_ResultSet_Test_001, TestSize.Level0) +/** +* @tc.name: ProxyDatasTest_QueryTimout_Test_001 +* @tc.desc: Verify query timeout functionality with zero timeout configuration +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: Test data containing record with TBL_NAME0 value "wang" exists +* @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI + 3. Create DataSharePredicates with condition: TBL_NAME0 equals "wang" + 4. Configure DataShareOption with timeout set to 0 + 5. Execute QueryTimeout with specified parameters and business error pointer + 6. Verify result set and error code +* @tc.expect: + 1. Query returns a non-null result set + 2. Business error code is E_OK (success status) +*/ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_QueryTimeout_Test_001, TestSize.Level1) +{ + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_001::Start"); + auto helper = dataShareHelper; + Uri uri(DATA_SHARE_PROXY_URI); + DataShare::DataSharePredicates predicates; + predicates.EqualTo(TBL_NAME0, "wang"); + std::vector columns; + DataShareOption option; + option.timeout = 0; + DatashareBusinessError businessError; + auto resultSet = helper->Query(uri, predicates, columns, option, &businessError); + EXPECT_NE(resultSet, nullptr); + EXPECT_EQ(businessError.GetCode(), E_OK); + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_001::End"); +} + +/** +* @tc.name: ProxyDatasTest_QueryTimeout_Test_002 +* @tc.desc: Verify query timeout stability and performance with multiple executions +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: Test data containing record with TBL_NAME0 value "wang" exists +* @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI + 3. Create DataSharePredicates with condition: TBL_NAME0 equals "wang" + 4. Configure DataShareOption with 4000ms timeout + 5. Execute QueryTimeout 100 times in sequence + 6. Measure execution time for each query + 7. Verify result set, error code and row count for each execution +* @tc.expect: + 1. Each query returns a non-null result set + 2. Each query completes within 1000ms + 3. Each query returns business error code E_OK + 4. Each result set contains exactly 1 record +*/ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_QueryTimeout_Test_002, TestSize.Level1) +{ + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_002::Start"); + auto helper = dataShareHelper; + Uri uri(DATA_SHARE_PROXY_URI); + DataShare::DataSharePredicates predicates; + predicates.EqualTo(TBL_NAME0, "wang"); + std::vector columns; + DataShareOption option; + option.timeout = 4000; // 4000 is the query timeout time. + auto limitTime = 1000; // 1000 is used to detect whether the query timeout waiting logic is abnormal. + int repeatTimes = 100; // 100 is the number of times the query is executed. + DatashareBusinessError businessError; + for (int i = 0; i < repeatTimes; i++) { + auto start = std::chrono::steady_clock::now(); + auto resultSet = helper->Query(uri, predicates, columns, option, &businessError); + auto finish = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(finish - start); + EXPECT_TRUE(duration < std::chrono::milliseconds(limitTime)); + EXPECT_NE(resultSet, nullptr); + EXPECT_EQ(businessError.GetCode(), E_OK); + int result = 0; + resultSet->GetRowCount(result); + EXPECT_EQ(result, 1); + } + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_002::End"); +} + +/** +* @tc.name: ProxyDatasTest_QueryTimeout_Test_003 +* @tc.desc: Verify query timeout stability under multi-threaded concurrent access +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: Test data containing record with TBL_NAME0 value "wang" exists +* @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI + 3. Create DataSharePredicates with condition: TBL_NAME0 equals "wang" + 4. Configure DataShareOption with 4000ms timeout + 5. Define query function that executes QueryTimeout 100 times + 6. Create 10 threads to run the query function concurrently + 7. Wait for all threads to complete execution + 8. Verify each query's execution time, result set and error code +* @tc.expect: + 1. All threads complete without execution errors + 2. Each query returns a non-null result set + 3. Each query completes within 1000ms + 4. Each query returns business error code E_OK + 5. Each result set contains exactly 1 record +*/ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_QueryTimeout_Test_003, TestSize.Level1) +{ + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_003::Start"); + auto helper = dataShareHelper; + Uri uri(DATA_SHARE_PROXY_URI); + DataShare::DataSharePredicates predicates; + predicates.EqualTo(TBL_NAME0, "wang"); + std::vector columns; + DataShareOption option; + option.timeout = 4000; // 4000 is the query timeout time. + auto limitTime = 1000; // 1000 is used to detect whether the query timeout waiting logic is abnormal. + int repeatTimes = 100; // 100 is the number of times the query is executed. + DatashareBusinessError businessError; + + std::function func = [&option, &helper, &uri, &predicates, &columns, &businessError, + &limitTime, &repeatTimes]() { + for (int i = 0; i < repeatTimes; i++) { + auto start = std::chrono::steady_clock::now(); + auto resultSet = helper->Query(uri, predicates, columns, option, &businessError); + auto finish = std::chrono::steady_clock::now(); + auto duration = std::chrono::duration_cast(finish - start); + EXPECT_TRUE(duration < std::chrono::milliseconds(limitTime)); + EXPECT_NE(resultSet, nullptr); + EXPECT_EQ(businessError.GetCode(), E_OK); + int result = 0; + resultSet->GetRowCount(result); + EXPECT_EQ(result, 1); + } + }; + int threadNum = 10; // 10 is the number of threads. + std::thread threads[threadNum]; + for (int i = 0; i < threadNum; ++i) { + threads[i] = std::thread(func); + } + + for (int i = 0; i < threadNum; ++i) { + threads[i].join(); + } + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_003::End"); +} + +/** +* @tc.name: ProxyDatasTest_QueryTimeout_Test_004 +* @tc.require: issueIC8OCN +* @tc.desc: Verify query timeout behavior when threshold is intentionally exceeded +* @tc.type: FUNC +* @tc.precon: Data store has sufficient capacity for test data insertion +* @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI + 3. Insert 500 test records with TBL_NAME0 values "query0" to "query499" + 4. Create DataSharePredicates with LIKE condition for TBL_NAME0 containing "query" + 5. Configure DataShareOption with 1ms timeout (intentionally short) + 6. Execute QueryTimeout 10 times and count timeout errors + 7. Delete all inserted test records using cleanup predicate + 8. Verify insertion success, timeout occurrences and cleanup success +* @tc.expect: + 1. All 500 test records are inserted successfully + 2. At least one query execution results in E_TIMEOUT_ERROR + 3. Cleanup delete operation removes all inserted records successfully +*/ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_QueryTimeout_Test_004, TestSize.Level1) +{ + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_004::Start"); + auto helper = dataShareHelper; + Uri uri(DATA_SHARE_PROXY_URI); + std::string name = "timeout"; + int retVal = 0; + int insertTimes = 500; // 500 is the number of times the insert is executed. + for (int i = 0; i < insertTimes; i++) { + DataShare::DataShareValuesBucket valuesBucket; + std::string name0 = "query" + std::to_string(i); + valuesBucket.Put(TBL_NAME0, name0); + valuesBucket.Put(TBL_NAME1, name); + retVal = helper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal > 0), true); + } + + DataShare::DataSharePredicates predicates; + predicates.Like(TBL_NAME0, "query"); + std::vector columns; + DataShareOption option; + option.timeout = 1; // 1 is the query timeout time. + int count = 0; + int queryTimes = 10; // 10 is the number of times the query is executed. + for (int i = 0; i < queryTimes; i++) { + DatashareBusinessError businessError; + auto resultSet = helper->Query(uri, predicates, columns, option, &businessError); + if (businessError.GetCode() == E_TIMEOUT_ERROR) { + count++; + } + } + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_004 Query Timeout %{public}d times", count); + EXPECT_TRUE(count > 0); + DataShare::DataSharePredicates delPredicates; + delPredicates.EqualTo(TBL_NAME1, name); + retVal = helper->Delete(uri, delPredicates); + EXPECT_EQ((retVal > 0), true); + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_004::End"); +} + + +/** +* @tc.name: ProxyDatasTest_QueryTimeout_Test_005 +* @tc.desc: test QueryTimeout function +* @tc.type: FUNC +* @tc.require: issueICS05H +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareHelper class + 2.call QueryTimeout function +* @tc.experct: QueryTimeout return nullptr when The function of the parent class was called +*/ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_QueryTimeout_Test_005, TestSize.Level1) +{ + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_005::Start"); + auto helper = dataShareHelper; + Uri uri(DATA_SHARE_PROXY_URI); + DataShare::DataSharePredicates predicates; + predicates.EqualTo(TBL_NAME0, "wang"); + std::vector columns; + DataShareOption option; + option.timeout = 0; // The function has no specific implementation, timeoutis meaningless + DatashareBusinessError businessError; + auto resultSet = helper->DataShareHelper::Query(uri, predicates, columns, option, &businessError); + EXPECT_EQ(resultSet, nullptr); + LOG_INFO("ProxyDatasTest_QueryTimeout_Test_005::End"); +} + +/** +* @tc.name: ProxyDatasTest_ResultSet_Test_001 +* @tc.desc: Verify result set functionality and error handling for invalid operations +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: Test data containing record with TBL_NAME0 value "wang" exists +* @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create URI for proxy data access using DATA_SHARE_PROXY_URI + 3. Execute query to get result set for TBL_NAME0 equals "wang" + 4. Verify basic result set properties and row count + 5. Check block management functionality (HasBlock, GetBlock) + 6. Test error handling with invalid column index for GetBlob + 7. Nullify block and verify subsequent value retrieval errors +* @tc.expect: + 1. Query returns non-null result set with row count = 1 + 2. Result set reports HasBlock = true and non-null block + 3. GetBlob with invalid column index returns E_INVALID_COLUMN_INDEX + 4. After SetBlock(nullptr), GetBlock returns null + 5. GetString and GetInt operations after nullifying block return E_ERROR +*/ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_ResultSet_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_ResultSet_Test_001::Start"); auto helper = dataShareHelper; @@ -159,7 +448,23 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_ResultSet_Test_001, TestSize.Level0) LOG_INFO("ProxyDatasTest_ResultSet_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_Template_Test_001 + * @tc.desc: Verify the functionality of adding and deleting query templates in the data share proxy + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create PredicateTemplateNode objects with SQL queries + 3. Assemble the nodes into a Template object + 4. Call AddQueryTemplate to register the template with the proxy URI and subscriber ID + 5. Call DelQueryTemplate to remove the registered template + * @tc.expect: + 1. AddQueryTemplate returns 0, indicating successful template registration + 2. DelQueryTemplate returns 0, indicating successful template deletion + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Template_Test_001::Start"); auto helper = dataShareHelper; @@ -177,7 +482,22 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_001, TestSize.Level0) LOG_INFO("ProxyDatasTest_Template_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_002, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_Template_Test_002 + * @tc.desc: Verify that adding and deleting query templates with an invalid URI fails as expected + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Obtain the DataShareHelper instance + 2. Create PredicateTemplateNode objects and assemble them into a Template + 3. Call AddQueryTemplate with an invalid URI and subscriber ID + 4. Call DelQueryTemplate with the same invalid URI and subscriber ID + * @tc.expect: + 1. AddQueryTemplate returns E_URI_NOT_EXIST, indicating failure due to invalid URI + 2. DelQueryTemplate returns E_URI_NOT_EXIST, indicating failure due to invalid URI + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_002, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Template_Test_002::Start"); auto helper = dataShareHelper; @@ -197,12 +517,24 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_002, TestSize.Level0) } /** -* @tc.name: ProxyDatasTest_Template_Test_003 -* @tc.desc: test Template update function -* @tc.type: FUNC -* @tc.require: -*/ -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_003, TestSize.Level0) + * @tc.name: ProxyDatasTest_Template_Test_003 + * @tc.desc: Verify the update functionality of query templates in the data share proxy + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a Template with an update SQL statement and register it via AddQueryTemplate + 2. Subscribe to RDB data changes using the template ID + 3. Insert new data that triggers the template's update condition + 4. Query the data to verify the update was applied + 5. Unsubscribe from RDB data changes + * @tc.expect: + 1. Template registration returns 0 (success) + 2. Subscription and unsubscription operations return 0 (success) + 3. Insert operation succeeds (return value > 0) + 4. Query returns a result set with 1 row, confirming the update was applied + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_003, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Template_Test_003::Start"); auto helper = dataShareHelper; @@ -253,12 +585,21 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_003, TestSize.Level0) } /** -* @tc.name: ProxyDatasTest_Template_Test_004 -* @tc.desc: test add template with parameter update function -* @tc.type: FUNC -* @tc.require: -*/ -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_004, TestSize.Level0) + * @tc.name: ProxyDatasTest_Template_Test_004 + * @tc.desc: Verify adding and deleting query templates with parameterized update functions + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a Template with predicate nodes and register it via AddQueryTemplate + 2. Delete the registered template via DelQueryTemplate + 3. Create another Template with an explicit update SQL statement and register it + 4. Delete the second template + * @tc.expect: + 1. All AddQueryTemplate calls return 0 (success) + 2. All DelQueryTemplate calls return 0 (success) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_004, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Template_Test_004::Start"); auto helper = dataShareHelper; @@ -283,12 +624,20 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_004, TestSize.Level0) } /** -* @tc.name: ProxyDatasTest_Template_Test_005 -* @tc.desc: test add template with wrong parameter update function -* @tc.type: FUNC -* @tc.require: -*/ -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_005, TestSize.Level0) + * @tc.name: ProxyDatasTest_Template_Test_005 + * @tc.desc: Verify that adding a template with an invalid parameterized update function (non-update SQL) fails + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a Template with an insert SQL statement as the update function + 2. Attempt to register the template via AddQueryTemplate + 3. Attempt to delete the (unregistered) template via DelQueryTemplate + * @tc.expect: + 1. AddQueryTemplate returns -1 (failure) due to invalid update SQL + 2. DelQueryTemplate returns 0 (success) (no error if template does not exist) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_005, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Template_Test_005::Start"); auto helper = dataShareHelper; @@ -306,7 +655,56 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_005, TestSize.Level0) LOG_INFO("ProxyDatasTest_Template_Test_005::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_Template_Test_006 + * @tc.desc: Verify adding and deleting query templates using a URI with a user ID parameter + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a URI by appending "?user=100" to the base data share proxy URI + 2. Create a Template with predicate nodes and register it using the new URI + 3. Delete the registered template using the same URI + * @tc.expect: + 1. AddQueryTemplate returns E_OK (success) + 2. DelQueryTemplate returns E_OK (success) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Template_Test_006, TestSize.Level1) +{ + LOG_INFO("ProxyDatasTest_Template_Test_006::Start"); + auto helper = dataShareHelper; + PredicateTemplateNode node1("p1", "select name0 as name from TBL00"); + PredicateTemplateNode node2("p2", "select name1 as name from TBL00"); + std::vector nodes; + nodes.emplace_back(node1); + nodes.emplace_back(node2); + Template tpl(nodes, "select name1 as name from TBL00"); + + std::string uri = DATA_SHARE_PROXY_URI + "?user=100"; + auto result = helper->AddQueryTemplate(uri, SUBSCRIBER_ID, tpl); + EXPECT_EQ(result, E_OK); + result = helper->DelQueryTemplate(uri, SUBSCRIBER_ID); + EXPECT_EQ(result, E_OK); + LOG_INFO("ProxyDatasTest_Template_Test_006::End"); +} + +/** + * @tc.name: ProxyDatasTest_Publish_Test_001 + * @tc.desc: Verify the functionality of publishing string data via the data share proxy and retrieving it + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a Data object containing a URI, subscriber ID, and string value + 2. Publish the data using Publish method with the target bundle name + 3. Retrieve the published data using GetPublishedData + 4. Verify the retrieved data matches the published data + * @tc.expect: + 1. Publish returns OperationResult with errCode_ 0 (success) + 2. GetPublishedData returns errCode_ 0 (success) + 3. Retrieved data has the same size, subscriber ID, key, and value as published data + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Publish_Test_001::Start"); auto helper = dataShareHelper; @@ -334,7 +732,21 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_001, TestSize.Level0) LOG_INFO("ProxyDatasTest_Publish_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_002, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_Publish_Test_002 + * @tc.desc: Verify that publishing data with a non-existent bundle name fails as expected + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a Data object with a URI, subscriber ID, and string value + 2. Attempt to publish the data using a non-existent bundle name + 3. Attempt to retrieve published data using the same invalid bundle name + * @tc.expect: + 1. Publish returns OperationResult with errCode_ E_BUNDLE_NAME_NOT_EXIST (failure) + 2. GetPublishedData returns errCode_ E_BUNDLE_NAME_NOT_EXIST (failure) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_002, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Publish_Test_002::Start"); auto helper = dataShareHelper; @@ -353,7 +765,23 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_002, TestSize.Level0) LOG_INFO("ProxyDatasTest_Publish_Test_002::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_003, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_Publish_Test_003 + * @tc.desc: Verify the functionality of publishing binary data (ashmem) via the data share proxy and retrieving it + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a Data object containing a URI, subscriber ID, and binary buffer + 2. Publish the data using Publish method with the target bundle name + 3. Retrieve the published data using GetPublishedData + 4. Verify the retrieved binary data matches the published data + * @tc.expect: + 1. Publish returns OperationResult with errCode_ 0 (success) + 2. GetPublishedData returns errCode_ 0 (success) + 3. Retrieved data has the same size, subscriber ID, and binary content as published data + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_003, TestSize.Level1) { LOG_INFO("ProxyDatasTest_Publish_Test_003::Start"); auto helper = dataShareHelper; @@ -381,7 +809,25 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_003, TestSize.Level0) LOG_INFO("ProxyDatasTest_Publish_Test_003::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationRdbData_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_CombinationRdbData_Test_001 + * @tc.desc: Verify combination functionality of RDB data subscription, enabling/disabling, and unsubscription + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Register a query template and subscribe to RDB data changes with a callback + 2. Enable RDB subscriptions + 3. Insert data to trigger the subscription callback + 4. Verify the callback is invoked the expected number of times + 5. Unsubscribe from RDB data changes and insert more data + * @tc.expect: + 1. Template registration, subscription, and enabling return 0 (success) + 2. Insert operations return values > 0 (success) + 3. Callback is invoked 2 times before unsubscription + 4. No additional callback invocations after unsubscription + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationRdbData_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_CombinationRdbData_Test_001::Start"); auto helper = dataShareHelper; @@ -432,7 +878,220 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationRdbData_Test_001, TestSize.Le LOG_INFO("ProxyDatasTest_CombinationRdbData_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_SubscribePublishedData_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_CombinationRdbData_Test_002 + * @tc.desc: Verify combination functionality of RDB data subscription, multiple disable operations, and re-enable + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Register a template and subscribe to RDB data changes with two helpers + 2. Disable subscriptions, insert data, and disable again + 3. Re-enable subscriptions and verify callback behavior + 4. Unsubscribe from both helpers + * @tc.expect: + 1. Template registration, subscriptions, disable/enable return 0 (success) + 2. Insert operation returns value > 0 (success) + 3. Callback is invoked 2 times total (1 before disable, 1 after re-enable) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationRdbData_Test_002, TestSize.Level1) +{ + auto helper = dataShareHelper; + auto helper2 = dataShareHelper2; + std::vector nodes; + Template tpl(nodes, "select name1 as name from TBL00"); + auto result = helper->AddQueryTemplate(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID, tpl); + EXPECT_EQ(result, 0); + + std::vector uris = {DATA_SHARE_PROXY_URI}; + TemplateId tplId; + tplId.subscriberId_ = SUBSCRIBER_ID; + tplId.bundleName_ = "ohos.datashareproxyclienttest.demo"; + std::atomic_int callbackTimes = 0; + std::mutex mutex; + std::condition_variable cv; + auto timeout = std::chrono::seconds(2); + std::vector results = + helper->SubscribeRdbData(uris, tplId, [&callbackTimes, &mutex, &cv](const RdbChangeNode &changeNode) { + std::lock_guard lock(mutex); + callbackTimes++; + cv.notify_all(); + }); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &result : results) EXPECT_EQ(result.errCode_, 0); + // if there is only one subscriber in a key, the subscriber can't be disabled twice + results = helper2->SubscribeRdbData(uris, tplId, [](const RdbChangeNode &changeNode) { + }); + + std::unique_lock lock(mutex); + cv.wait_for(lock, timeout); + EXPECT_EQ(callbackTimes, 1); + lock.unlock(); + results = helper->DisableRdbSubs(uris, tplId); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &result : results) EXPECT_EQ(result.errCode_, 0); + + Uri uri(DATA_SHARE_PROXY_URI); + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put(TBL_NAME1, 1); + int retVal = helper->Insert(uri, valuesBucket); + EXPECT_GT(retVal, 0); + + results = helper->DisableRdbSubs(uris, tplId); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &result : results) EXPECT_EQ(result.errCode_, 0); + results = helper->EnableRdbSubs(uris, tplId); + for (auto const &result : results) EXPECT_EQ(result.errCode_, 0); + EXPECT_EQ(callbackTimes, 2); + helper->UnsubscribeRdbData(uris, tplId); + helper2->UnsubscribeRdbData(uris, tplId); +} + +/** + * @tc.name: ProxyDatasTest_CombinationRdbData_Test_003 + * @tc.desc: Verify combination functionality of RDB data subscription, disable, re-enable, and unsubscription + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Register a template and subscribe to RDB data changes with a callback + 2. Disable subscriptions, then re-enable them + 3. Unsubscribe from RDB data changes + * @tc.expect: + 1. Template registration, subscription, disable/enable, and unsubscription return 0 (success) + 2. Callback is invoked 1 time (initial subscription) + 3. No additional callback invocations after disable/re-enable + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationRdbData_Test_003, TestSize.Level1) +{ + LOG_INFO("ProxyDatasTest_CombinationRdbData_Test_003::Start"); + auto helper = dataShareHelper; + std::vector nodes; + Template tpl(nodes, "select name1 as name from TBL00"); + auto result = helper->AddQueryTemplate(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID, tpl); + EXPECT_EQ(result, E_OK); + + std::vector uris = {DATA_SHARE_PROXY_URI}; + TemplateId tplId; + tplId.subscriberId_ = SUBSCRIBER_ID; + tplId.bundleName_ = "ohos.datashareproxyclienttest.demo"; + std::atomic_int callbackTimes = 0; + std::mutex mutex; + std::condition_variable cv; + auto timeout = std::chrono::seconds(2); + std::vector results = + helper->SubscribeRdbData(uris, tplId, [&callbackTimes, &mutex, &cv](const RdbChangeNode &changeNode) { + std::lock_guard lock(mutex); + callbackTimes++; + cv.notify_all(); + }); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &result : results) { + EXPECT_EQ(result.errCode_, E_OK); + } + + std::unique_lock lock(mutex); + cv.wait_for(lock, timeout); + EXPECT_EQ(callbackTimes, 1); + lock.unlock(); + results = helper->DisableRdbSubs(uris, tplId); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &result : results) { + EXPECT_EQ(result.errCode_, 0); + } + results = helper->EnableRdbSubs(uris, tplId); + for (auto const &result : results) { + EXPECT_EQ(result.errCode_, 0); + } + EXPECT_EQ(callbackTimes, 1); + results = helper->UnsubscribeRdbData(uris, tplId); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &result : results) { + EXPECT_EQ(result.errCode_, E_OK); + } + LOG_INFO("ProxyDatasTest_CombinationRdbData_Test_003::End"); +} + +/** + * @tc.name: ProxyDatasTest_CombinationPublishedData_Test_001 + * @tc.desc: Verify combination functionality of published data subscription, disable, re-enable, and unsubscription + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Publish data and subscribe to published data changes with two helpers + 2. Disable subscriptions, republish data, then disable again + 3. Re-enable subscriptions and verify callback behavior + 4. Unsubscribe from both helpers + * @tc.expect: + 1. Publish, subscription, disable/enable return 0 (success) + 2. Callback is invoked 2 times total (1 before disable, 1 after re-enable) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationPublishedData_Test_001, TestSize.Level1) +{ + LOG_INFO("ProxyDatasTest_CombinationPublishedData_Test_001::Start"); + auto helper = dataShareHelper; + auto helper2 = dataShareHelper2; + std::string bundleName = "com.acts.ohos.data.datasharetest"; + Data data; + data.datas_.emplace_back(DATA_SHARE_PROXY_URI, SUBSCRIBER_ID, "value1"); + std::vector results = helper->Publish(data, bundleName); + EXPECT_EQ(results.size(), data.datas_.size()); + for (auto const &result : results) EXPECT_EQ(result.errCode_, 0); + std::vector uris = {DATA_SHARE_PROXY_URI}; + std::atomic_int callbackTimes = 0; + std::mutex mutex; + std::condition_variable cv; + auto timeout = std::chrono::seconds(2); + results = helper->SubscribePublishedData(uris, SUBSCRIBER_ID, + [&callbackTimes, &mutex, &cv](const PublishedDataChangeNode &changeNode) { + std::lock_guard lock(mutex); + callbackTimes++; + cv.notify_all(); + }); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &operationResult : results) EXPECT_EQ(operationResult.errCode_, 0); + // if there is only one subscriber in a key, the subscriber can't be disabled twice + results = helper2->SubscribePublishedData(uris, SUBSCRIBER_ID, [](const PublishedDataChangeNode &changeNode) {}); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &operationResult : results) { + EXPECT_EQ(operationResult.errCode_, 0); + } + std::unique_lock lock(mutex); + cv.wait_for(lock, timeout); + EXPECT_EQ(callbackTimes, 1); + lock.unlock(); + results = helper->DisablePubSubs(uris, SUBSCRIBER_ID); + EXPECT_EQ(results.size(), uris.size()); + for (auto const &operationResult : results) EXPECT_EQ(operationResult.errCode_, 0); + + results = helper->Publish(data, bundleName); + EXPECT_EQ(results.size(), data.datas_.size()); + for (auto const &result : results) EXPECT_EQ(result.errCode_, 0); + results = helper->DisablePubSubs(uris, SUBSCRIBER_ID); + for (auto const &operationResult : results) EXPECT_EQ(operationResult.errCode_, 0); + results = helper->EnablePubSubs(uris, SUBSCRIBER_ID); + for (auto const &operationResult : results) EXPECT_EQ(operationResult.errCode_, 0); + EXPECT_EQ(callbackTimes, 2); + helper->UnsubscribePublishedData(uris, SUBSCRIBER_ID); + helper2->UnsubscribePublishedData(uris, SUBSCRIBER_ID); + LOG_INFO("ProxyDatasTest_CombinationPublishedData_Test_001::End"); +} + +/** + * @tc.name: ProxyDatasTest_SubscribePublishedData_Test_001 + * @tc.desc: Verify the functionality of subscribing to published data changes + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a list of URIs to subscribe to + 2. Call SubscribePublishedData with the URIs, subscriber ID, and a verification callback + * @tc.expect: + 1. Subscription returns OperationResult with errCode_ 0 (success) + 2. Callback verifies the owner bundle name when triggered + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_SubscribePublishedData_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_SubscribePublishedData_Test_001::Start"); auto helper = dataShareHelper; @@ -449,7 +1108,19 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_SubscribePublishedData_Test_001, TestSiz LOG_INFO("ProxyDatasTest_SubscribePublishedData_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_DisablePubSubs_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_DisablePubSubs_Test_001 + * @tc.desc: Verify the functionality of disabling published data subscriptions + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a list of URIs with active subscriptions + 2. Call DisablePubSubs with the URIs and subscriber ID + * @tc.expect: + 1. DisablePubSubs returns OperationResult with errCode_ 0 (success) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_DisablePubSubs_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_DisablePubSubs_Test_001::Start"); auto helper = dataShareHelper; @@ -462,7 +1133,19 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_DisablePubSubs_Test_001, TestSize.Level0 LOG_INFO("ProxyDatasTest_DisablePubSubs_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_EnablePubSubs_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_EnablePubSubs_Test_001 + * @tc.desc: Verify the functionality of enabling published data subscriptions + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a list of URIs with disabled subscriptions + 2. Call EnablePubSubs with the URIs and subscriber ID + * @tc.expect: + 1. EnablePubSubs returns OperationResult with errCode_ 0 (success) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_EnablePubSubs_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_EnablePubSubs_Test_001::Start"); auto helper = dataShareHelper; @@ -475,7 +1158,19 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_EnablePubSubs_Test_001, TestSize.Level0) LOG_INFO("ProxyDatasTest_EnablePubSubs_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_UnsubscribePublishedData_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_UnsubscribePublishedData_Test_001 + * @tc.desc: Verify the functionality of unsubscribing from published data changes + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Create a list of URIs with active subscriptions + 2. Call UnsubscribePublishedData with the URIs and subscriber ID + * @tc.expect: + 1. UnsubscribePublishedData returns OperationResult with errCode_ 0 (success) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_UnsubscribePublishedData_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_UnsubscribePublishedData_Test_001::Start"); auto helper = dataShareHelper; @@ -489,7 +1184,22 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_UnsubscribePublishedData_Test_001, TestS LOG_INFO("ProxyDatasTest_UnsubscribePublishedData_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_extSpCtl_Null_Test_001, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_extSpCtl_Null_Test_001 + * @tc.desc: Verify extended special control operations after releasing the helper + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Release the DataShareHelper instance + 2. Call GetFileTypes with an empty URI and string + 3. Call OpenFile and OpenRawFile with an empty URI and string + * @tc.expect: + 1. Release returns true (success) + 2. GetFileTypes returns an empty list + 3. OpenFile and OpenRawFile return -1 (failure) + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_extSpCtl_Null_Test_001, TestSize.Level1) { LOG_INFO("ProxyDatasTest_extSpCtl_Null_Test_001::Start"); auto helper = dataShareHelper; @@ -506,7 +1216,20 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_extSpCtl_Null_Test_001, TestSize.Level0) LOG_INFO("ProxyDatasTest_extSpCtl_Null_Test_001::End"); } -HWTEST_F(ProxyDatasTest, ProxyDatasTest_extSpCtl_Null_Test_002, TestSize.Level0) +/** + * @tc.name: ProxyDatasTest_extSpCtl_Null_Test_002 + * @tc.desc: Verify NormalizeUri and DenormalizeUri operations after releasing the helper + * @tc.type: FUNC + * @tc.require: None + * @tc.precon: None + * @tc.step: + 1. Release the DataShareHelper instance + 2. Call NormalizeUri and DenormalizeUri with an empty URI + * @tc.expect: + 1. Release returns true (success) + 2. NormalizeUri and DenormalizeUri return the input empty URI unchanged + */ +HWTEST_F(ProxyDatasTest, ProxyDatasTest_extSpCtl_Null_Test_002, TestSize.Level1) { LOG_INFO("ProxyDatasTest_extSpCtl_Null_Test_002::Start"); auto helper = dataShareHelper; diff --git a/data_share/test/native/unittest/long_time/concurrent_test/BUILD.gn b/data_share/test/native/unittest/long_time/concurrent_test/BUILD.gn new file mode 100644 index 00000000..4f1e1ea8 --- /dev/null +++ b/data_share/test/native/unittest/long_time/concurrent_test/BUILD.gn @@ -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. + +import("//build/test.gni") +import("//foundation/distributeddatamgr/data_share/datashare.gni") + +ohos_unittest("ConcurrentTest") { + module_out_path = "data_share/native_datashare" + + include_dirs = [ + "${datashare_native_proxy_path}/include", + "${datashare_common_native_path}/include", + ] + + sources = [ + "${datashare_common_native_path}/src/datashare_itypes_utils.cpp", + "${datashare_common_native_path}/src/datashare_string_utils.cpp", + "${datashare_native_proxy_path}/src/data_proxy_observer_stub.cpp", + "${datashare_native_proxy_path}/src/data_share_service_proxy.cpp", + "${datashare_native_proxy_path}/src/published_data_subscriber_manager.cpp", + "${datashare_native_proxy_path}/src/rdb_subscriber_manager.cpp", + "concurrent_subscriber_test.cpp", + ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer", + "${datashare_innerapi_path}/common:datashare_common", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} diff --git a/data_share/test/native/unittest/long_time/concurrent_test/concurrent_subscriber_test.cpp b/data_share/test/native/unittest/long_time/concurrent_test/concurrent_subscriber_test.cpp new file mode 100644 index 00000000..e8538658 --- /dev/null +++ b/data_share/test/native/unittest/long_time/concurrent_test/concurrent_subscriber_test.cpp @@ -0,0 +1,501 @@ +/* + * 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 "callbacks_manager.h" +#include "data_ability_observer_stub.h" +#include "datashare_errno.h" +#include "datashare_helper.h" +#include "datashare_log.h" +#include "datashare_template.h" +#include "datashare_string_utils.h" +#include "iservice_registry.h" +#include "published_data_subscriber_manager.h" +#include "rdb_subscriber_manager.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using RdbBaseCallbacks = CallbacksManager; +using RdbCallback = std::function; +RdbCallback g_rbdCallback = [](const RdbChangeNode &changeNode) {}; +RdbChangeNode g_rdbChangeNode; +using PublishedBaseCallbacks = CallbacksManager; +using PublishedDataCallback = std::function; +PublishedDataCallback g_publishedCallback = [](const PublishedDataChangeNode &changeNode) {}; +PublishedDataChangeNode g_publishedChangeNode; +constexpr int TEST_TIME = 20; +void *g_subscriber; + +/** + * @Usage: add long_time/concurrent_test/ConcurrentTest to unittest.deps of file + * foundation/distributeddatamgr/data_share/test/native/BUILD.gn + */ +class ConcurrentSubscriberTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void ConcurrentSubscriberTest::SetUpTestCase(void) +{ +} + +void ConcurrentSubscriberTest::TearDownTestCase(void) +{ +} + +void ConcurrentSubscriberTest::SetUp(void) +{ + // input testCase setup step,setup invoked before each testCase + testing::UnitTest *test = testing::UnitTest::GetInstance(); + ASSERT_NE(test, nullptr); + const testing::TestInfo *testInfo = test->current_test_info(); + ASSERT_NE(testInfo, nullptr); + string testCaseName = string(testInfo->name()); + LOG_INFO("[SetUp] %{public}s start", testCaseName.c_str()); + GTEST_LOG_(INFO) << testCaseName.append(" start"); +} +void ConcurrentSubscriberTest::TearDown(void) +{ + // input testCase teardown step,teardown invoked after each testCase + testing::UnitTest *test = testing::UnitTest::GetInstance(); + ASSERT_NE(test, nullptr); + const testing::TestInfo *testInfo = test->current_test_info(); + ASSERT_NE(testInfo, nullptr); + string testCaseName = string(testInfo->name()); + LOG_INFO("[SetUp] %{public}s end", testCaseName.c_str()); + GTEST_LOG_(INFO) << testCaseName.append(" end"); +} + +class RdbSubscriberManagerTest : public CallbacksManager { +public: + using Key = RdbObserverMapKey; + using Observer = RdbObserver; + void AddObservers(int64_t subscriberId, std::string &bundleName, std::string &uri, std::atomic &stop); + void DelObservers(int64_t subscriberId, std::string &bundleName, std::string &uri, std::atomic &stop); +}; + +void RdbSubscriberManagerTest::AddObservers( + int64_t subscriberId, std::string &bundleName, std::string &uri, std::atomic &stop) +{ + void *subscriber = g_subscriber; + RdbChangeNode *changeNode = &g_rdbChangeNode; + DataShare::TemplateId templateId; + templateId.subscriberId_ = subscriberId, templateId.bundleName_ = bundleName; + std::vector uris; + uris.emplace_back(uri); + Key rdbKey(uri, templateId); + std::vector keys; + std::for_each(uris.begin(), uris.end(), [&keys, &templateId](auto &uri) { keys.emplace_back(uri, templateId); }); + while (!stop.load()) { + LOG_INFO("Rdb AddObservers start, subscriberId: %{public}d", static_cast(subscriberId)); + RdbBaseCallbacks::AddObservers( + keys, subscriber, std::make_shared(g_rbdCallback), + [](const std::vector &localRegisterKeys, const std::shared_ptr observer) {}, + [&subscriber, &templateId, &rdbKey, &changeNode](const std::vector &firstAddKeys, + const std::shared_ptr observer, std::vector &opResult) { + std::vector firstAddUris; + std::for_each(firstAddKeys.begin(), firstAddKeys.end(), + [&firstAddUris](auto &result) { firstAddUris.emplace_back(result); }); + if (firstAddUris.empty()) { + return; + } + RdbSubscriberManager::GetInstance().lastChangeNodeMap_.InsertOrAssign(rdbKey, *changeNode); + }); + LOG_INFO("Rdb AddObservers end, subscriberId: %{public}d", static_cast(subscriberId)); + } +} + +void RdbSubscriberManagerTest::DelObservers( + int64_t subscriberId, std::string &bundleName, std::string &uri, std::atomic &stop) +{ + void *subscriber = g_subscriber; + DataShare::TemplateId templateId; + templateId.subscriberId_ = subscriberId, templateId.bundleName_ = bundleName; + std::vector uris; + uris.emplace_back(uri); + std::vector keys; + std::for_each(uris.begin(), uris.end(), [&keys, &templateId](auto &uri) { keys.emplace_back(uri, templateId); }); + while (!stop.load()) { + LOG_INFO("Rdb DelObservers start, subscriberId: %{public}d", static_cast(subscriberId)); + RdbBaseCallbacks::DelObservers( + keys, subscriber, [](const std::vector &lastDelKeys, std::vector &opResult) { + std::for_each(lastDelKeys.begin(), lastDelKeys.end(), + [](auto &result) { RdbSubscriberManager::GetInstance().lastChangeNodeMap_.Erase(result); }); + }); + LOG_INFO("Rdb DelObservers end, subscriberId: %{public}d", static_cast(subscriberId)); + } +} + +/** + * @tc.name: ConcurrentRdbObserverTest + * @tc.desc: Verify concurrent SubscribeRdbData and UnsubscribeRdbData operations + * @tc.type: concurrent + * @tc.require: None + * @tc.precon: RdbSubscriberManager is properly initialized + * @tc.step: + 1. Create an instance of RdbSubscriberManagerTest + 2. Define two URIs and two bundle names for testing + 3. Create four threads to concurrently perform: + - Add observers for URI0 with bundleName0 + - Delete observers for URI0 with bundleName0 + - Add observers for URI1 with bundleName1 + - Delete observers for URI1 with bundleName1 + 4. Run the concurrent operations for a specified test duration + 5. Stop all threads and wait for their completion + * @tc.expect: + 1. All concurrent operations complete without crashes + 2. No deadlocks occur during concurrent subscription management + 3. Observer management maintains internal consistency + */ +HWTEST_F(ConcurrentSubscriberTest, ConcurrentRdbObserverTest, TestSize.Level0) +{ + std::atomic stop = false; + int testTime = TEST_TIME; + RdbSubscriberManagerTest instance; + std::string uri0 = "uri0"; + std::string uri1 = "uri1"; + std::string bundleName0 = "bundleName0"; + std::string bundleName1 = "bundleName1"; + std::function func1 = [&instance, &bundleName0, &uri0, &stop]() { + instance.AddObservers(0, bundleName0, uri0, stop); + }; + std::function func2 = [&instance, &bundleName0, &uri0, &stop]() { + instance.DelObservers(0, bundleName0, uri0, stop); + }; + std::function func3 = [&instance, &bundleName1, &uri1, &stop]() { + instance.AddObservers(1, bundleName1, uri1, stop); + }; + std::function func4 = [&instance, &bundleName1, &uri1, &stop]() { + instance.DelObservers(1, bundleName1, uri1, stop); + }; + std::thread t1(func1); + std::thread t2(func2); + std::thread t3(func3); + std::thread t4(func4); + while (testTime > 0) { + sleep(1); + testTime--; + } + stop = true; + t1.join(); + t2.join(); + t3.join(); + t4.join(); +} + +class PublishedDataSubscriberManagerTest : public CallbacksManager { +public: + using Callback = std::function; + using Key = PublishedObserverMapKey; + using Observer = PublishedDataObserver; + void AddObservers(int64_t subscriberId, std::string &uri, std::atomic &stop); + void DelObservers(int64_t subscriberId, std::string &uri, std::atomic &stop); +}; + +void PublishedDataSubscriberManagerTest::AddObservers(int64_t subscriberId, std::string &uri, std::atomic &stop) +{ + void *subscriber = g_subscriber; + PublishedDataChangeNode *changeNode = &g_publishedChangeNode; + std::vector uris; + uris.emplace_back(uri); + Key publishedKey(uri, subscriberId); + std::vector keys; + std::for_each( + uris.begin(), uris.end(), [&keys, &subscriberId](auto &uri) { keys.emplace_back(uri, subscriberId); }); + while (!stop.load()) { + LOG_INFO("Published AddObservers start, subscriberId: %{public}d", static_cast(subscriberId)); + PublishedBaseCallbacks::AddObservers( + keys, subscriber, std::make_shared(g_publishedCallback), + [](const std::vector &localRegisterKeys, const std::shared_ptr observer) {}, + [&subscriber, &publishedKey, &changeNode](const std::vector &firstAddKeys, + const std::shared_ptr observer, std::vector &opResult) { + std::vector firstAddUris; + std::for_each(firstAddKeys.begin(), firstAddKeys.end(), + [&firstAddUris](auto &result) { firstAddUris.emplace_back(result); }); + if (firstAddUris.empty()) { + return; + } + PublishedDataSubscriberManager::GetInstance().lastChangeNodeMap_.Compute( + publishedKey, [](const Key &, PublishedDataChangeNode &value) { + value.datas_.clear(); + return true; + }); + PublishedDataSubscriberManager::GetInstance().lastChangeNodeMap_.Compute( + publishedKey, [&publishedKey](const Key &, PublishedDataChangeNode &value) { + value.datas_.emplace_back(publishedKey.uri_, publishedKey.subscriberId_, "data"); + value.ownerBundleName_ = ""; + return true; + }); + }); + LOG_INFO("Published AddObservers end, subscriberId: %{public}d", static_cast(subscriberId)); + } +} + +void PublishedDataSubscriberManagerTest::DelObservers(int64_t subscriberId, std::string &uri, std::atomic &stop) +{ + void *subscriber = g_subscriber; + std::vector uris; + uris.emplace_back(uri); + std::vector keys; + std::for_each( + uris.begin(), uris.end(), [&keys, &subscriberId](auto &uri) { keys.emplace_back(uri, subscriberId); }); + while (!stop.load()) { + LOG_INFO("Published DelObservers start, subscriberId: %{public}d", static_cast(subscriberId)); + PublishedBaseCallbacks::DelObservers( + keys, subscriber, [](const std::vector &lastDelKeys, std::vector &opResult) { + std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [](auto &result) { + PublishedDataSubscriberManager::GetInstance().lastChangeNodeMap_.Erase(result); + }); + }); + LOG_INFO("Published DelObservers end, subscriberId: %{public}d", static_cast(subscriberId)); + } +} + +/** + * @tc.name: ConcurrentPublishObserverTest + * @tc.desc: Verify concurrent SubscribePublishedData and UnsubscribePublishedData operations + * @tc.type: concurrent + * @tc.require: None + * @tc.precon: PublishedDataSubscriberManager is properly initialized + * @tc.step: + 1. Create an instance of PublishedDataSubscriberManagerTest + 2. Define two URIs for testing + 3. Create four threads to concurrently perform: + - Add observers for URI0 with subscriber ID 0 + - Delete observers for URI0 with subscriber ID 0 + - Add observers for URI1 with subscriber ID 1 + - Delete observers for URI1 with subscriber ID 1 + 4. Run the concurrent operations for a specified test duration + 5. Stop all threads and wait for their completion + * @tc.expect: + 1. All concurrent operations complete without crashes + 2. No deadlocks occur during concurrent subscription management + 3. Published data observer map maintains internal consistency + 4. Change node data is properly managed during concurrent access + */ +HWTEST_F(ConcurrentSubscriberTest, ConcurrentPublishObserverTest, TestSize.Level0) +{ + std::atomic stop = false; + int testTime = TEST_TIME; + PublishedDataSubscriberManagerTest instance; + std::string uri0 = "uri0"; + std::string uri1 = "uri1"; + std::function func1 = [&instance, &uri0, &stop]() { instance.AddObservers(0, uri0, stop); }; + std::function func2 = [&instance, &uri0, &stop]() { instance.DelObservers(0, uri0, stop); }; + std::function func3 = [&instance, &uri1, &stop]() { instance.AddObservers(1, uri1, stop); }; + std::function func4 = [&instance, &uri1, &stop]() { instance.DelObservers(1, uri1, stop); }; + std::thread t1(func1); + std::thread t2(func2); + std::thread t3(func3); + std::thread t4(func4); + while (testTime > 0) { + sleep(1); + testTime--; + } + stop = true; + t1.join(); + t2.join(); + t3.join(); + t4.join(); +} + +template +class ConditionLock { +public: + explicit ConditionLock() {} + ~ConditionLock() {} +public: + void Notify(const T &data) + { + std::lock_guard lock(mutex_); + data_ = data; + isSet_ = true; + cv_.notify_one(); + } + + T Wait() + { + std::unique_lock lock(mutex_); + cv_.wait_for(lock, std::chrono::seconds(INTERVAL), [this]() { return isSet_; }); + T data = data_; + cv_.notify_one(); + return data; + } + + void Clear() + { + std::lock_guard lock(mutex_); + isSet_ = false; + cv_.notify_one(); + } + +private: + bool isSet_ = false; + T data_; + std::mutex mutex_; + std::condition_variable cv_; + static constexpr int64_t INTERVAL = 2; +}; + +class DataShareObserverTest : public DataShare::DataShareObserver { +public: + explicit DataShareObserverTest(std::string uri) + { + uri_ = uri; + } + ~DataShareObserverTest() {} + + void OnChange(const ChangeInfo &changeInfo) override + { + changeInfo_ = changeInfo; + data.Notify(changeInfo); + } + + void Clear() + { + changeInfo_.changeType_ = INVAILD; + changeInfo_.uris_.clear(); + changeInfo_.data_ = nullptr; + changeInfo_.size_ = 0; + changeInfo_.valueBuckets_ = {}; + data.Clear(); + } + + ChangeInfo changeInfo_; + ConditionLock data; + std::string uri_; +}; + +class ConcurrentRegisterObserverExtProvider { +public: + void RegisterObserverExtProvider(std::shared_ptr helper, const Uri &uri, + std::shared_ptr dataObserver, std::atomic &stop) + { + while (!stop.load()) { + LOG_INFO("RegisterObserverExtProvider start, uri: %{public}s", + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + + helper->RegisterObserverExtProvider(uri, dataObserver, true); + + LOG_INFO("RegisterObserverExtProvider end, uri: %{public}s", + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + } + } + + void UnregisterObserverExtProvider(std::shared_ptr helper, const Uri &uri, + std::shared_ptr dataObserver, std::atomic &stop) + { + while (!stop.load()) { + LOG_INFO("UnregisterObserverExtProvider start, uri: %{public}s", + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + + helper->UnregisterObserverExtProvider(uri, dataObserver); + + LOG_INFO("UnregisterObserverExtProvider end, uri: %{public}s", + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + } + } +}; + +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::string DATA_SHARE_URI1 = "datashare:///com.acts.datasharetest1"; +std::string DATA_SHARE_URI2 = "datashare:///com.acts.datasharetest2"; +constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; + +std::shared_ptr CreateDataShareHelper(int32_t systemAbilityId) +{ + LOG_INFO("CreateDataShareHelper start"); + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saManager == nullptr) { + LOG_ERROR("GetSystemAbilityManager get samgr failed."); + return nullptr; + } + auto remoteObj = saManager->GetSystemAbility(systemAbilityId); + if (remoteObj == nullptr) { + LOG_ERROR("GetSystemAbility service failed."); + return nullptr; + } + return DataShare::DataShareHelper::Creator(remoteObj, DATA_SHARE_URI); +} + +/** + * @tc.name: ConcurrentRegisterObserverExtProviderTest + * @tc.desc: Verify concurrent RegisterObserverExtProvider and UnregisterObserverExtProvider operations + * @tc.type: concurrent + * @tc.require: None + * @tc.precon: + 1. DataShare service is properly initialized + 2. STORAGE_MANAGER_MANAGER_ID system ability is available + * @tc.step: + 1. Create a DataShareHelper instance using STORAGE_MANAGER_MANAGER_ID + 2. Define two URIs for testing (DATA_SHARE_URI1 and DATA_SHARE_URI2) + 3. Create two DataShareObserverTest instances for the URIs + 4. Create four threads to concurrently perform: + - Register observer for URI1 + - Unregister observer for URI1 + - Register observer for URI2 + - Unregister observer for URI2 + 5. Run the concurrent operations for a specified test duration + 6. Stop all threads and wait for their completion + * @tc.expect: + 1. DataShareHelper is created successfully (not nullptr) + 2. All concurrent registration and unregistration operations complete without crashes + 3. No deadlocks occur during concurrent observer management + 4. Observer registration state remains consistent during concurrent access + */ +HWTEST_F(ConcurrentSubscriberTest, ConcurrentRegisterObserverExtProviderTest, TestSize.Level0) +{ + LOG_INFO("ConcurrentRegisterObserverExtProviderTest::Start"); + std::atomic stop = false; + int testTime = TEST_TIME; + ConcurrentRegisterObserverExtProvider instance; + Uri uri1(DATA_SHARE_URI1); + Uri uri2(DATA_SHARE_URI2); + std::shared_ptr dataObserver1 = std::make_shared(DATA_SHARE_URI1); + std::shared_ptr dataObserver2 = std::make_shared(DATA_SHARE_URI2); + std::shared_ptr helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID); + ASSERT_NE(helper, nullptr); + + std::function func1 = [&instance, &helper, &uri1, &dataObserver1, &stop]() { + instance.RegisterObserverExtProvider(helper, uri1, dataObserver1, stop); + }; + std::function func2 = [&instance, &helper, &uri1, &dataObserver1, &stop]() { + instance.UnregisterObserverExtProvider(helper, uri1, dataObserver1, stop); + }; + std::function func3 = [&instance, &helper, &uri2, &dataObserver2, &stop]() { + instance.RegisterObserverExtProvider(helper, uri2, dataObserver2, stop); + }; + std::function func4 = [&instance, &helper, &uri2, &dataObserver2, &stop]() { + instance.UnregisterObserverExtProvider(helper, uri2, dataObserver2, stop); + }; + std::thread t1(func1); + std::thread t2(func2); + std::thread t3(func3); + std::thread t4(func4); + sleep(testTime); + stop = true; + t1.join(); + t2.join(); + t3.join(); + t4.join(); + LOG_INFO("ConcurrentRegisterObserverExtProviderTest::end"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/include/mediadatashare_unit_test.h b/data_share/test/native/unittest/mediadatashare_test/include/mediadatashare_unit_test.h index 3ca808d2..98760f7c 100644 --- a/data_share/test/native/unittest/mediadatashare_test/include/mediadatashare_unit_test.h +++ b/data_share/test/native/unittest/mediadatashare_test/include/mediadatashare_unit_test.h @@ -48,7 +48,7 @@ public: class IDataAbilityObserverTest : public AAFwk::DataAbilityObserverStub { public: - IDataAbilityObserverTest(); + IDataAbilityObserverTest() {} ~IDataAbilityObserverTest() {} diff --git a/data_share/test/native/unittest/mediadatashare_test/src/abnormal_branch_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/abnormal_branch_test.cpp index 7cb1c84e..24c1667d 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/abnormal_branch_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/abnormal_branch_test.cpp @@ -14,7 +14,11 @@ */ #include #include +#include #include "accesstoken_kit.h" +#include "ams_mgr_proxy.h" +#include "data_share_manager_impl.h" +#include "data_share_service_proxy.h" #include "datashare_helper.h" #include "datashare_log.h" #include "datashare_template.h" @@ -31,11 +35,16 @@ #include "shared_block.h" #include "datashare_block_writer_impl.h" #include "datashare_connection.h" +#include "ikvstore_data_service_mock.h" +#include "general_controller_service_impl.h" +#include "persistent_data_controller.h" +#include "published_data_controller.h" namespace OHOS { namespace DataShare { using namespace testing::ext; using namespace OHOS::Security::AccessToken; +constexpr int INVALID_VALUE = -1; class AbnormalBranchTest : public testing::Test { public: @@ -58,6 +67,34 @@ void AbnormalBranchTest::TearDown(void) { } +// Used for mock DataShareKvServiceProxy in order to +// cover the situation that DataShareManagerImpl::GetServiceProxy() == nullptr; +void DataShareManagerImplHelper() +{ + auto helper = DataShareManagerImpl::GetInstance(); + helper->dataShareService_ = nullptr; + auto manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + auto remoteObject = manager->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); + sptr mockProxy = sptr + (new MockDataShareKvServiceProxy(remoteObject)); + EXPECT_CALL(*mockProxy, GetFeatureInterface(testing::_)) + .WillOnce(testing::Return(nullptr)); + + helper->dataMgrService_ = (sptr)mockProxy; +} + +/** + * @tc.name: AbnormalBranchTest_shareBlock_Null_Test_001 + * @tc.desc: Verify operations on DataShareBlockWriterImpl when share block is null + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create DataShareBlockWriterImpl instance + 2. Call various write operations (AllocRow, Write with different types) + 3. Check return values of all operations + * @tc.expect: + 1. All operations return E_ERROR + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_shareBlock_Null_Test_001, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_shareBlock_Null_Test_001::Start"); @@ -81,6 +118,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_shareBlock_Null_Test_001, TestSi LOG_INFO("AbnormalBranchTest_shareBlock_Null_Test_001::End"); } +/** + * @tc.name: AbnormalBranchTest_ResultSetStubNull_Test_001 + * @tc.desc: Verify ISharedResultSetStub behavior when input parameters are null + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create ISharedResultSetStub instance with null parameter + 2. Call CreateStub method with null result and valid parcel + 3. Check returned ISharedResultSet pointer + * @tc.expect: + 1. CreateStub returns nullptr + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_ResultSetStubNull_Test_001, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_ResultSetStubNull_Test_001::Start"); @@ -92,6 +141,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_ResultSetStubNull_Test_001, Test LOG_INFO("AbnormalBranchTest_ResultSetStubNull_Test_001::End"); } +/** + * @tc.name: AbnormalBranchTest_RegisterClientDeathObserverNull_Test_001 + * @tc.desc: Verify RegisterClientDeathObserver with null observer + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create DataShareKvServiceProxy with null parameter + 2. Call RegisterClientDeathObserver with empty appId and null observer + 3. Check return value + * @tc.expect: + 1. Method returns -1 (failure) + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_RegisterClientDeathObserverNull_Test_001, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_RegisterClientDeathObserverNull_Test_001::Start"); @@ -102,14 +163,31 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_RegisterClientDeathObserverNull_ LOG_INFO("AbnormalBranchTest_RegisterClientDeathObserverNull_Test_001::End"); } +/** + * @tc.name: AbnormalBranchTest_mReadOnlyInvalid_Test_001 + * @tc.desc: Verify invalid operations on read-only SharedBlock + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create read-only SharedBlock instance + 2. Attempt modification operations (Clear, SetColumnNum, AllocRow, etc.) + 3. Check return values of all operations + * @tc.expect: + 1. All modification operations return SHARED_BLOCK_INVALID_OPERATION + 2. Init operation succeeds + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_mReadOnlyInvalid_Test_001, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_mReadOnlyInvalid_Test_001::Start"); - std::string name; - size_t size = 0; + std::string name = "Test Shared\0"; bool readOnly = true; - AppDataFwk::SharedBlock temp(name, nullptr, size, readOnly); - int result = temp.Clear(); + int32_t size = 1024; + sptr ashmem = Ashmem::CreateAshmem(name.c_str(), size); + ashmem->MapReadAndWriteAshmem(); + AppDataFwk::SharedBlock temp(name, ashmem, size, readOnly); + int result = temp.Init(); + EXPECT_TRUE(result); + result = temp.Clear(); EXPECT_EQ(result, AppDataFwk::SharedBlock::SHARED_BLOCK_INVALID_OPERATION); result = temp.SetColumnNum(1); EXPECT_EQ(result, AppDataFwk::SharedBlock::SHARED_BLOCK_INVALID_OPERATION); @@ -125,11 +203,23 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_mReadOnlyInvalid_Test_001, TestS EXPECT_EQ(result, AppDataFwk::SharedBlock::SHARED_BLOCK_INVALID_OPERATION); result = temp.PutNull(1, 1); EXPECT_EQ(result, AppDataFwk::SharedBlock::SHARED_BLOCK_INVALID_OPERATION); - result = temp.SetRawData(nullptr, size); + result = temp.SetRawData(nullptr, 0); EXPECT_EQ(result, AppDataFwk::SharedBlock::SHARED_BLOCK_INVALID_OPERATION); LOG_INFO("AbnormalBranchTest_mReadOnlyInvalid_Test_001::End"); } +/** + * @tc.name: AbnormalBranchTest_CreatorPossibleNull_Test_002 + * @tc.desc: Verify DataShareHelper::Creator with invalid parameters + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare CreateOptions with null token + 2. Call DataShareHelper::Creator with empty URI and prepared options + 3. Check returned DataShareHelper pointer + * @tc.expect: + 1. Creator returns nullptr (failure to create helper) + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_CreatorPossibleNull_Test_002, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_CreatorPossibleNull_Test_002::Start"); @@ -143,6 +233,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_CreatorPossibleNull_Test_002, Te LOG_INFO("AbnormalBranchTest_CreatorPossibleNull_Test_002::End"); } +/** + * @tc.name: AbnormalBranchTest_AddObserversProxyNull_Test_001 + * @tc.desc: Verify PublishedDataSubscriberManager::AddObservers with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null proxy and empty URIs list + 2. Call AddObservers with null subscriber, proxy and empty URIs + 3. Check size of returned results + * @tc.expect: + 1. Results size equals URIs size (0 in this case) + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_AddObserversProxyNull_Test_001, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_AddObserversProxyNull_Test_001::Start"); @@ -157,6 +259,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_AddObserversProxyNull_Test_001, LOG_INFO("AbnormalBranchTest_AddObserversProxyNull_Test_001::End"); } +/** + * @tc.name: AbnormalBranchTest_AddObserversProxyNull_Test_002 + * @tc.desc: Verify RdbSubscriberManager::AddObservers with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null proxy and empty URIs list + 2. Call AddObservers with null subscriber, proxy and empty URIs + 3. Check size of returned results + * @tc.expect: + 1. Results size equals URIs size (0 in this case) + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_AddObserversProxyNull_Test_002, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_AddObserversProxyNull_Test_002::Start"); @@ -171,6 +285,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_AddObserversProxyNull_Test_002, LOG_INFO("AbnormalBranchTest_AddObserversProxyNull_Test_002::End"); } +/** + * @tc.name: AbnormalBranchTest_DelObserversProxyNull_Test_001 + * @tc.desc: Verify PublishedDataSubscriberManager::DelObservers with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null proxy and empty URIs list + 2. Call DelObservers with null subscriber and proxy (both overloads) + 3. Check size of returned results + * @tc.expect: + 1. Results size equals URIs size (0 in this case) for both overloads + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_DelObserversProxyNull_Test_001, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_DelObserversProxyNull_Test_001::Start"); @@ -186,6 +312,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_DelObserversProxyNull_Test_001, LOG_INFO("AbnormalBranchTest_DelObserversProxyNull_Test_001::End"); } +/** + * @tc.name: AbnormalBranchTest_DelObserversProxyNull_Test_002 + * @tc.desc: Verify RdbSubscriberManager::DelObservers with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null proxy and empty URIs list + 2. Call DelObservers with null subscriber and proxy (both overloads) + 3. Check size of returned results + * @tc.expect: + 1. Results size equals URIs size (0 in this case) for both overloads + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_DelObserversProxyNull_Test_002, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_DelObserversProxyNull_Test_002::Start"); @@ -201,6 +339,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_DelObserversProxyNull_Test_002, LOG_INFO("AbnormalBranchTest_DelObserversProxyNull_Test_002::End"); } +/** + * @tc.name: AbnormalBranchTest_EnableObserversProxyNull_Test_001 + * @tc.desc: Verify PublishedDataSubscriberManager::EnableObservers with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null proxy and empty URIs list + 2. Call EnableObservers with null subscriber, proxy and empty URIs + 3. Check size of returned results + * @tc.expect: + 1. Results size equals URIs size (0 in this case) + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_EnableObserversProxyNull_Test_001, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_EnableObserversProxyNull_Test_001::Start"); @@ -214,6 +364,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_EnableObserversProxyNull_Test_00 LOG_INFO("AbnormalBranchTest_EnableObserversProxyNull_Test_001::End"); } +/** + * @tc.name: AbnormalBranchTest_EnableObserversProxyNull_Test_002 + * @tc.desc: Verify RdbSubscriberManager::EnableObservers with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null proxy and empty URIs list + 2. Call EnableObservers with null subscriber, proxy and empty URIs + 3. Check size of returned results + * @tc.expect: + 1. Results size equals URIs size (0 in this case) + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_EnableObserversProxyNull_Test_002, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_EnableObserversProxyNull_Test_002::Start"); @@ -227,6 +389,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_EnableObserversProxyNull_Test_00 LOG_INFO("AbnormalBranchTest_EnableObserversProxyNull_Test_002::End"); } +/** + * @tc.name: AbnormalBranchTest_DisableObserversProxyNull_Test_001 + * @tc.desc: Verify PublishedDataSubscriberManager::DisableObservers with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null proxy and empty URIs list + 2. Call DisableObservers with null subscriber, proxy and empty URIs + 3. Check size of returned results + * @tc.expect: + 1. Results size equals URIs size (0 in this case) + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_DisableObserversProxyNull_Test_001, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_DisableObserversProxyNull_Test_001::Start"); @@ -240,6 +414,18 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_DisableObserversProxyNull_Test_0 LOG_INFO("AbnormalBranchTest_DisableObserversProxyNull_Test_001::End"); } +/** + * @tc.name: AbnormalBranchTest_DisableObserversProxyNull_Test_002 + * @tc.desc: Verify RdbSubscriberManager::DisableObservers with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null proxy and empty URIs list + 2. Call DisableObservers with null subscriber, proxy and empty URIs + 3. Check size of returned results + * @tc.expect: + 1. Results size equals URIs size (0 in this case) + */ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_DisableObserversProxyNull_Test_002, TestSize.Level0) { LOG_INFO("AbnormalBranchTest_DisableObserversProxyNull_Test_002::Start"); @@ -252,5 +438,899 @@ HWTEST_F(AbnormalBranchTest, AbnormalBranchTest_DisableObserversProxyNull_Test_0 EXPECT_EQ(results.size(), uris.size()); LOG_INFO("AbnormalBranchTest_DisableObserversProxyNull_Test_002::End"); } + +/** + * @tc.name: PublishDelObserversTest001 + * @tc.desc: Verify PublishedDataSubscriberManager observer operations with null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null subscriber and valid proxy + 2. Call DisableObservers with null proxy and valid URIs + 3. Call DelObservers with valid proxy and URIs + 4. Call RecoverObservers with null proxy + 5. Check results sizes + * @tc.expect: + 1. DisableObservers with null proxy returns 0 results + 2. DelObservers with valid proxy returns results matching URIs size + */ +HWTEST_F(AbnormalBranchTest, PublishDelObserversTest001, TestSize.Level0) +{ + LOG_INFO("PublishDelObserversTest001::Start"); + void *subscriber = nullptr; + auto proxy = DataShareManagerImpl::GetServiceProxy(); + std::vector uris = {}; + std::string uri = "datashare:///com.test/db0/tbl0"; + uris.push_back(uri); + int64_t subscriberId = 0; + std::vector results = PublishedDataSubscriberManager::GetInstance().DisableObservers(subscriber, + nullptr, uris, subscriberId); + EXPECT_EQ(results.size(), 0); + results = PublishedDataSubscriberManager::GetInstance().DelObservers(subscriber, + proxy, uris, subscriberId); + EXPECT_EQ(results.size(), uris.size()); + proxy = nullptr; + PublishedDataSubscriberManager::GetInstance().RecoverObservers(proxy); + LOG_INFO("PublishDelObserversTest001::End"); +} + +/** + * @tc.name: PublishedDataSubscriberManagerOperatorTest001 + * @tc.desc: Verify PublishedDataObserver comparison operators + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create two PublishedDataObserver instances with identical callbacks + 2. Compare them using != and == operators + 3. Check comparison results + * @tc.expect: + 1. != operator returns true (observers are distinct) + 2. == operator returns false (observers are distinct) + */ +HWTEST_F(AbnormalBranchTest, PublishedDataSubscriberManagerOperatorTest001, TestSize.Level0) +{ + LOG_INFO("PublishedDataSubscriberManagerOperatorTest001::Start"); + const PublishedDataCallback callback = [](const PublishedDataChangeNode &changeNode){}; + PublishedDataObserver ob(callback); + PublishedDataObserver obCompare(callback); + EXPECT_TRUE(ob != obCompare); + EXPECT_FALSE(ob == obCompare); + LOG_INFO("PublishedDataSubscriberManagerOperatorTest001::End"); +} + +/** + * @tc.name: RdbDelObserversTest001 + * @tc.desc: Verify RdbSubscriberManager::DelObservers with valid and null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null subscriber and valid proxy + 2. Call DelObservers with valid proxy and URIs + 3. Call RecoverObservers with null proxy + 4. Check results size + * @tc.expect: + 1. DelObservers returns results matching URIs size + */ +HWTEST_F(AbnormalBranchTest, RdbDelObserversTest001, TestSize.Level0) +{ + LOG_INFO("RdbDelObserversTest001::Start"); + void *subscriber = nullptr; + auto proxy = DataShareManagerImpl::GetServiceProxy(); + std::vector uris = {}; + std::string uri = "datashare:///com.test/db0/tbl0"; + uris.push_back(uri); + TemplateId templateId; + std::vector results = RdbSubscriberManager::GetInstance().DelObservers(subscriber, + proxy, uris, templateId); + EXPECT_EQ(results.size(), uris.size()); + proxy = nullptr; + PublishedDataSubscriberManager::GetInstance().RecoverObservers(proxy); + LOG_INFO("RdbDelObserversTest001::End"); +} + +/** + * @tc.name: RdbDisableObserversTest001 + * @tc.desc: Verify RdbSubscriberManager::DisableObservers with valid and null proxy + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare null subscriber and valid proxy + 2. Call DisableObservers with null proxy and valid URIs + 3. Call DisableObservers with valid proxy and URIs + 4. Call RecoverObservers with null proxy + 5. Check results sizes + * @tc.expect: + 1. DisableObservers with null proxy returns 0 results + 2. DisableObservers with valid proxy returns results matching URIs size + */ +HWTEST_F(AbnormalBranchTest, RdbDisableObserversTest001, TestSize.Level0) +{ + LOG_INFO("RdbDisableObserversTest001::Start"); + void *subscriber = nullptr; + auto proxy = DataShareManagerImpl::GetServiceProxy(); + std::vector uris = {}; + std::string uri = "datashare:///com.test/db0/tbl0"; + uris.push_back(uri); + TemplateId templateId; + std::vector results = RdbSubscriberManager::GetInstance().DisableObservers(subscriber, + nullptr, uris, templateId); + EXPECT_EQ(results.size(), 0); + results = RdbSubscriberManager::GetInstance().DisableObservers(subscriber, + proxy, uris, templateId); + EXPECT_EQ(results.size(), uris.size()); + proxy = nullptr; + RdbSubscriberManager::GetInstance().RecoverObservers(proxy); + LOG_INFO("RdbDisableObserversTest001::End"); +} + +/** + * @tc.name: RdbSubscriberManagerOperatorTest001 + * @tc.desc: Verify RdbObserver comparison operators + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create two RdbObserver instances with identical callbacks + 2. Compare them using != and == operators + 3. Check comparison results + * @tc.expect: + 1. != operator returns true (observers are distinct) + 2. == operator returns false (observers are distinct) + */ +HWTEST_F(AbnormalBranchTest, RdbSubscriberManagerOperatorTest001, TestSize.Level0) +{ + LOG_INFO("RdbSubscriberManagerOperatorTest001::Start"); + const RdbCallback callback = [](const RdbChangeNode &changeNode){}; + RdbObserver ob(callback); + RdbObserver obCompare(callback); + EXPECT_TRUE(ob != obCompare); + EXPECT_FALSE(ob == obCompare); + LOG_INFO("RdbSubscriberManagerOperatorTest001::End"); +} + +/** + * @tc.name: RegisterClientDeathObserverTest001 + * @tc.desc: Verify DataShareManagerImpl::RegisterClientDeathObserver under various conditions + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create DataShareManagerImpl instance with null service and empty bundle name + 2. Call RegisterClientDeathObserver + 3. Set valid service proxy and call again + 4. Set valid bundle name and call again + 5. Check clientDeathObserverPtr_ state + * @tc.expect: + 1. Observer remains null with empty bundle name + 2. Observer is created when valid bundle name is provided + */ +HWTEST_F(AbnormalBranchTest, RegisterClientDeathObserverTest001, TestSize.Level0) +{ + LOG_INFO("RegisterClientDeathObserverTest001::Start"); + auto datashareManager = new DataShareManagerImpl(); + datashareManager->dataMgrService_ = nullptr; + datashareManager->bundleName_ = ""; + datashareManager->clientDeathObserverPtr_ = nullptr; + datashareManager->RegisterClientDeathObserver(); + datashareManager->dataMgrService_ = datashareManager->GetDistributedDataManager(); + EXPECT_NE(datashareManager->dataMgrService_, nullptr); + datashareManager->RegisterClientDeathObserver(); + EXPECT_EQ(datashareManager->clientDeathObserverPtr_, nullptr); + datashareManager->bundleName_ = "com.testbundlename"; + datashareManager->RegisterClientDeathObserver(); + EXPECT_NE(datashareManager->clientDeathObserverPtr_, nullptr); + datashareManager->RegisterClientDeathObserver(); + LOG_INFO("RegisterClientDeathObserverTest001::End"); +} + +/** +* @tc.name: RegisterClientDeathObserverTest002 +* @tc.desc: Check the main process of RegisterClientDeathObserver +* @tc.type: FUNC +* @tc.precon: None +* @tc.expect: Successfully register client death observer +* @tc.step: 1. Create a DataShareManagerImpl instance; + 2. Try to use the instance to get datashare service proxy; + 3. Check whether all member functions of the object are successfully constructed. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, RegisterClientDeathObserverTest002, TestSize.Level0) +{ + LOG_INFO("RegisterClientDeathObserverTest002::Start"); + auto datashareManager = DataShareManagerImpl::GetInstance(); + datashareManager->SetBundleName("com.testbundlename"); + datashareManager->GetDataShareServiceProxy(); + EXPECT_NE(datashareManager->dataMgrService_, nullptr); + EXPECT_NE(datashareManager->bundleName_, ""); + EXPECT_NE(datashareManager->clientDeathObserverPtr_, nullptr); + LOG_INFO("RegisterClientDeathObserverTest002::End"); +} + +/** +* @tc.name: OnRemoteDiedTest001 +* @tc.desc: Check the main process of OnRemoteDied and the reset process ResetServiceHandle +* @tc.type: FUNC +* @tc.precon: None +* @tc.expect: Successfully process OnRemoteDied +* @tc.step: 1. Create a DataShareManagerImpl instance; + 2. Call the OnRemoteDied() function; + 3. Check whether datashareManager is successfully deconstructed. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, OnRemoteDiedTest001, TestSize.Level0) +{ + LOG_INFO("OnRemoteDiedTest001::Start"); + auto datashareManager = DataShareManagerImpl::GetInstance(); + datashareManager->SetBundleName("com.testbundlename"); + datashareManager->GetDataShareServiceProxy(); + EXPECT_NE(datashareManager->dataMgrService_, nullptr); + EXPECT_NE(datashareManager->bundleName_, ""); + EXPECT_NE(datashareManager->clientDeathObserverPtr_, nullptr); + + datashareManager->OnRemoteDied(); + EXPECT_EQ(datashareManager->dataMgrService_, nullptr); + EXPECT_EQ(datashareManager->dataShareService_, nullptr); + LOG_INFO("OnRemoteDiedTest001::End"); +} + +/** +* @tc.name: SetRegisterCallbackTest001 +* @tc.desc: Check the main process of SetRegisterCallback +* @tc.type: FUNC +* @tc.precon: None +* @tc.expect: Successfully process SetRegisterCallback +* @tc.step: 1. Create a DataShareManagerImpl instance; + 2. Call the SetRegisterCallback() function; + 3. Check whether datashareManager is successfully deconstructed. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, SetRegisterCallbackTest001, TestSize.Level0) +{ + LOG_INFO("SetRegisterCallbackTest001::Start"); + auto datashareManager = DataShareManagerImpl::GetInstance(); + std::function callback = [](){}; + datashareManager->SetRegisterCallback(nullptr, callback); + LOG_INFO("SetRegisterCallbackTest001::End"); +} + +/** + * @tc.name: AmsMgrProxyOnProxyDiedTest001 + * @tc.desc: Verify AmsMgrProxy behavior when proxy dies + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create AmsMgrProxy with null service and proxy + 2. Call OnProxyDied and verify state + 3. Create new proxy, connect to SA, verify initialization + 4. Call OnProxyDied again and verify cleanup + * @tc.expect: + 1. OnProxyDied handles null pointers gracefully + 2. Proxy initializes properly after ConnectSA + 3. OnProxyDied cleans up resources + */ +HWTEST_F(AbnormalBranchTest, AmsMgrProxyOnProxyDiedTest001, TestSize.Level0) +{ + LOG_INFO("AmsMgrProxyOnProxyDiedTest001::Start"); + AmsMgrProxy* proxy = new AmsMgrProxy(); + proxy->sa_ = nullptr; + proxy->proxy_ = nullptr; + proxy->OnProxyDied(); + delete proxy; + proxy = new AmsMgrProxy(); + proxy->sa_ = nullptr; + proxy->proxy_ = nullptr; + proxy->ConnectSA(); + EXPECT_NE(proxy->sa_, nullptr); + EXPECT_NE(proxy->proxy_, nullptr); + EXPECT_NE(proxy->deathRecipient_, nullptr); + proxy->OnProxyDied(); + delete proxy; + LOG_INFO("AmsMgrProxyOnProxyDiedTest001::End"); +} + +/** +* @tc.name: AmsMgrProxyOnProxyDiedTest002 +* @tc.desc: Test sa_ with nullptr and destructor of AmsMgrProxy +* @tc.type: FUNC +* @tc.precon: None +* @tc.expect: Successfully process SetRegisterCallback +* @tc.step: 1. Create a AmsMgrProxy instance; + 2. Clear the proxy; + 3. After clear, try to connect SA; + 4. Check if this proxy can be connected successfully. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, AmsMgrProxyOnProxyDiedTest002, TestSize.Level0) +{ + LOG_INFO("AmsMgrProxyOnProxyDiedTest002::Start"); + AmsMgrProxy* proxy = AmsMgrProxy::GetInstance(); + proxy->OnProxyDied(); + proxy->ConnectSA(); + EXPECT_NE(proxy->sa_, nullptr); + EXPECT_NE(proxy->proxy_, nullptr); + EXPECT_NE(proxy->deathRecipient_, nullptr); + LOG_INFO("AmsMgrProxyOnProxyDiedTest002::End"); +} + +/** + * @tc.name: DataShareServiceProxySubscribeRdbDataTest001 + * @tc.desc: Verify DataShareServiceProxy subscription behavior after proxy death + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Create AmsMgrProxy with null service and proxy + 2. Call OnProxyDied and verify cleanup + 3. Create new proxy, connect to SA, verify initialization + 4. Call OnProxyDied again and verify cleanup + * @tc.expect: + 1. Proxy handles null states gracefully + 2. Proxy initializes properly after ConnectSA + 3. Resources are cleaned up after OnProxyDied + */ +HWTEST_F(AbnormalBranchTest, DataShareServiceProxySubscribeRdbDataTest001, TestSize.Level0) +{ + LOG_INFO("DataShareServiceProxySubscribeRdbDataTest001::Start"); + AmsMgrProxy* proxy = new AmsMgrProxy(); + proxy->sa_ = nullptr; + proxy->proxy_ = nullptr; + proxy->OnProxyDied(); + delete proxy; + proxy = new AmsMgrProxy(); + proxy->sa_ = nullptr; + proxy->proxy_ = nullptr; + proxy->ConnectSA(); + EXPECT_NE(proxy->sa_, nullptr); + EXPECT_NE(proxy->proxy_, nullptr); + EXPECT_NE(proxy->deathRecipient_, nullptr); + proxy->OnProxyDied(); + delete proxy; + LOG_INFO("DataShareServiceProxySubscribeRdbDataTest001::End"); +} + +/** + * @tc.name: SubscribeRdbDataTest001 + * @tc.desc: Verify SubscribeRdbData with empty URIs and null observer + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare empty URIs list and null observer + 2. Call SubscribeRdbData with valid proxy + 3. Check size of returned result set + * @tc.expect: + 1. Result set size is 0 (matches empty URIs list) + */ +HWTEST_F(AbnormalBranchTest, SubscribeRdbDataTest001, TestSize.Level0) +{ + LOG_INFO("EnableSubscribePublishedDataTest001::Start"); + std::vector uris = {}; + TemplateId templateId; + sptr observer = OHOS::sptr(nullptr); + auto proxy = DataShareManagerImpl::GetServiceProxy(); + auto resultset = proxy->SubscribeRdbData(uris, templateId, observer); + EXPECT_EQ(resultset.size(), 0); + LOG_INFO("EnableSubscribePublishedDataTest001::End"); +} + +/** + * @tc.name: SubscribePublishedDataTest001 + * @tc.desc: Verify SubscribePublishedData with empty URIs and null observer + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1. Prepare empty URIs list and null observer + 2. Call SubscribePublishedData with valid proxy + 3. Check size of returned result set + * @tc.expect: + 1. Result set size is 0 (matches empty URIs list) + */ +HWTEST_F(AbnormalBranchTest, SubscribePublishedDataTest001, TestSize.Level0) +{ + LOG_INFO("SubscribePublishedDataTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 1; + sptr observer = OHOS::sptr(nullptr); + auto proxy = DataShareManagerImpl::GetServiceProxy(); + auto resultset = proxy->SubscribePublishedData(uris, subscriberId, observer); + EXPECT_EQ(resultset.size(), 0); + LOG_INFO("SubscribePublishedDataTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplInsertTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return an DATA_SHARE_ERROR. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call Insert() in GeneralControllerServiceImpl; + 3. Check if the function return DATA_SHARE_ERROR. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplInsertTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplInsertTest001::Start"); + DataShareManagerImplHelper(); + DataShare::DataShareValuesBucket valuesBucket; + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + Uri uri(proxyUri); + auto generalCtl = std::make_shared(proxyUri); + int ret = generalCtl->Insert(uri, valuesBucket); + EXPECT_EQ(ret, DATA_SHARE_ERROR); + LOG_INFO("GeneralControllerServiceImplInsertTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplUpdateTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return an DATA_SHARE_ERROR. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call Update() in GeneralControllerServiceImpl; + 3. Check if the function return DATA_SHARE_ERROR. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplUpdateTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplUpdateTest001::Start"); + DataShareManagerImplHelper(); + DataShare::DataSharePredicates predicates; + DataShare::DataShareValuesBucket valuesBucket; + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + Uri uri(proxyUri); + auto generalCtl = std::make_shared(proxyUri); + int ret = generalCtl->Update(uri, predicates, valuesBucket); + EXPECT_EQ(ret, DATA_SHARE_ERROR); + LOG_INFO("GeneralControllerServiceImplUpdateTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplDeleteTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return an DATA_SHARE_ERROR. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call Update() in GeneralControllerServiceImpl; + 3. Check if the function return DATA_SHARE_ERROR. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplDeleteTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplDeleteTest001::Start"); + DataShareManagerImplHelper(); + DataShare::DataSharePredicates predicates; + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + Uri uri(proxyUri); + auto generalCtl = std::make_shared(proxyUri); + int ret = generalCtl->Delete(uri, predicates); + EXPECT_EQ(ret, DATA_SHARE_ERROR); + LOG_INFO("GeneralControllerServiceImplDeleteTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplInsertExTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code + and return pair of DATA_SHARE_ERROR and 0. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call InsertEx() in GeneralControllerServiceImpl; + 3. Check if the function return pair of DATA_SHARE_ERROR and 0. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplInsertExTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplInsertExTest001::Start"); + DataShareManagerImplHelper(); + DataShare::DataShareValuesBucket valuesBucket; + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + Uri uri(proxyUri); + auto generalCtl = std::make_shared(proxyUri); + auto ret = generalCtl->InsertEx(uri, valuesBucket); + EXPECT_EQ(ret, std::make_pair(DATA_SHARE_ERROR, 0)); + LOG_INFO("GeneralControllerServiceImplInsertExTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplUpdateExTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code + and return pair of DATA_SHARE_ERROR and 0. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call UpdateEx() in GeneralControllerServiceImpl; + 3. Check if the function return pair of DATA_SHARE_ERROR and 0. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplUpdateExTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplUpdateExTest001::Start"); + DataShareManagerImplHelper(); + DataShare::DataSharePredicates predicates; + DataShare::DataShareValuesBucket valuesBucket; + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + Uri uri(proxyUri); + auto generalCtl = std::make_shared(proxyUri); + auto ret = generalCtl->UpdateEx(uri, predicates, valuesBucket); + EXPECT_EQ(ret, std::make_pair(DATA_SHARE_ERROR, 0)); + LOG_INFO("GeneralControllerServiceImplUpdateExTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplDeleteExTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code + and return pair of DATA_SHARE_ERROR and 0. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call DeleteEx() in GeneralControllerServiceImpl; + 3. Check if the function return pair of DATA_SHARE_ERROR and 0. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplDeleteExTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplDeleteExTest001::Start"); + DataShareManagerImplHelper(); + DataShare::DataSharePredicates predicates; + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + Uri uri(proxyUri); + auto generalCtl = std::make_shared(proxyUri); + auto ret = generalCtl->DeleteEx(uri, predicates); + EXPECT_EQ(ret, std::make_pair(DATA_SHARE_ERROR, 0)); + LOG_INFO("GeneralControllerServiceImplDeleteExTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplQueryTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return a nullptr. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call Query() in GeneralControllerServiceImpl; + 3. Check if the function return nullptr. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplQueryTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplQueryTest001::Start"); + DataShareManagerImplHelper(); + DataShare::DataSharePredicates predicates; + std::vector columns; + DatashareBusinessError error; + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + Uri uri(proxyUri); + auto generalCtl = std::make_shared(proxyUri); + DataShareOption option; + auto ret = generalCtl->Query(uri, predicates, columns, error, option); + EXPECT_EQ(ret, nullptr); + LOG_INFO("GeneralControllerServiceImplQueryTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplNotifyChangeTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call NotifyChange() in GeneralControllerServiceImpl; + 3. Check if the function return. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplNotifyChangeTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplNotifyChangeTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + Uri uri(proxyUri); + auto generalCtl = std::make_shared(proxyUri); + generalCtl->NotifyChange(uri); + LOG_INFO("GeneralControllerServiceImplNotifyChangeTest001::End"); +} + +/** +* @tc.name: GeneralControllerServiceImplSetRegisterCallbackTest001 +* @tc.desc: Check the main process +* @tc.type: FUNC +* @tc.precon: None +* @tc.expect: Enter the DataShareManagerImpl::GetInstance() branch in the code. +* @tc.step: 1. Call SetRegisterCallback() in GeneralControllerServiceImpl; + 2. Check if the function return. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, GeneralControllerServiceImplSetRegisterCallbackTest001, TestSize.Level1) +{ + LOG_INFO("GeneralControllerServiceImplSetRegisterCallbackTest001::Start"); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + auto generalCtl = std::make_shared(proxyUri); + generalCtl->SetRegisterCallback(); + LOG_INFO("GeneralControllerServiceImplSetRegisterCallbackTest001::End"); +} + +/** +* @tc.name: PersistentDataControllerAddQueryTemplateTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return INVALID_VALUE +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call AddQueryTemplate() in PersistentDataController; + 3. Check if the function return INVALID_VALUE. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PersistentDataControllerAddQueryTemplateTest001, TestSize.Level1) +{ + LOG_INFO("PersistentDataControllerAddQueryTemplateTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector nodes; + Template tpl(nodes, "select name1 as name from TBL00"); + auto controller = PersistentDataController(); + auto ret = controller.AddQueryTemplate(proxyUri, 0, tpl); + EXPECT_EQ(ret, INVALID_VALUE); + LOG_INFO("PersistentDataControllerAddQueryTemplateTest001::End"); +} + +/** +* @tc.name: PersistentDataControllerDelQueryTemplateTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return INVALID_VALUE +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call DelQueryTemplate() in PersistentDataController; + 3. Check if the function return INVALID_VALUE. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PersistentDataControllerDelQueryTemplateTest001, TestSize.Level1) +{ + LOG_INFO("PersistentDataControllerDelQueryTemplateTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + auto controller = PersistentDataController(); + auto ret = controller.DelQueryTemplate(proxyUri, 0); + EXPECT_EQ(ret, INVALID_VALUE); + LOG_INFO("PersistentDataControllerDelQueryTemplateTest001::End"); +} + +/** +* @tc.name: PersistentDataControllerSubscribeRdbDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call SubscribeRdbData() in PersistentDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PersistentDataControllerSubscribeRdbDataTest001, TestSize.Level1) +{ + LOG_INFO("PersistentDataControllerSubscribeRdbDataTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector uris = {proxyUri}; + TemplateId tplId; + auto callback = std::function(); + auto controller = PersistentDataController(); + auto ret = controller.SubscribeRdbData(nullptr, uris, tplId, callback); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PersistentDataControllerSubscribeRdbDataTest001::End"); +} + +/** +* @tc.name: PersistentDataControllerUnSubscribeRdbDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call UnSubscribeRdbData() in PersistentDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PersistentDataControllerUnSubscribeRdbDataTest001, TestSize.Level1) +{ + LOG_INFO("PersistentDataControllerUnSubscribeRdbDataTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector uris = {proxyUri}; + TemplateId tplId; + auto controller = PersistentDataController(); + auto ret = controller.UnSubscribeRdbData(nullptr, uris, tplId); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PersistentDataControllerUnSubscribeRdbDataTest001::End"); +} + +/** +* @tc.name: PersistentDataControllerEnableSubscribeRdbDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call EnableSubscribeRdbData() in PersistentDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PersistentDataControllerEnableSubscribeRdbDataTest001, TestSize.Level1) +{ + LOG_INFO("PersistentDataControllerEnableSubscribeRdbDataTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector uris = {proxyUri}; + TemplateId tplId; + auto controller = PersistentDataController(); + auto ret = controller.EnableSubscribeRdbData(nullptr, uris, tplId); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PersistentDataControllerEnableSubscribeRdbDataTest001::End"); +} + +/** +* @tc.name: PersistentDataControllerDisableSubscribeRdbDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call DisableSubscribeRdbData() in PersistentDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PersistentDataControllerDisableSubscribeRdbDataTest001, TestSize.Level1) +{ + LOG_INFO("PersistentDataControllerDisableSubscribeRdbDataTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector uris = {proxyUri}; + TemplateId tplId; + auto controller = PersistentDataController(); + auto ret = controller.DisableSubscribeRdbData(nullptr, uris, tplId); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PersistentDataControllerDisableSubscribeRdbDataTest001::End"); +} + +/** +* @tc.name: PublishedDataControllerPublishTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call Publish() in PublishedDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PublishedDataControllerPublishTest001, TestSize.Level1) +{ + LOG_INFO("PublishedDataControllerPublishTest001::Start"); + DataShareManagerImplHelper(); + Data data; + std::string bundleName = "com.acts.ohos.data.datasharetest"; + auto controller = PublishedDataController(); + auto ret = controller.Publish(data, bundleName); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PublishedDataControllerPublishTest001::End"); +} + +/** +* @tc.name: PublishedDataControllerGetPublishedDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code + and return empty datas_ vector in Data. +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call GetPublishedData() in PublishedDataController; + 3. Check if the function return empty datas_ vector in Data. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PublishedDataControllerGetPublishedDataTest001, TestSize.Level1) +{ + LOG_INFO("PublishedDataControllerGetPublishedDataTest001::Start"); + DataShareManagerImplHelper(); + std::string bundleName = "com.acts.ohos.data.datasharetest"; + int errCode = 0; + auto controller = PublishedDataController(); + auto ret = controller.GetPublishedData(bundleName, errCode); + EXPECT_EQ(ret.datas_.size(), 0); + LOG_INFO("PublishedDataControllerGetPublishedDataTest001::End"); +} + +/** +* @tc.name: PublishedDataControllerSubscribePublishedDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call SubscribePublishedData() in PublishedDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PublishedDataControllerSubscribePublishedDataTest001, TestSize.Level1) +{ + LOG_INFO("PublishedDataControllerSubscribePublishedDataTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector uris = {proxyUri}; + auto callback = std::function(); + auto controller = PublishedDataController(); + auto ret = controller.SubscribePublishedData(nullptr, uris, 0, callback); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PublishedDataControllerSubscribePublishedDataTest001::End"); +} + +/** +* @tc.name: PublishedDataControllerSubscribeUnSubscribePublishedDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call UnSubscribePublishedData() in PublishedDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PublishedDataControllerSubscribeUnSubscribePublishedDataTest001, TestSize.Level1) +{ + LOG_INFO("PublishedDataControllerSubscribeUnSubscribePublishedDataTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector uris = {proxyUri}; + auto controller = PublishedDataController(); + auto ret = controller.UnSubscribePublishedData(nullptr, uris, 0); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PublishedDataControllerSubscribeUnSubscribePublishedDataTest001::End"); +} + +/** +* @tc.name: PublishedDataControllerSubscribeEnableSubscribePublishedDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call EnableSubscribePublishedData() in PublishedDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PublishedDataControllerSubscribeEnableSubscribePublishedDataTest001, TestSize.Level1) +{ + LOG_INFO("PublishedDataControllerSubscribeEnableSubscribePublishedDataTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector uris = {proxyUri}; + auto controller = PublishedDataController(); + auto ret = controller.EnableSubscribePublishedData(nullptr, uris, 0); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PublishedDataControllerSubscribeEnableSubscribePublishedDataTest001::End"); +} + +/** +* @tc.name: PublishedDataControllerSubscribeDisableSubscribePublishedDataTest001 +* @tc.desc: Fill the branch DataShareManagerImpl::GetServiceProxy() == nullptr +* @tc.type: FUNC +* @tc.precon: Mock the DataShareManagerImpl::GetServiceProxy() return nullptr +* @tc.expect: Enter the DataShareManagerImpl::GetServiceProxy() branch in the code and return empty vector +* @tc.step: 1. Mock GetServiceProxy() to return nullptr; + 2. Call DisableSubscribePublishedData() in PublishedDataController; + 3. Check if the function return empty vector. +* @tc.require: issueIBX9HL +*/ +HWTEST_F(AbnormalBranchTest, PublishedDataControllerSubscribeDisableSubscribePublishedDataTest001, TestSize.Level1) +{ + LOG_INFO("PublishedDataControllerSubscribeDisableSubscribePublishedDataTest001::Start"); + DataShareManagerImplHelper(); + std::string proxyUri = "datashareproxy://com.acts.ohos.data.datasharetest/test"; + std::vector uris = {proxyUri}; + auto controller = PublishedDataController(); + auto ret = controller.DisableSubscribePublishedData(nullptr, uris, 0); + EXPECT_EQ(ret.size(), 0); + LOG_INFO("PublishedDataControllerSubscribeDisableSubscribePublishedDataTest001::End"); +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/controller_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/controller_test.cpp index 2f8a4590..09b1d881 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/controller_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/controller_test.cpp @@ -22,12 +22,14 @@ #include "data_ability_observer_interface.h" #include "dataobs_mgr_changeinfo.h" #include "datashare_connection.h" +#include "datashare_errno.h" #include "datashare_helper.h" #include "datashare_log.h" #include "ext_special_controller.h" #include "extension_manager_proxy.h" #include "general_controller.h" #include "general_controller_provider_impl.h" +#include "general_controller_service_impl.h" #include "hap_token_info.h" #include "iservice_registry.h" #include "rdb_data_ability_utils.h" @@ -52,6 +54,19 @@ void ControllerTest::TearDownTestCase(void) {} void ControllerTest::SetUp(void) {} void ControllerTest::TearDown(void) {} +/** +* @tc.name: ControllerTest_ProviderImplInsertTest_001 +* @tc.desc: Verify Insert operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Prepare DataShareValuesBucket with test data + 3. Call Insert method with empty URI and values bucket + 4. Check if returned result is negative (indicating failure) +* @tc.expect: + 1. Insert operation returns negative value +*/ HWTEST_F(ControllerTest, ControllerTest_ProviderImplInsertTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_ProviderImplInsertTest_001::Start"); @@ -66,6 +81,20 @@ HWTEST_F(ControllerTest, ControllerTest_ProviderImplInsertTest_001, TestSize.Lev LOG_INFO("ControllerTest_ProviderImplInsertTest_001::End"); } +/** +* @tc.name: ControllerTest_ProviderImplInsertTest_002 +* @tc.desc: Verify Insert operation with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Prepare DataShareValuesBucket with test data + 4. Call Insert method with empty URI and values bucket + 5. Check if returned result is negative (indicating failure) +* @tc.expect: + 1. Insert operation returns negative value +*/ HWTEST_F(ControllerTest, ControllerTest_ProviderImplInsertTest_002, TestSize.Level0) { LOG_INFO("ControllerTest_ProviderImplInsertTest_002::Start"); @@ -86,6 +115,19 @@ HWTEST_F(ControllerTest, ControllerTest_ProviderImplInsertTest_002, TestSize.Lev LOG_INFO("ControllerTest_ProviderImplInsertTest_002::End"); } +/** +* @tc.name: ControllerTest_ProviderImplUpdateTest_001 +* @tc.desc: Verify Update operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Prepare DataSharePredicates and DataShareValuesBucket with test data + 3. Call Update method with empty URI, predicates and values bucket + 4. Check if returned result is negative (indicating failure) +* @tc.expect: + 1. Update operation returns negative value +*/ HWTEST_F(ControllerTest, ControllerTest_ProviderImplUpdateTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_ProviderImplUpdateTest_001::Start"); @@ -101,6 +143,20 @@ HWTEST_F(ControllerTest, ControllerTest_ProviderImplUpdateTest_001, TestSize.Lev LOG_INFO("ControllerTest_ProviderImplUpdateTest_001::End"); } +/** +* @tc.name: ControllerTest_ProviderImplUpdateTest_002 +* @tc.desc: Verify Update operation with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Prepare DataSharePredicates and DataShareValuesBucket with test data + 4. Call Update method with empty URI, predicates and values bucket + 5. Check if returned result is negative (indicating failure) +* @tc.expect: + 1. Update operation returns negative value +*/ HWTEST_F(ControllerTest, ControllerTest_ProviderImplUpdateTest_002, TestSize.Level0) { LOG_INFO("ControllerTest_ProviderImplUpdateTest_002::Start"); @@ -122,6 +178,19 @@ HWTEST_F(ControllerTest, ControllerTest_ProviderImplUpdateTest_002, TestSize.Lev LOG_INFO("ControllerTest_ProviderImplUpdateTest_002::End"); } +/** +* @tc.name: ControllerTest_ProviderImplDeleteTest_001 +* @tc.desc: Verify Delete operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Prepare DataSharePredicates with test conditions + 3. Call Delete method with empty URI and predicates + 4. Check if returned result is negative (indicating failure) +* @tc.expect: + 1. Delete operation returns negative value +*/ HWTEST_F(ControllerTest, ControllerTest_ProviderImplDeleteTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_ProviderImplDeleteTest_001::Start"); @@ -135,6 +204,20 @@ HWTEST_F(ControllerTest, ControllerTest_ProviderImplDeleteTest_001, TestSize.Lev LOG_INFO("ControllerTest_ProviderImplDeleteTest_001::End"); } +/** +* @tc.name: ControllerTest_ProviderImplDeleteTest_002 +* @tc.desc: Verify Delete operation with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Prepare DataSharePredicates with test conditions + 4. Call Delete method with empty URI and predicates + 5. Check if returned result is negative (indicating failure) +* @tc.expect: + 1. Delete operation returns negative value +*/ HWTEST_F(ControllerTest, ControllerTest_ProviderImplDeleteTest_002, TestSize.Level0) { LOG_INFO("ControllerTest_ProviderImplDeleteTest_002::Start"); @@ -154,6 +237,210 @@ HWTEST_F(ControllerTest, ControllerTest_ProviderImplDeleteTest_002, TestSize.Lev LOG_INFO("ControllerTest_ProviderImplDeleteTest_002::End"); } +/** +* @tc.name: Generalcontroller_ServiceImplInsertExTest_001 +* @tc.desc: Verify InsertEx operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Prepare DataShareValuesBucket with test data + 3. Call InsertEx method with empty URI and values bucket + 4. Check if returned result is (DATA_SHARE_ERROR, 0) +* @tc.expect: + 1. InsertEx operation returns pair(DATA_SHARE_ERROR, 0) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplInsertExTest_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplInsertExTest_001::Start"); + Uri uri(""); + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + DataShare::DataShareValuesBucket valuesBucket; + double valueD1 = 20.07; + valuesBucket.Put("phoneNumber", valueD1); + std::pair result = tempGenConProImp->InsertEx(uri, valuesBucket); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + LOG_INFO("Generalcontroller_ServiceImplInsertExTest_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplInsertExTest_002 +* @tc.desc: Verify InsertEx operation with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Prepare DataShareValuesBucket with test data + 4. Call InsertEx method with empty URI and values bucket + 5. Check if returned result is (DATA_SHARE_ERROR, 0) +* @tc.expect: + 1. InsertEx operation returns pair(DATA_SHARE_ERROR, 0) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplInsertExTest_002, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplInsertExTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + DataShare::DataShareValuesBucket valuesBucket; + double valueD1 = 20.07; + valuesBucket.Put("phoneNumber", valueD1); + std::pair result = tempGenConProImp->InsertEx(uri, valuesBucket); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + LOG_INFO("Generalcontroller_ServiceImplInsertExTest_002::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplUpdateExTest_001 +* @tc.desc: Verify UpdateEx operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Prepare DataSharePredicates and DataShareValuesBucket with test data + 3. Call UpdateEx method with empty URI, predicates and values bucket + 4. Check if returned result is (DATA_SHARE_ERROR, 0) +* @tc.expect: + 1. UpdateEx operation returns pair(DATA_SHARE_ERROR, 0) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplUpdateExTest_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplUpdateExTest_001::Start"); + Uri uri(""); + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + DataShare::DataSharePredicates predicates; + predicates.EqualTo("name", "Controller_Test001"); + DataShare::DataShareValuesBucket valuesBucket; + double valueD1 = 20.07; + valuesBucket.Put("phoneNumber", valueD1); + std::pair result = tempGenConProImp->UpdateEx(uri, predicates, valuesBucket); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + LOG_INFO("Generalcontroller_ServiceImplUpdateExTest_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplUpdateExTest_002 +* @tc.desc: Verify UpdateEx operation with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Prepare DataSharePredicates and DataShareValuesBucket with test data + 4. Call UpdateEx method with empty URI, predicates and values bucket + 5. Check if returned result is (DATA_SHARE_ERROR, 0) +* @tc.expect: + 1. UpdateEx operation returns pair(DATA_SHARE_ERROR, 0) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplUpdateExTest_002, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplUpdateExTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + DataShare::DataSharePredicates predicates; + predicates.EqualTo("name", "Controller_Test001"); + DataShare::DataShareValuesBucket valuesBucket; + double valueD1 = 20.07; + valuesBucket.Put("phoneNumber", valueD1); + std::pair result = tempGenConProImp->UpdateEx(uri, predicates, valuesBucket); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + LOG_INFO("Generalcontroller_ServiceImplUpdateExTest_002::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplDeleteExTest_001 +* @tc.desc: Verify DeleteEx operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Prepare DataSharePredicates with test conditions + 3. Call DeleteEx method with empty URI and predicates + 4. Check if returned result is (DATA_SHARE_ERROR, 0) +* @tc.expect: + 1. DeleteEx operation returns pair(DATA_SHARE_ERROR, 0) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplDeleteExTest_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplDeleteExTest_001::Start"); + Uri uri(""); + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + DataShare::DataSharePredicates predicates; + predicates.EqualTo("name", "Controller_Test001"); + std::pair result = tempGenConProImp->DeleteEx(uri, predicates); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + LOG_INFO("Generalcontroller_ServiceImplDeleteExTest_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplDeleteExTest_002 +* @tc.desc: Verify DeleteEx operation with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Prepare DataSharePredicates with test conditions + 4. Call DeleteEx method with empty URI and predicates + 5. Check if returned result is (DATA_SHARE_ERROR, 0) +* @tc.expect: + 1. DeleteEx operation returns pair(DATA_SHARE_ERROR, 0) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplDeleteExTest_002, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplDeleteExTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + DataShare::DataSharePredicates predicates; + predicates.EqualTo("name", "Controller_Test001"); + std::pair result = tempGenConProImp->DeleteEx(uri, predicates); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + LOG_INFO("Generalcontroller_ServiceImplDeleteExTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ProviderImplQueryTest_001 +* @tc.desc: Verify Query operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Prepare DataSharePredicates and column list + 3. Call Query method with empty URI, predicates and columns + 4. Check if returned result is nullptr +* @tc.expect: + 1. Query operation returns nullptr +*/ HWTEST_F(ControllerTest, ControllerTest_ProviderImplQueryTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_ProviderImplQueryTest_001::Start"); @@ -164,11 +451,26 @@ HWTEST_F(ControllerTest, ControllerTest_ProviderImplQueryTest_001, TestSize.Leve predicates.EqualTo("name", "Controller_Test001"); vector columns; DatashareBusinessError error; - auto result = tempGenConProImp->Query(uri, predicates, columns, error); + DataShareOption option; + auto result = tempGenConProImp->Query(uri, predicates, columns, error, option); EXPECT_EQ(result, nullptr); LOG_INFO("ControllerTest_ProviderImplQueryTest_001::End"); } +/** +* @tc.name: ControllerTest_ProviderImplQueryTest_002 +* @tc.desc: Verify Query operation with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Prepare DataSharePredicates and column list + 4. Call Query method with empty URI, predicates and columns + 5. Check if returned result is nullptr +* @tc.expect: + 1. Query operation returns nullptr +*/ HWTEST_F(ControllerTest, ControllerTest_ProviderImplQueryTest_002, TestSize.Level0) { LOG_INFO("ControllerTest_ProviderImplQueryTest_002::Start"); @@ -185,11 +487,631 @@ HWTEST_F(ControllerTest, ControllerTest_ProviderImplQueryTest_002, TestSize.Leve predicates.EqualTo("name", "Controller_Test001"); vector columns; DatashareBusinessError error; - auto result = tempGenConProImp->Query(uri, predicates, columns, error); + DataShareOption option; + auto result = tempGenConProImp->Query(uri, predicates, columns, error, option); EXPECT_EQ(result, nullptr); LOG_INFO("ControllerTest_ProviderImplQueryTest_002::End"); } +/** +* @tc.name: Generalcontroller_ServiceImplRegisterObserverTest_001 +* @tc.desc: Verify RegisterObserver operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Call RegisterObserver method with empty URI and null observer + 3. Verify URI remains empty +* @tc.expect: + 1. URI remains empty after operation +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplRegisterObserverTest_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplRegisterObserverTest_001::Start"); + Uri uri(""); + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + sptr dataObserver; + tempGenConProImp->RegisterObserver(uri, dataObserver); + EXPECT_EQ(uri, Uri("")); + LOG_INFO("Generalcontroller_ServiceImplRegisterObserverTest_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplRegisterObserverTest_002 +* @tc.desc: Verify RegisterObserver with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Call RegisterObserver method with empty URI and null observer + 4. Verify URI remains empty +* @tc.expect: + 1. URI remains empty after operation +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplRegisterObserverTest_002, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplRegisterObserverTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + sptr dataObserver; + tempGenConProImp->RegisterObserver(uri, dataObserver); + EXPECT_EQ(uri, Uri("")); + LOG_INFO("Generalcontroller_ServiceImplRegisterObserverTest_002::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplUnregisterObserverTest_001 +* @tc.desc: Verify UnregisterObserver operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Call UnregisterObserver method with empty URI and null observer + 3. Verify URI remains empty +* @tc.expect: + 1. URI remains empty after operation +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplUnregisterObserverTest_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplUnregisterObserverTest_001::Start"); + Uri uri(""); + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + sptr dataObserver; + tempGenConProImp->UnregisterObserver(uri, dataObserver); + EXPECT_EQ(uri, Uri("")); + LOG_INFO("Generalcontroller_ServiceImplUnregisterObserverTest_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplUnregisterObserverTest_002 +* @tc.desc: Verify UnregisterObserver with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Call UnregisterObserver method with empty URI and null observer + 4. Verify URI remains empty +* @tc.expect: + 1. URI remains empty after operation +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplUnregisterObserverTest_002, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplUnregisterObserverTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + sptr dataObserver; + tempGenConProImp->UnregisterObserver(uri, dataObserver); + EXPECT_EQ(uri, Uri("")); + LOG_INFO("Generalcontroller_ServiceImplUnregisterObserverTest_002::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplNotifyChangeTest_001 +* @tc.desc: Verify NotifyChange operation with null connection in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerProviderImpl with null connection and empty URI + 2. Call NotifyChange method with empty URI + 3. Verify URI remains empty +* @tc.expect: + 1. URI remains empty after operation +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplNotifyChangeTest_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplNotifyChangeTest_001::Start"); + Uri uri(""); + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + tempGenConProImp->NotifyChange(uri); + EXPECT_EQ(uri, Uri("")); + LOG_INFO("Generalcontroller_ServiceImplNotifyChangeTest_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImplNotifyChangeTest_002 +* @tc.desc: Verify NotifyChange with valid connection but unconnected state in GeneralControllerProviderImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create GeneralControllerProviderImpl with the connection and empty URI + 3. Call NotifyChange method with empty URI + 4. Verify URI remains empty +* @tc.expect: + 1. URI remains empty after operation +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImplNotifyChangeTest_002, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImplNotifyChangeTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + tempGenConProImp->NotifyChange(uri); + EXPECT_EQ(uri, Uri("")); + LOG_INFO("Generalcontroller_ServiceImplNotifyChangeTest_002::End"); +} + +/** +* @tc.name: Generalcontroller_ProviderImpl_RegisterObserverExtProvider_Test_001 +* @tc.desc: Verify RegisterObserverExtProvider with null connection and unconnected state +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create provider with null connection and call RegisterObserverExtProvider + 2. Create provider with valid but unconnected connection and call RegisterObserverExtProvider + 3. Check return codes for both cases +* @tc.expect: + 1. First call returns E_PROVIDER_CONN_NULL + 2. Second call returns E_PROVIDER_NOT_CONNECTED +*/ +HWTEST_F(ControllerTest, Generalcontroller_ProviderImpl_RegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ProviderImpl_RegisterObserverExtProvider_Test_001::Start"); + + Uri uri(""); + // connection is nullptr + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + ASSERT_NE(tempGenConProImp, nullptr); + sptr dataObserver; + // make isDescendants false + int ret = tempGenConProImp->RegisterObserverExtProvider(uri, dataObserver, false); + EXPECT_EQ(ret, E_PROVIDER_CONN_NULL); + + // connection not null + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + ASSERT_NE(connection, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + ret = tempGenConProImp->RegisterObserverExtProvider(uri, dataObserver, false); + EXPECT_EQ(ret, E_PROVIDER_NOT_CONNECTED); + + LOG_INFO("Generalcontroller_ProviderImpl_RegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: Generalcontroller_ProviderImpl_UnregisterObserverExtProvider_Test_001 +* @tc.desc: Verify UnregisterObserverExtProvider with null connection and unconnected state +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create provider with null connection and call UnregisterObserverExtProvider + 2. Create provider with valid but unconnected connection and call UnregisterObserverExtProvider + 3. Check return codes for both cases +* @tc.expect: + 1. First call returns E_PROVIDER_CONN_NULL + 2. Second call returns E_PROVIDER_NOT_CONNECTED +*/ +HWTEST_F(ControllerTest, Generalcontroller_ProviderImpl_UnregisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ProviderImpl_UnregisterObserverExtProvider_Test_001::Start"); + + Uri uri(""); + // connection is nullptr + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + ASSERT_NE(tempGenConProImp, nullptr); + sptr dataObserver; + // make isDescendants false + int ret = tempGenConProImp->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(ret, E_PROVIDER_CONN_NULL); + + // connection not null but dataShareProxy is nullptr + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + ASSERT_NE(connection, nullptr); + connection->dataShareProxy_ = nullptr; + ASSERT_EQ(connection->dataShareProxy_, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + ret = tempGenConProImp->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(ret, E_PROVIDER_NOT_CONNECTED); + + LOG_INFO("Generalcontroller_ProviderImpl_UnregisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: Generalcontroller_ProviderImpl_NotifyChangeExtProvider_Test_001 +* @tc.desc: Verify NotifyChangeExtProvider with null connection and unconnected state +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create provider with null connection and call NotifyChangeExtProvider + 2. Create provider with valid but unconnected connection and call NotifyChangeExtProvider + 3. Check return codes for both cases +* @tc.expect: + 1. First call returns E_PROVIDER_CONN_NULL + 2. Second call returns E_PROVIDER_NOT_CONNECTED +*/ +HWTEST_F(ControllerTest, Generalcontroller_ProviderImpl_NotifyChangeExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ProviderImpl_NotifyChangeExtProvider_Test_001::Start"); + + Uri uri(""); + // connection is nullptr + ChangeInfo changeInfo = { ChangeInfo::ChangeType::INSERT, { uri } }; + std::shared_ptr tempGenConProImp = + std::make_shared(nullptr, uri, nullptr); + sptr dataObserver; + // make isDescendants false + int ret = tempGenConProImp->NotifyChangeExtProvider(changeInfo); + EXPECT_EQ(ret, E_PROVIDER_CONN_NULL); + + // connection not null + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + tempGenConProImp = + std::make_shared(dataShareConnection, uri, nullptr); + ret = tempGenConProImp->NotifyChangeExtProvider(changeInfo); + EXPECT_EQ(ret, E_PROVIDER_NOT_CONNECTED); + + LOG_INFO("Generalcontroller_ProviderImpl_NotifyChangeExtProvider_Test_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImpl_RegisterObserverExtProvider_Test_001 +* @tc.desc: Verify RegisterObserverExtProvider operation in GeneralControllerServiceImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerServiceImpl with test URI + 2. Call RegisterObserverExtProvider with empty URI and null observer + 3. Check return code +* @tc.expect: + 1. Operation returns -1 (failure) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImpl_RegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImpl_RegisterObserverExtProvider_Test_001::Start"); + + Uri uri(""); + std::string extUri = "GeneralControllerServiceImpl"; + + std::shared_ptr tempGenConProImp = + std::make_shared(extUri); + ASSERT_NE(tempGenConProImp, nullptr); + sptr dataObserver; + + int ret = tempGenConProImp->RegisterObserverExtProvider(uri, dataObserver, false); + EXPECT_EQ(ret, -1); + + LOG_INFO("Generalcontroller_ServiceImpl_RegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImpl_UnregisterObserverExtProvider_Test_001 +* @tc.desc: Verify UnregisterObserverExtProvider operation in GeneralControllerServiceImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerServiceImpl with test URI + 2. Call UnregisterObserverExtProvider with empty URI and null observer + 3. Check return code +* @tc.expect: + 1. Operation returns -1 (failure) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImpl_UnregisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImpl_UnregisterObserverExtProvider_Test_001::Start"); + + Uri uri(""); + std::string extUri = "GeneralControllerServiceImpl"; + + std::shared_ptr tempGenConProImp = + std::make_shared(extUri); + ASSERT_NE(tempGenConProImp, nullptr); + sptr dataObserver; + + int ret = tempGenConProImp->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(ret, -1); + + LOG_INFO("Generalcontroller_ServiceImpl_UnregisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: Generalcontroller_ServiceImpl_NotifyChangeExtProvider_Test_001 +* @tc.desc: Verify NotifyChangeExtProvider operation in GeneralControllerServiceImpl +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerServiceImpl with test URI + 2. Prepare ChangeInfo with empty URI + 3. Call NotifyChangeExtProvider with the change info + 4. Check return code +* @tc.expect: + 1. Operation returns -1 (failure) +*/ +HWTEST_F(ControllerTest, Generalcontroller_ServiceImpl_NotifyChangeExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("Generalcontroller_ServiceImpl_NotifyChangeExtProvider_Test_001::Start"); + + Uri uri(""); + std::string extUri = "GeneralControllerServiceImpl"; + + ChangeInfo changeInfo = { ChangeInfo::ChangeType::INSERT, { uri } }; + // connection is nullptr + std::shared_ptr tempGenConProImp = + std::make_shared(extUri); + ASSERT_NE(tempGenConProImp, nullptr); + sptr dataObserver; + + int ret = tempGenConProImp->NotifyChangeExtProvider(changeInfo); + EXPECT_EQ(ret, -1); + + LOG_INFO("Generalcontroller_ServiceImpl_NotifyChangeExtProvider_Test_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerOpenFileTest_001 +* @tc.desc: Verify OpenFile operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Call OpenFile with empty URI and test mode + 3. Check if returned result is negative +* @tc.expect: + 1. OpenFile operation returns negative value +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerOpenFileTest_001, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerOpenFileTest_001::Start"); + Uri uri(""); + std::shared_ptr tempExtSpeCon = + std::make_shared(nullptr, uri, nullptr); + std::string mode = "test001"; + int result = tempExtSpeCon->OpenFile(uri, mode); + EXPECT_EQ((result < 0), true); + LOG_INFO("ControllerTest_ExtSpecialControllerOpenFileTest_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerOpenFileTest_002 +* @tc.desc: Verify OpenFile operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Call OpenFile with empty URI and test mode + 4. Check if returned result is negative +* @tc.expect: + 1. OpenFile operation returns negative value +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerOpenFileTest_002, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerOpenFileTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempExtSpeCon = + std::make_shared(dataShareConnection, uri, nullptr); + std::string mode = "test001"; + int result = tempExtSpeCon->OpenFile(uri, mode); + EXPECT_EQ((result < 0), true); + LOG_INFO("ControllerTest_ExtSpecialControllerOpenFileTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerOpenFileWithErrCodeTest_001 +* @tc.desc: Verify OpenFileWithErrCode function with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Call OpenFileWithErrCode with empty URI, test mode and error code + 3. Check if returned file descriptor is -1 +* @tc.expect: + 1. OpenFileWithErrCode returns -1 +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerOpenFileWithErrCodeTest_001, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerOpenFileWithErrCodeTest_001::Start"); + Uri uri(""); + std::shared_ptr tempExtSpeCon = + std::make_shared(nullptr, uri, nullptr); + std::string mode = "test001"; + int32_t errCode = 0; + int fd = tempExtSpeCon->OpenFileWithErrCode(uri, mode, errCode); + EXPECT_EQ(fd, -1); + LOG_INFO("ControllerTest_ExtSpecialControllerOpenFileWithErrCodeTest_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerOpenFileWithErrCodeTest_002 +* @tc.desc: Verify OpenFileWithErrCode function with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Call OpenFileWithErrCode with empty URI, test mode and error code + 4. Check if returned file descriptor is -1 +* @tc.expect: + 1. OpenFileWithErrCode returns -1 +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerOpenFileWithErrCodeTest_002, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerOpenFileWithErrCodeTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempExtSpeCon = + std::make_shared(dataShareConnection, uri, nullptr); + std::string mode = "test001"; + int32_t errCode = 0; + int fd = tempExtSpeCon->OpenFileWithErrCode(uri, mode, errCode); + EXPECT_EQ(fd, -1); + LOG_INFO("ControllerTest_ExtSpecialControllerOpenFileWithErrCodeTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerOpenRawFileTest_001 +* @tc.desc: Verify OpenRawFile operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Call OpenRawFile with empty URI and test mode + 3. Check if returned result is negative +* @tc.expect: + 1. OpenRawFile operation returns negative value +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerOpenRawFileTest_001, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerOpenRawFileTest_001::Start"); + Uri uri(""); + std::shared_ptr tempExtSpeCon = + std::make_shared(nullptr, uri, nullptr); + std::string mode = "test001"; + int result = tempExtSpeCon->OpenRawFile(uri, mode); + EXPECT_EQ((result < 0), true); + LOG_INFO("ControllerTest_ExtSpecialControllerOpenRawFileTest_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControlleOpenRawFileTest_002 +* @tc.desc: Verify OpenRawFile operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Call OpenRawFile with empty URI and test mode + 4. Check if returned result is negative +* @tc.expect: + 1. OpenRawFile operation returns negative value +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControlleOpenRawFileTest_002, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerOpenRawFileTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempExtSpeCon = + std::make_shared(dataShareConnection, uri, nullptr); + std::string mode = "test001"; + int result = tempExtSpeCon->OpenRawFile(uri, mode); + EXPECT_EQ((result < 0), true); + LOG_INFO("ControllerTest_ExtSpecialControllerOpenRawFileTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerGetTypeTest_001 +* @tc.desc: Verify GetType operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Call GetType with empty URI + 3. Check if returned result is empty string +* @tc.expect: + 1. GetType operation returns empty string +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerGetTypeTest_001, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerGetTypeTest_001::Start"); + Uri uri(""); + std::shared_ptr tempExtSpeCon = + std::make_shared(nullptr, uri, nullptr); + std::string result = tempExtSpeCon->GetType(uri); + EXPECT_EQ(result, ""); + LOG_INFO("ControllerTest_ExtSpecialControllerGetTypeTest_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControlleGetTypeTest_002 +* @tc.desc: Verify GetType operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Call GetType with empty URI + 4. Check if returned result is empty string +* @tc.expect: + 1. GetType operation returns empty string +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControlleGetTypeTest_002, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerGetTypeTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempExtSpeCon = + std::make_shared(dataShareConnection, uri, nullptr); + std::string result = tempExtSpeCon->GetType(uri); + EXPECT_EQ(result, ""); + LOG_INFO("ControllerTest_ExtSpecialControllerGetTypeTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerBatchInsertTest_001 +* @tc.desc: Verify BatchInsert operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Prepare vector of DataShareValuesBucket with test data + 3. Call BatchInsert with empty URI and values vector + 4. Check if returned result is negative +* @tc.expect: + 1. BatchInsert operation returns negative value +*/ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerBatchInsertTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_ExtSpecialControllerBatchInsertTest_001::Start"); @@ -210,6 +1132,20 @@ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerBatchInsertTest_001, LOG_INFO("ControllerTest_ExtSpecialControllerBatchInsertTest_001::End"); } +/** +* @tc.name: ControllerTest_ExtSpecialControllerBatchInsertTest_002 +* @tc.desc: Verify BatchInsert operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Prepare vector of DataShareValuesBucket with test data + 4. Call BatchInsert with empty URI and values vector + 5. Check if returned result is negative +* @tc.expect: + 1. BatchInsert operation returns negative value +*/ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerBatchInsertTest_002, TestSize.Level0) { LOG_INFO("ControllerTest_ExtSpecialControllerBatchInsertTest_002::Start"); @@ -236,6 +1172,256 @@ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerBatchInsertTest_002, LOG_INFO("ControllerTest_ExtSpecialControllerBatchInsertTest_002::End"); } +/** +* @tc.name: ControllerTest_ExtSpecialControllerBatchUpdateTest_001 +* @tc.desc: Verify BatchUpdate operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Prepare empty UpdateOperations and results vector + 3. Call BatchUpdate with operations and results + 4. Check if returned result is -1 +* @tc.expect: + 1. BatchUpdate operation returns -1 +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerBatchUpdateTest_001, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerBatchUpdateTest_001::Start"); + Uri uri(""); + std::shared_ptr tempExtSpeCon = + std::make_shared(nullptr, uri, nullptr); + DataShare::UpdateOperations operations; + std::vector results; + int result = tempExtSpeCon->BatchUpdate(operations, results); + EXPECT_EQ(result, -1); + LOG_INFO("ControllerTest_ExtSpecialControllerBatchUpdateTest_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerBatchUpdateTest_002 +* @tc.desc: Verify BatchUpdate operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Prepare empty UpdateOperations and results vector + 4. Call BatchUpdate with operations and results + 5. Check if returned result is -1 +* @tc.expect: + 1. BatchUpdate operation returns -1 +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerBatchUpdateTest_002, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerBatchUpdateTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempExtSpeCon = + std::make_shared(dataShareConnection, uri, nullptr); + DataShare::UpdateOperations operations; + std::vector results; + int result = tempExtSpeCon->BatchUpdate(operations, results); + EXPECT_EQ(result, -1); + LOG_INFO("ControllerTest_ExtSpecialControllerBatchUpdateTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerInsertExtTest_001 +* @tc.desc: Verify InsertExt operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Prepare DataShareValuesBucket with test data and result string + 3. Call InsertExt with empty URI, values bucket and result string + 4. Check if returned result is -1 +* @tc.expect: + 1. InsertExt operation returns -1 +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerInsertExtTest_001, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerInsertExtTest_001::Start"); + Uri uri(""); + std::shared_ptr tempExtSpeCon = + std::make_shared(nullptr, uri, nullptr); + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put("name", "dataShareTest006"); + valuesBucket.Put("phoneNumber", 20.6); + std::string result1 = "test001"; + int result = tempExtSpeCon->InsertExt(uri, valuesBucket, result1); + EXPECT_EQ(result, -1); + LOG_INFO("ControllerTest_ExtSpecialControllerInsertExtTest_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerInsertExtTest_002 +* @tc.desc: Verify InsertExt operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Prepare DataShareValuesBucket with test data and result string + 4. Call InsertExt with empty URI, values bucket and result string + 5. Check if returned result is -1 +* @tc.expect: + 1. InsertExt operation returns -1 +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerInsertExtTest_002, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerInsertExtTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempExtSpeCon = + std::make_shared(dataShareConnection, uri, nullptr); + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put("name", "dataShareTest006"); + valuesBucket.Put("phoneNumber", 20.6); + std::string result1 = "test001"; + int result = tempExtSpeCon->InsertExt(uri, valuesBucket, result1); + EXPECT_EQ(result, -1); + LOG_INFO("ControllerTest_ExtSpecialControllerInsertExtTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerExecuteBatchTest_001 +* @tc.desc: Verify ExecuteBatch operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Prepare empty OperationStatement vector and ExecResultSet + 3. Call ExecuteBatch with statements and result set + 4. Check if returned result is -1 +* @tc.expect: + 1. ExecuteBatch operation returns -1 +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerExecuteBatchTest_001, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerExecuteBatchTest_001::Start"); + Uri uri(""); + std::shared_ptr tempExtSpeCon = + std::make_shared(nullptr, uri, nullptr); + std::vector statements; + std::vector results; + ExecResultSet result1; + int result = tempExtSpeCon->ExecuteBatch(statements, result1); + EXPECT_EQ(result, -1); + LOG_INFO("ControllerTest_ExtSpecialControllerExecuteBatchTest_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerExecuteBatchTest_002 +* @tc.desc: Verify ExecuteBatch operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Prepare empty OperationStatement vector and ExecResultSet + 4. Call ExecuteBatch with statements and result set + 5. Check if returned result is -1 +* @tc.expect: + 1. ExecuteBatch operation returns -1 +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerExecuteBatchTest_002, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerExecuteBatchTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempExtSpeCon = + std::make_shared(dataShareConnection, uri, nullptr); + std::vector statements; + std::vector results; + ExecResultSet result1; + int result = tempExtSpeCon->ExecuteBatch(statements, result1); + EXPECT_EQ(result, -1); + LOG_INFO("ControllerTest_ExtSpecialControllerExecuteBatchTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerGetFileTypesTest_001 +* @tc.desc: Verify GetFileTypes operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Call GetFileTypes with empty URI and test type string + 3. Check if returned result is empty vector +* @tc.expect: + 1. GetFileTypes operation returns empty vector +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerGetFileTypesTest_001, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerGetFileTypesTest_001::Start"); + Uri uri(""); + std::shared_ptr tempExtSpeCon = + std::make_shared(nullptr, uri, nullptr); + std::string getFileTypes = "test001"; + std::vector result = tempExtSpeCon->GetFileTypes(uri, getFileTypes); + EXPECT_EQ(result, std::vector()); + LOG_INFO("ControllerTest_ExtSpecialControllerGetFileTypesTest_001::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControlleGetFileTypesTest_002 +* @tc.desc: Verify GetFileTypes operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Call GetFileTypes with empty URI and test type string + 4. Check if returned result is empty vector +* @tc.expect: + 1. GetFileTypes operation returns empty vector +*/ +HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControlleGetFileTypesTest_002, TestSize.Level0) +{ + LOG_INFO("ControllerTest_ExtSpecialControllerGetFileTypesTest_002::Start"); + Uri uri(""); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, nullptr); + auto dataShareConnection = + std::shared_ptr(connection.GetRefPtr(), [holder = connection](const auto *) { + holder->DisconnectDataShareExtAbility(); + }); + std::shared_ptr tempExtSpeCon = + std::make_shared(dataShareConnection, uri, nullptr); + std::string getFileTypes = "test001"; + std::vector result = tempExtSpeCon->GetFileTypes(uri, getFileTypes); + EXPECT_EQ(result, std::vector()); + LOG_INFO("ControllerTest_ExtSpecialControllerGetFileTypesTest_002::End"); +} + +/** +* @tc.name: ControllerTest_ExtSpecialControllerNormalizeUriTest_001 +* @tc.desc: Verify NormalizeUri operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Call NormalizeUri with empty URI + 3. Check if returned result is empty URI +* @tc.expect: + 1. NormalizeUri operation returns empty URI +*/ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerNormalizeUriTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_ExtSpecialControllerNormalizeUriTest_001::Start"); @@ -247,6 +1433,19 @@ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerNormalizeUriTest_001 LOG_INFO("ControllerTest_ExtSpecialControllerNormalizeUriTest_001::End"); } +/** +* @tc.name: ControllerTest_ExtSpecialControllerNormalizeUriTest_002 +* @tc.desc: Verify NormalizeUri operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Call NormalizeUri with empty URI + 4. Check if returned result is empty URI +* @tc.expect: + 1. NormalizeUri operation returns empty URI +*/ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerNormalizeUriTest_002, TestSize.Level0) { LOG_INFO("ControllerTest_ExtSpecialControllerNormalizeUriTest_002::Start"); @@ -264,6 +1463,18 @@ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerNormalizeUriTest_002 LOG_INFO("ControllerTest_ExtSpecialControllerNormalizeUriTest_002::End"); } +/** +* @tc.name: ControllerTest_ExtSpecialControllerDenormalizeUriTest_001 +* @tc.desc: Verify DenormalizeUri operation with null connection in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create ExtSpecialController with null connection and empty URI + 2. Call DenormalizeUri with empty URI + 3. Check if returned result is empty URI +* @tc.expect: + 1. DenormalizeUri operation returns empty URI +*/ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerDenormalizeUriTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_ExtSpecialControllerDenormalizeUriTest_001::Start"); @@ -275,6 +1486,19 @@ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerDenormalizeUriTest_0 LOG_INFO("ControllerTest_ExtSpecialControllerDenormalizeUriTest_001::End"); } +/** +* @tc.name: ControllerTest_ExtSpecialControllerDenormalizeUriTest_002 +* @tc.desc: Verify DenormalizeUri operation with valid connection but unconnected state in ExtSpecialController +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with empty URI + 2. Create ExtSpecialController with the connection and empty URI + 3. Call DenormalizeUri with empty URI + 4. Check if returned result is empty URI +* @tc.expect: + 1. DenormalizeUri operation returns empty URI +*/ HWTEST_F(ControllerTest, ControllerTest_ExtSpecialControllerDenormalizeUriTest_002, TestSize.Level0) { LOG_INFO("ControllerTest_ExtSpecialControllerDenormalizeUriTest_002::Start"); diff --git a/data_share/test/native/unittest/mediadatashare_test/src/datashare_block_writer_impl_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/datashare_block_writer_impl_test.cpp new file mode 100644 index 00000000..3b206690 --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/datashare_block_writer_impl_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 "datashare_block_writer_impl.h" +#include "datashare_log.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +class DataShareBlockWriterImplTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +/** +* @tc.name: AllocRowTest001 +* @tc.desc: test AllocRow function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call AllocRow function and check the result +* @tc.experct: AllocRow failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, AllocRowTest001, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest AllocRowTest001::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + auto result = dataShareBlockWriterImpl.AllocRow(); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest AllocRowTest001::End"); +} + +/** +* @tc.name: WriteTest001 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest001, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest001::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + auto result = dataShareBlockWriterImpl.Write(column); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest001::End"); +} + +/** +* @tc.name: WriteTest002 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest002, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest002::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + int64_t value = 1; + auto result = dataShareBlockWriterImpl.Write(column, value); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest002::End"); +} + +/** +* @tc.name: WriteTest003 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest003, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest003::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + double value = 1; + auto result = dataShareBlockWriterImpl.Write(column, value); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest003::End"); +} + +/** +* @tc.name: WriteTest004 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest004, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest004::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + uint8_t value[3] = {1}; + size_t size = 1; + auto result = dataShareBlockWriterImpl.Write(column, value, size); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest004::End"); +} + +/** +* @tc.name: WriteTest005 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest005, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest005::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + const char* value = "test"; + size_t sizeIncludingNull = 1; + auto result = dataShareBlockWriterImpl.Write(column, value, sizeIncludingNull); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest005::End"); +} + +/** +* @tc.name: GetCurrentRowIndexTest001 +* @tc.desc: test GetCurrentRowIndex function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call GetCurrentRowIndex function and check the result +* @tc.experct: GetCurrentRowIndex failed and reutrn false +*/ +HWTEST_F(DataShareBlockWriterImplTest, GetCurrentRowIndexTest001, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest GetCurrentRowIndexTest001::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t rowIndex = 1; + auto result = dataShareBlockWriterImpl.GetCurrentRowIndex(rowIndex); + EXPECT_EQ(result, false); + LOG_INFO("DataShareBlockWriterImplTest GetCurrentRowIndexTest001::End"); +} + +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/datashare_common_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/datashare_common_test.cpp new file mode 100644 index 00000000..eed7d3aa --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/datashare_common_test.cpp @@ -0,0 +1,725 @@ +/* + * 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 "datashare_errno.h" +#include "datashare_itypes_utils.h" +#include "datashare_log.h" +#include "datashare_abs_result_set.h" +#include "datashare_result_set.h" +#include "ikvstore_data_service.h" +#include "ipc_types.h" +#include "ishared_result_set_stub.h" +#include "itypes_util.h" +#include "message_parcel.h" +#include "gmock/gmock.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +class DataShareCommonTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +class ResultSetBridgeTest : public OHOS::DataShare::ResultSetBridge { +public: + int GetAllColumnNames(std::vector &columnNames) override + { + return 0; + } + + int GetRowCount(int32_t &count) override + { + return 0; + } + + int OnGo(int32_t startRowIndex, int32_t targetRowIndex, Writer &writer) override + { + return 0; + } +}; + +class MockDataShareAbsResultSet : public DataShareAbsResultSet { +public: + MOCK_METHOD1(GoToRow, int(int)); + MOCK_METHOD1(GetRowCount, int(int &)); + MOCK_METHOD1(GetAllColumnNames, int(std::vector &)); + MOCK_METHOD1(GetColumnCount, int(int &)); +}; + +class MockDataShareAbsResultSet2 : public DataShareAbsResultSet { +public: + MOCK_METHOD1(GetAllColumnNames, int(std::vector &)); +}; + +/** +* @tc.name: CreateStubTestTest001 +* @tc.desc: test CreateStub function when resuletset_ = nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and resuletset_ = nullptr + 2.call CreateStub function and check the result +* @tc.experct: CreateStub failed and reutrn nullptr +*/ +HWTEST_F(DataShareCommonTest, CreateStubTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest CreateStubTest001::Start"); + std::shared_ptr resultset; + MessageParcel parcel; + ISharedResultSetStub stub(resultset); + auto result = stub.CreateStub(resultset, parcel); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareCommonTest CreateStubTest001::End"); +} + +/** +* @tc.name: CreateStubTestTest002 +* @tc.desc: test CreateStub function when resuletset_ is not nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and resuletset_ is not nullptr + 2.call CreateStub function and check the result +* @tc.experct: CreateStub succees and not reutrn nullptr +*/ +HWTEST_F(DataShareCommonTest, CreateStubTestTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest CreateStubTestTest002::Start"); + std::shared_ptr resultset = std::make_shared(); + MessageParcel parcel; + ISharedResultSetStub stub(resultset); + auto result = stub.CreateStub(resultset, parcel); + EXPECT_NE(result, nullptr); + LOG_INFO("DataShareCommonTest CreateStubTestTest002::End"); +} + +/** +* @tc.name: OnRemoteRequestTest001 +* @tc.desc: test OnRemoteRequest function when resuletset_ = nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and resuletset_ = nullptr + 2.call OnRemoteRequest function and check the result +* @tc.experct: OnRemoteRequest failed and reutrn INVALID_FD +*/ +HWTEST_F(DataShareCommonTest, OnRemoteRequestTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest OnRemoteRequestTest001::Start"); + std::shared_ptr resultset; + ISharedResultSetStub stub(resultset); + uint32_t code = 0; + MessageParcel data; + MessageParcel parcel; + MessageOption option; + auto result = stub.OnRemoteRequest(code, data, parcel, option); + EXPECT_EQ(result, INVALID_FD); + LOG_INFO("DataShareCommonTest OnRemoteRequestTest001::End"); +} + +/** +* @tc.name: HandleGetRowCountRequestTest001 +* @tc.desc: test HandleGetRowCountRequest function when bridge = nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is nullptr + 2.call HandleGetRowCountRequest function and check the result +* @tc.experct: HandleGetRowCountRequest success and write E_ERROR into reply +*/ +HWTEST_F(DataShareCommonTest, HandleGetRowCountRequestTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest HandleGetRowCountRequestTest001::Start"); + std::shared_ptr resultset = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleGetRowCountRequest(data, reply); + EXPECT_EQ(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("DataShareCommonTest HandleGetRowCountRequestTest001::End"); +} + +/** +* @tc.name: HandleGetRowCountRequestTest002 +* @tc.desc: test HandleGetRowCountRequest function when bridge is not nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is not nullptr + 2.call HandleGetRowCountRequest function and check the result +* @tc.experct: HandleGetRowCountRequest success and write count into reply +*/ +HWTEST_F(DataShareCommonTest, HandleGetRowCountRequestTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest HandleGetRowCountRequestTest002::Start"); + std::shared_ptr resultset = std::make_shared(); + resultset->bridge_ = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleGetRowCountRequest(data, reply); + EXPECT_NE(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("DataShareCommonTest HandleGetRowCountRequestTest002::End"); +} + +/** +* @tc.name: HandleGetAllColumnNamesRequestTest001 +* @tc.desc: test HandleGetAllColumnNamesRequest function when bridge is nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is nullptr + 2.call HandleGetAllColumnNamesRequest function and check the result +* @tc.experct: HandleGetAllColumnNamesRequest success and write E_ERROR into reply +*/ +HWTEST_F(DataShareCommonTest, HandleGetAllColumnNamesRequestTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest HandleGetAllColumnNamesRequestTest001::Start"); + std::shared_ptr resultset = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleGetAllColumnNamesRequest(data, reply); + EXPECT_EQ(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("DataShareCommonTest HandleGetAllColumnNamesRequestTest001::End"); +} + +/** +* @tc.name: HandleGetAllColumnNamesRequestTest002 +* @tc.desc: test HandleGetAllColumnNamesRequest function when bridge is not nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is not nullptr + 2.call HandleGetAllColumnNamesRequest function and check the result +* @tc.experct: HandleGetAllColumnNamesRequest success and write count into reply +*/ +HWTEST_F(DataShareCommonTest, HandleGetAllColumnNamesRequestTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest HandleGetAllColumnNamesRequestTest002::Start"); + std::shared_ptr resultset = std::make_shared(); + resultset->bridge_ = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleGetAllColumnNamesRequest(data, reply); + EXPECT_NE(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("DataShareCommonTest HandleGetAllColumnNamesRequestTest002::End"); +} + +/** +* @tc.name: HandleOnGoRequestTest001 +* @tc.desc: test HandleOnGoRequest function when bridge is nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is nullptr + 2.call HandleOnGoRequest function and check the result +* @tc.experct: HandleOnGoRequest success and write -1 into reply +*/ +HWTEST_F(DataShareCommonTest, HandleOnGoRequestTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest HandleOnGoRequestTest001::Start"); + std::shared_ptr resultset = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleOnGoRequest(data, reply); + EXPECT_EQ(reply.ReadInt32(), -1); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("DataShareCommonTest HandleOnGoRequestTest001::End"); +} + +/** +* @tc.name: HandleOnGoRequestTest002 +* @tc.desc: test HandleOnGoRequest function when bridge is not nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is not nullptr + 2.call HandleOnGoRequest function and check the result +* @tc.experct: HandleOnGoRequest success and write count into reply +*/ +HWTEST_F(DataShareCommonTest, HandleOnGoRequestTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest HandleOnGoRequestTest002::Start"); + std::shared_ptr resultset = std::make_shared(); + resultset->bridge_ = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleOnGoRequest(data, reply); + EXPECT_NE(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("DataShareCommonTest HandleOnGoRequestTest002::End"); +} + +/** +* @tc.name: GetDataTypeTest001 +* @tc.desc: test GetDataType function when sharedBlock_ is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object and sharedBlock_ is nullptr + 2.call GetDataType function and check the result +* @tc.experct: GetDataType failed and return E_ERROR +*/ +HWTEST_F(DataShareCommonTest, GetDataTypeTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest GetDataTypeTest001::Start"); + DataShareResultSet dataShareResultSet; + int columnIndex = 1; + DataShare::DataType dataType; + auto result = dataShareResultSet.GetDataType(columnIndex, dataType); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareCommonTest GetDataTypeTest001::End"); +} + +/** +* @tc.name: CheckStateTest001 +* @tc.desc: test CheckState function when columnIndex >= 0 +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object + 2.call CheckState function when columnIndex >= 0 and check the result +* @tc.experct: CheckState failed and return E_INVALID_COLUMN_INDEX +*/ +HWTEST_F(DataShareCommonTest, CheckStateTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest CheckStateTest001::Start"); + DataShareResultSet dataShareResultSet; + int columnIndex = 1; + auto result = dataShareResultSet.CheckState(columnIndex); + EXPECT_EQ(result, E_INVALID_COLUMN_INDEX); + LOG_INFO("DataShareCommonTest CheckStateTest001::End"); +} + +/** +* @tc.name: CheckStateTest002 +* @tc.desc: test CheckState function when columnIndex < 0 +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object + 2.call CheckState function when columnIndex < 0 and check the result +* @tc.experct: CheckState failed and return E_INVALID_COLUMN_INDEX +*/ +HWTEST_F(DataShareCommonTest, CheckStateTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest CheckState002::Start"); + DataShareResultSet dataShareResultSet; + int columnIndex = -1; + auto result = dataShareResultSet.CheckState(columnIndex); + EXPECT_EQ(result, E_INVALID_COLUMN_INDEX); + LOG_INFO("DataShareCommonTest CheckState002::End"); +} + +/** +* @tc.name: MarshalTest001 +* @tc.desc: test Marshal function when resultset = nullptr +* @tc.type: FUNC +* @tc.require: issueICCAXH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object when resultset = nullptr + 2.call Marshal function and check the result +* @tc.experct: Marshal failed and return false +*/ +HWTEST_F(DataShareCommonTest, MarshalTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest MarshalTest001::Start"); + DataShareResultSet dataShareResultSet; + std::shared_ptr resultset = nullptr; + MessageParcel parcel; + auto result = dataShareResultSet.Marshal(resultset, parcel); + EXPECT_FALSE(result); + LOG_INFO("DataShareCommonTest MarshalTest001::End"); +} + +/** +* @tc.name: UnmarshalTest001 +* @tc.desc: test Unmarshal function +* @tc.type: FUNC +* @tc.require: issueICCAXH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object + 2.call Unmarshal function and check the result +* @tc.experct: Unmarshal failed and return nullptr +*/ +HWTEST_F(DataShareCommonTest, UnmarshalTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest UnmarshalTest001::Start"); + DataShareResultSet dataShareResultSet; + MessageParcel parcel; + auto result = dataShareResultSet.Unmarshal(parcel); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareCommonTest UnmarshalTest001::End"); +} + +/** +* @tc.name: UnmarshallingTest001 +* @tc.desc: test Unmarshalling function when parcel is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a ITypesUtil object and parcel is nullptr + 2.call Unmarshalling function and check the result +* @tc.experct: Unmarshalling failed and return false +*/ +HWTEST_F(DataShareCommonTest, UnmarshallingTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest UnmarshallingTest001::Start"); + ITypesUtil::Predicates predicates; + MessageParcel parcel; + auto result = ITypesUtil::Unmarshalling(predicates, parcel); + EXPECT_FALSE(result); + LOG_INFO("DataShareCommonTest UnmarshallingTest001::End"); +} + +/** +* @tc.name: UnmarshallingTest002 +* @tc.desc: test Unmarshalling function when parcel is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a ITypesUtil object and parcel is nullptr + 2.call Unmarshalling function and check the result +* @tc.experct: Unmarshalling failed and return false +*/ +HWTEST_F(DataShareCommonTest, UnmarshallingTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest UnmarshallingTest002::Start"); + OperationStatement operationStatement; + MessageParcel parcel; + auto result = ITypesUtil::Unmarshalling(operationStatement, parcel); + EXPECT_FALSE(result); + LOG_INFO("DataShareCommonTest UnmarshallingTest002::End"); +} + +/** +* @tc.name: UnmarshallingTest003 +* @tc.desc: test Unmarshalling function when parcel is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a ITypesUtil object and parcel is nullptr + 2.call Unmarshalling function and check the result +* @tc.experct: Unmarshalling failed and return false +*/ +HWTEST_F(DataShareCommonTest, UnmarshallingTest003, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest UnmarshallingTest003::Start"); + ExecResult execResult; + MessageParcel parcel; + auto result = ITypesUtil::Unmarshalling(execResult, parcel); + EXPECT_FALSE(result); + LOG_INFO("DataShareCommonTest UnmarshallingTest003::End"); +} + +/** +* @tc.name: UnmarshallingTest004 +* @tc.desc: test Unmarshalling function when parcel is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a ITypesUtil object and parcel is nullptr + 2.call Unmarshalling function and check the result +* @tc.experct: Unmarshalling failed and return false +*/ +HWTEST_F(DataShareCommonTest, UnmarshallingTest004, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest UnmarshallingTest004::Start"); + ExecResultSet execResultSet; + MessageParcel parcel; + auto result = ITypesUtil::Unmarshalling(execResultSet, parcel); + EXPECT_FALSE(result); + LOG_INFO("DataShareCommonTest UnmarshallingTest004::End"); +} + +/** +* @tc.name: MarshallingTest001 +* @tc.desc: test Marshalling function when parcel is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a ITypesUtil object and parcel is nullptr + 2.call Marshalling function and check the result +* @tc.experct: Marshalling success and return ture +*/ +HWTEST_F(DataShareCommonTest, MarshallingTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest MarshallingTest001::Start"); + ITypesUtil::RdbChangeNode changeNode; + MessageParcel parcel; + auto result = ITypesUtil::Marshalling(changeNode, parcel); + EXPECT_TRUE(result); + LOG_INFO("DataShareCommonTest MarshallingTest001::End"); +} + +/** +* @tc.name: MarshallingTest002 +* @tc.desc: test Marshalling function when sharedBlock_ is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object + 2.call Marshalling function when sharedBlock_ is nullptr and check the result +* @tc.experct: Marshalling failed and return false +*/ +HWTEST_F(DataShareCommonTest, MarshallingTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest MarshallingTest002::Start"); + DataShareResultSet dataShareResultSet; + MessageParcel parcel; + auto result = dataShareResultSet.Marshalling(parcel); + EXPECT_FALSE(result); + LOG_INFO("DataShareCommonTest MarshallingTest002::End"); +} + +/** +* @tc.name: GoToTest001 +* @tc.desc: test GoTo function when GoToRow return E_ERROR +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GoTo function when GoToRow return E_ERROR and check the result +* @tc.experct: GoTo failed and return E_ERROR +*/ +HWTEST_F(DataShareCommonTest, GoToTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest GoToTest001::Start"); + MockDataShareAbsResultSet mockResultSet; + int offset = 1; + EXPECT_CALL(mockResultSet, GoToRow(testing::_)) + .WillOnce(testing::Return(E_ERROR)); + auto result = mockResultSet.GoTo(offset); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareCommonTest GoToTest001::End"); +} + +/** +* @tc.name: GoToTest002 +* @tc.desc: test GoTo function +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GoTo function and check the result +* @tc.experct: GoTo success and return E_OK +*/ +HWTEST_F(DataShareCommonTest, GoToTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest GoToTest002::Start"); + DataShareAbsResultSet dataShareAbsResultSet; + int offset = 1; + auto result = dataShareAbsResultSet.GoTo(offset); + EXPECT_EQ(result, E_OK); + LOG_INFO("DataShareCommonTest GoToTest002::End"); +} + +/** +* @tc.name: IsEndedTest001 +* @tc.desc: test IsEnded function when GetRowCount return E_ERROR +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call IsEnded function when GetRowCount return E_ERROR and check the result +* @tc.experct: IsEnded failed and return E_ERROR +*/ +HWTEST_F(DataShareCommonTest, IsEndedTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest IsEndedTest001::Start"); + MockDataShareAbsResultSet mockResultSet; + EXPECT_CALL(mockResultSet, GetRowCount(testing::_)) + .WillOnce(testing::Return(E_ERROR)); + bool test = true; + auto result = mockResultSet.IsEnded(test); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareCommonTest IsEndedTest001::End"); +} + +/** +* @tc.name: IsEndedTest002 +* @tc.desc: test IsEnded function +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call IsEnded function and check the result +* @tc.experct: IsEnded success and return E_OK +*/ +HWTEST_F(DataShareCommonTest, IsEndedTest002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest IsEndedTest002::Start"); + DataShareAbsResultSet dataShareAbsResultSet; + bool test = true; + auto result = dataShareAbsResultSet.IsEnded(test); + EXPECT_EQ(result, E_OK); + LOG_INFO("DataShareCommonTest IsEndedTest002::End"); +} + +/** +* @tc.name: GetColumnCountTest001 +* @tc.desc: test GetColumnCount function when GetAllColumnNames return E_ERROR +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet2 object + 2.call GetColumnCount function when GetAllColumnNames return E_ERROR and check the result +* @tc.experct: GetColumnCount failed and return E_ERROR +*/ +HWTEST_F(DataShareCommonTest, GetColumnCountTest001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest GetColumnCountTest001::Start"); + MockDataShareAbsResultSet2 mockResultSet; + int offset = -1; + mockResultSet.count_ = -1; + EXPECT_CALL(mockResultSet, GetAllColumnNames(testing::_)) + .WillOnce(testing::Return(E_ERROR)); + auto result = mockResultSet.GetColumnCount(offset); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareCommonTest GetColumnCountTest001::End"); +} + +/** +* @tc.name: GetColumnName001 +* @tc.desc: test GetColumnName function when GetColumnCount return E_ERROR +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GetColumnName function when GetColumnCount return E_ERROR and check the result +* @tc.experct: GetColumnName failed and return E_ERROR +*/ +HWTEST_F(DataShareCommonTest, GetColumnName001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest GetColumnName001::Start"); + MockDataShareAbsResultSet mockResultSet; + int columnIndex = 1; + std::string columnName = "test"; + EXPECT_CALL(mockResultSet, GetColumnCount(testing::_)) + .WillOnce(testing::Return(E_ERROR)); + auto result = mockResultSet.GetColumnName(columnIndex, columnName); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareCommonTest GetColumnName001::End"); +} + +/** +* @tc.name: GetColumnName002 +* @tc.desc: test GetColumnName function when columnIndex >= 0 +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GetColumnName function when columnIndex >= 0 and check the result +* @tc.experct: GetColumnName failed and return E_INVALID_COLUMN_INDEX +*/ +HWTEST_F(DataShareCommonTest, GetColumnName002, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest MarshallingTest002::Start"); + DataShareAbsResultSet dataShareAbsResultSet; + int columnIndex = 1; + std::string columnName = "test"; + auto result = dataShareAbsResultSet.GetColumnName(columnIndex, columnName); + EXPECT_EQ(result, E_INVALID_COLUMN_INDEX); + LOG_INFO("DataShareCommonTest MarshallingTest002::End"); +} + +/** +* @tc.name: GetColumnName003 +* @tc.desc: test GetColumnName function when columnIndex < 0 +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GetColumnName function when columnIndex < 0 and check the result +* @tc.experct: GetColumnName failed and return E_INVALID_COLUMN_INDEX +*/ +HWTEST_F(DataShareCommonTest, GetColumnName003, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest MarshallingTest002::Start"); + DataShareAbsResultSet dataShareAbsResultSet; + int columnIndex = -1; + std::string columnName = "test"; + auto result = dataShareAbsResultSet.GetColumnName(columnIndex, columnName); + EXPECT_EQ(result, E_INVALID_COLUMN_INDEX); + LOG_INFO("DataShareCommonTest MarshallingTest002::End"); +} + +/** +* @tc.name: RegisterClientDeathObserver001 +* @tc.desc: test RegisterClientDeathObserver function when observer = nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object when observer = nullptr + 2.call RegisterClientDeathObserver function and check the result +* @tc.experct: RegisterClientDeathObserver failed and return -1 +*/ +HWTEST_F(DataShareCommonTest, RegisterClientDeathObserver001, TestSize.Level0) +{ + LOG_INFO("DataShareCommonTest RegisterClientDeathObserver001::Start"); + sptr observer = nullptr; + std::string appId = "testAppid"; + DataShareKvServiceProxy dataShareKvServiceProxy(observer); + auto result = dataShareKvServiceProxy.RegisterClientDeathObserver(appId, observer); + EXPECT_EQ(result, -1); + LOG_INFO("DataShareCommonTest RegisterClientDeathObserver001::End"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/datashare_connection_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/datashare_connection_test.cpp new file mode 100644 index 00000000..a3b19c11 --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/datashare_connection_test.cpp @@ -0,0 +1,345 @@ +/* + * 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 "datashare_connection.h" + +#include + +#include "accesstoken_kit.h" +#include "data_ability_observer_interface.h" +#include "datashare_errno.h" +#include "datashare_helper.h" +#include "datashare_log.h" +#include "datashare_proxy.h" +#include "extension_manager_proxy.h" +#include "general_controller.h" +#include "general_controller_provider_impl.h" +#include "general_controller_service_impl.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::AAFwk; +class DataShareConnectionTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + bool UrisEqual(std::list uri1, std::list uri2) + { + if (uri1.size() != uri2.size()) { + return false; + } + auto cmp = [](const Uri &first, const Uri &second) { + return first.ToString() < second.ToString(); + }; + uri1.sort(cmp); + uri2.sort(cmp); + auto it1 = uri1.begin(); + auto it2 = uri2.begin(); + for (; it1 != uri1.end() && it2 != uri2.end(); it1++, it2++) { + if (!it1->Equals(*it2)) { + return false; + } + } + return true; + } +}; + +class RemoteObjectTest : public IRemoteObject { +public: + explicit RemoteObjectTest(std::u16string descriptor) : IRemoteObject(descriptor) {} + ~RemoteObjectTest() {} + + int32_t GetObjectRefCount() + { + return 0; + } + int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + return 0; + } + bool AddDeathRecipient(const sptr &recipient) + { + return true; + } + bool RemoveDeathRecipient(const sptr &recipient) + { + return true; + } + int Dump(int fd, const std::vector &args) + { + return 0; + } +}; + +class IDataAbilityObserverTest : public DataAbilityObserverStub { +public: + explicit IDataAbilityObserverTest(std::string uri) {uri_ = uri;} + ~IDataAbilityObserverTest() + {} + + void OnChange() + { + GTEST_LOG_(INFO) << "OnChange enter"; + } + std::string uri_; +}; + +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::string DATA_SHARE_URI1 = "datashare:///com.acts.datasharetest1"; + +void DataShareConnectionTest::SetUpTestCase(void) {} +void DataShareConnectionTest::TearDownTestCase(void) {} +void DataShareConnectionTest::SetUp(void) {} +void DataShareConnectionTest::TearDown(void) {} + +/** +* @tc.name: DataShareConnection_UpdateObserverExtsProviderMap_Test_001 +* @tc.desc: Verify normal functionality of UpdateObserverExtsProviderMap method +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with test URI and token + 2. Verify observer map is initially empty + 3. Add two observers with different URIs using UpdateObserverExtsProviderMap + 4. Check that observer map size is correctly updated +* @tc.expect: + 1. Observer map is empty initially + 2. After adding observers, map size becomes 2 +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_UpdateObserverExtsProviderMap_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareConnection_UpdateObserverExtsProviderMap_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // insert data + EXPECT_TRUE(connection->observerExtsProvider_.Empty()); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI); + ASSERT_NE(dataObserver, nullptr); + connection->UpdateObserverExtsProviderMap(uri, dataObserver, true); + + Uri uri1(DATA_SHARE_URI1); + sptr dataObserver1 = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI1); + ASSERT_NE(dataObserver1, nullptr); + connection->UpdateObserverExtsProviderMap(uri1, dataObserver1, true); + + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 2); + connection = nullptr; + + LOG_INFO("DataShareConnection_UpdateObserverExtsProviderMap_Test_001::End"); +} + +/** +* @tc.name: DataShareConnection_DeleteObserverExtsProviderMap_001 +* @tc.desc: Verify DeleteObserverExtsProviderMap functionality for removing observers +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection and add two observers + 2. Verify initial map size is 2 + 3. Delete one valid observer and check map size + 4. Attempt to delete an invalid observer and check map size remains unchanged +* @tc.expect: + 1. After first deletion, map size is 1 + 2. After second deletion attempt, map size remains 1 +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_DeleteObserverExtsProviderMap_001, TestSize.Level0) +{ + LOG_INFO("DataShareConnection_DeleteObserverExtsProviderMap_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // insert data + EXPECT_TRUE(connection->observerExtsProvider_.Empty()); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI); + connection->UpdateObserverExtsProviderMap(uri, dataObserver, true); + + Uri uri1(DATA_SHARE_URI1); + sptr dataObserver1 = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI1); + connection->UpdateObserverExtsProviderMap(uri1, dataObserver1, true); + + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 2); + + // delete data that uri can match observer + connection->DeleteObserverExtsProviderMap(uri1, dataObserver1); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 1); + + // delete data that uri can not match observer + connection->DeleteObserverExtsProviderMap(uri1, dataObserver); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 1); + connection = nullptr; + + LOG_INFO("DataShareConnection_DeleteObserverExtsProviderMap_001::End"); +} + +/** +* @tc.name: DataShareConnection_ReRegisterObserverExtProvider_Test_001 +* @tc.desc: Verify ReRegisterObserverExtProvider can re-register existing observers +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with valid proxy + 2. Add two observers to the map + 3. Call ReRegisterObserverExtProvider method + 4. Verify observer map remains populated after re-registration +* @tc.expect: + 1. Observer map remains non-empty after re-registration +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_ReRegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareConnection_ReRegisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + connection->dataShareProxy_ = tokenProxy; + + // insert data + EXPECT_TRUE(connection->observerExtsProvider_.Empty()); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI); + connection->UpdateObserverExtsProviderMap(uri, dataObserver, true); + + Uri uri1(DATA_SHARE_URI1); + sptr dataObserver1 = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI1); + connection->UpdateObserverExtsProviderMap(uri1, dataObserver1, true); + + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 2); + + // test ReRegister func + connection->ReRegisterObserverExtProvider(); + // reRegister success, update observer map + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + connection = nullptr; + + LOG_INFO("DataShareConnection_ReRegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareConnection_OnAbilityConnectDone_Test_001 +* @tc.desc: Verify OnAbilityConnectDone handles reconnection and observer reregistration +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with valid proxy and observers + 2. Set isReconnect_ flag to true + 3. Call OnAbilityConnectDone with test parameters + 4. Verify observer map remains intact after connection +* @tc.expect: + 1. Observer map remains non-empty after connection completes +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_OnAbilityConnectDone_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareConnection_OnAbilityConnectDone_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + connection->dataShareProxy_ = tokenProxy; + + // insert data + EXPECT_TRUE(connection->observerExtsProvider_.Empty()); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI); + connection->UpdateObserverExtsProviderMap(uri, dataObserver, true); + + Uri uri1(DATA_SHARE_URI1); + sptr dataObserver1 = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI1); + connection->UpdateObserverExtsProviderMap(uri1, dataObserver1, true); + + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 2); + + // test ReRegister func + connection->isReconnect_.store(true); + std::string deviceId = "deviceId"; + std::string bundleName = "bundleName"; + std::string abilityName = "abilityName"; + AppExecFwk::ElementName element(deviceId, bundleName, abilityName); + int resultCode = 0; + connection->OnAbilityConnectDone(element, token, resultCode); + + // reRegister success, update observer map + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + connection = nullptr; + + LOG_INFO("DataShareConnection_OnAbilityConnectDone_Test_001::End"); +} + +/** +* @tc.name: DataShareConnection_OnAbilityDisconnectDone_Test_001 +* @tc.desc: Verify thread name is correctly set after disconnection +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection and set isReconnect_ to true + 2. Call OnAbilityDisconnectDone with test parameters + 3. Check that the thread name in the connection pool is correct +* @tc.expect: + 1. Thread name is set to "DShare_Connect" +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_OnAbilityDisconnectDone_Test_001, TestSize.Level1) +{ + LOG_INFO("DataShareConnection_OnAbilityDisconnectDone_Test_001::Start"); + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + + connection->isReconnect_.store(true); + std::string deviceId = "deviceId"; + std::string bundleName = "bundleName"; + std::string abilityName = "abilityName"; + AppExecFwk::ElementName element(deviceId, bundleName, abilityName); + int resultCode = 0; + connection->OnAbilityDisconnectDone(element, resultCode); + EXPECT_EQ(connection->pool_->pool_.threadName_, DATASHARE_EXECUTOR_NAME); + LOG_INFO("DataShareConnection_OnAbilityDisconnectDone_Test_001::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/datashare_helper_impl_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/datashare_helper_impl_test.cpp new file mode 100644 index 00000000..ef3aa57c --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/datashare_helper_impl_test.cpp @@ -0,0 +1,662 @@ +/* + * 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 "datashare_helper_impl.h" +#include "general_controller_service_impl.h" + +#include + +#include + +#include "datashare_log.h" +#include "gmock/gmock.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; + +class MockGeneralController : public GeneralController { +public: + MOCK_METHOD(int, Insert, (const Uri &uri, const DataShareValuesBucket &value), (override)); + MOCK_METHOD(int, Update, + (const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value), (override)); + MOCK_METHOD(int, Delete, (const Uri &uri, const DataSharePredicates &predicates), (override)); + MOCK_METHOD((std::shared_ptr), Query, + (const Uri &uri, const DataSharePredicates &predicates, (std::vector & columns), + DatashareBusinessError &businessError, DataShareOption &option), (override)); + MOCK_METHOD( + int, RegisterObserver, (const Uri &uri, const sptr &dataObserver), (override)); + MOCK_METHOD(int32_t, UnregisterObserver, (const Uri &uri, const sptr &dataObserver), + (override)); + MOCK_METHOD(void, NotifyChange, (const Uri &uri), (override)); + MOCK_METHOD( + int, RegisterObserverExtProvider, (const Uri &uri, const sptr &dataObserver, + bool isDescendants), (override)); + MOCK_METHOD(int32_t, UnregisterObserverExtProvider, (const Uri &uri, + const sptr &dataObserver), (override)); + MOCK_METHOD(int32_t, NotifyChangeExtProvider, (const ChangeInfo &changeInfo), (override)); + MOCK_METHOD( + (std::pair), InsertEx, (const Uri &uri, const DataShareValuesBucket &value), (override)); + MOCK_METHOD((std::pair), UpdateEx, + (const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value), (override)); + MOCK_METHOD( + (std::pair), DeleteEx, (const Uri &uri, const DataSharePredicates &predicates), (override)); +}; + +class DataShareHelperImplTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static std::shared_ptr GetInstance(std::shared_ptr instance = nullptr); + static std::shared_ptr GetController( + std::shared_ptr instance = nullptr); +}; + +void DataShareHelperImplTest::SetUpTestCase(void) +{ + DataShareHelperImplTest::GetInstance(std::make_shared("datashare://datasharehelperimpl")); + EXPECT_NE(DataShareHelperImplTest::GetInstance(), nullptr); + DataShareHelperImplTest::GetController(std::make_shared()); + EXPECT_NE(DataShareHelperImplTest::GetController(), nullptr); + DataShareHelperImplTest::GetInstance()->generalCtl_ = DataShareHelperImplTest::GetController(); + EXPECT_NE(DataShareHelperImplTest::GetInstance()->generalCtl_, nullptr); + EXPECT_EQ(DataShareHelperImplTest::GetInstance()->extSpCtl_, nullptr); + DataShareHelperImplTest::GetInstance()->persistentDataCtl_ = nullptr; + DataShareHelperImplTest::GetInstance()->publishedDataCtl_ = nullptr; +} +void DataShareHelperImplTest::TearDownTestCase(void) +{ +} +void DataShareHelperImplTest::SetUp(void) +{ +} +void DataShareHelperImplTest::TearDown(void) +{ +} +std::shared_ptr DataShareHelperImplTest::GetInstance(std::shared_ptr instance) +{ + static std::shared_ptr helperInstance = nullptr; + if (instance != nullptr) { + helperInstance = instance; + } + return helperInstance; +} +std::shared_ptr DataShareHelperImplTest::GetController( + std::shared_ptr instance) +{ + static std::shared_ptr controllerInstance = nullptr; + if (instance != nullptr) { + controllerInstance = instance; + } + return controllerInstance; +} + +/** +* @tc.name: QueryTest001 +* @tc.desc: Verify Query function behavior under different controller states +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: DataShareHelperImpl instance is properly initialized +* @tc.step: + 1. Create test URI and empty predicates/columns + 2. Set general controller to null and execute Query + 3. Initialize mock controller and set it as general controller + 4. Verify Query returns expected result set with mock controller + 5. Verify Query works with business error parameter +* @tc.expect: + 1. Query returns nullptr when controller is null + 2. Query returns expected result set when using mock controller + 3. Query works correctly with business error parameter +*/ +HWTEST_F(DataShareHelperImplTest, QueryTest001, TestSize.Level0) +{ + LOG_INFO("QueryTest001::Start"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataSharePredicates predicates; + std::vector columns; + DataShareHelperImplTest::GetInstance()->generalCtl_ = nullptr; + auto result = DataShareHelperImplTest::GetInstance()->Query(uri, predicates, columns, nullptr); + EXPECT_EQ(result, nullptr); + auto expectResult = std::make_shared(); + std::shared_ptr controller = DataShareHelperImplTest::GetController(); + DataShareHelperImplTest::GetInstance()->generalCtl_ = controller; + EXPECT_CALL(*controller, Query(testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(expectResult)); + result = DataShareHelperImplTest::GetInstance()->Query(uri, predicates, columns, nullptr); + EXPECT_EQ(result, expectResult); + DatashareBusinessError error; + EXPECT_CALL(*controller, Query(testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(expectResult)); + result = DataShareHelperImplTest::GetInstance()->Query(uri, predicates, columns, &error); + EXPECT_EQ(result, expectResult); + LOG_INFO("QueryTest001::End"); +} + +/** +* @tc.name: QueryTimeoutTest001 +* @tc.desc: Verify QueryTimeout function behavior under different controller states +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: DataShareHelperImpl instance is properly initialized +* @tc.step: + 1. Create test URI, empty predicates/columns and default option + 2. Set general controller to null and execute QueryTimeout + 3. Initialize mock controller and set it as general controller + 4. Verify QueryTimeout returns expected result set with mock controller + 5. Verify QueryTimeout works with business error parameter +* @tc.expect: + 1. QueryTimeout returns nullptr when controller is null + 2. QueryTimeout returns expected result set when using mock controller + 3. QueryTimeout works correctly with business error parameter +*/ +HWTEST_F(DataShareHelperImplTest, QueryTimeoutTest001, TestSize.Level0) +{ + LOG_INFO("QueryTimeoutTest001::Start"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataSharePredicates predicates; + std::vector columns; + DataShareOption option; + DataShareHelperImplTest::GetInstance()->generalCtl_ = nullptr; + auto result = DataShareHelperImplTest::GetInstance()->Query(uri, predicates, columns, option, nullptr); + EXPECT_EQ(result, nullptr); + auto expectResult = std::make_shared(); + std::shared_ptr controller = DataShareHelperImplTest::GetController(); + DataShareHelperImplTest::GetInstance()->generalCtl_ = controller; + EXPECT_CALL(*controller, Query(testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(expectResult)); + result = DataShareHelperImplTest::GetInstance()->Query(uri, predicates, columns, option, nullptr); + EXPECT_EQ(result, expectResult); + DatashareBusinessError error; + EXPECT_CALL(*controller, Query(testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(expectResult)); + result = DataShareHelperImplTest::GetInstance()->Query(uri, predicates, columns, option, &error); + EXPECT_EQ(result, expectResult); + LOG_INFO("QueryTimeoutTest001::End"); +} + +/** +* @tc.name: BatchUpdateTest001 +* @tc.desc: Verify BatchUpdate function behavior with empty operations +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: DataShareHelperImpl instance is properly initialized +* @tc.step: + 1. Create empty update operations and results vector + 2. Execute BatchUpdate with empty parameters + 3. Check return error code +* @tc.expect: + 1. BatchUpdate returns DATA_SHARE_ERROR when given empty operations +*/ +HWTEST_F(DataShareHelperImplTest, BatchUpdateTest001, TestSize.Level0) +{ + LOG_INFO("BatchUpdateTest001::Start"); + UpdateOperations operations; + std::vector results = {}; + int result = DataShareHelperImplTest::GetInstance()->BatchUpdate(operations, results); + EXPECT_EQ(result, DATA_SHARE_ERROR); + LOG_INFO("BatchUpdateTest001::End"); +} + +/** +* @tc.name: InsertExTest001 +* @tc.desc: Verify InsertEx handles null controller and error responses +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Set general controller to null and call InsertEx + 2. Restore mock controller and set expectation for error response + 3. Call InsertEx again with valid parameters + 4. Check returned results in both cases +* @tc.expect: + 1. First call returns DATA_SHARE_ERROR + 2. Second call returns E_REGISTERED_REPEATED error +*/ +HWTEST_F(DataShareHelperImplTest, InsertExTest001, TestSize.Level0) +{ + LOG_INFO("InsertExTest001::Start"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataShareValuesBucket value; + DataShareHelperImplTest::GetInstance()->generalCtl_ = nullptr; + std::pair result = DataShareHelperImplTest::GetInstance()->InsertEx(uri, value); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + std::shared_ptr controller = DataShareHelperImplTest::GetController(); + DataShareHelperImplTest::GetInstance()->generalCtl_ = controller; + EXPECT_CALL(*controller, InsertEx(testing::_, testing::_)) + .WillOnce(testing::Return(std::make_pair(E_REGISTERED_REPEATED, 0))); + result = DataShareHelperImplTest::GetInstance()->InsertEx(uri, value); + EXPECT_EQ(result.first, E_REGISTERED_REPEATED); + EXPECT_EQ(result.second, 0); + LOG_INFO("InsertExTest001::End"); +} + +/** +* @tc.name: UpdateExTest001 +* @tc.desc: Verify UpdateEx handles null controller and error responses +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Set general controller to null and call UpdateEx + 2. Restore mock controller and set expectation for error response + 3. Call UpdateEx again with valid parameters + 4. Check returned results in both cases +* @tc.expect: + 1. First call returns DATA_SHARE_ERROR + 2. Second call returns E_REGISTERED_REPEATED error +*/ +HWTEST_F(DataShareHelperImplTest, UpdateExTest001, TestSize.Level0) +{ + LOG_INFO("UpdateExTest001::Start"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataShareValuesBucket value; + DataSharePredicates predicates; + DataShareHelperImplTest::GetInstance()->generalCtl_ = nullptr; + std::pair result = DataShareHelperImplTest::GetInstance()->UpdateEx(uri, predicates, value); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + std::shared_ptr controller = DataShareHelperImplTest::GetController(); + DataShareHelperImplTest::GetInstance()->generalCtl_ = controller; + EXPECT_CALL(*controller, UpdateEx(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(std::make_pair(E_REGISTERED_REPEATED, 0))); + result = DataShareHelperImplTest::GetInstance()->UpdateEx(uri, predicates, value); + EXPECT_EQ(result.first, E_REGISTERED_REPEATED); + EXPECT_EQ(result.second, 0); + LOG_INFO("UpdateExTest001::End"); +} + +/** +* @tc.name: DeleteExTest001 +* @tc.desc: Verify DeleteEx handles null controller and error responses +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Set general controller to null and call DeleteEx + 2. Restore mock controller and set expectation for error response + 3. Call DeleteEx again with valid parameters + 4. Check returned results in both cases +* @tc.expect: + 1. First call returns DATA_SHARE_ERROR + 2. Second call returns E_REGISTERED_REPEATED error +*/ +HWTEST_F(DataShareHelperImplTest, DeleteExTest001, TestSize.Level0) +{ + LOG_INFO("DeleteExTest001::Start"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataSharePredicates predicates; + DataShareHelperImplTest::GetInstance()->generalCtl_ = nullptr; + std::pair result = DataShareHelperImplTest::GetInstance()->DeleteEx(uri, predicates); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + std::shared_ptr controller = DataShareHelperImplTest::GetController(); + DataShareHelperImplTest::GetInstance()->generalCtl_ = controller; + EXPECT_CALL(*controller, DeleteEx(testing::_, testing::_)) + .WillOnce(testing::Return(std::make_pair(E_REGISTERED_REPEATED, 0))); + result = DataShareHelperImplTest::GetInstance()->DeleteEx(uri, predicates); + EXPECT_EQ(result.first, E_REGISTERED_REPEATED); + EXPECT_EQ(result.second, 0); + LOG_INFO("DeleteExTest001::End"); +} + +/** +* @tc.name: DelQueryTemplateTest001 +* @tc.desc: Verify DelQueryTemplate returns error with valid parameters +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Call DelQueryTemplate with test URI and subscriber ID + 2. Check returned result code +* @tc.expect: + 1. DelQueryTemplate returns DATA_SHARE_ERROR +*/ +HWTEST_F(DataShareHelperImplTest, DelQueryTemplateTest001, TestSize.Level0) +{ + LOG_INFO("DelQueryTemplateTest001::Start"); + std::string uri("datashare:///com.datasharehelperimpl.test"); + int64_t subscriberId = 0; + int result = DataShareHelperImplTest::GetInstance()->DelQueryTemplate(uri, subscriberId); + EXPECT_EQ(result, DATA_SHARE_ERROR); + LOG_INFO("DelQueryTemplateTest001::End"); +} + +/** +* @tc.name: PublishTest001 +* @tc.desc: Verify Publish returns empty result with valid parameters +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create empty Data object and test bundle name + 2. Call Publish with these parameters + 3. Check size of returned result vector +* @tc.expect: + 1. Returned result vector is empty +*/ +HWTEST_F(DataShareHelperImplTest, PublishTest001, TestSize.Level0) +{ + LOG_INFO("PublishTest001::Start"); + Data data; + std::string bundleName("datashare:///com.datasharehelperimpl.test"); + std::vector result = DataShareHelperImplTest::GetInstance()->Publish(data, bundleName); + EXPECT_EQ(result.size(), 0); + LOG_INFO("PublishTest001::End"); +} + +/** +* @tc.name: GetPublishedDataTest001 +* @tc.desc: Verify GetPublishedData returns empty data with valid parameters +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create test bundle name and result code variable + 2. Call GetPublishedData with these parameters + 3. Check version and size of returned Data object +* @tc.expect: + 1. Returned Data object has version 0 and empty data vector +*/ +HWTEST_F(DataShareHelperImplTest, GetPublishedDataTest001, TestSize.Level0) +{ + LOG_INFO("GetPublishedDataTest001::Start"); + int resultCode = 0; + std::string bundleName("datashare:///com.datasharehelperimpl.test"); + Data result = DataShareHelperImplTest::GetInstance()->GetPublishedData(bundleName, resultCode); + EXPECT_EQ(result.version_, 0); + EXPECT_EQ(result.datas_.size(), 0); + LOG_INFO("GetPublishedDataTest001::End"); +} + +/** +* @tc.name: SubscribeRdbDataTest001 +* @tc.desc: Verify SubscribeRdbData returns empty result with empty URIs +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create empty URIs vector, template ID and callback + 2. Call SubscribeRdbData with these parameters + 3. Check size of returned result vector +* @tc.expect: + 1. Returned result vector is empty +*/ +HWTEST_F(DataShareHelperImplTest, SubscribeRdbDataTest001, TestSize.Level0) +{ + LOG_INFO("SubscribeRdbDataTest001::Start"); + std::vector uris = {}; + TemplateId templateId; + std::function callback; + std::vector result = + DataShareHelperImplTest::GetInstance()->SubscribeRdbData(uris, templateId, callback); + EXPECT_EQ(result.size(), 0); + LOG_INFO("SubscribeRdbDataTest001::End"); +} + +/** +* @tc.name: UnsubscribeRdbDataTest001 +* @tc.desc: Verify UnsubscribeRdbData returns empty result with empty URIs +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create empty URIs vector and template ID + 2. Call UnsubscribeRdbData with these parameters + 3. Check size of returned result vector +* @tc.expect: + 1. Returned result vector is empty +*/ +HWTEST_F(DataShareHelperImplTest, UnsubscribeRdbDataTest001, TestSize.Level0) +{ + LOG_INFO("UnsubscribeRdbDataTest001::Start"); + std::vector uris = {}; + TemplateId templateId; + std::vector result = DataShareHelperImplTest::GetInstance()->UnsubscribeRdbData(uris, templateId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("UnsubscribeRdbDataTest001::End"); +} + +/** +* @tc.name: DisableRdbSubsTest001 +* @tc.desc: Verify DisableRdbSubs returns empty result with empty URIs +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create empty URIs vector and template ID + 2. Call DisableRdbSubs with these parameters + 3. Check size of returned result vector +* @tc.expect: + 1. Returned result vector is empty +*/ +HWTEST_F(DataShareHelperImplTest, DisableRdbSubsTest001, TestSize.Level0) +{ + LOG_INFO("DisableRdbSubsTest001::Start"); + std::vector uris = {}; + TemplateId templateId; + std::vector result = DataShareHelperImplTest::GetInstance()->DisableRdbSubs(uris, templateId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("DisableRdbSubsTest001::End"); +} + +/** +* @tc.name: SubscribePublishedDataTest001 +* @tc.desc: Verify SubscribePublishedData returns empty result with empty URIs +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create empty URIs vector, subscriber ID and callback + 2. Call SubscribePublishedData with these parameters + 3. Check size of returned result vector +* @tc.expect: + 1. Returned result vector is empty +*/ +HWTEST_F(DataShareHelperImplTest, SubscribePublishedDataTest001, TestSize.Level0) +{ + LOG_INFO("SubscribePublishedDataTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 0; + std::function callback; + std::vector result = + DataShareHelperImplTest::GetInstance()->SubscribePublishedData(uris, subscriberId, callback); + EXPECT_EQ(result.size(), 0); + LOG_INFO("SubscribePublishedDataTest001::End"); +} + +/** +* @tc.name: UnsubscribePublishedDataTest001 +* @tc.desc: Verify UnsubscribePublishedData returns empty result with empty URIs +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create empty URIs vector and subscriber ID + 2. Call UnsubscribePublishedData with these parameters + 3. Check size of returned result vector +* @tc.expect: + 1. Returned result vector is empty +*/ +HWTEST_F(DataShareHelperImplTest, UnsubscribePublishedDataTest001, TestSize.Level0) +{ + LOG_INFO("UnsubscribePublishedDataTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 0; + std::vector result = + DataShareHelperImplTest::GetInstance()->UnsubscribePublishedData(uris, subscriberId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("UnsubscribePublishedDataTest001::End"); +} + +/** +* @tc.name: EnablePubSubsTest001 +* @tc.desc: Verify EnablePubSubs returns empty result with empty URIs +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create empty URIs vector and subscriber ID + 2. Call EnablePubSubs with these parameters + 3. Check size of returned result vector +* @tc.expect: + 1. Returned result vector is empty +*/ +HWTEST_F(DataShareHelperImplTest, EnablePubSubsTest001, TestSize.Level0) +{ + LOG_INFO("EnablePubSubsTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 0; + std::vector result = DataShareHelperImplTest::GetInstance()->EnablePubSubs(uris, subscriberId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("EnablePubSubsTest001::End"); +} + +/** +* @tc.name: DisablePubSubsTest001 +* @tc.desc: Verify DisablePubSubs returns empty result with empty URIs +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create empty URIs vector and subscriber ID + 2. Call DisablePubSubs with these parameters + 3. Check size of returned result vector +* @tc.expect: + 1. Returned result vector is empty +*/ +HWTEST_F(DataShareHelperImplTest, DisablePubSubsTest001, TestSize.Level0) +{ + LOG_INFO("DisablePubSubsTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 0; + std::vector result = DataShareHelperImplTest::GetInstance()->DisablePubSubs(uris, subscriberId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("DisablePubSubsTest001::End"); +} + +/** +* @tc.name: User_Define_func_No_ExtSpCtl_Test001 +* @tc.desc: Verify UserDefineFunc returns error when extSpCtl_ is null +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Set extSpCtl_ to null + 2. Create empty MessageParcel objects and MessageOption + 3. Call UserDefineFunc with these parameters + 4. Check returned result code +* @tc.expect: + 1. UserDefineFunc returns DATA_SHARE_ERROR +*/ +HWTEST_F(DataShareHelperImplTest, User_Define_func_No_ExtSpCtl_Test001, TestSize.Level0) +{ + LOG_INFO("User_Define_func_No_ExtSpCtl_Test001::Start"); + DataShareHelperImplTest::GetInstance()->extSpCtl_ = nullptr; + MessageParcel data; + MessageParcel reply; + MessageOption option; + auto result = DataShareHelperImplTest::GetInstance()->UserDefineFunc(data, reply, option); + EXPECT_EQ(result, DATA_SHARE_ERROR); + LOG_INFO("User_Define_func_No_ExtSpCtl_Test001::End"); +} + +class MockDataShareServiceProxy : public DataShareServiceProxy { +public: + explicit MockDataShareServiceProxy(const sptr& impl) : DataShareServiceProxy(impl) {} + ~MockDataShareServiceProxy() = default; + + std::shared_ptr Query(const Uri &uri, const Uri &extUri, const DataSharePredicates &predicates, + std::vector &columns, DatashareBusinessError &businessError) + { + businessError.SetCode(E_OK); + std::this_thread::sleep_for(std::chrono::seconds(3)); // sleep 3s + return nullptr; + } +}; + +/** +* @tc.name: QueryTimeoutTest002 +* @tc.desc: Test Query function with timeout option +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Create GeneralControllerServiceImpl and call Query with default option + 2. Set option timeout to 1 and call Query function again + 3. Set pool_ to nullptr and call Query function the third time +* @tc.experct: All Query calls return nullptr +*/ +HWTEST_F(DataShareHelperImplTest, QueryTimeoutTest002, TestSize.Level0) +{ + LOG_INFO("QueryTimeoutTest002::Start"); + sptr remoteObject; + std::shared_ptr service = std::make_shared(remoteObject); + auto manager = DataShareManagerImpl::GetInstance(); + manager->dataShareService_ = static_cast>(service); + auto generalCtl = GeneralControllerServiceImpl("datashare://datasharehelperimpl"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataSharePredicates predicates; + std::vector columns; + DataShareOption option; + DatashareBusinessError businessError; + auto res = generalCtl.Query(uri, predicates, columns, businessError, option); + EXPECT_EQ(res, nullptr); + + option.timeout = 1; + res = generalCtl.Query(uri, predicates, columns, businessError, option); + EXPECT_EQ(businessError.GetCode(), E_TIMEOUT_ERROR); + + option.timeout = 4000; // time out lager than task execute time + res = generalCtl.Query(uri, predicates, columns, businessError, option); + EXPECT_EQ(businessError.GetCode(), E_OK); + + generalCtl.pool_ = nullptr; + res = generalCtl.Query(uri, predicates, columns, businessError, option); + EXPECT_EQ(businessError.GetCode(), E_EXECUTOR_POOL_IS_NULL); + LOG_INFO("QueryTimeoutTest002::End"); +} + +/** +* @tc.name: QueryTimeoutTest003 +* @tc.desc: Test Query function timeout scenarios with different timeout values +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: None +* @tc.step: + 1. Set up MockDataShareServiceProxy and GeneralControllerServiceImpl + 2. Call Query with timeout less than task execute time + 3. Call Query with timeout larger than task execute time +* @tc.experct: First call returns E_TIMEOUT_ERROR, second call returns E_OK +*/ +HWTEST_F(DataShareHelperImplTest, QueryTimeoutTest003, TestSize.Level0) +{ + LOG_INFO("QueryTimeoutTest003::Start"); + sptr remoteObject; + std::shared_ptr service = std::make_shared(remoteObject); + auto manager = DataShareManagerImpl::GetInstance(); + manager->dataShareService_ = static_cast>(service); + + auto generalCtl = std::make_shared("datashare://datasharehelperimpl"); + auto helper = DataShareHelperImplTest::GetInstance(); + helper->generalCtl_ = generalCtl; + + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataSharePredicates predicates; + std::vector columns; + DataShareOption option; + option.timeout = 2000; // time out less than task execute time + DatashareBusinessError businessError; + auto res = helper->Query(uri, predicates, columns, option, &businessError); + EXPECT_EQ(businessError.GetCode(), E_TIMEOUT_ERROR); + + option.timeout = 4000; // time out lager than task execute time + res = helper->Query(uri, predicates, columns, option, &businessError); + EXPECT_EQ(businessError.GetCode(), E_OK); + + option.timeout = 0; + res = helper->Query(uri, predicates, columns, option, &businessError); + EXPECT_EQ(businessError.GetCode(), E_OK); + LOG_INFO("QueryTimeoutTest003::End"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/datashare_helper_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/datashare_helper_test.cpp new file mode 100644 index 00000000..7fecb5d7 --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/datashare_helper_test.cpp @@ -0,0 +1,254 @@ +/* + * 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 "datashare_helper.h" +#include "datashare_helper_impl.h" +#include "datashare_log.h" +#include "datashare_uri_utils.h" +#include "iservice_registry.h" +#include "ikvstore_data_service_mock.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; + +constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; +std::string NON_SILENT_ACCESS_URI = "datashare:///com.acts.datasharetest"; +std::string NON_SILENT_ACCESS_ERROR_URI = "datashare:///com.acts.test"; +constexpr int DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID = 1301; + +class DataShareHelperTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +void DataShareManagerImplHelper() +{ + auto helper = DataShareManagerImpl::GetInstance(); + helper->dataShareService_ = nullptr; + auto manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + auto remoteObject = manager->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); + sptr mockProxy = sptr + (new MockDataShareKvServiceProxy(remoteObject)); + EXPECT_CALL(*mockProxy, GetFeatureInterface(testing::_)) + .WillOnce(testing::Return(nullptr)); + helper->dataMgrService_ = (sptr)mockProxy; +} + +/** + * @tc.name: + * @tc.desc: test Creator function when options.isProxy_ = false and options.token_ = nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what options.isProxy_ = false and options.token_ = nullptr + 2.call Creator function and check the result + * @tc.experct: Creator failed and reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreatorTest001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreatorTest001::Start"); + std::string strUri = "testUri"; + CreateOptions options; + options.isProxy_ = false; + options.token_ = nullptr; + std::string bundleName = "testBundle"; + int waitTime = 1; + bool isSystem = true; + auto result = DataShareHelper::Creator(strUri, options, bundleName, waitTime, isSystem); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreatorTest001::End"); +} + +/** + * @tc.name: + * @tc.desc: test Creator function when options.isProxy_ = true and options.token_ = nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what options.isProxy_ = true and options.token_ = nullptr + 2.call Creator function and check the result + * @tc.experct: Creator failed and reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreatorTest002, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreatorTest002::Start"); + std::string strUri = "testUri"; + CreateOptions options; + options.isProxy_ = true; + options.token_ = nullptr; + std::string bundleName = "testBundle"; + int waitTime = 1; + bool isSystem = true; + auto result = DataShareHelper::Creator(strUri, options, bundleName, waitTime, isSystem); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreatorTest002::End"); +} + +/** + * @tc.name: + * @tc.desc: test Creator function when options.isProxy_ = false and options.token_ != nullptr + * @tc.type: FUNC + * @tc.require:issueICDSBD + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what options.isProxy_ = false and options.token_ != nullptr + 2.call Creator function and check the result + * @tc.experct: Creator success and not reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreatorTest003, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreatorTest003::Start"); + CreateOptions options; + options.isProxy_ = false; + +auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); +EXPECT_NE(saManager, nullptr); +auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID); +EXPECT_NE(remoteObj, nullptr); +options.token_ = remoteObj; +auto result = DataShareHelper::Creator(NON_SILENT_ACCESS_URI, options); +EXPECT_NE(result, nullptr); +LOG_INFO("DataShareHelperTest CreatorTest003::End"); +} + +/** + * @tc.name: + * @tc.desc: test Creator function when options.isProxy_ = true and options.token_ != nullptr + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what options.isProxy_ = true and options.token_ != nullptr + 2.call Creator function and check the result + * @tc.experct: Creator failed and not reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreatorTest004, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreatorTest004::Start"); + CreateOptions options; + options.isProxy_ = true; + + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + EXPECT_NE(saManager, nullptr); + auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID); + EXPECT_NE(remoteObj, nullptr); + options.token_ = remoteObj; + auto result = DataShareHelper::Creator(NON_SILENT_ACCESS_ERROR_URI, options); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreatorTest004::End"); +} + +/** + * @tc.name: + * @tc.desc: test CreateExtHelper function when Uri contains "appIndex=" + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what Uri contains "appIndex=" + 2.call CreateExtHelper function and check the result + * @tc.experct: CreateExtHelper failed and reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreateExtHelper001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreateExtHelper001::Start"); + OHOS::Uri uri("datashareproxy://com.acts.ohos.data.datasharetest/test?appIndex=abcd"); + uri.query_ = ("appIndex=abcd"); + sptr token = nullptr; + int waitTime = 1000; + bool isSystem = false; + auto result = DataShareHelper::CreateExtHelper(uri, token, waitTime, isSystem); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreateExtHelper001::End"); +} + +/** + * @tc.name: SetSilentSwitch001 + * @tc.desc: test SetSilentSwitch function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object + 2.call SetSilentSwitch function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.experct: SetSilentSwitch failed and reutrn DATA_SHARE_ERROR + */ +HWTEST_F(DataShareHelperTest, SetSilentSwitch001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest SetSilentSwitch001::Start"); + DataShareManagerImplHelper(); + OHOS::Uri uri("datashareproxy://com.acts.ohos.data.datasharetest/test?appIndex=abcd"); + uri.query_ = ("appIndex=abcd"); + bool enable = false; + bool isSystem = false; + auto result = DataShareHelper::SetSilentSwitch(uri, enable, isSystem); + EXPECT_EQ(result, DATA_SHARE_ERROR); + LOG_INFO("DataShareHelperTest SetSilentSwitch001::End"); +} + +/** + * @tc.name: GetSilentProxyStatus001 + * @tc.desc: test GetSilentProxyStatus function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object + 2.call GetSilentProxyStatus function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.experct: GetSilentProxyStatus failed and reutrn E_ERROR + */ +HWTEST_F(DataShareHelperTest, GetSilentProxyStatus001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest GetSilentProxyStatus001::Start"); + DataShareManagerImplHelper(); + std::string uri = "datashareproxy://com.acts.ohos.data.datasharetest/test?appIndex=abcd"; + bool isSystem = false; + auto result = DataShareHelper::GetSilentProxyStatus(uri, isSystem); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareHelperTest GetSilentProxyStatus001::End"); +} + +/** + * @tc.name: CreateServiceHelper001 + * @tc.desc: test CreateExtHelper function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object + 2.call CreateServiceHelper function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.experct: CreateServiceHelper failed and reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreateServiceHelper001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreateServiceHelper001::Start"); + DataShareManagerImplHelper(); + std::string exuri = "testExuri"; + std::string bundleName = "bundleName"; + bool isSystem = false; + auto result = DataShareHelper::CreateServiceHelper(exuri, bundleName, isSystem); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreateServiceHelper001::End"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/datashare_proxy_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/datashare_proxy_test.cpp new file mode 100644 index 00000000..132ba33a --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/datashare_proxy_test.cpp @@ -0,0 +1,221 @@ +/* + * 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 "datashare_proxy.h" + +#include + +#include "accesstoken_kit.h" +#include "data_ability_observer_interface.h" +#include "datashare_connection.h" +#include "datashare_errno.h" +#include "datashare_helper.h" +#include "datashare_log.h" +#include "extension_manager_proxy.h" +#include "general_controller.h" +#include "general_controller_provider_impl.h" +#include "general_controller_service_impl.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::AAFwk; +class DataShareProxyTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +class RemoteObjectTest : public IRemoteObject { +public: + explicit RemoteObjectTest(std::u16string descriptor) : IRemoteObject(descriptor) {} + ~RemoteObjectTest() {} + + int32_t GetObjectRefCount() + { + return 0; + } + int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + return 0; + } + bool AddDeathRecipient(const sptr &recipient) + { + return true; + } + bool RemoveDeathRecipient(const sptr &recipient) + { + return true; + } + int Dump(int fd, const std::vector &args) + { + return 0; + } +}; + +class IDataAbilityObserverTest : public DataAbilityObserverStub { +public: + IDataAbilityObserverTest() {} + ~IDataAbilityObserverTest() + {} + + void OnChange() + { + GTEST_LOG_(INFO) << "OnChange enter"; + } +}; + +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; + +void DataShareProxyTest::SetUpTestCase(void) {} +void DataShareProxyTest::TearDownTestCase(void) {} +void DataShareProxyTest::SetUp(void) {} +void DataShareProxyTest::TearDown(void) {} + +/** +* @tc.name: DataShareProxy_RegisterObserverExtProvider_Test_001 +* @tc.desc: Verify basic functionality of RegisterObserverExtProvider method +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with test URI and token + 2. Initialize DataShareProxy and assign to connection + 3. Get proxy instance and verify it's not null + 4. Create test observer and call RegisterObserverExtProvider + 5. Check returned result code +* @tc.expect: + 1. All objects are successfully initialized + 2. RegisterObserverExtProvider returns 0 (E_OK) +*/ +HWTEST_F(DataShareProxyTest, DataShareProxy_RegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareProxy_RegisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + + connection->dataShareProxy_ = tokenProxy; + ASSERT_NE(connection->dataShareProxy_, nullptr); + auto proxy = connection->GetDataShareProxy(uri, token); + ASSERT_NE(proxy, nullptr); + + // Observer not null + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + ASSERT_NE(dataObserver, nullptr); + // datashare_stub returns default 0(E_OK) + int ret = proxy->RegisterObserverExtProvider(uri, dataObserver, true, { false }); + EXPECT_EQ(ret, 0); + + LOG_INFO("DataShareProxy_RegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareProxy_UnregisterObserverExtProvider_Test_001 +* @tc.desc: Verify basic functionality of UnregisterObserverExtProvider method +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with test URI and token + 2. Initialize DataShareProxy and assign to connection + 3. Get proxy instance and verify it's not null + 4. Create test observer and call UnregisterObserverExtProvider + 5. Check returned result code +* @tc.expect: + 1. All objects are successfully initialized + 2. UnregisterObserverExtProvider returns 0 (E_OK) +*/ +HWTEST_F(DataShareProxyTest, DataShareProxy_UnregisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareProxy_UnregisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + connection->dataShareProxy_ = tokenProxy; + auto proxy = connection->GetDataShareProxy(uri, token); + ASSERT_NE(proxy, nullptr); + + // observer not null + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + ASSERT_NE(dataObserver, nullptr); + // datashare_stub returns default 0(E_OK) + int ret = proxy->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(ret, 0); + + LOG_INFO("DataShareProxy_UnregisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareProxy_NotifyChangeExtProvider_Test_001 +* @tc.desc: Verify basic functionality of NotifyChangeExtProvider method +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create DataShareConnection with test URI and token + 2. Initialize DataShareProxy and assign to connection + 3. Get proxy instance and verify it's not null + 4. Create test ChangeInfo object and call NotifyChangeExtProvider + 5. Check returned result code +* @tc.expect: + 1. All objects are successfully initialized + 2. NotifyChangeExtProvider returns 0 (E_OK) +*/ +HWTEST_F(DataShareProxyTest, DataShareProxy_NotifyChangeExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareProxy_NotifyChangeExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + connection->dataShareProxy_ = tokenProxy; + auto proxy = connection->GetDataShareProxy(uri, token); + ASSERT_NE(proxy, nullptr); + + ChangeInfo changeInfo = { ChangeInfo::ChangeType::INSERT, { uri } }; + // datashare_stub returns default 0(E_OK) + int ret = proxy->NotifyChangeExtProvider(changeInfo); + EXPECT_EQ(ret, 0); + + LOG_INFO("DataShareProxy_NotifyChangeExtProvider_Test_001::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/datashare_stub_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/datashare_stub_test.cpp new file mode 100644 index 00000000..29d32050 --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/datashare_stub_test.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "datashare_stub.h" + +#include + +#include "accesstoken_kit.h" +#include "data_ability_observer_stub.h" +#include "datashare_business_error.h" +#include "datashare_errno.h" +#include "datashare_itypes_utils.h" +#include "datashare_log.h" +#include "datashare_operation_statement.h" +#include "datashare_stub_impl.h" +#include "extension_manager_proxy.h" +#include "idatashare.h" +#include "ipc_skeleton.h" +#include "ipc_types.h" +#include "ishared_result_set.h" + + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace DistributedShare::DataShare; +using namespace OHOS::AAFwk; +using ChangeInfo = AAFwk::ChangeInfo; +class DataShareStubTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + + +class IDataAbilityObserverTest : public DataAbilityObserverStub { +public: + IDataAbilityObserverTest() {} + ~IDataAbilityObserverTest() + {} + + void OnChange() + { + GTEST_LOG_(INFO) << "OnChange enter"; + } +}; + +class TestDataShareStub : public DataShareStub { +public: + TestDataShareStub() {} + ~TestDataShareStub() {} + int OpenFile(const Uri &uri, const std::string &mode) + { + return 0; + } + int OpenRawFile(const Uri &uri, const std::string &mode) + { + return 0; + } + int Insert(const Uri &uri, const DataShareValuesBucket &value) + { + return 0; + } + int Update(const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) + { + return 0; + } + int Delete(const Uri &uri, const DataSharePredicates &predicates) + { + return 0; + } + std::shared_ptr Query(const Uri &uri, const DataSharePredicates &predicates, + std::vector &columns, DatashareBusinessError &businessError) + { + return nullptr; + } + std::string GetType(const Uri &uri) + { + return ""; + } + int BatchInsert(const Uri &uri, const std::vector &values) + { + return 0; + } + bool RegisterObserver(const Uri &uri, const sptr &dataObserver) + { + return true; + } + bool UnregisterObserver(const Uri &uri, const sptr &dataObserver) + { + return true; + } + bool NotifyChange(const Uri &uri) + { + return true; + } + Uri NormalizeUri(const Uri &uri) + { + return uri; + } + Uri DenormalizeUri(const Uri &uri) + { + return uri; + } + std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) + { + return {}; + } +}; + +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::shared_ptr dataShareStub = std::make_shared(); +std::u16string InterfaceToken = u"OHOS.DataShare.IDataShare"; + +void DataShareStubTest::SetUpTestCase(void) {} +void DataShareStubTest::TearDownTestCase(void) {} +void DataShareStubTest::SetUp(void) {} +void DataShareStubTest::TearDown(void) {} + +/** +* @tc.name: DataShareStub_CmdRegisterObserverExtProvider_Test_001 +* @tc.desc: Verify functionality of CMD_REGISTER_OBSERVEREXT_PROVIDER command handling +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create test URI and IDataAbilityObserverTest instance + 2. Prepare message parcel with interface token and parameters + 3. Call OnRemoteRequest with REGISTER_OBSERVEREXT_PROVIDER command + 4. Check returned error code and unmarshal result +* @tc.expect: + 1. All objects are successfully initialized + 2. OnRemoteRequest returns 0 (success) + 3. Unmarshaled result code is 0 (E_OK) +*/ +HWTEST_F(DataShareStubTest, DataShareStub_CmdRegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareStub_CmdRegisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + ASSERT_NE(dataObserver, nullptr); + uint32_t code = static_cast(IDataShareInterfaceCode::CMD_REGISTER_OBSERVEREXT_PROVIDER); + + MessageParcel data; + data.WriteInterfaceToken(InterfaceToken); + RegisterOption registerOption; + bool ret = ITypesUtil::Marshal(data, uri, dataObserver->AsObject(), true, registerOption); + EXPECT_TRUE(ret); + + MessageParcel reply; + MessageOption option; + ASSERT_NE(dataShareStub, nullptr); + int errCode = dataShareStub->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(errCode, 0); + ret = ITypesUtil::Unmarshal(reply, errCode); + EXPECT_TRUE(ret); + // return default errCode 0(E_OK) + EXPECT_EQ(errCode, 0); + + LOG_INFO("DataShareStub_CmdRegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareStub_CmdUnregisterObserverExtProvider_Test_001 +* @tc.desc: Verify functionality of CMD_UNREGISTER_OBSERVEREXT_PROVIDER command handling +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create test URI and IDataAbilityObserverTest instance + 2. Prepare message parcel with interface token and parameters + 3. Call OnRemoteRequest with UNREGISTER_OBSERVEREXT_PROVIDER command + 4. Check returned error code and unmarshal result +* @tc.expect: + 1. All objects are successfully initialized + 2. OnRemoteRequest returns 0 (success) + 3. Unmarshaled result code is 0 (E_OK) +*/ +HWTEST_F(DataShareStubTest, DataShareStub_CmdUnregisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareStub_CmdUnregisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + ASSERT_NE(dataObserver, nullptr); + uint32_t code = static_cast(IDataShareInterfaceCode::CMD_UNREGISTER_OBSERVEREXT_PROVIDER); + + MessageParcel data; + data.WriteInterfaceToken(InterfaceToken); + bool ret = ITypesUtil::Marshal(data, uri, dataObserver->AsObject()); + EXPECT_TRUE(ret); + + MessageParcel reply; + MessageOption option; + int errCode = dataShareStub->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(errCode, 0); + ret = ITypesUtil::Unmarshal(reply, errCode); + EXPECT_TRUE(ret); + // return default errCode 0(E_OK) + EXPECT_EQ(errCode, 0); + + LOG_INFO("DataShareStub_CmdUnregisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareStub_CmdNotifyChangeExtProvider_Test_001 +* @tc.desc: Verify functionality of CMD_NOTIFY_CHANGEEXT_PROVIDER command handling +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create test URI and ChangeInfo object + 2. Prepare message parcel with interface token and marshaled ChangeInfo + 3. Call OnRemoteRequest with NOTIFY_CHANGEEXT_PROVIDER command + 4. Check returned error code and unmarshal result +* @tc.expect: + 1. All objects are successfully initialized + 2. OnRemoteRequest returns 0 (success) + 3. Unmarshaled result code is 0 (E_OK) +*/ +HWTEST_F(DataShareStubTest, DataShareStub_CmdNotifyChangeExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareStub_CmdNotifyChangeExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + ChangeInfo changeInfo = { ChangeInfo::ChangeType::INSERT, { uri } }; + uint32_t code = static_cast(IDataShareInterfaceCode::CMD_NOTIFY_CHANGEEXT_PROVIDER); + + MessageParcel data; + data.WriteInterfaceToken(InterfaceToken); + bool ret = ChangeInfo::Marshalling(changeInfo, data); + EXPECT_TRUE(ret); + + MessageParcel reply; + MessageOption option; + int errCode = dataShareStub->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(errCode, 0); + ret = ITypesUtil::Unmarshal(reply, errCode); + EXPECT_TRUE(ret); + // return default errCode 0(E_OK) + EXPECT_EQ(errCode, 0); + + LOG_INFO("DataShareStub_CmdNotifyChangeExtProvider_Test_001::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/errorcode_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/errorcode_test.cpp index 9b8841b2..2a99cc2e 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/errorcode_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/errorcode_test.cpp @@ -29,26 +29,22 @@ namespace DataShare { using namespace testing::ext; using namespace OHOS::Security::AccessToken; constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; +std::string DATA_SHARE_URI = "datashare:///com.acts.errorcodetest"; +std::string SLIENT_ACCESS_URI = "datashare:///com.acts.errorcodetest/entry/DB00/TBL00?Proxy=true"; +std::string TBL_STU_NAME = "name"; +std::string TBL_STU_AGE = "age"; +std::shared_ptr g_slientAccessHelper; +std::shared_ptr dataShareHelper; + class ErrorCodeTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); void SetUp(); void TearDown(); - -protected: - static std::shared_ptr CreateDataShareHelper(int32_t saId, std::string uri); - static inline std::string DATA_SHARE_URI = "datashare:///com.acts.errorcodetest"; - static inline std::string SLIENT_ACCESS_URI = "datashare:///com.acts.errorcodetest/entry/DB00/TBL00?Proxy=true"; - std::string TBL_STU_NAME = "name"; - std::string TBL_STU_AGE = "age"; - static std::shared_ptr g_slientAccessHelper; - static std::shared_ptr dataShareHelper; }; -std::shared_ptr ErrorCodeTest::g_slientAccessHelper; -std::shared_ptr ErrorCodeTest::dataShareHelper; -std::shared_ptr ErrorCodeTest::CreateDataShareHelper(int32_t saId, std::string uri) +std::shared_ptr CreateDataShareHelper(int32_t systemAbilityId, std::string uri) { LOG_INFO("CreateDataShareHelper start"); auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); @@ -56,8 +52,8 @@ std::shared_ptr ErrorCodeTest::CreateDataShareHelper LOG_ERROR("GetSystemAbilityManager get samgr failed."); return nullptr; } - auto remoteObj = saManager->GetSystemAbility(saId); - while (remoteObj == nullptr) { + auto remoteObj = saManager->GetSystemAbility(systemAbilityId); + if (remoteObj == nullptr) { LOG_ERROR("GetSystemAbility service failed."); return nullptr; } @@ -124,6 +120,19 @@ void ErrorCodeTest::TearDownTestCase(void) void ErrorCodeTest::SetUp(void) {} void ErrorCodeTest::TearDown(void) {} +/** +* @tc.name: ErrorCodeTest_Insert_Test_001 +* @tc.desc: Verify successful insertion operation returns positive ID +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get slient access helper instance + 2. Create test URI and DataShareValuesBucket with student data + 3. Call Insert method with URI and values bucket + 4. Check if returned ID is positive +* @tc.experct: Insert operation succeeds and returns positive ID +*/ HWTEST_F(ErrorCodeTest, ErrorCodeTest_Insert_Test_001, TestSize.Level0) { LOG_INFO("ErrorCodeTest_Insert_Test_001::Start"); @@ -140,6 +149,21 @@ HWTEST_F(ErrorCodeTest, ErrorCodeTest_Insert_Test_001, TestSize.Level0) LOG_INFO("ErrorCodeTest_Insert_Test_001::End"); } +/** +* @tc.name: ErrorCodeTest_QUERY_Test_001 +* @tc.desc: Verify query operations return correct error codes for valid and invalid URIs +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Query existing data with valid URI and check for success + 2. Verify row count is 1 for existing data + 3. Query with invalid URI and check error code + 4. Verify result set is null for invalid URI +* @tc.experct: + 1. Valid query returns 0 error code and 1 row + 2. Invalid query returns E_DB_NOT_EXIST error and null result set +*/ HWTEST_F(ErrorCodeTest, ErrorCodeTest_QUERY_Test_001, TestSize.Level0) { LOG_INFO("ErrorCodeTest_QUERY_Test_001::Start"); @@ -166,6 +190,22 @@ HWTEST_F(ErrorCodeTest, ErrorCodeTest_QUERY_Test_001, TestSize.Level0) LOG_INFO("ErrorCodeTest_QUERY_Test_001::End"); } +/** +* @tc.name: ErrorCodeTest_QUERY_Test_002 +* @tc.desc: Verify unauthorized query returns correct error code +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Insert test data using dataShareHelper + 2. Query inserted data with predicates + 3. Check error code and result set for unauthorized access + 4. Clean up by deleting inserted data +* @tc.experct: + 1. Insert succeeds with positive ID + 2. Query returns 401 error code and null result set + 3. Delete operation succeeds with positive count +*/ HWTEST_F(ErrorCodeTest, ErrorCodeTest_QUERY_Test_002, TestSize.Level0) { LOG_INFO("ErrorCodeTest_QUERY_Test_002::Start"); diff --git a/data_share/test/native/unittest/mediadatashare_test/src/join_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/join_test.cpp index a8563cd9..6b3b35c3 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/join_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/join_test.cpp @@ -29,6 +29,14 @@ namespace DataShare { using namespace testing::ext; using namespace OHOS::Security::AccessToken; constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::string SLIENT_ACCESS_URI = "datashare:///com.acts.datasharetest?Proxy=true"; +std::string USER_URI = "datashare:///com.acts.datasharetest/entry/DB00/user?Proxy=true"; +std::string BOOK_URI = "datashare:///com.acts.datasharetest/entry/DB00/book?Proxy=true"; +std::string TBL_STU_NAME = "name"; +std::string TBL_STU_AGE = "age"; +std::shared_ptr g_slientAccessHelper; + class JoinTest : public testing::Test { public: static void SetUpTestCase(void); @@ -38,20 +46,9 @@ public: static void InsertUserDates(); static void InsertBookDates(); int ResultSize(std::shared_ptr &resultSet); - -protected: - static constexpr const char *DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; - static constexpr const char *SLIENT_ACCESS_URI = "datashare:///com.acts.datasharetest?Proxy=true"; - static constexpr const char *USER_URI = "datashare:///com.acts.datasharetest/entry/DB00/user?Proxy=true"; - static constexpr const char *BOOK_URI = "datashare:///com.acts.datasharetest/entry/DB00/book?Proxy=true"; - static std::shared_ptr CreateDataShareHelper(int32_t saId, std::string uri); - static std::shared_ptr g_slientAccessHelper; - std::string TBL_STU_NAME = "name"; - std::string TBL_STU_AGE = "age"; }; -std::shared_ptr JoinTest::g_slientAccessHelper; -std::shared_ptr JoinTest::CreateDataShareHelper(int32_t saId, std::string uri) +std::shared_ptr CreateDataShareHelper(int32_t systemAbilityId, std::string uri) { LOG_INFO("CreateDataShareHelper start"); auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); @@ -59,8 +56,8 @@ std::shared_ptr JoinTest::CreateDataShareHelper(int3 LOG_ERROR("GetSystemAbilityManager get samgr failed."); return nullptr; } - auto remoteObj = saManager->GetSystemAbility(saId); - while (remoteObj == nullptr) { + auto remoteObj = saManager->GetSystemAbility(systemAbilityId); + if (remoteObj == nullptr) { LOG_ERROR("GetSystemAbility service failed."); return nullptr; } @@ -207,6 +204,21 @@ int JoinTest::ResultSize(std::shared_ptr &resultSet) return count; } +/** +* @tc.name: Join_CrossJoin_001 +* @tc.desc: Verify cross join operation returns correct results +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create cross join predicate with "user.userId = book.userId" condition + 2. Execute query on user table with join predicate + 3. Verify row count is 3 + 4. Check first row data matches expected values +* @tc.experct: + 1. Query returns 3 rows + 2. First row contains correct user and book data for userId = 1 +*/ HWTEST_F(JoinTest, Join_CrossJoin_001, TestSize.Level0) { auto helper = g_slientAccessHelper; @@ -256,6 +268,22 @@ HWTEST_F(JoinTest, Join_CrossJoin_001, TestSize.Level0) EXPECT_EQ(1, userId_1); } +/** +* @tc.name: Join_InnerJoin_001 +* @tc.require: None +* @tc.desc: Verify inner join with filter returns correct single result +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Create inner join predicate with "user.userId = book.userId" condition + 2. Add filter for book.name = "SanGuo" + 3. Execute query on user table with join predicate + 4. Verify row count is 1 + 5. Check row data matches expected values for "SanGuo" book +* @tc.experct: + 1. Query returns 1 row + 2. Row contains correct user and book data for "SanGuo" book +*/ HWTEST_F(JoinTest, Join_InnerJoin_001, TestSize.Level0) { auto helper = g_slientAccessHelper; @@ -306,6 +334,22 @@ HWTEST_F(JoinTest, Join_InnerJoin_001, TestSize.Level0) EXPECT_EQ(1, userId_1); } +/** +* @tc.name: Join_LeftOuterJoin_001 +* @tc.desc: Verify left outer join with Using clause returns correct result +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create left outer join predicate using "userId" column + 2. Add filter for name = "SanGuo" + 3. Execute query on user table with join predicate + 4. Verify row count is 1 + 5. Check row data matches expected values +* @tc.experct: + 1. Query returns 1 row + 2. Row contains correct user and book data for matching record +*/ HWTEST_F(JoinTest, Join_LeftOuterJoin_001, TestSize.Level0) { auto helper = g_slientAccessHelper; @@ -352,6 +396,20 @@ HWTEST_F(JoinTest, Join_LeftOuterJoin_001, TestSize.Level0) EXPECT_EQ("SanGuo", name); } +/** +* @tc.name: Join_LeftOuterJoin_002 +* @tc.desc: Verify left outer join returns all user records with matching books +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create left outer join predicate with "user.userId = book.userId" condition + 2. Execute query on user table with join predicate + 3. Verify row count is 5 (all users including those without books) +* @tc.experct: + 1. Query returns 5 rows + 2. All user records are included in results +*/ HWTEST_F(JoinTest, Join_LeftOuterJoin_002, TestSize.Level0) { auto helper = g_slientAccessHelper; diff --git a/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp index 93ffe659..99b69215 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/mediadatashare_unit_test.cpp @@ -249,6 +249,18 @@ void MediaDataShareUnitTest::TearDownTestCase(void) void MediaDataShareUnitTest::SetUp(void) {} void MediaDataShareUnitTest::TearDown(void) {} +/** +* @tc.name: MediaDataShare_Predicates_Test_001 +* @tc.desc: Verify query with Equals and Limit predicates returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with Equals("name", "dataShareTest003") and Limit(1, 0) + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 1 row +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_001::Start"); @@ -267,6 +279,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_001, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_001, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_002 +* @tc.desc: Verify query with NotEqualTo predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with NotEqualTo("name", "dataShareTest003") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 2 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_002, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_002::Start"); @@ -284,6 +308,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_002, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_002, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_003 +* @tc.desc: Verify query with Contains predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with Contains("name", "dataShareTest") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 3 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_003, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_003::Start"); @@ -301,6 +337,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_003, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_003, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_004 +* @tc.desc: Verify query with BeginsWith predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with BeginsWith("name", "dataShare") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 3 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_004, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_004::Start"); @@ -318,6 +366,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_004, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_004, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_005 +* @tc.desc: Verify query with EndsWith predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with EndsWith("name", "003") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 1 row +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_005, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_005::Start"); @@ -335,6 +395,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_005, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_005, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_006 +* @tc.desc: Verify query with IsNull predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with IsNull("name") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 0 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_006, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_006::Start"); @@ -352,6 +424,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_006, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_006, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_007 +* @tc.desc: Verify query with IsNotNull predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with IsNotNull("name") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 3 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_007, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_007::Start"); @@ -369,6 +453,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_007, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_007, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_008 +* @tc.desc: Verify query with Like predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with Like("name", "%Test003") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 1 row +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_008, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_008::Start"); @@ -386,6 +482,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_008, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_008, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_009 +* @tc.desc: Verify query with Glob predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with Glob("name", "dataShareTes?003") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 1 row +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_009, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_009::Start"); @@ -403,6 +511,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_009, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_009, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_010 +* @tc.desc: Verify query with Between predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with Between("age", "0", "999") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 1 row +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_010, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_010::Start"); @@ -420,6 +540,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_010, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_010, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_011 +* @tc.desc: Verify query with NotBetween predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with NotBetween("age", "0", "999") + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 2 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_011, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_011::Start"); @@ -437,6 +569,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_011, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_011, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_012 +* @tc.desc: Verify query with GreaterThan predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with GreaterThan("age", 999) + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 2 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_012, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_012::Start"); @@ -454,6 +598,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_012, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_012, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_013 +* @tc.desc: Verify query with LessThan predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with LessThan("age", 1000) + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 1 row +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_013, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_013::Start"); @@ -471,6 +627,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_013, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_013, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_014 +* @tc.desc: Verify query with GreaterThanOrEqualTo predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with GreaterThanOrEqualTo("age", 1000) + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 2 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_014, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_014::Start"); @@ -488,6 +656,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_014, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_014, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_015 +* @tc.desc: Verify query with LessThanOrEqualTo predicate returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with LessThanOrEqualTo("age", 1000) + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 2 rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_015, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_015::Start"); @@ -505,6 +685,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_015, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_015, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_016 +* @tc.desc: Verify query with combined predicates (AND/OR) returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create complex predicates with nested conditions + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 1 row +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_016, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_016::Start"); @@ -527,6 +719,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_016, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_016, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_017 +* @tc.desc: Verify query with AND combined predicates returns correct result count +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates combining two EqualTo conditions with AND + 2. Execute query with these predicates + 3. Check the returned row count +* @tc.expected: Query returns exactly 1 row +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_017, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_017::Start"); @@ -544,6 +748,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_017, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_017, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_018 +* @tc.desc: Verify query with ascending order predicate returns correctly ordered results +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with OrderByAsc("age") + 2. Execute query with these predicates + 3. Check the name of the first row in results +* @tc.expected: First row contains name "dataShareTest005" +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_018, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_018::Start"); @@ -564,6 +780,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_018, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_018, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_019 +* @tc.desc: Verify query with descending order predicate returns correctly ordered results +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with OrderByDesc("phoneNumber") + 2. Execute query with these predicates + 3. Check the name of the first row in results +* @tc.expected: First row contains name "dataShareTest005" +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_019, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_019::Start"); @@ -584,6 +812,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_019, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_019, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_020 +* @tc.desc: Verify predicate setting mode can be set and retrieved correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create empty predicates + 2. Set setting mode to PREDICATES_METHOD + 3. Retrieve and check the setting mode +* @tc.expected: Retrieved setting mode matches PREDICATES_METHOD +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_020, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_020::Start"); @@ -594,6 +834,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_020, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_020, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_021 +* @tc.desc: Verify predicate operation list is correctly generated +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with Equals("name", "dataShareTest003") + 2. Retrieve the operation list + 3. Verify operation type and parameters +* @tc.expected: Operation list contains correct type and parameters +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_021, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_021::Start"); @@ -612,6 +864,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_021, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_021, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_022 +* @tc.desc: Verify where clause can be set and retrieved correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create empty predicates + 2. Set where clause to "`data2` > ?" + 3. Retrieve and verify the where clause +* @tc.expected: Retrieved where clause matches the set value +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_022, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_023::Start"); @@ -623,6 +887,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_022, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_023, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_023 +* @tc.desc: Verify where arguments can be set and retrieved correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create empty predicates + 2. Set where arguments with vector containing "-5" + 3. Retrieve and verify the where arguments +* @tc.expected: Retrieved where arguments match the set values +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_023, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_024::Start"); @@ -634,6 +910,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_023, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_024, End"); } +/** +* @tc.name: MediaDataShare_Predicates_Test_024 +* @tc.desc: Verify order clause can be set and retrieved correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create empty predicates + 2. Set order clause to "data3" + 3. Retrieve and verify the order clause +* @tc.expected: Retrieved order clause matches the set value +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_024, TestSize.Level0) { LOG_INFO("MediaDataShare_Predicates_Test_025::Start"); @@ -645,6 +933,19 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Predicates_Test_024, TestSize.Le LOG_INFO("MediaDataShare_Predicates_Test_025, End"); } +/** +* @tc.name: MediaDataShare_ValuesBucket_Test_001 +* @tc.desc: Verify DataShareValuesBucket basic operations work correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create empty ValuesBucket and verify it's empty + 2. Add a value and verify it's no longer empty + 3. Retrieve and verify the value + 4. Clear the bucket and verify it's empty again +* @tc.expected: All operations work as expected with correct values +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ValuesBucket_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_ValuesBucket_Test_001::Start"); @@ -664,6 +965,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ValuesBucket_Test_001, TestSize. LOG_INFO("MediaDataShare_ValuesBucket_Test_001 End"); } +/** +* @tc.name: MediaDataShare_ValueObject_Test_001 +* @tc.desc: Verify DataShareValueObject handles various data types correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create ValueObjects with different data types (int, int64, double, bool, vector) + 2. Verify copy and move operations + 3. Check that retrieved values match original values +* @tc.expected: All value types are stored and retrieved correctly +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ValueObject_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_ValueObject_Test_001::Start"); @@ -704,6 +1017,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ValueObject_Test_001, TestSize.L LOG_INFO("MediaDataShare_ValueObject_Test_001 End"); } +/** +* @tc.name: MediaDataShare_batchInsert_Test_001 +* @tc.desc: Verify batch insert operation correctly inserts multiple records +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create two ValuesBuckets with test data + 2. Perform batch insert with these buckets + 3. Verify the number of inserted records +* @tc.expected: Batch insert returns 2 indicating successful insertion of both records +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_batchInsert_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_batchInsert_Test_001::Start"); @@ -724,6 +1049,17 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_batchInsert_Test_001, TestSize.L LOG_INFO("MediaDataShare_batchInsert_Test_001 End"); } +/** +* @tc.name: MediaDataShare_NormalizeUri_Test_001 +* @tc.desc: Verify URI normalization function works correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Call NormalizeUri with media library URI + 2. Compare result with expected normalized URI +* @tc.expected: Normalized URI matches the expected value +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_NormalizeUri_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_NormalizeUri_Test_001::Start"); @@ -735,6 +1071,17 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_NormalizeUri_Test_001, TestSize. LOG_INFO("MediaDataShare_NormalizeUri_Test_001 End"); } +/** +* @tc.name: MediaDataShare_DenormalizeUri_Test_001 +* @tc.desc: Verify URI denormalization function works correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Call DenormalizeUri with media library URI + 2. Compare result with expected denormalized URI +* @tc.expected: Denormalized URI matches the expected value +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_DenormalizeUri_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_DenormalizeUri_Test_001::Start"); @@ -746,6 +1093,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_DenormalizeUri_Test_001, TestSiz LOG_INFO("MediaDataShare_DenormalizeUri_Test_001 End"); } +/** +* @tc.name: MediaDataShare_SingleValue_Test_001 +* @tc.desc: Verify SingleValue handles various data types correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create SingleValue objects with different data types + 2. Verify copy and move operations + 3. Check that retrieved values match original values +* @tc.expected: All value types are stored and retrieved correctly +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_SingleValue_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_SingleValue_Test_001::Start"); @@ -784,6 +1143,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_SingleValue_Test_001, TestSize.L LOG_INFO("MediaDataShare_SingleValue_Test_001 End"); } +/** +* @tc.name: MediaDataShare_MutliValue_Test_001 +* @tc.desc: Verify MutliValue handles various collection types correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create MutliValue objects with different collection types + 2. Verify copy and move operations + 3. Check that retrieved values match original values +* @tc.expected: All collections are stored and retrieved correctly +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_MutliValue_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_MutliValue_Test_001::Start"); @@ -821,6 +1192,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_MutliValue_Test_001, TestSize.Le LOG_INFO("MediaDataShare_MutliValue_Test_001 End"); } +/** +* @tc.name: MediaDataShare_ResultSet_Test_001 +* @tc.desc: Verify default ResultSet behavior with no data +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create empty ResultSet + 2. Attempt various operations (get columns, row count, move to row, get values) + 3. Verify operations return appropriate error codes +* @tc.expected: All operations on empty ResultSet return errors +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_ResultSet_Test_005::Start"); @@ -854,6 +1237,19 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_001, TestSize.Lev LOG_INFO("MediaDataShare_ResultSet_Test_005, End"); } +/** +* @tc.name: MediaDataShare_ResultSet_Test_002 +* @tc.require: None +* @tc.desc: Verify ResultSet column operations work correctly +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: + 1. Query data for "dataShareTest003" + 2. Verify column name retrieval + 3. Check blob retrieval from result set + 4. Verify all column names can be retrieved +* @tc.expected: All column operations return valid results +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_002, TestSize.Level0) { LOG_INFO("MediaDataShare_ResultSet_Test_002::Start"); @@ -885,6 +1281,19 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_002, TestSize.Lev LOG_INFO("MediaDataShare_ResultSet_Test_002, End"); } +/** +* @tc.name: MediaDataShare_ResultSet_Test_003 +* @tc.desc: Verify ResultSet block operations work correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Query data for "dataShareTest003" + 2. Check if result set has a block + 3. Retrieve, set and fill block + 4. Verify block operations maintain correct reference +* @tc.expected: All block operations work as expected +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_003, TestSize.Level0) { LOG_INFO("MediaDataShare_ResultSet_Test_003::Start"); @@ -909,6 +1318,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_003, TestSize.Lev LOG_INFO("MediaDataShare_ResultSet_Test_003, End"); } +/** +* @tc.name: MediaDataShare_ResultSet_Test_004 +* @tc.desc: Verify ResultSet navigation works correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Query data with names containing "dataShareTest" + 2. Move to first row + 3. Attempt navigation with OnGo method +* @tc.expected: Navigation operation returns true indicating success +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_004, TestSize.Level0) { LOG_INFO("MediaDataShare_ResultSet_Test_004::Start"); @@ -927,6 +1348,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_004, TestSize.Lev LOG_INFO("MediaDataShare_ResultSet_Test_004, End"); } +/** +* @tc.name: MediaDataShare_ResultSet_Test_005 +* @tc.desc: Verify empty ResultSet operations return appropriate errors +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create empty ResultSet + 2. Attempt various operations without data + 3. Verify error codes and return values +* @tc.expected: All operations on empty ResultSet return errors +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_005, TestSize.Level0) { LOG_INFO("MediaDataShare_ResultSet_Test_005::Start"); @@ -957,6 +1390,19 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_005, TestSize.Lev LOG_INFO("MediaDataShare_ResultSet_Test_005, End"); } +/** +* @tc.name: MediaDataShare_ResultSet_Test_006 +* @tc.desc: Verify ResultSet data type and value retrieval +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Insert test data with specific age value + 2. Query for the inserted data + 3. Verify data type and value match expectations + 4. Clean up test data +* @tc.expected: Data type is INTEGER and retrieved value matches inserted value +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_006, TestSize.Level0) { LOG_INFO("MediaDataShare_ResultSet_Test_006::Start"); @@ -991,6 +1437,17 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ResultSet_Test_006, TestSize.Lev LOG_INFO("MediaDataShare_ResultSet_Test_006, End"); } +/** +* @tc.name: Creator_IRemoteObjectNull_Test_001 +* @tc.desc: Verify Creator handles null remote object correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Attempt to create DataShareHelper with null IRemoteObject + 2. Check if returned helper is null +* @tc.expected: Creator returns nullptr when remote object is null +*/ HWTEST_F(MediaDataShareUnitTest, Creator_IRemoteObjectNull_Test_001, TestSize.Level0) { LOG_INFO("Creator_IRemoteObjectNull_Test_001::Start"); @@ -1000,6 +1457,18 @@ HWTEST_F(MediaDataShareUnitTest, Creator_IRemoteObjectNull_Test_001, TestSize.Le LOG_INFO("Creator_IRemoteObjectNull_Test_001 End"); } +/** +* @tc.name: Creator_UriError_Test_001 +* @tc.desc: Verify Creator handles invalid URI correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get valid remote object from system ability manager + 2. Attempt to create DataShareHelper with invalid URI + 3. Check if returned helper is null +* @tc.expected: Creator returns nullptr when URI is invalid +*/ HWTEST_F(MediaDataShareUnitTest, Creator_UriError_Test_001, TestSize.Level0) { LOG_INFO("Creator_UriError_Test_001::Start"); @@ -1012,6 +1481,19 @@ HWTEST_F(MediaDataShareUnitTest, Creator_UriError_Test_001, TestSize.Level0) LOG_INFO("Creator_UriError_Test_001 End"); } +/** +* @tc.name: Insert_ConnectionNull_Test_001 +* @tc.desc: Verify operations fail correctly when connection is released +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create DataShareHelper and immediately release it + 2. Attempt insert operation with released connection + 3. Attempt get type operation + 4. Verify error results +* @tc.expected: Insert returns -1 and GetType returns empty string +*/ HWTEST_F(MediaDataShareUnitTest, Insert_ConnectionNull_Test_001, TestSize.Level0) { LOG_INFO("Insert_ConnectionNull_Test_001::Start"); @@ -1037,6 +1519,23 @@ HWTEST_F(MediaDataShareUnitTest, Insert_ConnectionNull_Test_001, TestSize.Level0 LOG_INFO("Insert_ConnectionNull_Test_001 End"); } +/** +* @tc.name: MediaDataShare_CRUD_Test_001 +* @tc.desc: Verify basic CRUD operations (Create, Read, Update, Delete) work correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Insert a new record with name "Datashare_CRUD_Test001" + 2. Update the record to name "Datashare_CRUD_Test002" using predicates + 3. Query for the updated record to verify the change + 4. Delete the record using predicates +* @tc.expected: + 1.Insert returns a positive ID indicating success + 2.Update returns non-negative value indicating success + 3.Query returns exactly 1 row for the updated record + 4.Delete returns non-negative value indicating success +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_CRUD_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_CRUD_Test_001::Start"); @@ -1073,6 +1572,23 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_CRUD_Test_001, TestSize.Level0) LOG_INFO("MediaDataShare_CRUD_Test_001, End"); } +/** +* @tc.name: MediaDataShare_CRUDEX_Test_001 +* @tc.desc: Verify extended CRUD operations with error code returns work correctly +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Insert a new record using InsertEx and verify error code and return value + 2. Update the record using UpdateEx with predicates and verify results + 3. Query for the updated record to confirm changes + 4. Delete the record using DeleteEx and verify results +* @tc.expected: + 1.InsertEx returns error code 0 and non-negative ID + 2.UpdateEx returns error code 0 and non-negative affected rows + 3.Query returns exactly 1 row for the updated record + 4.DeleteEx returns error code 0 and non-negative affected rows +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_CRUDEX_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_CRUDEX_Test_001::Start"); @@ -1110,6 +1626,22 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_CRUDEX_Test_001, TestSize.Level0 LOG_INFO("MediaDataShare_CRUDEX_Test_001, End"); } +/** +* @tc.name: MediaDataShare_ImplPredicates_Test_001 +* @tc.desc: Verify In predicate generates correct operation items +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with In("name", {1, 2, 3}) condition + 2. Retrieve the operation items from predicates + 3. Verify operation type, parameters, and values +* @tc.expected: + 1.Exactly 1 operation item is generated + 2.Operation type is correct for In condition + 3.Parameters contain "name" and the correct integer values + 4.Variant indices match expected types (string and integer vector) +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ImplPredicates_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_ImplPredicates_Test_001::Start"); @@ -1124,7 +1656,8 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ImplPredicates_Test_001, TestSiz std::string str = std::get(operationItems[0].singleParams[0]); std::vector ret = std::get>(operationItems[0].multiParams[0]); EXPECT_EQ(operationItems.size(), 1); - EXPECT_EQ(operationItems[0].singleParams[0].index(), 4); + // index of variant, 3 is string + EXPECT_EQ(operationItems[0].singleParams[0].index(), 3); EXPECT_EQ(str, "name"); EXPECT_EQ(operationItems[0].multiParams[0].index(), 1); for (int i = 0; i < ret.size(); i++) { @@ -1134,6 +1667,18 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ImplPredicates_Test_001, TestSiz LOG_INFO("MediaDataShare_ImplPredicates_Test_001, End"); } +/** +* @tc.name: MediaDataShare_NotImplPredicates_Test_001 +* @tc.desc: Verify multiple predicate combinations generate correct number of operation items +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create predicates with multiple conditions: In, NotIn, Unlike, GroupBy, Distinct, IndexedBy, KeyPrefix, InKeys + 2. Retrieve the operation items from predicates + 3. Verify the total number of operation items +* @tc.expected: Exactly 8 operation items are generated matching the number of conditions +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_NotImplPredicates_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_NotImplPredicates_Test_001::Start"); @@ -1162,30 +1707,119 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_NotImplPredicates_Test_001, Test LOG_INFO("MediaDataShare_NotImplPredicates_Test_001, End"); } +/** +* @tc.name: MediaDataShare_Observer_001 +* @tc.desc: Verify normal registration and operation of non-silent data observer +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Register a data observer for the media library URI + 2. Insert a new record and trigger notification + 3. Delete the record and trigger notification + 4. Unregister the observer +* @tc.expected: + 1.Registration returns 0 indicating success + 2.Insert returns positive ID and notification is triggered + 3.Delete returns positive value and notification is triggered + 4.Unregistration returns 0 indicating success +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_Observer_001, TestSize.Level0) { LOG_INFO("MediaDataShare_Observer_001 start"); std::shared_ptr helper = g_dataShareHelper; ASSERT_TRUE(helper != nullptr); Uri uri(MEDIALIBRARY_DATA_URI); - sptr dataObserver; - helper->RegisterObserver(uri, dataObserver); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + int retVal = helper->RegisterObserver(uri, dataObserver); + EXPECT_EQ(retVal, 0); DataShare::DataShareValuesBucket valuesBucket; valuesBucket.Put("name", "Datashare_Observer_Test001"); - int retVal = helper->Insert(uri, valuesBucket); - EXPECT_EQ((retVal > 0), true); + retVal = helper->Insert(uri, valuesBucket); + EXPECT_GT(retVal, 0); helper->NotifyChange(uri); DataShare::DataSharePredicates deletePredicates; deletePredicates.EqualTo("name", "Datashare_Observer_Test001"); retVal = helper->Delete(uri, deletePredicates); - EXPECT_EQ((retVal >= 0), true); + EXPECT_GT(retVal, 0); helper->NotifyChange(uri); - helper->UnregisterObserver(uri, dataObserver); + retVal = helper->UnregisterObserver(uri, dataObserver); + EXPECT_EQ(retVal, 0); LOG_INFO("MediaDataShare_Observer_001 end"); } +/** +* @tc.name: MediaDataShare_ReregisterObserver_001 +* @tc.desc: Verify error handling when re-registering an existing observer +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Register a data observer for the media library URI + 2. Attempt to register the same observer again + 3. Perform insert and delete operations with notifications + 4. Unregister the observer +* @tc.expected: + 1.First registration returns 0 indicating success + 2.Second registration returns E_REGISTER_ERROR + 3.Insert and delete operations complete successfully + 4.Unregistration returns 0 indicating success +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ReregisterObserver_001, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_ReregisterObserver_001 start"); + std::shared_ptr helper = g_dataShareHelper; + EXPECT_NE(helper, nullptr); + Uri uri(MEDIALIBRARY_DATA_URI); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + int retVal = helper->RegisterObserver(uri, dataObserver); + EXPECT_EQ(retVal, 0); + retVal = helper->RegisterObserver(uri, dataObserver); + EXPECT_EQ(retVal, E_REGISTER_ERROR); + + DataShare::DataShareValuesBucket valuesBucket; + valuesBucket.Put("name", "MediaDataShare_ReregisterObserver_001"); + retVal = helper->Insert(uri, valuesBucket); + EXPECT_GT(retVal, 0); + helper->NotifyChange(uri); + + DataShare::DataSharePredicates deletePredicates; + deletePredicates.EqualTo("name", "MediaDataShare_ReregisterObserver_001"); + retVal = helper->Delete(uri, deletePredicates); + EXPECT_GT(retVal, 0); + helper->NotifyChange(uri); + retVal = helper->UnregisterObserver(uri, dataObserver); + EXPECT_EQ(retVal, 0); + LOG_INFO("MediaDataShare_ReregisterObserver_001 end"); +} + +/** +* @tc.name: MediaDataShare_ObserverExt_001 +* @tc.desc: Verify observer extension functionality for data change notifications +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: DataShareHelper instance is properly initialized and MEDIALIBRARY_DATA_URI is accessible +* @tc.step: + 1. Get DataShareHelper instance and verify it's not null + 2. Create test URI and DataShareObserverTest instance + 3. Register observer extension with the URI + 4. Insert test data and notify INSERT change + 5. Verify observer receives correct INSERT change information + 6. Insert data to descendant URI and notify INSERT change + 7. Verify observer receives correct descendant INSERT change information + 8. Delete test data and notify DELETE change with additional data + 9. Verify observer receives correct DELETE change information + 10. Unregister the observer +* @tc.expect: + 1. DataShareHelper instance is successfully obtained + 2. Test data is inserted successfully (retVal > 0) + 3. Observer receives accurate INSERT change information for main URI + 4. Observer receives accurate INSERT change information for descendant URI + 5. Observer receives accurate DELETE change information including additional data + 6. All operations complete without errors +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_001, TestSize.Level0) { LOG_INFO("MediaDataShare_ObserverExt_001 start"); @@ -1231,6 +1865,28 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_001, TestSize.Level0 LOG_INFO("MediaDataShare_ObserverExt_001 end"); } +/** +* @tc.name: MediaDataShare_UnregisterObserverExt_001 +* @tc.desc: Verify unregister functionality of observer extension +* @tc.type: FUNC +* @tc.require: issueIC8OCN +* @tc.precon: DataShareHelper instance is properly initialized and MEDIALIBRARY_DATA_URI is accessible +* @tc.step: + 1. Get DataShareHelper instance and verify it's not null + 2. Create test URI and DataShareObserverTest instance + 3. Register observer extension with the URI + 4. Insert test data and notify INSERT change + 5. Verify observer receives correct change information + 6. Unregister the observer from the URI + 7. Notify another DELETE change + 8. Verify observer no longer receives change information +* @tc.expect: + 1. DataShareHelper instance is successfully obtained + 2. Test data is inserted successfully (retVal > 0) + 3. Observer receives accurate change information before unregistration + 4. After unregistration, observer does NOT receive change notifications + 5. All operations complete without errors +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_UnregisterObserverExt_001, TestSize.Level0) { LOG_INFO("MediaDataShare_UnregisterObserverExt_001 start"); @@ -1260,6 +1916,22 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_UnregisterObserverExt_001, TestS LOG_INFO("MediaDataShare_UnregisterObserverExt_001 end"); } +/** +* @tc.name: MediaDataShare_ToAbsSharedResultSet_Test_001 +* @tc.desc: Test conversion of DataShare query result to AbsSharedResultSet +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance + 2. Create predicates to filter data by name "dataShareTest003" + 3. Query the media library URI with the predicates and empty columns + 4. Convert the query result to AbsSharedResultSet using RdbDataAbilityUtils + 5. Get the row count from the converted result set +* @tc.expect: + 1.The converted AbsSharedResultSet is not null + 2.The row count of the result set is 1 (matches the expected test data) +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ToAbsSharedResultSet_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_ToAbsSharedResultSet_Test_001::Start"); @@ -1279,6 +1951,20 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ToAbsSharedResultSet_Test_001, T LOG_INFO("MediaDataShare_ToAbsSharedResultSet_Test_001 End"); } +/** +* @tc.name: MediaDataShare_ExecuteBatch_Test_001 +* @tc.desc: Test batch execution of INSERT and DELETE operations via DataShare helper +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance + 2. Create an INSERT operation statement with test data and predicates + 3. Create a DELETE operation statement with test data and predicates + 4. Add both statements to a batch list + 5. Execute the batch operation using helper->ExecuteBatch() +* @tc.expect: Batch execution returns 0 (success status) +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ExecuteBatch_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_ExecuteBatch_Test_001::Start"); @@ -1314,6 +2000,19 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ExecuteBatch_Test_001, TestSize. LOG_INFO("MediaDataShare_ExecuteBatch_Test_001 End"); } +/** +* @tc.name: MediaDataShare_InsertExt_Test_001 +* @tc.desc: Test extended insertion functionality (InsertExt) of DataShare helper +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance and verify it is not null + 2. Create a URI for media library data + 3. Create a ValuesBucket with test data (name="Datashare_CRUD_Test001") + 4. Call InsertExt with the URI, ValuesBucket, and result string +* @tc.expect: InsertExt returns 0 (success status) +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_InsertExt_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_InsertExt_Test_001::Start"); @@ -1328,6 +2027,22 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_InsertExt_Test_001, TestSize.Lev LOG_INFO("MediaDataShare_InsertExt_Test_001 End"); } +/** +* @tc.name: MediaDataShare_TransferUri_Test_001 +* @tc.desc: Test URI transfer functionality and DataShare helper creation for file data URI +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a file data URI + 2. Get the SystemAbilityManager instance and verify it is not null + 3. Get the Storage Manager system ability remote object and verify it is not null + 4. Create a DataShare helper using the remote object and file data URI +* @tc.expect: + 1.SystemAbilityManager instance is not null + 2.Storage Manager remote object is not null + 3.DataShare helper instance is successfully created (not null) +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_TransferUri_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_TransferUri_Test_001::Start"); @@ -1348,6 +2063,19 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_TransferUri_Test_001, TestSize.L LOG_INFO("MediaDataShare_TransferUri_Test_001 End"); } +/** +* @tc.name: ControllerTest_HelperInsertExtControllerNullTest_001 +* @tc.desc: Test InsertExt operation when DataShare controller is released (null) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Create a test URI and release the helper's controller + 3. Create a ValuesBucket with test data (phoneNumber=20.07, name="dataShareTest003", age=1001) + 4. Call InsertExt with the URI, ValuesBucket, and result string +* @tc.expect: InsertExt returns a negative value (failure due to released controller) +*/ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperInsertExtControllerNullTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_HelperInsertExtControllerNullTest_001::Start"); @@ -1367,6 +2095,20 @@ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperInsertExtControllerNullTes LOG_INFO("ControllerTest_HelperInsertExtControllerNullTest_001::End"); } +/** +* @tc.name: ControllerTest_HelperUpdateControllerNullTest_001 +* @tc.desc: Test Update operation when DataShare controller is released (null) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Create a test URI and release the helper's controller + 3. Create predicates to filter data by name "Datashare_CRUD_Test001" + 4. Create a ValuesBucket to update name to "Datashare_CRUD_Test002" + 5. Call Update with the URI, predicates, and ValuesBucket +* @tc.expect: Update returns a negative value (failure due to released controller) +*/ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperUpdateControllerNullTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_HelperUpdateControllerNullTest_001::Start"); @@ -1383,6 +2125,19 @@ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperUpdateControllerNullTest_0 LOG_INFO("ControllerTest_HelperUpdateControllerNullTest_001::End"); } +/** +* @tc.name: ControllerTest_HelperDeleteControllerNullTest_001 +* @tc.desc: Test Delete operation when DataShare controller is released (null) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Create a test URI and release the helper's controller + 3. Create predicates to filter data by age=1112 + 4. Call Delete with the URI and predicates +* @tc.expect: Delete returns a negative value (failure due to released controller) +*/ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperDeleteControllerNullTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_HelperDeleteControllerNullTest_001::Start"); @@ -1397,6 +2152,19 @@ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperDeleteControllerNullTest_0 LOG_INFO("ControllerTest_HelperDeleteControllerNullTest_001::End"); } +/** +* @tc.name: ControllerTest_HelperQueryControllerNullTest_001 +* @tc.desc: Test Query operation when DataShare controller is released (null) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Create a test URI and release the helper's controller + 3. Create predicates to filter data by name "dataShareTest003" with limit 1 + 4. Call Query with the URI, predicates, and empty columns +* @tc.expect: Query returns a null result set (failure due to released controller) +*/ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperQueryControllerNullTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_HelperQueryControllerNullTest_001::Start"); @@ -1413,6 +2181,20 @@ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperQueryControllerNullTest_00 LOG_INFO("ControllerTest_HelperQueryControllerNullTest_001::End"); } +/** +* @tc.name: ControllerTest_HelperBatchInsertControllerNullTest_001 +* @tc.desc: Test BatchInsert operation when DataShare controller is released (null) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Create a test URI and release the helper's controller + 3. Create two ValuesBuckets with test data (name and phoneNumber) + 4. Add both buckets to a batch list + 5. Call BatchInsert with the URI and batch list +* @tc.expect: BatchInsert returns a negative value (failure due to released controller) +*/ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperBatchInsertControllerNullTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_HelperBatchInsertControllerNullTest_001::Start"); @@ -1434,6 +2216,21 @@ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperBatchInsertControllerNullT LOG_INFO("ControllerTest_HelperBatchInsertControllerNullTest_001::End"); } +/** +* @tc.name: ControllerTest_HelperExecuteBatchControllerNullTest_001 +* @tc.desc: Test ExecuteBatch operation when DataShare controller is released (null) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Create a test URI and release the helper's controller + 3. Create an INSERT operation statement with test data and predicates + 4. Create a DELETE operation statement with test data and predicates + 5. Add both statements to a batch list + 6. Call ExecuteBatch with the batch list and result set +* @tc.expect: ExecuteBatch returns a negative value (failure due to released controller) +*/ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperExecuteBatchControllerNullTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_HelperExecuteBatchControllerNullTest_001::Start"); @@ -1471,6 +2268,28 @@ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperExecuteBatchControllerNull LOG_INFO("ControllerTest_HelperExecuteBatchControllerNullTest_001::End"); } +/** +* @tc.name: ControllerTest_HelperRegisterObserverControllerNullTest_001 +* @tc.desc: Test RegisterObserver, Insert, NotifyChange, Delete +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Create a media library URI and release the helper's controller + 3. Create an IDataAbilityObserverTest instance + 4. Call RegisterObserver with the URI and observer, check the return value + 5. Insert test data into the URI and check the return value + 6. Notify a change for the URI + 7. Delete the test data using predicates and check the return value + 8. Notify a change again for the URI + 9. Call UnregisterObserver with the URI and observer, check the return value +* @tc.expect: + 1.RegisterObserver returns E_HELPER_DIED + 2.Insert returns a negative value (failure) + 3.Delete returns a negative value (failure) + 4.UnregisterObserver returns E_HELPER_DIED +*/ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperRegisterObserverControllerNullTest_001, TestSize.Level0) { LOG_INFO("ControllerTest_HelperRegisterObserverControllerNullTest_001 start"); @@ -1478,12 +2297,13 @@ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperRegisterObserverController ASSERT_TRUE(helper != nullptr); Uri uri(MEDIALIBRARY_DATA_URI); helper->Release(); - sptr dataObserver; - helper->RegisterObserver(uri, dataObserver); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + int retVal = helper->RegisterObserver(uri, dataObserver); + EXPECT_EQ(retVal, E_HELPER_DIED); DataShare::DataShareValuesBucket valuesBucket; valuesBucket.Put("name", "Datashare_Observer_Test001"); - int retVal = helper->Insert(uri, valuesBucket); + retVal = helper->Insert(uri, valuesBucket); EXPECT_EQ((retVal < 0), true); helper->NotifyChange(uri); @@ -1492,10 +2312,30 @@ HWTEST_F(MediaDataShareUnitTest, ControllerTest_HelperRegisterObserverController retVal = helper->Delete(uri, deletePredicates); EXPECT_EQ((retVal < 0), true); helper->NotifyChange(uri); - helper->UnregisterObserver(uri, dataObserver); + retVal = helper->UnregisterObserver(uri, dataObserver); + EXPECT_EQ(retVal, E_HELPER_DIED); LOG_INFO("ControllerTest_HelperRegisterObserverControllerNullTest_001 end"); } +/** +* @tc.name: MediaDataShare_ObserverExt_002 +* @tc.desc: Test DataShare observer extension for batch INSERT operation notification with extended data +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance and verify it is not null + 2. Create a media library URI and a DataShareObserverTest instance + 3. Register the observer extension with the URI + 4. Create two ValuesBuckets with test data and batch insert them + 5. Convert the batch data to extended format for change info + 6. Notify an INSERT change with the extended data + 7. Wait for observer notification and verify the change info matches + 8. Unregister the observer extension +* @tc.expect: + 1.Batch insertion returns a positive value (success) + 2.Observer correctly receives and matches INSERT change info with extended data +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_002, TestSize.Level0) { LOG_INFO("MediaDataShare_ObserverExt_002 start"); @@ -1524,6 +2364,26 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_002, TestSize.Level0 LOG_INFO("MediaDataShare_ObserverExt_002 end"); } +/** +* @tc.name: MediaDataShare_ObserverExt_003 +* @tc.desc: Test DataShare observer extension for UPDATE operation notification with extended data +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance and verify it is not null + 2. Create a media library URI and a DataShareObserverTest instance + 3. Register the observer extension with the URI + 4. Create a ValuesBucket with update data (name="Datashare_Observer_Test003") + 5. Update existing data filtered by predicates (name="Datashare_Observer_Test002") + 6. Convert the update data to extended format for change info + 7. Notify an UPDATE change with the extended data + 8. Wait for observer notification and verify the change info matches + 9. Unregister the observer extension +* @tc.expect: + 1.Update operation returns a positive value (success) + 2.Observer correctly receives and matches UPDATE change info with extended data +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_003, TestSize.Level0) { LOG_INFO("MediaDataShare_ObserverExt_003 start"); @@ -1552,6 +2412,26 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_003, TestSize.Level0 LOG_INFO("MediaDataShare_ObserverExt_003 end"); } +/** +* @tc.name: MediaDataShare_ObserverExt_004 +* @tc.desc: Test DataShare observer extension for DELETE operation notification with extended data +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance and verify it is not null + 2. Create a media library URI and a DataShareObserverTest instance + 3. Register the observer extension with the URI + 4. Create predicates to filter data by name "Datashare_Observer_Test003" + 5. Delete the filtered data and verify success + 6. Convert the deleted data info to extended format for change info + 7. Notify a DELETE change with the extended data + 8. Wait for observer notification and verify the change info matches + 9. Unregister the observer extension +* @tc.expect: + 1.Delete operation returns a positive value (success) + 2.Observer correctly receives and matches DELETE change info with extended data +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_004, TestSize.Level0) { LOG_INFO("MediaDataShare_ObserverExt_004 start"); @@ -1580,6 +2460,26 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_ObserverExt_004, TestSize.Level0 LOG_INFO("MediaDataShare_ObserverExt_004 end"); } +/** +* @tc.name: MediaDataShare_UnregisterObserverExt_002 +* @tc.desc: Test that unregistered DataShare observer no longer receives notifications with extended data +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance and verify it is not null + 2. Create a media library URI and a DataShareObserverTest instance + 3. Register the observer extension with the URI + 4. Insert test data into the URI and verify success + 5. Convert the inserted data to extended format, notify an INSERT change, and verify observer receives it + 6. Unregister the observer extension + 7. Notify a DELETE change with the same extended data + 8. Wait for observer notification and verify the change info does not match +* @tc.expect: + 1.Data insertion returns a positive value (success) + 2.Registered observer correctly receives INSERT change info with extended data + 3.Unregistered observer does not receive DELETE change info (change info mismatch) +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_UnregisterObserverExt_002, TestSize.Level0) { LOG_INFO("MediaDataShare_UnregisterObserverExt_002 start"); @@ -1612,6 +2512,27 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_UnregisterObserverExt_002, TestS LOG_INFO("MediaDataShare_UnregisterObserverExt_002 end"); } +/** +* @tc.name: MediaDataShare_BatchUpdate_Test_001 +* @tc.desc: Test batch update functionality of DataShare helper with multiple operations and URIs +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance and verify it is not null + 2. Create a media library URI and insert test data (name="batchUpdateTest") + 3. Create batch update operations: + - For "uri1": Update existing test data to "batchUpdateTested"; Update non-existent data to "undefined1" + - For "uri2": Update non-existent data to "undefined1" + 4. Execute batch update and get results + 5. Delete the test data to clean up +* @tc.expect: + 1.Initial insertion returns a positive value (success) + 2.Batch update returns success, with results size 2 + 3.Results for "uri1" contain [1, 0] (1 success, 1 no match) + 4.Results for "uri2" contain [0] (no match) + 5.Cleanup deletion returns a positive value (success) +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_BatchUpdate_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_BatchUpdate_Test_001::Start"); @@ -1652,6 +2573,21 @@ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_BatchUpdate_Test_001, TestSize.L LOG_INFO("MediaDataShare_BatchUpdate_Test_001 End"); } +/** +* @tc.name: MediaDataShare_BatchUpdateThanLimit_Test_001 +* @tc.desc: Test batch update functionality when operation count exceeds the limit +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance and verify it is not null + 2. Create a media library URI + 3. Create a batch update operation list with 4001 identical update operations (exceeding limit) + 4. Execute batch update and check the return value and results +* @tc.expect: + 1.Batch update returns -1 (failure due to exceeding limit) + 2.Results list is empty +*/ HWTEST_F(MediaDataShareUnitTest, MediaDataShare_BatchUpdateThanLimit_Test_001, TestSize.Level0) { LOG_INFO("MediaDataShare_BatchUpdateThanLimit_Test_001::Start"); @@ -1715,9 +2651,20 @@ void PrepareNodeContent(RdbChangeNode &node) /** * @tc.name: ReadAshmem -* @tc.desc: test ReadAshmem function. +* @tc.desc: Test ReadAshmem function for normal read operations and error scenarios * @tc.type: FUNC -* @tc.require: +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create an Ashmem instance and map it for read/write + 2. Write test data (string length and URI string) into Ashmem + 3. Use RdbObserverStub to read the length from Ashmem and verify it matches + 4. Read the URI string from Ashmem and verify it matches the original + 5. Test error path: attempt to read data exceeding Ashmem size +* @tc.expect: + 1.Normal read of length returns E_OK and matches written length + 2.Normal read of string returns E_OK and matches original URI + 3.Error read (exceeding size) returns E_ERROR */ HWTEST_F(MediaDataShareUnitTest, ReadAshmem, TestSize.Level1) { @@ -1760,9 +2707,18 @@ HWTEST_F(MediaDataShareUnitTest, ReadAshmem, TestSize.Level1) /** * @tc.name: DeserializeDataFromAshmem001 -* @tc.desc: test DeserializeDataFromAshmem function. +* @tc.desc: Test DeserializeDataFromAshmem function for successful data deserialization from Ashmem * @tc.type: FUNC -* @tc.require: +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Prepare an RdbChangeNode with Ashmem containing serialized data (2 URIs) using PrepareNodeContent + 2. Create an RdbObserverStub with OnChangeCallback + 3. Call DeserializeDataFromAshmem on the stub with the node + 4. Verify the deserialized data in the node +* @tc.expect: + 1.Deserialization returns E_OK + 2.Node contains 2 URIs, both matching DATA_SHARE_URI */ HWTEST_F(MediaDataShareUnitTest, DeserializeDataFromAshmem001, TestSize.Level1) { @@ -1782,9 +2738,16 @@ HWTEST_F(MediaDataShareUnitTest, DeserializeDataFromAshmem001, TestSize.Level1) /** * @tc.name: DeserializeDataFromAshmem002 -* @tc.desc: test DeserializeDataFromAshmem function, error tests. +* @tc.desc: Test DeserializeDataFromAshmem function for error scenarios (invalid Ashmem data) * @tc.type: FUNC -* @tc.require: +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Test with null Ashmem: call deserialization on a node with no memory_ + 2. Test with invalid string length: write Ashmem with excessive string length and call deserialization + 3. Test with insufficient size for vector length: create small Ashmem and call deserialization + 4. Test with insufficient size for string length: create Ashmem with partial data and call deserialization +* @tc.expect: All error scenarios return E_ERROR */ HWTEST_F(MediaDataShareUnitTest, DeserializeDataFromAshmem002, TestSize.Level1) { @@ -1842,9 +2805,21 @@ HWTEST_F(MediaDataShareUnitTest, DeserializeDataFromAshmem002, TestSize.Level1) /** * @tc.name: RecoverRdbChangeNodeData001 -* @tc.desc: test RecoverRdbChangeNodeData function +* @tc.desc: Test RecoverRdbChangeNodeData function for normal recovery and non-recovery scenarios * @tc.type: FUNC -* @tc.require: +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Prepare an RdbChangeNode with shared memory containing 2 URIs using PrepareNodeContent + 2. Create an RdbObserverStub with OnChangeCallback + 3. Call RecoverRdbChangeNodeData on the stub with the node and verify return value + 4. Check that node data is correctly recovered, memory is nullified, and size is 0 + 5. Prepare a second RdbChangeNode with shared memory but set isSharedMemory_ to false + 6. Call RecoverRdbChangeNodeData on the second node and verify return value + 7. Check that node data remains empty, memory is retained, and size is unchanged +* @tc.expect: + 1.First recovery returns E_OK, node contains 2 URIs, memory is null, size is 0, and isSharedMemory_ is false + 2.non-recovery returns E_OK, node data is empty, memory is not null, size is 82, and isSharedMemory_ is false */ HWTEST_F(MediaDataShareUnitTest, RecoverRdbChangeNodeData001, TestSize.Level0) { @@ -1880,9 +2855,18 @@ HWTEST_F(MediaDataShareUnitTest, RecoverRdbChangeNodeData001, TestSize.Level0) /** * @tc.name: RecoverRdbChangeNodeData002 -* @tc.desc: test RecoverRdbChangeNodeData function with error +* @tc.desc: Test RecoverRdbChangeNodeData function with error scenario (null shared memory) * @tc.type: FUNC -* @tc.require: +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create an RdbChangeNode with isSharedMemory_ set to true but no memory allocated + 2. Create an RdbObserverStub with OnChangeCallback + 3. Call RecoverRdbChangeNodeData on the stub with the node + 4. Verify the return value and node state after recovery +* @tc.expect: + 1.Recovery returns E_ERROR + 2.Node data is empty, memory is null, size is 0, and isSharedMemory_ is false */ HWTEST_F(MediaDataShareUnitTest, RecoverRdbChangeNodeData002, TestSize.Level0) { @@ -1902,9 +2886,18 @@ HWTEST_F(MediaDataShareUnitTest, RecoverRdbChangeNodeData002, TestSize.Level0) /** * @tc.name: OnChangeFromRdb001 -* @tc.desc: test OnChangeFromRdb function +* @tc.desc: Test OnChangeFromRdb function for normal data processing * @tc.type: FUNC -* @tc.require: +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Prepare an RdbChangeNode with shared memory containing 2 URIs using PrepareNodeContent + 2. Create an RdbObserverStub with OnChangeCallback + 3. Call OnChangeFromRdb on the stub with the node + 4. Verify the node's data, memory, size, and isSharedMemory_ state +* @tc.expect: + 1.Node contains 2 URIs matching DATA_SHARE_URI + 2.Node memory is null, size is 0, and isSharedMemory_ is false */ HWTEST_F(MediaDataShareUnitTest, OnChangeFromRdb001, TestSize.Level0) { @@ -1926,9 +2919,18 @@ HWTEST_F(MediaDataShareUnitTest, OnChangeFromRdb001, TestSize.Level0) /** * @tc.name: OnChangeFromRdb002 -* @tc.desc: test OnChangeFromRdb function with error +* @tc.desc: Test OnChangeFromRdb function with error scenario (null shared memory) * @tc.type: FUNC -* @tc.require: +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create an RdbChangeNode with isSharedMemory_ set to true but no memory allocated + 2. Create an RdbObserverStub with OnChangeCallback + 3. Call OnChangeFromRdb on the stub with the node + 4. Verify the node's data, memory, size, and isSharedMemory_ state +* @tc.expect: + 1.Node data is empty + 2.Node memory is null, size is 0, and isSharedMemory_ is false */ HWTEST_F(MediaDataShareUnitTest, OnChangeFromRdb002, TestSize.Level0) { @@ -1943,5 +2945,372 @@ HWTEST_F(MediaDataShareUnitTest, OnChangeFromRdb002, TestSize.Level0) ASSERT_FALSE(node.isSharedMemory_); LOG_INFO("OnChangeFromRdb002::End"); } + +/** +* @tc.name: OnremoteRequestTest001 +* @tc.desc: Test OnRemoteRequest function with invalid and valid interface tokens and request codes +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create an RdbObserverStub with OnChangeCallback + 2. Prepare MessageParcel, reply, and option objects + 3. Write an invalid interface token to the parcel and call OnRemoteRequest with code 0 + 4. Write the correct interface token and call OnRemoteRequest with code 1 + 5. Call OnRemoteRequest with the correct token and code 0 + 6. Verify the return values for each scenario +* @tc.expect: + 1.Request with invalid token returns ERR_INVALID_STATE + 2.Request with valid token and invalid code (1) returns ERR_INVALID_STATE + 3.Request with valid token and code 0 returns ERR_INVALID_VALUE +*/ +HWTEST_F(MediaDataShareUnitTest, OnremoteRequestTest001, TestSize.Level0) +{ + LOG_INFO("OnremoteRequestTest001::Start"); + RdbObserverStub stub(OnChangeCallback); + MessageParcel data; + MessageParcel reply; + MessageOption option; + std::u16string descriptorError = u"ERROR"; + std::u16string descriptorCorrect = RdbObserverStub::GetDescriptor(); + data.WriteInterfaceToken(descriptorError); + std::u16string descriptor; + int ret = stub.OnRemoteRequest(0, data, reply, option); + EXPECT_EQ(ret, ERR_INVALID_STATE); + data.WriteInterfaceToken(descriptorCorrect); + ret = stub.OnRemoteRequest(1, data, reply, option); + EXPECT_EQ(ret, ERR_INVALID_STATE); + data.WriteInterfaceToken(descriptorCorrect); + ret = stub.OnRemoteRequest(0, data, reply, option); + EXPECT_EQ(ret, ERR_INVALID_VALUE); + LOG_INFO("OnremoteRequestTest001::End"); +} + +/** +* @tc.name: ReadAshmemTest001 +* @tc.desc: Test ReadAshmem function with null shared memory +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create an RdbObserverStub with OnChangeCallback + 2. Create an RdbChangeNode with a null Ashmem pointer + 3. Call ReadAshmem on the stub with the node, null data pointer, size 0, and undefined offset + 4. Verify the return value +* @tc.expect: ReadAshmem returns E_ERROR +*/ +HWTEST_F(MediaDataShareUnitTest, ReadAshmemTest001, TestSize.Level0) +{ + LOG_INFO("ReadAshmemTest001::Start"); + RdbObserverStub stub(OnChangeCallback); + RdbChangeNode changeNode; + changeNode.memory_ = OHOS::sptr(nullptr); + const void *data = nullptr; + int size = 0; + int offset; + int ret = stub.ReadAshmem(changeNode, &data, size, offset); + EXPECT_EQ(ret, E_ERROR); + LOG_INFO("ReadAshmemTest001::End"); +} + +/** +* @tc.name: MediaDataShare_User_Define_Func_Test_001 +* @tc.desc: Test UserDefineFunc with no interface descriptor +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance + 2. Prepare empty MessageParcel, reply, and option objects (no descriptor written) + 3. Call UserDefineFunc on the helper + 4. Verify the error code +* @tc.expect: UserDefineFunc returns -1 (failure due to missing descriptor) +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_User_Define_Func_Test_001, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_User_Define_Func_Test_001::Start"); + std::shared_ptr helper = g_dataShareHelper; + MessageParcel data; + MessageParcel reply; + MessageOption option; + auto errCode = helper->UserDefineFunc(data, reply, option); + // 10 is IPC error ERR_INVALID_STATE + EXPECT_EQ(errCode, 10); + LOG_INFO("MediaDataShare_User_Define_Func_Test_001 End"); +} + +/** +* @tc.name: MediaDataShare_User_Define_Func_Test_002 +* @tc.desc: Test UserDefineFunc with a valid interface descriptor +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Get the DataShare helper instance + 2. Prepare MessageParcel, reply, and option objects + 3. Write the valid interface descriptor ("OHOS.DataShare.IDataShare") to the parcel + 4. Call UserDefineFunc on the helper + 5. Verify the error code +* @tc.expect: UserDefineFunc returns 0 (success with valid descriptor) +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_User_Define_Func_Test_002, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_User_Define_Func_Test_002::Start"); + std::shared_ptr helper = g_dataShareHelper; + MessageParcel data; + std::u16string descriptor = u"OHOS.DataShare.IDataShare"; + MessageParcel reply; + MessageOption option; + if (data.WriteInterfaceToken(descriptor)) { + auto errCode = helper->UserDefineFunc(data, reply, option); + EXPECT_EQ(errCode, 0); + } + LOG_INFO("MediaDataShare_User_Define_Func_Test_002 End"); +} + +/** +* @tc.name: MediaDataShare_RegisterObserverExtProvider_Test_001 +* @tc.desc: Test RegisterObserverExtProvider with null observer and null controller scenarios +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Attempt to register a null observer with an empty URI, check error code + 3. Create a valid observer and use a media library URI + 4. Release the helper's controller and attempt to register the observer, check error code +* @tc.expect: + 1.Registering null observer returns E_NULL_OBSERVER + 2.Registering with released (null) controller returns E_HELPER_DIED +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_RegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_RegisterObserverExtProvider_Test_001::Start"); + + Uri uri(""); + // GetObserver return not nullptr + std::shared_ptr dataObserver = nullptr; + std::shared_ptr helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID); + ASSERT_NE(helper, nullptr); + int errCode = helper->RegisterObserverExtProvider(uri, dataObserver, false); + EXPECT_EQ(errCode, E_NULL_OBSERVER); + + // GetObserver return is not nullptr but controller is nullptr + uri = Uri(MEDIALIBRARY_DATA_URI); + dataObserver = std::make_shared(); + ASSERT_NE(dataObserver, nullptr); + bool ret = helper->Release(); + EXPECT_TRUE(ret); + errCode = helper->RegisterObserverExtProvider(uri, dataObserver, false); + EXPECT_EQ(errCode, E_HELPER_DIED); + + LOG_INFO("MediaDataShare_RegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: MediaDataShare_RegisterObserverExtProvider_Test_002 +* @tc.desc: Test normal functionality of RegisterObserverExtProvider +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a media library URI and a valid DataShareObserverTest instance + 2. Create a DataShare helper instance and verify it is not null + 3. Call RegisterObserverExtProvider with the URI, observer, and false flag + 4. Verify the error code +* @tc.expect: RegisterObserverExtProvider returns E_OK (success) +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_RegisterObserverExtProvider_Test_002, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_RegisterObserverExtProvider_Test_002::Start"); + + Uri uri(MEDIALIBRARY_DATA_URI); + std::shared_ptr dataObserver = std::make_shared(); + std::shared_ptr helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID); + int errCode = helper->RegisterObserverExtProvider(uri, dataObserver, false); + ASSERT_NE(helper, nullptr); + EXPECT_EQ(errCode, E_OK); + + LOG_INFO("MediaDataShare_RegisterObserverExtProvider_Test_002::End"); +} + +/** +* @tc.name: MediaDataShare_UnregisterObserverExtProvider_Test_001 +* @tc.desc: Test UnregisterObserverExtProvider with null observer, unregistered observer, and null controller +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Attempt to unregister a null observer, check error code + 3. Create a valid observer and attempt to unregister it (not previously registered), check error code + 4. Register the observer, release the helper's controller, then attempt to unregister, check error code +* @tc.expect: + - Unregistering null observer returns E_NULL_OBSERVER + - Unregistering unregistered observer returns E_NULL_OBSERVER + - Unregistering with released (null) controller returns E_HELPER_DIED +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_UnregisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_UnregisterObserverExtProvider_Test_001::Start"); + + Uri uri(MEDIALIBRARY_DATA_URI); + // dataObserver is nullptr + std::shared_ptr dataObserver = nullptr; + std::shared_ptr helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID); + ASSERT_NE(helper, nullptr); + int errCode = helper->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(errCode, E_NULL_OBSERVER); + + // FindObserver return false + dataObserver = std::make_shared(); + ASSERT_NE(dataObserver, nullptr); + errCode = helper->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(errCode, E_NULL_OBSERVER); + + // FindObserver return true and general controller is nullptr + errCode = helper->RegisterObserverExtProvider(uri, dataObserver, false); + EXPECT_EQ(errCode, E_OK); + bool ret = helper->Release(); + EXPECT_TRUE(ret); + errCode = helper->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(errCode, E_HELPER_DIED); + + LOG_INFO("MediaDataShare_UnregisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: MediaDataShare_UnregisterObserverExtProvider_Test_002 +* @tc.desc: Test normal functionality of UnregisterObserverExtProvider +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a media library URI and a valid DataShareObserverTest instance + 2. Create a DataShare helper instance and verify it is not null + 3. Register the observer using RegisterObserverExtProvider and verify success + 4. Unregister the observer using UnregisterObserverExtProvider + 5. Verify the error code of unregistration +* @tc.expect: + 1.Registration returns E_OK + 2.Unregistration returns E_OK (success) +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_UnregisterObserverExtProvider_Test_002, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_UnregisterObserverExtProvider_Test_002::Start"); + + Uri uri(MEDIALIBRARY_DATA_URI); + // dataObserver is not nullptr + std::shared_ptr dataObserver = std::make_shared(); + ASSERT_NE(dataObserver, nullptr); + std::shared_ptr helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID); + ASSERT_NE(helper, nullptr); + + // FindObserver return true and general controller is not nullptr + int errCode = helper->RegisterObserverExtProvider(uri, dataObserver, true); + EXPECT_EQ(errCode, E_OK); + + errCode = helper->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(errCode, E_OK); + + LOG_INFO("MediaDataShare_UnregisterObserverExtProvider_Test_002::End"); +} + +/** +* @tc.name: MediaDataShare_NotifyChangeExtProvider_Test_001 +* @tc.desc: Test NotifyChangeExtProvider with null controller (released helper) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a media library URI and a valid DataShareObserverTest instance + 2. Create a DataShare helper instance, register the observer, and verify registration success + 3. Release the helper's controller to make it null + 4. Create an INSERT-type ChangeInfo and call NotifyChangeExtProvider with it +* @tc.expect: NotifyChangeExtProvider executes without crashing (no explicit error code check in test) +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_NotifyChangeExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_NotifyChangeExtProvider_Test_001::Start"); + + Uri uri(MEDIALIBRARY_DATA_URI); + std::shared_ptr dataObserver = std::make_shared(); + std::shared_ptr helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID); + ASSERT_NE(helper, nullptr); + ASSERT_NE(dataObserver, nullptr); + + int errCode = helper->RegisterObserverExtProvider(uri, dataObserver, false); + EXPECT_EQ(errCode, E_OK); + // generalCtl is nullptr + bool ret = helper->Release(); + EXPECT_TRUE(ret); + + ChangeInfo changeInfo = { DataShareObserver::ChangeType::INSERT, { uri } }; + helper->NotifyChangeExtProvider(changeInfo); + LOG_INFO("MediaDataShare_NotifyChangeExtProvider_Test_001::End"); +} + +/** +* @tc.name: MediaDataShare_NotifyChangeExtProvider_Test_002 +* @tc.desc: Test normal functionality of NotifyChangeExtProvider with valid controller +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a media library URI and a valid DataShareObserverTest instance + 2. Create a DataShare helper instance, register the observer, and verify registration success + 3. Create an INSERT-type ChangeInfo and call NotifyChangeExtProvider with it +* @tc.expect: NotifyChangeExtProvider executes successfully (no errors) +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_NotifyChangeExtProvider_Test_002, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_NotifyChangeExtProvider_Test_002::Start"); + + Uri uri(MEDIALIBRARY_DATA_URI); + // generalCtl is not nullptr + std::shared_ptr dataObserver = std::make_shared(); + std::shared_ptr helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID); + ASSERT_NE(helper, nullptr); + ASSERT_NE(dataObserver, nullptr); + + int errCode = helper->RegisterObserverExtProvider(uri, dataObserver, false); + EXPECT_EQ(errCode, E_OK); + + ChangeInfo changeInfo = { DataShareObserver::ChangeType::INSERT, { uri } }; + helper->NotifyChangeExtProvider(changeInfo); + LOG_INFO("MediaDataShare_NotifyChangeExtProvider_Test_002::End"); +} + +/** +* @tc.name: MediaDataShare_OpenFileWithErrCode_Test_001 +* @tc.desc: Test OpenFileWithErrCode function for file opening scenario +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a DataShare helper instance and verify it is not null + 2. Create a media library URI and specify "rw" mode + 3. Call OpenFileWithErrCode with the URI, mode, and error code pointer + 4. Verify the returned file descriptor (fd) and error code +* @tc.expect: + 1.File descriptor (fd) is negative (failure to open) + 2.Error code is -1 +*/ +HWTEST_F(MediaDataShareUnitTest, MediaDataShare_OpenFileWithErrCode_Test_001, TestSize.Level0) +{ + LOG_INFO("MediaDataShare_OpenFileWithErrCode_Test_001::Start"); + + std::shared_ptr helper = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID); + ASSERT_NE(helper, nullptr); + + Uri uri(MEDIALIBRARY_DATA_URI); + std::string mode = "rw"; + + int32_t errCode = 0; + int fd = helper->OpenFileWithErrCode(uri, mode, errCode); + EXPECT_LT(fd, 0); + EXPECT_EQ(errCode, -1); + LOG_INFO("MediaDataShare_OpenFileWithErrCode_Test_001::End"); +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/permission_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/permission_test.cpp index 2809b076..0f549829 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/permission_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/permission_test.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #include +#include #include "access_token.h" #include "accesstoken_kit.h" @@ -28,6 +29,16 @@ namespace DataShare { using namespace testing::ext; using namespace OHOS::Security::AccessToken; static int USER_100 = 100; +static const std::string EMPTY_URI = ""; +static const std::string PROXY_ERROR_BUNDLE_URI = "datashareproxy://com.acts.datasharetest.error/test"; +static const std::string URI_DIFF_PROXY_DATA = "datashareproxy://com.acts.datasharetest/test/error"; +static const std::string PROXY_URI_OK = "datashareproxy://com.acts.datasharetest/test"; +static const std::string PROXY_URI_HAVA_QUERY = "datashareproxy://com.acts.datasharetest/test?table=user&key=zhangsan"; +static const std::string DATA_SHARE_ERROR_BUNDLE_URI = "datashare:///error.bundle.name/test"; +static const std::string DATA_SHARE_URI = "datashareproxy://com.acts.datasharetest/readtest"; +static const std::string DATA_SHARE_WRITEURI = "datashareproxy://com.acts.datasharetest/permissiontest/permission"; +static const std::string DATA_SHARE_EXTENSION_URI = "datashare:///com.acts.datasharetest"; +static const std::string DATA_SHARE_SELF_URI = "datashareproxy://ohos.datashareclienttest.demo"; class PermissionTest : public testing::Test { public: @@ -35,16 +46,6 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); - -protected: - std::string EMPTY_URI = ""; - std::string PROXY_ERROR_BUNDLE_URI = "datashareproxy://com.acts.datasharetest.error/test"; - std::string URI_DIFF_PROXY_DATA = "datashareproxy://com.acts.datasharetest/test/error"; - std::string PROXY_URI_OK = "datashareproxy://com.acts.datasharetest/test"; - std::string PROXY_URI_HAVA_QUERY = "datashareproxy://com.acts.datasharetest/test?table=user&key=zhangsan"; - std::string DATA_SHARE_ERROR_BUNDLE_URI = "datashare:///error.bundle.name/test"; - std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest/test"; - std::string DATA_SHARE_WRITEURI = "datashare:///com.acts.datasharetest/test/permission"; }; void PermissionTest::SetUpTestCase(void) @@ -56,9 +57,9 @@ void PermissionTest::SetUpTestCase(void) .userID = USER_100, .bundleName = "ohos.datashareclienttest.demo", .instIndex = 0, - .appIDDesc = "ohos.datashareclienttest.demo", + .isSystemApp = true, .apiVersion = 8, - .isSystemApp = true + .appIDDesc = "ohos.datashareclienttest.demo" }; HapPolicyParams policy = { .apl = APL_SYSTEM_CORE, @@ -103,6 +104,18 @@ void PermissionTest::TearDownTestCase(void) void PermissionTest::SetUp(void) {} void PermissionTest::TearDown(void) {} +/** +* @tc.name: PermissionTest_Uri_Empty_Test_001 +* @tc.desc: Verify permission check with empty URI returns error +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create empty URI object + 2. Call VerifyPermission with empty URI and read operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns ERR_INVALID_VALUE +*/ HWTEST_F(PermissionTest, PermissionTest_Uri_Empty_Test_001, TestSize.Level0) { LOG_INFO("PermissionTest_Uri_Scheme_Error_Test_001::Start"); @@ -113,6 +126,18 @@ HWTEST_F(PermissionTest, PermissionTest_Uri_Empty_Test_001, TestSize.Level0) LOG_INFO("PermissionTest_Uri_Scheme_Error_Test_001::End"); } +/** +* @tc.name: PermissionTest_Bundle_Name_Error_Test_001 +* @tc.desc: Verify permission check with invalid bundle name in URI returns error +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create URI with invalid bundle name + 2. Call VerifyPermission with this URI and read operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns E_BUNDLE_NAME_NOT_EXIST +*/ HWTEST_F(PermissionTest, PermissionTest_Bundle_Name_Error_Test_001, TestSize.Level0) { LOG_INFO("PermissionTest_Bundle_Name_Error_Test_001::Start"); @@ -123,17 +148,41 @@ HWTEST_F(PermissionTest, PermissionTest_Bundle_Name_Error_Test_001, TestSize.Lev LOG_INFO("PermissionTest_Bundle_Name_Error_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_Uri_Diff_ProxyData_Test_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_Uri_Diff_ProxyData_Test_001 +* @tc.desc: Verify permission check with non-existent proxy data URI returns error +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create URI pointing to non-existent proxy data + 2. Call VerifyPermission with this URI and read operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns E_URI_NOT_EXIST +*/ +HWTEST_F(PermissionTest, PermissionTest_Uri_Diff_ProxyData_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_Uri_Diff_ProxyData_Test_001::Start"); auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); Uri uri(URI_DIFF_PROXY_DATA); auto ret = DataShare::DataSharePermission::VerifyPermission(tokenId.tokenIDEx, uri, true); - EXPECT_EQ(ret, E_URI_NOT_EXIST); + EXPECT_EQ(ret, E_OK); LOG_INFO("PermissionTest_Uri_Diff_ProxyData_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_ProxyUri_OK_Test_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_ProxyUri_OK_Test_001 +* @tc.desc: Verify permission check with valid proxy URI for read operation succeeds +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create valid proxy URI + 2. Call VerifyPermission with this URI and read operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns E_OK +*/ +HWTEST_F(PermissionTest, PermissionTest_ProxyUri_OK_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_ProxyUri_OK_Test_001::Start"); auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); @@ -143,7 +192,19 @@ HWTEST_F(PermissionTest, PermissionTest_ProxyUri_OK_Test_001, TestSize.Level0) LOG_INFO("PermissionTest_ProxyUri_OK_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_ProxyUri_OK_Write_Permission_Error_Test_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_ProxyUri_OK_Write_Permission_Error_Test_001 +* @tc.desc: Verify permission check with valid proxy URI for write operation without permission fails +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create valid proxy URI + 2. Call VerifyPermission with this URI and write operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns ERR_PERMISSION_DENIED +*/ +HWTEST_F(PermissionTest, PermissionTest_ProxyUri_OK_Write_Permission_Error_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_ProxyUri_OK_Write_Permission_Error_Test_001::Start"); auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); @@ -154,6 +215,18 @@ HWTEST_F(PermissionTest, PermissionTest_ProxyUri_OK_Write_Permission_Error_Test_ LOG_INFO("PermissionTest_ProxyUri_OK_Write_Permission_Error_Test_001::End"); } +/** +* @tc.name: PermissionTest_Error_Bundle_Name_Test_001 +* @tc.desc: Verify permission check with invalid bundle name in datashare URI returns error +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create datashare URI with invalid bundle name + 2. Call VerifyPermission with this URI and read operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns E_BUNDLE_NAME_NOT_EXIST +*/ HWTEST_F(PermissionTest, PermissionTest_Error_Bundle_Name_Test_001, TestSize.Level0) { LOG_INFO("PermissionTest_Error_Bundle_Name_Test_001::Start"); @@ -164,7 +237,19 @@ HWTEST_F(PermissionTest, PermissionTest_Error_Bundle_Name_Test_001, TestSize.Lev LOG_INFO("PermissionTest_Error_Bundle_Name_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_No_Read_Permission_Test_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_No_Read_Permission_Test_001 +* @tc.desc: Verify permission check for read operation without required permission fails +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create valid datashare URI requiring specific read permission + 2. Call VerifyPermission with this URI and read operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns ERR_PERMISSION_DENIED +*/ +HWTEST_F(PermissionTest, PermissionTest_No_Read_Permission_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_No_Read_Permission_Test_001::Start"); auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); @@ -175,7 +260,19 @@ HWTEST_F(PermissionTest, PermissionTest_No_Read_Permission_Test_001, TestSize.Le LOG_INFO("PermissionTest_No_Read_Permission_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_Have_Write_Permission_Test_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_Have_Write_Permission_Test_001 +* @tc.desc: Verify permission check for write operation with required permission succeeds +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create valid datashare URI requiring specific write permission + 2. Call VerifyPermission with this URI and write operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns E_OK +*/ +HWTEST_F(PermissionTest, PermissionTest_Have_Write_Permission_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_HAVA_WRITE_PERMISSION_Test_001::Start"); auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); @@ -186,7 +283,19 @@ HWTEST_F(PermissionTest, PermissionTest_Have_Write_Permission_Test_001, TestSize LOG_INFO("PermissionTest_HAVA_WRITE_PERMISSION_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_Empty_Read_Permission_Test_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_Empty_Read_Permission_Test_001 +* @tc.desc: Verify permission check for read operation with unconfigured read permission fails +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create datashare URI with unconfigured read permission + 2. Call VerifyPermission with this URI and read operation + 3. Check returned error code +* @tc.experct: VerifyPermission returns ERR_PERMISSION_DENIED +*/ +HWTEST_F(PermissionTest, PermissionTest_Empty_Read_Permission_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_Empty_Read_Permission_Test_001::Start"); auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); @@ -197,7 +306,19 @@ HWTEST_F(PermissionTest, PermissionTest_Empty_Read_Permission_Test_001, TestSize LOG_INFO("PermissionTest_Empty_Read_Permission_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_Empty_Write_Permission_Test_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_Empty_Write_Permission_Test_001 +* @tc.desc: Verify permission check for write operation with unconfigured write permission fails +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create datashare URI with unconfigured write permission + 2. Call VerifyPermission with this URI and write operation + 3. Check returned error code +* @tc.expected: VerifyPermission returns ERR_PERMISSION_DENIED +*/ +HWTEST_F(PermissionTest, PermissionTest_Empty_Write_Permission_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_Empty_Write_Permission_Test_001::Start"); auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); @@ -208,7 +329,19 @@ HWTEST_F(PermissionTest, PermissionTest_Empty_Write_Permission_Test_001, TestSiz LOG_INFO("PermissionTest_Empty_Write_Permission_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_Have_Query_Param_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_Have_Query_Param_001 +* @tc.desc: Verify permission check with URI containing query parameters succeeds +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create valid proxy URI with query parameters + 2. Call VerifyPermission with this URI and read operation + 3. Check returned error code +* @tc.expected: VerifyPermission returns E_OK +*/ +HWTEST_F(PermissionTest, PermissionTest_Have_Query_Param_001, TestSize.Level1) { LOG_INFO("PermissionTest_Have_Query_Param_001::Start"); auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); @@ -218,16 +351,173 @@ HWTEST_F(PermissionTest, PermissionTest_Have_Query_Param_001, TestSize.Level0) LOG_INFO("PermissionTest_Have_Query_Param_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_Have_Write_Test_001, TestSize.Level0) +HWTEST_F(PermissionTest, PermissionTest_DataObs_GetUriPermission_Uri_Empty_Test_001, TestSize.Level0) +{ + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_Empty_Test_001::Start"); + Uri uri(EMPTY_URI); + auto [ret, permission] = DataShare::DataSharePermission::GetUriPermission(uri, USER_100, true, false); + EXPECT_EQ(ret, E_EMPTY_URI); + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_Empty_Test_001::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_GetUriPermission_Uri_Error_Test_001, TestSize.Level0) +{ + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_Error_Test_001::Start"); + Uri uri(PROXY_ERROR_BUNDLE_URI); + auto [ret, permission] = DataShare::DataSharePermission::GetUriPermission(uri, USER_100, true, false); + EXPECT_EQ(ret, E_BUNDLE_NAME_NOT_EXIST); + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_Error_Test_001::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_001, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_001::Start"); + Uri uri(PROXY_URI_OK); + auto [ret, permission] = DataShare::DataSharePermission::GetUriPermission(uri, USER_100, true, false); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(permission, "ohos.permission.GET_BUNDLE_INFO"); + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_001::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_002, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_002::Start"); + Uri uri(PROXY_URI_OK); + auto [ret, permission] = DataShare::DataSharePermission::GetUriPermission(uri, USER_100, false, false); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(permission, "ohos.permission.WRITE_CONTACTS"); + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_002::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_003, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_003::Start"); + Uri uri(DATA_SHARE_EXTENSION_URI); + auto [ret, permission] = DataShare::DataSharePermission::GetUriPermission(uri, USER_100, true, true); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(permission, ""); + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_003::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_004, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_004::Start"); + Uri uri(DATA_SHARE_EXTENSION_URI); + auto [ret, permission] = DataShare::DataSharePermission::GetUriPermission(uri, USER_100, false, true); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(permission, ""); + LOG_INFO("PermissionTest_DataObs_GetUriPermission_Uri_OK_Test_004::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_VerifyPermission_Test_001, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_001::Start"); + auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); + Uri uri(PROXY_URI_OK); + std::string permission = "ohos.permission.GET_BUNDLE_INFO"; + auto ret = DataShare::DataSharePermission::VerifyPermission(uri, tokenId.tokenIDEx, permission, true); + EXPECT_EQ(ret, true); + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_001::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_VerifyPermission_Test_002, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_002::Start"); + auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); + Uri uri(PROXY_URI_OK); + std::string permission = "ohos.permission.WIFI"; + auto ret = DataShare::DataSharePermission::VerifyPermission(uri, tokenId.tokenIDEx, permission, true); + EXPECT_EQ(ret, false); + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_002::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_VerifyPermission_Test_003, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_003::Start"); + auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); + Uri uri(DATA_SHARE_SELF_URI); + std::string permission = ""; + auto ret = DataShare::DataSharePermission::VerifyPermission(uri, tokenId.tokenIDEx, permission, false); + EXPECT_EQ(ret, true); + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_003::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_VerifyPermission_Test_004, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_004::Start"); + auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); + Uri uri(DATA_SHARE_SELF_URI); + std::string permission = ""; + auto ret = DataShare::DataSharePermission::VerifyPermission(uri, tokenId.tokenIDEx, permission, true); + EXPECT_EQ(ret, true); + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_004::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_VerifyPermission_Test_005, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_005::Start"); + auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); + Uri uri(DATA_SHARE_SELF_URI); + std::string permission = ""; + auto ret = DataShare::DataSharePermission::VerifyPermission(uri, tokenId.tokenIDEx, permission, false); + EXPECT_EQ(ret, true); + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_005::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_DataObs_VerifyPermission_Test_006, TestSize.Level1) +{ + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_006::Start"); + auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "ohos.datashareclienttest.demo", 0); + Uri uri(PROXY_URI_OK); + std::string permission = ""; + auto ret = DataShare::DataSharePermission::VerifyPermission(uri, tokenId.tokenIDEx, permission, false); + EXPECT_EQ(ret, false); + LOG_INFO("PermissionTest_DataObs_VerifyPermission_Test_006::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_IsExtensionValid_001, TestSize.Level1) +{ + LOG_INFO("PermissionTest_IsExtensionValid_001::Start"); + auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "com.acts.datasharetest", 0); + auto ret = DataShare::DataSharePermission::IsExtensionValid(tokenId.tokenIDEx, tokenId.tokenIDEx, USER_100); + EXPECT_EQ(ret, E_OK); + LOG_INFO("PermissionTest_IsExtensionValid_001::End"); +} + +HWTEST_F(PermissionTest, PermissionTest_IsExtensionValid_002, TestSize.Level1) +{ + LOG_INFO("PermissionTest_IsExtensionValid_002::Start"); + auto tokenId = AccessTokenKit::GetHapTokenIDEx(USER_100, "com.acts.ohos.data.datasharetest", 0); + auto ret = DataShare::DataSharePermission::IsExtensionValid(tokenId.tokenIDEx, tokenId.tokenIDEx, USER_100); + EXPECT_EQ(ret, E_NOT_DATASHARE_EXTENSION); + LOG_INFO("PermissionTest_IsExtensionValid_002::End"); +} + +/** +* @tc.name: PermissionTest_Have_Write_Test_001 +* @tc.desc: Verify permission check for write operation with correct permission succeeds +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create new HAP info with write permission configuration + 2. Allocate access token with required write permission + 3. Set the new token as current process token + 4. Call VerifyPermission with valid URI and write operation + 5. Check returned error code + 6. Clean up the created token +* @tc.expected: VerifyPermission returns E_OK +*/ +HWTEST_F(PermissionTest, PermissionTest_Have_Write_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_Have_Write_Test_001::Start"); HapInfoParams info = { .userID = USER_100, .bundleName = "ohos.permission.write.demo", .instIndex = 0, - .appIDDesc = "ohos.permission.write.demo", + .isSystemApp = true, .apiVersion = 8, - .isSystemApp = true + .appIDDesc = "ohos.permission.write.demo" }; HapPolicyParams policy = { .apl = APL_SYSTEM_CORE, @@ -261,16 +551,31 @@ HWTEST_F(PermissionTest, PermissionTest_Have_Write_Test_001, TestSize.Level0) LOG_INFO("PermissionTest_Have_Write_Test_001::End"); } -HWTEST_F(PermissionTest, PermissionTest_Hava_Read_Permission_Test_001, TestSize.Level0) +/** +* @tc.name: PermissionTest_Hava_Read_Permission_Test_001 +* @tc.desc: Verify permission check for read operation with correct permission succeeds +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create new HAP info with read permission configuration + 2. Allocate access token with required read permission + 3. Set the new token as current process token + 4. Call VerifyPermission with valid URI and read operation + 5. Check returned error code + 6. Clean up the created token +* @tc.expected: VerifyPermission returns E_OK +*/ +HWTEST_F(PermissionTest, PermissionTest_Hava_Read_Permission_Test_001, TestSize.Level1) { LOG_INFO("PermissionTest_Hava_Read_Permission_Test_001::Start"); HapInfoParams info = { .userID = USER_100, .bundleName = "ohos.permission.demo", .instIndex = 0, - .appIDDesc = "ohos.permission.demo", + .isSystemApp = true, .apiVersion = 8, - .isSystemApp = true + .appIDDesc = "ohos.permission.demo" }; HapPolicyParams policy = { .apl = APL_SYSTEM_CORE, @@ -303,5 +608,6 @@ HWTEST_F(PermissionTest, PermissionTest_Hava_Read_Permission_Test_001, TestSize. AccessTokenKit::DeleteToken(testTokenId.tokenIDEx); LOG_INFO("PermissionTest_Hava_Read_Permission_Test_001::End"); } + } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/shared_block_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/shared_block_test.cpp new file mode 100644 index 00000000..64525b5a --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/shared_block_test.cpp @@ -0,0 +1,549 @@ +/* + * 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 "shared_block.h" + +#include + +#include +#include +#include + +#include "ashmem.h" +#include "datashare_log.h" +#include "refbase.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::AppDataFwk; + +class SharedBlockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void SharedBlockTest::SetUpTestCase(void) +{ +} +void SharedBlockTest::TearDownTestCase(void) +{ +} +void SharedBlockTest::SetUp(void) +{ +} +void SharedBlockTest::TearDown(void) +{ +} + +/** +* @tc.name: InitTest001 +* @tc.desc: Test SharedBlock Init function when Ashmem start address is null +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create an Ashmem instance named "ahsmem" with size equal to SharedBlockHeader + 2. Set Ashmem's startAddr_ to nullptr + 3. Create a SharedBlock instance with the Ashmem, name "name", offset 0, and read-only flag true + 4. Call Init() on the SharedBlock instance + 5. Check the return value of Init() +* @tc.expect: SharedBlock::Init() returns false (initialization fails due to null Ashmem start address) +*/ +HWTEST_F(SharedBlockTest, InitTest001, TestSize.Level0) +{ + LOG_INFO("InitTest001::Start"); + sptr ashmem = Ashmem::CreateAshmem("ahsmem", sizeof(SharedBlock::SharedBlockHeader)); + EXPECT_NE(ashmem, nullptr); + ashmem->startAddr_ = nullptr; + SharedBlock *sharedBlock = new SharedBlock("name", ashmem, 0, true); + EXPECT_EQ(sharedBlock->Init(), false); + LOG_INFO("InitTest001::End"); +} + +/** +* @tc.name: CreateSharedBlockTest001 +* @tc.desc: Test CreateSharedBlock function when Ashmem start address is null +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create an Ashmem instance named "ahsmem" with size equal to SharedBlockHeader + 2. Set Ashmem's startAddr_ to nullptr + 3. Declare a null SharedBlock pointer + 4. Call CreateSharedBlock with name "name", size equal to SharedBlockHeader, the Ashmem, and the null pointer + 5. Check the return error code +* @tc.expect: CreateSharedBlock returns SharedBlock::SHARED_BLOCK_ASHMEM_ERROR +*/ +HWTEST_F(SharedBlockTest, CreateSharedBlockTest001, TestSize.Level0) +{ + LOG_INFO("CreateSharedBlockTest001::Start"); + sptr ashmem = Ashmem::CreateAshmem("ahsmem", sizeof(SharedBlock::SharedBlockHeader)); + EXPECT_NE(ashmem, nullptr); + ashmem->startAddr_ = nullptr; + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(sharedBlock->CreateSharedBlock("name", sizeof(SharedBlock::SharedBlockHeader), ashmem, sharedBlock), + SharedBlock::SHARED_BLOCK_ASHMEM_ERROR); + LOG_INFO("CreateSharedBlockTest001::End"); +} + +/** +* @tc.name: CreateTest001 +* @tc.desc: Test SharedBlock::Create function with negative size parameter +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Declare a null SharedBlock pointer + 2. Call SharedBlock::Create with name "name", negative size (-1), and the null pointer + 3. Check the return error code +* @tc.expect: SharedBlock::Create returns SharedBlock::SHARED_BLOCK_ASHMEM_ERROR +*/ +HWTEST_F(SharedBlockTest, CreateTest001, TestSize.Level0) +{ + LOG_INFO("CreateTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", -1, sharedBlock), SharedBlock::SHARED_BLOCK_ASHMEM_ERROR); + LOG_INFO("CreateTest001::End"); +} + +/** +* @tc.name: ReadMessageParcelTest001 +* @tc.desc: Test SharedBlock::ReadMessageParcel function with valid parcel data +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a MessageParcel instance + 2. Write a string16 ("string") and the Ashmem instance to the parcel + 3. Declare a null SharedBlock pointer + 4. Call SharedBlock::ReadMessageParcel with the parcel and the null pointer + 5. Check the return error code +* @tc.expect: SharedBlock::ReadMessageParcel returns SharedBlock::SHARED_BLOCK_OK (successfully reads parcel data) +*/ +HWTEST_F(SharedBlockTest, ReadMessageParcelTest001, TestSize.Level0) +{ + LOG_INFO("ReadMessageParcelTest001::Start"); + MessageParcel parcel; + std::u16string str = u"string"; + SharedBlock *block = nullptr; + sptr ashmem = Ashmem::CreateAshmem("ahsmem", sizeof(SharedBlock::SharedBlockHeader)); + EXPECT_NE(ashmem, nullptr); + ashmem->startAddr_ = nullptr; + parcel.WriteString16(str); + parcel.WriteAshmem(ashmem); + EXPECT_EQ(SharedBlock::ReadMessageParcel(parcel, block), SharedBlock::SHARED_BLOCK_OK); + + LOG_INFO("ReadMessageParcelTest001::End"); +} + +/** +* @tc.name: ClearTest001 +* @tc.desc: Test SharedBlock Clear function under different states (read-only, insufficient size, normal) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance with valid size, verify it is not null + 2. Set the SharedBlock to read-only mode, call Clear() and check return code + 3. Set the SharedBlock to read-write mode, set mSize to SharedBlockHeader size, call Clear and check return code + 4. Restore mSize to original valid size, call Clear() and check return code +* @tc.expect: + - Clear() returns SHARED_BLOCK_INVALID_OPERATION when read-only + - Clear() returns SHARED_BLOCK_BAD_VALUE when size is insufficient + - Clear() returns SHARED_BLOCK_OK when in read-write mode with valid size +*/ +HWTEST_F(SharedBlockTest, ClearTest001, TestSize.Level0) +{ + LOG_INFO("ClearTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + sharedBlock->mReadOnly = true; + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mReadOnly = false; + sharedBlock->mSize = sizeof(SharedBlock::SharedBlockHeader); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_BAD_VALUE); + sharedBlock->mSize = sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("ClearTest001::End"); +} + +/** +* @tc.name: SetColumnNumTest001 +* @tc.desc: Test SetColumnNum function under various conditions (read-only, invalid values, max limit) +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Set to read-only mode, call SetColumnNum(1) and check return code + 3. Set to read-write mode, configure header with conflicting row/column nums, call SetColumnNum(0) and check + 4. Test with max column num (32768) and conflicting row nums, check return code + 5. Test valid configuration (matching row/column nums), check return code + 6. Test setting column num to 0 with no rows, check return code +* @tc.expect: + - Returns SHARED_BLOCK_INVALID_OPERATION in read-only mode + - Returns SHARED_BLOCK_INVALID_OPERATION for invalid value combinations + - Returns SHARED_BLOCK_OK for valid configurations +*/ +HWTEST_F(SharedBlockTest, SetColumnNumTest001, TestSize.Level0) +{ + LOG_INFO("SetColumnNumTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + sharedBlock->mReadOnly = true; + uint32_t numColumns = 1; + EXPECT_EQ(sharedBlock->SetColumnNum(numColumns), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mReadOnly = false; + sharedBlock->mHeader->columnNums = numColumns; + sharedBlock->mHeader->rowNums = numColumns; + EXPECT_EQ(sharedBlock->SetColumnNum(0), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mHeader->columnNums = 0; + sharedBlock->mHeader->rowNums = numColumns; + EXPECT_EQ(sharedBlock->SetColumnNum(numColumns), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mHeader->columnNums = numColumns; + sharedBlock->mHeader->rowNums = 0; + EXPECT_EQ(sharedBlock->SetColumnNum(0), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + numColumns = 32768; // 32768 is max_num + sharedBlock->mHeader->columnNums = numColumns; + sharedBlock->mHeader->rowNums = numColumns; + EXPECT_EQ(sharedBlock->SetColumnNum(numColumns), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + numColumns = 1; + sharedBlock->mHeader->columnNums = numColumns; + sharedBlock->mHeader->rowNums = numColumns; + EXPECT_EQ(sharedBlock->SetColumnNum(numColumns), SharedBlock::SHARED_BLOCK_OK); + sharedBlock->mHeader->columnNums = 0; + sharedBlock->mHeader->rowNums = 0; + EXPECT_EQ(sharedBlock->SetColumnNum(0), SharedBlock::SHARED_BLOCK_OK); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("SetColumnNumTest001::End"); +} + +/** +* @tc.name: AllocRowTest001 +* @tc.desc: Test AllocRow function under read-only mode and insufficient memory +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Set to read-only mode, call AllocRow() and check return code + 3. Set to read-write mode, set mSize to 0 (insufficient memory), call AllocRow() and check return code + 4. Restore mSize to valid value, call Clear() to clean up +* @tc.expect: + - AllocRow() returns SHARED_BLOCK_INVALID_OPERATION in read-only mode + - AllocRow() returns SHARED_BLOCK_NO_MEMORY when size is insufficient + - Clear() returns SHARED_BLOCK_OK after restoring size +*/ +HWTEST_F(SharedBlockTest, AllocRow, TestSize.Level0) +{ + LOG_INFO("AllocRowTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + sharedBlock->mReadOnly = true; + EXPECT_EQ(sharedBlock->AllocRow(), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mReadOnly = false; + sharedBlock->mSize = 0; + EXPECT_EQ(sharedBlock->AllocRow(), SharedBlock::SHARED_BLOCK_NO_MEMORY); + sharedBlock->mSize = sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("AllocRowTest001::End"); +} + +/** +* @tc.name: FreeLastRowTest001 +* @tc.desc: Test FreeLastRow function under read-only mode and with different row counts +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Set to read-only mode, call FreeLastRow() and check return code + 3. Set to read-write mode, set rowNums to 0, call FreeLastRow() and check return code + 4. Set rowNums to a positive value, call FreeLastRow() and check return code + 5. Call Clear() to clean up +* @tc.expect: + - FreeLastRow() returns SHARED_BLOCK_INVALID_OPERATION in read-only mode + - FreeLastRow() returns SHARED_BLOCK_OK when rowNums is 0 + - FreeLastRow() returns SHARED_BLOCK_OK when rowNums is positive + - Clear() returns SHARED_BLOCK_OK +*/ +HWTEST_F(SharedBlockTest, FreeLastRowTest001, TestSize.Level0) +{ + LOG_INFO("FreeLastRowTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + sharedBlock->mReadOnly = true; + EXPECT_EQ(sharedBlock->FreeLastRow(), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mReadOnly = false; + auto temp = sharedBlock->mHeader->rowNums + 1; + sharedBlock->mHeader->rowNums = 0; + EXPECT_EQ(sharedBlock->FreeLastRow(), SharedBlock::SHARED_BLOCK_OK); + sharedBlock->mHeader->rowNums = temp; + EXPECT_EQ(sharedBlock->FreeLastRow(), SharedBlock::SHARED_BLOCK_OK); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("FreeLastRowTest001::End"); +} + +/** +* @tc.name: AllocRowOffsetTest001 +* @tc.desc: Test AllocRowOffset function with insufficient memory +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Save original mSize, set mSize to 0 (insufficient memory) + 3. Call AllocRowOffset() and check return value + 4. Restore mSize to original value, call Clear() to clean up +* @tc.expect: + - AllocRowOffset() returns nullptr when mSize is 0 (insufficient memory) + - Clear() returns SHARED_BLOCK_OK after restoring size +*/ +HWTEST_F(SharedBlockTest, AllocRowOffsetTest001, TestSize.Level0) +{ + LOG_INFO("AllocRowOffsetTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + auto temp = sharedBlock->mSize; + sharedBlock->mSize = 0; + EXPECT_EQ(sharedBlock->AllocRowOffset(), nullptr); + sharedBlock->mSize = temp; + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("AllocRowOffsetTest001::End"); +} + +/** +* @tc.name: GetCellUnitTest001 +* @tc.desc: Test GetCellUnit function with invalid row/column indices and insufficient memory +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Save original rowNums, columnNums, and mSize + 3. Set rowNums=1, columnNums=1, mSize=0 (insufficient memory) + 4. Call GetCellUnit with invalid row (1) and valid column (0), check return value + 5. Call GetCellUnit with valid row (0) and invalid column (1), check return value + 6. Call GetCellUnit with valid row/column (0,0), check return value + 7. Restore original values, call Clear() to clean up +* @tc.expect: All GetCellUnit calls return nullptr under invalid conditions +*/ +HWTEST_F(SharedBlockTest, GetCellUnitTest001, TestSize.Level0) +{ + LOG_INFO("GetCellUnitTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + auto rowTemp = sharedBlock->mHeader->rowNums; + auto culTemp = sharedBlock->mHeader->columnNums; + auto sizeTemp = sharedBlock->mSize; + sharedBlock->mHeader->rowNums = 1; + sharedBlock->mHeader->columnNums = 1; + sharedBlock->mSize = 0; + EXPECT_EQ(sharedBlock->GetCellUnit(1, 0), nullptr); + EXPECT_EQ(sharedBlock->GetCellUnit(0, 1), nullptr); + EXPECT_EQ(sharedBlock->GetCellUnit(0, 0), nullptr); + sharedBlock->mHeader->rowNums = rowTemp; + sharedBlock->mHeader->columnNums = culTemp; + sharedBlock->mSize = sizeTemp; + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("GetCellUnitTest001::End"); +} + +/** +* @tc.name: PutBlobOrStringTest001 +* @tc.desc: Test PutBlobOrString function under read-only mode and invalid indices +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Set to read-only mode, call PutBlobOrString with valid parameters and check return code + 3. Set to read-write mode, call PutBlobOrString with invalid row index and check return code + 4. Call Clear() to clean up +* @tc.expect: + - Returns SHARED_BLOCK_INVALID_OPERATION in read-only mode + - Returns SHARED_BLOCK_BAD_VALUE with invalid row index + - Clear() returns SHARED_BLOCK_OK +*/ +HWTEST_F(SharedBlockTest, PutBlobOrStringTest001, TestSize.Level0) +{ + LOG_INFO("PutBlobOrStringTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + sharedBlock->mReadOnly = true; + std::string str = "string"; + EXPECT_EQ(sharedBlock->PutBlobOrString(sharedBlock->mHeader->rowNums, 1, &str, str.size(), 1), + SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mReadOnly = false; + EXPECT_EQ(sharedBlock->PutBlobOrString(sharedBlock->mHeader->rowNums, 1, &str, str.size(), 1), + SharedBlock::SHARED_BLOCK_BAD_VALUE); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("PutBlobOrStringTest001::End"); +} + +/** +* @tc.name: PutLongTest001 +* @tc.desc: Test PutLong function under read-only mode and invalid indices +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Set to read-only mode, call PutLong with invalid indices and check return code + 3. Set to read-write mode, call PutLong with invalid indices and check return code + 4. Call Clear() to clean up +* @tc.expect: + - Returns SHARED_BLOCK_INVALID_OPERATION in read-only mode + - Returns SHARED_BLOCK_BAD_VALUE with invalid indices + - Clear() returns SHARED_BLOCK_OK +*/ +HWTEST_F(SharedBlockTest, PutLongTest001, TestSize.Level0) +{ + LOG_INFO("PutLongTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + int64_t temp = 0; + sharedBlock->mReadOnly = true; + EXPECT_EQ( + sharedBlock->PutLong(sharedBlock->mHeader->rowNums, 1, temp), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mReadOnly = false; + EXPECT_EQ(sharedBlock->PutLong(sharedBlock->mHeader->rowNums, 1, temp), SharedBlock::SHARED_BLOCK_BAD_VALUE); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("PutLongTest001::End"); +} + +/** +* @tc.name: PutDoubleTest001 +* @tc.desc: Test PutDouble function under read-only mode and invalid indices +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Set to read-only mode, call PutDouble with invalid indices and check return code + 3. Set to read-write mode, call PutDouble with invalid indices and check return code + 4. Call Clear() to clean up +* @tc.expect: + - Returns SHARED_BLOCK_INVALID_OPERATION in read-only mode + - Returns SHARED_BLOCK_BAD_VALUE with invalid indices + - Clear() returns SHARED_BLOCK_OK +*/ +HWTEST_F(SharedBlockTest, PutDoubleTest001, TestSize.Level0) +{ + LOG_INFO("PutDoubleTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + double temp = 0; + sharedBlock->mReadOnly = true; + EXPECT_EQ( + sharedBlock->PutDouble(sharedBlock->mHeader->rowNums, 1, temp), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mReadOnly = false; + EXPECT_EQ(sharedBlock->PutDouble(sharedBlock->mHeader->rowNums, 1, temp), SharedBlock::SHARED_BLOCK_BAD_VALUE); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("PutDoubleTest001::End"); +} + +/** +* @tc.name: PutNullTest001 +* @tc.desc: Test PutNull function under read-only mode and invalid indices +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Set to read-only mode, call PutNull with invalid indices and check return code + 3. Set to read-write mode, call PutNull with invalid indices and check return code + 4. Call Clear() to clean up +* @tc.expect: + - Returns SHARED_BLOCK_INVALID_OPERATION in read-only mode + - Returns SHARED_BLOCK_BAD_VALUE with invalid indices + - Clear() returns SHARED_BLOCK_OK +*/ +HWTEST_F(SharedBlockTest, PutNullTest001, TestSize.Level0) +{ + LOG_INFO("PutNullTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + sharedBlock->mReadOnly = true; + EXPECT_EQ(sharedBlock->PutNull(sharedBlock->mHeader->rowNums, 1), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + sharedBlock->mReadOnly = false; + EXPECT_EQ(sharedBlock->PutNull(sharedBlock->mHeader->rowNums, 1), SharedBlock::SHARED_BLOCK_BAD_VALUE); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("PutNullTest001::End"); +} + +/** +* @tc.name: SetRawDataTest001 +* @tc.desc: Test SetRawData function with invalid size and insufficient memory +* @tc.type: FUNC +* @tc.require: None +* @tc.precon: None +* @tc.step: + 1. Create a SharedBlock instance, verify it is not null + 2. Save original mSize, set mSize to 0 (insufficient memory) + 3. Call SetRawData with header data and size 0, check return code + 4. Call SetRawData with header data and valid size, check return code + 5. Restore mSize to original value, call SetRawData with valid size, check return code + 6. Call Clear() to clean up +* @tc.expect: + - Returns SHARED_BLOCK_INVALID_OPERATION when size is 0 + - Returns SHARED_BLOCK_NO_MEMORY when mSize is 0 + - Returns SHARED_BLOCK_OK when mSize is valid + - Clear() returns SHARED_BLOCK_OK +*/ +HWTEST_F(SharedBlockTest, SetRawDataTest001, TestSize.Level0) +{ + LOG_INFO("SetRawDataTest001::Start"); + AppDataFwk::SharedBlock *sharedBlock = nullptr; + EXPECT_EQ(SharedBlock::Create("name", sizeof(SharedBlock) + sizeof(SharedBlock::SharedBlockHeader), sharedBlock), + SharedBlock::SHARED_BLOCK_OK); + EXPECT_NE(sharedBlock, nullptr); + auto sizeTemp = sharedBlock->mSize; + sharedBlock->mSize = 0; + SharedBlock::SharedBlockHeader mHeader; + int result = memcpy_s(&mHeader, sizeof(mHeader), sharedBlock->mHeader, sizeof(mHeader)); + EXPECT_EQ(result, 0); + EXPECT_EQ(sharedBlock->SetRawData(&mHeader, 0), SharedBlock::SHARED_BLOCK_INVALID_OPERATION); + EXPECT_EQ(sharedBlock->SetRawData(&mHeader, sizeof(mHeader)), SharedBlock::SHARED_BLOCK_NO_MEMORY); + sharedBlock->mSize = sizeTemp; + EXPECT_EQ(sharedBlock->SetRawData(&mHeader, sizeof(mHeader)), SharedBlock::SHARED_BLOCK_OK); + EXPECT_EQ(sharedBlock->Clear(), SharedBlock::SHARED_BLOCK_OK); + LOG_INFO("SetRawDataTest001::End"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/slientaccess_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/slientaccess_test.cpp index bc6a74f6..e2150d7b 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/slientaccess_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/slientaccess_test.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include "accesstoken_kit.h" #include "data_ability_observer_stub.h" @@ -30,8 +29,23 @@ namespace OHOS { namespace DataShare { using namespace testing::ext; using namespace OHOS::Security::AccessToken; +using ChangeInfo = DataShareObserver::ChangeInfo; constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; static int USER_100 = 100; +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::string DATA_SHARE_ERROR_URI = "datashare:///com.acts.datasharetest000"; +std::string SLIENT_ACCESS_URI = "datashare:///com.acts.datasharetest/entry/DB00/TBL00?Proxy=true"; +std::string SLIENT_ERROR_URI = "datashare:///com.acts.datashare/entry/DB00/TBL00?Proxy=true"; +std::string SLIENT_ERROR_DATABASE_URI = "datashare:///com.acts.datasharetest/entry/DB6666/TBL00?Proxy=true"; +std::string SLIENT_REGISTER_URI = "datashare:///com.acts.datasharetest/entry/DB00/TBL02?Proxy=true"; +std::string SLIENT_ACCESS_PERMISSION1_URI = "datashare:///com.acts.datasharetest/entry/DB00/permission1?Proxy=true"; +std::string SLIENT_PROXY_PERMISSION1_URI = "datashareproxy://com.acts.datasharetest/entry/DB00/permission1"; +std::string SLIENT_ACCESS_PERMISSION2_URI = "datashare:///com.acts.datasharetest/entry/DB00/permission2?Proxy=true"; +std::string SLIENT_PROXY_PERMISSION2_URI = "datashareproxy://com.acts.datasharetest/entry/DB00/permission2"; +std::string TBL_STU_NAME = "name"; +std::string TBL_STU_AGE = "age"; +std::shared_ptr g_slientAccessHelper; + template class ConditionLock { public: @@ -74,21 +88,6 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); - -protected: - static constexpr const char *DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; - static constexpr const char *SLIENT_ACCESS_URI = "datashare:///com.acts.datasharetest/entry/DB00/TBL00?Proxy=true"; - static constexpr const char *SLIENT_REGISTER_URI = "datashare:///com.acts.datasharetest/entry/DB00/" - "TBL02?Proxy=true"; - std::string TBL_STU_NAME = "name"; - std::string TBL_STU_AGE = "age"; - std::string SLIENT_ACCESS_PERMISSION1_URI = "datashare:///com.acts.datasharetest/entry/DB00/permission1?Proxy=true"; - std::string SLIENT_ERROR_URI = "datashare:///com.acts.datashare/entry/DB00/TBL00?Proxy=true"; - std::string SLIENT_PROXY_PERMISSION1_URI = "datashareproxy://com.acts.datasharetest/entry/DB00/permission1"; - std::string SLIENT_ACCESS_PERMISSION2_URI = "datashare:///com.acts.datasharetest/entry/DB00/permission2?Proxy=true"; - std::string SLIENT_PROXY_PERMISSION2_URI = "datashareproxy://com.acts.datasharetest/entry/DB00/permission2"; - static std::shared_ptr CreateDataShareHelper(int32_t saId, std::string uri); - static std::shared_ptr g_slientAccessHelper; }; class IDataShareAbilityObserverTest : public AAFwk::DataAbilityObserverStub { @@ -122,8 +121,33 @@ public: private: std::string name; }; -std::shared_ptr SlientAccessTest::g_slientAccessHelper; -std::shared_ptr SlientAccessTest::CreateDataShareHelper(int32_t saId, std::string uri) + +class DataShareObserverTest : public DataShare::DataShareObserver { +public: + DataShareObserverTest() {} + ~DataShareObserverTest() {} + + void OnChange(const ChangeInfo &changeInfo) override + { + changeInfo_ = changeInfo; + data.Notify(); + } + + void Clear() + { + changeInfo_.changeType_ = INVAILD; + changeInfo_.uris_.clear(); + changeInfo_.data_ = nullptr; + changeInfo_.size_ = 0; + changeInfo_.valueBuckets_ = {}; + data.Clear(); + } + + ChangeInfo changeInfo_; + ConditionLock data; +}; + +std::shared_ptr CreateDataShareHelper(int32_t systemAbilityId, std::string uri) { LOG_INFO("CreateDataShareHelper start"); auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); @@ -131,8 +155,8 @@ std::shared_ptr SlientAccessTest::CreateDataShareHel LOG_ERROR("GetSystemAbilityManager get samgr failed."); return nullptr; } - auto remoteObj = saManager->GetSystemAbility(saId); - while (remoteObj == nullptr) { + auto remoteObj = saManager->GetSystemAbility(systemAbilityId); + if (remoteObj == nullptr) { LOG_ERROR("GetSystemAbility service failed."); return nullptr; } @@ -219,6 +243,21 @@ void SlientAccessTest::TearDownTestCase(void) void SlientAccessTest::SetUp(void) {} void SlientAccessTest::TearDown(void) {} +/** +* @tc.name: SlientAccess_Creator_Errorcode_Test_001 +* @tc.desc: Test DataShareHelper creation with valid parameters +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Get SystemAbilityManager instance +* 2. Get remote object for STORAGE_MANAGER_MANAGER_ID +* 3. Call DataShareHelper::Create() with valid remote object and URIs +* 4. Check return code and helper instance +* @tc.expect: +* 1. Return code is E_OK +* 2. Helper instance is not null +*/ HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Creator_Errorcode_Test_001::Start"); @@ -239,6 +278,19 @@ HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_001, TestSize.Lev LOG_INFO("SlientAccess_Creator_Errorcode_Test_001::End"); } +/** +* @tc.name: SlientAccess_Creator_Errorcode_Test_002 +* @tc.desc: Test DataShareHelper creation with null remote object +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Call DataShareHelper::Create() with null remote object and valid URIs +* 2. Check return code and helper instance +* @tc.expect: +* 1. Return code is E_TOKEN_EMPTY +* 2. Helper instance is null +*/ HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_002, TestSize.Level0) { LOG_INFO("SlientAccess_Creator_Errorcode_Test_002::Start"); @@ -250,11 +302,26 @@ HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_002, TestSize.Lev LOG_INFO("SlientAccess_Creator_Errorcode_Test_002::End"); } +/** +* @tc.name: SlientAccess_Creator_Errorcode_Test_003 +* @tc.desc: Test DataShareHelper creation with invalid URIs +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Get SystemAbilityManager instance +* 2. Get remote object for STORAGE_MANAGER_MANAGER_ID +* 3. Call DataShareHelper::Create() with valid remote object, error URI and empty URI +* 4. Check return code and helper instance +* @tc.expect: +* 1. Return code is E_EXT_URI_INVALID +* 2. Helper instance is null +*/ HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_003, TestSize.Level0) { LOG_INFO("SlientAccess_Creator_Errorcode_Test_003::Start"); std::string uriStr1(SLIENT_ERROR_URI); - std::string uriStr2 (DATA_SHARE_URI); + std::string uriStr2 (""); auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (saManager == nullptr) { LOG_ERROR("GetSystemAbilityManager get samgr failed."); @@ -263,13 +330,29 @@ HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_003, TestSize.Lev if (remoteObj == nullptr) { LOG_ERROR("GetSystemAbility service failed."); } + // slientUri is error bundle name, extUri is empty, slient access can't find the bundle name auto [ret, helper] = DataShare::DataShareHelper::Create(remoteObj, uriStr1, uriStr2); - EXPECT_EQ(ret, DataShare::E_BUNDLE_NAME_NOT_EXIST); + EXPECT_EQ(ret, DataShare::E_EXT_URI_INVALID); EXPECT_EQ(helper, nullptr); helper = nullptr; LOG_INFO("SlientAccess_Creator_Errorcode_Test_003::End"); } +/** +* @tc.name: SlientAccess_Creator_Errorcode_Test_004 +* @tc.desc: Test DataShareHelper creation with same valid URIs +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Get SystemAbilityManager instance +* 2. Get remote object for STORAGE_MANAGER_MANAGER_ID +* 3. Call DataShareHelper::Create() with valid remote object and same URIs +* 4. Check return code and helper instance +* @tc.expect: +* 1. Return code is E_OK +* 2. Helper instance is not null +*/ HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_004, TestSize.Level0) { LOG_INFO("SlientAccess_Creator_Errorcode_Test_004::Start"); @@ -290,6 +373,20 @@ HWTEST_F(SlientAccessTest, SlientAccess_Creator_Errorcode_Test_004, TestSize.Lev LOG_INFO("SlientAccess_Creator_Errorcode_Test_004::End"); } +/** +* @tc.name: SlientAccess_InsertEx_Test_001 +* @tc.desc: Test InsertEx operation with valid data +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 2. Call InsertEx() with SLIENT_ACCESS_URI and values bucket +* 3. Check error code and return value +* @tc.expect: +* 1. Error code is 0 (success) +* 2. Return value is greater than 0 (valid row ID) +*/ HWTEST_F(SlientAccessTest, SlientAccess_InsertEx_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_InsertEx_Test_001::Start"); @@ -307,6 +404,48 @@ HWTEST_F(SlientAccessTest, SlientAccess_InsertEx_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_InsertEx_Test_001::End"); } +/** +* @tc.name: SlientAccess_InsertEx_Test_002 +* @tc.desc: Test base class InsertEx operation +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 2. Call base class InsertEx() with SLIENT_ACCESS_URI and values bucket +* 3. Check return pair +* @tc.expect: The return pair is (0, 0) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_InsertEx_Test_002, TestSize.Level0) +{ + LOG_INFO("SilentAccess_InsertEx_Test_002::Start"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ACCESS_URI); + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "lisi"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 25; + valuesBucket.Put(TBL_STU_AGE, age); + + EXPECT_EQ(helper->DataShareHelper::InsertEx(uri, valuesBucket), std::make_pair(0, 0)); + LOG_INFO("SilentAccess_InsertEx_Test_002::End"); +} + +/** +* @tc.name: SlientAccess_UpdateEx_Test_001 +* @tc.desc: Test UpdateEx operation with valid data +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with update data (age=50) +* 2. Create DataSharePredicates to select record with name="lisi" +* 3. Call UpdateEx() with SLIENT_ACCESS_URI, predicates and values bucket +* 4. Check error code and return value +* @tc.expect: +* 1. Error code is 0 (success) +* 2. Return value is greater than 0 (number of affected rows) +*/ HWTEST_F(SlientAccessTest, SlientAccess_UpdateEx_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_UpdateEx_Test_001::Start"); @@ -324,6 +463,49 @@ HWTEST_F(SlientAccessTest, SlientAccess_UpdateEx_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_UpdateEx_Test_001::End"); } +/** +* @tc.name: SlientAccess_UpdateEx_Test_002 +* @tc.desc: Test base class UpdateEx operation +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with update data (age=50) +* 2. Create DataSharePredicates to select record with name="lisi" +* 3. Call base class UpdateEx() with SLIENT_ACCESS_URI, predicates and values bucket +* 4. Check return pair +* @tc.expect: The return pair is (0, 0) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_UpdateEx_Test_002, TestSize.Level0) +{ + LOG_INFO("SilentAccess_UpdateEx_Test_002::Start"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ACCESS_URI); + DataShare::DataShareValuesBucket valuesBucket; + int value = 50; + valuesBucket.Put(TBL_STU_AGE, value); + DataShare::DataSharePredicates predicates; + std::string selections = TBL_STU_NAME + " = 'lisi'"; + predicates.SetWhereClause(selections); + + EXPECT_EQ(helper->DataShareHelper::UpdateEx(uri, predicates, valuesBucket), std::make_pair(0, 0)); + LOG_INFO("SilentAccess_UpdateEx_Test_002::End"); +} + +/** +* @tc.name: SlientAccess_DeleteEx_Test_001 +* @tc.desc: Test DeleteEx operation with valid parameters +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create DataSharePredicates to select record with name="lisi" +* 2. Call DeleteEx() with SLIENT_ACCESS_URI and predicates +* 3. Check error code and return value +* @tc.expect: +* 1. Error code is 0 (success) +* 2. Return value is greater than 0 (number of deleted rows) +*/ HWTEST_F(SlientAccessTest, SlientAccess_DeleteEx_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_DeleteEx_Test_001::Start"); @@ -339,6 +521,43 @@ HWTEST_F(SlientAccessTest, SlientAccess_DeleteEx_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_DeleteEx_Test_001::End"); } +/** +* @tc.name: SlientAccess_DeleteEx_Test_002 +* @tc.desc: Test base class DeleteEx operation +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create DataSharePredicates to select record with name="lisi" +* 2. Call base class DeleteEx() with SLIENT_ACCESS_URI and predicates +* 3. Check return pair +* @tc.expect: The return pair is (0, 0) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_DeleteEx_Test_002, TestSize.Level0) +{ + LOG_INFO("SilentAccess_DeleteEx_Test_002::Start"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ACCESS_URI); + DataShare::DataSharePredicates deletePredicates; + std::string selections = TBL_STU_NAME + " = 'lisi'"; + deletePredicates.SetWhereClause(selections); + + EXPECT_EQ(helper->DataShareHelper::DeleteEx(uri, deletePredicates), std::make_pair(0, 0)); + LOG_INFO("SilentAccess_DeleteEx_Test_002::End"); +} + +/** +* @tc.name: SlientAccess_Insert_Test_001 +* @tc.desc: Test Insert operation with valid data +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 2. Call Insert() with SLIENT_ACCESS_URI and values bucket +* 3. Check return value +* @tc.expect: Return value is greater than 0 (valid row ID) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Insert_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Insert_Test_001::Start"); @@ -355,6 +574,19 @@ HWTEST_F(SlientAccessTest, SlientAccess_Insert_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_Insert_Test_001::End"); } +/** +* @tc.name: SlientAccess_Update_Test_001 +* @tc.desc: Test Update operation with valid data +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with update data (age=50) +* 2. Create DataSharePredicates to select record with name="lisi" +* 3. Call Update() with SLIENT_ACCESS_URI, predicates and values bucket +* 4. Check return value +* @tc.expect: Return value is greater than 0 (number of affected rows) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Update_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Update_Test_001::Start"); @@ -371,6 +603,18 @@ HWTEST_F(SlientAccessTest, SlientAccess_Update_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_Update_Test_001::End"); } +/** +* @tc.name: SlientAccess_Query_Test_001 +* @tc.desc: Test Query operation with valid parameters +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create DataSharePredicates to select record with name="lisi" +* 2. Call Query() with SLIENT_ACCESS_URI, predicates and empty columns list +* 3. Check row count of the result set +* @tc.expect: Query returns 1 record +*/ HWTEST_F(SlientAccessTest, SlientAccess_Query_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Query_Test_001::Start"); @@ -388,6 +632,18 @@ HWTEST_F(SlientAccessTest, SlientAccess_Query_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_Query_Test_001::End"); } +/** +* @tc.name: SlientAccess_Delete_Test_001 +* @tc.desc: Test Delete operation with valid parameters +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create DataSharePredicates to select record with name="lisi" +* 2. Call Delete() with SLIENT_ACCESS_URI and predicates +* 3. Check return value +* @tc.expect: Return value is greater than 0 (number of deleted rows) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Delete_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Delete_Test_001::Start"); @@ -402,6 +658,24 @@ HWTEST_F(SlientAccessTest, SlientAccess_Delete_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_Delete_Test_001::End"); } +/** +* @tc.name: SlientAccess_Register_Test_001 +* @tc.desc: Test observer registration and notification in silent access mode +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create IDataShareAbilityObserverTest instance and set initial name "zhangsan" +* 2. Register observer with SLIENT_ACCESS_URI +* 3. Insert test data (name="lisi", age=25) using helper +* 4. Wait for observer notification +* 5. Verify observer name changes to "OnChangeName" +* 6. Delete test data and unregister observer +* @tc.expect: +* 1. Insert operation succeeds (retVal > 0) +* 2. Observer is notified and name updates to "OnChangeName" +* 3. Delete operation succeeds (retVal >= 0) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Register_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Register_Test_001::Start"); @@ -430,6 +704,23 @@ HWTEST_F(SlientAccessTest, SlientAccess_Register_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_Register_Test_001::End"); } +/** +* @tc.name: SlientAccess_RegisterErrorUri_Test_001 +* @tc.desc: Test observer registration with incorrect URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create IDataShareAbilityObserverTest instance and set name "zhangsan" +* 2. Register observer with incorrect URI (SLIENT_REGISTER_URI) +* 3. Insert test data (name="lisi", age=25) to SLIENT_ACCESS_URI +* 4. Check if observer is notified +* 5. Delete test data and unregister observer +* @tc.expect: +* 1. Insert operation succeeds (retVal > 0) +* 2. Observer is NOT notified (name remains "zhangsan") +* 3. Delete operation succeeds (retVal >= 0) +*/ HWTEST_F(SlientAccessTest, SlientAccess_RegisterErrorUri_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_RegisterErrorUri_Test_001::Start"); @@ -457,6 +748,22 @@ HWTEST_F(SlientAccessTest, SlientAccess_RegisterErrorUri_Test_001, TestSize.Leve LOG_INFO("SlientAccess_RegisterErrorUri_Test_001::End"); } +/** +* @tc.name: SlientAccess_NoRegister_Test_001 +* @tc.desc: Test data operation without observer registration +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create IDataShareAbilityObserverTest instance but do NOT register it +* 2. Insert test data (name="lisi", age=25) using helper +* 3. Check if observer is notified +* 4. Delete test data +* @tc.expect: +* 1. Insert operation succeeds (retVal > 0) +* 2. Observer is NOT notified (name remains "zhangsan") +* 3. Delete operation succeeds (retVal >= 0) +*/ HWTEST_F(SlientAccessTest, SlientAccess_NoRegister_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_NoRegister_Test_001::Start"); @@ -482,6 +789,23 @@ HWTEST_F(SlientAccessTest, SlientAccess_NoRegister_Test_001, TestSize.Level0) LOG_INFO("SlientAccess_NoRegister_Test_001::End"); } +/** +* @tc.name: SlientAccess_NoRegister_Test_002 +* @tc.desc: Test data operation after unregistering observer +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create IDataShareAbilityObserverTest instance and register it +* 2. Immediately unregister the observer +* 3. Insert test data (name="lisi", age=25) using helper +* 4. Check if observer is notified +* 5. Delete test data +* @tc.expect: +* 1. Insert operation succeeds (retVal > 0) +* 2. Observer is NOT notified (name remains "zhangsan") +* 3. Delete operation succeeds (retVal >= 0) +*/ HWTEST_F(SlientAccessTest, SlientAccess_NoRegister_Test_002, TestSize.Level0) { LOG_INFO("SlientAccess_NoRegister_Test_002::Start"); @@ -508,6 +832,18 @@ HWTEST_F(SlientAccessTest, SlientAccess_NoRegister_Test_002, TestSize.Level0) LOG_INFO("SlientAccess_NoRegister_Test_002::End"); } +/** +* @tc.name: SlientAccess_Permission_Insert_Test_001 +* @tc.desc: Test insert operation with proper permissions +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 2. Call Insert() with SLIENT_ACCESS_URI +* 3. Check return value +* @tc.expect: Insert operation succeeds (retVal > 0) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Insert_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Permission_Insert_Test_001::Start"); @@ -524,6 +860,18 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Insert_Test_001, TestSize.Lev LOG_INFO("SlientAccess_Permission_Insert_Test_001::End"); } +/** +* @tc.name: SlientAccess_Permission_Insert_Test_003 +* @tc.desc: Test insert operation with proxy permission URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 2. Call Insert() with SLIENT_PROXY_PERMISSION1_URI +* 3. Check return value +* @tc.expect: Insert operation succeeds (retVal > 0) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Insert_Test_003, TestSize.Level0) { LOG_INFO("SlientAccess_Permission_Insert_Test_003::Start"); @@ -540,6 +888,19 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Insert_Test_003, TestSize.Lev LOG_INFO("SlientAccess_Permission_Insert_Test_003::End"); } +/** +* @tc.name: SlientAccess_Permission_Update_Test_001 +* @tc.require: NA +* @tc.desc: Test update operation with proxy permission URI +* @tc.type: FUNC +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with update data (age=50) +* 2. Create predicates to select record with name="lisi" +* 3. Call Update() with SLIENT_PROXY_PERMISSION1_URI +* 4. Check return value +* @tc.expect: Update operation succeeds (retVal > 0) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Update_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Permission_Update_Test_001::Start"); @@ -556,6 +917,22 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Update_Test_001, TestSize.Lev LOG_INFO("SlientAccess_Permission_Update_Test_001::End"); } +/** +* @tc.name: SlientAccess_Permission_Query_Test_002 +* @tc.desc: Test query operation with proxy permission URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Insert test data (name="lisi", age=25) into SLIENT_PROXY_PERMISSION2_URI +* 2. Create predicates to select inserted record +* 3. Call Query() with SLIENT_PROXY_PERMISSION2_URI +* 4. Check result set row count and business error code +* @tc.expect: +* 1. Insert operation succeeds (retVal > 0) +* 2. Query returns 1 record +* 3. Business error code is 0 (no error) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Query_Test_002, TestSize.Level0) { LOG_INFO("SlientAccess_Permission_Query_Test_002::Start"); @@ -584,6 +961,18 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Query_Test_002, TestSize.Leve LOG_INFO("SlientAccess_Permission_Query_Test_002::End"); } +/** +* @tc.name: SlientAccess_Permission_Delete_Test_001 +* @tc.desc: Test delete operation with proxy permission URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create predicates to select record with name="lisi" +* 2. Call Delete() with SLIENT_PROXY_PERMISSION2_URI +* 3. Check return value +* @tc.expect: Delete operation succeeds and deletes 1 record (retVal = 1) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Delete_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Permission_Delete_Test_001::Start"); @@ -598,6 +987,20 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Delete_Test_001, TestSize.Lev LOG_INFO("SlientAccess_Permission_Delete_Test_001::End"); } +/** +* @tc.name: SlientAccess_Permission_Insert_Test_002 +* @tc.desc: Test insert operation without required permissions +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create HAP token with limited permissions +* 2. Set token ID for current process +* 3. Create DataShareHelper instance +* 4. Try to insert data into SLIENT_ACCESS_PERMISSION1_URI +* 5. Clean up token +* @tc.expect: Insert operation fails (retVal = -2) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Insert_Test_002, TestSize.Level0) { LOG_INFO("SlientAccess_Permission_Insert_Test_002::Start"); @@ -605,9 +1008,9 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Insert_Test_002, TestSize.Lev .userID = USER_100, .bundleName = "ohos.permission.write.demo", .instIndex = 0, - .appIDDesc = "ohos.permission.write.demo", + .isSystemApp = true, .apiVersion = 8, - .isSystemApp = true + .appIDDesc = "ohos.permission.write.demo" }; HapPolicyParams policy = { .apl = APL_SYSTEM_CORE, @@ -641,6 +1044,20 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Insert_Test_002, TestSize.Lev LOG_INFO("SlientAccess_Permission_Insert_Test_002::End"); } +/** +* @tc.name: SlientAccess_Permission_Update_Test_002 +* @tc.desc: Test update operation without required permissions +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create HAP token with limited permissions +* 2. Set token ID for current process +* 3. Create DataShareHelper instance +* 4. Try to update data in SLIENT_ACCESS_PERMISSION1_URI +* 5. Clean up token +* @tc.expect: Update operation fails (retVal = -2) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Update_Test_002, TestSize.Level0) { LOG_INFO("SlientAccess_Permission_Update_Test_002::Start"); @@ -648,9 +1065,9 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Update_Test_002, TestSize.Lev .userID = USER_100, .bundleName = "ohos.permission.write.demo", .instIndex = 0, - .appIDDesc = "ohos.permission.write.demo", + .isSystemApp = true, .apiVersion = 8, - .isSystemApp = true + .appIDDesc = "ohos.permission.write.demo" }; HapPolicyParams policy = { .apl = APL_SYSTEM_CORE, @@ -685,6 +1102,24 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Update_Test_002, TestSize.Lev LOG_INFO("SlientAccess_Permission_Update_Test_002::End"); } +/** +* @tc.name: SlientAccess_Permission_Query_Test_001 +* @tc.desc: Test query operation without required permissions +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create HAP token with limited permissions (only WRITE_CONTACTS granted) +* 2. Set token ID for current process +* 3. Create DataShareHelper instance +* 4. Try to query data from SLIENT_ACCESS_PERMISSION2_URI with predicates for "lisi" +* 5. Check result set, row count and business error code +* 6. Clean up token +* @tc.expect: +* 1. Result set is nullptr +* 2. Row count is 0 +* 3. Business error code is -2 (permission denied) +*/ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Query_Test_001, TestSize.Level0) { LOG_INFO("SlientAccess_Permission_Query_Test_001::Start"); @@ -692,9 +1127,9 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Query_Test_001, TestSize.Leve .userID = USER_100, .bundleName = "ohos.permission.write.demo", .instIndex = 0, - .appIDDesc = "ohos.permission.write.demo", + .isSystemApp = true, .apiVersion = 8, - .isSystemApp = true + .appIDDesc = "ohos.permission.write.demo" }; HapPolicyParams policy = { .apl = APL_SYSTEM_CORE, @@ -732,5 +1167,329 @@ HWTEST_F(SlientAccessTest, SlientAccess_Permission_Query_Test_001, TestSize.Leve AccessTokenKit::DeleteToken(testTokenId.tokenIDEx); LOG_INFO("SlientAccess_Permission_Query_Test_001::End"); } + +/** +* @tc.name: SlientAccess_Access_When_Uri_Error_Test_001 +* @tc.desc: Test data insertion with invalid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 2. Call Insert() with invalid URI (SLIENT_ERROR_URI) +* 3. Check return value +* @tc.expect: Insert operation fails (retVal < 0) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_Access_When_Uri_Error_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Permission_Access_When_URI_ERROR_Test_001::Begin"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ERROR_URI); + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "lisi"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 25; + valuesBucket.Put(TBL_STU_AGE, age); + + int retVal = helper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal < 0), true); + LOG_INFO("SlientAccess_Permission_Access_When_URI_ERROR_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_Access_With_Uncreated_DataBase_Test_001 +* @tc.desc: Test data insertion to uncreated database +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 2. Call Insert() with URI pointing to uncreated database (SLIENT_ERROR_DATABASE_URI) +* 3. Check return value +* @tc.expect: Insert operation fails (retVal < 0) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_Access_With_Uncreated_DataBase_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Access_With_Uncreated_DataBase_Test_001::Begin"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ERROR_DATABASE_URI); + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "lisi"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 25; + valuesBucket.Put(TBL_STU_AGE, age); + + int retVal = helper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal < 0), true); + LOG_INFO("SlientAccess_Access_With_Uncreated_DataBase_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_Creator_With_Uri_Error_Test_001 +* @tc.desc: Test DataShareHelper creation with invalid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Get SystemAbilityManager instance and remote object for STORAGE_MANAGER_MANAGER_ID +* 2. Try to create DataShareHelper with invalid URI (DATA_SHARE_ERROR_URI) +* 3. Check helper instance +* @tc.expect: Helper creation fails (helper == nullptr) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_Creator_With_Uri_Error_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Creator_With_Uri_Error_Test_001::Begin"); + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saManager == nullptr) { + LOG_ERROR("GetSystemAbilityManager get samgr failed."); + } + auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID); + if (remoteObj == nullptr) { + LOG_ERROR("GetSystemAbility service failed."); + } + std::string uriStr(DATA_SHARE_ERROR_URI); + auto helper = DataShare::DataShareHelper::Creator(remoteObj, uriStr, uriStr, 2); + EXPECT_EQ(helper, nullptr); + LOG_INFO("SlientAccess_Creator_With_Uri_Error_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_Creator_When_TimeOut_Test_001 +* @tc.desc: Test DataShareHelper creation with timeout +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Get SystemAbilityManager instance and remote object for STORAGE_MANAGER_MANAGER_ID +* 2. Try to create DataShareHelper with valid URI but timeout parameter 0 +* 3. Check helper instance +* @tc.expect: Helper creation fails due to timeout (helper == nullptr) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_Creator_When_TimeOut_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Creator_With_Uri_Error_Test_001::Begin"); + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saManager == nullptr) { + LOG_ERROR("GetSystemAbilityManager get samgr failed."); + } + auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID); + if (remoteObj == nullptr) { + LOG_ERROR("GetSystemAbility service failed."); + } + std::string uriStr(DATA_SHARE_URI); + auto helper = DataShare::DataShareHelper::Creator(remoteObj, uriStr, uriStr, 0); + EXPECT_EQ(helper, nullptr); + LOG_INFO("SlientAccess_Creator_With_Uri_Error_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_UserDefineFunc_Test_001 +* @tc.desc: Test custom user-defined function in DataShareHelper +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create empty MessageParcel objects for data and reply +* 2. Create default MessageOption +* 3. Call UserDefineFunc() on the helper +* 4. Check return value +* @tc.expect: User-defined function returns 0 (success) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_UserDefineFunc_Test_001, TestSize.Level0) +{ + LOG_INFO("SilentAccess_UserDefineFunc_Test_001::Start"); + auto helper = g_slientAccessHelper; + MessageParcel data; + MessageParcel reply; + MessageOption option; + auto result = helper->DataShareHelper::UserDefineFunc(data, reply, option); + EXPECT_EQ(result, 0); + LOG_INFO("SilentAccess_UserDefineFunc_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_Creator_ErrorBundle_Test_001 +* @tc.desc: Test DataShareHelper creation with invalid bundle name in URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create URI with invalid bundle name ("com.acts.error.bundleName") +* 2. Try to create DataShareHelper with this URI +* 3. Check helper instance +* @tc.expect: Helper creation fails (helper == nullptr) due to invalid bundle name +*/ +HWTEST_F(SlientAccessTest, SlientAccess_Creator_ErrorBundle_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Creator_ErrorBundle_Test_001::Start"); + std::string uriStr1("datashareproxy://com.acts.error.bundleName/test"); + // slientUri is error bundle name, slient access can't find the bundle name, return nullptr + auto helperSilent = CreateDataShareHelper(STORAGE_MANAGER_MANAGER_ID, uriStr1); + EXPECT_EQ(helperSilent, nullptr); + LOG_INFO("SlientAccess_Creator_ErrorBundle_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_Creator_ErrorBundle_ExtSuccess_Test_001 +* @tc.desc: Test DataShareHelper creation with invalid silent URI but valid ext URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Get SystemAbilityManager instance and remote object for STORAGE_MANAGER_MANAGER_ID +* 2. Try to create DataShareHelper with invalid silent URI but valid ext URI +* 3. Check return code and helper instance +* @tc.expect: +* 1. Return code is E_OK +* 2. Helper instance is not null (success due to valid ext URI) +*/ +HWTEST_F(SlientAccessTest, SlientAccess_Creator_ErrorBundle_ExtSuccess_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Creator_ErrorBundle_ExtSuccess_Test_001::Start"); + std::string uriStr1(SLIENT_ERROR_URI); + std::string uriStr2 (DATA_SHARE_URI); + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saManager == nullptr) { + LOG_ERROR("GetSystemAbilityManager get samgr failed."); + } + auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID); + if (remoteObj == nullptr) { + LOG_ERROR("GetSystemAbility service failed."); + } + // slientUri is error bundleName, extUri is effective, slient access can't find the bundleName, but ext success + auto [ret, helper] = DataShare::DataShareHelper::Create(remoteObj, uriStr1, uriStr2); + EXPECT_EQ(ret, DataShare::E_OK); + EXPECT_NE(helper, nullptr); + helper = nullptr; + LOG_INFO("SlientAccess_Creator_ErrorBundle_ExtSuccess_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_Create_With_Invalid_AppIndex_Test_001 +* @tc.desc: Test DataShareHelper creation with invalid appIndex in URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create URI with invalid appIndex parameter ("appIndex=-1") +* 2. Try to create DataShareHelper using Create() method +* 3. Try to create DataShareHelper using Creator() method +* 4. Try to create DataShareHelper with CreateOptions +* 5. Check return code and helper instances +* @tc.expect: +* 1. Create() returns E_EXT_URI_INVALID with null helper +* 2. Both Creator() methods return null helper +*/ +HWTEST_F(SlientAccessTest, SlientAccess_Create_With_Invalid_AppIndex_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Create_With_Invalid_AppIndex_Test_001::Start"); + std::string uri("datashareproxy://com.acts.datasharetest/test?Proxy=true&appIndex=-1"); + std::string extUri(DATA_SHARE_URI); + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saManager == nullptr) { + LOG_ERROR("GetSystemAbilityManager get samgr failed."); + } + auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID); + if (remoteObj == nullptr) { + LOG_ERROR("GetSystemAbility service failed."); + } + auto [ret, helper] = DataShare::DataShareHelper::Create(remoteObj, uri, ""); + EXPECT_EQ(ret, E_EXT_URI_INVALID); + EXPECT_EQ(helper, nullptr); + + helper = DataShare::DataShareHelper::Creator(remoteObj, uri); + EXPECT_EQ(helper, nullptr); + + CreateOptions options; + options.isProxy_ = true; + helper = DataShare::DataShareHelper::Creator(uri, options); + EXPECT_EQ(helper, nullptr); + LOG_INFO("SlientAccess_Create_With_Invalid_AppIndex_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_RegisterObserverExtProvider_Test_001 +* @tc.desc: Test RegisterObserverExtProvider with invalid URI (covers generalCtl == nullptr branch) +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create invalid URI (SLIENT_ERROR_URI) +* 2. Create DataShareObserverTest instance +* 3. Call RegisterObserverExtProvider with invalid URI and observer +* @tc.expect: No crash occurs, method executes without errors +*/ +HWTEST_F(SlientAccessTest, SlientAccess_RegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_RegisterObserverExtProvider_Test_001::Begin"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ERROR_URI); + std::shared_ptr dataObserver = std::make_shared(); + ASSERT_NE(helper, nullptr); + ASSERT_NE(dataObserver, nullptr); + + helper->RegisterObserverExtProvider(uri, dataObserver, false); + + LOG_INFO("SlientAccess_RegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_UnregisterObserverExtProvider_Test_001 +* @tc.desc: Test UnregisterObserverExtProvider with invalid URI (covers generalCtl == nullptr branch) +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create invalid URI (SLIENT_ERROR_URI) +* 2. Create DataShareObserverTest instance +* 3. Call UnregisterObserverExtProvider with invalid URI and observer +* 4. Create dummy ChangeInfo object +* @tc.expect: No crash occurs, method executes without errors +*/ +HWTEST_F(SlientAccessTest, SlientAccess_UnregisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_UnregisterObserverExtProvider_Test_001::Begin"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ERROR_URI); + std::shared_ptr dataObserver = std::make_shared(); + ASSERT_NE(helper, nullptr); + ASSERT_NE(dataObserver, nullptr); + + helper->UnregisterObserverExtProvider(uri, dataObserver); + + ChangeInfo changeInfo = { DataShareObserver::ChangeType::INSERT, { uri } }; + LOG_INFO("SlientAccess_UnregisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: SlientAccess_NotifyChangeExtProvider_Test_001 +* @tc.desc: Test NotifyChangeExtProvider with invalid URI (covers generalCtl == nullptr branch) +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create invalid URI (SLIENT_ERROR_URI) +* 2. Create DataShareObserverTest instance +* 3. Register observer with invalid URI +* 4. Create ChangeInfo object for INSERT operation +* 5. Call NotifyChangeExtProvider with ChangeInfo +* @tc.expect: No crash occurs, notification process executes without errors +*/ +HWTEST_F(SlientAccessTest, SlientAccess_NotifyChangeExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_NotifyChangeExtProvider_Test_001::Begin"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ERROR_URI); + std::shared_ptr dataObserver = std::make_shared(); + ASSERT_NE(helper, nullptr); + ASSERT_NE(dataObserver, nullptr); + + helper->RegisterObserverExtProvider(uri, dataObserver, true); + + ChangeInfo changeInfo = { DataShareObserver::ChangeType::INSERT, { uri } }; + helper->NotifyChangeExtProvider(changeInfo); + + LOG_INFO("SlientAccess_NotifyChangeExtProvider_Test_001::End"); +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/slientswitch_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/slientswitch_test.cpp index a0c08381..ac9842b8 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/slientswitch_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/slientswitch_test.cpp @@ -28,8 +28,14 @@ namespace DataShare { using namespace testing::ext; using namespace OHOS::Security::AccessToken; constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::string SLIENT_ACCESS_URI = "datashare:///com.acts.datasharetest/entry/DB00/TBL00?Proxy=true"; +std::string DATA_SHARE_PROXY_URI = "datashare:///com.acts.ohos.data.datasharetest/test"; constexpr int SUBSCRIBER_ID = 1000; +std::string TBL_STU_NAME = "name"; +std::string TBL_STU_AGE = "age"; int32_t ERROR = -1; +std::shared_ptr g_slientAccessHelper; class SlientSwitchTest : public testing::Test { public: @@ -37,21 +43,10 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); - -protected: - static inline std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; - static inline std::string SLIENT_ACCESS_URI = "datashare:///com.acts.datasharetest/entry/DB00/TBL00?Proxy=true"; - static inline std::string DATA_SHARE_PROXY_URI = "datashare:///com.acts.ohos.data.datasharetest/test"; - static inline std::string TBL_STU_NAME = "name"; - static inline std::string TBL_STU_AGE = "age"; - static std::shared_ptr CreateDataShareHelper(int32_t systemAbilityId, - const std::string &silentProxyUri, const std::string &providerUri = ""); - static std::shared_ptr g_slientAccessHelper; }; -std::shared_ptr SlientSwitchTest::g_slientAccessHelper; -std::shared_ptr SlientSwitchTest::CreateDataShareHelper(int32_t systemAbilityId, - const std::string &silentProxyUri, const std::string &providerUri) +std::shared_ptr CreateDataShareHelper(int32_t systemAbilityId, + const std::string &silentProxyUri, const std::string &providerUri = "") { LOG_INFO("CreateDataShareHelper start"); auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); @@ -126,6 +121,18 @@ void SlientSwitchTest::TearDownTestCase(void) void SlientSwitchTest::SetUp(void) {} void SlientSwitchTest::TearDown(void) {} +/** +* @tc.name: SlientSwitch_SetSilentSwitch_Test_001 +* @tc.desc: Test enabling silent switch with valid access URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Call DataShareHelper::SetSilentSwitch() with URI and true (enable) +* 3. Verify the return value +* @tc.expect: The operation succeeds with return value E_OK +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SetSilentSwitch_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SetSilentSwitch_Test_001::Start"); @@ -135,6 +142,18 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SetSilentSwitch_Test_001, TestSize.Level LOG_INFO("SlientSwitch_SetSilentSwitch_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SetSilentSwitch_Test_002 +* @tc.desc: Test disabling silent switch with valid access URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Call DataShareHelper::SetSilentSwitch() with URI and false (disable) +* 3. Verify the return value +* @tc.expect: The operation succeeds with return value E_OK +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SetSilentSwitch_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SetSilentSwitch_Test_002::Start"); @@ -144,6 +163,18 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SetSilentSwitch_Test_002, TestSize.Level LOG_INFO("SlientSwitch_SetSilentSwitch_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SetSilentSwitch_Test_003 +* @tc.desc: Test disabling silent switch with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create empty Uri object +* 2. Call DataShareHelper::SetSilentSwitch() with empty URI and false (disable) +* 3. Verify the return value +* @tc.expect: The operation succeeds with return value E_OK +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SetSilentSwitch_Test_003, TestSize.Level0) { LOG_INFO("SlientSwitch_SetSilentSwitch_Test_003::Start"); @@ -153,6 +184,18 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SetSilentSwitch_Test_003, TestSize.Level LOG_INFO("SlientSwitch_SetSilentSwitch_Test_003::End"); } +/** +* @tc.name: SlientSwitch_SetSilentSwitch_Test_004 +* @tc.desc: Test enabling silent switch with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create empty Uri object +* 2. Call DataShareHelper::SetSilentSwitch() with empty URI and true (enable) +* 3. Verify the return value +* @tc.expect: The operation succeeds with return value E_OK +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SetSilentSwitch_Test_004, TestSize.Level0) { LOG_INFO("SlientSwitch_SetSilentSwitch_Test_004::Start"); @@ -162,6 +205,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SetSilentSwitch_Test_004, TestSize.Level LOG_INFO("SlientSwitch_SetSilentSwitch_Test_004::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_Insert_Test_001 +* @tc.desc: Test data insertion when silent switch is disabled with valid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Disable silent switch using SetSilentSwitch() with URI +* 3. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 4. Call Insert() method with URI and values bucket +* 5. Verify the return value +* @tc.expect: Insert operation fails (return value <= 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Insert_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_Insert_Test_001::Start"); @@ -181,6 +238,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Insert_Test_001, TestSize. LOG_INFO("SlientSwitch_SwitchDisable_Insert_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_Insert_Test_002 +* @tc.desc: Test data insertion when silent switch is disabled with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Disable silent switch using SetSilentSwitch() with empty URI +* 2. Prepare DataShareValuesBucket with test data (name="wangwu", age=25) +* 3. Create Uri object with SLIENT_ACCESS_URI +* 4. Call Insert() method with URI and values bucket +* 5. Verify the return value +* @tc.expect: Insert operation fails (return value <= 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Insert_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_Insert_Test_002::Start"); @@ -200,6 +271,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Insert_Test_002, TestSize. LOG_INFO("SlientSwitch_SwitchDisable_Insert_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_Insert_Test_001 +* @tc.desc: Test data insertion when silent switch is enabled with valid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Enable silent switch using SetSilentSwitch() with URI +* 3. Prepare DataShareValuesBucket with test data (name="lisi", age=25) +* 4. Call Insert() method with URI and values bucket +* 5. Verify the return value +* @tc.expect: Insert operation succeeds (return value > 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Insert_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_Insert_Test_001::Start"); @@ -219,6 +304,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Insert_Test_001, TestSize.L LOG_INFO("SlientSwitch_SwitchEnable_Insert_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_Insert_Test_002 +* @tc.desc: Test data insertion when silent switch is enabled with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Enable silent switch using SetSilentSwitch() with empty URI +* 2. Prepare DataShareValuesBucket with test data (name="wangwu", age=25) +* 3. Create Uri object with SLIENT_ACCESS_URI +* 4. Call Insert() method with URI and values bucket +* 5. Verify the return value +* @tc.expect: Insert operation succeeds (return value > 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Insert_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_Insert_Test_002::Start"); @@ -238,6 +337,21 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Insert_Test_002, TestSize.L LOG_INFO("SlientSwitch_SwitchEnable_Insert_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_Update_Test_001 +* @tc.desc: Test data update when silent switch is disabled with valid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Disable silent switch using SetSilentSwitch() with URI +* 3. Prepare DataShareValuesBucket with update data (age=50) +* 4. Create DataSharePredicates to select record with name="lisi" +* 5. Call Update() method with URI, predicates and values bucket +* 6. Verify the return value +* @tc.expect: Update operation fails (return value <= 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Update_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_Update_Test_001::Start"); @@ -257,6 +371,21 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Update_Test_001, TestSize. LOG_INFO("SlientSwitch_SwitchDisable_Update_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_Update_Test_002 +* @tc.desc: Test data update when silent switch is disabled with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Disable silent switch using SetSilentSwitch() with empty URI +* 2. Prepare DataShareValuesBucket with update data (age=50) +* 3. Create DataSharePredicates to select record with name="wangwu" +* 4. Create Uri object with SLIENT_ACCESS_URI +* 5. Call Update() method with URI, predicates and values bucket +* 6. Verify the return value +* @tc.expect: Update operation fails (return value <= 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Update_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_Update_Test_002::Start"); @@ -277,6 +406,21 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Update_Test_002, TestSize. LOG_INFO("SlientSwitch_SwitchDisable_Update_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_Update_Test_001 +* @tc.desc: Test data update when silent switch is enabled with valid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Enable silent switch using SetSilentSwitch() with URI +* 3. Prepare DataShareValuesBucket with update data (age=50) +* 4. Create DataSharePredicates to select record with name="lisi" +* 5. Call Update() method with URI, predicates and values bucket +* 6. Verify the return value +* @tc.expect: Update operation succeeds (return value > 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Update_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_Update_Test_001::Start"); @@ -296,6 +440,21 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Update_Test_001, TestSize.L LOG_INFO("SlientSwitch_SwitchEnable_Update_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_Update_Test_002 +* @tc.desc: Test data update when silent switch is enabled with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Enable silent switch using SetSilentSwitch() with empty URI +* 2. Prepare DataShareValuesBucket with update data (age=50) +* 3. Create DataSharePredicates to select record with name="wangwu" +* 4. Create Uri object with SLIENT_ACCESS_URI +* 5. Call Update() method with URI, predicates and values bucket +* 6. Verify the return value +* @tc.expect: Update operation succeeds (return value > 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Update_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_Update_Test_002::Start"); @@ -316,6 +475,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Update_Test_002, TestSize.L LOG_INFO("SlientSwitch_SwitchEnable_Update_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_Query_Test_001 +* @tc.desc: Test data query when silent switch is disabled with valid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Disable silent switch using SetSilentSwitch() with URI +* 3. Create DataSharePredicates to select record with name="lisi" +* 4. Call Query() method with URI, predicates and empty columns list +* 5. Verify the result set +* @tc.expect: Query operation fails (resultSet is nullptr) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Query_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_Query_Test_001::Start"); @@ -332,6 +505,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Query_Test_001, TestSize.L LOG_INFO("SlientSwitch_SwitchDisable_Query_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_Query_Test_002 +* @tc.desc: Test data query when silent switch is disabled with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Disable silent switch using SetSilentSwitch() with empty URI +* 2. Create DataSharePredicates to select record with name="wangwu" +* 3. Create Uri object with SLIENT_ACCESS_URI +* 4. Call Query() method with URI, predicates and empty columns list +* 5. Verify the result set +* @tc.expect: Query operation fails (resultSet is nullptr) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Query_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_Query_Test_002::Start"); @@ -349,6 +536,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Query_Test_002, TestSize.L LOG_INFO("SlientSwitch_SwitchDisable_Query_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_Query_Test_001 +* @tc.desc: Test data query when silent switch is enabled with valid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Enable silent switch using SetSilentSwitch() with URI +* 3. Create DataSharePredicates to select record with name="lisi" +* 4. Call Query() method with URI, predicates and empty columns list +* 5. Check row count of the result set +* @tc.expect: Query operation succeeds and returns 1 record +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Query_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_Query_Test_001::Start"); @@ -369,6 +570,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Query_Test_001, TestSize.Le LOG_INFO("SlientSwitch_SwitchEnable_Query_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_Query_Test_002 +* @tc.desc: Test data query when silent switch is enabled with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Enable silent switch using SetSilentSwitch() with empty URI +* 2. Create DataSharePredicates to select record with name="wangwu" +* 3. Create Uri object with SLIENT_ACCESS_URI +* 4. Call Query() method with URI, predicates and empty columns list +* 5. Check row count of the result set +* @tc.expect: Query operation succeeds and returns 1 record +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Query_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_Query_Test_002::Start"); @@ -390,6 +605,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Query_Test_002, TestSize.Le LOG_INFO("SlientSwitch_SwitchEnable_Query_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_Delete_Test_001 +* @tc.desc: Test data deletion when silent switch is disabled with valid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Disable silent switch using SetSilentSwitch() with URI +* 3. Create DataSharePredicates to select record with name="lisi" +* 4. Call Delete() method with URI and predicates +* 5. Verify the return value +* @tc.expect: Delete operation fails (return value <= 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Delete_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_Delete_Test_001::Start"); @@ -406,6 +635,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Delete_Test_001, TestSize. LOG_INFO("SlientSwitch_SwitchDisable_Delete_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_Delete_Test_002 +* @tc.desc: Test data deletion when silent switch is disabled with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Disable silent switch using SetSilentSwitch() with empty URI +* 2. Create DataSharePredicates to select record with name="wangwu" +* 3. Create Uri object with SLIENT_ACCESS_URI +* 4. Call Delete() method with URI and predicates +* 5. Verify the return value +* @tc.expect: Delete operation fails (return value <= 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Delete_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_Delete_Test_002::Start"); @@ -423,6 +666,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_Delete_Test_002, TestSize. LOG_INFO("SlientSwitch_SwitchDisable_Delete_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_Delete_Test_001 +* @tc.desc: Test data deletion when silent switch is enabled with valid URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Create Uri object with SLIENT_ACCESS_URI +* 2. Enable silent switch using SetSilentSwitch() with URI +* 3. Create DataSharePredicates to select record with name="lisi" +* 4. Call Delete() method with URI and predicates +* 5. Verify the return value +* @tc.expect: Delete operation succeeds (return value > 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Delete_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_Delete_Test_001::Start"); @@ -439,6 +696,20 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Delete_Test_001, TestSize.L LOG_INFO("SlientSwitch_SwitchEnable_Delete_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_Delete_Test_002 +* @tc.desc: Test data deletion when silent switch is enabled with empty URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Enable silent switch using SetSilentSwitch() with empty URI +* 2. Create DataSharePredicates to select record with name="wangwu" +* 3. Create Uri object with SLIENT_ACCESS_URI +* 4. Call Delete() method with URI and predicates +* 5. Verify the return value +* @tc.expect: Delete operation succeeds (return value > 0) +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Delete_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_Delete_Test_002::Start"); @@ -456,6 +727,22 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_Delete_Test_002, TestSize.L LOG_INFO("SlientSwitch_SwitchEnable_Delete_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchDisable_CreateHelper_Test_001 +* @tc.desc: Test DataShareHelper creation when silent switch is disabled +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: + 1. Create initial DataShareHelper with valid parameters (should succeed) + 2. Disable silent switch using SetSilentSwitch() with empty URI + 3. Try to create another DataShareHelper with same parameters + 4. Re-enable silent switch +* @tc.expect: + 1. First helper creation succeeds (helper != nullptr) + 2. Second helper creation fails (helper == nullptr) + 3. Re-enabling switch returns E_OK +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_CreateHelper_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_CreateHelper_Test_001::Start"); @@ -484,6 +771,23 @@ Template GetTemplate() return tpl; } +/** +* @tc.name: SlientSwitch_SwitchDisable_CreateHelper_Test_002 +* @tc.desc: Test AddQueryTemplate when silent switch is disabled +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Disable silent switch using SetSilentSwitch() with empty URI +* 2. Create DataShareHelper with valid parameters +* 3. Get query template using GetTemplate() +* 4. Call AddQueryTemplate with proxy URI, subscriber ID and template +* 5. Re-enable silent switch +* @tc.expect: +* 1. Helper creation succeeds (helper != nullptr) +* 2. AddQueryTemplate returns ERROR (-1) +* 3. Re-enabling switch returns E_OK +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_CreateHelper_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchDisable_CreateHelper_Test_002::Start"); @@ -502,6 +806,21 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchDisable_CreateHelper_Test_002, Tes LOG_INFO("SlientSwitch_SwitchDisable_CreateHelper_Test_002::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_CreateHelper_Test_001 +* @tc.desc: Test AddQueryTemplate when silent switch is enabled (without provider URI) +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Enable silent switch using SetSilentSwitch() with empty URI +* 2. Create DataShareHelper with valid parameters (without provider URI) +* 3. Get query template using GetTemplate() +* 4. Call AddQueryTemplate with proxy URI, subscriber ID and template +* @tc.expect: +* 1. Helper creation succeeds (helper != nullptr) +* 2. AddQueryTemplate returns E_BUNDLE_NAME_NOT_EXIST +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_CreateHelper_Test_001, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_CreateHelper_Test_001::Start"); @@ -518,6 +837,21 @@ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_CreateHelper_Test_001, Test LOG_INFO("SlientSwitch_SwitchEnable_CreateHelper_Test_001::End"); } +/** +* @tc.name: SlientSwitch_SwitchEnable_CreateHelper_Test_002 +* @tc.desc: Test AddQueryTemplate when silent switch is enabled (with provider URI) +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: None +* @tc.step: +* 1. Enable silent switch using SetSilentSwitch() with empty URI +* 2. Create DataShareHelper with valid parameters (including provider URI) +* 3. Get query template using GetTemplate() +* 4. Call AddQueryTemplate with proxy URI, subscriber ID and template +* @tc.expect: +* 1. Helper creation succeeds (helper != nullptr) +* 2. AddQueryTemplate returns E_BUNDLE_NAME_NOT_EXIST +*/ HWTEST_F(SlientSwitchTest, SlientSwitch_SwitchEnable_CreateHelper_Test_002, TestSize.Level0) { LOG_INFO("SlientSwitch_SwitchEnable_CreateHelper_Test_002::Start"); diff --git a/data_share/test/native/unittest/mediadatashare_test/src/uri_utils_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/uri_utils_test.cpp new file mode 100644 index 00000000..febe91be --- /dev/null +++ b/data_share/test/native/unittest/mediadatashare_test/src/uri_utils_test.cpp @@ -0,0 +1,314 @@ +/* + * 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. + */ +#define LOG_TAG "URIUtilsTest" + +#include +#include + +#include "datashare_uri_utils.h" +#include "log_print.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::DataShare; +class URIUtilsTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +/** +* @tc.name: GetUserFromUri_001 +* @tc.desc: Test getting user from URI without user parameter +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest" without user parameter +* 2. Call DataShareURIUtils::GetUserFromUri() with the URI +* 3. Check the return result and user value +* @tc.expect: +* 1. The result is true +* 2. The user value is -1 (default) +*/ +HWTEST_F(URIUtilsTest, GetUserFromUri_001, TestSize.Level0) +{ + ZLOGI("GetUserFromUri_001 starts"); + std::string uri = "datashare:///com.acts.datasharetest"; + auto [res, user] = DataShareURIUtils::GetUserFromUri(uri); + EXPECT_EQ(res, true); + EXPECT_EQ(user, -1); + ZLOGI("GetUserFromUri_001 ends"); +} + +/** +* @tc.name: GetUserFromUri_002 +* @tc.desc: Test getting valid positive user from URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest?user=100" with valid user parameter +* 2. Call DataShareURIUtils::GetUserFromUri() with the URI +* 3. Check the return result and user value +* @tc.expect: +* 1. The result is true +* 2. The user value is 100 +*/ +HWTEST_F(URIUtilsTest, GetUserFromUri_002, TestSize.Level0) +{ + ZLOGI("GetUserFromUri_002 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user=100"; + auto [res, user] = DataShareURIUtils::GetUserFromUri(uri); + EXPECT_EQ(res, true); + EXPECT_EQ(user, 100); + ZLOGI("GetUserFromUri_002 ends"); +} + +/** +* @tc.name: GetUserFromUri_003 +* @tc.desc: Test getting user from URI with non-numeric user parameter +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest?user=f" with invalid user parameter +* 2. Call DataShareURIUtils::GetUserFromUri() with the URI +* 3. Check the return result and user value +* @tc.expect: +* 1. The result is false +* 2. The user value is -1 +*/ +HWTEST_F(URIUtilsTest, GetUserFromUri_003, TestSize.Level0) +{ + ZLOGI("GetUserFromUri_003 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user=f"; + auto [res, user] = DataShareURIUtils::GetUserFromUri(uri); + EXPECT_EQ(res, false); + EXPECT_EQ(user, -1); + ZLOGI("GetUserFromUri_003 ends"); +} + +/** +* @tc.name: GetUserFromUri_004 +* @tc.desc: Test getting user from URI with negative user parameter +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest?user=-1" with negative user parameter +* 2. Call DataShareURIUtils::GetUserFromUri() with the URI +* 3. Check the return result and user value +* @tc.expect: +* 1. The result is false +* 2. The user value is -1 +*/ +HWTEST_F(URIUtilsTest, GetUserFromUri_004, TestSize.Level0) +{ + ZLOGI("GetUserFromUri_004 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user=-1"; + auto [res, user] = DataShareURIUtils::GetUserFromUri(uri); + EXPECT_EQ(res, false); + EXPECT_EQ(user, -1); + ZLOGI("GetUserFromUri_004 ends"); +} + +/** +* @tc.name: GetUserFromUri_005 +* @tc.desc: Test getting user from URI with empty user parameter +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest?user=" with empty user parameter +* 2. Call DataShareURIUtils::GetUserFromUri() with the URI +* 3. Check the return result and user value +* @tc.expect: +* 1. The result is true +* 2. The user value is -1 +*/ +HWTEST_F(URIUtilsTest, GetUserFromUri_005, TestSize.Level0) +{ + ZLOGI("GetUserFromUri_005 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user="; + auto [res, user] = DataShareURIUtils::GetUserFromUri(uri); + EXPECT_EQ(res, true); + EXPECT_EQ(user, -1); + ZLOGI("GetUserFromUri_005 ends"); +} + +/** +* @tc.name: GetUserFromUri_006 +* @tc.desc: Test getting user from URI with whitespace user parameter +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest?user= " with whitespace user parameter +* 2. Call DataShareURIUtils::GetUserFromUri() with the URI +* 3. Check the return result and user value +* @tc.expect: +* 1. The result is false +* 2. The user value is -1 +*/ +HWTEST_F(URIUtilsTest, GetUserFromUri_006, TestSize.Level0) +{ + ZLOGI("GetUserFromUri_006 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user= "; + auto [res, user] = DataShareURIUtils::GetUserFromUri(uri); + EXPECT_EQ(res, false); + EXPECT_EQ(user, -1); + ZLOGI("GetUserFromUri_006 ends"); +} + +/** +* @tc.name: GetUserFromUri_007 +* @tc.desc: Test getting user from URI with overflow user parameter +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: + 1. Create URI "datashare:///com.acts.datasharetest?user=2147483648" with overflow user parameter + 2. Call DataShareURIUtils::GetUserFromUri() with the URI + 3. Check the return result and user value +* @tc.expect: + 1. The result is false + 2. The user value is -1 +*/ +HWTEST_F(URIUtilsTest, GetUserFromUri_007, TestSize.Level0) +{ + ZLOGI("GetUserFromUri_007 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user=2147483648"; + auto [res, user] = DataShareURIUtils::GetUserFromUri(uri); + EXPECT_EQ(res, false); + EXPECT_EQ(user, -1); + ZLOGI("GetUserFromUri_007 ends"); +} + +/** +* @tc.name: GetUserFromUri_008 +* @tc.desc: Test getting user from URI with multiple user parameters +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest?user=100&user=111" with multiple user parameters +* 2. Call DataShareURIUtils::GetUserFromUri() with the URI +* 3. Check the return result and user value +* @tc.expect: +* 1. The result is true +* 2. The user value is 111 (last occurrence) +*/ +HWTEST_F(URIUtilsTest, GetUserFromUri_008, TestSize.Level0) +{ + ZLOGI("GetUserFromUri_008 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user=100&user=111"; + auto [res, user] = DataShareURIUtils::GetUserFromUri(uri); + EXPECT_EQ(res, true); + EXPECT_EQ(user, 111); + ZLOGI("GetUserFromUri_008 ends"); +} + +/** +* @tc.name: GetQueryParams_001 +* @tc.desc: Test getting query parameters from URI +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest?user=100&srcToken=12345" with query parameters +* 2. Call DataShareURIUtils::GetQueryParams() with the URI +* 3. Check if the result is not empty +* @tc.expect:The returned query parameters are not empty +*/ +HWTEST_F(URIUtilsTest, GetQueryParams_001, TestSize.Level0) +{ + ZLOGI("GetQueryParams_001 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user=100&srcToken=12345"; + auto res = DataShareURIUtils::GetQueryParams(uri); + EXPECT_EQ(res.empty(), false); + ZLOGI("GetQueryParams_001 ends"); +} + +/** +* @tc.name: Strtoul_001 +* @tc.desc: Test converting empty string to unsigned integer +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create empty string +* 2. Call DataShareURIUtils::Strtoul() with the empty string +* 3. Check the return result and converted value +* @tc.expect: +* 1. The result is false +* 2. The converted value is 0 +*/ +HWTEST_F(URIUtilsTest, Strtoul_001, TestSize.Level0) +{ + ZLOGI("Strtoul_001 starts"); + std::string str = ""; + std::pair res = DataShareURIUtils::Strtoul(str); + EXPECT_EQ(res.first, false); + EXPECT_EQ(res.second, 0); + ZLOGI("Strtoul_001 ends"); +} + +/** +* @tc.name: FormatUri_001 +* @tc.desc: Test formatting URI by removing query parameters +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest?user=100&srcToken=12345" with query parameters +* 2. Call DataShareURIUtils::FormatUri() with the URI +* 3. Check the formatted URI +* @tc.expect:The formatted URI is "datashare:///com.acts.datasharetest" without query parameters +*/ +HWTEST_F(URIUtilsTest, FormatUri_001, TestSize.Level0) +{ + ZLOGI("FormatUri_001 starts"); + std::string uri = "datashare:///com.acts.datasharetest?user=100&srcToken=12345"; + std::string res = DataShareURIUtils::FormatUri(uri); + EXPECT_EQ(res, "datashare:///com.acts.datasharetest"); + ZLOGI("FormatUri_001 ends"); +} + +/** +* @tc.name: FormatUri_002 +* @tc.desc: Test formatting URI without query parameters +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create URI "datashare:///com.acts.datasharetest" without query parameters +* 2. Call DataShareURIUtils::FormatUri() with the URI +* 3. Check the formatted URI +* @tc.expect:The formatted URI is the same as input "datashare:///com.acts.datasharetest" +*/ +HWTEST_F(URIUtilsTest, FormatUri_002, TestSize.Level0) +{ + ZLOGI("FormatUri_002 starts"); + std::string uri = "datashare:///com.acts.datasharetest"; + std::string res = DataShareURIUtils::FormatUri(uri); + EXPECT_EQ(res, "datashare:///com.acts.datasharetest"); + ZLOGI("FormatUri_002 ends"); +} +} // namespace DataShare +} \ No newline at end of file diff --git a/data_share/test/native/unittest/mediadatashare_test/src/valueproxy_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/valueproxy_test.cpp index ade97386..950d26d0 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/valueproxy_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/valueproxy_test.cpp @@ -22,6 +22,20 @@ namespace DataShare { using namespace testing::ext; class ValueProxyTest : public testing::Test { }; + +/** +* @tc.name: VBucketsDataShare2Normal +* @tc.desc: Test conversion from DataShareValuesBucket vector to normal VBuckets +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create two DataShareValuesBucket objects and add key-value pairs +* 2. Put the buckets into a vector +* 3. Convert the vector using ValueProxy::Convert() +* 4. Verify the converted VBuckets size is 2 +* @tc.expect: The converted VBuckets has size 2, matching original vector size +*/ HWTEST_F(ValueProxyTest, VBucketsDataShare2Normal, TestSize.Level0) { using DataShareBucket = OHOS::DataShare::DataShareValuesBucket; @@ -35,6 +49,19 @@ HWTEST_F(ValueProxyTest, VBucketsDataShare2Normal, TestSize.Level0) extends = ValueProxy::Convert(std::move(VBuckets)); ASSERT_EQ(extends.size(), 2); } + +/** +* @tc.name: VBucketsNormal2DataShare +* @tc.desc: Test conversion from normal VBuckets to DataShareValuesBucket vector +* @tc.type: FUNC +* @tc.require: NA +* @tc.precon: NA +* @tc.step: +* 1. Create a VBuckets object with two entries containing key-value pairs +* 2. Convert the VBuckets using ValueProxy::Convert() +* 3. Verify the converted DataShareValuesBucket vector size is 2 +* @tc.expect: The converted vector has size 2, matching original VBuckets size +*/ HWTEST_F(ValueProxyTest, VBucketsNormal2DataShare, TestSize.Level0) { using DataShareBucket = OHOS::DataShare::DataShareValuesBucket; diff --git a/data_share/test/native/unittest/mock/ikvstore_data_service_mock.h b/data_share/test/native/unittest/mock/ikvstore_data_service_mock.h new file mode 100644 index 00000000..22eb89f4 --- /dev/null +++ b/data_share/test/native/unittest/mock/ikvstore_data_service_mock.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 IKVSTORE_DATA_SERVICE_MOCK_H +#define IKVSTORE_DATA_SERVICE_MOCK_H + +#include +#include "gmock/gmock.h" +#include "ikvstore_data_service.h" + +namespace OHOS { +namespace DataShare { +class MockDataShareKvServiceProxy : public DataShareKvServiceProxy { +public: + explicit MockDataShareKvServiceProxy(const sptr &impl) + : DataShareKvServiceProxy(impl) {} + ~MockDataShareKvServiceProxy() = default; + MOCK_METHOD(sptr, GetFeatureInterface, (const std::string &name), (override)); + MOCK_METHOD(uint32_t, RegisterClientDeathObserver, (const std::string &appId, sptr observer), + (override)); +}; +} +} +#endif // IKVSTORE_DATA_SERVICE_MOCK_H \ No newline at end of file diff --git a/relational_store/test/js/gdb/BUILD.gn b/data_share/test/unittest/native/BUILD.gn similarity index 58% rename from relational_store/test/js/gdb/BUILD.gn rename to data_share/test/unittest/native/BUILD.gn index 903b0e9f..0fc82db3 100644 --- a/relational_store/test/js/gdb/BUILD.gn +++ b/data_share/test/unittest/native/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2024 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 @@ -12,24 +12,20 @@ # limitations under the License. import("//build/test.gni") -import("//foundation/distributeddatamgr/relational_store/relational_store.gni") -#################################group######################################### +################################################################## group("unittest") { testonly = true deps = [] - if (arkdata_db_core_is_exists) { - deps += [ "unittest/src:unittest" ] - } + deps += [ + "consumer:unittest", + "common:unittest", + "provider:unittest", + "../../native/resource/datashare_ext_bundle:datashare_ext", + "../../native/resource/datashareproxy_bundle/proxydatas_with_permission:proxydatas_with_permission", + "../../native/resource/errorcode_ext_bundle:errorcode_ext", + "../../native/resource/ohos_test_new:copy_ohos_test_new", + ] } - -group("performancetest") { - testonly = true - deps = [] - - if (arkdata_db_core_is_exists) { - deps += [ "performance/src:GdbPerfJsTest" ] - } -} -############################################################################### +################################################################## \ No newline at end of file diff --git a/data_share/test/unittest/native/common/BUILD.gn b/data_share/test/unittest/native/common/BUILD.gn new file mode 100644 index 00000000..9024aadc --- /dev/null +++ b/data_share/test/unittest/native/common/BUILD.gn @@ -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. + +import("//build/test.gni") +import("//foundation/distributeddatamgr/data_share/datashare.gni") + +group("unittest") { + testonly = true + deps = [] + + deps += [ + ":DataShareAbsResultSetTest", + ":DataShareBlockWriterImplTest", + ":DatashareResultSetTest", + ":ValueProxyTest", + ":IsharedResultSetStubTest", + ] +} + +config("permission_config") { + visibility = [ ":*" ] + include_dirs = [ + "${datashare_common_native_path}/include", + "${datashare_native_permission_path}/include", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } +} + +ohos_unittest("DataShareAbsResultSetTest") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "${datashare_base_path}/cfi_blocklist.txt" + } + + module_out_path = "data_share/data_share/native/common" + + include_dirs = [ "${datashare_base_path}/frameworks/native/common/include/" ] + + sources = [ "${datashare_base_path}/test/unittest/native/common/src/datashare_abs_result_set_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "googletest:gmock_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "ipc:rpc", + "ipc:ipc_core", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DataShareBlockWriterImplTest") { + module_out_path = "data_share/data_share/native/common" + + include_dirs = [ + "${datashare_native_consumer_path}/include", + "${datashare_common_native_path}/include", + "${datashare_innerapi_path}/consumer/include", + "${datashare_innerapi_path}/common/include", + "${datashare_innerapi_path}/provider/include", + "${datashare_native_consumer_path}/controller/provider/include", + "${datashare_native_consumer_path}/controller/common", + "${datashare_native_consumer_path}/controller/service/include", + "${datashare_native_proxy_path}/include", + ] + + sources = [ + "${datashare_base_path}/test/unittest/native/common/src/datashare_block_writer_impl_test.cpp", + ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:zuri", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "kv_store:distributeddata_inner", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DatashareResultSetTest") { + module_out_path = "data_share/data_share/native/common" + + include_dirs = [ "${datashare_base_path}/frameworks/native/common/include/" ] + + sources = [ "${datashare_base_path}/test/unittest/native/common/src/datashare_result_set_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "ipc:rpc", + "ipc:ipc_core", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + + +ohos_unittest("ValueProxyTest") { + module_out_path = "data_share/data_share/native/common" + + include_dirs = [ "${datashare_base_path}/frameworks/native/common/include/" ] + + sources = [ "${datashare_base_path}/test/unittest/native/common/src/datashare_valuebucket_convert_test.cpp" ] + + deps = [ "${datashare_innerapi_path}/common:datashare_common_static" ] + + external_deps = [ + "ability_base:zuri", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "kv_store:distributeddata_inner", + ] +} + + +ohos_unittest("IsharedResultSetStubTest") { + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "${datashare_base_path}/cfi_blocklist.txt" + } + + module_out_path = "data_share/data_share/native/common" + + include_dirs = [ "${datashare_base_path}/frameworks/native/common/include/" ] + + sources = [ "${datashare_base_path}/test/unittest/native/common/src/ishared_result_set_stub_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "ipc:rpc", + "ipc:ipc_core", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} \ No newline at end of file diff --git a/data_share/test/unittest/native/common/src/datashare_abs_result_set_test.cpp b/data_share/test/unittest/native/common/src/datashare_abs_result_set_test.cpp new file mode 100644 index 00000000..2f6565c3 --- /dev/null +++ b/data_share/test/unittest/native/common/src/datashare_abs_result_set_test.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 +#include + +#include "datashare_errno.h" +#include "datashare_itypes_utils.h" +#include "datashare_log.h" +#include "datashare_abs_result_set.h" +#include "datashare_result_set.h" +#include "ikvstore_data_service.h" +#include "ipc_types.h" +#include "ishared_result_set_stub.h" +#include "itypes_util.h" +#include "message_parcel.h" +#include "gmock/gmock.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +class DataShareAbsResultSetTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +class MockDataShareAbsResultSet : public DataShareAbsResultSet { +public: + MOCK_METHOD1(GoToRow, int(int)); + MOCK_METHOD1(GetRowCount, int(int &)); + MOCK_METHOD1(GetAllColumnNames, int(std::vector &)); + MOCK_METHOD1(GetColumnCount, int(int &)); +}; + +class MockDataShareAbsResultSet2 : public DataShareAbsResultSet { +public: + MOCK_METHOD1(GetAllColumnNames, int(std::vector &)); +}; + +/** +* @tc.name: GoToTest001 +* @tc.desc: test GoTo function when GoToRow return E_ERROR +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GoTo function when GoToRow return E_ERROR and check the result +* @tc.experct: GoTo failed and return E_ERROR +*/ +HWTEST_F(DataShareAbsResultSetTest, GoToTest001, TestSize.Level0) +{ + LOG_INFO("DataShareAbsResultSetTest GoToTest001::Start"); + MockDataShareAbsResultSet mockResultSet; + int offset = 1; + EXPECT_CALL(mockResultSet, GoToRow(testing::_)) + .WillOnce(testing::Return(E_ERROR)); + auto result = mockResultSet.GoTo(offset); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareAbsResultSetTest GoToTest001::End"); +} + +/** +* @tc.name: GoToTest002 +* @tc.desc: test GoTo function +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GoTo function and check the result +* @tc.experct: GoTo success and return E_OK +*/ +HWTEST_F(DataShareAbsResultSetTest, GoToTest002, TestSize.Level0) +{ + LOG_INFO("DataShareAbsResultSetTest GoToTest002::Start"); + DataShareAbsResultSet dataShareAbsResultSet; + int offset = 1; + auto result = dataShareAbsResultSet.GoTo(offset); + EXPECT_EQ(result, E_OK); + LOG_INFO("DataShareAbsResultSetTest GoToTest002::End"); +} + +/** +* @tc.name: IsEndedTest001 +* @tc.desc: test IsEnded function when GetRowCount return E_ERROR +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call IsEnded function when GetRowCount return E_ERROR and check the result +* @tc.experct: IsEnded failed and return E_ERROR +*/ +HWTEST_F(DataShareAbsResultSetTest, IsEndedTest001, TestSize.Level0) +{ + LOG_INFO("DataShareAbsResultSetTest IsEndedTest001::Start"); + MockDataShareAbsResultSet mockResultSet; + EXPECT_CALL(mockResultSet, GetRowCount(testing::_)) + .WillOnce(testing::Return(E_ERROR)); + bool test = true; + auto result = mockResultSet.IsEnded(test); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareAbsResultSetTest IsEndedTest001::End"); +} + +/** +* @tc.name: IsEndedTest002 +* @tc.desc: test IsEnded function +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call IsEnded function and check the result +* @tc.experct: IsEnded success and return E_OK +*/ +HWTEST_F(DataShareAbsResultSetTest, IsEndedTest002, TestSize.Level0) +{ + LOG_INFO("DataShareAbsResultSetTest IsEndedTest002::Start"); + DataShareAbsResultSet dataShareAbsResultSet; + bool test = true; + auto result = dataShareAbsResultSet.IsEnded(test); + EXPECT_EQ(result, E_OK); + LOG_INFO("DataShareAbsResultSetTest IsEndedTest002::End"); +} + +/** +* @tc.name: GetColumnCountTest001 +* @tc.desc: test GetColumnCount function when GetAllColumnNames return E_ERROR +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet2 object + 2.call GetColumnCount function when GetAllColumnNames return E_ERROR and check the result +* @tc.experct: GetColumnCount failed and return E_ERROR +*/ +HWTEST_F(DataShareAbsResultSetTest, GetColumnCountTest001, TestSize.Level0) +{ + LOG_INFO("DataShareAbsResultSetTest GetColumnCountTest001::Start"); + MockDataShareAbsResultSet2 mockResultSet; + int offset = -1; + mockResultSet.count_ = -1; + EXPECT_CALL(mockResultSet, GetAllColumnNames(testing::_)) + .WillOnce(testing::Return(E_ERROR)); + auto result = mockResultSet.GetColumnCount(offset); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareAbsResultSetTest GetColumnCountTest001::End"); +} + +/** +* @tc.name: GetColumnName001 +* @tc.desc: test GetColumnName function when GetColumnCount return E_ERROR +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GetColumnName function when GetColumnCount return E_ERROR and check the result +* @tc.experct: GetColumnName failed and return E_ERROR +*/ +HWTEST_F(DataShareAbsResultSetTest, GetColumnName001, TestSize.Level0) +{ + LOG_INFO("DataShareAbsResultSetTest GetColumnName001::Start"); + MockDataShareAbsResultSet mockResultSet; + int columnIndex = 1; + std::string columnName = "test"; + EXPECT_CALL(mockResultSet, GetColumnCount(testing::_)) + .WillOnce(testing::Return(E_ERROR)); + auto result = mockResultSet.GetColumnName(columnIndex, columnName); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareAbsResultSetTest GetColumnName001::End"); +} + +/** +* @tc.name: GetColumnName002 +* @tc.desc: test GetColumnName function when columnIndex >= 0 +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GetColumnName function when columnIndex >= 0 and check the result +* @tc.experct: GetColumnName failed and return E_INVALID_COLUMN_INDEX +*/ +HWTEST_F(DataShareAbsResultSetTest, GetColumnName002, TestSize.Level0) +{ + LOG_INFO("DataShareAbsResultSetTest MarshallingTest002::Start"); + DataShareAbsResultSet dataShareAbsResultSet; + int columnIndex = 1; + std::string columnName = "test"; + auto result = dataShareAbsResultSet.GetColumnName(columnIndex, columnName); + EXPECT_EQ(result, E_INVALID_COLUMN_INDEX); + LOG_INFO("DataShareAbsResultSetTest MarshallingTest002::End"); +} + +/** +* @tc.name: GetColumnName003 +* @tc.desc: test GetColumnName function when columnIndex < 0 +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a MockDataShareAbsResultSet object + 2.call GetColumnName function when columnIndex < 0 and check the result +* @tc.experct: GetColumnName failed and return E_INVALID_COLUMN_INDEX +*/ +HWTEST_F(DataShareAbsResultSetTest, GetColumnName003, TestSize.Level0) +{ + LOG_INFO("DataShareAbsResultSetTest MarshallingTest002::Start"); + DataShareAbsResultSet dataShareAbsResultSet; + int columnIndex = -1; + std::string columnName = "test"; + auto result = dataShareAbsResultSet.GetColumnName(columnIndex, columnName); + EXPECT_EQ(result, E_INVALID_COLUMN_INDEX); + LOG_INFO("DataShareAbsResultSetTest MarshallingTest002::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/unittest/native/common/src/datashare_block_writer_impl_test.cpp b/data_share/test/unittest/native/common/src/datashare_block_writer_impl_test.cpp new file mode 100644 index 00000000..3b206690 --- /dev/null +++ b/data_share/test/unittest/native/common/src/datashare_block_writer_impl_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 "datashare_block_writer_impl.h" +#include "datashare_log.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +class DataShareBlockWriterImplTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +/** +* @tc.name: AllocRowTest001 +* @tc.desc: test AllocRow function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call AllocRow function and check the result +* @tc.experct: AllocRow failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, AllocRowTest001, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest AllocRowTest001::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + auto result = dataShareBlockWriterImpl.AllocRow(); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest AllocRowTest001::End"); +} + +/** +* @tc.name: WriteTest001 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest001, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest001::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + auto result = dataShareBlockWriterImpl.Write(column); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest001::End"); +} + +/** +* @tc.name: WriteTest002 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest002, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest002::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + int64_t value = 1; + auto result = dataShareBlockWriterImpl.Write(column, value); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest002::End"); +} + +/** +* @tc.name: WriteTest003 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest003, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest003::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + double value = 1; + auto result = dataShareBlockWriterImpl.Write(column, value); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest003::End"); +} + +/** +* @tc.name: WriteTest004 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest004, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest004::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + uint8_t value[3] = {1}; + size_t size = 1; + auto result = dataShareBlockWriterImpl.Write(column, value, size); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest004::End"); +} + +/** +* @tc.name: WriteTest005 +* @tc.desc: test Write function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call Write function and check the result +* @tc.experct: Write failed and reutrn E_ERROR +*/ +HWTEST_F(DataShareBlockWriterImplTest, WriteTest005, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest WriteTest005::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t column = 1; + const char* value = "test"; + size_t sizeIncludingNull = 1; + auto result = dataShareBlockWriterImpl.Write(column, value, sizeIncludingNull); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareBlockWriterImplTest WriteTest005::End"); +} + +/** +* @tc.name: GetCurrentRowIndexTest001 +* @tc.desc: test GetCurrentRowIndex function when shareBlock_ = nullptr +* @tc.type: FUNC +* @tc.require:issueIC413F +* @tc.precon: None +* @tc.step: + 1.Create a DataShareBlockWriterImpl object and shareBlock_ = nullptr + 2.call GetCurrentRowIndex function and check the result +* @tc.experct: GetCurrentRowIndex failed and reutrn false +*/ +HWTEST_F(DataShareBlockWriterImplTest, GetCurrentRowIndexTest001, TestSize.Level0) +{ + LOG_INFO("DataShareBlockWriterImplTest GetCurrentRowIndexTest001::Start"); + DataShareBlockWriterImpl dataShareBlockWriterImpl; + dataShareBlockWriterImpl.shareBlock_ = nullptr; + uint32_t rowIndex = 1; + auto result = dataShareBlockWriterImpl.GetCurrentRowIndex(rowIndex); + EXPECT_EQ(result, false); + LOG_INFO("DataShareBlockWriterImplTest GetCurrentRowIndexTest001::End"); +} + +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/unittest/native/common/src/datashare_result_set_test.cpp b/data_share/test/unittest/native/common/src/datashare_result_set_test.cpp new file mode 100644 index 00000000..6f767dfa --- /dev/null +++ b/data_share/test/unittest/native/common/src/datashare_result_set_test.cpp @@ -0,0 +1,169 @@ +/* + * 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 "datashare_errno.h" +#include "datashare_itypes_utils.h" +#include "datashare_log.h" +#include "datashare_abs_result_set.h" +#include "datashare_result_set.h" +#include "ikvstore_data_service.h" +#include "ipc_types.h" +#include "ishared_result_set_stub.h" +#include "itypes_util.h" +#include "message_parcel.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +class DatashareResultSetTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +/** +* @tc.name: GetDataTypeTest001 +* @tc.desc: test GetDataType function when sharedBlock_ is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object and sharedBlock_ is nullptr + 2.call GetDataType function and check the result +* @tc.experct: GetDataType failed and return E_ERROR +*/ +HWTEST_F(DatashareResultSetTest, GetDataTypeTest001, TestSize.Level0) +{ + LOG_INFO("DatashareResultSetTest GetDataTypeTest001::Start"); + DataShareResultSet dataShareResultSet; + int columnIndex = 1; + DataShare::DataType dataType; + auto result = dataShareResultSet.GetDataType(columnIndex, dataType); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DatashareResultSetTest GetDataTypeTest001::End"); +} + +/** +* @tc.name: CheckStateTest001 +* @tc.desc: test CheckState function when columnIndex >= 0 +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object + 2.call CheckState function when columnIndex >= 0 and check the result +* @tc.experct: CheckState failed and return E_INVALID_COLUMN_INDEX +*/ +HWTEST_F(DatashareResultSetTest, CheckStateTest001, TestSize.Level0) +{ + LOG_INFO("DatashareResultSetTest CheckStateTest001::Start"); + DataShareResultSet dataShareResultSet; + int columnIndex = 1; + auto result = dataShareResultSet.CheckState(columnIndex); + EXPECT_EQ(result, E_INVALID_COLUMN_INDEX); + LOG_INFO("DatashareResultSetTest CheckStateTest001::End"); +} + +/** +* @tc.name: CheckStateTest002 +* @tc.desc: test CheckState function when columnIndex < 0 +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object + 2.call CheckState function when columnIndex < 0 and check the result +* @tc.experct: CheckState failed and return E_INVALID_COLUMN_INDEX +*/ +HWTEST_F(DatashareResultSetTest, CheckStateTest002, TestSize.Level0) +{ + LOG_INFO("DatashareResultSetTest CheckState002::Start"); + DataShareResultSet dataShareResultSet; + int columnIndex = -1; + auto result = dataShareResultSet.CheckState(columnIndex); + EXPECT_EQ(result, E_INVALID_COLUMN_INDEX); + LOG_INFO("DatashareResultSetTest CheckState002::End"); +} + +/** +* @tc.name: MarshalTest001 +* @tc.desc: test Marshal function when resultset = nullptr +* @tc.type: FUNC +* @tc.require: issueICCAXH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object when resultset = nullptr + 2.call Marshal function and check the result +* @tc.experct: Marshal failed and return false +*/ +HWTEST_F(DatashareResultSetTest, MarshalTest001, TestSize.Level0) +{ + LOG_INFO("DatashareResultSetTest MarshalTest001::Start"); + DataShareResultSet dataShareResultSet; + std::shared_ptr resultset = nullptr; + MessageParcel parcel; + auto result = dataShareResultSet.Marshal(resultset, parcel); + EXPECT_FALSE(result); + LOG_INFO("DatashareResultSetTest MarshalTest001::End"); +} + +/** +* @tc.name: UnmarshalTest001 +* @tc.desc: test Unmarshal function +* @tc.type: FUNC +* @tc.require: issueICCAXH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object + 2.call Unmarshal function and check the result +* @tc.experct: Unmarshal failed and return nullptr +*/ +HWTEST_F(DatashareResultSetTest, UnmarshalTest001, TestSize.Level0) +{ + LOG_INFO("DatashareResultSetTest UnmarshalTest001::Start"); + DataShareResultSet dataShareResultSet; + MessageParcel parcel; + auto result = dataShareResultSet.Unmarshal(parcel); + EXPECT_EQ(result, nullptr); + LOG_INFO("DatashareResultSetTest UnmarshalTest001::End"); +} + +/** +* @tc.name: MarshallingTest001 +* @tc.desc: test Marshalling function when sharedBlock_ is nullptr +* @tc.type: FUNC +* @tc.require: issueIC9GIH +* @tc.precon: None +* @tc.step: + 1.Creat a DataShareResultSet object + 2.call Marshalling function when sharedBlock_ is nullptr and check the result +* @tc.experct: Marshalling failed and return false +*/ +HWTEST_F(DatashareResultSetTest, MarshallingTest001, TestSize.Level0) +{ + LOG_INFO("DatashareResultSetTest MarshallingTest001::Start"); + DataShareResultSet dataShareResultSet; + MessageParcel parcel; + auto result = dataShareResultSet.Marshalling(parcel); + EXPECT_FALSE(result); + LOG_INFO("DatashareResultSetTest MarshallingTest001::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/unittest/native/common/src/datashare_valuebucket_convert_test.cpp b/data_share/test/unittest/native/common/src/datashare_valuebucket_convert_test.cpp new file mode 100644 index 00000000..ade97386 --- /dev/null +++ b/data_share/test/unittest/native/common/src/datashare_valuebucket_convert_test.cpp @@ -0,0 +1,50 @@ +/* + * 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 +#include +#include "datashare_valuebucket_convert.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +class ValueProxyTest : public testing::Test { +}; +HWTEST_F(ValueProxyTest, VBucketsDataShare2Normal, TestSize.Level0) +{ + using DataShareBucket = OHOS::DataShare::DataShareValuesBucket; + DataShareBucket valuesBucket1; + DataShareBucket valuesBucket2; + valuesBucket1.Put("phoneNumber", 20.07); + valuesBucket1.Put("name", "dataShareTest003"); + valuesBucket2.Put("age", 1001); + std::vector VBuckets = {valuesBucket1, valuesBucket2}; + DataShareObserver::ChangeInfo::VBuckets extends; + extends = ValueProxy::Convert(std::move(VBuckets)); + ASSERT_EQ(extends.size(), 2); +} +HWTEST_F(ValueProxyTest, VBucketsNormal2DataShare, TestSize.Level0) +{ + using DataShareBucket = OHOS::DataShare::DataShareValuesBucket; + std::vector VBuckets; + DataShareObserver::ChangeInfo::VBuckets extends = { + {{"phoneNumber", 20.07}, {"name", "dataShareTest003"}}, + {{"age", 1001}} + }; + VBuckets = ValueProxy::Convert(std::move(extends)); + ASSERT_EQ(VBuckets.size(), 2); +} +} // namespace DataShare +} \ No newline at end of file diff --git a/data_share/test/unittest/native/common/src/ishared_result_set_stub_test.cpp b/data_share/test/unittest/native/common/src/ishared_result_set_stub_test.cpp new file mode 100644 index 00000000..8a5661d4 --- /dev/null +++ b/data_share/test/unittest/native/common/src/ishared_result_set_stub_test.cpp @@ -0,0 +1,276 @@ +/* + * 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 "datashare_errno.h" +#include "datashare_itypes_utils.h" +#include "datashare_log.h" +#include "datashare_abs_result_set.h" +#include "datashare_result_set.h" +#include "ikvstore_data_service.h" +#include "ipc_types.h" +#include "ishared_result_set_stub.h" +#include "itypes_util.h" +#include "message_parcel.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +class IsharedResultSetStubTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +class ResultSetBridgeTest : public OHOS::DataShare::ResultSetBridge { +public: + int GetAllColumnNames(std::vector &columnNames) override + { + return 0; + } + + int GetRowCount(int32_t &count) override + { + return 0; + } + + int OnGo(int32_t startRowIndex, int32_t targetRowIndex, Writer &writer) override + { + return 0; + } +}; + +/** +* @tc.name: CreateStubTestTest001 +* @tc.desc: test CreateStub function when resuletset_ = nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and resuletset_ = nullptr + 2.call CreateStub function and check the result +* @tc.experct: CreateStub failed and reutrn nullptr +*/ +HWTEST_F(IsharedResultSetStubTest, CreateStubTest001, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest CreateStubTest001::Start"); + std::shared_ptr resultset; + MessageParcel parcel; + ISharedResultSetStub stub(resultset); + auto result = stub.CreateStub(resultset, parcel); + EXPECT_EQ(result, nullptr); + LOG_INFO("IsharedResultSetStubTest CreateStubTest001::End"); +} + +/** +* @tc.name: CreateStubTestTest002 +* @tc.desc: test CreateStub function when resuletset_ is not nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and resuletset_ is not nullptr + 2.call CreateStub function and check the result +* @tc.experct: CreateStub succees and not reutrn nullptr +*/ +HWTEST_F(IsharedResultSetStubTest, CreateStubTestTest002, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest CreateStubTestTest002::Start"); + std::shared_ptr resultset = std::make_shared(); + MessageParcel parcel; + ISharedResultSetStub stub(resultset); + auto result = stub.CreateStub(resultset, parcel); + EXPECT_NE(result, nullptr); + LOG_INFO("IsharedResultSetStubTest CreateStubTestTest002::End"); +} + +/** +* @tc.name: OnRemoteRequestTest001 +* @tc.desc: test OnRemoteRequest function when resuletset_ = nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and resuletset_ = nullptr + 2.call OnRemoteRequest function and check the result +* @tc.experct: OnRemoteRequest failed and reutrn INVALID_FD +*/ +HWTEST_F(IsharedResultSetStubTest, OnRemoteRequestTest001, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest OnRemoteRequestTest001::Start"); + std::shared_ptr resultset; + ISharedResultSetStub stub(resultset); + uint32_t code = 0; + MessageParcel data; + MessageParcel parcel; + MessageOption option; + auto result = stub.OnRemoteRequest(code, data, parcel, option); + EXPECT_EQ(result, INVALID_FD); + LOG_INFO("IsharedResultSetStubTest OnRemoteRequestTest001::End"); +} + +/** +* @tc.name: HandleGetRowCountRequestTest001 +* @tc.desc: test HandleGetRowCountRequest function when bridge = nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is nullptr + 2.call HandleGetRowCountRequest function and check the result +* @tc.experct: HandleGetRowCountRequest success and write E_ERROR into reply +*/ +HWTEST_F(IsharedResultSetStubTest, HandleGetRowCountRequestTest001, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest HandleGetRowCountRequestTest001::Start"); + std::shared_ptr resultset = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleGetRowCountRequest(data, reply); + EXPECT_EQ(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("IsharedResultSetStubTest HandleGetRowCountRequestTest001::End"); +} + +/** +* @tc.name: HandleGetRowCountRequestTest002 +* @tc.desc: test HandleGetRowCountRequest function when bridge is not nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is not nullptr + 2.call HandleGetRowCountRequest function and check the result +* @tc.experct: HandleGetRowCountRequest success and write count into reply +*/ +HWTEST_F(IsharedResultSetStubTest, HandleGetRowCountRequestTest002, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest HandleGetRowCountRequestTest002::Start"); + std::shared_ptr resultset = std::make_shared(); + resultset->bridge_ = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleGetRowCountRequest(data, reply); + EXPECT_NE(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("IsharedResultSetStubTest HandleGetRowCountRequestTest002::End"); +} + +/** +* @tc.name: HandleGetAllColumnNamesRequestTest001 +* @tc.desc: test HandleGetAllColumnNamesRequest function when bridge is nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is nullptr + 2.call HandleGetAllColumnNamesRequest function and check the result +* @tc.experct: HandleGetAllColumnNamesRequest success and write E_ERROR into reply +*/ +HWTEST_F(IsharedResultSetStubTest, HandleGetAllColumnNamesRequestTest001, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest HandleGetAllColumnNamesRequestTest001::Start"); + std::shared_ptr resultset = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleGetAllColumnNamesRequest(data, reply); + EXPECT_EQ(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("IsharedResultSetStubTest HandleGetAllColumnNamesRequestTest001::End"); +} + +/** +* @tc.name: HandleGetAllColumnNamesRequestTest002 +* @tc.desc: test HandleGetAllColumnNamesRequest function when bridge is not nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is not nullptr + 2.call HandleGetAllColumnNamesRequest function and check the result +* @tc.experct: HandleGetAllColumnNamesRequest success and write count into reply +*/ +HWTEST_F(IsharedResultSetStubTest, HandleGetAllColumnNamesRequestTest002, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest HandleGetAllColumnNamesRequestTest002::Start"); + std::shared_ptr resultset = std::make_shared(); + resultset->bridge_ = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleGetAllColumnNamesRequest(data, reply); + EXPECT_NE(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("IsharedResultSetStubTest HandleGetAllColumnNamesRequestTest002::End"); +} + +/** +* @tc.name: HandleOnGoRequestTest001 +* @tc.desc: test HandleOnGoRequest function when bridge is nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is nullptr + 2.call HandleOnGoRequest function and check the result +* @tc.experct: HandleOnGoRequest success and write -1 into reply +*/ +HWTEST_F(IsharedResultSetStubTest, HandleOnGoRequestTest001, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest HandleOnGoRequestTest001::Start"); + std::shared_ptr resultset = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleOnGoRequest(data, reply); + EXPECT_EQ(reply.ReadInt32(), -1); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("IsharedResultSetStubTest HandleOnGoRequestTest001::End"); +} + +/** +* @tc.name: HandleOnGoRequestTest002 +* @tc.desc: test HandleOnGoRequest function when bridge is not nullptr +* @tc.type: FUNC +* @tc.require: issueIC7OBM +* @tc.precon: None +* @tc.step: + 1.Creat a ISharedResultSetStub object and bridge is not nullptr + 2.call HandleOnGoRequest function and check the result +* @tc.experct: HandleOnGoRequest success and write count into reply +*/ +HWTEST_F(IsharedResultSetStubTest, HandleOnGoRequestTest002, TestSize.Level0) +{ + LOG_INFO("IsharedResultSetStubTest HandleOnGoRequestTest002::Start"); + std::shared_ptr resultset = std::make_shared(); + resultset->bridge_ = std::make_shared(); + MessageParcel data; + MessageParcel reply; + ISharedResultSetStub stub(resultset); + auto result = stub.HandleOnGoRequest(data, reply); + EXPECT_NE(reply.ReadInt32(), E_ERROR); + EXPECT_EQ(result, NO_ERROR); + LOG_INFO("IsharedResultSetStubTest HandleOnGoRequestTest002::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/unittest/native/consumer/BUILD.gn b/data_share/test/unittest/native/consumer/BUILD.gn new file mode 100644 index 00000000..076d51e4 --- /dev/null +++ b/data_share/test/unittest/native/consumer/BUILD.gn @@ -0,0 +1,275 @@ +# 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/distributeddatamgr/data_share/datashare.gni") + +group("unittest") { + testonly = true + deps = [] + + deps += [ + ":DataShareHelperImplTest", + ":DataShareHelperTest", + ":DataShareProxyTest", + ":DataShareConnectionTest", + ] +} + +config("permission_config") { + visibility = [ ":*" ] + include_dirs = [ + "${datashare_common_native_path}/include", + "${datashare_native_permission_path}/include", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } +} + +ohos_unittest("DataShareConnectionTest") { + module_out_path = "data_share/data_share/native/consumer" + + include_dirs = [ + "${datashare_innerapi_path}/consumer/include", + "${datashare_native_consumer_path}/controller/common", + "${datashare_native_consumer_path}/controller/provider/include", + "${datashare_native_consumer_path}/controller/service/include", + "${datashare_native_consumer_path}/include", + "${datashare_innerapi_path}/common/include", + "${datashare_native_proxy_path}/include", + ] + + sources = + [ "${datashare_base_path}/test/unittest/native/consumer/src/datashare_connection_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_single", + "relational_store:rdb_data_ability_adapter", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + } +} + +ohos_unittest("DataShareHelperImplTest") { + module_out_path = "data_share/data_share/native/consumer" + + include_dirs = [ + "${datashare_native_consumer_path}/include", + "${datashare_common_native_path}/include", + "${datashare_innerapi_path}/consumer/include", + "${datashare_innerapi_path}/common/include", + "${datashare_innerapi_path}/provider/include", + "${datashare_native_consumer_path}/controller/provider/include", + "${datashare_native_consumer_path}/controller/common", + "${datashare_native_consumer_path}/controller/service/include", + "${datashare_native_proxy_path}/include", + ] + + sources = [ + "${datashare_common_native_path}/src/call_reporter.cpp", + "${datashare_common_native_path}/src/datashare_abs_result_set.cpp", + "${datashare_common_native_path}/src/datashare_itypes_utils.cpp", + "${datashare_common_native_path}/src/datashare_result_set.cpp", + "${datashare_common_native_path}/src/datashare_string_utils.cpp", + "${datashare_common_native_path}/src/datashare_template.cpp", + "${datashare_common_native_path}/src/datashare_uri_utils.cpp", + "${datashare_common_native_path}/src/ikvstore_data_service.cpp", + "${datashare_common_native_path}/src/ishared_result_set.cpp", + "${datashare_common_native_path}/src/ishared_result_set_proxy.cpp", + "${datashare_native_consumer_path}/controller/provider/src/ext_special_controller.cpp", + "${datashare_native_consumer_path}/controller/service/src/general_controller_service_impl.cpp", + "${datashare_native_consumer_path}/controller/service/src/persistent_data_controller.cpp", + "${datashare_native_consumer_path}/controller/service/src/published_data_controller.cpp", + "${datashare_native_consumer_path}/src/datashare_connection.cpp", + "${datashare_native_consumer_path}/src/datashare_helper.cpp", + "${datashare_native_consumer_path}/src/datashare_helper_impl.cpp", + "${datashare_native_consumer_path}/src/datashare_proxy.cpp", + "${datashare_native_proxy_path}/src/ams_mgr_proxy.cpp", + "${datashare_native_proxy_path}/src/data_proxy_observer_stub.cpp", + "${datashare_native_proxy_path}/src/data_share_manager_impl.cpp", + "${datashare_native_proxy_path}/src/data_share_service_proxy.cpp", + "${datashare_native_proxy_path}/src/idata_share_client_death_observer.cpp", + "${datashare_native_proxy_path}/src/published_data_subscriber_manager.cpp", + "${datashare_native_proxy_path}/src/rdb_subscriber_manager.cpp", + "${datashare_native_proxy_path}/src/proxy_data_subscriber_manager.cpp", + "${datashare_base_path}/test/unittest/native/consumer/src/datashare_helper_impl_test.cpp", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "googletest:gmock_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "ipc:rpc", + "kv_store:distributeddata_inner", + "relational_store:native_appdatafwk", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DataShareHelperTest") { + module_out_path = "data_share/data_share/native/consumer" + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "${datashare_base_path}/cfi_blocklist.txt" + } + + include_dirs = [ + "${datashare_base_path}/frameworks/native/common/include/", + "${datashare_base_path}/test/unittest/native/consumer/include/", + ] + + sources = [ "${datashare_base_path}/test/unittest/native/consumer/src/datashare_helper_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:app_context", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "googletest:gmock_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_single", + "ipc:rpc", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("DataShareProxyTest") { + module_out_path = "data_share/data_share/native/consumer" + + include_dirs = [ + "${datashare_innerapi_path}/consumer/include", + "${datashare_native_consumer_path}/controller/common", + "${datashare_native_consumer_path}/controller/provider/include", + "${datashare_native_consumer_path}/controller/service/include", + "${datashare_native_consumer_path}/include", + "${datashare_innerapi_path}/common/include", + "${datashare_native_proxy_path}/include", + ] + + sources = [ "${datashare_base_path}/test/unittest/native/consumer/src/datashare_proxy_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_single", + "relational_store:rdb_data_ability_adapter", + "samgr:samgr_proxy", + ] + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + } +} \ No newline at end of file diff --git a/data_share/test/unittest/native/consumer/include/ikvstore_data_service_mock.h b/data_share/test/unittest/native/consumer/include/ikvstore_data_service_mock.h new file mode 100644 index 00000000..22eb89f4 --- /dev/null +++ b/data_share/test/unittest/native/consumer/include/ikvstore_data_service_mock.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 IKVSTORE_DATA_SERVICE_MOCK_H +#define IKVSTORE_DATA_SERVICE_MOCK_H + +#include +#include "gmock/gmock.h" +#include "ikvstore_data_service.h" + +namespace OHOS { +namespace DataShare { +class MockDataShareKvServiceProxy : public DataShareKvServiceProxy { +public: + explicit MockDataShareKvServiceProxy(const sptr &impl) + : DataShareKvServiceProxy(impl) {} + ~MockDataShareKvServiceProxy() = default; + MOCK_METHOD(sptr, GetFeatureInterface, (const std::string &name), (override)); + MOCK_METHOD(uint32_t, RegisterClientDeathObserver, (const std::string &appId, sptr observer), + (override)); +}; +} +} +#endif // IKVSTORE_DATA_SERVICE_MOCK_H \ No newline at end of file diff --git a/data_share/test/unittest/native/consumer/src/datashare_connection_test.cpp b/data_share/test/unittest/native/consumer/src/datashare_connection_test.cpp new file mode 100644 index 00000000..b1e839b2 --- /dev/null +++ b/data_share/test/unittest/native/consumer/src/datashare_connection_test.cpp @@ -0,0 +1,279 @@ +/* + * 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 "datashare_connection.h" + +#include + +#include "accesstoken_kit.h" +#include "data_ability_observer_interface.h" +#include "datashare_errno.h" +#include "datashare_helper.h" +#include "datashare_log.h" +#include "datashare_proxy.h" +#include "extension_manager_proxy.h" +#include "general_controller.h" +#include "general_controller_provider_impl.h" +#include "general_controller_service_impl.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::AAFwk; +class DataShareConnectionTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + bool UrisEqual(std::list uri1, std::list uri2) + { + if (uri1.size() != uri2.size()) { + return false; + } + auto cmp = [](const Uri &first, const Uri &second) { + return first.ToString() < second.ToString(); + }; + uri1.sort(cmp); + uri2.sort(cmp); + auto it1 = uri1.begin(); + auto it2 = uri2.begin(); + for (; it1 != uri1.end() && it2 != uri2.end(); it1++, it2++) { + if (!it1->Equals(*it2)) { + return false; + } + } + return true; + } +}; + +class RemoteObjectTest : public IRemoteObject { +public: + explicit RemoteObjectTest(std::u16string descriptor) : IRemoteObject(descriptor) {} + ~RemoteObjectTest() {} + + int32_t GetObjectRefCount() + { + return 0; + } + int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + return 0; + } + bool AddDeathRecipient(const sptr &recipient) + { + return true; + } + bool RemoveDeathRecipient(const sptr &recipient) + { + return true; + } + int Dump(int fd, const std::vector &args) + { + return 0; + } +}; + +class IDataAbilityObserverTest : public DataAbilityObserverStub { +public: + explicit IDataAbilityObserverTest(std::string uri) {uri_ = uri;} + ~IDataAbilityObserverTest() + {} + + void OnChange() + { + GTEST_LOG_(INFO) << "OnChange enter"; + } + std::string uri_; +}; + +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::string DATA_SHARE_URI1 = "datashare:///com.acts.datasharetest1"; + +void DataShareConnectionTest::SetUpTestCase(void) {} +void DataShareConnectionTest::TearDownTestCase(void) {} +void DataShareConnectionTest::SetUp(void) {} +void DataShareConnectionTest::TearDown(void) {} + +/** +* @tc.name: DataShareConnection_UpdateObserverExtsProviderMap_Test_001 +* @tc.desc: test UpdateObserverExtsProviderMap normal func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_UpdateObserverExtsProviderMap_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareConnection_UpdateObserverExtsProviderMap_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // insert data + EXPECT_TRUE(connection->observerExtsProvider_.Empty()); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI); + ASSERT_NE(dataObserver, nullptr); + connection->UpdateObserverExtsProviderMap(uri, dataObserver, true); + + Uri uri1(DATA_SHARE_URI1); + sptr dataObserver1 = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI1); + ASSERT_NE(dataObserver1, nullptr); + connection->UpdateObserverExtsProviderMap(uri1, dataObserver1, true); + + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 2); + connection = nullptr; + + LOG_INFO("DataShareConnection_UpdateObserverExtsProviderMap_Test_001::End"); +} + +/** +* @tc.name: DataShareConnection_DeleteObserverExtsProviderMap_001 +* @tc.desc: test DeleteObserverExtsProviderMap default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_DeleteObserverExtsProviderMap_001, TestSize.Level0) +{ + LOG_INFO("DataShareConnection_DeleteObserverExtsProviderMap_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // insert data + EXPECT_TRUE(connection->observerExtsProvider_.Empty()); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI); + connection->UpdateObserverExtsProviderMap(uri, dataObserver, true); + + Uri uri1(DATA_SHARE_URI1); + sptr dataObserver1 = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI1); + connection->UpdateObserverExtsProviderMap(uri1, dataObserver1, true); + + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 2); + + // delete data that uri can match observer + connection->DeleteObserverExtsProviderMap(uri1, dataObserver1); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 1); + + // delete data that uri can not match observer + connection->DeleteObserverExtsProviderMap(uri1, dataObserver); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 1); + connection = nullptr; + + LOG_INFO("DataShareConnection_DeleteObserverExtsProviderMap_001::End"); +} + +/** +* @tc.name: DataShareConnection_ReRegisterObserverExtProvider_Test_001 +* @tc.desc: test ReRegisterObserverExtProvider default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_ReRegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareConnection_ReRegisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + connection->dataShareProxy_ = tokenProxy; + + // insert data + EXPECT_TRUE(connection->observerExtsProvider_.Empty()); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI); + connection->UpdateObserverExtsProviderMap(uri, dataObserver, true); + + Uri uri1(DATA_SHARE_URI1); + sptr dataObserver1 = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI1); + connection->UpdateObserverExtsProviderMap(uri1, dataObserver1, true); + + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 2); + + // test ReRegister func + connection->ReRegisterObserverExtProvider(); + // reRegister success, update observer map + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + connection = nullptr; + + LOG_INFO("DataShareConnection_ReRegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareConnection_OnAbilityConnectDone_Test_001 +* @tc.desc: test ReRegisterObserverExtProvider default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareConnectionTest, DataShareConnection_OnAbilityConnectDone_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareConnection_OnAbilityConnectDone_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + connection->dataShareProxy_ = tokenProxy; + + // insert data + EXPECT_TRUE(connection->observerExtsProvider_.Empty()); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI); + connection->UpdateObserverExtsProviderMap(uri, dataObserver, true); + + Uri uri1(DATA_SHARE_URI1); + sptr dataObserver1 = new (std::nothrow) IDataAbilityObserverTest(DATA_SHARE_URI1); + connection->UpdateObserverExtsProviderMap(uri1, dataObserver1, true); + + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + EXPECT_EQ(connection->observerExtsProvider_.Size(), 2); + + // test ReRegister func + connection->isReconnect_.store(true); + std::string deviceId = "deviceId"; + std::string bundleName = "bundleName"; + std::string abilityName = "abilityName"; + AppExecFwk::ElementName element(deviceId, bundleName, abilityName); + int resultCode = 0; + connection->OnAbilityConnectDone(element, token, resultCode); + + // reRegister success, update observer map + EXPECT_FALSE(connection->observerExtsProvider_.Empty()); + connection = nullptr; + + LOG_INFO("DataShareConnection_OnAbilityConnectDone_Test_001::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/unittest/native/consumer/src/datashare_helper_impl_test.cpp b/data_share/test/unittest/native/consumer/src/datashare_helper_impl_test.cpp new file mode 100644 index 00000000..9b7a555f --- /dev/null +++ b/data_share/test/unittest/native/consumer/src/datashare_helper_impl_test.cpp @@ -0,0 +1,293 @@ +/* + * 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 +#include +#include "datashare_helper_impl.h" +#include "datashare_log.h" +#include "gmock/gmock.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; + +class MockGeneralController : public GeneralController { +public: + MOCK_METHOD(int, Insert, (const Uri &uri, const DataShareValuesBucket &value), (override)); + MOCK_METHOD(int, Update, + (const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value), (override)); + MOCK_METHOD(int, Delete, (const Uri &uri, const DataSharePredicates &predicates), (override)); + MOCK_METHOD((std::shared_ptr), Query, + (const Uri &uri, const DataSharePredicates &predicates, (std::vector & columns), + DatashareBusinessError &businessError, DataShareOption &option), (override)); + MOCK_METHOD( + int, RegisterObserver, (const Uri &uri, const sptr &dataObserver), (override)); + MOCK_METHOD(int32_t, UnregisterObserver, (const Uri &uri, const sptr &dataObserver), + (override)); + MOCK_METHOD(void, NotifyChange, (const Uri &uri), (override)); + MOCK_METHOD( + int, RegisterObserverExtProvider, (const Uri &uri, const sptr &dataObserver, + bool isDescendants), (override)); + MOCK_METHOD(int32_t, UnregisterObserverExtProvider, (const Uri &uri, + const sptr &dataObserver), (override)); + MOCK_METHOD(int32_t, NotifyChangeExtProvider, (const ChangeInfo &changeInfo), (override)); + MOCK_METHOD( + (std::pair), InsertEx, (const Uri &uri, const DataShareValuesBucket &value), (override)); + MOCK_METHOD((std::pair), UpdateEx, + (const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value), (override)); + MOCK_METHOD( + (std::pair), DeleteEx, (const Uri &uri, const DataSharePredicates &predicates), (override)); +}; + +class DataShareHelperImplTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static std::shared_ptr GetInstance(std::shared_ptr instance = nullptr); + static std::shared_ptr GetController( + std::shared_ptr instance = nullptr); +}; + +void DataShareHelperImplTest::SetUpTestCase(void) +{ + DataShareHelperImplTest::GetInstance(std::make_shared("datashare://datasharehelperimpl")); + EXPECT_NE(DataShareHelperImplTest::GetInstance(), nullptr); + DataShareHelperImplTest::GetController(std::make_shared()); + EXPECT_NE(DataShareHelperImplTest::GetController(), nullptr); + DataShareHelperImplTest::GetInstance()->generalCtl_ = DataShareHelperImplTest::GetController(); + EXPECT_NE(DataShareHelperImplTest::GetInstance()->generalCtl_, nullptr); + EXPECT_EQ(DataShareHelperImplTest::GetInstance()->extSpCtl_, nullptr); + DataShareHelperImplTest::GetInstance()->persistentDataCtl_ = nullptr; + DataShareHelperImplTest::GetInstance()->publishedDataCtl_ = nullptr; +} +void DataShareHelperImplTest::TearDownTestCase(void) +{ +} +void DataShareHelperImplTest::SetUp(void) +{ +} +void DataShareHelperImplTest::TearDown(void) +{ +} +std::shared_ptr DataShareHelperImplTest::GetInstance(std::shared_ptr instance) +{ + static std::shared_ptr helperInstance = nullptr; + if (instance != nullptr) { + helperInstance = instance; + } + return helperInstance; +} +std::shared_ptr DataShareHelperImplTest::GetController( + std::shared_ptr instance) +{ + static std::shared_ptr controllerInstance = nullptr; + if (instance != nullptr) { + controllerInstance = instance; + } + return controllerInstance; +} + +HWTEST_F(DataShareHelperImplTest, BatchUpdateTest001, TestSize.Level0) +{ + LOG_INFO("BatchUpdateTest001::Start"); + UpdateOperations operations; + std::vector results = {}; + int result = DataShareHelperImplTest::GetInstance()->BatchUpdate(operations, results); + EXPECT_EQ(result, DATA_SHARE_ERROR); + LOG_INFO("BatchUpdateTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, InsertExTest001, TestSize.Level0) +{ + LOG_INFO("InsertExTest001::Start"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataShareValuesBucket value; + DataShareHelperImplTest::GetInstance()->generalCtl_ = nullptr; + std::pair result = DataShareHelperImplTest::GetInstance()->InsertEx(uri, value); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + std::shared_ptr controller = DataShareHelperImplTest::GetController(); + DataShareHelperImplTest::GetInstance()->generalCtl_ = controller; + EXPECT_CALL(*controller, InsertEx(testing::_, testing::_)) + .WillOnce(testing::Return(std::make_pair(E_REGISTERED_REPEATED, 0))); + result = DataShareHelperImplTest::GetInstance()->InsertEx(uri, value); + EXPECT_EQ(result.first, E_REGISTERED_REPEATED); + EXPECT_EQ(result.second, 0); + LOG_INFO("InsertExTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, UpdateExTest001, TestSize.Level0) +{ + LOG_INFO("UpdateExTest001::Start"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataShareValuesBucket value; + DataSharePredicates predicates; + DataShareHelperImplTest::GetInstance()->generalCtl_ = nullptr; + std::pair result = DataShareHelperImplTest::GetInstance()->UpdateEx(uri, predicates, value); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + std::shared_ptr controller = DataShareHelperImplTest::GetController(); + DataShareHelperImplTest::GetInstance()->generalCtl_ = controller; + EXPECT_CALL(*controller, UpdateEx(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(std::make_pair(E_REGISTERED_REPEATED, 0))); + result = DataShareHelperImplTest::GetInstance()->UpdateEx(uri, predicates, value); + EXPECT_EQ(result.first, E_REGISTERED_REPEATED); + EXPECT_EQ(result.second, 0); + LOG_INFO("UpdateExTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, DeleteExTest001, TestSize.Level0) +{ + LOG_INFO("DeleteExTest001::Start"); + OHOS::Uri uri("datashare:///com.datasharehelperimpl.test"); + DataSharePredicates predicates; + DataShareHelperImplTest::GetInstance()->generalCtl_ = nullptr; + std::pair result = DataShareHelperImplTest::GetInstance()->DeleteEx(uri, predicates); + EXPECT_EQ(result.first, DATA_SHARE_ERROR); + EXPECT_EQ(result.second, 0); + std::shared_ptr controller = DataShareHelperImplTest::GetController(); + DataShareHelperImplTest::GetInstance()->generalCtl_ = controller; + EXPECT_CALL(*controller, DeleteEx(testing::_, testing::_)) + .WillOnce(testing::Return(std::make_pair(E_REGISTERED_REPEATED, 0))); + result = DataShareHelperImplTest::GetInstance()->DeleteEx(uri, predicates); + EXPECT_EQ(result.first, E_REGISTERED_REPEATED); + EXPECT_EQ(result.second, 0); + LOG_INFO("DeleteExTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, DelQueryTemplateTest001, TestSize.Level0) +{ + LOG_INFO("DelQueryTemplateTest001::Start"); + std::string uri("datashare:///com.datasharehelperimpl.test"); + int64_t subscriberId = 0; + int result = DataShareHelperImplTest::GetInstance()->DelQueryTemplate(uri, subscriberId); + EXPECT_EQ(result, DATA_SHARE_ERROR); + LOG_INFO("DelQueryTemplateTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, PublishTest001, TestSize.Level0) +{ + LOG_INFO("PublishTest001::Start"); + Data data; + std::string bundleName("datashare:///com.datasharehelperimpl.test"); + std::vector result = DataShareHelperImplTest::GetInstance()->Publish(data, bundleName); + EXPECT_EQ(result.size(), 0); + LOG_INFO("PublishTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, GetPublishedDataTest001, TestSize.Level0) +{ + LOG_INFO("GetPublishedDataTest001::Start"); + int resultCode = 0; + std::string bundleName("datashare:///com.datasharehelperimpl.test"); + Data result = DataShareHelperImplTest::GetInstance()->GetPublishedData(bundleName, resultCode); + EXPECT_EQ(result.version_, 0); + EXPECT_EQ(result.datas_.size(), 0); + LOG_INFO("GetPublishedDataTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, SubscribeRdbDataTest001, TestSize.Level0) +{ + LOG_INFO("SubscribeRdbDataTest001::Start"); + std::vector uris = {}; + TemplateId templateId; + std::function callback; + std::vector result = + DataShareHelperImplTest::GetInstance()->SubscribeRdbData(uris, templateId, callback); + EXPECT_EQ(result.size(), 0); + LOG_INFO("SubscribeRdbDataTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, UnsubscribeRdbDataTest001, TestSize.Level0) +{ + LOG_INFO("UnsubscribeRdbDataTest001::Start"); + std::vector uris = {}; + TemplateId templateId; + std::vector result = DataShareHelperImplTest::GetInstance()->UnsubscribeRdbData(uris, templateId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("UnsubscribeRdbDataTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, DisableRdbSubsTest001, TestSize.Level0) +{ + LOG_INFO("DisableRdbSubsTest001::Start"); + std::vector uris = {}; + TemplateId templateId; + std::vector result = DataShareHelperImplTest::GetInstance()->DisableRdbSubs(uris, templateId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("DisableRdbSubsTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, SubscribePublishedDataTest001, TestSize.Level0) +{ + LOG_INFO("SubscribePublishedDataTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 0; + std::function callback; + std::vector result = + DataShareHelperImplTest::GetInstance()->SubscribePublishedData(uris, subscriberId, callback); + EXPECT_EQ(result.size(), 0); + LOG_INFO("SubscribePublishedDataTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, UnsubscribePublishedDataTest001, TestSize.Level0) +{ + LOG_INFO("UnsubscribePublishedDataTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 0; + std::vector result = + DataShareHelperImplTest::GetInstance()->UnsubscribePublishedData(uris, subscriberId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("UnsubscribePublishedDataTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, EnablePubSubsTest001, TestSize.Level0) +{ + LOG_INFO("EnablePubSubsTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 0; + std::vector result = DataShareHelperImplTest::GetInstance()->EnablePubSubs(uris, subscriberId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("EnablePubSubsTest001::End"); +} + +HWTEST_F(DataShareHelperImplTest, DisablePubSubsTest001, TestSize.Level0) +{ + LOG_INFO("DisableRdbSubsTest001::Start"); + std::vector uris = {}; + int64_t subscriberId = 0; + std::vector result = DataShareHelperImplTest::GetInstance()->DisablePubSubs(uris, subscriberId); + EXPECT_EQ(result.size(), 0); + LOG_INFO("DisablePubSubsTest001::End"); +} + +/* +* @tc.desc: test UserDefineFunc with no extSpCtl_ +* @tc.require: Null +*/ +HWTEST_F(DataShareHelperImplTest, User_Define_func_No_ExtSpCtl_Test001, TestSize.Level0) +{ + LOG_INFO("User_Define_func_No_ExtSpCtl_Test001::Start"); + DataShareHelperImplTest::GetInstance()->extSpCtl_ = nullptr; + MessageParcel data; + MessageParcel reply; + MessageOption option; + auto result = DataShareHelperImplTest::GetInstance()->UserDefineFunc(data, reply, option); + EXPECT_EQ(result, DATA_SHARE_ERROR); + LOG_INFO("User_Define_func_No_ExtSpCtl_Test001::End"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/unittest/native/consumer/src/datashare_helper_test.cpp b/data_share/test/unittest/native/consumer/src/datashare_helper_test.cpp new file mode 100644 index 00000000..b01721c0 --- /dev/null +++ b/data_share/test/unittest/native/consumer/src/datashare_helper_test.cpp @@ -0,0 +1,227 @@ +/* + * 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 "datashare_helper.h" +#include "datashare_helper_impl.h" +#include "datashare_log.h" +#include "datashare_uri_utils.h" +#include "iservice_registry.h" +#include "ikvstore_data_service_mock.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; + +constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; +std::string NON_SILENT_ACCESS_URI = "datashare:///com.acts.datasharetest"; +std::string NON_SILENT_ACCESS_ERROR_URI = "datashare:///com.acts.test"; +constexpr int DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID = 1301; + +class DataShareHelperTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +void DataShareManagerImplHelper() +{ + auto helper = DataShareManagerImpl::GetInstance(); + helper->dataShareService_ = nullptr; + auto manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + auto remoteObject = manager->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); + sptr mockProxy = sptr + (new MockDataShareKvServiceProxy(remoteObject)); + EXPECT_CALL(*mockProxy, GetFeatureInterface(testing::_)) + .WillOnce(testing::Return(nullptr)); + helper->dataMgrService_ = (sptr)mockProxy; +} + +/** + * @tc.name: + * @tc.desc: test Creator function when options.isProxy_ = false and options.token_ = nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what options.isProxy_ = false and options.token_ = nullptr + 2.call Creator function and check the result + * @tc.experct: Creator failed and reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreatorTest001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreatorTest001::Start"); + std::string strUri = "testUri"; + CreateOptions options; + options.isProxy_ = false; + options.token_ = nullptr; + std::string bundleName = "testBundle"; + int waitTime = 1; + bool isSystem = true; + auto result = DataShareHelper::Creator(strUri, options, bundleName, waitTime, isSystem); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreatorTest001::End"); +} + +/** + * @tc.name: + * @tc.desc: test Creator function when options.isProxy_ = true and options.token_ = nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what options.isProxy_ = true and options.token_ = nullptr + 2.call Creator function and check the result + * @tc.experct: Creator failed and reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreatorTest002, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreatorTest002::Start"); + std::string strUri = "testUri"; + CreateOptions options; + options.isProxy_ = true; + options.token_ = nullptr; + std::string bundleName = "testBundle"; + int waitTime = 1; + bool isSystem = true; + auto result = DataShareHelper::Creator(strUri, options, bundleName, waitTime, isSystem); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreatorTest002::End"); +} + +/** + * @tc.name: + * @tc.desc: test Creator function when options.isProxy_ = true and options.token_ != nullptr + * @tc.type: FUNC + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what options.isProxy_ = true and options.token_ != nullptr + 2.call Creator function and check the result + * @tc.experct: Creator failed and not reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreatorTest004, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreatorTest004::Start"); + CreateOptions options; + options.isProxy_ = true; + + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + EXPECT_NE(saManager, nullptr); + auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID); + EXPECT_NE(remoteObj, nullptr); + options.token_ = remoteObj; + auto result = DataShareHelper::Creator(NON_SILENT_ACCESS_ERROR_URI, options); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreatorTest004::End"); +} + +/** + * @tc.name: + * @tc.desc: test CreateExtHelper function when Uri contains "appIndex=" + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object what Uri contains "appIndex=" + 2.call CreateExtHelper function and check the result + * @tc.experct: CreateExtHelper failed and reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreateExtHelper001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreateExtHelper001::Start"); + OHOS::Uri uri("datashareproxy://com.acts.ohos.data.datasharetest/test?appIndex=abcd"); + uri.query_ = ("appIndex=abcd"); + sptr token = nullptr; + int waitTime = 1000; + bool isSystem = false; + auto result = DataShareHelper::CreateExtHelper(uri, token, waitTime, isSystem); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreateExtHelper001::End"); +} + +/** + * @tc.name: SetSilentSwitch001 + * @tc.desc: test SetSilentSwitch function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object + 2.call SetSilentSwitch function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.experct: SetSilentSwitch failed and reutrn DATA_SHARE_ERROR + */ +HWTEST_F(DataShareHelperTest, SetSilentSwitch001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest SetSilentSwitch001::Start"); + DataShareManagerImplHelper(); + OHOS::Uri uri("datashareproxy://com.acts.ohos.data.datasharetest/test?appIndex=abcd"); + uri.query_ = ("appIndex=abcd"); + bool enable = false; + bool isSystem = false; + auto result = DataShareHelper::SetSilentSwitch(uri, enable, isSystem); + EXPECT_EQ(result, DATA_SHARE_ERROR); + LOG_INFO("DataShareHelperTest SetSilentSwitch001::End"); +} + +/** + * @tc.name: GetSilentProxyStatus001 + * @tc.desc: test GetSilentProxyStatus function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object + 2.call GetSilentProxyStatus function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.experct: GetSilentProxyStatus failed and reutrn E_ERROR + */ +HWTEST_F(DataShareHelperTest, GetSilentProxyStatus001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest GetSilentProxyStatus001::Start"); + DataShareManagerImplHelper(); + std::string uri = "datashareproxy://com.acts.ohos.data.datasharetest/test?appIndex=abcd"; + bool isSystem = false; + auto result = DataShareHelper::GetSilentProxyStatus(uri, isSystem); + EXPECT_EQ(result, E_ERROR); + LOG_INFO("DataShareHelperTest GetSilentProxyStatus001::End"); +} + +/** + * @tc.name: CreateServiceHelper001 + * @tc.desc: test CreateExtHelper function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.type: FUNC + * @tc.require:issueIC413F + * @tc.precon: None + * @tc.step: + 1.Create a DataShareHelper object + 2.call CreateServiceHelper function when DataShareManagerImpl::GetServiceProxy() == nullptr + * @tc.experct: CreateServiceHelper failed and reutrn nullptr + */ +HWTEST_F(DataShareHelperTest, CreateServiceHelper001, TestSize.Level0) +{ + LOG_INFO("DataShareHelperTest CreateServiceHelper001::Start"); + DataShareManagerImplHelper(); + std::string exuri = "testExuri"; + std::string bundleName = "bundleName"; + bool isSystem = false; + auto result = DataShareHelper::CreateServiceHelper(exuri, bundleName, isSystem); + EXPECT_EQ(result, nullptr); + LOG_INFO("DataShareHelperTest CreateServiceHelper001::End"); +} +} // namespace DataShare +} // namespace OHOS \ No newline at end of file diff --git a/data_share/test/unittest/native/consumer/src/datashare_proxy_test.cpp b/data_share/test/unittest/native/consumer/src/datashare_proxy_test.cpp new file mode 100644 index 00000000..5702a793 --- /dev/null +++ b/data_share/test/unittest/native/consumer/src/datashare_proxy_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 "datashare_proxy.h" + +#include + +#include "accesstoken_kit.h" +#include "data_ability_observer_interface.h" +#include "datashare_connection.h" +#include "datashare_errno.h" +#include "datashare_helper.h" +#include "datashare_log.h" +#include "extension_manager_proxy.h" +#include "general_controller.h" +#include "general_controller_provider_impl.h" +#include "general_controller_service_impl.h" + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::AAFwk; +class DataShareProxyTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +class RemoteObjectTest : public IRemoteObject { +public: + explicit RemoteObjectTest(std::u16string descriptor) : IRemoteObject(descriptor) {} + ~RemoteObjectTest() {} + + int32_t GetObjectRefCount() + { + return 0; + } + int SendRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) + { + return 0; + } + bool AddDeathRecipient(const sptr &recipient) + { + return true; + } + bool RemoveDeathRecipient(const sptr &recipient) + { + return true; + } + int Dump(int fd, const std::vector &args) + { + return 0; + } +}; + +class IDataAbilityObserverTest : public DataAbilityObserverStub { +public: + IDataAbilityObserverTest() {} + ~IDataAbilityObserverTest() + {} + + void OnChange() + { + GTEST_LOG_(INFO) << "OnChange enter"; + } +}; + +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; + +void DataShareProxyTest::SetUpTestCase(void) {} +void DataShareProxyTest::TearDownTestCase(void) {} +void DataShareProxyTest::SetUp(void) {} +void DataShareProxyTest::TearDown(void) {} + +/** +* @tc.name: DataShareProxy_RegisterObserverExtProvider_Test_001 +* @tc.desc: test RegisterObserverExtProvider default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareProxyTest, DataShareProxy_RegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareProxy_RegisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + + connection->dataShareProxy_ = tokenProxy; + ASSERT_NE(connection->dataShareProxy_, nullptr); + auto proxy = connection->GetDataShareProxy(uri, token); + ASSERT_NE(proxy, nullptr); + + // Observer not null + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + ASSERT_NE(dataObserver, nullptr); + // datashare_stub returns default 0(E_OK) + int ret = proxy->RegisterObserverExtProvider(uri, dataObserver, true, { false }); + EXPECT_EQ(ret, 0); + + LOG_INFO("DataShareProxy_RegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareProxy_UnregisterObserverExtProvider_Test_001 +* @tc.desc: test UnregisterObserverExtProvider default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareProxyTest, DataShareProxy_UnregisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareProxy_UnregisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + connection->dataShareProxy_ = tokenProxy; + auto proxy = connection->GetDataShareProxy(uri, token); + ASSERT_NE(proxy, nullptr); + + // observer not null + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + ASSERT_NE(dataObserver, nullptr); + // datashare_stub returns default 0(E_OK) + int ret = proxy->UnregisterObserverExtProvider(uri, dataObserver); + EXPECT_EQ(ret, 0); + + LOG_INFO("DataShareProxy_UnregisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareProxy_NotifyChangeExtProvider_Test_001 +* @tc.desc: test NotifyChangeExtProvider default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareProxyTest, DataShareProxy_NotifyChangeExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareProxy_NotifyChangeExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + std::u16string tokenString = u"OHOS.DataShare.IDataShare"; + sptr token = new (std::nothrow) RemoteObjectTest(tokenString); + ASSERT_NE(token, nullptr); + sptr connection = + new (std::nothrow) DataShare::DataShareConnection(uri, token); + ASSERT_NE(connection, nullptr); + + // get proxy not null + std::shared_ptr tokenProxy = std::make_shared(token); + ASSERT_NE(tokenProxy, nullptr); + connection->dataShareProxy_ = tokenProxy; + auto proxy = connection->GetDataShareProxy(uri, token); + ASSERT_NE(proxy, nullptr); + + ChangeInfo changeInfo = { ChangeInfo::ChangeType::INSERT, { uri } }; + // datashare_stub returns default 0(E_OK) + int ret = proxy->NotifyChangeExtProvider(changeInfo); + EXPECT_EQ(ret, 0); + + LOG_INFO("DataShareProxy_NotifyChangeExtProvider_Test_001::End"); +} +} +} \ No newline at end of file diff --git a/data_share/test/unittest/native/provider/BUILD.gn b/data_share/test/unittest/native/provider/BUILD.gn new file mode 100644 index 00000000..6eeadc3e --- /dev/null +++ b/data_share/test/unittest/native/provider/BUILD.gn @@ -0,0 +1,92 @@ +# 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/distributeddatamgr/data_share/datashare.gni") + +group("unittest") { + testonly = true + deps = [] + + deps += [ + ":DataShareStubTest", + ] +} + +config("permission_config") { + visibility = [ ":*" ] + include_dirs = [ + "${datashare_common_native_path}/include", + "${datashare_native_permission_path}/include", + ] + + cflags = [] + if (target_cpu == "arm") { + cflags += [ "-DBINDER_IPC_32BIT" ] + } +} + +ohos_unittest("DataShareStubTest") { + module_out_path = "data_share/data_share/native/provider" + + include_dirs = [ + "${datashare_innerapi_path}/consumer/include", + "${datashare_innerapi_path}/common/include", + "${datashare_native_provider_path}/include", + "${datashare_native_proxy_path}/include", + ] + + sources = [ "${datashare_base_path}/test/unittest/native/provider/src/datashare_stub_test.cpp" ] + + deps = [ + "${datashare_innerapi_path}:datashare_consumer_static", + "${datashare_innerapi_path}:datashare_provider", + "${datashare_innerapi_path}/common:datashare_common_static", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:abilitykit_native", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_single", + "ipc:ipc_napi", + "relational_store:rdb_data_ability_adapter", + "samgr:samgr_proxy", + ] + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + blocklist = "${datashare_base_path}/cfi_blocklist.txt" + } + + cflags = [ + "-fvisibility=hidden", + "-Dprivate=public", + "-Dprotected=public", + ] +} \ No newline at end of file diff --git a/data_share/test/unittest/native/provider/src/datashare_stub_test.cpp b/data_share/test/unittest/native/provider/src/datashare_stub_test.cpp new file mode 100644 index 00000000..7cd067af --- /dev/null +++ b/data_share/test/unittest/native/provider/src/datashare_stub_test.cpp @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "datashare_stub.h" + +#include + +#include "accesstoken_kit.h" +#include "data_ability_observer_stub.h" +#include "datashare_business_error.h" +#include "datashare_errno.h" +#include "datashare_itypes_utils.h" +#include "datashare_log.h" +#include "datashare_operation_statement.h" +#include "datashare_stub_impl.h" +#include "extension_manager_proxy.h" +#include "idatashare.h" +#include "ipc_skeleton.h" +#include "ipc_types.h" +#include "ishared_result_set.h" + + +namespace OHOS { +namespace DataShare { +using namespace testing::ext; +using namespace DistributedShare::DataShare; +using namespace OHOS::AAFwk; +using ChangeInfo = AAFwk::ChangeInfo; +class DataShareStubTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + + +class IDataAbilityObserverTest : public DataAbilityObserverStub { +public: + IDataAbilityObserverTest() {} + ~IDataAbilityObserverTest() + {} + + void OnChange() + { + GTEST_LOG_(INFO) << "OnChange enter"; + } +}; + +class TestDataShareStub : public DataShareStub { +public: + TestDataShareStub() {} + ~TestDataShareStub() {} + int OpenFile(const Uri &uri, const std::string &mode) + { + return 0; + } + int OpenRawFile(const Uri &uri, const std::string &mode) + { + return 0; + } + int Insert(const Uri &uri, const DataShareValuesBucket &value) + { + return 0; + } + int Update(const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) + { + return 0; + } + int Delete(const Uri &uri, const DataSharePredicates &predicates) + { + return 0; + } + std::shared_ptr Query(const Uri &uri, const DataSharePredicates &predicates, + std::vector &columns, DatashareBusinessError &businessError) + { + return nullptr; + } + std::string GetType(const Uri &uri) + { + return ""; + } + int BatchInsert(const Uri &uri, const std::vector &values) + { + return 0; + } + bool RegisterObserver(const Uri &uri, const sptr &dataObserver) + { + return true; + } + bool UnregisterObserver(const Uri &uri, const sptr &dataObserver) + { + return true; + } + bool NotifyChange(const Uri &uri) + { + return true; + } + Uri NormalizeUri(const Uri &uri) + { + return uri; + } + Uri DenormalizeUri(const Uri &uri) + { + return uri; + } + std::vector GetFileTypes(const Uri &uri, const std::string &mimeTypeFilter) + { + return {}; + } +}; + +std::string DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; +std::shared_ptr dataShareStub = std::make_shared(); +std::u16string InterfaceToken = u"OHOS.DataShare.IDataShare"; + +void DataShareStubTest::SetUpTestCase(void) {} +void DataShareStubTest::TearDownTestCase(void) {} +void DataShareStubTest::SetUp(void) {} +void DataShareStubTest::TearDown(void) {} + +/** +* @tc.name: DataShareStub_CmdRegisterObserverExtProvider_Test_001 +* @tc.desc: test CmdRegisterObserverExtProvideroteRequest default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareStubTest, DataShareStub_CmdRegisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareStub_CmdRegisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + ASSERT_NE(dataObserver, nullptr); + uint32_t code = static_cast(IDataShareInterfaceCode::CMD_REGISTER_OBSERVEREXT_PROVIDER); + + MessageParcel data; + data.WriteInterfaceToken(InterfaceToken); + RegisterOption registerOption; + bool ret = ITypesUtil::Marshal(data, uri, dataObserver->AsObject(), true, registerOption); + EXPECT_TRUE(ret); + + MessageParcel reply; + MessageOption option; + ASSERT_NE(dataShareStub, nullptr); + int errCode = dataShareStub->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(errCode, 0); + ret = ITypesUtil::Unmarshal(reply, errCode); + EXPECT_TRUE(ret); + // return default errCode 0(E_OK) + EXPECT_EQ(errCode, 0); + + LOG_INFO("DataShareStub_CmdRegisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareStub_CmdUnregisterObserverExtProvider_Test_001 +* @tc.desc: test CmdUnregisterObserverExtProvideroteRequest default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareStubTest, DataShareStub_CmdUnregisterObserverExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareStub_CmdUnregisterObserverExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + sptr dataObserver = new (std::nothrow) IDataAbilityObserverTest(); + ASSERT_NE(dataObserver, nullptr); + uint32_t code = static_cast(IDataShareInterfaceCode::CMD_UNREGISTER_OBSERVEREXT_PROVIDER); + + MessageParcel data; + data.WriteInterfaceToken(InterfaceToken); + bool ret = ITypesUtil::Marshal(data, uri, dataObserver->AsObject()); + EXPECT_TRUE(ret); + + MessageParcel reply; + MessageOption option; + int errCode = dataShareStub->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(errCode, 0); + ret = ITypesUtil::Unmarshal(reply, errCode); + EXPECT_TRUE(ret); + // return default errCode 0(E_OK) + EXPECT_EQ(errCode, 0); + + LOG_INFO("DataShareStub_CmdUnregisterObserverExtProvider_Test_001::End"); +} + +/** +* @tc.name: DataShareStub_CmdNotifyChangeExtProvider_Test_001 +* @tc.desc: test CmdNotifyChangeExtProvider default func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareStubTest, DataShareStub_CmdNotifyChangeExtProvider_Test_001, TestSize.Level0) +{ + LOG_INFO("DataShareStub_CmdNotifyChangeExtProvider_Test_001::Start"); + + Uri uri(DATA_SHARE_URI); + ChangeInfo changeInfo = { ChangeInfo::ChangeType::INSERT, { uri } }; + uint32_t code = static_cast(IDataShareInterfaceCode::CMD_NOTIFY_CHANGEEXT_PROVIDER); + + MessageParcel data; + data.WriteInterfaceToken(InterfaceToken); + bool ret = ChangeInfo::Marshalling(changeInfo, data); + EXPECT_TRUE(ret); + + MessageParcel reply; + MessageOption option; + int errCode = dataShareStub->OnRemoteRequest(code, data, reply, option); + EXPECT_EQ(errCode, 0); + ret = ITypesUtil::Unmarshal(reply, errCode); + EXPECT_TRUE(ret); + // return default errCode 0(E_OK) + EXPECT_EQ(errCode, 0); + + LOG_INFO("DataShareStub_CmdNotifyChangeExtProvider_Test_001::End"); +} +} +} \ No newline at end of file diff --git a/datamgr_service/BUILD.gn b/datamgr_service/BUILD.gn index 71f3ee22..4bffdf86 100644 --- a/datamgr_service/BUILD.gn +++ b/datamgr_service/BUILD.gn @@ -19,6 +19,7 @@ group("build_native_test") { "services/distributeddataservice/app/test:unittest", "services/distributeddataservice/framework/test:unittest", "services/distributeddataservice/service/test:unittest", + "services/distributeddataservice/rust/test:unittest", ] } @@ -31,6 +32,7 @@ group("fuzztest") { "services/distributeddataservice/adapter/test:fuzztest", "services/distributeddataservice/app/test/fuzztest:fuzztest", "services/distributeddataservice/service/test/fuzztest:fuzztest", + "services/distributeddataservice/framework/test/fuzztest:fuzztest", ] } ############################################################################### diff --git a/datamgr_service/bundle.json b/datamgr_service/bundle.json index b1a8472d..f726ee71 100644 --- a/datamgr_service/bundle.json +++ b/datamgr_service/bundle.json @@ -81,6 +81,7 @@ "napi", "netmanager_base", "os_account", + "qos_manager", "relational_store", "resource_management", "safwk", @@ -129,6 +130,8 @@ "cloud/schema_meta.h", "cloud/subscription.h", "cloud/sync_event.h", + "crypto/crypto_manager.h", + "device_manager/device_manager_delegate.h", "dfx/dfx_types.h", "dfx/reporter.h", "directory/directory_manager.h", diff --git a/datamgr_service/datamgr_service.gni b/datamgr_service/datamgr_service.gni index da3e7a49..7b327cce 100644 --- a/datamgr_service/datamgr_service.gni +++ b/datamgr_service/datamgr_service.gni @@ -38,6 +38,8 @@ udmf_path = "//foundation/distributeddatamgr/udmf" dataobject_path = "//foundation/distributeddatamgr/data_object" +datamgr_service_path = "//foundation/distributeddatamgr/datamgr_service" + declare_args() { datamgr_service_power = true if (!defined(global_parts_info.power_manager_native_powermgr_client) || diff --git a/datamgr_service/services/distributeddataservice/adapter/CMakeLists.txt b/datamgr_service/services/distributeddataservice/adapter/CMakeLists.txt index 83d33118..a0bbef98 100644 --- a/datamgr_service/services/distributeddataservice/adapter/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/adapter/CMakeLists.txt @@ -11,7 +11,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=0 -fpermissive -Wattributes") set(MOCK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../mock") set(KV_STORE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../kv_store") add_definitions(-DCONFIG_PUBLIC_VERSION) +add_definitions(-D__CJSON_USE_INT64) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/account/src adapterSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/bundle_mgr adapterSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/broadcaster/src adapterSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/communicator/src adapterSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/dfx/src/behaviour adapterSrc) @@ -20,13 +22,14 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/dfx/src/statistic adapterSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/dfx/src adapterSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/network/src adapterSrc) list(REMOVE_ITEM adapterSrc "${CMAKE_CURRENT_SOURCE_DIR}/network/src/network_delegate_default_impl.cpp") -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/schema_helper/src adapterSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/screenlock/src adapterSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/schema_helper adapterSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/screenlock adapterSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/utils/src adapterSrc) list(REMOVE_ITEM adapterSrc "${CMAKE_CURRENT_SOURCE_DIR}/account/src/account_delegate_default_impl.cpp") include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../framework/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/account/src) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/bundle_mgr) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/broadcaster/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/communicator/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/dfx/src/behaviour) @@ -37,13 +40,6 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/network/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/schema_helper/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/screenlock/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/utils/src) -#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) -#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/account) -#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/broadcaster) -#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/communicator) -#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/dfx) -#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/permission) -#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/utils) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../utils_native/base/include) include(${MOCK_DIR}/include/CMakeLists.txt OPTIONAL) include(${KV_STORE_DIR}/interfaces/CMakeLists.txt OPTIONAL) @@ -51,9 +47,12 @@ set(links secure mock distributeddb crypto svcFwk) add_library(adapter SHARED ${adapterSrc}) target_link_libraries(adapter ${links}) +target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/bundle_mgr) +target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/network) +target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/schema_helper) target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/account) -target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/broadcaster) target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/communicator) target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/dfx) target_include_directories(adapter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/permission) diff --git a/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn index fc643f99..85697b11 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/account/BUILD.gn @@ -35,10 +35,7 @@ ohos_source_set("distributeddata_account") { "${data_service_path}/framework/include/account", ] - cflags_cc = [ - "-fvisibility=hidden", - "-fstack-protector-strong", - ] + cflags_cc = [ "-fvisibility=hidden" ] remove_configs = [ "//build/config/compiler:no_exceptions" ] diff --git a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.cpp index ddcb5002..fdd363d4 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.cpp @@ -20,9 +20,9 @@ namespace OHOS { namespace DistributedData { -namespace { -constexpr const char *DEFAULT_OHOS_ACCOUNT_UID = ""; // default UID -} +static constexpr int32_t FOREGROUND_USER = 100; +static constexpr const char *DEFAULT_OHOS_ACCOUNT_UID = "default"; // default UID + __attribute__((used)) static bool g_isInit = AccountDelegateDefaultImpl::Init(); std::string AccountDelegateDefaultImpl::GetCurrentAccountId() const @@ -31,6 +31,12 @@ std::string AccountDelegateDefaultImpl::GetCurrentAccountId() const return DEFAULT_OHOS_ACCOUNT_UID; } +std::string AccountDelegateDefaultImpl::GetUnencryptedAccountId(int32_t userId) const +{ + (void)userId; + return DEFAULT_OHOS_ACCOUNT_UID; +} + int32_t AccountDelegateDefaultImpl::GetUserByToken(uint32_t tokenId) const { (void)tokenId; @@ -89,6 +95,18 @@ void AccountDelegateDefaultImpl::BindExecutor(std::shared_ptr exec ZLOGD("no account part"); } +bool AccountDelegateDefaultImpl::QueryForegroundUserId(int &foregroundUserId) +{ + foregroundUserId = FOREGROUND_USER; + return true; +} + +bool AccountDelegateDefaultImpl::IsUserForeground(int32_t userId) +{ + (void)userId; + return true; +} + bool AccountDelegateDefaultImpl::Init() { static AccountDelegateDefaultImpl defaultAccountDelegate; diff --git a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.h b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.h index 6d2b5408..a8b709ad 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.h @@ -22,6 +22,7 @@ namespace DistributedData { class AccountDelegateDefaultImpl final : public AccountDelegateImpl { public: std::string GetCurrentAccountId() const override; + std::string GetUnencryptedAccountId(int32_t userId = 0) const override; int32_t GetUserByToken(uint32_t tokenId) const override; bool QueryUsers(std::vector &users) override; bool QueryForegroundUsers(std::vector &users) override; @@ -31,6 +32,8 @@ public: void SubscribeAccountEvent() override; void UnsubscribeAccountEvent() override; void BindExecutor(std::shared_ptr executors) override; + bool QueryForegroundUserId(int &foregroundUserId) override; + bool IsUserForeground(int32_t userId) override; static bool Init(); private: diff --git a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_impl.h b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_impl.h index e8fc5d5c..86874e0e 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_impl.h @@ -19,7 +19,7 @@ #include #include -#include "account_delegate.h" +#include "account/account_delegate.h" #include "concurrent_map.h" #include "log_print.h" diff --git a/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn index 39c09ee5..e1549dcc 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/account/test/BUILD.gn @@ -40,7 +40,7 @@ ohos_unittest("AccountDelegateTest") { "ability_base:base", "ability_base:want", "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "access_token:libtoken_setproc", "bundle_framework:appexecfwk_base", "c_utils:utils", diff --git a/datamgr_service/services/distributeddataservice/service/crypto/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/BUILD.gn similarity index 71% rename from datamgr_service/services/distributeddataservice/service/crypto/BUILD.gn rename to datamgr_service/services/distributeddataservice/adapter/bundle_mgr/BUILD.gn index 18b166a9..7ca4db4f 100644 --- a/datamgr_service/services/distributeddataservice/service/crypto/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2024 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,12 +13,12 @@ import("//build/ohos.gni") import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") -config("crypto_public_config") { +config("module_public_config") { visibility = [ ":*" ] - include_dirs = [ "include" ] + include_dirs = [ "${data_service_path}/adapter" ] } -ohos_source_set("distributeddata_crypto") { +ohos_source_set("distributeddata_bundle_mgr") { branch_protector_ret = "pac_ret" sanitize = { cfi = true @@ -27,17 +27,17 @@ ohos_source_set("distributeddata_crypto") { boundary_sanitize = true ubsan = true } - sources = [ "src/crypto_manager.cpp" ] - + sources = [ "bundle_mgr_adapter.cpp" ] cflags_cc = [ "-fvisibility=hidden", "-Oz", "-fstack-protector-strong", ] - include_dirs = [ "include" ] - + public_configs = [ ":module_public_config" ] cflags = [ + "-fdata-sections", + "-ffunction-sections", "-Werror", "-Wno-multichar", "-Wno-c99-designator", @@ -45,13 +45,12 @@ ohos_source_set("distributeddata_crypto") { "-Oz", "-fstack-protector-strong", ] - configs = [ ":crypto_public_config" ] - public_configs = [ ":crypto_public_config" ] - deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] - external_deps = [ - "dmsfwk:distributed_sdk", + + external_deps = [ "kv_store:datamgr_common" ] + external_deps += [ + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", "hilog:libhilog", - "huks:libhukssdk", ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" diff --git a/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/bundle_mgr_adapter.cpp b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/bundle_mgr_adapter.cpp new file mode 100644 index 00000000..555473d9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/bundle_mgr_adapter.cpp @@ -0,0 +1,110 @@ +/* + * 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. + */ + +#define LOG_TAG "BundleMgrAdapter" +#include "bundle_mgr/bundle_mgr_adapter.h" +#include "bundle_mgr_client.h" +#include "log_print.h" +using namespace OHOS::AppExecFwk; +namespace OHOS::DistributedData { +BundleFlag Convert(int32_t type) +{ + switch (type) { + case BundleMgrAdapter::BUNDLE_DEFAULT: + return GET_BUNDLE_DEFAULT; + case BundleMgrAdapter::BUNDLE_WITH_ABILITIES: + return GET_BUNDLE_WITH_ABILITIES; + case BundleMgrAdapter::BUNDLE_WITH_REQUESTED_PERMISSION: + return GET_BUNDLE_WITH_REQUESTED_PERMISSION; + case BundleMgrAdapter::BUNDLE_WITH_EXTENSION_INFO: + return GET_BUNDLE_WITH_EXTENSION_INFO; + case BundleMgrAdapter::BUNDLE_WITH_HASH_VALUE: + return GET_BUNDLE_WITH_HASH_VALUE; + case BundleMgrAdapter::BUNDLE_WITH_MENU: + return GET_BUNDLE_WITH_MENU; + case BundleMgrAdapter::BUNDLE_WITH_ROUTER_MAP: + return GET_BUNDLE_WITH_ROUTER_MAP; + case BundleMgrAdapter::BUNDLE_WITH_SKILL: + return GET_BUNDLE_WITH_SKILL; + } + ZLOGW("invalid type:%{public}d", type); + return GET_BUNDLE_DEFAULT; +} + +BundleMgrAdapter::HapModuleInfo Convert(AppExecFwk::HapModuleInfo &&info) +{ + BundleMgrAdapter::HapModuleInfo res; + res.hapPath = std::move(info.hapPath); + return res; +} + +BundleMgrAdapter::BundleInfo Convert(AppExecFwk::BundleInfo &&info) +{ + BundleMgrAdapter::BundleInfo res; + res.moduleDirs = info.moduleDirs; + res.hapModuleInfos.reserve(info.hapModuleInfos.size()); + for (auto &moduleInfo : info.hapModuleInfos) { + res.hapModuleInfos.push_back(Convert(std::move(moduleInfo))); + } + return res; +} + +BundleMgrAdapter &BundleMgrAdapter::GetInstance() +{ + static BundleMgrAdapter instance; + return instance; +} + +std::pair BundleMgrAdapter::GetBundleInfo(const std::string &bundleName, + BundleType type, int32_t user) +{ + AppExecFwk::BundleInfo info; + BundleMgrClient client; + bool res = client.GetBundleInfo(bundleName, Convert(type), info, user == 0 ? Constants::UNSPECIFIED_USERID : user); + if (!res) { + return { res, {} }; + } + BundleInfo bundleInfo = Convert(std::move(info)); + return { res, bundleInfo }; +} + +std::string BundleMgrAdapter::GetBundleName(int32_t uid) +{ + BundleMgrClient client; + std::string bundleName; + auto code = client.GetNameForUid(uid, bundleName); + if (code != 0) { + ZLOGE("failed. uid:%{public}d, code:%{public}d", uid, code); + return ""; + } + return bundleName; +} + +std::string BundleMgrAdapter::GetAppId(int32_t user, const std::string &bundleName) +{ + if (bundleName.empty()) { + ZLOGE("invalid args. user:%{public}d, bundleName:%{public}s", user, bundleName.c_str()); + return ""; + } + AppExecFwk::BundleInfo info; + BundleMgrClient client; + auto code = client.GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_DEFAULT, info, + user == 0 ? Constants::UNSPECIFIED_USERID : user); + if (code != 0) { + ZLOGE("failed. user:%{public}d, bundleName:%{public}s", user, bundleName.c_str()); + } + return info.appId; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/bundle_mgr_adapter.h b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/bundle_mgr_adapter.h new file mode 100644 index 00000000..fa0d4b95 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/bundle_mgr_adapter.h @@ -0,0 +1,58 @@ +/* + * 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 DISTRIBUTEDDATAMGR_DATAMGR_BUNDLE_MANAGER_ADAPTER_H +#define DISTRIBUTEDDATAMGR_DATAMGR_BUNDLE_MANAGER_ADAPTER_H + +#include +#include +#include "visibility.h" + +namespace OHOS { +namespace DistributedData { +class API_EXPORT BundleMgrAdapter { +public: + struct HapModuleInfo { + std::string hapPath; + }; + struct BundleInfo { + std::vector hapModuleInfos; + std::vector moduleDirs; + }; + enum BundleType { + // get bundle info except abilityInfos + BUNDLE_DEFAULT = 0x00000000, + // get bundle info include abilityInfos + BUNDLE_WITH_ABILITIES = 0x00000001, + // get bundle info include request permissions + BUNDLE_WITH_REQUESTED_PERMISSION = 0x00000010, + // get bundle info include extension info + BUNDLE_WITH_EXTENSION_INFO = 0x00000020, + // get bundle info include hash value + BUNDLE_WITH_HASH_VALUE = 0x00000030, + // get bundle info include menu, only for dump usage + BUNDLE_WITH_MENU = 0x00000040, + // get bundle info include router map, only for dump usage + BUNDLE_WITH_ROUTER_MAP = 0x00000080, + // get bundle info include skill info + BUNDLE_WITH_SKILL = 0x00000800, + }; + static BundleMgrAdapter &GetInstance(); + std::pair GetBundleInfo(const std::string &bundleName, BundleType type, int32_t user = 0); + std::string GetBundleName(int32_t uid); + std::string GetAppId(int32_t user, const std::string &bundleName); +}; +} // namespace DistributedData +} // namespace OHOS +#endif //DISTRIBUTEDDATAMGR_DATAMGR_BUNDLE_MANAGER_ADAPTER_H diff --git a/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/BUILD.gn new file mode 100644 index 00000000..193ada6a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/BUILD.gn @@ -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. +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") +module_output_path = "datamgr_service/datamgr_service/distributeddatafwk" + +############################################################################### +ohos_unittest("BundleMgrTest") { + module_out_path = module_output_path + + sources = [ "bundle_mgr_test.cpp" ] + + cflags = [ "-Werror" ] + deps = [ "${data_service_path}/adapter/bundle_mgr:distributeddata_bundle_mgr" ] + + external_deps = [ + "googletest:gtest_main", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + ] +} + +############################################################################### +group("unittest") { + testonly = true + + deps = [] + + deps += [ ":BundleMgrTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/bundle_mgr_client.h b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/bundle_mgr_client.h new file mode 100644 index 00000000..3759fdfe --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/bundle_mgr_client.h @@ -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. + */ + +#ifndef DISTRIBUTEDDATAMGR_DATAMGR_BUNDLE_MANAGER_ADAPTER_MOCK_H +#define DISTRIBUTEDDATAMGR_DATAMGR_BUNDLE_MANAGER_ADAPTER_MOCK_H + +#include "parcel.h" + +namespace OHOS { +namespace AppExecFwk { +enum BundleFlag { + // get bundle info except abilityInfos + GET_BUNDLE_DEFAULT = 0x00000000, + // get bundle info include abilityInfos + GET_BUNDLE_WITH_ABILITIES = 0x00000001, + // get bundle info include request permissions + GET_BUNDLE_WITH_REQUESTED_PERMISSION = 0x00000010, + // get bundle info include extension info + GET_BUNDLE_WITH_EXTENSION_INFO = 0x00000020, + // get bundle info include hash value + GET_BUNDLE_WITH_HASH_VALUE = 0x00000030, + // get bundle info inlcude menu, only for dump usage + GET_BUNDLE_WITH_MENU = 0x00000040, + // get bundle info inlcude router map, only for dump usage + GET_BUNDLE_WITH_ROUTER_MAP = 0x00000080, + // get bundle info include skill info + GET_BUNDLE_WITH_SKILL = 0x00000800, +}; +enum class GetBundleInfoFlag { + GET_BUNDLE_INFO_DEFAULT = 0x00000000, + GET_BUNDLE_INFO_WITH_APPLICATION = 0x00000001, + GET_BUNDLE_INFO_WITH_HAP_MODULE = 0x00000002, + GET_BUNDLE_INFO_WITH_ABILITY = 0x00000004, + GET_BUNDLE_INFO_WITH_EXTENSION_ABILITY = 0x00000008, + GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION = 0x00000010, + GET_BUNDLE_INFO_WITH_METADATA = 0x00000020, + GET_BUNDLE_INFO_WITH_DISABLE = 0x00000040, + GET_BUNDLE_INFO_WITH_SIGNATURE_INFO = 0x00000080, + GET_BUNDLE_INFO_WITH_MENU = 0x00000100, + GET_BUNDLE_INFO_WITH_ROUTER_MAP = 0x00000200, + GET_BUNDLE_INFO_WITH_SKILL = 0x00000800, + GET_BUNDLE_INFO_ONLY_WITH_LAUNCHER_ABILITY = 0x00001000, + GET_BUNDLE_INFO_OF_ANY_USER = 0x00002000, + GET_BUNDLE_INFO_EXCLUDE_CLONE = 0x00004000, +}; + +struct RequestPermissionUsedScene : public Parcelable { + std::string when; + std::vector abilities; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static RequestPermissionUsedScene *Unmarshalling(Parcel &parcel); +}; + +struct RequestPermission : public Parcelable { + uint32_t reasonId = 0; + std::string name; + std::string moduleName; + std::string reason; + RequestPermissionUsedScene usedScene; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static RequestPermission *Unmarshalling(Parcel &parcel); +}; + +struct SignatureInfo : public Parcelable { + std::string appId; + std::string fingerprint; + std::string appIdentifier; + std::string certificate; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static SignatureInfo *Unmarshalling(Parcel &parcel); +}; + +struct SimpleAppInfo : public Parcelable { + int32_t uid = -1; + std::string bundleName; + int32_t appIndex = -1; + int32_t ret = 0; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static SimpleAppInfo *Unmarshalling(Parcel &parcel); + std::string ToString() const; +}; + +// configuration information about a bundle +struct BundleInfo : public Parcelable { + bool isNewVersion = false; + bool isKeepAlive = false; + bool singleton = false; + bool isPreInstallApp = false; + + bool isNativeApp = false; + + bool entryInstallationFree = false; // application : false; atomic service : true + bool isDifferentName = false; + + uint32_t versionCode = 0; + uint32_t minCompatibleVersionCode = 0; + + uint32_t compatibleVersion = 0; + uint32_t targetVersion = 0; + int32_t appIndex = 0; // index for sandbox app + int32_t minSdkVersion = -1; + int32_t maxSdkVersion = -1; + // int32_t overlayType = NON_OVERLAY_TYPE; + + // user related fields, assign when calling the get interface + int uid = -1; + int gid = -1; + int64_t installTime = 0; + int64_t updateTime = 0; + int64_t firstInstallTime = 0; + std::string name; + std::string versionName; + + std::string vendor; + std::string releaseType; + std::string mainEntry; // modulePackage + std::string entryModuleName; // moduleName + std::string appId; + + std::string cpuAbi; + std::string seInfo; + std::string label; + std::string description; + std::string jointUserId; + SignatureInfo signatureInfo; + std::vector oldAppIds; // used for appId changed + + std::vector hapModuleNames; // the "module.package" in each config.json + std::vector moduleNames; // the "module.name" in each config.json + std::vector modulePublicDirs; // the public paths of all modules of the application. + std::vector moduleDirs; // the paths of all modules of the application. + std::vector moduleResPaths; // the paths of all resources paths. + + std::vector reqPermissions; + std::vector defPermissions; + std::vector reqPermissionStates; + std::vector reqPermissionDetails; + + bool ReadFromParcel(Parcel &parcel); + virtual bool Marshalling(Parcel &parcel) const override; + static BundleInfo *Unmarshalling(Parcel &parcel); +}; +class BundleMgrClient { +public: + static constexpr const char *BUNDLE_NAME = "com.ohos.BundleMock"; + static inline int uid_ = -1; + int userID_ = -1; + std::string name_; + BundleFlag flag_ = GET_BUNDLE_DEFAULT; + BundleMgrClient(); + virtual ~BundleMgrClient(); + + int32_t GetNameForUid(const int uid, std::string &name) + { + uid_ = uid; + name = BUNDLE_NAME; + return true; + } + bool GetBundleInfo(const std::string &bundleName, const BundleFlag flag, BundleInfo &bundleInfo, + int32_t userId = -1) + { + name_ = bundleName; + flag_ = flag; + userID_ = userId; + return true; + } +}; +} // namespace AppExecFwk +} // namespace OHOS + +#endif // DISTRIBUTEDDATAMGR_DATAMGR_BUNDLE_MANAGER_ADAPTER_MOCK_H diff --git a/relational_store/interfaces/inner_api/gdb/include/result.h b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/bundle_mgr_test.cpp similarity index 41% rename from relational_store/interfaces/inner_api/gdb/include/result.h rename to datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/bundle_mgr_test.cpp index b4b17ed8..bf559072 100644 --- a/relational_store/interfaces/inner_api/gdb/include/result.h +++ b/datamgr_service/services/distributeddataservice/adapter/bundle_mgr/test/bundle_mgr_test.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2024 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,28 +13,33 @@ * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_RESULT_H -#define OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_RESULT_H +#include -#include -#include -#include -#include -#include -#include +#include "bundle_mgr/bundle_mgr_adapter.h" +#include "ipc_skeleton.h" +namespace { +using namespace OHOS; +using namespace OHOS::DistributedData; +using namespace testing::ext; -#include "edge.h" -#include "path.h" -#include "vertex.h" -#include "rdb_visibility.h" - -namespace OHOS::DistributedDataAip { -using GraphValue = std::variant, - std::shared_ptr, std::shared_ptr, std::shared_ptr, std::nullptr_t>; - -class Result { +class BundleMgrTest : public testing::Test { public: - API_EXPORT virtual std::vector> GetAllData() const = 0; + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} + void SetUp() {} + void TearDown() {} }; -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_RESULT_H \ No newline at end of file + +/** +* @tc.name: GetBundleName +* @tc.desc: GetBundleName test +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(BundleMgrTest, GetBundleName, TestSize.Level0) +{ + auto bundleName = BundleMgrAdapter::GetInstance().GetBundleName(0); + EXPECT_TRUE(bundleName.empty()); +} +} // namespace \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn index 522a20c2..44098bb6 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn @@ -12,6 +12,11 @@ # limitations under the License. import("//build/ohos.gni") import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +config("module_public_config") { + visibility = [ ":*" ] + include_dirs = [ "${data_service_path}/adapter/include/communicator" ] +} ohos_source_set("distributeddata_communicator") { branch_protector_ret = "pac_ret" sanitize = { @@ -42,25 +47,19 @@ ohos_source_set("distributeddata_communicator") { ] include_dirs = [ - "../include/communicator", - "../include/utils", - "${data_service_path}/adapter/include/communicator", - "${data_service_path}/framework/include/dfx", - "${data_service_path}/framework/include/utils", + "${data_service_path}/adapter/include/utils", ] - cflags_cc = [ - "-fvisibility=hidden", - "-fstack-protector-strong", - ] + cflags_cc = [ "-fvisibility=hidden" ] + public_configs = [ ":module_public_config" ] deps = [ "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", - "../dfx:distributeddata_dfx", ] external_deps = [ + "access_token:libaccesstoken_sdk", "c_utils:utils", "device_manager:devicemanagersdk", "dsoftbus:softbus_client", diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_handler.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_handler.cpp index 40d6f8bb..3677ffdd 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_handler.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_handler.cpp @@ -15,11 +15,7 @@ #include "app_pipe_handler.h" #include -#include -#include -#include #include "log_print.h" -#include "dfx/reporter.h" #ifdef LOG_TAG #undef LOG_TAG @@ -46,44 +42,68 @@ AppPipeHandler::AppPipeHandler(const PipeInfo &pipeInfo) std::pair AppPipeHandler::SendData(const PipeInfo &pipeInfo, const DeviceId &deviceId, const DataInfo &dataInfo, uint32_t totalLength, const MessageInfo &info) { + if (softbusAdapter_ == nullptr) { + return std::make_pair(Status::ERROR, 0); + } return softbusAdapter_->SendData(pipeInfo, deviceId, dataInfo, totalLength, info); } Status AppPipeHandler::StartWatchDataChange(const AppDataChangeListener *observer, const PipeInfo &pipeInfo) { + if (softbusAdapter_ == nullptr) { + return Status::ERROR; + } return softbusAdapter_->StartWatchDataChange(observer, pipeInfo); } Status AppPipeHandler::StopWatchDataChange(__attribute__((unused))const AppDataChangeListener *observer, - const PipeInfo &pipeInfo) + const PipeInfo &pipeInfo) { + if (softbusAdapter_ == nullptr) { + return Status::ERROR; + } return softbusAdapter_->StopWatchDataChange(observer, pipeInfo); } bool AppPipeHandler::IsSameStartedOnPeer(const struct PipeInfo &pipeInfo, - __attribute__((unused))const struct DeviceId &peer) + __attribute__((unused))const struct DeviceId &peer) { + if (softbusAdapter_ == nullptr) { + return false; + } return softbusAdapter_->IsSameStartedOnPeer(pipeInfo, peer); } void AppPipeHandler::SetMessageTransFlag(const PipeInfo &pipeInfo, bool flag) { + if (softbusAdapter_ == nullptr) { + return; + } return softbusAdapter_->SetMessageTransFlag(pipeInfo, flag); } int AppPipeHandler::CreateSessionServer(const std::string &sessionName) const { + if (softbusAdapter_ == nullptr) { + return -1; + } return softbusAdapter_->CreateSessionServerAdapter(sessionName); } int AppPipeHandler::RemoveSessionServer(const std::string &sessionName) const { + if (softbusAdapter_ == nullptr) { + return -1; + } return softbusAdapter_->RemoveSessionServerAdapter(sessionName); } -Status AppPipeHandler::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId) +Status AppPipeHandler::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, const ExtraDataInfo &extraInfo) { - return softbusAdapter_->ReuseConnect(pipeInfo, deviceId); + if (softbusAdapter_ == nullptr) { + return Status::ERROR; + } + return softbusAdapter_->ReuseConnect(pipeInfo, deviceId, extraInfo); } } // namespace AppDistributedKv } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_handler.h b/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_handler.h index 6a9dc009..3cd90cb6 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_handler.h +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_handler.h @@ -16,20 +16,9 @@ #ifndef DISTRIBUTEDDATAFWK_SRC_PIPE_HANDLER_H #define DISTRIBUTEDDATAFWK_SRC_PIPE_HANDLER_H -#include -#include -#include -#include -#include "dfx/reporter.h" -#include "log_print.h" #include "app_data_change_listener.h" #include "softbus_adapter.h" -#ifdef LOG_TAG - #undef LOG_TAG -#endif -#define LOG_TAG "AppPipeHandler" - namespace OHOS { namespace AppDistributedKv { class AppPipeHandler { @@ -52,12 +41,11 @@ public: int RemoveSessionServer(const std::string &sessionName) const; - Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId); + Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, const ExtraDataInfo &extraInfo); private: PipeInfo pipeInfo_; - std::shared_ptr softbusAdapter_ {}; + std::shared_ptr softbusAdapter_; }; } // namespace AppDistributedKv } // namespace OHOS -#undef LOG_TAG -#endif /* DISTRIBUTEDDATAFWK_SRC_PIPE_HANDLER_H */ +#endif // DISTRIBUTEDDATAFWK_SRC_PIPE_HANDLER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_mgr.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_mgr.cpp index fb62e8a4..c444ade1 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_mgr.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_mgr.cpp @@ -13,16 +13,19 @@ * limitations under the License. */ -#include "app_pipe_mgr.h" -#include "kvstore_utils.h" -#include "dfx/reporter.h" - +#ifdef LOG_TAG #undef LOG_TAG +#endif #define LOG_TAG "AppPipeMgr" +#include "app_pipe_mgr.h" + +#include "utils/anonymous.h" + namespace OHOS { namespace AppDistributedKv { using namespace OHOS::DistributedKv; +using namespace OHOS::DistributedData; Status AppPipeMgr::StartWatchDataChange(const AppDataChangeListener *observer, const PipeInfo &pipeInfo) { ZLOGI("begin"); @@ -32,7 +35,7 @@ Status AppPipeMgr::StartWatchDataChange(const AppDataChangeListener *observer, c } std::lock_guard lock(dataBusMapMutex_); auto it = dataBusMap_.find(pipeInfo.pipeId); - if (it == dataBusMap_.end()) { + if (it == dataBusMap_.end() || it->second == nullptr) { ZLOGE("pipeid not found"); return Status::ERROR; } @@ -50,7 +53,7 @@ Status AppPipeMgr::StopWatchDataChange(const AppDataChangeListener *observer, co } std::lock_guard lock(dataBusMapMutex_); auto it = dataBusMap_.find(pipeInfo.pipeId); - if (it == dataBusMap_.end()) { + if (it == dataBusMap_.end() || it->second == nullptr) { ZLOGE("pipeid not found"); return Status::ERROR; } @@ -62,18 +65,26 @@ Status AppPipeMgr::StopWatchDataChange(const AppDataChangeListener *observer, co std::pair AppPipeMgr::SendData(const PipeInfo &pipeInfo, const DeviceId &deviceId, const DataInfo &dataInfo, uint32_t totalLength, const MessageInfo &info) { - if (dataInfo.length > DataBuffer::MAX_TRANSFER_SIZE || dataInfo.length == 0 || dataInfo.data == nullptr || - pipeInfo.pipeId.empty() || deviceId.deviceId.empty()) { - ZLOGW("Input is invalid, maxSize:%u, current size:%u", DataBuffer::MAX_TRANSFER_SIZE, dataInfo.length); + if (pipeInfo.pipeId.empty() || deviceId.deviceId.empty() || dataInfo.length > DataBuffer::MAX_TRANSFER_SIZE || + dataInfo.length == 0 || dataInfo.data == nullptr) { + ZLOGE("Input is invalid, maxSize:%{public}u, current size:%{public}u", DataBuffer::MAX_TRANSFER_SIZE, + dataInfo.length); + return std::make_pair(Status::ERROR, 0); + } + if (dataInfo.extraInfo.userId.empty() || dataInfo.extraInfo.appId.empty() || dataInfo.extraInfo.storeId.empty()) { + ZLOGE("access info is empty, userId:%{public}s, appId:%{public}s, storeId:%{public}s", + dataInfo.extraInfo.userId.c_str(), dataInfo.extraInfo.appId.c_str(), + Anonymous::Change(dataInfo.extraInfo.storeId).c_str()); return std::make_pair(Status::ERROR, 0); } - ZLOGD("pipeInfo:%s ,size:%u, total length:%u", pipeInfo.pipeId.c_str(), dataInfo.length, totalLength); + ZLOGD("pipeInfo:%{public}s ,size:%{public}u, total length:%{public}u", pipeInfo.pipeId.c_str(), + dataInfo.length, totalLength); std::shared_ptr appPipeHandler; { std::lock_guard lock(dataBusMapMutex_); auto it = dataBusMap_.find(pipeInfo.pipeId); - if (it == dataBusMap_.end()) { - ZLOGW("pipeInfo:%s not found", pipeInfo.pipeId.c_str()); + if (it == dataBusMap_.end() || it->second == nullptr) { + ZLOGE("pipeInfo:%{public}s not found", pipeInfo.pipeId.c_str()); return std::make_pair(Status::KEY_NOT_FOUND, 0); } appPipeHandler = it->second; @@ -90,7 +101,7 @@ Status AppPipeMgr::Start(const PipeInfo &pipeInfo) } std::lock_guard lock(dataBusMapMutex_); auto it = dataBusMap_.find(pipeInfo.pipeId); - if (it != dataBusMap_.end()) { + if (it != dataBusMap_.end() && it->second != nullptr) { ZLOGW("repeated start, pipeInfo:%{public}s.", pipeInfo.pipeId.c_str()); return Status::SUCCESS; } @@ -101,8 +112,7 @@ Status AppPipeMgr::Start(const PipeInfo &pipeInfo) ZLOGW("Start pipeInfo:%{public}s, failed ret:%{public}d.", pipeInfo.pipeId.c_str(), ret); return Status::ILLEGAL_STATE; } - - dataBusMap_.insert(std::pair>(pipeInfo.pipeId, handler)); + dataBusMap_.insert_or_assign(pipeInfo.pipeId, handler); return Status::SUCCESS; } @@ -111,7 +121,7 @@ Status AppPipeMgr::Stop(const PipeInfo &pipeInfo) { std::lock_guard lock(dataBusMapMutex_); auto it = dataBusMap_.find(pipeInfo.pipeId); - if (it == dataBusMap_.end()) { + if (it == dataBusMap_.end() || it->second == nullptr) { ZLOGW("pipeInfo:%s not found", pipeInfo.pipeId.c_str()); return Status::KEY_NOT_FOUND; } @@ -137,7 +147,7 @@ bool AppPipeMgr::IsSameStartedOnPeer(const struct PipeInfo &pipeInfo, const stru { std::lock_guard lock(dataBusMapMutex_); auto it = dataBusMap_.find(pipeInfo.pipeId); - if (it == dataBusMap_.end()) { + if (it == dataBusMap_.end() || it->second == nullptr) { ZLOGE("pipeInfo:%s not found. Return false.", pipeInfo.pipeId.c_str()); return false; } @@ -155,7 +165,7 @@ void AppPipeMgr::SetMessageTransFlag(const PipeInfo &pipeInfo, bool flag) { std::lock_guard lock(dataBusMapMutex_); auto it = dataBusMap_.find(pipeInfo.pipeId); - if (it == dataBusMap_.end()) { + if (it == dataBusMap_.end() || it->second == nullptr) { ZLOGW("pipeInfo:%s not found", pipeInfo.pipeId.c_str()); return; } @@ -164,25 +174,32 @@ void AppPipeMgr::SetMessageTransFlag(const PipeInfo &pipeInfo, bool flag) appPipeHandler->SetMessageTransFlag(pipeInfo, flag); } -Status AppPipeMgr::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId) +Status AppPipeMgr::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, const ExtraDataInfo &extraInfo) { if (pipeInfo.pipeId.empty() || deviceId.deviceId.empty()) { - ZLOGW("Input is invalid, pipeId:%{public}s, deviceId:%{public}s", pipeInfo.pipeId.c_str(), - KvStoreUtils::ToBeAnonymous(deviceId.deviceId).c_str()); + ZLOGE("Input is invalid, pipeId:%{public}s, deviceId:%{public}s", pipeInfo.pipeId.c_str(), + Anonymous::Change(deviceId.deviceId).c_str()); return Status::INVALID_ARGUMENT; } - ZLOGD("pipeInfo:%s", pipeInfo.pipeId.c_str()); + if (extraInfo.userId.empty() || extraInfo.bundleName.empty() || extraInfo.storeId.empty() || + extraInfo.tokenId == 0) { + ZLOGE("access info is empty, userId:%{public}s, bundleName:%{public}s, storeId:%{public}s, tokenId:%{public}d", + extraInfo.userId.c_str(), extraInfo.bundleName.c_str(), Anonymous::Change(extraInfo.storeId).c_str(), + extraInfo.tokenId); + return Status::ERROR; + } + ZLOGD("pipeInfo:%{public}s", pipeInfo.pipeId.c_str()); std::shared_ptr appPipeHandler; { std::lock_guard lock(dataBusMapMutex_); auto it = dataBusMap_.find(pipeInfo.pipeId); - if (it == dataBusMap_.end()) { - ZLOGW("pipeInfo:%s not found", pipeInfo.pipeId.c_str()); - return Status::INVALID_ARGUMENT; + if (it == dataBusMap_.end() || it->second == nullptr) { + ZLOGE("pipeInfo:%{public}s not found", pipeInfo.pipeId.c_str()); + return Status::KEY_NOT_FOUND; } appPipeHandler = it->second; } - return appPipeHandler->ReuseConnect(pipeInfo, deviceId); + return appPipeHandler->ReuseConnect(pipeInfo, deviceId, extraInfo); } } // namespace AppDistributedKv -} // namespace OHOS +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_mgr.h b/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_mgr.h index d7c35057..ac70d6b9 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_mgr.h +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/app_pipe_mgr.h @@ -47,7 +47,7 @@ public: void SetMessageTransFlag(const PipeInfo &pipeInfo, bool flag); - Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId); + Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, const ExtraDataInfo &extraInfo); private: std::mutex dataBusMapMutex_ {}; std::map> dataBusMap_ {}; diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/communication_provider_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/communication_provider_impl.cpp index 25cb6c74..25ae31cb 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/communication_provider_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/communication_provider_impl.cpp @@ -85,9 +85,10 @@ int32_t CommunicationProviderImpl::ListenBroadcastMsg(const PipeInfo &pipeInfo, return SoftBusAdapter::GetInstance()->ListenBroadcastMsg(pipeInfo, std::move(listener)); } -Status CommunicationProviderImpl::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId) +Status CommunicationProviderImpl::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, + const ExtraDataInfo &extraInfo) { - return appPipeMgr_.ReuseConnect(pipeInfo, deviceId); + return appPipeMgr_.ReuseConnect(pipeInfo, deviceId, extraInfo); } } // namespace AppDistributedKv } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/communication_provider_impl.h b/datamgr_service/services/distributeddataservice/adapter/communicator/src/communication_provider_impl.h index 1fb5a620..cdc67297 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/communication_provider_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/communication_provider_impl.h @@ -52,7 +52,7 @@ public: int32_t ListenBroadcastMsg(const PipeInfo &pipeInfo, std::function listener) override; - Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId) override; + Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, const ExtraDataInfo &extraInfo) override; protected: virtual Status Initialize(); diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/communicator_context.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/communicator_context.cpp index 76f63db9..b5415a6b 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/communicator_context.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/communicator_context.cpp @@ -14,13 +14,14 @@ */ #define LOG_TAG "CommunicatorContext" + #include "communicator_context.h" + #include "log_print.h" -#include "kvstore_utils.h" #include "softbus_error_code.h" +#include "utils/anonymous.h" namespace OHOS::DistributedData { -using KvUtils = OHOS::DistributedKv::KvStoreUtils; using Status = OHOS::DistributedKv::Status; CommunicatorContext &CommunicatorContext::GetInstance() @@ -92,7 +93,7 @@ void CommunicatorContext::NotifySessionReady(const std::string &deviceId, int32_ } } ZLOGI("Notify session begin, deviceId:%{public}s, observer count:%{public}zu", - KvUtils::ToBeAnonymous(deviceId).c_str(), observers_.size()); + Anonymous::Change(deviceId).c_str(), observers_.size()); } if (errCode == SOFTBUS_OK) { std::lock_guard sessionLockGard(sessionMutex_); diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/device_manager_adapter.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/device_manager_adapter.cpp index b9b0078f..ea4915cf 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/device_manager_adapter.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/device_manager_adapter.cpp @@ -14,20 +14,20 @@ */ #define LOG_TAG "DeviceManagerAdapter" -#include "device_manager_adapter.h" -#include +#include "device_manager_adapter.h" -#include "kvstore_utils.h" #include "log_print.h" #include "serializable/serializable.h" +#include "utils/anonymous.h" namespace OHOS::DistributedData { using namespace OHOS::DistributedHardware; using namespace OHOS::AppDistributedKv; -using KvStoreUtils = OHOS::DistributedKv::KvStoreUtils; constexpr int32_t DM_OK = 0; constexpr const char *PKG_NAME = "ohos.distributeddata.service"; +__attribute__((used)) static bool g_delegateInit = + DeviceManagerDelegate::RegisterInstance(&DeviceManagerAdapter::GetInstance()); class DataMgrDmStateCall final : public DistributedHardware::DeviceStateCallback { public: explicit DataMgrDmStateCall(DeviceManagerAdapter &dmAdapter) : dmAdapter_(dmAdapter) {} @@ -173,7 +173,7 @@ void DeviceManagerAdapter::Online(const DmDeviceInfo &info) return; } ZLOGI("[online] uuid:%{public}s, name:%{public}s, type:%{public}d, authForm:%{public}d, osType:%{public}d", - KvStoreUtils::ToBeAnonymous(dvInfo.uuid).c_str(), dvInfo.deviceName.c_str(), dvInfo.deviceType, + Anonymous::Change(dvInfo.uuid).c_str(), Anonymous::Change(dvInfo.deviceName).c_str(), dvInfo.deviceType, static_cast(dvInfo.authForm), dvInfo.osType); SaveDeviceInfo(dvInfo, DeviceChangeType::DEVICE_ONLINE); syncTask_.Insert(dvInfo.uuid, dvInfo.uuid); @@ -217,7 +217,7 @@ void DeviceManagerAdapter::NotifyReadyEvent(const std::string &uuid) if (uuid == CLOUD_DEVICE_UUID) { return; } - ZLOGI("[NotifyReadyEvent] uuid:%{public}s", KvStoreUtils::ToBeAnonymous(uuid).c_str()); + ZLOGI("[NotifyReadyEvent] uuid:%{public}s", Anonymous::Change(uuid).c_str()); std::string event = R"({"extra": {"deviceId":")" + uuid + R"(" } })"; DeviceManager::GetInstance().NotifyEvent(PKG_NAME, DmNotifyEvent::DM_NOTIFY_EVENT_ONDEVICEREADY, event); } @@ -242,7 +242,7 @@ void DeviceManagerAdapter::Offline(const DmDeviceInfo &info) } syncTask_.Erase(dvInfo.uuid); ZLOGI("[offline] uuid:%{public}s, name:%{public}s, type:%{public}d, authForm:%{public}d, osType:%{public}d", - KvStoreUtils::ToBeAnonymous(dvInfo.uuid).c_str(), dvInfo.deviceName.c_str(), dvInfo.deviceType, + Anonymous::Change(dvInfo.uuid).c_str(), Anonymous::Change(dvInfo.deviceName).c_str(), dvInfo.deviceType, static_cast(dvInfo.authForm), dvInfo.osType); SaveDeviceInfo(dvInfo, DeviceChangeType::DEVICE_OFFLINE); auto task = [this, dvInfo]() { @@ -263,8 +263,9 @@ void DeviceManagerAdapter::OnChanged(const DmDeviceInfo &info) ZLOGE("get device info fail"); return; } - ZLOGI("[OnChanged] uuid:%{public}s, name:%{public}s, type:%{public}d", - KvStoreUtils::ToBeAnonymous(dvInfo.uuid).c_str(), dvInfo.deviceName.c_str(), dvInfo.deviceType); + ZLOGI("[OnChanged] uuid:%{public}s, name:%{public}s, type:%{public}d, authForm:%{public}d osType:%{public}d", + Anonymous::Change(dvInfo.uuid).c_str(), Anonymous::Change(dvInfo.deviceName).c_str(), dvInfo.deviceType, + static_cast(dvInfo.authForm), dvInfo.osType); } void DeviceManagerAdapter::OnReady(const DmDeviceInfo &info) @@ -275,8 +276,9 @@ void DeviceManagerAdapter::OnReady(const DmDeviceInfo &info) return; } readyDevices_.InsertOrAssign(dvInfo.uuid, std::make_pair(DeviceState::DEVICE_ONREADY, dvInfo)); - ZLOGI("[OnReady] uuid:%{public}s, name:%{public}s, type:%{public}d", - KvStoreUtils::ToBeAnonymous(dvInfo.uuid).c_str(), dvInfo.deviceName.c_str(), dvInfo.deviceType); + ZLOGI("[OnReady] uuid:%{public}s, name:%{public}s, type:%{public}d, authForm:%{public}d, osType:%{public}d", + Anonymous::Change(dvInfo.uuid).c_str(), Anonymous::Change(dvInfo.deviceName).c_str(), dvInfo.deviceType, + static_cast(dvInfo.authForm), dvInfo.osType); auto task = [this, dvInfo]() { observers_.ForEachCopies([&dvInfo](const auto &key, auto &value) { if (value != nullptr) { @@ -326,6 +328,11 @@ void DeviceManagerAdapter::SaveDeviceInfo(const DeviceInfo &dvInfo, const Device deviceInfos_.Set(dvInfo.uuid, dvInfo); deviceInfos_.Set(dvInfo.udid, dvInfo); readyDevices_.InsertOrAssign(dvInfo.uuid, std::make_pair(DeviceState::DEVICE_ONLINE, dvInfo)); + if (dvInfo.osType != OH_OS_TYPE) { + otherDeviceInfos_.Set(dvInfo.networkId, dvInfo); + otherDeviceInfos_.Set(dvInfo.uuid, dvInfo); + otherDeviceInfos_.Set(dvInfo.udid, dvInfo); + } break; } case DeviceChangeType::DEVICE_OFFLINE: { @@ -333,6 +340,11 @@ void DeviceManagerAdapter::SaveDeviceInfo(const DeviceInfo &dvInfo, const Device deviceInfos_.Delete(dvInfo.uuid); deviceInfos_.Delete(dvInfo.udid); readyDevices_.Erase(dvInfo.uuid); + if (dvInfo.osType != OH_OS_TYPE) { + otherDeviceInfos_.Delete(dvInfo.networkId); + otherDeviceInfos_.Delete(dvInfo.uuid); + otherDeviceInfos_.Delete(dvInfo.udid); + } break; } default: { @@ -409,7 +421,7 @@ bool DeviceManagerAdapter::IsOHOSType(const std::string &id) int32_t DeviceManagerAdapter::GetAuthType(const std::string &id) { DeviceInfo dvInfo; - if (!deviceInfos_.Get(id, dvInfo)) { + if (!otherDeviceInfos_.Get(id, dvInfo) && !deviceInfos_.Get(id, dvInfo)) { InitDeviceInfo(); deviceInfos_.Get(id, dvInfo); } @@ -434,7 +446,7 @@ DeviceInfo DeviceManagerAdapter::GetDeviceInfoFromCache(const std::string &id) deviceInfos_.Get(id, dvInfo); } if (dvInfo.uuid.empty()) { - ZLOGE("invalid id:%{public}s", KvStoreUtils::ToBeAnonymous(id).c_str()); + ZLOGE("invalid id:%{public}s", Anonymous::Change(id).c_str()); } return dvInfo; } @@ -451,7 +463,7 @@ void DeviceManagerAdapter::InitDeviceInfo(bool onlyCache) for (const auto &info : dvInfos) { if (info.networkId.empty() || info.uuid.empty() || info.udid.empty()) { ZLOGE("networkId:%{public}s, uuid:%{public}d, udid:%{public}d", - KvStoreUtils::ToBeAnonymous(info.networkId).c_str(), info.uuid.empty(), info.udid.empty()); + Anonymous::Change(info.networkId).c_str(), info.uuid.empty(), info.udid.empty()); continue; } deviceInfos_.Set(info.networkId, info); @@ -487,7 +499,8 @@ DeviceInfo DeviceManagerAdapter::GetLocalDeviceInfo() return {}; } ZLOGI("[LocalDevice] uuid:%{public}s, name:%{public}s, type:%{public}d, osType:%{public}d", - KvStoreUtils::ToBeAnonymous(uuid).c_str(), info.deviceName, info.deviceTypeId, deviceExtraInfo.OS_TYPE); + Anonymous::Change(uuid).c_str(), Anonymous::Change(info.deviceName).c_str(), info.deviceTypeId, + deviceExtraInfo.OS_TYPE); return { std::move(uuid), std::move(udid), std::move(networkId), std::string(info.deviceName), info.deviceTypeId, deviceExtraInfo.OS_TYPE, static_cast(info.authForm) }; } @@ -507,9 +520,12 @@ std::string DeviceManagerAdapter::GetUuidByNetworkId(const std::string &networkI std::string uuid; auto ret = DeviceManager::GetInstance().GetUuidByNetworkId(PKG_NAME, networkId, uuid); if (ret != DM_OK || uuid.empty()) { - ZLOGE("failed, result:%{public}d, networkId:%{public}s", ret, KvStoreUtils::ToBeAnonymous(networkId).c_str()); + ZLOGE("failed, result:%{public}d, networkId:%{public}s", ret, Anonymous::Change(networkId).c_str()); return ""; } + dvInfo.uuid = uuid; + dvInfo.networkId = networkId; + deviceInfos_.Set(uuid, dvInfo); return uuid; } @@ -528,7 +544,7 @@ std::string DeviceManagerAdapter::GetUdidByNetworkId(const std::string &networkI std::string udid; auto ret = DeviceManager::GetInstance().GetUdidByNetworkId(PKG_NAME, networkId, udid); if (ret != DM_OK || udid.empty()) { - ZLOGE("failed, result:%{public}d, networkId:%{public}s", ret, KvStoreUtils::ToBeAnonymous(networkId).c_str()); + ZLOGE("failed, result:%{public}d, networkId:%{public}s", ret, Anonymous::Change(networkId).c_str()); return ""; } return udid; diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/process_communicator_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/process_communicator_impl.cpp index 5d7edbdd..4eedaa7b 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/process_communicator_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/process_communicator_impl.cpp @@ -143,9 +143,10 @@ DBStatus ProcessCommunicatorImpl::SendData(const DeviceInfos &dstDevInfo, const uint32_t totalLength) { PipeInfo pi = {thisProcessLabel_, ""}; - const DataInfo dataInfo = { const_cast(data), length}; - DeviceId destination; - destination.deviceId = dstDevInfo.identifier; + ExtraDataInfo extraInfo = { .userId = dstDevInfo.callee.userId, .appId = dstDevInfo.callee.appId, + .storeId = dstDevInfo.callee.storeId }; + DataInfo dataInfo = { .data = const_cast(data), .length = length, .extraInfo = extraInfo }; + DeviceId destination = { .deviceId = dstDevInfo.identifier }; auto [errCode, softBusErrCode] = CommunicationProvider::GetInstance().SendData(pi, destination, dataInfo, totalLength); if (errCode == Status::RATE_LIMIT) { @@ -251,7 +252,7 @@ std::shared_ptr ProcessCommunicatorImpl::GetExtendHeaderHand return {}; } -DBStatus ProcessCommunicatorImpl::GetDataHeadInfo(const uint8_t *data, uint32_t totalLen, uint32_t &headLength) +DBStatus ProcessCommunicatorImpl::GetDataHeadInfo(DataHeadInfo dataHeadInfo, uint32_t &headLength) { if (routeHeadHandlerCreator_ == nullptr) { ZLOGE("header handler creator not registered"); @@ -262,16 +263,16 @@ DBStatus ProcessCommunicatorImpl::GetDataHeadInfo(const uint8_t *data, uint32_t ZLOGE("failed to get header handler"); return DBStatus::DB_ERROR; } - auto ret = handler->ParseHeadDataLen(data, totalLen, headLength); + auto ret = handler->ParseHeadDataLen(dataHeadInfo.data, dataHeadInfo.totalLen, headLength, dataHeadInfo.device); if (!ret) { - ZLOGE("illegal head format, dataLen:%{public}u, headLength:%{public}u", totalLen, headLength); + ZLOGE("illegal head format, dataLen:%{public}u, headLength:%{public}u, device:%{public}s", + dataHeadInfo.totalLen, headLength, Anonymous::Change(dataHeadInfo.device).c_str()); return DBStatus::INVALID_FORMAT; } return DBStatus::OK; } -DBStatus ProcessCommunicatorImpl::GetDataUserInfo(const uint8_t *data, uint32_t totalLen, const std::string &label, - std::vector &userInfos) +DBStatus ProcessCommunicatorImpl::GetDataUserInfo(DataUserInfo dataUserInfo, std::vector &userInfos) { if (routeHeadHandlerCreator_ == nullptr) { ZLOGE("header handler creator not registered"); @@ -282,9 +283,11 @@ DBStatus ProcessCommunicatorImpl::GetDataUserInfo(const uint8_t *data, uint32_t ZLOGE("failed to get header handler"); return DBStatus::DB_ERROR; } - auto ret = handler->ParseHeadDataUser(data, totalLen, label, userInfos); + auto ret = handler->ParseHeadDataUser(dataUserInfo.data, dataUserInfo.totalLen, dataUserInfo.label, userInfos); if (!ret) { - ZLOGD("illegal head format, dataLen:%{public}u, label:%{public}s", totalLen, Anonymous::Change(label).c_str()); + ZLOGE("illegal head format, dataLen:%{public}u, label:%{public}s, device:%{public}s", + dataUserInfo.totalLen, Anonymous::Change(dataUserInfo.label).c_str(), + Anonymous::Change(dataUserInfo.device).c_str()); return DBStatus::INVALID_FORMAT; } if (userInfos.empty()) { @@ -295,10 +298,10 @@ DBStatus ProcessCommunicatorImpl::GetDataUserInfo(const uint8_t *data, uint32_t return DBStatus::OK; } -Status ProcessCommunicatorImpl::ReuseConnect(const DeviceId &deviceId) +Status ProcessCommunicatorImpl::ReuseConnect(const DeviceId &deviceId, const ExtraDataInfo &extraInfo) { PipeInfo pi = {thisProcessLabel_, ""}; - return CommunicationProvider::GetInstance().ReuseConnect(pi, deviceId); + return CommunicationProvider::GetInstance().ReuseConnect(pi, deviceId, extraInfo); } } // namespace AppDistributedKv } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h index 08c57281..637df501 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h @@ -15,6 +15,7 @@ #ifndef DISTRIBUTEDDATAFWK_SRC_SOFTBUS_ADAPTER_H #define DISTRIBUTEDDATAFWK_SRC_SOFTBUS_ADAPTER_H + #include #include #include @@ -28,23 +29,24 @@ #include "app_data_change_listener.h" #include "app_device_change_listener.h" #include "block_data.h" +#include "executor_pool.h" #include "socket.h" -#include "softbus_bus_center.h" #include "softbus_client.h" + namespace OHOS { namespace AppDistributedKv { -class SoftBusAdapter : public AppDistributedKv::AppDeviceChangeListener { +class SoftBusAdapter { public: - SoftBusAdapter(); - ~SoftBusAdapter(); - static std::shared_ptr GetInstance(); - struct ServerSocketInfo { std::string name; /**< Peer socket name */ std::string networkId; /**< Peer network ID */ std::string pkgName; /**< Peer package name */ }; + SoftBusAdapter(); + ~SoftBusAdapter(); + static std::shared_ptr GetInstance(); + // add DataChangeListener to watch data change; Status StartWatchDataChange(const AppDataChangeListener *observer, const PipeInfo &pipeInfo); @@ -81,26 +83,24 @@ public: uint32_t GetMtuSize(const DeviceId &deviceId); uint32_t GetTimeout(const DeviceId &deviceId); - void OnDeviceChanged(const AppDistributedKv::DeviceInfo &info, - const AppDistributedKv::DeviceChangeType &type) const override; - - Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId); + Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, const ExtraDataInfo &extraInfo); private: using Time = std::chrono::steady_clock::time_point; using Duration = std::chrono::steady_clock::duration; using Task = ExecutorPool::Task; + std::string DelConnect(int32_t socket, bool isForce); void StartCloseSessionTask(const std::string &deviceId); Task GetCloseSessionTask(); bool CloseSession(const std::string &networkId); void GetExpireTime(std::shared_ptr &conn); std::pair OpenConnect(const std::shared_ptr &conn, const DeviceId &deviceId); - std::shared_ptr GetConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, uint32_t qosType); - static constexpr const char *PKG_NAME = "distributeddata-default"; + bool ConfigSessionAccessInfo(const ExtraDataInfo &extraInfo, SessionAccessInfo &sessionAccessInfo); + std::shared_ptr GetConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, + const ExtraDataInfo &extraInfo); + static constexpr Time INVALID_NEXT = std::chrono::steady_clock::time_point::max(); - static constexpr uint32_t QOS_COUNT = 3; - static constexpr QosTV Qos[QOS_COUNT] = { { .qos = QOS_TYPE_MIN_BW, .value = 64 * 1024 }, - { .qos = QOS_TYPE_MAX_LATENCY, .value = 15000 }, { .qos = QOS_TYPE_MIN_LATENCY, .value = 1600 } }; + static std::shared_ptr instance_; ConcurrentMap dataChangeListeners_{}; ConcurrentMap>> connects_; diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter_standard.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter_standard.cpp index 6fbbcb80..c0a5a6d8 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter_standard.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter_standard.cpp @@ -12,37 +12,42 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include -#include -#include +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "SoftBusAdapter" + +#include "softbus_adapter.h" +#include "accesstoken_kit.h" +#include "account/account_delegate.h" #include "communication/connect_manager.h" #include "communicator_context.h" #include "data_level.h" #include "device_manager_adapter.h" -#include "dfx/dfx_types.h" -#include "dfx/reporter.h" -#include "kvstore_utils.h" #include "log_print.h" -#include "securec.h" -#include "session.h" -#include "softbus_adapter.h" -#include "softbus_bus_center.h" +#include "metadata/appid_meta_data.h" +#include "metadata/meta_data_manager.h" +#include "metadata/store_meta_data.h" #include "softbus_error_code.h" -#ifdef LOG_TAG -#undef LOG_TAG -#endif -#define LOG_TAG "SoftBusAdapter" +#include "trans_type.h" +#include "utils/anonymous.h" namespace OHOS { namespace AppDistributedKv { -using Context = DistributedData::CommunicatorContext; -constexpr uint32_t DEFAULT_MTU_SIZE = 4096 * 1024u; -constexpr uint32_t DEFAULT_TIMEOUT = 30 * 1000; using namespace std; -using namespace OHOS::DistributedDataDfx; using namespace OHOS::DistributedKv; -using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; +using namespace OHOS::DistributedData; +using namespace OHOS::Security::AccessToken; + +static constexpr const char *DEFAULT_USER = "default"; +static constexpr const char *SYSTEM_USER = "0"; +static constexpr const char *PKG_NAME = "distributeddata-default"; +static constexpr uint32_t DEFAULT_MTU_SIZE = 4096 * 1024u; +static constexpr uint32_t DEFAULT_TIMEOUT = 30 * 1000; +static constexpr uint32_t QOS_COUNT = 3; +static constexpr QosTV Qos[QOS_COUNT] = { { .qos = QOS_TYPE_MIN_BW, .value = 64 * 1024 }, + { .qos = QOS_TYPE_MAX_LATENCY, .value = 15000 }, { .qos = QOS_TYPE_MIN_LATENCY, .value = 1600 } }; class AppDataListenerWrap { public: @@ -55,12 +60,16 @@ public: static void OnServerBind(int32_t socket, PeerSocketInfo info); static void OnServerShutdown(int32_t socket, ShutdownReason reason); static void OnServerBytesReceived(int32_t socket, const void *data, uint32_t dataLen); + static bool OnServerAccessCheck(int32_t socket, PeerSocketInfo info, SocketAccessInfo *peerInfo, + SocketAccessInfo *localInfo); private: // notify all listeners when received message static void NotifyDataListeners(const uint8_t *data, const int size, const std::string &deviceId, const PipeInfo &pipeInfo); static std::string GetPipeId(const std::string &name); + static std::pair LoadMetaData(const std::string &bundleName, const std::string &storeId, + int32_t userId); static SoftBusAdapter *softBusAdapter_; }; @@ -69,7 +78,7 @@ SoftBusAdapter *AppDataListenerWrap::softBusAdapter_; std::shared_ptr SoftBusAdapter::instance_; namespace { -void OnDataLevelChanged(const char *networkId, const DataLevel dataLevel) +void OnDataLevelChanged(const char* networkId, const DataLevel dataLevel) { if (networkId == nullptr) { return; @@ -80,7 +89,7 @@ void OnDataLevelChanged(const char *networkId, const DataLevel dataLevel) .switches = dataLevel.switchLevel, .switchesLen = dataLevel.switchLength, }; - auto uuid = DmAdapter::GetInstance().GetUuidByNetworkId(networkId); + auto uuid = DeviceManagerAdapter::GetInstance().GetUuidByNetworkId(networkId); SoftBusAdapter::GetInstance()->OnBroadcast({ uuid }, std::move(level)); } @@ -88,6 +97,7 @@ IDataLevelCb g_callback = { .onDataLevelChanged = OnDataLevelChanged, }; } // namespace + SoftBusAdapter::SoftBusAdapter() { ZLOGI("begin"); @@ -102,23 +112,20 @@ SoftBusAdapter::SoftBusAdapter() serverListener_.OnShutdown = AppDataListenerWrap::OnServerShutdown; serverListener_.OnBytes = AppDataListenerWrap::OnServerBytesReceived; serverListener_.OnMessage = AppDataListenerWrap::OnServerBytesReceived; + serverListener_.OnNegotiate2 = AppDataListenerWrap::OnServerAccessCheck; - auto status = DmAdapter::GetInstance().StartWatchDeviceChange(this, { "softBusAdapter" }); - if (status != Status::SUCCESS) { - ZLOGW("register device change failed, status:%d", static_cast(status)); - } - - Context::GetInstance().SetSessionListener([this](const std::string &deviceId) { + CommunicatorContext::GetInstance().SetSessionListener([this](const std::string &deviceId) { StartCloseSessionTask(deviceId); }); ConnectManager::GetInstance()->RegisterCloseSessionTask([this](const std::string &networkId) { return CloseSession(networkId); }); - ConnectManager::GetInstance()->RegisterSessionCloseListener("context", [](const std::string &networkId) { - auto uuid = DmAdapter::GetInstance().GetUuidByNetworkId(networkId); - Context::GetInstance().NotifySessionClose(uuid); - }); + ConnectManager::GetInstance()->RegisterSessionCloseListener("CommunicatorContext", + [](const std::string &networkId) { + auto uuid = DeviceManagerAdapter::GetInstance().GetUuidByNetworkId(networkId); + CommunicatorContext::GetInstance().NotifySessionClose(uuid); + }); ConnectManager::GetInstance()->OnStart(); } @@ -174,7 +181,7 @@ void SoftBusAdapter::GetExpireTime(std::shared_ptr &conn) auto expireTime = conn->GetExpireTime() > now ? conn->GetExpireTime() : now; lock_guard lock(taskMutex_); if (taskId_ != ExecutorPool::INVALID_TASK_ID && expireTime < next_) { - taskId_ = Context::GetInstance().GetThreadPool()->Reset(taskId_, expireTime - now); + taskId_ = CommunicatorContext::GetInstance().GetThreadPool()->Reset(taskId_, expireTime - now); next_ = expireTime; } } @@ -182,9 +189,7 @@ void SoftBusAdapter::GetExpireTime(std::shared_ptr &conn) std::pair SoftBusAdapter::SendData(const PipeInfo &pipeInfo, const DeviceId &deviceId, const DataInfo &dataInfo, uint32_t length, const MessageInfo &info) { - bool isOHOSType = DmAdapter::GetInstance().IsOHOSType(deviceId.deviceId); - uint32_t qosType = isOHOSType ? SoftBusClient::QOS_HML : SoftBusClient::QOS_BR; - std::shared_ptr conn = GetConnect(pipeInfo, deviceId, qosType); + std::shared_ptr conn = GetConnect(pipeInfo, deviceId, dataInfo.extraInfo); if (conn == nullptr) { return std::make_pair(Status::ERROR, 0); } @@ -195,7 +200,7 @@ std::pair SoftBusAdapter::SendData(const PipeInfo &pipeInfo, co if (status != Status::SUCCESS) { return OpenConnect(conn, deviceId); } - status = conn->SendData(dataInfo, &clientListener_); + status = conn->SendData(dataInfo); if ((status != Status::NETWORK_ERROR) && (status != Status::RATE_LIMIT)) { GetExpireTime(conn); } @@ -203,12 +208,65 @@ std::pair SoftBusAdapter::SendData(const PipeInfo &pipeInfo, co return std::make_pair(status, errCode); } +bool SoftBusAdapter::ConfigSessionAccessInfo(const ExtraDataInfo &extraInfo, SessionAccessInfo &sessionAccessInfo) +{ + if (extraInfo.userId.empty() || (extraInfo.bundleName.empty() && extraInfo.appId.empty()) || + extraInfo.storeId.empty()) { + ZLOGE("extraInfo is empty, userId:%{public}s, bundleName:%{public}s, appId:%{public}s, storeId:%{public}s", + extraInfo.userId.c_str(), extraInfo.bundleName.c_str(), extraInfo.appId.c_str(), + Anonymous::Change(extraInfo.storeId).c_str()); + return false; + } + AppIDMetaData appIdMeta; + if (extraInfo.bundleName.empty() && !MetaDataManager::GetInstance().LoadMeta(extraInfo.appId, appIdMeta, true)) { + ZLOGE("load appIdMeta fail, appId:%{public}s", extraInfo.appId.c_str()); + return false; + } + StoreMetaData metaData; + metaData.deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + metaData.user = extraInfo.userId == DEFAULT_USER ? SYSTEM_USER : extraInfo.userId; + metaData.bundleName = extraInfo.bundleName.empty() ? appIdMeta.bundleName : extraInfo.bundleName; + metaData.storeId = extraInfo.storeId; + if ((extraInfo.tokenId == 0) && !MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)) { + ZLOGE("get meta data fail, metaKey:%{public}s", Anonymous::Change(metaData.GetKeyWithoutPath()).c_str()); + return false; + } + sessionAccessInfo.bundleName = metaData.bundleName; + sessionAccessInfo.storeId = metaData.storeId; + sessionAccessInfo.tokenId = (extraInfo.tokenId != 0) ? extraInfo.tokenId : metaData.tokenId; + int foregroundUserId = 0; + auto ret = AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + if (!ret) { + return false; + } + sessionAccessInfo.userId = foregroundUserId; + auto accountId = AccountDelegate::GetInstance()->GetCurrentAccountId(); + if (accountId.empty()) { + return false; + } + sessionAccessInfo.accountId = accountId; + return true; +} + std::shared_ptr SoftBusAdapter::GetConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, - uint32_t qosType) + const ExtraDataInfo &extraInfo) { + std::string networkId = DeviceManagerAdapter::GetInstance().ToNetworkID(deviceId.deviceId); + if (networkId.empty()) { + ZLOGE("networkId is empty, deviceId:%{public}s", Anonymous::Change(deviceId.deviceId).c_str()); + return nullptr; + } std::shared_ptr conn; + auto isOHType = DeviceManagerAdapter::GetInstance().IsOHOSType(deviceId.deviceId); + SessionAccessInfo sessionAccessInfo = { .isOHType = isOHType }; + if (isOHType && !ConfigSessionAccessInfo(extraInfo, sessionAccessInfo)) { + ZLOGE("peer device is not oh device or config accessInfo fail, deviceId:%{public}s", + Anonymous::Change(deviceId.deviceId).c_str()); + return nullptr; + } + uint32_t qosType = isOHType ? SoftBusClient::QOS_HML : SoftBusClient::QOS_BR; connects_.Compute(deviceId.deviceId, - [&pipeInfo, &deviceId, &conn, qosType](const auto &key, + [&pipeInfo, &deviceId, &sessionAccessInfo, &conn, qosType, &networkId](const auto &key, std::vector> &connects) -> bool { for (auto &connect : connects) { if (connect == nullptr) { @@ -219,7 +277,7 @@ std::shared_ptr SoftBusAdapter::GetConnect(const PipeInfo &pipeIn return true; } } - auto connect = std::make_shared(pipeInfo, deviceId, qosType); + auto connect = std::make_shared(pipeInfo, deviceId, networkId, qosType, sessionAccessInfo); connects.emplace_back(connect); conn = connect; return true; @@ -230,21 +288,32 @@ std::shared_ptr SoftBusAdapter::GetConnect(const PipeInfo &pipeIn std::pair SoftBusAdapter::OpenConnect(const std::shared_ptr &conn, const DeviceId &deviceId) { - auto task = [this, connect = std::weak_ptr(conn)]() { + auto networkId = DeviceManagerAdapter::GetInstance().ToNetworkID(deviceId.deviceId); + if (conn != nullptr) { + auto oldNetworkId = conn->GetNetworkId(); + if (networkId != oldNetworkId) { + ZLOGI("peer networkId changed, %{public}s->%{public}s", Anonymous::Change(oldNetworkId).c_str(), + Anonymous::Change(networkId).c_str()); + conn->UpdateNetworkId(networkId); + } + } + auto applyTask = [deviceId](int32_t errcode) { + CommunicatorContext::GetInstance().NotifySessionReady(deviceId.deviceId, errcode); + }; + auto connectTask = [this, connect = std::weak_ptr(conn)]() { auto conn = connect.lock(); if (conn != nullptr) { conn->OpenConnect(&clientListener_); } }; - auto networkId = DmAdapter::GetInstance().GetDeviceInfo(deviceId.deviceId).networkId; - ConnectManager::GetInstance()->ApplyConnect(networkId, task); + ConnectManager::GetInstance()->ApplyConnect(networkId, applyTask, connectTask); return std::make_pair(Status::RATE_LIMIT, 0); } void SoftBusAdapter::StartCloseSessionTask(const std::string &deviceId) { std::shared_ptr conn; - bool isOHOSType = DmAdapter::GetInstance().IsOHOSType(deviceId); + bool isOHOSType = DeviceManagerAdapter::GetInstance().IsOHOSType(deviceId); uint32_t qosType = isOHOSType ? SoftBusClient::QOS_HML : SoftBusClient::QOS_BR; auto connects = connects_.Find(deviceId); if (!connects.first) { @@ -263,8 +332,8 @@ void SoftBusAdapter::StartCloseSessionTask(const std::string &deviceId) auto expireTime = conn->GetExpireTime() > now ? conn->GetExpireTime() : now; lock_guard lock(taskMutex_); if (taskId_ == ExecutorPool::INVALID_TASK_ID) { - ZLOGI("Start close session, deviceId:%{public}s", KvStoreUtils::ToBeAnonymous(deviceId).c_str()); - taskId_ = Context::GetInstance().GetThreadPool()->Schedule(expireTime - now, GetCloseSessionTask()); + ZLOGI("Start close session, deviceId:%{public}s", Anonymous::Change(deviceId).c_str()); + taskId_ = CommunicatorContext::GetInstance().GetThreadPool()->Schedule(expireTime - now, GetCloseSessionTask()); next_ = expireTime; } } @@ -293,7 +362,7 @@ SoftBusAdapter::Task SoftBusAdapter::GetCloseSessionTask() }); connects_.EraseIf([](const auto &key, const auto &conn) -> bool { if (conn.empty()) { - ConnectManager::GetInstance()->OnSessionClose(DmAdapter::GetInstance().GetDeviceInfo(key).networkId); + ConnectManager::GetInstance()->OnSessionClose(DeviceManagerAdapter::GetInstance().ToNetworkID(key)); } return conn.empty(); }); @@ -315,9 +384,8 @@ SoftBusAdapter::Task SoftBusAdapter::GetCloseSessionTask() taskId_ = ExecutorPool::INVALID_TASK_ID; return; } - taskId_ = - Context::GetInstance().GetThreadPool()->Schedule(next > now ? next - now : ExecutorPool::INVALID_DELAY, - GetCloseSessionTask()); + taskId_ = CommunicatorContext::GetInstance().GetThreadPool()->Schedule( + next > now ? next - now : ExecutorPool::INVALID_DELAY, GetCloseSessionTask()); next_ = next; }; } @@ -331,8 +399,8 @@ uint32_t SoftBusAdapter::GetMtuSize(const DeviceId &deviceId) if (conn == nullptr) { continue; } - if (mtu < conn->GetMtuSize()) { - mtu = conn->GetMtuSize(); + if (mtu < conn->GetMtuBuffer()) { + mtu = conn->GetMtuBuffer(); } } if (mtu != 0) { @@ -353,26 +421,27 @@ std::string SoftBusAdapter::DelConnect(int32_t socket, bool isForce) std::string name; std::set closedConnect; connects_.EraseIf([socket, isForce, &name, &closedConnect](const auto &deviceId, auto &connects) -> bool { - if (!isForce && DmAdapter::GetInstance().IsOHOSType(deviceId)) { + if (!isForce && DeviceManagerAdapter::GetInstance().IsOHOSType(deviceId)) { return false; } + std::string networkId; for (auto iter = connects.begin(); iter != connects.end();) { if (*iter != nullptr && **iter == socket) { name += deviceId; name += " "; + networkId = (*iter)->GetNetworkId(); iter = connects.erase(iter); } else { iter++; } } - if (connects.empty()) { - closedConnect.insert(deviceId); + if (connects.empty() && !networkId.empty()) { + closedConnect.insert(std::move(networkId)); return true; } return false; }); - for (const auto &deviceId : closedConnect) { - auto networkId = DmAdapter::GetInstance().GetDeviceInfo(deviceId).networkId; + for (const auto &networkId : closedConnect) { ConnectManager::GetInstance()->OnSessionClose(networkId); } return name; @@ -387,13 +456,13 @@ bool SoftBusAdapter::IsSameStartedOnPeer(const struct PipeInfo &pipeInfo, __attribute__((unused)) const struct DeviceId &peer) { ZLOGI("pipeInfo:%{public}s deviceId:%{public}s", pipeInfo.pipeId.c_str(), - KvStoreUtils::ToBeAnonymous(peer.deviceId).c_str()); + Anonymous::Change(peer.deviceId).c_str()); return true; } void SoftBusAdapter::SetMessageTransFlag(const PipeInfo &pipeInfo, bool flag) { - ZLOGI("pipeInfo: %s flag: %d", pipeInfo.pipeId.c_str(), flag); + ZLOGI("pipeInfo:%{public}s, flag:%{public}d", pipeInfo.pipeId.c_str(), flag); flag_ = flag; } @@ -423,11 +492,9 @@ void SoftBusAdapter::NotifyDataListeners(const uint8_t *data, int size, const st auto ret = dataChangeListeners_.ComputeIfPresent(pipeInfo.pipeId, [&data, &size, &deviceId, &pipeInfo](const auto &key, const AppDataChangeListener *&value) { ZLOGD("ready to notify, pipeName:%{public}s, deviceId:%{public}s.", pipeInfo.pipeId.c_str(), - KvStoreUtils::ToBeAnonymous(deviceId).c_str()); - DeviceInfo deviceInfo = DmAdapter::GetInstance().GetDeviceInfo(deviceId); + Anonymous::Change(deviceId).c_str()); + DeviceInfo deviceInfo = DeviceManagerAdapter::GetInstance().GetDeviceInfo(deviceId); value->OnMessage(deviceInfo, data, size, pipeInfo); - TrafficStat ts{ pipeInfo.pipeId, deviceId, 0, size }; - Reporter::GetInstance()->TrafficStatistic()->Report(ts); return true; }); if (!ret) { @@ -447,14 +514,14 @@ Status SoftBusAdapter::Broadcast(const PipeInfo &pipeInfo, const LevelInfo &leve if (status == SOFTBUS_FUNC_NOT_SUPPORT) { return Status::NOT_SUPPORT_BROADCAST; } - return status ? Status::ERROR : Status::SUCCESS; + return status != SOFTBUS_OK ? Status::ERROR : Status::SUCCESS; } void SoftBusAdapter::OnBroadcast(const DeviceId &device, const LevelInfo &levelInfo) { - ZLOGI("device:%{public}s", KvStoreUtils::ToBeAnonymous(device.deviceId).c_str()); + ZLOGI("device:%{public}s", Anonymous::Change(device.deviceId).c_str()); if (!onBroadcast_) { - ZLOGW("no listener device:%{public}s", KvStoreUtils::ToBeAnonymous(device.deviceId).c_str()); + ZLOGW("no listener device:%{public}s", Anonymous::Change(device.deviceId).c_str()); return; } onBroadcast_(device.deviceId, levelInfo); @@ -481,7 +548,7 @@ void AppDataListenerWrap::OnClientShutdown(int32_t socket, ShutdownReason reason // when the local close the session, this callback function will not be triggered; // when the current function is called, soft bus has released the session resource, only connId is valid; std::string name = softBusAdapter_->OnClientShutdown(socket); - ZLOGI("[shutdown] socket:%{public}d, name:%{public}s", socket, KvStoreUtils::ToBeAnonymous(name).c_str()); + ZLOGI("[shutdown] socket:%{public}d, name:%{public}s", socket, Anonymous::Change(name).c_str()); } void AppDataListenerWrap::OnClientBytesReceived(int32_t socket, const void *data, uint32_t dataLen) {} @@ -490,17 +557,17 @@ void AppDataListenerWrap::OnClientSocketChanged(int32_t socket, QoSEvent eventId { if (eventId == QoSEvent::QOS_SATISFIED && qos != nullptr && qos[0].qos == QOS_TYPE_MIN_BW && qosCount == 1) { auto name = softBusAdapter_->OnClientShutdown(socket, false); - ZLOGI("[SocketChanged] socket:%{public}d, name:%{public}s", socket, KvStoreUtils::ToBeAnonymous(name).c_str()); + ZLOGI("[SocketChanged] socket:%{public}d, name:%{public}s", socket, Anonymous::Change(name).c_str()); } } void AppDataListenerWrap::OnServerBind(int32_t socket, PeerSocketInfo info) { softBusAdapter_->OnBind(socket, info); - std::string peerDevUuid = DmAdapter::GetInstance().GetUuidByNetworkId(std::string(info.networkId)); + std::string peerDevUuid = DeviceManagerAdapter::GetInstance().GetUuidByNetworkId(std::string(info.networkId)); ZLOGI("[OnServerBind] socket:%{public}d, peer name:%{public}s, peer devId:%{public}s", socket, info.name, - KvStoreUtils::ToBeAnonymous(peerDevUuid).c_str()); + Anonymous::Change(peerDevUuid).c_str()); } void AppDataListenerWrap::OnServerShutdown(int32_t socket, ShutdownReason reason) @@ -516,9 +583,9 @@ void AppDataListenerWrap::OnServerBytesReceived(int32_t socket, const void *data ZLOGE("Get peer socket info failed, socket id %{public}d", socket); return; }; - std::string peerDevUuid = DmAdapter::GetInstance().GetUuidByNetworkId(std::string(info.networkId)); + std::string peerDevUuid = DeviceManagerAdapter::GetInstance().GetUuidByNetworkId(std::string(info.networkId)); ZLOGD("[OnBytesReceived] socket:%{public}d, peer name:%{public}s, peer devId:%{public}s, data len:%{public}u", - socket, info.name.c_str(), KvStoreUtils::ToBeAnonymous(peerDevUuid).c_str(), dataLen); + socket, info.name.c_str(), Anonymous::Change(peerDevUuid).c_str(), dataLen); std::string pipeId = GetPipeId(info.name); if (pipeId.empty()) { @@ -529,6 +596,69 @@ void AppDataListenerWrap::OnServerBytesReceived(int32_t socket, const void *data NotifyDataListeners(reinterpret_cast(data), dataLen, peerDevUuid, { pipeId, "" }); } +std::pair AppDataListenerWrap::LoadMetaData(const std::string &bundleName, + const std::string &storeId, int32_t userId) +{ + StoreMetaData metaData; + metaData.deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + metaData.bundleName = bundleName; + metaData.storeId = storeId; + metaData.user = std::to_string(userId); + auto ret = MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData); + if (!ret) { + metaData.user = SYSTEM_USER; + ret = MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData); + } + return { ret, metaData }; +} + +bool AppDataListenerWrap::OnServerAccessCheck(int32_t socket, PeerSocketInfo info, SocketAccessInfo *peerInfo, + SocketAccessInfo *localInfo) +{ + ZLOGI("receive bind request, socket:%{public}d", socket); + if (peerInfo == nullptr || localInfo == nullptr) { + ZLOGE("peerInfo or localInfo is nullptr, peerInfo:%{public}d, localInfo:%{public}d", peerInfo == nullptr, + localInfo == nullptr); + return false; + } + SoftBusClient::AccessExtraInfo peerExtraInfo; + if (!DistributedData::Serializable::Unmarshall(peerInfo->extraAccessInfo, peerExtraInfo)) { + ZLOGE("Unmarshall failed, peer extraAccessInfo:%{public}s", peerInfo->extraAccessInfo); + return false; + } + int foregroundUserId = 0; + if (!AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId)) { + return false; + } + localInfo->userId = foregroundUserId; + auto resultPair = LoadMetaData(peerExtraInfo.bundleName, peerExtraInfo.storeId, foregroundUserId); + if (!resultPair.first) { + ZLOGE("local device has no store, bundleName:%{public}s", peerExtraInfo.bundleName.c_str()); + return false; + } + localInfo->localTokenId = resultPair.second.tokenId; + auto type = AccessTokenKit::GetTokenTypeFlag(resultPair.second.tokenId); + if (type == TOKEN_NATIVE || type == TOKEN_SHELL) { + ZLOGW("this is system service sync, bundleName:%{public}s", peerExtraInfo.bundleName.c_str()); + return true; + } + AclParams aclParams; + aclParams.accCaller.bundleName = peerExtraInfo.bundleName; + aclParams.accCaller.accountId = AccountDelegate::GetInstance()->GetCurrentAccountId(); + aclParams.accCaller.userId = foregroundUserId; + aclParams.accCaller.networkId = DeviceManagerAdapter::GetInstance().GetLocalDevice().networkId; + aclParams.accCallee.accountId = peerExtraInfo.accountId; + aclParams.accCallee.userId = peerInfo->userId; + aclParams.accCallee.networkId = std::string(info.networkId); + bool accessFlag = false; + if (resultPair.second.authType == AuthType::IDENTICAL_ACCOUNT) { + accessFlag = DeviceManagerAdapter::GetInstance().IsSameAccount(aclParams.accCaller, aclParams.accCallee); + } else { + accessFlag = DeviceManagerAdapter::GetInstance().CheckAccessControl(aclParams.accCaller, aclParams.accCallee); + } + return accessFlag; +} + std::string AppDataListenerWrap::GetPipeId(const std::string &name) { auto pos = name.find('_'); @@ -557,9 +687,9 @@ bool SoftBusAdapter::GetPeerSocketInfo(int32_t socket, ServerSocketInfo &info) void SoftBusAdapter::OnBind(int32_t socket, PeerSocketInfo info) { ServerSocketInfo socketInfo; - socketInfo.name = info.name; - socketInfo.networkId = info.networkId; - socketInfo.pkgName = info.pkgName; + socketInfo.name = std::string(info.name); + socketInfo.networkId = std::string(info.networkId); + socketInfo.pkgName = std::string(info.pkgName); peerSocketInfos_.Insert(socket, socketInfo); } @@ -568,15 +698,9 @@ void SoftBusAdapter::OnServerShutdown(int32_t socket) peerSocketInfos_.Erase(socket); } -void SoftBusAdapter::OnDeviceChanged(const AppDistributedKv::DeviceInfo &info, - const AppDistributedKv::DeviceChangeType &type) const -{ - return; -} - bool SoftBusAdapter::CloseSession(const std::string &networkId) { - auto uuid = DmAdapter::GetInstance().GetUuidByNetworkId(networkId); + auto uuid = DeviceManagerAdapter::GetInstance().GetUuidByNetworkId(networkId); auto ret = connects_.Erase(uuid); if (ret != 0) { ConnectManager::GetInstance()->OnSessionClose(networkId); @@ -584,14 +708,13 @@ bool SoftBusAdapter::CloseSession(const std::string &networkId) return ret != 0; } -Status SoftBusAdapter::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId) +Status SoftBusAdapter::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, const ExtraDataInfo &extraInfo) { - bool isOHOSType = DmAdapter::GetInstance().IsOHOSType(deviceId.deviceId); + bool isOHOSType = DeviceManagerAdapter::GetInstance().IsOHOSType(deviceId.deviceId); if (!isOHOSType) { return Status::NOT_SUPPORT; } - uint32_t qosType = SoftBusClient::QOS_HML; - std::shared_ptr conn = GetConnect(pipeInfo, deviceId, qosType); + std::shared_ptr conn = GetConnect(pipeInfo, deviceId, extraInfo); if (conn == nullptr) { return Status::ERROR; } @@ -599,20 +722,21 @@ Status SoftBusAdapter::ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &de if (status != Status::SUCCESS) { return status; } + uint32_t qosType = SoftBusClient::QOS_HML; // Avoid being cleared by scheduled tasks - connects_.Compute(deviceId.deviceId, - [&conn, qosType](const auto &key, std::vector> &connects) -> bool { - for (auto &connect : connects) { - if (connect == nullptr) { - continue; - } - if (connect->GetQoSType() == qosType) { - return true; - } + connects_.Compute(deviceId.deviceId, [&conn, qosType](const auto &key, + std::vector> &connects) -> bool { + for (auto &connect : connects) { + if (connect == nullptr) { + continue; } - connects.emplace_back(conn); - return true; - }); + if (connect->GetQoSType() == qosType) { + return true; + } + } + connects.emplace_back(conn); + return true; + }); StartCloseSessionTask(deviceId.deviceId); return Status::SUCCESS; } diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp index f4451869..67ec7146 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp @@ -14,30 +14,30 @@ */ #define LOG_TAG "SoftBusClient" + #include "softbus_client.h" #include "communicator_context.h" #include "communication/connect_manager.h" -#include "device_manager_adapter.h" #include "inner_socket.h" -#include "kvstore_utils.h" #include "log_print.h" #include "softbus_error_code.h" +#include "utils/anonymous.h" namespace OHOS::AppDistributedKv { using namespace OHOS::DistributedKv; -using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; -using Context = DistributedData::CommunicatorContext; -SoftBusClient::SoftBusClient(const PipeInfo& pipeInfo, const DeviceId& deviceId, uint32_t type) - : type_(type), pipe_(pipeInfo), device_(deviceId) +using namespace OHOS::DistributedData; + +SoftBusClient::SoftBusClient(const PipeInfo& pipeInfo, const DeviceId& deviceId, const std::string& networkId, + uint32_t type, const SessionAccessInfo &accessInfo) : type_(type), pipe_(pipeInfo), device_(deviceId), + networkId_(networkId), accessInfo_(accessInfo) { mtu_ = DEFAULT_MTU_SIZE; } SoftBusClient::~SoftBusClient() { - ZLOGI("Shutdown socket:%{public}d, deviceId:%{public}s", socket_, - KvStoreUtils::ToBeAnonymous(device_.deviceId).c_str()); + ZLOGI("Shutdown socket:%{public}d, deviceId:%{public}s", socket_, Anonymous::Change(device_.deviceId).c_str()); if (socket_ > 0) { Shutdown(socket_); } @@ -53,7 +53,7 @@ bool SoftBusClient::operator==(const std::string &deviceId) const return device_.deviceId == deviceId; } -uint32_t SoftBusClient::GetMtuSize() const +uint32_t SoftBusClient::GetMtuBuffer() const { ZLOGD("get mtu size socket:%{public}d mtu:%{public}d", socket_, mtu_); return mtu_; @@ -64,7 +64,7 @@ uint32_t SoftBusClient::GetTimeout() const return DEFAULT_TIMEOUT; } -Status SoftBusClient::SendData(const DataInfo &dataInfo, const ISocketListener *listener) +Status SoftBusClient::SendData(const DataInfo &dataInfo) { std::lock_guard lock(mutex_); auto result = CheckStatus(); @@ -111,12 +111,16 @@ Status SoftBusClient::OpenConnect(const ISocketListener *listener) return; } ZLOGI("Bind Start, device:%{public}s socket:%{public}d type:%{public}u", - KvStoreUtils::ToBeAnonymous(client->device_.deviceId).c_str(), clientSocket, type); + Anonymous::Change(client->device_.deviceId).c_str(), clientSocket, type); int32_t status = client->Open(clientSocket, type, listener); - Context::GetInstance().NotifySessionReady(client->device_.deviceId, status); + CommunicatorContext::GetInstance().NotifySessionReady(client->device_.deviceId, status); client->isOpening_.store(false); }; - Context::GetInstance().GetThreadPool()->Execute(task); + auto executorPool = CommunicatorContext::GetInstance().GetThreadPool(); + if (executorPool == nullptr) { + return Status::NETWORK_ERROR; + } + executorPool->Execute(task); return Status::RATE_LIMIT; } @@ -125,7 +129,7 @@ int32_t SoftBusClient::CreateSocket() const SocketInfo socketInfo; std::string peerName = pipe_.pipeId; socketInfo.peerName = const_cast(peerName.c_str()); - std::string networkId = DmAdapter::GetInstance().ToNetworkID(device_.deviceId); + auto networkId = GetNetworkId(); socketInfo.peerNetworkId = const_cast(networkId.c_str()); std::string clientName = pipe_.pipeId; socketInfo.name = const_cast(clientName.c_str()); @@ -135,6 +139,29 @@ int32_t SoftBusClient::CreateSocket() const int32_t socket = Socket(socketInfo); if (socket <= 0) { ZLOGE("Create the client Socket:%{public}d failed, peerName:%{public}s", socket, socketInfo.peerName); + return socket; + } + if (accessInfo_.isOHType) { + SocketAccessInfo info; + info.userId = accessInfo_.userId; + info.localTokenId = accessInfo_.tokenId; + AccessExtraInfo extraInfo; + extraInfo.bundleName = accessInfo_.bundleName; + extraInfo.accountId = accessInfo_.accountId; + extraInfo.storeId = accessInfo_.storeId; + std::string extraInfoStr = Serializable::Marshall(extraInfo); + if (extraInfoStr.empty()) { + ZLOGE("Marshall access info fail"); + return INVALID_SOCKET_ID; + } + info.extraAccessInfo = const_cast(extraInfoStr.c_str()); + auto status = SetAccessInfo(socket, info); + if (status != SOFTBUS_OK) { + ZLOGE("SetAccessInfo fail, status:%{public}d, userId:%{public}d, bundleName:%{public}s," + "accountId:%{public}s, storeId:%{public}s", status, info.userId, extraInfo.bundleName.c_str(), + Anonymous::Change(extraInfo.accountId).c_str(), Anonymous::Change(extraInfo.storeId).c_str()); + return INVALID_SOCKET_ID; + } } return socket; } @@ -155,29 +182,31 @@ Status SoftBusClient::CheckStatus() int32_t SoftBusClient::Open(int32_t socket, uint32_t type, const ISocketListener *listener, bool async) { - int32_t status = ::Bind(socket, QOS_INFOS[type % QOS_BUTT], QOS_COUNTS[type % QOS_BUTT], listener); - ZLOGI("Bind %{public}s,session:%{public}s,socketId:%{public}d", - KvStoreUtils::ToBeAnonymous(device_.deviceId).c_str(), pipe_.pipeId.c_str(), socket); - - if (status != 0) { - ZLOGE("[Bind] device:%{public}s socket failed, session:%{public}s,result:%{public}d", - KvStoreUtils::ToBeAnonymous(device_.deviceId).c_str(), pipe_.pipeId.c_str(), status); - ::Shutdown(socket); + auto networkId = GetNetworkId(); + ZLOGI("Bind start, device:%{public}s, networkId:%{public}s, session:%{public}s, socketId:%{public}d", + Anonymous::Change(device_.deviceId).c_str(), Anonymous::Change(networkId).c_str(), + pipe_.pipeId.c_str(), socket); + int32_t status = Bind(socket, QOS_INFOS[type % QOS_BUTT], QOS_COUNTS[type % QOS_BUTT], listener); + if (status != SOFTBUS_OK) { + ZLOGE("Bind fail, device:%{public}s, networkId:%{public}s, socketId:%{public}d, result:%{public}d", + Anonymous::Change(device_.deviceId).c_str(), Anonymous::Change(networkId).c_str(), socket, status); + Shutdown(socket); return status; } - UpdateExpireTime(async); uint32_t mtu = 0; std::tie(status, mtu) = GetMtu(socket); if (status != SOFTBUS_OK) { ZLOGE("GetMtu failed, session:%{public}s, socket:%{public}d, status:%{public}d", pipe_.pipeId.c_str(), socket_, status); - ::Shutdown(socket); + Shutdown(socket); return status; } UpdateBindInfo(socket, mtu, status, async); - ZLOGI("open %{public}s, session:%{public}s success, socket:%{public}d", - KvStoreUtils::ToBeAnonymous(device_.deviceId).c_str(), pipe_.pipeId.c_str(), socket_); - ConnectManager::GetInstance()->OnSessionOpen(DmAdapter::GetInstance().GetDeviceInfo(device_.deviceId).networkId); + expireTime_ = CalcExpireTime(); + ZLOGI("Bind success, device:%{public}s, networkId:%{public}s, session:%{public}s, socketId:%{public}d", + Anonymous::Change(device_.deviceId).c_str(), Anonymous::Change(networkId).c_str(), + pipe_.pipeId.c_str(), socket); + ConnectManager::GetInstance()->OnSessionOpen(networkId); return status; } @@ -192,21 +221,6 @@ int32_t SoftBusClient::GetSocket() const return socket_; } -void SoftBusClient::UpdateExpireTime(bool async) -{ - auto expireTime = CalcExpireTime(); - if (async) { - std::lock_guard lock(mutex_); - if (expireTime > expireTime_) { - expireTime_ = expireTime; - } - } else { - if (expireTime > expireTime_) { - expireTime_ = expireTime; - } - } -} - void SoftBusClient::UpdateBindInfo(int32_t socket, uint32_t mtu, int32_t status, bool async) { if (async) { @@ -224,7 +238,7 @@ void SoftBusClient::UpdateBindInfo(int32_t socket, uint32_t mtu, int32_t status, std::pair SoftBusClient::GetMtu(int32_t socket) { uint32_t mtu = 0; - auto ret = ::GetMtuSize(socket, &mtu); + auto ret = GetMtuSize(socket, &mtu); return { ret, mtu }; } @@ -244,7 +258,7 @@ Status SoftBusClient::ReuseConnect(const ISocketListener *listener) std::lock_guard lock(mutex_); auto checkStatus = CheckStatus(); if (checkStatus == Status::SUCCESS) { - UpdateExpireTime(false); + expireTime_ = CalcExpireTime(); return Status::SUCCESS; } int32_t socket = CreateSocket(); @@ -252,8 +266,20 @@ Status SoftBusClient::ReuseConnect(const ISocketListener *listener) return Status::NETWORK_ERROR; } ZLOGI("Reuse Start, device:%{public}s session:%{public}s socket:%{public}d", - KvStoreUtils::ToBeAnonymous(device_.deviceId).c_str(), pipe_.pipeId.c_str(), socket); + Anonymous::Change(device_.deviceId).c_str(), pipe_.pipeId.c_str(), socket); int32_t status = Open(socket, QOS_REUSE, listener, false); return status == SOFTBUS_OK ? Status::SUCCESS : Status::NETWORK_ERROR; } + +std::string SoftBusClient::GetNetworkId() const +{ + std::lock_guard lock(networkIdMutex_); + return networkId_; +} + +void SoftBusClient::UpdateNetworkId(const std::string& networkId) +{ + std::lock_guard lock(networkIdMutex_); + networkId_ = networkId; +} } // namespace OHOS::AppDistributedKv \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h index 67709bf9..f6851c97 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h @@ -17,40 +17,65 @@ #define DISTRIBUTEDDATAMGR_DATAMGR_SERVICE_SOFTBUS_CLIENT_H #include -#include #include #include "commu_types.h" -#include "executor_pool.h" +#include "serializable/serializable.h" #include "socket.h" -#include "softbus_bus_center.h" + namespace OHOS::AppDistributedKv { class SoftBusClient : public std::enable_shared_from_this { public: + struct AccessExtraInfo final : public DistributedData::Serializable { + std::string bundleName = ""; + std::string accountId = ""; + std::string storeId = ""; + + AccessExtraInfo() {}; + ~AccessExtraInfo() {}; + bool Marshal(json &node) const override + { + SetValue(node[GET_NAME(bundleName)], bundleName); + SetValue(node[GET_NAME(accountId)], accountId); + SetValue(node[GET_NAME(storeId)], storeId); + return true; + }; + bool Unmarshal(const json &node) override + { + GetValue(node, GET_NAME(bundleName), bundleName); + GetValue(node, GET_NAME(accountId), accountId); + GetValue(node, GET_NAME(storeId), storeId); + return true; + }; + }; + enum QoSType { QOS_BR, QOS_HML, QOS_REUSE, QOS_BUTT }; - SoftBusClient(const PipeInfo &pipeInfo, const DeviceId &deviceId, uint32_t type = QOS_HML); + + SoftBusClient(const PipeInfo &pipeInfo, const DeviceId &deviceId, const std::string& networkId, + uint32_t type = QOS_HML, const SessionAccessInfo &accessInfo = {}); ~SoftBusClient(); using Time = std::chrono::steady_clock::time_point; using Duration = std::chrono::steady_clock::duration; Status CheckStatus(); Status OpenConnect(const ISocketListener *listener); - Status SendData(const DataInfo &dataInfo, const ISocketListener *listener); + Status SendData(const DataInfo &dataInfo); bool operator==(int32_t socket) const; bool operator==(const std::string &deviceId) const; - uint32_t GetMtuSize() const; + uint32_t GetMtuBuffer() const; uint32_t GetTimeout() const; Time GetExpireTime() const; int32_t GetSocket() const; uint32_t GetQoSType() const; - void UpdateExpireTime(bool async = true); int32_t GetSoftBusError(); Status ReuseConnect(const ISocketListener *listener); + std::string GetNetworkId() const; + void UpdateNetworkId(const std::string &networkId); private: int32_t Open(int32_t socket, uint32_t type, const ISocketListener *listener, bool async = true); @@ -86,6 +111,7 @@ private: static constexpr uint32_t QOS_COUNTS[QOS_BUTT] = { BR_QOS_COUNT, HML_QOS_COUNT, REUSE_QOS_COUNT }; std::atomic_bool isOpening_ = false; mutable std::mutex mutex_; + mutable std::mutex networkIdMutex_; uint32_t type_ = QOS_HML; PipeInfo pipe_; DeviceId device_; @@ -95,7 +121,8 @@ private: int32_t socket_ = INVALID_SOCKET_ID; int32_t bindState_ = -1; int32_t softBusError_ = 0; + std::string networkId_; + SessionAccessInfo accessInfo_; }; } // namespace OHOS::AppDistributedKv - #endif // DISTRIBUTEDDATAMGR_DATAMGR_SERVICE_SOFTBUS_CLIENT_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/communicator/test/BUILD.gn index 5e5a3489..e236f8d5 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/BUILD.gn @@ -26,14 +26,17 @@ ohos_unittest("CommunicationProviderTest") { "../src", ] external_deps = [ + "access_token:libaccesstoken_sdk", "dsoftbus:softbus_client", "hilog:libhilog", "ipc:ipc_core", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", ] deps = [ "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } @@ -54,11 +57,13 @@ ohos_unittest("CommunicatorContextTest") { "../../include/communicator", ] external_deps = [ + "access_token:libaccesstoken_sdk", "c_utils:utils", "device_manager:devicemanagersdk", "dsoftbus:softbus_client", "googletest:gtest_main", "hilog:libhilog", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddb", ] @@ -68,6 +73,7 @@ ohos_unittest("CommunicatorContextTest") { ] deps = [ "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } @@ -78,11 +84,13 @@ ohos_unittest("CommunicatorDataBufferTest") { sources = [ "unittest/data_buffer_test.cpp" ] include_dirs = [ "../src" ] external_deps = [ + "access_token:libaccesstoken_sdk", "c_utils:utils", "device_manager:devicemanagersdk", "dsoftbus:softbus_client", "googletest:gtest_main", "hilog:libhilog", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", ] cflags = [ @@ -106,13 +114,14 @@ ohos_unittest("DeviceManagerAdapterTest") { ] external_deps = [ "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "access_token:libtoken_setproc", "c_utils:utils", "device_manager:devicemanagersdk", "dsoftbus:softbus_client", "hilog:libhilog", "ipc:ipc_core", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", ] cflags = [ @@ -121,6 +130,7 @@ ohos_unittest("DeviceManagerAdapterTest") { ] deps = [ "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } @@ -153,12 +163,10 @@ ohos_unittest("ProcessCommunicatorImplTest") { "../src", "../../include/communicator", "../../include/utils", - "${data_service_path}/adapter/include/communicator", - "${data_service_path}/framework/include/dfx", - "${data_service_path}/framework/include/utils", ] external_deps = [ + "access_token:libaccesstoken_sdk", "c_utils:utils", "device_manager:devicemanagersdk", "dsoftbus:softbus_client", @@ -166,6 +174,7 @@ ohos_unittest("ProcessCommunicatorImplTest") { "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "json:nlohmann_json_static", "kv_store:datamgr_common", "kv_store:distributeddata_inner", "kv_store:distributeddb", @@ -180,52 +189,42 @@ ohos_unittest("ProcessCommunicatorImplTest") { "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "../../dfx:distributeddata_dfx", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } ohos_unittest("SoftbusAdapterStandardTest") { module_out_path = module_output_path - - sources = [ - "../src/app_pipe_handler.cpp", - "../src/app_pipe_handler.h", - "../src/app_pipe_mgr.cpp", - "../src/app_pipe_mgr.h", - "../src/ark_communication_provider.cpp", - "../src/communication_provider.cpp", - "../src/communication_provider_impl.cpp", - "../src/communicator_context.cpp", - "../src/data_buffer.cpp", - "../src/device_manager_adapter.cpp", - "../src/process_communicator_impl.cpp", - "../src/softbus_adapter.h", - "../src/softbus_client.cpp", - "../src/softbus_client.h", - "unittest/softbus_adapter_standard_test.cpp", - ] - include_dirs = [ + "${data_service_path}/adapter/account/src", + "${data_service_path}/adapter/communicator/src", + "${data_service_path}/adapter/communicator/test/mock/device_manager", + "${data_service_path}/adapter/communicator/test/mock/softbus", "${data_service_path}/adapter/include/communicator", - "${data_service_path}/framework/include/dfx", - "../src", - "../../include/communicator", - "../../include/utils", - "${data_service_path}/framework/include/utils", + "${data_service_path}/service/test/mock", + ] + sources = [ + "${data_service_path}/adapter/account/src/account_delegate_default_impl.cpp", + "${data_service_path}/adapter/account/src/account_delegate_impl.cpp", + "${data_service_path}/adapter/communicator/src/communicator_context.cpp", + "${data_service_path}/adapter/communicator/src/data_buffer.cpp", + "${data_service_path}/adapter/communicator/src/device_manager_adapter.cpp", + "${data_service_path}/adapter/communicator/src/softbus_adapter_standard.cpp", + "${data_service_path}/adapter/communicator/src/softbus_client.cpp", + "${data_service_path}/adapter/communicator/test/mock/device_manager/device_manager.cpp", + "${data_service_path}/adapter/communicator/test/mock/softbus/data_level.cpp", + "${data_service_path}/adapter/communicator/test/mock/softbus/inner_socket.cpp", + "${data_service_path}/adapter/communicator/test/mock/softbus/socket.cpp", + "${data_service_path}/adapter/communicator/test/unittest/softbus_adapter_standard_test.cpp", + "${data_service_path}/service/test/mock/db_store_mock.cpp", + "${data_service_path}/service/test/mock/db_change_data_mock.cpp", ] external_deps = [ "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", - "access_token:libtoken_setproc", "c_utils:utils", - "device_manager:devicemanagersdk", - "dsoftbus:softbus_client", "hilog:libhilog", - "ipc:ipc_core", "json:nlohmann_json_static", "kv_store:datamgr_common", - "kv_store:distributeddata_inner", "kv_store:distributeddb", ] cflags = [ @@ -233,38 +232,38 @@ ohos_unittest("SoftbusAdapterStandardTest") { "-Dprotected=public", ] deps = [ - "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", - "../../dfx:distributeddata_dfx", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } ohos_unittest("SoftbusClientTest") { module_out_path = module_output_path - - sources = [ "unittest/softbus_client_test.cpp" ] include_dirs = [ - "${data_service_path}/adapter/include/autils", + "${data_service_path}/adapter/communicator/src", + "${data_service_path}/adapter/communicator/test/mock/softbus", "${data_service_path}/adapter/include/communicator", - "${data_service_path}/adapter/include/dfx", - "../src", + ] + sources = [ + "${data_service_path}/adapter/communicator/src/communicator_context.cpp", + "${data_service_path}/adapter/communicator/src/softbus_client.cpp", + "${data_service_path}/adapter/communicator/test/mock/softbus/inner_socket.cpp", + "${data_service_path}/adapter/communicator/test/mock/softbus/socket.cpp", + "${data_service_path}/adapter/communicator/test/unittest/softbus_client_test.cpp", ] external_deps = [ + "access_token:libaccesstoken_sdk", "c_utils:utils", - "device_manager:devicemanagersdk", - "dsoftbus:softbus_client", - "googletest:gtest_main", "hilog:libhilog", - "kv_store:distributeddata_inner", - "kv_store:distributeddb", + "json:nlohmann_json_static", + "kv_store:datamgr_common", ] cflags = [ "-Dprivate=public", "-Dprotected=public", ] deps = [ - "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } @@ -272,29 +271,38 @@ ohos_unittest("SoftbusClientTest") { ohos_unittest("AppPipeMgrServiceTest") { module_out_path = module_output_path include_dirs = [ - "${data_service_path}/adapter/include/autils", + "${data_service_path}/adapter/communicator/src", + "${data_service_path}/adapter/communicator/test/mock/device_manager", + "${data_service_path}/adapter/communicator/test/mock/softbus", "${data_service_path}/adapter/include/communicator", - "${data_service_path}/adapter/include/dfx", - "${data_service_path}/adapter/include/utils", - "${data_service_path}/framework/include/dfx", - "../src", ] - sources = [ "unittest/app_pipe_mgr_service_test.cpp" ] + sources = [ + "${data_service_path}/adapter/communicator/src/app_pipe_handler.cpp", + "${data_service_path}/adapter/communicator/src/app_pipe_mgr.cpp", + "${data_service_path}/adapter/communicator/src/communicator_context.cpp", + "${data_service_path}/adapter/communicator/src/data_buffer.cpp", + "${data_service_path}/adapter/communicator/src/device_manager_adapter.cpp", + "${data_service_path}/adapter/communicator/src/softbus_adapter_standard.cpp", + "${data_service_path}/adapter/communicator/src/softbus_client.cpp", + "${data_service_path}/adapter/communicator/test/mock/device_manager/device_manager.cpp", + "${data_service_path}/adapter/communicator/test/mock/softbus/data_level.cpp", + "${data_service_path}/adapter/communicator/test/mock/softbus/inner_socket.cpp", + "${data_service_path}/adapter/communicator/test/mock/softbus/socket.cpp", + "${data_service_path}/adapter/communicator/test/unittest/app_pipe_mgr_service_test.cpp", + ] external_deps = [ + "access_token:libaccesstoken_sdk", "c_utils:utils", - "device_manager:devicemanagersdk", - "dsoftbus:softbus_client", - "googletest:gtest_main", "hilog:libhilog", - "kv_store:distributeddata_inner", - "kv_store:distributeddb", + "json:nlohmann_json_static", + "kv_store:datamgr_common", ] cflags = [ "-Dprivate=public", "-Dprotected=public", ] deps = [ - "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/BUILD.gn index cc55d56d..b3c1e727 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/BUILD.gn @@ -35,14 +35,27 @@ ohos_fuzztest("SoftBusAdapterFuzzTest") { "-fno-omit-frame-pointer", ] - sources = [ "softbusadapter_fuzzer.cpp" ] + sources = [ + "${data_service_path}/adapter/communicator/src/communicator_context.cpp", + "${data_service_path}/adapter/communicator/src/device_manager_adapter.cpp", + "${data_service_path}/adapter/communicator/src/softbus_client.cpp", + "softbusadapter_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/adapter/utils:distributeddata_utils", + "${data_service_path}/framework:distributeddatasvcfwk", + ] external_deps = [ + "access_token:libaccesstoken_sdk", "c_utils:utils", "datamgr_service:distributeddatasvcfwk", "device_manager:devicemanagersdk", "dsoftbus:softbus_client", "hilog:libhilog", + "ipc:ipc_single", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddb", ] diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/softbusadapter_fuzzer.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/softbusadapter_fuzzer.cpp index 6420589a..03e0db57 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/softbusadapter_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/fuzztest/softbusadapter_fuzzer/softbusadapter_fuzzer.cpp @@ -13,23 +13,26 @@ * limitations under the License. */ +#include + #include "softbusadapter_fuzzer.h" #include #include -#include "softbus_adapter_standard.cpp" #include "message_parcel.h" #include "securec.h" +#include "softbus_adapter_standard.cpp" using namespace OHOS::AppDistributedKv; namespace OHOS { -bool OnBytesReceivedFuzz(const uint8_t *data, size_t size) +bool OnBytesReceivedFuzz(FuzzedDataProvider &provider) { - int connId = static_cast(*data); - unsigned int dataLen = static_cast(size); - AppDataListenerWrap::OnClientBytesReceived(connId, data, dataLen); + int connId = provider.ConsumeIntegral(); + std::vector remainingData = provider.ConsumeRemainingBytes(); + AppDataListenerWrap::OnClientBytesReceived(connId, static_cast(remainingData.data()), + remainingData.size()); return true; } } // namespace OHOS @@ -37,11 +40,7 @@ bool OnBytesReceivedFuzz(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::OnBytesReceivedFuzz(data, size); - + FuzzedDataProvider provider(data, size); + OHOS::OnBytesReceivedFuzz(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager.cpp new file mode 100644 index 00000000..0e6a938f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager.cpp @@ -0,0 +1,145 @@ +/* + * 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 "device_manager.h" + +#include "securec.h" + +namespace OHOS::DistributedHardware { +static constexpr const char *LOCAL_DEVICE_NAME = "local_device_name"; +static constexpr const char *LOCAL_NETWORK_ID = "local_network_id"; +static constexpr const char *LOCAL_UUID = "local_uuid"; +static constexpr const char *LOCAL_UDID = "local_udid"; +static constexpr const char *REMOTE_DEVICE_NAME = "remote_device_name"; +static constexpr const char *REMOTE_NETWORK_ID = "remote_network_id"; +static constexpr const char *REMOTE_UUID = "remote_uuid"; +static constexpr const char *REMOTE_UDID = "remote_udid"; + +DeviceManager &DeviceManager::GetInstance() +{ + static DeviceManager dmManager; + return dmManager; +} + +int32_t DeviceManager::InitDeviceManager(const std::string &pkgName, std::shared_ptr dmInitCallback) +{ + (void)pkgName; + (void)dmInitCallback; + return 0; +} + +int32_t DeviceManager::RegisterDevStateCallback(const std::string &pkgName, const std::string &extra, + std::shared_ptr callback) +{ + (void)pkgName; + (void)extra; + (void)callback; + return 0; +} + +int32_t DeviceManager::NotifyEvent(const std::string &pkgName, const int32_t eventId, const std::string &event) +{ + (void)pkgName; + (void)eventId; + (void)event; + return 0; +} + +int32_t DeviceManager::GetTrustedDeviceList(const std::string &pkgName, const std::string &extra, + std::vector &deviceList) +{ + (void)pkgName; + (void)extra; + DeviceExtraInfo extraInfo; + DmDeviceInfo remoteDeviceInfo = { .extraData = DistributedData::Serializable::Marshall(extraInfo) }; + (void)strcpy_s(remoteDeviceInfo.deviceName, DM_MAX_DEVICE_ID_LEN, REMOTE_DEVICE_NAME); + (void)strcpy_s(remoteDeviceInfo.networkId, DM_MAX_DEVICE_ID_LEN, REMOTE_NETWORK_ID); + deviceList.emplace_back(std::move(remoteDeviceInfo)); + return 0; +} + +int32_t DeviceManager::GetLocalDeviceInfo(const std::string &pkgName, DmDeviceInfo &deviceInfo) +{ + (void)pkgName; + (void)strcpy_s(deviceInfo.deviceName, DM_MAX_DEVICE_ID_LEN, LOCAL_DEVICE_NAME); + (void)strcpy_s(deviceInfo.networkId, DM_MAX_DEVICE_ID_LEN, LOCAL_NETWORK_ID); + DeviceExtraInfo extraInfo; + deviceInfo.extraData = DistributedData::Serializable::Marshall(extraInfo); + return 0; +} + +int32_t DeviceManager::GetUuidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &uuid) +{ + (void)pkgName; + if (networkId == LOCAL_NETWORK_ID) { + uuid = LOCAL_UUID; + } + if (networkId == REMOTE_NETWORK_ID) { + uuid = REMOTE_UUID; + } + return 0; +} + +int32_t DeviceManager::GetUdidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &udid) +{ + (void)pkgName; + if (networkId == LOCAL_NETWORK_ID) { + udid = LOCAL_UDID; + } + if (networkId == REMOTE_NETWORK_ID) { + udid = REMOTE_UDID; + } + return 0; +} + +int32_t DeviceManager::GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, + const std::string &appId, std::string &encryptedUuid) +{ + (void)pkgName; + (void)uuid; + (void)appId; + (void)encryptedUuid; + return 0; +} + +int32_t DeviceManager::GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, + std::string &uuid) +{ + (void)pkgName; + (void)networkId; + (void)uuid; + return 0; +} + +bool DeviceManager::IsSameAccount(const std::string &networkId) +{ + (void)networkId; + return true; +} + +bool DeviceManager::CheckAccessControl(const DmAccessCaller &caller, const DmAccessCallee &callee) +{ + (void)caller; + (void)callee; + return true; +} + +bool DeviceManager::CheckIsSameAccount(const DmAccessCaller &caller, const DmAccessCallee &callee) +{ + (void)caller; + (void)callee; + return true; +} +} // namespace OHOS::DistributedHardware \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager.h b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager.h new file mode 100644 index 00000000..63840264 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager.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 MOCK_DEVICE_MANAGER_H +#define MOCK_DEVICE_MANAGER_H + +#include + +#include "device_manager_callback.h" +#include "dm_device_info.h" + +namespace OHOS::DistributedHardware { +class DeviceManager { +public: + static DeviceManager &GetInstance(); + + int32_t InitDeviceManager(const std::string &pkgName, std::shared_ptr dmInitCallback); + int32_t RegisterDevStateCallback(const std::string &pkgName, const std::string &extra, + std::shared_ptr callback); + int32_t NotifyEvent(const std::string &pkgName, const int32_t eventId, const std::string &event); + int32_t GetTrustedDeviceList(const std::string &pkgName, const std::string &extra, + std::vector &deviceList); + int32_t GetLocalDeviceInfo(const std::string &pkgName, DmDeviceInfo &deviceInfo); + int32_t GetUuidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &uuid); + int32_t GetUdidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &udid); + int32_t GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, const std::string &appId, + std::string &encryptedUuid); + int32_t GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &uuid); + bool IsSameAccount(const std::string &networkId); + bool CheckAccessControl(const DmAccessCaller &caller, const DmAccessCallee &callee); + bool CheckIsSameAccount(const DmAccessCaller &caller, const DmAccessCallee &callee); + +private: + DeviceManager() = default; + ~DeviceManager() = default; +}; +} // namespace OHOS::DistributedHardware +#endif // MOCK_DEVICE_MANAGER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager_callback.h b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager_callback.h new file mode 100644 index 00000000..2ba425ae --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/device_manager_callback.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 MOCK_DEVICE_MANAGER_CALLBACK_H +#define MOCK_DEVICE_MANAGER_CALLBACK_H + +#include "dm_device_info.h" + +namespace OHOS::DistributedHardware { +class DmInitCallback { +public: + virtual ~DmInitCallback() {} + virtual void OnRemoteDied() = 0; +}; + +class DeviceStateCallback { +public: + virtual ~DeviceStateCallback() {} + virtual void OnDeviceOnline(const DmDeviceInfo &deviceInfo) = 0; + virtual void OnDeviceOffline(const DmDeviceInfo &deviceInfo) = 0; + virtual void OnDeviceChanged(const DmDeviceInfo &deviceInfo) = 0; + virtual void OnDeviceReady(const DmDeviceInfo &deviceInfo) = 0; +}; +} // namespace OHOS::DistributedHardware +#endif // MOCK_DEVICE_MANAGER_CALLBACK_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/dm_device_info.h b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/dm_device_info.h new file mode 100644 index 00000000..ad9a9de9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/device_manager/dm_device_info.h @@ -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. + */ + +#ifndef MOCK_DM_DEVICE_INFO_H +#define MOCK_DM_DEVICE_INFO_H + +#include "serializable/serializable.h" + +#define DM_MAX_DEVICE_ID_LEN (97) + +namespace OHOS::DistributedHardware { +struct DeviceExtraInfo final : public DistributedData::Serializable { + static constexpr int32_t OH_OS_TYPE = 10; + + int32_t OS_TYPE = OH_OS_TYPE; + + DeviceExtraInfo() {}; + ~DeviceExtraInfo() {}; + bool Marshal(json &node) const override + { + return SetValue(node[GET_NAME(OS_TYPE)], OS_TYPE); + }; + bool Unmarshal(const json &node) override + { + return GetValue(node, GET_NAME(OS_TYPE), OS_TYPE); + }; +}; + +struct DmDeviceInfo { + char deviceId[DM_MAX_DEVICE_ID_LEN] = {0}; + char deviceName[DM_MAX_DEVICE_ID_LEN] = {0}; + uint16_t deviceTypeId; + char networkId[DM_MAX_DEVICE_ID_LEN] = {0}; + int32_t range; + int32_t networkType; + int32_t authForm; + std::string extraData; +}; + +struct DmAccessCaller { + std::string accountId; + std::string pkgName; + std::string networkId; + int32_t userId; + uint64_t tokenId = 0; + std::string extra; +}; + +struct DmAccessCallee { + std::string accountId; + std::string networkId; + std::string peerId; + std::string pkgName; + int32_t userId; + uint64_t tokenId = 0; + std::string extra; +}; + +enum DmNotifyEvent { + DM_NOTIFY_EVENT_ONDEVICEREADY, +}; +} // namespace OHOS::DistributedHardware +#endif // MOCK_DM_DEVICE_INFO_H \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/transfergrdtypetocoltype_fuzzer.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/data_level.cpp similarity index 43% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/transfergrdtypetocoltype_fuzzer.cpp rename to datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/data_level.cpp index 5fc3b633..c621b08b 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/transfergrdtypetocoltype_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/data_level.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 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,34 +13,36 @@ * limitations under the License. */ -#include "rdb_store_config.h" -#include "rdb_errno.h" -#include "rdb_store_impl.h" -#include "rd_utils.h" -using namespace OHOS; -using namespace OHOS::NativeRdb; -namespace OHOS { +#include "data_level.h" -uint32_t ConvertToUint32(const uint8_t *ptr, size_t size) +static constexpr const char *REMOTE_NETWORK_ID = "remote_network_id"; + +SoftBusErrNo errCode_; +IDataLevelCb *callback_ = nullptr; + +void ConfigReturnCode(SoftBusErrNo errorCode) { - if (ptr == nullptr || (size < sizeof(uint32_t))) { - return 0; - } - return *(reinterpret_cast(ptr)); + errCode_ = errorCode; } -void transferGrdTypeToColTypeFuzzer(const uint8_t *data, size_t size) +int32_t RegDataLevelChangeCb(const char *pkgName, IDataLevelCb *callback) { - int err = ConvertToUint32(data, size); - RdUtils::TransferGrdTypeToColType(err); -} + (void)pkgName; + callback_ = callback; + return errCode_; } -/* Fuzzer entry point */ -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +int32_t UnregDataLevelChangeCb(const char *pkgName) { - /* Run your code on data */ - OHOS::transferGrdTypeToColTypeFuzzer(data, size); - return 0; + (void)pkgName; + callback_ = nullptr; + return SoftBusErrNo::SOFTBUS_OK; } +int32_t SetDataLevel(const DataLevel *dataLevel) +{ + if (errCode_ == SoftBusErrNo::SOFTBUS_OK && callback_ != nullptr) { + callback_->onDataLevelChanged(REMOTE_NETWORK_ID, *dataLevel); + } + return errCode_; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/data_level.h b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/data_level.h new file mode 100644 index 00000000..fdd24650 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/data_level.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 MOCK_SOFTBUS_DATA_LEVEL_H +#define MOCK_SOFTBUS_DATA_LEVEL_H + +#include + +#include "softbus_error_code.h" + +struct DataLevel { + uint16_t dynamicLevel; + uint16_t staticLevel; + uint32_t switchLevel; + uint16_t switchLength; +}; + +struct IDataLevelCb { + void (*onDataLevelChanged)(const char *networkId, const DataLevel dataLevel); +}; + +void ConfigReturnCode(SoftBusErrNo errorCode); + +int32_t RegDataLevelChangeCb(const char *pkgName, IDataLevelCb *callback); + +int32_t UnregDataLevelChangeCb(const char *pkgName); + +int32_t SetDataLevel(const DataLevel *dataLevel); + +#endif // MOCK_SOFTBUS_DATA_LEVEL_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/inner_socket.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/inner_socket.cpp new file mode 100644 index 00000000..a2bc12a6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/inner_socket.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 "inner_socket.h" + +#include "socket.h" + +static constexpr uint32_t MTU_SIZE = 4 * 1024u; + +int32_t GetMtuSize(int32_t socket, uint32_t *mtuSize) +{ + if (socket <= INVALID_MTU_SOCKET) { + return -1; + } + *mtuSize = MTU_SIZE; + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/inner_socket.h b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/inner_socket.h new file mode 100644 index 00000000..5db024db --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/inner_socket.h @@ -0,0 +1,23 @@ +/* + * 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 MOCK_SOFTBUS_INNER_SESSION_SOCKET_H +#define MOCK_SOFTBUS_INNER_SESSION_SOCKET_H + +#include + +int32_t GetMtuSize(int32_t socket, uint32_t *mtuSize); + +#endif // MOCK_SOFTBUS_INNER_SESSION_SOCKET_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/socket.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/socket.cpp new file mode 100644 index 00000000..02ddf200 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/socket.cpp @@ -0,0 +1,116 @@ +/* + * 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 "socket.h" + +#include "securec.h" +#include "softbus_error_code.h" + +static constexpr uint32_t EXTRA_INFO_LENGTH = 100; +static constexpr const char *SOCKET_NAME = "socket_test"; +static constexpr const char *PKG_NAME = "ddms_test"; +static constexpr const char *REMOTE_NETWORK_ID = "remote_network_id"; + +int32_t socketId_ = DEFAULT_SOCKET; +ISocketListener *clientListener_ = nullptr; +ISocketListener *serverListener_ = nullptr; +SocketAccessInfo accessInfo_; + +void ConfigSocketId(int32_t socketId) +{ + socketId_ = socketId; +} + +int32_t Socket(SocketInfo info) +{ + (void)info; + return socketId_; +} + +int32_t SetAccessInfo(int32_t socket, SocketAccessInfo accessInfo) +{ + if (socket == INVALID_SET_SOCKET) { + return SoftBusErrNo::SOFTBUS_ERROR; + } + accessInfo_.userId = accessInfo.userId; + accessInfo_.localTokenId = accessInfo.localTokenId; + accessInfo_.extraAccessInfo = new char[EXTRA_INFO_LENGTH]; + (void)strcpy_s(accessInfo_.extraAccessInfo, EXTRA_INFO_LENGTH, accessInfo.extraAccessInfo); + return SoftBusErrNo::SOFTBUS_OK; +} + +int32_t Bind(int32_t socket, const QosTV qos[], uint32_t qosCount, const ISocketListener *listener) +{ + (void)qos; + (void)qosCount; + if (socket <= INVALID_BIND_SOCKET) { + return SoftBusErrNo::SOFTBUS_ERROR; + } + if (serverListener_ != nullptr) { + PeerSocketInfo info; + info.name = const_cast(SOCKET_NAME); + info.pkgName = const_cast(PKG_NAME); + info.networkId = const_cast(REMOTE_NETWORK_ID); + SocketAccessInfo localInfo; + if (!serverListener_->OnNegotiate2(socket, info, &accessInfo_, &localInfo)) { + return SoftBusErrNo::SOFTBUS_ERROR; + } + serverListener_->OnBind(socket, info); + } + clientListener_ = const_cast(listener); + return SoftBusErrNo::SOFTBUS_OK; +} + +void Shutdown(int32_t socket) +{ + if (socket <= INVALID_MTU_SOCKET) { + return; + } + ShutdownReason reason = ShutdownReason::UN_KNOWN; + if (clientListener_ != nullptr && clientListener_->OnShutdown != nullptr) { + clientListener_->OnShutdown(socket, reason); + } + if (serverListener_ != nullptr && serverListener_->OnShutdown != nullptr) { + serverListener_->OnShutdown(socket, reason); + } +} + +int32_t SendBytes(int32_t socket, const void *data, uint32_t len) +{ + if (socket <= INVALID_SEND_SOCKET) { + return SoftBusErrNo::SOFTBUS_ERROR; + } + if (clientListener_ == nullptr) { + return SoftBusErrNo::SOFTBUS_OK; + } + if (clientListener_->OnBytes != nullptr) { + clientListener_->OnBytes(socket, data, len); + } + if (clientListener_->OnMessage != nullptr) { + clientListener_->OnMessage(socket, data, len); + } + return SoftBusErrNo::SOFTBUS_OK; +} + +int32_t Listen(int32_t socket, const QosTV qos[], uint32_t qosCount, const ISocketListener *listener) +{ + (void)qos; + (void)qosCount; + if (socket < VALID_SOCKET) { + return SoftBusErrNo::SOFTBUS_ERROR; + } + serverListener_ = const_cast(listener); + return SoftBusErrNo::SOFTBUS_OK; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/socket.h b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/socket.h new file mode 100644 index 00000000..03efd188 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/socket.h @@ -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. + */ + +#ifndef MOCK_SOFTBUS_SESSION_SOCKET_H +#define MOCK_SOFTBUS_SESSION_SOCKET_H + +#include + +enum TransDataType { + DATA_TYPE_BYTES, +}; + +enum ShutdownReason { + UN_KNOWN, +}; + +enum QoSEvent { + QOS_SATISFIED, + QOS_NOT_SATISFIED, +}; + +enum QosType { + QOS_TYPE_MIN_BW, + QOS_TYPE_MAX_LATENCY, + QOS_TYPE_MIN_LATENCY, + QOS_TYPE_REUSE_BE, +}; + +struct QosTV { + QosType qos; + int32_t value; +}; + +struct PeerSocketInfo { + char *name; + char *networkId; + char *pkgName; + TransDataType dataType = TransDataType::DATA_TYPE_BYTES; +}; + +struct SocketInfo { + char *name; + char *peerName; + char *peerNetworkId; + char *pkgName; + TransDataType dataType; +}; + +struct SocketAccessInfo { + int32_t userId; + uint64_t localTokenId; + char *businessAccountId; + char *extraAccessInfo; +}; + +struct ISocketListener { + void (*OnBind)(int32_t socket, PeerSocketInfo info); + void (*OnShutdown)(int32_t socket, ShutdownReason reason); + void (*OnBytes)(int32_t socket, const void *data, uint32_t dataLen); + void (*OnMessage)(int32_t socket, const void *data, uint32_t dataLen); + void (*OnQos)(int32_t socket, QoSEvent eventId, const QosTV *qos, uint32_t qosCount); + bool (*OnNegotiate2)(int32_t socket, PeerSocketInfo info, SocketAccessInfo *peerInfo, SocketAccessInfo *localInfo); +}; + +static constexpr int32_t DEFAULT_SOCKET = -1; +static constexpr int32_t INVALID_SOCKET = 0; +static constexpr int32_t INVALID_SET_SOCKET = 1; +static constexpr int32_t INVALID_BIND_SOCKET = 2; +static constexpr int32_t INVALID_MTU_SOCKET = 3; +static constexpr int32_t INVALID_SEND_SOCKET = 4; +static constexpr int32_t VALID_SOCKET = 5; + +void ConfigSocketId(int32_t socketId); + +int32_t Socket(SocketInfo info); + +int32_t Listen(int32_t socket, const QosTV qos[], uint32_t qosCount, const ISocketListener *listener); + +int32_t SetAccessInfo(int32_t socket, SocketAccessInfo accessInfo); + +int32_t Bind(int32_t socket, const QosTV qos[], uint32_t qosCount, const ISocketListener *listener); + +void Shutdown(int32_t socket); + +int32_t SendBytes(int32_t socket, const void *data, uint32_t len); +#endif // MOCK_SOFTBUS_SESSION_SOCKET_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/softbus_error_code.h b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/softbus_error_code.h new file mode 100644 index 00000000..7925f943 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/mock/softbus/softbus_error_code.h @@ -0,0 +1,25 @@ +/* + * 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 MOCK_SOFTBUS_ERROR_CODE_H +#define MOCK_SOFTBUS_ERROR_CODE_H + +enum SoftBusErrNo { + SOFTBUS_OK = 0, + SOFTBUS_ERROR = 1, + SOFTBUS_FUNC_NOT_SUPPORT = 2, + SOFTBUS_ALREADY_EXISTED = 3, +}; +#endif // MOCK_SOFTBUS_ERROR_CODE_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/app_pipe_mgr_service_test.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/app_pipe_mgr_service_test.cpp index f9ebce1a..97b3c6a3 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/app_pipe_mgr_service_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/app_pipe_mgr_service_test.cpp @@ -12,26 +12,47 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define LOG_TAG "AppPipeMgrServiceTest" #include "app_pipe_mgr.h" -#include "kvstore_utils.h" -#include "log_print.h" -#include "dfx/reporter.h" -#include "types.h" + #include +#include "socket.h" + namespace OHOS::Test { using namespace testing::ext; using namespace OHOS::AppDistributedKv; + +static constexpr int32_t DEFAULT_SOCKET = -1; +static constexpr int32_t INVALID_SOCKET = 0; +static constexpr int32_t INVALID_SET_SOCKET = 1; +static constexpr int32_t INVALID_BIND_SOCKET = 2; +static constexpr int32_t INVALID_MTU_SOCKET = 3; +static constexpr int32_t INVALID_SEND_SOCKET = 4; +static constexpr int32_t VALID_SOCKET = 5; +static constexpr uint32_t INVALID_TRANSFER_SIZE = 5 * 1024 * 1024; +static constexpr uint32_t VALID_TRANSFER_SIZE = 1024; +static constexpr uint32_t DATA_LENGTH = 8; +static constexpr uint32_t TOKEN_ID = 1111; +static constexpr const char *PIPE_ID = "AppPipeMgrServiceTest"; +static constexpr const char *DEVICE_ID = "deviceId"; +static constexpr const char *DATA_INFO = "DataInfo"; +static constexpr const char *USER_ID = "100"; +static constexpr const char *BUNDLE_NAME = "bundleName"; +static constexpr const char *STORE_ID = "storeId"; + class AppDataChangeListenerMock : public AppDataChangeListener { void OnMessage(const DeviceInfo &info, const uint8_t *ptr, const int size, - const struct PipeInfo &id) const override; + const struct PipeInfo &id) const override; }; void AppDataChangeListenerMock::OnMessage(const DeviceInfo &info, const uint8_t *ptr, const int size, const struct PipeInfo &id) const { + (void)info; + (void)ptr; + (void)size; + (void)id; return; } @@ -40,251 +61,312 @@ public: static void SetUpTestCase(void) {}; static void TearDownTestCase(void) {}; void SetUp() {}; - void TearDown() {}; + void TearDown(); + + static PipeInfo pipeInfo_; + static DeviceId deviceId_; + static DataInfo dataInfo_; + static MessageInfo msgInfo_; + static ExtraDataInfo extraInfo_; }; -/** -* @tc.name: StopWatchDataChange001 -* @tc.desc: StopWatchDataChange test -* @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, StopWatchDataChange001, TestSize.Level0) +PipeInfo AppPipeMgrServiceTest::pipeInfo_; +DeviceId AppPipeMgrServiceTest::deviceId_; +DataInfo AppPipeMgrServiceTest::dataInfo_; +MessageInfo AppPipeMgrServiceTest::msgInfo_; +ExtraDataInfo AppPipeMgrServiceTest::extraInfo_; + +void AppPipeMgrServiceTest::TearDown() { - AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - const AppDataChangeListener* observer = nullptr; - auto status = appPipeMgr.StopWatchDataChange(observer, pipeInfo); - EXPECT_EQ(Status::INVALID_ARGUMENT, status); - - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - status = appPipeMgr.StopWatchDataChange(observer, pipeInfo); - EXPECT_EQ(Status::INVALID_ARGUMENT, status); - - PipeInfo pipeInfoNull; - const AppDataChangeListener* observerListener = new AppDataChangeListenerMock(); - status = appPipeMgr.StopWatchDataChange(observerListener, pipeInfoNull); - EXPECT_EQ(Status::INVALID_ARGUMENT, status); + pipeInfo_.pipeId = ""; + deviceId_.deviceId = ""; + dataInfo_.length = 0; + dataInfo_.data = nullptr; + extraInfo_.userId = ""; + extraInfo_.bundleName = ""; + extraInfo_.storeId = ""; + dataInfo_.extraInfo = extraInfo_; } /** -* @tc.name: StopWatchDataChange002 -* @tc.desc: StopWatchDataChange test +* @tc.name: StartWatchDataChangeTest001 +* @tc.desc: StartWatchDataChange test * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, StopWatchDataChange002, TestSize.Level0) +*/ +HWTEST_F(AppPipeMgrServiceTest, StartWatchDataChangeTest001, TestSize.Level0) { AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - const AppDataChangeListener* observer = new AppDataChangeListenerMock(); - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - auto status = appPipeMgr.StopWatchDataChange(observer, pipeInfo); - EXPECT_EQ(Status::ERROR, status); - - auto handler = std::make_shared(pipeInfo); - std::map> dataBusMap = {{"pipeId", handler}}; - appPipeMgr.dataBusMap_ = dataBusMap; - status = appPipeMgr.StopWatchDataChange(observer, pipeInfo); - EXPECT_EQ(Status::ERROR, status); + auto status = appPipeMgr.StartWatchDataChange(nullptr, pipeInfo_); + ASSERT_EQ(status, Status::INVALID_ARGUMENT); + + AppDataChangeListenerMock* dataChangeListener = new AppDataChangeListenerMock(); + status = appPipeMgr.StartWatchDataChange(dataChangeListener, pipeInfo_); + ASSERT_EQ(status, Status::INVALID_ARGUMENT); + + pipeInfo_.pipeId = PIPE_ID; + status = appPipeMgr.StartWatchDataChange(dataChangeListener, pipeInfo_); + ASSERT_EQ(status, Status::ERROR); + + appPipeMgr.dataBusMap_.insert({ PIPE_ID, nullptr }); + status = appPipeMgr.StartWatchDataChange(dataChangeListener, pipeInfo_); + ASSERT_EQ(status, Status::ERROR); + + appPipeMgr.dataBusMap_.erase(PIPE_ID); + appPipeMgr.dataBusMap_.insert({ PIPE_ID, std::make_shared(pipeInfo_) }); + status = appPipeMgr.StartWatchDataChange(dataChangeListener, pipeInfo_); + ASSERT_EQ(status, Status::SUCCESS); + + delete dataChangeListener; } /** -* @tc.name: SendData001 -* @tc.desc: SendData test +* @tc.name: StopWatchDataChangeTest001 +* @tc.desc: StopWatchDataChange test * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, SendData001, TestSize.Level0) +*/ +HWTEST_F(AppPipeMgrServiceTest, StopWatchDataChangeTest001, TestSize.Level0) { AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - DeviceId deviceId = {"deviceId"}; - std::string content = "Helloworlds"; - const uint8_t *t = reinterpret_cast(content.c_str()); - DataInfo dataInfo = { const_cast(t), static_cast(content.length())}; - uint32_t totalLength = 0; - MessageInfo info; - auto handler = std::make_shared(pipeInfo); - std::map> dataBusMap = {{"pipeId", handler}}; - appPipeMgr.dataBusMap_ = dataBusMap; - auto status = appPipeMgr.SendData(pipeInfo, deviceId, dataInfo, totalLength, info); - EXPECT_EQ(std::make_pair(Status::RATE_LIMIT, 0), status); + auto status = appPipeMgr.StopWatchDataChange(nullptr, pipeInfo_); + ASSERT_EQ(status, Status::INVALID_ARGUMENT); + + AppDataChangeListenerMock* dataChangeListener = new AppDataChangeListenerMock(); + status = appPipeMgr.StopWatchDataChange(dataChangeListener, pipeInfo_); + ASSERT_EQ(status, Status::INVALID_ARGUMENT); + + pipeInfo_.pipeId = PIPE_ID; + status = appPipeMgr.StopWatchDataChange(dataChangeListener, pipeInfo_); + ASSERT_EQ(status, Status::ERROR); + + appPipeMgr.dataBusMap_.insert({ PIPE_ID, nullptr }); + status = appPipeMgr.StopWatchDataChange(dataChangeListener, pipeInfo_); + ASSERT_EQ(status, Status::ERROR); + + appPipeMgr.dataBusMap_.erase(PIPE_ID); + appPipeMgr.dataBusMap_.insert({ PIPE_ID, std::make_shared(pipeInfo_) }); + status = appPipeMgr.StopWatchDataChange(dataChangeListener, pipeInfo_); + ASSERT_EQ(status, Status::SUCCESS); + + delete dataChangeListener; } /** -* @tc.name: Start001 -* @tc.desc: Start test +* @tc.name: IsSameStartedOnPeerTest001 +* @tc.desc: IsSameStartedOnPeer test * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, Start001, TestSize.Level0) +*/ +HWTEST_F(AppPipeMgrServiceTest, IsSameStartedOnPeerTest001, TestSize.Level0) { AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - auto handler = std::make_shared(pipeInfo); - std::map> dataBusMap = {{"pipeId", handler}}; - appPipeMgr.dataBusMap_ = dataBusMap; - auto status = appPipeMgr.Start(pipeInfo); - EXPECT_EQ(Status::SUCCESS, status); + auto result = appPipeMgr.IsSameStartedOnPeer(pipeInfo_, deviceId_); + appPipeMgr.SetMessageTransFlag(pipeInfo_, true); + ASSERT_FALSE(result); + + pipeInfo_.pipeId = PIPE_ID; + result = appPipeMgr.IsSameStartedOnPeer(pipeInfo_, deviceId_); + ASSERT_FALSE(result); + + deviceId_.deviceId = DEVICE_ID; + result = appPipeMgr.IsSameStartedOnPeer(pipeInfo_, deviceId_); + appPipeMgr.SetMessageTransFlag(pipeInfo_, true); + ASSERT_FALSE(result); + + appPipeMgr.dataBusMap_.insert({ PIPE_ID, nullptr }); + result = appPipeMgr.IsSameStartedOnPeer(pipeInfo_, deviceId_); + appPipeMgr.SetMessageTransFlag(pipeInfo_, true); + ASSERT_FALSE(result); + + appPipeMgr.dataBusMap_.erase(PIPE_ID); + appPipeMgr.dataBusMap_.insert({ PIPE_ID, std::make_shared(pipeInfo_) }); + result = appPipeMgr.IsSameStartedOnPeer(pipeInfo_, deviceId_); + appPipeMgr.SetMessageTransFlag(pipeInfo_, true); + ASSERT_TRUE(result); } /** -* @tc.name: Stop001 -* @tc.desc: Stop test +* @tc.name: StartTest001 +* @tc.desc: test start function with all branch * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, Stop001, TestSize.Level0) -{ - AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - auto status = appPipeMgr.Stop(pipeInfo); - EXPECT_EQ(Status::KEY_NOT_FOUND, status); - - auto handler = std::make_shared(pipeInfo); - std::map> dataBusMap = {{"pipeId", handler}}; - appPipeMgr.dataBusMap_ = dataBusMap; - status = appPipeMgr.Stop(pipeInfo); - EXPECT_EQ(Status::SUCCESS, status); -} +*/ +//HWTEST_F(AppPipeMgrServiceTest, StartTest001, TestSize.Level0) +//{ +// AppPipeMgr appPipeMgr; +// auto status = appPipeMgr.Start(pipeInfo_); +// ASSERT_EQ(status, Status::INVALID_ARGUMENT); +// +// pipeInfo_.pipeId = PIPE_ID; +// ConfigSocketId(INVALID_SOCKET); +// status = appPipeMgr.Start(pipeInfo_); +// ASSERT_EQ(status, Status::ILLEGAL_STATE); +// +// ConfigSocketId(VALID_SOCKET); +// status = appPipeMgr.Start(pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +// +// status = appPipeMgr.Start(pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +//} /** -* @tc.name: IsSameStartedOnPeer001 -* @tc.desc: IsSameStartedOnPeer test +* @tc.name: StopTest001 +* @tc.desc: test stop function with all branch * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, IsSameStartedOnPeer001, TestSize.Level0) -{ - AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - DeviceId deviceId; - auto status = appPipeMgr.IsSameStartedOnPeer(pipeInfo, deviceId); - EXPECT_EQ(false, status); - - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - status = appPipeMgr.IsSameStartedOnPeer(pipeInfo, deviceId); - EXPECT_EQ(false, status); - - PipeInfo pipeInfoNull; - deviceId.deviceId = "deviceId"; - status = appPipeMgr.IsSameStartedOnPeer(pipeInfoNull, deviceId); - EXPECT_EQ(false, status); -} +*/ +//HWTEST_F(AppPipeMgrServiceTest, StopTest001, TestSize.Level0) +//{ +// AppPipeMgr appPipeMgr; +// pipeInfo_.pipeId = PIPE_ID; +// auto status = appPipeMgr.Stop(pipeInfo_); +// ASSERT_EQ(status, Status::KEY_NOT_FOUND); +// +// ConfigSocketId(VALID_SOCKET); +// status = appPipeMgr.Start(pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +// +// status = appPipeMgr.Stop(pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +//} /** -* @tc.name: IsSameStartedOnPeer002 -* @tc.desc: IsSameStartedOnPeer test +* @tc.name: SendDataTest001 +* @tc.desc: send data fail with all exception branch * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, IsSameStartedOnPeer002, TestSize.Level0) +*/ +HWTEST_F(AppPipeMgrServiceTest, SendDataTest001, TestSize.Level0) { AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - DeviceId deviceId; - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - deviceId.deviceId = "deviceId"; - auto status = appPipeMgr.IsSameStartedOnPeer(pipeInfo, deviceId); - EXPECT_EQ(false, status); - - auto handler = std::make_shared(pipeInfo); - std::map> dataBusMap = {{"pipeId", handler}}; - appPipeMgr.dataBusMap_ = dataBusMap; - status = appPipeMgr.IsSameStartedOnPeer(pipeInfo, deviceId); - EXPECT_EQ(true, status); + auto result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + pipeInfo_.pipeId = PIPE_ID; + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + deviceId_.deviceId = DEVICE_ID; + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + dataInfo_.length = 0; + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + dataInfo_.length = INVALID_TRANSFER_SIZE; + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + dataInfo_.length = VALID_TRANSFER_SIZE; + dataInfo_.data = nullptr; + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + dataInfo_.length = DATA_LENGTH; + dataInfo_.data = const_cast(reinterpret_cast(DATA_INFO)); + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + extraInfo_.userId = USER_ID; + dataInfo_.extraInfo = extraInfo_; + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + extraInfo_.appId = BUNDLE_NAME; + dataInfo_.extraInfo = extraInfo_; + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::ERROR); + + extraInfo_.storeId = STORE_ID; + dataInfo_.extraInfo = extraInfo_; + result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); + ASSERT_EQ(result.first, Status::KEY_NOT_FOUND); } /** -* @tc.name: SetMessageTransFlag001 -* @tc.desc: SetMessageTransFlag test +* @tc.name: SendDataTest002 +* @tc.desc: send data trigger success * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, SetMessageTransFlag001, TestSize.Level0) -{ - AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - bool flag = true; - EXPECT_NO_FATAL_FAILURE( - appPipeMgr.SetMessageTransFlag(pipeInfo, flag)); - - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - auto handler = std::make_shared(pipeInfo); - std::map> dataBusMap = {{"pipeId", handler}}; - appPipeMgr.dataBusMap_ = dataBusMap; - EXPECT_NO_FATAL_FAILURE( - appPipeMgr.SetMessageTransFlag(pipeInfo, flag)); -} +*/ +//HWTEST_F(AppPipeMgrServiceTest, SendDataTest002, TestSize.Level0) +//{ +// AppPipeMgr appPipeMgr; +// pipeInfo_.pipeId = PIPE_ID; +// +// ConfigSocketId(VALID_SOCKET); +// auto status = appPipeMgr.Start(pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +// +// deviceId_.deviceId = DEVICE_ID; +// dataInfo_.length = DATA_LENGTH; +// dataInfo_.data = const_cast(reinterpret_cast(DATA_INFO)); +// extraInfo_.userId = USER_ID; +// extraInfo_.appId = BUNDLE_NAME; +// extraInfo_.storeId = STORE_ID; +// dataInfo_.extraInfo = extraInfo_; +// auto result = appPipeMgr.SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::ERROR); +// +// status = appPipeMgr.Stop(pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +//} /** -* @tc.name: ReuseConnect001 -* @tc.desc: ReuseConnect test +* @tc.name: ReuseConnectTest001 +* @tc.desc: reuse connect fail with all exception branch * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, ReuseConnect001, TestSize.Level0) +*/ +HWTEST_F(AppPipeMgrServiceTest, ReuseConnectTest001, TestSize.Level0) { AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - DeviceId deviceId; - auto status = appPipeMgr.ReuseConnect(pipeInfo, deviceId); - EXPECT_EQ(Status::INVALID_ARGUMENT, status); - - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - status = appPipeMgr.ReuseConnect(pipeInfo, deviceId); - EXPECT_EQ(Status::INVALID_ARGUMENT, status); - - PipeInfo pipeInfoNull; - deviceId.deviceId = "deviceId"; - status = appPipeMgr.ReuseConnect(pipeInfoNull, deviceId); - EXPECT_EQ(Status::INVALID_ARGUMENT, status); + auto status = appPipeMgr.ReuseConnect(pipeInfo_, deviceId_, extraInfo_); + ASSERT_EQ(status, Status::INVALID_ARGUMENT); + + pipeInfo_.pipeId = PIPE_ID; + status = appPipeMgr.ReuseConnect(pipeInfo_, deviceId_, extraInfo_); + ASSERT_EQ(status, Status::INVALID_ARGUMENT); + + deviceId_.deviceId = DEVICE_ID; + status = appPipeMgr.ReuseConnect(pipeInfo_, deviceId_, extraInfo_); + ASSERT_EQ(status, Status::ERROR); + + extraInfo_.userId = USER_ID; + status = appPipeMgr.ReuseConnect(pipeInfo_, deviceId_, extraInfo_); + ASSERT_EQ(status, Status::ERROR); + + extraInfo_.bundleName = BUNDLE_NAME; + status = appPipeMgr.ReuseConnect(pipeInfo_, deviceId_, extraInfo_); + ASSERT_EQ(status, Status::ERROR); + + extraInfo_.storeId = STORE_ID; + status = appPipeMgr.ReuseConnect(pipeInfo_, deviceId_, extraInfo_); + ASSERT_EQ(status, Status::ERROR); + + extraInfo_.tokenId = TOKEN_ID; + status = appPipeMgr.ReuseConnect(pipeInfo_, deviceId_, extraInfo_); + ASSERT_EQ(status, Status::KEY_NOT_FOUND); } /** -* @tc.name: ReuseConnect002 -* @tc.desc: ReuseConnect test +* @tc.name: ReuseConnectTest002 +* @tc.desc: reuse connect trigger success * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong - */ -HWTEST_F(AppPipeMgrServiceTest, ReuseConnect002, TestSize.Level0) -{ - AppPipeMgr appPipeMgr; - PipeInfo pipeInfo; - DeviceId deviceId; - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - deviceId.deviceId = "deviceId"; - auto status = appPipeMgr.ReuseConnect(pipeInfo, deviceId); - EXPECT_EQ(Status::INVALID_ARGUMENT, status); - - auto handler = std::make_shared(pipeInfo); - std::map> dataBusMap = {{"pipeId", handler}}; - appPipeMgr.dataBusMap_ = dataBusMap; - status = appPipeMgr.ReuseConnect(pipeInfo, deviceId); - EXPECT_EQ(Status::NOT_SUPPORT, status); -} +*/ +//HWTEST_F(AppPipeMgrServiceTest, ReuseConnectTest002, TestSize.Level0) +//{ +// AppPipeMgr appPipeMgr; +// pipeInfo_.pipeId = PIPE_ID; +// +// ConfigSocketId(VALID_SOCKET); +// auto status = appPipeMgr.Start(pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +// +// deviceId_.deviceId = DEVICE_ID; +// extraInfo_.userId = USER_ID; +// extraInfo_.bundleName = BUNDLE_NAME; +// extraInfo_.storeId = STORE_ID; +// extraInfo_.tokenId = TOKEN_ID; +// status = appPipeMgr.ReuseConnect(pipeInfo_, deviceId_, extraInfo_); +// ASSERT_EQ(status, Status::NOT_SUPPORT); +// +// status = appPipeMgr.Stop(pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +//} } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/device_manager_adapter_test.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/device_manager_adapter_test.cpp index a813fb8a..f08d3153 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/device_manager_adapter_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/device_manager_adapter_test.cpp @@ -14,6 +14,7 @@ */ #include "device_manager_adapter.h" +#include "device_manager/device_manager_delegate.h" #include "gtest/gtest.h" #include "accesstoken_kit.h" #include "executor_pool.h" @@ -622,4 +623,17 @@ HWTEST_F(DeviceManagerAdapterTest, IsSameAccount01, TestSize.Level0) auto status = DeviceManagerAdapter::GetInstance().IsSameAccount(networkId); EXPECT_EQ(status, false); } + +/** +* @tc.name: RegisterDelegateInstance +* @tc.desc: test DeviceManagerDelegate::RegisterInstance function +* @tc.type: FUNC +*/ +HWTEST_F(DeviceManagerAdapterTest, RegisterDelegateInstance, TestSize.Level0) +{ + DeviceManagerDelegate::RegisterInstance(&DeviceManagerAdapter::GetInstance()); + // Repeated registration + DeviceManagerDelegate::RegisterInstance(&DeviceManagerAdapter::GetInstance()); + EXPECT_NE(nullptr, DeviceManagerDelegate::GetInstance()); +} } // namespace \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/process_communicator_impl_test.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/process_communicator_impl_test.cpp index f5c4cc30..cf282fc9 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/process_communicator_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/process_communicator_impl_test.cpp @@ -1,506 +1,475 @@ -/* - * 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 "communication_provider.h" -#include "device_manager_adapter_mock.h" -#include "process_communicator_impl.h" -#include "softbus_adapter.h" -#include "softbus_error_code.h" - -using namespace testing; -using namespace testing::ext; -using namespace OHOS::AppDistributedKv; -using namespace OHOS::DistributedData; -using OnDeviceChange = DistributedDB::OnDeviceChange; -using OnDataReceive = DistributedDB::OnDataReceive; -using OnSendAble = DistributedDB::OnSendAble; -using DeviceInfos = DistributedDB::DeviceInfos; -using DeviceInfoo = OHOS::AppDistributedKv::DeviceInfo; -using UserInfo = DistributedDB::UserInfo; - -namespace OHOS::AppDistributedKv { -class MockCommunicationProvider : public CommunicationProvider { -public: - ~MockCommunicationProvider() = default; - static MockCommunicationProvider& Init() - { - static MockCommunicationProvider instance; - return instance; - } - MOCK_METHOD(Status, StartWatchDataChange, (const AppDataChangeListener *, const PipeInfo &), (override)); - MOCK_METHOD(Status, StopWatchDataChange, (const AppDataChangeListener *, const PipeInfo &), (override)); - MOCK_METHOD(Status, Start, (const PipeInfo&), (override)); - MOCK_METHOD(Status, Stop, (const PipeInfo&), (override)); - MOCK_METHOD((std::pair), SendData, (const PipeInfo&, const DeviceId&, - const DataInfo&, uint32_t, const MessageInfo &), (override)); - MOCK_METHOD(bool, IsSameStartedOnPeer, (const PipeInfo &, const DeviceId &), (const)); - MOCK_METHOD(Status, ReuseConnect, (const PipeInfo&, const DeviceId&), (override)); - MOCK_METHOD(void, SetDeviceQuery, (std::shared_ptr), (override)); - MOCK_METHOD(void, SetMessageTransFlag, (const PipeInfo &, bool), (override)); - MOCK_METHOD(Status, Broadcast, (const PipeInfo &, const LevelInfo &), (override)); - MOCK_METHOD(int32_t, ListenBroadcastMsg, (const PipeInfo &, - std::function), (override)); -}; - -CommunicationProvider& CommunicationProvider::GetInstance() -{ - return MockCommunicationProvider::Init(); -} - -std::shared_ptr CommunicationProvider::MakeCommunicationProvider() -{ - static std::shared_ptr instance( - &MockCommunicationProvider::Init(), - [](void*) { - } - ); - return instance; -} -} - -class ProcessCommunicatorImplTest : public testing::Test { -public: - static inline std::shared_ptr deviceManagerAdapterMock = nullptr; - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - - ProcessCommunicatorImpl* communicator_; - MockCommunicationProvider* mockProvider; -}; - -namespace OHOS::DistributedData { -class ConcreteRouteHeadHandler : public RouteHeadHandler { - public: - bool ParseHeadDataLen(const uint8_t *data, uint32_t totalLen, uint32_t &headSize) - { - if (totalLen == 0) { - return true; - } - return false; - } - - bool ParseHeadDataUser(const uint8_t *data, uint32_t totalLen, const std::string &label, - std::vector &userInfos) - { - if (totalLen == 0) { - return true; - } - return false; - } -}; -} - -void ProcessCommunicatorImplTest::SetUp(void) -{ - communicator_ = ProcessCommunicatorImpl::GetInstance(); - communicator_->Stop(); - mockProvider = &MockCommunicationProvider::Init(); -} - -void ProcessCommunicatorImplTest::TearDown(void) -{ - mockProvider = nullptr; -} - -void ProcessCommunicatorImplTest::SetUpTestCase(void) -{ - deviceManagerAdapterMock = std::make_shared(); - BDeviceManagerAdapter::deviceManagerAdapter = deviceManagerAdapterMock; -} - -void ProcessCommunicatorImplTest::TearDownTestCase() -{ - deviceManagerAdapterMock = nullptr; - BDeviceManagerAdapter::deviceManagerAdapter = nullptr; -} - -/** -* @tc.name: StartTest01 -* @tc.desc: StartTest01 test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, StartTest01, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - EXPECT_CALL(*mockProvider, Start(_)).WillOnce(Return(Status::SUCCESS)); - auto status = communicator_->Start("test_process"); - EXPECT_EQ(status, DistributedDB::OK); - EXPECT_CALL(*mockProvider, Start(_)).WillOnce(Return(Status::INVALID_ARGUMENT)); - status = communicator_->Start("test_process"); - EXPECT_EQ(status, DistributedDB::DB_ERROR); -} - -/** -* @tc.name: StopTest01 -* @tc.desc: StopTest01 test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, StopTest01, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - EXPECT_CALL(*mockProvider, Stop(_)).WillOnce(Return(Status::SUCCESS)); - auto status = communicator_->Stop(); - EXPECT_EQ(status, DistributedDB::OK); - EXPECT_CALL(*mockProvider, Stop(_)).WillRepeatedly(Return(Status::INVALID_ARGUMENT)); - status = communicator_->Stop(); - EXPECT_EQ(status, DistributedDB::DB_ERROR); -} - -/** -* @tc.name: RegOnDeviceChange -* @tc.desc: RegOnDeviceChange test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, RegOnDeviceChange, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - EXPECT_CALL(*deviceManagerAdapterMock, StartWatchDeviceChange(_, _)).WillOnce(Return(Status::SUCCESS)) - .WillRepeatedly(Return(Status::SUCCESS)); - EXPECT_CALL(*deviceManagerAdapterMock, StopWatchDeviceChange(_, _)).WillOnce(Return(Status::SUCCESS)) - .WillRepeatedly(Return(Status::SUCCESS)); - auto myOnDeviceChange = [](const DeviceInfos &devInfo, bool isOnline) {}; - OnDeviceChange callback; - callback = myOnDeviceChange; - auto status = communicator_->RegOnDeviceChange(callback); - EXPECT_EQ(status, DistributedDB::OK); - callback = nullptr; - status = communicator_->RegOnDeviceChange(callback); - EXPECT_EQ(status, DistributedDB::OK); - - EXPECT_CALL(*deviceManagerAdapterMock, StartWatchDeviceChange(_, _)).WillOnce(Return(Status::INVALID_ARGUMENT)) - .WillRepeatedly(Return(Status::SUCCESS)); - EXPECT_CALL(*deviceManagerAdapterMock, StopWatchDeviceChange(_, _)).WillOnce(Return(Status::INVALID_ARGUMENT)) - .WillRepeatedly(Return(Status::SUCCESS)); - status = communicator_->RegOnDeviceChange(callback); - EXPECT_EQ(status, DistributedDB::DB_ERROR); - callback = myOnDeviceChange; - status = communicator_->RegOnDeviceChange(callback); - EXPECT_EQ(status, DistributedDB::DB_ERROR); -} - -/** -* @tc.name: RegOnDataReceive -* @tc.desc: RegOnDataReceive test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, RegOnDataReceive, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - auto myOnDeviceChange = [](const DeviceInfos &devInfo, const uint8_t *data, uint32_t length) {}; - OnDataReceive callback; - callback = myOnDeviceChange; - EXPECT_CALL(*mockProvider, StartWatchDataChange(_, _)).WillRepeatedly(Return(Status::SUCCESS)); - auto status = communicator_->RegOnDataReceive(callback); - EXPECT_EQ(status, DistributedDB::OK); - EXPECT_CALL(*mockProvider, StartWatchDataChange(_, _)).WillRepeatedly(Return(Status::ERROR)); - status = communicator_->RegOnDataReceive(callback); - EXPECT_EQ(status, DistributedDB::DB_ERROR); - - callback = nullptr; - EXPECT_CALL(*mockProvider, StopWatchDataChange(_, _)).WillRepeatedly(Return(Status::SUCCESS)); - status = communicator_->RegOnDataReceive(callback); - EXPECT_EQ(status, DistributedDB::OK); - EXPECT_CALL(*mockProvider, StopWatchDataChange(_, _)).WillRepeatedly(Return(Status::ERROR)); - status = communicator_->RegOnDataReceive(callback); - EXPECT_EQ(status, DistributedDB::DB_ERROR); -} - -/** -* @tc.name: RegOnSendAble -* @tc.desc: RegOnSendAble test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, RegOnSendAble, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - OnSendAble sendAbleCallback = nullptr; - EXPECT_NO_FATAL_FAILURE(communicator_->RegOnSendAble(sendAbleCallback)); -} - -/** -* @tc.name: SendData -* @tc.desc: SendData test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, SendData, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - DeviceInfos deviceInfos = {"SendDataTest"}; - const uint8_t *data; - uint8_t exampleData[] = {0x01, 0x02, 0x03, 0x04}; - data = exampleData; - uint32_t length = 1; - uint32_t totalLength = 1; - std::pair myPair = std::make_pair(Status::RATE_LIMIT, 1); - EXPECT_CALL(*mockProvider, SendData(_, _, _, _, _)).WillRepeatedly(Return(myPair)); - auto status = communicator_->SendData(deviceInfos, data, length, totalLength); - EXPECT_EQ(status, DistributedDB::RATE_LIMIT); - myPair = {Status::SUCCESS, 1}; - EXPECT_CALL(*mockProvider, SendData(_, _, _, _, _)).WillRepeatedly(Return(myPair)); - status = communicator_->SendData(deviceInfos, data, length, totalLength); - EXPECT_EQ(status, DistributedDB::OK); - myPair = {Status::ERROR, static_cast(DistributedDB::BUSY)}; - EXPECT_CALL(*mockProvider, SendData(_, _, _, _, _)).WillRepeatedly(Return(myPair)); - status = communicator_->SendData(deviceInfos, data, length, totalLength); - EXPECT_EQ(status, DistributedDB::BUSY); - myPair = {Status::ERROR, 0}; - EXPECT_CALL(*mockProvider, SendData(_, _, _, _, _)).WillRepeatedly(Return(myPair)); - status = communicator_->SendData(deviceInfos, data, length, totalLength); - EXPECT_EQ(status, DistributedDB::DB_ERROR); -} - -/** -* @tc.name: GetRemoteOnlineDeviceInfosList -* @tc.desc: GetRemoteOnlineDeviceInfosList test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, GetRemoteOnlineDeviceInfosList, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - auto remoteDevInfos = communicator_->GetRemoteOnlineDeviceInfosList(); - EXPECT_EQ(remoteDevInfos.empty(), true); - - DeviceInfoo deviceInfo; - deviceInfo.uuid = "GetRemoteOnlineDeviceInfosList"; - std::vector devInfos; - devInfos.push_back(deviceInfo); - EXPECT_CALL(*deviceManagerAdapterMock, GetRemoteDevices()).WillRepeatedly(Return(devInfos)); - remoteDevInfos = communicator_->GetRemoteOnlineDeviceInfosList(); - EXPECT_EQ(remoteDevInfos[0].identifier, deviceInfo.uuid); -} - -/** -* @tc.name: OnMessage -* @tc.desc: OnMessage test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, OnMessage, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - DeviceInfoo deviceInfo; - deviceInfo.uuid = "OnMessageTest"; - uint8_t data[] = {0x10, 0x20, 0x30, 0x40, 0x50}; - uint8_t *ptr = data; - int size = 1; - PipeInfo pipeInfo; - pipeInfo.pipeId = "OnMessageTest01"; - pipeInfo.userId = "OnMessageTest02"; - auto myOnDeviceChange = [](const DeviceInfos &devInfo, const uint8_t *data, uint32_t length) {}; - communicator_->onDataReceiveHandler_ = nullptr; - EXPECT_NO_FATAL_FAILURE(communicator_->OnMessage(deviceInfo, ptr, size, pipeInfo)); - communicator_->onDataReceiveHandler_ = myOnDeviceChange; - EXPECT_NO_FATAL_FAILURE(communicator_->OnMessage(deviceInfo, ptr, size, pipeInfo)); -} - -/** -* @tc.name: OnDeviceChanged -* @tc.desc: OnDeviceChanged test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, OnDeviceChanged, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - DeviceInfoo deviceInfo; - deviceInfo.uuid = "cloudDeviceUuid"; - EXPECT_NO_FATAL_FAILURE(communicator_->OnDeviceChanged(deviceInfo, DeviceChangeType::DEVICE_ONREADY)); - EXPECT_NO_FATAL_FAILURE(communicator_->OnDeviceChanged(deviceInfo, DeviceChangeType::DEVICE_OFFLINE)); - deviceInfo.uuid = "OnDeviceChangedTest"; - communicator_->onDeviceChangeHandler_ = nullptr; - EXPECT_NO_FATAL_FAILURE(communicator_->OnDeviceChanged(deviceInfo, DeviceChangeType::DEVICE_OFFLINE)); - auto myOnDeviceChange = [](const DeviceInfos &devInfo, bool isOnline) {}; - communicator_->onDeviceChangeHandler_ = myOnDeviceChange; - EXPECT_NO_FATAL_FAILURE(communicator_->OnDeviceChanged(deviceInfo, DeviceChangeType::DEVICE_OFFLINE)); -} - -/** -* @tc.name: OnSessionReady -* @tc.desc: OnSessionReady test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, OnSessionReady, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - DeviceInfoo deviceInfo; - deviceInfo.uuid = "OnSessionReadyTest"; - communicator_->sessionListener_ = nullptr; - EXPECT_NO_FATAL_FAILURE(communicator_->OnSessionReady(deviceInfo, 1)); - auto myOnSendAble = [](const DeviceInfos &deviceInfo, int deviceCommErrCode) {}; - communicator_->sessionListener_ = myOnSendAble; - EXPECT_NO_FATAL_FAILURE(communicator_->OnSessionReady(deviceInfo, 1)); -} - -/** -* @tc.name: GetExtendHeaderHandle -* @tc.desc: GetExtendHeaderHandle test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, GetExtendHeaderHandle, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - communicator_->routeHeadHandlerCreator_ = nullptr; - DistributedDB::ExtendInfo info; - auto handle = communicator_->GetExtendHeaderHandle(info); - EXPECT_EQ(handle, nullptr); - communicator_->routeHeadHandlerCreator_ = [](const DistributedDB::ExtendInfo &info) -> - std::shared_ptr { - return std::make_shared(); - }; - handle = communicator_->GetExtendHeaderHandle(info); - EXPECT_NE(handle, nullptr); -} - -/** -* @tc.name: GetDataHeadInfo -* @tc.desc: GetDataHeadInfo test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, GetDataHeadInfo, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - uint8_t data[] = {0x10, 0x20, 0x30, 0x40, 0x50}; - uint8_t *ptr = data; - uint32_t totalLen = 1; - uint32_t headLength = 1; - communicator_->routeHeadHandlerCreator_ = nullptr; - auto status = communicator_->GetDataHeadInfo(ptr, totalLen, headLength); - EXPECT_EQ(status, DistributedDB::DB_ERROR); - - communicator_->routeHeadHandlerCreator_ = [](const DistributedDB::ExtendInfo &info) -> - std::shared_ptr { - return std::make_shared(); - }; - status = communicator_->GetDataHeadInfo(ptr, totalLen, headLength); - EXPECT_EQ(status, DistributedDB::INVALID_FORMAT); - totalLen = 0; - status = communicator_->GetDataHeadInfo(ptr, totalLen, headLength); - EXPECT_EQ(status, DistributedDB::OK); -} - -/** -* @tc.name: GetDataUserInfo -* @tc.desc: GetDataUserInfo test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, GetDataUserInfo, TestSize.Level0) -{ - ASSERT_NE(communicator_, nullptr); - uint8_t data[] = {0x10, 0x20, 0x30, 0x40, 0x50}; - uint8_t *ptr = data; - uint32_t totalLen = 1; - std::string label = "GetDataUserInfoTest"; - std::vector userInfos; - UserInfo user1{"GetDataUserInfo01"}; - UserInfo user2{"GetDataUserInfo02"}; - UserInfo user3{"GetDataUserInfo03"}; - communicator_->routeHeadHandlerCreator_ = nullptr; - auto status = communicator_->GetDataUserInfo(ptr, totalLen, label, userInfos); - EXPECT_EQ(status, DistributedDB::DB_ERROR); - - communicator_->routeHeadHandlerCreator_ = [](const DistributedDB::ExtendInfo &info) -> - std::shared_ptr { - return std::make_shared(); - }; - status = communicator_->GetDataUserInfo(ptr, totalLen, label, userInfos); - EXPECT_EQ(status, DistributedDB::INVALID_FORMAT); - totalLen = 0; - EXPECT_EQ(userInfos.empty(), true); - status = communicator_->GetDataUserInfo(ptr, totalLen, label, userInfos); - EXPECT_EQ(status, DistributedDB::NO_PERMISSION); - userInfos.push_back(user1); - userInfos.push_back(user2); - userInfos.push_back(user3); - status = communicator_->GetDataUserInfo(ptr, totalLen, label, userInfos); - EXPECT_EQ(status, DistributedDB::OK); -} - -/** -* @tc.name: ReuseConnect01 -* @tc.desc: reuse connect -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(ProcessCommunicatorImplTest, ReuseConnect01, TestSize.Level0) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo pipe; - pipe.pipeId = "appId"; - pipe.userId = "groupId"; - DeviceId device = {"DeviceId"}; - auto status = SoftBusAdapter::GetInstance()->ReuseConnect(pipe, device); - EXPECT_EQ(status, Status::NOT_SUPPORT); - EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(testing::_)).WillOnce(testing::Return(true)) - .WillRepeatedly(testing::Return(true)); - status = SoftBusAdapter::GetInstance()->ReuseConnect(pipe, device); - EXPECT_EQ(status, Status::NETWORK_ERROR); -} - -/** -* @tc.name: CloseSession -* @tc.desc: close session -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(ProcessCommunicatorImplTest, CloseSession, TestSize.Level1) -{ - std::string networkId = "networkId"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - std::string uuid = "CloseSessionTest"; - EXPECT_CALL(*deviceManagerAdapterMock, GetUuidByNetworkId(testing::_)).WillOnce(testing::Return(uuid)) - .WillRepeatedly(testing::Return(uuid)); - std::shared_ptr conn = nullptr; - std::vector> clients; - clients.emplace_back(conn); - auto result = SoftBusAdapter::GetInstance()->connects_.Insert(uuid, clients); - EXPECT_EQ(result, true); - auto status = SoftBusAdapter::GetInstance()->CloseSession(networkId); - SoftBusAdapter::GetInstance()->connects_.Clear(); - EXPECT_EQ(status, true); -} \ 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. +// */ +// +//#include +//#include +//#include +//#include +//#include +//#include +//#include "communication_provider.h" +//#include "device_manager_adapter_mock.h" +//#include "process_communicator_impl.h" +//#include "softbus_adapter.h" +//#include "softbus_error_code.h" +// +//using namespace testing; +//using namespace testing::ext; +//using namespace OHOS::AppDistributedKv; +//using namespace OHOS::DistributedData; +//using OnDeviceChange = DistributedDB::OnDeviceChange; +//using OnDataReceive = DistributedDB::OnDataReceive; +//using OnSendAble = DistributedDB::OnSendAble; +//using DeviceInfos = DistributedDB::DeviceInfos; +//using DeviceInfoo = OHOS::AppDistributedKv::DeviceInfo; +//using UserInfo = DistributedDB::UserInfo; +//using DataHeadInfo = DistributedDB::DataHeadInfo; +//using DataUserInfo = DistributedDB::DataUserInfo; +//namespace OHOS::AppDistributedKv { +//class MockCommunicationProvider : public CommunicationProvider { +//public: +// ~MockCommunicationProvider() = default; +// static MockCommunicationProvider& Init() +// { +// static MockCommunicationProvider instance; +// return instance; +// } +// MOCK_METHOD(Status, StartWatchDataChange, (const AppDataChangeListener *, const PipeInfo &), (override)); +// MOCK_METHOD(Status, StopWatchDataChange, (const AppDataChangeListener *, const PipeInfo &), (override)); +// MOCK_METHOD(Status, Start, (const PipeInfo&), (override)); +// MOCK_METHOD(Status, Stop, (const PipeInfo&), (override)); +// MOCK_METHOD((std::pair), SendData, (const PipeInfo&, const DeviceId&, +// const DataInfo&, uint32_t, const MessageInfo &), (override)); +// MOCK_METHOD(bool, IsSameStartedOnPeer, (const PipeInfo &, const DeviceId &), (const)); +// MOCK_METHOD(Status, ReuseConnect, (const PipeInfo&, const DeviceId&, const ExtraDataInfo&), (override)); +// MOCK_METHOD(void, SetDeviceQuery, (std::shared_ptr), (override)); +// MOCK_METHOD(void, SetMessageTransFlag, (const PipeInfo &, bool), (override)); +// MOCK_METHOD(Status, Broadcast, (const PipeInfo &, const LevelInfo &), (override)); +// MOCK_METHOD(int32_t, ListenBroadcastMsg, (const PipeInfo &, +// std::function), (override)); +//}; +// +//CommunicationProvider& CommunicationProvider::GetInstance() +//{ +// return MockCommunicationProvider::Init(); +//} +// +//std::shared_ptr CommunicationProvider::MakeCommunicationProvider() +//{ +// static std::shared_ptr instance( +// &MockCommunicationProvider::Init(), +// [](void*) { +// } +// ); +// return instance; +//} +//} +// +//class ProcessCommunicatorImplTest : public testing::Test { +//public: +// static inline std::shared_ptr deviceManagerAdapterMock = nullptr; +// static void SetUpTestCase(void); +// static void TearDownTestCase(void); +// void SetUp(); +// void TearDown(); +// +// ProcessCommunicatorImpl* communicator_; +// MockCommunicationProvider* mockProvider; +//}; +// +//namespace OHOS::DistributedData { +//class ConcreteRouteHeadHandler : public RouteHeadHandler { +// public: +// bool ParseHeadDataLen(const uint8_t *data, uint32_t totalLen, uint32_t &headSize, const std::string &device) +// { +// if (totalLen == 0) { +// return true; +// } +// return false; +// } +// +// bool ParseHeadDataUser(const uint8_t *data, uint32_t totalLen, const std::string &label, +// std::vector &userInfos) +// { +// if (totalLen == 0) { +// return true; +// } +// return false; +// } +//}; +//} +// +//void ProcessCommunicatorImplTest::SetUp(void) +//{ +// communicator_ = ProcessCommunicatorImpl::GetInstance(); +// communicator_->Stop(); +// mockProvider = &MockCommunicationProvider::Init(); +//} +// +//void ProcessCommunicatorImplTest::TearDown(void) +//{ +// mockProvider = nullptr; +//} +// +//void ProcessCommunicatorImplTest::SetUpTestCase(void) +//{ +// deviceManagerAdapterMock = std::make_shared(); +// BDeviceManagerAdapter::deviceManagerAdapter = deviceManagerAdapterMock; +//} +// +//void ProcessCommunicatorImplTest::TearDownTestCase() +//{ +// deviceManagerAdapterMock = nullptr; +// BDeviceManagerAdapter::deviceManagerAdapter = nullptr; +//} +// +///** +//* @tc.name: StartTest01 +//* @tc.desc: StartTest01 test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, StartTest01, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// EXPECT_CALL(*mockProvider, Start(_)).WillOnce(Return(Status::SUCCESS)); +// auto status = communicator_->Start("test_process"); +// EXPECT_EQ(status, DistributedDB::OK); +// EXPECT_CALL(*mockProvider, Start(_)).WillOnce(Return(Status::INVALID_ARGUMENT)); +// status = communicator_->Start("test_process"); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +//} +// +///** +//* @tc.name: StopTest01 +//* @tc.desc: StopTest01 test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, StopTest01, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// EXPECT_CALL(*mockProvider, Stop(_)).WillOnce(Return(Status::SUCCESS)); +// auto status = communicator_->Stop(); +// EXPECT_EQ(status, DistributedDB::OK); +// EXPECT_CALL(*mockProvider, Stop(_)).WillRepeatedly(Return(Status::INVALID_ARGUMENT)); +// status = communicator_->Stop(); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +//} +// +///** +//* @tc.name: RegOnDeviceChange +//* @tc.desc: RegOnDeviceChange test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, RegOnDeviceChange, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// EXPECT_CALL(*deviceManagerAdapterMock, StartWatchDeviceChange(_, _)).WillOnce(Return(Status::SUCCESS)) +// .WillRepeatedly(Return(Status::SUCCESS)); +// EXPECT_CALL(*deviceManagerAdapterMock, StopWatchDeviceChange(_, _)).WillOnce(Return(Status::SUCCESS)) +// .WillRepeatedly(Return(Status::SUCCESS)); +// auto myOnDeviceChange = [](const DeviceInfos &devInfo, bool isOnline) {}; +// OnDeviceChange callback; +// callback = myOnDeviceChange; +// auto status = communicator_->RegOnDeviceChange(callback); +// EXPECT_EQ(status, DistributedDB::OK); +// callback = nullptr; +// status = communicator_->RegOnDeviceChange(callback); +// EXPECT_EQ(status, DistributedDB::OK); +// +// EXPECT_CALL(*deviceManagerAdapterMock, StartWatchDeviceChange(_, _)).WillOnce(Return(Status::INVALID_ARGUMENT)) +// .WillRepeatedly(Return(Status::SUCCESS)); +// EXPECT_CALL(*deviceManagerAdapterMock, StopWatchDeviceChange(_, _)).WillOnce(Return(Status::INVALID_ARGUMENT)) +// .WillRepeatedly(Return(Status::SUCCESS)); +// status = communicator_->RegOnDeviceChange(callback); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +// callback = myOnDeviceChange; +// status = communicator_->RegOnDeviceChange(callback); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +//} +// +///** +//* @tc.name: RegOnDataReceive +//* @tc.desc: RegOnDataReceive test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, RegOnDataReceive, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// auto myOnDeviceChange = [](const DeviceInfos &devInfo, const uint8_t *data, uint32_t length) {}; +// OnDataReceive callback; +// callback = myOnDeviceChange; +// EXPECT_CALL(*mockProvider, StartWatchDataChange(_, _)).WillRepeatedly(Return(Status::SUCCESS)); +// auto status = communicator_->RegOnDataReceive(callback); +// EXPECT_EQ(status, DistributedDB::OK); +// EXPECT_CALL(*mockProvider, StartWatchDataChange(_, _)).WillRepeatedly(Return(Status::ERROR)); +// status = communicator_->RegOnDataReceive(callback); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +// +// callback = nullptr; +// EXPECT_CALL(*mockProvider, StopWatchDataChange(_, _)).WillRepeatedly(Return(Status::SUCCESS)); +// status = communicator_->RegOnDataReceive(callback); +// EXPECT_EQ(status, DistributedDB::OK); +// EXPECT_CALL(*mockProvider, StopWatchDataChange(_, _)).WillRepeatedly(Return(Status::ERROR)); +// status = communicator_->RegOnDataReceive(callback); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +//} +// +///** +//* @tc.name: RegOnSendAble +//* @tc.desc: RegOnSendAble test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, RegOnSendAble, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// OnSendAble sendAbleCallback = nullptr; +// EXPECT_NO_FATAL_FAILURE(communicator_->RegOnSendAble(sendAbleCallback)); +//} +// +///** +//* @tc.name: SendData +//* @tc.desc: SendData test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, SendData, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// DeviceInfos deviceInfos = {"SendDataTest"}; +// const uint8_t *data; +// uint8_t exampleData[] = {0x01, 0x02, 0x03, 0x04}; +// data = exampleData; +// uint32_t length = 1; +// uint32_t totalLength = 1; +// std::pair myPair = std::make_pair(Status::RATE_LIMIT, 1); +// EXPECT_CALL(*mockProvider, SendData(_, _, _, _, _)).WillRepeatedly(Return(myPair)); +// auto status = communicator_->SendData(deviceInfos, data, length, totalLength); +// EXPECT_EQ(status, DistributedDB::RATE_LIMIT); +// myPair = {Status::SUCCESS, 1}; +// EXPECT_CALL(*mockProvider, SendData(_, _, _, _, _)).WillRepeatedly(Return(myPair)); +// status = communicator_->SendData(deviceInfos, data, length, totalLength); +// EXPECT_EQ(status, DistributedDB::OK); +// myPair = {Status::ERROR, static_cast(DistributedDB::BUSY)}; +// EXPECT_CALL(*mockProvider, SendData(_, _, _, _, _)).WillRepeatedly(Return(myPair)); +// status = communicator_->SendData(deviceInfos, data, length, totalLength); +// EXPECT_EQ(status, DistributedDB::BUSY); +// myPair = {Status::ERROR, 0}; +// EXPECT_CALL(*mockProvider, SendData(_, _, _, _, _)).WillRepeatedly(Return(myPair)); +// status = communicator_->SendData(deviceInfos, data, length, totalLength); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +//} +// +///** +//* @tc.name: GetRemoteOnlineDeviceInfosList +//* @tc.desc: GetRemoteOnlineDeviceInfosList test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, GetRemoteOnlineDeviceInfosList, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// auto remoteDevInfos = communicator_->GetRemoteOnlineDeviceInfosList(); +// EXPECT_EQ(remoteDevInfos.empty(), true); +// +// DeviceInfoo deviceInfo; +// deviceInfo.uuid = "GetRemoteOnlineDeviceInfosList"; +// std::vector devInfos; +// devInfos.push_back(deviceInfo); +// EXPECT_CALL(*deviceManagerAdapterMock, GetRemoteDevices()).WillRepeatedly(Return(devInfos)); +// remoteDevInfos = communicator_->GetRemoteOnlineDeviceInfosList(); +// EXPECT_EQ(remoteDevInfos[0].identifier, deviceInfo.uuid); +//} +// +///** +//* @tc.name: OnMessage +//* @tc.desc: OnMessage test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, OnMessage, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// DeviceInfoo deviceInfo; +// deviceInfo.uuid = "OnMessageTest"; +// uint8_t data[] = {0x10, 0x20, 0x30, 0x40, 0x50}; +// uint8_t *ptr = data; +// int size = 1; +// PipeInfo pipeInfo; +// pipeInfo.pipeId = "OnMessageTest01"; +// pipeInfo.userId = "OnMessageTest02"; +// auto myOnDeviceChange = [](const DeviceInfos &devInfo, const uint8_t *data, uint32_t length) {}; +// communicator_->onDataReceiveHandler_ = nullptr; +// EXPECT_NO_FATAL_FAILURE(communicator_->OnMessage(deviceInfo, ptr, size, pipeInfo)); +// communicator_->onDataReceiveHandler_ = myOnDeviceChange; +// EXPECT_NO_FATAL_FAILURE(communicator_->OnMessage(deviceInfo, ptr, size, pipeInfo)); +//} +// +///** +//* @tc.name: OnDeviceChanged +//* @tc.desc: OnDeviceChanged test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, OnDeviceChanged, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// DeviceInfoo deviceInfo; +// deviceInfo.uuid = "cloudDeviceUuid"; +// EXPECT_NO_FATAL_FAILURE(communicator_->OnDeviceChanged(deviceInfo, DeviceChangeType::DEVICE_ONREADY)); +// EXPECT_NO_FATAL_FAILURE(communicator_->OnDeviceChanged(deviceInfo, DeviceChangeType::DEVICE_OFFLINE)); +// deviceInfo.uuid = "OnDeviceChangedTest"; +// communicator_->onDeviceChangeHandler_ = nullptr; +// EXPECT_NO_FATAL_FAILURE(communicator_->OnDeviceChanged(deviceInfo, DeviceChangeType::DEVICE_OFFLINE)); +// auto myOnDeviceChange = [](const DeviceInfos &devInfo, bool isOnline) {}; +// communicator_->onDeviceChangeHandler_ = myOnDeviceChange; +// EXPECT_NO_FATAL_FAILURE(communicator_->OnDeviceChanged(deviceInfo, DeviceChangeType::DEVICE_OFFLINE)); +//} +// +///** +//* @tc.name: OnSessionReady +//* @tc.desc: OnSessionReady test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, OnSessionReady, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// DeviceInfoo deviceInfo; +// deviceInfo.uuid = "OnSessionReadyTest"; +// communicator_->sessionListener_ = nullptr; +// EXPECT_NO_FATAL_FAILURE(communicator_->OnSessionReady(deviceInfo, 1)); +// auto myOnSendAble = [](const DeviceInfos &deviceInfo, int deviceCommErrCode) {}; +// communicator_->sessionListener_ = myOnSendAble; +// EXPECT_NO_FATAL_FAILURE(communicator_->OnSessionReady(deviceInfo, 1)); +//} +// +///** +//* @tc.name: GetExtendHeaderHandle +//* @tc.desc: GetExtendHeaderHandle test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, GetExtendHeaderHandle, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// communicator_->routeHeadHandlerCreator_ = nullptr; +// DistributedDB::ExtendInfo info; +// auto handle = communicator_->GetExtendHeaderHandle(info); +// EXPECT_EQ(handle, nullptr); +// communicator_->routeHeadHandlerCreator_ = [](const DistributedDB::ExtendInfo &info) -> +// std::shared_ptr { +// return std::make_shared(); +// }; +// handle = communicator_->GetExtendHeaderHandle(info); +// EXPECT_NE(handle, nullptr); +//} +// +///** +//* @tc.name: GetDataHeadInfo +//* @tc.desc: GetDataHeadInfo test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, GetDataHeadInfo, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// uint8_t data[] = {0x10, 0x20, 0x30, 0x40, 0x50}; +// uint8_t *ptr = data; +// uint32_t headLength = 1; +// DataHeadInfo dataHeadInfo { ptr, 1, "" }; +// communicator_->routeHeadHandlerCreator_ = nullptr; +// auto status = communicator_->GetDataHeadInfo(dataHeadInfo, headLength); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +// +// communicator_->routeHeadHandlerCreator_ = [](const DistributedDB::ExtendInfo &info) -> +// std::shared_ptr { +// return std::make_shared(); +// }; +// status = communicator_->GetDataHeadInfo(dataHeadInfo, headLength); +// EXPECT_EQ(status, DistributedDB::INVALID_FORMAT); +// dataHeadInfo.totalLen = 0; +// status = communicator_->GetDataHeadInfo(dataHeadInfo, headLength); +// EXPECT_EQ(status, DistributedDB::OK); +//} +// +///** +//* @tc.name: GetDataUserInfo +//* @tc.desc: GetDataUserInfo test +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: wangbin +// */ +//HWTEST_F(ProcessCommunicatorImplTest, GetDataUserInfo, TestSize.Level0) +//{ +// ASSERT_NE(communicator_, nullptr); +// uint8_t data[] = {0x10, 0x20, 0x30, 0x40, 0x50}; +// uint8_t *ptr = data; +// DataUserInfo dataUserInfo { ptr, 1, "GetDataUserInfoTest", "" }; +// std::vector userInfos; +// UserInfo user1{"GetDataUserInfo01"}; +// UserInfo user2{"GetDataUserInfo02"}; +// UserInfo user3{"GetDataUserInfo03"}; +// communicator_->routeHeadHandlerCreator_ = nullptr; +// auto status = communicator_->GetDataUserInfo(dataUserInfo, userInfos); +// EXPECT_EQ(status, DistributedDB::DB_ERROR); +// +// communicator_->routeHeadHandlerCreator_ = [](const DistributedDB::ExtendInfo &info) -> +// std::shared_ptr { +// return std::make_shared(); +// }; +// status = communicator_->GetDataUserInfo(dataUserInfo, userInfos); +// EXPECT_EQ(status, DistributedDB::INVALID_FORMAT); +//} +// +///** +//* @tc.name: CloseSession +//* @tc.desc: close session +//* @tc.type: FUNC +//* @tc.author: nhj +//*/ +//HWTEST_F(ProcessCommunicatorImplTest, CloseSession, TestSize.Level1) +//{ +// std::string networkId = "networkId"; +// auto flag = SoftBusAdapter::GetInstance(); +// ASSERT_NE(flag, nullptr); +// std::string uuid = "CloseSessionTest"; +// EXPECT_CALL(*deviceManagerAdapterMock, GetUuidByNetworkId(testing::_)).WillOnce(testing::Return(uuid)) +// .WillRepeatedly(testing::Return(uuid)); +// std::shared_ptr conn = nullptr; +// std::vector> clients; +// clients.emplace_back(conn); +// auto result = SoftBusAdapter::GetInstance()->connects_.Insert(uuid, clients); +// EXPECT_EQ(result, true); +// auto status = SoftBusAdapter::GetInstance()->CloseSession(networkId); +// SoftBusAdapter::GetInstance()->connects_.Clear(); +// EXPECT_EQ(status, true); +//} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/softbus_adapter_standard_test.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/softbus_adapter_standard_test.cpp index 4666457e..21b8ccc0 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/softbus_adapter_standard_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/softbus_adapter_standard_test.cpp @@ -1,651 +1,469 @@ -/* - * Copyright (c) 2022 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 "app_device_change_listener.h" -#include -#include "gtest/gtest.h" -#include -#include "softbus_adapter.h" -#include "softbus_adapter_standard.cpp" -#include "softbus_error_code.h" -#include "types.h" -#include -#include - -namespace OHOS::Test { -using namespace testing::ext; -using namespace OHOS::AppDistributedKv; -using namespace OHOS::DistributedData; -using DeviceInfo = OHOS::AppDistributedKv::DeviceInfo; -class AppDataChangeListenerImpl : public AppDataChangeListener { - struct ServerSocketInfo { - std::string name; /**< Peer socket name */ - std::string networkId; /**< Peer network ID */ - std::string pkgName; /**< Peer package name */ - }; - - void OnMessage(const OHOS::AppDistributedKv::DeviceInfo &info, const uint8_t *ptr, const int size, - const struct PipeInfo &id) const override; -}; - -void AppDataChangeListenerImpl::OnMessage(const OHOS::AppDistributedKv::DeviceInfo &info, - const uint8_t *ptr, const int size, const struct PipeInfo &id) const -{} - -class SoftbusAdapterStandardTest : public testing::Test { -public: - static void SetUpTestCase(void) {} - static void TearDownTestCase(void) {} - void SetUp() {} - void TearDown() {} -protected: - static constexpr uint32_t DEFAULT_MTU_SIZE = 4096 * 1024u; - static constexpr uint32_t DEFAULT_TIMEOUT = 30 * 1000; -}; - -/** -* @tc.name: StartWatchDeviceChange -* @tc.desc: start watch data change -* @tc.type: FUNC -* @tc.require: -* @tc.author: nhj - */ -HWTEST_F(SoftbusAdapterStandardTest, StartWatchDeviceChange, TestSize.Level0) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - auto status = SoftBusAdapter::GetInstance()->StartWatchDataChange(nullptr, {}); - EXPECT_EQ(status, Status::INVALID_ARGUMENT); -} - -/** -* @tc.name: StartWatchDeviceChange -* @tc.desc: start watch data change -* @tc.type: FUNC -* @tc.require: -* @tc.author: nhj - */ -HWTEST_F(SoftbusAdapterStandardTest, StartWatchDeviceChange01, TestSize.Level0) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo appId; - appId.pipeId = "appId"; - appId.userId = "groupId"; - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - auto status = SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, appId); - EXPECT_EQ(status, Status::SUCCESS); - status = SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, appId); - delete dataListener; - EXPECT_EQ(status, Status::ERROR); -} - -/** -* @tc.name: StartWatchDeviceChange -* @tc.desc: start watch data change -* @tc.type: FUNC -* @tc.require: -* @tc.author: nhj - */ -HWTEST_F(SoftbusAdapterStandardTest, StartWatchDeviceChange02, TestSize.Level0) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo appId; - appId.pipeId = ""; - appId.userId = "groupId"; - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - auto status = SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, appId); - delete dataListener; - EXPECT_EQ(status, Status::SUCCESS); -} - -/** -* @tc.name: StartWatchDeviceChange03 -* @tc.desc:the observer is nullptr -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, StartWatchDeviceChange03, TestSize.Level1) -{ - PipeInfo appId; - appId.pipeId = "appId06"; - appId.userId = "groupId06"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - SoftBusAdapter::GetInstance()->StartWatchDataChange(nullptr, appId); - auto status = SoftBusAdapter::GetInstance()->StartWatchDataChange(nullptr, appId); - EXPECT_EQ(Status::INVALID_ARGUMENT, status); -} - -/** -* @tc.name: StopWatchDataChange -* @tc.desc: stop watch data change -* @tc.type: FUNC -* @tc.require: -* @tc.author: nhj - */ -HWTEST_F(SoftbusAdapterStandardTest, StopWatchDataChange, TestSize.Level0) -{ - PipeInfo appId; - appId.pipeId = "appId"; - appId.userId = "groupId"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - auto status = SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, appId); - EXPECT_EQ(status, Status::SUCCESS); - status = SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, appId); - delete dataListener; - EXPECT_EQ(status, Status::ERROR); -} - -/** -* @tc.name: StopWatchDataChange -* @tc.desc: stop watch data change -* @tc.type: FUNC -* @tc.require: -* @tc.author: nhj - */ -HWTEST_F(SoftbusAdapterStandardTest, StopWatchDataChange01, TestSize.Level0) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo appId; - appId.pipeId = ""; - appId.userId = "groupId"; - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - auto status = SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, appId); - delete dataListener; - EXPECT_EQ(status, Status::SUCCESS); -} - -/** -* @tc.name: GetExpireTime -* @tc.desc: GetExpireTime Test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(SoftbusAdapterStandardTest, GetExpireTime, TestSize.Level0) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo appId; - appId.pipeId = "appId"; - appId.userId = "groupId"; - DeviceId id = {"DeviceId"}; - std::shared_ptr conn = std::make_shared(appId, id, SoftBusClient::QoSType::QOS_HML); - EXPECT_NO_FATAL_FAILURE(SoftBusAdapter::GetInstance()->GetExpireTime(conn)); -} - -/** -* @tc.name: SendData -* @tc.desc: parse sent data -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, SendData, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - PipeInfo id; - id.pipeId = "appId"; - id.userId = "groupId"; - auto secRegister = SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, id); - EXPECT_EQ(Status::SUCCESS, secRegister); - std::string content = "Helloworlds"; - const uint8_t *t = reinterpret_cast(content.c_str()); - DeviceId di = {"DeviceId"}; - DataInfo data = { const_cast(t), static_cast(content.length())}; - auto status = SoftBusAdapter::GetInstance()->SendData(id, di, data, 11, { MessageType::DEFAULT }); - EXPECT_NE(status.first, Status::SUCCESS); - SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, id); - delete dataListener; -} - -/** -* @tc.name: SendData01 -* @tc.desc: parse sent data -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, SendData01, TestSize.Level1) -{ - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - PipeInfo pipe01; - pipe01.pipeId = "appId"; - pipe01.userId = "groupId"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - auto secRegister = SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, pipe01); - EXPECT_EQ(Status::SUCCESS, secRegister); - std::string content = ""; - const uint8_t *t = reinterpret_cast(content.c_str()); - DeviceId di = {"DeviceId"}; - DataInfo data = { const_cast(t), static_cast(content.length())}; - auto status = SoftBusAdapter::GetInstance()->SendData(pipe01, di, data, 10, { MessageType::FILE }); - EXPECT_NE(status.first, Status::ERROR); - EXPECT_EQ(status.first, Status::RATE_LIMIT); - SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, pipe01); - delete dataListener; -} - -/** -* @tc.name: StartCloseSessionTask -* @tc.desc: StartCloseSessionTask tests -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, StartCloseSessionTask, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - std::shared_ptr conn = nullptr; - std::vector> clients; - clients.emplace_back(conn); - auto status = SoftBusAdapter::GetInstance()->connects_.Insert("deviceId01", clients); - EXPECT_EQ(status, true); - SoftBusAdapter::GetInstance()->connects_.Clear(); - EXPECT_NO_FATAL_FAILURE(SoftBusAdapter::GetInstance()->StartCloseSessionTask("deviceId02")); -} - -/** -* @tc.name: OnClientShutdown -* @tc.desc: DelConnect tests -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, OnClientShutdown, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo appId; - appId.pipeId = "appId"; - appId.userId = "groupId"; - DeviceId id = {"DeviceId"}; - std::shared_ptr conn1 = std::make_shared(appId, id, SoftBusClient::QoSType::QOS_HML); - std::shared_ptr conn2 = nullptr; - std::vector> clients; - clients.emplace_back(conn1); - clients.emplace_back(conn2); - auto status = SoftBusAdapter::GetInstance()->connects_.Insert("deviceId01", clients); - EXPECT_EQ(status, true); - status = SoftBusAdapter::GetInstance()->connects_.Insert("deviceId02", {}); - EXPECT_EQ(status, true); - auto name = SoftBusAdapter::GetInstance()->OnClientShutdown(-1, true); - EXPECT_EQ(name, "deviceId01 "); - name = SoftBusAdapter::GetInstance()->OnClientShutdown(-1, false); - EXPECT_EQ(name, ""); - name = SoftBusAdapter::GetInstance()->OnClientShutdown(1, true); - SoftBusAdapter::GetInstance()->connects_.Clear(); - EXPECT_EQ(name, ""); -} - -/** -* @tc.name: NotifyDataListeners -* @tc.desc: NotifyDataListeners tests -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, NotifyDataListeners, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo appId; - appId.pipeId = "appId"; - appId.userId = "groupId"; - std::string content = "Helloworlds"; - const uint8_t *t = reinterpret_cast(content.c_str()); - SoftBusAdapter::GetInstance()->dataChangeListeners_.Clear(); - EXPECT_NO_FATAL_FAILURE(SoftBusAdapter::GetInstance()->NotifyDataListeners(t, 1, "deviceId", appId)); - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - SoftBusAdapter::GetInstance()->dataChangeListeners_.Insert(appId.pipeId, dataListener); - delete dataListener; - SoftBusAdapter::GetInstance()->dataChangeListeners_.Clear(); - EXPECT_NO_FATAL_FAILURE(SoftBusAdapter::GetInstance()->NotifyDataListeners(t, 1, "deviceId", appId)); -} - -/** -* @tc.name: ListenBroadcastMsg -* @tc.desc: ListenBroadcastMsg tests -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, ListenBroadcastMsg, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - SoftBusAdapter::GetInstance()->onBroadcast_= nullptr; - PipeInfo appId; - appId.pipeId = "appId"; - appId.userId = "groupId"; - auto result = SoftBusAdapter::GetInstance()->ListenBroadcastMsg(appId, nullptr); - EXPECT_EQ(result, SoftBusErrNo::SOFTBUS_INVALID_PARAM); - - auto listener = [](const std::string &message, const LevelInfo &info) {}; - result = SoftBusAdapter::GetInstance()->ListenBroadcastMsg(appId, listener); - EXPECT_EQ(result, SoftBusErrNo::SOFTBUS_INVALID_PARAM); - result = SoftBusAdapter::GetInstance()->ListenBroadcastMsg(appId, listener); - EXPECT_EQ(result, SoftBusErrNo::SOFTBUS_ALREADY_EXISTED); -} - -/** -* @tc.name: OnBroadcast -* @tc.desc: OnBroadcast tests -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, OnBroadcast, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - DeviceId id = {"DeviceId"}; - LevelInfo level; - level.dynamic = 1; - level.statics = 1; - level.switches = 1; - level.switchesLen = 1; - EXPECT_NE(SoftBusAdapter::GetInstance()->onBroadcast_, nullptr); - EXPECT_NO_FATAL_FAILURE(SoftBusAdapter::GetInstance()->OnBroadcast(id, level)); - SoftBusAdapter::GetInstance()->onBroadcast_ = nullptr; - EXPECT_NO_FATAL_FAILURE(SoftBusAdapter::GetInstance()->OnBroadcast(id, level)); -} - -/** -* @tc.name: OnClientSocketChanged -* @tc.desc: OnClientSocketChanged tests -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, OnClientSocketChanged, TestSize.Level1) -{ - QosTV qosTv; - qosTv.qos = QosType::QOS_TYPE_MIN_BW; - qosTv.value = 1; - EXPECT_NO_FATAL_FAILURE(AppDataListenerWrap::OnClientSocketChanged(1, QoSEvent::QOS_SATISFIED, &qosTv, 1)); - EXPECT_NO_FATAL_FAILURE(AppDataListenerWrap::OnClientSocketChanged(1, QoSEvent::QOS_SATISFIED, &qosTv, 0)); - qosTv.qos = QosType::QOS_TYPE_MAX_WAIT_TIMEOUT; - EXPECT_NO_FATAL_FAILURE(AppDataListenerWrap::OnClientSocketChanged(1, QoSEvent::QOS_SATISFIED, &qosTv, 0)); - EXPECT_NO_FATAL_FAILURE(AppDataListenerWrap::OnClientSocketChanged(1, QoSEvent::QOS_SATISFIED, nullptr, 0)); - EXPECT_NO_FATAL_FAILURE(AppDataListenerWrap::OnClientSocketChanged(1, QoSEvent::QOS_NOT_SATISFIED, nullptr, 0)); -} - -/** -* @tc.name: OnServerBytesReceived -* @tc.desc: OnServerBytesReceived tests -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, OnServerBytesReceived, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PeerSocketInfo info; - info.name = strdup(""); - info.networkId = strdup("peertest01"); - info.pkgName = strdup("ohos.kv.test"); - info.dataType = TransDataType::DATA_TYPE_MESSAGE; - AppDistributedKv::SoftBusAdapter::ServerSocketInfo serinfo; - auto result = SoftBusAdapter::GetInstance()->GetPeerSocketInfo(1, serinfo); - EXPECT_EQ(result, false); - char str[] = "Hello"; - const void* data = static_cast(str); - EXPECT_NO_FATAL_FAILURE(AppDataListenerWrap::OnServerBytesReceived(1, data, 10)); - SoftBusAdapter::GetInstance()->OnBind(1, info); - result = SoftBusAdapter::GetInstance()->GetPeerSocketInfo(1, serinfo); - EXPECT_EQ(result, true); - EXPECT_NO_FATAL_FAILURE(AppDataListenerWrap::OnServerBytesReceived(1, data, 10)); - info.name = strdup("name"); - SoftBusAdapter::GetInstance()->OnBind(2, info); - result = SoftBusAdapter::GetInstance()->GetPeerSocketInfo(2, serinfo); - EXPECT_EQ(result, true); - EXPECT_NO_FATAL_FAILURE(AppDataListenerWrap::OnServerBytesReceived(2, data, 10)); -} - -/** -* @tc.name: GetPipeId -* @tc.desc: GetPipeId tests -* @tc.type: FUNC -* @tc.author: -*/ -HWTEST_F(SoftbusAdapterStandardTest, GetPipeId, TestSize.Level1) -{ - std::string names = "GetPipeId"; - auto name = AppDataListenerWrap::GetPipeId(names); - EXPECT_EQ(name, names); - names = "test01_GetPipeId"; - name = AppDataListenerWrap::GetPipeId(names); - EXPECT_EQ(name, "test01"); -} - -/** -* @tc.name: GetMtuSize -* @tc.desc: get size -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, GetMtuSize, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - PipeInfo id; - id.pipeId = "appId"; - id.userId = "groupId"; - SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, id); - DeviceId di = {"DeviceId"}; - auto size = SoftBusAdapter::GetInstance()->GetMtuSize(di); - EXPECT_EQ(size, DEFAULT_MTU_SIZE); - SoftBusAdapter::GetInstance()->GetCloseSessionTask(); - SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, id); - delete dataListener; -} - -/** -* @tc.name: GetTimeout -* @tc.desc: get timeout -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, GetTimeout, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - PipeInfo id; - id.pipeId = "appId01"; - id.userId = "groupId01"; - SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, id); - DeviceId di = {"DeviceId"}; - auto time = SoftBusAdapter::GetInstance()->GetTimeout(di); - EXPECT_EQ(time, DEFAULT_TIMEOUT); - SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, id); - delete dataListener; -} - -/** -* @tc.name: IsSameStartedOnPeer -* @tc.desc: get size -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, IsSameStartedOnPeer, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo id; - id.pipeId = "appId01"; - id.userId = "groupId01"; - DeviceId di = {"DeviceId"}; - SoftBusAdapter::GetInstance()->SetMessageTransFlag(id, true); - auto status = SoftBusAdapter::GetInstance()->IsSameStartedOnPeer(id, di); - EXPECT_EQ(status, true); -} - -/** -* @tc.name: ReuseConnect -* @tc.desc: reuse connect -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, ReuseConnect, TestSize.Level1) -{ - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - PipeInfo pipe; - pipe.pipeId = "appId"; - pipe.userId = "groupId"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, pipe); - DeviceId device = {"DeviceId"}; - auto reuse = SoftBusAdapter::GetInstance()->ReuseConnect(pipe, device); - EXPECT_EQ(reuse, Status::NOT_SUPPORT); - SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, pipe); - delete dataListener; -} - -/** -* @tc.name: ReuseConnect01 -* @tc.desc: reuse connect -* @tc.type: FUNC -* @tc.author: wangbin -*/ -HWTEST_F(SoftbusAdapterStandardTest, ReuseConnect01, TestSize.Level1) -{ - ASSERT_NE(SoftBusAdapter::GetInstance(), nullptr); - PipeInfo pipe; - pipe.pipeId = "appId"; - pipe.userId = "groupId"; - DeviceId device = {"DeviceId"}; - auto status = SoftBusAdapter::GetInstance()->ReuseConnect(pipe, device); - EXPECT_EQ(status, Status::NOT_SUPPORT); -} - -/** -* @tc.name: GetConnect -* @tc.desc: get connect -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, GetConnect, TestSize.Level1) -{ - const AppDataChangeListenerImpl *dataListener = new AppDataChangeListenerImpl(); - PipeInfo pipe; - pipe.pipeId = "appId01"; - pipe.userId = "groupId01"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - SoftBusAdapter::GetInstance()->StartWatchDataChange(dataListener, pipe); - DeviceId device = {"DeviceId01"}; - std::shared_ptr conn = nullptr; - auto reuse = SoftBusAdapter::GetInstance()->GetConnect(pipe, device, 1); - EXPECT_NE(reuse, nullptr); - SoftBusAdapter::GetInstance()->StopWatchDataChange(dataListener, pipe); - delete dataListener; -} - -/** -* @tc.name: Broadcast -* @tc.desc: broadcast -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, Broadcast, TestSize.Level1) -{ - PipeInfo id; - id.pipeId = "appId"; - id.userId = "groupId"; - LevelInfo level; - level.dynamic = 1; - level.statics = 1; - level.switches = 1; - level.switchesLen = 1; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - SoftBusAdapter::GetInstance()->SetMessageTransFlag(id, true); - auto status = SoftBusAdapter::GetInstance()->Broadcast(id, level); - EXPECT_EQ(status, Status::ERROR); -} - -/** -* @tc.name: OpenConnect -* @tc.desc: open connect -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, OpenConnect, TestSize.Level1) -{ - DeviceId device = {"DeviceId"}; - std::shared_ptr conn = nullptr; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - auto status = SoftBusAdapter::GetInstance()->OpenConnect(conn, device); - EXPECT_NE(status.first, Status::SUCCESS); - EXPECT_EQ(status.first, Status::RATE_LIMIT); - EXPECT_EQ(status.second, 0); -} - -/** -* @tc.name: CloseSession -* @tc.desc: close session -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, CloseSession, TestSize.Level1) -{ - std::string networkId = "networkId"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - auto status = SoftBusAdapter::GetInstance()->CloseSession(networkId); - EXPECT_EQ(status, false); -} - -/** -* @tc.name: CloseSession01 -* @tc.desc: close session -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, CloseSession01, TestSize.Level1) -{ - std::string networkId = ""; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - auto status = SoftBusAdapter::GetInstance()->CloseSession(networkId); - EXPECT_EQ(status, false); -} - -/** -* @tc.name: GetPeerSocketInfo -* @tc.desc: get socket info -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, GetPeerSocketInfo, TestSize.Level1) -{ - AppDistributedKv::SoftBusAdapter::ServerSocketInfo info; - info.name = "kv"; - info.networkId= "192.168.1.1"; - info.pkgName = "test"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - auto status = SoftBusAdapter::GetInstance()->GetPeerSocketInfo(-1, info); - EXPECT_EQ(status, false); -} - -/** -* @tc.name: GetPeerSocketInfo -* @tc.desc: get socket info -* @tc.type: FUNC -* @tc.author: nhj -*/ -HWTEST_F(SoftbusAdapterStandardTest, GetPeerSocketInfo01, TestSize.Level1) -{ - AppDistributedKv::SoftBusAdapter::ServerSocketInfo info; - info.name = "service"; - info.networkId= "192.168.1.1"; - info.pkgName = "test"; - auto flag = SoftBusAdapter::GetInstance(); - ASSERT_NE(flag, nullptr); - auto status = SoftBusAdapter::GetInstance()->GetPeerSocketInfo(1, info); - EXPECT_EQ(status, true); -} -} // namespace OHOS::Test \ No newline at end of file +///* +// * Copyright (c) 2022 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 "softbus_adapter.h" +// +//#include +// +//#include "account/account_delegate.h" +//#include "app_data_change_listener.h" +//#include "app_device_change_listener.h" +//#include "communication/connect_manager.h" +//#include "communicator_context.h" +//#include "data_level.h" +//#include "db_store_mock.h" +//#include "device_manager_adapter.h" +//#include "executor_pool.h" +//#include "inner_socket.h" +//#include "metadata/appid_meta_data.h" +//#include "metadata/meta_data_manager.h" +//#include "metadata/store_meta_data.h" +//#include "types.h" +// +//namespace OHOS::Test { +//using namespace testing::ext; +//using namespace OHOS::AppDistributedKv; +//using namespace OHOS::DistributedData; +// +//static constexpr size_t THREAD_MIN = 0; +//static constexpr size_t THREAD_MAX = 3; +//static constexpr uint16_t DYNAMIC_LEVEL = 0xFFFF; +//static constexpr uint16_t STATIC_LEVEL = 0x1111; +//static constexpr uint32_t SWITCH_VALUE = 0x00000001; +//static constexpr uint16_t SWITCH_LENGTH = 1; +//static constexpr const char *TEST_BUNDLE_NAME = "TestApplication"; +//static constexpr const char *TEST_STORE_NAME = "TestStore"; +// +//class DeviceChangeListenerTest : public AppDeviceChangeListener { +//public: +// void OnDeviceChanged(const DeviceInfo &info, const DeviceChangeType &type) const override {} +// void OnSessionReady(const DeviceInfo &info, int32_t errCode) const override; +// void ResetReadyFlag(); +// +// mutable int32_t bindResult_; +// mutable bool isReady_ = false; +//}; +// +//void DeviceChangeListenerTest::OnSessionReady(const DeviceInfo &info, int32_t errCode) const +//{ +// (void)info; +// bindResult_ = errCode; +// isReady_ = true; +//} +// +//void DeviceChangeListenerTest::ResetReadyFlag() +//{ +// isReady_ = false; +//} +// +//class AppDataChangeListenerTest : public AppDataChangeListener { +//public: +// void OnMessage(const DeviceInfo &info, const uint8_t *ptr, const int size, const PipeInfo &pipeInfo) const override +// { +// } +//}; +// +//class SoftBusAdapterStandardTest : public testing::Test { +//public: +// static void SetUpTestCase(void); +// static void TearDownTestCase(void); +// void SetUp() {} +// void TearDown(); +// +// void ProcessBroadcastMsg(const std::string &device, const LevelInfo &levelInfo); +// static void ConfigSendParameters(bool isCancel); +// +// mutable bool dataLevelResult_ = false; +// +// static std::shared_ptr executors_; +// static std::shared_ptr softBusAdapter_; +// static std::shared_ptr connectManager_; +// static DeviceChangeListenerTest deviceListener_; +// static AppDataChangeListenerTest dataChangeListener_; +// static PipeInfo pipeInfo_; +// static DeviceId deviceId_; +// static ExtraDataInfo extraInfo_; +// static DataInfo dataInfo_; +// static MessageInfo msgInfo_; +// static LevelInfo sendLevelInfo_; +// static LevelInfo receiveLevelInfo_; +// static std::string foregroundUserId_; +// static DeviceInfo localDeviceInfo_; +// static DeviceInfo remoteDeviceInfo_; +// static std::shared_ptr dbStoreMock_; +//}; +// +//std::shared_ptr SoftBusAdapterStandardTest::executors_; +//std::shared_ptr SoftBusAdapterStandardTest::softBusAdapter_; +//std::shared_ptr SoftBusAdapterStandardTest::connectManager_; +//DeviceChangeListenerTest SoftBusAdapterStandardTest::deviceListener_; +//AppDataChangeListenerTest SoftBusAdapterStandardTest::dataChangeListener_; +//PipeInfo SoftBusAdapterStandardTest::pipeInfo_; +//DeviceId SoftBusAdapterStandardTest::deviceId_; +//ExtraDataInfo SoftBusAdapterStandardTest::extraInfo_; +//DataInfo SoftBusAdapterStandardTest::dataInfo_; +//MessageInfo SoftBusAdapterStandardTest::msgInfo_; +//LevelInfo SoftBusAdapterStandardTest::sendLevelInfo_; +//LevelInfo SoftBusAdapterStandardTest::receiveLevelInfo_; +//std::string SoftBusAdapterStandardTest::foregroundUserId_; +//DeviceInfo SoftBusAdapterStandardTest::localDeviceInfo_; +//DeviceInfo SoftBusAdapterStandardTest::remoteDeviceInfo_; +//std::shared_ptr SoftBusAdapterStandardTest::dbStoreMock_; +// +//void SoftBusAdapterStandardTest::SetUpTestCase(void) +//{ +// connectManager_ = ConnectManager::GetInstance(); +// softBusAdapter_ = SoftBusAdapter::GetInstance(); +// +// CommunicatorContext::GetInstance().RegSessionListener(&deviceListener_); +// +// executors_ = std::make_shared(THREAD_MAX, THREAD_MIN); +// CommunicatorContext::GetInstance().SetThreadPool(executors_); +// +// dbStoreMock_ = std::make_shared(); +// MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); +// +// localDeviceInfo_ = DeviceManagerAdapter::GetInstance().GetLocalDevice(); +// auto remoteDeviceInfos = DeviceManagerAdapter::GetInstance().GetRemoteDevices(); +// if (!remoteDeviceInfos.empty()) { +// remoteDeviceInfo_ = remoteDeviceInfos[0]; +// } +// +// int userId = 0; +// AccountDelegate::GetInstance()->QueryForegroundUserId(userId); +// foregroundUserId_ = std::to_string(userId); +//} +// +//void SoftBusAdapterStandardTest::TearDownTestCase(void) +//{ +// CommunicatorContext::GetInstance().UnRegSessionListener(&deviceListener_); +//} +// +//void SoftBusAdapterStandardTest::TearDown() +//{ +// softBusAdapter_->connects_.Clear(); +// ConfigSendParameters(true); +//} +// +//void SoftBusAdapterStandardTest::ConfigSendParameters(bool isCancel) +//{ +// deviceId_.deviceId = isCancel ? "" : remoteDeviceInfo_.uuid; +// +// extraInfo_.userId = isCancel ? "" : foregroundUserId_; +// extraInfo_.bundleName = isCancel ? "" : TEST_BUNDLE_NAME; +// extraInfo_.storeId = isCancel ? "" : TEST_STORE_NAME; +// +// dataInfo_.extraInfo.userId = isCancel ? "" : foregroundUserId_; +// dataInfo_.extraInfo.appId = isCancel ? "" : TEST_BUNDLE_NAME; +// dataInfo_.extraInfo.storeId = isCancel ? "" : TEST_STORE_NAME; +// +// StoreMetaData localMetaData; +// localMetaData.deviceId = localDeviceInfo_.uuid; +// localMetaData.user = foregroundUserId_; +// localMetaData.bundleName = TEST_BUNDLE_NAME; +// localMetaData.storeId = TEST_STORE_NAME; +// +// StoreMetaData remoteMetaData; +// remoteMetaData.deviceId = remoteDeviceInfo_.uuid; +// remoteMetaData.user = foregroundUserId_; +// remoteMetaData.bundleName = TEST_BUNDLE_NAME; +// remoteMetaData.storeId = TEST_STORE_NAME; +// +// if (isCancel) { +// MetaDataManager::GetInstance().DelMeta(TEST_BUNDLE_NAME, true); +// MetaDataManager::GetInstance().DelMeta(localMetaData.GetKeyWithoutPath()); +// MetaDataManager::GetInstance().DelMeta(remoteMetaData.GetKeyWithoutPath()); +// } else { +// AppIDMetaData appIdMeta; +// appIdMeta.appId = TEST_BUNDLE_NAME; +// appIdMeta.bundleName = TEST_BUNDLE_NAME; +// MetaDataManager::GetInstance().SaveMeta(TEST_BUNDLE_NAME, appIdMeta, true); +// MetaDataManager::GetInstance().SaveMeta(localMetaData.GetKeyWithoutPath(), localMetaData); +// MetaDataManager::GetInstance().SaveMeta(remoteMetaData.GetKeyWithoutPath(), remoteMetaData); +// } +//} +// +//void SoftBusAdapterStandardTest::ProcessBroadcastMsg(const std::string &device, const LevelInfo &levelInfo) +//{ +// (void)device; +// receiveLevelInfo_ = levelInfo; +// dataLevelResult_ = true; +//} +// +///** +//* @tc.name: SessionServerTest001 +//* @tc.desc: create and remove session server +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, SessionServerTest001, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_SOCKET); +// auto result = softBusAdapter_->CreateSessionServerAdapter(""); +// ASSERT_NE(result, 0); +// +// ConfigSocketId(VALID_SOCKET); +// result = softBusAdapter_->CreateSessionServerAdapter(""); +// ASSERT_EQ(result, 0); +// +// result = softBusAdapter_->RemoveSessionServerAdapter(""); +// ASSERT_EQ(result, 0); +//} +// +///** +//* @tc.name: WatchDataChangeTest001 +//* @tc.desc: watch and unwatch data change +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, WatchDataChangeTest001, TestSize.Level1) +//{ +// auto status = softBusAdapter_->StartWatchDataChange(nullptr, pipeInfo_); +// ASSERT_EQ(status, Status::INVALID_ARGUMENT); +// +// status = softBusAdapter_->StartWatchDataChange(&dataChangeListener_, pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +// +// status = softBusAdapter_->StartWatchDataChange(&dataChangeListener_, pipeInfo_); +// ASSERT_EQ(status, Status::ERROR); +// +// status = softBusAdapter_->StopWatchDataChange(nullptr, pipeInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +// +// status = softBusAdapter_->StopWatchDataChange(nullptr, pipeInfo_); +// ASSERT_EQ(status, Status::ERROR); +//} +// +///** +//* @tc.name: SendDataTest001 +//* @tc.desc: send data fail with invalid param +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, SendDataTest001, TestSize.Level1) +//{ +// auto result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::ERROR); +// +// deviceId_.deviceId = remoteDeviceInfo_.uuid; +// result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::ERROR); +// +// dataInfo_.extraInfo.userId = foregroundUserId_; +// result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::ERROR); +// +// dataInfo_.extraInfo.appId = TEST_BUNDLE_NAME; +// result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::ERROR); +// +// dataInfo_.extraInfo.storeId = TEST_STORE_NAME; +// result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::ERROR); +// +// AppIDMetaData appIdMeta; +// appIdMeta.appId = TEST_BUNDLE_NAME; +// appIdMeta.bundleName = TEST_BUNDLE_NAME; +// MetaDataManager::GetInstance().SaveMeta(TEST_BUNDLE_NAME, appIdMeta, true); +// +// result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::ERROR); +//} +// +///** +//* @tc.name: SendDataTest002 +//* @tc.desc: send data with bind fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, SendDataTest002, TestSize.Level1) +//{ +// ConfigSendParameters(false); +// ConfigSocketId(INVALID_MTU_SOCKET); +// +// auto result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::RATE_LIMIT); +// while (!(deviceListener_.isReady_)) { +// std::this_thread::sleep_for(std::chrono::seconds(1)); +// } +// ASSERT_NE(deviceListener_.bindResult_, 0); +// +// deviceListener_.ResetReadyFlag(); +//} +// +///** +//* @tc.name: SendDataTest003 +//* @tc.desc: send data with bind success +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, SendDataTest003, TestSize.Level1) +//{ +// ConfigSendParameters(false); +// ConfigSocketId(VALID_SOCKET); +// +// auto res = softBusAdapter_->CreateSessionServerAdapter(""); +// ASSERT_EQ(res, 0); +// +// auto result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::RATE_LIMIT); +// while (!(deviceListener_.isReady_)) { +// std::this_thread::sleep_for(std::chrono::seconds(1)); +// } +// ASSERT_EQ(deviceListener_.bindResult_, 0); +// +// uint32_t mtuBuffer; +// GetMtuSize(VALID_SOCKET, &mtuBuffer); +// auto mtuSize = softBusAdapter_->GetMtuSize(deviceId_); +// ASSERT_EQ(mtuSize, mtuBuffer); +// +// auto timeOut = softBusAdapter_->GetTimeout(deviceId_); +// ASSERT_NE(timeOut, 0); +// +// result = softBusAdapter_->SendData(pipeInfo_, deviceId_, dataInfo_, 0, msgInfo_); +// ASSERT_EQ(result.first, Status::SUCCESS); +// +// std::this_thread::sleep_for(std::chrono::seconds(10)); +// mtuSize = softBusAdapter_->GetMtuSize(deviceId_); +// ASSERT_NE(mtuSize, mtuBuffer); +//} +// +///** +//* @tc.name: ReuseConnectTest001 +//* @tc.desc: reuse connect fail with invalid parameter +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, ReuseConnectTest001, TestSize.Level1) +//{ +// auto result = softBusAdapter_->ReuseConnect(pipeInfo_, deviceId_, extraInfo_); +// ASSERT_EQ(result, Status::NOT_SUPPORT); +// +// deviceId_.deviceId = remoteDeviceInfo_.uuid; +// extraInfo_.userId = foregroundUserId_; +// result = softBusAdapter_->ReuseConnect(pipeInfo_, deviceId_, extraInfo_); +// ASSERT_EQ(result, Status::ERROR); +// +// extraInfo_.bundleName = TEST_BUNDLE_NAME; +// result = softBusAdapter_->ReuseConnect(pipeInfo_, deviceId_, extraInfo_); +// ASSERT_EQ(result, Status::ERROR); +// +// extraInfo_.storeId = TEST_STORE_NAME; +// result = softBusAdapter_->ReuseConnect(pipeInfo_, deviceId_, extraInfo_); +// ASSERT_EQ(result, Status::ERROR); +//} +// +///** +//* @tc.name: ReuseConnectTest002 +//* @tc.desc: reuse connect fail with bind fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, ReuseConnectTest002, TestSize.Level1) +//{ +// ConfigSendParameters(false); +// ConfigSocketId(INVALID_MTU_SOCKET); +// +// auto result = softBusAdapter_->ReuseConnect(pipeInfo_, deviceId_, extraInfo_); +// ASSERT_EQ(result, Status::NETWORK_ERROR); +//} +// +///** +//* @tc.name: ReuseConnectTest003 +//* @tc.desc: reuse connect success +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, ReuseConnectTest003, TestSize.Level1) +//{ +// ConfigSendParameters(false); +// ConfigSocketId(VALID_SOCKET); +// +// auto res = softBusAdapter_->CreateSessionServerAdapter(""); +// ASSERT_EQ(res, 0); +// +// auto result = softBusAdapter_->ReuseConnect(pipeInfo_, deviceId_, extraInfo_); +// ASSERT_EQ(result, Status::SUCCESS); +// +// std::this_thread::sleep_for(std::chrono::seconds(10)); +//} +// +///** +//* @tc.name: IsSameStartedOnPeerTest001 +//* @tc.desc: test IsSameStartedOnPeer +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, IsSameStartedOnPeerTest001, TestSize.Level1) +//{ +// auto result = softBusAdapter_->IsSameStartedOnPeer(pipeInfo_, deviceId_); +// ASSERT_TRUE(result); +//} +// +///** +//* @tc.name: ListenBroadcastTest001 +//* @tc.desc: listen broadcast test +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, ListenBroadcastTest001, TestSize.Level1) +//{ +// ConfigReturnCode(SoftBusErrNo::SOFTBUS_ERROR); +// auto status = softBusAdapter_->ListenBroadcastMsg(pipeInfo_, nullptr); +// ASSERT_NE(status, 0); +// +// ConfigReturnCode(SoftBusErrNo::SOFTBUS_OK); +// auto dataLevelListener = [this](const std::string &device, const LevelInfo &levelInfo) { +// ProcessBroadcastMsg(device, levelInfo); +// }; +// status = softBusAdapter_->ListenBroadcastMsg(pipeInfo_, dataLevelListener); +// ASSERT_EQ(status, 0); +// +// status = softBusAdapter_->ListenBroadcastMsg(pipeInfo_, dataLevelListener); +// ASSERT_NE(status, 0); +//} +// +///** +//* @tc.name: BroadcastTest001 +//* @tc.desc: broadcast msg fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, BroadcastTest001, TestSize.Level1) +//{ +// ConfigReturnCode(SoftBusErrNo::SOFTBUS_FUNC_NOT_SUPPORT); +// auto status = softBusAdapter_->Broadcast(pipeInfo_, sendLevelInfo_); +// ASSERT_EQ(status, Status::NOT_SUPPORT_BROADCAST); +// +// ConfigReturnCode(SoftBusErrNo::SOFTBUS_ERROR); +// status = softBusAdapter_->Broadcast(pipeInfo_, sendLevelInfo_); +// ASSERT_EQ(status, Status::ERROR); +//} +// +///** +//* @tc.name: BroadcastTest002 +//* @tc.desc: broadcast msg success and receive msg +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusAdapterStandardTest, BroadcastTest002, TestSize.Level1) +//{ +// auto dataLevelListener = [this](const std::string &device, const LevelInfo &levelInfo) { +// ProcessBroadcastMsg(device, levelInfo); +// }; +// ConfigReturnCode(SoftBusErrNo::SOFTBUS_OK); +// (void)softBusAdapter_->ListenBroadcastMsg(pipeInfo_, dataLevelListener); +// +// sendLevelInfo_.dynamic = DYNAMIC_LEVEL; +// sendLevelInfo_.statics = STATIC_LEVEL; +// sendLevelInfo_.switches = SWITCH_VALUE; +// sendLevelInfo_.switchesLen = SWITCH_LENGTH; +// +// auto status = softBusAdapter_->Broadcast(pipeInfo_, sendLevelInfo_); +// ASSERT_EQ(status, Status::SUCCESS); +// ASSERT_EQ(receiveLevelInfo_.dynamic, sendLevelInfo_.dynamic); +// ASSERT_EQ(receiveLevelInfo_.statics, sendLevelInfo_.statics); +// ASSERT_EQ(receiveLevelInfo_.switches, sendLevelInfo_.switches); +// ASSERT_EQ(receiveLevelInfo_.switchesLen, sendLevelInfo_.switchesLen); +//} +//} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/softbus_client_test.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/softbus_client_test.cpp index 3ba19844..f24a8bed 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/softbus_client_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest/softbus_client_test.cpp @@ -1,189 +1,371 @@ -/* - * 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 "softbus_client.h" -#include "types.h" - - -namespace OHOS::Test { -using namespace testing::ext; -using namespace OHOS::AppDistributedKv; -using PipeInfo = OHOS::AppDistributedKv::PipeInfo; -constexpr int32_t SOFTBUS_OK = 0; - -class SoftbusClientTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp() {} - void TearDown() {} - - static std::shared_ptr client; -}; - -std::shared_ptr SoftbusClientTest::client = nullptr; - -void SoftbusClientTest::SetUpTestCase(void) -{ - PipeInfo pipeInfo; - pipeInfo.pipeId = "pipeId"; - pipeInfo.userId = "userId"; - DeviceId id = {"DeviceId"}; - client = std::make_shared(pipeInfo, id); -} - -void SoftbusClientTest::TearDownTestCase(void) -{ - client = nullptr; -} - -/** -* @tc.name: SendData -* @tc.desc: SendData test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(SoftbusClientTest, SendData, TestSize.Level0) -{ - ASSERT_NE(client, nullptr); - std::string content = "Helloworlds"; - const uint8_t *data = reinterpret_cast(content.c_str()); - DataInfo info = { const_cast(data), static_cast(content.length())}; - ISocketListener *listener = nullptr; - auto status = client->SendData(info, listener); - EXPECT_EQ(status, Status::ERROR); - client->bindState_ = 0; - status = client->SendData(info, listener); - EXPECT_EQ(status, Status::ERROR); -} - -/** -* @tc.name: OpenConnect -* @tc.desc: OpenConnect test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(SoftbusClientTest, OpenConnect, TestSize.Level0) -{ - ASSERT_NE(client, nullptr); - ISocketListener *listener = nullptr; - client->bindState_ = 0; - auto status = client->OpenConnect(listener); - EXPECT_EQ(status, Status::SUCCESS); - client->bindState_ = 1; - client->isOpening_.store(true); - status = client->OpenConnect(listener); - EXPECT_EQ(status, Status::RATE_LIMIT); - client->isOpening_.store(false); - status = client->OpenConnect(listener); - EXPECT_EQ(status, Status::NETWORK_ERROR); -} - -/** -* @tc.name: CheckStatus -* @tc.desc: CheckStatus test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(SoftbusClientTest, CheckStatus, TestSize.Level0) -{ - ASSERT_NE(client, nullptr); - client->bindState_ = 0; - auto status = client->CheckStatus(); - EXPECT_EQ(status, Status::SUCCESS); - client->bindState_ = -1; - client->isOpening_.store(true); - status = client->CheckStatus(); - EXPECT_EQ(status, Status::RATE_LIMIT); - client->isOpening_.store(false); - status = client->CheckStatus(); - EXPECT_EQ(status, Status::ERROR); -} - -/** -* @tc.name: Open -* @tc.desc: Open test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(SoftbusClientTest, Open, TestSize.Level0) -{ - ASSERT_NE(client, nullptr); - ISocketListener *listener = nullptr; - auto status = client->Open(1, AppDistributedKv::SoftBusClient::QOS_BR, listener, false); - EXPECT_NE(status, SOFTBUS_OK); -} - -/** -* @tc.name: UpdateExpireTime -* @tc.desc: UpdateExpireTime test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(SoftbusClientTest, UpdateExpireTime, TestSize.Level0) -{ - ASSERT_NE(client, nullptr); - client->type_ = AppDistributedKv::SoftBusClient::QOS_BR; - auto expireTime = client->CalcExpireTime(); - EXPECT_NO_FATAL_FAILURE(client->UpdateExpireTime(true)); - EXPECT_LT(expireTime, client->expireTime_); - EXPECT_NO_FATAL_FAILURE(client->UpdateExpireTime(false)); - EXPECT_LT(expireTime, client->expireTime_); -} - -/** -* @tc.name: UpdateBindInfo -* @tc.desc: UpdateBindInfo test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(SoftbusClientTest, UpdateBindInfo, TestSize.Level0) -{ - ASSERT_NE(client, nullptr); - EXPECT_NO_FATAL_FAILURE(client->UpdateBindInfo(1, 1, AppDistributedKv::SoftBusClient::QOS_BR, false)); - EXPECT_NO_FATAL_FAILURE(client->UpdateBindInfo(1, 1, AppDistributedKv::SoftBusClient::QOS_BR, true)); -} - -/** -* @tc.name: ReuseConnect -* @tc.desc: ReuseConnect test -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin - */ -HWTEST_F(SoftbusClientTest, ReuseConnect, TestSize.Level0) -{ - ASSERT_NE(client, nullptr); - ISocketListener *listener = nullptr; - client->bindState_ = 0; - auto status = client->ReuseConnect(listener); - EXPECT_EQ(status, Status::SUCCESS); - client->bindState_ = -1; - client->isOpening_.store(true); - status = client->ReuseConnect(listener); - EXPECT_EQ(status, Status::NETWORK_ERROR); -} -} // namespace OHOS::Test \ 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. +// */ +// +//#include "softbus_client.h" +// +//#include +// +//#include "app_device_change_listener.h" +//#include "communicator_context.h" +//#include "executor_pool.h" +// +//namespace OHOS::Test { +//using namespace testing::ext; +//using namespace OHOS::AppDistributedKv; +//using namespace OHOS::DistributedData; +// +//static constexpr int32_t DEFAULT_SOCKET = -1; +//static constexpr int32_t INVALID_SOCKET = 0; +//static constexpr int32_t INVALID_SET_SOCKET = 1; +//static constexpr int32_t INVALID_BIND_SOCKET = 2; +//static constexpr int32_t INVALID_MTU_SOCKET = 3; +//static constexpr int32_t INVALID_SEND_SOCKET = 4; +//static constexpr int32_t VALID_SOCKET = 5; +//static constexpr size_t THREAD_MIN = 0; +//static constexpr size_t THREAD_MAX = 1; +//static constexpr const char* PIP_ID = "SoftBusClientTest"; +//static constexpr const char* UUID = "uuid"; +//static constexpr const char* NETWORK_ID = "network_id"; +//static constexpr const char* INVALID_NETWORK_ID = "invalid_network_id"; +// +//class DeviceChangeListenerTest : public AppDeviceChangeListener { +//public: +// void OnDeviceChanged(const DeviceInfo &info, const DeviceChangeType &type) const override {} +// void OnSessionReady(const DeviceInfo &info, int32_t errCode) const override; +// void ResetReadyFlag(); +// +// mutable int32_t bindResult_; +// mutable bool isReady_ = false; +//}; +// +//void DeviceChangeListenerTest::OnSessionReady(const DeviceInfo &info, int32_t errCode) const +//{ +// (void)info; +// bindResult_ = errCode; +// isReady_ = true; +//} +// +//void DeviceChangeListenerTest::ResetReadyFlag() +//{ +// isReady_ = false; +//} +// +//class SoftBusClientTest : public testing::Test { +//public: +// static void SetUpTestCase(void); +// static void TearDownTestCase(void); +// void SetUp(); +// void TearDown() {} +// +// static PipeInfo pipeInfo_; +// static DeviceId deviceId_; +// static SessionAccessInfo accessInfo_; +// static DeviceChangeListenerTest deviceListener_; +// static std::shared_ptr executors_; +//}; +// +//PipeInfo SoftBusClientTest::pipeInfo_; +//DeviceId SoftBusClientTest::deviceId_; +//SessionAccessInfo SoftBusClientTest::accessInfo_; +//DeviceChangeListenerTest SoftBusClientTest::deviceListener_; +//std::shared_ptr SoftBusClientTest::executors_; +// +//void SoftBusClientTest::SetUpTestCase(void) +//{ +// pipeInfo_.pipeId = PIP_ID; +// deviceId_.deviceId = UUID; +// CommunicatorContext::GetInstance().RegSessionListener(&deviceListener_); +// executors_ = std::make_shared(THREAD_MAX, THREAD_MIN); +//} +// +//void SoftBusClientTest::TearDownTestCase(void) +//{ +// CommunicatorContext::GetInstance().UnRegSessionListener(&deviceListener_); +//} +// +//void SoftBusClientTest::SetUp() +//{ +// CommunicatorContext::GetInstance().SetThreadPool(executors_); +//} +// +///** +//* @tc.name: OperatorTest001 +//* @tc.desc: operator test +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, OperatorTest001, TestSize.Level1) +//{ +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_HML, +// accessInfo_); +// ASSERT_TRUE(*connect == UUID); +// ASSERT_TRUE(*connect == DEFAULT_SOCKET); +// ASSERT_EQ(connect->GetSocket(), DEFAULT_SOCKET); +//} +// +///** +//* @tc.name: NetworkIdTest001 +//* @tc.desc: network id test +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, NetworkIdTest001, TestSize.Level1) +//{ +// auto connect = std::make_shared(pipeInfo_, deviceId_, INVALID_NETWORK_ID, SoftBusClient::QOS_HML, +// accessInfo_); +// auto networkId = connect->GetNetworkId(); +// ASSERT_EQ(networkId, INVALID_NETWORK_ID); +// connect->UpdateNetworkId(NETWORK_ID); +// networkId = connect->GetNetworkId(); +// ASSERT_EQ(networkId, NETWORK_ID); +//} +// +///** +//* @tc.name: OpenConnectTest001 +//* @tc.desc: open connect fail and socketId is invalid +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, OpenConnectTest001, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_HML, +// accessInfo_); +// auto status = connect->OpenConnect(nullptr); +// ASSERT_EQ(status, Status::NETWORK_ERROR); +//} +// +///** +//* @tc.name: OpenConnectTest002 +//* @tc.desc: open connect fail and socket is valid but set access info fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, OpenConnectTest002, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_SET_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_HML, +// accessInfo_); +// auto status = connect->OpenConnect(nullptr); +// ASSERT_EQ(status, Status::NETWORK_ERROR); +//} +// +///** +//* @tc.name: OpenConnectTest003 +//* @tc.desc: open connect fail and executor pool is nullptr +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, OpenConnectTest003, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_BIND_SOCKET); +// CommunicatorContext::GetInstance().SetThreadPool(nullptr); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_HML, +// accessInfo_); +// auto status = connect->OpenConnect(nullptr); +// ASSERT_EQ(status, Status::NETWORK_ERROR); +//} +// +///** +//* @tc.name: OpenConnectTest004 +//* @tc.desc: open connect fail and socket is valid but bind fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, OpenConnectTest004, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_BIND_SOCKET); +// +// accessInfo_.isOHType = false; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_BR, +// accessInfo_); +// auto status = connect->OpenConnect(nullptr); +// ASSERT_EQ(status, Status::RATE_LIMIT); +// while (!(deviceListener_.isReady_)) { +// sleep(1); +// } +// deviceListener_.ResetReadyFlag(); +// auto result = deviceListener_.bindResult_; +// ASSERT_NE(result, 0); +// +// accessInfo_.isOHType = true; +// auto ohConnect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_HML, +// accessInfo_); +// status = ohConnect->OpenConnect(nullptr); +// ASSERT_EQ(status, Status::RATE_LIMIT); +// while (!(deviceListener_.isReady_)) { +// sleep(1); +// } +// deviceListener_.ResetReadyFlag(); +// result = deviceListener_.bindResult_; +// ASSERT_NE(result, 0); +//} +// +///** +//* @tc.name: OpenConnectTest005 +//* @tc.desc: open connect fail and bind success but get mtu fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, OpenConnectTest005, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_MTU_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_HML, +// accessInfo_); +// auto status = connect->OpenConnect(nullptr); +// ASSERT_EQ(status, Status::RATE_LIMIT); +// while (!(deviceListener_.isReady_)) { +// sleep(1); +// } +// deviceListener_.ResetReadyFlag(); +// auto result = deviceListener_.bindResult_; +// ASSERT_NE(result, 0); +//} +// +///** +//* @tc.name: OpenConnectTest006 +//* @tc.desc: open connect success +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, OpenConnectTest006, TestSize.Level1) +//{ +// ConfigSocketId(VALID_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_HML, +// accessInfo_); +// auto status = connect->OpenConnect(nullptr); +// ASSERT_EQ(status, Status::RATE_LIMIT); +// while (!(deviceListener_.isReady_)) { +// sleep(1); +// } +// deviceListener_.ResetReadyFlag(); +// auto result = deviceListener_.bindResult_; +// ASSERT_EQ(result, 0); +// status = connect->CheckStatus(); +// ASSERT_EQ(status, Status::SUCCESS); +// +// status = connect->OpenConnect(nullptr); +// ASSERT_EQ(status, Status::SUCCESS); +//} +// +///** +//* @tc.name: ReuseConnectTest001 +//* @tc.desc: reuse connect fail and socketId is invalid +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, ReuseConnectTest001, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_REUSE, +// accessInfo_); +// auto status = connect->ReuseConnect(nullptr); +// ASSERT_EQ(status, Status::NETWORK_ERROR); +//} +// +///** +//* @tc.name: ReuseConnectTest002 +//* @tc.desc: reuse connect fail and socket is valid but set access info fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, ReuseConnectTest002, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_SET_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_REUSE, +// accessInfo_); +// auto status = connect->ReuseConnect(nullptr); +// ASSERT_EQ(status, Status::NETWORK_ERROR); +//} +// +///** +//* @tc.name: ReuseConnectTest003 +//* @tc.desc: reuse connect fail and socket is valid but bind fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, ReuseConnectTest003, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_BIND_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_REUSE, +// accessInfo_); +// auto status = connect->ReuseConnect(nullptr); +// ASSERT_EQ(status, Status::NETWORK_ERROR); +//} +// +///** +//* @tc.name: ReuseConnectTest004 +//* @tc.desc: reuse connect fail and bind success but get mtu fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, ReuseConnectTest004, TestSize.Level1) +//{ +// ConfigSocketId(INVALID_MTU_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_REUSE, +// accessInfo_); +// auto status = connect->ReuseConnect(nullptr); +// ASSERT_EQ(status, Status::NETWORK_ERROR); +//} +// +///** +//* @tc.name: ReuseConnectTest005 +//* @tc.desc: reuse connect success +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, ReuseConnectTest005, TestSize.Level1) +//{ +// ConfigSocketId(VALID_SOCKET); +// accessInfo_.isOHType = true; +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_REUSE, +// accessInfo_); +// auto status = connect->ReuseConnect(nullptr); +// ASSERT_EQ(status, Status::SUCCESS); +//} +// +///** +//* @tc.name: SendDataTest001 +//* @tc.desc: send data fail +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, SendDataTest001, TestSize.Level1) +//{ +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_REUSE, +// accessInfo_); +// DataInfo dataInfo; +// auto status = connect->SendData(dataInfo); +// ASSERT_NE(status, Status::SUCCESS); +// +// ConfigSocketId(INVALID_SEND_SOCKET); +// status = connect->ReuseConnect(nullptr); +// ASSERT_EQ(status, Status::SUCCESS); +// status = connect->SendData(dataInfo); +// ASSERT_NE(status, Status::SUCCESS); +//} +// +///** +//* @tc.name: SendDataTest002 +//* @tc.desc: send data success +//* @tc.type: FUNC +//*/ +//HWTEST_F(SoftBusClientTest, SendDataTest002, TestSize.Level1) +//{ +// ConfigSocketId(VALID_SOCKET); +// auto connect = std::make_shared(pipeInfo_, deviceId_, NETWORK_ID, SoftBusClient::QOS_REUSE, +// accessInfo_); +// DataInfo dataInfo; +// auto status = connect->ReuseConnect(nullptr); +// ASSERT_EQ(status, Status::SUCCESS); +// status = connect->SendData(dataInfo); +// ASSERT_EQ(status, Status::SUCCESS); +//} +//} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/dfx/BUILD.gn index 483c4544..1b2cc6e7 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/BUILD.gn @@ -43,18 +43,14 @@ ohos_source_set("distributeddata_dfx") { "./src/fault", "./src/statistic", "../include/dfx", - "../include/log", - "../include/utils", - "../include/communicator", - "${data_service_path}/framework/include/dfx", - "${data_service_path}/framework/include/utils", ] - cflags_cc = [ - "-fvisibility=hidden", - "-fstack-protector-strong", - ] + cflags_cc = [ "-fvisibility=hidden" ] + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/adapter/communicator:distributeddata_communicator", + ] external_deps = [ "c_utils:utils", "device_manager:devicemanagersdk", diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/cloud_sync_fault_impl.h b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/cloud_sync_fault_impl.h index 89ee3d5b..54e6b60b 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/cloud_sync_fault_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/cloud_sync_fault_impl.h @@ -16,9 +16,9 @@ #ifndef DISTRIBUTEDDATAMGR_DATAMGR_SERVICE_CLOUD_SYNC_FAULT_IMPL_H #define DISTRIBUTEDDATAMGR_DATAMGR_SERVICE_CLOUD_SYNC_FAULT_IMPL_H +#include "dfx/dfx_types.h" #include "dfx/fault_reporter.h" #include "hiview_adapter.h" -#include "dfx/dfx_types.h" namespace OHOS { namespace DistributedDataDfx { @@ -43,6 +43,6 @@ public: private: std::shared_ptr executors_; }; -} // namespace DistributedDataDfx -} // namespace OHOS +} // namespace DistributedDataDfx +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_DATAMGR_SERVICE_CLOUD_SYNC_FAULT_IMPL_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/communication_fault_impl.h b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/communication_fault_impl.h index bf25665a..19673336 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/communication_fault_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/communication_fault_impl.h @@ -16,9 +16,9 @@ #ifndef DISTRIBUTEDDATAMGR_COMMUNICATION_FAULT_IMPL_H #define DISTRIBUTEDDATAMGR_COMMUNICATION_FAULT_IMPL_H +#include "dfx/dfx_types.h" #include "dfx/fault_reporter.h" #include "hiview_adapter.h" -#include "dfx/dfx_types.h" namespace OHOS { namespace DistributedDataDfx { @@ -39,6 +39,6 @@ public: private: std::shared_ptr executors_; }; -} // namespace DistributedDataDfx -} // namespace OHOS +} // namespace DistributedDataDfx +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_COMMUNICATION_FAULT_IMPL_H diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/database_fault_impl.h b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/database_fault_impl.h index 755d0318..1185dce0 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/database_fault_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/database_fault_impl.h @@ -38,7 +38,7 @@ public: private: std::shared_ptr executors_; }; -} // namespace DistributedDataDfx -} // namespace OHOS +} // namespace DistributedDataDfx +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_DATABASE_FAULT_IMPL_H diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/runtime_fault_impl.h b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/runtime_fault_impl.h index ce2fa7c6..ae7f1a3e 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/runtime_fault_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/runtime_fault_impl.h @@ -15,8 +15,8 @@ #ifndef DISTRIBUTEDDATAMGR_RUNTIME_FAULT_IMPL_H #define DISTRIBUTEDDATAMGR_RUNTIME_FAULT_IMPL_H -#include "hiview_adapter.h" #include "dfx/fault_reporter.h" +#include "hiview_adapter.h" namespace OHOS { namespace DistributedDataDfx { @@ -37,6 +37,6 @@ public: private: std::shared_ptr executors_; }; -} // namespace DistributedDataDfx -} // namespace OHOS +} // namespace DistributedDataDfx +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_RUNTIME_FAULT_IMPL_H diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/service_fault_impl.h b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/service_fault_impl.h index c627f53e..df665d0c 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/service_fault_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/fault/service_fault_impl.h @@ -16,8 +16,8 @@ #ifndef DISTRIBUTEDDATAMGR_SERVICE_FAULT_IMPL_H #define DISTRIBUTEDDATAMGR_SERVICE_FAULT_IMPL_H -#include "hiview_adapter.h" #include "dfx/fault_reporter.h" +#include "hiview_adapter.h" namespace OHOS { namespace DistributedDataDfx { @@ -38,6 +38,6 @@ public: private: std::shared_ptr executors_; }; -} // namespace DistributedDataDfx -} // namespace OHOS +} // namespace DistributedDataDfx +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_SERVICE_FAULT_IMPL_H diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/hiview_adapter.cpp b/datamgr_service/services/distributeddataservice/adapter/dfx/src/hiview_adapter.cpp index c27789c7..35e0ceaf 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/hiview_adapter.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/hiview_adapter.cpp @@ -21,11 +21,12 @@ #include #include "log_print.h" +#include "utils/anonymous.h" #include "utils/time_utils.h" - namespace OHOS { namespace DistributedDataDfx { using namespace DistributedKv; +using Anonymous = DistributedData::Anonymous; namespace { constexpr const char *DATAMGR_DOMAIN = "DISTDATAMGR"; // fault key @@ -134,6 +135,7 @@ void HiViewAdapter::ReportDBFault(int dfxCode, const DBFaultMsg &msg, std::share return; } ExecutorPool::Task task([dfxCode, msg]() { + std::string storeId = Anonymous::Change(msg.storeId); struct HiSysEventParam params[] = { { .name = { *APP_ID }, .t = HISYSEVENT_STRING, @@ -141,7 +143,7 @@ void HiViewAdapter::ReportDBFault(int dfxCode, const DBFaultMsg &msg, std::share .arraySize = 0 }, { .name = { *STORE_ID }, .t = HISYSEVENT_STRING, - .v = { .s = const_cast(msg.storeId.c_str()) }, + .v = { .s = const_cast(storeId.c_str()) }, .arraySize = 0 }, { .name = { *MODULE_NAME }, .t = HISYSEVENT_STRING, @@ -171,6 +173,7 @@ void HiViewAdapter::ReportCommFault(int dfxCode, const CommFaultMsg &msg, std::s } ExecutorPool ::Task task([dfxCode, msg]() { std::string message; + std::string storeId = Anonymous::Change(msg.storeId); for (size_t i = 0; i < msg.deviceId.size(); i++) { message.append("No: ").append(std::to_string(i)) .append(" sync to device: ").append(msg.deviceId[i]) @@ -187,7 +190,7 @@ void HiViewAdapter::ReportCommFault(int dfxCode, const CommFaultMsg &msg, std::s .arraySize = 0 }, { .name = { *STORE_ID }, .t = HISYSEVENT_STRING, - .v = { .s = const_cast(msg.storeId.c_str()) }, + .v = { .s = const_cast(storeId.c_str()) }, .arraySize = 0 }, { .name = { *SYNC_ERROR_INFO }, .t = HISYSEVENT_STRING, @@ -243,6 +246,7 @@ void HiViewAdapter::ReportBehaviour(int dfxCode, const BehaviourMsg &msg, std::s } ExecutorPool::Task task([dfxCode, msg]() { std::string message; + std::string storeId = Anonymous::Change(msg.storeId); message.append("Behaviour type : ").append(std::to_string(static_cast(msg.behaviourType))) .append(" behaviour info : ").append(msg.extensionInfo); struct HiSysEventParam params[] = { @@ -256,7 +260,7 @@ void HiViewAdapter::ReportBehaviour(int dfxCode, const BehaviourMsg &msg, std::s .arraySize = 0 }, { .name = { *STORE_ID }, .t = HISYSEVENT_STRING, - .v = { .s = const_cast(msg.storeId.c_str()) }, + .v = { .s = const_cast(storeId.c_str()) }, .arraySize = 0 }, { .name = { *BEHAVIOUR_INFO }, .t = HISYSEVENT_STRING, @@ -302,7 +306,7 @@ void HiViewAdapter::ReportDbSize(const StatisticWrap &stat) if (!vh.CalcValueHash(stat.val.userId, userId)) { return; } - + std::string storeId = Anonymous::Change(stat.val.storeId); struct HiSysEventParam params[] = { { .name = { *USER_ID }, .t = HISYSEVENT_STRING, @@ -314,7 +318,7 @@ void HiViewAdapter::ReportDbSize(const StatisticWrap &stat) .arraySize = 0 }, { .name = { *STORE_ID }, .t = HISYSEVENT_STRING, - .v = { .s = const_cast(stat.val.storeId.c_str()) }, + .v = { .s = const_cast(storeId.c_str()) }, .arraySize = 0 }, { .name = { *DB_SIZE }, .t = HISYSEVENT_UINT64, .v = { .ui64 = dbSize }, .arraySize = 0 }, }; @@ -383,6 +387,7 @@ void HiViewAdapter::InvokeTraffic() if (!vh.CalcValueHash(kv.second.val.deviceId, deviceId)) { continue; } + std::string devId = Anonymous::Change(deviceId); struct HiSysEventParam params[] = { { .name = { *TAG }, .t = HISYSEVENT_STRING, .v = { .s = const_cast(POWERSTATS) }, .arraySize = 0 }, { .name = { *APP_ID }, @@ -391,7 +396,7 @@ void HiViewAdapter::InvokeTraffic() .arraySize = 0 }, { .name = { *DEVICE_ID }, .t = HISYSEVENT_STRING, - .v = { .s = const_cast(deviceId.c_str()) }, + .v = { .s = const_cast(devId.c_str()) }, .arraySize = 0 }, { .name = { *SEND_SIZE }, .t = HISYSEVENT_INT64, diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/reporter_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/dfx/src/reporter_impl.cpp index a03d4761..a8b142fa 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/reporter_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/reporter_impl.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "dfx/reporter_impl.h" +#include "reporter_impl.h" #include "behaviour/behaviour_reporter_impl.h" #include "fault/cloud_sync_fault_impl.h" diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/api_performance_statistic_impl.h b/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/api_performance_statistic_impl.h index 8c44d269..f5cdff36 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/api_performance_statistic_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/api_performance_statistic_impl.h @@ -16,9 +16,9 @@ #ifndef DISTRIBUTEDDATAMGR_API_PERFORMANCE_STATISTIC_IMPL_H #define DISTRIBUTEDDATAMGR_API_PERFORMANCE_STATISTIC_IMPL_H +#include "dfx/dfx_types.h" #include "dfx/statistic_reporter.h" #include "hiview_adapter.h" -#include "dfx/dfx_types.h" namespace OHOS { namespace DistributedDataDfx { @@ -31,7 +31,6 @@ public: private: std::shared_ptr executors_; }; -} // namespace DistributedDataDfx -} // namespace OHOS +} // namespace DistributedDataDfx +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_API_PERFORMANCE_STATISTIC_IMPL_H - diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/traffic_statistic_impl.h b/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/traffic_statistic_impl.h index b7cac17f..85238d9d 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/traffic_statistic_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/traffic_statistic_impl.h @@ -30,6 +30,6 @@ public: private: std::shared_ptr executors_; }; -} // namespace DistributedDataDfx -} // namespace OHOS +} // namespace DistributedDataDfx +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_TRAFFIC_STATISTIC_IMPL_H diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/visit_statistic_impl.h b/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/visit_statistic_impl.h index c193a659..9898ad54 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/visit_statistic_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/src/statistic/visit_statistic_impl.h @@ -30,6 +30,6 @@ public: private: std::shared_ptr executors_; }; -} // namespace DistributedDataDfx -} // namespace OHOS +} // namespace DistributedDataDfx +} // namespace OHOS #endif // DISTRIBUTEDDATAMGR_VISIT_STATISTIC_IMPL_H diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/dfx/test/BUILD.gn index 78a3fa45..67f11fdd 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/test/BUILD.gn @@ -36,6 +36,7 @@ ohos_unittest("DistributeddataDfxMSTTest") { external_deps = [ "c_utils:utils", "datamgr_service:distributeddatasvcfwk", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", @@ -43,11 +44,7 @@ ohos_unittest("DistributeddataDfxMSTTest") { "openssl:libcrypto_shared", ] ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps = [ - "${data_service_path}/adapter/dfx:distributeddata_dfx", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - ] + deps = [ "${data_service_path}/adapter/dfx:distributeddata_dfx" ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } @@ -77,6 +74,7 @@ ohos_unittest("DistributeddataDfxUTTest") { external_deps = [ "c_utils:utils", "datamgr_service:distributeddatasvcfwk", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", @@ -87,8 +85,6 @@ ohos_unittest("DistributeddataDfxUTTest") { deps = [ "${data_service_path}/adapter/dfx:distributeddata_dfx", "${data_service_path}/adapter/utils:distributeddata_utils", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/distributeddata_dfx_mst_test.cpp b/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/distributeddata_dfx_mst_test.cpp index c5a67afe..5c0065d8 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/distributeddata_dfx_mst_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/distributeddata_dfx_mst_test.cpp @@ -15,7 +15,7 @@ #include #include -#include "reporter.h" +#include "dfx/reporter.h" using namespace testing::ext; using namespace OHOS::DistributedDataDfx; diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/distributeddata_dfx_ut_test.cpp b/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/distributeddata_dfx_ut_test.cpp index d7fed644..4530a003 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/distributeddata_dfx_ut_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/distributeddata_dfx_ut_test.cpp @@ -15,7 +15,7 @@ #include #include -#include "reporter.h" +#include "dfx/reporter.h" #include "fake_hiview.h" #include "value_hash.h" diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/fake/hiview/fake_hiview.cpp b/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/fake/hiview/fake_hiview.cpp index 1f58aa67..b49734e0 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/fake/hiview/fake_hiview.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/fake/hiview/fake_hiview.cpp @@ -13,5 +13,5 @@ * limitations under the License. */ -#include "./include/fake_hiview.h" +#include "include/fake_hiview.h" std::map FakeHivew::fakeCache_; diff --git a/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/hiview_adapter_dfx_test.cpp b/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/hiview_adapter_dfx_test.cpp index f26e70e9..f2198e83 100644 --- a/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/hiview_adapter_dfx_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/dfx/test/unittest/hiview_adapter_dfx_test.cpp @@ -15,11 +15,11 @@ #define LOG_TAG "HiViewAdapterDfxTest" #include "device_manager_adapter.h" -#include "dfx_types.h" +#include "dfx/dfx_types.h" +#include "dfx/radar_reporter.h" #include "gtest/gtest.h" #include "hiview_adapter.h" #include "log_print.h" -#include "radar_reporter.h" using namespace OHOS; using namespace testing; diff --git a/datamgr_service/services/distributeddataservice/adapter/include/communicator/commu_types.h b/datamgr_service/services/distributeddataservice/adapter/include/communicator/commu_types.h index 6b1f1af6..f64fa0dc 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/communicator/commu_types.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/communicator/commu_types.h @@ -16,19 +16,12 @@ #ifndef OHOS_DISTRIBUTED_DATA_ADAPTER_COMMUNICATOR_COMMU_TYPES_H #define OHOS_DISTRIBUTED_DATA_ADAPTER_COMMUNICATOR_COMMU_TYPES_H #include +#include "device_manager/device_manager_types.h" #include "store_errno.h" #include "visibility.h" namespace OHOS::AppDistributedKv { using Status = DistributedKv::Status; -struct API_EXPORT DeviceInfo { - std::string uuid; - std::string udid; - std::string networkId; - std::string deviceName; - uint32_t deviceType; - int32_t osType; - int32_t authForm; -}; +using DeviceInfo = DistributedData::DeviceInfo; struct API_EXPORT AccessCaller { std::string accountId; @@ -59,9 +52,18 @@ enum RouteType : int32_t { BUTT, }; +struct ExtraDataInfo { + std::string userId; + std::string appId; + std::string bundleName; + std::string storeId; + uint32_t tokenId = 0; +}; + struct DataInfo { uint8_t *data; uint32_t length; + ExtraDataInfo extraInfo; }; struct API_EXPORT PipeInfo { @@ -99,5 +101,14 @@ struct API_EXPORT LevelInfo { uint32_t switches; uint16_t switchesLen; }; + +struct API_EXPORT SessionAccessInfo { + int32_t userId = -1; + std::string bundleName; + std::string storeId; + std::string accountId; + uint32_t tokenId = 0; + bool isOHType = true; +}; } #endif // OHOS_DISTRIBUTED_DATA_ADAPTER_COMMUNICATOR_COMMU_TYPES_H diff --git a/datamgr_service/services/distributeddataservice/adapter/include/communicator/communication_provider.h b/datamgr_service/services/distributeddataservice/adapter/include/communicator/communication_provider.h index 07cfb231..32c5b761 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/communicator/communication_provider.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/communicator/communication_provider.h @@ -66,7 +66,7 @@ public: virtual int32_t ListenBroadcastMsg(const PipeInfo &pipeInfo, std::function listener) = 0; - virtual Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId) = 0; + virtual Status ReuseConnect(const PipeInfo &pipeInfo, const DeviceId &deviceId, const ExtraDataInfo &extraInfo) = 0; }; } // namespace AppDistributedKv } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/adapter/include/communicator/communicator_context.h b/datamgr_service/services/distributeddataservice/adapter/include/communicator/communicator_context.h index ce09ab58..7b9ea464 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/communicator/communicator_context.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/communicator/communicator_context.h @@ -21,7 +21,6 @@ #include "commu_types.h" #include "concurrent_map.h" #include "visibility.h" -#include "iprocess_communicator.h" namespace OHOS::DistributedData { class API_EXPORT CommunicatorContext { diff --git a/datamgr_service/services/distributeddataservice/adapter/include/communicator/device_manager_adapter.h b/datamgr_service/services/distributeddataservice/adapter/include/communicator/device_manager_adapter.h index a50783ae..575a2f39 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/communicator/device_manager_adapter.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/communicator/device_manager_adapter.h @@ -24,13 +24,14 @@ #include "concurrent_map.h" #include "device_manager.h" #include "device_manager_callback.h" +#include "device_manager/device_manager_delegate.h" #include "dm_device_info.h" #include "executor_pool.h" #include "lru_bucket.h" namespace OHOS { namespace DistributedData { -class API_EXPORT DeviceManagerAdapter { +class API_EXPORT DeviceManagerAdapter : public DeviceManagerDelegate { public: enum DeviceState { DEVICE_ONLINE, @@ -52,7 +53,7 @@ public: void Init(std::shared_ptr executors); Status StartWatchDeviceChange(const AppDeviceChangeListener *observer, const PipeInfo &pipeInfo); Status StopWatchDeviceChange(const AppDeviceChangeListener *observer, const PipeInfo &pipeInfo); - DeviceInfo GetLocalDevice(); + DeviceInfo GetLocalDevice() override; std::vector GetRemoteDevices(); std::vector GetOnlineDevices(); bool IsDeviceReady(const std::string &id); @@ -103,6 +104,7 @@ private: const DmDeviceInfo cloudDmInfo; ConcurrentMap observers_ {}; LRUBucket deviceInfos_ {64}; + LRUBucket otherDeviceInfos_ {64}; static constexpr size_t TIME_TASK_CAPACITY = 50; static constexpr int32_t SYNC_TIMEOUT = 60 * 1000; // ms static constexpr int32_t OH_OS_TYPE = 10; diff --git a/datamgr_service/services/distributeddataservice/adapter/include/communicator/process_communicator_impl.h b/datamgr_service/services/distributeddataservice/adapter/include/communicator/process_communicator_impl.h index 41df2779..4b326aa5 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/communicator/process_communicator_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/communicator/process_communicator_impl.h @@ -36,6 +36,8 @@ public: using UserInfo = DistributedDB::UserInfo; using RouteHeadHandlerCreator = std::function(const DistributedDB::ExtendInfo &info)>; + using DataHeadInfo = DistributedDB::DataHeadInfo; + using DataUserInfo = DistributedDB::DataUserInfo; API_EXPORT static ProcessCommunicatorImpl *GetInstance(); API_EXPORT void SetRouteHeadHandlerCreator(RouteHeadHandlerCreator handlerCreator); @@ -62,11 +64,10 @@ public: API_EXPORT std::shared_ptr GetExtendHeaderHandle( const DistributedDB::ExtendInfo &info) override; - API_EXPORT DBStatus GetDataHeadInfo(const uint8_t *data, uint32_t totalLen, uint32_t &headLength) override; - API_EXPORT DBStatus GetDataUserInfo(const uint8_t *data, uint32_t totalLen, const std::string &label, - std::vector &userInfos) override; + API_EXPORT DBStatus GetDataHeadInfo(DataHeadInfo dataHeadInfo, uint32_t &headLength) override; + API_EXPORT DBStatus GetDataUserInfo(DataUserInfo dataUserInfo, std::vector &userInfos) override; - Status ReuseConnect(const DeviceId &deviceId); + Status ReuseConnect(const DeviceId &deviceId, const ExtraDataInfo &extraInfo); private: void OnMessage(const DeviceInfo &info, const uint8_t *ptr, const int size, diff --git a/datamgr_service/services/distributeddataservice/adapter/include/communicator/route_head_handler.h b/datamgr_service/services/distributeddataservice/adapter/include/communicator/route_head_handler.h index 47596818..c379ac09 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/communicator/route_head_handler.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/communicator/route_head_handler.h @@ -26,7 +26,8 @@ public: using DBStatus = DistributedDB::DBStatus; using UserInfo = DistributedDB::UserInfo; - virtual bool ParseHeadDataLen(const uint8_t *data, uint32_t totalLen, uint32_t &headSize) = 0; + virtual bool ParseHeadDataLen(const uint8_t *data, uint32_t totalLen, uint32_t &headSize, + const std::string &device) = 0; virtual bool ParseHeadDataUser(const uint8_t *data, uint32_t totalLen, const std::string &label, std::vector &userInfos) = 0; }; diff --git a/datamgr_service/services/distributeddataservice/adapter/network/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/network/BUILD.gn index f120004b..6e2210db 100644 --- a/datamgr_service/services/distributeddataservice/adapter/network/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/network/BUILD.gn @@ -13,15 +13,9 @@ import("//build/ohos.gni") import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") -config("network_public_config") { +config("module_public_config") { visibility = [ ":*" ] - include_dirs = [ - "${data_service_path}/adapter/network/src", - "${data_service_path}/framework/include/network", - ] - if (datamgr_service_cloud) { - include_dirs += [ "${data_service_path}/adapter/include/communicator" ] - } + include_dirs = [ "${data_service_path}/adapter" ] } ohos_source_set("distributeddata_network") { @@ -37,10 +31,9 @@ ohos_source_set("distributeddata_network") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] - configs = [ ":network_public_config" ] + configs = [ ":module_public_config" ] cflags = [ "-fdata-sections", "-ffunction-sections", @@ -49,19 +42,19 @@ ohos_source_set("distributeddata_network") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] external_deps = [ "kv_store:datamgr_common" ] if (datamgr_service_cloud) { sources += [ "src/network_delegate_normal_impl.cpp" ] - deps = [ - "${data_service_path}/adapter/communicator:distributeddata_communicator", - ] + deps += [ "${data_service_path}/adapter/communicator:distributeddata_communicator" ] external_deps += [ + "c_utils:utils", "device_manager:devicemanagersdk", "hilog:libhilog", + "ipc:ipc_single", "netmanager_base:net_conn_manager_if", ] } else { diff --git a/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_default_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_default_impl.cpp index 0372dc5b..192c32cb 100644 --- a/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_default_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_default_impl.cpp @@ -40,6 +40,10 @@ NetworkDelegate::NetworkType NetworkDelegateDefaultImpl::GetNetworkType(bool ret return NetworkType::NONE; } +void NetworkDelegateDefaultImpl::BindExecutor(std::shared_ptr executors) +{ +} + bool NetworkDelegateDefaultImpl::Init() { static NetworkDelegateDefaultImpl delegate; diff --git a/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_default_impl.h b/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_default_impl.h index 5c7583f2..16f3e258 100644 --- a/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_default_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_default_impl.h @@ -25,7 +25,7 @@ public: bool IsNetworkAvailable() override; void RegOnNetworkChange() override; NetworkType GetNetworkType(bool retrieve = false) override; - + void BindExecutor(std::shared_ptr executors) override; private: NetworkDelegateDefaultImpl(); ~NetworkDelegateDefaultImpl(); diff --git a/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_normal_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_normal_impl.cpp index 9389f8dc..5f6d25db 100644 --- a/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_normal_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_normal_impl.cpp @@ -114,22 +114,42 @@ NetworkDelegateNormalImpl::~NetworkDelegateNormalImpl() void NetworkDelegateNormalImpl::RegOnNetworkChange() { - static std::atomic_bool flag = false; - if (flag.exchange(true)) { - ZLOGW("run only one"); - return; + if (executors_ != nullptr) { + executors_->Execute(GetTask(0)); } - sptr observer = new (std::nothrow) NetConnCallbackObserver(*this); - if (observer == nullptr) { - ZLOGE("new operator error.observer is nullptr"); - flag.store(false); - return; - } - auto nRet = NetConnClient::GetInstance().RegisterNetConnCallback(observer); - if (nRet != NETMANAGER_SUCCESS) { +} + +void NetworkDelegateNormalImpl::BindExecutor(std::shared_ptr executors) +{ + executors_ = std::move(executors); +} + +ExecutorPool::Task NetworkDelegateNormalImpl::GetTask(uint32_t retry) +{ + return [this, retry] { + static std::atomic_bool flag = false; + if (flag.exchange(true)) { + ZLOGW("run only one"); + return; + } + sptr observer = new (std::nothrow) NetConnCallbackObserver(*this); + if (observer == nullptr) { + ZLOGE("new operator error.observer is nullptr"); + flag.store(false); + return; + } + auto nRet = NetConnClient::GetInstance().RegisterNetConnCallback(observer); + if (nRet == NETMANAGER_SUCCESS) { + return; + } ZLOGE("RegisterNetConnCallback failed, ret = %{public}d", nRet); flag.store(false); - } + if (retry + 1 >= MAX_RETRY_TIME) { + ZLOGE("fail to register subscriber!"); + return; + } + executors_->Schedule(std::chrono::seconds(RETRY_WAIT_TIME_S), GetTask(retry + 1)); + }; } bool NetworkDelegateNormalImpl::IsNetworkAvailable() diff --git a/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_normal_impl.h b/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_normal_impl.h index 4000ef97..e5944270 100644 --- a/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_normal_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/network/src/network_delegate_normal_impl.h @@ -30,6 +30,7 @@ public: bool IsNetworkAvailable() override; NetworkType GetNetworkType(bool retrieve = false) override; void RegOnNetworkChange() override; + void BindExecutor(std::shared_ptr executors) override; friend class NetConnCallbackObserver; private: NetworkDelegateNormalImpl(); @@ -43,11 +44,15 @@ private: std::chrono::steady_clock::now().time_since_epoch()) .count(); } + ExecutorPool::Task GetTask(uint32_t retry); static constexpr int32_t EFFECTIVE_DURATION = 30 * 1000; // ms static constexpr int32_t NET_LOST_DURATION = 10 * 1000; // ms + static constexpr int32_t MAX_RETRY_TIME = 3; + static constexpr int32_t RETRY_WAIT_TIME_S = 1; NetworkType defaultNetwork_ = NONE; uint64_t expireTime_ = 0; uint64_t netLostTime_ = 0; + std::shared_ptr executors_; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_NETWORK_NORMAL_DELEGATE_IMPL_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/BUILD.gn new file mode 100644 index 00000000..6dcd6a6d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/BUILD.gn @@ -0,0 +1,67 @@ +# 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("NetworkDelegateNormalImplFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + fuzz_config_file = "${data_service_path}/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer" + + sources = [ + "${data_service_path}/framework/network/network_delegate.cpp", + "networkdelegatenormalimpl_fuzzer.cpp", + ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + include_dirs = [ + "${data_service_path}/adapter/include/communicator", + "${data_service_path}/framework/include/network", + "${data_service_path}/adapter/include/utils", + "${data_service_path}/framework/include", + "${data_service_path}/adapter/network/src", + "${data_service_path}/adapter/include", + ] + + deps = [ + "${data_service_path}/adapter/communicator:distributeddata_communicator", + ] + + external_deps = [ + "c_utils:utils", + "device_manager:devicemanagersdk", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + "netmanager_base:net_conn_manager_if", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":NetworkDelegateNormalImplFuzzTest" ] +} +############################################################################### diff --git a/kv_store/test/fuzztest/singlekvstorestub_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/corpus/init similarity index 92% rename from kv_store/test/fuzztest/singlekvstorestub_fuzzer/corpus/init rename to datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/corpus/init index 6198079a..7ade8a0f 100644 --- a/kv_store/test/fuzztest/singlekvstorestub_fuzzer/corpus/init +++ b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/corpus/init @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 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 diff --git a/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/networkdelegatenormalimpl_fuzzer.cpp b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/networkdelegatenormalimpl_fuzzer.cpp new file mode 100644 index 00000000..f06ce4a5 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/networkdelegatenormalimpl_fuzzer.cpp @@ -0,0 +1,89 @@ +/* + * 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 "network_delegate.h" +#include "network_delegate_normal_impl.h" +#include "network_delegate_normal_impl.cpp" +#include + +using namespace OHOS::DistributedData; + +namespace OHOS { +void GetNetworkTypeFuzz(FuzzedDataProvider &provider) +{ + NetworkDelegateNormalImpl delegate; + delegate.Init(); + bool retrieve = provider.ConsumeIntegral(); + delegate.GetNetworkType(retrieve); + + sptr observer = new (std::nothrow) NetConnCallbackObserver(delegate); + sptr netHandle = new (std::nothrow) NetHandle(); + sptr netAllCap = new (std::nothrow) NetAllCapabilities(); + observer->NetCapabilitiesChange(netHandle, netAllCap); + netAllCap->netCaps_.insert(NetManagerStandard::NET_CAPABILITY_VALIDATED); + observer->NetCapabilitiesChange(netHandle, netAllCap); + observer->NetAvailable(netHandle); + observer->NetUnavailable(); +} + +void GetTaskFuzz(FuzzedDataProvider &provider) +{ + NetworkDelegateNormalImpl delegate; + delegate.Init(); + uint32_t retry = provider.ConsumeIntegral(); + delegate.GetTask(retry); + + sptr observer = new (std::nothrow) NetConnCallbackObserver(delegate); + sptr netHandle = new (std::nothrow) NetHandle(); + sptr info = new (std::nothrow) NetLinkInfo(); + observer->NetConnectionPropertiesChange(netHandle, info); + observer->NetLost(netHandle); + delegate.RegOnNetworkChange(); +} + +void BindExecutorFuzz(FuzzedDataProvider &provider) +{ + NetworkDelegateNormalImpl delegate; + delegate.Init(); + size_t max = provider.ConsumeIntegralInRange(12, 15); + size_t min = provider.ConsumeIntegralInRange(5, 8); + auto executor = std::make_shared(max, min); + delegate.BindExecutor(executor); + delegate.IsNetworkAvailable(); +} + +void NetBlockStatusChangeFuzz(FuzzedDataProvider &provider) +{ + NetworkDelegateNormalImpl delegate; + delegate.Init(); + sptr observer = new (std::nothrow) NetConnCallbackObserver(delegate); + sptr netHandle = nullptr; + bool blocked = provider.ConsumeIntegral(); + observer->NetBlockStatusChange(netHandle, blocked); + delegate.RefreshNet(); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::GetNetworkTypeFuzz(provider); + OHOS::GetTaskFuzz(provider); + OHOS::BindExecutorFuzz(provider); + OHOS::NetBlockStatusChangeFuzz(provider); + return 0; +} \ No newline at end of file diff --git a/kv_store/test/fuzztest/distributedkvdataservice_fuzzer/distributedkvdataservice_fuzzer.h b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/networkdelegatenormalimpl_fuzzer.h similarity index 70% rename from kv_store/test/fuzztest/distributedkvdataservice_fuzzer/distributedkvdataservice_fuzzer.h rename to datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/networkdelegatenormalimpl_fuzzer.h index 37eb9ac9..1ae55e23 100644 --- a/kv_store/test/fuzztest/distributedkvdataservice_fuzzer/distributedkvdataservice_fuzzer.h +++ b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/networkdelegatenormalimpl_fuzzer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 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,10 +13,9 @@ * limitations under the License. */ -#ifndef DISTRIBUTEDKVDATASERVICE_FUZZER_H -#define DISTRIBUTEDKVDATASERVICE_FUZZER_H +#ifndef NETWORKDELEGATENORMALIMPL_FUZZER_H +#define NETWORKDELEGATENORMALIMPL_FUZZER_H -#define FUZZ_PROJECT_NAME "distributedkvdataservice_fuzzer" - -#endif // DISTRIBUTEDKVDATASERVICE_FUZZER_H +#define FUZZ_PROJECT_NAME "networkdelegatenormalimpl_fuzzer" +#endif // NETWORKDELEGATENORMALIMPL_FUZZER_H \ No newline at end of file diff --git a/kv_store/test/fuzztest/jsonservice_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/project.xml similarity index 63% rename from kv_store/test/fuzztest/jsonservice_fuzzer/project.xml rename to datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/project.xml index 73736f01..a37a23b1 100644 --- a/kv_store/test/fuzztest/jsonservice_fuzzer/project.xml +++ b/datamgr_service/services/distributeddataservice/adapter/network/test/fuzztest/networkdelegatenormalimpl_fuzzer/project.xml @@ -1,5 +1,5 @@ - - - - 1000 - - 1800 - - 4096 - - + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/network/test/network_delegate_normal_impl_test.cpp b/datamgr_service/services/distributeddataservice/adapter/network/test/network_delegate_normal_impl_test.cpp index 9d4842a9..bf7df17c 100644 --- a/datamgr_service/services/distributeddataservice/adapter/network/test/network_delegate_normal_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/network/test/network_delegate_normal_impl_test.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "network/network_delegate.h" +#include "network_delegate.h" #include "network_delegate_normal_impl.h" #include "network_delegate_normal_impl.cpp" #include diff --git a/datamgr_service/services/distributeddataservice/adapter/network/test/network_delegate_test.cpp b/datamgr_service/services/distributeddataservice/adapter/network/test/network_delegate_test.cpp index 391aa008..a5b575e1 100644 --- a/datamgr_service/services/distributeddataservice/adapter/network/test/network_delegate_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/network/test/network_delegate_test.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ #define LOG_TAG "NetworkDelegateTest" -#include "network/network_delegate.h" +#include "network_delegate.h" #include #include diff --git a/datamgr_service/services/distributeddataservice/adapter/schema_helper/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/schema_helper/BUILD.gn index 4bfbe3be..c3516c44 100644 --- a/datamgr_service/services/distributeddataservice/adapter/schema_helper/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/schema_helper/BUILD.gn @@ -15,7 +15,7 @@ import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") config("module_public_config") { visibility = [ ":*" ] - include_dirs = [ "../include/schema_helper" ] + include_dirs = [ "." ] } ohos_source_set("distributeddata_schema_helper") { @@ -27,15 +27,13 @@ ohos_source_set("distributeddata_schema_helper") { boundary_sanitize = true ubsan = true } - sources = [ "src/get_schema_helper.cpp" ] + sources = [ "get_schema_helper.cpp" ] cflags_cc = [ "-fvisibility=hidden", "-fstack-protector-strong", ] - include_dirs = [ "../include/schema_helper" ] - public_configs = [ ":module_public_config" ] external_deps = [ "bundle_framework:appexecfwk_base", diff --git a/datamgr_service/services/distributeddataservice/adapter/schema_helper/src/get_schema_helper.cpp b/datamgr_service/services/distributeddataservice/adapter/schema_helper/get_schema_helper.cpp similarity index 98% rename from datamgr_service/services/distributeddataservice/adapter/schema_helper/src/get_schema_helper.cpp rename to datamgr_service/services/distributeddataservice/adapter/schema_helper/get_schema_helper.cpp index b5c847b3..25ce2299 100644 --- a/datamgr_service/services/distributeddataservice/adapter/schema_helper/src/get_schema_helper.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/schema_helper/get_schema_helper.cpp @@ -14,7 +14,7 @@ */ #define LOG_TAG "SchemaHelper" -#include "schema_helper/get_schema_helper.h" +#include "get_schema_helper.h" #include "bundle_mgr_interface.h" #include "if_system_ability_manager.h" diff --git a/datamgr_service/services/distributeddataservice/adapter/include/schema_helper/get_schema_helper.h b/datamgr_service/services/distributeddataservice/adapter/schema_helper/get_schema_helper.h similarity index 100% rename from datamgr_service/services/distributeddataservice/adapter/include/schema_helper/get_schema_helper.h rename to datamgr_service/services/distributeddataservice/adapter/schema_helper/get_schema_helper.h diff --git a/datamgr_service/services/distributeddataservice/adapter/screenlock/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/screenlock/BUILD.gn index 28f3b0b7..766eb3f9 100644 --- a/datamgr_service/services/distributeddataservice/adapter/screenlock/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/BUILD.gn @@ -13,6 +13,11 @@ import("//build/ohos.gni") import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") +config("module_public_config") { + visibility = [ ":*" ] + include_dirs = [ "${data_service_path}/adapter" ] +} + ohos_source_set("distributeddata_screenlock") { branch_protector_ret = "pac_ret" sanitize = { @@ -22,25 +27,24 @@ ohos_source_set("distributeddata_screenlock") { boundary_sanitize = true ubsan = true } - sources = [ "src/screen_lock.cpp" ] + sources = [ "screen_lock.cpp" ] cflags_cc = [ "-fvisibility=hidden", "-fstack-protector-strong", ] - include_dirs = [ - "../include/screenlock", - "../include/utils", - "${data_service_path}/framework/include", + public_configs = [ ":module_public_config" ] + deps = [ + "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/framework:distributeddatasvcfwk", ] - deps = [ "${data_service_path}/adapter/account:distributeddata_account" ] - external_deps = [ "c_utils:utils", "common_event_service:cesfwk_innerkits", "hilog:libhilog", + "ipc:ipc_core", "kv_store:datamgr_common", "screenlock_mgr:screenlock_client", ] diff --git a/datamgr_service/services/distributeddataservice/adapter/screenlock/src/screen_lock.cpp b/datamgr_service/services/distributeddataservice/adapter/screenlock/screen_lock.cpp similarity index 94% rename from datamgr_service/services/distributeddataservice/adapter/screenlock/src/screen_lock.cpp rename to datamgr_service/services/distributeddataservice/adapter/screenlock/screen_lock.cpp index 36c5d601..42d0ee8b 100644 --- a/datamgr_service/services/distributeddataservice/adapter/screenlock/src/screen_lock.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/screen_lock.cpp @@ -14,7 +14,7 @@ */ #define LOG_TAG "ScreenLock" -#include "screenlock/screen_lock.h" +#include "screen_lock.h" #include "account/account_delegate.h" #include "log_print.h" @@ -94,7 +94,9 @@ void ScreenLock::SubscribeScreenEvent() NotifyScreenUnlocked(user); }); } - executors_->Execute(GetTask(0)); + if (executors_ != nullptr) { + executors_->Execute(GetTask(0)); + } } void ScreenLock::UnsubscribeScreenEvent() @@ -132,7 +134,9 @@ ExecutorPool::Task ScreenLock::GetTask(uint32_t retry) ZLOGE("fail to register subscriber!"); return; } - executors_->Schedule(std::chrono::seconds(RETRY_WAIT_TIME_S), GetTask(retry + 1)); + if (executors_ != nullptr) { + executors_->Schedule(std::chrono::seconds(RETRY_WAIT_TIME_S), GetTask(retry + 1)); + } }; } } // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/include/screenlock/screen_lock.h b/datamgr_service/services/distributeddataservice/adapter/screenlock/screen_lock.h similarity index 100% rename from datamgr_service/services/distributeddataservice/adapter/include/screenlock/screen_lock.h rename to datamgr_service/services/distributeddataservice/adapter/screenlock/screen_lock.h diff --git a/datamgr_service/services/distributeddataservice/adapter/screenlock/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/BUILD.gn index f1f16b53..132dc9bd 100644 --- a/datamgr_service/services/distributeddataservice/adapter/screenlock/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/BUILD.gn @@ -18,30 +18,25 @@ module_output_path = "datamgr_service/datamgr_service/distributeddatafwk" ohos_unittest("ScreenLockTest") { module_out_path = module_output_path - sources = [ - "${data_service_path}/adapter/screenlock/src/screen_lock.cpp", - "${data_service_path}/framework/account/account_delegate.cpp", - "${data_service_path}/framework/screen/screen_manager.cpp", - "screen_lock_test.cpp", - ] - include_dirs = [ - "${data_service_path}/adapter/include/screenlock", - "${data_service_path}/framework/include", - "${data_service_path}/framework/include/account", - ] + sources = [ "screen_lock_test.cpp" ] + cflags = [ "-Dprivate=public", "-Dprotected=public", "-Werror", ] + deps = [ + "${data_service_path}/adapter/screenlock:distributeddata_screenlock", + "${data_service_path}/framework:distributeddatasvcfwk" + ] external_deps = [ "c_utils:utils", "common_event_service:cesfwk_innerkits", "googletest:gtest_main", "hilog:libhilog", - "kv_store:distributeddata_inner", - "screenlock_mgr:screenlock_client", + "ipc:ipc_core", + "kv_store:datamgr_common", ] defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] } diff --git a/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/BUILD.gn new file mode 100644 index 00000000..cc14fd93 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/BUILD.gn @@ -0,0 +1,56 @@ +# 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("ScreenlockFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + fuzz_config_file = + "${data_service_path}/adapter/screenlock/test/fuzztest/screenlock_fuzzer" + + sources = [ "screenlock_fuzzer.cpp" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-Dprivate=public", + "-Dprotected=public", + ] + + deps = [ + "${data_service_path}/adapter/screenlock:distributeddata_screenlock", + "${data_service_path}/framework:distributeddatasvcfwk", + ] + + external_deps = [ + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":ScreenlockFuzzTest" ] +} +############################################################################### diff --git a/kv_store/test/fuzztest/jsonservice_fuzzer/jsonservice_fuzzer.h b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/corpus/init similarity index 78% rename from kv_store/test/fuzztest/jsonservice_fuzzer/jsonservice_fuzzer.h rename to datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/corpus/init index af5feb8c..7ade8a0f 100644 --- a/kv_store/test/fuzztest/jsonservice_fuzzer/jsonservice_fuzzer.h +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/corpus/init @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 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,9 +13,4 @@ * limitations under the License. */ -#ifndef JSON_FUZZER_H -#define JSON_FUZZER_H - -#define FUZZ_PROJECT_NAME "Json_fuzzer" - -#endif // JSON_FUZZER_H \ No newline at end of file +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/project.xml new file mode 100644 index 00000000..a37a23b1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/screenlock_fuzzer.cpp b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/screenlock_fuzzer.cpp new file mode 100644 index 00000000..0d6bb47b --- /dev/null +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/screenlock_fuzzer.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 +#include "screenlock_fuzzer.h" +#include "screenlock/screen_lock.h" + +using namespace OHOS::DistributedData; +namespace OHOS { +class ScreenLockObserver : public ScreenManager::Observer { +public: + void OnScreenUnlocked(int32_t user) override + { + } + + std::string GetName() override + { + return name_; + } + + void SetName(const std::string &name) + { + name_ = name; + } + +private: + std::string name_ = "screenTestObserver"; +}; + +void SubscribeFuzz(FuzzedDataProvider &provider) +{ + auto screenLock = std::make_shared(); + screenLock->Subscribe(nullptr); + auto observer = std::make_shared(); + std::string name = provider.ConsumeRandomLengthString(); + observer->SetName(name); + screenLock->Subscribe(observer); + screenLock->IsLocked(); +} + +void UnsubscribeFuzz(FuzzedDataProvider &provider) +{ + auto screenLock = std::make_shared(); + auto observer = std::make_shared(); + std::string name = provider.ConsumeRandomLengthString(); + observer->SetName(name); + screenLock->Subscribe(observer); + screenLock->Unsubscribe(observer); + screenLock->UnsubscribeScreenEvent(); +} + +void GetTaskFuzz(FuzzedDataProvider &provider) +{ + auto screenLock = std::make_shared(); + int retry = provider.ConsumeIntegralInRange(1, 20); + screenLock->GetTask(retry); +} + +void NotifyScreenUnlockedFuzz(FuzzedDataProvider &provider) +{ + auto screenLock = std::make_shared(); + int user = provider.ConsumeIntegral(); + screenLock->NotifyScreenUnlocked(user); +} + +void OnReceiveEventFuzz(FuzzedDataProvider &provider) +{ + OHOS::EventFwk::MatchingSkills matchingSkills; + std::string reserved = provider.ConsumeRandomLengthString(); + matchingSkills.AddEvent(reserved); + OHOS::EventFwk::CommonEventSubscribeInfo info(matchingSkills); + int priority = provider.ConsumeIntegral(); + info.SetPriority(priority); + info.SetPermission("ohos.permission.SUBSCRIBE_SCREEN_LOCK"); + auto subscriber = std::make_shared(info); + OHOS::AAFwk::Want want; + want.SetAction(CommonEventSupport::COMMON_EVENT_HWID_LOGIN); + CommonEventData commonEventData(want); + CommonEventData event(want); + subscriber->OnReceiveEvent(event); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::SubscribeFuzz(provider); + OHOS::UnsubscribeFuzz(provider); + OHOS::GetTaskFuzz(provider); + OHOS::NotifyScreenUnlockedFuzz(provider); + OHOS::OnReceiveEventFuzz(provider); + return 0; +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/rddbrepair_fuzzer.h b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/screenlock_fuzzer.h similarity index 76% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/rddbrepair_fuzzer.h rename to datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/screenlock_fuzzer.h index 0a95b06c..2ae3c12c 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/rddbrepair_fuzzer.h +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/fuzztest/screenlock_fuzzer/screenlock_fuzzer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 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,9 +13,9 @@ * limitations under the License. */ -#ifndef RDDBREPAIR_FUZZER_H -#define RDDBREPAIR_FUZZER_H +#ifndef SCREENLOCK_FUZZER_H +#define SCREENLOCK_FUZZER_H -#define FUZZ_PROJECT_NAME "rddbrepair_fuzzer" +#define FUZZ_PROJECT_NAME "screenlock_fuzzer" -#endif // RDDBREPAIR_FUZZER_H \ No newline at end of file +#endif // SCREENLOCK_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/screenlock/test/screen_lock_test.cpp b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/screen_lock_test.cpp index be5a5f5f..5384155b 100644 --- a/datamgr_service/services/distributeddataservice/adapter/screenlock/test/screen_lock_test.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/screenlock/test/screen_lock_test.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "screen_lock.h" +#include "screenlock/screen_lock.h" #include namespace { @@ -53,6 +53,8 @@ public: void TearDown() { } +protected: + static constexpr int32_t MAX_RETRY_TIME = 300; }; /** @@ -65,7 +67,6 @@ public: HWTEST_F(ScreenLockTest, Subscribe001, TestSize.Level0) { auto screenLock = std::make_shared(); - screenLock->ScreenManager::Subscribe(nullptr); screenLock->Subscribe(nullptr); EXPECT_TRUE(screenLock->observerMap_.Empty()); auto observer = std::make_shared(); @@ -101,7 +102,6 @@ HWTEST_F(ScreenLockTest, Subscribe002, TestSize.Level0) HWTEST_F(ScreenLockTest, Unsubscribe001, TestSize.Level0) { auto screenLock = std::make_shared(); - screenLock->ScreenManager::Unsubscribe(nullptr); auto observer = std::make_shared(); screenLock->Subscribe(observer); EXPECT_EQ(screenLock->observerMap_.Size(), 1); @@ -122,10 +122,62 @@ HWTEST_F(ScreenLockTest, SubscribeScreenEvent001, TestSize.Level0) screenLock->BindExecutor(executor); ASSERT_NE(screenLock->executors_, nullptr); EXPECT_EQ(screenLock->eventSubscriber_, nullptr); - screenLock->ScreenManager::SubscribeScreenEvent(); screenLock->SubscribeScreenEvent(); EXPECT_NE(screenLock->eventSubscriber_, nullptr); - screenLock->ScreenManager::UnsubscribeScreenEvent(); screenLock->UnsubscribeScreenEvent(); + screenLock->executors_ = nullptr; +} + +/** +* @tc.name: SubscribeScreenEvent002 +* @tc.desc: subscribe ScreenEvent +* @tc.type: FUNC +* @tc.author: +*/ +HWTEST_F(ScreenLockTest, SubscribeScreenEvent002, TestSize.Level0) +{ + auto screenLock = std::make_shared(); + EXPECT_EQ(screenLock->executors_, nullptr); + EXPECT_EQ(screenLock->eventSubscriber_, nullptr); + screenLock->SubscribeScreenEvent(); + EXPECT_NE(screenLock->eventSubscriber_, nullptr); + screenLock->UnsubscribeScreenEvent(); +} + +/** +* @tc.name: GetTask001 +* @tc.desc: subscribe ScreenEvent +* @tc.type: FUNC +* @tc.author: +*/ +HWTEST_F(ScreenLockTest, GetTask001, TestSize.Level0) +{ + auto screenLock = std::make_shared(); + EXPECT_EQ(screenLock->executors_, nullptr); + EXPECT_EQ(screenLock->eventSubscriber_, nullptr); + auto Task = screenLock->GetTask(0); + Task(); + auto executor = std::make_shared(12, 5); + screenLock->BindExecutor(executor); + ASSERT_NE(screenLock->executors_, nullptr); + Task = screenLock->GetTask(MAX_RETRY_TIME - 1); + Task(); +} + +/** +* @tc.name: GetTask002 +* @tc.desc: subscribe ScreenEvent +* @tc.type: FUNC +* @tc.author: +*/ +HWTEST_F(ScreenLockTest, GetTask002, TestSize.Level0) +{ + auto screenLock = std::make_shared(); + EXPECT_EQ(screenLock->executors_, nullptr); + EXPECT_EQ(screenLock->eventSubscriber_, nullptr); + screenLock->SubscribeScreenEvent(); + EXPECT_NE(screenLock->eventSubscriber_, nullptr); + auto Task = screenLock->GetTask(0); + Task(); } } // namespace \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/test/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/test/BUILD.gn index 6f6f3b43..4ccfd981 100644 --- a/datamgr_service/services/distributeddataservice/adapter/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/test/BUILD.gn @@ -22,9 +22,13 @@ group("unittest") { "../account/test:unittest", "../communicator/test:unittest", "../dfx/test:unittest", - "../screenlock/test:unittest", ] + if (defined(global_parts_info) && + defined(global_parts_info.theme_screenlock_mgr)) { + deps += [ "${data_service_path}/adapter/screenlock/test:unittest" ] + } + if (datamgr_service_cloud) { deps += [ "../network/test:unittest" ] } @@ -33,5 +37,13 @@ group("unittest") { group("fuzztest") { testonly = true - deps = [ "../communicator/test/fuzztest:fuzztest" ] + deps = [ + "../communicator/test/fuzztest:fuzztest", + "../network/test/fuzztest/networkdelegatenormalimpl_fuzzer:fuzztest", + ] + + if (defined(global_parts_info) && + defined(global_parts_info.theme_screenlock_mgr)) { + deps += [ "../screenlock/test/fuzztest/screenlock_fuzzer:fuzztest" ] + } } diff --git a/datamgr_service/services/distributeddataservice/adapter/utils/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/utils/BUILD.gn index 8325bf05..bf5b815f 100644 --- a/datamgr_service/services/distributeddataservice/adapter/utils/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/utils/BUILD.gn @@ -24,17 +24,14 @@ ohos_source_set("distributeddata_utils") { } sources = [ "src/kvstore_utils.cpp" ] - cflags_cc = [ - "-fvisibility=hidden", - "-fstack-protector-strong", - ] + cflags_cc = [ "-fvisibility=hidden" ] if (build_public_version) { cflags_cc += [ "-DCONFIG_PUBLIC_VERSION" ] } include_dirs = [ "../include/utils" ] - ldflags = [ "-Wl,-z,relro,-z,now,--exclude-libs,ALL" ] + ldflags = [ "-Wl,--exclude-libs,ALL" ] external_deps = [ "c_utils:utils", diff --git a/datamgr_service/services/distributeddataservice/app/BUILD.gn b/datamgr_service/services/distributeddataservice/app/BUILD.gn index b66d0134..2415418d 100644 --- a/datamgr_service/services/distributeddataservice/app/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/BUILD.gn @@ -38,9 +38,6 @@ ohos_sa_profile("distributeddata_profile") { config("module_private_config") { visibility = [ ":*" ] include_dirs = [ - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", "${data_service_path}/adapter/include/account", "${data_service_path}/adapter/include/permission", "${data_service_path}/adapter/include/screen", @@ -76,16 +73,14 @@ config("module_private_config") { "-Oz", "-fdata-sections", "-ffunction-sections", - "-fstack-protector-strong", ] cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] - ldflags = [ "-Wl,-z,relro,-z,now,--gc-sections" ] + ldflags = [ "-Wl,--gc-sections" ] } ohos_shared_library("distributeddataservice") { @@ -98,7 +93,6 @@ ohos_shared_library("distributeddataservice") { ubsan = true } sources = [ - "${data_service_path}/service/common/xcollie.cpp", "src/clone/clone_backup_info.cpp", "src/clone/secret_key_backup_data.cpp", "src/db_info_handle_impl.cpp", @@ -127,7 +121,6 @@ ohos_shared_library("distributeddataservice") { configs = [ ":module_private_config" ] deps = [ - "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/app/src/checker:distributeddata_checker", "${data_service_path}/app/src/installer:distributeddata_installer", "${data_service_path}/framework:distributeddatasvcfwk", @@ -170,4 +163,4 @@ ohos_shared_library("distributeddataservice") { subsystem_name = "distributeddatamgr" part_name = "datamgr_service" defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] -} +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/CMakeLists.txt b/datamgr_service/services/distributeddataservice/app/CMakeLists.txt index 0d383c14..b885fb47 100644 --- a/datamgr_service/services/distributeddataservice/app/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/app/CMakeLists.txt @@ -11,6 +11,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") set(MOCK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../mock") set(KV_STORE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../kv_store") add_definitions(-DPROCESS_LABEL="mytest") +add_definitions(-D__CJSON_USE_INT64) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src appSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/flowctrl_manager appSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/installer appSrc) diff --git a/datamgr_service/services/distributeddataservice/app/distributed_data.cfg b/datamgr_service/services/distributeddataservice/app/distributed_data.cfg index 65e8ac88..0480668e 100644 --- a/datamgr_service/services/distributeddataservice/app/distributed_data.cfg +++ b/datamgr_service/services/distributeddataservice/app/distributed_data.cfg @@ -17,7 +17,7 @@ "name" : "distributeddata", "path" : ["/system/bin/sa_main","/system/profile/distributeddata.json"], "uid" : "ddms", - "gid" : ["system","shell","readproc","ddms","dfs_share","netsys_socket","data_reserve"], + "gid" : ["system","shell","readproc","ddms","dfs_share","data_reserve"], "writepid":[ "/dev/cpuset/foreground/tasks", "/dev/stune/foreground/tasks", diff --git a/datamgr_service/services/distributeddataservice/app/src/checker/BUILD.gn b/datamgr_service/services/distributeddataservice/app/src/checker/BUILD.gn index 6695b0d6..f0fa8dd2 100644 --- a/datamgr_service/services/distributeddataservice/app/src/checker/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/src/checker/BUILD.gn @@ -30,7 +30,6 @@ ohos_source_set("distributeddata_checker") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ "${data_service_path}/framework/include" ] @@ -38,12 +37,9 @@ ohos_source_set("distributeddata_checker") { if (build_public_version) { cflags_cc += [ "-DCONFIG_PUBLIC_VERSION" ] } - ldflags = [ "-Wl,-z,relro,-z,now,--exclude-libs,ALL" ] + ldflags = [ "-Wl,--exclude-libs,ALL" ] deps = [ "${data_service_path}/adapter/utils:distributeddata_utils" ] - cflags = [ - "-Oz", - "-fstack-protector-strong", - ] + cflags = [ "-Oz" ] external_deps = [ "ability_base:base", "ability_base:want", diff --git a/datamgr_service/services/distributeddataservice/app/src/checker/bundle_checker.cpp b/datamgr_service/services/distributeddataservice/app/src/checker/bundle_checker.cpp index 674e09d5..b726ab91 100644 --- a/datamgr_service/services/distributeddataservice/app/src/checker/bundle_checker.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/checker/bundle_checker.cpp @@ -61,8 +61,26 @@ bool BundleChecker::SetSwitchesInfo(const CheckerManager::Switches &switches) return true; } +std::string BundleChecker::GetKey(const std::string &bundleName, int32_t userId) +{ + return bundleName + "###" + std::to_string(userId); +} + +std::string BundleChecker::GetAppidFromCache(const std::string &bundleName, int32_t userId) +{ + std::string appId; + std::string key = GetKey(bundleName, userId); + appIds_.Get(key, appId); + return appId; +} + std::string BundleChecker::GetBundleAppId(const CheckerManager::StoreInfo &info) { + int32_t userId = info.uid / OHOS::AppExecFwk::Constants::BASE_USER_RANGE; + std::string appId = GetAppidFromCache(info.bundleName, userId); + if (!appId.empty()) { + return appId; + } auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (samgrProxy == nullptr) { ZLOGE("Failed to get system ability mgr."); @@ -78,15 +96,28 @@ std::string BundleChecker::GetBundleAppId(const CheckerManager::StoreInfo &info) ZLOGE("Failed to get bundle manager"); return ""; } - int32_t userId = info.uid / OHOS::AppExecFwk::Constants::BASE_USER_RANGE; - std::string appId = bundleManager->GetAppIdByBundleName(info.bundleName, userId); + appId = bundleManager->GetAppIdByBundleName(info.bundleName, userId); if (appId.empty()) { ZLOGE("GetAppIdByBundleName failed appId:%{public}s, bundleName:%{public}s, uid:%{public}d", appId.c_str(), info.bundleName.c_str(), userId); + } else { + appIds_.Set(GetKey(info.bundleName, userId), appId); } return appId; } +void BundleChecker::DeleteCache(const std::string &bundleName, int32_t user, int32_t index) +{ + std::string key = GetKey(bundleName, user); + appIds_.Delete(key); +} + +void BundleChecker::ClearCache() +{ + appIds_.ResetCapacity(0); + appIds_.ResetCapacity(CACHE_SIZE); +} + std::string BundleChecker::GetAppId(const CheckerManager::StoreInfo &info) { if (AccessTokenKit::GetTokenTypeFlag(info.tokenId) != TOKEN_HAP) { @@ -114,7 +145,6 @@ bool BundleChecker::IsValid(const CheckerManager::StoreInfo &info) if (AccessTokenKit::GetHapTokenInfo(info.tokenId, tokenInfo) != RET_SUCCESS) { return false; } - return tokenInfo.bundleName == info.bundleName; } diff --git a/datamgr_service/services/distributeddataservice/app/src/checker/bundle_checker.h b/datamgr_service/services/distributeddataservice/app/src/checker/bundle_checker.h index 1eba18e5..d5c655bb 100644 --- a/datamgr_service/services/distributeddataservice/app/src/checker/bundle_checker.h +++ b/datamgr_service/services/distributeddataservice/app/src/checker/bundle_checker.h @@ -16,6 +16,7 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CHECKER_BUNDLE_CHECKER_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CHECKER_BUNDLE_CHECKER_H #include "checker/checker_manager.h" +#include "lru_bucket.h" namespace OHOS { namespace DistributedData { class BundleChecker : public CheckerManager::Checker { @@ -36,8 +37,12 @@ public: std::vector GetStaticStores() override; bool IsDynamic(const CheckerManager::StoreInfo &info) override; bool IsStatic(const CheckerManager::StoreInfo &info) override; - + void DeleteCache(const std::string &bundleName, int32_t user, int32_t index) override; + void ClearCache() override; private: + static constexpr int32_t CACHE_SIZE = 32; + std::string GetAppidFromCache(const std::string &bundleName, int32_t userId); + std::string GetKey(const std::string &bundleName, int32_t userId); static BundleChecker instance_; std::map trusts_; std::map distrusts_; @@ -45,6 +50,7 @@ private: std::vector dynamicStores_; std::vector staticStores_; std::string GetBundleAppId(const CheckerManager::StoreInfo &info); + LRUBucket appIds_ { CACHE_SIZE }; }; } // namespace DistributedData } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.cpp b/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.cpp index e81ed5a8..1cddeacf 100644 --- a/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.cpp @@ -53,6 +53,14 @@ int32_t FeatureStubImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const return featureImpl_->OnAppExit(uid, pid, tokenId, bundleName); } +int32_t FeatureStubImpl::OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) +{ + if (featureImpl_ == nullptr) { + return -1; + } + return featureImpl_->OnFeatureExit(uid, pid, tokenId, bundleName); +} + int32_t FeatureStubImpl::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index) { if (featureImpl_ == nullptr) { diff --git a/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.h b/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.h index 77e90d58..7c2715a6 100644 --- a/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.h +++ b/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.h @@ -32,6 +32,7 @@ public: MessageOption &option) override; int32_t OnInitialize(std::shared_ptr executor); int32_t OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName); + int32_t OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName); int32_t OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index); int32_t OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index); int32_t OnAppInstall(const std::string &bundleName, int32_t user, int32_t index); diff --git a/datamgr_service/services/distributeddataservice/app/src/installer/BUILD.gn b/datamgr_service/services/distributeddataservice/app/src/installer/BUILD.gn index 49eb62d2..0ccfc73e 100644 --- a/datamgr_service/services/distributeddataservice/app/src/installer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/src/installer/BUILD.gn @@ -40,13 +40,9 @@ ohos_source_set("distributeddata_installer") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] - cflags = [ - "-Oz", - "-fstack-protector-strong", - ] + cflags = [ "-Oz" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk", diff --git a/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.cpp b/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.cpp index 6977b3ab..ecb54854 100644 --- a/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.cpp @@ -83,9 +83,9 @@ void InstallEventSubscriber::OnUninstall(const std::string &bundleName, int32_t } for (auto &meta : storeMetaData) { if (meta.instanceId == appIndex && !meta.appId.empty() && !meta.storeId.empty()) { - ZLOGI("uninstalled bundleName:%{public}s storeId:%{public}s, userId:%{public}d, appIndex:%{public}d", - bundleName.c_str(), Anonymous::Change(meta.storeId).c_str(), userId, appIndex); - MetaDataManager::GetInstance().DelMeta(meta.GetKey()); + ZLOGI("storeMetaData uninstalled bundleName:%{public}s storeId:%{public}s, userId:%{public}d, " + "appIndex:%{public}d", bundleName.c_str(), Anonymous::Change(meta.storeId).c_str(), userId, appIndex); + MetaDataManager::GetInstance().DelMeta(meta.GetKeyWithoutPath()); MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetKeyLocal(), true); MetaDataManager::GetInstance().DelMeta(meta.GetSecretKey(), true); @@ -96,7 +96,8 @@ void InstallEventSubscriber::OnUninstall(const std::string &bundleName, int32_t MetaDataManager::GetInstance().DelMeta(meta.GetDebugInfoKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetDfxInfoKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetCloneSecretKey(), true); - PermitDelegate::GetInstance().DelCache(meta.GetKey()); + MetaDataManager::GetInstance().DelMeta(StoreMetaMapping(meta).GetKey(), true); + PermitDelegate::GetInstance().DelCache(meta.GetKeyWithoutPath()); } } } diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_account_observer.h b/datamgr_service/services/distributeddataservice/app/src/kvstore_account_observer.h index d8ea3d15..bbc53508 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_account_observer.h +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_account_observer.h @@ -18,7 +18,7 @@ #include -#include "account_delegate.h" +#include "account/account_delegate.h" #include "executor_pool.h" namespace OHOS { diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp index ac38e8a7..f7642bfa 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp @@ -33,7 +33,7 @@ #include "communication_provider.h" #include "communicator_context.h" #include "config_factory.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "db_info_handle_impl.h" #include "device_manager_adapter.h" #include "device_matrix.h" @@ -51,6 +51,8 @@ #include "mem_mgr_proxy.h" #include "metadata/appid_meta_data.h" #include "metadata/meta_data_manager.h" +#include "network/network_delegate.h" +#include "metadata/store_meta_data.h" #include "permission_validator.h" #include "permit_delegate.h" #include "process_communicator_impl.h" @@ -78,9 +80,9 @@ using namespace OHOS::Security::AccessToken; using KvStoreDelegateManager = DistributedDB::KvStoreDelegateManager; using SecretKeyMeta = DistributedData::SecretKeyMetaData; using DmAdapter = DistributedData::DeviceManagerAdapter; -constexpr const char *EXTENSION_BACKUP = "backup"; -constexpr const char *EXTENSION_RESTORE = "restore"; -constexpr const char *CLONE_KEY_ALIAS = "distributed_db_backup_key"; +constexpr const char* EXTENSION_BACKUP = "backup"; +constexpr const char* EXTENSION_RESTORE = "restore"; +constexpr const char* CLONE_KEY_ALIAS = "distributed_db_backup_key"; REGISTER_SYSTEM_ABILITY_BY_ID(KvStoreDataService, DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID, true); @@ -89,8 +91,10 @@ constexpr int MAX_DOWNLOAD_ASSETS_COUNT = 50; constexpr int MAX_DOWNLOAD_TASK = 5; constexpr int KEY_SIZE = 32; constexpr int AES_256_NONCE_SIZE = 32; +constexpr int MAX_CLIENT_DEATH_OBSERVER_SIZE = 16; -KvStoreDataService::KvStoreDataService(bool runOnCreate) : SystemAbility(runOnCreate), clients_() +KvStoreDataService::KvStoreDataService(bool runOnCreate) + : SystemAbility(runOnCreate), clients_() { ZLOGI("begin."); } @@ -136,18 +140,18 @@ void KvStoreDataService::Initialize() DmAdapter::GetInstance().StartWatchDeviceChange(deviceInnerListener_.get(), { "innerListener" }); CommunicatorContext::GetInstance().RegSessionListener(deviceInnerListener_.get()); auto translateCall = [](const std::string &oriDevId, const DistributedDB::StoreInfo &info) { - StoreMetaData meta; + StoreMetaMapping storeMetaMapping; AppIDMetaData appIdMeta; MetaDataManager::GetInstance().LoadMeta(info.appId, appIdMeta, true); - meta.bundleName = appIdMeta.bundleName; - meta.storeId = info.storeId; - meta.user = info.userId; - meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true); + storeMetaMapping.bundleName = appIdMeta.bundleName; + storeMetaMapping.storeId = info.storeId; + storeMetaMapping.user = info.userId; + storeMetaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + MetaDataManager::GetInstance().LoadMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); std::string uuid; - if (OHOS::Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(meta.tokenId) == + if (OHOS::Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(storeMetaMapping.tokenId) == OHOS::Security::AccessToken::TOKEN_HAP) { - uuid = DmAdapter::GetInstance().CalcClientUuid(meta.appId, oriDevId); + uuid = DmAdapter::GetInstance().CalcClientUuid(storeMetaMapping.appId, oriDevId); } else { uuid = DmAdapter::GetInstance().CalcClientUuid(" ", oriDevId); } @@ -202,7 +206,8 @@ void KvStoreDataService::LoadFeatures() } /* RegisterClientDeathObserver */ -Status KvStoreDataService::RegisterClientDeathObserver(const AppId &appId, sptr observer) +Status KvStoreDataService::RegisterClientDeathObserver(const AppId &appId, sptr observer, + const std::string &featureName) { ZLOGD("begin."); KVSTORE_ACCOUNT_EVENT_PROCESSING_CHECKER(Status::SYSTEM_ACCOUNT_EVENT_PROCESSING); @@ -222,18 +227,51 @@ Status KvStoreDataService::RegisterClientDeathObserver(const AppId &appId, sptr< } auto pid = IPCSkeleton::GetCallingPid(); clients_.Compute(info.tokenId, - [&appId, &info, pid, this, obs = std::move(observer)](const auto tokenId, auto &clients) { - auto res = clients.try_emplace(pid, appId, *this, std::move(obs)); - ZLOGI("bundleName:%{public}s, uid:%{public}d, pid:%{public}d, inserted:%{public}s.", appId.appId.c_str(), - info.uid, pid, res.second ? "success" : "failed"); + [&appId, &info, pid, this, obs = std::move(observer), featureName](const auto tokenId, auto &clients) { + auto it = clients.find(pid); + if (it == clients.end()) { + auto res = clients.try_emplace(pid, appId, *this, std::move(obs), featureName); + ZLOGI("bundle:%{public}s, feature:%{public}s, uid:%{public}d, pid:%{public}d, emplace:%{public}s.", + appId.appId.c_str(), featureName.c_str(), info.uid, pid, res.second ? "success" : "failed"); + } else { + auto res = it->second.Insert(obs, featureName); + ZLOGI("bundle:%{public}s, feature:%{public}s, uid:%{public}d, pid:%{public}d, inserted:%{public}s.", + appId.appId.c_str(), featureName.c_str(), info.uid, pid, res ? "success" : "failed"); + } return !clients.empty(); }); return Status::SUCCESS; } +int32_t KvStoreDataService::Exit(const std::string &featureName) +{ + ZLOGI("FeatureExit:%{public}s", featureName.c_str()); + auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto pid = IPCSkeleton::GetCallingPid(); + std::string bundleName; + KvStoreClientDeathObserverImpl impl(*this); + bool removed = false; + clients_.ComputeIfPresent(tokenId, [pid, &featureName, &bundleName, &impl, &removed](auto &, auto &value) { + auto it = value.find(pid); + if (it == value.end()) { + return !value.empty(); + } + bundleName = it->second.GetAppId(); + removed = it->second.Delete(featureName); + if (it->second.Empty()) { + impl = std::move(it->second); + value.erase(it); + } + return !value.empty(); + }); + auto [exist, feature] = features_.Find(featureName); + if (removed && exist && feature != nullptr) { + feature->OnFeatureExit(IPCSkeleton::GetCallingUid(), pid, tokenId, bundleName); + } + return Status::SUCCESS; +} Status KvStoreDataService::AppExit(pid_t uid, pid_t pid, uint32_t token, const AppId &appId) { - ZLOGI("AppExit"); // memory of parameter appId locates in a member of clientDeathObserverMap_ and will be freed after // clientDeathObserverMap_ erase, so we have to take a copy if we want to use this parameter after erase operation. AppId appIdTmp = appId; @@ -297,6 +335,7 @@ void KvStoreDataService::OnStart() AccountDelegate::GetInstance()->RegisterHashFunc(Crypto::Sha256); DmAdapter::GetInstance().Init(executors_); AutoCache::GetInstance().Bind(executors_); + NetworkDelegate::GetInstance()->BindExecutor(executors_); static constexpr int32_t RETRY_TIMES = 50; static constexpr int32_t RETRY_INTERVAL = 500 * 1000; // unit is ms for (BlockInteger retry(RETRY_INTERVAL); retry < RETRY_TIMES; ++retry) { @@ -318,17 +357,20 @@ void KvStoreDataService::OnStart() } AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID); AddSystemAbilityListener(MEMORY_MANAGER_SA_ID); + AddSystemAbilityListener(COMM_NET_CONN_MANAGER_SYS_ABILITY_ID); + AddSystemAbilityListener(SUBSYS_ACCOUNT_SYS_ABILITY_ID_BEGIN); + AddSystemAbilityListener(CONCURRENT_TASK_SERVICE_ID); RegisterStoreInfo(); - Handler handlerStoreInfo = - std::bind(&KvStoreDataService::DumpStoreInfo, this, std::placeholders::_1, std::placeholders::_2); + Handler handlerStoreInfo = std::bind(&KvStoreDataService::DumpStoreInfo, this, std::placeholders::_1, + std::placeholders::_2); DumpManager::GetInstance().AddHandler("STORE_INFO", uintptr_t(this), handlerStoreInfo); RegisterUserInfo(); - Handler handlerUserInfo = - std::bind(&KvStoreDataService::DumpUserInfo, this, std::placeholders::_1, std::placeholders::_2); + Handler handlerUserInfo = std::bind(&KvStoreDataService::DumpUserInfo, this, std::placeholders::_1, + std::placeholders::_2); DumpManager::GetInstance().AddHandler("USER_INFO", uintptr_t(this), handlerUserInfo); RegisterBundleInfo(); - Handler handlerBundleInfo = - std::bind(&KvStoreDataService::DumpBundleInfo, this, std::placeholders::_1, std::placeholders::_2); + Handler handlerBundleInfo = std::bind(&KvStoreDataService::DumpBundleInfo, this, std::placeholders::_1, + std::placeholders::_2); DumpManager::GetInstance().AddHandler("BUNDLE_INFO", uintptr_t(this), handlerBundleInfo); StartService(); } @@ -345,6 +387,8 @@ void KvStoreDataService::LoadConfigs() Bootstrap::GetInstance().LoadBackup(executors_); Bootstrap::GetInstance().LoadCloud(); Bootstrap::GetInstance().LoadAppIdMappings(); + Bootstrap::GetInstance().LoadDeviceSyncAppWhiteLists(); + Bootstrap::GetInstance().LoadSyncTrustedApp(); } void KvStoreDataService::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId) @@ -352,11 +396,15 @@ void KvStoreDataService::OnAddSystemAbility(int32_t systemAbilityId, const std:: ZLOGI("add system abilityid:%{public}d", systemAbilityId); (void)deviceId; if (systemAbilityId == COMMON_EVENT_SERVICE_ID) { - AccountDelegate::GetInstance()->SubscribeAccountEvent(); Installer::GetInstance().Init(this, executors_); ScreenManager::GetInstance()->SubscribeScreenEvent(); + } else if (systemAbilityId == SUBSYS_ACCOUNT_SYS_ABILITY_ID_BEGIN) { + AccountDelegate::GetInstance()->SubscribeAccountEvent(); } else if (systemAbilityId == MEMORY_MANAGER_SA_ID) { - Memory::MemMgrClient::GetInstance().NotifyProcessStatus(getpid(), 1, 1, DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); + Memory::MemMgrClient::GetInstance().NotifyProcessStatus(getpid(), 1, 1, + DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); + } else if (systemAbilityId == COMM_NET_CONN_MANAGER_SYS_ABILITY_ID) { + NetworkDelegate::GetInstance()->RegOnNetworkChange(); } return; } @@ -365,10 +413,12 @@ void KvStoreDataService::OnRemoveSystemAbility(int32_t systemAbilityId, const st { ZLOGI("remove system abilityid:%{public}d", systemAbilityId); (void)deviceId; + if (systemAbilityId == SUBSYS_ACCOUNT_SYS_ABILITY_ID_BEGIN) { + AccountDelegate::GetInstance()->UnsubscribeAccountEvent(); + } if (systemAbilityId != COMMON_EVENT_SERVICE_ID) { return; } - AccountDelegate::GetInstance()->UnsubscribeAccountEvent(); ScreenManager::GetInstance()->UnsubscribeScreenEvent(); Installer::GetInstance().UnsubscribeEvent(); } @@ -434,12 +484,14 @@ bool KvStoreDataService::WriteBackupInfo(const std::string &content, const std:: FILE *fp = fopen(backupPath.c_str(), "w"); if (!fp) { - ZLOGE("Secret key backup file fopen failed, path: %{public}s, errno: %{public}d", backupPath.c_str(), errno); + ZLOGE("Secret key backup file fopen failed, path: %{public}s, errno: %{public}d", + Anonymous::Change(backupPath).c_str(), errno); return false; } size_t ret = fwrite(content.c_str(), 1, content.length(), fp); if (ret != content.length()) { - ZLOGE("Secret key backup file fwrite failed, path: %{public}s, errno: %{public}d", backupPath.c_str(), errno); + ZLOGE("Secret key backup file fwrite failed, path: %{public}s, errno: %{public}d", + Anonymous::Change(backupPath).c_str(), errno); (void)fclose(fp); return false; } @@ -453,7 +505,8 @@ bool KvStoreDataService::WriteBackupInfo(const std::string &content, const std:: int32_t KvStoreDataService::OnBackup(MessageParcel &data, MessageParcel &reply) { CloneBackupInfo backupInfo; - if (!backupInfo.Unmarshal(data.ReadString()) || backupInfo.bundleInfos.empty() || backupInfo.userId.empty()) { + if (!backupInfo.Unmarshal(data.ReadString()) || + backupInfo.bundleInfos.empty() || backupInfo.userId.empty()) { std::fill(backupInfo.encryptionInfo.symkey.begin(), backupInfo.encryptionInfo.symkey.end(), '\0'); return -1; } @@ -471,11 +524,7 @@ int32_t KvStoreDataService::OnBackup(MessageParcel &data, MessageParcel &reply) return -1; } - std::string content; - if (!GetSecretKeyBackup(backupInfo.bundleInfos, backupInfo.userId, iv, content)) { - DeleteCloneKey(); - return -1; - }; + auto content = GetSecretKeyBackup(backupInfo.bundleInfos, backupInfo.userId, iv); DeleteCloneKey(); std::string backupPath = DirectoryManager::GetInstance().GetClonePath(backupInfo.userId); @@ -506,13 +555,14 @@ std::vector KvStoreDataService::ReEncryptKey(const std::string &key, Se if (!MetaDataManager::GetInstance().LoadMeta(key, secretKeyMeta, true)) { return {}; }; - std::vector password; - if (!CryptoManager::GetInstance().Decrypt(metaData, secretKeyMeta, password)) { + CryptoManager::CryptoParams decryptParams = { .area = secretKeyMeta.area, .userId = metaData.user, + .nonce = secretKeyMeta.nonce }; + auto password = CryptoManager::GetInstance().Decrypt(secretKeyMeta.sKey, decryptParams); + if (password.empty()) { return {}; - }; - + } auto cloneKeyAlias = std::vector(CLONE_KEY_ALIAS, CLONE_KEY_ALIAS + strlen(CLONE_KEY_ALIAS)); - CryptoManager::EncryptParams encryptParams = { .keyAlias = cloneKeyAlias, .nonce = iv }; + CryptoManager::CryptoParams encryptParams = { .keyAlias = cloneKeyAlias, .nonce = iv }; auto reEncryptedKey = CryptoManager::GetInstance().Encrypt(password, encryptParams); password.assign(password.size(), 0); if (reEncryptedKey.size() == 0) { @@ -521,12 +571,12 @@ std::vector KvStoreDataService::ReEncryptKey(const std::string &key, Se return reEncryptedKey; } -bool KvStoreDataService::GetSecretKeyBackup(const std::vector &bundleInfos, - const std::string &userId, const std::vector &iv, std::string &content) +std::string KvStoreDataService::GetSecretKeyBackup(const std::vector &bundleInfos, + const std::string &userId, const std::vector &iv) { SecretKeyBackupData backupInfos; std::string deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - for (const auto &bundleInfo : bundleInfos) { + for (const auto& bundleInfo : bundleInfos) { std::string metaPrefix = StoreMetaData::GetKey({ deviceId, userId, "default", bundleInfo.bundleName }); std::vector StoreMetas; if (!MetaDataManager::GetInstance().LoadMeta(metaPrefix, StoreMetas, true)) { @@ -554,8 +604,7 @@ bool KvStoreDataService::GetSecretKeyBackup(const std::vector &iv) { + auto sKey = DistributedData::Base64::Decode(item.sKey); + auto cloneKeyAlias = std::vector(CLONE_KEY_ALIAS, CLONE_KEY_ALIAS + strlen(CLONE_KEY_ALIAS)); + CryptoManager::CryptoParams decryptParams = { .keyAlias = cloneKeyAlias, .nonce = iv }; + auto rawKey = CryptoManager::GetInstance().Decrypt(sKey, decryptParams); + if (rawKey.empty()) { + ZLOGE("Decrypt failed, bundleName:%{public}s, storeName:%{public}s, storeType:%{public}d", + item.bundleName.c_str(), Anonymous::Change(item.dbName).c_str(), item.storeType); + sKey.assign(sKey.size(), 0); + rawKey.assign(rawKey.size(), 0); + return false; + } + StoreMetaData metaData; metaData.bundleName = item.bundleName; metaData.storeId = item.dbName; metaData.user = item.user == "0" ? "0" : userId; metaData.instanceId = item.instanceId; - auto sKey = DistributedData::Base64::Decode(item.sKey); - std::vector rawKey; - auto cloneKeyAlias = std::vector(CLONE_KEY_ALIAS, CLONE_KEY_ALIAS + strlen(CLONE_KEY_ALIAS)); - CryptoManager::EncryptParams encryptParams = { .keyAlias = cloneKeyAlias, .nonce = iv }; - if (!CryptoManager::GetInstance().Decrypt(sKey, rawKey, encryptParams)) { - ZLOGE("Decrypt failed, bundleName:%{public}s, storeName:%{public}s, storeType:%{public}d", + SecretKeyMetaData secretKey; + CryptoManager::CryptoParams encryptParams = { .area = item.area, .userId = metaData.user }; + secretKey.sKey = CryptoManager::GetInstance().Encrypt(rawKey, encryptParams); + if (secretKey.sKey.empty()) { + ZLOGE("Encrypt failed, bundleName:%{public}s, storeName:%{public}s, storeType:%{public}d", item.bundleName.c_str(), Anonymous::Change(item.dbName).c_str(), item.storeType); sKey.assign(sKey.size(), 0); rawKey.assign(rawKey.size(), 0); - return false; } - SecretKeyMetaData secretKey; secretKey.storeType = item.storeType; - if (item.area < 0) { - secretKey.sKey = CryptoManager::GetInstance().Encrypt(rawKey, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - } else { - secretKey.sKey = CryptoManager::GetInstance().Encrypt(rawKey, item.area, userId); - secretKey.area = item.area; - } + secretKey.nonce = encryptParams.nonce; + secretKey.area = item.area; secretKey.time = { item.time.begin(), item.time.end() }; + sKey.assign(sKey.size(), 0); rawKey.assign(rawKey.size(), 0); return MetaDataManager::GetInstance().SaveMeta(metaData.GetCloneSecretKey(), secretKey, true); @@ -689,8 +744,8 @@ void KvStoreDataService::StartService() ZLOGI("Start distributedata Success, Publish ret: %{public}d", static_cast(ret)); } -void KvStoreDataService::OnStoreMetaChanged(const std::vector &key, const std::vector &value, - CHANGE_FLAG flag) +void KvStoreDataService::OnStoreMetaChanged( + const std::vector &key, const std::vector &value, CHANGE_FLAG flag) { if (flag != CHANGE_FLAG::UPDATE) { return; @@ -718,19 +773,18 @@ void KvStoreDataService::OnStop() } KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreClientDeathObserverImpl(const AppId &appId, - KvStoreDataService &service, sptr observer) - : appId_(appId), dataService_(service), observerProxy_(std::move(observer)), - deathRecipient_(new KvStoreDeathRecipient(*this)) + KvStoreDataService &service, sptr observer, const std::string &featureName) + : appId_(appId), dataService_(service), deathRecipient_(new KvStoreDeathRecipient(*this)) { ZLOGD("KvStoreClientDeathObserverImpl"); uid_ = IPCSkeleton::GetCallingUid(); pid_ = IPCSkeleton::GetCallingPid(); token_ = IPCSkeleton::GetCallingTokenID(); - if (observerProxy_ != nullptr) { - ZLOGI("add death recipient"); - observerProxy_->AddDeathRecipient(deathRecipient_); + if (observer != nullptr) { + observer->AddDeathRecipient(deathRecipient_); + observerProxy_.insert_or_assign(featureName, std::move(observer)); } else { - ZLOGW("observerProxy_ is nullptr"); + ZLOGW("observer is nullptr"); } } KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreClientDeathObserverImpl(KvStoreDataService &service) @@ -760,10 +814,12 @@ KvStoreDataService::KvStoreClientDeathObserverImpl &KvStoreDataService::KvStoreC KvStoreDataService::KvStoreClientDeathObserverImpl::~KvStoreClientDeathObserverImpl() { - ZLOGI("~KvStoreClientDeathObserverImpl"); - if (deathRecipient_ != nullptr && observerProxy_ != nullptr) { - ZLOGI("remove death recipient"); - observerProxy_->RemoveDeathRecipient(deathRecipient_); + if (deathRecipient_ != nullptr && !observerProxy_.empty()) { + for (auto &[key, value] : observerProxy_) { + if (value != nullptr) { + value->RemoveDeathRecipient(deathRecipient_); + } + } } if (uid_ == INVALID_UID || pid_ == INVALID_PID || token_ == INVALID_TOKEN || !appId_.IsValid()) { return; @@ -793,11 +849,41 @@ void KvStoreDataService::KvStoreClientDeathObserverImpl::Reset() appId_.appId = ""; } +bool KvStoreDataService::KvStoreClientDeathObserverImpl::Insert(sptr observer, + const std::string &featureName) +{ + if (observer != nullptr && observerProxy_.size() < MAX_CLIENT_DEATH_OBSERVER_SIZE && + observerProxy_.insert({featureName, observer}).second) { + observer->AddDeathRecipient(deathRecipient_); + return true; + } + return false; +} + +bool KvStoreDataService::KvStoreClientDeathObserverImpl::Delete(const std::string &featureName) +{ + auto it = observerProxy_.find(featureName); + if (it != observerProxy_.end() && it->second != nullptr) { + it->second->RemoveDeathRecipient(deathRecipient_); + } + return observerProxy_.erase(featureName) != 0; +} + +std::string KvStoreDataService::KvStoreClientDeathObserverImpl::GetAppId() +{ + return appId_; +} + +bool KvStoreDataService::KvStoreClientDeathObserverImpl::Empty() +{ + return observerProxy_.empty(); +} + KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreDeathRecipient::KvStoreDeathRecipient( KvStoreClientDeathObserverImpl &kvStoreClientDeathObserverImpl) : kvStoreClientDeathObserverImpl_(kvStoreClientDeathObserverImpl) { - ZLOGI("KvStore Client Death Observer"); + ZLOGD("KvStore Client Death Observer"); } KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreDeathRecipient::~KvStoreDeathRecipient() @@ -808,9 +894,10 @@ KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreDeathRecipient::~KvSt void KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreDeathRecipient::OnRemoteDied( const wptr &remote) { - (void)remote; - ZLOGI("begin"); - kvStoreClientDeathObserverImpl_.NotifyClientDie(); + (void) remote; + if (!clientDead_.exchange(true)) { + kvStoreClientDeathObserverImpl_.NotifyClientDie(); + } } void KvStoreDataService::AccountEventChanged(const AccountEventInfo &eventInfo) @@ -822,13 +909,14 @@ void KvStoreDataService::AccountEventChanged(const AccountEventInfo &eventInfo) g_kvStoreAccountEventStatus = 1; // delete all kvstore meta belong to this user std::vector metaData; - MetaDataManager::GetInstance().LoadMeta(StoreMetaData::GetPrefix({ "" }), metaData, true); + MetaDataManager::GetInstance().LoadMeta(StoreMetaData::GetPrefix({""}), metaData, true); for (const auto &meta : metaData) { if (meta.user != eventInfo.userId) { continue; } - ZLOGI("bundleName:%{public}s, user:%{public}s", meta.bundleName.c_str(), meta.user.c_str()); - MetaDataManager::GetInstance().DelMeta(meta.GetKey()); + ZLOGI("StoreMetaData bundleName:%{public}s, user:%{public}s", meta.bundleName.c_str(), + meta.user.c_str()); + MetaDataManager::GetInstance().DelMeta(meta.GetKeyWithoutPath()); MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetKeyLocal(), true); MetaDataManager::GetInstance().DelMeta(meta.GetSecretKey(), true); @@ -839,8 +927,10 @@ void KvStoreDataService::AccountEventChanged(const AccountEventInfo &eventInfo) MetaDataManager::GetInstance().DelMeta(meta.GetDebugInfoKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetDfxInfoKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetCloneSecretKey(), true); - PermitDelegate::GetInstance().DelCache(meta.GetKey()); + MetaDataManager::GetInstance().DelMeta(StoreMetaMapping(meta).GetKey(), true); + PermitDelegate::GetInstance().DelCache(meta.GetKeyWithoutPath()); } + CheckerManager::GetInstance().ClearCache(); g_kvStoreAccountEventStatus = 0; break; } @@ -873,7 +963,7 @@ void KvStoreDataService::NotifyAccountEvent(const AccountEventInfo &eventInfo) AutoCache::GetInstance().CloseStore([&userIds](const StoreMetaData &meta) { if (userIds.count(atoi(meta.user.c_str())) == 0) { ZLOGW("Illegal use of database by user %{public}s, %{public}s:%{public}s", meta.user.c_str(), - meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); + meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); return true; } return false; @@ -904,13 +994,15 @@ void KvStoreDataService::InitSecurityAdapter(std::shared_ptr execu auto dbStatus = DistributedDB::RuntimeConfig::SetProcessSystemAPIAdapter(security_); ZLOGD("set distributed db system api adapter: %d.", static_cast(dbStatus)); - auto status = DmAdapter::GetInstance().StartWatchDeviceChange(security_.get(), { "security" }); + auto status = DmAdapter::GetInstance().StartWatchDeviceChange(security_.get(), {"security"}); if (status != Status::SUCCESS) { ZLOGD("security register device change failed, status:%d", static_cast(status)); } } -void KvStoreDataService::SetCompatibleIdentify(const AppDistributedKv::DeviceInfo &info) const {} +void KvStoreDataService::SetCompatibleIdentify(const AppDistributedKv::DeviceInfo &info) const +{ +} void KvStoreDataService::OnDeviceOnline(const AppDistributedKv::DeviceInfo &info) { @@ -958,8 +1050,9 @@ void KvStoreDataService::OnSessionReady(const AppDistributedKv::DeviceInfo &info int32_t KvStoreDataService::OnUninstall(const std::string &bundleName, int32_t user, int32_t index) { + CheckerManager::GetInstance().DeleteCache(bundleName, user, index); auto staticActs = FeatureSystem::GetInstance().GetStaticActs(); - staticActs.ForEachCopies([bundleName, user, index](const auto &, const std::shared_ptr &acts) { + staticActs.ForEachCopies([bundleName, user, index](const auto &, const std::shared_ptr& acts) { acts->OnAppUninstall(bundleName, user, index); return false; }); @@ -968,8 +1061,9 @@ int32_t KvStoreDataService::OnUninstall(const std::string &bundleName, int32_t u int32_t KvStoreDataService::OnUpdate(const std::string &bundleName, int32_t user, int32_t index) { + CheckerManager::GetInstance().DeleteCache(bundleName, user, index); auto staticActs = FeatureSystem::GetInstance().GetStaticActs(); - staticActs.ForEachCopies([bundleName, user, index](const auto &, const std::shared_ptr &acts) { + staticActs.ForEachCopies([bundleName, user, index](const auto &, const std::shared_ptr& acts) { acts->OnAppUpdate(bundleName, user, index); return false; }); @@ -978,8 +1072,9 @@ int32_t KvStoreDataService::OnUpdate(const std::string &bundleName, int32_t user int32_t KvStoreDataService::OnInstall(const std::string &bundleName, int32_t user, int32_t index) { + CheckerManager::GetInstance().DeleteCache(bundleName, user, index); auto staticActs = FeatureSystem::GetInstance().GetStaticActs(); - staticActs.ForEachCopies([bundleName, user, index](const auto &, const std::shared_ptr &acts) { + staticActs.ForEachCopies([bundleName, user, index](const auto &, const std::shared_ptr& acts) { acts->OnAppInstall(bundleName, user, index); return false; }); @@ -998,6 +1093,7 @@ int32_t KvStoreDataService::OnScreenUnlocked(int32_t user) int32_t KvStoreDataService::ClearAppStorage(const std::string &bundleName, int32_t userId, int32_t appIndex, int32_t tokenId) { + CheckerManager::GetInstance().DeleteCache(bundleName, userId, appIndex); auto callerToken = IPCSkeleton::GetCallingTokenID(); NativeTokenInfo nativeTokenInfo; if (AccessTokenKit::GetNativeTokenInfo(callerToken, nativeTokenInfo) != RET_SUCCESS || @@ -1025,9 +1121,9 @@ int32_t KvStoreDataService::ClearAppStorage(const std::string &bundleName, int32 for (auto &meta : metaData) { if (meta.instanceId == appIndex && !meta.appId.empty() && !meta.storeId.empty()) { - ZLOGI("data cleared bundleName:%{public}s, stordId:%{public}s, appIndex:%{public}d", bundleName.c_str(), - Anonymous::Change(meta.storeId).c_str(), appIndex); - MetaDataManager::GetInstance().DelMeta(meta.GetKey()); + ZLOGI("StoreMetaData data cleared bundleName:%{public}s, stordId:%{public}s, appIndex:%{public}d", + bundleName.c_str(), Anonymous::Change(meta.storeId).c_str(), appIndex); + MetaDataManager::GetInstance().DelMeta(meta.GetKeyWithoutPath()); MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetKeyLocal(), true); MetaDataManager::GetInstance().DelMeta(meta.GetSecretKey(), true); @@ -1037,7 +1133,8 @@ int32_t KvStoreDataService::ClearAppStorage(const std::string &bundleName, int32 MetaDataManager::GetInstance().DelMeta(meta.GetDebugInfoKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetDfxInfoKey(), true); MetaDataManager::GetInstance().DelMeta(meta.GetAutoLaunchKey(), true); - PermitDelegate::GetInstance().DelCache(meta.GetKey()); + MetaDataManager::GetInstance().DelMeta(StoreMetaMapping(meta).GetKey(), true); + PermitDelegate::GetInstance().DelCache(meta.GetKeyWithoutPath()); } } return SUCCESS; @@ -1116,58 +1213,25 @@ void KvStoreDataService::PrintfInfo(int fd, const std::vector &me } info.append(GetIndentation(indentation)) .append("--------------------------------------------------------------------------\n") - .append(GetIndentation(indentation)) - .append("StoreID : ") - .append(data.storeId) - .append("\n") - .append(GetIndentation(indentation)) - .append("UId : ") - .append(data.user) - .append("\n") - .append(GetIndentation(indentation)) - .append("BundleName : ") - .append(data.bundleName) - .append("\n") - .append(GetIndentation(indentation)) - .append("AppID : ") - .append(data.appId) - .append("\n") - .append(GetIndentation(indentation)) - .append("StorePath : ") - .append(data.dataDir) - .append("\n") - .append(GetIndentation(indentation)) - .append("StoreType : ") - .append(std::to_string(data.storeType)) - .append("\n") - .append(GetIndentation(indentation)) - .append("encrypt : ") - .append(std::to_string(data.isEncrypt)) - .append("\n") - .append(GetIndentation(indentation)) - .append("autoSync : ") - .append(std::to_string(data.isAutoSync)) - .append("\n") - .append(GetIndentation(indentation)) - .append("schema : ") - .append(data.schema) - .append("\n") - .append(GetIndentation(indentation)) - .append("securityLevel : ") - .append(std::to_string(data.securityLevel)) - .append("\n") - .append(GetIndentation(indentation)) - .append("area : ") - .append(std::to_string(data.area)) - .append("\n") - .append(GetIndentation(indentation)) - .append("instanceID : ") - .append(std::to_string(data.instanceId)) - .append("\n") - .append(GetIndentation(indentation)) - .append("version : ") - .append(version) - .append("\n"); + .append(GetIndentation(indentation)).append("StoreID : ").append(data.storeId).append("\n") + .append(GetIndentation(indentation)).append("UId : ").append(data.user).append("\n") + .append(GetIndentation(indentation)).append("BundleName : ").append(data.bundleName).append("\n") + .append(GetIndentation(indentation)).append("AppID : ").append(data.appId).append("\n") + .append(GetIndentation(indentation)).append("StorePath : ").append(data.dataDir).append("\n") + .append(GetIndentation(indentation)).append("StoreType : ") + .append(std::to_string(data.storeType)).append("\n") + .append(GetIndentation(indentation)).append("encrypt : ") + .append(std::to_string(data.isEncrypt)).append("\n") + .append(GetIndentation(indentation)).append("autoSync : ") + .append(std::to_string(data.isAutoSync)).append("\n") + .append(GetIndentation(indentation)).append("schema : ").append(data.schema).append("\n") + .append(GetIndentation(indentation)).append("securityLevel : ") + .append(std::to_string(data.securityLevel)).append("\n") + .append(GetIndentation(indentation)).append("area : ") + .append(std::to_string(data.area)).append("\n") + .append(GetIndentation(indentation)).append("instanceID : ") + .append(std::to_string(data.instanceId)).append("\n") + .append(GetIndentation(indentation)).append("version : ").append(version).append("\n"); } dprintf(fd, "--------------------------------------StoreInfo-------------------------------------\n%s\n", info.c_str()); @@ -1316,9 +1380,12 @@ void KvStoreDataService::PrintfInfo(int fd, const std::map #include -#include "account_delegate.h" +#include "account/account_delegate.h" #include "clone/clone_backup_info.h" #include "clone/secret_key_backup_data.h" #include "dfx/reporter.h" @@ -92,12 +92,15 @@ public: void PrintfInfo(int fd, const std::map &datas); void DumpBundleInfo(int fd, std::map> ¶ms); - Status RegisterClientDeathObserver(const AppId &appId, sptr observer) override; + Status RegisterClientDeathObserver(const AppId &appId, sptr observer, + const std::string &featureName) override; sptr GetFeatureInterface(const std::string &name) override; int32_t ClearAppStorage(const std::string &bundleName, int32_t userId, int32_t appIndex, int32_t tokenId) override; + int32_t Exit(const std::string &featureName) override; + void OnDump() override; int Dump(int fd, const std::vector &args) override; @@ -134,18 +137,22 @@ public: int32_t OnBackup(MessageParcel &data, MessageParcel &reply); int32_t OnRestore(MessageParcel &data, MessageParcel &reply); bool WriteBackupInfo(const std::string &content, const std::string &backupPath); - bool GetSecretKeyBackup(const std::vector &bundleInfos, - const std::string &userId, const std::vector &iv, std::string &content); + std::string GetSecretKeyBackup(const std::vector &bundleInfos, + const std::string &userId, const std::vector &iv); private: void NotifyAccountEvent(const AccountEventInfo &eventInfo); class KvStoreClientDeathObserverImpl { public: - KvStoreClientDeathObserverImpl(const AppId &appId, KvStoreDataService &service, sptr observer); + KvStoreClientDeathObserverImpl(const AppId &appId, KvStoreDataService &service, sptr observer, + const std::string &featureName); explicit KvStoreClientDeathObserverImpl(KvStoreDataService &service); explicit KvStoreClientDeathObserverImpl(KvStoreClientDeathObserverImpl &&impl); KvStoreClientDeathObserverImpl &operator=(KvStoreClientDeathObserverImpl &&impl); - + bool Insert(sptr observer, const std::string &featureName); + bool Delete(const std::string &featureName); + bool Empty(); + std::string GetAppId(); virtual ~KvStoreClientDeathObserverImpl(); pid_t GetPid() const; @@ -159,6 +166,7 @@ private: private: KvStoreClientDeathObserverImpl &kvStoreClientDeathObserverImpl_; + std::atomic_bool clientDead_ = false; }; void NotifyClientDie(); void Reset(); @@ -167,7 +175,7 @@ private: uint32_t token_; AppId appId_; KvStoreDataService &dataService_; - sptr observerProxy_; + std::map> observerProxy_; sptr deathRecipient_; }; @@ -196,7 +204,7 @@ private: const std::vector &iv); bool ImportCloneKey(const std::string &keyStr); void DeleteCloneKey(); - + std::string GetBackupReplyCode(int replyCode, const std::string &info = ""); int32_t ReplyForRestore(MessageParcel &reply, int32_t result); @@ -221,5 +229,5 @@ private: static constexpr pid_t INVALID_PID = -1; static constexpr uint32_t INVALID_TOKEN = 0; }; -} // namespace OHOS::DistributedKv -#endif // KVSTORE_DATASERVICE_H \ No newline at end of file +} +#endif // KVSTORE_DATASERVICE_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service_stub.cpp b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service_stub.cpp index 4d0a55fa..3b74cbee 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service_stub.cpp @@ -37,7 +37,8 @@ int32_t KvStoreDataServiceStub::RegisterClientDeathObserverOnRemote(MessageParce if (kvStoreClientDeathObserverProxy == nullptr) { return -1; } - Status status = RegisterClientDeathObserver(appId, std::move(kvStoreClientDeathObserverProxy)); + std::string featureName = data.ReadString(); + Status status = RegisterClientDeathObserver(appId, std::move(kvStoreClientDeathObserverProxy), featureName); if (!reply.WriteInt32(static_cast(status))) { return -1; } @@ -67,8 +68,21 @@ int32_t KvStoreDataServiceStub::ClearAppStorageOnRemote(MessageParcel &data, Mes if (!ITypesUtil::Unmarshal(data, bundleName, userId, appIndex, tokenId)) { return -1; } - auto remoteObject = ClearAppStorage(bundleName, userId, appIndex, tokenId); - if (!ITypesUtil::Marshal(reply, remoteObject)) { + auto code = ClearAppStorage(bundleName, userId, appIndex, tokenId); + if (!ITypesUtil::Marshal(reply, code)) { + return -1; + } + return 0; +} + +int32_t KvStoreDataServiceStub::ExitOnRemote(MessageParcel &data, MessageParcel &reply) +{ + std::string featureName; + if (!ITypesUtil::Unmarshal(data, featureName)) { + return -1; + } + auto code = Exit(featureName); + if (!ITypesUtil::Marshal(reply, code)) { return -1; } return 0; diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service_stub.h b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service_stub.h index 08767f6d..2e776bd0 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service_stub.h +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service_stub.h @@ -26,6 +26,7 @@ private: int32_t GetFeatureInterfaceOnRemote(MessageParcel &data, MessageParcel &reply); int32_t RegisterClientDeathObserverOnRemote(MessageParcel &data, MessageParcel &reply); int32_t ClearAppStorageOnRemote(MessageParcel &data, MessageParcel &reply); + int32_t ExitOnRemote(MessageParcel &data, MessageParcel &reply); using RequestHandler = int32_t (KvStoreDataServiceStub::*)(MessageParcel &, MessageParcel &); using code = KvStoreDataServiceInterfaceCode; @@ -33,6 +34,7 @@ private: &KvStoreDataServiceStub::GetFeatureInterfaceOnRemote, &KvStoreDataServiceStub::RegisterClientDeathObserverOnRemote, &KvStoreDataServiceStub::ClearAppStorageOnRemote, + &KvStoreDataServiceStub::ExitOnRemote, }; }; } // namespace OHOS::DistributedKv diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.cpp b/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.cpp index 06b07a9c..1472fdd5 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.cpp @@ -20,11 +20,10 @@ #include #include -#include "account_delegate.h" +#include "account/account_delegate.h" #include "bootstrap.h" -#include "cloud/change_event.h" #include "communication_provider.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter.h" #include "device_matrix.h" #include "directory/directory_manager.h" @@ -144,11 +143,40 @@ void KvStoreMetaManager::InitMetaData() return; } + StoreMetaData data = InitStoreMetaData(); + StoreMetaDataLocal localData; + localData.isAutoSync = false; + localData.isBackup = false; + localData.isEncrypt = false; + localData.dataDir = metaDBDirectory_; + localData.schema = ""; + localData.isPublic = true; + MetaDataManager::GetInstance().SaveMeta(data.GetKeyWithoutPath(), data); + MetaDataManager::GetInstance().SaveMeta(data.GetKey(), data, true); + MetaDataManager::GetInstance().SaveMeta(data.GetKeyLocal(), localData, true); + std::string localUuid; + DeviceMetaData deviceMeta; + if (MetaDataManager::GetInstance().LoadMeta(deviceMeta.GetKey(), deviceMeta, true)) { + localUuid = deviceMeta.newUuid; + } else { + localUuid = DmAdapter::GetInstance().GetLocalDevice().uuid; + } + if (localUuid.empty()) { + ZLOGE("get uuid failed"); + return; + } + UpdateMetaData(localUuid); CheckMetaDeviceId(); + SetCloudSyncer(); + ZLOGI("end."); +} + +StoreMetaData KvStoreMetaManager::InitStoreMetaData() +{ + StoreMetaData data; auto uid = getuid(); auto tokenId = IPCSkeleton::GetCallingTokenID(); auto userId = AccountDelegate::GetInstance()->GetUserByToken(tokenId); - StoreMetaData data; data.appId = label_; data.appType = "default"; data.bundleName = label_; @@ -169,46 +197,89 @@ void KvStoreMetaManager::InitMetaData() data.securityLevel = SecurityLevel::S1; data.area = EL1; data.tokenId = tokenId; - StoreMetaDataLocal localData; - localData.isAutoSync = false; - localData.isBackup = false; - localData.isEncrypt = false; - localData.dataDir = metaDBDirectory_; - localData.schema = ""; - localData.isPublic = true; - if (!(MetaDataManager::GetInstance().SaveMeta(data.GetKey(), data) && - MetaDataManager::GetInstance().SaveMeta(data.GetKey(), data, true) && - MetaDataManager::GetInstance().SaveMeta(data.GetKeyLocal(), localData, true))) { - ZLOGE("save meta fail"); - } - UpdateMetaData(); - SetCloudSyncer(); - ZLOGI("end."); + return data; } -void KvStoreMetaManager::UpdateMetaData() +void KvStoreMetaManager::UpdateMetaData(const std::string &uuid) { VersionMetaData versionMeta; - if (!MetaDataManager::GetInstance().LoadMeta(versionMeta.GetKey(), versionMeta, true) - || versionMeta.version < META_VERSION) { + bool isExist = MetaDataManager::GetInstance().LoadMeta(versionMeta.GetKey(), versionMeta, true); + if (isExist && versionMeta.version == VersionMetaData::CURRENT_VERSION) { + return; + } + bool syncMetaUpdateNeeded = !isExist || versionMeta.version < VersionMetaData::UPDATE_SYNC_META_VERSION; + bool storeMetaUpgradeNeeded = !isExist || versionMeta.version < VersionMetaData::UPDATE_STORE_META_KEY_VERSION; + if (syncMetaUpdateNeeded) { std::vector metaDataList; - std::string prefix = StoreMetaData::GetPrefix({ DmAdapter::GetInstance().GetLocalDevice().uuid }); + std::string prefix = StoreMetaData::GetPrefix({ uuid }); MetaDataManager::GetInstance().LoadMeta(prefix, metaDataList); - for (auto metaData : metaDataList) { + std::vector keys; + for (const auto &metaData : metaDataList) { MetaDataManager::GetInstance().SaveMeta(metaData.GetKey(), metaData, true); if (CheckerManager::GetInstance().IsDistrust(Converter::ConvertToStoreInfo(metaData)) || - (metaData.storeType >= StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN - && metaData.storeType <= StoreMetaData::StoreType::STORE_RELATIONAL_END)) { - MetaDataManager::GetInstance().DelMeta(metaData.GetKey()); + (metaData.storeType >= StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN && + metaData.storeType <= StoreMetaData::StoreType::STORE_RELATIONAL_END)) { + keys.push_back(metaData.GetKey()); } } + MetaDataManager::GetInstance().DelMeta(keys); + versionMeta.version = VersionMetaData::UPDATE_SYNC_META_VERSION; + MetaDataManager::GetInstance().SaveMeta(versionMeta.GetKey(), versionMeta, true); } - if (versionMeta.version != VersionMetaData::CURRENT_VERSION) { - versionMeta.version = VersionMetaData::CURRENT_VERSION; + if (storeMetaUpgradeNeeded && UpgradeStoreMeta(uuid)) { + versionMeta.version = VersionMetaData::UPDATE_STORE_META_KEY_VERSION; MetaDataManager::GetInstance().SaveMeta(versionMeta.GetKey(), versionMeta, true); } } +// The metadata database is upgraded. The suffix is added to the path. +bool KvStoreMetaManager::UpgradeStoreMeta(const std::string &uuid) +{ + std::vector metaDataList; + std::string prefix = StoreMetaData::GetPrefix({ uuid }); + if (!MetaDataManager::GetInstance().LoadMeta(prefix, metaDataList, true)) { + ZLOGE("load meta failed"); + return false; + } + size_t batchSize = 100; // The batch quantity is 100. + return Constant::BatchProcess(metaDataList, batchSize, [](const auto &begin, const auto &end) { + std::vector entries; + std::vector deleteKeys; + auto size = static_cast(std::distance(begin, end)); + entries.reserve(size * 3); // Expand the entries size by 3 times. + deleteKeys.reserve(size * 4); // Expand the deleteKeys size by 4 times. + auto it = begin; + do { + auto &meta = *it; + StoreMetaDataLocal localMeta; + bool isExist = MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocalWithoutPath(), localMeta, true); + if (isExist) { + deleteKeys.push_back(meta.GetKeyLocalWithoutPath()); + entries.push_back({ meta.GetKeyLocal(), Serializable::Marshall(localMeta) }); + } + SecretKeyMetaData secretKeyMetaData; + isExist = MetaDataManager::GetInstance().LoadMeta(meta.GetSecretKeyWithoutPath(), secretKeyMetaData, true); + if (isExist) { + deleteKeys.push_back(meta.GetSecretKeyWithoutPath()); + entries.push_back({ meta.GetSecretKey(), Serializable::Marshall(secretKeyMetaData) }); + } + deleteKeys.push_back(meta.GetKeyWithoutPath()); + deleteKeys.push_back(meta.GetDebugInfoKeyWithoutPath()); + deleteKeys.push_back(meta.GetDfxInfoKeyWithoutPath()); + StoreMetaMapping storeMetaMapping(meta); + auto key = storeMetaMapping.GetKey(); + entries.push_back({ std::move(key), Serializable::Marshall(storeMetaMapping) }); + entries.push_back({ meta.GetKey(), Serializable::Marshall(meta) }); + } while (++it != end); + + if (MetaDataManager::GetInstance().SaveMeta(entries, true)) { + MetaDataManager::GetInstance().DelMeta(deleteKeys, true); + return true; + } + return false; + }); +} + void KvStoreMetaManager::InitMetaParameter() { ZLOGI("start."); @@ -581,11 +652,10 @@ void KvStoreMetaManager::CheckMetaDeviceId() if (deviceMeta.newUuid != localUuid) { UpdateStoreMetaData(localUuid, deviceMeta.newUuid); UpdateMetaDatas(localUuid, deviceMeta.newUuid); - deviceMeta.oldUuid = deviceMeta.newUuid; + ZLOGI("meta changed! cur uuid:%{public}s, old uuid:%{public}s", Anonymous::Change(localUuid).c_str(), + Anonymous::Change(deviceMeta.newUuid).c_str()); deviceMeta.newUuid = localUuid; MetaDataManager::GetInstance().SaveMeta(deviceMeta.GetKey(), deviceMeta, true); - ZLOGI("meta changed! curruuid:%{public}s, olduuid:%{public}s", - deviceMeta.newUuid.c_str(), deviceMeta.oldUuid.c_str()); } } @@ -601,10 +671,10 @@ void KvStoreMetaManager::UpdateStoreMetaData(const std::string &newUuid, const s MetaDataManager::GetInstance().DelMeta(oldMeta.GetKey(), true); StoreMetaData syncStoreMeta; - if (MetaDataManager::GetInstance().LoadMeta(oldMeta.GetKey(), syncStoreMeta)) { + if (MetaDataManager::GetInstance().LoadMeta(oldMeta.GetKeyWithoutPath(), syncStoreMeta)) { syncStoreMeta.deviceId = newUuid; - MetaDataManager::GetInstance().SaveMeta(storeMeta.GetKey(), syncStoreMeta); - MetaDataManager::GetInstance().DelMeta(oldMeta.GetKey()); + MetaDataManager::GetInstance().SaveMeta(storeMeta.GetKeyWithoutPath(), syncStoreMeta); + MetaDataManager::GetInstance().DelMeta(oldMeta.GetKeyWithoutPath()); } StrategyMeta strategyMeta; @@ -635,6 +705,21 @@ void KvStoreMetaManager::UpdateStoreMetaData(const std::string &newUuid, const s MetaDataManager::GetInstance().DelMeta(storeMeta.GetSecretKey(), true); MetaDataManager::GetInstance().DelMeta(storeMeta.GetCloneSecretKey(), true); } + MetaDataManager::GetInstance().DelMeta(oldMeta.GetDebugInfoKey(), true); + MetaDataManager::GetInstance().DelMeta(oldMeta.GetDfxInfoKey(), true); + } + UpdateStoreMetaMapping(newUuid, oldUuid); +} + +void KvStoreMetaManager::UpdateStoreMetaMapping(const std::string &newUuid, const std::string &oldUuid) +{ + std::vector storeMetaMappings; + MetaDataManager::GetInstance().LoadMeta(StoreMetaMapping::GetPrefix({ oldUuid }), storeMetaMappings, true); + for (auto &meta : storeMetaMappings) { + auto oldKey = meta.GetKey(); + meta.deviceId = newUuid; + MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true); + MetaDataManager::GetInstance().DelMeta(oldKey, true); } } diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.h b/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.h index f7b28e1c..df3abc66 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.h +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.h @@ -75,7 +75,9 @@ private: void InitMetaData(); - void UpdateMetaData(); + DistributedData::StoreMetaData InitStoreMetaData(); + + void UpdateMetaData(const std::string &uuid); void SubscribeMetaKvStore(); @@ -100,8 +102,12 @@ private: void UpdateStoreMetaData(const std::string &newUuid, const std::string &oldUuid); + void UpdateStoreMetaMapping(const std::string &newUuid, const std::string &oldUuid); + void UpdateMetaDatas(const std::string &newUuid, const std::string &oldUuid); + static bool UpgradeStoreMeta(const std::string &uuid); + static ExecutorPool::Task GetBackupTask( TaskQueue queue, std::shared_ptr executors, const NbDelegate store); @@ -137,7 +143,6 @@ private: std::mutex mutex_; std::shared_ptr executors_; TaskId delaySyncTaskId_ = ExecutorPool::INVALID_TASK_ID; - static constexpr int32_t META_VERSION = 4; static constexpr int32_t MAX_TASK_COUNT = 1; }; } // namespace DistributedKv diff --git a/datamgr_service/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.cpp b/datamgr_service/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.cpp index f52cde72..2399a18e 100644 --- a/datamgr_service/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.cpp @@ -19,6 +19,8 @@ #include #include "account/account_delegate.h" #include "auth_delegate.h" +#include "access_check/app_access_check_config_manager.h" +#include "app_id_mapping/app_id_mapping_config_manager.h" #include "device_manager_adapter.h" #include "kvstore_meta_manager.h" #include "log_print.h" @@ -37,6 +39,9 @@ using DmAdapter = DistributedData::DeviceManagerAdapter; using DBManager = DistributedDB::KvStoreDelegateManager; constexpr const int ALIGN_WIDTH = 8; constexpr const char *DEFAULT_USERID = "0"; +constexpr const char *DATA_OBJECT_STORE_ID = "distributedObject_"; +constexpr const char *UDMF_STORE_ID = "drag"; + std::shared_ptr RouteHeadHandlerImpl::Create(const ExtendInfo &info) { auto handler = std::make_shared(info); @@ -58,62 +63,86 @@ RouteHeadHandlerImpl::RouteHeadHandlerImpl(const ExtendInfo &info) void RouteHeadHandlerImpl::Init() { ZLOGD("begin"); - if (deviceId_.empty()) { + if (deviceId_.empty() || !DmAdapter::GetInstance().IsOHOSType(deviceId_)) { return; } if (userId_ != DEFAULT_USERID) { - if (!DmAdapter::GetInstance().IsOHOSType(deviceId_)) { + StoreMetaData metaData; + metaData.deviceId = deviceId_; + metaData.user = DEFAULT_USERID; + metaData.bundleName = appId_; + metaData.storeId = storeId_; + if (MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)) { userId_ = DEFAULT_USERID; - } else { - StoreMetaData metaData; - metaData.deviceId = deviceId_; - metaData.user = DEFAULT_USERID; - metaData.bundleName = appId_; - metaData.storeId = storeId_; - if (MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData)) { - userId_ = DEFAULT_USERID; - } } } + if (appId_ == Bootstrap::GetInstance().GetProcessLabel() && storeId_ != Bootstrap::GetInstance().GetMetaDBName()) { + int foregroundUserId = 0; + AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + userId_ = std::to_string(foregroundUserId); + } SessionPoint localPoint { DmAdapter::GetInstance().GetLocalDevice().uuid, - static_cast(atoi(userId_.c_str())), appId_, storeId_ }; + static_cast(atoi(userId_.c_str())), appId_, storeId_, + AccountDelegate::GetInstance()->GetCurrentAccountId() }; session_ = SessionManager::GetInstance().GetSession(localPoint, deviceId_); ZLOGD("valid session:appId:%{public}s, srcDevId:%{public}s, srcUser:%{public}u, trgDevId:%{public}s,", session_.appId.c_str(), Anonymous::Change(session_.sourceDeviceId).c_str(), session_.sourceUserId, Anonymous::Change(session_.targetDeviceId).c_str()); } +std::string RouteHeadHandlerImpl::GetTargetUserId() +{ + if (!session_.IsValid()) { + ZLOGE("session has no valid user to peer device, targetDeviceId:%{public}s", + Anonymous::Change(session_.targetDeviceId).c_str()); + return ""; + } + return std::to_string(session_.targetUserIds[0]); +} + DistributedDB::DBStatus RouteHeadHandlerImpl::GetHeadDataSize(uint32_t &headSize) { ZLOGD("begin"); headSize = 0; - if (appId_ == Bootstrap::GetInstance().GetProcessLabel()) { + if (appId_ == Bootstrap::GetInstance().GetProcessLabel() && storeId_ != UDMF_STORE_ID && + storeId_ != DATA_OBJECT_STORE_ID) { ZLOGI("meta data permitted"); return DistributedDB::OK; } - auto devInfo = DmAdapter::GetInstance().GetDeviceInfo(session_.targetDeviceId); - if (devInfo.osType != OH_OS_TYPE) { - ZLOGD("devicdId:%{public}s is not oh type", - Anonymous::Change(session_.targetDeviceId).c_str()); + if (!DmAdapter::GetInstance().IsOHOSType(session_.targetDeviceId)) { + ZLOGD("deviceId:%{public}s is not oh type", Anonymous::Change(session_.targetDeviceId).c_str()); + if (appId_.empty()) { + return DistributedDB::DB_ERROR; + } + if (!AppAccessCheckConfigManager::GetInstance().IsTrust( + AppIdMappingConfigManager::GetInstance().Convert(appId_))) { + return DistributedDB::DB_ERROR; + } return DistributedDB::OK; } bool flag = false; auto peerCap = UpgradeManager::GetInstance().GetCapability(session_.targetDeviceId, flag); if (!flag) { ZLOGI("get peer cap failed"); - return DistributedDB::DB_ERROR; - } - if (peerCap.version == CapMetaData::INVALID_VERSION) { + return (appId_ == Bootstrap::GetInstance().GetProcessLabel() && + (storeId_ == UDMF_STORE_ID || storeId_ == DATA_OBJECT_STORE_ID)) + ? DistributedDB::OK + : DistributedDB::DB_ERROR; + } + if ((appId_ == Bootstrap::GetInstance().GetProcessLabel() && storeId_ != Bootstrap::GetInstance().GetMetaDBName() + && peerCap.version < CapMetaData::UDMF_AND_OBJECT_VERSION) + || peerCap.version == CapMetaData::INVALID_VERSION) { // older versions ignore pack extend head - ZLOGI("ignore older version device"); + ZLOGI("ignore older version device, appId:%{public}s, version:%{public}d", appId_.c_str(), peerCap.version); return DistributedDB::OK; } if (!session_.IsValid()) { ZLOGI("no valid session to peer device"); return DistributedDB::DB_ERROR; } - size_t expectSize = sizeof(RouteHead) + sizeof(SessionDevicePair) + sizeof(SessionUserPair) - + session_.targetUserIds.size() * sizeof(int) + sizeof(SessionAppId) + session_.appId.size(); + size_t expectSize = sizeof(RouteHead) + sizeof(SessionDevicePair) + sizeof(SessionUserPair) + + session_.targetUserIds.size() * sizeof(int) + sizeof(SessionAppId) + session_.appId.size() + + sizeof(SessionStoreId) + session_.storeId.size() + sizeof(SessionAccountId) + session_.accountId.size(); // align message uint width headSize = GET_ALIGNED_SIZE(expectSize, ALIGN_WIDTH); @@ -127,6 +156,10 @@ DistributedDB::DBStatus RouteHeadHandlerImpl::GetHeadDataSize(uint32_t &headSize DistributedDB::DBStatus RouteHeadHandlerImpl::FillHeadData(uint8_t *data, uint32_t headSize, uint32_t totalLen) { ZLOGD("begin"); + if (data == nullptr) { + ZLOGE("data is nullptr"); + return DistributedDB::DB_ERROR; + } if (headSize != headSize_) { ZLOGI("size not match"); return DistributedDB::DB_ERROR; @@ -193,26 +226,82 @@ bool RouteHeadHandlerImpl::PackDataBody(uint8_t *data, uint32_t totalLen) } ptr += (sizeof(SessionUserPair) + session_.targetUserIds.size() * sizeof(int)); - SessionAppId *appPair = reinterpret_cast(ptr); - ptr += sizeof(SessionAppId); + const uint8_t *end = data + totalLen; + if (!PackAppId(&ptr, end) || !PackStoreId(&ptr, end) || !PackAccountId(&ptr, end)) { + return false; + } + return true; +} - uint8_t *end = data + totalLen; +bool RouteHeadHandlerImpl::PackAppId(uint8_t **data, const uint8_t *end) +{ + SessionAppId *appPair = reinterpret_cast(*data); uint32_t appIdSize = session_.appId.size(); - ret = memcpy_s(appPair->appId, end - ptr, session_.appId.data(), appIdSize); - if (ret != 0) { - ZLOGE("strcpy for app id failed, error:%{public}d", errno); + appPair->len = HostToNet(appIdSize); + *data += sizeof(SessionAppId); + auto ret = memcpy_s(appPair->appId, end - *data, session_.appId.c_str(), appIdSize); + if (ret != EOK) { + ZLOGE("memcpy for app id failed, ret is %{public}d, leftSize is %{public}u, appIdSize is %{public}u", + ret, static_cast(end - *data), appIdSize); return false; } - appPair->len = HostToNet(appIdSize); + *data += appIdSize; + return true; +} + +bool RouteHeadHandlerImpl::PackStoreId(uint8_t **data, const uint8_t *end) +{ + SessionStoreId *storePair = reinterpret_cast(*data); + uint32_t storeIdSize = session_.storeId.size(); + storePair->len = HostToNet(storeIdSize); + *data += sizeof(SessionStoreId); + auto ret = memcpy_s(storePair->storeId, end - *data, session_.storeId.data(), storeIdSize); + if (ret != EOK) { + ZLOGE("memcpy for store id failed, ret is %{public}d, leftSize is %{public}u, storeIdSize is %{public}u", + ret, static_cast(end - *data), storeIdSize); + return false; + } + *data += storeIdSize; return true; } -bool RouteHeadHandlerImpl::ParseHeadDataLen(const uint8_t *data, uint32_t totalLen, uint32_t &headSize) +bool RouteHeadHandlerImpl::PackAccountId(uint8_t **data, const uint8_t *end) +{ + SessionAccountId *accountPair = reinterpret_cast(*data); + uint32_t accountIdSize = session_.accountId.size(); + accountPair->len = HostToNet(accountIdSize); + *data += sizeof(SessionAccountId); + auto ret = memcpy_s(accountPair->accountId, end - *data, session_.accountId.data(), accountIdSize); + if (ret != EOK) { + ZLOGE("memcpy for account id failed, ret is %{public}d, leftSize is %{public}u, storeIdSize is %{public}u", + ret, static_cast(end - *data), accountIdSize); + return false; + } + return true; +} + +bool RouteHeadHandlerImpl::ParseHeadDataLen(const uint8_t *data, uint32_t totalLen, uint32_t &headSize, + const std::string &device) { if (data == nullptr) { ZLOGE("invalid input data, totalLen:%{public}d", totalLen); return false; } + if (!DmAdapter::GetInstance().IsOHOSType(device)) { + ZLOGI("other type device received. device:%{public}s", Anonymous::Change(device).c_str()); + return true; + } + + if (appId_ == Bootstrap::GetInstance().GetProcessLabel() && + (storeId_ == UDMF_STORE_ID || storeId_ == DATA_OBJECT_STORE_ID)) { + bool flag = false; + auto peerCap = UpgradeManager::GetInstance().GetCapability(device, flag); + if (flag && peerCap.version < CapMetaData::UDMF_AND_OBJECT_VERSION) { + ZLOGI("get peer cap success, peerCap's version is %{public}d, less than 3", peerCap.version); + return false; + } + } + RouteHead head = { 0 }; auto ret = UnPackDataHead(data, totalLen, head); headSize = ret ? sizeof(RouteHead) + head.dataLen : 0; @@ -222,6 +311,9 @@ bool RouteHeadHandlerImpl::ParseHeadDataLen(const uint8_t *data, uint32_t totalL std::string RouteHeadHandlerImpl::ParseStoreId(const std::string &deviceId, const std::string &label) { + if (!session_.storeId.empty()) { + return session_.storeId; + } std::vector metaData; auto prefix = StoreMetaData::GetPrefix({ deviceId }); if (!MetaDataManager::GetInstance().LoadMeta(prefix, metaData)) { @@ -255,11 +347,12 @@ bool RouteHeadHandlerImpl::ParseHeadDataUser(const uint8_t *data, uint32_t total metaData.deviceId = session_.targetDeviceId; metaData.user = DEFAULT_USERID; metaData.bundleName = session_.appId; - metaData.storeId = storeId; - if (!MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData)) { + metaData.storeId = std::move(storeId); + if (!MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)) { int foregroundUserId = 0; AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); - UserInfo userInfo = { .receiveUser = std::to_string(foregroundUserId) }; + UserInfo userInfo = { .receiveUser = std::to_string(foregroundUserId), + .sendUser = std::to_string(session_.sourceUserId) }; userInfos.emplace_back(userInfo); return true; } @@ -268,14 +361,22 @@ bool RouteHeadHandlerImpl::ParseHeadDataUser(const uint8_t *data, uint32_t total // flip the local and peer ends SessionPoint local { .deviceId = session_.targetDeviceId, .appId = session_.appId }; - SessionPoint peer { .deviceId = session_.sourceDeviceId, .userId = session_.sourceUserId, .appId = session_.appId }; + SessionPoint peer { .deviceId = session_.sourceDeviceId, .userId = session_.sourceUserId, .appId = session_.appId, + .accountId = session_.accountId }; ZLOGD("valid session:appId:%{public}s, srcDevId:%{public}s, srcUser:%{public}u, trgDevId:%{public}s,", session_.appId.c_str(), Anonymous::Change(session_.sourceDeviceId).c_str(), session_.sourceUserId, Anonymous::Change(session_.targetDeviceId).c_str()); + bool flag = false; + auto peerCap = UpgradeManager::GetInstance().GetCapability(session_.sourceDeviceId, flag); + if (!flag) { + ZLOGI("get peer cap failed, peer deviceId:%{public}s", Anonymous::Change(session_.sourceDeviceId).c_str()); + return false; + } + bool accountFlag = peerCap.version >= CapMetaData::ACCOUNT_VERSION; for (const auto &item : session_.targetUserIds) { local.userId = item; - if (SessionManager::GetInstance().CheckSession(local, peer)) { - UserInfo userInfo = { .receiveUser = std::to_string(item) }; + if (SessionManager::GetInstance().CheckSession(local, peer, accountFlag)) { + UserInfo userInfo = { .receiveUser = std::to_string(item), .sendUser = std::to_string(peer.userId) }; userInfos.emplace_back(userInfo); } } @@ -325,7 +426,7 @@ bool RouteHeadHandlerImpl::UnPackDataHead(const uint8_t *data, uint32_t totalLen bool RouteHeadHandlerImpl::UnPackDataBody(const uint8_t *data, uint32_t totalLen) { - const uint8_t *ptr = data; + uint8_t *ptr = const_cast(data); uint32_t leftSize = totalLen; if (leftSize < sizeof(SessionDevicePair)) { @@ -358,17 +459,71 @@ bool RouteHeadHandlerImpl::UnPackDataBody(const uint8_t *data, uint32_t totalLen ptr += userPairSize; leftSize -= userPairSize; + if (!UnPackAppId(&ptr, leftSize)) { + return false; + } + bool flag = false; + auto peerCap = UpgradeManager::GetInstance().GetCapability(session_.sourceDeviceId, flag); + if (!flag) { + ZLOGE("get peer cap failed, peer deviceId:%{public}s", Anonymous::Change(session_.sourceDeviceId).c_str()); + return false; + } + if (peerCap.version >= CapMetaData::ACCOUNT_VERSION && + (!UnPackStoreId(&ptr, leftSize) || !UnPackAccountId(&ptr, leftSize))) { + return false; + } + return true; +} + +bool RouteHeadHandlerImpl::UnPackAppId(uint8_t **data, uint32_t leftSize) +{ if (leftSize < sizeof(SessionAppId)) { - ZLOGE("failed to parse app id, leftSize : %{public}d", leftSize); + ZLOGE("failed to parse app id, leftSize:%{public}d.", leftSize); return false; } - const SessionAppId *appId = reinterpret_cast(ptr); + const SessionAppId *appId = reinterpret_cast(*data); auto appIdLen = NetToHost(appId->len); if (leftSize - sizeof(SessionAppId) < appIdLen) { ZLOGE("failed to parse app id, appIdLen:%{public}d, leftSize:%{public}d.", appIdLen, leftSize); return false; } - session_.appId.append(appId->appId, appIdLen); + session_.appId = std::string(appId->appId, appIdLen); + leftSize -= (sizeof(SessionAppId) + appIdLen); + *data += (sizeof(SessionAppId) + appIdLen); + return true; +} + +bool RouteHeadHandlerImpl::UnPackStoreId(uint8_t **data, uint32_t leftSize) +{ + if (leftSize < sizeof(SessionStoreId)) { + ZLOGE("failed to parse store id, leftSize:%{public}d.", leftSize); + return false; + } + const SessionStoreId *storeId = reinterpret_cast(*data); + auto storeIdLen = NetToHost(storeId->len); + if (leftSize - sizeof(SessionStoreId) < storeIdLen) { + ZLOGE("failed to parse store id, storeIdLen:%{public}d, leftSize:%{public}d.", storeIdLen, leftSize); + return false; + } + session_.storeId = std::string(storeId->storeId, storeIdLen); + leftSize -= (sizeof(SessionAppId) + storeIdLen); + *data += (sizeof(SessionAppId) + storeIdLen); + return true; +} + +bool RouteHeadHandlerImpl::UnPackAccountId(uint8_t **data, uint32_t leftSize) +{ + if (leftSize < sizeof(SessionAccountId)) { + ZLOGE("failed to parse account id, leftSize:%{public}d.", leftSize); + return false; + } + const SessionAccountId *accountId = reinterpret_cast(*data); + auto accountIdLen = NetToHost(accountId->len); + if (leftSize - sizeof(SessionAccountId) < accountIdLen) { + ZLOGE("failed to parse account id, accountIdLen:%{public}d, leftSize:%{public}d.", accountIdLen, leftSize); + return false; + } + session_.accountId = std::string(accountId->accountId, accountIdLen); return true; } } // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.h b/datamgr_service/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.h index f23360dd..85611780 100644 --- a/datamgr_service/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.h +++ b/datamgr_service/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.h @@ -53,6 +53,16 @@ struct SessionAppId { uint32_t len; char appId[0]; }; + +struct SessionStoreId { + uint32_t len; + char storeId[0]; +}; + +struct SessionAccountId { + uint32_t len; + char accountId[0]; +}; #pragma pack() class RouteHeadHandlerImpl : public DistributedData::RouteHeadHandler { @@ -61,20 +71,27 @@ public: explicit RouteHeadHandlerImpl(const ExtendInfo &info); DBStatus GetHeadDataSize(uint32_t &headSize) override; DBStatus FillHeadData(uint8_t *data, uint32_t headSize, uint32_t totalLen) override; - bool ParseHeadDataLen(const uint8_t *data, uint32_t totalLen, uint32_t &headSize) override; + bool ParseHeadDataLen(const uint8_t *data, uint32_t totalLen, uint32_t &headSize, + const std::string &device) override; bool ParseHeadDataUser(const uint8_t *data, uint32_t totalLen, const std::string &label, std::vector &userInfos) override; + std::string GetTargetUserId() override; private: void Init(); bool PackData(uint8_t *data, uint32_t totalLen); bool PackDataHead(uint8_t *data, uint32_t totalLen); bool PackDataBody(uint8_t *data, uint32_t totalLen); + bool PackAppId(uint8_t **data, const uint8_t *end); + bool PackStoreId(uint8_t **data, const uint8_t *end); + bool PackAccountId(uint8_t **data, const uint8_t *end); bool UnPackData(const uint8_t *data, uint32_t totalLen, uint32_t &unpackedSize); bool UnPackDataHead(const uint8_t *data, uint32_t totalLen, RouteHead &routeHead); bool UnPackDataBody(const uint8_t *data, uint32_t totalLen); + bool UnPackAppId(uint8_t **data, uint32_t leftSize); + bool UnPackStoreId(uint8_t **data, uint32_t leftSize); + bool UnPackAccountId(uint8_t **data, uint32_t leftSize); std::string ParseStoreId(const std::string &deviceId, const std::string &label); - std::string userId_; std::string appId_; std::string storeId_; diff --git a/datamgr_service/services/distributeddataservice/app/src/session_manager/session_manager.cpp b/datamgr_service/services/distributeddataservice/app/src/session_manager/session_manager.cpp index e13e4357..cb435f6f 100644 --- a/datamgr_service/services/distributeddataservice/app/src/session_manager/session_manager.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/session_manager/session_manager.cpp @@ -44,9 +44,11 @@ Session SessionManager::GetSession(const SessionPoint &local, const std::string ZLOGD("begin. peer device:%{public}s", Anonymous::Change(targetDeviceId).c_str()); Session session; session.appId = local.appId; + session.storeId = local.storeId; session.sourceUserId = local.userId; session.sourceDeviceId = local.deviceId; session.targetDeviceId = targetDeviceId; + session.accountId = local.accountId; auto users = UserDelegate::GetInstance().GetRemoteUserStatus(targetDeviceId); // system service if (local.userId == UserDelegate::SYSTEM_USER) { @@ -64,6 +66,8 @@ Session SessionManager::GetSession(const SessionPoint &local, const std::string aclParams.accCallee.userId = user.id; auto [isPermitted, isSameAccount] = AuthDelegate::GetInstance()->CheckAccess(local.userId, user.id, targetDeviceId, aclParams); + ZLOGD("targetDeviceId:%{public}s, user.id:%{public}d, isPermitted:%{public}d, isSameAccount: %{public}d", + Anonymous::Change(targetDeviceId).c_str(), user.id, isPermitted, isSameAccount); if (isPermitted) { auto it = std::find(session.targetUserIds.begin(), session.targetUserIds.end(), user.id); if (it == session.targetUserIds.end() && isSameAccount) { @@ -91,7 +95,7 @@ bool SessionManager::GetSendAuthParams(const SessionPoint &local, const std::str for (const auto &storeMeta : metaData) { if (storeMeta.appId == local.appId && storeMeta.storeId == local.storeId) { aclParams.accCaller.bundleName = storeMeta.bundleName; - aclParams.accCaller.accountId = AccountDelegate::GetInstance()->GetCurrentAccountId(); + aclParams.accCaller.accountId = local.accountId; aclParams.accCaller.userId = local.userId; aclParams.accCaller.networkId = DmAdapter::GetInstance().ToNetworkID(local.deviceId); @@ -106,13 +110,13 @@ bool SessionManager::GetSendAuthParams(const SessionPoint &local, const std::str return false; } -bool SessionManager::GetRecvAuthParams(const SessionPoint &local, const std::string &targetDeviceId, - AclParams &aclParams, int32_t peerUser) const +bool SessionManager::GetRecvAuthParams(const SessionPoint &local, const SessionPoint &peer, bool accountFlag, + AclParams &aclParams) const { std::vector metaData; - if (!MetaDataManager::GetInstance().LoadMeta(StoreMetaData::GetPrefix({ targetDeviceId }), metaData)) { - ZLOGE("load meta failed, deviceId:%{public}s, user:%{public}d", Anonymous::Change(targetDeviceId).c_str(), - peerUser); + if (!MetaDataManager::GetInstance().LoadMeta(StoreMetaData::GetPrefix({ peer.deviceId }), metaData)) { + ZLOGE("load meta failed, deviceId:%{public}s, user:%{public}d", Anonymous::Change(peer.deviceId).c_str(), + peer.userId); return false; } for (const auto &storeMeta : metaData) { @@ -123,28 +127,30 @@ bool SessionManager::GetRecvAuthParams(const SessionPoint &local, const std::str aclParams.accCaller.userId = local.userId; aclParams.accCaller.networkId = DmAdapter::GetInstance().ToNetworkID(local.deviceId); - aclParams.accCallee.accountId = accountId; - aclParams.accCallee.userId = peerUser; - aclParams.accCallee.networkId = DmAdapter::GetInstance().ToNetworkID(targetDeviceId); + aclParams.accCallee.accountId = accountFlag ? peer.accountId : accountId; + aclParams.accCallee.userId = peer.userId; + aclParams.accCallee.networkId = DmAdapter::GetInstance().ToNetworkID(peer.deviceId); aclParams.authType = storeMeta.authType; return true; } } ZLOGE("get params failed,appId:%{public}s,tarDevid:%{public}s,user:%{public}d,peer:%{public}d", - local.appId.c_str(), Anonymous::Change(targetDeviceId).c_str(), local.userId, peerUser); + local.appId.c_str(), Anonymous::Change(peer.deviceId).c_str(), local.userId, peer.userId); return false; } -bool SessionManager::CheckSession(const SessionPoint &local, const SessionPoint &peer) const +bool SessionManager::CheckSession(const SessionPoint &local, const SessionPoint &peer, bool accountFlag) const { AclParams aclParams; - if (!GetRecvAuthParams(local, peer.deviceId, aclParams, peer.userId)) { + if (!GetRecvAuthParams(local, peer, accountFlag, aclParams)) { ZLOGE("get recv auth params failed:%{public}s", Anonymous::Change(peer.deviceId).c_str()); return false; } auto [isPermitted, isSameAccount] = AuthDelegate::GetInstance()->CheckAccess(local.userId, peer.userId, peer.deviceId, aclParams); + ZLOGD("peer.deviceId:%{public}s, peer.userId:%{public}d, isPermitted:%{public}d, isSameAccount: %{public}d", + Anonymous::Change(peer.deviceId).c_str(), peer.userId, isPermitted, isSameAccount); if (isPermitted && local.userId != UserDelegate::SYSTEM_USER) { isPermitted = Account::GetInstance()->IsUserForeground(local.userId); } @@ -159,6 +165,8 @@ bool Session::Marshal(json &node) const ret = SetValue(node[GET_NAME(sourceUserId)], sourceUserId) && ret; ret = SetValue(node[GET_NAME(targetUserIds)], targetUserIds) && ret; ret = SetValue(node[GET_NAME(appId)], appId) && ret; + ret = SetValue(node[GET_NAME(storeId)], storeId) && ret; + ret = SetValue(node[GET_NAME(accountId)], accountId) && ret; return ret; } @@ -170,6 +178,8 @@ bool Session::Unmarshal(const json &node) ret = GetValue(node, GET_NAME(sourceUserId), sourceUserId) && ret; ret = GetValue(node, GET_NAME(targetUserIds), targetUserIds) && ret; ret = GetValue(node, GET_NAME(appId), appId) && ret; + ret = GetValue(node, GET_NAME(storeId), storeId) && ret; + ret = GetValue(node, GET_NAME(accountId), accountId) && ret; return ret; } } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/app/src/session_manager/session_manager.h b/datamgr_service/services/distributeddataservice/app/src/session_manager/session_manager.h index ca83970b..c41e30c2 100644 --- a/datamgr_service/services/distributeddataservice/app/src/session_manager/session_manager.h +++ b/datamgr_service/services/distributeddataservice/app/src/session_manager/session_manager.h @@ -30,6 +30,7 @@ struct SessionPoint { uint32_t userId; std::string appId; std::string storeId; + std::string accountId; }; class Session : public Serializable { @@ -39,6 +40,8 @@ public: uint32_t sourceUserId; std::vector targetUserIds; std::string appId; + std::string storeId; + std::string accountId; bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; inline bool IsValid() @@ -51,12 +54,12 @@ class SessionManager { public: static SessionManager &GetInstance(); Session GetSession(const SessionPoint &local, const std::string &targetDeviceId) const; - bool CheckSession(const SessionPoint &local, const SessionPoint &peer) const; + bool CheckSession(const SessionPoint &local, const SessionPoint &peer, bool accountFlag) const; private: bool GetSendAuthParams(const SessionPoint &local, const std::string &targetDeviceId, AclParams &aclParams) const; - bool GetRecvAuthParams(const SessionPoint &local, const std::string &targetDeviceId, - AclParams &aclParams, int peerUser) const; + bool GetRecvAuthParams(const SessionPoint &local, const SessionPoint &peer, bool accountFlag, + AclParams &aclParams) const; }; } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.cpp b/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.cpp index 4055f30f..7654c983 100644 --- a/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.cpp @@ -16,14 +16,10 @@ #include "upgrade_manager.h" -#include -#include "account_delegate.h" #include "device_manager_adapter.h" #include "log_print.h" #include "metadata/meta_data_manager.h" #include "utils/anonymous.h" -#include "utils/constant.h" -#include "app_id_mapping/app_id_mapping_config_manager.h" namespace OHOS::DistributedData { using namespace OHOS::DistributedKv; @@ -36,18 +32,42 @@ UpgradeManager &UpgradeManager::GetInstance() void UpgradeManager::Init(std::shared_ptr executors) { - if (executors_) { - return; + MetaDataManager::GetInstance().Subscribe( + CapMetaRow::KEY_PREFIX, [this](const std::string &key, const std::string &value, int32_t flag) -> auto { + CapMetaData capMeta; + if (value.empty()) { + MetaDataManager::GetInstance().LoadMeta(key, capMeta); + } else { + CapMetaData::Unmarshall(value, capMeta); + } + auto deviceId = CapMetaRow::GetDeviceId(key); + if (deviceId.empty()) { + ZLOGE("deviceId is empty, key:%{public}s, flag:%{public}d", Anonymous::Change(key).c_str(), flag); + return false; + } + if (deviceId == DmAdapter::GetInstance().GetLocalDevice().uuid) { + return true; + } + capMeta.deviceId = capMeta.deviceId.empty() ? deviceId : capMeta.deviceId; + ZLOGI("CapMetaData has change, deviceId:%{public}s, version:%{public}d, flag:%{public}d", + Anonymous::Change(capMeta.deviceId).c_str(), capMeta.version, flag); + if (flag == MetaDataManager::INSERT || flag == MetaDataManager::UPDATE) { + capabilities_.InsertOrAssign(capMeta.deviceId, capMeta); + } else if (flag == MetaDataManager::DELETE) { + capabilities_.Erase(capMeta.deviceId); + } + return true; + }); + if (executors != nullptr) { + executors_ = std::move(executors); + executors_->Execute(GetTask()); } - executors_ = std::move(executors); - executors_->Execute(GetTask()); } ExecutorPool::Task UpgradeManager::GetTask() { return [this] { - auto succ = InitLocalCapability(); - if (succ) { + if (InitLocalCapability() || executors_ == nullptr) { return; } executors_->Schedule(std::chrono::milliseconds(RETRY_INTERVAL), GetTask()); @@ -79,6 +99,7 @@ bool UpgradeManager::InitLocalCapability() auto localDeviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; CapMetaData capMetaData; capMetaData.version = CapMetaData::CURRENT_VERSION; + capMetaData.deviceId = localDeviceId; auto dbKey = CapMetaRow::GetKeyFor(localDeviceId); bool status = MetaDataManager::GetInstance().SaveMeta({ dbKey.begin(), dbKey.end() }, capMetaData); if (status) { diff --git a/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.h b/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.h index 411181e3..fd4ec20f 100644 --- a/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.h +++ b/datamgr_service/services/distributeddataservice/app/src/session_manager/upgrade_manager.h @@ -15,18 +15,13 @@ #ifndef DISTRIBUTEDDATAMGR_UPGRADE_MANAGER_H #define DISTRIBUTEDDATAMGR_UPGRADE_MANAGER_H -#include -#include "auth_delegate.h" #include "concurrent_map.h" -#include "kvstore_meta_manager.h" #include "metadata/capability_meta_data.h" #include "executor_pool.h" #include "types.h" -namespace OHOS::DistributedData { -using DistributedDB::KvStoreNbDelegate; -using OHOS::DistributedKv::KvStoreTuple; +namespace OHOS::DistributedData { class UpgradeManager { public: static UpgradeManager &GetInstance(); @@ -39,10 +34,6 @@ private: ExecutorPool::Task GetTask(); ConcurrentMap capabilities_ {}; std::shared_ptr executors_; - - static constexpr int32_t NO_ACCOUNT = 0; - static constexpr int32_t IDENTICAL_ACCOUNT = 1; - static constexpr const char *defaultAccountId = "ohosAnonymousUid"; }; } // namespace OHOS::DistributedData #endif // DISTRIBUTEDDATAMGR_UPGRADE_MANAGER_H diff --git a/datamgr_service/services/distributeddataservice/app/test/BUILD.gn b/datamgr_service/services/distributeddataservice/app/test/BUILD.gn index f3f91289..d79c567b 100644 --- a/datamgr_service/services/distributeddataservice/app/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/test/BUILD.gn @@ -19,12 +19,6 @@ module_output_path = "datamgr_service/datamgr_service/distributeddataservice" config("module_private_config") { visibility = [ ":*" ] include_dirs = [ - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/common", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/src", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_path}/interfaces/innerkits/distributeddata/include", "${data_service_path}/adapter/include/permission", "${data_service_path}/adapter/include/account", "${data_service_path}/adapter/include", @@ -41,9 +35,7 @@ config("module_private_config") { "${data_service_path}/app/src", "${data_service_path}/app/src/session_manager", "${data_service_path}/service/kvdb", - "${device_manager_path}/interfaces/inner_kits/native_cpp/include", - "//commonlibrary/c_utils/base/include", - "//utils/system/safwk/native/include", + "${data_service_path}/service/test/mock", "../include", "../src", "../src/security", @@ -52,7 +44,6 @@ config("module_private_config") { "../../service/backup/include", "../../../../interfaces/innerkits/distributeddata", "../../service/dumper/include", - "//third_party/json/single_include", "${data_service_path}/adapter/include/communicator", ] @@ -96,9 +87,22 @@ ohos_unittest("KvStoreDataServiceTest") { "${data_service_path}/app/src/session_manager/upgrade_manager.cpp", "${data_service_path}/app/src/task_manager.cpp", "${data_service_path}/app/test/unittest/kvstore_data_service_test.cpp", + "${data_service_path}/app/test/unittest/security_test.cpp", + "${data_service_path}/app/test/unittest/sensitive_test.cpp", "${data_service_path}/service/common/xcollie.cpp", ] + sanitize = { + ubsan = true + boundary_sanitize = true + integer_overflow = true + cfi_no_nvcall = true + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } + configs = [ ":module_private_config" ] external_deps = [ @@ -109,7 +113,9 @@ ohos_unittest("KvStoreDataServiceTest") { "common_event_service:cesfwk_innerkits", "dataclassification:data_transit_mgr", "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", "file_api:securitylabel", + "googletest:gtest_main", "hicollie:libhicollie", "hilog:libhilog", "hisysevent:libhisysevent", @@ -117,7 +123,9 @@ ohos_unittest("KvStoreDataServiceTest") { "hitrace:libhitracechain", "ipc:ipc_core", "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", "kv_store:distributeddb", + "kv_store:kvdb_inner_lite", "memmgr:memmgrclient", "safwk:system_ability_fwk", "samgr:samgr_proxy", @@ -133,7 +141,84 @@ ohos_unittest("KvStoreDataServiceTest") { deps = [ "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//third_party/googletest:gtest_main", + ] + part_name = "datamgr_service" +} + +ohos_unittest("KvStoreMetaManagerUpdateKeyTest") { + module_out_path = module_output_path + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } + sources = [ + "${data_service_path}/app/src/checker/bundle_checker.cpp", + "${data_service_path}/app/src/checker/system_checker.cpp", + "${data_service_path}/app/src/clone/clone_backup_info.cpp", + "${data_service_path}/app/src/clone/secret_key_backup_data.cpp", + "${data_service_path}/app/src/db_info_handle_impl.cpp", + "${data_service_path}/app/src/feature_stub_impl.cpp", + "${data_service_path}/app/src/installer/installer.cpp", + "${data_service_path}/app/src/installer/installer_impl.cpp", + "${data_service_path}/app/src/kvstore_account_observer.cpp", + "${data_service_path}/app/src/kvstore_data_service.cpp", + "${data_service_path}/app/src/kvstore_data_service_stub.cpp", + "${data_service_path}/app/src/kvstore_device_listener.cpp", + "${data_service_path}/app/src/kvstore_meta_manager.cpp", + "${data_service_path}/app/src/kvstore_screen_observer.cpp", + "${data_service_path}/app/src/security/security.cpp", + "${data_service_path}/app/src/security/sensitive.cpp", + "${data_service_path}/app/src/session_manager/route_head_handler_impl.cpp", + "${data_service_path}/app/src/session_manager/session_manager.cpp", + "${data_service_path}/app/src/session_manager/upgrade_manager.cpp", + "${data_service_path}/app/src/task_manager.cpp", + "${data_service_path}/app/test/unittest/kvstore_meta_manager_update_key_test.cpp", + "${data_service_path}/service/common/xcollie.cpp", + "${data_service_path}/service/test/mock/device_manager_adapter_mock.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:want", + "access_token:libaccesstoken_sdk", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "dataclassification:data_transit_mgr", + "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", + "file_api:securitylabel", + "googletest:gmock", + "googletest:gtest_main", + "hicollie:libhicollie", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "kv_store:kvdb_inner_lite", + "memmgr:memmgrclient", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + if (datamgr_service_power) { + external_deps += [ + "battery_manager:batterysrv_client", + "power_manager:powermgr_client", + ] + } + cflags = [ + "-fno-access-control", # Ignore Private Member Access Control + ] + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", ] part_name = "datamgr_service" } @@ -153,6 +238,7 @@ ohos_unittest("SessionManagerTest") { cfi = true cfi_cross_dso = true debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" } cflags_cc = [ "-DUT_TEST" ] @@ -160,15 +246,23 @@ ohos_unittest("SessionManagerTest") { external_deps = [ "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "access_token:libtoken_setproc", "c_utils:utils", "dataclassification:data_transit_mgr", "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", "file_api:securitylabel", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "ipc:ipc_core", + "json:nlohmann_json_static", + "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "kv_store:kvdb_inner_lite", "safwk:system_ability_fwk", "samgr:samgr_proxy", ] @@ -183,12 +277,9 @@ ohos_unittest("SessionManagerTest") { deps = [ "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/app/src/checker:distributeddata_checker", - "${kv_store_path}/interfaces/innerkits/distributeddatamgr:distributeddata_mgr", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/service:distributeddatasvc", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "${data_service_path}/service/test/mock:distributeddata_mock_static", ] part_name = "datamgr_service" @@ -233,16 +324,20 @@ ohos_unittest("KvStoreDataServiceClearTest") { "c_utils:utils", "dataclassification:data_transit_mgr", "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", "file_api:securitylabel", + "googletest:gtest_main", "hicollie:libhicollie", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", "hitrace:libhitracechain", "ipc:ipc_core", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", "kv_store:distributeddb", + "kv_store:kvdb_inner_lite", "memmgr:memmgrclient", "safwk:system_ability_fwk", "samgr:samgr_proxy", @@ -261,7 +356,6 @@ ohos_unittest("KvStoreDataServiceClearTest") { "${data_service_path}/app/src/installer:distributeddata_installer", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//third_party/googletest:gtest_main", ] part_name = "datamgr_service" @@ -298,6 +392,7 @@ ohos_unittest("FeatureStubImplTest") { "c_utils:utils", "dataclassification:data_transit_mgr", "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", "file_api:securitylabel", "googletest:gtest_main", "hilog:libhilog", @@ -329,6 +424,166 @@ ohos_unittest("FeatureStubImplTest") { part_name = "datamgr_service" } +ohos_unittest("UpgradeManagerTest") { + module_out_path = module_output_path + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + + include_dirs = [ + "${data_service_path}/app/src/session_manager", + "${data_service_path}/app/test/mock/capability", + "${data_service_path}/framework/include", + ] + + sources = [ + "${data_service_path}/app/test/mock/capability/metadata/meta_data_manager.cpp", + "${data_service_path}/app/test/mock/capability/device_manager_adapter.cpp", + "${data_service_path}/app/src/session_manager/upgrade_manager.cpp", + "${data_service_path}/framework/metadata/capability_meta_data.cpp", + "${data_service_path}/framework/serializable/serializable.cpp", + "${data_service_path}/framework/utils/anonymous.cpp", + "${data_service_path}/framework/utils/constant.cpp", + "${data_service_path}/app/test/unittest/upgrade_manager_test.cpp", + ] + + external_deps = [ + "c_utils:utils", + "googletest:gtest_main", + "hilog:libhilog", + "json:nlohmann_json_static", + "kv_store:distributeddata_inner", + ] + + part_name = "datamgr_service" +} + +ohos_unittest("RouteHeadHandlerImplTest") { + module_out_path = module_output_path + + include_dirs = [ + "${data_service_path}/adapter/include/permission", + "${data_service_path}/adapter/include/account", + "${data_service_path}/adapter/include", + "${data_service_path}/adapter/include/utils", + "${data_service_path}/framework/include", + "${data_service_path}/service/bootstrap/include", + "${data_service_path}/service/common", + "${data_service_path}/service/config/include", + "${data_service_path}/service/crypto/include", + "${data_service_path}/service/data_share/common", + "${data_service_path}/service/directory/include", + "${data_service_path}/service/permission/include", + "${data_service_path}/service/matrix/include", + "${data_service_path}/app/src", + "${data_service_path}/app/src/session_manager", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/test/mock", + "../include", + "../src", + "../src/security", + "unittest", + "../src/installer", + "../../service/backup/include", + "../../../../interfaces/innerkits/distributeddata", + "../../service/dumper/include", + "${data_service_path}/adapter/include/communicator", + ] + + sources = [ + "../src/kvstore_meta_manager.cpp", + "../src/session_manager/route_head_handler_impl.cpp", + "../src/session_manager/session_manager.cpp", + "../src/session_manager/upgrade_manager.cpp", + "unittest/route_head_handler_impl_test.cpp", + ] + + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } + + cflags_cc = [ "-DUT_TEST" ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "access_token:libtoken_setproc", + "c_utils:utils", + "dataclassification:data_transit_mgr", + "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", + "file_api:securitylabel", + "googletest:gmock", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "ipc:ipc_core", + "json:nlohmann_json_static", + "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + if (datamgr_service_power) { + external_deps += [ + "battery_manager:batterysrv_client", + "power_manager:powermgr_client", + ] + } + + deps = [ + "${data_service_path}/adapter/utils:distributeddata_utils", + "${data_service_path}/app/src/checker:distributeddata_checker", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "${data_service_path}/service/test/mock:distributeddata_mock_static", + ] + + cflags = [ + "-Werror", + "-Dprivate=public", + "-Dprotected=public", + ] + ldflags = [ "-Wl,--whole-archive" ] + defines = [ + "TEST_ON_DEVICE", + "OPENSSL_SUPPRESS_DEPRECATED", + ] + + part_name = "datamgr_service" +} + +ohos_unittest("BundleCheckerTest") { + module_out_path = module_output_path + sources = [ "unittest/bundle_checker_test.cpp" ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "c_utils:utils", + "googletest:gtest_main", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "openssl:libcrypto_shared", + ] + + deps = [ + "${data_service_path}/app/src/checker:distributeddata_checker", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + ] +} + ############################################################################### group("unittest") { @@ -336,24 +591,13 @@ group("unittest") { deps = [] deps += [ + ":BundleCheckerTest", ":FeatureStubImplTest", ":KvStoreDataServiceClearTest", ":KvStoreDataServiceTest", + ":KvStoreMetaManagerUpdateKeyTest", ":SessionManagerTest", + ":UpgradeManagerTest", + ":RouteHeadHandlerImplTest", ] -} - -############################################################################### -group("moduletest") { - testonly = true - deps = [ - "//third_party/googletest:gmock", - "//third_party/googletest:gtest_main", - "//third_party/sqlite:sqlite", - ] - - deps += [ - #":DistributedDataAccountEventModuleTest", - ] -} -############################################################################### +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/BUILD.gn index a04a1d62..94d22099 100644 --- a/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/BUILD.gn @@ -20,9 +20,6 @@ ohos_fuzztest("DataServiceStubFuzzTest") { module_out_path = "datamgr_service/datamgr_service" include_dirs = [ - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", "${data_service_path}/service/bootstrap/include", "${data_service_path}/service/config/include", "${data_service_path}/service/crypto/include", @@ -46,8 +43,6 @@ ohos_fuzztest("DataServiceStubFuzzTest") { "${data_service_path}/adapter/include/installer", "${data_service_path}/adapter/include/utils", "${data_service_path}/adapter/include", - "${device_manager_path}/interfaces/inner_kits/native_cpp/include", - "//third_party/json/single_include", "${data_service_path}/adapter/include/communicator", ] @@ -89,7 +84,6 @@ ohos_fuzztest("DataServiceStubFuzzTest") { "${data_service_path}/app/src/installer:distributeddata_installer", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "${kv_store_distributeddb_path}:distributeddb", ] external_deps = [ @@ -100,6 +94,7 @@ ohos_fuzztest("DataServiceStubFuzzTest") { "bundle_framework:appexecfwk_core", "c_utils:utils", "dataclassification:data_transit_mgr", + "device_manager:devicemanagersdk", "file_api:securitylabel", "hicollie:libhicollie", "hilog:libhilog", @@ -109,6 +104,7 @@ ohos_fuzztest("DataServiceStubFuzzTest") { "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", + "kv_store:distributeddb", "memmgr:memmgrclient", "safwk:system_ability_fwk", "samgr:samgr_proxy", diff --git a/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/dataservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/dataservicestub_fuzzer.cpp index e5164c94..27f99656 100644 --- a/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/dataservicestub_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/dataservicestub_fuzzer.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "dataservicestub_fuzzer.h" #include @@ -29,12 +31,13 @@ const std::u16string INTERFACE_TOKEN = u"OHOS.DistributedKv.IKvStoreDataService" const uint32_t CODE_MIN = 0; const uint32_t CODE_MAX = 10; -bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { - uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + uint32_t code = provider.ConsumeIntegralInRange(CODE_MIN, CODE_MAX); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); - request.WriteBuffer(data, size); + std::vector remainingData = provider.ConsumeRemainingBytes(); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); request.RewindRead(0); MessageParcel reply; MessageOption option; @@ -47,11 +50,7 @@ bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::OnRemoteRequestFuzz(data, size); - + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/mock/capability/device_manager_adapter.cpp b/datamgr_service/services/distributeddataservice/app/test/mock/capability/device_manager_adapter.cpp new file mode 100644 index 00000000..76e30d27 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/mock/capability/device_manager_adapter.cpp @@ -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. + */ + +#include "device_manager_adapter.h" + +namespace OHOS::DistributedData { +static constexpr const char* LOCAL_DEVICE = "ABCDEF0123456789"; +DeviceManagerAdapter &DeviceManagerAdapter::GetInstance() +{ + static DeviceManagerAdapter dmAdapter; + return dmAdapter; +} + +DeviceInfo DeviceManagerAdapter::GetLocalDevice() +{ + return { .uuid = LOCAL_DEVICE }; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/mock/capability/device_manager_adapter.h b/datamgr_service/services/distributeddataservice/app/test/mock/capability/device_manager_adapter.h new file mode 100644 index 00000000..ceb43b53 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/mock/capability/device_manager_adapter.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 MOCK_META_DEVICE_MANAGER_H +#define MOCK_META_DEVICE_MANAGER_H + +#include + +namespace OHOS::DistributedData { +struct DeviceInfo { + std::string uuid; +}; + +class DeviceManagerAdapter { +public: + static DeviceManagerAdapter &GetInstance(); + DeviceInfo GetLocalDevice(); + +private: + DeviceManagerAdapter() = default; + ~DeviceManagerAdapter() = default; +}; +} // namespace OHOS::DistributedData +#endif // MOCK_META_DEVICE_MANAGER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/mock/capability/metadata/meta_data_manager.cpp b/datamgr_service/services/distributeddataservice/app/test/mock/capability/metadata/meta_data_manager.cpp new file mode 100644 index 00000000..867002fd --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/mock/capability/metadata/meta_data_manager.cpp @@ -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. + */ + +#include "meta_data_manager.h" + +namespace OHOS::DistributedData { +MetaDataManager &MetaDataManager::GetInstance() +{ + static MetaDataManager instance; + return instance; +} + +void MetaDataManager::Init(std::shared_ptr executors) +{ + executors_ = std::move(executors); +} + +bool MetaDataManager::SaveMeta(const std::string &key, const CapMetaData &value) +{ + capabilities_.InsertOrAssign(key, value); + executors_->Execute([this, key, value]() { + if (capObserver_ != nullptr) { + capObserver_(key, Serializable::Marshall(value), INSERT); + } + }); + return true; +} + +bool MetaDataManager::LoadMeta(const std::string &key, CapMetaData &value) +{ + auto index = capabilities_.Find(key); + if (index.first) { + value = index.second; + return true; + } + return false; +} + +bool MetaDataManager::Subscribe(std::string prefix, Observer observer) +{ + (void)prefix; + capObserver_ = observer; + return true; +} + +void MetaDataManager::UnSubscribe() +{ + capObserver_ = nullptr; +} + +bool MetaDataManager::UpdateMeta(const std::string &key, const CapMetaData &value) +{ + capabilities_.InsertOrAssign(key, value); + executors_->Execute([this, key, value]() { + if (capObserver_ != nullptr) { + capObserver_(key, Serializable::Marshall(value), UPDATE); + } + }); + return true; +} + +bool MetaDataManager::DeleteMeta(const std::string &key, const CapMetaData &value) +{ + capabilities_.Erase(key); + executors_->Execute([this, key, value]() { + if (capObserver_ != nullptr) { + capObserver_(key, Serializable::Marshall(value), DELETE); + } + }); + return true; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/include/rdb_fault_hiview_reporter.h b/datamgr_service/services/distributeddataservice/app/test/mock/capability/metadata/meta_data_manager.h similarity index 35% rename from relational_store/frameworks/native/gdb/include/rdb_fault_hiview_reporter.h rename to datamgr_service/services/distributeddataservice/app/test/mock/capability/metadata/meta_data_manager.h index c67b3c27..8fbf3814 100644 --- a/relational_store/frameworks/native/gdb/include/rdb_fault_hiview_reporter.h +++ b/datamgr_service/services/distributeddataservice/app/test/mock/capability/metadata/meta_data_manager.h @@ -13,38 +13,42 @@ * limitations under the License. */ -#ifndef DISTRIBUTEDDATAMGR_GDB_FAULT_HIVIEW_REPORTER_H -#define DISTRIBUTEDDATAMGR_GDB_FAULT_HIVIEW_REPORTER_H +#ifndef MOCK_META_DATA_MANAGER_H +#define MOCK_META_DATA_MANAGER_H -#include -#include "rdb_store_config.h" +#include -namespace OHOS::NativeRdb { -// Fault Type Define -static constexpr const char *FT_OPEN = "OPEN_DB"; -static constexpr const char *FT_CURD = "CURD_DB"; -static constexpr const char *FT_EX_FILE = "EX_FILE"; -static constexpr const char *FT_EX_HUKS = "EX_HUKS"; -static constexpr const char *FT_CP = "CHECK_POINT"; +#include "metadata/capability_meta_data.h" +#include "concurrent_map.h" +#include "executor_pool.h" -class RdbFaultEvent { +namespace OHOS::DistributedData { +class MetaDataManager { public: - RdbFaultEvent(const std::string &faultType, int32_t errorCode, const std::string &bundleName, - const std::string &custLog) {}; -}; + enum Action : int32_t { + INSERT = 0, + UPDATE = 1, + DELETE = 2, + }; + + using Observer = std::function; + + static MetaDataManager &GetInstance(); + void Init(std::shared_ptr executors); + bool SaveMeta(const std::string &key, const CapMetaData &value); + bool LoadMeta(const std::string &key, CapMetaData &value); + bool Subscribe(std::string prefix, Observer observer); + void UnSubscribe(); + bool UpdateMeta(const std::string &key, const CapMetaData &value); + bool DeleteMeta(const std::string &key, const CapMetaData &value); -class RdbFaultDbFileEvent : public RdbFaultEvent { -public: - RdbFaultDbFileEvent(const std::string &faultType, int32_t errorCode, const RdbStoreConfig &config, - const std::string &custLog = "", bool printDbInfo = false) - : RdbFaultEvent(faultType, errorCode, "", custLog), config_(config) {} private: - RdbStoreConfig config_; -}; + MetaDataManager() = default; + ~MetaDataManager() = default; -class RdbFaultHiViewReporter { -public: - static void ReportFault(const RdbFaultEvent &faultEvent) {}; + Observer capObserver_; + ConcurrentMap capabilities_ {}; + std::shared_ptr executors_; }; -} // namespace OHOS::NativeRdb -#endif // DISTRIBUTEDDATAMGR_GDB_FAULT_HIVIEW_REPORTER_H \ No newline at end of file +} // namespace OHOS::DistributedData +#endif // MOCK_META_DATA_MANAGER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/bundle_checker_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/bundle_checker_test.cpp new file mode 100644 index 00000000..deb5c7de --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/bundle_checker_test.cpp @@ -0,0 +1,118 @@ +/* +* 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 "accesstoken_kit.h" +#include "checker/bundle_checker.h" +#include "bootstrap.h" +#include "hap_token_info.h" +#include "nativetoken_kit.h" +#include "utils/crypto.h" +using namespace testing::ext; +using namespace OHOS::DistributedData; +using namespace OHOS::Security::AccessToken; +class BundleCheckerTest : public testing::Test { +public: + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} + void SetUp(); + void TearDown(); + NativeTokenInfoParams infoInstance{0}; +}; + +void BundleCheckerTest::SetUp(void) +{ + infoInstance.dcapsNum = 0; + infoInstance.permsNum = 0; + infoInstance.aclsNum = 0; + infoInstance.dcaps = nullptr; + infoInstance.perms = nullptr; + infoInstance.acls = nullptr; + infoInstance.processName = "BundleCheckerTest"; + infoInstance.aplStr = "system_core"; + + HapInfoParams info = { + .userID = 100, + .bundleName = "com.ohos.dlpmanager", + .instIndex = 0, + .appIDDesc = "com.ohos.dlpmanager" + }; + PermissionDef infoManagerTestPermDef = { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.test.demo", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "open the door", + .descriptionId = 1 + }; + PermissionStateFull infoManagerTestState = { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = {"local"}, + .grantStatus = {PermissionState::PERMISSION_GRANTED}, + .grantFlags = {1} + }; + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = {infoManagerTestPermDef}, + .permStateList = {infoManagerTestState} + }; + AccessTokenKit::AllocHapToken(info, policy); + + Bootstrap::GetInstance().LoadComponents(); + Bootstrap::GetInstance().LoadDirectory(); + Bootstrap::GetInstance().LoadCheckers(); + Bootstrap::GetInstance().LoadNetworks(); +} + +void BundleCheckerTest::TearDown() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(100, "com.ohos.dlpmanager", 0); + AccessTokenKit::DeleteToken(tokenId); +} + +/** +* @tc.name: GetAppIdTest001 +* @tc.desc: get appId from cache. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(BundleCheckerTest, GetAppIdTest001, TestSize.Level0) +{ + CheckerManager::StoreInfo info; + auto tokenId = AccessTokenKit::GetHapTokenID(100, "com.ohos.dlpmanager", 0); + info.uid = 100 * 200000; + info.tokenId = tokenId; + info.bundleName = "com.ohos.dlpmanager"; + BundleChecker checker; + std::string appIdInCache; + ASSERT_TRUE(!checker.GetAppId(info).empty()); + checker.appIds_.Get("com.ohos.dlpmanager###100", appIdInCache); + ASSERT_FALSE(appIdInCache.empty()); + ASSERT_EQ(Crypto::Sha256(appIdInCache), checker.GetAppId(info)); + + checker.DeleteCache(info.bundleName, 100, 0); + std::string appIdInCache1; + checker.appIds_.Get("com.ohos.dlpmanager###100", appIdInCache1); + ASSERT_TRUE(appIdInCache1.empty()); + + checker.GetAppId(info); + ASSERT_GE(checker.appIds_.Size(), 1); + checker.ClearCache(); + ASSERT_EQ(checker.appIds_.Size(), 0); +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/feature_stub_impl_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/feature_stub_impl_test.cpp index bae31a7d..f4e87071 100644 --- a/datamgr_service/services/distributeddataservice/app/test/unittest/feature_stub_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/feature_stub_impl_test.cpp @@ -184,7 +184,6 @@ HWTEST_F(FeatureStubImplTest, OnAppExit001, TestSize.Level1) pid_t pid = 0; uint32_t tokenId = 0; std::string bundleName = "com.ohos.test"; - std::shared_ptr executor = std::make_shared(1, 0); auto result = featureStubImpl->OnAppExit(uid, pid, tokenId, bundleName); EXPECT_EQ(result, -1); } @@ -204,11 +203,46 @@ HWTEST_F(FeatureStubImplTest, OnAppExit002, TestSize.Level1) pid_t pid = 0; uint32_t tokenId = 0; std::string bundleName = "com.ohos.test"; - std::shared_ptr executor = std::make_shared(1, 0); auto result = featureStubImpl->OnAppExit(uid, pid, tokenId, bundleName); EXPECT_EQ(result, E_OK); } +/** +* @tc.name: OnFeatureExit001 +* @tc.desc: OnFeatureExit function test. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(FeatureStubImplTest, OnFeatureExit001, TestSize.Level1) +{ + std::shared_ptr feature = nullptr; + std::shared_ptr featureStubImpl = std::make_shared(feature); + pid_t uid = 0; + pid_t pid = 0; + uint32_t tokenId = 0; + std::string bundleName = "com.ohos.test"; + auto result = featureStubImpl->OnFeatureExit(uid, pid, tokenId, bundleName); + EXPECT_EQ(result, -1); +} + +/** +* @tc.name: OnFeatureExit002 +* @tc.desc: OnFeatureExit function test. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(FeatureStubImplTest, OnFeatureExit002, TestSize.Level1) +{ + std::shared_ptr feature = std::make_shared(); + std::shared_ptr featureStubImpl = std::make_shared(feature); + pid_t uid = 0; + pid_t pid = 0; + uint32_t tokenId = 0; + std::string bundleName = "com.ohos.test"; + auto result = featureStubImpl->OnFeatureExit(uid, pid, tokenId, bundleName); + EXPECT_EQ(result, E_OK); +} + /** * @tc.name: OnAppUninstall001 * @tc.desc: OnAppUninstall function test. diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_data_service_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_data_service_test.cpp index 7b9aeb3d..fcaec798 100644 --- a/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_data_service_test.cpp +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_data_service_test.cpp @@ -15,7 +15,7 @@ #include "auth_delegate.h" #include "bootstrap.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter.h" #include "executor_pool.h" #include @@ -30,6 +30,7 @@ #include "system_ability.h" #include "system_ability_definition.h" #include "upgrade_manager.h" +#include "utils/base64_utils.h" using namespace testing::ext; using namespace OHOS; @@ -81,7 +82,6 @@ void KvStoreDataServiceTest::SetUpTestCase(void) KvStoreMetaManager::GetInstance().BindExecutor(executors); KvStoreMetaManager::GetInstance().InitMetaParameter(); KvStoreMetaManager::GetInstance().InitMetaListener(); - DeviceManagerAdapter::GetInstance().Init(executors); } void KvStoreDataServiceTest::TearDownTestCase(void) @@ -149,10 +149,45 @@ HWTEST_F(KvStoreDataServiceTest, RegisterClientDeathObserver001, TestSize.Level1 Bootstrap::GetInstance().LoadCheckers(); KvStoreMetaManager::GetInstance().BindExecutor(std::make_shared(12, 5)); KvStoreMetaManager::GetInstance().InitMetaParameter(); - Status status = kvDataService.RegisterClientDeathObserver(appId, new KvStoreClientDeathObserver()); + Status status = kvDataService.RegisterClientDeathObserver(appId, new KvStoreClientDeathObserver(), ""); EXPECT_EQ(status, Status::SUCCESS) << "RegisterClientDeathObserver failed"; } +/** +* @tc.name: RegisterClientDeathObserver002 +* @tc.desc: register client death observer +* @tc.type: FUNC +*/ +HWTEST_F(KvStoreDataServiceTest, RegisterClientDeathObserver002, TestSize.Level1) +{ + AppId appId; + appId.appId = "app0"; + KvStoreDataService kvDataService; + Bootstrap::GetInstance().LoadComponents(); + Bootstrap::GetInstance().LoadCheckers(); + KvStoreMetaManager::GetInstance().BindExecutor(std::make_shared(12, 5)); + KvStoreMetaManager::GetInstance().InitMetaParameter(); + Status status = kvDataService.RegisterClientDeathObserver(appId, nullptr, ""); + EXPECT_EQ(status, Status::SUCCESS) << "RegisterClientDeathObserver failed"; + for (int i = 0; i < 17; i++) { + auto featureName = std::to_string(i); + status = kvDataService.RegisterClientDeathObserver(appId, new KvStoreClientDeathObserver(), featureName); + EXPECT_EQ(status, Status::SUCCESS) << "RegisterClientDeathObserver failed"; + } +} + +/** +* @tc.name: Exit001 +* @tc.desc: feature Exit +* @tc.type: FUNC +*/ +HWTEST_F(KvStoreDataServiceTest, Exit001, TestSize.Level1) +{ + KvStoreDataService kvDataService; + EXPECT_EQ(kvDataService.Exit(""), Status::SUCCESS); +} + + /** * @tc.name: GetIndentation001 * @tc.desc: @@ -669,21 +704,19 @@ HWTEST_F(KvStoreDataServiceTest, DumpBundleInfo001, TestSize.Level0) } /** -* @tc.name: UpgradeManagerTest001 -* @tc.desc: test Init function +* @tc.name: OnExtensionRestore001 +* @tc.desc: restore with invalid fd * @tc.type: FUNC * @tc.require: -* @tc.author: SQL +* @tc.author: zhaojh */ -HWTEST_F(UpgradeManagerTest, UpgradeManagerTest001, TestSize.Level0) +HWTEST_F(KvStoreDataServiceTest, OnExtension001, TestSize.Level0) { - auto executors = std::make_shared(1, 0); - DistributedData::UpgradeManager instance; - instance.Init(executors); - EXPECT_TRUE(instance.executors_); - - instance.Init(executors); - EXPECT_TRUE(instance.executors_); + KvStoreDataService kvStoreDataServiceTest; + MessageParcel data; + MessageParcel reply; + data.WriteFileDescriptor(-1); + EXPECT_EQ(kvStoreDataServiceTest.OnExtension("invalid", data, reply), 0); } /** @@ -829,7 +862,7 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionRestore006, TestSize.Level0) * @tc.desc: test OnExtension function backup invalid json * @tc.type: FUNC * @tc.require: - * @tc.author: SQL + * @tc.author: zhaojh */ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup001, TestSize.Level0) { KvStoreDataService kvStoreDataServiceTest; @@ -845,7 +878,7 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup001, TestSize.Level0) { * @tc.desc: test OnExtension function backup application empty * @tc.type: FUNC * @tc.require: - * @tc.author: SQL + * @tc.author: zhaojh */ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup002, TestSize.Level0) { KvStoreDataService kvStoreDataServiceTest; @@ -863,7 +896,7 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup002, TestSize.Level0) { * @tc.desc: test OnExtension function backup no userInfo * @tc.type: FUNC * @tc.require: - * @tc.author: SQL + * @tc.author: zhaojh */ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup003, TestSize.Level0) { KvStoreDataService kvStoreDataServiceTest; @@ -882,7 +915,7 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup003, TestSize.Level0) { * @tc.desc: test OnExtension function backup userinfo empty * @tc.type: FUNC * @tc.require: - * @tc.author: SQL + * @tc.author: zhaojh */ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup004, TestSize.Level0) { KvStoreDataService kvStoreDataServiceTest; @@ -902,7 +935,7 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup004, TestSize.Level0) { * @tc.desc: test OnExtension function backup secret key length invalid * @tc.type: FUNC * @tc.require: - * @tc.author: SQL + * @tc.author: zhaojh */ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup005, TestSize.Level0) { KvStoreDataService kvStoreDataServiceTest; @@ -926,7 +959,7 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup005, TestSize.Level0) { * @tc.desc: test OnExtension function backup secret iv length invalid * @tc.type: FUNC * @tc.require: - * @tc.author: SQL + * @tc.author: zhaojh */ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup006, TestSize.Level0) { KvStoreDataService kvStoreDataServiceTest; @@ -950,7 +983,7 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup006, TestSize.Level0) { * @tc.desc: test OnExtension function backup no bundle * @tc.type: FUNC * @tc.require: - * @tc.author: SQL + * @tc.author: zhaojh */ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup007, TestSize.Level0) { KvStoreDataService kvStoreDataServiceTest; @@ -984,7 +1017,7 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup007, TestSize.Level0) { * @tc.desc: test OnExtension function backup no bundle * @tc.type: FUNC * @tc.require: - * @tc.author: SQL + * @tc.author: zhaojh */ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup008, TestSize.Level0) { KvStoreDataService kvStoreDataServiceTest; @@ -994,20 +1027,24 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup008, TestSize.Level0) { testMeta.bundleName = "com.example.restore_test"; testMeta.storeId = "Source"; testMeta.user = "100"; - testMeta.area = DEFAULT_ENCRYPTION_LEVEL; + testMeta.area = CryptoManager::Area::EL1; testMeta.instanceId = 0; testMeta.deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; testMeta.isEncrypt = true; + testMeta.dataDir = "TEST_DIR"; std::vector sKey{2, 249, 221, 119, 177, 216, 217, 134, 185, 139, 114, 38, 140, 64, 165, 35, 77, 169, 0, 226, 226, 166, 37, 73, 181, 229, 42, 88, 108, 111, 131, 104, 141, 43, 96, 119, 214, 34, 177, 129, 233, 96, 98, 164, 87, 115, 187, 170}; SecretKeyMetaData testSecret; - testSecret.sKey = CryptoManager::GetInstance().Encrypt(sKey, testMeta.area, testMeta.user); + CryptoManager::CryptoParams encryptParams = { .area = testMeta.area }; + testSecret.sKey = CryptoManager::GetInstance().Encrypt(sKey, encryptParams); testSecret.storeType = 10; testSecret.time = std::vector{233, 39, 137, 103, 0, 0, 0, 0}; + testSecret.nonce = encryptParams.nonce; + testSecret.area = encryptParams.area; EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(testMeta.GetKey(), testMeta, true), true); EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(testMeta.GetSecretKey(), testSecret, true), true); @@ -1036,4 +1073,280 @@ HWTEST_F(KvStoreDataServiceTest, OnExtensionBackup008, TestSize.Level0) { EXPECT_TRUE(backupData.infos.size() == 1); } -} // namespace OHOS::Test \ No newline at end of file + +/** + * @tc.name: ReEncryptKey001 + * @tc.desc: test ReEncryptKey load meta failed + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(KvStoreDataServiceTest, ReEncryptKey001, TestSize.Level0) +{ + KvStoreDataService kvStoreDataServiceTest; + MessageParcel data; + MessageParcel reply; + + SecretKeyMetaData secretKeyMeta; + StoreMetaData storeMeta; + std::vector iv; + auto ret = kvStoreDataServiceTest.ReEncryptKey("", secretKeyMeta, storeMeta, iv); + EXPECT_TRUE(ret.empty()); +} + +/** + * @tc.name: ReEncryptKey002 + * @tc.desc: test ReEncryptKey failed when meta sKey is invalid + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(KvStoreDataServiceTest, ReEncryptKey002, TestSize.Level0) +{ + KvStoreDataService kvStoreDataServiceTest; + MessageParcel data; + MessageParcel reply; + + StoreMetaData testMeta; + testMeta.bundleName = "com.example.restore_test"; + testMeta.storeId = "Source"; + testMeta.user = "100"; + testMeta.area = CryptoManager::Area::EL1; + testMeta.instanceId = 0; + testMeta.deviceId = + DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + testMeta.isEncrypt = true; + testMeta.dataDir = "TEST_DIR"; + SecretKeyMetaData testSecret; + CryptoManager::CryptoParams encryptParams = { .area = testMeta.area }; + testSecret.storeType = 10; + testSecret.time = std::vector{233, 39, 137, 103, 0, 0, 0, 0}; + testSecret.nonce = encryptParams.nonce; + testSecret.area = encryptParams.area; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(testMeta.GetKey(), testMeta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(testMeta.GetSecretKey(), testSecret, true), true); + + SecretKeyMetaData secretKeyMeta; + std::vector iv; + auto ret = kvStoreDataServiceTest.ReEncryptKey(testMeta.GetSecretKey(), secretKeyMeta, testMeta, iv); + EXPECT_TRUE(ret.empty()); +} + +/** + * @tc.name: ReEncryptKey003 + * @tc.desc: test reEncryptKey failed when iv is invalid + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(KvStoreDataServiceTest, ReEncryptKey003, TestSize.Level0) +{ + KvStoreDataService kvStoreDataServiceTest; + MessageParcel data; + MessageParcel reply; + + StoreMetaData testMeta; + testMeta.bundleName = "com.example.restore_test"; + testMeta.storeId = "Source"; + testMeta.user = "100"; + testMeta.area = CryptoManager::Area::EL1; + testMeta.instanceId = 0; + testMeta.deviceId = + DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + testMeta.isEncrypt = true; + testMeta.dataDir = "TEST_DIR"; + std::vector sKey{2, 249, 221, 119, 177, 216, 217, 134, 185, 139, + 114, 38, 140, 64, 165, 35, 77, 169, 0, 226, + 226, 166, 37, 73, 181, 229, 42, 88, 108, 111, + 131, 104, 141, 43, 96, 119, 214, 34, 177, 129, + 233, 96, 98, 164, 87, 115, 187, 170}; + SecretKeyMetaData testSecret; + CryptoManager::CryptoParams encryptParams = { .area = testMeta.area }; + testSecret.sKey = CryptoManager::GetInstance().Encrypt(sKey, encryptParams); + testSecret.storeType = 10; + testSecret.time = std::vector{233, 39, 137, 103, 0, 0, 0, 0}; + testSecret.nonce = encryptParams.nonce; + testSecret.area = encryptParams.area; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(testMeta.GetKey(), testMeta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(testMeta.GetSecretKey(), testSecret, true), true); + + SecretKeyMetaData secretKeyMeta; + std::vector iv; + auto ret = kvStoreDataServiceTest.ReEncryptKey(testMeta.GetSecretKey(), secretKeyMeta, testMeta, iv); + EXPECT_TRUE(ret.empty()); +} + +/** + * @tc.name: OnExtensionRestore_InvalidUserId + * @tc.desc: Test OnRestore returns -1 when userId is empty + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(KvStoreDataServiceTest, OnExtensionRestore_InvalidUserId, TestSize.Level0) +{ + KvStoreDataService kvStoreDataServiceTest; + MessageParcel data; + MessageParcel reply; + // Prepare a valid backup file (content doesn't matter, as IV size will fail first) + EXPECT_EQ(WriteContentToFile(SECRETKEY_BACKUP_FILE, NORMAL_BACKUP_DATA), 0); + int32_t fd = open(SECRETKEY_BACKUP_FILE.c_str(), O_RDONLY); + ASSERT_GE(fd, 0); + data.WriteFileDescriptor(fd); + + std::string cloneInfoStr = + "[{\"type\":\"encryption_info\",\"detail\":{\"encryption_symkey\":\"27," + "145,118,212,62,156,133,135,50,68,188,239,20,170,227,190,37,142,218," + "158,177,32,5,160,13,114,186,141,59,91,44,200\",\"encryption_algname\":" + "\"AES256\",\"gcmParams_iv\":\"1,2,3,4,5,6,7,8,9,10\"}},{\"type\":\"userId\",\"detail\":\"\"}]"; + data.WriteString(cloneInfoStr); + + // Should return -1 due to IV size error + EXPECT_EQ(kvStoreDataServiceTest.OnExtension("restore", data, reply), -1); + close(fd); +} + +/** + * @tc.name: OnExtensionRestore_InvalidIvSize + * @tc.desc: Test OnRestore returns -1 when IV size is incorrect + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(KvStoreDataServiceTest, OnExtensionRestore_InvalidIvSize, TestSize.Level0) +{ + KvStoreDataService kvStoreDataServiceTest; + MessageParcel data; + MessageParcel reply; + + EXPECT_EQ(WriteContentToFile(SECRETKEY_BACKUP_FILE, NORMAL_BACKUP_DATA), 0); + int32_t fd = open(SECRETKEY_BACKUP_FILE.c_str(), O_RDONLY); + ASSERT_GE(fd, 0); + data.WriteFileDescriptor(fd); + + // Prepare cloneInfoStr with invalid IV (length != AES_256_NONCE_SIZE) + std::string cloneInfoStr = + "[{\"type\":\"encryption_info\",\"detail\":{\"encryption_symkey\":\"27," + "145,118,212,62,156,133,135,50,68,188,239,20,170,227,190,37,142,218," + "158,177,32,5,160,13,114,186,141,59,91,44,200\",\"encryption_algname\":" + "\"AES256\",\"gcmParams_iv\":\"1,2,3,4,5,6,7,8,9,10\"}},{\"type\":\"userId\",\"detail\":\"100\"}]"; + data.WriteString(cloneInfoStr); + + // Should return -1 due to IV size error + EXPECT_EQ(kvStoreDataServiceTest.OnExtension("restore", data, reply), -1); + close(fd); +} + +/** + * @tc.name: OnExtensionRestore_ImportCloneKeyFailed + * @tc.desc: Test OnRestore returns -1 when ImportCloneKey fails (invalid key size) + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(KvStoreDataServiceTest, OnExtensionRestore_ImportCloneKeyFailed, TestSize.Level0) +{ + KvStoreDataService kvStoreDataServiceTest; + MessageParcel data; + MessageParcel reply; + + // Prepare a valid backup file (content doesn't matter, as ImportCloneKey will fail first) + EXPECT_EQ(WriteContentToFile(SECRETKEY_BACKUP_FILE, NORMAL_BACKUP_DATA), 0); + int32_t fd = open(SECRETKEY_BACKUP_FILE.c_str(), O_RDONLY); + ASSERT_GE(fd, 0); + data.WriteFileDescriptor(fd); + + // Prepare cloneInfoStr with invalid encryption_symkey (too short, so ImportCloneKey fails) + std::string cloneInfoStr = + "[{\"type\":\"encryption_info\",\"detail\":{\"encryption_symkey\":\"1,2,3\",\"encryption_algname\":\"AES256\"," + "\"gcmParams_iv\":\"97,160,201,177,46,37,129,18,112,220,107,106,25,231,15,15,""58,85,31,83,123,216,211,2,222," + "49,122,72,21,251,83,16\"}},{\"type\":\"userId\",\"detail\":\"100\"}]"; + data.WriteString(cloneInfoStr); + + // Should return -1 due to ImportCloneKey failure + EXPECT_EQ(kvStoreDataServiceTest.OnExtension("restore", data, reply), -1); + close(fd); +} + +/** + * @tc.name: OnExtensionRestore_RestoreSuccess + * @tc.desc: Test OnRestore returns 0 when ImportCloneKey succeeds + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(KvStoreDataServiceTest, OnExtensionRestore_RestoreSuccess, TestSize.Level0) +{ + KvStoreDataService kvStoreDataServiceTest; + MessageParcel data; + MessageParcel reply; + + StoreMetaData testMeta; + testMeta.bundleName = "com.myapp.example"; + testMeta.storeId = "storeId"; + testMeta.user = "100"; + testMeta.area = CryptoManager::Area::EL1; + testMeta.instanceId = 0; + testMeta.deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + testMeta.isEncrypt = true; + testMeta.dataDir = "TEST_DIR"; + std::vector sKey(32, 0); + SecretKeyMetaData testSecret; + CryptoManager::CryptoParams encryptParams = { .area = testMeta.area }; + testSecret.sKey = CryptoManager::GetInstance().Encrypt(sKey, encryptParams); + testSecret.storeType = 10; + testSecret.time = std::vector{ 233, 39, 137, 103, 0, 0, 0, 0 }; + testSecret.nonce = encryptParams.nonce; + testSecret.area = encryptParams.area; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(testMeta.GetKey(), testMeta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(testMeta.GetSecretKey(), testSecret, true), true); + + std::string symKey = "27,145,118,212,62,156,133,135,50,68,188,239,20,170,227,190,37,142," + "218,158,177,32,5,160,13,114,186,141,59,91,44,200"; + std::vector iv{ 97, 160, 201, 177, 46, 37, 129, 18, 112, 220, 107, 106, 25, 231, 15, 15, 58, 85, 31, 83, + 123, 216, 211, 2, 222, 49, 122, 72, 21, 251, 83, 16 }; + + ASSERT_EQ(kvStoreDataServiceTest.ImportCloneKey(symKey), true); + + SecretKeyMetaData secretKeyMeta; + auto reEncryptedKey = kvStoreDataServiceTest.ReEncryptKey(testMeta.GetSecretKey(), secretKeyMeta, testMeta, iv); + kvStoreDataServiceTest.DeleteCloneKey(); + auto encodeEncryptedKey = DistributedData::Base64::Encode(reEncryptedKey); + + const std::string backupData = + std::string("{\"infos\":[{\"bundleName\":\"com.myapp.example\",\"dbName\":\"storeId\"," + "\"instanceId\":0,\"storeType\":\"10\",\"user\":\"100\",\"sKey\":\"") + + encodeEncryptedKey + std::string("\",\"time\":[50,180,137,103,0,0,0,0]}]}"); + + EXPECT_EQ(WriteContentToFile(SECRETKEY_BACKUP_FILE, backupData), 0); + int32_t fd = open(SECRETKEY_BACKUP_FILE.c_str(), O_RDONLY); + ASSERT_GE(fd, 0); + data.WriteFileDescriptor(fd); + + std::string cloneInfoStr = + std::string("[{\"type\":\"encryption_info\",\"detail\":{\"encryption_symkey\":\"") + symKey + + std::string("\",\"encryption_algname\":\"AES256\",\"gcmParams_iv\":\"97,160,201,177,46,37,129,18,112,220,107," + "106,25,231,15,15,58,85,31,83,123,216,211,2,222,49,122,72,21,251,83,16\"}}," + "{\"type\":\"userId\",\"detail\":\"100\"}]"); + data.WriteString(cloneInfoStr); + + EXPECT_EQ(kvStoreDataServiceTest.OnExtension("restore", data, reply), 0); + close(fd); +} + +/** + * @tc.name: WriteBackupInfo_FwriteFail + * @tc.desc: Test WriteBackupInfo returns false when fwrite fails + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(KvStoreDataServiceTest, WriteBackupInfo_FwriteFail, TestSize.Level0) +{ + KvStoreDataService kvStoreDataServiceTest; + std::string content = "test_content"; + // Try to open a directory as a file, which should fail at fopen + bool result = kvStoreDataServiceTest.WriteBackupInfo(content, "/"); + EXPECT_FALSE(result); +} +} // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_meta_manager_update_key_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_meta_manager_update_key_test.cpp new file mode 100644 index 00000000..a520cfb6 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_meta_manager_update_key_test.cpp @@ -0,0 +1,337 @@ +/* +* 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. +*/ +#define LOG_TAG "KvstoreMetaManagerUpdateKeyTest" + +#include "bootstrap.h" +#include "device_manager_adapter.h" +#include "device_manager_adapter_mock.h" +#include "executor_pool.h" +#include "gtest/gtest.h" +#include "kvstore_meta_manager.h" +#include "log_print.h" +#include "metadata/device_meta_data.h" +#include "metadata/meta_data_manager.h" +#include "metadata/secret_key_meta_data.h" +#include "metadata/store_meta_data.h" +#include "metadata/store_meta_data_local.h" +#include "metadata/version_meta_data.h" +#include "semaphore_ex.h" +#include "store_types.h" +namespace { +using namespace testing::ext; +using namespace testing; +using namespace OHOS::DistributedData; +using KvStoreMetaManager = OHOS::DistributedKv::KvStoreMetaManager; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; +class KvstoreMetaManagerUpdateKeyTest : public testing::Test { +public: + static void SetUpTestCase() + { + deviceManagerAdapterMock = std::make_shared(); + BDeviceManagerAdapter::deviceManagerAdapter = deviceManagerAdapterMock; + DeviceInfo deviceInfo; + deviceInfo.uuid = "ABCD"; + EXPECT_CALL(*deviceManagerAdapterMock, GetLocalDevice()).WillRepeatedly(Return(deviceInfo)); + EXPECT_CALL(*deviceManagerAdapterMock, GetUuidByNetworkId(_)).WillRepeatedly(Return(deviceInfo.uuid)); + EXPECT_CALL(*deviceManagerAdapterMock, CalcClientUuid(_, _)).WillRepeatedly(Return(deviceInfo.uuid)); + EXPECT_CALL(*deviceManagerAdapterMock, ToUUID(deviceInfo.uuid)).WillRepeatedly(Return(deviceInfo.uuid)); + auto executors = std::make_shared(1, 0); + Bootstrap::GetInstance().LoadComponents(); + Bootstrap::GetInstance().LoadDirectory(); + DeviceManagerAdapter::GetInstance().Init(executors); + KvStoreMetaManager::GetInstance().BindExecutor(executors); + KvStoreMetaManager::GetInstance().InitMetaParameter(); + } + + static void TearDownTestCase() + { + deviceManagerAdapterMock = nullptr; + BDeviceManagerAdapter::deviceManagerAdapter = nullptr; + } + + void SetUp() + { + } + + void TearDown() + { + } + + static inline std::shared_ptr deviceManagerAdapterMock = nullptr; +}; + +/** +* @tc.name: keyUpdataTestWithUuid +* @tc.desc: key updata test +* @tc.type: FUNC +* @tc.require: +* @tc.author: cjx +*/ +HWTEST_F(KvstoreMetaManagerUpdateKeyTest, KeyUpdataTest001, TestSize.Level1) +{ + auto store = KvStoreMetaManager::GetInstance().GetMetaKvStore(); + DeviceMetaData deviceMetaData; + deviceMetaData.newUuid = "KeyUpdataTest001_oldUuid"; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(deviceMetaData.GetKey(), deviceMetaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(deviceMetaData.GetKey(), deviceMetaData, true)); + + StoreMetaData metaData; + metaData.deviceId = "KeyUpdataTest001_oldUuid"; + metaData.user = "KeyUpdataTest001_user"; + metaData.bundleName = "KeyUpdataTest001_bundleName"; + metaData.storeId = "KeyUpdataTest001_storeId"; + metaData.dataDir = "KeyUpdataTest001_dataDir"; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + StoreMetaDataLocal metaDataLocal; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + SecretKeyMetaData secretKeymetaData; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetSecretKeyWithoutPath(), secretKeymetaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetSecretKeyWithoutPath(), secretKeymetaData, true)); + + VersionMetaData versionMeta; + versionMeta.version = VersionMetaData::UPDATE_SYNC_META_VERSION; + MetaDataManager::GetInstance().SaveMeta(versionMeta.GetKey(), versionMeta, true); + + KvStoreMetaManager::GetInstance().InitMetaData(); + metaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocal(), metaDataLocal, true)); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetSecretKeyWithoutPath(), secretKeymetaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetSecretKey(), secretKeymetaData, true)); + + StoreMetaMapping storeMetaMapping(metaData); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKey(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath())); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyLocal(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetSecretKey(), true)); +} + +/** +* @tc.name: KeyUpdataTest +* @tc.desc: key updata test +* @tc.type: FUNC +* @tc.require: +* @tc.author: cjx +*/ +HWTEST_F(KvstoreMetaManagerUpdateKeyTest, KeyUpdataTest002, TestSize.Level1) +{ + auto store = KvStoreMetaManager::GetInstance().GetMetaKvStore(); + StoreMetaData metaData; + metaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData.user = "KeyUpdataTest002_user"; + metaData.bundleName = "KeyUpdataTest002_bundleName"; + metaData.storeId = "KeyUpdataTest002_storeId"; + metaData.dataDir = "KeyUpdataTest002_dataDir"; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + StoreMetaDataLocal metaDataLocal; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + SecretKeyMetaData secretKeymetaData; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetSecretKeyWithoutPath(), secretKeymetaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetSecretKeyWithoutPath(), secretKeymetaData, true)); + + VersionMetaData versionMeta; + versionMeta.version = VersionMetaData::UPDATE_SYNC_META_VERSION; + MetaDataManager::GetInstance().SaveMeta(versionMeta.GetKey(), versionMeta, true); + KvStoreMetaManager::GetInstance().InitMetaData(); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocal(), metaDataLocal, true)); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetSecretKeyWithoutPath(), secretKeymetaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetSecretKey(), secretKeymetaData, true)); + + StoreMetaMapping storeMetaMapping(metaData); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKey(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath())); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyLocal(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetSecretKey(), true)); +} + +/** +* @tc.name: KeyUpdataTest +* @tc.desc: key updata test +* @tc.type: FUNC +* @tc.require: +* @tc.author: cjx +*/ +HWTEST_F(KvstoreMetaManagerUpdateKeyTest, KeyUpdataTest003, TestSize.Level1) +{ + auto store = KvStoreMetaManager::GetInstance().GetMetaKvStore(); + StoreMetaData metaData; + metaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData.user = "KeyUpdataTest003_user"; + metaData.bundleName = "KeyUpdataTest003_bundleName"; + metaData.storeId = "KeyUpdataTest003_storeId"; + metaData.dataDir = "KeyUpdataTest003_dataDir"; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + + KvStoreMetaManager::GetInstance().InitMetaData(); + + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKey(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath())); +} + +/** +* @tc.name: KeyUpdataTest +* @tc.desc: key updata test +* @tc.type: FUNC +* @tc.require: +* @tc.author: my +*/ +HWTEST_F(KvstoreMetaManagerUpdateKeyTest, KeyUpdataTest004, TestSize.Level1) +{ + auto store = KvStoreMetaManager::GetInstance().GetMetaKvStore(); + StoreMetaData metaData; + metaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData.user = "KeyUpdataTest004_user"; + metaData.bundleName = "KeyUpdataTest004_bundleName"; + metaData.storeId = "KeyUpdataTest004_storeId"; + metaData.dataDir = "KeyUpdataTest004_dataDir"; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + + VersionMetaData versionMeta; + MetaDataManager::GetInstance().DelMeta(versionMeta.GetKey(), true); + + KvStoreMetaManager::GetInstance().InitMetaData(); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKey(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath())); +} + +/** +* @tc.name: KeyUpdataTest +* @tc.desc: key updata test +* @tc.type: FUNC +* @tc.require: +* @tc.author: my +*/ +HWTEST_F(KvstoreMetaManagerUpdateKeyTest, KeyUpdataTest005, TestSize.Level1) +{ + auto store = KvStoreMetaManager::GetInstance().GetMetaKvStore(); + StoreMetaData metaData; + metaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData.user = "KeyUpdataTest005_user"; + metaData.bundleName = "KeyUpdataTest005_bundleName"; + metaData.storeId = "KeyUpdataTest005_storeId"; + metaData.dataDir = "KeyUpdataTest005_dataDir"; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + + VersionMetaData versionMeta; + versionMeta.version = 3; // Set version to 3. + MetaDataManager::GetInstance().SaveMeta(versionMeta.GetKey(), versionMeta, true); + KvStoreMetaManager::GetInstance().InitMetaData(); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)); + + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKey(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath())); +} + +/** +* @tc.name: KeyUpdataTest +* @tc.desc: key updata test +* @tc.type: FUNC +* @tc.require: +* @tc.author: my +*/ +HWTEST_F(KvstoreMetaManagerUpdateKeyTest, KeyUpdataTest006, TestSize.Level1) +{ + auto store = KvStoreMetaManager::GetInstance().GetMetaKvStore(); + StoreMetaData metaData; + + VersionMetaData versionMeta; + versionMeta.version = VersionMetaData::UPDATE_SYNC_META_VERSION; + MetaDataManager::GetInstance().SaveMeta(versionMeta.GetKey(), versionMeta, true); + KvStoreMetaManager::GetInstance().InitMetaData(); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData, true)); +} + +/** +* @tc.name: KeyUpdataTest +* @tc.desc: key updata test +* @tc.type: FUNC +* @tc.require: +* @tc.author: my +*/ +HWTEST_F(KvstoreMetaManagerUpdateKeyTest, KeyUpdataTest007, TestSize.Level1) +{ + auto store = KvStoreMetaManager::GetInstance().GetMetaKvStore(); + + StoreMetaData metaData; + metaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData.user = "KeyUpdataTest007_user"; + metaData.bundleName = "KeyUpdataTest007_bundleName"; + metaData.storeId = "KeyUpdataTest007_storeId"; + metaData.dataDir = "KeyUpdataTest007_dataDir"; + StoreMetaDataLocal metaDataLocal; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + + VersionMetaData versionMeta; + versionMeta.version = VersionMetaData::UPDATE_SYNC_META_VERSION; + MetaDataManager::GetInstance().SaveMeta(versionMeta.GetKey(), versionMeta, true); + KvStoreMetaManager::GetInstance().InitMetaData(); + + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocalWithoutPath(), metaDataLocal, true)); + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyLocal(), metaDataLocal, true)); + + StoreMetaMapping storeMetaMapping(metaData); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true)); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData.GetKeyLocal(), true)); +} +} // namespace \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/route_head_handler_impl_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/route_head_handler_impl_test.cpp new file mode 100644 index 00000000..1edb1091 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/route_head_handler_impl_test.cpp @@ -0,0 +1,240 @@ +/* + * 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 "session_manager/session_manager.h" + +#include + +#include "accesstoken_kit.h" +#include "account_delegate_mock.h" +#include "auth_delegate_mock.h" +#include "bootstrap.h" +#include "device_manager_adapter.h" +#include "device_manager_adapter_mock.h" +#include "gtest/gtest.h" +#include +#include "meta_data_manager_mock.h" +#include "metadata/meta_data_manager.h" +#include "metadata/store_meta_data.h" +#include "nativetoken_kit.h" +#include "session_manager/route_head_handler_impl.h" +#include "session_manager/upgrade_manager.h" +#include "token_setproc.h" +#include "user_delegate.h" +#include "user_delegate_mock.h" +#include "utils/endian_converter.h" + +namespace { +using namespace testing; +using namespace testing::ext; +using namespace OHOS::DistributedKv; +using namespace OHOS::DistributedData; +using namespace DistributedDB; +using namespace OHOS; +using namespace OHOS::Security::AccessToken; +using DeviceInfo = OHOS::AppDistributedKv::DeviceInfo; +using UserInfo = DistributedDB::UserInfo; +constexpr const char *PEER_DEVICE_ID = "PEER_DEVICE_ID"; +constexpr const char *PROCESSLABEL = "distributeddata"; +constexpr const char *META_DB = "service_meta"; +constexpr const char *DRAG = "drag"; +constexpr const char *OTHER_APP_ID = "test_app_id"; +constexpr const char *USER_ID = "100"; +static constexpr int32_t OH_OS_TYPE = 10; + +void GrantPermissionNative() +{ + const char **perms = new const char *[2]; + perms[0] = "ohos.permission.DISTRIBUTED_DATASYNC"; + perms[1] = "ohos.permission.ACCESS_SERVICE_DM"; + TokenInfoParams infoInstance = { + .dcapsNum = 0, + .permsNum = 2, + .aclsNum = 0, + .dcaps = nullptr, + .perms = perms, + .acls = nullptr, + .processName = "distributed_data_test", + .aplStr = "system_basic", + }; + uint64_t tokenId = GetAccessTokenId(&infoInstance); + SetSelfTokenID(tokenId); + AccessTokenKit::ReloadNativeTokenInfo(); + delete[] perms; +} + +class RouteHeadHandlerImplTest : public testing::Test { +public: + static void SetUpTestCase() + { + GrantPermissionNative(); + deviceManagerAdapterMock = std::make_shared(); + BDeviceManagerAdapter::deviceManagerAdapter = deviceManagerAdapterMock; + metaDataManagerMock = std::make_shared(); + BMetaDataManager::metaDataManager = metaDataManagerMock; + metaDataMock = std::make_shared>(); + BMetaData::metaDataManager = metaDataMock; + userDelegateMock = std::make_shared(); + BUserDelegate::userDelegate = userDelegateMock; + } + static void TearDownTestCase() + { + deviceManagerAdapterMock = nullptr; + BDeviceManagerAdapter::deviceManagerAdapter = nullptr; + metaDataManagerMock = nullptr; + BMetaDataManager::metaDataManager = nullptr; + metaDataMock = nullptr; + BMetaData::metaDataManager = nullptr; + userDelegateMock = nullptr; + BUserDelegate::userDelegate = nullptr; + } + void SetUp(){}; + void TearDown(){}; + static inline std::shared_ptr deviceManagerAdapterMock = nullptr; + static inline std::shared_ptr metaDataManagerMock = nullptr; + static inline std::shared_ptr> metaDataMock = nullptr; + static inline std::shared_ptr userDelegateMock = nullptr; +private: + bool CheckGetEmptyHeadDataLen(const DistributedDB::ExtendInfo& info); + bool CheckParseEmptyHeadDataLen(const DistributedDB::ExtendInfo& info); +}; + +bool RouteHeadHandlerImplTest::CheckGetEmptyHeadDataLen(const DistributedDB::ExtendInfo& info) +{ + DeviceInfo deviceInfo; + deviceInfo.osType = OH_OS_TYPE; + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + EXPECT_CALL(*deviceManagerAdapterMock, GetDeviceInfo(_)).WillRepeatedly(Return(deviceInfo)); + + auto sendHandler = RouteHeadHandlerImpl::Create(info); + if (sendHandler == nullptr) { + return false; + } + CapMetaData capMetaData; + capMetaData.version = CapMetaData::UDMF_AND_OBJECT_VERSION; + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillRepeatedly(DoAll(SetArgReferee<1>(capMetaData), Return(true))); + uint32_t headSize = 0; + auto status = sendHandler->GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::OK); + EXPECT_EQ(headSize, 0); + return true; +} + +bool RouteHeadHandlerImplTest::CheckParseEmptyHeadDataLen(const DistributedDB::ExtendInfo& info) +{ + DeviceInfo deviceInfo; + deviceInfo.osType = OH_OS_TYPE; + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + EXPECT_CALL(*deviceManagerAdapterMock, GetDeviceInfo(_)).WillRepeatedly(Return(deviceInfo)); + + auto recvHandler = RouteHeadHandlerImpl::Create(info); + if (recvHandler == nullptr) { + return false; + } + + CapMetaData capMetaData; + capMetaData.version = CapMetaData::UDMF_AND_OBJECT_VERSION; + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillRepeatedly(DoAll(SetArgReferee<1>(capMetaData), Return(true))); + + uint32_t routeHeadSize = 0; + std::unique_ptr data = std::make_unique(routeHeadSize); + uint32_t parseSize = 0; + auto status = recvHandler->ParseHeadDataLen(data.get(), routeHeadSize, parseSize, PEER_DEVICE_ID); + EXPECT_EQ(status, false); + EXPECT_EQ(parseSize, routeHeadSize); + return true; +} + +/** + * @tc.name: GetEmptyHeadDataLen_Test1 + * @tc.desc: test get udmf store + * @tc.type: FUNC + */ +HWTEST_F(RouteHeadHandlerImplTest, GetEmptyHeadDataLen_Test1, TestSize.Level0) +{ + const DistributedDB::ExtendInfo info = { + .appId = PROCESSLABEL, .storeId = DRAG, .userId = USER_ID, .dstTarget = PEER_DEVICE_ID + }; + EXPECT_TRUE(CheckParseEmptyHeadDataLen(info)); +} + +/** + * @tc.name: GetEmptyHeadDataLen_Test2 + * @tc.desc: test meta db + * @tc.type: FUNC + */ +HWTEST_F(RouteHeadHandlerImplTest, GetEmptyHeadDataLen_Test2, TestSize.Level0) +{ + const DistributedDB::ExtendInfo info = { + .appId = PROCESSLABEL, .storeId = META_DB, .userId = USER_ID, .dstTarget = PEER_DEVICE_ID + }; + EXPECT_TRUE(CheckParseEmptyHeadDataLen(info)); +} + +/** + * @tc.name: CheckParseEmptyHeadDataLen_Test1 + * @tc.desc: test get udmf store + * @tc.type: FUNC + */ +HWTEST_F(RouteHeadHandlerImplTest, CheckParseEmptyHeadDataLen_Test1, TestSize.Level0) +{ + const DistributedDB::ExtendInfo info = { + .appId = PROCESSLABEL, .storeId = DRAG, .userId = USER_ID, .dstTarget = PEER_DEVICE_ID + }; + EXPECT_TRUE(CheckParseEmptyHeadDataLen(info)); +} + +/** + * @tc.name: CheckParseEmptyHeadDataLen_Test2 + * @tc.desc: test get meta db + * @tc.type: FUNC + */ +HWTEST_F(RouteHeadHandlerImplTest, CheckParseEmptyHeadDataLen_Test2, TestSize.Level0) +{ + const DistributedDB::ExtendInfo info = { + .appId = PROCESSLABEL, .storeId = META_DB, .userId = USER_ID, .dstTarget = PEER_DEVICE_ID + }; + EXPECT_TRUE(CheckParseEmptyHeadDataLen(info)); +} + +/** + * @tc.name: CheckParseEmptyHeadDataLen_Test3 + * @tc.desc: test OTHER_APP_ID + * @tc.type: FUNC + */ +HWTEST_F(RouteHeadHandlerImplTest, CheckParseEmptyHeadDataLen_Test3, TestSize.Level0) +{ + const DistributedDB::ExtendInfo info = { + .appId = OTHER_APP_ID, .storeId = DRAG, .userId = USER_ID, .dstTarget = PEER_DEVICE_ID + }; + EXPECT_TRUE(CheckParseEmptyHeadDataLen(info)); +} + +/** + * @tc.name: CheckParseEmptyHeadDataLen_Test4 + * @tc.desc: test get OTHER_APP_ID and meta db + * @tc.type: FUNC + + */ +HWTEST_F(RouteHeadHandlerImplTest, CheckParseEmptyHeadDataLen_Test4, TestSize.Level0) +{ + const DistributedDB::ExtendInfo info = { + .appId = OTHER_APP_ID, .storeId = META_DB, .userId = USER_ID, .dstTarget = PEER_DEVICE_ID + }; + EXPECT_TRUE(CheckParseEmptyHeadDataLen(info)); +} +} // namespace \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/security_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/security_test.cpp new file mode 100644 index 00000000..6be236a0 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/security_test.cpp @@ -0,0 +1,206 @@ +/* + * 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 "security.h" + +#include + +#include "device_manager_adapter.h" + +using namespace testing::ext; +using namespace OHOS::DistributedKv; +using namespace DistributedDB; +using SecurityOption = DistributedDB::SecurityOption; +using DBStatus = DistributedDB::DBStatus; +namespace OHOS::Test { +class SecurityTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + +protected: + static constexpr const char *FILE_TEST_PATH = "/data/test/KvStoreDataServiceTest"; + static constexpr const char *INVALID_FILE_PATH = "/data/test/invalidTest"; + static constexpr const char *DIR_PATH = "/data/test"; +}; + +void SecurityTest::SetUpTestCase(void) +{ +} + +void SecurityTest::TearDownTestCase(void) +{ +} + +void SecurityTest::SetUp(void) +{ +} + +void SecurityTest::TearDown(void) +{ +} + +/** + * @tc.name: IsXattrValueValid + * @tc.desc: Test for IsXattrValueValid value is empty. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, IsXattrValueValid001, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string value = ""; + auto res = security->IsXattrValueValid(value); + EXPECT_EQ(res, false); +} + +/** + * @tc.name: SetSecurityOption001 + * @tc.desc: Test for SetSecurityOption filePath is empty. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, SetSecurityOption001, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath; + SecurityOption option; + auto res = security->SetSecurityOption(filePath, option); + EXPECT_EQ(res, DBStatus::INVALID_ARGS); +} + +/** + * @tc.name: SetSecurityOption002 + * @tc.desc: Test for SetSecurityOption filePath is invalid. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, SetSecurityOption002, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath = INVALID_FILE_PATH; + SecurityOption option; + auto res = security->SetSecurityOption(filePath, option); + EXPECT_EQ(res, DBStatus::INVALID_ARGS); +} + +/** + * @tc.name: SetSecurityOption003 + * @tc.desc: Test for SetSecurityOption securityLabel is NOT_SET. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, SetSecurityOption003, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath = FILE_TEST_PATH; + SecurityOption option; + option.securityLabel = NOT_SET; + auto res = security->SetSecurityOption(filePath, option); + EXPECT_EQ(res, DBStatus::OK); +} + +/** + * @tc.name: SetSecurityOption004 + * @tc.desc: Test for SetSecurityOption securityLabel is invalid. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, SetSecurityOption004, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath = FILE_TEST_PATH; + SecurityOption option; + option.securityLabel = INVALID_SEC_LABEL; + auto res = security->SetSecurityOption(filePath, option); + EXPECT_EQ(res, DBStatus::INVALID_ARGS); +} + +/** + * @tc.name: SetSecurityOption005 + * @tc.desc: Test for SetSecurityOption securityLabel is normal. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, SetSecurityOption005, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath = FILE_TEST_PATH; + SecurityOption option; + option.securityLabel = S0; + auto res = security->SetSecurityOption(filePath, option); + EXPECT_EQ(res, DBStatus::OK); +} + +/** + * @tc.name: GetSecurityOption001 + * @tc.desc: Test for GetSecurityOption filePath is empty. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, GetSecurityOption001, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath; + SecurityOption option; + auto res = security->GetSecurityOption(filePath, option); + EXPECT_EQ(res, DBStatus::INVALID_ARGS); +} + +/** + * @tc.name: GetSecurityOption002 + * @tc.desc: Test for GetSecurityOption DIR_PATH is NOT_SUPPORT. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, GetSecurityOption002, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath = DIR_PATH; + SecurityOption option; + auto res = security->GetSecurityOption(filePath, option); + EXPECT_EQ(res, DBStatus::NOT_SUPPORT); +} + +/** + * @tc.name: GetSecurityOption003 + * @tc.desc: Test for GetSecurityOption filePath is invalid. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, GetSecurityOption003, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath = INVALID_FILE_PATH; + SecurityOption option; + auto res = security->GetSecurityOption(filePath, option); + EXPECT_EQ(res, DBStatus::OK); + EXPECT_EQ(option.securityLabel, NOT_SET); + EXPECT_EQ(option.securityFlag, ECE); +} + +/** + * @tc.name: GetSecurityOption005 + * @tc.desc: Test for GetSecurityOption file of securityLabel is S3. + * @tc.type: FUNC + */ +HWTEST_F(SecurityTest, GetSecurityOption005, TestSize.Level1) +{ + auto security = std::make_shared(); + std::string filePath = FILE_TEST_PATH; + SecurityOption setOption; + setOption.securityLabel = S3; + auto res = security->SetSecurityOption(filePath, setOption); + EXPECT_EQ(res, DBStatus::OK); + SecurityOption getOption; + res = security->GetSecurityOption(filePath, getOption); + EXPECT_EQ(res, DBStatus::OK); + EXPECT_EQ(getOption.securityLabel, S3); + EXPECT_EQ(getOption.securityFlag, SECE); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/sensitive_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/sensitive_test.cpp new file mode 100644 index 00000000..20105457 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/sensitive_test.cpp @@ -0,0 +1,138 @@ +/* + * 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 "sensitive.h" + +#include + +using namespace testing::ext; +using namespace OHOS::DistributedKv; +namespace OHOS::Test { +class SensitiveTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void SensitiveTest::SetUpTestCase(void) +{ +} + +void SensitiveTest::TearDownTestCase(void) +{ +} + +void SensitiveTest::SetUp(void) +{ +} + +void SensitiveTest::TearDown(void) +{ +} + +/** + * @tc.name: GetDeviceSecurityLevel001 + * @tc.desc: Test for GetDeviceSecurityLevel deviceId is empty. + * @tc.type: FUNC + */ +HWTEST_F(SensitiveTest, GetDeviceSecurityLevel001, TestSize.Level1) +{ + auto sensitive = std::make_shared(); + auto res = sensitive->GetDeviceSecurityLevel(); + EXPECT_EQ(res, DATA_SEC_LEVEL1); +} + +/** + * @tc.name: GetDeviceSecurityLevel002 + * @tc.desc: Test for GetDeviceSecurityLevel secruityLevel > DATA_SEC_LEVEL1. + * @tc.type: FUNC + */ +HWTEST_F(SensitiveTest, GetDeviceSecurityLevel002, TestSize.Level1) +{ + auto sensitive = std::make_shared(); + sensitive->securityLevel = DATA_SEC_LEVEL2; + auto res = sensitive->GetDeviceSecurityLevel(); + EXPECT_EQ(res, DATA_SEC_LEVEL2); +} + +/** + * @tc.name: Operator001 + * @tc.desc: Test for Operator securityLabel is NOT_SET. + * @tc.type: FUNC + */ +HWTEST_F(SensitiveTest, Operator001, TestSize.Level1) +{ + Sensitive sensitive; + DistributedDB::SecurityOption option; + option.securityLabel = DistributedDB::NOT_SET; + EXPECT_TRUE(sensitive >= option); +} + +/** + * @tc.name: Operator002 + * @tc.desc: Test for Operator securityLabel is S3. + * @tc.type: FUNC + */ +HWTEST_F(SensitiveTest, Operator002, TestSize.Level1) +{ + Sensitive sensitive; + DistributedDB::SecurityOption option; + option.securityLabel = DistributedDB::S3; + EXPECT_FALSE(sensitive >= option); +} + +/** + * @tc.name: Operator002 + * @tc.desc: Test for Operator securityLabel is S1. + * @tc.type: FUNC + */ +HWTEST_F(SensitiveTest, Operator003, TestSize.Level1) +{ + Sensitive sensitive; + DistributedDB::SecurityOption option; + option.securityLabel = DistributedDB::S1; + EXPECT_TRUE(sensitive >= option); +} + +/** + * @tc.name: Operator003 + * @tc.desc: Test for Operator securityLabel is S4. + * @tc.type: FUNC + */ +HWTEST_F(SensitiveTest, Operator004, TestSize.Level1) +{ + Sensitive sensitive; + sensitive.securityLevel = DATA_SEC_LEVEL2; + DistributedDB::SecurityOption option; + option.securityLabel = DistributedDB::S4; + EXPECT_FALSE(sensitive >= option); +} + +/** + * @tc.name: Operator004 + * @tc.desc: Test for Operator securityLabel is S1. + * @tc.type: FUNC + */ +HWTEST_F(SensitiveTest, Operator005, TestSize.Level1) +{ + Sensitive sensitive; + sensitive.securityLevel = DATA_SEC_LEVEL2; + DistributedDB::SecurityOption option; + option.securityLabel = DistributedDB::S1; + EXPECT_TRUE(sensitive >= option); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/session_manager_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/session_manager_test.cpp index 8031dc6c..f0813691 100644 --- a/datamgr_service/services/distributeddataservice/app/test/unittest/session_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/session_manager_test.cpp @@ -13,10 +13,20 @@ * limitations under the License. */ +#include "session_manager/session_manager.h" + +#include + +#include "access_check/app_access_check_config_manager.h" #include "accesstoken_kit.h" +#include "account_delegate_mock.h" +#include "auth_delegate_mock.h" #include "bootstrap.h" +#include "db_store_mock.h" #include "device_manager_adapter.h" -#include "kvstore_meta_manager.h" +#include "device_manager_adapter_mock.h" +#include "gtest/gtest.h" +#include "meta_data_manager_mock.h" #include "metadata/meta_data_manager.h" #include "metadata/store_meta_data.h" #include "nativetoken_kit.h" @@ -24,18 +34,27 @@ #include "session_manager/upgrade_manager.h" #include "token_setproc.h" #include "user_delegate.h" -#include "gtest/gtest.h" +#include "user_delegate_mock.h" +#include "utils/endian_converter.h" namespace { +using namespace testing; using namespace testing::ext; using namespace OHOS::DistributedKv; using namespace OHOS::DistributedData; +using namespace DistributedDB; using namespace OHOS; using namespace OHOS::Security::AccessToken; +using DeviceInfo = OHOS::AppDistributedKv::DeviceInfo; +using UserInfo = DistributedDB::UserInfo; +using AppMappingInfo = OHOS::DistributedData::AppAccessCheckConfigManager::AppMappingInfo; constexpr const char *PEER_DEVICE_ID = "PEER_DEVICE_ID"; +constexpr const char *DEFAULT_USERID = "0"; constexpr int PEER_USER_ID1 = 101; constexpr int PEER_USER_ID2 = 100; +constexpr int32_t USER_MAXID = 4; constexpr int METADATA_UID = 2000000; +static constexpr int32_t OH_OS_TYPE = 10; void GrantPermissionNative() { @@ -55,20 +74,51 @@ void GrantPermissionNative() uint64_t tokenId = GetAccessTokenId(&infoInstance); SetSelfTokenID(tokenId); AccessTokenKit::ReloadNativeTokenInfo(); - delete []perms; + delete[] perms; } class SessionManagerTest : public testing::Test { public: + void CreateUserStatus(std::vector &users) + { + for (int32_t i = 0; i < USER_MAXID; i++) { + UserStatus stat; + stat.id = i; + users.push_back(stat); + } + } + + static void CreateStoreMetaData(std::vector &datas, SessionPoint local) + { + StoreMetaData data; + data.appId = local.appId; + data.storeId = local.storeId; + data.bundleName = "com.test.session"; + StoreMetaData data1; + data1.appId = local.appId; + data1.storeId = "local.storeId"; + data1.bundleName = "com.test.session1"; + StoreMetaData data2; + data2.appId = "local.appId"; + data2.storeId = local.storeId; + data2.bundleName = "com.test.session2"; + StoreMetaData data3; + data3.appId = "local.appId"; + data3.storeId = "local.storeId"; + data3.bundleName = "com.test.session3"; + datas.push_back(data); + datas.push_back(data1); + datas.push_back(data2); + datas.push_back(data3); + } + static void SetUpTestCase() { + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); auto executors = std::make_shared(12, 5); Bootstrap::GetInstance().LoadComponents(); Bootstrap::GetInstance().LoadDirectory(); Bootstrap::GetInstance().LoadCheckers(); - KvStoreMetaManager::GetInstance().BindExecutor(executors); - KvStoreMetaManager::GetInstance().InitMetaParameter(); - KvStoreMetaManager::GetInstance().InitMetaListener(); DeviceManagerAdapter::GetInstance().Init(executors); // init peer device @@ -90,51 +140,203 @@ public: auto peerCapMetaKey = CapMetaRow::GetKeyFor(userMetaData.deviceId); MetaDataManager::GetInstance().SaveMeta({ peerCapMetaKey.begin(), peerCapMetaKey.end() }, capMetaData); - - StoreMetaData metaData; - metaData.bundleName = "ohos.test.demo"; - metaData.appId = "ohos.test.demo"; - metaData.storeId = "test_store"; - metaData.user = "100"; - metaData.deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; - metaData.tokenId = AccessTokenKit::GetHapTokenID(PEER_USER_ID2, "ohos.test.demo", 0); - metaData.uid = METADATA_UID; - metaData.storeType = 1; - MetaDataManager::GetInstance().SaveMeta(metaData.GetKey(), metaData); + InitSystemMetaData(); + InitNormalMetaData(); GrantPermissionNative(); } + static void TearDownTestCase() { auto peerUserMetaKey = UserMetaRow::GetKeyFor(PEER_DEVICE_ID); MetaDataManager::GetInstance().DelMeta(std::string(peerUserMetaKey.begin(), peerUserMetaKey.end())); auto peerCapMetaKey = CapMetaRow::GetKeyFor(PEER_DEVICE_ID); MetaDataManager::GetInstance().DelMeta(std::string(peerCapMetaKey.begin(), peerCapMetaKey.end())); - StoreMetaData metaData; - metaData.bundleName = "ohos.test.demo"; - metaData.appId = "ohos.test.demo"; - metaData.storeId = "test_store"; - metaData.user = "100"; - metaData.deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; - metaData.tokenId = AccessTokenKit::GetHapTokenID(PEER_USER_ID2, "ohos.test.demo", 0); - metaData.uid = METADATA_UID; - metaData.storeType = 1; - MetaDataManager::GetInstance().DelMeta(metaData.GetKey()); } + void SetUp() { + deviceManagerAdapterMock = std::make_shared(); + BDeviceManagerAdapter::deviceManagerAdapter = deviceManagerAdapterMock; + userDelegateMock = std::make_shared(); + BUserDelegate::userDelegate = userDelegateMock; + ConstructValidData(); + auto res = MetaDataManager::GetInstance().SaveMeta(systemMetaData_.GetKey(), systemMetaData_); + EXPECT_EQ(res, true); + res = MetaDataManager::GetInstance().SaveMeta(normalMetaData_.GetKey(), normalMetaData_); + EXPECT_EQ(res, true); } + void TearDown() { + deviceManagerAdapterMock = nullptr; + BDeviceManagerAdapter::deviceManagerAdapter = nullptr; + userDelegateMock = nullptr; + BUserDelegate::userDelegate = nullptr; + MetaDataManager::GetInstance().DelMeta(systemMetaData_.GetKey()); + MetaDataManager::GetInstance().DelMeta(normalMetaData_.GetKey()); + } + + void ConstructValidData() + { + const std::string storeId = "test_store"; + InitializeBuffer(); + ConstructRouteHead(storeId); + ConstructSessionDevicePair(); + ConstructSessionUserPair(); + ConstructSessionAppId(); + ConstructSessionStoreId(storeId); + + const size_t validlLen = sizeof(RouteHead) + sizeof(SessionDevicePair) + sizeof(SessionUserPair) + + sizeof(uint32_t) * 1 + sizeof(SessionAppId) + APP_STR_LEN + sizeof(SessionStoreId) + + storeId.size(); + validTotalLen = validlLen; + } + + static void InitSystemMetaData(); + static void InitNormalMetaData(); + static std::shared_ptr dbStoreMock_; + static StoreMetaData systemMetaData_; + static StoreMetaData normalMetaData_; + + static inline std::shared_ptr deviceManagerAdapterMock = nullptr; + static inline std::shared_ptr userDelegateMock = nullptr; + +private: + void InitializeBuffer() + { + memset_s(dataBuffer, BUFFER_SIZE, 0, BUFFER_SIZE); + ptr = dataBuffer; + remaining = BUFFER_SIZE; } + + void ConstructRouteHead(const std::string &storeId) + { + RouteHead head{}; + head.magic = HostToNet(RouteHead::MAGIC_NUMBER); + head.version = HostToNet(RouteHead::VERSION); + head.dataLen = HostToNet(sizeof(SessionDevicePair) + sizeof(SessionUserPair) + sizeof(uint32_t) * 1 + + sizeof(SessionAppId) + APP_STR_LEN + sizeof(SessionStoreId) + storeId.size()); + head.checkSum = 0; + + errno_t err = memcpy_s(ptr, remaining, &head, sizeof(RouteHead)); + ASSERT_EQ(err, 0) << "Failed to copy RouteHead"; + ptr += sizeof(RouteHead); + remaining -= sizeof(RouteHead); + } + + void ConstructSessionDevicePair() + { + SessionDevicePair devPair{ .sourceId = "PEER_DEVICE_ID", .targetId = "PEER_DEVICE_ID" }; + constexpr size_t DEV_ID_SIZE = sizeof(devPair.sourceId); + + errno_t err = memset_s(devPair.sourceId, DEV_ID_SIZE, 'A', DEV_ID_SIZE - 1); + ASSERT_EQ(err, 0) << "Failed to init sourceId"; + devPair.sourceId[DEV_ID_SIZE - 1] = '\0'; + + err = memset_s(devPair.targetId, DEV_ID_SIZE, 'B', DEV_ID_SIZE - 1); + ASSERT_EQ(err, 0) << "Failed to init targetId"; + devPair.targetId[DEV_ID_SIZE - 1] = '\0'; + + err = memcpy_s(ptr, remaining, &devPair, sizeof(SessionDevicePair)); + ASSERT_EQ(err, 0) << "Failed to copy SessionDevicePair"; + ptr += sizeof(SessionDevicePair); + remaining -= sizeof(SessionDevicePair); + } + + void ConstructSessionUserPair() + { + SessionUserPair userPair{}; + userPair.sourceUserId = HostToNet(100U); + userPair.targetUserCount = HostToNet(1U); + + errno_t err = memcpy_s(ptr, remaining, &userPair, sizeof(SessionUserPair)); + ASSERT_EQ(err, 0) << "Failed to copy SessionUserPair"; + ptr += sizeof(SessionUserPair); + remaining -= sizeof(SessionUserPair); + + uint32_t targetUser = HostToNet(200U); + err = memcpy_s(ptr, remaining, &targetUser, sizeof(uint32_t)); + ASSERT_EQ(err, 0) << "Failed to copy targetUser"; + ptr += sizeof(uint32_t); + remaining -= sizeof(uint32_t); + } + + void ConstructSessionAppId() + { + SessionAppId appId{}; + const char *appStr = "test"; + appId.len = HostToNet(static_cast(APP_STR_LEN)); + + errno_t err = memcpy_s(ptr, remaining, &appId, sizeof(SessionAppId)); + ASSERT_EQ(err, 0) << "Failed to copy SessionAppId"; + ptr += sizeof(SessionAppId); + remaining -= sizeof(SessionAppId); + + err = memcpy_s(ptr, remaining, appStr, APP_STR_LEN); + ASSERT_EQ(err, 0) << "Failed to copy appId data"; + ptr += APP_STR_LEN; + remaining -= APP_STR_LEN; + } + + void ConstructSessionStoreId(const std::string &storeId) + { + SessionStoreId storeIdHeader{}; + storeIdHeader.len = HostToNet(static_cast(storeId.size())); + + errno_t err = memcpy_s(ptr, remaining, &storeIdHeader, sizeof(SessionStoreId)); + ASSERT_EQ(err, 0) << "Failed to copy storeId length"; + ptr += sizeof(SessionStoreId); + remaining -= sizeof(SessionStoreId); + + err = memcpy_s(ptr, remaining, storeId.c_str(), storeId.size()); + ASSERT_EQ(err, 0) << "Failed to copy storeId data"; + ptr += storeId.size(); + remaining -= storeId.size(); + } + + size_t validTotalLen; + uint8_t dataBuffer[1024]; + static constexpr size_t APP_STR_LEN = 4; + uint8_t *ptr = dataBuffer; + size_t remaining = BUFFER_SIZE; + static constexpr size_t BUFFER_SIZE = sizeof(dataBuffer); }; +std::shared_ptr SessionManagerTest::dbStoreMock_ = std::make_shared(); +StoreMetaData SessionManagerTest::systemMetaData_; +StoreMetaData SessionManagerTest::normalMetaData_; + +void SessionManagerTest::InitNormalMetaData() +{ + normalMetaData_.bundleName = "ohos.test.demo"; + normalMetaData_.appId = "ohos.test.demo"; + normalMetaData_.storeId = "test_store"; + normalMetaData_.user = "100"; + normalMetaData_.deviceId = "local_device"; + normalMetaData_.tokenId = AccessTokenKit::GetHapTokenID(PEER_USER_ID2, "ohos.test.demo", 0); + normalMetaData_.uid = METADATA_UID; + normalMetaData_.storeType = 1; +} + +void SessionManagerTest::InitSystemMetaData() +{ + systemMetaData_.bundleName = "ohos.test.demo"; + systemMetaData_.appId = "ohos.test.demo"; + systemMetaData_.storeId = "test_store"; + systemMetaData_.user = DEFAULT_USERID; + systemMetaData_.deviceId = "local_device"; + systemMetaData_.tokenId = AccessTokenKit::GetHapTokenID(PEER_USER_ID2, "ohos.test.demo", 0); + systemMetaData_.uid = METADATA_UID; + systemMetaData_.storeType = 1; +} + /** -* @tc.name: PackAndUnPack01 -* @tc.desc: test get db dir -* @tc.type: FUNC -* @tc.require: -* @tc.author: illybyy -*/ + * @tc.name: PackAndUnPack01 + * @tc.desc: test get db dir + * @tc.type: FUNC + * @tc.require: + * @tc.author: illybyy + */ HWTEST_F(SessionManagerTest, PackAndUnPack01, TestSize.Level2) { const DistributedDB::ExtendInfo info = { @@ -151,10 +353,584 @@ HWTEST_F(SessionManagerTest, PackAndUnPack01, TestSize.Level2) std::vector users; auto recvHandler = RouteHeadHandlerImpl::Create({}); ASSERT_NE(recvHandler, nullptr); - uint32_t parseSize = 1; - recvHandler->ParseHeadDataLen(data.get(), routeHeadSize, parseSize); + uint32_t parseSize = 0; + std::string device = ""; + recvHandler->ParseHeadDataLen(data.get(), routeHeadSize, parseSize, device); EXPECT_EQ(routeHeadSize, parseSize); recvHandler->ParseHeadDataUser(data.get(), routeHeadSize, "", users); ASSERT_EQ(users.size(), 0); } + +/** + * @tc.name: GetHeadDataSize_Test1 + * @tc.desc: test appId equal processLabel. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test1, TestSize.Level1) +{ + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t headSize = 0; + routeHeadHandlerImpl.appId_ = Bootstrap::GetInstance().GetProcessLabel(); + auto status = routeHeadHandlerImpl.GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::OK); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: GetHeadDataSize_Test2 + * @tc.desc: test appId not equal processLabel. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test2, TestSize.Level1) +{ + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t headSize = 0; + routeHeadHandlerImpl.appId_ = "otherAppId"; + auto status = routeHeadHandlerImpl.GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::DB_ERROR); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: GetHeadDataSize_Test3 + * @tc.desc: test devInfo.osType equal OH_OS_TYPE, appId not equal processLabel. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test3, TestSize.Level1) +{ + DeviceInfo deviceInfo; + deviceInfo.osType = OH_OS_TYPE; + EXPECT_CALL(*deviceManagerAdapterMock, GetDeviceInfo(_)).WillRepeatedly(Return(deviceInfo)); + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t headSize = 0; + routeHeadHandlerImpl.appId_ = "otherAppId"; + auto status = routeHeadHandlerImpl.GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::DB_ERROR); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: GetHeadDataSize_Test4 + * @tc.desc: test GetHeadDataSize + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test4, TestSize.Level1) +{ + DeviceInfo deviceInfo; + deviceInfo.osType = OH_OS_TYPE; + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + EXPECT_CALL(*deviceManagerAdapterMock, GetDeviceInfo(_)).WillRepeatedly(Return(deviceInfo)); + + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test_store", .userId = DEFAULT_USERID, .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + + auto userId = sendHandler->GetTargetUserId(); + EXPECT_EQ(userId, "0"); + + std::vector userStatus; + UserStatus userStat1; + UserStatus userStat2; + UserStatus userStat3; + userStat1.id = 1; + userStat2.id = 2; + userStat3.id = 3; + userStatus.push_back(userStat1); + userStatus.push_back(userStat2); + userStatus.push_back(userStat3); + EXPECT_CALL(*userDelegateMock, GetRemoteUserStatus(_)).WillRepeatedly(Return(userStatus)); + + uint32_t headSize = 0; + auto status = sendHandler->GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::OK); + EXPECT_EQ(headSize, 208); + + uint32_t routeHeadSize = 10; + std::unique_ptr data = std::make_unique(routeHeadSize); + status = sendHandler->FillHeadData(data.get(), routeHeadSize, routeHeadSize); + EXPECT_EQ(status, DistributedDB::DB_ERROR); +} + +/** + * @tc.name: GetHeadDataSize_Test5 + * @tc.desc: test device is not OH_OS_TYPE and appId is empty. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test5, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillOnce(Return(true)).WillOnce(Return(false)); + const DistributedDB::ExtendInfo info = { + .appId = "", .storeId = "test_store", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + uint32_t headSize; + auto status = sendHandler->GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::DB_ERROR); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: GetHeadDataSize_Test6 + * @tc.desc: test device != OH_OS_TYPE && appId.isNotEmpty && appId.isTrusted. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test6, TestSize.Level1) +{ + const DistributedDB::ExtendInfo info = { + .appId = "com.test.demo", .storeId = "test", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + std::vector mapper = { { .appId = info.appId, .bundleName = info.appId } }; + AppAccessCheckConfigManager::GetInstance().Initialize(mapper); + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + uint32_t headSize; + auto status = sendHandler->GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::OK); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: GetHeadDataSize_Test7 + * @tc.desc: test GetCapability is failed. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test7, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test", .userId = "100", .dstTarget = "10" + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + uint32_t headSize; + auto status = sendHandler->GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::DB_ERROR); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: GetHeadDataSize_Test8 + * @tc.desc: test peerCap.version != INALID_VERSION && session is invalid. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test8, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + uint32_t headSize; + auto status = sendHandler->GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::DB_ERROR); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: GetHeadDataSize_Test9 + * @tc.desc: test peerCap.version != INALID_VERSION && session is valid. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, GetHeadDataSize_Test9, TestSize.Level1) +{ + DeviceInfo deviceInfo; + deviceInfo.uuid = PEER_DEVICE_ID; + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + EXPECT_CALL(*deviceManagerAdapterMock, GetLocalDevice()).WillRepeatedly(Return(deviceInfo)); + const DistributedDB::ExtendInfo info = { + .appId = "test", .storeId = "test_store", .userId = DEFAULT_USERID, .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + uint32_t headSize; + auto status = sendHandler->GetHeadDataSize(headSize); + EXPECT_EQ(status, DistributedDB::OK); + EXPECT_EQ(headSize, 200); + + uint32_t totalLen = 300; + std::unique_ptr data = std::make_unique(totalLen); + status = sendHandler->FillHeadData(data.get(), headSize, totalLen); + EXPECT_EQ(status, DistributedDB::OK); + uint32_t parseHeadSize; + auto res = sendHandler->ParseHeadDataLen(data.get(), totalLen, parseHeadSize, info.storeId); + EXPECT_EQ(res, true); + EXPECT_EQ(parseHeadSize, 200); + + std::vector userInfos; + std::string label; + res = sendHandler->ParseHeadDataUser(data.get(), totalLen, label, userInfos); + EXPECT_EQ(res, true); + EXPECT_EQ(label, ""); + EXPECT_EQ(userInfos.size(), 1); +} + +/** + * @tc.name: ParseHeadDataLenTest001 + * @tc.desc: test ParseHeadDataLen data is nullptr. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, ParseHeadDataLenTest001, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test_store", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + + uint32_t totalLen = 10; + uint32_t headSize; + std::string device = "device"; + + bool result = sendHandler->ParseHeadDataLen(nullptr, totalLen, headSize, device); + EXPECT_EQ(result, false); + + auto status = sendHandler->FillHeadData(nullptr, headSize, headSize); + EXPECT_EQ(status, DistributedDB::DB_ERROR); +} + +/** + * @tc.name: ParseHeadDataLenTest002 + * @tc.desc: test ParseHeadDataLen totalLen < sizeof(RouteHead). + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, ParseHeadDataLenTest002, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test_store", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + + uint32_t totalLen = 10; + uint32_t headSize; + std::string device = "device"; + + bool result = sendHandler->ParseHeadDataLen(dataBuffer, totalLen, headSize, device); + EXPECT_EQ(result, false); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: ParseHeadDataLenTest003 + * @tc.desc: test ParseHeadDataLen totalLen - sizeof(RouteHead) < routeHead.dataLen. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, ParseHeadDataLenTest003, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test_store", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + + uint32_t totalLen = 20; + uint32_t headSize; + std::string device = "device"; + + bool result = sendHandler->ParseHeadDataLen(dataBuffer, totalLen, headSize, device); + EXPECT_EQ(result, false); + EXPECT_EQ(headSize, 0); +} + +/** + * @tc.name: ParseHeadDataUserTest001 + * @tc.desc: test parse null data. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, ParseHeadDataUserTest001, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test_store", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + + auto userId = sendHandler->GetTargetUserId(); + EXPECT_EQ(userId, ""); + uint32_t totalLen = 10; + std::string label = "testLabel"; + std::vector userInfos; + + bool result = sendHandler->ParseHeadDataUser(nullptr, totalLen, label, userInfos); + + EXPECT_FALSE(result); + EXPECT_EQ(userInfos.size(), 0); +} + +/** + * @tc.name: ParseHeadDataUserTest002 + * @tc.desc: test totalLen < sizeof(RouteHead). + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, ParseHeadDataUserTest002, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test_store", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + + uint8_t data[10] = { 0 }; + std::string label = "testLabel"; + std::vector userInfos; + + bool result = sendHandler->ParseHeadDataUser(data, sizeof(RouteHead) - 1, label, userInfos); + + EXPECT_FALSE(result); + EXPECT_EQ(userInfos.size(), 0); +} + +/** + * @tc.name: ParseHeadDataUserTest003 + * @tc.desc: test totalLen < sizeof(RouteHead). + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, ParseHeadDataUserTest003, TestSize.Level1) +{ + EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType(_)).WillRepeatedly(Return(true)); + const DistributedDB::ExtendInfo info = { + .appId = "otherAppId", .storeId = "test_store", .userId = "100", .dstTarget = PEER_DEVICE_ID + }; + auto sendHandler = RouteHeadHandlerImpl::Create(info); + ASSERT_NE(sendHandler, nullptr); + + uint8_t data[10] = { 0 }; + std::string label = "testLabel"; + std::vector userInfos; + + RouteHead head = { 0 }; + head.version = RouteHead::VERSION; + head.dataLen = static_cast(sizeof(data) - sizeof(RouteHead)); + + bool result = sendHandler->ParseHeadDataUser(data, sizeof(RouteHead), label, userInfos); + + EXPECT_FALSE(result); + EXPECT_EQ(userInfos.size(), 0); +} + +/** + * @tc.name: PackDataTest1 + * @tc.desc: test headSize_ > totalLen. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, PackDataTest1, TestSize.Level1) +{ + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + routeHeadHandlerImpl.headSize_ = 1; + uint32_t totalLen = 0; + EXPECT_EQ(routeHeadHandlerImpl.PackData(dataBuffer, totalLen), false); +} + +/** + * @tc.name: PackDataTest2 + * @tc.desc: test headSize_ < sizeof(RouteHead). + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, PackDataTest2, TestSize.Level1) +{ + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + routeHeadHandlerImpl.headSize_ = 10; + uint32_t totalLen = 11; + EXPECT_EQ(routeHeadHandlerImpl.PackData(dataBuffer, totalLen), false); +} + +/** + * @tc.name: UnPackData_InvalidMagic + * @tc.desc: test invalid magic. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, UnPackData_InvalidMagic, TestSize.Level1) +{ + RouteHead *head = reinterpret_cast(dataBuffer); + head->magic = 0xFFFF; + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t unpackedSize; + EXPECT_FALSE(routeHeadHandlerImpl.UnPackData(dataBuffer, validTotalLen, unpackedSize)); +} + +/** + * @tc.name: UnPackData_VersionMismatch + * @tc.desc: test version mismatch. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, UnPackData_VersionMismatch, TestSize.Level1) +{ + RouteHead *head = reinterpret_cast(dataBuffer); + head->version = 0x00; + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t unpackedSize; + EXPECT_FALSE(routeHeadHandlerImpl.UnPackData(dataBuffer, validTotalLen, unpackedSize)); +} + +/** + * @tc.name: UnPackDataBody01 + * @tc.desc: test leftSize < sizeof(SessionDevicePair). + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, UnPackDataBody01, TestSize.Level1) +{ + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t totalLen = 100; + auto res = routeHeadHandlerImpl.UnPackDataBody(dataBuffer, totalLen); + EXPECT_EQ(res, false); +} + +/** + * @tc.name: UnPackDataBody02 + * @tc.desc: test leftSize < sizeof(SessionUserPair). + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, UnPackDataBody02, TestSize.Level1) +{ + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t totalLen = 133; + auto res = routeHeadHandlerImpl.UnPackDataBody(dataBuffer, totalLen); + EXPECT_EQ(res, false); +} + +/** + * @tc.name: UnPackDataBody03 + * @tc.desc: test leftSize < userPairSize. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, UnPackDataBody03, TestSize.Level1) +{ + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t totalLen = 136; + auto res = routeHeadHandlerImpl.UnPackDataBody(dataBuffer, totalLen); + EXPECT_EQ(res, false); +} + +/** + * @tc.name: UnPackDataBody05 + * @tc.desc: test leftSize < sizeof(SessionAppId). + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, UnPackDataBody05, TestSize.Level1) +{ + ExtendInfo info; + RouteHeadHandlerImpl routeHeadHandlerImpl(info); + uint32_t totalLen = 400; + auto res = routeHeadHandlerImpl.UnPackDataBody(dataBuffer, totalLen); + EXPECT_EQ(res, false); +} + +/** + * @tc.name: ShouldAddSystemUserWhenLocalUserIdIsSystem + * @tc.desc: test GetSession. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, ShouldAddSystemUserWhenLocalUserIdIsSystem, TestSize.Level1) +{ + SessionPoint local; + local.userId = UserDelegate::SYSTEM_USER; + local.appId = "ohos.test.demo"; + local.deviceId = "local_device"; + local.storeId = "test_store"; + + std::vector users; + CreateUserStatus(users); + EXPECT_CALL(*userDelegateMock, GetRemoteUserStatus(_)).WillOnce(Return(users)); + EXPECT_CALL(AuthHandlerMock::GetInstance(), CheckAccess(_, _, _, _)) + .WillOnce(Return(std::pair(true, true))) + .WillOnce(Return(std::pair(true, false))) + .WillOnce(Return(std::pair(false, true))) + .WillOnce(Return(std::pair(false, false))); + Session session = SessionManager::GetInstance().GetSession(local, local.deviceId); + ASSERT_EQ(2, session.targetUserIds.size()); + EXPECT_EQ(UserDelegate::SYSTEM_USER, session.targetUserIds[0]); +} + +/** + * @tc.name: ShouldReturnEarlyWhenGetSendAuthParamsFails + * @tc.desc: test GetSession. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, ShouldReturnEarlyWhenGetSendAuthParamsFails, TestSize.Level1) +{ + SessionPoint local; + local.userId = 100; + local.appId = "test_app"; + local.deviceId = "local_device"; + EXPECT_CALL(*userDelegateMock, GetRemoteUserStatus(_)).WillOnce(Return(std::vector{})); + + Session session = SessionManager::GetInstance().GetSession(local, "target_device"); + + EXPECT_TRUE(session.targetUserIds.empty()); +} + +/** + * @tc.name: CheckSession + * @tc.desc: test CheckSession. + * @tc.type: FUNC + * @tc.author: guochao + */ +HWTEST_F(SessionManagerTest, CheckSession, TestSize.Level1) +{ + SessionPoint localSys; + localSys.userId = UserDelegate::SYSTEM_USER; + localSys.appId = "ohos.test.demo"; + localSys.deviceId = "local_device"; + localSys.storeId = "test_store"; + SessionPoint localNormal; + localNormal.userId = 100; + localNormal.appId = "ohos.test.demo"; + localNormal.deviceId = "local_device"; + localNormal.storeId = "test_store"; + localNormal.accountId = "test_account"; + SessionPoint invalidPoint; + EXPECT_CALL(AuthHandlerMock::GetInstance(), CheckAccess(_, _, _, _)) + .WillOnce(Return(std::pair(false, true))) + .WillOnce(Return(std::pair(true, false))); + bool result = SessionManager::GetInstance().CheckSession(invalidPoint, invalidPoint, true); + EXPECT_FALSE(result); + result = SessionManager::GetInstance().CheckSession(localSys, localNormal, true); + EXPECT_FALSE(result); + result = SessionManager::GetInstance().CheckSession(localNormal, localSys, true); + EXPECT_TRUE(result); +} } // namespace \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/upgrade_manager_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/upgrade_manager_test.cpp new file mode 100644 index 00000000..70164b93 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/upgrade_manager_test.cpp @@ -0,0 +1,141 @@ +/* + * 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 "upgrade_manager.h" + +#include + +#include "device_manager_adapter.h" +#include "metadata/meta_data_manager.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::DistributedData; + +static constexpr size_t THREAD_MIN = 0; +static constexpr size_t THREAD_MAX = 2; +static constexpr const char* REMOTE_DEVICE = "0123456789ABCDEF"; + +class UpgradeManagerTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void) {}; + void SetUp() {}; + void TearDown() {}; + + static std::shared_ptr executors_; + static std::string localDevice_; +}; + +std::shared_ptr UpgradeManagerTest::executors_; +std::string UpgradeManagerTest::localDevice_; + +void UpgradeManagerTest::SetUpTestCase(void) +{ + localDevice_ = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + executors_ = std::make_shared(THREAD_MAX, THREAD_MIN); + MetaDataManager::GetInstance().Init(executors_); + UpgradeManager::GetInstance().Init(executors_); + sleep(1); +} + +/** +* @tc.name: GetCapabilityTest001 +* @tc.desc: get local device capability +* @tc.type: FUNC +*/ +HWTEST_F(UpgradeManagerTest, GetCapabilityTest001, TestSize.Level1) +{ + bool result = false; + auto capMeta = UpgradeManager::GetInstance().GetCapability(localDevice_, result); + ASSERT_EQ(result, true); + ASSERT_EQ(capMeta.version, CapMetaData::CURRENT_VERSION); + ASSERT_EQ(capMeta.deviceId, localDevice_); +} + +/** +* @tc.name: GetCapabilityTest002 +* @tc.desc: get non-exist remote device capability +* @tc.type: FUNC +*/ +HWTEST_F(UpgradeManagerTest, GetCapabilityTest002, TestSize.Level1) +{ + bool result = true; + auto capMeta = UpgradeManager::GetInstance().GetCapability(REMOTE_DEVICE, result); + ASSERT_EQ(result, false); + ASSERT_EQ(capMeta.version, CapMetaData::INVALID_VERSION); + ASSERT_EQ(capMeta.deviceId, ""); +} + +/** +* @tc.name: GetCapabilityTest003 +* @tc.desc: get remote device capability by callback of meta save-update-delete +* @tc.type: FUNC +*/ +HWTEST_F(UpgradeManagerTest, GetCapabilityTest003, TestSize.Level1) +{ + CapMetaData capMetaData; + capMetaData.version = CapMetaData::CURRENT_VERSION; + capMetaData.deviceId = REMOTE_DEVICE; + auto capKey = CapMetaRow::GetKeyFor(REMOTE_DEVICE); + (void)MetaDataManager::GetInstance().SaveMeta({ capKey.begin(), capKey.end() }, capMetaData); + sleep(1); + + bool result = false; + auto capMeta = UpgradeManager::GetInstance().GetCapability(REMOTE_DEVICE, result); + ASSERT_EQ(result, true); + ASSERT_EQ(capMeta.version, capMetaData.version); + ASSERT_EQ(capMeta.deviceId, REMOTE_DEVICE); + + capMetaData.version = CapMetaData::INVALID_VERSION; + (void)MetaDataManager::GetInstance().UpdateMeta({ capKey.begin(), capKey.end() }, capMetaData); + sleep(1); + + result = false; + capMeta = UpgradeManager::GetInstance().GetCapability(REMOTE_DEVICE, result); + ASSERT_EQ(result, true); + ASSERT_EQ(capMeta.version, capMetaData.version); + ASSERT_EQ(capMeta.deviceId, REMOTE_DEVICE); + + (void)MetaDataManager::GetInstance().DeleteMeta({ capKey.begin(), capKey.end() }, capMetaData); + sleep(1); + + capMeta = UpgradeManager::GetInstance().GetCapability(REMOTE_DEVICE, result); + ASSERT_EQ(result, false); + ASSERT_EQ(capMeta.version, CapMetaData::INVALID_VERSION); + ASSERT_EQ(capMeta.deviceId, ""); +} + +/** +* @tc.name: GetCapabilityTest004 +* @tc.desc: get remote device capability by meta store +* @tc.type: FUNC +*/ +HWTEST_F(UpgradeManagerTest, GetCapabilityTest004, TestSize.Level1) +{ + MetaDataManager::GetInstance().UnSubscribe(); + CapMetaData capMetaData; + capMetaData.version = CapMetaData::CURRENT_VERSION; + capMetaData.deviceId = REMOTE_DEVICE; + auto capKey = CapMetaRow::GetKeyFor(REMOTE_DEVICE); + (void)MetaDataManager::GetInstance().SaveMeta({ capKey.begin(), capKey.end() }, capMetaData); + + bool result = false; + auto capMeta = UpgradeManager::GetInstance().GetCapability(REMOTE_DEVICE, result); + ASSERT_EQ(result, true); + ASSERT_EQ(capMeta.version, capMetaData.version); + ASSERT_EQ(capMeta.deviceId, REMOTE_DEVICE); +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/BUILD.gn index 96970573..fc66642e 100644 --- a/datamgr_service/services/distributeddataservice/framework/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/framework/BUILD.gn @@ -21,12 +21,7 @@ config("module_config") { visibility = [ ":*" ] include_dirs = [ "include", - "include/utils", "${data_service_path}/adapter/include", - "${kv_store_path}/interfaces/innerkits/distributeddata/include", - "${kv_store_common_path}", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/include/", ] } @@ -34,10 +29,6 @@ config("module_public_config") { visibility = [ ":*" ] include_dirs = [ "include", - "${data_service_path}/framework/include/account", - "${data_service_path}/framework/include/dfx", - "${data_service_path}/framework/include/network", - "${kv_store_common_path}", ] } @@ -52,6 +43,7 @@ ohos_shared_library("distributeddatasvcfwk") { } sources = [ "account/account_delegate.cpp", + "access_check/app_access_check_config_manager.cpp", "app_id_mapping/app_id_mapping_config_manager.cpp", "backuprule/backup_rule_manager.cpp", "changeevent/remote_change_event.cpp", @@ -76,6 +68,9 @@ ohos_shared_library("distributeddatasvcfwk") { "cloud/sync_event.cpp", "cloud/sync_strategy.cpp", "communication/connect_manager.cpp", + "crypto/crypto_manager.cpp", + "device_manager/device_manager_delegate.cpp", + "device_sync_app/device_sync_app_manager.cpp", "dfx/reporter.cpp", "directory/directory_manager.cpp", "dump/dump_manager.cpp", @@ -92,6 +87,7 @@ ohos_shared_library("distributeddatasvcfwk") { "metadata/matrix_meta_data.cpp", "metadata/meta_data.cpp", "metadata/meta_data_manager.cpp", + "metadata/object_user_meta_data.cpp", "metadata/secret_key_meta_data.cpp", "metadata/store_debug_info.cpp", "metadata/store_meta_data.cpp", @@ -124,15 +120,11 @@ ohos_shared_library("distributeddatasvcfwk") { "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-fdata-sections", "-ffunction-sections", - "-fstack-protector-strong", ] - ldflags = [ "-Wl,-z,relro,-z,now,--gc-sections" ] + ldflags = [ "-Wl,--gc-sections" ] - cflags_cc = [ - "-fvisibility=hidden", - "-fstack-protector-strong", - ] + cflags_cc = [ "-fvisibility=hidden" ] configs = [ ":module_config" ] @@ -143,8 +135,11 @@ ohos_shared_library("distributeddatasvcfwk") { "c_utils:utils", "common_event_service:cesfwk_innerkits", "hilog:libhilog", + "huks:libhukssdk", "json:nlohmann_json_static", "openssl:libcrypto_shared", + "kv_store:datamgr_common", + "kv_store:distributeddb", ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt b/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt index 6b9b30cf..e6e0e711 100644 --- a/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/framework/CMakeLists.txt @@ -4,12 +4,14 @@ project(svcFwk) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -fno-rtti -fvisibility=default -D_GNU_SOURCE") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -fPIC -fpic -ffunction-sections -D_GLIBC_MOCK") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--no-as-needed -ldl") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--no-as-needed -ldl -D__CJSON_USE_INT64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=0 -fpermissive -Wattributes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") set(MOCK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../mock") set(KV_STORE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../kv_store") +add_definitions(-D__CJSON_USE_INT64) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/access_check svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/account svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/app_id_mapping svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/backuprule svcFwkSrc) @@ -17,7 +19,10 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/changeevent svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/checker svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/cloud svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/communication svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/crypto svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/device_manager svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/directory svcFwkSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/device_sync_app svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/dfx svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/dump svcFwkSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/eventcenter svcFwkSrc) @@ -37,7 +42,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../relational_store/int include(${MOCK_DIR}/include/CMakeLists.txt OPTIONAL) include(${KV_STORE_DIR}/interfaces/CMakeLists.txt OPTIONAL) -set(links secure mock) +set(links secure mock distributeddb) set(LIBRARY_OUTPUT_PATH "${PROJECT_BINARY_DIR}/../../../../") add_library(svcFwk SHARED ${svcFwkSrc}) target_link_libraries(svcFwk ${links}) diff --git a/datamgr_service/services/distributeddataservice/framework/access_check/app_access_check_config_manager.cpp b/datamgr_service/services/distributeddataservice/framework/access_check/app_access_check_config_manager.cpp new file mode 100644 index 00000000..7d5b5f9d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/access_check/app_access_check_config_manager.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. + */ + +#define LOG_TAG "AppAccessCheckConfigManager" +#include "access_check/app_access_check_config_manager.h" +#include "log_print.h" +#include "utils/anonymous.h" + +namespace OHOS::DistributedData { +AppAccessCheckConfigManager &AppAccessCheckConfigManager::GetInstance() +{ + static AppAccessCheckConfigManager instance; + return instance; +} + +void AppAccessCheckConfigManager::Initialize(const std::vector &mapper) +{ + for (const auto &info : mapper) { + appMapper_.insert_or_assign(info.bundleName, info.appId); + } +} + +bool AppAccessCheckConfigManager::IsTrust(const std::string &appId) +{ + auto it = appMapper_.find(appId); + if (it != appMapper_.end() && (it->second == appId)) { + return true; + } + ZLOGE("check access failed, appId:%{public}s", Anonymous::Change(appId).c_str()); + return false; +} + +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/account/account_delegate.cpp b/datamgr_service/services/distributeddataservice/framework/account/account_delegate.cpp index 2b77557d..6ef95954 100644 --- a/datamgr_service/services/distributeddataservice/framework/account/account_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/framework/account/account_delegate.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "account_delegate.h" +#include "account/account_delegate.h" namespace OHOS { namespace DistributedData { diff --git a/datamgr_service/services/distributeddataservice/framework/app_id_mapping/app_id_mapping_config_manager.cpp b/datamgr_service/services/distributeddataservice/framework/app_id_mapping/app_id_mapping_config_manager.cpp index 3d03d524..2f903bbb 100644 --- a/datamgr_service/services/distributeddataservice/framework/app_id_mapping/app_id_mapping_config_manager.cpp +++ b/datamgr_service/services/distributeddataservice/framework/app_id_mapping/app_id_mapping_config_manager.cpp @@ -40,4 +40,13 @@ std::pair AppIdMappingConfigManager::Convert(const std return std::make_pair(it->second, "default"); } + +std::string AppIdMappingConfigManager::Convert(const std::string &appId) +{ + auto it = toDstMapper_.find(appId); + if (it == toDstMapper_.end()) { + return appId; + } + return it->second; +} } // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/checker/checker_manager.cpp b/datamgr_service/services/distributeddataservice/framework/checker/checker_manager.cpp index e02f50c6..739ff5ce 100644 --- a/datamgr_service/services/distributeddataservice/framework/checker/checker_manager.cpp +++ b/datamgr_service/services/distributeddataservice/framework/checker/checker_manager.cpp @@ -47,6 +47,26 @@ void CheckerManager::RegisterPlugin(const std::string &checker, std::functionDeleteCache(bundleName, user, index); + } +} + +void CheckerManager::ClearCache() +{ + for (auto &[name, checker] : checkers_) { + if (checker == nullptr) { + continue; + } + checker->ClearCache(); + } +} + std::string CheckerManager::GetAppId(const StoreInfo &info) { for (auto &[name, checker] : checkers_) { diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp index 86347588..3d916243 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp @@ -40,14 +40,14 @@ int32_t CloudDB::BatchDelete(const std::string &table, VBuckets &extends) return E_NOT_SUPPORT; } -std::shared_ptr CloudDB::Query(const std::string &table, const VBucket &extend) +std::pair> CloudDB::Query(const std::string &table, const VBucket &extend) { - return nullptr; + return { E_NOT_SUPPORT, nullptr }; } -std::shared_ptr CloudDB::Query(GenQuery &query, const VBucket &extend) +std::pair> CloudDB::Query(GenQuery &query, const VBucket &extend) { - return nullptr; + return { E_NOT_SUPPORT, nullptr }; } int32_t CloudDB::PreSharing(const std::string &table, VBuckets &extend) diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp index 2841cf0b..5d718ee7 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp @@ -87,4 +87,9 @@ bool CloudServer::IsSupportCloud(int32_t userId) { return false; } + +bool CloudServer::CloudDriverUpdated(const std::string &bundleName) +{ + return false; +} } // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp index 7844058a..273fc6b4 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp @@ -23,6 +23,7 @@ bool SchemaMeta::Marshal(Serializable::json &node) const SetValue(node[GET_NAME(version)], version); SetValue(node[GET_NAME(bundleName)], bundleName); SetValue(node[GET_NAME(databases)], databases); + SetValue(node[GET_NAME(e2eeEnable)], e2eeEnable); return true; } @@ -35,6 +36,7 @@ bool SchemaMeta::Unmarshal(const Serializable::json &node) GetValue(node, GET_NAME(bundleName), bundleName); GetValue(node, GET_NAME(databases), databases); GetValue(node, GET_NAME(dbSchema), databases); + GetValue(node, GET_NAME(e2eeEnable), e2eeEnable); return true; } diff --git a/datamgr_service/services/distributeddataservice/framework/communication/connect_manager.cpp b/datamgr_service/services/distributeddataservice/framework/communication/connect_manager.cpp index 74f8f70a..d63ad334 100644 --- a/datamgr_service/services/distributeddataservice/framework/communication/connect_manager.cpp +++ b/datamgr_service/services/distributeddataservice/framework/communication/connect_manager.cpp @@ -129,9 +129,10 @@ void ConnectManager::OnDestory() { } -int32_t ConnectManager::ApplyConnect(__attribute__((unused)) const std::string &networkId, ConnectTask task) +int32_t ConnectManager::ApplyConnect(__attribute__((unused)) const std::string &networkId, + __attribute__((unused)) ApplyTask applyTask, ConnectTask connectTask) { - task(); + connectTask(); return 0; } } // OHOS::AppDistributedKv \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/crypto/src/crypto_manager.cpp b/datamgr_service/services/distributeddataservice/framework/crypto/crypto_manager.cpp similarity index 62% rename from datamgr_service/services/distributeddataservice/service/crypto/src/crypto_manager.cpp rename to datamgr_service/services/distributeddataservice/framework/crypto/crypto_manager.cpp index d36f34cb..9db85ede 100644 --- a/datamgr_service/services/distributeddataservice/service/crypto/src/crypto_manager.cpp +++ b/datamgr_service/services/distributeddataservice/framework/crypto/crypto_manager.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ #define LOG_TAG "CryptoManager" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include #include @@ -23,7 +23,13 @@ #include "log_print.h" #include "metadata/meta_data_manager.h" #include "securec.h" + namespace OHOS::DistributedData { +static constexpr int32_t NONCE_SIZE = 12; +static constexpr const char *ROOT_KEY_ALIAS = "distributed_db_root_key"; +static constexpr const char *HKS_BLOB_TYPE_NONCE = "Z5s0Bo571KoqwIi6"; +static constexpr const char *HKS_BLOB_TYPE_AAD = "distributeddata"; + using system_clock = std::chrono::system_clock; CryptoManager::CryptoManager() @@ -33,7 +39,9 @@ CryptoManager::CryptoManager() vecAad_ = std::vector(HKS_BLOB_TYPE_AAD, HKS_BLOB_TYPE_AAD + strlen(HKS_BLOB_TYPE_AAD)); } -CryptoManager::~CryptoManager() {} +CryptoManager::~CryptoManager() +{ +} CryptoManager &CryptoManager::GetInstance() { @@ -49,19 +57,32 @@ struct HksParam aes256Param[] = { { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, }; -bool AddHksParams(HksParamSet *params, const CryptoManager::ParamConfig ¶mConfig, - const std::vector &vecAad) +bool AddHksParams(HksParamSet *params, CryptoManager::ParamConfig ¶mConfig) { - struct HksBlob blobAad = { uint32_t(vecAad.size()), const_cast(vecAad.data()) }; - struct HksBlob blobNonce = { uint32_t(paramConfig.nonce.size()), const_cast(paramConfig.nonce.data()) }; + if (paramConfig.nonce.empty()) { + uint8_t nonce[NONCE_SIZE] = {0}; + struct HksBlob blobNonce = { .size = NONCE_SIZE, .data = nonce }; + auto result = HksGenerateRandom(nullptr, &blobNonce); + if (result != HKS_SUCCESS) { + ZLOGE("HksGenerateRandom failed with error %{public}d", result); + return false; + } + std::vector nonceContent(blobNonce.data, blobNonce.data + blobNonce.size); + paramConfig.nonce = nonceContent; + } + struct HksBlob blobAad = { uint32_t(paramConfig.aadValue.size()), + const_cast(paramConfig.aadValue.data()) }; std::vector hksParam; - hksParam.push_back({ .tag = HKS_TAG_PURPOSE, .uint32Param = paramConfig.purpose }); - hksParam.push_back(HksParam{ .tag = HKS_TAG_NONCE, .blob = blobNonce }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_PURPOSE, .uint32Param = paramConfig.purpose }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_NONCE, + .blob = { uint32_t(paramConfig.nonce.size()), const_cast(paramConfig.nonce.data()) } }); hksParam.push_back(HksParam{ .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }); - hksParam.push_back({ .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = paramConfig.storageLevel }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = paramConfig.storageLevel }); + if (paramConfig.storageLevel > HKS_AUTH_STORAGE_LEVEL_DE) { - hksParam.push_back(HksParam{ .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = atoi(paramConfig.userId.c_str()) }); + hksParam.emplace_back( + HksParam { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = std::atoi(paramConfig.userId.c_str()) }); } auto ret = HksAddParams(params, aes256Param, sizeof(aes256Param) / sizeof(aes256Param[0])); @@ -87,17 +108,16 @@ int32_t GetRootKeyParams(HksParamSet *¶ms, uint32_t storageLevel, const std: return ret; } - std::vector hksParam = { - { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, - { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, - { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, - { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, - { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, - { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, - { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = storageLevel }, - }; + std::vector hksParam; + hksParam.push_back(HksParam{ .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_DIGEST, .uint32Param = 0 }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }); + hksParam.push_back(HksParam{ .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = storageLevel }); if (storageLevel > HKS_AUTH_STORAGE_LEVEL_DE) { - hksParam.emplace_back(HksParam{ .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = std::stoi(userId) }); + hksParam.emplace_back(HksParam { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = std::atoi(userId.c_str()) }); } ret = HksAddParams(params, hksParam.data(), hksParam.size()); @@ -137,8 +157,8 @@ int32_t CryptoManager::GenerateRootKey(uint32_t storageLevel, const std::string ZLOGI("GenerateRootKey Succeed. storageLevel:%{public}u, userId:%{public}s", storageLevel, userId.c_str()); return ErrCode::SUCCESS; } - ZLOGE("HksGenerateKey failed with error %{public}d, storageLevel:%{public}u, userId:%{public}s", ret, storageLevel, - userId.c_str()); + ZLOGE("HksGenerateKey failed with error %{public}d, storageLevel:%{public}u, userId:%{public}s", + ret, storageLevel, userId.c_str()); return ErrCode::ERROR; } @@ -198,42 +218,30 @@ int32_t CryptoManager::PrepareRootKey(uint32_t storageLevel, const std::string & userId.c_str(), status); return status; } -std::vector CryptoManager::Encrypt(const std::vector &key, int32_t area, const std::string &userId) -{ - EncryptParams encryptParams = { .keyAlias = vecRootKeyAlias_, .nonce = vecNonce_ }; - return Encrypt(key, area, userId, encryptParams); -} - -std::vector CryptoManager::Encrypt(const std::vector &key) -{ - EncryptParams encryptParams = { .keyAlias = vecRootKeyAlias_, .nonce = vecNonce_ }; - return Encrypt(key, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER, encryptParams); -} -std::vector CryptoManager::Encrypt(const std::vector &key, const EncryptParams &encryptParams) +std::vector CryptoManager::Encrypt(const std::vector &password, CryptoParams &encryptParams) { - return Encrypt(key, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER, encryptParams); -} - -std::vector CryptoManager::Encrypt(const std::vector &key, int32_t area, const std::string &userId, - const EncryptParams &encryptParams) -{ - uint32_t storageLevel = GetStorageLevel(area); - if (PrepareRootKey(storageLevel, userId) != ErrCode::SUCCESS) { + encryptParams.area = encryptParams.area < 0 ? Area::EL1 : encryptParams.area; + uint32_t storageLevel = GetStorageLevel(encryptParams.area); + if (PrepareRootKey(storageLevel, encryptParams.userId) != ErrCode::SUCCESS) { return {}; } struct HksParamSet *params = nullptr; int32_t ret = HksInitParamSet(¶ms); if (ret != HKS_SUCCESS) { - ZLOGE("HksInitParamSet() failed with error %{public}d", ret); + ZLOGE("HksInitParamSet failed with error %{public}d", ret); return {}; } - ParamConfig paramConfig = { .nonce = encryptParams.nonce, + + ParamConfig paramConfig = { .purpose = HKS_KEY_PURPOSE_ENCRYPT, .storageLevel = storageLevel, - .userId = userId }; - if (!AddHksParams(params, paramConfig, vecAad_)) { + .userId = encryptParams.userId, + .nonce = encryptParams.nonce, + .aadValue = vecAad_ + }; + if (!AddHksParams(params, paramConfig)) { return {}; } ret = HksBuildParamSet(¶ms); @@ -243,11 +251,14 @@ std::vector CryptoManager::Encrypt(const std::vector &key, int return {}; } + if (encryptParams.keyAlias.empty()) { + encryptParams.keyAlias = vecRootKeyAlias_; + } + struct HksBlob keyName = { uint32_t(encryptParams.keyAlias.size()), + const_cast(encryptParams.keyAlias.data())}; + struct HksBlob plainKey = { uint32_t(password.size()), const_cast(password.data()) }; uint8_t cipherBuf[256] = { 0 }; struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf }; - struct HksBlob keyName = { uint32_t(encryptParams.keyAlias.size()), - const_cast(encryptParams.keyAlias.data()) }; - struct HksBlob plainKey = { uint32_t(key.size()), const_cast(key.data()) }; ret = HksEncrypt(&keyName, params, &plainKey, &cipherText); (void)HksFreeParamSet(¶ms); if (ret != HKS_SUCCESS) { @@ -255,108 +266,83 @@ std::vector CryptoManager::Encrypt(const std::vector &key, int return {}; } + if (encryptParams.nonce.empty()) { + encryptParams.nonce = paramConfig.nonce; + } std::vector encryptedKey(cipherText.data, cipherText.data + cipherText.size); - (void)memset_s(cipherBuf, sizeof(cipherBuf), 0, sizeof(cipherBuf)); + std::fill(cipherBuf, cipherBuf + sizeof(cipherBuf), 0); return encryptedKey; } -bool CryptoManager::UpdateSecretKey(const StoreMetaData &meta, const std::vector &key, - SecretKeyType secretKeyType) -{ - if (!meta.isEncrypt) { - return false; - } - SecretKeyMetaData secretKey; - EncryptParams encryptParams = { .keyAlias = vecRootKeyAlias_, .nonce = vecNonce_ }; - secretKey.storeType = meta.storeType; - secretKey.area = meta.area; - secretKey.sKey = Encrypt(key, meta.area, meta.user, encryptParams); - auto time = system_clock::to_time_t(system_clock::now()); - secretKey.time = { reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time) }; - if (secretKeyType == LOCAL_SECRET_KEY) { - return MetaDataManager::GetInstance().SaveMeta(meta.GetSecretKey(), secretKey, true); - } else { - return MetaDataManager::GetInstance().SaveMeta(meta.GetCloneSecretKey(), secretKey, true); - } -} - -bool CryptoManager::Decrypt(const StoreMetaData &meta, SecretKeyMetaData &secretKeyMeta, std::vector &key, - SecretKeyType secretKeyType) +std::vector CryptoManager::Decrypt(const std::vector &source, CryptoParams &decryptParams) { - EncryptParams encryptParams = { .keyAlias = vecRootKeyAlias_, .nonce = vecNonce_ }; - if (secretKeyMeta.area < 0) { - ZLOGI("Decrypt old secret key"); - if (Decrypt(secretKeyMeta.sKey, key, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER, encryptParams)) { - StoreMetaData metaData; - if (MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), metaData, true)) { - ZLOGI("Upgrade secret key"); - UpdateSecretKey(metaData, key, secretKeyType); - } - return true; - } - } else { - return Decrypt(secretKeyMeta.sKey, key, secretKeyMeta.area, meta.user, encryptParams); + uint32_t storageLevel = GetStorageLevel(decryptParams.area); + if (PrepareRootKey(storageLevel, decryptParams.userId) != ErrCode::SUCCESS) { + return {}; } - return false; -} - -bool CryptoManager::Decrypt(std::vector &source, std::vector &key, int32_t area, - const std::string &userId) -{ - EncryptParams encryptParams = { .keyAlias = vecRootKeyAlias_, .nonce = vecNonce_ }; - return Decrypt(source, key, area, userId, encryptParams); -} - -bool CryptoManager::Decrypt(std::vector &source, std::vector &key, const EncryptParams &encryptParams) -{ - return Decrypt(source, key, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER, encryptParams); -} -bool CryptoManager::Decrypt(std::vector &source, std::vector &key, int32_t area, - const std::string &userId, const EncryptParams &encryptParams) -{ - uint32_t storageLevel = GetStorageLevel(area); - if (PrepareRootKey(storageLevel, userId) != ErrCode::SUCCESS) { - return false; - } struct HksParamSet *params = nullptr; int32_t ret = HksInitParamSet(¶ms); if (ret != HKS_SUCCESS) { - ZLOGE("HksInitParamSet() failed with error %{public}d", ret); - return false; + ZLOGE("HksInitParamSet failed with error %{public}d", ret); + return {}; } - ParamConfig paramConfig = { .nonce = encryptParams.nonce, + ParamConfig paramConfig = { .purpose = HKS_KEY_PURPOSE_DECRYPT, .storageLevel = storageLevel, - .userId = userId }; - if (!AddHksParams(params, paramConfig, vecAad_)) { - return false; + .userId = decryptParams.userId, + .nonce = decryptParams.nonce.empty() ? vecNonce_ : decryptParams.nonce, + .aadValue = vecAad_ + }; + if (!AddHksParams(params, paramConfig)) { + return {}; } - ret = HksBuildParamSet(¶ms); if (ret != HKS_SUCCESS) { ZLOGE("HksBuildParamSet failed with error %{public}d", ret); HksFreeParamSet(¶ms); - return false; + return {}; } + if (decryptParams.keyAlias.empty()) { + decryptParams.keyAlias = vecRootKeyAlias_; + } + struct HksBlob keyName = { uint32_t(decryptParams.keyAlias.size()), + const_cast(decryptParams.keyAlias.data()) }; + struct HksBlob encryptedKeyBlob = { uint32_t(source.size()), const_cast(source.data()) }; uint8_t plainBuf[256] = { 0 }; struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf }; - struct HksBlob encryptedKeyBlob = { uint32_t(source.size()), source.data() }; - struct HksBlob keyName = { uint32_t(encryptParams.keyAlias.size()), - const_cast(encryptParams.keyAlias.data()) }; ret = HksDecrypt(&keyName, params, &encryptedKeyBlob, &plainKeyBlob); (void)HksFreeParamSet(¶ms); if (ret != HKS_SUCCESS) { ZLOGE("HksDecrypt failed with error %{public}d", ret); - return false; + return {}; } + std::vector password(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size); + return password; +} - key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size); - (void)memset_s(plainBuf, sizeof(plainBuf), 0, sizeof(plainBuf)); - return true; +void CryptoManager::UpdateSecretMeta(const std::vector &password, const StoreMetaData &metaData, + const std::string &metaKey, SecretKeyMetaData &secretKey) +{ + if (password.empty() || (!secretKey.nonce.empty() && secretKey.area >= 0)) { + return; + } + CryptoParams encryptParams = { .area = metaData.area, .userId = metaData.user, + .nonce = secretKey.nonce }; + auto encryptKey = Encrypt(password, encryptParams); + if (encryptKey.empty()) { + return; + } + secretKey.sKey = encryptKey; + secretKey.nonce = encryptParams.nonce; + secretKey.area = metaData.area; + auto time = system_clock::to_time_t(system_clock::now()); + secretKey.time = { reinterpret_cast(&time), + reinterpret_cast(&time) + sizeof(time) }; + MetaDataManager::GetInstance().SaveMeta(metaKey, secretKey, true); } bool BuildImportKeyParams(struct HksParamSet *¶ms) @@ -367,10 +353,10 @@ bool BuildImportKeyParams(struct HksParamSet *¶ms) return false; } struct HksParam purposeParam[] = { - { .tag = HKS_TAG_IS_KEY_ALIAS, .boolParam = true }, - { .tag = HKS_TAG_KEY_GENERATE_TYPE, .uint32Param = HKS_KEY_GENERATE_TYPE_DEFAULT }, - { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, - { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, + {.tag = HKS_TAG_IS_KEY_ALIAS, .boolParam = true}, + {.tag = HKS_TAG_KEY_GENERATE_TYPE, .uint32Param = HKS_KEY_GENERATE_TYPE_DEFAULT}, + {.tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT}, + {.tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE}, }; ret = HksAddParams(params, aes256Param, sizeof(aes256Param) / sizeof(aes256Param[0])); if (ret != HKS_SUCCESS) { diff --git a/datamgr_service/services/distributeddataservice/framework/device_manager/device_manager_delegate.cpp b/datamgr_service/services/distributeddataservice/framework/device_manager/device_manager_delegate.cpp new file mode 100644 index 00000000..e85b94b9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/device_manager/device_manager_delegate.cpp @@ -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. + */ + +#include "device_manager/device_manager_delegate.h" + +namespace OHOS { +namespace DistributedData { +DeviceManagerDelegate *DeviceManagerDelegate::instance_ = nullptr; + +bool DeviceManagerDelegate::RegisterInstance(DeviceManagerDelegate *instance) +{ + if (instance_ != nullptr) { + return false; + } + instance_ = instance; + return true; +} + +DeviceManagerDelegate *DeviceManagerDelegate::GetInstance() +{ + return instance_; +} +} // namespace DistributedData +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/device_sync_app/device_sync_app_manager.cpp b/datamgr_service/services/distributeddataservice/framework/device_sync_app/device_sync_app_manager.cpp new file mode 100644 index 00000000..e20ee46e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/device_sync_app/device_sync_app_manager.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. + */ +#define LOG_TAG "DeviceSyncAppManager" +#include "device_sync_app/device_sync_app_manager.h" + +namespace OHOS::DistributedData { +DeviceSyncAppManager::DeviceSyncAppManager() +{ +} + +DeviceSyncAppManager &DeviceSyncAppManager::GetInstance() +{ + static DeviceSyncAppManager instance; + return instance; +} + +void DeviceSyncAppManager::Initialize(const std::vector &lists) +{ + for (const auto &list : lists) { + whiteLists_.push_back(list); + } +} + +bool DeviceSyncAppManager::Check(const WhiteList &whiteList) +{ + for (const auto &info : whiteLists_) { + if (info.appId == whiteList.appId && (info.bundleName == whiteList.bundleName) && + (info.version == whiteList.version)) { + return true; + } + } + return false; +} + +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/directory/directory_manager.cpp b/datamgr_service/services/distributeddataservice/framework/directory/directory_manager.cpp index 9deb434e..1586511c 100644 --- a/datamgr_service/services/distributeddataservice/framework/directory/directory_manager.cpp +++ b/datamgr_service/services/distributeddataservice/framework/directory/directory_manager.cpp @@ -107,7 +107,7 @@ std::string DirectoryManager::GetClonePath(const std::string &userId, uint32_t v return ""; } -void DirectoryManager::Initialize(const std::vector &strategies) +void DirectoryManager::Initialize(const std::vector &strategies, const std::vector &storeTypes) { strategies_.resize(strategies.size()); for (size_t i = 0; i < strategies.size(); ++i) { @@ -127,6 +127,8 @@ void DirectoryManager::Initialize(const std::vector &strategies) std::sort(strategies_.begin(), strategies_.end(), [](const StrategyImpl &curr, const StrategyImpl &prev) { return curr.version > prev.version; }); + + storeTypes_ = storeTypes; } std::string DirectoryManager::GetType(const StoreMetaData &metaData) const @@ -140,19 +142,10 @@ std::string DirectoryManager::GetType(const StoreMetaData &metaData) const std::string DirectoryManager::GetStore(const StoreMetaData &metaData) const { - if (metaData.storeType >= StoreMetaData::StoreType::STORE_KV_BEGIN && - metaData.storeType <= StoreMetaData::StoreType::STORE_KV_END) { - return "kvdb"; - } - // rdb use empty session - if (metaData.storeType >= StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN && - metaData.storeType <= StoreMetaData::StoreType::STORE_RELATIONAL_END) { - return "rdb"; - } - // object use meta - if (metaData.storeType >= StoreMetaData::StoreType::STORE_OBJECT_BEGIN && - metaData.storeType <= StoreMetaData::StoreType::STORE_OBJECT_END) { - return "kvdb"; + for (const auto &storeType : storeTypes_) { + if (metaData.storeType >= storeType.range.front() && metaData.storeType <= storeType.range.back()) { + return storeType.type; + } } return "other"; } @@ -288,6 +281,7 @@ bool DirectoryManager::CreateDirectory(const std::string &path) const if (access(subPath.c_str(), F_OK) != 0) { if (mkdir(subPath.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0) { + ZLOGE("mkdir error:%{public}d", errno); return false; } } @@ -295,44 +289,4 @@ bool DirectoryManager::CreateDirectory(const std::string &path) const return access(path.c_str(), F_OK) == 0; } - -bool DirectoryManager::DeleteDirectory(const char* path) -{ - if (path == nullptr) { - return false; - } - DIR* dir; - struct dirent* dirEntry; - struct stat buf; - char* curWorkDir = getcwd(nullptr, 0); - if ((dir = opendir(path)) == nullptr) { - return true; - } - if (chdir(path) == -1) { - closedir(dir); - return false; - } - while ((dirEntry = readdir(dir))) { - if ((strcmp(dirEntry->d_name, ".") == 0) || (strcmp(dirEntry->d_name, "..") == 0)) { - continue; - } - if (stat(dirEntry->d_name, &buf) == -1) { - closedir(dir); - return false; - } - if (S_ISDIR(buf.st_mode)) { - DeleteDirectory(dirEntry->d_name); - continue; - } - if (remove(dirEntry->d_name) == -1) { - closedir(dir); - return false; - } - } - closedir(dir); - if (chdir(curWorkDir) == -1 || rmdir(path) == -1) { - return false; - } - return true; -} } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/framework/feature/feature_system.cpp b/datamgr_service/services/distributeddataservice/framework/feature/feature_system.cpp index 593a7c63..23b77e16 100644 --- a/datamgr_service/services/distributeddataservice/framework/feature/feature_system.cpp +++ b/datamgr_service/services/distributeddataservice/framework/feature/feature_system.cpp @@ -76,6 +76,10 @@ int32_t FeatureSystem::Feature::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId return E_OK; } +int32_t FeatureSystem::Feature::OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) +{ + return E_OK; +} int32_t FeatureSystem::Feature::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index) { return E_OK; diff --git a/datamgr_service/services/distributeddataservice/framework/include/access_check/app_access_check_config_manager.h b/datamgr_service/services/distributeddataservice/framework/include/access_check/app_access_check_config_manager.h new file mode 100644 index 00000000..fecf7315 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/access_check/app_access_check_config_manager.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 OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_APP_ACCESS_CHECK_CONFIG_MANAGER_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_APP_ACCESS_CHECK_CONFIG_MANAGER_H +#include +#include +#include +#include "visibility.h" +namespace OHOS { +namespace DistributedData { +class AppAccessCheckConfigManager { +public: + struct AppMappingInfo { + std::string appId; + std::string bundleName; + }; + API_EXPORT static AppAccessCheckConfigManager &GetInstance(); + API_EXPORT void Initialize(const std::vector &mapper); + API_EXPORT bool IsTrust(const std::string &appId); + +private: + std::map appMapper_; +}; + +} // namespace DistributedData +} // namespace OHOS +#endif //OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_APP_ACCESS_CHECK_CONFIG_MANAGER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/account/account_delegate.h b/datamgr_service/services/distributeddataservice/framework/include/account/account_delegate.h index 5636131f..c2ed384f 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/account/account_delegate.h +++ b/datamgr_service/services/distributeddataservice/framework/include/account/account_delegate.h @@ -67,8 +67,8 @@ public: API_EXPORT virtual void UnsubscribeAccountEvent() = 0; API_EXPORT virtual bool QueryUsers(std::vector &users) = 0; API_EXPORT virtual bool QueryForegroundUsers(std::vector &users) = 0; - API_EXPORT virtual bool IsLoginAccount() = 0; API_EXPORT virtual bool QueryForegroundUserId(int &foregroundUserId) = 0; + API_EXPORT virtual bool IsLoginAccount() = 0; API_EXPORT virtual bool IsVerified(int userId) = 0; API_EXPORT virtual bool RegisterHashFunc(HashFunc hash) = 0; API_EXPORT virtual bool IsDeactivating(int userId) = 0; diff --git a/datamgr_service/services/distributeddataservice/framework/include/app_id_mapping/app_id_mapping_config_manager.h b/datamgr_service/services/distributeddataservice/framework/include/app_id_mapping/app_id_mapping_config_manager.h index 9799f9af..2133bcb0 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/app_id_mapping/app_id_mapping_config_manager.h +++ b/datamgr_service/services/distributeddataservice/framework/include/app_id_mapping/app_id_mapping_config_manager.h @@ -30,7 +30,7 @@ public: API_EXPORT void Initialize(const std::vector &mapper); API_EXPORT std::pair Convert(const std::string &appId, const std::string &accountId); - + API_EXPORT std::string Convert(const std::string &appId); private: std::map toDstMapper_; }; diff --git a/datamgr_service/services/distributeddataservice/framework/include/changeevent/remote_change_event.h b/datamgr_service/services/distributeddataservice/framework/include/changeevent/remote_change_event.h index bf58f432..aa6ca90d 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/changeevent/remote_change_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/changeevent/remote_change_event.h @@ -33,8 +33,8 @@ public: std::string storeId; std::string deviceId; std::string bundleName; - int changeType = 0; // 0 means CLOUD_DATA_CHANGE std::vector tables; + int changeType = 0; // 0 means CLOUD_DATA_CHANGE }; RemoteChangeEvent(int32_t evtId, DataInfo&& info); diff --git a/datamgr_service/services/distributeddataservice/framework/include/checker/checker_manager.h b/datamgr_service/services/distributeddataservice/framework/include/checker/checker_manager.h index f5327994..f42f43c6 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/checker/checker_manager.h +++ b/datamgr_service/services/distributeddataservice/framework/include/checker/checker_manager.h @@ -53,6 +53,8 @@ public: virtual std::vector GetStaticStores() = 0; virtual bool IsDynamic(const StoreInfo &info) = 0; virtual bool IsStatic(const StoreInfo &info) = 0; + virtual void DeleteCache(const std::string &bundleName, int32_t user, int32_t index){}; + virtual void ClearCache(){}; protected: API_EXPORT ~Checker() = default; }; @@ -68,6 +70,9 @@ public: API_EXPORT bool IsSwitches(const StoreInfo &info); API_EXPORT void LoadCheckers(std::vector &checkers); API_EXPORT Checker *GetChecker(const std::string &checker); + API_EXPORT void DeleteCache(const std::string &bundleName, int32_t user, int32_t index); + API_EXPORT void ClearCache(); + private: std::map checkers_; ConcurrentMap> getters_; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h index fcf7cfca..58933563 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h @@ -40,9 +40,9 @@ public: virtual int32_t BatchDelete(const std::string &table, VBuckets &extends); - virtual std::shared_ptr Query(const std::string &table, const VBucket &extend); + virtual std::pair> Query(const std::string &table, const VBucket &extend); - virtual std::shared_ptr Query(GenQuery &query, const VBucket &extend); + virtual std::pair> Query(GenQuery &query, const VBucket &extend); virtual int32_t PreSharing(const std::string &table, VBuckets &extend); diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h index 9cb060c8..0d87d026 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h @@ -43,6 +43,7 @@ public: virtual void ReleaseUserInfo(int32_t userId); virtual void Bind(std::shared_ptr executor); virtual bool IsSupportCloud(int32_t userId); + virtual bool CloudDriverUpdated(const std::string &bundleName); private: static CloudServer *instance_; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h index bc74d210..88939219 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h @@ -73,7 +73,8 @@ public: static constexpr const char *SHARING_RESOURCE = "#_sharing_resource"; static constexpr const char *HASH_KEY = "#_hash_key"; - static constexpr uint32_t CURRENT_VERSION = 0x10000; + static constexpr uint32_t CURRENT_VERSION = 0x10001; + static constexpr uint32_t CLEAN_WATER_VERSION = 0x10001; static inline uint32_t GetLowVersion(uint32_t metaVersion = CURRENT_VERSION) { return metaVersion & 0xFFFF; @@ -87,6 +88,7 @@ public: int32_t version = 0; std::string bundleName; std::vector databases; + bool e2eeEnable = false; bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; @@ -104,4 +106,4 @@ enum AutoSyncType { }; } // namespace OHOS::DistributedData -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SCHEMA_META_H +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SCHEMA_META_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/communication/connect_manager.h b/datamgr_service/services/distributeddataservice/framework/include/communication/connect_manager.h index 5e9093c7..eb0e07c1 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/communication/connect_manager.h +++ b/datamgr_service/services/distributeddataservice/framework/include/communication/connect_manager.h @@ -27,6 +27,7 @@ namespace OHOS { namespace AppDistributedKv { class API_EXPORT ConnectManager { public: + using ApplyTask = std::function; using ConnectTask = std::function; using CloseSessionTask = std::function; using SessionCloseListener = std::function; @@ -51,7 +52,7 @@ public: virtual void OnStart(); virtual void OnDestory(); - virtual int32_t ApplyConnect(const std::string &networkId, ConnectTask task); + virtual int32_t ApplyConnect(const std::string &networkId, ApplyTask applyTask, ConnectTask connectTask); private: static std::mutex mtx_; diff --git a/datamgr_service/services/distributeddataservice/service/crypto/include/crypto_manager.h b/datamgr_service/services/distributeddataservice/framework/include/crypto/crypto_manager.h similarity index 53% rename from datamgr_service/services/distributeddataservice/service/crypto/include/crypto_manager.h rename to datamgr_service/services/distributeddataservice/framework/include/crypto/crypto_manager.h index dca7f96d..ec2b8c2a 100644 --- a/datamgr_service/services/distributeddataservice/service/crypto/include/crypto_manager.h +++ b/datamgr_service/services/distributeddataservice/framework/include/crypto/crypto_manager.h @@ -23,80 +23,71 @@ #include "visibility.h" namespace OHOS::DistributedData { -static constexpr int32_t DEFAULT_ENCRYPTION_LEVEL = 1; -static constexpr const char *DEFAULT_USER = "0"; class API_EXPORT CryptoManager { public: + static constexpr const char *DEFAULT_USER = "0"; + enum SecretKeyType { LOCAL_SECRET_KEY, CLONE_SECRET_KEY, }; - struct ParamConfig { - std::vector nonce; - uint32_t purpose; - uint32_t storageLevel; - std::string userId; - }; - struct EncryptParams { - std::vector keyAlias; - std::vector nonce; - }; + enum Area : int32_t { EL0, EL1, EL2, EL3, EL4, - EL5 + EL5, }; - static CryptoManager &GetInstance(); - int32_t GenerateRootKey(); - int32_t CheckRootKey(); - std::vector Encrypt(const std::vector &key); - std::vector Encrypt(const std::vector &key, const EncryptParams &encryptParams); - std::vector Encrypt(const std::vector &key, int32_t area, const std::string &userId); - std::vector Encrypt(const std::vector &key, - int32_t area, const std::string &userId, const EncryptParams &encryptParams - ); - bool Decrypt(std::vector &source, std::vector &key, const EncryptParams &encryptParams); - bool Decrypt(std::vector &source, std::vector &key, int32_t area, const std::string &userId); - bool Decrypt(std::vector &source, std::vector &key, - int32_t area, const std::string &userId, const EncryptParams &encryptParams - ); - bool ImportKey(const std::vector &key, const std::vector &keyAlias); - bool DeleteKey(const std::vector &keyAlias); - bool UpdateSecretKey(const StoreMetaData &meta, const std::vector &password, - SecretKeyType secretKeyType = LOCAL_SECRET_KEY); - bool Decrypt(const StoreMetaData &meta, SecretKeyMetaData &secretKeyMeta, std::vector &key, - SecretKeyType secretKeyType = LOCAL_SECRET_KEY); enum ErrCode : int32_t { SUCCESS, NOT_EXIST, ERROR, }; + + struct CryptoParams { + int32_t area = Area::EL1; + std::string userId = DEFAULT_USER; + std::vector keyAlias; + std::vector nonce; + }; + + struct ParamConfig { + uint32_t purpose; + uint32_t storageLevel; + std::string userId; + std::vector nonce; + std::vector aadValue; + }; + + static CryptoManager &GetInstance(); + + int32_t GenerateRootKey(); + int32_t CheckRootKey(); + + std::vector Encrypt(const std::vector &password, CryptoParams &encryptParams); + std::vector Decrypt(const std::vector &source, CryptoParams &decryptParams); + void UpdateSecretMeta(const std::vector &password, const StoreMetaData &metaData, + const std::string &metaKey, SecretKeyMetaData &secretKey); + + bool ImportKey(const std::vector &key, const std::vector &keyAlias); + bool DeleteKey(const std::vector &keyAlias); + private: - static constexpr const char *ROOT_KEY_ALIAS = "distributed_db_root_key"; - static constexpr const char *HKS_BLOB_TYPE_NONCE = "Z5s0Bo571KoqwIi6"; - static constexpr const char *HKS_BLOB_TYPE_AAD = "distributeddata"; - static constexpr int KEY_SIZE = 32; - static constexpr int AES_256_NONCE_SIZE = 32; - static constexpr int HOURS_PER_YEAR = (24 * 365); + CryptoManager(); + ~CryptoManager(); + uint32_t GetStorageLevel(int32_t area); int32_t GenerateRootKey(uint32_t storageLevel, const std::string &userId); int32_t CheckRootKey(uint32_t storageLevel, const std::string &userId); - uint32_t GetStorageLevel(int32_t area); int32_t PrepareRootKey(uint32_t storageLevel, const std::string &userId); - std::vector EncryptInner(const std::vector &key, const SecretKeyType type, int32_t area, - const std::string &userId); - bool DecryptInner(std::vector &source, std::vector &key, int32_t area, - const std::string &userId, std::vector &keyAlias, std::vector &nonce); - CryptoManager(); + + std::mutex mutex_; std::vector vecRootKeyAlias_{}; std::vector vecNonce_{}; std::vector vecAad_{}; - ~CryptoManager(); - std::mutex mutex_; }; } // namespace OHOS::DistributedData -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_SERVICE_CRYPTO_CRYPTO_MANAGER_H +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_SERVICE_CRYPTO_CRYPTO_MANAGER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/device_manager/device_manager_delegate.h b/datamgr_service/services/distributeddataservice/framework/include/device_manager/device_manager_delegate.h new file mode 100644 index 00000000..0e7d5782 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/device_manager/device_manager_delegate.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 DISTRIBUTEDDATAMGR_DEVICE_MANAGER_DELEGATE_H +#define DISTRIBUTEDDATAMGR_DEVICE_MANAGER_DELEGATE_H + +#include "device_manager_types.h" +#include "visibility.h" + +namespace OHOS { +namespace DistributedData { +class DeviceManagerDelegate { +public: + virtual ~DeviceManagerDelegate() = default; + virtual DeviceInfo GetLocalDevice() = 0; + API_EXPORT static bool RegisterInstance(DeviceManagerDelegate *instance); + API_EXPORT static DeviceManagerDelegate *GetInstance(); +private: + static DeviceManagerDelegate *instance_; +}; +} // namespace DistributedData +} // namespace OHOS +#endif // DISTRIBUTEDDATAMGR_DEVICE_MANAGER_DELEGATE_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/device_manager/device_manager_types.h b/datamgr_service/services/distributeddataservice/framework/include/device_manager/device_manager_types.h new file mode 100644 index 00000000..315e76c1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/device_manager/device_manager_types.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 OHOS_DISTRIBUTED_DATA_FRAMEWORK_DEVICE_MANAGER_TYPES_H +#define OHOS_DISTRIBUTED_DATA_FRAMEWORK_DEVICE_MANAGER_TYPES_H +#include +#include "visibility.h" +namespace OHOS::DistributedData { +struct API_EXPORT DeviceInfo { + std::string uuid; + std::string udid; + std::string networkId; + std::string deviceName; + uint32_t deviceType; + int32_t osType; + int32_t authForm; +}; +} +#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORK_DEVICE_MANAGER_TYPES_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/device_sync_app/device_sync_app_manager.h b/datamgr_service/services/distributeddataservice/framework/include/device_sync_app/device_sync_app_manager.h new file mode 100644 index 00000000..664883bc --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/device_sync_app/device_sync_app_manager.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 DISTRIBUTEDDATAMGR_DEVICE_SYNC_APP_MANAGER_H +#define DISTRIBUTEDDATAMGR_DEVICE_SYNC_APP_MANAGER_H + +#include +#include +#include "visibility.h" +namespace OHOS::DistributedData { +class DeviceSyncAppManager { +public: + struct WhiteList { + std::string appId; + std::string bundleName; + uint32_t version; + }; + API_EXPORT static DeviceSyncAppManager &GetInstance(); + API_EXPORT void Initialize(const std::vector &lists); + API_EXPORT bool Check(const WhiteList &whiteList); + +private: + DeviceSyncAppManager(); + std::vector whiteLists_; +}; +} // namespace OHOS::DistributedData +#endif // DISTRIBUTEDDATAMGR_DEVICE_SYNC_APP_MANAGER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/dfx/dfx_types.h b/datamgr_service/services/distributeddataservice/framework/include/dfx/dfx_types.h index bb1a0e91..a83fd252 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/dfx/dfx_types.h +++ b/datamgr_service/services/distributeddataservice/framework/include/dfx/dfx_types.h @@ -88,6 +88,7 @@ enum class Fault { CSF_DOWNLOAD_ASSETS = 82, CSF_GS_CREATE_DISTRIBUTED_TABLE = 83, CSF_GS_CLOUD_SYNC = 84, + CSF_GS_CLOUD_CLEAN = 85, }; enum class FaultType { diff --git a/datamgr_service/services/distributeddataservice/framework/include/directory/directory_manager.h b/datamgr_service/services/distributeddataservice/framework/include/directory/directory_manager.h index 0570bcd6..c7cc4253 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/directory/directory_manager.h +++ b/datamgr_service/services/distributeddataservice/framework/include/directory/directory_manager.h @@ -32,6 +32,10 @@ public: std::string metaPath; std::string clonePath; }; + struct StoreType { + std::vector range; + std::string type; + }; API_EXPORT static DirectoryManager &GetInstance(); API_EXPORT std::string GetStorePath(const StoreMetaData &metaData, uint32_t version = INVALID_VERSION); API_EXPORT std::string GetSecretKeyPath(const StoreMetaData &metaData, uint32_t version = INVALID_VERSION); @@ -40,9 +44,8 @@ public: API_EXPORT std::string GetMetaStorePath(uint32_t version = INVALID_VERSION); API_EXPORT std::string GetMetaBackupPath(uint32_t version = INVALID_VERSION); API_EXPORT std::vector GetVersions(); - API_EXPORT void Initialize(const std::vector &strategies); + API_EXPORT void Initialize(const std::vector &strategies, const std::vector &storeTypes); API_EXPORT bool CreateDirectory(const std::string &path) const; - API_EXPORT bool DeleteDirectory(const char* path); private: using Action = std::string (DirectoryManager::*)(const StoreMetaData &) const; @@ -69,6 +72,7 @@ private: std::string GenPath(const StoreMetaData &metaData, uint32_t version, const std::string &exPath = "") const; const std::map actions_; std::vector strategies_; + std::vector storeTypes_; }; } // namespace OHOS::DistributedData #endif // DISTRIBUTEDDATAMGR_DIRECTORY_MANAGER_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/feature/feature_system.h b/datamgr_service/services/distributeddataservice/framework/include/feature/feature_system.h index 8f0d1424..1fceb814 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/feature/feature_system.h +++ b/datamgr_service/services/distributeddataservice/framework/include/feature/feature_system.h @@ -47,6 +47,7 @@ public: virtual int32_t OnInitialize(); virtual int32_t OnBind(const BindInfo &bindInfo); virtual int32_t OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName); + virtual int32_t OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName); virtual int32_t OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index); virtual int32_t OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index); virtual int32_t OnAppInstall(const std::string &bundleName, int32_t user, int32_t index); diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/capability_meta_data.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/capability_meta_data.h index 702a362a..1c49339e 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/capability_meta_data.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/capability_meta_data.h @@ -20,9 +20,14 @@ namespace OHOS::DistributedData { class API_EXPORT CapMetaData final : public Serializable { public: - static constexpr int32_t CURRENT_VERSION = 1; + // 1->2 add accountId to session + // 2->3 udmf and object add to session + static constexpr int32_t CURRENT_VERSION = 3; static constexpr int32_t INVALID_VERSION = -1; + static constexpr int32_t ACCOUNT_VERSION = 2; + static constexpr int32_t UDMF_AND_OBJECT_VERSION = 3; int32_t version = INVALID_VERSION; + std::string deviceId = ""; API_EXPORT bool Marshal(json &node) const override; API_EXPORT bool Unmarshal(const json &node) override; @@ -32,6 +37,7 @@ class CapMetaRow { public: static constexpr const char *KEY_PREFIX = "CapabilityMeta"; API_EXPORT static std::vector GetKeyFor(const std::string &key); + API_EXPORT static const std::string GetDeviceId(const std::string &key); }; } // namespace OHOS::DistributedData #endif // DISTRIBUTEDDATAMGR_CAPABILITY_META_DATA_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/device_meta_data.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/device_meta_data.h index 7df8c556..a5dd8e61 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/device_meta_data.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/device_meta_data.h @@ -28,7 +28,6 @@ public: API_EXPORT std::string GetKey() const; std::string newUuid = ""; - std::string oldUuid = ""; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_METADATA_DEVICE_META_DATA_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/meta_data_manager.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/meta_data_manager.h index 08a2465c..dee2bf9f 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/meta_data_manager.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/meta_data_manager.h @@ -21,6 +21,7 @@ #include "concurrent_map.h" #include "serializable/serializable.h" +#include "lru_bucket.h" namespace DistributedDB { class KvStoreNbDelegate; } @@ -51,11 +52,16 @@ public: using Backup = std::function &)>; using Bytes = std::vector; using OnComplete = std::function &)>; + struct Entry { + std::string key; + std::string value; + }; API_EXPORT static MetaDataManager &GetInstance(); API_EXPORT void Initialize(std::shared_ptr metaStore, const Backup &backup, const std::string &storeId); API_EXPORT void SetSyncer(const Syncer &syncer); API_EXPORT void SetCloudSyncer(const CloudSyncer &cloudSyncer); API_EXPORT bool SaveMeta(const std::string &key, const Serializable &value, bool isLocal = false); + API_EXPORT bool SaveMeta(const std::vector &values, bool isLocal = false); API_EXPORT bool LoadMeta(const std::string &key, Serializable &value, bool isLocal = false); template API_EXPORT bool LoadMeta(const std::string &prefix, std::vector &values, bool isLocal = false) @@ -75,16 +81,48 @@ public: } API_EXPORT bool DelMeta(const std::string &key, bool isLocal = false); + API_EXPORT bool DelMeta(const std::vector &keys, bool isLocal = false); API_EXPORT bool Subscribe(std::shared_ptr filter, Observer observer); API_EXPORT bool Subscribe(std::string prefix, Observer observer, bool isLocal = false); API_EXPORT bool Unsubscribe(std::string filter); - API_EXPORT bool Sync(const std::vector &devices, OnComplete complete, bool wait = false); + API_EXPORT bool Sync(const std::vector &devices, OnComplete complete, bool wait = false, + bool isRetry = true); private: MetaDataManager(); ~MetaDataManager(); API_EXPORT bool GetEntries(const std::string &prefix, std::vector &entries, bool isLocal); + + void DelCacheMeta(const std::string &key, bool isLocal) + { + if (!isLocal) { + return; + } + localdata_.Delete(key); + } + + bool LoadCacheMeta(const std::string &key, Serializable &value, bool isLocal) + { + if (!isLocal) { + return false; + } + std::string data; + if (!localdata_.Get(key, data)) { + return false; + } + Serializable::Unmarshall(data, value); + return true; + } + + void SaveCacheMeta(const std::string &key, const std::string &data, bool isLocal) + { + if (!isLocal) { + return; + } + localdata_.Set(key, data); + } + void StopSA(); bool inited_ = false; @@ -95,6 +133,7 @@ private: Syncer syncer_; CloudSyncer cloudSyncer_; std::string storeId_; + LRUBucket localdata_ {64}; }; } // namespace OHOS::DistributedData -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_METADATA_META_DATA_MANAGER_H \ No newline at end of file +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_METADATA_META_DATA_MANAGER_H diff --git a/relational_store/test/native/gdb/unittest/gdb_store_config_test.cpp b/datamgr_service/services/distributeddataservice/framework/include/metadata/object_user_meta_data.h similarity index 49% rename from relational_store/test/native/gdb/unittest/gdb_store_config_test.cpp rename to datamgr_service/services/distributeddataservice/framework/include/metadata/object_user_meta_data.h index 306ddf92..cd2dd38e 100644 --- a/relational_store/test/native/gdb/unittest/gdb_store_config_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/object_user_meta_data.h @@ -13,29 +13,23 @@ * limitations under the License. */ -#include "gdb_store_config.h" -#include +#ifndef DISTRIBUTEDDATAMGR_OBJECT_USER_META_DATA_H +#define DISTRIBUTEDDATAMGR_OBJECT_USER_META_DATA_H -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; -class GdbStoreConfigTest : public testing::Test { +#include "serializable/serializable.h" +namespace OHOS::DistributedData { +class API_EXPORT ObjectUserMetaData final : public Serializable { public: - static void SetUpTestCase() {} - static void TearDownTestCase() {} - void SetUp() {} - void TearDown() {} -}; + std::string userId; -/** - * @tc.name: GdbStoreConfig_Test_SetWriteTime - * @tc.desc: test SetWriteTime - * @tc.type: FUNC - */ -HWTEST_F(GdbStoreConfigTest, GdbStoreConfig_Test_SetWriteTime, TestSize.Level1) -{ - StoreConfig storeCfg; - const int timeout = 10; - storeCfg.SetWriteTime(timeout); - int getTime = storeCfg.GetWriteTime(); - EXPECT_EQ(getTime, timeout); -} \ No newline at end of file + API_EXPORT bool Marshal(json &node) const override; + API_EXPORT bool Unmarshal(const json &node) override; + API_EXPORT ObjectUserMetaData(); + + API_EXPORT static std::string GetKey(); + +private: + static constexpr const char *KEY_PREFIX = "ObjectUserMetaData"; +}; +} // namespace OHOS::DistributedData +#endif // DISTRIBUTEDDATAMGR_OBJECT_USER_META_DATA_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/secret_key_meta_data.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/secret_key_meta_data.h index ed7537cd..cb546472 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/secret_key_meta_data.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/secret_key_meta_data.h @@ -21,8 +21,10 @@ namespace DistributedData { struct API_EXPORT SecretKeyMetaData final : public Serializable { std::vector time {}; std::vector sKey {}; + std::vector nonce {}; int32_t storeType = 0; int32_t area = -1; + API_EXPORT SecretKeyMetaData(); API_EXPORT ~SecretKeyMetaData(); API_EXPORT bool Marshal(json &node) const override; diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data.h index 2d177634..201fccc0 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data.h @@ -21,7 +21,7 @@ #include "store/store_info.h" namespace OHOS::DistributedData { -struct API_EXPORT StoreMetaData final : public Serializable { +struct API_EXPORT StoreMetaData : public Serializable { // record meta version for compatible, should update when modify store meta data structure. static constexpr uint32_t CURRENT_VERSION = 0x03000006; // UID -> uid, deviceAccountId -> userId, userId -> user @@ -69,30 +69,60 @@ struct API_EXPORT StoreMetaData final : public Serializable { STORE_RELATIONAL_END = 19, STORE_OBJECT_BEGIN = 20, STORE_OBJECT_END = 29, + STORE_GDB_BEGIN = 30, + STORE_GDB_END = 39, STORE_BUTT = 255 }; API_EXPORT StoreMetaData(); API_EXPORT StoreMetaData(const std::string &userId, const std::string &appId, const std::string &storeId); API_EXPORT explicit StoreMetaData(const StoreInfo &storeInfo); - API_EXPORT ~StoreMetaData(); + API_EXPORT virtual ~StoreMetaData(); API_EXPORT bool operator==(const StoreMetaData &metaData) const; API_EXPORT bool operator!=(const StoreMetaData &metaData) const; API_EXPORT bool Marshal(json &node) const override; API_EXPORT bool Unmarshal(const json &node) override; - API_EXPORT std::string GetKey() const; - API_EXPORT std::string GetKeyLocal() const; - API_EXPORT std::string GetSecretKey() const; - API_EXPORT std::string GetStrategyKey() const; - API_EXPORT std::string GetBackupSecretKey() const; - API_EXPORT std::string GetAutoLaunchKey() const; - API_EXPORT std::string GetDebugInfoKey() const; - API_EXPORT std::string GetDfxInfoKey() const; - API_EXPORT std::string GetStoreAlias() const; - API_EXPORT StoreInfo GetStoreInfo() const; + API_EXPORT virtual std::string GetKeyWithoutPath() const; + API_EXPORT virtual std::string GetKey() const; + API_EXPORT virtual std::string GetKeyLocalWithoutPath() const; + API_EXPORT virtual std::string GetKeyLocal() const; + API_EXPORT virtual std::string GetSecretKeyWithoutPath() const; + API_EXPORT virtual std::string GetSecretKey() const; + API_EXPORT virtual std::string GetStrategyKey() const; + API_EXPORT virtual std::string GetBackupSecretKey() const; + API_EXPORT virtual std::string GetAutoLaunchKey() const; + API_EXPORT virtual std::string GetDebugInfoKey() const; + API_EXPORT virtual std::string GetDebugInfoKeyWithoutPath() const; + API_EXPORT virtual std::string GetDfxInfoKey() const; + API_EXPORT virtual std::string GetDfxInfoKeyWithoutPath() const; + API_EXPORT virtual std::string GetStoreAlias() const; + API_EXPORT virtual StoreInfo GetStoreInfo() const; + API_EXPORT virtual std::string GetCloneSecretKey() const; API_EXPORT static std::string GetKey(const std::initializer_list &fields); API_EXPORT static std::string GetPrefix(const std::initializer_list &fields); - API_EXPORT std::string GetCloneSecretKey() const; +}; + +struct API_EXPORT StoreMetaMapping final : public StoreMetaData { + static constexpr const char *KEY_PREFIX = "StoreMetaMapping"; + std::string cloudPath; + std::string devicePath; + std::string searchPath; + + API_EXPORT StoreMetaMapping(); + API_EXPORT StoreMetaMapping(const StoreMetaData &storeMeta); + API_EXPORT explicit StoreMetaMapping(const StoreInfo &storeInfo); + API_EXPORT ~StoreMetaMapping(); + API_EXPORT bool Marshal(json &node) const override; + API_EXPORT bool Unmarshal(const json &node) override; + API_EXPORT std::string GetKey() const override; + API_EXPORT std::string GetCloudStoreMetaKey() const; + API_EXPORT std::string GetDeviceStoreMetaKey() const; + API_EXPORT static std::string GetPrefix(const std::initializer_list &fields); + API_EXPORT StoreMetaMapping& operator=(const StoreMetaData &meta); + +private: + static std::string GetKey(const std::initializer_list &fields); + std::string GetStoreMetaKeyWithPath(const std::string &path) const; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_METADATA_STORE_META_DATA_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/version_meta_data.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/version_meta_data.h index 75b64a1d..3da3d359 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/version_meta_data.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/version_meta_data.h @@ -20,7 +20,9 @@ namespace OHOS::DistributedData { class API_EXPORT VersionMetaData final : public Serializable { public: - static constexpr int32_t CURRENT_VERSION = 4; + static constexpr int32_t CURRENT_VERSION = 5; + static constexpr int32_t UPDATE_STORE_META_KEY_VERSION = 5; + static constexpr int32_t UPDATE_SYNC_META_VERSION = 4; static constexpr int32_t INVALID_VERSION = -1; int32_t version = INVALID_VERSION; diff --git a/datamgr_service/services/distributeddataservice/framework/include/network/network_delegate.h b/datamgr_service/services/distributeddataservice/framework/include/network/network_delegate.h index ae7e9f94..38763f58 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/network/network_delegate.h +++ b/datamgr_service/services/distributeddataservice/framework/include/network/network_delegate.h @@ -19,7 +19,8 @@ #include #include -#include "types.h" +#include "executor_pool.h" +#include "visibility.h" namespace OHOS { namespace DistributedData { @@ -37,6 +38,7 @@ public: API_EXPORT static bool RegisterNetworkInstance(NetworkDelegate *instance); virtual bool IsNetworkAvailable() = 0; virtual void RegOnNetworkChange() = 0; + virtual void BindExecutor(std::shared_ptr executors) = 0; virtual NetworkType GetNetworkType(bool retrieve = false) = 0; private: diff --git a/datamgr_service/services/distributeddataservice/framework/include/serializable/serializable.h b/datamgr_service/services/distributeddataservice/framework/include/serializable/serializable.h index a0b6ad5a..93f88754 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/serializable/serializable.h +++ b/datamgr_service/services/distributeddataservice/framework/include/serializable/serializable.h @@ -62,6 +62,7 @@ public: API_EXPORT static bool GetValue(const json &node, const std::string &name, bool &value); API_EXPORT static bool GetValue(const json &node, const std::string &name, std::vector &value); API_EXPORT static bool GetValue(const json &node, const std::string &name, Serializable &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, double &value); API_EXPORT static bool SetValue(json &node, const std::string &value); API_EXPORT static bool SetValue(json &node, const uint32_t &value); API_EXPORT static bool SetValue(json &node, const int32_t &value); diff --git a/datamgr_service/services/distributeddataservice/framework/include/snapshot/snapshot.h b/datamgr_service/services/distributeddataservice/framework/include/snapshot/snapshot.h index 8a9fa7ee..8c1e46d5 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/snapshot/snapshot.h +++ b/datamgr_service/services/distributeddataservice/framework/include/snapshot/snapshot.h @@ -45,10 +45,6 @@ public: virtual bool IsBoundAsset(const Asset& asset) = 0; }; - -struct BindAssets { - std::shared_ptr>> bindAssets; -}; } // namespace DistributedData } // namespace OHOS #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_SNAPSHOT_SNAPSHOT_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h index 1549d0f1..be03ada1 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/auto_cache.h @@ -52,24 +52,24 @@ public: API_EXPORT std::pair GetDBStore(const StoreMetaData &meta, const Watchers &watchers); - API_EXPORT Stores GetStoresIfPresent(uint32_t tokenId, const std::string &storeName = "", - const std::string &userId = ""); - - API_EXPORT void CloseStore(uint32_t tokenId, const std::string &storeId = "", const std::string &userId = ""); + API_EXPORT Stores GetStoresIfPresent( + uint32_t tokenId, const std::string &path = "", const std::string &storeId = ""); + API_EXPORT void CloseStore(uint32_t tokenId, const std::string &path = "", const std::string &storeId = ""); + API_EXPORT void CloseStore(const Filter &filter); - - API_EXPORT void SetObserver(uint32_t tokenId, const std::string &storeId, const Watchers &watchers, - const std::string &userId = ""); - - API_EXPORT void Enable(uint32_t tokenId, const std::string &storeId = "", const std::string &userId = ""); - - API_EXPORT void Disable(uint32_t tokenId, const std::string &storeId, const std::string &userId = ""); + + API_EXPORT void SetObserver( + uint32_t tokenId, const Watchers &watchers, const std::string &path, const std::string &storeId = ""); + + API_EXPORT void Enable(uint32_t tokenId, const std::string &path = "", const std::string &storeId = ""); + + API_EXPORT void Disable(uint32_t tokenId, const std::string &path = "", const std::string &storeId = ""); private: AutoCache(); ~AutoCache(); - std::string GenerateKey(const std::string &userId, const std::string &storeId) const; + std::string GenerateKey(const std::string &path, const std::string &storeId) const; void GarbageCollect(bool isForce); void StartTimer(); struct Delegate : public GeneralWatcher { diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h index d50b1ab8..47429abd 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h @@ -46,7 +46,7 @@ public: CLOUD_BEGIN = 4, CLOUD_TIME_FIRST = CLOUD_BEGIN, CLOUD_NATIVE_FIRST, - CLOUD_ClOUD_FIRST, + CLOUD_CLOUD_FIRST, CLOUD_END, NEARBY_SUBSCRIBE_REMOTE, NEARBY_UNSUBSCRIBE_REMOTE, @@ -62,6 +62,7 @@ public: CLOUD_DATA, CLOUD_INFO, LOCAL_DATA, + CLEAN_WATER, CLEAN_MODE_BUTT }; @@ -114,6 +115,7 @@ public: int32_t maxNumber = 30; int32_t maxSize = 1024 * 512 * 3; // 1.5M int32_t maxRetryConflictTimes = 3; // default max retry 3 times when version conflict + bool isSupportEncrypt = false; }; enum class DistributedTableMode : int { diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h index e1f9b3a1..88ef5065 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h @@ -101,6 +101,7 @@ struct SyncParam { std::string prepareTraceId; int32_t user; bool asyncDownloadAsset = false; + bool isRetry = true; }; enum SyncStage : int8_t { @@ -115,6 +116,7 @@ struct ReportParam { std::string prepareTraceId; SyncStage syncStage = SyncStage::PREPARE; int32_t errCode = 0; + std::string message = ""; }; using Assets = std::vector; diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/store_info.h b/datamgr_service/services/distributeddataservice/framework/include/store/store_info.h index 8c5d02b2..3543cca5 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/store_info.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/store_info.h @@ -27,6 +27,7 @@ struct StoreInfo { int32_t user = 0; std::string deviceId; uint64_t syncId = 0; + std::string path; }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_STORE_INFO_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/thread/thread_manager.h b/datamgr_service/services/distributeddataservice/framework/include/thread/thread_manager.h index c213d6c9..c435b8dd 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/thread/thread_manager.h +++ b/datamgr_service/services/distributeddataservice/framework/include/thread/thread_manager.h @@ -29,7 +29,7 @@ public: private: ThreadManager(); - uint32_t minThreadNum_ = 5; // default min executor pool thread num + uint32_t minThreadNum_ = 2; // default min executor pool thread num uint32_t maxThreadNum_ = 12; // default max executor pool thread num uint32_t ipcThreadNum_ = 16; // normal ipc num }; diff --git a/datamgr_service/services/distributeddataservice/framework/include/utils/constant.h b/datamgr_service/services/distributeddataservice/framework/include/utils/constant.h index bfeaee6b..48aaf154 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/utils/constant.h +++ b/datamgr_service/services/distributeddataservice/framework/include/utils/constant.h @@ -44,6 +44,20 @@ public: API_EXPORT static std::vector Split(const std::string &str, const std::string &delim); + template + API_EXPORT static bool BatchProcess(const std::vector &value, size_t batchSize, Action action) + { + auto it = value.begin(); + while (it != value.end()) { + auto end = it + std::min(batchSize, static_cast(std::distance(it, value.end()))); + if (!action(it, end)) { + return false; + } + it = end; + } + return true; + } + template inline static constexpr bool is_pod = (std::is_standard_layout_v && std::is_trivial_v); diff --git a/datamgr_service/services/distributeddataservice/framework/metadata/capability_meta_data.cpp b/datamgr_service/services/distributeddataservice/framework/metadata/capability_meta_data.cpp index ab81aaeb..9e2d2947 100644 --- a/datamgr_service/services/distributeddataservice/framework/metadata/capability_meta_data.cpp +++ b/datamgr_service/services/distributeddataservice/framework/metadata/capability_meta_data.cpp @@ -20,10 +20,14 @@ namespace OHOS::DistributedData { constexpr int32_t CapMetaData::CURRENT_VERSION; constexpr int32_t CapMetaData::INVALID_VERSION; constexpr const char *CapMetaRow::KEY_PREFIX; +constexpr int32_t INDEX_NUM = 2; +constexpr int32_t INDEX_PREFIX = 0; +constexpr int32_t INDEX_DEVICE = 1; bool CapMetaData::Marshal(json &node) const { bool ret = true; ret = SetValue(node[GET_NAME(version)], version) && ret; + ret = SetValue(node[GET_NAME(deviceId)], deviceId) && ret; return ret; } @@ -31,6 +35,7 @@ bool CapMetaData::Unmarshal(const json &node) { bool ret = true; ret = GetValue(node, GET_NAME(version), version) && ret; + ret = GetValue(node, GET_NAME(deviceId), deviceId) && ret; return ret; } @@ -39,4 +44,13 @@ std::vector CapMetaRow::GetKeyFor(const std::string &key) std::string str = Constant::Concatenate({ KEY_PREFIX, Constant::KEY_SEPARATOR, key }); return { str.begin(), str.end() }; } + +const std::string CapMetaRow::GetDeviceId(const std::string &key) +{ + auto items = Constant::Split(key, Constant::KEY_SEPARATOR); + if (items.size() < INDEX_NUM || items[INDEX_PREFIX] != KEY_PREFIX) { + return ""; + } + return items[INDEX_DEVICE]; +} } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/framework/metadata/device_meta_data.cpp b/datamgr_service/services/distributeddataservice/framework/metadata/device_meta_data.cpp index c16c6400..c3aa1e3f 100644 --- a/datamgr_service/services/distributeddataservice/framework/metadata/device_meta_data.cpp +++ b/datamgr_service/services/distributeddataservice/framework/metadata/device_meta_data.cpp @@ -20,14 +20,12 @@ static constexpr const char *KEY_PREFIX = "DeviceMeta"; bool DeviceMetaData::Marshal(json &node) const { SetValue(node[GET_NAME(newUuid)], newUuid); - SetValue(node[GET_NAME(oldUuid)], oldUuid); return true; } bool DeviceMetaData::Unmarshal(const json &node) { GetValue(node, GET_NAME(newUuid), newUuid); - GetValue(node, GET_NAME(oldUuid), oldUuid); return true; } diff --git a/datamgr_service/services/distributeddataservice/framework/metadata/meta_data_manager.cpp b/datamgr_service/services/distributeddataservice/framework/metadata/meta_data_manager.cpp index e7ade4b8..a5cc012a 100644 --- a/datamgr_service/services/distributeddataservice/framework/metadata/meta_data_manager.cpp +++ b/datamgr_service/services/distributeddataservice/framework/metadata/meta_data_manager.cpp @@ -213,15 +213,51 @@ bool MetaDataManager::SaveMeta(const std::string &key, const Serializable &value ZLOGE("failed! status:%{public}d isLocal:%{public}d, key:%{public}s", status, isLocal, Anonymous::Change(key).c_str()); } + DelCacheMeta(key, isLocal); return status == DistributedDB::DBStatus::OK; } -bool MetaDataManager::LoadMeta(const std::string &key, Serializable &value, bool isLocal) +bool MetaDataManager::SaveMeta(const std::vector &values, bool isLocal) { if (!inited_) { return false; } + if (values.empty()) { + return true; + } + std::vector entries; + entries.reserve(values.size()); + for (const auto &[key, value] : values) { + entries.push_back({ { key.begin(), key.end() }, { value.begin(), value.end() } }); + DelCacheMeta(key, isLocal); + } + auto status = isLocal ? metaStore_->PutLocalBatch(entries) : metaStore_->PutBatch(entries); + if (status == DistributedDB::DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB) { + ZLOGE("db corrupted! status:%{public}d isLocal:%{public}d, size:%{public}zu", status, isLocal, values.size()); + CorruptReporter::CreateCorruptedFlag(DirectoryManager::GetInstance().GetMetaStorePath(), storeId_); + StopSA(); + return false; + } + if (status == DistributedDB::DBStatus::OK && backup_) { + backup_(metaStore_); + } + if (!isLocal && cloudSyncer_) { + cloudSyncer_(); + } + if (status != DistributedDB::DBStatus::OK) { + ZLOGE("failed! status:%{public}d isLocal:%{public}d, size:%{public}zu", status, isLocal, values.size()); + } + return status == DistributedDB::DBStatus::OK; +} +bool MetaDataManager::LoadMeta(const std::string &key, Serializable &value, bool isLocal) +{ + if (!inited_) { + return false; + } + if (LoadCacheMeta(key, value, isLocal)) { + return true; + } DistributedDB::Value data; auto status = isLocal ? metaStore_->GetLocal({ key.begin(), key.end() }, data) : metaStore_->Get({ key.begin(), key.end() }, data); @@ -235,7 +271,9 @@ bool MetaDataManager::LoadMeta(const std::string &key, Serializable &value, bool if (status != DistributedDB::DBStatus::OK) { return false; } - Serializable::Unmarshall({ data.begin(), data.end() }, value); + std::string tempdata(data.begin(), data.end()); + SaveCacheMeta(key, tempdata, isLocal); + Serializable::Unmarshall(tempdata, value); if (isLocal) { data.assign(data.size(), 0); } @@ -270,8 +308,7 @@ bool MetaDataManager::DelMeta(const std::string &key, bool isLocal) if (!inited_) { return false; } - - DistributedDB::Value data; + DelCacheMeta(key, isLocal); auto status = isLocal ? metaStore_->DeleteLocal({ key.begin(), key.end() }) : metaStore_->Delete({ key.begin(), key.end() }); if (status == DistributedDB::DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB) { @@ -290,18 +327,58 @@ bool MetaDataManager::DelMeta(const std::string &key, bool isLocal) return ((status == DistributedDB::DBStatus::OK) || (status == DistributedDB::DBStatus::NOT_FOUND)); } -bool MetaDataManager::Sync(const std::vector &devices, OnComplete complete, bool wait) +bool MetaDataManager::DelMeta(const std::vector &keys, bool isLocal) +{ + if (!inited_) { + return false; + } + if (keys.empty()) { + return true; + } + std::vector dbKeys; + dbKeys.reserve(keys.size()); + for (auto &key : keys) { + dbKeys.emplace_back(key.begin(), key.end()); + DelCacheMeta(key, isLocal); + } + auto status = isLocal ? metaStore_->DeleteLocalBatch(dbKeys) : metaStore_->DeleteBatch(dbKeys); + if (status == DistributedDB::DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB) { + ZLOGE("db corrupted! status:%{public}d isLocal:%{public}d, key size:%{public}zu", status, isLocal, + dbKeys.size()); + CorruptReporter::CreateCorruptedFlag(DirectoryManager::GetInstance().GetMetaStorePath(), storeId_); + StopSA(); + return false; + } + if (status == DistributedDB::DBStatus::OK && backup_) { + backup_(metaStore_); + } + if (!isLocal && cloudSyncer_) { + cloudSyncer_(); + } + return ((status == DistributedDB::DBStatus::OK) || (status == DistributedDB::DBStatus::NOT_FOUND)); +} + +bool MetaDataManager::Sync(const std::vector &devices, OnComplete complete, bool wait, bool isRetry) { if (!inited_ || devices.empty()) { return false; } - auto status = metaStore_->Sync(devices, DistributedDB::SyncMode::SYNC_MODE_PUSH_PULL, [complete](auto &dbResults) { - std::map results; - for (auto &[uuid, status] : dbResults) { - results.insert_or_assign(uuid, static_cast(status)); - } - complete(results); - }, wait); + DistributedDB::DeviceSyncOption syncOption; + syncOption.devices = devices; + syncOption.mode = DistributedDB::SyncMode::SYNC_MODE_PUSH_PULL; + syncOption.isWait = wait; + syncOption.isRetry = isRetry; + auto status = metaStore_->Sync(syncOption, + [complete](const std::map &dbResults) { + if (complete == nullptr) { + return; + } + std::map results; + for (auto &[uuid, status] : dbResults) { + results.insert_or_assign(uuid, static_cast(status)); + } + complete(results); + }); if (status == DistributedDB::DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB) { ZLOGE("db corrupted! status:%{public}d", status); CorruptReporter::CreateCorruptedFlag(DirectoryManager::GetInstance().GetMetaStorePath(), storeId_); diff --git a/datamgr_service/services/distributeddataservice/framework/metadata/object_user_meta_data.cpp b/datamgr_service/services/distributeddataservice/framework/metadata/object_user_meta_data.cpp new file mode 100644 index 00000000..c5d5d9e0 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/metadata/object_user_meta_data.cpp @@ -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. + */ +#include "metadata/object_user_meta_data.h" + +namespace OHOS::DistributedData { +ObjectUserMetaData::ObjectUserMetaData() +{ +} +bool ObjectUserMetaData::Marshal(json &node) const +{ + return SetValue(node[GET_NAME(userId)], userId); +} + +bool ObjectUserMetaData::Unmarshal(const json &node) +{ + return GetValue(node, GET_NAME(userId), userId); +} + +std::string ObjectUserMetaData::GetKey() +{ + return KEY_PREFIX; +} +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/metadata/secret_key_meta_data.cpp b/datamgr_service/services/distributeddataservice/framework/metadata/secret_key_meta_data.cpp index 168844c4..3af423fb 100644 --- a/datamgr_service/services/distributeddataservice/framework/metadata/secret_key_meta_data.cpp +++ b/datamgr_service/services/distributeddataservice/framework/metadata/secret_key_meta_data.cpp @@ -24,12 +24,14 @@ SecretKeyMetaData::SecretKeyMetaData() SecretKeyMetaData::~SecretKeyMetaData() { sKey.assign(sKey.size(), 0); + nonce.assign(nonce.size(), 0); } bool SecretKeyMetaData::Marshal(json &node) const { SetValue(node[GET_NAME(time)], time); SetValue(node[GET_NAME(sKey)], sKey); + SetValue(node[GET_NAME(nonce)], nonce); SetValue(node[GET_NAME(storeType)], storeType); SetValue(node[GET_NAME(area)], area); return true; @@ -39,6 +41,7 @@ bool SecretKeyMetaData::Unmarshal(const json &node) { GetValue(node, GET_NAME(time), time); GetValue(node, GET_NAME(sKey), sKey); + GetValue(node, GET_NAME(nonce), nonce); GetValue(node, GET_NAME(storeType), storeType); GetValue(node, GET_NAME(area), area); return true; diff --git a/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data.cpp b/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data.cpp index 61d67858..3dba8c53 100644 --- a/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data.cpp +++ b/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data.cpp @@ -22,6 +22,7 @@ #include "metadata/strategy_meta_data.h" #include "utils/anonymous.h" #include "utils/constant.h" +#include "utils/crypto.h" namespace OHOS { namespace DistributedData { constexpr uint32_t StoreMetaData::CURRENT_VERSION; @@ -127,8 +128,8 @@ StoreMetaData::StoreMetaData(const std::string &userId, const std::string &appId } StoreMetaData::StoreMetaData(const StoreInfo &storeInfo) - : instanceId(storeInfo.instanceId), bundleName(storeInfo.bundleName), storeId(storeInfo.storeName), - user(std::to_string(storeInfo.user)) + : instanceId(storeInfo.instanceId), bundleName(storeInfo.bundleName), dataDir(storeInfo.path), + storeId(storeInfo.storeName), user(std::to_string(storeInfo.user)) { } @@ -160,25 +161,26 @@ bool StoreMetaData::operator!=(const StoreMetaData &metaData) const std::string StoreMetaData::GetKey() const { if (instanceId == 0) { - return GetKey({ deviceId, user, "default", bundleName, storeId }); + return GetKey({ deviceId, user, "default", bundleName, storeId, dataDir }); } - return GetKey({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId) }); + return GetKey({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId), dataDir }); } std::string StoreMetaData::GetKeyLocal() const { if (instanceId == 0) { - return StoreMetaDataLocal::GetKey({ deviceId, user, "default", bundleName, storeId }); + return StoreMetaDataLocal::GetKey({ deviceId, user, "default", bundleName, storeId, dataDir }); } - return StoreMetaDataLocal::GetKey({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId) }); + return StoreMetaDataLocal::GetKey( + { deviceId, user, "default", bundleName, storeId, std::to_string(instanceId), dataDir }); } std::string StoreMetaData::GetSecretKey() const { if (version < UUID_CHANGED_TAG) { - return SecretKeyMetaData::GetKey({ user, "default", bundleName, storeId }); + return SecretKeyMetaData::GetKey({ user, "default", bundleName, storeId, dataDir }); } - return SecretKeyMetaData::GetKey({ user, "default", bundleName, storeId, std::to_string(instanceId) }); + return SecretKeyMetaData::GetKey({ user, "default", bundleName, storeId, std::to_string(instanceId), dataDir }); } std::string StoreMetaData::GetBackupSecretKey() const @@ -195,11 +197,23 @@ std::string StoreMetaData::GetAutoLaunchKey() const } std::string StoreMetaData::GetDebugInfoKey() const +{ + return StoreDebugInfo::GetPrefix( + { deviceId, user, "default", bundleName, storeId, std::to_string(instanceId), dataDir }); +} + +std::string StoreMetaData::GetDebugInfoKeyWithoutPath() const { return StoreDebugInfo::GetPrefix({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId) }); } std::string StoreMetaData::GetDfxInfoKey() const +{ + return StoreDfxInfo::GetPrefix( + { deviceId, user, "default", bundleName, storeId, std::to_string(instanceId), dataDir }); +} + +std::string StoreMetaData::GetDfxInfoKeyWithoutPath() const { return StoreDfxInfo::GetPrefix({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId) }); } @@ -245,5 +259,101 @@ std::string StoreMetaData::GetCloneSecretKey() const { return SecretKeyMetaData::GetCloneKey({ user, "default", bundleName, storeId, std::to_string(instanceId) }); } + +std::string StoreMetaData::GetKeyWithoutPath() const +{ + if (instanceId == 0) { + return GetKey({ deviceId, user, "default", bundleName, storeId }); + } + return GetKey({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId) }); +} + +std::string StoreMetaData::GetKeyLocalWithoutPath() const +{ + if (instanceId == 0) { + return StoreMetaDataLocal::GetKey({ deviceId, user, "default", bundleName, storeId }); + } + return StoreMetaDataLocal::GetKey({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId) }); +} + +std::string StoreMetaData::GetSecretKeyWithoutPath() const +{ + if (version < UUID_CHANGED_TAG) { + return SecretKeyMetaData::GetKey({ user, "default", bundleName, storeId }); + } + return SecretKeyMetaData::GetKey({ user, "default", bundleName, storeId, std::to_string(instanceId) }); +} + +StoreMetaMapping::StoreMetaMapping() {} +StoreMetaMapping::StoreMetaMapping(const StoreMetaData &storeMeta) : StoreMetaData(storeMeta) {} +StoreMetaMapping::~StoreMetaMapping() {} + +bool StoreMetaMapping::Marshal(json &node) const +{ + StoreMetaData::Marshal(node); + SetValue(node[GET_NAME(cloudPath)], cloudPath); + SetValue(node[GET_NAME(devicePath)], devicePath); + SetValue(node[GET_NAME(searchPath)], searchPath); + return true; +} +bool StoreMetaMapping::Unmarshal(const Serializable::json &node) +{ + StoreMetaData::Unmarshal(node); + GetValue(node, GET_NAME(cloudPath), cloudPath); + GetValue(node, GET_NAME(devicePath), devicePath); + GetValue(node, GET_NAME(searchPath), searchPath); + return true; +} + +std::string StoreMetaMapping::GetKey() const +{ + if (instanceId == 0) { + return GetKey({ deviceId, user, "default", bundleName, storeId }); + } + return GetKey({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId) }); +} + +std::string StoreMetaMapping::GetCloudStoreMetaKey() const +{ + return GetStoreMetaKeyWithPath(cloudPath); +} + +std::string StoreMetaMapping::GetDeviceStoreMetaKey() const +{ + return GetStoreMetaKeyWithPath(devicePath); +} + +std::string StoreMetaMapping::GetPrefix(const std::initializer_list &fields) +{ + return GetKey(fields).append(Constant::KEY_SEPARATOR); +} + +StoreMetaMapping& StoreMetaMapping::operator=(const StoreMetaData &meta) +{ + if (this == &meta) { + return *this; + } + this->StoreMetaData::operator=(meta); + return *this; +} + +std::string StoreMetaMapping::GetStoreMetaKeyWithPath(const std::string &path) const +{ + if (instanceId == 0) { + return StoreMetaData::GetKey({ deviceId, user, "default", bundleName, storeId, path }); + } + return StoreMetaData::GetKey({ deviceId, user, "default", bundleName, storeId, std::to_string(instanceId), path }); +} + +std::string StoreMetaMapping::GetKey(const std::initializer_list &fields) +{ + std::string prefix = KEY_PREFIX; + for (const auto &field : fields) { + prefix.append(Constant::KEY_SEPARATOR).append(field); + } + return prefix; +} +StoreMetaMapping::StoreMetaMapping(const StoreInfo &storeInfo) : StoreMetaData(storeInfo) {} + } // namespace DistributedData } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp b/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp index 253a9323..9eec3a30 100644 --- a/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp +++ b/datamgr_service/services/distributeddataservice/framework/serializable/serializable.cpp @@ -141,6 +141,16 @@ bool Serializable::GetValue(const json &node, const std::string &name, bool &val return false; } +bool Serializable::GetValue(const json &node, const std::string &name, double &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_number_float()) { + return false; + } + subNode.get_to(value); + return true; +} + bool Serializable::GetValue(const json &node, const std::string &name, std::vector &value) { auto &subNode = GetSubNode(node, name); @@ -230,5 +240,6 @@ const Serializable::json &Serializable::GetSubNode(const json &node, const std:: } return *it; } + } // namespace DistributedData -} // namespace OHOS +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp index 0b17f5bc..4253619e 100644 --- a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp +++ b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp @@ -17,11 +17,11 @@ #include -#include "account_delegate.h" +#include "account/account_delegate.h" #include "changeevent/remote_change_event.h" #include "eventcenter/event_center.h" #include "log_print.h" -#include "screenlock/screen_lock.h" +#include "screen/screen_manager.h" #include "utils/anonymous.h" namespace OHOS::DistributedData { using Account = AccountDelegate; @@ -61,24 +61,25 @@ AutoCache::~AutoCache() } } -std::string AutoCache::GenerateKey(const std::string &userId, const std::string &storeId) const +std::string AutoCache::GenerateKey(const std::string &path, const std::string &storeId) const { std::string key = ""; - if (userId.empty() || storeId.empty()) { + if (path.empty() || storeId.empty()) { return key; } - return key.append(userId).append(KEY_SEPARATOR).append(storeId); + return key.append(path).append(KEY_SEPARATOR).append(storeId); } std::pair AutoCache::GetDBStore(const StoreMetaData &meta, const Watchers &watchers) { Store store; - auto storeKey = GenerateKey(meta.user, meta.storeId); + auto storeKey = GenerateKey(meta.dataDir, meta.storeId); if (meta.storeType >= MAX_CREATOR_NUM || meta.storeType < 0 || !creators_[meta.storeType] || disables_.ContainIf(meta.tokenId, [&storeKey](const std::set &stores) -> bool { return stores.count(storeKey) != 0; })) { - ZLOGW("storeType is invalid or store is disabled,user:%{public}s,bundleName:%{public}s,storeName:%{public}s", - meta.user.c_str(), meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); + ZLOGW("storeType %{public}d is invalid or store is disabled, user:%{public}s, bundleName:%{public}s, " + "storeName:%{public}s", meta.storeType, meta.user.c_str(), meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); return { E_ERROR, store }; } if (meta.area == GeneralStore::EL4 && ScreenManager::GetInstance()->IsLocked()) { @@ -126,11 +127,10 @@ AutoCache::Store AutoCache::GetStore(const StoreMetaData &meta, const Watchers & return GetDBStore(meta, watchers).second; } -AutoCache::Stores AutoCache::GetStoresIfPresent(uint32_t tokenId, const std::string &storeName, - const std::string &userId) +AutoCache::Stores AutoCache::GetStoresIfPresent(uint32_t tokenId, const std::string &path, const std::string &storeName) { Stores stores; - auto storeKey = GenerateKey(userId, storeName); + auto storeKey = GenerateKey(path, storeName); stores_.ComputeIfPresent( tokenId, [&stores, &storeKey](auto &, std::map &delegates) -> bool { if (storeKey.empty()) { @@ -170,13 +170,13 @@ void AutoCache::StartTimer() ZLOGD("start timer,taskId: %{public}" PRIu64, taskId_); } -void AutoCache::CloseStore(uint32_t tokenId, const std::string &storeId, const std::string &userId) +void AutoCache::CloseStore(uint32_t tokenId, const std::string &path, const std::string &storeId) { ZLOGD("close store start, store:%{public}s, token:%{public}u", Anonymous::Change(storeId).c_str(), tokenId); std::set storeIds; std::list closeStores; bool isScreenLocked = ScreenManager::GetInstance()->IsLocked(); - auto storeKey = GenerateKey(userId, storeId); + auto storeKey = GenerateKey(path, storeId); stores_.ComputeIfPresent(tokenId, [this, &storeKey, isScreenLocked, &storeIds, &closeStores](auto &, auto &delegates) { auto it = delegates.begin(); @@ -241,10 +241,10 @@ void AutoCache::CloseStore(const AutoCache::Filter &filter) }); } -void AutoCache::SetObserver(uint32_t tokenId, const std::string &storeId, const AutoCache::Watchers &watchers, - const std::string &userId) +void AutoCache::SetObserver(uint32_t tokenId, const AutoCache::Watchers &watchers, const std::string &path, + const std::string &storeId) { - auto storeKey = GenerateKey(userId, storeId); + auto storeKey = GenerateKey(path, storeId); stores_.ComputeIfPresent(tokenId, [&storeKey, &watchers](auto &key, auto &stores) { ZLOGD("tokenId:0x%{public}x storeId:%{public}s observers:%{public}zu", key, Anonymous::Change(storeKey).c_str(), watchers.size()); @@ -274,23 +274,23 @@ void AutoCache::GarbageCollect(bool isForce) }); } -void AutoCache::Enable(uint32_t tokenId, const std::string &storeId, const std::string &userId) +void AutoCache::Enable(uint32_t tokenId, const std::string &path, const std::string &storeId) { - auto storeKey = GenerateKey(userId, storeId); + auto storeKey = GenerateKey(path, storeId); disables_.ComputeIfPresent(tokenId, [&storeKey](auto key, std::set &stores) { stores.erase(storeKey); return !(stores.empty() || storeKey.empty()); }); } -void AutoCache::Disable(uint32_t tokenId, const std::string &storeId, const std::string &userId) +void AutoCache::Disable(uint32_t tokenId, const std::string &path, const std::string &storeId) { - auto storeKey = GenerateKey(userId, storeId); + auto storeKey = GenerateKey(path, storeId); disables_.Compute(tokenId, [&storeKey](auto key, std::set &stores) { stores.insert(storeKey); return !stores.empty(); }); - CloseStore(tokenId, storeId, userId); + CloseStore(tokenId, path, storeId); } AutoCache::Delegate::Delegate(GeneralStore *delegate, const Watchers &watchers, int32_t user, const StoreMetaData &meta) diff --git a/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn index 24a5a8d6..37a5bafd 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/framework/test/BUILD.gn @@ -21,30 +21,19 @@ config("module_private_config") { visibility = [ ":*" ] include_dirs = [ - "${device_manager_path}/interfaces/inner_kits/native_cpp/include", - "../include/", - "../../service/bootstrap/include/", - "../../service/common/", - "../../service/rdb/", - "../../../../../relational_store/interfaces/inner_api/rdb/include", - "../../../../../relational_store/interfaces/inner_api/common_type/include", - "${kv_store_distributeddb_path}/interfaces/include", - "${kv_store_distributeddb_path}/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/src", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_path}/interfaces/innerkits/distributeddata/include", + "${data_service_path}/service/bootstrap/include/", + "${data_service_path}/service/common/", + "${data_service_path}/service/rdb/", "${data_service_path}/adapter/include", "${data_service_path}/framework/include", "${data_service_path}/service/config/include", "${data_service_path}/app/src", "${data_service_path}/adapter/include/account", + "${data_service_path}/adapter/include/communicator", "${data_service_path}/app/src/security", "${data_service_path}/service/crypto/include", "${data_service_path}/service/matrix/include", - "//third_party/json/single_include", + "${data_service_path}/service/kvdb", ] cflags = [ "-Werror" ] ldflags = [ "-Wl,--whole-archive" ] @@ -59,19 +48,19 @@ ohos_unittest("CheckerManagerTest") { external_deps = [ "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddata_inner", + "openssl:libcrypto_shared", ] deps = [ "${data_service_path}/app/src/checker:distributeddata_checker", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/service:distributeddatasvc", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", ] } @@ -83,15 +72,13 @@ ohos_unittest("EventCenterTest") { external_deps = [ "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddata_inner", ] - deps = [ - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", - ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] } ohos_unittest("SerializableTest") { @@ -105,16 +92,14 @@ ohos_unittest("SerializableTest") { "ability_base:base", "ability_base:want", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddata_inner", + "openssl:libcrypto_shared", ] - deps = [ - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] } ohos_unittest("ServiceUtilsTest") { @@ -133,14 +118,14 @@ ohos_unittest("ServiceUtilsTest") { "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "json:nlohmann_json_static", + "kv_store:datamgr_common", ] - deps = [ - "${data_service_path}/framework:distributeddatasvcfwk", - "//third_party/googletest:gtest_main", - ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] } ohos_unittest("StoreTest") { @@ -170,6 +155,8 @@ ohos_unittest("StoreTest") { "access_token:libnativetoken", "c_utils:utils", "common_event_service:cesfwk_innerkits", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_inner", @@ -183,7 +170,6 @@ ohos_unittest("StoreTest") { "${data_service_path}/service:distributeddatasvc", "${data_service_path}/service/common:distributeddata_common", "${data_service_path}/service/test/mock:distributeddata_mock_static", - "//third_party/googletest:gtest_main", ] } @@ -192,6 +178,10 @@ ohos_unittest("AssetLoaderTest") { sources = [ "asset_loader_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + + external_deps = [ + "kv_store:datamgr_common", + ] } ohos_unittest("BackupRuleManagerTest") { @@ -199,6 +189,10 @@ ohos_unittest("BackupRuleManagerTest") { sources = [ "backup_rule_manager_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + + external_deps = [ + "kv_store:datamgr_common", + ] } ohos_unittest("BindEventTest") { @@ -206,6 +200,10 @@ ohos_unittest("BindEventTest") { sources = [ "bind_event_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + + external_deps = [ + "kv_store:datamgr_common", + ] } ohos_unittest("CloudInfoTest") { @@ -213,6 +211,12 @@ ohos_unittest("CloudInfoTest") { sources = [ "cloud_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + + external_deps = [ + "c_utils:utils", + "json:nlohmann_json_static", + "kv_store:datamgr_common", + ] } ohos_unittest("EventTest") { @@ -220,6 +224,10 @@ ohos_unittest("EventTest") { sources = [ "event_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + + external_deps = [ + "kv_store:datamgr_common", + ] } ohos_unittest("GeneralStoreTest") { @@ -227,6 +235,10 @@ ohos_unittest("GeneralStoreTest") { sources = [ "general_store_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + external_deps = [ + "c_utils:utils", + "kv_store:datamgr_common", + ] } ohos_unittest("SubscriptionTest") { @@ -234,35 +246,44 @@ ohos_unittest("SubscriptionTest") { sources = [ "subscription_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + external_deps = [ + "json:nlohmann_json_static", + "kv_store:datamgr_common", + ] } ohos_unittest("FeatureTest") { module_out_path = module_output_path sources = [ "feature_test.cpp" ] configs = [ ":module_private_config" ] - deps = [ - "${data_service_path}/framework:distributeddatasvcfwk", - "${kv_store_path}/interfaces/innerkits/distributeddata:distributeddata_inner", - ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + external_deps = [ "kv_store:distributeddata_inner" ] } ohos_unittest("MetaDataManagerTest") { module_out_path = module_output_path - sources = [ "meta_data_manager_test.cpp" ] + sources = [ + "meta_data_manager_test.cpp", + "mock/db_store_mock.cpp", + ] configs = [ ":module_private_config" ] external_deps = [ "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "json:nlohmann_json_static", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "kv_store:distributeddata_inner", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//third_party/googletest:gtest_main", ] } @@ -271,6 +292,13 @@ ohos_unittest("StoreMetaDataLocalTest") { sources = [ "store_meta_data_local_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + + external_deps = [ + "json:nlohmann_json_static", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "kv_store:distributeddata_inner", + ] } ohos_unittest("ConstantTest") { @@ -278,6 +306,10 @@ ohos_unittest("ConstantTest") { sources = [ "constant_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + + external_deps = [ + "kv_store:datamgr_common", + ] } ohos_unittest("CryptoTest") { @@ -285,6 +317,10 @@ ohos_unittest("CryptoTest") { sources = [ "crypto_test.cpp" ] configs = [ ":module_private_config" ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + + external_deps = [ + "kv_store:datamgr_common", + ] } ohos_unittest("ServiceMetaDataTest") { @@ -308,47 +344,22 @@ ohos_unittest("ServiceMetaDataTest") { configs = [ ":module_private_config" ] - include_dirs = [ - "${device_manager_path}/interfaces/inner_kits/native_cpp/include", - "../include/", - "../../service/bootstrap/include/", - "../../service/common/", - "../../service/rdb/", - "../../../../../relational_store/interfaces/inner_api/rdb/include", - "../../../../../relational_store/interfaces/inner_api/common_type/include", - "${kv_store_distributeddb_path}/interfaces/include", - "${kv_store_distributeddb_path}/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/src", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_path}/interfaces/innerkits/distributeddata/include", - "${data_service_path}/adapter/include", - "${data_service_path}/framework/include", - "${data_service_path}/service/config/include", - "${data_service_path}/app/src", - "${data_service_path}/adapter/include/account", - "${data_service_path}/app/src/security", - "${data_service_path}/service/crypto/include", - "${data_service_path}/service/matrix/include", - "${data_service_path}/service/kvdb", - "//third_party/json/single_include", - "${data_service_path}/adapter/include/communicator", - ] - external_deps = [ "c_utils:utils", "dataclassification:data_transit_mgr", "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", "hitrace:libhitracechain", "ipc:ipc_core", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", "kv_store:distributeddb", + "openssl:libcrypto_shared", "safwk:system_ability_fwk", "samgr:samgr_proxy", ] @@ -360,14 +371,42 @@ ohos_unittest("ServiceMetaDataTest") { "${data_service_path}/app/src/checker:distributeddata_checker", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/kvdb:distributeddata_kvdb", - "${kv_store_distributeddb_path}:distributeddb", - "${kv_store_path}/interfaces/innerkits/distributeddata:distributeddata_inner", - "${kv_store_path}/interfaces/innerkits/distributeddatamgr:distributeddata_mgr", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", ] } +ohos_unittest("ScreenManagerTest") { + module_out_path = module_output_path + sources = [ "screen_manager_test.cpp" ] + configs = [ ":module_private_config" ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + external_deps = [ "kv_store:datamgr_common" ] +} + +ohos_unittest("AppIdMappingConfigManagerTest") { + module_out_path = module_output_path + sources = [ "app_id_mapping_config_manager_test.cpp" ] + configs = [ ":module_private_config" ] + cflags = [ "-fno-access-control" ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + external_deps = [ "kv_store:datamgr_common" ] +} + +ohos_unittest("ConnectManagerTest") { + module_out_path = module_output_path + sources = [ "connect_manager_test.cpp" ] + configs = [ ":module_private_config" ] + cflags = [ "-fno-access-control" ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + external_deps = [ "kv_store:datamgr_common" ] +} + +ohos_unittest("DeviceSyncAppManagerTest") { + module_out_path = module_output_path + sources = [ "device_sync_app_manager_test.cpp" ] + configs = [ ":module_private_config" ] + deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + external_deps = [ "kv_store:datamgr_common" ] +} ############################################################################### group("unittest") { testonly = true @@ -375,18 +414,22 @@ group("unittest") { deps = [] deps += [ + ":AppIdMappingConfigManagerTest", ":AssetLoaderTest", ":BackupRuleManagerTest", ":BindEventTest", ":CheckerManagerTest", ":CloudInfoTest", + ":ConnectManagerTest", ":ConstantTest", ":CryptoTest", + ":DeviceSyncAppManagerTest", ":EventCenterTest", ":EventTest", ":FeatureTest", ":GeneralStoreTest", ":MetaDataManagerTest", + ":ScreenManagerTest", ":SerializableTest", ":ServiceMetaDataTest", ":ServiceUtilsTest", diff --git a/datamgr_service/services/distributeddataservice/framework/test/app_id_mapping_config_manager_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/app_id_mapping_config_manager_test.cpp new file mode 100644 index 00000000..c441ba91 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/app_id_mapping_config_manager_test.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 "app_id_mapping/app_id_mapping_config_manager.h" + +#include + +using namespace testing::ext; +using namespace OHOS::DistributedData; +namespace OHOS::Test { +class AppIdMappingConfigManagerTest : public testing::Test {}; + +/** +* @tc.name: Convert +* @tc.desc: Generate a pair based on the input appId and accountId. +* @tc.type: FUNC +*/ +HWTEST_F(AppIdMappingConfigManagerTest, Convert01, TestSize.Level1) +{ + std::vector mapper = { + {"src1", "dst1"}, + {"src2", "dst2"}, + {"src3", "dst3"} + }; + AppIdMappingConfigManager::GetInstance().Initialize(mapper); + auto result = AppIdMappingConfigManager::GetInstance().Convert("123", "123456789"); + EXPECT_EQ(result.first, "123"); + EXPECT_EQ(result.second, "123456789"); + result = AppIdMappingConfigManager::GetInstance().Convert("src1", "987654321"); + EXPECT_EQ(result.first, "dst1"); + EXPECT_EQ(result.second, "default"); +} + +/** +* @tc.name: Convert +* @tc.desc: Convert the input appId to another id. +* @tc.type: FUNC +*/ +HWTEST_F(AppIdMappingConfigManagerTest, Convert02, TestSize.Level1) +{ + std::vector mapper = { + {"src1", "dst1"}, + {"src2", "dst2"}, + {"src3", "dst3"} + }; + AppIdMappingConfigManager::GetInstance().Initialize(mapper); + auto result = AppIdMappingConfigManager::GetInstance().Convert("321"); + EXPECT_EQ(result, "321");; + result = AppIdMappingConfigManager::GetInstance().Convert("src1"); + EXPECT_EQ(result, "dst1"); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/cloud_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/cloud_test.cpp index 1940f95f..57e4ab7e 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/cloud_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/cloud_test.cpp @@ -22,7 +22,6 @@ #include "cloud/cloud_info.h" #include "cloud/cloud_server.h" #include "cloud/schema_meta.h" -#include "nlohmann/json.hpp" #include "utils/crypto.h" #include "screen/screen_manager.h" #include "store/general_store.h" @@ -502,9 +501,9 @@ HWTEST_F(ServicesCloudDBTest, CloudDB, TestSize.Level0) EXPECT_EQ(result1, GeneralError::E_NOT_SUPPORT); auto result2 = cloudDB.Query(table, extend); - EXPECT_EQ(result2, nullptr); + EXPECT_EQ(result2.second, nullptr); result2 = cloudDB.Query(query, extend); - EXPECT_EQ(result2, nullptr); + EXPECT_EQ(result2.second, nullptr); auto result3 = cloudDB.AliveTime(); EXPECT_EQ(result3, -1); @@ -547,16 +546,4 @@ HWTEST_F(CloudEventTest, GetEventId, TestSize.Level0) auto ret = event.GetEventId(); EXPECT_EQ(ret, evtId); } - -/** -* @tc.name: IsLocked -* @tc.desc: test IsLocked function -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(ScreenManagerTest, IsLocked, TestSize.Level0) -{ - ASSERT_FALSE(ScreenManager::GetInstance()->IsLocked()); -} } // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/framework/test/connect_manager_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/connect_manager_test.cpp new file mode 100644 index 00000000..7965d9eb --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/connect_manager_test.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 "communication/connect_manager.h" + +#include + +using namespace testing::ext; +using namespace OHOS::AppDistributedKv; +namespace OHOS::Test { +class ConnectManagerTest : public testing::Test {}; + +/** +* @tc.name: RegisterInstance +* @tc.desc: Register Instance. +* @tc.type: FUNC +*/ +HWTEST_F(ConnectManagerTest, RegisterInstance, TestSize.Level1) +{ + auto instance = ConnectManager::GetInstance(); + ASSERT_NE(instance, nullptr); + auto result = ConnectManager::RegisterInstance(std::make_shared()); + ASSERT_TRUE(result); + ASSERT_NE(ConnectManager::GetInstance(), nullptr); +} + +/** +* @tc.name: CloseSession +* @tc.desc: Close the session related to the networkid. +* @tc.type: FUNC +*/ +HWTEST_F(ConnectManagerTest, CloseSession, TestSize.Level1) +{ + auto ret = ConnectManager::GetInstance()->CloseSession(""); + ASSERT_FALSE(ret); + ConnectManager::GetInstance()->closeSessionTask_ = [](const std::string &networkId) { + return true; + }; + ret = ConnectManager::GetInstance()->CloseSession(""); + ASSERT_TRUE(ret); +} + +/** +* @tc.name: RegisterCloseSessionTask +* @tc.desc: Only one session closing task can be registered. +* @tc.type: FUNC +*/ +HWTEST_F(ConnectManagerTest, RegisterCloseSessionTask, TestSize.Level1) +{ + ConnectManager::GetInstance()->closeSessionTask_ = [](const std::string &networkId) { + return true; + }; + auto ret = ConnectManager::GetInstance()->RegisterCloseSessionTask([](const std::string &networkId) { + return true; + }); + ASSERT_FALSE(ret); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/device_sync_app_manager_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/device_sync_app_manager_test.cpp new file mode 100644 index 00000000..6ae441b9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/device_sync_app_manager_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 "device_sync_app/device_sync_app_manager.h" +#include + +using namespace testing::ext; +using namespace OHOS::DistributedData; + +namespace OHOS::Test { +class DeviceSyncAppManagerTest : public testing::Test { +public: + void SetUp() + { + whiteList1 = {"appId1", "bundleName1", 1}; + whiteList2 = {"appId2", "bundleName2", 2}; + whiteList3 = {"appId3", "bundleName3", 3}; + + std::vector lists = {whiteList1, whiteList2, whiteList3}; + DeviceSyncAppManager::GetInstance().Initialize(lists); + } + + DeviceSyncAppManager::WhiteList whiteList1; + DeviceSyncAppManager::WhiteList whiteList2; + DeviceSyncAppManager::WhiteList whiteList3; +}; + +/** +* @tc.name: Check001 +* @tc.desc: Checks that the given WhiteList object exists in whiteLists_ list. +* @tc.type: FUNC +*/ +HWTEST_F(DeviceSyncAppManagerTest, Check001, TestSize.Level1) +{ + DeviceSyncAppManager::WhiteList whiteList = {"appId1", "bundleName1", 1}; + bool result = DeviceSyncAppManager::GetInstance().Check(whiteList); + EXPECT_TRUE(result); +} + +/** +* @tc.name: Check002 +* @tc.desc: Check that the given appId object does not match. +* @tc.type: FUNC +*/ +HWTEST_F(DeviceSyncAppManagerTest, Check002, TestSize.Level1) +{ + DeviceSyncAppManager::WhiteList testList = {"appId2", "bundleName1", 1}; + bool result = DeviceSyncAppManager::GetInstance().Check(testList); + EXPECT_FALSE(result); +} + +/** +* @tc.name: Check003 +* @tc.desc: Check that the given bundleName object does not match. +* @tc.type: FUNC +*/ +HWTEST_F(DeviceSyncAppManagerTest, Check003, TestSize.Level1) +{ + DeviceSyncAppManager::WhiteList testList = {"appId1", "bundleName2", 1}; + bool result = DeviceSyncAppManager::GetInstance().Check(testList); + EXPECT_FALSE(result); +} + +/** +* @tc.name: Check004 +* @tc.desc: Check that the given version object does not match. +* @tc.type: FUNC +*/ +HWTEST_F(DeviceSyncAppManagerTest, Check004, TestSize.Level1) +{ + DeviceSyncAppManager::WhiteList testList = {"appId1", "bundleName1", 2}; + bool result = DeviceSyncAppManager::GetInstance().Check(testList); + EXPECT_FALSE(result); +} + +/** +* @tc.name: Check005 +* @tc.desc: Checks that the given WhiteList object does not exist in whiteLists_ list. +* @tc.type: FUNC +*/ +HWTEST_F(DeviceSyncAppManagerTest, Check005, TestSize.Level1) +{ + DeviceSyncAppManager::WhiteList whiteList = {"appId4", "bundleName4", 4}; + bool result = DeviceSyncAppManager::GetInstance().Check(whiteList); + EXPECT_FALSE(result); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/BUILD.gn new file mode 100644 index 00000000..b35cb67a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/BUILD.gn @@ -0,0 +1,25 @@ +# 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/ohos.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +######################################################################################### +group("fuzztest") { + testonly = true + + deps = [ + "storedebuginfo_fuzzer:fuzztest", + "screenmanager_fuzzer:fuzztest", + ] +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/BUILD.gn new file mode 100644 index 00000000..f063faa1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/BUILD.gn @@ -0,0 +1,55 @@ +# 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("ScreenManagerFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + include_dirs = [ + "${data_service_path}/framework/include", + ] + + fuzz_config_file = + "${data_service_path}/framework/test/fuzztest/screenmanager_fuzzer" + + sources = [ "screenmanager_fuzzer.cpp" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "kv_store:datamgr_common", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":ScreenManagerFuzzTest" ] +} +############################################################################### \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/corpus/init new file mode 100644 index 00000000..7ade8a0f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/project.xml new file mode 100644 index 00000000..a37a23b1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/rddbrepair_fuzzer.cpp b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/screenmanager_fuzzer.cpp similarity index 53% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/rddbrepair_fuzzer.cpp rename to datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/screenmanager_fuzzer.cpp index ce6c2faf..d944f95c 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/rddbrepair_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/screenmanager_fuzzer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 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,24 +13,28 @@ * limitations under the License. */ -#include "rd_utils.h" -#include "rdb_errno.h" -#include "rdb_store_config.h" -#include "rdb_store_impl.h" -using namespace OHOS; -using namespace OHOS::NativeRdb; -namespace OHOS { +#include +#include "screenmanager_fuzzer.h" +#include "screen/screen_manager.h" + +using namespace OHOS::DistributedData; -void rddbrepairFuzzer(const uint8_t *data, size_t size) +namespace OHOS { +void TestScreenManager(FuzzedDataProvider &provider) { - RdUtils::RdDbRepair(reinterpret_cast(data), reinterpret_cast(data)); + ScreenManager::GetInstance()->Subscribe(nullptr); + ScreenManager::GetInstance()->Unsubscribe(nullptr); + ScreenManager::GetInstance()->BindExecutor(nullptr); + ScreenManager::GetInstance()->SubscribeScreenEvent(); + ScreenManager::GetInstance()->UnsubscribeScreenEvent(); } + } // namespace OHOS /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - /* Run your code on data */ - OHOS::rddbrepairFuzzer(data, size); + FuzzedDataProvider provider(data, size); + OHOS::TestScreenManager(provider); return 0; -} +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/screenmanager_fuzzer.h b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/screenmanager_fuzzer.h new file mode 100644 index 00000000..ab2fe6fe --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/screenmanager_fuzzer/screenmanager_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 SCREENMANAGER_FUZZER_H +#define SCREENMANAGER_FUZZER_H + +#define FUZZ_PROJECT_NAME "screenmanager_fuzzer" + +#endif // SCREENMANAGER_FUZZER_H diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/BUILD.gn new file mode 100644 index 00000000..a44f574a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/BUILD.gn @@ -0,0 +1,56 @@ +# 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("StoreDebugInfoFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + include_dirs = [ + "${data_service_path}/framework/include", + ] + + fuzz_config_file = + "${data_service_path}/framework/test/fuzztest/storedebuginfo_fuzzer" + + sources = [ "storedebuginfo_fuzzer.cpp" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "json:nlohmann_json_static", + "kv_store:datamgr_common", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":StoreDebugInfoFuzzTest" ] +} +############################################################################### \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/corpus/init new file mode 100644 index 00000000..7ade8a0f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/project.xml new file mode 100644 index 00000000..a37a23b1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/storedebuginfo_fuzzer.cpp b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/storedebuginfo_fuzzer.cpp new file mode 100644 index 00000000..f497a3d1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/storedebuginfo_fuzzer.cpp @@ -0,0 +1,55 @@ +/* + * 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 "storedebuginfo_fuzzer.h" +#include "metadata/store_debug_info.h" + +using namespace OHOS::DistributedData; + +namespace OHOS { + +void StoreDebugInfoFuzz(FuzzedDataProvider &provider) +{ + StoreDebugInfo::FileInfo fileInfo; + StoreDebugInfo debugInfo; + std::string fileName = "filename"; + debugInfo.fileInfos.insert(std::make_pair(fileName, fileInfo)); + Serializable::json node; + std::string key = provider.ConsumeRandomLengthString(); + std::string valueStr = provider.ConsumeRandomLengthString(); + int valueInt = provider.ConsumeIntegral(); + float valueFloat = provider.ConsumeFloatingPoint(); + bool valueBool = provider.ConsumeBool(); + int valueRange = provider.ConsumeIntegralInRange(0, 100); + node[key] = valueStr; + node["integer"] = valueInt; + node["float"] = valueFloat; + node["boolean"] = valueBool; + node["range"] = valueRange; + fileInfo.Marshal(node); + fileInfo.Unmarshal(node); + debugInfo.Marshal(node); + debugInfo.Unmarshal(node); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::StoreDebugInfoFuzz(provider); + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/storedebuginfo_fuzzer.h b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/storedebuginfo_fuzzer.h new file mode 100644 index 00000000..152fe67a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/fuzztest/storedebuginfo_fuzzer/storedebuginfo_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 STOREDEBUGINFO_FUZZER_H +#define STOREDEBUGINFO_FUZZER_H + +#define FUZZ_PROJECT_NAME "storedebuginfo_fuzzer" + +#endif // STOREDEBUGINFO_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/meta_data_manager_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/meta_data_manager_test.cpp index a733b88c..da055af3 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/meta_data_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/meta_data_manager_test.cpp @@ -14,26 +14,61 @@ */ #define LOG_TAG "MetaDataManagerTest" -#include "log_print.h" #include "metadata/meta_data_manager.h" #include + +#include "log_print.h" +#include "mock/db_store_mock.h" using namespace OHOS; using namespace testing::ext; using namespace OHOS::DistributedData; using namespace OHOS::DistributedKv; namespace OHOS::Test { +class DBStoreMockImpl; class MetaDataManagerTest : public testing::Test { public: static const std::string INVALID_DEVICE_ID; - static const std::string EMPTY_DEVICE_ID; - static void SetUpTestCase(void) {}; + static void SetUpTestCase(void); static void TearDownTestCase(void) {}; void SetUp() {}; void TearDown() {}; + static std::shared_ptr metaStore; }; const std::string MetaDataManagerTest::INVALID_DEVICE_ID = "1234567890"; -const std::string MetaDataManagerTest::EMPTY_DEVICE_ID = ""; +std::shared_ptr MetaDataManagerTest::metaStore = nullptr; +class DBStoreMockImpl : public DBStoreMock { +public: + using PutLocalBatchFunc = std::function &)>; + PutLocalBatchFunc putLocalBatchFunc; + DBStatus PutLocalBatch(const std::vector &entries) override + { + if (putLocalBatchFunc) { + return putLocalBatchFunc(entries); + } + return DBStoreMock::PutLocalBatch(entries); + } + using DeleteLocalBatchFunc = std::function &)>; + DeleteLocalBatchFunc deleteLocalBatchFunc; + DBStatus DeleteLocalBatch(const std::vector &keys) override + { + if (deleteLocalBatchFunc) { + return deleteLocalBatchFunc(keys); + } + return DBStoreMock::DeleteLocalBatch(keys); + } +}; + +void MetaDataManagerTest::SetUpTestCase(void) +{ + metaStore = std::make_shared(); + MetaDataManager::GetInstance().Initialize( + metaStore, + [](const auto &store) { + return 0; + }, + "meta"); +}; /** * @tc.name: FilterConstructorAndGetKeyTest * @tc.desc: FilterConstructor and GetKey. @@ -79,7 +114,6 @@ HWTEST_F(MetaDataManagerTest, FilterOperatorTest, TestSize.Level1) HWTEST_F(MetaDataManagerTest, SyncTest001, TestSize.Level1) { std::vector devices; - devices.emplace_back(EMPTY_DEVICE_ID); MetaDataManager::OnComplete complete; auto result = MetaDataManager::GetInstance().Sync(devices, complete); EXPECT_FALSE(result); @@ -98,6 +132,113 @@ HWTEST_F(MetaDataManagerTest, SyncTest002, TestSize.Level1) devices.emplace_back(INVALID_DEVICE_ID); MetaDataManager::OnComplete complete; auto result = MetaDataManager::GetInstance().Sync(devices, complete); - EXPECT_FALSE(result); + EXPECT_TRUE(result); +} + +/** + * @tc.name: SyncTest003 + * @tc.desc: devices is invalid. + * @tc.type: FUNC + * @tc.require: + * @tc.author: SQL + */ +HWTEST_F(MetaDataManagerTest, SyncTest003, TestSize.Level1) +{ + std::vector devices; + devices.emplace_back(INVALID_DEVICE_ID); + MetaDataManager::OnComplete complete = [](auto &results) {}; + auto result = MetaDataManager::GetInstance().Sync(devices, complete); + EXPECT_TRUE(result); +} + +/** + * @tc.name: SaveMetaTest001 + * @tc.desc: Batch save empty. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(MetaDataManagerTest, SaveMetaTest001, TestSize.Level1) +{ + std::vector values; + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(values, true)); +} + +/** + * @tc.name: SaveMetaTest002 + * @tc.desc: Return error code when saving. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(MetaDataManagerTest, SaveMetaTest002, TestSize.Level1) +{ + std::vector values; + values.push_back({ "SaveMetaTest002", "value" }); + metaStore->putLocalBatchFunc = [](auto &entries) { + return DistributedDB::DBStatus::DB_ERROR; + }; + EXPECT_FALSE(MetaDataManager::GetInstance().SaveMeta(values, true)); + metaStore->putLocalBatchFunc = nullptr; +} + +/** + * @tc.name: SaveMetaTest004 + * @tc.desc: Trigger sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(MetaDataManagerTest, SaveMetaTest003, TestSize.Level1) +{ + metaStore->putLocalBatchFunc = nullptr; + std::vector values; + values.push_back({ "SaveMetaTest004", "value" }); + bool flag = false; + MetaDataManager::GetInstance().SetCloudSyncer([&flag]() { + flag = true; + return; + }); + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(values, false)); + EXPECT_TRUE(flag); + MetaDataManager::GetInstance().SetCloudSyncer(nullptr); +} + +/** + * @tc.name: DelMetaTest001 + * @tc.desc: Return INVALID_PASSWD_OR_CORRUPTED_DB when del meta. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(MetaDataManagerTest, DelMetaTest001, TestSize.Level1) +{ + metaStore->deleteLocalBatchFunc = nullptr; + std::vector keys{ "DelMetaTest001" }; + metaStore->deleteLocalBatchFunc = [](auto &keys) { + return DistributedDB::DBStatus::DB_ERROR; + }; + EXPECT_FALSE(MetaDataManager::GetInstance().DelMeta(keys, true)); + metaStore->deleteLocalBatchFunc = nullptr; +} + +/** + * @tc.name: DelMetaTest003 + * @tc.desc: Trigger sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(MetaDataManagerTest, DelMetaTest002, TestSize.Level1) +{ + std::vector keys{ "DelMetaTest003" }; + bool flag = false; + MetaDataManager::GetInstance().SetCloudSyncer([&flag]() { + flag = true; + return; + }); + EXPECT_TRUE(MetaDataManager::GetInstance().DelMeta(keys, false)); + EXPECT_TRUE(flag); + MetaDataManager::GetInstance().SetCloudSyncer(nullptr); } } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/meta_data_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/meta_data_test.cpp index 6ab4d6ce..8d67bc0f 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/meta_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/meta_data_test.cpp @@ -25,6 +25,7 @@ #include "metadata/matrix_meta_data.h" #include "metadata/meta_data.h" #include "metadata/meta_data_manager.h" +#include "metadata/object_user_meta_data.h" #include "metadata/secret_key_meta_data.h" #include "metadata/store_meta_data.h" #include "metadata/store_meta_data_local.h" @@ -34,7 +35,7 @@ #include "metadata/device_meta_data.h" #include "utils/constant.h" #include "gtest/gtest.h" -#include +#include "serializable/serializable.h" using namespace testing::ext; using namespace OHOS; using namespace OHOS::DistributedKv; @@ -224,12 +225,13 @@ HWTEST_F(ServiceMetaDataTest, SecretKeyMetaData002, TestSize.Level1) HWTEST_F(ServiceMetaDataTest, StoreMetaData001, TestSize.Level1) { StoreMetaData storeMetaData("100", "appid", "test_store"); + storeMetaData.dataDir = "testDir"; StoreMetaData storeMeta; std::string key = storeMetaData.GetKey(); - EXPECT_EQ(key, "KvStoreMetaData######100###default######test_store"); + EXPECT_EQ(key, "KvStoreMetaData######100###default######test_store###testDir"); std::string keylocal = storeMetaData.GetKeyLocal(); - EXPECT_EQ(keylocal, "KvStoreMetaDataLocal######100###default######test_store"); + EXPECT_EQ(keylocal, "KvStoreMetaDataLocal######100###default######test_store###testDir"); std::initializer_list fields = { "100", "appid", "test_store" }; std::string keyfields = storeMetaData.GetKey(fields); EXPECT_EQ(keyfields, "KvStoreMetaData###100###appid###test_store"); @@ -245,15 +247,16 @@ HWTEST_F(ServiceMetaDataTest, StoreMetaData001, TestSize.Level1) result = MetaDataManager::GetInstance().DelMeta(key, true); EXPECT_TRUE(result); - result = MetaDataManager::GetInstance().SaveMeta(key, storeMetaData); + std::string syncKey = storeMetaData.GetKeyWithoutPath(); + result = MetaDataManager::GetInstance().SaveMeta(syncKey, storeMetaData); EXPECT_TRUE(result); - result = MetaDataManager::GetInstance().LoadMeta(key, storeMeta); + result = MetaDataManager::GetInstance().LoadMeta(syncKey, storeMeta); EXPECT_TRUE(result); EXPECT_EQ(storeMetaData.GetKey(), storeMeta.GetKey()); EXPECT_EQ(storeMetaData.GetKeyLocal(), storeMeta.GetKeyLocal()); EXPECT_EQ(storeMetaData.GetKey(fields), storeMeta.GetKey(fields)); - result = MetaDataManager::GetInstance().DelMeta(key); + result = MetaDataManager::GetInstance().DelMeta(syncKey); EXPECT_TRUE(result); } @@ -267,10 +270,11 @@ HWTEST_F(ServiceMetaDataTest, StoreMetaData001, TestSize.Level1) HWTEST_F(ServiceMetaDataTest, StoreMetaData002, TestSize.Level1) { StoreMetaData storeMetaData("100", "appid", "test_store"); + storeMetaData.dataDir = "testDir"; StoreMetaData storeMeta; std::string secretkey = storeMetaData.GetSecretKey(); - EXPECT_EQ(secretkey, "SecretKey###100###default######test_store###0###SINGLE_KEY"); + EXPECT_EQ(secretkey, "SecretKey###100###default######test_store###0###testDir###SINGLE_KEY"); std::string backupsecretkey = storeMetaData.GetBackupSecretKey(); EXPECT_EQ(backupsecretkey, "BackupSecretKey###100###default######test_store###0###"); @@ -350,12 +354,13 @@ HWTEST_F(ServiceMetaDataTest, StoreMetaData004, TestSize.Level1) StoreMetaData storeMetaData("100", "appid", "test_store"); storeMetaData.version = TEST_CURRENT_VERSION; storeMetaData.instanceId = 1; + storeMetaData.dataDir = "testDir"; StoreMetaData storeMeta; std::string key = storeMetaData.GetKey(); - EXPECT_EQ(key, "KvStoreMetaData######100###default######test_store###1"); + EXPECT_EQ(key, "KvStoreMetaData######100###default######test_store###1###testDir"); std::string keylocal = storeMetaData.GetKeyLocal(); - EXPECT_EQ(keylocal, "KvStoreMetaDataLocal######100###default######test_store###1"); + EXPECT_EQ(keylocal, "KvStoreMetaDataLocal######100###default######test_store###1###testDir"); auto result = MetaDataManager::GetInstance().SaveMeta(key, storeMetaData, true); EXPECT_TRUE(result); @@ -367,14 +372,15 @@ HWTEST_F(ServiceMetaDataTest, StoreMetaData004, TestSize.Level1) result = MetaDataManager::GetInstance().DelMeta(key, true); EXPECT_TRUE(result); - result = MetaDataManager::GetInstance().SaveMeta(key, storeMetaData); + std::string syncKey = storeMetaData.GetKeyWithoutPath(); + result = MetaDataManager::GetInstance().SaveMeta(syncKey, storeMetaData); EXPECT_TRUE(result); - result = MetaDataManager::GetInstance().LoadMeta(key, storeMeta); + result = MetaDataManager::GetInstance().LoadMeta(syncKey, storeMeta); EXPECT_TRUE(result); EXPECT_EQ(storeMetaData.GetKey(), storeMeta.GetKey()); EXPECT_EQ(storeMetaData.GetKeyLocal(), storeMeta.GetKeyLocal()); - result = MetaDataManager::GetInstance().DelMeta(key); + result = MetaDataManager::GetInstance().DelMeta(syncKey); EXPECT_TRUE(result); } @@ -390,10 +396,11 @@ HWTEST_F(ServiceMetaDataTest, StoreMetaData005, TestSize.Level1) StoreMetaData storeMetaData("100", "appid", "test_store"); storeMetaData.version = TEST_CURRENT_VERSION; storeMetaData.instanceId = 1; + storeMetaData.dataDir = "testDir"; StoreMetaData storeMeta; std::string secretkey = storeMetaData.GetSecretKey(); - EXPECT_EQ(secretkey, "SecretKey###100###default######test_store###SINGLE_KEY"); + EXPECT_EQ(secretkey, "SecretKey###100###default######test_store###testDir###SINGLE_KEY"); std::string backupsecretkey = storeMetaData.GetBackupSecretKey(); EXPECT_EQ(backupsecretkey, "BackupSecretKey###100###default######test_store###"); std::string strategykey = storeMetaData.GetStrategyKey(); @@ -534,6 +541,44 @@ HWTEST_F(ServiceMetaDataTest, StoreMetaData007, TestSize.Level1) EXPECT_FALSE(storemetaData1 != storemetaData2); } +/** + * @tc.name: StoreMetaData + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: MY + */ +HWTEST_F(ServiceMetaDataTest, StoreMetaData008, TestSize.Level1) +{ + StoreMetaData storeMetaData("100", "appid", "test_store"); + storeMetaData.instanceId = 1; + storeMetaData.dataDir = "008_dataDir"; + storeMetaData.deviceId = "008_uuid"; + storeMetaData.bundleName = "008_bundleName"; + + std::string key = "KvStoreMetaDataLocal###008_uuid###100###default###008_bundleName###test_store###1"; + EXPECT_EQ(storeMetaData.GetKeyLocalWithoutPath(), key); +} + +/** + * @tc.name: StoreMetaData + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: MY + */ +HWTEST_F(ServiceMetaDataTest, StoreMetaData009, TestSize.Level1) +{ + StoreMetaData storeMetaData("100", "appid", "test_store"); + storeMetaData.instanceId = 1; + storeMetaData.dataDir = "009_dataDir"; + storeMetaData.deviceId = "009_uuid"; + storeMetaData.bundleName = "009_bundleName"; + + std::string key = "StoreDfxInfo###009_uuid###100###default###009_bundleName###test_store###1###"; + EXPECT_EQ(storeMetaData.GetDfxInfoKeyWithoutPath(), key); +} + /** * @tc.name: GetStoreInfo * @tc.desc: test StoreMetaData GetStoreInfo function @@ -651,6 +696,7 @@ HWTEST_F(ServiceMetaDataTest, StrategyMeta002, TestSize.Level1) HWTEST_F(ServiceMetaDataTest, MetaData, TestSize.Level1) { StoreMetaData storeMetaData("100", "appid", "test_store"); + storeMetaData.dataDir = "testDir1"; SecretKeyMetaData secretKeyMetaData; MetaData metaData; MetaData metaDataLoad; @@ -811,18 +857,14 @@ HWTEST_F(ServiceMetaDataTest, DeviceMetaData, TestSize.Level1) { DeviceMetaData metaData; std::string newUuid = "newuuid"; - std::string oldUuid = "olduuid"; metaData.newUuid = newUuid; - metaData.oldUuid = oldUuid; Serializable::json node1; metaData.Marshal(node1); EXPECT_EQ(node1["newUuid"], newUuid); - EXPECT_EQ(node1["oldUuid"], oldUuid); DeviceMetaData newMetaData; newMetaData.Unmarshal(node1); EXPECT_EQ(newMetaData.newUuid, newUuid); - EXPECT_EQ(newMetaData.oldUuid, oldUuid); } /** @@ -840,6 +882,7 @@ HWTEST_F(ServiceMetaDataTest, InitTestMeta, TestSize.Level1) oldMeta.bundleName = "test_appid_001"; oldMeta.storeId = "test_storeid_001"; oldMeta.isEncrypt = true; + oldMeta.dataDir = "testDir2"; bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKey(), oldMeta, true); EXPECT_TRUE(isSuccess); StoreMetaDataLocal metaDataLocal; @@ -857,7 +900,7 @@ HWTEST_F(ServiceMetaDataTest, InitTestMeta, TestSize.Level1) isSuccess = MetaDataManager::GetInstance().SaveMeta(MatrixMetaData::GetPrefix({"mockOldUuid"}), matrixMeta0, true); EXPECT_TRUE(isSuccess); - isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKey(), oldMeta); + isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKeyWithoutPath(), oldMeta); EXPECT_TRUE(isSuccess); MatrixMetaData matrixMeta; isSuccess = MetaDataManager::GetInstance().SaveMeta(MatrixMetaData::GetPrefix({"mockOldUuid"}), matrixMeta); @@ -890,11 +933,12 @@ HWTEST_F(ServiceMetaDataTest, UpdateStoreMetaData, TestSize.Level1) newMeta.user = "200"; newMeta.bundleName = "test_appid_001"; newMeta.storeId = "test_storeid_001"; + newMeta.dataDir = "testDir2"; KvStoreMetaManager::GetInstance().UpdateStoreMetaData(mockNewUuid, mockOldUuid); bool isSuccess = MetaDataManager::GetInstance().LoadMeta(newMeta.GetKey(), newMeta, true); EXPECT_TRUE(isSuccess); EXPECT_TRUE(newMeta.isNeedUpdateDeviceId); - isSuccess = MetaDataManager::GetInstance().LoadMeta(newMeta.GetKey(), newMeta); + isSuccess = MetaDataManager::GetInstance().LoadMeta(newMeta.GetKeyWithoutPath(), newMeta); EXPECT_TRUE(isSuccess); AutoLaunchMetaData autoLaunchMetaData; isSuccess = MetaDataManager::GetInstance().LoadMeta(AutoLaunchMetaData::GetPrefix({ newMeta.deviceId, newMeta.user, @@ -916,11 +960,6 @@ HWTEST_F(ServiceMetaDataTest, UpdateMetaDatas, TestSize.Level1) { std::string mockNewUuid = "mockNewUuid"; std::string mockOldUuid = "mockOldUuid"; - StoreMetaData newMeta; - newMeta.deviceId = "mockNewUuid"; - newMeta.user = "200"; - newMeta.bundleName = "test_appid_001"; - newMeta.storeId = "test_storeid_001"; KvStoreMetaManager::GetInstance().UpdateMetaDatas(mockNewUuid, mockOldUuid); MatrixMetaData matrixMeta; bool isSuccess = MetaDataManager::GetInstance().LoadMeta(MatrixMetaData::GetPrefix({ "mockNewUuid" }), @@ -955,6 +994,7 @@ HWTEST_F(ServiceMetaDataTest, DelTestMeta, TestSize.Level1) newMeta.user = "200"; newMeta.bundleName = "test_appid_001"; newMeta.storeId = "test_storeid_001"; + newMeta.dataDir = "testDir2"; bool isSuccess = MetaDataManager::GetInstance().DelMeta(newMeta.GetKey(), true); EXPECT_TRUE(isSuccess); isSuccess = MetaDataManager::GetInstance().DelMeta(newMeta.GetKeyLocal(), true); @@ -967,7 +1007,7 @@ HWTEST_F(ServiceMetaDataTest, DelTestMeta, TestSize.Level1) isSuccess = MetaDataManager::GetInstance().DelMeta(MatrixMetaData::GetPrefix({ "mockNewUuid" }), true); EXPECT_TRUE(isSuccess); - isSuccess = MetaDataManager::GetInstance().DelMeta(newMeta.GetKey()); + isSuccess = MetaDataManager::GetInstance().DelMeta(newMeta.GetKeyWithoutPath()); EXPECT_TRUE(isSuccess); isSuccess = MetaDataManager::GetInstance().DelMeta(MatrixMetaData::GetPrefix({"mockNewUuid"})); EXPECT_TRUE(isSuccess); @@ -994,4 +1034,17 @@ HWTEST_F(ServiceMetaDataTest, GetKey, TestSize.Level1) std::string prefix = metaData.GetKey(); EXPECT_EQ(prefix, expectedPrefix); } + +/** +* @tc.name: ObjectUserMetaDataGetKey +* @tc.desc: ObjectUserMetaDataGetKey +* @tc.type: FUNC +*/ +HWTEST_F(ServiceMetaDataTest, ObjectUserMetaDataGetKey, TestSize.Level1) +{ + ObjectUserMetaData metaData; + std::string expectedPrefix = "ObjectUserMetaData"; + std::string prefix = metaData.GetKey(); + EXPECT_EQ(prefix, expectedPrefix); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/mock/db_store_mock.cpp b/datamgr_service/services/distributeddataservice/framework/test/mock/db_store_mock.cpp new file mode 100644 index 00000000..53c1b35e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/mock/db_store_mock.cpp @@ -0,0 +1,375 @@ +/* + * 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 "db_store_mock.h" + +namespace OHOS { +namespace DistributedData { +using namespace DistributedDB; +DBStatus DBStoreMock::Get(const Key &key, Value &value) const +{ + return Get(entries_, key, value); +} + +DBStatus DBStoreMock::GetEntries(const Key &keyPrefix, std::vector &entries) const +{ + return GetEntries(entries_, keyPrefix, entries); +} + +DBStatus DBStoreMock::GetEntries(const Key &keyPrefix, KvStoreResultSet *&resultSet) const +{ + resultSet = nullptr; + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::GetEntries(const Query &query, std::vector &entries) const +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::GetEntries(const Query &query, KvStoreResultSet *&resultSet) const +{ + resultSet = nullptr; + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::GetCount(const Query &query, int &count) const +{ + count = 0; + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::CloseResultSet(KvStoreResultSet *&resultSet) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Put(const Key &key, const Value &value) +{ + return PutBatch(entries_, { { key, value } }); +} + +DBStatus DBStoreMock::PutBatch(const std::vector &entries) +{ + return PutBatch(entries_, entries); +} + +DBStatus DBStoreMock::DeleteBatch(const std::vector &keys) +{ + return DeleteBatch(entries_, keys); +} + +DBStatus DBStoreMock::Delete(const Key &key) +{ + return DeleteBatch(entries_, { key }); +} + +DBStatus DBStoreMock::GetLocal(const Key &key, Value &value) const +{ + return Get(localEntries_, key, value); +} + +DBStatus DBStoreMock::GetLocalEntries(const Key &keyPrefix, std::vector &entries) const +{ + return GetEntries(localEntries_, keyPrefix, entries); +} + +DBStatus DBStoreMock::PutLocal(const Key &key, const Value &value) +{ + return PutBatch(localEntries_, { { key, value } }); +} + +DBStatus DBStoreMock::DeleteLocal(const Key &key) +{ + return DeleteBatch(localEntries_, { key }); +} + +DBStatus DBStoreMock::PublishLocal(const Key &key, bool deleteLocal, bool updateTimestamp, + const KvStoreNbPublishOnConflict &onConflict) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::UnpublishToLocal(const Key &key, bool deletePublic, bool updateTimestamp) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::RegisterObserver(const Key &key, unsigned int mode, KvStoreObserver *observer) +{ + observers_.Compute(observer, [key](auto &, std::set &prefixes) { + prefixes.insert(key); + return !prefixes.empty(); + }); + return OK; +} + +DBStatus DBStoreMock::UnRegisterObserver(const KvStoreObserver *observer) +{ + KvStoreObserver *key = const_cast(observer); + observers_.Erase(key); + return OK; +} + +DBStatus DBStoreMock::RemoveDeviceData(const std::string &device) +{ + return NOT_SUPPORT; +} + +std::string DBStoreMock::GetStoreId() const +{ + return std::string(); +} + +DBStatus DBStoreMock::Sync(const std::vector &devices, SyncMode mode, + const std::function &)> &onComplete, bool wait) +{ + std::map result; + for (const auto &device : devices) { + result[device] = OK; + } + onComplete(result); + return OK; +} + +DBStatus DBStoreMock::Pragma(PragmaCmd cmd, PragmaData ¶mData) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::SetConflictNotifier(int conflictType, const KvStoreNbConflictNotifier ¬ifier) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Rekey(const CipherPassword &password) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Export(const std::string &filePath, const CipherPassword &passwd, bool force) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Import(const std::string &filePath, const CipherPassword &passwd, bool isNeedIntegrityCheck) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::StartTransaction() +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Commit() +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Rollback() +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::PutLocalBatch(const std::vector &entries) +{ + return PutBatch(localEntries_, entries); +} + +DBStatus DBStoreMock::DeleteLocalBatch(const std::vector &keys) +{ + return DeleteBatch(localEntries_, keys); +} + +DBStatus DBStoreMock::GetSecurityOption(SecurityOption &option) const +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::SetRemotePushFinishedNotify(const RemotePushFinishedNotifier ¬ifier) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Sync(const std::vector &devices, SyncMode mode, + const std::function &)> &onComplete, const Query &query, bool wait) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::CheckIntegrity() const +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::SetEqualIdentifier(const std::string &identifier, const std::vector &targets) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::SetPushDataInterceptor(const PushDataInterceptor &interceptor) +{ + return NOT_SUPPORT; +} +DBStatus DBStoreMock::SubscribeRemoteQuery(const std::vector &devices, + const std::function &)> &onComplete, const Query &query, bool wait) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::UnSubscribeRemoteQuery(const std::vector &devices, + const std::function &)> &onComplete, const Query &query, bool wait) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::RemoveDeviceData() +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::GetKeys(const Key &keyPrefix, std::vector &keys) const +{ + return NOT_SUPPORT; +} + +size_t DBStoreMock::GetSyncDataSize(const std::string &device) const +{ + return DEFAULT_SIZE; +} + +DBStatus DBStoreMock::Get(ConcurrentMap &store, const Key &key, Value &value) const +{ + auto it = store.Find(key); + value = std::move(it.second); + return it.first ? OK : NOT_FOUND; +} + +DBStatus DBStoreMock::GetEntries(ConcurrentMap &store, const Key &keyPrefix, + std::vector &entries) const +{ + store.ForEach([&entries, &keyPrefix](const Key &key, Value &value) { + auto it = std::search(key.begin(), key.end(), keyPrefix.begin(), keyPrefix.end()); + if (it == key.begin()) { + entries.push_back({key, value}); + } + return false; + }); + return entries.size() > 0 ? OK : NOT_FOUND; +} + +DBStatus DBStoreMock::PutBatch(ConcurrentMap &store, const std::vector &entries) +{ + return OK; +} + +DBStatus DBStoreMock::DeleteBatch(ConcurrentMap &store, const std::vector &keys) +{ + return OK; +} + +DBStatus DBStoreMock::UpdateKey(const UpdateKeyCallback &callback) +{ + return NOT_SUPPORT; +} + +std::pair DBStoreMock::GetWatermarkInfo(const std::string &device) +{ + WatermarkInfo mark; + return { DBStatus::OK, mark }; +} + +DBStatus DBStoreMock::Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::SetCloudDB(const std::map> &cloudDBs) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::SetCloudDbSchema(const std::map &schema) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::RemoveDeviceData(const std::string &device, ClearMode mode) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::RemoveDeviceData(const std::string &device, const std::string &user, + ClearMode mode) +{ + return NOT_SUPPORT; +} + +int32_t DBStoreMock::GetTaskCount() +{ + return 0; +} + +void DBStoreMock::SetGenCloudVersionCallback(const GenerateCloudVersionCallback &callback) +{ +} + +std::pair> DBStoreMock::GetCloudVersion(const std::string &device) +{ + return { NOT_SUPPORT, {} }; +} + +DBStatus DBStoreMock::SetCloudSyncConfig(const CloudSyncConfig &config) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::SetReceiveDataInterceptor(const DataInterceptor &interceptor) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::GetDeviceEntries(const std::string &device, std::vector &entries) const +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) +{ + return NOT_SUPPORT; +} + +DBStatus DBStoreMock::Sync(const DeviceSyncOption &option, + const std::function &)> &onComplete) +{ + std::map result; + for (const auto &device : option.devices) { + result[device] = OK; + } + onComplete(result); + return OK; +} + +DBStatus DBStoreMock::CancelSync(uint32_t syncId) +{ + return NOT_SUPPORT; +}; + +KvStoreNbDelegate::DatabaseStatus DBStoreMock::GetDatabaseStatus() const +{ + return {}; +} +} // namespace DistributedData +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/mock/db_store_mock.h b/datamgr_service/services/distributeddataservice/framework/test/mock/db_store_mock.h new file mode 100644 index 00000000..c9246a8c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/mock/db_store_mock.h @@ -0,0 +1,134 @@ +/* + * 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 OHOS_DISTRIBUTEDDATA_SERVICE_TEST_DB_STORE_MOCK_H +#define OHOS_DISTRIBUTEDDATA_SERVICE_TEST_DB_STORE_MOCK_H +#include "concurrent_map.h" +#include "kv_store_nb_delegate.h" +#include "store_types.h" +namespace OHOS { +namespace DistributedData { +class DBStoreMock : public DistributedDB::KvStoreNbDelegate { +public: + using DBStatus = DistributedDB::DBStatus; + DBStatus Reset(); + using Entry = DistributedDB::Entry; + using Key = DistributedDB::Key; + using Value = DistributedDB::Value; + using KvStoreResultSet = DistributedDB::KvStoreResultSet; + using Query = DistributedDB::Query; + using KvStoreNbPublishOnConflict = DistributedDB::KvStoreNbPublishOnConflict; + using KvStoreObserver = DistributedDB::KvStoreObserver; + using SyncMode = DistributedDB::SyncMode; + using PragmaCmd = DistributedDB::PragmaCmd; + using PragmaData = DistributedDB::PragmaData; + using CipherPassword = DistributedDB::CipherPassword; + using KvStoreNbConflictNotifier = DistributedDB::KvStoreNbConflictNotifier; + using SecurityOption = DistributedDB::SecurityOption; + using RemotePushFinishedNotifier = DistributedDB::RemotePushFinishedNotifier; + using PushDataInterceptor = DistributedDB::PushDataInterceptor; + using UpdateKeyCallback = DistributedDB::UpdateKeyCallback; + using WatermarkInfo = DistributedDB::WatermarkInfo; + using ClearMode = DistributedDB::ClearMode; + using DataBaseSchema = DistributedDB::DataBaseSchema; + using ICloudDb = DistributedDB::ICloudDb; + using CloudSyncOption = DistributedDB::CloudSyncOption; + using SyncProcessCallback = DistributedDB::SyncProcessCallback; + using GenerateCloudVersionCallback = DistributedDB::GenerateCloudVersionCallback; + using CloudSyncConfig = DistributedDB::CloudSyncConfig; + using DataInterceptor = DistributedDB::DataInterceptor; + using DeviceSyncOption = DistributedDB::DeviceSyncOption; + using DeviceSyncProcessCallback = DistributedDB::DeviceSyncProcessCallback; + DBStatus Get(const Key &key, Value &value) const override; + DBStatus GetEntries(const Key &keyPrefix, std::vector &entries) const override; + DBStatus GetEntries(const Key &keyPrefix, KvStoreResultSet *&resultSet) const override; + DBStatus GetEntries(const Query &query, std::vector &entries) const override; + DBStatus GetEntries(const Query &query, KvStoreResultSet *&resultSet) const override; + DBStatus GetCount(const Query &query, int &count) const override; + DBStatus CloseResultSet(KvStoreResultSet *&resultSet) override; + DBStatus Put(const Key &key, const Value &value) override; + DBStatus PutBatch(const std::vector &entries) override; + DBStatus DeleteBatch(const std::vector &keys) override; + DBStatus Delete(const Key &key) override; + DBStatus GetLocal(const Key &key, Value &value) const override; + DBStatus GetLocalEntries(const Key &keyPrefix, std::vector &entries) const override; + DBStatus PutLocal(const Key &key, const Value &value) override; + DBStatus DeleteLocal(const Key &key) override; + DBStatus PublishLocal(const Key &key, bool deleteLocal, bool updateTimestamp, + const KvStoreNbPublishOnConflict &onConflict) override; + DBStatus UnpublishToLocal(const Key &key, bool deletePublic, bool updateTimestamp) override; + DBStatus RegisterObserver(const Key &key, unsigned int mode, KvStoreObserver *observer) override; + DBStatus UnRegisterObserver(const KvStoreObserver *observer) override; + DBStatus RemoveDeviceData(const std::string &device) override; + std::string GetStoreId() const override; + DBStatus Sync(const std::vector &devices, SyncMode mode, + const std::function &)> &onComplete, bool wait) override; + DBStatus Pragma(PragmaCmd cmd, PragmaData ¶mData) override; + DBStatus SetConflictNotifier(int conflictType, const KvStoreNbConflictNotifier ¬ifier) override; + DBStatus Rekey(const CipherPassword &password) override; + DBStatus Export(const std::string &filePath, const CipherPassword &passwd, bool force) override; + DBStatus Import(const std::string &filePath, const CipherPassword &passwd, bool isNeedIntegrityCheck) override; + DBStatus StartTransaction() override; + DBStatus Commit() override; + DBStatus Rollback() override; + DBStatus PutLocalBatch(const std::vector &entries) override; + DBStatus DeleteLocalBatch(const std::vector &keys) override; + DBStatus GetSecurityOption(SecurityOption &option) const override; + DBStatus SetRemotePushFinishedNotify(const RemotePushFinishedNotifier ¬ifier) override; + DBStatus Sync(const std::vector &devices, SyncMode mode, + const std::function &)> &onComplete, const Query &query, + bool wait) override; + DBStatus CheckIntegrity() const override; + DBStatus SetEqualIdentifier(const std::string &identifier, const std::vector &targets) override; + DBStatus SetPushDataInterceptor(const PushDataInterceptor &interceptor) override; + DBStatus SubscribeRemoteQuery(const std::vector &devices, + const std::function &)> &onComplete, const Query &query, + bool wait) override; + DBStatus UnSubscribeRemoteQuery(const std::vector &devices, + const std::function &)> &onComplete, const Query &query, + bool wait) override; + DBStatus RemoveDeviceData() override; + DBStatus GetKeys(const Key &keyPrefix, std::vector &keys) const override; + size_t GetSyncDataSize(const std::string &device) const override; + DBStatus UpdateKey(const UpdateKeyCallback &callback) override; + std::pair GetWatermarkInfo(const std::string &device) override; + DBStatus Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) override; + DBStatus SetCloudDB(const std::map> &cloudDBs) override; + DBStatus SetCloudDbSchema(const std::map &schema) override; + DBStatus RemoveDeviceData(const std::string &device, ClearMode mode) override; + DBStatus RemoveDeviceData(const std::string &device, const std::string &user, ClearMode mode) override; + int32_t GetTaskCount() override; + void SetGenCloudVersionCallback(const GenerateCloudVersionCallback &callback) override; + std::pair> GetCloudVersion(const std::string &device) override; + DBStatus SetCloudSyncConfig(const CloudSyncConfig &config) override; + DBStatus SetReceiveDataInterceptor(const DataInterceptor &interceptor) override; + DBStatus GetDeviceEntries(const std::string &device, std::vector &entries) const override; + DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) override; + DBStatus Sync(const DeviceSyncOption &option, + const std::function &)> &onComplete) override; + DBStatus CancelSync(uint32_t syncId) override; + DatabaseStatus GetDatabaseStatus() const override; +private: + static const uint32_t DEFAULT_SIZE = 0; + DBStatus Get(ConcurrentMap &store, const Key &key, Value &value) const; + DBStatus GetEntries(ConcurrentMap &store, const Key &keyPrefix, std::vector &entries) const; + DBStatus PutBatch(ConcurrentMap &store, const std::vector &entries); + DBStatus DeleteBatch(ConcurrentMap &store, const std::vector &keys); + mutable ConcurrentMap entries_; + mutable ConcurrentMap localEntries_; + mutable ConcurrentMap> observers_; +}; +} // namespace DistributedData +} // namespace OHOS +#endif // OHOS_DISTRIBUTEDDATA_SERVICE_TEST_DB_STORE_MOCK_H diff --git a/datamgr_service/services/distributeddataservice/framework/test/screen_manager_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/screen_manager_test.cpp new file mode 100644 index 00000000..32156d37 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/test/screen_manager_test.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. +//*/ +// +//#define LOG_TAG "ScreenManagerTest" +//#include +// +//#include "screen/screen_manager.h" +// +//using namespace testing::ext; +//using namespace OHOS::DistributedData; +//namespace OHOS::Test { +//class ScreenManagerTest : public testing::Test { +//public: +// static void SetUpTestCase(void); +// static void TearDownTestCase(void){}; +// void SetUp(){}; +// void TearDown(){}; +//}; +// +//void ScreenManagerTest::SetUpTestCase() +//{ +// ScreenManager::GetInstance()->BindExecutor(nullptr); +//} +// +///** +//* @tc.name: IsLocked +//* @tc.desc: test IsLocked function +//* @tc.type: FUNC +//* @tc.require: +//* @tc.author: +//*/ +//HWTEST_F(ScreenManagerTest, IsLocked, TestSize.Level1) +//{ +// EXPECT_NO_FATAL_FAILURE(ScreenManager::GetInstance()->Subscribe(nullptr)); +// EXPECT_NO_FATAL_FAILURE(ScreenManager::GetInstance()->Unsubscribe(nullptr)); +// EXPECT_NO_FATAL_FAILURE(ScreenManager::GetInstance()->SubscribeScreenEvent()); +// EXPECT_NO_FATAL_FAILURE(ScreenManager::GetInstance()->UnsubscribeScreenEvent()); +// ASSERT_FALSE(ScreenManager::GetInstance()->IsLocked()); +//} +//} // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp index 14a00bf9..dd162aff 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp @@ -128,10 +128,15 @@ HWTEST_F(SerializableTest, GetNormalVal, TestSize.Level2) normal.value = -56; normal.isClear = true; normal.cols = {"adfasdfas"}; + auto json = normal.Marshall(); auto jstr = to_string(normal.Marshall()); Normal normal1; normal1.Unmarshall(jstr); ASSERT_TRUE(normal == normal1) << normal1.name; + ASSERT_FALSE(normal1.Unmarshall("")); + ASSERT_FALSE(normal1.Unmarshall("{")); + std::vector testVec = {"adfasdfas", "banana"}; + ASSERT_FALSE(json["cols"] == testVec); } /** @@ -314,4 +319,302 @@ HWTEST_F(SerializableTest, IsJson, TestSize.Level1) ASSERT_FALSE(Serializable::IsJson(str)); ASSERT_TRUE(Serializable::IsJson(jsonStr)); } + +/** +* @tc.name: ToJson_01 +* @tc.desc: to json. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, ToJson_01, TestSize.Level1) +{ + std::string jsonStr = "{\"key\":\"value\"}"; + Serializable::json result = Serializable::ToJson(jsonStr); + ASSERT_FALSE(result.is_discarded()); +} + +/** +* @tc.name: ToJson_02 +* @tc.desc: to json. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, ToJson_02, TestSize.Level1) +{ + std::string jsonStr = "invalid_json"; + Serializable::json result = Serializable::ToJson(jsonStr); + ASSERT_FALSE(result.is_discarded()); +} + +/** +* @tc.name: ToJson_03 +* @tc.desc: to json. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, ToJson_03, TestSize.Level1) +{ + std::string jsonStr = ""; + Serializable::json result = Serializable::ToJson(jsonStr); + ASSERT_TRUE(result.empty()); +} + +/** +* @tc.name: ToJson_04 +* @tc.desc: to json. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, ToJson_04, TestSize.Level1) +{ + std::string jsonStr = "{invalid_json}"; + Serializable::json result = Serializable::ToJson(jsonStr); + ASSERT_FALSE(result.is_discarded()); +} + +/** +* @tc.name: ToJson_05 +* @tc.desc: test string to json of value with numeric type. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, ToJson_05, TestSize.Level1) +{ + std::string jsonStr = "{\"key\": 10}"; + Serializable::json result = Serializable::ToJson(jsonStr); + uint64_t uint64Value; + bool ret = Serializable::GetValue(result, "key", uint64Value); + ASSERT_TRUE(ret); + + std::string jsonStr2 = "{\"key\": 10.0}"; + Serializable::json result2 = Serializable::ToJson(jsonStr2); + double doubleValue; + ret = Serializable::GetValue(result2, "key", doubleValue); + ASSERT_TRUE(ret); +} + +/** +* @tc.name: GetValueTest001 +* @tc.desc: Test to json when type not match. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, GetValueTest001, TestSize.Level1) +{ + std::string jsonStr = "{\"key\": 10}"; + Serializable::json result = Serializable::ToJson(jsonStr); + + std::string value; + bool ret = Serializable::GetValue(result, "key", value); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(result, "notExist", value); + ASSERT_FALSE(ret); + + std::string jsonStr2 = "{\"key\": \"str\"}"; + Serializable::json strResult = Serializable::ToJson(jsonStr2); + int32_t intValue; + ret = Serializable::GetValue(strResult, "key", intValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", intValue); + ASSERT_FALSE(ret); + + uint32_t uintValue; + ret = Serializable::GetValue(strResult, "key", uintValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", uintValue); + ASSERT_FALSE(ret); + + uint64_t uint64Value; + ret = Serializable::GetValue(strResult, "key", uint64Value); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", uint64Value); + ASSERT_FALSE(ret); + + int64_t int64Value; + ret = Serializable::GetValue(strResult, "key", int64Value); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", int64Value); + ASSERT_FALSE(ret); + + bool boolValue; + ret = Serializable::GetValue(strResult, "key", boolValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", boolValue); + ASSERT_FALSE(ret); + + double doubleValue; + ret = Serializable::GetValue(strResult, "key", doubleValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", doubleValue); + ASSERT_FALSE(ret); + + std::vector arrayValue; + ret = Serializable::GetValue(strResult, "key", arrayValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", arrayValue); + ASSERT_FALSE(ret); +} + +/** +* @tc.name: SetUintValue +* @tc.desc: set value with uint param. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, SetUintValue, TestSize.Level2) +{ + struct TestUint final : public Serializable { + public: + std::vector testBytes = { 0x01, 0x02, 0x03, 0x04 }; + bool Marshal(json &node) const override + { + SetValue(node[GET_NAME(testBytes)], testBytes); + return true; + } + + bool Unmarshal(const json &node) override + { + bool success = true; + success = GetValue(node, GET_NAME(testBytes), testBytes) && success; + return success; + } + + bool operator==(const TestUint &other) const + { + return testBytes == other.testBytes; + } + }; + + std::string jsonStr2 = "{\"key\": \"str\"}"; + Serializable::json strResult = Serializable::ToJson(jsonStr2); + TestUint serialValue; + bool ret = Serializable::GetValue(strResult, "key", serialValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", serialValue); + ASSERT_FALSE(ret); +} + +/** +* @tc.name: SetStringMapValue +* @tc.desc: set map value with string param. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, SetStringMapValue, TestSize.Level2) +{ + struct TestStringMap final : public Serializable { + public: + std::map testMap = { + {"name", "John"}, + {"email", "john@example.com"} + }; + bool Marshal(json &node) const override + { + SetValue(node[GET_NAME(testMap)], testMap); + return true; + } + bool Unmarshal(const json &node) override + { + GetValue(node, GET_NAME(testMap), testMap); + return true; + } + bool operator==(const TestStringMap &other) const + { + return testMap == other.testMap; + } + }; + + TestStringMap in; + in.testMap["name"] = "New York"; + in.testMap["email"] = "john@sample.com"; + auto json = to_string(in.Marshall()); + TestStringMap out; + out.Unmarshall(json); + ASSERT_TRUE(in == out); +} + +/** +* @tc.name: SetStringMapValue +* @tc.desc: set map value with int param. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, SetMapValue, TestSize.Level2) +{ + struct TestMap final : public Serializable { + public: + std::map testMap = { + {"id", 123456}, + {"version", 42} + }; + bool Marshal(json &node) const override + { + SetValue(node[GET_NAME(testMap)], testMap); + return true; + } + bool Unmarshal(const json &node) override + { + GetValue(node, GET_NAME(testMap), testMap); + return true; + } + bool operator==(const TestMap &other) const + { + return testMap == other.testMap; + } + }; + + TestMap in; + in.testMap["version"] = 552; + auto json = to_string(in.Marshall()); + TestMap out; + out.Unmarshall(json); + ASSERT_TRUE(in == out); +} + +/** +* @tc.name: BoundaryTest +* @tc.desc: test boundary. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, BoundaryTest, TestSize.Level1) +{ + struct TestBoundary : public Serializable { + int32_t int32Val; + uint32_t uint32Val; + int64_t int64Val; + uint64_t uint64Val; + bool Marshal(json &node) const override + { + SetValue(node[GET_NAME(int32Val)], int32Val); + SetValue(node[GET_NAME(uint32Val)], uint32Val); + SetValue(node[GET_NAME(int64Val)], int64Val); + SetValue(node[GET_NAME(uint64Val)], uint64Val); + return true; + } + bool Unmarshal(const json &node) override + { + bool success = true; + success = GetValue(node, GET_NAME(int32Val), int32Val) && success; + success = GetValue(node, GET_NAME(uint32Val), uint32Val) && success; + success = GetValue(node, GET_NAME(int64Val), int64Val) && success; + success = GetValue(node, GET_NAME(uint64Val), uint64Val) && success; + return success; + } + }; + TestBoundary in, out; + in.int32Val = INT32_MIN; + in.uint32Val = 0; + in.int64Val = INT64_MIN; + in.uint64Val = 0; + + auto json = to_string(in.Marshall()); + out.Unmarshall(json); + EXPECT_EQ(out.int32Val, in.int32Val); + EXPECT_EQ(out.uint32Val, in.uint32Val); + EXPECT_EQ(out.int64Val, in.int64Val); + EXPECT_EQ(out.uint64Val, in.uint64Val); + + in.int32Val = INT32_MAX; + in.uint32Val = UINT32_MAX; + in.int64Val = INT64_MAX; + in.uint64Val = UINT64_MAX; + + json = to_string(in.Marshall()); + out.Unmarshall(json); + EXPECT_EQ(out.int32Val, in.int32Val); + EXPECT_EQ(out.uint32Val, in.uint32Val); + EXPECT_EQ(out.int64Val, in.int64Val); + EXPECT_EQ(out.uint64Val, in.uint64Val); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/test/store_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/store_test.cpp index 7bc31f25..304b19bd 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/store_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/store_test.cpp @@ -260,4 +260,62 @@ HWTEST_F(AutoCacheTest, GetDBStore, TestSize.Level2) meta.area = GeneralStore::EL5; EXPECT_NE(AutoCache::GetInstance().GetDBStore(meta, watchers).first, GeneralError::E_SCREEN_LOCKED); } + +/** +* @tc.name: CloseStore001 +* @tc.desc: AutoCache CloseStore001 +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(AutoCacheTest, CloseStore001, TestSize.Level2) +{ + GeneralStoreMock* store = new (std::nothrow) GeneralStoreMock(); + ASSERT_NE(store, nullptr); + AutoCache::Watchers watchers; + mock_->isLocked_ = true; + StoreMetaData meta; + meta.area = GeneralStore::EL1; + meta.dataDir = ""; + uint32_t tokenId = 123; + AutoCache autoCache; + autoCache.stores_.Compute(tokenId, + [this, &meta, &watchers, &store](auto &, std::map &stores) -> bool { + std::string storeKey = "key"; + stores.emplace(std::piecewise_construct, std::forward_as_tuple(storeKey), + std::forward_as_tuple(store, watchers, 0, meta)); + return !stores.empty(); + }); + autoCache.CloseStore(tokenId, meta.dataDir); + EXPECT_TRUE(autoCache.stores_.Empty()); +} + +/** +* @tc.name: CloseStore002 +* @tc.desc: AutoCache CloseStore002 +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(AutoCacheTest, CloseStore002, TestSize.Level2) +{ + GeneralStoreMock* store = new (std::nothrow) GeneralStoreMock(); + ASSERT_NE(store, nullptr); + AutoCache::Watchers watchers; + mock_->isLocked_ = true; + StoreMetaData meta; + meta.area = GeneralStore::EL4; + meta.dataDir = ""; + uint32_t tokenId = 123; + AutoCache autoCache; + autoCache.stores_.Compute(tokenId, + [this, &meta, &watchers, &store](auto &, std::map &stores) -> bool { + std::string storeKey = "key"; + stores.emplace(std::piecewise_construct, std::forward_as_tuple(storeKey), + std::forward_as_tuple(store, watchers, 0, meta)); + return !stores.empty(); + }); + autoCache.CloseStore(tokenId, meta.dataDir); + EXPECT_FALSE(autoCache.stores_.Empty()); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/utils/anonymous.cpp b/datamgr_service/services/distributeddataservice/framework/utils/anonymous.cpp index 4a1d3d0d..de87b5b2 100644 --- a/datamgr_service/services/distributeddataservice/framework/utils/anonymous.cpp +++ b/datamgr_service/services/distributeddataservice/framework/utils/anonymous.cpp @@ -67,7 +67,7 @@ std::string Anonymous::Change(const std::string &name) noAlnum.push_back(""); } if (!noAlnumStr.empty()) { - noAlnum.push_back(alnumStr); + noAlnum.push_back(noAlnumStr); alnum.push_back(""); } std::string res = ""; diff --git a/datamgr_service/services/distributeddataservice/framework/utils/constant.cpp b/datamgr_service/services/distributeddataservice/framework/utils/constant.cpp index 6fedf3f6..f0b40f54 100644 --- a/datamgr_service/services/distributeddataservice/framework/utils/constant.cpp +++ b/datamgr_service/services/distributeddataservice/framework/utils/constant.cpp @@ -15,7 +15,6 @@ #define LOG_TAG "Constant" #include "utils/constant.h" #include -#include "log_print.h" #include "securec.h" namespace OHOS { diff --git a/datamgr_service/services/distributeddataservice/framework/utils/corrupt_reporter.cpp b/datamgr_service/services/distributeddataservice/framework/utils/corrupt_reporter.cpp index 405e2991..065ab010 100644 --- a/datamgr_service/services/distributeddataservice/framework/utils/corrupt_reporter.cpp +++ b/datamgr_service/services/distributeddataservice/framework/utils/corrupt_reporter.cpp @@ -27,7 +27,7 @@ constexpr const char *DB_CORRUPTED_POSTFIX = ".corruptedflg"; bool CorruptReporter::CreateCorruptedFlag(const std::string &path, const std::string &dbName) { if (path.empty() || dbName.empty()) { - ZLOGW("The path or dbName is empty, path:%{public}s, dbName:%{public}s", path.c_str(), + ZLOGW("The path or dbName is empty, path:%{public}s, dbName:%{public}s", Anonymous::Change(path).c_str(), Anonymous::Change(dbName).c_str()); return false; } @@ -35,7 +35,7 @@ bool CorruptReporter::CreateCorruptedFlag(const std::string &path, const std::st if (access(flagFileName.c_str(), F_OK) == 0) { return true; } - int fd = creat(flagFileName.c_str(), S_IRWXU | S_IRWXG); + int fd = creat(flagFileName.c_str(), S_IRUSR | S_IWUSR); if (fd == -1) { ZLOGW("Create corrupted flag fail, flagFileName:%{public}s, errno:%{public}d", Anonymous::Change(flagFileName).c_str(), errno); @@ -48,7 +48,7 @@ bool CorruptReporter::CreateCorruptedFlag(const std::string &path, const std::st bool CorruptReporter::HasCorruptedFlag(const std::string &path, const std::string &dbName) { if (path.empty() || dbName.empty()) { - ZLOGW("The path or dbName is empty, path:%{public}s, dbName:%{public}s", path.c_str(), + ZLOGW("The path or dbName is empty, path:%{public}s, dbName:%{public}s", Anonymous::Change(path).c_str(), Anonymous::Change(dbName).c_str()); return false; } @@ -59,7 +59,7 @@ bool CorruptReporter::HasCorruptedFlag(const std::string &path, const std::strin bool CorruptReporter::DeleteCorruptedFlag(const std::string &path, const std::string &dbName) { if (path.empty() || dbName.empty()) { - ZLOGW("The path or dbName is empty, path:%{public}s, dbName:%{public}s", path.c_str(), + ZLOGW("The path or dbName is empty, path:%{public}s, dbName:%{public}s", Anonymous::Change(path).c_str(), Anonymous::Change(dbName).c_str()); return false; } diff --git a/datamgr_service/services/distributeddataservice/rust/connect_adapter/BUILD.gn b/datamgr_service/services/distributeddataservice/rust/connect_adapter/BUILD.gn index 292dc200..49162568 100644 --- a/datamgr_service/services/distributeddataservice/rust/connect_adapter/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/rust/connect_adapter/BUILD.gn @@ -34,14 +34,8 @@ ohos_shared_library("conn_adapter") { "src/connect_wrapper.cpp", ] configs = [ ":export_connect" ] - cflags = [ - "-Werror", - "-fstack-protector-strong", - ] - cflags_cc = [ - "-fvisibility=hidden", - "-fstack-protector-strong", - ] + cflags = [ "-Werror" ] + cflags_cc = [ "-fvisibility=hidden" ] external_deps = [ "ability_base:want", diff --git a/datamgr_service/services/distributeddataservice/rust/connect_adapter/src/connect.cpp b/datamgr_service/services/distributeddataservice/rust/connect_adapter/src/connect.cpp index a61a7939..9ec682c1 100644 --- a/datamgr_service/services/distributeddataservice/rust/connect_adapter/src/connect.cpp +++ b/datamgr_service/services/distributeddataservice/rust/connect_adapter/src/connect.cpp @@ -68,7 +68,6 @@ void Connect::WaitConnect() cv_.wait_for(lock, std::chrono::seconds(CONNECT_TIMEOUT), [this] { return flag_; }); - cv_.notify_one(); } namespace ConnectInner { diff --git a/datamgr_service/services/distributeddataservice/rust/extension/BUILD.gn b/datamgr_service/services/distributeddataservice/rust/extension/BUILD.gn index 6730b990..92cd41b8 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/rust/extension/BUILD.gn @@ -23,7 +23,6 @@ config("module_public_config") { visibility = [ ":*" ] include_dirs = [ "../../framework/include", - "${kv_store_common_path}", ] } @@ -47,13 +46,9 @@ ohos_shared_library("opencloudextension") { cflags = [ "-Werror", "-Wno-multichar", - "-fstack-protector-strong", ] - cflags_cc = [ - "-fvisibility=hidden", - "-fstack-protector-strong", - ] + cflags_cc = [ "-fvisibility=hidden" ] configs = [ ":module_public_config" ] @@ -66,8 +61,9 @@ ohos_shared_library("opencloudextension") { "access_token:libaccesstoken_sdk", "hilog:libhilog", "json:nlohmann_json_static", + "c_utils:utils", "kv_store:datamgr_common", ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" -} +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.cpp b/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.cpp index da137619..3b042ba2 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.cpp +++ b/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.cpp @@ -119,7 +119,7 @@ int32_t CloudDbImpl::BatchDelete(const std::string &table, DBVBuckets &extends) return ExtensionUtil::ConvertStatus(status); } -std::shared_ptr CloudDbImpl::Query(const std::string &table, const DBVBucket &extend) +std::pair> CloudDbImpl::Query(const std::string &table, const DBVBucket &extend) { std::string cursor; auto it = extend.find(DistributedData::SchemaMeta::CURSOR_FIELD); @@ -134,7 +134,11 @@ std::shared_ptr CloudDbImpl::Query(const std::string &table, const DBV }; OhCloudExtCloudDbData *cloudData = nullptr; auto status = OhCloudExtCloudDbBatchQuery(database_, &info, &cloudData); - return (status == ERRNO_SUCCESS && cloudData != nullptr) ? std::make_shared(cloudData) : nullptr; + if (status == ERRNO_SUCCESS && cloudData != nullptr) { + return std::make_pair(DBErr::E_OK, std::make_shared(cloudData)); + } + return status != ERRNO_SUCCESS ? std::make_pair(ExtensionUtil::ConvertStatus(status), nullptr) + : std::make_pair(DBErr::E_ERROR, nullptr); } int32_t CloudDbImpl::Lock() diff --git a/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.h b/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.h index 099bfaad..5351ebbb 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.h +++ b/datamgr_service/services/distributeddataservice/rust/extension/cloud_db_impl.h @@ -36,7 +36,7 @@ public: int32_t BatchUpdate(const std::string &table, DBVBuckets &&values, DBVBuckets &extends) override; int32_t BatchUpdate(const std::string &table, DBVBuckets &&values, const DBVBuckets &extends) override; int32_t BatchDelete(const std::string &table, DBVBuckets &extends) override; - std::shared_ptr Query(const std::string &table, const DBVBucket &extend) override; + std::pair> Query(const std::string &table, const DBVBucket &extend) override; int32_t Lock() override; int32_t Heartbeat() override; int32_t Unlock() override; diff --git a/datamgr_service/services/distributeddataservice/rust/extension/cloud_server_impl.cpp b/datamgr_service/services/distributeddataservice/rust/extension/cloud_server_impl.cpp index f47a2620..e5413cff 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/cloud_server_impl.cpp +++ b/datamgr_service/services/distributeddataservice/rust/extension/cloud_server_impl.cpp @@ -28,11 +28,19 @@ #include "utils/anonymous.h" namespace OHOS::CloudData { -__attribute__((used)) static bool g_isInit = - DistributedData::CloudServer::RegisterCloudInstance(new (std::nothrow) CloudServerImpl()); +__attribute__((used)) static bool g_isInit = CloudServerImpl::Init(); using namespace Security::AccessToken; using DBMetaMgr = DistributedData::MetaDataManager; using Anonymous = DistributedData::Anonymous; + +bool CloudServerImpl::Init() +{ + static CloudServerImpl cloudServerInstance; + static std::once_flag onceFlag; + std::call_once(onceFlag, [&]() { DistributedData::CloudServer::RegisterCloudInstance(&cloudServerInstance); }); + return true; +} + std::pair CloudServerImpl::GetServerInfo(int32_t userId, bool needSpaceInfo) { DBCloudInfo result; @@ -544,7 +552,7 @@ int32_t CloudServerImpl::Unsubscribe(int32_t userId, const std::mapsecond); + uint32_t subId = static_cast(std::atoi(it->second.c_str())); if (OhCloudExtVectorPush(relation, &subId, sizeof(uint32_t)) != ERRNO_SUCCESS) { return DBErr::E_ERROR; } diff --git a/datamgr_service/services/distributeddataservice/rust/extension/cloud_server_impl.h b/datamgr_service/services/distributeddataservice/rust/extension/cloud_server_impl.h index bd7c185e..debb7aad 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/cloud_server_impl.h +++ b/datamgr_service/services/distributeddataservice/rust/extension/cloud_server_impl.h @@ -36,6 +36,7 @@ using DBRelation = DBSub::Relation; using DBErr = DistributedData::GeneralError; class CloudServerImpl : public DistributedData::CloudServer { public: + static bool Init(); std::pair GetServerInfo(int32_t userId, bool needSpaceInfo) override; std::pair GetAppSchema(int32_t userId, const std::string &bundleName) override; int32_t Subscribe(int32_t userId, const std::map> &dbs) override; diff --git a/datamgr_service/services/distributeddataservice/rust/extension/extension_util.cpp b/datamgr_service/services/distributeddataservice/rust/extension/extension_util.cpp index 6c6a4654..5f232141 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/extension_util.cpp +++ b/datamgr_service/services/distributeddataservice/rust/extension/extension_util.cpp @@ -424,8 +424,23 @@ DBInfo ExtensionUtil::ConvertAppInfo(OhCloudExtAppInfo *appInfo) return info; } +bool ExtensionUtil::ContainNullChar(const std::string &path) +{ + uint32_t pathLength = path.length(); + const char *cStrPath = path.c_str(); + uint32_t cStrLength = strlen(cStrPath); + if (pathLength != cStrLength) { + ZLOGW("The string contains null characters."); + return true; + } + return false; +} + std::pair ExtensionUtil::Convert(const DBAsset &dbAsset) { + if (ContainNullChar(dbAsset.path) || ContainNullChar(dbAsset.uri)) { + return { nullptr, 0 }; + } OhCloudExtCloudAssetBuilder builder { .version = dbAsset.version, .status = ConvertAssetStatus(static_cast(dbAsset.status)), diff --git a/datamgr_service/services/distributeddataservice/rust/extension/extension_util.h b/datamgr_service/services/distributeddataservice/rust/extension/extension_util.h index 71465ede..fc422f52 100644 --- a/datamgr_service/services/distributeddataservice/rust/extension/extension_util.h +++ b/datamgr_service/services/distributeddataservice/rust/extension/extension_util.h @@ -58,6 +58,7 @@ public: static std::pair Convert(const DBAssets &dbAssets); static std::pair Convert(const DBTable &dbTable); static OhCloudExtAssetStatus ConvertAssetStatus(DBAssetStatus status); + static bool ContainNullChar(const std::string &path); private: static void ConvertAssetLeft(OhCloudExtCloudAsset *asset, DBAsset &dbAsset); diff --git a/datamgr_service/services/distributeddataservice/rust/test/BUILD.gn b/datamgr_service/services/distributeddataservice/rust/test/BUILD.gn new file mode 100644 index 00000000..42c09239 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/rust/test/BUILD.gn @@ -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. +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +module_output_path = "datamgr_service/datamgr_service/distributeddatafwk" + +############################################################################### +config("module_private_config") { + visibility = [ ":*" ] + include_dirs = [ + "../extension", + "../ylong_cloud_extension/include", + ] + + cflags = [ "-Werror" ] + defines = [ + "TEST_ON_DEVICE", + "OPENSSL_SUPPRESS_DEPRECATED", + ] +} + +ohos_unittest("ExtensionUtilTest") { + module_out_path = module_output_path + sources = [ + "../extension/extension_util.cpp", + "unittest/extension_util_test.cpp" + ] + + configs = [ ":module_private_config" ] + + deps = [ + "${data_service_path}/rust/extension:opencloudextension", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/rust/ylong_cloud_extension:ylong_cloud_extension", + ] + external_deps = [ + "hilog:libhilog", + "json:nlohmann_json_static", + "kv_store:datamgr_common", + ] + + part_name = "datamgr_service" +} + +############################################################################### + +group("unittest") { + testonly = true + deps = [] + + deps += [ + ":ExtensionUtilTest", + ] +} diff --git a/datamgr_service/services/distributeddataservice/rust/test/unittest/extension_util_test.cpp b/datamgr_service/services/distributeddataservice/rust/test/unittest/extension_util_test.cpp new file mode 100644 index 00000000..d01643b9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/rust/test/unittest/extension_util_test.cpp @@ -0,0 +1,196 @@ +/* +* 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 "extension_util.h" +#include + +using namespace testing::ext; +using namespace OHOS::CloudData; + +namespace OHOS::Test { +class ExtensionUtilTest : public testing::Test {}; + +/** +* @tc.name: Convert001 +* @tc.desc: Check that the character string does not contain null characters. +* @tc.type: FUNC +*/ +HWTEST_F(ExtensionUtilTest, Convert001, TestSize.Level1) +{ + DBAsset dbAsset; + dbAsset.version = 1; + dbAsset.status = DBAsset::STATUS_NORMAL; + dbAsset.expiresTime = 1234567890; + dbAsset.id = "12345"; + dbAsset.name = "test_asset"; + dbAsset.createTime = "2025-07-03T00:00:00Z"; + dbAsset.modifyTime = "2025-07-04T00:00:00Z"; + dbAsset.size = "1024"; + dbAsset.hash = "abc123"; + dbAsset.uri = "http://example.com/path/to/file"; + dbAsset.path = "/path/to/file"; + + auto [asset, assetLen] = ExtensionUtil::Convert(dbAsset); + EXPECT_NE(asset, nullptr); + EXPECT_GT(assetLen, 0); + delete asset; +} + +/** +* @tc.name: Convert002 +* @tc.desc: Check whether the path contains null characters. +* @tc.type: FUNC +*/ +HWTEST_F(ExtensionUtilTest, Convert002, TestSize.Level1) +{ + const char data[] = "/path\0/to/file"; + std::string path(data, 13); + DBAsset dbAsset; + dbAsset.version = 1; + dbAsset.status = DBAsset::STATUS_NORMAL; + dbAsset.expiresTime = 1234567890; + dbAsset.id = "12345"; + dbAsset.name = "test_asset"; + dbAsset.createTime = "2025-07-03T00:00:00Z"; + dbAsset.modifyTime = "2025-07-04T00:00:00Z"; + dbAsset.size = "1024"; + dbAsset.hash = "abc123"; + dbAsset.uri = "http://example.com/path/to/file"; + dbAsset.path = path; + + auto [asset, assetLen] = ExtensionUtil::Convert(dbAsset); + EXPECT_EQ(asset, nullptr); + EXPECT_EQ(assetLen, 0); +} + +/** +* @tc.name: Convert003 +* @tc.desc: Check whether the URI contains null characters. +* @tc.type: FUNC +*/ +HWTEST_F(ExtensionUtilTest, Convert003, TestSize.Level1) +{ + const char data[] = "http://example.com/path\0to/file"; + std::string uri(data, 32); + DBAsset dbAsset; + dbAsset.version = 1; + dbAsset.status = DBAsset::STATUS_NORMAL; + dbAsset.expiresTime = 1234567890; + dbAsset.id = "12345"; + dbAsset.name = "test_asset"; + dbAsset.createTime = "2025-07-03T00:00:00Z"; + dbAsset.modifyTime = "2025-07-04T00:00:00Z"; + dbAsset.size = "1024"; + dbAsset.hash = "abc123"; + dbAsset.uri = uri; + dbAsset.path = "/path/to/file"; + + auto [asset, assetLen] = ExtensionUtil::Convert(dbAsset); + EXPECT_EQ(asset, nullptr); + EXPECT_EQ(assetLen, 0); +} + +/** +* @tc.name: Convert004 +* @tc.desc: Check whether the path and URI contain null characters. +* @tc.type: FUNC +*/ +HWTEST_F(ExtensionUtilTest, Convert004, TestSize.Level1) +{ + const char data1[] = "http://example.com/path\0to/file"; + std::string uri(data1, 32); + const char data2[] = "/path\0/to/file"; + std::string path(data2, 13); + DBAsset dbAsset; + dbAsset.version = 1; + dbAsset.status = DBAsset::STATUS_NORMAL; + dbAsset.expiresTime = 1234567890; + dbAsset.id = "12345"; + dbAsset.name = "test_asset"; + dbAsset.createTime = "2025-07-03T00:00:00Z"; + dbAsset.modifyTime = "2025-07-04T00:00:00Z"; + dbAsset.size = "1024"; + dbAsset.hash = "abc123"; + dbAsset.uri = uri; + dbAsset.path = path; + + auto [asset, assetLen] = ExtensionUtil::Convert(dbAsset); + EXPECT_EQ(asset, nullptr); + EXPECT_EQ(assetLen, 0); +} + +/** +* @tc.name: ConvertVBuckets001 +* @tc.desc: Test that convert DBVBuckets to empty. +* @tc.type: FUNC +*/ +HWTEST_F(ExtensionUtilTest, ConvertVBuckets001, TestSize.Level1) +{ + DBVBuckets buckets; + auto [result, size] = ExtensionUtil::Convert(std::move(buckets)); + EXPECT_NE(result, nullptr); + EXPECT_EQ(size, 0); +} + +/** +* @tc.name: ConvertVBuckets002 +* @tc.desc: Test that convert function DBVBucket is DBAsset type. +* @tc.type: FUNC +*/ +HWTEST_F(ExtensionUtilTest, ConvertVBuckets002, TestSize.Level1) +{ + DBVBuckets buckets; + DBVBucket bucket; + DBAsset dbAsset; + bucket["dbAsset"] = dbAsset; + buckets.push_back(bucket); + auto [result, size] = ExtensionUtil::Convert(std::move(buckets)); + EXPECT_NE(result, nullptr); + EXPECT_GT(size, 0); +} + +/** +* @tc.name: ConvertVBuckets003 +* @tc.desc: Test that convert function DBVBucket is DBAssets type. +* @tc.type: FUNC +*/ +HWTEST_F(ExtensionUtilTest, ConvertVBuckets003, TestSize.Level1) +{ + DBVBuckets buckets; + DBVBucket bucket; + DBAssets dbAssets; + bucket["dbAsset"] = dbAssets; + buckets.push_back(bucket); + auto [result, size] = ExtensionUtil::Convert(std::move(buckets)); + EXPECT_NE(result, nullptr); + EXPECT_GT(size, 0); +} + +/** +* @tc.name: ConvertVBuckets004 +* @tc.desc: Test that convert function DBVBucket is str type. +* @tc.type: FUNC +*/ +HWTEST_F(ExtensionUtilTest, ConvertVBuckets004, TestSize.Level1) +{ + DBVBuckets buckets; + DBVBucket bucket; + std::string key = "123"; + bucket["dbAsset"] = key; + buckets.push_back(bucket); + auto [result, size] = ExtensionUtil::Convert(std::move(buckets)); + EXPECT_NE(result, nullptr); + EXPECT_GT(size, 0); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/rust/ylong_cloud_extension/BUILD.gn b/datamgr_service/services/distributeddataservice/rust/ylong_cloud_extension/BUILD.gn index 4ac4309e..a49b928b 100644 --- a/datamgr_service/services/distributeddataservice/rust/ylong_cloud_extension/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/rust/ylong_cloud_extension/BUILD.gn @@ -44,7 +44,7 @@ if (use_clang_coverage) { } else { ohos_rust_unittest("rust_ylong_cloud_ext_unit_test") { module_out_path = - "distributeddatamgr/datamgr_service/services/rust/ylong_cloud_extension" + "datamgr_service/datamgr_service/services/rust/ylong_cloud_extension" sources = [ "src/lib.rs" ] external_deps = [ diff --git a/datamgr_service/services/distributeddataservice/service/BUILD.gn b/datamgr_service/services/distributeddataservice/service/BUILD.gn index b07724a0..79969996 100644 --- a/datamgr_service/services/distributeddataservice/service/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/BUILD.gn @@ -35,17 +35,8 @@ config("module_public_config") { "${data_service_path}/adapter/include", "${data_service_path}/app/src", "${data_service_path}/framework/include", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_distributeddb_path}/include/", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/interfaces/include/relational", - ] - cflags = [ - "-Wno-c99-designator", - "-fstack-protector-strong", ] + cflags = [ "-Wno-c99-designator" ] } ohos_shared_library("distributeddatasvc") { @@ -66,15 +57,13 @@ ohos_shared_library("distributeddatasvc") { "-Oz", "-fdata-sections", "-ffunction-sections", - "-fstack-protector-strong", ] - ldflags = [ "-Wl,-z,relro,-z,now,--gc-sections" ] + ldflags = [ "-Wl,--gc-sections" ] cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] configs = [ ":module_public_config" ] @@ -83,13 +72,14 @@ ohos_shared_library("distributeddatasvc") { deps = [ "${data_service_path}/adapter/account:distributeddata_account", "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/adapter/dfx:distributeddata_dfx", + "${data_service_path}/adapter/network:distributeddata_network", "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/backup:distributeddata_backup", "${data_service_path}/service/bootstrap:distributeddata_bootstrap", "${data_service_path}/service/common:distributeddata_common", "${data_service_path}/service/config:distributeddata_config", - "${data_service_path}/service/crypto:distributeddata_crypto", "${data_service_path}/service/dumper:distributeddata_dumper", "${data_service_path}/service/matrix:distributeddata_matrix", "${data_service_path}/service/permission:distributeddata_permit", diff --git a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt index c0bfb2f7..f72e4548 100644 --- a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt @@ -12,6 +12,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=deprecated-declarations -Wno- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") set(MOCK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../mock") set(KV_STORE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../kv_store") +add_definitions(-D__CJSON_USE_INT64) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/backup/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/cloud serviceSrc) @@ -19,7 +20,6 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/cloud/sync_strategies serviceSr aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/common serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/config/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/config/src/model serviceSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/crypto/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/rdb serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/kvdb serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/matrix/src serviceSrc) @@ -46,7 +46,6 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/permission/src serviceSrc) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/backup/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/config/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/common) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/crypto/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/permission/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/matrix/include) diff --git a/datamgr_service/services/distributeddataservice/service/backup/BUILD.gn b/datamgr_service/services/distributeddataservice/service/backup/BUILD.gn index 6a492ef4..194f7a03 100644 --- a/datamgr_service/services/distributeddataservice/service/backup/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/backup/BUILD.gn @@ -32,7 +32,6 @@ ohos_source_set("distributeddata_backup") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ @@ -47,18 +46,17 @@ ohos_source_set("distributeddata_backup") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk", - "${data_service_path}/service/crypto:distributeddata_crypto", ] external_deps = [ "device_manager:devicemanagersdk", "hilog:libhilog", "json:nlohmann_json_static", + "c_utils:utils", "kv_store:datamgr_common", ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/service/backup/include/backup_manager.h b/datamgr_service/services/distributeddataservice/service/backup/include/backup_manager.h index 76001559..e394d4a8 100644 --- a/datamgr_service/services/distributeddataservice/service/backup/include/backup_manager.h +++ b/datamgr_service/services/distributeddataservice/service/backup/include/backup_manager.h @@ -43,7 +43,7 @@ public: void BackSchedule(std::shared_ptr executors); void SetBackupParam(const BackupParam &backupParam); void RegisterExporter(int32_t type, Exporter exporter); - bool GetPassWord(const StoreMetaData &meta, std::vector &password); + std::vector GetPassWord(const StoreMetaData &meta); private: BackupManager(); diff --git a/datamgr_service/services/distributeddataservice/service/backup/src/backup_manager.cpp b/datamgr_service/services/distributeddataservice/service/backup/src/backup_manager.cpp index ddbb2319..8c96a953 100644 --- a/datamgr_service/services/distributeddataservice/service/backup/src/backup_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/backup/src/backup_manager.cpp @@ -21,11 +21,13 @@ #include #include "backuprule/backup_rule_manager.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter.h" #include "directory/directory_manager.h" #include "log_print.h" #include "metadata/meta_data_manager.h" +#include "types.h" +#include "utils/anonymous.h" namespace OHOS::DistributedData { namespace { constexpr const int COPY_SIZE = 1024; @@ -128,30 +130,24 @@ void BackupManager::BackSchedule(std::shared_ptr executors) void BackupManager::DoBackup(const StoreMetaData &meta) { - bool result = false; - auto key = meta.GetSecretKey(); - auto backupKey = meta.GetBackupSecretKey(); - std::vector decryptKey; - SecretKeyMetaData secretKey; - if (MetaDataManager::GetInstance().LoadMeta(key, secretKey, true)) { - CryptoManager::GetInstance().Decrypt(meta, secretKey, decryptKey); - if (secretKey.area < 0) { - MetaDataManager::GetInstance().LoadMeta(key, secretKey, true); - } + if (exporters_[meta.storeType] == nullptr) { + return; } auto backupPath = DirectoryManager::GetInstance().GetStoreBackupPath(meta); std::string backupFullPath = backupPath + "/" + AUTO_BACKUP_NAME; - KeepData(backupFullPath); - if (exporters_[meta.storeType] != nullptr) { - exporters_[meta.storeType](meta, backupFullPath + BACKUP_TMP_POSTFIX, result); - } - if (result) { - SaveData(backupFullPath, backupKey, secretKey); - } else { + bool result = false; + exporters_[meta.storeType](meta, backupFullPath + BACKUP_TMP_POSTFIX, result); + if (!result) { CleanData(backupFullPath); + return; } - decryptKey.assign(decryptKey.size(), 0); + SecretKeyMetaData secretKey; + result = MetaDataManager::GetInstance().LoadMeta(meta.GetSecretKey(), secretKey, true); + if (meta.isEncrypt && !result) { + return; + } + SaveData(backupFullPath, meta.GetBackupSecretKey(), secretKey); } bool BackupManager::CanBackup() @@ -279,7 +275,8 @@ BackupManager::ClearType BackupManager::GetClearType(const StoreMetaData &meta) void BackupManager::CopyFile(const std::string &oldPath, const std::string &newPath, bool isCreate) { - std::fstream fin, fout; + std::fstream fin; + std::fstream fout; if (!IsFileExist(oldPath)) { return; } @@ -298,13 +295,22 @@ void BackupManager::CopyFile(const std::string &oldPath, const std::string &newP fout.close(); } -bool BackupManager::GetPassWord(const StoreMetaData &meta, std::vector &password) +std::vector BackupManager::GetPassWord(const StoreMetaData &meta) { SecretKeyMetaData secretKey; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetBackupSecretKey(), secretKey, true)) { - return false; + auto metaKey = meta.GetBackupSecretKey(); + if (!MetaDataManager::GetInstance().LoadMeta(metaKey, secretKey, true) || secretKey.sKey.empty()) { + return {}; + } + CryptoManager::CryptoParams decryptParams = { .area = secretKey.area, .userId = meta.user, + .nonce = secretKey.nonce }; + auto password = CryptoManager::GetInstance().Decrypt(secretKey.sKey, decryptParams); + if (password.empty()) { + return password; } - return CryptoManager::GetInstance().Decrypt(meta, secretKey, password); + // update secret key of area or nonce + CryptoManager::GetInstance().UpdateSecretMeta(password, meta, metaKey, secretKey); + return password; } bool BackupManager::IsFileExist(const std::string &path) @@ -324,7 +330,7 @@ bool BackupManager::RemoveFile(const std::string &path) return true; } if (remove(path.c_str()) != 0) { - ZLOGE("remove error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("remove error:%{public}d, path:%{public}s", errno, Anonymous::Change(path).c_str()); return false; } return true; diff --git a/datamgr_service/services/distributeddataservice/service/bootstrap/BUILD.gn b/datamgr_service/services/distributeddataservice/service/bootstrap/BUILD.gn index 70b1c24c..f79f3c0c 100644 --- a/datamgr_service/services/distributeddataservice/service/bootstrap/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/bootstrap/BUILD.gn @@ -32,7 +32,6 @@ ohos_source_set("distributeddata_bootstrap") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ "${data_service_path}/service/config/include" ] @@ -44,19 +43,18 @@ ohos_source_set("distributeddata_bootstrap") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/backup:distributeddata_backup", "${data_service_path}/service/config:distributeddata_config", - "${data_service_path}/service/crypto:distributeddata_crypto", ] external_deps = [ "hilog:libhilog", "json:nlohmann_json_static", + "c_utils:utils", "kv_store:datamgr_common", ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/service/bootstrap/include/bootstrap.h b/datamgr_service/services/distributeddataservice/service/bootstrap/include/bootstrap.h index 852d3af3..eaf76724 100644 --- a/datamgr_service/services/distributeddataservice/service/bootstrap/include/bootstrap.h +++ b/datamgr_service/services/distributeddataservice/service/bootstrap/include/bootstrap.h @@ -33,6 +33,8 @@ public: API_EXPORT void LoadBackup(std::shared_ptr executors); API_EXPORT void LoadAppIdMappings(); API_EXPORT void LoadThread(); + API_EXPORT void LoadDeviceSyncAppWhiteLists(); + API_EXPORT void LoadSyncTrustedApp(); private: static constexpr const char *DEFAULT_LABEL = "distributeddata"; static constexpr const char *DEFAULT_META = "service_meta"; @@ -40,4 +42,4 @@ private: }; } // namespace DistributedData } // namespace OHOS -#endif // OHOS_DISTRIBUTED_DATA_SERVICES_BOOTSTRAP_BOOTSTRAP_H +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_BOOTSTRAP_BOOTSTRAP_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp b/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp index 1752431c..106363c1 100644 --- a/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp +++ b/datamgr_service/services/distributeddataservice/service/bootstrap/src/bootstrap.cpp @@ -17,12 +17,14 @@ #include +#include "access_check/app_access_check_config_manager.h" #include "app_id_mapping/app_id_mapping_config_manager.h" #include "backup_manager.h" #include "backuprule/backup_rule_manager.h" #include "checker/checker_manager.h" #include "cloud/cloud_config_manager.h" #include "config_factory.h" +#include "device_sync_app/device_sync_app_manager.h" #include "directory/directory_manager.h" #include "log_print.h" #include "thread/thread_manager.h" @@ -154,7 +156,12 @@ void Bootstrap::LoadDirectory() for (size_t i = 0; i < config->strategy.size(); ++i) { strategies[i] = config->strategy[i]; } - DirectoryManager::GetInstance().Initialize(strategies); + auto typeSize = config->storeTypes.size(); + std::vector storeTypes(typeSize); + for (size_t i = 0; i < typeSize; ++i) { + storeTypes[i] = config->storeTypes[i]; + } + DirectoryManager::GetInstance().Initialize(strategies, storeTypes); } void Bootstrap::LoadCloud() @@ -191,5 +198,31 @@ void Bootstrap::LoadThread() } ThreadManager::GetInstance().Initialize(config->minThreadNum, config->maxThreadNum, config->ipcThreadNum); } + +void Bootstrap::LoadDeviceSyncAppWhiteLists() +{ + auto *deviceSyncAppWhiteLists = ConfigFactory::GetInstance().GetDeviceSyncAppWhiteListConfig(); + if (deviceSyncAppWhiteLists == nullptr) { + return; + } + std::vector infos; + for (const auto &info : deviceSyncAppWhiteLists->whiteLists) { + infos.push_back({ info.appId, info.bundleName, info.version }); + } + DeviceSyncAppManager::GetInstance().Initialize(infos); +} + +void Bootstrap::LoadSyncTrustedApp() +{ + auto *config = ConfigFactory::GetInstance().GetSyncAppsConfig(); + if (config == nullptr) { + return; + } + std::vector infos; + for (const auto &info : config->trusts) { + infos.push_back({ info.bundleName, info.appId }); + } + AppAccessCheckConfigManager::GetInstance().Initialize(infos); +} } // namespace DistributedData -} // namespace OHOS +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/BUILD.gn b/datamgr_service/services/distributeddataservice/service/cloud/BUILD.gn index 3c592276..1b874d23 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/cloud/BUILD.gn @@ -28,6 +28,7 @@ ohos_source_set("distributeddata_cloud") { } sources = [ "cloud_data_translate.cpp", + "cloud_notifier_proxy.cpp", "cloud_service_impl.cpp", "cloud_service_stub.cpp", "cloud_types_util.cpp", @@ -39,7 +40,6 @@ ohos_source_set("distributeddata_cloud") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ @@ -60,11 +60,9 @@ ohos_source_set("distributeddata_cloud") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ - "${data_service_path}/adapter/network:distributeddata_network", "${data_service_path}/adapter/schema_helper:distributeddata_schema_helper", ] @@ -72,6 +70,8 @@ ohos_source_set("distributeddata_cloud") { "access_token:libtokenid_sdk", "device_manager:devicemanagersdk", "hicollie:libhicollie", + "hilog:libhilog", + "ipc:ipc_single", "json:nlohmann_json_static", "kv_store:datamgr_common", "kv_store:distributeddb", diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_data_translate.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_data_translate.cpp index 80762e38..b1e0983f 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_data_translate.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_data_translate.cpp @@ -50,7 +50,7 @@ std::vector RdbCloudDataTranslate::AssetsToBlob(const Assets &assets) auto magicU8 = reinterpret_cast(const_cast(&leMagic)); rawData.insert(rawData.end(), magicU8, magicU8 + sizeof(ASSETS_MAGIC)); rawData.insert(rawData.end(), reinterpret_cast(&num), reinterpret_cast(&num) + sizeof(num)); - for (auto &asset : assets) { + for (const auto &asset : assets) { auto data = AssetToBlob(asset); rawData.insert(rawData.end(), data.begin(), data.end()); } diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_notifier_proxy.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_notifier_proxy.cpp new file mode 100644 index 00000000..0eb531b2 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_notifier_proxy.cpp @@ -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. + */ +#define LOG_TAG "CloudNotifierProxy" + +#include "cloud_notifier_proxy.h" + +#include "cloud_service.h" +#include "itypes_util.h" +#include "log_print.h" +#include "utils/anonymous.h" + +namespace OHOS::CloudData { +using namespace DistributedRdb; +using NotifierCode = RelationalStore::ICloudNotifierInterfaceCode; + +CloudNotifierProxy::CloudNotifierProxy(const sptr &object) + : IRemoteProxy(object) +{} + +CloudNotifierProxy::~CloudNotifierProxy() noexcept {} + +int32_t CloudNotifierProxy::OnComplete(uint32_t seqNum, DistributedRdb::Details &&result) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(GetDescriptor())) { + ZLOGE("write descriptor failed"); + return CloudService::IPC_PARCEL_ERROR; + } + if (!ITypesUtil::Marshal(data, seqNum, result)) { + return CloudService::IPC_PARCEL_ERROR; + } + + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + auto remote = Remote(); + if (remote == nullptr) { + ZLOGE("get remote failed, seqNum:%{public}u", seqNum); + return CloudService::IPC_ERROR; + } + auto status = remote->SendRequest(static_cast(NotifierCode::CLOUD_NOTIFIER_CMD_SYNC_COMPLETE), + data, reply, option); + if (status != CloudService::SUCCESS) { + ZLOGE("seqNum:%{public}u, send request failed, status:%{public}d", seqNum, status); + } + return status; +} +} // namespace OHOS::CloudData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_notifier_proxy.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_notifier_proxy.h new file mode 100644 index 00000000..64a361dd --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_notifier_proxy.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 OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_NOTIFIER_PROXY_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_NOTIFIER_PROXY_H + +#include +#include + +#include "cloud_notifier.h" + +namespace OHOS::CloudData { +class CloudNotifierProxyBroker : public ICloudNotifier, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.CloudData.ICloudNotifier"); +}; + +class CloudNotifierProxy : public IRemoteProxy { +public: + explicit CloudNotifierProxy(const sptr& object); + virtual ~CloudNotifierProxy() noexcept; + + int32_t OnComplete(uint32_t seqNum, DistributedRdb::Details &&result) override; + +private: + static inline BrokerDelegator delegator_; +}; +} // namespace OHOS::CloudData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_NOTIFIER_PROXY_H diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index 88c7aa99..3179ab11 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -23,6 +23,7 @@ #include "accesstoken_kit.h" #include "account/account_delegate.h" #include "checker/checker_manager.h" +#include "cloud/change_event.h" #include "cloud/cloud_last_sync_info.h" #include "cloud/cloud_mark.h" #include "cloud/cloud_server.h" @@ -33,25 +34,26 @@ #include "cloud_value_util.h" #include "device_manager_adapter.h" #include "dfx/radar_reporter.h" +#include "dfx/reporter.h" #include "eventcenter/event_center.h" +#include "get_schema_helper.h" #include "hap_token_info.h" #include "ipc_skeleton.h" #include "log_print.h" #include "metadata/meta_data_manager.h" +#include "metadata/store_meta_data.h" #include "network/network_delegate.h" #include "rdb_types.h" -#include "dfx/reporter.h" #include "relational_store_manager.h" #include "runtime_config.h" -#include "schema_helper/get_schema_helper.h" #include "store/auto_cache.h" #include "sync_manager.h" #include "sync_strategies/network_sync_strategy.h" #include "utils/anonymous.h" +#include "utils/constant.h" #include "values_bucket.h" #include "xcollie.h" - namespace OHOS::CloudData { using namespace DistributedData; using namespace std::chrono; @@ -66,12 +68,14 @@ static constexpr const char *FT_ENABLE_CLOUD = "ENABLE_CLOUD"; static constexpr const char *FT_DISABLE_CLOUD = "DISABLE_CLOUD"; static constexpr const char *FT_SWITCH_ON = "SWITCH_ON"; static constexpr const char *FT_SWITCH_OFF = "SWITCH_OFF"; +static constexpr const char *FT_CLOUD_CLEAN = "CLOUD_CLEAN"; static constexpr const char *FT_QUERY_INFO = "QUERY_SYNC_INFO"; static constexpr const char *FT_USER_CHANGE = "USER_CHANGE"; static constexpr const char *FT_USER_UNLOCK = "USER_UNLOCK"; static constexpr const char *FT_NETWORK_RECOVERY = "NETWORK_RECOVERY"; static constexpr const char *FT_SERVICE_INIT = "SERVICE_INIT"; static constexpr const char *FT_SYNC_TASK = "SYNC_TASK"; +static constexpr const char *FT_ENCRYPT_CHANGED = "ENCRYPT_CHANGED"; static constexpr const char *CLOUD_SCHEMA = "arkdata/cloud/cloud_schema.json"; __attribute__((used)) CloudServiceImpl::Factory CloudServiceImpl::factory_; const CloudServiceImpl::SaveStrategy CloudServiceImpl::STRATEGY_SAVERS[Strategy::STRATEGY_BUTT] = { @@ -246,6 +250,7 @@ int32_t CloudServiceImpl::DoClean(const CloudInfo &cloudInfo, const std::map(CloudEvent::CLEAN_DATA, storeInfo)); + storeInfo.path = meta.dataDir; + if (action != GeneralStore::CLEAN_WATER) { + EventCenter::GetInstance().PostEvent(std::make_unique(CloudEvent::CLEAN_DATA, storeInfo)); + } auto status = store->Clean({}, action, ""); if (status != E_OK) { ZLOGW("remove device data status:%{public}d, user:%{public}d, bundleName:%{public}s, " "storeId:%{public}s", status, static_cast(user), meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); + Report(FT_CLOUD_CLEAN, Fault::CSF_GS_CLOUD_CLEAN, meta.bundleName, "Clean:" + std::to_string(status) + + ", storeId=" + meta.GetStoreAlias() + ", action=" + std::to_string(action)); } else { ZLOGD("clean success, user:%{public}d, bundleName:%{public}s, storeId:%{public}s", static_cast(user), meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); @@ -290,20 +300,24 @@ void CloudServiceImpl::DoClean(int32_t user, const SchemaMeta &schemaMeta, int32 bool CloudServiceImpl::GetStoreMetaData(StoreMetaData &meta) { - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { - if (meta.user == "0") { - ZLOGE("failed, no store meta bundleName:%{public}s, storeId:%{public}s, user = %{public}s", - meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), meta.user.c_str()); - return false; - } - meta.user = "0"; - StoreMetaDataLocal localMeta; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMeta, true) || - !localMeta.isPublic || !MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { - ZLOGE("meta empty, not public store. bundleName:%{public}s, storeId:%{public}s, user = %{public}s", - meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), meta.user.c_str()); - return false; - } + StoreMetaMapping metaMapping(meta); + meta.dataDir = SyncManager::GetPath(meta); + if (!meta.dataDir.empty() && MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + return true; + } + meta.user = "0"; // check if it is a public store + meta.dataDir = SyncManager::GetPath(meta); + + if (meta.dataDir.empty() || !MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + ZLOGE("failed, no store meta. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return false; + } + StoreMetaDataLocal localMetaData; + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMetaData, true) || !localMetaData.isPublic) { + ZLOGE("meta empty, not public store. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return false; } return true; } @@ -315,16 +329,21 @@ int32_t CloudServiceImpl::Clean(const std::string &id, const std::map(cloudInfo.user)); + Report(FT_CLOUD_CLEAN, Fault::CSF_GS_CLOUD_CLEAN, "", + "get cloud info from meta failed=" + std::to_string(status)); return ERROR; } if (id != cloudInfo.id) { ZLOGE("different id, [server] id:%{public}s, [meta] id:%{public}s", Anonymous::Change(cloudInfo.id).c_str(), Anonymous::Change(id).c_str()); + Report(FT_CLOUD_CLEAN, Fault::CSF_GS_CLOUD_CLEAN, "", + "different id, new:" + Anonymous::Change(id) + ", old:" + Anonymous::Change(cloudInfo.id)); return ERROR; } auto dbActions = ConvertAction(actions); if (dbActions.empty()) { ZLOGE("invalid actions. id:%{public}s", Anonymous::Change(cloudInfo.id).c_str()); + Report(FT_CLOUD_CLEAN, Fault::CSF_GS_CLOUD_CLEAN, "", "convert action failed"); return ERROR; } return DoClean(cloudInfo, dbActions); @@ -489,21 +508,25 @@ std::map CloudServiceImpl::ExecuteStatistics(const { std::map result; for (auto &database : schemaMeta.databases) { - if (storeId.empty() || database.alias == storeId) { - StoreMetaData meta; - meta.bundleName = schemaMeta.bundleName; - meta.storeId = database.name; - meta.user = std::to_string(cloudInfo.user); - meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - auto it = cloudInfo.apps.find(schemaMeta.bundleName); - if (it == cloudInfo.apps.end()) { - ZLOGE("bundleName:%{public}s is not exist", schemaMeta.bundleName.c_str()); - break; - } - meta.instanceId = it->second.instanceId; - MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true); - result.insert_or_assign(database.alias, QueryStatistics(meta, database)); + if (!storeId.empty() && database.alias != storeId) { + continue; + } + auto it = cloudInfo.apps.find(schemaMeta.bundleName); + if (it == cloudInfo.apps.end()) { + ZLOGE("bundleName:%{public}s is not exist", schemaMeta.bundleName.c_str()); + break; + } + StoreMetaMapping meta; + meta.bundleName = schemaMeta.bundleName; + meta.storeId = database.name; + meta.user = std::to_string(cloudInfo.user); + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta.instanceId = it->second.instanceId; + MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true); + if (!meta.cloudPath.empty() && meta.cloudPath != meta.dataDir) { + MetaDataManager::GetInstance().LoadMeta(meta.GetCloudStoreMetaKey(), meta, true); } + result.insert_or_assign(database.alias, QueryStatistics(meta, database)); } return result; } @@ -668,12 +691,17 @@ std::pair CloudServiceImpl::QueryLastSyncInfo(const s int32_t CloudServiceImpl::OnInitialize() { XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY); - NetworkDelegate::GetInstance()->RegOnNetworkChange(); DistributedDB::RuntimeConfig::SetCloudTranslate(std::make_shared()); - Execute(GenTask(0, 0, CloudSyncScene::SERVICE_INIT, - { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_DO_CLOUD_SYNC, WORK_SUB })); std::vector users; Account::GetInstance()->QueryUsers(users); + for (auto user : users) { + if (user == DEFAULT_USER) { + continue; + } + CleanWaterVersion(user); + } + Execute(GenTask(0, 0, CloudSyncScene::SERVICE_INIT, + { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_DO_CLOUD_SYNC, WORK_SUB })); for (auto user : users) { if (user == DEFAULT_USER) { continue; @@ -688,6 +716,35 @@ int32_t CloudServiceImpl::OnInitialize() return E_OK; } +bool CloudServiceImpl::CleanWaterVersion(int32_t user) +{ + auto [status, cloudInfo] = GetCloudInfoFromMeta(user); + if (status != SUCCESS) { + return false; + } + auto stores = CheckerManager::GetInstance().GetDynamicStores(); + auto staticStores = CheckerManager::GetInstance().GetStaticStores(); + stores.insert(stores.end(), staticStores.begin(), staticStores.end()); + auto keys = cloudInfo.GetSchemaKey(); + for (const auto &[bundle, key] : keys) { + SchemaMeta schemaMeta; + if (MetaDataManager::GetInstance().LoadMeta(key, schemaMeta, true) && + schemaMeta.metaVersion < SchemaMeta::CLEAN_WATER_VERSION) { + bool found = std::any_of(stores.begin(), stores.end(), + [&schemaMeta](const CheckerManager::StoreInfo &storeInfo) { + return storeInfo.bundleName == schemaMeta.bundleName; + }); + if (!found) { + continue; + } + DoClean(user, schemaMeta, GeneralStore::CleanMode::CLEAN_WATER); + schemaMeta.metaVersion = SchemaMeta::CLEAN_WATER_VERSION; + } + MetaDataManager::GetInstance().SaveMeta(key, schemaMeta, true); + } + return true; +} + int32_t CloudServiceImpl::OnBind(const BindInfo &info) { if (executor_ != nullptr || info.executors == nullptr) { @@ -735,6 +792,10 @@ int32_t CloudServiceImpl::OnReady(const std::string &device) if (device != DeviceManagerAdapter::CLOUD_DEVICE_UUID) { return SUCCESS; } + if (!Account::GetInstance()->IsLoginAccount()) { + ZLOGW("current user is not logged in."); + return E_NOT_LOGIN; + } std::vector users; Account::GetInstance()->QueryForegroundUsers(users); if (users.empty()) { @@ -792,7 +853,8 @@ std::pair CloudServiceImpl::GetCloudInfoFromServer(int32_t u ZLOGD("cloud server is nullptr, user:%{public}d", userId); return { SERVER_UNAVAILABLE, cloudInfo }; } - return instance->GetServerInfo(cloudInfo.user, false); + auto [code, info] = instance->GetServerInfo(cloudInfo.user, false); + return { code != E_OK ? code : info.IsValid() ? E_OK : E_ERROR, info }; } int32_t CloudServiceImpl::UpdateCloudInfoFromServer(int32_t user) @@ -832,6 +894,8 @@ bool CloudServiceImpl::UpdateCloudInfo(int32_t user, CloudSyncScene scene) actions[bundle] = GeneralStore::CleanMode::CLOUD_INFO; } DoClean(oldInfo, actions); + Report(GetDfxFaultType(scene), Fault::CSF_CLOUD_INFO, "", + "Clean: different id, new:" + Anonymous::Change(cloudInfo.id) + ", old:" + Anonymous::Change(oldInfo.id)); } return true; } @@ -875,6 +939,54 @@ bool CloudServiceImpl::UpdateSchema(int32_t user, CloudSyncScene scene) return true; } +/** +* Will be called when 'cloudDriver' OnAppUpdate/OnAppInstall to get the newest 'e2eeEnable'. +*/ +int32_t CloudServiceImpl::UpdateSchemaFromServer(int32_t user) +{ + auto [status, cloudInfo] = GetCloudInfo(user); + if (status != SUCCESS) { + ZLOGW("get cloud info failed, user:%{public}d, status:%{public}d", user, status); + return status; + } + return UpdateSchemaFromServer(cloudInfo, user); +} + +int32_t CloudServiceImpl::UpdateSchemaFromServer(const CloudInfo &cloudInfo, int32_t user) +{ + auto keys = cloudInfo.GetSchemaKey(); + for (const auto &[bundle, key] : keys) { + auto [status, schemaMeta] = GetAppSchemaFromServer(user, bundle); + if (status == NOT_SUPPORT) { + ZLOGW("app not support, del cloudInfo! user:%{public}d, bundleName:%{public}s", user, bundle.c_str()); + MetaDataManager::GetInstance().DelMeta(cloudInfo.GetKey(), true); + return status; + } + if (status != SUCCESS) { + continue; + } + UpdateE2eeEnable(key, schemaMeta.e2eeEnable, bundle); + } + return SUCCESS; +} + +void CloudServiceImpl::UpdateE2eeEnable(const std::string &schemaKey, bool newE2eeEnable, + const std::string &bundleName) +{ + SchemaMeta oldMeta; + if (!MetaDataManager::GetInstance().LoadMeta(schemaKey, oldMeta, true)) { + return; + } + if (oldMeta.e2eeEnable == newE2eeEnable) { + return; + } + ZLOGI("Update e2eeEnable: %{public}d->%{public}d", oldMeta.e2eeEnable, newE2eeEnable); + Report(FT_ENCRYPT_CHANGED, Fault::CSF_APP_SCHEMA, bundleName, + "oldE2eeEnable=" + std::to_string(oldMeta.e2eeEnable) + ",newE2eeEnable=" + std::to_string(newE2eeEnable)); + oldMeta.e2eeEnable = newE2eeEnable; + MetaDataManager::GetInstance().SaveMeta(schemaKey, oldMeta, true); +} + std::pair CloudServiceImpl::GetAppSchemaFromServer(int32_t user, const std::string &bundleName) { SchemaMeta schemaMeta; @@ -1032,6 +1144,9 @@ int32_t CloudServiceImpl::CloudStatic::OnAppUninstall(const std::string &bundleN int32_t CloudServiceImpl::CloudStatic::OnAppInstall(const std::string &bundleName, int32_t user, int32_t index) { ZLOGI("bundleName:%{public}s,user:%{public}d,instanceId:%{public}d", bundleName.c_str(), user, index); + if (CloudDriverCheck(bundleName, user)) { + return SUCCESS; + } auto ret = UpdateCloudInfoFromServer(user); if (ret == E_OK) { StoreInfo info{.bundleName = bundleName, .instanceId = index, .user = user}; @@ -1043,11 +1158,29 @@ int32_t CloudServiceImpl::CloudStatic::OnAppInstall(const std::string &bundleNam int32_t CloudServiceImpl::CloudStatic::OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index) { ZLOGI("bundleName:%{public}s,user:%{public}d,instanceId:%{public}d", bundleName.c_str(), user, index); + if (CloudDriverCheck(bundleName, user)) { + return SUCCESS; + } HapInfo hapInfo{ .user = user, .instIndex = index, .bundleName = bundleName }; Execute([this, hapInfo]() { UpdateSchemaFromHap(hapInfo); }); return SUCCESS; } +bool CloudServiceImpl::CloudStatic::CloudDriverCheck(const std::string &bundleName, int32_t user) +{ + auto instance = CloudServer::GetInstance(); + if (instance == nullptr) { + return false; + } + if (instance->CloudDriverUpdated(bundleName)) { + // cloudDriver install, update schema(for update 'e2eeEnable') + ZLOGI("cloud driver check valid, bundleName:%{public}s, user:%{public}d", bundleName.c_str(), user); + Execute([this, user]() { UpdateSchemaFromServer(user); }); + return true; + } + return false; +} + int32_t CloudServiceImpl::UpdateSchemaFromHap(const HapInfo &hapInfo) { auto [status, cloudInfo] = GetCloudInfoFromMeta(hapInfo.user); @@ -1127,7 +1260,11 @@ void CloudServiceImpl::GetSchema(const Event &event) storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.instanceId); if (storeInfo.user == 0) { std::vector users; - AccountDelegate::GetInstance()->QueryUsers(users); + auto ret = AccountDelegate::GetInstance()->QueryUsers(users); + if (!ret || users.empty()) { + ZLOGE("failed to query os accounts, ret:%{public}d", ret); + return; + } GetSchemaMeta(users[0], storeInfo.bundleName, storeInfo.instanceId); } else { GetSchemaMeta(storeInfo.user, storeInfo.bundleName, storeInfo.instanceId); @@ -1169,9 +1306,15 @@ void CloudServiceImpl::DoSync(const Event &event) std::pair> CloudServiceImpl::PreShare( const StoreInfo &storeInfo, GenQuery &query) { - StoreMetaData meta(storeInfo); + StoreMetaMapping meta(storeInfo); meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + ZLOGE("failed, no store mapping bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return { GeneralError::E_ERROR, nullptr }; + } + if (!meta.cloudPath.empty() && meta.dataDir != meta.cloudPath && + !MetaDataManager::GetInstance().LoadMeta(meta.GetCloudStoreMetaKey(), meta, true)) { ZLOGE("failed, no store meta bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); return { GeneralError::E_ERROR, nullptr }; @@ -1195,6 +1338,76 @@ bool CloudServiceImpl::ReleaseUserInfo(int32_t user, CloudSyncScene scene) return true; } +int32_t CloudServiceImpl::InitNotifier(sptr notifier) +{ + if (notifier == nullptr) { + ZLOGE("no notifier."); + return INVALID_ARGUMENT; + } + auto notifierProxy = iface_cast(notifier); + uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); + syncAgents_.Compute(tokenId, [notifierProxy](auto, SyncAgent &agent) { + agent = SyncAgent(); + agent.notifier_ = notifierProxy; + return true; + }); + return SUCCESS; +} + +Details CloudServiceImpl::HandleGenDetails(const GenDetails &details) +{ + Details dbDetails; + for (const auto& [id, detail] : details) { + auto &dbDetail = dbDetails[id]; + dbDetail.progress = detail.progress; + dbDetail.code = detail.code; + for (auto &[name, table] : detail.details) { + auto &dbTable = dbDetail.details[name]; + Constant::Copy(&dbTable, &table); + } + } + return dbDetails; +} + +void CloudServiceImpl::OnAsyncComplete(uint32_t tokenId, uint32_t seqNum, Details &&result) +{ + ZLOGI("tokenId=%{public}x, seqnum=%{public}u", tokenId, seqNum); + sptr notifier = nullptr; + syncAgents_.ComputeIfPresent(tokenId, [¬ifier](auto, SyncAgent &syncAgent) { + notifier = syncAgent.notifier_; + return true; + }); + if (notifier != nullptr) { + notifier->OnComplete(seqNum, std::move(result)); + } +} + +int32_t CloudServiceImpl::CloudSync(const std::string &bundleName, const std::string &storeId, + const Option &option, const AsyncDetail &async) +{ + if (option.syncMode < DistributedData::GeneralStore::CLOUD_BEGIN || + option.syncMode >= DistributedData::GeneralStore::CLOUD_END) { + ZLOGE("not support cloud sync, syncMode = %{public}d", option.syncMode); + return INVALID_ARGUMENT; + } + StoreInfo storeInfo; + storeInfo.bundleName = bundleName; + storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); + storeInfo.user = AccountDelegate::GetInstance()->GetUserByToken(storeInfo.tokenId); + storeInfo.storeName = storeId; + GenAsync asyncCallback = + [this, tokenId = storeInfo.tokenId, seqNum = option.seqNum](const GenDetails &result) mutable { + OnAsyncComplete(tokenId, seqNum, HandleGenDetails(result)); + }; + auto highMode = GeneralStore::MANUAL_SYNC_MODE; + auto mixMode = static_cast(GeneralStore::MixMode(option.syncMode, highMode)); + SyncParam syncParam = { mixMode, 0, false }; + auto info = ChangeEvent::EventInfo(syncParam, false, nullptr, asyncCallback); + auto evt = std::make_unique(std::move(storeInfo), std::move(info)); + EventCenter::GetInstance().PostEvent(std::move(evt)); + return SUCCESS; +} + bool CloudServiceImpl::DoCloudSync(int32_t user, CloudSyncScene scene) { auto [status, cloudInfo] = GetCloudInfo(user); @@ -1387,6 +1600,10 @@ std::vector CloudServiceImpl::ConvertCursor(std::shared CloudServiceImpl::HapInfo CloudServiceImpl::GetHapInfo(uint32_t tokenId) { + if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) { + ZLOGE("TokenType is not TOKEN_HAP, tokenId:0x%{public}x", tokenId); + return { 0, 0, ""}; + } HapTokenInfo tokenInfo; int errCode = AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo); if (errCode != RET_SUCCESS) { diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h index fb777f13..fbd5a977 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -22,6 +22,7 @@ #include "cloud/cloud_event.h" #include "cloud/cloud_extra_data.h" #include "cloud/cloud_info.h" +#include "cloud_notifier_proxy.h" #include "cloud/schema_meta.h" #include "cloud/sharing_center.h" #include "cloud/subscription.h" @@ -33,6 +34,7 @@ #include "values_bucket.h" namespace OHOS::CloudData { +using namespace DistributedRdb; class CloudServiceImpl : public CloudServiceStub { public: using CloudLastSyncInfo = DistributedData::CloudLastSyncInfo; @@ -51,6 +53,9 @@ public: std::pair QueryLastSyncInfo( const std::string &id, const std::string &bundleName, const std::string &storeId) override; int32_t SetGlobalCloudStrategy(Strategy strategy, const std::vector &values) override; + int32_t CloudSync(const std::string &bundleName, const std::string &storeId, const Option &option, + const AsyncDetail &async) override; + int32_t InitNotifier(sptr notifier) override; std::pair> AllocResourceAndShare(const std::string &storeId, const DistributedRdb::PredicatesMemo &predicates, const std::vector &columns, @@ -83,6 +88,8 @@ private: int32_t OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index) override; int32_t OnAppInstall(const std::string &bundleName, int32_t user, int32_t index) override; int32_t OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index) override; + private: + bool CloudDriverCheck(const std::string &bundleName, int32_t user); }; class Factory { public: @@ -126,6 +133,11 @@ private: std::string bundleName; }; + struct SyncAgent { + SyncAgent() = default; + sptr notifier_; + }; + static std::map ConvertAction(const std::map &actions); static HapInfo GetHapInfo(uint32_t tokenId); static std::string GetDfxFaultType(CloudSyncScene scene); @@ -145,13 +157,16 @@ private: bool ReleaseUserInfo(int32_t user, CloudSyncScene scene); bool DoCloudSync(int32_t user, CloudSyncScene scene); bool StopCloudSync(int32_t user, CloudSyncScene scene); + bool CleanWaterVersion(int32_t user); static std::pair GetCloudInfo(int32_t userId); static std::pair GetCloudInfoFromMeta(int32_t userId); static std::pair GetCloudInfoFromServer(int32_t userId); static int32_t UpdateCloudInfoFromServer(int32_t user); static std::pair GetAppSchemaFromServer(int32_t user, const std::string &bundleName); + static Details HandleGenDetails(const DistributedData::GenDetails &details); + void OnAsyncComplete(uint32_t tokenId, uint32_t seqNum, Details &&result); std::pair GetSchemaMeta(int32_t userId, const std::string &bundleName, int32_t instanceId); void UpgradeSchemaMeta(int32_t user, const SchemaMeta &schemaMeta); std::map ExecuteStatistics( @@ -184,15 +199,18 @@ private: using SaveStrategy = int32_t (*)(const std::vector &values, const HapInfo &hapInfo); static const SaveStrategy STRATEGY_SAVERS[Strategy::STRATEGY_BUTT]; static int32_t SaveNetworkStrategy(const std::vector &values, const HapInfo &hapInfo); - void Report(const std::string &faultType, DistributedDataDfx::Fault errCode, const std::string &bundleName, + static void Report(const std::string &faultType, DistributedDataDfx::Fault errCode, const std::string &bundleName, const std::string &appendix); + QueryLastResults AssembleLastResults(const std::vector &databases, + const std::map &lastSyncInfos); static std::pair GetSchemaFromHap(const HapInfo &hapInfo); static int32_t UpdateSchemaFromHap(const HapInfo &hapInfo); + static int32_t UpdateSchemaFromServer(int32_t user); + static int32_t UpdateSchemaFromServer(const CloudInfo &cloudInfo, int32_t user); + static void UpdateE2eeEnable(const std::string &schemaKey, bool newE2eeEnable, const std::string &bundleName); static void UpdateClearWaterMark( const HapInfo &hapInfo, const SchemaMeta &newSchemaMeta, const SchemaMeta &schemaMeta); - QueryLastResults AssembleLastResults(const std::vector &databases, - const std::map &lastSyncInfos); std::shared_ptr executor_; SyncManager syncManager_; @@ -202,6 +220,7 @@ private: uint64_t expireTime_ = static_cast( std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) .count()); + ConcurrentMap syncAgents_; static constexpr Handle WORK_CLOUD_INFO_UPDATE = &CloudServiceImpl::UpdateCloudInfo; static constexpr Handle WORK_SCHEMA_UPDATE = &CloudServiceImpl::UpdateSchema; diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp index ace668b5..f1a2fd85 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp @@ -36,6 +36,7 @@ const CloudServiceStub::Handler CloudServiceStub::HANDLERS[TRANS_BUTT] = { &CloudServiceStub::OnQueryStatistics, &CloudServiceStub::OnQueryLastSyncInfo, &CloudServiceStub::OnSetGlobalCloudStrategy, + &CloudServiceStub::OnCloudSync, &CloudServiceStub::OnAllocResourceAndShare, &CloudServiceStub::OnShare, &CloudServiceStub::OnUnshare, @@ -46,6 +47,7 @@ const CloudServiceStub::Handler CloudServiceStub::HANDLERS[TRANS_BUTT] = { &CloudServiceStub::OnConfirmInvitation, &CloudServiceStub::OnChangeConfirmation, &CloudServiceStub::OnSetCloudStrategy, + &CloudServiceStub::OnInitNotifier, }; int CloudServiceStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel &data, OHOS::MessageParcel &reply) @@ -326,4 +328,29 @@ int32_t CloudServiceStub::OnSetCloudStrategy(MessageParcel &data, MessageParcel auto status = SetCloudStrategy(strategy, values); return ITypesUtil::Marshal(reply, status) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } + +int32_t CloudServiceStub::OnCloudSync(MessageParcel &data, MessageParcel &reply) +{ + std::string bundleName; + std::string storeId; + Option option; + if (!ITypesUtil::Unmarshal(data, bundleName, storeId, option)) { + ZLOGE("Unmarshal failed, bundleName:%{public}s, storeId:%{public}s, syncMode:%{public}d, seqNum:%{public}u", + bundleName.c_str(), Anonymous::Change(storeId).c_str(), option.syncMode, option.seqNum); + return IPC_STUB_INVALID_DATA_ERR; + } + auto status = CloudSync(bundleName, storeId, option, nullptr); + return ITypesUtil::Marshal(reply, status) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; +} + +int32_t CloudServiceStub::OnInitNotifier(MessageParcel &data, MessageParcel &reply) +{ + sptr notifier = nullptr; + if (!ITypesUtil::Unmarshal(data, notifier) || notifier == nullptr) { + ZLOGE("Unmarshal failed, notifier is nullptr?[%{public}u]", notifier == nullptr); + return IPC_STUB_INVALID_DATA_ERR; + } + auto status = InitNotifier(notifier); + return ITypesUtil::Marshal(reply, status) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; +} } // namespace OHOS::CloudData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h index 5f51fe84..ea1d57bd 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h @@ -37,6 +37,7 @@ private: int32_t OnQueryStatistics(MessageParcel &data, MessageParcel &reply); int32_t OnQueryLastSyncInfo(MessageParcel &data, MessageParcel &reply); int32_t OnSetGlobalCloudStrategy(MessageParcel &data, MessageParcel &reply); + int32_t OnCloudSync(MessageParcel &data, MessageParcel &reply); int32_t OnAllocResourceAndShare(MessageParcel &data, MessageParcel &reply); int32_t OnShare(MessageParcel &data, MessageParcel &reply); @@ -49,6 +50,7 @@ private: int32_t OnChangeConfirmation(MessageParcel &data, MessageParcel &reply); int32_t OnSetCloudStrategy(MessageParcel &data, MessageParcel &reply); + int32_t OnInitNotifier(MessageParcel &data, MessageParcel &reply); static const Handler HANDLERS[TRANS_BUTT]; }; } // namespace OHOS::CloudData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.cpp index 116d1b72..cc6aa141 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.cpp @@ -109,4 +109,16 @@ bool Unmarshalling(CloudSyncInfo &output, MessageParcel &data) { return Unmarshal(data, output.startTime, output.finishTime, output.code, output.syncStatus); } + +template<> +bool Marshalling(const Option &input, MessageParcel &data) +{ + return Marshal(data, input.syncMode, input.seqNum); +} + +template<> +bool Unmarshalling(Option &output, MessageParcel &data) +{ + return Unmarshal(data, output.syncMode, output.seqNum); +} } // namespace OHOS::ITypesUtil \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h index 7a53f693..e4c02995 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h @@ -17,6 +17,7 @@ #define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_TYPES_UTIL_H #include "cloud_types.h" +#include "cloud_service.h" #include "itypes_util.h" #include "values_bucket.h" @@ -32,6 +33,7 @@ using ValuesBucket = OHOS::NativeRdb::ValuesBucket; using StatisticInfo = OHOS::CloudData::StatisticInfo; using Strategy = OHOS::CloudData::Strategy; using CloudSyncInfo = OHOS::CloudData::CloudSyncInfo; +using Option = OHOS::CloudData::CloudService::Option; template<> bool Marshalling(const Participant &input, MessageParcel &data); @@ -68,5 +70,10 @@ template<> bool Marshalling(const CloudSyncInfo &input, MessageParcel &data); template<> bool Unmarshalling(CloudSyncInfo &output, MessageParcel &data); + +template<> +bool Marshalling(const Option &input, MessageParcel &data); +template<> +bool Unmarshalling(Option &output, MessageParcel &data); } // namespace OHOS::ITypesUtil #endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_TYPES_UTIL_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp index aa290128..d35bd45e 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp @@ -49,8 +49,8 @@ std::atomic SyncManager::genId_ = 0; constexpr int32_t SYSTEM_USER_ID = 0; static constexpr const char *FT_GET_STORE = "GET_STORE"; static constexpr const char *FT_CALLBACK = "CALLBACK"; -SyncManager::SyncInfo::SyncInfo(int32_t user, const std::string &bundleName, const Store &store, const Tables &tables, - int32_t triggerMode) +SyncManager::SyncInfo::SyncInfo( + int32_t user, const std::string &bundleName, const Store &store, const Tables &tables, int32_t triggerMode) : user_(user), bundleName_(bundleName), triggerMode_(triggerMode) { if (!store.empty()) { @@ -176,13 +176,19 @@ std::function SyncManager::GetLockChangeHandler() return; } - StoreMetaData meta(storeInfo); + StoreMetaMapping meta(storeInfo); meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { - ZLOGE("not found meta. bundleName: %{public}s, storeName: %{public}s, user: %{public}d.", + ZLOGE("no store mapping. bundleName: %{public}s, storeName: %{public}s, user: %{public}d.", storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.user); return; } + if (!meta.cloudPath.empty() && meta.dataDir != meta.cloudPath && + !MetaDataManager::GetInstance().LoadMeta(meta.GetCloudStoreMetaKey(), meta, true)) { + ZLOGE("failed, no store meta. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return; + } auto [status, store] = GetStore(meta, storeInfo.user); if (store == nullptr) { ZLOGE("failed to get store. bundleName: %{public}s, storeName: %{public}s, user: %{public}d.", @@ -201,8 +207,8 @@ std::function SyncManager::GetLockChangeHandler() SyncManager::SyncManager() { - EventCenter::GetInstance().Subscribe(CloudEvent::LOCK_CLOUD_CONTAINER, GetLockChangeHandler()); - EventCenter::GetInstance().Subscribe(CloudEvent::UNLOCK_CLOUD_CONTAINER, GetLockChangeHandler()); + EventCenter::GetInstance().Subscribe(CloudEvent::LOCK_CLOUD_CONTAINER, SyncManager::GetLockChangeHandler()); + EventCenter::GetInstance().Subscribe(CloudEvent::UNLOCK_CLOUD_CONTAINER, SyncManager::GetLockChangeHandler()); EventCenter::GetInstance().Subscribe(CloudEvent::LOCAL_CHANGE, GetClientChangeHandler()); syncStrategy_ = std::make_shared(); auto metaName = Bootstrap::GetInstance().GetProcessLabel(); @@ -299,15 +305,15 @@ std::function SyncManager::GetPostEventTask(const std::vectorsecond, SyncStage::END, E_ERROR }); + SyncManager::Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second, + SyncStage::END, E_ERROR, "!IsOn:" + schema.bundleName }); continue; } for (const auto &database : schema.databases) { if (!info.Contains(database.name)) { UpdateFinishSyncInfo({ cloud.user, cloud.id, schema.bundleName, database.name }, syncId, E_ERROR); - Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second, SyncStage::END, - E_ERROR }); + SyncManager::Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second, + SyncStage::END, E_ERROR, "!Contains:" + database.name }); continue; } StoreInfo storeInfo = { 0, schema.bundleName, database.name, cloud.apps[schema.bundleName].instanceId, @@ -317,8 +323,8 @@ std::function SyncManager::GetPostEventTask(const std::vectorsecond, SyncStage::END, - status }); + SyncManager::Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second, + SyncStage::END, status, "CheckSyncAction" }); info.SetError(status); continue; } @@ -353,13 +359,13 @@ ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount info.SetError(E_CLOUD_DISABLED); return; } - auto traceIds = GetPrepareTraceId(info, cloud); + auto traceIds = SyncManager::GetPrepareTraceId(info, cloud); BatchReport(info.user_, traceIds, SyncStage::PREPARE, E_OK); UpdateStartSyncInfo(cloudSyncInfos); auto code = IsValid(info, cloud); if (code != E_OK) { BatchUpdateFinishState(cloudSyncInfos, code); - BatchReport(info.user_, traceIds, SyncStage::END, code); + BatchReport(info.user_, traceIds, SyncStage::END, code, "!IsValid"); return; } @@ -373,7 +379,7 @@ ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount retryer(RETRY_INTERVAL, E_RETRY_TIMEOUT, GenStore::CLOUD_ERR_OFFSET + E_CLOUD_DISABLED, it == traceIds.end() ? "" : it->second); BatchUpdateFinishState(cloudSyncInfos, E_CLOUD_DISABLED); - BatchReport(info.user_, traceIds, SyncStage::END, E_CLOUD_DISABLED); + BatchReport(info.user_, traceIds, SyncStage::END, E_CLOUD_DISABLED, "empty schema:" + info.bundleName_); return; } } @@ -386,6 +392,34 @@ ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount }; } +void SyncManager::StartCloudSync(const DistributedData::SyncEvent &evt, const StoreMetaData &meta, + const AutoCache::Store &store, Retryer retryer, DistributedData::GenDetails &details) +{ + auto &storeInfo = evt.GetStoreInfo(); + GenAsync async = evt.GetAsyncDetail(); + auto prepareTraceId = evt.GetPrepareTraceId(); + auto user = evt.GetUser(); + auto &detail = details[SyncInfo::DEFAULT_ID]; + ReportSyncEvent(evt, BizState::BEGIN, E_OK); + SyncParam syncParam = { evt.GetMode(), evt.GetWait(), evt.IsCompensation(), MODE_DEFAULT, prepareTraceId }; + syncParam.asyncDownloadAsset = meta.asyncDownloadAsset; + auto [status, dbCode] = store->Sync({ SyncInfo::DEFAULT_ID }, *(evt.GetQuery()), + evt.AutoRetry() ? RetryCallback(storeInfo, retryer, evt.GetTriggerMode(), prepareTraceId, user) + : GetCallback(async, storeInfo, evt.GetTriggerMode(), prepareTraceId, user), syncParam); + if (status != E_OK) { + if (async) { + detail.code = ConvertValidGeneralCode(status); + async(std::move(details)); + } + UpdateFinishSyncInfo({ storeInfo.user, GetAccountId(storeInfo.user), storeInfo.bundleName, + storeInfo.storeName }, storeInfo.syncId, E_ERROR); + if (status != GeneralError::E_NOT_SUPPORT) { + auto code = dbCode == 0 ? GenStore::CLOUD_ERR_OFFSET + status : dbCode; + ReportSyncEvent(evt, BizState::END, code); + } + } +} + std::function SyncManager::GetSyncHandler(Retryer retryer) { return [this, retryer](const Event &event) { @@ -393,13 +427,13 @@ std::function SyncManager::GetSyncHandler(Retryer retryer) auto &storeInfo = evt.GetStoreInfo(); GenAsync async = evt.GetAsyncDetail(); auto prepareTraceId = evt.GetPrepareTraceId(); - auto user = evt.GetUser(); GenDetails details; auto &detail = details[SyncInfo::DEFAULT_ID]; detail.progress = GenProgress::SYNC_FINISH; auto [hasMeta, meta] = GetMetaData(storeInfo); if (!hasMeta) { - return DoExceptionalCallback(async, details, storeInfo, prepareTraceId); + return DoExceptionalCallback(async, details, storeInfo, + {0, "", prepareTraceId, SyncStage::END, GeneralError::E_ERROR, "no meta"}); } auto [code, store] = GetStore(meta, storeInfo.user); if (code == E_SCREEN_LOCKED) { @@ -408,60 +442,43 @@ std::function SyncManager::GetSyncHandler(Retryer retryer) if (store == nullptr) { ZLOGE("store null, storeId:%{public}s, prepareTraceId:%{public}s", meta.GetStoreAlias().c_str(), prepareTraceId.c_str()); - return DoExceptionalCallback(async, details, storeInfo, prepareTraceId); + return DoExceptionalCallback(async, details, storeInfo, + {0, "", prepareTraceId, SyncStage::END, GeneralError::E_ERROR, "store null"}); } if (!meta.enableCloud) { ZLOGW("meta.enableCloud is false, storeId:%{public}s, prepareTraceId:%{public}s", meta.GetStoreAlias().c_str(), prepareTraceId.c_str()); - return DoExceptionalCallback(async, details, storeInfo, prepareTraceId, E_CLOUD_DISABLED); + return DoExceptionalCallback(async, details, storeInfo, + {0, "", prepareTraceId, SyncStage::END, E_CLOUD_DISABLED, "disable cloud"}); } ZLOGI("database:<%{public}d:%{public}s:%{public}s:%{public}s> sync start, asyncDownloadAsset?[%{public}d]", - storeInfo.user, storeInfo.bundleName.c_str(), meta.GetStoreAlias().c_str(), prepareTraceId.c_str(), - meta.asyncDownloadAsset); - ReportSyncEvent(evt, BizState::BEGIN, E_OK); - SyncParam syncParam = { evt.GetMode(), evt.GetWait(), evt.IsCompensation(), MODE_DEFAULT, prepareTraceId }; - syncParam.asyncDownloadAsset = meta.asyncDownloadAsset; - auto [status, dbCode] = store->Sync({ SyncInfo::DEFAULT_ID }, *(evt.GetQuery()), - evt.AutoRetry() ? RetryCallback(storeInfo, retryer, evt.GetTriggerMode(), prepareTraceId, user) - : GetCallback(async, storeInfo, evt.GetTriggerMode(), prepareTraceId, user), - syncParam); - if (status != E_OK) { - if (async) { - detail.code = status; - async(std::move(details)); - } - UpdateFinishSyncInfo({ storeInfo.user, GetAccountId(storeInfo.user), storeInfo.bundleName, - storeInfo.storeName }, - storeInfo.syncId, E_ERROR); - if (status != GeneralError::E_NOT_SUPPORT) { - auto code = dbCode == 0 ? GenStore::CLOUD_ERR_OFFSET + status : dbCode; - ReportSyncEvent(evt, BizState::END, code); - } - } + storeInfo.user, storeInfo.bundleName.c_str(), meta.GetStoreAlias().c_str(), prepareTraceId.c_str(), + meta.asyncDownloadAsset); + StartCloudSync(evt, meta, store, retryer, details); }; } void SyncManager::ReportSyncEvent(const SyncEvent &evt, BizState bizState, int32_t code) { - SyncStage syncStage = SyncStage::START; auto &storeInfo = evt.GetStoreInfo(); if (bizState == BizState::BEGIN) { - syncStage = SyncStage::START; - RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, TRIGGER_SYNC, storeInfo.syncId, - evt.GetTriggerMode() }, - "GetSyncHandler", bizState); + RadarReporter::Report({storeInfo.bundleName.c_str(), CLOUD_SYNC, TRIGGER_SYNC, + storeInfo.syncId, evt.GetTriggerMode()}, "GetSyncHandler", bizState); } else { - syncStage = SyncStage::END; - RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, - evt.GetTriggerMode(), code }, - "GetSyncHandler", bizState); + RadarReporter::Report({storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, + storeInfo.syncId, evt.GetTriggerMode(), code}, "GetSyncHandler", bizState); } - Report({ evt.GetUser(), storeInfo.bundleName, evt.GetPrepareTraceId(), syncStage, code }); + SyncStage syncStage = (bizState == BizState::BEGIN) ? SyncStage::START : SyncStage::END; + SyncManager::Report({evt.GetUser(), storeInfo.bundleName, evt.GetPrepareTraceId(), syncStage, code, + "GetSyncHandler"}); } std::function SyncManager::GetClientChangeHandler() { return [this](const Event &event) { + if (executor_ == nullptr) { + return; + } auto &evt = static_cast(event); auto store = evt.GetStoreInfo(); SyncInfo syncInfo(store.user, store.bundleName, store.storeName); @@ -476,8 +493,8 @@ std::function SyncManager::GetClientChangeHandler() }; } -void SyncManager::Report(const std::string &faultType, const std::string &bundleName, int32_t errCode, - const std::string &appendix) +void SyncManager::Report( + const std::string &faultType, const std::string &bundleName, int32_t errCode, const std::string &appendix) { ArkDataFaultMsg msg = { .faultType = faultType, .bundleName = bundleName, @@ -487,23 +504,29 @@ void SyncManager::Report(const std::string &faultType, const std::string &bundle Reporter::GetInstance()->CloudSyncFault()->Report(msg); } +bool SyncManager::HandleRetryFinished(const SyncInfo &info, int32_t user, int32_t code, int32_t dbCode, + const std::string &prepareTraceId) +{ + if (code == E_OK || code == E_SYNC_TASK_MERGED) { + return true; + } + info.SetError(code); + RadarReporter::Report({ info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, info.triggerMode_, + dbCode }, + "GetRetryer", BizState::END); + SyncManager::Report({ user, info.bundleName_, prepareTraceId, SyncStage::END, + dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode, "GetRetryer finish" }); + Report(FT_CALLBACK, info.bundleName_, static_cast(Fault::CSF_GS_CLOUD_SYNC), + "code=" + std::to_string(code) + ",dbCode=" + std::to_string(static_cast(dbCode))); + return true; +} + SyncManager::Retryer SyncManager::GetRetryer(int32_t times, const SyncInfo &syncInfo, int32_t user) { if (times >= RETRY_TIMES) { return [this, user, info = SyncInfo(syncInfo)](Duration, int32_t code, int32_t dbCode, const std::string &prepareTraceId) mutable { - if (code == E_OK || code == E_SYNC_TASK_MERGED) { - return true; - } - info.SetError(code); - RadarReporter::Report({ info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, info.triggerMode_, - dbCode }, - "GetRetryer", BizState::END); - Report({ user, info.bundleName_, prepareTraceId, SyncStage::END, - dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode }); - Report(FT_CALLBACK, info.bundleName_, static_cast(Fault::CSF_GS_CLOUD_SYNC), - "code=" + std::to_string(code) + ",dbCode=" + std::to_string(static_cast(dbCode))); - return true; + return HandleRetryFinished(info, user, code, dbCode, prepareTraceId); }; } return [this, times, user, info = SyncInfo(syncInfo)](Duration interval, int32_t code, int32_t dbCode, @@ -514,15 +537,18 @@ SyncManager::Retryer SyncManager::GetRetryer(int32_t times, const SyncInfo &sync if (code == E_NO_SPACE_FOR_ASSET || code == E_RECODE_LIMIT_EXCEEDED) { info.SetError(code); RadarReporter::Report({ info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, info.triggerMode_, - dbCode }, + dbCode }, "GetRetryer", BizState::END); - Report({ user, info.bundleName_, prepareTraceId, SyncStage::END, - dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode }); + SyncManager::Report({ user, info.bundleName_, prepareTraceId, SyncStage::END, + dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode, "GetRetryer continue" }); Report(FT_CALLBACK, info.bundleName_, static_cast(Fault::CSF_GS_CLOUD_SYNC), - "code=" + std::to_string(code) + ",dbCode=" + std::to_string(static_cast(dbCode))); + "code=" + std::to_string(code) + ",dbCode=" + std::to_string(static_cast(dbCode))); return true; } + if (executor_ == nullptr) { + return false; + } activeInfos_.ComputeIfAbsent(info.syncId_, [this, times, interval, &info](uint64_t key) mutable { auto syncId = GenerateId(info.user_); auto ref = GenSyncRef(syncId); @@ -609,7 +635,6 @@ std::pair SyncManager::GetStore(const StoreMetaData & return { E_USER_UNLOCK, nullptr }; } if (CloudServer::GetInstance() == nullptr) { - ZLOGD("not support cloud sync"); return { E_NOT_SUPPORT, nullptr }; } auto [status, store] = AutoCache::GetInstance().GetDBStore(meta, {}); @@ -648,6 +673,7 @@ std::pair SyncManager::GetStore(const StoreMetaData & if (MetaDataManager::GetInstance().LoadMeta(info.GetKey(), info, true)) { config.maxNumber = info.maxNumber; config.maxSize = info.maxSize; + config.isSupportEncrypt = schemaMeta.e2eeEnable; } store->Bind(dbMeta, bindInfos, config); } @@ -727,7 +753,7 @@ std::pair SyncManager::GetLastResults(std::mapsecond.code != -1) { - return { SUCCESS, std::move(iter->second) }; + return { SUCCESS, iter->second }; } return { E_ERROR, {} }; } @@ -737,10 +763,7 @@ bool SyncManager::NeedSaveSyncInfo(const QueryKey &queryKey) if (queryKey.accountId.empty()) { return false; } - if (std::find(kvApps_.begin(), kvApps_.end(), queryKey.bundleName) != kvApps_.end()) { - return false; - } - return true; + return kvApps_.find(queryKey.bundleName) == kvApps_.end(); } std::pair> SyncManager::QueryLastSyncInfo( @@ -750,8 +773,8 @@ std::pair> SyncManager::QueryL for (const auto &queryKey : queryKeys) { std::string storeId = queryKey.storeId; QueryKey key{ queryKey.user, queryKey.accountId, queryKey.bundleName, queryKey.storeId }; - lastSyncInfos_.ComputeIfPresent(key, - [&storeId, &lastSyncInfoMap](auto &key, std::map &vals) { + lastSyncInfos_.ComputeIfPresent( + key, [&storeId, &lastSyncInfoMap](auto &key, std::map &vals) { auto [status, syncInfo] = GetLastResults(vals); if (status == SUCCESS) { lastSyncInfoMap.insert(std::make_pair(std::move(storeId), std::move(syncInfo))); @@ -761,7 +784,7 @@ std::pair> SyncManager::QueryL if (lastSyncInfoMap.find(queryKey.storeId) != lastSyncInfoMap.end()) { continue; } - auto [status, syncInfo] = GetLastSyncInfoFromMeta(queryKey); + auto [status, syncInfo] = SyncManager::GetLastSyncInfoFromMeta(queryKey); if (status == SUCCESS) { lastSyncInfoMap.insert(std::make_pair(std::move(syncInfo.storeId), std::move(syncInfo))); } @@ -801,7 +824,7 @@ void SyncManager::UpdateFinishSyncInfo(const QueryKey &queryKey, uint64_t syncId iter = val.erase(iter); } else if (iter->first == syncId) { iter->second.finishTime = duration_cast(system_clock::now().time_since_epoch()).count(); - iter->second.code = code; + iter->second.code = ConvertValidGeneralCode(code); iter->second.syncStatus = SyncStatus::FINISHED; SaveLastSyncInfo(key, std::move(iter->second)); iter = val.erase(iter); @@ -818,7 +841,7 @@ std::function SyncManager::GetCallback(const Gen { return [this, async, storeInfo, triggerMode, prepareTraceId, user](const GenDetails &result) { if (async != nullptr) { - async(result); + async(ConvertGenDetailsCode(result)); } if (result.empty()) { @@ -832,9 +855,9 @@ std::function SyncManager::GetCallback(const Gen int32_t dbCode = (result.begin()->second.dbCode == GenStore::DB_ERR_OFFSET) ? 0 : result.begin()->second.dbCode; RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, triggerMode, - dbCode, result.begin()->second.changeCount }, + dbCode, result.begin()->second.changeCount }, "GetCallback", BizState::END); - Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::END, dbCode }); + SyncManager::Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::END, dbCode, "GetCallback" }); if (dbCode != 0) { Report(FT_CALLBACK, storeInfo.bundleName, static_cast(Fault::CSF_GS_CLOUD_SYNC), "callback failed, dbCode=" + std::to_string(dbCode)); @@ -881,15 +904,16 @@ std::vector SyncManager::GetSchemaMeta(const CloudInfo &cloud, const } void SyncManager::DoExceptionalCallback(const GenAsync &async, GenDetails &details, const StoreInfo &storeInfo, - const std::string &prepareTraceId, int32_t code) + const ReportParam ¶m) { if (async) { - details[SyncInfo::DEFAULT_ID].code = code; + details[SyncInfo::DEFAULT_ID].code = param.errCode; async(details); } QueryKey queryKey{ storeInfo.user, GetAccountId(storeInfo.user), storeInfo.bundleName, storeInfo.storeName }; - UpdateFinishSyncInfo(queryKey, storeInfo.syncId, code); - Report({ storeInfo.user, storeInfo.bundleName, prepareTraceId, SyncStage::END, code }); + UpdateFinishSyncInfo(queryKey, storeInfo.syncId, param.errCode); + SyncManager::Report({ storeInfo.user, storeInfo.bundleName, param.prepareTraceId, SyncStage::END, + param.errCode, param.message }); } bool SyncManager::InitDefaultUser(int32_t &user) @@ -921,10 +945,10 @@ std::function SyncManager::Retr UpdateFinishSyncInfo(queryKey, storeInfo.syncId, code); if (code == E_OK) { RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, - triggerMode, code, details.begin()->second.changeCount }, + triggerMode, code, details.begin()->second.changeCount }, "RetryCallback", BizState::END); - Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::END, - dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode }); + SyncManager::Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::END, + dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode, "RetryCallback" }); } } retryer(GetInterval(code), code, dbCode, prepareTraceId); @@ -939,26 +963,41 @@ void SyncManager::BatchUpdateFinishState(const std::vector SyncManager::GetMetaData(const StoreInfo &storeInfo) { StoreMetaData meta(storeInfo); meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { - meta.user = "0"; // check if it is a public store. - StoreMetaDataLocal localMetaData; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMetaData, true) || - !localMetaData.isPublic || !MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { - ZLOGE("failed, no store meta. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), - meta.GetStoreAlias().c_str()); - return { false, meta }; - } + meta.dataDir = GetPath(meta); + if (!meta.dataDir.empty() && MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + return { true, meta }; + } + meta.user = "0"; // check if it is a public store. + meta.dataDir = GetPath(meta); + if (meta.dataDir.empty() || !MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + ZLOGE("failed, no store meta. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return { false, meta }; + } + StoreMetaDataLocal localMetaData; + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMetaData, true) || !localMetaData.isPublic) { + ZLOGE("failed, no store LocalMeta. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return { false, meta }; } return { true, meta }; } @@ -995,7 +1034,7 @@ void SyncManager::CleanCompensateSync(int32_t userId) void SyncManager::AddCompensateSync(const StoreMetaData &meta) { - compensateSyncInfos_.Compute(std::stoi(meta.user), + compensateSyncInfos_.Compute(std::atoi(meta.user.c_str()), [&meta](auto &, std::map> &apps) { apps[meta.bundleName].insert(meta.storeId); return true; @@ -1006,14 +1045,13 @@ std::pair SyncManager::GetLastSyncInfoFromMeta(const { CloudLastSyncInfo lastSyncInfo; if (!MetaDataManager::GetInstance().LoadMeta(CloudLastSyncInfo::GetKey(queryKey.user, queryKey.bundleName, - queryKey.storeId), - lastSyncInfo, true)) { - ZLOGE("load last sync info fail, bundleName: %{public}s, user:%{public}d", queryKey.bundleName.c_str(), - queryKey.user); + queryKey.storeId), lastSyncInfo, true)) { + ZLOGE("load last sync info fail, bundleName: %{public}s, user:%{public}d", + queryKey.bundleName.c_str(), queryKey.user); return { E_ERROR, lastSyncInfo }; } - if (queryKey.accountId != lastSyncInfo.id || - (!queryKey.storeId.empty() && queryKey.storeId != lastSyncInfo.storeId)) { + if (queryKey.accountId != lastSyncInfo.id || (!queryKey.storeId.empty() && + queryKey.storeId != lastSyncInfo.storeId)) { return { E_ERROR, lastSyncInfo }; } return { SUCCESS, std::move(lastSyncInfo) }; @@ -1021,11 +1059,26 @@ std::pair SyncManager::GetLastSyncInfoFromMeta(const void SyncManager::SaveLastSyncInfo(const QueryKey &queryKey, CloudLastSyncInfo &&info) { - if (!MetaDataManager::GetInstance().SaveMeta(CloudLastSyncInfo::GetKey(queryKey.user, queryKey.bundleName, - queryKey.storeId), - info, true)) { - ZLOGE("save cloud last info fail, bundleName: %{public}s, user:%{public}d", queryKey.bundleName.c_str(), - queryKey.user); + if (!MetaDataManager::GetInstance().SaveMeta(CloudLastSyncInfo::GetKey(queryKey.user, + queryKey.bundleName, queryKey.storeId), info, true)) { + ZLOGE("save cloud last info fail, bundleName: %{public}s, user:%{public}d", + queryKey.bundleName.c_str(), queryKey.user); + } +} + +GenDetails SyncManager::ConvertGenDetailsCode(const GenDetails &details) +{ + GenDetails newDetails; + for (const auto &it : details) { + GenProgressDetail detail = it.second; + detail.code = ConvertValidGeneralCode(detail.code); + newDetails.emplace(std::make_pair(it.first, std::move(detail))); } + return newDetails; +} + +int32_t SyncManager::ConvertValidGeneralCode(int32_t code) +{ + return (code >= E_OK && code < E_BUSY) ? code : E_ERROR; } } // namespace OHOS::CloudData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h index 6214a046..a24f0ae6 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h @@ -46,7 +46,6 @@ public: using TraceIds = std::map; using SyncStage = DistributedData::SyncStage; using ReportParam = DistributedData::ReportParam; - static std::pair GetStore(const StoreMetaData &meta, int32_t user, bool mustBind = true); class SyncInfo final { public: using Store = std::string; @@ -95,14 +94,16 @@ public: }; SyncManager(); ~SyncManager(); + static void Report(const ReportParam &reportParam); + static std::pair GetStore(const StoreMetaData &meta, int32_t user, bool mustBind = true); int32_t Bind(std::shared_ptr executor); int32_t DoCloudSync(SyncInfo syncInfo); int32_t StopCloudSync(int32_t user = 0); std::pair> QueryLastSyncInfo( const std::vector &queryKeys); - void Report(const ReportParam &reportParam); void OnScreenUnlocked(int32_t user); void CleanCompensateSync(int32_t userId); + static std::string GetPath(const StoreMetaData &meta); private: using Event = DistributedData::Event; @@ -137,6 +138,19 @@ private: static std::vector GetSchemaMeta(const CloudInfo &cloud, const std::string &bundleName); static bool NeedGetCloudInfo(CloudInfo &cloud); static GeneralError IsValid(SyncInfo &info, CloudInfo &cloud); + static std::function GetLockChangeHandler(); + static TraceIds GetPrepareTraceId(const SyncInfo &info, const CloudInfo &cloud); + static void Report( + const std::string &faultType, const std::string &bundleName, int32_t errCode, const std::string &appendix); + static std::pair GetLastResults(std::map &infos); + static std::pair GetLastSyncInfoFromMeta(const QueryKey &queryKey); + static void SaveLastSyncInfo(const QueryKey &queryKey, CloudLastSyncInfo &&info); + static void BatchReport(int32_t userId, const TraceIds &traceIds, SyncStage syncStage, int32_t errCode, + const std::string &message = ""); + static void ReportSyncEvent(const DistributedData::SyncEvent &evt, DistributedDataDfx::BizState bizState, + int32_t code); + static bool HandleRetryFinished(const SyncInfo &info, int32_t user, int32_t code, int32_t dbCode, + const std::string &prepareTraceId); Task GetSyncTask(int32_t times, bool retry, RefCount ref, SyncInfo &&syncInfo); void UpdateSchema(const SyncInfo &syncInfo); std::function GetSyncHandler(Retryer retryer); @@ -151,24 +165,18 @@ private: std::function GetPostEventTask(const std::vector &schemas, CloudInfo &cloud, SyncInfo &info, bool retry, const TraceIds &traceIds); void DoExceptionalCallback(const GenAsync &async, GenDetails &details, const StoreInfo &storeInfo, - const std::string &prepareTraceId, int32_t code = GeneralError::E_ERROR); + const ReportParam ¶m); bool InitDefaultUser(int32_t &user); std::function RetryCallback(const StoreInfo &storeInfo, Retryer retryer, int32_t triggerMode, const std::string &prepareTraceId, int32_t user); - static std::pair GetLastResults(std::map &infos); void BatchUpdateFinishState(const std::vector> &cloudSyncInfos, int32_t code); bool NeedSaveSyncInfo(const QueryKey &queryKey); - std::function GetLockChangeHandler(); - void BatchReport(int32_t userId, const TraceIds &traceIds, SyncStage syncStage, int32_t errCode); - TraceIds GetPrepareTraceId(const SyncInfo &info, const CloudInfo &cloud); + void StartCloudSync(const DistributedData::SyncEvent &evt, const StoreMetaData &meta, + const AutoCache::Store &store, Retryer retryer, DistributedData::GenDetails &details); std::pair GetMetaData(const StoreInfo &storeInfo); void AddCompensateSync(const StoreMetaData &meta); - static void Report( - const std::string &faultType, const std::string &bundleName, int32_t errCode, const std::string &appendix); - void ReportSyncEvent(const DistributedData::SyncEvent &evt, DistributedDataDfx::BizState bizState, int32_t code); - std::pair GetLastSyncInfoFromMeta(const QueryKey &queryKey); - static void SaveLastSyncInfo(const QueryKey &queryKey, CloudLastSyncInfo &&info); - + static DistributedData::GenDetails ConvertGenDetailsCode(const GenDetails &details); + static int32_t ConvertValidGeneralCode(int32_t code); static std::atomic genId_; std::shared_ptr executor_; ConcurrentMap actives_; diff --git a/datamgr_service/services/distributeddataservice/service/common/BUILD.gn b/datamgr_service/services/distributeddataservice/service/common/BUILD.gn index 7a493bd1..50a08c56 100644 --- a/datamgr_service/services/distributeddataservice/service/common/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/common/BUILD.gn @@ -31,7 +31,6 @@ ohos_source_set("distributeddata_common") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ "include" ] @@ -41,15 +40,16 @@ ohos_source_set("distributeddata_common") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] external_deps = [ "hicollie:libhicollie", "hilog:libhilog", + "ipc:ipc_single", "kv_store:distributeddb", "relational_store:native_rdb", + "kv_store:datamgr_common", ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" diff --git a/datamgr_service/services/distributeddataservice/service/common/xcollie.h b/datamgr_service/services/distributeddataservice/service/common/xcollie.h index 68f8436c..c5a880c0 100644 --- a/datamgr_service/services/distributeddataservice/service/common/xcollie.h +++ b/datamgr_service/services/distributeddataservice/service/common/xcollie.h @@ -18,6 +18,7 @@ #include #include "xcollie/xcollie.h" +#include "visibility.h" namespace OHOS::DistributedData { class XCollie { @@ -26,9 +27,9 @@ public: XCOLLIE_LOG = 0x1, XCOLLIE_RECOVERY = 0x2 }; - XCollie(const std::string &tag, uint32_t flag, uint32_t timeoutSeconds = RESTART_TIME_THRESHOLD, + API_EXPORT XCollie(const std::string &tag, uint32_t flag, uint32_t timeoutSeconds = RESTART_TIME_THRESHOLD, std::function func = nullptr, void *arg = nullptr); - ~XCollie(); + API_EXPORT ~XCollie(); private: int32_t id_ = -1; diff --git a/datamgr_service/services/distributeddataservice/service/config/BUILD.gn b/datamgr_service/services/distributeddataservice/service/config/BUILD.gn index 9349f811..99550fc4 100644 --- a/datamgr_service/services/distributeddataservice/service/config/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/config/BUILD.gn @@ -24,11 +24,14 @@ ohos_source_set("distributeddata_config") { } sources = [ "src/config_factory.cpp", + "src/model/app_access_check_config.cpp", "src/model/app_id_mapping_config.cpp", "src/model/backup_config.cpp", "src/model/checker_config.cpp", "src/model/cloud_config.cpp", "src/model/component_config.cpp", + "src/model/datashare_config.cpp", + "src/model/device_sync_app_white_list_config.cpp", "src/model/directory_config.cpp", "src/model/global_config.cpp", "src/model/network_config.cpp", @@ -39,7 +42,6 @@ ohos_source_set("distributeddata_config") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ @@ -53,13 +55,13 @@ ohos_source_set("distributeddata_config") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] external_deps = [ "hilog:libhilog", "json:nlohmann_json_static", + "kv_store:datamgr_common", ] subsystem_name = "distributeddatamgr" part_name = "datamgr_service" diff --git a/datamgr_service/services/distributeddataservice/service/config/include/config_factory.h b/datamgr_service/services/distributeddataservice/service/config/include/config_factory.h index bce10b04..87fcb7e6 100644 --- a/datamgr_service/services/distributeddataservice/service/config/include/config_factory.h +++ b/datamgr_service/services/distributeddataservice/service/config/include/config_factory.h @@ -33,6 +33,9 @@ public: API_EXPORT CloudConfig *GetCloudConfig(); API_EXPORT std::vector *GetAppIdMappingConfig(); API_EXPORT ThreadConfig *GetThreadConfig(); + API_EXPORT DataShareConfig *GetDataShareConfig(); + API_EXPORT DeviceSyncAppWhiteListConfig *GetDeviceSyncAppWhiteListConfig(); + API_EXPORT AppAccessCheckConfig *GetSyncAppsConfig(); private: static constexpr const char *CONF_PATH = "/system/etc/distributeddata/conf"; ConfigFactory(); diff --git a/datamgr_service/services/distributeddataservice/service/config/include/model/app_access_check_config.h b/datamgr_service/services/distributeddataservice/service/config/include/model/app_access_check_config.h new file mode 100644 index 00000000..5c3876f9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/config/include/model/app_access_check_config.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 OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_APP_ACCESS_CHECK_CONFIG_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_APP_ACCESS_CHECK_CONFIG_H + +#include "serializable/serializable.h" +namespace OHOS { +namespace DistributedData { +class AppAccessCheckConfig final : public Serializable { +public: + struct TrustApp final : public Serializable { + std::string bundleName = ""; + std::string appId = ""; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + std::vector trusts; +}; +} // namespace DistributedData +} // namespace OHOS +#endif //OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_APP_ACCESS_CHECK_CONFIG_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/config/include/model/datashare_config.h b/datamgr_service/services/distributeddataservice/service/config/include/model/datashare_config.h new file mode 100644 index 00000000..33d5f9b3 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/config/include/model/datashare_config.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 OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_DATASHARE_CONFIG_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_DATASHARE_CONFIG_H + +#include "serializable/serializable.h" +namespace OHOS { +namespace DistributedData { +class DataShareConfig final : public Serializable { +public: + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + std::vector dataShareExtNames; + std::vector updateLaunchNames; +}; +} // namespace DistributedData +} // namespace OHOS +#endif //OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_DATASHARE_CONFIG_H diff --git a/datamgr_service/services/distributeddataservice/service/config/include/model/device_sync_app_white_list_config.h b/datamgr_service/services/distributeddataservice/service/config/include/model/device_sync_app_white_list_config.h new file mode 100644 index 00000000..03729b9c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/config/include/model/device_sync_app_white_list_config.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 OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_DEVICE_SYNC_APP_WHITE_LIST_CONFIG_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_DEVICE_SYNC_APP_WHITE_LIST_CONFIG_H + +#include "serializable/serializable.h" +namespace OHOS { +namespace DistributedData { +class DeviceSyncAppWhiteListConfig final : public Serializable { +public: + struct WhiteList final : public Serializable { + std::string appId; + std::string bundleName; + uint32_t version; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + + std::vector whiteLists; +}; +} // namespace DistributedData +} // namespace OHOS +#endif //OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_DEVICE_SYNC_APP_WHITE_LIST_CONFIG_H diff --git a/datamgr_service/services/distributeddataservice/service/config/include/model/directory_config.h b/datamgr_service/services/distributeddataservice/service/config/include/model/directory_config.h index 03422499..8d7f170d 100644 --- a/datamgr_service/services/distributeddataservice/service/config/include/model/directory_config.h +++ b/datamgr_service/services/distributeddataservice/service/config/include/model/directory_config.h @@ -25,7 +25,12 @@ public: bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; }; + struct StoreType final : public Serializable, public DirectoryManager::StoreType { + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; std::vector strategy; + std::vector storeTypes; bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; }; diff --git a/datamgr_service/services/distributeddataservice/service/config/include/model/global_config.h b/datamgr_service/services/distributeddataservice/service/config/include/model/global_config.h index 91f5a237..4d7a9e53 100644 --- a/datamgr_service/services/distributeddataservice/service/config/include/model/global_config.h +++ b/datamgr_service/services/distributeddataservice/service/config/include/model/global_config.h @@ -15,14 +15,17 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_GLOBAL_CONFIG_H #define OHOS_DISTRIBUTED_DATA_SERVICES_CONFIG_MODEL_GLOBAL_CONFIG_H +#include "model/app_access_check_config.h" #include "model/app_id_mapping_config.h" #include "model/backup_config.h" #include "model/checker_config.h" #include "model/cloud_config.h" #include "model/component_config.h" +#include "model/datashare_config.h" #include "model/directory_config.h" #include "model/network_config.h" #include "model/thread_config.h" +#include "model/device_sync_app_white_list_config.h" #include "serializable/serializable.h" namespace OHOS { namespace DistributedData { @@ -40,6 +43,9 @@ public: CloudConfig *cloud = nullptr; std::vector *appIdMapping = nullptr; ThreadConfig *thread = nullptr; + DataShareConfig *dataShare = nullptr; + DeviceSyncAppWhiteListConfig *deviceSyncAppWhiteList = nullptr; + AppAccessCheckConfig *syncAppList = nullptr; ~GlobalConfig(); bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; diff --git a/datamgr_service/services/distributeddataservice/service/config/src/config_factory.cpp b/datamgr_service/services/distributeddataservice/service/config/src/config_factory.cpp index 3b05fce8..0f91cb6a 100644 --- a/datamgr_service/services/distributeddataservice/service/config/src/config_factory.cpp +++ b/datamgr_service/services/distributeddataservice/service/config/src/config_factory.cpp @@ -91,5 +91,20 @@ ThreadConfig *ConfigFactory::GetThreadConfig() { return config_.thread; } + +DataShareConfig *ConfigFactory::GetDataShareConfig() +{ + return config_.dataShare; +} + +DeviceSyncAppWhiteListConfig *ConfigFactory::GetDeviceSyncAppWhiteListConfig() +{ + return config_.deviceSyncAppWhiteList; +} + +AppAccessCheckConfig *ConfigFactory::GetSyncAppsConfig() +{ + return config_.syncAppList; +} } // namespace DistributedData } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/config/src/model/app_access_check_config.cpp b/datamgr_service/services/distributeddataservice/service/config/src/model/app_access_check_config.cpp new file mode 100644 index 00000000..41b658f9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/config/src/model/app_access_check_config.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 "model/app_access_check_config.h" +namespace OHOS { +namespace DistributedData { +bool AppAccessCheckConfig::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(trusts)], trusts); + return true; +} + +bool AppAccessCheckConfig::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(trusts), trusts); + return true; +} + +bool AppAccessCheckConfig::TrustApp::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(bundleName)], bundleName); + SetValue(node[GET_NAME(appId)], appId); + return true; +} + +bool AppAccessCheckConfig::TrustApp::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(bundleName), bundleName); + GetValue(node, GET_NAME(appId), appId); + return true; +} + +} // namespace DistributedData +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/config/src/model/datashare_config.cpp b/datamgr_service/services/distributeddataservice/service/config/src/model/datashare_config.cpp new file mode 100644 index 00000000..66f10496 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/config/src/model/datashare_config.cpp @@ -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. + */ +#include "model/datashare_config.h" +namespace OHOS { +namespace DistributedData { +bool DataShareConfig::Marshal(json &node) const +{ + SetValue(node[GET_NAME(dataShareExtNames)], dataShareExtNames); + SetValue(node[GET_NAME(updateLaunchNames)], updateLaunchNames); + return true; +} + +bool DataShareConfig::Unmarshal(const json &node) +{ + GetValue(node, GET_NAME(dataShareExtNames), dataShareExtNames); + GetValue(node, GET_NAME(updateLaunchNames), updateLaunchNames); + return true; +} +} // namespace DistributedData +} // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/config/src/model/device_sync_app_white_list_config.cpp b/datamgr_service/services/distributeddataservice/service/config/src/model/device_sync_app_white_list_config.cpp new file mode 100644 index 00000000..594d3f2a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/config/src/model/device_sync_app_white_list_config.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 "model/device_sync_app_white_list_config.h" +namespace OHOS { +namespace DistributedData { +bool DeviceSyncAppWhiteListConfig::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(whiteLists)], whiteLists); + return true; +} +bool DeviceSyncAppWhiteListConfig::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(whiteLists), whiteLists); + return true; +} + +bool DeviceSyncAppWhiteListConfig::WhiteList::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(appId)], appId); + SetValue(node[GET_NAME(bundleName)], bundleName); + SetValue(node[GET_NAME(version)], version); + return true; +} +bool DeviceSyncAppWhiteListConfig::WhiteList::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(appId), appId); + GetValue(node, GET_NAME(bundleName), bundleName); + GetValue(node, GET_NAME(version), version); + return true; +} +} // namespace DistributedData +} // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/config/src/model/directory_config.cpp b/datamgr_service/services/distributeddataservice/service/config/src/model/directory_config.cpp index 9f01b1e7..58d4f493 100644 --- a/datamgr_service/services/distributeddataservice/service/config/src/model/directory_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/config/src/model/directory_config.cpp @@ -36,15 +36,32 @@ bool DirectoryConfig::DirectoryStrategy::Unmarshal(const json &node) return true; } +bool DirectoryConfig::StoreType::Marshal(json &node) const +{ + SetValue(node[GET_NAME(range)], range); + SetValue(node[GET_NAME(type)], type); + return true; +} + +bool DirectoryConfig::StoreType::Unmarshal(const json &node) +{ + GetValue(node, GET_NAME(range), range); + GetValue(node, GET_NAME(type), type); + return true; +} + bool DirectoryConfig::Marshal(json &node) const { SetValue(node[GET_NAME(strategy)], strategy); + SetValue(node[GET_NAME(storeTypes)], storeTypes); return true; } bool DirectoryConfig::Unmarshal(const json &node) { - return GetValue(node, GET_NAME(strategy), strategy); + GetValue(node, GET_NAME(strategy), strategy); + GetValue(node, GET_NAME(storeTypes), storeTypes); + return true; } } // namespace DistributedData } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/config/src/model/global_config.cpp b/datamgr_service/services/distributeddataservice/service/config/src/model/global_config.cpp index e64b0122..51b12d61 100644 --- a/datamgr_service/services/distributeddataservice/service/config/src/model/global_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/config/src/model/global_config.cpp @@ -30,6 +30,9 @@ bool GlobalConfig::Marshal(json &node) const SetValue(node[GET_NAME(cloud)], cloud); SetValue(node[GET_NAME(appIdMapping)], appIdMapping); SetValue(node[GET_NAME(thread)], thread); + SetValue(node[GET_NAME(dataShare)], dataShare); + SetValue(node[GET_NAME(deviceSyncAppWhiteList)], deviceSyncAppWhiteList); + SetValue(node[GET_NAME(syncAppList)], syncAppList); return true; } @@ -47,6 +50,9 @@ bool GlobalConfig::Unmarshal(const json &node) GetValue(node, GET_NAME(cloud), cloud); GetValue(node, GET_NAME(appIdMapping), appIdMapping); GetValue(node, GET_NAME(thread), thread); + GetValue(node, GET_NAME(dataShare), dataShare); + GetValue(node, GET_NAME(deviceSyncAppWhiteList), deviceSyncAppWhiteList); + GetValue(node, GET_NAME(syncAppList), syncAppList); return true; } @@ -60,6 +66,9 @@ GlobalConfig::~GlobalConfig() delete cloud; delete appIdMapping; delete thread; + delete dataShare; + delete deviceSyncAppWhiteList; + delete syncAppList; } } // namespace DistributedData } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn b/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn index 2964c14d..788eceec 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn @@ -24,14 +24,15 @@ config("module_public_config") { "../../adapter/include", "../../app/src", "../../framework/include", - "${datashare_path}/frameworks/native/common/include", - "${datashare_path}/interfaces/inner_api/common/include", - "${datashare_path}/interfaces/inner_api/consumer/include", "${data_service_path}/adapter/include/communicator", + "${data_service_path}/service/config/include", "../common", "../crypto/include", "../permission/include", ] + if (is_emulator) { + defines = [ "IS_EMULATOR" ] + } } group("build_module") { deps = [ ":data_share_service" ] @@ -48,16 +49,18 @@ ohos_source_set("data_share_service") { sources = [ "common/app_connect_manager.cpp", "common/bundle_mgr_proxy.cpp", + "common/common_utils.cpp", "common/db_delegate.cpp", "common/div_strategy.cpp", "common/extension_ability_manager.cpp", "common/extension_connect_adaptor.cpp", "common/extension_mgr_proxy.cpp", "common/kv_delegate.cpp", + "common/proxy_data_manager.cpp", "common/rdb_delegate.cpp", "common/scheduler_manager.cpp", "common/seq_strategy.cpp", - "common/uri_utils.cpp", + "common/utils.cpp", "data/published_data.cpp", "data/resultset_json_formatter.cpp", "data/template_data.cpp", @@ -85,6 +88,7 @@ ohos_source_set("data_share_service") { "strategies/rdb_notify_strategy.cpp", "strategies/subscribe_strategy.cpp", "strategies/template_strategy.cpp", + "subscriber_managers/proxy_data_subscriber_manager.cpp", "subscriber_managers/published_data_subscriber_manager.cpp", "subscriber_managers/rdb_subscriber_manager.cpp", "sys_event_subscriber.cpp", @@ -94,13 +98,11 @@ ohos_source_set("data_share_service") { "-Wno-multichar", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] configs = [ ":module_public_config" ] @@ -123,6 +125,7 @@ ohos_source_set("data_share_service") { "bundle_framework:appexecfwk_core", "c_utils:utils", "data_share:datashare_common", + "data_share:datashare_common_lite", "device_manager:devicemanagersdk", "hicollie:libhicollie", "hilog:libhilog", @@ -132,6 +135,8 @@ ohos_source_set("data_share_service") { "json:nlohmann_json_static", "kv_store:datamgr_common", "kv_store:distributeddb", + "qos_manager:concurrent_task_client", + "qos_manager:qos", "relational_store:native_rdb", "relational_store:rdb_data_share_adapter", "samgr:samgr_proxy", @@ -140,4 +145,4 @@ ohos_source_set("data_share_service") { subsystem_name = "distributeddatamgr" part_name = "datamgr_service" -} +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.cpp index 410408be..afd7e1f4 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.cpp @@ -16,13 +16,14 @@ #include "bundle_mgr_proxy.h" #include "account/account_delegate.h" +#include "common_utils.h" #include "datashare_errno.h" #include "datashare_radar_reporter.h" #include "if_system_ability_manager.h" #include "iservice_registry.h" #include "log_print.h" #include "system_ability_definition.h" -#include "uri_utils.h" +#include "utils.h" #include "ipc_skeleton.h" #include "hiview_fault_adapter.h" @@ -114,6 +115,23 @@ int BundleMgrProxy::GetBundleInfoFromBMS( return E_OK; } +int BundleMgrProxy::GetBundleInfoFromBMSWithCheck( + const std::string &bundleName, int32_t userId, BundleConfig &bundleConfig, int32_t appIndex) +{ + int res = GetBundleInfoFromBMS(bundleName, userId, bundleConfig, appIndex); + if (res != E_OK) { + return res; + } + // Not allow normal app visit normal app. + if (!DataShareThreadLocal::IsFromSystemApp() && !bundleConfig.isSystemApp) { + ZLOGE("Not allow normal app visit normal app, bundle:%{public}s, callingPid:%{public}d", + bundleName.c_str(), IPCSkeleton::GetCallingPid()); + return E_NOT_SYSTEM_APP; + } + + return E_OK; +} + std::pair BundleMgrProxy::GetCallerAppIdentifier( const std::string &bundleName, int32_t userId) { @@ -179,7 +197,7 @@ void BundleMgrProxy::Delete(const std::string &bundleName, int32_t userId, int32 std::shared_ptr BundleMgrProxy::GetInstance() { - static std::shared_ptr proxy(new BundleMgrProxy()); + static std::shared_ptr proxy = std::make_shared(); return proxy; } @@ -199,6 +217,7 @@ std::pair BundleMgrProxy::ConvertToDataShareBundle(AppExecFwk return std::make_pair(err, bundleConfig); } bundleConfig.extensionInfos = extensionInfos; + bundleConfig.isSystemApp = bundleInfo.applicationInfo.isSystemApp; return std::make_pair(E_OK, bundleConfig); } @@ -243,6 +262,7 @@ std::pair> BundleMgrProxy::ConvertHapModuleInfo( hapModuleInfo.resourcePath = std::move(item.resourcePath); hapModuleInfo.hapPath = std::move(item.hapPath); hapModuleInfo.moduleName = std::move(item.moduleName); + hapModuleInfo.crossAppSharedConfig.resourcePath = std::move(item.crossAppSharedConfig); std::vector proxyDatas; for (auto &proxyData : item.proxyDatas) { ProxyData data; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.h b/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.h index 71bcc496..7198715f 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.h @@ -37,11 +37,17 @@ struct ProxyData { ProfileConfig profileInfo; }; +struct CrossAppSharedConfig { + std::string resourcePath; + ProxyDataProfileInfo profile; +}; + struct HapModuleInfo { std::string resourcePath; std::string hapPath; std::string moduleName; std::vector proxyDatas; + CrossAppSharedConfig crossAppSharedConfig; }; struct ExtensionAbilityInfo { @@ -57,21 +63,32 @@ struct ExtensionAbilityInfo { struct BundleConfig { std::string name; bool singleton = false; + bool isSystemApp = false; std::vector hapModuleInfos; std::vector extensionInfos; }; +struct BundleInfo { + std::string bundleName; + std::string appIdentifier; + int32_t userId; + int32_t appIndex; + uint32_t tokenId; +}; + class BundleMgrProxy final : public std::enable_shared_from_this { public: + BundleMgrProxy() = default; ~BundleMgrProxy(); static std::shared_ptr GetInstance(); int GetBundleInfoFromBMS(const std::string &bundleName, int32_t userId, BundleConfig &bundleConfig, int32_t appIndex = 0); + int GetBundleInfoFromBMSWithCheck(const std::string &bundleName, int32_t userId, + BundleConfig &bundleConfig, int32_t appIndex = 0); void Delete(const std::string &bundleName, int32_t userId, int32_t appIndex); sptr CheckBMS(); std::pair GetCallerAppIdentifier(const std::string &bundleName, int32_t userId); private: - BundleMgrProxy() = default; class ServiceDeathRecipient : public IRemoteObject::DeathRecipient { public: explicit ServiceDeathRecipient(std::weak_ptr owner) : owner_(owner) {} diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/common_utils.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/common_utils.cpp new file mode 100644 index 00000000..824008e7 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/common_utils.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. + */ +#define LOG_TAG "CommonUtils" +#include "common_utils.h" + +#include "accesstoken_kit.h" +#include "config_factory.h" +#include "log_print.h" +#include "tokenid_kit.h" + +namespace OHOS::DataShare { + +bool& DataShareThreadLocal::GetFromSystemApp() +{ + static thread_local bool isFromSystemApp = true; + return isFromSystemApp; +} + +void DataShareThreadLocal::SetFromSystemApp(bool isFromSystemApp) +{ + GetFromSystemApp() = isFromSystemApp; +} + +bool DataShareThreadLocal::IsFromSystemApp() +{ + return GetFromSystemApp(); +} + +void DataShareThreadLocal::CleanFromSystemApp() +{ + SetFromSystemApp(true); +} + +bool CheckSystemAbility(uint32_t tokenId) +{ + Security::AccessToken::ATokenTypeEnum tokenType = + Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId); + return (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE || + tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL); +} + +// GetTokenType use tokenId, and IsSystemApp use fullTokenId, these are different +bool CheckSystemCallingPermission(uint32_t tokenId, uint64_t fullTokenId) +{ + if (CheckSystemAbility(tokenId)) { + return true; + } + // IsSystemAppByFullTokenID here is not IPC + return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId); +} + +} // namespace OHOS::DataShare diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/common_utils.h b/datamgr_service/services/distributeddataservice/service/data_share/common/common_utils.h new file mode 100644 index 00000000..58c5cbd3 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/common_utils.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 DATASHARESERVICE_COMMON_UTILS_H +#define DATASHARESERVICE_COMMON_UTILS_H + +#include +#include +#include + +namespace OHOS::DataShare { +struct DataShareThreadLocal { + static bool& GetFromSystemApp(); + static void SetFromSystemApp(bool isFromSystemApp); + static bool IsFromSystemApp(); + static void CleanFromSystemApp(); +}; + +bool CheckSystemAbility(uint32_t tokenId); + +bool CheckSystemCallingPermission(uint32_t tokenId, uint64_t fullTokenId); + +inline int64_t GetSystemTime() +{ + return std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count(); +} + +} // namespace OHOS::DataShare +#endif // DATASHARESERVICE_COMMON_UTILS_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/context.h b/datamgr_service/services/distributeddataservice/service/data_share/common/context.h index 62da611a..e7043d23 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/context.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/context.h @@ -16,6 +16,7 @@ #ifndef DATASHARESERVICE_CONTEXT_H #define DATASHARESERVICE_CONTEXT_H +#include #include #include #include @@ -34,9 +35,16 @@ class Context { public: explicit Context() {} explicit Context(const std::string &uri) : uri(uri) {} - virtual ~Context() = default; + virtual ~Context() + { + if (secretMetaKey.size() > 0) { + std::fill(secretMetaKey.begin(), secretMetaKey.end(), '\0'); + } + } + std::string uri; int32_t currentUserId = -1; + int32_t visitedUserId = -1; int32_t appIndex = 0; int32_t haMode = 0; std::string permission; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/db_delegate.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/db_delegate.cpp index 50196297..9e77bcbb 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/db_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/db_delegate.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "DBAdaptor" #include "db_delegate.h" -#include "account_delegate.h" +#include "account/account_delegate.h" #include "kv_delegate.h" #include "log_print.h" #include "rdb_delegate.h" @@ -34,7 +34,7 @@ std::shared_ptr DBDelegate::Create(DistributedData::StoreMetaData &m { if (Account::GetInstance()->IsDeactivating(atoi(metaData.user.c_str()))) { ZLOGW("user %{public}s is deactivating, storeName: %{public}s", metaData.user.c_str(), - metaData.GetStoreAlias().c_str()); + StringUtils::GeneralAnonymous(metaData.GetStoreAlias()).c_str()); return nullptr; } std::shared_ptr store; @@ -46,12 +46,7 @@ std::shared_ptr DBDelegate::Create(DistributedData::StoreMetaData &m it->second->time_ = std::chrono::steady_clock::now() + std::chrono::seconds(INTERVAL); return !stores.empty(); } - store = std::make_shared(metaData, NO_CHANGE_VERSION, true, extUri, backup); - if (store->IsInvalid()) { - store = nullptr; - ZLOGE("creator failed, storeName: %{public}s", metaData.GetStoreAlias().c_str()); - return false; - } + store = std::make_shared(); auto entity = std::make_shared(store, metaData); stores.emplace(metaData.storeId, entity); StartTimer(metaData.isEncrypt); @@ -62,7 +57,24 @@ std::shared_ptr DBDelegate::Create(DistributedData::StoreMetaData &m } else { stores_.Compute(metaData.tokenId, storeFunc); } - return store; + + // rdbStore is initialized outside the ConcurrentMap, because this maybe a time-consuming operation. + bool success = store->Init(metaData, NO_CHANGE_VERSION, true, extUri, backup); + if (success) { + return store; + } + ZLOGE("creator failed, storeName: %{public}s", StringUtils::GeneralAnonymous(metaData.GetStoreAlias()).c_str()); + auto eraseFunc = [&metaData] + (auto &, std::map> &stores) -> bool { + stores.erase(metaData.storeId); + return !stores.empty(); + }; + if (metaData.isEncrypt) { + storesEncrypt_.Compute(metaData.tokenId, eraseFunc); + } else { + stores_.Compute(metaData.tokenId, eraseFunc); + } + return nullptr; } void DBDelegate::SetExecutorPool(std::shared_ptr executor) @@ -155,13 +167,13 @@ void DBDelegate::EraseStoreCache(const int32_t tokenId) storesEncrypt_.Erase(tokenId); } -std::shared_ptr KvDBDelegate::GetInstance( - bool reInit, const std::string &dir, const std::shared_ptr &executors) +std::shared_ptr KvDBDelegate::GetInstance(const std::string &dir, + const std::shared_ptr &executors) { static std::shared_ptr delegate = nullptr; static std::mutex mutex; std::lock_guard lock(mutex); - if ((delegate == nullptr || reInit) && executors != nullptr) { + if (delegate == nullptr && executors != nullptr) { delegate = std::make_shared(dir, executors); } return delegate; @@ -203,4 +215,4 @@ const std::string &KvData::GetId() const } KvData::KvData(const Id &id) : id(DistributedData::Serializable::Marshall(id)) {} -} // namespace OHOS::DataShare \ No newline at end of file +} // namespace OHOS::DataShare diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/db_delegate.h b/datamgr_service/services/distributeddataservice/service/data_share/common/db_delegate.h index 0cb36808..804a6763 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/db_delegate.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/db_delegate.h @@ -37,6 +37,8 @@ public: using Filter = std::function; static std::shared_ptr Create(DistributedData::StoreMetaData &metaData, const std::string &extUri = "", const std::string &backup = ""); + virtual bool Init(const DistributedData::StoreMetaData &meta, int version, + bool registerFunction, const std::string &extUri, const std::string &backup) = 0; static void Close(const Filter &filter); virtual std::pair> Query(const std::string &tableName, const DataSharePredicates &predicates, const std::vector &columns, @@ -125,11 +127,12 @@ class KvDBDelegate { public: static constexpr const char *TEMPLATE_TABLE = "template_"; static constexpr const char *DATA_TABLE = "data_"; + static constexpr const char *PROXYDATA_TABLE = "proxydata_"; static std::shared_ptr GetInstance( - bool reInit = false, const std::string &dir = "", const std::shared_ptr &executors = nullptr); + const std::string &dir = "", const std::shared_ptr &executors = nullptr); virtual ~KvDBDelegate() = default; - virtual std::pair Upsert(const std::string &collectionName, const KvData &value) = 0; - virtual std::pair Delete(const std::string &collectionName, const std::string &filter) = 0; + virtual std::pair Upsert(const std::string &collectionName, const KvData &value) = 0; + virtual std::pair Delete(const std::string &collectionName, const std::string &filter) = 0; virtual int32_t Get(const std::string &collectionName, const Id &id, std::string &value) = 0; virtual int32_t Get(const std::string &collectionName, const std::string &filter, const std::string &projection, std::string &result) = 0; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_ability_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_ability_manager.cpp index 2328285d..fa1011fd 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_ability_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_ability_manager.cpp @@ -19,7 +19,7 @@ #include "extension_mgr_proxy.h" #include "log_print.h" #include "datashare_errno.h" -#include "uri_utils.h" +#include "utils.h" namespace OHOS::DataShare { ExtensionAbilityManager &ExtensionAbilityManager::GetInstance() diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_connect_adaptor.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_connect_adaptor.cpp index 6a48232a..357b3560 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_connect_adaptor.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_connect_adaptor.cpp @@ -24,7 +24,7 @@ #include "extension_ability_info.h" #include "extension_mgr_proxy.h" #include "log_print.h" -#include "uri_utils.h" +#include "utils.h" namespace OHOS::DataShare { ExtensionConnectAdaptor::ExtensionConnectAdaptor() : data_(std::make_shared>(1)) diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_mgr_proxy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_mgr_proxy.cpp index dacd6ce8..fce328cd 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/extension_mgr_proxy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/extension_mgr_proxy.cpp @@ -23,7 +23,7 @@ #include "log_print.h" #include "system_ability_definition.h" #include "want.h" -#include "uri_utils.h" +#include "utils.h" #include "datashare_errno.h" namespace OHOS::DataShare { diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/kv_delegate.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/kv_delegate.cpp index be360b40..1c2375d4 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/kv_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/kv_delegate.cpp @@ -15,6 +15,7 @@ #define LOG_TAG "KvAdaptor" #include +#include #include #include #include @@ -23,14 +24,16 @@ #include "datashare_errno.h" #include "directory/directory_manager.h" +#include "hiview_fault_adapter.h" #include "grd_base/grd_error.h" #include "grd_document/grd_document_api.h" #include "ipc_skeleton.h" #include "log_print.h" #include "log_debug.h" +#include "time_service_client.h" namespace OHOS::DataShare { -constexpr int WAIT_TIME = 30; +constexpr int64_t TIME_LIMIT_BY_MILLISECONDS = 18 * 3600 * 1000; // 18 hours // If using multi-process access, back up dataShare.db.map as well. Check config file to see whether // using multi-process maccess @@ -126,6 +129,8 @@ bool KvDelegate::RestoreIfNeed(int32_t dbStatus) db_ = nullptr; isInitDone_ = false; } + DataShareFaultInfo faultInfo{HiViewFaultAdapter::kvDBCorrupt, "", "", "", __FUNCTION__, dbStatus, ""}; + HiViewFaultAdapter::ReportDataFault(faultInfo); // If db is NULL, it has been closed. Restore(); return true; @@ -185,11 +190,39 @@ std::pair KvDelegate::Delete(const std::string &collectionName return std::make_pair(E_OK, deleteCount); } +void KvDelegate::ScheduleBackup() +{ + auto currTime = MiscServices::TimeServiceClient::GetInstance()->GetBootTimeMs(); + if (currTime < 0) { + // Only do an error log print since schedule time does not rely on the time gets by GetBootTimeMs(). + ZLOGE("GetBootTimeMs failed, status %{public}" PRId64 "", currTime); + } else { + absoluteWaitTime_ = currTime + TIME_LIMIT_BY_MILLISECONDS; + } + + taskId_ = executors_->Schedule(std::chrono::seconds(waitTime_), [this]() { + std::lock_guard lock(mutex_); + GRD_DBClose(db_, GRD_DB_CLOSE); + db_ = nullptr; + isInitDone_ = false; + taskId_ = ExecutorPool::INVALID_TASK_ID; + Backup(); + }); +} + bool KvDelegate::Init() { if (isInitDone_) { if (executors_ != nullptr) { - executors_->Reset(taskId_, std::chrono::seconds(WAIT_TIME)); + auto currTime = MiscServices::TimeServiceClient::GetInstance()->GetBootTimeMs(); + if (currTime < 0) { + ZLOGE("GetBootTimeMs failed, status %{public}" PRId64 "", currTime); + // still return true since kv can work normally + return true; + } + if (currTime < absoluteWaitTime_) { + executors_->Reset(taskId_, std::chrono::seconds(waitTime_)); + } } return true; } @@ -201,14 +234,8 @@ bool KvDelegate::Init() return false; } if (executors_ != nullptr) { - taskId_ = executors_->Schedule(std::chrono::seconds(WAIT_TIME), [this]() { - std::lock_guard lock(mutex_); - GRD_DBClose(db_, GRD_DB_CLOSE); - db_ = nullptr; - isInitDone_ = false; - taskId_ = ExecutorPool::INVALID_TASK_ID; - Backup(); - }); + // schedule first backup task + ScheduleBackup(); } status = GRD_CreateCollection(db_, TEMPLATE_TABLE, nullptr, 0); if (status != GRD_OK) { @@ -225,6 +252,14 @@ bool KvDelegate::Init() RestoreIfNeed(status); return false; } + + status = GRD_CreateCollection(db_, PROXYDATA_TABLE, nullptr, 0); + if (status != GRD_OK) { + // If opeaning db succeeds, it is rare to fail to create tables + ZLOGE("GRD_CreateCollection data table failed,status %{public}d", status); + RestoreIfNeed(status); + return false; + } isInitDone_ = true; return true; } @@ -368,4 +403,4 @@ KvDelegate::KvDelegate(const std::string &path, const std::shared_ptr executors_ = nullptr; ExecutorPool::TaskId taskId_ = ExecutorPool::INVALID_TASK_ID; bool hasChange_ = false; + int64_t absoluteWaitTime_ = 0; + int64_t waitTime_ = 6 * 3600; // 6 hours }; } // namespace OHOS::DataShare #endif // DATASHARESERVICE_KV_DELEGATE_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/proxy_data_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/proxy_data_manager.cpp new file mode 100644 index 00000000..18a7b536 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/proxy_data_manager.cpp @@ -0,0 +1,490 @@ +/* + * 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. + */ + +#define LOG_TAG "ProxyDataManager" + +#include "datashare_observer.h" +#include "data_share_profile_config.h" +#include "dataproxy_handle_common.h" +#include "log_print.h" +#include "proxy_data_manager.h" +#include "utils.h" +#include "utils/anonymous.h" + +namespace OHOS::DataShare { + +ProxyDataManager &ProxyDataManager::GetInstance() +{ + static ProxyDataManager instance; + return instance; +} + +ProxyDataList::ProxyDataList(const ProxyDataListNode &node) + : KvData(Id(std::to_string(node.tokenId), node.userId)), value(node) +{ +} + +bool ProxyDataList::HasVersion() const +{ + return true; +} + +int ProxyDataList::GetVersion() const +{ + return value.GetVersion(); +} + +std::string ProxyDataList::GetValue() const +{ + return DistributedData::Serializable::Marshall(value); +} + +PublishedProxyData::PublishedProxyData(const ProxyDataNode &node) + : KvData(Id(node.proxyData.uri, node.userId)), value(node) +{ +} + +bool PublishedProxyData::HasVersion() const +{ + return true; +} + +int PublishedProxyData::GetVersion() const +{ + return value.GetVersion(); +} + +std::string PublishedProxyData::GetValue() const +{ + return DistributedData::Serializable::Marshall(value); +} + +ProxyDataListNode::ProxyDataListNode() : VersionData(-1) {} + +ProxyDataNode::ProxyDataNode() : VersionData(-1) {} + +bool ProxyDataNode::Marshal(DistributedData::Serializable::json &node) const +{ + bool ret = SetValue(node[GET_NAME(proxyData)], proxyData); + ret = ret && SetValue(node[GET_NAME(userId)], userId); + ret = ret && SetValue(node[GET_NAME(tokenId)], tokenId); + return ret && VersionData::Marshal(node); +} + +bool ProxyDataNode::Unmarshal(const DistributedData::Serializable::json &node) +{ + bool ret = GetValue(node, GET_NAME(proxyData), proxyData); + ret = ret && GetValue(node, GET_NAME(userId), userId); + return ret && GetValue(node, GET_NAME(tokenId), tokenId); +} + +bool ProxyDataListNode::Marshal(DistributedData::Serializable::json &node) const +{ + bool ret = SetValue(node[GET_NAME(uris)], uris); + ret = ret && SetValue(node[GET_NAME(userId)], userId); + ret = ret && SetValue(node[GET_NAME(tokenId)], tokenId); + return ret && VersionData::Marshal(node); +} + +bool ProxyDataListNode::Unmarshal(const DistributedData::Serializable::json &node) +{ + bool ret = GetValue(node, GET_NAME(uris), uris); + ret = ret && GetValue(node, GET_NAME(userId), userId); + ret = ret && GetValue(node, GET_NAME(tokenId), tokenId); + return ret; +} + +bool PublishedProxyData::VerifyPermission(const BundleInfo &callerBundleInfo, const ProxyDataNode &data) +{ + if (callerBundleInfo.tokenId == data.tokenId) { + return true; + } + + for (const auto &item : data.proxyData.allowList) { + if (callerBundleInfo.appIdentifier == item) { + return true; + } + } + return false; +} + +bool PublishedProxyData::CheckAndCorrectProxyData(DataShareProxyData &proxyData) +{ + // the upper limit of value is 4096 bytes, only string type is possible to exceed the limit + if (proxyData.value_.index() == DataProxyValueType::VALUE_STRING) { + std::string valueStr = std::get(proxyData.value_); + if (valueStr.size() > VALUE_MAX_SIZE) { + ZLOGE("value of proxyData %{public}s is over limit, size %{public}zu", + URIUtils::Anonymous(proxyData.uri_).c_str(), valueStr.size()); + return false; + } + } + if (proxyData.uri_.size() > URI_MAX_SIZE) { + ZLOGE("uri of proxyData %{public}s is over limit, size %{public}zu", + URIUtils::Anonymous(proxyData.uri_).c_str(), proxyData.uri_.size()); + return false; + } + int32_t allowListCount = 1; + auto it = proxyData.allowList_.begin(); + while (it != proxyData.allowList_.end()) { + if (it->size() > APPIDENTIFIER_MAX_SIZE) { + ZLOGW("appidentifier of proxyData %{public}s is over limit, size %{public}zu", + URIUtils::Anonymous(proxyData.uri_).c_str(), it->size()); + it = proxyData.allowList_.erase(it); + } else { + if (allowListCount++ > ALLOW_LIST_MAX_COUNT) { + break; + } + it++; + } + } + if (proxyData.allowList_.size() > ALLOW_LIST_MAX_COUNT) { + ZLOGW("allowList of proxyData %{public}s is over limit, size %{public}zu", + URIUtils::Anonymous(proxyData.uri_).c_str(), proxyData.allowList_.size()); + proxyData.allowList_.resize(ALLOW_LIST_MAX_COUNT); + } + return true; +} + +int32_t PublishedProxyData::PutIntoTable(std::shared_ptr kvDelegate, int32_t user, + uint32_t tokenId, const std::vector &proxyDataList, const DataShareProxyData &proxyData) +{ + if (kvDelegate == nullptr) { + ZLOGE("kv delegate is null!"); + return INNER_ERROR; + } + + SerialDataShareProxyData serialProxyData(proxyData.uri_, proxyData.value_, proxyData.allowList_); + auto ret = kvDelegate->Upsert(KvDBDelegate::PROXYDATA_TABLE, PublishedProxyData(ProxyDataNode( + serialProxyData, user, tokenId))); + if (ret.first != E_OK) { + ZLOGE("db Upsert failed, %{public}s %{public}d", + URIUtils::Anonymous(proxyData.uri_).c_str(), ret.first); + return INNER_ERROR; + } + + if (!proxyDataList.empty()) { + auto value = ProxyDataList(ProxyDataListNode( + proxyDataList, user, tokenId)); + ret = kvDelegate->Upsert(KvDBDelegate::PROXYDATA_TABLE, value); + if (ret.first != E_OK) { + ZLOGE("db Upsert failed, %{public}x %{public}d", tokenId, user); + return INNER_ERROR; + } + } + return SUCCESS; +} + +int32_t PublishedProxyData::InsertProxyData(std::shared_ptr kvDelegate, const std::string &bundleName, + const int32_t &user, const uint32_t &tokenId, const DataShareProxyData &proxyData) +{ + if (kvDelegate == nullptr) { + ZLOGE("kv delegate is null!"); + return INNER_ERROR; + } + + ProxyDataListNode proxyDataList; + std::string listFilter = Id(std::to_string(tokenId), user); + std::string listQueryResult; + kvDelegate->Get(KvDBDelegate::PROXYDATA_TABLE, listFilter, "{}", listQueryResult); + if (!listQueryResult.empty()) { + if (!ProxyDataListNode::Unmarshall(listQueryResult, proxyDataList)) { + ZLOGE("ProxyDataListNode unmarshall failed, %{public}s", + StringUtils::GeneralAnonymous(listQueryResult).c_str()); + return INNER_ERROR; + } + } + if (proxyDataList.uris.size() >= PROXY_DATA_MAX_COUNT) { + return OVER_LIMIT; + } + + std::string modifyBundle; + URIUtils::GetBundleNameFromProxyURI(proxyData.uri_, modifyBundle); + if (modifyBundle != bundleName) { + ZLOGE("only allowed to publish the proxyData of self bundle %{public}s, dest bundle %{public}s", + bundleName.c_str(), modifyBundle.c_str()); + return NO_PERMISSION; + } + + auto it = std::find(proxyDataList.uris.begin(), proxyDataList.uris.end(), proxyData.uri_); + if (it == proxyDataList.uris.end()) { + proxyDataList.uris.emplace_back(proxyData.uri_); + } + return PutIntoTable(kvDelegate, user, tokenId, proxyDataList.uris, proxyData); +} + +int32_t PublishedProxyData::UpdateProxyData(std::shared_ptr kvDelegate, const std::string &bundleName, + const int32_t &user, const uint32_t &tokenId, const DataShareProxyData &proxyData) +{ + if (kvDelegate == nullptr) { + ZLOGE("kv delegate is null!"); + return INNER_ERROR; + } + std::vector proxyDataList; + return PutIntoTable(kvDelegate, user, tokenId, proxyDataList, proxyData); +} + +int32_t PublishedProxyData::Query(const std::string &uri, const BundleInfo &callerBundleInfo, + DataShareProxyData &proxyData) +{ + auto delegate = KvDBDelegate::GetInstance(); + if (delegate == nullptr) { + ZLOGE("db open failed"); + return INNER_ERROR; + } + std::string filter = Id(uri, callerBundleInfo.userId); + std::string queryResult; + delegate->Get(KvDBDelegate::PROXYDATA_TABLE, filter, "{}", queryResult); + if (queryResult.empty()) { + return URI_NOT_EXIST; + } + ProxyDataNode data; + if (!ProxyDataNode::Unmarshall(queryResult, data)) { + ZLOGE("Unmarshall failed, %{public}s", StringUtils::GeneralAnonymous(queryResult).c_str()); + return INNER_ERROR; + } + DataShareProxyData tempProxyData(data.proxyData.uri, data.proxyData.value, data.proxyData.allowList); + if (callerBundleInfo.tokenId != data.tokenId) { + tempProxyData.allowList_ = {}; + } + if (!VerifyPermission(callerBundleInfo, data)) { + return NO_PERMISSION; + } + + proxyData = tempProxyData; + return SUCCESS; +} + +int32_t PublishedProxyData::Upsert(const DataShareProxyData &proxyData, const BundleInfo &callerBundleInfo, + DataShareObserver::ChangeType &type) +{ + type = DataShareObserver::ChangeType::INVAILD; + auto delegate = KvDBDelegate::GetInstance(); + if (delegate == nullptr) { + ZLOGE("db open failed"); + return INNER_ERROR; + } + + auto data = proxyData; + if (!CheckAndCorrectProxyData(data)) { + return OVER_LIMIT; + } + std::string filter = Id(data.uri_, callerBundleInfo.userId); + std::string queryResult; + delegate->Get(KvDBDelegate::PROXYDATA_TABLE, filter, "{}", queryResult); + if (queryResult.empty()) { + type = DataShareObserver::ChangeType::INSERT; + return InsertProxyData(delegate, callerBundleInfo.bundleName, + callerBundleInfo.userId, callerBundleInfo.tokenId, data); + } else { + ProxyDataNode oldData; + if (!ProxyDataNode::Unmarshall(queryResult, oldData)) { + ZLOGE("ProxyDataNode unmarshall failed, %{public}s", StringUtils::GeneralAnonymous(queryResult).c_str()); + return INNER_ERROR; + } + if (callerBundleInfo.tokenId != oldData.tokenId) { + ZLOGE("only allow to modify the proxyData of self bundle %{public}d, dest bundle %{public}d", + callerBundleInfo.tokenId, oldData.tokenId); + return NO_PERMISSION; + } + if (data.isValueUndefined) { + data.value_ = oldData.proxyData.value; + } + if (data.isAllowListUndefined) { + data.allowList_ = oldData.proxyData.allowList; + } + // only when value changed is need notify + if (oldData.proxyData.value != data.value_) { + type = DataShareObserver::ChangeType::UPDATE; + } + return UpdateProxyData(delegate, callerBundleInfo.bundleName, + callerBundleInfo.userId, callerBundleInfo.tokenId, data); + } +} + +int32_t PublishedProxyData::Delete(const std::string &uri, const BundleInfo &callerBundleInfo, + DataShareProxyData &oldProxyData, DataShareObserver::ChangeType &type) +{ + type = DataShareObserver::ChangeType::INVAILD; + auto delegate = KvDBDelegate::GetInstance(); + if (delegate == nullptr) { + ZLOGE("db open failed"); + return INNER_ERROR; + } + + std::string bundleName; + URIUtils::GetBundleNameFromProxyURI(uri, bundleName); + if (callerBundleInfo.bundleName != bundleName) { + return NO_PERMISSION; + } + std::string queryResult; + delegate->Get(KvDBDelegate::PROXYDATA_TABLE, Id(uri, callerBundleInfo.userId), "{}", queryResult); + if (queryResult.empty()) { + return URI_NOT_EXIST; + } + + ProxyDataNode oldData; + if (!ProxyDataNode::Unmarshall(queryResult, oldData)) { + ZLOGE("Unmarshall failed, %{private}s", queryResult.c_str()); + return INNER_ERROR; + } + if (callerBundleInfo.tokenId != oldData.tokenId) { + return NO_PERMISSION; + } + auto ret = delegate->Delete(KvDBDelegate::PROXYDATA_TABLE, Id(uri, callerBundleInfo.userId)); + if (ret.first != E_OK) { + ZLOGE("db Delete failed, %{public}s %{public}d", URIUtils::Anonymous(uri).c_str(), ret.first); + return INNER_ERROR; + } + std::vector uris; + auto count = ProxyDataList::Query(callerBundleInfo.tokenId, callerBundleInfo.userId, uris); + if (count <= 0) { + ZLOGI("get bundle %{public}s's proxyData failed", callerBundleInfo.bundleName.c_str()); + return INNER_ERROR; + } + auto it = std::find(uris.begin(), uris.end(), uri); + if (it != uris.end()) { + uris.erase(it); + } + ret = delegate->Upsert(KvDBDelegate::PROXYDATA_TABLE, ProxyDataList(ProxyDataListNode( + uris, callerBundleInfo.userId, callerBundleInfo.tokenId))); + if (ret.first != E_OK) { + ZLOGE("db Upsert failed, %{public}x %{public}d", callerBundleInfo.tokenId, ret.first); + return INNER_ERROR; + } + oldProxyData = DataShareProxyData(oldData.proxyData.uri, oldData.proxyData.value, oldData.proxyData.allowList); + type = DataShareObserver::ChangeType::DELETE; + return SUCCESS; +} + +int32_t ProxyDataList::Query(uint32_t tokenId, int32_t userId, std::vector &proxyDataList) +{ + int32_t invalidNum = -1; + auto delegate = KvDBDelegate::GetInstance(); + if (delegate == nullptr) { + ZLOGE("db open failed"); + return invalidNum; + } + std::string filter = Id(std::to_string(tokenId), userId); + std::string queryResult; + delegate->Get(KvDBDelegate::PROXYDATA_TABLE, filter, "{}", queryResult); + if (queryResult.empty()) { + return invalidNum; + } + ProxyDataListNode data; + if (!ProxyDataListNode::Unmarshall(queryResult, data)) { + ZLOGE("Unmarshall failed, %{public}s", StringUtils::GeneralAnonymous(queryResult).c_str()); + return invalidNum; + } + + proxyDataList = std::move(data.uris); + return proxyDataList.size(); +} + +bool ProxyDataManager::GetCrossAppSharedConfig(const std::string &bundleName, int32_t user, + int32_t index, std::vector &proxyDatas) +{ + BundleConfig bundleConfig; + auto ret = BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS(bundleName, user, bundleConfig, index); + if (ret != E_OK) { + ZLOGE("Get bundleInfo falied, ret : %{public}d", ret); + return false; + } + std::vector resourcePath; + std::vector datas; + std::for_each(bundleConfig.hapModuleInfos.begin(), + bundleConfig.hapModuleInfos.end(), [&datas](const HapModuleInfo hapModuleInfo) { + if (!hapModuleInfo.crossAppSharedConfig.resourcePath.empty()) { + auto [ret, data] = DataShareProfileConfig::GetCrossAppSharedConfig( + hapModuleInfo.crossAppSharedConfig.resourcePath, hapModuleInfo.resourcePath, hapModuleInfo.hapPath); + if (ret == SUCCESS) { + datas.insert(datas.end(), data.begin(), data.end()); + } else { + ZLOGE("get shareConfig failed, err: %{public}d", ret); + } + } + }); + std::for_each(datas.begin(), datas.end(), [&proxyDatas](auto &data) { + proxyDatas.emplace_back(std::move(data.uri), std::move(data.value), std::move(data.allowList)); + }); + return true; +} + +void ProxyDataManager::OnAppInstall(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId) +{ + std::vector proxyDatas; + BundleInfo callerBundleInfo; + callerBundleInfo.bundleName = bundleName; + callerBundleInfo.userId = user; + callerBundleInfo.appIndex = index; + callerBundleInfo.tokenId = tokenId; + if (!GetCrossAppSharedConfig(bundleName, user, index, proxyDatas)) { + ZLOGE("GetCrossAppSharedConfig after install failed"); + return; + } + DataShareObserver::ChangeType type; + std::for_each(proxyDatas.begin(), proxyDatas.end(), + [user, bundleName, callerBundleInfo, &type](const DataShareProxyData proxyData) { + PublishedProxyData::Upsert(proxyData, callerBundleInfo, type); + }); +} + +void ProxyDataManager::OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId) +{ + std::vector proxyDatas; + BundleInfo callerBundleInfo; + callerBundleInfo.bundleName = bundleName; + callerBundleInfo.userId = user; + callerBundleInfo.appIndex = index; + callerBundleInfo.tokenId = tokenId; + DataShareObserver::ChangeType type; + if (!GetCrossAppSharedConfig(bundleName, user, index, proxyDatas)) { + ZLOGE("GetCrossAppSharedConfig after install failed"); + return; + } + std::vector uris; + auto count = ProxyDataList::Query(tokenId, user, uris); + if (count <= 0) { + ZLOGI("bundle %{public}s has no proxyData", bundleName.c_str()); + } + DataShareProxyData oldProxyData; + for (const auto &uri : uris) { + PublishedProxyData::Delete(uri, callerBundleInfo, oldProxyData, type); + } + std::for_each(proxyDatas.begin(), proxyDatas.end(), + [user, bundleName, callerBundleInfo, &type](const DataShareProxyData proxyData) { + PublishedProxyData::Upsert(proxyData, callerBundleInfo, type); + }); +} + +void ProxyDataManager::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId) +{ + DataShareProxyData proxyData; + BundleInfo callerBundleInfo; + callerBundleInfo.bundleName = bundleName; + callerBundleInfo.userId = user; + callerBundleInfo.appIndex = index; + callerBundleInfo.tokenId = tokenId; + DataShareObserver::ChangeType type; + std::vector uris; + auto count = ProxyDataList::Query(tokenId, user, uris); + if (count <= 0) { + ZLOGI("bundle %{public}s has no proxyData", bundleName.c_str()); + } + for (const auto &uri : uris) { + PublishedProxyData::Delete(uri, callerBundleInfo, proxyData, type); + } +} +} // namespace OHOS::DataShare \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/proxy_data_manager.h b/datamgr_service/services/distributeddataservice/service/data_share/common/proxy_data_manager.h new file mode 100644 index 00000000..75da70ed --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/proxy_data_manager.h @@ -0,0 +1,101 @@ +/* + * 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 DATASHARESERVICE_PROXY_DATA_MANAGER_H +#define DATASHARESERVICE_PROXY_DATA_MANAGER_H + +#include "bundle_mgr_proxy.h" +#include "dataproxy_handle_common.h" +#include "db_delegate.h" + +namespace OHOS::DataShare { + +class ProxyDataListNode final : public VersionData { +public: + ProxyDataListNode(); + ProxyDataListNode(const std::vector &uris, int32_t userId, uint32_t tokenId) + : VersionData(0), uris(uris), userId(userId), tokenId(tokenId) {} + ~ProxyDataListNode() = default; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + std::vector uris; + int32_t userId = Id::INVALID_USER; + uint32_t tokenId = 0; +}; + +class ProxyDataList final : public KvData { +public: + explicit ProxyDataList(const ProxyDataListNode &node); + ~ProxyDataList() = default; + static int32_t Query(uint32_t tokenId, int32_t userId, std::vector &proxyDataList); + bool HasVersion() const override; + int GetVersion() const override; + std::string GetValue() const override; + +private: + ProxyDataListNode value; +}; + +class ProxyDataNode final : public VersionData { +public: + ProxyDataNode(); + ProxyDataNode(const SerialDataShareProxyData proxyData, int32_t userId, uint32_t tokenId) + : VersionData(0), proxyData(proxyData), userId(userId), tokenId(tokenId) {} + ~ProxyDataNode() = default; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + SerialDataShareProxyData proxyData; + int32_t userId = Id::INVALID_USER; + uint32_t tokenId = 0; +}; + +class PublishedProxyData final : public KvData { +public: + explicit PublishedProxyData(const ProxyDataNode &node); + ~PublishedProxyData() = default; + static int32_t Query(const std::string &uri, const BundleInfo &callerBundleInfo, DataShareProxyData &proxyData); + static int32_t Delete(const std::string &uri, const BundleInfo &callerBundleInfo, DataShareProxyData &oldProxyData, + DataShareObserver::ChangeType &type); + static int32_t Upsert(const DataShareProxyData &proxyData, const BundleInfo &callerBundleInfo, + DataShareObserver::ChangeType &type); + static bool VerifyPermission(const BundleInfo &callerBundleInfo, const ProxyDataNode &data); + bool HasVersion() const override; + int GetVersion() const override; + std::string GetValue() const override; + +private: + static int32_t InsertProxyData(std::shared_ptr kvDelegate, const std::string &bundleName, + const int32_t &user, const uint32_t &tokenId, const DataShareProxyData &proxyData); + static int32_t UpdateProxyData(std::shared_ptr kvDelegate, const std::string &bundleName, + const int32_t &user, const uint32_t &tokenId, const DataShareProxyData &proxyData); + static int32_t PutIntoTable(std::shared_ptr kvDelegate, int32_t user, + uint32_t tokenId, const std::vector &proxyDataList, const DataShareProxyData &proxyData); + static bool CheckAndCorrectProxyData(DataShareProxyData &proxyData); + ProxyDataNode value; +}; + +class ProxyDataManager { +public: + static ProxyDataManager &GetInstance(); + void OnAppInstall(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId); + void OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId); + void OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index, uint32_t tokenId); + +private: + bool GetCrossAppSharedConfig(const std::string &bundleName, int32_t user, int32_t index, + std::vector &proxyDatas); +}; +} // namespace OHOS::DataShare +#endif // DATASHARESERVICE_PROXY_DATA_MANAGER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.cpp index de1036ff..940f599c 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.cpp @@ -15,7 +15,7 @@ #define LOG_TAG "RdbAdaptor" #include "rdb_delegate.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "datashare_errno.h" #include "datashare_radar_reporter.h" #include "device_manager_adapter.h" @@ -35,6 +35,7 @@ #include "db_delegate.h" #include "log_debug.h" #include "ipc_skeleton.h" +#include "common_utils.h" namespace OHOS::DataShare { constexpr static int32_t MAX_RESULTSET_COUNT = 32; @@ -81,13 +82,19 @@ std::pair RdbDelegate::GetConfig(const DistributedData::Sto config.SetBundleName(meta.bundleName); if (meta.isEncrypt) { DistributedData::SecretKeyMetaData secretKeyMeta; - if (!DistributedData::MetaDataManager::GetInstance().LoadMeta(meta.GetSecretKey(), secretKeyMeta, true)) { + auto metaKey = meta.GetSecretKey(); + if (!DistributedData::MetaDataManager::GetInstance().LoadMeta(metaKey, secretKeyMeta, true) || + secretKeyMeta.sKey.empty()) { return std::make_pair(E_DB_NOT_EXIST, config); } - std::vector decryptKey; - if (!DistributedData::CryptoManager::GetInstance().Decrypt(meta, secretKeyMeta, decryptKey)) { + DistributedData::CryptoManager::CryptoParams decryptParams = { .area = secretKeyMeta.area, + .userId = meta.user, .nonce = secretKeyMeta.nonce }; + auto decryptKey = DistributedData::CryptoManager::GetInstance().Decrypt(secretKeyMeta.sKey, decryptParams); + if (decryptKey.empty()) { return std::make_pair(E_ERROR, config); - }; + } + // update secret key of area or nonce + DistributedData::CryptoManager::GetInstance().UpdateSecretMeta(decryptKey, meta, metaKey, secretKeyMeta); config.SetEncryptKey(decryptKey); std::fill(decryptKey.begin(), decryptKey.end(), 0); } @@ -97,16 +104,32 @@ std::pair RdbDelegate::GetConfig(const DistributedData::Sto return std::make_pair(E_OK, config); } -RdbDelegate::RdbDelegate(const DistributedData::StoreMetaData &meta, int version, +RdbDelegate::RdbDelegate() +{ +} + +bool RdbDelegate::Init(const DistributedData::StoreMetaData &meta, int version, bool registerFunction, const std::string &extUri, const std::string &backup) - : tokenId_(meta.tokenId), bundleName_(meta.bundleName), storeName_(meta.storeId), - haMode_(meta.haMode), extUri_(extUri), backup_(backup), user_(meta.user) { + if (isInited_) { + return true; + } + std::lock_guard lock(initMutex_); + if (isInited_) { + return true; + } + tokenId_ = meta.tokenId; + bundleName_ = meta.bundleName; + storeName_ = meta.storeId; + haMode_ = meta.haMode; + extUri_ = extUri; + backup_ = backup; + user_ = meta.user; auto [err, config] = GetConfig(meta, registerFunction); if (err != E_OK) { ZLOGW("Get rdbConfig failed, errCode is %{public}d, dir is %{public}s", err, - DistributedData::Anonymous::Change(meta.dataDir).c_str()); - return; + URIUtils::Anonymous(meta.dataDir).c_str()); + return false; } DefaultOpenCallback callback; TimeoutReport timeoutReport({meta.bundleName, "", meta.storeId, __FUNCTION__, 0}); @@ -115,22 +138,28 @@ RdbDelegate::RdbDelegate(const DistributedData::StoreMetaData &meta, int version timeoutReport.Report(meta.user, callingPid, -1, meta.instanceId); if (errCode_ != E_OK) { ZLOGW("GetRdbStore failed, errCode is %{public}d, dir is %{public}s", errCode_, - DistributedData::Anonymous::Change(meta.dataDir).c_str()); + URIUtils::Anonymous(meta.dataDir).c_str()); RdbDelegate::TryAndSend(errCode_); + return false; } + isInited_ = true; + return true; } + RdbDelegate::~RdbDelegate() { ZLOGI("Destruct. BundleName: %{public}s. StoreName: %{public}s. user: %{public}s", bundleName_.c_str(), - DistributedData::Anonymous::Change(storeName_).c_str(), user_.c_str()); + StringUtils::GeneralAnonymous(storeName_).c_str(), user_.c_str()); } + void RdbDelegate::TryAndSend(int errCode) { if (errCode != E_SQLITE_CORRUPT || (haMode_ == HAMode::SINGLE && (backup_ != DUAL_WRITE && backup_ != PERIODIC))) { return; } ZLOGE("Database corruption. BundleName: %{public}s. StoreName: %{public}s. ExtUri: %{public}s", - bundleName_.c_str(), storeName_.c_str(), DistributedData::Anonymous::Change(extUri_).c_str()); + bundleName_.c_str(), StringUtils::GeneralAnonymous(storeName_).c_str(), + URIUtils::Anonymous(extUri_).c_str()); AAFwk::WantParams params; params.SetParam("BundleName", AAFwk::String::Box(bundleName_)); params.SetParam("StoreName", AAFwk::String::Box(storeName_)); @@ -149,7 +178,7 @@ std::pair RdbDelegate::InsertEx(const std::string &tableName, ValuesBucket bucket = RdbDataShareAdapter::RdbUtils::ToValuesBucket(valuesBucket); int ret = store_->Insert(rowId, tableName, bucket); if (ret != E_OK) { - ZLOGE("Insert failed %{public}s %{public}d", tableName.c_str(), ret); + ZLOGE("Insert failed %{public}s %{public}d", StringUtils::GeneralAnonymous(tableName).c_str(), ret); RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_CALL_RDB, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::INSERT_RDB_ERROR); if (ret == E_SQLITE_ERROR) { @@ -173,7 +202,7 @@ std::pair RdbDelegate::UpdateEx( RdbPredicates predicates = RdbDataShareAdapter::RdbUtils::ToPredicates(predicate, tableName); int ret = store_->Update(changeCount, bucket, predicates); if (ret != E_OK) { - ZLOGE("Update failed %{public}s %{public}d", tableName.c_str(), ret); + ZLOGE("Update failed %{public}s %{public}d", StringUtils::GeneralAnonymous(tableName).c_str(), ret); RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_CALL_RDB, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::UPDATE_RDB_ERROR); if (ret == E_SQLITE_ERROR) { @@ -195,7 +224,7 @@ std::pair RdbDelegate::DeleteEx(const std::string &tableName, RdbPredicates predicates = RdbDataShareAdapter::RdbUtils::ToPredicates(predicate, tableName); int ret = store_->Delete(changeCount, predicates); if (ret != E_OK) { - ZLOGE("Delete failed %{public}s %{public}d", tableName.c_str(), ret); + ZLOGE("Delete failed %{public}s %{public}d", StringUtils::GeneralAnonymous(tableName).c_str(), ret); RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_CALL_RDB, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::DELETE_RDB_ERROR); if (ret == E_SQLITE_ERROR) { @@ -216,7 +245,6 @@ std::pair> RdbDelegate::Query(const std return std::make_pair(errCode_, nullptr); } int count = resultSetCount.fetch_add(1); - ZLOGD_MACRO("start query %{public}d", count); if (count >= MAX_RESULTSET_COUNT && IsLimit(count, callingPid, callingTokenId)) { resultSetCount--; return std::make_pair(E_RESULTSET_BUSY, nullptr); @@ -226,7 +254,7 @@ std::pair> RdbDelegate::Query(const std if (resultSet == nullptr) { RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_CALL_RDB, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::QUERY_RDB_ERROR); - ZLOGE("Query failed %{public}s, pid: %{public}d", tableName.c_str(), callingPid); + ZLOGE("Query failed %{public}s, pid: %{public}d", StringUtils::GeneralAnonymous(tableName).c_str(), callingPid); resultSetCount--; return std::make_pair(E_ERROR, nullptr); } @@ -240,14 +268,15 @@ std::pair> RdbDelegate::Query(const std ++value; return true; }); - int64_t beginTime = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count(); + int64_t beginTime = GetSystemTime(); auto bridge = RdbDataShareAdapter::RdbUtils::ToResultSetBridge(resultSet); - std::shared_ptr result = { new DataShareResultSet(bridge), [callingPid, beginTime](auto p) { - ZLOGD_MACRO("release resultset"); + auto resultSetPtr = new (std::nothrow) DataShareResultSet(bridge); + if (resultSetPtr == nullptr) { + return std::make_pair(E_ERROR, nullptr); + } + auto result = std::shared_ptr(resultSetPtr, [callingPid, beginTime](auto p) { resultSetCount--; - int64_t endTime = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count(); + int64_t endTime = GetSystemTime(); if (endTime - beginTime > TIMEOUT_TIME) { ZLOGE("pid %{public}d query time is %{public}" PRId64 ", %{public}d resultSet is used.", callingPid, (endTime - beginTime), resultSetCount.load()); @@ -257,7 +286,7 @@ std::pair> RdbDelegate::Query(const std return value > 0; }); delete p; - }}; + }); return std::make_pair(E_OK, result); } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.h b/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.h index d7c3eeda..9c8fcd7d 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.h @@ -24,16 +24,17 @@ #include "rdb_errno.h" #include "rdb_helper.h" #include "rdb_store.h" -#include "uri_utils.h" +#include "utils.h" #include "rdb_utils.h" namespace OHOS::DataShare { using namespace OHOS::NativeRdb; class RdbDelegate final : public DBDelegate { public: - explicit RdbDelegate(const DistributedData::StoreMetaData &meta, int version, - bool registerFunction, const std::string &extUri, const std::string &backup); + explicit RdbDelegate(); ~RdbDelegate(); + bool Init(const DistributedData::StoreMetaData &meta, int version, + bool registerFunction, const std::string &extUri, const std::string &backup) override; std::pair> Query(const std::string &tableName, const DataSharePredicates &predicates, const std::vector &columns, int32_t callingPid, uint32_t callingTokenId) override; @@ -59,13 +60,15 @@ private: static constexpr int RETRY = 3; static constexpr const char *DUAL_WRITE = "dualWrite"; static constexpr const char *PERIODIC = "periodic"; - uint32_t tokenId_; - std::string bundleName_; - std::string storeName_; - int32_t haMode_; - std::string extUri_; - std::string backup_; - std::string user_; + uint32_t tokenId_ = 0; + std::string bundleName_ = ""; + std::string storeName_ = ""; + int32_t haMode_ = 0; + std::string extUri_ = ""; + std::string backup_ = ""; + std::string user_ = ""; + std::mutex initMutex_; + bool isInited_ = false; }; class DefaultOpenCallback : public RdbOpenCallback { public: diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.cpp index 79ca8015..fa7ec6a9 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.cpp @@ -20,7 +20,7 @@ #include "log_print.h" #include "timer_info.h" -#include "uri_utils.h" +#include "utils.h" #include "utils/anonymous.h" #include "log_debug.h" @@ -41,7 +41,7 @@ void SchedulerManager::Execute(const std::string &uri, const int32_t userId, Dis metaData.user = std::to_string(userId); auto delegate = DBDelegate::Create(metaData); if (delegate == nullptr) { - ZLOGE("malloc fail %{public}s", DistributedData::Anonymous::Change(uri).c_str()); + ZLOGE("malloc fail %{public}s", URIUtils::Anonymous(uri).c_str()); return; } std::vector keys = RdbSubscriberManager::GetInstance().GetKeysByUri(uri); @@ -57,7 +57,7 @@ void SchedulerManager::Execute(const Key &key, const int32_t userId, const Distr meta.user = std::to_string(userId); auto delegate = DBDelegate::Create(meta); if (delegate == nullptr) { - ZLOGE("malloc fail %{public}s", DistributedData::Anonymous::Change(key.uri).c_str()); + ZLOGE("malloc fail %{public}s", URIUtils::Anonymous(key.uri).c_str()); return; } ExecuteSchedulerSQL(userId, meta, key, delegate); @@ -87,12 +87,22 @@ void SchedulerManager::Stop(const Key &key) void SchedulerManager::Enable(const Key &key, int32_t userId, const DistributedData::StoreMetaData &metaData) { + Template tpl; + if (!TemplateManager::GetInstance().Get(key, userId, tpl) || + tpl.scheduler_.empty() || tpl.scheduler_.find(REMIND_TIMER_FUNC) == std::string::npos) { + ZLOGE("find template scheduler failed, %{public}s, %{public}" PRId64 ", %{public}s", + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); + return; + } bool isTimerStopped = false; { std::lock_guard lock(mutex_); auto it = schedulerStatusCache_.find(key); if (it != schedulerStatusCache_.end()) { it->second = true; + } else { + ZLOGW("enable key not found, %{public}s, %{public}" PRId64 ", %{public}s", + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); } auto timer = timerCache_.find(key); if (timer == timerCache_.end()) { @@ -111,6 +121,9 @@ void SchedulerManager::Disable(const Key &key) auto it = schedulerStatusCache_.find(key); if (it != schedulerStatusCache_.end()) { it->second = false; + } else { + ZLOGW("disable key not found, %{public}s, %{public}" PRId64 ", %{public}s", + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); } } @@ -160,9 +173,18 @@ bool SchedulerManager::GetSchedulerStatus(const Key &key) { bool enabled = false; std::lock_guard lock(mutex_); + uint32_t lastSize = lastStatusCacheSize_; + uint32_t nowSize = schedulerStatusCache_.size(); + if (nowSize != lastSize) { + lastStatusCacheSize_ = nowSize; + ZLOGI("size changed last %{public}d, now %{public}d", lastSize, nowSize); + } auto it = schedulerStatusCache_.find(key); if (it != schedulerStatusCache_.end()) { enabled = it->second; + } else { + ZLOGW("key not found, %{public}s, %{public}" PRId64 ", %{public}s", + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); } return enabled; } @@ -188,14 +210,14 @@ void SchedulerManager::SetTimer( auto it = timerCache_.find(key); if (it != timerCache_.end()) { ZLOGD_MACRO("has current taskId: %{private}s, subscriberId is %{public}" PRId64 ", bundleName is %{public}s", - DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); auto timerId = it->second; ResetTimerTask(timerId, reminderTime); return; } auto callback = [key, metaData, userId, this]() { ZLOGI("schedule notify start, uri is %{private}s, subscriberId is %{public}" PRId64 ", bundleName is " - "%{public}s", DistributedData::Anonymous::Change(key.uri).c_str(), + "%{public}s", URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); int64_t timerId = EraseTimerTaskId(key); DestoryTimerTask(timerId); @@ -210,7 +232,7 @@ void SchedulerManager::SetTimer( return; } ZLOGI("create new task success, uri is %{public}s, subscriberId is %{public}" PRId64 ", bundleName is %{public}s", - DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); timerCache_.emplace(key, timerId); } @@ -220,19 +242,19 @@ void SchedulerManager::ExecuteSchedulerSQL(const int32_t userId, DistributedData Template tpl; if (!TemplateManager::GetInstance().Get(key, userId, tpl)) { ZLOGE("template undefined, %{public}s, %{public}" PRId64 ", %{public}s", - DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); return; } if (tpl.scheduler_.empty()) { ZLOGW("template scheduler_ empty, %{public}s, %{public}" PRId64 ", %{public}s", - DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); return; } GenRemindTimerFuncParams(userId, metaData, key, tpl.scheduler_); auto resultSet = delegate->QuerySql(tpl.scheduler_); if (resultSet == nullptr) { ZLOGE("resultSet is nullptr, %{public}s, %{public}" PRId64 ", %{public}s", - DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); return; } int count; @@ -240,7 +262,7 @@ void SchedulerManager::ExecuteSchedulerSQL(const int32_t userId, DistributedData if (errCode != E_OK || count == 0) { ZLOGE("GetRowCount error, %{public}s, %{public}" PRId64 ", %{public}s, errorCode is %{public}d, count is " "%{public}d", - DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str(), errCode, + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str(), errCode, count); return; } @@ -251,7 +273,7 @@ void SchedulerManager::GenRemindTimerFuncParams( { auto index = schedulerSQL.find(REMIND_TIMER_FUNC); if (index == std::string::npos) { - ZLOGW("not find remindTimer, sql is %{public}s", schedulerSQL.c_str()); + ZLOGW("not find remindTimer, sql is %{public}s", URIUtils::Anonymous(schedulerSQL).c_str()); return; } index += REMIND_TIMER_FUNC_LEN; @@ -271,7 +293,7 @@ void SchedulerManager::RemoveTimer(const Key &key) auto it = timerCache_.find(key); if (it != timerCache_.end()) { ZLOGW("RemoveTimer %{public}s %{public}s %{public}" PRId64, - DistributedData::Anonymous::Change(key.uri).c_str(), key.bundleName.c_str(), key.subscriberId); + URIUtils::Anonymous(key.uri).c_str(), key.bundleName.c_str(), key.subscriberId); DestoryTimerTask(it->second); timerCache_.erase(key); } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.h b/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.h index 934f3975..16555197 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.h @@ -41,6 +41,7 @@ public: private: static constexpr const char *REMIND_TIMER_FUNC = "remindTimer("; static constexpr int REMIND_TIMER_FUNC_LEN = 12; + uint32_t lastStatusCacheSize_ = 0; SchedulerManager() = default; ~SchedulerManager() = default; static void GenRemindTimerFuncParams(const int32_t userId, DistributedData::StoreMetaData &metaData, const Key &key, diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/utils.cpp similarity index 86% rename from datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.cpp rename to datamgr_service/services/distributeddataservice/service/data_share/common/utils.cpp index 1953824c..6f30af21 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/utils.cpp @@ -12,9 +12,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define LOG_TAG "URIUtils" +#define LOG_TAG "Utils" -#include "uri_utils.h" +#include "utils.h" #include @@ -24,6 +24,10 @@ #include "utils/anonymous.h" namespace OHOS::DataShare { +// Size of the characters that need to be left for both head and tail. +constexpr int32_t REVEAL_SIZE = 4; +constexpr const char *REPLACE_CHAIN = "***"; +constexpr const char *DEFAULT_ANONYMOUS = "******"; bool URIUtils::GetInfoFromURI(const std::string &uri, UriInfo &uriInfo) { Uri uriTemp(uri); @@ -36,7 +40,7 @@ bool URIUtils::GetInfoFromURI(const std::string &uri, UriInfo &uriInfo) if (splitUri[BUNDLE_NAME].empty() || splitUri[MODULE_NAME].empty() || splitUri[STORE_NAME].empty() || splitUri[TABLE_NAME].empty()) { ZLOGE("Uri has empty field! bundleName: %{public}s uri: %{public}s", splitUri[BUNDLE_NAME].c_str(), - DistributedData::Anonymous::Change(uri).c_str()); + URIUtils::Anonymous(uri).c_str()); return false; } @@ -147,7 +151,7 @@ std::pair URIUtils::Strtoul(const std::string &str) } char* end = nullptr; errno = 0; - data = strtoul(str.c_str(), &end, 10); + data = strtoul(str.c_str(), &end, END_LENGTH); if (errno == ERANGE || end == nullptr || end == str || *end != '\0') { return std::make_pair(false, data); } @@ -180,4 +184,20 @@ std::map URIUtils::GetQueryParams(const std::string& u } return params; } + +std::string StringUtils::GeneralAnonymous(const std::string &name) +{ + // To short to be partial anonymized + if (name.length() <= REVEAL_SIZE) { + return DEFAULT_ANONYMOUS; + } + + // only leave HEAD + if (name.length() <= (REVEAL_SIZE + REVEAL_SIZE)) { + return (name.substr(0, REVEAL_SIZE) + REPLACE_CHAIN); + } + // leave 4 char at head and tail respectively + return (name.substr(0, REVEAL_SIZE) + REPLACE_CHAIN + name.substr(name.length() - REVEAL_SIZE, REVEAL_SIZE)); +} + } // namespace OHOS::DataShare \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.h b/datamgr_service/services/distributeddataservice/service/data_share/common/utils.h similarity index 78% rename from datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.h rename to datamgr_service/services/distributeddataservice/service/data_share/common/utils.h index 8f229850..de55c6b0 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/utils.h @@ -35,6 +35,24 @@ struct UriConfig { std::string scheme; }; +class StringUtils { +public: + /** + * @brief Anonymizes the input string by preserving specified length at head/tail + * and replacing the middle part with placeholder + * @param name Original string to be processed (non-empty assumed) + * @return std::string Anonymized result according to length rules: + * 1. Length <= 4: Returns DEFAULT_ANONYMOUS ("******") + * 2. 4 < Length <= 8: Returns first 4 chars + REPLACE_CHAIN ("***") + * 3. Length > 8: Returns first 4 chars + REPLACE_CHAIN + last 4 chars + * @example + * "abcdefghi" -> "abcd***fghi" + * "12345" -> "1234***" + * "AB" -> "******" + */ + static std::string GeneralAnonymous(const std::string &name); +}; + class URIUtils { public: static bool GetInfoFromURI(const std::string &uri, UriInfo &uriInfo); @@ -67,7 +85,6 @@ private: PARAM_SIZE }; static constexpr int32_t END_LENGTH = 10; - static constexpr const char *DEFAULT_ANONYMOUS = "******"; }; } // namespace OHOS::DataShare #endif // DATASHARESERVICE_URI_UTILS_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data/published_data.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data/published_data.cpp index 0e73d871..d8c6960a 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data/published_data.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data/published_data.cpp @@ -18,6 +18,7 @@ #include "log_print.h" #include "subscriber_managers/published_data_subscriber_manager.h" #include "utils/base64_utils.h" +#include "utils.h" namespace OHOS::DataShare { bool PublishedData::HasVersion() const @@ -151,7 +152,7 @@ int32_t PublishedData::Query(const std::string &filter, PublishedDataNode::Data } PublishedDataNode data; if (!PublishedDataNode::Unmarshall(queryResult, data)) { - ZLOGE("Unmarshall failed, %{private}s", queryResult.c_str()); + ZLOGE("Unmarshall failed, %{public}s", StringUtils::GeneralAnonymous(queryResult).c_str()); return E_ERROR; } publishedData = std::move(data.value); @@ -170,7 +171,7 @@ void PublishedData::Delete(const std::string &bundleName, const int32_t userId) ZLOGE("db open failed"); return; } - auto [status, count] = delegate->Delete(KvDBDelegate::DATA_TABLE, + auto [status, count] = delegate->Delete(KvDBDelegate::DATA_TABLE, "{\"bundleName\":\"" + bundleName + "\", \"userId\": " + std::to_string(userId) + "}"); if (status != E_OK) { ZLOGE("db Delete failed, %{public}s %{public}d", bundleName.c_str(), status); @@ -209,9 +210,9 @@ void PublishedData::ClearAging() } if (data.timestamp < lastValidTime && PublishedDataSubscriberManager::GetInstance() .GetCount(PublishedDataKey(data.key, data.bundleName, data.subscriberId)) == 0) { - auto [errorCode, count] = delegate->Delete(KvDBDelegate::DATA_TABLE, + auto [errorCode, count] = delegate->Delete(KvDBDelegate::DATA_TABLE, Id(PublishedData::GenId(data.key, data.bundleName, data.subscriberId), data.userId)); - if (errorCode != E_OK) { + if (errorCode != E_OK) { ZLOGE("db Delete failed, %{public}s %{public}s", data.key.c_str(), data.bundleName.c_str()); } agingSize++; @@ -235,12 +236,12 @@ void PublishedData::UpdateTimestamp( int32_t status = delegate->Get(KvDBDelegate::DATA_TABLE, Id(GenId(key, bundleName, subscriberId), userId), queryResult); if (status != E_OK) { - ZLOGE("db Get failed, %{private}s %{public}d", queryResult.c_str(), status); + ZLOGE("db Get failed, %{public}s %{public}d", StringUtils::GeneralAnonymous(queryResult).c_str(), status); return; } PublishedDataNode data; if (!PublishedDataNode::Unmarshall(queryResult, data)) { - ZLOGE("Unmarshall failed, %{private}s", queryResult.c_str()); + ZLOGE("Unmarshall failed, %{public}s", StringUtils::GeneralAnonymous(queryResult).c_str()); return; } auto now = time(nullptr); @@ -249,9 +250,9 @@ void PublishedData::UpdateTimestamp( return; } data.timestamp = now; - auto [errorCode, count] = delegate->Upsert(KvDBDelegate::DATA_TABLE, PublishedData(data)); - if (errorCode == E_OK) { - ZLOGI("update timestamp %{private}s", data.key.c_str()); + auto [errorCode, count] = delegate->Upsert(KvDBDelegate::DATA_TABLE, PublishedData(data)); + if (errorCode == E_OK) { + ZLOGI("update timestamp %{public}s", StringUtils::GeneralAnonymous(data.key).c_str()); } } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.cpp index e713b4ac..f6f13b3d 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.cpp @@ -20,11 +20,14 @@ #include "accesstoken_kit.h" #include "account/account_delegate.h" +#include "config_factory.h" #include "datashare_errno.h" #include "hap_token_info.h" +#include "ipc_skeleton.h" #include "log_print.h" #include "strategies/general/load_config_common_strategy.h" -#include "uri_utils.h" +#include "tokenid_kit.h" +#include "utils.h" #include "utils/anonymous.h" namespace OHOS::DataShare { @@ -39,6 +42,12 @@ DataProviderConfig::DataProviderConfig(const std::string &uri, uint32_t callerTo LoadConfigCommonStrategy::GetInfoFromProxyURI(providerInfo_.uri, providerInfo_.visitedUserId, callerTokenId, providerInfo_.bundleName); URIUtils::FormatUri(providerInfo_.uri); + // if visitedUserId is 0, set current foreground userId as visitedUserId + if (providerInfo_.visitedUserId == 0) { + if (!(AccountDelegate::GetInstance()->QueryForegroundUserId(providerInfo_.visitedUserId))) { + ZLOGE("Get foreground userId failed"); + } + } } else { auto [success, data] = URIUtils::GetUserFromProxyURI(providerInfo_.uri); if (success) { @@ -61,7 +70,7 @@ std::pair DataProviderConfig::GetBundleInfo() } providerInfo_.bundleName = uriConfig_.pathSegments[0]; } - auto ret = BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( + auto ret = BundleMgrProxy::GetInstance()->GetBundleInfoFromBMSWithCheck( providerInfo_.bundleName, providerInfo_.visitedUserId, bundleInfo, providerInfo_.appIndex); return std::make_pair(ret, bundleInfo); } @@ -155,7 +164,7 @@ int DataProviderConfig::GetFromExtension() return E_URI_NOT_EXIST; } BundleConfig bundleInfo; - auto ret = BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( + auto ret = BundleMgrProxy::GetInstance()->GetBundleInfoFromBMSWithCheck( providerInfo_.bundleName, providerInfo_.visitedUserId, bundleInfo, providerInfo_.appIndex); if (ret != E_OK) { ZLOGE("BundleInfo failed! bundleName: %{public}s", providerInfo_.bundleName.c_str()); @@ -225,6 +234,17 @@ std::pair DataProviderConfig::GetProvider GetMetaDataFromUri(); return std::make_pair(ret, providerInfo_); } + if (ret != E_URI_NOT_EXIST) { + return std::make_pair(ret, providerInfo_); + } + auto fullTokenId = IPCSkeleton::GetCallingFullTokenID(); + Security::AccessToken::HapTokenInfo tokenInfo; + auto result = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(IPCSkeleton::GetCallingTokenID(), tokenInfo); + if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId) + || (result == Security::AccessToken::RET_SUCCESS && !IsInExtList(tokenInfo.bundleName))) { + ZLOGE("The URI in the extension, is not allowed for silent access.! ret: %{public}d, bundleName: %{public}s," + "uri: %{public}s", ret, tokenInfo.bundleName.c_str(), URIUtils::Anonymous(providerInfo_.uri).c_str()); + } ret = GetFromExtension(); if (ret != E_OK) { ZLOGE("Get providerInfo failed! ret: %{public}d, uri: %{public}s", @@ -232,4 +252,14 @@ std::pair DataProviderConfig::GetProvider } return std::make_pair(ret, providerInfo_); } + +bool DataProviderConfig::IsInExtList(const std::string &bundleName) +{ + DataShareConfig *config = ConfigFactory::GetInstance().GetDataShareConfig(); + if (config == nullptr) { + return true; + } + std::vector& extNames = config->dataShareExtNames; + return std::find(extNames.begin(), extNames.end(), bundleName) != extNames.end(); +} } // namespace OHOS::DataShare diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.h b/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.h index 95d1c1ca..c1acce43 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.h @@ -18,12 +18,11 @@ #include #include -#include "common/bundle_mgr_proxy.h" #include "account/account_delegate.h" #include "bundle_mgr_proxy.h" #include "data_share_profile_config.h" #include "hap_module_info.h" -#include "uri_utils.h" +#include "utils.h" namespace OHOS::DataShare { using ExtensionAbility = OHOS::AppExecFwk::ExtensionAbilityInfo; @@ -64,6 +63,7 @@ private: int GetFromExtensionProperties(const ProfileInfo &profileInfo, const std::string &moduleName); void GetMetaDataFromUri(); std::pair GetBundleInfo(); + bool IsInExtList(const std::string &bundleName); enum class PATH_PARAM : int32_t { BUNDLE_NAME = 0, MODULE_NAME, diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_proxy_observer.h b/datamgr_service/services/distributeddataservice/service/data_share/data_proxy_observer.h index 10a71f53..3c361f36 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_proxy_observer.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_proxy_observer.h @@ -18,6 +18,7 @@ #include #include "datashare_template.h" +#include "dataproxy_handle_common.h" namespace OHOS { namespace DataShare { @@ -32,6 +33,12 @@ public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DataShare.IDataProxyPublishedDataObserver"); virtual void OnChangeFromPublishedData(PublishedDataChangeNode &changeNode) = 0; }; + +class IProxyDataObserver : public OHOS::IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DataShare.IProxyDataObserver"); + virtual void OnChangeFromProxyData(std::vector &changeNode) = 0; +}; } // namespace DataShare } // namespace OHOS #endif // DATA_PROXY_OBSERVER_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.cpp index 544f887f..dc25bcaf 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.cpp @@ -25,7 +25,8 @@ #include "extension_connect_adaptor.h" #include "log_print.h" #include "metadata/meta_data_manager.h" -#include "uri_utils.h" +#include "metadata/store_meta_data.h" +#include "utils.h" #include "utils/anonymous.h" #include "ipc_skeleton.h" @@ -34,17 +35,18 @@ std::pair DataShareDbConfig::QueryMetaData const std::string &bundleName, const std::string &storeName, int32_t userId, int32_t appIndex) { TimeoutReport timeoutReport({bundleName, "", storeName, __FUNCTION__, 0}); - DistributedData::StoreMetaData meta; - meta.deviceId = DistributedData::DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; - meta.user = std::to_string(userId); - meta.bundleName = bundleName; - meta.storeId = storeName; - meta.instanceId = appIndex; - DistributedData::StoreMetaData metaData; - bool isCreated = DistributedData::MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), metaData, true); + DistributedData::StoreMetaMapping storeMetaMapping; + storeMetaMapping.deviceId = DistributedData::DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + storeMetaMapping.user = std::to_string(userId); + storeMetaMapping.bundleName = bundleName; + storeMetaMapping.storeId = storeName; + storeMetaMapping.instanceId = appIndex; + bool isCreated = + DistributedData::MetaDataManager::GetInstance().LoadMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); + auto callingPid = IPCSkeleton::GetCallingPid(); timeoutReport.Report(std::to_string(userId), callingPid, appIndex); - return std::make_pair(isCreated, metaData); + return std::make_pair(isCreated, storeMetaMapping); } std::pair DataShareDbConfig::GetMetaData(const DbConfig &dbConfig) @@ -72,8 +74,8 @@ std::tuple> Dat auto [errCode, metaData] = GetMetaData(dbConfig); if (errCode != E_OK) { ZLOGE("DB not exist,bundleName:%{public}s,storeName:%{public}s,user:%{public}d,err:%{public}d,uri:%{public}s", - dbConfig.bundleName.c_str(), dbConfig.storeName.c_str(), dbConfig.userId, errCode, - URIUtils::Anonymous(dbConfig.uri).c_str()); + dbConfig.bundleName.c_str(), StringUtils::GeneralAnonymous(dbConfig.storeName).c_str(), dbConfig.userId, + errCode, URIUtils::Anonymous(dbConfig.uri).c_str()); RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::PROXY_MATEDATA_EXISTS, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::META_DATA_NOT_EXISTS); return std::make_tuple(errCode, metaData, nullptr); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.h b/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.h index 88efe930..ff4e32b9 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.h @@ -23,7 +23,7 @@ #include "db_delegate.h" #include "extension_ability_info.h" #include "metadata/store_meta_data.h" -#include "uri_utils.h" +#include "utils.h" namespace OHOS::DataShare { class DataShareDbConfig { diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_obs_proxy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_obs_proxy.cpp index f63090f1..db021d14 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_obs_proxy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_obs_proxy.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "ObserverProxy" #include "data_share_obs_proxy.h" #include "datashare_errno.h" +#include "dataproxy_handle_common.h" #include "itypes_util.h" #include "datashare_itypes_utils.h" @@ -45,10 +46,7 @@ int RdbObserverProxy::CreateAshmem(RdbChangeNode &changeNode) return E_ERROR; } if (changeNode.memory_ != nullptr) { - ZLOGE( - "Unknown error: changeNode.memory_ should be null, but something is there %{public}p", - (void *)changeNode.memory_ - ); + ZLOGE("Unknown error: changeNode.memory_ should be null, but something is there."); return E_ERROR; } changeNode.memory_ = memory; @@ -201,6 +199,28 @@ void PublishedDataObserverProxy::OnChangeFromPublishedData(PublishedDataChangeNo return; } + MessageParcel reply; + MessageOption option; + int32_t result = Remote()->SendRequest(REQUEST_CODE, parcel, reply, option); + if (result != ERR_NONE) { + ZLOGE("SendRequest error, result=%{public}d", result); + return; + } + ZLOGD("SendRequest ok, retval is %{public}d", reply.ReadInt32()); +} + +void ProxyDataObserverProxy::OnChangeFromProxyData(std::vector &changeInfo) +{ + MessageParcel parcel; + if (!parcel.WriteInterfaceToken(PublishedDataObserverProxy::GetDescriptor())) { + return; + } + + if (!ITypesUtil::Marshal(parcel, changeInfo)) { + ZLOGE("failed to WriteParcelable changeNode "); + return; + } + MessageParcel reply; MessageOption option; int32_t result = Remote()->SendRequest(REQUEST_CODE, parcel, reply, option); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_obs_proxy.h b/datamgr_service/services/distributeddataservice/service/data_share/data_share_obs_proxy.h index c6726d59..81846c1c 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_obs_proxy.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_obs_proxy.h @@ -45,5 +45,16 @@ public: private: static inline BrokerDelegator delegator_; }; + +class ProxyDataObserverProxy : public IRemoteProxy { +public: + explicit ProxyDataObserverProxy(const sptr& remote) + : IRemoteProxy(remote) {} + virtual ~ProxyDataObserverProxy() {} + void OnChangeFromProxyData(std::vector &changeNode) override; + +private: + static inline BrokerDelegator delegator_; +}; } // namespace OHOS::DataShare #endif // DATA_SHARE_OBS_PROXY_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.cpp index 9787d9df..de4a8f65 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.cpp @@ -26,7 +26,7 @@ #include "bundle_mgr_proxy.h" #include "datashare_errno.h" #include "log_print.h" -#include "uri_utils.h" +#include "utils.h" #include "utils/anonymous.h" #include "log_debug.h" @@ -36,6 +36,7 @@ constexpr const char *PROFILE_FILE_PREFIX = "$profile:"; constexpr const char *SEPARATOR = "/"; static constexpr int PATH_SIZE = 2; static constexpr int MAX_ALLOWLIST_COUNT = 256; +static constexpr size_t MAX_FILE_SIZE = 10 * 1024 * 1024; const size_t PROFILE_PREFIX_LEN = strlen(PROFILE_FILE_PREFIX); bool Config::Marshal(json &node) const { @@ -134,6 +135,40 @@ bool ProfileInfo::Unmarshal(const json &node) return true; } +bool SerialDataShareProxyData::Marshal(json &node) const +{ + SetValue(node[GET_NAME(uri)], uri); + SetValue(node[GET_NAME(value)], value); + SetValue(node[GET_NAME(allowList)], allowList); + return true; +} + +bool SerialDataShareProxyData::Unmarshal(const json &node) +{ + bool ret = GetValue(node, GET_NAME(uri), uri); + // the value in profile can only be string, but the type of value which is published is variant, + // use type variant to unmarshal a string will fail, so use a string to try unmarshal again + if (!GetValue(node, GET_NAME(value), value)) { + std::string valueStr; + GetValue(node, GET_NAME(value), valueStr); + value = valueStr; + } + GetValue(node, GET_NAME(allowList), allowList); + return ret; +} + +bool ProxyDataProfileInfo::Marshal(json &node) const +{ + SetValue(node[GET_NAME(crossAppSharedConfig)], dataShareProxyDatas); + return true; +} + +bool ProxyDataProfileInfo::Unmarshal(const json &node) +{ + bool ret = GetValue(node, GET_NAME(crossAppSharedConfig), dataShareProxyDatas); + return ret; +} + std::pair DataShareProfileConfig::GetDataProperties( const std::vector &metadata, const std::string &resPath, const std::string &hapPath, const std::string &name) @@ -150,6 +185,27 @@ std::pair DataShareProfileConfig::GetDataProperties( return std::make_pair(SUCCESS, profileInfo); } +std::pair> DataShareProfileConfig::GetCrossAppSharedConfig( + const std::string &resource, const std::string &resPath, const std::string &hapPath) +{ + std::vector serialProxyDatas; + ProxyDataProfileInfo profileInfo; + std::string resourcePath = !hapPath.empty() ? hapPath : resPath; + + std::shared_ptr resMgr = InitResMgr(resourcePath); + if (resMgr == nullptr) { + return std::make_pair(ERROR, serialProxyDatas); + } + std::string info = GetResFromResMgr(resource, *resMgr, hapPath); + if (info.empty()) { + return std::make_pair(NOT_FOUND, serialProxyDatas); + } + if (!profileInfo.Unmarshall(info)) { + return std::make_pair(ERROR, serialProxyDatas); + } + return std::make_pair(SUCCESS, profileInfo.dataShareProxyDatas); +} + std::string DataShareProfileConfig::GetProfileInfoByMetadata(const std::vector &metadata, const std::string &resourcePath, const std::string &hapPath, const std::string &name) { @@ -173,7 +229,7 @@ std::string DataShareProfileConfig::GetProfileInfoByMetadata(const std::vector DataShareProfileConfig::InitResMgr(const std::string &resourcePath) { - std::shared_ptr resMgr(CreateResourceManager()); + std::shared_ptr resMgr(CreateResourceManager(false)); if (resMgr == nullptr) { return nullptr; } @@ -207,7 +263,7 @@ std::string DataShareProfileConfig::GetResFromResMgr( std::unique_ptr fileContent = nullptr; size_t len = 0; RState ret = resMgr.GetProfileDataByName(profileName.c_str(), len, fileContent); - if (ret != SUCCESS || fileContent == nullptr) { + if (ret != RState::SUCCESS || fileContent == nullptr) { ZLOGE("failed, ret is %{public}d, profileName is %{public}s", ret, profileName.c_str()); return profileInfo; } @@ -225,13 +281,14 @@ std::string DataShareProfileConfig::GetResFromResMgr( // hap is decompressed status, get file path then read file. std::string resPath; RState ret = resMgr.GetProfileByName(profileName.c_str(), resPath); - if (ret != SUCCESS) { - ZLOGE("profileName not found, ret is %{public}d, profileName is %{public}s", ret, profileName.c_str()); + if (ret != RState::SUCCESS) { + ZLOGE("profileName not found, ret is %{public}d, profileName is %{public}s", ret, + StringUtils::GeneralAnonymous(profileName).c_str()); return profileInfo; } std::string profile = ReadProfile(resPath); if (profile.empty()) { - ZLOGE("Read profile failed, resPath is %{public}s", resPath.c_str()); + ZLOGE("Read profile failed, resPath is %{public}s", URIUtils::Anonymous(resPath).c_str()); return profileInfo; } return profile; @@ -243,7 +300,8 @@ bool DataShareProfileConfig::IsFileExisted(const std::string &filePath) return false; } if (access(filePath.c_str(), F_OK) != 0) { - ZLOGE("can not access file, errno is %{public}d, filePath is %{public}s", errno, filePath.c_str()); + ZLOGE("can not access file, errno is %{public}d, filePath is %{public}s", errno, + URIUtils::Anonymous(filePath).c_str()); return false; } return true; @@ -264,7 +322,10 @@ std::string DataShareProfileConfig::ReadProfile(const std::string &resPath) tmp << in.rdbuf(); std::string content = tmp.str(); if (content.empty()) { - ZLOGE("the file is empty, resPath is %{public}s", resPath.c_str()); + ZLOGE("the file is empty, resPath is %{public}s", URIUtils::Anonymous(resPath).c_str()); + return ""; + } else if (content.length() > MAX_FILE_SIZE) { + ZLOGE("the file is too large, resPath is %{public}s,", URIUtils::Anonymous(resPath).c_str()); return ""; } return content; @@ -275,9 +336,9 @@ bool DataShareProfileConfig::GetProfileInfo(const std::string &calledBundleName, { BundleConfig bundleInfo; // profile is the same when app clone - if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS(calledBundleName, + if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMSWithCheck(calledBundleName, currentUserId, bundleInfo) != E_OK) { - ZLOGE("data share GetBundleInfoFromBMS failed! bundleName: %{public}s, currentUserId = %{public}d", + ZLOGE("data share GetBundleInfoFromBMSWithCheck failed! bundleName: %{public}s, currentUserId = %{public}d", calledBundleName.c_str(), currentUserId); return false; } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.h b/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.h index 781cd5f3..7f7d0445 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.h @@ -22,6 +22,7 @@ #include #include "bundle_info.h" +#include "dataproxy_handle_common.h" #include "resource_manager.h" #include "serializable/serializable.h" @@ -68,6 +69,25 @@ struct ProfileInfo : public DistributedData::Serializable { bool Unmarshal(const json &node) override; }; +struct SerialDataShareProxyData : public DistributedData::Serializable { + SerialDataShareProxyData() = default; + SerialDataShareProxyData(const std::string &uri, const DataProxyValue &value, + const std::vector &allowList) + : uri(uri), value(value), allowList(allowList) {} + virtual ~SerialDataShareProxyData() = default; + std::string uri; + DataProxyValue value; + std::vector allowList; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; +}; + +struct ProxyDataProfileInfo : public DistributedData::Serializable { + std::vector dataShareProxyDatas; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; +}; + enum AccessCrossMode : uint8_t { USER_UNDEFINED, USER_SHARED, @@ -86,6 +106,8 @@ public: std::map &profileInfos); static std::pair GetDataProperties(const std::vector &metadata, const std::string &resPath, const std::string &hapPath, const std::string &name); + static std::pair> GetCrossAppSharedConfig(const std::string &resource, + const std::string &resPath, const std::string &hapPath); static AccessCrossMode GetAccessCrossMode(const ProfileInfo &profileInfo, const std::string &tableUri, const std::string &storeUri); private: diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp index 02b2ce85..0b3e7c81 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp @@ -24,6 +24,8 @@ #include "app_connect_manager.h" #include "common_event_manager.h" #include "common_event_support.h" +#include "concurrent_task_client.h" +#include "config_factory.h" #include "data_ability_observer_interface.h" #include "data_share_profile_config.h" #include "dataobs_mgr_client.h" @@ -42,7 +44,7 @@ #include "ipc_skeleton.h" #include "iservice_registry.h" #include "log_print.h" -#include "common/uri_utils.h" +#include "common/utils.h" #include "metadata/auto_launch_meta_data.h" #include "metadata/meta_data_manager.h" #include "matching_skills.h" @@ -53,11 +55,16 @@ #include "sys_event_subscriber.h" #include "system_ability_definition.h" #include "system_ability_status_change_stub.h" +#include "task_executor.h" #include "template_data.h" #include "utils/anonymous.h" #include "xcollie.h" #include "log_debug.h" #include "parameters.h" +#include "dataproxy_handle_common.h" +#include "proxy_data_manager.h" +#include "datashare_observer.h" +#include "subscriber_managers/proxy_data_subscriber_manager.h" namespace OHOS::DataShare { using FeatureSystem = DistributedData::FeatureSystem; @@ -67,6 +74,7 @@ using namespace OHOS::DistributedData; __attribute__((used)) DataShareServiceImpl::Factory DataShareServiceImpl::factory_; // decimal base static constexpr int DECIMAL_BASE = 10; +DataShareServiceImpl::BindInfo DataShareServiceImpl::binderInfo_; class DataShareServiceImpl::SystemAbilityStatusChangeListener : public SystemAbilityStatusChangeStub { public: @@ -83,11 +91,17 @@ public: void DataShareServiceImpl::SystemAbilityStatusChangeListener::OnAddSystemAbility( int32_t systemAbilityId, const std::string &deviceId) { - if (systemAbilityId != COMMON_EVENT_SERVICE_ID) { - return; - } - ZLOGI("Common event service start. saId:%{public}d", systemAbilityId); - InitSubEvent(); + ZLOGI("saId:%{public}d", systemAbilityId); + if (systemAbilityId == COMMON_EVENT_SERVICE_ID) { + InitSubEvent(); + } else if (systemAbilityId == CONCURRENT_TASK_SERVICE_ID) { + std::unordered_map payload; + // get current thread pid + payload["pid"] = std::to_string(getpid()); + // request qos auth for current pid + OHOS::ConcurrentTask::ConcurrentTaskClient::GetInstance().RequestAuth(payload); + } + return; } DataShareServiceImpl::Factory::Factory() @@ -118,9 +132,10 @@ std::pair DataShareServiceImpl::InsertEx(const std::string &ur callingTokenId}, true); auto [errCode, ret] = dbDelegate->InsertEx(providerInfo.tableName, valuesBucket); if (errCode == E_OK && ret > 0) { - NotifyChange(uri); + NotifyChange(uri, providerInfo.visitedUserId); RdbSubscriberManager::GetInstance().Emit(uri, providerInfo.visitedUserId, metaData); - } else { + } + if (errCode != E_OK) { ReportExcuteFault(callingTokenId, providerInfo, errCode, func); } timeoutReport.Report(); @@ -129,7 +144,7 @@ std::pair DataShareServiceImpl::InsertEx(const std::string &ur return ExecuteEx(uri, extUri, IPCSkeleton::GetCallingTokenID(), false, callBack); } -bool DataShareServiceImpl::NotifyChange(const std::string &uri) +bool DataShareServiceImpl::NotifyChange(const std::string &uri, int32_t userId) { RadarReporter::RadarReport report(RadarReporter::NOTIFY_OBSERVER_DATA_CHANGE, RadarReporter::NOTIFY_DATA_CHANGE, __FUNCTION__); @@ -139,8 +154,7 @@ bool DataShareServiceImpl::NotifyChange(const std::string &uri) report.SetError(RadarReporter::DATA_OBS_EMPTY_ERROR); return false; } - - ErrCode ret = obsMgrClient->NotifyChange(Uri(uri)); + ErrCode ret = obsMgrClient->NotifyChange(Uri(uri), userId); if (ret != ERR_OK) { ZLOGE("obsMgrClient->NotifyChange error return %{public}d", ret); report.SetError(RadarReporter::NOTIFY_ERROR); @@ -166,9 +180,10 @@ std::pair DataShareServiceImpl::UpdateEx(const std::string &ur callingTokenId}, true); auto [errCode, ret] = dbDelegate->UpdateEx(providerInfo.tableName, predicate, valuesBucket); if (errCode == E_OK && ret > 0) { - NotifyChange(uri); + NotifyChange(uri, providerInfo.visitedUserId); RdbSubscriberManager::GetInstance().Emit(uri, providerInfo.visitedUserId, metaData); - } else { + } + if (errCode != E_OK) { ReportExcuteFault(callingTokenId, providerInfo, errCode, func); } timeoutReport.Report(); @@ -194,9 +209,10 @@ std::pair DataShareServiceImpl::DeleteEx(const std::string &ur callingTokenId}, true); auto [errCode, ret] = dbDelegate->DeleteEx(providerInfo.tableName, predicate); if (errCode == E_OK && ret > 0) { - NotifyChange(uri); + NotifyChange(uri, providerInfo.visitedUserId); RdbSubscriberManager::GetInstance().Emit(uri, providerInfo.visitedUserId, metaData); - } else { + } + if (errCode != E_OK) { ReportExcuteFault(callingTokenId, providerInfo, errCode, func); } timeoutReport.Report(); @@ -243,7 +259,7 @@ int32_t DataShareServiceImpl::AddTemplate(const std::string &uri, const int64_t TemplateId tpltId; tpltId.subscriberId_ = subscriberId; if (!GetCallerBundleName(tpltId.bundleName_)) { - ZLOGE("get bundleName error, %{public}s", DistributedData::Anonymous::Change(uri).c_str()); + ZLOGE("get bundleName error, %{public}s", URIUtils::Anonymous(uri).c_str()); return ERROR; } ZLOGI("Add template, uri %{private}s, subscriberId %{public}" PRIi64 ", bundleName %{public}s," @@ -251,7 +267,7 @@ int32_t DataShareServiceImpl::AddTemplate(const std::string &uri, const int64_t uri.c_str(), subscriberId, tpltId.bundleName_.c_str(), tplt.predicates_.size()); return templateStrategy_.Execute(context, [&uri, &tpltId, &tplt, &context]() -> int32_t { auto result = TemplateManager::GetInstance().Add( - Key(uri, tpltId.subscriberId_, tpltId.bundleName_), context->currentUserId, tplt); + Key(uri, tpltId.subscriberId_, tpltId.bundleName_), context->visitedUserId, tplt); RdbSubscriberManager::GetInstance().Emit(context->uri, tpltId.subscriberId_, tpltId.bundleName_, context); return result; }); @@ -263,14 +279,14 @@ int32_t DataShareServiceImpl::DelTemplate(const std::string &uri, const int64_t TemplateId tpltId; tpltId.subscriberId_ = subscriberId; if (!GetCallerBundleName(tpltId.bundleName_)) { - ZLOGE("get bundleName error, %{public}s", DistributedData::Anonymous::Change(uri).c_str()); + ZLOGE("get bundleName error, %{public}s", URIUtils::Anonymous(uri).c_str()); return ERROR; } ZLOGI("Delete template, uri %{private}s, subscriberId %{public}" PRIi64 ", bundleName %{public}s.", - DistributedData::Anonymous::Change(uri).c_str(), subscriberId, tpltId.bundleName_.c_str()); + URIUtils::Anonymous(uri).c_str(), subscriberId, tpltId.bundleName_.c_str()); return templateStrategy_.Execute(context, [&uri, &tpltId, &context]() -> int32_t { return TemplateManager::GetInstance().Delete( - Key(uri, tpltId.subscriberId_, tpltId.bundleName_), context->currentUserId); + Key(uri, tpltId.subscriberId_, tpltId.bundleName_), context->visitedUserId); }); } @@ -335,11 +351,11 @@ std::vector DataShareServiceImpl::Publish(const Data &data, con int32_t result = publishStrategy_.Execute(context, item); results.emplace_back(item.key_, result); if (result != E_OK) { - ZLOGE("publish error, key is %{public}s", DistributedData::Anonymous::Change(item.key_).c_str()); + ZLOGE("publish error, key is %{public}s", URIUtils::Anonymous(item.key_).c_str()); continue; } publishedData.emplace_back(context->uri, context->calledBundleName, item.subscriberId_); - userId = context->currentUserId; + userId = context->visitedUserId; } if (!publishedData.empty()) { PublishedDataSubscriberManager::GetInstance().Emit(publishedData, userId, callerBundleName); @@ -369,7 +385,8 @@ std::vector DataShareServiceImpl::SubscribeRdbData( auto context = std::make_shared(uri); results.emplace_back(uri, subscribeStrategy_.Execute(context, [&id, &observer, &context, this]() { return RdbSubscriberManager::GetInstance().Add( - Key(context->uri, id.subscriberId_, id.bundleName_), observer, context, binderInfo_.executors); + Key(context->uri, id.subscriberId_, id.bundleName_), + observer, context, binderInfo_.executors); })); } return results; @@ -437,7 +454,7 @@ std::vector DataShareServiceImpl::SubscribePublishedData(const result = subscribeStrategy_.Execute(context, [&subscriberId, &observer, &context]() { return PublishedDataSubscriberManager::GetInstance().Add( PublishedDataKey(context->uri, context->callerBundleName, subscriberId), observer, - context->callerTokenId); + context->callerTokenId, context->visitedUserId); }); results.emplace_back(uri, result); if (result == E_OK) { @@ -445,10 +462,10 @@ std::vector DataShareServiceImpl::SubscribePublishedData(const if (binderInfo_.executors != nullptr) { binderInfo_.executors->Execute([context, subscriberId]() { PublishedData::UpdateTimestamp( - context->uri, context->calledBundleName, subscriberId, context->currentUserId); + context->uri, context->calledBundleName, subscriberId, context->visitedUserId); }); } - userId = context->currentUserId; + userId = context->visitedUserId; } } if (!publishedKeys.empty()) { @@ -477,7 +494,7 @@ std::vector DataShareServiceImpl::UnsubscribePublishedData(cons if (result == E_OK && binderInfo_.executors != nullptr) { binderInfo_.executors->Execute([context, subscriberId]() { PublishedData::UpdateTimestamp( - context->uri, context->calledBundleName, subscriberId, context->currentUserId); + context->uri, context->calledBundleName, subscriberId, context->visitedUserId); }); } return result; @@ -510,7 +527,7 @@ std::vector DataShareServiceImpl::EnablePubSubs(const std::vect if (result == E_OK && binderInfo_.executors != nullptr) { binderInfo_.executors->Execute([context, subscriberId]() { PublishedData::UpdateTimestamp( - context->uri, context->calledBundleName, subscriberId, context->currentUserId); + context->uri, context->calledBundleName, subscriberId, context->visitedUserId); }); } results.emplace_back(uri, result); @@ -519,7 +536,7 @@ std::vector DataShareServiceImpl::EnablePubSubs(const std::vect if (PublishedDataSubscriberManager::GetInstance().IsNotifyOnEnabled(pKey, context->callerTokenId)) { publishedKeys.emplace_back(pKey); } - userId = context->currentUserId; + userId = context->visitedUserId; } } if (!publishedKeys.empty()) { @@ -548,7 +565,7 @@ std::vector DataShareServiceImpl::DisablePubSubs(const std::vec if (result == E_OK && binderInfo_.executors != nullptr) { binderInfo_.executors->Execute([context, subscriberId]() { PublishedData::UpdateTimestamp( - context->uri, context->calledBundleName, subscriberId, context->currentUserId); + context->uri, context->calledBundleName, subscriberId, context->visitedUserId); }); } return result; @@ -583,12 +600,14 @@ int32_t DataShareServiceImpl::OnBind(const BindInfo &binderInfo) saveMeta.uid = IPCSkeleton::GetCallingUid(); saveMeta.storeType = DATA_SHARE_SINGLE_VERSION; saveMeta.dataDir = DistributedData::DirectoryManager::GetInstance().GetStorePath(saveMeta); - KvDBDelegate::GetInstance(false, saveMeta.dataDir, binderInfo.executors); + KvDBDelegate::GetInstance(saveMeta.dataDir, binderInfo.executors); SchedulerManager::GetInstance().SetExecutorPool(binderInfo.executors); + NativeRdb::TaskExecutor::GetInstance().SetExecutor(binderInfo.executors); ExtensionAbilityManager::GetInstance().SetExecutorPool(binderInfo.executors); DBDelegate::SetExecutorPool(binderInfo.executors); HiViewAdapter::GetInstance().SetThreadPool(binderInfo.executors); SubscribeCommonEvent(); + SubscribeConcurrentTask(); SubscribeTimeChanged(); SubscribeChange(); ZLOGI("end"); @@ -602,10 +621,29 @@ void DataShareServiceImpl::SubscribeCommonEvent() ZLOGE("System mgr is nullptr"); return; } - sptr callback(new SystemAbilityStatusChangeListener()); + sptr callback(new (std::nothrow)SystemAbilityStatusChangeListener()); + if (callback == nullptr) { + ZLOGE("new SystemAbilityStatusChangeListener failed! no memory"); + return; + } systemManager->SubscribeSystemAbility(COMMON_EVENT_SERVICE_ID, callback); } +void DataShareServiceImpl::SubscribeConcurrentTask() +{ + sptr systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemManager == nullptr) { + ZLOGE("System mgr is nullptr"); + return; + } + sptr callback(new (std::nothrow)SystemAbilityStatusChangeListener()); + if (callback == nullptr) { + ZLOGE("new SystemAbilityStatusChangeListener failed! no memory"); + return; + } + systemManager->SubscribeSystemAbility(CONCURRENT_TASK_SERVICE_ID, callback); +} + void DataShareServiceImpl::SubscribeChange() { EventCenter::GetInstance().Subscribe(RemoteChangeEvent::RDB_META_SAVE, [this](const Event &event) { @@ -773,6 +811,38 @@ int32_t DataShareServiceImpl::DataShareStatic::OnAppUpdate(const std::string &bu return E_OK; } +void DataShareServiceImpl::UpdateLaunchInfo() +{ + DataShareConfig *config = ConfigFactory::GetInstance().GetDataShareConfig(); + if (config == nullptr) { + ZLOGE("DataShareConfig is nullptr"); + return; + } + + ZLOGI("UpdateLaunchInfo begin."); + for (auto &bundleName : config->updateLaunchNames) { + std::string prefix = StoreMetaData::GetPrefix( + { DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid }); + std::vector storeMetaData; + MetaDataManager::GetInstance().LoadMeta(prefix, storeMetaData, true); + std::vector updateMetaData; + for (auto &meta : storeMetaData) { + if (meta.bundleName != bundleName) { + continue; + } + updateMetaData.push_back(meta); + } + for (auto &meta : updateMetaData) { + MetaDataManager::GetInstance().DelMeta(meta.GetAutoLaunchKey(), true); + } + for (auto &meta : updateMetaData) { + BundleMgrProxy::GetInstance()->Delete(bundleName, atoi(meta.user.c_str()), 0); + SaveLaunchInfo(meta.bundleName, meta.user, DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid); + } + ZLOGI("update bundleName %{public}s, size:%{public}zu.", bundleName.c_str(), storeMetaData.size()); + } +} + int32_t DataShareServiceImpl::DataShareStatic::OnClearAppStorage(const std::string &bundleName, int32_t user, int32_t index, int32_t tokenId) { @@ -800,15 +870,16 @@ int32_t DataShareServiceImpl::OnAppUpdate(const std::string &bundleName, int32_t void DataShareServiceImpl::NotifyObserver(const std::string &uri) { - ZLOGD_MACRO("%{private}s try notified", uri.c_str()); + auto anonymous = URIUtils::Anonymous(uri); + ZLOGD_MACRO("%{private}s try notified", anonymous.c_str()); auto context = std::make_shared(uri); if (!GetCallerBundleName(context->callerBundleName)) { - ZLOGE("get bundleName error, %{private}s", uri.c_str()); + ZLOGE("get bundleName error, %{private}s", anonymous.c_str()); return; } auto ret = rdbNotifyStrategy_.Execute(context); if (ret) { - ZLOGI("%{private}s start notified", uri.c_str()); + ZLOGI("%{private}s start notified", anonymous.c_str()); RdbSubscriberManager::GetInstance().Emit(uri, context); } } @@ -857,8 +928,9 @@ void DataShareServiceImpl::RegisterDataShareServiceInfo() void DataShareServiceImpl::RegisterHandler() { - Handler handler = - std::bind(&DataShareServiceImpl::DumpDataShareServiceInfo, this, std::placeholders::_1, std::placeholders::_2); + Handler handler = [] (int fd, std::map> ¶ms) { + DumpDataShareServiceInfo(fd, params); + }; DumpManager::GetInstance().AddHandler("FEATURE_INFO", uintptr_t(this), handler); } @@ -946,6 +1018,125 @@ int32_t DataShareServiceImpl::UnregisterObserver(const std::string &uri, return ERROR; } +bool DataShareServiceImpl::GetCallerBundleInfo(BundleInfo &callerBundleInfo) +{ + GetCallerInfo(callerBundleInfo.bundleName, callerBundleInfo.appIndex); + callerBundleInfo.userId = AccountDelegate::GetInstance()->GetUserByToken(IPCSkeleton::GetCallingTokenID()); + callerBundleInfo.tokenId = IPCSkeleton::GetCallingTokenID(); + auto [ret, callerAppIdentifier] = BundleMgrProxy::GetInstance()->GetCallerAppIdentifier( + callerBundleInfo.bundleName, callerBundleInfo.userId); + if (ret != 0) { + ZLOGE("Get caller appIdentifier failed, callerBundleName is %{public}s", callerBundleInfo.bundleName.c_str()); + return false; + } + callerBundleInfo.appIdentifier = callerAppIdentifier; + return true; +} + +std::vector DataShareServiceImpl::PublishProxyData(const std::vector &proxyDatas, + const DataProxyConfig &proxyConfig) +{ + std::vector result; + BundleInfo callerBundleInfo; + if (!GetCallerBundleInfo(callerBundleInfo)) { + ZLOGE("get callerBundleInfo failed"); + return result; + } + std::vector keys; + std::map> datas; + for (const auto &data : proxyDatas) { + DataShareObserver::ChangeType type; + auto ret = PublishedProxyData::Upsert(data, callerBundleInfo, type); + result.emplace_back(data.uri_, static_cast(ret)); + if (ret == SUCCESS && + (type == DataShareObserver::ChangeType::INSERT || type == DataShareObserver::ChangeType::UPDATE)) { + keys.emplace_back(data.uri_, callerBundleInfo.bundleName); + datas[type].emplace_back(data); + } + } + ProxyDataSubscriberManager::GetInstance().Emit(keys, datas, callerBundleInfo.userId); + return result; +} + +std::vector DataShareServiceImpl::DeleteProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) +{ + std::vector result; + BundleInfo callerBundleInfo; + if (!GetCallerBundleInfo(callerBundleInfo)) { + ZLOGE("get callerBundleInfo failed"); + return result; + } + std::vector keys; + std::map> datas; + for (const auto &uri : uris) { + DataShareProxyData oldProxyData; + DataShareObserver::ChangeType type; + auto ret = PublishedProxyData::Delete(uri, callerBundleInfo, oldProxyData, type); + result.emplace_back(uri, static_cast(ret)); + if (ret == SUCCESS && type == DataShareObserver::ChangeType::DELETE) { + keys.emplace_back(uri, callerBundleInfo.bundleName); + datas[type].emplace_back(oldProxyData); + } + } + ProxyDataSubscriberManager::GetInstance().Emit(keys, datas, callerBundleInfo.userId); + return result; +} + +std::vector DataShareServiceImpl::GetProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) +{ + std::vector result; + BundleInfo callerBundleInfo; + if (!GetCallerBundleInfo(callerBundleInfo)) { + ZLOGE("get callerBundleInfo failed"); + return result; + } + for (const auto &uri : uris) { + DataShareProxyData proxyData; + auto ret = PublishedProxyData::Query(uri, callerBundleInfo, proxyData); + result.emplace_back(uri, static_cast(ret), proxyData.value_, proxyData.allowList_); + } + return result; +} + +std::vector DataShareServiceImpl::SubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig, const sptr observer) +{ + std::vector results = {}; + BundleInfo callerBundleInfo; + if (!GetCallerBundleInfo(callerBundleInfo)) { + ZLOGE("get callerBundleInfo failed"); + return results; + } + for (const auto &uri : uris) { + DataShareProxyData proxyData; + DataProxyErrorCode ret = + static_cast(PublishedProxyData::Query(uri, callerBundleInfo, proxyData)); + if (ret == SUCCESS) { + ret = ProxyDataSubscriberManager::GetInstance().Add( + ProxyDataKey(uri, callerBundleInfo.bundleName), observer, callerBundleInfo.bundleName, + callerBundleInfo.appIdentifier, callerBundleInfo.userId); + } + results.emplace_back(uri, ret); + } + return results; +} + +std::vector DataShareServiceImpl::UnsubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) +{ + std::string bundleName; + GetCallerBundleName(bundleName); + int32_t userId = AccountDelegate::GetInstance()->GetUserByToken(IPCSkeleton::GetCallingTokenID()); + std::vector result = {}; + for (const auto &uri : uris) { + auto ret = ProxyDataSubscriberManager::GetInstance().Delete(ProxyDataKey(uri, bundleName), userId); + result.emplace_back(uri, ret); + } + return result; +} + bool DataShareServiceImpl::VerifyAcrossAccountsPermission(int32_t currentUserId, int32_t visitedUserId, const std::string &acrossAccountsPermission, uint32_t callerTokenId) { @@ -1003,7 +1194,7 @@ std::pair DataShareServiceImpl::ExecuteEx(const std::string &u auto [code, metaData, dbDelegate] = dbConfig.GetDbConfig(config); if (code != E_OK) { ZLOGE("Get dbConfig fail,bundleName:%{public}s,tableName:%{public}s,tokenId:0x%{public}x, uri:%{public}s", - providerInfo.bundleName.c_str(), providerInfo.tableName.c_str(), tokenId, + providerInfo.bundleName.c_str(), StringUtils::GeneralAnonymous(providerInfo.tableName).c_str(), tokenId, URIUtils::Anonymous(providerInfo.uri).c_str()); return std::make_pair(code, 0); } @@ -1072,7 +1263,7 @@ int32_t DataShareServiceImpl::GetBMSAndMetaDataStatus(const std::string &uri, co auto [code, metaData] = dbConfig.GetMetaData(dbArg); if (code != E_OK) { ZLOGE("Get metaData fail,bundleName:%{public}s,tableName:%{public}s,tokenId:0x%{public}x, uri:%{public}s", - calledInfo.bundleName.c_str(), calledInfo.tableName.c_str(), tokenId, + calledInfo.bundleName.c_str(), StringUtils::GeneralAnonymous(calledInfo.tableName).c_str(), tokenId, URIUtils::Anonymous(calledInfo.uri).c_str()); return E_METADATA_NOT_EXISTS; } @@ -1088,9 +1279,12 @@ void DataShareServiceImpl::InitSubEvent() } EventFwk::MatchingSkills matchingSkills; matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED); + matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills); subscribeInfo.SetThreadMode(EventFwk::CommonEventSubscribeInfo::COMMON); - auto sysEventSubscriber = std::make_shared(subscribeInfo); + auto sysEventSubscriber = std::make_shared(subscribeInfo, binderInfo_.executors); if (!EventFwk::CommonEventManager::SubscribeCommonEvent(sysEventSubscriber)) { ZLOGE("Subscribe sys event failed."); alreadySubscribe = false; @@ -1150,13 +1344,13 @@ bool DataShareServiceImpl::VerifyPermission(const std::string &bundleName, const } } else { Security::AccessToken::HapTokenInfo tokenInfo; - auto result = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo); - if (result == Security::AccessToken::RET_SUCCESS && tokenInfo.bundleName == bundleName) { - return true; - } // Provider from ProxyData, which does not allow empty permissions and cannot be access without configured if (permission.empty()) { - ZLOGE("Permission empty! token:0x%{public}x, bundleName:%{public}s", tokenId, bundleName.c_str()); + auto result = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo); + if (result == Security::AccessToken::RET_SUCCESS && tokenInfo.bundleName == bundleName) { + return true; + } + ZLOGE("Permission denied! token:0x%{public}x, bundleName:%{public}s", tokenId, bundleName.c_str()); return false; } // If the permission is NO_PERMISSION, access is also allowed diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.h b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.h index e4d0a7d9..41b2965e 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.h @@ -22,11 +22,11 @@ #include "accesstoken_kit.h" #include "bundle_mgr_proxy.h" +#include "changeevent/remote_change_event.h" #include "common_event_subscribe_info.h" #include "common_event_subscriber.h" -#include "changeevent/remote_change_event.h" -#include "data_proxy_observer.h" #include "data_provider_config.h" +#include "data_proxy_observer.h" #include "data_share_db_config.h" #include "data_share_service_stub.h" #include "data_share_silent_config.h" @@ -39,7 +39,7 @@ #include "rdb_notify_strategy.h" #include "subscribe_strategy.h" #include "template_strategy.h" -#include "uri_utils.h" +#include "utils.h" #include "visibility.h" namespace OHOS::DataShare { @@ -79,7 +79,7 @@ public: int32_t OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index) override; int32_t OnUserChange(uint32_t code, const std::string &user, const std::string &account) override; void NotifyObserver(const std::string &uri) override; - void DumpDataShareServiceInfo(int fd, std::map> ¶ms); + static void DumpDataShareServiceInfo(int fd, std::map> ¶ms); int32_t OnInitialize() override; int32_t EnableSilentProxy(const std::string &uri, bool enable) override; int32_t GetSilentProxyStatus(const std::string &uri, bool isCreateHelper) override; @@ -91,6 +91,17 @@ public: const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket) override; std::pair DeleteEx(const std::string &uri, const std::string &extUri, const DataSharePredicates &predicate) override; + std::vector PublishProxyData(const std::vector &proxyData, + const DataProxyConfig &proxyConfig) override; + std::vector DeleteProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) override; + std::vector GetProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) override; + std::vector SubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig, const sptr observer) override; + std::vector UnsubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) override; + static void UpdateLaunchInfo(); private: class SystemAbilityStatusChangeListener; using StaticActs = DistributedData::StaticActs; @@ -118,13 +129,14 @@ private: void RegisterDataShareServiceInfo(); void RegisterHandler(); bool SubscribeTimeChanged(); - bool NotifyChange(const std::string &uri); + bool NotifyChange(const std::string &uri, int32_t userId); bool GetCallerBundleName(std::string &bundleName); std::pair ExecuteEx(const std::string &uri, const std::string &extUri, const int32_t tokenId, bool isRead, ExecuteCallbackEx callback); std::pair GetCallerInfo(std::string &bundleName, int32_t &appIndex); int32_t GetBMSAndMetaDataStatus(const std::string &uri, const int32_t tokenId); void SubscribeCommonEvent(); + void SubscribeConcurrentTask(); static void InitSubEvent(); void AutoLaunch(const DistributedData::Event &event); void SubscribeChange(); @@ -141,6 +153,7 @@ private: const std::vector &allowLists); bool VerifyPermission(const std::string &bundleName, const std::string &permission, bool isFromExtension, const int32_t tokenId); + bool GetCallerBundleInfo(BundleInfo &callerBundleInfo); static Factory factory_; static constexpr int32_t ERROR = -1; static constexpr int32_t ERROR_PERMISSION_DENIED = -2; @@ -153,7 +166,7 @@ private: SubscribeStrategy subscribeStrategy_; TemplateStrategy templateStrategy_; RdbNotifyStrategy rdbNotifyStrategy_; - BindInfo binderInfo_; + static BindInfo binderInfo_; std::shared_ptr timerReceiver_ = nullptr; DataShareSilentConfig dataShareSilentConfig_; }; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp index d0b000ee..35586c10 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp @@ -13,13 +13,13 @@ * limitations under the License. */ +#include "datashare_errno.h" #define LOG_TAG "DataShareServiceStub" #include "data_share_service_stub.h" #include -#include "accesstoken_kit.h" -#include "tokenid_kit.h" +#include "common_utils.h" #include "data_share_obs_proxy.h" #include "hiview_adapter.h" #include "hiview_fault_adapter.h" @@ -27,10 +27,31 @@ #include "ishared_result_set.h" #include "itypes_util.h" #include "log_print.h" +#include "qos.h" +#include "utils.h" #include "utils/anonymous.h" +#include "dataproxy_handle_common.h" namespace OHOS { namespace DataShare { + +class DataShareServiceStub::QosManager { +public: + QosManager() + { +#ifndef IS_EMULATOR + // set thread qos QOS_USER_INTERACTIVE + QOS::SetThreadQos(QOS::QosLevel::QOS_USER_INTERACTIVE); +#endif + } + ~QosManager() + { +#ifndef IS_EMULATOR + QOS::ResetThreadQos(); +#endif + } +}; + bool DataShareServiceStub::CheckInterfaceToken(MessageParcel &data) { auto localDescriptor = IDataShareService::GetDescriptor(); @@ -48,11 +69,13 @@ int32_t DataShareServiceStub::OnInsertEx(MessageParcel &data, MessageParcel &rep std::string extUri; DataShareValuesBucket bucket; if (!ITypesUtil::Unmarshal(data, uri, extUri, bucket.valuesMap)) { - ZLOGE("Unmarshal uri:%{public}s bucket size:%{public}zu", DistributedData::Anonymous::Change(uri).c_str(), + ZLOGE("Unmarshal uri:%{public}s bucket size:%{public}zu", URIUtils::Anonymous(uri).c_str(), bucket.valuesMap.size()); return IPC_STUB_INVALID_DATA_ERR; } auto [errCode, status] = InsertEx(uri, extUri, bucket); + ZLOGI("Insert uri:%{public}s, e:%{public}x, s:%{public}x", + URIUtils::Anonymous(uri).c_str(), errCode, status); if (!ITypesUtil::Marshal(reply, errCode, status)) { ZLOGE("Marshal errCode: 0x%{public}x, status: 0x%{public}x", errCode, status); return IPC_STUB_WRITE_PARCEL_ERR; @@ -67,11 +90,13 @@ int32_t DataShareServiceStub::OnUpdateEx(MessageParcel &data, MessageParcel &rep DataSharePredicates predicate; DataShareValuesBucket bucket; if (!ITypesUtil::Unmarshal(data, uri, extUri, predicate, bucket.valuesMap)) { - ZLOGE("Unmarshal uri:%{public}s bucket size:%{public}zu", DistributedData::Anonymous::Change(uri).c_str(), + ZLOGE("Unmarshal uri:%{public}s bucket size:%{public}zu", URIUtils::Anonymous(uri).c_str(), bucket.valuesMap.size()); return IPC_STUB_INVALID_DATA_ERR; } auto [errCode, status] = UpdateEx(uri, extUri, predicate, bucket); + ZLOGI("Update uri:%{public}s, e:%{public}x, s:%{public}x", + URIUtils::Anonymous(uri).c_str(), errCode, status); if (!ITypesUtil::Marshal(reply, errCode, status)) { ZLOGE("Marshal errCode: 0x%{public}x, status: 0x%{public}x", errCode, status); return IPC_STUB_WRITE_PARCEL_ERR; @@ -85,10 +110,12 @@ int32_t DataShareServiceStub::OnDeleteEx(MessageParcel &data, MessageParcel &rep std::string extUri; DataSharePredicates predicate; if (!ITypesUtil::Unmarshal(data, uri, extUri, predicate)) { - ZLOGE("Unmarshal uri:%{public}s", DistributedData::Anonymous::Change(uri).c_str()); + ZLOGE("Unmarshal uri:%{public}s", URIUtils::Anonymous(uri).c_str()); return IPC_STUB_INVALID_DATA_ERR; } auto [errCode, status] = DeleteEx(uri, extUri, predicate); + ZLOGI("Delete uri:%{public}s, e:%{public}x, s:%{public}x", + URIUtils::Anonymous(uri).c_str(), errCode, status); if (!ITypesUtil::Marshal(reply, errCode, status)) { ZLOGE("Marshal errCode: 0x%{public}x, status: 0x%{public}x", errCode, status); return IPC_STUB_WRITE_PARCEL_ERR; @@ -103,7 +130,7 @@ int32_t DataShareServiceStub::OnQuery(MessageParcel &data, MessageParcel &reply) DataSharePredicates predicate; std::vector columns; if (!ITypesUtil::Unmarshal(data, uri, extUri, predicate, columns)) { - ZLOGE("Unmarshal uri:%{public}s columns size:%{public}zu", DistributedData::Anonymous::Change(uri).c_str(), + ZLOGE("Unmarshal uri:%{public}s columns size:%{public}zu", URIUtils::Anonymous(uri).c_str(), columns.size()); return IPC_STUB_INVALID_DATA_ERR; } @@ -327,36 +354,23 @@ int32_t DataShareServiceStub::OnNotifyConnectDone(MessageParcel &data, MessagePa return 0; } -bool DataShareServiceStub::CheckProxyCallingPermission(uint32_t tokenId) -{ - Security::AccessToken::ATokenTypeEnum tokenType = - Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId); - return (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE || - tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL); -} - -// GetTokenType use tokenId, and IsSystemApp use fullTokenId, these are different -bool DataShareServiceStub::CheckSystemUidCallingPermission(uint32_t tokenId, uint64_t fullTokenId) -{ - if (CheckProxyCallingPermission(tokenId)) { - return true; - } - // IsSystemAppByFullTokenID here is not IPC - return Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(fullTokenId); -} - int DataShareServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply) { + // set thread qos + DataShareServiceStub::QosManager qos; + int tryTimes = TRY_TIMES; while (!isReady_.load() && tryTimes > 0) { tryTimes--; std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME)); } auto callingPid = IPCSkeleton::GetCallingPid(); + auto fullTokenId = IPCSkeleton::GetCallingFullTokenID(); + bool isSystemApp = CheckSystemCallingPermission(IPCSkeleton::GetCallingTokenID(), fullTokenId); + DataShareThreadLocal::SetFromSystemApp(isSystemApp); if (code >= DATA_SHARE_CMD_SYSTEM_CODE) { - auto fullTokenId = IPCSkeleton::GetCallingFullTokenID(); - if (!CheckSystemUidCallingPermission(IPCSkeleton::GetCallingTokenID(), fullTokenId)) { - ZLOGE("CheckSystemUidCallingPermission fail, token:%{public}" PRIx64 + if (!isSystemApp) { + ZLOGE("CheckSystemCallingPermission fail, token:%{public}" PRIx64 ", callingPid:%{public}d, code:%{public}u", fullTokenId, callingPid, code); return E_NOT_SYSTEM_APP; } @@ -366,6 +380,7 @@ int DataShareServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Me ZLOGI("code:%{public}u, callingPid:%{public}d", code, callingPid); } if (!CheckInterfaceToken(data)) { + DataShareThreadLocal::CleanFromSystemApp(); return DATA_SHARE_ERROR; } int res = -1; @@ -384,6 +399,7 @@ int DataShareServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data, Me } HiViewAdapter::GetInstance().ReportDataStatistic(callerInfo); } + DataShareThreadLocal::CleanFromSystemApp(); return res; } @@ -403,7 +419,7 @@ int32_t DataShareServiceStub::OnSetSilentSwitch(MessageParcel &data, MessageParc std::string uri; bool enable = false; if (!ITypesUtil::Unmarshal(data, uri, enable)) { - ZLOGE("Unmarshal set silent switch failed. uri: %{public}s", DistributedData::Anonymous::Change(uri).c_str()); + ZLOGE("Unmarshal set silent switch failed. uri: %{public}s", URIUtils::Anonymous(uri).c_str()); return IPC_STUB_INVALID_DATA_ERR; } int32_t status = EnableSilentProxy(uri, enable); @@ -418,7 +434,7 @@ int32_t DataShareServiceStub::OnGetSilentProxyStatus(MessageParcel &data, Messag { std::string uri; if (!ITypesUtil::Unmarshal(data, uri)) { - ZLOGE("Unmarshal silent enable failed. uri: %{public}s", DistributedData::Anonymous::Change(uri).c_str()); + ZLOGE("Unmarshal silent enable failed. uri: %{public}s", URIUtils::Anonymous(uri).c_str()); return IPC_STUB_INVALID_DATA_ERR; } int32_t enable = GetSilentProxyStatus(uri); @@ -443,5 +459,91 @@ void DataShareServiceStub::SetServiceReady() { isReady_.store(true); } + +int32_t DataShareServiceStub::OnPublishProxyData(MessageParcel& data, MessageParcel& reply) +{ + std::vector proxyDatas; + DataProxyConfig config; + if (!ITypesUtil::Unmarshal(data, proxyDatas, config)) { + ZLOGE("OnPublishProxyData unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + std::vector results = PublishProxyData(proxyDatas, config); + if (!ITypesUtil::Marshal(reply, results)) { + ZLOGE("OnPublishProxyData marshal reply failed."); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return E_OK; +} + +int32_t DataShareServiceStub::OnDeleteProxyData(MessageParcel& data, MessageParcel& reply) +{ + std::vector uris; + DataProxyConfig config; + if (!ITypesUtil::Unmarshal(data, uris, config)) { + ZLOGE("unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + std::vector results = DeleteProxyData(uris, config); + if (!ITypesUtil::Marshal(reply, results)) { + ZLOGE("OnPublishProxyData marshal reply failed."); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return E_OK; +} + +int32_t DataShareServiceStub::OnGetProxyData(MessageParcel& data, MessageParcel& reply) +{ + std::vector uris; + DataProxyConfig config; + if (!ITypesUtil::Unmarshal(data, uris, config)) { + ZLOGE("unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + std::vector results = GetProxyData(uris, config); + if (!ITypesUtil::Marshal(reply, results)) { + ZLOGE("OnPublishProxyData marshal reply failed."); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return E_OK; +} + +int32_t DataShareServiceStub::OnSubscribeProxyData(MessageParcel& data, MessageParcel& reply) +{ + std::vector uris; + DataProxyConfig config; + if (!ITypesUtil::Unmarshal(data, uris)) { + ZLOGE("unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + auto remoteObj = data.ReadRemoteObject(); + sptr observer = new (std::nothrow)ProxyDataObserverProxy(remoteObj); + if (observer == nullptr) { + ZLOGE("observer is nullptr"); + return DATA_SHARE_ERROR; + } + std::vector results = SubscribeProxyData(uris, config, observer); + if (!ITypesUtil::Marshal(reply, results)) { + ZLOGE("ITypesUtil::Marshal(reply, results) failed"); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return 0; +} + +int32_t DataShareServiceStub::OnUnsubscribeProxyData(MessageParcel& data, MessageParcel& reply) +{ + std::vector uris; + DataProxyConfig config; + if (!ITypesUtil::Unmarshal(data, uris)) { + ZLOGE("unmarshal failed"); + return IPC_STUB_INVALID_DATA_ERR; + } + std::vector results = UnsubscribeProxyData(uris, config); + if (!ITypesUtil::Marshal(reply, results)) { + ZLOGE("ITypesUtil::Marshal(reply, results) failed"); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return 0; +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.h b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.h index b84c2696..27f1690f 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.h @@ -27,10 +27,9 @@ public: void SetServiceReady(); private: + class QosManager; static constexpr std::chrono::milliseconds TIME_THRESHOLD = std::chrono::milliseconds(500); static bool CheckInterfaceToken(MessageParcel& data); - bool CheckProxyCallingPermission(uint32_t tokenId); - bool CheckSystemUidCallingPermission(uint32_t tokenId, uint64_t fullTokenId); int32_t OnQuery(MessageParcel& data, MessageParcel& reply); int32_t OnAddTemplate(MessageParcel& data, MessageParcel& reply); int32_t OnDelTemplate(MessageParcel& data, MessageParcel& reply); @@ -53,6 +52,11 @@ private: int32_t OnInsertEx(MessageParcel& data, MessageParcel& reply); int32_t OnUpdateEx(MessageParcel& data, MessageParcel& reply); int32_t OnDeleteEx(MessageParcel& data, MessageParcel& reply); + int32_t OnPublishProxyData(MessageParcel& data, MessageParcel& reply); + int32_t OnDeleteProxyData(MessageParcel& data, MessageParcel& reply); + int32_t OnGetProxyData(MessageParcel& data, MessageParcel& reply); + int32_t OnSubscribeProxyData(MessageParcel& data, MessageParcel& reply); + int32_t OnUnsubscribeProxyData(MessageParcel& data, MessageParcel& reply); using RequestHandle = int (DataShareServiceStub::*)(MessageParcel &, MessageParcel &); static constexpr RequestHandle HANDLERS[DATA_SHARE_SERVICE_CMD_MAX] = { &DataShareServiceStub::OnQuery, @@ -76,7 +80,12 @@ private: &DataShareServiceStub::OnUnregisterObserver, &DataShareServiceStub::OnInsertEx, &DataShareServiceStub::OnDeleteEx, - &DataShareServiceStub::OnUpdateEx}; + &DataShareServiceStub::OnUpdateEx, + &DataShareServiceStub::OnPublishProxyData, + &DataShareServiceStub::OnDeleteProxyData, + &DataShareServiceStub::OnGetProxyData, + &DataShareServiceStub::OnSubscribeProxyData, + &DataShareServiceStub::OnUnsubscribeProxyData}; static constexpr int SLEEP_TIME = 300; static constexpr int TRY_TIMES = 5; std::atomic isReady_ = false; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_silent_config.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_silent_config.cpp index 18b221ac..eee4709a 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_silent_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_silent_config.cpp @@ -23,7 +23,7 @@ #include "hap_token_info.h" #include "ipc_skeleton.h" #include "log_print.h" -#include "uri_utils.h" +#include "utils.h" #include "utils/anonymous.h" namespace OHOS::DataShare { @@ -59,7 +59,7 @@ bool DataShareSilentConfig::EnableSilentProxy(uint32_t callerTokenId, const std: uri = std::string(ALL_URI); } ZLOGI("Enable silent proxy, callerTokenId:%{public}u, enable:%{public}d, uri:%{public}s", - callerTokenId, enable, DistributedData::Anonymous::Change(uri).c_str()); + callerTokenId, enable, URIUtils::Anonymous(uri).c_str()); enableSilentUris_.Compute(callerTokenId, [&enable, &uri](const uint32_t &key, std::map &uris) { uris[uri] = enable; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/dfx/hiview_fault_adapter.h b/datamgr_service/services/distributeddataservice/service/data_share/dfx/hiview_fault_adapter.h index 3b001e62..bb491003 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/dfx/hiview_fault_adapter.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/dfx/hiview_fault_adapter.h @@ -41,6 +41,7 @@ public: static constexpr const char* timeOut = "TIME_OUT"; static constexpr const char* resultsetFull = "RESULTSET_FULL"; static constexpr const char* curdFailed = "CURD_FAILED"; + static constexpr const char* kvDBCorrupt = "KVDB_CORRUPT"; static void ReportDataFault(const DataShareFaultInfo &faultInfo); static std::pair GetCallingName(uint32_t callingTokenid); }; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/idata_share_service.h b/datamgr_service/services/distributeddataservice/service/data_share/idata_share_service.h index 05e1fd15..9f08d74c 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/idata_share_service.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/idata_share_service.h @@ -25,6 +25,7 @@ #include "datashare_template.h" #include "data_proxy_observer.h" #include "iremote_object.h" +#include "dataproxy_handle_common.h" namespace OHOS::DataShare { class IDataShareService { @@ -53,6 +54,11 @@ public: DATA_SHARE_SERVICE_CMD_INSERTEX, DATA_SHARE_SERVICE_CMD_DELETEEX, DATA_SHARE_SERVICE_CMD_UPDATEEX, + DATA_SHARE_SERVICE_CMD_PROXY_PUBLISH, + DATA_SHARE_SERVICE_CMD_PROXY_DELETE, + DATA_SHARE_SERVICE_CMD_PROXY_GET, + DATA_SHARE_SERVICE_CMD_SUBSCRIBE_PROXY_DATA, + DATA_SHARE_SERVICE_CMD_UNSUBSCRIBE_PROXY_DATA, DATA_SHARE_SERVICE_CMD_MAX, DATA_SHARE_SERVICE_CMD_QUERY_SYSTEM = DATA_SHARE_CMD_SYSTEM_CODE, DATA_SHARE_SERVICE_CMD_ADD_TEMPLATE_SYSTEM, @@ -117,6 +123,16 @@ public: const DataSharePredicates &predicate, const DataShareValuesBucket &valuesBucket) = 0; virtual std::pair DeleteEx(const std::string &uri, const std::string &extUri, const DataSharePredicates &predicate) = 0; -}; + virtual std::vector PublishProxyData(const std::vector &proxyData, + const DataProxyConfig &proxyConfig) = 0; + virtual std::vector DeleteProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) = 0; + virtual std::vector GetProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) = 0; + virtual std::vector SubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig, const sptr observer) = 0; + virtual std::vector UnsubscribeProxyData(const std::vector &uris, + const DataProxyConfig &proxyConfig) = 0; + }; } // namespace OHOS::DataShare #endif // DISTRIBUTEDDATAFWK_IDATA_SHARE_SERVICE_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/data_proxy/load_config_from_data_proxy_node_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/data_proxy/load_config_from_data_proxy_node_strategy.cpp index c796152c..1810afac 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/data_proxy/load_config_from_data_proxy_node_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/data_proxy/load_config_from_data_proxy_node_strategy.cpp @@ -17,7 +17,7 @@ #include "load_config_from_data_proxy_node_strategy.h" #include "bundle_mgr_proxy.h" -#include "common/uri_utils.h" +#include "common/utils.h" #include "data_share_profile_config.h" #include "datashare_errno.h" #include "log_print.h" @@ -30,9 +30,9 @@ bool LoadConfigFromDataProxyNodeStrategy::operator()(std::shared_ptr co return false; } context->type = PUBLISHED_DATA_TYPE; - if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( - context->calledBundleName, context->currentUserId, context->bundleInfo) != E_OK) { - ZLOGE("GetBundleInfoFromBMS failed! bundleName: %{public}s", context->calledBundleName.c_str()); + if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMSWithCheck( + context->calledBundleName, context->visitedUserId, context->bundleInfo) != E_OK) { + ZLOGE("GetBundleInfoFromBMSWithCheck failed! bundleName: %{public}s", context->calledBundleName.c_str()); context->errCode = E_BUNDLE_NAME_NOT_EXIST; return false; } @@ -40,10 +40,12 @@ bool LoadConfigFromDataProxyNodeStrategy::operator()(std::shared_ptr co context->permission = "reject"; return true; } + std::string uri = context->uri; + URIUtils::FormatUri(uri); for (auto const &hapModuleInfo : context->bundleInfo.hapModuleInfos) { auto proxyDatas = hapModuleInfo.proxyDatas; for (auto const &proxyData : proxyDatas) { - if (proxyData.uri != context->uri) { + if (proxyData.uri != uri) { continue; } context->permission = context->isRead ? proxyData.requiredReadPermission @@ -69,7 +71,7 @@ bool LoadConfigFromDataProxyNodeStrategy::operator()(std::shared_ptr co return true; } context->errCode = E_URI_NOT_EXIST; - ZLOGI("not find DataProperties! %{private}s is private", context->uri.c_str()); + ZLOGI("not find DataProperties! %{public}s is private", URIUtils::Anonymous(context->uri).c_str()); return false; } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/data_share/load_config_from_data_share_bundle_info_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/data_share/load_config_from_data_share_bundle_info_strategy.cpp index 16fe9151..cd5a5aa8 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/data_share/load_config_from_data_share_bundle_info_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/data_share/load_config_from_data_share_bundle_info_strategy.cpp @@ -20,7 +20,7 @@ #include "data_share_profile_config.h" #include "datashare_errno.h" #include "log_print.h" -#include "uri_utils.h" +#include "utils.h" #include "utils/anonymous.h" namespace OHOS::DataShare { @@ -80,9 +80,9 @@ bool LoadConfigFromDataShareBundleInfoStrategy::operator()(std::shared_ptrcalledBundleName.c_str()); return false; } - if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( - context->calledBundleName, context->currentUserId, context->bundleInfo) != E_OK) { - ZLOGE("GetBundleInfoFromBMS failed! bundleName: %{public}s", context->calledBundleName.c_str()); + if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMSWithCheck( + context->calledBundleName, context->visitedUserId, context->bundleInfo) != E_OK) { + ZLOGE("GetBundleInfoFromBMSWithCheck failed! bundleName: %{public}s", context->calledBundleName.c_str()); return false; } for (auto const &item : context->bundleInfo.extensionInfos) { @@ -107,7 +107,7 @@ bool LoadConfigFromDataShareBundleInfoStrategy::LoadConfigFromUri(std::shared_pt { UriInfo uriInfo; if (!URIUtils::GetInfoFromURI(context->uri, uriInfo)) { - ZLOGE("Invalid uri: %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + ZLOGE("Invalid uri: %{public}s", URIUtils::Anonymous(context->uri).c_str()); return false; } context->calledBundleName = std::move(uriInfo.bundleName); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/check_is_data_proxy_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/check_is_data_proxy_strategy.cpp index 6842ed8b..8d94c9e6 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/check_is_data_proxy_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/check_is_data_proxy_strategy.cpp @@ -14,7 +14,7 @@ */ #include "check_is_data_proxy_strategy.h" -#include "uri_utils.h" +#include "utils.h" namespace OHOS::DataShare { bool CheckIsDataProxyStrategy::operator()(std::shared_ptr context) diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_common_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_common_strategy.cpp index b8dece0f..042ba779 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_common_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_common_strategy.cpp @@ -20,7 +20,7 @@ #include "hap_token_info.h" #include "ipc_skeleton.h" #include "log_print.h" -#include "uri_utils.h" +#include "utils.h" namespace OHOS::DataShare { using namespace OHOS::DistributedData; @@ -33,13 +33,14 @@ bool LoadConfigCommonStrategy::operator()(std::shared_ptr context) context->callerTokenId = IPCSkeleton::GetCallingTokenID(); } context->currentUserId = AccountDelegate::GetInstance()->GetUserByToken(context->callerTokenId); + context->visitedUserId = context->currentUserId; if (!URIUtils::GetAppIndexFromProxyURI(context->uri, context->appIndex)) { return false; } // sa, userId is in uri, caller token id is from first caller tokenId if (context->currentUserId == 0) { GetInfoFromProxyURI( - context->uri, context->currentUserId, context->callerTokenId, context->calledBundleName); + context->uri, context->visitedUserId, context->callerTokenId, context->calledBundleName); URIUtils::FormatUri(context->uri); } if (context->needAutoLoadCallerBundleName && context->callerBundleName.empty()) { diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_data_info_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_data_info_strategy.cpp index d5283e4d..d3966097 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_data_info_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_data_info_strategy.cpp @@ -22,7 +22,7 @@ #include "metadata/meta_data_manager.h" #include "metadata/store_meta_data.h" #include "rdb_errno.h" -#include "utils/anonymous.h" +#include "utils.h" namespace OHOS::DataShare { LoadConfigDataInfoStrategy::LoadConfigDataInfoStrategy() @@ -33,12 +33,14 @@ LoadConfigDataInfoStrategy::LoadConfigDataInfoStrategy() static bool QueryMetaData(const std::string &bundleName, const std::string &storeName, DistributedData::StoreMetaData &metaData, const int32_t userId, const int32_t appIndex) { - DistributedData::StoreMetaData meta; - meta.deviceId = DistributedData::DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; - meta.user = std::to_string(userId); - meta.bundleName = bundleName; - meta.storeId = storeName; - bool isCreated = DistributedData::MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), metaData, true); + DistributedData::StoreMetaMapping storeMetaMapping; + storeMetaMapping.deviceId = DistributedData::DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + storeMetaMapping.user = std::to_string(userId); + storeMetaMapping.bundleName = bundleName; + storeMetaMapping.storeId = storeName; + bool isCreated = DistributedData::MetaDataManager::GetInstance().LoadMeta( + storeMetaMapping.GetKey(), storeMetaMapping, true); + metaData = storeMetaMapping; if (!isCreated) { ZLOGE("DB not exist"); return false; @@ -53,13 +55,13 @@ bool LoadConfigNormalDataInfoStrategy::operator()(std::shared_ptr conte } DistributedData::StoreMetaData metaData; if (!QueryMetaData( - context->calledBundleName, context->calledStoreName, metaData, context->currentUserId, context->appIndex)) { + context->calledBundleName, context->calledStoreName, metaData, context->visitedUserId, context->appIndex)) { // connect extension and retry AAFwk::WantParams wantParams; ExtensionConnectAdaptor::TryAndWait(context->uri, context->calledBundleName, wantParams); if (!QueryMetaData( - context->calledBundleName, context->calledStoreName, metaData, context->currentUserId, context->appIndex)) { - ZLOGE("QueryMetaData fail, %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + context->calledBundleName, context->calledStoreName, metaData, context->visitedUserId, context->appIndex)) { + ZLOGE("QueryMetaData fail, %{public}s", URIUtils::Anonymous(context->uri).c_str()); context->errCode = NativeRdb::E_DB_NOT_EXIST; return false; } @@ -83,7 +85,7 @@ bool LoadConfigSingleDataInfoStrategy::operator()(std::shared_ptr conte AAFwk::WantParams wantParams; ExtensionConnectAdaptor::TryAndWait(context->uri, context->calledBundleName, wantParams); if (!QueryMetaData(context->calledBundleName, context->calledStoreName, metaData, 0, context->appIndex)) { - ZLOGE("QueryMetaData fail, %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + ZLOGE("QueryMetaData fail, %{public}s", URIUtils::Anonymous(context->uri).c_str()); context->errCode = NativeRdb::E_DB_NOT_EXIST; return false; } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/get_data_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/get_data_strategy.cpp index c32d5daf..a532d7c5 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/get_data_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/get_data_strategy.cpp @@ -20,7 +20,7 @@ #include "data_proxy/load_config_from_data_proxy_node_strategy.h" #include "general/load_config_common_strategy.h" #include "log_print.h" -#include "utils/anonymous.h" +#include "utils.h" namespace OHOS::DataShare { Data GetDataStrategy::Execute(std::shared_ptr context, int &errorCode) @@ -32,15 +32,15 @@ Data GetDataStrategy::Execute(std::shared_ptr context, int &errorCode) return Data(); } if (!preProcess(context)) { - ZLOGE("pre process fail, uri: %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + ZLOGE("pre process fail, uri: %{public}s", URIUtils::Anonymous(context->uri).c_str()); errorCode = context->errCode; return Data(); } - auto result = PublishedData::Query(context->calledBundleName, context->currentUserId); + auto result = PublishedData::Query(context->calledBundleName, context->visitedUserId); Data data; for (auto &item : result) { if (!CheckPermission(context, item.value.key)) { - ZLOGI("uri: %{private}s not allowed", context->uri.c_str()); + ZLOGI("uri: %{public}s not allowed", URIUtils::Anonymous(context->uri).c_str()); continue; } if (item.GetVersion() > data.version_) { diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/publish_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/publish_strategy.cpp index b0b7ca77..10d4ecba 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/publish_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/publish_strategy.cpp @@ -22,7 +22,7 @@ #include "general/permission_strategy.h" #include "log_print.h" #include "published_data.h" -#include "utils/anonymous.h" +#include "utils.h" namespace OHOS::DataShare { int32_t PublishStrategy::Execute(std::shared_ptr context, const PublishedDataItem &item) @@ -33,7 +33,7 @@ int32_t PublishStrategy::Execute(std::shared_ptr context, const Publish return -1; } if (!preProcess(context)) { - ZLOGE("pre process fail, uri: %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + ZLOGE("pre process fail, uri: %{public}s", URIUtils::Anonymous(context->uri).c_str()); return context->errCode; } auto delegate = KvDBDelegate::GetInstance(); @@ -42,13 +42,13 @@ int32_t PublishStrategy::Execute(std::shared_ptr context, const Publish return -1; } PublishedDataItem::DataType value = item.GetData(); - PublishedDataNode node(context->uri, context->calledBundleName, item.subscriberId_, context->currentUserId, + PublishedDataNode node(context->uri, context->calledBundleName, item.subscriberId_, context->visitedUserId, PublishedDataNode::MoveTo(value)); PublishedData data(node, context->version); - auto [status, count] = delegate->Upsert(KvDBDelegate::DATA_TABLE, data); + auto [status, count] = delegate->Upsert(KvDBDelegate::DATA_TABLE, data); if (status != E_OK) { ZLOGE("db Upsert failed, %{public}s %{public}s %{public}d", context->calledBundleName.c_str(), - DistributedData::Anonymous::Change(context->uri).c_str(), status); + URIUtils::Anonymous(context->uri).c_str(), status); return status; } return E_OK; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/rdb_notify_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/rdb_notify_strategy.cpp index 95ca0ceb..a28760d0 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/rdb_notify_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/rdb_notify_strategy.cpp @@ -20,7 +20,7 @@ #include "general/load_config_data_info_strategy.h" #include "general/load_config_from_bundle_info_strategy.h" #include "log_print.h" -#include "utils/anonymous.h" +#include "utils.h" #include "log_debug.h" namespace OHOS::DataShare { @@ -32,7 +32,7 @@ bool RdbNotifyStrategy::Execute(std::shared_ptr context) return false; } if (!preProcess(context)) { - ZLOGE("pre process fail, uri: %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + ZLOGE("pre process fail, uri: %{public}s", URIUtils::Anonymous(context->uri).c_str()); return false; } if (context->callerBundleName != context->calledBundleName) { diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/subscribe_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/subscribe_strategy.cpp index 4b7314c8..36b15b45 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/subscribe_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/subscribe_strategy.cpp @@ -21,7 +21,7 @@ #include "general/load_config_data_info_strategy.h" #include "general/permission_strategy.h" #include "log_print.h" -#include "utils/anonymous.h" +#include "utils.h" namespace OHOS::DataShare { int32_t SubscribeStrategy::Execute(std::shared_ptr context, std::function process) @@ -34,7 +34,7 @@ int32_t SubscribeStrategy::Execute(std::shared_ptr context, std::functi context->isRead = true; context->needAutoLoadCallerBundleName = true; if (!preProcess(context)) { - ZLOGE("pre process fail, uri: %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + ZLOGE("pre process fail, uri: %{public}s", URIUtils::Anonymous(context->uri).c_str()); return context->errCode; } return process(); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/template_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/template_strategy.cpp index fd33112a..e771c615 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/template_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/template_strategy.cpp @@ -20,7 +20,7 @@ #include "datashare_errno.h" #include "general/load_config_common_strategy.h" #include "log_print.h" -#include "utils/anonymous.h" +#include "utils.h" namespace OHOS::DataShare { int32_t TemplateStrategy::Execute(std::shared_ptr context, std::function process) @@ -32,7 +32,7 @@ int32_t TemplateStrategy::Execute(std::shared_ptr context, std::functio } if (!preProcess(context)) { - ZLOGE("pre process fail, uri: %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); + ZLOGE("pre process fail, uri: %{public}s", URIUtils::Anonymous(context->uri).c_str()); return context->errCode; } return process(); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp new file mode 100644 index 00000000..cea47b58 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.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. + */ + +#define LOG_TAG "ProxyDataSubscriberManager" + +#include "proxy_data_subscriber_manager.h" + +#include "dataproxy_handle_common.h" +#include "ipc_skeleton.h" +#include "log_print.h" +#include "proxy_data_manager.h" +#include "utils.h" +#include "utils/anonymous.h" + +namespace OHOS::DataShare { +ProxyDataSubscriberManager &ProxyDataSubscriberManager::GetInstance() +{ + static ProxyDataSubscriberManager manager; + return manager; +} + +DataProxyErrorCode ProxyDataSubscriberManager::Add(const ProxyDataKey &key, const sptr &observer, + const std::string &bundleName, const std::string &callerAppIdentifier, const int32_t &userId) +{ + auto callerTokenId = IPCSkeleton::GetCallingTokenID(); + ProxyDataCache_.Compute( + key, [&observer, callerTokenId, bundleName, callerAppIdentifier, userId](const ProxyDataKey &key, + std::vector &value) { + ZLOGI("add proxy data subscriber, uri %{public}s", + URIUtils::Anonymous(key.uri).c_str()); + value.emplace_back(observer, callerTokenId, bundleName, callerAppIdentifier, userId); + return true; + }); + return SUCCESS; +} + +DataProxyErrorCode ProxyDataSubscriberManager::Delete(const ProxyDataKey &key, const int32_t &userId) +{ + auto callerTokenId = IPCSkeleton::GetCallingTokenID(); + auto result = + ProxyDataCache_.ComputeIfPresent(key, [&userId, callerTokenId](const auto &key, + std::vector &value) { + for (auto it = value.begin(); it != value.end();) { + if (it->callerTokenId == callerTokenId && it->userId == userId) { + ZLOGI("delete proxy data subscriber, uri %{public}s", + URIUtils::Anonymous(key.uri).c_str()); + it = value.erase(it); + } else { + it++; + } + } + return !value.empty(); + }); + return result ? SUCCESS : URI_NOT_EXIST; +} + +bool ProxyDataSubscriberManager::CheckAllowList(const std::vector &allowList, + const std::string &callerAppIdentifier) +{ + for (const auto &item : allowList) { + if (callerAppIdentifier == item || item == ALLOW_ALL) { + return true; + } + } + return false; +} + +// if arg observer is not null, notify that observer only; otherwise notify all observers +void ProxyDataSubscriberManager::Emit(const std::vector &keys, + const std::map> &datas, const int32_t &userId) +{ + std::map, std::vector> callbacks; + for (auto typeIt = datas.begin(); typeIt != datas.end(); ++typeIt) { + auto type = typeIt->first; + for (const auto &data : typeIt->second) { + std::string bundleName; + URIUtils::GetBundleNameFromProxyURI(data.uri_, bundleName); + auto it = ProxyDataCache_.Find(ProxyDataKey(data.uri_, bundleName)); + if (!it.first) { + continue; + } + auto &observers = it.second; + std::for_each(observers.begin(), observers.end(), + [&callbacks, data, userId, bundleName, &type, this](const auto &obs) { + if ((CheckAllowList(data.allowList_, obs.callerAppIdentifier) || + bundleName == obs.bundleName) && obs.userId == userId) { + callbacks[obs.observer].emplace_back(type, data.uri_, data.value_); + } else { + ZLOGE("no permission to receive notification"); + } + }); + } + } + for (auto &[callback, changeInfo] : callbacks) { + if (callback != nullptr) { + callback->OnChangeFromProxyData(changeInfo); + } + } +} + +void ProxyDataSubscriberManager::Clear() +{ + ProxyDataCache_.Clear(); +} + +ProxyDataKey::ProxyDataKey(const std::string &uri, const std::string &bundle) + : uri(uri), bundleName(bundle) +{ + /* private published data can use key as simple uri */ + /* etc: datashareproxy://{bundleName}/meeting can use meeting replaced */ + /* if key is normal uri, bundleName is from uri */ + if (URIUtils::IsDataProxyURI(uri)) { + URIUtils::GetBundleNameFromProxyURI(uri, bundleName); + } +} + +bool ProxyDataKey::operator<(const ProxyDataKey &rhs) const +{ + return uri < rhs.uri; +} + +bool ProxyDataKey::operator>(const ProxyDataKey &rhs) const +{ + return rhs < *this; +} + +bool ProxyDataKey::operator<=(const ProxyDataKey &rhs) const +{ + return !(rhs < *this); +} + +bool ProxyDataKey::operator>=(const ProxyDataKey &rhs) const +{ + return !(*this < rhs); +} + +bool ProxyDataKey::operator==(const ProxyDataKey &rhs) const +{ + return uri == rhs.uri && bundleName == rhs.bundleName; +} + +bool ProxyDataKey::operator!=(const ProxyDataKey &rhs) const +{ + return !(rhs == *this); +} + +ProxyDataSubscriberManager::ObserverNode::ObserverNode(const sptr &observer, + const uint32_t &callerTokenId, const std::string &bundleName, + const std::string &callerAppIdentifier, const int32_t &userId) : observer(observer), + callerTokenId(callerTokenId), bundleName(bundleName), callerAppIdentifier(callerAppIdentifier), userId(userId) +{ +} +} // namespace OHOS::DataShare diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.h b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.h new file mode 100644 index 00000000..e2e7135f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/proxy_data_subscriber_manager.h @@ -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. + */ + +#ifndef DATASHARESERVICE_PROXY_DATA_SUBSCRIBER_MANAGER_H +#define DATASHARESERVICE_PROXY_DATA_SUBSCRIBER_MANAGER_H + +#include "concurrent_map.h" +#include "data_proxy_observer.h" +#include "dataproxy_handle_common.h" + +namespace OHOS::DataShare { +struct ProxyDataKey { + ProxyDataKey(const std::string &uri, const std::string &bundleName); + bool operator<(const ProxyDataKey &rhs) const; + bool operator>(const ProxyDataKey &rhs) const; + bool operator<=(const ProxyDataKey &rhs) const; + bool operator>=(const ProxyDataKey &rhs) const; + bool operator==(const ProxyDataKey &rhs) const; + bool operator!=(const ProxyDataKey &rhs) const; + std::string uri; + std::string bundleName; +}; + +class ProxyDataSubscriberManager { +public: + static ProxyDataSubscriberManager &GetInstance(); + DataProxyErrorCode Add(const ProxyDataKey &key, const sptr &observer, + const std::string &bundleName, const std::string &callerAppIdentifier, const int32_t &userId); + DataProxyErrorCode Delete(const ProxyDataKey &key, const int32_t &userId); + void Emit(const std::vector &keys, const std::map> &datas, const int32_t &userId); + void Clear(); + +private: +struct ObserverNode { + ObserverNode(const sptr &observer, const uint32_t &callerTokenId, + const std::string &bundleName, const std::string &callerAppIdentifier, const int32_t &userId = 0); + sptr observer; + uint32_t callerTokenId; + std::string bundleName; + std::string callerAppIdentifier; + int32_t userId = 0; + }; + + bool CheckAllowList(const std::vector &allowList, + const std::string &callerAppIdentifier); + ProxyDataSubscriberManager() = default; + ConcurrentMap> ProxyDataCache_; +}; +} // namespace OHOS::DataShare +#endif // DATASHARESERVICE_PROXY_DATA_SUBSCRIBER_MANAGER_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp index 3df3c016..a1a36685 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp @@ -22,7 +22,7 @@ #include "general/load_config_data_info_strategy.h" #include "log_print.h" #include "published_data.h" -#include "uri_utils.h" +#include "utils.h" #include "utils/anonymous.h" namespace OHOS::DataShare { @@ -32,15 +32,16 @@ PublishedDataSubscriberManager &PublishedDataSubscriberManager::GetInstance() return manager; } -int PublishedDataSubscriberManager::Add( - const PublishedDataKey &key, const sptr observer, uint32_t firstCallerTokenId) +int PublishedDataSubscriberManager::Add(const PublishedDataKey &key, + const sptr observer, uint32_t firstCallerTokenId, int32_t userId) { publishedDataCache_.Compute( - key, [&observer, &firstCallerTokenId, this](const PublishedDataKey &key, std::vector &value) { + key, [&observer, &firstCallerTokenId, userId, this](const PublishedDataKey &key, + std::vector &value) { ZLOGI("add publish subscriber, uri %{public}s tokenId 0x%{public}x", - DistributedData::Anonymous::Change(key.key).c_str(), firstCallerTokenId); + URIUtils::Anonymous(key.key).c_str(), firstCallerTokenId); value.emplace_back(observer, firstCallerTokenId, IPCSkeleton::GetCallingTokenID(), - IPCSkeleton::GetCallingPid()); + IPCSkeleton::GetCallingPid(), userId); return true; }); return E_OK; @@ -54,7 +55,7 @@ int PublishedDataSubscriberManager::Delete(const PublishedDataKey &key, uint32_t for (auto it = value.begin(); it != value.end();) { if (it->firstCallerTokenId == firstCallerTokenId) { ZLOGI("delete publish subscriber, uri %{public}s tokenId 0x%{public}x", - DistributedData::Anonymous::Change(key.key).c_str(), firstCallerTokenId); + URIUtils::Anonymous(key.key).c_str(), firstCallerTokenId); it = value.erase(it); } else { it++; @@ -71,7 +72,7 @@ void PublishedDataSubscriberManager::Delete(uint32_t callerTokenId, uint32_t cal for (auto it = value.begin(); it != value.end();) { if (it->callerTokenId == callerTokenId && it->callerPid == callerPid) { ZLOGI("erase start, uri is %{public}s, tokenId is 0x%{public}x, pid is %{public}d", - DistributedData::Anonymous::Change(key.key).c_str(), callerTokenId, callerPid); + URIUtils::Anonymous(key.key).c_str(), callerTokenId, callerPid); it = value.erase(it); } else { it++; @@ -83,7 +84,7 @@ void PublishedDataSubscriberManager::Delete(uint32_t callerTokenId, uint32_t cal int PublishedDataSubscriberManager::Disable(const PublishedDataKey &key, uint32_t firstCallerTokenId) { - auto result = + bool result = publishedDataCache_.ComputeIfPresent(key, [&firstCallerTokenId](const auto &key, std::vector &value) { for (auto it = value.begin(); it != value.end(); it++) { @@ -94,12 +95,16 @@ int PublishedDataSubscriberManager::Disable(const PublishedDataKey &key, uint32_ } return true; }); + if (!result) { + ZLOGE("disable failed, uri is %{public}s, bundleName is %{public}s, subscriberId is %{public}" PRId64, + URIUtils::Anonymous(key.key).c_str(), key.bundleName.c_str(), key.subscriberId); + } return result ? E_OK : E_SUBSCRIBER_NOT_EXIST; } int PublishedDataSubscriberManager::Enable(const PublishedDataKey &key, uint32_t firstCallerTokenId) { - auto result = + bool result = publishedDataCache_.ComputeIfPresent(key, [&firstCallerTokenId](const auto &key, std::vector &value) { for (auto it = value.begin(); it != value.end(); it++) { @@ -109,9 +114,14 @@ int PublishedDataSubscriberManager::Enable(const PublishedDataKey &key, uint32_t } return true; }); + if (!result) { + ZLOGE("enable failed, uri is %{public}s, bundleName is %{public}s, subscriberId is %{public}" PRId64, + URIUtils::Anonymous(key.key).c_str(), key.bundleName.c_str(), key.subscriberId); + } return result ? E_OK : E_SUBSCRIBER_NOT_EXIST; } +// if arg observer is not null, notify that observer only; otherwise notify all observers void PublishedDataSubscriberManager::Emit(const std::vector &keys, int32_t userId, const std::string &ownerBundleName, const sptr observer) { @@ -133,7 +143,7 @@ void PublishedDataSubscriberManager::Emit(const std::vector &k publishedResult.erase(key); continue; } - PutInto(callbacks, val, key, observer); + PutInto(callbacks, val, key, observer, userId); break; } return false; @@ -157,7 +167,7 @@ void PublishedDataSubscriberManager::Emit(const std::vector &k void PublishedDataSubscriberManager::PutInto( std::map, std::vector> &callbacks, const std::vector &val, const PublishedDataKey &key, - const sptr observer) + const sptr observer, int32_t userId) { for (auto const &callback : val) { if (callback.enabled && callback.observer != nullptr) { @@ -165,6 +175,10 @@ void PublishedDataSubscriberManager::PutInto( if (observer != nullptr && callback.observer != observer) { continue; } + if (callback.userId != 0 && callback.userId != userId && userId != 0) { + ZLOGE("Not across user publish, from %{public}d to %{public}d", userId, callback.userId); + continue; + } callbacks[callback.observer].emplace_back(key); } } @@ -267,8 +281,8 @@ bool PublishedDataKey::operator!=(const PublishedDataKey &rhs) const } PublishedDataSubscriberManager::ObserverNode::ObserverNode(const sptr &observer, - uint32_t firstCallerTokenId, uint32_t callerTokenId, uint32_t callerPid) - : observer(observer), firstCallerTokenId(firstCallerTokenId), callerTokenId(callerTokenId), callerPid(callerPid) + uint32_t firstCallerTokenId, uint32_t callerTokenId, uint32_t callerPid, int32_t userId): observer(observer), + firstCallerTokenId(firstCallerTokenId), callerTokenId(callerTokenId), callerPid(callerPid), userId(userId) { } } // namespace OHOS::DataShare diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.h b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.h index 81024cac..93295a29 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.h @@ -26,7 +26,8 @@ #include "executor_pool.h" namespace OHOS::DataShare { struct PublishedDataKey { - PublishedDataKey(const std::string &key, const std::string &bundleName, int64_t subscriberId); + PublishedDataKey(const std::string &key, const std::string &bundleName, + int64_t subscriberId); bool operator<(const PublishedDataKey &rhs) const; bool operator>(const PublishedDataKey &rhs) const; bool operator<=(const PublishedDataKey &rhs) const; @@ -42,7 +43,7 @@ class PublishedDataSubscriberManager { public: static PublishedDataSubscriberManager &GetInstance(); int Add(const PublishedDataKey &key, const sptr observer, - uint32_t firstCallerTokenId); + uint32_t firstCallerTokenId, int32_t userId); int Delete(const PublishedDataKey &key, uint32_t firstCallerTokenId); void Delete(uint32_t callerTokenId, uint32_t callerPid); int Disable(const PublishedDataKey &key, uint32_t firstCallerTokenId); @@ -58,18 +59,20 @@ public: private: struct ObserverNode { ObserverNode(const sptr &observer, uint32_t firstCallerTokenId, - uint32_t callerTokenId = 0, uint32_t callerPid = 0); + uint32_t callerTokenId = 0, uint32_t callerPid = 0, int32_t userId = 0); sptr observer; uint32_t firstCallerTokenId; uint32_t callerTokenId; uint32_t callerPid; bool enabled = true; bool isNotifyOnEnabled = false; + int32_t userId = 0; }; PublishedDataSubscriberManager() = default; void PutInto(std::map, std::vector> &, - const std::vector &, const PublishedDataKey &, const sptr); + const std::vector &, const PublishedDataKey &, const sptr, + int32_t userId); ConcurrentMap> publishedDataCache_; }; } // namespace OHOS::DataShare diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp index de0d94af..ed4df8ea 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp @@ -24,7 +24,7 @@ #include "log_print.h" #include "scheduler_manager.h" #include "template_data.h" -#include "uri_utils.h" +#include "utils.h" #include "utils/anonymous.h" namespace OHOS::DataShare { @@ -116,23 +116,24 @@ int RdbSubscriberManager::Add(const Key &key, const sptr { int result = E_OK; rdbCache_.Compute(key, [&observer, &context, executorPool, this](const auto &key, auto &value) { - ZLOGI("add subscriber, uri %{private}s tokenId 0x%{public}x", key.uri.c_str(), context->callerTokenId); + ZLOGI("add subscriber, uri %{public}s tokenId 0x%{public}x", + URIUtils::Anonymous(key.uri).c_str(), context->callerTokenId); auto callerTokenId = IPCSkeleton::GetCallingTokenID(); auto callerPid = IPCSkeleton::GetCallingPid(); - value.emplace_back(observer, context->callerTokenId, callerTokenId, callerPid); + value.emplace_back(observer, context->callerTokenId, callerTokenId, callerPid, context->visitedUserId); std::vector node; - node.emplace_back(observer, context->callerTokenId, callerTokenId, callerPid); + node.emplace_back(observer, context->callerTokenId, callerTokenId, callerPid, context->visitedUserId); ExecutorPool::Task task = [key, node, context, this]() { LoadConfigDataInfoStrategy loadDataInfo; if (!loadDataInfo(context)) { ZLOGE("loadDataInfo failed, uri %{public}s tokenId 0x%{public}x", - DistributedData::Anonymous::Change(key.uri).c_str(), context->callerTokenId); + URIUtils::Anonymous(key.uri).c_str(), context->callerTokenId); return; } DistributedData::StoreMetaData metaData = RdbSubscriberManager::GenMetaDataFromContext(context); - Notify(key, context->currentUserId, node, metaData); + Notify(key, context->visitedUserId, node, metaData); if (GetEnableObserverCount(key) == 1) { - SchedulerManager::GetInstance().Start(key, context->currentUserId, metaData); + SchedulerManager::GetInstance().Start(key, context->visitedUserId, metaData); } }; executorPool->Execute(task); @@ -147,7 +148,7 @@ int RdbSubscriberManager::Delete(const Key &key, uint32_t firstCallerTokenId) rdbCache_.ComputeIfPresent(key, [&firstCallerTokenId, this](const auto &key, std::vector &value) { ZLOGI("delete subscriber, uri %{public}s tokenId 0x%{public}x", - DistributedData::Anonymous::Change(key.uri).c_str(), firstCallerTokenId); + URIUtils::Anonymous(key.uri).c_str(), firstCallerTokenId); for (auto it = value.begin(); it != value.end();) { if (it->firstCallerTokenId == firstCallerTokenId) { ZLOGI("erase start"); @@ -177,7 +178,7 @@ void RdbSubscriberManager::Delete(uint32_t callerTokenId, uint32_t callerPid) if (value.empty()) { ZLOGI("delete timer, subId %{public}" PRId64 ", bundleName %{public}s, tokenId %{public}x, uri %{public}s.", key.subscriberId, key.bundleName.c_str(), callerTokenId, - DistributedData::Anonymous::Change(key.uri).c_str()); + URIUtils::Anonymous(key.uri).c_str()); SchedulerManager::GetInstance().Stop(key); } return value.empty(); @@ -187,7 +188,7 @@ void RdbSubscriberManager::Delete(uint32_t callerTokenId, uint32_t callerPid) int RdbSubscriberManager::Disable(const Key &key, uint32_t firstCallerTokenId) { bool isAllDisabled = true; - auto result = + bool result = rdbCache_.ComputeIfPresent(key, [&firstCallerTokenId, &isAllDisabled, this](const auto &key, std::vector &value) { for (auto it = value.begin(); it != value.end(); it++) { @@ -204,6 +205,10 @@ int RdbSubscriberManager::Disable(const Key &key, uint32_t firstCallerTokenId) if (isAllDisabled) { SchedulerManager::GetInstance().Disable(key); } + if (!result) { + ZLOGE("disable failed, uri is %{public}s, bundleName is %{public}s, subscriberId is %{public}" PRId64, + URIUtils::Anonymous(key.uri).c_str(), key.bundleName.c_str(), key.subscriberId); + } return result ? E_OK : E_SUBSCRIBER_NOT_EXIST; } @@ -211,7 +216,7 @@ int RdbSubscriberManager::Enable(const Key &key, std::shared_ptr contex { bool isChanged = false; DistributedData::StoreMetaData metaData; - auto result = rdbCache_.ComputeIfPresent(key, [&context, &metaData, &isChanged, this](const auto &key, + bool result = rdbCache_.ComputeIfPresent(key, [&context, &metaData, &isChanged, this](const auto &key, std::vector &value) { for (auto it = value.begin(); it != value.end(); it++) { if (it->firstCallerTokenId != context->callerTokenId) { @@ -227,13 +232,17 @@ int RdbSubscriberManager::Enable(const Key &key, std::shared_ptr contex if (it->isNotifyOnEnabled) { std::vector node; node.emplace_back(it->observer, context->callerTokenId); - Notify(key, context->currentUserId, node, metaData); + Notify(key, context->visitedUserId, node, metaData); } } return true; }); if (isChanged) { - SchedulerManager::GetInstance().Enable(key, context->currentUserId, metaData); + SchedulerManager::GetInstance().Enable(key, context->visitedUserId, metaData); + } + if (!result) { + ZLOGE("enable failed, uri is %{public}s, bundleName is %{public}s, subscriberId is %{public}" PRId64, + URIUtils::Anonymous(key.uri).c_str(), key.bundleName.c_str(), key.subscriberId); } return result ? E_OK : E_SUBSCRIBER_NOT_EXIST; } @@ -252,12 +261,12 @@ void RdbSubscriberManager::Emit(const std::string &uri, std::shared_ptr if (key.uri != uri) { return false; } - Notify(key, context->currentUserId, val, metaData); + Notify(key, context->visitedUserId, val, metaData); SetObserverNotifyOnEnabled(val); return false; }); SchedulerManager::GetInstance().Execute( - uri, context->currentUserId, metaData); + uri, context->visitedUserId, metaData); } void RdbSubscriberManager::Emit(const std::string &uri, int32_t userId, @@ -338,15 +347,14 @@ int RdbSubscriberManager::Notify(const Key &key, int32_t userId, const std::vect Template tpl; if (!TemplateManager::GetInstance().Get(key, userId, tpl)) { ZLOGE("template undefined, %{public}s, %{public}" PRId64 ", %{public}s", - DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); + URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); return E_TEMPLATE_NOT_EXIST; } DistributedData::StoreMetaData meta = metaData; - meta.bundleName = key.bundleName; meta.user = std::to_string(userId); auto delegate = DBDelegate::Create(meta, key.uri); if (delegate == nullptr) { - ZLOGE("Create fail %{public}s %{public}s", DistributedData::Anonymous::Change(key.uri).c_str(), + ZLOGE("Create fail %{public}s %{public}s", URIUtils::Anonymous(key.uri).c_str(), key.bundleName.c_str()); return E_ERROR; } @@ -365,13 +373,19 @@ int RdbSubscriberManager::Notify(const Key &key, int32_t userId, const std::vect auto [errCode, rowCount] = delegate->UpdateSql(tpl.update_); if (errCode != E_OK) { ZLOGE("Update failed, err:%{public}d, %{public}s, %{public}" PRId64 ", %{public}s", - errCode, DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); + errCode, URIUtils::Anonymous(key.uri).c_str(), key.subscriberId, key.bundleName.c_str()); } } ZLOGI("emit, valSize: %{public}zu, dataSize:%{public}zu, uri:%{public}s,", - val.size(), changeNode.data_.size(), DistributedData::Anonymous::Change(changeNode.uri_).c_str()); + val.size(), changeNode.data_.size(), URIUtils::Anonymous(changeNode.uri_).c_str()); for (const auto &callback : val) { + // not notify across user + if (callback.userId != userId && userId != 0 && callback.userId != 0) { + ZLOGI("Not allow across notify, uri:%{public}s, from %{public}d to %{public}d.", + URIUtils::Anonymous(changeNode.uri_).c_str(), userId, callback.userId); + continue; + } if (callback.enabled && callback.observer != nullptr) { callback.observer->OnChangeFromRdb(changeNode); } @@ -399,12 +413,12 @@ void RdbSubscriberManager::Emit(const std::string &uri, int64_t subscriberId, if (key.uri != uri || key.subscriberId != subscriberId) { return false; } - Notify(key, context->currentUserId, val, metaData); + Notify(key, context->visitedUserId, val, metaData); SetObserverNotifyOnEnabled(val); return false; }); Key executeKey(uri, subscriberId, bundleName); - SchedulerManager::GetInstance().Start(executeKey, context->currentUserId, metaData); + SchedulerManager::GetInstance().Start(executeKey, context->visitedUserId, metaData); } DistributedData::StoreMetaData RdbSubscriberManager::GenMetaDataFromContext(const std::shared_ptr context) @@ -414,12 +428,14 @@ DistributedData::StoreMetaData RdbSubscriberManager::GenMetaDataFromContext(cons metaData.dataDir = context->calledSourceDir; metaData.storeId = context->calledStoreName; metaData.haMode = context->haMode; + metaData.isEncrypt = context->isEncryptDb; + metaData.bundleName = context->calledBundleName; return metaData; } RdbSubscriberManager::ObserverNode::ObserverNode(const sptr &observer, - uint32_t firstCallerTokenId, uint32_t callerTokenId, uint32_t callerPid) - : observer(observer), firstCallerTokenId(firstCallerTokenId), callerTokenId(callerTokenId), callerPid(callerPid) + uint32_t firstCallerTokenId, uint32_t callerTokenId, uint32_t callerPid, int32_t userId): observer(observer), + firstCallerTokenId(firstCallerTokenId), callerTokenId(callerTokenId), callerPid(callerPid), userId(userId) { } } // namespace OHOS::DataShare \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.h b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.h index 9379ed1a..35c4a2b3 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.h @@ -73,13 +73,14 @@ public: private: struct ObserverNode { ObserverNode(const sptr &observer, uint32_t firstCallerTokenId, - uint32_t callerTokenId = 0, uint32_t callerPid = 0); + uint32_t callerTokenId = 0, uint32_t callerPid = 0, int32_t userId = 0); sptr observer; uint32_t firstCallerTokenId; uint32_t callerTokenId; uint32_t callerPid; bool enabled = true; bool isNotifyOnEnabled = false; + int32_t userId = 0; }; RdbSubscriberManager() = default; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/sys_event_subscriber.cpp b/datamgr_service/services/distributeddataservice/service/data_share/sys_event_subscriber.cpp index b0fe15ee..afd50786 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/sys_event_subscriber.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/sys_event_subscriber.cpp @@ -18,19 +18,46 @@ #include "common_event_manager.h" #include "common_event_support.h" #include "log_print.h" +#include "proxy_data_manager.h" namespace OHOS::DataShare { -SysEventSubscriber::SysEventSubscriber(const EventFwk::CommonEventSubscribeInfo& info) - : CommonEventSubscriber(info) +SysEventSubscriber::SysEventSubscriber(const EventFwk::CommonEventSubscribeInfo& info, + std::shared_ptr executors): CommonEventSubscriber(info), executors_(executors) { - callbacks_ = { { EventFwk::CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED, - &SysEventSubscriber::OnBMSReady } }; + callbacks_ = { + { EventFwk::CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED, + &SysEventSubscriber::OnBMSReady } + }; + installCallbacks_ = { + { EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED, + &SysEventSubscriber::OnAppInstall }, + { EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED, + &SysEventSubscriber::OnAppUpdate }, + { EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED, + &SysEventSubscriber::OnAppUninstall } + }; } void SysEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData& event) { EventFwk::Want want = event.GetWant(); std::string action = want.GetAction(); + auto installEvent = installCallbacks_.find(action); + if (installEvent != installCallbacks_.end()) { + std::string bundleName = want.GetElement().GetBundleName(); + int32_t userId = want.GetIntParam(USER_ID, -1); + int32_t appIndex = want.GetIntParam(APP_INDEX, 0); + uint32_t tokenId = static_cast(want.GetIntParam(ACCESS_TOKEN_ID, 0)); + // when application updated, the tokenId in event's want is 0, so use other way to get tokenId + if (tokenId == 0) { + tokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(userId, bundleName, appIndex); + } + bool isCrossAppSharedConfig = want.GetBoolParam(CROSS_APP_SHARED_CONFIG, false); + ZLOGI("bundleName:%{public}s, user:%{public}d, appIndex:%{public}d, tokenId:%{public}d, " + "isCrossAppSharedConfig:%{public}d", bundleName.c_str(), userId, appIndex, tokenId, isCrossAppSharedConfig); + (this->*(installEvent->second))(bundleName, userId, appIndex, tokenId, isCrossAppSharedConfig); + } + auto it = callbacks_.find(action); if (it != callbacks_.end()) { (this->*(it->second))(); @@ -40,6 +67,42 @@ void SysEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData& event) void SysEventSubscriber::OnBMSReady() { NotifyDataShareReady(); + auto executors = executors_; + if (executors == nullptr) { + ZLOGE("executors is null."); + return; + } + executors->Execute([]() { + DataShareServiceImpl::UpdateLaunchInfo(); + }); +} + +void SysEventSubscriber::OnAppInstall(const std::string &bundleName, + int32_t userId, int32_t appIndex, uint32_t tokenId, bool isCrossAppSharedConfig) +{ + ZLOGI("%{public}s installed, userId: %{public}d, appIndex: %{public}d, tokenId: %{public}d", + bundleName.c_str(), userId, appIndex, tokenId); + if (isCrossAppSharedConfig) { + ProxyDataManager::GetInstance().OnAppInstall(bundleName, userId, appIndex, tokenId); + } +} + +void SysEventSubscriber::OnAppUpdate(const std::string &bundleName, + int32_t userId, int32_t appIndex, uint32_t tokenId, bool isCrossAppSharedConfig) +{ + ZLOGI("%{public}s updated, userId: %{public}d, appIndex: %{public}d, tokenId: %{public}d", + bundleName.c_str(), userId, appIndex, tokenId); + if (isCrossAppSharedConfig) { + ProxyDataManager::GetInstance().OnAppUpdate(bundleName, userId, appIndex, tokenId); + } +} + +void SysEventSubscriber::OnAppUninstall(const std::string &bundleName, + int32_t userId, int32_t appIndex, uint32_t tokenId, bool isCrossAppSharedConfig) +{ + ZLOGI("%{public}s uninstalled, userId: %{public}d, appIndex: %{public}d, tokenId: %{public}d", + bundleName.c_str(), userId, appIndex, tokenId); + ProxyDataManager::GetInstance().OnAppUninstall(bundleName, userId, appIndex, tokenId); } void SysEventSubscriber::NotifyDataShareReady() @@ -55,4 +118,4 @@ void SysEventSubscriber::NotifyDataShareReady() } ZLOGI("Notify dataShare ready succeed."); } -} +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/sys_event_subscriber.h b/datamgr_service/services/distributeddataservice/service/data_share/sys_event_subscriber.h index b266387c..0594044b 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/sys_event_subscriber.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/sys_event_subscriber.h @@ -23,14 +23,29 @@ namespace OHOS::DataShare { class SysEventSubscriber : public EventFwk::CommonEventSubscriber { public: using SysEventCallback = void (SysEventSubscriber::*)(); - explicit SysEventSubscriber(const EventFwk::CommonEventSubscribeInfo &info); + using InstallEventCallback = void (SysEventSubscriber::*)(const std::string &bundleName, + int32_t userId, int32_t appIndex, uint32_t tokenId, bool isCrossAppSharedConfig); + explicit SysEventSubscriber(const EventFwk::CommonEventSubscribeInfo &info, + std::shared_ptr executors); ~SysEventSubscriber() {} void OnReceiveEvent(const EventFwk::CommonEventData& event) override; void OnBMSReady(); + void OnAppInstall(const std::string &bundleName, + int32_t userId, int32_t appIndex, uint32_t tokenId, bool isCrossAppSharedConfig); + void OnAppUpdate(const std::string &bundleName, + int32_t userId, int32_t appIndex, uint32_t tokenId, bool isCrossAppSharedConfig); + void OnAppUninstall(const std::string &bundleName, + int32_t userId, int32_t appIndex, uint32_t tokenId, bool isCrossAppSharedConfig); private: void NotifyDataShareReady(); std::map callbacks_; + std::map installCallbacks_; + static constexpr const char *USER_ID = "userId"; + static constexpr const char *APP_INDEX = "appIndex"; + static constexpr const char *ACCESS_TOKEN_ID = "accessTokenId"; + static constexpr const char *CROSS_APP_SHARED_CONFIG = "crossAppSharedConfig"; + std::shared_ptr executors_ = nullptr; }; } #endif \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/dumper/BUILD.gn b/datamgr_service/services/distributeddataservice/service/dumper/BUILD.gn index 9ba04db7..72b194d7 100644 --- a/datamgr_service/services/distributeddataservice/service/dumper/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/dumper/BUILD.gn @@ -27,7 +27,6 @@ ohos_source_set("distributeddata_dumper") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ "include" ] @@ -38,7 +37,6 @@ ohos_source_set("distributeddata_dumper") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/BUILD.gn b/datamgr_service/services/distributeddataservice/service/kvdb/BUILD.gn index 9f1d96da..874dc361 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/kvdb/BUILD.gn @@ -55,7 +55,6 @@ ohos_source_set("distributeddata_kvdb") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] cflags = [ @@ -64,7 +63,6 @@ ohos_source_set("distributeddata_kvdb") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.cpp index 320db40c..f7696545 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.cpp @@ -63,9 +63,6 @@ std::pair AuthHandlerStub::CheckAccess(int localUserId, int peerUser if (!CheckUsers(localUserId, peerUserId, peerDeviceId)) { return std::make_pair(false, false); } - if (!DmAdapter::GetInstance().IsOHOSType(peerDeviceId)) { - return std::make_pair(true, false); - } if (aclParams.authType == static_cast(DistributedKv::AuthType::DEFAULT)) { if (DmAdapter::GetInstance().IsSameAccount(aclParams.accCaller, aclParams.accCallee)) { return std::make_pair(true, true); diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.h b/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.h index 199b7e74..29d9f551 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/auth_delegate.h @@ -34,11 +34,13 @@ enum AUTH_GROUP_TYPE { class AuthHandler { public: virtual std::pair CheckAccess(int localUserId, int peerUserId, - const std::string &peerDeviceId, const AclParams &aclParams); + const std::string &peerDeviceId, const AclParams &aclParams) = 0; + virtual ~AuthHandler() = default; }; class AuthDelegate { public: + AuthDelegate() = default; API_EXPORT static AuthHandler *GetInstance(); }; } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_exporter.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_exporter.cpp index b9b4f8c7..41281f79 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_exporter.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_exporter.cpp @@ -16,10 +16,11 @@ #include "kvdb_exporter.h" #include "backup_manager.h" +#include "dfx/reporter.h" #include "directory/directory_manager.h" #include "kvdb_general_store.h" #include "log_print.h" -#include "dfx/reporter.h" +#include "utils/anonymous.h" namespace OHOS::DistributedKv { using namespace OHOS::DistributedData; using namespace OHOS::DistributedDataDfx; @@ -42,7 +43,8 @@ void KVDBExporter::Exporter(const StoreMetaData &meta, const std::string &backup } dbStatus = delegate->CheckIntegrity(); if (dbStatus != DistributedDB::DBStatus::OK) { - ZLOGE("CheckIntegrity fail, dbStatus:%{public}d, backupPath:%{public}s", dbStatus, backupPath.c_str()); + ZLOGE("CheckIntegrity fail, dbStatus:%{public}d, backupPath:%{public}s", dbStatus, + Anonymous::Change(backupPath).c_str()); result = false; return; } @@ -60,7 +62,7 @@ void KVDBExporter::Exporter(const StoreMetaData &meta, const std::string &backup .append(std::to_string(result)) .append("]"); Reporter::GetInstance()->GetBehaviourReporter()->Report( - { meta.account, meta.appId, meta.storeId, BehaviourType::DATABASE_BACKUP, message }); + { meta.account, meta.appId, Anonymous::Change(meta.storeId), BehaviourType::DATABASE_BACKUP, message }); } KVDBExporter::KVDBExporter() noexcept diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.cpp index da7a931e..b825f970 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.cpp @@ -20,13 +20,15 @@ #include "app_id_mapping/app_id_mapping_config_manager.h" #include "bootstrap.h" #include "checker/checker_manager.h" +#include "cloud/cloud_sync_finished_event.h" #include "cloud/schema_meta.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter.h" #include "device_matrix.h" #include "dfx/dfx_types.h" #include "dfx/reporter.h" #include "directory/directory_manager.h" +#include "eventcenter/event_center.h" #include "kvdb_query.h" #include "log_print.h" #include "metadata/meta_data_manager.h" @@ -96,21 +98,26 @@ static DBSchema GetDBSchema(const Database &database) } return schema; } + KVDBGeneralStore::DBPassword KVDBGeneralStore::GetDBPassword(const StoreMetaData &data) { DBPassword dbPassword; if (!data.isEncrypt) { return dbPassword; } - SecretKeyMetaData secretKey; - secretKey.storeType = data.storeType; - auto storeKey = data.GetSecretKey(); - MetaDataManager::GetInstance().LoadMeta(storeKey, secretKey, true); - std::vector password; - StoreMetaData metaData; - MetaDataManager::GetInstance().LoadMeta(data.GetKey(), metaData, true); - CryptoManager::GetInstance().Decrypt(metaData, secretKey, password); + auto metaKey = data.GetSecretKey(); + if (!MetaDataManager::GetInstance().LoadMeta(metaKey, secretKey, true) || secretKey.sKey.empty()) { + return dbPassword; + } + CryptoManager::CryptoParams decryptParams = { .area = secretKey.area, .userId = data.user, + .nonce = secretKey.nonce }; + auto password = CryptoManager::GetInstance().Decrypt(secretKey.sKey, decryptParams); + if (password.empty()) { + return dbPassword; + } + // update secret key of area or nonce + CryptoManager::GetInstance().UpdateSecretMeta(password, data, metaKey, secretKey); dbPassword.SetValue(password.data(), password.size()); password.assign(password.size(), 0); return dbPassword; @@ -171,8 +178,8 @@ KVDBGeneralStore::KVDBGeneralStore(const StoreMetaData &meta) DBStatus status = DBStatus::NOT_FOUND; manager_.SetKvStoreConfig({ meta.dataDir }); std::unique_lock lock(rwMutex_); - manager_.GetKvStore(meta.storeId, GetDBOption(meta, GetDBPassword(meta)), - [&status, this](auto dbStatus, auto *tmpStore) { + manager_.GetKvStore( + meta.storeId, GetDBOption(meta, GetDBPassword(meta)), [&status, this](auto dbStatus, auto *tmpStore) { status = dbStatus; delegate_ = tmpStore; }); @@ -199,7 +206,7 @@ KVDBGeneralStore::KVDBGeneralStore(const StoreMetaData &meta) storeInfo_.bundleName = meta.bundleName; storeInfo_.storeName = meta.storeId; storeInfo_.instanceId = meta.instanceId; - storeInfo_.user = std::stoi(meta.user); + storeInfo_.user = std::atoi(meta.user.c_str()); enableCloud_ = meta.enableCloud; } @@ -229,8 +236,8 @@ int32_t KVDBGeneralStore::BindSnapshots(std::shared_ptr &bindInfos, - const CloudConfig &config) +int32_t KVDBGeneralStore::Bind( + const Database &database, const std::map &bindInfos, const CloudConfig &config) { if (bindInfos.empty()) { ZLOGW("No cloudDB!"); @@ -245,8 +252,8 @@ int32_t KVDBGeneralStore::Bind(const Database &database, const std::map(bindInfo.db_, nullptr) }); + dbClouds.insert({ std::to_string(userId), + std::make_shared(bindInfo.db_, nullptr) }); bindInfos_.insert(std::make_pair(userId, std::move(bindInfo))); schemas.insert({ std::to_string(userId), dbSchema }); } @@ -255,6 +262,7 @@ int32_t KVDBGeneralStore::Bind(const Database &database, const std::map lock(rwMutex_); if (delegate_ == nullptr) { return GeneralError::E_ALREADY_CLOSED; @@ -321,8 +329,8 @@ int32_t KVDBGeneralStore::Replace(const std::string &table, VBucket &&value) return GeneralError::E_NOT_SUPPORT; } -std::pair> KVDBGeneralStore::Query(__attribute__((unused)) const std::string &table, - const std::string &sql, Values &&args) +std::pair> KVDBGeneralStore::Query( + __attribute__((unused)) const std::string &table, const std::string &sql, Values &&args) { return { GeneralError::E_NOT_SUPPORT, nullptr }; } @@ -372,7 +380,11 @@ DBStatus KVDBGeneralStore::CloudSync(const Devices &devices, DistributedDB::Sync syncOption.lockAction = DistributedDB::LockAction::NONE; if (storeInfo_.user == 0) { std::vector users; - AccountDelegate::GetInstance()->QueryUsers(users); + auto ret = AccountDelegate::GetInstance()->QueryUsers(users); + if (!ret || users.empty()) { + ZLOGE("failed to query os accounts, ret:%{public}d", ret); + return DBStatus::DB_ERROR; + } syncOption.users.push_back(std::to_string(users[0])); } else { syncOption.users.push_back(std::to_string(storeInfo_.user)); @@ -431,11 +443,9 @@ std::pair KVDBGeneralStore::Sync(const Devices &devices, GenQu dbStatus = delegate_->UnSubscribeRemoteQuery(devices, GetDBSyncCompleteCB(std::move(async)), dbQuery, false); } else if (syncMode < NEARBY_END) { - if (kvQuery->IsEmpty()) { - dbStatus = delegate_->Sync(devices, dbMode, GetDBSyncCompleteCB(std::move(async)), false); - } else { - dbStatus = delegate_->Sync(devices, dbMode, GetDBSyncCompleteCB(std::move(async)), dbQuery, false); - } + DeviceSyncOption syncOption = { .devices = devices, .mode = dbMode, .query = dbQuery, .isWait = false, + .isRetry = syncParam.isRetry }; + dbStatus = delegate_->Sync(syncOption, GetDBSyncCompleteCB(std::move(async))); } else { ZLOGE("Err sync mode! sync mode:%{public}d", syncMode); dbStatus = DistributedDB::INVALID_ARGS; @@ -465,22 +475,24 @@ void KVDBGeneralStore::SetEqualIdentifier(const std::string &appId, const std::s auto accountId = account.empty() ? AccountDelegate::GetInstance()->GetUnencryptedAccountId() : account; auto convertedIds = AppIdMappingConfigManager::GetInstance().Convert(appId, accountId); auto identifier = KvManager::GetKvStoreIdentifier(convertedIds.second, convertedIds.first, storeId); - ZLOGI("same account store:%{public}s, user:%{public}s, device:%{public}.10s, appId:%{public}s", + ZLOGI("same account store:%{public}s, user:%{public}s, device:%{public}s, appId:%{public}s", Anonymous::Change(storeId).c_str(), Anonymous::Change(convertedIds.second).c_str(), - DistributedData::Serializable::Marshall(sameAccountDevs).c_str(), convertedIds.first.c_str()); + Anonymous::Change(DistributedData::Serializable::Marshall(sameAccountDevs)).c_str(), + convertedIds.first.c_str()); delegate_->SetEqualIdentifier(identifier, sameAccountDevs); } if (!defaultAccountDevs.empty()) { auto convertedIds = AppIdMappingConfigManager::GetInstance().Convert(appId, defaultAccountId); auto identifier = KvManager::GetKvStoreIdentifier(convertedIds.second, convertedIds.first, storeId); - ZLOGI("no account store:%{public}s, device:%{public}.10s, appId:%{public}s", Anonymous::Change(storeId).c_str(), - DistributedData::Serializable::Marshall(defaultAccountDevs).c_str(), convertedIds.first.c_str()); + ZLOGI("no account store:%{public}s, device:%{public}s, appId:%{public}s", Anonymous::Change(storeId).c_str(), + Anonymous::Change(DistributedData::Serializable::Marshall(defaultAccountDevs)).c_str(), + convertedIds.first.c_str()); delegate_->SetEqualIdentifier(identifier, defaultAccountDevs); } } -void KVDBGeneralStore::GetIdentifierParams(std::vector &devices, const std::vector &uuids, - int32_t authType) +void KVDBGeneralStore::GetIdentifierParams( + std::vector &devices, const std::vector &uuids, int32_t authType) { for (const auto &devId : uuids) { if (DMAdapter::GetInstance().IsOHOSType(devId)) { @@ -511,14 +523,19 @@ int32_t KVDBGeneralStore::Clean(const std::vector &devices, int32_t return GeneralError::E_ALREADY_CLOSED; } DBStatus status = OK; + ClearKvMetaDataOption option; switch (mode) { case CLOUD_INFO: - status = delegate_->RemoveDeviceData("", - isPublic_ ? static_cast(CLOUD_DATA) : static_cast(CLOUD_INFO)); + status = delegate_->RemoveDeviceData( + "", isPublic_ ? static_cast(CLOUD_DATA) : static_cast(CLOUD_INFO)); break; case CLOUD_DATA: status = delegate_->RemoveDeviceData("", static_cast(CLOUD_DATA)); break; + case CLEAN_WATER: + option.type = ClearKvMetaOpType::CLEAN_CLOUD_WATERMARK; + status = delegate_->ClearMetaData(option); + break; case NEARBY_DATA: if (devices.empty()) { status = delegate_->RemoveDeviceData(); @@ -580,8 +597,8 @@ int32_t KVDBGeneralStore::AddRef() return ++ref_; } -int32_t KVDBGeneralStore::SetDistributedTables(const std::vector &tables, int32_t type, - const std::vector &references) +int32_t KVDBGeneralStore::SetDistributedTables( + const std::vector &tables, int32_t type, const std::vector &references) { return GeneralError::E_OK; } diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp index f04980cc..c497a128 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp @@ -27,7 +27,6 @@ #include "cloud/cloud_server.h" #include "communication_provider.h" #include "communicator_context.h" -#include "crypto_manager.h" #include "device_manager_adapter.h" #include "directory/directory_manager.h" #include "dump/dump_manager.h" @@ -40,6 +39,7 @@ #include "matrix_event.h" #include "metadata/appid_meta_data.h" #include "metadata/capability_meta_data.h" +#include "metadata/store_meta_data.h" #include "metadata/switches_meta_data.h" #include "permit_delegate.h" #include "query_helper.h" @@ -101,7 +101,7 @@ void KVDBServiceImpl::Init() auto process = [this](const Event &event) { const auto &evt = static_cast(event); const auto &storeInfo = evt.GetStoreInfo(); - StoreMetaData meta(storeInfo); + StoreMetaMapping meta(storeInfo); meta.deviceId = DMAdapter::GetInstance().GetLocalDevice().uuid; if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { if (meta.user == "0") { @@ -111,8 +111,8 @@ void KVDBServiceImpl::Init() } meta.user = "0"; StoreMetaDataLocal localMeta; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMeta, true) || !localMeta.isPublic || - !MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true) || + !MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMeta, true) || !localMeta.isPublic) { ZLOGE("meta empty, not public store. bundleName:%{public}s, storeId:%{public}s, user = %{public}s", meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), meta.user.c_str()); return; @@ -180,7 +180,7 @@ Status KVDBServiceImpl::GetStoreIds(const AppId &appId, int32_t subUser, std::ve Status KVDBServiceImpl::Delete(const AppId &appId, const StoreId &storeId, int32_t subUser) { - StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); + StoreMetaData metaData = LoadStoreMetaData(appId, storeId, subUser); if (metaData.instanceId < 0) { return ILLEGAL_STATE; } @@ -193,7 +193,9 @@ Status KVDBServiceImpl::Delete(const AppId &appId, const StoreId &storeId, int32 syncAgent.delayTimes_.erase(storeId); return true; }); - MetaDataManager::GetInstance().DelMeta(metaData.GetKey()); + StoreMetaMapping storeMetaMapping(metaData); + MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true); + MetaDataManager::GetInstance().DelMeta(metaData.GetKeyWithoutPath()); MetaDataManager::GetInstance().DelMeta(metaData.GetKey(), true); MetaDataManager::GetInstance().DelMeta(metaData.GetKeyLocal(), true); MetaDataManager::GetInstance().DelMeta(metaData.GetSecretKey(), true); @@ -202,8 +204,8 @@ Status KVDBServiceImpl::Delete(const AppId &appId, const StoreId &storeId, int32 MetaDataManager::GetInstance().DelMeta(metaData.GetAutoLaunchKey(), true); MetaDataManager::GetInstance().DelMeta(metaData.GetDebugInfoKey(), true); MetaDataManager::GetInstance().DelMeta(metaData.GetCloneSecretKey(), true); - PermitDelegate::GetInstance().DelCache(metaData.GetKey()); - AutoCache::GetInstance().CloseStore(metaData.tokenId, storeId, metaData.user); + PermitDelegate::GetInstance().DelCache(metaData.GetKeyWithoutPath()); + AutoCache::GetInstance().CloseStore(metaData.tokenId, metaData.dataDir); ZLOGD("appId:%{public}s storeId:%{public}s instanceId:%{public}d", appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), metaData.instanceId); return SUCCESS; @@ -211,11 +213,11 @@ Status KVDBServiceImpl::Delete(const AppId &appId, const StoreId &storeId, int32 Status KVDBServiceImpl::Close(const AppId &appId, const StoreId &storeId, int32_t subUser) { - StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); + StoreMetaData metaData = LoadStoreMetaData(appId, storeId, subUser); if (metaData.instanceId < 0) { return ILLEGAL_STATE; } - AutoCache::GetInstance().CloseStore(metaData.tokenId, storeId, metaData.user); + AutoCache::GetInstance().CloseStore(metaData.tokenId, metaData.dataDir, storeId); ZLOGD("appId:%{public}s storeId:%{public}s instanceId:%{public}d", appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), metaData.instanceId); return SUCCESS; @@ -223,7 +225,7 @@ Status KVDBServiceImpl::Close(const AppId &appId, const StoreId &storeId, int32_ Status KVDBServiceImpl::CloudSync(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo) { - StoreMetaData metaData = GetStoreMetaData(appId, storeId); + StoreMetaMapping metaData = GetStoreMetaData(appId, storeId); if (!MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true)) { ZLOGE("invalid, appId:%{public}s storeId:%{public}s", appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str()); @@ -243,8 +245,14 @@ void KVDBServiceImpl::OnAsyncComplete(uint32_t tokenId, uint64_t seqNum, Progres Status KVDBServiceImpl::Sync(const AppId &appId, const StoreId &storeId, int32_t subUser, SyncInfo &syncInfo) { + auto instanceId = GetInstIndex(IPCSkeleton::GetCallingTokenID(), appId); + if (instanceId != 0) { + ZLOGE("twin application not allow sync, instanceId:%{public}d, appId:%{public}s, storeId:%{public}s", + instanceId, appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str()); + return Status::NOT_SUPPORT; + } StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); - MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData); + MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData); auto delay = GetSyncDelayTime(syncInfo.delay, storeId, metaData.user); if (metaData.isAutoSync && syncInfo.seqId == std::numeric_limits::max()) { DeviceMatrix::GetInstance().OnChanged(metaData); @@ -269,7 +277,7 @@ Status KVDBServiceImpl::Sync(const AppId &appId, const StoreId &storeId, int32_t Status KVDBServiceImpl::NotifyDataChange(const AppId &appId, const StoreId &storeId, uint64_t delay) { StoreMetaData meta = GetStoreMetaData(appId, storeId); - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) { + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyWithoutPath(), meta)) { ZLOGE("invalid, appId:%{public}s storeId:%{public}s", appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str()); return Status::INVALID_ARGUMENT; @@ -527,7 +535,7 @@ Status KVDBServiceImpl::AddSubscribeInfo(const AppId &appId, const StoreId &stor const SyncInfo &syncInfo) { StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); - MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData); + MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData); auto delay = GetSyncDelayTime(syncInfo.delay, storeId, metaData.user); return KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(metaData.tokenId), delay, std::bind(&KVDBServiceImpl::DoSyncInOrder, this, metaData, syncInfo, std::placeholders::_1, ACTION_SUBSCRIBE), @@ -538,7 +546,7 @@ Status KVDBServiceImpl::RmvSubscribeInfo(const AppId &appId, const StoreId &stor const SyncInfo &syncInfo) { StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); - MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData); + MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData); auto delay = GetSyncDelayTime(syncInfo.delay, storeId, metaData.user); return KvStoreSyncManager::GetInstance()->AddSyncOperation(uintptr_t(metaData.tokenId), delay, std::bind( @@ -552,7 +560,7 @@ Status KVDBServiceImpl::Subscribe(const AppId &appId, const StoreId &storeId, in if (observer == nullptr) { return INVALID_ARGUMENT; } - StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); + StoreMetaData metaData = LoadStoreMetaData(appId, storeId, subUser); ZLOGI("appId:%{public}s storeId:%{public}s tokenId:0x%{public}x", appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), metaData.tokenId); bool isCreate = false; @@ -568,8 +576,8 @@ Status KVDBServiceImpl::Subscribe(const AppId &appId, const StoreId &storeId, in return true; }); if (isCreate) { - AutoCache::GetInstance().SetObserver(metaData.tokenId, storeId, - GetWatchers(metaData.tokenId, storeId, metaData.user), metaData.user); + AutoCache::GetInstance().SetObserver(metaData.tokenId, + GetWatchers(metaData.tokenId, storeId, metaData.user), metaData.dataDir, storeId); } return SUCCESS; } @@ -577,7 +585,7 @@ Status KVDBServiceImpl::Subscribe(const AppId &appId, const StoreId &storeId, in Status KVDBServiceImpl::Unsubscribe(const AppId &appId, const StoreId &storeId, int32_t subUser, sptr observer) { - StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); + StoreMetaData metaData = LoadStoreMetaData(appId, storeId, subUser); ZLOGI("appId:%{public}s storeId:%{public}s tokenId:0x%{public}x", appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), metaData.tokenId); bool destroyed = false; @@ -600,40 +608,58 @@ Status KVDBServiceImpl::Unsubscribe(const AppId &appId, const StoreId &storeId, return true; }); if (destroyed) { - AutoCache::GetInstance().SetObserver(metaData.tokenId, storeId, - GetWatchers(metaData.tokenId, storeId, metaData.user), metaData.user); + AutoCache::GetInstance().SetObserver(metaData.tokenId, + GetWatchers(metaData.tokenId, storeId, metaData.user), metaData.dataDir, storeId); } return SUCCESS; } +std::vector KVDBServiceImpl::LoadSecretKey(const StoreMetaData &metaData, + CryptoManager::SecretKeyType secretKeyType) +{ + SecretKeyMetaData secretKey; + std::string metaKey; + if (secretKeyType == CryptoManager::SecretKeyType::LOCAL_SECRET_KEY) { + metaKey = metaData.GetSecretKey(); + } else if (secretKeyType == CryptoManager::SecretKeyType::CLONE_SECRET_KEY) { + metaKey = metaData.GetCloneSecretKey(); + } + if (!MetaDataManager::GetInstance().LoadMeta(metaKey, secretKey, true) || secretKey.sKey.empty()) { + return {}; + } + CryptoManager::CryptoParams decryptParams = { .area = secretKey.area, .userId = metaData.user, + .nonce = secretKey.nonce }; + auto password = CryptoManager::GetInstance().Decrypt(secretKey.sKey, decryptParams); + if (password.empty()) { + return {}; + } + // update secret key of area or nonce + CryptoManager::GetInstance().UpdateSecretMeta(password, metaData, metaKey, secretKey); + return password; +} + Status KVDBServiceImpl::GetBackupPassword(const AppId &appId, const StoreId &storeId, int32_t subUser, std::vector> &passwords, int32_t passwordType) { - StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); + StoreMetaData metaData = LoadStoreMetaData(appId, storeId, subUser); if (passwordType == KVDBService::PasswordType::BACKUP_SECRET_KEY) { - std::vector backupPwd; - bool res = BackupManager::GetInstance().GetPassWord(metaData, backupPwd); - if (res) { - passwords.emplace_back(backupPwd); + auto backupPwd = BackupManager::GetInstance().GetPassWord(metaData); + if (backupPwd.empty()) { + return ERROR; } + passwords.emplace_back(backupPwd); backupPwd.assign(backupPwd.size(), 0); - return res ? SUCCESS : ERROR; + return SUCCESS; } if (passwordType == KVDBService::PasswordType::SECRET_KEY) { passwords.reserve(SECRET_KEY_COUNT); - SecretKeyMetaData secretKey; - std::vector password; - if (MetaDataManager::GetInstance().LoadMeta(metaData.GetSecretKey(), secretKey, true) && - CryptoManager::GetInstance().Decrypt(metaData, secretKey, password)) { + auto password = LoadSecretKey(metaData, CryptoManager::SecretKeyType::LOCAL_SECRET_KEY); + if (!password.empty()) { passwords.emplace_back(password); - password.assign(password.size(), 0); } - - std::vector clonePwd; - if (MetaDataManager::GetInstance().LoadMeta(metaData.GetCloneSecretKey(), secretKey, true) && - CryptoManager::GetInstance().Decrypt(metaData, secretKey, clonePwd, CryptoManager::CLONE_SECRET_KEY)) { - passwords.emplace_back(clonePwd); - clonePwd.assign(clonePwd.size(), 0); + auto clonePassword = LoadSecretKey(metaData, CryptoManager::SecretKeyType::CLONE_SECRET_KEY); + if (!clonePassword.empty()) { + passwords.emplace_back(clonePassword); } return passwords.size() > 0 ? SUCCESS : ERROR; } @@ -645,6 +671,9 @@ Status KVDBServiceImpl::GetBackupPassword(const AppId &appId, const StoreId &sto Status KVDBServiceImpl::SetConfig(const AppId &appId, const StoreId &storeId, const StoreConfig &storeConfig) { StoreMetaData meta = GetStoreMetaData(appId, storeId); + StoreMetaMapping storeMetaMapping(meta); + MetaDataManager::GetInstance().LoadMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); + meta.dataDir = storeMetaMapping.dataDir; auto isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true); if (!isCreated) { return SUCCESS; @@ -654,15 +683,19 @@ Status KVDBServiceImpl::SetConfig(const AppId &appId, const StoreId &storeId, co if (!MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true)) { return Status::ERROR; } + storeMetaMapping = meta; + if (!MetaDataManager::GetInstance().SaveMeta(storeMetaMapping.GetKey(), storeMetaMapping, true)) { + return Status::ERROR; + } StoreMetaData syncMeta; - if (MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), syncMeta)) { + if (MetaDataManager::GetInstance().LoadMeta(meta.GetKeyWithoutPath(), syncMeta)) { syncMeta.enableCloud = storeConfig.cloudConfig.enableCloud; syncMeta.cloudAutoSync = storeConfig.cloudConfig.autoSync; - if (!MetaDataManager::GetInstance().SaveMeta(syncMeta.GetKey(), syncMeta)) { + if (!MetaDataManager::GetInstance().SaveMeta(syncMeta.GetKeyWithoutPath(), syncMeta)) { return Status::ERROR; } } - auto stores = AutoCache::GetInstance().GetStoresIfPresent(meta.tokenId, storeId, meta.user); + auto stores = AutoCache::GetInstance().GetStoresIfPresent(meta.tokenId, meta.dataDir, storeId); for (auto store : stores) { store->SetConfig({ storeConfig.cloudConfig.enableCloud }); } @@ -678,8 +711,8 @@ Status KVDBServiceImpl::BeforeCreate(const AppId &appId, const StoreId &storeId, StoreMetaData meta = GetStoreMetaData(appId, storeId, options.subUser); AddOptions(options, meta); - StoreMetaData old; - auto isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), old, true); + StoreMetaMapping old(meta); + auto isCreated = MetaDataManager::GetInstance().LoadMeta(old.GetKey(), old, true); if (!isCreated) { return SUCCESS; } @@ -717,6 +750,35 @@ Status KVDBServiceImpl::BeforeCreate(const AppId &appId, const StoreId &storeId, return dbStatus == DBStatus::OK ? SUCCESS : DB_ERROR; } +void KVDBServiceImpl::SaveSecretKeyMeta(const StoreMetaData &metaData, const std::vector &password) +{ + CryptoManager::CryptoParams encryptParams = { .area = metaData.area, .userId = metaData.user }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(password, encryptParams); + if (!encryptKey.empty() && !encryptParams.nonce.empty()) { + SecretKeyMetaData secretKey; + secretKey.storeType = metaData.storeType; + secretKey.area = metaData.area; + secretKey.sKey = encryptKey; + secretKey.nonce = encryptParams.nonce; + auto time = system_clock::to_time_t(system_clock::now()); + secretKey.time = { reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time) }; + MetaDataManager::GetInstance().SaveMeta(metaData.GetSecretKey(), secretKey, true); + } + SecretKeyMetaData cloneKey; + auto metaKey = metaData.GetCloneSecretKey(); + // update clone secret key with area + if (MetaDataManager::GetInstance().LoadMeta(metaKey, cloneKey, true) && !cloneKey.sKey.empty() && + (cloneKey.nonce.empty() || cloneKey.area < 0)) { + CryptoManager::CryptoParams decryptParams = { .area = cloneKey.area, .userId = metaData.user, + .nonce = cloneKey.nonce }; + auto clonePassword = CryptoManager::GetInstance().Decrypt(cloneKey.sKey, decryptParams); + if (!clonePassword.empty()) { + CryptoManager::GetInstance().UpdateSecretMeta(clonePassword, metaData, metaKey, cloneKey); + } + clonePassword.assign(clonePassword.size(), 0); + } +} + Status KVDBServiceImpl::AfterCreate( const AppId &appId, const StoreId &storeId, const Options &options, const std::vector &password) { @@ -729,15 +791,16 @@ Status KVDBServiceImpl::AfterCreate( StoreMetaData metaData = GetStoreMetaData(appId, storeId, options.subUser); AddOptions(options, metaData); - StoreMetaData oldMeta; - auto isCreated = MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), oldMeta, true); + StoreMetaMapping oldMeta(metaData); + auto isCreated = MetaDataManager::GetInstance().LoadMeta(oldMeta.GetKey(), oldMeta, true); Status status = SUCCESS; if (isCreated && oldMeta != metaData) { auto dbStatus = Upgrade::GetInstance().UpdateStore(oldMeta, metaData, password); ZLOGI("update status:%{public}d appId:%{public}s storeId:%{public}s inst:%{public}d " "type:%{public}d->%{public}d dir:%{public}s dataType:%{public}d->%{public}d", dbStatus, appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), metaData.instanceId, - oldMeta.storeType, metaData.storeType, metaData.dataDir.c_str(), oldMeta.dataType, metaData.dataType); + oldMeta.storeType, metaData.storeType, Anonymous::Change(metaData.dataDir).c_str(), + oldMeta.dataType, metaData.dataType); if (dbStatus != DBStatus::OK) { status = STORE_UPGRADE_FAILED; } @@ -745,28 +808,25 @@ Status KVDBServiceImpl::AfterCreate( if (!isCreated || oldMeta != metaData) { if (!CheckerManager::GetInstance().IsDistrust(Converter::ConvertToStoreInfo(metaData))) { - MetaDataManager::GetInstance().SaveMeta(metaData.GetKey(), metaData); + MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyWithoutPath(), metaData); } MetaDataManager::GetInstance().SaveMeta(metaData.GetKey(), metaData, true); + oldMeta = metaData; + MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKey(), oldMeta, true); } AppIDMetaData appIdMeta; appIdMeta.bundleName = metaData.bundleName; appIdMeta.appId = metaData.appId; MetaDataManager::GetInstance().SaveMeta(appIdMeta.GetKey(), appIdMeta, true); SaveLocalMetaData(options, metaData); - if (metaData.isEncrypt && CryptoManager::GetInstance().UpdateSecretKey(metaData, password)) { - SecretKeyMetaData secretKey; - if (MetaDataManager::GetInstance().LoadMeta(metaData.GetCloneSecretKey(), secretKey, true) && - secretKey.area < 0) { - std::vector clonePwd; - // Update the encryption method for the key - CryptoManager::GetInstance().Decrypt(metaData, secretKey, clonePwd, CryptoManager::CLONE_SECRET_KEY); - clonePwd.assign(clonePwd.size(), 0); - } + + if (metaData.isEncrypt && !password.empty()) { + SaveSecretKeyMeta(metaData, password); } ZLOGI("appId:%{public}s storeId:%{public}s instanceId:%{public}d type:%{public}d dir:%{public}s " "isCreated:%{public}d dataType:%{public}d", appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), - metaData.instanceId, metaData.storeType, metaData.dataDir.c_str(), isCreated, metaData.dataType); + metaData.instanceId, metaData.storeType, Anonymous::Change(metaData.dataDir).c_str(), isCreated, + metaData.dataType); return status; } @@ -801,10 +861,9 @@ bool KVDBServiceImpl::CompareTripleIdentifier(const std::string &accountId, cons { std::vector accountIds { accountId, "ohosAnonymousUid", "default" }; for (auto &id : accountIds) { - auto convertedIds = - AppIdMappingConfigManager::GetInstance().Convert(storeMeta.appId, storeMeta.user); + auto appId = AppIdMappingConfigManager::GetInstance().Convert(storeMeta.appId); const std::string &tempTripleIdentifier = - DistributedDB::KvStoreDelegateManager::GetKvStoreIdentifier(id, convertedIds.first, + DistributedDB::KvStoreDelegateManager::GetKvStoreIdentifier(id, appId, storeMeta.storeId, false); if (tempTripleIdentifier == identifier) { ZLOGI("find triple identifier,storeId:%{public}s,id:%{public}s", @@ -917,6 +976,14 @@ void KVDBServiceImpl::SaveLocalMetaData(const Options &options, const StoreMetaD MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyLocal(), localMetaData, true); } +StoreMetaData KVDBServiceImpl::LoadStoreMetaData(const AppId &appId, const StoreId &storeId, int32_t subUser) +{ + StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); + StoreMetaMapping storeMetaMapping(metaData); + MetaDataManager::GetInstance().LoadMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); + return storeMetaMapping; +} + StoreMetaData KVDBServiceImpl::GetStoreMetaData(const AppId &appId, const StoreId &storeId, int32_t subUser) { StoreMetaData metaData; @@ -979,7 +1046,8 @@ Status KVDBServiceImpl::DoCloudSync(const StoreMetaData &meta, const SyncInfo &s if (instance == nullptr) { return Status::CLOUD_DISABLED; } - if (!NetworkDelegate::GetInstance()->IsNetworkAvailable()) { + auto network = NetworkDelegate::GetInstance(); + if (network == nullptr || !network->IsNetworkAvailable()) { return Status::NETWORK_ERROR; } std::vector users; @@ -1003,6 +1071,7 @@ Status KVDBServiceImpl::DoCloudSync(const StoreMetaData &meta, const SyncInfo &s storeInfo.user = atoi(meta.user.c_str()); storeInfo.tokenId = meta.tokenId; storeInfo.storeName = meta.storeId; + storeInfo.path = meta.dataDir; GenAsync syncCallback = [tokenId = storeInfo.tokenId, seqId = syncInfo.seqId, this](const GenDetails &details) { OnAsyncComplete(tokenId, seqId, HandleGenDetails(details)); }; @@ -1058,7 +1127,7 @@ Status KVDBServiceImpl::DoSyncInOrder( auto status = DoSyncBegin(ret.first, meta, info, complete, type); ZLOGD("data sync status:%{public}d appId:%{public}s, storeId:%{public}s", static_cast(status), meta.bundleName.c_str(), Anonymous::Change(meta.storeId).c_str()); - }); + }, false, info.isRetry); if (!result) { RADAR_REPORT(STANDARD_DEVICE_SYNC, STANDARD_META_SYNC, RADAR_FAILED, ERROR_CODE, Status::ERROR, BIZ_STATE, END, SYNC_STORE_ID, Anonymous::Change(meta.storeId), SYNC_APP_ID, meta.bundleName, @@ -1081,7 +1150,7 @@ bool KVDBServiceImpl::IsNeedMetaSync(const StoreMetaData &meta, const std::vecto if ((!MetaDataManager::GetInstance().LoadMeta(std::string(capKey.begin(), capKey.end()), capMeta) && !(devInfo.osType != OH_OS_TYPE && devInfo.deviceType == static_cast(DistributedHardware::DmDeviceType::DEVICE_TYPE_CAR))) || - !MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData)) { + !MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)) { isAfterMeta = true; break; } @@ -1106,7 +1175,7 @@ StoreMetaData KVDBServiceImpl::GetDistributedDataMeta(const std::string &deviceI meta.bundleName = Bootstrap::GetInstance().GetProcessLabel(); meta.storeId = Bootstrap::GetInstance().GetMetaDBName(); meta.user = DEFAULT_USER_ID; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) { + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyWithoutPath(), meta)) { ZLOGE("Load meta fail, device: %{public}s", Anonymous::Change(deviceId).c_str()); } return meta; @@ -1141,7 +1210,7 @@ Status KVDBServiceImpl::DoSyncBegin(const std::vector &devices, con if (store == nullptr) { ZLOGE("GetStore failed! appId:%{public}s storeId:%{public}s storeId length:%{public}zu dir:%{public}s", meta.bundleName.c_str(), Anonymous::Change(meta.storeId).c_str(), - meta.storeId.size(), meta.dataDir.c_str()); + meta.storeId.size(), Anonymous::Change(meta.dataDir).c_str()); RADAR_REPORT(STANDARD_DEVICE_SYNC, OPEN_STORE, RADAR_FAILED, ERROR_CODE, Status::ERROR, BIZ_STATE, END, SYNC_STORE_ID, Anonymous::Change(meta.storeId), SYNC_APP_ID, meta.bundleName, CONCURRENT_ID, std::to_string(info.syncId), DATA_TYPE, meta.dataType); @@ -1160,15 +1229,14 @@ Status KVDBServiceImpl::DoSyncBegin(const std::vector &devices, con } SyncParam syncParam{}; syncParam.mode = mode; + syncParam.isRetry = info.isRetry; RADAR_REPORT(STANDARD_DEVICE_SYNC, START_SYNC, RADAR_START, SYNC_STORE_ID, Anonymous::Change(meta.storeId), SYNC_APP_ID, meta.bundleName, CONCURRENT_ID, std::to_string(info.syncId), DATA_TYPE, meta.dataType); - auto ret = store->Sync( - devices, query, + auto ret = store->Sync(devices, query, [this, complete](const GenDetails &result) mutable { auto deviceStatus = HandleGenBriefDetails(result); complete(deviceStatus); - }, - syncParam); + }, syncParam); auto status = Status(ret.first); if (status != Status::SUCCESS) { RADAR_REPORT(STANDARD_DEVICE_SYNC, START_SYNC, RADAR_FAILED, ERROR_CODE, status, BIZ_STATE, END, @@ -1488,12 +1556,12 @@ Status KVDBServiceImpl::RemoveDeviceData(const AppId &appId, const StoreId &stor const std::string &device) { StoreMetaData metaData = GetStoreMetaData(appId, storeId, subUser); - MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData); + MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData); auto watcher = GetWatchers(metaData.tokenId, metaData.storeId, metaData.user); auto store = AutoCache::GetInstance().GetStore(metaData, watcher); if (store == nullptr) { ZLOGE("GetStore failed! appId:%{public}s storeId:%{public}s dir:%{public}s", metaData.bundleName.c_str(), - Anonymous::Change(metaData.storeId).c_str(), metaData.dataDir.c_str()); + Anonymous::Change(metaData.storeId).c_str(), Anonymous::Change(metaData.dataDir).c_str()); return Status::ERROR; } diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h index 4604f8b5..dd185700 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h @@ -19,6 +19,7 @@ #include #include "concurrent_map.h" +#include "crypto/crypto_manager.h" #include "device_matrix.h" #include "kv_store_delegate_manager.h" #include "kv_store_nb_delegate.h" @@ -95,6 +96,7 @@ private: using DBMode = DistributedDB::SyncMode; using Action = OHOS::DistributedData::MetaDataManager::Action; using GeneralError = DistributedData::GeneralError; + using CryptoManager = DistributedData::CryptoManager; enum SyncAction { ACTION_SYNC, ACTION_SUBSCRIBE, @@ -123,6 +125,7 @@ private: void Init(); void AddOptions(const Options &options, StoreMetaData &metaData); StoreMetaData GetStoreMetaData(const AppId &appId, const StoreId &storeId, int32_t subUser = 0); + StoreMetaData LoadStoreMetaData(const AppId &appId, const StoreId &storeId, int32_t subUser = 0); StoreMetaData GetDistributedDataMeta(const std::string &deviceId); StrategyMeta GetStrategyMeta(const AppId &appId, const StoreId &storeId, int32_t subUser = 0); int32_t GetInstIndex(uint32_t tokenId, const AppId &appId); @@ -161,6 +164,8 @@ private: bool CompareTripleIdentifier(const std::string &accountId, const std::string &identifier, const StoreMetaData &storeMeta); std::string GenerateKey(const std::string &userId, const std::string &storeId) const; + std::vector LoadSecretKey(const StoreMetaData &metaData, CryptoManager::SecretKeyType secretKeyType); + void SaveSecretKeyMeta(const StoreMetaData &metaData, const std::vector &password); static Factory factory_; ConcurrentMap syncAgents_; std::shared_ptr executors_; diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp index 37de8906..acfa5fbd 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp @@ -22,6 +22,10 @@ #include "utils/constant.h" namespace OHOS::DistributedKv { using namespace OHOS::DistributedData; +static constexpr const char *SLASH = "/"; +static constexpr const char *BACK_SLASH = "\\"; +static constexpr const char *POINT = ".."; + const KVDBServiceStub::Handler KVDBServiceStub::HANDLERS[static_cast(KVDBServiceInterfaceCode::TRANS_BUTT)] = { &KVDBServiceStub::OnGetStoreIds, @@ -141,6 +145,9 @@ int32_t KVDBServiceStub::OnBeforeCreate( Anonymous::Change(storeId.storeId).c_str()); return IPC_STUB_INVALID_DATA_ERR; } + if (!IsValidField(appId.appId) || !IsValidField(storeId.storeId) || !IsValidField(options.hapName)) { + return IPC_STUB_INVALID_DATA_ERR; + } int32_t status = BeforeCreate(appId, storeId, options); if (!ITypesUtil::Marshal(reply, status)) { ZLOGE("Marshal status:0x%{public}x appId:%{public}s storeId:%{public}s", status, appId.appId.c_str(), @@ -160,6 +167,9 @@ int32_t KVDBServiceStub::OnAfterCreate( Anonymous::Change(storeId.storeId).c_str()); return IPC_STUB_INVALID_DATA_ERR; } + if (!IsValidField(appId.appId) || !IsValidField(storeId.storeId) || !IsValidField(options.hapName)) { + return IPC_STUB_INVALID_DATA_ERR; + } int32_t status = AfterCreate(appId, storeId, options, password); password.assign(password.size(), 0); if (!ITypesUtil::Marshal(reply, status)) { @@ -209,7 +219,7 @@ int32_t KVDBServiceStub::OnSync(const AppId &appId, const StoreId &storeId, Mess SyncInfo syncInfo; int32_t subUser; if (!ITypesUtil::Unmarshal(data, syncInfo.seqId, syncInfo.mode, syncInfo.devices, syncInfo.delay, syncInfo.query, - subUser)) { + subUser, syncInfo.isRetry)) { ZLOGE("Unmarshal appId:%{public}s storeId:%{public}s", appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str()); return IPC_STUB_INVALID_DATA_ERR; @@ -579,4 +589,13 @@ int32_t KVDBServiceStub::OnRemoveDeviceData(const AppId &appId, const StoreId &s } return ERR_NONE; } + +bool KVDBServiceStub::IsValidField(const std::string ¶m) +{ + if ((param.find(SLASH) != std::string::npos) || (param.find(BACK_SLASH) != std::string::npos) || (param == POINT)) { + ZLOGE("check failed, param is: %{public}s", Anonymous::Change(param).c_str()); + return false; + } + return true; +} } // namespace OHOS::DistributedKv diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h index f26cb7c8..ab87da37 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h @@ -62,6 +62,7 @@ private: bool CheckPermission(uint32_t code, const StoreInfo &storeInfo); std::pair GetStoreInfo(uint32_t code, MessageParcel &data); + bool IsValidField(const std::string ¶m); }; } // namespace OHOS::DistributedKv #endif // OHOS_DISTRIBUTED_DATA_SERVICE_KVDB_SERVICE_STUB_H diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/query_helper.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/query_helper.cpp index f877df1f..c1bd2d6c 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/query_helper.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/query_helper.cpp @@ -21,6 +21,7 @@ #include "kvstore_utils.h" #include "log_print.h" #include "types.h" +#include "utils/anonymous.h" namespace OHOS::DistributedKv { constexpr int QUERY_SKIP_SIZE = 1; constexpr int QUERY_WORD_SIZE = 2; @@ -559,7 +560,7 @@ bool QueryHelper::HandleInKeys(const std::vector &words, int &point const std::vector inKeys = GetStringList(words, inkeyOffSet, end); std::set> inDbKeys; for (const std::string &inKey : inKeys) { - ZLOGI("inKey=%{public}s", inKey.c_str()); + ZLOGI("inKey=%{public}s", DistributedData::Anonymous::Change(inKey).c_str()); std::vector dbKey; dbKey.assign(inKey.begin(), inKey.end()); inDbKeys.insert(dbKey); diff --git a/datamgr_service/services/distributeddataservice/service/matrix/BUILD.gn b/datamgr_service/services/distributeddataservice/service/matrix/BUILD.gn index 3499cbe6..88c1d03a 100644 --- a/datamgr_service/services/distributeddataservice/service/matrix/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/matrix/BUILD.gn @@ -35,7 +35,6 @@ ohos_source_set("distributeddata_matrix") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ @@ -50,7 +49,6 @@ ohos_source_set("distributeddata_matrix") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ @@ -61,6 +59,7 @@ ohos_source_set("distributeddata_matrix") { "device_manager:devicemanagersdk", "hilog:libhilog", "json:nlohmann_json_static", + "c_utils:utils", "kv_store:datamgr_common", ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/service/object/BUILD.gn b/datamgr_service/services/distributeddataservice/service/object/BUILD.gn index 29056fe0..b5bba90b 100644 --- a/datamgr_service/services/distributeddataservice/service/object/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/object/BUILD.gn @@ -18,6 +18,7 @@ config("object_public_config") { include_dirs = [ "${data_service_path}/service/common", + "${data_service_path}/service/matrix/include", "${data_service_path}/adapter/include/communicator", "${data_service_path}/adapter/include/utils", ] @@ -49,7 +50,6 @@ ohos_source_set("distributeddata_object") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ "include" ] @@ -62,7 +62,6 @@ ohos_source_set("distributeddata_object") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ @@ -77,6 +76,8 @@ ohos_source_set("distributeddata_object") { "dfs_service:cloudsync_asset_kit_inner", "dfs_service:distributed_file_daemon_kit_inner", "dmsfwk:distributed_sdk", + "hilog:libhilog", + "ipc:ipc_single", "hisysevent:libhisysevent", "kv_store:datamgr_common", "kv_store:distributeddb", diff --git a/datamgr_service/services/distributeddataservice/service/object/include/object_asset_loader.h b/datamgr_service/services/distributeddataservice/service/object/include/object_asset_loader.h index 44d3f8ab..160539fa 100644 --- a/datamgr_service/services/distributeddataservice/service/object/include/object_asset_loader.h +++ b/datamgr_service/services/distributeddataservice/service/object/include/object_asset_loader.h @@ -41,7 +41,7 @@ public: class ObjectAssetLoader { public: - static ObjectAssetLoader *GetInstance(); + static ObjectAssetLoader &GetInstance(); void SetThreadPool(std::shared_ptr executors); bool Transfer(const int32_t userId, const std::string& bundleName, const std::string& deviceId, const DistributedData::Asset& asset); diff --git a/datamgr_service/services/distributeddataservice/service/object/include/object_asset_machine.h b/datamgr_service/services/distributeddataservice/service/object/include/object_asset_machine.h index 14283191..273c781e 100644 --- a/datamgr_service/services/distributeddataservice/service/object/include/object_asset_machine.h +++ b/datamgr_service/services/distributeddataservice/service/object/include/object_asset_machine.h @@ -50,12 +50,8 @@ struct DFAAction { class ObjectAssetMachine { public: - ObjectAssetMachine(); - static int32_t DFAPostEvent(AssetEvent eventId, ChangedAssetInfo& changedAsset, Asset& asset, const std::pair& newAsset = std::pair()); - -private: }; } // namespace DistributedObject } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/object/include/object_callback_proxy.h b/datamgr_service/services/distributeddataservice/service/object/include/object_callback_proxy.h index e2990849..fabd1494 100644 --- a/datamgr_service/services/distributeddataservice/service/object/include/object_callback_proxy.h +++ b/datamgr_service/services/distributeddataservice/service/object/include/object_callback_proxy.h @@ -80,6 +80,20 @@ public: private: static inline BrokerDelegator delegator_; }; + +class ObjectProgressCallbackProxyBroker : public IObjectProgressCallback, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedObject.IObjectProgressCallback"); +}; + +class ObjectProgressCallbackProxy : public IRemoteProxy { +public: + explicit ObjectProgressCallbackProxy(const sptr &impl); + ~ObjectProgressCallbackProxy() = default; + void Completed(int32_t progress) override; +private: + static inline BrokerDelegator delegator_; +}; } // namespace DistributedObject } // namespace OHOS #endif // DISTRIBUTEDDATAMGR_OBJECT_CALLBACK_PROXY_H diff --git a/datamgr_service/services/distributeddataservice/service/object/include/object_data_listener.h b/datamgr_service/services/distributeddataservice/service/object/include/object_data_listener.h index 3c1bfdea..7c3140c7 100644 --- a/datamgr_service/services/distributeddataservice/service/object/include/object_data_listener.h +++ b/datamgr_service/services/distributeddataservice/service/object/include/object_data_listener.h @@ -38,6 +38,9 @@ public: const std::string &dstBundleName) override; int32_t OnFinished(const std::string &srcNetworkId, const sptr &assetObj, int32_t result) override; + int32_t OnRecvProgress(const std::string &srcNetworkId, + const sptr &assetObj, + uint64_t totalBytes, uint64_t processBytes) override; }; } // namespace DistributedObject } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/object/include/object_manager.h b/datamgr_service/services/distributeddataservice/service/object/include/object_manager.h index 2f4f6302..85dd8134 100644 --- a/datamgr_service/services/distributeddataservice/service/object/include/object_manager.h +++ b/datamgr_service/services/distributeddataservice/service/object/include/object_manager.h @@ -21,6 +21,7 @@ #include "device_manager_adapter.h" #include "kv_store_delegate_manager.h" #include "kvstore_sync_callback.h" +#include "metadata/store_meta_data.h" #include "object_asset_loader.h" #include "object_callback.h" #include "object_callback_proxy.h" @@ -64,6 +65,7 @@ class ObjectStoreManager { public: using DmAdaper = OHOS::DistributedData::DeviceManagerAdapter; using UriToSnapshot = std::shared_ptr>>; + using StoreMetaData = OHOS::DistributedData::StoreMetaData; enum RestoreStatus : int32_t { NONE = 0, @@ -76,9 +78,9 @@ public: ObjectStoreManager(); ~ObjectStoreManager(); - static ObjectStoreManager *GetInstance() + static ObjectStoreManager &GetInstance() { - static ObjectStoreManager *manager = new ObjectStoreManager(); + static ObjectStoreManager manager; return manager; } int32_t Save(const std::string &appId, const std::string &sessionId, const ObjectRecord &data, @@ -89,18 +91,21 @@ public: sptr callback, uint32_t tokenId); void SetData(const std::string &dataDir, const std::string &userId); int32_t Clear(); + int32_t InitUserMeta(); int32_t DeleteByAppId(const std::string &appId, int32_t user); void RegisterRemoteCallback(const std::string &bundleName, const std::string &sessionId, - pid_t pid, uint32_t tokenId, - sptr callback); + pid_t pid, uint32_t tokenId, sptr callback); void UnregisterRemoteCallback(const std::string &bundleName, pid_t pid, uint32_t tokenId, - const std::string &sessionId = ""); - void NotifyChange(ObjectRecord &changedData); + const std::string &sessionId = ""); + void RegisterProgressObserverCallback(const std::string &bundleName, const std::string &sessionId, + pid_t pid, uint32_t tokenId, sptr callback); + void UnregisterProgressObserverCallback(const std::string &bundleName, pid_t pid, uint32_t tokenId, + const std::string &sessionId = ""); + void NotifyChange(const ObjectRecord &changedData); void NotifyAssetsReady(const std::string& objectKey, const std::string& bundleName, const std::string& srcNetworkId = ""); void NotifyAssetsStart(const std::string& objectKey, const std::string& srcNetworkId = ""); - void CloseAfterMinute(); - int32_t Open(); + void NotifyAssetsRecvProgress(const std::string& objectKey, int32_t progress); void SetThreadPool(std::shared_ptr executors); UriToSnapshot GetSnapShots(const std::string &bundleName, const std::string &storeName); int32_t BindAsset(const uint32_t tokenId, const std::string& appId, const std::string& sessionId, @@ -108,6 +113,8 @@ public: int32_t OnAssetChanged(const uint32_t tokenId, const std::string& appId, const std::string& sessionId, const std::string& deviceId, const ObjectStore::Asset& asset); void DeleteSnapshot(const std::string &bundleName, const std::string &sessionId); + int32_t AutoLaunchStore(); + bool UnRegisterAssetsLister(); private: constexpr static const char *SEPERATOR = "_"; constexpr static const char *TIME_REGEX = "_\\d{10}_p_"; @@ -128,10 +135,15 @@ private: std::map> observers_; bool operator<(const CallbackInfo &it_) const { - if (pid < it_.pid) { - return true; - } - return false; + return pid < it_.pid; + } + }; + struct ProgressCallbackInfo { + pid_t pid; + std::map> observers_; + bool operator<(const ProgressCallbackInfo &it_) const + { + return pid < it_.pid; } }; struct SaveInfo : DistributedData::Serializable { @@ -150,6 +162,7 @@ private: DistributedDB::KvStoreNbDelegate *OpenObjectKvStore(); void FlushClosedStore(); void Close(); + void ForceClose(); int32_t SetSyncStatus(bool status); int32_t SaveToStore(const std::string &appId, const std::string &sessionId, const std::string &toDeviceId, const ObjectRecord &data); @@ -162,6 +175,8 @@ private: void ProcessSyncCallback(const std::map &results, const std::string &appId, const std::string &sessionId, const std::string &deviceId); void SaveUserToMeta(); + bool IsNeedMetaSync(const StoreMetaData &meta, const std::vector &networkIds); + int32_t DoSync(const std::string &prefix, const std::vector &deviceList, uint64_t sequenceId); std::string GetCurrentUser(); void DoNotify(uint32_t tokenId, const CallbackInfo& value, const std::map& data, bool allReady); @@ -182,6 +197,8 @@ private: void PullAssets(const std::map& data, const SaveInfo& saveInfo); std::map GetObjectData(const ObjectRecord& changedData, SaveInfo& saveInfo, bool& hasAsset); + void CloseAfterMinute(); + int32_t Open(); inline std::string GetPropertyPrefix(const std::string &appId, const std::string &sessionId) { return appId + SEPERATOR + sessionId + SEPERATOR + DmAdaper::GetInstance().GetLocalDevice().udid + SEPERATOR; @@ -201,24 +218,26 @@ private: return std::string(USERID) + SEPERATOR + userId + SEPERATOR + appId + SEPERATOR + DmAdaper::GetInstance().GetLocalDevice().udid; }; - std::recursive_mutex kvStoreMutex_; - std::mutex mutex_; - DistributedDB::KvStoreDelegateManager *kvStoreDelegateManager_ = nullptr; + mutable std::shared_timed_mutex rwMutex_; + std::shared_ptr kvStoreDelegateManager_ = nullptr; DistributedDB::KvStoreNbDelegate *delegate_ = nullptr; - ObjectDataListener *objectDataListener_ = nullptr; + ObjectDataListener objectDataListener_; sptr objectAssetsRecvListener_ = nullptr; sptr objectAssetsSendListener_ = nullptr; - uint32_t syncCount_ = 0; + std::atomic syncCount_{ 0 }; std::string userId_; - std::atomic isSyncing_ = false; + std::atomic isSyncing_{ false }; ConcurrentMap callbacks_; + ConcurrentMap processCallbacks_; std::shared_ptr executors_; DistributedData::AssetBindInfo ConvertBindInfo(ObjectStore::AssetBindInfo& bindInfo); - VBucket ConvertVBucket(ObjectStore::ValuesBucket &vBucket); ConcurrentMap> snapshots_; // key:bundleName_sessionId ConcurrentMap bindSnapshots_; // key:bundleName_storeName ConcurrentMap restoreStatus_; // key:bundleName+sessionId ConcurrentMap objectTimer_; // key:bundleName+sessionId + ConcurrentMap assetsRecvProgress_; // key:bundleName+sessionId + std::map progressInfo_; + std::mutex progressMutex_; }; } // namespace DistributedObject } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/object/include/object_service_impl.h b/datamgr_service/services/distributeddataservice/service/object/include/object_service_impl.h index 437d49e9..98f0fcd6 100644 --- a/datamgr_service/services/distributeddataservice/service/object/include/object_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/object/include/object_service_impl.h @@ -17,6 +17,7 @@ #define DISTRIBUTEDDATASERVICE_OBJECT_SERVICE_H #include "feature/static_acts.h" +#include "metadata/store_meta_data.h" #include "object_manager.h" #include "object_service_stub.h" #include "visibility.h" @@ -37,10 +38,12 @@ public: int32_t RegisterDataObserver(const std::string &bundleName, const std::string &sessionId, sptr callback) override; int32_t UnregisterDataChangeObserver(const std::string &bundleName, const std::string &sessionId) override; + int32_t RegisterProgressObserver(const std::string &bundleName, const std::string &sessionId, + sptr callback) override; + int32_t UnregisterProgressObserver(const std::string &bundleName, const std::string &sessionId) override; int32_t DeleteSnapshot(const std::string &bundleName, const std::string &sessionId) override; int32_t IsBundleNameEqualTokenId( const std::string &bundleName, const std::string &sessionId, const uint32_t &tokenId); - void Clear(); int32_t ResolveAutoLaunch(const std::string &identifier, DistributedDB::AutoLaunchParam ¶m) override; int32_t OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &appId) override; int32_t OnInitialize() override; @@ -68,8 +71,12 @@ private: }; void RegisterObjectServiceInfo(); void RegisterHandler(); + int32_t SaveMetaData(StoreMetaData& saveMeta); + void UpdateMetaData(); + static Factory factory_; std::shared_ptr executors_; + static constexpr int64_t WAIT_ACCOUNT_SERVICE = 5; }; } // namespace OHOS::DistributedObject #endif diff --git a/datamgr_service/services/distributeddataservice/service/object/include/object_service_stub.h b/datamgr_service/services/distributeddataservice/service/object/include/object_service_stub.h index fef5c7ec..e254a2bd 100644 --- a/datamgr_service/services/distributeddataservice/service/object/include/object_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/object/include/object_service_stub.h @@ -37,6 +37,8 @@ private: int32_t ObjectStoreBindAssetOnRemote(MessageParcel &data, MessageParcel &reply); int32_t OnDeleteSnapshot(MessageParcel &data, MessageParcel &reply); int32_t OnIsContinue(MessageParcel &data, MessageParcel &reply); + int32_t OnSubscribeProgress(MessageParcel &data, MessageParcel &reply); + int32_t OnUnsubscribeProgress(MessageParcel &data, MessageParcel &reply); using RequestHandle = int (ObjectServiceStub::*)(MessageParcel &, MessageParcel &); static constexpr RequestHandle HANDLERS[static_cast(ObjectCode::OBJECTSTORE_SERVICE_CMD_MAX)] = { &ObjectServiceStub::ObjectStoreSaveOnRemote, @@ -48,6 +50,8 @@ private: &ObjectServiceStub::ObjectStoreBindAssetOnRemote, &ObjectServiceStub::OnDeleteSnapshot, &ObjectServiceStub::OnIsContinue, + &ObjectServiceStub::OnSubscribeProgress, + &ObjectServiceStub::OnUnsubscribeProgress, }; }; } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/object/src/object_asset_loader.cpp b/datamgr_service/services/distributeddataservice/service/object/src/object_asset_loader.cpp index c3d582e6..efabc95b 100644 --- a/datamgr_service/services/distributeddataservice/service/object/src/object_asset_loader.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/src/object_asset_loader.cpp @@ -24,9 +24,10 @@ #include "distributed_file_daemon_manager.h" namespace OHOS::DistributedObject { using namespace OHOS::FileManagement::CloudSync; -ObjectAssetLoader *ObjectAssetLoader::GetInstance() +using namespace OHOS::DistributedData; +ObjectAssetLoader &ObjectAssetLoader::GetInstance() { - static ObjectAssetLoader *loader = new ObjectAssetLoader(); + static ObjectAssetLoader loader; return loader; } @@ -42,7 +43,7 @@ bool ObjectAssetLoader::Transfer(const int32_t userId, const std::string& bundle assetInfo.uri = asset.uri; assetInfo.assetName = asset.name; ZLOGI("Start transfer, bundleName: %{public}s, deviceId: %{public}s, assetName: %{public}s", bundleName.c_str(), - DistributedData::Anonymous::Change(deviceId).c_str(), assetInfo.assetName.c_str()); + Anonymous::Change(deviceId).c_str(), Anonymous::Change(assetInfo.assetName).c_str()); auto block = std::make_shared>>(WAIT_TIME, std::tuple{ true, OBJECT_SUCCESS }); auto res = CloudSyncAssetManager::GetInstance().DownloadFile(userId, bundleName, deviceId, assetInfo, [block](const std::string& uri, int32_t status) { @@ -50,17 +51,17 @@ bool ObjectAssetLoader::Transfer(const int32_t userId, const std::string& bundle }); if (res != OBJECT_SUCCESS) { ZLOGE("fail, res: %{public}d, name: %{public}s, deviceId: %{public}s, bundleName: %{public}s", res, - asset.name.c_str(), DistributedData::Anonymous::Change(deviceId).c_str(), bundleName.c_str()); + Anonymous::Change(asset.name).c_str(), Anonymous::Change(deviceId).c_str(), bundleName.c_str()); return false; } auto [timeout, status] = block->GetValue(); if (timeout || status != OBJECT_SUCCESS) { ZLOGE("fail, timeout: %{public}d, status: %{public}d, name: %{public}s, deviceId: %{public}s ", timeout, - status, asset.name.c_str(), DistributedData::Anonymous::Change(deviceId).c_str()); + status, Anonymous::Change(asset.name).c_str(), Anonymous::Change(deviceId).c_str()); return false; } ZLOGD("Transfer end, bundleName: %{public}s, deviceId: %{public}s, assetName: %{public}s", bundleName.c_str(), - DistributedData::Anonymous::Change(deviceId).c_str(), assetInfo.assetName.c_str()); + Anonymous::Change(deviceId).c_str(), Anonymous::Change(assetInfo.assetName).c_str()); return true; } @@ -69,7 +70,7 @@ void ObjectAssetLoader::TransferAssetsAsync(const int32_t userId, const std::str { if (executors_ == nullptr) { ZLOGE("executors is null, bundleName: %{public}s, deviceId: %{public}s, userId: %{public}d", - bundleName.c_str(), DistributedData::Anonymous::Change(deviceId).c_str(), userId); + bundleName.c_str(), Anonymous::Change(deviceId).c_str(), userId); callback(false); return; } @@ -148,7 +149,7 @@ bool ObjectAssetLoader::IsDownloading(const DistributedData::Asset& asset) { auto [success, hash] = downloading_.Find(asset.uri); if (success && hash == asset.hash) { - ZLOGD("asset is downloading. assetName:%{public}s", asset.name.c_str()); + ZLOGD("asset is downloading. assetName:%{public}s", Anonymous::Change(asset.name).c_str()); return true; } return false; @@ -158,7 +159,7 @@ bool ObjectAssetLoader::IsDownloaded(const DistributedData::Asset& asset) { auto [success, hash] = downloaded_.Find(asset.uri); if (success && hash == asset.hash) { - ZLOGD("asset is downloaded. assetName:%{public}s", asset.name.c_str()); + ZLOGD("asset is downloaded. assetName:%{public}s", Anonymous::Change(asset.name).c_str()); return true; } return false; @@ -167,15 +168,21 @@ bool ObjectAssetLoader::IsDownloaded(const DistributedData::Asset& asset) int32_t ObjectAssetLoader::PushAsset(int32_t userId, const sptr &assetObj, const sptr &sendCallback) { + if (assetObj == nullptr) { + ZLOGE("PushAsset err, assetObj is null"); + return OBJECT_INNER_ERROR; + } ObjectStore::RadarReporter::ReportStage(std::string(__FUNCTION__), ObjectStore::SAVE, ObjectStore::PUSH_ASSETS, ObjectStore::IDLE); - ZLOGI("PushAsset start, asset size:%{public}zu, bundleName:%{public}s, sessionId:%{public}s", - assetObj->uris_.size(), assetObj->dstBundleName_.c_str(), assetObj->sessionId_.c_str()); + ZLOGI("PushAsset start, userId:%{public}d, asset size:%{public}zu, bundleName:%{public}s, sessionId:%{public}s", + userId, assetObj->uris_.size(), assetObj->dstBundleName_.c_str(), + Anonymous::Change(assetObj->sessionId_).c_str()); auto status = Storage::DistributedFile::DistributedFileDaemonManager::GetInstance().PushAsset(userId, assetObj, sendCallback); if (status != OBJECT_SUCCESS) { ZLOGE("PushAsset err status: %{public}d, asset size:%{public}zu, bundleName:%{public}s, sessionId:%{public}s", - status, assetObj->uris_.size(), assetObj->dstBundleName_.c_str(), assetObj->sessionId_.c_str()); + status, assetObj->uris_.size(), assetObj->dstBundleName_.c_str(), + Anonymous::Change(assetObj->sessionId_).c_str()); ObjectStore::RadarReporter::ReportStateError(std::string(__FUNCTION__), ObjectStore::SAVE, ObjectStore::PUSH_ASSETS, ObjectStore::RADAR_FAILED, status, ObjectStore::FINISHED); } diff --git a/datamgr_service/services/distributeddataservice/service/object/src/object_asset_machine.cpp b/datamgr_service/services/distributeddataservice/service/object/src/object_asset_machine.cpp index dcb034ad..690affe9 100644 --- a/datamgr_service/services/distributeddataservice/service/object/src/object_asset_machine.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/src/object_asset_machine.cpp @@ -57,12 +57,12 @@ static int32_t Recover(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& a static int32_t UpdateStore(ChangedAssetInfo& changedAsset); -static AutoCache::Store GetStore(ChangedAssetInfo& changedAsset); +static AutoCache::Store GetStore(const ChangedAssetInfo& changedAsset); static VBuckets GetMigratedData(AutoCache::Store& store, AssetBindInfo& assetBindInfo, const Asset& newAsset); static void MergeAssetData(VBucket& record, const Asset& newAsset, const AssetBindInfo& assetBindInfo); static void MergeAsset(Asset& oldAsset, const Asset& newAsset); static std::string BuildSql(const AssetBindInfo& bindInfo, Values& args); -static BindEvent::BindEventInfo MakeBindInfo(ChangedAssetInfo& changedAsset); +static BindEvent::BindEventInfo MakeBindInfo(const ChangedAssetInfo& changedAsset); static const DFAAction AssetDFA[STATUS_BUTT][EVENT_BUTT] = { { @@ -133,7 +133,8 @@ static const DFAAction AssetDFA[STATUS_BUTT][EVENT_BUTT] = { int32_t ObjectAssetMachine::DFAPostEvent(AssetEvent eventId, ChangedAssetInfo& changedAssetInfo, Asset& asset, const std::pair& newAsset) { - if (eventId < 0 || eventId >= EVENT_BUTT) { + if (eventId < 0 || eventId >= EVENT_BUTT || changedAssetInfo.status >= STATUS_BUTT) { + ZLOGE("invalid parameters, eventId: %{public}d, status:%{public}d", eventId, changedAssetInfo.status); return GeneralError::E_ERROR; } @@ -164,16 +165,16 @@ static int32_t DoTransfer(int32_t eventId, ChangedAssetInfo& changedAsset, Asset changedAsset.deviceId = newAsset.first; changedAsset.asset = newAsset.second; std::vector assets{ changedAsset.asset }; - ObjectAssetLoader::GetInstance()->TransferAssetsAsync(changedAsset.storeInfo.user, + ObjectAssetLoader::GetInstance().TransferAssetsAsync(changedAsset.storeInfo.user, changedAsset.storeInfo.bundleName, changedAsset.deviceId, assets, [&changedAsset](bool success) { if (success) { auto status = UpdateStore(changedAsset); if (status != E_OK) { ZLOGE("UpdateStore error, error:%{public}d, assetName:%{public}s, store:%{public}s, " "table:%{public}s", - status, changedAsset.asset.name.c_str(), + status, Anonymous::Change(changedAsset.asset.name).c_str(), Anonymous::Change(changedAsset.bindInfo.storeName).c_str(), - changedAsset.bindInfo.tableName.c_str()); + Anonymous::Change(changedAsset.bindInfo.tableName).c_str()); } } ObjectAssetMachine::DFAPostEvent(TRANSFER_FINISHED, changedAsset, changedAsset.asset); @@ -287,7 +288,7 @@ static void MergeAsset(Asset& oldAsset, const Asset& newAsset) oldAsset.path = newAsset.path; } -static AutoCache::Store GetStore(ChangedAssetInfo& changedAsset) +static AutoCache::Store GetStore(const ChangedAssetInfo& changedAsset) { StoreMetaData meta; meta.storeId = changedAsset.bindInfo.storeName; @@ -295,7 +296,7 @@ static AutoCache::Store GetStore(ChangedAssetInfo& changedAsset) meta.user = std::to_string(changedAsset.storeInfo.user); meta.instanceId = changedAsset.storeInfo.instanceId; meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) { + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyWithoutPath(), meta)) { ZLOGE("meta empty, bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); return nullptr; @@ -337,8 +338,8 @@ static int32_t ChangeAssetToNormal(int32_t eventId, ChangedAssetInfo& changedAss static int32_t Recover(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& asset, const std::pair& newAsset) { - ZLOGE("An abnormal event has occurred, eventId:%{public}d, status:%{public}d, assetName:%{public}s", eventId, - changedAsset.status, changedAsset.asset.name.c_str()); + ZLOGI("An abnormal event has occurred, eventId:%{public}d, status:%{public}d, assetName:%{public}s", eventId, + changedAsset.status, Anonymous::Change(changedAsset.asset.name).c_str()); BindEvent::BindEventInfo bindEventInfo = MakeBindInfo(changedAsset); changedAsset.status = TransferStatus::STATUS_STABLE; @@ -347,7 +348,7 @@ static int32_t Recover(int32_t eventId, ChangedAssetInfo& changedAsset, Asset& a return E_OK; } -static BindEvent::BindEventInfo MakeBindInfo(ChangedAssetInfo& changedAsset) +static BindEvent::BindEventInfo MakeBindInfo(const ChangedAssetInfo& changedAsset) { BindEvent::BindEventInfo bindEventInfo; bindEventInfo.bundleName = changedAsset.storeInfo.bundleName; @@ -361,8 +362,5 @@ static BindEvent::BindEventInfo MakeBindInfo(ChangedAssetInfo& changedAsset) bindEventInfo.assetName = changedAsset.bindInfo.assetName; return bindEventInfo; } - -ObjectAssetMachine::ObjectAssetMachine() {} - } // namespace DistributedObject } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/object/src/object_callback_proxy.cpp b/datamgr_service/services/distributeddataservice/service/object/src/object_callback_proxy.cpp index 7e4c649a..32fdda71 100644 --- a/datamgr_service/services/distributeddataservice/service/object/src/object_callback_proxy.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/src/object_callback_proxy.cpp @@ -42,6 +42,11 @@ ObjectChangeCallbackProxy::ObjectChangeCallbackProxy(const sptr & { } +ObjectProgressCallbackProxy::ObjectProgressCallbackProxy(const sptr &impl) + : IRemoteProxy(impl) +{ +} + void ObjectSaveCallbackProxy::Completed(const std::map &results) { MessageParcel data; @@ -57,7 +62,7 @@ void ObjectSaveCallbackProxy::Completed(const std::map &re MessageOption mo { MessageOption::TF_SYNC }; int error = Remote()->SendRequest(COMPLETED, data, reply, mo); if (error != 0) { - ZLOGW("SendRequest failed, error %d", error); + ZLOGW("SendRequest failed, error %{public}d", error); } } @@ -70,13 +75,13 @@ void ObjectRevokeSaveCallbackProxy::Completed(int32_t status) return; } if (!ITypesUtil::Marshal(data, status)) { - ZLOGE("write descriptor failed"); + ZLOGE("Marshalling failed, status:%{public}d", status); return; } MessageOption mo { MessageOption::TF_SYNC }; int error = Remote()->SendRequest(COMPLETED, data, reply, mo); if (error != 0) { - ZLOGW("SendRequest failed, error %d", error); + ZLOGW("SendRequest failed, error %{public}d", error); } } @@ -89,13 +94,13 @@ void ObjectRetrieveCallbackProxy::Completed(const std::mapSendRequest(COMPLETED, data, reply, mo); if (error != 0) { - ZLOGW("SendRequest failed, error %d", error); + ZLOGW("SendRequest failed, error %{public}d", error); } } @@ -108,13 +113,32 @@ void ObjectChangeCallbackProxy::Completed(const std::mapSendRequest(COMPLETED, data, reply, mo); if (error != 0) { - ZLOGW("SendRequest failed, error %d", error); + ZLOGW("SendRequest failed, error %{public}d", error); + } +} + +void ObjectProgressCallbackProxy::Completed(int32_t progress) +{ + MessageParcel data; + MessageParcel reply; + if (!data.WriteInterfaceToken(GetDescriptor())) { + ZLOGE("write descriptor failed"); + return; + } + if (!ITypesUtil::Marshal(data, progress)) { + ZLOGE("Marshal failed"); + return; + } + MessageOption mo { MessageOption::TF_ASYNC }; + int error = Remote()->SendRequest(COMPLETED, data, reply, mo); + if (error != 0) { + ZLOGW("SendRequest failed, error %{public}d", error); } } } // namespace DistributedObject diff --git a/datamgr_service/services/distributeddataservice/service/object/src/object_data_listener.cpp b/datamgr_service/services/distributeddataservice/service/object/src/object_data_listener.cpp index e7a7a5d0..bdbdcb47 100644 --- a/datamgr_service/services/distributeddataservice/service/object/src/object_data_listener.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/src/object_data_listener.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#include #define LOG_TAG "ObjectDataListener" #include "object_data_listener.h" @@ -22,6 +23,8 @@ #include "utils/anonymous.h" namespace OHOS { namespace DistributedObject { +constexpr int32_t PROGRESS_MAX = 100; +constexpr int32_t PROGRESS_INVALID = -1; ObjectDataListener::ObjectDataListener() { } @@ -43,15 +46,16 @@ void ObjectDataListener::OnChange(const DistributedDB::KvStoreChangedData &data) std::string key(entry.key.begin(), entry.key.end()); changedData.insert_or_assign(std::move(key), entry.value); } - DistributedObject::ObjectStoreManager::GetInstance()->NotifyChange(changedData); + DistributedObject::ObjectStoreManager::GetInstance().NotifyChange(changedData); } int32_t ObjectAssetsRecvListener::OnStart(const std::string &srcNetworkId, const std::string &dstNetworkId, const std::string &sessionId, const std::string &dstBundleName) { auto objectKey = dstBundleName + sessionId; - ZLOGI("OnStart, objectKey:%{public}s", objectKey.c_str()); - ObjectStoreManager::GetInstance()->NotifyAssetsStart(objectKey, srcNetworkId); + ZLOGI("OnStart, objectKey:%{public}s", DistributedData::Anonymous::Change(objectKey).c_str()); + ObjectStoreManager::GetInstance().NotifyAssetsStart(objectKey, srcNetworkId); + ObjectStoreManager::GetInstance().NotifyAssetsRecvProgress(objectKey, 0); return OBJECT_SUCCESS; } @@ -65,10 +69,35 @@ int32_t ObjectAssetsRecvListener::OnFinished(const std::string &srcNetworkId, co ObjectStore::ASSETS_RECV, ObjectStore::RADAR_FAILED, result); return result; } - auto objectKey = assetObj->dstBundleName_+assetObj->sessionId_; - ZLOGI("OnFinished, status:%{public}d objectKey:%{public}s, asset size:%{public}zu", result, objectKey.c_str(), - assetObj->uris_.size()); - ObjectStoreManager::GetInstance()->NotifyAssetsReady(objectKey, assetObj->dstBundleName_, srcNetworkId); + auto objectKey = assetObj->dstBundleName_ + assetObj->sessionId_; + ZLOGI("OnFinished, status:%{public}d objectKey:%{public}s, asset size:%{public}zu", result, + DistributedData::Anonymous::Change(objectKey).c_str(), assetObj->uris_.size()); + ObjectStoreManager::GetInstance().NotifyAssetsReady(objectKey, assetObj->dstBundleName_, srcNetworkId); + if (result != OBJECT_SUCCESS) { + ObjectStoreManager::GetInstance().NotifyAssetsRecvProgress(objectKey, PROGRESS_INVALID); + } else { + ObjectStoreManager::GetInstance().NotifyAssetsRecvProgress(objectKey, PROGRESS_MAX); + } + return OBJECT_SUCCESS; +} + + +int32_t ObjectAssetsRecvListener::OnRecvProgress( + const std::string &srcNetworkId, const sptr &assetObj, uint64_t totalBytes, uint64_t processBytes) +{ + if (assetObj == nullptr || totalBytes == 0) { + ZLOGE("OnRecvProgress error! srcNetworkId:%{public}s, totalBytes: %{public}" PRIu64, + DistributedData::Anonymous::Change(srcNetworkId).c_str(), totalBytes); + return OBJECT_INNER_ERROR; + } + + auto objectKey = assetObj->dstBundleName_ + assetObj->sessionId_; + ZLOGI("srcNetworkId: %{public}s, objectKey:%{public}s, totalBytes: %{public}" PRIu64 + ", processBytes: %{public}" PRIu64 ".", + DistributedData::Anonymous::Change(srcNetworkId).c_str(), + DistributedData::Anonymous::Change(objectKey).c_str(), totalBytes, processBytes); + int32_t progress = static_cast((processBytes * 100.0 / totalBytes) * 0.9); + ObjectStoreManager::GetInstance().NotifyAssetsRecvProgress(objectKey, progress); return OBJECT_SUCCESS; } } // namespace DistributedObject diff --git a/datamgr_service/services/distributeddataservice/service/object/src/object_manager.cpp b/datamgr_service/services/distributeddataservice/service/object/src/object_manager.cpp index 3e3c554f..66d35fd0 100644 --- a/datamgr_service/services/distributeddataservice/service/object/src/object_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/src/object_manager.cpp @@ -26,9 +26,13 @@ #include "common/string_utils.h" #include "datetime_ex.h" #include "distributed_file_daemon_manager.h" +#include "device_matrix.h" +#include "ipc_skeleton.h" +#include "metadata/capability_meta_data.h" #include "kvstore_utils.h" #include "log_print.h" #include "metadata/meta_data_manager.h" +#include "metadata/object_user_meta_data.h" #include "metadata/store_meta_data.h" #include "object_dms_handler.h" #include "object_radar_reporter.h" @@ -43,7 +47,12 @@ using Account = OHOS::DistributedData::AccountDelegate; using AccessTokenKit = Security::AccessToken::AccessTokenKit; using ValueProxy = OHOS::DistributedData::ValueProxy; using DistributedFileDaemonManager = Storage::DistributedFile::DistributedFileDaemonManager; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; + constexpr const char *SAVE_INFO = "p_###SAVEINFO###"; +constexpr int32_t PROGRESS_MAX = 100; +constexpr int32_t PROGRESS_INVALID = -1; +constexpr uint32_t LOCK_TIMEOUT = 3600; // second ObjectStoreManager::ObjectStoreManager() { ZLOGI("ObjectStoreManager construct"); @@ -52,13 +61,6 @@ ObjectStoreManager::ObjectStoreManager() ObjectStoreManager::~ObjectStoreManager() { - ZLOGI("ObjectStoreManager destroy"); - if (objectAssetsRecvListener_ != nullptr) { - auto status = DistributedFileDaemonManager::GetInstance().UnRegisterAssetCallback(objectAssetsRecvListener_); - if (status != DistributedDB::DBStatus::OK) { - ZLOGE("UnRegister assetsRecvListener err %{public}d", status); - } - } } DistributedDB::KvStoreNbDelegate *ObjectStoreManager::OpenObjectKvStore() @@ -68,9 +70,6 @@ DistributedDB::KvStoreNbDelegate *ObjectStoreManager::OpenObjectKvStore() option.createDirByStoreIdOnly = true; option.syncDualTupleMode = true; option.secOption = { DistributedDB::S1, DistributedDB::ECE }; - if (objectDataListener_ == nullptr) { - objectDataListener_ = new ObjectDataListener(); - } ZLOGD("start GetKvStore"); kvStoreDelegateManager_->GetKvStore(ObjectCommon::OBJECTSTORE_DB_STOREID, option, [&store, this](DistributedDB::DBStatus dbStatus, DistributedDB::KvStoreNbDelegate *kvStoreNbDelegate) { @@ -78,12 +77,16 @@ DistributedDB::KvStoreNbDelegate *ObjectStoreManager::OpenObjectKvStore() ZLOGE("GetKvStore fail %{public}d", dbStatus); return; } + if (kvStoreNbDelegate == nullptr) { + ZLOGE("GetKvStore kvStoreNbDelegate is nullptr"); + return; + } ZLOGI("GetKvStore successsfully"); store = kvStoreNbDelegate; std::vector tmpKey; DistributedDB::DBStatus status = store->RegisterObserver(tmpKey, DistributedDB::ObserverMode::OBSERVER_CHANGES_FOREIGN, - objectDataListener_); + &objectDataListener_); if (status != DistributedDB::DBStatus::OK) { ZLOGE("RegisterObserver err %{public}d", status); } @@ -107,6 +110,19 @@ bool ObjectStoreManager::RegisterAssetsLister() return true; } +bool ObjectStoreManager::UnRegisterAssetsLister() +{ + ZLOGI("ObjectStoreManager UnRegisterAssetsLister"); + if (objectAssetsRecvListener_ != nullptr) { + auto status = DistributedFileDaemonManager::GetInstance().UnRegisterAssetCallback(objectAssetsRecvListener_); + if (status != DistributedDB::DBStatus::OK) { + ZLOGE("UnRegister assetsRecvListener err %{public}d", status); + return false; + } + } + return true; +} + void ObjectStoreManager::ProcessSyncCallback(const std::map &results, const std::string &appId, const std::string &sessionId, const std::string &deviceId) { @@ -131,8 +147,13 @@ int32_t ObjectStoreManager::Save(const std::string &appId, const std::string &se const ObjectRecord &data, const std::string &deviceId, sptr callback) { auto proxy = iface_cast(callback); + if (proxy == nullptr) { + ZLOGE("proxy is nullptr, callback is %{public}s.", (callback == nullptr) ? "nullptr" : "not null"); + return INVALID_ARGUMENT; + } if (deviceId.size() == 0) { - ZLOGE("DeviceId empty, appId: %{public}s, sessionId: %{public}s", appId.c_str(), sessionId.c_str()); + ZLOGE("DeviceId empty, appId: %{public}s, sessionId: %{public}s", appId.c_str(), + Anonymous::Change(sessionId).c_str()); proxy->Completed(std::map()); return INVALID_ARGUMENT; } @@ -156,13 +177,13 @@ int32_t ObjectStoreManager::Save(const std::string &appId, const std::string &se return result; } ZLOGI("Sync data, bundleName: %{public}s, sessionId: %{public}s, deviceId: %{public}s", dstBundleName.c_str(), - sessionId.c_str(), Anonymous::Change(deviceId).c_str()); + Anonymous::Change(sessionId).c_str(), Anonymous::Change(deviceId).c_str()); SyncCallBack syncCallback = [proxy, dstBundleName, sessionId, deviceId, this](const std::map &results) { ProcessSyncCallback(results, dstBundleName, sessionId, deviceId); proxy->Completed(results); }; - result = SyncOnStore(GetPropertyPrefix(dstBundleName, sessionId, deviceId), {deviceId}, syncCallback); + result = SyncOnStore(GetPropertyPrefix(dstBundleName, sessionId, deviceId), { deviceId }, syncCallback); if (result != OBJECT_SUCCESS) { ZLOGE("Sync data failed, result: %{public}d", result); ObjectStore::RadarReporter::ReportStateError(std::string(__FUNCTION__), ObjectStore::SAVE, @@ -182,7 +203,11 @@ int32_t ObjectStoreManager::PushAssets(const std::string &srcBundleName, const s if (assets.empty() || data.find(ObjectStore::FIELDS_PREFIX + ObjectStore::DEVICEID_KEY) == data.end()) { return OBJECT_SUCCESS; } - sptr assetObj = new AssetObj(); + sptr assetObj = new (std::nothrow) AssetObj(); + if (assetObj == nullptr) { + ZLOGE("New AssetObj failed"); + return OBJECT_INNER_ERROR; + } assetObj->dstBundleName_ = dstBundleName; assetObj->srcBundleName_ = srcBundleName; assetObj->dstNetworkId_ = deviceId; @@ -194,7 +219,7 @@ int32_t ObjectStoreManager::PushAssets(const std::string &srcBundleName, const s objectAssetsSendListener_ = new ObjectAssetsSendListener(); } int userId = std::atoi(GetCurrentUser().c_str()); - auto status = ObjectAssetLoader::GetInstance()->PushAsset(userId, assetObj, objectAssetsSendListener_); + auto status = ObjectAssetLoader::GetInstance().PushAsset(userId, assetObj, objectAssetsSendListener_); return status; } @@ -202,6 +227,11 @@ int32_t ObjectStoreManager::RevokeSave( const std::string &appId, const std::string &sessionId, sptr callback) { auto proxy = iface_cast(callback); + if (proxy == nullptr) { + ZLOGE("proxy is nullptr, callback is %{public}s, appId: %{public}s, sessionId: %{public}s.", + (callback == nullptr) ? "nullptr" : "not null", appId.c_str(), Anonymous::Change(sessionId).c_str()); + return INVALID_ARGUMENT; + } int32_t result = Open(); if (result != OBJECT_SUCCESS) { ZLOGE("Open failed, errCode = %{public}d", result); @@ -241,6 +271,10 @@ int32_t ObjectStoreManager::Retrieve( const std::string &bundleName, const std::string &sessionId, sptr callback, uint32_t tokenId) { auto proxy = iface_cast(callback); + if (proxy == nullptr) { + ZLOGE("proxy is nullptr, callback is %{public}s.", (callback == nullptr) ? "nullptr" : "not null"); + return INVALID_ARGUMENT; + } int32_t result = Open(); if (result != OBJECT_SUCCESS) { ZLOGE("Open object kvstore failed, result: %{public}d", result); @@ -250,7 +284,7 @@ int32_t ObjectStoreManager::Retrieve( ObjectRecord results{}; int32_t status = RetrieveFromStore(bundleName, sessionId, results); if (status != OBJECT_SUCCESS) { - ZLOGI("Retrieve from store failed, status: %{public}d, close after one minute.", status); + ZLOGE("Retrieve from store failed, status: %{public}d, close after one minute.", status); CloseAfterMinute(); proxy->Completed(ObjectRecord(), false); return status; @@ -260,8 +294,7 @@ int32_t ObjectStoreManager::Retrieve( if (assets.empty() || results.find(ObjectStore::FIELDS_PREFIX + ObjectStore::DEVICEID_KEY) == results.end()) { allReady = true; } else { - auto objectKey = bundleName + sessionId; - restoreStatus_.ComputeIfPresent(objectKey, [&allReady](const auto &key, auto &value) { + restoreStatus_.ComputeIfPresent(bundleName + sessionId, [&allReady](const auto &key, auto &value) { if (value == RestoreStatus::ALL_READY) { allReady = true; return false; @@ -273,13 +306,12 @@ int32_t ObjectStoreManager::Retrieve( }); } status = RevokeSaveToStore(GetPrefixWithoutDeviceId(bundleName, sessionId)); + Close(); if (status != OBJECT_SUCCESS) { ZLOGE("Revoke save failed, status: %{public}d", status); - Close(); proxy->Completed(ObjectRecord(), false); return status; } - Close(); proxy->Completed(results, allReady); if (allReady) { ObjectStore::RadarReporter::ReportStateFinished(std::string(__FUNCTION__), ObjectStore::DATA_RESTORE, @@ -291,39 +323,64 @@ int32_t ObjectStoreManager::Retrieve( int32_t ObjectStoreManager::Clear() { ZLOGI("enter"); + DistributedData::ObjectUserMetaData userMeta; + if (!DistributedData::MetaDataManager::GetInstance().LoadMeta(userMeta.GetKey(), userMeta, true)) { + ZLOGE("load meta error"); + return OBJECT_INNER_ERROR; + } + if (userMeta.userId.empty()) { + ZLOGI("no object user meta, don't need clean"); + return OBJECT_SUCCESS; + } std::string userId = GetCurrentUser(); if (userId.empty()) { + ZLOGE("no user error"); return OBJECT_INNER_ERROR; } - std::vector metaData; - std::string appId = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); - std::string metaKey = GetMetaUserIdKey(userId, appId); - if (!DistributedData::MetaDataManager::GetInstance().LoadMeta(metaKey, metaData, true)) { - ZLOGE("no store of %{public}s", appId.c_str()); - return OBJECT_STORE_NOT_FOUND; - } - for (const auto &storeMeta : metaData) { - if (storeMeta.storeType < StoreMetaData::StoreType::STORE_OBJECT_BEGIN - || storeMeta.storeType > StoreMetaData::StoreType::STORE_OBJECT_END) { - continue; - } - if (storeMeta.user == userId) { - ZLOGI("user is same, not need to change, mate user:%{public}s::user:%{public}s.", - storeMeta.user.c_str(), userId.c_str()); - return OBJECT_SUCCESS; - } + if (userMeta.userId == userId) { + ZLOGI("user is same, don't need clear, user:%{public}s.", userId.c_str()); + return OBJECT_SUCCESS; } - ZLOGD("user is change, need to change"); + ZLOGI("user changed, need clear, userId:%{public}s", userId.c_str()); int32_t result = Open(); if (result != OBJECT_SUCCESS) { ZLOGE("Open failed, errCode = %{public}d", result); return STORE_NOT_OPEN; } result = RevokeSaveToStore(""); - Close(); + callbacks_.Clear(); + processCallbacks_.Clear(); + ForceClose(); return result; } +int32_t ObjectStoreManager::InitUserMeta() +{ + ObjectUserMetaData userMeta; + if (DistributedData::MetaDataManager::GetInstance().LoadMeta(userMeta.GetKey(), userMeta, true)) { + ZLOGI("userId has been set, don't need clean"); + return OBJECT_SUCCESS; + } + std::string userId = GetCurrentUser(); + if (userId.empty()) { + ZLOGI("get userId error"); + return OBJECT_INNER_ERROR; + } + userMeta.userId = userId; + std::string appId = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); + std::string metaKey = GetMetaUserIdKey(userId, appId); + if (!DistributedData::MetaDataManager::GetInstance().DelMeta(metaKey, true)) { + ZLOGE("delete old meta error, userId:%{public}s", userId.c_str()); + return OBJECT_INNER_ERROR; + } + if (!DistributedData::MetaDataManager::GetInstance().SaveMeta(DistributedData::ObjectUserMetaData::GetKey(), + userMeta, true)) { + ZLOGE("save meta error, userId:%{public}s", userId.c_str()); + return OBJECT_INNER_ERROR; + } + return OBJECT_SUCCESS; +} + int32_t ObjectStoreManager::DeleteByAppId(const std::string &appId, int32_t user) { int32_t result = Open(); @@ -338,12 +395,6 @@ int32_t ObjectStoreManager::DeleteByAppId(const std::string &appId, int32_t user appId.c_str(), user); } Close(); - std::string userId = std::to_string(user); - std::string metaKey = GetMetaUserIdKey(userId, appId); - auto status = DistributedData::MetaDataManager::GetInstance().DelMeta(metaKey, true); - if (!status) { - ZLOGE("Delete meta failed, userId: %{public}s, appId: %{public}s", userId.c_str(), appId.c_str()); - } return result; } @@ -357,6 +408,13 @@ void ObjectStoreManager::RegisterRemoteCallback(const std::string &bundleName, c } ZLOGD("ObjectStoreManager::RegisterRemoteCallback start"); auto proxy = iface_cast(callback); + if (proxy == nullptr) { + ZLOGE("proxy is nullptr, callback is %{public}s, bundleName: %{public}s, sessionId: %{public}s, pid: " + "%{public}d, tokenId: %{public}u.", + (callback == nullptr) ? "nullptr" : "not null", bundleName.c_str(), Anonymous::Change(sessionId).c_str(), + pid, tokenId); + return; + } std::string prefix = bundleName + sessionId; callbacks_.Compute(tokenId, ([pid, &proxy, &prefix](const uint32_t key, CallbackInfo &value) { if (value.pid != pid) { @@ -367,8 +425,8 @@ void ObjectStoreManager::RegisterRemoteCallback(const std::string &bundleName, c })); } -void ObjectStoreManager::UnregisterRemoteCallback(const std::string &bundleName, pid_t pid, uint32_t tokenId, - const std::string &sessionId) +void ObjectStoreManager::UnregisterRemoteCallback( + const std::string &bundleName, pid_t pid, uint32_t tokenId, const std::string &sessionId) { if (bundleName.empty()) { ZLOGD("bundleName is empty"); @@ -393,7 +451,81 @@ void ObjectStoreManager::UnregisterRemoteCallback(const std::string &bundleName, })); } -void ObjectStoreManager::NotifyChange(ObjectRecord &changedData) +void ObjectStoreManager::RegisterProgressObserverCallback(const std::string &bundleName, const std::string &sessionId, + pid_t pid, uint32_t tokenId, sptr callback) +{ + if (bundleName.empty() || sessionId.empty()) { + ZLOGD("ObjectStoreManager::RegisterProgressObserverCallback empty bundleName = %{public}s, sessionId = " + "%{public}s", + bundleName.c_str(), DistributedData::Anonymous::Change(sessionId).c_str()); + return; + } + auto proxy = iface_cast(callback); + if (proxy == nullptr) { + ZLOGE("proxy is nullptr, callback is %{public}s, bundleName: %{public}s, sessionId: %{public}s, pid: " + "%{public}d, tokenId: %{public}u.", + (callback == nullptr) ? "nullptr" : "not null", bundleName.c_str(), Anonymous::Change(sessionId).c_str(), + pid, tokenId); + return; + } + std::string objectKey = bundleName + sessionId; + sptr observer; + processCallbacks_.Compute( + tokenId, ([pid, &proxy, &objectKey, &observer](const uint32_t key, ProgressCallbackInfo &value) { + if (value.pid != pid) { + value = ProgressCallbackInfo{ pid }; + } + value.observers_.insert_or_assign(objectKey, proxy); + observer = value.observers_[objectKey]; + return !value.observers_.empty(); + })); + int32_t progress = PROGRESS_INVALID; + { + std::lock_guard lock(progressMutex_); + auto it = progressInfo_.find(objectKey); + if (it == progressInfo_.end()) { + return; + } + progress = it->second; + } + if (observer != nullptr && progress != PROGRESS_INVALID) { + observer->Completed(progress); + } + if (progress == PROGRESS_MAX) { + assetsRecvProgress_.Erase(objectKey); + std::lock_guard lock(progressMutex_); + progressInfo_.erase(objectKey); + } +} + +void ObjectStoreManager::UnregisterProgressObserverCallback( + const std::string &bundleName, pid_t pid, uint32_t tokenId, const std::string &sessionId) +{ + if (bundleName.empty()) { + ZLOGD("bundleName is empty"); + return; + } + processCallbacks_.Compute( + tokenId, ([pid, &sessionId, &bundleName](const uint32_t key, ProgressCallbackInfo &value) { + if (value.pid != pid) { + return true; + } + if (sessionId.empty()) { + return false; + } + std::string prefix = bundleName + sessionId; + for (auto it = value.observers_.begin(); it != value.observers_.end();) { + if ((*it).first == prefix) { + it = value.observers_.erase(it); + } else { + ++it; + } + } + return true; + })); +} + +void ObjectStoreManager::NotifyChange(const ObjectRecord &changedData) { ZLOGI("OnChange start, size:%{public}zu", changedData.size()); bool hasAsset = false; @@ -484,6 +616,34 @@ void ObjectStoreManager::ComputeStatus(const std::string& objectKey, const SaveI }); } +bool ObjectStoreManager::IsNeedMetaSync(const StoreMetaData &meta, const std::vector &uuids) +{ + bool isAfterMeta = false; + for (const auto &uuid : uuids) { + auto metaData = meta; + metaData.deviceId = uuid; + CapMetaData capMeta; + auto capKey = CapMetaRow::GetKeyFor(uuid); + bool flag = !MetaDataManager::GetInstance().LoadMeta(std::string(capKey.begin(), capKey.end()), capMeta) || + !MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData); + if (flag) { + isAfterMeta = true; + break; + } + auto [exist, mask] = DeviceMatrix::GetInstance().GetRemoteMask(uuid); + if ((mask & DeviceMatrix::META_STORE_MASK) == DeviceMatrix::META_STORE_MASK) { + isAfterMeta = true; + break; + } + auto [existLocal, localMask] = DeviceMatrix::GetInstance().GetMask(uuid); + if ((localMask & DeviceMatrix::META_STORE_MASK) == DeviceMatrix::META_STORE_MASK) { + isAfterMeta = true; + break; + } + } + return isAfterMeta; +} + void ObjectStoreManager::NotifyDataChanged(const std::map& data, const SaveInfo& saveInfo) { for (auto const& [objectKey, results] : data) { @@ -498,6 +658,10 @@ void ObjectStoreManager::NotifyDataChanged(const std::map& data) { + if (executors_ == nullptr) { + ZLOGE("executors_ is null"); + return OBJECT_INNER_ERROR; + } auto taskId = executors_->Schedule(std::chrono::seconds(WAIT_TIME), [this, objectKey, data, saveInfo]() { ZLOGE("wait assets finisehd timeout, try pull assets, objectKey:%{public}s", objectKey.c_str()); PullAssets(data, saveInfo); @@ -520,7 +684,7 @@ void ObjectStoreManager::PullAssets(const std::map& d for (const auto& [objectId, assets] : changedAssets) { std::string networkId = DmAdaper::GetInstance().ToNetworkID(saveInfo.sourceDeviceId); auto block = std::make_shared>>(WAIT_TIME, std::tuple{ true, true }); - ObjectAssetLoader::GetInstance()->TransferAssetsAsync(std::stoi(GetCurrentUser()), + ObjectAssetLoader::GetInstance().TransferAssetsAsync(std::atoi(GetCurrentUser().c_str()), saveInfo.bundleName, networkId, assets, [this, block](bool success) { block->SetValue({ false, success }); }); @@ -530,9 +694,47 @@ void ObjectStoreManager::PullAssets(const std::map& d } } -void ObjectStoreManager::NotifyAssetsReady(const std::string& objectKey, const std::string& bundleName, - const std::string& srcNetworkId) +void ObjectStoreManager::NotifyAssetsRecvProgress(const std::string &objectKey, int32_t progress) +{ + assetsRecvProgress_.InsertOrAssign(objectKey, progress); + std::list> observers; + bool flag = false; + processCallbacks_.ForEach( + [&objectKey, &observers, &flag](uint32_t tokenId, const ProgressCallbackInfo &value) { + if (value.observers_.empty()) { + flag = true; + return false; + } + auto it = value.observers_.find(objectKey); + if (it != value.observers_.end()) { + observers.push_back(it->second); + } + return false; + }); + if (flag) { + std::lock_guard lock(progressMutex_); + progressInfo_.insert_or_assign(objectKey, progress); + } + for (auto &observer : observers) { + if (observer == nullptr) { + continue; + } + observer->Completed(progress); + } + if (!observers.empty() && progress == PROGRESS_MAX) { + assetsRecvProgress_.Erase(objectKey); + std::lock_guard lock(progressMutex_); + progressInfo_.erase(objectKey); + } +} + +void ObjectStoreManager::NotifyAssetsReady( + const std::string &objectKey, const std::string &bundleName, const std::string &srcNetworkId) { + if (executors_ == nullptr) { + ZLOGE("executors_ is nullptr"); + return; + } restoreStatus_.ComputeIfAbsent( objectKey, [](const std::string& key) -> auto { return RestoreStatus::NONE; @@ -598,7 +800,9 @@ Assets ObjectStoreManager::GetAssetsFromDBRecords(const ObjectRecord& result) std::string assetPrefix = key.substr(0, key.find(ObjectStore::ASSET_DOT)); if (!IsAssetKey(key) || assetKey.find(assetPrefix) != assetKey.end() || result.find(assetPrefix + ObjectStore::NAME_SUFFIX) == result.end() || - result.find(assetPrefix + ObjectStore::URI_SUFFIX) == result.end()) { + result.find(assetPrefix + ObjectStore::URI_SUFFIX) == result.end() || + result.find(assetPrefix + ObjectStore::MODIFY_TIME_SUFFIX) == result.end() || + result.find(assetPrefix + ObjectStore::SIZE_SUFFIX) == result.end()) { continue; } Asset asset; @@ -654,6 +858,10 @@ void ObjectStoreManager::DoNotify(uint32_t tokenId, const CallbackInfo& value, void ObjectStoreManager::DoNotifyAssetsReady(uint32_t tokenId, const CallbackInfo& value, const std::string& objectKey, bool allReady) { + if (executors_ == nullptr) { + ZLOGE("executors_ is nullptr"); + return; + } for (const auto& observer : value.observers_) { if (objectKey != observer.first) { continue; @@ -674,6 +882,10 @@ void ObjectStoreManager::DoNotifyAssetsReady(uint32_t tokenId, const CallbackInf void ObjectStoreManager::DoNotifyWaitAssetTimeout(const std::string &objectKey) { + if (executors_ == nullptr) { + ZLOGE("executors_ is nullptr"); + return; + } ObjectStore::RadarReporter::ReportStageError(std::string(__FUNCTION__), ObjectStore::DATA_RESTORE, ObjectStore::ASSETS_RECV, ObjectStore::RADAR_FAILED, ObjectStore::TIMEOUT); callbacks_.ForEach([this, &objectKey](uint32_t tokenId, const CallbackInfo &value) { @@ -697,11 +909,15 @@ void ObjectStoreManager::DoNotifyWaitAssetTimeout(const std::string &objectKey) void ObjectStoreManager::SetData(const std::string &dataDir, const std::string &userId) { - ZLOGI("enter %{public}s", dataDir.c_str()); - kvStoreDelegateManager_ = - new DistributedDB::KvStoreDelegateManager(DistributedData::Bootstrap::GetInstance().GetProcessLabel(), userId); + ZLOGI("enter, user: %{public}s", userId.c_str()); + kvStoreDelegateManager_ = std::make_shared + (DistributedData::Bootstrap::GetInstance().GetProcessLabel(), userId); DistributedDB::KvStoreConfig kvStoreConfig { dataDir }; - kvStoreDelegateManager_->SetKvStoreConfig(kvStoreConfig); + auto status = kvStoreDelegateManager_->SetKvStoreConfig(kvStoreConfig); + if (status != DistributedDB::OK) { + ZLOGE("Set kvstore config failed, status: %{public}d", status); + return; + } userId_ = userId; } @@ -711,7 +927,7 @@ int32_t ObjectStoreManager::Open() ZLOGE("Kvstore delegate manager not init"); return OBJECT_INNER_ERROR; } - std::lock_guard lock(kvStoreMutex_); + std::unique_lock lock(rwMutex_); if (delegate_ == nullptr) { delegate_ = OpenObjectKvStore(); if (delegate_ == nullptr) { @@ -722,25 +938,44 @@ int32_t ObjectStoreManager::Open() ZLOGI("Open object kvstore success"); } else { syncCount_++; - ZLOGI("Object kvstore syncCount: %{public}d", syncCount_); + ZLOGI("Object kvstore syncCount: %{public}d", syncCount_.load()); } return OBJECT_SUCCESS; } -void ObjectStoreManager::Close() +void ObjectStoreManager::ForceClose() { - std::lock_guard lock(kvStoreMutex_); + std::unique_lock lock(rwMutex_, std::chrono::seconds(LOCK_TIMEOUT)); if (delegate_ == nullptr) { return; } - int32_t taskCount = delegate_->GetTaskCount(); + auto status = kvStoreDelegateManager_->CloseKvStore(delegate_); + if (status != DistributedDB::DBStatus::OK) { + ZLOGE("CloseKvStore fail %{public}d", status); + return; + } + delegate_ = nullptr; + isSyncing_ = false; + syncCount_ = 0; +} + +void ObjectStoreManager::Close() +{ + int32_t taskCount = 0; + { + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + return; + } + taskCount = delegate_->GetTaskCount(); + } if (taskCount > 0 && syncCount_ == 1) { CloseAfterMinute(); ZLOGW("Store is busy, close after a minute, task count: %{public}d", taskCount); return; } syncCount_--; - ZLOGI("closed a store, syncCount = %{public}d", syncCount_); + ZLOGI("closed a store, syncCount = %{public}d", syncCount_.load()); FlushClosedStore(); } @@ -750,7 +985,6 @@ void ObjectStoreManager::SyncCompleted( std::string userId; SequenceSyncManager::Result result = SequenceSyncManager::GetInstance()->Process(sequenceId, results, userId); if (result == SequenceSyncManager::SUCCESS_USER_HAS_FINISHED && userId == userId_) { - std::lock_guard lock(kvStoreMutex_); SetSyncStatus(false); FlushClosedStore(); } @@ -766,10 +1000,14 @@ void ObjectStoreManager::SyncCompleted( } } } - + void ObjectStoreManager::FlushClosedStore() { - std::lock_guard lock(kvStoreMutex_); + if (executors_ == nullptr) { + ZLOGE("executors_ is nullptr"); + return; + } + std::unique_lock lock(rwMutex_); if (!isSyncing_ && syncCount_ == 0 && delegate_ != nullptr) { ZLOGD("close store"); auto status = kvStoreDelegateManager_->CloseKvStore(delegate_); @@ -782,24 +1020,23 @@ void ObjectStoreManager::FlushClosedStore() return; } delegate_ = nullptr; - if (objectDataListener_ != nullptr) { - delete objectDataListener_; - objectDataListener_ = nullptr; - } } } void ObjectStoreManager::ProcessOldEntry(const std::string &appId) { std::vector entries; - auto status = delegate_->GetEntries(std::vector(appId.begin(), appId.end()), entries); - if (status != DistributedDB::DBStatus::NOT_FOUND) { - ZLOGI("Get old entries empty, bundleName: %{public}s", appId.c_str()); - return; - } - if (status != DistributedDB::DBStatus::OK) { - ZLOGE("Get old entries failed, bundleName: %{public}s, status %{public}d", appId.c_str(), status); - return; + { + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("delegate is nullptr."); + return; + } + auto status = delegate_->GetEntries(std::vector(appId.begin(), appId.end()), entries); + if (status != DistributedDB::DBStatus::OK) { + ZLOGE("Get old entries failed, bundleName: %{public}s, status %{public}d", appId.c_str(), status); + return; + } } std::map sessionIds; int64_t oldestTime = 0; @@ -847,21 +1084,30 @@ int32_t ObjectStoreManager::SaveToStore(const std::string &appId, const std::str saveInfoEntry.value = std::vector(saveInfoValue.begin(), saveInfoValue.end()); std::vector entries; entries.emplace_back(saveInfoEntry); - for (auto &item : data) { + for (const auto &item : data) { DistributedDB::Entry entry; std::string key = GetPropertyPrefix(appId, sessionId, toDeviceId) + timestamp + SEPERATOR + item.first; entry.key = std::vector(key.begin(), key.end()); entry.value = item.second; entries.emplace_back(entry); } - auto status = delegate_->PutBatch(entries); - if (status != DistributedDB::DBStatus::OK) { - ZLOGE("PutBatch failed, bundleName: %{public}s, sessionId: %{public}s, dstNetworkId: %{public}s, " - "status: %{public}d", appId.c_str(), sessionId.c_str(), Anonymous::Change(toDeviceId).c_str(), status); - return status; + { + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("delegate is nullptr."); + return E_DB_ERROR; + } + auto status = delegate_->PutBatch(entries); + if (status != DistributedDB::DBStatus::OK) { + ZLOGE("PutBatch failed, bundleName: %{public}s, sessionId: %{public}s, dstNetworkId: %{public}s, " + "status: %{public}d", + appId.c_str(), Anonymous::Change(sessionId).c_str(), Anonymous::Change(toDeviceId).c_str(), status); + return status; + } } ZLOGI("PutBatch success, bundleName: %{public}s, sessionId: %{public}s, dstNetworkId: %{public}s, " - "count: %{public}zu", appId.c_str(), sessionId.c_str(), Anonymous::Change(toDeviceId).c_str(), entries.size()); + "count: %{public}zu", + appId.c_str(), Anonymous::Change(sessionId).c_str(), Anonymous::Change(toDeviceId).c_str(), entries.size()); return OBJECT_SUCCESS; } @@ -869,9 +1115,9 @@ int32_t ObjectStoreManager::SyncOnStore( const std::string &prefix, const std::vector &deviceList, SyncCallBack &callback) { std::vector syncDevices; - for (auto &device : deviceList) { + for (auto const &device : deviceList) { if (device == LOCAL_DEVICE) { - ZLOGI("Save to local, do not need sync, prefix: %{public}s", prefix.c_str()); + ZLOGI("Save to local, do not need sync, prefix: %{public}s", Anonymous::Change(prefix).c_str()); callback({{LOCAL_DEVICE, OBJECT_SUCCESS}}); return OBJECT_SUCCESS; } @@ -883,10 +1129,35 @@ int32_t ObjectStoreManager::SyncOnStore( return OBJECT_SUCCESS; } uint64_t sequenceId = SequenceSyncManager::GetInstance()->AddNotifier(userId_, callback); + + int32_t id = AccountDelegate::GetInstance()->GetUserByToken(IPCSkeleton::GetCallingFullTokenID()); + StoreMetaData meta = StoreMetaData(std::to_string(id), Bootstrap::GetInstance().GetProcessLabel(), + DistributedObject::ObjectCommon::OBJECTSTORE_DB_STOREID); + auto uuids = DmAdapter::GetInstance().ToUUID(syncDevices); + bool isNeedMetaSync = IsNeedMetaSync(meta, uuids); + if (!isNeedMetaSync) { + return DoSync(prefix, syncDevices, sequenceId); + } + bool result = MetaDataManager::GetInstance().Sync(uuids, [this, prefix, syncDevices, sequenceId](auto &results) { + auto status = DoSync(prefix, syncDevices, sequenceId); + ZLOGI("Store sync after meta sync end, status:%{public}d", status); + }); + ZLOGI("prefix:%{public}s, meta sync end, result:%{public}d", Anonymous::Change(prefix).c_str(), result); + return result ? OBJECT_SUCCESS : DoSync(prefix, syncDevices, sequenceId); +} + +int32_t ObjectStoreManager::DoSync(const std::string &prefix, const std::vector &deviceList, + uint64_t sequenceId) +{ + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("db store was closed."); + return E_DB_ERROR; + } DistributedDB::Query dbQuery = DistributedDB::Query::Select(); dbQuery.PrefixKey(std::vector(prefix.begin(), prefix.end())); ZLOGI("Start sync data, sequenceId: 0x%{public}" PRIx64 "", sequenceId); - auto status = delegate_->Sync(syncDevices, DistributedDB::SyncMode::SYNC_MODE_PUSH_ONLY, + auto status = delegate_->Sync(deviceList, DistributedDB::SyncMode::SYNC_MODE_PUSH_ONLY, [this, sequenceId](const std::map &devicesMap) { ZLOGI("Sync data finished, sequenceId: 0x%{public}" PRIx64 "", sequenceId); std::map result; @@ -908,7 +1179,6 @@ int32_t ObjectStoreManager::SyncOnStore( int32_t ObjectStoreManager::SetSyncStatus(bool status) { - std::lock_guard lock(kvStoreMutex_); isSyncing_ = status; return OBJECT_SUCCESS; } @@ -916,6 +1186,11 @@ int32_t ObjectStoreManager::SetSyncStatus(bool status) int32_t ObjectStoreManager::RevokeSaveToStore(const std::string &prefix) { std::vector entries; + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("db store was closed."); + return E_DB_ERROR; + } auto status = delegate_->GetEntries(std::vector(prefix.begin(), prefix.end()), entries); if (status == DistributedDB::DBStatus::NOT_FOUND) { ZLOGI("Get entries empty, prefix: %{public}s", Anonymous::Change(prefix).c_str()); @@ -948,16 +1223,21 @@ int32_t ObjectStoreManager::RetrieveFromStore(const std::string &appId, const st { std::vector entries; std::string prefix = GetPrefixWithoutDeviceId(appId, sessionId); + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("db store was closed."); + return E_DB_ERROR; + } auto status = delegate_->GetEntries(std::vector(prefix.begin(), prefix.end()), entries); if (status == DistributedDB::DBStatus::NOT_FOUND) { - ZLOGI("Get entries empty, prefix: %{public}s, status: %{public}d", prefix.c_str(), status); + ZLOGI("Get entries empty, prefix: %{public}s, status: %{public}d", Anonymous::Change(prefix).c_str(), status); return KEY_NOT_FOUND; } if (status != DistributedDB::DBStatus::OK) { - ZLOGE("Get entries failed, prefix: %{public}s, status: %{public}d", prefix.c_str(), status); + ZLOGE("Get entries failed, prefix: %{public}s, status: %{public}d", Anonymous::Change(prefix).c_str(), status); return DB_ERROR; } - ZLOGI("Get entries success, prefix: %{public}s, count: %{public}zu", prefix.c_str(), entries.size()); + ZLOGI("GetEntries success,prefix:%{public}s,count:%{public}zu", Anonymous::Change(prefix).c_str(), entries.size()); for (const auto &entry : entries) { std::string key(entry.key.begin(), entry.key.end()); if (key.find(SAVE_INFO) != std::string::npos) { @@ -1056,8 +1336,9 @@ std::vector ObjectStoreManager::SplitEntryKey(const std::string &ke std::string ObjectStoreManager::GetCurrentUser() { std::vector users; - AccountDelegate::GetInstance()->QueryUsers(users); - if (users.empty()) { + auto ret = AccountDelegate::GetInstance()->QueryUsers(users); + if (!ret || users.empty()) { + ZLOGE("failed to query os accounts, ret:%{public}d", ret); return ""; } return std::to_string(users[0]); @@ -1071,20 +1352,24 @@ void ObjectStoreManager::SaveUserToMeta() return; } std::string appId = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); - StoreMetaData userMeta; - userMeta.storeId = DistributedObject::ObjectCommon::OBJECTSTORE_DB_STOREID; - userMeta.user = userId; - userMeta.storeType = ObjectDistributedType::OBJECT_SINGLE_VERSION; - std::string userMetaKey = GetMetaUserIdKey(userId, appId); - auto saved = DistributedData::MetaDataManager::GetInstance().SaveMeta(userMetaKey, userMeta, true); + DistributedData::ObjectUserMetaData userMeta; + userMeta.userId = userId; + auto saved = DistributedData::MetaDataManager::GetInstance().SaveMeta( + DistributedData::ObjectUserMetaData::GetKey(), userMeta, true); if (!saved) { - ZLOGE("userMeta save failed"); + ZLOGE("userMeta save failed, userId:%{public}s", userId.c_str()); } } void ObjectStoreManager::CloseAfterMinute() { - executors_->Schedule(std::chrono::minutes(INTERVAL), std::bind(&ObjectStoreManager::Close, this)); + if (executors_ == nullptr) { + ZLOGE("executors_ is nullptr."); + return; + } + executors_->Schedule(std::chrono::minutes(INTERVAL), [this]() { + Close(); + }); } void ObjectStoreManager::SetThreadPool(std::shared_ptr executors) @@ -1110,7 +1395,7 @@ SequenceSyncManager::Result SequenceSyncManager::Process( return ERR_SID_NOT_EXIST; } std::map syncResults; - for (auto &item : results) { + for (const auto &item : results) { syncResults[item.first] = item.second == DistributedDB::DBStatus::OK ? 0 : -1; } seqIdCallbackRelations_[sequenceId](syncResults); @@ -1170,6 +1455,10 @@ int32_t ObjectStoreManager::BindAsset(const uint32_t tokenId, const std::string& return true; }); + if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) { + ZLOGE("TokenType is not TOKEN_HAP, token:0x%{public}x, bundleName:%{public}s", tokenId, appId.c_str()); + return GeneralError::E_ERROR; + } HapTokenInfo tokenInfo; auto status = AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo); if (status != RET_SUCCESS) { @@ -1221,7 +1510,7 @@ int32_t ObjectStoreManager::OnAssetChanged(const uint32_t tokenId, const std::st } auto block = std::make_shared>>(WAIT_TIME, std::tuple{ true, true }); - ObjectAssetLoader::GetInstance()->TransferAssetsAsync(userId, appId, deviceId, { dataAsset }, [block](bool ret) { + ObjectAssetLoader::GetInstance().TransferAssetsAsync(userId, appId, deviceId, { dataAsset }, [block](bool ret) { block->SetValue({ false, ret }); }); auto [timeout, success] = block->GetValue(); @@ -1264,5 +1553,17 @@ void ObjectStoreManager::DeleteSnapshot(const std::string& bundleName, const std }); snapshots_.Erase(snapshotKey); } + +int32_t ObjectStoreManager::AutoLaunchStore() +{ + int32_t status = Open(); + if (status != OBJECT_SUCCESS) { + ZLOGE("Open fail %{public}d", status); + return status; + } + CloseAfterMinute(); + ZLOGI("Auto launch, close after a minute"); + return OBJECT_SUCCESS; +} } // namespace DistributedObject } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/object/src/object_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/object/src/object_service_impl.cpp index fdb08505..ff6d5ee3 100644 --- a/datamgr_service/services/distributeddataservice/service/object/src/object_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/src/object_service_impl.cpp @@ -43,7 +43,9 @@ using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; using StoreMetaData = OHOS::DistributedData::StoreMetaData; using FeatureSystem = OHOS::DistributedData::FeatureSystem; using DumpManager = OHOS::DistributedData::DumpManager; +using CheckerManager = OHOS::DistributedData::CheckerManager; __attribute__((used)) ObjectServiceImpl::Factory ObjectServiceImpl::factory_; +constexpr const char *METADATA_STORE_PATH = "/data/service/el1/public/database/distributeddata/kvdb"; ObjectServiceImpl::Factory::Factory() { FeatureSystem::GetInstance().RegisterCreator( @@ -72,7 +74,7 @@ int32_t ObjectServiceImpl::ObjectStoreSave(const std::string &bundleName, const if (status != OBJECT_SUCCESS) { return status; } - status = ObjectStoreManager::GetInstance()->Save(bundleName, sessionId, data, deviceId, callback); + status = ObjectStoreManager::GetInstance().Save(bundleName, sessionId, data, deviceId, callback); if (status != OBJECT_SUCCESS) { ZLOGE("save fail %{public}d", status); } @@ -89,7 +91,7 @@ int32_t ObjectServiceImpl::OnAssetChanged(const std::string &bundleName, const s if (status != OBJECT_SUCCESS) { return status; } - status = ObjectStoreManager::GetInstance()->OnAssetChanged(tokenId, bundleName, sessionId, deviceId, assetValue); + status = ObjectStoreManager::GetInstance().OnAssetChanged(tokenId, bundleName, sessionId, deviceId, assetValue); if (status != OBJECT_SUCCESS) { ZLOGE("file transfer failed fail %{public}d", status); } @@ -104,10 +106,10 @@ int32_t ObjectServiceImpl::BindAssetStore(const std::string &bundleName, const s if (status != OBJECT_SUCCESS) { return status; } - status = ObjectStoreManager::GetInstance()->BindAsset(tokenId, bundleName, sessionId, asset, bindInfo); + status = ObjectStoreManager::GetInstance().BindAsset(tokenId, bundleName, sessionId, asset, bindInfo); if (status != OBJECT_SUCCESS) { ZLOGE("bind asset fail %{public}d, bundleName:%{public}s, sessionId:%{public}s, assetName:%{public}s", status, - bundleName.c_str(), sessionId.c_str(), asset.name.c_str()); + bundleName.c_str(), Anonymous::Change(sessionId).c_str(), Anonymous::Change(asset.name).c_str()); } return status; } @@ -115,6 +117,10 @@ int32_t ObjectServiceImpl::BindAssetStore(const std::string &bundleName, const s int32_t ObjectServiceImpl::IsContinue(bool &result) { uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); + if (Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId) != Security::AccessToken::TOKEN_HAP) { + ZLOGE("TokenType is not TOKEN_HAP, tokenId: %{public}u", tokenId); + return OBJECT_INNER_ERROR; + } Security::AccessToken::HapTokenInfo tokenInfo; auto status = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo); if (status != 0) { @@ -133,10 +139,31 @@ int32_t ObjectServiceImpl::OnInitialize() ZLOGE("failed to get local device id"); return OBJECT_INNER_ERROR; } - auto token = IPCSkeleton::GetCallingTokenID(); - const std::string accountId = DistributedData::AccountDelegate::GetInstance()->GetCurrentAccountId(); - const auto userId = DistributedData::AccountDelegate::GetInstance()->GetUserByToken(token); - StoreMetaData saveMeta; + + if (executors_ == nullptr) { + ZLOGE("executors_ is nullptr"); + return OBJECT_INNER_ERROR; + } + executors_->Schedule(std::chrono::seconds(WAIT_ACCOUNT_SERVICE), [this]() { + StoreMetaData saveMeta; + SaveMetaData(saveMeta); + ObjectStoreManager::GetInstance().SetData(saveMeta.dataDir, saveMeta.user); + ObjectStoreManager::GetInstance().InitUserMeta(); + RegisterObjectServiceInfo(); + RegisterHandler(); + ObjectDmsHandler::GetInstance().RegisterDmsEvent(); + }); + + return OBJECT_SUCCESS; +} + +int32_t ObjectServiceImpl::SaveMetaData(StoreMetaData &saveMeta) +{ + auto localDeviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + if (localDeviceId.empty()) { + ZLOGE("failed to get local device id"); + return OBJECT_INNER_ERROR; + } saveMeta.appType = "default"; saveMeta.deviceId = localDeviceId; saveMeta.storeId = DistributedObject::ObjectCommon::OBJECTSTORE_DB_STOREID; @@ -145,17 +172,23 @@ int32_t ObjectServiceImpl::OnInitialize() saveMeta.isEncrypt = false; saveMeta.bundleName = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); saveMeta.appId = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); - saveMeta.user = std::to_string(userId); - saveMeta.account = accountId; - saveMeta.tokenId = token; + saveMeta.account = DistributedData::AccountDelegate::GetInstance()->GetCurrentAccountId(); + saveMeta.tokenId = IPCSkeleton::GetCallingTokenID(); saveMeta.securityLevel = DistributedKv::SecurityLevel::S1; saveMeta.area = DistributedKv::Area::EL1; saveMeta.uid = IPCSkeleton::GetCallingUid(); saveMeta.storeType = ObjectDistributedType::OBJECT_SINGLE_VERSION; saveMeta.dataType = DistributedKv::DataType::TYPE_DYNAMICAL; - saveMeta.dataDir = DistributedData::DirectoryManager::GetInstance().GetStorePath(saveMeta); - ObjectStoreManager::GetInstance()->SetData(saveMeta.dataDir, std::to_string(userId)); - bool isSaved = DistributedData::MetaDataManager::GetInstance().SaveMeta(saveMeta.GetKey(), saveMeta) && + saveMeta.authType = DistributedKv::AuthType::IDENTICAL_ACCOUNT; + int foregroundUserId = 0; + DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + saveMeta.user = std::to_string(foregroundUserId); + saveMeta.dataDir = METADATA_STORE_PATH; + if (!DistributedData::DirectoryManager::GetInstance().CreateDirectory(saveMeta.dataDir)) { + ZLOGE("Create directory error, dataDir: %{public}s.", Anonymous::Change(saveMeta.dataDir).c_str()); + return OBJECT_INNER_ERROR; + } + bool isSaved = DistributedData::MetaDataManager::GetInstance().SaveMeta(saveMeta.GetKeyWithoutPath(), saveMeta) && DistributedData::MetaDataManager::GetInstance().SaveMeta(saveMeta.GetKey(), saveMeta, true); if (!isSaved) { ZLOGE("SaveMeta failed"); @@ -168,18 +201,21 @@ int32_t ObjectServiceImpl::OnInitialize() if (!isSaved) { ZLOGE("Save appIdMeta failed"); } - ZLOGI("SaveMeta success appId %{public}s, storeId %{public}s", - saveMeta.appId.c_str(), saveMeta.GetStoreAlias().c_str()); - RegisterObjectServiceInfo(); - RegisterHandler(); - ObjectDmsHandler::GetInstance().RegisterDmsEvent(); + ZLOGI("SaveMeta success appId %{public}s, storeId %{public}s", saveMeta.appId.c_str(), + saveMeta.GetStoreAlias().c_str()); return OBJECT_SUCCESS; } int32_t ObjectServiceImpl::OnUserChange(uint32_t code, const std::string &user, const std::string &account) { if (code == static_cast(AccountStatus::DEVICE_ACCOUNT_SWITCHED)) { - Clear(); + int32_t status = ObjectStoreManager::GetInstance().Clear(); + if (status != OBJECT_SUCCESS) { + ZLOGE("Clear fail user:%{public}s, status: %{public}d", user.c_str(), status); + } + StoreMetaData saveMeta; + SaveMetaData(saveMeta); + ObjectStoreManager::GetInstance().SetData(saveMeta.dataDir, saveMeta.user); } return Feature::OnUserChange(code, user, account); } @@ -193,7 +229,7 @@ int32_t ObjectServiceImpl::ObjectStoreRevokeSave( if (status != OBJECT_SUCCESS) { return status; } - status = ObjectStoreManager::GetInstance()->RevokeSave(bundleName, sessionId, callback); + status = ObjectStoreManager::GetInstance().RevokeSave(bundleName, sessionId, callback); if (status != OBJECT_SUCCESS) { ZLOGE("revoke save fail %{public}d", status); return status; @@ -210,7 +246,7 @@ int32_t ObjectServiceImpl::ObjectStoreRetrieve( if (status != OBJECT_SUCCESS) { return status; } - status = ObjectStoreManager::GetInstance()->Retrieve(bundleName, sessionId, callback, tokenId); + status = ObjectStoreManager::GetInstance().Retrieve(bundleName, sessionId, callback, tokenId); if (status != OBJECT_SUCCESS) { ZLOGE("retrieve fail %{public}d", status); return status; @@ -228,7 +264,7 @@ int32_t ObjectServiceImpl::RegisterDataObserver( return status; } auto pid = IPCSkeleton::GetCallingPid(); - ObjectStoreManager::GetInstance()->RegisterRemoteCallback(bundleName, sessionId, pid, tokenId, callback); + ObjectStoreManager::GetInstance().RegisterRemoteCallback(bundleName, sessionId, pid, tokenId, callback); return OBJECT_SUCCESS; } @@ -241,7 +277,32 @@ int32_t ObjectServiceImpl::UnregisterDataChangeObserver(const std::string &bundl return status; } auto pid = IPCSkeleton::GetCallingPid(); - ObjectStoreManager::GetInstance()->UnregisterRemoteCallback(bundleName, pid, tokenId, sessionId); + ObjectStoreManager::GetInstance().UnregisterRemoteCallback(bundleName, pid, tokenId, sessionId); + return OBJECT_SUCCESS; +} + +int32_t ObjectServiceImpl::RegisterProgressObserver( + const std::string &bundleName, const std::string &sessionId, sptr callback) +{ + uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); + int32_t status = IsBundleNameEqualTokenId(bundleName, sessionId, tokenId); + if (status != OBJECT_SUCCESS) { + return status; + } + auto pid = IPCSkeleton::GetCallingPid(); + ObjectStoreManager::GetInstance().RegisterProgressObserverCallback(bundleName, sessionId, pid, tokenId, callback); + return OBJECT_SUCCESS; +} + +int32_t ObjectServiceImpl::UnregisterProgressObserver(const std::string &bundleName, const std::string &sessionId) +{ + uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); + int32_t status = IsBundleNameEqualTokenId(bundleName, sessionId, tokenId); + if (status != OBJECT_SUCCESS) { + return status; + } + auto pid = IPCSkeleton::GetCallingPid(); + ObjectStoreManager::GetInstance().UnregisterProgressObserverCallback(bundleName, pid, tokenId, sessionId); return OBJECT_SUCCESS; } @@ -252,7 +313,7 @@ int32_t ObjectServiceImpl::DeleteSnapshot(const std::string &bundleName, const s if (status != OBJECT_SUCCESS) { return status; } - ObjectStoreManager::GetInstance()->DeleteSnapshot(bundleName, sessionId); + ObjectStoreManager::GetInstance().DeleteSnapshot(bundleName, sessionId); return OBJECT_SUCCESS; } @@ -264,8 +325,7 @@ int32_t ObjectServiceImpl::IsBundleNameEqualTokenId( storeInfo.tokenId = tokenId; storeInfo.bundleName = bundleName; storeInfo.storeId = sessionId; - std::string appId = DistributedData::CheckerManager::GetInstance().GetAppId(storeInfo); - if (appId.empty()) { + if (!CheckerManager::GetInstance().IsValid(storeInfo)) { ZLOGE("object bundleName wrong, bundleName = %{public}s, uid = %{public}d, tokenId = %{public}s", bundleName.c_str(), storeInfo.uid, Anonymous::Change(std::to_string(storeInfo.tokenId)).c_str()); return OBJECT_PERMISSION_DENIED; @@ -273,18 +333,9 @@ int32_t ObjectServiceImpl::IsBundleNameEqualTokenId( return OBJECT_SUCCESS; } -void ObjectServiceImpl::Clear() -{ - ZLOGI("begin."); - int32_t status = ObjectStoreManager::GetInstance()->Clear(); - if (status != OBJECT_SUCCESS) { - ZLOGE("save fail %{public}d", status); - } -} - int32_t ObjectServiceImpl::ObjectStatic::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index) { - int32_t result = ObjectStoreManager::GetInstance()->DeleteByAppId(bundleName, user); + int32_t result = ObjectStoreManager::GetInstance().DeleteByAppId(bundleName, user); if (result != OBJECT_SUCCESS) { ZLOGE("Delete object data failed, result:%{public}d, bundleName:%{public}s, user:%{public}d, index:%{public}d", result, bundleName.c_str(), user, index); @@ -318,13 +369,10 @@ int32_t ObjectServiceImpl::ResolveAutoLaunch(const std::string &identifier, Dist continue; } if (storeMeta.bundleName == DistributedData::Bootstrap::GetInstance().GetProcessLabel()) { - int32_t status = DistributedObject::ObjectStoreManager::GetInstance()->Open(); + int32_t status = DistributedObject::ObjectStoreManager::GetInstance().AutoLaunchStore(); if (status != OBJECT_SUCCESS) { - ZLOGE("Open fail %{public}d", status); continue; } - DistributedObject::ObjectStoreManager::GetInstance()->CloseAfterMinute(); - ZLOGI("Auto launch, close after a minute"); return OBJECT_SUCCESS; } } @@ -335,7 +383,8 @@ int32_t ObjectServiceImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, con { ZLOGI("ObjectServiceImpl::OnAppExit uid=%{public}d, pid=%{public}d, tokenId=%{public}d, bundleName=%{public}s", uid, pid, tokenId, appId.c_str()); - ObjectStoreManager::GetInstance()->UnregisterRemoteCallback(appId, pid, tokenId); + ObjectStoreManager::GetInstance().UnregisterRemoteCallback(appId, pid, tokenId); + ObjectStoreManager::GetInstance().UnregisterProgressObserverCallback(appId, pid, tokenId); return FeatureSystem::STUB_SUCCESS; } @@ -349,7 +398,7 @@ ObjectServiceImpl::ObjectServiceImpl() meta.bundleName = eventInfo.bundleName; meta.user = std::to_string(eventInfo.user); meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) { + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyWithoutPath(), meta)) { ZLOGE("meta empty, bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); return; @@ -359,7 +408,7 @@ ObjectServiceImpl::ObjectServiceImpl() ZLOGE("store null, storeId:%{public}s", meta.GetStoreAlias().c_str()); return; } - auto bindAssets = ObjectStoreManager::GetInstance()->GetSnapShots(eventInfo.bundleName, eventInfo.storeName); + auto bindAssets = ObjectStoreManager::GetInstance().GetSnapShots(eventInfo.bundleName, eventInfo.storeName); store->BindSnapshots(bindAssets); }; EventCenter::GetInstance().Subscribe(BindEvent::BIND_SNAPSHOT, process); @@ -377,8 +426,9 @@ void ObjectServiceImpl::RegisterObjectServiceInfo() void ObjectServiceImpl::RegisterHandler() { - Handler handler = - std::bind(&ObjectServiceImpl::DumpObjectServiceInfo, this, std::placeholders::_1, std::placeholders::_2); + Handler handler = [this](int fd, std::map> ¶ms) { + DumpObjectServiceInfo(fd, params); + }; DumpManager::GetInstance().AddHandler("FEATURE_INFO", uintptr_t(this), handler); } @@ -392,13 +442,14 @@ void ObjectServiceImpl::DumpObjectServiceInfo(int fd, std::mapSetThreadPool(executors_); - ObjectAssetLoader::GetInstance()->SetThreadPool(executors_); + ObjectStoreManager::GetInstance().SetThreadPool(executors_); + ObjectAssetLoader::GetInstance().SetThreadPool(executors_); return 0; } } // namespace OHOS::DistributedObject diff --git a/datamgr_service/services/distributeddataservice/service/object/src/object_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/object/src/object_service_stub.cpp index 20255eab..a5d521a3 100644 --- a/datamgr_service/services/distributeddataservice/service/object/src/object_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/src/object_service_stub.cpp @@ -26,6 +26,7 @@ namespace OHOS::DistributedObject { using namespace DistributedKv; +using Anonymous = DistributedData::Anonymous; int32_t ObjectServiceStub::ObjectStoreSaveOnRemote(MessageParcel &data, MessageParcel &reply) { std::string sessionId; @@ -61,7 +62,7 @@ int32_t ObjectServiceStub::OnAssetChangedOnRemote(MessageParcel &data, MessagePa } ObjectStore::Asset assetValue; if (!ITypesUtil::Unmarshalling(assetValue, data)) { - ZLOGE("Unmarshal assetValue fail, asset name: %{public}s", assetValue.name.c_str()); + ZLOGE("Unmarshal assetValue fail, asset name: %{public}s", Anonymous::Change(assetValue.name).c_str()); return IPC_STUB_INVALID_DATA_ERR; } int32_t status = OnAssetChanged(bundleName, sessionId, deviceId, assetValue); @@ -80,8 +81,8 @@ int32_t ObjectServiceStub::ObjectStoreBindAssetOnRemote(MessageParcel &data, Mes ObjectStore::AssetBindInfo bindInfo; if (!ITypesUtil::Unmarshal(data, bundleName, sessionId, asset, bindInfo)) { ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s assetName:%{public}s bindStore:%{public}s", - DistributedData::Anonymous::Change(sessionId).c_str(), bundleName.c_str(), - asset.name.c_str(), bindInfo.storeName.c_str()); + Anonymous::Change(sessionId).c_str(), bundleName.c_str(), Anonymous::Change(asset.name).c_str(), + Anonymous::Change(bindInfo.storeName).c_str()); return IPC_STUB_INVALID_DATA_ERR; } @@ -164,6 +165,41 @@ int32_t ObjectServiceStub::OnUnsubscribeRequest(MessageParcel &data, MessageParc return 0; } +int32_t ObjectServiceStub::OnSubscribeProgress(MessageParcel &data, MessageParcel &reply) +{ + std::string sessionId; + std::string bundleName; + sptr obj; + if (!ITypesUtil::Unmarshal(data, bundleName, sessionId, obj) || obj == nullptr) { + ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s, callback is nullptr: %{public}d", + DistributedData::Anonymous::Change(sessionId).c_str(), bundleName.c_str(), obj == nullptr); + return IPC_STUB_INVALID_DATA_ERR; + } + int32_t status = RegisterProgressObserver(bundleName, sessionId, obj); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return status; +} + +int32_t ObjectServiceStub::OnUnsubscribeProgress(MessageParcel &data, MessageParcel &reply) +{ + std::string sessionId; + std::string bundleName; + if (!ITypesUtil::Unmarshal(data, bundleName, sessionId)) { + ZLOGE("Unmarshal sessionId:%{public}s bundleName:%{public}s", + DistributedData::Anonymous::Change(sessionId).c_str(), bundleName.c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + int32_t status = UnregisterProgressObserver(bundleName, sessionId); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return status; +} + int32_t ObjectServiceStub::OnDeleteSnapshot(MessageParcel &data, MessageParcel &reply) { std::string sessionId; diff --git a/datamgr_service/services/distributeddataservice/service/permission/BUILD.gn b/datamgr_service/services/distributeddataservice/service/permission/BUILD.gn index 0f28d277..c6a4e1f1 100644 --- a/datamgr_service/services/distributeddataservice/service/permission/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/permission/BUILD.gn @@ -36,7 +36,6 @@ ohos_source_set("distributeddata_permit") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] include_dirs = [ @@ -52,12 +51,10 @@ ohos_source_set("distributeddata_permit") { "-Wno-c99-designator", "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Oz", - "-fstack-protector-strong", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk", - "${data_service_path}/service/crypto:distributeddata_crypto", ] external_deps = [ "access_token:libaccesstoken_sdk", diff --git a/datamgr_service/services/distributeddataservice/service/permission/src/permit_delegate.cpp b/datamgr_service/services/distributeddataservice/service/permission/src/permit_delegate.cpp index d3d02087..dd5b3c2c 100644 --- a/datamgr_service/services/distributeddataservice/service/permission/src/permit_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/service/permission/src/permit_delegate.cpp @@ -102,13 +102,13 @@ bool PermitDelegate::VerifyPermission(const CheckParam ¶m, uint8_t flag) } return !value.empty(); }); - auto key = data.GetKey(); + auto key = data.GetKeyWithoutPath(); if (!metaDataBucket_.Get(key, data)) { if (!MetaDataManager::GetInstance().LoadMeta(key, data)) { - ZLOGE("load meta failed."); + ZLOGE("load meta failed, %{public}s", Anonymous::Change(data.storeId).c_str()); return false; } - metaDataBucket_.Set(data.GetKey(), data); + metaDataBucket_.Set(data.GetKeyWithoutPath(), data); } if (data.appType.compare("default") == 0) { ZLOGD("default, sync permission success."); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/BUILD.gn b/datamgr_service/services/distributeddataservice/service/rdb/BUILD.gn index ad693d92..4273bba4 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/rdb/BUILD.gn @@ -63,13 +63,11 @@ ohos_source_set("distributeddata_rdb") { "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Werror", "-Oz", - "-fstack-protector-strong", ] deps = [ "${data_service_path}/service/bootstrap:distributeddata_bootstrap", "${data_service_path}/service/common:distributeddata_common", - "${data_service_path}/service/crypto:distributeddata_crypto", "${data_service_path}/service/matrix:distributeddata_matrix", "${data_service_path}/service/permission:distributeddata_permit", ] @@ -97,7 +95,6 @@ ohos_source_set("distributeddata_rdb") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.cpp b/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.cpp index 4c3b04d3..e9ce03d3 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.cpp @@ -23,13 +23,13 @@ using namespace OHOS::DistributedData; CacheCursor::CacheCursor(std::vector &&records) : row_(0), maxCol_(0), records_(std::move(records)) { - maxRow_ = records_.size(); + maxRow_ = static_cast(records_.size()); if (maxRow_ > 0) { for (auto it = records_[0].begin(); it != records_[0].end(); it++) { colNames_.push_back(it->first); colTypes_.push_back(it->second.index()); } - maxCol_ = colNames_.size(); + maxCol_ = static_cast(colNames_.size()); } } diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp index 801af00c..00059689 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp @@ -27,8 +27,8 @@ using namespace DistributedDB; using ValueProxy = OHOS::DistributedData::ValueProxy; namespace OHOS::DistributedRdb { -RdbAssetLoader::RdbAssetLoader(std::shared_ptr cloudAssetLoader, BindAssets* bindAssets) - : assetLoader_(std::move(cloudAssetLoader)), snapshots_(bindAssets) +RdbAssetLoader::RdbAssetLoader(std::shared_ptr cloudAssetLoader, BindAssets bindAssets) + : assetLoader_(std::move(cloudAssetLoader)), snapshots_(std::move(bindAssets)) { } @@ -169,11 +169,11 @@ void RdbAssetLoader::PostEvent(DistributedData::AssetEvent eventId, DistributedD deleteAssets.insert(downLoadAsset.uri); continue; } - if (snapshots_ == nullptr || snapshots_->bindAssets == nullptr) { + if (snapshots_ == nullptr) { continue; } - auto it = snapshots_->bindAssets->find(downLoadAsset.uri); - if (it == snapshots_->bindAssets->end() || it->second == nullptr) { + auto it = snapshots_->find(downLoadAsset.uri); + if (it == snapshots_->end() || it->second == nullptr) { continue; } auto snapshot = it->second; @@ -185,7 +185,7 @@ void RdbAssetLoader::PostEvent(DistributedData::AssetEvent eventId, DistributedD } else { auto skipPos = skipAssets.find(downLoadAsset.uri); auto deletePos = deleteAssets.find(downLoadAsset.uri); - if (skipPos != skipAssets.end() || deletePos != skipAssets.end()) { + if (skipPos != skipAssets.end() || deletePos != deleteAssets.end()) { continue; } snapshot->Downloaded(downLoadAsset); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h index 1eb7b3e7..2e05a0ab 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h @@ -23,18 +23,19 @@ #include "snapshot/snapshot.h" namespace OHOS::DistributedRdb { +using Snapshot = DistributedData::Snapshot; +using BindAssets = std::shared_ptr>>; class RdbAssetLoader : public DistributedDB::IAssetLoader { public: using Type = DistributedDB::Type; using Asset = DistributedDB::Asset; using DBStatus = DistributedDB::DBStatus; - using BindAssets = DistributedData::BindAssets; using AssetsRecord = DistributedData::AssetRecord; using AssetStatus = DistributedData::Asset::Status; using GeneralError = DistributedData::GeneralError; using VBucket = DistributedData::VBucket; - explicit RdbAssetLoader(std::shared_ptr cloudAssetLoader, BindAssets *bindAssets); + explicit RdbAssetLoader(std::shared_ptr cloudAssetLoader, BindAssets bindAssets); ~RdbAssetLoader() = default; @@ -61,7 +62,7 @@ private: std::set &skipAssets, std::set &deleteAssets); std::shared_ptr assetLoader_; - BindAssets *snapshots_; + const BindAssets snapshots_; }; } // namespace OHOS::DistributedRdb #endif // OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_ASSET_LOADER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp index 0a072607..13a50912 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp @@ -26,8 +26,8 @@ namespace OHOS::DistributedRdb { using namespace DistributedDB; using namespace DistributedData; -RdbCloud::RdbCloud(std::shared_ptr cloudDB, BindAssets* bindAssets) - : cloudDB_(std::move(cloudDB)), snapshots_(bindAssets) +RdbCloud::RdbCloud(std::shared_ptr cloudDB, BindAssets bindAssets) + : cloudDB_(std::move(cloudDB)), snapshots_(std::move(bindAssets)) { } @@ -76,17 +76,18 @@ DBStatus RdbCloud::Query(const std::string &tableName, DBVBucket &extend, std::v { auto [nodes, status] = ConvertQuery(extend); std::shared_ptr cursor = nullptr; + int32_t code = E_OK; if (status == GeneralError::E_OK && !nodes.empty()) { RdbQuery query; query.SetQueryNodes(tableName, std::move(nodes)); - cursor = cloudDB_->Query(query, ValueProxy::Convert(std::move(extend))); + std::tie(code, cursor) = cloudDB_->Query(query, ValueProxy::Convert(std::move(extend))); } else { - cursor = cloudDB_->Query(tableName, ValueProxy::Convert(std::move(extend))); + std::tie(code, cursor) = cloudDB_->Query(tableName, ValueProxy::Convert(std::move(extend))); } - if (cursor == nullptr) { + if (cursor == nullptr || code != E_OK) { ZLOGE("cursor is null, table:%{public}s, extend:%{public}zu", Anonymous::Change(tableName).c_str(), extend.size()); - return ConvertStatus(static_cast(E_ERROR)); + return ConvertStatus(static_cast(code != E_OK ? code : E_ERROR)); } int32_t count = cursor->GetCount(); data.reserve(count); @@ -305,11 +306,11 @@ void RdbCloud::PostEvent(DistributedData::Value& value, DataBucket& extend, std: void RdbCloud::PostEventAsset(DistributedData::Asset& asset, DataBucket& extend, std::set& skipAssets, DistributedData::AssetEvent eventId) { - if (snapshots_->bindAssets == nullptr) { + if (snapshots_ == nullptr) { return; } - auto it = snapshots_->bindAssets->find(asset.uri); - if (it == snapshots_->bindAssets->end() || it->second == nullptr) { + auto it = snapshots_->find(asset.uri); + if (it == snapshots_->end() || it->second == nullptr) { return; } diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h index 1a3f37e5..7901cd75 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h @@ -25,6 +25,8 @@ #include "snapshot/snapshot.h" namespace OHOS::DistributedRdb { +using Snapshot = DistributedData::Snapshot; +using BindAssets = std::shared_ptr>>; class RdbCloud : public DistributedDB::ICloudDb { public: enum FLAG : uint8_t { @@ -35,10 +37,9 @@ public: using DBVBucket = DistributedDB::VBucket; using DBQueryNodes = std::vector; using DataBucket = DistributedData::VBucket; - using BindAssets = DistributedData::BindAssets; using GeneralError = DistributedData::GeneralError; - explicit RdbCloud(std::shared_ptr cloudDB, BindAssets* bindAssets); + explicit RdbCloud(std::shared_ptr cloudDB, BindAssets bindAssets); virtual ~RdbCloud() = default; DBStatus BatchInsert(const std::string &tableName, std::vector &&record, std::vector &extend) override; @@ -67,7 +68,7 @@ private: static void ConvertErrorField(DistributedData::VBuckets& extends); static constexpr int32_t TO_MS = 1000; // s > ms std::shared_ptr cloudDB_; - BindAssets* snapshots_; + const BindAssets snapshots_; uint8_t flag_ = 0; std::mutex mutex_; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp index 87e15dac..d6b43d5b 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp @@ -26,10 +26,10 @@ #include "cloud/cloud_mark.h" #include "cloud/cloud_store_types.h" #include "cloud/schema_meta.h" +#include "device_sync_app/device_sync_app_manager.h" #include "cloud_service.h" #include "commonevent/data_sync_event.h" -#include "communicator/device_manager_adapter.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter.h" #include "dfx/dfx_types.h" #include "dfx/reporter.h" @@ -38,13 +38,12 @@ #include "metadata/meta_data_manager.h" #include "metadata/secret_key_meta_data.h" #include "rdb_cursor.h" -#include "rdb_helper.h" #include "rdb_query.h" -#include "rdb_result_set_impl.h" #include "relational_store_manager.h" #include "snapshot/bind_event.h" #include "utils/anonymous.h" #include "value_proxy.h" +#include "snapshot/snapshot.h" namespace OHOS::DistributedRdb { using namespace DistributedData; using namespace DistributedDB; @@ -62,6 +61,7 @@ constexpr const char *INSERT = "INSERT INTO "; constexpr const char *REPLACE = "REPLACE INTO "; constexpr const char *VALUES = " VALUES "; constexpr const char *LOGOUT_DELETE_FLAG = "DELETE#ALL_CLOUDDATA"; +constexpr const char *LOGOUT_RESERVE_FLAG = "RESERVE#ALL_CLOUDDATA"; constexpr const LockAction LOCK_ACTION = static_cast(static_cast(LockAction::INSERT) | static_cast(LockAction::UPDATE) | static_cast(LockAction::DELETE) | static_cast(LockAction::DOWNLOAD)); @@ -141,8 +141,9 @@ void RdbGeneralStore::InitStoreInfo(const StoreMetaData &meta) storeInfo_.bundleName = meta.bundleName; storeInfo_.storeName = meta.storeId; storeInfo_.instanceId = meta.instanceId; - storeInfo_.user = std::stoi(meta.user); + storeInfo_.user = std::atoi(meta.user.c_str()); storeInfo_.deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + storeInfo_.path = meta.dataDir; } RelationalStoreDelegate::Option GetOption(const StoreMetaData &meta) @@ -155,21 +156,37 @@ RelationalStoreDelegate::Option GetOption(const StoreMetaData &meta) return option; } +RdbGeneralStore::DBPassword RdbGeneralStore::GetDBPassword(const StoreMetaData &data) +{ + DBPassword dbPassword; + SecretKeyMetaData secretKey; + auto metaKey = data.GetSecretKey(); + if (!MetaDataManager::GetInstance().LoadMeta(metaKey, secretKey, true) || secretKey.sKey.empty()) { + return dbPassword; + } + CryptoManager::CryptoParams decryptParams = { .area = secretKey.area, .userId = data.user, + .nonce = secretKey.nonce }; + auto password = CryptoManager::GetInstance().Decrypt(secretKey.sKey, decryptParams); + if (password.empty()) { + return dbPassword; + } + // update secret key of area or nonce + CryptoManager::GetInstance().UpdateSecretMeta(password, data, metaKey, secretKey); + dbPassword.SetValue(password.data(), password.size()); + password.assign(password.size(), 0); + return dbPassword; +} + RdbGeneralStore::RdbGeneralStore(const StoreMetaData &meta) : manager_(meta.appId, meta.user, meta.instanceId), tasks_(std::make_shared>()) { observer_.storeId_ = meta.storeId; observer_.meta_ = meta; RelationalStoreDelegate::Option option = GetOption(meta); + option.isNeedCompressOnSync = true; option.observer = &observer_; if (meta.isEncrypt) { - std::string key = meta.GetSecretKey(); - SecretKeyMetaData secretKeyMeta; - MetaDataManager::GetInstance().LoadMeta(key, secretKeyMeta, true); - std::vector decryptKey; - CryptoManager::GetInstance().Decrypt(meta, secretKeyMeta, decryptKey); - option.passwd.SetValue(decryptKey.data(), decryptKey.size()); - std::fill(decryptKey.begin(), decryptKey.end(), 0); + option.passwd = GetDBPassword(meta); option.isEncryptedDb = meta.isEncrypt; option.cipher = CipherType::AES_256_GCM; for (uint32_t i = 0; i < ITERS_COUNT; ++i) { @@ -197,15 +214,15 @@ RdbGeneralStore::RdbGeneralStore(const StoreMetaData &meta) delegate_->Pragma(PragmaCmd::LOGIC_DELETE_SYNC_DATA, data); } ZLOGI("Get rdb store, tokenId:%{public}u, bundleName:%{public}s, storeName:%{public}s, user:%{public}s," - "isEncrypt:%{public}d, isManualClean:%{public}d, isSearchable:%{public}d, path:%{public}s", - meta.tokenId, meta.bundleName.c_str(), Anonymous::Change(meta.storeId).c_str(), meta.user.c_str(), - meta.isEncrypt, meta.isManualClean, meta.isSearchable, meta.dataDir.c_str()); + "isEncrypt:%{public}d, isManualClean:%{public}d, isSearchable:%{public}d", + meta.tokenId, meta.bundleName.c_str(), Anonymous::Change(meta.storeId).c_str(), meta.user.c_str(), + meta.isEncrypt, meta.isManualClean, meta.isSearchable); } RdbGeneralStore::~RdbGeneralStore() { - ZLOGI("Destruct. BundleName: %{public}s. StoreName: %{public}s. user: %{public}d", storeInfo_.bundleName.c_str(), - Anonymous::Change(storeInfo_.storeName).c_str(), storeInfo_.user); + ZLOGI("Destruct. BundleName: %{public}s. StoreName: %{public}s. user: %{public}d", + storeInfo_.bundleName.c_str(), Anonymous::Change(storeInfo_.storeName).c_str(), storeInfo_.user); manager_.CloseStore(delegate_); delegate_ = nullptr; bindInfo_.loader_ = nullptr; @@ -220,10 +237,10 @@ RdbGeneralStore::~RdbGeneralStore() executor_ = nullptr; } -int32_t RdbGeneralStore::BindSnapshots(std::shared_ptr>> bindAssets) +int32_t RdbGeneralStore::BindSnapshots(BindAssets bindAssets) { - if (snapshots_.bindAssets == nullptr) { - snapshots_.bindAssets = bindAssets; + if (snapshots_ == nullptr) { + snapshots_ = bindAssets; } return GenErr::E_OK; } @@ -255,14 +272,15 @@ int32_t RdbGeneralStore::Bind(const Database &database, const std::map lock(rdbCloudMutex_); - rdbCloud_ = std::make_shared(bindInfo_.db_, &snapshots_); - rdbLoader_ = std::make_shared(bindInfo_.loader_, &snapshots_); + rdbCloud_ = std::make_shared(bindInfo_.db_, snapshots_); + rdbLoader_ = std::make_shared(bindInfo_.loader_, snapshots_); } DistributedDB::CloudSyncConfig dbConfig; dbConfig.maxUploadCount = config.maxNumber; dbConfig.maxUploadSize = config.maxSize; dbConfig.maxRetryConflictTimes = config.maxRetryConflictTimes; + dbConfig.isSupportEncrypt = config.isSupportEncrypt; DBSchema schema = GetDBSchema(database); std::shared_lock lock(rwMutex_); if (delegate_ == nullptr) { @@ -295,7 +313,8 @@ int32_t RdbGeneralStore::Close(bool isForce) return GeneralError::E_OK; } auto [dbStatus, downloadCount] = delegate_->GetDownloadingAssetsCount(); - if (!isForce && (delegate_->GetCloudSyncTaskCount() > 0 || downloadCount > 0)) { + if (!isForce && + (delegate_->GetCloudSyncTaskCount() > 0 || downloadCount > 0 || delegate_->GetDeviceSyncTaskCount() > 0)) { return GeneralError::E_BUSY; } auto status = manager_.CloseStore(delegate_); @@ -331,7 +350,7 @@ int32_t RdbGeneralStore::Execute(const std::string &table, const std::string &sq auto status = delegate_->ExecuteSql({ sql, {}, false }, changedData); if (status != DBStatus::OK) { ZLOGE("Execute failed! ret:%{public}d, sql:%{public}s, data size:%{public}zu", status, - Anonymous::Change(sql).c_str(), changedData.size()); + Anonymous::Change(sql).c_str(), changedData.size()); if (status == DBStatus::BUSY) { return GeneralError::E_BUSY; } @@ -402,8 +421,8 @@ int32_t RdbGeneralStore::Insert(const std::string &table, VBuckets &&values) if (IsPrintLog(status)) { auto time = static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); - ZLOGE("Failed! ret:%{public}d, sql:%{public}s, data size:%{public}zu times %{public}" PRIu64 ".", status, - Anonymous::Change(sql).c_str(), changedData.size(), time); + ZLOGE("Failed! ret:%{public}d, sql:%{public}s, data size:%{public}zu times %{public}" PRIu64 ".", + status, Anonymous::Change(sql).c_str(), changedData.size(), time); } return GeneralError::E_ERROR; } @@ -463,8 +482,8 @@ int32_t RdbGeneralStore::Update(const std::string &table, const std::string &set } auto status = delegate_->ExecuteSql({ sqlIn, std::move(bindArgs), false }, changedData); if (status != DBStatus::OK) { - ZLOGE("Failed! ret:%{public}d, sql:%{public}s, data size:%{public}zu", status, - Anonymous::Change(sqlIn).c_str(), changedData.size()); + ZLOGE("Failed! ret:%{public}d, sql:%{public}s, data size:%{public}zu", status, Anonymous::Change(sqlIn).c_str(), + changedData.size()); return GeneralError::E_ERROR; } return GeneralError::E_OK; @@ -494,8 +513,8 @@ int32_t RdbGeneralStore::Replace(const std::string &table, VBucket &&value) } auto status = delegate_->ExecuteSql({ sql, std::move(bindArgs) }, changedData); if (status != DBStatus::OK) { - ZLOGE("Replace failed! ret:%{public}d, table:%{public}s, sql:%{public}s, fields:%{public}s", status, - Anonymous::Change(table).c_str(), Anonymous::Change(sql).c_str(), columnSql.c_str()); + ZLOGE("Replace failed! ret:%{public}d, table:%{public}s, sql:%{public}s, fields:%{public}s", + status, Anonymous::Change(table).c_str(), Anonymous::Change(sql).c_str(), columnSql.c_str()); if (status == DBStatus::BUSY) { return GeneralError::E_BUSY; } @@ -509,7 +528,7 @@ int32_t RdbGeneralStore::Delete(const std::string &table, const std::string &sql return 0; } -std::pair> RdbGeneralStore::Query(__attribute__((unused)) const std::string &table, +std::pair> RdbGeneralStore::Query(__attribute__((unused))const std::string &table, const std::string &sql, Values &&args) { std::shared_lock lock(rwMutex_); @@ -541,7 +560,7 @@ std::pair> RdbGeneralStore::Query(const std::st return { GeneralError::E_ERROR, nullptr }; } auto cursor = RemoteQuery(*rdbQuery->GetDevices().begin(), rdbQuery->GetRemoteCondition()); - return { cursor != nullptr ? GeneralError::E_OK : GeneralError::E_ERROR, cursor }; + return { cursor != nullptr ? GeneralError::E_OK : GeneralError::E_ERROR, cursor}; } return { GeneralError::E_ERROR, nullptr }; } @@ -564,7 +583,7 @@ int32_t RdbGeneralStore::CleanTrackerData(const std::string &tableName, int64_t std::shared_lock lock(rwMutex_); if (delegate_ == nullptr) { ZLOGE("Database already closed! database:%{public}s, table:%{public}s", - Anonymous::Change(storeInfo_.storeName).c_str(), Anonymous::Change(tableName).c_str()); + Anonymous::Change(storeInfo_.storeName).c_str(), Anonymous::Change(tableName).c_str()); return GeneralError::E_ERROR; } @@ -629,9 +648,8 @@ std::pair RdbGeneralStore::Sync(const Devices &devices, GenQue std::shared_lock lock(rwMutex_); if (delegate_ == nullptr) { ZLOGE("store already closed! devices count:%{public}zu, the 1st:%{public}s, mode:%{public}d, " - "wait:%{public}d", - devices.size(), devices.empty() ? "null" : Anonymous::Change(*devices.begin()).c_str(), syncParam.mode, - syncParam.wait); + "wait:%{public}d", devices.size(), + devices.empty() ? "null" : Anonymous::Change(*devices.begin()).c_str(), syncParam.mode, syncParam.wait); return { GeneralError::E_ALREADY_CLOSED, DBStatus::OK }; } auto dbStatus = DistributedDB::INVALID_ARGS; @@ -702,8 +720,8 @@ VBuckets RdbGeneralStore::ExtractExtend(VBuckets &values) const return extends; } -std::string RdbGeneralStore::BuildSql(const std::string &table, const std::string &statement, - const std::vector &columns) const +std::string RdbGeneralStore::BuildSql( + const std::string &table, const std::string &statement, const std::vector &columns) const { std::string sql = "select "; sql.append(CLOUD_GID); @@ -790,7 +808,8 @@ RdbGeneralStore::DBBriefCB RdbGeneralStore::GetDBBriefCB(DetailAsync async) if (!async) { return [](auto &) {}; } - return [async = std::move(async)](const std::map> &result) { + return [async = std::move(async)]( + const std::map> &result) { DistributedData::GenDetails details; for (auto &[key, tables] : result) { auto &value = details[key]; @@ -811,7 +830,7 @@ RdbGeneralStore::DBProcessCB RdbGeneralStore::GetDBProcessCB(DetailAsync async, { std::shared_lock lock(asyncMutex_); return [async, autoAsync = async_, highMode, storeInfo = storeInfo_, flag = syncNotifyFlag_, syncMode, syncId, - rdbCloud = GetRdbCloud()](const std::map &processes) { + rdbCloud = GetRdbCloud()](const std::map &processes) { DistributedData::GenDetails details; for (auto &[id, process] : processes) { bool isDownload = false; @@ -833,9 +852,9 @@ RdbGeneralStore::DBProcessCB RdbGeneralStore::GetDBProcessCB(DetailAsync async, table.download.failed = value.downLoadInfo.failCount; table.download.untreated = table.download.total - table.download.success - table.download.failed; detail.changeCount = (process.process == FINISHED) - ? value.downLoadInfo.insertCount + value.downLoadInfo.updateCount + - value.downLoadInfo.deleteCount - : 0; + ? value.downLoadInfo.insertCount + value.downLoadInfo.updateCount + + value.downLoadInfo.deleteCount + : 0; totalCount += table.download.total; } if (process.process == FINISHED) { @@ -853,8 +872,8 @@ RdbGeneralStore::DBProcessCB RdbGeneralStore::GetDBProcessCB(DetailAsync async, async(details); } - if (highMode == AUTO_SYNC_MODE && autoAsync && - (details.empty() || details.begin()->second.code != E_SYNC_TASK_MERGED)) { + if (highMode == AUTO_SYNC_MODE && autoAsync + && (details.empty() || details.begin()->second.code != E_SYNC_TASK_MERGED)) { autoAsync(details); } }; @@ -897,6 +916,20 @@ void RdbGeneralStore::Report(const std::string &faultType, int32_t errCode, cons Reporter::GetInstance()->CloudSyncFault()->Report(msg); } +int32_t RdbGeneralStore::SetReference(const std::vector &references) +{ + std::vector properties; + for (const auto &reference : references) { + properties.push_back({reference.sourceTable, reference.targetTable, reference.refFields}); + } + auto status = delegate_->SetReference(properties); + if (status != DistributedDB::DBStatus::OK && status != DistributedDB::DBStatus::PROPERTY_CHANGED) { + ZLOGE("distributed table set reference failed, err:%{public}d", status); + return GeneralError::E_ERROR; + } + return GeneralError::E_OK; +} + int32_t RdbGeneralStore::SetDistributedTables(const std::vector &tables, int32_t type, const std::vector &references) { @@ -913,22 +946,24 @@ int32_t RdbGeneralStore::SetDistributedTables(const std::vector &ta ZLOGE("create distributed table failed, table:%{public}s, err:%{public}d", Anonymous::Change(table).c_str(), dBStatus); Report(FT_OPEN_STORE, static_cast(Fault::CSF_GS_CREATE_DISTRIBUTED_TABLE), - "SetDistributedTables ret=" + std::to_string(static_cast(dBStatus))); + "SetDistributedTables: set table(" + Anonymous::Change(table) + ") =" + + std::to_string(static_cast(dBStatus))); return GeneralError::E_ERROR; } } - std::vector properties; - for (const auto &reference : references) { - properties.push_back({ reference.sourceTable, reference.targetTable, reference.refFields }); - } - auto status = delegate_->SetReference(properties); - if (status != DistributedDB::DBStatus::OK && status != DistributedDB::DBStatus::PROPERTY_CHANGED) { - ZLOGE("distributed table set reference failed, err:%{public}d", status); - return GeneralError::E_ERROR; + if (type == DistributedTableType::DISTRIBUTED_CLOUD) { + auto status = SetReference(references); + if (status != GeneralError::E_OK) { + Report(FT_OPEN_STORE, static_cast(Fault::CSF_GS_CREATE_DISTRIBUTED_TABLE), + "SetDistributedTables: set reference=" + std::to_string(static_cast(status))); + return GeneralError::E_ERROR; + } } auto [exist, database] = GetDistributedSchema(observer_.meta_); - if (exist) { - delegate_->SetDistributedSchema(GetGaussDistributedSchema(database)); + if (exist && type == DistributedTableType::DISTRIBUTED_DEVICE) { + auto force = DeviceSyncAppManager::GetInstance().Check( + {observer_.meta_.appId, observer_.meta_.bundleName, database.version}); + delegate_->SetDistributedSchema(GetGaussDistributedSchema(database), force); } CloudMark metaData(storeInfo_); if (MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true) && metaData.isClearWaterMark) { @@ -950,9 +985,10 @@ int32_t RdbGeneralStore::SetDistributedTables(const std::vector &ta void RdbGeneralStore::SetConfig(const StoreConfig &storeConfig) { std::shared_lock lock(rwMutex_); - if (delegate_ == nullptr) { + if (delegate_ == nullptr) { ZLOGE("database already closed!, tableMode is :%{public}d", - storeConfig.tableMode.has_value() ? static_cast(storeConfig.tableMode.value()) : -1); + storeConfig.tableMode.has_value() ? static_cast(storeConfig.tableMode.value()) : -1); + return; } if (storeConfig.tableMode.has_value()) { RelationalStoreDelegate::StoreConfig config; @@ -981,8 +1017,8 @@ int32_t RdbGeneralStore::SetTrackerTable(const std::string &tableName, const std return GeneralError::E_WITH_INVENTORY_DATA; } if (status != DBStatus::OK) { - ZLOGE("Set tracker table failed! ret:%{public}d, database:%{public}s, tables name:%{public}s", status, - Anonymous::Change(storeInfo_.storeName).c_str(), Anonymous::Change(tableName).c_str()); + ZLOGE("Set tracker table failed! ret:%{public}d, database:%{public}s, tables name:%{public}s", + status, Anonymous::Change(storeInfo_.storeName).c_str(), Anonymous::Change(tableName).c_str()); return GeneralError::E_ERROR; } return GeneralError::E_OK; @@ -1083,8 +1119,8 @@ void RdbGeneralStore::OnSyncFinish(const StoreInfo &storeInfo, uint32_t flag, ui return; } StoreInfo info = storeInfo; - auto evt = - std::make_unique(std::move(info), syncMode, DataSyncEvent::DataSyncStatus::FINISH, traceId); + auto evt = std::make_unique(std::move(info), syncMode, DataSyncEvent::DataSyncStatus::FINISH, + traceId); EventCenter::GetInstance().PostEvent(std::move(evt)); } @@ -1116,15 +1152,16 @@ std::vector RdbGeneralStore::GetIntersection(std::vector res; for (auto &it : syncTables) { - if (localTables.count(it) && localTables.count(RelationalStoreManager::GetDistributedLogTableName(it))) { + if (localTables.count(it) && + localTables.count(RelationalStoreManager::GetDistributedLogTableName(it))) { res.push_back(std::move(it)); } } return res; } -void RdbGeneralStore::ObserverProxy::PostDataChange(const StoreMetaData &meta, const std::vector &tables, - ChangeType type) +void RdbGeneralStore::ObserverProxy::PostDataChange(const StoreMetaData &meta, + const std::vector &tables, ChangeType type) { RemoteChangeEvent::DataInfo info; info.userId = meta.user; @@ -1166,9 +1203,9 @@ void RdbGeneralStore::ObserverProxy::OnChange(DBOrigin origin, const std::string ZLOGD("store:%{public}s table:%{public}s data change from :%{public}s", Anonymous::Change(storeId_).c_str(), Anonymous::Change(data.tableName).c_str(), Anonymous::Change(originalId).c_str()); GenOrigin genOrigin; - genOrigin.origin = (origin == DBOrigin::ORIGIN_LOCAL) ? GenOrigin::ORIGIN_LOCAL - : (origin == DBOrigin::ORIGIN_CLOUD) ? GenOrigin::ORIGIN_CLOUD - : GenOrigin::ORIGIN_NEARBY; + genOrigin.origin = (origin == DBOrigin::ORIGIN_LOCAL) + ? GenOrigin::ORIGIN_LOCAL + : (origin == DBOrigin::ORIGIN_CLOUD) ? GenOrigin::ORIGIN_CLOUD : GenOrigin::ORIGIN_NEARBY; genOrigin.dataType = data.type == DistributedDB::ASSET ? GenOrigin::ASSET_DATA : GenOrigin::BASIC_DATA; genOrigin.id.push_back(originalId); genOrigin.store = storeId_; @@ -1190,8 +1227,8 @@ void RdbGeneralStore::ObserverProxy::OnChange(DBOrigin origin, const std::string info.push_back(std::move(value)); continue; } - auto deleteKey = std::get_if(&value); - if (deleteKey != nullptr && (*deleteKey == LOGOUT_DELETE_FLAG)) { + auto key = std::get_if(&value); + if (key != nullptr && (*key == LOGOUT_DELETE_FLAG || *key == LOGOUT_RESERVE_FLAG)) { // notify to start app notifyFlag = true; } @@ -1199,8 +1236,11 @@ void RdbGeneralStore::ObserverProxy::OnChange(DBOrigin origin, const std::string } } if (notifyFlag) { - ZLOGI("post data change for cleaning cloud data"); - PostDataChange(meta_, {}, CLOUD_DATA_CLEAN); + ZLOGI("post data change for cleaning cloud data. store:%{public}s table:%{public}s data change from " + ":%{public}s", + Anonymous::Change(storeId_).c_str(), Anonymous::Change(data.tableName).c_str(), + Anonymous::Change(originalId).c_str()); + PostDataChange(meta_, {}, CLOUD_LOGOUT); } if (!data.field.empty()) { fields[std::move(data.tableName)] = std::move(*(data.field.begin())); @@ -1264,7 +1304,7 @@ Executor::Task RdbGeneralStore::GetFinishTask(SyncId syncId) }); if (cb != nullptr) { ZLOGW("database:%{public}s syncId:%{public}" PRIu64 " miss finished. ", - Anonymous::Change(storeInfo_.storeName).c_str(), syncId); + Anonymous::Change(storeInfo_.storeName).c_str(), syncId); std::map result; result.insert({ "", { DistributedDB::FINISHED, DBStatus::DB_ERROR } }); cb(result); @@ -1289,7 +1329,7 @@ void RdbGeneralStore::RemoveTasks() tasks_->EraseIf([&cbs, &taskIds, store = storeInfo_.storeName](SyncId syncId, const FinishTask &task) { if (task.cb != nullptr) { ZLOGW("database:%{public}s syncId:%{public}" PRIu64 " miss finished. ", Anonymous::Change(store).c_str(), - syncId); + syncId); } cbs.push_back(std::move(task.cb)); taskIds.push_back(task.taskId); @@ -1305,7 +1345,7 @@ void RdbGeneralStore::RemoveTasks() } }; if (executor_ != nullptr) { - for (auto taskId : taskIds) { + for (auto taskId: taskIds) { executor_->Remove(taskId, true); } executor_->Execute([cbs, func]() { diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h index 98b5d2ed..64296b5f 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h @@ -43,8 +43,9 @@ public: using GenErr = DistributedData::GeneralError; using RdbStore = OHOS::NativeRdb::RdbStore; using Reference = DistributedData::Reference; + using DBPassword = DistributedDB::CipherPassword; using Snapshot = DistributedData::Snapshot; - using BindAssets = DistributedData::BindAssets; + using BindAssets = std::shared_ptr>>; explicit RdbGeneralStore(const StoreMetaData &meta); ~RdbGeneralStore(); @@ -83,7 +84,7 @@ public: void SetConfig(const StoreConfig &storeConfig) override; int32_t AddRef() override; int32_t Release() override; - int32_t BindSnapshots(std::shared_ptr>> bindAssets) override; + int32_t BindSnapshots(BindAssets bindAssets) override; int32_t MergeMigratedData(const std::string &tableName, VBuckets&& values) override; int32_t CleanTrackerData(const std::string &tableName, int64_t cursor) override; std::pair LockCloudDB() override; @@ -93,6 +94,7 @@ public: private: RdbGeneralStore(const RdbGeneralStore& rdbGeneralStore); RdbGeneralStore& operator=(const RdbGeneralStore& rdbGeneralStore); + int32_t SetReference(const std::vector &references); using RdbDelegate = DistributedDB::RelationalStoreDelegate; using RdbManager = DistributedDB::RelationalStoreManager; using SyncProcess = DistributedDB::SyncProcess; @@ -130,7 +132,7 @@ private: private: enum ChangeType { CLOUD_DATA_CHANGE = 0, - CLOUD_DATA_CLEAN + CLOUD_LOGOUT, }; void PostDataChange(const StoreMetaData &meta, const std::vector &tables, ChangeType type); friend RdbGeneralStore; @@ -158,6 +160,7 @@ private: std::pair DoCloudSync(const Devices &devices, const DistributedDB::Query &dbQuery, const DistributedData::SyncParam &syncParam, bool isPriority, DetailAsync async); void Report(const std::string &faultType, int32_t errCode, const std::string &appendix); + DBPassword GetDBPassword(const StoreMetaData &data); ObserverProxy observer_; RdbManager manager_; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_schema_config.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_schema_config.cpp index 8bfff9e0..8c1337e6 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_schema_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_schema_config.cpp @@ -39,7 +39,6 @@ bool RdbSchemaConfig::GetDistributedSchema(const StoreMetaData &meta, Database & if (!InitBundleInfo(meta.bundleName, std::atoi(meta.user.c_str()), bundleInfo)) { return false; } - std::string storeName = meta.storeId; auto ret = GetSchemaFromHap(bundleInfo, meta.storeId, database); if (ret) { database.user = meta.user; @@ -99,7 +98,7 @@ bool RdbSchemaConfig::GetSchemaFromHap( std::string jsonData(fileContent.get(), fileContent.get() + length); DbSchema databases; databases.Unmarshall(jsonData); - for (auto &schema : databases.databases) { + for (const auto &schema : databases.databases) { if (schema.name == storeName) { database = schema; return true; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index 886de4a0..43c0c7cf 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -18,6 +18,7 @@ #include "abs_rdb_predicates.h" #include "accesstoken_kit.h" #include "account/account_delegate.h" +#include "bootstrap.h" #include "changeevent/remote_change_event.h" #include "checker/checker_manager.h" #include "cloud/change_event.h" @@ -26,7 +27,6 @@ #include "cloud/make_query_event.h" #include "cloud/schema_meta.h" #include "communicator/device_manager_adapter.h" -#include "crypto_manager.h" #include "device_matrix.h" #include "directory/directory_manager.h" #include "dump/dump_manager.h" @@ -40,11 +40,13 @@ #include "metadata/store_debug_info.h" #include "metadata/store_meta_data.h" #include "metadata/store_meta_data_local.h" +#include "permit_delegate.h" #include "rdb_general_store.h" +#include "rdb_hiview_adapter.h" #include "rdb_notifier_proxy.h" #include "rdb_query.h" -#include "rdb_schema_config.h" #include "rdb_result_set_impl.h" +#include "rdb_schema_config.h" #include "rdb_watcher.h" #include "store/general_store.h" #include "tokenid_kit.h" @@ -53,9 +55,7 @@ #include "utils/constant.h" #include "utils/converter.h" #include "xcollie.h" -#include "permit_delegate.h" -#include "bootstrap.h" -#include "rdb_hiview_adapter.h" +using OHOS::DistributedData::AccountDelegate; using OHOS::DistributedData::Anonymous; using OHOS::DistributedData::CheckerManager; using OHOS::DistributedData::MetaDataManager; @@ -71,6 +71,7 @@ using system_clock = std::chrono::system_clock; constexpr uint32_t ITERATE_TIMES = 10000; constexpr uint32_t ALLOW_ONLINE_AUTO_SYNC = 8; +constexpr int32_t VALID_PARAM_LENGTH = 2; const size_t KEY_COUNT = 2; namespace OHOS::DistributedRdb { __attribute__((used)) RdbServiceImpl::Factory RdbServiceImpl::factory_; @@ -102,7 +103,7 @@ RdbServiceImpl::RdbServiceImpl() { ZLOGI("construct"); DistributedDB::RelationalStoreManager::SetAutoLaunchRequestCallback( - [this](const std::string &identifier, DistributedDB::AutoLaunchParam ¶m) { + [this](const std::string& identifier, DistributedDB::AutoLaunchParam ¶m) { return ResolveAutoLaunch(identifier, param); }); RegisterEvent(); @@ -141,7 +142,6 @@ int32_t RdbServiceImpl::ResolveAutoLaunch(const std::string &identifier, Distrib if (entry.isEncrypt) { param.option.iterateTimes = ITERATE_TIMES; param.option.cipher = DistributedDB::CipherType::AES_256_GCM; - GetDBPassword(entry, param.option.passwd); } AutoCache::GetInstance().GetStore(entry, GetWatchers(entry.tokenId, entry.storeId)); return true; @@ -179,22 +179,63 @@ int32_t RdbServiceImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const return E_OK; } -bool RdbServiceImpl::CheckAccess(const std::string& bundleName, const std::string& storeName) +int32_t RdbServiceImpl::OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) +{ + ZLOGI("rdb exit, tokenId:%{public}d, pid:%{public}d, bundleName:%{public}s.", tokenId, pid, bundleName.c_str()); + bool destroyed = false; + syncAgents_.ComputeIfPresent(tokenId, [pid, &destroyed](auto &key, SyncAgents &agents) { + auto it = agents.find(pid); + if (it != agents.end()) { + it->second.SetNotifier(nullptr); + agents.erase(it); + } + if (!agents.empty()) { + return true; + } + destroyed = true; + return false; + }); + if (destroyed) { + auto stores = AutoCache::GetInstance().GetStoresIfPresent(tokenId); + for (auto store : stores) { + if (store != nullptr) { + store->UnregisterDetailProgressObserver(); + } + } + AutoCache::GetInstance().Enable(tokenId); + } + heartbeatTaskIds_.Erase(pid); + return E_OK; +} + +bool RdbServiceImpl::IsValidAccess(const std::string& bundleName, const std::string& storeName) { CheckerManager::StoreInfo storeInfo; storeInfo.uid = IPCSkeleton::GetCallingUid(); storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); storeInfo.bundleName = bundleName; storeInfo.storeId = RemoveSuffix(storeName); - return !CheckerManager::GetInstance().GetAppId(storeInfo).empty(); + + return CheckerManager::GetInstance().IsValid(storeInfo); } -std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device, const std::string &table) +std::string RdbServiceImpl::ObtainDistributedTableName(const RdbSyncerParam ¶m, const std::string &device, + const std::string &table) { - ZLOGI("device=%{public}s table=%{public}s", Anonymous::Change(device).c_str(), table.c_str()); - auto uuid = DmAdapter::GetInstance().GetUuidByNetworkId(device); + if (!IsValidAccess(param.bundleName_, "")) { + ZLOGE("bundleName:%{public}s. Permission error", param.bundleName_.c_str()); + return ""; + } + auto tokenId = IPCSkeleton::GetCallingTokenID(); + std::string appId = " "; + if (AccessTokenKit::GetTokenTypeFlag(tokenId) == Security::AccessToken::TOKEN_HAP) { + auto uid = IPCSkeleton::GetCallingUid(); + appId = CheckerManager::GetInstance().GetAppId({ uid, tokenId, param.bundleName_ }); + } + auto uuid = DmAdapter::GetInstance().CalcClientUuid(appId, DmAdapter::GetInstance().ToUUID(device)); if (uuid.empty()) { - ZLOGE("get uuid failed"); + ZLOGE("get uuid failed, bundle:%{public}s, deviceId:%{public}s, table:%{public}s", param.bundleName_.c_str(), + Anonymous::Change(device).c_str(), Anonymous::Change(table).c_str()); return ""; } return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table); @@ -203,7 +244,7 @@ std::string RdbServiceImpl::ObtainDistributedTableName(const std::string &device int32_t RdbServiceImpl::InitNotifier(const RdbSyncerParam ¶m, const sptr notifier) { XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY); - if (!CheckAccess(param.bundleName_, "")) { + if (!IsValidAccess(param.bundleName_, "")) { ZLOGE("bundleName:%{public}s. Permission error", param.bundleName_.c_str()); return RDB_ERROR; } @@ -242,13 +283,13 @@ std::shared_ptr RdbServiceImpl::GetStore(const Rd void RdbServiceImpl::UpdateMeta(const StoreMetaData &meta, const StoreMetaData &localMeta, AutoCache::Store store) { StoreMetaData syncMeta; - bool isCreatedSync = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), syncMeta); + bool isCreatedSync = MetaDataManager::GetInstance().LoadMeta(meta.GetKeyWithoutPath(), syncMeta); if (!isCreatedSync || localMeta != syncMeta) { ZLOGI("save sync meta. bundle:%{public}s store:%{public}s type:%{public}d->%{public}d " "encrypt:%{public}d->%{public}d , area:%{public}d->%{public}d", meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), syncMeta.storeType, meta.storeType, syncMeta.isEncrypt, meta.isEncrypt, syncMeta.area, meta.area); - MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), localMeta); + MetaDataManager::GetInstance().SaveMeta(meta.GetKeyWithoutPath(), localMeta); } Database dataBase; if (RdbSchemaConfig::GetDistributedSchema(localMeta, dataBase) && !dataBase.name.empty() && @@ -261,7 +302,7 @@ void RdbServiceImpl::UpdateMeta(const StoreMetaData &meta, const StoreMetaData & int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam ¶m, const std::vector &tables, const std::vector &references, bool isRebuild, int32_t type) { - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidParam(param) || !IsValidAccess(param.bundleName_, param.storeName_)) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; @@ -279,14 +320,16 @@ int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam ¶m, const Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; } - auto store = GetStore(param); + auto store = GetStore(meta); if (store == nullptr) { - ZLOGE("bundleName:%{public}s, storeName:%{public}s. GetStore failed", param.bundleName_.c_str(), - Anonymous::Change(param.storeName_).c_str()); + ZLOGE("bundle:%{public}s, %{public}s.", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; } + StoreMetaMapping metaMapping(localMeta); + MetaDataManager::GetInstance().LoadMeta(metaMapping.GetKey(), metaMapping, true); if (type == DistributedTableType::DISTRIBUTED_DEVICE) { UpdateMeta(meta, localMeta, store); + metaMapping.devicePath = meta.dataDir; } else if (type == DistributedTableType::DISTRIBUTED_CLOUD) { if (localMeta.asyncDownloadAsset != param.asyncDownloadAsset_ || localMeta.enableCloud != param.enableCloud_) { ZLOGI("update meta, bundleName:%{public}s, storeName:%{public}s, asyncDownloadAsset? [%{public}d -> " @@ -297,7 +340,10 @@ int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam ¶m, const localMeta.enableCloud = param.enableCloud_; MetaDataManager::GetInstance().SaveMeta(localMeta.GetKey(), localMeta, true); } + metaMapping.cloudPath = meta.dataDir; } + metaMapping = localMeta; + MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true); std::vector relationships; for (const auto &reference : references) { DistributedData::Reference relationship = { reference.sourceTable, reference.targetTable, reference.refFields }; @@ -377,20 +423,21 @@ RdbServiceImpl::DetailAsync RdbServiceImpl::GetCallbacks(uint32_t tokenId, const std::pair> RdbServiceImpl::RemoteQuery(const RdbSyncerParam& param, const std::string& device, const std::string& sql, const std::vector& selectionArgs) { - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidParam(param) || !IsValidAccess(param.bundleName_, param.storeName_)) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return { RDB_ERROR, nullptr }; } - auto store = GetStore(param); + StoreMetaData meta = GetStoreMetaData(param); + auto store = GetStore(meta); if (store == nullptr) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. GetStore failed", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return { RDB_ERROR, nullptr }; } - StoreMetaData meta = GetStoreMetaData(param); - std::vector devices = {DmAdapter::GetInstance().ToUUID(device)}; - if (IsNeedMetaSync(meta, devices) && !MetaDataManager::GetInstance().Sync(devices, [](auto &results) {}, true)) { + std::vector devices = { DmAdapter::GetInstance().ToUUID(device) }; + if (IsNeedMetaSync(meta, devices) && !MetaDataManager::GetInstance().Sync( + devices, [](auto &results) {}, true)) { ZLOGW("bundleName:%{public}s, storeName:%{public}s. meta sync failed", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); } @@ -406,7 +453,7 @@ std::pair> RdbServiceImpl::R int32_t RdbServiceImpl::Sync(const RdbSyncerParam ¶m, const Option &option, const PredicatesMemo &predicates, const AsyncDetail &async) { - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidParam(param) || !IsValidAccess(param.bundleName_, param.storeName_)) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; @@ -422,7 +469,8 @@ int32_t RdbServiceImpl::Sync(const RdbSyncerParam ¶m, const Option &option, int RdbServiceImpl::DoSync(const RdbSyncerParam ¶m, const RdbService::Option &option, const PredicatesMemo &predicates, const AsyncDetail &async) { - auto store = GetStore(param); + StoreMetaData meta = GetStoreMetaData(param); + auto store = GetStore(meta); if (store == nullptr) { return RDB_ERROR; } @@ -432,10 +480,9 @@ int RdbServiceImpl::DoSync(const RdbSyncerParam ¶m, const RdbService::Option : DmAdapter::ToUUID(rdbQuery.GetDevices()); auto pid = IPCSkeleton::GetCallingPid(); SyncParam syncParam = { option.mode, 0, option.isCompensation }; - StoreMetaData meta = GetStoreMetaData(param); auto tokenId = IPCSkeleton::GetCallingTokenID(); ZLOGD("seqNum=%{public}u", option.seqNum); - auto complete = [this, rdbQuery, store, pid, syncParam, tokenId, async, seq = option.seqNum]( + auto complete = [this, rdbQuery, store, pid, syncParam, tokenId, seq = option.seqNum]( const auto &results) mutable { auto ret = ProcessResult(results); store->Sync( @@ -466,7 +513,7 @@ bool RdbServiceImpl::IsNeedMetaSync(const StoreMetaData &meta, const std::vector CapMetaData capMeta; auto capKey = CapMetaRow::GetKeyFor(uuid); if (!MetaDataManager::GetInstance().LoadMeta(std::string(capKey.begin(), capKey.end()), capMeta) || - !MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData)) { + !MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)) { isAfterMeta = true; break; } @@ -551,7 +598,7 @@ void RdbServiceImpl::DoCloudSync(const RdbSyncerParam ¶m, const RdbService:: async(HandleGenDetails(details)); } }; - auto highMode = (!predicates.tables_.empty() && option.mode == DistributedData::GeneralStore::CLOUD_ClOUD_FIRST) + auto highMode = (!predicates.tables_.empty() && option.mode == DistributedData::GeneralStore::CLOUD_CLOUD_FIRST) ? GeneralStore::ASSETS_SYNC_MODE : (option.isAutoSync ? GeneralStore::AUTO_SYNC_MODE : GeneralStore::MANUAL_SYNC_MODE); auto mixMode = static_cast(GeneralStore::MixMode(option.mode, highMode)); @@ -566,7 +613,7 @@ void RdbServiceImpl::DoCloudSync(const RdbSyncerParam ¶m, const RdbService:: } int32_t RdbServiceImpl::Subscribe(const RdbSyncerParam ¶m, const SubscribeOption &option, - RdbStoreObserver *observer) + std::shared_ptr observer) { if (option.mode < 0 || option.mode >= SUBSCRIBE_MODE_MAX) { ZLOGE("mode:%{public}d error", option.mode); @@ -588,15 +635,14 @@ int32_t RdbServiceImpl::Subscribe(const RdbSyncerParam ¶m, const SubscribeOp return true; }); if (isCreate) { - auto subUser = GetSubUser(param.subUser_); - AutoCache::GetInstance().SetObserver(tokenId, RemoveSuffix(param.storeName_), - GetWatchers(tokenId, param.storeName_), subUser); + AutoCache::GetInstance().SetObserver(tokenId, GetWatchers(tokenId, param.storeName_), + GetPath(param), RemoveSuffix(param.storeName_)); } return RDB_OK; } int32_t RdbServiceImpl::UnSubscribe(const RdbSyncerParam ¶m, const SubscribeOption &option, - RdbStoreObserver *observer) + std::shared_ptr observer) { if (option.mode < 0 || option.mode >= SUBSCRIBE_MODE_MAX) { ZLOGE("mode:%{public}d error", option.mode); @@ -618,9 +664,8 @@ int32_t RdbServiceImpl::UnSubscribe(const RdbSyncerParam ¶m, const Subscribe return true; }); if (destroyed) { - auto subUser = GetSubUser(param.subUser_); - AutoCache::GetInstance().SetObserver(tokenId, RemoveSuffix(param.storeName_), - GetWatchers(tokenId, param.storeName_), subUser); + AutoCache::GetInstance().SetObserver(tokenId, GetWatchers(tokenId, param.storeName_), + GetPath(param), RemoveSuffix(param.storeName_)); } return RDB_OK; } @@ -672,15 +717,20 @@ int32_t RdbServiceImpl::UnregisterAutoSyncCallback(const RdbSyncerParam& param, int32_t RdbServiceImpl::Delete(const RdbSyncerParam ¶m) { XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY); + if (!IsValidAccess(param.bundleName_, param.storeName_)) { + ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), + Anonymous::Change(param.storeName_).c_str()); + return RDB_ERROR; + } auto tokenId = IPCSkeleton::GetCallingTokenID(); - auto subUser = GetSubUser(param.subUser_); - AutoCache::GetInstance().CloseStore(tokenId, RemoveSuffix(param.storeName_), subUser); - RdbSyncerParam tmpParam = param; - HapTokenInfo hapTokenInfo; - AccessTokenKit::GetHapTokenInfo(tokenId, hapTokenInfo); - tmpParam.bundleName_ = hapTokenInfo.bundleName; - auto storeMeta = GetStoreMetaData(tmpParam); - MetaDataManager::GetInstance().DelMeta(storeMeta.GetKey()); + auto storeMeta = GetStoreMetaData(param); + StoreMetaMapping storeMetaMapping(storeMeta); + MetaDataManager::GetInstance().LoadMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); + if (!MetaDataManager::GetInstance().LoadMeta(storeMeta.GetKey(), storeMeta, true)) { + storeMeta.dataDir = storeMetaMapping.dataDir; + } + AutoCache::GetInstance().CloseStore(tokenId, storeMeta.dataDir, RemoveSuffix(param.storeName_)); + MetaDataManager::GetInstance().DelMeta(storeMeta.GetKeyWithoutPath()); MetaDataManager::GetInstance().DelMeta(storeMeta.GetKey(), true); MetaDataManager::GetInstance().DelMeta(storeMeta.GetKeyLocal(), true); MetaDataManager::GetInstance().DelMeta(storeMeta.GetSecretKey(), true); @@ -690,13 +740,29 @@ int32_t RdbServiceImpl::Delete(const RdbSyncerParam ¶m) MetaDataManager::GetInstance().DelMeta(storeMeta.GetDebugInfoKey(), true); MetaDataManager::GetInstance().DelMeta(storeMeta.GetDfxInfoKey(), true); MetaDataManager::GetInstance().DelMeta(storeMeta.GetCloneSecretKey(), true); + std::vector metaList; + if (MetaDataManager::GetInstance().LoadMeta(storeMeta.GetKeyWithoutPath(), metaList, true) && !metaList.empty()) { + if (storeMetaMapping.cloudPath == storeMetaMapping.dataDir) { + storeMetaMapping.cloudPath = ""; + } + if (storeMetaMapping.searchPath == storeMetaMapping.dataDir) { + storeMetaMapping.searchPath = ""; + } + if (storeMetaMapping.devicePath == storeMetaMapping.dataDir) { + storeMetaMapping.devicePath = ""; + } + storeMetaMapping = metaList[0]; + MetaDataManager::GetInstance().SaveMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); + } else { + MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true); + } return RDB_OK; } std::pair> RdbServiceImpl::QuerySharingResource( const RdbSyncerParam& param, const PredicatesMemo& predicates, const std::vector& columns) { - if (!CheckAccess(param.bundleName_, param.storeName_) || + if (!IsValidAccess(param.bundleName_, param.storeName_) || !TokenIdKit::IsSystemAppByFullTokenID(IPCSkeleton::GetCallingFullTokenID())) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); @@ -737,17 +803,75 @@ std::pair> RdbServiceImpl::AllocResource(StoreI return result; } +bool RdbServiceImpl::IsValidPath(const std::string ¶m) +{ + if ((param.find("/") != std::string::npos) || (param.find("\\") != std::string::npos) || (param == "..")) { + return false; + } + return true; +} + +bool RdbServiceImpl::IsValidCustomDir(const std::string &customDir, int32_t upLimit) +{ + if (customDir.empty()) { + return true; + } + if (customDir[0] == '/') { + return false; + } + std::vector components = Constant::Split(customDir, "/"); + int32_t up = 0; + for (const auto &comp : components) { + if (comp.empty() || comp == ".") { + continue; + } + if (comp != "..") { + up--; + continue; + } + if (++up > upLimit) { + return false; + } + } + return true; +} + +bool RdbServiceImpl::IsValidParam(const RdbSyncerParam ¶m) +{ + if (param.storeName_.find("/") != std::string::npos) { + ZLOGE("storeName is Invalid, storeName is %{public}s.", Anonymous::Change(param.storeName_).c_str()); + return false; + } + if (!IsValidPath(param.bundleName_)) { + ZLOGE("bundleName is Invalid, bundleName is %{public}s.", param.bundleName_.c_str()); + return false; + } + if (!IsValidPath(param.user_)) { + ZLOGE("user is Invalid, user is %{public}s.", param.user_.c_str()); + return false; + } + if (!IsValidPath(param.hapName_)) { + ZLOGE("hapName is Invalid, hapName is %{public}s.", param.hapName_.c_str()); + return false; + } + int32_t upLimit = param.hapName_.empty() ? 1 : VALID_PARAM_LENGTH; + if (!IsValidCustomDir(param.customDir_, upLimit)) { + ZLOGE("customDir is Invalid, customDir is %{public}s.", Anonymous::Change(param.customDir_).c_str()); + return false; + } + return true; +} + int32_t RdbServiceImpl::BeforeOpen(RdbSyncerParam ¶m) { XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY); - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidParam(param) || !IsValidAccess(param.bundleName_, param.storeName_)) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; } - auto meta = GetStoreMetaData(param); - auto isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true); - if (!isCreated) { + auto [exist, meta] = LoadStoreMetaData(param); + if (!exist) { ZLOGW("bundleName:%{public}s, storeName:%{public}s. no meta", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return RDB_NO_META; @@ -756,7 +880,7 @@ int32_t RdbServiceImpl::BeforeOpen(RdbSyncerParam ¶m) return RDB_OK; } -void RdbServiceImpl::SetReturnParam(StoreMetaData &metadata, RdbSyncerParam ¶m) +void RdbServiceImpl::SetReturnParam(const StoreMetaData &metadata, RdbSyncerParam ¶m) { param.bundleName_ = metadata.bundleName; param.type_ = metadata.storeType; @@ -770,10 +894,53 @@ void RdbServiceImpl::SetReturnParam(StoreMetaData &metadata, RdbSyncerParam &par param.haMode_ = metadata.haMode; } +void RdbServiceImpl::SaveLaunchInfo(StoreMetaData &meta) +{ + RemoteChangeEvent::DataInfo info; + info.bundleName = meta.bundleName; + info.deviceId = meta.deviceId; + info.userId = meta.user; + if (executors_ != nullptr) { + executors_->Schedule(ExecutorPool::INVALID_DELAY, [dataInfo = std::move(info)]() mutable { + auto evt = std::make_unique(RemoteChangeEvent::RDB_META_SAVE, std::move(dataInfo)); + EventCenter::GetInstance().PostEvent(std::move(evt)); + }); + } +} + +void RdbServiceImpl::SaveSecretKeyMeta(const StoreMetaData &metaData, const std::vector &password) +{ + CryptoManager::CryptoParams encryptParams = { .area = metaData.area, .userId = metaData.user }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(password, encryptParams); + if (!encryptKey.empty() && !encryptParams.nonce.empty()) { + SecretKeyMetaData secretKey; + secretKey.storeType = metaData.storeType; + secretKey.area = metaData.area; + secretKey.sKey = encryptKey; + secretKey.nonce = encryptParams.nonce; + auto time = system_clock::to_time_t(system_clock::now()); + secretKey.time = { reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time) }; + MetaDataManager::GetInstance().SaveMeta(metaData.GetSecretKey(), secretKey, true); + } + SecretKeyMetaData cloneKey; + auto metaKey = metaData.GetCloneSecretKey(); + // update clone secret key with area + if (MetaDataManager::GetInstance().LoadMeta(metaKey, cloneKey, true) && !cloneKey.sKey.empty() && + (cloneKey.nonce.empty() || cloneKey.area < 0)) { + CryptoManager::CryptoParams decryptParams = { .area = cloneKey.area, .userId = metaData.user, + .nonce = cloneKey.nonce }; + auto clonePassword = CryptoManager::GetInstance().Decrypt(cloneKey.sKey, decryptParams); + if (!clonePassword.empty()) { + CryptoManager::GetInstance().UpdateSecretMeta(clonePassword, metaData, metaKey, cloneKey); + } + clonePassword.assign(clonePassword.size(), 0); + } +} + int32_t RdbServiceImpl::AfterOpen(const RdbSyncerParam ¶m) { XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY); - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidParam(param) || !IsValidAccess(param.bundleName_, param.storeName_)) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; @@ -781,6 +948,7 @@ int32_t RdbServiceImpl::AfterOpen(const RdbSyncerParam ¶m) auto meta = GetStoreMetaData(param); StoreMetaData old; auto isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), old, true); + meta.enableCloud = isCreated ? old.enableCloud : meta.enableCloud; if (!isCreated || meta != old) { Upgrade(param, old); ZLOGI("meta bundle:%{public}s store:%{public}s type:%{public}d->%{public}d encrypt:%{public}d->%{public}d " @@ -790,19 +958,35 @@ int32_t RdbServiceImpl::AfterOpen(const RdbSyncerParam ¶m) MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true); AutoLaunchMetaData launchData; if (!MetaDataManager::GetInstance().LoadMeta(meta.GetAutoLaunchKey(), launchData, true)) { - RemoteChangeEvent::DataInfo info; - info.bundleName = meta.bundleName; - info.deviceId = meta.deviceId; - info.userId = meta.user; - auto evt = std::make_unique(RemoteChangeEvent::RDB_META_SAVE, std::move(info)); - EventCenter::GetInstance().PostEvent(std::move(evt)); + SaveLaunchInfo(meta); } } + StoreMetaMapping metaMapping(meta); + MetaDataManager::GetInstance().LoadMeta(metaMapping.GetKey(), metaMapping, true); + if (meta.isSearchable) { + metaMapping.searchPath = meta.dataDir; + } + metaMapping = meta; + MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true); + SaveDebugInfo(meta, param); SavePromiseInfo(meta, param); SaveDfxInfo(meta, param); + if (!SaveAppIDMeta(meta, old)) { + return RDB_ERROR; + } + + if (param.isEncrypt_ && !param.password_.empty()) { + SaveSecretKeyMeta(meta, param.password_); + } + GetSchema(param); + return RDB_OK; +} + +bool RdbServiceImpl::SaveAppIDMeta(const StoreMetaData &meta, const StoreMetaData &old) +{ AppIDMetaData appIdMeta; appIdMeta.bundleName = meta.bundleName; appIdMeta.appId = meta.appId; @@ -810,23 +994,14 @@ int32_t RdbServiceImpl::AfterOpen(const RdbSyncerParam ¶m) ZLOGE("meta bundle:%{public}s store:%{public}s type:%{public}d->%{public}d encrypt:%{public}d->%{public}d " "area:%{public}d->%{public}d", meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), old.storeType, meta.storeType, old.isEncrypt, meta.isEncrypt, old.area, meta.area); - return RDB_ERROR; - } - if (param.isEncrypt_ && !param.password_.empty()) { - if (SetSecretKey(param, meta) != RDB_OK) { - ZLOGE("Set secret key failed, bundle:%{public}s store:%{public}s", - meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); - return RDB_ERROR; - } - UpgradeCloneSecretKey(meta); + return false; } - GetSchema(param); - return RDB_OK; + return true; } int32_t RdbServiceImpl::ReportStatistic(const RdbSyncerParam& param, const RdbStatEvent &statEvent) { - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidAccess(param.bundleName_, param.storeName_)) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; @@ -846,6 +1021,8 @@ void RdbServiceImpl::GetSchema(const RdbSyncerParam ¶m) storeInfo.instanceId = instanceId; storeInfo.user = user; storeInfo.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + auto meta = GetStoreMetaData(param); + storeInfo.path = meta.dataDir; executors_->Execute([storeInfo]() { auto event = std::make_unique(CloudEvent::GET_SCHEMA, std::move(storeInfo)); EventCenter::GetInstance().PostEvent(move(event)); @@ -854,6 +1031,33 @@ void RdbServiceImpl::GetSchema(const RdbSyncerParam ¶m) } } +std::pair RdbServiceImpl::LoadStoreMetaData(const RdbSyncerParam ¶m) +{ + StoreMetaData metaData; + metaData.uid = IPCSkeleton::GetCallingUid(); + metaData.tokenId = IPCSkeleton::GetCallingTokenID(); + auto [instanceId, user] = GetInstIndexAndUser(metaData.tokenId, param.bundleName_); + metaData.instanceId = instanceId; + metaData.bundleName = param.bundleName_; + metaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData.storeId = RemoveSuffix(param.storeName_); + if (AccessTokenKit::GetTokenTypeFlag(metaData.tokenId) != TOKEN_HAP && param.subUser_ != 0) { + metaData.user = std::to_string(param.subUser_); + } else { + metaData.user = std::to_string(user); + } + metaData.storeType = param.type_; + metaData.securityLevel = param.level_; + metaData.area = param.area_; + metaData.appId = CheckerManager::GetInstance().GetAppId(Converter::ConvertToStoreInfo(metaData)); + metaData.appType = "harmony"; + metaData.hapName = param.hapName_; + metaData.customDir = param.customDir_; + metaData.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData) + "/" + param.storeName_; + auto exist = MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true); + return {exist, metaData}; +} + StoreMetaData RdbServiceImpl::GetStoreMetaData(const RdbSyncerParam ¶m) { StoreMetaData metaData; @@ -886,33 +1090,6 @@ StoreMetaData RdbServiceImpl::GetStoreMetaData(const RdbSyncerParam ¶m) return metaData; } -int32_t RdbServiceImpl::SetSecretKey(const RdbSyncerParam ¶m, const StoreMetaData &meta) -{ - SecretKeyMetaData newSecretKey; - newSecretKey.storeType = meta.storeType; - newSecretKey.area = meta.area; - newSecretKey.sKey = CryptoManager::GetInstance().Encrypt(param.password_, meta.area, meta.user); - if (newSecretKey.sKey.empty()) { - ZLOGE("encrypt work key error."); - return RDB_ERROR; - } - auto time = system_clock::to_time_t(system_clock::now()); - newSecretKey.time = { reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time) }; - return MetaDataManager::GetInstance().SaveMeta(meta.GetSecretKey(), newSecretKey, true) ? RDB_OK : RDB_ERROR; -} - -bool RdbServiceImpl::UpgradeCloneSecretKey(const StoreMetaData &meta) -{ - SecretKeyMetaData secretKey; - if (MetaDataManager::GetInstance().LoadMeta(meta.GetCloneSecretKey(), secretKey, true) && secretKey.area < 0) { - std::vector clonePwd; - // Update the encryption method for the key - CryptoManager::GetInstance().Decrypt(meta, secretKey, clonePwd, CryptoManager::CLONE_SECRET_KEY); - clonePwd.assign(clonePwd.size(), 0); - } - return true; -} - int32_t RdbServiceImpl::Upgrade(const RdbSyncerParam ¶m, const StoreMetaData &old) { if (old.storeType == RDB_DEVICE_COLLABORATION && old.version < StoreMetaData::UUID_CHANGED_TAG) { @@ -942,26 +1119,6 @@ Details RdbServiceImpl::HandleGenDetails(const GenDetails &details) return dbDetails; } -bool RdbServiceImpl::GetDBPassword(const StoreMetaData &metaData, DistributedDB::CipherPassword &password) -{ - if (!metaData.isEncrypt) { - return true; - } - - std::string key = metaData.GetSecretKey(); - DistributedData::SecretKeyMetaData secretKeyMeta; - MetaDataManager::GetInstance().LoadMeta(key, secretKeyMeta, true); - std::vector decryptKey; - CryptoManager::GetInstance().Decrypt(metaData, secretKeyMeta, decryptKey); - if (password.SetValue(decryptKey.data(), decryptKey.size()) != DistributedDB::CipherPassword::OK) { - std::fill(decryptKey.begin(), decryptKey.end(), 0); - ZLOGE("Set secret key value failed. len is (%{public}d)", int32_t(decryptKey.size())); - return false; - } - std::fill(decryptKey.begin(), decryptKey.end(), 0); - return true; -} - std::string RdbServiceImpl::RemoveSuffix(const std::string& name) { std::string suffix(".db"); @@ -998,20 +1155,23 @@ int32_t RdbServiceImpl::OnBind(const BindInfo &bindInfo) StoreMetaData RdbServiceImpl::GetStoreMetaData(const Database &dataBase) { - StoreMetaData storeMetaData; - storeMetaData.storeId = dataBase.name; - storeMetaData.bundleName = dataBase.bundleName; - storeMetaData.user = dataBase.user; - storeMetaData.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + StoreMetaMapping storeMetaMapping; + storeMetaMapping.storeId = dataBase.name; + storeMetaMapping.bundleName = dataBase.bundleName; + storeMetaMapping.user = dataBase.user; + storeMetaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; auto tokenId = IPCSkeleton::GetCallingTokenID(); - storeMetaData.tokenId = tokenId; - auto [instanceId, user] = GetInstIndexAndUser(storeMetaData.tokenId, storeMetaData.bundleName); - storeMetaData.instanceId = instanceId; - MetaDataManager::GetInstance().LoadMeta(storeMetaData.GetKey(), storeMetaData, true); + storeMetaMapping.tokenId = tokenId; + auto [instanceId, user] = GetInstIndexAndUser(storeMetaMapping.tokenId, storeMetaMapping.bundleName); + storeMetaMapping.instanceId = instanceId; + MetaDataManager::GetInstance().LoadMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); + StoreMetaData storeMetaData = storeMetaMapping; + if (storeMetaMapping.dataDir != storeMetaMapping.devicePath) { + MetaDataManager::GetInstance().LoadMeta(storeMetaMapping.GetDeviceStoreMetaKey(), storeMetaData, true); + } return storeMetaData; } - std::shared_ptr RdbServiceImpl::GetStore(const StoreMetaData &storeMetaData) { auto watchers = GetWatchers(storeMetaData.tokenId, storeMetaData.storeId); @@ -1019,12 +1179,16 @@ std::shared_ptr RdbServiceImpl::GetStore(const St return store; } -std::vector RdbServiceImpl::GetReuseDevice(const std::vector &devices) +std::vector RdbServiceImpl::GetReuseDevice(const std::vector &devices, + const StoreMetaData &metaData) { std::vector onDevices; auto instance = AppDistributedKv::ProcessCommunicatorImpl::GetInstance(); + AppDistributedKv::ExtraDataInfo extraInfo = { .userId = metaData.user, .bundleName = metaData.bundleName, + .storeId = metaData.storeId, .tokenId = metaData.tokenId }; for (auto &device : devices) { - if (instance->ReuseConnect({device}) == Status::SUCCESS) { + AppDistributedKv::DeviceId deviceId = { .deviceId = device }; + if (instance->ReuseConnect(deviceId, extraInfo) == Status::SUCCESS) { onDevices.push_back(device); } } @@ -1035,30 +1199,27 @@ int RdbServiceImpl::DoAutoSync( const std::vector &devices, const Database &dataBase, std::vector tables) { StoreMetaData storeMetaData = GetStoreMetaData(dataBase); - auto tokenId = storeMetaData.tokenId; auto store = GetStore(storeMetaData); if (store == nullptr) { ZLOGE("autosync store null, storeId:%{public}s", storeMetaData.GetStoreAlias().c_str()); return RDB_ERROR; } - SyncParam syncParam = {0, 0}; - auto pid = IPCSkeleton::GetCallingPid(); - DetailAsync async; if (executors_ == nullptr) { ZLOGE("autosync executors_ null, storeId:%{public}s", storeMetaData.GetStoreAlias().c_str()); return RDB_ERROR; } + SyncParam syncParam = { 0, 0 }; + DetailAsync async; for (auto &table : tables) { - executors_->Execute([this, table, store, pid, syncParam, tokenId, async, - devices, storeMetaData]() { + executors_->Execute([this, table, store, syncParam, async, devices, storeMetaData]() { RdbQuery rdbQuery; rdbQuery.MakeQuery(table); - std::vector onDevices = GetReuseDevice(devices); + std::vector onDevices = GetReuseDevice(devices, storeMetaData); if (onDevices.empty()) { ZLOGE("autosync ondevices null, storeId:%{public}s", storeMetaData.GetStoreAlias().c_str()); return; } - auto complete = [this, rdbQuery, store, pid, syncParam, tokenId, async, seq = 0]( + auto complete = [this, rdbQuery, store, syncParam, async]( const auto &results) mutable { auto ret = ProcessResult(results); store->Sync(ret.first, rdbQuery, async, syncParam); @@ -1099,8 +1260,8 @@ int32_t RdbServiceImpl::OnReady(const std::string &device) dataBase.autoSyncType == AutoSyncType::SYNC_ON_CHANGE_READY) && index > 0) { std::vector devices = {device}; - if (!DoOnlineSync(devices, dataBase)) { - ZLOGE("store online sync fail, storeId:%{public}s", dataBase.name.c_str()); + if (DoOnlineSync(devices, dataBase) != RDB_OK) { + ZLOGE("store online sync fail, storeId:%{public}s", Anonymous::Change(dataBase.name).c_str()); } index--; } @@ -1179,8 +1340,21 @@ int32_t RdbServiceImpl::RdbStatic::OnAppUpdate(const std::string &bundleName, in std::string prefix = Database::GetPrefix({std::to_string(user), "default", bundleName}); std::vector dataBase; if (MetaDataManager::GetInstance().LoadMeta(prefix, dataBase, true)) { - for (const auto &dataBase : dataBase) { - MetaDataManager::GetInstance().DelMeta(dataBase.GetKey(), true); + for (const auto &database : dataBase) { + MetaDataManager::GetInstance().DelMeta(database.GetKey(), true); + ZLOGD("del metadata store is: %{public}s; user is: %{public}s; bundleName is: %{public}s", + Anonymous::Change(database.name).c_str(), database.user.c_str(), database.bundleName.c_str()); + StoreMetaData meta; + meta.user = database.user; + meta.deviceId = database.deviceId; + meta.storeId = database.name; + meta.bundleName = bundleName; + Database base; + if (RdbSchemaConfig::GetDistributedSchema(meta, base) && !base.name.empty() && !base.bundleName.empty()) { + MetaDataManager::GetInstance().SaveMeta(base.GetKey(), base, true); + ZLOGD("save metadata store is: %{public}s; user is: %{public}s; bundleName is: %{public}s", + Anonymous::Change(base.name).c_str(), base.user.c_str(), base.bundleName.c_str()); + } } } return CloseStore(bundleName, user, index); @@ -1255,7 +1429,7 @@ int32_t RdbServiceImpl::NotifyDataChange( const RdbSyncerParam ¶m, const RdbChangedData &rdbChangedData, const RdbNotifyConfig &rdbNotifyConfig) { XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY); - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidParam(param) || !IsValidAccess(param.bundleName_, param.storeName_)) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; @@ -1264,14 +1438,15 @@ int32_t RdbServiceImpl::NotifyDataChange( storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); storeInfo.bundleName = param.bundleName_; storeInfo.storeName = RemoveSuffix(param.storeName_); + storeInfo.path = GetPath(param); auto [instanceId, user] = GetInstIndexAndUser(storeInfo.tokenId, param.bundleName_); storeInfo.instanceId = instanceId; storeInfo.user = user; storeInfo.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; DataChangeEvent::EventInfo eventInfo; eventInfo.isFull = rdbNotifyConfig.isFull_; - if (!DoDataChangeSync(storeInfo, rdbChangedData)) { - ZLOGE("store datachange sync fail, storeId:%{public}s", storeInfo.storeName.c_str()); + if (DoDataChangeSync(storeInfo, rdbChangedData) != RDB_OK) { + ZLOGE("store datachange sync fail, storeId:%{public}s", Anonymous::Change(storeInfo.storeName).c_str()); } for (const auto &[key, value] : rdbChangedData.tableData) { if (value.isTrackedDataChange) { @@ -1279,7 +1454,7 @@ int32_t RdbServiceImpl::NotifyDataChange( eventInfo.tableProperties.insert_or_assign(key, std::move(tableChangeProperties)); } } - if (IsPostImmediately(IPCSkeleton::GetCallingPid(), rdbNotifyConfig, storeInfo, eventInfo, param.storeName_)) { + if (IsPostImmediately(IPCSkeleton::GetCallingPid(), rdbNotifyConfig, storeInfo, eventInfo, storeInfo.path)) { auto evt = std::make_unique(std::move(storeInfo), std::move(eventInfo)); EventCenter::GetInstance().PostEvent(std::move(evt)); } @@ -1287,12 +1462,12 @@ int32_t RdbServiceImpl::NotifyDataChange( } bool RdbServiceImpl::IsPostImmediately(const int32_t callingPid, const RdbNotifyConfig &rdbNotifyConfig, - StoreInfo &storeInfo, DataChangeEvent::EventInfo &eventInfo, const std::string &storeName) + StoreInfo &storeInfo, DataChangeEvent::EventInfo &eventInfo, const std::string &path) { bool postImmediately = false; heartbeatTaskIds_.Compute(callingPid, [this, &postImmediately, &rdbNotifyConfig, &storeInfo, &eventInfo, - &storeName](const int32_t &key, std::map &tasks) { - auto iter = tasks.find(storeName); + &path](const int32_t &key, std::map &tasks) { + auto iter = tasks.find(path); ExecutorPool::TaskId taskId = ExecutorPool::INVALID_TASK_ID; if (iter != tasks.end()) { taskId = iter->second; @@ -1302,7 +1477,7 @@ bool RdbServiceImpl::IsPostImmediately(const int32_t callingPid, const RdbNotify executors_->Remove(taskId); } postImmediately = true; - tasks.erase(storeName); + tasks.erase(path); return !tasks.empty(); } @@ -1317,7 +1492,7 @@ bool RdbServiceImpl::IsPostImmediately(const int32_t callingPid, const RdbNotify taskId = executors_->Reset(taskId, std::chrono::milliseconds(rdbNotifyConfig.delay_)); } } - tasks.insert_or_assign(storeName, taskId); + tasks.insert_or_assign(path, taskId); return true; }); return postImmediately; @@ -1326,7 +1501,7 @@ bool RdbServiceImpl::IsPostImmediately(const int32_t callingPid, const RdbNotify int32_t RdbServiceImpl::SetSearchable(const RdbSyncerParam& param, bool isSearchable) { XCollie xcollie(__FUNCTION__, XCollie::XCOLLIE_LOG | XCollie::XCOLLIE_RECOVERY); - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidAccess(param.bundleName_, param.storeName_)) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; @@ -1347,6 +1522,7 @@ int32_t RdbServiceImpl::PostSearchEvent(int32_t evtId, const RdbSyncerParam& par storeInfo.instanceId = instanceId; storeInfo.user = user; storeInfo.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + storeInfo.path = GetPath(param); auto evt = std::make_unique(std::move(storeInfo), std::move(eventInfo), evtId); EventCenter::GetInstance().PostEvent(std::move(evt)); @@ -1357,8 +1533,7 @@ int32_t RdbServiceImpl::Disable(const RdbSyncerParam ¶m) { auto tokenId = IPCSkeleton::GetCallingTokenID(); auto storeId = RemoveSuffix(param.storeName_); - auto userId = GetSubUser(param.subUser_); - AutoCache::GetInstance().Disable(tokenId, storeId, userId); + AutoCache::GetInstance().Disable(tokenId, GetPath(param), storeId); return RDB_OK; } @@ -1366,41 +1541,52 @@ int32_t RdbServiceImpl::Enable(const RdbSyncerParam ¶m) { auto tokenId = IPCSkeleton::GetCallingTokenID(); auto storeId = RemoveSuffix(param.storeName_); - auto userId = GetSubUser(param.subUser_); - AutoCache::GetInstance().Enable(tokenId, storeId, userId); + AutoCache::GetInstance().Enable(tokenId, GetPath(param), storeId); return RDB_OK; } +std::vector RdbServiceImpl::LoadSecretKey(const StoreMetaData &metaData, + CryptoManager::SecretKeyType secretKeyType) +{ + SecretKeyMetaData secretKey; + std::string metaKey; + if (secretKeyType == CryptoManager::SecretKeyType::LOCAL_SECRET_KEY) { + metaKey = metaData.GetSecretKey(); + } else if (secretKeyType == CryptoManager::SecretKeyType::CLONE_SECRET_KEY) { + metaKey = metaData.GetCloneSecretKey(); + } + if (!MetaDataManager::GetInstance().LoadMeta(metaKey, secretKey, true) || secretKey.sKey.empty()) { + return {}; + } + CryptoManager::CryptoParams decryptParams = { .area = secretKey.area, .userId = metaData.user, + .nonce = secretKey.nonce }; + auto password = CryptoManager::GetInstance().Decrypt(secretKey.sKey, decryptParams); + if (password.empty()) { + return {}; + } + // update secret key of area or nonce + CryptoManager::GetInstance().UpdateSecretMeta(password, metaData, metaKey, secretKey); + return password; +} + int32_t RdbServiceImpl::GetPassword(const RdbSyncerParam ¶m, std::vector> &password) { - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidAccess(param.bundleName_, param.storeName_)) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; } + password.reserve(KEY_COUNT); auto meta = GetStoreMetaData(param); - password.resize(KEY_COUNT); - SecretKeyMetaData secretKey; - SecretKeyMetaData cloneSecretKey; - bool keyMeta = MetaDataManager::GetInstance().LoadMeta(meta.GetSecretKey(), secretKey, true); - bool cloneKeyMeta = MetaDataManager::GetInstance().LoadMeta(meta.GetCloneSecretKey(), cloneSecretKey, true); - if (!keyMeta && !cloneKeyMeta) { - ZLOGE("bundleName:%{public}s, storeName:%{public}s. no meta", param.bundleName_.c_str(), - Anonymous::Change(param.storeName_).c_str()); - return RDB_NO_META; + auto key = LoadSecretKey(meta, CryptoManager::SecretKeyType::LOCAL_SECRET_KEY); + if (!key.empty()) { + password.emplace_back(key); } - bool key = CryptoManager::GetInstance().Decrypt(meta, secretKey, password.at(0)); - bool cloneKey = CryptoManager::GetInstance().Decrypt( - meta, cloneSecretKey, password.at(1), CryptoManager::CLONE_SECRET_KEY); - if (!key && !cloneKey) { - ZLOGE("bundleName:%{public}s, storeName:%{public}s. decrypt err", param.bundleName_.c_str(), - Anonymous::Change(param.storeName_).c_str()); - for (auto &item : password) { - item.assign(item.size(), 0); - } - return RDB_ERROR; + auto cloneKey = LoadSecretKey(meta, CryptoManager::SecretKeyType::CLONE_SECRET_KEY); + if (!cloneKey.empty()) { + password.emplace_back(cloneKey); } - return RDB_OK; + return password.size() > 0 ? RDB_OK : RDB_ERROR; } StoreInfo RdbServiceImpl::GetStoreInfo(const RdbSyncerParam ¶m) @@ -1410,13 +1596,15 @@ StoreInfo RdbServiceImpl::GetStoreInfo(const RdbSyncerParam ¶m) storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); storeInfo.user = AccountDelegate::GetInstance()->GetUserByToken(storeInfo.tokenId); storeInfo.storeName = RemoveSuffix(param.storeName_); + auto meta = GetStoreMetaData(param); + storeInfo.path = meta.dataDir; return storeInfo; } std::pair RdbServiceImpl::LockCloudContainer(const RdbSyncerParam ¶m) { std::pair result { RDB_ERROR, 0 }; - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidAccess(param.bundleName_, param.storeName_)) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return result; @@ -1438,7 +1626,7 @@ std::pair RdbServiceImpl::LockCloudContainer(const RdbSyncerP int32_t RdbServiceImpl::UnlockCloudContainer(const RdbSyncerParam ¶m) { int32_t result = RDB_ERROR; - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidAccess(param.bundleName_, param.storeName_)) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return result; @@ -1459,7 +1647,7 @@ int32_t RdbServiceImpl::UnlockCloudContainer(const RdbSyncerParam ¶m) int32_t RdbServiceImpl::GetDebugInfo(const RdbSyncerParam ¶m, std::map &debugInfo) { - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidAccess(param.bundleName_, param.storeName_)) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; @@ -1512,7 +1700,7 @@ int32_t RdbServiceImpl::SaveDebugInfo(const StoreMetaData &metaData, const RdbSy int32_t RdbServiceImpl::GetDfxInfo(const RdbSyncerParam ¶m, DistributedRdb::RdbDfxInfo &dfxInfo) { - if (!CheckAccess(param.bundleName_, param.storeName_)) { + if (!IsValidAccess(param.bundleName_, param.storeName_)) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; @@ -1568,14 +1756,18 @@ int32_t RdbServiceImpl::VerifyPromiseInfo(const RdbSyncerParam ¶m) auto uid = IPCSkeleton::GetCallingUid(); meta.user = param.user_; StoreMetaDataLocal localMeta; - auto isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMeta, true); - if (!isCreated) { - ZLOGE("Store not exist. bundleName:%{public}s, storeName:%{public}s", meta.bundleName.c_str(), - meta.storeId.c_str()); - return RDB_ERROR; + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMeta, true)) { + StoreMetaMapping metaMapping(meta); + MetaDataManager::GetInstance().LoadMeta(metaMapping.GetKey(), metaMapping, true); + meta.dataDir = metaMapping.dataDir; + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMeta, true)) { + ZLOGE("Store not exist. bundleName:%{public}s, storeName:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return RDB_ERROR; + } } ATokenTypeEnum type = AccessTokenKit::GetTokenType(tokenId); - if (type == ATokenTypeEnum::TOKEN_NATIVE) { + if (type == ATokenTypeEnum::TOKEN_NATIVE || type == ATokenTypeEnum::TOKEN_SHELL) { auto tokenIdRet = std::find(localMeta.promiseInfo.tokenIds.begin(), localMeta.promiseInfo.tokenIds.end(), tokenId); auto uidRet = std::find(localMeta.promiseInfo.uids.begin(), localMeta.promiseInfo.uids.end(), uid); @@ -1587,15 +1779,18 @@ int32_t RdbServiceImpl::VerifyPromiseInfo(const RdbSyncerParam ¶m) !isPromise) { return RDB_ERROR; } - } - if (type == ATokenTypeEnum::TOKEN_HAP) { - for (const auto& permissionName : localMeta.promiseInfo.permissionNames) { + } else if (type == ATokenTypeEnum::TOKEN_HAP) { + for (const auto &permissionName : localMeta.promiseInfo.permissionNames) { if (PermitDelegate::VerifyPermission(permissionName, tokenId)) { return RDB_OK; } } ZLOGE("Permission denied! tokenId:0x%{public}x", tokenId); return RDB_ERROR; + } else { + ZLOGE("invalid type! bundleName:%{public}s, storeName:%{public}s, token_type is %{public}d.", + meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), type); + return RDB_ERROR; } return RDB_OK; } @@ -1615,7 +1810,7 @@ bool RdbServiceImpl::TryUpdateDeviceId(const RdbSyncerParam ¶m, const StoreM StoreMetaData syncMeta; if (oldMeta.isNeedUpdateDeviceId && oldMeta.storeType >= StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN && oldMeta.storeType <= StoreMetaData::StoreType::STORE_RELATIONAL_END && - MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), syncMeta)) { + MetaDataManager::GetInstance().LoadMeta(meta.GetKeyWithoutPath(), syncMeta)) { auto store = GetStore(param); if (store == nullptr) { ZLOGE("store is null, bundleName:%{public}s storeName:%{public}s", param.bundleName_.c_str(), @@ -1636,9 +1831,15 @@ void RdbServiceImpl::RegisterEvent() auto process = [this](const Event &event) { auto &evt = static_cast(event); auto &storeInfo = evt.GetStoreInfo(); - StoreMetaData meta(storeInfo); - meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + StoreMetaMapping mapping(storeInfo); + mapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + if (!MetaDataManager::GetInstance().LoadMeta(mapping.GetKey(), mapping, true)) { + ZLOGE("bundle:%{public}s, storeId:%{public}s", mapping.bundleName.c_str(), mapping.GetStoreAlias().c_str()); + return; + } + StoreMetaData meta = mapping; + if (!mapping.cloudPath.empty() && mapping.cloudPath != mapping.dataDir && + !MetaDataManager::GetInstance().LoadMeta(mapping.GetCloudStoreMetaKey(), meta, true)) { ZLOGE("meta empty, bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), meta.GetStoreAlias().c_str()); return; @@ -1677,4 +1878,28 @@ void RdbServiceImpl::RegisterEvent() EventCenter::GetInstance().Subscribe(BindEvent::COMPENSATE_SYNC, compensateSyncProcess); EventCenter::GetInstance().Subscribe(BindEvent::RECOVER_SYNC, compensateSyncProcess); } + +std::string RdbServiceImpl::GetPath(const RdbSyncerParam ¶m) +{ + StoreMetaData metaData; + metaData.uid = IPCSkeleton::GetCallingUid(); + metaData.tokenId = IPCSkeleton::GetCallingTokenID(); + auto [instanceId, user] = GetInstIndexAndUser(metaData.tokenId, param.bundleName_); + metaData.instanceId = instanceId; + metaData.bundleName = param.bundleName_; + metaData.storeId = RemoveSuffix(param.storeName_); + if (AccessTokenKit::GetTokenTypeFlag(metaData.tokenId) != TOKEN_HAP && param.subUser_ != 0) { + metaData.user = std::to_string(param.subUser_); + } else { + metaData.user = std::to_string(user); + } + metaData.storeType = param.type_; + metaData.securityLevel = param.level_; + metaData.area = param.area_; + metaData.appType = "harmony"; + metaData.hapName = param.hapName_; + metaData.customDir = param.customDir_; + return DirectoryManager::GetInstance().GetStorePath(metaData) + "/" + param.storeName_; +} + } // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h index 0c06e926..b7fe3c03 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -24,6 +24,7 @@ #include "commonevent/data_change_event.h" #include "commonevent/set_searchable_event.h" #include "concurrent_map.h" +#include "crypto/crypto_manager.h" #include "feature/static_acts.h" #include "metadata/secret_key_meta_data.h" #include "metadata/store_meta_data.h" @@ -53,7 +54,8 @@ public: virtual ~RdbServiceImpl(); /* IPC interface */ - std::string ObtainDistributedTableName(const std::string& device, const std::string& table) override; + std::string ObtainDistributedTableName(const RdbSyncerParam ¶m, const std::string &device, + const std::string &table) override; int32_t InitNotifier(const RdbSyncerParam ¶m, sptr notifier) override; @@ -66,10 +68,12 @@ public: int32_t Sync(const RdbSyncerParam ¶m, const Option &option, const PredicatesMemo &predicates, const AsyncDetail &async) override; - int32_t Subscribe(const RdbSyncerParam ¶m, const SubscribeOption &option, RdbStoreObserver *observer) override; + int32_t Subscribe(const RdbSyncerParam ¶m, + const SubscribeOption &option, + std::shared_ptr observer) override; int32_t UnSubscribe(const RdbSyncerParam ¶m, const SubscribeOption &option, - RdbStoreObserver *observer) override; + std::shared_ptrobserver) override; int32_t RegisterAutoSyncCallback(const RdbSyncerParam& param, std::shared_ptr observer) override; @@ -81,6 +85,8 @@ public: int32_t OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) override; + int32_t OnFeatureExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) override; + int32_t Delete(const RdbSyncerParam ¶m) override; std::pair> QuerySharingResource(const RdbSyncerParam& param, @@ -122,6 +128,7 @@ private: using DBStatus = DistributedDB::DBStatus; using SyncResult = std::pair, std::map>; using AutoCache = DistributedData::AutoCache; + using CryptoManager = DistributedData::CryptoManager; struct SyncAgent { SyncAgent() = default; explicit SyncAgent(const std::string &bundleName); @@ -178,7 +185,7 @@ private: int DoAutoSync( const std::vector &devices, const Database &dataBase, std::vector tableNames); - std::vector GetReuseDevice(const std::vector &devices); + std::vector GetReuseDevice(const std::vector &devices, const StoreMetaData &metaData); int DoOnlineSync(const std::vector &devices, const Database &dataBase); int DoDataChangeSync(const StoreInfo &storeInfo, const RdbChangedData &rdbChangedData); @@ -187,23 +194,40 @@ private: DetailAsync GetCallbacks(uint32_t tokenId, const std::string &storeName); - bool CheckAccess(const std::string& bundleName, const std::string& storeName); - std::shared_ptr GetStore(const RdbSyncerParam& param); std::shared_ptr GetStore(const StoreMetaData &storeMetaData); void OnAsyncComplete(uint32_t tokenId, pid_t pid, uint32_t seqNum, Details &&result); - StoreMetaData GetStoreMetaData(const RdbSyncerParam ¶m); + int32_t Upgrade(const RdbSyncerParam ¶m, const StoreMetaData &old); + + void GetSchema(const RdbSyncerParam ¶m); + + bool IsPostImmediately(const int32_t callingPid, const RdbNotifyConfig &rdbNotifyConfig, StoreInfo &storeInfo, + DistributedData::DataChangeEvent::EventInfo &eventInfo, const std::string &storeName); + + bool TryUpdateDeviceId(const RdbSyncerParam ¶m, const StoreMetaData &oldMeta, StoreMetaData &meta); - StoreMetaData GetStoreMetaData(const Database &dataBase); + void SaveLaunchInfo(StoreMetaData &meta); - int32_t SetSecretKey(const RdbSyncerParam ¶m, const StoreMetaData &meta); + static bool IsValidAccess(const std::string& bundleName, const std::string& storeName); - int32_t Upgrade(const RdbSyncerParam ¶m, const StoreMetaData &old); + static bool IsValidPath(const std::string& param); + + static bool IsValidCustomDir(const std::string &customDir, int32_t upLimit); - std::pair> AllocResource( + static bool IsValidParam(const RdbSyncerParam ¶m); + + static StoreMetaData GetStoreMetaData(const RdbSyncerParam ¶m); + + static std::pair LoadStoreMetaData(const RdbSyncerParam ¶m); + + static std::string GetPath(const RdbSyncerParam ¶m); + + static StoreMetaData GetStoreMetaData(const Database &dataBase); + + static std::pair> AllocResource( StoreInfo& storeInfo, std::shared_ptr rdbQuery); static Details HandleGenDetails(const DistributedData::GenDetails &details); @@ -215,35 +239,31 @@ private: static std::pair GetInstIndexAndUser(uint32_t tokenId, const std::string &bundleName); static std::string GetSubUser(const int32_t subUser); + + static bool SaveAppIDMeta(const StoreMetaData &meta, const StoreMetaData &old); - static bool GetDBPassword(const StoreMetaData &metaData, DistributedDB::CipherPassword &password); + static void SetReturnParam(const StoreMetaData &metadata, RdbSyncerParam ¶m); - void GetSchema(const RdbSyncerParam ¶m); + static bool IsNeedMetaSync(const StoreMetaData &meta, const std::vector &uuids); - void SetReturnParam(StoreMetaData &metadata, RdbSyncerParam ¶m); + static SyncResult ProcessResult(const std::map &results); - bool IsNeedMetaSync(const StoreMetaData &meta, const std::vector &uuids); + static StoreInfo GetStoreInfo(const RdbSyncerParam ¶m); - SyncResult ProcessResult(const std::map &results); + static int32_t SaveDebugInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m); - StoreInfo GetStoreInfo(const RdbSyncerParam ¶m); + static int32_t SaveDfxInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m); - int32_t SaveDebugInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m); + static int32_t SavePromiseInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m); - int32_t SaveDfxInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m); - - int32_t SavePromiseInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m); - - int32_t PostSearchEvent(int32_t evtId, const RdbSyncerParam& param, + static int32_t PostSearchEvent(int32_t evtId, const RdbSyncerParam& param, DistributedData::SetSearchableEvent::EventInfo &eventInfo); - bool IsPostImmediately(const int32_t callingPid, const RdbNotifyConfig &rdbNotifyConfig, StoreInfo &storeInfo, - DistributedData::DataChangeEvent::EventInfo &eventInfo, const std::string &storeName); - void UpdateMeta(const StoreMetaData &meta, const StoreMetaData &localMeta, AutoCache::Store store); + static void UpdateMeta(const StoreMetaData &meta, const StoreMetaData &localMeta, AutoCache::Store store); - bool UpgradeCloneSecretKey(const StoreMetaData &meta); + std::vector LoadSecretKey(const StoreMetaData &metaData, CryptoManager::SecretKeyType secretKeyType); - bool TryUpdateDeviceId(const RdbSyncerParam ¶m, const StoreMetaData &oldMeta, StoreMetaData &meta); + void SaveSecretKeyMeta(const StoreMetaData &metaData, const std::vector &password); static Factory factory_; ConcurrentMap syncAgents_; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp index 737b216b..f52549c1 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp @@ -28,15 +28,17 @@ namespace OHOS::DistributedRdb { using Anonymous = DistributedData::Anonymous; int32_t RdbServiceStub::OnRemoteObtainDistributedTableName(MessageParcel &data, MessageParcel &reply) { + RdbSyncerParam param; std::string device; std::string table; - if (!ITypesUtil::Unmarshal(data, device, table)) { + if (!ITypesUtil::Unmarshal(data, param, device, table)) { ZLOGE("Unmarshal device:%{public}s table:%{public}s", Anonymous::Change(device).c_str(), table.c_str()); return IPC_STUB_INVALID_DATA_ERR; } - std::string distributedTableName = ObtainDistributedTableName(device, table); - if (!ITypesUtil::Marshal(reply, distributedTableName)) { + std::string distributedTableName = ObtainDistributedTableName(param, device, table); + int32_t status = distributedTableName.empty() ? RDB_ERROR : RDB_OK; + if (!ITypesUtil::Marshal(reply, status, distributedTableName)) { ZLOGE("Marshal distributedTableName:%{public}s", distributedTableName.c_str()); return IPC_STUB_WRITE_PARCEL_ERR; } diff --git a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn index 97804c0c..98c13fef 100644 --- a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn @@ -21,7 +21,6 @@ config("module_private_config") { visibility = [ ":*" ] include_dirs = [ - "//foundation/distributedhardware/device_manager/interfaces/inner_kits/native_cpp/include", "${data_service_path}/adapter/include", "${data_service_path}/app/src", "${data_service_path}/framework/include", @@ -44,12 +43,6 @@ config("module_private_config") { "${data_service_path}/service/permission/include", "${data_service_path}/service/rdb/", "${data_service_path}/service/test/mock", - "${dataobject_path}/interfaces/innerkits", - "${dataobject_path}/frameworks/innerkitsimpl/include", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/include/", - "${relational_store_path}/interfaces/inner_api/cloud_data/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", "${data_service_path}/adapter/include/communicator", ] cflags = [ "-Werror" ] @@ -64,52 +57,18 @@ ohos_unittest("CloudDataTest") { cfi = true cfi_cross_dso = true debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" } module_out_path = module_output_path sources = [ - "${data_service_path}/service/backup/src/backup_manager.cpp", - "${data_service_path}/service/bootstrap/src/bootstrap.cpp", "${data_service_path}/service/cloud/cloud_data_translate.cpp", + "${data_service_path}/service/cloud/cloud_notifier_proxy.cpp", "${data_service_path}/service/cloud/cloud_service_impl.cpp", "${data_service_path}/service/cloud/cloud_service_stub.cpp", "${data_service_path}/service/cloud/cloud_types_util.cpp", "${data_service_path}/service/cloud/cloud_value_util.cpp", "${data_service_path}/service/cloud/sync_manager.cpp", "${data_service_path}/service/cloud/sync_strategies/network_sync_strategy.cpp", - "${data_service_path}/service/common/common_types_utils.cpp", - "${data_service_path}/service/common/value_proxy.cpp", - "${data_service_path}/service/common/xcollie.cpp", - "${data_service_path}/service/config/src/config_factory.cpp", - "${data_service_path}/service/config/src/model/app_id_mapping_config.cpp", - "${data_service_path}/service/config/src/model/backup_config.cpp", - "${data_service_path}/service/config/src/model/checker_config.cpp", - "${data_service_path}/service/config/src/model/cloud_config.cpp", - "${data_service_path}/service/config/src/model/component_config.cpp", - "${data_service_path}/service/config/src/model/directory_config.cpp", - "${data_service_path}/service/config/src/model/global_config.cpp", - "${data_service_path}/service/config/src/model/network_config.cpp", - "${data_service_path}/service/config/src/model/protocol_config.cpp", - "${data_service_path}/service/config/src/model/thread_config.cpp", - "${data_service_path}/service/crypto/src/crypto_manager.cpp", - "${data_service_path}/service/kvdb/user_delegate.cpp", - "${data_service_path}/service/matrix/src/device_matrix.cpp", - "${data_service_path}/service/matrix/src/matrix_event.cpp", - "${data_service_path}/service/permission/src/permission_validator.cpp", - "${data_service_path}/service/permission/src/permit_delegate.cpp", - "${data_service_path}/service/rdb/cache_cursor.cpp", - "${data_service_path}/service/rdb/rdb_asset_loader.cpp", - "${data_service_path}/service/rdb/rdb_cloud.cpp", - "${data_service_path}/service/rdb/rdb_cursor.cpp", - "${data_service_path}/service/rdb/rdb_general_store.cpp", - "${data_service_path}/service/rdb/rdb_hiview_adapter.cpp", - "${data_service_path}/service/rdb/rdb_notifier_proxy.cpp", - "${data_service_path}/service/rdb/rdb_query.cpp", - "${data_service_path}/service/rdb/rdb_result_set_impl.cpp", - "${data_service_path}/service/rdb/rdb_result_set_stub.cpp", - "${data_service_path}/service/rdb/rdb_schema_config.cpp", - "${data_service_path}/service/rdb/rdb_service_impl.cpp", - "${data_service_path}/service/rdb/rdb_service_stub.cpp", - "${data_service_path}/service/rdb/rdb_watcher.cpp", "${data_service_path}/service/test/mock/checker_mock.cpp", "cloud_data_test.cpp", ] @@ -117,35 +76,32 @@ ohos_unittest("CloudDataTest") { configs = [ ":module_private_config" ] external_deps = [ - "ability_base:base", - "ability_base:want", "access_token:libaccesstoken_sdk", "access_token:libtoken_setproc", "access_token:libtokenid_sdk", - "bundle_framework:appexecfwk_base", - "bundle_framework:appexecfwk_core", "c_utils:utils", "device_manager:devicemanagersdk", "hicollie:libhicollie", "hilog:libhilog", - "hisysevent:libhisysevent", - "huks:libhukssdk", - "ipc:ipc_core", + "googletest:gmock", + "googletest:gtest", + "ipc:ipc_single", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddb", - "netmanager_base:net_conn_manager_if", "relational_store:native_rdb", - "resource_management:global_resmgr", - "samgr:samgr_proxy", ] deps = [ "${data_service_path}/adapter/account:distributeddata_account", "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/adapter/dfx:distributeddata_dfx", "${data_service_path}/adapter/schema_helper:distributeddata_schema_helper", - "../../framework:distributeddatasvcfwk", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service/bootstrap:distributeddata_bootstrap", + "${data_service_path}/service/common:distributeddata_common", + "${data_service_path}/service/rdb:distributeddata_rdb", "mock:distributeddata_mock_static", - "//third_party/googletest:gtest_main", ] cflags = [ @@ -155,57 +111,81 @@ ohos_unittest("CloudDataTest") { cflags_cc = cflags } +ohos_unittest("CloudDataMockTest") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } + module_out_path = module_output_path + sources = [ + "${data_service_path}/service/cloud/cloud_data_translate.cpp", + "${data_service_path}/service/cloud/cloud_notifier_proxy.cpp", + "${data_service_path}/service/cloud/cloud_service_impl.cpp", + "${data_service_path}/service/cloud/cloud_service_stub.cpp", + "${data_service_path}/service/cloud/cloud_types_util.cpp", + "${data_service_path}/service/cloud/cloud_value_util.cpp", + "${data_service_path}/service/cloud/sync_manager.cpp", + "${data_service_path}/service/cloud/sync_strategies/network_sync_strategy.cpp", + "${data_service_path}/service/test/mock/checker_mock.cpp", + "mock/access_token_mock.cpp", + "mock/account_delegate_mock.cpp", + "cloud_data_mock_test.cpp", + ] + + configs = [ ":module_private_config" ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + + deps = [ + "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/adapter/dfx:distributeddata_dfx", + "${data_service_path}/adapter/schema_helper:distributeddata_schema_helper", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service/bootstrap:distributeddata_bootstrap", + "${data_service_path}/service/common:distributeddata_common", + "${data_service_path}/service/rdb:distributeddata_rdb", + "mock:distributeddata_mock_static", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "device_manager:devicemanagersdk", + "googletest:gmock", + "googletest:gtest", + "hicollie:libhicollie", + "hilog:libhilog", + "ipc:ipc_single", + "json:nlohmann_json_static", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "relational_store:native_rdb", + ] +} + + ohos_unittest("CloudServiceImplTest") { sanitize = { cfi = true cfi_cross_dso = true debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" } module_out_path = module_output_path sources = [ - "${data_service_path}/service/backup/src/backup_manager.cpp", - "${data_service_path}/service/bootstrap/src/bootstrap.cpp", "${data_service_path}/service/cloud/cloud_data_translate.cpp", + "${data_service_path}/service/cloud/cloud_notifier_proxy.cpp", "${data_service_path}/service/cloud/cloud_service_impl.cpp", "${data_service_path}/service/cloud/cloud_service_stub.cpp", "${data_service_path}/service/cloud/cloud_types_util.cpp", "${data_service_path}/service/cloud/cloud_value_util.cpp", "${data_service_path}/service/cloud/sync_manager.cpp", "${data_service_path}/service/cloud/sync_strategies/network_sync_strategy.cpp", - "${data_service_path}/service/common/common_types_utils.cpp", - "${data_service_path}/service/common/value_proxy.cpp", - "${data_service_path}/service/common/xcollie.cpp", - "${data_service_path}/service/config/src/config_factory.cpp", - "${data_service_path}/service/config/src/model/app_id_mapping_config.cpp", - "${data_service_path}/service/config/src/model/backup_config.cpp", - "${data_service_path}/service/config/src/model/checker_config.cpp", - "${data_service_path}/service/config/src/model/cloud_config.cpp", - "${data_service_path}/service/config/src/model/component_config.cpp", - "${data_service_path}/service/config/src/model/directory_config.cpp", - "${data_service_path}/service/config/src/model/global_config.cpp", - "${data_service_path}/service/config/src/model/network_config.cpp", - "${data_service_path}/service/config/src/model/protocol_config.cpp", - "${data_service_path}/service/config/src/model/thread_config.cpp", - "${data_service_path}/service/crypto/src/crypto_manager.cpp", - "${data_service_path}/service/kvdb/user_delegate.cpp", - "${data_service_path}/service/matrix/src/device_matrix.cpp", - "${data_service_path}/service/matrix/src/matrix_event.cpp", - "${data_service_path}/service/permission/src/permission_validator.cpp", - "${data_service_path}/service/permission/src/permit_delegate.cpp", - "${data_service_path}/service/rdb/cache_cursor.cpp", - "${data_service_path}/service/rdb/rdb_asset_loader.cpp", - "${data_service_path}/service/rdb/rdb_cloud.cpp", - "${data_service_path}/service/rdb/rdb_cursor.cpp", - "${data_service_path}/service/rdb/rdb_general_store.cpp", - "${data_service_path}/service/rdb/rdb_hiview_adapter.cpp", - "${data_service_path}/service/rdb/rdb_notifier_proxy.cpp", - "${data_service_path}/service/rdb/rdb_query.cpp", - "${data_service_path}/service/rdb/rdb_result_set_impl.cpp", - "${data_service_path}/service/rdb/rdb_result_set_stub.cpp", - "${data_service_path}/service/rdb/rdb_schema_config.cpp", - "${data_service_path}/service/rdb/rdb_service_impl.cpp", - "${data_service_path}/service/rdb/rdb_service_stub.cpp", - "${data_service_path}/service/rdb/rdb_watcher.cpp", "${data_service_path}/service/test/mock/checker_mock.cpp", "cloud_service_impl_test.cpp", ] @@ -213,35 +193,31 @@ ohos_unittest("CloudServiceImplTest") { configs = [ ":module_private_config" ] external_deps = [ - "ability_base:base", - "ability_base:want", "access_token:libaccesstoken_sdk", "access_token:libtoken_setproc", - "access_token:libtokenid_sdk", - "bundle_framework:appexecfwk_base", - "bundle_framework:appexecfwk_core", + "json:nlohmann_json_static", "c_utils:utils", "device_manager:devicemanagersdk", + "googletest:gmock", + "googletest:gtest", "hicollie:libhicollie", "hilog:libhilog", - "hisysevent:libhisysevent", - "huks:libhukssdk", - "ipc:ipc_core", + "ipc:ipc_single", "kv_store:distributeddata_inner", "kv_store:distributeddb", - "netmanager_base:net_conn_manager_if", "relational_store:native_rdb", - "resource_management:global_resmgr", - "samgr:samgr_proxy", ] deps = [ "${data_service_path}/adapter/account:distributeddata_account", "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/adapter/dfx:distributeddata_dfx", "${data_service_path}/adapter/schema_helper:distributeddata_schema_helper", - "../../framework:distributeddatasvcfwk", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service/bootstrap:distributeddata_bootstrap", + "${data_service_path}/service/common:distributeddata_common", + "${data_service_path}/service/rdb:distributeddata_rdb", "mock:distributeddata_mock_static", - "//third_party/googletest:gtest_main", ] cflags = [ @@ -261,6 +237,7 @@ ohos_unittest("CloudTest") { "ability_base:base", "ability_base:want", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_inner", @@ -271,7 +248,6 @@ ohos_unittest("CloudTest") { "../../framework:distributeddatasvcfwk", "../../service:distributeddatasvc", "mock:distributeddata_mock_static", - "//third_party/googletest:gtest_main", ] } @@ -282,11 +258,6 @@ ohos_unittest("ValueProxyServiceTest") { "value_proxy_test.cpp", ] - include_dirs = [ - "../../../../../relational_store/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", - ] - configs = [ ":module_private_config" ] cflags = [ @@ -300,17 +271,17 @@ ohos_unittest("ValueProxyServiceTest") { "ability_base:base", "ability_base:want", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "relational_store:native_rdb", ] deps = [ - "${kv_store_distributeddb_path}:distributeddb", - "${relational_store_inner_api_path}:native_rdb_static", "../../framework:distributeddatasvcfwk", "../../service:distributeddatasvc", - "//third_party/googletest:gtest_main", ] } @@ -324,16 +295,16 @@ ohos_unittest("ConfigFactoryTest") { "ability_base:base", "ability_base:want", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddata_inner", + "openssl:libcrypto_shared", ] deps = [ "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/service:distributeddatasvc", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", ] } @@ -347,17 +318,17 @@ ohos_unittest("DirectoryManagerTest") { "ability_base:base", "ability_base:want", "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddata_inner", ] deps = [ "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/service:distributeddatasvc", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", ] } @@ -371,17 +342,19 @@ ohos_unittest("CryptoManagerTest") { "ability_base:base", "ability_base:want", "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", "access_token:libnativetoken", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", + "huks:libhukssdk", "ipc:ipc_core", + "kv_store:distributeddata_inner", ] deps = [ "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/service:distributeddatasvc", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", ] } @@ -407,16 +380,17 @@ ohos_unittest("DeviceMatrixTest") { "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "c_utils:utils", + "device_manager:devicemanagersdk", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner", - "//third_party/googletest:gtest_main", ] } @@ -425,10 +399,12 @@ ohos_unittest("KVDBGeneralStoreTest") { cfi = true cfi_cross_dso = true debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" } module_out_path = module_output_path sources = [ "kvdb_general_store_test.cpp", + "mock/account_delegate_mock.cpp", "mock/db_change_data_mock.cpp", "mock/db_store_mock.cpp", "mock/general_watcher_mock.cpp", @@ -439,9 +415,6 @@ ohos_unittest("KVDBGeneralStoreTest") { "${data_service_path}/service/common", "${data_service_path}/service/rdb", "${data_service_path}/service/kvdb", - "${relational_store_path}/interfaces/innerapi/clouddata/include", - "${relational_store_path}/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", ] configs = [ ":module_private_config" ] @@ -457,18 +430,20 @@ ohos_unittest("KVDBGeneralStoreTest") { "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "c_utils:utils", + "device_manager:devicemanagersdk", + "googletest:gmock_main", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "relational_store:native_rdb", ] deps = [ - "${data_service_path}/adapter/account:distributeddata_account", "${data_service_path}/adapter/communicator:distributeddata_communicator", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/kvdb:distributeddata_kvdb", - "${kv_store_distributeddb_path}:distributeddb", - "//third_party/googletest:gtest_main", ] } @@ -552,12 +527,7 @@ ohos_unittest("RdbResultSetImplTest") { "rdb_result_set_impl_test.cpp", ] - include_dirs = [ - "${data_service_path}/service/rdb", - "${relational_store_path}/interfaces/inner_api/cloud_data/include", - "${relational_store_path}/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", - ] + include_dirs = [ "${data_service_path}/service/rdb" ] configs = [ ":module_private_config" ] @@ -574,35 +544,33 @@ ohos_unittest("RdbResultSetImplTest") { "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "c_utils:utils", + "googletest:gmock_main", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddb", + "relational_store:native_rdb", + "kv_store:datamgr_common", ] deps = [ "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", - "${kv_store_distributeddb_path}:distributeddb", - "${relational_store_inner_api_path}:native_rdb_static", - "//third_party/googletest:gtest_main", ] } ohos_unittest("RdbServiceTest") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } module_out_path = module_output_path sources = [ - "${data_service_path}/service/common/value_proxy.cpp", - "${data_service_path}/service/rdb/cache_cursor.cpp", - "${data_service_path}/service/rdb/rdb_asset_loader.cpp", - "${data_service_path}/service/rdb/rdb_cloud.cpp", - "${data_service_path}/service/rdb/rdb_cursor.cpp", - "${data_service_path}/service/rdb/rdb_general_store.cpp", - "${data_service_path}/service/rdb/rdb_notifier_proxy.cpp", - "${data_service_path}/service/rdb/rdb_query.cpp", - "${data_service_path}/service/rdb/rdb_result_set_impl.cpp", - "${data_service_path}/service/rdb/rdb_result_set_stub.cpp", - "${data_service_path}/service/rdb/rdb_watcher.cpp", "cache_cursor_test.cpp", "mock/general_watcher_mock.cpp", + "mock/relational_store_manager_mock.cpp", "rdb_asset_loader_test.cpp", "rdb_cloud_test.cpp", "rdb_cursor_test.cpp", @@ -611,17 +579,9 @@ ohos_unittest("RdbServiceTest") { "rdb_result_set_stub_test.cpp", ] - include_dirs = [ - "${relational_store_path}/interfaces/inner_api/cloud_data/include", - "${relational_store_path}/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", - ] - configs = [ ":module_private_config" ] cflags = [ - "-Dprivate=public", - "-Dprotected=public", "-Wno-multichar", "-Wno-c99-designator", "-fno-access-control", # Ignore Private Member Access Control @@ -633,82 +593,246 @@ ohos_unittest("RdbServiceTest") { "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "c_utils:utils", + "device_manager:devicemanagersdk", + "googletest:gmock_main", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddb", + "relational_store:native_rdb", ] deps = [ + "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/adapter/dfx:distributeddata_dfx", + "${data_service_path}/adapter/network:distributeddata_network", "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", - "${data_service_path}/service:distributeddatasvc", - "${kv_store_distributeddb_path}:distributeddb", - "${relational_store_inner_api_path}:native_rdb_static", - "//third_party/googletest:gtest_main", + "${data_service_path}/service/backup:distributeddata_backup", + "${data_service_path}/service/bootstrap:distributeddata_bootstrap", + "${data_service_path}/service/common:distributeddata_common", + "${data_service_path}/service/dumper:distributeddata_dumper", + "${data_service_path}/service/matrix:distributeddata_matrix", + "${data_service_path}/service/permission:distributeddata_permit", ] + + if (defined(global_parts_info) && + defined(global_parts_info.theme_screenlock_mgr)) { + deps += + [ "${data_service_path}/adapter/screenlock:distributeddata_screenlock" ] + } + + if (datamgr_service_cloud) { + deps += [ "${data_service_path}/service/cloud:distributeddata_cloud" ] + } + + if (datamgr_service_kvdb) { + deps += [ "${data_service_path}/service/kvdb:distributeddata_kvdb" ] + } + + if (datamgr_service_rdb) { + deps += [ "${data_service_path}/service/rdb:distributeddata_rdb" ] + } + + if (datamgr_service_object) { + deps += [ "${data_service_path}/service/object:distributeddata_object" ] + } } -ohos_unittest("ObjectAssetLoaderTest") { +ohos_unittest("RdbServiceImplTest") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } module_out_path = module_output_path sources = [ - "../object/src/object_asset_loader.cpp", - "../object/src/object_asset_machine.cpp", - "../object/src/object_snapshot.cpp", - "object_asset_loader_test.cpp", + "${data_service_path}/service/test/mock/general_store_mock.cpp", + "${data_service_path}/service/test/mock/cursor_mock.cpp", + "mock/device_manager_adapter_mock.cpp", + "mock/checker_mock.cpp", + "mock/db_change_data_mock.cpp", + "mock/db_store_mock.cpp", + "rdb_service_impl_test.cpp", ] include_dirs = [ - "${dataobject_path}/frameworks/innerkitsimpl/include/common", - "${dataobject_path}/interfaces/innerkits", - "${relational_store_path}/interfaces/inner_api/common_type/include", + "${data_service_path}/adapter/include/communicator", + "${data_service_path}/framework/include/eventcenter", + "${data_service_path}/service/test/mock", ] - configs = [ ":module_private_config" ] + defines = [ + "TEST_ON_DEVICE", + "OPENSSL_SUPPRESS_DEPRECATED", + ] + cflags = [ + "-Werror", + "-Dprivate=public", + "-Dprotected=public", + "-Wno-multichar", + "-Wno-c99-designator", + "-fno-access-control", # Ignore Private Member Access Control + ] external_deps = [ + "ability_base:base", + "ability_base:want", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtokenid_sdk", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", "c_utils:utils", - "dfs_service:cloudsync_asset_kit_inner", - "dfs_service:distributed_file_daemon_kit_inner", + "data_share:datashare_common", + "data_share:datashare_consumer", + "device_manager:devicemanagersdk", + "dsoftbus:softbus_client", + "googletest:gmock_main", + "googletest:gtest_main", + "hicollie:libhicollie", "hilog:libhilog", "hisysevent:libhisysevent", + "huks:libhukssdk", "ipc:ipc_core", - "json:nlohmann_json_static", + "kv_store:datamgr_common", "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "relational_store:native_rdb", + "resource_management:global_resmgr", ] deps = [ + "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//third_party/googletest:gtest_main", - ] - - cflags = [ - "-Dprivate=public", - "-Dprotected=public", + "${data_service_path}/service/rdb:distributeddata_rdb", ] } -ohos_unittest("ObjectAssetMachineTest") { +ohos_unittest("RdbServiceImplTokenTest") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } module_out_path = module_output_path sources = [ - "../object/src/object_asset_loader.cpp", - "../object/src/object_asset_machine.cpp", - "object_asset_machine_test.cpp", + "mock/access_token_mock.cpp", + "mock/checker_mock.cpp", + "mock/db_change_data_mock.cpp", + "mock/db_store_mock.cpp", + "rdb_service_impl_token_test.cpp", ] include_dirs = [ - "${dataobject_path}/frameworks/innerkitsimpl/include/common", - "${dataobject_path}/interfaces/innerkits", - "${relational_store_path}/interfaces/inner_api/common_type/include", + "${data_service_path}/adapter/include/communicator", + "${data_service_path}/framework/include/eventcenter", + "${data_service_path}/service/test/mock", + ] + + defines = [ + "TEST_ON_DEVICE", + "OPENSSL_SUPPRESS_DEPRECATED", + ] + cflags = [ + "-Werror", + "-Dprotected=public", + "-Wno-multichar", + "-Wno-c99-designator", + "-fno-access-control", # Ignore Private Member Access Control + ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtokenid_sdk", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "data_share:datashare_common", + "data_share:datashare_consumer", + "device_manager:devicemanagersdk", + "dsoftbus:softbus_client", + "googletest:gmock_main", + "googletest:gtest_main", + "hicollie:libhicollie", + "hilog:libhilog", + "hisysevent:libhisysevent", + "huks:libhukssdk", + "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "relational_store:native_rdb", + "resource_management:global_resmgr", + ] + + deps = [ + "${data_service_path}/adapter/utils:distributeddata_utils", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "${data_service_path}/service/rdb:distributeddata_rdb", + ] +} + +ohos_unittest("ObjectAssetLoaderTest") { + module_out_path = module_output_path + sources = [ + "../object/src/object_asset_loader.cpp", + "../object/src/object_asset_machine.cpp", + "../object/src/object_snapshot.cpp", + "object_asset_loader_test.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "c_utils:utils", + "data_object:data_object_inner", + "dfs_service:cloudsync_asset_kit_inner", + "dfs_service:distributed_file_daemon_kit_inner", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "ipc:ipc_core", + "json:nlohmann_json_static", + "kv_store:distributeddata_inner", + ] + + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("ObjectAssetMachineTest") { + module_out_path = module_output_path + sources = [ + "../object/src/object_asset_loader.cpp", + "../object/src/object_asset_machine.cpp", + "object_asset_machine_test.cpp", ] configs = [ ":module_private_config" ] external_deps = [ "c_utils:utils", + "data_object:data_object_inner", "dfs_service:cloudsync_asset_kit_inner", "dfs_service:distributed_file_daemon_kit_inner", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "ipc:ipc_core", @@ -719,7 +843,6 @@ ohos_unittest("ObjectAssetMachineTest") { deps = [ "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//third_party/googletest:gtest_main", ] } @@ -728,6 +851,7 @@ ohos_unittest("ObjectDmsHandlerTest") { cfi = true cfi_cross_dso = true debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" } module_out_path = module_output_path sources = [ @@ -741,7 +865,9 @@ ohos_unittest("ObjectDmsHandlerTest") { external_deps = [ "c_utils:utils", + "device_manager:devicemanagersdk", "dmsfwk:distributed_sdk", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_inner", @@ -750,7 +876,6 @@ ohos_unittest("ObjectDmsHandlerTest") { deps = [ "${data_service_path}/adapter/communicator:distributeddata_communicator", "${data_service_path}/framework:distributeddatasvcfwk", - "//third_party/googletest:gtest_main", ] cflags = [ @@ -762,6 +887,7 @@ ohos_unittest("ObjectDmsHandlerTest") { ohos_unittest("ObjectManagerTest") { module_out_path = module_output_path sources = [ + "${data_service_path}/app/src/kvstore_meta_manager.cpp", "${data_service_path}/service/common/common_types_utils.cpp", "${data_service_path}/service/common/value_proxy.cpp", "../object/src/object_asset_loader.cpp", @@ -774,6 +900,7 @@ ohos_unittest("ObjectManagerTest") { "../object/src/object_service_stub.cpp", "../object/src/object_snapshot.cpp", "../object/src/object_types_utils.cpp", + "mock/device_manager_adapter_mock.cpp", "mock/kv_store_nb_delegate_mock.cpp", "object_manager_test.cpp", "object_service_impl_test.cpp", @@ -781,11 +908,10 @@ ohos_unittest("ObjectManagerTest") { ] include_dirs = [ - "${dataobject_path}/frameworks/innerkitsimpl/include", - "${data_service_path}/service/common", - "${dataobject_path}/frameworks/innerkitsimpl/include/common", - "${dataobject_path}/interfaces/innerkits", "${data_service_path}/adapter/include/utils", + "${data_service_path}/app/src", + "${data_service_path}/service/common", + "${data_service_path}/service/test/mock", ] configs = [ ":module_private_config" ] @@ -795,23 +921,30 @@ ohos_unittest("ObjectManagerTest") { "access_token:libtoken_setproc", "access_token:libtokenid_sdk", "c_utils:utils", + "data_object:data_object_inner", "data_object:distributeddataobject_impl", + "dataclassification:data_transit_mgr", + "device_manager:devicemanagersdk", "dfs_service:cloudsync_asset_kit_inner", "dfs_service:distributed_file_daemon_kit_inner", "dmsfwk:distributed_sdk", + "googletest:gmock_main", + "googletest:gtest_main", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "ipc:ipc_core", "json:nlohmann_json_static", "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", "kv_store:distributeddb", "relational_store:native_rdb", + "safwk:system_ability_fwk", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//third_party/googletest:gtest_main", ] cflags = [ @@ -820,38 +953,104 @@ ohos_unittest("ObjectManagerTest") { ] } -ohos_unittest("ObjectSnapshotTest") { +ohos_unittest("ObjectManagerMockTest") { module_out_path = module_output_path sources = [ + "${data_service_path}/app/src/kvstore_meta_manager.cpp", + "${data_service_path}/service/common/common_types_utils.cpp", + "${data_service_path}/service/common/value_proxy.cpp", "../object/src/object_asset_loader.cpp", "../object/src/object_asset_machine.cpp", + "../object/src/object_callback_proxy.cpp", + "../object/src/object_data_listener.cpp", + "../object/src/object_dms_handler.cpp", + "../object/src/object_manager.cpp", + "../object/src/object_service_impl.cpp", + "../object/src/object_service_stub.cpp", "../object/src/object_snapshot.cpp", - "object_snapshot_test.cpp", + "../object/src/object_types_utils.cpp", + "mock/access_token_mock.cpp", + "mock/account_delegate_mock.cpp", + "mock/device_manager_adapter_mock.cpp", + "mock/kv_store_nb_delegate_mock.cpp", + "object_manager_mock_test.cpp", + "mock/meta_data_manager_mock.cpp", + "mock/device_matrix_mock.cpp", + "mock/distributed_file_daemon_manager_mock.cpp", ] include_dirs = [ - "${dataobject_path}/frameworks/innerkitsimpl/include/common", - "${dataobject_path}/interfaces/innerkits", - "${relational_store_path}/interfaces/inner_api/common_type/include", + "${data_service_path}/adapter/include/utils", + "${data_service_path}/app/src", + "${data_service_path}/service/common", + "${data_service_path}/service/test/mock", ] configs = [ ":module_private_config" ] external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", + "access_token:libtokenid_sdk", "c_utils:utils", + "data_object:distributeddataobject_impl", + "data_object:data_object_inner", + "dataclassification:data_transit_mgr", + "device_manager:devicemanagersdk", "dfs_service:cloudsync_asset_kit_inner", "dfs_service:distributed_file_daemon_kit_inner", + "dmsfwk:distributed_sdk", + "googletest:gmock_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "ipc:ipc_core", + "cJSON:cjson", + "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "relational_store:native_rdb", + "safwk:system_ability_fwk", + ] + + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] +} + +ohos_unittest("ObjectSnapshotTest") { + module_out_path = module_output_path + sources = [ + "../object/src/object_asset_loader.cpp", + "../object/src/object_asset_machine.cpp", + "../object/src/object_snapshot.cpp", + "object_snapshot_test.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "c_utils:utils", + "data_object:data_object_inner", + "dfs_service:cloudsync_asset_kit_inner", + "dfs_service:distributed_file_daemon_kit_inner", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "ipc:ipc_core", "json:nlohmann_json_static", "kv_store:distributeddata_inner", + "relational_store:native_rdb", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//third_party/googletest:gtest_main", ] } @@ -872,9 +1071,6 @@ ohos_unittest("MetaDataTest") { "${data_service_path}/app/src", "${data_service_path}/service/kvdb", "${data_service_path}/adapter/include/account", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", "${data_service_path}/adapter/include/communicator", ] @@ -882,15 +1078,21 @@ ohos_unittest("MetaDataTest") { external_deps = [ "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "access_token:libtoken_setproc", "c_utils:utils", "dataclassification:data_transit_mgr", + "device_manager:devicemanagersdk", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "ipc:ipc_core", "json:nlohmann_json_static", "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "kv_store:kvdb_inner_lite", + "safwk:system_ability_fwk", ] deps = [ @@ -898,12 +1100,17 @@ ohos_unittest("MetaDataTest") { "${data_service_path}/adapter/communicator:distributeddata_communicator", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/kvdb:distributeddata_kvdb", - "${kv_store_path}/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", ] } ohos_unittest("UdmfRunTimeStoreTest") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } + module_out_path = module_output_path sources = [ "${data_service_path}/app/src/kvstore_meta_manager.cpp", @@ -915,44 +1122,51 @@ ohos_unittest("UdmfRunTimeStoreTest") { "${data_service_path}/adapter/include/communicator", "${data_service_path}/app/src", "${data_service_path}/service/kvdb", + "${data_service_path}/service/matrix/include", "${data_service_path}/service/udmf", "${data_service_path}/service/udmf/store", "${data_service_path}/service/udmf/preprocess", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", + "${data_service_path}/framework/include/directory", ] configs = [ ":module_private_config" ] + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + external_deps = [ "ability_base:base", "ability_base:want", "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "access_token:libtoken_setproc", "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", "c_utils:utils", "dataclassification:data_transit_mgr", + "device_manager:devicemanagersdk", "dsoftbus:softbus_client", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "image_framework:image", "ipc:ipc_core", "kv_store:distributeddata_inner", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "kv_store:distributeddata_mgr", + "openssl:libcrypto_shared", "samgr:samgr_proxy", + "safwk:system_ability_fwk", "udmf:udmf_client", ] deps = [ - "${data_service_path}/adapter/communicator:distributeddata_communicator", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", "${data_service_path}/service/udmf:udmf_server", - "${kv_store_path}/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", ] defines = [ @@ -966,31 +1180,32 @@ ohos_unittest("DataShareServiceImplTest") { cfi = true cfi_cross_dso = true debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" } module_out_path = module_output_path include_dirs = [ - "${datashare_path}/frameworks/native/common/include", - "${datashare_path}/interfaces/inner_api/common/include", - "${datashare_path}/interfaces/inner_api/consumer/include", - "//third_party/json/single_include", + "${data_service_path}/service/config/include", + "${data_service_path}/framework/include/metadata", + "${data_service_path}/service/data_share/common", ] sources = [ "${data_service_path}/service/common/xcollie.cpp", - "${data_service_path}/service/crypto/src/crypto_manager.cpp", "${data_service_path}/service/data_share/common/app_connect_manager.cpp", "${data_service_path}/service/data_share/common/bundle_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/common_utils.cpp", "${data_service_path}/service/data_share/common/db_delegate.cpp", "${data_service_path}/service/data_share/common/div_strategy.cpp", "${data_service_path}/service/data_share/common/extension_ability_manager.cpp", "${data_service_path}/service/data_share/common/extension_connect_adaptor.cpp", "${data_service_path}/service/data_share/common/extension_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/proxy_data_manager.cpp", "${data_service_path}/service/data_share/common/kv_delegate.cpp", "${data_service_path}/service/data_share/common/rdb_delegate.cpp", "${data_service_path}/service/data_share/common/scheduler_manager.cpp", "${data_service_path}/service/data_share/common/seq_strategy.cpp", - "${data_service_path}/service/data_share/common/uri_utils.cpp", + "${data_service_path}/service/data_share/common/utils.cpp", "${data_service_path}/service/data_share/data/published_data.cpp", "${data_service_path}/service/data_share/data/resultset_json_formatter.cpp", "${data_service_path}/service/data_share/data/template_data.cpp", @@ -1018,6 +1233,7 @@ ohos_unittest("DataShareServiceImplTest") { "${data_service_path}/service/data_share/strategies/rdb_notify_strategy.cpp", "${data_service_path}/service/data_share/strategies/subscribe_strategy.cpp", "${data_service_path}/service/data_share/strategies/template_strategy.cpp", + "${data_service_path}/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp", "${data_service_path}/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp", "${data_service_path}/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp", "${data_service_path}/service/data_share/sys_event_subscriber.cpp", @@ -1032,6 +1248,8 @@ ohos_unittest("DataShareServiceImplTest") { "data_share_subscriber_managers_test.cpp", "data_share_types_util_test.cpp", "kv_dalegate_test.cpp", + "mock/account_delegate_mock.cpp", + "data_share_uri_utils_test.cpp", ] configs = [ ":module_private_config" ] @@ -1062,7 +1280,11 @@ ohos_unittest("DataShareServiceImplTest") { "c_utils:utils", "common_event_service:cesfwk_innerkits", "data_share:datashare_common", + "data_share:datashare_common_lite", + "data_share:datashare_consumer", "device_manager:devicemanagersdk", + "googletest:gmock_main", + "googletest:gtest_main", "hicollie:libhicollie", "hilog:libhilog", "hisysevent:libhisysevent", @@ -1072,6 +1294,8 @@ ohos_unittest("DataShareServiceImplTest") { "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddb", + "qos_manager:concurrent_task_client", + "qos_manager:qos", "relational_store:native_rdb", "relational_store:rdb_data_share_adapter", "resource_management:global_resmgr", @@ -1083,13 +1307,212 @@ ohos_unittest("DataShareServiceImplTest") { "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "${kv_store_distributeddb_path}:distributeddb", - "//third_party/googletest:gtest_main", + ] +} + +ohos_unittest("DataShareServiceImplMockTest") { + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } + module_out_path = module_output_path + + include_dirs = [ "${data_service_path}/service/config/include" ] + + sources = [ + "${data_service_path}/service/common/xcollie.cpp", + "${data_service_path}/service/config/src/model/app_access_check_config.cpp", + "${data_service_path}/service/config/src/model/app_id_mapping_config.cpp", + "${data_service_path}/service/config/src/model/backup_config.cpp", + "${data_service_path}/service/config/src/model/checker_config.cpp", + "${data_service_path}/service/config/src/model/cloud_config.cpp", + "${data_service_path}/service/config/src/model/component_config.cpp", + "${data_service_path}/service/config/src/model/datashare_config.cpp", + "${data_service_path}/service/config/src/model/device_sync_app_white_list_config.cpp", + "${data_service_path}/service/config/src/model/directory_config.cpp", + "${data_service_path}/service/config/src/model/global_config.cpp", + "${data_service_path}/service/config/src/model/network_config.cpp", + "${data_service_path}/service/config/src/model/protocol_config.cpp", + "${data_service_path}/service/config/src/model/thread_config.cpp", + "${data_service_path}/service/data_share/common/app_connect_manager.cpp", + "${data_service_path}/service/data_share/common/bundle_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/common_utils.cpp", + "${data_service_path}/service/data_share/common/db_delegate.cpp", + "${data_service_path}/service/data_share/common/div_strategy.cpp", + "${data_service_path}/service/data_share/common/extension_ability_manager.cpp", + "${data_service_path}/service/data_share/common/extension_connect_adaptor.cpp", + "${data_service_path}/service/data_share/common/extension_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/proxy_data_manager.cpp", + "${data_service_path}/service/data_share/common/kv_delegate.cpp", + "${data_service_path}/service/data_share/common/rdb_delegate.cpp", + "${data_service_path}/service/data_share/common/scheduler_manager.cpp", + "${data_service_path}/service/data_share/common/seq_strategy.cpp", + "${data_service_path}/service/data_share/common/utils.cpp", + "${data_service_path}/service/data_share/data/published_data.cpp", + "${data_service_path}/service/data_share/data/resultset_json_formatter.cpp", + "${data_service_path}/service/data_share/data/template_data.cpp", + "${data_service_path}/service/data_share/data_provider_config.cpp", + "${data_service_path}/service/data_share/data_share_db_config.cpp", + "${data_service_path}/service/data_share/data_share_obs_proxy.cpp", + "${data_service_path}/service/data_share/data_share_profile_config.cpp", + "${data_service_path}/service/data_share/data_share_service_impl.cpp", + "${data_service_path}/service/data_share/data_share_service_stub.cpp", + "${data_service_path}/service/data_share/data_share_silent_config.cpp", + "${data_service_path}/service/data_share/dfx/hiview_adapter.cpp", + "${data_service_path}/service/data_share/dfx/hiview_fault_adapter.cpp", + "${data_service_path}/service/data_share/strategies/data_proxy/load_config_from_data_proxy_node_strategy.cpp", + "${data_service_path}/service/data_share/strategies/data_share/load_config_from_data_share_bundle_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/check_is_data_proxy_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/check_is_single_app_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/cross_permission_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_common_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_data_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_from_bundle_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/permission_strategy.cpp", + "${data_service_path}/service/data_share/strategies/get_data_strategy.cpp", + "${data_service_path}/service/data_share/strategies/publish_strategy.cpp", + "${data_service_path}/service/data_share/strategies/rdb_notify_strategy.cpp", + "${data_service_path}/service/data_share/strategies/subscribe_strategy.cpp", + "${data_service_path}/service/data_share/strategies/template_strategy.cpp", + "${data_service_path}/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp", + "${data_service_path}/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp", + "${data_service_path}/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp", + "${data_service_path}/service/data_share/sys_event_subscriber.cpp", + "data_share_sys_event_subscriber_test.cpp", + "data_share_scheduler_manager_test.cpp", + "mock/config_factory_mock.cpp", + ] + + configs = [ ":module_private_config" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-Wno-multichar", + "-Wno-c99-designator", + "-Dprivate=public", + "-Dprotected=public", + ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "ability_runtime:wantagent_innerkits", + "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", + "access_token:libtokenid_sdk", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "data_share:datashare_common", + "data_share:datashare_common_lite", + "data_share:datashare_consumer", + "device_manager:devicemanagersdk", + "googletest:gmock_main", + "googletest:gtest_main", + "hicollie:libhicollie", + "hilog:libhilog", + "hisysevent:libhisysevent", + "huks:libhukssdk", + "init:libbegetutil", + "ipc:ipc_core", + "cJSON:cjson", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "kv_store:distributeddb", + "qos_manager:concurrent_task_client", + "qos_manager:qos", + "relational_store:native_rdb", + "relational_store:rdb_data_share_adapter", + "resource_management:global_resmgr", + "samgr:samgr_proxy", + "time_service:time_client", + ] + + deps = [ + "${data_service_path}/adapter/utils:distributeddata_utils", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + ] +} + +ohos_unittest("KvdbServicePasswordTest") { + module_out_path = module_output_path + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } + sources = [ + "kvdb_service_password_test.cpp", + ] + + include_dirs = [ + "${data_service_path}/app/src", + "${data_service_path}/service/kvdb", + "${data_service_path}/adapter/include/account", + "${data_service_path}/framework/include", + "${data_service_path}/framework/include/cloud", + "${data_service_path}/framework/include/eventcenter", + "${data_service_path}/service/test/mock", + "${data_service_path}/adapter/include/communicator", + ] + + configs = [ ":module_private_config" ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "access_token:libtoken_setproc", + "c_utils:utils", + "dataclassification:data_transit_mgr", + "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "ipc:ipc_core", + "json:nlohmann_json_static", + "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "kv_store:kvdb_inner_lite", + "relational_store:native_rdb", + "safwk:system_ability_fwk", + ] + + deps = [ + "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service/kvdb:distributeddata_kvdb", + "mock:distributeddata_mock_static", ] } ohos_unittest("KvdbServiceImplTest") { module_out_path = module_output_path + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } sources = [ "${data_service_path}/app/src/kvstore_meta_manager.cpp", "kvdb_service_impl_test.cpp", @@ -1108,9 +1531,6 @@ ohos_unittest("KvdbServiceImplTest") { "${data_service_path}/framework/include/cloud", "${data_service_path}/framework/include/eventcenter", "${data_service_path}/service/test/mock", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", "${data_service_path}/adapter/include/communicator", ] @@ -1123,17 +1543,24 @@ ohos_unittest("KvdbServiceImplTest") { external_deps = [ "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "access_token:libtoken_setproc", "c_utils:utils", "dataclassification:data_transit_mgr", "device_auth:deviceauth_sdk", + "device_manager:devicemanagersdk", "googletest:gmock_main", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "ipc:ipc_core", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "kv_store:kvdb_inner_lite", "relational_store:native_rdb", + "safwk:system_ability_fwk", ] deps = [ @@ -1141,9 +1568,7 @@ ohos_unittest("KvdbServiceImplTest") { "${data_service_path}/adapter/communicator:distributeddata_communicator", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/kvdb:distributeddata_kvdb", - "${kv_store_path}/frameworks/libs/distributeddb:distributeddb", "mock:distributeddata_mock_static", - "//third_party/googletest:gtest_main", ] } @@ -1165,7 +1590,9 @@ ohos_unittest("DumpHelperTest") { external_deps = [ "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", + "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddb", "relational_store:native_rdb", @@ -1174,21 +1601,93 @@ ohos_unittest("DumpHelperTest") { deps = [ "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "//third_party/googletest:gtest_main", ] } ohos_unittest("UdmfServiceImplTest") { module_out_path = module_output_path + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } sources = [ "${data_service_path}/framework/feature/feature_system.cpp", + "${data_service_path}/app/src/kvstore_meta_manager.cpp", "udmf_service_impl_test.cpp", ] include_dirs = [ - "${data_service_path}/service/udmf/store", + "${data_service_path}/adapter/include/account", + "${data_service_path}/adapter/include/communicator", + "${data_service_path}/app/src", + "${data_service_path}/framework/include/account", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/matrix/include", "${data_service_path}/service/udmf", + "${data_service_path}/service/udmf/store", + "${data_service_path}/service/udmf/preprocess", + "${data_service_path}/service/udmf/permission", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "access_token:libtoken_setproc", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "dataclassification:data_transit_mgr", + "device_manager:devicemanagersdk", + "dsoftbus:softbus_client", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "image_framework:image", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "kv_store:distributeddata_mgr", + "openssl:libcrypto_shared", + "samgr:samgr_proxy", + "safwk:system_ability_fwk", + "udmf:udmf_client", + ] + + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "${data_service_path}/service/udmf:udmf_server", + ] + + defines = [ + "private=public", + "protected=public", + ] +} + +ohos_unittest("UdmfServiceImplMockTest") { + module_out_path = module_output_path + sources = [ + "${data_service_path}/framework/feature/feature_system.cpp", + "udmf_service_impl_mock_test.cpp", + ] + + include_dirs = [ + "${data_service_path}/adapter/include/account", + "${data_service_path}/adapter/include/communicator", "${data_service_path}/framework/include", + "${data_service_path}/service/matrix/include", + "${data_service_path}/service/udmf/preprocess", + "${data_service_path}/service/udmf/store", + "${data_service_path}/service/udmf", + "${data_service_path}/service/udmf/permission", + "${data_service_path}/service/test/mock", ] cflags = [ @@ -1199,25 +1698,39 @@ ohos_unittest("UdmfServiceImplTest") { deps = [ "${data_service_path}/service:distributeddatasvc", "${data_service_path}/service/udmf:udmf_server", + "mock:distributeddata_mock_static", ] external_deps = [ "ability_runtime:uri_permission_mgr", "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "access_token:libtoken_setproc", "app_file_service:remote_file_share_native", "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", "c_utils:utils", + "dataclassification:data_transit_mgr", "device_manager:devicemanagersdk", + "googletest:gmock_main", "googletest:gtest_main", "hilog:libhilog", + "hisysevent:libhisysevent", "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddb", + "kv_store:distributeddata_mgr", "relational_store:native_rdb", "samgr:samgr_proxy", + "safwk:system_ability_fwk", "udmf:udmf_client", ] + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } } ohos_unittest("UdmfServiceStubTest") { @@ -1225,9 +1738,12 @@ ohos_unittest("UdmfServiceStubTest") { sources = [ "udmf_service_stub_test.cpp" ] include_dirs = [ + "${data_service_path}/service/matrix/include", + "${data_service_path}/service/udmf/preprocess", "${data_service_path}/service/udmf/store", "${data_service_path}/service/udmf", "${data_service_path}/framework/include", + "${data_service_path}/service/udmf/permission", ] cflags = [ @@ -1236,6 +1752,7 @@ ohos_unittest("UdmfServiceStubTest") { ] deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", "${data_service_path}/service/udmf:udmf_server", ] @@ -1268,6 +1785,7 @@ ohos_unittest("UdmfServiceStubMockTest") { "${data_service_path}/framework/feature/feature_system.cpp", "${data_service_path}/framework/metadata/appid_meta_data.cpp", "${data_service_path}/framework/metadata/auto_launch_meta_data.cpp", + "${data_service_path}/framework/metadata/capability_meta_data.cpp", "${data_service_path}/framework/metadata/capability_range.cpp", "${data_service_path}/framework/metadata/meta_data_manager.cpp", "${data_service_path}/framework/metadata/secret_key_meta_data.cpp", @@ -1286,8 +1804,8 @@ ohos_unittest("UdmfServiceStubMockTest") { "${data_service_path}/service/udmf/permission/uri_permission_manager.cpp", "${data_service_path}/service/udmf/preprocess/data_handler.cpp", "${data_service_path}/service/udmf/preprocess/preprocess_utils.cpp", + "${data_service_path}/service/udmf/preprocess/udmf_notifier_proxy.cpp", "${data_service_path}/service/udmf/store/runtime_store.cpp", - "${data_service_path}/service/udmf/store/store_account_observer.cpp", "${data_service_path}/service/udmf/store/store_cache.cpp", "${data_service_path}/service/udmf/udmf_service_impl.cpp", "${data_service_path}/service/udmf/udmf_service_stub.cpp", @@ -1295,6 +1813,7 @@ ohos_unittest("UdmfServiceStubMockTest") { ] include_dirs = [ + "${data_service_path}/service/matrix/include", "${data_service_path}/service/udmf/store", "${data_service_path}/service/udmf", "${data_service_path}/framework/include", @@ -1326,6 +1845,7 @@ ohos_unittest("UdmfServiceStubMockTest") { "bundle_framework:appexecfwk_core", "c_utils:utils", "device_manager:devicemanagersdk", + "dfs_service:distributed_file_daemon_kit_inner", "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", @@ -1340,6 +1860,96 @@ ohos_unittest("UdmfServiceStubMockTest") { ] } +ohos_unittest("UdmfPreProcessUtilsTest") { + module_out_path = module_output_path + sources = [ "udmf_preprocess_utils_test.cpp" ] + + include_dirs = [ + "${data_service_path}/service/udmf/permission", + "${data_service_path}/service/udmf/preprocess", + ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + + deps = [ + "${data_service_path}/service:distributeddatasvc", + "${data_service_path}/service/udmf:udmf_server", + ] + + external_deps = [ + "ability_runtime:uri_permission_mgr", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "device_manager:devicemanagersdk", + "googletest:gtest_main", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "relational_store:native_rdb", + "udmf:udmf_client", + ] +} + +ohos_unittest("UdmfPreProcessUtilsMockTest") { + module_out_path = module_output_path + sources = [ + "${data_service_path}/service/test/mock/access_token_mock.cpp", + "${data_service_path}/service/udmf/preprocess/preprocess_utils.cpp", + "udmf_preprocess_utils_mock_test.cpp", + ] + + include_dirs = [ + "${data_service_path}/service/matrix/include", + "${data_service_path}/service/udmf/preprocess", + "${data_service_path}/service/test/mock", + "${data_service_path}/service/udmf/store", + "${data_service_path}/framework/include/account", + "${data_service_path}/adapter/include/communicator", + ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + + deps = [ + "${data_service_path}/service:distributeddatasvc", + "mock:distributeddata_mock_static", + ] + + external_deps = [ + "ability_runtime:uri_permission_mgr", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "access_token:libtokenid_sdk", + "app_file_service:remote_file_share_native", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "device_manager:devicemanagersdk", + "dfs_service:distributed_file_daemon_kit_inner", + "googletest:gmock_main", + "googletest:gtest_main", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "hilog:libhilog", + "ipc:ipc_single", + "kv_store:datamgr_common", + "samgr:samgr_proxy", + "udmf:udmf_client", + ] +} + ohos_unittest("UdmfCheckerManagerTest") { module_out_path = module_output_path sources = [ @@ -1524,11 +2134,14 @@ ohos_unittest("BootStrapMockTest") { module_out_path = module_output_path sources = [ "${data_service_path}/service/bootstrap/src/bootstrap.cpp", + "${data_service_path}/service/config/src/model/app_access_check_config.cpp", "${data_service_path}/service/config/src/model/app_id_mapping_config.cpp", "${data_service_path}/service/config/src/model/backup_config.cpp", "${data_service_path}/service/config/src/model/checker_config.cpp", "${data_service_path}/service/config/src/model/cloud_config.cpp", "${data_service_path}/service/config/src/model/component_config.cpp", + "${data_service_path}/service/config/src/model/datashare_config.cpp", + "${data_service_path}/service/config/src/model/device_sync_app_white_list_config.cpp", "${data_service_path}/service/config/src/model/directory_config.cpp", "${data_service_path}/service/config/src/model/global_config.cpp", "${data_service_path}/service/config/src/model/network_config.cpp", @@ -1547,8 +2160,9 @@ ohos_unittest("BootStrapMockTest") { deps = [ "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/backup:distributeddata_backup", - "../../framework:distributeddatasvcfwk", ] cflags = [ @@ -1690,7 +2304,6 @@ ohos_unittest("UpgradeMockTest") { "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/bootstrap:distributeddata_bootstrap", - "${data_service_path}/service/crypto:distributeddata_crypto", "${data_service_path}/service/matrix:distributeddata_matrix", "${data_service_path}/service/rdb:distributeddata_rdb", "${data_service_path}/service/test/mock:distributeddata_mock_static", @@ -1787,6 +2400,7 @@ ohos_unittest("BackupManagerServiceTest") { "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", "kv_store:distributeddb", + "safwk:system_ability_fwk", ] deps = [ @@ -1798,6 +2412,93 @@ ohos_unittest("BackupManagerServiceTest") { ] } +ohos_unittest("UdmfServiceImplDbCorruptionMockTest") { + module_out_path = module_output_path + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "${datamgr_service_path}/cfi_blocklist.txt" + } + sources = [ + "${data_service_path}/app/src/kvstore_meta_manager.cpp", + "${data_service_path}/service/udmf/lifecycle/clean_on_startup.cpp", + "${data_service_path}/service/udmf/lifecycle/clean_on_timeout.cpp", + "${data_service_path}/service/udmf/lifecycle/lifecycle_manager.cpp", + "${data_service_path}/service/udmf/lifecycle/lifecycle_policy.cpp", + "${data_service_path}/service/udmf/permission/checker_manager.cpp", + "${data_service_path}/service/udmf/permission/data_checker.cpp", + "${data_service_path}/service/udmf/permission/uri_permission_manager.cpp", + "${data_service_path}/service/udmf/preprocess/data_handler.cpp", + "${data_service_path}/service/udmf/preprocess/udmf_notifier_proxy.cpp", + "${data_service_path}/service/udmf/store/runtime_store.cpp", + "${data_service_path}/service/udmf/store/store_cache.cpp", + "${data_service_path}/service/udmf/udmf_service_impl.cpp", + "${data_service_path}/service/udmf/udmf_service_stub.cpp", + "mock/kv_store_nb_delegate_corruption_mock.cpp", + "mock/preprocess_utils_mock.cpp", + "udmf_db_corruption_mock_test.cpp", + ] + + include_dirs = [ + "${data_service_path}/adapter/include/account", + "${data_service_path}/adapter/include/communicator", + "${data_service_path}/app/src", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/matrix/include", + "${data_service_path}/service/udmf", + "${data_service_path}/service/udmf/store", + "${data_service_path}/service/udmf/preprocess", + "${data_service_path}/service/udmf/permission", + "${data_service_path}/service/test/mock", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "ability_base:zuri", + "ability_runtime:uri_permission_mgr", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "access_token:libtoken_setproc", + "access_token:libtokenid_sdk", + "app_file_service:remote_file_share_native", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "dataclassification:data_transit_mgr", + "device_manager:devicemanagersdk", + "dfs_service:distributed_file_daemon_kit_inner", + "dsoftbus:softbus_client", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "openssl:libcrypto_shared", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + "udmf:udmf_client", + ] + + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + ] + + defines = [ + "private=public", + "protected=public", + ] +} + ############################################################################### group("unittest") { testonly = true @@ -1811,6 +2512,7 @@ group("unittest") { if (datamgr_service_cloud) { deps += [ ":CloudDataTest", + ":CloudDataMockTest", ":CloudServiceImplTest", ":CloudTest", "ohos_test:copy_ohos_test", @@ -1821,8 +2523,12 @@ group("unittest") { if (datamgr_service_udmf) { deps += [ ":UdmfCheckerManagerTest", + ":UdmfPreProcessUtilsMockTest", + ":UdmfPreProcessUtilsTest", ":UdmfRunTimeStoreTest", + ":UdmfServiceImplMockTest", ":UdmfServiceImplTest", + ":UdmfServiceImplDbCorruptionMockTest", ":UdmfServiceStubMockTest", ":UdmfServiceStubTest", ] @@ -1835,12 +2541,15 @@ group("unittest") { ":ObjectDmsHandlerTest", ":ObjectManagerTest", ":ObjectSnapshotTest", + ":ObjectManagerMockTest", ] } if (datamgr_service_rdb) { deps += [ ":RdbResultSetImplTest", + ":RdbServiceImplTest", + ":RdbServiceImplTokenTest", ":RdbServiceTest", ] } @@ -1852,6 +2561,7 @@ group("unittest") { ":KVDBGeneralStoreAbnormalTest", ":KVDBGeneralStoreTest", ":KvdbServiceImplTest", + ":KvdbServicePasswordTest", ":QueryHelperUnitTest", ":UpgradeMockTest", ":UserDelegateMockTest", @@ -1859,7 +2569,10 @@ group("unittest") { } if (datamgr_service_data_share) { - deps += [ ":DataShareServiceImplTest" ] + deps += [ + ":DataShareServiceImplTest", + ":DataShareServiceImplMockTest", + ] } deps += [ diff --git a/datamgr_service/services/distributeddataservice/service/test/auth_delegate_mock_test.cpp b/datamgr_service/services/distributeddataservice/service/test/auth_delegate_mock_test.cpp index 1d6c08d7..5b1b206b 100644 --- a/datamgr_service/services/distributeddataservice/service/test/auth_delegate_mock_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/auth_delegate_mock_test.cpp @@ -91,7 +91,7 @@ HWTEST_F(AuthDelegateMockTest, CheckAccess001, testing::ext::TestSize.Level0) EXPECT_CALL(*userDelegateMock, GetRemoteUserStatus(_)).WillOnce(Return(peerUsers)); EXPECT_CALL(*devMgrAdapterMock, IsOHOSType(_)).WillOnce(Return(false)); auto result = authHandler->CheckAccess(localUserId, peerUserId, peerDevId, aclParams); - EXPECT_TRUE(result.first); + EXPECT_FALSE(result.first); } /** diff --git a/datamgr_service/services/distributeddataservice/service/test/backup_manager_service_test.cpp b/datamgr_service/services/distributeddataservice/service/test/backup_manager_service_test.cpp index fac7bdbc..654adadf 100644 --- a/datamgr_service/services/distributeddataservice/service/test/backup_manager_service_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/backup_manager_service_test.cpp @@ -20,9 +20,11 @@ #include "backup_manager.h" #include "backuprule/backup_rule_manager.h" #include "bootstrap.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter.h" #include "directory/directory_manager.h" +#include "file_ex.h" +#include "ipc_skeleton.h" #include "log_print.h" #include "metadata/meta_data_manager.h" #include "kvstore_meta_manager.h" @@ -33,10 +35,17 @@ using namespace std; using namespace OHOS::DistributedData; namespace OHOS::Test { namespace DistributedDataTest { +static constexpr int32_t LOOP_NUM = 2; static constexpr uint32_t SKEY_SIZE = 32; static constexpr int MICROSEC_TO_SEC_TEST = 1000; static constexpr const char *TEST_BACKUP_BUNDLE = "test_backup_bundleName"; static constexpr const char *TEST_BACKUP_STOREID = "test_backup_storeId"; +static constexpr const char *BASE_DIR = "/data/service/el1/public/database/test_backup_bundleName"; +static constexpr const char *DATA_DIR = "/data/service/el1/public/database/test_backup_bundleName/rdb"; +static constexpr const char *BACKUP_DIR = "/data/service/el1/public/database/test_backup_bundleName/rdb/backup"; +static constexpr const char *STORE_DIR = + "/data/service/el1/public/database/test_backup_bundleName/rdb/backup/test_backup_storeId"; +static constexpr const char *AUTO_BACKUP_NAME = "/autoBackup.bak"; class BackupManagerServiceTest : public testing::Test { public: class TestRule : public BackupRuleManager::BackupRule { @@ -57,10 +66,17 @@ public: void SetUp(); void TearDown(); static std::vector Random(uint32_t len); - void InitMetaData(); - StoreMetaData metaData_; + static void InitMetaData(); + static void Exporter(const StoreMetaData &meta, const std::string &backupPath, bool &result); + static void ConfigExport(bool flag); + + static StoreMetaData metaData_; + static bool isExport_; }; +StoreMetaData BackupManagerServiceTest::metaData_; +bool BackupManagerServiceTest::isExport_ = false; + void BackupManagerServiceTest::SetUpTestCase(void) { auto executors = std::make_shared(1, 0); @@ -71,6 +87,9 @@ void BackupManagerServiceTest::SetUpTestCase(void) DistributedKv::KvStoreMetaManager::GetInstance().BindExecutor(executors); DistributedKv::KvStoreMetaManager::GetInstance().InitMetaParameter(); DistributedKv::KvStoreMetaManager::GetInstance().InitMetaListener(); + InitMetaData(); + MetaDataManager::GetInstance().DelMeta(metaData_.GetSecretKey(), true); + MetaDataManager::GetInstance().DelMeta(metaData_.GetBackupSecretKey(), true); } void BackupManagerServiceTest::TearDownTestCase() @@ -94,10 +113,11 @@ void BackupManagerServiceTest::InitMetaData() metaData_.area = OHOS::DistributedKv::EL1; metaData_.instanceId = 0; metaData_.isAutoSync = true; - metaData_.storeType = DistributedKv::KvStoreType::SINGLE_VERSION; + metaData_.storeType = StoreMetaData::StoreType::STORE_KV_BEGIN; metaData_.storeId = TEST_BACKUP_STOREID; metaData_.dataDir = "/data/service/el1/public/database/" + std::string(TEST_BACKUP_BUNDLE) + "/kvdb"; metaData_.securityLevel = OHOS::DistributedKv::SecurityLevel::S2; + metaData_.tokenId = IPCSkeleton::GetSelfTokenID(); } std::vector BackupManagerServiceTest::Random(uint32_t len) @@ -111,6 +131,21 @@ std::vector BackupManagerServiceTest::Random(uint32_t len) return key; } +void BackupManagerServiceTest::ConfigExport(bool flag) +{ + isExport_ = flag; +} + +void BackupManagerServiceTest::Exporter(const StoreMetaData &meta, const std::string &backupPath, bool &result) +{ + (void)meta; + result = isExport_; + if (isExport_) { + std::vector content(TEST_BACKUP_BUNDLE, TEST_BACKUP_BUNDLE + std::strlen(TEST_BACKUP_BUNDLE)); + result = SaveBufferToFile(backupPath, content); + } +} + /** * @tc.name: Init * @tc.desc: Init testing exception branching scenarios. @@ -297,18 +332,134 @@ HWTEST_F(BackupManagerServiceTest, GetClearType002, TestSize.Level1) } /** -* @tc.name: GetPassWord -* @tc.desc: GetPassWord testing exception branching scenarios. +* @tc.name: GetPassWordTest001 +* @tc.desc: get password fail with exception branch * @tc.type: FUNC -* @tc.require: -* @tc.author: suoqilong */ -HWTEST_F(BackupManagerServiceTest, GetPassWord, TestSize.Level1) +HWTEST_F(BackupManagerServiceTest, GetPassWordTest001, TestSize.Level1) { StoreMetaData meta; - std::vector password; - bool status = BackupManager::GetInstance().GetPassWord(meta, password); - EXPECT_FALSE(status); + auto password = BackupManager::GetInstance().GetPassWord(meta); + ASSERT_TRUE(password.empty()); + + SecretKeyMetaData secretKey; + secretKey.area = metaData_.area; + secretKey.storeType = metaData_.storeType; + auto result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetBackupSecretKey(), secretKey, true); + ASSERT_TRUE(result); + password = BackupManager::GetInstance().GetPassWord(metaData_); + ASSERT_TRUE(password.empty()); + + auto key = Random(SKEY_SIZE); + ASSERT_FALSE(key.empty()); + secretKey.sKey = key; + secretKey.nonce = key; + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetBackupSecretKey(), secretKey, true); + ASSERT_TRUE(result); + password = BackupManager::GetInstance().GetPassWord(metaData_); + ASSERT_TRUE(password.empty()); + + MetaDataManager::GetInstance().DelMeta(metaData_.GetBackupSecretKey(), true); +} + +/** +* @tc.name: GetPassWordTest002 +* @tc.desc: get backup password success +* @tc.type: FUNC +*/ +HWTEST_F(BackupManagerServiceTest, GetPassWordTest002, TestSize.Level1) +{ + auto key = Random(SKEY_SIZE); + ASSERT_FALSE(key.empty()); + CryptoManager::CryptoParams encryptParams; + auto encryptKey = CryptoManager::GetInstance().Encrypt(key, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + + SecretKeyMetaData secretKey; + secretKey.area = encryptParams.area; + secretKey.storeType = metaData_.storeType; + secretKey.sKey = encryptKey; + secretKey.nonce = encryptParams.nonce; + auto result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetBackupSecretKey(), secretKey, true); + ASSERT_TRUE(result); + + for (int32_t index = 0; index < LOOP_NUM; ++index) { + auto password = BackupManager::GetInstance().GetPassWord(metaData_); + ASSERT_FALSE(password.empty()); + ASSERT_EQ(password.size(), key.size()); + for (size_t i = 0; i < key.size(); ++i) { + ASSERT_EQ(password[i], key[i]); + } + } + + MetaDataManager::GetInstance().DelMeta(metaData_.GetBackupSecretKey(), true); +} + +/** +* @tc.name: DoBackupTest001 +* @tc.desc: do backup with every condition +* @tc.type: FUNC +*/ +HWTEST_F(BackupManagerServiceTest, DoBackupTest001, TestSize.Level1) +{ + metaData_.storeType = StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN; + mkdir(BASE_DIR, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + mkdir(DATA_DIR, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + mkdir(BACKUP_DIR, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + mkdir(STORE_DIR, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + + auto backupPath = DirectoryManager::GetInstance().GetStoreBackupPath(metaData_); + ASSERT_EQ(backupPath, STORE_DIR); + + std::string backupFilePath = backupPath + AUTO_BACKUP_NAME; + + std::shared_ptr testManager = std::make_shared(); + testManager->DoBackup(metaData_); + ASSERT_NE(access(backupFilePath.c_str(), F_OK), 0); + + testManager->RegisterExporter(metaData_.storeType, Exporter); + ConfigExport(false); + testManager->DoBackup(metaData_); + ASSERT_NE(access(backupFilePath.c_str(), F_OK), 0); + + ConfigExport(true); + metaData_.isEncrypt = false; + testManager->DoBackup(metaData_); + ASSERT_EQ(access(backupFilePath.c_str(), F_OK), 0); + (void)remove(backupFilePath.c_str()); + + MetaDataManager::GetInstance().DelMeta(metaData_.GetSecretKey(), true); + SecretKeyMetaData secretKey; + auto result = MetaDataManager::GetInstance().LoadMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_FALSE(result); + + metaData_.isEncrypt = true; + testManager->DoBackup(metaData_); + ASSERT_NE(access(backupFilePath.c_str(), F_OK), 0); + + SecretKeyMetaData backupSecretKey; + result = MetaDataManager::GetInstance().LoadMeta(metaData_.GetBackupSecretKey(), backupSecretKey, true); + ASSERT_FALSE(result); + + secretKey.area = metaData_.area; + secretKey.storeType = metaData_.storeType; + auto key = Random(SKEY_SIZE); + ASSERT_FALSE(key.empty()); + secretKey.sKey = key; + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_TRUE(result); + testManager->DoBackup(metaData_); + ASSERT_EQ(access(backupFilePath.c_str(), F_OK), 0); + result = MetaDataManager::GetInstance().LoadMeta(metaData_.GetBackupSecretKey(), backupSecretKey, true); + ASSERT_TRUE(result); + + MetaDataManager::GetInstance().DelMeta(metaData_.GetSecretKey(), true); + MetaDataManager::GetInstance().DelMeta(metaData_.GetBackupSecretKey(), true); + (void)remove(backupFilePath.c_str()); + (void)remove(STORE_DIR); + (void)remove(BACKUP_DIR); + (void)remove(DATA_DIR); + (void)remove(BASE_DIR); } /** diff --git a/datamgr_service/services/distributeddataservice/service/test/cloud_data_mock_test.cpp b/datamgr_service/services/distributeddataservice/service/test/cloud_data_mock_test.cpp new file mode 100644 index 00000000..5f7e68b9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/cloud_data_mock_test.cpp @@ -0,0 +1,403 @@ +/* +* 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. +*/ +#define LOG_TAG "CloudDataMockTest" + +#include +#include + +#include "cloud/cloud_server.h" +#include "cloud_service_impl.h" +#include "communicator/device_manager_adapter.h" +#include "device_matrix.h" +#include "eventcenter/event_center.h" +#include "ipc_skeleton.h" +#include "log_print.h" +#include "metadata/meta_data_manager.h" +#include "mock/access_token_mock.h" +#include "mock/account_delegate_mock.h" +#include "mock/db_store_mock.h" +#include "network_delegate_mock.h" + +using namespace testing::ext; +using namespace testing; +using namespace DistributedDB; +using namespace OHOS::DistributedData; +using namespace OHOS::Security::AccessToken; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; + +namespace OHOS::Test { +namespace DistributedDataTest { +static constexpr const char *TEST_CLOUD_BUNDLE = "test_cloud_bundleName"; +static constexpr const char *TEST_CLOUD_APPID = "test_cloud_appid"; +static constexpr const char *TEST_CLOUD_STORE = "test_cloud_store"; +static constexpr const char *TEST_CLOUD_ID = "test_cloud_id"; +static constexpr const char *TEST_CLOUD_DATABASE_ALIAS_1 = "test_cloud_database_alias_1"; +static constexpr const char *TEST_CLOUD_DATABASE_ALIAS_2 = "test_cloud_database_alias_2"; +static constexpr const char *TEST_CLOUD_PATH = "/data/app/el2/100/database/test_cloud_bundleName/entry/rdb/" + "test_cloud_store"; +static constexpr const int32_t TEST_TOKEN_FLAG_CALL_COUNT = 3; +class CloudDataMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static inline std::shared_ptr accTokenMock = nullptr; + static SchemaMeta schemaMeta_; + static std::shared_ptr cloudServiceImpl_; + +protected: + static void InitMetaData(); + static void InitSchemaMeta(); + static void InitCloudInfo(); + static std::shared_ptr dbStoreMock_; + static StoreMetaData metaData_; + static CloudInfo cloudInfo_; + static NetworkDelegateMock delegate_; + static inline AccountDelegateMock *accountDelegateMock = nullptr; +}; + +class CloudServerMock : public CloudServer { +public: + std::pair GetServerInfo(int32_t userId, bool needSpaceInfo) override; + std::pair GetAppSchema(int32_t userId, const std::string &bundleName) override; + virtual ~CloudServerMock() = default; + static constexpr uint64_t REMAINSPACE = 1000; + static constexpr uint64_t TATALSPACE = 2000; + static constexpr int32_t INVALID_USER_ID = -1; +}; + +std::pair CloudServerMock::GetServerInfo(int32_t userId, bool needSpaceInfo) +{ + CloudInfo cloudInfo; + cloudInfo.user = userId; + cloudInfo.id = TEST_CLOUD_ID; + cloudInfo.remainSpace = REMAINSPACE; + cloudInfo.totalSpace = TATALSPACE; + cloudInfo.enableCloud = true; + + CloudInfo::AppInfo appInfo; + appInfo.bundleName = TEST_CLOUD_BUNDLE; + appInfo.appId = TEST_CLOUD_APPID; + appInfo.version = 1; + appInfo.cloudSwitch = true; + + cloudInfo.apps[TEST_CLOUD_BUNDLE] = std::move(appInfo); + return { E_OK, cloudInfo }; +} + +std::pair CloudServerMock::GetAppSchema(int32_t userId, const std::string &bundleName) +{ + if (userId == INVALID_USER_ID) { + return { E_ERROR, CloudDataMockTest::schemaMeta_ }; + } + + if (bundleName.empty()) { + SchemaMeta schemaMeta; + return { E_OK, schemaMeta }; + } + return { E_OK, CloudDataMockTest::schemaMeta_ }; +} + +std::shared_ptr CloudDataMockTest::dbStoreMock_ = std::make_shared(); +SchemaMeta CloudDataMockTest::schemaMeta_; +StoreMetaData CloudDataMockTest::metaData_; +CloudInfo CloudDataMockTest::cloudInfo_; +std::shared_ptr CloudDataMockTest::cloudServiceImpl_ = + std::make_shared(); +NetworkDelegateMock CloudDataMockTest::delegate_; + +void CloudDataMockTest::InitMetaData() +{ + metaData_.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData_.appId = TEST_CLOUD_APPID; + metaData_.bundleName = TEST_CLOUD_BUNDLE; + metaData_.tokenId = OHOS::IPCSkeleton::GetCallingTokenID(); + metaData_.user = std::to_string(AccountDelegate::GetInstance()->GetUserByToken(metaData_.tokenId)); + metaData_.area = OHOS::DistributedKv::EL1; + metaData_.instanceId = 0; + metaData_.isAutoSync = true; + metaData_.storeType = DistributedRdb::RDB_DEVICE_COLLABORATION; + metaData_.storeId = TEST_CLOUD_STORE; + metaData_.dataDir = TEST_CLOUD_PATH; + PolicyValue value; + value.type = OHOS::DistributedKv::PolicyType::IMMEDIATE_SYNC_ON_ONLINE; +} + +void CloudDataMockTest::InitSchemaMeta() +{ + SchemaMeta::Field field1; + field1.colName = "test_cloud_field_name1"; + field1.alias = "test_cloud_field_alias1"; + SchemaMeta::Field field2; + field2.colName = "test_cloud_field_name2"; + field2.alias = "test_cloud_field_alias2"; + + SchemaMeta::Table table; + table.name = "test_cloud_table_name"; + table.alias = "test_cloud_table_alias"; + table.fields.emplace_back(field1); + table.fields.emplace_back(field2); + + SchemaMeta::Database database; + database.name = TEST_CLOUD_STORE; + database.alias = TEST_CLOUD_DATABASE_ALIAS_1; + database.tables.emplace_back(table); + + schemaMeta_.version = 1; + schemaMeta_.bundleName = TEST_CLOUD_BUNDLE; + schemaMeta_.databases.emplace_back(database); + database.alias = TEST_CLOUD_DATABASE_ALIAS_2; + schemaMeta_.databases.emplace_back(database); + schemaMeta_.e2eeEnable = false; +} + +void CloudDataMockTest::InitCloudInfo() +{ + cloudInfo_.user = AccountDelegate::GetInstance()->GetUserByToken(IPCSkeleton::GetCallingTokenID()); + cloudInfo_.id = TEST_CLOUD_ID; + cloudInfo_.enableCloud = true; + + CloudInfo::AppInfo appInfo; + appInfo.bundleName = TEST_CLOUD_BUNDLE; + appInfo.appId = TEST_CLOUD_APPID; + appInfo.version = 1; + appInfo.cloudSwitch = true; + + cloudInfo_.apps[TEST_CLOUD_BUNDLE] = std::move(appInfo); +} + +void CloudDataMockTest::SetUpTestCase(void) +{ + accountDelegateMock = new (std::nothrow) AccountDelegateMock(); + if (accountDelegateMock != nullptr) { + AccountDelegate::instance_ = nullptr; + AccountDelegate::RegisterAccountInstance(accountDelegateMock); + } + // 2 means that the GetUserByToken interface will be called twice + EXPECT_CALL(*accountDelegateMock, GetUserByToken(_)).Times(2).WillRepeatedly(Return(0)); + + accTokenMock = std::make_shared(); + BAccessTokenKit::accessTokenkit = accTokenMock; + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(_)) + .Times(TEST_TOKEN_FLAG_CALL_COUNT) + .WillRepeatedly(Return(ATokenTypeEnum::TOKEN_HAP)); + + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + MetaDataManager::GetInstance().SetSyncer( + [](const auto &, auto) { DeviceMatrix::GetInstance().OnChanged(DeviceMatrix::META_STORE_MASK); }); + + auto cloudServerMock = new CloudServerMock(); + CloudServer::RegisterCloudInstance(cloudServerMock); + size_t max = 12; + size_t min = 5; + + auto executor = std::make_shared(max, min); + cloudServiceImpl_->OnBind( + { "CloudDataMockTest", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + auto dmExecutor = std::make_shared(max, min); + DeviceManagerAdapter::GetInstance().Init(dmExecutor); + NetworkDelegate::RegisterNetworkInstance(&delegate_); + delegate_.isNetworkAvailable_ = true; + InitCloudInfo(); + InitMetaData(); + InitSchemaMeta(); +} + +void CloudDataMockTest::TearDownTestCase() +{ + if (accountDelegateMock != nullptr) { + delete accountDelegateMock; + accountDelegateMock = nullptr; + } + accTokenMock = nullptr; + BAccessTokenKit::accessTokenkit = nullptr; +} + +void CloudDataMockTest::SetUp() +{ + MetaDataManager::GetInstance().SaveMeta(cloudInfo_.GetKey(), cloudInfo_, true); + MetaDataManager::GetInstance().SaveMeta(metaData_.GetKey(), metaData_, true); + StoreMetaMapping storeMetaMapping(metaData_); + MetaDataManager::GetInstance().SaveMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); + MetaDataManager::GetInstance().SaveMeta(cloudInfo_.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta_, true); +} + +void CloudDataMockTest::TearDown() +{ + EventCenter::GetInstance().Unsubscribe(CloudEvent::LOCAL_CHANGE); + MetaDataManager::GetInstance().DelMeta(cloudInfo_.GetKey(), true); + MetaDataManager::GetInstance().DelMeta(metaData_.GetKey(), true); + StoreMetaMapping storeMetaMapping(metaData_); + MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true); + MetaDataManager::GetInstance().DelMeta(cloudInfo_.GetSchemaKey(TEST_CLOUD_BUNDLE), true); +} + +/** +* @tc.name: GetSchema001 +* @tc.desc: Test the scenario where the QueryUsers users not empty and return true in the GetSchema function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(CloudDataMockTest, GetSchema001, TestSize.Level1) +{ + EXPECT_CALL(*accountDelegateMock, GetUserByToken(_)).WillOnce(Return(0)); + auto cloudServerMock = std::make_shared(); + auto user = AccountDelegate::GetInstance()->GetUserByToken(OHOS::IPCSkeleton::GetCallingTokenID()); + auto [status, cloudInfo] = cloudServerMock->GetServerInfo(user, true); + ASSERT_TRUE(MetaDataManager::GetInstance().DelMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), true)); + SchemaMeta schemaMeta; + ASSERT_FALSE(MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true)); + std::vector users = { 0, 1 }; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(users), Return(true))); + EXPECT_CALL(*accountDelegateMock, IsVerified(_)).Times(1).WillOnce(DoAll(Return(true))); + DistributedData::StoreInfo storeInfo{ OHOS::IPCSkeleton::GetCallingTokenID(), TEST_CLOUD_BUNDLE, TEST_CLOUD_STORE, + 0 }; + auto event = std::make_unique(CloudEvent::GET_SCHEMA, storeInfo); + EventCenter::GetInstance().PostEvent(std::move(event)); + auto ret = MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true); + ASSERT_TRUE(ret); +} + +/** +* @tc.name: GetSchema002 +* @tc.desc: Test the scenario where the QueryUsers users empty in the GetSchema function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(CloudDataMockTest, GetSchema002, TestSize.Level1) +{ + EXPECT_CALL(*accountDelegateMock, GetUserByToken(_)).WillOnce(Return(0)); + auto cloudServerMock = std::make_shared(); + auto user = AccountDelegate::GetInstance()->GetUserByToken(OHOS::IPCSkeleton::GetCallingTokenID()); + auto [status, cloudInfo] = cloudServerMock->GetServerInfo(user, true); + ASSERT_TRUE(MetaDataManager::GetInstance().DelMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), true)); + SchemaMeta schemaMeta; + ASSERT_FALSE(MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true)); + + std::vector users; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)) + .Times(1) + .WillOnce( + DoAll(SetArgReferee<0>(users), Invoke([](std::vector &users) { users.clear(); }), Return(true))); + DistributedData::StoreInfo storeInfo{ OHOS::IPCSkeleton::GetCallingTokenID(), TEST_CLOUD_BUNDLE, TEST_CLOUD_STORE, + 0 }; + auto event = std::make_unique(CloudEvent::GET_SCHEMA, storeInfo); + EventCenter::GetInstance().PostEvent(std::move(event)); + auto ret = MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true); + ASSERT_FALSE(ret); +} + +/** +* @tc.name: GetSchema003 +* @tc.desc: Test the scenario where the QueryUsers return false in the GetSchema function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(CloudDataMockTest, GetSchema003, TestSize.Level1) +{ + EXPECT_CALL(*accountDelegateMock, GetUserByToken(_)).WillOnce(Return(0)); + auto cloudServerMock = std::make_shared(); + auto user = AccountDelegate::GetInstance()->GetUserByToken(OHOS::IPCSkeleton::GetCallingTokenID()); + auto [status, cloudInfo] = cloudServerMock->GetServerInfo(user, true); + ASSERT_TRUE(MetaDataManager::GetInstance().DelMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), true)); + SchemaMeta schemaMeta; + ASSERT_FALSE(MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true)); + + std::vector users; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(users), Return(false))); + DistributedData::StoreInfo storeInfo{ OHOS::IPCSkeleton::GetCallingTokenID(), TEST_CLOUD_BUNDLE, TEST_CLOUD_STORE, + 0 }; + auto event = std::make_unique(CloudEvent::GET_SCHEMA, storeInfo); + EventCenter::GetInstance().PostEvent(std::move(event)); + auto ret = MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true); + ASSERT_FALSE(ret); +} + +/** +* @tc.name: OnReadyTest_LoginAccount +* @tc.desc: Test OnReady function when IsLoginAccount is true or false +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataMockTest, OnReadyTest_LoginAccount, TestSize.Level0) +{ + ZLOGI("CloudDataMockTest OnReadyTest_LoginAccount start"); + std::string device = "test"; + EXPECT_CALL(*accountDelegateMock, QueryForegroundUsers(_)).WillRepeatedly(testing::Return(false)); + auto ret = cloudServiceImpl_->OnReady(device); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); + + EXPECT_CALL(*accountDelegateMock, IsLoginAccount()).Times(1).WillOnce(testing::Return(false)); + ret = cloudServiceImpl_->OnReady(DeviceManagerAdapter::CLOUD_DEVICE_UUID); + EXPECT_NE(ret, CloudData::CloudService::SUCCESS); + + EXPECT_CALL(*accountDelegateMock, IsLoginAccount()).Times(1).WillOnce(testing::Return(true)); + ret = cloudServiceImpl_->OnReady(DeviceManagerAdapter::CLOUD_DEVICE_UUID); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); + ZLOGI("CloudDataMockTest OnReadyTest_LoginAccount end"); +} + + +/** +* @tc.name: GetHapInfo001 +* @tc.desc: Test GetHapInfo function when GetTokenTypeFlag is not TOKEN_HAP. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataMockTest, GetHapInfo001, TestSize.Level1) +{ + ZLOGI("CloudDataMockTest GetHapInfo001 start"); + DistributedRdb::PredicatesMemo predicates; + predicates.tables_.push_back(TEST_CLOUD_BUNDLE); + std::vector columns; + CloudData::Participants participants; + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(_)) + .Times(1) + .WillOnce(Return(ATokenTypeEnum::TOKEN_NATIVE)); + auto [ret, _] = cloudServiceImpl_->AllocResourceAndShare(TEST_CLOUD_STORE, predicates, columns, participants); + EXPECT_EQ(ret, E_ERROR); + ZLOGI("CloudDataMockTest GetHapInfo001 end"); +} + +/** +* @tc.name: GetHapInfo002 +* @tc.desc: Test GetHapInfo function when GetTokenTypeFlag is TOKEN_HAP. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataMockTest, GetHapInfo002, TestSize.Level1) +{ + ZLOGI("CloudDataMockTest GetHapInfo002 start"); + DistributedRdb::PredicatesMemo predicates; + predicates.tables_.push_back(TEST_CLOUD_BUNDLE); + std::vector columns; + CloudData::Participants participants; + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(_)) + .Times(1) + .WillOnce(Return(ATokenTypeEnum::TOKEN_HAP)); + EXPECT_CALL(*accTokenMock, GetHapTokenInfo(_, _)) + .Times(1) + .WillOnce(Return(-1)); + auto [ret, _] = cloudServiceImpl_->AllocResourceAndShare(TEST_CLOUD_STORE, predicates, columns, participants); + EXPECT_EQ(ret, E_ERROR); + ZLOGI("CloudDataMockTest GetHapInfo002 end"); +} +} // namespace DistributedDataTest +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp b/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp index a41c6b73..7e299550 100644 --- a/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp @@ -105,6 +105,8 @@ static constexpr const char *PERMISSION_DISTRIBUTED_DATASYNC = "ohos.permission. static constexpr const char *PERMISSION_ACCESS_SERVICE_DM = "ohos.permission.ACCESS_SERVICE_DM"; static constexpr const char *PERMISSION_MANAGE_LOCAL_ACCOUNTS = "ohos.permission.MANAGE_LOCAL_ACCOUNTS"; static constexpr const char *PERMISSION_GET_BUNDLE_INFO = "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED"; +static constexpr const char *TEST_CLOUD_PATH = + "/data/app/el2/100/database/test_cloud_bundleName/entry/rdb/test_cloud_store"; PermissionDef GetPermissionDef(const std::string &permission) { PermissionDef def = { .permissionName = permission, @@ -211,6 +213,7 @@ void CloudDataTest::InitMetaData() metaData_.isAutoSync = true; metaData_.storeType = DistributedRdb::RDB_DEVICE_COLLABORATION; metaData_.storeId = TEST_CLOUD_STORE; + metaData_.dataDir = TEST_CLOUD_PATH; PolicyValue value; value.type = OHOS::DistributedKv::PolicyType::IMMEDIATE_SYNC_ON_ONLINE; } @@ -240,6 +243,7 @@ void CloudDataTest::InitSchemaMeta() schemaMeta_.databases.emplace_back(database); database.alias = TEST_CLOUD_DATABASE_ALIAS_2; schemaMeta_.databases.emplace_back(database); + schemaMeta_.e2eeEnable = false; } void CloudDataTest::InitCloudInfo() @@ -303,6 +307,8 @@ void CloudDataTest::SetUp() { MetaDataManager::GetInstance().SaveMeta(cloudInfo_.GetKey(), cloudInfo_, true); MetaDataManager::GetInstance().SaveMeta(metaData_.GetKey(), metaData_, true); + StoreMetaMapping storeMetaMapping(metaData_); + MetaDataManager::GetInstance().SaveMeta(storeMetaMapping.GetKey(), storeMetaMapping, true); MetaDataManager::GetInstance().SaveMeta(cloudInfo_.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta_, true); } @@ -311,6 +317,8 @@ void CloudDataTest::TearDown() EventCenter::GetInstance().Unsubscribe(CloudEvent::LOCAL_CHANGE); MetaDataManager::GetInstance().DelMeta(cloudInfo_.GetKey(), true); MetaDataManager::GetInstance().DelMeta(metaData_.GetKey(), true); + StoreMetaMapping storeMetaMapping(metaData_); + MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true); MetaDataManager::GetInstance().DelMeta(cloudInfo_.GetSchemaKey(TEST_CLOUD_BUNDLE), true); } @@ -321,7 +329,7 @@ void CloudDataTest::TearDown() * @tc.require: * @tc.author: ht */ -HWTEST_F(CloudDataTest, GetSchema, TestSize.Level0) +HWTEST_F(CloudDataTest, GetSchema, TestSize.Level1) { auto cloudServerMock = std::make_shared(); auto user = AccountDelegate::GetInstance()->GetUserByToken(OHOS::IPCSkeleton::GetCallingTokenID()); @@ -384,7 +392,7 @@ HWTEST_F(CloudDataTest, QueryStatistics002, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, QueryStatistics003, TestSize.Level0) +HWTEST_F(CloudDataTest, QueryStatistics003, TestSize.Level1) { // Construct the statisticInfo data auto creator = [](const StoreMetaData &metaData) -> GeneralStore* { @@ -420,7 +428,7 @@ HWTEST_F(CloudDataTest, QueryStatistics003, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, QueryStatistics004, TestSize.Level0) +HWTEST_F(CloudDataTest, QueryStatistics004, TestSize.Level1) { // Construct the statisticInfo data auto creator = [](const StoreMetaData &metaData) -> GeneralStore* { @@ -494,11 +502,13 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo003, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, QueryLastSyncInfo004, TestSize.Level0) +HWTEST_F(CloudDataTest, QueryLastSyncInfo004, TestSize.Level1) { auto ret = cloudServiceImpl_->DisableCloud(TEST_CLOUD_ID); EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); - cloudServiceImpl_->OnReady(DeviceManagerAdapter::CLOUD_DEVICE_UUID); + auto user = AccountDelegate::GetInstance()->GetUserByToken(OHOS::IPCSkeleton::GetCallingTokenID()); + cloudServiceImpl_->OnUserChange( + static_cast(AccountStatus::DEVICE_ACCOUNT_SWITCHED), std::to_string(user), "accountId"); sleep(1); @@ -518,7 +528,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo004, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, QueryLastSyncInfo005, TestSize.Level0) +HWTEST_F(CloudDataTest, QueryLastSyncInfo005, TestSize.Level1) { std::map switches; switches.emplace(TEST_CLOUD_ID, true); @@ -526,7 +536,9 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo005, TestSize.Level0) MetaDataManager::GetInstance().LoadMeta(cloudInfo_.GetKey(), info, true); info.apps[TEST_CLOUD_BUNDLE].cloudSwitch = false; MetaDataManager::GetInstance().SaveMeta(info.GetKey(), info, true); - cloudServiceImpl_->OnReady(DeviceManagerAdapter::CLOUD_DEVICE_UUID); + auto user = AccountDelegate::GetInstance()->GetUserByToken(OHOS::IPCSkeleton::GetCallingTokenID()); + cloudServiceImpl_->OnUserChange( + static_cast(AccountStatus::DEVICE_ACCOUNT_SWITCHED), std::to_string(user), "accountId"); sleep(1); auto [status, result] = @@ -580,7 +592,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo007, TestSize.Level0) lastSyncInfo.syncStatus = 1; MetaDataManager::GetInstance().SaveMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_1), lastSyncInfo, true); - + std::vector lastSyncInfos; MetaDataManager::GetInstance().LoadMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_1), lastSyncInfos, true); @@ -626,7 +638,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo008, TestSize.Level0) lastSyncInfo1.code = 0; MetaDataManager::GetInstance().SaveMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_2), lastSyncInfo1, true); - + std::vector lastSyncInfos; MetaDataManager::GetInstance().LoadMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, ""), lastSyncInfos, true); @@ -679,7 +691,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo009, TestSize.Level0) lastSyncInfo1.code = 0; MetaDataManager::GetInstance().SaveMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_2), lastSyncInfo1, true); - + std::vector lastSyncInfos; MetaDataManager::GetInstance().LoadMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, ""), lastSyncInfos, true); @@ -725,7 +737,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo010, TestSize.Level0) lastSyncInfo1.code = 0; MetaDataManager::GetInstance().SaveMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_2), lastSyncInfo1, true); - + CloudData::SyncManager sync; CloudData::SyncManager::SyncInfo info(user, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_1); auto [status, result] = sync.QueryLastSyncInfo({ { user, TEST_CLOUD_ID, TEST_CLOUD_BUNDLE, "1234"} }); @@ -739,7 +751,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo010, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, QueryLastSyncInfo011, TestSize.Level0) +HWTEST_F(CloudDataTest, QueryLastSyncInfo011, TestSize.Level1) { schemaMeta_.databases[1].name = TEST_CLOUD_STORE_1; MetaDataManager::GetInstance().SaveMeta(cloudInfo_.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta_, true); @@ -785,7 +797,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo012, TestSize.Level0) lastSyncInfo.syncStatus = 1; MetaDataManager::GetInstance().SaveMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_1), lastSyncInfo, true); - + std::vector lastSyncInfos; MetaDataManager::GetInstance().LoadMeta(CloudLastSyncInfo::GetKey(user, TEST_CLOUD_BUNDLE, TEST_CLOUD_DATABASE_ALIAS_1), lastSyncInfos, true); @@ -868,7 +880,7 @@ HWTEST_F(CloudDataTest, UpdateFinishSyncInfo, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, Share001, TestSize.Level0) +HWTEST_F(CloudDataTest, Share001, TestSize.Level1) { std::string sharingRes = ""; CloudData::Participants participants{}; @@ -883,7 +895,7 @@ HWTEST_F(CloudDataTest, Share001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, Unshare001, TestSize.Level0) +HWTEST_F(CloudDataTest, Unshare001, TestSize.Level1) { std::string sharingRes = ""; CloudData::Participants participants{}; @@ -898,7 +910,7 @@ HWTEST_F(CloudDataTest, Unshare001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, ChangePrivilege001, TestSize.Level0) +HWTEST_F(CloudDataTest, ChangePrivilege001, TestSize.Level1) { std::string sharingRes = ""; CloudData::Participants participants{}; @@ -913,7 +925,7 @@ HWTEST_F(CloudDataTest, ChangePrivilege001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, ChangeConfirmation001, TestSize.Level0) +HWTEST_F(CloudDataTest, ChangeConfirmation001, TestSize.Level1) { std::string sharingRes = ""; int32_t confirmation = 0; @@ -928,7 +940,7 @@ HWTEST_F(CloudDataTest, ChangeConfirmation001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, ConfirmInvitation001, TestSize.Level0) +HWTEST_F(CloudDataTest, ConfirmInvitation001, TestSize.Level1) { std::string sharingRes = ""; int32_t confirmation = 0; @@ -943,7 +955,7 @@ HWTEST_F(CloudDataTest, ConfirmInvitation001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, Exit001, TestSize.Level0) +HWTEST_F(CloudDataTest, Exit001, TestSize.Level1) { std::string sharingRes = ""; std::pair result; @@ -957,7 +969,7 @@ HWTEST_F(CloudDataTest, Exit001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, Query001, TestSize.Level0) +HWTEST_F(CloudDataTest, Query001, TestSize.Level1) { std::string sharingRes = ""; CloudData::QueryResults result; @@ -971,7 +983,7 @@ HWTEST_F(CloudDataTest, Query001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, QueryByInvitation001, TestSize.Level0) +HWTEST_F(CloudDataTest, QueryByInvitation001, TestSize.Level1) { std::string invitation = ""; CloudData::QueryResults result; @@ -1015,7 +1027,7 @@ HWTEST_F(CloudDataTest, AllocResourceAndShare001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, SetGlobalCloudStrategy001, TestSize.Level0) +HWTEST_F(CloudDataTest, SetGlobalCloudStrategy001, TestSize.Level1) { std::vector values; values.push_back(CloudData::NetWorkStrategy::WIFI); @@ -1033,7 +1045,7 @@ HWTEST_F(CloudDataTest, SetGlobalCloudStrategy001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, SetCloudStrategy001, TestSize.Level0) +HWTEST_F(CloudDataTest, SetCloudStrategy001, TestSize.Level1) { std::vector values; values.push_back(CloudData::NetWorkStrategy::WIFI); @@ -1045,6 +1057,126 @@ HWTEST_F(CloudDataTest, SetCloudStrategy001, TestSize.Level0) EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); } +/** +* @tc.name: CloudSync001 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync001, TestSize.Level0) +{ + int32_t syncMode = DistributedData::GeneralStore::NEARBY_BEGIN; + uint32_t seqNum = 10; + // invalid syncMode + auto ret = cloudServiceImpl_->CloudSync("bundleName", "storeId", { syncMode, seqNum }, nullptr); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); +} + +/** +* @tc.name: CloudSync002 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync002, TestSize.Level0) +{ + int32_t syncMode = DistributedData::GeneralStore::NEARBY_PULL_PUSH; + uint32_t seqNum = 10; + // invalid syncMode + auto ret = cloudServiceImpl_->CloudSync("bundleName", "storeId", { syncMode, seqNum }, nullptr); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); +} + +/** +* @tc.name: CloudSync003 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync003, TestSize.Level1) +{ + int32_t syncMode = DistributedData::GeneralStore::CLOUD_BEGIN; + uint32_t seqNum = 10; + auto ret = cloudServiceImpl_->CloudSync("bundleName", "storeId", { syncMode, seqNum }, nullptr); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: CloudSync004 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync004, TestSize.Level1) +{ + int32_t syncMode = DistributedData::GeneralStore::CLOUD_TIME_FIRST; + uint32_t seqNum = 10; + auto ret = cloudServiceImpl_->CloudSync("bundleName", "storeId", { syncMode, seqNum }, nullptr); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: CloudSync005 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync005, TestSize.Level1) +{ + int32_t syncMode = DistributedData::GeneralStore::CLOUD_NATIVE_FIRST; + uint32_t seqNum = 10; + auto ret = cloudServiceImpl_->CloudSync("bundleName", "storeId", { syncMode, seqNum }, nullptr); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: CloudSync006 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync006, TestSize.Level1) +{ + int32_t syncMode = DistributedData::GeneralStore::CLOUD_CLOUD_FIRST; + uint32_t seqNum = 10; + auto ret = cloudServiceImpl_->CloudSync("bundleName", "storeId", { syncMode, seqNum }, nullptr); + EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: CloudSync007 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync007, TestSize.Level0) +{ + int32_t syncMode = DistributedData::GeneralStore::CLOUD_END; + uint32_t seqNum = 10; + auto ret = cloudServiceImpl_->CloudSync("bundleName", "storeId", { syncMode, seqNum }, nullptr); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); + + CloudData::Details details{}; + uint32_t tokenId = 0; + cloudServiceImpl_->OnAsyncComplete(tokenId, seqNum, std::move(details)); +} + +/** +* @tc.name: InitNotifier001 +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, InitNotifier001, TestSize.Level0) +{ + sptr notifier = nullptr; + auto ret = cloudServiceImpl_->InitNotifier(notifier); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); + + ret = cloudServiceImpl_->InitNotifier(notifier); + EXPECT_EQ(ret, CloudData::CloudService::INVALID_ARGUMENT); +} + /** * @tc.name: Clean * @tc.desc: @@ -1148,7 +1280,7 @@ HWTEST_F(CloudDataTest, NotifyDataChange002, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, NotifyDataChange003, TestSize.Level0) +HWTEST_F(CloudDataTest, NotifyDataChange003, TestSize.Level1) { constexpr const int32_t userId = 100; constexpr const int32_t defaultUserId = 0; @@ -1167,21 +1299,6 @@ HWTEST_F(CloudDataTest, NotifyDataChange003, TestSize.Level0) EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); } -/** -* @tc.name: OnReady -* @tc.desc: -* @tc.type: FUNC -* @tc.require: - */ -HWTEST_F(CloudDataTest, OnReady001, TestSize.Level0) -{ - std::string device = "test"; - auto ret = cloudServiceImpl_->OnReady(device); - EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); - ret = cloudServiceImpl_->OnReady(DeviceManagerAdapter::CLOUD_DEVICE_UUID); - EXPECT_EQ(ret, CloudData::CloudService::SUCCESS); -} - /** * @tc.name: Offline * @tc.desc: @@ -1300,7 +1417,7 @@ HWTEST_F(CloudDataTest, EnableCloud, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnEnableCloud, TestSize.Level0) +HWTEST_F(CloudDataTest, OnEnableCloud, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1321,7 +1438,7 @@ HWTEST_F(CloudDataTest, OnEnableCloud, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnDisableCloud, TestSize.Level0) +HWTEST_F(CloudDataTest, OnDisableCloud, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1340,7 +1457,7 @@ HWTEST_F(CloudDataTest, OnDisableCloud, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnChangeAppSwitch, TestSize.Level0) +HWTEST_F(CloudDataTest, OnChangeAppSwitch, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1361,7 +1478,7 @@ HWTEST_F(CloudDataTest, OnChangeAppSwitch, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnClean, TestSize.Level0) +HWTEST_F(CloudDataTest, OnClean, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1382,7 +1499,7 @@ HWTEST_F(CloudDataTest, OnClean, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnNotifyDataChange, TestSize.Level0) +HWTEST_F(CloudDataTest, OnNotifyDataChange, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1402,7 +1519,7 @@ HWTEST_F(CloudDataTest, OnNotifyDataChange, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnNotifyChange, TestSize.Level0) +HWTEST_F(CloudDataTest, OnNotifyChange, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1424,7 +1541,7 @@ HWTEST_F(CloudDataTest, OnNotifyChange, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnQueryStatistics, TestSize.Level0) +HWTEST_F(CloudDataTest, OnQueryStatistics, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1445,7 +1562,7 @@ HWTEST_F(CloudDataTest, OnQueryStatistics, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnQueryLastSyncInfo, TestSize.Level0) +HWTEST_F(CloudDataTest, OnQueryLastSyncInfo, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1466,7 +1583,7 @@ HWTEST_F(CloudDataTest, OnQueryLastSyncInfo, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnSetGlobalCloudStrategy, TestSize.Level0) +HWTEST_F(CloudDataTest, OnSetGlobalCloudStrategy, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1488,7 +1605,7 @@ HWTEST_F(CloudDataTest, OnSetGlobalCloudStrategy, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnAllocResourceAndShare, TestSize.Level0) +HWTEST_F(CloudDataTest, OnAllocResourceAndShare, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1512,7 +1629,7 @@ HWTEST_F(CloudDataTest, OnAllocResourceAndShare, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnShare, TestSize.Level0) +HWTEST_F(CloudDataTest, OnShare, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1534,7 +1651,7 @@ HWTEST_F(CloudDataTest, OnShare, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnUnshare, TestSize.Level0) +HWTEST_F(CloudDataTest, OnUnshare, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1556,7 +1673,7 @@ HWTEST_F(CloudDataTest, OnUnshare, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnExit, TestSize.Level0) +HWTEST_F(CloudDataTest, OnExit, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1577,7 +1694,7 @@ HWTEST_F(CloudDataTest, OnExit, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnChangePrivilege, TestSize.Level0) +HWTEST_F(CloudDataTest, OnChangePrivilege, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1599,7 +1716,7 @@ HWTEST_F(CloudDataTest, OnChangePrivilege, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnQuery, TestSize.Level0) +HWTEST_F(CloudDataTest, OnQuery, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1620,7 +1737,7 @@ HWTEST_F(CloudDataTest, OnQuery, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnQueryByInvitation, TestSize.Level0) +HWTEST_F(CloudDataTest, OnQueryByInvitation, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1641,7 +1758,7 @@ HWTEST_F(CloudDataTest, OnQueryByInvitation, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnConfirmInvitation, TestSize.Level0) +HWTEST_F(CloudDataTest, OnConfirmInvitation, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1663,7 +1780,7 @@ HWTEST_F(CloudDataTest, OnConfirmInvitation, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, OnChangeConfirmation, TestSize.Level0) +HWTEST_F(CloudDataTest, OnChangeConfirmation, TestSize.Level1) { MessageParcel reply; MessageParcel data; @@ -1700,6 +1817,51 @@ HWTEST_F(CloudDataTest, OnSetCloudStrategy, TestSize.Level0) EXPECT_EQ(ret, ERR_NONE); } +/** +* @tc.name: OnCloudSync +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnCloudSync, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_CLOUD_SYNC, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + std::string bundleName = "bundleName"; + std::string storeId = "storeId"; + CloudData::CloudService::Option option; + option.syncMode = 4; + option.seqNum = 1; + ITypesUtil::Marshal(data, bundleName, storeId, option); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_CLOUD_SYNC, data, reply); + EXPECT_EQ(ret, ERR_NONE); +} + +/** +* @tc.name: OnInitNotifier +* @tc.desc: +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, OnInitNotifier, TestSize.Level0) +{ + MessageParcel reply; + MessageParcel data; + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_INIT_NOTIFIER, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); + data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); + std::string bundleName = "bundleName"; + sptr notifier = nullptr; + ITypesUtil::Marshal(data, bundleName, notifier); + ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_INIT_NOTIFIER, data, reply); + EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); +} + /** * @tc.name: SharingUtil001 * @tc.desc: @@ -1837,12 +1999,12 @@ HWTEST_F(CloudDataTest, GetPostEventTask, TestSize.Level0) } /** -* @tc.name: GetRetryer +* @tc.name: GetRetryer001 * @tc.desc: Test the input parameters of different interfaces * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, GetRetryer, TestSize.Level0) +HWTEST_F(CloudDataTest, GetRetryer001, TestSize.Level0) { int32_t user = 100; CloudData::SyncManager::SyncInfo info(user); @@ -1860,6 +2022,28 @@ HWTEST_F(CloudDataTest, GetRetryer, TestSize.Level0) EXPECT_TRUE(ret); } +/** +* @tc.name: GetRetryer002 +* @tc.desc: Test the executor_ is nullptr scenarios. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, GetRetryer002, TestSize.Level0) +{ + int32_t user = 100; + std::string prepareTraceId; + CloudData::SyncManager sync; + sync.executor_ = nullptr; + int32_t evtId = 100; + auto event = std::make_unique(evtId); + auto handler = sync.GetClientChangeHandler(); + handler(*event); + CloudData::SyncManager::Duration duration; + CloudData::SyncManager::SyncInfo info(user); + auto ret = sync.GetRetryer(0, info, user)(duration, E_CLOUD_DISABLED, E_CLOUD_DISABLED, prepareTraceId); + EXPECT_FALSE(ret); +} + /** * @tc.name: GetCallback * @tc.desc: Test the processing logic of different progress callbacks @@ -1982,13 +2166,79 @@ HWTEST_F(CloudDataTest, UpdateCloudInfoFromServer, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, GetCloudInfo, TestSize.Level0) +HWTEST_F(CloudDataTest, GetCloudInfo, TestSize.Level1) { MetaDataManager::GetInstance().DelMeta(cloudInfo_.GetKey(), true); auto ret = cloudServiceImpl_->GetCloudInfo(cloudInfo_.user); EXPECT_EQ(ret.first, CloudData::SUCCESS); } +/** +* @tc.name: UpdateSchemaFromServer_001 +* @tc.desc: Test get UpdateSchemaFromServer +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, UpdateSchemaFromServer_001, TestSize.Level1) +{ + auto status = cloudServiceImpl_->UpdateSchemaFromServer(cloudInfo_.user); + EXPECT_EQ(status, CloudData::SUCCESS); +} + +/** + * @tc.name: OnAppInstallTest + * @tc.desc: Test the OnAppInstallTest + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, OnAppInstallTest, TestSize.Level1) +{ + ZLOGI("CloudDataTest OnAppInstallTest start"); + ASSERT_NE(cloudServiceImpl_, nullptr); + ASSERT_NE(cloudServiceImpl_->factory_.staticActs_, nullptr); + int32_t index = 0; + auto status = cloudServiceImpl_->factory_.staticActs_->OnAppInstall(TEST_CLOUD_BUNDLE, cloudInfo_.user, index); + EXPECT_EQ(status, GeneralError::E_OK); +} + +/** + * @tc.name: OnAppUpdateTest + * @tc.desc: Test the OnAppUpdateTest + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, OnAppUpdateTest, TestSize.Level1) +{ + ZLOGI("CloudDataTest OnAppUpdateTest start"); + ASSERT_NE(cloudServiceImpl_, nullptr); + ASSERT_NE(cloudServiceImpl_->factory_.staticActs_, nullptr); + int32_t index = 0; + auto status = cloudServiceImpl_->factory_.staticActs_->OnAppUpdate(TEST_CLOUD_BUNDLE, cloudInfo_.user, index); + EXPECT_EQ(status, CloudData::CloudService::SUCCESS); +} + +/** +* @tc.name: UpdateE2eeEnableTest +* @tc.desc: Test the UpdateE2eeEnable +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(CloudDataTest, UpdateE2eeEnableTest, TestSize.Level1) +{ + SchemaMeta schemaMeta; + std::string schemaKey = CloudInfo::GetSchemaKey(cloudInfo_.user, TEST_CLOUD_BUNDLE, 0); + ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)); + EXPECT_EQ(schemaMeta.e2eeEnable, schemaMeta_.e2eeEnable); + + ASSERT_NE(cloudServiceImpl_, nullptr); + cloudServiceImpl_->UpdateE2eeEnable(schemaKey, false, TEST_CLOUD_BUNDLE); + ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)); + EXPECT_EQ(schemaMeta.e2eeEnable, schemaMeta_.e2eeEnable); + cloudServiceImpl_->UpdateE2eeEnable(schemaKey, true, TEST_CLOUD_BUNDLE); + ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)); + EXPECT_EQ(schemaMeta.e2eeEnable, true); +} + /** * @tc.name: SubTask * @tc.desc: Test the subtask execution logic @@ -2202,7 +2452,7 @@ HWTEST_F(CloudDataTest, OnAppUninstall, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, GetCloudInfo001, TestSize.Level0) +HWTEST_F(CloudDataTest, GetCloudInfo001, TestSize.Level1) { int32_t userId = 1000; auto [status, cloudInfo] = cloudServiceImpl_->GetCloudInfo(userId); @@ -2228,6 +2478,7 @@ HWTEST_F(CloudDataTest, PreShare, TestSize.Level0) info.bundleName = TEST_CLOUD_BUNDLE; info.storeName = TEST_CLOUD_BUNDLE; info.user = userId; + info.path = TEST_CLOUD_PATH; StoreMetaData meta(info); meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true); @@ -2425,7 +2676,7 @@ HWTEST_F(CloudDataTest, GetPriorityLevel001, TestSize.Level1) }); DistributedRdb::RdbServiceImpl rdbServiceImpl; DistributedRdb::RdbSyncerParam param{ .bundleName_ = TEST_CLOUD_BUNDLE, .storeName_ = TEST_CLOUD_STORE }; - DistributedRdb::RdbService::Option option{ .mode = GeneralStore::SyncMode::CLOUD_ClOUD_FIRST, .isAsync = true }; + DistributedRdb::RdbService::Option option{ .mode = GeneralStore::SyncMode::CLOUD_CLOUD_FIRST, .isAsync = true }; DistributedRdb::PredicatesMemo memo; memo.tables_ = { TEST_CLOUD_TABLE }; rdbServiceImpl.DoCloudSync(param, option, memo, nullptr); @@ -2469,7 +2720,7 @@ HWTEST_F(CloudDataTest, GetPriorityLevel003, TestSize.Level1) }); DistributedRdb::RdbServiceImpl rdbServiceImpl; DistributedRdb::RdbSyncerParam param{ .bundleName_ = TEST_CLOUD_BUNDLE, .storeName_ = TEST_CLOUD_STORE }; - DistributedRdb::RdbService::Option option{ .mode = GeneralStore::SyncMode::CLOUD_ClOUD_FIRST, .isAsync = true }; + DistributedRdb::RdbService::Option option{ .mode = GeneralStore::SyncMode::CLOUD_CLOUD_FIRST, .isAsync = true }; DistributedRdb::PredicatesMemo memo; rdbServiceImpl.DoCloudSync(param, option, memo, nullptr); } @@ -2490,7 +2741,7 @@ HWTEST_F(CloudDataTest, GetPriorityLevel004, TestSize.Level1) }); DistributedRdb::RdbServiceImpl rdbServiceImpl; DistributedRdb::RdbSyncerParam param{ .bundleName_ = TEST_CLOUD_BUNDLE, .storeName_ = TEST_CLOUD_STORE }; - DistributedRdb::RdbService::Option option{ .mode = GeneralStore::SyncMode::CLOUD_ClOUD_FIRST, + DistributedRdb::RdbService::Option option{ .mode = GeneralStore::SyncMode::CLOUD_CLOUD_FIRST, .seqNum = 0, .isAsync = true, .isAutoSync = true }; @@ -2504,10 +2755,10 @@ HWTEST_F(CloudDataTest, GetPriorityLevel004, TestSize.Level1) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, UpdateSchemaFromHap001, TestSize.Level0) +HWTEST_F(CloudDataTest, UpdateSchemaFromHap001, TestSize.Level1) { ASSERT_NE(cloudServiceImpl_, nullptr); - CloudData::CloudServiceImpl::HapInfo info = { .user = -1, .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE,}; + CloudData::CloudServiceImpl::HapInfo info = { .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE, .user = -1 }; auto ret = cloudServiceImpl_->UpdateSchemaFromHap(info); EXPECT_EQ(ret, Status::ERROR); } @@ -2518,10 +2769,10 @@ HWTEST_F(CloudDataTest, UpdateSchemaFromHap001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, UpdateSchemaFromHap002, TestSize.Level0) +HWTEST_F(CloudDataTest, UpdateSchemaFromHap002, TestSize.Level1) { ASSERT_NE(cloudServiceImpl_, nullptr); - CloudData::CloudServiceImpl::HapInfo info = { .user = cloudInfo_.user, .instIndex = 0, .bundleName = "", }; + CloudData::CloudServiceImpl::HapInfo info = { .instIndex = 0, .bundleName = "", .user = cloudInfo_.user }; auto ret = cloudServiceImpl_->UpdateSchemaFromHap(info); EXPECT_EQ(ret, Status::ERROR); } @@ -2532,11 +2783,11 @@ HWTEST_F(CloudDataTest, UpdateSchemaFromHap002, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, UpdateSchemaFromHap003, TestSize.Level0) +HWTEST_F(CloudDataTest, UpdateSchemaFromHap003, TestSize.Level1) { ASSERT_NE(cloudServiceImpl_, nullptr); CloudData::CloudServiceImpl::HapInfo info = { - .user = cloudInfo_.user, .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE, + .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE, .user = cloudInfo_.user }; auto ret = cloudServiceImpl_->UpdateSchemaFromHap(info); EXPECT_EQ(ret, Status::SUCCESS); @@ -2552,8 +2803,9 @@ HWTEST_F(CloudDataTest, UpdateSchemaFromHap003, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, UpdateSchemaFromHap004, TestSize.Level0) +HWTEST_F(CloudDataTest, UpdateSchemaFromHap004, TestSize.Level1) { + ZLOGI("CloudServiceImplTest UpdateSchemaFromHap004 start"); ASSERT_NE(cloudServiceImpl_, nullptr); CloudInfo::AppInfo exampleAppInfo; exampleAppInfo.bundleName = COM_EXAMPLE_TEST_CLOUD; @@ -2565,7 +2817,7 @@ HWTEST_F(CloudDataTest, UpdateSchemaFromHap004, TestSize.Level0) cloudInfo.apps[COM_EXAMPLE_TEST_CLOUD] = std::move(exampleAppInfo); MetaDataManager::GetInstance().SaveMeta(cloudInfo_.GetKey(), cloudInfo, true); CloudData::CloudServiceImpl::HapInfo info = { - .user = cloudInfo_.user, .instIndex = 0, .bundleName = COM_EXAMPLE_TEST_CLOUD, + .instIndex = 0, .bundleName = COM_EXAMPLE_TEST_CLOUD, .user = cloudInfo_.user }; auto ret = cloudServiceImpl_->UpdateSchemaFromHap(info); EXPECT_EQ(ret, Status::SUCCESS); @@ -2585,7 +2837,7 @@ HWTEST_F(CloudDataTest, UpdateClearWaterMark001, TestSize.Level0) { ASSERT_NE(cloudServiceImpl_, nullptr); CloudData::CloudServiceImpl::HapInfo hapInfo = { - .user = cloudInfo_.user, .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE + .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE, .user = cloudInfo_.user }; SchemaMeta::Database database; database.name = TEST_CLOUD_STORE; @@ -2593,7 +2845,7 @@ HWTEST_F(CloudDataTest, UpdateClearWaterMark001, TestSize.Level0) SchemaMeta schemaMeta; schemaMeta.version = 1; schemaMeta.databases.push_back(database); - + SchemaMeta::Database database1; database1.name = TEST_CLOUD_STORE_1; database1.version = 2; @@ -2621,7 +2873,7 @@ HWTEST_F(CloudDataTest, UpdateClearWaterMark002, TestSize.Level0) { ASSERT_NE(cloudServiceImpl_, nullptr); CloudData::CloudServiceImpl::HapInfo hapInfo = { - .user = cloudInfo_.user, .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE + .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE, .user = cloudInfo_.user }; SchemaMeta::Database database; database.name = TEST_CLOUD_STORE; @@ -2629,7 +2881,7 @@ HWTEST_F(CloudDataTest, UpdateClearWaterMark002, TestSize.Level0) SchemaMeta schemaMeta; schemaMeta.version = 1; schemaMeta.databases.push_back(database); - + SchemaMeta::Database database1; database1.name = TEST_CLOUD_STORE; database1.version = 1; @@ -2657,7 +2909,7 @@ HWTEST_F(CloudDataTest, UpdateClearWaterMark003, TestSize.Level0) { ASSERT_NE(cloudServiceImpl_, nullptr); CloudData::CloudServiceImpl::HapInfo hapInfo = { - .user = cloudInfo_.user, .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE + .instIndex = 0, .bundleName = TEST_CLOUD_BUNDLE, .user = cloudInfo_.user }; SchemaMeta::Database database; database.name = TEST_CLOUD_STORE; @@ -2665,7 +2917,7 @@ HWTEST_F(CloudDataTest, UpdateClearWaterMark003, TestSize.Level0) SchemaMeta schemaMeta; schemaMeta.version = 1; schemaMeta.databases.push_back(database); - + SchemaMeta::Database database1; database1.name = TEST_CLOUD_STORE; database1.version = 2; @@ -2722,14 +2974,14 @@ HWTEST_F(CloudDataTest, TryUpdateDeviceId001, TestSize.Level1) oldMeta.storeId = "test_storeid_001"; oldMeta.isNeedUpdateDeviceId = true; oldMeta.storeType = StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN; - bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKey(), oldMeta); + bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKeyWithoutPath(), oldMeta); EXPECT_EQ(isSuccess, true); StoreMetaData meta1 = oldMeta; auto ret = rdbServiceImpl.TryUpdateDeviceId(param, oldMeta, meta1); EXPECT_EQ(ret, true); - MetaDataManager::GetInstance().DelMeta(oldMeta.GetKey()); + MetaDataManager::GetInstance().DelMeta(oldMeta.GetKeyWithoutPath()); } - + /** * @tc.name: TryUpdateDeviceId002 * @tc.desc: TryUpdateDeviceId test @@ -2748,14 +3000,14 @@ HWTEST_F(CloudDataTest, TryUpdateDeviceId002, TestSize.Level1) oldMeta.storeId = "test_storeid_001"; oldMeta.isNeedUpdateDeviceId = false; oldMeta.storeType = StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN; - bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKey(), oldMeta); + bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKeyWithoutPath(), oldMeta); EXPECT_EQ(isSuccess, true); StoreMetaData meta1 = oldMeta; auto ret = rdbServiceImpl.TryUpdateDeviceId(param, oldMeta, meta1); EXPECT_EQ(ret, true); - MetaDataManager::GetInstance().DelMeta(oldMeta.GetKey()); + MetaDataManager::GetInstance().DelMeta(oldMeta.GetKeyWithoutPath()); } - + /** * @tc.name: TryUpdateDeviceId003 * @tc.desc: TryUpdateDeviceId test @@ -2774,14 +3026,14 @@ HWTEST_F(CloudDataTest, TryUpdateDeviceId003, TestSize.Level1) oldMeta.storeId = "test_storeid_001"; oldMeta.isNeedUpdateDeviceId = true; oldMeta.storeType = StoreMetaData::StoreType::STORE_RELATIONAL_END; - bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKey(), oldMeta); + bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKeyWithoutPath(), oldMeta); EXPECT_EQ(isSuccess, true); StoreMetaData meta1 = oldMeta; auto ret = rdbServiceImpl.TryUpdateDeviceId(param, oldMeta, meta1); EXPECT_EQ(ret, true); - MetaDataManager::GetInstance().DelMeta(oldMeta.GetKey()); + MetaDataManager::GetInstance().DelMeta(oldMeta.GetKeyWithoutPath()); } - + /** * @tc.name: TryUpdateDeviceId004 * @tc.desc: TryUpdateDeviceId test @@ -2800,12 +3052,120 @@ HWTEST_F(CloudDataTest, TryUpdateDeviceId004, TestSize.Level1) oldMeta.storeId = "test_storeid_001"; oldMeta.isNeedUpdateDeviceId = false; oldMeta.storeType = StoreMetaData::StoreType::STORE_RELATIONAL_END; - bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKey(), oldMeta); + bool isSuccess = MetaDataManager::GetInstance().SaveMeta(oldMeta.GetKeyWithoutPath(), oldMeta); EXPECT_EQ(isSuccess, true); StoreMetaData meta1 = oldMeta; auto ret = rdbServiceImpl.TryUpdateDeviceId(param, oldMeta, meta1); EXPECT_EQ(ret, true); - MetaDataManager::GetInstance().DelMeta(oldMeta.GetKey()); + MetaDataManager::GetInstance().DelMeta(oldMeta.GetKeyWithoutPath()); +} + +/** +* @tc.name: OnInitialize +* @tc.desc: OnInitialize test +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(CloudDataTest, OnInitialize, TestSize.Level1) +{ + auto code = cloudServiceImpl_->OnInitialize(); + EXPECT_EQ(code, E_OK); +} + +/** +* @tc.name: CleanWaterVersion +* @tc.desc: CleanWaterVersion test +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(CloudDataTest, CleanWaterVersion, TestSize.Level1) +{ + auto ret = cloudServiceImpl_->CleanWaterVersion(200); + EXPECT_FALSE(ret); + ret = cloudServiceImpl_->CleanWaterVersion( + AccountDelegate::GetInstance()->GetUserByToken(IPCSkeleton::GetCallingTokenID())); + EXPECT_TRUE(ret); +} + +/** +* @tc.name: ConvertGenDetailsCode +* @tc.desc: Test ConvertGenDetailsCode function. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, ConvertGenDetailsCode, TestSize.Level0) +{ + DistributedData::GenDetails result; + GenProgressDetail detail; + detail.progress = GenProgress::SYNC_IN_PROGRESS; + detail.code = 100; + result.insert(std::make_pair("test", detail)); + auto details = CloudData::SyncManager::ConvertGenDetailsCode(result); + EXPECT_TRUE(details["test"].code == E_ERROR); + + DistributedData::GenDetails result1; + GenProgressDetail detail1; + detail1.progress = GenProgress::SYNC_IN_PROGRESS; + detail1.code = E_ERROR; + result1.insert(std::make_pair("test", detail1)); + details = CloudData::SyncManager::ConvertGenDetailsCode(result1); + EXPECT_TRUE(details["test"].code == E_ERROR); + + DistributedData::GenDetails result2; + GenProgressDetail detail2; + detail2.progress = GenProgress::SYNC_IN_PROGRESS; + detail2.code = E_OK; + result2.insert(std::make_pair("test", detail2)); + details = CloudData::SyncManager::ConvertGenDetailsCode(result2); + EXPECT_TRUE(details["test"].code == E_OK); + + DistributedData::GenDetails result3; + GenProgressDetail detail3; + detail3.progress = GenProgress::SYNC_IN_PROGRESS; + detail3.code = E_BLOCKED_BY_NETWORK_STRATEGY; + result3.insert(std::make_pair("test", detail3)); + details = CloudData::SyncManager::ConvertGenDetailsCode(result3); + EXPECT_TRUE(details["test"].code == E_BLOCKED_BY_NETWORK_STRATEGY); + + DistributedData::GenDetails result4; + GenProgressDetail detail4; + detail4.progress = GenProgress::SYNC_IN_PROGRESS; + detail4.code = E_BUSY; + result4.insert(std::make_pair("test", detail4)); + details = CloudData::SyncManager::ConvertGenDetailsCode(result4); + EXPECT_TRUE(details["test"].code == E_ERROR); +} + +/** +* @tc.name: ConvertValidGeneralCode +* @tc.desc: Test ConvertValidGeneralCode function. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, GetValidGeneralCode, TestSize.Level0) +{ + auto ret = CloudData::SyncManager::ConvertValidGeneralCode(E_OK); + EXPECT_TRUE(ret == E_OK); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_ERROR); + EXPECT_TRUE(ret == E_ERROR); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_NETWORK_ERROR); + EXPECT_TRUE(ret == E_NETWORK_ERROR); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_CLOUD_DISABLED); + EXPECT_TRUE(ret == E_CLOUD_DISABLED); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_LOCKED_BY_OTHERS); + EXPECT_TRUE(ret == E_LOCKED_BY_OTHERS); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_RECODE_LIMIT_EXCEEDED); + EXPECT_TRUE(ret == E_RECODE_LIMIT_EXCEEDED); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_NO_SPACE_FOR_ASSET); + EXPECT_TRUE(ret == E_NO_SPACE_FOR_ASSET); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_BLOCKED_BY_NETWORK_STRATEGY); + EXPECT_TRUE(ret == E_BLOCKED_BY_NETWORK_STRATEGY); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_BUSY); + EXPECT_TRUE(ret == E_ERROR); + ret = CloudData::SyncManager::ConvertValidGeneralCode(E_SYNC_TASK_MERGED); + EXPECT_TRUE(ret == E_ERROR); } } // namespace DistributedDataTest } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/cloud_service_impl_test.cpp b/datamgr_service/services/distributeddataservice/service/test/cloud_service_impl_test.cpp index bad6767d..ed40cca5 100644 --- a/datamgr_service/services/distributeddataservice/service/test/cloud_service_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/cloud_service_impl_test.cpp @@ -19,31 +19,49 @@ #include #include "accesstoken_kit.h" +#include "account/account_delegate.h" #include "bootstrap.h" +#include "checker_mock.h" +#include "cloud/change_event.h" +#include "cloud/cloud_event.h" #include "cloud/cloud_server.h" +#include "cloud/cloud_share_event.h" #include "cloud/schema_meta.h" #include "cloud_types.h" +#include "cloud_types_util.h" #include "cloud_value_util.h" #include "communicator/device_manager_adapter.h" +#include "device_matrix.h" +#include "eventcenter/event_center.h" +#include "feature/feature_system.h" +#include "ipc_skeleton.h" #include "log_print.h" +#include "metadata/meta_data_manager.h" #include "metadata/store_meta_data.h" #include "metadata/store_meta_data_local.h" #include "mock/db_store_mock.h" #include "mock/general_store_mock.h" +#include "mock/meta_data_manager_mock.h" #include "model/component_config.h" #include "network/network_delegate.h" #include "network_delegate_mock.h" #include "rdb_query.h" +#include "rdb_service.h" +#include "rdb_service_impl.h" #include "rdb_types.h" +#include "store/auto_cache.h" #include "store/store_info.h" #include "token_setproc.h" +#include "directory/directory_manager.h" using namespace testing::ext; +using namespace testing; using namespace OHOS::DistributedData; using namespace OHOS::Security::AccessToken; using Confirmation = OHOS::CloudData::Confirmation; using Status = OHOS::CloudData::CloudService::Status; using CloudSyncScene = OHOS::CloudData::CloudServiceImpl::CloudSyncScene; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; namespace OHOS::Test { namespace DistributedDataTest { @@ -58,12 +76,56 @@ public: void SetUp(); void TearDown(); + static void InitMetaData(); + static void CheckDelMeta(StoreMetaMapping &metaMapping, StoreMetaData &meta, StoreMetaData &meta1); static std::shared_ptr cloudServiceImpl_; static NetworkDelegateMock delegate_; +protected: + static std::shared_ptr dbStoreMock_; + static StoreMetaData metaData_; }; std::shared_ptr CloudServiceImplTest::cloudServiceImpl_ = std::make_shared(); NetworkDelegateMock CloudServiceImplTest::delegate_; +std::shared_ptr CloudServiceImplTest::dbStoreMock_ = std::make_shared(); +StoreMetaData CloudServiceImplTest::metaData_; + +void CloudServiceImplTest::CheckDelMeta(StoreMetaMapping &metaMapping, StoreMetaData &meta, StoreMetaData &meta1) +{ + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); + metaMapping.cloudPath = ""; + metaMapping.dataDir = DirectoryManager::GetInstance().GetStorePath(metaMapping) + "/" + metaMapping.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + meta.user = "100"; + auto res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); + metaMapping.dataDir = ""; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + meta.user = "100"; + res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); +} + +void CloudServiceImplTest::InitMetaData() +{ + metaData_.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData_.appId = "test_rdb_cloud_service_impl_appid"; + metaData_.bundleName = "test_rdb_cloud_service_impl_bundleName"; + metaData_.tokenId = OHOS::IPCSkeleton::GetCallingTokenID(); + metaData_.user = std::to_string(AccountDelegate::GetInstance()->GetUserByToken(metaData_.tokenId)); + metaData_.area = OHOS::DistributedKv::EL1; + metaData_.instanceId = 0; + metaData_.isAutoSync = true; + metaData_.storeType = DistributedRdb::RDB_DEVICE_COLLABORATION; + metaData_.storeId = "test_cloud_service_impl_store"; + metaData_.dataDir = "/test_cloud_service_impl_store"; +} void CloudServiceImplTest::SetUpTestCase(void) { @@ -71,14 +133,18 @@ void CloudServiceImplTest::SetUpTestCase(void) size_t min = 5; auto executor = std::make_shared(max, min); DeviceManagerAdapter::GetInstance().Init(executor); + Bootstrap::GetInstance().LoadCheckers(); + CryptoManager::GetInstance().GenerateRootKey(); + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); NetworkDelegate::RegisterNetworkInstance(&delegate_); + InitMetaData(); } -void CloudServiceImplTest::TearDownTestCase() {} +void CloudServiceImplTest::TearDownTestCase() { } -void CloudServiceImplTest::SetUp() {} +void CloudServiceImplTest::SetUp() { } -void CloudServiceImplTest::TearDown() {} +void CloudServiceImplTest::TearDown() { } /** * @tc.name: EnableCloud001 @@ -258,6 +324,23 @@ HWTEST_F(CloudServiceImplTest, GetCloudInfoFromServer001, TestSize.Level0) EXPECT_EQ(status, CloudData::CloudService::SERVER_UNAVAILABLE); } +/** + * @tc.name: GetCloudInfoFromServer002 + * @tc.desc: Test GetCloudInfoFromServer functions with cloudinfo is empty. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudServiceImplTest, GetCloudInfoFromServer002, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest GetCloudInfoFromServer002 start"); + CloudServer cloudServer; + CloudServer::RegisterCloudInstance(&cloudServer); + int user = 100; + auto [status, result] = cloudServiceImpl_->GetCloudInfoFromServer(user); + EXPECT_EQ(status, E_ERROR); + CloudServer::instance_ = nullptr; +} + /** * @tc.name: ReleaseUserInfo001 * @tc.desc: Test ReleaseUserInfo functions with invalid parameter. @@ -285,6 +368,120 @@ HWTEST_F(CloudServiceImplTest, DoSubscribe, TestSize.Level0) EXPECT_TRUE(status); } +/** + * @tc.name: OnAppInstallTest + * @tc.desc: Test the OnAppInstallTest + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudServiceImplTest, OnAppInstallTest, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest OnAppInstallTest start"); + ASSERT_NE(cloudServiceImpl_, nullptr); + ASSERT_NE(cloudServiceImpl_->factory_.staticActs_, nullptr); + int32_t user = 0; + int32_t index = 0; + auto status = cloudServiceImpl_->factory_.staticActs_->OnAppInstall(TEST_CLOUD_BUNDLE, user, index); + EXPECT_EQ(status, GeneralError::E_ERROR); +} + +/** + * @tc.name: OnAppUpdateTest + * @tc.desc: Test the OnAppUpdateTest + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudServiceImplTest, OnAppUpdateTest, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest OnAppUpdateTest start"); + ASSERT_NE(cloudServiceImpl_, nullptr); + ASSERT_NE(cloudServiceImpl_->factory_.staticActs_, nullptr); + int32_t user = 0; + int32_t index = 0; + auto status = cloudServiceImpl_->factory_.staticActs_->OnAppUpdate(TEST_CLOUD_BUNDLE, user, index); + EXPECT_EQ(status, CloudData::CloudService::SUCCESS); +} + +/** + * @tc.name: CloudDriverCheckTest + * @tc.desc: Test the CloudDriverCheck + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudServiceImplTest, CloudDriverCheckTest, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest CloudDriverCheckTest start"); + ASSERT_NE(cloudServiceImpl_, nullptr); + ASSERT_NE(cloudServiceImpl_->factory_.staticActs_, nullptr); + CloudServer cloudServer; + CloudServer::RegisterCloudInstance(&cloudServer); + int32_t user = 0; + auto result = cloudServiceImpl_->factory_.staticActs_->CloudDriverCheck(TEST_CLOUD_BUNDLE, user); + EXPECT_EQ(result, false); + CloudServer::instance_ = nullptr; +} + +/** + * @tc.name: UpdateSchemaFromServerTest_001 + * @tc.desc: Test UpdateSchemaFromServer functions + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudServiceImplTest, UpdateSchemaFromServerTest_001, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest UpdateSchemaFromServerTest_001 start"); + CloudServer cloudServer; + CloudServer::RegisterCloudInstance(&cloudServer); + int user = 100; + auto status = cloudServiceImpl_->UpdateSchemaFromServer(user); + EXPECT_EQ(status, E_ERROR); + CloudServer::instance_ = nullptr; +} + +/** + * @tc.name: UpdateSchemaFromServerTest_002 + * @tc.desc: Test UpdateSchemaFromServer functions. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudServiceImplTest, UpdateSchemaFromServerTest_002, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest UpdateSchemaFromServerTest_002 start"); + CloudServer cloudServer; + CloudServer::RegisterCloudInstance(&cloudServer); + int user = 0; + CloudInfo cloudInfo; + cloudInfo.user = user; + DistributedData::CloudInfo::AppInfo appInfo; + appInfo.bundleName = TEST_CLOUD_BUNDLE; + appInfo.appId = TEST_CLOUD_APPID; + appInfo.cloudSwitch = true; + cloudInfo.apps = {{ TEST_CLOUD_BUNDLE, appInfo }}; + auto status = cloudServiceImpl_->UpdateSchemaFromServer(cloudInfo, user); + EXPECT_EQ(status, CloudData::CloudService::SUCCESS); + CloudServer::instance_ = nullptr; +} + +/** + * @tc.name: UpdateE2eeEnableTest + * @tc.desc: Test UpdateE2eeEnable functions. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudServiceImplTest, UpdateE2eeEnableTest, TestSize.Level0) +{ + ZLOGI("CloudServiceImplTest UpdateE2eeEnableTest start"); + ASSERT_NE(cloudServiceImpl_, nullptr); + CloudServer cloudServer; + auto result = cloudServer.CloudDriverUpdated(TEST_CLOUD_BUNDLE); + EXPECT_EQ(result, false); + + std::string schemaKey = "schemaKey"; + cloudServiceImpl_->UpdateE2eeEnable(schemaKey, true, TEST_CLOUD_BUNDLE); + SchemaMeta schemaMeta; + ASSERT_FALSE(MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)); +} + /** * @tc.name: Share001 * @tc.desc: Test the Share with invalid parameters @@ -381,12 +578,229 @@ HWTEST_F(CloudServiceImplTest, QueryByInvitation001, TestSize.Level0) HWTEST_F(CloudServiceImplTest, ConfirmInvitation001, TestSize.Level0) { int32_t confirmation = 0; - std::tuple result{ 0, "", "" }; + std::tuple result { 0, "", "" }; std::string invitation; auto status = cloudServiceImpl_->ConfirmInvitation(invitation, confirmation, result); EXPECT_EQ(status, GeneralError::E_ERROR); } +/** + * @tc.name: GetStoreMetaData_001 + * @tc.desc: test GetStoreMetaData LoadMeta success. + * @tc.type: FUNC + */ +HWTEST_F(CloudServiceImplTest, GetStoreMetaData_001, TestSize.Level1) +{ + StoreMetaData meta; + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta.user = "0"; + meta.bundleName = "bundleName"; + meta.storeId = "storeName"; + meta.dataDir = DirectoryManager::GetInstance().GetStorePath(meta) + "/" + meta.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + bool res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); + meta.instanceId = 1; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); +} + +/** + * @tc.name: GetStoreMetaData_002 + * @tc.desc: test GetStoreMetaData LoadMeta failed and user is 0. + * @tc.type: FUNC + */ +HWTEST_F(CloudServiceImplTest, GetStoreMetaData_002, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + metaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaMapping.user = "0"; + metaMapping.bundleName = "bundleName"; + metaMapping.storeId = "storeName"; + metaMapping.cloudPath = DirectoryManager::GetInstance().GetStorePath(metaMapping) + "/" + metaMapping.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + StoreMetaData meta; + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta.user = "100"; + meta.bundleName = "bundleName"; + meta.storeId = "storeName"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + bool res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + meta.instanceId = 1; + metaMapping.instanceId = 1; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + meta.user = "100"; + res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + metaMapping.cloudPath = ""; + metaMapping.dataDir = DirectoryManager::GetInstance().GetStorePath(metaMapping) + "/" + metaMapping.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + meta.user = "100"; + res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + metaMapping.dataDir = ""; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + meta.user = "100"; + res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); +} + +/** + * @tc.name: GetStoreMetaData_003 + * @tc.desc: test GetStoreMetaData LoadMeta failed and user is not 0. + * @tc.type: FUNC + */ +HWTEST_F(CloudServiceImplTest, GetStoreMetaData_003, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + metaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaMapping.user = "0"; + metaMapping.bundleName = "bundleName"; + metaMapping.storeId = "storeName"; + metaMapping.cloudPath = DirectoryManager::GetInstance().GetStorePath(metaMapping) + "/" + metaMapping.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + StoreMetaData meta; + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta.user = "100"; + meta.bundleName = "bundleName"; + meta.storeId = "storeName"; + StoreMetaData meta1; + meta1.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta1.user = "0"; + meta1.bundleName = "bundleName"; + meta1.storeId = "storeName"; + meta1.dataDir = DirectoryManager::GetInstance().GetStorePath(meta) + "/" + meta.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + StoreMetaDataLocal localMetaData; + bool res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); +} + +/** + * @tc.name: GetStoreMetaData_004 + * @tc.desc: test GetStoreMetaData First load of metadata failed and the user is not 0, + * then the load of metadata succeeded. + * @tc.type: FUNC + */ +HWTEST_F(CloudServiceImplTest, GetStoreMetaData_004, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + metaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaMapping.user = "0"; + metaMapping.bundleName = "bundleName"; + metaMapping.storeId = "storeName"; + metaMapping.instanceId = 1; + metaMapping.cloudPath = DirectoryManager::GetInstance().GetStorePath(metaMapping) + "/" + metaMapping.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + StoreMetaData meta; + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta.user = "100"; + meta.bundleName = "bundleName"; + meta.storeId = "storeName"; + meta.instanceId = 1; + StoreMetaData meta1; + meta1.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta1.user = "0"; + meta1.bundleName = "bundleName"; + meta1.storeId = "storeName"; + meta1.instanceId = 1; + meta1.dataDir = DirectoryManager::GetInstance().GetStorePath(meta1) + "/" + meta1.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + StoreMetaDataLocal localMetaData; + bool res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); + CheckDelMeta(metaMapping, meta, meta1); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKeyLocal(), localMetaData, true), true); + meta.user = "100"; + res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, false); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKeyLocal(), true), true); + localMetaData.isPublic = true; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKeyLocal(), localMetaData, true), true); + meta.user = "100"; + metaMapping.cloudPath = DirectoryManager::GetInstance().GetStorePath(meta1) + "/" + meta1.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + res = cloudServiceImpl_->GetStoreMetaData(meta); + EXPECT_EQ(res, true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKeyLocal(), true), true); +} + +/** + * @tc.name: PreShare_001 + * @tc.desc: test PreShare is dataDir empty. + * @tc.type: FUNC + */ +HWTEST_F(CloudServiceImplTest, PreShare_001, TestSize.Level1) +{ + StoreInfo storeInfo; + storeInfo.bundleName = "bundleName"; + storeInfo.storeName = "storeName"; + storeInfo.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + storeInfo.user = 100; + StoreMetaMapping storeMetaMapping; + storeMetaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + storeMetaMapping.user = "100"; + storeMetaMapping.bundleName = "bundleName"; + storeMetaMapping.storeId = "storeName"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(storeMetaMapping.GetKey(), storeMetaMapping, true), true); + std::shared_ptr query; + auto [errCode, cursor] = cloudServiceImpl_->PreShare(storeInfo, *query); + EXPECT_EQ(errCode, E_ERROR); + ASSERT_EQ(cursor, nullptr); + storeInfo.path = "path"; + storeMetaMapping.cloudPath = "path1"; + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(storeMetaMapping.GetKey(), storeMetaMapping, true), true); + auto [errCode1, cursor1] = cloudServiceImpl_->PreShare(storeInfo, *query); + EXPECT_EQ(errCode1, E_ERROR); + ASSERT_EQ(cursor1, nullptr); + storeInfo.path = "path"; + storeMetaMapping.cloudPath = "path"; + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(storeMetaMapping.GetKey(), storeMetaMapping, true), true); + auto [errCode2, cursor2] = cloudServiceImpl_->PreShare(storeInfo, *query); + EXPECT_EQ(errCode2, E_ERROR); + ASSERT_EQ(cursor2, nullptr); + storeInfo.instanceId = 1; + storeMetaMapping.instanceId = 1; + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(storeMetaMapping.GetKey(), storeMetaMapping, true), true); + auto [errCode3, cursor3] = cloudServiceImpl_->PreShare(storeInfo, *query); + EXPECT_EQ(errCode3, E_ERROR); + ASSERT_EQ(cursor3, nullptr); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(storeMetaMapping.GetKey(), true), true); +} + /** * @tc.name: ChangeConfirmation001 * @tc.desc: Test the ChangeConfirmation with invalid parameters @@ -500,13 +914,13 @@ public: void TearDown(); }; -void ComponentConfigTest::SetUpTestCase(void) {} +void ComponentConfigTest::SetUpTestCase(void) { } -void ComponentConfigTest::TearDownTestCase() {} +void ComponentConfigTest::TearDownTestCase() { } -void ComponentConfigTest::SetUp() {} +void ComponentConfigTest::SetUp() { } -void ComponentConfigTest::TearDown() {} +void ComponentConfigTest::TearDown() { } /** * @tc.name: CapabilityRange diff --git a/datamgr_service/services/distributeddataservice/service/test/crypto_manager_test.cpp b/datamgr_service/services/distributeddataservice/service/test/crypto_manager_test.cpp index 4b42a2cb..fe4e537f 100644 --- a/datamgr_service/services/distributeddataservice/service/test/crypto_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/crypto_manager_test.cpp @@ -13,48 +13,96 @@ * limitations under the License. */ -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include -#include "crypto_manager.h" #include "gtest/gtest.h" -#include "metadata/secret_key_meta_data.h" -#include "metadata/store_meta_data.h" -#include "types.h" + +#include "access_token.h" +#include "accesstoken_kit.h" +#include "hks_api.h" +#include "hks_param.h" +#include "nativetoken_kit.h" +#include "token_setproc.h" + +namespace OHOS::Test { using namespace testing::ext; using namespace OHOS::DistributedData; -namespace OHOS::Test { -namespace DistributedDataTest { +using namespace OHOS::Security::AccessToken; + +static constexpr int32_t KEY_LENGTH = 32; +static constexpr int32_t NONCE_SIZE = 12; +static constexpr int32_t INVALID_AREA = -1; +static constexpr int32_t TEST_USERID_NUM = 100; +static constexpr const char *TEST_USERID = "100"; +static constexpr const char *TEST_BUNDLE_NAME = "test_application"; +static constexpr const char *TEST_STORE_NAME = "test_store"; +static constexpr const char *ROOT_KEY_ALIAS = "distributed_db_root_key"; +static constexpr const char *PROCESS_NAME = "distributeddata"; + class CryptoManagerTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); - void SetUp(){}; - void TearDown(){}; - static std::vector Random(uint32_t len); + void SetUp() {} + void TearDown() {} + + static void SetNativeTokenIdFromProcess(const std::string &process); + static std::vector Random(int32_t len); + static void DeleteRootKey(int32_t area); + static uint32_t GetStorageLevel(int32_t area); -protected: static std::vector randomKey; + static std::vector vecRootKeyAlias; + static std::vector nonce; }; -static const uint32_t KEY_LENGTH = 32; -static const uint32_t ENCRYPT_KEY_LENGTH = 48; -static constexpr int32_t EL2 = 2; -static constexpr int32_t EL4 = 4; -static constexpr const char *TEST_USERID = "100"; std::vector CryptoManagerTest::randomKey; +std::vector CryptoManagerTest::vecRootKeyAlias; +std::vector CryptoManagerTest::nonce; + +void CryptoManagerTest::SetNativeTokenIdFromProcess(const std::string &process) +{ + std::string dumpInfo; + AtmToolsParamInfo info; + info.processName = process; + AccessTokenKit::DumpTokenInfo(info, dumpInfo); + size_t pos = dumpInfo.find("\"tokenID\": "); + if (pos == std::string::npos) { + return; + } + pos += std::string("\"tokenID\": ").length(); + std::string numStr; + while (pos < dumpInfo.length() && std::isdigit(dumpInfo[pos])) { + numStr += dumpInfo[pos]; + ++pos; + } + std::istringstream iss(numStr); + AccessTokenID tokenID; + iss >> tokenID; + SetSelfTokenID(tokenID); +} + void CryptoManagerTest::SetUpTestCase(void) { + SetNativeTokenIdFromProcess(PROCESS_NAME); + randomKey = Random(KEY_LENGTH); + vecRootKeyAlias = std::vector(ROOT_KEY_ALIAS, ROOT_KEY_ALIAS + strlen(ROOT_KEY_ALIAS)); + nonce = Random(NONCE_SIZE); } void CryptoManagerTest::TearDownTestCase(void) { randomKey.assign(randomKey.size(), 0); + nonce.assign(nonce.size(), 0); + DeleteRootKey(CryptoManager::Area::EL1); + DeleteRootKey(CryptoManager::Area::EL2); + DeleteRootKey(CryptoManager::Area::EL4); } -std::vector CryptoManagerTest::Random(uint32_t len) +std::vector CryptoManagerTest::Random(int32_t len) { std::random_device randomDevice; std::uniform_int_distribution distribution(0, std::numeric_limits::max()); @@ -65,235 +113,314 @@ std::vector CryptoManagerTest::Random(uint32_t len) return key; } -/** -* @tc.name: GenerateRootKey -* @tc.desc: generate the root key -* @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang -*/ -HWTEST_F(CryptoManagerTest, GenerateRootKey, TestSize.Level0) +uint32_t CryptoManagerTest::GetStorageLevel(int32_t area) { - auto errCode = CryptoManager::GetInstance().GenerateRootKey(); - EXPECT_EQ(errCode, CryptoManager::ErrCode::SUCCESS); + if (area >= CryptoManager::Area::EL4 && area <= CryptoManager::Area::EL5) { + return HKS_AUTH_STORAGE_LEVEL_ECE; + } + if (area >= CryptoManager::Area::EL2 && area <= CryptoManager::Area::EL3) { + return HKS_AUTH_STORAGE_LEVEL_CE; + } + return HKS_AUTH_STORAGE_LEVEL_DE; +} + +void CryptoManagerTest::DeleteRootKey(int32_t area) +{ + struct HksParamSet *params = nullptr; + if (HksInitParamSet(¶ms) != HKS_SUCCESS) { + return; + } + auto storageLevel = GetStorageLevel(area); + std::vector hksParam = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = storageLevel }, + }; + if (storageLevel > HKS_AUTH_STORAGE_LEVEL_DE) { + hksParam.emplace_back(HksParam { .tag = HKS_TAG_SPECIFIC_USER_ID, .int32Param = TEST_USERID_NUM }); + } + if (HksAddParams(params, hksParam.data(), hksParam.size()) != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return; + } + if (HksBuildParamSet(¶ms) != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return; + } + struct HksBlob keyName = { uint32_t(vecRootKeyAlias.size()), const_cast(vecRootKeyAlias.data()) }; + (void)HksDeleteKey(&keyName, params); + HksFreeParamSet(¶ms); } /** -* @tc.name: CheckRootKey -* @tc.desc: check root key exist; +* @tc.name: GenerateRootKeyTest001 +* @tc.desc: generate the root key of DE * @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang */ -HWTEST_F(CryptoManagerTest, CheckRootKey, TestSize.Level0) +HWTEST_F(CryptoManagerTest, GenerateRootKeyTest001, TestSize.Level0) { - auto errCode = CryptoManager::GetInstance().CheckRootKey(); + auto errCode = CryptoManager::GetInstance().GenerateRootKey(); EXPECT_EQ(errCode, CryptoManager::ErrCode::SUCCESS); + + errCode = CryptoManager::GetInstance().CheckRootKey(); + ASSERT_EQ(errCode, CryptoManager::ErrCode::SUCCESS); } /** -* @tc.name: Encrypt001 -* @tc.desc: encrypt random key; +* @tc.name: EncryptAndDecryptTest001 +* @tc.desc: encrypt random key and decrypt with EL1 * @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang */ -HWTEST_F(CryptoManagerTest, Encrypt001, TestSize.Level0) +HWTEST_F(CryptoManagerTest, EncryptAndDecryptTest001, TestSize.Level0) { - auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - EXPECT_EQ(encryptKey.size(), ENCRYPT_KEY_LENGTH); - encryptKey.assign(encryptKey.size(), 0); + auto errCode = CryptoManager::GetInstance().GenerateRootKey(); + ASSERT_EQ(errCode, CryptoManager::ErrCode::SUCCESS); + CryptoManager::CryptoParams encryptParams = { .area = CryptoManager::Area::EL1, .userId = TEST_USERID }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + ASSERT_FALSE(encryptParams.nonce.empty()); + + CryptoManager::CryptoParams decryptParams = { .area = CryptoManager::Area::EL1, .userId = TEST_USERID, + .nonce = encryptParams.nonce }; + auto decryptKey = CryptoManager::GetInstance().Decrypt(encryptKey, decryptParams); + ASSERT_FALSE(decryptKey.empty()); + for (auto i = 0; i < KEY_LENGTH; ++i) { + ASSERT_EQ(decryptKey[i], randomKey[i]); + } + decryptKey.assign(encryptKey.size(), 0); } /** -* @tc.name: Encrypt002 -* @tc.desc: encrypt empty key; +* @tc.name: EncryptAndDecryptTest002 +* @tc.desc: encrypt random key and decrypt with EL2 * @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang */ -HWTEST_F(CryptoManagerTest, Encrypt002, TestSize.Level0) +HWTEST_F(CryptoManagerTest, EncryptAndDecryptTest002, TestSize.Level0) { - auto encryptKey = CryptoManager::GetInstance().Encrypt({ }, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - EXPECT_TRUE(encryptKey.empty()); + CryptoManager::CryptoParams encryptParams = { .area = CryptoManager::Area::EL2, .userId = TEST_USERID }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + ASSERT_FALSE(encryptParams.nonce.empty()); + + CryptoManager::CryptoParams decryptParams = { .area = CryptoManager::Area::EL2, .userId = TEST_USERID, + .nonce = encryptParams.nonce }; + auto decryptKey = CryptoManager::GetInstance().Decrypt(encryptKey, decryptParams); + ASSERT_FALSE(decryptKey.empty()); + for (auto i = 0; i < KEY_LENGTH; ++i) { + ASSERT_EQ(decryptKey[i], randomKey[i]); + } + decryptKey.assign(encryptKey.size(), 0); } /** -* @tc.name: Encrypt003 -* @tc.desc: Check root key fail; +* @tc.name: EncryptAndDecryptTest003 +* @tc.desc: encrypt random key and decrypt with EL3 * @tc.type: FUNC -* @tc.require: -* @tc.author: yanhui */ -HWTEST_F(CryptoManagerTest, Encrypt003, TestSize.Level0) +HWTEST_F(CryptoManagerTest, EncryptAndDecryptTest003, TestSize.Level0) { - auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, EL2, DEFAULT_USER); - EXPECT_TRUE(encryptKey.empty()); - encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, EL4, DEFAULT_USER); - EXPECT_TRUE(encryptKey.empty()); - - encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, EL2, TEST_USERID); - // check interact across local accounts permission failed - EXPECT_TRUE(encryptKey.empty()); - encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, EL4, TEST_USERID); - // check interact across local accounts permission failed - EXPECT_TRUE(encryptKey.empty()); + CryptoManager::CryptoParams encryptParams = { .area = CryptoManager::Area::EL3, .userId = TEST_USERID }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + ASSERT_FALSE(encryptParams.nonce.empty()); + + CryptoManager::CryptoParams decryptParams = { .area = CryptoManager::Area::EL3, .userId = TEST_USERID, + .nonce = encryptParams.nonce }; + auto decryptKey = CryptoManager::GetInstance().Decrypt(encryptKey, decryptParams); + ASSERT_FALSE(decryptKey.empty()); + for (auto i = 0; i < KEY_LENGTH; ++i) { + ASSERT_EQ(decryptKey[i], randomKey[i]); + } + decryptKey.assign(encryptKey.size(), 0); } /** -* @tc.name: Encrypt004 -* @tc.desc: Encrypt clone key, but root key not imported; +* @tc.name: EncryptAndDecryptTest004 +* @tc.desc: encrypt random key and decrypt with EL4 * @tc.type: FUNC -* @tc.require: -* @tc.author: yanhui */ -HWTEST_F(CryptoManagerTest, Encrypt004, TestSize.Level0) +HWTEST_F(CryptoManagerTest, EncryptAndDecryptTest004, TestSize.Level0) { - const std::string str = "distributed_db_backup_key"; - auto cloneKey = std::vector(str.begin(), str.end()); - std::vector nonce{}; - CryptoManager::EncryptParams params = { .keyAlias = cloneKey, .nonce = nonce }; - auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, params); - EXPECT_TRUE(encryptKey.empty()); - std::vector key; - - auto result = CryptoManager::GetInstance().Decrypt(encryptKey, key, params); - ASSERT_FALSE(result); + CryptoManager::CryptoParams encryptParams = { .area = CryptoManager::Area::EL4, .userId = TEST_USERID }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + ASSERT_FALSE(encryptParams.nonce.empty()); + + CryptoManager::CryptoParams decryptParams = { .area = CryptoManager::Area::EL4, .userId = TEST_USERID, + .nonce = encryptParams.nonce }; + auto decryptKey = CryptoManager::GetInstance().Decrypt(encryptKey, decryptParams); + ASSERT_FALSE(decryptKey.empty()); + for (auto i = 0; i < KEY_LENGTH; ++i) { + ASSERT_EQ(decryptKey[i], randomKey[i]); + } + decryptKey.assign(encryptKey.size(), 0); } /** -* @tc.name: DecryptKey001 -* @tc.desc: decrypt the encrypt key; +* @tc.name: EncryptAndDecryptTest005 +* @tc.desc: encrypt random key and decrypt with INVALID_AREA * @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang */ -HWTEST_F(CryptoManagerTest, DecryptKey001, TestSize.Level0) +HWTEST_F(CryptoManagerTest, EncryptAndDecryptTest005, TestSize.Level0) { - auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - std::vector key; - auto result = CryptoManager::GetInstance().Decrypt(encryptKey, key, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - EXPECT_TRUE(result); - EXPECT_EQ(key.size(), KEY_LENGTH); - encryptKey.assign(encryptKey.size(), 0); + CryptoManager::CryptoParams encryptParams = { .area = INVALID_AREA, .userId = TEST_USERID }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + ASSERT_FALSE(encryptParams.nonce.empty()); + + CryptoManager::CryptoParams decryptParams = { .area = encryptParams.area, .userId = TEST_USERID, + .nonce = encryptParams.nonce }; + auto decryptKey = CryptoManager::GetInstance().Decrypt(encryptKey, decryptParams); + ASSERT_FALSE(decryptKey.empty()); + for (auto i = 0; i < KEY_LENGTH; ++i) { + ASSERT_EQ(decryptKey[i], randomKey[i]); + } + decryptKey.assign(encryptKey.size(), 0); } /** -* @tc.name: DecryptKey002 -* @tc.desc: decrypt the key, the source key is not encrypt; +* @tc.name: EncryptAndDecryptTest006 +* @tc.desc: encrypt random key and decrypt with EL1 and key alias * @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang */ -HWTEST_F(CryptoManagerTest, DecryptKey002, TestSize.Level0) +HWTEST_F(CryptoManagerTest, EncryptAndDecryptTest006, TestSize.Level0) { - std::vector key; - auto result = CryptoManager::GetInstance().Decrypt(randomKey, key, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - EXPECT_FALSE(result); - EXPECT_TRUE(key.empty()); + CryptoManager::CryptoParams encryptParams = { .area = CryptoManager::Area::EL1, .userId = TEST_USERID, + .keyAlias = vecRootKeyAlias }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + ASSERT_FALSE(encryptParams.nonce.empty()); + + CryptoManager::CryptoParams decryptParams = { .area = encryptParams.area, .userId = TEST_USERID, + .keyAlias = vecRootKeyAlias, .nonce = encryptParams.nonce }; + auto decryptKey = CryptoManager::GetInstance().Decrypt(encryptKey, decryptParams); + ASSERT_FALSE(decryptKey.empty()); + for (auto i = 0; i < KEY_LENGTH; ++i) { + ASSERT_EQ(decryptKey[i], randomKey[i]); + } + decryptKey.assign(encryptKey.size(), 0); } /** -* @tc.name: DecryptKey003 -* @tc.desc: decrypt the key, the source key is empty; +* @tc.name: EncryptAndDecryptTest007 +* @tc.desc: encrypt random key and decrypt with EL1 and nonce value * @tc.type: FUNC -* @tc.require: -* @tc.author: zuojiangjiang */ -HWTEST_F(CryptoManagerTest, DecryptKey003, TestSize.Level0) +HWTEST_F(CryptoManagerTest, EncryptAndDecryptTest007, TestSize.Level0) { - std::vector srcKey {}; - std::vector key; - auto result = CryptoManager::GetInstance().Decrypt(srcKey, key, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - EXPECT_FALSE(result); - EXPECT_TRUE(key.empty()); + CryptoManager::CryptoParams encryptParams = { .area = CryptoManager::Area::EL1, .userId = TEST_USERID, + .nonce = nonce }; + auto encryptKey = CryptoManager::GetInstance().Encrypt(randomKey, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + + CryptoManager::CryptoParams decryptParams = { .area = encryptParams.area, .userId = TEST_USERID, + .keyAlias = vecRootKeyAlias, .nonce = encryptParams.nonce }; + auto decryptKey = CryptoManager::GetInstance().Decrypt(encryptKey, decryptParams); + ASSERT_FALSE(decryptKey.empty()); + for (auto i = 0; i < KEY_LENGTH; ++i) { + ASSERT_EQ(decryptKey[i], randomKey[i]); + } + decryptKey.assign(encryptKey.size(), 0); } /** -* @tc.name: DecryptKey004 -* @tc.desc: Check root key fail; +* @tc.name: UpdateSecretMetaTest001 +* @tc.desc: update meta with invalid params * @tc.type: FUNC -* @tc.require: -* @tc.author: yanhui */ -HWTEST_F(CryptoManagerTest, DecryptKey004, TestSize.Level0) +HWTEST_F(CryptoManagerTest, UpdateSecretMetaTest001, TestSize.Level0) { - std::vector key; - auto result = CryptoManager::GetInstance().Decrypt(randomKey, key, EL2, DEFAULT_USER); - EXPECT_FALSE(result); - EXPECT_TRUE(key.empty()); - result = CryptoManager::GetInstance().Decrypt(randomKey, key, EL4, DEFAULT_USER); - EXPECT_FALSE(result); - EXPECT_TRUE(key.empty()); + std::vector password; + StoreMetaData metaData; + SecretKeyMetaData secretKey; + CryptoManager::GetInstance().UpdateSecretMeta(password, metaData, "", secretKey); + ASSERT_TRUE(secretKey.sKey.empty()); + + secretKey.nonce = nonce; + secretKey.area = CryptoManager::Area::EL1; + CryptoManager::GetInstance().UpdateSecretMeta(randomKey, metaData, "", secretKey); + ASSERT_TRUE(secretKey.sKey.empty()); } /** -* @tc.name: Decrypt001 -* @tc.desc: SecretKeyMetaData is old. +* @tc.name: UpdateSecretMetaTest002 +* @tc.desc: update meta with area EL1 * @tc.type: FUNC -* @tc.require: -* @tc.author: yanhui */ -HWTEST_F(CryptoManagerTest, Decrypt001, TestSize.Level0) +HWTEST_F(CryptoManagerTest, UpdateSecretMetaTest002, TestSize.Level0) { - SecretKeyMetaData secretKeyMeta; + auto errCode = CryptoManager::GetInstance().GenerateRootKey(); + ASSERT_EQ(errCode, CryptoManager::ErrCode::SUCCESS); + SecretKeyMetaData secretKey; StoreMetaData metaData; - std::vector key; - secretKeyMeta.sKey = CryptoManager::GetInstance().Encrypt(randomKey, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - auto result = CryptoManager::GetInstance().Decrypt(metaData, secretKeyMeta, key); - EXPECT_TRUE(result); + metaData.bundleName = TEST_BUNDLE_NAME; + metaData.storeId = TEST_STORE_NAME; + metaData.user = TEST_USERID; + metaData.area = CryptoManager::Area::EL1; + CryptoManager::GetInstance().UpdateSecretMeta(randomKey, metaData, metaData.GetSecretKey(), secretKey); + ASSERT_FALSE(secretKey.sKey.empty()); + ASSERT_FALSE(secretKey.nonce.empty()); + ASSERT_EQ(secretKey.area, metaData.area); } /** -* @tc.name: Decrypt002 -* @tc.desc: SecretKeyMetaData is new. +* @tc.name: UpdateSecretMetaTest003 +* @tc.desc: update meta with area EL2 * @tc.type: FUNC -* @tc.require: -* @tc.author: yanhui */ -HWTEST_F(CryptoManagerTest, Decrypt002, TestSize.Level0) +HWTEST_F(CryptoManagerTest, UpdateSecretMetaTest003, TestSize.Level0) { - SecretKeyMetaData secretKeyMeta; - secretKeyMeta.area = 1; + SecretKeyMetaData secretKey; StoreMetaData metaData; - std::vector key; - secretKeyMeta.sKey = CryptoManager::GetInstance().Encrypt(randomKey, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - auto result = CryptoManager::GetInstance().Decrypt(metaData, secretKeyMeta, key); - EXPECT_TRUE(result); - for (int8_t i = 0; i < randomKey.size(); i++) { - EXPECT_EQ(randomKey[i], key[i]); - } + metaData.bundleName = TEST_BUNDLE_NAME; + metaData.storeId = TEST_STORE_NAME; + metaData.user = TEST_USERID; + metaData.area = CryptoManager::Area::EL2; + CryptoManager::GetInstance().UpdateSecretMeta(randomKey, metaData, metaData.GetSecretKey(), secretKey); + ASSERT_FALSE(secretKey.sKey.empty()); + ASSERT_FALSE(secretKey.nonce.empty()); + ASSERT_EQ(secretKey.area, metaData.area); } /** -* @tc.name: UpdatePassword001 -* @tc.desc: The data is unencrypted. +* @tc.name: UpdateSecretMetaTest004 +* @tc.desc: update meta with area EL3 * @tc.type: FUNC -* @tc.require: -* @tc.author: yanhui */ -HWTEST_F(CryptoManagerTest, UpdatePassword001, TestSize.Level0) +HWTEST_F(CryptoManagerTest, UpdateSecretMetaTest004, TestSize.Level0) { + SecretKeyMetaData secretKey; StoreMetaData metaData; - std::vector key; - EXPECT_FALSE(CryptoManager::GetInstance().UpdateSecretKey(metaData, key)); + metaData.bundleName = TEST_BUNDLE_NAME; + metaData.storeId = TEST_STORE_NAME; + metaData.user = TEST_USERID; + metaData.area = CryptoManager::Area::EL3; + CryptoManager::GetInstance().UpdateSecretMeta(randomKey, metaData, metaData.GetSecretKey(), secretKey); + ASSERT_FALSE(secretKey.sKey.empty()); + ASSERT_FALSE(secretKey.nonce.empty()); + ASSERT_EQ(secretKey.area, metaData.area); } /** -* @tc.name: UpdatePassword002 -* @tc.desc: The data is encrypted. +* @tc.name: UpdateSecretMetaTest005 +* @tc.desc: update meta with area EL4 * @tc.type: FUNC -* @tc.require: -* @tc.author: yanhui */ -HWTEST_F(CryptoManagerTest, UpdatePassword002, TestSize.Level0) +HWTEST_F(CryptoManagerTest, UpdateSecretMetaTest005, TestSize.Level0) { + SecretKeyMetaData secretKey; StoreMetaData metaData; - metaData.isEncrypt = true; - metaData.area = DEFAULT_ENCRYPTION_LEVEL; - // MetaDataManager not initialized - EXPECT_FALSE(CryptoManager::GetInstance().UpdateSecretKey(metaData, randomKey)); - EXPECT_FALSE(CryptoManager::GetInstance().UpdateSecretKey(metaData, randomKey, CryptoManager::CLONE_SECRET_KEY)); + metaData.bundleName = TEST_BUNDLE_NAME; + metaData.storeId = TEST_STORE_NAME; + metaData.user = TEST_USERID; + metaData.area = CryptoManager::Area::EL4; + CryptoManager::GetInstance().UpdateSecretMeta(randomKey, metaData, metaData.GetSecretKey(), secretKey); + ASSERT_FALSE(secretKey.sKey.empty()); + ASSERT_FALSE(secretKey.nonce.empty()); + ASSERT_EQ(secretKey.area, metaData.area); } -} // namespace DistributedDataTest -} // namespace OHOS::Test +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/data_proxy_handle_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_proxy_handle_test.cpp new file mode 100644 index 00000000..20ca8dd8 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/data_proxy_handle_test.cpp @@ -0,0 +1,494 @@ +/* +* 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. +*/ +#define LOG_TAG "DataShareProxyHandleTest" + +#include "data_share_service_impl.h" + +#include + +#include "accesstoken_kit.h" +#include "dataproxy_handle_common.h" +#include "hap_token_info.h" +#include "ipc_skeleton.h" +#include "iservice_registry.h" +#include "log_print.h" +#include "proxy_data_manager.h" +#include "system_ability_definition.h" +#include "token_setproc.h" + +using namespace testing::ext; +using namespace OHOS::DataShare; +using namespace OHOS::DistributedData; +using namespace OHOS::Security::AccessToken; + +namespace OHOS::Test { +using OHOS::DataShare::LogLabel; +class DataShareProxyHandleTest : public testing::Test { +public: + static constexpr int64_t USER_TEST = 100; + std::string TEST_URI1 = "datashareproxy://com.test.dataprxoyhandle/test1"; + std::string TEST_URI2 = "datashareproxy://com.test.dataprxoyhandle/test2"; + std::string TEST_URI3 = "datashareproxy://com.test.dataprxoyhandle/test3"; + std::string TEST_URI_OTHER = "datashareproxy://com.test.dataprxoyhandle.other/test"; + // value1, value2, value3 are the values in profile + DataProxyValue VALUE1 = "value1"; + DataProxyValue VALUE2 = "value2"; + DataProxyValue VALUE3 = "value3"; + std::string APPIDENTIFIER1 = "appIdentifier1"; + std::string APPIDENTIFIER2 = "appIdentifier2"; + std::string APPIDENTIFIER3 = "appIdentifier3"; + std::string BUNDLE_NAME = "com.test.dataprxoyhandle"; + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetSelfTokenInfo(int32_t user); + void SetUp(); + void TearDown(); +}; + +void DataShareProxyHandleTest::SetUp(void) +{ + HapInfoParams info = { + .userID = USER_TEST, + .bundleName = BUNDLE_NAME, + .instIndex = 0, + .appIDDesc = BUNDLE_NAME + }; + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED", + .bundleName = BUNDLE_NAME, + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = BUNDLE_NAME, + .descriptionId = 1 + } + }, + .permStateList = { + { + .permissionName = "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + } + } + }; + AccessTokenKit::AllocHapToken(info, policy); + auto testTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID( + info.userID, info.bundleName, info.instIndex); + SetSelfTokenID(testTokenId); +} + +void DataShareProxyHandleTest::TearDown(void) +{ + auto tokenId = AccessTokenKit::GetHapTokenID(USER_TEST, "com.test.dataprxoyhandle", 0); + AccessTokenKit::DeleteToken(tokenId); +} + +/** +* @tc.name: OnAppInstallTest001 +* @tc.desc: test receive app install event +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, OnAppInstallTest001, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest OnAppInstallTest001 start"); + auto testTokenId = GetSelfTokenID(); + ProxyDataManager::GetInstance().OnAppInstall(BUNDLE_NAME, USER_TEST, 0, testTokenId); + DataShareServiceImpl dataShareServiceImpl; + std::vector uris = { TEST_URI1, TEST_URI2 }; + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + for (auto const &result : getResults) { + EXPECT_EQ(result.result_, OHOS::DataShare::SUCCESS); + } + // see details in profile + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].value_, VALUE1); + EXPECT_EQ(getResults[0].allowList_.size(), 1); + + EXPECT_EQ(getResults[1].uri_, TEST_URI2); + EXPECT_EQ(getResults[1].value_, VALUE2); + EXPECT_EQ(getResults[1].allowList_.size(), 1); + + auto results = dataShareServiceImpl.DeleteProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[1].uri_, TEST_URI2); + for (auto const &result : results) { + EXPECT_EQ(result.result_, OHOS::DataShare::SUCCESS); + } + ZLOGI("DataShareProxyHandleTest OnAppInstallTest001 end"); +} + +/** +* @tc.name: OnAppInstallTest001 +* @tc.desc: test receive app uninstall event +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, OnAppUninstallTest001, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest OnAppUninstallTest001 start"); + DataShareServiceImpl dataShareServiceImpl; + std::vector proxyDatas; + std::vector allowList = { APPIDENTIFIER1 }; + proxyDatas.emplace_back(TEST_URI1, VALUE1, allowList); + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + auto results = dataShareServiceImpl.PublishProxyData(proxyDatas, config); + ASSERT_EQ(results.size(), proxyDatas.size()); + for (auto const &result : results) { + EXPECT_EQ(result.result_, OHOS::DataShare::SUCCESS); + } + EXPECT_EQ(results[0].uri_, TEST_URI1); + + std::vector uris = { TEST_URI1 }; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + for (auto const &result : getResults) { + EXPECT_EQ(result.result_, OHOS::DataShare::SUCCESS); + } + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].value_, VALUE1); + EXPECT_EQ(getResults[0].allowList_.size(), 1); + + auto testTokenId = GetSelfTokenID(); + ProxyDataManager::GetInstance().OnAppUninstall(BUNDLE_NAME, USER_TEST, 0, testTokenId); + + getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + for (auto const &result : getResults) { + EXPECT_EQ(result.result_, OHOS::DataShare::URI_NOT_EXIST); + } + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + ZLOGI("DataShareProxyHandleTest OnAppUninstallTest001 end"); +} + +/** +* @tc.name: OnAppUpdate001 +* @tc.desc: test receive app update event +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, OnAppUpdateTest001, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest OnAppUpdateTest001 start"); + DataShareServiceImpl dataShareServiceImpl; + std::vector proxyDatas; + std::vector allowList = { APPIDENTIFIER3 }; + proxyDatas.emplace_back(TEST_URI3, VALUE3, allowList); + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + auto results = dataShareServiceImpl.PublishProxyData(proxyDatas, config); + ASSERT_EQ(results.size(), proxyDatas.size()); + for (auto const &result : results) { + EXPECT_EQ(result.result_, OHOS::DataShare::SUCCESS); + } + EXPECT_EQ(results[0].uri_, TEST_URI3); + + std::vector uris = { TEST_URI3 }; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + for (auto const &result : getResults) { + EXPECT_EQ(result.result_, OHOS::DataShare::SUCCESS); + } + EXPECT_EQ(getResults[0].uri_, TEST_URI3); + EXPECT_EQ(getResults[0].value_, VALUE3); + EXPECT_EQ(getResults[0].allowList_.size(), 1); + + auto testTokenId = GetSelfTokenID(); + ProxyDataManager::GetInstance().OnAppUpdate(BUNDLE_NAME, USER_TEST, 0, testTokenId); + + std::vector urisAfterUpdate = { TEST_URI1, TEST_URI2, TEST_URI3 }; + getResults = dataShareServiceImpl.GetProxyData(urisAfterUpdate, config); + ASSERT_EQ(getResults.size(), urisAfterUpdate.size()); + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].result_, OHOS::DataShare::SUCCESS); + EXPECT_EQ(getResults[1].uri_, TEST_URI2); + EXPECT_EQ(getResults[1].result_, OHOS::DataShare::SUCCESS); + EXPECT_EQ(getResults[2].uri_, TEST_URI3); + EXPECT_EQ(getResults[2].result_, OHOS::DataShare::URI_NOT_EXIST); + + std::vector urisToDelete = { TEST_URI1, TEST_URI2 }; + results = dataShareServiceImpl.DeleteProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[1].uri_, TEST_URI2); + for (auto const &result : results) { + EXPECT_EQ(result.result_, OHOS::DataShare::SUCCESS); + } + ZLOGI("DataShareProxyHandleTest OnAppUpdateTest001 end"); +} + +/** +* @tc.name: PublishProxyData001 +* @tc.desc: test publish proxyData with string value function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, PublishProxyData001, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest PublishProxyData001 start"); + DataShareServiceImpl dataShareServiceImpl; + std::vector proxyDatas; + DataProxyValue strValue = "strValue"; + std::vector allowList = { APPIDENTIFIER1 }; + proxyDatas.emplace_back(TEST_URI1, strValue, allowList); + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + auto results = dataShareServiceImpl.PublishProxyData(proxyDatas, config); + ASSERT_EQ(results.size(), proxyDatas.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::SUCCESS); + + std::vector uris = { TEST_URI1 }; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].result_, OHOS::DataShare::SUCCESS); + EXPECT_EQ(getResults[0].value_, strValue); + EXPECT_EQ(getResults[0].allowList_.size(), 1); + + results = dataShareServiceImpl.DeleteProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::SUCCESS); + ZLOGI("DataShareProxyHandleTest PublishProxyData001 end"); +} + +/** +* @tc.name: PublishProxyData002 +* @tc.desc: test publish proxyData with int value function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, PublishProxyData002, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest PublishProxyData002 start"); + DataShareServiceImpl dataShareServiceImpl; + std::vector proxyDatas; + DataProxyValue intValue = 100; + std::vector allowList = { APPIDENTIFIER1 }; + proxyDatas.emplace_back(TEST_URI1, intValue, allowList); + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + auto results = dataShareServiceImpl.PublishProxyData(proxyDatas, config); + ASSERT_EQ(results.size(), proxyDatas.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::SUCCESS); + + std::vector uris = { TEST_URI1 }; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].result_, OHOS::DataShare::SUCCESS); + EXPECT_EQ(getResults[0].value_, intValue); + EXPECT_EQ(getResults[0].allowList_.size(), 1); + + results = dataShareServiceImpl.DeleteProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::SUCCESS); + ZLOGI("DataShareProxyHandleTest PublishProxyData002 end"); +} + +/** +* @tc.name: PublishProxyData003 +* @tc.desc: test publish proxyData with double value function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, PublishProxyData003, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest PublishProxyData003 start"); + DataShareServiceImpl dataShareServiceImpl; + std::vector proxyDatas; + DataProxyValue fValue = 100.00; + std::vector allowList = { APPIDENTIFIER1 }; + proxyDatas.emplace_back(TEST_URI1, fValue, allowList); + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + auto results = dataShareServiceImpl.PublishProxyData(proxyDatas, config); + ASSERT_EQ(results.size(), proxyDatas.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::SUCCESS); + + std::vector uris = { TEST_URI1 }; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].result_, OHOS::DataShare::SUCCESS); + EXPECT_EQ(getResults[0].value_, fValue); + EXPECT_EQ(getResults[0].allowList_.size(), 1); + + results = dataShareServiceImpl.DeleteProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::SUCCESS); + ZLOGI("DataShareProxyHandleTest PublishProxyData003 end"); +} + +/** +* @tc.name: PublishProxyData004 +* @tc.desc: test publish proxyData with bool value function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, PublishProxyData004, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest PublishProxyData004 start"); + DataShareServiceImpl dataShareServiceImpl; + std::vector proxyDatas; + DataProxyValue boolValue = true; + std::vector allowList = { APPIDENTIFIER1 }; + proxyDatas.emplace_back(TEST_URI1, boolValue, allowList); + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + auto results = dataShareServiceImpl.PublishProxyData(proxyDatas, config); + ASSERT_EQ(results.size(), proxyDatas.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::SUCCESS); + + std::vector uris = { TEST_URI1 }; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].result_, OHOS::DataShare::SUCCESS); + EXPECT_EQ(getResults[0].value_, boolValue); + EXPECT_EQ(getResults[0].allowList_.size(), 1); + + results = dataShareServiceImpl.DeleteProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::SUCCESS); + ZLOGI("DataShareProxyHandleTest PublishProxyData004 end"); +} + +/** +* @tc.name: PublishProxyData005 +* @tc.desc: test publish proxyData of other bundle function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, PublishProxyData005, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest PublishProxyData005 start"); + DataShareServiceImpl dataShareServiceImpl; + std::vector proxyDatas; + DataProxyValue boolValue = true; + std::vector allowList = { APPIDENTIFIER1 }; + proxyDatas.emplace_back(TEST_URI_OTHER, boolValue, allowList); + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + std::vector uris = { TEST_URI_OTHER }; + auto results = dataShareServiceImpl.PublishProxyData(proxyDatas, config); + ASSERT_EQ(results.size(), proxyDatas.size()); + EXPECT_EQ(results[0].uri_, TEST_URI_OTHER); + EXPECT_EQ(results[0].result_, OHOS::DataShare::NO_PERMISSION); + ZLOGI("DataShareProxyHandleTest PublishProxyData005 end"); +} + +/** +* @tc.name: DeleteProxyData001 +* @tc.desc: test delete proxyData which is not published function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, DeleteProxyData001, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest DeleteProxyData001 start"); + DataShareServiceImpl dataShareServiceImpl; + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + std::vector uris = { TEST_URI1 }; + auto results = dataShareServiceImpl.DeleteProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + EXPECT_EQ(results[0].uri_, TEST_URI1); + EXPECT_EQ(results[0].result_, OHOS::DataShare::URI_NOT_EXIST); + ZLOGI("DataShareProxyHandleTest DeleteProxyData001 end"); +} + +/** +* @tc.name: DeleteProxyData002 +* @tc.desc: test delete proxyData without permission function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, DeleteProxyData002, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest DeleteProxyData002 start"); + DataShareServiceImpl dataShareServiceImpl; + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + std::vector uris = { TEST_URI_OTHER }; + auto results = dataShareServiceImpl.DeleteProxyData(uris, config); + ASSERT_EQ(results.size(), uris.size()); + EXPECT_EQ(results[0].uri_, TEST_URI_OTHER); + EXPECT_EQ(results[0].result_, OHOS::DataShare::NO_PERMISSION); + ZLOGI("DataShareProxyHandleTest DeleteProxyData002 end"); +} + +/** +* @tc.name: GetProxyData001 +* @tc.desc: test get proxyData without permission function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, GetProxyData001, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest GetProxyData001 start"); + DataShareServiceImpl dataShareServiceImpl; + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + std::vector uris = { TEST_URI1 }; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].result_, OHOS::DataShare::URI_NOT_EXIST); + ZLOGI("DataShareProxyHandleTest GetProxyData001 end"); +} + +/** +* @tc.name: GetProxyData002 +* @tc.desc: test get proxyData without permission function +* @tc.type: FUNC +* @tc.require:SQL +*/ +HWTEST_F(DataShareProxyHandleTest, GetProxyData002, TestSize.Level1) +{ + ZLOGI("DataShareProxyHandleTest GetProxyData002 start"); + auto tokenId = AccessTokenKit::GetHapTokenID(USER_TEST, BUNDLE_NAME, 0); + AccessTokenKit::DeleteToken(tokenId); + DataShareServiceImpl dataShareServiceImpl; + DataProxyConfig config; + config.type_ = DataProxyType::SHARED_CONFIG; + std::vector uris = { TEST_URI1 }; + auto getResults = dataShareServiceImpl.GetProxyData(uris, config); + ASSERT_EQ(getResults.size(), uris.size()); + EXPECT_EQ(getResults[0].uri_, TEST_URI1); + EXPECT_EQ(getResults[0].result_, OHOS::DataShare::NO_PERMISSION); + SetSelfTokenID(tokenId); + ZLOGI("DataShareProxyHandleTest GetProxyData002 end"); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/data_share_common_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_common_test.cpp index ad14f7d3..8a250b4e 100644 --- a/datamgr_service/services/distributeddataservice/service/test/data_share_common_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_common_test.cpp @@ -16,9 +16,14 @@ #include #include +#include "extension_connect_adaptor.h" #include "data_share_profile_config.h" #include "div_strategy.h" #include "log_print.h" +#include "rdb_delegate.h" +#include "rdb_subscriber_manager.h" +#include "scheduler_manager.h" +#include "seq_strategy.h" #include "strategy.h" namespace OHOS::Test { @@ -89,4 +94,519 @@ HWTEST_F(DataShareCommonTest, DivStrategy003, TestSize.Level1) EXPECT_EQ(result, false); ZLOGI("DataShareCommonTest DivStrategy003 end"); } + +/** +* @tc.name: SeqStrategyInit001 +* @tc.desc: test SeqStrategyInit function when item is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a seqStrategy object and strategy2 = nullptr + 2.call Init function +* @tc.experct: Init failed and return false +*/ +HWTEST_F(DataShareCommonTest, SeqStrategyInit001, TestSize.Level1) +{ + ZLOGI("SeqStrategyInit001 start"); + Strategy* strategy1 = new Strategy(); + Strategy* strategy2 = nullptr; + SeqStrategy seqStrategy; + bool result = seqStrategy.Init({strategy1, strategy2}); + EXPECT_FALSE(result); + delete strategy1; + ZLOGI("SeqStrategyInit001 end"); +} + +/** +* @tc.name: DoConnect001 +* @tc.desc: test DoConnect function when callback_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a ExtensionConnectAdaptor object and callback = nullptr + 2.call DoConnect function +* @tc.experct: DoConnect failed and return false +*/ +HWTEST_F(DataShareCommonTest, DoConnect001, TestSize.Level1) +{ + ZLOGI("DoConnect001 start"); + std::string uri = "testUri"; + std::string bundleName = "testBundle"; + AAFwk::WantParams wantParams; + ExtensionConnectAdaptor extensionConnectAdaptor; + bool result = extensionConnectAdaptor.DoConnect(uri, bundleName, wantParams); + EXPECT_FALSE(result); + ZLOGI("DoConnect001 end"); +} + +/** +* @tc.name: InsertEx001 +* @tc.desc: test InsertEx function when store_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a rdbDelegate object and store_ = nullptr + 2.call InsertEx function +* @tc.experct: InsertEx failed and return E_DB_ERROR +*/ +HWTEST_F(DataShareCommonTest, InsertEx001, TestSize.Level1) +{ + ZLOGI("InsertEx001 start"); + DistributedData::StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = "test"; + metaData.area = 1; + int version = 0; + bool registerFunction = false; + std::string extUri = "uri"; + std::string backup = "backup"; + RdbDelegate rdbDelegate; + rdbDelegate.Init(metaData, version, registerFunction, extUri, backup); + rdbDelegate.store_ = nullptr; + std::string tableName = ""; + DataShare::DataShareValuesBucket valuesBucket; + std::string name0 = ""; + valuesBucket.Put("", name0); + auto result = rdbDelegate.InsertEx(tableName, valuesBucket); + EXPECT_EQ(result.first, E_DB_ERROR); + ZLOGI("InsertEx001 end"); +} + +/** +* @tc.name: UpdateEx001 +* @tc.desc: test UpdateEx function when store_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a RdbDelegate object and store_ = nullptr + 2.call UpdateEx function +* @tc.experct: UpdateEx failed and return E_DB_ERROR +*/ +HWTEST_F(DataShareCommonTest, UpdateEx001, TestSize.Level1) +{ + ZLOGI("UpdateEx001 start"); + DistributedData::StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = "test"; + metaData.area = 1; + int version = 0; + bool registerFunction = false; + std::string extUri = "uri"; + std::string backup = "backup"; + RdbDelegate rdbDelegate; + rdbDelegate.Init(metaData, version, registerFunction, extUri, backup); + rdbDelegate.store_ = nullptr; + std::string tableName = ""; + DataShare::DataShareValuesBucket valuesBucket; + std::string name0 = ""; + valuesBucket.Put("", name0); + DataSharePredicates predicate; + auto result = rdbDelegate.UpdateEx(tableName, predicate, valuesBucket); + EXPECT_EQ(result.first, E_DB_ERROR); + ZLOGI("UpdateEx001 end"); +} + +/** +* @tc.name: DeleteEx001 +* @tc.desc: test DeleteEx function when store_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a RdbDelegate object and store_ = nullptr + 2.call DeleteEx function +* @tc.experct: DeleteEx failed and return E_DB_ERROR +*/ +HWTEST_F(DataShareCommonTest, DeleteEx001, TestSize.Level1) +{ + ZLOGI("DeleteEx001 start"); + DistributedData::StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = "test"; + metaData.area = 1; + int version = 0; + bool registerFunction = false; + std::string extUri = "uri"; + std::string backup = "backup"; + RdbDelegate rdbDelegate; + rdbDelegate.Init(metaData, version, registerFunction, extUri, backup); + rdbDelegate.store_ = nullptr; + std::string tableName = ""; + DataSharePredicates predicate; + auto result = rdbDelegate.DeleteEx(tableName, predicate); + EXPECT_EQ(result.first, E_DB_ERROR); + ZLOGI("DeleteEx001 end"); +} + +/** +* @tc.name: Query001 +* @tc.desc: test Query function when store_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a RdbDelegate object and store_ = nullptr + 2.call Query function +* @tc.experct: Query failed and return errCode +*/ +HWTEST_F(DataShareCommonTest, Query001, TestSize.Level1) +{ + ZLOGI("Query001 start"); + DistributedData::StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = "test"; + metaData.area = 1; + int version = 0; + bool registerFunction = false; + std::string extUri = "uri"; + std::string backup = "backup"; + RdbDelegate rdbDelegate; + rdbDelegate.Init(metaData, version, registerFunction, extUri, backup); + rdbDelegate.store_ = nullptr; + std::string tableName = ""; + DataSharePredicates predicate; + std::vector columns; + int32_t callingPid = 1; + uint32_t callingTokenId = 1; + auto result = rdbDelegate.Query(tableName, predicate, columns, callingPid, callingTokenId); + EXPECT_EQ(result.first, rdbDelegate.errCode_); + ZLOGI("Query001 end"); +} + +/** +* @tc.name: Query002 +* @tc.desc: test Query function when store_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a RdbDelegate object and store_ = nullptr + 2.call Query function +* @tc.experct: Query failed and return "" +*/ +HWTEST_F(DataShareCommonTest, Query002, TestSize.Level1) +{ + ZLOGI("Query002 start"); + DistributedData::StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = "test"; + metaData.area = 1; + int version = 0; + bool registerFunction = false; + std::string extUri = "uri"; + std::string backup = "backup"; + RdbDelegate rdbDelegate; + rdbDelegate.Init(metaData, version, registerFunction, extUri, backup); + rdbDelegate.store_ = nullptr; + std::string sql = "testsql"; + std::vector selectionArgs; + auto result = rdbDelegate.Query(sql, selectionArgs); + EXPECT_EQ(result, ""); + ZLOGI("Query002 end"); +} + +/** +* @tc.name: QuerySql001 +* @tc.desc: test QuerySql function when store_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a RdbDelegate object and store_ = nullptr + 2.call QuerySql function +* @tc.experct: QuerySql failed and return nullptr +*/ +HWTEST_F(DataShareCommonTest, QuerySql001, TestSize.Level1) +{ + ZLOGI("QuerySql001 start"); + DistributedData::StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = "test"; + metaData.area = 1; + int version = 0; + bool registerFunction = false; + std::string extUri = "uri"; + std::string backup = "backup"; + RdbDelegate rdbDelegate; + rdbDelegate.Init(metaData, version, registerFunction, extUri, backup); + rdbDelegate.store_ = nullptr; + std::string sql = "testsql"; + auto result = rdbDelegate.QuerySql(sql); + EXPECT_EQ(result, nullptr); + ZLOGI("QuerySql001 end"); +} + +/** +* @tc.name: UpdateSql001 +* @tc.desc: test UpdateSql function when store_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a RdbDelegate object and store_ = nullptr + 2.call UpdateSql function +* @tc.experct: UpdateSql failed and return E_ERROR +*/ +HWTEST_F(DataShareCommonTest, UpdateSql001, TestSize.Level1) +{ + ZLOGI("UpdateSql001 start"); + DistributedData::StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = "test"; + metaData.area = 1; + int version = 0; + bool registerFunction = false; + std::string extUri = "uri"; + std::string backup = "backup"; + RdbDelegate rdbDelegate; + rdbDelegate.Init(metaData, version, registerFunction, extUri, backup); + rdbDelegate.store_ = nullptr; + std::string sql = "testsql"; + auto result = rdbDelegate.UpdateSql(sql); + EXPECT_EQ(result.first, OHOS::DataShare::E_ERROR); + ZLOGI("UpdateSql001 end"); +} + +/** +* @tc.name: EraseTimerTaskId001 +* @tc.desc: test EraseTimerTaskId function when not find key +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object and timerCache_ is null + 2.call EraseTimerTaskId function +* @tc.experct: not find key, EraseTimerTaskId failed and return -1 +*/ +HWTEST_F(DataShareCommonTest, EraseTimerTaskId001, TestSize.Level1) +{ + ZLOGI("EraseTimerTaskId001 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + int64_t result = manager.EraseTimerTaskId(key); + EXPECT_EQ(result, -1); + ZLOGI("EraseTimerTaskId001 end"); +} + +/** +* @tc.name: EraseTimerTaskId002 +* @tc.desc: test EraseTimerTaskId function when find key +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object and timerCache_[key] = timeid + 2.call EraseTimerTaskId function +* @tc.experct: find key, EraseTimerTaskId success and return timeid +*/ +HWTEST_F(DataShareCommonTest, EraseTimerTaskId002, TestSize.Level1) +{ + ZLOGI("EraseTimerTaskId002 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + int64_t timeid = 1; + manager.timerCache_[key] = timeid; + int64_t result = manager.EraseTimerTaskId(key); + EXPECT_EQ(result, timeid); + ZLOGI("EraseTimerTaskId002 end"); +} + +/** +* @tc.name: GetSchedulerStatus001 +* @tc.desc: test GetSchedulerStatus function when not find key +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object and schedulerStatusCache_ is null + 2.call GetSchedulerStatus function +* @tc.experct: not find key, GetSchedulerStatus failed and return false +*/ +HWTEST_F(DataShareCommonTest, GetSchedulerStatus001, TestSize.Level1) +{ + ZLOGI("GetSchedulerStatus001 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + bool result = manager.GetSchedulerStatus(key); + EXPECT_FALSE(result); + ZLOGI("GetSchedulerStatus001 end"); +} + +/** +* @tc.name: GetSchedulerStatus002 +* @tc.desc: test GetSchedulerStatus function when find key +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object and schedulerStatusCache_[key] = true; + 2.call GetSchedulerStatus function +* @tc.experct: find key, GetSchedulerStatus success and return true +*/ +HWTEST_F(DataShareCommonTest, GetSchedulerStatus002, TestSize.Level1) +{ + ZLOGI("GetSchedulerStatus002 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + manager.schedulerStatusCache_[key] = true; + bool result = manager.GetSchedulerStatus(key); + EXPECT_TRUE(result); + ZLOGI("GetSchedulerStatus002 end"); +} + +/** +* @tc.name: RemoveTimer001 +* @tc.desc: test RemoveTimer function when executor_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object what timerCache_[key] = 1 and executor_ is nullptr + 2.call RemoveTimer function to remove timer +* @tc.experct: RemoveTimer failed and timerCache_ is not null +*/ +HWTEST_F(DataShareCommonTest, RemoveTimer001, TestSize.Level1) +{ + ZLOGI("RemoveTimer001 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + manager.executor_ = nullptr; + manager.timerCache_[key] = 1; + manager.RemoveTimer(key); + EXPECT_NE(manager.timerCache_.find(key), manager.timerCache_.end()); + ZLOGI("RemoveTimer001 end"); +} + +/** +* @tc.name: RemoveTimer002 +* @tc.desc: test RemoveTimer function when executor_ is not nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object and timerCache_[key] = 1 and executor_ is not nullptr + 2.call RemoveTimer function to remove timer +* @tc.experct: RemoveTimer success and timerCache_ is null +*/ +HWTEST_F(DataShareCommonTest, RemoveTimer002, TestSize.Level1) +{ + ZLOGI("RemoveTimer002 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + manager.executor_ = std::make_shared(5, 3); + manager.timerCache_[key] = 1; + manager.RemoveTimer(key); + EXPECT_EQ(manager.timerCache_.find(key), manager.timerCache_.end()); + ZLOGI("RemoveTimer002 end"); +} + +/** +* @tc.name: ClearTimer001 +* @tc.desc: test ClearTimer function when executor_ is nullptr +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object what timerCache_[key] = 1 and executor_ is nullptr + 2.call ClearTimer function to clear timer +* @tc.experct: ClearTimer failed and timerCache_ is not empty +*/ +HWTEST_F(DataShareCommonTest, ClearTimer001, TestSize.Level1) +{ + ZLOGI("ClearTimer001 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + manager.executor_ = nullptr; + manager.timerCache_[key] = 1; + manager.ClearTimer(); + EXPECT_FALSE(manager.timerCache_.empty()); + ZLOGI("ClearTimer001 end"); +} + +/** +* @tc.name: ClearTimer002 +* @tc.desc: test ClearTimer function when executor_ is not nullptr and find key +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object and timerCache_[key] = 1 and executor_ is not nullptr + 2.call ClearTimer function to clear timer +* @tc.experct: ClearTimer success and timerCache_ is empty +*/ +HWTEST_F(DataShareCommonTest, ClearTimer002, TestSize.Level1) +{ + ZLOGI("ClearTimer002 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + manager.executor_ = std::make_shared(5, 3); + manager.timerCache_[key] = 1; + manager.ClearTimer(); + EXPECT_TRUE(manager.timerCache_.empty()); + ZLOGI("ClearTimer002 end"); +} + +/** +* @tc.name: ClearTimer003 +* @tc.desc: test ClearTimer function when executor_ is not nullptr and not find key +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a SchedulerManager object and timerCache_ is null + 2.call ClearTimer function +* @tc.experct: ClearTimer failed and timerCache_ is empty +*/ +HWTEST_F(DataShareCommonTest, ClearTimer003, TestSize.Level1) +{ + ZLOGI("ClearTimer003 start"); + Key key("uri1", 1, "name1"); + auto& manager = SchedulerManager::GetInstance(); + manager.executor_ = std::make_shared(5, 3); + manager.ClearTimer(); + EXPECT_TRUE(manager.timerCache_.empty()); + ZLOGI("ClearTimer003 end"); +} + +/** + * @tc.name: DBDelegateTest001 + * @tc.desc: do nothing when delegate already inited + * @tc.type: FUNC + */ +HWTEST_F(DataShareCommonTest, DBDelegateTest001, TestSize.Level0) { + RdbDelegate delegate; + DistributedData::StoreMetaData meta; + meta.tokenId = 1; + + delegate.isInited_ = true; + delegate.Init({}, 0, false, "extUri", "backup"); + + EXPECT_TRUE(delegate.isInited_); + EXPECT_EQ(delegate.tokenId_, 0); + EXPECT_EQ(delegate.extUri_, ""); + EXPECT_EQ(delegate.backup_, ""); +} + +/** + * @tc.name : DBDelegateTest002 + * @tc.number: init members in delegate init + * @tc.type: FUNC + */ +HWTEST_F(DataShareCommonTest, DBDelegateTest002, TestSize.Level0) { + RdbDelegate delegate; + DistributedData::StoreMetaData meta; + meta.tokenId = 1; + + delegate.isInited_ = false; + delegate.Init(meta, 0, false, "extUri", "backup"); + + EXPECT_FALSE(delegate.isInited_); + EXPECT_EQ(delegate.tokenId_, meta.tokenId); + EXPECT_EQ(delegate.extUri_, "extUri"); + EXPECT_EQ(delegate.backup_, "backup"); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/data_share_scheduler_manager_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_scheduler_manager_test.cpp new file mode 100644 index 00000000..0a8be958 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_scheduler_manager_test.cpp @@ -0,0 +1,160 @@ +/* +* 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. +*/ +#define LOG_TAG "DataShareSchedulerManagerTest" + +#include + +#include "log_print.h" +#include "db_delegate.h" +#include "template_data.h" +#include "scheduler_manager.h" + +namespace OHOS::Test { +using namespace OHOS::DataShare; +using namespace testing::ext; +class DataShareSchedulerManagerTest : public testing::Test { +public: + static constexpr int64_t USER_TEST = 100; + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +/** +* @tc.name: EnableScheduler001 +* @tc.desc: test EnableScheduler function when not find key +* @tc.type: FUNC +* @tc.require: +* @tc.precon: None +* @tc.step: + 1.Add a template + 2.Creat a SchedulerManager object + 3.call Enable Scheduler function +* @tc.expect: not find key, Enable SchedulerStatus and GetSchedulerStatus return false +*/ +HWTEST_F(DataShareSchedulerManagerTest, EnableScheduler001, TestSize.Level1) +{ + ZLOGI("EnableScheduler001 start"); + Key key("uri1", 12345, "name1"); + Template tplt; + tplt.predicates_.emplace_back("test", "predicate test"); + tplt.scheduler_ = "scheduler test"; + std::string dataDir = "/data/service/el1/public/database/distributeddata/kvdb"; + std::shared_ptr executors = std::make_shared(1, 1); + auto kvDelegate = KvDBDelegate::GetInstance(dataDir, executors); + ASSERT_NE(kvDelegate, nullptr); + TemplateData data(key.uri, key.bundleName, key.subscriberId, USER_TEST, tplt); + auto ret = kvDelegate->Upsert(KvDBDelegate::TEMPLATE_TABLE, data); + EXPECT_EQ(ret.first, OHOS::DataShare::E_OK); + EXPECT_GT(ret.second, 0); + + auto& manager = SchedulerManager::GetInstance(); + DistributedData::StoreMetaData metaData; + manager.Enable(key, USER_TEST, metaData); + bool status = manager.GetSchedulerStatus(key); + EXPECT_FALSE(status); + + ret = kvDelegate->Delete(KvDBDelegate::TEMPLATE_TABLE, + static_cast(Id(TemplateData::GenId(key.uri, key.bundleName, key.subscriberId), USER_TEST))); + EXPECT_EQ(ret.first, OHOS::DataShare::E_OK); + EXPECT_GT(ret.second, 0); + ZLOGI("EnableScheduler001 end"); +} + +/** +* @tc.name: DisableScheduler001 +* @tc.desc: test EnableScheduler function when not find key +* @tc.type: FUNC +* @tc.require: +* @tc.precon: None +* @tc.step: + 1.Add a template + 2.Creat a SchedulerManager object + 3.call Disable Scheduler function +* @tc.expect: not find key, Disable SchedulerStatus and GetSchedulerStatus return false +*/ +HWTEST_F(DataShareSchedulerManagerTest, DisableScheduler001, TestSize.Level1) +{ + ZLOGI("DisableScheduler001 start"); + Key key("uri1", 12345, "name1"); + Template tplt; + tplt.predicates_.emplace_back("test", "predicate test"); + tplt.scheduler_ = "scheduler test"; + std::string dataDir = "/data/service/el1/public/database/distributeddata/kvdb"; + std::shared_ptr executors = std::make_shared(1, 1); + auto kvDelegate = KvDBDelegate::GetInstance(dataDir, executors); + ASSERT_NE(kvDelegate, nullptr); + TemplateData data(key.uri, key.bundleName, key.subscriberId, USER_TEST, tplt); + auto ret = kvDelegate->Upsert(KvDBDelegate::TEMPLATE_TABLE, data); + EXPECT_EQ(ret.first, OHOS::DataShare::E_OK); + EXPECT_GT(ret.second, 0); + + auto& manager = SchedulerManager::GetInstance(); + manager.Disable(key); + bool status = manager.GetSchedulerStatus(key); + EXPECT_FALSE(status); + + ret = kvDelegate->Delete(KvDBDelegate::TEMPLATE_TABLE, + static_cast(Id(TemplateData::GenId(key.uri, key.bundleName, key.subscriberId), USER_TEST))); + EXPECT_EQ(ret.first, OHOS::DataShare::E_OK); + EXPECT_GT(ret.second, 0); + ZLOGI("DisableScheduler001 end"); +} + +/** +* @tc.name: ChangeStatusCacheSize001 +* @tc.desc: test statusCache size changed when getting scheduler status +* @tc.type: FUNC +* @tc.require: +* @tc.precon: None +* @tc.step: + 1.Add a template + 2.Creat a SchedulerManager object + 3.Change the size of statusCache + 4.call GetSchedulerStatus function +* @tc.expect: the size of SchedulerStatus changed and print log +*/ +HWTEST_F(DataShareSchedulerManagerTest, ChangeStatusCacheSize001, TestSize.Level1) +{ + ZLOGI("ChangeStatusCacheSize001 start"); + Key key("uri1", 12345, "name1"); + Template tplt; + tplt.predicates_.emplace_back("test", "predicate test"); + tplt.scheduler_ = "scheduler test"; + std::string dataDir = "/data/service/el1/public/database/distributeddata/kvdb"; + std::shared_ptr executors = std::make_shared(1, 1); + auto kvDelegate = KvDBDelegate::GetInstance(dataDir, executors); + ASSERT_NE(kvDelegate, nullptr); + TemplateData data(key.uri, key.bundleName, key.subscriberId, USER_TEST, tplt); + auto ret = kvDelegate->Upsert(KvDBDelegate::TEMPLATE_TABLE, data); + EXPECT_EQ(ret.first, OHOS::DataShare::E_OK); + EXPECT_GT(ret.second, 0); + + auto &manager = SchedulerManager::GetInstance(); + manager.Disable(key); + Key key2("testUri", 12345, "testName"); + manager.schedulerStatusCache_.emplace(key2, false); + bool status = manager.GetSchedulerStatus(key); + EXPECT_FALSE(status); + manager.schedulerStatusCache_.erase(key2); + + ret = kvDelegate->Delete(KvDBDelegate::TEMPLATE_TABLE, + static_cast(Id(TemplateData::GenId(key.uri, key.bundleName, key.subscriberId), USER_TEST))); + EXPECT_EQ(ret.first, OHOS::DataShare::E_OK); + EXPECT_GT(ret.second, 0); + ZLOGI("ChangeStatusCacheSize001 end"); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/data_share_service_impl_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_service_impl_test.cpp index a14d505b..4574112b 100644 --- a/datamgr_service/services/distributeddataservice/service/test/data_share_service_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_service_impl_test.cpp @@ -20,12 +20,15 @@ #include #include "accesstoken_kit.h" +#include "account_delegate_mock.h" #include "data_share_service_stub.h" +#include "device_manager_adapter.h" #include "dump/dump_manager.h" #include "hap_token_info.h" #include "ipc_skeleton.h" #include "iservice_registry.h" #include "log_print.h" +#include "metadata/meta_data_manager.h" #include "system_ability_definition.h" #include "token_setproc.h" @@ -44,50 +47,58 @@ public: static constexpr int64_t USER_TEST = 100; static constexpr int64_t TEST_SUB_ID = 100; static constexpr uint32_t CUREEENT_USER_ID = 123; - static void SetUpTestCase(void){}; - static void TearDownTestCase(void){}; + static constexpr uint32_t NATIVE_USER_ID = 0; + static void SetUpTestCase(void) + { + accountDelegateMock = new (std::nothrow) AccountDelegateMock(); + if (accountDelegateMock != nullptr) { + AccountDelegate::instance_ = nullptr; + AccountDelegate::RegisterAccountInstance(accountDelegateMock); + } + } + static void TearDownTestCase(void) + { + if (accountDelegateMock != nullptr) { + delete accountDelegateMock; + accountDelegateMock = nullptr; + } + } + void SetSelfTokenInfo(int32_t user); void SetUp(); void TearDown(); + static inline AccountDelegateMock *accountDelegateMock = nullptr; }; -void DataShareServiceImplTest::SetUp(void) +void DataShareServiceImplTest::SetSelfTokenInfo(int32_t user) { - HapInfoParams info = { - .userID = USER_TEST, + HapInfoParams info = { .userID = user, .bundleName = "ohos.datasharetest.demo", .instIndex = 0, - .appIDDesc = "ohos.datasharetest.demo" - }; - HapPolicyParams policy = { - .apl = APL_NORMAL, + .appIDDesc = "ohos.datasharetest.demo" }; + HapPolicyParams policy = { .apl = APL_NORMAL, .domain = "test.domain", - .permList = { - { - .permissionName = "ohos.permission.test", - .bundleName = "ohos.datasharetest.demo", - .grantMode = 1, - .availableLevel = APL_NORMAL, - .label = "label", - .labelId = 1, - .description = "ohos.datasharetest.demo", - .descriptionId = 1 - } - }, - .permStateList = { - { - .permissionName = "ohos.permission.test", - .isGeneral = true, - .resDeviceID = { "local" }, - .grantStatus = { PermissionState::PERMISSION_GRANTED }, - .grantFlags = { 1 } - } - } - }; + .permList = { { .permissionName = "ohos.permission.test", + .bundleName = "ohos.datasharetest.demo", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "ohos.datasharetest.demo", + .descriptionId = 1 } }, + .permStateList = { { .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } } } }; AccessTokenKit::AllocHapToken(info, policy); - auto testTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID( - info.userID, info.bundleName, info.instIndex); + auto testTokenId = + Security::AccessToken::AccessTokenKit::GetHapTokenID(info.userID, info.bundleName, info.instIndex); SetSelfTokenID(testTokenId); } +void DataShareServiceImplTest::SetUp(void) +{ + SetSelfTokenInfo(USER_TEST); +} void DataShareServiceImplTest::TearDown(void) { @@ -146,10 +157,10 @@ HWTEST_F(DataShareServiceImplTest, NotifyChange001, TestSize.Level1) { DataShareServiceImpl dataShareServiceImpl; std::string uri = SLIENT_ACCESS_URI; - auto result = dataShareServiceImpl.NotifyChange(uri); + auto result = dataShareServiceImpl.NotifyChange(uri, USER_TEST); EXPECT_EQ(result, true); - result = dataShareServiceImpl.NotifyChange(""); + result = dataShareServiceImpl.NotifyChange("", USER_TEST); EXPECT_EQ(result, false); } @@ -324,13 +335,13 @@ HWTEST_F(DataShareServiceImplTest, SubscribePublishedData001, TestSize.Level1) auto tokenId = AccessTokenKit::GetHapTokenID(USER_TEST, "ohos.datasharetest.demo", 0); AccessTokenKit::DeleteToken(tokenId); - std::vector result = dataShareServiceImpl.SubscribePublishedData(uris, subscriberId, observer); + std::vector result = dataShareServiceImpl.SubscribePublishedData(uris, subscriberId, observer); EXPECT_NE(result.size(), uris.size()); for (auto const &operationResult : result) { EXPECT_EQ(operationResult.errCode_, 0); } - result = dataShareServiceImpl.UnsubscribePublishedData(uris, subscriberId); + result = dataShareServiceImpl.UnsubscribePublishedData(uris, subscriberId); EXPECT_NE(result.size(), uris.size()); for (auto const &operationResult : result) { EXPECT_EQ(operationResult.errCode_, 0); @@ -491,4 +502,65 @@ HWTEST_F(DataShareServiceImplTest, GetCallerInfo002, TestSize.Level1) EXPECT_EQ(result.first, false); ZLOGI("DataShareServiceImplTest GetCallerInfo002 end"); } + +/** +* @tc.name: GetSilentProxyStatus001 +* @tc.desc: test GetSilentProxyStatus001 function while creating helper +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(DataShareServiceImplTest, GetSilentProxyStatus001, TestSize.Level1) +{ + ZLOGI("DataShareServiceImplTest GetSilentProxyStatus001 start"); + SetSelfTokenInfo(NATIVE_USER_ID); + DataShareServiceImpl dataShareServiceImpl; + auto result = dataShareServiceImpl.GetSilentProxyStatus(SLIENT_ACCESS_URI, true); + EXPECT_EQ(result, OHOS::DataShare::E_OK); + + result = dataShareServiceImpl.GetSilentProxyStatus(SLIENT_ACCESS_URI + "?user=100", true); + EXPECT_EQ(result, OHOS::DataShare::E_OK); + SetSelfTokenInfo(USER_TEST); + ZLOGI("DataShareServiceImplTest GetSilentProxyStatus001 end"); +} + +/** +* @tc.name: DataProviderConfig001 +* @tc.desc: test get provider info function +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(DataShareServiceImplTest, DataProviderConfig001, TestSize.Level1) +{ + ZLOGI("DataShareServiceImplTest DataProviderConfig001 start"); + SetSelfTokenInfo(NATIVE_USER_ID); + auto testTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(NATIVE_USER_ID, BUNDLE_NAME, 0); + EXPECT_CALL(*accountDelegateMock, QueryForegroundUserId(testing::_)).Times(1).WillOnce(testing::Return(false)); + DataProviderConfig config(SLIENT_ACCESS_URI, testTokenId); + EXPECT_EQ(config.providerInfo_.uri, SLIENT_ACCESS_URI); + EXPECT_EQ(config.providerInfo_.currentUserId, NATIVE_USER_ID); + EXPECT_EQ(config.providerInfo_.visitedUserId, NATIVE_USER_ID); + SetSelfTokenInfo(USER_TEST); + ZLOGI("DataShareServiceImplTest DataProviderConfig001 end"); +} + +/** +* @tc.name: UpdateLaunchInfoMock001 +* @tc.desc: mock GetInstance return nullptr +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(DataShareServiceImplTest, UpdateLaunchInfo001, TestSize.Level1) +{ + ZLOGI("DataShareServiceImplTest UpdateLaunchInfo001 start"); + + DataShareServiceImpl dataShareServiceImpl; + // cover branch of config is nullptr + dataShareServiceImpl.UpdateLaunchInfo(); + + std::string prefix = StoreMetaData::GetPrefix({ DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid }); + std::vector storeMetaData; + MetaDataManager::GetInstance().LoadMeta(prefix, storeMetaData, true); + EXPECT_EQ(storeMetaData.size(), 0); + ZLOGI("DataShareServiceImplTest UpdateLaunchInfo001 end"); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/data_share_subscriber_managers_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_subscriber_managers_test.cpp index c5bccacf..63406f39 100644 --- a/datamgr_service/services/distributeddataservice/service/test/data_share_subscriber_managers_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_subscriber_managers_test.cpp @@ -110,9 +110,9 @@ HWTEST_F(DataShareSubscriberManagersTest, Add, TestSize.Level1) nodes.emplace_back(node2); Template tpl(nodes, "select name1 as name from TBL00"); DataShare::Key key(DATA_SHARE_URI_TEST, tpltId.subscriberId_, tpltId.bundleName_); - auto result = TemplateManager::GetInstance().Add(key, context->currentUserId, tpl); + auto result = TemplateManager::GetInstance().Add(key, context->visitedUserId, tpl); EXPECT_EQ(result, DataShare::E_ERROR); - result = TemplateManager::GetInstance().Delete(key, context->currentUserId); + result = TemplateManager::GetInstance().Delete(key, context->visitedUserId); EXPECT_EQ(result, DataShare::E_ERROR); } @@ -210,7 +210,7 @@ HWTEST_F(DataShareSubscriberManagersTest, IsNotifyOnEnabled, TestSize.Level1) sptr observer; std::vector val; std::map, std::vector> callbacks; - PublishedDataSubscriberManager::GetInstance().PutInto(callbacks, val, key, observer); + PublishedDataSubscriberManager::GetInstance().PutInto(callbacks, val, key, observer, context->visitedUserId); std::vector publishedKeys; PublishedDataSubscriberManager::GetInstance().SetObserversNotifiedOnEnabled(publishedKeys); uint32_t tokenId = AccessTokenKit::GetHapTokenID(USER_TEST, BUNDLE_NAME_TEST, USER_TEST); diff --git a/datamgr_service/services/distributeddataservice/service/test/data_share_sys_event_subscriber_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_sys_event_subscriber_test.cpp new file mode 100644 index 00000000..8e6097ef --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_sys_event_subscriber_test.cpp @@ -0,0 +1,67 @@ +/* +* 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. +*/ +#define LOG_TAG "DataShareSysEventSubscriberTest" + +#include "sys_event_subscriber.h" + +#include + +#include "data_share_service_impl.h" +#include "common_event_manager.h" +#include "common_event_support.h" +#include "log_print.h" +#include "mock/meta_data_manager_mock.h" +#include "proxy_data_manager.h" + +namespace OHOS::Test { +using namespace OHOS::DataShare; +using namespace testing::ext; +class DataShareSysEventSubscriberTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +/** +* @tc.name: OnBMSReady001 +* @tc.desc: test OnBMSReady func +* @tc.type: FUNC +*/ +HWTEST_F(DataShareSysEventSubscriberTest, OnBMSReady001, TestSize.Level1) +{ + ZLOGI("DataShareSysEventSubscriberTest OnBMSReady001 start"); + EventFwk::MatchingSkills testMatchingSkills; + testMatchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_BUNDLE_SCAN_FINISHED); + testMatchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED); + testMatchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); + EventFwk::CommonEventSubscribeInfo subscribeInfo(testMatchingSkills); + subscribeInfo.SetThreadMode(EventFwk::CommonEventSubscribeInfo::COMMON); + // executors not null + auto executors = std::make_shared(1, 0); + // make sysEventSubscriber not null + auto sysEventSubscriber = std::make_shared(subscribeInfo, executors);\ + ASSERT_NE(sysEventSubscriber, nullptr); + sysEventSubscriber->OnBMSReady(); + ASSERT_NE(sysEventSubscriber->executors_, nullptr); + + // cover executors == nullptr branch + sysEventSubscriber->executors_ = nullptr; + ASSERT_EQ(sysEventSubscriber->executors_, nullptr); + sysEventSubscriber->OnBMSReady(); + ZLOGI("DataShareSysEventSubscriberTest OnBMSReady001 end"); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_uri_utils_test.cpp similarity index 34% rename from relational_store/frameworks/native/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp rename to datamgr_service/services/distributeddataservice/service/test/data_share_uri_utils_test.cpp index 801ed84b..baccbc53 100644 --- a/relational_store/frameworks/native/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_uri_utils_test.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 @@ -12,51 +12,52 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define LOG_TAG "DatashareURIUtilsTest" +#include "utils.h" -#include "rdb_device_manager_adapter.h" - +#include #include namespace OHOS { -namespace DeviceManagerAdaptor { -using namespace OHOS::DistributedHardware; -constexpr int32_t DM_OK = 0; -constexpr int32_t DM_ERROR = -1; -RdbDeviceManagerAdaptor::RdbDeviceManagerAdaptor(const std::string &packageName) - :packageName_(packageName) +namespace DataShare { +using namespace testing::ext; +using namespace OHOS::DataShare; +class DatashareURIUtilsTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +HWTEST_F(DatashareURIUtilsTest, GeneralAnonymous_001, TestSize.Level0) { - Init(); + EXPECT_EQ(StringUtils::GeneralAnonymous("DataShareTable"), "Data***able"); } -RdbDeviceManagerAdaptor::~RdbDeviceManagerAdaptor() +HWTEST_F(DatashareURIUtilsTest, GeneralAnonymous_002, TestSize.Level0) { - UnInit(); + EXPECT_EQ(StringUtils::GeneralAnonymous("1bc"), "******"); } -RdbDeviceManagerAdaptor &RdbDeviceManagerAdaptor::GetInstance(const std::string &packageName) +HWTEST_F(DatashareURIUtilsTest, GeneralAnonymous_003, TestSize.Level0) { - static RdbDeviceManagerAdaptor instance(packageName); - return instance; + EXPECT_EQ(StringUtils::GeneralAnonymous("contact"), "cont***"); } -void RdbDeviceManagerAdaptor::Init() +HWTEST_F(DatashareURIUtilsTest, GeneralAnonymous_004, TestSize.Level0) { - auto callback = std::make_shared(); - DeviceManager::GetInstance().InitDeviceManager(packageName_, callback); + EXPECT_EQ(StringUtils::GeneralAnonymous("name"), "******"); } -void RdbDeviceManagerAdaptor::UnInit() +HWTEST_F(DatashareURIUtilsTest, GeneralAnonymous_005, TestSize.Level0) { - DeviceManager::GetInstance().UnInitDeviceManager(packageName_); + EXPECT_EQ(StringUtils::GeneralAnonymous(""), "******"); } -int RdbDeviceManagerAdaptor::GetEncryptedUuidByNetworkId(const std::string &networkId, std::string &uuid) +HWTEST_F(DatashareURIUtilsTest, GeneralAnonymous_006, TestSize.Level0) { - int ret = DeviceManager::GetInstance().GetEncryptedUuidByNetworkId(packageName_, networkId, uuid); - if (ret != DM_OK) { - return DM_ERROR; - } - return DM_OK; + EXPECT_EQ(StringUtils::GeneralAnonymous("store.db"), "stor***"); } -} // namespace DeviceManagerAdaptor +} // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/directory_manager_test.cpp b/datamgr_service/services/distributeddataservice/service/test/directory_manager_test.cpp index c763765a..96a433b9 100644 --- a/datamgr_service/services/distributeddataservice/service/test/directory_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/directory_manager_test.cpp @@ -191,6 +191,33 @@ HWTEST_F(DirectoryManagerTest, GetKVDBBackupPath, TestSize.Level0) EXPECT_EQ(path, metaData.dataDir + "/backup/testStpre"); } +/** +* @tc.name: GetUdmfPath +* @tc.desc: test get udmf store path +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(DirectoryManagerTest, GetUdmfStorePath, TestSize.Level0) +{ + StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); + metaData.appId = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); + metaData.storeId = "drag"; + metaData.securityLevel = SecurityLevel::S2; + metaData.tokenId = GetAccessTokenId(&tokenParam_); + metaData.area = DistributedKv::Area::EL2; + metaData.uid = static_cast(getuid()); + metaData.storeType = DistributedKv::KvStoreType::SINGLE_VERSION; + metaData.dataType = DistributedKv::DataType::TYPE_DYNAMICAL; + metaData.authType = DistributedKv::AuthType::IDENTICAL_ACCOUNT; + metaData.dataDir = "/data/service/el2/100/database/distributeddata/kvdb"; + auto path = DirectoryManager::GetInstance().GetStorePath(metaData); + EXPECT_EQ(path, metaData.dataDir); + auto res = DistributedData::DirectoryManager::GetInstance().CreateDirectory(path); + EXPECT_EQ(res, true); +} + /** * @tc.name: GetStorageMetaPath * @tc.desc: test get meta store dir @@ -229,30 +256,32 @@ HWTEST_F(DirectoryManagerTest, GetSecretKeyPath, TestSize.Level0) } /** -* @tc.name: DeleteDirectory -* @tc.desc: test delete dir +* @tc.name: GetStoreTypePath +* @tc.desc: test get db dir * @tc.type: FUNC -* @tc.require: -* @tc.author: */ -HWTEST_F(DirectoryManagerTest, DeleteDirectory, TestSize.Level0) +HWTEST_F(DirectoryManagerTest, GetStoreTypePath, TestSize.Level0) { - std::string path = "/data/service/el1/public/database/bundle_manager_service/kvdb/100/data"; - bool ret = DirectoryManager::GetInstance().CreateDirectory(path); - EXPECT_TRUE(ret); - std::ofstream file( - "/data/service/el1/public/database/bundle_manager_service/kvdb/100/data/test.txt", std::ios::out); - if (file.is_open()) { - file << "test content" << std::endl; - file.close(); - } - std::ofstream file1("/data/service/el1/public/database/bundle_manager_service/kvdb/100/test.txt", std::ios::out); - if (file1.is_open()) { - file1 << "test content" << std::endl; - file1.close(); - } - std::string deleteDir = "/data/service/el1/public/database/bundle_manager_service/kvdb/100"; - bool ret1 = DirectoryManager::GetInstance().DeleteDirectory(deleteDir.c_str()); - EXPECT_TRUE(ret1); - EXPECT_EQ(access(deleteDir.c_str(), F_OK), -1); + StoreMetaData metaData; + metaData.user = "100"; + metaData.bundleName = "ohos.test.demo"; + metaData.securityLevel = SecurityLevel::S2; + metaData.area = 1; + metaData.tokenId = AccessTokenKit::GetHapTokenID(100, "ohos.test.demo", 0); + metaData.appId = "ohos.test.demo_09AEF01D"; + + metaData.storeType = StoreMetaData::StoreType::STORE_KV_BEGIN; + metaData.dataDir = "/data/app/el1/100/database/ohos.test.demo/kvdb"; + auto path = DirectoryManager::GetInstance().GetStorePath(metaData); + EXPECT_EQ(path, metaData.dataDir); + + metaData.storeType = StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN; + metaData.dataDir = "/data/app/el1/100/database/ohos.test.demo/rdb"; + path = DirectoryManager::GetInstance().GetStorePath(metaData); + EXPECT_EQ(path, metaData.dataDir); + + metaData.storeType = StoreMetaData::StoreType::STORE_BUTT; + metaData.dataDir = "/data/app/el1/100/database/ohos.test.demo/other"; + path = DirectoryManager::GetInstance().GetStorePath(metaData); + EXPECT_EQ(path, metaData.dataDir); } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/BUILD.gn index efc92352..107fde07 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/BUILD.gn @@ -21,11 +21,18 @@ group("fuzztest") { deps = [ "dumphelper_fuzzer:fuzztest" ] if (datamgr_service_cloud) { - deps += [ "cloudservicestub_fuzzer:fuzztest" ] + deps += [ + "cloudservicestub_fuzzer:fuzztest", + "syncstrategies_fuzzer:fuzztest", + ] } if (datamgr_service_object) { - deps += [ "objectservicestub_fuzzer:fuzztest" ] + deps += [ + "objectservicestub_fuzzer:fuzztest", + "objectserviceimp_fuzzer:fuzztest", + "objectservicelistener_fuzzer:fuzztest", + ] } if (datamgr_service_rdb) { @@ -40,7 +47,11 @@ group("fuzztest") { } if (datamgr_service_data_share) { - deps += [ "datashareservicestub_fuzzer:fuzztest" ] + deps += [ + "datashareservicestub_fuzzer:fuzztest", + "datashareserviceimpl_fuzzer:fuzztest", + "datasharesubscriber_fuzzer:fuzztest", + ] } if (datamgr_service_udmf) { diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn index 3cb8f10b..2618103a 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn @@ -20,11 +20,6 @@ ohos_fuzztest("CloudServiceStubFuzzTest") { module_out_path = "datamgr_service/datamgr_service" include_dirs = [ - "${data_service_path}/adapter/include", - "${data_service_path}/app/src", - "${data_service_path}/framework/include", - "${data_service_path}/service/backup/include", - "${data_service_path}/service/bootstrap/include", "${data_service_path}/service/cloud", "${data_service_path}/service/common", "${data_service_path}/service/config/include", @@ -35,24 +30,10 @@ ohos_fuzztest("CloudServiceStubFuzzTest") { "${data_service_path}/service/object", "${data_service_path}/service/permission/include", "${data_service_path}/service/rdb", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_distributeddb_path}", - "${kv_store_distributeddb_path}/include/", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/interfaces/include/relational", - "${dataobject_path}/frameworks/innerkitsimpl/include", - "${relational_store_path}/interfaces/inner_api/cloud_data/include", - "${relational_store_path}/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", - "//third_party/json/single_include", "${data_service_path}/adapter/include/communicator", ] - fuzz_config_file = - "${data_service_path}/service/test/fuzztest/cloudservicestub_fuzzer" + fuzz_config_file = "${data_service_path}/service/test/fuzztest/cloudservicestub_fuzzer" cflags = [ "-g", @@ -64,65 +45,24 @@ ohos_fuzztest("CloudServiceStubFuzzTest") { sources = [ "${data_service_path}/app/src/checker/bundle_checker.cpp", "${data_service_path}/app/src/checker/system_checker.cpp", - "${data_service_path}/service/backup/src/backup_manager.cpp", - "${data_service_path}/service/bootstrap/src/bootstrap.cpp", - "${data_service_path}/service/cloud/cloud_data_translate.cpp", - "${data_service_path}/service/cloud/cloud_service_impl.cpp", - "${data_service_path}/service/cloud/cloud_service_stub.cpp", - "${data_service_path}/service/cloud/cloud_types_util.cpp", - "${data_service_path}/service/cloud/cloud_value_util.cpp", - "${data_service_path}/service/cloud/sync_manager.cpp", - "${data_service_path}/service/cloud/sync_strategies/network_sync_strategy.cpp", - "${data_service_path}/service/common/common_types_utils.cpp", - "${data_service_path}/service/common/value_proxy.cpp", - "${data_service_path}/service/common/xcollie.cpp", - "${data_service_path}/service/config/src/config_factory.cpp", - "${data_service_path}/service/config/src/model/app_id_mapping_config.cpp", - "${data_service_path}/service/config/src/model/backup_config.cpp", - "${data_service_path}/service/config/src/model/checker_config.cpp", - "${data_service_path}/service/config/src/model/cloud_config.cpp", - "${data_service_path}/service/config/src/model/component_config.cpp", - "${data_service_path}/service/config/src/model/directory_config.cpp", - "${data_service_path}/service/config/src/model/global_config.cpp", - "${data_service_path}/service/config/src/model/network_config.cpp", - "${data_service_path}/service/config/src/model/protocol_config.cpp", - "${data_service_path}/service/config/src/model/thread_config.cpp", - "${data_service_path}/service/crypto/src/crypto_manager.cpp", - "${data_service_path}/service/kvdb/user_delegate.cpp", - "${data_service_path}/service/permission/src/permission_validator.cpp", - "${data_service_path}/service/permission/src/permit_delegate.cpp", - "${data_service_path}/service/rdb/cache_cursor.cpp", - "${data_service_path}/service/rdb/rdb_asset_loader.cpp", - "${data_service_path}/service/rdb/rdb_cloud.cpp", - "${data_service_path}/service/rdb/rdb_cursor.cpp", - "${data_service_path}/service/rdb/rdb_general_store.cpp", - "${data_service_path}/service/rdb/rdb_hiview_adapter.cpp", - "${data_service_path}/service/rdb/rdb_notifier_proxy.cpp", - "${data_service_path}/service/rdb/rdb_query.cpp", - "${data_service_path}/service/rdb/rdb_result_set_impl.cpp", - "${data_service_path}/service/rdb/rdb_result_set_stub.cpp", - "${data_service_path}/service/rdb/rdb_schema_config.cpp", - "${data_service_path}/service/rdb/rdb_service_impl.cpp", - "${data_service_path}/service/rdb/rdb_service_stub.cpp", - "${data_service_path}/service/rdb/rdb_watcher.cpp", "cloudservicestub_fuzzer.cpp", ] deps = [ "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/adapter/dfx:distributeddata_dfx", "${data_service_path}/adapter/network:distributeddata_network", "${data_service_path}/adapter/schema_helper:distributeddata_schema_helper", "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "${kv_store_distributeddb_path}:distributeddb", + "${data_service_path}/service/bootstrap:distributeddata_bootstrap", + "${data_service_path}/service/cloud:distributeddata_cloud", + "${data_service_path}/service/common:distributeddata_common", + "${data_service_path}/service/rdb:distributeddata_rdb", ] external_deps = [ - "ability_base:want", - "ability_base:zuri", - "ability_runtime:ability_manager", - "ability_runtime:dataobs_manager", "access_token:libaccesstoken_sdk", "access_token:libtoken_setproc", "access_token:libtokenid_sdk", @@ -136,8 +76,10 @@ ohos_fuzztest("CloudServiceStubFuzzTest") { "hisysevent:libhisysevent", "huks:libhukssdk", "ipc:ipc_core", + "kv_store:datamgr_common", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", + "kv_store:distributeddb", "relational_store:native_rdb", "resource_management:global_resmgr", "safwk:system_ability_fwk", diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/cloudservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/cloudservicestub_fuzzer.cpp index 1d11a9d3..72904220 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/cloudservicestub_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/cloudservicestub_fuzzer.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "cloudservicestub_fuzzer.h" #include @@ -65,19 +67,22 @@ void AllocAndSetHapToken() SetSelfTokenID(tokenID.tokenIDEx); } -bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { - std::shared_ptr cloudServiceImpl = std::make_shared(); - std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); - cloudServiceImpl->OnBind( - { "CloudServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - - AllocAndSetHapToken(); + static std::shared_ptr cloudServiceImpl = std::make_shared(); + static std::once_flag onceFlag; + std::call_once(onceFlag, [&]() { + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + cloudServiceImpl->OnBind( + { "CloudServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + AllocAndSetHapToken(); + }); - uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + uint32_t code = provider.ConsumeIntegralInRange(CODE_MIN, CODE_MAX); + std::vector remainingData = provider.ConsumeRemainingBytes(); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); - request.WriteBuffer(data, size); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); request.RewindRead(0); MessageParcel reply; std::shared_ptr cloudServiceStub = cloudServiceImpl; @@ -89,11 +94,7 @@ bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::OnRemoteRequestFuzz(data, size); - + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/BUILD.gn new file mode 100644 index 00000000..baa4fa6e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/BUILD.gn @@ -0,0 +1,151 @@ +# 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("DataShareServiceImplFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + include_dirs = [ + "${data_service_path}/adapter/include", + "${data_service_path}/app/src", + "${data_service_path}/framework/include", + "${data_service_path}/service/common", + "${data_service_path}/service/config/include", + "${data_service_path}/service/crypto/include", + "${data_service_path}/service/data_share/common", + "${data_service_path}/service/data_share/data", + "${data_service_path}/service/data_share/dfx", + "${data_service_path}/service/data_share/strategies", + "${data_service_path}/service/data_share/subscriber_managers", + "${data_service_path}/service/data_share", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/permission/include", + "${data_service_path}/adapter/include/communicator", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/datashareserviceimpl_fuzzer" + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ + "${data_service_path}/service/common/xcollie.cpp", + "${data_service_path}/service/data_share/common/app_connect_manager.cpp", + "${data_service_path}/service/data_share/common/bundle_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/common_utils.cpp", + "${data_service_path}/service/data_share/common/db_delegate.cpp", + "${data_service_path}/service/data_share/common/div_strategy.cpp", + "${data_service_path}/service/data_share/common/extension_ability_manager.cpp", + "${data_service_path}/service/data_share/common/extension_connect_adaptor.cpp", + "${data_service_path}/service/data_share/common/extension_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/kv_delegate.cpp", + "${data_service_path}/service/data_share/common/proxy_data_manager.cpp", + "${data_service_path}/service/data_share/common/rdb_delegate.cpp", + "${data_service_path}/service/data_share/common/scheduler_manager.cpp", + "${data_service_path}/service/data_share/common/seq_strategy.cpp", + "${data_service_path}/service/data_share/common/utils.cpp", + "${data_service_path}/service/data_share/data/published_data.cpp", + "${data_service_path}/service/data_share/data/resultset_json_formatter.cpp", + "${data_service_path}/service/data_share/data/template_data.cpp", + "${data_service_path}/service/data_share/data_provider_config.cpp", + "${data_service_path}/service/data_share/data_share_db_config.cpp", + "${data_service_path}/service/data_share/data_share_obs_proxy.cpp", + "${data_service_path}/service/data_share/data_share_profile_config.cpp", + "${data_service_path}/service/data_share/data_share_service_impl.cpp", + "${data_service_path}/service/data_share/data_share_service_stub.cpp", + "${data_service_path}/service/data_share/data_share_silent_config.cpp", + "${data_service_path}/service/data_share/data_share_types_util.cpp", + "${data_service_path}/service/data_share/dfx/hiview_adapter.cpp", + "${data_service_path}/service/data_share/dfx/hiview_fault_adapter.cpp", + "${data_service_path}/service/data_share/strategies/data_proxy/load_config_from_data_proxy_node_strategy.cpp", + "${data_service_path}/service/data_share/strategies/data_share/load_config_from_data_share_bundle_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/check_is_data_proxy_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/check_is_single_app_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/cross_permission_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_common_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_data_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_from_bundle_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/permission_strategy.cpp", + "${data_service_path}/service/data_share/strategies/get_data_strategy.cpp", + "${data_service_path}/service/data_share/strategies/publish_strategy.cpp", + "${data_service_path}/service/data_share/strategies/rdb_notify_strategy.cpp", + "${data_service_path}/service/data_share/strategies/subscribe_strategy.cpp", + "${data_service_path}/service/data_share/strategies/template_strategy.cpp", + "${data_service_path}/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp", + "${data_service_path}/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp", + "${data_service_path}/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp", + "${data_service_path}/service/data_share/sys_event_subscriber.cpp", + "${data_service_path}/service/kvdb/user_delegate.cpp", + "${data_service_path}/service/permission/src/permit_delegate.cpp", + "datashareserviceimpl_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "ability_runtime:wantagent_innerkits", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "data_share:datashare_common", + "data_share:datashare_consumer", + "device_manager:devicemanagersdk", + "hicollie:libhicollie", + "hilog:libhilog", + "hisysevent:libhisysevent", + "huks:libhukssdk", + "init:libbegetutil", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "qos_manager:concurrent_task_client", + "qos_manager:qos", + "relational_store:native_rdb", + "relational_store:rdb_data_share_adapter", + "resource_management:global_resmgr", + "samgr:samgr_proxy", + "time_service:time_client", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":DataShareServiceImplFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/corpus/init new file mode 100644 index 00000000..7ade8a0f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/datashareserviceimpl_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/datashareserviceimpl_fuzzer.cpp new file mode 100644 index 00000000..83644b24 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/datashareserviceimpl_fuzzer.cpp @@ -0,0 +1,399 @@ +/* + * 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 "datashareserviceimpl_fuzzer.h" + +#include +#include + +#include "data_share_service_impl.h" +#include "ipc_skeleton.h" +#include "message_parcel.h" +#include "securec.h" + +using namespace OHOS::DataShare; +namespace OHOS { + +void NotifyChangeFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string uri = provider.ConsumeRandomLengthString(); + int32_t userId = provider.ConsumeIntegral(); + dataShareServiceImpl->NotifyChange(uri, userId); +} + +void GetCallerInfoFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string bundleName = "bundlename"; + int32_t appIndex = provider.ConsumeIntegral(); + dataShareServiceImpl->GetCallerInfo(bundleName, appIndex); +} + +void MakeMetaDataFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string bundleName = provider.ConsumeRandomLengthString(); + std::string userId = provider.ConsumeRandomLengthString(); + std::string deviceId = provider.ConsumeRandomLengthString(); + std::string storeId = provider.ConsumeRandomLengthString(); + dataShareServiceImpl->MakeMetaData(bundleName, userId, deviceId, storeId); +} + +void OnAppUninstallFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string bundleName = provider.ConsumeRandomLengthString(); + int32_t userId = provider.ConsumeIntegral(); + int32_t index = provider.ConsumeIntegral(); + dataShareServiceImpl->OnAppUninstall(bundleName, userId, index); +} + +void OnAppUpdateFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string bundleName = provider.ConsumeRandomLengthString(); + int32_t userId = provider.ConsumeIntegral(); + int32_t index = provider.ConsumeIntegral(); + dataShareServiceImpl->OnAppUpdate(bundleName, userId, index); +} + +void RegisterObserverFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string uri = provider.ConsumeRandomLengthString(); + sptr remoteObj = nullptr; + dataShareServiceImpl->RegisterObserver(uri, remoteObj); +} + +void UnregisterObserverFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string uri = provider.ConsumeRandomLengthString(); + sptr remoteObj = nullptr; + dataShareServiceImpl->UnregisterObserver(uri, remoteObj); +} + +void VerifyAcrossAccountsPermissionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + int32_t curId = provider.ConsumeIntegral(); + int32_t visId = provider.ConsumeIntegral(); + std::string permission = provider.ConsumeRandomLengthString(); + uint32_t tokenId = provider.ConsumeIntegral(); + dataShareServiceImpl->VerifyAcrossAccountsPermission(curId, visId, permission, tokenId); +} + +void CheckAllowListFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + uint32_t currentUserId = provider.ConsumeIntegral(); + uint32_t callerTokenId = provider.ConsumeIntegral(); + std::vector allowLists; + AllowList list1; + list1.appIdentifier = provider.ConsumeRandomLengthString(); + list1.onlyMain = provider.ConsumeBool(); + AllowList list2; + list2.appIdentifier = provider.ConsumeRandomLengthString(); + list2.onlyMain = provider.ConsumeBool(); + allowLists.push_back(list1); + allowLists.push_back(list2); + dataShareServiceImpl->CheckAllowList(currentUserId, callerTokenId, allowLists); +} + +void ReportExcuteFaultFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + uint32_t callingTokenId = provider.ConsumeIntegral(); + int32_t errCode = provider.ConsumeIntegral(); + std::string func = provider.ConsumeRandomLengthString(); + DataProviderConfig::ProviderInfo providerInfo; + providerInfo.moduleName = provider.ConsumeRandomLengthString(); + providerInfo.bundleName = provider.ConsumeRandomLengthString(); + providerInfo.storeName = provider.ConsumeRandomLengthString(); + dataShareServiceImpl->ReportExcuteFault(callingTokenId, providerInfo, errCode, func); +} + +void VerifyPermissionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string bundleName = provider.ConsumeRandomLengthString(); + std::string permission = provider.ConsumeRandomLengthString(); + bool isFromExtension = provider.ConsumeBool(); + int32_t tokenId = provider.ConsumeIntegral(); + dataShareServiceImpl->VerifyPermission(bundleName, permission, isFromExtension, tokenId); +} + +void OnAppExitFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + pid_t uid = provider.ConsumeIntegral(); + pid_t pid = provider.ConsumeIntegral(); + uint32_t tokenId = provider.ConsumeIntegral(); + std::string bundleName = provider.ConsumeRandomLengthString(); + dataShareServiceImpl->OnAppExit(uid, pid, tokenId, bundleName); +} + +void DumpDataShareServiceInfoFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + int fd = provider.ConsumeIntegral(); + std::map> params; + params["key1"] = {"value1", "value2"}; + params["key2"] = {"val_b1", "val_b2", "val_b3"}; + dataShareServiceImpl->DumpDataShareServiceInfo(fd, params); +} + +void DataShareStaticOnClearAppStorageFuzz(FuzzedDataProvider &provider) +{ + DataShareServiceImpl::DataShareStatic dataShareStatic; + std::string bundleName = provider.ConsumeRandomLengthString(); + int32_t userId = provider.ConsumeIntegral(); + int32_t index = provider.ConsumeIntegral(); + int32_t tokenId = provider.ConsumeIntegral(); + dataShareStatic.OnClearAppStorage(bundleName, userId, index, tokenId); +} + +void TimerReceiverOnReceiveEventFuzz(FuzzedDataProvider &provider) +{ + DataShareServiceImpl::TimerReceiver tmerReceiver; + EventFwk::Want want; + EventFwk::CommonEventData commonEventData(want); + commonEventData.SetWant(want); + tmerReceiver.OnReceiveEvent(commonEventData); +} + +void OnUserChangeFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + uint32_t code = provider.ConsumeIntegralInRange(0, 10); + std::string user = provider.ConsumeRandomLengthString(); + std::string account = provider.ConsumeRandomLengthString(); + dataShareServiceImpl->OnUserChange(code, user, account); +} + +void DataShareStaticOnAppUninstall(FuzzedDataProvider &provider) +{ + DataShareServiceImpl::DataShareStatic dataShareStatic; + std::string bundleName = provider.ConsumeRandomLengthString(); + int32_t user = provider.ConsumeIntegral(); + int32_t index = provider.ConsumeIntegral(); + dataShareStatic.OnAppUninstall(bundleName, user, index); +} + +void AllowCleanDataLaunchAppFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + int32_t evtId = provider.ConsumeIntegral(); + DistributedData::RemoteChangeEvent::DataInfo dataInfo; + dataInfo.userId = provider.ConsumeRandomLengthString(); + dataInfo.storeId = provider.ConsumeRandomLengthString(); + dataInfo.deviceId = provider.ConsumeRandomLengthString(); + dataInfo.bundleName = provider.ConsumeRandomLengthString(); + DistributedData::RemoteChangeEvent event(evtId, std::move(dataInfo)); + bool launchForCleanData = provider.ConsumeBool(); + dataShareServiceImpl->AllowCleanDataLaunchApp(event, launchForCleanData); +} + +void AutoLaunchFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + int32_t evtId = provider.ConsumeIntegral(); + DistributedData::RemoteChangeEvent::DataInfo dataInfo; + dataInfo.userId = provider.ConsumeRandomLengthString(); + dataInfo.storeId = provider.ConsumeRandomLengthString(); + dataInfo.deviceId = provider.ConsumeRandomLengthString(); + dataInfo.bundleName = provider.ConsumeRandomLengthString(); + DistributedData::RemoteChangeEvent event(evtId, std::move(dataInfo)); + dataShareServiceImpl->AutoLaunch(event); +} + +void UpdateExFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string uri = provider.ConsumeRandomLengthString(); + std::string extUri = provider.ConsumeRandomLengthString(); + DataSharePredicates predicates; + DataShareValuesBucket valuesBucket; + std::string key1 = provider.ConsumeRandomLengthString(); + std::string key2 = provider.ConsumeRandomLengthString(); + std::string key3 = provider.ConsumeRandomLengthString(); + std::string key4 = provider.ConsumeRandomLengthString(); + int valueInt = provider.ConsumeIntegral(); + float valueFloat = provider.ConsumeFloatingPoint(); + std::string valueStr = provider.ConsumeRandomLengthString(); + bool valueBool = provider.ConsumeBool(); + valuesBucket.valuesMap[key1] = valueInt; + valuesBucket.valuesMap[key2] = valueFloat; + valuesBucket.valuesMap[key3] = valueStr; + valuesBucket.valuesMap[key4] = valueBool; + dataShareServiceImpl->UpdateEx(uri, extUri, predicates, valuesBucket); +} + +void DeleteExFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string uri = provider.ConsumeRandomLengthString(); + std::string extUri = provider.ConsumeRandomLengthString(); + DataSharePredicates predicates; + dataShareServiceImpl->DeleteEx(uri, extUri, predicates); +} + +void DelTemplateFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string uri = provider.ConsumeRandomLengthString(); + int64_t subscriberId = provider.ConsumeIntegral(); + dataShareServiceImpl->DelTemplate(uri, subscriberId); +} + +void PublishFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + Data data; + std::string bundleNameOfProvider = provider.ConsumeRandomLengthString(); + dataShareServiceImpl->Publish(data, bundleNameOfProvider); +} + +void SubscribeRdbDataFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + uint8_t len = provider.ConsumeIntegral(); + std::vector uris(len); + for (int i = 0; i < len; i++) { + std::string uri = provider.ConsumeRandomLengthString(); + uris[i] = uri; + } + TemplateId id; + id.subscriberId_ = provider.ConsumeIntegral(); + id.bundleName_ = provider.ConsumeRandomLengthString(); + sptr observer; + dataShareServiceImpl->SubscribeRdbData(uris, id, observer); +} + +void EnableRdbSubsFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + uint8_t len = provider.ConsumeIntegral(); + std::vector uris(len); + for (int i = 0; i < len; i++) { + std::string uri = provider.ConsumeRandomLengthString(); + uris[i] = uri; + } + TemplateId id; + id.subscriberId_ = provider.ConsumeIntegral(); + id.bundleName_ = provider.ConsumeRandomLengthString(); + dataShareServiceImpl->EnableRdbSubs(uris, id); +} + +void SubscribePublishedDataFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + uint8_t len = provider.ConsumeIntegral(); + std::vector uris(len); + for (int i = 0; i < len; i++) { + std::string uri = provider.ConsumeRandomLengthString(); + uris[i] = uri; + } + int64_t subscriberId = provider.ConsumeIntegral(); + sptr observer; + dataShareServiceImpl->SubscribePublishedData(uris, subscriberId, observer); +} + +void DisablePubSubsFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + uint8_t len = provider.ConsumeIntegral(); + std::vector uris(len); + for (int i = 0; i < len; i++) { + std::string uri = provider.ConsumeRandomLengthString(); + uris[i] = uri; + } + int64_t subscriberId = provider.ConsumeIntegral(); + dataShareServiceImpl->DisablePubSubs(uris, subscriberId); +} + +void SaveLaunchInfoFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string userId = provider.ConsumeRandomLengthString(); + std::string deviceId = provider.ConsumeRandomLengthString(); + std::string bundleName = provider.ConsumeRandomLengthString(); + dataShareServiceImpl->SaveLaunchInfo(bundleName, userId, deviceId); +} + +void OnConnectDoneFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + dataShareServiceImpl->OnConnectDone(); +} + +void DataShareStaticOnAppUpdate(FuzzedDataProvider &provider) +{ + DataShareServiceImpl::DataShareStatic dataShareStatic; + std::string bundleName = provider.ConsumeRandomLengthString(); + int32_t user = provider.ConsumeIntegral(); + int32_t index = provider.ConsumeIntegral(); + dataShareStatic.OnAppUpdate(bundleName, user, index); +} + +void EnableSilentProxyFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::string uri = provider.ConsumeRandomLengthString(); + bool enable = provider.ConsumeBool(); + dataShareServiceImpl->EnableSilentProxy(uri, enable); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::NotifyChangeFuzz(provider); + OHOS::GetCallerInfoFuzz(provider); + OHOS::MakeMetaDataFuzz(provider); + OHOS::OnAppUninstallFuzz(provider); + OHOS::OnAppUpdateFuzz(provider); + OHOS::RegisterObserverFuzz(provider); + OHOS::UnregisterObserverFuzz(provider); + OHOS::VerifyAcrossAccountsPermissionFuzz(provider); + OHOS::CheckAllowListFuzz(provider); + OHOS::ReportExcuteFaultFuzz(provider); + OHOS::VerifyPermissionFuzz(provider); + OHOS::OnAppExitFuzz(provider); + OHOS::DumpDataShareServiceInfoFuzz(provider); + OHOS::DataShareStaticOnClearAppStorageFuzz(provider); + OHOS::TimerReceiverOnReceiveEventFuzz(provider); + OHOS::OnUserChangeFuzz(provider); + OHOS::DataShareStaticOnAppUninstall(provider); + OHOS::AllowCleanDataLaunchAppFuzz(provider); + OHOS::AutoLaunchFuzz(provider); + OHOS::UpdateExFuzz(provider); + OHOS::DeleteExFuzz(provider); + OHOS::DelTemplateFuzz(provider); + OHOS::PublishFuzz(provider); + OHOS::SubscribeRdbDataFuzz(provider); + OHOS::EnableRdbSubsFuzz(provider); + OHOS::SubscribePublishedDataFuzz(provider); + OHOS::DisablePubSubsFuzz(provider); + OHOS::SaveLaunchInfoFuzz(provider); + OHOS::OnConnectDoneFuzz(provider); + OHOS::DataShareStaticOnAppUpdate(provider); + OHOS::EnableSilentProxyFuzz(provider); + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/datashareserviceimpl_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/datashareserviceimpl_fuzzer.h new file mode 100644 index 00000000..24a855ff --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/datashareserviceimpl_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 DATAMGR_SERVICE_DATA_SHARE_SERVICE_IMPL_FUZZER_H +#define DATAMGR_SERVICE_DATA_SHARE_SERVICE_IMPL_FUZZER_H + +#define FUZZ_PROJECT_NAME "datashareserviceimpl_fuzzer" + +#endif // DATAMGR_SERVICE_DATA_SHARE_SERVICE_IMPL_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/project.xml new file mode 100644 index 00000000..a37a23b1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareserviceimpl_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn index 67dd0941..58249837 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn @@ -24,6 +24,7 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "${data_service_path}/app/src", "${data_service_path}/framework/include", "${data_service_path}/service/common", + "${data_service_path}/service/config/include", "${data_service_path}/service/crypto/include", "${data_service_path}/service/data_share/common", "${data_service_path}/service/data_share/data", @@ -33,10 +34,6 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "${data_service_path}/service/data_share", "${data_service_path}/service/kvdb", "${data_service_path}/service/permission/include", - "${datashare_path}/frameworks/native/common/include", - "${datashare_path}/interfaces/inner_api/common/include", - "${datashare_path}/interfaces/inner_api/consumer/include", - "//third_party/json/single_include", "${data_service_path}/adapter/include/communicator", ] @@ -52,19 +49,20 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { sources = [ "${data_service_path}/service/common/xcollie.cpp", - "${data_service_path}/service/crypto/src/crypto_manager.cpp", "${data_service_path}/service/data_share/common/app_connect_manager.cpp", "${data_service_path}/service/data_share/common/bundle_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/common_utils.cpp", "${data_service_path}/service/data_share/common/db_delegate.cpp", "${data_service_path}/service/data_share/common/div_strategy.cpp", "${data_service_path}/service/data_share/common/extension_ability_manager.cpp", "${data_service_path}/service/data_share/common/extension_connect_adaptor.cpp", "${data_service_path}/service/data_share/common/extension_mgr_proxy.cpp", "${data_service_path}/service/data_share/common/kv_delegate.cpp", + "${data_service_path}/service/data_share/common/proxy_data_manager.cpp", "${data_service_path}/service/data_share/common/rdb_delegate.cpp", "${data_service_path}/service/data_share/common/scheduler_manager.cpp", "${data_service_path}/service/data_share/common/seq_strategy.cpp", - "${data_service_path}/service/data_share/common/uri_utils.cpp", + "${data_service_path}/service/data_share/common/utils.cpp", "${data_service_path}/service/data_share/data/published_data.cpp", "${data_service_path}/service/data_share/data/resultset_json_formatter.cpp", "${data_service_path}/service/data_share/data/template_data.cpp", @@ -92,6 +90,7 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "${data_service_path}/service/data_share/strategies/rdb_notify_strategy.cpp", "${data_service_path}/service/data_share/strategies/subscribe_strategy.cpp", "${data_service_path}/service/data_share/strategies/template_strategy.cpp", + "${data_service_path}/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp", "${data_service_path}/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp", "${data_service_path}/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp", "${data_service_path}/service/data_share/sys_event_subscriber.cpp", @@ -104,6 +103,7 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "${data_service_path}/adapter/account:distributeddata_account", "${data_service_path}/adapter/communicator:distributeddata_communicator", "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", ] external_deps = [ @@ -120,6 +120,7 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "c_utils:utils", "common_event_service:cesfwk_innerkits", "data_share:datashare_common", + "data_share:datashare_consumer", "device_manager:devicemanagersdk", "hicollie:libhicollie", "hilog:libhilog", @@ -129,6 +130,8 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddb", + "qos_manager:concurrent_task_client", + "qos_manager:qos", "relational_store:native_rdb", "relational_store:rdb_data_share_adapter", "resource_management:global_resmgr", diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/datashareservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/datashareservicestub_fuzzer.cpp index df4f212d..ca846d32 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/datashareservicestub_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/datashareservicestub_fuzzer.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "datashareservicestub_fuzzer.h" #include @@ -28,37 +30,74 @@ using namespace OHOS::DataShare; namespace OHOS { const std::u16string INTERFACE_TOKEN = u"OHOS.DataShare.IDataShareService"; constexpr uint32_t CODE_MIN = 0; -constexpr uint32_t CODE_MAX = IDataShareService::DATA_SHARE_SERVICE_CMD_MAX + 1; +constexpr uint32_t CODE_MAX = static_cast(IDataShareService::DATA_SHARE_SERVICE_CMD_MAX) + 1; constexpr size_t NUM_MIN = 5; constexpr size_t NUM_MAX = 12; -bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { std::shared_ptr dataShareServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); dataShareServiceImpl->OnBind( { "DataShareServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + uint32_t code = provider.ConsumeIntegralInRange(CODE_MIN, CODE_MAX); + std::vector remainingData = provider.ConsumeRemainingBytes(); + MessageParcel request; + request.WriteInterfaceToken(INTERFACE_TOKEN); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); + request.RewindRead(0); + MessageParcel reply; + std::shared_ptr dataShareServiceStub = dataShareServiceImpl; + dataShareServiceStub->OnRemoteRequest(code, request, reply); + return true; +} + +bool OnRemoteRequestFuzz01(uint32_t code, FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + dataShareServiceImpl->OnBind( + { "DataShareServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + std::vector remainingData = provider.ConsumeRemainingBytes(); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); - request.WriteBuffer(data, size); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); request.RewindRead(0); MessageParcel reply; std::shared_ptr dataShareServiceStub = dataShareServiceImpl; dataShareServiceStub->OnRemoteRequest(code, request, reply); return true; } + +bool OnRemoteRequestFuzz02(FuzzedDataProvider &provider) +{ + std::shared_ptr dataShareServiceImpl = std::make_shared(); + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + dataShareServiceImpl->OnBind( + { "DataShareServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + std::vector remainingData = provider.ConsumeRemainingBytes(); + MessageParcel request; + request.WriteInterfaceToken(INTERFACE_TOKEN); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); + request.RewindRead(0); + MessageParcel reply; + std::shared_ptr dataShareServiceStub = dataShareServiceImpl; + dataShareServiceStub->OnRemoteRequest(IDataShareService::DATA_SHARE_CMD_SYSTEM_CODE, request, reply); + return true; +} } // namespace OHOS /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); + uint32_t codeTest = OHOS::CODE_MIN; + while (codeTest <= OHOS::CODE_MAX) { + OHOS::OnRemoteRequestFuzz01(codeTest, provider); + codeTest++; } - - OHOS::OnRemoteRequestFuzz(data, size); - + OHOS::OnRemoteRequestFuzz02(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/BUILD.gn new file mode 100644 index 00000000..ddfb2cd7 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/BUILD.gn @@ -0,0 +1,151 @@ +# 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("DataShareSubscriberFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + include_dirs = [ + "${data_service_path}/adapter/include", + "${data_service_path}/app/src", + "${data_service_path}/framework/include", + "${data_service_path}/service/common", + "${data_service_path}/service/config/include", + "${data_service_path}/service/crypto/include", + "${data_service_path}/service/data_share/common", + "${data_service_path}/service/data_share/data", + "${data_service_path}/service/data_share/dfx", + "${data_service_path}/service/data_share/strategies", + "${data_service_path}/service/data_share/subscriber_managers", + "${data_service_path}/service/data_share", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/permission/include", + "${data_service_path}/adapter/include/communicator", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/datasharesubscriber_fuzzer" + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ + "${data_service_path}/service/common/xcollie.cpp", + "${data_service_path}/service/data_share/common/app_connect_manager.cpp", + "${data_service_path}/service/data_share/common/bundle_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/common_utils.cpp", + "${data_service_path}/service/data_share/common/db_delegate.cpp", + "${data_service_path}/service/data_share/common/div_strategy.cpp", + "${data_service_path}/service/data_share/common/extension_ability_manager.cpp", + "${data_service_path}/service/data_share/common/extension_connect_adaptor.cpp", + "${data_service_path}/service/data_share/common/extension_mgr_proxy.cpp", + "${data_service_path}/service/data_share/common/kv_delegate.cpp", + "${data_service_path}/service/data_share/common/proxy_data_manager.cpp", + "${data_service_path}/service/data_share/common/rdb_delegate.cpp", + "${data_service_path}/service/data_share/common/scheduler_manager.cpp", + "${data_service_path}/service/data_share/common/seq_strategy.cpp", + "${data_service_path}/service/data_share/common/utils.cpp", + "${data_service_path}/service/data_share/data/published_data.cpp", + "${data_service_path}/service/data_share/data/resultset_json_formatter.cpp", + "${data_service_path}/service/data_share/data/template_data.cpp", + "${data_service_path}/service/data_share/data_provider_config.cpp", + "${data_service_path}/service/data_share/data_share_db_config.cpp", + "${data_service_path}/service/data_share/data_share_obs_proxy.cpp", + "${data_service_path}/service/data_share/data_share_profile_config.cpp", + "${data_service_path}/service/data_share/data_share_service_impl.cpp", + "${data_service_path}/service/data_share/data_share_service_stub.cpp", + "${data_service_path}/service/data_share/data_share_silent_config.cpp", + "${data_service_path}/service/data_share/data_share_types_util.cpp", + "${data_service_path}/service/data_share/dfx/hiview_adapter.cpp", + "${data_service_path}/service/data_share/dfx/hiview_fault_adapter.cpp", + "${data_service_path}/service/data_share/strategies/data_proxy/load_config_from_data_proxy_node_strategy.cpp", + "${data_service_path}/service/data_share/strategies/data_share/load_config_from_data_share_bundle_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/check_is_data_proxy_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/check_is_single_app_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/cross_permission_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_common_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_data_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/load_config_from_bundle_info_strategy.cpp", + "${data_service_path}/service/data_share/strategies/general/permission_strategy.cpp", + "${data_service_path}/service/data_share/strategies/get_data_strategy.cpp", + "${data_service_path}/service/data_share/strategies/publish_strategy.cpp", + "${data_service_path}/service/data_share/strategies/rdb_notify_strategy.cpp", + "${data_service_path}/service/data_share/strategies/subscribe_strategy.cpp", + "${data_service_path}/service/data_share/strategies/template_strategy.cpp", + "${data_service_path}/service/data_share/subscriber_managers/proxy_data_subscriber_manager.cpp", + "${data_service_path}/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp", + "${data_service_path}/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp", + "${data_service_path}/service/data_share/sys_event_subscriber.cpp", + "${data_service_path}/service/kvdb/user_delegate.cpp", + "${data_service_path}/service/permission/src/permit_delegate.cpp", + "datasharesubscriber_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "ability_runtime:extension_manager", + "ability_runtime:wantagent_innerkits", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "common_event_service:cesfwk_innerkits", + "data_share:datashare_common", + "data_share:datashare_consumer", + "device_manager:devicemanagersdk", + "hicollie:libhicollie", + "hilog:libhilog", + "hisysevent:libhisysevent", + "huks:libhukssdk", + "init:libbegetutil", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "qos_manager:concurrent_task_client", + "qos_manager:qos", + "relational_store:native_rdb", + "relational_store:rdb_data_share_adapter", + "resource_management:global_resmgr", + "samgr:samgr_proxy", + "time_service:time_client", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":DataShareSubscriberFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/corpus/init new file mode 100644 index 00000000..7ade8a0f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/datasharesubscriber_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/datasharesubscriber_fuzzer.cpp new file mode 100644 index 00000000..d55ec512 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/datasharesubscriber_fuzzer.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "DataShareSubscriberFuzzTest" +#include + +#include "datasharesubscriber_fuzzer.h" + +#include +#include + +#include "log_print.h" +#include "proxy_data_subscriber_manager.h" +#include "ipc_skeleton.h" +#include "message_parcel.h" +#include "securec.h" + +using namespace OHOS::DataShare; +namespace OHOS { + +void AddFuzz(FuzzedDataProvider &provider) +{ + std::string uri = provider.ConsumeRandomLengthString(); + std::string bundleName = provider.ConsumeRandomLengthString(); + ProxyDataKey key(uri, bundleName); + sptr observer; + std::string callerAppIdentifier = provider.ConsumeRandomLengthString(); + int32_t userId = provider.ConsumeIntegral(); + auto& manager = ProxyDataSubscriberManager::GetInstance(); + manager.Add(key, observer, bundleName, callerAppIdentifier, userId); +} + +void CheckAllowListFuzz(FuzzedDataProvider &provider) +{ + std::string callerAppIdentifier = provider.ConsumeRandomLengthString(); + uint8_t len = provider.ConsumeIntegralInRange(0, 20); + std::vector allowLists(len); + for (int i = 0; i < len; i++) { + std::string allowList = provider.ConsumeRandomLengthString(); + allowLists[i] = allowList; + } + auto& manager = ProxyDataSubscriberManager::GetInstance(); + manager.CheckAllowList(allowLists, callerAppIdentifier); +} + +void EmitFuzz(FuzzedDataProvider &provider) +{ + uint8_t keyNum = provider.ConsumeIntegralInRange(0, 20); + std::vector keys; + for (int i = 0; i < keyNum; i++) { + std::string uri = provider.ConsumeRandomLengthString(); + std::string bundleName = provider.ConsumeRandomLengthString(); + keys.push_back(ProxyDataKey(uri, bundleName)); + } + std::map> datas; + std::vector insertData; + DataShareProxyData data1; + insertData.push_back(data1); + datas[DataShareObserver::ChangeType::INSERT] = insertData; + int32_t userId = provider.ConsumeIntegral(); + auto& manager = ProxyDataSubscriberManager::GetInstance(); + manager.Emit(keys, datas, userId); +} + +void ObserverNodeFuzz(FuzzedDataProvider &provider) +{ + sptr observer; + uint32_t tokenId = provider.ConsumeIntegral(); + std::string name = provider.ConsumeRandomLengthString(); + std::string caller = provider.ConsumeRandomLengthString(); + int32_t userId = provider.ConsumeIntegral(); + ProxyDataSubscriberManager::ObserverNode observerNode(observer, tokenId, name, caller, userId); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::AddFuzz(provider); + OHOS::CheckAllowListFuzz(provider); + OHOS::EmitFuzz(provider); + OHOS::ObserverNodeFuzz(provider); + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/datasharesubscriber_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/datasharesubscriber_fuzzer.h new file mode 100644 index 00000000..dfa8298b --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/datasharesubscriber_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 DATAMGR_SERVICE_DATA_SHARE_SUBSCRIBER_FUZZER_H +#define DATAMGR_SERVICE_DATA_SHARE_SUBSCRIBER_FUZZER_H + +#define FUZZ_PROJECT_NAME "datasharesubscriber_fuzzer" + +#endif // DATAMGR_SERVICE_DATA_SHARE_SUBSCRIBER_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/project.xml new file mode 100644 index 00000000..a37a23b1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datasharesubscriber_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/dumphelper_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/dumphelper_fuzzer/BUILD.gn index 2fd16555..a9c5923a 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/dumphelper_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/dumphelper_fuzzer/BUILD.gn @@ -19,22 +19,7 @@ import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") ohos_fuzztest("DumpHelperFuzzTest") { module_out_path = "datamgr_service/datamgr_service" - include_dirs = [ - "${data_service_path}/service/dumper/include", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_distributeddb_path}", - "${kv_store_distributeddb_path}/include/", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/interfaces/include/relational", - "${dataobject_path}/frameworks/innerkitsimpl/include", - "${relational_store_path}/interfaces/inner_api/cloud_data/include", - "${relational_store_path}/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", - "//third_party/json/single_include", - ] + include_dirs = [ "${data_service_path}/service/dumper/include" ] fuzz_config_file = "${data_service_path}/service/test/fuzztest/dumphelper_fuzzer" @@ -55,7 +40,6 @@ ohos_fuzztest("DumpHelperFuzzTest") { "${data_service_path}/adapter/account:distributeddata_account", "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", - "${kv_store_distributeddb_path}:distributeddb", ] external_deps = [ @@ -75,7 +59,9 @@ ohos_fuzztest("DumpHelperFuzzTest") { "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", + "kv_store:distributeddb", "relational_store:native_rdb", + "kv_store:distributeddb" ] } diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/dumphelper_fuzzer/dumphelper_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/dumphelper_fuzzer/dumphelper_fuzzer.cpp index b8ff95c4..c4033acf 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/dumphelper_fuzzer/dumphelper_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/dumphelper_fuzzer/dumphelper_fuzzer.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "dumphelper_fuzzer.h" #include @@ -30,16 +32,15 @@ using namespace OHOS::Security::AccessToken; namespace OHOS { -bool DumpFuzz(const uint8_t *data, size_t size) +bool DumpFuzz(FuzzedDataProvider &provider) { - int connId = static_cast(*data); + int connId = provider.ConsumeIntegral(); std::vector args; const std::string argstest1 = "OHOS.DistributedData.DumpHelper1"; const std::string argstest2 = "OHOS.DistributedData.DumpHelper2"; args.emplace_back(argstest1); args.emplace_back(argstest2); DumpHelper::GetInstance().Dump(connId, args); - return true; } } // namespace OHOS @@ -47,11 +48,7 @@ bool DumpFuzz(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::DumpFuzz(data, size); - + FuzzedDataProvider provider(data, size); + OHOS::DumpFuzz(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/BUILD.gn index 458b5897..6e09939e 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/BUILD.gn @@ -33,16 +33,6 @@ ohos_fuzztest("KvdbServiceStubFuzzTest") { "${data_service_path}/service/matrix/include", "${data_service_path}/service/permission/include", "${data_service_path}/service/rdb", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_distributeddb_path}", - "${kv_store_distributeddb_path}/include/", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/interfaces/include/relational", - "${relational_store_path}/interfaces/inner_api/common_type/include", - "//third_party/json/single_include", "${data_service_path}/adapter/include/communicator", "${data_service_path}/adapter/include/utils", ] @@ -64,17 +54,19 @@ ohos_fuzztest("KvdbServiceStubFuzzTest") { "${data_service_path}/service/bootstrap/src/bootstrap.cpp", "${data_service_path}/service/common/value_proxy.cpp", "${data_service_path}/service/config/src/config_factory.cpp", + "${data_service_path}/service/config/src/model/app_access_check_config.cpp", "${data_service_path}/service/config/src/model/app_id_mapping_config.cpp", "${data_service_path}/service/config/src/model/backup_config.cpp", "${data_service_path}/service/config/src/model/checker_config.cpp", "${data_service_path}/service/config/src/model/cloud_config.cpp", "${data_service_path}/service/config/src/model/component_config.cpp", + "${data_service_path}/service/config/src/model/datashare_config.cpp", + "${data_service_path}/service/config/src/model/device_sync_app_white_list_config.cpp", "${data_service_path}/service/config/src/model/directory_config.cpp", "${data_service_path}/service/config/src/model/global_config.cpp", "${data_service_path}/service/config/src/model/network_config.cpp", "${data_service_path}/service/config/src/model/protocol_config.cpp", "${data_service_path}/service/config/src/model/thread_config.cpp", - "${data_service_path}/service/crypto/src/crypto_manager.cpp", "${data_service_path}/service/kvdb/auth_delegate.cpp", "${data_service_path}/service/kvdb/kvdb_exporter.cpp", "${data_service_path}/service/kvdb/kvdb_general_store.cpp", @@ -100,7 +92,6 @@ ohos_fuzztest("KvdbServiceStubFuzzTest") { "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "${kv_store_distributeddb_path}:distributeddb", ] external_deps = [ @@ -119,6 +110,9 @@ ohos_fuzztest("KvdbServiceStubFuzzTest") { "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "kv_store:kvdb_inner_lite", + "relational_store:native_rdb", "safwk:system_ability_fwk", "samgr:samgr_proxy", ] diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/kvdbservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/kvdbservicestub_fuzzer.cpp index 09829930..09582f0e 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/kvdbservicestub_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/kvdbservicestub_fuzzer/kvdbservicestub_fuzzer.cpp @@ -12,6 +12,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#include + #include "kvdbservicestub_fuzzer.h" #include @@ -33,7 +36,7 @@ constexpr uint32_t CODE_MAX = static_cast(KVDBServiceInterfaceCode::TR constexpr size_t NUM_MIN = 5; constexpr size_t NUM_MAX = 12; -bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { std::shared_ptr kvdbServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); @@ -45,10 +48,11 @@ bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) Bootstrap::GetInstance().LoadCheckers(); Bootstrap::GetInstance().LoadNetworks(); - uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + uint32_t code = provider.ConsumeIntegralInRange(CODE_MIN, CODE_MAX); + std::vector remainingData = provider.ConsumeRemainingBytes(); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); - request.WriteBuffer(data, size); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); request.RewindRead(0); MessageParcel reply; std::shared_ptr kvdbServiceStub = kvdbServiceImpl; @@ -60,11 +64,7 @@ bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::OnRemoteRequestFuzz(data, size); - + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/BUILD.gn new file mode 100644 index 00000000..039f0bf8 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/BUILD.gn @@ -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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("ObjectServiceImpFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + include_dirs = [ + "${data_service_path}/service/object/include", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/objectserviceimp_fuzzer" + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", + ] + + sources = [ + "objectserviceimp_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "${data_service_path}/service/object:distributeddata_object", + ] + + external_deps = [ + "ability_base:want", + "ability_base:zuri", + "ability_runtime:ability_manager", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "data_object:data_object_inner", + "data_object:distributeddataobject_impl", + "device_manager:devicemanagersdk", + "dfs_service:distributed_file_daemon_kit_inner", + "dmsfwk:distributed_sdk", + "hilog:libhilog", + "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":ObjectServiceImpFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/corpus/init new file mode 100644 index 00000000..7ade8a0f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/objectserviceimp_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/objectserviceimp_fuzzer.cpp new file mode 100644 index 00000000..de7adc4e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/objectserviceimp_fuzzer.cpp @@ -0,0 +1,171 @@ +/* + * 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 "objectserviceimp_fuzzer.h" +#include "object_service_impl.h" +#include "account/account_delegate.h" + +using namespace OHOS::DistributedObject; + +namespace OHOS { + +void ObjectStoreSaveFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + sptr callback; + std::string bundleName = provider.ConsumeRandomLengthString(100); + std::string sessionId = provider.ConsumeRandomLengthString(100); + std::string deviceId = provider.ConsumeRandomLengthString(100); + std::map> data; + std::vector remainingData = provider.ConsumeRemainingBytes(); + data["key1"] = remainingData; + objectServiceImpl->ObjectStoreSave(bundleName, sessionId, deviceId, data, callback); +} + +void OnUserChangeFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + uint32_t code = static_cast(AccountStatus::DEVICE_ACCOUNT_SWITCHED); + std::string user = provider.ConsumeRandomLengthString(100); + std::string account = provider.ConsumeRandomLengthString(100); + objectServiceImpl->OnUserChange(code, user, account); +} + +void ObjectStoreRevokeSaveFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + sptr callback; + std::string bundleName = provider.ConsumeRandomLengthString(100); + std::string sessionId = provider.ConsumeRandomLengthString(100); + objectServiceImpl->ObjectStoreRevokeSave(bundleName, sessionId, callback); +} + +void ObjectStoreRetrieveFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + sptr callback; + std::string bundleName = provider.ConsumeRandomLengthString(100); + std::string sessionId = provider.ConsumeRandomLengthString(100); + objectServiceImpl->ObjectStoreRetrieve(bundleName, sessionId, callback); +} + +void RegisterDataObserverFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + sptr callback; + std::string bundleName = provider.ConsumeRandomLengthString(100); + std::string sessionId = provider.ConsumeRandomLengthString(100); + objectServiceImpl->RegisterDataObserver(bundleName, sessionId, callback); +} + +void OnAppUninstallFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + if (objectServiceImpl->factory_.staticActs_ == nullptr) { + return; + } + std::string bundleName = provider.ConsumeRandomLengthString(100); + int32_t user = provider.ConsumeIntegral(); + int32_t index = provider.ConsumeIntegral(); + objectServiceImpl->factory_.staticActs_->OnAppUninstall(bundleName, user, index); +} + +void ResolveAutoLaunchFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + std::string identifier = provider.ConsumeRandomLengthString(100); + DistributedDB::AutoLaunchParam param; + objectServiceImpl->ResolveAutoLaunch(identifier, param); +} + +void OnAppExitFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + pid_t uid = provider.ConsumeIntegral(); + pid_t pid = provider.ConsumeIntegral(); + uint32_t tokenId = provider.ConsumeIntegral(); + std::string bundleName = provider.ConsumeRandomLengthString(100); + objectServiceImpl->OnAppExit(uid, pid, tokenId, bundleName); + objectServiceImpl->RegisterObjectServiceInfo(); + objectServiceImpl->RegisterHandler(); +} + +void DumpObjectServiceInfoFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + int fd = provider.ConsumeIntegral(); + std::string key = provider.ConsumeRandomLengthString(100); + std::string value1 = provider.ConsumeRandomLengthString(100); + std::string value2 = provider.ConsumeRandomLengthString(100); + std::map> params; + std::vector value = {value1, value2}; + params.emplace(std::make_pair(key, value)); + objectServiceImpl->DumpObjectServiceInfo(fd, params); +} +void SaveMetaDataFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + StoreMetaData saveMeta; + objectServiceImpl->SaveMetaData(saveMeta); + auto &dmAdapter = DeviceManagerAdapter::GetInstance(); + std::string uuid = provider.ConsumeRandomLengthString(100); + std::string udid = provider.ConsumeRandomLengthString(100); + if (uuid.empty()) { + uuid = "123"; + } + if (udid.empty()) { + udid = "234"; + } + dmAdapter.localInfo_.uuid = uuid; + dmAdapter.localInfo_.udid = udid; + objectServiceImpl->SaveMetaData(saveMeta); +} + +void BindAssetStoreFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + std::string bundleName = provider.ConsumeRandomLengthString(100); + std::string sessionId = provider.ConsumeRandomLengthString(100); + ObjectStore::Asset asset = {.id = provider.ConsumeRandomLengthString(100), + .name = provider.ConsumeRandomLengthString(100), + .uri = provider.ConsumeRandomLengthString(100)}; + ObjectStore::AssetBindInfo bindInfo = {.storeName = provider.ConsumeRandomLengthString(100), + .tableName = provider.ConsumeRandomLengthString(100), + .primaryKey = {{"data1", 123}, {"data2", "test1"}}, + .field = provider.ConsumeRandomLengthString(100), + .assetName = provider.ConsumeRandomLengthString(100)}; + objectServiceImpl->BindAssetStore(bundleName, sessionId, asset, bindInfo); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::ObjectStoreSaveFuzzTest(provider); + OHOS::OnUserChangeFuzzTest(provider); + OHOS::ObjectStoreRevokeSaveFuzzTest(provider); + OHOS::ObjectStoreRetrieveFuzzTest(provider); + OHOS::RegisterDataObserverFuzzTest(provider); + OHOS::OnAppUninstallFuzzTest(provider); + OHOS::ResolveAutoLaunchFuzzTest(provider); + OHOS::OnAppExitFuzzTest(provider); + OHOS::DumpObjectServiceInfoFuzzTest(provider); + OHOS::SaveMetaDataFuzzTest(provider); + OHOS::BindAssetStoreFuzzTest(provider); + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/objectserviceimp_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/objectserviceimp_fuzzer.h new file mode 100644 index 00000000..8aa6bb0e --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/objectserviceimp_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 OBJECT_SERVICE_IMP_FUZZER_H +#define OBJECT_SERVICE_IMP_FUZZER_H + +#define FUZZ_PROJECT_NAME "objectserviceimp_fuzzer" + +#endif // OBJECT_SERVICE_IMP_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/project.xml new file mode 100644 index 00000000..a37a23b1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectserviceimp_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/BUILD.gn new file mode 100644 index 00000000..e2105e20 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/BUILD.gn @@ -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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("ObjectServiceListenerFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + include_dirs = [ + "${data_service_path}/service/object/include", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/objectservicelistener_fuzzer" + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", + ] + + sources = [ + "objectservicelistener_fuzzer.cpp", + ] + + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "${data_service_path}/service/object:distributeddata_object", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libtokenid_sdk", + "data_object:data_object_inner", + "dfs_service:distributed_file_daemon_kit_inner", + "hilog:libhilog", + "ipc:ipc_single", + "kv_store:distributeddb", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":ObjectServiceListenerFuzzTest" ] +} +############################################################################### diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/corpus/init new file mode 100644 index 00000000..7ade8a0f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/objectservicelistener_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/objectservicelistener_fuzzer.cpp new file mode 100644 index 00000000..f277dab7 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/objectservicelistener_fuzzer.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 "objectservicelistener_fuzzer.h" +#include "object_data_listener.h" + +using namespace OHOS::DistributedObject; + +namespace OHOS { +void OnStartFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectAssetsRecvListener = std::make_shared(); + std::string srcNetworkId = provider.ConsumeRandomLengthString(100); + std::string dstNetworkId = provider.ConsumeRandomLengthString(100); + std::string sessionId = provider.ConsumeRandomLengthString(100); + std::string dstBundleName = provider.ConsumeRandomLengthString(100); + objectAssetsRecvListener->OnStart(srcNetworkId, dstNetworkId, sessionId, dstBundleName); +} + +void OnFinishedFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectAssetsRecvListener = std::make_shared(); + std::string srcNetworkId = provider.ConsumeRandomLengthString(100); + int32_t result = provider.ConsumeIntegral(); + sptr assetObj = new AssetObj(); + objectAssetsRecvListener->OnFinished(srcNetworkId, assetObj, result); +} + +void OnRecvProgressFuzzTest(FuzzedDataProvider &provider) +{ + std::shared_ptr objectAssetsRecvListener = std::make_shared(); + std::string srcNetworkId = provider.ConsumeRandomLengthString(100); + uint64_t totalBytes = provider.ConsumeIntegral(); + uint64_t processBytes = provider.ConsumeIntegral(); + sptr assetObj1 = new AssetObj(); + objectAssetsRecvListener->OnRecvProgress(srcNetworkId, assetObj1, totalBytes, processBytes); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::OnStartFuzzTest(provider); + OHOS::OnFinishedFuzzTest(provider); + OHOS::OnRecvProgressFuzzTest(provider); + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/objectservicelistener_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/objectservicelistener_fuzzer.h new file mode 100644 index 00000000..355f79d9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/objectservicelistener_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 OBJECT_SERVICE_LISTENER_FUZZER_H +#define OBJECT_SERVICE_LISTENER_FUZZER_H + +#define FUZZ_PROJECT_NAME "objectservicelistener_fuzzer" + +#endif // OBJECT_SERVICE_LISTENER_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/project.xml new file mode 100644 index 00000000..a37a23b1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicelistener_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/BUILD.gn index 336b0dbf..e1185088 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/BUILD.gn @@ -30,19 +30,6 @@ ohos_fuzztest("ObjectServiceStubFuzzTest") { "${data_service_path}/service/crypto/include", "${data_service_path}/service/object/include", "${data_service_path}/service/matrix/include", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_distributeddb_path}", - "${kv_store_distributeddb_path}/include/", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/interfaces/include/relational", - "${dataobject_path}/frameworks/innerkitsimpl/include", - "${dataobject_path}/frameworks/innerkitsimpl/include/common", - "${dataobject_path}/interfaces/innerkits", - "//third_party/json/single_include", - "${relational_store_path}/interfaces/inner_api/common_type/include", "${data_service_path}/adapter/include/communicator", "${data_service_path}/adapter/include/utils", ] @@ -63,17 +50,19 @@ ohos_fuzztest("ObjectServiceStubFuzzTest") { "${data_service_path}/service/common/common_types_utils.cpp", "${data_service_path}/service/common/value_proxy.cpp", "${data_service_path}/service/config/src/config_factory.cpp", + "${data_service_path}/service/config/src/model/app_access_check_config.cpp", "${data_service_path}/service/config/src/model/app_id_mapping_config.cpp", "${data_service_path}/service/config/src/model/backup_config.cpp", "${data_service_path}/service/config/src/model/checker_config.cpp", "${data_service_path}/service/config/src/model/cloud_config.cpp", "${data_service_path}/service/config/src/model/component_config.cpp", + "${data_service_path}/service/config/src/model/datashare_config.cpp", + "${data_service_path}/service/config/src/model/device_sync_app_white_list_config.cpp", "${data_service_path}/service/config/src/model/directory_config.cpp", "${data_service_path}/service/config/src/model/global_config.cpp", "${data_service_path}/service/config/src/model/network_config.cpp", "${data_service_path}/service/config/src/model/protocol_config.cpp", "${data_service_path}/service/config/src/model/thread_config.cpp", - "${data_service_path}/service/crypto/src/crypto_manager.cpp", "${data_service_path}/service/object/src/object_asset_loader.cpp", "${data_service_path}/service/object/src/object_asset_machine.cpp", "${data_service_path}/service/object/src/object_callback_proxy.cpp", @@ -92,7 +81,6 @@ ohos_fuzztest("ObjectServiceStubFuzzTest") { "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "${kv_store_distributeddb_path}:distributeddb", ] external_deps = [ @@ -103,6 +91,7 @@ ohos_fuzztest("ObjectServiceStubFuzzTest") { "access_token:libaccesstoken_sdk", "access_token:libtokenid_sdk", "c_utils:utils", + "data_object:data_object_inner", "data_object:distributeddataobject_impl", "device_auth:deviceauth_sdk", "device_manager:devicemanagersdk", @@ -116,6 +105,7 @@ ohos_fuzztest("ObjectServiceStubFuzzTest") { "json:nlohmann_json_static", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", + "kv_store:distributeddb", ] } diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/objectservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/objectservicestub_fuzzer.cpp index 24ce52ba..5a11e1f3 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/objectservicestub_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/objectservicestub_fuzzer.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "objectservicestub_fuzzer.h" #include @@ -32,17 +34,18 @@ constexpr uint32_t CODE_MAX = static_cast(ObjectCode::OBJECTSTORE_SERV constexpr size_t NUM_MIN = 5; constexpr size_t NUM_MAX = 12; -bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { std::shared_ptr objectServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); objectServiceImpl->OnBind( { "ObjectServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + uint32_t code = provider.ConsumeIntegralInRange(CODE_MIN, CODE_MAX); + std::vector remainingData = provider.ConsumeRemainingBytes(); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); - request.WriteBuffer(data, size); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); request.RewindRead(0); MessageParcel reply; std::shared_ptr objectServiceStub = objectServiceImpl; @@ -54,11 +57,7 @@ bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::OnRemoteRequestFuzz(data, size); - + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/BUILD.gn index 984eddf3..90e0d2f2 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/BUILD.gn @@ -25,18 +25,6 @@ ohos_fuzztest("RdbResultSetStubFuzzTest") { "${data_service_path}/framework/include", "${data_service_path}/service/rdb", "${data_service_path}/service/common", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_distributeddb_path}", - "${kv_store_distributeddb_path}/include/", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/interfaces/include/relational", - "${relational_store_path}/interfaces/inner_api/cloud_data/include", - "${relational_store_path}/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", - "//third_party/json/single_include", ] fuzz_config_file = @@ -60,8 +48,6 @@ ohos_fuzztest("RdbResultSetStubFuzzTest") { "${data_service_path}/adapter/account:distributeddata_account", "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", - "${kv_store_distributeddb_path}:distributeddb", - "${relational_store_inner_api_path}:native_rdb_static", ] external_deps = [ @@ -80,6 +66,7 @@ ohos_fuzztest("RdbResultSetStubFuzzTest") { "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", + "kv_store:distributeddb", "relational_store:native_rdb", ] } diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/rdbresultsetstub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/rdbresultsetstub_fuzzer.cpp index 9f10a09f..0f322d63 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/rdbresultsetstub_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbresultsetstub_fuzzer/rdbresultsetstub_fuzzer.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "rdbresultsetstub_fuzzer.h" #include @@ -28,16 +30,17 @@ using namespace OHOS::DistributedRdb; namespace OHOS { +using Code = NativeRdb::RemoteResultSet::Code; const std::u16string INTERFACE_TOKEN = u"OHOS::NativeRdb.IResultSet"; -constexpr uint32_t CODE_MIN = 0; -constexpr uint32_t CODE_MAX = NativeRdb::RemoteResultSet::Code::CMD_MAX + 1; -bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { - uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + const int min = 0; + uint32_t code = provider.ConsumeIntegralInRange(min, Code::CMD_MAX); + std::vector remainingData = provider.ConsumeRemainingBytes(); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); - request.WriteBuffer(data, size); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); request.RewindRead(0); MessageParcel reply; MessageOption option; @@ -52,11 +55,7 @@ bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::OnRemoteRequestFuzz(data, size); - + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/BUILD.gn index e51d7851..23fe264d 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/BUILD.gn @@ -35,19 +35,6 @@ ohos_fuzztest("RdbServiceStubFuzzTest") { "${data_service_path}/service/object", "${data_service_path}/service/permission/include", "${data_service_path}/service/rdb", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_distributeddb_path}", - "${kv_store_distributeddb_path}/include/", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/interfaces/include/relational", - "${dataobject_path}/frameworks/innerkitsimpl/include", - "${relational_store_path}/interfaces/inner_api/cloud_data/include", - "${relational_store_path}/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", - "//third_party/json/single_include", "${data_service_path}/adapter/include/communicator", ] @@ -64,46 +51,19 @@ ohos_fuzztest("RdbServiceStubFuzzTest") { sources = [ "${data_service_path}/app/src/checker/bundle_checker.cpp", "${data_service_path}/app/src/checker/system_checker.cpp", - "${data_service_path}/service/backup/src/backup_manager.cpp", - "${data_service_path}/service/bootstrap/src/bootstrap.cpp", - "${data_service_path}/service/common/value_proxy.cpp", - "${data_service_path}/service/common/xcollie.cpp", - "${data_service_path}/service/config/src/config_factory.cpp", - "${data_service_path}/service/config/src/model/app_id_mapping_config.cpp", - "${data_service_path}/service/config/src/model/backup_config.cpp", - "${data_service_path}/service/config/src/model/checker_config.cpp", - "${data_service_path}/service/config/src/model/cloud_config.cpp", - "${data_service_path}/service/config/src/model/component_config.cpp", - "${data_service_path}/service/config/src/model/directory_config.cpp", - "${data_service_path}/service/config/src/model/global_config.cpp", - "${data_service_path}/service/config/src/model/network_config.cpp", - "${data_service_path}/service/config/src/model/protocol_config.cpp", - "${data_service_path}/service/config/src/model/thread_config.cpp", - "${data_service_path}/service/crypto/src/crypto_manager.cpp", - "${data_service_path}/service/rdb/cache_cursor.cpp", - "${data_service_path}/service/rdb/rdb_asset_loader.cpp", - "${data_service_path}/service/rdb/rdb_cloud.cpp", - "${data_service_path}/service/rdb/rdb_cursor.cpp", - "${data_service_path}/service/rdb/rdb_general_store.cpp", - "${data_service_path}/service/rdb/rdb_hiview_adapter.cpp", - "${data_service_path}/service/rdb/rdb_notifier_proxy.cpp", - "${data_service_path}/service/rdb/rdb_query.cpp", - "${data_service_path}/service/rdb/rdb_result_set_impl.cpp", - "${data_service_path}/service/rdb/rdb_result_set_stub.cpp", - "${data_service_path}/service/rdb/rdb_schema_config.cpp", - "${data_service_path}/service/rdb/rdb_service_impl.cpp", - "${data_service_path}/service/rdb/rdb_service_stub.cpp", - "${data_service_path}/service/rdb/rdb_watcher.cpp", "rdbservicestub_fuzzer.cpp", ] deps = [ "${data_service_path}/adapter/account:distributeddata_account", + "${data_service_path}/adapter/dfx:distributeddata_dfx", "${data_service_path}/adapter/utils:distributeddata_utils", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", - "${kv_store_distributeddb_path}:distributeddb", - "${relational_store_inner_api_path}:native_rdb_static", + "${data_service_path}/service/bootstrap:distributeddata_bootstrap", + "${data_service_path}/service/cloud:distributeddata_cloud", + "${data_service_path}/service/common:distributeddata_common", + "${data_service_path}/service/rdb:distributeddata_rdb", ] external_deps = [ @@ -120,11 +80,11 @@ ohos_fuzztest("RdbServiceStubFuzzTest") { "device_manager:devicemanagersdk", "hicollie:libhicollie", "hilog:libhilog", - "hisysevent:libhisysevent", "huks:libhukssdk", "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", + "kv_store:distributeddb", "relational_store:native_rdb", "resource_management:global_resmgr", "samgr:samgr_proxy", diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/rdbservicestub_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/rdbservicestub_fuzzer.cpp index a9ef6e03..4f126d96 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/rdbservicestub_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/rdbservicestub_fuzzer.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "rdbservicestub_fuzzer.h" #include @@ -32,17 +34,18 @@ constexpr uint32_t CODE_MAX = static_cast(RdbServiceCode::RDB_SERVICE_ constexpr size_t NUM_MIN = 5; constexpr size_t NUM_MAX = 12; -bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { std::shared_ptr rdbServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); rdbServiceImpl->OnBind( { "RdbServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + uint32_t code = provider.ConsumeIntegralInRange(CODE_MIN, CODE_MAX); + std::vector remainingData = provider.ConsumeRemainingBytes(); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); - request.WriteBuffer(data, size); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); request.RewindRead(0); MessageParcel reply; std::shared_ptr rdbServiceStub = rdbServiceImpl; @@ -54,11 +57,7 @@ bool OnRemoteRequestFuzz(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::OnRemoteRequestFuzz(data, size); - + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/BUILD.gn new file mode 100644 index 00000000..1be915e1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/BUILD.gn @@ -0,0 +1,67 @@ +# 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. +##############################hydra-fuzz######################################## +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") + +##############################fuzztest########################################## +ohos_fuzztest("SyncStrategiesFuzzTest") { + module_out_path = "datamgr_service/datamgr_service" + + include_dirs = [ + "${data_service_path}/framework/include", + "${data_service_path}/service/cloud", + "${data_service_path}/service/common", + ] + + fuzz_config_file = + "${data_service_path}/service/test/fuzztest/syncstrategies_fuzzer" + + sources = [ "syncstrategies_fuzzer.cpp" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", + ] + + deps = [ + "${data_service_path}/adapter/dfx:distributeddata_dfx", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service/cloud:distributeddata_cloud", + "${data_service_path}/service/common:distributeddata_common", + "${data_service_path}/service/bootstrap:distributeddata_bootstrap", + "${data_service_path}/service/permission:distributeddata_permit", + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", + "access_token:libtokenid_sdk", + "c_utils:utils", + "hilog:libhilog", + "json:nlohmann_json_static", + "kv_store:datamgr_common", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + + deps = [ ":SyncStrategiesFuzzTest" ] +} +############################################################################### \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/corpus/init b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/corpus/init new file mode 100644 index 00000000..7ade8a0f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/project.xml new file mode 100644 index 00000000..a37a23b1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/syncstrategies_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/syncstrategies_fuzzer.cpp new file mode 100644 index 00000000..2cf4591d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/syncstrategies_fuzzer.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 +#include "syncstrategies_fuzzer.h" +#include "sync_strategies/network_sync_strategy.h" + +using namespace OHOS::DistributedData; +using namespace OHOS::CloudData; + +namespace OHOS { +void SyncStrategiesFuzz001(FuzzedDataProvider &provider) +{ + int32_t user = provider.ConsumeIntegral(); + std::string bundleName = provider.ConsumeRandomLengthString(100); + NetworkSyncStrategy strategy; + StoreInfo storeInfo; + storeInfo.user = user; + storeInfo.bundleName = bundleName; + strategy.CheckSyncAction(storeInfo); +} + +void SyncStrategiesFuzz002(FuzzedDataProvider &provider) +{ + uint32_t strategy = provider.ConsumeIntegral(); + NetworkSyncStrategy strategyInstance; + strategyInstance.Check(strategy); +} + +void SyncStrategiesFuzz003(FuzzedDataProvider &provider) +{ + int32_t user = provider.ConsumeIntegral(); + std::string bundleName = provider.ConsumeRandomLengthString(100); + NetworkSyncStrategy strategyInstance; + strategyInstance.GetStrategy(user, bundleName); + strategyInstance.GetKey(user); + + NetworkSyncStrategy::StrategyInfo info; + info.user = 1; + info.bundleName = "StrategyInfo"; + Serializable::json node; + std::string key = provider.ConsumeRandomLengthString(100); + std::string valueStr = provider.ConsumeRandomLengthString(100); + int valueInt = provider.ConsumeIntegral(); + float valueFloat = provider.ConsumeFloatingPoint(); + bool valueBool = provider.ConsumeBool(); + int valueRange = provider.ConsumeIntegralInRange(0, 100); + node[key] = valueStr; + node["integer"] = valueInt; + node["float"] = valueFloat; + node["boolean"] = valueBool; + node["range"] = valueRange; + info.Marshal(node); + info.Unmarshal(node); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::SyncStrategiesFuzz001(provider); + OHOS::SyncStrategiesFuzz002(provider); + OHOS::SyncStrategiesFuzz003(provider); + return 0; +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/syncstrategies_fuzzer.h b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/syncstrategies_fuzzer.h new file mode 100644 index 00000000..ab2199aa --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/syncstrategies_fuzzer/syncstrategies_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 SYNCSTRATEGIES_FUZZER_H +#define SYNCSTRATEGIES_FUZZER_H + +#define FUZZ_PROJECT_NAME "syncstrategies_fuzzer" + +#endif // SYNCSTRATEGIES_FUZZER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/BUILD.gn index 27778e7e..398162fc 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/BUILD.gn @@ -20,16 +20,13 @@ ohos_fuzztest("UdmfServiceFuzzTest") { module_out_path = "datamgr_service/datamgr_service" include_dirs = [ - "${udmf_path}/framework/common", - "${udmf_path}/interfaces/innerkits/common", - "${udmf_path}/interfaces/innerkits/data", "${data_service_path}/framework/include", + "${data_service_path}/service/matrix/include", "${data_service_path}/service/udmf/lifecycle", "${data_service_path}/service/udmf/permission", "${data_service_path}/service/udmf/preprocess", "${data_service_path}/service/udmf/store", "${data_service_path}/service/udmf", - "${kv_store_path}/frameworks/common", ] fuzz_config_file = @@ -40,6 +37,7 @@ ohos_fuzztest("UdmfServiceFuzzTest") { "-O0", "-Wno-unused-variable", "-fno-omit-frame-pointer", + "-fno-access-control" ] sources = [ "udmfservice_fuzzer.cpp" ] @@ -47,8 +45,10 @@ ohos_fuzztest("UdmfServiceFuzzTest") { deps = [ "${data_service_path}/adapter/account:distributeddata_account", "${data_service_path}/adapter/communicator:distributeddata_communicator", + "${data_service_path}/adapter/dfx:distributeddata_dfx", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service/bootstrap:distributeddata_bootstrap", + "${data_service_path}/service/matrix:distributeddata_matrix", "${data_service_path}/service/udmf:udmf_server", ] @@ -77,4 +77,4 @@ group("fuzztest") { deps = [ ":UdmfServiceFuzzTest" ] } -############################################################################### +############################################################################### \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/udmfservice_fuzzer.cpp b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/udmfservice_fuzzer.cpp index 1d5b03a1..59d2290c 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/udmfservice_fuzzer.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/udmfservice_fuzzer/udmfservice_fuzzer.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include + #include "udmfservice_fuzzer.h" #include "accesstoken_kit.h" @@ -35,53 +37,58 @@ constexpr size_t NUM_MIN = 5; constexpr size_t NUM_MAX = 12; static constexpr int ID_LEN = 32; static constexpr int MINIMUM = 48; +static constexpr int MAXIMUM = 121; -QueryOption GenerateFuzzQueryOption(const uint8_t* data, size_t size) +QueryOption GenerateFuzzQueryOption(FuzzedDataProvider &provider) { std::vector groupId(ID_LEN, '0'); - size_t length = groupId.size() > size ? size : groupId.size(); - for (size_t i = 0; i < length; ++i) { - groupId[i] = data[i] % MINIMUM + MINIMUM; + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); } std::string groupIdStr(groupId.begin(), groupId.end()); UnifiedKey udKey = UnifiedKey("drag", "com.test.demo", groupIdStr); - QueryOption query = { - .key = udKey.GetUnifiedKey(), - .intention = Intention::UD_INTENTION_DRAG - }; + QueryOption query; + query.key = udKey.GetUnifiedKey(); + query.intention = Intention::UD_INTENTION_DRAG; + query.tokenId = provider.ConsumeIntegral(); return query; } -bool OnRemoteRequestFuzz(const uint8_t* data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - uint32_t code = static_cast(*data) % (CODE_MAX - CODE_MIN + 1) + CODE_MIN; + uint32_t code = provider.ConsumeIntegralInRange(CODE_MIN, CODE_MAX); + std::vector remainingData = provider.ConsumeRemainingBytes(); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); - request.WriteBuffer(data, size); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); request.RewindRead(0); MessageParcel reply; udmfServiceImpl->OnRemoteRequest(code, request, reply); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; return true; } -void SetDataFuzz(const uint8_t *data, size_t size) +void SetDataFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; - std::string svalue(data, data + size); + + std::string svalue = provider.ConsumeRandomLengthString(); UnifiedData data1; std::shared_ptr obj = std::make_shared(); obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; obj->value_[FILE_URI_PARAM] = svalue; - obj->value_[FILE_TYPE] = "abcdefg"; + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); auto record = std::make_shared(FILE_URI, obj); data1.AddRecord(record); MessageParcel request; @@ -89,49 +96,58 @@ void SetDataFuzz(const uint8_t *data, size_t size) ITypesUtil::Marshal(request, option1, data1); MessageParcel reply; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::SET_DATA), request, reply); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void GetDataFuzz(const uint8_t *data, size_t size) +void GetDataFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - QueryOption query = GenerateFuzzQueryOption(data, size); + QueryOption query = GenerateFuzzQueryOption(provider); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); ITypesUtil::Marshal(request, query); MessageParcel reply; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::GET_DATA), request, reply); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void GetBatchDataFuzz(const uint8_t *data, size_t size) +void GetBatchDataFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - QueryOption query = GenerateFuzzQueryOption(data, size); + QueryOption query = GenerateFuzzQueryOption(provider); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); ITypesUtil::Marshal(request, query); MessageParcel reply; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::GET_BATCH_DATA), request, reply); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void UpdateDataFuzz(const uint8_t *data, size_t size) +void UpdateDataFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - QueryOption query = GenerateFuzzQueryOption(data, size); - std::string svalue(data, data + size); + QueryOption query = GenerateFuzzQueryOption(provider); + std::string svalue = provider.ConsumeRandomLengthString(); UnifiedData data1; std::shared_ptr obj = std::make_shared(); obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; obj->value_[FILE_URI_PARAM] = svalue; - obj->value_[FILE_TYPE] = "abcdefg"; + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); auto record = std::make_shared(FILE_URI, obj); data1.AddRecord(record); MessageParcel request; @@ -139,49 +155,57 @@ void UpdateDataFuzz(const uint8_t *data, size_t size) ITypesUtil::Marshal(request, query, data1); MessageParcel reply; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::UPDATE_DATA), request, reply); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void DeleteDataFuzz(const uint8_t *data, size_t size) +void DeleteDataFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - QueryOption query = GenerateFuzzQueryOption(data, size); + QueryOption query = GenerateFuzzQueryOption(provider); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); ITypesUtil::Marshal(request, query); MessageParcel reply; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::DELETE_DATA), request, reply); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void GetSummaryFuzz(const uint8_t *data, size_t size) +void GetSummaryFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - QueryOption query = GenerateFuzzQueryOption(data, size); + QueryOption query = GenerateFuzzQueryOption(provider); MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); ITypesUtil::Marshal(request, query); MessageParcel reply; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::GET_SUMMARY), request, reply); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void AddPrivilegeDataFuzz(const uint8_t *data, size_t size) +void AddPrivilegeDataFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - QueryOption query = GenerateFuzzQueryOption(data, size); + QueryOption query = GenerateFuzzQueryOption(provider); - Privilege privilege = { - .tokenId = 1, - .readPermission = "read", - .writePermission = "write" - }; + Privilege privilege; + privilege.tokenId = 1; + privilege.readPermission = "read"; + privilege.writePermission = "write"; MessageParcel request; request.WriteInterfaceToken(INTERFACE_TOKEN); @@ -189,15 +213,18 @@ void AddPrivilegeDataFuzz(const uint8_t *data, size_t size) MessageParcel replyUpdate; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::ADD_PRIVILEGE), request, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void SyncDataFuzz(const uint8_t *data, size_t size) +void SyncDataFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - QueryOption query = GenerateFuzzQueryOption(data, size); + QueryOption query = GenerateFuzzQueryOption(provider); std::vector devices = { "11", "22" }; MessageParcel requestUpdate; requestUpdate.WriteInterfaceToken(INTERFACE_TOKEN); @@ -205,56 +232,62 @@ void SyncDataFuzz(const uint8_t *data, size_t size) MessageParcel replyUpdate; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::SYNC), requestUpdate, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void IsRemoteDataFuzz(const uint8_t *data, size_t size) +void IsRemoteDataFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); - QueryOption query = GenerateFuzzQueryOption(data, size); + QueryOption query = GenerateFuzzQueryOption(provider); MessageParcel requestUpdate; requestUpdate.WriteInterfaceToken(INTERFACE_TOKEN); ITypesUtil::Marshal(requestUpdate, query); MessageParcel replyUpdate; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::IS_REMOTE_DATA), requestUpdate, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void ObtainAsynProcessFuzz(const uint8_t *data, size_t size) +void ObtainAsynProcessFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); std::vector groupId(ID_LEN, '0'); - size_t length = groupId.size() > size ? size : groupId.size(); - for (size_t i = 0; i < length; ++i) { - groupId[i] = data[i] % MINIMUM + MINIMUM; + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MINIMUM); } std::string businessUdKey(groupId.begin(), groupId.end()); - AsyncProcessInfo processInfo = { - .businessUdKey = businessUdKey, - }; + AsyncProcessInfo processInfo; + processInfo.businessUdKey = businessUdKey; MessageParcel requestUpdate; requestUpdate.WriteInterfaceToken(INTERFACE_TOKEN); ITypesUtil::Marshal(requestUpdate, processInfo); MessageParcel replyUpdate; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::OBTAIN_ASYN_PROCESS), requestUpdate, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; } -void ClearAsynProcessFuzz(const uint8_t *data, size_t size) +void ClearAsynProcessFuzz(FuzzedDataProvider &provider) { std::shared_ptr udmfServiceImpl = std::make_shared(); std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); udmfServiceImpl->OnBind( { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); std::vector groupId(ID_LEN, '0'); - size_t length = groupId.size() > size ? size : groupId.size(); - for (size_t i = 0; i < length; ++i) { - groupId[i] = data[i] % MINIMUM + MINIMUM; + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MINIMUM); } std::string businessUdKey(groupId.begin(), groupId.end()); MessageParcel requestUpdate; @@ -263,6 +296,558 @@ void ClearAsynProcessFuzz(const uint8_t *data, size_t size) MessageParcel replyUpdate; udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::CLEAR_ASYN_PROCESS_BY_KEY), requestUpdate, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; +} + +void SetDelayInfoFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + MessageParcel requestUpdate; + requestUpdate.WriteInterfaceToken(INTERFACE_TOKEN); + DataLoadInfo dataLoadInfo; + dataLoadInfo.recordCount = provider.ConsumeIntegral(); + dataLoadInfo.types.emplace(provider.ConsumeRandomLengthString()); + dataLoadInfo.sequenceKey = provider.ConsumeRandomLengthString(); + ITypesUtil::Marshal(requestUpdate, dataLoadInfo); + sptr iUdmfNotifier = nullptr; + ITypesUtil::Marshal(requestUpdate, iUdmfNotifier); + MessageParcel replyUpdate; + udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::SET_DELAY_INFO), + requestUpdate, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; +} + +void PushDelayDataFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + + MessageParcel requestUpdate; + requestUpdate.WriteInterfaceToken(INTERFACE_TOKEN); + std::string key = provider.ConsumeRandomLengthString(); + ITypesUtil::Marshal(requestUpdate, key); + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + data.AddRecord(record); + ITypesUtil::Marshal(requestUpdate, data); + + MessageParcel replyUpdate; + udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::SET_DELAY_DATA), + requestUpdate, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; +} + +void GetDataIfAvailableFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + + MessageParcel requestUpdate; + requestUpdate.WriteInterfaceToken(INTERFACE_TOKEN); + std::string key = provider.ConsumeRandomLengthString(); + ITypesUtil::Marshal(requestUpdate, key); + DataLoadInfo dataLoadInfo; + dataLoadInfo.recordCount = provider.ConsumeIntegral(); + dataLoadInfo.types.emplace(provider.ConsumeRandomLengthString()); + dataLoadInfo.sequenceKey = provider.ConsumeRandomLengthString(); + ITypesUtil::Marshal(requestUpdate, dataLoadInfo); + sptr iUdmfNotifier = nullptr; + ITypesUtil::Marshal(requestUpdate, iUdmfNotifier); + + MessageParcel replyUpdate; + udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::GET_DELAY_DATA), + requestUpdate, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; +} + +void OnGetAppShareOptionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + + MessageParcel requestUpdate; + requestUpdate.WriteInterfaceToken(INTERFACE_TOKEN); + CustomOption option = {.intention = Intention::UD_INTENTION_DRAG}; + std::string intention = UD_INTENTION_MAP.at(option.intention); + ITypesUtil::Marshal(requestUpdate, intention); + + MessageParcel replyUpdate; + udmfServiceImpl->OnRemoteRequest(static_cast(UdmfServiceInterfaceCode::GET_APP_SHARE_OPTION), + requestUpdate, replyUpdate); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; +} + +void CheckDragParamsFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string intention = provider.ConsumeRandomLengthString(); + std::string bundleName = provider.ConsumeRandomLengthString(); + std::vector groupId(ID_LEN, '0'); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey udKey(intention, bundleName, groupIdStr); + QueryOption query; + udmfServiceImpl->CheckDragParams(udKey, query); +} + +void IsPermissionInCacheFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + QueryOption query = GenerateFuzzQueryOption(provider); + udmfServiceImpl->IsPermissionInCache(query); +} + +void IsReadAndKeepFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + Privilege privilege; + privilege.tokenId = provider.ConsumeIntegral(); + privilege.readPermission = "read"; + privilege.writePermission = "write"; + Privilege privilege2; + privilege2.tokenId = provider.ConsumeIntegral(); + privilege2.readPermission = "readAndKeep"; + privilege2.writePermission = "write"; + std::vector privileges = { privilege, privilege2 }; + QueryOption query = GenerateFuzzQueryOption(provider); + udmfServiceImpl->IsReadAndKeep(privileges, query); +} + +void ProcessUriFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + QueryOption query = GenerateFuzzQueryOption(provider); + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + data.AddRecord(record); + udmfServiceImpl->ProcessUri(query, data); +} + +void ProcessCrossDeviceDataFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + uint32_t tokenId = provider.ConsumeIntegral(); + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + data.AddRecord(record); + std::vector uris; + udmfServiceImpl->ProcessCrossDeviceData(tokenId, data, uris); +} + +void ResolveAutoLaunchFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + auto identifier = provider.ConsumeRandomLengthString(); + UdmfServiceImpl::DBLaunchParam param; + param.userId = provider.ConsumeRandomLengthString(); + param.appId = provider.ConsumeRandomLengthString(); + param.storeId = provider.ConsumeRandomLengthString(); + param.path = provider.ConsumeRandomLengthString(); + udmfServiceImpl->ResolveAutoLaunch(identifier, param); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; +} + +void HasDatahubPriviledgeFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + auto bundleName = provider.ConsumeRandomLengthString(); + udmfServiceImpl->HasDatahubPriviledge(bundleName); +} + +void OnUserChangeFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + uint32_t code = provider.ConsumeIntegral(); + auto user = provider.ConsumeRandomLengthString(); + auto account = provider.ConsumeRandomLengthString(); + udmfServiceImpl->OnUserChange(code, user, account); +} + +void IsNeedTransferDeviceTypeFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + QueryOption query = GenerateFuzzQueryOption(provider); + udmfServiceImpl->IsNeedTransferDeviceType(query); +} + +void CheckAddPrivilegePermissionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string intention = provider.ConsumeRandomLengthString(); + std::string bundleName = provider.ConsumeRandomLengthString(); + std::vector groupId(ID_LEN, '0'); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey udKey(intention, bundleName, groupIdStr); + std::string processName = provider.ConsumeRandomLengthString(); + QueryOption query = GenerateFuzzQueryOption(provider); + udmfServiceImpl->CheckAddPrivilegePermission(udKey, processName, query); +} + +void ProcessDataFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + QueryOption query = GenerateFuzzQueryOption(provider); + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + data.AddRecord(record); + std::vector dataSet = { data }; + udmfServiceImpl->ProcessData(query, dataSet); +} + +void VerifyIntentionPermissionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::shared_ptr executor = std::make_shared(NUM_MAX, NUM_MIN); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), std::move(executor) }); + QueryOption query = GenerateFuzzQueryOption(provider); + UnifiedData data; + std::string intention = provider.ConsumeRandomLengthString(); + std::string bundleName = provider.ConsumeRandomLengthString(); + std::vector groupId(ID_LEN); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey udKey(intention, bundleName, groupIdStr); + CheckerManager::CheckInfo info; + info.tokenId = provider.ConsumeIntegral(); + udmfServiceImpl->VerifyIntentionPermission(query, data, udKey, info); + Runtime runtime; + data.SetRuntime(runtime); + udmfServiceImpl->VerifyIntentionPermission(query, data, udKey, info); + udmfServiceImpl->OnBind( + { "UdmfServiceStubFuzz", static_cast(IPCSkeleton::GetSelfTokenID()), nullptr }); + executor = nullptr; +} + +void IsFileMangerIntentionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + auto intention = provider.ConsumeRandomLengthString(); + udmfServiceImpl->IsFileMangerIntention(intention); +} + +void CheckAppIdFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string intention = provider.ConsumeRandomLengthString(); + std::string bundleName = provider.ConsumeRandomLengthString(); + std::string appId = provider.ConsumeRandomLengthString(); + std::string groupId = provider.ConsumeRandomLengthString(); + uint32_t tokenid = provider.ConsumeIntegral(); + Privilege privilege; + privilege.tokenId = tokenid; + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + data.AddRecord(record); + UnifiedKey key(intention, bundleName, groupId); + std::shared_ptr runtime = std::make_shared(); + runtime->key = key; + runtime->privileges.emplace_back(privilege); + runtime->sourcePackage = bundleName; + runtime->createPackage = bundleName; + runtime->recordTotalNum = static_cast(data.GetRecords().size()); + runtime->tokenId = tokenid; + runtime->appId = appId; + udmfServiceImpl->CheckAppId(runtime, bundleName); +} + +void CheckDeleteDataPermissionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string bundleName = provider.ConsumeRandomLengthString(); + std::string appId = provider.ConsumeRandomLengthString(); + uint32_t tokenid = provider.ConsumeIntegral(); + Privilege privilege; + privilege.tokenId = tokenid; + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + data.AddRecord(record); + std::vector groupId(ID_LEN, '0'); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey udKey = UnifiedKey("drag", "com.test.demo", groupIdStr); + std::shared_ptr runtime = std::make_shared(); + runtime->key = udKey; + runtime->privileges.emplace_back(privilege); + runtime->sourcePackage = bundleName; + runtime->createPackage = bundleName; + runtime->recordTotalNum = static_cast(data.GetRecords().size()); + runtime->tokenId = tokenid; + runtime->appId = appId; + QueryOption query; + query.key = udKey.GetUnifiedKey(); + query.intention = Intention::UD_INTENTION_DRAG; + query.tokenId = provider.ConsumeIntegral(); + udmfServiceImpl->CheckDeleteDataPermission(appId, runtime, query); +} + +void StoreSyncFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::vector groupId(ID_LEN, '0'); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey key = UnifiedKey("drag", "com.test.demo", groupIdStr); + QueryOption query; + query.key = key.GetUnifiedKey(); + query.intention = Intention::UD_INTENTION_DRAG; + query.tokenId = provider.ConsumeIntegral(); + std::vector devices = { "11", "22" }; + udmfServiceImpl->StoreSync(key, query, devices); +} + +void SetAppShareOptionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string intention = provider.ConsumeRandomLengthString(); + int32_t shareOption = provider.ConsumeIntegral(); + udmfServiceImpl->SetAppShareOption(intention, shareOption); +} + +void RemoveAppShareOptionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string intention = provider.ConsumeRandomLengthString(); + udmfServiceImpl->RemoveAppShareOption(intention); +} + +void QueryDataCommonFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::vector groupId(ID_LEN, '0'); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey udKey = UnifiedKey("drag", "com.test.demo", groupIdStr); + QueryOption query; + query.key = udKey.GetUnifiedKey(); + query.intention = Intention::UD_INTENTION_DRAG; + query.tokenId = provider.ConsumeIntegral(); + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + data.AddRecord(record); + std::shared_ptr store; + std::vector dataSet = { data }; + udmfServiceImpl->QueryDataCommon(query, dataSet, store); +} + +void ClearAsynProcessByKeyFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string businessUdKey = provider.ConsumeRandomLengthString(); + udmfServiceImpl->ClearAsynProcessByKey(businessUdKey); +} + +void TransferToEntriesIfNeedFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::vector groupId(ID_LEN, '0'); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey udKey = UnifiedKey("drag", "com.test.demo", groupIdStr); + QueryOption query; + query.key = udKey.GetUnifiedKey(); + query.intention = Intention::UD_INTENTION_DRAG; + query.tokenId = provider.ConsumeIntegral(); + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + std::shared_ptr obj1 = std::make_shared(); + obj1->value_[UNIFORM_DATA_TYPE] = "general.image-uri"; + obj1->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj1->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + std::shared_ptr obj2 = std::make_shared(); + obj2->value_[UNIFORM_DATA_TYPE] = "general.txt-uri"; + obj2->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj2->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + std::shared_ptr obj3 = std::make_shared(); + obj3->value_[UNIFORM_DATA_TYPE] = "general.html-uri"; + obj3->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj3->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + auto record1 = std::make_shared(FILE_URI, obj1); + auto record2 = std::make_shared(FILE_URI, obj2); + auto record3 = std::make_shared(FILE_URI, obj3); + data.AddRecord(record); + data.AddRecord(record1); + data.AddRecord(record2); + data.AddRecord(record3); + udmfServiceImpl->TransferToEntriesIfNeed(query, data); +} + +void IsValidOptionsNonDragFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::vector groupId(ID_LEN, '0'); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey key = UnifiedKey("drag", "com.test.demo", groupIdStr); + CustomOption option = {.intention = Intention::UD_INTENTION_DRAG}; + std::string intention = UD_INTENTION_MAP.at(option.intention); + udmfServiceImpl->IsValidOptionsNonDrag(key, intention); +} + +void CloseStoreWhenCorruptedFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string intention = provider.ConsumeRandomLengthString(); + int32_t status = provider.ConsumeIntegral(); + udmfServiceImpl->CloseStoreWhenCorrupted(intention, status); +} + +void HandleDbErrorFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string intention = provider.ConsumeRandomLengthString(); + int32_t status = provider.ConsumeIntegral(); + udmfServiceImpl->HandleDbError(intention, status); +} + +void BuildMetaFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string storeId = provider.ConsumeRandomLengthString(); + int userId = provider.ConsumeIntegral(); + udmfServiceImpl->BuildMeta(storeId, userId); +} + +void ProcessResultFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::map results; + std::string key = provider.ConsumeRandomLengthString(); + int32_t value = provider.ConsumeIntegral(); + results.emplace(std::make_pair(key, value)); + udmfServiceImpl->ProcessResult(results); +} + +void RegisterAsyncProcessInfoFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::string businessUdKey = provider.ConsumeRandomLengthString(); + udmfServiceImpl->RegisterAsyncProcessInfo(businessUdKey); +} + +void IsNeedMetaSyncFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + DistributedData::StoreMetaData meta; + uint8_t len = provider.ConsumeIntegral(); + std::vector uuids(len); + for (int i = 0; i < len; i++) { + std::string uuid = provider.ConsumeRandomLengthString(); + uuids[i] = uuid; + } + udmfServiceImpl->IsNeedMetaSync(meta, uuids); +} + +void VerifyDataAccessPermissionFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + std::shared_ptr runtime = std::make_shared(); + std::vector groupId(ID_LEN, '0'); + for (size_t i = 0; i < groupId.size(); ++i) { + groupId[i] = provider.ConsumeIntegralInRange(MINIMUM, MAXIMUM); + } + std::string groupIdStr(groupId.begin(), groupId.end()); + UnifiedKey udKey = UnifiedKey("drag", "com.test.demo", groupIdStr); + QueryOption query; + query.key = udKey.GetUnifiedKey(); + query.intention = Intention::UD_INTENTION_DRAG; + query.tokenId = provider.ConsumeIntegral(); + UnifiedData data; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + data.AddRecord(record); + udmfServiceImpl->VerifyDataAccessPermission(runtime, query, data); +} + +void HandleDelayDataCallbackFuzz(FuzzedDataProvider &provider) +{ + std::shared_ptr udmfServiceImpl = std::make_shared(); + DelayGetDataInfo delayGetDataInfo; + UnifiedData unifiedData; + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = provider.ConsumeRandomLengthString(); + obj->value_[FILE_TYPE] = provider.ConsumeRandomLengthString(); + auto record = std::make_shared(FILE_URI, obj); + unifiedData.AddRecord(record); + std::string key = provider.ConsumeRandomLengthString(); + udmfServiceImpl->HandleDelayDataCallback(delayGetDataInfo, unifiedData, key); } } @@ -278,25 +863,56 @@ extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - if (data == nullptr) { - return 0; - } - - OHOS::OnRemoteRequestFuzz(data, size); - OHOS::SetDataFuzz(data, size); - OHOS::GetDataFuzz(data, size); + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); + OHOS::SetDataFuzz(provider); + OHOS::GetDataFuzz(provider); - OHOS::GetBatchDataFuzz(data, size); - OHOS::UpdateDataFuzz(data, size); - OHOS::DeleteDataFuzz(data, size); + OHOS::GetBatchDataFuzz(provider); + OHOS::UpdateDataFuzz(provider); + OHOS::DeleteDataFuzz(provider); - OHOS::GetSummaryFuzz(data, size); - OHOS::AddPrivilegeDataFuzz(data, size); - OHOS::SyncDataFuzz(data, size); + OHOS::GetSummaryFuzz(provider); + OHOS::AddPrivilegeDataFuzz(provider); + OHOS::SyncDataFuzz(provider); - OHOS::IsRemoteDataFuzz(data, size); - OHOS::ObtainAsynProcessFuzz(data, size); - OHOS::ClearAsynProcessFuzz(data, size); + OHOS::IsRemoteDataFuzz(provider); + OHOS::ObtainAsynProcessFuzz(provider); + OHOS::ClearAsynProcessFuzz(provider); + OHOS::SetDelayInfoFuzz(provider); + OHOS::PushDelayDataFuzz(provider); + OHOS::GetDataIfAvailableFuzz(provider); + OHOS::OnGetAppShareOptionFuzz(provider); + OHOS::CheckDragParamsFuzz(provider); + OHOS::IsPermissionInCacheFuzz(provider); + OHOS::IsReadAndKeepFuzz(provider); + OHOS::ProcessUriFuzz(provider); + OHOS::ProcessCrossDeviceDataFuzz(provider); + OHOS::ResolveAutoLaunchFuzz(provider); + OHOS::HasDatahubPriviledgeFuzz(provider); + OHOS::OnUserChangeFuzz(provider); + OHOS::IsNeedTransferDeviceTypeFuzz(provider); + OHOS::CheckAddPrivilegePermissionFuzz(provider); + OHOS::ProcessDataFuzz(provider); + OHOS::VerifyIntentionPermissionFuzz(provider); + OHOS::IsFileMangerIntentionFuzz(provider); + OHOS::CheckAppIdFuzz(provider); + OHOS::CheckDeleteDataPermissionFuzz(provider); + OHOS::StoreSyncFuzz(provider); + OHOS::SetAppShareOptionFuzz(provider); + OHOS::RemoveAppShareOptionFuzz(provider); + OHOS::QueryDataCommonFuzz(provider); + OHOS::ClearAsynProcessByKeyFuzz(provider); + OHOS::TransferToEntriesIfNeedFuzz(provider); + OHOS::IsValidOptionsNonDragFuzz(provider); + OHOS::CloseStoreWhenCorruptedFuzz(provider); + OHOS::HandleDbErrorFuzz(provider); + OHOS::BuildMetaFuzz(provider); + OHOS::ProcessResultFuzz(provider); + OHOS::RegisterAsyncProcessInfoFuzz(provider); + OHOS::IsNeedMetaSyncFuzz(provider); + OHOS::VerifyDataAccessPermissionFuzz(provider); + OHOS::HandleDelayDataCallbackFuzz(provider); return 0; } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/kv_dalegate_test.cpp b/datamgr_service/services/distributeddataservice/service/test/kv_dalegate_test.cpp index 26bba5c0..a7b758fe 100644 --- a/datamgr_service/services/distributeddataservice/service/test/kv_dalegate_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/kv_dalegate_test.cpp @@ -16,19 +16,24 @@ #include #include +#include +#include +#include #include "data_share_profile_config.h" +#include "db_delegate.h" #include "executor_pool.h" -#include "grd_error.h" +#include "grd_base/grd_error.h" #include "kv_delegate.h" #include "log_print.h" +#include "proxy_data_manager.h" +#include "parameters.h" namespace OHOS::Test { using namespace testing::ext; using namespace OHOS::DataShare; class KvDelegateTest : public testing::Test { public: - static constexpr int64_t USER_TEST = 100; - static void SetUpTestCase(void){}; + static void SetUpTestCase(void); static void TearDownTestCase(void){}; void SetUp(){}; void TearDown(){}; @@ -42,6 +47,49 @@ const char* g_backupFiles[] = { }; const char* BACKUP_SUFFIX = ".backup"; std::shared_ptr executors = std::make_shared(5, 3); +bool g_isRK3568 = false; + +void KvDelegateTest::SetUpTestCase(void) +{ + static std::once_flag flag; + static std::string product; + const std::string invalidProduct { "default" }; + std::call_once(flag, []() { + product = OHOS::system::GetParameter("const.build.product", ""); + }); + if (product == invalidProduct) { + std::cout << "This test is not for " << invalidProduct << ", skip it." << std::endl; + g_isRK3568 = true; + return; + } +} + +bool FileComparison(const std::string& file1, const std::string& file2) +{ + std::ifstream f1(file1, std::ios::binary); + std::ifstream f2(file2, std::ios::binary); + + if (!f1.is_open() || !f2.is_open()) { + ZLOGI("fail to open files!"); + return false; // fail to open files + } + + // compare file size + f1.seekg(0, std::ios::end); + f2.seekg(0, std::ios::end); + if (f1.tellg() != f2.tellg()) { + ZLOGI("File size is different!"); + return false; + } + f1.seekg(0); + f2.seekg(0); + + return std::equal( + std::istreambuf_iterator(f1), + std::istreambuf_iterator(), + std::istreambuf_iterator(f2) + ); +} /** * @tc.name: RestoreIfNeedt001 @@ -112,4 +160,411 @@ HWTEST_F(KvDelegateTest, GetVersion001, TestSize.Level1) EXPECT_EQ(result, false); ZLOGI("KvDelegateTest GetVersion001 end"); } + +/** +* @tc.name: Upsert001 +* @tc.desc: test Upsert function when GDR_DBOpen failed +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a kvDelegate object and kvDelegate.isInitDone_= false + 2.call Upsert function to upsert filter +* @tc.experct: Upsert failed and return E_ERROR +*/ +HWTEST_F(KvDelegateTest, Upsert001, TestSize.Level1) +{ + ZLOGI("KvDelegateTest Upsert001 start"); + std::string path = "path/to/your/db"; + KvDelegate kvDelegate(path, executors); + std::string collectionName = "test"; + std::string filter = "filter"; + std::string value = "value"; + auto result = kvDelegate.Upsert(collectionName, filter, value); + EXPECT_EQ(result.first, E_ERROR); + ZLOGI("KvDelegateTest Upsert001 end"); +} + +/** +* @tc.name: Delete001 +* @tc.desc: test Delete function when GDR_DBOpen failed +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a kvDelegate object and kvDelegate.isInitDone_= false + 2.call Delete function to Delete filter +* @tc.experct: Delete failed and return E_ERROR +*/ +HWTEST_F(KvDelegateTest, Delete001, TestSize.Level1) +{ + ZLOGI("KvDelegateTest Delete001 start"); + std::string path = "path/to/your/db"; + KvDelegate kvDelegate(path, executors); + std::string collectionName = "test"; + std::string filter = "filter"; + auto result = kvDelegate.Delete(collectionName, filter); + EXPECT_EQ(result.first, E_ERROR); + ZLOGI("KvDelegateTest Delete001 end"); +} + +/** +* @tc.name: Init001 +* @tc.desc: test Init function when isInitDone_ = true +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a kvDelegate object and kvDelegate.isInitDone_= true + 2.call Init function +* @tc.experct: Init failed and return true +*/ +HWTEST_F(KvDelegateTest, Init001, TestSize.Level1) +{ + ZLOGI("KvDelegateTest Init001 start"); + std::string path = "path/to/your/db"; + KvDelegate kvDelegate(path, executors); + kvDelegate.isInitDone_ = true; + auto result = kvDelegate.Init(); + EXPECT_TRUE(result); + ZLOGI("KvDelegateTest Init001 end"); +} + +/** +* @tc.name: Init002 +* @tc.desc: test Init function when isInitDone_ = false +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a kvDelegate object and kvDelegate.isInitDone_= false + 2.call Init function +* @tc.experct: Init failed and return false +*/ +HWTEST_F(KvDelegateTest, Init002, TestSize.Level1) +{ + ZLOGI("KvDelegateTest Init002 start"); + std::string path = "path/to/your/db"; + KvDelegate kvDelegate(path, executors); + auto result = kvDelegate.Init(); + EXPECT_FALSE(result); + ZLOGI("KvDelegateTest Init002 end"); +} + +/** +* @tc.name: Get001 +* @tc.desc: test Get function when GDR_DBOpen failed +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a kvDelegate object and kvDelegate.isInitDone_= false + 2.call Get function +* @tc.experct: Get failed and return E_ERROR +*/ +HWTEST_F(KvDelegateTest, Get001, TestSize.Level1) +{ + ZLOGI("Get001 start"); + std::string path = "path/to/your/db"; + KvDelegate kvDelegate(path, executors); + std::string collectionName = "test"; + std::string filter = "filter"; + std::string projection = "projection"; + std::string value = "value"; + std::string result = "result"; + auto result1 = kvDelegate.Get(collectionName, filter, projection, result); + EXPECT_EQ(result1, E_ERROR); + ZLOGI("Get001 end"); +} + +/** +* @tc.name: Backup001 +* @tc.desc: test Backup function when hasChange_ is true +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a kvDelegate object and kvDelegate.hasChange_ = true + 2.call Backup function +* @tc.experct: need backup and change kvDelegate.hasChange_ to false +*/ +HWTEST_F(KvDelegateTest, Backup001, TestSize.Level1) +{ + ZLOGI("Backup001 start"); + std::string path = "path/to/your/db"; + KvDelegate kvDelegate(path, executors); + kvDelegate.hasChange_ = true; + kvDelegate.Backup(); + EXPECT_FALSE(kvDelegate.hasChange_); + ZLOGI("Backup001 end"); +} + +/** +* @tc.name: Backup002 +* @tc.desc: test Backup function when hasChange_ is false +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a kvDelegate object and kvDelegate.hasChange_ = false + 2.call Backup function +* @tc.experct: no need to backup and kvDelegate.hasChange_ not change +*/ +HWTEST_F(KvDelegateTest, Backup002, TestSize.Level1) +{ + ZLOGI("Backup002 start"); + std::string path = "path/to/your/db"; + KvDelegate kvDelegate(path, executors); + kvDelegate.Backup(); + EXPECT_FALSE(kvDelegate.hasChange_); + ZLOGI("Backup002 end"); +} + +/** +* @tc.name: GetBatch001 +* @tc.desc: test GetBatch function when GDR_DBOpen failed +* @tc.type: FUNC +* @tc.require:issueIBX9E1 +* @tc.precon: None +* @tc.step: + 1.Creat a kvDelegate object and kvDelegate.isInitDone_= false + 2.call GetBach function +* @tc.experct: GetBach failed and return E_ERROR +*/ +HWTEST_F(KvDelegateTest, GetBatch001, TestSize.Level1) +{ + ZLOGI("GetBatch001 start"); + std::string path = "path/to/your/db"; + KvDelegate kvDelegate(path, executors); + std::string collectionName = "test"; + std::string filter = "filter"; + std::string projection = "projection"; + std::string value = "value"; + std::vector result; + auto result1 = kvDelegate.GetBatch(collectionName, filter, projection, result); + EXPECT_EQ(result1, E_ERROR); + ZLOGI("GetBatch001 end"); +} + +/** +* @tc.name: KVDelegateGetInstanceTest001 +* @tc.desc: Test KvDelegate::GetInstance() function when both delegate and executors are null. +* @tc.type: FUNC +* @tc.require:issueICNFIF +* @tc.precon: None +* @tc.step: + 1.Call KvDBDelegate::GetInstance() to initialize kvDBDelegate. +* @tc.experct: Init failed. delegate is nullptr. +*/ +HWTEST_F(KvDelegateTest, KVDelegateGetInstanceTest001, TestSize.Level0) { + ZLOGI("KVDelegateGetInstanceTest001 start"); + auto delegate = KvDBDelegate::GetInstance("/data/test", nullptr); + EXPECT_EQ(delegate, nullptr); + ZLOGI("KVDelegateGetInstanceTest001 end"); +} + +/** +* @tc.name: KVDelegateGetInstanceTest002 +* @tc.desc: Test KvDelegate::GetInstance() function when delegate is null and executors is not null. +* @tc.type: FUNC +* @tc.require:issueICNFIF +* @tc.precon: None +* @tc.step: + 1.Call KvDBDelegate::GetInstance() to initialize kvDBDelegate. + 2.Call KvDBDelegate::GetInstance() to get kvDelegate when delegate is already initialized. +* @tc.experct: Init failed. delegate is nullptr. +*/ +HWTEST_F(KvDelegateTest, KVDelegateGetInstanceTest002, TestSize.Level0) { + ZLOGI("KVDelegateGetInstanceTest002 start"); + auto executors = std::make_shared(2, 1); + auto delegate = KvDBDelegate::GetInstance("/data/test", executors); + EXPECT_NE(delegate, nullptr); + delegate = KvDBDelegate::GetInstance("/data/test", executors); + EXPECT_NE(delegate, nullptr); + ZLOGI("KVDelegateGetInstanceTest002 end"); +} + +/** +* @tc.name: KVDelegateGetInstanceTest003 +* @tc.desc: Test KvDelegate::GetInstance() function when delegate is not null and executors is null. +* @tc.type: FUNC +* @tc.require:issueICNFIF +* @tc.precon: None +* @tc.step: + 1.Call KvDBDelegate::GetInstance() to initialize kvDBDelegate. + 2.Call KvDBDelegate::GetInstance() with empty executors to get kvDelegate when delegate is already initialized +* @tc.experct: Init failed. delegate is nullptr. +*/ +HWTEST_F(KvDelegateTest, KVDelegateGetInstanceTest003, TestSize.Level0) { + ZLOGI("KVDelegateGetInstanceTest003 start"); + auto executors = std::make_shared(2, 1); + auto delegate = KvDBDelegate::GetInstance("/data/test", executors); + EXPECT_NE(delegate, nullptr); + delegate = KvDBDelegate::GetInstance("/data/test", nullptr); + EXPECT_NE(delegate, nullptr); + ZLOGI("KVDelegateGetInstanceTest003 end"); +} + +/** +* @tc.name: KVDelegateResetBackupTest001 +* @tc.desc: Test KvDelegate::Init() when does not satisfy reset schedule conditions. Insert two datasets with the + second time waitTime_ set to 3600s. First scheduled backup waitTime is 1s. absoluteWaitTime_ is set + to 0ms to make sure backup schedule will not be reset to wait another 3600, First scheduled backup should be + done and not reset, and second inserted data should be included in the backup process, thus the backup + database should remain same as the original database with two dataset. +* @tc.type: FUNC +* @tc.require:issueICNFIF +* @tc.precon: None +* @tc.step: + 1.Initilize a KvDelegate object. + 2.set waitTime_ to 1s. + 3.call Upsert() to insert a dataset. + 4.Call NotifyBackup() to set hasChange_ condition to true to allow backup. + 5.Keep scheduled backup from being reset by setting absoluteWaitTime_ to 0ms. + 6.Set waitTime_ to 3600s to make sure if backup schedule resets, it will be reset to 3600s. + 7.call Upsert() to insert another dataset. + 8.Call NotifyBackup() to set hasChange_ condition to true to allow backup. +* @tc.experct: backup file should be the same as original file. +*/ +HWTEST_F(KvDelegateTest, KVDelegateResetBackupTest001, TestSize.Level0) { + if (g_isRK3568) { + GTEST_SKIP(); + } + ZLOGI("KVDelegateResetBackupTest001 start"); + auto executors = std::make_shared(2, 1); + auto delegate = new KvDelegate("/data/test", executors); + delegate->waitTime_ = 2; // 1s + std::vector proxyDataList = {"name", "age", "job"}; + std::vector proxyDataList1 = {"test", "hellow", "world"}; + auto value = ProxyDataList(ProxyDataListNode(proxyDataList, 24, 12)); + auto value1 = ProxyDataList(ProxyDataListNode(proxyDataList1, 10, 24)); + auto result = delegate->Upsert("proxydata_", value); + delegate->NotifyBackup(); + EXPECT_EQ(result.first, 0); + + // Set absoluteWaitTime_ to 0ms to make sure backup schedule will not be reset to wait another 3600s. + delegate->absoluteWaitTime_ = 0; + delegate->waitTime_ = 3600; + auto result1 = delegate->Upsert("proxydata_", value1); + delegate->NotifyBackup(); + EXPECT_EQ(result1.first, 0); + // First scheduled backup waitTime is 1s. Margin of error is 1s. + sleep(2); + // Backup shoud be done because schdule did not reset. + for (auto &fileName : g_backupFiles) { + std::string src = delegate->path_ + "/" + fileName; + std::string dst = src; + dst.append(BACKUP_SUFFIX); + EXPECT_TRUE(FileComparison(src, dst)); + } + ZLOGI("KVDelegateResetBackupTest001 end"); +} + +/** +* @tc.name: KVDelegateRestoreTest001 +* @tc.desc: Test RestoreIfNeed() after backup is done +* @tc.type: FUNC +* @tc.require:issueICNFIF +* @tc.precon: None +* @tc.step: + 1.Creat a KvDelegate object with an initialized executorPool. + 2.Set waitTime_ to 2s. + 3.Call Upsert() to insert a dataset. + 4.Get the dataset just inserted. + 5.Call NotifyBackup() to set hasChange_ condition to true to allow backup. + 6.Call FileComparison() to compare original database with backup database. + 7.Delete original database and call RestoreIfNeed() with GRD_REBUILD_DATABASE as input param. +* @tc.experct: Successfully Get the dataset previously inserted. +*/ +HWTEST_F(KvDelegateTest, KVDelegateRestoreTest001, TestSize.Level1) { + if (g_isRK3568) { + GTEST_SKIP(); + } + ZLOGI("KVDelegateRestoreTest001 start"); + auto executors = std::make_shared(2, 1); + auto delegate = new KvDelegate("/data/test", executors); + delegate->waitTime_ = 1; + std::vector proxyDataList = {"name", "age", "job"}; + auto value = ProxyDataList(ProxyDataListNode(proxyDataList, 24, 12)); + auto result = delegate->Upsert("proxydata_", value); + delegate->NotifyBackup(); + EXPECT_EQ(result.first, 0); + Id id = Id(std::to_string(12), 24); + std::string queryResult = ""; + + auto result1 = delegate->Get("proxydata_", id, queryResult); + + EXPECT_EQ(result1, 0); + // Scheduled backup waitTime is 1s, 1s for margin of error. + sleep(2); + for (auto &fileName : g_backupFiles) { + std::string src = delegate->path_ + "/" + fileName; + std::string dst = src; + dst.append(BACKUP_SUFFIX); + EXPECT_TRUE(FileComparison(src, dst)); + } + + EXPECT_EQ(std::remove("/data/test/dataShare.db"), 0); + bool restoreRet = delegate->RestoreIfNeed(GRD_REBUILD_DATABASE); + EXPECT_TRUE(restoreRet); + + std::string queryRetAfterRestore = ""; + result1 = delegate->Get("proxydata_", id, queryRetAfterRestore); + EXPECT_EQ(result1, 0); + ZLOGI("KVDelegateRestoreTest001 end"); +} + +/** +* @tc.name: KVDelegateInitTest001 +* @tc.desc: Test KvDelegate::Init() function when executors_ are null. +* @tc.type: FUNC +* @tc.require:issueICNFIF +* @tc.precon: None +* @tc.step: + 1.Initilize a KvDelegate object. + 2.Set executors_ to nullptr. + 3.Call Init() function. + 4.Call Init() function again. +* @tc.experct: Database init success, db_ is not nullptr. +*/ +HWTEST_F(KvDelegateTest, KVDelegateInitTest001, TestSize.Level0) { + ZLOGI("KVDelegateInitTest001 start"); + auto executors = std::make_shared(2, 1); + auto delegate = new KvDelegate("/data/test", executors); + EXPECT_NE(delegate, nullptr); + delegate->executors_ = nullptr; + bool result = delegate->Init(); + EXPECT_TRUE(result); + EXPECT_NE(delegate->db_, nullptr); + EXPECT_TRUE(delegate->isInitDone_); + EXPECT_EQ(delegate->absoluteWaitTime_, 0); + bool result1 = delegate->Init(); + EXPECT_TRUE(result1); + EXPECT_TRUE(delegate->isInitDone_); + ZLOGI("KVDelegateInitTest001 end"); +} + +/** +* @tc.name: KVDelegateInitTest002 +* @tc.desc: Test KvDelegate::Init() function when executors_ is not null. +* @tc.type: FUNC +* @tc.require:issueICNFIF +* @tc.precon: None +* @tc.step: + 1.Initilize a KvDelegate object. + 2.call Init() function. +* @tc.experct: Init success. Schedule success, taskId is not invalid. +*/ +HWTEST_F(KvDelegateTest, KVDelegateInitTest002, TestSize.Level0) { + ZLOGI("KVDelegateInitTest002 start"); + auto executors = std::make_shared(2, 1); + auto delegate = new KvDelegate("/data/test", executors); + bool result = delegate->Init(); + EXPECT_TRUE(result); + EXPECT_NE(delegate->db_, nullptr); + EXPECT_TRUE(delegate->isInitDone_); + EXPECT_NE(delegate->absoluteWaitTime_, 0); + EXPECT_NE(delegate->taskId_, ExecutorPool::INVALID_TASK_ID); + ZLOGI("KVDelegateInitTest002 end"); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_abnormal_test.cpp b/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_abnormal_test.cpp index a6d46bbb..1e78eb6a 100644 --- a/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_abnormal_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_abnormal_test.cpp @@ -25,7 +25,7 @@ #include "cloud/asset_loader.h" #include "cloud/cloud_db.h" #include "cloud/schema_meta.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter_mock.h" #include "kv_store_nb_delegate_mock.h" #include "kvdb_query.h" @@ -127,16 +127,19 @@ HWTEST_F(KVDBGeneralStoreAbnormalTest, GetDBOptionTest001, TestSize.Level0) HWTEST_F(KVDBGeneralStoreAbnormalTest, SetEqualIdentifier, TestSize.Level0) { auto store = new (std::nothrow) KVDBGeneralStore(metaData_); - std::vector uuids{"uuidtest01"}; + std::vector uuids{ "uuidtest01" }; KvStoreNbDelegateMock mockDelegate; mockDelegate.taskCountMock_ = 1; store->delegate_ = &mockDelegate; EXPECT_NE(store->delegate_, nullptr); - EXPECT_CALL(*deviceManagerAdapterMock, ToUUID(testing::_)).WillOnce(testing::Return(uuids)); + EXPECT_CALL(*deviceManagerAdapterMock, ToUUID(testing::A>())) + .WillOnce(testing::Return(uuids)); auto uuids1 = DMAdapter::ToUUID(DMAdapter::GetInstance().GetRemoteDevices()); - EXPECT_CALL(*deviceManagerAdapterMock, ToUUID(testing::_)).WillOnce(testing::Return(uuids)); + EXPECT_CALL(*deviceManagerAdapterMock, ToUUID(testing::A>())) + .WillOnce(testing::Return(uuids)); EXPECT_CALL(*deviceManagerAdapterMock, IsOHOSType("uuidtest01")) - .WillOnce(testing::Return(false)).WillOnce(testing::Return(false)); + .WillOnce(testing::Return(false)) + .WillOnce(testing::Return(false)); store->SetEqualIdentifier(metaData_.appId, metaData_.storeId); EXPECT_EQ(uuids1, uuids); store->delegate_ = nullptr; diff --git a/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_test.cpp b/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_test.cpp index 6da7e1d4..3566bb00 100644 --- a/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_test.cpp @@ -24,7 +24,7 @@ #include "cloud/asset_loader.h" #include "cloud/cloud_db.h" #include "cloud/schema_meta.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter.h" #include "kv_store_nb_delegate_mock.h" #include "kvdb_query.h" @@ -33,10 +33,12 @@ #include "metadata/secret_key_meta_data.h" #include "metadata/store_meta_data.h" #include "metadata/store_meta_data_local.h" +#include "mock/account_delegate_mock.h" #include "mock/db_store_mock.h" #include "mock/general_watcher_mock.h" using namespace testing::ext; +using namespace testing; using namespace DistributedDB; using namespace OHOS::DistributedData; using DBStoreMock = OHOS::DistributedData::DBStoreMock; @@ -49,6 +51,8 @@ using StoreId = OHOS::DistributedKv::StoreId; using AppId = OHOS::DistributedKv::AppId; namespace OHOS::Test { namespace DistributedDataTest { +static constexpr const char *INVALID_APPID = "invalid_kvdb_store_test"; + class KVDBGeneralStoreTest : public testing::Test { public: static void SetUpTestCase(void); @@ -56,30 +60,30 @@ public: void SetUp(); void TearDown(); protected: - static constexpr const char *bundleName = "test_distributeddata"; - static constexpr const char *storeName = "test_service_meta"; + static constexpr const char *BUNDLE_NAME = "test_distributeddata"; + static constexpr const char *STORE_NAME = "test_service_meta"; void InitMetaData(); static std::vector Random(uint32_t len); static std::shared_ptr dbStoreMock_; StoreMetaData metaData_; + static inline AccountDelegateMock *accountDelegateMock = nullptr; }; std::shared_ptr KVDBGeneralStoreTest::dbStoreMock_ = std::make_shared(); static const uint32_t KEY_LENGTH = 32; -static const uint32_t ENCRYPT_KEY_LENGTH = 48; void KVDBGeneralStoreTest::InitMetaData() { - metaData_.bundleName = bundleName; - metaData_.appId = bundleName; + metaData_.bundleName = BUNDLE_NAME; + metaData_.appId = BUNDLE_NAME; metaData_.user = "0"; metaData_.area = OHOS::DistributedKv::EL1; metaData_.instanceId = 0; metaData_.isAutoSync = true; metaData_.storeType = DistributedKv::KvStoreType::SINGLE_VERSION; - metaData_.storeId = storeName; - metaData_.dataDir = "/data/service/el1/public/database/" + std::string(bundleName) + "/kvdb"; + metaData_.storeId = STORE_NAME; + metaData_.dataDir = "/data/service/el1/public/database/" + std::string(BUNDLE_NAME) + "/kvdb"; metaData_.securityLevel = SecurityLevel::S2; } @@ -94,9 +98,22 @@ std::vector KVDBGeneralStoreTest::Random(uint32_t len) return key; } -void KVDBGeneralStoreTest::SetUpTestCase(void) {} +void KVDBGeneralStoreTest::SetUpTestCase(void) +{ + accountDelegateMock = new (std::nothrow) AccountDelegateMock(); + if (accountDelegateMock != nullptr) { + AccountDelegate::instance_ = nullptr; + AccountDelegate::RegisterAccountInstance(accountDelegateMock); + } +} -void KVDBGeneralStoreTest::TearDownTestCase() {} +void KVDBGeneralStoreTest::TearDownTestCase() +{ + if (accountDelegateMock != nullptr) { + delete accountDelegateMock; + accountDelegateMock = nullptr; + } +} void KVDBGeneralStoreTest::SetUp() { @@ -104,7 +121,11 @@ void KVDBGeneralStoreTest::SetUp() InitMetaData(); } -void KVDBGeneralStoreTest::TearDown() {} +void KVDBGeneralStoreTest::TearDown() +{ + MetaDataManager::GetInstance().DelMeta(metaData_.GetSecretKey(), true); + MetaDataManager::GetInstance().DelMeta(metaData_.GetKey(), true); +} class MockGeneralWatcher : public DistributedData::GeneralWatcher { public: @@ -121,8 +142,12 @@ public: class MockKvStoreChangedData : public DistributedDB::KvStoreChangedData { public: - MockKvStoreChangedData() {} - virtual ~MockKvStoreChangedData() {} + MockKvStoreChangedData() + { + } + virtual ~MockKvStoreChangedData() + { + } std::list entriesInserted = {}; std::list entriesUpdated = {}; std::list entriesDeleted = {}; @@ -150,14 +175,43 @@ public: /** * @tc.name: GetDBPasswordTest_001 -* @tc.desc: GetDBPassword from meta. +* @tc.desc: get password with all exception branch * @tc.type: FUNC -* @tc.require: -* @tc.author: Hollokin */ HWTEST_F(KVDBGeneralStoreTest, GetDBPasswordTest_001, TestSize.Level0) { - ZLOGI("GetDBPasswordTest start"); + metaData_.isEncrypt = false; + auto dbPassword = KVDBGeneralStore::GetDBPassword(metaData_); + ASSERT_EQ(dbPassword.GetSize(), 0); + + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + + metaData_.isEncrypt = true; + dbPassword = KVDBGeneralStore::GetDBPassword(metaData_); + ASSERT_EQ(dbPassword.GetSize(), 0); + + SecretKeyMetaData secretKey; + auto result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_TRUE(result); + dbPassword = KVDBGeneralStore::GetDBPassword(metaData_); + ASSERT_EQ(dbPassword.GetSize(), 0); + + std::vector randomKey = Random(KEY_LENGTH); + ASSERT_FALSE(randomKey.empty()); + secretKey.sKey = randomKey; + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_TRUE(result); + dbPassword = KVDBGeneralStore::GetDBPassword(metaData_); + ASSERT_EQ(dbPassword.GetSize(), 0); +} + +/** +* @tc.name: GetDBPasswordTest_002 +* @tc.desc: GetDBPassword from meta. +* @tc.type: FUNC +*/ +HWTEST_F(KVDBGeneralStoreTest, GetDBPasswordTest_002, TestSize.Level0) +{ MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKey(), metaData_, true)); EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), metaData_, true)); @@ -166,13 +220,11 @@ HWTEST_F(KVDBGeneralStoreTest, GetDBPasswordTest_001, TestSize.Level0) } /** -* @tc.name: GetDBPasswordTest_002 +* @tc.name: GetDBPasswordTest_003 * @tc.desc: GetDBPassword from encrypt meta. * @tc.type: FUNC -* @tc.require: -* @tc.author: Hollokin */ -HWTEST_F(KVDBGeneralStoreTest, GetDBPasswordTest_002, TestSize.Level0) +HWTEST_F(KVDBGeneralStoreTest, GetDBPasswordTest_003, TestSize.Level0) { ZLOGI("GetDBPasswordTest_002 start"); MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); @@ -183,10 +235,15 @@ HWTEST_F(KVDBGeneralStoreTest, GetDBPasswordTest_002, TestSize.Level0) EXPECT_EQ(errCode, CryptoManager::ErrCode::SUCCESS); std::vector randomKey = Random(KEY_LENGTH); + ASSERT_FALSE(randomKey.empty()); SecretKeyMetaData secretKey; secretKey.storeType = metaData_.storeType; - secretKey.sKey = CryptoManager::GetInstance().Encrypt(randomKey, DEFAULT_ENCRYPTION_LEVEL, DEFAULT_USER); - EXPECT_EQ(secretKey.sKey.size(), ENCRYPT_KEY_LENGTH); + CryptoManager::CryptoParams encryptParams = { .area = metaData_.area, .userId = metaData_.user }; + secretKey.sKey = CryptoManager::GetInstance().Encrypt(randomKey, encryptParams); + ASSERT_FALSE(secretKey.sKey.empty()); + ASSERT_FALSE(encryptParams.nonce.empty()); + secretKey.area = metaData_.area; + secretKey.nonce = encryptParams.nonce; EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true)); auto dbPassword = KVDBGeneralStore::GetDBPassword(metaData_); @@ -194,6 +251,35 @@ HWTEST_F(KVDBGeneralStoreTest, GetDBPasswordTest_002, TestSize.Level0) randomKey.assign(randomKey.size(), 0); } +/** +* @tc.name: GetDBPasswordTest_004 +* @tc.desc: get password with exception branch +* @tc.type: FUNC +*/ +HWTEST_F(KVDBGeneralStoreTest, GetDBPasswordTest_004, TestSize.Level0) +{ + metaData_.bundleName = INVALID_APPID; + auto dbPassword = KVDBGeneralStore::GetDBPassword(metaData_); + ASSERT_EQ(dbPassword.GetSize(), 0); + + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + + SecretKeyMetaData secretKey; + auto result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_TRUE(result); + dbPassword = KVDBGeneralStore::GetDBPassword(metaData_); + ASSERT_EQ(dbPassword.GetSize(), 0); + + auto key = Random(KEY_LENGTH); + ASSERT_FALSE(key.empty()); + secretKey.sKey = key; + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_TRUE(result); + dbPassword = KVDBGeneralStore::GetDBPassword(metaData_); + ASSERT_EQ(dbPassword.GetSize(), 0); + MetaDataManager::GetInstance().DelMeta(metaData_.GetSecretKey(), true); +} + /** * @tc.name: GetDBSecurityTest * @tc.desc: GetDBSecurity @@ -317,7 +403,7 @@ HWTEST_F(KVDBGeneralStoreTest, BusyClose, TestSize.Level0) HWTEST_F(KVDBGeneralStoreTest, SyncTest, TestSize.Level0) { ZLOGI("SyncTest start"); - mkdir(("/data/service/el1/public/database/" + std::string(bundleName)).c_str(), + mkdir(("/data/service/el1/public/database/" + std::string(BUNDLE_NAME)).c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); auto store = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store, nullptr); @@ -332,6 +418,7 @@ HWTEST_F(KVDBGeneralStoreTest, SyncTest, TestSize.Level0) EXPECT_NE(ret.first, GeneralError::E_OK); auto status = store->Close(); EXPECT_EQ(status, GeneralError::E_OK); + delete store; } /** @@ -442,32 +529,101 @@ HWTEST_F(KVDBGeneralStoreTest, GetDBSyncCompleteCB, TestSize.Level0) } /** -* @tc.name: CloudSync +* @tc.name: CloudSync001 +* @tc.desc: Test the scenario where the QueryUsers return false in the CloudSync function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(KVDBGeneralStoreTest, CloudSync001, TestSize.Level0) +{ + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + store->SetEqualIdentifier(BUNDLE_NAME, STORE_NAME); + KvStoreNbDelegateMock mockDelegate; + store->delegate_ = &mockDelegate; + std::vector devices = { "device1", "device2" }; + auto asyncs = [](const GenDetails &result) {}; + store->storeInfo_.user = 0; + auto cloudSyncMode = DistributedDB::SyncMode::SYNC_MODE_PUSH_ONLY; + store->SetEqualIdentifier(BUNDLE_NAME, STORE_NAME); + std::string prepareTraceId; + std::vector users; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(users), Return(false))); + auto ret = store->CloudSync(devices, cloudSyncMode, asyncs, 0, prepareTraceId); + EXPECT_EQ(ret, DBStatus::DB_ERROR); + store->delegate_ = nullptr; + delete store; +} + +/** +* @tc.name: CloudSync002 * @tc.desc: CloudSync test the functionality of different branches. * @tc.type: FUNC * @tc.require: -* @tc.author: SQL +* @tc.author: */ -HWTEST_F(KVDBGeneralStoreTest, CloudSync, TestSize.Level0) +HWTEST_F(KVDBGeneralStoreTest, CloudSync002, TestSize.Level0) { auto store = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store, nullptr); - store->SetEqualIdentifier(bundleName, storeName); + store->SetEqualIdentifier(BUNDLE_NAME, STORE_NAME); KvStoreNbDelegateMock mockDelegate; store->delegate_ = &mockDelegate; std::vector devices = { "device1", "device2" }; auto asyncs = [](const GenDetails &result) {}; store->storeInfo_.user = 0; auto cloudSyncMode = DistributedDB::SyncMode::SYNC_MODE_PUSH_ONLY; - store->SetEqualIdentifier(bundleName, storeName); + store->SetEqualIdentifier(BUNDLE_NAME, STORE_NAME); std::string prepareTraceId; + std::vector users; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)) + .Times(1) + .WillOnce(DoAll( + SetArgReferee<0>(users), + Invoke([](std::vector& users) { users.clear(); }), + Return(true))); auto ret = store->CloudSync(devices, cloudSyncMode, asyncs, 0, prepareTraceId); - EXPECT_EQ(ret, DBStatus::OK); + EXPECT_EQ(ret, DBStatus::DB_ERROR); store->storeInfo_.user = 1; cloudSyncMode = DistributedDB::SyncMode::SYNC_MODE_CLOUD_FORCE_PUSH; ret = store->CloudSync(devices, cloudSyncMode, asyncs, 0, prepareTraceId); EXPECT_EQ(ret, DBStatus::OK); + store->delegate_ = nullptr; + delete store; +} + +/** +* @tc.name: CloudSync003 +* @tc.desc: Test the scenario where the QueryUsers return true in the CloudSync function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(KVDBGeneralStoreTest, CloudSync003, TestSize.Level0) +{ + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + store->SetEqualIdentifier(BUNDLE_NAME, STORE_NAME); + KvStoreNbDelegateMock mockDelegate; + store->delegate_ = &mockDelegate; + std::vector devices = { "device1", "device2" }; + auto asyncs = [](const GenDetails &result) {}; + store->storeInfo_.user = 0; + auto cloudSyncMode = DistributedDB::SyncMode::SYNC_MODE_PUSH_ONLY; + store->SetEqualIdentifier(BUNDLE_NAME, STORE_NAME); + std::string prepareTraceId; + std::vector users = {0, 1}; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)) + .Times(1) + .WillOnce(DoAll( + SetArgReferee<0>(users), + Return(true))); + auto ret = store->CloudSync(devices, cloudSyncMode, asyncs, 0, prepareTraceId); + EXPECT_EQ(ret, DBStatus::OK); + store->delegate_ = nullptr; + delete store; } /** @@ -481,7 +637,7 @@ HWTEST_F(KVDBGeneralStoreTest, GetIdentifierParams, TestSize.Level0) { auto store = new (std::nothrow) KVDBGeneralStore(metaData_); std::vector sameAccountDevs{}; - std::vector uuids{"uuidtest01", "uuidtest02", "uuidtest03"}; + std::vector uuids{ "uuidtest01", "uuidtest02", "uuidtest03" }; store->GetIdentifierParams(sameAccountDevs, uuids, 0); // NO_ACCOUNT for (const auto &devId : uuids) { EXPECT_EQ(DMAdapter::GetInstance().IsOHOSType(devId), false); @@ -491,15 +647,15 @@ HWTEST_F(KVDBGeneralStoreTest, GetIdentifierParams, TestSize.Level0) } /** -* @tc.name: Sync -* @tc.desc: Sync test the functionality of different branches. +* @tc.name: Sync002 +* @tc.desc: Sync test the functionality of 3 < syncMode < 7 branches. * @tc.type: FUNC * @tc.require: -* @tc.author: SQL +* @tc.author: */ -HWTEST_F(KVDBGeneralStoreTest, Sync, TestSize.Level0) +HWTEST_F(KVDBGeneralStoreTest, Sync002, TestSize.Level0) { - mkdir(("/data/service/el1/public/database/" + std::string(bundleName)).c_str(), + mkdir(("/data/service/el1/public/database/" + std::string(BUNDLE_NAME)).c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); auto store = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store, nullptr); @@ -512,6 +668,8 @@ HWTEST_F(KVDBGeneralStoreTest, Sync, TestSize.Level0) syncParam.mode = mixMode; KvStoreNbDelegateMock mockDelegate; store->delegate_ = &mockDelegate; + std::vector users1 = { 0, 1 }; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).WillRepeatedly(DoAll(SetArgReferee<0>(users1), Return(true))); auto ret = store->Sync({}, query, [](const GenDetails &result) {}, syncParam); EXPECT_EQ(ret.first, GeneralError::E_NOT_SUPPORT); GeneralStore::StoreConfig storeConfig; @@ -519,13 +677,34 @@ HWTEST_F(KVDBGeneralStoreTest, Sync, TestSize.Level0) store->SetConfig(storeConfig); ret = store->Sync({}, query, [](const GenDetails &result) {}, syncParam); EXPECT_EQ(ret.first, GeneralError::E_OK); + store->delegate_ = nullptr; + delete store; +} - syncMode = GeneralStore::SyncMode::NEARBY_END; - mixMode = GeneralStore::MixMode(syncMode, highMode); +/** +* @tc.name: Sync003 +* @tc.desc: Sync test the functionality of different branches. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(KVDBGeneralStoreTest, Sync003, TestSize.Level0) +{ + mkdir(("/data/service/el1/public/database/" + std::string(BUNDLE_NAME)).c_str(), + (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + auto store = new (std::nothrow) KVDBGeneralStore(metaData_); + ASSERT_NE(store, nullptr); + uint32_t syncMode = GeneralStore::SyncMode::NEARBY_END; + uint32_t highMode = GeneralStore::HighMode::MANUAL_SYNC_MODE; + auto mixMode = GeneralStore::MixMode(syncMode, highMode); + std::string kvQuery = ""; + DistributedKv::KVDBQuery query(kvQuery); + SyncParam syncParam{}; syncParam.mode = mixMode; - ret = store->Sync({}, query, [](const GenDetails &result) {}, syncParam); + KvStoreNbDelegateMock mockDelegate; + store->delegate_ = &mockDelegate; + auto ret = store->Sync({}, query, [](const GenDetails &result) {}, syncParam); EXPECT_EQ(ret.first, GeneralError::E_INVALID_ARGS); - std::vector devices = { "device1", "device2" }; syncMode = GeneralStore::SyncMode::NEARBY_SUBSCRIBE_REMOTE; mixMode = GeneralStore::MixMode(syncMode, highMode); @@ -550,6 +729,8 @@ HWTEST_F(KVDBGeneralStoreTest, Sync, TestSize.Level0) syncParam.mode = mixMode; ret = store->Sync(devices, query, [](const GenDetails &result) {}, syncParam); EXPECT_EQ(ret.first, GeneralError::E_INVALID_ARGS); + store->delegate_ = nullptr; + delete store; } /** @@ -567,7 +748,7 @@ HWTEST_F(KVDBGeneralStoreTest, Clean, TestSize.Level0) std::string tableName = "tableName"; auto ret = store->Clean(devices, -1, tableName); EXPECT_EQ(ret, GeneralError::E_INVALID_ARGS); - ret = store->Clean(devices, 5, tableName); + ret = store->Clean(devices, 6, tableName); EXPECT_EQ(ret, GeneralError::E_INVALID_ARGS); ret = store->Clean(devices, GeneralStore::CleanMode::NEARBY_DATA, tableName); EXPECT_EQ(ret, GeneralError::E_ALREADY_CLOSED); @@ -587,6 +768,9 @@ HWTEST_F(KVDBGeneralStoreTest, Clean, TestSize.Level0) ret = store->Clean(devices, GeneralStore::CleanMode::LOCAL_DATA, tableName); EXPECT_EQ(ret, GeneralError::E_ERROR); + + ret = store->Clean(devices, GeneralStore::CleanMode::CLEAN_WATER, tableName); + EXPECT_EQ(ret, GeneralError::E_OK); } /** @@ -791,7 +975,7 @@ HWTEST_F(KVDBGeneralStoreTest, GetDBOption001, TestSize.Level0) */ HWTEST_F(KVDBGeneralStoreTest, Sync001, TestSize.Level0) { - mkdir(("/data/service/el1/public/database/" + std::string(bundleName)).c_str(), + mkdir(("/data/service/el1/public/database/" + std::string(BUNDLE_NAME)).c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); auto store = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store, nullptr); @@ -829,7 +1013,6 @@ HWTEST_F(KVDBGeneralStoreTest, Sync001, TestSize.Level0) delete store; } - /** * @tc.name: SetEqualIdentifier * @tc.desc: SetEqualIdentifier test. @@ -841,8 +1024,8 @@ HWTEST_F(KVDBGeneralStoreTest, SetEqualIdentifier, TestSize.Level0) { auto store = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store, nullptr); - std::vector sameAccountDevs{"account01", "account02", "account03"}; - std::vector uuids{"uuidtest01", "uuidtest02", "uuidtest03"}; + std::vector sameAccountDevs{ "account01", "account02", "account03" }; + std::vector uuids{ "uuidtest01", "uuidtest02", "uuidtest03" }; AppId appId01 = { "ohos.kvdbservice.test01" }; StoreId storeId01 = { "meta_test_storeid" }; std::string account = "account"; @@ -862,8 +1045,8 @@ HWTEST_F(KVDBGeneralStoreTest, GetIdentifierParams001, TestSize.Level0) { auto store = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store, nullptr); - std::vector sameAccountDevs{"account01", "account02", "account03"}; - std::vector uuids{"uuidtest01", "uuidtest02", "uuidtest03"}; + std::vector sameAccountDevs{ "account01", "account02", "account03" }; + std::vector uuids{ "uuidtest01", "uuidtest02", "uuidtest03" }; store->GetIdentifierParams(sameAccountDevs, uuids, 1); // for (const auto &devId : uuids) { EXPECT_EQ(DMAdapter::GetInstance().IsOHOSType(devId), false); @@ -947,7 +1130,7 @@ HWTEST_F(KVDBGeneralStoreTest, GetDBProcessCB002, TestSize.Level0) { auto store = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store, nullptr); - std::map processes = {{"test_id", {}}}; + std::map processes = { { "test_id", {} } }; GeneralStore::DetailAsync async; EXPECT_EQ(async, nullptr); auto callback = store->GetDBProcessCB(async); @@ -1027,7 +1210,7 @@ HWTEST_F(KVDBGeneralStoreTest, ConstructorTest, TestSize.Level0) delete store3; // Test observer registration - metaData_.storeId = storeName; + metaData_.storeId = STORE_NAME; metaData_.storeType = DistributedKv::KvStoreType::SINGLE_VERSION; auto store4 = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store4, nullptr); diff --git a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_impl_test.cpp b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_impl_test.cpp index c2f49cc0..03957797 100644 --- a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_impl_test.cpp @@ -13,10 +13,10 @@ * limitations under the License. */ #define LOG_TAG "KvdbServiceImplTest" -#include "kvdb_service_impl.h" - -#include #include +#include + +#include #include #include "bootstrap.h" @@ -25,20 +25,20 @@ #include "cloud/cloud_server.h" #include "device_manager_adapter.h" #include "distributed_kv_data_manager.h" -#include "eventcenter/event_center.h" +#include "event_center.h" #include "ipc_skeleton.h" -#include "kvdb_service_stub.h" #include "kvdb_query.h" +#include "kvdb_service_impl.h" +#include "kvdb_service_stub.h" #include "kvstore_death_recipient.h" #include "kvstore_meta_manager.h" #include "kvstore_sync_manager.h" #include "log_print.h" -#include #include "mock/access_token_mock.h" #include "mock/meta_data_manager_mock.h" +#include "nativetoken_kit.h" #include "network/network_delegate.h" #include "network_delegate_mock.h" -#include "nativetoken_kit.h" #include "token_setproc.h" #include "types.h" #include "utils/anonymous.h" @@ -66,6 +66,7 @@ using StoreMetaData = OHOS::DistributedData::StoreMetaData; using SyncEnd = OHOS::DistributedKv::KvStoreSyncManager::SyncEnd; using DBResult = std::map; using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; +using DBLaunchParam = OHOS::DistributedKv::KVDBServiceImpl::DBLaunchParam; static OHOS::DistributedKv::StoreId storeId = { "kvdb_test_storeid" }; static OHOS::DistributedKv::AppId appId = { "ohos.test.kvdb" }; static constexpr const char *TEST_USER = "0"; @@ -75,8 +76,11 @@ class KvdbServiceImplTest : public testing::Test { public: static inline std::shared_ptr accTokenMock = nullptr; static inline std::shared_ptr metaDataManagerMock = nullptr; + static inline std::shared_ptr> metaDataMock = nullptr; static constexpr size_t NUM_MIN = 5; static constexpr size_t NUM_MAX = 12; + static constexpr uint32_t TOKENID1 = 123; + static constexpr uint32_t TOKENID2 = 456; static DistributedKvDataManager manager; static Options create; static UserId userId; @@ -92,7 +96,7 @@ public: static void RemoveAllStore(OHOS::DistributedKv::DistributedKvDataManager &manager); void SetUp(); void TearDown(); - + void CreateStoreMetaData(std::vector &datas, DBLaunchParam param); KvdbServiceImplTest(); protected: @@ -152,6 +156,8 @@ void KvdbServiceImplTest::SetUpTestCase(void) BAccessTokenKit::accessTokenkit = accTokenMock; metaDataManagerMock = std::make_shared(); BMetaDataManager::metaDataManager = metaDataManagerMock; + metaDataMock = std::make_shared>(); + BMetaData::metaDataManager = metaDataMock; NetworkDelegate::RegisterNetworkInstance(&delegate_); } @@ -165,6 +171,8 @@ void KvdbServiceImplTest::TearDownTestCase() BAccessTokenKit::accessTokenkit = nullptr; metaDataManagerMock = nullptr; BMetaDataManager::metaDataManager = nullptr; + metaDataMock = nullptr; + BMetaData::metaDataManager = nullptr; } void KvdbServiceImplTest::SetUp(void) @@ -193,7 +201,60 @@ void SyncEndCallback(const std::map &statu } } -KvdbServiceImplTest::KvdbServiceImplTest(void) {} +KvdbServiceImplTest::KvdbServiceImplTest(void) +{ +} + +void KvdbServiceImplTest::CreateStoreMetaData(std::vector &datas, DBLaunchParam param) +{ + std::vector metaData; + + // 1: storeType out of range. + StoreMetaData meta1; + meta1.storeType = StoreMetaData::StoreType::STORE_KV_BEGIN - 1; + metaData.push_back(meta1); + + StoreMetaData meta2; + meta2.storeType = StoreMetaData::StoreType::STORE_KV_END + 1; + metaData.push_back(meta2); + + // 2: user ID mismatch. + StoreMetaData meta3; + meta3.storeType = StoreMetaData::StoreType::STORE_KV_BEGIN; + meta3.user = "user2"; // param.userId = "user1" + metaData.push_back(meta3); + + // 3: appId equals to process label. + StoreMetaData meta4; + meta4.storeType = StoreMetaData::StoreType::STORE_KV_BEGIN; + meta4.appId = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); + metaData.push_back(meta4); + + // 4: The identifier does not match and CompareTripleIdentifier is false. + StoreMetaData meta5; + meta5.storeType = StoreMetaData::StoreType::STORE_KV_BEGIN; + meta5.storeId = "store_id_1"; + meta5.appId = "app_id_1"; + metaData.push_back(meta5); + + // 5: Normal execution logic. + StoreMetaData meta6; + meta6.storeType = StoreMetaData::StoreType::STORE_KV_BEGIN; + meta6.user = param.userId; // param.userId = "user1" + meta6.appId = "valid_app_id"; + meta6.storeId = "store_id_2"; + meta6.tokenId = TOKENID1; + metaData.push_back(meta6); + + // 6: trigger SetEqualIdentifier. + StoreMetaData meta7; + meta7.storeType = StoreMetaData::StoreType::STORE_KV_BEGIN; + meta7.user = param.userId; + meta7.appId = "valid_app_id"; + meta7.storeId = "store_id_3"; + meta7.tokenId = TOKENID2; + metaData.push_back(meta7); +} /** * @tc.name: KvdbServiceImpl001 @@ -231,8 +292,9 @@ HWTEST_F(KvdbServiceImplTest, KvdbServiceImpl001, TestSize.Level0) status = kvdbServiceImpl_->UnsubscribeSwitchData(appId); EXPECT_EQ(status, Status::SUCCESS); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return - (ATokenTypeEnum::TOKEN_NATIVE)).WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); status = kvdbServiceImpl_->Close(appId, id1, 0); EXPECT_EQ(status, Status::SUCCESS); } @@ -256,7 +318,7 @@ HWTEST_F(KvdbServiceImplTest, OnInitialize001, TestSize.Level0) auto event = std::make_unique(CloudEvent::CLOUD_SYNC, storeInfo); EXPECT_NE(event, nullptr); result = EventCenter::GetInstance().PostEvent(move(event)); - EXPECT_EQ(result, 1); // CODE_SYNC + EXPECT_EQ(result, 1); // CODE_SYNC auto event1 = std::make_unique(CloudEvent::CLEAN_DATA, storeInfo); EXPECT_NE(event1, nullptr); result = EventCenter::GetInstance().PostEvent(move(event1)); @@ -320,8 +382,9 @@ HWTEST_F(KvdbServiceImplTest, DeleteTest001, TestSize.Level0) Status status1 = manager.GetSingleKvStore(create, appId, storeId, kvStore); ASSERT_NE(kvStore, nullptr); ASSERT_EQ(status1, Status::SUCCESS); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return - (ATokenTypeEnum::TOKEN_NATIVE)).WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); auto status = kvdbServiceImpl_->Delete(appId, storeId, 0); ZLOGI("DeleteTest001 status = :%{public}d", status); ASSERT_EQ(status, Status::SUCCESS); @@ -338,8 +401,9 @@ HWTEST_F(KvdbServiceImplTest, DeleteTest002, TestSize.Level0) ZLOGI("DeleteTest002 start"); AppId appId01 = { "ohos.kvdbserviceimpl.test01" }; StoreId storeId01 = { "meta_test_storeid" }; - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return - (ATokenTypeEnum::TOKEN_NATIVE)).WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); auto status = kvdbServiceImpl_->Delete(appId01, storeId01, 0); ZLOGI("DeleteTest002 status = :%{public}d", status); ASSERT_EQ(status, Status::SUCCESS); @@ -353,9 +417,11 @@ HWTEST_F(KvdbServiceImplTest, DeleteTest002, TestSize.Level0) */ HWTEST_F(KvdbServiceImplTest, DeleteTest003, TestSize.Level0) { - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); - EXPECT_CALL(*accTokenMock, GetHapTokenInfo(testing::_, testing::_)).WillOnce(testing::Return(-1)) + EXPECT_CALL(*accTokenMock, GetHapTokenInfo(testing::_, testing::_)) + .WillOnce(testing::Return(-1)) .WillRepeatedly(testing::Return(-1)); int32_t status = kvdbServiceImpl_->Delete(appId, storeId, 0); EXPECT_EQ(status, DistributedKv::ILLEGAL_STATE); @@ -369,9 +435,11 @@ HWTEST_F(KvdbServiceImplTest, DeleteTest003, TestSize.Level0) */ HWTEST_F(KvdbServiceImplTest, CloseTest001, TestSize.Level0) { - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); - EXPECT_CALL(*accTokenMock, GetHapTokenInfo(testing::_, testing::_)).WillOnce(testing::Return(-1)) + EXPECT_CALL(*accTokenMock, GetHapTokenInfo(testing::_, testing::_)) + .WillOnce(testing::Return(-1)) .WillRepeatedly(testing::Return(-1)); int32_t status = kvdbServiceImpl_->Close(appId, storeId, 0); EXPECT_EQ(status, DistributedKv::ILLEGAL_STATE); @@ -386,29 +454,29 @@ HWTEST_F(KvdbServiceImplTest, CloseTest001, TestSize.Level0) HWTEST_F(KvdbServiceImplTest, OnAsyncCompleteTest001, TestSize.Level0) { DistributedKv::Statistic upload; - upload.failed = 1; // test - upload.success = 1; // test - upload.total = 1; // test + upload.failed = 1; // test + upload.success = 1; // test + upload.total = 1; // test upload.untreated = 1; // test DistributedKv::Statistic download; - download.failed = 1; // test - download.success = 1; // test - download.total = 1; // test + download.failed = 1; // test + download.success = 1; // test + download.total = 1; // test download.untreated = 1; // test DistributedKv::TableDetail details; details.download = download; details.upload = upload; DistributedKv::ProgressDetail detail; - detail.code = 1; // test + detail.code = 1; // test detail.progress = 1; // test detail.details = details; sptr notifier; DistributedKv::KVDBServiceImpl::SyncAgent syncAgent; - syncAgent.pid_ = 1; // test + syncAgent.pid_ = 1; // test syncAgent.switchesObserverCount_ = 1; // test syncAgent.appId_ = { "ohos.OnAsyncCompleteTest001.kvdb" }; syncAgent.notifier_ = notifier; - kvdbServiceImpl_->syncAgents_.Insert(100, syncAgent); // test + kvdbServiceImpl_->syncAgents_.Insert(100, syncAgent); // test kvdbServiceImpl_->OnAsyncComplete(1, 1, std::move(detail)); // test EXPECT_EQ(kvdbServiceImpl_->syncAgents_.Find(1).first, false); kvdbServiceImpl_->OnAsyncComplete(100, 1, std::move(detail)); // test @@ -464,7 +532,7 @@ HWTEST_F(KvdbServiceImplTest, UnregServiceNotifierTest001, TestSize.Level0) ASSERT_EQ(status1, Status::SUCCESS); sptr notifier; DistributedKv::KVDBServiceImpl::SyncAgent syncAgent; - syncAgent.pid_ = 1; // test + syncAgent.pid_ = 1; // test syncAgent.switchesObserverCount_ = 1; // test syncAgent.appId_ = { "ohos.OnAsyncCompleteTest001.kvdb" }; syncAgent.notifier_ = notifier; @@ -548,11 +616,13 @@ HWTEST_F(KvdbServiceImplTest, EnableCapabilityTest001, TestSize.Level0) Status status1 = manager.GetSingleKvStore(create, appId, storeId, kvStore); ASSERT_NE(kvStore, nullptr); ASSERT_EQ(status1, Status::SUCCESS); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); auto status = kvdbServiceImpl_->EnableCapability(appId, storeId, 0); ASSERT_EQ(status, Status::SUCCESS); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); status = kvdbServiceImpl_->EnableCapability(appId, storeId, 0); ASSERT_EQ(status, Status::ILLEGAL_STATE); @@ -569,7 +639,8 @@ HWTEST_F(KvdbServiceImplTest, GetInstIndexTest001, TestSize.Level0) Status status1 = manager.GetSingleKvStore(create, appId, storeId, kvStore); ASSERT_NE(kvStore, nullptr); ASSERT_EQ(status1, Status::SUCCESS); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); auto status = kvdbServiceImpl_->GetInstIndex(100, appId); ASSERT_EQ(status, -1); @@ -587,13 +658,15 @@ HWTEST_F(KvdbServiceImplTest, IsNeedMetaSyncTest001, TestSize.Level0) ASSERT_NE(kvStore, nullptr); ASSERT_EQ(status1, Status::SUCCESS); StoreMetaData meta = kvdbServiceImpl_->GetStoreMetaData(appId, storeId); - std::vector uuids{"uuidtest01"}; + std::vector uuids{ "uuidtest01" }; EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)) - .WillOnce(testing::Return(true)).WillRepeatedly(testing::Return(true)); + .WillOnce(testing::Return(true)) + .WillRepeatedly(testing::Return(true)); auto status = kvdbServiceImpl_->IsNeedMetaSync(meta, uuids); ASSERT_EQ(status, false); EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)) - .WillOnce(testing::Return(false)).WillRepeatedly(testing::Return(false)); + .WillOnce(testing::Return(false)) + .WillRepeatedly(testing::Return(false)); status = kvdbServiceImpl_->IsNeedMetaSync(meta, uuids); ASSERT_EQ(status, true); } @@ -611,11 +684,13 @@ HWTEST_F(KvdbServiceImplTest, GetDistributedDataMetaTest001, TestSize.Level0) ASSERT_EQ(status, Status::SUCCESS); std::string deviceId = "KvdbServiceImplTest_deviceId"; EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)) - .WillOnce(testing::Return(false)).WillRepeatedly(testing::Return(false)); + .WillOnce(testing::Return(false)) + .WillRepeatedly(testing::Return(false)); auto meta = kvdbServiceImpl_->GetDistributedDataMeta(deviceId); ASSERT_EQ(meta.user, "0"); EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)) - .WillOnce(testing::Return(true)).WillRepeatedly(testing::Return(true)); + .WillOnce(testing::Return(true)) + .WillRepeatedly(testing::Return(true)); meta = kvdbServiceImpl_->GetDistributedDataMeta(deviceId); ASSERT_EQ(meta.deviceId, deviceId); } @@ -651,7 +726,7 @@ HWTEST_F(KvdbServiceImplTest, DoSyncBeginTest001, TestSize.Level0) Status status = manager.GetSingleKvStore(create, appId, storeId, kvStore); ASSERT_NE(kvStore, nullptr); ASSERT_EQ(status, Status::SUCCESS); - std::vector device1{"uuidtest01"}; + std::vector device1{ "uuidtest01" }; std::vector device2; StoreMetaData meta = kvdbServiceImpl_->GetStoreMetaData(appId, storeId); SyncInfo syncInfo; @@ -687,12 +762,14 @@ HWTEST_F(KvdbServiceImplTest, DoCompleteTest001, TestSize.Level0) DBResult dbResult; dbResult.insert_or_assign("DoCompleteTest_1", DBStatus::OK); dbResult.insert_or_assign("DoCompleteTest_1", DBStatus::DB_ERROR); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); status = kvdbServiceImpl_->DoComplete(meta, syncInfo, refCount, dbResult); ASSERT_EQ(status, Status::SUCCESS); syncInfo.seqId = std::numeric_limits::max(); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); status = kvdbServiceImpl_->DoComplete(meta, syncInfo, refCount, dbResult); ASSERT_EQ(status, Status::SUCCESS); @@ -712,7 +789,7 @@ HWTEST_F(KvdbServiceImplTest, ConvertDbStatusNativeTest001, TestSize.Level0) ASSERT_EQ(status, Status::DEVICE_NOT_ONLINE); DBStatus dbstatus = static_cast(DBStatus::OK - 1); status = kvdbServiceImpl_->ConvertDbStatusNative(dbstatus); - ASSERT_EQ(status, - 1); + ASSERT_EQ(status, -1); } /** @@ -765,12 +842,14 @@ HWTEST_F(KvdbServiceImplTest, DisableCapabilityTest001, TestSize.Level0) Status status1 = manager.GetSingleKvStore(create, appId, storeId, kvStore); ASSERT_NE(kvStore, nullptr); ASSERT_EQ(status1, Status::SUCCESS); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); auto status = kvdbServiceImpl_->DisableCapability(appId, storeId, 0); ZLOGI("DisableCapabilityTest001 status = :%{public}d", status); ASSERT_EQ(status, Status::SUCCESS); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); status = kvdbServiceImpl_->EnableCapability(appId, storeId, 0); ASSERT_EQ(status, Status::ILLEGAL_STATE); @@ -790,12 +869,14 @@ HWTEST_F(KvdbServiceImplTest, SetCapabilityTest001, TestSize.Level0) ASSERT_EQ(status1, Status::SUCCESS); std::vector local; std::vector remote; - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); auto status = kvdbServiceImpl_->SetCapability(appId, storeId, 0, local, remote); ZLOGI("SetCapabilityTest001 status = :%{public}d", status); ASSERT_EQ(status, Status::SUCCESS); - EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)).WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); status = kvdbServiceImpl_->EnableCapability(appId, storeId, 0); ASSERT_EQ(status, Status::ILLEGAL_STATE); @@ -872,7 +953,7 @@ HWTEST_F(KvdbServiceImplTest, UnsubscribeTest001, TestSize.Level0) ASSERT_EQ(status1, Status::SUCCESS); sptr notifier; DistributedKv::KVDBServiceImpl::SyncAgent syncAgent; - syncAgent.pid_ = 1; // test + syncAgent.pid_ = 1; // test syncAgent.switchesObserverCount_ = 1; // test syncAgent.appId_ = { "ohos.OnAsyncCompleteTest001.kvdb" }; syncAgent.notifier_ = notifier; @@ -884,29 +965,6 @@ HWTEST_F(KvdbServiceImplTest, UnsubscribeTest001, TestSize.Level0) ASSERT_EQ(status, Status::SUCCESS); } -/** -* @tc.name: GetBackupPasswordTest001 -* @tc.desc: GetBackupPassword test -* @tc.type: FUNC -* @tc.author: wangbin -*/ -HWTEST_F(KvdbServiceImplTest, GetBackupPasswordTest001, TestSize.Level0) -{ - auto status = manager.GetSingleKvStore(create, appId, storeId, kvStore); - ASSERT_NE(kvStore, nullptr); - ASSERT_EQ(status, Status::SUCCESS); - std::vector> password; - status = kvdbServiceImpl_->GetBackupPassword - (appId, storeId, 0, password, DistributedKv::KVDBService::PasswordType::BACKUP_SECRET_KEY); - ASSERT_EQ(status, Status::ERROR); - status = kvdbServiceImpl_->GetBackupPassword - (appId, storeId, 0, password, DistributedKv::KVDBService::PasswordType::SECRET_KEY); - ASSERT_EQ(status, Status::ERROR); - status = kvdbServiceImpl_->GetBackupPassword - (appId, storeId, 0, password, DistributedKv::KVDBService::PasswordType::BUTTON); - ASSERT_EQ(status, Status::ERROR); -} - /** * @tc.name: BeforeCreateTest001 * @tc.desc: BeforeCreate test @@ -929,7 +987,8 @@ HWTEST_F(KvdbServiceImplTest, BeforeCreateTest001, TestSize.Level0) creates.cloudConfig.enableCloud = true; kvdbServiceImpl_->executors_ = std::make_shared(1, 1); EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)) - .WillOnce(testing::Return(false)).WillRepeatedly(testing::Return(false)); + .WillOnce(testing::Return(false)) + .WillRepeatedly(testing::Return(false)); auto status = kvdbServiceImpl_->BeforeCreate(appId, storeId, creates); ASSERT_NE(status, Status::STORE_META_CHANGED); kvdbServiceImpl_->executors_ = nullptr; @@ -1061,6 +1120,7 @@ HWTEST_F(KvdbServiceImplTest, ResolveAutoLaunch, TestSize.Level0) EXPECT_EQ(status, Status::SUCCESS); std::string identifier = "identifier"; DistributedKv::KVDBServiceImpl::DBLaunchParam launchParam; + launchParam.userId = "user1"; auto result = kvdbServiceImpl_->ResolveAutoLaunch(identifier, launchParam); EXPECT_EQ(result, Status::STORE_NOT_FOUND); std::shared_ptr executors = std::make_shared(1, 0); @@ -1069,6 +1129,10 @@ HWTEST_F(KvdbServiceImplTest, ResolveAutoLaunch, TestSize.Level0) DistributedKv::KvStoreMetaManager::GetInstance().BindExecutor(executors); DistributedKv::KvStoreMetaManager::GetInstance().InitMetaParameter(); DistributedKv::KvStoreMetaManager::GetInstance().InitMetaListener(); + std::vector datas; + CreateStoreMetaData(datas, launchParam); + EXPECT_CALL(*metaDataMock, LoadMeta(testing::_, testing::_, testing::_)) + .WillRepeatedly(testing::DoAll(testing::SetArgReferee<1>(datas), testing::Return(true))); result = kvdbServiceImpl_->ResolveAutoLaunch(identifier, launchParam); EXPECT_EQ(result, Status::SUCCESS); } @@ -1317,25 +1381,25 @@ HWTEST_F(KvdbServiceImplTest, DoCloudSync01, TestSize.Level0) HWTEST_F(KvdbServiceImplTest, OnAsyncCompleteTest002, TestSize.Level0) { DistributedKv::Statistic upload; - upload.failed = 1; // test - upload.success = 1; // test - upload.total = 1; // test + upload.failed = 1; // test + upload.success = 1; // test + upload.total = 1; // test upload.untreated = 1; // test DistributedKv::Statistic download; - download.failed = 1; // test - download.success = 1; // test - download.total = 1; // test + download.failed = 1; // test + download.success = 1; // test + download.total = 1; // test download.untreated = 1; // test DistributedKv::TableDetail details; details.download = download; details.upload = upload; DistributedKv::ProgressDetail detail; - detail.code = 1; // test + detail.code = 1; // test detail.progress = 1; // test detail.details = details; DistributedKv::KVDBServiceImpl::SyncAgent syncAgent; sptr notifier = nullptr; - syncAgent.pid_ = 1; // test + syncAgent.pid_ = 1; // test syncAgent.switchesObserverCount_ = 1; // test syncAgent.appId_ = { "ohos.OnAsyncCompleteTest.kvdb" }; syncAgent.notifier_ = notifier; @@ -1359,7 +1423,7 @@ HWTEST_F(KvdbServiceImplTest, OnAsyncCompleteTest003, TestSize.Level0) { DistributedKv::KVDBServiceImpl::SyncAgent syncAgent; sptr notifier; - syncAgent.pid_ = 1; // test + syncAgent.pid_ = 1; // test syncAgent.switchesObserverCount_ = 1; // test syncAgent.appId_ = { "ohos.OnAsyncCompleteTest001.kvdb" }; syncAgent.notifier_ = notifier; @@ -1431,16 +1495,36 @@ HWTEST_F(KvdbServiceImplTest, syncTest003, TestSize.Level0) SyncInfo syncInfo; syncInfo.seqId = std::numeric_limits::max(); EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)) - .WillOnce(testing::Return(true)).WillRepeatedly(testing::Return(true)); + .WillOnce(testing::Return(true)) + .WillRepeatedly(testing::Return(true)); auto status = kvdbServiceImpl_->Sync(appId, storeId, 0, syncInfo); EXPECT_EQ(localMeta.HasPolicy(DistributedKv::IMMEDIATE_SYNC_ON_CHANGE), false); EXPECT_NE(status, Status::SUCCESS); EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)) - .WillOnce(testing::Return(false)).WillRepeatedly(testing::Return(false)); + .WillOnce(testing::Return(false)) + .WillRepeatedly(testing::Return(false)); status = kvdbServiceImpl_->Sync(appId, storeId, 0, syncInfo); EXPECT_EQ(localMeta.HasPolicy(DistributedKv::IMMEDIATE_SYNC_ON_ONLINE), true); } +/** +* @tc.name: SyncTest004 +* @tc.desc: twin application sync test +* @tc.type: FUNC +*/ +HWTEST_F(KvdbServiceImplTest, SyncTest004, TestSize.Level0) +{ + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); + EXPECT_CALL(*accTokenMock, GetHapTokenInfo(testing::_, testing::_)) + .WillOnce(testing::Return(0)) + .WillRepeatedly(testing::Return(0)); + SyncInfo syncInfo; + auto status = kvdbServiceImpl_->Sync(appId, storeId, 0, syncInfo); + ASSERT_EQ(status, Status::NOT_SUPPORT); +} + /** * @tc.name: GetSyncParamTest001 * @tc.desc: GetStoreIds @@ -1472,7 +1556,7 @@ HWTEST_F(KvdbServiceImplTest, GetSyncParamTest002, TestSize.Level0) HWTEST_F(KvdbServiceImplTest, SubscribeSwitchData, TestSize.Level0) { options_.isNeedCompress = false; - std::vector password {}; + std::vector password{}; StoreMetaData metaData; auto status = kvdbServiceImpl_->AfterCreate(appId, storeId, options_, password); ASSERT_EQ(status, Status::SUCCESS); diff --git a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_password_test.cpp b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_password_test.cpp new file mode 100644 index 00000000..2d30d07c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_password_test.cpp @@ -0,0 +1,201 @@ +/* +* 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 "kvdb_service_impl.h" + +#include +#include + +#include "device_manager_adapter.h" +#include "ipc_skeleton.h" +#include "mock/db_store_mock.h" + +namespace OHOS::Test { +using namespace testing::ext; +using namespace OHOS::DistributedData; +using namespace OHOS::DistributedKv; + +static constexpr int32_t KEY_LENGTH = 32; +static constexpr int32_t TEST_USER_NUM = 0; +static constexpr const char *TEST_USER = "0"; +static constexpr const char *TEST_APP_ID = "KvdbServicePasswordTest"; +static constexpr const char *TEST_STORE_ID = "StoreTest"; + +class KvdbServicePasswordTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void) {} + void SetUp() {} + void TearDown() {} + + static std::vector Random(int32_t len); + + static AppId appId_; + static StoreId storeId_; + static StoreMetaData metaData_; + static std::shared_ptr kvdbServiceImpl_; +}; + +AppId KvdbServicePasswordTest::appId_; +StoreId KvdbServicePasswordTest::storeId_; +StoreMetaData KvdbServicePasswordTest::metaData_; +std::shared_ptr KvdbServicePasswordTest::kvdbServiceImpl_; + +void KvdbServicePasswordTest::SetUpTestCase(void) +{ + appId_ = { TEST_APP_ID }; + storeId_ = { TEST_STORE_ID }; + kvdbServiceImpl_ = std::make_shared(); + metaData_.deviceId = DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; + metaData_.bundleName = TEST_APP_ID; + metaData_.appId = TEST_APP_ID; + metaData_.storeId = TEST_STORE_ID; + metaData_.user = TEST_USER; + metaData_.area = Area::EL1; + metaData_.tokenId = IPCSkeleton::GetSelfTokenID(); + (void)CryptoManager::GetInstance().GenerateRootKey(); +} + +std::vector KvdbServicePasswordTest::Random(int32_t len) +{ + std::random_device randomDevice; + std::uniform_int_distribution distribution(0, std::numeric_limits::max()); + std::vector key(len); + for (uint32_t i = 0; i < len; i++) { + key[i] = static_cast(distribution(randomDevice)); + } + return key; +} + +/** +* @tc.name: GetBackupPasswordTest001 +* @tc.desc: get backup password with exception branch +* @tc.type: FUNC +*/ +HWTEST_F(KvdbServicePasswordTest, GetBackupPasswordTest001, TestSize.Level0) +{ + std::vector> passwords; + + auto status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::BACKUP_SECRET_KEY); + ASSERT_EQ(status, Status::ERROR); + + status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::SECRET_KEY); + ASSERT_EQ(status, Status::ERROR); + + status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::BUTTON); + ASSERT_EQ(status, Status::ERROR); + + std::shared_ptr dbStoreMock = std::make_shared(); + MetaDataManager::GetInstance().Initialize(dbStoreMock, nullptr, ""); + SecretKeyMetaData secretKey; + + auto result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_TRUE(result); + status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::SECRET_KEY); + ASSERT_EQ(status, Status::ERROR); + + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetCloneSecretKey(), secretKey, true); + ASSERT_TRUE(result); + status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::SECRET_KEY); + ASSERT_EQ(status, Status::ERROR); + + auto key = Random(KEY_LENGTH); + ASSERT_FALSE(key.empty()); + secretKey.sKey = key; + + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_TRUE(result); + status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::SECRET_KEY); + ASSERT_EQ(status, Status::ERROR); + + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetCloneSecretKey(), secretKey, true); + ASSERT_TRUE(result); + status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::SECRET_KEY); + ASSERT_EQ(status, Status::ERROR); + + MetaDataManager::GetInstance().DelMeta(metaData_.GetSecretKey(), true); + MetaDataManager::GetInstance().DelMeta(metaData_.GetCloneSecretKey(), true); +} + +/** +* @tc.name: GetBackupPasswordTest002 +* @tc.desc: get all type password success +* @tc.type: FUNC +*/ +HWTEST_F(KvdbServicePasswordTest, GetBackupPasswordTest002, TestSize.Level0) +{ + auto key = Random(KEY_LENGTH); + ASSERT_FALSE(key.empty()); + + std::shared_ptr dbStoreMock = std::make_shared(); + MetaDataManager::GetInstance().Initialize(dbStoreMock, nullptr, ""); + + CryptoManager::CryptoParams encryptParams; + auto encryptKey = CryptoManager::GetInstance().Encrypt(key, encryptParams); + ASSERT_FALSE(encryptKey.empty()); + ASSERT_FALSE(encryptParams.nonce.empty()); + + SecretKeyMetaData secretKey; + secretKey.sKey = encryptKey; + secretKey.nonce = encryptParams.nonce; + std::vector> passwords; + + // 1.get backup secret key success + auto result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetBackupSecretKey(), secretKey, true); + ASSERT_TRUE(result); + auto status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::BACKUP_SECRET_KEY); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_GT(passwords.size(), 0); + ASSERT_EQ(passwords[0].size(), key.size()); + for (auto i = 0; i < key.size(); ++i) { + ASSERT_EQ(passwords[0][i], key[i]); + } + MetaDataManager::GetInstance().DelMeta(metaData_.GetBackupSecretKey(), true); + + // 2.get secret key success + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), secretKey, true); + ASSERT_TRUE(result); + status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::SECRET_KEY); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_GT(passwords.size(), 0); + ASSERT_EQ(passwords[0].size(), key.size()); + for (auto i = 0; i < key.size(); ++i) { + ASSERT_EQ(passwords[0][i], key[i]); + } + MetaDataManager::GetInstance().DelMeta(metaData_.GetSecretKey(), true); + + // 3.get clone secret key success + result = MetaDataManager::GetInstance().SaveMeta(metaData_.GetCloneSecretKey(), secretKey, true); + ASSERT_TRUE(result); + status = kvdbServiceImpl_->GetBackupPassword( + appId_, storeId_, TEST_USER_NUM, passwords, DistributedKv::KVDBService::PasswordType::SECRET_KEY); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_GT(passwords.size(), 0); + ASSERT_EQ(passwords[0].size(), key.size()); + for (auto i = 0; i < key.size(); ++i) { + ASSERT_EQ(passwords[0][i], key[i]); + } + MetaDataManager::GetInstance().DelMeta(metaData_.GetCloneSecretKey(), true); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_stub_unittest.cpp b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_stub_unittest.cpp index bf41f55f..0c6ffd87 100644 --- a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_stub_unittest.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_stub_unittest.cpp @@ -34,8 +34,13 @@ using StoreId = OHOS::DistributedKv::StoreId; using AppId = OHOS::DistributedKv::AppId; using Options = OHOS::DistributedKv::Options; const std::u16string INTERFACE_TOKEN = u"OHOS.DistributedKv.IKvStoreDataService"; -static OHOS::DistributedKv::StoreId storeId = { "kvdb_test_storeid" }; -static OHOS::DistributedKv::AppId appId = { "ohos.test.kvdb" }; +static const StoreId STOREID = { "kvdb_test_storeid" }; +static const AppId APPID = { "kvdb_test_appid" }; +static const std::string HAPNAME = "testHap"; +static const std::string INVALID_HAPNAME = "./testHap"; +static const StoreId INVALID_STOREID = { "./kvdb_test_storeid" }; +static const AppId INVALID_APPID = { "\\kvdb_test_appid" }; + namespace OHOS::Test { namespace DistributedDataTest { class KVDBServiceStubTest : public testing::Test { @@ -149,35 +154,110 @@ HWTEST_F(KVDBServiceStubTest, CheckPermission001, TestSize.Level1) /** - * @tc.name: OnBeforeCreate + * @tc.name: OnBeforeCreate001 * @tc.desc: Test OnBeforeCreate * @tc.type: FUNC * @tc.require: */ -HWTEST_F(KVDBServiceStubTest, OnBeforeCreate, TestSize.Level1) +HWTEST_F(KVDBServiceStubTest, OnBeforeCreate001, TestSize.Level1) { MessageParcel data; + data.WriteInterfaceToken(INTERFACE_TOKEN); MessageParcel reply; - AppId appId = {"testApp"}; - StoreId storeId = {"testStoreId"}; - auto status = kvdbServiceStub->OnBeforeCreate(appId, storeId, data, reply); + Options options; + options.hapName = HAPNAME; + ITypesUtil::Marshal(data, options); + auto status = kvdbServiceStub->OnBeforeCreate(APPID, STOREID, data, reply); + EXPECT_EQ(status, IPC_STUB_INVALID_DATA_ERR); +} + +/** + * @tc.name: OnBeforeCreate002 + * @tc.desc: Test OnBeforeCreate + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(KVDBServiceStubTest, OnBeforeCreate002, TestSize.Level1) +{ + MessageParcel data; + data.WriteInterfaceToken(INTERFACE_TOKEN); + MessageParcel reply; + Options options; + options.hapName = HAPNAME; + ITypesUtil::Marshal(data, options); + auto status = kvdbServiceStub->OnBeforeCreate(INVALID_APPID, INVALID_STOREID, data, reply); + EXPECT_EQ(status, IPC_STUB_INVALID_DATA_ERR); +} + +/** + * @tc.name: OnBeforeCreate003 + * @tc.desc: Test OnBeforeCreate + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(KVDBServiceStubTest, OnBeforeCreate003, TestSize.Level1) +{ + MessageParcel data; + data.WriteInterfaceToken(INTERFACE_TOKEN); + MessageParcel reply; + Options options; + options.hapName = INVALID_HAPNAME; + ITypesUtil::Marshal(data, options); + auto status = kvdbServiceStub->OnBeforeCreate(APPID, STOREID, data, reply); EXPECT_EQ(status, IPC_STUB_INVALID_DATA_ERR); } /** - * @tc.name: OnAfterCreate + * @tc.name: OnAfterCreate001 * @tc.desc: Test OnAfterCreate * @tc.type: FUNC * @tc.require: */ -HWTEST_F(KVDBServiceStubTest, OnAfterCreate, TestSize.Level1) +HWTEST_F(KVDBServiceStubTest, OnAfterCreate001, TestSize.Level1) { MessageParcel data; data.WriteInterfaceToken(INTERFACE_TOKEN); MessageParcel reply; - AppId appId = {"testApp"}; - StoreId storeId = {"testStore"}; - auto status = kvdbServiceStub->OnAfterCreate(appId, storeId, data, reply); + Options options; + options.hapName = HAPNAME; + ITypesUtil::Marshal(data, options); + auto status = kvdbServiceStub->OnAfterCreate(APPID, STOREID, data, reply); + EXPECT_EQ(status, IPC_STUB_INVALID_DATA_ERR); +} + +/** + * @tc.name: OnAfterCreate002 + * @tc.desc: Test OnAfterCreate + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(KVDBServiceStubTest, OnAfterCreate002, TestSize.Level1) +{ + MessageParcel data; + data.WriteInterfaceToken(INTERFACE_TOKEN); + MessageParcel reply; + Options options; + options.hapName = HAPNAME; + ITypesUtil::Marshal(data, options); + auto status = kvdbServiceStub->OnAfterCreate(INVALID_APPID, INVALID_STOREID, data, reply); + EXPECT_EQ(status, IPC_STUB_INVALID_DATA_ERR); +} + +/** + * @tc.name: OnAfterCreate003 + * @tc.desc: Test OnAfterCreate + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(KVDBServiceStubTest, OnAfterCreate003, TestSize.Level1) +{ + MessageParcel data; + data.WriteInterfaceToken(INTERFACE_TOKEN); + MessageParcel reply; + Options options; + options.hapName = INVALID_HAPNAME; + ITypesUtil::Marshal(data, options); + auto status = kvdbServiceStub->OnAfterCreate(APPID, STOREID, data, reply); EXPECT_EQ(status, IPC_STUB_INVALID_DATA_ERR); } @@ -350,5 +430,37 @@ HWTEST_F(KVDBServiceStubTest, OnRemoveDeviceData, TestSize.Level1) auto status = kvdbServiceStub->OnRemoveDeviceData(appId, storeId, data, reply); EXPECT_EQ(status, IPC_STUB_INVALID_DATA_ERR); } + +/** + * @tc.name: IsValidField001 + * @tc.desc: IsValidField function test. + * @tc.type: FUNC + */ +HWTEST_F(KVDBServiceStubTest, IsValidField001, TestSize.Level0) +{ + EXPECT_TRUE(kvdbServiceStub->IsValidField("validpath")); + EXPECT_TRUE(kvdbServiceStub->IsValidField("another_valid_path")); + EXPECT_TRUE(kvdbServiceStub->IsValidField("file123")); +} + +/** + * @tc.name: IsValidField002 + * @tc.desc: IsValidField function test. + * @tc.type: FUNC + */ +HWTEST_F(KVDBServiceStubTest, IsValidField002, TestSize.Level0) +{ + EXPECT_FALSE(kvdbServiceStub->IsValidField("path/with/forward/slash")); + EXPECT_FALSE(kvdbServiceStub->IsValidField("/starting/slash")); + EXPECT_FALSE(kvdbServiceStub->IsValidField("ending/slash/")); + EXPECT_FALSE(kvdbServiceStub->IsValidField("path\\with\\backslash")); + EXPECT_FALSE(kvdbServiceStub->IsValidField("\\starting\\ending")); + EXPECT_FALSE(kvdbServiceStub->IsValidField("ending\\")); + EXPECT_FALSE(kvdbServiceStub->IsValidField("..")); + EXPECT_FALSE(kvdbServiceStub->IsValidField("path/with\\mixed/slashes")); + EXPECT_FALSE(kvdbServiceStub->IsValidField("path\\with/mixed\\slashes")); +} + + } // namespace DistributedDataTest } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_test.cpp b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_test.cpp index c1a589f4..1ae56025 100644 --- a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_test.cpp @@ -18,7 +18,7 @@ #include "auth_delegate.h" #include "bootstrap.h" #include "change_notification.h" -#include "crypto_manager.h" +#include "crypto/crypto_manager.h" #include "device_manager_adapter.h" #include "directory/directory_manager.h" #include "ikvstore_observer.h" diff --git a/datamgr_service/services/distributeddataservice/service/test/meta_data_test.cpp b/datamgr_service/services/distributeddataservice/service/test/meta_data_test.cpp index 1476b51d..714fd0b5 100644 --- a/datamgr_service/services/distributeddataservice/service/test/meta_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/meta_data_test.cpp @@ -29,6 +29,7 @@ #include "metadata/store_meta_data_local.h" #include "nativetoken_kit.h" #include "token_setproc.h" +#include "directory/directory_manager.h" using namespace testing::ext; using namespace OHOS::DistributedData; using namespace OHOS::Security::AccessToken; @@ -120,6 +121,8 @@ void MetaDataTest::SetUp() metaData_.instanceId = GetInstIndex(metaData_.tokenId, appId); metaData_.version = 1; MetaDataManager::GetInstance().DelMeta(metaData_.GetKey()); + metaData_.area = options_.area; + metaData_.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData_); } void MetaDataTest::TearDown() {} @@ -138,7 +141,7 @@ HWTEST_F(MetaDataTest, SaveLoadMateData, TestSize.Level0) std::vector password {}; auto status = kvdbServiceImpl_->AfterCreate(appId, storeId, options_, password); ASSERT_EQ(status, Status::SUCCESS); - ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetKey(), metaData)); + ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetKeyWithoutPath(), metaData)); ASSERT_TRUE(metaData.isNeedCompress); } @@ -157,9 +160,9 @@ HWTEST_F(MetaDataTest, MateDataChanged, TestSize.Level0) std::vector password {}; auto status = kvdbServiceImpl_->AfterCreate(appId, storeId, options_, password); ASSERT_EQ(status, Status::SUCCESS); - ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetKey(), metaData)); + ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetKeyWithoutPath(), metaData)); ASSERT_FALSE(metaData.isNeedCompress); - ASSERT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData_.GetKey())); + ASSERT_TRUE(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath())); } } // namespace DistributedDataTest } // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/mock/BUILD.gn index a0833e47..10ea0e49 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/mock/BUILD.gn @@ -18,6 +18,8 @@ config("module_private_config") { include_dirs = [ "${data_service_path}/adapter/include/communicator", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/matrix/include/", "../../../framework/include/", "../../../service/rdb/", "./", @@ -27,6 +29,7 @@ config("module_private_config") { } ohos_static_library("distributeddata_mock_static") { + testonly = true branch_protector_ret = "pac_ret" sanitize = { cfi = true @@ -35,18 +38,26 @@ ohos_static_library("distributeddata_mock_static") { } sources = [ + "auth_delegate_mock.cpp", "cursor_mock.cpp", "db_change_data_mock.cpp", "db_store_mock.cpp", + "device_manager_adapter_mock.cpp", "general_store_mock.cpp", "kv_store_nb_delegate_mock.cpp", "network_delegate_mock.cpp", "screen_lock_mock.cpp", + "user_delegate_mock.cpp", + "device_matrix_mock.cpp", ] deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] external_deps = [ + "device_manager:devicemanagersdk", + "googletest:gmock", + "googletest:gtest", + "json:nlohmann_json_static", "kv_store:distributeddata_mgr", "kv_store:distributeddb", "relational_store:native_rdb", diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/access_token_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/access_token_mock.cpp index 0f70c3f3..e3e5addd 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/access_token_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/access_token_mock.cpp @@ -19,14 +19,30 @@ namespace Security { namespace AccessToken { ATokenTypeEnum AccessTokenKit::GetTokenTypeFlag(AccessTokenID tokenID) { + if (BAccessTokenKit::accessTokenkit == nullptr) { + return ATokenTypeEnum::TOKEN_INVALID; + } return BAccessTokenKit::accessTokenkit->GetTokenTypeFlag(tokenID); } +ATokenTypeEnum AccessTokenKit::GetTokenType(AccessTokenID tokenID) +{ + if (BAccessTokenKit::accessTokenkit == nullptr) { + return ATokenTypeEnum::TOKEN_INVALID; + } + return BAccessTokenKit::accessTokenkit->GetTokenType(tokenID); +} + int AccessTokenKit::GetHapTokenInfo(AccessTokenID tokenID, HapTokenInfo& hapTokenInfoRes) { return BAccessTokenKit::accessTokenkit->GetHapTokenInfo(tokenID, hapTokenInfoRes); } +int AccessTokenKit::GetNativeTokenInfo(AccessTokenID tokenID, NativeTokenInfo& nativeTokenInfo) +{ + return BAccessTokenKit::accessTokenkit->GetNativeTokenInfo(tokenID, nativeTokenInfo); +} + int AccessTokenKit::VerifyAccessToken(AccessTokenID tokenID, const std::string& permissionName) { return BAccessTokenKit::accessTokenkit->VerifyAccessToken(tokenID, permissionName); diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/access_token_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/access_token_mock.h index dd6e20e2..e02b6d0d 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/access_token_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/access_token_mock.h @@ -25,7 +25,9 @@ namespace AccessToken { class BAccessTokenKit { public: virtual ATokenTypeEnum GetTokenTypeFlag(AccessTokenID) = 0; + virtual ATokenTypeEnum GetTokenType(AccessTokenID) = 0; virtual int GetHapTokenInfo(AccessTokenID, HapTokenInfo&) = 0; + virtual int GetNativeTokenInfo(AccessTokenID, NativeTokenInfo&) = 0; virtual int VerifyAccessToken(AccessTokenID, const std::string&) = 0; BAccessTokenKit() = default; virtual ~BAccessTokenKit() = default; @@ -36,7 +38,9 @@ private: class AccessTokenKitMock : public BAccessTokenKit { public: MOCK_METHOD(ATokenTypeEnum, GetTokenTypeFlag, (AccessTokenID)); + MOCK_METHOD(ATokenTypeEnum, GetTokenType, (AccessTokenID)); MOCK_METHOD(int, GetHapTokenInfo, (AccessTokenID, HapTokenInfo&)); + MOCK_METHOD(int, GetNativeTokenInfo, (AccessTokenID, NativeTokenInfo&)); MOCK_METHOD(int, VerifyAccessToken, (AccessTokenID, const std::string&)); }; } diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/account_delegate_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/account_delegate_mock.cpp index 1f4b6d5e..011d0d2f 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/account_delegate_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/account_delegate_mock.cpp @@ -30,7 +30,7 @@ bool AccountDelegate::RegisterAccountInstance(AccountDelegate *instance) AccountDelegate *AccountDelegate::GetInstance() { - return &(AccountDelegateMock::Init()); + return instance_; } } // namespace DistributedData } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/account_delegate_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/account_delegate_mock.h index fe8af6ba..a2ca487c 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/account_delegate_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/account_delegate_mock.h @@ -18,17 +18,12 @@ #include #include -#include "account_delegate.h" +#include "account/account_delegate.h" namespace OHOS { namespace DistributedData { class AccountDelegateMock : public AccountDelegate { public: virtual ~AccountDelegateMock() = default; - static AccountDelegateMock& Init() - { - static AccountDelegateMock instance; - return instance; - } MOCK_METHOD(int32_t, Subscribe, (std::shared_ptr)); MOCK_METHOD(int32_t, Unsubscribe, (std::shared_ptr)); MOCK_METHOD(std::string, GetCurrentAccountId, (), (const)); diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/auth_delegate_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/auth_delegate_mock.cpp new file mode 100644 index 00000000..7d1cf72b --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/auth_delegate_mock.cpp @@ -0,0 +1,26 @@ +/* + * 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 "auth_delegate_mock.h" + +namespace OHOS { +namespace DistributedData { + +AuthHandler *AuthDelegate::GetInstance() +{ + return &(AuthHandlerMock::GetInstance()); +} +} // namespace DistributedData +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/auth_delegate_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/auth_delegate_mock.h new file mode 100644 index 00000000..4524aec5 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/auth_delegate_mock.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 OHOS_DISTRIBUTEDDATA_AUTH_DELEGATE_MOCK_H +#define OHOS_DISTRIBUTEDDATA_AUTH_DELEGATE_MOCK_H + +#include + +#include + +#include "auth_delegate.h" +namespace OHOS { +namespace DistributedData { +class AuthHandlerMock : public AuthHandler { +public: + static AuthHandlerMock &GetInstance() + { + static AuthHandlerMock instance; + return instance; + } + MOCK_METHOD((std::pair), CheckAccess, + (int localUserId, int peerUserId, const std::string &peerDeviceId, const AclParams &aclParams), (override)); +}; +} // namespace DistributedData +} // namespace OHOS +#endif // OHOS_DISTRIBUTEDDATA_AUTH_DELEGATE_MOCK_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/checker_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/checker_mock.cpp index 22a2e748..4adc8baa 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/checker_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/checker_mock.cpp @@ -47,7 +47,7 @@ std::string CheckerMock::GetAppId(const CheckerManager::StoreInfo &info) bool CheckerMock::IsValid(const CheckerManager::StoreInfo &info) { - return true; + return !info.bundleName.empty(); } bool CheckerMock::SetDistrustInfo(const CheckerManager::Distrust &distrust) diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/cloud_db_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/cloud_db_mock.h new file mode 100644 index 00000000..effbcc86 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/cloud_db_mock.h @@ -0,0 +1,51 @@ +/* + * 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 OHOS_DISTRIBUTEDDATA_SERVICE_CLOUD_DB_MOCK_H +#define OHOS_DISTRIBUTEDDATA_SERVICE_CLOUD_DB_MOCK_H + +#include + +#include "cloud/cloud_db.h" + +namespace OHOS::DistributedData { + +class MockCloudDB : public CloudDB { +public: + using Watcher = GeneralWatcher; + using Async = std::function>)>; + using Devices = std::vector; + + MOCK_METHOD(int32_t, Execute, (const std::string &, const std::string &, const VBucket &), (override)); + MOCK_METHOD(int32_t, BatchInsert, (const std::string &, VBuckets &&, VBuckets &), (override)); + MOCK_METHOD(int32_t, BatchUpdate, (const std::string &, VBuckets &&, VBuckets &), (override)); + MOCK_METHOD(int32_t, BatchUpdate, (const std::string &, VBuckets &&, const VBuckets &), (override)); + MOCK_METHOD(int32_t, BatchDelete, (const std::string &, VBuckets &), (override)); + MOCK_METHOD( + (std::pair>), Query, (const std::string &, const VBucket &), (override)); + MOCK_METHOD((std::pair>), Query, (GenQuery &, const VBucket &), (override)); + MOCK_METHOD(int32_t, PreSharing, (const std::string &, VBuckets &), (override)); + MOCK_METHOD(int32_t, Sync, (const Devices &, int32_t, const GenQuery &, Async, int32_t), (override)); + MOCK_METHOD(int32_t, Watch, (int32_t, Watcher &), (override)); + MOCK_METHOD(int32_t, Unwatch, (int32_t, Watcher &), (override)); + MOCK_METHOD(int32_t, Lock, (), (override)); + MOCK_METHOD(int32_t, Heartbeat, (), (override)); + MOCK_METHOD(int32_t, Unlock, (), (override)); + MOCK_METHOD(int64_t, AliveTime, (), (override)); + MOCK_METHOD(int32_t, Close, (), (override)); + MOCK_METHOD((std::pair), GetEmptyCursor, (const std::string &), (override)); + MOCK_METHOD(void, SetPrepareTraceId, (const std::string &), (override)); +}; +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTEDDATA_SERVICE_CLOUD_DB_MOCK_H diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/config_factory_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/config_factory_mock.cpp index aa685cd2..e38c560d 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/config_factory_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/config_factory_mock.cpp @@ -81,5 +81,10 @@ ThreadConfig *ConfigFactory::GetThreadConfig() { return nullptr; } + +DataShareConfig *ConfigFactory::GetDataShareConfig() +{ + return nullptr; +} } // namespace DistributedData } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/cursor_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/cursor_mock.h index c63bdacc..57be55a6 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/cursor_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/cursor_mock.h @@ -14,6 +14,8 @@ */ #ifndef OHOS_DISTRIBUTEDDATA_SERVICE_TEST_CURSOR_MOCK_H #define OHOS_DISTRIBUTEDDATA_SERVICE_TEST_CURSOR_MOCK_H +#include + #include #include #include @@ -45,6 +47,22 @@ private: std::shared_ptr resultSet_; int32_t index_ = 0; }; + +class MockCursor : public DistributedData::Cursor { + MOCK_METHOD(int32_t, GetColumnNames, (std::vector &names), (const, override)); + MOCK_METHOD(int32_t, GetColumnName, (int32_t col, std::string &name), (const, override)); + MOCK_METHOD(int32_t, GetColumnType, (int32_t col), (const, override)); + MOCK_METHOD(int32_t, GetCount, (), (const, override)); + MOCK_METHOD(int32_t, MoveToFirst, (), (override)); + MOCK_METHOD(int32_t, MoveToNext, (), (override)); + MOCK_METHOD(int32_t, MoveToPrev, (), (override)); + MOCK_METHOD(int32_t, GetEntry, (VBucket &entry), (override)); + MOCK_METHOD(int32_t, GetRow, (VBucket &data), (override)); + MOCK_METHOD(int32_t, Get, (int32_t col, Value &value), (override)); + MOCK_METHOD(int32_t, Get, (const std::string &col, Value &value), (override)); + MOCK_METHOD(int32_t, Close, (), (override)); + MOCK_METHOD(bool, IsEnd, (), (override)); +}; } // namespace DistributedData } // namespace OHOS #endif // OHOS_DISTRIBUTEDDATA_SERVICE_TEST_CURSOR_MOCK_H diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.cpp index 84c31cd2..b4af1df8 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.cpp @@ -382,6 +382,12 @@ DBStatus DBStoreMock::Sync(const DeviceSyncOption &option, const DeviceSyncProce return NOT_SUPPORT; } +DBStatus DBStoreMock::Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete) +{ + return NOT_SUPPORT; +} + DBStatus DBStoreMock::CancelSync(uint32_t syncId) { return NOT_SUPPORT; diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.h index 5c7e0ff3..d26dddec 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.h @@ -115,6 +115,8 @@ public: DBStatus SetReceiveDataInterceptor(const DataInterceptor &interceptor) override; DBStatus GetDeviceEntries(const std::string &device, std::vector &entries) const override; DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) override; + DBStatus Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete) override; DBStatus CancelSync(uint32_t syncId) override; DatabaseStatus GetDatabaseStatus() const override; private: diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/device_manager_adapter_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/device_manager_adapter_mock.cpp index fae2fb0f..f6da6ffa 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/device_manager_adapter_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/device_manager_adapter_mock.cpp @@ -34,6 +34,23 @@ std::vector OHOS::DistributedData::DeviceManagerAdapter::ToUUID(std return BDeviceManagerAdapter::deviceManagerAdapter->ToUUID(devices); } +std::vector OHOS::DistributedData::DeviceManagerAdapter::ToUUID(const std::vector &devices) +{ + if (BDeviceManagerAdapter::deviceManagerAdapter == nullptr) { + std::vector vec; + return vec; + } + return BDeviceManagerAdapter::deviceManagerAdapter->ToUUID(devices); +} + +std::string OHOS::DistributedData::DeviceManagerAdapter::ToUUID(const std::string &id) +{ + if (BDeviceManagerAdapter::deviceManagerAdapter == nullptr) { + return id; + } + return BDeviceManagerAdapter::deviceManagerAdapter->ToUUID(id); +} + bool OHOS::DistributedData::DeviceManagerAdapter::IsOHOSType(const std::string &id) { if (BDeviceManagerAdapter::deviceManagerAdapter == nullptr) { @@ -50,6 +67,14 @@ bool DeviceManagerAdapter::IsSameAccount(const AccessCaller &accCaller, const Ac return BDeviceManagerAdapter::deviceManagerAdapter->IsSameAccount(accCaller, accCallee); } +bool DeviceManagerAdapter::IsSameAccount(const std::string &devicdId) +{ + if (BDeviceManagerAdapter::deviceManagerAdapter == nullptr) { + return false; + } + return BDeviceManagerAdapter::deviceManagerAdapter->IsSameAccount(devicdId); +} + bool DeviceManagerAdapter::CheckAccessControl(const AccessCaller &accCaller, const AccessCallee &accCallee) { if (BDeviceManagerAdapter::deviceManagerAdapter == nullptr) { @@ -118,6 +143,15 @@ std::string OHOS::DistributedData::DeviceManagerAdapter::ToNetworkID(const std:: return BDeviceManagerAdapter::deviceManagerAdapter->ToNetworkID(id); } +std::string OHOS::DistributedData::DeviceManagerAdapter::CalcClientUuid( + const std::string &appId, const std::string &uuid) +{ + if (BDeviceManagerAdapter::deviceManagerAdapter == nullptr) { + return " "; + } + return BDeviceManagerAdapter::deviceManagerAdapter->CalcClientUuid(appId, uuid); +} + DeviceManagerAdapter::~DeviceManagerAdapter() { } diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/device_manager_adapter_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/device_manager_adapter_mock.h index abdef014..12686243 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/device_manager_adapter_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/device_manager_adapter_mock.h @@ -16,8 +16,9 @@ #define OHOS_DISTRIBUTEDDATA_SERVICE_TEST_BDEVICE_MANAGER_ADAPTER_MOCK_H #include -#include "device_manager_adapter.h" + #include "commu_types.h" +#include "device_manager_adapter.h" namespace OHOS { namespace DistributedData { @@ -30,14 +31,18 @@ public: virtual std::vector GetRemoteDevices() = 0; virtual bool IsOHOSType(const std::string &) = 0; virtual std::vector ToUUID(std::vector) = 0; + virtual std::vector ToUUID(const std::vector &) = 0; + virtual std::string ToUUID(const std::string &) = 0; virtual Status StartWatchDeviceChange(const AppDeviceChangeListener *, const PipeInfo &) = 0; virtual Status StopWatchDeviceChange(const AppDeviceChangeListener *, const PipeInfo &) = 0; virtual bool IsSameAccount(const AccessCaller &, const AccessCallee &) = 0; - virtual std::string GetUuidByNetworkId(const std::string &) = 0; - virtual DeviceInfo GetDeviceInfo(const std::string &) = 0; - virtual std::string ToNetworkID(const std::string &) = 0; + virtual bool IsSameAccount(const std::string &) = 0; + virtual std::string GetUuidByNetworkId(const std::string &); + virtual DeviceInfo GetDeviceInfo(const std::string &); + virtual std::string ToNetworkID(const std::string &); virtual bool CheckAccessControl(const AccessCaller &, const AccessCallee &) = 0; virtual DeviceInfo GetLocalDevice() = 0; + virtual std::string CalcClientUuid(const std::string &appId, const std::string &uuid) = 0; static inline std::shared_ptr deviceManagerAdapter = nullptr; BDeviceManagerAdapter() = default; virtual ~BDeviceManagerAdapter() = default; @@ -45,17 +50,21 @@ public: class DeviceManagerAdapterMock : public BDeviceManagerAdapter { public: - MOCK_METHOD0(GetRemoteDevices, std::vector()); - MOCK_METHOD1(IsOHOSType, bool(const std::string &)); - MOCK_METHOD1(ToUUID, std::vector(std::vector)); - MOCK_METHOD2(StartWatchDeviceChange, Status(const AppDeviceChangeListener *, const PipeInfo &)); - MOCK_METHOD2(StopWatchDeviceChange, Status(const AppDeviceChangeListener *, const PipeInfo &)); - MOCK_METHOD2(IsSameAccount, bool(const AccessCaller &, const AccessCallee &)); - MOCK_METHOD1(GetUuidByNetworkId,std::string(const std::string &)); - MOCK_METHOD1(GetDeviceInfo, DeviceInfo(const std::string &)); - MOCK_METHOD1(ToNetworkID, std::string(const std::string &)); - MOCK_METHOD2(CheckAccessControl, bool(const AccessCaller &, const AccessCallee &)); - MOCK_METHOD0(GetLocalDevice, DeviceInfo()); + MOCK_METHOD(std::vector, GetRemoteDevices, ()); + MOCK_METHOD(bool, IsOHOSType, (const std::string &)); + MOCK_METHOD((std::vector), ToUUID, (std::vector)); + MOCK_METHOD((std::vector), ToUUID, (const std::vector &)); + MOCK_METHOD(std::string, ToUUID, (const std::string &)); + MOCK_METHOD(Status, StartWatchDeviceChange, (const AppDeviceChangeListener *, const PipeInfo &)); + MOCK_METHOD(Status, StopWatchDeviceChange, (const AppDeviceChangeListener *, const PipeInfo &)); + MOCK_METHOD(bool, IsSameAccount, (const AccessCaller &, const AccessCallee &)); + MOCK_METHOD(bool, IsSameAccount, (const std::string &)); + MOCK_METHOD(std::string, GetUuidByNetworkId, (const std::string &)); + MOCK_METHOD(DeviceInfo, GetDeviceInfo, (const std::string &)); + MOCK_METHOD(std::string, ToNetworkID, (const std::string &)); + MOCK_METHOD(bool, CheckAccessControl, (const AccessCaller &, const AccessCallee &)); + MOCK_METHOD(DeviceInfo, GetLocalDevice, ()); + MOCK_METHOD(std::string, CalcClientUuid, (const std::string &, const std::string &)); }; } // namespace DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/device_matrix_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/device_matrix_mock.cpp new file mode 100644 index 00000000..4cba3f33 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/device_matrix_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 "device_matrix_mock.h" + +namespace OHOS { +namespace DistributedData { +std::pair DeviceMatrix::GetRemoteMask(const std::string &device, DeviceMatrix::LevelType type) +{ + return BDeviceMatrix::deviceMatrix->GetRemoteMask(device, type); +} + +std::pair DeviceMatrix::GetMask(const std::string &device, DeviceMatrix::LevelType type) +{ + return BDeviceMatrix::deviceMatrix->GetMask(device, type); +} +} // namespace DistributedData +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/device_matrix_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/device_matrix_mock.h new file mode 100644 index 00000000..f67eb94c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/device_matrix_mock.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 OHOS_DEVICE_MATRIX_MOCK_H +#define OHOS_DEVICE_MATRIX_MOCK_H + +#include + +#include "device_matrix.h" + +namespace OHOS::DistributedData { +class BDeviceMatrix { +public: + virtual std::pair GetMask(const std::string &, DeviceMatrix::LevelType); + virtual std::pair GetRemoteMask(const std::string &, DeviceMatrix::LevelType); + BDeviceMatrix() = default; + virtual ~BDeviceMatrix() = default; + static inline std::shared_ptr deviceMatrix = nullptr; +}; +class DeviceMatrixMock : public BDeviceMatrix { +public: + MOCK_METHOD((std::pair), GetMask, (const std::string &, DeviceMatrix::LevelType), (override)); + MOCK_METHOD((std::pair), GetRemoteMask, (const std::string &, DeviceMatrix::LevelType), (override)); +}; +} // namespace OHOS::DistributedData +#endif //OHOS_DEVICE_MATRIX_MOCK_H diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/distributed_file_daemon_manager_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/distributed_file_daemon_manager_mock.cpp new file mode 100644 index 00000000..7d6a44ed --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/distributed_file_daemon_manager_mock.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 "distributed_file_daemon_manager_mock.h" +// +//namespace OHOS { +//namespace Storage { +//namespace DistributedFile { +//constexpr const int32_t ERROR = -1; +// +//DistributedFileDaemonManager &DistributedFileDaemonManager::GetInstance() +//{ +// return DistributedFileDaemonManagerImpl::GetInstance(); +//} +// +//int32_t DistributedFileDaemonManagerImpl::RegisterAssetCallback(const sptr &recvCallback) +//{ +// if (BDistributedFileDaemonManager::fileDaemonManger_ == nullptr) { +// return ERROR; +// } +// return BDistributedFileDaemonManager::fileDaemonManger_->RegisterAssetCallback(recvCallback); +//} +// +//int32_t DistributedFileDaemonManagerImpl::UnRegisterAssetCallback(const sptr &recvCallback) +//{ +// if (BDistributedFileDaemonManager::fileDaemonManger_ == nullptr) { +// return ERROR; +// } +// return BDistributedFileDaemonManager::fileDaemonManger_->UnRegisterAssetCallback(recvCallback); +//} +//} // namespace DistributedFile +//} // namespace Storage +//} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/distributed_file_daemon_manager_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/distributed_file_daemon_manager_mock.h new file mode 100644 index 00000000..b1d66ad0 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/distributed_file_daemon_manager_mock.h @@ -0,0 +1,122 @@ +///* +// * 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 OHOS_DISTRIBUTED_FILE_DAEMON_MANAGER_MOCK_H +//#define OHOS_DISTRIBUTED_FILE_DAEMON_MANAGER_MOCK_H +// +//#include +// +//#include "distributed_file_daemon_manager.h" +//namespace OHOS { +//namespace Storage { +//namespace DistributedFile { +//class BDistributedFileDaemonManager { +//public: +// virtual int32_t RegisterAssetCallback(const sptr &recvCallback) = 0; +// virtual int32_t UnRegisterAssetCallback(const sptr &recvCallback) = 0; +// BDistributedFileDaemonManager() = default; +// virtual ~BDistributedFileDaemonManager() = default; +// +//private: +// static inline std::shared_ptr fileDaemonManger_ = nullptr; +//}; +// +//class DistributedFileDaemonManagerMock : public BDistributedFileDaemonManager { +//public: +// MOCK_METHOD(int32_t, RegisterAssetCallback, (const sptr &recvCallback)); +// MOCK_METHOD(int32_t, UnRegisterAssetCallback, (const sptr &recvCallback)); +//}; +// +//class DistributedFileDaemonManagerImpl : public DistributedFileDaemonManager { +//public: +// static DistributedFileDaemonManagerImpl &GetInstance() +// { +// static DistributedFileDaemonManagerImpl instance; +// return instance; +// } +// int32_t RegisterAssetCallback(const sptr &recvCallback) override; +// int32_t UnRegisterAssetCallback(const sptr &recvCallback) 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 PrepareSession(const std::string &srcUri, const std::string &dstUri, const std::string &srcDeviceId, +// const sptr &listener, HmdfsInfo &info) override +// { +// return 0; +// } +// int32_t CancelCopyTask(const std::string &sessionName) override +// { +// return 0; +// } +// int32_t CancelCopyTask(const std::string &srcUri, const std::string &dstUri) override +// { +// return 0; +// } +// +// int32_t PushAsset(int32_t userId, const sptr &assetObj, +// const sptr &sendCallback) 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; +// } +// int32_t GetDfsSwitchStatus(const std::string &networkId, int32_t &switchStatus) override +// { +// return 0; +// } +// int32_t UpdateDfsSwitchStatus(int32_t switchStatus) override +// { +// return 0; +// } +// int32_t GetConnectedDeviceList(std::vector &deviceList) override +// { +// return 0; +// } +//}; +//} // namespace DistributedFile +//} // namespace Storage +//} // namespace OHOS +//#endif \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.cpp index 89e80c6e..d6455371 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.cpp @@ -41,14 +41,14 @@ int32_t GeneralStoreMock::Execute(const std::string &table, const std::string &s return 0; } -int32_t GeneralStoreMock::SetDistributedTables(const std::vector &tables, int32_t type, - const std::vector &references) +int32_t GeneralStoreMock::SetDistributedTables( + const std::vector &tables, int32_t type, const std::vector &references) { return 0; } -int32_t GeneralStoreMock::SetTrackerTable(const std::string &tableName, const std::set &trackerColNames, - const std::set &extendColNames, bool isForceUpgrade) +int32_t GeneralStoreMock::SetTrackerTable(const std::string &tableName, + const std::set &trackerColNames, const std::set &extendColNames, bool isForceUpgrade) { return 0; } @@ -76,18 +76,18 @@ int32_t GeneralStoreMock::Delete(const std::string &table, const std::string &sq std::pair> GeneralStoreMock::Query(const std::string &table, GenQuery &query) { - return { GeneralError::E_NOT_SUPPORT, nullptr }; + return {GeneralError::E_NOT_SUPPORT, nullptr}; } -std::pair GeneralStoreMock::Sync(const Devices &devices, GenQuery &query, DetailAsync async, - const SyncParam &syncParm) +std::pair GeneralStoreMock::Sync(const Devices &devices, GenQuery &query, + DetailAsync async, const SyncParam &syncParm) { return { GeneralError::E_OK, 0 }; } std::pair> GeneralStoreMock::PreSharing(GenQuery &query) { - return { GeneralError::E_NOT_SUPPORT, nullptr }; + return {GeneralError::E_NOT_SUPPORT, nullptr}; } int32_t GeneralStoreMock::Clean(const std::vector &devices, int32_t mode, const std::string &tableName) @@ -148,7 +148,7 @@ int32_t GeneralStoreMock::CleanTrackerData(const std::string &tableName, int64_t std::pair> GeneralStoreMock::Query(const std::string &table, const std::string &sql, Values &&args) { - return { GeneralError::E_OK, cursor_ }; + return {GeneralError::E_OK, cursor_}; } void GeneralStoreMock::MakeCursor(const std::map &entry) diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.cpp index e4ec970b..5b9f480b 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.cpp @@ -25,8 +25,32 @@ std::vector MockQuery::GetTables() return tables_; } +const std::string GetStatement() +{ + return "AS distributed_log"; +} + +void MockQuery::MakeRemoteQuery(const std::string &devices, const std::string &sql, Values &&args) +{ + isRemote_ = true; + devices_ = { devices }; + sql_ = sql; + args_ = std::move(args); +} + +void MockQuery::MakeQuery(const DistributedRdb::PredicatesMemo &predicates) +{ + if (!predicates.tables_.empty()) { + predicates_ = std::make_shared(*predicates.tables_.begin()); + predicates_->SetWhereClause("id = 1"); + } + devices_ = predicates.devices_; + tables_ = predicates.tables_; +} int32_t MockGeneralWatcher::OnChange(const Origin &origin, const PRIFields &primaryFields, ChangeInfo &&values) { + origin_ = origin; + primaryFields_ = primaryFields; return GeneralError::E_OK; } @@ -34,4 +58,4 @@ int32_t MockGeneralWatcher::OnChange(const Origin &origin, const Fields &fields, { return GeneralError::E_OK; } -} // OHOS::DistributedData +} // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.h index 27748455..dac5bbd6 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/general_watcher_mock.h @@ -14,12 +14,11 @@ */ #ifndef OHOS_DISTRIBUTEDDATA_SERVICE_TEST_GENERAL_WATCH_MOCK_H #define OHOS_DISTRIBUTEDDATA_SERVICE_TEST_GENERAL_WATCH_MOCK_H - -#include "store/general_value.h" +#include "rdb_query.h" #include "store/general_watcher.h" namespace OHOS::DistributedData { -class MockQuery : public GenQuery { +class MockQuery : public DistributedRdb::RdbQuery { public: ~MockQuery() = default; static constexpr uint64_t TYPE_ID = 0x20000001; @@ -28,6 +27,9 @@ public: bool IsEqual(uint64_t tid) override; std::vector GetTables() override; + const std::string GetStatement(); + void MakeRemoteQuery(const std::string &devices, const std::string &sql, DistributedData::Values &&args); + void MakeQuery(const DistributedRdb::PredicatesMemo &predicates); }; class MockGeneralWatcher : public DistributedData::GeneralWatcher { @@ -35,6 +37,10 @@ public: int32_t OnChange(const Origin &origin, const PRIFields &primaryFields, ChangeInfo &&values) override; int32_t OnChange(const Origin &origin, const Fields &fields, ChangeData &&datas) override; + +private: + Origin origin_; + PRIFields primaryFields_; }; -} // OHOS::DistributedData +} // namespace OHOS::DistributedData #endif \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_corruption_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_corruption_mock.cpp new file mode 100644 index 00000000..b9ead1e0 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_corruption_mock.cpp @@ -0,0 +1,353 @@ +/* + * 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 "kv_store_nb_delegate_corruption_mock.h" + +#include "store_types.h" +namespace DistributedDB { +DBStatus KvStoreNbDelegateCorruptionMock::Get(const Key &key, Value &value) const +{ + return DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetEntries(const Key &keyPrefix, std::vector &entries) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetEntries(const Key &keyPrefix, KvStoreResultSet *&resultSet) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetEntries(const Query &query, std::vector &entries) const +{ + return DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetEntries(const Query &query, KvStoreResultSet *&resultSet) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetCount(const Query &query, int &count) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::CloseResultSet(KvStoreResultSet *&resultSet) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Put(const Key &key, const Value &value) +{ + return DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; +} + +DBStatus KvStoreNbDelegateCorruptionMock::PutBatch(const std::vector &entries) +{ + return DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; +} + +DBStatus KvStoreNbDelegateCorruptionMock::DeleteBatch(const std::vector &keys) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Delete(const Key &key) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetLocal(const Key &key, Value &value) const +{ + return DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetLocalEntries(const Key &keyPrefix, std::vector &entries) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::PutLocal(const Key &key, const Value &value) +{ + return DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; +} + +DBStatus KvStoreNbDelegateCorruptionMock::DeleteLocal(const Key &key) +{ + return DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; +} + +DBStatus KvStoreNbDelegateCorruptionMock::PublishLocal(const Key &key, bool deleteLocal, bool updateTimestamp, + const KvStoreNbPublishOnConflict &onConflict) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::UnpublishToLocal(const Key &key, bool deletePublic, bool updateTimestamp) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::RegisterObserver(const Key &key, unsigned int mode, + KvStoreObserver *observer) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::UnRegisterObserver(const KvStoreObserver *observer) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::RemoveDeviceData(const std::string &device) +{ + return DBStatus::OK; +} + +std::string KvStoreNbDelegateCorruptionMock::GetStoreId() const +{ + return "ok"; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Sync(const std::vector &devices, SyncMode mode, + const std::function &devicesMap)> &onComplete, + bool wait) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Pragma(PragmaCmd cmd, PragmaData ¶mData) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::SetConflictNotifier(int conflictType, + const KvStoreNbConflictNotifier ¬ifier) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Rekey(const CipherPassword &password) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Export(const std::string &filePath, + const CipherPassword &passwd, bool force) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::StartTransaction() +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Commit() +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Rollback() +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::PutLocalBatch(const std::vector &entries) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::DeleteLocalBatch(const std::vector &keys) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetSecurityOption(SecurityOption &option) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::SetRemotePushFinishedNotify(const RemotePushFinishedNotifier ¬ifier) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Sync(const std::vector &devices, SyncMode mode, + const std::function &devicesMap)> &onComplete, + const Query &query, bool wait) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::CheckIntegrity() const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::SetEqualIdentifier(const std::string &identifier, + const std::vector &targets) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::SetPushDataInterceptor(const PushDataInterceptor &interceptor) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::SubscribeRemoteQuery(const std::vector &devices, + const std::function &devicesMap)> &onComplete, + const Query &query, bool wait) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::UnSubscribeRemoteQuery(const std::vector &devices, + const std::function &devicesMap)> &onComplete, + const Query &query, bool wait) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::RemoveDeviceData() +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetKeys(const Key &keyPrefix, std::vector &keys) const +{ + return DBStatus::OK; +} + +size_t KvStoreNbDelegateCorruptionMock::GetSyncDataSize(const std::string &device) const +{ + size_t size = 0; + return size; +} + +DBStatus KvStoreNbDelegateCorruptionMock::UpdateKey(const UpdateKeyCallback &callback) +{ + return DBStatus::OK; +} + +std::pair KvStoreNbDelegateCorruptionMock::GetWatermarkInfo(const std::string &device) +{ + std::pair ret; + return ret; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::SetCloudDB(const std::map> &cloudDBs) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::SetCloudDbSchema(const std::map &schema) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::RemoveDeviceData(const std::string &device, ClearMode mode) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::RemoveDeviceData(const std::string &device, + const std::string &user, ClearMode mode) +{ + return DBStatus::OK; +} + +int32_t KvStoreNbDelegateCorruptionMock::GetTaskCount() +{ + int32_t taskCount = taskCountMock_; + return taskCount; +} + +void KvStoreNbDelegateCorruptionMock::SetGenCloudVersionCallback(const GenerateCloudVersionCallback &callback) +{ + auto callback_ = callback; +} + +std::pair> KvStoreNbDelegateCorruptionMock::GetCloudVersion( + const std::string &device) +{ + if (device.empty()) { + return { DBStatus::OK, {} }; + } else if (device == "test") { + return { DBStatus::DB_ERROR, {} }; + } else if (device == "device") { + return { DBStatus::DB_ERROR, {{device, device}} }; + } else { + return { DBStatus::OK, {{device, device}} }; + } +} + +DBStatus KvStoreNbDelegateCorruptionMock::SetReceiveDataInterceptor(const DataInterceptor &interceptor) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::SetCloudSyncConfig(const CloudSyncConfig &config) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::GetDeviceEntries(const std::string &device, std::vector &entries) const +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Sync(const DeviceSyncOption &option, + const DeviceSyncProcessCallback &onProcess) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete) +{ + return DBStatus::OK; +} + +DBStatus KvStoreNbDelegateCorruptionMock::CancelSync(uint32_t syncId) +{ + return DBStatus::OK; +} + +KvStoreNbDelegate::DatabaseStatus KvStoreNbDelegateCorruptionMock::GetDatabaseStatus() const +{ + return {}; +} + +DBStatus KvStoreNbDelegateCorruptionMock::ClearMetaData(ClearKvMetaDataOption option) +{ + return DBStatus::OK; +} +} // namespace DistributedDB \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_corruption_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_corruption_mock.h new file mode 100644 index 00000000..6a7fa48a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_corruption_mock.h @@ -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. + */ + +#ifndef KV_STORE_NB_DELEGATE_CORRUPTION_H_MOCK +#define KV_STORE_NB_DELEGATE_CORRUPTION_H_MOCK + +#include +#include +#include + +#include "cloud/cloud_store_types.h" +#include "cloud/icloud_db.h" +#include "intercepted_data.h" +#include "iprocess_system_api_adapter.h" +#include "kv_store_nb_conflict_data.h" +#include "kv_store_nb_delegate.h" +#include "kv_store_observer.h" +#include "kv_store_result_set.h" +#include "query.h" +#include "store_types.h" + +namespace DistributedDB { +class KvStoreNbDelegateCorruptionMock : public DistributedDB::KvStoreNbDelegate { +public: + int32_t taskCountMock_ = 0; + ~KvStoreNbDelegateCorruptionMock() = default; + DBStatus Get(const Key &key, Value &value) const; + DBStatus GetEntries(const Key &keyPrefix, std::vector &entries) const; + DBStatus GetEntries(const Key &keyPrefix, KvStoreResultSet *&resultSet) const; + DBStatus GetEntries(const Query &query, std::vector &entries) const; + DBStatus GetEntries(const Query &query, KvStoreResultSet *&resultSet) const; + DBStatus GetCount(const Query &query, int &count) const; + DBStatus CloseResultSet(KvStoreResultSet *&resultSet); + DBStatus Put(const Key &key, const Value &value); + DBStatus PutBatch(const std::vector &entries); + DBStatus DeleteBatch(const std::vector &keys); + DBStatus Delete(const Key &key); + DBStatus GetLocal(const Key &key, Value &value) const; + DBStatus GetLocalEntries(const Key &keyPrefix, std::vector &entries) const; + DBStatus PutLocal(const Key &key, const Value &value); + DBStatus DeleteLocal(const Key &key); + DBStatus PublishLocal(const Key &key, bool deleteLocal, bool updateTimestamp, + const KvStoreNbPublishOnConflict &onConflict); + DBStatus UnpublishToLocal(const Key &key, bool deletePublic, bool updateTimestamp); + DBStatus RegisterObserver(const Key &key, unsigned int mode, KvStoreObserver *observer); + DBStatus UnRegisterObserver(const KvStoreObserver *observer); + DBStatus RemoveDeviceData(const std::string &device); + std::string GetStoreId() const; + DBStatus Sync(const std::vector &devices, SyncMode mode, + const std::function &devicesMap)> &onComplete, + bool wait = false); + DBStatus Pragma(PragmaCmd cmd, PragmaData ¶mData); + DBStatus SetConflictNotifier(int conflictType, + const KvStoreNbConflictNotifier ¬ifier); + DBStatus Rekey(const CipherPassword &password); + DBStatus Export(const std::string &filePath, const CipherPassword &passwd, bool force = false); + DBStatus Import(const std::string &filePath, const CipherPassword &passwd, bool isNeedIntegrityCheck = false); + DBStatus StartTransaction(); + DBStatus Commit(); + DBStatus Rollback(); + DBStatus PutLocalBatch(const std::vector &entries); + DBStatus DeleteLocalBatch(const std::vector &keys); + DBStatus GetSecurityOption(SecurityOption &option) const; + DBStatus SetRemotePushFinishedNotify(const RemotePushFinishedNotifier ¬ifier); + DBStatus Sync(const std::vector &devices, SyncMode mode, + const std::function &devicesMap)> &onComplete, + const Query &query, bool wait); + DBStatus CheckIntegrity() const; + DBStatus SetEqualIdentifier(const std::string &identifier, + const std::vector &targets); + DBStatus SetPushDataInterceptor(const PushDataInterceptor &interceptor); + DBStatus SubscribeRemoteQuery(const std::vector &devices, + const std::function &devicesMap)> &onComplete, + const Query &query, bool wait); + DBStatus UnSubscribeRemoteQuery(const std::vector &devices, + const std::function &devicesMap)> &onComplete, + const Query &query, bool wait); + DBStatus RemoveDeviceData(); + DBStatus GetKeys(const Key &keyPrefix, std::vector &keys) const; + size_t GetSyncDataSize(const std::string &device) const; + DBStatus UpdateKey(const UpdateKeyCallback &callback); + std::pair GetWatermarkInfo(const std::string &device); + DBStatus Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess); + DBStatus SetCloudDB(const std::map> &cloudDBs); + DBStatus SetCloudDbSchema(const std::map &schema); + DBStatus RemoveDeviceData(const std::string &device, ClearMode mode); + DBStatus RemoveDeviceData(const std::string &device, const std::string &user, ClearMode mode); + int32_t GetTaskCount(); + void SetGenCloudVersionCallback(const GenerateCloudVersionCallback &callback); + std::pair> GetCloudVersion( + const std::string &device); + DBStatus SetReceiveDataInterceptor(const DataInterceptor &interceptor); + DBStatus SetCloudSyncConfig(const CloudSyncConfig &config); + DBStatus GetDeviceEntries(const std::string &device, std::vector &entries) const; + DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess); + DBStatus Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete); + DBStatus CancelSync(uint32_t syncId); + DatabaseStatus GetDatabaseStatus() const; + DBStatus ClearMetaData(ClearKvMetaDataOption option); +}; +} // namespace DistributedDB +#endif // KV_STORE_NB_DELEGATE_CORRUPTION_H_MOCK \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.cpp index d37fc737..b5668bbf 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.cpp @@ -328,6 +328,12 @@ DBStatus KvStoreNbDelegateMock::Sync(const DeviceSyncOption &option, const Devic return DBStatus::OK; } +DBStatus KvStoreNbDelegateMock::Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete) +{ + return DBStatus::OK; +} + DBStatus KvStoreNbDelegateMock::CancelSync(uint32_t syncId) { return DBStatus::OK; @@ -337,4 +343,9 @@ KvStoreNbDelegate::DatabaseStatus KvStoreNbDelegateMock::GetDatabaseStatus() con { return {}; } + +DBStatus KvStoreNbDelegateMock::ClearMetaData(ClearKvMetaDataOption option) +{ + return DBStatus::OK; +} } // namespace DistributedDB \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.h index 7f3d77c8..bf558013 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.h @@ -105,8 +105,11 @@ public: DBStatus SetCloudSyncConfig(const CloudSyncConfig &config); DBStatus GetDeviceEntries(const std::string &device, std::vector &entries) const; DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess); + DBStatus Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete); DBStatus CancelSync(uint32_t syncId); DatabaseStatus GetDatabaseStatus() const; + DBStatus ClearMetaData(ClearKvMetaDataOption option); }; } // namespace DistributedDB #endif // KV_STORE_NB_DELEGATE_H_MOCK \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/meta_data_manager_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/meta_data_manager_mock.cpp index 5923f7da..3a23d322 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/meta_data_manager_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/meta_data_manager_mock.cpp @@ -12,23 +12,44 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include #include "meta_data_manager_mock.h" +#include + +#include "metadata/capability_meta_data.h" + namespace OHOS::DistributedData { using namespace std; + OHOS::DistributedData::MetaDataManager &OHOS::DistributedData::MetaDataManager::GetInstance() { static MetaDataManager instance; return instance; } -OHOS::DistributedData::MetaDataManager::MetaDataManager() { } +OHOS::DistributedData::MetaDataManager::MetaDataManager() +{ +} -OHOS::DistributedData::MetaDataManager::~MetaDataManager() { } +OHOS::DistributedData::MetaDataManager::~MetaDataManager() +{ +} bool OHOS::DistributedData::MetaDataManager::LoadMeta(const std::string &key, Serializable &value, bool isLocal) { return BMetaDataManager::metaDataManager->LoadMeta(key, value, isLocal); } -} \ No newline at end of file + +bool OHOS::DistributedData::MetaDataManager::Sync(const std::vector &devices, + MetaDataManager::OnComplete complete, bool wait, bool isRetry) +{ + return BMetaDataManager::metaDataManager->Sync(devices, complete, wait, isRetry); +} + +template<> +bool OHOS::DistributedData::MetaDataManager::LoadMeta( + const std::string &prefix, std::vector &values, bool isLocal) +{ + return BMetaData::metaDataManager->LoadMeta(prefix, values, isLocal); +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/meta_data_manager_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/meta_data_manager_mock.h index 28b4562a..32bcd387 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/meta_data_manager_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/meta_data_manager_mock.h @@ -16,24 +16,37 @@ #define OHOS_META_DATA_MANAGER_MOCK_H #include + +#include "metadata/appid_meta_data.h" #include "metadata/meta_data_manager.h" -#include "metadata/strategy_meta_data.h" #include "metadata/store_meta_data.h" -#include "metadata/appid_meta_data.h" +#include "metadata/strategy_meta_data.h" namespace OHOS::DistributedData { class BMetaDataManager { public: virtual bool LoadMeta(const std::string &, Serializable &, bool) = 0; + virtual bool Sync(const std::vector &, MetaDataManager::OnComplete, bool, bool) = 0; BMetaDataManager() = default; virtual ~BMetaDataManager() = default; -private: static inline std::shared_ptr metaDataManager = nullptr; }; - class MetaDataManagerMock : public BMetaDataManager { public: - MOCK_METHOD(bool, LoadMeta, (const std::string &, Serializable &, bool)); + MOCK_METHOD(bool, LoadMeta, (const std::string &, Serializable &, bool), (override)); + MOCK_METHOD(bool, Sync, (const std::vector &, MetaDataManager::OnComplete, bool, bool), (override)); +}; + +template class BMetaData { +public: + virtual bool LoadMeta(const std::string &, std::vector &, bool) = 0; + BMetaData() = default; + virtual ~BMetaData() = default; + static inline std::shared_ptr> metaDataManager = nullptr; +}; +template class MetaDataMock : public BMetaData { +public: + MOCK_METHOD(bool, LoadMeta, (const std::string &, std::vector &, bool), (override)); }; -} +} // namespace OHOS::DistributedData #endif //OHOS_META_DATA_MANAGER_MOCK_H diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/network_delegate_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/network_delegate_mock.cpp index ce26d253..cfab2309 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/network_delegate_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/network_delegate_mock.cpp @@ -30,5 +30,10 @@ void NetworkDelegateMock::RegOnNetworkChange() { return; } + +void NetworkDelegateMock::BindExecutor(std::shared_ptr executors) +{ + return; +} } // namespace DistributedData } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/network_delegate_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/network_delegate_mock.h index d1d65cf9..0fcea3d2 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/network_delegate_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/network_delegate_mock.h @@ -24,6 +24,7 @@ public: bool IsNetworkAvailable() override; NetworkType GetNetworkType(bool retrieve = false) override; void RegOnNetworkChange() override; + void BindExecutor(std::shared_ptr executors) override; bool isNetworkAvailable_ = true; virtual ~NetworkDelegateMock() = default; }; diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/preprocess_utils_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/preprocess_utils_mock.cpp new file mode 100644 index 00000000..47178428 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/preprocess_utils_mock.cpp @@ -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. +// */ +//#define LOG_TAG "PreProcessUtils" +// +//#include "preprocess_utils.h" +// +//#include "bundle_info.h" +//#include "dds_trace.h" +//#include "accesstoken_kit.h" +//#include "iservice_registry.h" +//#include "log_print.h" +//#include "system_ability_definition.h" +//#include "utils/crypto.h" +//#include "uri_permission_manager_client.h" +//#include "bundle_mgr_interface.h" +//namespace OHOS { +//namespace UDMF { +//using namespace OHOS::DistributedDataDfx; +//using namespace Security::AccessToken; +////using namespace OHOS::AppFileService::ModuleRemoteFileShare; +// +//int32_t PreProcessUtils::FillRuntimeInfo(UnifiedData &data, CustomOption &option) +//{ +// auto it = UD_INTENTION_MAP.find(option.intention); +// if (it == UD_INTENTION_MAP.end()) { +// return E_ERROR; +// } +// std::string bundleName = "bundleName"; +// std::string intention = it->second; +// UnifiedKey key(intention, bundleName, GenerateId()); +// Privilege privilege; +// privilege.tokenId = option.tokenId; +// +// Runtime runtime; +// runtime.key = key; +// runtime.privileges.emplace_back(privilege); +// runtime.createTime = GetTimestamp(); +// runtime.sourcePackage = bundleName; +// runtime.createPackage = bundleName; +// runtime.recordTotalNum = static_cast(data.GetRecords().size()); +// runtime.tokenId = option.tokenId; +// runtime.visibility = option.visibility; +// runtime.appId = "appId"; +// data.SetRuntime(runtime); +// return E_OK; +//} +// +//std::string PreProcessUtils::GenerateId() +//{ +// return "1122ac"; +//} +// +//time_t PreProcessUtils::GetTimestamp() +//{ +// std::chrono::time_point tp = +// std::chrono::time_point_cast(std::chrono::system_clock::now()); +// time_t timestamp = tp.time_since_epoch().count(); +// return timestamp; +//} +// +//int32_t PreProcessUtils::GetHapUidByToken(uint32_t tokenId, int &userId) +//{ +// return E_OK; +//} +// +//bool PreProcessUtils::GetHapBundleNameByToken(int tokenId, std::string &bundleName) +//{ +// bundleName = "processName"; +// return true; +//} +// +//bool PreProcessUtils::GetNativeProcessNameByToken(int tokenId, std::string &processName) +//{ +// processName = "processName"; +// return true; +//} +// +//std::string PreProcessUtils::GetLocalDeviceId() +//{ +// return "123"; +//} +// +//void PreProcessUtils::SetRemoteData(UnifiedData &data) +//{ +// return; +//} +// +//int32_t PreProcessUtils::SetRemoteUri(uint32_t tokenId, UnifiedData &data) +//{ +// return E_OK; +//} +// +//bool PreProcessUtils::GetInstIndex(uint32_t tokenId, int32_t &instIndex) +//{ +// return true; +//} +// +//bool PreProcessUtils::IsNetworkingEnabled() +//{ +// return true; +//} +// +//void PreProcessUtils::ProcessFileType(std::vector> records, +// std::function)> callback) +//{ +// return; +//} +// +//void PreProcessUtils::ProcessRecord(std::shared_ptr record, uint32_t tokenId, +// bool isLocal, std::vector &uris) +//{ +// return; +//} +// +//void PreProcessUtils::GetHtmlFileUris(uint32_t tokenId, UnifiedData &data, +// bool isLocal, std::vector &uris) +//{ +// return; +//} +// +//void PreProcessUtils::ClearHtmlDfsUris(UnifiedData &data) +//{ +// return; +//} +// +//void PreProcessUtils::ProcessHtmlFileUris(uint32_t tokenId, UnifiedData &data, bool isLocal, std::vector &uris) +//{ +// return; +//} +// +//void PreProcessUtils::SetRecordUid(UnifiedData &data) +//{ +// return; +//} +// +//bool PreProcessUtils::GetDetailsFromUData(const UnifiedData &data, UDDetails &details) +//{ +// return true; +//} +// +//Status PreProcessUtils::GetSummaryFromDetails(const UDDetails &details, Summary &summary) +//{ +// return E_OK; +//} +// +//sptr PreProcessUtils::GetBundleMgr() +//{ +// auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); +// if (samgrProxy == nullptr) { +// ZLOGE("Failed to get system ability mgr."); +// return nullptr; +// } +// auto bundleMgrProxy = samgrProxy->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); +// if (bundleMgrProxy == nullptr) { +// ZLOGE("Failed to Get BMS SA."); +// return nullptr; +// } +// auto bundleManager = iface_cast(bundleMgrProxy); +// if (bundleManager == nullptr) { +// ZLOGE("Failed to get bundle manager"); +// return nullptr; +// } +// return bundleManager; +//} +// +//bool PreProcessUtils::GetSpecificBundleName(const std::string &bundleName, int32_t appIndex, +// std::string &specificBundleName) +//{ +// return true; +//} +// +//bool PreProcessUtils::GetSpecificBundleNameByTokenId(uint32_t tokenId, std::string &specificBundleName, +// std::string &bundleName) +//{ +// specificBundleName = "specificBundleName"; +// bundleName = "bundleName"; +// return true; +//} +//} // namespace UDMF +//} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/preprocess_utils_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/preprocess_utils_mock.h new file mode 100644 index 00000000..92af6e73 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/preprocess_utils_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 UDMF_PREPROCESS_UTILS_H +#define UDMF_PREPROCESS_UTILS_H + +#include "bundlemgr/bundle_mgr_proxy.h" +#include "unified_data.h" + +namespace OHOS { +namespace UDMF { +class PreProcessUtils { +public: + static int32_t FillRuntimeInfo(UnifiedData &data, CustomOption &option); + static std::string GenerateId(); + static time_t GetTimestamp(); + static int32_t GetHapUidByToken(uint32_t tokenId, int &userId); + static bool GetHapBundleNameByToken(int tokenId, std::string &bundleName); + static bool GetNativeProcessNameByToken(int tokenId, std::string &processName); + static std::string GetLocalDeviceId(); + static void SetRemoteData(UnifiedData &data); + static int32_t SetRemoteUri(uint32_t tokenId, UnifiedData &data); + static bool GetInstIndex(uint32_t tokenId, int32_t &instIndex); + static bool IsNetworkingEnabled(); + static void ProcessFileType(std::vector> records, + std::function)> callback); + static void GetHtmlFileUris(uint32_t tokenId, UnifiedData &data, bool isLocal, std::vector &uris); + static void ClearHtmlDfsUris(UnifiedData &data); + static void ProcessHtmlFileUris(uint32_t tokenId, UnifiedData &data, bool isLocal, std::vector &uris); + static void ProcessRecord(std::shared_ptr record, uint32_t tokenId, + bool isLocal, std::vector &uris); + static void SetRecordUid(UnifiedData &data); + static bool GetDetailsFromUData(const UnifiedData &data, UDDetails &details); + static Status GetSummaryFromDetails(const UDDetails &details, Summary &summary); + static bool GetSpecificBundleNameByTokenId(uint32_t tokenId, std::string &specificBundleName, + std::string &bundleName); + static std::string GetAppId(const std::string &bundleName); + static sptr GetBundleMgr(); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_PREPROCESS_UTILS_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/relational_store_delegate_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/relational_store_delegate_mock.h new file mode 100644 index 00000000..a478667a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/relational_store_delegate_mock.h @@ -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. + */ +#ifndef RELATIONAL_STORE_DELEGATE_MOCK_H +#define RELATIONAL_STORE_DELEGATE_MOCK_H +#include "rdb_general_store.h" +namespace DistributedDB { +class MockRelationalStoreDelegate : public DistributedDB::RelationalStoreDelegate { +public: + ~MockRelationalStoreDelegate() = default; + + DBStatus Sync(const std::vector &devices, DistributedDB::SyncMode mode, const Query &query, + const SyncStatusCallback &onComplete, bool wait) override + { + return DBStatus::OK; + } + static inline int32_t cloudSyncTask = 0; + static bool SetCloudSyncTaskCount(int32_t task) + { + cloudSyncTask = task; + return true; + } + static inline int32_t deviceSyncTask = 0; + static bool SetDeviceTaskCount(int32_t task) + { + deviceSyncTask = task; + return true; + } + static inline int32_t downloadingAssetsCount = 0; + static bool SetDownloadingAssetsCount(int32_t task) + { + downloadingAssetsCount = task; + return true; + } + int32_t GetCloudSyncTaskCount() override + { + return cloudSyncTask; + } + std::pair GetDownloadingAssetsCount() override + { + return {DBStatus::OK, downloadingAssetsCount}; + } + int32_t GetDeviceSyncTaskCount() override + { + return deviceSyncTask; + } + DBStatus RemoveDeviceData(const std::string &device, const std::string &tableName) override + { + return DBStatus::OK; + } + + DBStatus RemoteQuery(const std::string &device, const RemoteCondition &condition, uint64_t timeout, + std::shared_ptr &result) override + { + if (device == "test") { + return DBStatus::DB_ERROR; + } + return DBStatus::OK; + } + + DBStatus RemoveDeviceData() override + { + return DBStatus::OK; + } + + DBStatus Sync(const std::vector &devices, DistributedDB::SyncMode mode, const Query &query, + const SyncProcessCallback &onProcess, int64_t waitTime) override + { + return DBStatus::OK; + } + + DBStatus SetCloudDB(const std::shared_ptr &cloudDb) override + { + return DBStatus::OK; + } + + DBStatus SetCloudDbSchema(const DataBaseSchema &schema) override + { + return DBStatus::OK; + } + + DBStatus RegisterObserver(StoreObserver *observer) override + { + return DBStatus::OK; + } + + DBStatus UnRegisterObserver() override + { + return DBStatus::OK; + } + + DBStatus UnRegisterObserver(StoreObserver *observer) override + { + return DBStatus::OK; + } + + DBStatus SetIAssetLoader(const std::shared_ptr &loader) override + { + return DBStatus::OK; + } + + DBStatus Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) override + { + return DBStatus::OK; + } + + DBStatus SetTrackerTable(const TrackerSchema &schema) override + { + if (schema.tableName == "WITH_INVENTORY_DATA") { + return DBStatus::WITH_INVENTORY_DATA; + } + if (schema.tableName == "test") { + return DBStatus::DB_ERROR; + } + return DBStatus::OK; + } + + DBStatus ExecuteSql(const SqlCondition &condition, std::vector &records) override + { + if (condition.sql == "") { + return DBStatus::DB_ERROR; + } + + std::string sqls = "INSERT INTO test ( #flag, #float, #gid, #value) VALUES ( ?, ?, ?, ?)"; + std::string sqlIn = " UPDATE test SET setSql WHERE whereSql"; + std::string sql = "REPLACE INTO test ( #flag, #float, #gid, #value) VALUES ( ?, ?, ?, ?)"; + if (condition.sql == sqls || condition.sql == sqlIn || condition.sql == sql) { + return DBStatus::DB_ERROR; + } + return DBStatus::OK; + } + + DBStatus SetReference(const std::vector &tableReferenceProperty) override + { + if (gTestResult) { + return DBStatus::DB_ERROR; + } + return DBStatus::OK; + } + + DBStatus CleanTrackerData(const std::string &tableName, int64_t cursor) override + { + return DBStatus::OK; + } + + DBStatus Pragma(PragmaCmd cmd, PragmaData &pragmaData) override + { + return DBStatus::OK; + } + + DBStatus UpsertData(const std::string &tableName, const std::vector &records, + RecordStatus status = RecordStatus::WAIT_COMPENSATED_SYNC) override + { + return DBStatus::OK; + } + + DBStatus SetCloudSyncConfig(const CloudSyncConfig &config) override + { + return DBStatus::OK; + } + static bool gTestResult; +protected: + DBStatus RemoveDeviceDataInner(const std::string &device, ClearMode mode) override + { + if (gTestResult) { + return DBStatus::DB_ERROR; + } + return DBStatus::OK; + } + + DBStatus CreateDistributedTableInner(const std::string &tableName, TableSyncType type) override + { + if (tableName == "test") { + return DBStatus::DB_ERROR; + } + return DBStatus::OK; + } +}; +} // namespace DistributedDB +#endif \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/relational_store_manager_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/relational_store_manager_mock.cpp new file mode 100644 index 00000000..ee3e111b --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/mock/relational_store_manager_mock.cpp @@ -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. + */ +#define LOG_TAG "MockRelationalStoreManager" +#include + +#include "relational_store_delegate_mock.h" +#include "relational_store_manager.h" +namespace DistributedDB { +bool MockRelationalStoreDelegate::gTestResult = false; +DBStatus RelationalStoreManager::OpenStore(const std::string &path, const std::string &storeId, + const RelationalStoreDelegate::Option &option, RelationalStoreDelegate *&delegate) +{ + delegate = new (std::nothrow) MockRelationalStoreDelegate(); + if (delegate == nullptr) { + return DB_ERROR; + } + delegate->CreateDistributedTable("naturalbase_rdb_test"); + delegate->CreateDistributedTable("naturalbase_rdb_name"); + if (storeId == "mock") { + return OK; + } + return DB_ERROR; +} + +DBStatus RelationalStoreManager::CloseStore(RelationalStoreDelegate *store) +{ + delete store; + store = nullptr; + return OK; +} +} // namespace DistributedDB \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/user_delegate_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/user_delegate_mock.cpp index bc1d1353..d013c3c1 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/user_delegate_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/user_delegate_mock.cpp @@ -91,7 +91,7 @@ bool UserDelegate::NotifyUserEvent(const UserDelegate::UserEvent &userEvent) void UserDelegate::LocalUserObserver::OnAccountChanged(const AccountEventInfo &eventInfo, int32_t timeout) { - return; + userDelegate_.NotifyUserEvent({}); } UserDelegate::LocalUserObserver::LocalUserObserver(UserDelegate &userDelegate) : userDelegate_(userDelegate) {} diff --git a/datamgr_service/services/distributeddataservice/service/test/object_asset_loader_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_asset_loader_test.cpp index c25e185c..dc5188fa 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_asset_loader_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_asset_loader_test.cpp @@ -43,7 +43,7 @@ protected: void ObjectAssetLoaderTest::SetUp() { - uri_ = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; + uri_ = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; Asset asset{ .name = "test_name", .uri = uri_, @@ -65,8 +65,8 @@ void ObjectAssetLoaderTest::TearDown() {} */ HWTEST_F(ObjectAssetLoaderTest, UploadTest001, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); - auto result = assetLoader->Transfer(userId_, bundleName_, deviceId_, asset_); + auto &assetLoader = ObjectAssetLoader::GetInstance(); + auto result = assetLoader.Transfer(userId_, bundleName_, deviceId_, asset_); ASSERT_EQ(result, false); } @@ -79,13 +79,13 @@ HWTEST_F(ObjectAssetLoaderTest, UploadTest001, TestSize.Level0) */ HWTEST_F(ObjectAssetLoaderTest, TransferAssetsAsync001, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); + auto &assetLoader = ObjectAssetLoader::GetInstance(); std::function lambdaFunc = [](bool success) { if (success) {} }; std::vector assets{ asset_ }; - ASSERT_EQ(assetLoader->executors_, nullptr); - assetLoader->TransferAssetsAsync(userId_, bundleName_, deviceId_, assets, lambdaFunc); + ASSERT_EQ(assetLoader.executors_, nullptr); + assetLoader.TransferAssetsAsync(userId_, bundleName_, deviceId_, assets, lambdaFunc); } /** @@ -97,16 +97,16 @@ HWTEST_F(ObjectAssetLoaderTest, TransferAssetsAsync001, TestSize.Level0) */ HWTEST_F(ObjectAssetLoaderTest, TransferAssetsAsync002, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); + auto &assetLoader = ObjectAssetLoader::GetInstance(); std::function lambdaFunc = [](bool success) { if (success) {} }; std::vector assets{ asset_ }; std::shared_ptr executors = std::make_shared(5, 3); ASSERT_NE(executors, nullptr); - assetLoader->SetThreadPool(executors); - ASSERT_NE(assetLoader->executors_, nullptr); - assetLoader->TransferAssetsAsync(userId_, bundleName_, deviceId_, assets, lambdaFunc); + assetLoader.SetThreadPool(executors); + ASSERT_NE(assetLoader.executors_, nullptr); + assetLoader.TransferAssetsAsync(userId_, bundleName_, deviceId_, assets, lambdaFunc); } /** @@ -118,14 +118,13 @@ HWTEST_F(ObjectAssetLoaderTest, TransferAssetsAsync002, TestSize.Level0) */ HWTEST_F(ObjectAssetLoaderTest, FinishTask001, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); - ASSERT_NE(assetLoader, nullptr); + auto &assetLoader = ObjectAssetLoader::GetInstance(); TransferTask task; task.downloadAssets.insert(uri_); - assetLoader->FinishTask(asset_.uri, true); - ASSERT_TRUE(assetLoader->tasks_.Empty()); - assetLoader->FinishTask(asset_.uri, false); - ASSERT_TRUE(assetLoader->tasks_.Empty()); + assetLoader.FinishTask(asset_.uri, true); + ASSERT_TRUE(assetLoader.tasks_.Empty()); + assetLoader.FinishTask(asset_.uri, false); + ASSERT_TRUE(assetLoader.tasks_.Empty()); } /** @@ -137,12 +136,12 @@ HWTEST_F(ObjectAssetLoaderTest, FinishTask001, TestSize.Level0) */ HWTEST_F(ObjectAssetLoaderTest, IsDownloading001, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); - assetLoader->downloading_.InsertOrAssign(asset_.uri, asset_.hash); - auto result = assetLoader->IsDownloading(asset_); + auto &assetLoader = ObjectAssetLoader::GetInstance(); + assetLoader.downloading_.InsertOrAssign(asset_.uri, asset_.hash); + auto result = assetLoader.IsDownloading(asset_); ASSERT_EQ(result, true); - assetLoader->downloading_.Erase(asset_.uri); - result = assetLoader->IsDownloading(asset_); + assetLoader.downloading_.Erase(asset_.uri); + result = assetLoader.IsDownloading(asset_); ASSERT_EQ(result, false); } @@ -155,11 +154,11 @@ HWTEST_F(ObjectAssetLoaderTest, IsDownloading001, TestSize.Level0) */ HWTEST_F(ObjectAssetLoaderTest, IsDownloaded001, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); - auto result = assetLoader->IsDownloaded(asset_); + auto &assetLoader = ObjectAssetLoader::GetInstance(); + auto result = assetLoader.IsDownloaded(asset_); ASSERT_EQ(result, false); - assetLoader->downloaded_.Insert(asset_.uri, "modifyTime_size"); - result = assetLoader->IsDownloaded(asset_); + assetLoader.downloaded_.Insert(asset_.uri, "modifyTime_size"); + result = assetLoader.IsDownloaded(asset_); ASSERT_EQ(result, true); } @@ -172,13 +171,12 @@ HWTEST_F(ObjectAssetLoaderTest, IsDownloaded001, TestSize.Level0) */ HWTEST_F(ObjectAssetLoaderTest, UpdateDownloaded001, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); - ASSERT_NE(assetLoader, nullptr); - while (!assetLoader->assetQueue_.empty()) { - assetLoader->assetQueue_.pop(); + auto &assetLoader = ObjectAssetLoader::GetInstance(); + while (!assetLoader.assetQueue_.empty()) { + assetLoader.assetQueue_.pop(); } - assetLoader->UpdateDownloaded(asset_); - auto [success, hash] = assetLoader->downloaded_.Find(asset_.uri); + assetLoader.UpdateDownloaded(asset_); + auto [success, hash] = assetLoader.downloaded_.Find(asset_.uri); ASSERT_TRUE(success); EXPECT_EQ(hash, asset_.hash); } @@ -192,18 +190,17 @@ HWTEST_F(ObjectAssetLoaderTest, UpdateDownloaded001, TestSize.Level0) */ HWTEST_F(ObjectAssetLoaderTest, UpdateDownloaded002, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); - ASSERT_NE(assetLoader, nullptr); - while (!assetLoader->assetQueue_.empty()) { - assetLoader->assetQueue_.pop(); + auto &assetLoader = ObjectAssetLoader::GetInstance(); + while (!assetLoader.assetQueue_.empty()) { + assetLoader.assetQueue_.pop(); } - for (int i = 0; i <= assetLoader->LAST_DOWNLOAD_ASSET_SIZE; i++) { - assetLoader->assetQueue_.push(asset_.uri); + for (int i = 0; i <= assetLoader.LAST_DOWNLOAD_ASSET_SIZE; i++) { + assetLoader.assetQueue_.push(asset_.uri); } - assetLoader->UpdateDownloaded(asset_); - EXPECT_NE(assetLoader->assetQueue_.size(), ObjectAssetLoader::LAST_DOWNLOAD_ASSET_SIZE); - EXPECT_EQ(assetLoader->assetQueue_.size(), ObjectAssetLoader::LAST_DOWNLOAD_ASSET_SIZE + 1); - auto [success, hash] = assetLoader->downloaded_.Find(asset_.uri); + assetLoader.UpdateDownloaded(asset_); + EXPECT_NE(assetLoader.assetQueue_.size(), ObjectAssetLoader::LAST_DOWNLOAD_ASSET_SIZE); + EXPECT_EQ(assetLoader.assetQueue_.size(), ObjectAssetLoader::LAST_DOWNLOAD_ASSET_SIZE + 1); + auto [success, hash] = assetLoader.downloaded_.Find(asset_.uri); EXPECT_EQ(success, false); EXPECT_EQ(hash, ""); } @@ -215,8 +212,7 @@ HWTEST_F(ObjectAssetLoaderTest, UpdateDownloaded002, TestSize.Level0) */ HWTEST_F(ObjectAssetLoaderTest, PushAsset001, TestSize.Level0) { - auto assetLoader = ObjectAssetLoader::GetInstance(); - ASSERT_NE(assetLoader, nullptr); + auto &assetLoader = ObjectAssetLoader::GetInstance(); sptr assetObj = new AssetObj(); assetObj->dstBundleName_ = bundleName_; assetObj->srcBundleName_ = bundleName_; @@ -225,10 +221,22 @@ HWTEST_F(ObjectAssetLoaderTest, PushAsset001, TestSize.Level0) sptr sendCallback = new ObjectAssetsSendListener(); ASSERT_NE(sendCallback, nullptr); - int32_t ret = assetLoader->PushAsset(userId_, assetObj, sendCallback); + int32_t ret = assetLoader.PushAsset(userId_, assetObj, sendCallback); EXPECT_NE(ret, DistributedObject::OBJECT_SUCCESS); } +/** +* @tc.name: PushAsset002 +* @tc.desc: PushAsset test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectAssetLoaderTest, PushAsset002, TestSize.Level0) +{ + auto &assetLoader = ObjectAssetLoader::GetInstance(); + int32_t ret = assetLoader.PushAsset(userId_, nullptr, nullptr); + EXPECT_EQ(ret, DistributedObject::OBJECT_INNER_ERROR); +} + /** * @tc.name: OnSendResult001 * @tc.desc: OnSendResult test. diff --git a/datamgr_service/services/distributeddataservice/service/test/object_asset_machine_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_asset_machine_test.cpp index dd3f5b43..071a5eab 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_asset_machine_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_asset_machine_test.cpp @@ -32,6 +32,7 @@ class ObjectAssetMachineTest : public testing::Test { public: void SetUp(); void TearDown(); + static void SetUpTestCase(void); protected: AssetBindInfo AssetBindInfo_; @@ -39,14 +40,20 @@ protected: std::string uri_; std::string bundleName_ = "test_bundleName"; std::map changedAssets_; - std::string sessionId = "123"; + std::string sessionId_ = "123"; StoreInfo storeInfo_; - std::shared_ptr machine; + std::shared_ptr machine_; }; +void ObjectAssetMachineTest::SetUpTestCase(void) +{ + auto executors = std::make_shared(2, 1); + ObjectAssetLoader::GetInstance().SetThreadPool(executors); +} + void ObjectAssetMachineTest::SetUp() { - uri_ = "file:://com.huawei.hmos.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; + uri_ = "file:://com.examples.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; Asset asset{ .name = "test_name", .uri = uri_, @@ -75,10 +82,9 @@ void ObjectAssetMachineTest::SetUp() storeInfo_ = storeInfo; ChangedAssetInfo changedAssetInfo(asset, AssetBindInfo, storeInfo); changedAssets_[uri_] = changedAssetInfo; - if (machine == nullptr) { - machine = std::make_shared(); - auto executors = std::make_shared(2, 1); - ObjectAssetLoader::GetInstance()->SetThreadPool(executors); + changedAssets_[uri_].status = STATUS_STABLE; + if (machine_ == nullptr) { + machine_ = std::make_shared(); } } @@ -102,7 +108,7 @@ HWTEST_F(ObjectAssetMachineTest, StatusTransfer001, TestSize.Level0) }; std::pair changedAsset{ "device_2", asset }; changedAssets_[uri_].status = STATUS_TRANSFERRING; - machine->DFAPostEvent(REMOTE_CHANGED, changedAssets_[uri_], asset, changedAsset); + machine_->DFAPostEvent(REMOTE_CHANGED, changedAssets_[uri_], asset, changedAsset); ASSERT_EQ(changedAssets_[uri_].status, STATUS_WAIT_TRANSFER); ASSERT_EQ(changedAssets_[uri_].deviceId, changedAsset.first); ASSERT_EQ(changedAssets_[uri_].asset.hash, asset.hash); @@ -126,7 +132,7 @@ HWTEST_F(ObjectAssetMachineTest, StatusTransfer002, TestSize.Level0) }; std::pair changedAsset{ "device_2", asset }; changedAssets_[uri_].status = STATUS_TRANSFERRING; - machine->DFAPostEvent(TRANSFER_FINISHED, changedAssets_[uri_], asset, changedAsset); + machine_->DFAPostEvent(TRANSFER_FINISHED, changedAssets_[uri_], asset, changedAsset); ASSERT_EQ(changedAssets_[uri_].status, STATUS_STABLE); } @@ -148,7 +154,7 @@ HWTEST_F(ObjectAssetMachineTest, StatusTransfer003, TestSize.Level0) }; std::pair changedAsset{ "device_2", asset }; changedAssets_[uri_].status = STATUS_UPLOADING; - machine->DFAPostEvent(REMOTE_CHANGED, changedAssets_[uri_], asset, changedAsset); + machine_->DFAPostEvent(REMOTE_CHANGED, changedAssets_[uri_], asset, changedAsset); ASSERT_EQ(changedAssets_[uri_].status, STATUS_WAIT_TRANSFER); ASSERT_EQ(changedAssets_[uri_].deviceId, changedAsset.first); ASSERT_EQ(changedAssets_[uri_].asset.hash, asset.hash); @@ -170,7 +176,27 @@ HWTEST_F(ObjectAssetMachineTest, DFAPostEvent001, TestSize.Level0) }; std::pair changedAsset{ "device_2", asset }; changedAssets_[uri_].status = STATUS_UPLOADING; - auto ret = machine->DFAPostEvent(EVENT_BUTT, changedAssets_[uri_], asset, changedAsset); + auto ret = machine_->DFAPostEvent(EVENT_BUTT, changedAssets_[uri_], asset, changedAsset); + ASSERT_EQ(ret, GeneralError::E_ERROR); +} + +/** +* @tc.name: DFAPostEvent001 +* @tc.desc: DFAPostEvent invalid status test +* @tc.type: FUNC +*/ +HWTEST_F(ObjectAssetMachineTest, DFAPostEvent002, TestSize.Level0) +{ + Asset asset{ + .name = "test_name", + .uri = uri_, + .modifyTime = "modifyTime1", + .size = "size1", + .hash = "modifyTime1_size1", + }; + std::pair changedAsset{ "device_2", asset }; + changedAssets_[uri_].status = DistributedData::STATUS_NO_CHANGE; + auto ret = machine_->DFAPostEvent(UPLOAD, changedAssets_[uri_], asset, changedAsset); ASSERT_EQ(ret, GeneralError::E_ERROR); } @@ -191,13 +217,13 @@ HWTEST_F(ObjectAssetMachineTest, StatusUpload001, TestSize.Level0) .hash = "modifyTime1_size1", }; std::pair changedAsset{ "device_1", asset }; - machine->DFAPostEvent(UPLOAD, changedAssets_[uri_], asset, changedAsset); + machine_->DFAPostEvent(UPLOAD, changedAssets_[uri_], asset, changedAsset); ASSERT_EQ(changedAssets_[uri_].status, STATUS_UPLOADING); - machine->DFAPostEvent(UPLOAD_FINISHED, changedAssets_[uri_], asset); + machine_->DFAPostEvent(UPLOAD_FINISHED, changedAssets_[uri_], asset); ASSERT_EQ(changedAssets_[uri_].status, STATUS_STABLE); // dotransfer - machine->DFAPostEvent(REMOTE_CHANGED, changedAssets_[uri_], asset, changedAsset); + machine_->DFAPostEvent(REMOTE_CHANGED, changedAssets_[uri_], asset, changedAsset); ASSERT_EQ(changedAssets_[uri_].status, STATUS_TRANSFERRING); } @@ -227,23 +253,23 @@ HWTEST_F(ObjectAssetMachineTest, StatusUpload002, TestSize.Level0) .assetName = "asset_" + timestamp + ".jpg", }; StoreInfo storeInfo { - .tokenId = static_cast(time), + .tokenId = time, .bundleName = "bundleName_" + timestamp, .storeName = "store_" + timestamp, - .instanceId = static_cast(time), - .user = static_cast(time), + .instanceId = time, + .user = time, }; ChangedAssetInfo changedAssetInfo(asset, bindInfo, storeInfo); std::pair changedAsset{ "device_" + timestamp, asset }; - machine->DFAPostEvent(UPLOAD, changedAssetInfo, asset); + machine_->DFAPostEvent(UPLOAD, changedAssetInfo, asset); ASSERT_EQ(changedAssetInfo.status, STATUS_UPLOADING); - machine->DFAPostEvent(REMOTE_CHANGED, changedAssetInfo, asset, changedAsset); + machine_->DFAPostEvent(REMOTE_CHANGED, changedAssetInfo, asset, changedAsset); ASSERT_EQ(changedAssetInfo.status, STATUS_WAIT_TRANSFER); ASSERT_EQ(changedAssetInfo.asset.hash, asset.hash); - machine->DFAPostEvent(UPLOAD_FINISHED, changedAssetInfo, asset); + machine_->DFAPostEvent(UPLOAD_FINISHED, changedAssetInfo, asset); ASSERT_EQ(changedAssetInfo.status, STATUS_TRANSFERRING); } @@ -280,10 +306,10 @@ HWTEST_F(ObjectAssetMachineTest, StatusDownload001, TestSize.Level0) ChangedAssetInfo changedAssetInfo(asset, AssetBindInfo, storeInfo); std::pair changedAsset{ "device_006", asset }; - machine->DFAPostEvent(DOWNLOAD, changedAssetInfo, asset, changedAsset); + machine_->DFAPostEvent(DOWNLOAD, changedAssetInfo, asset, changedAsset); ASSERT_EQ(changedAssetInfo.status, STATUS_DOWNLOADING); - machine->DFAPostEvent(DOWNLOAD_FINISHED, changedAssetInfo, asset); + machine_->DFAPostEvent(DOWNLOAD_FINISHED, changedAssetInfo, asset); ASSERT_EQ(changedAssetInfo.status, STATUS_STABLE); } } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/object_manager_mock_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_manager_mock_test.cpp new file mode 100644 index 00000000..2c7663b0 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/object_manager_mock_test.cpp @@ -0,0 +1,522 @@ +/* +* 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. +*/ + +#define LOG_TAG "ObjectManagerMockTest" +#include +#include + +#include "device_manager_adapter_mock.h" +#include "device_matrix_mock.h" +#include "gtest/gtest.h" +#include "mock/access_token_mock.h" +#include "mock/account_delegate_mock.h" +#include "mock/distributed_file_daemon_manager_mock.h" +#include "mock/meta_data_manager_mock.h" +#include "object_manager.h" +#include "object_service_impl.h" + + +using namespace OHOS::DistributedObject; +using namespace OHOS::DistributedData; +using namespace OHOS::Storage::DistributedFile; +using namespace OHOS::Security::AccessToken; +using namespace testing::ext; +using namespace testing; +using AssetValue = OHOS::CommonType::AssetValue; +using DeviceInfo = OHOS::AppDistributedKv::DeviceInfo; +using OnComplete = OHOS::DistributedData::MetaDataManager::OnComplete; + +namespace OHOS::Test { +namespace DistributedDataTest { +class ObjectManagerMockTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + metaDataManagerMock = std::make_shared(); + BMetaDataManager::metaDataManager = metaDataManagerMock; + metaDataMock = std::make_shared>(); + BMetaData::metaDataManager = metaDataMock; + devMgrAdapterMock = std::make_shared(); + BDeviceManagerAdapter::deviceManagerAdapter = devMgrAdapterMock; + deviceMatrixMock = std::make_shared(); + BDeviceMatrix::deviceMatrix = deviceMatrixMock; + fileDaemonMgrMock = std::make_shared(); + BDistributedFileDaemonManager::fileDaemonManger_ = fileDaemonMgrMock; + accountDelegateMock = new (std::nothrow) AccountDelegateMock(); + if (accountDelegateMock != nullptr) { + AccountDelegate::instance_ = nullptr; + AccountDelegate::RegisterAccountInstance(accountDelegateMock); + } + accTokenMock = std::make_shared(); + BAccessTokenKit::accessTokenkit = accTokenMock; + } + static void TearDownTestCase(void) + { + metaDataManagerMock = nullptr; + BMetaDataManager::metaDataManager = nullptr; + metaDataMock = nullptr; + BMetaData::metaDataManager = nullptr; + devMgrAdapterMock = nullptr; + BDeviceManagerAdapter::deviceManagerAdapter = nullptr; + deviceMatrixMock = nullptr; + BDeviceMatrix::deviceMatrix = nullptr; + fileDaemonMgrMock = nullptr; + BDistributedFileDaemonManager::fileDaemonManger_ = nullptr; + if (accountDelegateMock != nullptr) { + delete accountDelegateMock; + accountDelegateMock = nullptr; + } + accTokenMock = nullptr; + BAccessTokenKit::accessTokenkit = nullptr; + } + + static inline std::shared_ptr metaDataManagerMock = nullptr; + static inline std::shared_ptr> metaDataMock = nullptr; + static inline std::shared_ptr devMgrAdapterMock = nullptr; + static inline std::shared_ptr deviceMatrixMock = nullptr; + static inline std::shared_ptr fileDaemonMgrMock = nullptr; + static inline AccountDelegateMock *accountDelegateMock = nullptr; + static inline std::shared_ptr accTokenMock = nullptr; + void SetUp() {}; + void TearDown() {}; + +protected: + std::string sessionId_ = "123"; + OHOS::ObjectStore::AssetBindInfo assetBindInfo_; + AssetValue assetValue_; +}; + +/** + * @tc.name: IsNeedMetaSync001 + * @tc.desc: Test IsNeedMetaSync when LoadMeta fails for CapMetaData. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(ObjectManagerMockTest, IsNeedMetaSync001, TestSize.Level0) +{ + EXPECT_CALL(*fileDaemonMgrMock, RegisterAssetCallback(_)).WillOnce(testing::Return(0)); + auto &manager = ObjectStoreManager::GetInstance(); + StoreMetaData meta; + meta.deviceId = "test_device_id"; + meta.user = "0"; + meta.storeId = "distributedObject_"; + meta.bundleName = "test_bundle"; + std::vector uuids = { "test_uuid" }; + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)).WillOnce(testing::Return(false)); + bool isNeedSync = manager.IsNeedMetaSync(meta, uuids); + EXPECT_EQ(isNeedSync, true); + EXPECT_CALL(*metaDataManagerMock, LoadMeta(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(true)) + .WillOnce(testing::Return(false)); + isNeedSync = manager.IsNeedMetaSync(meta, uuids); + EXPECT_EQ(isNeedSync, true); +} + +/** + * @tc.name: IsNeedMetaSync002 + * @tc.desc: Test IsNeedMetaSync when LoadMeta fails for StoreMetaData. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(ObjectManagerMockTest, IsNeedMetaSync002, TestSize.Level0) +{ + auto &manager = ObjectStoreManager::GetInstance(); + StoreMetaData meta; + meta.deviceId = "test_device_id"; + meta.user = "0"; + meta.storeId = "distributedObject_"; + meta.bundleName = "test_bundle"; + std::vector uuids = { "test_uuid" }; + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)).WillRepeatedly(Return((true))); + EXPECT_CALL(*deviceMatrixMock, GetRemoteMask(_, _)) + .WillRepeatedly(Return(std::make_pair(true, DeviceMatrix::META_STORE_MASK))); + + bool result = manager.IsNeedMetaSync(meta, uuids); + EXPECT_EQ(result, true); +} + +/** + * @tc.name: IsNeedMetaSync003 + * @tc.desc: Test IsNeedMetaSync when LoadMeta fails for StoreMetaData. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(ObjectManagerMockTest, IsNeedMetaSync003, TestSize.Level0) +{ + auto &manager = ObjectStoreManager::GetInstance(); + StoreMetaData meta; + meta.deviceId = "test_device_id"; + meta.user = "0"; + meta.storeId = "distributedObject_"; + meta.bundleName = "test_bundle"; + std::vector uuids = { "test_uuid" }; + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)).WillRepeatedly(Return(true)); + EXPECT_CALL(*deviceMatrixMock, GetRemoteMask(_, _)).WillOnce(Return(std::make_pair(true, 0))); + EXPECT_CALL(*deviceMatrixMock, GetMask(_, _)).WillOnce(Return(std::make_pair(true, DeviceMatrix::META_STORE_MASK))); + + bool result = manager.IsNeedMetaSync(meta, uuids); + EXPECT_EQ(result, true); + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)).WillRepeatedly(Return(true)); + + EXPECT_CALL(*deviceMatrixMock, GetRemoteMask(_, _)).WillOnce(Return(std::make_pair(true, 0))); + + EXPECT_CALL(*deviceMatrixMock, GetMask(_, _)).WillOnce(Return(std::make_pair(true, 0))); + + result = manager.IsNeedMetaSync(meta, uuids); + EXPECT_EQ(result, false); +} + +/** + * @tc.name: SyncOnStore001 + * @tc.desc: Test SyncOnStore + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(ObjectManagerMockTest, SyncOnStore001, TestSize.Level0) +{ + // 2 means that the GetUserByToken interface will be called twice + EXPECT_CALL(*accountDelegateMock, GetUserByToken(_)).Times(2).WillRepeatedly(Return(0)); + auto &manager = ObjectStoreManager::GetInstance(); + std::function &results)> func; + func = [](const std::map &results) { return results; }; + std::string prefix = "ObjectManagerTest"; + StoreMetaData meta; + meta.deviceId = "test_device_id"; + meta.user = "0"; + meta.storeId = "distributedObject_"; + meta.bundleName = "test_bundle"; + std::vector uuids = { "test_uuid" }; + + // local device + { + std::vector localDeviceList = { "local" }; + auto result = manager.SyncOnStore(prefix, localDeviceList, func); + EXPECT_EQ(result, OBJECT_SUCCESS); + } + + // remote device. IsNeedMetaSync: true; Sync: true + { + std::vector remoteDeviceList = { "remote_device_1" }; + EXPECT_CALL(*devMgrAdapterMock, GetUuidByNetworkId(_)).WillRepeatedly(Return("mock_uuid")); + EXPECT_CALL(*devMgrAdapterMock, ToUUID(testing::A &>())) + .WillOnce(Return(std::vector{ "mock_uuid_1" })); + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)).WillOnce(testing::Return(false)); + EXPECT_CALL(*metaDataManagerMock, Sync(_, _, _, _)).WillOnce(testing::Return(true)); + auto result = manager.SyncOnStore(prefix, remoteDeviceList, func); + EXPECT_EQ(result, OBJECT_SUCCESS); + } + + // remote device. IsNeedMetaSync: false + { + std::vector remoteDeviceList = { "remote_device_1" }; + EXPECT_CALL(*devMgrAdapterMock, GetUuidByNetworkId(_)).WillRepeatedly(Return("mock_uuid")); + EXPECT_CALL(*devMgrAdapterMock, ToUUID(testing::A &>())) + .WillOnce(Return(std::vector{ "mock_uuid_1" })); + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(testing::Return(true)) + .WillOnce(testing::Return(true)); + EXPECT_CALL(*deviceMatrixMock, GetRemoteMask(_, _)).WillOnce(Return(std::make_pair(true, 0))); + EXPECT_CALL(*deviceMatrixMock, GetMask(_, _)).WillOnce(Return(std::make_pair(true, 0))); + auto result = manager.SyncOnStore(prefix, remoteDeviceList, func); + EXPECT_EQ(result, E_DB_ERROR); + } +} + +/** +* @tc.name: GetCurrentUser001 +* @tc.desc: Test the scenario where the QueryUsers return false in the GetCurrentUser function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ObjectManagerMockTest, GetCurrentUser001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::vector users; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(users), Return(false))); + auto result = manager.GetCurrentUser(); + EXPECT_EQ(result, ""); +} + +/** +* @tc.name: GetCurrentUser002 +* @tc.desc: Test the scenario where the QueryUsers users empty in the GetCurrentUser function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ObjectManagerMockTest, GetCurrentUser002, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::vector users; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)) + .Times(1) + .WillOnce( + DoAll(SetArgReferee<0>(users), Invoke([](std::vector &users) { users.clear(); }), Return(true))); + auto result = manager.GetCurrentUser(); + EXPECT_EQ(result, ""); +} + +/** +* @tc.name: GetCurrentUser003 +* @tc.desc: Test the scenario where the QueryUsers return true in the GetCurrentUser function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ObjectManagerMockTest, GetCurrentUser003, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::vector users = { 0, 1 }; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(users), Return(true))); + auto result = manager.GetCurrentUser(); + EXPECT_EQ(result, std::to_string(users[0])); +} + +/** +* @tc.name: WaitAssets001 +* @tc.desc: WaitAssets test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, WaitAssets001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string objectKey = "objectKey"; + ObjectStoreManager::SaveInfo info; + std::map data; + auto ret = manager.WaitAssets(objectKey, info, data); + EXPECT_EQ(ret, DistributedObject::OBJECT_INNER_ERROR); +} + +/** +* @tc.name: NotifyAssetsReady001 +* @tc.desc: NotifyAssetsReady test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, NotifyAssetsReady001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string objectKey = "objectKey"; + std::string bundleName = "bundleName"; + std::string srcNetworkId = "srcNetworkId"; + manager.NotifyAssetsReady(objectKey, bundleName, srcNetworkId); + EXPECT_EQ(manager.executors_, nullptr); +} + +/** +* @tc.name: DoNotifyAssetsReady001 +* @tc.desc: DoNotifyAssetsReady test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, DoNotifyAssetsReady001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + uint32_t tokenId = 0; + ObjectStoreManager::CallbackInfo info; + std::string objectKey = "objectKey"; + bool isReady = true; + manager.DoNotifyAssetsReady(tokenId, info, objectKey, isReady); + EXPECT_EQ(manager.executors_, nullptr); +} + +/** +* @tc.name: DoNotifyWaitAssetTimeout001 +* @tc.desc: DoNotifyWaitAssetTimeout test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, DoNotifyWaitAssetTimeout001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string objectKey = "objectKey"; + manager.DoNotifyWaitAssetTimeout(objectKey); + EXPECT_EQ(manager.executors_, nullptr); +} + +/** +* @tc.name: FlushClosedStore001 +* @tc.desc: FlushClosedStore test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, FlushClosedStore001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + manager.FlushClosedStore(); + EXPECT_EQ(manager.executors_, nullptr); +} + +/** +* @tc.name: CloseAfterMinute001 +* @tc.desc: CloseAfterMinute test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, CloseAfterMinute001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + manager.CloseAfterMinute(); + EXPECT_EQ(manager.executors_, nullptr); +} + +/** +* @tc.name: UnRegisterAssetsLister001 +* @tc.desc: UnRegisterAssetsLister test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, UnRegisterAssetsLister001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + manager.objectAssetsRecvListener_ = nullptr; + auto ret = manager.UnRegisterAssetsLister(); + EXPECT_EQ(ret, true); + EXPECT_CALL(*fileDaemonMgrMock, RegisterAssetCallback(_)).WillOnce(testing::Return(0)); + manager.RegisterAssetsLister(); + EXPECT_CALL(*fileDaemonMgrMock, UnRegisterAssetCallback(_)).WillOnce(testing::Return(-1)); + ret = manager.UnRegisterAssetsLister(); + EXPECT_EQ(ret, false); + EXPECT_CALL(*fileDaemonMgrMock, UnRegisterAssetCallback(_)).WillOnce(testing::Return(0)); + ret = manager.UnRegisterAssetsLister(); + EXPECT_EQ(ret, true); +} + +/** +* @tc.name: InitUserMeta001 +* @tc.desc: Test the scenario where the QueryUsers return false in the GetCurrentUser function. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, InitUserMeta001, TestSize.Level1) +{ + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(testing::Return(false)); + auto &manager = ObjectStoreManager::GetInstance(); + std::vector users; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(users), Return(false))); + auto status = manager.InitUserMeta(); + EXPECT_EQ(status, DistributedObject::OBJECT_INNER_ERROR); +} + +/** +* @tc.name: InitUserMeta002 +* @tc.desc: Test the scenario where the QueryUsers users empty in the GetCurrentUser function. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, InitUserMeta002, TestSize.Level1) +{ + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(testing::Return(false)); + auto &manager = ObjectStoreManager::GetInstance(); + std::vector users; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)) + .Times(1) + .WillOnce( + DoAll(SetArgReferee<0>(users), Invoke([](std::vector &users) { users.clear(); }), Return(true))); + auto status = manager.InitUserMeta(); + EXPECT_EQ(status, DistributedObject::OBJECT_INNER_ERROR); +} + +/** +* @tc.name: InitUserMeta003 +* @tc.desc: Test the scenario where the QueryUsers return true in the GetCurrentUser function. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, InitUserMeta003, TestSize.Level1) +{ + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(testing::Return(false)); + DeviceInfo devInfo = { .uuid = "666" }; + EXPECT_CALL(*devMgrAdapterMock, GetLocalDevice()).WillOnce(Return(devInfo)); + auto &manager = ObjectStoreManager::GetInstance(); + std::vector users = { 0, 1 }; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(users), Return(true))); + auto status = manager.InitUserMeta(); + EXPECT_EQ(status, DistributedObject::OBJECT_INNER_ERROR); +} + +/** +* @tc.name: BindAsset001 +* @tc.desc: Test BindAsset function when GetTokenTypeFlag is not TOKEN_HAP. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, BindAsset001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string bundleName = "BindAsset"; + uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(_)) + .Times(1) + .WillOnce(Return(ATokenTypeEnum::TOKEN_NATIVE)); + auto result = manager.BindAsset(tokenId, bundleName, sessionId_, assetValue_, assetBindInfo_); + EXPECT_EQ(result, DistributedObject::OBJECT_DBSTATUS_ERROR); +} + +/** +* @tc.name: BindAsset002 +* @tc.desc: Test BindAsset function when GetTokenTypeFlag is TOKEN_HAP. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, BindAsset002, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string bundleName = "BindAsset"; + uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(_)) + .Times(1) + .WillOnce(Return(ATokenTypeEnum::TOKEN_HAP)); + EXPECT_CALL(*accTokenMock, GetHapTokenInfo(_, _)) + .Times(1) + .WillOnce(Return(0)); + auto result = manager.BindAsset(tokenId, bundleName, sessionId_, assetValue_, assetBindInfo_); + EXPECT_EQ(result, DistributedObject::OBJECT_SUCCESS); +} + +/** +* @tc.name: IsContinue001 +* @tc.desc: Test IsContinue function when GetTokenTypeFlag is not TOKEN_HAP. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, IsContinue001, TestSize.Level1) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + bool isContinue = false; + EXPECT_CALL(*fileDaemonMgrMock, UnRegisterAssetCallback(_)).WillRepeatedly(testing::Return(0)); + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(_)) + .Times(1) + .WillOnce(Return(ATokenTypeEnum::TOKEN_NATIVE)); + auto ret = objectServiceImpl->IsContinue(isContinue); + EXPECT_EQ(ret, DistributedObject::OBJECT_INNER_ERROR); +} + +/** +* @tc.name: IsContinue002 +* @tc.desc: Test IsContinue function when GetTokenTypeFlag is TOKEN_HAP. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerMockTest, IsContinue002, TestSize.Level1) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + bool isContinue = false; + EXPECT_CALL(*accTokenMock, GetTokenTypeFlag(_)) + .Times(2) + .WillRepeatedly(Return(ATokenTypeEnum::TOKEN_HAP)); + EXPECT_CALL(*accTokenMock, GetHapTokenInfo(_, _)) + .Times(1) + .WillOnce(Return(0)); + auto ret = objectServiceImpl->IsContinue(isContinue); + EXPECT_EQ(ret, DistributedObject::OBJECT_SUCCESS); +} +}; // namespace DistributedDataTest +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/object_manager_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_manager_test.cpp index 835dca5b..17183561 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_manager_test.cpp @@ -20,21 +20,179 @@ #include #include +#include "bootstrap.h" +#include "device_manager_adapter_mock.h" #include "executor_pool.h" #include "kv_store_nb_delegate_mock.h" +#include "kvstore_meta_manager.h" +#include "metadata/object_user_meta_data.h" #include "object_types.h" #include "snapshot/machine_status.h" using namespace testing::ext; using namespace OHOS::DistributedObject; +using namespace OHOS::DistributedData; +using namespace std; +using namespace testing; using AssetValue = OHOS::CommonType::AssetValue; using RestoreStatus = OHOS::DistributedObject::ObjectStoreManager::RestoreStatus; namespace OHOS::Test { +class IObjectSaveCallback { +public: + virtual void Completed(const std::map &results) = 0; +}; +class IObjectRevokeSaveCallback { +public: + virtual void Completed(int32_t status) = 0; +}; +class IObjectRetrieveCallback { +public: + virtual void Completed(const std::map> &results, bool allReady) = 0; +}; +class IObjectChangeCallback { +public: + virtual void Completed(const std::map> &results, bool allReady) = 0; +}; + +class IObjectProgressCallback { +public: + virtual void Completed(int32_t progress) = 0; +}; + +class ObjectSaveCallbackBroker : public IObjectSaveCallback, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedObject.IObjectSaveCallback"); +}; +class ObjectSaveCallbackStub : public IRemoteStub { +public: + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override + { + return 0; + } +}; +class ObjectRevokeSaveCallbackBroker : public IObjectRevokeSaveCallback, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedObject.IObjectRevokeSaveCallback"); +}; +class ObjectRevokeSaveCallbackStub : public IRemoteStub { +public: + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override + { + return 0; + } +}; +class ObjectRetrieveCallbackBroker : public IObjectRetrieveCallback, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedObject.IObjectRetrieveCallback"); +}; +class ObjectRetrieveCallbackStub : public IRemoteStub { +public: + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override + { + return 0; + } +}; + +class ObjectChangeCallbackBroker : public IObjectChangeCallback, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedObject.IObjectChangeCallback"); +}; + +class ObjectChangeCallbackStub : public IRemoteStub { +public: + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override + { + return 0; + } +}; + +class ObjectProgressCallbackBroker : public IObjectProgressCallback, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedObject.IObjectProgressCallback"); +}; + +class ObjectProgressCallbackStub : public IRemoteStub { +public: + int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override + { + return 0; + } +}; + +class ObjectSaveCallback : public ObjectSaveCallbackStub { +public: + explicit ObjectSaveCallback(const std::function &)> &callback) + : callback_(callback) + { + } + void Completed(const std::map &results) override + { + } + +private: + const std::function &)> callback_; +}; +class ObjectRevokeSaveCallback : public ObjectRevokeSaveCallbackStub { +public: + explicit ObjectRevokeSaveCallback(const std::function &callback) : callback_(callback) + { + } + void Completed(int32_t) override + { + } + +private: + const std::function callback_; +}; +class ObjectRetrieveCallback : public ObjectRetrieveCallbackStub { +public: + explicit ObjectRetrieveCallback( + const std::function> &, bool)> &callback) + : callback_(callback) + { + } + void Completed(const std::map> &results, bool allReady) override + { + } + +private: + const std::function> &, bool)> callback_; +}; + +class ObjectChangeCallback : public ObjectChangeCallbackStub { +public: + explicit ObjectChangeCallback( + const std::function> &, bool)> &callback) + : callback_(callback) + { + } + void Completed(const std::map> &results, bool allReady) override + { + } + +private: + const std::function> &, bool)> callback_; +}; + +class ObjectProgressCallback : public ObjectProgressCallbackStub { +public: + explicit ObjectProgressCallback(const std::function &callback) : callback_(callback) + { + } + void Completed(int32_t progress) override + { + } + +private: + const std::function callback_; +}; class ObjectManagerTest : public testing::Test { public: void SetUp(); void TearDown(); + static void SetUpTestCase(void); + static void TearDownTestCase(void); protected: Asset asset_; @@ -47,16 +205,17 @@ protected: uint64_t sequenceId_2 = 20; uint64_t sequenceId_3 = 30; std::string userId_ = "100"; - std::string bundleName_ = "com.examples.hmos.notepad"; + std::string bundleName_ = "com.examples.notepad"; OHOS::ObjectStore::AssetBindInfo assetBindInfo_; pid_t pid_ = 10; uint32_t tokenId_ = 100; AssetValue assetValue_; + static inline std::shared_ptr devMgrAdapterMock = nullptr; }; void ObjectManagerTest::SetUp() { - uri_ = "file:://com.examples.hmos.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; + uri_ = "file:://com.examples.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; Asset asset{ .name = "test_name", .uri = uri_, @@ -91,7 +250,27 @@ void ObjectManagerTest::SetUp() assetBindInfo_ = AssetBindInfo; } -void ObjectManagerTest::TearDown() {} +void ObjectManagerTest::SetUpTestCase(void) +{ + devMgrAdapterMock = make_shared(); + BDeviceManagerAdapter::deviceManagerAdapter = devMgrAdapterMock; + std::shared_ptr executors = std::make_shared(1, 0); + Bootstrap::GetInstance().LoadDirectory(); + Bootstrap::GetInstance().LoadCheckers(); + DistributedKv::KvStoreMetaManager::GetInstance().BindExecutor(executors); + DistributedKv::KvStoreMetaManager::GetInstance().InitMetaParameter(); + DistributedKv::KvStoreMetaManager::GetInstance().InitMetaListener(); +} + +void ObjectManagerTest::TearDownTestCase(void) +{ + BDeviceManagerAdapter::deviceManagerAdapter = nullptr; + devMgrAdapterMock = nullptr; +} + +void ObjectManagerTest::TearDown() +{ +} /** * @tc.name: DeleteNotifier001 @@ -118,12 +297,10 @@ HWTEST_F(ObjectManagerTest, Process001, TestSize.Level0) { auto syncManager = SequenceSyncManager::GetInstance(); std::map results; - results = {{ "test_cloud", DistributedDB::DBStatus::OK }}; + results = { { "test_cloud", DistributedDB::DBStatus::OK } }; std::function &results)> func; - func = [](const std::map &results) { - return results; - }; + func = [](const std::map &results) { return results; }; auto result = syncManager->Process(sequenceId_, results, userId_); ASSERT_EQ(result, SequenceSyncManager::ERR_SID_NOT_EXIST); syncManager->seqIdCallbackRelations_.emplace(sequenceId_, func); @@ -142,11 +319,9 @@ HWTEST_F(ObjectManagerTest, DeleteNotifierNoLock001, TestSize.Level0) { auto syncManager = SequenceSyncManager::GetInstance(); std::function &results)> func; - func = [](const std::map &results) { - return results; - }; + func = [](const std::map &results) { return results; }; syncManager->seqIdCallbackRelations_.emplace(sequenceId_, func); - std::vector seqIds = {sequenceId_, sequenceId_2, sequenceId_3}; + std::vector seqIds = { sequenceId_, sequenceId_2, sequenceId_3 }; std::string userId = "user_1"; auto result = syncManager->DeleteNotifierNoLock(sequenceId_, userId_); ASSERT_EQ(result, SequenceSyncManager::SUCCESS_USER_HAS_FINISHED); @@ -155,6 +330,29 @@ HWTEST_F(ObjectManagerTest, DeleteNotifierNoLock001, TestSize.Level0) ASSERT_EQ(result, SequenceSyncManager::SUCCESS_USER_IN_USE); } +/** +* @tc.name: SaveToStoreTest +* @tc.desc: SaveToStore test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, SaveToStoreTest, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string dataDir = "/data/app/el2/100/database"; + manager.SetData(dataDir, userId_); + auto result = manager.Open(); + ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); + ASSERT_NE(manager.delegate_, nullptr); + ObjectRecord data{}; + result = manager.SaveToStore("appId", "sessionId", "toDeviceId", data); + ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); + + manager.ForceClose(); + ASSERT_EQ(manager.delegate_, nullptr); + result = manager.SaveToStore("appId", "sessionId", "toDeviceId", data); + ASSERT_NE(result, DistributedObject::OBJECT_SUCCESS); +} + /** * @tc.name: Clear001 * @tc.desc: Clear test. @@ -164,9 +362,15 @@ HWTEST_F(ObjectManagerTest, DeleteNotifierNoLock001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, Clear001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); - auto result = manager->Clear(); - ASSERT_EQ(result, OHOS::DistributedObject::OBJECT_STORE_NOT_FOUND); + ObjectUserMetaData userMeta; + MetaDataManager::GetInstance().SaveMeta(ObjectUserMetaData::GetKey(), userMeta, true); + auto &manager = ObjectStoreManager::GetInstance(); + std::string dataDir = "/data/app/el2/100/database"; + manager.SetData(dataDir, userId_); + auto result = manager.Clear(); + ASSERT_EQ(result, OHOS::DistributedObject::OBJECT_SUCCESS); + auto size = manager.callbacks_.Size(); + ASSERT_EQ(size, 0); } /** @@ -178,14 +382,17 @@ HWTEST_F(ObjectManagerTest, Clear001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, registerAndUnregisterRemoteCallback001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); - sptr callback; - manager->RegisterRemoteCallback(bundleName_, sessionId_, pid_, tokenId_, callback); - ObjectStoreManager::CallbackInfo callbackInfo = manager->callbacks_.Find(tokenId_).second; + auto &manager = ObjectStoreManager::GetInstance(); + std::function> &, bool)> cb = + [](const std::map> &, bool) {}; + sptr objectRemoteResumeCallback = new (std::nothrow) ObjectChangeCallback(cb); + ASSERT_NE(objectRemoteResumeCallback, nullptr); + manager.RegisterRemoteCallback(bundleName_, sessionId_, pid_, tokenId_, objectRemoteResumeCallback->AsObject()); + ObjectStoreManager::CallbackInfo callbackInfo = manager.callbacks_.Find(tokenId_).second; std::string prefix = bundleName_ + sessionId_; ASSERT_NE(callbackInfo.observers_.find(prefix), callbackInfo.observers_.end()); - manager->UnregisterRemoteCallback(bundleName_, pid_, tokenId_, sessionId_); - callbackInfo = manager->callbacks_.Find(tokenId_).second; + manager.UnregisterRemoteCallback(bundleName_, pid_, tokenId_, sessionId_); + callbackInfo = manager.callbacks_.Find(tokenId_).second; ASSERT_EQ(callbackInfo.observers_.find(prefix), callbackInfo.observers_.end()); } @@ -198,14 +405,15 @@ HWTEST_F(ObjectManagerTest, registerAndUnregisterRemoteCallback001, TestSize.Lev */ HWTEST_F(ObjectManagerTest, registerAndUnregisterRemoteCallback002, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); sptr callback; uint32_t tokenId = 101; - manager->RegisterRemoteCallback("", sessionId_, pid_, tokenId, callback); - manager->RegisterRemoteCallback(bundleName_, "", pid_, tokenId, callback); - manager->RegisterRemoteCallback("", "", pid_, tokenId, callback); - ASSERT_EQ(manager->callbacks_.Find(tokenId).first, false); - manager->UnregisterRemoteCallback("", pid_, tokenId, sessionId_); + manager.RegisterRemoteCallback("", sessionId_, pid_, tokenId, callback); + manager.RegisterRemoteCallback(bundleName_, "", pid_, tokenId, callback); + manager.RegisterRemoteCallback("", "", pid_, tokenId, callback); + manager.RegisterRemoteCallback(bundleName_, sessionId_, pid_, tokenId, nullptr); + ASSERT_EQ(manager.callbacks_.Find(tokenId).first, false); + manager.UnregisterRemoteCallback("", pid_, tokenId, sessionId_); } /** @@ -217,7 +425,7 @@ HWTEST_F(ObjectManagerTest, registerAndUnregisterRemoteCallback002, TestSize.Lev */ HWTEST_F(ObjectManagerTest, NotifyDataChanged001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::string bundleName1_ = "com.examples.ophm.notepad"; std::string objectKey = bundleName1_ + sessionId_; std::map>> data; @@ -226,13 +434,13 @@ HWTEST_F(ObjectManagerTest, NotifyDataChanged001, TestSize.Level0) data1_.push_back(RestoreStatus::DATA_READY); data1_.push_back(RestoreStatus::ASSETS_READY); data1_.push_back(RestoreStatus::ALL_READY); - data1 = {{ "objectKey", data1_ }}; - data = {{ objectKey, data1 }}; + data1 = { { "objectKey", data1_ } }; + data = { { objectKey, data1 } }; std::shared_ptr executors = std::make_shared(5, 3); // executor pool - manager->SetThreadPool(executors); - ASSERT_EQ(manager->restoreStatus_.Find(objectKey).first, false); - manager->NotifyDataChanged(data, {}); - ASSERT_EQ(manager->restoreStatus_.Find(objectKey).second, RestoreStatus::DATA_READY); + manager.SetThreadPool(executors); + ASSERT_EQ(manager.restoreStatus_.Find(objectKey).first, false); + manager.NotifyDataChanged(data, {}); + ASSERT_EQ(manager.restoreStatus_.Find(objectKey).second, RestoreStatus::DATA_READY); } /** @@ -244,16 +452,16 @@ HWTEST_F(ObjectManagerTest, NotifyDataChanged001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, NotifyAssetsReady001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::string objectKey = bundleName_ + sessionId_; std::string srcNetworkId = "1"; - ASSERT_EQ(manager->restoreStatus_.Find(objectKey).first, false); - manager->NotifyAssetsReady(objectKey, srcNetworkId); - ASSERT_EQ(manager->restoreStatus_.Find(objectKey).second, RestoreStatus::ASSETS_READY); - manager->restoreStatus_.Clear(); - manager->restoreStatus_.Insert(objectKey, RestoreStatus::DATA_READY); - manager->NotifyAssetsReady(objectKey, srcNetworkId); - ASSERT_EQ(manager->restoreStatus_.Find(objectKey).second, RestoreStatus::ALL_READY); + ASSERT_EQ(manager.restoreStatus_.Find(objectKey).first, false); + manager.NotifyAssetsReady(objectKey, srcNetworkId); + ASSERT_EQ(manager.restoreStatus_.Find(objectKey).second, RestoreStatus::ASSETS_READY); + manager.restoreStatus_.Clear(); + manager.restoreStatus_.Insert(objectKey, RestoreStatus::DATA_READY); + manager.NotifyAssetsReady(objectKey, srcNetworkId); + ASSERT_EQ(manager.restoreStatus_.Find(objectKey).second, RestoreStatus::ALL_READY); } /** @@ -263,36 +471,36 @@ HWTEST_F(ObjectManagerTest, NotifyAssetsReady001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, NotifyAssetsReady002, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); - std::string objectKey="com.example.myapplicaiton123456"; + auto &manager = ObjectStoreManager::GetInstance(); + std::string objectKey = "com.example.myapplicaiton123456"; std::string srcNetworkId = "654321"; - manager->restoreStatus_.Clear(); - manager->NotifyAssetsStart(objectKey, srcNetworkId); - auto [has0, value0] = manager->restoreStatus_.Find(objectKey); + manager.restoreStatus_.Clear(); + manager.NotifyAssetsStart(objectKey, srcNetworkId); + auto [has0, value0] = manager.restoreStatus_.Find(objectKey); EXPECT_TRUE(has0); EXPECT_EQ(value0, RestoreStatus::NONE); - manager->restoreStatus_.Clear(); - manager->NotifyAssetsReady(objectKey, srcNetworkId); - auto [has1, value1] = manager->restoreStatus_.Find(objectKey); + manager.restoreStatus_.Clear(); + manager.NotifyAssetsReady(objectKey, srcNetworkId); + auto [has1, value1] = manager.restoreStatus_.Find(objectKey); EXPECT_TRUE(has1); EXPECT_EQ(value1, RestoreStatus::ASSETS_READY); - manager->restoreStatus_.Clear(); - manager->restoreStatus_.Insert(objectKey, RestoreStatus::DATA_NOTIFIED); - manager->NotifyAssetsReady(objectKey, srcNetworkId); - auto [has2, value2] = manager->restoreStatus_.Find(objectKey); + manager.restoreStatus_.Clear(); + manager.restoreStatus_.Insert(objectKey, RestoreStatus::DATA_NOTIFIED); + manager.NotifyAssetsReady(objectKey, srcNetworkId); + auto [has2, value2] = manager.restoreStatus_.Find(objectKey); EXPECT_TRUE(has2); EXPECT_EQ(value2, RestoreStatus::ALL_READY); - manager->restoreStatus_.Clear(); - manager->restoreStatus_.Insert(objectKey, RestoreStatus::DATA_READY); - manager->NotifyAssetsReady(objectKey, srcNetworkId); - auto [has3, value3] = manager->restoreStatus_.Find(objectKey); + manager.restoreStatus_.Clear(); + manager.restoreStatus_.Insert(objectKey, RestoreStatus::DATA_READY); + manager.NotifyAssetsReady(objectKey, srcNetworkId); + auto [has3, value3] = manager.restoreStatus_.Find(objectKey); EXPECT_TRUE(has3); EXPECT_EQ(value3, RestoreStatus::ALL_READY); - manager->restoreStatus_.Clear(); + manager.restoreStatus_.Clear(); } /** @@ -304,18 +512,18 @@ HWTEST_F(ObjectManagerTest, NotifyAssetsReady002, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, NotifyChange001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::map> data; std::map> data1; std::vector data1_; data1_.push_back(RestoreStatus::DATA_READY); data_.push_back(RestoreStatus::ALL_READY); - data = {{ "test_cloud", data_ }}; - data1 = {{ "p_###SAVEINFO###001", data1_ }}; - manager->NotifyChange(data1); - EXPECT_FALSE(manager->restoreStatus_.Find("p_###SAVEINFO###001").first); - manager->NotifyChange(data); - EXPECT_FALSE(manager->restoreStatus_.Find("test_cloud").first); + data = { { "test_cloud", data_ } }; + data1 = { { "p_###SAVEINFO###001", data1_ } }; + manager.NotifyChange(data1); + EXPECT_FALSE(manager.restoreStatus_.Find("p_###SAVEINFO###001").first); + manager.NotifyChange(data); + EXPECT_FALSE(manager.restoreStatus_.Find("test_cloud").first); } /** @@ -325,11 +533,11 @@ HWTEST_F(ObjectManagerTest, NotifyChange001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, NotifyChange002, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::shared_ptr executor = std::make_shared(1, 0); - manager->SetThreadPool(executor); + manager.SetThreadPool(executor); std::map> data{}; - std::vector value{0}; + std::vector value{ 0 }; std::string bundleName = "com.example.myapplication"; std::string sessionId = "123456"; std::string source = "source"; @@ -349,13 +557,14 @@ HWTEST_F(ObjectManagerTest, NotifyChange002, TestSize.Level0) data.insert_or_assign(assetPrefix + ObjectStore::MODIFY_TIME_SUFFIX, value); data.insert_or_assign(assetPrefix + ObjectStore::SIZE_SUFFIX, value); data.insert_or_assign("testkey", value); - manager->NotifyChange(data); - EXPECT_TRUE(manager->restoreStatus_.Contains(bundleName+sessionId)); - auto [has, taskId] = manager->objectTimer_.Find(bundleName+sessionId); + EXPECT_CALL(*devMgrAdapterMock, IsSameAccount(_)).WillOnce(Return(true)); + manager.NotifyChange(data); + EXPECT_TRUE(manager.restoreStatus_.Contains(bundleName + sessionId)); + auto [has, taskId] = manager.objectTimer_.Find(bundleName + sessionId); EXPECT_TRUE(has); - manager->restoreStatus_.Clear(); - manager->executors_->Remove(taskId); - manager->objectTimer_.Clear(); + manager.restoreStatus_.Clear(); + manager.executors_->Remove(taskId); + manager.objectTimer_.Clear(); } /** @@ -365,30 +574,30 @@ HWTEST_F(ObjectManagerTest, NotifyChange002, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, ComputeStatus001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::shared_ptr executor = std::make_shared(1, 0); - manager->SetThreadPool(executor); - std::string objectKey="com.example.myapplicaiton123456"; + manager.SetThreadPool(executor); + std::string objectKey = "com.example.myapplicaiton123456"; std::map>> data{}; - manager->restoreStatus_.Clear(); - manager->ComputeStatus(objectKey, {}, data); - auto [has0, value0] = manager->restoreStatus_.Find(objectKey); + manager.restoreStatus_.Clear(); + manager.ComputeStatus(objectKey, {}, data); + auto [has0, value0] = manager.restoreStatus_.Find(objectKey); EXPECT_TRUE(has0); EXPECT_EQ(value0, RestoreStatus::DATA_READY); - auto [has1, taskId1] = manager->objectTimer_.Find(objectKey); + auto [has1, taskId1] = manager.objectTimer_.Find(objectKey); EXPECT_TRUE(has1); - manager->executors_->Remove(taskId1); - manager->objectTimer_.Clear(); - manager->restoreStatus_.Clear(); + manager.executors_->Remove(taskId1); + manager.objectTimer_.Clear(); + manager.restoreStatus_.Clear(); - manager->restoreStatus_.Insert(objectKey, RestoreStatus::ASSETS_READY); - manager->ComputeStatus(objectKey, {}, data); - auto [has2, value2] = manager->restoreStatus_.Find(objectKey); + manager.restoreStatus_.Insert(objectKey, RestoreStatus::ASSETS_READY); + manager.ComputeStatus(objectKey, {}, data); + auto [has2, value2] = manager.restoreStatus_.Find(objectKey); EXPECT_TRUE(has2); EXPECT_EQ(value2, RestoreStatus::ALL_READY); - auto [has3, taskId3] = manager->objectTimer_.Find(objectKey); + auto [has3, taskId3] = manager.objectTimer_.Find(objectKey); EXPECT_FALSE(has3); - manager->restoreStatus_.Clear(); + manager.restoreStatus_.Clear(); } /** @@ -400,18 +609,20 @@ HWTEST_F(ObjectManagerTest, ComputeStatus001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, Open001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); - manager->kvStoreDelegateManager_ = nullptr; - auto result = manager->Open(); + auto &manager = ObjectStoreManager::GetInstance(); + manager.kvStoreDelegateManager_ = nullptr; + auto result = manager.Open(); ASSERT_EQ(result, DistributedObject::OBJECT_INNER_ERROR); std::string dataDir = "/data/app/el2/100/database"; - manager->SetData(dataDir, userId_); - manager->delegate_ = nullptr; - result = manager->Open(); + manager.SetData(dataDir, userId_); + manager.delegate_ = nullptr; + result = manager.Open(); ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); - manager->delegate_ = manager->OpenObjectKvStore(); - result = manager->Open(); + manager.delegate_ = manager.OpenObjectKvStore(); + result = manager.Open(); ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); + manager.ForceClose(); + ASSERT_EQ(manager.delegate_, nullptr); } /** @@ -423,13 +634,13 @@ HWTEST_F(ObjectManagerTest, Open001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, OnAssetChanged001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::shared_ptr snapshot = std::make_shared(); auto snapshotKey = appId_ + "_" + sessionId_; - auto result = manager->OnAssetChanged(tokenId_, appId_, sessionId_, deviceId_, assetValue_); + auto result = manager.OnAssetChanged(tokenId_, appId_, sessionId_, deviceId_, assetValue_); ASSERT_EQ(result, DistributedObject::OBJECT_INNER_ERROR); - manager->snapshots_.Insert(snapshotKey, snapshot); - result = manager->OnAssetChanged(tokenId_, appId_, sessionId_, deviceId_, assetValue_); + manager.snapshots_.Insert(snapshotKey, snapshot); + result = manager.OnAssetChanged(tokenId_, appId_, sessionId_, deviceId_, assetValue_); ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); } @@ -442,34 +653,17 @@ HWTEST_F(ObjectManagerTest, OnAssetChanged001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, DeleteSnapshot001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::shared_ptr snapshot = std::make_shared(); auto snapshotKey = bundleName_ + "_" + sessionId_; - auto snapshots = manager->snapshots_.Find(snapshotKey).second; + auto snapshots = manager.snapshots_.Find(snapshotKey).second; ASSERT_EQ(snapshots, nullptr); - manager->DeleteSnapshot(bundleName_, sessionId_); + manager.DeleteSnapshot(bundleName_, sessionId_); - manager->snapshots_.Insert(snapshotKey, snapshot); - snapshots = manager->snapshots_.Find(snapshotKey).second; + manager.snapshots_.Insert(snapshotKey, snapshot); + snapshots = manager.snapshots_.Find(snapshotKey).second; ASSERT_NE(snapshots, nullptr); - manager->DeleteSnapshot(bundleName_, sessionId_); -} - -/** -* @tc.name: OpenObjectKvStore001 -* @tc.desc: OpenObjectKvStore test. -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin -*/ -HWTEST_F(ObjectManagerTest, OpenObjectKvStore001, TestSize.Level0) -{ - auto manager = ObjectStoreManager::GetInstance(); - manager->objectDataListener_ = nullptr; - ASSERT_EQ(manager->objectDataListener_, nullptr); - manager->OpenObjectKvStore(); - ASSERT_NE(manager->objectDataListener_, nullptr); - manager->OpenObjectKvStore(); + manager.DeleteSnapshot(bundleName_, sessionId_); } /** @@ -481,19 +675,19 @@ HWTEST_F(ObjectManagerTest, OpenObjectKvStore001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, FlushClosedStore001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); - manager->isSyncing_ = true; - manager->syncCount_ = 10; // test syncCount_ - manager->delegate_ = nullptr; - manager->FlushClosedStore(); - manager->isSyncing_ = false; - manager->FlushClosedStore(); - manager->syncCount_ = 0; // test syncCount_ - manager->FlushClosedStore(); - manager->delegate_ = manager->OpenObjectKvStore(); - ASSERT_NE(manager->delegate_, nullptr); - manager->FlushClosedStore(); - ASSERT_EQ(manager->delegate_, nullptr); + auto &manager = ObjectStoreManager::GetInstance(); + manager.isSyncing_ = true; + manager.syncCount_ = 10; // test syncCount_ + manager.delegate_ = nullptr; + manager.FlushClosedStore(); + manager.isSyncing_ = false; + manager.FlushClosedStore(); + manager.syncCount_ = 0; // test syncCount_ + manager.FlushClosedStore(); + manager.delegate_ = manager.OpenObjectKvStore(); + ASSERT_NE(manager.delegate_, nullptr); + manager.FlushClosedStore(); + ASSERT_EQ(manager.delegate_, nullptr); } /** @@ -505,40 +699,13 @@ HWTEST_F(ObjectManagerTest, FlushClosedStore001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, Close001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); - manager->syncCount_ = 1; // test syncCount_ - manager->Close(); - ASSERT_EQ(manager->syncCount_, 1); // 1 is for testing - manager->delegate_ = manager->OpenObjectKvStore(); - manager->Close(); - ASSERT_EQ(manager->syncCount_, 0); // 0 is for testing -} - -/** -* @tc.name: SyncOnStore001 -* @tc.desc: SyncOnStore test. -* @tc.type: FUNC -* @tc.require: -* @tc.author: wangbin -*/ -HWTEST_F(ObjectManagerTest, SyncOnStore001, TestSize.Level0) -{ - auto manager = ObjectStoreManager::GetInstance(); - manager->delegate_ = manager->OpenObjectKvStore(); - std::function &results)> func; - func = [](const std::map &results) { - return results; - }; - std::string prefix = "ObjectManagerTest"; - std::vector deviceList; - // not local device & syncDevices empty - deviceList.push_back("local1"); - auto result = manager->SyncOnStore(prefix, deviceList, func); - ASSERT_NE(result, OBJECT_SUCCESS); - // local device - deviceList.push_back("local"); - result = manager->SyncOnStore(prefix, deviceList, func); - ASSERT_EQ(result, OBJECT_SUCCESS); + auto &manager = ObjectStoreManager::GetInstance(); + manager.syncCount_ = 1; // test syncCount_ + manager.Close(); + ASSERT_EQ(manager.syncCount_, 1); // 1 is for testing + manager.delegate_ = manager.OpenObjectKvStore(); + manager.Close(); + ASSERT_EQ(manager.syncCount_, 0); // 0 is for testing } /** @@ -550,15 +717,15 @@ HWTEST_F(ObjectManagerTest, SyncOnStore001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, RetrieveFromStore001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); DistributedDB::KvStoreNbDelegateMock mockDelegate; - manager->delegate_ = &mockDelegate; + manager.delegate_ = &mockDelegate; std::vector id; - id.push_back(1); // for testing - id.push_back(2); // for testing + id.push_back(1); // for testing + id.push_back(2); // for testing std::map> results; - results = {{ "test_cloud", id }}; - auto result = manager->RetrieveFromStore(appId_, sessionId_, results); + results = { { "test_cloud", id } }; + auto result = manager.RetrieveFromStore(appId_, sessionId_, results); ASSERT_EQ(result, OBJECT_SUCCESS); } @@ -571,28 +738,26 @@ HWTEST_F(ObjectManagerTest, RetrieveFromStore001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, SyncCompleted001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); auto syncManager = SequenceSyncManager::GetInstance(); std::map results; - results = {{ "test_cloud", DistributedDB::DBStatus::OK }}; + results = { { "test_cloud", DistributedDB::DBStatus::OK } }; std::function &results)> func; - func = [](const std::map &results) { - return results; - }; - manager->userId_ = "99"; + func = [](const std::map &results) { return results; }; + manager.userId_ = "99"; std::vector userId; userId.push_back(99); userId.push_back(100); - manager->SyncCompleted(results, sequenceId_); - syncManager->userIdSeqIdRelations_ = {{ "test_cloud", userId }}; - manager->SyncCompleted(results, sequenceId_); + manager.SyncCompleted(results, sequenceId_); + syncManager->userIdSeqIdRelations_ = { { "test_cloud", userId } }; + manager.SyncCompleted(results, sequenceId_); userId.clear(); syncManager->seqIdCallbackRelations_.emplace(sequenceId_, func); - manager->SyncCompleted(results, sequenceId_); + manager.SyncCompleted(results, sequenceId_); userId.push_back(99); userId.push_back(100); - manager->SyncCompleted(results, sequenceId_); - EXPECT_FALSE(manager->isSyncing_); + manager.SyncCompleted(results, sequenceId_); + EXPECT_FALSE(manager.isSyncing_); } /** @@ -604,12 +769,12 @@ HWTEST_F(ObjectManagerTest, SyncCompleted001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, SplitEntryKey001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::string key1 = ""; std::string key2 = "ObjectManagerTest"; - auto result = manager->SplitEntryKey(key1); + auto result = manager.SplitEntryKey(key1); ASSERT_EQ(result.empty(), true); - result = manager->SplitEntryKey(key2); + result = manager.SplitEntryKey(key2); ASSERT_EQ(result.empty(), true); } @@ -620,9 +785,9 @@ HWTEST_F(ObjectManagerTest, SplitEntryKey001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, SplitEntryKey002, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::string key1 = "com.example.myapplication_sessionId_source_target_1234567890_p_propertyName"; - auto res = manager->SplitEntryKey(key1); + auto res = manager.SplitEntryKey(key1); EXPECT_EQ(res[0], "com.example.myapplication"); EXPECT_EQ(res[1], "sessionId"); EXPECT_EQ(res[2], "source"); @@ -631,19 +796,19 @@ HWTEST_F(ObjectManagerTest, SplitEntryKey002, TestSize.Level0) EXPECT_EQ(res[5], "p_propertyName"); std::string key2 = "com.example.myapplication_sessionId_source_target_000_p_propertyName"; - res = manager->SplitEntryKey(key2); + res = manager.SplitEntryKey(key2); EXPECT_TRUE(res.empty()); std::string key3 = "com.example.myapplicationsessionIdsourcetarget_1234567890_p_propertyName"; - res = manager->SplitEntryKey(key3); + res = manager.SplitEntryKey(key3); EXPECT_TRUE(res.empty()); std::string key4 = "com.example.myapplicationsessionIdsource_target_1234567890_p_propertyName"; - res = manager->SplitEntryKey(key4); + res = manager.SplitEntryKey(key4); EXPECT_TRUE(res.empty()); std::string key5 = "com.example.myapplicationsessionId_source_target_1234567890_p_propertyName"; - res = manager->SplitEntryKey(key5); + res = manager.SplitEntryKey(key5); EXPECT_TRUE(res.empty()); } @@ -656,18 +821,18 @@ HWTEST_F(ObjectManagerTest, SplitEntryKey002, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, ProcessOldEntry001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); - manager->delegate_ = manager->OpenObjectKvStore(); + auto &manager = ObjectStoreManager::GetInstance(); + manager.delegate_ = manager.OpenObjectKvStore(); std::vector entries; - auto status = manager->delegate_->GetEntries(std::vector(appId_.begin(), appId_.end()), entries); + auto status = manager.delegate_->GetEntries(std::vector(appId_.begin(), appId_.end()), entries); ASSERT_EQ(status, DistributedDB::DBStatus::NOT_FOUND); - manager->ProcessOldEntry(appId_); + manager.ProcessOldEntry(appId_); DistributedDB::KvStoreNbDelegateMock mockDelegate; - manager->delegate_ = &mockDelegate; - status = manager->delegate_->GetEntries(std::vector(appId_.begin(), appId_.end()), entries); + manager.delegate_ = &mockDelegate; + status = manager.delegate_->GetEntries(std::vector(appId_.begin(), appId_.end()), entries); ASSERT_EQ(status, DistributedDB::DBStatus::OK); - manager->ProcessOldEntry(appId_); + manager.ProcessOldEntry(appId_); } /** @@ -679,13 +844,13 @@ HWTEST_F(ObjectManagerTest, ProcessOldEntry001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, ProcessSyncCallback001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::map results; - manager->ProcessSyncCallback(results, appId_, sessionId_, deviceId_); - results.insert({"local", 1}); // for testing + manager.ProcessSyncCallback(results, appId_, sessionId_, deviceId_); + results.insert({ "local", 1 }); // for testing ASSERT_EQ(results.empty(), false); ASSERT_NE(results.find("local"), results.end()); - manager->ProcessSyncCallback(results, appId_, sessionId_, deviceId_); + manager.ProcessSyncCallback(results, appId_, sessionId_, deviceId_); } /** @@ -696,23 +861,23 @@ HWTEST_F(ObjectManagerTest, ProcessSyncCallback001, TestSize.Level0) HWTEST_F(ObjectManagerTest, ProcessSyncCallback002, TestSize.Level0) { std::string dataDir = "/data/app/el2/100/database"; - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::map results; - - results.insert({"remote", 1}); // for testing + + results.insert({ "remote", 1 }); // for testing ASSERT_EQ(results.empty(), false); ASSERT_EQ(results.find("local"), results.end()); - manager->kvStoreDelegateManager_ = nullptr; + manager.kvStoreDelegateManager_ = nullptr; // open store failed -> success - manager->ProcessSyncCallback(results, appId_, sessionId_, deviceId_); + manager.ProcessSyncCallback(results, appId_, sessionId_, deviceId_); // open store success -> success - manager->SetData(dataDir, userId_); - ASSERT_NE(manager->kvStoreDelegateManager_, nullptr); - manager->delegate_ = manager->OpenObjectKvStore(); - ASSERT_NE(manager->delegate_, nullptr); - manager->ProcessSyncCallback(results, appId_, sessionId_, deviceId_); + manager.SetData(dataDir, userId_); + ASSERT_NE(manager.kvStoreDelegateManager_, nullptr); + manager.delegate_ = manager.OpenObjectKvStore(); + ASSERT_NE(manager.delegate_, nullptr); + manager.ProcessSyncCallback(results, appId_, sessionId_, deviceId_); } /** @@ -724,32 +889,32 @@ HWTEST_F(ObjectManagerTest, ProcessSyncCallback002, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, IsAssetComplete001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::map> results; std::vector completes; completes.push_back(1); // for testing completes.push_back(2); // for testing std::string assetPrefix = "IsAssetComplete_test"; - results.insert({assetPrefix, completes}); - auto result = manager->IsAssetComplete(results, assetPrefix); + results.insert({ assetPrefix, completes }); + auto result = manager.IsAssetComplete(results, assetPrefix); ASSERT_EQ(result, false); - results.insert({assetPrefix + ObjectStore::NAME_SUFFIX, completes}); - result = manager->IsAssetComplete(results, assetPrefix); + results.insert({ assetPrefix + ObjectStore::NAME_SUFFIX, completes }); + result = manager.IsAssetComplete(results, assetPrefix); ASSERT_EQ(result, false); - results.insert({assetPrefix + ObjectStore::URI_SUFFIX, completes}); - result = manager->IsAssetComplete(results, assetPrefix); + results.insert({ assetPrefix + ObjectStore::URI_SUFFIX, completes }); + result = manager.IsAssetComplete(results, assetPrefix); ASSERT_EQ(result, false); - results.insert({assetPrefix + ObjectStore::PATH_SUFFIX, completes}); - result = manager->IsAssetComplete(results, assetPrefix); + results.insert({ assetPrefix + ObjectStore::PATH_SUFFIX, completes }); + result = manager.IsAssetComplete(results, assetPrefix); ASSERT_EQ(result, false); - results.insert({assetPrefix + ObjectStore::CREATE_TIME_SUFFIX, completes}); - result = manager->IsAssetComplete(results, assetPrefix); + results.insert({ assetPrefix + ObjectStore::CREATE_TIME_SUFFIX, completes }); + result = manager.IsAssetComplete(results, assetPrefix); ASSERT_EQ(result, false); - results.insert({assetPrefix + ObjectStore::MODIFY_TIME_SUFFIX, completes}); - result = manager->IsAssetComplete(results, assetPrefix); + results.insert({ assetPrefix + ObjectStore::MODIFY_TIME_SUFFIX, completes }); + result = manager.IsAssetComplete(results, assetPrefix); ASSERT_EQ(result, false); - results.insert({assetPrefix + ObjectStore::SIZE_SUFFIX, completes}); - result = manager->IsAssetComplete(results, assetPrefix); + results.insert({ assetPrefix + ObjectStore::SIZE_SUFFIX, completes }); + result = manager.IsAssetComplete(results, assetPrefix); ASSERT_EQ(result, true); } @@ -762,18 +927,18 @@ HWTEST_F(ObjectManagerTest, IsAssetComplete001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, GetAssetsFromDBRecords001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::map> results; std::vector completes; completes.push_back(1); // for testing completes.push_back(2); // for testing std::string assetPrefix = "IsAssetComplete_test"; - results.insert({assetPrefix, completes}); - results.insert({assetPrefix + ObjectStore::NAME_SUFFIX, completes}); - results.insert({assetPrefix + ObjectStore::URI_SUFFIX, completes}); - results.insert({assetPrefix + ObjectStore::MODIFY_TIME_SUFFIX, completes}); - results.insert({assetPrefix + ObjectStore::SIZE_SUFFIX, completes}); - auto result = manager->GetAssetsFromDBRecords(results); + results.insert({ assetPrefix, completes }); + results.insert({ assetPrefix + ObjectStore::NAME_SUFFIX, completes }); + results.insert({ assetPrefix + ObjectStore::URI_SUFFIX, completes }); + results.insert({ assetPrefix + ObjectStore::MODIFY_TIME_SUFFIX, completes }); + results.insert({ assetPrefix + ObjectStore::SIZE_SUFFIX, completes }); + auto result = manager.GetAssetsFromDBRecords(results); ASSERT_EQ(result.empty(), false); } @@ -784,14 +949,14 @@ HWTEST_F(ObjectManagerTest, GetAssetsFromDBRecords001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, GetAssetsFromDBRecords002, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::map> result; - std::vector value0{0}; + std::vector value0{ 0 }; std::string data0 = "[STRING]test"; value0.insert(value0.end(), data0.begin(), data0.end()); - std::vector value1{0}; + std::vector value1{ 0 }; std::string data1 = "(string)test"; value1.insert(value1.end(), data1.begin(), data1.end()); @@ -800,26 +965,26 @@ HWTEST_F(ObjectManagerTest, GetAssetsFromDBRecords002, TestSize.Level0) std::string assetPrefix0 = prefix + "_p_asset0"; std::string assetPrefix1 = prefix + "_p_asset1"; - result.insert({dataKey, value0}); - auto assets = manager->GetAssetsFromDBRecords(result); + result.insert({ dataKey, value0 }); + auto assets = manager.GetAssetsFromDBRecords(result); EXPECT_TRUE(assets.empty()); - + result.clear(); - result.insert({assetPrefix0 + ObjectStore::URI_SUFFIX, value0}); - assets = manager->GetAssetsFromDBRecords(result); + result.insert({ assetPrefix0 + ObjectStore::URI_SUFFIX, value0 }); + assets = manager.GetAssetsFromDBRecords(result); EXPECT_TRUE(assets.empty()); result.clear(); - result.insert({assetPrefix1 + ObjectStore::NAME_SUFFIX, value1}); - assets = manager->GetAssetsFromDBRecords(result); + result.insert({ assetPrefix1 + ObjectStore::NAME_SUFFIX, value1 }); + assets = manager.GetAssetsFromDBRecords(result); EXPECT_TRUE(assets.empty()); result.clear(); - result.insert({assetPrefix0 + ObjectStore::NAME_SUFFIX, value0}); - result.insert({assetPrefix0 + ObjectStore::URI_SUFFIX, value0}); - result.insert({assetPrefix0 + ObjectStore::MODIFY_TIME_SUFFIX, value0}); - result.insert({assetPrefix0 + ObjectStore::SIZE_SUFFIX, value0}); - assets = manager->GetAssetsFromDBRecords(result); + result.insert({ assetPrefix0 + ObjectStore::NAME_SUFFIX, value0 }); + result.insert({ assetPrefix0 + ObjectStore::URI_SUFFIX, value0 }); + result.insert({ assetPrefix0 + ObjectStore::MODIFY_TIME_SUFFIX, value0 }); + result.insert({ assetPrefix0 + ObjectStore::SIZE_SUFFIX, value0 }); + assets = manager.GetAssetsFromDBRecords(result); ASSERT_EQ(assets.size(), 1); EXPECT_EQ(assets[0].name, "test"); EXPECT_EQ(assets[0].uri, "test"); @@ -828,11 +993,11 @@ HWTEST_F(ObjectManagerTest, GetAssetsFromDBRecords002, TestSize.Level0) EXPECT_EQ(assets[0].hash, "test_test"); result.clear(); - result.insert({assetPrefix1 + ObjectStore::NAME_SUFFIX, value1}); - result.insert({assetPrefix1 + ObjectStore::URI_SUFFIX, value1}); - result.insert({assetPrefix1 + ObjectStore::MODIFY_TIME_SUFFIX, value1}); - result.insert({assetPrefix1 + ObjectStore::SIZE_SUFFIX, value1}); - assets = manager->GetAssetsFromDBRecords(result); + result.insert({ assetPrefix1 + ObjectStore::NAME_SUFFIX, value1 }); + result.insert({ assetPrefix1 + ObjectStore::URI_SUFFIX, value1 }); + result.insert({ assetPrefix1 + ObjectStore::MODIFY_TIME_SUFFIX, value1 }); + result.insert({ assetPrefix1 + ObjectStore::SIZE_SUFFIX, value1 }); + assets = manager.GetAssetsFromDBRecords(result); ASSERT_EQ(assets.size(), 1); EXPECT_EQ(assets[0].name, "(string)test"); EXPECT_EQ(assets[0].uri, "(string)test"); @@ -850,14 +1015,14 @@ HWTEST_F(ObjectManagerTest, GetAssetsFromDBRecords002, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, RegisterAssetsLister001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); - manager->objectAssetsSendListener_ = nullptr; - manager->objectAssetsRecvListener_ = nullptr; - auto result = manager->RegisterAssetsLister(); + auto &manager = ObjectStoreManager::GetInstance(); + manager.objectAssetsSendListener_ = nullptr; + manager.objectAssetsRecvListener_ = nullptr; + auto result = manager.RegisterAssetsLister(); ASSERT_EQ(result, true); - manager->objectAssetsSendListener_ = new ObjectAssetsSendListener(); - manager->objectAssetsRecvListener_ = new ObjectAssetsRecvListener();; - result = manager->RegisterAssetsLister(); + manager.objectAssetsSendListener_ = new ObjectAssetsSendListener(); + manager.objectAssetsRecvListener_ = new ObjectAssetsRecvListener(); + result = manager.RegisterAssetsLister(); ASSERT_EQ(result, true); } @@ -870,14 +1035,14 @@ HWTEST_F(ObjectManagerTest, RegisterAssetsLister001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, PushAssets001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::map> data; std::string assetPrefix = "PushAssets_test"; std::vector completes; completes.push_back(1); // for testing completes.push_back(2); // for testing - data.insert({assetPrefix, completes}); - auto result = manager->PushAssets(appId_, appId_, sessionId_, data, deviceId_); + data.insert({ assetPrefix, completes }); + auto result = manager.PushAssets(appId_, appId_, sessionId_, data, deviceId_); ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); } @@ -888,9 +1053,9 @@ HWTEST_F(ObjectManagerTest, PushAssets001, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, PushAssets002, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::map> data; - std::vector value{0}; + std::vector value{ 0 }; std::string data0 = "[STRING]test"; value.insert(value.end(), data0.begin(), data0.end()); @@ -900,19 +1065,19 @@ HWTEST_F(ObjectManagerTest, PushAssets002, TestSize.Level0) std::string fieldsPrefix = "p_"; std::string deviceIdKey = "__deviceId"; - data.insert({assetPrefix + ObjectStore::NAME_SUFFIX, value}); - data.insert({assetPrefix + ObjectStore::URI_SUFFIX, value}); - data.insert({assetPrefix + ObjectStore::MODIFY_TIME_SUFFIX, value}); - data.insert({assetPrefix + ObjectStore::SIZE_SUFFIX, value}); - data.insert({fieldsPrefix + deviceIdKey, value}); + data.insert({ assetPrefix + ObjectStore::NAME_SUFFIX, value }); + data.insert({ assetPrefix + ObjectStore::URI_SUFFIX, value }); + data.insert({ assetPrefix + ObjectStore::MODIFY_TIME_SUFFIX, value }); + data.insert({ assetPrefix + ObjectStore::SIZE_SUFFIX, value }); + data.insert({ fieldsPrefix + deviceIdKey, value }); - manager->objectAssetsSendListener_ = nullptr; - int32_t ret = manager->PushAssets(appId_, appId_, sessionId_, data, deviceId_); + manager.objectAssetsSendListener_ = nullptr; + int32_t ret = manager.PushAssets(appId_, appId_, sessionId_, data, deviceId_); EXPECT_NE(ret, DistributedObject::OBJECT_SUCCESS); - manager->objectAssetsSendListener_ = new ObjectAssetsSendListener(); - ASSERT_NE(manager->objectAssetsSendListener_, nullptr); - ret = manager->PushAssets(appId_, appId_, sessionId_, data, deviceId_); + manager.objectAssetsSendListener_ = new ObjectAssetsSendListener(); + ASSERT_NE(manager.objectAssetsSendListener_, nullptr); + ret = manager.PushAssets(appId_, appId_, sessionId_, data, deviceId_); EXPECT_NE(ret, DistributedObject::OBJECT_SUCCESS); } @@ -925,9 +1090,7 @@ HWTEST_F(ObjectManagerTest, AddNotifier001, TestSize.Level0) { auto syncManager = SequenceSyncManager::GetInstance(); std::function &results)> func; - func = [](const std::map &results) { - return results; - }; + func = [](const std::map &results) { return results; }; auto sequenceId_ = syncManager->AddNotifier(userId_, func); auto result = syncManager->DeleteNotifier(sequenceId_, userId_); ASSERT_EQ(result, SequenceSyncManager::SUCCESS_USER_HAS_FINISHED); @@ -942,9 +1105,7 @@ HWTEST_F(ObjectManagerTest, AddNotifier002, TestSize.Level0) { auto syncManager = SequenceSyncManager::GetInstance(); std::function &results)> func; - func = [](const std::map &results) { - return results; - }; + func = [](const std::map &results) { return results; }; auto sequenceId = syncManager->AddNotifier(userId_, func); ASSERT_NE(sequenceId, sequenceId_); auto result = syncManager->DeleteNotifier(sequenceId_, userId_); @@ -958,10 +1119,10 @@ HWTEST_F(ObjectManagerTest, AddNotifier002, TestSize.Level0) */ HWTEST_F(ObjectManagerTest, BindAsset001, TestSize.Level0) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::string bundleName = "BindAsset"; uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); - auto result = manager->BindAsset(tokenId, bundleName, sessionId_, assetValue_, assetBindInfo_); + auto result = manager.BindAsset(tokenId, bundleName, sessionId_, assetValue_, assetBindInfo_); ASSERT_EQ(result, DistributedObject::OBJECT_DBSTATUS_ERROR); } @@ -995,7 +1156,7 @@ HWTEST_F(ObjectManagerTest, OnFinished001, TestSize.Level1) */ HWTEST_F(ObjectManagerTest, GetObjectData001, TestSize.Level1) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::string bundleName = bundleName_; std::string sessionId = sessionId_; @@ -1009,9 +1170,9 @@ HWTEST_F(ObjectManagerTest, GetObjectData001, TestSize.Level1) // p_name not asset key std::string p_name = "p_namejpg"; std::string key = bundleName + "_" + sessionId + "_" + source + "_" + target + "_" + timestamp + "_" + p_name; - std::map> changedData = {{ key, data_ }}; + std::map> changedData = { { key, data_ } }; bool hasAsset = false; - auto ret = manager->GetObjectData(changedData, saveInfo, hasAsset); + auto ret = manager.GetObjectData(changedData, saveInfo, hasAsset); EXPECT_FALSE(ret.empty()); EXPECT_FALSE(hasAsset); } @@ -1023,7 +1184,7 @@ HWTEST_F(ObjectManagerTest, GetObjectData001, TestSize.Level1) */ HWTEST_F(ObjectManagerTest, GetObjectData002, TestSize.Level1) { - auto manager = ObjectStoreManager::GetInstance(); + auto &manager = ObjectStoreManager::GetInstance(); std::string bundleName = ""; std::string sessionId = ""; @@ -1045,9 +1206,9 @@ HWTEST_F(ObjectManagerTest, GetObjectData002, TestSize.Level1) timestamp = "1234567890"; std::string p_name = "p_name.jpg"; std::string key = bundleName + "_" + sessionId + "_" + source + "_" + target + "_" + timestamp + "_" + p_name; - std::map> changedData = {{ key, data_ }}; + std::map> changedData = { { key, data_ } }; bool hasAsset = false; - auto ret = manager->GetObjectData(changedData, saveInfo, hasAsset); + auto ret = manager.GetObjectData(changedData, saveInfo, hasAsset); EXPECT_FALSE(ret.empty()); EXPECT_EQ(saveInfo.bundleName, bundleName); EXPECT_TRUE(hasAsset); @@ -1058,11 +1219,259 @@ HWTEST_F(ObjectManagerTest, GetObjectData002, TestSize.Level1) // p_name not asset key p_name = "p_namejpg"; std::string key_1 = bundleName + "_" + sessionId + "_" + source + "_" + target + "_" + timestamp + "_" + p_name; - std::map> changedData_1 = {{ key_1, data_ }}; + std::map> changedData_1 = { { key_1, data_ } }; hasAsset = false; - ret = manager->GetObjectData(changedData_1, saveInfo, hasAsset); + ret = manager.GetObjectData(changedData_1, saveInfo, hasAsset); EXPECT_FALSE(ret.empty()); EXPECT_NE(saveInfo.bundleName, bundleName); EXPECT_FALSE(hasAsset); } + +/** +* @tc.name: InitUserMeta001 +* @tc.desc: test clear old user meta. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, InitUserMeta001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + auto status = manager.InitUserMeta(); + ASSERT_EQ(status, DistributedObject::OBJECT_SUCCESS); +} + +/** +* @tc.name: registerAndUnregisterProgressObserverCallback001 +* @tc.desc: test RegisterProgressObserverCallback and UnregisterProgressObserverCallback. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ObjectManagerTest, registerAndUnregisterProgressObserverCallback001, TestSize.Level0) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::function cb = [](int32_t progress) {}; + sptr objectRemoteResumeCallback = new (std::nothrow) ObjectProgressCallback(cb); + ASSERT_NE(objectRemoteResumeCallback, nullptr); + manager.RegisterProgressObserverCallback(bundleName_, sessionId_, pid_, tokenId_, + objectRemoteResumeCallback->AsObject()); + ObjectStoreManager::ProgressCallbackInfo progressCallbackInfo = manager.processCallbacks_.Find(tokenId_).second; + std::string objectKey = bundleName_ + sessionId_; + ASSERT_NE(progressCallbackInfo.observers_.find(objectKey), progressCallbackInfo.observers_.end()); + manager.UnregisterProgressObserverCallback(bundleName_, pid_, tokenId_, sessionId_); + progressCallbackInfo = manager.processCallbacks_.Find(tokenId_).second; + ASSERT_EQ(progressCallbackInfo.observers_.find(objectKey), progressCallbackInfo.observers_.end()); +} + +/** +* @tc.name: registerAndUnregisterProgressObserverCallback002 +* @tc.desc: abnormal use cases. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ObjectManagerTest, registerAndUnregisterProgressObserverCallback002, TestSize.Level0) +{ + auto &manager = ObjectStoreManager::GetInstance(); + sptr callback; + uint32_t tokenId = 101; + manager.RegisterProgressObserverCallback("", sessionId_, pid_, tokenId, callback); + manager.RegisterProgressObserverCallback(bundleName_, "", pid_, tokenId, callback); + manager.RegisterProgressObserverCallback("", "", pid_, tokenId, callback); + ObjectStoreManager::ProgressCallbackInfo progressCallbackInfo = manager.processCallbacks_.Find(tokenId_).second; + progressCallbackInfo.pid = pid_; + manager.RegisterProgressObserverCallback(bundleName_, sessionId_, pid_, tokenId_, callback); + ASSERT_EQ(manager.processCallbacks_.Find(tokenId).first, false); + manager.UnregisterProgressObserverCallback("", pid_, tokenId, sessionId_); + manager.UnregisterProgressObserverCallback("", pid_, tokenId, ""); + manager.UnregisterProgressObserverCallback(bundleName_, pid_, tokenId, ""); +} + +/** +* @tc.name: NotifyAssetsRecvProgress001 +* @tc.desc: NotifyAssetsRecvProgress test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(ObjectManagerTest, NotifyAssetsRecvProgress001, TestSize.Level0) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string objectKey = bundleName_ + sessionId_; + std::string errProgress = "errProgress"; + int32_t progress = 99; + ObjectStoreManager::ProgressCallbackInfo progressCallbackInfo = manager.processCallbacks_.Find(tokenId_).second; + manager.NotifyAssetsRecvProgress(objectKey, progress); + ASSERT_EQ(manager.assetsRecvProgress_.Find(objectKey).first, true); + manager.assetsRecvProgress_.Clear(); + manager.assetsRecvProgress_.Insert(objectKey, progress); + manager.NotifyAssetsRecvProgress(errProgress, progress); + progressCallbackInfo.observers_.clear(); +} + +/** +* @tc.name: OnRecvProgress001 +* @tc.desc: OnRecvProgress test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, OnRecvProgress001, TestSize.Level1) +{ + std::string srcNetworkId = "srcNetworkId"; + sptr assetObj = nullptr; + uint64_t totalBytes = 100; + uint64_t processBytes = 100; + ObjectAssetsRecvListener listener; + int32_t ret = listener.OnRecvProgress(srcNetworkId, assetObj, totalBytes, processBytes); + EXPECT_EQ(ret, DistributedObject::OBJECT_INNER_ERROR); + uint64_t totalBytes_01 = 0; + ret = listener.OnRecvProgress(srcNetworkId, assetObj, totalBytes_01, processBytes); + EXPECT_EQ(ret, DistributedObject::OBJECT_INNER_ERROR); + sptr assetObj_1 = new AssetObj(); + ret = listener.OnRecvProgress(srcNetworkId, assetObj_1, totalBytes_01, processBytes); + EXPECT_EQ(ret, DistributedObject::OBJECT_INNER_ERROR); + ret = listener.OnRecvProgress(srcNetworkId, assetObj_1, totalBytes, processBytes); + EXPECT_EQ(ret, DistributedObject::OBJECT_SUCCESS); +} + +/** +* @tc.name: OnFinished002 +* @tc.desc: OnFinished test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, OnFinished002, TestSize.Level1) +{ + std::string srcNetworkId = "srcNetworkId"; + ObjectAssetsRecvListener listener; + sptr assetObj_1 = new AssetObj(); + assetObj_1->dstBundleName_ = bundleName_; + assetObj_1->srcBundleName_ = bundleName_; + assetObj_1->dstNetworkId_ = "1"; + assetObj_1->sessionId_ = "123"; + int32_t result = 100; + auto ret = listener.OnFinished(srcNetworkId, assetObj_1, result); + int32_t result_1 = 0; + ret = listener.OnFinished(srcNetworkId, assetObj_1, result_1); + EXPECT_EQ(ret, DistributedObject::OBJECT_SUCCESS); +} + +/** +* @tc.name: Save001 +* @tc.desc: Save test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, Save001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string appId = "appId"; + std::string sessionId = "sessionId"; + ObjectRecord data; + std::string deviceId = "deviceId"; + auto ret = manager.Save(appId, sessionId, data, deviceId, nullptr); + EXPECT_EQ(ret, DistributedKv::INVALID_ARGUMENT); +} + +/** +* @tc.name: Save002 +* @tc.desc: Save test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, Save002, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string appId = "appId"; + std::string sessionId = "sessionId"; + ObjectRecord data; + std::string deviceId = ""; + std::function &)> cb = [](const std::map &) {}; + sptr objectSaveCallback = new (std::nothrow) ObjectSaveCallback(cb); + ASSERT_NE(objectSaveCallback, nullptr); + auto ret = manager.Save(appId, sessionId, data, deviceId, objectSaveCallback->AsObject()); + EXPECT_EQ(ret, DistributedKv::INVALID_ARGUMENT); +} + +/** +* @tc.name: RevokeSave001 +* @tc.desc: RevokeSave test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, RevokeSave001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string appId = "appId"; + std::string sessionId = "sessionId"; + auto ret = manager.RevokeSave(appId, sessionId, nullptr); + EXPECT_EQ(ret, DistributedKv::INVALID_ARGUMENT); +} + +/** +* @tc.name: RevokeSave002 +* @tc.desc: RevokeSave test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, RevokeSave002, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string appId = "appId"; + std::string sessionId = "sessionId"; + std::function cb = [](int32_t) {}; + sptr objectRevokeSaveCallback = new (std::nothrow) ObjectRevokeSaveCallback(cb); + ASSERT_NE(objectRevokeSaveCallback, nullptr); + auto ret = manager.RevokeSave(appId, sessionId, objectRevokeSaveCallback->AsObject()); + EXPECT_EQ(ret, DistributedObject::OBJECT_SUCCESS); +} + +/** +* @tc.name: Retrieve001 +* @tc.desc: Retrieve test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, Retrieve001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string bundleName = "bundleName"; + std::string sessionId = "sessionId"; + uint32_t tokenId = 0; + auto ret = manager.Retrieve(bundleName, sessionId, nullptr, tokenId); + EXPECT_EQ(ret, DistributedKv::INVALID_ARGUMENT); +} + +/** +* @tc.name: Retrieve002 +* @tc.desc: Retrieve test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, Retrieve002, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string bundleName = "bundleName"; + std::string sessionId = "sessionId"; + uint32_t tokenId = 0; + std::function> &, bool)> cb = + [](const std::map> &, bool) {}; + sptr objectRetrieveCallback = new (std::nothrow) ObjectRetrieveCallback(cb); + ASSERT_NE(objectRetrieveCallback, nullptr); + auto ret = manager.Retrieve(bundleName, sessionId, objectRetrieveCallback->AsObject(), tokenId); + EXPECT_EQ(ret, DistributedKv::KEY_NOT_FOUND); +} + +/** +* @tc.name: GetSnapShots001 +* @tc.desc: ObjectStoreManager get snapShots test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectManagerTest, GetSnapShots001, TestSize.Level1) +{ + auto &manager = ObjectStoreManager::GetInstance(); + std::string bundleName = "bundleA"; + std::string storeName = "storeA"; + + auto ptr1 = manager.GetSnapShots(bundleName, storeName); + ASSERT_NE(ptr1, nullptr); + EXPECT_TRUE(ptr1->empty()); + auto snapshot = std::make_shared(); + (*ptr1)["snap1"] = snapshot; + + auto ptr2 = manager.GetSnapShots(bundleName, storeName); + EXPECT_EQ(ptr1, ptr2); + EXPECT_EQ((*ptr2)["snap1"], snapshot); +} } // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/service/test/object_service_impl_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_service_impl_test.cpp index e67f493a..79bd608f 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_service_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_service_impl_test.cpp @@ -20,11 +20,14 @@ #include #include "accesstoken_kit.h" +#include "device_manager_adapter_mock.h" #include "ipc_skeleton.h" #include "token_setproc.h" using namespace testing::ext; using namespace OHOS::DistributedObject; +using namespace std; +using namespace testing; namespace OHOS::Test { class ObjectServiceImplTest : public testing::Test { public: @@ -45,11 +48,12 @@ protected: ObjectStore::AssetBindInfo assetBindInfo_; pid_t pid_ = 10; uint32_t tokenId_ = 100; + static inline std::shared_ptr devMgrAdapterMock = nullptr; }; void ObjectServiceImplTest::SetUp() { - uri_ = "file:://com.examples.hmos.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; + uri_ = "file:://com.examples.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; ObjectStore::Asset asset{ .id = "test_name", .name = uri_, @@ -73,9 +77,14 @@ void ObjectServiceImplTest::SetUp() .assetName = "asset1.jpg", }; assetBindInfo_ = AssetBindInfo; + devMgrAdapterMock = make_shared(); + BDeviceManagerAdapter::deviceManagerAdapter = devMgrAdapterMock; } -void ObjectServiceImplTest::TearDown() {} +void ObjectServiceImplTest::TearDown() +{ + devMgrAdapterMock = nullptr; +} /** * @tc.name: OnAssetChanged001 @@ -84,7 +93,7 @@ void ObjectServiceImplTest::TearDown() {} */ HWTEST_F(ObjectServiceImplTest, OnAssetChanged001, TestSize.Level1) { - std::string bundleName = "com.examples.hmos.notepad"; + std::string bundleName = "com.examples.notepad"; OHOS::Security::AccessToken::AccessTokenID tokenId = OHOS::Security::AccessToken::AccessTokenKit::GetHapTokenID(100, bundleName, 0); SetSelfTokenID(tokenId); @@ -103,7 +112,7 @@ HWTEST_F(ObjectServiceImplTest, OnAssetChanged001, TestSize.Level1) */ HWTEST_F(ObjectServiceImplTest, BindAssetStore001, TestSize.Level1) { - std::string bundleName = "com.examples.hmos.notepad"; + std::string bundleName = "com.examples.notepad"; OHOS::Security::AccessToken::AccessTokenID tokenId = OHOS::Security::AccessToken::AccessTokenKit::GetHapTokenID(100, bundleName, 0); SetSelfTokenID(tokenId); @@ -122,7 +131,7 @@ HWTEST_F(ObjectServiceImplTest, BindAssetStore001, TestSize.Level1) */ HWTEST_F(ObjectServiceImplTest, DeleteSnapshot001, TestSize.Level1) { - std::string bundleName = "com.examples.hmos.notepad"; + std::string bundleName = "com.examples.notepad"; OHOS::Security::AccessToken::AccessTokenID tokenId = OHOS::Security::AccessToken::AccessTokenKit::GetHapTokenID(100, bundleName, 0); SetSelfTokenID(tokenId); @@ -149,6 +158,47 @@ HWTEST_F(ObjectServiceImplTest, ResolveAutoLaunch001, TestSize.Level1) std::string identifier = "identifier"; std::shared_ptr objectServiceImpl = std::make_shared(); int32_t ret = objectServiceImpl->ResolveAutoLaunch(identifier, param); - EXPECT_EQ(ret, OBJECT_STORE_NOT_FOUND); + EXPECT_EQ(ret, OBJECT_SUCCESS); +} + +/** + * @tc.name: OnInitialize001 + * @tc.desc: OnInitialize test. + * @tc.type: FUNC + */ +HWTEST_F(ObjectServiceImplTest, OnInitialize001, TestSize.Level1) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + objectServiceImpl->executors_ = nullptr; + DeviceInfo devInfo = { .uuid = "123" }; + EXPECT_CALL(*devMgrAdapterMock, GetLocalDevice()) + .WillOnce(Return(devInfo)); + int32_t ret = objectServiceImpl->OnInitialize(); + EXPECT_EQ(ret, OBJECT_INNER_ERROR); +} + +/** + * @tc.name: RegisterProgressObserver001 + * @tc.desc: RegisterProgressObserver test. + * @tc.type: FUNC + */ +HWTEST_F(ObjectServiceImplTest, RegisterProgressObserver001, TestSize.Level1) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + sptr callback; + int32_t ret = objectServiceImpl->RegisterProgressObserver(bundleName_, sessionId_, callback); + EXPECT_EQ(ret, OBJECT_PERMISSION_DENIED); +} + +/** + * @tc.name: UnregisterProgressObserver001 + * @tc.desc: UnregisterProgressObserver test. + * @tc.type: FUNC + */ +HWTEST_F(ObjectServiceImplTest, UnregisterProgressObserver001, TestSize.Level1) +{ + std::shared_ptr objectServiceImpl = std::make_shared(); + int32_t ret = objectServiceImpl->UnregisterProgressObserver(bundleName_, sessionId_); + EXPECT_EQ(ret, OBJECT_PERMISSION_DENIED); } } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/object_service_stub_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_service_stub_test.cpp index 1cbb5e1a..274ef0f9 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_service_stub_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_service_stub_test.cpp @@ -99,6 +99,12 @@ HWTEST_F(ObjectServiceStubTest, ObjectServiceTest002, TestSize.Level1) result = objectServiceStub->ObjectStoreBindAssetOnRemote(request, reply); EXPECT_EQ(result, IPC_STUB_INVALID_DATA_ERR); + result = objectServiceStub->OnSubscribeProgress(request, reply); + EXPECT_EQ(result, IPC_STUB_INVALID_DATA_ERR); + + result = objectServiceStub->OnUnsubscribeProgress(request, reply); + EXPECT_EQ(result, IPC_STUB_INVALID_DATA_ERR); + result = objectServiceStub->OnDeleteSnapshot(request, reply); EXPECT_EQ(result, IPC_STUB_INVALID_DATA_ERR); diff --git a/datamgr_service/services/distributeddataservice/service/test/object_snapshot_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_snapshot_test.cpp index 37cee3e9..0826280f 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_snapshot_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_snapshot_test.cpp @@ -41,7 +41,7 @@ protected: void ObjectSnapshotTest::SetUp() { - uri_ = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; + uri_ = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset1.jpg"; Asset asset{ .name = "test_name", .uri = uri_, @@ -85,7 +85,7 @@ HWTEST_F(ObjectSnapshotTest, UploadTest001, TestSize.Level0) auto snapshot = std::make_shared(); Asset asset{ .name = "test_name", - .uri = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", + .uri = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", .modifyTime = "modifyTime1", .size = "size1", .hash = "modifyTime1_size1", @@ -124,7 +124,7 @@ HWTEST_F(ObjectSnapshotTest, DownloadTest001, TestSize.Level0) auto snapshot = std::make_shared(); Asset asset{ .name = "test_name", - .uri = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", + .uri = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", .modifyTime = "modifyTime1", .size = "size1", .hash = "modifyTime1_size1", @@ -163,7 +163,7 @@ HWTEST_F(ObjectSnapshotTest, GetAssetStatusTest001, TestSize.Level0) auto snapshot = std::make_shared(); Asset asset{ .name = "test_name", - .uri = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", + .uri = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", .modifyTime = "modifyTime1", .size = "size1", .hash = "modifyTime1_size1", @@ -202,7 +202,7 @@ HWTEST_F(ObjectSnapshotTest, UploadedTest001, TestSize.Level0) auto snapshot = std::make_shared(); Asset asset{ .name = "test_name", - .uri = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", + .uri = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", .modifyTime = "modifyTime1", .size = "size1", .hash = "modifyTime1_size1", @@ -241,7 +241,7 @@ HWTEST_F(ObjectSnapshotTest, DownloadedTest001, TestSize.Level0) auto snapshot = std::make_shared(); Asset asset{ .name = "test_name", - .uri = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", + .uri = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", .modifyTime = "modifyTime1", .size = "size1", .hash = "modifyTime1_size1", @@ -280,7 +280,7 @@ HWTEST_F(ObjectSnapshotTest, TransferredTest001, TestSize.Level0) auto snapshot = std::make_shared(); Asset asset{ .name = "test_name", - .uri = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", + .uri = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", .modifyTime = "modifyTime1", .size = "size1", .hash = "modifyTime1_size1", @@ -320,7 +320,7 @@ HWTEST_F(ObjectSnapshotTest, OnDataChangedTest001, TestSize.Level0) std::string deviceId = "object_snapshot_test_1"; Asset asset{ .name = "test_name", - .uri = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", + .uri = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", .modifyTime = "modifyTime1", .size = "size1", .hash = "modifyTime1_size1", @@ -360,7 +360,7 @@ HWTEST_F(ObjectSnapshotTest, BindAsset001, TestSize.Level0) auto snapshot = std::make_shared(); Asset asset{ .name = "test_name", - .uri = "file:://com.example.hmos.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", + .uri = "file:://com.example.notepad/data/storage/el2/distributedfiles/dir/asset2.jpg", .modifyTime = "modifyTime1", .size = "size1", .hash = "modifyTime1_size1", diff --git a/datamgr_service/services/distributeddataservice/service/test/ohos_test/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/ohos_test/BUILD.gn new file mode 100644 index 00000000..ed9f42f0 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/ohos_test/BUILD.gn @@ -0,0 +1,21 @@ +# 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/ohos.gni") + +ohos_copy("copy_ohos_test") { + subsystem_name = "distributeddatamgr" + part_name = "datamgr_service" + sources = [ "./ohos_test.xml" ] + outputs = [ "$root_out_dir/tests/unittest/datamgr_service/datamgr_service/resource/ohos_test.xml" ] +} diff --git a/datamgr_service/services/distributeddataservice/service/test/ohos_test/ohos_test.xml b/datamgr_service/services/distributeddataservice/service/test/ohos_test/ohos_test.xml new file mode 100644 index 00000000..8586520c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/ohos_test/ohos_test.xml @@ -0,0 +1,28 @@ + + + + + + + + + + \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/permit_delegate_mock_test.cpp b/datamgr_service/services/distributeddataservice/service/test/permit_delegate_mock_test.cpp index e312860b..79170873 100644 --- a/datamgr_service/services/distributeddataservice/service/test/permit_delegate_mock_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/permit_delegate_mock_test.cpp @@ -165,12 +165,13 @@ HWTEST_F(PermitDelegateMockTest, VerifyPermission001, testing::ext::TestSize.Lev ASSERT_TRUE(result); AppIDMetaData appMeta("permitdelegatemocktestId", "com.permitdelegatetest.app"); EXPECT_CALL(*metaDataMgrMock, LoadMeta(_, _, _)).WillOnce(DoAll(SetArgReferee<1>(appMeta), Return(true))); - CheckParam checkParam; - checkParam.appId = "permitdelegatemocktestId"; - checkParam.userId = "userid"; - checkParam.storeId = "storeid"; - checkParam.deviceId = "deviceid"; - checkParam.instanceId = 1; + CheckParam checkParam = { + .appId = "permitdelegatemocktestId", + .userId = "userid", + .storeId = "storeid", + .deviceId = "deviceid", + .instanceId = 1 + }; uint8_t flag = 1; EXPECT_CALL(*metaDataMgrMock, LoadMeta(_, _, false)).WillOnce(Return(false)); result = PermitDelegate::GetInstance().VerifyPermission(checkParam, flag); @@ -192,8 +193,8 @@ HWTEST_F(PermitDelegateMockTest, VerifyPermission002, testing::ext::TestSize.Lev auto ret = PermitDelegate::GetInstance().appId2BundleNameMap_.Find(key); ASSERT_TRUE(ret.second == value); CheckParam checkParam = { - .userId = "userid2", .appId = "permitdelegatemocktestId2", + .userId = "userid2", .storeId = "storeid2", .deviceId = "deviceid2", .instanceId = 0 diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_asset_loader_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_asset_loader_test.cpp index f8d56ca2..e261e4cc 100644 --- a/datamgr_service/services/distributeddataservice/service/test/rdb_asset_loader_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_asset_loader_test.cpp @@ -16,13 +16,15 @@ #include "rdb_asset_loader.h" -#include "gtest/gtest.h" #include "log_print.h" +#include "object_snapshot.h" #include "rdb_notifier_proxy.h" #include "rdb_watcher.h" #include "store/cursor.h" #include "store/general_value.h" #include "store/general_watcher.h" +#include "gtest/gtest.h" + using namespace OHOS; using namespace testing; using namespace testing::ext; @@ -88,7 +90,7 @@ HWTEST_F(RdbAssetLoaderTest, Download, TestSize.Level0) { BindAssets bindAssets; std::shared_ptr cloudAssetLoader = std::make_shared(); - DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, bindAssets); std::string tableName = "testTable"; std::string groupId = "testGroup"; Type prefix; @@ -109,7 +111,7 @@ HWTEST_F(RdbAssetLoaderTest, BatchDownload, TestSize.Level0) { BindAssets bindAssets; auto cloudAssetLoader = std::make_shared(); - DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, bindAssets); std::string tableName = "testTable"; Type prefix; std::map assets; @@ -133,7 +135,7 @@ HWTEST_F(RdbAssetLoaderTest, Convert001, TestSize.Level0) { BindAssets bindAssets; auto cloudAssetLoader = std::make_shared(); - DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, bindAssets); Type prefix; std::map assets; assets["asset1"].push_back(g_rdbAsset); @@ -156,7 +158,7 @@ HWTEST_F(RdbAssetLoaderTest, Convert002, TestSize.Level0) { BindAssets bindAssets; auto cloudAssetLoader = std::make_shared(); - DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, bindAssets); Value prefix; VBucket assets; std::vector assetsRecords; @@ -177,7 +179,7 @@ HWTEST_F(RdbAssetLoaderTest, RemoveLocalAssets, TestSize.Level0) { BindAssets bindAssets; std::shared_ptr cloudAssetLoader = std::make_shared(); - DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, bindAssets); std::vector assets; assets.push_back(g_rdbAsset); auto result = rdbAssetLoader.RemoveLocalAssets(assets); @@ -194,12 +196,12 @@ HWTEST_F(RdbAssetLoaderTest, RemoveLocalAssets, TestSize.Level0) HWTEST_F(RdbAssetLoaderTest, CancelDownloadTest, TestSize.Level0) { BindAssets bindAssets; - DistributedRdb::RdbAssetLoader rdbAssetLoader1(nullptr, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader1(nullptr, bindAssets); auto result = rdbAssetLoader1.CancelDownload(); EXPECT_EQ(result, DistributedDB::DBStatus::DB_ERROR); std::shared_ptr cloudAssetLoader = std::make_shared(); - DistributedRdb::RdbAssetLoader rdbAssetLoader2(cloudAssetLoader, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader2(cloudAssetLoader, bindAssets); result = rdbAssetLoader2.CancelDownload(); EXPECT_EQ(result, DistributedDB::DBStatus::OK); } @@ -213,10 +215,9 @@ HWTEST_F(RdbAssetLoaderTest, CancelDownloadTest, TestSize.Level0) */ HWTEST_F(RdbAssetLoaderTest, PostEvent001, TestSize.Level0) { - BindAssets bindAssets; - bindAssets.bindAssets = nullptr; + BindAssets bindAssets = nullptr; std::shared_ptr assetLoader = std::make_shared(); - DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); std::string tableName = "testTable"; std::string groupId = "testGroup"; Type prefix; @@ -235,29 +236,328 @@ HWTEST_F(RdbAssetLoaderTest, PostEvent001, TestSize.Level0) */ HWTEST_F(RdbAssetLoaderTest, PostEvent002, TestSize.Level0) { - DistributedData::Asset asset; - asset.name = ""; - asset.id = ""; - asset.path = ""; - asset.uri = ""; - asset.modifyTime = ""; - asset.createTime = ""; - asset.size = ""; - asset.hash = ""; - asset.status = DistributedData::Asset::STATUS_DELETE; - + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_DELETE, + }; DistributedData::Assets assets; assets.push_back(asset); - BindAssets bindAssets; - bindAssets.bindAssets = nullptr; + BindAssets bindAssets = nullptr; std::shared_ptr assetLoader = std::make_shared(); - DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, &bindAssets); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); std::set skipAssets; std::set deleteAssets; rdbAssetLoader.PostEvent(DistributedData::AssetEvent::DOWNLOAD, assets, skipAssets, deleteAssets); EXPECT_EQ(deleteAssets.size(), 1); } +/** +@tc.name: PostEvent003 +@tc.desc: RdbAssetLoader PostEvent003 test +@tc.type: FUNC +@tc.require: +@tc.author: SQL +*/ +HWTEST_F(RdbAssetLoaderTest, PostEvent003, TestSize.Level0) { + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_NORMAL, + }; + DistributedData::Assets assets; + assets.push_back(asset); + BindAssets bindAssets = nullptr; + std::shared_ptr assetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); + std::set skipAssets; + std::set deleteAssets; + rdbAssetLoader.PostEvent(DistributedData::AssetEvent::DOWNLOAD, assets, skipAssets, deleteAssets); + EXPECT_EQ(deleteAssets.size(), 0); + EXPECT_EQ(skipAssets.size(), 0); +} + +/** +@tc.name: PostEvent004 +@tc.desc: RdbAssetLoader PostEvent004 test,snapshots_ can find data with a value of null +@tc.type: FUNC +@tc.require: +@tc.author: SQL +*/ +HWTEST_F(RdbAssetLoaderTest, PostEvent004, TestSize.Level0) { + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "PostEvent004", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_NORMAL, + }; + DistributedData::Assets assets; + assets.push_back(asset); + BindAssets bindAssets = std::make_shared>>(); + bindAssets->insert({"PostEvent004", nullptr}); + std::shared_ptr assetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); + std::set skipAssets; + std::set deleteAssets; + rdbAssetLoader.PostEvent(DistributedData::AssetEvent::DOWNLOAD, assets, skipAssets, deleteAssets); + EXPECT_EQ(deleteAssets.size(), 0); + EXPECT_EQ(skipAssets.size(), 0); +} + +/** +@tc.name: PostEvent005 +@tc.desc: RdbAssetLoader PostEvent005 test,snapshots_ can find data and the value is not null +@tc.type: FUNC +@tc.require: +@tc.author: SQL +*/ +HWTEST_F(RdbAssetLoaderTest, PostEvent005, TestSize.Level0) { + class ObjectSnapshotMock : public DistributedObject::ObjectSnapshot { + public: + int32_t Download(Asset &asset) override { + hasDownload = true; + return 0; + } + bool hasDownload = false; + }; + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "PostEvent005", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_NORMAL, + }; + DistributedData::Assets assets; + assets.push_back(asset); + BindAssets bindAssets = std::make_shared>>(); + auto objectSnapshotMock = std::make_shared(); + bindAssets->insert({"PostEvent005", objectSnapshotMock}); + std::shared_ptr assetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); + std::set skipAssets; + std::set deleteAssets; + rdbAssetLoader.PostEvent(DistributedData::AssetEvent::DOWNLOAD, assets, + skipAssets, deleteAssets); + EXPECT_EQ(objectSnapshotMock->hasDownload, true); +} + +/** +@tc.name: PostEvent006 +@tc.desc: RdbAssetLoader PostEvent006 test,snapshots_ not found +@tc.type: FUNC +@tc.require: +@tc.author: SQL +*/ +HWTEST_F(RdbAssetLoaderTest, PostEvent006, TestSize.Level0) { + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_NORMAL, + }; + DistributedData::Assets assets; + assets.push_back(asset); + BindAssets bindAssets = std::make_shared>>(); + bindAssets->insert({"PostEvent006", std::make_shared()}); + std::shared_ptr assetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); + std::set skipAssets; + std::set deleteAssets; + rdbAssetLoader.PostEvent(DistributedData::AssetEvent::DOWNLOAD, assets, skipAssets, deleteAssets); + EXPECT_EQ(deleteAssets.size(), 0); + EXPECT_EQ(skipAssets.size(), 0); +} + +/** +@tc.name: PostEvent007 +@tc.desc: RdbAssetLoader PostEvent007 test, Both deleteAssets and skipAssets can be found. +@tc.type: FUNC +@tc.require: +@tc.author: SQL +*/ +HWTEST_F(RdbAssetLoaderTest, PostEvent007, TestSize.Level0) { + class ObjectSnapshotMock : public DistributedObject::ObjectSnapshot { + public: + int32_t Downloaded(Asset &asset) override { + hasDownloaded = true; + return 0; + } + bool hasDownloaded = false; + }; + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "PostEvent007", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_NORMAL, + }; + DistributedData::Assets assets; + assets.push_back(asset); + BindAssets bindAssets = std::make_shared>>(); + auto objectSnapshotMock = std::make_shared(); + bindAssets->insert({"PostEvent007", objectSnapshotMock}); + std::shared_ptr assetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); + std::set skipAssets; + skipAssets.insert("PostEvent007"); + std::set deleteAssets; + deleteAssets.insert("PostEvent007"); + rdbAssetLoader.PostEvent(DistributedData::AssetEvent::UPLOAD, assets, skipAssets, deleteAssets); + EXPECT_EQ(objectSnapshotMock->hasDownloaded, false); +} + +/** +@tc.name: PostEvent008 +@tc.desc: RdbAssetLoader PostEvent008 test, Neither deleteAssets nor skipAssets can be found. +@tc.type: FUNC +@tc.require: +@tc.author: SQL +*/ +HWTEST_F(RdbAssetLoaderTest, PostEvent008, TestSize.Level0) { + class ObjectSnapshotMock : public DistributedObject::ObjectSnapshot { + public: + int32_t Downloaded(Asset &asset) override { + hasDownloaded = true; + return 0; + } + bool hasDownloaded = false; + }; + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "PostEvent008", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_NORMAL, + }; + DistributedData::Assets assets; + assets.push_back(asset); + BindAssets bindAssets = std::make_shared>>(); + auto objectSnapshotMock = std::make_shared(); + bindAssets->insert({"PostEvent008", objectSnapshotMock}); + std::shared_ptr assetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); + std::set skipAssets; + std::set deleteAssets; + rdbAssetLoader.PostEvent(DistributedData::AssetEvent::UPLOAD, assets, skipAssets, deleteAssets); + EXPECT_EQ(objectSnapshotMock->hasDownloaded, true); +} +/** + +@tc.name: PostEvent009 +@tc.desc: RdbAssetLoader PostEvent009 test, deleteAssets can be found, skipAssets cannot be found. +@tc.type: FUNC +@tc.require: +@tc.author: SQL +*/ +HWTEST_F(RdbAssetLoaderTest, PostEvent009, TestSize.Level0) { + class ObjectSnapshotMock : public DistributedObject::ObjectSnapshot { + public: + int32_t Downloaded(Asset &asset) override { + hasDownloaded = true; + return 0; + } + bool hasDownloaded = false; + }; + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "PostEvent009", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_NORMAL, + }; + DistributedData::Assets assets; + assets.push_back(asset); + BindAssets bindAssets = std::make_shared>>(); + auto objectSnapshotMock = std::make_shared(); + bindAssets->insert({"PostEvent009", objectSnapshotMock}); + std::shared_ptr assetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); + std::set skipAssets; + std::set deleteAssets; + deleteAssets.insert("PostEvent009"); + rdbAssetLoader.PostEvent(DistributedData::AssetEvent::UPLOAD, assets, skipAssets, deleteAssets); + EXPECT_EQ(objectSnapshotMock->hasDownloaded, false); +} + +/** +@tc.name: PostEvent0010 +@tc.desc: RdbAssetLoader PostEvent0010 test, skipAssets can be found, deleteAssets cannot be found. +@tc.type: FUNC +@tc.require: +@tc.author: SQL +*/ +HWTEST_F(RdbAssetLoaderTest, PostEvent0010, TestSize.Level0) { + class ObjectSnapshotMock : public DistributedObject::ObjectSnapshot { + public: + int32_t Downloaded(Asset &asset) override { + hasDownloaded = true; + return 0; + } + bool hasDownloaded = false; + }; + DistributedData::Asset asset = { + .name = "", + .id = "", + .path = "", + .uri = "PostEvent0010", + .modifyTime = "", + .createTime = "", + .size = "", + .hash = "", + .status = DistributedData::Asset::STATUS_NORMAL, + }; + DistributedData::Assets assets; + assets.push_back(asset); + BindAssets bindAssets = std::make_shared>>(); + auto objectSnapshotMock = std::make_shared(); + bindAssets->insert({"PostEvent0010", objectSnapshotMock}); + std::shared_ptr assetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(assetLoader, bindAssets); + std::set skipAssets; + skipAssets.insert("PostEvent0010"); + std::set deleteAssets; + rdbAssetLoader.PostEvent(DistributedData::AssetEvent::UPLOAD, assets, skipAssets, deleteAssets); + EXPECT_EQ(objectSnapshotMock->hasDownloaded, false); +} + /** * @tc.name: ConvertStatus * @tc.desc: RdbAssetLoader ConvertStatus abnormal diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_cloud_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_cloud_test.cpp index cca78a80..2683faa9 100644 --- a/datamgr_service/services/distributeddataservice/service/test/rdb_cloud_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_cloud_test.cpp @@ -16,27 +16,77 @@ #include "rdb_cloud.h" +#include "cloud_db_mock.h" +#include "cursor_mock.h" +#include "gmock/gmock.h" #include "gtest/gtest.h" #include "log_print.h" using namespace testing::ext; +using namespace testing; using namespace OHOS::DistributedData; using namespace OHOS::DistributedRdb; using DBVBucket = DistributedDB::VBucket; using DBStatus = DistributedDB::DBStatus; -std::vector g_DBVBucket = { { { "#gid", { "0000000" } }, { "#flag", { true } }, +using DBAsset = DistributedDB::Asset; +using DBAssets = DistributedDB::Assets; +using AssetOpType = DistributedDB::AssetOpType; +using AssetStatus = DistributedDB::AssetStatus; +DBAsset assetValue1 = { .version = 1, + .name = "texture_diffuse", + .assetId = "123", + .subpath = "textures/environment", + .uri = "http://asset.com/textures/123.jpg", + .modifyTime = "2025-04-05T12:30:00Z", + .createTime = "2025-04-05T10:15:00Z", + .size = "1024", + .hash = "sha256-abc123", + .flag = static_cast(AssetOpType::INSERT), + .status = static_cast(AssetStatus::NORMAL), + .timestamp = std::time(nullptr) }; + +DBAsset assetValue2 = { .version = 2, + .name = "texture_diffuse", + .assetId = "456", + .subpath = "textures/environment", + .uri = "http://asset.com/textures/456.jpg", + .modifyTime = "2025-06-19T12:30:00Z", + .createTime = "2025-04-05T10:15:00Z", + .size = "1024", + .hash = "sha256-abc456", + .flag = static_cast(AssetOpType::UPDATE), + .status = static_cast(AssetStatus::NORMAL), + .timestamp = std::time(nullptr) }; + +DBAssets assetsValue = { assetValue1, assetValue2 }; +std::vector g_DBVBuckets = { { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, { "#float", { double(100) } }, { "#_type", { int64_t(1) } }, - { "#_query", { Bytes({ 1, 2, 3, 4 }) } } } }; + { "#_error", { "E_ERROR" } }, { "#_error", { "INVALID" } }, { "#_query", { Bytes({ 1, 2, 3, 4 }) } }, + { "#asset", assetValue1 }, { "#assets", assetsValue } } }; +DBVBucket g_DBVBucket = { { "#value", { int64_t(100) } } }; + namespace OHOS::Test { namespace DistributedRDBTest { class RdbCloudTest : public testing::Test { public: - static void SetUpTestCase(void){}; - static void TearDownTestCase(void){}; + static void SetUpTestCase(); + static void TearDownTestCase(); void SetUp(){}; void TearDown(){}; + static inline std::shared_ptr mockCloudDB = nullptr; + static constexpr int32_t COUNT = 2; }; +void RdbCloudTest::SetUpTestCase() +{ + mockCloudDB = std::make_shared(); +} + +void RdbCloudTest::TearDownTestCase() +{ + mockCloudDB = nullptr; +} + /** * @tc.name: RdbCloudTest001 * @tc.desc: RdbCloud BatchInsert BatchUpdate BatchDelete test. @@ -48,14 +98,21 @@ HWTEST_F(RdbCloudTest, RdbCloudTest001, TestSize.Level1) { BindAssets bindAssets; Bytes bytes; - std::shared_ptr cloudDB = std::make_shared(); - RdbCloud rdbCloud(cloudDB, &bindAssets); + RdbCloud rdbCloud(std::make_shared(), bindAssets); std::string tableName = "testTable"; - auto result = rdbCloud.BatchInsert(tableName, std::move(g_DBVBucket), g_DBVBucket); + + std::vector dataInsert = g_DBVBuckets; + std::vector extendInsert = g_DBVBuckets; + auto result = rdbCloud.BatchInsert(tableName, std::move(dataInsert), extendInsert); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - result = rdbCloud.BatchUpdate(tableName, std::move(g_DBVBucket), g_DBVBucket); + + std::vector dataUpdate = g_DBVBuckets; + std::vector extendUpdate = g_DBVBuckets; + result = rdbCloud.BatchUpdate(tableName, std::move(dataUpdate), extendUpdate); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - result = rdbCloud.BatchDelete(tableName, g_DBVBucket); + + std::vector extendDelete = g_DBVBuckets; + result = rdbCloud.BatchDelete(tableName, extendDelete); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); } @@ -69,24 +126,21 @@ HWTEST_F(RdbCloudTest, RdbCloudTest001, TestSize.Level1) HWTEST_F(RdbCloudTest, RdbCloudTest002, TestSize.Level1) { BindAssets bindAssets; - std::shared_ptr cloudDB = std::make_shared(); - RdbCloud rdbCloud(cloudDB, &bindAssets); + RdbCloud rdbCloud(std::make_shared(), bindAssets); std::string tableName = "testTable"; rdbCloud.Lock(); std::string traceId = "id"; rdbCloud.SetPrepareTraceId(traceId); - auto result = rdbCloud.BatchInsert(tableName, std::move(g_DBVBucket), g_DBVBucket); + std::vector dataInsert = g_DBVBuckets; + std::vector extendInsert = g_DBVBuckets; + auto result = rdbCloud.BatchInsert(tableName, std::move(dataInsert), extendInsert); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - DBVBucket extends = { - {"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}, - {"#_type", {int64_t(1)}}, {"#_query", {Bytes({ 1, 2, 3, 4 })}} - }; - result = rdbCloud.Query(tableName, extends, g_DBVBucket); + DBVBucket extends = { { "#gid", { "00000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } }, { "#_type", { int64_t(1) } }, { "#_query", { Bytes({ 1, 2, 3, 4 }) } } }; + result = rdbCloud.Query(tableName, extends, g_DBVBuckets); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - std::vector vBuckets = { - {{"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}, - {"#_type", {int64_t(1)}}, {"#_query", {Bytes({ 1, 2, 3, 4 })}}} - }; + std::vector vBuckets = { { { "#gid", { "00000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } }, { "#_type", { int64_t(1) } }, { "#_query", { Bytes({ 1, 2, 3, 4 }) } } } }; rdbCloud.PreSharing(tableName, vBuckets); result = rdbCloud.HeartBeat(); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); @@ -105,32 +159,23 @@ HWTEST_F(RdbCloudTest, RdbCloudTest002, TestSize.Level1) */ HWTEST_F(RdbCloudTest, RdbCloudTest003, TestSize.Level1) { - BindAssets bindAssets; - bindAssets.bindAssets = nullptr; - std::shared_ptr cloudDB = std::make_shared(); - RdbCloud rdbCloud(cloudDB, &bindAssets); + BindAssets bindAssets = nullptr; + RdbCloud rdbCloud(std::make_shared(), bindAssets); std::string tableName = "testTable"; - DBVBucket extends = { - {"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}, - {"#_type", {int64_t(1)}} - }; - std::vector data = { - {{"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}} - }; + DBVBucket extends = { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } }, { "#_type", { int64_t(1) } } }; + std::vector data = { { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } } } }; auto result = rdbCloud.Query(tableName, extends, data); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - extends = { - {"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}, - {"#_query", {Bytes({ 1, 2, 3, 4 })}} - }; + extends = { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } }, { "#_query", { Bytes({ 1, 2, 3, 4 }) } } }; result = rdbCloud.Query(tableName, extends, data); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - extends = { - {"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}, - {"#_type", {int64_t(0)}} - }; + extends = { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } }, { "#_type", { int64_t(0) } } }; result = rdbCloud.Query(tableName, extends, data); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); } @@ -145,8 +190,7 @@ HWTEST_F(RdbCloudTest, RdbCloudTest003, TestSize.Level1) HWTEST_F(RdbCloudTest, RdbCloudTest004, TestSize.Level1) { BindAssets bindAssets; - std::shared_ptr cloudDB = std::make_shared(); - RdbCloud rdbCloud(cloudDB, &bindAssets); + RdbCloud rdbCloud(std::make_shared(), bindAssets); auto err = rdbCloud.UnLockCloudDB(OHOS::DistributedRdb::RdbCloud::FLAG::SYSTEM_ABILITY); EXPECT_EQ(err, GeneralError::E_NOT_SUPPORT); @@ -169,8 +213,7 @@ HWTEST_F(RdbCloudTest, RdbCloudTest004, TestSize.Level1) HWTEST_F(RdbCloudTest, ConvertStatus, TestSize.Level1) { BindAssets bindAssets; - std::shared_ptr cloudDB = std::make_shared(); - RdbCloud rdbCloud(cloudDB, &bindAssets); + RdbCloud rdbCloud(std::make_shared(), bindAssets); auto result = rdbCloud.ConvertStatus(GeneralError::E_OK); EXPECT_EQ(result, DBStatus::OK); result = rdbCloud.ConvertStatus(GeneralError::E_NETWORK_ERROR); @@ -195,8 +238,6 @@ HWTEST_F(RdbCloudTest, ConvertStatus, TestSize.Level1) EXPECT_EQ(result, DBStatus::TIME_OUT); result = rdbCloud.ConvertStatus(GeneralError::E_CLOUD_DISABLED); EXPECT_EQ(result, DBStatus::CLOUD_DISABLED); - result = rdbCloud.ConvertStatus(GeneralError::E_SKIP_ASSET); - EXPECT_EQ(result, DBStatus::SKIP_ASSET); } /** @@ -209,27 +250,174 @@ HWTEST_F(RdbCloudTest, ConvertStatus, TestSize.Level1) HWTEST_F(RdbCloudTest, ConvertQuery, TestSize.Level1) { RdbCloud::DBQueryNodes nodes; - DistributedDB::QueryNode node = { DistributedDB::QueryNodeType::IN, "", {int64_t(1)} }; + DistributedDB::QueryNode node = { DistributedDB::QueryNodeType::IN, "", { int64_t(1) } }; nodes.push_back(node); - node = { DistributedDB::QueryNodeType::OR, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::OR, "", { int64_t(1) } }; nodes.push_back(node); - node = { DistributedDB::QueryNodeType::AND, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::AND, "", { int64_t(1) } }; nodes.push_back(node); - node = { DistributedDB::QueryNodeType::EQUAL_TO, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::EQUAL_TO, "", { int64_t(1) } }; nodes.push_back(node); - node = { DistributedDB::QueryNodeType::BEGIN_GROUP, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::BEGIN_GROUP, "", { int64_t(1) } }; nodes.push_back(node); - node = { DistributedDB::QueryNodeType::END_GROUP, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::END_GROUP, "", { int64_t(1) } }; nodes.push_back(node); - + auto result = RdbCloud::ConvertQuery(std::move(nodes)); EXPECT_EQ(result.size(), 6); nodes.clear(); - node = { DistributedDB::QueryNodeType::ILLEGAL, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::ILLEGAL, "", { int64_t(1) } }; nodes.push_back(node); result = RdbCloud::ConvertQuery(std::move(nodes)); EXPECT_EQ(result.size(), 0); } + +/** +* @tc.name: SetPrepareTraceId001 +* @tc.desc: RdbCloud PostEvent test cloudDB_ is nullptr. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, SetPrepareTraceId001, TestSize.Level1) +{ + std::string traceId = "testId"; + EXPECT_CALL(*mockCloudDB, SetPrepareTraceId(_)).Times(0); + BindAssets bindAssets; + std::shared_ptr mockCloudDB = nullptr; + RdbCloud rdbCloud(mockCloudDB, bindAssets); + rdbCloud.SetPrepareTraceId(traceId); +} + +/** +* @tc.name: PostEvent001 +* @tc.desc: RdbCloud PostEvent test bindAssets is nullptr. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, PostEvent001, TestSize.Level1) +{ + BindAssets bindAssets; + RdbCloud rdbCloud(std::make_shared(), nullptr); + std::string traceId = "testId"; + rdbCloud.SetPrepareTraceId(traceId); + std::string tableName = "testTable"; + std::vector dataInsert = g_DBVBuckets; + std::vector extendInsert = g_DBVBuckets; + auto result = rdbCloud.BatchInsert(tableName, std::move(dataInsert), extendInsert); + EXPECT_EQ(result, DBStatus::CLOUD_ERROR); +} + +/** +* @tc.name: PostEvent002 +* @tc.desc: RdbCloud PostEvent test snapshots contains asset.uri. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, PostEvent002, TestSize.Level1) +{ + BindAssets snapshots = std::make_shared>>(); + std::shared_ptr snapshot; + snapshots->insert_or_assign(assetValue1.uri, snapshot); + RdbCloud rdbCloud(std::make_shared(), snapshots); + std::string tableName = "testTable"; + std::vector dataInsert = g_DBVBuckets; + std::vector extendInsert = g_DBVBuckets; + auto result = rdbCloud.BatchInsert(tableName, std::move(dataInsert), extendInsert); + EXPECT_EQ(result, DBStatus::CLOUD_ERROR); +} + +/** +* @tc.name: PostEvent003 +* @tc.desc: RdbCloud PostEvent test snapshots does not contains asset.uri. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, PostEvent003, TestSize.Level1) +{ + BindAssets snapshots = std::make_shared>>(); + std::shared_ptr snapshot; + std::string uri = "testuri"; + snapshots->insert_or_assign(uri, snapshot); + RdbCloud rdbCloud(std::make_shared(), snapshots); + std::string tableName = "testTable"; + std::vector dataInsert = g_DBVBuckets; + std::vector extendInsert = g_DBVBuckets; + auto result = rdbCloud.BatchInsert(tableName, std::move(dataInsert), extendInsert); + EXPECT_EQ(result, DBStatus::CLOUD_ERROR); +} + +/** +* @tc.name: PostEvent004 +* @tc.desc: RdbCloud PostEvent test the snapshot contained in the snapshots is nullpt. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, PostEvent004, TestSize.Level1) +{ + BindAssets snapshots = std::make_shared>>(); + std::shared_ptr snapshot = nullptr; + std::string uri = "testuri"; + snapshots->insert_or_assign(uri, snapshot); + RdbCloud rdbCloud(std::make_shared(), snapshots); + std::string tableName = "testTable"; + std::vector dataInsert = g_DBVBuckets; + std::vector extendInsert = g_DBVBuckets; + auto result = rdbCloud.BatchInsert(tableName, std::move(dataInsert), extendInsert); + EXPECT_EQ(result, DBStatus::CLOUD_ERROR); +} + +/** +* @tc.name: Query001 +* @tc.desc: RdbCloud Query test the cursor is nullptr and code is not E_OK. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, Query001, TestSize.Level1) +{ + std::shared_ptr cursor = nullptr; + std::string tableName = "testTable"; + EXPECT_CALL(*mockCloudDB, Query(tableName, _)).WillOnce(Return(std::make_pair(E_NETWORK_ERROR, cursor))); + BindAssets snapshots; + RdbCloud rdbCloud(mockCloudDB, snapshots); + auto result = rdbCloud.Query(tableName, g_DBVBucket, g_DBVBuckets); + EXPECT_EQ(result, DBStatus::CLOUD_NETWORK_ERROR); +} + +/** +* @tc.name: Query002 +* @tc.desc: RdbCloud Query test code is QUERY_END. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, Query002, TestSize.Level1) +{ + std::shared_ptr mockCursor = std::make_shared(); + std::string tableName = "testTable"; + EXPECT_CALL(*mockCloudDB, Query(tableName, _)).WillOnce(Return(std::make_pair(E_OK, mockCursor))); + EXPECT_CALL(*mockCursor, GetCount()).WillOnce(Return(COUNT)); + EXPECT_CALL(*mockCursor, GetEntry(_)).WillOnce(Return(E_OK)).WillOnce(Return(E_ERROR)); + EXPECT_CALL(*mockCursor, MoveToNext()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*mockCursor, IsEnd()).WillOnce(Return(true)); + + BindAssets snapshots; + RdbCloud rdbCloud(mockCloudDB, snapshots); + auto result = rdbCloud.Query(tableName, g_DBVBucket, g_DBVBuckets); + EXPECT_EQ(result, DBStatus::QUERY_END); +} + +/** +* @tc.name: Query003 +* @tc.desc: RdbCloud Query test code is CLOUD_ERROR. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, Query003, TestSize.Level1) +{ + std::shared_ptr mockCursor = std::make_shared(); + std::string tableName = "testTable"; + EXPECT_CALL(*mockCloudDB, Query(tableName, _)).WillOnce(Return(std::make_pair(E_OK, mockCursor))); + EXPECT_CALL(*mockCursor, GetCount()).WillOnce(Return(COUNT)); + EXPECT_CALL(*mockCursor, GetEntry(_)).WillOnce(Return(E_OK)).WillOnce(Return(E_ERROR)); + EXPECT_CALL(*mockCursor, MoveToNext()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*mockCursor, IsEnd()).WillOnce(Return(false)); + + BindAssets snapshots; + RdbCloud rdbCloud(mockCloudDB, snapshots); + auto result = rdbCloud.Query(tableName, g_DBVBucket, g_DBVBuckets); + EXPECT_EQ(result, DBStatus::CLOUD_ERROR); +} } // namespace DistributedRDBTest } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_general_store_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_general_store_test.cpp index 70e914dd..1e2effe7 100644 --- a/datamgr_service/services/distributeddataservice/service/test/rdb_general_store_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_general_store_test.cpp @@ -21,6 +21,9 @@ #include "bootstrap.h" #include "cloud/schema_meta.h" +#include "error/general_error.h" +#include "errors.h" +#include "eventcenter/event_center.h" #include "gtest/gtest.h" #include "log_print.h" #include "metadata/meta_data_manager.h" @@ -29,7 +32,11 @@ #include "metadata/store_meta_data_local.h" #include "mock/general_watcher_mock.h" #include "rdb_query.h" +#include "relational_store_delegate_mock.h" #include "store/general_store.h" +#include "store/general_value.h" +#include "store_observer.h" +#include "store_types.h" #include "types.h" using namespace testing::ext; @@ -37,14 +44,15 @@ using namespace DistributedDB; using namespace OHOS::DistributedData; using namespace OHOS::DistributedRdb; using DBStatus = DistributedDB::DBStatus; -using StoreMetaData = OHOS::DistributedData::StoreMetaData; RdbGeneralStore::Values g_RdbValues = { { "0000000" }, { true }, { int64_t(100) }, { double(100) }, { int64_t(1) }, { Bytes({ 1, 2, 3, 4 }) } }; RdbGeneralStore::VBucket g_RdbVBucket = { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, { "#float", { double(100) } } }; -bool g_testResult = false; +bool MockRelationalStoreDelegate::gTestResult = false; namespace OHOS::Test { namespace DistributedRDBTest { +using StoreMetaData = OHOS::DistributedData::StoreMetaData; +using namespace OHOS::DistributedRdb; static constexpr uint32_t PRINT_ERROR_CNT = 150; static constexpr const char *BUNDLE_NAME = "test_rdb_general_store"; static constexpr const char *STORE_NAME = "test_service_rdb"; @@ -56,15 +64,18 @@ public: { Bootstrap::GetInstance().LoadDirectory(); InitMetaData(); + store = std::make_shared(metaData_); + ASSERT_NE(store, nullptr); }; void TearDown() { - g_testResult = false; + MockRelationalStoreDelegate::gTestResult = false; }; protected: void InitMetaData(); StoreMetaData metaData_; + std::shared_ptr store; }; void RdbGeneralStoreTest::InitMetaData() @@ -79,158 +90,9 @@ void RdbGeneralStoreTest::InitMetaData() metaData_.storeId = STORE_NAME; metaData_.dataDir = "/data/service/el1/public/database/" + std::string(BUNDLE_NAME) + "/rdb"; metaData_.securityLevel = DistributedKv::SecurityLevel::S2; + metaData_.isSearchable = true; } -class MockRelationalStoreDelegate : public DistributedDB::RelationalStoreDelegate { -public: - ~MockRelationalStoreDelegate() = default; - - DBStatus Sync(const std::vector &devices, DistributedDB::SyncMode mode, const Query &query, - const SyncStatusCallback &onComplete, bool wait) override - { - return DBStatus::OK; - } - - int32_t GetCloudSyncTaskCount() override - { - static int32_t count = 0; - count = (count + 1) % 2; // The result of count + 1 is the remainder of 2. - return count; - } - - DBStatus RemoveDeviceData(const std::string &device, const std::string &tableName) override - { - return DBStatus::OK; - } - - DBStatus RemoteQuery(const std::string &device, const RemoteCondition &condition, uint64_t timeout, - std::shared_ptr &result) override - { - if (device == "test") { - return DBStatus::DB_ERROR; - } - return DBStatus::OK; - } - - DBStatus RemoveDeviceData() override - { - return DBStatus::OK; - } - - DBStatus Sync(const std::vector &devices, DistributedDB::SyncMode mode, const Query &query, - const SyncProcessCallback &onProcess, int64_t waitTime) override - { - return DBStatus::OK; - } - - DBStatus SetCloudDB(const std::shared_ptr &cloudDb) override - { - return DBStatus::OK; - } - - DBStatus SetCloudDbSchema(const DataBaseSchema &schema) override - { - return DBStatus::OK; - } - - DBStatus RegisterObserver(StoreObserver *observer) override - { - return DBStatus::OK; - } - - DBStatus UnRegisterObserver() override - { - return DBStatus::OK; - } - - DBStatus UnRegisterObserver(StoreObserver *observer) override - { - return DBStatus::OK; - } - - DBStatus SetIAssetLoader(const std::shared_ptr &loader) override - { - return DBStatus::OK; - } - - DBStatus Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) override - { - return DBStatus::OK; - } - - DBStatus SetTrackerTable(const TrackerSchema &schema) override - { - if (schema.tableName == "WITH_INVENTORY_DATA") { - return DBStatus::WITH_INVENTORY_DATA; - } - if (schema.tableName == "test") { - return DBStatus::DB_ERROR; - } - return DBStatus::OK; - } - - DBStatus ExecuteSql(const SqlCondition &condition, std::vector &records) override - { - if (condition.sql == "") { - return DBStatus::DB_ERROR; - } - - std::string sqls = "INSERT INTO test ( #flag, #float, #gid, #value) VALUES ( ?, ?, ?, ?)"; - std::string sqlIn = " UPDATE test SET setSql WHERE whereSql"; - std::string sql = "REPLACE INTO test ( #flag, #float, #gid, #value) VALUES ( ?, ?, ?, ?)"; - if (condition.sql == sqls || condition.sql == sqlIn || condition.sql == sql) { - return DBStatus::DB_ERROR; - } - return DBStatus::OK; - } - - DBStatus SetReference(const std::vector &tableReferenceProperty) override - { - if (g_testResult) { - return DBStatus::DB_ERROR; - } - return DBStatus::OK; - } - - DBStatus CleanTrackerData(const std::string &tableName, int64_t cursor) override - { - return DBStatus::OK; - } - - DBStatus Pragma(PragmaCmd cmd, PragmaData &pragmaData) override - { - return DBStatus::OK; - } - - DBStatus UpsertData(const std::string &tableName, const std::vector &records, - RecordStatus status = RecordStatus::WAIT_COMPENSATED_SYNC) override - { - return DBStatus::OK; - } - - DBStatus SetCloudSyncConfig(const CloudSyncConfig &config) override - { - return DBStatus::OK; - } - -protected: - DBStatus RemoveDeviceDataInner(const std::string &device, ClearMode mode) override - { - if (g_testResult) { - return DBStatus::DB_ERROR; - } - return DBStatus::OK; - } - - DBStatus CreateDistributedTableInner(const std::string &tableName, TableSyncType type) override - { - if (tableName == "test") { - return DBStatus::DB_ERROR; - } - return DBStatus::OK; - } -}; - class MockStoreChangedData : public DistributedDB::StoreChangedData { public: std::string GetDataChangeDevice() const override @@ -248,15 +110,11 @@ public: * @tc.name: BindSnapshots001 * @tc.desc: RdbGeneralStore BindSnapshots test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, BindSnapshots001, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); BindAssets bindAssets; - auto result = store->BindSnapshots(bindAssets.bindAssets); + auto result = store->BindSnapshots(bindAssets); EXPECT_EQ(result, GeneralError::E_OK); } @@ -264,19 +122,35 @@ HWTEST_F(RdbGeneralStoreTest, BindSnapshots001, TestSize.Level1) * @tc.name: BindSnapshots002 * @tc.desc: RdbGeneralStore BindSnapshots nullptr test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, BindSnapshots002, TestSize.Level1) { DistributedData::StoreMetaData meta; meta = metaData_; meta.isEncrypt = true; - auto store = new (std::nothrow) RdbGeneralStore(meta); + auto store = std::make_shared(meta); ASSERT_NE(store, nullptr); - store->snapshots_.bindAssets = nullptr; + store->snapshots_ = nullptr; BindAssets bindAssets; - auto result = store->BindSnapshots(bindAssets.bindAssets); + auto result = store->BindSnapshots(bindAssets); + EXPECT_EQ(result, GeneralError::E_OK); +} + +/** +@tc.name: BindSnapshots003 +@tc.desc: RdbGeneralStore BindSnapshots not nullptr test +@tc.type: FUNC +*/ +HWTEST_F(RdbGeneralStoreTest, BindSnapshots003, TestSize.Level1) +{ + DistributedData::StoreMetaData meta; + meta = metaData_; + meta.isEncrypt = true; + auto store = std::make_shared(meta); + ASSERT_NE(store, nullptr); + BindAssets bindAssets = std::make_shared>>(); + store->snapshots_ = bindAssets; + auto result = store->BindSnapshots(bindAssets); EXPECT_EQ(result, GeneralError::E_OK); } @@ -284,13 +158,9 @@ HWTEST_F(RdbGeneralStoreTest, BindSnapshots002, TestSize.Level1) * @tc.name: Bind001 * @tc.desc: RdbGeneralStore Bind bindInfo test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Bind001, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedData::Database database; GeneralStore::CloudConfig config; std::map bindInfos; @@ -330,16 +200,11 @@ HWTEST_F(RdbGeneralStoreTest, Bind001, TestSize.Level1) * @tc.name: Bind002 * @tc.desc: RdbGeneralStore Bind delegate_ is nullptr test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Bind002, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedData::Database database; std::map bindInfos; - std::shared_ptr db = std::make_shared(); std::shared_ptr loader = std::make_shared(); GeneralStore::BindInfo bindInfo(db, loader); @@ -359,13 +224,9 @@ HWTEST_F(RdbGeneralStoreTest, Bind002, TestSize.Level1) * @tc.name: Bind003 * @tc.desc: RdbGeneralStore Bind delegate_ test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Bind003, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedData::Database database; std::map bindInfos; @@ -374,8 +235,8 @@ HWTEST_F(RdbGeneralStoreTest, Bind003, TestSize.Level1) GeneralStore::BindInfo bindInfo(db, loader); uint32_t key = 1; bindInfos[key] = bindInfo; - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); GeneralStore::CloudConfig config; auto result = store->Bind(database, bindInfos, config); EXPECT_NE(store->delegate_, nullptr); @@ -384,32 +245,84 @@ HWTEST_F(RdbGeneralStoreTest, Bind003, TestSize.Level1) /** * @tc.name: Close -* @tc.desc: RdbGeneralStore Close and IsBound function test +* @tc.desc: RdbGeneralStore Close and isforce is false and GetDeviceSyncTaskCount is 2 * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Close, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); - auto result = store->IsBound(std::stoi(metaData_.user)); + auto result = store->IsBound(std::atoi(metaData_.user.c_str())); EXPECT_EQ(result, false); EXPECT_EQ(store->delegate_, nullptr); auto ret = store->Close(); EXPECT_EQ(ret, GeneralError::E_OK); - - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); + MockRelationalStoreDelegate::SetCloudSyncTaskCount(0); + MockRelationalStoreDelegate::SetDownloadingAssetsCount(0); + MockRelationalStoreDelegate::SetDeviceTaskCount(2); ret = store->Close(); EXPECT_EQ(ret, GeneralError::E_BUSY); } +/** + * @tc.name: Close1 + * @tc.desc: RdbGeneralStore Close and isforce is false and GetCloudSyncTaskCount is 1 + * @tc.type: FUNC + */ +HWTEST_F(RdbGeneralStoreTest, Close1, TestSize.Level1) +{ + metaData_.storeId = "mock"; + auto store = std::make_shared(metaData_); + MockRelationalStoreDelegate::SetCloudSyncTaskCount(1); + auto ret = store->Close(); + EXPECT_EQ(ret, GeneralError::E_BUSY); +} +/** + * @tc.name: Close2 + * @tc.desc: RdbGeneralStore Close and isforce is false and DownloadingAssetsCount is 1 + * @tc.type: FUNC + */ +HWTEST_F(RdbGeneralStoreTest, Close2, TestSize.Level1) +{ + metaData_.storeId = "mock"; + auto store = std::make_shared(metaData_); + MockRelationalStoreDelegate::SetCloudSyncTaskCount(0); + MockRelationalStoreDelegate::SetDownloadingAssetsCount(1); + auto ret = store->Close(); + EXPECT_EQ(ret, GeneralError::E_BUSY); +} +/** + * @tc.name: Close3 + * @tc.desc: RdbGeneralStore Close and isforce is true + * @tc.type: FUNC + */ +HWTEST_F(RdbGeneralStoreTest, Close3, TestSize.Level1) +{ + metaData_.storeId = "mock"; + auto store = std::make_shared(metaData_); + auto ret = store->Close(true); + EXPECT_EQ(ret, GeneralError::E_OK); +} +/** + * @tc.name: Close4 + * @tc.desc: RdbGeneralStore Close and there is no task + * @tc.type: FUNC + */ +HWTEST_F(RdbGeneralStoreTest, Close4, TestSize.Level1) +{ + metaData_.storeId = "mock"; + auto store = std::make_shared(metaData_); + MockRelationalStoreDelegate::SetCloudSyncTaskCount(0); + MockRelationalStoreDelegate::SetDownloadingAssetsCount(0); + MockRelationalStoreDelegate::SetDeviceTaskCount(0); + auto ret = store->Close(); + EXPECT_EQ(ret, GeneralError::E_OK); +} + /** * @tc.name: Close * @tc.desc: RdbGeneralStore Close test * @tc.type: FUNC -* @tc.require: * @tc.author: shaoyuanzhao */ HWTEST_F(RdbGeneralStoreTest, BusyClose, TestSize.Level1) @@ -432,21 +345,16 @@ HWTEST_F(RdbGeneralStoreTest, BusyClose, TestSize.Level1) * @tc.name: Execute * @tc.desc: RdbGeneralStore Execute function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Execute, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "table"; std::string sql = "sql"; EXPECT_EQ(store->delegate_, nullptr); auto result = store->Execute(table, sql); EXPECT_EQ(result, GeneralError::E_ERROR); - - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); result = store->Execute(table, sql); EXPECT_EQ(result, GeneralError::E_OK); @@ -459,13 +367,9 @@ HWTEST_F(RdbGeneralStoreTest, Execute, TestSize.Level1) * @tc.name: SqlConcatenate * @tc.desc: RdbGeneralStore SqlConcatenate function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, SqlConcatenate, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedData::VBucket value; std::string strColumnSql = "strColumnSql"; std::string strRowValueSql = "strRowValueSql"; @@ -485,13 +389,9 @@ HWTEST_F(RdbGeneralStoreTest, SqlConcatenate, TestSize.Level1) * @tc.name: Insert001 * @tc.desc: RdbGeneralStore Insert error test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Insert001, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedData::VBuckets values; EXPECT_EQ(values.size(), 0); std::string table = "table"; @@ -519,23 +419,14 @@ HWTEST_F(RdbGeneralStoreTest, Insert001, TestSize.Level1) * @tc.name: Insert002 * @tc.desc: RdbGeneralStore Insert function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Insert002, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "table"; DistributedData::VBuckets extends = { { g_RdbVBucket } }; auto result = store->Insert(table, std::move(extends)); EXPECT_EQ(result, GeneralError::E_ERROR); - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; - result = store->Insert(table, std::move(extends)); - EXPECT_EQ(result, GeneralError::E_OK); - std::string test = "test"; result = store->Insert(test, std::move(extends)); EXPECT_EQ(result, GeneralError::E_ERROR); @@ -547,19 +438,19 @@ HWTEST_F(RdbGeneralStoreTest, Insert002, TestSize.Level1) result = store->Insert(test, std::move(extends)); EXPECT_EQ(result, GeneralError::E_ERROR); } + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); + result = store->Insert(table, std::move(extends)); + EXPECT_EQ(result, GeneralError::E_OK); } /** * @tc.name: Update * @tc.desc: RdbGeneralStore Update function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Update, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "table"; std::string setSql = "setSql"; RdbGeneralStore::Values values; @@ -582,9 +473,8 @@ HWTEST_F(RdbGeneralStoreTest, Update, TestSize.Level1) result = store->Update(table, setSql, std::move(g_RdbValues), whereSql, std::move(g_RdbValues)); EXPECT_EQ(result, GeneralError::E_ERROR); - - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); result = store->Update(table, setSql, std::move(g_RdbValues), whereSql, std::move(g_RdbValues)); EXPECT_EQ(result, GeneralError::E_OK); @@ -596,13 +486,9 @@ HWTEST_F(RdbGeneralStoreTest, Update, TestSize.Level1) * @tc.name: Replace * @tc.desc: RdbGeneralStore Replace function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Replace, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "table"; RdbGeneralStore::VBucket values; auto result = store->Replace("", std::move(g_RdbVBucket)); @@ -613,9 +499,8 @@ HWTEST_F(RdbGeneralStoreTest, Replace, TestSize.Level1) result = store->Replace(table, std::move(g_RdbVBucket)); EXPECT_EQ(result, GeneralError::E_ERROR); - - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); result = store->Replace(table, std::move(g_RdbVBucket)); EXPECT_EQ(result, GeneralError::E_OK); @@ -627,13 +512,9 @@ HWTEST_F(RdbGeneralStoreTest, Replace, TestSize.Level1) * @tc.name: Delete * @tc.desc: RdbGeneralStore Delete function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Delete, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "table"; std::string sql = "sql"; auto result = store->Delete(table, sql, std::move(g_RdbValues)); @@ -644,21 +525,16 @@ HWTEST_F(RdbGeneralStoreTest, Delete, TestSize.Level1) * @tc.name: Query001 * @tc.desc: RdbGeneralStore Query function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Query001, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "table"; std::string sql = "sql"; auto [err1, result1] = store->Query(table, sql, std::move(g_RdbValues)); EXPECT_EQ(err1, GeneralError::E_ALREADY_CLOSED); EXPECT_EQ(result1, nullptr); - - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); auto [err2, result2] = store->Query(table, sql, std::move(g_RdbValues)); EXPECT_EQ(err2, GeneralError::E_OK); EXPECT_NE(result2, nullptr); @@ -668,13 +544,9 @@ HWTEST_F(RdbGeneralStoreTest, Query001, TestSize.Level1) * @tc.name: Query002 * @tc.desc: RdbGeneralStore Query function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Query002, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "table"; std::string sql = "sql"; MockQuery query; @@ -688,24 +560,65 @@ HWTEST_F(RdbGeneralStoreTest, Query002, TestSize.Level1) EXPECT_EQ(result2, nullptr); } +/** + * @tc.name: Query003 + * @tc.desc: it is not a remote query return E_ERROR. + * @tc.type: FUNC + */ +HWTEST_F(RdbGeneralStoreTest, Query003, TestSize.Level1) +{ + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); + ASSERT_NE(store, nullptr); + + MockQuery query; + const std::string devices = "device1"; + const std::string sql; + Values args; + query.lastResult = true; + std::string table = "test_table"; + auto [err, cursor] = store->Query(table, query); + EXPECT_EQ(err, GeneralError::E_ERROR); +} + +/** + * @tc.name: Query004 + * @tc.desc: Test successful remote query + * @tc.type: FUNC + */ +HWTEST_F(RdbGeneralStoreTest, Query004, TestSize.Level1) +{ + MockQuery query; + const std::string devices = "device1"; + const std::string sql; + Values args; + query.MakeRemoteQuery(devices, sql, std::move(args)); + query.lastResult = true; + + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); + + std::string table = "test_table"; + auto [err, cursor] = store->Query(table, query); + + EXPECT_EQ(err, GeneralError::E_OK); + EXPECT_NE(cursor, nullptr); +} + /** * @tc.name: MergeMigratedData * @tc.desc: RdbGeneralStore MergeMigratedData function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, MergeMigratedData, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string tableName = "tableName"; DistributedData::VBuckets extends = { { g_RdbVBucket } }; auto result = store->MergeMigratedData(tableName, std::move(extends)); EXPECT_EQ(result, GeneralError::E_ERROR); - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); result = store->MergeMigratedData(tableName, std::move(extends)); EXPECT_EQ(result, GeneralError::E_OK); } @@ -714,13 +627,9 @@ HWTEST_F(RdbGeneralStoreTest, MergeMigratedData, TestSize.Level1) * @tc.name: Sync * @tc.desc: RdbGeneralStore Sync function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Sync, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); GeneralStore::Devices devices; MockQuery query; GeneralStore::DetailAsync async; @@ -728,42 +637,132 @@ HWTEST_F(RdbGeneralStoreTest, Sync, TestSize.Level1) auto result = store->Sync(devices, query, async, syncParam); EXPECT_EQ(result.first, GeneralError::E_ALREADY_CLOSED); - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); result = store->Sync(devices, query, async, syncParam); EXPECT_EQ(result.first, GeneralError::E_OK); } +/** +* @tc.name: Sync +* @tc.desc: RdbGeneralStore Sync CLOUD_TIME_FIRST test +* @tc.type: FUNC +*/ +HWTEST_F(RdbGeneralStoreTest, Sync001, TestSize.Level1) +{ + GeneralStore::Devices devices; + MockQuery query; + GeneralStore::DetailAsync async; + SyncParam syncParam; + syncParam.mode = GeneralStore::CLOUD_TIME_FIRST; + + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); + auto [result1, result2] = store->Sync(devices, query, async, syncParam); + EXPECT_EQ(result1, GeneralError::E_OK); + syncParam.mode = GeneralStore::NEARBY_END; + std::tie(result1, result2) = store->Sync(devices, query, async, syncParam); + EXPECT_EQ(result1, GeneralError::E_ERROR); + syncParam.mode = GeneralStore::NEARBY_PULL_PUSH; + std::tie(result1, result2) = store->Sync(devices, query, async, syncParam); + EXPECT_EQ(result1, GeneralError::E_OK); +} + +/** +* @tc.name: Sync +* @tc.desc: RdbGeneralStore Sync DistributedTable test +* @tc.type: FUNC +*/ +HWTEST_F(RdbGeneralStoreTest, Sync002, TestSize.Level1) +{ + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); + ASSERT_NE(store, nullptr); + + GeneralStore::Devices devices; + RdbQuery query; + GeneralStore::DetailAsync async; + SyncParam syncParam; + auto [result1, result2] = store->Sync(devices, query, async, syncParam); + EXPECT_EQ(result1, GeneralError::E_OK); +} + /** * @tc.name: PreSharing * @tc.desc: RdbGeneralStore PreSharing function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, PreSharing, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); MockQuery query; auto [errCode, result] = store->PreSharing(query); EXPECT_NE(errCode, GeneralError::E_OK); EXPECT_EQ(result, nullptr); } +/** +* @tc.name: PreSharing +* @tc.desc: RdbGeneralStore PreSharing function test, return E_INVALID_ARGS. +* @tc.type: FUNC +*/ +HWTEST_F(RdbGeneralStoreTest, PreSharing001, TestSize.Level1) +{ + MockQuery query; + query.lastResult = true; + auto [errCode, result] = store->PreSharing(query); + EXPECT_EQ(errCode, GeneralError::E_INVALID_ARGS); + EXPECT_EQ(result, nullptr); +} + +/** +* @tc.name: PreSharing +* @tc.desc: RdbGeneralStore PreSharing function delegate is nullptr test. +* @tc.type: FUNC +*/ +HWTEST_F(RdbGeneralStoreTest, PreSharing002, TestSize.Level1) +{ + MockQuery query; + DistributedRdb::PredicatesMemo predicates; + predicates.devices_ = { "device1" }; + predicates.tables_ = { "tables1" }; + query.lastResult = true; + query.MakeQuery(predicates); + auto [errCode, result] = store->PreSharing(query); + EXPECT_EQ(errCode, GeneralError::E_ALREADY_CLOSED); + EXPECT_EQ(result, nullptr); +} + +/** +* @tc.name: PreSharing +* @tc.desc: RdbGeneralStore PreSharing function E_CLOUD_DISABLED test. +* @tc.type: FUNC +*/ +HWTEST_F(RdbGeneralStoreTest, PreSharing003, TestSize.Level1) +{ + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); + ASSERT_NE(store, nullptr); + MockQuery query; + DistributedRdb::PredicatesMemo predicates; + predicates.devices_ = { "device1" }; + predicates.tables_ = { "tables1" }; + query.lastResult = true; + query.MakeQuery(predicates); + auto [errCode, result] = store->PreSharing(query); + EXPECT_EQ(errCode, GeneralError::E_CLOUD_DISABLED); + ASSERT_EQ(result, nullptr); +} + /** * @tc.name: ExtractExtend * @tc.desc: RdbGeneralStore ExtractExtend function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, ExtractExtend, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); RdbGeneralStore::VBucket extend = { { "#gid", { "0000000" } }, { "#flag", { true } }, - { "#value", { int64_t(100) } }, { "#float", { double(100) } }, { "#cloud_gid", { "cloud_gid" } } }; + { "#value", { int64_t(100) } }, { "#float", { double(100) } }, { "#cloud_gid", { "cloud_gid" } }, + { "cloud_gid", { "" } } }; DistributedData::VBuckets extends = { { extend } }; auto result = store->ExtractExtend(extends); EXPECT_EQ(result.size(), extends.size()); @@ -776,13 +775,9 @@ HWTEST_F(RdbGeneralStoreTest, ExtractExtend, TestSize.Level1) * @tc.name: Clean * @tc.desc: RdbGeneralStore Clean function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Clean, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string tableName = "tableName"; std::vector devices = { "device1", "device2" }; auto result = store->Clean(devices, -1, tableName); @@ -792,8 +787,8 @@ HWTEST_F(RdbGeneralStoreTest, Clean, TestSize.Level1) result = store->Clean(devices, GeneralStore::CLOUD_INFO, tableName); EXPECT_EQ(result, GeneralError::E_ALREADY_CLOSED); - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); result = store->Clean(devices, GeneralStore::CLOUD_INFO, tableName); EXPECT_EQ(result, GeneralError::E_OK); result = store->Clean(devices, GeneralStore::CLOUD_DATA, tableName); @@ -802,7 +797,7 @@ HWTEST_F(RdbGeneralStoreTest, Clean, TestSize.Level1) result = store->Clean(devices1, GeneralStore::NEARBY_DATA, tableName); EXPECT_EQ(result, GeneralError::E_OK); - g_testResult = true; + MockRelationalStoreDelegate::gTestResult = true; result = store->Clean(devices, GeneralStore::CLOUD_INFO, tableName); EXPECT_EQ(result, GeneralError::E_ERROR); result = store->Clean(devices, GeneralStore::CLOUD_DATA, tableName); @@ -817,13 +812,9 @@ HWTEST_F(RdbGeneralStoreTest, Clean, TestSize.Level1) * @tc.name: Watch * @tc.desc: RdbGeneralStore Watch and Unwatch function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Watch, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); MockGeneralWatcher watcher; auto result = store->Watch(GeneralWatcher::Origin::ORIGIN_CLOUD, watcher); EXPECT_EQ(result, GeneralError::E_INVALID_ARGS); @@ -845,13 +836,9 @@ HWTEST_F(RdbGeneralStoreTest, Watch, TestSize.Level1) * @tc.name: OnChange * @tc.desc: RdbGeneralStore OnChange function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, OnChange, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); MockGeneralWatcher watcher; MockStoreChangedData data; DistributedDB::ChangedData changedData; @@ -865,12 +852,54 @@ HWTEST_F(RdbGeneralStoreTest, OnChange, TestSize.Level1) EXPECT_EQ(result, GeneralError::E_OK); } +/** +* @tc.name: OnChange001 +* @tc.desc: RdbGeneralStore OnChange function test +* @tc.type: FUNC +*/ +HWTEST_F(RdbGeneralStoreTest, OnChange001, TestSize.Level1) +{ + MockGeneralWatcher watcher; + MockStoreChangedData data; + DistributedDB::ChangedData changedData; + changedData.primaryData[0] = { { std::monostate{}, 42, 3.14, "hello", true }, + { Bytes{ 1, 2, 3, 4 }, + DistributedDB::Asset{ 1, "zhangsan", "123", "/data/test", "file://xxx", "123", "100", "100", "999", + static_cast(AssetOpType::NO_CHANGE), static_cast(AssetStatus::NORMAL), 0 }, + Bytes{ 5, 6, 7, 8 } }, + { int64_t(-123), 2.718, 100, 0.001 } }; + changedData.primaryData[1] = { { std::monostate{}, 42, 3.14, "hello", true }, + { Bytes{ 1, 2, 3, 4 }, + DistributedDB::Asset{ 1, "zhangsan", "123", "/data/test", "file://xxx", "123", "100", "100", "999", + static_cast(AssetOpType::NO_CHANGE), static_cast(AssetStatus::NORMAL), 0 }, + Bytes{ 5, 6, 7, 8 } }, + { int64_t(-123), 2.718, 100, 0.001 } }; + changedData.primaryData[2] = { { "DELETE#ALL_CLOUDDATA", std::monostate{}, 42, 3.14, "hello", true }, + { Bytes{ 1, 2, 3, 4 }, + DistributedDB::Asset{ 1, "zhangsan", "123", "/data/test", "file://xxx", "123", "100", "100", "999", + static_cast(AssetOpType::NO_CHANGE), static_cast(AssetStatus::NORMAL), 0 }, + Bytes{ 5, 6, 7, 8 } }, + { int64_t(-123), 2.718, 100, 0.001 } }; + changedData.field = { "name", "age" }; + changedData.tableName = "test"; + DistributedDB::ChangedData changedDataTmp; + changedDataTmp = changedData; + auto result = store->Watch(GeneralWatcher::Origin::ORIGIN_ALL, watcher); + EXPECT_EQ(result, GeneralError::E_OK); + store->observer_.OnChange(data); + store->observer_.OnChange(DistributedDB::Origin::ORIGIN_CLOUD, "originalId", std::move(changedData)); + EXPECT_EQ(watcher.primaryFields_[changedDataTmp.tableName], *(changedDataTmp.field.begin())); + store->observer_.OnChange(DistributedDB::Origin::ORIGIN_LOCAL, "originalId", std::move(changedDataTmp)); + ASSERT_NE(watcher.origin_.id.size(), 0); + EXPECT_EQ(watcher.origin_.id[0], "originalId"); + result = store->Unwatch(GeneralWatcher::Origin::ORIGIN_ALL, watcher); + EXPECT_EQ(result, GeneralError::E_OK); +} + /** * @tc.name: Release * @tc.desc: RdbGeneralStore Release and AddRef function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, Release, TestSize.Level1) { @@ -897,28 +926,27 @@ HWTEST_F(RdbGeneralStoreTest, Release, TestSize.Level1) * @tc.name: SetDistributedTables * @tc.desc: RdbGeneralStore SetDistributedTables function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, SetDistributedTables, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::vector tables = { "table1", "table2" }; - int32_t type = 0; + int32_t type = DistributedTableType::DISTRIBUTED_DEVICE; std::vector references; auto result = store->SetDistributedTables(tables, type, references); EXPECT_EQ(result, GeneralError::E_ALREADY_CLOSED); - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); result = store->SetDistributedTables(tables, type, references); EXPECT_EQ(result, GeneralError::E_OK); std::vector test = { "test" }; result = store->SetDistributedTables(test, type, references); EXPECT_EQ(result, GeneralError::E_ERROR); - g_testResult = true; + MockRelationalStoreDelegate::gTestResult = true; + result = store->SetDistributedTables(tables, type, references); + EXPECT_EQ(result, GeneralError::E_OK); + type = DistributedTableType::DISTRIBUTED_CLOUD; result = store->SetDistributedTables(tables, type, references); EXPECT_EQ(result, GeneralError::E_ERROR); } @@ -927,21 +955,17 @@ HWTEST_F(RdbGeneralStoreTest, SetDistributedTables, TestSize.Level1) * @tc.name: SetTrackerTable * @tc.desc: RdbGeneralStore SetTrackerTable function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, SetTrackerTable, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string tableName = "tableName"; std::set trackerColNames = { "col1", "col2" }; std::set extendColNames = { "extendColName1", "extendColName2" }; auto result = store->SetTrackerTable(tableName, trackerColNames, extendColNames); EXPECT_EQ(result, GeneralError::E_ALREADY_CLOSED); - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); result = store->SetTrackerTable(tableName, trackerColNames, extendColNames); EXPECT_EQ(result, GeneralError::E_OK); result = store->SetTrackerTable("WITH_INVENTORY_DATA", trackerColNames, extendColNames); @@ -954,17 +978,13 @@ HWTEST_F(RdbGeneralStoreTest, SetTrackerTable, TestSize.Level1) * @tc.name: RemoteQuery * @tc.desc: RdbGeneralStore RemoteQuery function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, RemoteQuery, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string device = "device"; DistributedDB::RemoteCondition remoteCondition; - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); auto result = store->RemoteQuery("test", remoteCondition); EXPECT_EQ(result, nullptr); result = store->RemoteQuery(device, remoteCondition); @@ -975,13 +995,9 @@ HWTEST_F(RdbGeneralStoreTest, RemoteQuery, TestSize.Level1) * @tc.name: ConvertStatus * @tc.desc: RdbGeneralStore ConvertStatus function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, ConvertStatus, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); auto result = store->ConvertStatus(DBStatus::OK); EXPECT_EQ(result, GeneralError::E_OK); result = store->ConvertStatus(DBStatus::CLOUD_NETWORK_ERROR); @@ -1006,15 +1022,12 @@ HWTEST_F(RdbGeneralStoreTest, ConvertStatus, TestSize.Level1) * @tc.name: QuerySql * @tc.desc: RdbGeneralStore QuerySql function test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, QuerySql, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); ASSERT_NE(store, nullptr); - MockRelationalStoreDelegate mockDelegate; - store->delegate_ = &mockDelegate; auto [err1, result1] = store->QuerySql("", std::move(g_RdbValues)); EXPECT_EQ(err1, GeneralError::E_ERROR); EXPECT_TRUE(result1.empty()); @@ -1028,13 +1041,9 @@ HWTEST_F(RdbGeneralStoreTest, QuerySql, TestSize.Level1) * @tc.name: BuildSqlWhenCloumnEmpty * @tc.desc: test buildsql method when cloumn empty * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, BuildSqlWhenCloumnEmpty, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "mock_table"; std::string statement = "mock_statement"; std::vector columns; @@ -1048,13 +1057,9 @@ HWTEST_F(RdbGeneralStoreTest, BuildSqlWhenCloumnEmpty, TestSize.Level1) * @tc.name: BuildSqlWhenParamValid * @tc.desc: test buildsql method when param valid * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, BuildSqlWhenParamValid, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); std::string table = "mock_table"; std::string statement = "mock_statement"; std::vector columns; @@ -1071,13 +1076,9 @@ HWTEST_F(RdbGeneralStoreTest, BuildSqlWhenParamValid, TestSize.Level1) * @tc.name: LockAndUnLockCloudDBTest * @tc.desc: lock and unlock cloudDB test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, LockAndUnLockCloudDBTest, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); auto result = store->LockCloudDB(); EXPECT_EQ(result.first, 1); EXPECT_EQ(result.second, 0); @@ -1089,13 +1090,9 @@ HWTEST_F(RdbGeneralStoreTest, LockAndUnLockCloudDBTest, TestSize.Level1) * @tc.name: InFinishedTest * @tc.desc: isFinished test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, InFinishedTest, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedRdb::RdbGeneralStore::SyncId syncId = 1; bool isFinished = store->IsFinished(syncId); EXPECT_TRUE(isFinished); @@ -1105,13 +1102,9 @@ HWTEST_F(RdbGeneralStoreTest, InFinishedTest, TestSize.Level1) * @tc.name: GetRdbCloudTest * @tc.desc: getRdbCloud test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, GetRdbCloudTest, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); auto rdbCloud = store->GetRdbCloud(); EXPECT_EQ(rdbCloud, nullptr); } @@ -1120,13 +1113,9 @@ HWTEST_F(RdbGeneralStoreTest, GetRdbCloudTest, TestSize.Level1) * @tc.name: RegisterDetailProgressObserverTest * @tc.desc: RegisterDetailProgressObserver test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, RegisterDetailProgressObserverTest, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedData::GeneralStore::DetailAsync async; auto result = store->RegisterDetailProgressObserver(async); EXPECT_EQ(result, GeneralError::E_OK); @@ -1136,13 +1125,9 @@ HWTEST_F(RdbGeneralStoreTest, RegisterDetailProgressObserverTest, TestSize.Level * @tc.name: GetFinishTaskTest * @tc.desc: GetFinishTask test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, GetFinishTaskTest, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedRdb::RdbGeneralStore::SyncId syncId = 1; auto result = store->GetFinishTask(syncId); ASSERT_NE(result, nullptr); @@ -1152,16 +1137,27 @@ HWTEST_F(RdbGeneralStoreTest, GetFinishTaskTest, TestSize.Level1) * @tc.name: GetCBTest * @tc.desc: GetCB test * @tc.type: FUNC -* @tc.require: -* @tc.author: SQL */ HWTEST_F(RdbGeneralStoreTest, GetCBTest, TestSize.Level1) { - auto store = new (std::nothrow) RdbGeneralStore(metaData_); - ASSERT_NE(store, nullptr); DistributedRdb::RdbGeneralStore::SyncId syncId = 1; auto result = store->GetCB(syncId); ASSERT_NE(result, nullptr); } + +/** +* @tc.name: UpdateDBStatus +* @tc.desc: UpdateDBStatus test +* @tc.type: FUNC +*/ +HWTEST_F(RdbGeneralStoreTest, UpdateDBStatus, TestSize.Level1) +{ + auto result = store->UpdateDBStatus(); + EXPECT_EQ(result, E_ALREADY_CLOSED); + metaData_.storeId = "mock"; + store = std::make_shared(metaData_); + result = store->UpdateDBStatus(); + EXPECT_EQ(result, E_OK); +} } // namespace DistributedRDBTest } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_service_impl_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_service_impl_test.cpp new file mode 100644 index 00000000..abe24883 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_service_impl_test.cpp @@ -0,0 +1,2464 @@ +/* + * 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 "account/account_delegate.h" +#include "bootstrap.h" +#include "checker_mock.h" +#include "cloud/change_event.h" +#include "cloud/schema_meta.h" +#include "crypto/crypto_manager.h" +#include "device_manager_adapter.h" +#include "device_matrix.h" +#include "event_center.h" +#include "ipc_skeleton.h" +#include "metadata/capability_meta_data.h" +#include "metadata/meta_data_manager.h" +#include "metadata/store_meta_data.h" +#include "metadata/store_meta_data_local.h" +#include "metadata/store_debug_info.h" +#include "mock/device_manager_adapter_mock.h" +#include "mock/db_store_mock.h" +#include "mock/general_store_mock.h" +#include "store/general_value.h" +#include "rdb_service_impl.h" +#include "rdb_types.h" +#include "relational_store_manager.h" +#include "gtest/gtest.h" +#include "directory/directory_manager.h" + +using namespace OHOS::DistributedRdb; +using namespace OHOS::DistributedData; +using namespace DistributedDB; +using namespace testing::ext; +using namespace testing; +using namespace std; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; + +namespace OHOS::Test { +namespace DistributedRDBTest { + +static constexpr const char *TEST_BUNDLE = "test_rdb_service_impl_bundleName"; +static constexpr const char *TEST_APPID = "test_rdb_service_impl_appid"; +static constexpr const char *TEST_STORE = "test_rdb_service_impl_store"; +static constexpr int32_t KEY_LENGTH = 32; +static constexpr uint32_t DELY_TIME = 10000; + +class RdbServiceImplTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + static void InitMetaData(); + static void InitMapping(StoreMetaMapping &meta); + void SetUp(); + void TearDown(); + static std::vector Random(int32_t len); +protected: + static std::shared_ptr dbStoreMock_; + static StoreMetaData metaData_; + static CheckerMock checkerMock_; + static inline std::shared_ptr deviceManagerAdapterMock = nullptr; + static void InitMetaDataManager(); +}; + +std::shared_ptr RdbServiceImplTest::dbStoreMock_ = std::make_shared(); +StoreMetaData RdbServiceImplTest::metaData_; +CheckerMock RdbServiceImplTest::checkerMock_; + +void RdbServiceImplTest::InitMetaData() +{ + metaData_.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData_.appId = TEST_APPID; + metaData_.bundleName = TEST_BUNDLE; + metaData_.tokenId = OHOS::IPCSkeleton::GetCallingTokenID(); + metaData_.user = std::to_string(AccountDelegate::GetInstance()->GetUserByToken(metaData_.tokenId)); + metaData_.area = OHOS::DistributedKv::EL1; + metaData_.instanceId = 0; + metaData_.isAutoSync = true; + metaData_.storeType = DistributedRdb::RDB_DEVICE_COLLABORATION; + metaData_.storeId = TEST_STORE; + metaData_.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData_) + "/" + TEST_STORE; +} + +void RdbServiceImplTest::InitMapping(StoreMetaMapping &metaMapping) +{ + metaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaMapping.user = "100"; + metaMapping.bundleName = "bundleName"; + metaMapping.storeId = "storeName"; +} + +void RdbServiceImplTest::InitMetaDataManager() +{ + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + MetaDataManager::GetInstance().SetSyncer([](const auto &, auto) { + DeviceMatrix::GetInstance().OnChanged(DeviceMatrix::META_STORE_MASK); + }); +} + +void RdbServiceImplTest::SetUpTestCase() +{ + deviceManagerAdapterMock = std::make_shared(); + BDeviceManagerAdapter::deviceManagerAdapter = deviceManagerAdapterMock; + DeviceInfo deviceInfo; + deviceInfo.uuid = "ABCD"; + EXPECT_CALL(*deviceManagerAdapterMock, GetLocalDevice()).WillRepeatedly(Return(deviceInfo)); + EXPECT_CALL(*deviceManagerAdapterMock, GetUuidByNetworkId(_)).WillRepeatedly(Return(deviceInfo.uuid)); + EXPECT_CALL(*deviceManagerAdapterMock, CalcClientUuid(_, _)).WillRepeatedly(Return(deviceInfo.uuid)); + EXPECT_CALL(*deviceManagerAdapterMock, ToUUID(deviceInfo.uuid)).WillRepeatedly(Return(deviceInfo.uuid)); + + InitMetaData(); + Bootstrap::GetInstance().LoadCheckers(); + CryptoManager::GetInstance().GenerateRootKey(); + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); +} + +void RdbServiceImplTest::TearDownTestCase() +{ + deviceManagerAdapterMock = nullptr; + BDeviceManagerAdapter::deviceManagerAdapter = nullptr; +} + +void RdbServiceImplTest::SetUp() +{ +} + +void RdbServiceImplTest::TearDown() +{ +} + +std::vector RdbServiceImplTest::Random(int32_t len) +{ + std::random_device randomDevice; + std::uniform_int_distribution distribution(0, std::numeric_limits::max()); + std::vector key(len); + for (uint32_t i = 0; i < len; i++) { + key[i] = static_cast(distribution(randomDevice)); + } + return key; +} + +/** +* @tc.name: OnRemoteRequest001 +* @tc.desc: ResolveAutoLaunch LoadMeta Failed. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, ResolveAutoLaunch001, TestSize.Level0) +{ + auto localId = DmAdapter::GetInstance().GetLocalDevice().uuid; + DistributedDB::AutoLaunchParam param; + RdbServiceImpl service; + + std::string identifier = "test_identifier"; + int32_t result = service.ResolveAutoLaunch(identifier, param); + EXPECT_EQ(result, false); +} + +/** +* @tc.name: ResolveAutoLaunch002 +* @tc.desc: ResolveAutoLaunch no meta. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, ResolveAutoLaunch002, TestSize.Level0) +{ + InitMetaDataManager(); + auto localId = DmAdapter::GetInstance().GetLocalDevice().uuid; + DistributedDB::AutoLaunchParam param; + RdbServiceImpl service; + + std::string identifier = "test_identifier"; + int32_t result = service.ResolveAutoLaunch(identifier, param); + EXPECT_EQ(result, false); +} + +/** +* @tc.name: ResolveAutoLaunch003 +* @tc.desc: ResolveAutoLaunch has meta, identifier not match. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, ResolveAutoLaunch003, TestSize.Level0) +{ + auto ret = MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false); + EXPECT_EQ(ret, true); + StoreMetaData meta; + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta.user = std::to_string(AccountDelegate::GetInstance()->GetUserByToken(meta.tokenId)); + meta.bundleName = TEST_BUNDLE; + meta.storeId = "ResolveAutoLaunch003"; + meta.instanceId = 0; + meta.appId = TEST_APPID; + meta.tokenId = OHOS::IPCSkeleton::GetCallingTokenID(); + meta.area = OHOS::DistributedKv::EL1; + meta.isAutoSync = true; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKeyWithoutPath(), meta, false), true); + + DistributedDB::AutoLaunchParam param; + RdbServiceImpl service; + + std::string identifier = "test_identifier"; + int32_t result = service.ResolveAutoLaunch(identifier, param); + + EXPECT_EQ(result, false); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** +* @tc.name: ResolveAutoLaunch004 +* @tc.desc: ResolveAutoLaunch has meta, identifier match. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, ResolveAutoLaunch004, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + DistributedDB::AutoLaunchParam param; + RdbServiceImpl service; + RelationalStoreManager userMgr(metaData_.appId, metaData_.user, metaData_.storeId); + auto identifier = userMgr.GetRelationalStoreIdentifier(metaData_.user, metaData_.appId, metaData_.storeId, true); + + int32_t result = service.ResolveAutoLaunch(identifier, param); + + EXPECT_EQ(result, true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** +* @tc.name: ResolveAutoLaunch005 +* @tc.desc: ResolveAutoLaunch has meta, identifier match, is encrypt. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, ResolveAutoLaunch005, TestSize.Level0) +{ + auto meta = metaData_; + meta.isEncrypt = true; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKeyWithoutPath(), meta, false), true); + DistributedDB::AutoLaunchParam param; + RdbServiceImpl service; + RelationalStoreManager userMgr1(meta.appId, meta.user, meta.storeId); + auto identifier = userMgr1.GetRelationalStoreIdentifier(meta.user, meta.appId, meta.storeId, true); + + int32_t result = service.ResolveAutoLaunch(identifier, param); + + EXPECT_EQ(result, true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKeyWithoutPath(), false), true); +} + +/** +* @tc.name: ResolveAutoLaunch006 +* @tc.desc: test ObtainDistributedTableName, uuid exist. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, ResolveAutoLaunch006, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + RdbServiceImpl service; + auto deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + RdbSyncerParam param{ .bundleName_ = TEST_BUNDLE }; + auto ret = service.ObtainDistributedTableName(param, deviceId, TEST_STORE); + EXPECT_GT(ret.length(), 0); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** +* @tc.name: ObtainDistributedTableName001 +* @tc.desc: test ObtainDistributedTableName, uuid invalid. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, ObtainDistributedTableName001, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + RdbServiceImpl service; + RdbSyncerParam param; + auto ret = service.ObtainDistributedTableName(param, "invalid_device_id", TEST_STORE); + EXPECT_EQ(ret.length(), 0); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: RemoteQuery001 + * @tc.desc: test RemoteQuery, param invalid. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, RemoteQuery001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + param.hapName_ = "test/test"; + std::vector selectionArgs; + auto deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + auto ret = service.RemoteQuery(param, deviceId, "", selectionArgs); + EXPECT_EQ(ret.first, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: RemoteQuery002 + * @tc.desc: test RemoteQuery, when CheckAccess fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, RemoteQuery002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + std::vector selectionArgs; + auto deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + auto ret = service.RemoteQuery(param, deviceId, "", selectionArgs); + EXPECT_EQ(ret.first, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: RemoteQuery003 + * @tc.desc: test RemoteQuery, when CheckAccess pass but query failed. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, RemoteQuery003, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = "RemoteQuery003"; + std::vector selectionArgs; + auto deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + auto ret = service.RemoteQuery(param, deviceId, "", selectionArgs); + EXPECT_EQ(ret.first, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** +* @tc.name: TransferStringToHex001 +* @tc.desc: test TransferStringToHex, param empty. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, TransferStringToHex001, TestSize.Level0) +{ + RdbServiceImpl service; + auto ret = service.TransferStringToHex(""); + EXPECT_EQ(ret.length(), 0); +} + +/** +* @tc.name: GetCallbacks001 +* @tc.desc: test GetCallbacks. +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhaojh +*/ +HWTEST_F(RdbServiceImplTest, GetCallbacks001, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + RdbServiceImpl service; + auto ret = service.GetCallbacks(metaData_.tokenId, metaData_.storeId); + EXPECT_EQ(ret, nullptr); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: DoSync001 + * @tc.desc: Test DoSync when the store is null. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, DoSync001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + RdbService::Option option; + PredicatesMemo predicates; + AsyncDetail async; + + auto result = service.DoSync(param, option, predicates, async); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: DoSync002 + * @tc.desc: Test DoSync when meta sync is needed and succeeds. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, DoSync002, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.type_ = metaData_.storeType; + param.level_ = metaData_.securityLevel; + param.area_ = metaData_.area; + param.hapName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + param.isEncrypt_ = metaData_.isEncrypt; + param.isSearchable_ = metaData_.isSearchable; + param.haMode_ = metaData_.haMode; + param.asyncDownloadAsset_ = metaData_.asyncDownloadAsset; + + RdbService::Option option; + option.mode = DistributedData::GeneralStore::AUTO_SYNC_MODE; + option.seqNum = 1; + + PredicatesMemo predicates; + AsyncDetail async; + + auto result = service.DoSync(param, option, predicates, async); + EXPECT_EQ(result, RDB_ERROR); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: IsNeedMetaSync001 + * @tc.desc: Test IsNeedMetaSync when LoadMeta fails for CapMetaData. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, IsNeedMetaSync001, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + std::vector devices = {DmAdapter::GetInstance().ToUUID(metaData_.deviceId)}; + RdbServiceImpl service; + bool result = service.IsNeedMetaSync(metaData_, devices); + + EXPECT_EQ(result, true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: IsNeedMetaSync002 + * @tc.desc: Test IsNeedMetaSync when LoadMeta fails for StoreMetaData. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, IsNeedMetaSync002, TestSize.Level0) +{ + CapMetaData capMetaData; + auto capKey = CapMetaRow::GetKeyFor(metaData_.deviceId); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(std::string(capKey.begin(), capKey.end()), capMetaData), true); + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + std::vector devices = {DmAdapter::GetInstance().ToUUID(metaData_.deviceId)}; + RdbServiceImpl service; + bool result = service.IsNeedMetaSync(metaData_, devices); + + EXPECT_EQ(result, false); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: ProcessResult001 + * @tc.desc: Test ProcessResult when all results have DBStatus::OK. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, ProcessResult001, TestSize.Level0) +{ + RdbServiceImpl service; + std::map results = {{"device1", static_cast(DBStatus::OK)}, + {"device2", static_cast(DBStatus::OK)}}; + + auto result = service.ProcessResult(results); + + EXPECT_EQ(result.second.at("device1"), DBStatus::OK); + EXPECT_EQ(result.second.at("device2"), DBStatus::OK); +} + +/** + * @tc.name: ProcessResult002 + * @tc.desc: Test ProcessResult when some results have DBStatus::OK and others do not. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, ProcessResult002, TestSize.Level0) +{ + RdbServiceImpl service; + std::map results = {{"device1", static_cast(DBStatus::OK)}, + {"device2", static_cast(DBStatus::DB_ERROR)}, + {"device3", static_cast(DBStatus::OK)}}; + + auto result = service.ProcessResult(results); + + EXPECT_EQ(result.second.at("device1"), DBStatus::OK); + EXPECT_EQ(result.second.at("device2"), DBStatus::DB_ERROR); + EXPECT_EQ(result.second.at("device3"), DBStatus::OK); +} + +/** + * @tc.name: ProcessResult004 + * @tc.desc: Test ProcessResult with an empty results map. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, ProcessResult004, TestSize.Level0) +{ + RdbServiceImpl service; + std::map results; + + auto result = service.ProcessResult(results); + + EXPECT_EQ(result.first.size(), 0); + EXPECT_EQ(result.second.size(), 0); +} + +/** + * @tc.name: DoCompensateSync001 + * @tc.desc: Test DoCompensateSync when the event has valid bindInfo and COMPENSATE_SYNC event ID. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, DoCompensateSync001, TestSize.Level0) +{ + RdbServiceImpl service; + + int32_t eventId = 1; + DistributedData::BindEvent::BindEventInfo bindInfo; + bindInfo.bundleName = TEST_BUNDLE; + bindInfo.tokenId = metaData_.tokenId; + bindInfo.user = metaData_.uid; + bindInfo.storeName = TEST_STORE; + bindInfo.tableName = "test_table"; + bindInfo.primaryKey = {{"key1", "value1"}, {"key2", "value2"}}; + + BindEvent event(eventId, std::move(bindInfo)); + EventCenter::GetInstance().Subscribe(CloudEvent::LOCAL_CHANGE, [this] (const Event &event) { + auto &evt = static_cast(event); + auto mode = evt.GetMode(); + EXPECT_EQ(GeneralStore::GetPriorityLevel(GeneralStore::GetHighMode(static_cast(mode))), 1); + }); + service.DoCompensateSync(event); + EventCenter::GetInstance().Unsubscribe(CloudEvent::LOCAL_CHANGE); +} + +/** + * @tc.name: ReportStatistic001 + * @tc.desc: Test ReportStatistic when CheckAccess fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, ReportStatistic001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + RdbStatEvent statEvent; + + int32_t result = service.ReportStatistic(param, statEvent); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: ReportStatistic002 + * @tc.desc: Test ReportStatistic when CheckAccess success. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, ReportStatistic002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + RdbStatEvent statEvent; + + int32_t result = service.ReportStatistic(param, statEvent); + + EXPECT_EQ(result, OK); +} + +/** + * @tc.name: GetReuseDevice001 + * @tc.desc: Test GetReuseDevice when all devices are reusable. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, GetReuseDevice001, TestSize.Level0) +{ + RdbServiceImpl service; + std::vector devices = {"device1"}; + StoreMetaData metaData; + auto result = service.GetReuseDevice(devices, metaData); + EXPECT_EQ(result.size(), 0); +} + +/** + * @tc.name: DoAutoSync001 + * @tc.desc: Test DoAutoSync when the store is null. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, DoAutoSync001, TestSize.Level0) +{ + RdbServiceImpl service; + std::vector devices = {"device1"}; + DistributedData::Database dataBase; + std::vector tables = {"table1"}; + + auto result = service.DoAutoSync(devices, dataBase, tables); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: DoAutoSync002 + * @tc.desc: Test DoAutoSync when the store is null. + * @tc.type: FUNC + * @tc.require: + * @tc.author: my + */ +HWTEST_F(RdbServiceImplTest, DoAutoSync002, TestSize.Level0) +{ + StoreMetaMapping metaMapping; + InitMapping(metaMapping); + metaMapping.dataDir = "path"; + metaMapping.devicePath = "path1"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + RdbServiceImpl service; + std::vector devices = {"device1"}; + DistributedData::Database dataBase; + std::vector tables = {"table1"}; + dataBase.bundleName = "bundleName"; + dataBase.name = "storeName"; + dataBase.user = "100"; + auto result = service.DoAutoSync(devices, dataBase, tables); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: DoOnlineSync001 + * @tc.desc: Test DoOnlineSync when all tables have deviceSyncFields. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, DoOnlineSync001, TestSize.Level0) +{ + RdbServiceImpl service; + std::vector devices = {"device1"}; + DistributedData::Database dataBase; + dataBase.name = TEST_STORE; + + DistributedData::Table table1; + table1.name = "table1"; + table1.deviceSyncFields = {"field1", "field2"}; + DistributedData::Table table2; + table2.name = "table2"; + table2.deviceSyncFields = {}; + + dataBase.tables = {table1, table2}; + + auto result = service.DoOnlineSync(devices, dataBase); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: OnReady001 + * @tc.desc: Test OnReady when LoadMeta fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, OnReady001, TestSize.Level0) +{ + RdbServiceImpl service; + std::string device = "test_device"; + + int32_t result = service.OnReady(device); + EXPECT_EQ(result, 0); +} + +/** + * @tc.name: OnReady002 + * @tc.desc: Test OnReady when no databases have autoSyncType SYNC_ON_READY or SYNC_ON_CHANGE_READY. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, OnReady002, TestSize.Level0) +{ + RdbServiceImpl service; + std::string device = metaData_.deviceId; + + DistributedData::Database dataBase1; + dataBase1.name = "test_rdb_service_impl_sync_store2"; + dataBase1.bundleName = TEST_BUNDLE; + dataBase1.user = std::to_string(AccountDelegate::GetInstance()->GetUserByToken(metaData_.tokenId)); + dataBase1.autoSyncType = AutoSyncType::SYNC_ON_READY; + + DistributedData::Database dataBase2; + dataBase2.name = "test_rdb_service_impl_sync_store2"; + dataBase2.bundleName = TEST_BUNDLE; + dataBase2.user = std::to_string(AccountDelegate::GetInstance()->GetUserByToken(metaData_.tokenId)); + dataBase2.autoSyncType = AutoSyncType::SYNC_ON_CHANGE_READY; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(dataBase1.GetKey(), metaData_, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(dataBase2.GetKey(), metaData_, true), true); + int32_t result = service.OnReady(device); + + EXPECT_EQ(result, 0); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(dataBase1.GetKey(), metaData_, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(dataBase2.GetKey(), metaData_, true), true); +} + +/** + * @tc.name: AfterOpen001 + * @tc.desc: Test AfterOpen when CheckParam not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, AfterOpen001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + param.hapName_ = "test/test"; + int32_t result = service.AfterOpen(param); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: AfterOpen002 + * @tc.desc: Test AfterOpen when CheckAccess not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, AfterOpen002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + int32_t result = service.AfterOpen(param); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: AfterOpen003 + * @tc.desc: Test AfterOpen when CheckAccess pass and CheckParam pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, AfterOpen003, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + int32_t result = service.AfterOpen(param); + + EXPECT_EQ(result, RDB_OK); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: AfterOpen004 + * @tc.desc: Test AfterOpen when CheckAccess pass and CheckParam pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, AfterOpen004, TestSize.Level0) +{ + metaData_.isSearchable = true; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + int32_t result = service.AfterOpen(param); + + EXPECT_EQ(result, RDB_OK); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: NotifyDataChange001 + * @tc.desc: Test NotifyDataChange when CheckParam not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, NotifyDataChange001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + param.hapName_ = "test/test"; + RdbChangedData rdbChangedData; + RdbNotifyConfig rdbNotifyConfig; + int32_t result = service.NotifyDataChange(param, rdbChangedData, rdbNotifyConfig); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: NotifyDataChange002 + * @tc.desc: Test NotifyDataChange when CheckAccess not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, NotifyDataChange002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + RdbChangedData rdbChangedData; + RdbNotifyConfig rdbNotifyConfig; + int32_t result = service.NotifyDataChange(param, rdbChangedData, rdbNotifyConfig); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: NotifyDataChange003 + * @tc.desc: Test NotifyDataChange when Check pass. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, NotifyDataChange003, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.storeName_ = "validStoreName"; + param.bundleName_ = "validBundleName"; + param.user_ = "validUser"; + param.hapName_ = "validHapName"; + param.customDir_ = "dir1/dir2"; + RdbChangedData rdbChangedData; + RdbNotifyConfig rdbNotifyConfig; + rdbNotifyConfig.delay_ = 0; + int32_t result = service.NotifyDataChange(param, rdbChangedData, rdbNotifyConfig); + EXPECT_EQ(result, RDB_OK); + rdbNotifyConfig.delay_ = DELY_TIME; + result = service.NotifyDataChange(param, rdbChangedData, rdbNotifyConfig); + EXPECT_EQ(result, RDB_OK); +} + +/** + * @tc.name: SetSearchable001 + * @tc.desc: Test SetSearchable when CheckAccess fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, SetSearchable001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + + bool isSearchable = true; + int32_t result = service.SetSearchable(param, isSearchable); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: SetSearchable002 + * @tc.desc: Test SetSearchable when CheckAccess succeeds and PostSearchEvent is called. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, SetSearchable002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + + bool isSearchable = true; + int32_t result = service.SetSearchable(param, isSearchable); + + EXPECT_EQ(result, RDB_OK); +} + +/** + * @tc.name: GetPassword001 + * @tc.desc: Test GetPassword when CheckAccess fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, GetPassword001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + std::vector> password; + + int32_t result = service.GetPassword(param, password); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: GetPassword002 + * @tc.desc: Test GetPassword when no meta data is found. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, GetPassword002, TestSize.Level0) +{ + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + auto meta = metaData_; + meta.isEncrypt = true; + auto sKey = Random(KEY_LENGTH); + ASSERT_FALSE(sKey.empty()); + SecretKeyMetaData secretKey; + CryptoManager::CryptoParams encryptParams; + secretKey.sKey = CryptoManager::GetInstance().Encrypt(sKey, encryptParams); + secretKey.area = encryptParams.area; + secretKey.storeType = meta.storeType; + secretKey.nonce = encryptParams.nonce; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetSecretKey(), secretKey, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = meta.bundleName; + param.storeName_ = meta.storeId; + std::vector> password; + int32_t result = service.GetPassword(param, password); + + EXPECT_EQ(result, RDB_OK); + ASSERT_GT(password.size(), 0); + EXPECT_EQ(password.at(0), sKey); + MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); + MetaDataManager::GetInstance().DelMeta(meta.GetSecretKey(), true); +} + +/** + * @tc.name: GetPassword003 + * @tc.desc: Test GetPassword when decryption fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, GetPassword003, TestSize.Level0) +{ + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + auto meta = metaData_; + meta.isEncrypt = true; + auto sKey = Random(KEY_LENGTH); + ASSERT_FALSE(sKey.empty()); + SecretKeyMetaData secretKey; + secretKey.sKey = sKey; // Invalid key for decryption + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetSecretKey(), secretKey, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = meta.bundleName; + param.storeName_ = meta.storeId; + std::vector> password; + + int32_t result = service.GetPassword(param, password); + + EXPECT_EQ(result, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetSecretKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); +} + +/** + * @tc.name: GetPassword004 + * @tc.desc: Test GetPassword when no meta data is found. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, GetPassword004, TestSize.Level0) +{ + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + auto meta = metaData_; + meta.isEncrypt = true; + auto sKey = Random(KEY_LENGTH); + ASSERT_FALSE(sKey.empty()); + SecretKeyMetaData secretKey; + CryptoManager::CryptoParams encryptParams; + secretKey.sKey = CryptoManager::GetInstance().Encrypt(sKey, encryptParams); + secretKey.area = encryptParams.area; + secretKey.storeType = meta.storeType; + secretKey.nonce = encryptParams.nonce; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetCloneSecretKey(), secretKey, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = meta.bundleName; + param.storeName_ = meta.storeId; + param.type_ = meta.storeType; + std::vector> password; + + int32_t result = service.GetPassword(param, password); + + EXPECT_EQ(result, RDB_OK); + ASSERT_GT(password.size(), 0); + EXPECT_EQ(password.at(0), sKey); + MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); + MetaDataManager::GetInstance().DelMeta(meta.GetCloneSecretKey(), true); +} + +/** + * @tc.name: GetPassword005 + * @tc.desc: Test GetPassword when no meta data. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, GetPassword005, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + param.type_ = StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN; + std::vector> password; + + int32_t result = service.GetPassword(param, password); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: GetPassword006 + * @tc.desc: Test GetPassword when meta data is found. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, GetPassword006, TestSize.Level0) +{ + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + auto meta = metaData_; + meta.isEncrypt = true; + auto sKey = Random(KEY_LENGTH); + ASSERT_FALSE(sKey.empty()); + SecretKeyMetaData secretKey; + CryptoManager::CryptoParams encryptParams; + secretKey.sKey = CryptoManager::GetInstance().Encrypt(sKey, encryptParams); + secretKey.area = encryptParams.area; + secretKey.storeType = meta.storeType; + secretKey.nonce = encryptParams.nonce; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetCloneSecretKey(), secretKey, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = meta.bundleName; + param.storeName_ = meta.storeId; + param.type_ = meta.storeType; + param.customDir_ = "../../../base/haps/entry/files/.backup/textautofill"; + std::vector> password; + + int32_t result = service.GetPassword(param, password); + + EXPECT_EQ(result, RDB_OK); + ASSERT_GT(password.size(), 0); + EXPECT_EQ(password.at(0), sKey); + MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); + MetaDataManager::GetInstance().DelMeta(meta.GetCloneSecretKey(), true); +} + +/** + * @tc.name: SetDistributedTables001 + * @tc.desc: Test SetDistributedTables when CheckAccess not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, SetDistributedTables001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + std::vector tables; + std::vector references; + + int32_t result = service.SetDistributedTables(param, tables, references, false); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: SetDistributedTables002 + * @tc.desc: Test SetDistributedTables when type is search. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, SetDistributedTables002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + param.type_ = StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN; + std::vector tables; + std::vector references; + + int32_t result = + service.SetDistributedTables(param, tables, references, false, + DistributedTableType::DISTRIBUTED_SEARCH); + EXPECT_EQ(result, RDB_OK); +} + +/** + * @tc.name: SetDistributedTables003 + * @tc.desc: Test SetDistributedTables when type is search. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, SetDistributedTables003, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + param.type_ = StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN; + param.hapName_ = "test/test"; + std::vector tables; + std::vector references; + + int32_t result = + service.SetDistributedTables(param, tables, references, false, + DistributedTableType::DISTRIBUTED_SEARCH); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: SetDistributedTables004 + * @tc.desc: Test SetDistributedTables when type is device. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, SetDistributedTables004, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = "SetDistributedTables004"; + param.type_ = StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN; + std::vector tables; + std::vector references; + + auto meta = service.GetStoreMetaData(param); + ASSERT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + + auto creator = [](const StoreMetaData &metaData) -> GeneralStore* { + auto store = new (std::nothrow) GeneralStoreMock(); + return store; + }; + AutoCache::GetInstance().RegCreator(DistributedRdb::RDB_DEVICE_COLLABORATION, creator); + + int32_t result = + service.SetDistributedTables(param, tables, references, false, + DistributedTableType::DISTRIBUTED_DEVICE); + EXPECT_EQ(result, RDB_OK); + ASSERT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); +} + +/** + * @tc.name: Sync001 + * @tc.desc: Test Sync when CheckAccess not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, Sync001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + RdbService::Option option {}; + PredicatesMemo predicates; + + int32_t result = service.Sync(param, option, predicates, nullptr); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: Sync002 + * @tc.desc: Test Sync when CheckParam not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, Sync002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + param.hapName_ = "test/test"; + RdbService::Option option {}; + PredicatesMemo predicates; + + int32_t result = service.Sync(param, option, predicates, nullptr); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: Sync003 + * @tc.desc: Test Sync when mode is nearby begin. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, Sync003, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = "Sync003"; + RdbService::Option option { DistributedData::GeneralStore::NEARBY_BEGIN }; + PredicatesMemo predicates; + + int32_t result = service.Sync(param, option, predicates, nullptr); + EXPECT_EQ(result, RDB_OK); +} + +/** + * @tc.name: Sync004 + * @tc.desc: Test Sync when mode is cloud begin. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, Sync004, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = "Sync004"; + RdbService::Option option { DistributedData::GeneralStore::CLOUD_BEGIN }; + PredicatesMemo predicates; + + int32_t result = service.Sync(param, option, predicates, nullptr); + EXPECT_EQ(result, RDB_OK); +} + + +/** + * @tc.name: QuerySharingResource001 + * @tc.desc: Test QuerySharingResource when CheckParam not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, QuerySharingResource001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + PredicatesMemo predicates; + std::vector columns; + auto result = service.QuerySharingResource(param, predicates, columns); + EXPECT_EQ(result.first, RDB_ERROR); +} + +/** + * @tc.name: BeforeOpen001 + * @tc.desc: Test BeforeOpen when CheckParam not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, BeforeOpen001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + param.hapName_ = "test/test"; + int32_t result = service.BeforeOpen(param); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: BeforeOpen002 + * @tc.desc: Test BeforeOpen when checkacess not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, BeforeOpen002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + int32_t result = service.BeforeOpen(param); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: BeforeOpen003 + * @tc.desc: Test BeforeOpen when checkacess pass and CheckParam pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, BeforeOpen003, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + int32_t result = service.BeforeOpen(param); + EXPECT_EQ(result, RDB_NO_META); +} + +/** + * @tc.name: BeforeOpen004 + * @tc.desc: Test BeforeOpen when checkacess pass and CheckParam pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, BeforeOpen004, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKey(), metaData_, true), true); + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + int32_t result = service.BeforeOpen(param); + EXPECT_EQ(result, RDB_OK); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKey(), true), true); +} + +/** + * @tc.name: Subscribe001 + * @tc.desc: Test Subscribe when option mode invalid. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, Subscribe001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + SubscribeOption option {}; + option.mode = SubscribeMode::SUBSCRIBE_MODE_MAX; + + int32_t result = service.Subscribe(param, option, nullptr); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: UnSubscribe001 + * @tc.desc: Test UnSubscribe when option mode invalid. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, UnSubscribe001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + SubscribeOption option {}; + option.mode = SubscribeMode::SUBSCRIBE_MODE_MAX; + + int32_t result = service.UnSubscribe(param, option, nullptr); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: GetDfxInfo001 + * @tc.desc: Test GetDfxInfo when CheckAccess not pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, GetDfxInfo001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + DistributedRdb::RdbDfxInfo dfxInfo; + + int32_t result = service.GetDfxInfo(param, dfxInfo); + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: GetDfxInfo002 + * @tc.desc: Test GetDfxInfo when CheckAccess pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, GetDfxInfo002, TestSize.Level0) +{ + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + auto meta = metaData_; + DistributedData::StoreDfxInfo dfxMeta; + dfxMeta.lastOpenTime = "test"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetDfxInfoKey(), dfxMeta, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = meta.bundleName; + param.storeName_ = meta.storeId; + param.type_ = meta.storeType; + param.customDir_ = "../../../base/haps/entry/files/.backup/textautofill"; + DistributedRdb::RdbDfxInfo dfxInfo; + int32_t result = service.GetDfxInfo(param, dfxInfo); + EXPECT_EQ(dfxInfo.lastOpenTime_, "test"); + EXPECT_EQ(result, RDB_OK); + MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); + MetaDataManager::GetInstance().DelMeta(meta.GetDfxInfoKey(), true); +} + +/** + * @tc.name: LockCloudContainer001 + * @tc.desc: Test LockCloudContainer when CheckAccess fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, LockCloudContainer001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + + auto result = service.LockCloudContainer(param); + + EXPECT_EQ(result.first, RDB_ERROR); + EXPECT_EQ(result.second, 0); +} + +/** + * @tc.name: LockCloudContainer002 + * @tc.desc: Test LockCloudContainer when CheckAccess succeeds and callback updates the result. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, LockCloudContainer002, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + + auto result = service.LockCloudContainer(param); + + // Simulate callback execution + EXPECT_EQ(result.first, RDB_ERROR); + EXPECT_EQ(result.second, 0); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: UnlockCloudContainer001 + * @tc.desc: Test UnlockCloudContainer when CheckAccess fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, UnlockCloudContainer001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + + int32_t result = service.UnlockCloudContainer(param); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: UnlockCloudContainer002 + * @tc.desc: Test UnlockCloudContainer when CheckAccess succeeds and callback updates the result. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, UnlockCloudContainer002, TestSize.Level0) +{ + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyWithoutPath(), metaData_, false), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + + int32_t result = service.UnlockCloudContainer(param); + + // Simulate callback execution + EXPECT_EQ(result, RDB_ERROR); // Assuming the callback sets status to RDB_OK + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyWithoutPath(), false), true); +} + +/** + * @tc.name: GetDebugInfo001 + * @tc.desc: Test GetDebugInfo when CheckAccess fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, GetDebugInfo001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + std::map debugInfo; + + int32_t result = service.GetDebugInfo(param, debugInfo); + + EXPECT_EQ(result, RDB_ERROR); + EXPECT_TRUE(debugInfo.empty()); +} + +/** + * @tc.name: GetDebugInfo002 + * @tc.desc: Test GetDebugInfo when CheckAccess pass. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, GetDebugInfo002, TestSize.Level0) +{ + auto meta = metaData_; + DistributedData::StoreDebugInfo debugMeta; + DistributedData::StoreDebugInfo::FileInfo fileInfo1; + fileInfo1.inode = 4; + fileInfo1.size = 5; + fileInfo1.dev = 6; + fileInfo1.mode = 7; + fileInfo1.uid = 8; + fileInfo1.gid = 9; + debugMeta.fileInfos.insert(std::pair{ "test1", fileInfo1 }); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetDebugInfoKey(), debugMeta, true), true); + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.type_ = metaData_.storeType; + param.level_ = metaData_.securityLevel; + param.area_ = metaData_.area; + param.hapName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + param.isEncrypt_ = metaData_.isEncrypt; + param.isSearchable_ = metaData_.isSearchable; + param.haMode_ = metaData_.haMode; + param.asyncDownloadAsset_ = metaData_.asyncDownloadAsset; + param.user_ = metaData_.user; + param.customDir_ = "../../../base/haps/entry/files/.backup/textautofill"; + std::map debugInfo; + int32_t result = service.GetDebugInfo(param, debugInfo); + EXPECT_EQ(result, RDB_OK); + RdbDebugInfo rdbInfo = debugInfo["test1"]; + EXPECT_EQ(rdbInfo.inode_, 4); + EXPECT_EQ(rdbInfo.size_, 5); + EXPECT_EQ(rdbInfo.dev_, 6); + EXPECT_EQ(rdbInfo.mode_, 7); + EXPECT_EQ(rdbInfo.uid_, 8); + EXPECT_EQ(rdbInfo.gid_, 9); + EXPECT_EQ(debugInfo.size(), 1); + MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true); + MetaDataManager::GetInstance().DelMeta(meta.GetDebugInfoKey(), true); +} + +/** + * @tc.name: VerifyPromiseInfo001 + * @tc.desc: Test VerifyPromiseInfo when LoadMeta fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, VerifyPromiseInfo001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: VerifyPromiseInfo002 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, VerifyPromiseInfo002, TestSize.Level0) +{ + StoreMetaDataLocal localMeta; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {tokenId}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {}; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.type_ = metaData_.storeType; + param.level_ = metaData_.securityLevel; + param.area_ = metaData_.area; + param.hapName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + param.isEncrypt_ = metaData_.isEncrypt; + param.isSearchable_ = metaData_.isSearchable; + param.haMode_ = metaData_.haMode; + param.asyncDownloadAsset_ = metaData_.asyncDownloadAsset; + param.user_ = metaData_.user; + + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_OK); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} + +/** + * @tc.name: VerifyPromiseInfo003 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, VerifyPromiseInfo003, TestSize.Level0) +{ + StoreMetaDataLocal localMeta; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {tokenId}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {}; + metaData_.dataDir = "path"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + StoreMetaMapping storeMetaMapping(metaData_); + storeMetaMapping.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData_) + "/" + TEST_STORE; + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaData_.bundleName; + param.type_ = metaData_.storeType; + param.level_ = metaData_.securityLevel; + param.area_ = metaData_.area; + param.hapName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + param.isEncrypt_ = metaData_.isEncrypt; + param.isSearchable_ = metaData_.isSearchable; + param.haMode_ = metaData_.haMode; + param.asyncDownloadAsset_ = metaData_.asyncDownloadAsset; + param.user_ = metaData_.user; + int32_t result = service.VerifyPromiseInfo(param); + EXPECT_EQ(result, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} + +/** + * @tc.name: CheckParam001 + * @tc.desc: Test VerifyPromiseInfo when bundleName_ contain '/'. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, CheckParam001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = "test/test"; + param.hapName_ = "test"; + param.storeName_ = "test"; + param.user_ = "test"; + param.customDir_ = "test"; + + bool result = service.IsValidParam(param); + + EXPECT_EQ(result, false); + param.bundleName_ = ".."; + + result = service.IsValidParam(param); + + EXPECT_EQ(result, false); + + param.bundleName_ = "test\\..test"; + + result = service.IsValidParam(param); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: CheckParam002 + * @tc.desc: Test VerifyPromiseInfo when hapName_ contain '/'. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, CheckParam002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = "test"; + param.hapName_ = "test/test"; + param.storeName_ = "test"; + param.user_ = "test"; + param.customDir_ = "test"; + + bool result = service.IsValidParam(param); + + EXPECT_EQ(result, false); + param.hapName_ = ".."; + + result = service.IsValidParam(param); + + EXPECT_EQ(result, false); + + param.hapName_ = "test\\..test"; + + result = service.IsValidParam(param); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: CheckParam003 + * @tc.desc: Test CheckParam when user_ contain '/'. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, CheckParam003, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = "test"; + param.hapName_ = "test"; + param.storeName_ = "test"; + param.user_ = "test/test"; + param.customDir_ = "test"; + + bool result = service.IsValidParam(param); + + EXPECT_EQ(result, false); + + param.user_ = ".."; + + result = service.IsValidParam(param); + + EXPECT_EQ(result, false); + param.user_ = "test\\..test"; + + result = service.IsValidParam(param); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: CheckParam004 + * @tc.desc: Test CheckParam. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, CheckParam004, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = "test"; + param.hapName_ = "test"; + param.storeName_ = "test"; + param.user_ = "test"; + param.customDir_ = "test"; + + bool result = service.IsValidParam(param); + + EXPECT_EQ(result, true); +} + +/** + * @tc.name: CheckParam005 + * @tc.desc: Test VerifyPromiseInfo when storename contain '/'. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, CheckParam005, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = "test"; + param.hapName_ = "test"; + param.storeName_ = "test/test"; + param.user_ = "test"; + param.customDir_ = "test"; + + bool result = service.IsValidParam(param); + + EXPECT_EQ(result, false); +} + +/** + * @tc.name: CheckParam006 + * @tc.desc: Test VerifyPromiseInfo when customDir is invalid. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, CheckParam006, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = "test"; + param.hapName_ = "test"; + param.storeName_ = "test"; + param.user_ = "test"; + param.customDir_ = "test/../../test/../../../"; + bool result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/../test/../../../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/../../../test/../../../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/./../../test/../../../../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/.../../../test/../../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); + + param.customDir_ = "test/test/../../../test/test/../test/../../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); + + param.customDir_ = "test/test/../../../../../test/test/test/"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = ""; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); + + param.customDir_ = "/test"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test//////////////////..///////../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); + + param.customDir_ = "test/..//////////////////..///////../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/..//////////////////..///////../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/..////./././///////////..///////../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/..////./././//////////////////../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); +} + +/** + * @tc.name: CheckParam007 + * @tc.desc: Test VerifyPromiseInfo when customDir is invalid and hapname is empty. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTest, CheckParam007, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = "test"; + param.hapName_ = ""; + param.storeName_ = "test"; + param.user_ = "test"; + param.customDir_ = "test/../../test/../../../"; + bool result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/../test/../../../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/../../../test/../../../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/../../../test/../../../../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/.../../test/../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); + + param.customDir_ = "test/test/../../../test/test/../test/../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); + + param.customDir_ = "test/test/../../../../../test/test/test/"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = ""; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); + + param.customDir_ = "/test"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test//////////////////..///////../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); + + param.customDir_ = "test/..//////////////////..///////../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/..//////////////////..///////../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/..////./././///////////..///////../../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, false); + + param.customDir_ = "test/..////./././///////////////////../"; + result = service.IsValidParam(param); + EXPECT_EQ(result, true); +} + +/** + * @tc.name: Delete_001 + * @tc.desc: Test Delete when param is invalid. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, Delete_001, TestSize.Level1) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = ""; + auto errCode = service.Delete(param); + EXPECT_EQ(errCode, RDB_ERROR); + param.bundleName_ = "bundleName"; + param.storeName_ = "storeName"; + param.user_ = "0"; + errCode = service.Delete(param); + EXPECT_EQ(errCode, RDB_OK); +} + +/** + * @tc.name: Delete_002 + * @tc.desc: Test Delete_002. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, Delete_002, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + metaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaMapping.user = "0"; + metaMapping.bundleName = "bundleName"; + metaMapping.storeId = "storeName"; + metaMapping.instanceId = 1; + + StoreMetaData meta1; + meta1.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta1.user = "0"; + meta1.bundleName = "bundleName"; + meta1.storeId = "storeName"; + meta1.dataDir = DirectoryManager::GetInstance().GetStorePath(meta1) + "/" + metaMapping.storeId; + meta1.instanceId = 1; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + + metaMapping.cloudPath = meta1.dataDir; + metaMapping.devicePath = meta1.dataDir; + metaMapping.searchPath = meta1.dataDir; + metaMapping.dataDir = meta1.dataDir; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + StoreMetaData meta2; + meta2.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta2.user = "0"; + meta2.bundleName = "bundleName"; + meta2.storeId = "storeName"; + meta2.dataDir ="path2"; + meta2.instanceId = 1; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta2.GetKey(), meta2, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaMapping.bundleName; + param.storeName_ = metaMapping.storeId; + param.user_ = metaMapping.user; + auto errCode = service.Delete(param); + EXPECT_EQ(errCode, RDB_OK); + MetaDataManager::GetInstance().LoadMeta(metaMapping.GetKey(), metaMapping, true); + EXPECT_EQ(metaMapping.cloudPath, ""); + EXPECT_EQ(metaMapping.devicePath, ""); + EXPECT_EQ(metaMapping.searchPath, ""); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta2.GetKey(), true), true); +} + +/** + * @tc.name: Delete_003 + * @tc.desc: Test Delete_003. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, Delete_003, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + metaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaMapping.user = "0"; + metaMapping.bundleName = "bundleName"; + metaMapping.storeId = "storeName"; + + StoreMetaData meta1; + meta1.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta1.user = "0"; + meta1.bundleName = "bundleName"; + meta1.storeId = "storeName"; + meta1.dataDir = DirectoryManager::GetInstance().GetStorePath(meta1) + "/" + metaMapping.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + + metaMapping.cloudPath = "path2"; + metaMapping.devicePath = "path2"; + metaMapping.searchPath = "path2"; + metaMapping.dataDir = meta1.dataDir; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + StoreMetaData meta2; + meta2.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta2.user = "0"; + meta2.bundleName = "bundleName"; + meta2.storeId = "storeName"; + meta2.dataDir ="path2"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta2.GetKey(), meta2, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaMapping.bundleName; + param.storeName_ = metaMapping.storeId; + param.user_ = metaMapping.user; + auto errCode = service.Delete(param); + EXPECT_EQ(errCode, RDB_OK); + MetaDataManager::GetInstance().LoadMeta(metaMapping.GetKey(), metaMapping, true); + EXPECT_EQ(metaMapping.cloudPath, "path2"); + EXPECT_EQ(metaMapping.devicePath, "path2"); + EXPECT_EQ(metaMapping.searchPath, "path2"); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta2.GetKey(), true), true); +} + +/** + * @tc.name: Delete_004 + * @tc.desc: Test Delete_004. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, Delete_004, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + metaMapping.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaMapping.user = "0"; + metaMapping.bundleName = "bundleName"; + metaMapping.storeId = "storeName"; + metaMapping.instanceId = 1; + + StoreMetaData meta1; + meta1.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta1.user = "0"; + meta1.bundleName = "bundleName"; + meta1.storeId = "storeName"; + meta1.dataDir = "path1"; + meta1.instanceId = 1; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta1.GetKey(), meta1, true), true); + + metaMapping.cloudPath = "path2"; + metaMapping.devicePath = "path2"; + metaMapping.searchPath = "path2"; + metaMapping.dataDir = DirectoryManager::GetInstance().GetStorePath(meta1) + "/" + metaMapping.storeId; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = metaMapping.bundleName; + param.storeName_ = metaMapping.storeId; + param.user_ = metaMapping.user; + auto errCode = service.Delete(param); + EXPECT_EQ(errCode, RDB_OK); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta1.GetKey(), true), true); +} + +/** + * @tc.name: RegisterEvent_001 + * @tc.desc: Test RegisterEvent_001. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, RegisterEvent_001, TestSize.Level1) +{ + RdbServiceImpl service; + DistributedData::StoreInfo storeInfo; + storeInfo.bundleName = "RegisterEvent_bundleName"; + storeInfo.storeName = "RegisterEvent_storeName"; + storeInfo.user = 100; + storeInfo.path = "RegisterEvent_path"; + auto event = std::make_unique(CloudEvent::CLOUD_SYNC, storeInfo); + EXPECT_NE(event, nullptr); + auto result = EventCenter::GetInstance().PostEvent(move(event)); + EXPECT_EQ(result, 1); // CODE_SYNC +} + +/** + * @tc.name: RegisterEvent_002 + * @tc.desc: Test RegisterEvent_002. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, RegisterEvent_002, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + InitMapping(metaMapping); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + RdbServiceImpl service; + DistributedData::StoreInfo storeInfo; + storeInfo.bundleName = "bundleName"; + storeInfo.storeName = "storeName"; + storeInfo.user = 100; + storeInfo.path = "path"; + auto event = std::make_unique(CloudEvent::CLOUD_SYNC, storeInfo); + EXPECT_NE(event, nullptr); + auto result = EventCenter::GetInstance().PostEvent(move(event)); + EXPECT_EQ(result, 1); // CODE_SYNC + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); +} + + +/** + * @tc.name: RegisterEvent_003 + * @tc.desc: Test RegisterEvent_003. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, RegisterEvent_003, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + InitMapping(metaMapping); + metaMapping.cloudPath ="path1"; + metaMapping.dataDir ="path"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + StoreMetaData meta; + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta.user = "100"; + meta.bundleName = "bundleName"; + meta.storeId = "storeName"; + meta.dataDir ="path1"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + RdbServiceImpl service; + DistributedData::StoreInfo storeInfo; + storeInfo.bundleName = "bundleName"; + storeInfo.storeName = "storeName"; + storeInfo.user = 100; + storeInfo.path = "path"; + auto event = std::make_unique(CloudEvent::CLOUD_SYNC, storeInfo); + EXPECT_NE(event, nullptr); + auto result = EventCenter::GetInstance().PostEvent(move(event)); + EXPECT_EQ(result, 1); // CODE_SYNC + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); +} + +/** + * @tc.name: RegisterEvent_004 + * @tc.desc: Test RegisterEvent_005. + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, RegisterEvent_004, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + InitMapping(metaMapping); + metaMapping.cloudPath ="path"; + metaMapping.dataDir ="path"; + metaMapping.storeType = StoreMetaData::STORE_KV_BEGIN; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + RdbServiceImpl service; + DistributedData::StoreInfo storeInfo; + storeInfo.bundleName = "bundleName"; + storeInfo.storeName = "storeName"; + storeInfo.user = 100; + storeInfo.path = "path"; + auto event = std::make_unique(CloudEvent::CLOUD_SYNC, storeInfo); + EXPECT_NE(event, nullptr); + auto result = EventCenter::GetInstance().PostEvent(move(event)); + EXPECT_EQ(result, 1); // CODE_SYNC + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); +} + +/** + * @tc.name: RegisterEvent_005 + * @tc.desc: Test RegisterEvent_005 + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, RegisterEvent_005, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + InitMapping(metaMapping); + metaMapping.cloudPath ="path"; + metaMapping.dataDir ="path"; + metaMapping.storeType = StoreMetaData::STORE_OBJECT_BEGIN; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + RdbServiceImpl service; + DistributedData::StoreInfo storeInfo; + storeInfo.bundleName = "bundleName"; + storeInfo.storeName = "storeName"; + storeInfo.user = 100; + storeInfo.path = "path"; + auto event = std::make_unique(CloudEvent::CLOUD_SYNC, storeInfo); + EXPECT_NE(event, nullptr); + auto result = EventCenter::GetInstance().PostEvent(move(event)); + EXPECT_EQ(result, 1); // CODE_SYNC + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); +} + +/** + * @tc.name: RegisterEvent_006 + * @tc.desc: Test RegisterEvent_006 + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceImplTest, RegisterEvent_006, TestSize.Level1) +{ + StoreMetaMapping metaMapping; + InitMapping(metaMapping); + metaMapping.cloudPath ="path1"; + metaMapping.dataDir ="path"; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaMapping.GetKey(), metaMapping, true), true); + + RdbServiceImpl service; + DistributedData::StoreInfo storeInfo; + storeInfo.bundleName = "bundleName"; + storeInfo.storeName = "storeName"; + storeInfo.user = 100; + storeInfo.path = "path"; + auto event = std::make_unique(CloudEvent::CLOUD_SYNC, storeInfo); + EXPECT_NE(event, nullptr); + auto result = EventCenter::GetInstance().PostEvent(move(event)); + EXPECT_EQ(result, 1); // CODE_SYNC + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaMapping.GetKey(), true), true); +} + +/** + * @tc.name: QuerySharingResource_PermissionDenied_001 + * @tc.desc: Test QuerySharingResource returns RDB_ERROR when CheckAccess fails. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, QuerySharingResource_PermissionDenied_001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + // param.bundleName_ and param.storeName_ left empty to trigger CheckAccess failure + PredicatesMemo predicates; + predicates.tables_ = {"table1"}; + std::vector columns = {"col1", "col2"}; + + auto result = service.QuerySharingResource(param, predicates, columns); + EXPECT_EQ(result.first, RDB_ERROR); + EXPECT_EQ(result.second, nullptr); +} + +/** + * @tc.name: QuerySharingResource_PermissionDenied_002 + * @tc.desc: Test QuerySharingResource returns RDB_ERROR when not system app. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, QuerySharingResource_PermissionDenied_002, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + param.bundleName_ = TEST_BUNDLE; + param.storeName_ = TEST_STORE; + PredicatesMemo predicates; + predicates.tables_ = {"table1"}; + std::vector columns = {"col1", "col2"}; + + auto result = service.QuerySharingResource(param, predicates, columns); + EXPECT_EQ(result.first, RDB_ERROR); + EXPECT_EQ(result.second, nullptr); +} + +/** + * @tc.name: SaveSecretKeyMeta_CloneKeyUpdate_001 + * @tc.desc: Test SaveSecretKeyMeta updates clone secret key when area < 0 or nonce is empty. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, SaveSecretKeyMeta_CloneKeyUpdate_001, TestSize.Level0) +{ + // Prepare metaData and secret key + auto meta = metaData_; + meta.isEncrypt = true; + std::vector password = Random(KEY_LENGTH); + + // Prepare cloneKey with area < 0 and empty nonce + SecretKeyMetaData cloneKey; + CryptoManager::CryptoParams params; + cloneKey.sKey = CryptoManager::GetInstance().Encrypt(password, params); + cloneKey.area = -1; + cloneKey.nonce.clear(); + cloneKey.storeType = meta.storeType; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetCloneSecretKey(), cloneKey, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + + // Call SaveSecretKeyMeta, should trigger UpdateSecretMeta for cloneKey + RdbServiceImpl service; + service.SaveSecretKeyMeta(meta, password); + + // Clean up + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetCloneSecretKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); +} + +/** + * @tc.name: SaveSecretKeyMeta_CloneKeyUpdate_EmptySKey_002 + * @tc.desc: Test SaveSecretKeyMeta does not update clone secret key if sKey is empty. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, SaveSecretKeyMeta_CloneKeyUpdate_EmptySKey_002, TestSize.Level0) +{ + auto meta = metaData_; + meta.isEncrypt = true; + std::vector password = Random(KEY_LENGTH); + + // Prepare cloneKey with empty sKey + SecretKeyMetaData cloneKey; + cloneKey.sKey.clear(); + cloneKey.area = -1; + cloneKey.nonce.clear(); + cloneKey.storeType = meta.storeType; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetCloneSecretKey(), cloneKey, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + + RdbServiceImpl service; + service.SaveSecretKeyMeta(meta, password); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetCloneSecretKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); +} + +/** + * @tc.name: SaveSecretKeyMeta_CloneKeyUpdate_NoUpdate_003 + * @tc.desc: Test SaveSecretKeyMeta does not update clone secret key if area >= 0 and nonce not empty. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhaojh + */ +HWTEST_F(RdbServiceImplTest, SaveSecretKeyMeta_CloneKeyUpdate_NoUpdate_003, TestSize.Level0) +{ + auto meta = metaData_; + meta.isEncrypt = true; + std::vector password = Random(KEY_LENGTH); + + // Prepare cloneKey with area >= 0 and nonce not empty + SecretKeyMetaData cloneKey; + CryptoManager::CryptoParams params; + cloneKey.sKey = CryptoManager::GetInstance().Encrypt(password, params); + cloneKey.area = 1; + cloneKey.nonce = { 1, 2, 3, 4 }; + cloneKey.storeType = meta.storeType; + + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetCloneSecretKey(), cloneKey, true), true); + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(meta.GetKey(), meta, true), true); + + RdbServiceImpl service; + service.SaveSecretKeyMeta(meta, password); + + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetCloneSecretKey(), true), true); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(meta.GetKey(), true), true); +} +} // namespace DistributedRDBTest +} // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_service_impl_token_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_service_impl_token_test.cpp new file mode 100644 index 00000000..4a49356a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_service_impl_token_test.cpp @@ -0,0 +1,351 @@ +/* + * 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 "account/account_delegate.h" +#include "rdb_service_impl.h" +#include "ipc_skeleton.h" +#include "gmock/gmock.h" +#include "mock/access_token_mock.h" +#include "bootstrap.h" +#include "checker_mock.h" +#include "crypto/crypto_manager.h" +#include "device_manager_adapter.h" +#include "device_matrix.h" +#include "metadata/meta_data_manager.h" +#include "metadata/store_meta_data.h" +#include "metadata/store_meta_data_local.h" +#include "mock/db_store_mock.h" +#include "rdb_types.h" +#include "relational_store_manager.h" +#include "gtest/gtest.h" +#include "directory/directory_manager.h" +using namespace OHOS::DistributedRdb; +using namespace OHOS::DistributedData; +using namespace DistributedDB; +using namespace OHOS::Security::AccessToken; +using namespace testing::ext; +using namespace testing; +using namespace std; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; + +namespace OHOS::Test { +namespace DistributedRDBTest { + +static constexpr const char *TEST_BUNDLE = "test_rdb_service_impl_bundleName"; +static constexpr const char *TEST_APPID = "test_rdb_service_impl_appid"; +static constexpr const char *TEST_STORE = "test_rdb_service_impl_store"; + +class RdbServiceImplTokenTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + static void InitMetaData(); + void SetUp(); + void TearDown(); +protected: + static inline std::shared_ptr accTokenMock = nullptr; + static std::shared_ptr dbStoreMock_; + static StoreMetaData metaData_; + static CheckerMock checkerMock_; + static void InitMetaDataManager(); + static void GetRdbSyncerParam(RdbSyncerParam ¶m); +}; +std::shared_ptr RdbServiceImplTokenTest::dbStoreMock_ = std::make_shared(); +StoreMetaData RdbServiceImplTokenTest::metaData_; +CheckerMock RdbServiceImplTokenTest::checkerMock_; + + +void RdbServiceImplTokenTest::InitMetaData() +{ + metaData_.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData_.appId = TEST_APPID; + metaData_.bundleName = TEST_BUNDLE; + metaData_.tokenId = OHOS::IPCSkeleton::GetCallingTokenID(); + metaData_.user = std::to_string(AccountDelegate::GetInstance()->GetUserByToken(metaData_.tokenId)); + metaData_.area = OHOS::DistributedKv::EL1; + metaData_.instanceId = -1; + metaData_.isAutoSync = true; + metaData_.storeType = DistributedRdb::RDB_DEVICE_COLLABORATION; + metaData_.storeId = TEST_STORE; + metaData_.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData_) + "/" + TEST_STORE; +} + +void RdbServiceImplTokenTest::InitMetaDataManager() +{ + MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr, ""); + MetaDataManager::GetInstance().SetSyncer([](const auto &, auto) { + DeviceMatrix::GetInstance().OnChanged(DeviceMatrix::META_STORE_MASK); + }); +} + +void RdbServiceImplTokenTest::SetUpTestCase() +{ + accTokenMock = std::make_shared(); + BAccessTokenKit::accessTokenkit = accTokenMock; + size_t max = 12; + size_t min = 5; + auto dmExecutor = std::make_shared(max, min); + DeviceManagerAdapter::GetInstance().Init(dmExecutor); + InitMetaData(); + Bootstrap::GetInstance().LoadCheckers(); + CryptoManager::GetInstance().GenerateRootKey(); +} + +void RdbServiceImplTokenTest::TearDownTestCase() +{ + accTokenMock = nullptr; + BAccessTokenKit::accessTokenkit = nullptr; +} + +void RdbServiceImplTokenTest::SetUp() +{ +} + +void RdbServiceImplTokenTest::TearDown() +{ +} + +void RdbServiceImplTokenTest::GetRdbSyncerParam(RdbSyncerParam ¶m) +{ + param.bundleName_ = metaData_.bundleName; + param.type_ = metaData_.storeType; + param.level_ = metaData_.securityLevel; + param.area_ = metaData_.area; + param.hapName_ = metaData_.bundleName; + param.storeName_ = metaData_.storeId; + param.isEncrypt_ = metaData_.isEncrypt; + param.isSearchable_ = metaData_.isSearchable; + param.haMode_ = metaData_.haMode; + param.asyncDownloadAsset_ = metaData_.asyncDownloadAsset; + param.user_ = metaData_.user; +} + +/** + * @tc.name: VerifyPromiseInfo001 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTokenTest, VerifyPromiseInfo001, TestSize.Level0) +{ + RdbServiceImpl service; + RdbSyncerParam param; + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_ERROR); +} + +/** + * @tc.name: VerifyPromiseInfo002 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTokenTest, VerifyPromiseInfo002, TestSize.Level0) +{ + InitMetaDataManager(); + StoreMetaDataLocal localMeta; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {tokenId}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {}; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + EXPECT_CALL(*accTokenMock, GetTokenType(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_INVALID)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_INVALID)); + RdbServiceImpl service; + RdbSyncerParam param; + GetRdbSyncerParam(param); + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} + +/** + * @tc.name: VerifyPromiseInfo003 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTokenTest, VerifyPromiseInfo003, TestSize.Level0) +{ + StoreMetaDataLocal localMeta; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {tokenId}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {}; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + EXPECT_CALL(*accTokenMock, GetTokenType(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_SHELL)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_SHELL)); + RdbServiceImpl service; + RdbSyncerParam param; + GetRdbSyncerParam(param); + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_OK); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} + +/** + * @tc.name: VerifyPromiseInfo004 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTokenTest, VerifyPromiseInfo004, TestSize.Level0) +{ + StoreMetaDataLocal localMeta; + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {}; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + EXPECT_CALL(*accTokenMock, GetTokenType(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_SHELL)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_SHELL)); + RdbServiceImpl service; + RdbSyncerParam param; + GetRdbSyncerParam(param); + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} + +/** + * @tc.name: VerifyPromiseInfo005 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTokenTest, VerifyPromiseInfo005, TestSize.Level0) +{ + StoreMetaDataLocal localMeta; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {tokenId}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {}; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + EXPECT_CALL(*accTokenMock, GetTokenType(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); + RdbServiceImpl service; + RdbSyncerParam param; + GetRdbSyncerParam(param); + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_OK); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} + +/** + * @tc.name: VerifyPromiseInfo006 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTokenTest, VerifyPromiseInfo006, TestSize.Level0) +{ + StoreMetaDataLocal localMeta; + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {}; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + EXPECT_CALL(*accTokenMock, GetTokenType(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_NATIVE)); + RdbServiceImpl service; + RdbSyncerParam param; + GetRdbSyncerParam(param); + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} +/** + * @tc.name: VerifyPromiseInfo007 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTokenTest, VerifyPromiseInfo007, TestSize.Level0) +{ + StoreMetaDataLocal localMeta; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {tokenId}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {}; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + EXPECT_CALL(*accTokenMock, GetTokenType(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); + RdbServiceImpl service; + RdbSyncerParam param; + GetRdbSyncerParam(param); + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_ERROR); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} + +/** + * @tc.name: VerifyPromiseInfo008 + * @tc.desc: Test VerifyPromiseInfo when tokenId and uid are not in promiseInfo. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zd + */ +HWTEST_F(RdbServiceImplTokenTest, VerifyPromiseInfo008, TestSize.Level0) +{ + StoreMetaDataLocal localMeta; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + localMeta.isAutoSync = true; + localMeta.promiseInfo.tokenIds = {tokenId}; + localMeta.promiseInfo.uids = {}; + localMeta.promiseInfo.permissionNames = {TEST_BUNDLE}; + EXPECT_EQ(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta, true), true); + + EXPECT_CALL(*accTokenMock, GetTokenType(testing::_)) + .WillOnce(testing::Return(ATokenTypeEnum::TOKEN_HAP)) + .WillRepeatedly(testing::Return(ATokenTypeEnum::TOKEN_HAP)); + RdbServiceImpl service; + RdbSyncerParam param; + GetRdbSyncerParam(param); + int32_t result = service.VerifyPromiseInfo(param); + + EXPECT_EQ(result, RDB_OK); + EXPECT_EQ(MetaDataManager::GetInstance().DelMeta(metaData_.GetKeyLocal(), true), true); +} +} // namespace DistributedRDBTest +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/app.json b/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/app.json new file mode 100644 index 00000000..3bbd52d9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/app.json @@ -0,0 +1,13 @@ +{ + "app": { + "bundleName": "com.example.testCloud", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name", + "distributedNotificationEnabled": true, + "minAPIVersion": 9, + "targetAPIVersion": 9 + } +} diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/resources/base/element/string.json b/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/resources/base/element/string.json new file mode 100644 index 00000000..771eddc8 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "Extension" + } + ] +} diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/resources/base/media/app_icon.png b/datamgr_service/services/distributeddataservice/service/test/testCloud/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 zcmX|G1ymHk)?T_}Vd;>R?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}y { + if (err.code) { + console.error('Failed to load the content. Cause:' + JSON.stringify(err)); + return; + } + console.info('Succeeded in loading the content. Data: ' + JSON.stringify(data)) + }); + } + + onWindowStageDestroy() { + // Main window is destroyed, release UI related resources + console.log("[Demo] MainAbility onWindowStageDestroy") + } + + onForeground() { + // Ability has brought to foreground + console.log("[Demo] MainAbility onForeground") + } + + onBackground() { + // Ability has back to background + console.log("[Demo] MainAbility onBackground") + } +}; diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/ets/pages/index.ets b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/ets/pages/index.ets new file mode 100644 index 00000000..33bf2faf --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/ets/pages/index.ets @@ -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. + */ + +@Entry +@Component +struct Index { + @State message: string = 'StartAbility Success' + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(30) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/module.json b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/module.json new file mode 100644 index 00000000..352fc3e1 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/module.json @@ -0,0 +1,40 @@ +{ + "module": { + "name": "entry", + "type": "entry", + "srcEntrance": "./ets/Application/MyAbilityStage.ts", + "description": "$string:entry_desc", + "mainElement": "MainAbility", + "deviceTypes": [ + "default", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "uiSyntax": "ets", + "abilities": [ + { + "name": "MainAbility", + "srcEntrance": "./ets/MainAbility/MainAbility.ts", + "description": "$string:MainAbility_desc", + "icon": "$media:icon", + "label": "$string:MainAbility_label", + "startWindowIcon": "$media:icon", + "startWindowBackground": "$color:white", + "visible": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ] + } +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/element/color.json b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/element/color.json new file mode 100644 index 00000000..1bbc9aa9 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "white", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/element/string.json b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/element/string.json new file mode 100644 index 00000000..496f24f7 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "entry_desc", + "value": "testCloud" + }, + { + "name": "MainAbility_desc", + "value": "testCloud" + }, + { + "name": "MainAbility_label", + "value": "testCloud" + } + ] +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/media/icon.png b/datamgr_service/services/distributeddataservice/service/test/testCloud/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c GIT binary patch literal 6790 zcmX|G1ymHk)?T_}Vd;>R?p|tHQo6fg38|$UVM!6BLrPFWk?s;$LOP{GmJpBl$qoSA!PUg~PA65-S00{{S`XKG6NkG0RgjEntPrmV+?0|00mu7;+5 zrdpa{2QLqPJ4Y{j7=Mrl{BaxrkdY69+c~(w{Fv-v&aR%aEI&JYSeRTLWm!zbv;?)_ ziZB;fwGbbeL5Q}YLx`J$lp~A09KK8t_z}PZ=4ZzgdeKtgoc+o5EvN9A1K1_<>M?MBqb#!ASf&# zEX?<)!RH(7>1P+j=jqG(58}TVN-$psA6K}atCuI!KTJD&FMmH-78ZejBm)0qc{ESp z|LuG1{QnBUJRg_E=h1#XMWt2%fcoN@l7eAS!Es?Q+;XsRNPhiiE=@AqlLkJzF`O18 zbsbSmKN=aaq8k3NFYZfDWpKmM!coBU0(XnL8R{4=i|wi{!uWYM2je{U{B*K2PVdu&=E zTq*-XsEsJ$u5H4g6DIm2Y!DN`>^v|AqlwuCD;w45K0@eqauiqWf7l&o)+YLHm~|L~ z7$0v5mkobriU!H<@mVJHLlmQqzQ3d6Rh_-|%Yy2li*tHO>_vcnuZ7OR_xkAIuIU&x z-|8Y0wj|6|a6_I(v91y%k_kNw6pnkNdxjqG8!%Vz_d%c_!X+6-;1`GC9_FpjoHev5fEV7RhJ>r=mh-jp$fqbqRJ=obwdgLDVP5+s zy1=_DWG0Y-Jb3t^WXmkr(d9~08k-|#Ly zaNOmT(^9tIb&eb4%CzIT zAm3CUtWSr1t4?h1kk#NBi{U|pJslvME{q|_eS^3En>SOqSxyuN1x;Is@8~m?*>}** znrRFArP!K_52RpX*&JHMR<^lVdm8ypJ}0R(SD(51j;6@ni$6bQ+2XL+R^|NnSp5}(kzvMZ^(@4fD_{QVu$(&K6H|C37TG1Am9Re{<<3gd zh@`>;BqkXMW&p0T6rt|iB$)~CvFe(XC)F9WgAZn*0@t$oZo;!*}r@_`h?KKH&6A@3= zISXoQB+~`op>NP-buiA*^0n{@i{_?MRG)&k)c)k_F+-2Lud!S9pc+i`s74NpBCaGF zXN+pHkubw*msGBTY27BKHv)RRh3;nMg4&$fD_6X9Vt~;_4D+5XPH~#Kn-yjcy!$}1 zigv#FNY>TqMhtIBb@UoF!cE~Q8~;!Pek>SQQwHnHuWKoVBosAiOr}q>!>aE*Krc)V zBUMEcJ5NU0g8}-h6i1zpMY9>m4ne?=U2~`w7K7Q0gB_=p@$5K7p6}thw z-~3dMj?YNX2X$lZ+7ngQ$=s}3mizNN@kE%OtB)?c&i~2L55z8^=yz;xMHLmlY>&Q# zJj?!)M#q_SyfkQh)k?j8IfLtB)ZCp|*vf4_B zos?73yd^h-Ac+;?E4*bpf=o*^3x3-`TVjbY4n6!EN10K6o@fxdyps05Vo3PU)otB} z`3kR+2w7_C#8Z!q`J)p{Vh!+m9-UP!$STp+Hb}}#@#_u^SsUQg<}59< zTvH3%XS4G+6FF^(m6bVF&nSUIXcl;nw{=H$%fgeJ>CgDYiLdpDXr{;-AnG z8dvcrHYVMI&`R6;GWekI@Ir3!uo)oz4^{6q0m^}@f2tM9&=YHNi6-?rh0-{+k@cQm zdp`g#YdQn%MDVg2GR>wZ`n2<0l4)9nx1Wfr&!Dvz=bPwU!h2S?ez6MVc5APE4-xLB zi&W9Q8k2@0w!C53g?iAIQ}~p*3O(@zja6KQ=M3zfW*_6o5SwR-)6VBh~m7{^-=MC-owYH5-u40a}a0liho3QZZ5L{bS_xM1)4}19)zTU$$MY zq3eZML1WC{K%YFd`Be0M-rkO^l?h{kM{$2oK1*A@HVJ57*yhDkUF!2WZ&oA4Y-sK( zCY69%#`mBCi6>6uw(x4gbFaP0+FD*JKJ-q!F1E?vLJ+d35!I5d7@^eU?(CS|C^tmI5?lv@s{{*|1F zFg|OzNpZ0hxljdjaW%45O0MOttRrd(Z?h{HYbB-KFUx&9GfFL3b8NwZ$zNu)WbBD` zYkj$^UB5%3Pj1MDr>S2Ejr9pUcgA!;ZG!@{uAy12)vG=*^9-|dNQBc8&`oxBlU~#y zs!anJX&T?57Jdr^sb>e+V`MVfY>Y0ESg7MG<7W0g&bR-ZYzzZ%2H&Etcp zcd6QeXO1D!5A#zM0lx*GH}`M)2~ZFLE;sP^RSB5wVMNfiZXPd(cmO>j=OSA3`o5r& zna(|^jGXbdN7PK)U8b7^zYtYkkeb%<%F~=OqB~kXMQkq}ii|skh@WSRt>5za;cjP0 zZ~nD%6)wzedqE}BMLt~qKwlvTr33))#uP~xyw#*Eaa|DbMQ_%mG0U8numf8)0DX`r zRoG2bM;#g|p-8gWnwRV5SCW0tLjLO&9Z?K>FImeIxlGUgo0Zk`9Qzhj1eco~7XZy+hXc@YF&ZQ=? zn*^1O56yK^x{y}q`j7}blGCx%dydV!c7)g~tJzmHhV=W~jbWRRR{1<^oDK+1clprm zz$eCy7y9+?{E|YgkW~}}iB#I4XoJ*xr8R?i_Hv$=Cof5bo-Nj~f`-DLebH}&0% zfQj9@WGd4;N~Y?mzQsHJTJq6!Qzl^-vwol(+fMt#Pl=Wh#lI5Vmu@QM0=_r+1wHt` z+8WZ~c2}KQQ+q)~2Ki77QvV&`xb|xVcTms99&cD$Zz4+-^R4kvUBxG8gDk7Y`K*)JZ^2rL(+ZWV~%W(@6 z)0bPArG#BROa_PHs~&WplQ_UIrpd)1N1QGPfv!J(Z9jNT#i%H?CE6|pPZb9hJ1JW4 z^q;ft#!HRNV0YgPojzIYT`8LuET2rUe-J|c!9l4`^*;4WtY@Ew@pL>wkjmMgGfN7 ze}}GtmU0@<_#08~I-Suk=^*9GLW=H4xhsml;vAV{%hy5Eegl@!6qKqbG024%n2HHw zCc@ivW_$@5ZoHP70(7D+(`PvgjW1Pd`wsiuv-aCukMrafwDm)B!xXVy*j2opohhoU zcJz%ADmj>i3`-3-$7nQKBQQuGY;2Qt&+(L~C>vSGFj5{Mlv?T_^dql;{zkpe4R1}R z%XfZyQ}wr*sr>jrKgm*PWLjuVc%6&&`Kbf1SuFpHPN&>W)$GmqC;pIoBC`=4-hPY8 zT*>%I2fP}vGW;R=^!1be?ta2UQd2>alOFFbVl;(SQJ4Jk#)4Z0^wpWEVvY4=vyDk@ zqlModi@iVPMC+{?rm=4(n+<;|lmUO@UKYA>EPTS~AndtK^Wy^%#3<;(dQdk3WaUkRtzSMC9}7x2||CNpF#(3T4C)@ z$~RWs`BNABKX|{cmBt>Q=&gkXl&x!!NK_%5hW0LS)Z4PB>%sV?F-{Wyj#s7W%$F{D zXdK^Fp3wvy+48+GP6F_|^PCRx=ddcTO3sG;B23A49~Qaw31SZ0Rc~`r4qqt%#OGW{ zCA_(LG5^N>yzUn&kAgVmxb=EA8s&tBXC}S1CZ(KoW)(%^JjLTPo^fs`Va;`=YlVPgmB$!yB}<(4ym6OeZ3xAJJ#;)2+B%p3P1Wt+d$eo`vz`T zXfUP2))kBDPoscH;Jc7I3NU<({|@wM$&GaDt`n7WLgIY3IA7A6-_R?z8N3mz|}*i z(zl5ot--Oq@f2-nv{X(ujT2T(k1vY_qh93pK@>H-qc%2Xta)IP0Q%zt%bqYgI`o!wv!0QerB`nCN^1n|@$sVOQ!V0teVG!I z_fD%JvfDeT1cK#-{o6Gv7}& zY0#NWin~kVaf$aufV&;63Hbs|`QVZWpDX6IMk1Hj2G}fiH9e-^6u2zf^FIr^BwD<6zjw63+{yUe8PUFvk8v{sJ=R{d#`O!sz`Q13~< zPT$JS(w=yQfU2`zPCNfSw=&zup@DXc(98afjhv@1w_f!m2Z>rMJ19AB&dB%P#Ls3b z=lK7OILM+SQ&VEd=1GN6o&>YVVtIzoZ%=Z_SdqJN2}E43{bE`>w+A;=y->@^k{oCC z$F*WTY&?34;kfyFV?b*Xb1Pq`Z=%OgwEg)Rz)tx=`f%5#w_INP=x&z5!jI;#;N$ma zhO)+MDm;SxOEVL15; zGq(v2pL3&P1Sl)8P*;G-fd{l1QJsv@e@d8)1PK4w2m*M%V3j-V~L^$i|&C@b?D?9tfwE{B^}Z$k8e5FmQ>v7Xz)sG32g9t}YBt zyR$+*_00RmPx+0mW+vVG4mxd(n$(eQf3-w>JPl2UJpafrPaL5@2j}%{VE-) zBI%6Qpj*dsdH<;g!S!avA~bv^0E+ zfyJbSjPb+j;J52U)<|cIcntQBI2T#>2;tOxu{%D?kML476AErF(qN9hPva5Nkc@BF zC-tLF@3ZFb%Kpj)M<{)x*l|*Ia@ECeXo2E4h2f!aV=cHAhi_E_mfUth(sM4^hJq7B zQsGWqdZUm9S%F`$nQ*_#NcuD`&)Ek%_s{&^78{9Hm ztri&rYLOxgFdG>O@+XHy z9#;|&vBCPXH5Mon^I`jSuR$&~ZWtyB67ujzFSj!51>#C}C17~TffQ{c-!QFQkTQ%! zIR^b1`zHx|*1GU?tbBx23weFLz5H?y_Q%N&t$}k?w+``2A=aotj0;2v$~AL z{scF-cL{wsdrmPvf#a9OHyYLcwQD4Kcm)`LLwMh4WT~p29f7M!iafJSU`IV}QY5Wa z(n44-9oA}?J{a+ah*@31WTs#&J#o1`H98#6IQf;Wv0N_!);f&9g7o-k(lW5rWnDUR zQBFIRG+X=6NnsI@mxnwm;tf5;_Uxg?jZ8m-m0}&6+DA!qam(p$mN5R})yA_7m$q@| zFEd|dpS595rxQr-n#GjI5i-AhnUE>Cr;jpCqSrD~EwK_DqI^7%3#p5)%T_od!t3SOmH9MyXeeGO2(UQL;ax|x?Ncixmeo1=$ z{-);Au{*tfzOG?KQ~K|ak8-HQ?`Pekhe2WM(8s{xv-p>Zmu_6{G!-oE$7$mY`MOJorI=+mMx?H;`pr!;fVYz?5~yXBACruWB`Ph zZM}90_<^OBxIhyZ9BW$`>6JvO;%VFpqVr8|7t3~AmxYak6?`Pp#c;**_SYmi`&z23 z`p6_~ePvH)C6x-G9$hgL=eVALq`-AiamN>!3~Lxw&{H(b{B(7xSRm6<3<{%{yXiH# zos5Rv1L+8fUKJLo%P>4I&$}ymbUK|l3~)$l;SmzQgllt5=a4Zva%m-vq%V;Tq*&n z%+L*>q%)OSD^F#*7b;tbXpCfN6^%y-Wrb2*42pqr_Vuuz2?$~JY$eXJssI_|qNFd* zi37M+Rvf^@8c3QWLQ!0d3M1ojG9bjYKwa+B>j{-MDEw*4v;mb~3v?=6PXMS?6ATiN zPFx44$N-c- z1V!L6LYT}KrvntBBIzI_&KDqB2#R5es4C6K!4k9uk46}}Rlp9}i=T*cWRUdZoVX>G z_(M>$)m~^oU2dz%YJlBnI$BR-R;vL^8Vs`m4kc4eW$X<=WUN_uicL+1MoID!x8mpboxhT(7`OVewd1h0quSOpy+-Mz! z_{}inK@ADa=`KYmUsE{jk3cOxx+zp`t`67JJ~!Hk8PGHePGI=WC}%Cg`^;3Mx7Nk_ z)S8eJpu8pQw_}Yck2S)r0tdG>;c#P#8X;;oHYKn|EO9;7h%lHl#v7bzj%Jj%8QqPj z2Scp=yuw&zJ$=)f39}on?cZn2jiP$Ku10J1*4j9qTC261T$Hy4B<337NIwR1*V7ho z6ACr)eshBLs!aeFa$z;uD4(!jzuLpsxM4RE@(*O!iinx6r~7k_Aqa0bz_8orbr_sZ zwniHaG!Eh!ZyAFwECEtqIu1;h@T?W;I4@yo8O_)0J4D(qIfZ zwH^yZ0Yp<}4kHv63Xtk#P)9fEV=SIToz@aiYvllSx=0p`U!+4ID!@zRW4Z6nacVn zNJ$?ADanCOnN%W`%FDM#_Ja{wcL_%Q{zGz^EHeZ6p&XE%CG*I$@}vekG!~2z8^iN* z2H6yJH^>*GIeEE*qJ?e(k3dtw6tPQ|H*s*6K#LM>Okh%IfWhQ^g&G2CpoY}KS6i2_ z(C8s`DKyXo?9U_tKyg2bqT7+EiZVeVjfJj$lLlUpmo+S%2B~BqA2P`>8ImEd`9S)Q z-mdP?;pYA0-g<7v>RqPtrHYOM$=`R){NvN7Po0^JZ7cs)_VHIoY3VHYBLxTE>~yZo z9)I|G&HFNX`OyihH@QF+C=lq}J5@dbj9)VL)3zSv_&?=rnA_8L-@@LnG8b)BnZZaA zFiIl%uUsyZ4qF25726}_m*U&SQkr^N;g)(+N zvpYNGYu#;`HX6D3EYTaz>K?N$mp489{{Xgr;LAjYI>h*;u{jfw)4~WY|`c?wqJ`aKKIvAdj$O$ z1^v7=pr27^bjycw0pXu{bTh#8{-Z0n-O;%ihPz2bkOtBX5>dK&2br{h+#BM_ob|Xo zLn-rR$g#4%)|E|)rE4!KY)7xnV7~Ojk+}%{3zkRw3h%$y8S`2fmk%@l zYZC(IfKj4Q@vl|z4tx8?cr7HPSn1#Vs}y3@b(Wz?5*gX{KS%(+GPEf4U<&sj~`*=Q%P?Tw?+!4 z?U?p!X2H&>!(3xGw_omj8rU9bHU2w}o?|z+tXq2-tZH_wY(23x|M;w~_stX9G6fys zf{xA&=x8$W#zRAy+`-cuWJZv-R6STnV)M>8;%y`}W&M}O*1eps-SyPln;X7358qcL zKRfZoZ$9Cc8g_5X`fk^yqKWUEcwX`P-tx_h+1h2t7T?2mw{*Sst_#$>a&py-vZ_~m zUOu#D;@U0WEL)cQ%|{(mmR))5(N|^_T)FVpnP+}bc{ce0KE#}EsgeIfW4AQ7AvcUH zoB;?ah@AR`Zs~8iOOO5TN=3L~`?0e1XZPnGJCS#GQ83qW&f@uO*^;}%J=U*}U+5Y4 z@r4tk1+zMO7sGF_h;DH8OjlifwRY!`7hcFcL_N?qJ~ipbCr{hkqvxK%&$3>wJ@mHb z#RpCnLn+A|L1YgKuMW_3M~-peMjiaX=_J8~>kpi486@=m^emEqN!J_Mnb0WVQq%$n zDg$NOQVpmBB{zEIkWyZF-&Jcs%)VctI^_8Mwtdh2?L2v;a>1Kzd#8@Gce7yl z^_yHOHvyxxaLnP?w@dR5e)wI(max, min); + DmAdapter::GetInstance().Init(executors); + DistributedKv::KvStoreMetaManager::GetInstance().BindExecutor(executors); + DistributedKv::KvStoreMetaManager::GetInstance().InitMetaParameter(); + DistributedKv::KvStoreMetaManager::GetInstance().InitMetaListener(); +} + +/** +* @tc.name: SaveDataTest001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, SaveDataTest001, TestSize.Level1) +{ + StoreCache::GetInstance().stores_.Clear(); + std::string key = DATA_HUB_INTENTION; + auto store = std::make_shared(key); + store->kvStore_ = std::make_shared(); + int foregroundUserId = 0; + DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + key.append(std::to_string(foregroundUserId)); + StoreCache::GetInstance().stores_.InsertOrAssign(key, store); + CustomOption option; + option.intention = Intention::UD_INTENTION_DATA_HUB; + option.tokenId = 1; + auto record = std::make_shared(); + UnifiedData data; + data.AddRecord(record); + std::string key1 = "key"; + UdmfServiceImpl serviceImpl; + auto status = serviceImpl.SaveData(option, data, key1); + EXPECT_EQ(status, OHOS::UDMF::E_DB_ERROR); +} + +/** +* @tc.name: RetrieveData001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, RetrieveData001, TestSize.Level1) +{ + StoreCache::GetInstance().stores_.Clear(); + std::string intention = "drag"; + auto store = std::make_shared(intention); + store->kvStore_ = std::make_shared(); + int foregroundUserId = 0; + DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + intention.append(std::to_string(foregroundUserId)); + StoreCache::GetInstance().stores_.InsertOrAssign(intention, store); + std::string key = "udmf://drag/get.example.myapplication/L]WQ=JezoKgDc8\\Rz`q6koADcGRdKMnf"; + QueryOption option = { + .key = key + }; + UnifiedData data; + UdmfServiceImpl serviceImpl; + auto status = serviceImpl.RetrieveData(option, data); + EXPECT_EQ(status, OHOS::UDMF::E_DB_ERROR); +} + +/** +* @tc.name: DeleteData001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, DeleteData001, TestSize.Level1) +{ + StoreCache::GetInstance().stores_.Clear(); + std::string intention = DATA_HUB_INTENTION; + auto store = std::make_shared(intention); + store->kvStore_ = std::make_shared(); + int foregroundUserId = 0; + DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + intention.append(std::to_string(foregroundUserId)); + StoreCache::GetInstance().stores_.InsertOrAssign(intention, store); + std::string key = "udmf://DataHub/delete.example.myapplication/L]WQ=JezoKgDc8\\Rz`q6koADcGRdKMnf"; + QueryOption option = { + .key = key, + }; + auto record = std::make_shared(); + UnifiedData data; + data.AddRecord(record); + std::vector dataList = { data }; + UdmfServiceImpl serviceImpl; + auto status = serviceImpl.DeleteData(option, dataList); + EXPECT_EQ(status, OHOS::UDMF::E_DB_ERROR); +} + +/** +* @tc.name: GetSummary001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, GetSummary001, TestSize.Level1) +{ + StoreCache::GetInstance().stores_.Clear(); + std::string intention = DATA_HUB_INTENTION; + auto store = std::make_shared(intention); + store->kvStore_ = std::make_shared(); + int foregroundUserId = 0; + DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + intention.append(std::to_string(foregroundUserId)); + StoreCache::GetInstance().stores_.InsertOrAssign(intention, store); + std::string key = "udmf://DataHub/summary.example.myapplication/L]WQ=JezoKgDc8\\Rz`q6koADcGRdKMnf"; + QueryOption option = { + .key = key, + }; + Summary summary; + UdmfServiceImpl serviceImpl; + auto status = serviceImpl.GetSummary(option, summary); + EXPECT_EQ(status, OHOS::UDMF::E_DB_ERROR); +} + +/** +* @tc.name: IsRemoteData001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, IsRemoteData001, TestSize.Level1) +{ + StoreCache::GetInstance().stores_.Clear(); + std::string intention = DATA_HUB_INTENTION; + auto store = std::make_shared(intention); + store->kvStore_ = std::make_shared(); + int foregroundUserId = 0; + DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + intention.append(std::to_string(foregroundUserId)); + StoreCache::GetInstance().stores_.InsertOrAssign(intention, store); + std::string key = "udmf://DataHub/remote.example.myapplication/L]WQ=JezoKgDc8\\Rz`q6koADcGRdKMnf"; + QueryOption option = { + .key = key, + }; + UdmfServiceImpl serviceImpl; + bool ret = false; + auto status = serviceImpl.IsRemoteData(option, ret); + EXPECT_EQ(status, OHOS::UDMF::E_DB_ERROR); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: GetAppShareOption001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, GetAppShareOption001, TestSize.Level1) +{ + StoreCache::GetInstance().stores_.Clear(); + std::string intention = DATA_HUB_INTENTION; + auto store = std::make_shared(intention); + store->kvStore_ = std::make_shared(); + int foregroundUserId = 0; + DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + intention.append(std::to_string(foregroundUserId)); + StoreCache::GetInstance().stores_.InsertOrAssign(intention, store); + UdmfServiceImpl serviceImpl; + int32_t shareOption = CROSS_APP; + auto status = serviceImpl.GetAppShareOption("DataHub", shareOption); + EXPECT_EQ(status, OHOS::UDMF::E_DB_ERROR); +} + +/** +* @tc.name: QueryDataCommon001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, QueryDataCommon001, TestSize.Level1) +{ + StoreCache::GetInstance().stores_.Clear(); + std::string intention = DATA_HUB_INTENTION; + auto store = std::make_shared(intention); + store->kvStore_ = std::make_shared(); + int foregroundUserId = 0; + DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId); + intention.append(std::to_string(foregroundUserId)); + StoreCache::GetInstance().stores_.InsertOrAssign(intention, store); + UdmfServiceImpl serviceImpl; + QueryOption option = { + .intention = Intention::UD_INTENTION_DATA_HUB, + }; + std::vector dataList; + std::shared_ptr store1; + auto status = serviceImpl.QueryDataCommon(option, dataList, store1); + EXPECT_EQ(status, OHOS::UDMF::E_DB_ERROR); +} + +/** +* @tc.name: PutLocal001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, PutLocal001, TestSize.Level1) +{ + std::string key = "key"; + std::string value = "value"; + auto store = std::make_shared(DATA_HUB_INTENTION); + store->kvStore_ = std::make_shared(); + auto status = store->PutLocal(key, value); + EXPECT_EQ(status, OHOS::UDMF::E_DB_CORRUPTED); +} + +/** +* @tc.name: GetLocal001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, GetLocal001, TestSize.Level1) +{ + std::string key = "key"; + std::string value; + auto store = std::make_shared(DATA_HUB_INTENTION); + store->kvStore_ = std::make_shared(); + auto status = store->GetLocal(key, value); + EXPECT_EQ(status, OHOS::UDMF::E_DB_CORRUPTED); +} + +/** +* @tc.name: DeleteLocal001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, DeleteLocal001, TestSize.Level1) +{ + std::string key = "key"; + auto store = std::make_shared(DATA_HUB_INTENTION); + store->kvStore_ = std::make_shared(); + auto status = store->DeleteLocal(key); + EXPECT_EQ(status, OHOS::UDMF::E_DB_CORRUPTED); +} + +/** +* @tc.name: PutRuntime001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, PutRuntime001, TestSize.Level1) +{ + std::string key = "key"; + Runtime runtime; + auto store = std::make_shared(DATA_HUB_INTENTION); + store->kvStore_ = std::make_shared(); + auto status = store->PutRuntime(key, runtime); + EXPECT_EQ(status, OHOS::UDMF::E_DB_CORRUPTED); +} + +/** +* @tc.name: GetRuntime001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, GetRuntime001, TestSize.Level1) +{ + std::string key = "key"; + Runtime runtime; + auto store = std::make_shared(DATA_HUB_INTENTION); + store->kvStore_ = std::make_shared(); + auto status = store->GetRuntime(key, runtime); + EXPECT_EQ(status, OHOS::UDMF::E_DB_CORRUPTED); +} + +/** +* @tc.name: Update001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, Update001, TestSize.Level1) +{ + UnifiedData data; + auto rumtime = std::make_shared(); + UnifiedKey key(DATA_HUB_INTENTION, "com.demo.test", "111"); + rumtime->key = key; + data.runtime_ = rumtime; + auto store = std::make_shared(DATA_HUB_INTENTION); + store->kvStore_ = std::make_shared(); + auto status = store->Update(data); + EXPECT_EQ(status, OHOS::UDMF::E_DB_CORRUPTED); +} + +/** +* @tc.name: Delete001 +* @tc.desc: Abnormal test of OnRemoteRequest, code is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplDbCorruptionMockTest, Delete001, TestSize.Level1) +{ + std::string key = "key"; + auto store = std::make_shared(DATA_HUB_INTENTION); + store->kvStore_ = std::make_shared(); + auto status = store->Delete(key); + EXPECT_EQ(status, OHOS::UDMF::E_DB_CORRUPTED); +} +}; // namespace DistributedDataTest +}; // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/udmf_preprocess_utils_mock_test.cpp b/datamgr_service/services/distributeddataservice/service/test/udmf_preprocess_utils_mock_test.cpp new file mode 100644 index 00000000..b09a55ff --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/udmf_preprocess_utils_mock_test.cpp @@ -0,0 +1,132 @@ +/* +* 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 "preprocess_utils.h" +#include "gtest/gtest.h" +#include "access_token_mock.h" + +namespace OHOS::UDMF { +using namespace testing; +using namespace std; +using namespace testing::ext; +using namespace OHOS::Security::AccessToken; +class UdmfPreProcessUtilsMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp() {} + void TearDown() {} + static inline shared_ptr accessTokenKitMock = nullptr; +}; + +void UdmfPreProcessUtilsMockTest::SetUpTestCase(void) +{ + accessTokenKitMock = make_shared(); + BAccessTokenKit::accessTokenkit = accessTokenKitMock; +} + +void UdmfPreProcessUtilsMockTest::TearDownTestCase(void) +{ + BAccessTokenKit::accessTokenkit = nullptr; + accessTokenKitMock = nullptr; +} + +/** +* @tc.name: GetHapUidByToken001 +* @tc.desc: Abnormal test of GetHapUidByToken, AccessTokenKit GetHapTokenInfo failed +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsMockTest, GetHapUidByToken001, TestSize.Level1) +{ + uint32_t tokenId = 0; + int userId = 0; + PreProcessUtils preProcessUtils; + EXPECT_CALL(*accessTokenKitMock, GetHapTokenInfo(_, _)).WillOnce(Return(RET_SUCCESS)); + int32_t ret = preProcessUtils.GetHapUidByToken(tokenId, userId); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: GetInstIndex001 +* @tc.desc: Abnormal test of GetInstIndex, AccessTokenKit GetInstIndex failed +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsMockTest, GetInstIndex001, TestSize.Level1) +{ + uint32_t tokenId = 0; + int32_t instIndex = 0; + PreProcessUtils preProcessUtils; + EXPECT_CALL(*accessTokenKitMock, GetTokenTypeFlag(_)).WillOnce(Return(TOKEN_HAP)); + EXPECT_CALL(*accessTokenKitMock, GetHapTokenInfo(_, _)).WillOnce(Return(RET_SUCCESS)); + bool ret = preProcessUtils.GetInstIndex(tokenId, instIndex); + EXPECT_EQ(ret, true); +} + +/** +* @tc.name: GetAlterableBundleNameByTokenId001 +* @tc.desc: Abnormal test of GetSpecificBundleNameByTokenId +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsMockTest, GetAlterableBundleNameByTokenId001, TestSize.Level1) +{ + uint32_t tokenId = 0; + EXPECT_CALL(*accessTokenKitMock, GetHapTokenInfo(_, _)).WillOnce(Return(RET_FAILED)); + EXPECT_CALL(*accessTokenKitMock, GetTokenTypeFlag(_)).WillOnce(Return(TOKEN_SHELL)); + std::string bundleName = ""; + std::string specificBundleName = ""; + PreProcessUtils preProcessUtils; + bool ret = preProcessUtils.GetSpecificBundleNameByTokenId(tokenId, specificBundleName, bundleName); + EXPECT_EQ(ret, false); +} + +/** +* @tc.name: GetAlterableBundleNameByTokenId002 +* @tc.desc: Normal test of GetSpecificBundleNameByTokenId for native +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsMockTest, GetAlterableBundleNameByTokenId002, TestSize.Level1) +{ + uint32_t tokenId = 999; + EXPECT_CALL(*accessTokenKitMock, GetHapTokenInfo(_, _)).WillOnce(Return(RET_FAILED)); + EXPECT_CALL(*accessTokenKitMock, GetTokenTypeFlag(_)).WillOnce(Return(TOKEN_NATIVE)); + EXPECT_CALL(*accessTokenKitMock, GetNativeTokenInfo(_, _)).WillOnce(Return(RET_SUCCESS)); + std::string bundleName = ""; + std::string specificBundleName = ""; + PreProcessUtils preProcessUtils; + bool ret = preProcessUtils.GetSpecificBundleNameByTokenId(tokenId, specificBundleName, bundleName); + EXPECT_EQ(ret, true); +} + +/** +* @tc.name: GetAlterableBundleNameByTokenId003 +* @tc.desc: Normal test of GetSpecificBundleNameByTokenId for hap +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsMockTest, GetAlterableBundleNameByTokenId003, TestSize.Level1) +{ + uint32_t tokenId = 9999; + EXPECT_CALL(*accessTokenKitMock, GetHapTokenInfo(_, _)).WillOnce(Return(RET_SUCCESS)); + std::string bundleName = ""; + std::string specificBundleName = ""; + PreProcessUtils preProcessUtils; + bool ret = preProcessUtils.GetSpecificBundleNameByTokenId(tokenId, specificBundleName, bundleName); + EXPECT_EQ(ret, true); +} +}; // namespace UDMF \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/udmf_preprocess_utils_test.cpp b/datamgr_service/services/distributeddataservice/service/test/udmf_preprocess_utils_test.cpp new file mode 100644 index 00000000..bb8d6287 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/udmf_preprocess_utils_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 "preprocess_utils.h" +#include "gtest/gtest.h" +#include "text.h" + +namespace OHOS::UDMF { +using namespace testing::ext; +class UdmfPreProcessUtilsTest : public testing::Test { +public: + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} + void SetUp() {} + void TearDown() {} +}; + +/** +* @tc.name: RuntimeDataImputation001 +* @tc.desc: Abnormal test of FillRuntimeInfo, option is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, RuntimeDataImputation001, TestSize.Level1) +{ + UnifiedData data; + CustomOption option; + PreProcessUtils preProcessUtils; + int32_t ret = preProcessUtils.FillRuntimeInfo(data, option); + EXPECT_EQ(ret, E_ERROR); +} + +/** +* @tc.name: GetHapUidByToken001 +* @tc.desc: Abnormal test of GetHapUidByToken, tokenId is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, GetHapUidByToken001, TestSize.Level1) +{ + uint32_t tokenId = 0; + int userId = 0; + PreProcessUtils preProcessUtils; + int32_t ret = preProcessUtils.GetHapUidByToken(tokenId, userId); + EXPECT_EQ(ret, E_ERROR); +} + +/** +* @tc.name: SetRemoteData001 +* @tc.desc: Abnormal test of SetRemoteData, data is null +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, SetRemoteData001, TestSize.Level1) +{ + UnifiedData data; + PreProcessUtils preProcessUtils; + EXPECT_NO_FATAL_FAILURE(preProcessUtils.SetRemoteData(data)); +} + +/** +* @tc.name: SetRemoteData002 +* @tc.desc: Normal test of SetRemoteData +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, SetRemoteData002, TestSize.Level1) +{ + UnifiedData data; + std::vector> inputRecords; + for (int32_t i = 0; i < 512; ++i) { + inputRecords.emplace_back(std::make_shared()); + } + data.SetRecords(inputRecords); + data.runtime_ = std::make_shared(); + PreProcessUtils preProcessUtils; + EXPECT_NO_FATAL_FAILURE(preProcessUtils.SetRemoteData(data)); +} + +/** +* @tc.name: GetDfsUrisFromLocal001 +* @tc.desc: Abnormal test of GetDfsUrisFromLocal, uris is null +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, GetDfsUrisFromLocal001, TestSize.Level1) +{ + const std::vector uris; + int32_t userId = 0; + UnifiedData data; + PreProcessUtils preProcessUtils; + int32_t ret = preProcessUtils.GetDfsUrisFromLocal(uris, userId, data); + EXPECT_EQ(ret, E_FS_ERROR); +} + +/** +* @tc.name: CheckUriAuthorization001 +* @tc.desc: Abnormal test of CheckUriAuthorization, uris is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, CheckUriAuthorization001, TestSize.Level1) +{ + const std::vector uris = {"test"}; + uint32_t tokenId = 0; + PreProcessUtils preProcessUtils; + bool ret = preProcessUtils.CheckUriAuthorization(uris, tokenId); + EXPECT_EQ(ret, false); +} + +/** +* @tc.name: GetInstIndex001 +* @tc.desc: Normal test of GetInstIndex +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, GetInstIndex001, TestSize.Level1) +{ + uint32_t tokenId = 0; + int32_t instIndex = 0; + PreProcessUtils preProcessUtils; + bool ret = preProcessUtils.GetInstIndex(tokenId, instIndex); + EXPECT_EQ(instIndex, 0); + EXPECT_EQ(ret, true); +} + +/** +* @tc.name: ProcessFileType001 +* @tc.desc: Abnormal test of ProcessFileType, records is nullptr +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, ProcessFileType001, TestSize.Level1) +{ + std::shared_ptr record = std::make_shared(); + std::shared_ptr obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = "http://demo.com.html"; + obj->value_[FILE_TYPE] = "general.html"; + record->AddEntry("general.file-uri", obj); + std::shared_ptr obj1 = std::make_shared(); + obj1->value_[UNIFORM_DATA_TYPE] = "general.content-form"; + obj1->value_["title"] = "test"; + record->AddEntry("general.content-form", obj1); + + std::shared_ptr record1 = std::make_shared(); + record1->AddEntry("general.file-uri", obj1); + std::shared_ptr record2 = std::make_shared(); + record2->AddEntry("general.file-uri", "1111"); + std::shared_ptr record3 = std::make_shared(); + record3->AddEntry("general.file-uri", 1); + std::vector> records = { record, record1, record2, record3 }; + std::vector uris; + PreProcessUtils::ProcessFileType(records, [&uris](std::shared_ptr obj) { + std::string oriUri; + obj->GetValue(ORI_URI, oriUri); + if (oriUri.empty()) { + return false; + } + uris.push_back(oriUri); + return true; + }); + EXPECT_EQ(uris.size(), 1); +} + +/** +* @tc.name: GetHtmlFileUris001 +* @tc.desc: Abnormal test of GetHtmlFileUris, uris is invalid +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfPreProcessUtilsTest, GetHtmlFileUris001, TestSize.Level1) +{ + uint32_t tokenId = 0; + UnifiedData data; + bool isLocal = false; + std::vector uris = {"test"}; + PreProcessUtils preProcessUtils; + EXPECT_NO_FATAL_FAILURE(preProcessUtils.GetHtmlFileUris(tokenId, data, isLocal, uris)); +} +}; // namespace UDMF \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/udmf_run_time_store_test.cpp b/datamgr_service/services/distributeddataservice/service/test/udmf_run_time_store_test.cpp index d8d440cf..e188e228 100644 --- a/datamgr_service/services/distributeddataservice/service/test/udmf_run_time_store_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/udmf_run_time_store_test.cpp @@ -29,6 +29,7 @@ #include "runtime_store.h" #include "text.h" #include "token_setproc.h" +#include "directory_manager.h" using namespace testing::ext; using namespace OHOS::DistributedData; @@ -91,7 +92,9 @@ public: const uint32_t MAX_VALUE_SIZE = 4 * 1024 * 1024; const std::string STORE_ID = "drag"; const std::string KEY_PREFIX = "TEST_"; + const std::string SUMMARY_KEY_PREFIX = "SUMMARY_KEY_PREFIX"; const std::string EMPTY_DEVICE_ID = ""; + const std::string BUNDLE_NAME = "udmf_test"; static constexpr size_t tempUdataRecordSize = 1; }; @@ -124,6 +127,9 @@ HWTEST_F(UdmfRunTimeStoreTest, PutEntries001, TestSize.Level1) bool result = store->Init(); EXPECT_EQ(true, result); + auto status = store->Delete(KEY_PREFIX); + EXPECT_EQ(E_OK, status); + Key key; Value value; GetRandomValue(value, MAX_KEY_SIZE); // 1K @@ -133,7 +139,7 @@ HWTEST_F(UdmfRunTimeStoreTest, PutEntries001, TestSize.Level1) entrysRand.push_back({ key, value }); } - int32_t status = store->PutEntries(entrysRand); + status = store->PutEntries(entrysRand); EXPECT_EQ(E_OK, status); vector entries; @@ -412,24 +418,17 @@ HWTEST_F(UdmfRunTimeStoreTest, Get001, TestSize.Level1) bool result = store->Init(); EXPECT_TRUE(result); - Key key; Key keyInvalid; Value value; - Value valueInvalid; - GetRandomKey(key, MAX_KEY_SIZE); // 1K GetRandomKey(keyInvalid, MAX_KEY_SIZE + 1); // 1K + 1 GetRandomValue(value, MAX_VALUE_SIZE); // 4M - GetRandomValue(valueInvalid, MAX_VALUE_SIZE + 1); // 4M + 1 vector entrysMix1(1, { keyInvalid, value }); - vector entrysMix2(1, { key, valueInvalid }); - UnifiedData unifiedData; int32_t status = store->PutEntries(entrysMix1); EXPECT_EQ(E_DB_ERROR, status); + entrysMix1.clear(); status = store->GetEntries(KEY_PREFIX, entrysMix1); EXPECT_EQ(E_OK, status); - - status = store->Get(KEY_PREFIX, unifiedData); - EXPECT_EQ(E_NOT_FOUND, status); + EXPECT_TRUE(entrysMix1.empty()); status = store->Delete(KEY_PREFIX); EXPECT_EQ(E_OK, status); @@ -458,11 +457,10 @@ HWTEST_F(UdmfRunTimeStoreTest, Get002, TestSize.Level1) } auto status = store->PutEntries(entrysRand); EXPECT_EQ(E_DB_ERROR, status); - status = store->GetEntries(EMPTY_DEVICE_ID, entrysRand); + entrysRand.clear(); + status = store->GetEntries(KEY_PREFIX, entrysRand); EXPECT_EQ(E_OK, status); - UnifiedData data1; - status = store->Get(EMPTY_DEVICE_ID, data1); - EXPECT_EQ(E_NOT_FOUND, status); + EXPECT_TRUE(entrysRand.empty()); status = store->Delete(KEY_PREFIX); EXPECT_EQ(E_OK, status); @@ -551,6 +549,88 @@ HWTEST_F(UdmfRunTimeStoreTest, GetDetailsFromUData01, TestSize.Level1) EXPECT_FALSE(status); } +/** +* @tc.name: Sync01 +* @tc.desc: check for legal parameters, delete entries error. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, Sync01, TestSize.Level1) +{ + std::vector devices = {"device"}; + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + Status ret = store->Sync(devices); + EXPECT_EQ(ret, E_DB_ERROR); +} + +/** +* @tc.name: Sync02 +* @tc.desc: check for legal parameters, delete entries error. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, Sync02, TestSize.Level1) +{ + std::vector devices = { }; + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + Status ret = store->Sync(devices); + EXPECT_EQ(ret, E_INVALID_PARAMETERS); +} + +/** +* @tc.name: Sync03 +* @tc.desc: check for legal parameters, delete entries error. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, Sync03, TestSize.Level1) +{ + std::vector devices = { "device" }; + ProcessCallback callback; + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + Status ret = store->Sync(devices, callback); + EXPECT_EQ(ret, E_DB_ERROR); +} + +/** +* @tc.name: Sync04 +* @tc.desc: check for legal parameters, delete entries error. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, Sync04, TestSize.Level1) +{ + std::vector devices = { }; + ProcessCallback callback; + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + Status ret = store->Sync(devices, callback); + EXPECT_EQ(ret, E_INVALID_PARAMETERS); +} + +/** +* @tc.name: Clear01 +* @tc.desc: check for legal parameters, delete entries error. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, Clear01, TestSize.Level1) +{ + static constexpr const char *DATA_PREFIX = "udmf://"; + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + Status ret = store->Clear(); + EXPECT_EQ(ret, store->Delete(DATA_PREFIX)); +} + /** * @tc.name: GetSummary * @tc.desc: check for legal parameters, delete entries error. @@ -562,18 +642,102 @@ HWTEST_F(UdmfRunTimeStoreTest, GetSummary, TestSize.Level1) auto store = std::make_shared(STORE_ID); bool result = store->Init(); EXPECT_TRUE(result); + Summary summary; + summary.summary = { + { "general.file", 10 }, + { "general.png", 10 }, + { "general.html", 10 }, + { "general.jpeg", 10 }, + { "general.avi", 10}, + { "aabbcc", 10} + }; + UnifiedKey key(SUMMARY_KEY_PREFIX); + auto status = store->PutSummary(key, summary); + EXPECT_EQ(status, E_OK); + status = store->GetSummary(key, summary); + ASSERT_EQ(status, E_OK); +} - UnifiedData data; - UDDetails details; - details.insert({ "udmf_key", "udmf_value" }); - auto text = std::make_shared(); - text->SetDetails(details); - data.AddRecord(text); - Summary summary; - UnifiedKey key(KEY_PREFIX); - auto status = store->GetSummary(key, summary); - ASSERT_EQ(status, E_DB_ERROR); +/** +* @tc.name: GetRuntime001 +* @tc.desc: Normal testcase of GetRuntime +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, GetRuntime001, TestSize.Level1) +{ + UnifiedKey udKey(STORE_ID, BUNDLE_NAME, UDMF::PreProcessUtils::GenerateId()); + Runtime runtime{ + .key = udKey + }; + UnifiedData inputData; + inputData.SetRuntime(runtime); + auto key = inputData.GetRuntime()->key.GetUnifiedKey(); + + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + auto status = store->PutRuntime(key, *inputData.GetRuntime()); + EXPECT_EQ(status, E_OK); + + Runtime outRuntime; + status = store->GetRuntime(key, outRuntime); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(inputData.GetRuntime()->createTime, outRuntime.createTime); +} + +/** +* @tc.name: GetRuntime002 +* @tc.desc: Abnormal testcase of GetRuntime +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, GetRuntime002, TestSize.Level1) +{ + UnifiedKey udKey(STORE_ID, BUNDLE_NAME, UDMF::PreProcessUtils::GenerateId()); + Runtime runtime{ + .key = udKey + }; + UnifiedData inputData; + inputData.SetRuntime(runtime); + auto key = inputData.GetRuntime()->key.GetUnifiedKey(); + + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + + Runtime outRuntime; + auto status = store->GetRuntime(key, outRuntime); + EXPECT_EQ(status, E_NOT_FOUND); +} + +/** +* @tc.name: MarkWhenCorrupted001 +* @tc.desc: Normal testcase of MarkWhenCorrupted +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, MarkWhenCorrupted001, TestSize.Level1) +{ + DistributedDB::DBStatus status = DistributedDB::DBStatus::OK; + auto store = std::make_shared(STORE_ID); + store->MarkWhenCorrupted(status); + EXPECT_FALSE(store->isCorrupted_); +} + +/** +* @tc.name: MarkWhenCorrupted001 +* @tc.desc: Normal testcase of MarkWhenCorrupted +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, MarkWhenCorrupted002, TestSize.Level1) +{ + DistributedDB::DBStatus status = DistributedDB::DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; + auto store = std::make_shared(STORE_ID); + store->MarkWhenCorrupted(status); + EXPECT_TRUE(store->isCorrupted_); } }; // namespace DistributedDataTest }; // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/udmf_service_impl_mock_test.cpp b/datamgr_service/services/distributeddataservice/service/test/udmf_service_impl_mock_test.cpp new file mode 100644 index 00000000..9daa166f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/udmf_service_impl_mock_test.cpp @@ -0,0 +1,140 @@ +/* +* 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. +*/ + +#define LOG_TAG "UdmfServiceImplMockTest" +#include "udmf_service_impl.h" +#include "gtest/gtest.h" +#include "error_code.h" +#include "text.h" +#include "accesstoken_kit.h" +#include "bootstrap.h" +#include "executor_pool.h" +#include "ipc_skeleton.h" +#include "mock/access_token_mock.h" +#include "mock/meta_data_manager_mock.h" +#include "nativetoken_kit.h" +#include "token_setproc.h" +#include "kvstore_meta_manager.h" +using namespace OHOS::DistributedData; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; +using namespace testing::ext; +using namespace testing; + +namespace OHOS::Test { +namespace DistributedDataTest { +class UdmfServiceImplMockTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + accTokenMock = std::make_shared(); + BAccessTokenKit::accessTokenkit = accTokenMock; + metaDataManagerMock = std::make_shared(); + BMetaDataManager::metaDataManager = metaDataManagerMock; + metaDataMock = std::make_shared>(); + BMetaData::metaDataManager = metaDataMock; + } + static void TearDownTestCase(void) + { + accTokenMock = nullptr; + BAccessTokenKit::accessTokenkit = nullptr; + metaDataManagerMock = nullptr; + BMetaDataManager::metaDataManager = nullptr; + metaDataMock = nullptr; + BMetaData::metaDataManager = nullptr; + } + static inline std::shared_ptr accTokenMock = nullptr; + static inline std::shared_ptr metaDataManagerMock = nullptr; + static inline std::shared_ptr> metaDataMock = nullptr; + void SetUp() {}; + void TearDown() {}; +}; + +/** +* @tc.name: IsNeedMetaSyncTest001 +* @tc.desc: IsNeedMetaSync test +* @tc.type: FUNC +*/ +HWTEST_F(UdmfServiceImplMockTest, IsNeedMetaSyncTest001, TestSize.Level0) +{ + UdmfServiceImpl udmfServiceImpl; + StoreMetaData meta = StoreMetaData("100", "distributeddata", "drag"); + std::vector devices = {"remote_device"}; + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(Return(false)); + auto isNeedSync = udmfServiceImpl.IsNeedMetaSync(meta, devices); + EXPECT_EQ(isNeedSync, true); + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(Return(false)); + isNeedSync = udmfServiceImpl.IsNeedMetaSync(meta, devices); + EXPECT_EQ(isNeedSync, true); + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(Return(true)) + .WillOnce(Return(false)); + isNeedSync = udmfServiceImpl.IsNeedMetaSync(meta, devices); + EXPECT_EQ(isNeedSync, true); + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(Return(true)) + .WillOnce(Return(true)); + isNeedSync = udmfServiceImpl.IsNeedMetaSync(meta, devices); + EXPECT_EQ(isNeedSync, true); +} + +/** +* @tc.name: IsNeedMetaSyncTest002 +* @tc.desc: IsNeedMetaSync test matrix mask +* @tc.type: FUNC +*/ +HWTEST_F(UdmfServiceImplMockTest, IsNeedMetaSyncTest002, TestSize.Level0) +{ + QueryOption query; + query.key = "test_key"; + query.tokenId = 1; + query.intention = UD_INTENTION_DRAG; + UdmfServiceImpl udmfServiceImpl; + StoreMetaData meta = StoreMetaData("100", "distributeddata", "drag"); + std::vector devices = {"remote_device"}; + + EXPECT_CALL(*metaDataManagerMock, LoadMeta(_, _, _)) + .WillOnce(Return(false)) + .WillOnce(Return(false)); + auto isNeedSync = udmfServiceImpl.IsNeedMetaSync(meta, devices); + EXPECT_EQ(isNeedSync, true); + // mock mask +} + +/** + * @tc.name: ResolveAutoLaunchTest001 + * @tc.desc: ResolveAutoLaunch test. + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplMockTest, ResolveAutoLaunchTest001, TestSize.Level0) +{ + DistributedDB::AutoLaunchParam param { + .userId = "100", + .appId = "distributeddata", + .storeId = "drag", + }; + std::string identifier = "identifier"; + std::shared_ptr udmfServiceImpl = std::make_shared(); + auto ret = udmfServiceImpl->ResolveAutoLaunch(identifier, param); + EXPECT_EQ(ret, UDMF::E_NOT_FOUND); +} +}; // DistributedDataTest +}; // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/udmf_service_impl_test.cpp b/datamgr_service/services/distributeddataservice/service/test/udmf_service_impl_test.cpp index d93a5590..9a32e158 100644 --- a/datamgr_service/services/distributeddataservice/service/test/udmf_service_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/udmf_service_impl_test.cpp @@ -15,19 +15,80 @@ #define LOG_TAG "UdmfServiceImplTest" #include "udmf_service_impl.h" +#include "accesstoken_kit.h" +#include "account_delegate.h" +#include "bootstrap.h" +#include "device_manager_adapter.h" +#include "executor_pool.h" #include "gtest/gtest.h" -#include "error_code.h" +#include "ipc_skeleton.h" +#include "kvstore_meta_manager.h" +#include "metadata/meta_data_manager.h" +#include "nativetoken_kit.h" +#include "preprocess_utils.h" +#include "runtime_store.h" #include "text.h" +#include "plain_text.h" +#include "token_setproc.h" -using namespace OHOS::DistributedData; -namespace OHOS::UDMF { using namespace testing::ext; +using namespace OHOS::DistributedData; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; +using Entry = DistributedDB::Entry; +using Key = DistributedDB::Key; +using Value = DistributedDB::Value; +using UnifiedData = OHOS::UDMF::UnifiedData; +using Summary = OHOS::UDMF::Summary; +namespace OHOS::Test { +namespace DistributedDataTest { + +static void GrantPermissionNative() +{ + const char **perms = new const char *[3]; + perms[0] = "ohos.permission.DISTRIBUTED_DATASYNC"; + perms[1] = "ohos.permission.ACCESS_SERVICE_DM"; + perms[2] = "ohos.permission.MONITOR_DEVICE_NETWORK_STATE"; // perms[2] is a permission parameter + TokenInfoParams infoInstance = { + .dcapsNum = 0, + .permsNum = 3, + .aclsNum = 0, + .dcaps = nullptr, + .perms = perms, + .acls = nullptr, + .processName = "distributed_data_test", + .aplStr = "system_basic", + }; + uint64_t tokenId = GetAccessTokenId(&infoInstance); + SetSelfTokenID(tokenId); + AccessTokenKit::ReloadNativeTokenInfo(); + delete[] perms; +} + class UdmfServiceImplTest : public testing::Test { public: - static void SetUpTestCase(void) {} - static void TearDownTestCase(void) {} - void SetUp() {} - void TearDown() {} + static void SetUpTestCase(void) + { + GrantPermissionNative(); + DistributedData::Bootstrap::GetInstance().LoadComponents(); + DistributedData::Bootstrap::GetInstance().LoadDirectory(); + DistributedData::Bootstrap::GetInstance().LoadCheckers(); + size_t max = 2; + size_t min = 1; + auto executors = std::make_shared(max, min); + DmAdapter::GetInstance().Init(executors); + DistributedKv::KvStoreMetaManager::GetInstance().BindExecutor(executors); + DistributedKv::KvStoreMetaManager::GetInstance().InitMetaParameter(); + DistributedKv::KvStoreMetaManager::GetInstance().InitMetaListener(); + } + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; + + static constexpr const char *STORE_ID = "drag"; + static constexpr uint32_t TOKEN_ID = 5; + static constexpr const char *APP_ID = "appId"; }; /** @@ -119,7 +180,22 @@ HWTEST_F(UdmfServiceImplTest, Sync001, TestSize.Level1) std::vector devices = {"device1"}; UdmfServiceImpl udmfServiceImpl; int32_t ret = udmfServiceImpl.Sync(query, devices); - EXPECT_EQ(ret, E_INVALID_PARAMETERS); + EXPECT_EQ(ret, E_NO_PERMISSION); +} + +/** +* @tc.name: VerifyPermission001 +* @tc.desc: Abnormal test of VerifyPermission, permission is empty +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplTest, VerifyPermission001, TestSize.Level1) +{ + std::string permission; + uint32_t callerTokenId = 0; + UdmfServiceImpl udmfServiceImpl; + bool ret = udmfServiceImpl.VerifyPermission(permission, callerTokenId); + EXPECT_FALSE(ret); } /** @@ -206,14 +282,163 @@ HWTEST_F(UdmfServiceImplTest, SetAppShareOption004, TestSize.Level1) */ HWTEST_F(UdmfServiceImplTest, OnUserChangeTest001, TestSize.Level1) { - uint32_t code = 4; + // Clear store + StoreCache::GetInstance().CloseStores(); + auto stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 0); + // Init store + StoreCache::GetInstance().GetStore("SystemShare"); + stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 1); + + uint32_t code = static_cast(DistributedData::AccountStatus::DEVICE_ACCOUNT_STOPPING); + std::string user = "OH_USER_test"; + std::string account = "OH_ACCOUNT_test"; + UdmfServiceImpl udmfServiceImpl; + auto status = udmfServiceImpl.OnUserChange(code, user, account); + ASSERT_EQ(status, UDMF::E_OK); + stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 0); +} + +/** +* @tc.name: OnUserChangeTest002 +* @tc.desc: OnUserChange test +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplTest, OnUserChangeTest002, TestSize.Level1) +{ + // Clear store + StoreCache::GetInstance().CloseStores(); + auto stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 0); + // Init store + StoreCache::GetInstance().GetStore(STORE_ID); + stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 1); + + uint32_t code = static_cast(DistributedData::AccountStatus::DEVICE_ACCOUNT_STOPPED); std::string user = "OH_USER_test"; std::string account = "OH_ACCOUNT_test"; UdmfServiceImpl udmfServiceImpl; auto status = udmfServiceImpl.OnUserChange(code, user, account); - ASSERT_EQ(status, E_OK); - auto sizeAfter = StoreCache::GetInstance().stores_.Size(); - ASSERT_EQ(sizeAfter, 0); + ASSERT_EQ(status, UDMF::E_OK); + stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 0); +} + +/** +* @tc.name: OnUserChangeTest003 +* @tc.desc: OnUserChange test +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplTest, OnUserChangeTest003, TestSize.Level1) +{ + // Clear store + StoreCache::GetInstance().CloseStores(); + auto stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 0); + // Init store + StoreCache::GetInstance().GetStore(STORE_ID); + stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 1); + + uint32_t code = static_cast(DistributedData::AccountStatus::DEVICE_ACCOUNT_SWITCHED); + std::string user = "OH_USER_test"; + std::string account = "OH_ACCOUNT_test"; + UdmfServiceImpl udmfServiceImpl; + auto status = udmfServiceImpl.OnUserChange(code, user, account); + ASSERT_EQ(status, UDMF::E_OK); + stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 0); +} + +/** +* @tc.name: OnUserChangeTest004 +* @tc.desc: OnUserChange test +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplTest, OnUserChangeTest004, TestSize.Level1) +{ + // Clear store + StoreCache::GetInstance().CloseStores(); + auto stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 0); + // Init store + StoreCache::GetInstance().GetStore(STORE_ID); + stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 1); + + uint32_t code = static_cast(DistributedData::AccountStatus::DEVICE_ACCOUNT_UNLOCKED); + std::string user = "OH_USER_test"; + std::string account = "OH_ACCOUNT_test"; + UdmfServiceImpl udmfServiceImpl; + auto status = udmfServiceImpl.OnUserChange(code, user, account); + ASSERT_EQ(status, UDMF::E_OK); + stores = StoreCache::GetInstance().stores_.Size(); + ASSERT_EQ(stores, 1); +} + +/** +* @tc.name: SaveMetaData001 +* @tc.desc: Abnormal testcase of GetRuntime +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplTest, SaveMetaData001, TestSize.Level0) +{ + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + + result = store->Init(); + EXPECT_TRUE(result); +} + +/** +* @tc.name: SaveMetaData001 +* @tc.desc: Abnormal testcase of GetRuntime +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplTest, SyncTest001, TestSize.Level0) +{ + QueryOption query; + query.key = "udmf://drag/ohos.test.demo1/_aS6adWi7 devices = {"remote_device"}; + + auto ret = udmfServiceImpl.Sync(query, devices); + EXPECT_EQ(ret, UDMF::E_NO_PERMISSION); +} + +/** +* @tc.name: ResolveAutoLaunch001 +* @tc.desc: test ResolveAutoLaunch +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfServiceImplTest, ResolveAutoLaunch001, TestSize.Level0) +{ + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_TRUE(result); + + DistributedDB::AutoLaunchParam param { + .userId = "100", + .appId = "distributeddata", + .storeId = "drag", + }; + std::string identifier = "identifier"; + std::shared_ptr udmfServiceImpl = std::make_shared(); + auto ret = udmfServiceImpl->ResolveAutoLaunch(identifier, param); + EXPECT_EQ(ret, UDMF::E_OK); } /** @@ -240,4 +465,216 @@ HWTEST_F(UdmfServiceImplTest, TransferToEntriesIfNeedTest001, TestSize.Level1) int recordSize = 2; EXPECT_EQ(data.GetRecords().size(), recordSize); } -}; // namespace UDMF \ No newline at end of file +/** + * @tc.name: IsValidInput001 + * @tc.desc: invalid unifiedData + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, IsValidInput001, TestSize.Level1) +{ + QueryOption query; + UnifiedData unifiedData; + UnifiedKey key; + + UdmfServiceImpl impl; + bool result = impl.IsValidInput(query, unifiedData, key); + EXPECT_FALSE(result); +} + +/** + * @tc.name: IsValidInput002 + * @tc.desc: invalid key + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, IsValidInput002, TestSize.Level1) +{ + QueryOption query; + UnifiedData unifiedData; + auto record1 = std::make_shared(); + auto record2 = std::make_shared(); + unifiedData.AddRecord(record1); + unifiedData.AddRecord(record2); + UnifiedKey key; + + UdmfServiceImpl impl; + bool result = impl.IsValidInput(query, unifiedData, key); + EXPECT_FALSE(result); +} + +/** + * @tc.name: IsValidInput003 + * @tc.desc: valid input + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, IsValidInput003, TestSize.Level1) +{ + QueryOption query; + query.intention = Intention::UD_INTENTION_DATA_HUB; + query.key = "udmf://DataHub/aaa/N]2fIEMbrJj@wp:jMuPa7"; + UnifiedData unifiedData; + auto record1 = std::make_shared(); + auto record2 = std::make_shared(); + unifiedData.AddRecord(record1); + unifiedData.AddRecord(record2); + UnifiedKey key("udmf://DataHub/aaa/N]2fIEMbrJj@wp:jMuPa7"); + EXPECT_TRUE(key.IsValid()); + + UdmfServiceImpl impl; + bool result = impl.IsValidInput(query, unifiedData, key); + EXPECT_TRUE(result); +} + +/** + * @tc.name: IsValidInput004 + * @tc.desc: invalid intention + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, IsValidInput004, TestSize.Level1) +{ + QueryOption query; + query.intention = Intention::UD_INTENTION_DRAG; + UnifiedData unifiedData; + UnifiedKey key("udmf://drag/aaa/N]2fIEMbrJj@wp:jMuPa7"); + + UdmfServiceImpl impl; + bool result = impl.IsValidInput(query, unifiedData, key); + EXPECT_FALSE(result); +} + +/** + * @tc.name: CheckAppId001 + * @tc.desc: invalid bundleName + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, CheckAppId001, TestSize.Level1) +{ + std::shared_ptr runtime = std::make_shared(); + runtime->appId = "appId"; + std::string bundleName = "ohos.test.demo1"; + + UdmfServiceImpl impl; + int32_t result = impl.CheckAppId(runtime, bundleName); + EXPECT_EQ(result, E_INVALID_PARAMETERS); +} + +/** + * @tc.name: CheckAppId002 + * @tc.desc: invalid runtime + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, CheckAppId002, TestSize.Level1) +{ + std::shared_ptr runtime = std::make_shared(); + std::string bundleName = "ohos.test.demo1"; + + UdmfServiceImpl impl; + int32_t result = impl.CheckAppId(runtime, bundleName); + EXPECT_EQ(result, E_INVALID_PARAMETERS); +} + +/** +* @tc.name: CheckDeleteDataPermission001 +* @tc.desc: runtime is null +* @tc.type: FUNC +*/ +HWTEST_F(UdmfServiceImplTest, CheckDeleteDataPermission001, TestSize.Level1) +{ + std::string appId; + std::shared_ptr runtime; + QueryOption query; + UdmfServiceImpl impl; + bool ret = impl.CheckDeleteDataPermission(appId, runtime, query); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: CheckDeleteDataPermission002 +* @tc.desc: query.tokenId is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UdmfServiceImplTest, CheckDeleteDataPermission002, TestSize.Level1) +{ + std::string appId; + std::shared_ptr runtime = std::make_shared(); + runtime->tokenId = TOKEN_ID; + QueryOption query; + UdmfServiceImpl impl; + bool ret = impl.CheckDeleteDataPermission(appId, runtime, query); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: CheckDeleteDataPermission003 +* @tc.desc: Normal test +* @tc.type: FUNC +*/ +HWTEST_F(UdmfServiceImplTest, CheckDeleteDataPermission003, TestSize.Level1) +{ + std::string appId; + std::shared_ptr runtime = std::make_shared(); + runtime->tokenId = TOKEN_ID; + QueryOption query; + query.tokenId = TOKEN_ID; + UdmfServiceImpl impl; + bool ret = impl.CheckDeleteDataPermission(appId, runtime, query); + EXPECT_TRUE(ret); +} + +/** +* @tc.name: CheckDeleteDataPermission004 +* @tc.desc: bundleName is empty +* @tc.type: FUNC +*/ +HWTEST_F(UdmfServiceImplTest, CheckDeleteDataPermission004, TestSize.Level1) +{ + std::string appId; + std::shared_ptr runtime = std::make_shared(); + runtime->appId = APP_ID; + QueryOption query; + query.tokenId = TOKEN_ID; + UdmfServiceImpl impl; + bool ret = impl.CheckDeleteDataPermission(appId, runtime, query); + EXPECT_FALSE(ret); +} + +/** + * @tc.name: VerifyDataAccessPermission001 + * @tc.desc: no permission + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, VerifyDataAccessPermission001, TestSize.Level1) +{ + std::shared_ptr runtime = std::make_shared(); + const QueryOption query; + UnifiedData unifiedData; + + UdmfServiceImpl impl; + auto result = impl.VerifyDataAccessPermission(runtime, query, unifiedData); + EXPECT_EQ(result, E_NO_PERMISSION); +} + +/** + * @tc.name: VerifyDataAccessPermission002 + * @tc.desc: runtime is nullptr + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, VerifyDataAccessPermission002, TestSize.Level1) +{ + std::shared_ptr runtime = std::make_shared(); + Privilege privilege { + .tokenId = TOKEN_ID, + .readPermission = STORE_ID, + .writePermission = STORE_ID, + }; + runtime->privileges = { privilege }; + QueryOption query; + query.tokenId = TOKEN_ID; + UnifiedData unifiedData; + + UdmfServiceImpl impl; + auto result = impl.VerifyDataAccessPermission(runtime, query, unifiedData); + EXPECT_EQ(runtime->privileges[0].tokenId, query.tokenId); + EXPECT_EQ(result, OHOS::UDMF::E_OK); +} +}; // namespace DistributedDataTest +}; // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/service/test/unittest/cloud/cloud_data_test.cpp b/datamgr_service/services/distributeddataservice/service/test/unittest/cloud/cloud_data_test.cpp index 9229bd8a..ba36cc02 100644 --- a/datamgr_service/services/distributeddataservice/service/test/unittest/cloud/cloud_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/unittest/cloud/cloud_data_test.cpp @@ -194,7 +194,7 @@ HWTEST_F(CloudDataTest, GetSchemaTest001, TestSize.Level0) auto event = std::make_unique(CloudEvent::GET_SCHEMA, std::move(storeInfo)); EventCenter::GetInstance().PostEvent(std::move(event)); ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true)); - ASSERT_EQ(to_string(schemaMeta.Marshall()), to_string(SCHEMA_META.Marshall())); + ASSERT_EQ(schemaMeta.Marshall().dump(), SCHEMA_META.Marshall().dump()); } /** diff --git a/datamgr_service/services/distributeddataservice/service/test/user_delegate_mock_test.cpp b/datamgr_service/services/distributeddataservice/service/test/user_delegate_mock_test.cpp index 373782b7..5a40b23a 100644 --- a/datamgr_service/services/distributeddataservice/service/test/user_delegate_mock_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/user_delegate_mock_test.cpp @@ -13,12 +13,14 @@ * limitations under the License. */ -#include #include -#include "user_delegate.h" -#include "device_manager_adapter_mock.h" +#include + #include "account_delegate_mock.h" +#include "device_manager_adapter_mock.h" #include "metadata/meta_data_manager.h" +#include "user_delegate.h" + using namespace OHOS::DistributedData; using namespace testing::ext; @@ -39,27 +41,48 @@ bool MetaDataManager::Subscribe(std::string prefix, Observer observer, bool isLo return false; } +bool MetaDataManager::SaveMeta(const std::string &key, const Serializable &value, bool isLocal) +{ + (void)key; + (void)value; + return true; +} + namespace OHOS::Test { namespace DistributedDataTest { class UserDelegateMockTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); - void SetUp() {} - void TearDown() {} + void SetUp() + { + } + void TearDown() + { + } static inline shared_ptr devMgrAdapterMock = nullptr; + static inline AccountDelegateMock *accountDelegateMock = nullptr; }; void UserDelegateMockTest::SetUpTestCase(void) { devMgrAdapterMock = make_shared(); BDeviceManagerAdapter::deviceManagerAdapter = devMgrAdapterMock; + accountDelegateMock = new (std::nothrow) AccountDelegateMock(); + if (accountDelegateMock != nullptr) { + AccountDelegate::instance_ = nullptr; + AccountDelegate::RegisterAccountInstance(accountDelegateMock); + } } void UserDelegateMockTest::TearDownTestCase(void) { BDeviceManagerAdapter::deviceManagerAdapter = nullptr; devMgrAdapterMock = nullptr; + if (accountDelegateMock != nullptr) { + delete accountDelegateMock; + accountDelegateMock = nullptr; + } } /** @@ -84,13 +107,12 @@ HWTEST_F(UserDelegateMockTest, GetLocalUserStatus, TestSize.Level0) */ HWTEST_F(UserDelegateMockTest, InitLocalUserMeta, TestSize.Level0) { - EXPECT_CALL(AccountDelegateMock::Init(), QueryUsers(_)).WillOnce(Return(false)); + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(Return(false)); bool ret = UserDelegate::GetInstance().InitLocalUserMeta(); EXPECT_FALSE(ret); std::vector users; - EXPECT_CALL(AccountDelegateMock::Init(), QueryUsers(_)) - .WillRepeatedly(DoAll(SetArgReferee<0>(users), Return(true))); + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).Times(1).WillOnce(DoAll(SetArgReferee<0>(users), Return(true))); ret = UserDelegate::GetInstance().InitLocalUserMeta(); UserDelegate::GetInstance().DeleteUsers("users"); EXPECT_FALSE(ret); @@ -137,15 +159,20 @@ HWTEST_F(UserDelegateMockTest, GetUsers, TestSize.Level0) */ HWTEST_F(UserDelegateMockTest, Init, TestSize.Level0) { - EXPECT_CALL(AccountDelegateMock::Init(), Subscribe(_)).WillRepeatedly(Return(0)); + EXPECT_CALL(*accountDelegateMock, Subscribe(_)).WillRepeatedly(Return(0)); DeviceInfo devInfo = { .uuid = "HJJ4FGAGAAGA45WF3663FAGA" }; EXPECT_CALL(*devMgrAdapterMock, GetLocalDevice()).WillRepeatedly(Return(devInfo)); - std::shared_ptr poolPtr = std::make_shared(0, 1); + std::shared_ptr poolPtr = std::make_shared(1, 0); ASSERT_NE(poolPtr, nullptr); - UserDelegate::GetInstance().executors_ = poolPtr; - ASSERT_NE(UserDelegate::GetInstance().executors_, nullptr); - UserDelegate::GetInstance().Init(poolPtr); - ASSERT_TRUE(UserDelegate::GetInstance().executors_ != nullptr); -} + UserDelegate instance; + instance.executors_ = poolPtr; + ASSERT_NE(instance.executors_, nullptr); + + std::vector users = { 0, 1 }; + EXPECT_CALL(*accountDelegateMock, QueryUsers(_)).WillRepeatedly(DoAll(SetArgReferee<0>(users), Return(true))); + EXPECT_TRUE(instance.InitLocalUserMeta()); + instance.Init(poolPtr); + ASSERT_TRUE(instance.executors_ != nullptr); } -} \ No newline at end of file +} // namespace DistributedDataTest +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/value_proxy_test.cpp b/datamgr_service/services/distributeddataservice/service/test/value_proxy_test.cpp index 66deaa95..469d2230 100644 --- a/datamgr_service/services/distributeddataservice/service/test/value_proxy_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/value_proxy_test.cpp @@ -373,30 +373,30 @@ HWTEST_F(ValueProxyServiceTest, AssetsOperator001, TestSize.Level0) ValueProxy::Assets proxy1; ValueProxy::Assets proxy2; ValueProxy::Assets proxy3; - DistributedDB::Asset asset; - asset.version = 1; - asset.status = DistributedData::Asset::Status::STATUS_INSERT; - asset.name = "Asset1"; - asset.uri = "uri1"; - asset.size = "1"; - asset.hash = "hash1"; - proxy1.assets_.push_back(asset); - - asset.version = 2; - asset.status = DistributedData::Asset::Status::STATUS_NORMAL; - asset.name = "Asset2"; - asset.uri = "uri2"; - asset.size = "2"; - asset.hash = "hash2"; - proxy2.assets_.push_back(asset); - - asset.version = 3; - asset.status = DistributedData::Asset::Status::STATUS_NORMAL; - asset.name = "Asset3"; - asset.uri = "uri3"; - asset.size = "3"; - asset.hash = "hash3"; - proxy2.assets_.push_back(asset); + proxy1.assets_.push_back(ValueProxy::Asset(DistributedDB::Asset { + .version = 1, + .status = DistributedData::Asset::Status::STATUS_INSERT, + .name = "Asset1", + .uri = "uri1", + .size = "1", + .hash = "hash1", + })); + proxy2.assets_.push_back(ValueProxy::Asset(DistributedDB::Asset { + .version = 2, + .status = DistributedData::Asset::Status::STATUS_NORMAL, + .name = "Asset2", + .uri = "uri2", + .size = "2", + .hash = "hash2", + })); + proxy2.assets_.push_back(ValueProxy::Asset(DistributedDB::Asset { + .version = 3, + .status = DistributedData::Asset::Status::STATUS_NORMAL, + .name = "Asset3", + .uri = "uri3", + .size = "3", + .hash = "hash3", + })); // operator "=" same asset case proxy3 = proxy1; proxy1 = proxy3; @@ -406,7 +406,7 @@ HWTEST_F(ValueProxyServiceTest, AssetsOperator001, TestSize.Level0) EXPECT_EQ(proxy1.assets_.size(), 2); // operator Distributeddata Asset() - asset = proxy1.assets_[0]; + DistributedData::Asset asset = proxy1.assets_[0]; EXPECT_EQ(asset.version, 2); // operator "=" noexcept same asset case @@ -427,19 +427,19 @@ HWTEST_F(ValueProxyServiceTest, AssetOperator001, TestSize.Level0) { ValueProxy::Asset asset1 = DistributedDB::Asset { .version = 1, + .status = DistributedData::Asset::Status::STATUS_INSERT, .name = "Asset1", .uri = "uri1", .size = "1", .hash = "hash1", - .status = DistributedData::Asset::Status::STATUS_INSERT, }; ValueProxy::Asset asset2 = DistributedDB::Asset { .version = 2, + .status = DistributedData::Asset::Status::STATUS_NORMAL, .name = "Asset2", .uri = "uri2", .size = "2", .hash = "hash2", - .status = DistributedData::Asset::Status::STATUS_NORMAL, }; ValueProxy::Asset asset3 = asset1; DistributedData::Asset asset = asset3; diff --git a/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn b/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn index 971ab272..6ac31730 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn @@ -17,10 +17,9 @@ config("module_public_config") { visibility = [ ":*" ] include_dirs = [ - "${data_service_path}/framework/include", - "${data_service_path}/framework/include/dfx", "${data_service_path}/adapter/include/communicator", - "${data_service_path}/adapter/include/account", + "${data_service_path}/service/matrix/include", + "${data_service_path}/service/permission/include", "${data_service_path}/service/udmf/lifecycle", "${data_service_path}/service/udmf/permission", "${data_service_path}/service/udmf/preprocess", @@ -28,13 +27,6 @@ config("module_public_config") { "${data_service_path}/service/udmf/utd", "${data_service_path}/service/udmf", "${data_service_path}/service/bootstrap/include", - "${kv_store_path}/interfaces/innerkits/distributeddata/include", - "${kv_store_path}/framework/libs/distributeddb/interfaces/include", - "${kv_store_common_path}", - "${udmf_path}/framework/common", - "${udmf_path}/interfaces/innerkits/common", - "${udmf_path}/interfaces/innerkits/data", - "${data_service_path}/adapter/account/src", ] } @@ -57,8 +49,8 @@ ohos_source_set("udmf_server") { "permission/uri_permission_manager.cpp", "preprocess/data_handler.cpp", "preprocess/preprocess_utils.cpp", + "preprocess/udmf_notifier_proxy.cpp", "store/runtime_store.cpp", - "store/store_account_observer.cpp", "store/store_cache.cpp", "udmf_service_impl.cpp", "udmf_service_stub.cpp", @@ -70,10 +62,12 @@ ohos_source_set("udmf_server") { "-D_LIBCPP_HAS_COND_CLOCKWAIT", "-Werror", "-Oz", - "-fstack-protector-strong", ] - deps = [ "${data_service_path}/framework:distributeddatasvcfwk" ] + deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service/permission:distributeddata_permit" + ] external_deps = [ "ability_base:zuri", @@ -83,11 +77,13 @@ ohos_source_set("udmf_server") { "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", "device_manager:devicemanagersdk", + "dfs_service:distributed_file_daemon_kit_inner", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", "hitrace:libhitracechain", "ipc:ipc_core", + "kv_store:datamgr_common", "kv_store:distributeddb", "udmf:udmf_client", "udmf:utd_client", @@ -95,7 +91,6 @@ ohos_source_set("udmf_server") { cflags_cc = [ "-fvisibility=hidden", "-Oz", - "-fstack-protector-strong", ] subsystem_name = "distributeddatamgr" diff --git a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_manager.cpp b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_manager.cpp index cbfdca07..e427c2e7 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_manager.cpp @@ -23,6 +23,9 @@ namespace UDMF { using CleanAfterGet = LifeCyclePolicy; std::unordered_map> LifeCycleManager::intentionPolicy_ = { { UD_INTENTION_MAP.at(UD_INTENTION_DRAG), std::make_shared() }, + { UD_INTENTION_MAP.at(UD_INTENTION_PICKER), std::make_shared() }, + { UD_INTENTION_MAP.at(UD_INTENTION_MENU), std::make_shared() }, + { UD_INTENTION_MAP.at(UD_INTENTION_SYSTEM_SHARE), std::make_shared() }, { UD_INTENTION_MAP.at(UD_INTENTION_DATA_HUB), std::make_shared() } }; diff --git a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.cpp b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.cpp index cc3d8865..5651c916 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.cpp @@ -30,7 +30,7 @@ Status LifeCyclePolicy::OnGot(const UnifiedKey &key) ZLOGE("Get store failed:%{public}s", key.intention.c_str()); return E_DB_ERROR; } - if (store->Delete(key.key) != E_OK) { + if (store->Delete(UnifiedKey(key.key).GetKeyCommonPrefix()) != E_OK) { ZLOGE("Remove data failed:%{public}s", key.intention.c_str()); return E_DB_ERROR; } @@ -59,6 +59,8 @@ Status LifeCyclePolicy::OnTimeout(const std::string &intention) return E_DB_ERROR; } std::vector timeoutKeys; + Duration interval = INTERVAL; + CheckFileMangerIntention(intention, interval); auto status = GetTimeoutKeys(store, INTERVAL, timeoutKeys); if (status != E_OK) { ZLOGE("Timeout keys get failed"); @@ -92,10 +94,20 @@ Status LifeCyclePolicy::GetTimeoutKeys( } if (curTime > data.GetRuntime()->createTime + duration_cast(interval).count() || curTime < data.GetRuntime()->createTime) { - timeoutKeys.push_back(data.GetRuntime()->key.key); + timeoutKeys.push_back(UnifiedKey(data.GetRuntime()->key.key).GetKeyCommonPrefix()); } } return E_OK; } + +Status LifeCyclePolicy::CheckFileMangerIntention(const std::string &intention, Duration &interval) +{ + if (intention == UD_INTENTION_MAP.at(UD_INTENTION_SYSTEM_SHARE) || + intention == UD_INTENTION_MAP.at(UD_INTENTION_PICKER) || + intention == UD_INTENTION_MAP.at(UD_INTENTION_MENU)) { + interval = SYSTEM_SHARE_INTERVAL; + } + return E_OK; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.h b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.h index f7703e56..2979965d 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/lifecycle/lifecycle_policy.h @@ -23,6 +23,7 @@ class LifeCyclePolicy { public: using Duration = std::chrono::steady_clock::duration; static constexpr Duration INTERVAL = std::chrono::milliseconds(60 * 60 * 1000); + static constexpr Duration SYSTEM_SHARE_INTERVAL = std::chrono::milliseconds(24 * 60 * 60 * 1000); virtual ~LifeCyclePolicy() = default; virtual Status OnGot(const UnifiedKey &key); virtual Status OnStart(const std::string &intention); @@ -31,6 +32,7 @@ public: const std::shared_ptr &store, Duration interval, std::vector &timeoutKeys); private: + Status CheckFileMangerIntention(const std::string &intention, Duration &interval); static constexpr const char *DATA_PREFIX = "udmf://"; }; } // namespace UDMF diff --git a/datamgr_service/services/distributeddataservice/service/udmf/permission/checker_manager.h b/datamgr_service/services/distributeddataservice/service/udmf/permission/checker_manager.h index bb892e15..72991aec 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/permission/checker_manager.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/permission/checker_manager.h @@ -24,7 +24,7 @@ namespace UDMF { class CheckerManager { public: struct CheckInfo { - uint32_t tokenId; + uint32_t tokenId {0}; }; class Checker { @@ -41,7 +41,7 @@ public: bool IsValid(const std::vector &privileges, const CheckInfo &info); private: - std::map checkers_; + std::map checkers_ {}; ConcurrentMap> getters_; }; } // namespace UDMF diff --git a/datamgr_service/services/distributeddataservice/service/udmf/permission/uri_permission_manager.cpp b/datamgr_service/services/distributeddataservice/service/udmf/permission/uri_permission_manager.cpp index 1e7e1e90..a20b3e94 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/permission/uri_permission_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/permission/uri_permission_manager.cpp @@ -22,7 +22,7 @@ namespace OHOS { namespace UDMF { -constexpr const std::uint32_t GRANT_URI_PERMISSION_MAX_SIZE = 500; +constexpr const std::uint32_t GRANT_URI_PERMISSION_MAX_SIZE = 10000; UriPermissionManager &UriPermissionManager::GetInstance() { static UriPermissionManager instance; diff --git a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/data_handler.cpp b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/data_handler.cpp index d772d999..74c7d856 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/data_handler.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/data_handler.cpp @@ -35,7 +35,7 @@ Status DataHandler::MarshalToEntries(const UnifiedData &unifiedData, std::vector std::vector udKeyBytes = { unifiedKey.begin(), unifiedKey.end() }; Entry entry = { udKeyBytes, runtimeBytes }; entries.emplace_back(entry); - std::string propsKey = unifiedData.GetRuntime()->key.GetPropertyKey() + UD_KEY_PROPERTIES_SEPARATOR; + std::string propsKey = unifiedData.GetRuntime()->key.GetKeyCommonPrefix() + UD_KEY_PROPERTIES_SEPARATOR; std::vector propsBytes; auto propsTlv = TLVObject(propsBytes); if (!TLVUtil::Writing(*unifiedData.GetProperties(), propsTlv, TAG::TAG_PROPERTIES)) { @@ -86,7 +86,7 @@ Status DataHandler::UnmarshalEntryItem(UnifiedData &unifiedData, const std::vect continue; } auto isStartWithKey = keyStr.find(key) == 0; - std::string propsKey = UnifiedKey(key).GetPropertyKey() + UD_KEY_PROPERTIES_SEPARATOR; + std::string propsKey = UnifiedKey(key).GetKeyCommonPrefix() + UD_KEY_PROPERTIES_SEPARATOR; if (!isStartWithKey && (keyStr == propsKey)) { std::shared_ptr properties; if (!TLVUtil::ReadTlv(properties, data, TAG::TAG_PROPERTIES)) { diff --git a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.cpp b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.cpp index ab49f959..597cc9a7 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.cpp @@ -19,16 +19,21 @@ #include #include +#include "bundle_info.h" #include "dds_trace.h" #include "udmf_radar_reporter.h" #include "accesstoken_kit.h" +#include "checker/checker_manager.h" #include "device_manager_adapter.h" +#include "file_mount_manager.h" +#include "iservice_registry.h" #include "log_print.h" +#include "system_ability_definition.h" #include "udmf_radar_reporter.h" #include "udmf_utils.h" -#include "remote_file_share.h" #include "utils/crypto.h" #include "uri_permission_manager_client.h" +#include "ipc_skeleton.h" namespace OHOS { namespace UDMF { static constexpr int ID_LEN = 32; @@ -51,18 +56,24 @@ using namespace Security::AccessToken; using namespace OHOS::AppFileService::ModuleRemoteFileShare; using namespace RadarReporter; -int32_t PreProcessUtils::RuntimeDataImputation(UnifiedData &data, CustomOption &option) +int32_t PreProcessUtils::FillRuntimeInfo(UnifiedData &data, CustomOption &option) { auto it = UD_INTENTION_MAP.find(option.intention); if (it == UD_INTENTION_MAP.end()) { return E_ERROR; } std::string bundleName; - GetHapBundleNameByToken(option.tokenId, bundleName); + std::string specificBundleName; + if (!GetSpecificBundleNameByTokenId(option.tokenId, specificBundleName, bundleName)) { + ZLOGE("GetSpecificBundleNameByTokenId failed, tokenid:%{public}u", option.tokenId); + return E_ERROR; + } std::string intention = it->second; - UnifiedKey key(intention, bundleName, GenerateId()); + UnifiedKey key(intention, specificBundleName, GenerateId()); Privilege privilege; privilege.tokenId = option.tokenId; + std::string appId = DistributedData::CheckerManager::GetInstance().GetAppId( + { IPCSkeleton::GetCallingUid(), option.tokenId, bundleName }); Runtime runtime; runtime.key = key; runtime.privileges.emplace_back(privilege); @@ -72,7 +83,9 @@ int32_t PreProcessUtils::RuntimeDataImputation(UnifiedData &data, CustomOption & runtime.deviceId = GetLocalDeviceId(); runtime.recordTotalNum = static_cast(data.GetRecords().size()); runtime.tokenId = option.tokenId; - runtime.sdkVersion = data.GetSdkVersion(); + runtime.sdkVersion = GetSdkVersionByToken(option.tokenId); + runtime.visibility = option.visibility; + runtime.appId = appId; data.SetRuntime(runtime); return E_OK; } @@ -174,18 +187,6 @@ void PreProcessUtils::SetRemoteData(UnifiedData &data) }); } -bool PreProcessUtils::IsFileType(std::shared_ptr record) -{ - if (record == nullptr) { - return false; - } - if (!std::holds_alternative>(record->GetOriginValue())) { - return false; - } - auto obj = std::get>(record->GetOriginValue()); - return obj->value_.find(ORI_URI) != obj->value_.end(); -} - int32_t PreProcessUtils::SetRemoteUri(uint32_t tokenId, UnifiedData &data) { std::vector uris; @@ -232,9 +233,9 @@ int32_t PreProcessUtils::GetDfsUrisFromLocal(const std::vector &uri DdsTrace trace( std::string(TAG) + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), - BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::IDLE, BizState::DFX_BEGIN); + BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::IDLE); std::unordered_map dfsUris; - int ret = RemoteFileShare::GetDfsUrisFromLocal(uris, userId, dfsUris); + int32_t ret = Storage::DistributedFile::FileMountManager::GetDfsUrisDirFromLocal(uris, userId, dfsUris); if (ret != 0 || dfsUris.empty()) { RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::FAILED, E_FS_ERROR, BizState::DFX_END); @@ -266,7 +267,7 @@ int32_t PreProcessUtils::GetDfsUrisFromLocal(const std::vector &uri }); } RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), - BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::SUCCESS, BizState::DFX_END); + BizScene::SET_DATA, SetDataStage::GERERATE_DFS_URI, StageRes::SUCCESS); return E_OK; } @@ -317,18 +318,30 @@ void PreProcessUtils::ProcessFileType(std::vector { for (auto record : records) { if (record == nullptr) { + ZLOGW("Record is empty!"); continue; } - if (!PreProcessUtils::IsFileType(record)) { + auto entries = record->GetEntries(); + if (entries == nullptr) { + ZLOGW("GetEntries returns empty!"); continue; } - auto obj = std::get>(record->GetOriginValue()); + auto entry = entries->find(GENERAL_FILE_URI); + if (entry == entries->end()) { + continue; + } + auto value = entry->second; + if (!std::holds_alternative>(value)) { + continue; + } + auto obj = std::get>(value); if (obj == nullptr) { ZLOGE("ValueType is not Object, Not convert to remote uri!"); continue; } - if (!callback(obj)) { - continue; + std::string dataType; + if (obj->GetValue(UNIFORM_DATA_TYPE, dataType) && dataType == GENERAL_FILE_URI) { + callback(obj); } } } @@ -338,7 +351,7 @@ void PreProcessUtils::ProcessRecord(std::shared_ptr record, uint3 { record->ComputeUris([&uris, &isLocal, &tokenId] (UriInfo &uriInfo) { std::string newUriStr = ""; - if (isLocal) { + if (isLocal && uriInfo.authUri.empty()) { Uri tmpUri(uriInfo.oriUri); std::string path = tmpUri.GetPath(); std::string bundleName; @@ -354,7 +367,7 @@ void PreProcessUtils::ProcessRecord(std::shared_ptr record, uint3 } uriInfo.authUri = newUriStr; } else { - newUriStr = uriInfo.dfsUri; + newUriStr = isLocal ? uriInfo.authUri : uriInfo.dfsUri; } Uri uri(newUriStr); if (uri.GetAuthority().empty()) { @@ -425,7 +438,7 @@ bool PreProcessUtils::GetDetailsFromUData(const UnifiedData &data, UDDetails &de { auto records = data.GetRecords(); if (records.size() != TEMP_UDATA_RECORD_SIZE) { - ZLOGE("Records size error.size:%{public}zu", records.size()); + ZLOGI("Records size:%{public}zu", records.size()); return false; } if (records[0] == nullptr) { @@ -471,5 +484,80 @@ Status PreProcessUtils::GetSummaryFromDetails(const UDDetails &details, Summary } return E_OK; } + +std::string PreProcessUtils::GetSdkVersionByToken(uint32_t tokenId) +{ + if (Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId) != + Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) { + ZLOGE("Caller is not application, tokenid is %{public}u", tokenId); + return ""; + } + Security::AccessToken::HapTokenInfo hapTokenInfo; + auto ret = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, hapTokenInfo); + if (ret != 0) { + ZLOGE("GetHapTokenInfo fail, tokenid is %{public}u, ret is %{public}d.", tokenId, ret); + return ""; + } + return std::to_string(hapTokenInfo.apiVersion); +} + +bool PreProcessUtils::GetSpecificBundleNameByTokenId(uint32_t tokenId, std::string &specificBundleName, + std::string &bundleName) +{ + Security::AccessToken::HapTokenInfo hapInfo; + if (Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo) + == Security::AccessToken::AccessTokenKitRet::RET_SUCCESS) { + bundleName = hapInfo.bundleName; + return GetSpecificBundleName(hapInfo.bundleName, hapInfo.instIndex, specificBundleName); + } + if (UTILS::IsTokenNative()) { + ZLOGI("TypeATokenTypeEnum is TOKEN_NATIVE"); + std::string processName; + if (GetNativeProcessNameByToken(tokenId, processName)) { + bundleName = std::move(processName); + specificBundleName = bundleName; + return true; + } + } + ZLOGE("Get bundle name faild, tokenid:%{public}u", tokenId); + return false; +} + +sptr PreProcessUtils::GetBundleMgr() +{ + auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (samgrProxy == nullptr) { + ZLOGE("Failed to get system ability mgr."); + return nullptr; + } + auto bundleMgrProxy = samgrProxy->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (bundleMgrProxy == nullptr) { + ZLOGE("Failed to Get BMS SA."); + return nullptr; + } + auto bundleManager = iface_cast(bundleMgrProxy); + if (bundleManager == nullptr) { + ZLOGE("Failed to get bundle manager"); + return nullptr; + } + return bundleManager; +} + +bool PreProcessUtils::GetSpecificBundleName(const std::string &bundleName, int32_t appIndex, + std::string &specificBundleName) +{ + auto bundleManager = GetBundleMgr(); + if (bundleManager == nullptr) { + ZLOGE("Failed to get bundle manager, bundleName:%{public}s, appIndex:%{public}d", bundleName.c_str(), appIndex); + return false; + } + auto ret = bundleManager->GetDirByBundleNameAndAppIndex(bundleName, appIndex, specificBundleName); + if (ret != ERR_OK) { + ZLOGE("GetDirByBundleNameAndAppIndex failed, ret:%{public}d, bundleName:%{public}s, appIndex:%{public}d", + ret, bundleName.c_str(), appIndex); + return false; + } + return true; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.h b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.h index 6d613007..e378592c 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/preprocess_utils.h @@ -15,13 +15,14 @@ #ifndef UDMF_PREPROCESS_UTILS_H #define UDMF_PREPROCESS_UTILS_H +#include "bundlemgr/bundle_mgr_proxy.h" #include "unified_data.h" namespace OHOS { namespace UDMF { class PreProcessUtils { public: - static int32_t RuntimeDataImputation(UnifiedData &data, CustomOption &option); + static int32_t FillRuntimeInfo(UnifiedData &data, CustomOption &option); static std::string GenerateId(); static time_t GetTimestamp(); static int32_t GetHapUidByToken(uint32_t tokenId, int &userId); @@ -42,10 +43,14 @@ public: static void SetRecordUid(UnifiedData &data); static bool GetDetailsFromUData(const UnifiedData &data, UDDetails &details); static Status GetSummaryFromDetails(const UDDetails &details, Summary &summary); + static bool GetSpecificBundleNameByTokenId(uint32_t tokenId, std::string &specificBundleName, + std::string &bundleName); + static sptr GetBundleMgr(); private: static bool CheckUriAuthorization(const std::vector& uris, uint32_t tokenId); static int32_t GetDfsUrisFromLocal(const std::vector &uris, int32_t userId, UnifiedData &data); - static bool IsFileType(std::shared_ptr record); + static std::string GetSdkVersionByToken(uint32_t tokenId); + static bool GetSpecificBundleName(const std::string &bundleName, int32_t appIndex, std::string &specificBundleName); }; } // namespace UDMF } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/udmf_notifier_proxy.cpp b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/udmf_notifier_proxy.cpp new file mode 100644 index 00000000..6bd4b72f --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/udmf_notifier_proxy.cpp @@ -0,0 +1,85 @@ +/* + * 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. + */ + +#define LOG_TAG "UDMFNotifierProxy" +#include "udmf_notifier_proxy.h" + +#include "distributeddata_udmf_ipc_interface_code.h" +#include "log_print.h" +#include "message_parcel.h" +#include "message_option.h" +#include "udmf_types_util.h" +#include "utils/anonymous.h" + +namespace OHOS { +namespace UDMF { +#define IPC_SEND(code, reply, ...) \ + ({ \ + int32_t ipcStatus = E_OK; \ + do { \ + MessageParcel request; \ + if (!request.WriteInterfaceToken(GetDescriptor())) { \ + ipcStatus = E_WRITE_PARCEL_ERROR; \ + break; \ + } \ + if (!ITypesUtil::Marshal(request, ##__VA_ARGS__)) { \ + ipcStatus = E_WRITE_PARCEL_ERROR; \ + break; \ + } \ + MessageOption option; \ + auto result = remote_->SendRequest((code), request, reply, option); \ + if (result != 0) { \ + ZLOGE("SendRequest failed, result = %{public}d!", result); \ + ipcStatus = E_IPC; \ + break; \ + } \ + ITypesUtil::Unmarshal(reply, ipcStatus); \ + } while (0); \ + ipcStatus; \ + }) + +UdmfNotifierProxy::UdmfNotifierProxy(const sptr &impl) + : IRemoteProxy(impl) +{ + remote_ = Remote(); +} + +void UdmfNotifierProxy::HandleDelayObserver(const std::string &key, const DataLoadInfo &dataLoadInfo) +{ + MessageParcel reply; + int32_t status = + IPC_SEND(static_cast(UdmfNotifierInterfaceCode::HANDLE_DELAY_OBSERVER), reply, key, dataLoadInfo); + if (status != E_OK) { + ZLOGE("status:%{public}d", status); + } +} + +DelayDataCallbackProxy::DelayDataCallbackProxy(const sptr &impl) + : IRemoteProxy(impl) +{ + remote_ = Remote(); +} + +void DelayDataCallbackProxy::DelayDataCallback(const std::string &key, const UnifiedData &data) +{ + MessageParcel reply; + int32_t status = + IPC_SEND(static_cast(UdmfNotifierInterfaceCode::HANDLE_DELAY_DATA), reply, key, data); + if (status != E_OK) { + ZLOGE("status:%{public}d", status); + } +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/preprocess/udmf_notifier_proxy.h b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/udmf_notifier_proxy.h new file mode 100644 index 00000000..782ed38c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/udmf/preprocess/udmf_notifier_proxy.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 UDMF_NOTIFIER_PROXY_H +#define UDMF_NOTIFIER_PROXY_H + +#include "iremote_broker.h" +#include "iremote_proxy.h" +#include "iudmf_notifier.h" + +namespace OHOS { +namespace UDMF { +class UdmfNotifierProxy : public IRemoteProxy { +public: + explicit UdmfNotifierProxy(const sptr &impl); + ~UdmfNotifierProxy() = default; + void HandleDelayObserver(const std::string &key, const DataLoadInfo &dataLoadInfo) override; + +private: + static inline BrokerDelegator delegator_; + sptr remote_; +}; + +class DelayDataCallbackProxy : public IRemoteProxy { +public: + explicit DelayDataCallbackProxy(const sptr &impl); + ~DelayDataCallbackProxy() = default; + void DelayDataCallback(const std::string &key, const UnifiedData &data) override; + +private: + static inline BrokerDelegator delegator_; + sptr remote_; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_NOTIFIER_PROXY_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp b/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp index d8742dc7..f55d72d7 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp @@ -16,8 +16,6 @@ #include "runtime_store.h" -#include -#include #include "data_handler.h" #include "log_print.h" #include "ipc_skeleton.h" @@ -26,6 +24,7 @@ #include "account/account_delegate.h" #include "metadata/meta_data_manager.h" #include "metadata/appid_meta_data.h" +#include "metadata/store_meta_data.h" #include "device_manager_adapter.h" #include "bootstrap.h" #include "directory/directory_manager.h" @@ -36,6 +35,7 @@ namespace OHOS { namespace UDMF { using namespace RadarReporter; using namespace DistributedDB; +using namespace OHOS::DistributedData; using Anonymous = OHOS::DistributedData::Anonymous; using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; constexpr const char *SUMMARY_SUFIX = "#summary"; @@ -60,7 +60,7 @@ Status RuntimeStore::PutLocal(const std::string &key, const std::string &value) auto status = kvStore_->PutLocal(keyBytes, valueBytes); if (status != DBStatus::OK) { ZLOGE("KvStore PutLocal failed, status: %{public}d.", status); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } return E_OK; } @@ -73,7 +73,7 @@ Status RuntimeStore::GetLocal(const std::string &key, std::string &value) DBStatus status = kvStore_->GetLocal(keyBytes, valueBytes); if (status != DBStatus::OK && status != DBStatus::NOT_FOUND) { ZLOGE("GetLocal entry failed, key: %{public}s.", key.c_str()); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } if (valueBytes.empty()) { ZLOGW("GetLocal entry is empty, key: %{public}s", key.c_str()); @@ -91,7 +91,7 @@ Status RuntimeStore::DeleteLocal(const std::string &key) DBStatus status = kvStore_->DeleteLocal(keyBytes); if (status != DBStatus::OK && status != DBStatus::NOT_FOUND) { ZLOGE("DeleteLocal failed, key: %{public}s.", key.c_str()); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } return E_OK; } @@ -115,9 +115,10 @@ Status RuntimeStore::Get(const std::string &key, UnifiedData &unifiedData) { UpdateTime(); std::vector entries; - if (GetEntries(UnifiedKey(key).GetPropertyKey(), entries) != E_OK) { + auto status = GetEntries(UnifiedKey(key).GetKeyCommonPrefix(), entries); + if (status != E_OK) { ZLOGE("GetEntries failed, dataPrefix: %{public}s.", key.c_str()); - return E_DB_ERROR; + return status; } if (entries.empty()) { ZLOGW("entries is empty, dataPrefix: %{public}s", key.c_str()); @@ -137,7 +138,7 @@ Status RuntimeStore::PutSummary(const UnifiedData &data, std::vector &ent UnifiedDataHelper::GetSummary(data, summary); } - auto propertyKey = data.GetRuntime()->key.GetPropertyKey(); + auto propertyKey = data.GetRuntime()->key.GetKeyCommonPrefix(); Value value; auto status = DataHandler::MarshalToEntries(summary, value, TAG::TAG_SUMMARY); if (status != E_OK) { @@ -149,19 +150,34 @@ Status RuntimeStore::PutSummary(const UnifiedData &data, std::vector &ent return E_OK; } +Status RuntimeStore::PutSummary(UnifiedKey &key, const Summary &summary) +{ + auto propertyKey = key.GetKeyCommonPrefix(); + Value value; + auto status = DataHandler::MarshalToEntries(summary, value, TAG::TAG_SUMMARY); + if (status != E_OK) { + ZLOGE("Marshal summary failed, key: %{public}s, status:%{public}d", propertyKey.c_str(), status); + return status; + } + auto summaryKey = propertyKey + SUMMARY_SUFIX; + std::vector entries{{{summaryKey.begin(), summaryKey.end()}, value}}; + return PutEntries(std::move(entries)); +} + Status RuntimeStore::GetSummary(UnifiedKey &key, Summary &summary) { UpdateTime(); Value value; - auto summaryKey = key.GetPropertyKey() + SUMMARY_SUFIX; + auto summaryKey = key.GetKeyCommonPrefix() + SUMMARY_SUFIX; auto res = kvStore_->Get({summaryKey.begin(), summaryKey.end()}, value); if (res != OK || value.empty()) { ZLOGW("Get stored summary failed, key: %{public}s, status:%{public}d", summaryKey.c_str(), res); UnifiedData unifiedData; auto udKey = key.GetUnifiedKey(); - if (Get(udKey, unifiedData) != E_OK) { + auto status = Get(udKey, unifiedData); + if (status != E_OK) { ZLOGE("Get unified data failed, key: %{public}s", udKey.c_str()); - return E_DB_ERROR; + return status; } UDDetails details {}; if (PreProcessUtils::GetDetailsFromUData(unifiedData, details)) { @@ -190,7 +206,7 @@ Status RuntimeStore::PutRuntime(const std::string &key, const Runtime &runtime) auto res = kvStore_->Put({key.begin(), key.end()}, value); if (res != OK) { ZLOGE("Put failed, key:%{public}s, status:%{public}d", key.c_str(), res); - return E_DB_ERROR; + return MarkWhenCorrupted(res); } return E_OK; } @@ -200,9 +216,13 @@ Status RuntimeStore::GetRuntime(const std::string &key, Runtime &runtime) UpdateTime(); Value value; auto res = kvStore_->Get({key.begin(), key.end()}, value); + if (res == NOT_FOUND) { + ZLOGW("Runtime not found, key: %{public}s", key.c_str()); + return E_NOT_FOUND; + } if (res != OK || value.empty()) { ZLOGE("Get failed, key: %{public}s, status:%{public}d", key.c_str(), res); - return E_DB_ERROR; + return MarkWhenCorrupted(res); } auto status = DataHandler::UnmarshalEntries(value, runtime, TAG::TAG_RUNTIME); if (status != E_OK) { @@ -215,14 +235,16 @@ Status RuntimeStore::GetRuntime(const std::string &key, Runtime &runtime) Status RuntimeStore::Update(const UnifiedData &unifiedData) { std::string key = unifiedData.GetRuntime()->key.key; - if (Delete(key) != E_OK) { + auto status = Delete(UnifiedKey(key).GetKeyCommonPrefix()); + if (status != E_OK) { UpdateTime(); ZLOGE("Delete unified data failed, dataPrefix: %{public}s.", key.c_str()); - return E_DB_ERROR; + return status; } - if (Put(unifiedData) != E_OK) { + status = Put(unifiedData); + if (status != E_OK) { ZLOGE("Update unified data failed, dataPrefix: %{public}s.", key.c_str()); - return E_DB_ERROR; + return status; } return E_OK; } @@ -230,9 +252,10 @@ Status RuntimeStore::Update(const UnifiedData &unifiedData) Status RuntimeStore::Delete(const std::string &key) { std::vector entries; - if (GetEntries(key, entries) != E_OK) { + auto status = GetEntries(key, entries); + if (status != E_OK) { ZLOGE("GetEntries failed, dataPrefix: %{public}s.", key.c_str()); - return E_DB_ERROR; + return status; } if (entries.empty()) { ZLOGD("entries is empty."); @@ -364,7 +387,7 @@ Status RuntimeStore::GetBatchData(const std::string &dataPrefix, std::vectorCloseKvStore(kvStore_.get()); -} - bool RuntimeStore::Init() { if (!SaveMetaData()) { // get keyinfo about create db fail. @@ -417,18 +435,17 @@ bool RuntimeStore::Init() }); if (status != DBStatus::OK) { ZLOGE("GetKvStore fail, status: %{public}d.", static_cast(status)); + if (status == INVALID_PASSWD_OR_CORRUPTED_DB) { + status = delegateManager_->DeleteKvStore(storeId_); + if (status != DBStatus::OK) { + ZLOGE("DeleteKvStore fail, status: %{public}d.", static_cast(status)); + } + } return false; } - auto release = [this](KvStoreNbDelegate *delegate) { - ZLOGI("Release runtime kvStore."); - if (delegate == nullptr) { - return; - } - auto retStatus = delegateManager_->CloseKvStore(delegate); - if (retStatus != DBStatus::OK) { - ZLOGE("CloseKvStore fail, status: %{public}d.", static_cast(retStatus)); - } + ZLOGI("Release runtime kvStore, db is corrupted: %{public}d.", isCorrupted_); + ReleaseStore(delegate); }; kvStore_ = std::shared_ptr(delegate, release); uint32_t pragmData = 16 * 1024 * 1024; @@ -459,11 +476,11 @@ bool RuntimeStore::BuildMetaDataParam(DistributedData::StoreMetaData &metaData) metaData.account = DistributedData::AccountDelegate::GetInstance()->GetCurrentAccountId(); metaData.tokenId = token; metaData.securityLevel = DistributedKv::SecurityLevel::S1; - metaData.area = DistributedKv::Area::EL1; - metaData.uid = static_cast(getuid()); + metaData.area = DistributedKv::Area::EL2; + metaData.uid = static_cast(IPCSkeleton::GetCallingUid()); metaData.storeType = DistributedKv::KvStoreType::SINGLE_VERSION; metaData.dataType = DistributedKv::DataType::TYPE_DYNAMICAL; - metaData.dataDir = DistributedData::DirectoryManager::GetInstance().GetStorePath(metaData); + metaData.authType = DistributedKv::AuthType::IDENTICAL_ACCOUNT; return true; } @@ -481,24 +498,26 @@ bool RuntimeStore::SaveMetaData() ZLOGE("QueryForegroundUserId failed."); return false; } - - saveMeta.dataDir.append("/").append(std::to_string(foregroundUserId)); + saveMeta.user = std::to_string(foregroundUserId); + saveMeta.dataDir = DistributedData::DirectoryManager::GetInstance().GetStorePath(saveMeta); if (!DistributedData::DirectoryManager::GetInstance().CreateDirectory(saveMeta.dataDir)) { - ZLOGE("Create directory error"); + ZLOGE("Create directory error, dataDir: %{public}s.", Anonymous::Change(saveMeta.dataDir).c_str()); return false; } - SetDelegateManager(saveMeta.dataDir, saveMeta.appId, saveMeta.user, std::to_string(foregroundUserId)); + SetDelegateManager(saveMeta.dataDir, saveMeta.appId, saveMeta.user); DistributedData::StoreMetaData loadLocal; DistributedData::StoreMetaData syncMeta; if (DistributedData::MetaDataManager::GetInstance().LoadMeta(saveMeta.GetKey(), loadLocal, true) && - DistributedData::MetaDataManager::GetInstance().LoadMeta(saveMeta.GetKey(), syncMeta, false)) { - ZLOGD("Meta data is already saved."); - return true; + DistributedData::MetaDataManager::GetInstance().LoadMeta(saveMeta.GetKeyLocalWithoutPath(), syncMeta, false)) { + if (loadLocal == saveMeta && syncMeta == saveMeta) { + ZLOGD("Meta data is already saved."); + return true; + } } - auto saved = DistributedData::MetaDataManager::GetInstance().SaveMeta(saveMeta.GetKey(), saveMeta) && + auto saved = DistributedData::MetaDataManager::GetInstance().SaveMeta(saveMeta.GetKeyWithoutPath(), saveMeta) && DistributedData::MetaDataManager::GetInstance().SaveMeta(saveMeta.GetKey(), saveMeta, true); if (!saved) { ZLOGE("SaveMeta failed, saveMeta.key:%{public}s", saveMeta.GetKey().c_str()); @@ -515,12 +534,32 @@ bool RuntimeStore::SaveMetaData() return true; } -void RuntimeStore::SetDelegateManager(const std::string &dataDir, const std::string &appId, const std::string &userId, - const std::string &subUser) +void RuntimeStore::ReleaseStore(DistributedDB::KvStoreNbDelegate *delegate) +{ + if (delegate == nullptr) { + return; + } + auto retStatus = delegateManager_->CloseKvStore(delegate); + if (retStatus != DBStatus::OK) { + ZLOGE("CloseKvStore fail, status: %{public}d.", static_cast(retStatus)); + return; + } + if (isCorrupted_) { + retStatus = delegateManager_->DeleteKvStore(storeId_); + if (retStatus != DBStatus::OK) { + ZLOGE("DeleteKvStore fail, status: %{public}d.", static_cast(retStatus)); + } + } +} + +void RuntimeStore::SetDelegateManager(const std::string &dataDir, const std::string &appId, const std::string &userId) { - delegateManager_ = std::make_shared(appId, userId, subUser); + delegateManager_ = std::make_shared(appId, userId); DistributedDB::KvStoreConfig kvStoreConfig { dataDir }; - delegateManager_->SetKvStoreConfig(kvStoreConfig); + auto status = delegateManager_->SetKvStoreConfig(kvStoreConfig); + if (status != DBStatus::OK) { + ZLOGE("SetKvStoreConfig failed, status: %{public}d.", status); + } } Status RuntimeStore::GetEntries(const std::string &dataPrefix, std::vector &entries) @@ -532,7 +571,7 @@ Status RuntimeStore::GetEntries(const std::string &dataPrefix, std::vectorGetEntries(dbQuery, entries); if (status != DBStatus::OK && status != DBStatus::NOT_FOUND) { ZLOGE("KvStore getEntries failed, status: %{public}d.", static_cast(status)); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } return E_OK; } @@ -542,7 +581,7 @@ Status RuntimeStore::PutEntries(const std::vector &entries) DBStatus status = kvStore_->PutBatch(entries); if (status != DBStatus::OK) { ZLOGE("putBatch failed, status: %{public}d.", status); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } return E_OK; } @@ -552,10 +591,19 @@ Status RuntimeStore::DeleteEntries(const std::vector &keys) DBStatus status = kvStore_->DeleteBatch(keys); if (status != DBStatus::OK) { ZLOGE("deleteBatch failed, status: %{public}d.", status); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } return E_OK; } +Status RuntimeStore::MarkWhenCorrupted(DistributedDB::DBStatus status) +{ + if (status == INVALID_PASSWD_OR_CORRUPTED_DB) { + ZLOGE("Kv database corrupted"); + isCorrupted_ = true; + return E_DB_CORRUPTED; + } + return E_DB_ERROR; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.h b/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.h index f195eba3..75a8a89b 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.h @@ -43,7 +43,7 @@ public: Status DeleteLocal(const std::string &key) override; Status PutRuntime(const std::string &key, const Runtime &runtime) override; Status GetRuntime(const std::string &key, Runtime &runtime) override; - void Close() override; + Status PutSummary(UnifiedKey &key, const Summary &summary) override; bool Init() override; private: @@ -53,8 +53,7 @@ private: std::shared_ptr delegateManager_ = nullptr; std::shared_ptr kvStore_; std::string storeId_; - void SetDelegateManager(const std::string &dataDir, const std::string &appId, const std::string &userId, - const std::string &subUser); + void SetDelegateManager(const std::string &dataDir, const std::string &appId, const std::string &userId); bool SaveMetaData(); Status GetEntries(const std::string &dataPrefix, std::vector &entries); Status PutEntries(const std::vector &entries); @@ -65,6 +64,10 @@ private: void NotifySyncProcss(const DevSyncProcessMap &processMap, ProcessCallback callback, const DevNameMap &deviceNameMap); Status PutSummary(const UnifiedData &data, std::vector &entries); + Status MarkWhenCorrupted(DistributedDB::DBStatus status); + void ReleaseStore(DistributedDB::KvStoreNbDelegate *delegate); + + bool isCorrupted_ = false; }; } // namespace UDMF } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/store.h b/datamgr_service/services/distributeddataservice/service/udmf/store/store.h index 1c54e65d..2124e08a 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/store.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/store.h @@ -43,8 +43,8 @@ public: virtual Status DeleteLocal(const std::string &key) = 0; virtual Status PutRuntime(const std::string &key, const Runtime &runtime) = 0; virtual Status GetRuntime(const std::string &key, Runtime &runtime) = 0; + virtual Status PutSummary(UnifiedKey &key, const Summary &summary) = 0; virtual bool Init() = 0; - virtual void Close() = 0; bool operator<(const Time &time) const { diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.cpp b/datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.cpp deleted file mode 100644 index 9085a9b5..00000000 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "RuntimeStoreAccountObserver" - -#include "store_account_observer.h" -#include "log_print.h" -#include "directory/directory_manager.h" -#include "bootstrap.h" -#include "ipc_skeleton.h" - -namespace OHOS { -namespace UDMF { -using namespace DistributedKv; -using namespace DistributedData; -void RuntimeStoreAccountObserver::OnAccountChanged(const AccountEventInfo &eventInfo, int32_t timeout) -{ - ZLOGI("account event begin. status is %{public}d.", eventInfo.status); - if (eventInfo.status == AccountStatus::DEVICE_ACCOUNT_DELETE) { - DistributedData::StoreMetaData metaData; - uint32_t token = IPCSkeleton::GetSelfTokenID(); - metaData.bundleName = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); - metaData.appId = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); - metaData.user = eventInfo.userId; - metaData.tokenId = token; - metaData.securityLevel = DistributedKv::SecurityLevel::S1; - metaData.area = DistributedKv::Area::EL1; - metaData.storeType = DistributedKv::KvStoreType::SINGLE_VERSION; - metaData.dataDir = DistributedData::DirectoryManager::GetInstance().GetStorePath(metaData); - std::string userPath = metaData.dataDir.append("/").append(eventInfo.userId); - DistributedData::DirectoryManager::GetInstance().DeleteDirectory(userPath.c_str()); - } -} - -} // namespace UDMF -} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp b/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp index f5395918..00fb5c08 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp @@ -38,15 +38,13 @@ std::shared_ptr StoreCache::GetStore(std::string intention) } std::string key = intention; key.append(std::to_string(foregroundUserId)); - stores_.Compute(key, [&store, intention](const auto &key, std::shared_ptr &storePtr) -> bool { if (storePtr != nullptr) { store = storePtr; return true; } - if (intention == UD_INTENTION_MAP.at(UD_INTENTION_DRAG) - || intention == UD_INTENTION_MAP.at(UD_INTENTION_DATA_HUB)) { + if (IsValidIntention(intention)) { storePtr = std::make_shared(intention); if (!storePtr->Init()) { ZLOGE("Init runtime store failed."); @@ -57,10 +55,9 @@ std::shared_ptr StoreCache::GetStore(std::string intention) } return false; }); - std::unique_lock lock(taskMutex_); if (taskId_ == ExecutorPool::INVALID_TASK_ID && executorPool_ != nullptr) { - taskId_ = executorPool_->Schedule(std::chrono::minutes(INTERVAL), std::bind(&StoreCache::GarbageCollect, this)); + taskId_ = executorPool_->Schedule(std::chrono::minutes(INTERVAL), [this]() { this->GarbageCollect(); }); } return store; } @@ -78,7 +75,7 @@ void StoreCache::GarbageCollect() std::unique_lock lock(taskMutex_); if (!stores_.Empty() && executorPool_ != nullptr) { ZLOGD("GarbageCollect, stores size:%{public}zu", stores_.Size()); - taskId_ = executorPool_->Schedule(std::chrono::minutes(INTERVAL), std::bind(&StoreCache::GarbageCollect, this)); + taskId_ = executorPool_->Schedule(std::chrono::minutes(INTERVAL), [this]() { this->GarbageCollect(); }); } else { taskId_ = ExecutorPool::INVALID_TASK_ID; } @@ -94,5 +91,23 @@ void StoreCache::CloseStores() ZLOGI("CloseStores, stores size:%{public}zu", stores_.Size()); stores_.Clear(); } + +void StoreCache::RemoveStore(const std::string &intention) +{ + ZLOGI("RemoveStore, intention:%{public}s", intention.c_str()); + int foregroundUserId = 0; + if (!DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId)) { + ZLOGE("QueryForegroundUserId failed."); + return; + } + std::string key = intention; + key.append(std::to_string(foregroundUserId)); + stores_.Erase(key); +} + +bool StoreCache::IsValidIntention(const std::string &intention) +{ + return UnifiedDataUtils::GetIntentionByString(intention) != UD_INTENTION_BUTT; +} } // namespace UDMF } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.h b/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.h index fd052949..10ec3e35 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.h @@ -28,6 +28,7 @@ public: static StoreCache &GetInstance(); void SetThreadPool(std::shared_ptr executors); void CloseStores(); + void RemoveStore(const std::string &intention); private: StoreCache() {} @@ -38,6 +39,7 @@ private: StoreCache &operator=(const StoreCache &obj) = delete; void GarbageCollect(); + static bool IsValidIntention(const std::string &intention); ConcurrentMap> stores_; std::mutex taskMutex_; diff --git a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp index acd9857b..36e4deba 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp @@ -21,28 +21,35 @@ #include "tokenid_kit.h" #include "accesstoken_kit.h" +#include "account/account_delegate.h" #include "bootstrap.h" #include "bundle_info.h" #include "bundlemgr/bundle_mgr_proxy.h" +#include "checker/checker_manager.h" #include "checker_manager.h" #include "device_manager_adapter.h" +#include "device_matrix.h" #include "iservice_registry.h" #include "lifecycle/lifecycle_manager.h" #include "log_print.h" +#include "metadata/capability_meta_data.h" #include "metadata/store_meta_data.h" #include "metadata/meta_data_manager.h" #include "preprocess_utils.h" #include "dfx/reporter.h" -#include "store_account_observer.h" #include "system_ability_definition.h" #include "uri_permission_manager.h" #include "udmf_radar_reporter.h" +#include "udmf_utils.h" #include "unified_data_helper.h" #include "utils/anonymous.h" +#include "permission_validator.h" namespace OHOS { namespace UDMF { using namespace Security::AccessToken; +using namespace OHOS::DistributedHardware; +using namespace OHOS::DistributedData; using FeatureSystem = DistributedData::FeatureSystem; using UdmfBehaviourMsg = OHOS::DistributedDataDfx::UdmfBehaviourMsg; using Reporter = OHOS::DistributedDataDfx::Reporter; @@ -59,6 +66,7 @@ constexpr const char *DEVICE_2IN1_TAG = "2in1"; constexpr const char *DEVICE_PHONE_TAG = "phone"; constexpr const char *DEVICE_DEFAULT_TAG = "default"; constexpr const char *HAP_LIST[] = {"com.ohos.pasteboarddialog"}; +constexpr uint32_t FOUNDATION_UID = 5523; __attribute__((used)) UdmfServiceImpl::Factory UdmfServiceImpl::factory_; UdmfServiceImpl::Factory::Factory() { @@ -69,8 +77,6 @@ UdmfServiceImpl::Factory::Factory() } return product_; }, FeatureSystem::BIND_NOW); - auto observer = std::make_shared(); - DistributedData::AccountDelegate::GetInstance()->Subscribe(observer); } UdmfServiceImpl::Factory::~Factory() @@ -97,6 +103,8 @@ int32_t UdmfServiceImpl::SetData(CustomOption &option, UnifiedData &unifiedData, msg.appId = "unknown"; res = E_ERROR; } else { + RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), + BizScene::SET_DATA, SetDataStage::SET_DATA_SERVICE_BEGIN, StageRes::IDLE, bundleName); msg.appId = bundleName; res = SaveData(option, unifiedData, key); } @@ -120,37 +128,33 @@ int32_t UdmfServiceImpl::SaveData(CustomOption &option, UnifiedData &unifiedData ZLOGE("UnifiedData is invalid."); return E_INVALID_PARAMETERS; } - if (!UnifiedDataUtils::IsValidIntention(option.intention)) { ZLOGE("Invalid parameters intention: %{public}d.", option.intention); return E_INVALID_PARAMETERS; } - // imput runtime info before put it into store and save one privilege - if (PreProcessUtils::RuntimeDataImputation(unifiedData, option) != E_OK) { + if (PreProcessUtils::FillRuntimeInfo(unifiedData, option) != E_OK) { ZLOGE("Imputation failed"); return E_ERROR; } - std::string intention = unifiedData.GetRuntime()->key.intention; if (intention == UD_INTENTION_MAP.at(UD_INTENTION_DRAG)) { int32_t ret = PreProcessUtils::SetRemoteUri(option.tokenId, unifiedData); if (ret != E_OK) { - ZLOGE("SetRemoteUri failed, ret: %{public}d, bundleName:%{public}s.", ret, + ZLOGW("SetRemoteUri failed, ret: %{public}d, bundleName:%{public}s.", ret, unifiedData.GetRuntime()->createPackage.c_str()); - return ret; } } PreProcessUtils::SetRecordUid(unifiedData); - auto store = StoreCache::GetInstance().GetStore(intention); if (store == nullptr) { ZLOGE("Get store failed:%{public}s", intention.c_str()); return E_DB_ERROR; } - - if (store->Put(unifiedData) != E_OK) { - ZLOGE("Put unified data failed:%{public}s", intention.c_str()); + int32_t status = store->Put(unifiedData); + if (status != E_OK) { + ZLOGE("Put unified data failed:%{public}s, status:%{public}d", intention.c_str(), status); + HandleDbError(intention, status); return E_DB_ERROR; } key = unifiedData.GetRuntime()->key.GetUnifiedKey(); @@ -189,11 +193,23 @@ int32_t UdmfServiceImpl::GetData(const QueryOption &query, UnifiedData &unifiedD return res; } -int32_t UdmfServiceImpl::RetrieveData(const QueryOption &query, UnifiedData &unifiedData) +bool UdmfServiceImpl::CheckDragParams(UnifiedKey &key, const QueryOption &query) { - UnifiedKey key(query.key); if (!key.IsValid()) { ZLOGE("Unified key: %{public}s is invalid.", query.key.c_str()); + return false; + } + if (key.intention != UD_INTENTION_MAP.at(UD_INTENTION_DRAG)) { + ZLOGE("Invalid intention:%{public}s", key.intention.c_str()); + return false; + } + return true; +} + +int32_t UdmfServiceImpl::RetrieveData(const QueryOption &query, UnifiedData &unifiedData) +{ + UnifiedKey key(query.key); + if (!CheckDragParams(key, query)) { return E_INVALID_PARAMETERS; } auto store = StoreCache::GetInstance().GetStore(key.intention); @@ -204,6 +220,7 @@ int32_t UdmfServiceImpl::RetrieveData(const QueryOption &query, UnifiedData &uni int32_t res = store->Get(query.key, unifiedData); if (res != E_OK) { ZLOGE("Get data failed,res:%{public}d,key:%{public}s", res, query.key.c_str()); + HandleDbError(key.intention, res); return res; } @@ -211,17 +228,14 @@ int32_t UdmfServiceImpl::RetrieveData(const QueryOption &query, UnifiedData &uni ZLOGE("Get data incomplete,key:%{public}s", query.key.c_str()); return E_NOT_FOUND; } - - CheckerManager::CheckInfo info; - info.tokenId = query.tokenId; std::shared_ptr runtime = unifiedData.GetRuntime(); if (runtime == nullptr) { return E_DB_ERROR; } - if (!CheckerManager::GetInstance().IsValid(runtime->privileges, info) && !IsPermissionInCache(query)) { - RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), - BizScene::GET_DATA, GetDataStage::VERIFY_PRIVILEGE, StageRes::FAILED, E_NO_PERMISSION); - return E_NO_PERMISSION; + + res = VerifyDataAccessPermission(runtime, query, unifiedData); + if (res != E_OK) { + return res; } if (key.intention == UD_INTENTION_MAP.at(UD_INTENTION_DRAG)) { @@ -240,14 +254,33 @@ int32_t UdmfServiceImpl::RetrieveData(const QueryOption &query, UnifiedData &uni } } - privilegeCache_.erase(query.key); - + { + std::lock_guard lock(cacheMutex_); + privilegeCache_.erase(query.key); + } PreProcessUtils::SetRemoteData(unifiedData); return E_OK; } +int32_t UdmfServiceImpl::VerifyDataAccessPermission(std::shared_ptr runtime, const QueryOption &query, + const UnifiedData &unifiedData) +{ + CheckerManager::CheckInfo info; + info.tokenId = query.tokenId; + + if (!CheckerManager::GetInstance().IsValid(runtime->privileges, info) && !IsPermissionInCache(query)) { + RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), + BizScene::GET_DATA, GetDataStage::VERIFY_PRIVILEGE, StageRes::FAILED, E_NO_PERMISSION); + ZLOGE("Get data failed,key:%{public}s", query.key.c_str()); + return E_NO_PERMISSION; + } + + return E_OK; +} + bool UdmfServiceImpl::IsPermissionInCache(const QueryOption &query) { + std::lock_guard lock(cacheMutex_); auto iter = privilegeCache_.find(query.key); if (iter != privilegeCache_.end() && iter->second.tokenId == query.tokenId) { return true; @@ -263,6 +296,7 @@ bool UdmfServiceImpl::IsReadAndKeep(const std::vector &privileges, co } } + std::lock_guard lock(cacheMutex_); auto iter = privilegeCache_.find(query.key); if (iter != privilegeCache_.end() && iter->second.tokenId == query.tokenId && iter->second.readPermission == PRIVILEGE_READ_AND_KEEP) { @@ -361,8 +395,17 @@ int32_t UdmfServiceImpl::GetBatchData(const QueryOption &query, std::vectorvisibility == VISIBILITY_OWN_PROCESS && + query.tokenId != data.GetRuntime()->tokenId) { + continue; + } else { + unifiedDataSet.push_back(std::move(data)); + } + } + if (!IsFileMangerSa() && ProcessData(query, unifiedDataSet) != E_OK) { + ZLOGE("Query no permission."); + return E_NO_PERMISSION; } return E_OK; } @@ -370,13 +413,16 @@ int32_t UdmfServiceImpl::GetBatchData(const QueryOption &query, std::vectorGet(query.key, data); if (res != E_OK) { ZLOGE("Get data failed:%{public}s", key.intention.c_str()); + HandleDbError(key.intention, res); return res; } + auto verifyRes = VerifyUpdatePermission(query, data, bundleName); + if (verifyRes != E_OK) { + ZLOGE("VerifyUpdatePermission failed:%{public}d, key: %{public}s.", verifyRes, query.key.c_str()); + return verifyRes; + } + std::shared_ptr runtime = data.GetRuntime(); + runtime->lastModifiedTime = PreProcessUtils::GetTimestamp(); + unifiedData.SetRuntime(*runtime); + PreProcessUtils::SetRecordUid(unifiedData); + if ((res = store->Update(unifiedData)) != E_OK) { + ZLOGE("Unified data update failed:%{public}s", key.intention.c_str()); + HandleDbError(key.intention, res); + return E_DB_ERROR; + } + return E_OK; +} + +int32_t UdmfServiceImpl::VerifyUpdatePermission(const QueryOption &query, UnifiedData &data, std::string &bundleName) +{ if (data.IsEmpty()) { - ZLOGE("Invalid parameter, unified data has no record; intention: %{public}s.", key.intention.c_str()); + ZLOGE("Invalid parameter, unified data has no record"); return E_INVALID_PARAMETERS; } std::shared_ptr runtime = data.GetRuntime(); if (runtime == nullptr) { + ZLOGE("Invalid parameter, runtime is nullptr."); return E_DB_ERROR; } - if (runtime->tokenId != query.tokenId && !HasDatahubPriviledge(bundleName)) { - ZLOGE("Update failed: tokenId mismatch"); + if (runtime->tokenId != query.tokenId && !HasDatahubPriviledge(bundleName) && + CheckAppId(runtime, bundleName) != E_OK) { + ZLOGE("Update failed: tokenId or appId mismatch, bundleName: %{public}s", bundleName.c_str()); return E_INVALID_PARAMETERS; } - runtime->lastModifiedTime = PreProcessUtils::GetTimestamp(); - unifiedData.SetRuntime(*runtime); - PreProcessUtils::SetRecordUid(unifiedData); - if (store->Update(unifiedData) != E_OK) { - ZLOGE("Unified data update failed:%{public}s", key.intention.c_str()); - return E_DB_ERROR; + return E_OK; +} + +int32_t UdmfServiceImpl::CheckAppId(std::shared_ptr runtime, const std::string &bundleName) +{ + if (runtime->appId.empty()) { + ZLOGE("Update failed: Invalid parameter, runtime->appId is empty"); + return E_INVALID_PARAMETERS; + } + std::string appId = DistributedData::CheckerManager::GetInstance().GetAppId( + { IPCSkeleton::GetCallingUid(), runtime->tokenId, bundleName }); + if (appId.empty() || appId != runtime->appId) { + ZLOGE("Update failed: runtime->appId %{public}s and bundleName appId %{public}s mismatch", + runtime->appId.c_str(), appId.c_str()); + return E_INVALID_PARAMETERS; } return E_OK; } @@ -416,9 +493,19 @@ int32_t UdmfServiceImpl::UpdateData(const QueryOption &query, UnifiedData &unifi int32_t UdmfServiceImpl::DeleteData(const QueryOption &query, std::vector &unifiedDataSet) { ZLOGD("start"); + UnifiedKey key(query.key); + if (!key.IsValid() && !key.key.empty()) { + ZLOGE("invalid key, query.key: %{public}s", query.key.c_str()); + return E_INVALID_PARAMETERS; + } + std::string intention = FindIntentionMap(query.intention); + if (!IsValidOptionsNonDrag(key, intention)) { + ZLOGE("invalid option, query.key: %{public}s, intention: %{public}d", query.key.c_str(), query.intention); + return E_INVALID_PARAMETERS; + } std::vector dataSet; std::shared_ptr store; - auto status = QueryDataCommon(query, dataSet, store); + int32_t status = QueryDataCommon(query, dataSet, store); if (status != E_OK) { ZLOGE("QueryDataCommon failed."); return status; @@ -428,29 +515,53 @@ int32_t UdmfServiceImpl::DeleteData(const QueryOption &query, std::vector runtime; + std::string appId; std::vector deleteKeys; for (const auto &data : dataSet) { - runtime = data.GetRuntime(); - if (runtime == nullptr) { - return E_DB_ERROR; - } - if (runtime->tokenId == query.tokenId) { - unifiedDataSet.push_back(data); - deleteKeys.push_back(runtime->key.key); + auto runtime = data.GetRuntime(); + if (!CheckDeleteDataPermission(appId, runtime, query)) { + continue; } + unifiedDataSet.push_back(data); + deleteKeys.emplace_back(UnifiedKey(runtime->key.key).GetKeyCommonPrefix()); } if (deleteKeys.empty()) { ZLOGE("No data to delete for this application"); return E_OK; } ZLOGI("Delete data start. size: %{public}zu.", deleteKeys.size()); - if (store->DeleteBatch(deleteKeys) != E_OK) { + status = store->DeleteBatch(deleteKeys); + if (status != E_OK) { ZLOGE("Remove data failed."); + HandleDbError(key.intention, status); return E_DB_ERROR; } return E_OK; } +bool UdmfServiceImpl::CheckDeleteDataPermission(std::string &appId, const std::shared_ptr &runtime, + const QueryOption &query) +{ + if (runtime == nullptr) { + ZLOGE("Invalid runtime."); + return false; + } + if (runtime->tokenId == query.tokenId) { + return true; + } + std::string bundleName; + std::string specificBundleName; + if (!PreProcessUtils::GetSpecificBundleNameByTokenId(query.tokenId, specificBundleName, bundleName)) { + ZLOGE("GetSpecificBundleNameByTokenId failed, tokenid:%{public}u", query.tokenId); + return false; + } + if (CheckAppId(runtime, bundleName) != E_OK) { + ZLOGE("Delete failed: tokenId or appId mismatch, bundleName: %{public}s", bundleName.c_str()); + return false; + } + return true; +} + int32_t UdmfServiceImpl::GetSummary(const QueryOption &query, Summary &summary) { ZLOGD("start"); @@ -465,9 +576,10 @@ int32_t UdmfServiceImpl::GetSummary(const QueryOption &query, Summary &summary) ZLOGE("Get store failed:%{public}s", key.intention.c_str()); return E_DB_ERROR; } - - if (store->GetSummary(key, summary) != E_OK) { + int32_t status = store->GetSummary(key, summary); + if (status != E_OK) { ZLOGE("Store get summary failed:%{public}s", key.intention.c_str()); + HandleDbError(key.intention, status); return E_DB_ERROR; } return E_OK; @@ -484,17 +596,16 @@ int32_t UdmfServiceImpl::AddPrivilege(const QueryOption &query, Privilege &privi std::string processName; if (!PreProcessUtils::GetNativeProcessNameByToken(query.tokenId, processName)) { + ZLOGE("GetNativeProcessNameByToken is faild"); return E_ERROR; } - if (key.intention == UD_INTENTION_MAP.at(UD_INTENTION_DRAG)) { - if (find(DRAG_AUTHORIZED_PROCESSES, std::end(DRAG_AUTHORIZED_PROCESSES), processName) == - std::end(DRAG_AUTHORIZED_PROCESSES)) { - ZLOGE("Process:%{public}s lacks permission for intention:drag", processName.c_str()); - return E_NO_PERMISSION; - } - } else { - ZLOGE("Intention: %{public}s has no authorized processes", key.intention.c_str()); + if (CheckAddPrivilegePermission(key, processName, query) != E_OK) { + ZLOGE("Intention:%{public}s no permission", key.intention.c_str()); + return E_NO_PERMISSION; + } + if (!UTILS::IsNativeCallingToken()) { + ZLOGE("Calling Token is not native"); return E_NO_PERMISSION; } @@ -505,27 +616,34 @@ int32_t UdmfServiceImpl::AddPrivilege(const QueryOption &query, Privilege &privi } Runtime runtime; - auto res = store->GetRuntime(query.key, runtime); + int32_t res = store->GetRuntime(query.key, runtime); if (res == E_NOT_FOUND) { + std::lock_guard lock(cacheMutex_); privilegeCache_[query.key] = privilege; ZLOGW("Add privilege in cache, key: %{public}s.", query.key.c_str()); return E_OK; } if (res != E_OK) { ZLOGE("Get runtime failed, res:%{public}d, key:%{public}s.", res, query.key.c_str()); + HandleDbError(key.intention, res); return res; } runtime.privileges.emplace_back(privilege); res = store->PutRuntime(query.key, runtime); if (res != E_OK) { ZLOGE("Update runtime failed, res:%{public}d, key:%{public}s", res, query.key.c_str()); + HandleDbError(key.intention, res); } return res; } int32_t UdmfServiceImpl::Sync(const QueryOption &query, const std::vector &devices) { - ZLOGD("start"); + if (!UTILS::IsTokenNative() || + !DistributedKv::PermissionValidator::GetInstance().CheckSyncPermission(query.tokenId)) { + ZLOGE("Tokenid permission verification failed!"); + return E_NO_PERMISSION; + } RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), BizScene::SYNC_DATA, SyncDataStage::SYNC_BEGIN, StageRes::IDLE, BizState::DFX_BEGIN); UnifiedKey key(query.key); @@ -536,6 +654,12 @@ int32_t UdmfServiceImpl::Sync(const QueryOption &query, const std::vector &devices) +{ auto store = StoreCache::GetInstance().GetStore(key.intention); if (store == nullptr) { RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), @@ -550,21 +674,70 @@ int32_t UdmfServiceImpl::Sync(const QueryOption &query, const std::vector lock(mutex_); asyncProcessInfoMap_.insert_or_assign(syncInfo.businessUdKey, syncInfo); - ZLOGD("store.Sync: name=%{public}s, id=%{public}u, status=%{public}u, total=%{public}u, finish=%{public}u", - syncInfo.srcDevName.c_str(), syncInfo.syncId, syncInfo.syncStatus, - syncInfo.syncTotal, syncInfo.syncFinished); }; RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), BizScene::SYNC_DATA, SyncDataStage::SYNC_BEGIN, StageRes::SUCCESS); + int userId = 0; + if (!AccountDelegate::GetInstance()->QueryForegroundUserId(userId)) { + ZLOGE("QueryForegroundUserId failed"); + return E_ERROR; + } + auto meta = BuildMeta(key.intention, userId); + auto uuids = DmAdapter::GetInstance().ToUUID(devices); + if (IsNeedMetaSync(meta, uuids)) { + bool res = MetaDataManager::GetInstance().Sync(uuids, [this, devices, callback, store] (auto &results) { + auto successRes = ProcessResult(results); + if (store->Sync(successRes, callback) != E_OK) { + ZLOGE("Store sync failed"); + RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), + BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::FAILED, E_DB_ERROR, BizState::DFX_END); + } + }); + if (!res) { + ZLOGE("Meta sync failed"); + RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), + BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::FAILED, E_DB_ERROR, BizState::DFX_END); + return E_DB_ERROR; + } + return E_OK; + } if (store->Sync(devices, callback) != E_OK) { - ZLOGE("Store sync failed:%{public}s", key.intention.c_str()); + ZLOGE("Store sync failed"); RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), BizScene::SYNC_DATA, SyncDataStage::SYNC_END, StageRes::FAILED, E_DB_ERROR, BizState::DFX_END); - return E_DB_ERROR; + return UDMF::E_DB_ERROR; } return E_OK; } +bool UdmfServiceImpl::IsNeedMetaSync(const StoreMetaData &meta, const std::vector &uuids) +{ + using namespace OHOS::DistributedData; + bool isAfterMeta = false; + for (const auto &uuid : uuids) { + auto metaData = meta; + metaData.deviceId = uuid; + CapMetaData capMeta; + auto capKey = CapMetaRow::GetKeyFor(uuid); + if (!MetaDataManager::GetInstance().LoadMeta(std::string(capKey.begin(), capKey.end()), capMeta) || + !MetaDataManager::GetInstance().LoadMeta(metaData.GetKeyWithoutPath(), metaData)) { + isAfterMeta = true; + break; + } + auto [exist, mask] = DeviceMatrix::GetInstance().GetRemoteMask(uuid); + if ((mask & DeviceMatrix::META_STORE_MASK) == DeviceMatrix::META_STORE_MASK) { + isAfterMeta = true; + break; + } + auto [existLocal, localMask] = DeviceMatrix::GetInstance().GetMask(uuid); + if ((localMask & DeviceMatrix::META_STORE_MASK) == DeviceMatrix::META_STORE_MASK) { + isAfterMeta = true; + break; + } + } + return isAfterMeta; +} + int32_t UdmfServiceImpl::IsRemoteData(const QueryOption &query, bool &result) { UnifiedKey key(query.key); @@ -579,19 +752,16 @@ int32_t UdmfServiceImpl::IsRemoteData(const QueryOption &query, bool &result) return E_DB_ERROR; } - UnifiedData unifiedData; - if (store->Get(query.key, unifiedData) != E_OK) { - ZLOGE("Store get unifiedData failed:%{public}s", key.intention.c_str()); - return E_DB_ERROR; - } - std::shared_ptr runtime = unifiedData.GetRuntime(); - if (runtime == nullptr) { - ZLOGE("Store get runtime failed, key: %{public}s.", query.key.c_str()); + Runtime runtime; + int32_t res = store->GetRuntime(query.key, runtime); + if (res != E_OK) { + ZLOGE("Get runtime failed, res:%{public}d, key:%{public}s.", res, query.key.c_str()); + HandleDbError(key.intention, res); return E_DB_ERROR; } std::string localDeviceId = PreProcessUtils::GetLocalDeviceId(); - if (localDeviceId != runtime->deviceId) { + if (localDeviceId != runtime.deviceId) { result = true; } return E_OK; @@ -623,9 +793,10 @@ int32_t UdmfServiceImpl::SetAppShareOption(const std::string &intention, int32_t ZLOGE("SetAppShareOption failed,shareOption already set:%{public}s", shareOptionTmp.c_str()); return E_SETTINGS_EXISTED; } - - if (store->PutLocal(std::to_string(accessTokenIDEx), ShareOptionsUtil::GetEnumStr(shareOption)) != E_OK) { - ZLOGE("Store get unifiedData failed:%{public}d", shareOption); + int32_t status = store->PutLocal(std::to_string(accessTokenIDEx), ShareOptionsUtil::GetEnumStr(shareOption)); + if (status != E_OK) { + ZLOGE("Store get unifiedData failed:%{public}d", status); + HandleDbError(intention, status); return E_DB_ERROR; } return E_OK; @@ -647,6 +818,7 @@ int32_t UdmfServiceImpl::GetAppShareOption(const std::string &intention, int32_t int32_t ret = store->GetLocal(std::to_string(accessTokenIDEx), appShareOption); if (ret != E_OK) { ZLOGW("GetLocal failed:%{public}s", intention.c_str()); + HandleDbError(intention, ret); return ret; } ZLOGI("GetLocal ok intention:%{public}s,appShareOption:%{public}s", intention.c_str(), appShareOption.c_str()); @@ -674,8 +846,10 @@ int32_t UdmfServiceImpl::RemoveAppShareOption(const std::string &intention) } UnifiedData unifiedData; - if (store->DeleteLocal(std::to_string(accessTokenIDEx)) != E_OK) { - ZLOGE("Store DeleteLocal failed:%{public}s", intention.c_str()); + int32_t status = store->DeleteLocal(std::to_string(accessTokenIDEx)); + if (status != E_OK) { + ZLOGE("Store DeleteLocal failed:%{public}s, status:%{public}d", intention.c_str(), status); + HandleDbError(intention, status); return E_DB_ERROR; } return E_OK; @@ -698,17 +872,21 @@ int32_t UdmfServiceImpl::OnInitialize() int32_t UdmfServiceImpl::QueryDataCommon( const QueryOption &query, std::vector &dataSet, std::shared_ptr &store) { - auto find = UD_INTENTION_MAP.find(query.intention); - std::string intention = find == UD_INTENTION_MAP.end() ? intention : find->second; - if (!UnifiedDataUtils::IsValidOptions(query.key, intention)) { + UnifiedKey key(query.key); + if (!key.IsValid() && !key.key.empty()) { + ZLOGE("invalid key, query.key: %{public}s", query.key.c_str()); + return E_INVALID_PARAMETERS; + } + std::string intention = FindIntentionMap(query.intention); + if (!IsValidOptionsNonDrag(key, intention)) { ZLOGE("Unified key: %{public}s and intention: %{public}s is invalid.", query.key.c_str(), intention.c_str()); return E_INVALID_PARAMETERS; } - std::string dataPrefix = DATA_PREFIX + intention; - UnifiedKey key(query.key); - key.IsValid(); - if (intention.empty()) { - dataPrefix = UnifiedKey(key.key).GetPropertyKey(); + std::string dataPrefix; + if (key.key.empty()) { + dataPrefix = DATA_PREFIX + intention; + } else { + dataPrefix = UnifiedKey(key.key).GetKeyCommonPrefix(); intention = key.intention; } ZLOGD("dataPrefix = %{public}s, intention: %{public}s.", dataPrefix.c_str(), intention.c_str()); @@ -717,8 +895,10 @@ int32_t UdmfServiceImpl::QueryDataCommon( ZLOGE("Get store failed:%{public}s", intention.c_str()); return E_DB_ERROR; } - if (store->GetBatchData(dataPrefix, dataSet) != E_OK) { - ZLOGE("Get dataSet failed, dataPrefix: %{public}s.", dataPrefix.c_str()); + int32_t status = store->GetBatchData(dataPrefix, dataSet); + if (status != E_OK) { + ZLOGE("Get dataSet failed, dataPrefix: %{public}s, status:%{public}d.", dataPrefix.c_str(), status); + HandleDbError(intention, status); return E_DB_ERROR; } return E_OK; @@ -782,7 +962,7 @@ int32_t UdmfServiceImpl::ResolveAutoLaunch(const std::string &identifier, DBLaun for (const auto &storeMeta : metaData) { if (storeMeta.storeType < StoreMetaData::StoreType::STORE_KV_BEGIN || storeMeta.storeType > StoreMetaData::StoreType::STORE_KV_END || - storeMeta.appId != DistributedData::Bootstrap::GetInstance().GetProcessLabel()) { + storeMeta.appId != Bootstrap::GetInstance().GetProcessLabel()) { continue; } auto identifierTag = DistributedDB::KvStoreDelegateManager::GetKvStoreIdentifier("", storeMeta.appId, @@ -792,11 +972,10 @@ int32_t UdmfServiceImpl::ResolveAutoLaunch(const std::string &identifier, DBLaun } auto store = StoreCache::GetInstance().GetStore(storeMeta.storeId); if (store == nullptr) { - ZLOGE("GetStore fail, storeId:%{public}s", DistributedData::Anonymous::Change(storeMeta.storeId).c_str()); + ZLOGE("GetStore fail, storeId:%{public}s", Anonymous::Change(storeMeta.storeId).c_str()); continue; } - ZLOGI("storeId:%{public}s,appId:%{public}s,user:%{public}s", - DistributedData::Anonymous::Change(storeMeta.storeId).c_str(), + ZLOGI("storeId:%{public}s,appId:%{public}s,user:%{public}s", Anonymous::Change(storeMeta.storeId).c_str(), storeMeta.appId.c_str(), storeMeta.user.c_str()); return E_OK; } @@ -806,7 +985,8 @@ int32_t UdmfServiceImpl::ResolveAutoLaunch(const std::string &identifier, DBLaun bool UdmfServiceImpl::VerifyPermission(const std::string &permission, uint32_t callerTokenId) { if (permission.empty()) { - return true; + ZLOGE("VerifyPermission failed, Permission is empty."); + return false; } int status = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerTokenId, permission); if (status != Security::AccessToken::PermissionState::PERMISSION_GRANTED) { @@ -833,8 +1013,10 @@ void UdmfServiceImpl::RegisterAsyncProcessInfo(const std::string &businessUdKey) int32_t UdmfServiceImpl::OnUserChange(uint32_t code, const std::string &user, const std::string &account) { - ZLOGI("user change, code:%{public}u, user:%{public}s, account:%{public}s", code, user.c_str(), account.c_str()); - if (code == static_cast(DistributedData::AccountStatus::DEVICE_ACCOUNT_SWITCHED)) { + ZLOGI("user change, code:%{public}u, user:%{public}s", code, user.c_str()); + if (code == static_cast(DistributedData::AccountStatus::DEVICE_ACCOUNT_STOPPING) + || code == static_cast(DistributedData::AccountStatus::DEVICE_ACCOUNT_STOPPED) + || code == static_cast(DistributedData::AccountStatus::DEVICE_ACCOUNT_SWITCHED)) { StoreCache::GetInstance().CloseStores(); } return Feature::OnUserChange(code, user, account); @@ -843,23 +1025,18 @@ int32_t UdmfServiceImpl::OnUserChange(uint32_t code, const std::string &user, co void UdmfServiceImpl::TransferToEntriesIfNeed(const QueryOption &query, UnifiedData &unifiedData) { if (unifiedData.IsNeedTransferToEntries() && IsNeedTransferDeviceType(query)) { - unifiedData.TransferToEntries(unifiedData); + unifiedData.ConvertRecordsToEntries(); } } bool UdmfServiceImpl::IsNeedTransferDeviceType(const QueryOption &query) { - auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); - if (samgrProxy == nullptr) { - ZLOGE("Failed to get system ability mgr."); - return false; - } - auto bundleMgrProxy = samgrProxy->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); - if (bundleMgrProxy == nullptr) { - ZLOGE("Failed to Get BMS SA."); + auto deviceInfo = DmAdapter::GetInstance().GetLocalDevice(); + if (deviceInfo.deviceType != DEVICE_TYPE_PC && deviceInfo.deviceType != DEVICE_TYPE_PAD + && deviceInfo.deviceType != DEVICE_TYPE_2IN1) { return false; } - auto bundleManager = iface_cast(bundleMgrProxy); + auto bundleManager = PreProcessUtils::GetBundleMgr(); if (bundleManager == nullptr) { ZLOGE("Failed to get bundle manager"); return false; @@ -883,5 +1060,282 @@ bool UdmfServiceImpl::IsNeedTransferDeviceType(const QueryOption &query) } return false; } + +int32_t UdmfServiceImpl::CheckAddPrivilegePermission(UnifiedKey &key, + std::string &processName, const QueryOption &query) +{ + if (IsFileMangerIntention(key.intention)) { + if (IsFileMangerSa()) { + return E_OK; + } + std::string intention = FindIntentionMap(query.intention); + if (!intention.empty() && key.intention != intention) { + ZLOGE("Query.intention no not equal to key.intention"); + return E_INVALID_PARAMETERS; + } + return E_OK; + } + if (key.intention == UD_INTENTION_MAP.at(UD_INTENTION_DRAG)) { + if (find(DRAG_AUTHORIZED_PROCESSES, std::end(DRAG_AUTHORIZED_PROCESSES), processName) == + std::end(DRAG_AUTHORIZED_PROCESSES)) { + ZLOGE("Process:%{public}s lacks permission for intention:drag", processName.c_str()); + return E_NO_PERMISSION; + } + return E_OK; + } + ZLOGE("Check addPrivilege permission is faild."); + return E_NO_PERMISSION; +} + +bool UdmfServiceImpl::IsFileMangerSa() +{ + if (IPCSkeleton::GetCallingUid() == FOUNDATION_UID) { + return true; + } + ZLOGE("Caller no permission"); + return false; +} + +int32_t UdmfServiceImpl::ProcessData(const QueryOption &query, std::vector &dataSet) +{ + UnifiedKey key(query.key); + if (!key.key.empty() && !key.IsValid()) { + ZLOGE("invalid key, query.key: %{public}s", query.key.c_str()); + return E_INVALID_PARAMETERS; + } + std::string intention = FindIntentionMap(query.intention); + if (intention == UD_INTENTION_MAP.at(UD_INTENTION_DATA_HUB) || + key.intention == UD_INTENTION_MAP.at(UD_INTENTION_DATA_HUB)) { + return E_OK; + } + CheckerManager::CheckInfo info; + info.tokenId = query.tokenId; + for (auto &data : dataSet) { + auto ret = VerifyIntentionPermission(query, data, key, info); + if (ret != E_OK) { + ZLOGE("Verify intention permission is faild:%{public}d", ret); + return ret; + } + } + return E_OK; +} + +int32_t UdmfServiceImpl::VerifyIntentionPermission(const QueryOption &query, + UnifiedData &data, UnifiedKey &key, CheckerManager::CheckInfo &info) +{ + std::shared_ptr runtime = data.GetRuntime(); + if (runtime == nullptr) { + ZLOGE("runtime is nullptr."); + return E_DB_ERROR; + } + if (!CheckerManager::GetInstance().IsValid(runtime->privileges, info)) { + ZLOGE("Query no permission."); + return E_NO_PERMISSION; + } + if (!IsReadAndKeep(runtime->privileges, query)) { + if (LifeCycleManager::GetInstance().OnGot(key) != E_OK) { + ZLOGE("Remove data failed:%{public}s", key.intention.c_str()); + return E_DB_ERROR; + } + } + return E_OK; +} + +bool UdmfServiceImpl::IsFileMangerIntention(const std::string &intention) +{ + Intention optionIntention = UnifiedDataUtils::GetIntentionByString(intention); + if (optionIntention == UD_INTENTION_SYSTEM_SHARE || + optionIntention == UD_INTENTION_MENU || + optionIntention == UD_INTENTION_PICKER) { + return true; + } + return false; +} + +std::string UdmfServiceImpl::FindIntentionMap(const Intention &queryIntention) +{ + auto find = UD_INTENTION_MAP.find(queryIntention); + return find == UD_INTENTION_MAP.end() ? "" : find->second; +} + +bool UdmfServiceImpl::IsValidOptionsNonDrag(UnifiedKey &key, const std::string &intention) +{ + if (UnifiedDataUtils::IsValidOptions(key, intention)) { + return !key.key.empty() || intention == UD_INTENTION_MAP.at(Intention::UD_INTENTION_DATA_HUB); + } + return false; +} + +int32_t UdmfServiceImpl::SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptr iUdmfNotifier, std::string &key) +{ + std::string bundleName; + std::string specificBundleName; + auto tokenId = static_cast(IPCSkeleton::GetCallingTokenID()); + if (!PreProcessUtils::GetSpecificBundleNameByTokenId(tokenId, specificBundleName, bundleName)) { + ZLOGE("GetSpecificBundleNameByTokenId failed, tokenid:%{public}u", tokenId); + return E_ERROR; + } + UnifiedKey udkey(UD_INTENTION_MAP.at(UD_INTENTION_DRAG), specificBundleName, dataLoadInfo.sequenceKey); + key = udkey.GetUnifiedKey(); + dataLoadCallback_.Insert(key, iface_cast(iUdmfNotifier)); + + auto store = StoreCache::GetInstance().GetStore(UD_INTENTION_MAP.at(UD_INTENTION_DRAG)); + if (store == nullptr) { + ZLOGE("Get store failed:%{public}s", key.c_str()); + return E_DB_ERROR; + } + + Summary summary; + UnifiedDataHelper::GetSummaryFromLoadInfo(dataLoadInfo, summary); + int32_t status = store->PutSummary(udkey, summary); + if (status != E_OK) { + ZLOGE("Put summary failed:%{public}s, status:%{public}d", key.c_str(), status); + HandleDbError(UD_INTENTION_MAP.at(UD_INTENTION_DRAG), status); + return E_DB_ERROR; + } + return E_OK; +} + +int32_t UdmfServiceImpl::PushDelayData(const std::string &key, UnifiedData &unifiedData) +{ + CustomOption option; + option.intention = UD_INTENTION_DRAG; + option.tokenId = static_cast(IPCSkeleton::GetCallingTokenID()); + if (PreProcessUtils::FillRuntimeInfo(unifiedData, option) != E_OK) { + ZLOGE("Imputation failed"); + return E_ERROR; + } + int32_t ret = PreProcessUtils::SetRemoteUri(option.tokenId, unifiedData); + if (ret != E_OK) { + ZLOGW("SetRemoteUri failed, ret:%{public}d, key:%{public}s.", ret, key.c_str()); + } + + auto it = delayDataCallback_.Find(key); + if (!it.first) { + ZLOGE("DelayData callback no exist, key:%{public}s", key.c_str()); + return E_ERROR; + } + QueryOption query; + query.tokenId = it.second.tokenId; + query.key = key; + if (option.tokenId != query.tokenId && !IsPermissionInCache(query)) { + ZLOGE("No permission"); + return E_NO_PERMISSION; + } + ret = ProcessUri(query, unifiedData); + if (ret != E_OK) { + ZLOGE("ProcessUri failed:%{public}d", ret); + return E_NO_PERMISSION; + } + { + std::lock_guard lock(cacheMutex_); + privilegeCache_.erase(key); + } + PreProcessUtils::SetRemoteData(unifiedData); + + TransferToEntriesIfNeed(query, unifiedData); + return HandleDelayDataCallback(it.second, unifiedData, key); +} + +int32_t UdmfServiceImpl::HandleDelayDataCallback(DelayGetDataInfo &delayGetDataInfo, UnifiedData &unifiedData, + const std::string &key) +{ + auto callback = iface_cast(delayGetDataInfo.dataCallback); + if (callback == nullptr) { + ZLOGE("Delay data callback is null, key:%{public}s", key.c_str()); + return E_ERROR; + } + callback->DelayDataCallback(key, unifiedData); + delayDataCallback_.Erase(key); + return E_OK; +} + +int32_t UdmfServiceImpl::GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr iUdmfNotifier, std::shared_ptr unifiedData) +{ + ZLOGD("start"); + QueryOption query; + query.tokenId = static_cast(IPCSkeleton::GetCallingTokenID()); + query.key = key; + if (unifiedData == nullptr) { + ZLOGE("Data is null, key:%{public}s", key.c_str()); + return E_ERROR; + } + auto status = RetrieveData(query, *unifiedData); + if (status == E_OK) { + return E_OK; + } + if (status != E_NOT_FOUND) { + ZLOGE("Retrieve data failed, key:%{public}s", key.c_str()); + return status; + } + DelayGetDataInfo delayGetDataInfo; + delayGetDataInfo.dataCallback = iUdmfNotifier; + delayGetDataInfo.tokenId = static_cast(IPCSkeleton::GetCallingTokenID()); + delayDataCallback_.InsertOrAssign(key, std::move(delayGetDataInfo)); + + auto it = dataLoadCallback_.Find(key); + if (!it.first) { + ZLOGE("DataLoad callback no exist, key:%{public}s", key.c_str()); + return E_ERROR; + } + it.second->HandleDelayObserver(key, dataLoadInfo); + dataLoadCallback_.Erase(key); + return E_OK; +} + +bool UdmfServiceImpl::IsValidInput(const QueryOption &query, UnifiedData &unifiedData, UnifiedKey &key) +{ + if (!unifiedData.IsValid() || !key.IsValid()) { + ZLOGE("Data or key is invalid, key = %{public}s", query.key.c_str()); + return false; + } + std::string intention = FindIntentionMap(query.intention); + if (!IsValidOptionsNonDrag(key, intention) || key.intention != UD_INTENTION_MAP.at(UD_INTENTION_DATA_HUB)) { + ZLOGE("Invalid params: key.intention = %{public}s, intention = %{public}s", + key.intention.c_str(), intention.c_str()); + return false; + } + return true; +} + +void UdmfServiceImpl::CloseStoreWhenCorrupted(const std::string &intention, int32_t status) +{ + if (status == E_DB_CORRUPTED) { + ZLOGE("Kv database corrupted, start to remove store"); + StoreCache::GetInstance().RemoveStore(intention); + } +} + +void UdmfServiceImpl::HandleDbError(const std::string &intention, int32_t &status) +{ + CloseStoreWhenCorrupted(intention, status); + if (status == E_DB_CORRUPTED) { + // reset status to E_DB_ERROR + status = E_DB_ERROR; + } +} + +StoreMetaData UdmfServiceImpl::BuildMeta(const std::string &storeId, int userId) +{ + StoreMetaData meta; + meta.user = std::to_string(userId); + meta.storeId = storeId; + meta.bundleName = Bootstrap::GetInstance().GetProcessLabel(); + return meta; +} + +std::vector UdmfServiceImpl::ProcessResult(const std::map &results) +{ + std::vector devices; + for (const auto &[uuid, status] : results) { + if (static_cast(status) == DistributedDB::DBStatus::OK) { + DeviceMatrix::GetInstance().OnExchanged(uuid, DeviceMatrix::META_STORE_MASK); + devices.emplace_back(uuid); + } + } + ZLOGI("Meta sync finish, total size:%{public}zu, success size:%{public}zu", results.size(), devices.size()); + return devices; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h index 48a80b44..0260d75f 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h @@ -19,6 +19,9 @@ #include "store_cache.h" #include "udmf_service_stub.h" #include "kv_store_delegate_manager.h" +#include "metadata/store_meta_data.h" +#include "checker_manager.h" +#include "udmf_notifier_proxy.h" namespace OHOS { namespace UDMF { /* @@ -47,7 +50,14 @@ public: int32_t ClearAsynProcessByKey(const std::string &businessUdKey) override; int32_t ResolveAutoLaunch(const std::string &identifier, DBLaunchParam ¶m) override; int32_t OnUserChange(uint32_t code, const std::string &user, const std::string &account) override; + int32_t SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptr iUdmfNotifier, + std::string &key) override; + int32_t PushDelayData(const std::string &key, UnifiedData &unifiedData) override; + int32_t GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr iUdmfNotifier, std::shared_ptr unifiedData) override; private: + bool IsNeedMetaSync(const DistributedData::StoreMetaData &meta, const std::vector &uuids); + int32_t StoreSync(const UnifiedKey &key, const QueryOption &query, const std::vector &devices); int32_t SaveData(CustomOption &option, UnifiedData &unifiedData, std::string &key); int32_t RetrieveData(const QueryOption &query, UnifiedData &unifiedData); int32_t QueryDataCommon(const QueryOption &query, std::vector &dataSet, std::shared_ptr &store); @@ -60,6 +70,28 @@ private: void RegisterAsyncProcessInfo(const std::string &businessUdKey); void TransferToEntriesIfNeed(const QueryOption &query, UnifiedData &unifiedData); bool IsNeedTransferDeviceType(const QueryOption &query); + bool CheckDragParams(UnifiedKey &key, const QueryOption &query); + int32_t CheckAddPrivilegePermission(UnifiedKey &key, std::string &processName, const QueryOption &query); + int32_t ProcessData(const QueryOption &query, std::vector &dataSet); + int32_t VerifyIntentionPermission(const QueryOption &query, UnifiedData &dataSet, + UnifiedKey &key, CheckerManager::CheckInfo &info); + bool IsFileMangerSa(); + bool IsFileMangerIntention(const std::string &intention); + std::string FindIntentionMap(const Intention &queryintention); + bool IsValidOptionsNonDrag(UnifiedKey &key, const std::string &intention); + bool IsValidInput(const QueryOption &query, UnifiedData &unifiedData, UnifiedKey &key); + bool CheckDeleteDataPermission(std::string &appId, const std::shared_ptr &runtime, + const QueryOption &query); + int32_t CheckAppId(std::shared_ptr runtime, const std::string &bundleName); + void CloseStoreWhenCorrupted(const std::string &intention, int32_t status); + void HandleDbError(const std::string &intention, int32_t &status); + int32_t HandleDelayDataCallback(DelayGetDataInfo &delayGetDataInfo, UnifiedData &unifiedData, + const std::string &key); + int32_t VerifyDataAccessPermission(std::shared_ptr runtime, const QueryOption &query, + const UnifiedData &unifiedData); + std::vector ProcessResult(const std::map &results); + DistributedData::StoreMetaData BuildMeta(const std::string &storeId, int userId); + int32_t VerifyUpdatePermission(const QueryOption &query, UnifiedData &unifiedData, std::string &bundleName); class Factory { public: @@ -70,11 +102,14 @@ private: std::shared_ptr product_; }; static Factory factory_; - std::map privilegeCache_; + mutable std::recursive_mutex cacheMutex_; + std::map privilegeCache_ {}; std::shared_ptr executors_; std::mutex mutex_; - std::unordered_map asyncProcessInfoMap_; + std::unordered_map asyncProcessInfoMap_ {}; + ConcurrentMap> dataLoadCallback_ {}; + ConcurrentMap delayDataCallback_ {}; }; } // namespace UDMF } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.cpp index f433413b..9e9a05f1 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.cpp @@ -289,5 +289,66 @@ int32_t UdmfServiceStub::OnClearAsynProcessByKey(MessageParcel &data, MessagePar } return E_OK; } + +int32_t UdmfServiceStub::OnSetDelayInfo(MessageParcel &data, MessageParcel &reply) +{ + ZLOGD("start"); + DataLoadInfo dataLoadInfo; + sptr iUdmfNotifier; + + if (!ITypesUtil::Unmarshal(data, dataLoadInfo, iUdmfNotifier)) { + ZLOGE("Unmarshal failed!"); + return E_READ_PARCEL_ERROR; + } + std::string key; + int32_t status = SetDelayInfo(dataLoadInfo, iUdmfNotifier, key); + if (!ITypesUtil::Marshal(reply, status, key)) { + ZLOGE("Marshal failed:%{public}d", status); + return E_WRITE_PARCEL_ERROR; + } + return E_OK; +} + +int32_t UdmfServiceStub::OnPushDelayData(MessageParcel &data, MessageParcel &reply) +{ + ZLOGD("start"); + std::string key; + UnifiedData unifiedData; + + if (!ITypesUtil::Unmarshal(data, key, unifiedData)) { + ZLOGE("Unmarshal failed!"); + return E_READ_PARCEL_ERROR; + } + + int32_t status = PushDelayData(key, unifiedData); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal failed:%{public}d", status); + return E_WRITE_PARCEL_ERROR; + } + return E_OK; +} + +int32_t UdmfServiceStub::OnGetDataIfAvailable(MessageParcel &data, MessageParcel &reply) +{ + ZLOGD("start"); + std::string key; + DataLoadInfo dataLoadInfo; + sptr iUdmfNotifier; + if (!ITypesUtil::Unmarshal(data, key, dataLoadInfo, iUdmfNotifier)) { + ZLOGE("Unmarshal failed!"); + return E_READ_PARCEL_ERROR; + } + auto unifiedData = std::make_shared(); + int32_t status = GetDataIfAvailable(key, dataLoadInfo, iUdmfNotifier, unifiedData); + if (unifiedData == nullptr) { + ZLOGE("Data is null, key:%{public}s", key.c_str()); + return E_ERROR; + } + if (!ITypesUtil::Marshal(reply, status, *unifiedData)) { + ZLOGE("Marshal failed:%{public}d", status); + return E_WRITE_PARCEL_ERROR; + } + return E_OK; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.h b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.h index 793a13d9..c5f617a9 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_stub.h @@ -46,6 +46,9 @@ private: int32_t OnObtainAsynProcess(MessageParcel &data, MessageParcel &reply); int32_t OnClearAsynProcessByKey(MessageParcel &data, MessageParcel &reply); int32_t OnInvokeHap(MessageParcel &data, MessageParcel &reply); + int32_t OnPushDelayData(MessageParcel &data, MessageParcel &reply); + int32_t OnSetDelayInfo(MessageParcel &data, MessageParcel &reply); + int32_t OnGetDataIfAvailable(MessageParcel &data, MessageParcel &reply); using Handler = int32_t (UdmfServiceStub::*)(MessageParcel &data, MessageParcel &reply); static constexpr Handler HANDLERS[static_cast(UdmfServiceInterfaceCode::CODE_BUTT)] = { @@ -62,7 +65,10 @@ private: &UdmfServiceStub::OnGetAppShareOption, &UdmfServiceStub::OnRemoveAppShareOption, &UdmfServiceStub::OnObtainAsynProcess, - &UdmfServiceStub::OnClearAsynProcessByKey + &UdmfServiceStub::OnClearAsynProcessByKey, + &UdmfServiceStub::OnSetDelayInfo, + &UdmfServiceStub::OnPushDelayData, + &UdmfServiceStub::OnGetDataIfAvailable, }; }; } // namespace UDMF diff --git a/interface_sdk/api/@ohos.data.UdmfComponents.d.ets b/interface_sdk/api/@ohos.data.UdmfComponents.d.ets new file mode 100644 index 00000000..e3a59e42 --- /dev/null +++ b/interface_sdk/api/@ohos.data.UdmfComponents.d.ets @@ -0,0 +1,112 @@ +/* + * 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. + */ +/** + * @file + * @kit ArkData + */ +import uniformDataStruct from '@ohos.data.uniformDataStruct'; + +/** + * Enumerates the form card types. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ +declare enum FormType { + /** + * Big form card, with fixed size of 4 x 4. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ + TYPE_BIG = 0, + + /** + * Medium-sized form card, with fixed size of 4 x 2. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ + TYPE_MID = 1, + + /** + * Small form card, with fixed size of 2 x 1. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ + TYPE_SMALL = 2 +} + +/** + * Defines a content form card. + * + * @struct { ContentFormCard } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ +@Component +declare struct ContentFormCard { + /** + * Data of the form card. + * + * @type { uniformDataStruct.ContentForm } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ + contentFormData: uniformDataStruct.ContentForm; + + /** + * Type of the form card. + * + * @type { FormType } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ + @Prop + formType: FormType; + + /** + * Width of the form card. + * + * @type { ?number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ + @Prop + formWidth?: number; + + /** + * Height of the form card. + * + * @type { ?number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ + @Prop + formHeight?: number; + + /** + * Callback to be invoked when the form card is tapped. + * + * @type { ?Function } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 20 + */ + handleOnClick?: Function; +} + +export { ContentFormCard, FormType }; \ No newline at end of file diff --git a/interface_sdk/api/@ohos.data.ValuesBucket.d.ts b/interface_sdk/api/@ohos.data.ValuesBucket.d.ts index a3951e90..2406877f 100644 --- a/interface_sdk/api/@ohos.data.ValuesBucket.d.ts +++ b/interface_sdk/api/@ohos.data.ValuesBucket.d.ts @@ -34,6 +34,16 @@ * @crossplatform * @since 12 */ +/** + * Indicates possible value types + * + * @typedef { number | string | boolean } + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @stagemodelonly + * @crossplatform + * @atomicservice + * @since 20 + */ export type ValueType = number | string | boolean; /** diff --git a/interface_sdk/api/@ohos.data.cloudData.d.ts b/interface_sdk/api/@ohos.data.cloudData.d.ts index 22288866..d8a2e688 100644 --- a/interface_sdk/api/@ohos.data.cloudData.d.ts +++ b/interface_sdk/api/@ohos.data.cloudData.d.ts @@ -158,6 +158,34 @@ declare namespace cloudData { normal: number; } + /** + * Describes sync status. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 18 + */ + enum SyncStatus { + /** + * Indicates cloud sync status is running. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 18 + */ + RUNNING = 0, + + /** + * Indicates cloud sync status was finished. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 18 + */ + FINISHED = 1 + } + /** * Sync information. * @@ -196,6 +224,16 @@ declare namespace cloudData { * @since 12 */ code: relationalStore.ProgressCode; + + /** + * Sync status. + * + * @type { ?SyncStatus } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 18 + */ + syncStatus?: SyncStatus; } /** diff --git a/interface_sdk/api/@ohos.data.cloudExtension.d.ts b/interface_sdk/api/@ohos.data.cloudExtension.d.ts index d983c477..e00e9d93 100644 --- a/interface_sdk/api/@ohos.data.cloudExtension.d.ts +++ b/interface_sdk/api/@ohos.data.cloudExtension.d.ts @@ -33,6 +33,7 @@ declare namespace cloudExtension { /** * Provides interface for managing cloud assets. * + * @extends relationalStore.Asset * @interface CloudAsset * @syscap SystemCapability.DistributedDataManager.CloudSync.Server * @systemapi diff --git a/interface_sdk/api/@ohos.data.dataShare.d.ts b/interface_sdk/api/@ohos.data.dataShare.d.ts index 67e04fe7..5dfdf18f 100644 --- a/interface_sdk/api/@ohos.data.dataShare.d.ts +++ b/interface_sdk/api/@ohos.data.dataShare.d.ts @@ -56,6 +56,17 @@ declare namespace dataShare { * @since 10 */ isProxy?: boolean; + /** + * Specifies the time to wait for connecting extension, in seconds. + * + * @type { ?number } + * @default 2 + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 18 + */ + waitTime?: number; } /** @@ -72,6 +83,21 @@ declare namespace dataShare { * @stagemodelonly * @since 9 */ + /** + * Obtains the dataShareHelper. + * + * @param { Context } context - Indicates the application context. + * @param { string } uri - Indicates the path of the file to open. + * @param { AsyncCallback } callback - {DataShareHelper}: The dataShareHelper for consumer. + * @throws { BusinessError } 202 - Not System Application. + * @throws { BusinessError } 401 - Parameter error.Possible causes: 1. Mandatory parameters are left unspecified; + * 2. Incorrect parameters types. + * @throws { BusinessError } 15700010 - The DataShareHelper is not initialized successfully. + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 19 + */ function createDataShareHelper(context: Context, uri: string, callback: AsyncCallback): void; /** * Obtains the dataShareHelper. @@ -88,6 +114,22 @@ declare namespace dataShare { * @stagemodelonly * @since 10 */ + /** + * Obtains the dataShareHelper. + * + * @param { Context } context - Indicates the application context. + * @param { string } uri - Indicates the path of the file to open. + * @param { DataShareHelperOptions } options - Indicates the optional config. + * @param { AsyncCallback } callback - {DataShareHelper}: The dataShareHelper for consumer. + * @throws { BusinessError } 202 - Not System Application. + * @throws { BusinessError } 401 - Parameter error.Possible causes: 1. Mandatory parameters are left unspecified; + * 2. Incorrect parameters types. + * @throws { BusinessError } 15700010 - The DataShareHelper is not initialized successfully. + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 19 + */ function createDataShareHelper( context: Context, uri: string, @@ -124,6 +166,22 @@ declare namespace dataShare { * @stagemodelonly * @since 10 */ + /** + * Obtains the dataShareHelper. + * + * @param { Context } context - Indicates the application context. + * @param { string } uri - Indicates the path of the file to open. + * @param { DataShareHelperOptions } options - Indicates the optional config. + * @returns { Promise } {DataShareHelper}: The dataShareHelper for consumer. + * @throws { BusinessError } 202 - Not System Application. + * @throws { BusinessError } 401 - Parameter error.Possible causes: 1. Mandatory parameters are left unspecified; + * 2. Incorrect parameters types. + * @throws { BusinessError } 15700010 - The DataShareHelper is not initialized successfully. + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 19 + */ function createDataShareHelper( context: Context, uri: string, @@ -144,6 +202,21 @@ declare namespace dataShare { * @stagemodelonly * @since 11 */ + /** + * Enables silent access dynamically. + * + * @param { Context } context - Indicates the application context. + * @param { string } uri - Indicates the uri of the data share silent proxy resource. + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 202 - Not System Application. + * @throws { BusinessError } 401 - Parameter error.Possible causes: 1. Mandatory parameters are left unspecified; + * 2. Incorrect parameters types. + * @throws { BusinessError } 15700011 - The URI is not exist. + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 19 + */ function enableSilentProxy(context: Context, uri?: string): Promise; /** @@ -160,6 +233,21 @@ declare namespace dataShare { * @stagemodelonly * @since 11 */ + /** + * Disables silent access dynamically. + * + * @param { Context } context - Indicates the application context. + * @param { string } uri - Indicates the uri of the data share silent proxy resource. + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 202 - Not System Application. + * @throws { BusinessError } 401 - Parameter error.Possible causes: 1. Mandatory parameters are left unspecified; + * 2. Incorrect parameters types. + * @throws { BusinessError } 15700011 - The URI is not exist. + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 19 + */ function disableSilentProxy(context: Context, uri?: string): Promise; /** @@ -362,6 +450,18 @@ declare namespace dataShare { * @since 10 */ scheduler: string; + + /** + * Specifies the update sql of the template. + * The update is called after the predicates execution is complete. + * + * @type { ?string } + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 18 + */ + update?: string; } /** * Specifies the operation result structure. @@ -600,7 +700,7 @@ declare namespace dataShare { /** * Subscribes to the change of the data specified by the given URI. * - * @param { 'dataChange' } type - Indicates the event type, which must be 'dataChange'. + * @param { 'dataChange' } event - Indicates the event type, which must be 'dataChange'. * @param { SubscriptionType } type - Indicates the subscription type, which is defined in {@link SubscriptionType}. * @param { string } uri - Indicates the path of the data to subscribe. * @param { AsyncCallback } callback - Indicates the callback used to return the data change. @@ -618,7 +718,7 @@ declare namespace dataShare { /** * Unsubscribes from the change of the data specified by the given URI. * - * @param { 'dataChange' } type - Indicates the event type, which must be 'dataChange'. + * @param { 'dataChange' } event - Indicates the event type, which must be 'dataChange'. * @param { SubscriptionType } type - Indicates the subscription type, which is defined in {@link SubscriptionType}. * @param { string } uri - Indicates the path of the data to unsubscribe. * @param { AsyncCallback } callback - Indicates the callback to unsubscribe. @@ -1309,7 +1409,8 @@ declare namespace dataShare { * @returns {Promise>>} {Record>}: The result set of batch operations. * @throws { BusinessError } 401 - Parameter error.Possible causes: 1. Mandatory parameters are left unspecified; * 2. Incorrect parameters types. - * @throws { BusinessError } 15700000 - Inner error. + * @throws { BusinessError } 15700000 - Inner error. Possible causes: 1.The internal status is abnormal; + * 2.The interface is incorrectly used; 3.Permission configuration error; 4.A system error. * @throws { BusinessError } 15700013 - The DataShareHelper instance is already closed. * @throws { BusinessError } 202 - Not System Application. * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer @@ -1583,12 +1684,25 @@ declare namespace dataShare { * Close the connection between datashare and extension. * * @returns { Promise } The promise returned by the function. - * @throws { BusinessError } 15700000 - Inner error. + * @throws { BusinessError } 15700000 - Inner error. Possible causes: 1.The internal status is abnormal; + * 2.The interface is incorrectly used; 3.Permission configuration error; 4.A system error. * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer * @systemapi * @stagemodelonly * @since 12 */ + /** + * Close the connection between datashare and extension. + * + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 202 - Not System Application. + * @throws { BusinessError } 15700000 - Inner error. Possible causes: 1.The internal status is abnormal; + * 2.The interface is incorrectly used; 3.Permission configuration error; 4.A system error. + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 19 + */ close(): Promise; } } diff --git a/interface_sdk/api/@ohos.data.dataSharePredicates.d.ts b/interface_sdk/api/@ohos.data.dataSharePredicates.d.ts index 19fb6d0e..281cdd85 100644 --- a/interface_sdk/api/@ohos.data.dataSharePredicates.d.ts +++ b/interface_sdk/api/@ohos.data.dataSharePredicates.d.ts @@ -37,27 +37,51 @@ import { ValueType } from './@ohos.data.ValuesBucket'; * @crossplatform * @since 12 */ +/** + * This module provides data share services based on the ExtensionAbility. + * + * @namespace dataSharePredicates + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @StageModelOnly + * @crossplatform + * @atomicservice + * @since 20 + */ declare namespace dataSharePredicates { /** - * Manages relational database configurations. + * Provides a filter object to query data in a database by using DataShare APIs. + * This type is not multi-thread safe. If a DataSharePredicates instance is operated by multiple threads + * at the same time in an application, use a lock for it. * * @syscap SystemCapability.DistributedDataManager.DataShare.Core * @StageModelOnly * @since 10 */ /** - * Manages relational database configurations. + * Provides a filter object to query data in a database by using DataShare APIs. + * This type is not multi-thread safe. If a DataSharePredicates instance is operated by multiple threads + * at the same time in an application, use a lock for it. * * @syscap SystemCapability.DistributedDataManager.DataShare.Core * @StageModelOnly * @crossplatform * @since 12 */ + /** + * Manages relational database configurations. + * + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @StageModelOnly + * @crossplatform + * @atomicservice + * @since 20 + */ class DataSharePredicates { /** * Configure the DataSharePredicates to match the field whose data type is ValueType and value is equal * to a specified value. * This method is similar to = of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @param { ValueType } value - Indicates the value to match with the DataSharePredicates. @@ -70,6 +94,7 @@ declare namespace dataSharePredicates { * Configure the DataSharePredicates to match the field whose data type is ValueType and value is equal * to a specified value. * This method is similar to = of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @param { ValueType } value - Indicates the value to match with the DataSharePredicates. @@ -79,12 +104,28 @@ declare namespace dataSharePredicates { * @crossplatform * @since 12 */ + /** + * Configure the DataSharePredicates to match the field whose data type is ValueType and value is equal + * to a specified value. + * This method is similar to = of the SQL statement. + * Currently only used for RDB and KVDB(schema). + * + * @param { string } field - Indicates the column name in the database table. + * @param { ValueType } value - Indicates the value to match with the DataSharePredicates. + * @returns { DataSharePredicates } Returns the DataSharePredicates that match the specified field. + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @StageModelOnly + * @crossplatform + * @atomicservice + * @since 20 + */ equalTo(field: string, value: ValueType): DataSharePredicates; /** * Configure the DataSharePredicates to match the field whose data type is ValueType and value is unequal to * a specified value. * This method is similar to != of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @param { ValueType } value - Indicates the value to match with the DataSharePredicates. @@ -99,6 +140,7 @@ declare namespace dataSharePredicates { /** * Adds a left parenthesis to the DataSharePredicates. * This method is similar to ( of the SQL statement and needs to be used together with endWrap(). + * Currently only used for RDB. * * @returns { DataSharePredicates } Returns the DataSharePredicates with the left parenthesis. * @syscap SystemCapability.DistributedDataManager.DataShare.Core @@ -112,6 +154,7 @@ declare namespace dataSharePredicates { * Adds a right parenthesis to the DataSharePredicates. * This method is similar to ) of the SQL statement and needs to be used together * with beginWrap(). + * Currently only used for RDB. * * @returns { DataSharePredicates } Returns the DataSharePredicates with the right parenthesis. * @syscap SystemCapability.DistributedDataManager.DataShare.Core @@ -124,6 +167,7 @@ declare namespace dataSharePredicates { /** * Adds an or condition to the DataSharePredicates. * This method is similar to or of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @returns { DataSharePredicates } Returns the DataSharePredicates with the or condition. * @syscap SystemCapability.DistributedDataManager.DataShare.Core @@ -136,6 +180,7 @@ declare namespace dataSharePredicates { /** * Adds an and condition to the DataSharePredicates. * This method is similar to and of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @returns { DataSharePredicates } Returns the DataSharePredicates with the and condition. * @syscap SystemCapability.DistributedDataManager.DataShare.Core @@ -145,6 +190,7 @@ declare namespace dataSharePredicates { /** * Adds an and condition to the DataSharePredicates. * This method is similar to and of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @returns { DataSharePredicates } Returns the DataSharePredicates with the and condition. * @syscap SystemCapability.DistributedDataManager.DataShare.Core @@ -152,12 +198,25 @@ declare namespace dataSharePredicates { * @crossplatform * @since 12 */ + /** + * Adds an and condition to the DataSharePredicates. + * This method is similar to and of the SQL statement. + * Currently only used for RDB and KVDB(schema). + * + * @returns { DataSharePredicates } Returns the DataSharePredicates with the and condition. + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @StageModelOnly + * @crossplatform + * @atomicservice + * @since 20 + */ and(): DataSharePredicates; /** * Configure the DataSharePredicates to match the field whose data type is string and value * contains a specified value. * This method is similar to contains of the SQL statement. + * Currently only used for RDB. * * @param { string } field - Indicates the column name in the database table. * @param { string } value - Indicates the value to match with the DataSharePredicates. @@ -173,6 +232,7 @@ declare namespace dataSharePredicates { * Configure the DataSharePredicates to match the field whose data type is string and value starts * with a specified string. * This method is similar to value% of the SQL statement. + * Currently only used for RDB. * * @param { string } field - Indicates the column name in the database table. * @param { string } value - Indicates the value to match with the DataSharePredicates. @@ -188,6 +248,7 @@ declare namespace dataSharePredicates { * Configure the DataSharePredicates to match the field whose data type is string and value * ends with a specified string. * This method is similar to %value of the SQL statement. + * Currently only used for RDB. * * @param { string } field - Indicates the column name in the database table. * @param { string } value - Indicates the value to match with the DataSharePredicates. @@ -202,6 +263,7 @@ declare namespace dataSharePredicates { /** * Configure the DataSharePredicates to match the fields whose value is null. * This method is similar to is null of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @returns { DataSharePredicates } Returns the DataSharePredicates that match the specified field. @@ -215,6 +277,7 @@ declare namespace dataSharePredicates { /** * Configure the DataSharePredicates to match the specified fields whose value is not null. * This method is similar to is not null of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @returns { DataSharePredicates } Returns the DataSharePredicates that match the specified field. @@ -229,6 +292,7 @@ declare namespace dataSharePredicates { * Configure the DataSharePredicates to match the fields whose data type is string and value is * similar to a specified string. * This method is similar to like of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @param { string } value - Indicates the value to match with the DataSharePredicates. The percent sign (%) in the value @@ -245,6 +309,7 @@ declare namespace dataSharePredicates { * Configure the DataSharePredicates to match the fields whose data type is string and value is * not similar to a specified string. * This method is similar to unlike of the SQL statement. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @param { string } value - Indicates the value to match with the DataSharePredicates. The percent sign (%) in the value @@ -261,6 +326,7 @@ declare namespace dataSharePredicates { * Configure DataSharePredicates to match the specified field whose data type is string and the value contains * a wildcard. * Different from like, the input parameters of this method are case-sensitive. + * Currently only used for RDB. * * @param { string } field - Indicates the column name in the database table. * @param { string } value - Indicates the value to match with DataSharePredicates. @@ -274,6 +340,7 @@ declare namespace dataSharePredicates { /** * Restricts the value of the field to the range between low value and high value. + * Currently only used for RDB. * * @param { string } field - Indicates the column name. * @param { ValueType } low - Indicates the minimum value. @@ -289,6 +356,7 @@ declare namespace dataSharePredicates { /** * Configure DataSharePredicates to match the specified field whose data type is int and value is * out of a given range. + * Currently only used for RDB. * * @param { string } field - Indicates the column name in the database table. * @param { ValueType } low - Indicates the minimum value to match with DataSharePredicates. @@ -303,6 +371,7 @@ declare namespace dataSharePredicates { /** * Restricts the value of the field to be greater than the specified value. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name. * @param { ValueType } value - Indicates the String field. @@ -316,6 +385,7 @@ declare namespace dataSharePredicates { /** * Restricts the value of the field to be smaller than the specified value. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name. * @param { ValueType } value - Indicates the String field. @@ -329,6 +399,7 @@ declare namespace dataSharePredicates { /** * Restricts the value of the field to be greater than or equal to the specified value. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name. * @param { ValueType } value - Indicates the String field. @@ -342,6 +413,7 @@ declare namespace dataSharePredicates { /** * Restricts the value of the field to be smaller than or equal to the specified value. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name. * @param { ValueType } value - Indicates the String field. @@ -356,6 +428,7 @@ declare namespace dataSharePredicates { /** * Restricts the ascending order of the return list. When there are several orders, * the one close to the head has the highest priority. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name for sorting the return list. * @returns { DataSharePredicates } Returns the SQL query statement with the specified DataSharePredicates. @@ -366,6 +439,7 @@ declare namespace dataSharePredicates { /** * Restricts the ascending order of the return list. When there are several orders, * the one close to the head has the highest priority. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name for sorting the return list. * @returns { DataSharePredicates } Returns the SQL query statement with the specified DataSharePredicates. @@ -374,11 +448,25 @@ declare namespace dataSharePredicates { * @crossplatform * @since 12 */ + /** + * Restricts the ascending order of the return list. When there are several orders, + * the one close to the head has the highest priority. + * Currently only used for RDB and KVDB(schema). + * + * @param { string } field - Indicates the column name for sorting the return list. + * @returns { DataSharePredicates } Returns the SQL query statement with the specified DataSharePredicates. + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @StageModelOnly + * @crossplatform + * @atomicservice + * @since 20 + */ orderByAsc(field: string): DataSharePredicates; /** * Restricts the descending order of the return list. When there are several orders, * the one close to the head has the highest priority. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name for sorting the return list. * @returns { DataSharePredicates } Returns the SQL query statement with the specified DataSharePredicates. @@ -389,6 +477,7 @@ declare namespace dataSharePredicates { /** * Restricts the descending order of the return list. When there are several orders, * the one close to the head has the highest priority. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name for sorting the return list. * @returns { DataSharePredicates } Returns the SQL query statement with the specified DataSharePredicates. @@ -397,10 +486,24 @@ declare namespace dataSharePredicates { * @crossplatform * @since 12 */ + /** + * Restricts the descending order of the return list. When there are several orders, + * the one close to the head has the highest priority. + * Currently only used for RDB and KVDB(schema). + * + * @param { string } field - Indicates the column name for sorting the return list. + * @returns { DataSharePredicates } Returns the SQL query statement with the specified DataSharePredicates. + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @StageModelOnly + * @crossplatform + * @atomicservice + * @since 20 + */ orderByDesc(field: string): DataSharePredicates; /** * Restricts each row of the query result to be unique. + * Currently only used for RDB. * * @returns { DataSharePredicates } Returns the SQL query statement with the specified DataSharePredicates. * @syscap SystemCapability.DistributedDataManager.DataShare.Core @@ -412,6 +515,7 @@ declare namespace dataSharePredicates { /** * Construct a query object to specify the number of results and the starting position. + * Currently only used for RDB and KVDB(schema). * * @param { number } total - Represents the specified number of results. * @param { number } offset - Indicates the starting position. @@ -422,6 +526,7 @@ declare namespace dataSharePredicates { */ /** * Construct a query object to specify the number of results and the starting position. + * Currently only used for RDB and KVDB(schema). * * @param { number } total - Represents the specified number of results. * @param { number } offset - Indicates the starting position. @@ -431,10 +536,24 @@ declare namespace dataSharePredicates { * @crossplatform * @since 12 */ + /** + * Construct a query object to specify the number of results and the starting position. + * Currently only used for RDB and KVDB(schema). + * + * @param { number } total - Represents the specified number of results. + * @param { number } offset - Indicates the starting position. + * @returns { DataSharePredicates } Returns the query object. + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @StageModelOnly + * @crossplatform + * @atomicservice + * @since 20 + */ limit(total: number, offset: number): DataSharePredicates; /** * Configure {@code DataSharePredicates} to group query results by specified columns. + * Currently only used for RDB. * * @param { Array } fields - Indicates the specified columns by which query results are grouped. * @returns { DataSharePredicates } Returns the DataSharePredicates with the specified columns by which query results are grouped. @@ -448,6 +567,7 @@ declare namespace dataSharePredicates { /** * Configure {@code DataSharePredicates} to specify the index column. * Before using this method, you need to create an index column. + * Currently only used for RDB. * * @param { string } field - Indicates the name of the index column. * @returns { DataSharePredicates } Returns DataSharePredicates with the specified index column. @@ -461,6 +581,7 @@ declare namespace dataSharePredicates { /** * Configure {@code DataSharePredicates} to match the specified field whose data type is ValueType array and values * are within a given range. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @param { Array } value - Indicates the values to match with DataSharePredicates. @@ -472,6 +593,7 @@ declare namespace dataSharePredicates { /** * Configure {@code DataSharePredicates} to match the specified field whose data type is ValueType array and values * are within a given range. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @param { Array } value - Indicates the values to match with DataSharePredicates. @@ -481,11 +603,26 @@ declare namespace dataSharePredicates { * @crossplatform * @since 12 */ + /** + * Configure {@code DataSharePredicates} to match the specified field whose data type is ValueType array and values + * are within a given range. + * Currently only used for RDB and KVDB(schema). + * + * @param { string } field - Indicates the column name in the database table. + * @param { Array } value - Indicates the values to match with DataSharePredicates. + * @returns { DataSharePredicates } Returns DataSharePredicates that matches the specified field. + * @syscap SystemCapability.DistributedDataManager.DataShare.Core + * @StageModelOnly + * @crossplatform + * @atomicservice + * @since 20 + */ in(field: string, value: Array): DataSharePredicates; /** * Configure {@code DataSharePredicates} to match the specified field whose data type is String array and values * are out of a given range. + * Currently only used for RDB and KVDB(schema). * * @param { string } field - Indicates the column name in the database table. * @param { Array } value - Indicates the values to match with DataSharePredicates. @@ -499,6 +636,7 @@ declare namespace dataSharePredicates { /** * Configure {@code DataSharePredicates} Creates a query condition using the specified key prefix. + * Currently only used for KVDB. * * @param { string } prefix - Represents the specified key prefix. * @returns { DataSharePredicates } Returns the query object. @@ -511,6 +649,7 @@ declare namespace dataSharePredicates { /** * Configure {@code DataSharePredicates} to match the specified value whose key is within a given range. + * Currently only used for KVDB. * * @param { Array } keys - Represents the key names. * @returns { DataSharePredicates } Returns the query object. diff --git a/interface_sdk/api/@ohos.data.distributedDataObject.d.ts b/interface_sdk/api/@ohos.data.distributedDataObject.d.ts index 5960ab17..c4119afc 100644 --- a/interface_sdk/api/@ohos.data.distributedDataObject.d.ts +++ b/interface_sdk/api/@ohos.data.distributedDataObject.d.ts @@ -177,6 +177,31 @@ declare namespace distributedDataObject { sessionId: string; } + /** + * Indicates the observer of object data changed. + * + * @typedef { function } ChangeCallback + * @param { string } sessionId - The sessionId of the changed object. + * @param { Array } fields - Property names of changed data. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ + type DataObserver = (sessionId: string, fields: Array) => void; + + /** + * Indicates the observer of object status changed. + * + * @typedef { function } StatusObserver + * @param { string } sessionId - The sessionId of the changed object. + * @param { string } networkId - The networkId of the changed device. + * @param { string } status 'online' The object became online on the device and data can be synced to the device; + * 'offline' The object became offline on the device and the object can not sync any data; + * 'restored' The object restored success. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ + type StatusObserver = (sessionId: string, networkId: string, status: string) => void; + /** * Object create by {@link createDistributedObject}. * @@ -291,7 +316,7 @@ declare namespace distributedDataObject { * @param {AsyncCallback} callback - The callback of setSessionId. * @throws {BusinessError} 201 - Permission verification failed. * @throws {BusinessError} 401 - Parameter error. Incorrect parameter types. - * @throws {BusinessError} 15400001 - Create table failed. + * @throws {BusinessError} 15400001 - Failed to create the in-memory database. * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject * @since 9 */ @@ -304,7 +329,7 @@ declare namespace distributedDataObject { * @throws {BusinessError} 201 - Permission verification failed. * @throws {BusinessError} 401 - Parameter error. Possible causes: 1. Incorrect parameter types; * 2. The sessionId allows only letters, digits, and underscores(_), and cannot exceed 128 in length. - * @throws {BusinessError} 15400001 - Create table failed. + * @throws {BusinessError} 15400001 - Failed to create the in-memory database. * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject * @since 12 */ @@ -317,10 +342,19 @@ declare namespace distributedDataObject { * @param {AsyncCallback} callback - The callback of setSessionId. * @throws {BusinessError} 201 - Permission verification failed. * @throws {BusinessError} 401 - Parameter error. Incorrect parameter types. - * @throws {BusinessError} 15400001 - Create table failed. + * @throws {BusinessError} 15400001 - Failed to create the in-memory database. * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject * @since 9 */ + /** + * Leave all session. + * + * @param {AsyncCallback} callback - The callback of setSessionId. + * @throws {BusinessError} 401 - Parameter error. Incorrect parameter types. + * @throws {BusinessError} 15400001 - Failed to create the in-memory database. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ setSessionId(callback: AsyncCallback): void; /** @@ -331,7 +365,7 @@ declare namespace distributedDataObject { * @returns {Promise} - The promise returned by the function. * @throws {BusinessError} 201 - Permission verification failed. * @throws {BusinessError} 401 - Parameter error. Incorrect parameter types. - * @throws {BusinessError} 15400001 - Create table failed. + * @throws {BusinessError} 15400001 - Failed to create the in-memory database. * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject * @since 9 */ @@ -344,7 +378,7 @@ declare namespace distributedDataObject { * @throws {BusinessError} 201 - Permission verification failed. * @throws {BusinessError} 401 - Parameter error. Possible causes: 1. Incorrect parameter types; * 2. The sessionId allows only letters, digits, and underscores(_), and cannot exceed 128 in length. - * @throws {BusinessError} 15400001 - Create table failed. + * @throws {BusinessError} 15400001 - Failed to create the in-memory database. * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject * @since 12 */ @@ -520,6 +554,76 @@ declare namespace distributedDataObject { * @since 11 */ bindAssetStore(assetKey: string, bindInfo: BindInfo): Promise; + + /** + * On watch of change. + * + * @param { 'change' } type - Event type, fixed as 'change', indicates data change. + * @param { DataObserver } callback - The observer of object data changed. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ + on(type: 'change', callback: DataObserver): void; + + /** + * Off watch of change. + * + * @param { 'change' } type - Event type, fixed as 'change', indicates data change. + * @param { DataObserver } callback - The observer of object data changed, if not null, off the callback, if undefined, off all callbacks. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ + off(type: 'change', callback?: DataObserver): void; + + /** + * On watch of status. + * + * @param { 'status' } type - Event type, fixed as 'status', indicates the online and offline of the object. + * @param { StatusObserver } callback - The observer of object status changed. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ + on(type: 'status', callback: StatusObserver): void; + + /** + * Off watch of status. + * + * @param { 'status' } type - Event type, fixed as 'status', indicates the online and offline of the object. + * @param { StatusObserver } callback - The observer of object status changed, if not null, off the callback, if undefined, off all callbacks. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ + off(type: 'status', callback?: StatusObserver): void; + + /** + * Mark an attribute of a distributed object as an asset type. This interface must be called before setSessionId. + * + * @param { string } assetKey - Indicates the key of the asset type in Object. + * @param { string } uri - Indicates the uri of asset. + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 15400002 - Parameter error. Possible causes: + * 1. The assetKey is invalid, such as ""; + * 2. The uri is invalid, such as "". + * @throws {BusinessError} 15400003 - The sessionId of the distributed object has been set. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ + setAsset(assetKey: string, uri: string): Promise; + + /** + * Marks an attribute of a distributed object as an asset array type. This interface must be called before setSessionId. + * + * @param { string } assetsKey - Indicates the key of the asset type in Object. + * @param { Array } uris - Indicates the uri array of asset. + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 15400002 - Parameter error. Possible causes: + * 1. The assetKey is invalid, such as ""; + * 2. The uris is invalid, such as the length of uris is more than 50. + * @throws {BusinessError} 15400003 - The sessionId of the distributed object has been set. + * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject + * @since 20 + */ + setAssets(assetsKey: string, uris: Array): Promise; } } diff --git a/interface_sdk/api/@ohos.data.distributedKVStore.d.ts b/interface_sdk/api/@ohos.data.distributedKVStore.d.ts index 62b91341..7c1b0573 100644 --- a/interface_sdk/api/@ohos.data.distributedKVStore.d.ts +++ b/interface_sdk/api/@ohos.data.distributedKVStore.d.ts @@ -79,6 +79,7 @@ declare namespace distributedKVStore { * Max key length is 1024. * * @type { number } + * @readonly * @syscap SystemCapability.DistributedDataManager.KVStore.Core * @since 9 */ @@ -88,6 +89,7 @@ declare namespace distributedKVStore { * Max value length is 4194303. * * @type { number } + * @readonly * @syscap SystemCapability.DistributedDataManager.KVStore.Core * @since 9 */ @@ -97,6 +99,7 @@ declare namespace distributedKVStore { * Max device coordinate key length is 896. * * @type { number } + * @readonly * @syscap SystemCapability.DistributedDataManager.KVStore.Core * @since 9 */ @@ -106,6 +109,7 @@ declare namespace distributedKVStore { * Max store id length is 128. * * @type { number } + * @readonly * @syscap SystemCapability.DistributedDataManager.KVStore.Core * @since 9 */ @@ -115,6 +119,7 @@ declare namespace distributedKVStore { * Max query length is 512000. * * @type { number } + * @readonly * @syscap SystemCapability.DistributedDataManager.KVStore.Core * @since 9 */ @@ -124,6 +129,7 @@ declare namespace distributedKVStore { * Max batch operation size is 128. * * @type { number } + * @readonly * @syscap SystemCapability.DistributedDataManager.KVStore.Core * @since 9 */ @@ -580,7 +586,8 @@ declare namespace distributedKVStore { *

Add a child node to makes this node a non-leaf node and field value will be ignored if it has a child node. * * @param { FieldNode } child - The field node to append. - * @returns { boolean } Returns true if the child node is successfully added to this {@code FieldNode} and false otherwise. + * @returns { boolean } Returns true if the child node is successfully added to this {@code FieldNode} + * and false otherwise. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.KVStore.DistributedKVStore @@ -688,11 +695,11 @@ declare namespace distributedKVStore { /** * Moves the read position by a relative offset to the current position. * - * @param { number } offset - Indicates the relative offset to the current position. A negative offset indicates moving - * backwards, and a positive offset indicates moving forwards. For example, if the current position is entry 1 and - * this offset is 2, the destination position will be entry 3; if the current position is entry 3 and this offset is -2, - * the destination position will be entry 1. The valid final position after moving forwards starts with 0. If the - * final position is invalid, false will be returned. + * @param { number } offset - Indicates the relative offset to the current position. A negative offset indicates + * moving backwards, and a positive offset indicates moving forwards. For example, if the current position is entry + * 1 and this offset is 2, the destination position will be entry 3; if the current position is entry 3 and this + * offset is -2, the destination position will be entry 1. The valid final position after moving forwards starts + * with 0. If the final position is invalid, false will be returned. * @returns { boolean } Returns true if the operation succeeds; return false otherwise. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. @@ -787,7 +794,8 @@ declare namespace distributedKVStore { reset(): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is equal to the specified long value. + * Constructs a {@code Query} object to query entries with the specified field whose value is equal to the + * specified long value. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { number | string | boolean } value - Indicates the value to be compared. @@ -801,7 +809,8 @@ declare namespace distributedKVStore { equalTo(field: string, value: number | string | boolean): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is not equal to the specified int value. + * Constructs a {@code Query} object to query entries with the specified field whose value is not equal to the + * specified int value. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { number | string | boolean } value - Indicates the value to be compared. @@ -815,8 +824,8 @@ declare namespace distributedKVStore { notEqualTo(field: string, value: number | string | boolean): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is greater than or equal to the - * specified int value. + * Constructs a {@code Query} object to query entries with the specified field whose value is greater than or + * equal to the specified int value. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { number | string | boolean } value - Indicates the value to be compared. @@ -830,7 +839,8 @@ declare namespace distributedKVStore { greaterThan(field: string, value: number | string | boolean): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is less than the specified int value. + * Constructs a {@code Query} object to query entries with the specified field whose value is less than the + * specified int value. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { number | string } value - Indicates the value to be compared. @@ -859,8 +869,8 @@ declare namespace distributedKVStore { greaterThanOrEqualTo(field: string, value: number | string): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is less than or equal to the - * specified int value. + * Constructs a {@code Query} object to query entries with the specified field whose value is less than or + * equal to the specified int value. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { number | string } value - Indicates the value to be compared. @@ -887,7 +897,8 @@ declare namespace distributedKVStore { isNull(field: string): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is within the specified int value list. + * Constructs a {@code Query} object to query entries with the specified field whose value is within the specified + * int value list. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { number[] } valueList - Indicates the int value list. @@ -901,7 +912,8 @@ declare namespace distributedKVStore { inNumber(field: string, valueList: number[]): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is within the specified string value list. + * Constructs a {@code Query} object to query entries with the specified field whose value is within the specified + * string value list. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { string[] } valueList - Indicates the string value list. @@ -915,7 +927,8 @@ declare namespace distributedKVStore { inString(field: string, valueList: string[]): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is not within the specified int value list. + * Constructs a {@code Query} object to query entries with the specified field whose value is not within the + * specified int value list. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { number[] } valueList - Indicates the int value list. @@ -929,7 +942,8 @@ declare namespace distributedKVStore { notInNumber(field: string, valueList: number[]): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is not within the specified string value list. + * Constructs a {@code Query} object to query entries with the specified field whose value is not within the + * specified string value list. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { string[] } valueList - Indicates the string value list. @@ -943,7 +957,8 @@ declare namespace distributedKVStore { notInString(field: string, valueList: string[]): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is similar to the specified string value. + * Constructs a {@code Query} object to query entries with the specified field whose value is similar to the + * specified string value. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { string } value - Indicates the string value. @@ -957,7 +972,8 @@ declare namespace distributedKVStore { like(field: string, value: string): Query; /** - * Constructs a {@code Query} object to query entries with the specified field whose value is not similar to the specified string value. + * Constructs a {@code Query} object to query entries with the specified field whose value is not similar to the + * specified string value. * * @param { string } field - Indicates the field, which cannot contain ^. * @param { string } value - Indicates the string value. @@ -1019,8 +1035,12 @@ declare namespace distributedKVStore { /** * Constructs a {@code Query} object to specify the number of results and the start position. * - * @param { number } total - Indicates the number of results. - * @param { number } offset - Indicates the start position. + * @param { number } total - Maximum number of results to query. The value must be a non-negative integer. + * If the input value is less than 0, the number of results is not limited. + * @param { number } offset - Start position of the query result. By default, + * the start position is the beginning of the result set. If **offset** is a negative number, + * the start position is the beginning of the result set. If **offset** exceeds the end of the result set, + * the query result is empty. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. @@ -1043,8 +1063,8 @@ declare namespace distributedKVStore { /** * Creates a query condition group with a left bracket. - *

Multiple query conditions in an {@code Query} object can be grouped. The query conditions in a group can be used as a - * whole to combine with other query conditions. + *

Multiple query conditions in an {@code Query} object can be grouped. The query conditions in a group can + * beused as a whole to combine with other query conditions. * * @returns { Query } Returns the {@coed Query} object. * @syscap SystemCapability.DistributedDataManager.KVStore.Core @@ -1054,8 +1074,8 @@ declare namespace distributedKVStore { /** * Creates a query condition group with a right bracket. - *

Multiple query conditions in an {@code Query} object can be grouped. The query conditions in a group can be used as a - * whole to combine with other query conditions. + *

Multiple query conditions in an {@code Query} object can be grouped. The query conditions in a group can + * be used as a whole to combine with other query conditions. * * @returns { Query } Returns the {@coed Query} object. * @syscap SystemCapability.DistributedDataManager.KVStore.Core @@ -1128,7 +1148,8 @@ declare namespace distributedKVStore { interface SingleKVStore { /** * Writes a key-value pair of the string type into the {@code SingleKVStore} database. - *

If you do not want to synchronize this key-value pair to other devices, set the write option in the local database. + *

If you do not want to synchronize this key-value pair to other devices, set the write option in the local + * database. * * @param { string } key - Indicates the key. Length must be less than {@code MAX_KEY_LENGTH}. * Spaces before and after the key will be cleared. @@ -1144,7 +1165,8 @@ declare namespace distributedKVStore { */ /** * Writes a key-value pair of the string type into the {@code SingleKVStore} database. - *

If you do not want to synchronize this key-value pair to other devices, set the write option in the local database. + *

If you do not want to synchronize this key-value pair to other devices, set the write option in the local + * database. * * @param { string } key - Indicates the key. Length must be less than {@code MAX_KEY_LENGTH}. * Spaces before and after the key will be cleared. @@ -1163,7 +1185,8 @@ declare namespace distributedKVStore { /** * Writes a key-value pair of the string type into the {@code SingleKVStore} database. - *

If you do not want to synchronize this key-value pair to other devices, set the write option in the local database. + *

If you do not want to synchronize this key-value pair to other devices, set the write option in the local + * database. * * @param { string } key - Indicates the key. Length must be less than {@code MAX_KEY_LENGTH}. * Spaces before and after the key will be cleared. @@ -1179,7 +1202,8 @@ declare namespace distributedKVStore { */ /** * Writes a key-value pair of the string type into the {@code SingleKVStore} database. - *

If you do not want to synchronize this key-value pair to other devices, set the write option in the local database. + *

If you do not want to synchronize this key-value pair to other devices, set the write option in the local + * database. * * @param { string } key - Indicates the key. Length must be less than {@code MAX_KEY_LENGTH}. * Spaces before and after the key will be cleared. @@ -1257,7 +1281,8 @@ declare namespace distributedKVStore { * @param { AsyncCallback } callback - the callback of putBatch. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.KVStore.Core @@ -1272,7 +1297,8 @@ declare namespace distributedKVStore { * @param { AsyncCallback } callback - the callback of putBatch. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. @@ -1290,7 +1316,8 @@ declare namespace distributedKVStore { * @returns { Promise } the promise returned by the function. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.KVStore.Core @@ -1305,7 +1332,8 @@ declare namespace distributedKVStore { * @returns { Promise } the promise returned by the function. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. @@ -1385,7 +1413,8 @@ declare namespace distributedKVStore { * @param { AsyncCallback } callback - the callback of delete. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.DataShare.Provider @@ -1400,7 +1429,8 @@ declare namespace distributedKVStore { * @param { AsyncCallback } callback - the callback of delete. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. @@ -1418,7 +1448,8 @@ declare namespace distributedKVStore { * @returns { Promise } the promise returned by the function. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.DataShare.Provider @@ -1433,7 +1464,8 @@ declare namespace distributedKVStore { * @returns { Promise } the promise returned by the function. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. @@ -1507,7 +1539,8 @@ declare namespace distributedKVStore { * synchronized from remote devices. This operation does not synchronize data to other databases or affect * subsequent data synchronization. * - * @param { string } deviceId - Identifies the device whose data is to be removed and the value cannot be the current device ID. + * @param { string } deviceId - Identifies the device whose data is to be removed and the value cannot be the + * current device ID. * @param { AsyncCallback } callback - the callback of removeDeviceData. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Parameter verification failed. @@ -1522,7 +1555,8 @@ declare namespace distributedKVStore { * synchronized from remote devices. This operation does not synchronize data to other databases or affect * subsequent data synchronization. * - * @param { string } deviceId - Identifies the device whose data is to be removed and the value cannot be the current device ID. + * @param { string } deviceId - Identifies the device whose data is to be removed and the value cannot be the + * current device ID. * @returns { Promise } the promise returned by the function. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Parameter verification failed. @@ -1627,7 +1661,8 @@ declare namespace distributedKVStore { getEntries(query: Query): Promise; /** - * Obtains the result set with a specified prefix from a {@code SingleKVStore} database. The {@code KVStoreResultSet} + * Obtains the result set with a specified prefix from a {@code SingleKVStore} database. + * The {@code KVStoreResultSet} * object can be used to query all key-value pairs that meet the search criteria. Each {@code SingleKVStore} * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created * four objects, calling this method will return a failure. Therefore, you are advised to call the closeResultSet @@ -1644,7 +1679,8 @@ declare namespace distributedKVStore { * @since 9 */ /** - * Obtains the result set with a specified prefix from a {@code SingleKVStore} database. The {@code KVStoreResultSet} + * Obtains the result set with a specified prefix from a {@code SingleKVStore} database. + * The {@code KVStoreResultSet} * object can be used to query all key-value pairs that meet the search criteria. Each {@code SingleKVStore} * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created * four objects, calling this method will return a failure. Therefore, you are advised to call the closeResultSet @@ -1664,7 +1700,8 @@ declare namespace distributedKVStore { getResultSet(keyPrefix: string, callback: AsyncCallback): void; /** - * Obtains the result set with a specified prefix from a {@code SingleKVStore} database. The {@code KVStoreResultSet} + * Obtains the result set with a specified prefix from a {@code SingleKVStore} database. + * The {@code KVStoreResultSet} * object can be used to query all key-value pairs that meet the search criteria. Each {@code SingleKVStore} * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created * four objects, calling this method will return a failure. Therefore, you are advised to call the closeResultSet @@ -1681,7 +1718,8 @@ declare namespace distributedKVStore { * @since 9 */ /** - * Obtains the result set with a specified prefix from a {@code SingleKVStore} database. The {@code KVStoreResultSet} + * Obtains the result set with a specified prefix from a {@code SingleKVStore} database. + * The {@code KVStoreResultSet} * object can be used to query all key-value pairs that meet the search criteria. Each {@code SingleKVStore} * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created * four objects, calling this method will return a failure. Therefore, you are advised to call the closeResultSet @@ -1766,7 +1804,8 @@ declare namespace distributedKVStore { * object matching the specified {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.DataShare.Provider @@ -1782,7 +1821,8 @@ declare namespace distributedKVStore { * object matching the specified {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100001 - Over max limits. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. @@ -1801,7 +1841,8 @@ declare namespace distributedKVStore { * object matching the specified {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.DataShare.Provider @@ -1817,7 +1858,8 @@ declare namespace distributedKVStore { * object matching the specified {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100001 - Over max limits. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. @@ -2202,7 +2244,8 @@ declare namespace distributedKVStore { * Register a databases synchronization callback to the database. *

Sync result is returned through asynchronous callback. * - * @param { 'syncComplete' } event - Subscribed event name, fixed as 'syncComplete', indicates the synchronization completion event. + * @param { 'syncComplete' } event - Subscribed event name, fixed as 'syncComplete', indicates the synchronization + * completion event. * @param { Callback> } syncCallback - {Array<[string, number]>}: the * deviceId and it's corresponding synchronization result which 0 means synchronization success * and otherwise failed. @@ -2216,7 +2259,8 @@ declare namespace distributedKVStore { /** * Unsubscribe from the SingleKVStore database based on the specified subscribeType and listener. * - * @param { 'dataChange' } event - The unsubscribe event name, fixed as 'dataChange', indicates the data change event. + * @param { 'dataChange' } event - The unsubscribe event name, fixed as 'dataChange', indicates the data change + * event. * @param { Callback } listener - {ChangeNotification}: the {@code ChangeNotification} * object indicates the data change events in the distributed database. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; @@ -2230,7 +2274,8 @@ declare namespace distributedKVStore { /** * Unregister the database synchronization callback. * - * @param { 'syncComplete' } event - The unsubscribe event name, fixed as 'syncComplete', indicates the synchronization completion event. + * @param { 'syncComplete' } event - The unsubscribe event name, fixed as 'syncComplete', indicates the + * synchronization completion event. * @param { Callback> } syncCallback - {Array<[string, number]>}: the * deviceId and it's corresponding synchronization result which 0 means synchronization success * and otherwise failed. @@ -2266,12 +2311,16 @@ declare namespace distributedKVStore { /** * Provides methods related to device-collaboration distributed databases. - *

To create a {@code DeviceKVStore} database, you can use the {@link data.distributed.common.KVManager.getKVStore(Options, String)} - * method with {@code KVStoreType} set to {@code DEVICE_COLLABORATION} for the input parameter Options. This database manages distributed - * data by device, and cannot modify data synchronized from remote devices. When an application writes a key-value pair entry + *

To create a {@code DeviceKVStore} database, you can use the + * {@link data.distributed.common.KVManager.getKVStore(Options, String)} + * method with {@code KVStoreType} set to {@code DEVICE_COLLABORATION} for the input parameter Options. + * This database manages distributed + * data by device, and cannot modify data synchronized from remote devices. When an application writes a + * key-value pair entry * into the database, the system automatically adds the ID of the device running the application to the key. * - * @interface DeviceKVStore + * @extends SingleKVStore + * @typedef DeviceKVStore * @syscap SystemCapability.DistributedDataManager.KVStore.DistributedKVStore * @since 9 */ @@ -2314,7 +2363,8 @@ declare namespace distributedKVStore { * Obtains the value matching a specified device ID and key. * * @param { string } deviceId - Indicates the device to be queried. - * @param { string } key - Indicates the key of the value to be queried. The length must be less than {@code MAX_KEY_LENGTH}. + * @param { string } key - Indicates the key of the value to be queried. The length must be less than + * {@code MAX_KEY_LENGTH}. * @param { AsyncCallback } callback - * {boolean | string | number | Uint8Array}: the returned value specified by the deviceId and key. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; @@ -2332,7 +2382,8 @@ declare namespace distributedKVStore { * Obtains the value matching a specified device ID and key. * * @param { string } deviceId - Indicates the device to be queried. - * @param { string } key - Indicates the key of the value to be queried. The length must be less than {@code MAX_KEY_LENGTH}. + * @param { string } key - Indicates the key of the value to be queried. The length must be less than + * {@code MAX_KEY_LENGTH}. * @returns { Promise } * {Uint8Array|string|boolean|number}: the returned value specified by the deviceId and key. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; @@ -2473,7 +2524,8 @@ declare namespace distributedKVStore { /** * Obtains the result set with the local device ID and specified prefix from a {@code DeviceKVStore} database. * The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. - * Each {@code DeviceKVStore} instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. + * Each {@code DeviceKVStore} instance can have a maximum of four {@code KVStoreResultSet} objects at the + * same time. * If you have created four objects, calling this method will return a failure. Therefore, you are advised to * call the closeResultSet method to close unnecessary {@code KVStoreResultSet} objects in a timely manner. * @@ -2490,7 +2542,8 @@ declare namespace distributedKVStore { /** * Obtains the result set with the local device ID and specified prefix from a {@code DeviceKVStore} database. * The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. - * Each {@code DeviceKVStore} instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. + * Each {@code DeviceKVStore} instance can have a maximum of four {@code KVStoreResultSet} objects at the + * same time. * If you have created four objects, calling this method will return a failure. Therefore, you are advised to * call the closeResultSet method to close unnecessary {@code KVStoreResultSet} objects in a timely manner. * @@ -2510,7 +2563,8 @@ declare namespace distributedKVStore { /** * Obtains the result set with the local device ID and specified prefix from a {@code DeviceKVStore} database. * The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. - * Each {@code DeviceKVStore} instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. + * Each {@code DeviceKVStore} instance can have a maximum of four {@code KVStoreResultSet} objects at the + * same time. * If you have created four objects, calling this method will return a failure. Therefore, you are advised to * call the closeResultSet method to close unnecessary {@code KVStoreResultSet} objects in a timely manner. * @@ -2527,7 +2581,8 @@ declare namespace distributedKVStore { /** * Obtains the result set with the local device ID and specified prefix from a {@code DeviceKVStore} database. * The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. - * Each {@code DeviceKVStore} instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. + * Each {@code DeviceKVStore} instance can have a maximum of four {@code KVStoreResultSet} objects at the + * same time. * If you have created four objects, calling this method will return a failure. Therefore, you are advised to * call the closeResultSet method to close unnecessary {@code KVStoreResultSet} objects in a timely manner. * @@ -2546,9 +2601,12 @@ declare namespace distributedKVStore { /** * Obtains the {@code KVStoreResultSet} object matching the specified device ID and key prefix. - *

The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. Each {@code DeviceKVStore} - * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created four objects, - * calling this method will return a failure. Therefore, you are advised to call the closeResultSet method to close unnecessary + *

The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. + * Each {@code DeviceKVStore} + * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created four + * objects, + * calling this method will return a failure. Therefore, you are advised to call the closeResultSet method to close + * unnecessary * {@code KVStoreResultSet} objects in a timely manner. * * @param { string } deviceId - Identifies the device whose data is to be queried. @@ -2564,9 +2622,12 @@ declare namespace distributedKVStore { */ /** * Obtains the {@code KVStoreResultSet} object matching the specified device ID and key prefix. - *

The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. Each {@code DeviceKVStore} - * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created four objects, - * calling this method will return a failure. Therefore, you are advised to call the closeResultSet method to close unnecessary + *

The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. + * Each {@code DeviceKVStore} + * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created four + * objects, + * calling this method will return a failure. Therefore, you are advised to call the closeResultSet method to close + * unnecessary * {@code KVStoreResultSet} objects in a timely manner. * * @param { string } deviceId - Identifies the device whose data is to be queried. @@ -2585,9 +2646,12 @@ declare namespace distributedKVStore { /** * Obtains the {@code KVStoreResultSet} object matching the specified device ID and key prefix. - *

The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. Each {@code DeviceKVStore} - * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created four objects, - * calling this method will return a failure. Therefore, you are advised to call the closeResultSet method to close unnecessary + *

The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. + * Each {@code DeviceKVStore} + * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created four + * objects, + * calling this method will return a failure. Therefore, you are advised to call the closeResultSet method to close + * unnecessary * {@code KVStoreResultSet} objects in a timely manner. * * @param { string } deviceId - Identifies the device whose data is to be queried. @@ -2603,9 +2667,12 @@ declare namespace distributedKVStore { */ /** * Obtains the {@code KVStoreResultSet} object matching the specified device ID and key prefix. - *

The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. Each {@code DeviceKVStore} - * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created four objects, - * calling this method will return a failure. Therefore, you are advised to call the closeResultSet method to close unnecessary + *

The {@code KVStoreResultSet} object can be used to query all key-value pairs that meet the search criteria. + * Each {@code DeviceKVStore} + * instance can have a maximum of four {@code KVStoreResultSet} objects at the same time. If you have created four + * objects, + * calling this method will return a failure. Therefore, you are advised to call the closeResultSet method to close + * unnecessary * {@code KVStoreResultSet} objects in a timely manner. * * @param { string } deviceId - Identifies the device whose data is to be queried. @@ -2683,7 +2750,8 @@ declare namespace distributedKVStore { /** * Obtains the {@code KVStoreResultSet} object matching a specified device ID and {@code Query} object. * - * @param { string } deviceId - Indicates the ID of the device to which the {@code KVStoreResultSet} object belongs. + * @param { string } deviceId - Indicates the ID of the device to which the {@code KVStoreResultSet} object + * belongs. * @param { Query } query - Indicates the {@code Query} object. * @param { AsyncCallback } callback - {KVStoreResultSet}: the {@code KVStoreResultSet} * object matching the specified deviceId and {@code Query} object. @@ -2697,7 +2765,8 @@ declare namespace distributedKVStore { /** * Obtains the {@code KVStoreResultSet} object matching a specified device ID and {@code Query} object. * - * @param { string } deviceId - Indicates the ID of the device to which the {@code KVStoreResultSet} object belongs. + * @param { string } deviceId - Indicates the ID of the device to which the {@code KVStoreResultSet} object + * belongs. * @param { Query } query - Indicates the {@code Query} object. * @param { AsyncCallback } callback - {KVStoreResultSet}: the {@code KVStoreResultSet} * object matching the specified deviceId and {@code Query} object. @@ -2714,7 +2783,8 @@ declare namespace distributedKVStore { /** * Obtains the {@code KVStoreResultSet} object matching a specified device ID and {@code Query} object. * - * @param { string } deviceId - Indicates the ID of the device to which the {@code KVStoreResultSet} object belongs. + * @param { string } deviceId - Indicates the ID of the device to which the {@code KVStoreResultSet} object + * belongs. * @param { Query } query - Indicates the {@code Query} object. * @returns { Promise } {KVStoreResultSet}: the {@code KVStoreResultSet} * object matching the specified deviceId and {@code Query} object. @@ -2728,7 +2798,8 @@ declare namespace distributedKVStore { /** * Obtains the {@code KVStoreResultSet} object matching a specified device ID and {@code Query} object. * - * @param { string } deviceId - Indicates the ID of the device to which the {@code KVStoreResultSet} object belongs. + * @param { string } deviceId - Indicates the ID of the device to which the {@code KVStoreResultSet} object + * belongs. * @param { Query } query - Indicates the {@code Query} object. * @returns { Promise } {KVStoreResultSet}: the {@code KVStoreResultSet} * object matching the specified deviceId and {@code Query} object. @@ -2750,7 +2821,8 @@ declare namespace distributedKVStore { * object matching the local device ID and specified {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.DataShare.Provider @@ -2766,7 +2838,8 @@ declare namespace distributedKVStore { * object matching the local device ID and specified {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100001 - Over max limits. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. @@ -2785,7 +2858,8 @@ declare namespace distributedKVStore { * object matching the local device ID and specified {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.DataShare.Provider @@ -2801,7 +2875,8 @@ declare namespace distributedKVStore { * object matching the local device ID and specified {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100001 - Over max limits. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. @@ -2821,7 +2896,8 @@ declare namespace distributedKVStore { * object matching the specified deviceId and {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.DataShare.Provider @@ -2838,7 +2914,8 @@ declare namespace distributedKVStore { * object matching the specified deviceId and {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100001 - Over max limits. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. @@ -2862,7 +2939,8 @@ declare namespace distributedKVStore { * object matching the specified deviceId and {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. * @syscap SystemCapability.DistributedDataManager.DataShare.Provider @@ -2879,7 +2957,8 @@ declare namespace distributedKVStore { * object matching the specified deviceId and {@code dataSharePredicates.DataSharePredicates} object. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 15100001 - Over max limits. * @throws { BusinessError } 15100003 - Database corrupted. * @throws { BusinessError } 15100005 - Database or result set already closed. @@ -2970,7 +3049,8 @@ declare namespace distributedKVStore { function createKVManager(config: KVManagerConfig): KVManager; /** - * Provides interfaces to manage a {@code SingleKVStore} database, including obtaining, closing, and deleting the {@code SingleKVStore}. + * Provides interfaces to manage a {@code SingleKVStore} database, including obtaining, closing, and deleting the + * {@code SingleKVStore}. * * @interface KVManager * @syscap SystemCapability.DistributedDataManager.KVStore.Core @@ -2981,7 +3061,7 @@ declare namespace distributedKVStore { * Creates and obtains a KVStore database by specifying {@code Options} and {@code storeId}. * * @param { string } storeId - Identifies the KVStore database. The value of this parameter must be unique - * for the same application, and different applications can share the same value. The storeId can consist + * for the same application, and different applications can share the same value. The storeId can consist * of only letters, digits, and underscores (_), and cannot exceed 128 characters. * @param { Options } options - Indicates the {@code Options} object used for creating and * obtaining the KVStore database. @@ -3000,7 +3080,7 @@ declare namespace distributedKVStore { * Creates and obtains a KVStore database by specifying {@code Options} and {@code storeId}. * * @param { string } storeId - Identifies the KVStore database. The value of this parameter must be unique - * for the same application, and different applications can share the same value. The storeId can consist + * for the same application, and different applications can share the same value. The storeId can consist * of only letters, digits, and underscores (_), and cannot exceed 128 characters. * @param { Options } options - Indicates the {@code Options} object used for creating and * obtaining the KVStore database. @@ -3017,15 +3097,16 @@ declare namespace distributedKVStore { /** * Closes the KVStore database. - *

Warning: This method is not thread-safe. If you call this method to stop a KVStore database that is running, your - * thread may crash. - *

The KVStore database to close must be an object created by using the {@code getKVStore} method. Before using this - * method, release the resources created for the database, for example, {@code KVStoreResultSet} for KVStore, otherwise - * closing the database will fail. - * - * @param { string } appId - Identifies the application that the database belong to, and cannot exceed 256 characters. - * @param { string } storeId - Identifies the KVStore database to close. The storeId can consist of only letters, digits, - * and underscores (_), and cannot exceed 128 characters. + *

Warning: This method is not thread-safe. If you call this method to stop a KVStore database that is running, + * your thread may crash. + *

The KVStore database to close must be an object created by using the {@code getKVStore} method. Before using + * this method, release the resources created for the database, for example, {@code KVStoreResultSet} for KVStore, + * otherwise closing the database will fail. + * + * @param { string } appId - Identifies the application that the database belong to, and cannot exceed 256 + * characters. + * @param { string } storeId - Identifies the KVStore database to close. The storeId can consist of only letters, + * digits, and underscores (_), and cannot exceed 128 characters. * @param { AsyncCallback } callback - the callback of closeKVStore. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Parameter verification failed. @@ -3036,15 +3117,16 @@ declare namespace distributedKVStore { /** * Closes the KVStore database. - *

Warning: This method is not thread-safe. If you call this method to stop a KVStore database that is running, your - * thread may crash. - *

The KVStore database to close must be an object created by using the {@code getKVStore} method. Before using this - * method, release the resources created for the database, for example, {@code KVStoreResultSet} for KVStore, otherwise - * closing the database will fail. - * - * @param { string } appId - Identifies the application that the database belong to, and cannot exceed 256 characters. - * @param { string } storeId - Identifies the KVStore database to close. The storeId can consist of only letters, digits, - * and underscores (_), and cannot exceed 128 characters. + *

Warning: This method is not thread-safe. If you call this method to stop a KVStore database that is running, + * your thread may crash. + *

The KVStore database to close must be an object created by using the {@code getKVStore} method. Before using + * this method, release the resources created for the database, for example, {@code KVStoreResultSet} for KVStore, + * otherwise closing the database will fail. + * + * @param { string } appId - Identifies the application that the database belong to, and cannot exceed 256 + * characters. + * @param { string } storeId - Identifies the KVStore database to close. The storeId can consist of only letters, + * digits, and underscores (_), and cannot exceed 128 characters. * @returns { Promise } the promise returned by the function. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Parameter verification failed. @@ -3056,12 +3138,13 @@ declare namespace distributedKVStore { /** * Deletes the KVStore database identified by storeId. *

Before using this method, close all KVStore instances in use that are identified by the same storeId. - *

You can use this method to delete a KVStore database not in use. After the database is deleted, all its data will be - * lost. + *

You can use this method to delete a KVStore database not in use. After the database is deleted, all its data + * will be lost. * - * @param { string } appId - Identifies the application that the database belong to, and cannot exceed 256 characters. - * @param { string } storeId - Identifies the KVStore database to delete. The storeId can consist of only letters, digits, - * and underscores (_), and cannot exceed 128 characters. + * @param { string } appId - Identifies the application that the database belong to, and cannot exceed 256 + * characters. + * @param { string } storeId - Identifies the KVStore database to delete. The storeId can consist of only letters, + * digits, and underscores (_), and cannot exceed 128 characters. * @param { AsyncCallback } callback - the callback of deleteKVStore. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Parameter verification failed. @@ -3074,12 +3157,13 @@ declare namespace distributedKVStore { /** * Deletes the KVStore database identified by storeId. *

Before using this method, close all KVStore instances in use that are identified by the same storeId. - *

You can use this method to delete a KVStore database not in use. After the database is deleted, all its data will be - * lost. + *

You can use this method to delete a KVStore database not in use. After the database is deleted, all its data + * will be lost. * - * @param { string } appId - Identifies the application that the database belong to, and cannot exceed 256 characters. - * @param { string } storeId - Identifies the KVStore database to delete. The storeId can consist of only letters, digits, - * and underscores (_), and cannot exceed 128 characters. + * @param { string } appId - Identifies the application that the database belong to, and cannot exceed 256 + * characters. + * @param { string } storeId - Identifies the KVStore database to delete. The storeId can consist of only letters, + * digits, and underscores (_), and cannot exceed 128 characters. * @returns { Promise } the promise returned by the function. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Parameter verification failed. @@ -3090,10 +3174,11 @@ declare namespace distributedKVStore { deleteKVStore(appId: string, storeId: string): Promise; /** - * Obtains the storeId of all KVStore databases that are created by using the {@code getKVStore} method and not deleted by - * calling the {@code deleteKVStore} method. + * Obtains the storeId of all KVStore databases that are created by using the {@code getKVStore} method and not + * deleted by calling the {@code deleteKVStore} method. * - * @param { string } appId - Identifies the application that obtains the databases, and cannot exceed 256 characters. + * @param { string } appId - Identifies the application that obtains the databases, and cannot exceed 256 + * characters. * @param { AsyncCallback } callback - {string[]}: the storeId of all created KVStore databases. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Parameter verification failed. @@ -3103,12 +3188,13 @@ declare namespace distributedKVStore { getAllKVStoreId(appId: string, callback: AsyncCallback): void; /** - * Obtains the storeId of all KVStore databases that are created by using the {@code getKVStore} method and not deleted by - * calling the {@code deleteKVStore} method. + * Obtains the storeId of all KVStore databases that are created by using the {@code getKVStore} method and not + * deleted by calling the {@code deleteKVStore} method. * - * @param { string } appId - Identifies the application that obtains the databases, and cannot exceed 256 characters. + * @param { string } appId - Identifies the application that obtains the databases, and cannot exceed 256 + * characters. * @returns { Promise } {string[]}: the storeId of all created KVStore databases. - * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified. + * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.KVStore.Core * @since 9 @@ -3117,10 +3203,11 @@ declare namespace distributedKVStore { /** * Register a death callback to get notification when the data manager service is terminated. - *

If the data manager service is terminated,you need to re-subscribe to data change notifications and synchronization - * completion notifications, and calling the sync method will return a failure. + *

If the data manager service is terminated,you need to re-subscribe to data change notifications and + * synchronization completion notifications, and calling the sync method will return a failure. * - * @param { 'distributedDataServiceDie' } event - Subscribed event name, fixed as 'distributedDataServiceDie', as a service status change events. + * @param { 'distributedDataServiceDie' } event - Subscribed event name, fixed as 'distributedDataServiceDie', + * as a service status change events. * @param { Callback } deathCallback - callback to be invoked when the data manager service is terminated. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types; @@ -3132,11 +3219,13 @@ declare namespace distributedKVStore { /** * Unregister the death callback. Not notification will be received when the data manager service is terminated. - *

The unregistered death callback must be a registered death callback of the database. If no death callback parameter - * is passed, all database death callbacks will be unregistered. + *

The unregistered death callback must be a registered death callback of the database. If no death callback + * parameter is passed, all database death callbacks will be unregistered. * - * @param { 'distributedDataServiceDie' } event - Unsubscribe event name, fixed as 'distributedDataServiceDie', as a service status change events. - * @param { Callback } deathCallback - the data manager service is terminated callback which has been registered. + * @param { 'distributedDataServiceDie' } event - Unsubscribe event name, fixed as 'distributedDataServiceDie', + * as a service status change events. + * @param { Callback } deathCallback - the data manager service is terminated callback which has been + * registered. * @throws { BusinessError } 401 - Parameter error.Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types; *
3.Parameter verification failed. diff --git a/interface_sdk/api/@ohos.data.graphStore.d.ts b/interface_sdk/api/@ohos.data.graphStore.d.ts new file mode 100644 index 00000000..0f904d61 --- /dev/null +++ b/interface_sdk/api/@ohos.data.graphStore.d.ts @@ -0,0 +1,551 @@ +/* + * 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. + */ + +/** + * @file + * @kit ArkData + */ + +import Context from './application/BaseContext'; + +/** + * Provides methods for graphStore create and delete. + * + * @namespace graphStore + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ +declare namespace graphStore { + /** + * Indicates possible value types + * + * @typedef { null | number | string } ValueType + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + type ValueType = null | number | string; + + /** + * Describes the security level. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + enum SecurityLevel { + /** + * S1: means the db is low level security + * There are some low impact, when the data is leaked. + * + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + S1 = 1, + /** + * S2: means the db is middle level security + * There are some major impact, when the data is leaked. + * + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + S2 = 2, + /** + * S3: means the db is high level security + * There are some severity impact, when the data is leaked. + * + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + S3 = 3, + /** + * S4: means the db is critical level security + * There are some critical impact, when the data is leaked. + * + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + S4 = 4 + } + + /** + * Manages graph database configurations. + * + * @interface storeConfig + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + interface StoreConfig { + /** + * The database name. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + name: string; + /** + * Specifies the security level of the database. + * + * @type { SecurityLevel } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + securityLevel: SecurityLevel; + /** + * Specifies whether the database is encrypted. + * + * @type { ?boolean } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + encrypt?: boolean; + } + + /** + * Defines Vertex Type. + * + * @interface Vertex + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + interface Vertex { + /** + * The Vertex element identifier. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + vid: string; + /** + * Labels of the vertex. + * + * @type { Array } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + labels: Array; + /** + * Properties of the vertex. + * + * @type { Record } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + properties: Record; + } + + /** + * Defines Edge Type. + * + * @interface Edge + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + interface Edge { + /** + * The Edge element identifier. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + eid: string; + /** + * Type of the edge. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + type: string; + /** + * The Start Vertex element identifier. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + startVid: string; + /** + * The End Vertex element identifier. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + endVid: string; + /** + * Properties of the edge. + * + * @type { Record } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + properties: Record; + } + + /** + * Defines PathSegment Type. + * + * @interface PathSegment + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + interface PathSegment { + /** + * Start vertex. + * + * @type { Vertex } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + start: Vertex; + /** + * End vertex. + * + * @type { Vertex } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + end: Vertex; + /** + * The edge between start vertex and end vertex. + * + * @type { Edge } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + edge: Edge; + } + + /** + * Defines Path Type. + * + * @interface Path + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + interface Path { + /** + * Start vertex. + * + * @type { Vertex } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + start: Vertex; + /** + * End vertex. + * + * @type { Vertex } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + end: Vertex; + /** + * Length of segments. + * + * @type { number } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + length: number; + /** + * Segments in the path. + * + * @type { Array } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + segments: Array; + } + + /** + * The GQL statement execution result. + * + * @interface Result + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + interface Result { + /** + * The data records of querying the database. + * + * @type { ?Array> } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + records?: Array>; + } + + /** + * Provides transactional methods for managing the graph database. + * + * @interface Transaction + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + interface Transaction { + /** + * Execute a query procedure. + * + * @param { string } gql - Indicates the GQL statement to execute. + * @returns { Promise } The {@link Result} object if the operation is successful. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300001 - Database corrupted. + * @throws { BusinessError } 31300002 - Already closed. + * @throws { BusinessError } 31300003 - The database is busy. + * @throws { BusinessError } 31300004 - The database is out of memory. + * @throws { BusinessError } 31300005 - The database is full. + * @throws { BusinessError } 31300006 - A duplicate graph name, vertex or edge type, or vertex or edge property name exists. + * @throws { BusinessError } 31300007 - The graph name, vertex or edge type, or vertex or edge property is not defined. + * @throws { BusinessError } 31300008 - The graph name, vertex or edge type, or vertex or edge property name does not conform to constraints. + * @throws { BusinessError } 31300009 - The GQL statement syntax error. + * @throws { BusinessError } 31300010 - The GQL statement semantic error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + read(gql: string): Promise; + + /** + * Execute a data-modifying procedure. + * + * @param { string } gql - Indicates the GQL statement to execute. + * @returns { Promise } The {@link Result} object if the operation is successful. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300001 - Database corrupted. + * @throws { BusinessError } 31300002 - Already closed. + * @throws { BusinessError } 31300003 - The database is busy. + * @throws { BusinessError } 31300004 - The database is out of memory. + * @throws { BusinessError } 31300005 - The database is full. + * @throws { BusinessError } 31300006 - A duplicate graph name, vertex or edge type, or vertex or edge property name exists. + * @throws { BusinessError } 31300007 - The graph name, vertex or edge type, or vertex or edge property is not defined. + * @throws { BusinessError } 31300008 - The graph name, vertex or edge type, or vertex or edge property name does not conform to constraints. + * @throws { BusinessError } 31300009 - The GQL statement syntax error. + * @throws { BusinessError } 31300010 - The GQL statement semantic error. + * @throws { BusinessError } 31300012 - The number of graph names, vertex or edge types, or vertex or edge properties exceeds the limit. + * @throws { BusinessError } 31300013 - A conflicting constraint already exists. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + write(gql: string): Promise; + + /** + * Commit the transaction. + * + * @returns { Promise } The Promise used to return the result. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300001 - Database corrupted. + * @throws { BusinessError } 31300002 - Already closed. + * @throws { BusinessError } 31300003 - The database is busy. + * @throws { BusinessError } 31300004 - The database is out of memory. + * @throws { BusinessError } 31300005 - The database is full. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + commit(): Promise; + + /** + * Rollback the transaction. + * + * @returns { Promise } The Promise used to return the result. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300001 - Database corrupted. + * @throws { BusinessError } 31300002 - Already closed. + * @throws { BusinessError } 31300003 - The database is busy. + * @throws { BusinessError } 31300004 - The database is out of memory. + * @throws { BusinessError } 31300005 - The database is full. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + rollback(): Promise; + } + + /** + * Provides methods for managing the graph database. + * + * @interface GraphStore + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + interface GraphStore { + /** + * Execute a query procedure. + * + * @param { string } gql - Indicates the GQL statement to execute. + * @returns { Promise } The {@link Result} object if the operation is successful. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300001 - Database corrupted. + * @throws { BusinessError } 31300002 - Already closed. + * @throws { BusinessError } 31300003 - The database is busy. + * @throws { BusinessError } 31300004 - The database is out of memory. + * @throws { BusinessError } 31300005 - The database is full. + * @throws { BusinessError } 31300006 - A duplicate graph name, vertex or edge type, or vertex or edge property name exists. + * @throws { BusinessError } 31300007 - The graph name, vertex or edge type, or vertex or edge property is not defined. + * @throws { BusinessError } 31300008 - The graph name, vertex or edge type, or vertex or edge property name does not conform to constraints. + * @throws { BusinessError } 31300009 - The GQL statement syntax error. + * @throws { BusinessError } 31300010 - The GQL statement semantic error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + read(gql: string): Promise; + + /** + * Execute a data-modifying or catalog-modifying procedure. + * + * @param { string } gql - Indicates the GQL statement to execute. + * @returns { Promise } The {@link Result} object if the operation is successful. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300001 - Database corrupted. + * @throws { BusinessError } 31300002 - Already closed. + * @throws { BusinessError } 31300003 - The database is busy. + * @throws { BusinessError } 31300004 - The database is out of memory. + * @throws { BusinessError } 31300005 - The database is full. + * @throws { BusinessError } 31300006 - A duplicate graph name, vertex or edge type, or vertex or edge property name exists. + * @throws { BusinessError } 31300007 - The graph name, vertex or edge type, or vertex or edge property is not defined. + * @throws { BusinessError } 31300008 - The graph name, vertex or edge type, or vertex or edge property name does not conform to constraints. + * @throws { BusinessError } 31300009 - The GQL statement syntax error. + * @throws { BusinessError } 31300010 - The GQL statement semantic error. + * @throws { BusinessError } 31300012 - The number of graph names, vertex or edge types, or vertex or edge properties exceeds the limit. + * @throws { BusinessError } 31300013 - A conflicting constraint already exists. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + write(gql: string): Promise; + + /** + * Create a transaction instance. + * + * @returns { Promise } The {@link Transaction} object if the operation is successful. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300001 - Database corrupted. + * @throws { BusinessError } 31300002 - Already closed. + * @throws { BusinessError } 31300003 - The database is busy. + * @throws { BusinessError } 31300004 - The database is out of memory. + * @throws { BusinessError } 31300005 - The database is full. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + createTransaction(): Promise; + + /** + * Close the GraphStore and opened transactions will be rollback. + * @returns { Promise } The Promise returned by the function. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + close(): Promise; + } + + /** + * Obtains a graph store. + * You can set parameters of the graph store as required. In general, this method is recommended + * to obtain a graph store. + * + * @param { Context } context - Indicates the context of an application or ability. + * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this graph store. + * @returns { Promise } The graph store {@link GraphStore}. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300001 - Database corrupted. + * @throws { BusinessError } 31300014 - Failed to open or delete the database with an invalid database path. + * @throws { BusinessError } 31300015 - StoreConfig, for example, securityLevel or encrypt, is changed. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + function getStore(context: Context, config: StoreConfig): Promise; + + /** + * Deletes the database with a specified store config. + * + * @param { Context } context - Indicates the context of an application or ability. + * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this graph store. + * @returns { Promise } The Promise returned by the function. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 31300000 - Inner error. + * @throws { BusinessError } 31300014 - Failed to open or delete the database with an invalid database path. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @systemapi + * @since 18 + */ + function deleteStore(context: Context, config: StoreConfig): Promise; +} + +export default graphStore; diff --git a/interface_sdk/api/@ohos.data.intelligence.d.ts b/interface_sdk/api/@ohos.data.intelligence.d.ts new file mode 100644 index 00000000..f80129e1 --- /dev/null +++ b/interface_sdk/api/@ohos.data.intelligence.d.ts @@ -0,0 +1,271 @@ +/* + * 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. + */ + +/** + * @file + * @kit ArkData + */ + +/** + * Provides methods for intelligent data processing. + * + * @namespace intelligence + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ +declare namespace intelligence { + /** + * Obtains a text embedding model. + * + * @param { ModelConfig } config - The configuration of the embedding model. + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + function getTextEmbeddingModel(config: ModelConfig): Promise; + + /** + * Obtains an image embedding model. + * + * @param { ModelConfig } config - The configuration of the embedding model. + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + function getImageEmbeddingModel(config: ModelConfig): Promise; + + /** + * Manages configurations of the embedding model. + * + * @interface ModelConfig + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + interface ModelConfig { + /** + * Version of the model. + * The outputs of text or image embedding models with the same version are in the same vector space. + * + * @type { ModelVersion } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + version: ModelVersion; + + /** + * Indicates whether NPU is used. + * + * @type { boolean } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + isNpuAvailable: boolean; + + /** + * If NPU is used for accelerating, a local path is required for model caching. + * + * @type { ?string } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + cachePath?: string; + } + + /** + * Version of the model. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + enum ModelVersion { + /** + * The basic embedding model. + * + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + BASIC_MODEL = 0 + } + + /** + * Describes the text embedding functions of the multi-modal embedding model. + * Chinese and English are supported. + * + * @interface TextEmbedding + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + interface TextEmbedding { + /** + * Loads this text embedding model. If the loading fails, an error code is returned. + * + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + loadModel(): Promise; + + /** + * Releases this text embedding model. If the releasing fails, an error code is returned. + * + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + releaseModel(): Promise; + + /** + * Obtains the embedding vector of the given text. + * The model can process up to 512 characters of text per inference, supporting both Chinese and English. + * + * @param { string } text - The input text of the embedding model. + * @returns { Promise> } The promise used to return the embedding result. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + getEmbedding(text: string): Promise>; + + /** + * Obtains the embedding vector of a given batch of text. + * The model can process up to 512 characters of text per inference, supporting both Chinese and English. + * + * @param { Array } batchTexts - The input batch of texts of the embedding model. + * @returns { Promise>> } The promise used to return the embedding result. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + getEmbedding(batchTexts: Array): Promise>>; + } + + /** + * Describes the image embedding functions of the multi-modal embedding model. + * + * @interface ImageEmbedding + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + interface ImageEmbedding { + /** + * Loads this image embedding model. If the loading fails, an error code is returned. + * + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + loadModel(): Promise; + + /** + * Releases this image embedding model. If the releasing fails, an error code is returned. + * + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + releaseModel(): Promise; + + /** + * Obtains the embedding vector of the given image. + * The model can handle images below 20 MB in size in a single inference. + * + * @param { Image } image - The input image of the embedding model. + * @returns { Promise> } The promise used to return the embedding result. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + getEmbedding(image: Image): Promise>; + } + + /** + * The type of the image can be its URI. + * + * @typedef { string } Image + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 15 + */ + type Image = string; + + /** + * Splits text. + * + * @param { string } text - Text for chunking. The length of the text is no longer then 100k tokens. + * @param { SplitConfig } config - Configurations of text chunking. + * @returns { Promise> } The promise used to return the result. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 31300000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + function splitText(text: string, config: SplitConfig): Promise>; + + /** + * Manages text chunk process configurations. + * + * @interface SplitConfig + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + interface SplitConfig { + /** + * The maximun size of chunks. + * + * @type { number } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + size: number; + + /** + * The ratio of overlap between adjacent chunks. + * + * @type { number } + * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core + * @since 15 + */ + overlapRatio: number; + } +} + +export default intelligence; \ No newline at end of file diff --git a/interface_sdk/api/@ohos.data.preferences.d.ts b/interface_sdk/api/@ohos.data.preferences.d.ts index 93426060..40d6de6d 100644 --- a/interface_sdk/api/@ohos.data.preferences.d.ts +++ b/interface_sdk/api/@ohos.data.preferences.d.ts @@ -74,7 +74,8 @@ declare namespace preferences { /** * Indicates possible value types * - * @typedef {number | string | boolean | Array | Array | Array | Uint8Array | object | bigint} + * @typedef {number | string | boolean | Array | Array | Array | Uint8Array | object | + * bigint} * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice * @since 12 @@ -149,6 +150,34 @@ declare namespace preferences { */ const MAX_VALUE_LENGTH: number; + /** + * the storage type + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @atomicservice + * @since 18 + */ + enum StorageType { + /** + * XML storage type + * + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @atomicservice + * @since 18 + */ + XML = 0, + + /** + * GSKV storage type + * + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @atomicservice + * @since 18 + */ + GSKV + } + /** * Manages preferences file configurations. * @@ -202,6 +231,16 @@ declare namespace preferences { * @since 11 */ dataGroupId?: string | null | undefined; + + /** + * The preferences storage type. + * + * @type { ?(StorageType | null | undefined) } + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @atomicservice + * @since 18 + */ + storageType?: StorageType | null | undefined; } /** @@ -212,10 +251,10 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - The {@link Preferences} instance matching the specified - * preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * preferences file name. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -227,10 +266,10 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - The {@link Preferences} instance matching the specified - * preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * preferences file name. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -243,10 +282,10 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - The {@link Preferences} instance matching the specified - * preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * preferences file name. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -263,13 +302,13 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @param { AsyncCallback } callback - The {@link Preferences} instance matching the specified - * preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * preferences file name. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -282,14 +321,14 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @param { AsyncCallback } callback - The {@link Preferences} instance matching the specified - * preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * preferences file name. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -305,9 +344,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } The {@link Preferences} instance matching the specified preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -319,9 +358,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } The {@link Preferences} instance matching the specified preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -334,9 +373,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } The {@link Preferences} instance matching the specified preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -353,12 +392,12 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @returns { Promise } The {@link Preferences} instance matching the specified preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -371,13 +410,13 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @returns { Promise } The {@link Preferences} instance matching the specified preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -394,12 +433,12 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @returns { Preferences } The {@link Preferences} instance matching the specified preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -413,13 +452,13 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @returns { Preferences } The {@link Preferences} instance matching the specified preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -427,6 +466,16 @@ declare namespace preferences { */ function getPreferencesSync(context: Context, options: Options): Preferences; + /** + * check the {@link StorageType} type is supported or not on current system. + * @param { StorageType } type - Indicates storage type which want to check. + * @returns { boolean } a boolean value indicates this system support the type or not. + * @throws { BusinessError } 401 - Parameter error. Possible causes: Incorrect parameter types + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @atomicservice + * @since 18 + */ + function isStorageTypeSupported(type: StorageType): boolean; /** * Deletes a {@link Preferences} instance matching a specified preferences file name * from the cache which is performed by removePreferencesFromCache and deletes the @@ -438,10 +487,10 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -456,10 +505,10 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -475,11 +524,11 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -498,13 +547,13 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -520,14 +569,14 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -546,10 +595,10 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -564,10 +613,10 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -583,11 +632,11 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -606,13 +655,13 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -628,14 +677,14 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -653,9 +702,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -669,9 +718,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -686,9 +735,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -707,12 +756,12 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -727,13 +776,13 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -751,9 +800,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -767,9 +816,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -784,9 +833,9 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -805,12 +854,12 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -825,13 +874,13 @@ declare namespace preferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -848,9 +897,9 @@ declare namespace preferences { * * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -864,9 +913,9 @@ declare namespace preferences { * * @param { Context } context - Indicates the context of application or capability. * @param { string } name - Indicates the preferences file name. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -884,12 +933,12 @@ declare namespace preferences { * * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -903,13 +952,13 @@ declare namespace preferences { * * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates the {@link Options} option of preferences file position. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @atomicservice @@ -959,13 +1008,13 @@ declare namespace preferences { *

If the value is {@code null} or not in the ValueType format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } defValue - Indicates the default value to return. * @param { AsyncCallback } callback - The value matching the specified key if it is found; - * returns the default value otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -974,13 +1023,13 @@ declare namespace preferences { *

If the value is {@code null} or not in the ValueType format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } defValue - Indicates the default value to return. * @param { AsyncCallback } callback - The value matching the specified key if it is found; - * returns the default value otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -990,13 +1039,13 @@ declare namespace preferences { *

If the value is {@code null} or not in the ValueType format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } defValue - Indicates the default value to return. * @param { AsyncCallback } callback - The value matching the specified key if it is found; - * returns the default value otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1010,13 +1059,13 @@ declare namespace preferences { *

If the value is {@code null} or not in the ValueType format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } defValue - Indicates the default value to return. * @returns { Promise } The value matching the specified key if it is found; - * returns the default value otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -1025,13 +1074,13 @@ declare namespace preferences { *

If the value is {@code null} or not in the ValueType format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } defValue - Indicates the default value to return. * @returns { Promise } The value matching the specified key if it is found; - * returns the default value otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1041,13 +1090,13 @@ declare namespace preferences { *

If the value is {@code null} or not in the ValueType format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } defValue - Indicates the default value to return. * @returns { Promise } The value matching the specified key if it is found; - * returns the default value otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1061,13 +1110,13 @@ declare namespace preferences { *

If the value is {@code null} or not in the ValueType format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } defValue - Indicates the default value to return. * @returns { ValueType } The value matching the specified key if it is found; - * returns the default value otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1077,13 +1126,13 @@ declare namespace preferences { *

If the value is {@code null} or not in the ValueType format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } defValue - Indicates the default value to return. * @returns { ValueType } The value matching the specified key if it is found; - * returns the default value otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1175,12 +1224,12 @@ declare namespace preferences { * Checks whether the {@link Preferences} object contains a preferences matching a specified key. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. - * @param { AsyncCallback } callback - {@code true} if the {@link Preferences} object contains a preferences - * with the specified key;returns {@code false} otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_KEY_LENGTH. + * @param { AsyncCallback } callback - {@code true} if the {@link Preferences} object contains a + * preferences with the specified key;returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -1188,12 +1237,12 @@ declare namespace preferences { * Checks whether the {@link Preferences} object contains a preferences matching a specified key. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. - * @param { AsyncCallback } callback - {@code true} if the {@link Preferences} object contains a preferences - * with the specified key;returns {@code false} otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_KEY_LENGTH. + * @param { AsyncCallback } callback - {@code true} if the {@link Preferences} object contains a + * preferences with the specified key;returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1202,12 +1251,12 @@ declare namespace preferences { * Checks whether the {@link Preferences} object contains a preferences matching a specified key. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. - * @param { AsyncCallback } callback - {@code true} if the {@link Preferences} object contains a preferences - * with the specified key;returns {@code false} otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_KEY_LENGTH. + * @param { AsyncCallback } callback - {@code true} if the {@link Preferences} object contains a + * preferences with the specified key;returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1220,12 +1269,12 @@ declare namespace preferences { * Checks whether the {@link Preferences} object contains a preferences matching a specified key. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { Promise } {@code true} if the {@link Preferences} object contains - * a preferences with the specified key; returns {@code false} otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * a preferences with the specified key; returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -1233,12 +1282,12 @@ declare namespace preferences { * Checks whether the {@link Preferences} object contains a preferences matching a specified key. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { Promise } {@code true} if the {@link Preferences} object contains - * a preferences with the specified key; returns {@code false} otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * a preferences with the specified key; returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1247,12 +1296,12 @@ declare namespace preferences { * Checks whether the {@link Preferences} object contains a preferences matching a specified key. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { Promise } {@code true} if the {@link Preferences} object contains - * a preferences with the specified key; returns {@code false} otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * a preferences with the specified key; returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1266,12 +1315,12 @@ declare namespace preferences { * is executed synchronously. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { boolean } {@code true} if the {@link Preferences} object contains - * a preferences with the specified key; returns {@code false} otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * a preferences with the specified key; returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1281,12 +1330,12 @@ declare namespace preferences { * is executed synchronously. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { boolean } {@code true} if the {@link Preferences} object contains - * a preferences with the specified key; returns {@code false} otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * a preferences with the specified key; returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1301,13 +1350,13 @@ declare namespace preferences { * file. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. + * MAX_VALUE_LENGTH. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -1315,15 +1364,19 @@ declare namespace preferences { * Sets an int value for the key in the {@link Preferences} object. *

You can call the {@link #flush} method to save the {@link Preferences} object to the * file. + *

When the value contains strings in a non-UTF-8 format, use the Uint8Array type for storage. + * Otherwise, the format of the persistent file is incorrect and the file is damaged. + *

If the corresponding key already exists, the {@link put} method will overwrite its value. + * You can use the {@link #hasSync} method to check whether the corresponding key-value pair exists. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. + * MAX_VALUE_LENGTH. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1332,15 +1385,19 @@ declare namespace preferences { * Sets an int value for the key in the {@link Preferences} object. *

You can call the {@link #flush} method to save the {@link Preferences} object to the * file. + *

When the value contains strings in a non-UTF-8 format, use the Uint8Array type for storage. + * Otherwise, the format of the persistent file is incorrect and the file is damaged. + *

If the corresponding key already exists, the {@link put} method will overwrite its value. + * You can use the {@link #hasSync} method to check whether the corresponding key-value pair exists. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. + * MAX_VALUE_LENGTH. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1353,15 +1410,19 @@ declare namespace preferences { * Sets an int value for the key in the {@link Preferences} object. *

You can call the {@link #flush} method to save the {@link Preferences} object to the * file. + *

When the value contains strings in a non-UTF-8 format, use the Uint8Array type for storage. + * Otherwise, the format of the persistent file is incorrect and the file is damaged. + *

If the corresponding key already exists, the {@link put} method will overwrite its value. + * You can use the {@link #hasSync} method to check whether the corresponding key-value pair exists. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. + * MAX_VALUE_LENGTH. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -1369,15 +1430,19 @@ declare namespace preferences { * Sets an int value for the key in the {@link Preferences} object. *

You can call the {@link #flush} method to save the {@link Preferences} object to the * file. + *

When the value contains strings in a non-UTF-8 format, use the Uint8Array type for storage. + * Otherwise, the format of the persistent file is incorrect and the file is damaged. + *

If the corresponding key already exists, the {@link put} method will overwrite its value. + * You can use the {@link #hasSync} method to check whether the corresponding key-value pair exists. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. + * MAX_VALUE_LENGTH. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1386,15 +1451,19 @@ declare namespace preferences { * Sets an int value for the key in the {@link Preferences} object. *

You can call the {@link #flush} method to save the {@link Preferences} object to the * file. + *

When the value contains strings in a non-UTF-8 format, use the Uint8Array type for storage. + * Otherwise, the format of the persistent file is incorrect and the file is damaged. + *

If the corresponding key already exists, the {@link put} method will overwrite its value. + * You can use the {@link #hasSync} method to check whether the corresponding key-value pair exists. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. + * MAX_VALUE_LENGTH. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1407,14 +1476,18 @@ declare namespace preferences { * Sets an int value for the key in the {@link Preferences} object. This interface is executed synchronously. *

You can call the {@link #flush} method to save the {@link Preferences} object to the * file. + *

When the value contains strings in a non-UTF-8 format, use the Uint8Array type for storage. + * Otherwise, the format of the persistent file is incorrect and the file is damaged. + *

If the corresponding key already exists, the {@link put} method will overwrite its value. + * You can use the {@link #hasSync} method to check whether the corresponding key-value pair exists. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_VALUE_LENGTH. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1423,14 +1496,18 @@ declare namespace preferences { * Sets an int value for the key in the {@link Preferences} object. This interface is executed synchronously. *

You can call the {@link #flush} method to save the {@link Preferences} object to the * file. + *

When the value contains strings in a non-UTF-8 format, use the Uint8Array type for storage. + * Otherwise, the format of the persistent file is incorrect and the file is damaged. + *

If the corresponding key already exists, the {@link put} method will overwrite its value. + * You can use the {@link #hasSync} method to check whether the corresponding key-value pair exists. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { ValueType } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_VALUE_LENGTH. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1441,44 +1518,41 @@ declare namespace preferences { /** * Deletes the preferences with a specified key from the {@link Preferences} object. - *

You can call the {@link #flush} method to save the {@link Preferences} object to the - * file. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ /** * Deletes the preferences with a specified key from the {@link Preferences} object. - *

You can call the {@link #flush} method to save the {@link Preferences} object to the - * file. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 */ /** * Deletes the preferences with a specified key from the {@link Preferences} object. - *

You can call the {@link #flush} method to save the {@link Preferences} object to the - * file. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { AsyncCallback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1489,44 +1563,41 @@ declare namespace preferences { /** * Deletes the preferences with a specified key from the {@link Preferences} object. - *

You can call the {@link #flush} method to save the {@link Preferences} object to the - * file. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ /** * Deletes the preferences with a specified key from the {@link Preferences} object. - *

You can call the {@link #flush} method to save the {@link Preferences} object to the - * file. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 */ /** * Deletes the preferences with a specified key from the {@link Preferences} object. - *

You can call the {@link #flush} method to save the {@link Preferences} object to the - * file. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { Promise } A promise object. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1541,10 +1612,10 @@ declare namespace preferences { * object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_KEY_LENGTH. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1555,10 +1626,10 @@ declare namespace preferences { * object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_KEY_LENGTH. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1706,14 +1777,25 @@ declare namespace preferences { */ flush(): Promise; + /** + * Saves the {@link Preferences} object to the file. + * + * @throws { BusinessError } 15500000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 14 + */ + flushSync(): void; + /** * Registers an observer to listen for the change of a {@link Preferences} object. * * @param { 'change' } type - Indicates the callback when preferences changes. * @param { Callback<{ key: string }> } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -1722,9 +1804,9 @@ declare namespace preferences { * * @param { 'change' } type - Indicates the callback when preferences changes. * @param { Function } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1734,9 +1816,9 @@ declare namespace preferences { * * @param { 'change' } type - Indicates the callback when preferences changes. * @param { Callback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1750,10 +1832,10 @@ declare namespace preferences { * * @param { 'multiProcessChange' } type - Indicates the callback when preferences changed in multiple processes. * @param { Function } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. - * @throws { BusinessError } 15500019 - Failed to obtain subscription service. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. + * @throws { BusinessError } 15500019 - Failed to obtain the subscription service. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 10 */ @@ -1762,11 +1844,11 @@ declare namespace preferences { * * @param { 'multiProcessChange' } type - Indicates the callback when preferences changed in multiple processes. * @param { Callback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15500019 - Failed to obtain subscription service. + * @throws { BusinessError } 15500019 - Failed to obtain the subscription service. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice * @since 11 @@ -1779,9 +1861,9 @@ declare namespace preferences { * @param { 'dataChange' } type - Indicates the type of the event to observe. * @param { Array } keys - Indicates one or more keys to listen for. * @param { Callback> } callback - Indicates the callback used to return the data change. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -1794,9 +1876,9 @@ declare namespace preferences { * * @param { 'change' } type - Indicates the callback when preferences changes. * @param { Callback<{ key: string }> } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 9 */ @@ -1805,9 +1887,9 @@ declare namespace preferences { * * @param { 'change' } type - Indicates the callback when preferences changes. * @param { Function } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 @@ -1817,9 +1899,9 @@ declare namespace preferences { * * @param { 'change' } type - Indicates the callback when preferences changes. * @param { Callback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform @@ -1833,9 +1915,9 @@ declare namespace preferences { * * @param { 'multiProcessChange' } type - Indicates the callback when preferences changed in multiple processes. * @param { Function } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 10 */ @@ -1844,9 +1926,9 @@ declare namespace preferences { * * @param { 'multiProcessChange' } type - Indicates the callback when preferences changed in multiple processes. * @param { Callback } callback - Indicates the callback function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -1860,9 +1942,9 @@ declare namespace preferences { * @param { 'dataChange' } type - Indicates the event type. * @param { Array } keys - Indicates the data whose changes are not observed. * @param { Callback> } callback - Indicates the callback to unregister. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice diff --git a/interface_sdk/api/@ohos.data.relationalStore.d.ts b/interface_sdk/api/@ohos.data.relationalStore.d.ts index 1c9b5a9c..8acdd436 100644 --- a/interface_sdk/api/@ohos.data.relationalStore.d.ts +++ b/interface_sdk/api/@ohos.data.relationalStore.d.ts @@ -346,7 +346,7 @@ declare namespace relationalStore { * @type { ?string } * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform - * @since 16 + * @since 18 */ rootDir?: string; @@ -384,7 +384,7 @@ declare namespace relationalStore { * * @type { ?boolean } * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 18 */ vector?: boolean; @@ -431,7 +431,7 @@ declare namespace relationalStore { * * @type { ?Tokenizer } * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 17 */ tokenizer?: Tokenizer; @@ -641,28 +641,28 @@ declare namespace relationalStore { * * @enum { number } * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 17 */ enum Tokenizer { /** * NONE_TOKENIZER: not use tokenizer * * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 17 */ NONE_TOKENIZER = 0, /** * ICU_TOKENIZER: native icu tokenizer. * * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 17 */ ICU_TOKENIZER, /** * CUSTOM_TOKENIZER: self-developed enhance tokenizer. * * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 18 */ CUSTOM_TOKENIZER } @@ -941,6 +941,46 @@ declare namespace relationalStore { executeTime: number; } + /** + * Defines an exception message. + * + * @interface ExceptionMessage + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + interface ExceptionMessage { + /** + * Error code returned by SQLite, see {@link https://www.sqlite.org/rescode.html}. + * + * @type { number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + code: number; + + /** + * Error message. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + message: string; + + /** + * SQL statement executed when the exception occurs. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + sql: string; + } + /** * Describes the {@code RdbStore} type. * @@ -1295,9 +1335,18 @@ declare namespace relationalStore { * * @type { ?boolean } * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 18 */ asyncDownloadAsset?: boolean; + + /** + * Specifies whether the cloud sync is enabled for the database. + * + * @type { ?boolean } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 18 + */ + enableCloud?: boolean; } /** @@ -1548,6 +1597,99 @@ declare namespace relationalStore { transactionType?: TransactionType; } + /** + * Enumerates the data types of a column. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + enum ColumnType { + /** + * The value in the column is null. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + NULL, + + /** + * The value in the column is a 64-bit integer. It can be used to hold an 8-bit (including Boolean values), 16-bit, + * 32-bit, or 64-bit integer.if the 64-bit integer is greater than 2^53 or less than -2^53, you can use getString + * to convert the 64-bit integer into a string. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + INTEGER, + + /** + * The value in the column is a floating point number. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + REAL, + + /** + * The value in the column is a string. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + TEXT, + + /** + * The value in the column is a Uint8Array. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + BLOB, + + /** + * The value in the column is an asset. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + ASSET, + + /** + * The value in the column is an array of assets. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + ASSETS, + + /** + * The value in the column is a Float32Array. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + FLOAT_VECTOR, + + /** + * The value in the column is a bigint. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + UNLIMITED_INT, + } + /** * Manages relational database configurations. * @@ -2183,7 +2325,8 @@ declare namespace relationalStore { * Configure RdbPredicates to specify the start position of the returned result. * Use this method together with limit(number). * - * @param { number } rowOffset - Indicates the start position of the returned result. The value is a positive integer. + * @param { number } rowOffset - Indicates the start position of the returned result. + * The value is a positive integer. * @returns { RdbPredicates } - The SQL query statement with the specified {@link RdbPredicates}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -2194,7 +2337,8 @@ declare namespace relationalStore { * Configure RdbPredicates to specify the start position of the returned result. * Use this method together with limit(number). * - * @param { number } rowOffset - Indicates the start position of the returned result. The value is a positive integer. + * @param { number } rowOffset - Indicates the start position of the returned result. + * The value is a positive integer. * @returns { RdbPredicates } - The SQL query statement with the specified {@link RdbPredicates}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -2335,6 +2479,20 @@ declare namespace relationalStore { * @since 12 */ notLike(field: string, value: string): RdbPredicates; + + /** + * Filters the grouped data that meets the specified conditions. + * + * @param { string } conditions - Conditions used to filter the data obtained using GROUP BY. + * @param { Array } args - Parameters to be used in the conditions. + * @returns { RdbPredicates } - Returns the RdbPredicates object. + * @throws { BusinessError } 14800001 - Invalid args. Possible causes: 1. conditions is empty; + *
2. The GROUP BY clause is missing. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + having(conditions:string, args?: Array): RdbPredicates; } /** @@ -2543,11 +2701,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800019 - The SQL must be a query statement. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -2601,11 +2760,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800019 - The SQL must be a query statement. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -2625,13 +2785,83 @@ declare namespace relationalStore { */ getColumnName(columnIndex: number): string; + /** + * Obtains the column data type based on the specified column index. + * The column index is passed as an input parameter. + * + * @param { number | string } columnIdentifier - Index or name of the column. + * @returns { Promise } Promise used to return the data type obtained, + * in an {@link ColumnType} instance. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. + * @throws { BusinessError } 14800019 - The SQL must be a query statement. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. + * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800030 - SQLite: Unable to open the database file. + * @throws { BusinessError } 14800031 - SQLite: TEXT or BLOB exceeds size limit. + * @throws { BusinessError } 14800032 - SQLite: Abort due to constraint violation. + * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. + * @throws { BusinessError } 14800034 - SQLite: Library used incorrectly. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + getColumnType(columnIdentifier: number | string): Promise; + + /** + * Obtains the column data type based on the specified column index. This API returns the result synchronously. + * + * @param { number | string } columnIdentifier - Index or name of the column. + * @returns { ColumnType } Column data type obtained. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. + * @throws { BusinessError } 14800019 - The SQL must be a query statement. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. + * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800030 - SQLite: Unable to open the database file. + * @throws { BusinessError } 14800031 - SQLite: TEXT or BLOB exceeds size limit. + * @throws { BusinessError } 14800032 - SQLite: Abort due to constraint violation. + * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. + * @throws { BusinessError } 14800034 - SQLite: Library used incorrectly. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 18 + */ + getColumnTypeSync(columnIdentifier: number | string): ColumnType; + /** * Go to the specified row of the result set forwards or backwards by an offset relative to its current position. * A positive offset indicates moving backwards, and a negative offset indicates moving forwards. * * @param { number } offset - Indicates the offset relative to the current position. * @returns { boolean } True if the result set is moved successfully and does not go beyond the range; - * Returns false otherwise. + * Returns false otherwise. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -2644,7 +2874,7 @@ declare namespace relationalStore { * * @param { number } offset - Indicates the offset relative to the current position. * @returns { boolean } True if the result set is moved successfully and does not go beyond the range; - * Returns false otherwise. + * Returns false otherwise. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -2658,15 +2888,16 @@ declare namespace relationalStore { * * @param { number } offset - Indicates the offset relative to the current position. * @returns { boolean } True if the result set is moved successfully and does not go beyond the range; - * Returns false otherwise. + * Returns false otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800019 - The SQL must be a query statement. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -2717,11 +2948,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800019 - The SQL must be a query statement. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -2745,7 +2977,7 @@ declare namespace relationalStore { * Go to the first row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is empty. + * Returns false otherwise, for example, if the result set is empty. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 @@ -2754,7 +2986,7 @@ declare namespace relationalStore { * Go to the first row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is empty. + * Returns false otherwise, for example, if the result set is empty. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -2764,13 +2996,14 @@ declare namespace relationalStore { * Go to the first row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is empty. + * Returns false otherwise, for example, if the result set is empty. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800019 - The SQL must be a query statement. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -2794,7 +3027,7 @@ declare namespace relationalStore { * Go to the last row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is empty. + * Returns false otherwise, for example, if the result set is empty. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 @@ -2803,7 +3036,7 @@ declare namespace relationalStore { * Go to the last row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is empty. + * Returns false otherwise, for example, if the result set is empty. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -2813,13 +3046,14 @@ declare namespace relationalStore { * Go to the last row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is empty. + * Returns false otherwise, for example, if the result set is empty. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800019 - The SQL must be a query statement. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -2843,7 +3077,7 @@ declare namespace relationalStore { * Go to the next row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is already in the last row. + * Returns false otherwise, for example, if the result set is already in the last row. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 @@ -2852,7 +3086,7 @@ declare namespace relationalStore { * Go to the next row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is already in the last row. + * Returns false otherwise, for example, if the result set is already in the last row. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -2862,13 +3096,14 @@ declare namespace relationalStore { * Go to the next row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is already in the last row. + * Returns false otherwise, for example, if the result set is already in the last row. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800019 - The SQL must be a query statement. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -2892,7 +3127,7 @@ declare namespace relationalStore { * Go to the previous row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is already in the first row. + * Returns false otherwise, for example, if the result set is already in the first row. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 @@ -2901,7 +3136,7 @@ declare namespace relationalStore { * Go to the previous row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is already in the first row. + * Returns false otherwise, for example, if the result set is already in the first row. * @throws { BusinessError } 14800012 - The result set is empty or the specified location is invalid. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -2911,13 +3146,14 @@ declare namespace relationalStore { * Go to the previous row of the result set. * * @returns { boolean } True if the result set is moved successfully; - * Returns false otherwise, for example, if the result set is already in the first row. + * Returns false otherwise, for example, if the result set is already in the first row. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800019 - The SQL must be a query statement. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -2974,11 +3210,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3035,11 +3272,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3096,11 +3334,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3157,11 +3396,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3205,11 +3445,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3253,11 +3494,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3287,11 +3529,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3320,11 +3563,12 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3353,10 +3597,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - The capability is not supported because the database is not a vector DB. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3371,7 +3616,8 @@ declare namespace relationalStore { * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. * @throws { BusinessError } 14800034 - SQLite: Library used incorrectly. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @systemapi + * @since 12 */ getFloat32Array(columnIndex: number): Float32Array; @@ -3389,11 +3635,12 @@ declare namespace relationalStore { * * @returns { ValuesBucket } Indicates the row of data {@link ValuesBucket} to be inserted into the table. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3418,11 +3665,12 @@ declare namespace relationalStore { * * @returns { ValuesBucket } Indicates the row of data {@link ValuesBucket} to be inserted into the table. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3446,15 +3694,17 @@ declare namespace relationalStore { * Obtains the values of all columns in the specified rows. * @param { number } maxCount - Indicates the maximum number of rows. * @param { number } position - Indicates the start position to obtain the values. - * @returns { Promise> } Promise used to return the values obtained, in an{@link Array}. + * @returns { Promise> } Promise used to return the values obtained, + * in an {@link Array}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3467,7 +3717,7 @@ declare namespace relationalStore { * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform - * @since 16 + * @since 18 */ getRows(maxCount: number, position?: number): Promise>; @@ -3477,11 +3727,12 @@ declare namespace relationalStore { * @returns { sendableRelationalStore.ValuesBucket } Indicates the row of data * {@link sendableRelationalStore.ValuesBucket} to be inserted into the table. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3505,7 +3756,7 @@ declare namespace relationalStore { * * @param { number } columnIndex - Indicates the specified column index, which starts from 0. * @returns { boolean } True if the value of the specified column in the current row is null; - * Returns false otherwise. + * Returns false otherwise. * @throws { BusinessError } 14800013 - The column value is null or the column type is incompatible. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -3517,7 +3768,7 @@ declare namespace relationalStore { * * @param { number } columnIndex - Indicates the specified column index, which starts from 0. * @returns { boolean } True if the value of the specified column in the current row is null; - * Returns false otherwise. + * Returns false otherwise. * @throws { BusinessError } 14800013 - The column value is null or the column type is incompatible. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -3530,15 +3781,16 @@ declare namespace relationalStore { * * @param { number } columnIndex - Indicates the specified column index, which starts from 0. * @returns { boolean } True if the value of the specified column in the current row is null; - * Returns false otherwise. + * Returns false otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800012 - Row out of bounds. - * @throws { BusinessError } 14800013 - Column out of bounds. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. + * @throws { BusinessError } 14800013 - Resultset is empty or column index is out of bounds. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3580,7 +3832,7 @@ declare namespace relationalStore { * Calling this method on the result set will release all of its resources and makes it ineffective. * * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800012 - Row out of bounds. + * @throws { BusinessError } 14800012 - ResultSet is empty or pointer index is out of bounds. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 12 @@ -3634,9 +3886,10 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -3695,10 +3948,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3744,10 +3998,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3803,10 +4058,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3852,10 +4108,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3886,10 +4143,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3921,10 +4179,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -3948,8 +4207,10 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. - * @param { AsyncCallback } callback - The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { AsyncCallback } callback - + * The number of values that were inserted if the operation is successful. returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. @@ -3960,8 +4221,10 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. - * @param { AsyncCallback } callback - The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { AsyncCallback } callback - + * The number of values that were inserted if the operation is successful. returns -1 otherwise. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -3974,15 +4237,18 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. - * @param { AsyncCallback } callback - The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @param { Array } values - Indicates the rows of data {@link ValuesBucket} + * to be inserted into the table. + * @param { AsyncCallback } callback - + * The number of values that were inserted if the operation is successful. returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4007,8 +4273,10 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. - * @returns { Promise } The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @returns { Promise } The number of values that were inserted if the operation is successful. + * returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. @@ -4019,8 +4287,10 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. - * @returns { Promise } The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @returns { Promise } The number of values that were inserted if the operation is successful. + * returns -1 otherwise. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -4033,15 +4303,18 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. - * @returns { Promise } The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @returns { Promise } The number of values that were inserted if the operation is successful. + * returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4066,15 +4339,17 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. * @returns { number } The number of values that were inserted if the operation is successful. returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4099,16 +4374,19 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. - * @returns { Promise } The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @returns { Promise } The number of values that were inserted if the operation is successful. + * returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4125,7 +4403,7 @@ declare namespace relationalStore { * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform - * @since 16 + * @since 18 */ batchInsertWithConflictResolution(table: string, values: Array, conflict: ConflictResolution): Promise; @@ -4133,16 +4411,17 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. - * @returns { Promise } The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. * @returns { number } The number of values that were inserted if the operation is successful. returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4159,7 +4438,7 @@ declare namespace relationalStore { * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform - * @since 16 + * @since 18 */ batchInsertWithConflictResolutionSync(table: string, values: Array, conflict: ConflictResolution): number; @@ -4167,8 +4446,9 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -4180,8 +4460,9 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; @@ -4195,16 +4476,18 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4229,8 +4512,9 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. @@ -4245,17 +4529,19 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4275,18 +4561,19 @@ declare namespace relationalStore { * @since 12 */ update( - values: ValuesBucket, - predicates: RdbPredicates, - conflict: ConflictResolution, - callback: AsyncCallback + values: ValuesBucket, + predicates: RdbPredicates, + conflict: ConflictResolution, + callback: AsyncCallback ): void; /** * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -4298,8 +4585,9 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; @@ -4313,16 +4601,18 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4347,8 +4637,9 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. @@ -4363,17 +4654,19 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4398,17 +4691,19 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates with sync interface. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. * @returns { number } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4434,14 +4729,15 @@ declare namespace relationalStore { * * @param { string } table - Indicates the target table. * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. + * The key-value pairs are associated with column names of the database table. * @param { dataSharePredicates.DataSharePredicates } predicates - Indicates the specified update condition by - * the instance object of {@link dataSharePredicates.DataSharePredicates}. + * the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4452,15 +4748,16 @@ declare namespace relationalStore { * * @param { string } table - Indicates the target table. * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. + * The key-value pairs are associated with column names of the database table. * @param { dataSharePredicates.DataSharePredicates } predicates - Indicates the specified update condition by - * the instance object of {@link dataSharePredicates.DataSharePredicates}. + * the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4471,18 +4768,20 @@ declare namespace relationalStore { * * @param { string } table - Indicates the target table. * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. + * The key-value pairs are associated with column names of the database table. * @param { dataSharePredicates.DataSharePredicates } predicates - Indicates the specified update condition by - * the instance object of {@link dataSharePredicates.DataSharePredicates}. + * the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { AsyncCallback } callback - The number of affected rows. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4503,10 +4802,10 @@ declare namespace relationalStore { * @since 12 */ update( - table: string, - values: ValuesBucket, - predicates: dataSharePredicates.DataSharePredicates, - callback: AsyncCallback + table: string, + values: ValuesBucket, + predicates: dataSharePredicates.DataSharePredicates, + callback: AsyncCallback ): void; /** @@ -4514,14 +4813,15 @@ declare namespace relationalStore { * * @param { string } table - Indicates the target table. * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. + * The key-value pairs are associated with column names of the database table. * @param { dataSharePredicates.DataSharePredicates } predicates - Indicates the specified update condition by - * the instance object of {@link dataSharePredicates.DataSharePredicates}. + * the instance object of {@link dataSharePredicates.DataSharePredicates}. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4532,15 +4832,16 @@ declare namespace relationalStore { * * @param { string } table - Indicates the target table. * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. + * The key-value pairs are associated with column names of the database table. * @param { dataSharePredicates.DataSharePredicates } predicates - Indicates the specified update condition by - * the instance object of {@link dataSharePredicates.DataSharePredicates}. + * the instance object of {@link dataSharePredicates.DataSharePredicates}. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4551,18 +4852,20 @@ declare namespace relationalStore { * * @param { string } table - Indicates the target table. * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. + * The key-value pairs are associated with column names of the database table. * @param { dataSharePredicates.DataSharePredicates } predicates - Indicates the specified update condition by - * the instance object of {@link dataSharePredicates.DataSharePredicates}. + * the instance object of {@link dataSharePredicates.DataSharePredicates}. * @returns { Promise } The number of affected rows. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4587,7 +4890,8 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -4598,7 +4902,8 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; @@ -4611,15 +4916,17 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4643,7 +4950,8 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -4654,7 +4962,8 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. * @returns { Promise } return the number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; @@ -4667,15 +4976,17 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. * @returns { Promise } return the number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4699,15 +5010,17 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates with sync interface. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. - * @returns { number } return the number of affected rows. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. + * @returns { number } return the number of rows deleted. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4732,12 +5045,13 @@ declare namespace relationalStore { * * @param { string } table - Indicates the target table. * @param { dataSharePredicates.DataSharePredicates } predicates - The specified delete condition by - * the instance object of {@link dataSharePredicates.DataSharePredicates}. + * the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4747,14 +5061,15 @@ declare namespace relationalStore { * Deletes data from the database based on a specified instance object of RdbPredicates. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified delete condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified delete condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { AsyncCallback } callback - The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4764,17 +5079,19 @@ declare namespace relationalStore { * Deletes data from the database based on a specified instance object of RdbPredicates. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified delete condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified delete condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { AsyncCallback } callback - The number of affected rows. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4800,13 +5117,14 @@ declare namespace relationalStore { * Deletes data from the database based on a specified instance object of RdbPredicates. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified delete condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified delete condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4816,14 +5134,15 @@ declare namespace relationalStore { * Deletes data from the database based on a specified instance object of RdbPredicates. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified delete condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified delete condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4833,17 +5152,19 @@ declare namespace relationalStore { * Deletes data from the database based on a specified instance object of RdbPredicates. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified delete condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified delete condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @returns { Promise } The number of affected rows. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -4868,7 +5189,8 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -4880,12 +5202,13 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -4896,8 +5219,10 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to query. If the value is empty array, the query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - + * The columns to query. If the value is empty array, the query applies to all columns. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -4908,8 +5233,10 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to query. If the value is empty array, the query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - + * The columns to query. If the value is empty array, the query applies to all columns. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -4921,13 +5248,15 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to query. If the value is empty array, the query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - + * The columns to query. If the value is empty array, the query applies to all columns. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -4938,7 +5267,8 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } columns - The columns to query. If the value is null, the query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; @@ -4950,7 +5280,8 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } columns - The columns to query. If the value is null, the query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; @@ -4963,13 +5294,14 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } columns - The columns to query. If the value is null, the query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -4981,13 +5313,14 @@ declare namespace relationalStore { * Queries data in the database based on specified conditions. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified query condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified query condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -4997,14 +5330,15 @@ declare namespace relationalStore { * Queries data in the database based on specified conditions. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified query condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified query condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi @@ -5017,14 +5351,16 @@ declare namespace relationalStore { * Queries data in the database based on specified conditions. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified query condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. - * @param { Array } columns - The columns to query. If the value is empty array, the query applies to all columns. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified query condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. + * @param { Array } columns - + * The columns to query. If the value is empty array, the query applies to all columns. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -5034,15 +5370,17 @@ declare namespace relationalStore { * Queries data in the database based on specified conditions. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified query condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. - * @param { Array } columns - The columns to query. If the value is empty array, the query applies to all columns. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified query condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. + * @param { Array } columns - + * The columns to query. If the value is empty array, the query applies to all columns. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi @@ -5050,24 +5388,25 @@ declare namespace relationalStore { * @since 12 */ query( - table: string, - predicates: dataSharePredicates.DataSharePredicates, - columns: Array, - callback: AsyncCallback + table: string, + predicates: dataSharePredicates.DataSharePredicates, + columns: Array, + callback: AsyncCallback ): void; /** * Queries data in the database based on specified conditions. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified query condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified query condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { Array } columns - The columns to query. If the value is null, the query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @StageModelOnly @@ -5077,15 +5416,16 @@ declare namespace relationalStore { * Queries data in the database based on specified conditions. * * @param { string } table - Indicates the target table. - * @param { dataSharePredicates.DataSharePredicates } predicates - The specified query condition by the instance object - * of {@link dataSharePredicates.DataSharePredicates}. + * @param { dataSharePredicates.DataSharePredicates } predicates - + * The specified query condition by the instance object of {@link dataSharePredicates.DataSharePredicates}. * @param { Array } columns - The columns to query. If the value is null, the query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi @@ -5093,21 +5433,23 @@ declare namespace relationalStore { * @since 12 */ query( - table: string, - predicates: dataSharePredicates.DataSharePredicates, - columns?: Array + table: string, + predicates: dataSharePredicates.DataSharePredicates, + columns?: Array ): Promise; /** * Queries data in the database based on specified conditions with sync function. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to query. If the value is empty array, the query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - + * The columns to query. If the value is empty array, the query applies to all columns. * @returns { ResultSet } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -5135,7 +5477,7 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -5147,7 +5489,8 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -5159,7 +5502,8 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -5172,12 +5516,13 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -5189,7 +5534,8 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -5201,7 +5547,8 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -5214,12 +5561,13 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -5231,12 +5579,13 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement with sync interface. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @returns { ResultSet } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform @@ -5250,12 +5599,15 @@ declare namespace relationalStore { * @param { string } table - Indicates the name of the table to check. * @param { string } columnName - Indicates the name of the column to check. * @param { PRIKeyType[] } primaryKeys - Indicates the primary keys of the rows to check. - * @returns { Promise } -The promise returned by the function. ModifyTime indicates the modify time of current row. + * @returns { Promise } - + * The promise returned by the function. ModifyTime indicates the modify time of current row. * If this table does not support cloud, the {@link ModifyTime} will be empty. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 3 - 4 parameter(s)! 2. The RdbStore must be not nullptr. - * 3. The tablesNames must be not empty string. 4. The columnName must be not empty string. 5. The PRIKey must be number or string. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 3 - 4 parameter(s)! 2. The RdbStore must be not nullptr. + * 3. The tablesNames must be not empty string. 4. The columnName must be not empty string. + * 5. The PRIKey must be number or string. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 10 */ @@ -5265,16 +5617,20 @@ declare namespace relationalStore { * @param { string } table - Indicates the name of the table to check. * @param { string } columnName - Indicates the name of the column to check. * @param { PRIKeyType[] } primaryKeys - Indicates the primary keys of the rows to check. - * @returns { Promise } -The promise returned by the function. ModifyTime indicates the modify time of current row. + * @returns { Promise } - + * The promise returned by the function. ModifyTime indicates the modify time of current row. * If this table does not support cloud, the {@link ModifyTime} will be empty. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 3 - 4 parameter(s)! 2. The RdbStore must be not nullptr. - * 3. The tablesNames must be not empty string. 4. The columnName must be not empty string. 5. The PRIKey must be number or string. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 3 - 4 parameter(s)! 2. The RdbStore must be not nullptr. + * 3. The tablesNames must be not empty string. 4. The columnName must be not empty string. + * 5. The PRIKey must be number or string. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5299,12 +5655,15 @@ declare namespace relationalStore { * @param { string } table - Indicates the name of the table to check. * @param { string } columnName - Indicates the name of the column to check. * @param { PRIKeyType[] } primaryKeys - Indicates the primary keys of the rows to check. - * @param { AsyncCallback } callback - The callback of getModifyTime. ModifyTime indicates the modify time of current row. + * @param { AsyncCallback } callback - + * The callback of getModifyTime. ModifyTime indicates the modify time of current row. * If this table does not support cloud, the {@link ModifyTime} will be empty. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 3 - 4 parameter(s)! 2. The RdbStore must be not nullptr. - * 3. The tablesNames must be not empty string. 4. The columnName must be not empty string. 5. The PRIKey must be number or string. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 3 - 4 parameter(s)! 2. The RdbStore must be not nullptr. + * 3. The tablesNames must be not empty string. 4. The columnName must be not empty string. + * 5. The PRIKey must be number or string. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 10 */ @@ -5314,16 +5673,20 @@ declare namespace relationalStore { * @param { string } table - Indicates the name of the table to check. * @param { string } columnName - Indicates the name of the column to check. * @param { PRIKeyType[] } primaryKeys - Indicates the primary keys of the rows to check. - * @param { AsyncCallback } callback - The callback of getModifyTime. ModifyTime indicates the modify time of current row. + * @param { AsyncCallback } callback - + * The callback of getModifyTime. ModifyTime indicates the modify time of current row. * If this table does not support cloud, the {@link ModifyTime} will be empty. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 3 - 4 parameter(s)! 2. The RdbStore must be not nullptr. - * 3. The tablesNames must be not empty string. 4. The columnName must be not empty string. 5. The PRIKey must be number or string. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 3 - 4 parameter(s)! 2. The RdbStore must be not nullptr. + * 3. The tablesNames must be not empty string. 4. The columnName must be not empty string. + * 5. The PRIKey must be number or string. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5341,10 +5704,10 @@ declare namespace relationalStore { * @since 12 */ getModifyTime( - table: string, - columnName: string, - primaryKeys: PRIKeyType[], - callback: AsyncCallback + table: string, + columnName: string, + primaryKeys: PRIKeyType[], + callback: AsyncCallback ): void; /** @@ -5357,7 +5720,8 @@ declare namespace relationalStore { * @param { AsyncCallback } callback - Indicates the callback invoked to return the result. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The tablesNames must be not empty string. 4. The cursor must be valid cursor. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 11 @@ -5370,14 +5734,16 @@ declare namespace relationalStore { * @param { string } table - Indicates the name of the table to check. * @param { number } cursor - Indicates the position of the data to be cleaned up. * @param { AsyncCallback } callback - Indicates the callback invoked to return the result. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The tablesNames must be not empty string. 4. The cursor must be valid cursor. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5403,7 +5769,8 @@ declare namespace relationalStore { * @param { AsyncCallback } callback - The callback of clean. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The tablesNames must be not empty string. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 11 @@ -5413,14 +5780,16 @@ declare namespace relationalStore { * * @param { string } table - Indicates the name of the table to check. * @param { AsyncCallback } callback - The callback of clean. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s). 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s). 2. The RdbStore must be not nullptr. * 3. The tablesNames must be not empty string. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5450,7 +5819,8 @@ declare namespace relationalStore { * @returns { Promise } -The promise returned by the function. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The tablesNames must be not empty string. 4. The cursor must be valid cursor. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 11 @@ -5464,14 +5834,16 @@ declare namespace relationalStore { * @param { string } table - Indicates the name of the table to check. * @param { number } [cursor] - Indicates the cursor. * @returns { Promise } -The promise returned by the function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The tablesNames must be not empty string. 4. The cursor must be valid cursor. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5493,13 +5865,15 @@ declare namespace relationalStore { /** * Obtains sharing resource of rows corresponding to the predicates. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } [columns] - The specified columns to query. * @returns { Promise } -The promise returned by the function. * {@link ResultSet} is query result. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The predicates must be an RdbPredicates. 4. The columns must be a string array. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @systemapi @@ -5508,18 +5882,21 @@ declare namespace relationalStore { /** * Obtains sharing resource of rows corresponding to the predicates. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } [columns] - The specified columns to query. * @returns { Promise } -The promise returned by the function. * {@link ResultSet} is query result. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The predicates must be an RdbPredicates. 4. The columns must be a string array. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5542,12 +5919,14 @@ declare namespace relationalStore { /** * Obtains sharing resource of rows corresponding to the predicates. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The callback of querySharingResource. * {@link ResultSet} is query result. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The predicates must be an RdbPredicates. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @systemapi @@ -5556,17 +5935,20 @@ declare namespace relationalStore { /** * Obtains sharing resource of rows corresponding to the predicates. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { AsyncCallback } callback - The callback of querySharingResource. * {@link ResultSet} is query result. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The predicates must be an RdbPredicates. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5589,13 +5971,15 @@ declare namespace relationalStore { /** * Obtains sharing resource of rows corresponding to the predicates. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } columns - The specified columns to query. * @param { AsyncCallback } callback - The callback of querySharingResource. * {@link ResultSet} is query result. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The predicates must be an RdbPredicates. 4. The columns must be a string array. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @systemapi @@ -5604,18 +5988,21 @@ declare namespace relationalStore { /** * Obtains sharing resource of rows corresponding to the predicates. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } columns - The specified columns to query. * @param { AsyncCallback } callback - The callback of querySharingResource. * {@link ResultSet} is query result. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be not nullptr. * 3. The predicates must be an RdbPredicates. 4. The columns must be a string array. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5657,10 +6044,11 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5685,7 +6073,8 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters but returns no value. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @param { AsyncCallback } callback - The callback of executeSql. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -5697,7 +6086,8 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters but returns no value. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @param { AsyncCallback } callback - The callback of executeSql. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; @@ -5711,16 +6101,18 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters but returns no value. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @param { AsyncCallback } callback - The callback of executeSql. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5745,7 +6137,8 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters but returns no value. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -5757,7 +6150,8 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters but returns no value. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; @@ -5771,16 +6165,18 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters but returns no value. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } bindArgs - + * Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5805,16 +6201,18 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters and returns a value of ValueType. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. + * The values are strings. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5839,16 +6237,18 @@ declare namespace relationalStore { * * @param { string } sql - Indicates the SQL statement to execute. * @param { number } txId - Indicates the transaction ID which is obtained by beginTrans or 0. - * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. + * The values are strings. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5872,15 +6272,17 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters and returns a value of ValueType with sync interface. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. + * The values are strings. * @returns { ValueType } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5924,10 +6326,11 @@ declare namespace relationalStore { * * @throws { BusinessError } 401 - Parameter error. The store must not be nullptr. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5955,10 +6358,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. The store must not be nullptr. * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -5998,10 +6402,11 @@ declare namespace relationalStore { * * @throws { BusinessError } 401 - Parameter error. The store must not be nullptr. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6028,11 +6433,12 @@ declare namespace relationalStore { * @returns { Promise } Promise used to return the result. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. - * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6071,10 +6477,11 @@ declare namespace relationalStore { * * @throws { BusinessError } 401 - Parameter error. The store must not be nullptr. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6100,11 +6507,12 @@ declare namespace relationalStore { * @param { number } txId - Indicates the transaction ID which is obtained by beginTrans. * @returns { Promise } Promise used to return the result. * @throws { BusinessError } 401 - Parameter error. The store must not be nullptr. - * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6153,11 +6561,12 @@ declare namespace relationalStore { * @param { AsyncCallback } callback - The callback of backup. * @throws { BusinessError } 401 - Parameter error. The store must not be nullptr. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6208,10 +6617,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6262,10 +6672,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6316,10 +6727,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6343,13 +6755,15 @@ declare namespace relationalStore { * Restores a database from a specified database file. * * @returns { Promise } The promise returned by the function. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -6392,7 +6806,7 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -6421,7 +6835,7 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -6455,7 +6869,7 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800051 - The type of the distributed table does not match. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 @@ -6469,7 +6883,8 @@ declare namespace relationalStore { * @param { Array } tables - Indicates the table names you want to set. * @param { DistributedType } type - Indicates the distributed type {@link DistributedType}. * This method only works when type equals to DistributedType.DISTRIBUTED_CLOUD - * @param { DistributedConfig } config - Indicates the distributed config of the tables. For details, see {@link DistributedConfig}. + * @param { DistributedConfig } config - + * Indicates the distributed config of the tables. For details, see {@link DistributedConfig}. * @param { AsyncCallback } callback - The callback of setDistributedTables. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -6486,22 +6901,23 @@ declare namespace relationalStore { * @param { Array } tables - Indicates the table names you want to set. * @param { DistributedType } type - Indicates the distributed type {@link DistributedType}. * ohos.permission.DISTRIBUTED_DATASYNC is required only when type is DISTRIBUTED_DEVICE. - * @param { DistributedConfig } config - Indicates the distributed config of the tables. For details, see {@link DistributedConfig}. + * @param { DistributedConfig } config - + * Indicates the distributed config of the tables. For details, see {@link DistributedConfig}. * @param { AsyncCallback } callback - The callback of setDistributedTables. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800051 - The type of the distributed table does not match. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ setDistributedTables( - tables: Array, - type: DistributedType, - config: DistributedConfig, - callback: AsyncCallback + tables: Array, + type: DistributedType, + config: DistributedConfig, + callback: AsyncCallback ): void; /** @@ -6511,7 +6927,8 @@ declare namespace relationalStore { * @param { Array } tables - Indicates the table names you want to set. * @param { DistributedType } type - Indicates the distributed type {@link DistributedType}. * This method only works when type equals to DistributedType.DISTRIBUTED_CLOUD - * @param { DistributedConfig } config - Indicates the distributed config of the tables. For details, see {@link DistributedConfig}. + * @param { DistributedConfig } config - + * Indicates the distributed config of the tables. For details, see {@link DistributedConfig}. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -6528,13 +6945,14 @@ declare namespace relationalStore { * @param { Array } tables - Indicates the table names you want to set. * @param { DistributedType } type - Indicates the distributed type {@link DistributedType}. * ohos.permission.DISTRIBUTED_DATASYNC is required only when type is DISTRIBUTED_DEVICE. - * @param { DistributedConfig } config - Indicates the distributed config of the tables. For details, see {@link DistributedConfig}. + * @param { DistributedConfig } config - + * Indicates the distributed config of the tables. For details, see {@link DistributedConfig}. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800051 - The type of the distributed table does not match. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 @@ -6568,7 +6986,7 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -6601,7 +7019,7 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -6612,10 +7030,12 @@ declare namespace relationalStore { * * @permission ohos.permission.DISTRIBUTED_DATASYNC * @param { SyncMode } mode - Indicates the database synchronization mode. - * @param { RdbPredicates } predicates - The specified sync condition by the instance object of {@link RdbPredicates}. - * @param { AsyncCallback> } callback - {Array<[string, number]>}: devices sync status array, - * {string}: device id, - * {number}: device sync status. + * @param { RdbPredicates } predicates - + * The specified sync condition by the instance object of {@link RdbPredicates}. + * @param { AsyncCallback> } callback - + * {Array<[string, number]>}: devices sync status array, + * {string}: device id, + * {number}: device sync status. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. @@ -6628,15 +7048,17 @@ declare namespace relationalStore { * * @permission ohos.permission.DISTRIBUTED_DATASYNC * @param { SyncMode } mode - Indicates the database synchronization mode. - * @param { RdbPredicates } predicates - The specified sync condition by the instance object of {@link RdbPredicates}. - * @param { AsyncCallback> } callback - {Array<[string, number]>}: devices sync status array, - * {string}: device id, - * {number}: device sync status. + * @param { RdbPredicates } predicates - + * The specified sync condition by the instance object of {@link RdbPredicates}. + * @param { AsyncCallback> } callback - + * {Array<[string, number]>}: devices sync status array, + * {string}: device id, + * {number}: device sync status. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -6647,8 +7069,10 @@ declare namespace relationalStore { * * @permission ohos.permission.DISTRIBUTED_DATASYNC * @param { SyncMode } mode - Indicates the database synchronization mode. - * @param { RdbPredicates } predicates - The specified sync condition by the instance object of {@link RdbPredicates}. - * @returns { Promise> } {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @param { RdbPredicates } predicates - + * The specified sync condition by the instance object of {@link RdbPredicates}. + * @returns { Promise> } + * {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. @@ -6661,13 +7085,15 @@ declare namespace relationalStore { * * @permission ohos.permission.DISTRIBUTED_DATASYNC * @param { SyncMode } mode - Indicates the database synchronization mode. - * @param { RdbPredicates } predicates - The specified sync condition by the instance object of {@link RdbPredicates}. - * @returns { Promise> } {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @param { RdbPredicates } predicates - + * The specified sync condition by the instance object of {@link RdbPredicates}. + * @returns { Promise> } + * {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -6677,10 +7103,14 @@ declare namespace relationalStore { * Sync data to cloud. * * @param { SyncMode } mode - indicates the database synchronization mode. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. - * @param { AsyncCallback } callback - {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The progress must be a callback type. 5. The callback must be a function. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. + * @param { AsyncCallback } callback - + * {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The progress must be a callback type. + * 5. The callback must be a function. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 10 @@ -6689,12 +7119,16 @@ declare namespace relationalStore { * Sync data to cloud. * * @param { SyncMode } mode - indicates the database synchronization mode. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. - * @param { AsyncCallback } callback - {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The progress must be a callback type. 5. The callback must be a function. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. + * @param { AsyncCallback } callback - + * {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The progress must be a callback type. + * 5. The callback must be a function. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 12 */ @@ -6704,9 +7138,11 @@ declare namespace relationalStore { * Sync data to cloud. * * @param { SyncMode } mode - indicates the database synchronization mode. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. * @returns { Promise } : devices sync status array, {string}: device id, {number}: device sync status. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. * 3. The mode must be a SyncMode of cloud. 4. The progress must be a callback type. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client @@ -6716,12 +7152,14 @@ declare namespace relationalStore { * Sync data to cloud. * * @param { SyncMode } mode - indicates the database synchronization mode. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. * @returns { Promise } : devices sync status array, {string}: device id, {number}: device sync status. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. * 3. The mode must be a SyncMode of cloud. 4. The progress must be a callback type. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 12 */ @@ -6732,11 +7170,14 @@ declare namespace relationalStore { * * @param { SyncMode } mode - indicates the database synchronization mode. * @param { string[] } tables - indicates the database synchronization mode. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. - * @param { AsyncCallback } callback - {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. 5. The progress must be a callback type. - * 6. The callback must be a function. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. + * @param { AsyncCallback } callback - + * {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. + * 5. The progress must be a callback type. 6. The callback must be a function. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 10 @@ -6746,21 +7187,24 @@ declare namespace relationalStore { * * @param { SyncMode } mode - indicates the database synchronization mode. * @param { string[] } tables - indicates the database synchronization mode. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. - * @param { AsyncCallback } callback - {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. 5. The progress must be a callback type. - * 6. The callback must be a function. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. + * @param { AsyncCallback } callback - + * {Array<[string, number]>}: devices sync status array, {string}: device id, {number}: device sync status. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. + * 5. The progress must be a callback type. 6. The callback must be a function. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 12 */ cloudSync( - mode: SyncMode, - tables: string[], - progress: Callback, - callback: AsyncCallback + mode: SyncMode, + tables: string[], + progress: Callback, + callback: AsyncCallback ): void; /** @@ -6768,10 +7212,13 @@ declare namespace relationalStore { * * @param { SyncMode } mode - indicates the database synchronization mode. * @param { string[] } tables - indicates the database synchronization mode. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. * @returns { Promise } : devices sync status array, {string}: device id, {number}: device sync status. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. 5. The progress must be a callback type. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. + * 5. The progress must be a callback type. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 10 @@ -6781,12 +7228,15 @@ declare namespace relationalStore { * * @param { SyncMode } mode - indicates the database synchronization mode. * @param { string[] } tables - indicates the database synchronization mode. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. * @returns { Promise } : devices sync status array, {string}: device id, {number}: device sync status. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. 5. The progress must be a callback type. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. + * 5. The progress must be a callback type. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 12 */ @@ -6796,13 +7246,17 @@ declare namespace relationalStore { * Sync data to cloud. * * @param { SyncMode } mode - indicates the database synchronization mode. - * @param { RdbPredicates } predicates - The specified sync condition by the instance object of {@link RdbPredicates}. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. + * @param { RdbPredicates } predicates - + * The specified sync condition by the instance object of {@link RdbPredicates}. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. * @param { AsyncCallback } callback - The callback of cloudSync. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. 5. The progress must be a callback type. - * 6. The callback must be a function. - * @throws { BusinessError } 202 - if permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. + * 5. The progress must be a callback type. 6. The callback must be a function. + * @throws { BusinessError } 202 - + * if permission verification failed, application which is not a system application uses system API. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @systemapi @@ -6812,35 +7266,43 @@ declare namespace relationalStore { * Sync data to cloud. * * @param { SyncMode } mode - indicates the database synchronization mode. - * @param { RdbPredicates } predicates - The specified sync condition by the instance object of {@link RdbPredicates}. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. + * @param { RdbPredicates } predicates - + * The specified sync condition by the instance object of {@link RdbPredicates}. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. * @param { AsyncCallback } callback - The callback of cloudSync. - * @throws { BusinessError } 202 - if permission verification failed, application which is not a system application uses system API. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. 5. The progress must be a callback type. - * 6. The callback must be a function. + * @throws { BusinessError } 202 - + * if permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. + * 5. The progress must be a callback type. 6. The callback must be a function. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @systemapi * @since 12 */ cloudSync( - mode: SyncMode, - predicates: RdbPredicates, - progress: Callback, - callback: AsyncCallback + mode: SyncMode, + predicates: RdbPredicates, + progress: Callback, + callback: AsyncCallback ): void; /** * Sync data to cloud. * * @param { SyncMode } mode - indicates the database synchronization mode. - * @param { RdbPredicates } predicates - The specified sync condition by the instance object of {@link RdbPredicates}. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. + * @param { RdbPredicates } predicates - + * The specified sync condition by the instance object of {@link RdbPredicates}. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. * @returns { Promise } : The promise returned by the function. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. 5. The progress must be a callback type. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. + * 5. The progress must be a callback type. * @throws { BusinessError } 202 - if permission verification failed, application which is not a system * application uses system API. * @throws { BusinessError } 801 - Capability not supported. @@ -6852,15 +7314,19 @@ declare namespace relationalStore { * Sync data to cloud. * * @param { SyncMode } mode - indicates the database synchronization mode. - * @param { RdbPredicates } predicates - The specified sync condition by the instance object of {@link RdbPredicates}. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. + * @param { RdbPredicates } predicates - + * The specified sync condition by the instance object of {@link RdbPredicates}. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. * @returns { Promise } : The promise returned by the function. * @throws { BusinessError } 202 - if permission verification failed, application which is not a system * application uses system API. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. - * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. 5. The progress must be a callback type. + * @throws { BusinessError } 401 - Parameter error. + * Possible causes: 1. Need 2 - 4 parameter(s). 2. The RdbStore must be not nullptr. + * 3. The mode must be a SyncMode of cloud. 4. The tablesNames must be not empty. + * 5. The progress must be a callback type. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @systemapi * @since 12 @@ -6872,8 +7338,10 @@ declare namespace relationalStore { * * @param { string } device - Indicates specified remote device. * @param { string } table - Indicates the target table. - * @param { RdbPredicates } predicates - The specified remote remote query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to remote query. If the value is empty array, the remote query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified remote remote query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - The columns to remote query. + * If the value is empty array, the remote query applies to all columns. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -6887,23 +7355,25 @@ declare namespace relationalStore { * * @param { string } device - Indicates specified remote device. * @param { string } table - Indicates the target table. - * @param { RdbPredicates } predicates - The specified remote remote query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to remote query. If the value is empty array, the remote query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified remote remote query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - The columns to remote query. + * If the value is empty array, the remote query applies to all columns. * @param { AsyncCallback } callback - The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ remoteQuery( - device: string, - table: string, - predicates: RdbPredicates, - columns: Array, - callback: AsyncCallback + device: string, + table: string, + predicates: RdbPredicates, + columns: Array, + callback: AsyncCallback ): void; /** @@ -6911,8 +7381,10 @@ declare namespace relationalStore { * * @param { string } device - Indicates specified remote device. * @param { string } table - Indicates the target table. - * @param { RdbPredicates } predicates - The specified remote remote query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to remote query. If the value is empty array, the remote query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified remote remote query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - The columns to remote query. + * If the value is empty array, the remote query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -6926,27 +7398,30 @@ declare namespace relationalStore { * * @param { string } device - Indicates specified remote device. * @param { string } table - Indicates the target table. - * @param { RdbPredicates } predicates - The specified remote remote query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to remote query. If the value is empty array, the remote query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified remote remote query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - The columns to remote query. + * If the value is empty array, the remote query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ remoteQuery(device: string, table: string, predicates: RdbPredicates, columns: Array): Promise; /** - * Registers an observer for the database. When data in the distributed database changes, - * the callback will be invoked. + * Subscribes to data changes of this RDB store. + * The registered callback will be called when data in a distributed RDB store changes. * * @param { 'dataChange' } event - Indicates the event must be string 'dataChange'. * @param { SubscribeType } type - Indicates the subscription type, which is defined in {@link SubscribeType}. * If its value is SUBSCRIBE_TYPE_REMOTE, ohos.permission.DISTRIBUTED_DATASYNC is required. - * @param { Callback> } observer - {Array}: the observer of data change events in the distributed database. + * @param { Callback> } observer - + * {Array}: the observer of data change events in the distributed database. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. @@ -6954,43 +7429,47 @@ declare namespace relationalStore { * @since 9 */ /** - * Registers an observer for the database. When data in the distributed database changes, + * Subscribes to data changes of this RDB store. + * The registered callback will be called when data in a distributed RDB store changes. * the callback will be invoked. * * @param { 'dataChange' } event - Indicates the event must be string 'dataChange'. * @param { SubscribeType } type - Indicates the subscription type, which is defined in {@link SubscribeType}. * If its value is SUBSCRIBE_TYPE_REMOTE, ohos.permission.DISTRIBUTED_DATASYNC is required. - * @param { Callback> } observer - {Array}: the observer of data change events in the distributed database. + * @param { Callback> } observer - + * {Array}: the observer of data change events in the distributed database. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ on(event: 'dataChange', type: SubscribeType, observer: Callback>): void; /** - * Registers an observer for the database. When data in the distributed database or the local database changes, - * the callback will be invoked. + * Subscribes to data changes of this RDB store. + * The registered callback will be called when data in a distributed RDB store changes. * * @param { 'dataChange' } event - Indicates the event must be string 'dataChange'. * @param { SubscribeType } type - Indicates the subscription type, which is defined in {@link SubscribeType}. * If its value is SUBSCRIBE_TYPE_REMOTE, ohos.permission.DISTRIBUTED_DATASYNC is required. - * If its value is SUBSCRIBE_TYPE_LOCAL_DETAILS, the callback will be invoked for data changes in the local database. + * If its value is SUBSCRIBE_TYPE_LOCAL_DETAILS, + * the callback will be invoked for data changes in the local database. * @param { Callback> | Callback> } observer * {Array}: The observer of data change events in the distributed database. * {Array}: The change info of data change events in the distributed database or the local database. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 10 */ /** - * Registers an observer for the database. When data in the distributed database changes, - * the callback will be invoked. + * Subscribes to data changes of this RDB store. + * The registered callback will be called when data in a distributed RDB store changes. * * @param { 'dataChange' } event - Indicates the event must be string 'dataChange'. * @param { SubscribeType } type - Indicates the subscription type, which is defined in {@link SubscribeType}. @@ -6998,11 +7477,12 @@ declare namespace relationalStore { * @param { Callback> | Callback> } observer * {Array}: The observer of data change events in the distributed database. * {Array}: The change info of data change events in the distributed database. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -7011,8 +7491,9 @@ declare namespace relationalStore { /** * Registers an observer for the database. * - * @param { string } event - Indicates the subscription event. - * @param { boolean } interProcess - Indicates whether it is an interprocess subscription or an in-process subscription. + * @param { string } event - Event type, which must match the event type in {@link emit}. + * @param { boolean } interProcess - + * Indicates whether it is an interprocess subscription or an in-process subscription. * @param { Callback } observer - The observer of data change events in the database. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -7025,14 +7506,15 @@ declare namespace relationalStore { /** * Registers an observer for the database. * - * @param { string } event - Indicates the subscription event. - * @param { boolean } interProcess - Indicates whether it is an interprocess subscription or an in-process subscription. + * @param { string } event - Event type, which must match the event type in {@link emit}. + * @param { boolean } interProcess - + * Indicates whether it is an interprocess subscription or an in-process subscription. * @param { Callback } observer - The observer of data change events in the database. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800050 - Failed to obtain the subscription service. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 @@ -7043,8 +7525,10 @@ declare namespace relationalStore { * Register an automatic synchronization callback to the database. * * @param { 'autoSyncProgress' } event - Indicates the event must be string 'autoSyncProgress'. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 3 parameter(s)! 2. The RdbStore must be valid. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 2 - 3 parameter(s)! 2. The RdbStore must be valid. * 3. The event must be a not empty string. 4. The progress must be function. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core @@ -7054,11 +7538,13 @@ declare namespace relationalStore { * Register an automatic synchronization callback to the database. * * @param { 'autoSyncProgress' } event - Indicates the event must be string 'autoSyncProgress'. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 2 - 3 parameter(s)! 2. The RdbStore must be valid. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 2 - 3 parameter(s)! 2. The RdbStore must be valid. * 3. The event must be a not empty string. 4. The progress must be function. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -7067,16 +7553,42 @@ declare namespace relationalStore { /** * Subscribes to the SQL statistics. * @param { 'statistics' } event - Indicates the event type, which must be 'statistics'. - * @param { Callback } observer - Indicates the callback used to return the SQL execution statistics {@link SqlExeInfo} in the database. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1.Mandatory parameters are left unspecified; 2.Incorrect parameter types. + * @param { Callback } observer - + * Indicates the callback used to return the SQL execution statistics {@link SqlExeInfo} in the database. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Mandatory parameters are left unspecified; 2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ on(event: 'statistics', observer: Callback ): void; + /** + * Subscribes to the SQL execution error logs. + * @param { 'sqliteErrorOccurred' } event - Event type, which must be 'sqliteErrorOccurred'. + * @param { Callback } observer - Callback used to return the SQL execution error log {@link ExceptionMessage}. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + on(event: 'sqliteErrorOccurred', observer: Callback ): void; + + /** + * Subscribes to the SQL performance statistics. + * @param { 'perfStat' } event - Event type, which must be 'perfStat'. + * @param { Callback } observer - Callback used to return the SQL execution statistics {@link SqlExecutionInfo}. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + on(event: 'perfStat', observer: Callback): void; + /** * Remove specified observer of specified type from the database. * @@ -7100,7 +7612,7 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -7112,11 +7624,13 @@ declare namespace relationalStore { * @param { 'dataChange' } event - indicates the event must be string 'dataChange'. * @param { SubscribeType } type - indicates the subscription type, which is defined in {@link SubscribeType}. * If its value is SUBSCRIBE_TYPE_REMOTE, ohos.permission.DISTRIBUTED_DATASYNC is required. - * @param { Callback> | Callback> } observer - {Array}: the data change observer already registered. + * @param { Callback> | Callback> } observer - + * {Array}: the data change observer already registered. * {Array}: the change info already registered. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 10 @@ -7127,27 +7641,30 @@ declare namespace relationalStore { * @param { 'dataChange' } event - indicates the event must be string 'dataChange'. * @param { SubscribeType } type - indicates the subscription type, which is defined in {@link SubscribeType}. * If its value is SUBSCRIBE_TYPE_REMOTE, ohos.permission.DISTRIBUTED_DATASYNC is required. - * @param { Callback> | Callback> } observer - {Array}: the data change observer already registered. + * @param { Callback> | Callback> } observer - + * {Array}: the data change observer already registered. * {Array}: the change info already registered. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ off( - event: 'dataChange', - type: SubscribeType, - observer?: Callback> | Callback> + event: 'dataChange', + type: SubscribeType, + observer?: Callback> | Callback> ): void; /** * Remove specified observer of specified type from the database. * * @param { string } event - Indicates the subscription event. - * @param { boolean } interProcess - Indicates whether it is an interprocess subscription or an in-process subscription. + * @param { boolean } interProcess - + * Indicates whether it is an interprocess subscription or an in-process subscription. * @param { Callback } observer - The data change observer already registered. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -7161,13 +7678,14 @@ declare namespace relationalStore { * Remove specified observer of specified type from the database. * * @param { string } event - Indicates the subscription event. - * @param { boolean } interProcess - Indicates whether it is an interprocess subscription or an in-process subscription. + * @param { boolean } interProcess - + * Indicates whether it is an interprocess subscription or an in-process subscription. * @param { Callback } observer - The data change observer already registered. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800050 - Failed to obtain the subscription service. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 @@ -7178,8 +7696,10 @@ declare namespace relationalStore { * Unregister the database auto synchronization callback. * * @param { 'autoSyncProgress' } event - indicates the event must be string 'autoSyncProgress'. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be valid. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be valid. * 3. The event must be a not empty string. 4. The progress must be function. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core @@ -7189,11 +7709,13 @@ declare namespace relationalStore { * Unregister the database auto synchronization callback. * * @param { 'autoSyncProgress' } event - indicates the event must be string 'autoSyncProgress'. - * @param { Callback } progress - the specified sync condition by the instance object of {@link ProgressDetails}. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be valid. + * @param { Callback } progress - + * Callback used to return the {@link ProgressDetails} result. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + * 1. Need 1 - 3 parameter(s)! 2. The RdbStore must be valid. * 3. The event must be a not empty string. 4. The progress must be function. * @throws { BusinessError } 801 - Capability not supported. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ @@ -7206,12 +7728,36 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 */ off(event: 'statistics', observer?: Callback ): void; + /** + * Unsubscribes from the SQL execution error logs. + * @param { 'sqliteErrorOccurred' } event - Indicates the event type, which must be 'sqliteErrorOccurred'. + * @param { Callback } observer - Callback to unregister. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + off(event: 'sqliteErrorOccurred', observer?: Callback ): void; + + /** + * Unsubscribes from the SQL performance statistics. + * @param { 'perfStat' } event - Event type, which must be 'perfStat'. + * @param { Callback } observer - Callback to unregister. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 20 + */ + off(event: 'perfStat', observer?: Callback): void; + /** * Notifies the registered observers of a change to the data resource specified by Uri. * @@ -7232,7 +7778,7 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800050 - Failed to obtain the subscription service. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 12 @@ -7261,12 +7807,13 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800016 - The database alias already exists. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7289,7 +7836,8 @@ declare namespace relationalStore { * Attaches a database file to the currently linked database. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @param { string } attachName - Indicates the alias of the database. * @param { number } waitTime - Indicates the maximum time allowed for attaching the database file. * @returns { Promise } Promise used to return the number of attached databases. @@ -7297,14 +7845,15 @@ declare namespace relationalStore { *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800016 - The database alias already exists. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. + * @throws { BusinessError } 14801002 - Invalid data group ID. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7332,10 +7881,11 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7357,16 +7907,18 @@ declare namespace relationalStore { /** * Locks data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified lock condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified lock condition by the instance object of {@link RdbPredicates}. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800018 - No data meets the condition. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7389,16 +7941,18 @@ declare namespace relationalStore { /** * Unlocks data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified Unlock condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified Unlock condition by the instance object of {@link RdbPredicates}. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800018 - No data meets the condition. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7421,16 +7975,18 @@ declare namespace relationalStore { /** * Queries locked data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } columns - The columns to query. If the value is null, the query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database does not respond. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7454,7 +8010,8 @@ declare namespace relationalStore { * Lock cloud container before non-auto cloud sync. * * @returns { Promise } The expired time of the lock. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @since 12 @@ -7465,7 +8022,8 @@ declare namespace relationalStore { * Unlock cloud container. * * @returns { Promise } The promise returned by the function. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, + * application which is not a system application uses system API. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @systemapi * @since 12 @@ -7478,8 +8036,8 @@ declare namespace relationalStore { * @param { TransactionOptions } options - The option for creating transactions. * @returns { Promise } The {@link Transaction} object if the operation is successful. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800015 - The database is busy. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7508,8 +8066,8 @@ declare namespace relationalStore { * * @returns { Promise } Promise used to return the result. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. @@ -7527,8 +8085,8 @@ declare namespace relationalStore { * * @returns { Promise } Promise used to return the result. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. @@ -7551,9 +8109,10 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7580,9 +8139,10 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7603,14 +8163,17 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. - * @returns { Promise } The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @returns { Promise } The number of values that were inserted if the operation is successful. + * returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7631,14 +8194,16 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. * @returns { number } The number of values that were inserted if the operation is successful. returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7659,15 +8224,18 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. - * @returns { Promise } The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @returns { Promise } The number of values that were inserted if the operation is successful. + * returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7683,7 +8251,7 @@ declare namespace relationalStore { * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform - * @since 16 + * @since 18 */ batchInsertWithConflictResolution(table: string, values: Array, conflict: ConflictResolution): Promise; @@ -7691,15 +8259,17 @@ declare namespace relationalStore { * Inserts a batch of data into the target table. * * @param { string } table - Indicates the target table. - * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param { Array } values - + * Indicates the rows of data {@link ValuesBucket} to be inserted into the table. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. * @returns { number } The number of values that were inserted if the operation is successful. returns -1 otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. @@ -7715,7 +8285,7 @@ declare namespace relationalStore { * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform - * @since 16 + * @since 18 */ batchInsertWithConflictResolutionSync(table: string, values: Array, conflict: ConflictResolution): number; @@ -7723,16 +8293,18 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. * @returns { Promise } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7753,16 +8325,18 @@ declare namespace relationalStore { * Updates data in the database based on a specified instance object of RdbPredicates with sync interface. * * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - + * Indicates the specified update condition by the instance object of {@link RdbPredicates}. * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. * @returns { number } The number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7782,14 +8356,16 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. * @returns { Promise } return the number of affected rows. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7809,14 +8385,16 @@ declare namespace relationalStore { /** * Deletes data from the database based on a specified instance object of RdbPredicates with sync interface. * - * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. - * @returns { number } return the number of affected rows. + * @param { RdbPredicates } predicates - + * The specified delete condition by the instance object of {@link RdbPredicates}. + * @returns { number } return the number of rows deleted. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7836,15 +8414,17 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. * @param { Array } columns - The columns to query. If the value is null, the query applies to all columns. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. @@ -7859,15 +8439,18 @@ declare namespace relationalStore { /** * Queries data in the database based on specified conditions with sync function. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The columns to query. If the value is empty array, the query applies to all columns. + * @param { RdbPredicates } predicates - + * The specified query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - + * The columns to query. If the value is empty array, the query applies to all columns. * @returns { ResultSet } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7884,14 +8467,16 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. + * The values are strings. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7908,14 +8493,16 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement with sync interface. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. + * The values are strings. * @returns { ResultSet } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7932,15 +8519,17 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters and returns a value of ValueType. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. + * The values are strings. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7960,15 +8549,17 @@ declare namespace relationalStore { * Executes a SQL statement that contains specified parameters and returns a value of ValueType with sync interface. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. + * The values are strings. * @returns { ValueType } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800011 - Database corrupted. - * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. + * @throws { BusinessError } 14800014 - The RdbStore or ResultSet is already closed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800024 - SQLite: The database file is locked. * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. @@ -7992,13 +8583,16 @@ declare namespace relationalStore { * to obtain a rdb store. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @param { AsyncCallback } callback - The RDB store {@link RdbStore}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. - * @throws { BusinessError } 14800011 - Failed to open database by database corrupted. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - + * Failed to open database by Failed to open the database because it is corrupted. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 */ @@ -8008,15 +8602,18 @@ declare namespace relationalStore { * to obtain a rdb store. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @param { AsyncCallback } callback - The RDB store {@link RdbStore}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. - * @throws { BusinessError } 14800011 - Failed to open database by database corrupted. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - + * Failed to open database by Failed to open the database because it is corrupted. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. + * @throws { BusinessError } 14801002 - Invalid data group ID. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 10 @@ -8027,17 +8624,19 @@ declare namespace relationalStore { * to obtain a rdb store. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @param { AsyncCallback } callback - The RDB store {@link RdbStore}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. - * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. - * @throws { BusinessError } 14800017 - Config changed. + * @throws { BusinessError } 14801002 - Invalid data group ID. + * @throws { BusinessError } 14800017 - StoreConfig is changed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. @@ -8054,18 +8653,20 @@ declare namespace relationalStore { * to obtain a rdb store. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @param { AsyncCallback } callback - The RDB store {@link RdbStore}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. - * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. - * @throws { BusinessError } 14800017 - Config changed. + * @throws { BusinessError } 14801002 - Invalid data group ID. + * @throws { BusinessError } 14800017 - StoreConfig is changed. * @throws { BusinessError } 14800020 - The secret key is corrupted or lost. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. @@ -8084,13 +8685,16 @@ declare namespace relationalStore { * to obtain a rdb store. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @returns { Promise } The RDB store {@link RdbStore}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. - * @throws { BusinessError } 14800011 - Failed to open database by database corrupted. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - + * Failed to open database by Failed to open the database because it is corrupted. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 */ @@ -8100,15 +8704,18 @@ declare namespace relationalStore { * to obtain a rdb store. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @returns { Promise } The RDB store {@link RdbStore}. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. - * @throws { BusinessError } 14800011 - Failed to open database by database corrupted. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - + * Failed to open database by Failed to open the database because it is corrupted. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. + * @throws { BusinessError } 14801002 - Invalid data group ID. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 10 @@ -8119,17 +8726,19 @@ declare namespace relationalStore { * to obtain a rdb store. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. - * @returns { Promise } The RDB store {@link RdbStore}. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @returns { Promise } Promise used to return the **RdbStore** object obtained. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. - * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. - * @throws { BusinessError } 14800017 - Config changed. + * @throws { BusinessError } 14801002 - Invalid data group ID. + * @throws { BusinessError } 14800017 - StoreConfig is changed. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. * @throws { BusinessError } 14800029 - SQLite: The database is full. @@ -8144,18 +8753,20 @@ declare namespace relationalStore { * to obtain a rdb store. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. - * @returns { Promise } The RDB store {@link RdbStore}. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @returns { Promise } Promise used to return the **RdbStore** object obtained. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. - * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. + * @throws { BusinessError } 14800011 - Failed to open the database because it is corrupted. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. - * @throws { BusinessError } 14800017 - Config changed. + * @throws { BusinessError } 14801002 - Invalid data group ID. + * @throws { BusinessError } 14800017 - StoreConfig is changed. * @throws { BusinessError } 14800020 - The secret key is corrupted or lost. * @throws { BusinessError } 14800021 - SQLite: Generic error. + * Possible causes: Insert failed or the updated data does not exist. * @throws { BusinessError } 14800022 - SQLite: Callback routine requested an abort. * @throws { BusinessError } 14800023 - SQLite: Access permission denied. * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. @@ -8178,7 +8789,8 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 */ @@ -8192,7 +8804,8 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 10 @@ -8204,14 +8817,16 @@ declare namespace relationalStore { * When specify custom directory, this function should be called. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @param { AsyncCallback } callback - The callback of deleteRdbStore. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. + * @throws { BusinessError } 14801002 - Invalid data group ID. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 10 @@ -8228,7 +8843,8 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 9 */ @@ -8242,7 +8858,8 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 10 @@ -8257,7 +8874,7 @@ declare namespace relationalStore { * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 12 @@ -8269,14 +8886,16 @@ declare namespace relationalStore { * When specify custom directory, this function should be called. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Failed to open or delete database by invalid database path. + * @throws { BusinessError } 14800010 - + * Failed to open or delete database by Failed to open or delete the database by an invalid database path. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. + * @throws { BusinessError } 14801002 - Invalid data group ID. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 10 @@ -8286,15 +8905,16 @@ declare namespace relationalStore { * When specify custom directory, this function should be called. * * @param { Context } context - Indicates the context of an application or ability. - * @param { StoreConfig } config - Indicates the {@link StoreConfig} configuration of the database related to this RDB store. + * @param { StoreConfig } config - + * Indicates the {@link StoreConfig} configuration of the database related to this RDB store. * @returns { Promise } The promise returned by the function. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. - * @throws { BusinessError } 14800010 - Invalid database path. + * @throws { BusinessError } 14800010 - Failed to open or delete the database by an invalid database path. * @throws { BusinessError } 14801001 - The operation is supported in the stage model only. - * @throws { BusinessError } 14801002 - Invalid data ground ID. + * @throws { BusinessError } 14801002 - Invalid data group ID. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 12 @@ -8306,7 +8926,7 @@ declare namespace relationalStore { * * @returns { boolean } Returns {@code true} if the vector database is supported; returns {@code false} otherwise. * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 18 */ function isVectorSupported(): boolean; @@ -8316,9 +8936,9 @@ declare namespace relationalStore { * @returns { boolean } Returns {@code true} if the tokenizer is supported; returns {@code false} otherwise. * @throws { BusinessError } 401 - Parameter error. Possible causes: Incorrect parameter types * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @since 16 + * @since 18 */ - function isTokenizerSupported(tokenizer: Tokenizer): boolean; + function isTokenizerSupported(tokenizer: Tokenizer): boolean; } export default relationalStore; diff --git a/interface_sdk/api/@ohos.data.sendablePreferences.d.ets b/interface_sdk/api/@ohos.data.sendablePreferences.d.ets index 626fbf4f..3c16c185 100644 --- a/interface_sdk/api/@ohos.data.sendablePreferences.d.ets +++ b/interface_sdk/api/@ohos.data.sendablePreferences.d.ets @@ -90,13 +90,13 @@ declare namespace sendablePreferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates information about the preferences file. For details, see {@link Options}. * @returns { Promise } Promise used to return the {@link Preferences}. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice * @since 12 @@ -112,13 +112,13 @@ declare namespace sendablePreferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates information about the preferences file. For details, see {@link Options}. * @returns { Preferences } return the {@link Preferences}. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice * @since 12 @@ -136,14 +136,14 @@ declare namespace sendablePreferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates information about the preferences file. For details, see {@link Options}. * @returns { Promise } Promise that returns no value. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15500010 - Failed to delete preferences file. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15500010 - Failed to delete the user preferences persistence file. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice * @since 12 @@ -160,13 +160,13 @@ declare namespace sendablePreferences { * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates information about the preferences file. For details, see {@link Options}. * @returns { Promise } Promise that returns no value. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice * @since 12 @@ -182,13 +182,13 @@ declare namespace sendablePreferences { * * @param { Context } context - Indicates the context of application or capability. * @param { Options } options - Indicates information about the preferences file. For details, see {@link Options}. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15501001 - Only supported in stage mode. - * @throws { BusinessError } 15501002 - The data group id is not valid. + * @throws { BusinessError } 15501001 - The operations is supported in stage mode only. + * @throws { BusinessError } 15501002 - Invalid dataGroupId. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice * @since 12 @@ -213,13 +213,13 @@ declare namespace sendablePreferences { *

If the value is {@code null} or not in the lang.ISendable format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { lang.ISendable } defValue - Indicates the default value to return. - * @returns { Promise } Promise used to return the result. If a value matching the specified key + * @returns { Promise } Promise used to return the result. If a value matching the specified key * is found, the value is returned. Otherwise, the default value is returned. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -232,13 +232,13 @@ declare namespace sendablePreferences { *

If the value is {@code null} or not in the lang.ISendable format, the default value is returned. * * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { lang.ISendable } defValue - Indicates the default value to return. * @returns { lang.ISendable } If a value matching the specified key is found, the value is returned. Otherwise, * the default value is returned. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -272,12 +272,12 @@ declare namespace sendablePreferences { * Checks whether the {@link Preferences} instance contains a value matching the specified key. * * @param { string } key - Indicates the key of the value to check. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { Promise } Promise used to return the result. {@code true} is returned if the * {@link Preferences} object contains a value matching the specified key; {@code false} is returned otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -290,12 +290,12 @@ declare namespace sendablePreferences { * This API returns the result synchronously. * * @param { string } key - Indicates the key of the value to check. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { boolean } {@code true} is returned if the {@link Preferences} object contains a value matching * the specified key; {@code false} is returned otherwise. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -308,13 +308,13 @@ declare namespace sendablePreferences { *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to set. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { lang.ISendable } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. + * MAX_VALUE_LENGTH. * @returns { Promise } Promise that returns no value. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -324,16 +324,16 @@ declare namespace sendablePreferences { /** * Sets an lang.ISendable value for the key in the {@link Preferences} object. - * This API returns the result synchronously. + * This API returns the result synchronously. *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to set. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @param { lang.ISendable } value - Indicates the value of the preferences. - * MAX_VALUE_LENGTH. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_VALUE_LENGTH. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -346,11 +346,11 @@ declare namespace sendablePreferences { *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. + * MAX_KEY_LENGTH. * @returns { Promise } Promise that returns no value. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -364,10 +364,10 @@ declare namespace sendablePreferences { *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. - * MAX_KEY_LENGTH. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * MAX_KEY_LENGTH. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -388,7 +388,7 @@ declare namespace sendablePreferences { clear(): Promise; /** - * Clears all preferences from the {@link Preferences} object. This API returns the result synchronously. + * Clears all preferences from the {@link Preferences} object. This API returns the result synchronously. *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. * * @throws { BusinessError } 15500000 - Inner error. @@ -409,14 +409,24 @@ declare namespace sendablePreferences { */ flush(): Promise; + /** + * Flushes the {@link Preferences} object to the file. + * + * @throws { BusinessError } 15500000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @atomicservice + * @since 14 + */ + flushSync(): void; + /** * Registers an observer to listen for the change of a {@link Preferences} object. * * @param { 'change' } type - Indicates the type of the event to observe. * @param { Callback } callback - Indicates the callback used to return the preferences changes. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -430,11 +440,11 @@ declare namespace sendablePreferences { * @param { 'multiProcessChange' } type - Indicates the type of the event to observe. * @param { Callback } callback - Indicates the callback used to return the preferences changed * in multiple processes. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. - * @throws { BusinessError } 15500019 - Failed to obtain subscription service. + * @throws { BusinessError } 15500019 - Failed to obtain the subscription service. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice * @since 12 @@ -447,9 +457,9 @@ declare namespace sendablePreferences { * @param { 'dataChange' } type - Indicates the type of the event to observe. * @param { Array } keys - Indicates one or more keys to listen for. * @param { Callback } callback - Indicates the callback used to return the data change. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -462,9 +472,9 @@ declare namespace sendablePreferences { * * @param { 'change' } type - Indicates the event type. * @param { Callback } callback - Indicates the callback to unregister. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -477,9 +487,9 @@ declare namespace sendablePreferences { * * @param { 'multiProcessChange' } type - Indicates the event type. * @param { Callback } callback - Indicates the callback to unregister. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice @@ -493,9 +503,9 @@ declare namespace sendablePreferences { * @param { 'dataChange' } type - Indicates the event type. * @param { Array } keys - Indicates the data whose changes are not observed. * @param { Callback } callback - Indicates the callback to unregister. - * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; - * 2. Incorrect parameter types; - * 3. Parameter verification failed. + * @throws { BusinessError } 401 - Parameter error. Possible causes: + *
1. Mandatory parameters are left unspecified;
2. Incorrect parameter types; + *
3. Parameter verification failed. * @throws { BusinessError } 15500000 - Inner error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @atomicservice diff --git a/interface_sdk/api/@ohos.data.unifiedDataChannel.d.ts b/interface_sdk/api/@ohos.data.unifiedDataChannel.d.ts index d9383673..d26d476e 100644 --- a/interface_sdk/api/@ohos.data.unifiedDataChannel.d.ts +++ b/interface_sdk/api/@ohos.data.unifiedDataChannel.d.ts @@ -23,14 +23,22 @@ import image from "./@ohos.multimedia.image"; import Want from "./@ohos.app.ability.Want"; /** - * Provide methods for sharing data between different applications across unified data channels. + * As a part of the Unified Data Management Framework (UDMF), the unifiedDataChannel module provides unified data + * channels and standard data access interfaces for many-to-many data sharing across applications. It also provides + * definitions for uniform data types, such as text and image, to streamline data interaction between different + * applications and minimize the workload of data type adaptation. Although the UDMF does not parse user data, you are + * advised not to transfer sensitive personal data or privacy data due to low-level security of storage path. * * @namespace unifiedDataChannel * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 10 */ /** - * Provide methods for sharing data between different applications across unified data channels. + * As a part of the Unified Data Management Framework (UDMF), the unifiedDataChannel module provides unified data + * channels and standard data access interfaces for many-to-many data sharing across applications. It also provides + * definitions for uniform data types, such as text and image, to streamline data interaction between different + * applications and minimize the workload of data type adaptation. Although the UDMF does not parse user data, you are + * advised not to transfer sensitive personal data or privacy data due to low-level security of storage path. * * @namespace unifiedDataChannel * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -38,13 +46,17 @@ import Want from "./@ohos.app.ability.Want"; * @since 11 */ /** - * Provide methods for sharing data between different applications across unified data channels. + * As a part of the Unified Data Management Framework (UDMF), the unifiedDataChannel module provides unified data + * channels and standard data access interfaces for many-to-many data sharing across applications. It also provides + * definitions for uniform data types, such as text and image, to streamline data interaction between different + * applications and minimize the workload of data type adaptation. Although the UDMF does not parse user data, you are + * advised not to transfer sensitive personal data or privacy data due to low-level security of storage path. * * @namespace unifiedDataChannel * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ declare namespace unifiedDataChannel { /** @@ -96,7 +108,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ type ValueType = number | string | boolean | image.PixelMap | Want | ArrayBuffer | object | null | undefined; @@ -173,7 +185,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class UnifiedData { /** @@ -200,11 +212,11 @@ declare namespace unifiedDataChannel { * * @param { UnifiedRecord } record - Record will add into unified data. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; - *
2.Incorrect Parameters types. + *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ constructor(record: UnifiedRecord); /** @@ -220,7 +232,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ constructor(); /** @@ -247,11 +259,11 @@ declare namespace unifiedDataChannel { * * @param { UnifiedRecord } record - Record will add into unified data. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; - *
2.Incorrect Parameters types. + *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ addRecord(record: UnifiedRecord): void; /** @@ -276,12 +288,16 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ getRecords(): Array; /** - * Checks whether there is a specified type of data in DataProperties. + * Checks whether this UnifiedData object contains the specified data type, including the data types added by using + * the addEntry function. + * For file types, if the type set of UnifiedData contains general.jpeg, true is returned when the hasType API is + * called to check whether the general.image type is included, because the general.jpeg type belongs to the + * general.image type. * @param { string } type - indicates to query data type. * @returns { boolean } if having mimeType in UnifiedData returns true, else returns false. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; @@ -291,15 +307,19 @@ declare namespace unifiedDataChannel { * @since 12 */ /** - * Checks whether there is a specified type of data in DataProperties. + * Checks whether this UnifiedData object contains the specified data type, including the data types added by using + * the addEntry function. + * For file types, if the type set of UnifiedData contains general.jpeg, true is returned when the hasType API is + * called to check whether the general.image type is included, because the general.jpeg type belongs to the + * general.image type. * @param { string } type - indicates to query data type. * @returns { boolean } if having mimeType in UnifiedData returns true, else returns false. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; - *
2.Incorrect Parameters types. + *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ hasType(type: string): boolean; @@ -316,7 +336,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ getTypes(): Array; @@ -331,13 +351,13 @@ declare namespace unifiedDataChannel { } /** - * The data abstract supported by unified data + * Summarizes the data information of the unifiedData object, including the data type and size. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 10 */ /** - * The data abstract supported by unified data + * Summarizes the data information of the unifiedData object, including the data type and size. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @atomicservice @@ -390,12 +410,15 @@ declare namespace unifiedDataChannel { * @since 11 */ /** - * Describe the unified record + * An abstract definition of the data content supported by the UDMF. A UnifiedRecord object contains one or more data + * records, for example, a text record, an image record, or an HTML record. Since API version 15, different styles of + * the same content can be added to a UnifiedRecord object. Data users can obtain the corresponding styles as + * required. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class UnifiedRecord { /** @@ -420,7 +443,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ getType(): string; @@ -437,14 +460,15 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ constructor(); /** * Create unified record by type and value. * - * @param { string } type - indicates to data type of unified record. It can not be empty. When type of value is object, parameter type must be pixel-map or want UTD type. + * @param { string } type - indicates to data type of unified record. It can not be empty. When type of value is + * object, parameter type must be pixel-map or want UTD type. * @param { ValueType } value - indicates to value of unified record. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types; @@ -456,15 +480,16 @@ declare namespace unifiedDataChannel { /** * Create unified record by type and value. * - * @param { string } type - indicates to data type of unified record. It can not be empty. When type of value is object, parameter type must be pixel-map or want UTD type. + * @param { string } type - indicates to data type of unified record. It can not be empty. When type of value is + * object, parameter type must be pixel-map or want UTD type. * @param { ValueType } value - indicates to value of unified record. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; - *
2.Incorrect Parameters types; + *
2.Incorrect parameters types; *
3.Parameter verification failed. * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ constructor(type: string, value: ValueType); @@ -483,9 +508,57 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ getValue(): ValueType; + + /** + * Obtains all the data types in the data record. This API can be called using the UnifiedRecord object to query all + * data types in the record, including the data types added using the addEntry function. + * + * @returns { Array } Return the types of unified record. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + getTypes(): Array; + + /** + * Adds data of a specified data type and content to the current data record. You can use this API to add different + * data types and contents to the same data. + * + * @param { string } type - type of entry. + * @param { ValueType } value - value of entry. + * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; + *
2.Incorrect parameters types. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + addEntry(type: string, value: ValueType): void; + + /** + * Get an entry from unified record + * + * @param { string } type - type of entry want to get. + * @returns { ValueType } Return the value corresponding to the type. + * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; + *
2.Incorrect parameters types. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + getEntry(type: string): ValueType; + + /** + * Get entries from unified record + * + * @returns { Record } Return all entries in the record. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + getEntries(): Record; } /** @@ -510,7 +583,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class Text extends UnifiedRecord { /** @@ -534,7 +607,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ details?: Record; } @@ -561,7 +634,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class PlainText extends Text { /** @@ -585,7 +658,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ textContent: string; /** @@ -609,7 +682,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ abstract?: string; } @@ -636,7 +709,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class Hyperlink extends Text { /** @@ -660,7 +733,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ url: string; /** @@ -684,7 +757,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ description?: string; } @@ -711,7 +784,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class HTML extends Text { /** @@ -735,7 +808,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ htmlContent: string; /** @@ -759,7 +832,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ plainContent?: string; } @@ -786,7 +859,7 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class File extends UnifiedRecord { /** @@ -810,17 +883,17 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ details?: Record; /** - * Indicates the uri of file + * URI of the local file or online file. The local file URI can be obtained using the getUriFromPath function. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 10 */ /** - * Indicates the uri of file + * URI of the local file or online file. The local file URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -828,13 +901,13 @@ declare namespace unifiedDataChannel { * @since 11 */ /** - * Indicates the uri of file + * URI of the local file or online file. The local file URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ uri: string; } @@ -861,17 +934,17 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class Image extends File { /** - * Indicates the uri of image + * URI of the local image or online image. The local image URI can be obtained using the getUriFromPath function. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 10 */ /** - * Indicates the uri of image + * URI of the local image or online image. The local image URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -879,13 +952,13 @@ declare namespace unifiedDataChannel { * @since 11 */ /** - * Indicates the uri of image + * URI of the local image or online image. The local image URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ imageUri: string; } @@ -912,17 +985,17 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class Video extends File { /** - * Indicates the uri of video + * URI of the local video or online video. The local video URI can be obtained using the getUriFromPath function. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 10 */ /** - * Indicates the uri of video + * URI of the local video or online video. The local video URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -930,13 +1003,13 @@ declare namespace unifiedDataChannel { * @since 11 */ /** - * Indicates the uri of video + * URI of the local video or online video. The local video URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ videoUri: string; } @@ -963,17 +1036,17 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class Audio extends File { /** - * Indicates the uri of audio + * URI of the local audio or online audio. The local audio URI can be obtained using the getUriFromPath function. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 10 */ /** - * Indicates the uri of audio + * URI of the local audio or online audio. The local audio URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -981,13 +1054,13 @@ declare namespace unifiedDataChannel { * @since 11 */ /** - * Indicates the uri of audio + * URI of the local audio or online audio. The local audio URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ audioUri: string; } @@ -1014,17 +1087,17 @@ declare namespace unifiedDataChannel { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ class Folder extends File { /** - * Indicates the uri of folder + * URI of the local folder or online folder. The local folder URI can be obtained using the getUriFromPath function. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 10 */ /** - * Indicates the uri of folder + * URI of the local folder or online folder. The local folder URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -1032,13 +1105,13 @@ declare namespace unifiedDataChannel { * @since 11 */ /** - * Indicates the uri of folder + * URI of the local folder or online folder. The local folder URI can be obtained using the getUriFromPath function. * * @type { string } * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ folderUri: string; } @@ -1409,7 +1482,41 @@ declare namespace unifiedDataChannel { * @StageModelOnly * @since 12 */ - DRAG = 'Drag' + /** + * Indicates the intention of drag + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @stagemodelonly + * @since 14 + */ + DRAG = 'Drag', + + /** + * Indicates a system sharing channel. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @stagemodelonly + * @since 20 + */ + SYSTEM_SHARE = 'SystemShare', + + /** + * Indicates a Picker channel. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @stagemodelonly + * @since 20 + */ + PICKER = 'Picker', + + /** + * Indicates a menu channel. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @stagemodelonly + * @since 20 + */ + MENU = 'Menu' } /** @@ -1458,6 +1565,318 @@ declare namespace unifiedDataChannel { key?: string; }; + /** + * Defines the types of file conflict options when getting data from the UDMF. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + enum FileConflictOptions { + /** + * Overwrite when destUri has file with same name. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + OVERWRITE, + + /** + * Skip when destUri has file with same name. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + SKIP + } + + /** + * Defines the types of progress indicator when getting data from the UDMF. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + enum ProgressIndicator { + /** + * Getting data without system default progress indicator. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + NONE, + + /** + * Getting data with system default progress indicator. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + DEFAULT + } + + /** + * Defines the listener status of obtaining progress and data. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + enum ListenerStatus { + /** + * Indicates the finished status. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + FINISHED = 0, + + /** + * Indicates that processing is still in progress. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + PROCESSING, + + /** + * Indicates that the process has been canceled. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + CANCELED, + + /** + * Indicates that an internal error has occurred. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + INNER_ERROR = 200, + + /** + * Indicates that the GetDataParams contains invalid parameters. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + INVALID_PARAMETERS, + + /** + * Indicates that no data is obtained. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + DATA_NOT_FOUND, + + /** + * Indicates that an error occurred in the synchronization process. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + SYNC_FAILED, + + /** + * Indicates that an error occurred during file copying. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + COPY_FILE_FAILED, + } + + /** + * Indicates the progress information. + * + * @interface ProgressInfo + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + interface ProgressInfo { + /** + * Indicates the UDMF processing progress. + * + * @type { number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + progress: number; + + /** + * Indicates the status of obtaining progress and data. + * + * @type { ListenerStatus } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + status: ListenerStatus; + } + + /** + * A listener callback function that fetches progress info and data. + * + * @typedef { function } DataProgressListener + * @param { ProgressInfo } progressInfo - the progress information. + * @param { UnifiedData | null } data - Data obtained when the progress reaches 100%. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + type DataProgressListener = (progressInfo: ProgressInfo, data: UnifiedData | null) => void; + + /** + * Represents the get data parameters when getting data from udmf. + * + * @interface GetDataParams + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + interface GetDataParams { + /** + * Indicates whether to use default system progress indicator. + * + * @type { ProgressIndicator } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + progressIndicator: ProgressIndicator; + + /** + * Indicates progress and data listener when getting unified data. + * + * @type { DataProgressListener } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + dataProgressListener: DataProgressListener; + + /** + * Indicates the dest path uri where copy file will be copied to sandbox of application. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + destUri?: string; + + /** + * Indicates file conflict options when dest path has file with same name. + * + * @type { FileConflictOptions } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 15 + */ + fileConflictOptions?: FileConflictOptions; + + /** + * Indicates the supported data information. + * + * @type { ?DataLoadInfo } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 20 + */ + acceptableInfo?: DataLoadInfo; + } + + /** + * Indicates data loading information. + * + * @interface DataLoadInfo + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 20 + */ + interface DataLoadInfo { + /** + * Represents the data type or supported types to load. + *
This parameter is mandatory when used by the data provider. + * + * @type { ?Set } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 20 + */ + types?: Set; + + /** + * Indicates the maximum number of data records to be loaded. + * + * @type { ?number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 20 + */ + recordCount?: number; + } + + /** + * Indicates the callback function for loading data. + * + * @typedef { function } DataLoadHandler + * @param { DataLoadInfo } acceptableInfo Indicates the type and number of data that can be accepted by the receiver. + * @returns { UnifiedData | null } the {@link UnifiedData} object to be loaded. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 20 + */ + type DataLoadHandler = (acceptableInfo?: DataLoadInfo) => UnifiedData | null; + + /** + * Indicates data loading params. + * + * @interface DataLoadParams + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 20 + */ + interface DataLoadParams { + /** + * Indicates the callback function for loading data. + * + * @type { DataLoadHandler } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 20 + */ + loadHandler: DataLoadHandler; + + /** + * Indicates data loading information. + * @type { DataLoadInfo } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @atomicservice + * @since 20 + */ + dataLoadInfo: DataLoadInfo; + } + /** * Insert data into unified data channel by Intention * @@ -1561,8 +1980,10 @@ declare namespace unifiedDataChannel { /** * Query data of unified data channel by Intention or Unique Identifier * - * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} or {@link UnifiedData}. - * @param { AsyncCallback> } callback - {Array}: the target {@link UnifiedData} object array. + * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} + * or {@link UnifiedData}. + * @param { AsyncCallback> } callback - {Array}: the target {@link UnifiedData} + * object array. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -1571,8 +1992,10 @@ declare namespace unifiedDataChannel { /** * Query data of unified data channel by Intention or Unique Identifier * - * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} or {@link UnifiedData}. - * @param { AsyncCallback> } callback - {Array}: the target {@link UnifiedData} object array. + * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} + * or {@link UnifiedData}. + * @param { AsyncCallback> } callback - {Array}: the target {@link UnifiedData} object + * array. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -1584,7 +2007,8 @@ declare namespace unifiedDataChannel { /** * Query data of unified data channel by Intention or Unique Identifier * - * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} or {@link UnifiedData}. + * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} + * or {@link UnifiedData}. * @returns { Promise> } {Array}: the target {@link UnifiedData} object array. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. @@ -1594,7 +2018,8 @@ declare namespace unifiedDataChannel { /** * Query data of unified data channel by Intention or Unique Identifier * - * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} or {@link UnifiedData}. + * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} + * or {@link UnifiedData}. * @returns { Promise> } {Array}: the target {@link UnifiedData} object array. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. @@ -1607,8 +2032,10 @@ declare namespace unifiedDataChannel { /** * Delete data of unified data channel by Intention or Unique Identifier * - * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} or {@link UnifiedData}. - * @param { AsyncCallback> } callback - {Array}: the deleted {@link UnifiedData} object array. + * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} + * or {@link UnifiedData}. + * @param { AsyncCallback> } callback - {Array}: the deleted {@link UnifiedData} + * object array. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -1617,8 +2044,10 @@ declare namespace unifiedDataChannel { /** * Delete data of unified data channel by Intention or Unique Identifier * - * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} or {@link UnifiedData}. - * @param { AsyncCallback> } callback - {Array}: the deleted {@link UnifiedData} object array. + * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} + * or {@link UnifiedData}. + * @param { AsyncCallback> } callback - {Array}: the deleted {@link UnifiedData} + * object array. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -1630,7 +2059,8 @@ declare namespace unifiedDataChannel { /** * Delete data of unified data channel by Intention or Unique Identifier * - * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} or {@link UnifiedData}. + * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} + * or {@link UnifiedData}. * @returns { Promise> } {Array}: the deleted {@link UnifiedData} object array. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. @@ -1640,7 +2070,8 @@ declare namespace unifiedDataChannel { /** * Delete data of unified data channel by Intention or Unique Identifier * - * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} or {@link UnifiedData}. + * @param { Options } options - fill the intention or unique identifier field to indicate the target {@link Intention} + * or {@link UnifiedData}. * @returns { Promise> } {Array}: the deleted {@link UnifiedData} object array. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. @@ -1651,26 +2082,45 @@ declare namespace unifiedDataChannel { function deleteData(options: Options): Promise>; /** - * Set app sharing options. + * Sets the ShareOptions for the application data. Currently, only the drag-and-drop data channel is supported. * * @param { Intention } intention - Describe the sharing channel that UDMF support. * @param { ShareOptions } shareOptions - Types of scope that UnifiedData can be used. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses + * system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; * 2. Incorrect parameter types. - * @throws { BusinessError } 20400001 - Settings already exist. + * @throws { BusinessError } 20400001 - Settings already exist. To reconfigure, remove the existing sharing options. * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @systemapi * @StageModelOnly * @since 12 */ + /** + * Sets the ShareOptions for the application data. Currently, only the drag-and-drop data channel is supported. + * + * @permission ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION + * @param { Intention } intention - Describe the sharing channel that UDMF support. Currently only supports DRAG + * intention. + * @param { ShareOptions } shareOptions - Types of scope that UnifiedData can be used. + * @throws { BusinessError } 201 - Permission denied. Interface caller does not have permission + * "ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION". + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + * 2. Incorrect parameter types; + * 3. Parameter verification failed. + * @throws { BusinessError } 20400001 - Settings already exist. To reconfigure, remove the existing sharing options. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @stagemodelonly + * @since 14 + */ function setAppShareOptions(intention: Intention, shareOptions: ShareOptions): void; /** * Remove app sharing options. * * @param { Intention } intention - Describe the sharing channel that UDMF support. - * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application + * uses system API. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; * 2. Incorrect parameter types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -1678,7 +2128,38 @@ declare namespace unifiedDataChannel { * @StageModelOnly * @since 12 */ + /** + * Remove app sharing options. + * + * @permission ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION + * @param { Intention } intention - Describe the sharing channel that UDMF support. Currently only supports DRAG + * intention. + * @throws { BusinessError } 201 - Permission denied. Interface caller does not have permission + * "ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION". + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + * 2. Incorrect parameter types; + * 3. Parameter verification failed. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @stagemodelonly + * @since 14 + */ function removeAppShareOptions(intention: Intention): void; + + /** + * Converts the provided data into a multi-style data structure, which is useful when the original data uses multiple + * records to represent different styles of the same data. This API is used only when the following rules are met: + * 1.The number of records in data is greater than + * 2.The value of unifiedData.properties.tag is records_to_entries_data_format. + * + * @param { UnifiedData } data - {@link UnifiedData} Data to convert. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified. + * 2. Incorrect parameter types. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @stagemodelonly + * @atomicservice + * @since 17 + */ + function convertRecordsToEntries(data: UnifiedData): void; } export default unifiedDataChannel; diff --git a/interface_sdk/api/@ohos.data.uniformDataStruct.d.ts b/interface_sdk/api/@ohos.data.uniformDataStruct.d.ts index adb83f2e..4f811c4e 100644 --- a/interface_sdk/api/@ohos.data.uniformDataStruct.d.ts +++ b/interface_sdk/api/@ohos.data.uniformDataStruct.d.ts @@ -18,6 +18,8 @@ * @kit ArkData */ +import image from './@ohos.multimedia.image'; + /** * Provide uniform data struct definition. * @@ -60,7 +62,14 @@ declare namespace uniformDataStruct { */ abstract?: string; /** - * Indicates the details of the PlainText. + * Object of the dictionary type used to describe the attributes of the text content. Both the key and value of the + * object are of the string type. For example, the following is a details object used to describe the properties of + * a file: + * { + * "title":"Title of the file", + * "content":"Content of the file" + * } + * By default, it is an empty dictionary object. * * @type { ?Record } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -102,7 +111,14 @@ declare namespace uniformDataStruct { */ description?: string; /** - * Indicates the details of the Hyperlink. + * Object of the dictionary type used to describe the attributes of the hyperlink. Both the key and value of the + * object are of the string type. For example, the following is a details object used to describe the properties of + * a file: + * { + * "title":"Title of the hyperlink", + * "content":"Content" + * } + * By default, it is an empty dictionary object. * * @type { ?Record } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -146,7 +162,14 @@ declare namespace uniformDataStruct { */ plainContent?: string; /** - * Indicates the details of html. + * Object of the dictionary type used to describe the attributes of the HTML content. Both the key and value of the + * object are of the string type. For example, the following is a details object used to describe the properties of + * a file: + * { + * "title":"Title of the HTML content", + * "content":"Content" + * } + * By default, it is an empty dictionary object. * * @type { ?Record } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -164,7 +187,7 @@ declare namespace uniformDataStruct { */ interface OpenHarmonyAppItem { /** - * Indicates the uniform data type of this data struct. + * Uniform data type, which has a fixed value of openharmony.app-item. For details, see UniformDataType. * * @type { 'openharmony.app-item' } * @readonly @@ -221,7 +244,8 @@ declare namespace uniformDataStruct { */ abilityName: string; /** - * Indicates the details of app. + * Object of the dictionary type used to describe the icon. The key is of the string type, and the value can be a + * number, a string, or a Uint8Array. By default, it is an empty dictionary object. * * @type { ?Record } * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -229,6 +253,235 @@ declare namespace uniformDataStruct { */ details?: Record; } + + /** + * Uniform data type, which has a fixed value of general.content-form. + * + * @interface ContentForm + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 14 + */ + interface ContentForm { + /** + * Indicates the uniform data type of this data struct. + * + * @type { 'general.content-form' } + * @readonly + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 14 + */ + readonly uniformDataType: 'general.content-form'; + + /** + * Indicates the thumb data of content form. + * + * @type { Uint8Array } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 14 + */ + thumbData?: Uint8Array; + + /** + * Indicates the description of content form. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 14 + */ + description?: string; + + /** + * Indicates the title of content form. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 14 + */ + title: string; + + /** + * Indicates the app icon of content form. + * + * @type { Uint8Array } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 14 + */ + appIcon?: Uint8Array; + + /** + * Indicates the app name of content form. + * + * @type { appName } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 14 + */ + appName?: string; + + /** + * Indicates the link url of content form. + * + * @type { linkUri } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 14 + */ + linkUri?: string; + } + + /** + * Describe form uniform data struct. + * + * @interface Form + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + interface Form { + /** + * Uniform data type, which has a fixed value of openharmony.form. For details, see UniformDataType. + * + * @type { 'openharmony.form' } + * @readonly + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + readonly uniformDataType: 'openharmony.form'; + + /** + * Indicates the form id of form. + * + * @type { number } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + formId: number; + + /** + * Indicates the form name of form. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + formName: string; + + /** + * Indicates the bundle name of form. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + bundleName: string; + + /** + * Indicates the ability name of form. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + abilityName: string; + + /** + * Indicates the module of form. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + module: string; + + /** + * Indicates the details of form. + * + * @type { ?Record } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + details?: Record; + } + + /** + * Describe the file uri uniform data struct. + * + * @interface FileUri + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + interface FileUri { + /** + * Uniform data type, which has a fixed value of general.file-uri. For details, see UniformDataType. + * + * @type { 'general.file-uri' } + * @readonly + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + readonly uniformDataType: 'general.file-uri'; + + /** + * Indicates the oriUri of fileUri. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + oriUri: string; + + /** + * Indicates the file type of fileUri. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + fileType: string; + + /** + * Indicates the details of fileUri. + * + * @type { ?Record } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + details?: Record; + } + + /** + * Describe the pixelMap uniform data struct. + * + * @interface PixelMap + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + interface PixelMap { + /** + * Uniform data type, which has a fixed value of openharmony.pixel-map. For details, see UniformDataType. + * + * @type { 'openharmony.pixel-map' } + * @readonly + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + readonly uniformDataType: 'openharmony.pixel-map'; + + /** + * Indicates the pixelMap value of pixelMap. + * + * @type { image.PixelMap } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + pixelMap: image.PixelMap; + + /** + * Indicates the details of pixelMap. + * + * @type { ?Record } + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + details?: Record; + } } export default uniformDataStruct; \ No newline at end of file diff --git a/interface_sdk/api/@ohos.data.uniformTypeDescriptor.d.ts b/interface_sdk/api/@ohos.data.uniformTypeDescriptor.d.ts index b38c554e..c3e9d9ec 100644 --- a/interface_sdk/api/@ohos.data.uniformTypeDescriptor.d.ts +++ b/interface_sdk/api/@ohos.data.uniformTypeDescriptor.d.ts @@ -40,7 +40,7 @@ * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ declare namespace uniformTypeDescriptor { /** @@ -65,7 +65,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ enum UniformDataType { /** @@ -111,7 +111,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ TEXT = 'general.text', @@ -134,7 +134,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ PLAIN_TEXT = 'general.plain-text', @@ -157,7 +157,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ HTML = 'general.html', @@ -180,7 +180,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ HYPERLINK = 'general.hyperlink', @@ -475,7 +475,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ IMAGE = 'general.image', @@ -722,7 +722,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ VIDEO = 'general.video', @@ -865,7 +865,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ AUDIO = 'general.audio', @@ -983,15 +983,15 @@ declare namespace uniformTypeDescriptor { /** * Mp2 audio format data type. - * + * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 12 */ MP2 = 'general.mp2', /** - * Mpeg audio format data type. - * + * MPEG audio format. This type belongs to AUDIO. + * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 12 */ @@ -999,7 +999,7 @@ declare namespace uniformTypeDescriptor { /** * Ulaw audio format data type. - * + * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 12 */ @@ -1048,7 +1048,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ FILE = 'general.file', @@ -1079,7 +1079,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ FOLDER = 'general.folder', @@ -1172,7 +1172,7 @@ declare namespace uniformTypeDescriptor { JAVA_ARCHIVE = 'com.sun.java-archive', /** - * GNU archive data type. + * GNU. This type belongs to ARCHIVE. * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 11 @@ -1548,7 +1548,7 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @crossplatform * @atomicservice - * @since 13 + * @since 14 */ OPENHARMONY_PIXEL_MAP = 'openharmony.pixel-map', @@ -1611,7 +1611,7 @@ declare namespace uniformTypeDescriptor { /** * Ofd data type. - * + * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 12 */ @@ -1619,7 +1619,7 @@ declare namespace uniformTypeDescriptor { /** * Cad data type. - * + * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 12 */ @@ -1627,11 +1627,27 @@ declare namespace uniformTypeDescriptor { /** * Octet stream data type. - * + * * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 12 */ - OCTET_STREAM = 'general.octet-stream' + OCTET_STREAM = 'general.octet-stream', + + /** + * File uri data type. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + FILE_URI = 'general.file-uri', + + /** + * Content widget type. This type belongs to OBJECT. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 15 + */ + CONTENT_FORM = 'general.content-form' } /** @@ -1775,12 +1791,14 @@ declare namespace uniformTypeDescriptor { function getTypeDescriptor(typeId: string): TypeDescriptor; /** - * Queries and returns the uniform type descriptor by the given filename extension and the uniform data type it belongs to. + * Queries and returns the uniform type descriptor by the given filename extension and the uniform data type it + * belongs to. * * @param { string } filenameExtension - Filename extension. * @param { string } [belongsTo] - A uniform data type ID it belongs to. * @returns { string } Returns the uniform data type ID corresponding to the given filename extension and the - *
uniform data type it belongs to(If the 'belongsTo' parameter is set) or flexible type if the uniform data type does not exist. + *
uniform data type it belongs to(If the 'belongsTo' parameter is set) or flexible type if the uniform data type + * does not exist. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core @@ -1803,28 +1821,32 @@ declare namespace uniformTypeDescriptor { function getUniformDataTypeByMIMEType(mimeType: string, belongsTo?: string): string; /** - * Queries and returns the uniform type descriptor list by the given filename extension and the uniform data type it belongs to. + * Queries and returns the uniform type descriptor list by the given filename extension and the uniform data type it + * belongs to. * * @param { string } filenameExtension - Filename extension. * @param { string } [belongsTo] - A uniform data type ID it belongs to. - * @returns { Array } Returns the uniform data type ID list corresponding to the given filename extension and the - *
uniform data type it belongs to(If the 'belongsTo' parameter is set) or flexible type if the uniform data type does not exist. + * @returns { Array } Returns the uniform data type ID list corresponding to the given filename extension and + * the uniform data type it belongs to(If the 'belongsTo' parameter is set) or flexible type if the uniform data type + * does not exist. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; - *
2.Incorrect Parameters types. + *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 13 */ function getUniformDataTypesByFilenameExtension(filenameExtension: string, belongsTo?: string): Array; /** - * Queries and returns the uniform type descriptor list by the given MIME type and the uniform data type it belongs to. + * Queries and returns the uniform type descriptor list by the given MIME type and the uniform data type it belongs + * to. * * @param { string } mimeType - MIME type. * @param { string } [belongsTo] - A uniform data type ID it belongs to. - * @returns { Array } Returns the uniform data type ID list corresponding to the given MIME type and the uniform data type - *
it belongs to(If the 'belongsTo' parameter is set) or flexible type if the uniform data type does not exist. + * @returns { Array } Returns the uniform data type ID list corresponding to the given MIME type and the + * uniform data type it belongs to(If the 'belongsTo' parameter is set) or flexible type if the uniform data type does + * not exist. * @throws { BusinessError } 401 - Parameter error. Possible causes:1.Mandatory parameters are left unspecified; - *
2.Incorrect Parameters types. + *
2.Incorrect parameters types. * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 13 */ diff --git a/kv_store/CODEOWNERS b/kv_store/CODEOWNERS index 71c2f7c9..e26e631e 100644 --- a/kv_store/CODEOWNERS +++ b/kv_store/CODEOWNERS @@ -14,6 +14,6 @@ # any change to # frameworks/innerkitsimpl/distributeddatasvc/include/distributeddata_ipc_interface_code.h # frameworks/innerkitsimpl/kvdb/include/distributeddata_kvdb_ipc_interface_code.h -# needs to be reviewed by @leonchan5 -frameworks/innerkitsimpl/distributeddatasvc/include/distributeddata_ipc_interface_code.h @leonchan5 -frameworks/innerkitsimpl/kvdb/include/distributeddata_kvdb_ipc_interface_code.h @leonchan5 \ No newline at end of file +# needs to be reviewed by @leonchan5 liubao6@huawei.com +frameworks/innerkitsimpl/distributeddatasvc/include/distributeddata_ipc_interface_code.h @leonchan5 liubao6@huawei.com +frameworks/innerkitsimpl/kvdb/include/distributeddata_kvdb_ipc_interface_code.h @leonchan5 liubao6@huawei.com \ No newline at end of file diff --git a/kv_store/bundle.json b/kv_store/bundle.json index fda9c229..e9982833 100644 --- a/kv_store/bundle.json +++ b/kv_store/bundle.json @@ -51,8 +51,6 @@ "deps": { "third_party": [ "bounds_checking_function", - "cJSON", - "jsoncpp", "libuv", "openssl", "sqlite", @@ -66,6 +64,7 @@ "bundle_framework", "access_token", "common_event_service", + "cJSON", "c_utils", "device_manager", "dmsfwk", @@ -79,7 +78,9 @@ "safwk", "samgr", "file_api", - "zlib" + "zlib", + "openssl", + "sqlite" ] }, "build": { @@ -92,7 +93,6 @@ "//foundation/distributeddatamgr/kv_store/interfaces/jskits/distributedkvstore:build_module", "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/jskits/distributedkvstore:build_module", "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_client_sync", - "//foundation/distributeddatamgr/kv_store/interfaces/cj:cj_distributed_kv_store_ffi", "//foundation/distributeddatamgr/kv_store/databaseutils:database_utils" ], "inner_kits": [ @@ -277,6 +277,42 @@ ], "header_base": "//foundation/distributeddatamgr/kv_store/databaseutils/include" } + }, + { + "name": "//foundation/distributeddatamgr/kv_store/interfaces/cj:cj_distributed_kv_store_ffi", + "header": { + "header_files": [], + "header_base": "//foundation/distributeddatamgr/kv_store/frameworks/cj/include" + } + }, + { + "name": "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb_client", + "header": { + "header_files": [ + "relational_store_client.h", + "relational_store_sqlite_ext.h", + "relational_store_manager.h" + ], + "header_base": "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/interfaces/include/relational" + } + }, + { + "name": "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb_client", + "header": { + "header_files": [ + "store_observer.h" + ], + "header_base": "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/interfaces/include" + } + }, + { + "name": "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb_client", + "header": { + "header_files": [ + "query.h" + ], + "header_base": "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/include" + } } ], "test": [ diff --git a/kv_store/databaseutils/include/acl.h b/kv_store/databaseutils/include/acl.h index 8177eb0e..0e4c9d92 100644 --- a/kv_store/databaseutils/include/acl.h +++ b/kv_store/databaseutils/include/acl.h @@ -151,6 +151,7 @@ private: std::unique_ptr Serialize(uint32_t &bufSize); int DeSerialize(const char *p, int32_t bufSize); int InsertEntry(const AclXattrEntry &entry); + std::string Anonymous(const std::string &name); AclXattrHeader header_; /* * Only one entry should exist for the following types: diff --git a/kv_store/databaseutils/src/acl.cpp b/kv_store/databaseutils/src/acl.cpp index f220bf37..bb7aa345 100644 --- a/kv_store/databaseutils/src/acl.cpp +++ b/kv_store/databaseutils/src/acl.cpp @@ -33,6 +33,11 @@ namespace OHOS { namespace DATABASE_UTILS { using namespace DistributedKv; +static constexpr int32_t HEAD_SIZE = 3; +static constexpr int32_t END_SIZE = 3; +static constexpr int32_t MIN_SIZE = 9; +static constexpr const char *REPLACE_CHAIN = "***"; +static constexpr const char *DEFAULT_ANONYMOUS = "******"; Acl::Acl(const std::string &path) : path_(path), hasError_(false) { /* init acl from file's defaule or mode*/ @@ -156,7 +161,7 @@ void Acl::AclFromDefault() AclFromMode(); } else { hasError_ = true; - ZLOGW("The getxattr failed. error %{public}s path %{public}s", std::strerror(errno), path_.c_str()); + ZLOGW("The getxattr failed. error %{public}s path %{public}s", std::strerror(errno), Anonymous(path_).c_str()); } } @@ -217,5 +222,18 @@ bool Acl::HasEntry(const AclXattrEntry &Acl) { return entries_.find(Acl) != entries_.end(); } + +std::string Acl::Anonymous(const std::string &name) +{ + if (name.length() <= HEAD_SIZE) { + return DEFAULT_ANONYMOUS; + } + + if (name.length() < MIN_SIZE) { + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN); + } + + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE)); +} } } \ No newline at end of file diff --git a/kv_store/databaseutils/test/BUILD.gn b/kv_store/databaseutils/test/BUILD.gn index 2899a28f..5c4891a8 100644 --- a/kv_store/databaseutils/test/BUILD.gn +++ b/kv_store/databaseutils/test/BUILD.gn @@ -30,7 +30,7 @@ ohos_unittest("DataBaseUtilsTest") { sources += [ "../src/acl.cpp" ] configs = [ ":database_utils_config" ] - + cflags = [ "-Dprivate=public" ] external_deps = [ "hilog:libhilog" ] public_external_deps = [ "bounds_checking_function:libsec_shared", @@ -38,89 +38,6 @@ ohos_unittest("DataBaseUtilsTest") { ] } -ohos_unittest("DataMgrServiceProxyVirtualTest") { - module_out_path = module_output_path - - sources = [ - "${kv_store_base_path}/frameworks/innerkitsimpl/distributeddatasvc/src/datamgr_service_proxy.cpp", - "datamgr_service_proxy_virtual_test.cpp", - ] - - configs = [ ":database_utils_config" ] - - external_deps = [ - "c_utils:utils", - "googletest:gtest_main", - "hilog:libhilog", - "ipc:ipc_single", - "samgr:samgr_proxy", - ] - - deps = [ - "${kv_store_base_path}/frameworks/libs/distributeddb/:distributeddb", - "${kv_store_base_path}/interfaces/innerkits/distributeddata:distributeddata_inner", - "${kv_store_base_path}/interfaces/innerkits/distributeddatamgr:distributeddata_mgr", - ] -} - -ohos_unittest("BlobVirtualTest") { - module_out_path = module_output_path - - sources = [ - "${kv_store_base_path}/frameworks/innerkitsimpl/distributeddatasvc/src/datamgr_service_proxy.cpp", - "bool_virtual_test.cpp", - ] - - configs = [ ":database_utils_config" ] - - external_deps = [ - "c_utils:utils", - "googletest:gtest_main", - "hilog:libhilog", - "ipc:ipc_single", - "samgr:samgr_proxy", - ] - - deps = [ - "${kv_store_base_path}/frameworks/libs/distributeddb/:distributeddb", - "${kv_store_base_path}/interfaces/innerkits/distributeddata:distributeddata_inner", - "${kv_store_base_path}/interfaces/innerkits/distributeddatamgr:distributeddata_mgr", - ] -} - -ohos_unittest("DataQueryVirtualTest") { - module_out_path = module_output_path - - sources = [ - "${kv_store_base_path}/frameworks/innerkitsimpl/distributeddatasvc/src/datamgr_service_proxy.cpp", - "data_query_virtual_test.cpp", - "delegate_mgr_callback_virtual_test.cpp", - "distributed_kv_data_manager_vritual_test.cpp", - "kv_utils_virtual_test.cpp", - "kvdb_notifier_virtual_test.cpp", - "kvstore_datashare_bridge_virtual_test.cpp", - "local_kv_store_virtual_test.cpp", - "local_subscribe_store_virtual_test.cpp", - "single_kvstore_query_virtual_test.cpp", - ] - - configs = [ ":database_utils_config" ] - - external_deps = [ - "c_utils:utils", - "googletest:gtest_main", - "hilog:libhilog", - "ipc:ipc_single", - "samgr:samgr_proxy", - ] - - deps = [ - "${kv_store_base_path}/frameworks/libs/distributeddb/:distributeddb", - "${kv_store_base_path}/interfaces/innerkits/distributeddata:distributeddata_inner", - "${kv_store_base_path}/interfaces/innerkits/distributeddatamgr:distributeddata_mgr", - ] -} - group("unittest") { testonly = true diff --git a/kv_store/databaseutils/test/acl_test.cpp b/kv_store/databaseutils/test/acl_test.cpp index 46e1934a..3aac9174 100644 --- a/kv_store/databaseutils/test/acl_test.cpp +++ b/kv_store/databaseutils/test/acl_test.cpp @@ -184,7 +184,7 @@ HWTEST_F(AclTest, SetDefaultUser002, TestSize.Level0) * @tc.require: * @tc.author: SQL */ -HWTEST_F(AclTest, AclXattrEntry001, TestSize.Level0) +HWTEST_F(AclTest, AclXattrEntry001, TestSize.Level1) { AclXattrEntry entryA(ACL_TAG::USER, UID, Acl::R_RIGHT | Acl::W_RIGHT); AclXattrEntry entryB(ACL_TAG::USER, UID, Acl::R_RIGHT | Acl::W_RIGHT); @@ -201,7 +201,7 @@ HWTEST_F(AclTest, AclXattrEntry001, TestSize.Level0) * @tc.require: * @tc.author: SQL */ -HWTEST_F(AclTest, AclXattrEntry002, TestSize.Level0) +HWTEST_F(AclTest, AclXattrEntry002, TestSize.Level1) { AclXattrEntry entryA(ACL_TAG::USER, UID, Acl::R_RIGHT | Acl::W_RIGHT); auto result = entryA.IsValid(); @@ -223,7 +223,7 @@ HWTEST_F(AclTest, AclXattrEntry002, TestSize.Level0) * @tc.require: * @tc.author: SQL */ -HWTEST_F(AclTest, ACL_PERM001, TestSize.Level0) +HWTEST_F(AclTest, ACL_PERM001, TestSize.Level1) { ACL_PERM perm1; perm1.SetR(); @@ -236,4 +236,22 @@ HWTEST_F(AclTest, ACL_PERM001, TestSize.Level0) EXPECT_TRUE(perm1.IsWritable()); EXPECT_TRUE(perm1.IsExecutable()); } + +/** + * @tc.name: Anonymous001 + * @tc.desc: Test Anonymous. + * @tc.type: FUNC + * @tc.require: + * @tc.author: SQL + */ +HWTEST_F(AclTest, Anonymous001, TestSize.Level1) +{ + Acl aclNew(PATH_ABC); + std::string name = ""; + EXPECT_EQ(aclNew.Anonymous(name), "******"); + name = "12345678"; + EXPECT_EQ(aclNew.Anonymous(name), "123***"); + name = "123456789"; + EXPECT_EQ(aclNew.Anonymous(name), "123***789"); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/bool_virtual_test.cpp b/kv_store/databaseutils/test/bool_virtual_test.cpp deleted file mode 100644 index 6f5c0a5f..00000000 --- a/kv_store/databaseutils/test/bool_virtual_test.cpp +++ /dev/null @@ -1,540 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "BlobVirtualTest" - -#include "blob.h" -#include "change_notification.h" -#include "kv_types_util.h" -#include "types.h" -#include -#include -#include - -using namespace OHOS::DistributedKv; -using namespace testing; -using namespace testing::ext; -namespace OHOS::Test { -class BlobVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void BlobVirtualTest::SetUpTestCase(void) -{} - -void BlobVirtualTest::TearDownTestCase(void) -{} - -void BlobVirtualTest::SetUp(void) -{} - -void BlobVirtualTest::TearDown(void) -{} - -class ChangeNotificationVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void ChangeNotificationVirtualTest::SetUpTestCase(void) -{} - -void ChangeNotificationVirtualTest::TearDownTestCase(void) -{} - -void ChangeNotificationVirtualTest::SetUp(void) -{} - -void ChangeNotificationVirtualTest::TearDown(void) -{} - -/** - * @tc.name: DefaultConstructor - * @tc.desc: - * @tc.type: DefaultConstructor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, DefaultConstructor, TestSize.Level0) -{ - ZLOGI("DefaultConstructor begin."); - Blob defaultConstructor; - EXPECT_TRUE(defaultConstructor.Empty()); -} - -/** - * @tc.name: CopyConstructor - * @tc.desc: - * @tc.type: CopyConstructor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, CopyConstructor, TestSize.Level0) -{ - ZLOGI("CopyConstructor begin."); - Blob copyConstructor1("hello", 5); - Blob copyConstructor2(blob1); - EXPECT_EQ(copyConstructor1, copyConstructor2); -} - -/** - * @tc.name: MoveConstructor - * @tc.desc: - * @tc.type: MoveConstructor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, MoveConstructor, TestSize.Level0) -{ - ZLOGI("MoveConstructor begin."); - Blob moveConstructor1("hello", 5); - Blob moveConstructor2(std::move(blob1)); - EXPECT_TRUE(moveConstructor1.Empty()); - EXPECT_EQ(std::string(moveConstructor2.Data().begin(), - moveConstructor2.Data().end()), "hello"); -} - -/** - * @tc.name: CopyAssignmentOperator - * @tc.desc: - * @tc.type: CopyAssignmentOperator test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, CopyAssignmentOperator) -{ - ZLOGI("CopyAssignmentOperator begin."); - Blob copyAssignmentOperator1("hello", 5); - Blob copyAssignmentOperator2; - copyAssignmentOperator2 = copyAssignmentOperator1; - EXPECT_EQ(copyAssignmentOperator1, copyAssignmentOperator2); -} - -/** - * @tc.name: MoveAssignmentOperator - * @tc.desc: - * @tc.type: MoveAssignmentOperator test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, MoveAssignmentOperator, TestSize.Level0) -{ - ZLOGI("MoveAssignmentOperator begin."); - Blob moveAssignmentOperator1("hello", 5); - Blob moveAssignmentOperator2; - blob2 = std::move(moveAssignmentOperator1); - EXPECT_TRUE(moveAssignmentOperator1.Empty()); - EXPECT_EQ(std::string(moveAssignmentOperator2.Data().begin(), - moveAssignmentOperator2.Data().end()), "hello"); -} - -/** - * @tc.name: ConstCharConstructorWithSize - * @tc.desc: - * @tc.type: ConstCharConstructorWithSize test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, ConstCharConstructorWithSize, TestSize.Level0) -{ - ZLOGI("ConstCharConstructorWithSize begin."); - Blob constCharConstructorWithSize("hello", 5); - EXPECT_EQ(std::string(constCharConstructorWithSize.Data().begin(), - constCharConstructorWithSize.Data().end()), "hello"); -} - -/** - * @tc.name: ConstCharConstructorWithNullTerminator - * @tc.desc: - * @tc.type: ConstCharConstructorWithNullTerminator test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, ConstCharConstructorWithNullTerminator, TestSize.Level0) -{ - ZLOGI("ConstCharConstructorWithNullTerminator begin."); - Blob blob("ConstCharConstructorWithNullTerminator"); - EXPECT_EQ(std::string(blob.Data().begin(), blob.Data().end()), "ConstCharConstructorWithNullTerminator"); -} - -/** - * @tc.name: StringConstructor - * @tc.desc: - * @tc.type: StringConstructor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, StringConstructor, TestSize.Level0) -{ - ZLOGI("StringConstructor begin."); - std::string str = "StringConstructor"; - Blob stringConstructor(str); - EXPECT_EQ(std::string(stringConstructor.Data().begin(), - stringConstructor.Data().end()), str); -} - -/** - * @tc.name: StringAssignmentOperator - * @tc.desc: - * @tc.type: StringAssignmentOperator test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, StringAssignmentOperator, TestSize.Level0) -{ - ZLOGI("StringAssignmentOperator begin."); - std::string str = "StringAssignmentOperator"; - Blob stringAssignmentOperator; - stringAssignmentOperator = str; - EXPECT_EQ(std::string(stringAssignmentOperator.Data().begin(), - stringAssignmentOperator.Data().end()), str); -} - -/** - * @tc.name: ConstCharAssignmentOperator - * @tc.desc: - * @tc.type: ConstCharAssignmentOperator test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, ConstCharAssignmentOperator, TestSize.Level0) -{ - ZLOGI("ConstCharAssignmentOperator begin."); - std::string str = "StringAssignmentOperator"; - Blob constCharAssignmentOperator; - constCharAssignmentOperator = str; - EXPECT_EQ(std::string(constCharAssignmentOperator.Data().begin(), - constCharAssignmentOperator.Data().end()), str); -} - -/** - * @tc.name: VectorConstructor - * @tc.desc: - * @tc.type: VectorConstructor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, VectorConstructor, TestSize.Level0) -{ - ZLOGI("VectorConstructor begin."); - std::vector vec = {'h', 'e', 'l', 'l', 'o'}; - Blob vectorConstructor(vec); - EXPECT_EQ(std::string(vectorConstructor.Data().begin(), - vectorConstructor.Data().end()), "hello"); -} - -/** - * @tc.name: MoveVectorConstructor - * @tc.desc: - * @tc.type: MoveVectorConstructor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, MoveVectorConstructor, TestSize.Level0) -{ - ZLOGI("MoveVectorConstructor begin."); - std::vector vec = {'h', 'e', 'l', 'l', 'o'}; - Blob moveVectorConstructor(std::move(vec)); - EXPECT_EQ(std::string(moveVectorConstructor.Data().begin(), - moveVectorConstructor.Data().end()), "hello"); - EXPECT_TRUE(vec.empty()); -} - -/** - * @tc.name: DataAccessor - * @tc.desc: - * @tc.type: DataAccessor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, DataAccessor, TestSize.Level0) -{ - ZLOGI("DataAccessor begin."); - Blob dataAccessor("hello", 5); - const std::vector& data = dataAccessor.Data(); - EXPECT_EQ(data[0], 'h'); - EXPECT_EQ(data[4], 'o'); -} - -/** - * @tc.name: SizeAccessor - * @tc.desc: - * @tc.type: SizeAccessor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, SizeAccessor, TestSize.Level0) -{ - ZLOGI("SizeAccessor begin."); - Blob sizeAccessor("hello", 5); - EXPECT_EQ(sizeAccessor.Size(), 5u); -} - -/** - * @tc.name: RawSizeAccessor - * @tc.desc: - * @tc.type: RawSizeAccessor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, RawSizeAccessor, TestSize.Level0) -{ - ZLOGI("RawSizeAccessor begin."); - Blob rawSizeAccessor("hello", 5); - EXPECT_EQ(rawSizeAccessor.RawSize(), 9); // sizeof(int) + 5 -} - -/** - * @tc.name: EmptyAccessor - * @tc.desc: - * @tc.type: EmptyAccessor test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, EmptyAccessor, TestSize.Level0) -{ - ZLOGI("EmptyAccessor begin."); - Blob emptyAccessor; - EXPECT_TRUE(emptyAccessor.Empty()); - Blob emptyAccessor2("hello"); - EXPECT_FALSE(emptyAccessor2.Empty()); -} - -/** - * @tc.name: ElementAccessOperator - * @tc.desc: - * @tc.type: ElementAccessOperator test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, ElementAccessOperator, TestSize.Level0) -{ - ZLOGI("ElementAccessOperator begin."); - Blob elementAccessOperator("hello", 5); - EXPECT_EQ(elementAccessOperator[0], 'h'); - EXPECT_EQ(elementAccessOperator[4], 'o'); - EXPECT_EQ(elementAccessOperator[5], 0); -} - -/** - * @tc.name: EqualityOperator - * @tc.desc: - * @tc.type: EqualityOperator test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, EqualityOperator, TestSize.Level0) -{ - ZLOGI("EqualityOperator begin."); - Blob equalityOperator1("hello", 5); - Blob equalityOperator2("hello", 5); - EXPECT_TRUE(equalityOperator1 == equalityOperator2); - Blob equalityOperator3("world", 5); - EXPECT_FALSE(equalityOperator1 == equalityOperator3); -} - -/** - * @tc.name: Clear - * @tc.desc: - * @tc.type: Clear test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, Clear, TestSize.Level0) -{ - ZLOGI("Clear begin."); - Blob blobClear("hello", 5); - blobClear.Clear(); - EXPECT_TRUE(blobClear.Empty()); -} - -/** - * @tc.name: ToString - * @tc.desc: - * @tc.type: ToString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, ToString, TestSize.Level0) -{ - ZLOGI("ToString begin."); - Blob blobToString("hello", 5); - EXPECT_EQ(blobToString.ToString(), "hello"); -} - -/** - * @tc.name: Compare - * @tc.desc: - * @tc.type: Compare test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, Compare, TestSize.Level0) -{ - ZLOGI("Compare begin."); - Blob blobCompare1("abc", 3); - Blob blobCompare2("abcd", 4); - Blob blobCompare3("abc", 3); - EXPECT_LT(blobCompare1.Compare(blobCompare2), 0); - EXPECT_EQ(blobCompare1.Compare(blobCompare3), 0); - EXPECT_GT(blobCompare2.Compare(blobCompare1), 0); -} - -/** - * @tc.name: StartsWith - * @tc.desc: - * @tc.type: StartsWith test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, StartsWith, TestSize.Level0) -{ - ZLOGI("StartsWith begin."); - Blob blobStartsWith1("abcdef", 6); - Blob blobStartsWith2("abc", 3); - Blob blobStartsWith3("abcd", 4); - Blob blobStartsWith4("xyz", 3); - EXPECT_TRUE(blobStartsWith1.StartsWith(blobStartsWith2)); - EXPECT_TRUE(blobStartsWith1.StartsWith(blobStartsWith3)); - EXPECT_FALSE(blobStartsWith1.StartsWith(blobStartsWith4)); -} - -/** - * @tc.name: WriteToBuffer - * @tc.desc: - * @tc.type: WriteToBuffer test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, WriteToBuffer, TestSize.Level0) -{ - ZLOGI("WriteToBuffer begin."); - Blob blobWriteToBuffer("hello", 5); - uint8_t buffer[100]; - uint8_t* cursorPtr = buffer; - int bufferLeftSize = sizeof(buffer); - EXPECT_TRUE(blobWriteToBuffer.WriteToBuffer(cursorPtr, bufferLeftSize)); - EXPECT_EQ(*reinterpret_cast(buffer), 5); - EXPECT_EQ(std::string(reinterpret_cast(buffer + sizeof(int)), 5), "hello"); - EXPECT_EQ(bufferLeftSize, sizeof(buffer) - sizeof(int) - 5); -} - -/** - * @tc.name: ReadFromBuffer - * @tc.desc: - * @tc.type: ReadFromBuffer test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(BlobVirtualTest, ReadFromBuffer, TestSize.Level0) -{ - ZLOGI("ReadFromBuffer begin."); - uint8_t buffer[100]; - int blobSize = 5; - *reinterpret_cast(buffer) = blobSize; - std::string str = "hello"; - strncpy_s(reinterpret_cast(buffer + sizeof(int)), blobSize, str, strlen(str)); - const uint8_t* cursorPtr = buffer; - int bufferLeftSize = sizeof(buffer); - Blob blob; - EXPECT_TRUE(blob.ReadFromBuffer(cursorPtr, bufferLeftSize)); - EXPECT_EQ(std::string(blob.Data().begin(), blob.Data().end()), "hello"); - EXPECT_EQ(bufferLeftSize, sizeof(buffer) - sizeof(int) - blobSize); -} - -/** - * @tc.name: ChangeNotificationVirtualTest001 - * @tc.desc: - * @tc.type: test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(ChangeNotificationVirtualTest, ChangeNotificationVirtualTest001, TestSize.Level0) -{ - ZLOGI("ChangeNotificationVirtualTest001 begin."); - std::vector insertEntries = {{"key1", "value1"}, {"key2", "value2"}}; - std::vector updateEntries = {{"key3", "newValue3"}}; - std::vector deleteEntries = {{"key4", ""}}; - std::string deviceId = "device123"; - bool isClear = false; - - OHOS::DistributedKv::ChangeNotification cn(std::move(insertEntries), - std::move(updateEntries), std::move(deleteEntries), deviceId, isClear); - - EXPECT_TRUE(cn.GetInsertEntries().size() == 2); - EXPECT_TRUE(cn.GetUpdateEntries().size() == 1); - EXPECT_TRUE(cn.GetDeleteEntries().size() == 1); - EXPECT_TRUE(cn.GetDeviceId() == deviceId); - EXPECT_TRUE(!cn.IsClear()); -} - -/** - * @tc.name: ChangeNotificationVirtualTest002 - * @tc.desc: - * @tc.type: test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(ChangeNotificationVirtualTest, ChangeNotificationVirtualTest002, TestSize.Level0) -{ - ZLOGI("ChangeNotificationVirtualTest002 begin."); - std::vector insertEntries; - std::vector updateEntries; - std::vector deleteEntries; - std::string deviceId = "device456"; - bool isClear = true; - - OHOS::DistributedKv::ChangeNotification cn(std::move(insertEntries), - std::move(updateEntries), std::move(deleteEntries), deviceId, isClear); - - EXPECT_TRUE(cn.GetInsertEntries().empty()); - EXPECT_TRUE(cn.GetUpdateEntries().empty()); - EXPECT_TRUE(cn.GetDeleteEntries().empty()); - EXPECT_TRUE(cn.GetDeviceId() == deviceId); - EXPECT_TRUE(cn.IsClear()); -} - -/** - * @tc.name: ChangeNotificationVirtualTest003 - * @tc.desc: - * @tc.type: test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(ChangeNotificationVirtualTest, ChangeNotificationVirtualTest003, TestSize.Level0) -{ - ZLOGI("ChangeNotificationVirtualTest003 begin."); - std::vector insertEntries; - std::vector updateEntries = {{"keyUpdated", "newValue"}}; - std::vector deleteEntries; - std::string deviceId = "device789"; - bool isClear = false; - - OHOS::DistributedKv::ChangeNotification cn(std::move(insertEntries), - std::move(updateEntries), std::move(deleteEntries), deviceId, isClear); - - EXPECT_TRUE(cn.GetInsertEntries().empty()); - EXPECT_TRUE(cn.GetUpdateEntries().size() == 1); - EXPECT_TRUE(cn.GetDeleteEntries().empty()); - EXPECT_TRUE(cn.GetDeviceId() == deviceId); - EXPECT_TRUE(!cn.IsClear()); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/data_query_virtual_test.cpp b/kv_store/databaseutils/test/data_query_virtual_test.cpp deleted file mode 100644 index 5e20203e..00000000 --- a/kv_store/databaseutils/test/data_query_virtual_test.cpp +++ /dev/null @@ -1,1184 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "DataQueryVirtualTest" - -#include "data_query.h" -#include "kv_types_util.h" -#include -#include "types.h" -#include -#include -#include - -using namespace OHOS::DistributedKv; -using namespace testing; -using namespace testing::ext; -namespace OHOS::Test { -class DataQueryVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void DataQueryVirtualTest::SetUpTestCase(void) -{} - -void DataQueryVirtualTest::TearDownTestCase(void) -{} - -void DataQueryVirtualTest::SetUp(void) -{} - -void DataQueryVirtualTest::TearDown(void) -{} - -class MockQuery { -public: - MOCK_METHOD2(Range, void(const std::vector&, const std::vector&)); - MOCK_METHOD1(IsNull, void(const std::string&)); - MOCK_METHOD1(IsNotNull, void(const std::string&)); -}; - -/** - * @tc.name: Reset - * @tc.desc: - * @tc.type: Reset test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, Reset, TestSize.Level0) -{ - ZLOGI("ResetTest begin."); - DataQuery queryReset; - queryReset.EqualTo("field1", 123); - queryReset.Reset(); - EXPECT_EQ(queryReset.str_, ""); - EXPECT_FALSE(queryReset.hasKeys_); - EXPECT_FALSE(queryReset.hasPrefix_); - EXPECT_EQ(queryReset.deviceId_, ""); - EXPECT_EQ(queryReset.prefix_, ""); -} - -/** - * @tc.name: EqualToInteger - * @tc.desc: - * @tc.type: EqualToInteger test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, EqualToInteger, TestSize.Level0) -{ - ZLOGI("EqualToInteger begin."); - DataQuery queryEqualToInteger; - queryEqualToInteger.EqualTo("field1", 123); - EXPECT_EQ(queryEqualToInteger.str_, - std::string(DataQuery::EQUAL_TO) + " " + DataQuery::TYPE_INTEGER + " field1 123"); -} - -/** - * @tc.name: EqualToLong - * @tc.desc: - * @tc.type: EqualToLong test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, EqualToLong, TestSize.Level0) -{ - ZLOGI("EqualToLong begin."); - DataQuery queryEqualToLong; - queryEqualToLong.EqualTo("field1", 123456789012345LL); - EXPECT_EQ(queryEqualToLong.str_, - std::string(DataQuery::EQUAL_TO) + " " + DataQuery::TYPE_LONG + " field1 123456789012345"); -} - -/** - * @tc.name: EqualToDouble - * @tc.desc: - * @tc.type: EqualToDouble test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, EqualToDouble, TestSize.Level0) -{ - ZLOGI("EqualToDouble begin."); - DataQuery queryEqualToDouble; - queryEqualToDouble.EqualTo("field1", 123.45); - EXPECT_EQ(queryEqualToDouble.str_, - std::string(DataQuery::EQUAL_TO) + " " + DataQuery::TYPE_DOUBLE + " field1 123.45"); -} - -/** - * @tc.name: EqualToString - * @tc.desc: - * @tc.type: EqualToString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, EqualToString, TestSize.Level0) -{ - ZLOGI("EqualToString begin."); - DataQuery queryEqualToString; - queryEqualToString.EqualTo("field1", "testValue"); - EXPECT_EQ(queryEqualToString.str_, - std::string(DataQuery::EQUAL_TO) + " " + DataQuery::TYPE_STRING + " field1 testValue"); -} - -/** - * @tc.name: EqualToBooleanTrue - * @tc.desc: - * @tc.type: EqualToBooleanTrue test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, EqualToBooleanTrue, TestSize.Level0) -{ - ZLOGI("EqualToBooleanTrue begin."); - DataQuery queryEqualToBooleanTrue; - queryEqualToBooleanTrue.EqualTo("field1", true); - EXPECT_EQ(queryEqualToBooleanTrue.str_, - std::string(DataQuery::EQUAL_TO) + " " + DataQuery::TYPE_BOOLEAN + " field1 true"); -} - -/** - * @tc.name: EqualToBooleanFalse - * @tc.desc: - * @tc.type: EqualToBooleanFalse test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, EqualToBooleanFalse, TestSize.Level0) -{ - ZLOGI("EqualToBooleanFalse begin."); - DataQuery queryEqualToBooleanFalse; - queryEqualToBooleanFalse.EqualTo("field1", false); - EXPECT_EQ(queryEqualToBooleanFalse.str_, - std::string(DataQuery::EQUAL_TO) + " " + DataQuery::TYPE_BOOLEAN + " field1 false"); -} - -/** - * @tc.name: NotEqualToInteger - * @tc.desc: - * @tc.type: NotEqualToInteger test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotEqualToInteger, TestSize.Level0) -{ - ZLOGI("NotEqualToInteger begin."); - DataQuery queryNotEqualToInteger; - queryNotEqualToInteger.NotEqualTo("field1", 123); - EXPECT_EQ(queryNotEqualToInteger.str_, - std::string(DataQuery::NOT_EQUAL_TO) + " " + DataQuery::TYPE_INTEGER + " field1 123"); -} - -/** - * @tc.name: NotEqualToLong - * @tc.desc: - * @tc.type: NotEqualToLong test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotEqualToLong, TestSize.Level0) -{ - ZLOGI("NotEqualToLong begin."); - DataQuery queryNotEqualToLong; - queryNotEqualToLong.NotEqualTo("field1", 123456789012345LL); - EXPECT_EQ(queryNotEqualToLong.str_, - std::string(DataQuery::NOT_EQUAL_TO) + " " + DataQuery::TYPE_LONG + " field1 123456789012345"); -} - -/** - * @tc.name: NotEqualToDouble - * @tc.desc: - * @tc.type: NotEqualToDouble test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotEqualToDouble, TestSize.Level0) -{ - ZLOGI("NotEqualToDouble begin."); - DataQuery queryNotEqualToDouble; - queryNotEqualToDouble.NotEqualTo("field1", 123.45); - EXPECT_EQ(queryNotEqualToDouble.str_, - std::string(DataQuery::NOT_EQUAL_TO) + " " + DataQuery::TYPE_DOUBLE + " field1 123.45"); -} - -/** - * @tc.name: NotEqualToString - * @tc.desc: - * @tc.type: NotEqualToString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotEqualToString, TestSize.Level0) -{ - ZLOGI("NotEqualToString begin."); - DataQuery queryNotEqualToString; - queryNotEqualToString.NotEqualTo("field1", "testValue"); - EXPECT_EQ(queryNotEqualToString.str_, - std::string(DataQuery::NOT_EQUAL_TO) + " " + DataQuery::TYPE_STRING + " field1 testValue"); -} - -/** - * @tc.name: NotEqualToBooleanTrue - * @tc.desc: - * @tc.type: NotEqualToBooleanTrue test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotEqualToBooleanTrue, TestSize.Level0) -{ - ZLOGI("NotEqualToBooleanTrue begin."); - DataQuery queryNotEqualToBooleanTrue; - queryNotEqualToBooleanTrue.NotEqualTo("field1", true); - EXPECT_EQ(queryNotEqualToBooleanTrue.str_, - std::string(DataQuery::NOT_EQUAL_TO) + " " + DataQuery::TYPE_BOOLEAN + " field1 true"); -} - -/** - * @tc.name: NotEqualToBooleanFalse - * @tc.desc: - * @tc.type: NotEqualToBooleanFalse test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotEqualToBooleanFalse, TestSize.Level0) -{ - ZLOGI("NotEqualToBooleanFalse begin."); - DataQuery queryNotEqualToBooleanFalse; - queryNotEqualToBooleanFalse.NotEqualTo("field1", false); - EXPECT_EQ(queryNotEqualToBooleanFalse.str_, - std::string(DataQuery::NOT_EQUAL_TO) + " " + DataQuery::TYPE_BOOLEAN + " field1 false"); -} - -/** - * @tc.name: GreaterThanInteger - * @tc.desc: - * @tc.type: GreaterThanInteger test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GreaterThanInteger, TestSize.Level0) -{ - ZLOGI("GreaterThanInteger begin."); - DataQuery queryNotEqualToBooleanFalse; - queryGreaterThanInteger.GreaterThan("field1", 123); - EXPECT_EQ(queryGreaterThanInteger.str_, - std::string(DataQuery::GREATER_THAN) + " " + DataQuery::TYPE_INTEGER + " field1 123"); -} - -/** - * @tc.name: GreaterThanLong - * @tc.desc: - * @tc.type: GreaterThanLong test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GreaterThanLong, TestSize.Level0) -{ - ZLOGI("GreaterThanLong begin."); - DataQuery queryGreaterThanLong; - queryGreaterThanLong.GreaterThan("field1", 123456789012345LL); - EXPECT_EQ(queryGreaterThanLong.str_, - std::string(DataQuery::GREATER_THAN) + " " + DataQuery::TYPE_LONG + " field1 123456789012345"); -} - -/** - * @tc.name: GreaterThanDouble - * @tc.desc: - * @tc.type: GreaterThanDouble test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GreaterThanDouble, TestSize.Level0) -{ - ZLOGI("GreaterThanDouble begin."); - DataQuery queryGreaterThanDouble; - queryGreaterThanDouble.GreaterThan("field1", 123.45); - EXPECT_EQ(queryGreaterThanDouble.str_, - std::string(DataQuery::GREATER_THAN) + " " + DataQuery::TYPE_DOUBLE + " field1 123.45"); -} - -/** - * @tc.name: GreaterThanString - * @tc.desc: - * @tc.type: GreaterThanString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GreaterThanString, TestSize.Level0) -{ - ZLOGI("GreaterThanString begin."); - DataQuery queryGreaterThanString; - queryGreaterThanString.GreaterThan("field1", "testValue"); - EXPECT_EQ(queryGreaterThanString.str_, - std::string(DataQuery::GREATER_THAN) + " " + DataQuery::TYPE_STRING + " field1 testValue"); -} - -/** - * @tc.name: LessThanInteger - * @tc.desc: - * @tc.type: LessThanInteger test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, LessThanInteger, TestSize.Level0) -{ - ZLOGI("LessThanInteger begin."); - DataQuery queryLessThanInteger; - queryLessThanInteger.LessThan("field1", 123); - EXPECT_EQ(queryLessThanInteger.str_, - std::string(DataQuery::LESS_THAN) + " " + DataQuery::TYPE_INTEGER + " field1 123"); -} - -/** - * @tc.name: LessThanLong - * @tc.desc: - * @tc.type: LessThanLong test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, LessThanLong, TestSize.Level0) -{ - ZLOGI("GreaterThanLong begin."); - DataQuery queryLessThanLong; - queryLessThanLong.LessThan("field1", 123456789012345LL); - EXPECT_EQ(queryLessThanLong.str_, - std::string(DataQuery::LESS_THAN) + " " + DataQuery::TYPE_LONG + " field1 123456789012345"); -} - -/** - * @tc.name: LessThanDouble - * @tc.desc: - * @tc.type: LessThanDouble test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, LessThanDouble, TestSize.Level0) -{ - ZLOGI("LessThanDouble begin."); - DataQuery queryLessThanDouble; - queryLessThanDouble.LessThan("field1", 123.45); - EXPECT_EQ(queryLessThanDouble.str_, - std::string(DataQuery::LESS_THAN) + " " + DataQuery::TYPE_DOUBLE + " field1 123.45"); -} - -/** - * @tc.name: LessThanString - * @tc.desc: - * @tc.type: LessThanString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, LessThanString, TestSize.Level0) -{ - ZLOGI("LessThanString begin."); - DataQuery queryLessThanString; - queryLessThanString.LessThan("field1", "testValue"); - EXPECT_EQ(queryLessThanString.str_, - std::string(DataQuery::LESS_THAN) + " " + DataQuery::TYPE_STRING + " field1 testValue"); -} - -/** - * @tc.name: GreaterThanOrEqualToInteger - * @tc.desc: - * @tc.type: GreaterThanOrEqualToInteger test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GreaterThanOrEqualToInteger, TestSize.Level0) -{ - ZLOGI("LessThanInteger begin."); - DataQuery queryGreaterThanOrEqualToInteger; - queryGreaterThanOrEqualToInteger.GreaterThanOrEqualTo("field1", 123); - EXPECT_EQ(queryGreaterThanOrEqualToInteger.str_, - std::string(DataQuery::GREATER_THAN_OR_EQUAL_TO) + " " + DataQuery::TYPE_INTEGER + " field1 123"); -} - -/** - * @tc.name: GreaterThanOrEqualToLong - * @tc.desc: - * @tc.type: GreaterThanOrEqualToLong test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GreaterThanOrEqualToLong, TestSize.Level0) -{ - ZLOGI("GreaterThanLong begin."); - DataQuery queryGreaterThanOrEqualToLong; - queryGreaterThanOrEqualToLong.GreaterThanOrEqualTo("field1", 123456789012345LL); - EXPECT_EQ(queryGreaterThanOrEqualToLong.str_, - std::string(DataQuery::GREATER_THAN_OR_EQUAL_TO) + " " + DataQuery::TYPE_LONG + " field1 123456789012345"); -} - -/** - * @tc.name: GreaterThanOrEqualToDouble - * @tc.desc: - * @tc.type: GreaterThanOrEqualToDouble test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GreaterThanOrEqualToDouble, TestSize.Level0) -{ - ZLOGI("LessThanDouble begin."); - DataQuery queryGreaterThanOrEqualToDouble; - queryGreaterThanOrEqualToDouble.GreaterThanOrEqualTo("field1", 123.45); - EXPECT_EQ(queryGreaterThanOrEqualToDouble.str_, - std::string(DataQuery::GREATER_THAN_OR_EQUAL_TO) + " " + DataQuery::TYPE_DOUBLE + " field1 123.45"); -} - -/** - * @tc.name: GreaterThanOrEqualToString - * @tc.desc: - * @tc.type: GreaterThanOrEqualToString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GreaterThanOrEqualToString, TestSize.Level0) -{ - ZLOGI("LessThanString begin."); - DataQuery queryGreaterThanOrEqualToString; - queryGreaterThanOrEqualToString.GreaterThanOrEqualTo("field1", "testValue"); - EXPECT_EQ(queryGreaterThanOrEqualToString.str_, - std::string(DataQuery::GREATER_THAN_OR_EQUAL_TO) + " " + DataQuery::TYPE_STRING + " field1 testValue"); -} - -/** - * @tc.name: LessThanOrEqualToInteger - * @tc.desc: - * @tc.type: LessThanOrEqualToInteger test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, LessThanOrEqualToInteger, TestSize.Level0) -{ - ZLOGI("LessThanOrEqualToInteger begin."); - DataQuery queryLessThanOrEqualToInteger; - queryLessThanOrEqualToInteger.LessThanOrEqualTo("field1", 123); - EXPECT_EQ(queryLessThanOrEqualToInteger.str_, - std::string(DataQuery::LESS_THAN_OR_EQUAL_TO) + " " + DataQuery::TYPE_INTEGER + " field1 123"); -} - -/** - * @tc.name: LessThanOrEqualToLong - * @tc.desc: - * @tc.type: LessThanOrEqualToLong test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, LessThanOrEqualToLong, TestSize.Level0) -{ - ZLOGI("LessThanOrEqualToLong begin."); - DataQuery queryLessThanOrEqualToLong; - queryLessThanOrEqualToLong.LessThanOrEqualTo("field1", 123456789012345LL); - EXPECT_EQ(queryLessThanOrEqualToLong.str_, - std::string(DataQuery::LESS_THAN_OR_EQUAL_TO) + " " + DataQuery::TYPE_LONG + " field1 123456789012345"); -} - -/** - * @tc.name: LessThanOrEqualToDouble - * @tc.desc: - * @tc.type: LessThanOrEqualToDouble test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, LessThanOrEqualToDouble, TestSize.Level0) -{ - ZLOGI("LessThanOrEqualToDouble begin."); - DataQuery queryLessThanOrEqualToDouble; - queryLessThanOrEqualToDouble.LessThanOrEqualTo("field1", 123.45); - EXPECT_EQ(queryLessThanOrEqualToDouble.str_, - std::string(DataQuery::LESS_THAN_OR_EQUAL_TO) + " " + DataQuery::TYPE_DOUBLE + " field1 123.45"); -} - -/** - * @tc.name: LessThanOrEqualToString - * @tc.desc: - * @tc.type: LessThanOrEqualToString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, LessThanOrEqualToString, TestSize.Level0) -{ - ZLOGI("LessThanOrEqualToString begin."); - DataQuery queryLessThanOrEqualToString; - queryLessThanOrEqualToString.LessThanOrEqualTo("field1", "testValue"); - EXPECT_EQ(queryLessThanOrEqualToString.str_, - std::string(DataQuery::LESS_THAN_OR_EQUAL_TO) + " " + DataQuery::TYPE_STRING + " field1 testValue"); -} - -/** - * @tc.name: Between_ValidInputs_CallsRange - * @tc.desc: - * @tc.type: Between_ValidInputs_CallsRange test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, Between_ValidInputs_CallsRange, TestSize.Level0) -{ - ZLOGI("Between_ValidInputs_CallsRange begin."); - MockQuery mockQuery; - DataQuery queryBetween(&mockQuery); - - EXPECT_CALL(mockQuery, Range(ElementsAre('a', 'b'), ElementsAre('c', 'd'))); - - queryBetween.Between("ab", "cd"); -} - -/** - * @tc.name: IsNull_ValidField_UpdatesStringAndCallsIsNull - * @tc.desc: - * @tc.type: IsNull_ValidField_UpdatesStringAndCallsIsNull test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, IsNull_ValidField_UpdatesStringAndCallsIsNull, TestSize.Level0) -{ - ZLOGI("IsNull_ValidField_UpdatesStringAndCallsIsNull begin."); - MockQuery mockQuery; - DataQuery queryIsNull(&mockQuery); - - EXPECT_CALL(mockQuery, IsNull("field")); - - queryIsNull.IsNull("field"); -} - -/** - * @tc.name: IsNull_InvalidField_DoesNotUpdateStringOrCallIsNull - * @tc.desc: - * @tc.type: IsNull_InvalidField_DoesNotUpdateStringOrCallIsNull test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, IsNull_InvalidField_DoesNotUpdateStringOrCallIsNull, TestSize.Level0) -{ - ZLOGI("IsNull_InvalidField_DoesNotUpdateStringOrCallIsNull begin."); - MockQuery mockQuery; - DataQuery queryIsNull(&mockQuery); - - EXPECT_CALL(mockQuery, IsNull(_)).Times(0); - - queryIsNull.IsNull("invalid field"); -} - -/** - * @tc.name: IsNotNull_ValidField_UpdatesStringAndCallsIsNotNull - * @tc.desc: - * @tc.type: IsNotNull_ValidField_UpdatesStringAndCallsIsNotNull test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, IsNotNull_ValidField_UpdatesStringAndCallsIsNotNull, TestSize.Level0) -{ - ZLOGI("IsNotNull_ValidField_UpdatesStringAndCallsIsNotNull begin."); - MockQuery mockQuery; - DataQuery queryIsNotNull(&mockQuery); - - EXPECT_CALL(mockQuery, IsNotNull("field")); - - queryIsNotNull.IsNotNull("field"); -} - -/** - * @tc.name: IsNotNull_InvalidField_DoesNotUpdateStringOrCallIsNotNull - * @tc.desc: - * @tc.type: IsNotNull_InvalidField_DoesNotUpdateStringOrCallIsNotNull test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, IsNotNull_InvalidField_DoesNotUpdateStringOrCallIsNotNull, TestSize.Level0) -{ - ZLOGI("IsNotNull_InvalidField_DoesNotUpdateStringOrCallIsNotNull begin."); - MockQuery mockQuery; - DataQuery queryIsNotNull(&mockQuery); - - EXPECT_CALL(mockQuery, IsNotNull(_)).Times(0); - - query.IsNotNull("invalid field"); -} - -/** - * @tc.name: InInteger - * @tc.desc: - * @tc.type: InInteger test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, InInteger, TestSize.Level0) -{ - ZLOGI("InInteger begin."); - DataQuery queryInInteger; - queryInInteger.In("field1", 123); - EXPECT_EQ(queryInInteger.str_, - std::string(DataQuery::IN) + " " + DataQuery::TYPE_INTEGER + " field1 123"); -} - -/** - * @tc.name: InLong - * @tc.desc: - * @tc.type: InLong test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, InLong, TestSize.Level0) -{ - ZLOGI("InLong begin."); - DataQuery queryInLong; - queryInLong.In("field1", 123456789012345LL); - EXPECT_EQ(queryInLong.str_, - std::string(DataQuery::IN) + " " + DataQuery::TYPE_LONG + " field1 123456789012345"); -} - -/** - * @tc.name: InDouble - * @tc.desc: - * @tc.type: InDouble test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, InDouble, TestSize.Level0) -{ - ZLOGI("InDouble begin."); - DataQuery queryInDouble; - queryInDouble.In("field1", 123.45); - EXPECT_EQ(queryInDouble.str_, - std::string(DataQuery::IN) + " " + DataQuery::TYPE_DOUBLE + " field1 123.45"); -} - -/** - * @tc.name: InString - * @tc.desc: - * @tc.type: InString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, InString, TestSize.Level0) -{ - ZLOGI("InString begin."); - DataQuery queryInString; - queryInString.In("field1", "testValue"); - EXPECT_EQ(queryInString.str_, - std::string(DataQuery::IN) + " " + DataQuery::TYPE_STRING + " field1 testValue"); -} - -/** - * @tc.name: NotInInteger - * @tc.desc: - * @tc.type: NotInInteger test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotInInteger, TestSize.Level0) -{ - ZLOGI("NotInInteger begin."); - DataQuery queryNotInInteger; - queryNotInInteger.NotIn("field1", 123); - EXPECT_EQ(queryNotInInteger.str_, - std::string(DataQuery::NOT_IN) + " " + DataQuery::TYPE_INTEGER + " field1 123"); -} - -/** - * @tc.name: NotInLong - * @tc.desc: - * @tc.type: NotInLong test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotInLong, TestSize.Level0) -{ - ZLOGI("NotInLong begin."); - DataQuery queryNotInLong; - queryNotInLong.NotIn("field1", 123456789012345LL); - EXPECT_EQ(queryNotInLong.str_, - std::string(DataQuery::NOT_IN) + " " + DataQuery::TYPE_LONG + " field1 123456789012345"); -} - -/** - * @tc.name: NotInDouble - * @tc.desc: - * @tc.type: NotInDouble test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotInDouble, TestSize.Level0) -{ - ZLOGI("InDouble begin."); - DataQuery queryNotInDouble; - queryNotInDouble.NotIn("field1", 123.45); - EXPECT_EQ(queryNotInDouble.str_, - std::string(DataQuery::NOT_IN) + " " + DataQuery::TYPE_DOUBLE + " field1 123.45"); -} - -/** - * @tc.name: NotInString - * @tc.desc: - * @tc.type: NotInString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, NotInString, TestSize.Level0) -{ - ZLOGI("NotInString begin."); - DataQuery queryNotInString; - queryNotInString.NotIn("field1", "testValue"); - EXPECT_EQ(queryNotInString.str_, - std::string(DataQuery::NOT_IN) + " " + DataQuery::TYPE_STRING + " field1 testValue"); -} - -/** - * @tc.name: Like_ValidFieldAndValue_AppendsToQuery - * @tc.desc: - * @tc.type: Like_ValidFieldAndValue_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, Like_ValidFieldAndValue_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("Like_ValidFieldAndValue_AppendsToQuery begin."); - std::shared_ptr queryLikeMock = std::make_shared(); - DataQuery queryLike; - EXPECT_CALL(*queryLikeMock, Like("field", "value")).Times(1); - queryLike.Like("field", "value"); - EXPECT_EQ(queryLike.ToString(), std::string(DataQuery::LIKE) + " field value"); -} - -/** - * @tc.name: Unlike_ValidFieldAndValue_AppendsToQuery - * @tc.desc: - * @tc.type: Unlike_ValidFieldAndValue_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, Unlike_ValidFieldAndValue_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("Unlike_ValidFieldAndValue_AppendsToQuery begin."); - std::shared_ptr queryUnlikeMock = std::make_shared(); - DataQuery queryUnlike; - EXPECT_CALL(*queryUnlikeMock, NotLike("field", "value")).Times(1); - queryUnlike.Unlike("field", "value"); - EXPECT_EQ(queryUnlike.ToString(), std::string(DataQuery::NOT_LIKE) + " field1 testValue"); -} - -/** - * @tc.name: And_AppendsAndToQuery - * @tc.desc: - * @tc.type: And_AppendsAndToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, And_AppendsAndToQuery, TestSize.Level0) -{ - ZLOGI("And_AppendsAndToQuery begin."); - std::shared_ptr queryAndMock = std::make_shared(); - DataQuery queryAnd; - EXPECT_CALL(*queryAndMock, And()).Times(1); - queryAnd.And(); - EXPECT_EQ(queryAnd.ToString(), " AND"); -} - -/** - * @tc.name: Or_AppendsOrToQuery - * @tc.desc: - * @tc.type: Or_AppendsOrToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, Or_AppendsOrToQuery, TestSize.Level0) -{ - ZLOGI("Or_AppendsOrToQuery begin."); - std::shared_ptr queryOrMock = std::make_shared(); - DataQuery queryOr; - EXPECT_CALL(*queryOrMock, Or()).Times(1); - queryOr.Or(); - EXPECT_EQ(queryOr.ToString(), " OR"); -} - -/** - * @tc.name: OrderByAsc_ValidField_AppendsToQuery - * @tc.desc: - * @tc.type: OrderByAsc_ValidField_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, OrderByAsc_ValidField_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("OrderByAsc_ValidField_AppendsToQuery begin."); - std::shared_ptr queryOrderByAscMock = std::make_shared(); - DataQuery queryOrderByAsc; - EXPECT_CALL(*queryOrderByAscMock, OrderBy("field")).Times(1); - queryOrderByAsc.OrderByAsc("field"); - EXPECT_EQ(queryOrderByAsc.ToString(), " ORDER BY ASC field"); -} - -/** - * @tc.name: OrderByDesc_ValidField_AppendsToQuery - * @tc.desc: - * @tc.type: OrderByDesc_ValidField_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, OrderByDesc_ValidField_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("OrderByDesc_ValidField_AppendsToQuery begin."); - std::shared_ptr queryOrderByDescMock = std::make_shared(); - DataQuery queryOrderByDesc; - EXPECT_CALL(*queryOrderByDescMock, OrderBy("field", false)).Times(1); - queryOrderByDesc.OrderByDesc("field"); - EXPECT_EQ(queryOrderByDesc.ToString(), " ORDER BY DESC field"); -} - -/** - * @tc.name: OrderByWriteTime_Ascending_AppendsToQuery - * @tc.desc: - * @tc.type: OrderByWriteTime_Ascending_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, OrderByWriteTime_Ascending_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("OrderByWriteTime_Ascending_AppendsToQuery begin."); - std::shared_ptr queryOrderByWriteTimeMock = std::make_shared(); - DataQuery queryOrderByWriteTime; - EXPECT_CALL(*queryOrderByWriteTimeMock, OrderByWriteTime(true)).Times(1); - queryOrderByWriteTime.OrderByWriteTime(true); - EXPECT_EQ(queryOrderByWriteTime.ToString(), " ORDER BY WRITE_TIME ASC"); -} - -/** - * @tc.name: OrderByWriteTime_Descending_AppendsToQuery - * @tc.desc: - * @tc.type: OrderByWriteTime_Descending_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, OrderByWriteTime_Descending_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("OrderByWriteTime_Descending_AppendsToQuery begin."); - std::shared_ptr queryOrderByWriteTimeMock = std::make_shared(); - DataQuery queryOrderByWriteTime; - EXPECT_CALL(*queryMock, OrderByWriteTime(false)).Times(1); - queryOrderByWriteTime.OrderByWriteTime(false); - EXPECT_EQ(queryOrderByWriteTime.ToString(), " ORDER BY WRITE_TIME DESC"); -} - -/** - * @tc.name: Limit_ValidNumberAndOffset_AppendsToQuery - * @tc.desc: - * @tc.type: Limit_ValidNumberAndOffset_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, Limit_ValidNumberAndOffset_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("Limit_ValidNumberAndOffset_AppendsToQuery begin."); - std::shared_ptr queryLimitMock = std::make_shared(); - DataQuery queryLimit; - EXPECT_CALL(*queryLimitMock, Limit(10, 0)).Times(1); - queryLimit.Limit(10, 0); - EXPECT_EQ(queryLimit.ToString(), " LIMIT 10 0"); -} - -/** - * @tc.name: BeginGroup_AppendsBeginGroupToQuery - * @tc.desc: - * @tc.type: BeginGroup_AppendsBeginGroupToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, BeginGroup_AppendsBeginGroupToQuery, TestSize.Level0) -{ - ZLOGI("BeginGroup_AppendsBeginGroupToQuery begin."); - std::shared_ptr queryBeginGroupMock = std::make_shared(); - DataQuery queryBeginGroup; - EXPECT_CALL(*queryBeginGroupMock, BeginGroup()).Times(1); - queryBeginGroup.BeginGroup(); - EXPECT_EQ(queryBeginGroup.ToString(), " ("); -} - -/** - * @tc.name: EndGroup_AppendsEndGroupToQuery - * @tc.desc: - * @tc.type: EndGroup_AppendsEndGroupToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, EndGroup_AppendsEndGroupToQuery, TestSize.Level0) -{ - ZLOGI("EndGroup_AppendsEndGroupToQuery begin."); - std::shared_ptr queryEndGroupMock = std::make_shared(); - DataQuery queryEndGroup; - EXPECT_CALL(*queryEndGroupMock, EndGroup()).Times(1); - queryEndGroup.EndGroup(); - EXPECT_EQ(queryEndGroup.ToString(), " )"); -} - -/** - * @tc.name: KeyPrefix_ValidPrefix_AppendsToQuery - * @tc.desc: - * @tc.type: KeyPrefix_ValidPrefix_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, KeyPrefix_ValidPrefix_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("KeyPrefix_ValidPrefix_AppendsToQuery begin."); - std::shared_ptr queryKeyPrefixMock = std::make_shared(); - DataQuery queryKeyPrefix; - EXPECT_CALL(*queryKeyPrefixMock, KeyPrefix("prefix")).Times(1); - queryKeyPrefix.KeyPrefix("prefix"); - EXPECT_EQ(queryKeyPrefix.ToString(), " KEY_PREFIX prefix"); -} - -/** - * @tc.name: DeviceId_ValidDeviceId_AppendsToQuery - * @tc.desc: - * @tc.type: DeviceId_ValidDeviceId_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, DeviceId_ValidDeviceId_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("DeviceId_ValidDeviceId_AppendsToQuery begin."); - std::shared_ptr queryDeviceIdMock = std::make_shared(); - DataQuery queryDeviceId; - EXPECT_CALL(*queryDeviceIdMock, DeviceId("deviceId")).Times(1); - queryDeviceId.DeviceId("deviceId"); - EXPECT_EQ(queryDeviceId.ToString(), " DEVICE_ID deviceId"); -} - -/** - * @tc.name: SetSuggestIndex_ValidIndex_AppendsToQuery - * @tc.desc: - * @tc.type: SetSuggestIndex_ValidIndex_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, SetSuggestIndex_ValidIndex_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("DeviceId_ValidDeviceId_AppendsToQuery begin."); - std::shared_ptr querySetSuggestIndexMock = std::make_shared(); - DataQuery querySetSuggestIndex; - EXPECT_CALL(*querySetSuggestIndexMock, SuggestIndex("index")).Times(1); - querySetSuggestIndex.SetSuggestIndex("index"); - EXPECT_EQ(querySetSuggestIndex.ToString(), " SUGGEST_INDEX index"); -} - -/** - * @tc.name: InKeys_ValidKeys_AppendsToQuery - * @tc.desc: - * @tc.type: InKeys_ValidKeys_AppendsToQuery test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, InKeys_ValidKeys_AppendsToQuery, TestSize.Level0) -{ - ZLOGI("InKeys_ValidKeys_AppendsToQuery begin."); - std::shared_ptr queryInKeysMock = std::make_shared(); - DataQuery queryInKeys; - std::vector keys = {"key1", "key2"}; - EXPECT_CALL(*queryInKeysMock, InKeys(keys)).Times(1); - queryInKeys.InKeys(keys); - EXPECT_EQ(queryInKeys.ToString(), " IN_KEYS START_IN key1 key2 END_IN"); -} - -/** - * @tc.name: ToString_QueryTooLong_ReturnsEmptyString - * @tc.desc: - * @tc.type: ToString_QueryTooLong_ReturnsEmptyString test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, ToString_QueryTooLong_ReturnsEmptyString, TestSize.Level0) -{ - ZLOGI("ToString_QueryTooLong_ReturnsEmptyString begin."); - DataQuery queryToString; - queryToString.str_.assign(MAX_QUERY_LENGTH + 1, 'a'); - EXPECT_EQ(queryToString.ToString(), ""); -} - -/** - * @tc.name: AppendCommon_ValidInput_CorrectAppending - * @tc.desc: - * @tc.type: AppendCommon_ValidInput_CorrectAppending test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, AppendCommon_ValidInput_CorrectAppending, TestSize.Level0) -{ - ZLOGI("AppendCommon_ValidInput_CorrectAppending begin."); - DataQuery queryAppendCommon; - string keyword = "key"; - string fieldType = "type"; - string field = "field"; - int value = 123; - queryAppendCommon.AppendCommon(keyword, fieldType, field, value); - EXPECT_EQ(queryAppendCommon.GetQuery(), " key type field 123"); -} - -/** - * @tc.name: AppendCommonString_ValidInput_CorrectAppending - * @tc.desc: - * @tc.type: AppendCommonString_ValidInput_CorrectAppending test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, AppendCommonString_ValidInput_CorrectAppending, TestSize.Level0) -{ - ZLOGI("AppendCommonString_ValidInput_CorrectAppending begin."); - DataQuery queryAppendCommonString; - string keyword = "key"; - string fieldType = "type"; - string field = "field"; - string value = "value"; - queryAppendCommonString.AppendCommonString(keyword, fieldType, field, value); - EXPECT_EQ(queryAppendCommonString.GetQuery(), " key type field value"); -} - -/** - * @tc.name: AppendCommonBoolean_ValidInput_CorrectAppending - * @tc.desc: - * @tc.type: AppendCommonBoolean_ValidInput_CorrectAppending test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, AppendCommonBoolean_ValidInput_CorrectAppending, TestSize.Level0) -{ - ZLOGI("AppendCommonBoolean_ValidInput_CorrectAppending begin."); - DataQuery queryAppendCommonBoolean; - string keyword = "key"; - string fieldType = "type"; - string field = "field"; - bool value = true; - queryAppendCommonBoolean.AppendCommonBoolean(keyword, fieldType, field, value); - EXPECT_EQ(queryAppendCommonBoolean.GetQuery(), " key type field true"); -} - -/** - * @tc.name: AppendCommonList_ValidInput_CorrectAppending - * @tc.desc: - * @tc.type: AppendCommonList_ValidInput_CorrectAppending test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, AppendCommonList_ValidInput_CorrectAppending, TestSize.Level0) -{ - ZLOGI("AppendCommonList_ValidInput_CorrectAppending begin."); - DataQuery queryAppendCommonList; - string keyword = "key"; - string fieldType = "type"; - string field = "field"; - vector valueList = {1, 2, 3}; - queryAppendCommonList.AppendCommonList(keyword, fieldType, field, valueList); - EXPECT_EQ(queryAppendCommonList.GetQuery(), " key type field ( 1 2 3 )"); -} - -/** - * @tc.name: AppendCommonListString_ValidInput_CorrectAppending - * @tc.desc: - * @tc.type: AppendCommonListString_ValidInput_CorrectAppending test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, AppendCommonListString_ValidInput_CorrectAppending, TestSize.Level0) -{ - ZLOGI("AppendCommonListString_ValidInput_CorrectAppending begin."); - DataQuery queryAppendCommonListString; - string keyword = "key"; - string fieldType = "type"; - string field = "field"; - vector valueList = {"value1", "value2"}; - queryAppendCommonListString.AppendCommonListString(keyword, fieldType, field, valueList); - EXPECT_EQ(queryAppendCommonListString.GetQuery(), " key type field ( value1 value2 )"); -} - -/** - * @tc.name: EscapeSpace_ValidInput_CorrectEscaping - * @tc.desc: - * @tc.type: EscapeSpace_ValidInput_CorrectEscaping test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, EscapeSpace_ValidInput_CorrectEscaping, TestSize.Level0) -{ - ZLOGI("EscapeSpace_ValidInput_CorrectEscaping begin."); - DataQuery queryEscapeSpace; - string input = "field with space"; - queryEscapeSpace.EscapeSpace(input); - EXPECT_EQ(input, "field\\ with\\ space"); -} - -/** - * @tc.name: ValidateField_ValidField_ReturnsTrue - * @tc.desc: - * @tc.type: ValidateField_ValidField_ReturnsTrue test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, ValidateField_ValidField_ReturnsTrue, TestSize.Level0) -{ - ZLOGI("ValidateField_ValidField_ReturnsTrue begin."); - DataQuery queryValidateField; - string field = "validField"; - EXPECT_TRUE(queryValidateField.ValidateField(field)); -} - -/** - * @tc.name: ValidateField_EmptyField_ReturnsFalse - * @tc.desc: - * @tc.type: ValidateField_EmptyField_ReturnsFalse test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, ValidateField_EmptyField_ReturnsFalse, TestSize.Level0) -{ - ZLOGI("ValidateField_EmptyField_ReturnsFalse begin."); - DataQuery queryValidateField; - string field = ""; - EXPECT_FALSE(queryValidateField.ValidateField(field)); -} - -/** - * @tc.name: ValidateField_FieldWithSpecialChar_ReturnsFalse - * @tc.desc: - * @tc.type: ValidateField_FieldWithSpecialChar_ReturnsFalse test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, ValidateField_FieldWithSpecialChar_ReturnsFalse, TestSize.Level0) -{ - ZLOGI("ValidateField_FieldWithSpecialChar_ReturnsFalse begin."); - DataQuery queryValidateField; - string field = "field with special*char"; - EXPECT_FALSE(queryValidateField.ValidateField(field)); -} - -/** - * @tc.name: BasicToString_ValidInput_CorrectConversion - * @tc.desc: - * @tc.type: BasicToString_ValidInput_CorrectConversion test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, BasicToString_ValidInput_CorrectConversion, TestSize.Level0) -{ - ZLOGI("BasicToString_ValidInput_CorrectConversion begin."); - DataQuery queryBasicToString; - int value = 456; - string result = queryBasicToString.BasicToString(value); - EXPECT_EQ(result, "456"); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/datamgr_service_proxy_virtual_test.cpp b/kv_store/databaseutils/test/datamgr_service_proxy_virtual_test.cpp deleted file mode 100644 index 94f72158..00000000 --- a/kv_store/databaseutils/test/datamgr_service_proxy_virtual_test.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "DataMgrServiceProxyVirtualTest" - -#include "datamgr_service_proxy.h" -#include "itypes_util.h" -#include "log_print.h" -#include "message_parcel.h" -#include "mock_remote_object.h" -#include "types.h" -#include -#include -#include - -using namespace OHOS::DistributedKv; -using namespace testing; -using namespace testing::ext; -namespace OHOS::Test { -class DataMgrServiceProxyVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void DataMgrServiceProxyVirtualTest::SetUpTestCase(void) -{} - -void DataMgrServiceProxyVirtualTest::TearDownTestCase(void) -{} - -void DataMgrServiceProxyVirtualTest::SetUp(void) -{} - -void DataMgrServiceProxyVirtualTest::TearDown(void) -{} - -/** - * @tc.name: GetFeatureInterface_Success - * @tc.desc: - * @tc.type: GetFeatureInterface_Success test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, GetFeatureInterface_Success, TestSize.Level0) -{ - ZLOGI("GetFeatureInterface_Success begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .WillOnce(Return(0)); // Simulation returns successfully - - auto result = proxy.GetFeatureInterface("GetFeatureInterface_Success"); - ASSERT_NE(result, nullptr); -} - -/** - * @tc.name: GetFeatureInterface_WriteDescriptorFailed - * @tc.desc: - * @tc.type: GetFeatureInterface_WriteDescriptorFailed test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, GetFeatureInterface_WriteDescriptorFailed, TestSize.Level0) -{ - ZLOGI("GetFeatureInterface_WriteDescriptorFailed begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .Times(0); // SendRequest is not called - - auto result = proxy.GetFeatureInterface("GetFeatureInterface_WriteDescriptorFailed"); - ASSERT_EQ(result, nullptr); -} - -/** - * @tc.name: GetFeatureInterface_WriteNameFailed - * @tc.desc: - * @tc.type: GetFeatureInterface_WriteNameFailed test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, GetFeatureInterface_WriteNameFailed, TestSize.Level0) -{ - ZLOGI("GetFeatureInterface_WriteNameFailed begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .Times(0); // SendRequest is not called - - auto result = proxy.GetFeatureInterface("GetFeatureInterface_WriteNameFailed"); - ASSERT_EQ(result, nullptr); -} - -/** - * @tc.name: GetFeatureInterface_SendRequestError - * @tc.desc: - * @tc.type: GetFeatureInterface_SendRequestError test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, GetFeatureInterface_SendRequestError, TestSize.Level0) -{ - ZLOGI("GetFeatureInterface_SendRequestError begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .WillOnce(Return(-1)); // Simulating an error - - auto result = proxy.GetFeatureInterface("GetFeatureInterface_SendRequestError"); - ASSERT_EQ(result, nullptr); -} - -/** - * @tc.name: RegisterClientDeathObserver_Success - * @tc.desc: - * @tc.type: RegisterClientDeathObserver_Success test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, RegisterClientDeathObserver_Success, TestSize.Level0) -{ - ZLOGI("RegisterClientDeathObserver_Success begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .WillOnce(Return(0)); // Simulation returns successfully - - AppId appId; - appId.appId = "RegisterClientDeathObserver_Success"; - sptr observer = new MockRemoteObject(); - auto status = proxy.RegisterClientDeathObserver(appId, observer); - ASSERT_EQ(status, Status::SUCCESS); -} - -/** - * @tc.name: RegisterClientDeathObserver_WriteDescriptorFailed - * @tc.desc: - * @tc.type: RegisterClientDeathObserver_WriteDescriptorFailed test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, RegisterClientDeathObserver_WriteDescriptorFailed, TestSize.Level0) -{ - ZLOGI("RegisterClientDeathObserver_WriteDescriptorFailed begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .Times(0); // SendRequest is not called - - AppId appId; - appId.appId = "RegisterClientDeathObserver_WriteDescriptorFailed"; - sptr observer = new MockRemoteObject(); - auto status = proxy.RegisterClientDeathObserver(appId, observer); - ASSERT_EQ(status, Status::IPC_ERROR); -} - -/** - * @tc.name: RegisterClientDeathObserver_WriteStringFailed - * @tc.desc: - * @tc.type: RegisterClientDeathObserver_WriteStringFailed test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, RegisterClientDeathObserver_WriteStringFailed, TestSize.Level0) -{ - ZLOGI("RegisterClientDeathObserver_WriteStringFailed begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .Times(0); // SendRequest is not called - - AppId appId; - appId.appId = "RegisterClientDeathObserver_WriteStringFailed"; - sptr observer = new MockRemoteObject(); - auto status = proxy.RegisterClientDeathObserver(appId, observer); - ASSERT_EQ(status, Status::IPC_ERROR); -} - -/** - * @tc.name: RegisterClientDeathObserver_NullObserver - * @tc.desc: - * @tc.type: RegisterClientDeathObserver_NullObserver test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, RegisterClientDeathObserver_NullObserver, TestSize.Level0) -{ - ZLOGI("RegisterClientDeathObserver_NullObserver begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .Times(0); // SendRequest is not called - - AppId appId; - appId.appId = "RegisterClientDeathObserver_NullObserver"; - auto status = proxy.RegisterClientDeathObserver(appId, nullptr); - ASSERT_EQ(status, Status::INVALID_ARGUMENT); -} - -/** - * @tc.name: RegisterClientDeathObserver_SendRequestError - * @tc.desc: - * @tc.type: RegisterClientDeathObserver_SendRequestError test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, RegisterClientDeathObserver_SendRequestError, TestSize.Level0) -{ - ZLOGI("RegisterClientDeathObserver_SendRequestError begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .WillOnce(Return(-1)); // Simulating an error - - AppId appId; - appId.appId = "RegisterClientDeathObserver_SendRequestError"; - sptr observer = new MockRemoteObject(); - auto status = proxy.RegisterClientDeathObserver(appId, observer); - ASSERT_EQ(status, Status::IPC_ERROR); -} - -/** - * @tc.name: ClearAppStorage_Success - * @tc.desc: - * @tc.type: ClearAppStorage_Success test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, ClearAppStorage_Success, TestSize.Level0) -{ - ZLOGI("ClearAppStorage_Success begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .WillOnce(Return(0)); // Simulation returns successfully - - auto result = proxy.ClearAppStorage("ClearAppStorage_Success", 1, 1, 1); - ASSERT_EQ(result, Status::SUCCESS); -} - -/** - * @tc.name: ClearAppStorage_WriteDescriptorFailed - * @tc.desc: - * @tc.type: ClearAppStorage_WriteDescriptorFailed test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, ClearAppStorage_WriteDescriptorFailed, TestSize.Level0) -{ - ZLOGI("ClearAppStorage_WriteDescriptorFailed begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .Times(0); // SendRequest is not called - - auto result = proxy.ClearAppStorage("ClearAppStorage_WriteDescriptorFailed", 1, 1, 1); - ASSERT_EQ(result, Status::IPC_ERROR); -} - -/** - * @tc.name: ClearAppStorage_WriteDataFailed - * @tc.desc: - * @tc.type: ClearAppStorage_WriteDataFailed test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, ClearAppStorage_WriteDataFailed, TestSize.Level0) -{ - ZLOGI("ClearAppStorage_WriteDataFailed begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .Times(0); // SendRequest is not called - - auto result = proxy.ClearAppStorage("ClearAppStorage_WriteDataFailed", 1, 1, 1); - ASSERT_EQ(result, Status::IPC_ERROR); -} - -/** - * @tc.name: ClearAppStorage_SendRequestError - * @tc.desc: - * @tc.type: ClearAppStorage_SendRequestError test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataMgrServiceProxyVirtualTest, ClearAppStorage_SendRequestError, TestSize.Level0) -{ - ZLOGI("ClearAppStorage_SendRequestError begin."); - std::shared_ptr mockImpl = std::make_shared(); - DataMgrServiceProxy proxy(mockImpl); - - EXPECT_CALL(*mockImpl, SendRequest(_, _, _, _)) - .WillOnce(Return(-1)); // Simulating an error - - auto result = proxy.ClearAppStorage("ClearAppStorage_SendRequestError", 1, 1, 1); - ASSERT_EQ(result, Status::IPC_ERROR); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/delegate_mgr_callback_virtual_test.cpp b/kv_store/databaseutils/test/delegate_mgr_callback_virtual_test.cpp deleted file mode 100644 index 3a7ad643..00000000 --- a/kv_store/databaseutils/test/delegate_mgr_callback_virtual_test.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "DelegateMgrCallbackVirtualTest" - -#include "kv_types_util.h" -#include "types.h" -#include -#include -#include -#include "distributeddb_kvstore_delegate_manager.h" -#include "delegate_mgr_callback.h" -#include - -using namespace OHOS::DistributedKv; -using namespace testing; -using namespace testing::ext; -namespace OHOS::Test { -class DelegateMgrCallbackVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void DelegateMgrCallbackVirtualTest::SetUpTestCase(void) -{ -} - -void DelegateMgrCallbackVirtualTest::TearDownTestCase(void) -{ -} - -void DelegateMgrCallbackVirtualTest::SetUp(void) -{ -} - -void DelegateMgrCallbackVirtualTest::TearDown(void) -{ -} - -class MockKvStoreDelegateManager : public KvStoreDelegateManager { -public: - MOCK_METHOD2(GetKvStoreDiskSize, DBStatus(const std::string &, uint64_t &)); -}; - -/** - * @tc.name: GetKvStoreDiskSize_DelegateIsNull_ReturnsFalse - * @tc.desc: - * @tc.type: GetKvStoreDiskSize_DelegateIsNull_ReturnsFalse test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GetKvStoreDiskSize_DelegateIsNull_ReturnsFalse, TestSize.Level0) -{ - ZLOGI("GetKvStoreDiskSize_DelegateIsNull_ReturnsFalse begin."); - MockKvStoreDelegateManager *mockDelegate1; - DelegateMgrCallback *callback1; - mockDelegate1 = new MockKvStoreDelegateManager(); - callback1 = new DelegateMgrCallback(nullptr); - - uint64_t size = 0; - EXPECT_FALSE(callback1->GetKvStoreDiskSize("storeId", size)); - - delete callback1; - delete mockDelegate1; -} - -/** - * @tc.name: GetKvStoreDiskSize_DelegateReturnsOK_ReturnsTrue - * @tc.desc: - * @tc.type: GetKvStoreDiskSize_DelegateReturnsOK_ReturnsTrue test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GetKvStoreDiskSize_DelegateReturnsOK_ReturnsTrue, TestSize.Level0) -{ - ZLOGI("GetKvStoreDiskSize_DelegateReturnsOK_ReturnsTrue begin."); - MockKvStoreDelegateManager *mockDelegate2; - DelegateMgrCallback *callback2; - mockDelegate2 = new MockKvStoreDelegateManager(); - callback2 = new DelegateMgrCallback(mockDelegate2); - uint64_t size = 0; - EXPECT_CALL(*mockDelegate2, GetKvStoreDiskSize("storeId", _)).WillOnce(Return(DBStatus::OK)); - EXPECT_TRUE(callback2->GetKvStoreDiskSize("storeId", size)); - - delete callback2; - delete mockDelegate2; -} - -/** - * @tc.name: GetKvStoreDiskSize_DelegateReturnsNonOK_ReturnsFalse - * @tc.desc: - * @tc.type: GetKvStoreDiskSize_DelegateReturnsNonOK_ReturnsFalse test function - * @tc.require: - * @tc.author: - */ -HWTEST_F(DataQueryVirtualTest, GetKvStoreDiskSize_DelegateReturnsNonOK_ReturnsFalse, TestSize.Level0) -{ - ZLOGI("GetKvStoreDiskSize_DelegateReturnsNonOK_ReturnsFalse begin."); - MockKvStoreDelegateManager *mockDelegate3; - DelegateMgrCallback *callback3; - mockDelegate3 = new MockKvStoreDelegateManager(); - callback3 = new DelegateMgrCallback(mockDelegate3); - - uint64_t size = 0; - EXPECT_CALL(*mockDelegate3, GetKvStoreDiskSize("storeId", _)).WillOnce(Return(DBStatus::NOT_FOUND)); - EXPECT_FALSE(callback->GetKvStoreDiskSize("storeId", size)); - - delete callback3; - delete mockDelegate3; -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/distributed_kv_data_manager_vritual_test.cpp b/kv_store/databaseutils/test/distributed_kv_data_manager_vritual_test.cpp deleted file mode 100644 index a7d4f492..00000000 --- a/kv_store/databaseutils/test/distributed_kv_data_manager_vritual_test.cpp +++ /dev/null @@ -1,863 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "DistributedKvDataManagerVirtualTest" - -#include -#include -#include "distributed_kv_data_manager.h" -#include "kv_store_delegate_manager.h" -#include "kv_store_observer.h" -#include "kv_store_death_recipient.h" -#include "process_communication_impl.h" -#include "process_system_api_adapter_impl.h" -#include "store_manager.h" -#include "store_util.h" -#include "runtime_config.h" -#include "kv_store_service_death_notifier.h" -#include "dds_trace.h" -#include "kvstore_service_death_notifier.h" -#include "kv_store_death_recipient.h" -#include "kv_store_observer.h" -#include "kv_store_delegate_manager.h" -#include "process_communication_impl.h" -#include "process_system_api_adapter_impl.h" -#include "store_manager.h" -#include "store_util.h" -#include "runtime_config.h" -#include "kv_store_service_death_notifier.h" -#include "dds_trace.h" - -using namespace OHOS::DistributedKv; -using namespace testing; -using namespace testing::ext; -namespace OHOS::Test { -static constexpr size_t NUM_MIN_V = 5; -static constexpr size_t NUM_MAX_V = 12; -class DistributedKvDataManagerVirtualTest : public testing::Test { -public: - static std::shared_ptr executors; - static DistributedKvDataManager managerVirtual; - static Options createVirtual; - static Options noCreateVirtual; - static UserId userIdVirtual; - static AppId appIdVirtual; - static StoreId storeId64Virtual; - static StoreId storeId65Virtual; - static StoreId storeIdTestVirtual; - static StoreId storeIdEmptyVirtual; - static Entry entryAVirtual; - static Entry entryBVirtual; - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; -std::shared_ptr DistributedKvDataManagerTest::executors = - std::make_shared(NUM_MAX_V, NUM_MIN_V); - -void DistributedKvDataManagerVirtualTest::SetUpTestCase(void) -{} - -void DistributedKvDataManagerVirtualTest::TearDownTestCase(void) -{} - -void DistributedKvDataManagerVirtualTest::SetUp(void) -{} - -void DistributedKvDataManagerVirtualTest::TearDown(void) -{} - -class ChangeNotificationVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void ChangeNotificationVirtualTest::SetUpTestCase(void) -{} - -void ChangeNotificationVirtualTest::TearDownTestCase(void) -{} - -void ChangeNotificationVirtualTest::SetUp(void) -{} - -void ChangeNotificationVirtualTest::TearDown(void) -{} - -/** - * @tc.name: GetKvStore001 - * @tc.desc: Get an exist SingleKvStore - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlGetKvStore001 - */ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore001, TestSize.Level1) -{ - ZLOGI("GetKvStore001 begin."); - DistributedKvDataManager managerVirtual; - std::shared_ptr notExistKvStoreVirtual; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(notExistKvStoreVirtual, nullptr); - - std::shared_ptr existKvStoreVirtual; - statusVirtual = - managerVirtual.GetSingleKvStore(noCreateVirtual, appIdVirtual, storeId64Virtual, existKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(existKvStoreVirtual, nullptr); -} - -/** -* @tc.name: GetKvStore002 -* @tc.desc: Create and get a new SingleKvStore -* @tc.type: FUNC -* @tc.require: GetKvStore002 -* @tc.author: sqlGetKvStore002 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore002, TestSize.Level1) -{ - ZLOGI("GetKvStore002 begin."); - std::shared_ptr notExistKvStoreVirtual; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(notExistKvStoreVirtual, nullptr); - managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - managerVirtual.DeleteKvStore(appIdVirtual, storeId64Virtual); -} - -/** -* @tc.name: GetKvStore003 -* @tc.desc: Get a non-existing SingleKvStore, and the callback function should receive STORE_NOT_FOUND and -* get a nullptr. -* @tc.type: FUNC -* @tc.require: GetKvStore003 -* @tc.author: sqlGetKvStore003 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore003, TestSize.Level1) -{ - ZLOGI("GetKvStore003 begin."); - std::shared_ptr notExistKvStoreVirtual; - (void)managerVirtual.GetSingleKvStore(noCreateVirtual, appIdVirtual, storeId64Virtual, notExistKvStoreVirtual); - EXPECT_EQ(notExistKvStoreVirtual, nullptr); -} - -/** -* @tc.name: GetKvStore004 -* @tc.desc: Create a SingleKvStore with an empty storeId, and the callback function should receive -* @tc.type: FUNC -* @tc.require: GetKvStore004 -* @tc.author: sqlGetKvStore004 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore004, TestSize.Level1) -{ - ZLOGI("GetKvStore004 begin."); - std::shared_ptr notExistKvStoreVirtual; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeIdEmptyVirtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::INVALID_ARGUMENT); - EXPECT_EQ(notExistKvStoreVirtual, nullptr); -} - -/** -* @tc.name: GetKvStore005 -* @tc.desc: Get a SingleKvStore with an empty storeId, and the callback function should receive INVALID_ARGUMENT -* @tc.type: FUNC -* @tc.require: GetKvStore005 -* @tc.author: sqlGetKvStore005 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore005, TestSize.Level1) -{ - ZLOGI("GetKvStore005 begin."); - std::shared_ptr notExistKvStoreVirtual; - Status statusVirtual = - managerVirtual.GetSingleKvStore(noCreateVirtual, appIdVirtual, storeIdEmptyVirtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::INVALID_ARGUMENT); - EXPECT_EQ(notExistKvStoreVirtual, nullptr); -} - -/** -* @tc.name: GetKvStore006 -* @tc.desc: Create a SingleKvStore with a 65-byte storeId, and the callback function should receive INVALID_ARGUMENT -* @tc.type: FUNC -* @tc.require: GetKvStore006 -* @tc.author: sqlGetKvStore006 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore006, TestSize.Level1) -{ - ZLOGI("GetKvStore006 begin."); - std::shared_ptr notExistKvStoreVirtual; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId65Virtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::INVALID_ARGUMENT); - EXPECT_EQ(notExistKvStoreVirtual, nullptr); -} - -/** -* @tc.name: GetKvStore007 -* @tc.desc: Get a SingleKvStore with a 65-byte storeId, the callback function should receive INVALID_ARGUMENT -* @tc.type: FUNC -* @tc.require: GetKvStore007 -* @tc.author: sqlGetKvStore007 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore007, TestSize.Level1) -{ - ZLOGI("GetKvStore007 begin."); - std::shared_ptr notExistKvStoreVirtual; - Status statusVirtual = - managerVirtual.GetSingleKvStore(noCreateVirtual, appIdVirtual, storeId65Virtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::INVALID_ARGUMENT); - EXPECT_EQ(notExistKvStoreVirtual, nullptr); -} - -/** - * @tc.name: GetKvStore008 - * @tc.desc: Get a SingleKvStore which supports cloud sync. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlGetKvStore008 - */ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore008, TestSize.Level1) -{ - ZLOGI("GetKvStore008 begin."); - std::shared_ptr cloudKvStore = nullptr; - Options options = createVirtual; - options.isPublic = true; - options.cloudConfig = { - .enableCloud = true, - .autoSync = true - }; - Status statusVirtual = - managerVirtual.GetSingleKvStore(options, appIdVirtual, storeId64Virtual, cloudKvStore); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(cloudKvStore, nullptr); -} - -/** - * @tc.name: GetKvStore009 - * @tc.desc: Get a SingleKvStore which security level upgrade. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlGetKvStore009 - */ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStore009, TestSize.Level1) -{ - ZLOGI("GetKvStore009 begin."); - std::shared_ptr kvStore = nullptr; - Options options = createVirtual; - options.securityLevel = S1; - Status statusVirtual = - managerVirtual.GetSingleKvStore(options, appIdVirtual, storeId64Virtual, kvStore); - - managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - options.securityLevel = S2; - statusVirtual = - managerVirtual.GetSingleKvStore(options, appIdVirtual, storeId64Virtual, kvStore); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(kvStore, nullptr); - - managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - options.securityLevel = S1; - statusVirtual = - managerVirtual.GetSingleKvStore(options, appIdVirtual, storeId64Virtual, kvStore); - ASSERT_EQ(statusVirtual, Status::STORE_META_CHANGED); - EXPECT_EQ(kvStore, nullptr); -} - -/** -* @tc.name: GetKvStoreInvalidSecurityLevel -* @tc.desc: Get a SingleKvStore with a 64 - * -byte storeId, the callback function should receive INVALID_ARGUMENT -* @tc.type: FUNC -* @tc.require: SR000IIM2J AR000IIMLL -* @tc.author: sqlGetKvStoreInvalidSecurityLevel -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetKvStoreInvalidSecurityLevel, TestSize.Level1) -{ - ZLOGI("GetKvStoreInvalidSecurityLevel begin."); - std::shared_ptr notExistKvStoreVirtual; - Options invalidOption = createVirtual; - invalidOption.securityLevel = INVALID_LABEL; - Status statusVirtual = - managerVirtual.GetSingleKvStore(invalidOption, appIdVirtual, storeId64Virtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::INVALID_ARGUMENT); - EXPECT_EQ(notExistKvStoreVirtual, nullptr); -} - -/** -* @tc.name: GetAllKvStore001 -* @tc.desc: Get all KvStore IDs when no KvStore exists, and the callback function should receive a 0-length vector. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlGetAllKvStore001 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetAllKvStore001, TestSize.Level1) -{ - ZLOGI("GetAllKvStore001 begin."); - std::vector storeIds; - Status statusVirtual = managerVirtual.GetAllKvStoreId(appIdVirtual, storeIds); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_EQ(storeIds.size(), static_cast(0)); -} - -/** -* @tc.name: GetAllKvStore002 -* @tc.desc: Get all SingleKvStore IDs when no KvStore exists, and the callback function should receive a empty vector. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlGetAllKvStore002 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetAllKvStore002, TestSize.Level1) -{ - ZLOGI("GetAllKvStore002 begin."); - StoreId id1; - id1.storeId = "id1"; - StoreId id2; - id2.storeId = "id2"; - StoreId id3; - id3.storeId = "id3"; - std::shared_ptr kvStore; - Status statusVirtual = managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, id1, kvStore); - ASSERT_NE(kvStore, nullptr); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - statusVirtual = managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, id2, kvStore); - ASSERT_NE(kvStore, nullptr); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - statusVirtual = managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, id3, kvStore); - ASSERT_NE(kvStore, nullptr); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - std::vector storeIds; - statusVirtual = managerVirtual.GetAllKvStoreId(appIdVirtual, storeIds); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - bool haveId1 = false; - bool haveId2 = false; - bool haveId3 = false; - for (StoreId &id : storeIds) { - if (id.storeId == "id1") { - haveId1 = true; - } else if (id.storeId == "id2") { - haveId2 = true; - } else if (id.storeId == "id3") { - haveId3 = true; - } else { - ZLOGI("got an unknown storeId."); - EXPECT_TRUE(false); - } - } - EXPECT_TRUE(haveId1); - EXPECT_TRUE(haveId2); - EXPECT_TRUE(haveId3); - EXPECT_EQ(storeIds.size(), static_cast(3)); -} - -/** -* @tc.name: CloseKvStore001 -* @tc.desc: Close an opened KVStore, and the callback function should return SUCCESS. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlCloseKvStore001 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseKvStore001, TestSize.Level1) -{ - ZLOGI("CloseKvStore001 begin."); - std::shared_ptr kvStore; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore, nullptr); - - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: CloseKvStore002 -* @tc.desc: Close a closed SingleKvStore, and the callback function should return SUCCESS. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlCloseKvStore002 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseKvStore002, TestSize.Level1) -{ - ZLOGI("CloseKvStore002 begin."); - std::shared_ptr kvStore; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore, nullptr); - - managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::STORE_NOT_OPEN); -} - -/** -* @tc.name: CloseKvStore003 -* @tc.desc: Close a SingleKvStore with an empty storeId, and the callback function should return INVALID_ARGUMENT. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlCloseKvStore003 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseKvStore003, TestSize.Level1) -{ - ZLOGI("CloseKvStore003 begin."); - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeIdEmptyVirtual); - EXPECT_EQ(stat, Status::INVALID_ARGUMENT); -} - -/** -* @tc.name: CloseKvStore004 -* @tc.desc: Close a SingleKvStore with a 65-byte storeId, and the callback function should return INVALID_ARGUMENT. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlCloseKvStore004 -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseKvStore004, TestSize.Level1) -{ - ZLOGI("CloseKvStore004 begin."); - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId65Virtual); - EXPECT_EQ(stat, Status::INVALID_ARGUMENT); -} - -/** -* @tc.name: CloseKvStore005 -* @tc.desc: Close a non-existing SingleKvStore, and the callback function should return STORE_NOT_OPEN. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseKvStore005, TestSize.Level1) -{ - ZLOGI("CloseKvStore005 begin."); - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::STORE_NOT_OPEN); -} - -/** -* @tc.name: CloseKvStoreMulti001 -* @tc.desc: Open a SingleKvStore several times and close them one by one. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000CSKRU -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseKvStoreMulti001, TestSize.Level1) -{ - ZLOGI("CloseKvStoreMulti001 begin."); - std::shared_ptr notExistKvStoreVirtual; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(notExistKvStoreVirtual, nullptr); - - std::shared_ptr existKvStoreVirtual; - managerVirtual.GetSingleKvStore(noCreateVirtual, appIdVirtual, storeId64Virtual, existKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(existKvStoreVirtual, nullptr); - - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); - - stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: CloseKvStoreMulti002 -* @tc.desc: Open a SingleKvStore several times and close them one by one. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000CSKRU -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseKvStoreMulti002, TestSize.Level1) -{ - ZLOGI("CloseKvStoreMulti002 begin."); - std::shared_ptr notExistKvStoreVirtual; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, notExistKvStoreVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(notExistKvStoreVirtual, nullptr); - - std::shared_ptr existKvStore1; - statusVirtual = - managerVirtual.GetSingleKvStore(noCreateVirtual, appIdVirtual, storeId64Virtual, existKvStore1); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(existKvStore1, nullptr); - - std::shared_ptr existKvStore2; - statusVirtual = - managerVirtual.GetSingleKvStore(noCreateVirtual, appIdVirtual, storeId64Virtual, existKvStore2); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(existKvStore2, nullptr); - - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); - - stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); - - stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); - - stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_NE(stat, Status::SUCCESS); -} - -/** -* @tc.name: CloseAllKvStore001 -* @tc.desc: Close all opened KvStores, and the callback function should return SUCCESS. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseAllKvStore001, TestSize.Level1) -{ - ZLOGI("CloseAllKvStore001 begin."); - std::shared_ptr kvStore1; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore1); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore1, nullptr); - - std::shared_ptr kvStore2; - statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeIdTestVirtual, kvStore2); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore2, nullptr); - - Status stat = managerVirtual.CloseAllKvStore(appIdVirtual); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: CloseAllKvStore002 -* @tc.desc: Close all KvStores which exist but are not opened, and the callback function should return STORE_NOT_OPEN. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, CloseAllKvStore002, TestSize.Level1) -{ - ZLOGI("CloseAllKvStore002 begin."); - std::shared_ptr kvStore; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore, nullptr); - - std::shared_ptr kvStore2; - statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeIdTestVirtual, kvStore2); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore2, nullptr); - - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); - - stat = managerVirtual.CloseAllKvStore(appIdVirtual); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: DeleteKvStore001 -* @tc.desc: Delete a closed KvStore, and the callback function should return SUCCESS. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteKvStore001, TestSize.Level1) -{ - ZLOGI("DeleteKvStore001 begin."); - std::shared_ptr kvStore; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore, nullptr); - - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - ASSERT_EQ(stat, Status::SUCCESS); - - stat = managerVirtual.DeleteKvStore(appIdVirtual, storeId64Virtual, createVirtual.baseDir); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: DeleteKvStore002 -* @tc.desc: Delete an opened SingleKvStore, and the callback function should return SUCCESS. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteKvStore002, TestSize.Level1) -{ - ZLOGI("DeleteKvStore002 begin."); - std::shared_ptr kvStore; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore, nullptr); - - // first close it if opened, and then delete it. - Status stat = managerVirtual.DeleteKvStore(appIdVirtual, storeId64Virtual, createVirtual.baseDir); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: DeleteKvStore003 -* @tc.desc: Delete a non-existing KvStore, and the callback function should return DB_ERROR. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteKvStore003, TestSize.Level1) -{ - ZLOGI("DeleteKvStore003 begin."); - Status stat = managerVirtual.DeleteKvStore(appIdVirtual, storeId64Virtual, createVirtual.baseDir); - EXPECT_EQ(stat, Status::STORE_NOT_FOUND); -} - -/** -* @tc.name: DeleteKvStore004 -* @tc.desc: Delete a KvStore with an empty storeId, and the callback function should return INVALID_ARGUMENT. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteKvStore004, TestSize.Level1) -{ - ZLOGI("DeleteKvStore004 begin."); - Status stat = managerVirtual.DeleteKvStore(appIdVirtual, storeIdEmptyVirtual); - EXPECT_EQ(stat, Status::INVALID_ARGUMENT); -} - -/** -* @tc.name: DeleteKvStore005 -* @tc.desc: Delete a KvStore with 65 bytes long storeId (which exceed storeId length limit). Should -* return INVALID_ARGUMENT. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteKvStore005, TestSize.Level1) -{ - ZLOGI("DeleteKvStore005 begin."); - Status stat = managerVirtual.DeleteKvStore(appIdVirtual, storeId65Virtual); - EXPECT_EQ(stat, Status::INVALID_ARGUMENT); -} - -/** -* @tc.name: DeleteAllKvStore001 -* @tc.desc: Delete all KvStores after closing all of them, and the callback function should return SUCCESS. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteAllKvStore001, TestSize.Level1) -{ - ZLOGI("DeleteAllKvStore001 begin."); - std::shared_ptr kvStore1; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore1); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore1, nullptr); - std::shared_ptr kvStore2; - statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeIdTestVirtual, kvStore2); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore2, nullptr); - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); - stat = managerVirtual.CloseKvStore(appIdVirtual, storeIdTestVirtual); - EXPECT_EQ(stat, Status::SUCCESS); - - stat = managerVirtual.DeleteAllKvStore({""}, createVirtual.baseDir); - EXPECT_NE(stat, Status::SUCCESS); - stat = managerVirtual.DeleteAllKvStore(appIdVirtual, ""); - EXPECT_EQ(stat, Status::INVALID_ARGUMENT); - - stat = managerVirtual.DeleteAllKvStore(appIdVirtual, createVirtual.baseDir); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: DeleteAllKvStore002 -* @tc.desc: Delete all kvstore fail when any kvstore in the appIdVirtual is not closed -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteAllKvStore002, TestSize.Level1) -{ - ZLOGI("DeleteAllKvStore002 begin."); - std::shared_ptr kvStore1; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore1); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore1, nullptr); - std::shared_ptr kvStore2; - statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeIdTestVirtual, kvStore2); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore2, nullptr); - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); - - stat = managerVirtual.DeleteAllKvStore(appIdVirtual, createVirtual.baseDir); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: DeleteAllKvStore003 -* @tc.desc: Delete all KvStores even if no KvStore exists in the appIdVirtual. -* @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM -* @tc.author: sqlliqiao -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteAllKvStore003, TestSize.Level1) -{ - ZLOGI("DeleteAllKvStore003 begin."); - Status stat = managerVirtual.DeleteAllKvStore(appIdVirtual, createVirtual.baseDir); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: DeleteAllKvStore004 -* @tc.desc: when delete the last active kvstore, the system will remove the app managerVirtual scene -* @tc.type: FUNC -* @tc.require: bugs -* @tc.author: sqlSven Wang -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, DeleteAllKvStore004, TestSize.Level1) -{ - ZLOGI("DeleteAllKvStore004 begin."); - std::shared_ptr kvStore1; - Status statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeId64Virtual, kvStore1); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore1, nullptr); - std::shared_ptr kvStore2; - statusVirtual = - managerVirtual.GetSingleKvStore(createVirtual, appIdVirtual, storeIdTestVirtual, kvStore2); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_NE(kvStore2, nullptr); - Status stat = managerVirtual.CloseKvStore(appIdVirtual, storeId64Virtual); - EXPECT_EQ(stat, Status::SUCCESS); - stat = managerVirtual.CloseKvStore(appIdVirtual, storeIdTestVirtual); - EXPECT_EQ(stat, Status::SUCCESS); - stat = managerVirtual.DeleteKvStore(appIdVirtual, storeIdTestVirtual, createVirtual.baseDir); - EXPECT_EQ(stat, Status::SUCCESS); - stat = managerVirtual.DeleteAllKvStore(appIdVirtual, createVirtual.baseDir); - EXPECT_EQ(stat, Status::SUCCESS); -} - -/** -* @tc.name: PutSwitchWithEmptyAppId -* @tc.desc: put switch data, but appIdVirtual is empty. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sqlzuojiangjiang -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, PutSwitchWithEmptyAppId, TestSize.Level1) -{ - ZLOGI("PutSwitchWithEmptyAppId begin."); - SwitchData data; - Status statusVirtual = managerVirtual.PutSwitch({ "" }, data); - ASSERT_EQ(statusVirtual, Status::INVALID_ARGUMENT); -} - -/** -* @tc.name: PutSwitchWithInvalidAppId -* @tc.desc: put switch data, but appIdVirtual is not 'distributed_device_profile_service'. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sqlzuojiangjiang -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, PutSwitchWithInvalidAppId, TestSize.Level1) -{ - ZLOGI("PutSwitchWithInvalidAppId begin."); - SwitchData data; - Status statusVirtual = managerVirtual.PutSwitch({ "swicthes_test_appId" }, data); - ASSERT_EQ(statusVirtual, Status::PERMISSION_DENIED); -} - -/** -* @tc.name: GetSwitchWithInvalidArg -* @tc.desc: get switch data, but appIdVirtual is empty, networkId is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sqlzuojiangjiang -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetSwitchWithInvalidArg, TestSize.Level1) -{ - ZLOGI("GetSwitchWithInvalidArg begin."); - auto [status1, data1] = managerVirtual.GetSwitch({ "" }, "networkId_test"); - ASSERT_EQ(status1, Status::INVALID_ARGUMENT); - auto [status2, data2] = managerVirtual.GetSwitch({ "switches_test_appId" }, ""); - ASSERT_EQ(status2, Status::INVALID_ARGUMENT); - auto [status3, data3] = managerVirtual.GetSwitch({ "switches_test_appId" }, "networkId_test"); - ASSERT_EQ(status3, Status::INVALID_ARGUMENT); -} - -/** -* @tc.name: GetSwitchWithInvalidAppId -* @tc.desc: get switch data, but appIdVirtual is not 'distributed_device_profile_service'. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sqlzuojiangjiang -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, GetSwitchWithInvalidAppId, TestSize.Level1) -{ - ZLOGI("GetSwitchWithInvalidAppId begin."); - auto devInfo = DevManager::GetInstance().GetLocalDevice(); - EXPECT_NE(devInfo.networkId, ""); - auto [statusVirtual, data] = managerVirtual.GetSwitch({ "switches_test_appId" }, devInfo.networkId); - ASSERT_EQ(statusVirtual, Status::PERMISSION_DENIED); -} - -/** -* @tc.name: SubscribeSwitchesData -* @tc.desc: subscribe switch data. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sqlzuojiangjiang -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, SubscribeSwitchesData, TestSize.Level1) -{ - ZLOGI("SubscribeSwitchesData begin."); - std::shared_ptr observer = std::make_shared(); - auto statusVirtual = managerVirtual.SubscribeSwitchData({ "switches_test_appId" }, observer); - ASSERT_EQ(statusVirtual, Status::PERMISSION_DENIED); -} - -/** -* @tc.name: UnsubscribeSwitchesData -* @tc.desc: unsubscribe switch data. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sqlzuojiangjiang -*/ -HWTEST_F(DistributedKvDataManagerVirtualTest, UnsubscribeSwitchesData, TestSize.Level1) -{ - ZLOGI("UnsubscribeSwitchesData begin."); - std::shared_ptr observer = std::make_shared(); - auto statusVirtual = managerVirtual.SubscribeSwitchData({ "switches_test_appId" }, observer); - ASSERT_EQ(statusVirtual, Status::PERMISSION_DENIED); - statusVirtual = managerVirtual.UnsubscribeSwitchData({ "switches_test_appId" }, observer); - ASSERT_EQ(statusVirtual, Status::PERMISSION_DENIED); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/kv_utils_virtual_test.cpp b/kv_store/databaseutils/test/kv_utils_virtual_test.cpp deleted file mode 100644 index aec5af97..00000000 --- a/kv_store/databaseutils/test/kv_utils_virtual_test.cpp +++ /dev/null @@ -1,1053 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "KvUtilVirtualTest" - -#include -#include -#include -#include -#include -#include "kv_utils.h" -#include "data_query.h" -#include "data_share_abs_predicates.h" -#include "data_share_values_bucket.h" -#include "data_share_value_object.h" - -using namespace testing::ext; -using namespace OHOS::DistributedKv; -using namespace OHOS::DataShare; -namespace OHOS::Test { -static constexpr const char *KEY = "key"; -static constexpr const char *VALUE = "value"; -static constexpr const char *VALID_SCHEMA_STRICT_DEFINE = "{\"SCHEMA_VERSION\":\"1.0\"," - "\"SCHEMA_MODE\":\"STRICT\"," - "\"SCHEMA_SKIPSIZE\":0," - "\"SCHEMA_DEFINE\":" - "{" - "\"age\":\"INTEGER, NOT NULL\"" - "}," - "\"SCHEMA_INDEXES\":[\"$.age\"]}"; -using var_t = std::variant>; -class KvUtilVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - -protected: - static DistributedKvDataManager managerVirtual; - static std::shared_ptr singleKvStoreVirtual; - - static std::string Entry2Str(const Entry &entry); - static void ClearEntry(Entry &entry); - static Blob VariantValue2Blob(const var_t &value); - static Blob VariantKey2Blob(const var_t &value); -}; -std::shared_ptr KvUtilVirtualTest::singleKvStoreVirtual = nullptr; -DistributedKvDataManager KvUtilVirtualTest::managerVirtual; - -void KvUtilVirtualTest::SetUp(void) -{ - ZLOGI("SetUp begin."); -} - -void KvUtilVirtualTest::TearDown(void) -{ - ZLOGI("TearDown begin."); -} - -std::string KvUtilVirtualTest::Entry2Str(const Entry &entry) -{ - ZLOGI("Entry2Str begin."); - return entry.key.ToString() + entry.value.ToString(); -} - -void KvUtilVirtualTest::ClearEntry(Entry &entry) -{ - ZLOGI("ClearEntry begin."); - entry.key.Clear(); - entry.value.Clear(); -} - -Blob KvUtilVirtualTest::VariantKey2Blob(const var_t &value) -{ - ZLOGI("VariantKey2Blob begin."); - std::vector uData; - if (auto *val = std::get_if(&value)) { - std::string data = *val; - uData.insert(uData.end(), data.begin(), data.end()); - } - return Blob(uData); -} - -Blob KvUtilVirtualTest::VariantValue2Blob(const var_t &value) -{ - ZLOGI("VariantValue2Blob begin."); - std::vector data; - auto strValue = std::get_if(&value); - if (strValue != nullptr) { - data.push_back(KvUtils::STRING); - data.insert(data.end(), (*strValue).begin(), (*strValue).end()); - } - auto boolValue = std::get_if(&value); - if (boolValue != nullptr) { - data.push_back(KvUtils::BOOLEAN); - data.push_back(static_cast(*boolValue)); - } - uint8_t *tmp = nullptr; - auto dblValue = std::get_if(&value); - if (dblValue != nullptr) { - double tmp4dbl = *dblValue; - uint64_t tmp64 = htobe64(*reinterpret_cast(&tmp4dbl)); - tmp = reinterpret_cast(&tmp64); - data.push_back(KvUtils::DOUBLE); - data.insert(data.end(), tmp, tmp + sizeof(double) / sizeof(uint8_t)); - } - auto intValue = std::get_if(&value); - if (intValue != nullptr) { - int64_t tmp4int = *intValue; - uint64_t tmp64 = htobe64(*reinterpret_cast(&tmp4int)); - tmp = reinterpret_cast(&tmp64); - data.push_back(KvUtils::INTEGER); - data.insert(data.end(), tmp, tmp + sizeof(int64_t) / sizeof(uint8_t)); - } - auto u8ArrayValue = std::get_if>(&value); - if (u8ArrayValue != nullptr) { - data.push_back(KvUtils::BYTE_ARRAY); - data.insert(data.end(), (*u8ArrayValue).begin(), (*u8ArrayValue).end()); - } - return Blob(data); -} - -void KvUtilVirtualTest::SetUpTestCase(void) -{ - ZLOGI("SetUpTestCase begin."); - Options options = { - .createIfMissing = true, - .encrypt = false, - .autoSync = false, - .kvStoreType = KvStoreType::SINGLE_VERSION, - .schema = VALID_SCHEMA_STRICT_DEFINE }; - options.area = EL1; - options.securityLevel = S1; - options.baseDir = std::string("/data/service/el1/public/database/KvUtilVirtualTest"); - AppId appId = { "KvUtilVirtualTest" }; - StoreId storeId = { "test_single" }; - mkdir(options.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); - managerVirtual.DeleteKvStore(appId, storeId, options.baseDir); - managerVirtual.GetSingleKvStore(options, appId, storeId, singleKvStoreVirtual); - EXPECT_NE(singleKvStoreVirtual, nullptr); - singleKvStoreVirtual->Put("test_key_1", "{\"age\":1}"); - singleKvStoreVirtual->Put("test_key_2", "{\"age\":2}"); - singleKvStoreVirtual->Put("test_key_3", "{\"age\":3}"); - singleKvStoreVirtual->Put("kv_utils", "{\"age\":4}"); -} - -void KvUtilVirtualTest::TearDownTestCase(void) -{ - ZLOGI("TearDownTestCase begin."); - managerVirtual.DeleteKvStore({"KvUtilVirtualTest" }, - { "test_single" }, "/data/service/el1/public/database/KvUtilVirtualTest"); - (void)remove("/data/service/el1/public/database/KvUtilVirtualTest/key"); - (void)remove("/data/service/el1/public/database/KvUtilVirtualTest/kvdb"); - (void)remove("/data/service/el1/public/database/KvUtilVirtualTest"); -} - -/** - * @tc.name: KvStoreResultSetToResultSetBridgeAbnormal - * @tc.desc: kvStore resultSetVirtual to resultSetVirtual bridgeVirtual, the former is nullptr - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, KvStoreResultSetToResultSetBridgeAbnormal, TestSize.Level0) -{ - ZLOGI("KvStoreResultSetToResultSetBridgeAbnormal begin."); - std::shared_ptr resultSetVirtual = nullptr; - auto bridgeVirtual = KvUtils::ToResultSetBridge(resultSetVirtual); - EXPECT_EQ(bridgeVirtual, nullptr); -} - -/** - * @tc.name: KvStoreResultSetToResultSetBridge - * @tc.desc: kvStore resultSetVirtual to resultSetVirtual bridgeVirtual - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, KvStoreResultSetToResultSetBridge, TestSize.Level0) -{ - ZLOGI("KvStoreResultSetToResultSetBridge begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.KeyPrefix("test"); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - std::shared_ptr resultSetVirtual = nullptr; - statusVirtual = singleKvStoreVirtual->GetResultSet(queryVirtual, resultSetVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_NE(resultSetVirtual, nullptr); - EXPECT_EQ(resultSetVirtual->GetCount(), 3); - auto bridgeVirtual = KvUtils::ToResultSetBridge(resultSetVirtual); - EXPECT_NE(bridgeVirtual, nullptr); -} - -/** - * @tc.name: PredicatesToQueryEqualTo - * @tc.desc: to queryVirtual equalTo - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryEqualTo, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryEqualTo begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.EqualTo("$.age", 1); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.EqualTo("$.age", 1); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryNotEqualTo - * @tc.desc: to queryVirtual not equalTo - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryNotEqualTo, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryNotEqualTo begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.NotEqualTo("$.age", 1); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.NotEqualTo("$.age", 1); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryGreaterThan - * @tc.desc: to queryVirtual greater than - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryGreaterThan, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryGreaterThan begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.GreaterThan("$.age", 1); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.GreaterThan("$.age", 1); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryLessThan - * @tc.desc: to queryVirtual less than - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryLessThan, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryLessThan begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.LessThan("$.age", 3); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.LessThan("$.age", 3); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryGreaterThanOrEqualTo - * @tc.desc: to queryVirtual greater than or equalTo - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryGreaterThanOrEqualTo, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryGreaterThanOrEqualTo begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.GreaterThanOrEqualTo("$.age", 1); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.GreaterThanOrEqualTo("$.age", 1); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryLessThanOrEqualTo - * @tc.desc: to queryVirtual less than or equalTo - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryLessThanOrEqualTo, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryLessThanOrEqualTo begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.LessThanOrEqualTo("$.age", 3); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.LessThanOrEqualTo("$.age", 3); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryIn - * @tc.desc: to queryVirtual in - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryIn, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryIn begin."); - std::vector vectInt { 1, 2 }; - DataSharePredicates predicatesVirtual; - predicatesVirtual.In("$.age", vectInt); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.In("$.age", vectInt); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryNotIn - * @tc.desc: to queryVirtual not in - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryNotIn, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryNotIn begin."); - std::vector vectInt { 1, 2 }; - DataSharePredicates predicatesVirtual; - predicatesVirtual.NotIn("$.age", vectInt); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.NotIn("$.age", vectInt); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryLike - * @tc.desc: to queryVirtual or, like - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryLike, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryLike begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.Like("$.age", "1"); - predicatesVirtual.Or(); - predicatesVirtual.Like("$.age", "3"); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.Like("$.age", "1"); - trgQueryVirtual.Or(); - trgQueryVirtual.Like("$.age", "3"); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryUnlike - * @tc.desc: to queryVirtual and, unlike - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryUnlike, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryUnlike begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.Unlike("$.age", "1"); - predicatesVirtual.And(); - predicatesVirtual.Unlike("$.age", "3"); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.Unlike("$.age", "1"); - trgQueryVirtual.And(); - trgQueryVirtual.Unlike("$.age", "3"); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryIsNull - * @tc.desc: to queryVirtual is null - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryIsNull, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryIsNull begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.IsNull("$.age"); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.IsNull("$.age"); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryIsNotNull - * @tc.desc: to queryVirtual is not null - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryIsNotNull, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryIsNotNull begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.IsNotNull("$.age"); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.IsNotNull("$.age"); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryOrderByAsc - * @tc.desc: to queryVirtual is order by asc - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryOrderByAsc, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryOrderByAsc begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.OrderByAsc("$.age"); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.OrderByAsc("$.age"); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryOrderByDesc - * @tc.desc: to queryVirtual is order by desc - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryOrderByDesc, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryOrderByDesc begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.OrderByDesc("$.age"); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.OrderByDesc("$.age"); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryLimit - * @tc.desc: to queryVirtual is limit - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryLimit, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryLimit begin."); - DataSharePredicates predicatesVirtual; - predicatesVirtual.Limit(0, 9); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.Limit(0, 9); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: PredicatesToQueryInKeys - * @tc.desc: to queryVirtual is in keys - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, PredicatesToQueryInKeys, TestSize.Level0) -{ - ZLOGI("PredicatesToQueryInKeys begin."); - std::vector keys { "test_field", "", "^test_field", "^", "test_field_name" }; - DataSharePredicates predicatesVirtual; - predicatesVirtual.InKeys(keys); - DataQuery queryVirtual; - auto statusVirtual = KvUtils::ToQuery(predicatesVirtual, queryVirtual); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - DataQuery trgQueryVirtual; - trgQueryVirtual.InKeys(keys); - EXPECT_EQ(queryVirtual.ToString(), trgQueryVirtual.ToString()); -} - -/** - * @tc.name: DataShareValuesBucketToEntryAbnormal - * @tc.desc: dataShare values bucket to entry, the bucket is invalid - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntryAbnormal, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntryAbnormal begin."); - DataShareValuesBucket bucket {}; - Entry trgEntry {}; - auto entry = KvUtils::ToEntry(bucket); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); - bucket.Put("invalid key", "value"); - EXPECT_FALSE(bucket.IsEmpty()); - entry = KvUtils::ToEntry(bucket); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); - bucket.Put(KEY, "value"); - entry = KvUtils::ToEntry(bucket); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); -} - -/** - * @tc.name: DataShareValuesBucketToEntryNull - * @tc.desc: dataShare values bucket to entry, the bucket value is null - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntryNull, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntryNull begin."); - DataShareValuesBucket bucket {}; - bucket.Put(KEY, {}); - bucket.Put(VALUE, {}); - auto entry = KvUtils::ToEntry(bucket); - Entry trgEntry; - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); -} - -/** - * @tc.name: DataShareValuesBucketToEntryInt64_t - * @tc.desc: dataShare values bucket to entry, the bucket value type is int64_t - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntryInt64_t, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntryInt64_t begin."); - DataShareValuesBucket bucket {}; - Entry trgEntry; - var_t varValue; - varValue.emplace<1>(314); - var_t varKey; - varKey.emplace<3>("314"); - bucket.Put(KEY, varKey); - bucket.Put(VALUE, varValue); - auto entry = KvUtils::ToEntry(bucket); - trgEntry.key = VariantKey2Blob(varKey); - trgEntry.value = VariantValue2Blob(varValue); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); -} - -/** - * @tc.name: DataShareValuesBucketToEntryDouble - * @tc.desc: dataShare values bucket to entry, the bucket value type is double - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntryDouble, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntryDouble begin."); - DataShareValuesBucket bucket {}; - Entry trgEntry; - var_t varValue; - varValue.emplace<2>(3.14); - var_t varKey; - varKey.emplace<3>("314"); - bucket.Put(KEY, varKey); - bucket.Put(VALUE, varValue); - auto entry = KvUtils::ToEntry(bucket); - trgEntry.key = VariantKey2Blob(varKey); - trgEntry.value = VariantValue2Blob(varValue); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); -} - -/** - * @tc.name: DataShareValuesBucketToEntryString - * @tc.desc: dataShare values bucket to entry, the bucket value type is string - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntryString, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntryString begin."); - DataShareValuesBucket bucket {}; - Entry trgEntry; - var_t varValue; - varValue.emplace<3>("3.14"); - var_t varKey; - varKey.emplace<3>("314"); - bucket.Put(KEY, varKey); - bucket.Put(VALUE, varValue); - auto entry = KvUtils::ToEntry(bucket); - trgEntry.key = VariantKey2Blob(varKey); - trgEntry.value = VariantValue2Blob(varValue); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); -} - -/** - * @tc.name: DataShareValuesBucketToEntryBool - * @tc.desc: dataShare values bucket to entry, the bucket value type is bool - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntryBool, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntryBool begin."); - DataShareValuesBucket bucket {}; - Entry trgEntry; - var_t varValue; - varValue.emplace<4>(true); - var_t varKey; - varKey.emplace<3>("314"); - bucket.Put(KEY, varKey); - bucket.Put(VALUE, varValue); - auto entry = KvUtils::ToEntry(bucket); - trgEntry.key = VariantKey2Blob(varKey); - trgEntry.value = VariantValue2Blob(varValue); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); -} - -/** - * @tc.name: DataShareValuesBucketToEntryUint8Array - * @tc.desc: dataShare values bucket to entry, the bucket value type is uint8array - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntryUint8Array, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntryUint8Array begin."); - DataShareValuesBucket bucket {}; - Entry trgEntry; - var_t varValue; - std::vector vecUint8 { 3, 14 }; - varValue.emplace<5>(vecUint8); - var_t varKey; - varKey.emplace<3>("314"); - bucket.Put(KEY, varKey); - bucket.Put(VALUE, varValue); - auto entry = KvUtils::ToEntry(bucket); - trgEntry.key = VariantKey2Blob(varKey); - trgEntry.value = VariantValue2Blob(varValue); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); -} - -/** - * @tc.name: DataShareValuesBucketToEntryInvalidKey - * @tc.desc: dataShare values bucket to entry, the bucket key type is not string - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntryInvalidKey, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntryInvalidKey begin."); - DataShareValuesBucket bucket {}; - Entry trgEntry; - var_t varValue; - std::vector vecUint8 { 3, 14 }; - varValue.emplace<5>(vecUint8); - var_t varKey; - varKey.emplace<1>(314); - bucket.Put(KEY, varKey); - bucket.Put(VALUE, varValue); - auto entry = KvUtils::ToEntry(bucket); - trgEntry.key = VariantKey2Blob(varKey); - EXPECT_EQ(Entry2Str(entry), Entry2Str(trgEntry)); -} - -/** - * @tc.name: DataShareValuesBucketToEntriesAbnormal - * @tc.desc: dataShare values bucket to entries, the buckets is invalid - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntriesAbnormal, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntriesAbnormal begin."); - std::vector buckets {}; - auto entries = KvUtils::ToEntries(buckets); - EXPECT_TRUE(entries.empty()); -} - -/** - * @tc.name: DataShareValuesBucketToEntriesNormal - * @tc.desc: dataShare values bucket to entries, the buckets has valid value - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, DataShareValuesBucketToEntriesNormal, TestSize.Level0) -{ - ZLOGI("DataShareValuesBucketToEntriesNormal begin."); - std::vector buckets {}; - DataShareValuesBucket bucket; - Entry trgEntryFirst; - Entry trgEntrySecond; - var_t varValue; - varValue.emplace<1>(314); - var_t varKey; - varKey.emplace<3>("314"); - bucket.Put(KEY, varKey); - bucket.Put(VALUE, varValue); - buckets.emplace_back(bucket); - trgEntryFirst.key = VariantKey2Blob(varKey); - trgEntryFirst.value = VariantValue2Blob(varValue); - bucket.Clear(); - varValue.emplace<2>(3.14); - varKey.emplace<3>("3.14"); - bucket.Put(KEY, varKey); - bucket.Put(VALUE, varValue); - buckets.emplace_back(bucket); - trgEntrySecond.key = VariantKey2Blob(varKey); - trgEntrySecond.value = VariantValue2Blob(varValue); - auto entries = KvUtils::ToEntries(buckets); - EXPECT_EQ(entries.size(), 2); - EXPECT_EQ(Entry2Str(entries[0]), Entry2Str(trgEntryFirst)); - EXPECT_EQ(Entry2Str(entries[1]), Entry2Str(trgEntrySecond)); -} - -/** - * @tc.name: GetKeysFromDataSharePredicatesAbnormal - * @tc.desc: get keys from data share predicatesVirtual, the predicatesVirtual is invalid - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, GetKeysFromDataSharePredicatesAbnormal, TestSize.Level0) -{ - ZLOGI("GetKeysFromDataSharePredicatesAbnormal begin."); - DataSharePredicates predicatesVirtual; - std::vector kvKeys; - auto statusVirtual = KvUtils::GetKeys(predicatesVirtual, kvKeys); - EXPECT_EQ(statusVirtual, Status::ERROR); - predicatesVirtual.EqualTo("$.age", 1); - statusVirtual = KvUtils::GetKeys(predicatesVirtual, kvKeys); - EXPECT_EQ(statusVirtual, Status::NOT_SUPPORT); -} - -/** - * @tc.name: GetKeysFromDataSharePredicatesNormal - * @tc.desc: get keys from data share predicatesVirtual, the predicatesVirtual has valid value - * @tc.type: FUNC - * @tc.require: - * @tc.author: sqlzuojiangjiang - */ -HWTEST_F(KvUtilVirtualTest, GetKeysFromDataSharePredicatesNormal, TestSize.Level0) -{ - ZLOGI("GetKeysFromDataSharePredicatesNormal begin."); - std::vector keys { "test_field", "", "^test_field", "^", "test_field_name" }; - DataSharePredicates predicatesVirtual; - predicatesVirtual.InKeys(keys); - std::vector kvKeys; - auto statusVirtual = KvUtils::GetKeys(predicatesVirtual, kvKeys); - EXPECT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_EQ(keys.size(), kvKeys.size()); - for (size_t i = 0; i < keys.size(); i++) { - EXPECT_EQ(keys[i], kvKeys[i].ToString()); - } -} - -/** - * @tc.name: ToResultSetBridge_NullResultSet_ReturnsNull - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToResultSetBridge_NullResultSet_ReturnsNull, TestSize.Level0) -{ - ZLOGI("ToResultSetBridge_NullResultSet_ReturnsNull begin."); - std::shared_ptr nullResultSet = nullptr; - auto result = KvUtils::ToResultSetBridge(nullResultSet); - EXPECT_EQ(result, nullptr); -} - -/** - * @tc.name: ToResultSetBridge_ValidResultSet_ReturnsBridge - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToResultSetBridge_ValidResultSet_ReturnsBridge, TestSize.Level0) -{ - ZLOGI("ToResultSetBridge_ValidResultSet_ReturnsBridge begin."); - auto result = KvUtils::ToResultSetBridge(resultSet); - EXPECT_NE(result, nullptr); -} - -/** - * @tc.name: ToQuery_ValidOperations_Success - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToQuery_ValidOperations_Success, TestSize.Level0) -{ - ZLOGI("ToQuery_ValidOperations_Success begin."); - predicates->AddOperation({IN_KEY, {"key1", "key2"}}); - Status status = KvUtils::ToQuery(*predicates, *query); - EXPECT_EQ(status, Status::SUCCESS); -} - -/** - * @tc.name: ToQuery_InvalidOperation_NotSupport - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToQuery_InvalidOperation_NotSupport, TestSize.Level0) -{ - ZLOGI("ToQuery_InvalidOperation_NotSupport begin."); - predicates->AddOperation({-1, {}}); - Status status = KvUtils::ToQuery(*predicates, *query); - EXPECT_EQ(status, Status::NOT_SUPPORT); -} - -/** - * @tc.name: ToEntries_EmptyBuckets_ReturnsEmpty - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToEntries_EmptyBuckets_ReturnsEmpty, TestSize.Level0) -{ - ZLOGI("ToEntries_EmptyBuckets_ReturnsEmpty begin."); - std::vector emptyBuckets; - auto entries = KvUtils::ToEntries(emptyBuckets); - EXPECT_TRUE(entries.empty()); -} - -/** - * @tc.name: ToEntries_NonEmptyBuckets_ReturnsEntries - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToEntries_NonEmptyBuckets_ReturnsEntries, TestSize.Level0) -{ - ZLOGI("ToEntries_NonEmptyBuckets_ReturnsEntries begin."); - DataShareValuesBucket bucket; - bucket.valuesMap = {{"key", "value"}}; - std::vector buckets = {bucket}; - auto entries = KvUtils::ToEntries(buckets); - EXPECT_EQ(entries.size(), 1); -} - -/** - * @tc.name: ToEntry_EmptyValuesMap_ReturnsEmptyEntry - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToEntries_NonEmptyBuckets_ReturnsEntries, TestSize.Level0) -{ - ZLOGI("ToEntries_NonEmptyBuckets_ReturnsEntries begin."); - DataShareValuesBucket bucket; - Entry entry = KvUtils::ToEntry(bucket); - EXPECT_TRUE(entry.key.empty()); - EXPECT_TRUE(entry.value.empty()); -} - -/** - * @tc.name: ToEntry_NonEmptyValuesMap_ReturnsEntry - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToEntry_NonEmptyValuesMap_ReturnsEntry, TestSize.Level0) -{ - ZLOGI("ToEntry_NonEmptyValuesMap_ReturnsEntry begin."); - DataShareValuesBucket bucket; - bucket.valuesMap = {{"key", "value"}}; - Entry entry = KvUtils::ToEntry(bucket); - EXPECT_FALSE(entry.key.empty()); - EXPECT_FALSE(entry.value.empty()); -} - -/** - * @tc.name: GetKeys_EmptyOperations_ReturnsError - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, GetKeys_EmptyOperations_ReturnsError, TestSize.Level0) -{ - ZLOGI("GetKeys_EmptyOperations_ReturnsError begin."); - std::vector keys; - Status status = KvUtils::GetKeys(*predicates, keys); - EXPECT_EQ(status, Status::ERROR); -} - -/** - * @tc.name: GetKeys_ValidInKeyOperation_Success - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, GetKeys_ValidInKeyOperation_Success, TestSize.Level0) -{ - ZLOGI("GetKeys_ValidInKeyOperation_Success begin."); - predicates->AddOperation({IN_KEY, {"key1", "key2"}}); - std::vector keys; - Status status = KvUtils::GetKeys(*predicates, keys); - EXPECT_EQ(status, Status::SUCCESS); - EXPECT_EQ(keys.size(), 2); -} - -/** - * @tc.name: GetKeys_InvalidOperation_NotSupport - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, GetKeys_InvalidOperation_NotSupport, TestSize.Level0) -{ - ZLOGI("GetKeys_InvalidOperation_NotSupport begin."); - predicates->AddOperation({-1, {}}); - std::vector keys; - Status status = KvUtils::GetKeys(*predicates, keys); - EXPECT_EQ(status, Status::NOT_SUPPORT); -} - -/** - * @tc.name: ToEntryKey_ValidKey_Success - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToEntryKey_ValidKey_Success, TestSize.Level0) -{ - ZLOGI("ToEntryKey_ValidKey_Success begin."); - std::map values = {{"key", "value"}}; - Blob blob; - Status status = KvUtils::ToEntryKey(values, blob); - EXPECT_EQ(status, Status::SUCCESS); -} - -/** - * @tc.name: ToEntryKey_MissingKey_Error - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToEntryKey_MissingKey_Error, TestSize.Level0) -{ - ZLOGI("ToEntryKey_MissingKey_Error begin."); - std::map values = {{"otherKey", "value"}}; - Blob blob; - Status status = KvUtils::ToEntryKey(values, blob); - EXPECT_EQ(status, Status::ERROR); -} - -/** - * @tc.name: ToEntryValue_ValidValue_Success - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToEntryValue_ValidValue_Success, TestSize.Level0) -{ - ZLOGI("ToEntryValue_ValidValue_Success begin."); - std::map values = {{"value", "value"}}; - Blob blob; - Status status = KvUtils::ToEntryValue(values, blob); - EXPECT_EQ(status, Status::SUCCESS); -} - -/** - * @tc.name: ToEntryValue_MissingValue_Error - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KvUtilsTest, ToEntryValue_MissingValue_Error, TestSize.Level0) -{ - ZLOGI("ToEntryValue_MissingValue_Error begin."); - std::map values = {{"otherValue", "value"}}; - Blob blob; - Status status = KvUtils::ToEntryValue(values, blob); - EXPECT_EQ(status, Status::ERROR); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/kvdb_notifier_virtual_test.cpp b/kv_store/databaseutils/test/kvdb_notifier_virtual_test.cpp deleted file mode 100644 index 06ca65e7..00000000 --- a/kv_store/databaseutils/test/kvdb_notifier_virtual_test.cpp +++ /dev/null @@ -1,397 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "KVDBNotifierVirtualTest" - -#include -#include -#include -#include -#include -#include "kvdb_notifier_client.h" -#include "kvdb_sync_callback.h" -#include "kv_store_observer.h" -#include "kvdb_notifier_stub.h" -#include "message_parcel.h" -#include "types.h" -#include "dev_manager.h" -#include "dds_trace.h" -#include "store_util.h" - -using namespace OHOS::DistributedKv; -using namespace testing; -using namespace testing::ext; -namespace OHOS::Test { -class KVDBNotifierClientVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void KVDBNotifierClientVirtualTest::SetUpTestCase(void) -{} - -void KVDBNotifierClientVirtualTest::TearDownTestCase(void) -{} - -void KVDBNotifierClientVirtualTest::SetUp(void) -{} - -void KVDBNotifierClientVirtualTest::TearDown(void) -{} - -class MockDevManager : public DevManager { -public: - string ToUUID(const string &device) override - { - if (device == "device1") { - return "uuid1"; - } - return ""; - } -}; - -class MockKvStoreSyncCallback : public KvStoreSyncCallback { -public: - void SyncCompleted(const map &results) override - { - syncCompletedCalled = true; - } - void SyncCompleted(const map &results, uint64_t sequenceId) override - { - syncCompletedWithIdCalled = true; - } - bool syncCompletedCalled = false; - bool syncCompletedWithIdCalled = false; -}; - -class MockKvStoreObserver : public KvStoreObserver { -public: - void OnSwitchChange(const SwitchNotification ¬ification) override - { - onSwitchChangeCalled = true; - } - bool onSwitchChangeCalled = false; -}; - -class MockAsyncDetail : public AsyncDetail { -public: - void operator()(ProgressDetail &&detail) override - { - asyncDetailCalled = true; - } - bool asyncDetailCalled = false; -}; - -class KVDBNotifierClientTest : public testing::Test { -protected: - void SetUp() override - { - devManager = make_shared(); - notifierClient = make_unique(); - } - - shared_ptr devManager; - unique_ptr notifierClient; -}; - -class KVDBNotifierStubVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void KVDBNotifierStubVirtualTest::SetUpTestCase(void) -{} - -void KVDBNotifierStubVirtualTest::TearDownTestCase(void) -{} - -void KVDBNotifierStubVirtualTest::SetUp(void) -{} - -void KVDBNotifierStubVirtualTest::TearDown(void) -{} - -/** - * @tc.name: SyncCompleted_CallbackFound_CallbackInvoked - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, SyncCompleted_CallbackFound_CallbackInvoked, TestSize.Level0) -{ - ZLOGI("SyncCompleted_CallbackFound_CallbackInvoked begin."); - uint64_t sequenceId = 1; - auto callback = make_shared(); - notifierClient->AddSyncCallback(callback, sequenceId); - - notifierClient->SyncCompleted({}, sequenceId); - - EXPECT_TRUE(callback->syncCompletedCalled); - EXPECT_TRUE(callback->syncCompletedWithIdCalled); -} - -/** - * @tc.name: SyncCompleted_CallbackNotFound_NoInvocation - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, SyncCompleted_CallbackNotFound_NoInvocation, TestSize.Level0) -{ - ZLOGI("SyncCompleted_CallbackNotFound_NoInvocation begin."); - uint64_t sequenceId = 1; - notifierClient->SyncCompleted({}, sequenceId); - // No callback added, so no invocation should happen -} - -/** - * @tc.name: OnRemoteChange_DeviceToUUID_RemoteUpdated - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, OnRemoteChange_DeviceToUUID_RemoteUpdated, TestSize.Level0) -{ - ZLOGI("OnRemoteChange_DeviceToUUID_RemoteUpdated begin."); - map mask = {{"device1", true}}; - notifierClient->OnRemoteChange(mask, static_cast(DataType::TYPE_STATICS)); - - // Check if the remote is updated - auto [exist, value] = notifierClient->remotes_.Find("uuid1"); - EXPECT_TRUE(exist); - EXPECT_TRUE(value.first); -} - -/** - * @tc.name: IsChanged_DeviceExists_ReturnsCorrectStatus - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, IsChanged_DeviceExists_ReturnsCorrectStatus, TestSize.Level0) -{ - ZLOGI("IsChanged_DeviceExists_ReturnsCorrectStatus begin."); - notifierClient->remotes_.InsertOrAssign("uuid1", make_pair(true, false)); - - EXPECT_TRUE(notifierClient->IsChanged("uuid1", DataType::TYPE_STATICS)); - EXPECT_FALSE(notifierClient->IsChanged("uuid1", DataType::TYPE_DYNAMICAL)); -} - -/** - * @tc.name: AddSyncCallback_NullCallback_NoAddition - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, AddSyncCallback_NullCallback_NoAddition, TestSize.Level0) -{ - ZLOGI("AddSyncCallback_NullCallback_NoAddition begin."); - uint64_t sequenceId = 1; - notifierClient->AddSyncCallback(nullptr, sequenceId); - - // No callback should be added - EXPECT_FALSE(notifierClient->syncCallbackInfo_.Find(sequenceId).first); -} - -/** - * @tc.name: AddCloudSyncCallback_NullCallback_NoAddition - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, AddCloudSyncCallback_NullCallback_NoAddition, TestSize.Level0) -{ - ZLOGI("AddCloudSyncCallback_NullCallback_NoAddition begin."); - uint64_t sequenceId = 1; - notifierClient->AddCloudSyncCallback(sequenceId, nullptr); - - // No callback should be added - EXPECT_FALSE(notifierClient->cloudSyncCallbacks_.Find(sequenceId).first); -} - -/** - * @tc.name: AddSwitchCallback_NullObserver_NoAddition - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, AddSwitchCallback_NullObserver_NoAddition, TestSize.Level0) -{ - ZLOGI("AddSwitchCallback_NullObserver_NoAddition begin."); - notifierClient->AddSwitchCallback("appId", nullptr); - - // No observer should be added - EXPECT_EQ(notifierClient->switchObservers_.Size(), 0); -} - -/** - * @tc.name: AddSwitchCallback_DuplicateObserver_NoAddition - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, AddSwitchCallback_DuplicateObserver_NoAddition, TestSize.Level0) -{ - ZLOGI("AddSwitchCallback_DuplicateObserver_NoAddition begin."); - auto observer = make_shared(); - notifierClient->AddSwitchCallback("appId", observer); - notifierClient->AddSwitchCallback("appId", observer); - - // Only one observer should be added - EXPECT_EQ(notifierClient->switchObservers_.Size(), 1); -} - -/** - * @tc.name: OnSwitchChange_ObserversNotified - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierClientVirtualTest, OnSwitchChange_ObserversNotified, TestSize.Level0) -{ - ZLOGI("OnSwitchChange_ObserversNotified begin."); - auto observer = make_shared(); - notifierClient->AddSwitchCallback("appId", observer); - - SwitchNotification notification; - notifierClient->OnSwitchChange(notification); - - EXPECT_TRUE(observer->onSwitchChangeCalled); -} - -/** - * @tc.name: OnRemoteRequest_ValidCodeAndDescriptor_ShouldInvokeHandler - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierStubVirtualTest, OnRemoteRequest_ValidCodeAndDescriptor_ShouldInvokeHandler, TestSize.Level0) -{ - ZLOGI("OnRemoteRequest_ValidCodeAndDescriptor_ShouldInvokeHandler begin."); - MessageParcel data; - MessageParcel reply; - MessageOption option; - data.WriteInterfaceToken(KVDBNotifierStub::GetDescriptor()); - data.WriteInt32(1); // 假设这是有效的数据 - - EXPECT_CALL(*stub, OnSyncCompleted(testing::Ref(data), testing::_)).WillOnce(testing::Return(ERR_NONE)); - - int32_t result = - stub->OnRemoteRequest(static_cast(KVDBNotifierCode::SYNC_COMPLETED), data, reply, option); - EXPECT_EQ(result, ERR_NONE); -} - -/** - * @tc.name: OnRemoteRequest_InvalidDescriptor_ShouldReturnError - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierStubVirtualTest, OnRemoteRequest_InvalidDescriptor_ShouldReturnError, TestSize.Level0) -{ - ZLOGI("OnRemoteRequest_InvalidDescriptor_ShouldReturnError begin."); - MessageParcel data; - MessageParcel reply; - MessageOption option; - data.WriteInterfaceToken(u"InvalidDescriptor"); - - int32_t result = - stub->OnRemoteRequest(static_cast(KVDBNotifierCode::SYNC_COMPLETED), data, reply, option); - EXPECT_EQ(result, -1); -} - -/** - * @tc.name: OnRemoteRequest_CodeOutOfBound_ShouldReturnError - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierStubVirtualTest, OnRemoteRequest_CodeOutOfBound_ShouldReturnError, TestSize.Level0) -{ - ZLOGI("OnRemoteRequest_CodeOutOfBound_ShouldReturnError begin."); - MessageParcel data; - MessageParcel reply; - MessageOption option; - data.WriteInterfaceToken(KVDBNotifierStub::GetDescriptor()); - - int32_t result = - stub->OnRemoteRequest(static_cast(KVDBNotifierCode::TRANS_BUTT), data, reply, option); - EXPECT_EQ(result, - IPCObjectStub::OnRemoteRequest(static_cast(KVDBNotifierCode::TRANS_BUTT), data, reply, option)); -} - -/** - * @tc.name: OnSyncCompleted_ValidData_ShouldInvokeSyncCompleted - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierStubVirtualTest, OnSyncCompleted_ValidData_ShouldInvokeSyncCompleted, TestSize.Level0) -{ - ZLOGI("OnSyncCompleted_ValidData_ShouldInvokeSyncCompleted begin."); - MessageParcel data; - MessageParcel reply; - std::map results = {{"key", Status::SUCCESS}}; - uint64_t sequenceId = 12345; - - EXPECT_CALL(ITypesUtil, Unmarshal(testing::Ref(data), testing::Ref(results), testing::Ref(sequenceId))) - .WillOnce(testing::Return(true)); - - EXPECT_CALL(*stub, SyncCompleted(testing::_, sequenceId)).Times(1); - - int32_t result = stub->OnSyncCompleted(data, reply); - EXPECT_EQ(result, ERR_NONE); -} - -/** - * @tc.name: OnSyncCompleted_InvalidData_ShouldReturnError - * @tc.desc: - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(KVDBNotifierStubVirtualTest, OnSyncCompleted_InvalidData_ShouldReturnError, TestSize.Level0) -{ - ZLOGI("OnSyncCompleted_InvalidData_ShouldReturnError begin."); - MessageParcel data; - MessageParcel reply; - std::map results; - uint64_t sequenceId = 0; - - EXPECT_CALL(ITypesUtil, Unmarshal(testing::Ref(data), testing::Ref(results), testing::Ref(sequenceId))) - .WillOnce(testing::Return(false)); - - int32_t result = stub->OnSyncCompleted(data, reply); - EXPECT_EQ(result, IPC_STUB_INVALID_DATA_ERR); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/kvstore_datashare_bridge_virtual_test.cpp b/kv_store/databaseutils/test/kvstore_datashare_bridge_virtual_test.cpp deleted file mode 100644 index 659251ec..00000000 --- a/kv_store/databaseutils/test/kvstore_datashare_bridge_virtual_test.cpp +++ /dev/null @@ -1,740 +0,0 @@ -/* - * Copyright (c) 2022 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. - */ -#define LOG_TAG "KvstoreDatashareBridgeVirtualTest" - -#include "distributed_kv_data_manager.h" -#include "gtest/gtest.h" -#include "kv_utils.h" -#include -#include -#include "kvstore_datashare_bridge.h" -#include "kvstore_result_set.h" -#include "result_set_bridge.h" -#include "store_errno.h" -#include "types.h" -#include "kvstore_observer_client.h" -#include "kvstore_observer.h" -#include "log_print.h" -#include -#include -#include -#include "kvstore_service_death_notifier.h" -#include "if_system_ability_manager.h" -#include "iservice_registry.h" -#include "kvstore_client_death_observer.h" -#include "datamgr_service_proxy.h" -#include "refbase.h" -#include "system_ability_definition.h" -#include "task_executor.h" - -using namespace testing::ext; -using namespace OHOS::DistributedKv; -using namespace OHOS::DataShare; -namespace OHOS::Test { -class BridgeWriterVirtual final : public ResultSetBridge::Writer { -public: - int AllocRow() override; - int WriteVirtual(uint32_t column) override; - int WriteVirtual(uint32_t column, int64_t value) override; - int WriteVirtual(uint32_t column, double value) override; - int WriteVirtual(uint32_t column, const uint8_t *value, size_t size) override; - int WriteVirtual(uint32_t column, const char *value, size_t size) override; - void SetAllocRowStatue(int status); - Key GetKey() const; - Key GetValue() const; - -private: - int allocStatus_Virtual = E_OK; - std::vector key_Virtual; - std::vector value_Virtual; -}; - -void BridgeWriterVirtual::SetAllocRowStatue(int status) -{ - allocStatus_Virtual = status; -} - -Key BridgeWriterVirtual::GetKey() const -{ - return key_Virtual; -} - -Value BridgeWriterVirtual::GetValue() const -{ - return value_Virtual; -} - -int BridgeWriterVirtual::AllocRow() -{ - return allocStatus_Virtual; -} - -int BridgeWriterVirtual::WriteVirtual(uint32_t column) -{ - return E_OK; -} - -int BridgeWriterVirtual::WriteVirtual(uint32_t column, int64_t value) -{ - return E_OK; -} - -int BridgeWriterVirtual::WriteVirtual(uint32_t column, double value) -{ - return E_OK; -} - -int BridgeWriterVirtual::WriteVirtual(uint32_t column, const uint8_t *value, size_t size) -{ - return E_OK; -} - -int BridgeWriterVirtual::WriteVirtual(uint32_t column, const char *value, size_t size) -{ - if (column < 0 || column > 1 || value == nullptr) { - return E_ERROR; - } - auto vec = std::vector(value, value + size - 1); - if (column == 0) { - key_Virtual.insert(key_Virtual.end(), vec.begin(), vec.end()); - } else { - value_Virtual.insert(value_Virtual.end(), vec.begin(), vec.end()); - } - return E_OK; -} - -class KvstoreDatashareBridgeVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp() {} - void TearDown() {} - -protected: - static DistributedKvDataManager managerVirtual; - static std::shared_ptr singleKvStoreVirtual; -}; -std::shared_ptr KvstoreDatashareBridgeVirtualTest::singleKvStoreVirtual = nullptr; -DistributedKvDataManager KvstoreDatashareBridgeVirtualTest::managerVirtual; -static constexpr int32_t INVALID_COUNT = -1; -static constexpr const char *VALID_SCHEMA_STRICT_DEFINE = "{\"SCHEMA_VERSION\":\"1.0\"," - "\"SCHEMA_MODE\":\"STRICT\"," - "\"SCHEMA_SKIPSIZE\":0," - "\"SCHEMA_DEFINE\":{" - "\"age\":\"INTEGER, NOT NULL\"" - "}," - "\"SCHEMA_INDEXES\":[\"$.age\"]}"; - -void KvstoreDatashareBridgeVirtualTest::SetUpTestCase(void) -{ - Options options = { .createIfMissing = true, .encrypt = false, .autoSync = false, - .kvStoreType = KvStoreType::SINGLE_VERSION, .schema = VALID_SCHEMA_STRICT_DEFINE }; - options.area = EL1; - options.securityLevel = S1; - options.baseDir = std::string("/data/service/el1/public/database/KvstoreDatashareBridgeVirtualTest"); - AppId appId = { "KvstoreDatashareBridgeVirtualTest" }; - StoreId storeId = { "test_single" }; - mkdir(options.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); - managerVirtual.DeleteKvStore(appId, storeId, options.baseDir); - managerVirtual.GetSingleKvStore(options, appId, storeId, singleKvStoreVirtual); - EXPECT_NE(singleKvStoreVirtual, nullptr); - singleKvStoreVirtual->Put("test_key_1", "{\"age\":1}"); - singleKvStoreVirtual->Put("test_key_2", "{\"age\":2}"); - singleKvStoreVirtual->Put("test_key_3", "{\"age\":3}"); - singleKvStoreVirtual->Put("data_share", "{\"age\":4}"); -} - -void KvstoreDatashareBridgeVirtualTest::TearDownTestCase(void) -{ - managerVirtual.DeleteKvStore({"KvstoreDatashareBridgeVirtualTest"}, {"test_single"}, - "/data/service/el1/public/database/KvstoreDatashareBridgeVirtualTest"); - (void) remove("/data/service/el1/public/database/KvstoreDatashareBridgeVirtualTest/key"); - (void) remove("/data/service/el1/public/database/KvstoreDatashareBridgeVirtualTest/kvdb"); - (void) remove("/data/service/el1/public/database/KvstoreDatashareBridgeVirtualTest"); -} - -class MockKvStoreResultSet : public KvStoreResultSet { -public: - explicit MockKvStoreResultSet(int count) : count_(count) - { - } - - int GetCount() override - { - return count_; - } - - bool MoveToPosition(int pos) override - { - return pos >= 0 && pos < count_; - } - - Status GetEntry(Entry &entry) override - { - if (pos_ >= 0 && pos_ < count_) { - entry.key = Key("key" + std::to_string(pos_)); - entry.value = Value("value" + std::to_string(pos_)); - return Status::SUCCESS; - } - return Status::ERROR; - } - -private: - int count_; - int pos_ = -1; -}; - -class MockWriter : public ResultSetBridge::Writer { -public: - int AllocRow() override - { - return E_OK; - } - - int Write(int index, const char *data, int size) override - { - return E_OK; - } -}; - -class KvStoreObserverClientVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void KvStoreObserverClientVirtualTest::SetUpTestCase(void) -{} - -void KvStoreObserverClientVirtualTest::TearDownTestCase(void) -{} - -void KvStoreObserverClientVirtualTest::SetUp(void) -{} - -void KvStoreObserverClientVirtualTest::TearDown(void) -{} - -class MockKvStoreObserver : public KvStoreObserver { -public: - MOCK_METHOD1(OnChange, void(const ChangeNotification &changeNotification)); - MOCK_METHOD2(OnChange, void(const DataOrigin &origin, IKvStoreObserver::Keys &&keys)); -}; - -class KvStoreServiceDeathNotifierVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void KvStoreServiceDeathNotifierVirtualTest::SetUpTestCase(void) -{} - -void KvStoreServiceDeathNotifierVirtualTest::TearDownTestCase(void) -{} - -void KvStoreServiceDeathNotifierVirtualTest::SetUp(void) -{} - -void KvStoreServiceDeathNotifierVirtualTest::TearDown(void) -{} - -class MockSystemAbilityManager : public SystemAbilityManager { -public: - MOCK_METHOD(sptr, CheckSystemAbility, (int32_t), (override)); -}; - -class MockTaskExecutor : public TaskExecutor { -public: - MOCK_METHOD(void, Execute, (std::function), (override)); -}; - -class MockKvStoreDeathRecipient : public KvStoreDeathRecipient { -public: - MOCK_METHOD(void, OnRemoteDied, (), (override)); -}; - -class SyncObserverVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void SyncObserverVirtualTest::SetUpTestCase(void) -{} - -void SyncObserverVirtualTest::TearDownTestCase(void) -{} - -void SyncObserverVirtualTest::SetUp(void) -{} - -void SyncObserverVirtualTest::TearDown(void) -{} - -class MockKvStoreSyncCallback : public KvStoreSyncCallback { -public: - MOCK_METHOD1(SyncCompleted, void(const std::map &results)); -}; - -/** -* @tc.name: SyncCompleted_EmptyCallbacks_NoException -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(MockKvStoreSyncCallback, SyncCompleted_EmptyCallbacks_NoException, TestSize.Level0) -{ - ZLOGI("SyncCompleted_EmptyCallbacks_NoException begin."); - SyncObserver observer; - std::map results; - EXPECT_NO_THROW(observer.SyncCompleted(results)); -} - -/** -* @tc.name: SyncCompleted_NonEmptyCallbacks_CallbacksInvoked -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(MockKvStoreSyncCallback, SyncCompleted_NonEmptyCallbacks_CallbacksInvoked, TestSize.Level0) -{ - ZLOGI("SyncCompleted_NonEmptyCallbacks_CallbacksInvoked begin."); - SyncObserver observer; - auto mockCallback = std::make_shared(); - observer.Add(mockCallback); - - std::map results = {{"key1", Status::SUCCESS}}; - EXPECT_CALL(*mockCallback, SyncCompleted(results)).Times(1); - - observer.SyncCompleted(results); -} - -/** -* @tc.name: GetDistributedKvDataService_ProxyExists_ReturnsProxy -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreServiceDeathNotifierVirtualTest, GetDistributedKvDataService_ProxyExists_ReturnsProxy, TestSize.Level0) -{ - ZLOGI("GetDistributedKvDataService_ProxyExists_ReturnsProxy begin."); - auto &instance = KvStoreServiceDeathNotifier::GetInstance(); - instance.kvDataServiceProxy_ = new DataMgrServiceProxy(nullptr); - - auto proxy = instance.GetDistributedKvDataService(); - - EXPECT_EQ(proxy, instance.kvDataServiceProxy_); -} - -/** -* @tc.name: GetDistributedKvDataService_ProxyDoesNotExist -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreServiceDeathNotifierVirtualTest, GetDistributedKvDataService_ProxyDoesNotExist, TestSize.Level0) -{ - ZLOGI("GetDistributedKvDataService_ProxyDoesNotExist begin."); - auto &instance = KvStoreServiceDeathNotifier::GetInstance(); - instance.kvDataServiceProxy_ = nullptr; - - auto samgr = std::dynamic_pointer_cast( - SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager()); - auto remote = sptr(new RemoteObject("test")); - EXPECT_CALL(*samgr, CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID)).WillOnce(testing::Return(remote)); - - auto proxy = instance.GetDistributedKvDataService(); - - EXPECT_NE(proxy, nullptr); - EXPECT_NE(instance.kvDataServiceProxy_, nullptr); -} - -/** -* @tc.name: RegisterClientDeathObserver_ProxyExists -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreServiceDeathNotifierVirtualTest, RegisterClientDeathObserver_ProxyExists, TestSize.Level0) -{ - ZLOGI("RegisterClientDeathObserver_ProxyExists begin."); - auto &instance = KvStoreServiceDeathNotifier::GetInstance(); - instance.kvDataServiceProxy_ = new DataMgrServiceProxy(nullptr); - - instance.RegisterClientDeathObserver(); - - EXPECT_NE(instance.clientDeathObserverPtr_, nullptr); -} - -/** -* @tc.name: AddServiceDeathWatcher_Success_AddsWatcher -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreServiceDeathNotifierVirtualTest, AddServiceDeathWatcher_Success_AddsWatcher, TestSize.Level0) -{ - ZLOGI("AddServiceDeathWatcher_Success_AddsWatcher begin."); - auto &instance = KvStoreServiceDeathNotifier::GetInstance(); - auto watcher = std::make_shared(); - - instance.AddServiceDeathWatcher(watcher); - - EXPECT_EQ(instance.serviceDeathWatchers_.size(), 1); -} - -/** -* @tc.name: RemoveServiceDeathWatcher_Found_RemovesWatcher -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreServiceDeathNotifierVirtualTest, RemoveServiceDeathWatcher_Found_RemovesWatcher, TestSize.Level0) -{ - ZLOGI("RemoveServiceDeathWatcher_Found_RemovesWatcher begin."); - auto &instance = KvStoreServiceDeathNotifier::GetInstance(); - auto watcher = std::make_shared(); - instance.serviceDeathWatchers_.insert(watcher); - - instance.RemoveServiceDeathWatcher(watcher); - - EXPECT_EQ(instance.serviceDeathWatchers_.size(), 0); -} - -/** -* @tc.name: ServiceDeathRecipient_OnRemoteDied_NotifiesWatchers -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreServiceDeathNotifierVirtualTest, ServiceDeathRecipient_OnRemoteDied_NotifiesWatchers, TestSize.Level0) -{ - ZLOGI("ServiceDeathRecipient_OnRemoteDied_NotifiesWatchers begin."); - auto &instance = KvStoreServiceDeathNotifier::GetInstance(); - auto watcher = std::make_shared(); - instance.serviceDeathWatchers_.insert(watcher); - - auto executor = std::dynamic_pointer_cast(TaskExecutor::GetInstance().GetExecutor()); - EXPECT_CALL(*executor, Execute(testing::_)).WillOnce(testing::Invoke([](std::function task) { - task(); - })); - - instance.ServiceDeathRecipient().OnRemoteDied(nullptr); - - EXPECT_CALL(*watcher, OnRemoteDied()).Times(1); -} - -/** -* @tc.name: OnChange_ChangeNotification_KvStoreObserverNotNull -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreObserverClientVirtualTest, OnChange_ChangeNotification_KvStoreObserverNotNull, TestSize.Level0) -{ - ZLOGI("OnChange_ChangeNotification_KvStoreObserverNotNull begin."); - ChangeNotification changeNotification; - EXPECT_CALL(*kvStoreObserver, OnChange(Ref(changeNotification))); - kvStoreObserverClient->OnChange(changeNotification); -} - -/** -* @tc.name: OnChange_ChangeNotification_KvStoreObserverNull -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreObserverClientVirtualTest, OnChange_ChangeNotification_KvStoreObserverNull, TestSize.Level0) -{ - ZLOGI("OnChange_ChangeNotification_KvStoreObserverNull begin."); - kvStoreObserverClient = std::make_shared(nullptr); - ChangeNotification changeNotification; - EXPECT_CALL(*kvStoreObserver, OnChange(Ref(changeNotification))).Times(0); - kvStoreObserverClient->OnChange(changeNotification); -} - -/** -* @tc.name: OnChange_DataOriginAndKeys_KvStoreObserverNotNull -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreObserverClientVirtualTest, OnChange_DataOriginAndKeys_KvStoreObserverNotNull, TestSize.Level0) -{ - ZLOGI("OnChange_DataOriginAndKeys_KvStoreObserverNotNull begin."); - DataOrigin origin; - IKvStoreObserver::Keys keys; - EXPECT_CALL(*kvStoreObserver, OnChange(Ref(origin), Ref(keys))); - kvStoreObserverClient->OnChange(origin, std::move(keys)); -} - -/** -* @tc.name: OnChange_DataOriginAndKeys_KvStoreObserverNull -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvStoreObserverClientVirtualTest, OnChange_DataOriginAndKeys_KvStoreObserverNull, TestSize.Level0) -{ - ZLOGI("OnChange_DataOriginAndKeys_KvStoreObserverNull begin."); - kvStoreObserverClient = std::make_shared(nullptr); - DataOrigin origin; - IKvStoreObserver::Keys keys; - EXPECT_CALL(*kvStoreObserver, OnChange(Ref(origin), Ref(keys))).Times(0); - kvStoreObserverClient->OnChange(origin, std::move(keys)); -} - -/** -* @tc.name: GetRowCountByInvalidBridge -* @tc.desc: get row countVirtual, the kvStore resultSetVirtual is nullptr -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, GetRowCountByInvalidBridge, TestSize.Level0) -{ - ZLOGI("GetRowCountByInvalidBridge begin."); - auto bridgeVirtual = std::make_shared(nullptr); - int32_t countVirtual; - auto resultVirtual = bridgeVirtual->GetRowCount(countVirtual); - EXPECT_EQ(resultVirtual, E_ERROR); - EXPECT_EQ(countVirtual, INVALID_COUNT); - std::vector columnNames; - resultVirtual = bridgeVirtual->GetAllColumnNames(columnNames); - EXPECT_FALSE(columnNames.empty()); - EXPECT_EQ(resultVirtual, E_OK); -} - -/** -* @tc.name: KvStoreResultSetToDataShareResultSetAbnormal -* @tc.desc: kvStore resultSetVirtual to dataShare resultSetVirtual, the former has invalid predicate -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, KvStoreResultSetToDataShareResultSetAbnormal, TestSize.Level0) -{ - ZLOGI("KvStoreResultSetToDataShareResultSetAbnormal begin."); - std::shared_ptr resultSetVirtual = nullptr; - DataQuery queryVirtual; - queryVirtual.KeyPrefix("key"); - singleKvStoreVirtual->GetResultSet(queryVirtual, resultSetVirtual); - EXPECT_NE(resultSetVirtual, nullptr); - auto bridgeVirtual = KvUtils::ToResultSetBridge(resultSetVirtual); - int32_t countVirtual; - auto resultVirtual = bridgeVirtual->GetRowCount(countVirtual); - EXPECT_EQ(resultVirtual, E_OK); - EXPECT_EQ(countVirtual, 0); -} - -/** -* @tc.name: KvStoreResultSetToDataShareResultSetNormal -* @tc.desc: kvStore resultSetVirtual to dataShare resultSetVirtual, the former has valid predicate -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, KvStoreResultSetToDataShareResultSetNormal, TestSize.Level0) -{ - ZLOGI("KvStoreResultSetToDataShareResultSetNormal begin."); - DataQuery queryVirtual; - queryVirtual.KeyPrefix("test"); - std::shared_ptr resultSetVirtual = nullptr; - singleKvStoreVirtual->GetResultSet(queryVirtual, resultSetVirtual); - EXPECT_NE(resultSetVirtual, nullptr); - auto bridgeVirtual = KvUtils::ToResultSetBridge(resultSetVirtual); - int32_t countVirtual; - auto resultVirtual = bridgeVirtual->GetRowCount(countVirtual); - EXPECT_EQ(resultVirtual, E_OK); - EXPECT_EQ(countVirtual, 3); - countVirtual = -1; - bridgeVirtual->GetRowCount(countVirtual); - EXPECT_EQ(countVirtual, 3); -} - -/** -* @tc.name: BridgeOnGoAbnormal -* @tc.desc: bridgeVirtual on go, the input parameter is invalid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, BridgeOnGoAbnormal, TestSize.Level0) -{ - ZLOGI("BridgeOnGoAbnormal begin."); - DataQuery queryVirtual; - queryVirtual.KeyPrefix("test"); - std::shared_ptr resultSetVirtual = nullptr; - singleKvStoreVirtual->GetResultSet(queryVirtual, resultSetVirtual); - EXPECT_NE(resultSetVirtual, nullptr); - auto bridgeVirtual = KvUtils::ToResultSetBridge(resultSetVirtual); - int32_t startVirtual = -1; - int32_t targetVirtual = 0; - BridgeWriterVirtual writerVirtual; - EXPECT_EQ(bridgeVirtual->OnGo(startVirtual, targetVirtual, writerVirtual), -1); - EXPECT_TRUE(writerVirtual.GetKey().Empty()); - EXPECT_TRUE(writerVirtual.GetValue().Empty()); - startVirtual = 0; - targetVirtual = -1; - EXPECT_EQ(bridgeVirtual->OnGo(startVirtual, targetVirtual, writerVirtual), -1); - EXPECT_TRUE(writerVirtual.GetKey().Empty()); - EXPECT_TRUE(writerVirtual.GetValue().Empty()); - startVirtual = 1; - targetVirtual = 0; - EXPECT_EQ(bridgeVirtual->OnGo(startVirtual, targetVirtual, writerVirtual), -1); - EXPECT_TRUE(writerVirtual.GetKey().Empty()); - EXPECT_TRUE(writerVirtual.GetValue().Empty()); - startVirtual = 1; - targetVirtual = 3; - EXPECT_EQ(bridgeVirtual->OnGo(startVirtual, targetVirtual, writerVirtual), -1); - EXPECT_TRUE(writerVirtual.GetKey().Empty()); - EXPECT_TRUE(writerVirtual.GetValue().Empty()); -} - -/** -* @tc.name: BridgeOnGoNormal -* @tc.desc: bridgeVirtual on go, the input parameter is valid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, BridgeOnGoNormal, TestSize.Level0) -{ - ZLOGI("BridgeOnGoNormal begin."); - DataQuery queryVirtual; - queryVirtual.KeyPrefix("test"); - std::shared_ptr resultSetVirtual = nullptr; - singleKvStoreVirtual->GetResultSet(queryVirtual, resultSetVirtual); - EXPECT_NE(resultSetVirtual, nullptr); - auto bridgeVirtual = KvUtils::ToResultSetBridge(resultSetVirtual); - int startVirtual = 0; - int targetVirtual = 2; - BridgeWriterVirtual writerVirtual; - writerVirtual.SetAllocRowStatue(E_ERROR); - EXPECT_EQ(bridgeVirtual->OnGo(startVirtual, targetVirtual, writerVirtual), -1); - EXPECT_TRUE(writerVirtual.GetKey().Empty()); - EXPECT_TRUE(writerVirtual.GetValue().Empty()); - writerVirtual.SetAllocRowStatue(E_OK); - EXPECT_EQ(bridgeVirtual->OnGo(startVirtual, targetVirtual, writerVirtual), targetVirtual); - size_t keySize = 0; - size_t valueSize = 0; - for (auto i = startVirtual; i <= targetVirtual; i++) { - resultSetVirtual->MoveToPosition(i); - Entry entry; - resultSetVirtual->GetEntry(entry); - keySize += entry.key.Size(); - valueSize += entry.value.Size(); - } - EXPECT_EQ(writerVirtual.GetKey().Size(), keySize); - EXPECT_EQ(writerVirtual.GetValue().Size(), valueSize); -} - -/** -* @tc.name: OnGo_ValidIndices_FillAllRows -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, OnGo_ValidIndices_FillAllRows, TestSize.Level0) -{ - ZLOGI("OnGo_ValidIndices_FillAllRows begin."); - MockWriter writer; - int result = bridge->OnGo(0, 5, writer); - EXPECT_EQ(result, 5); -} - -/** -* @tc.name: OnGo_InvalidStartIndex_ReturnsError -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, OnGo_InvalidStartIndex_ReturnsError, TestSize.Level0) -{ - ZLOGI("OnGo_InvalidStartIndex_ReturnsError begin."); - MockWriter writer; - int result = bridge->OnGo(-1, 5, writer); - EXPECT_EQ(result, -1); -} - -/** -* @tc.name: OnGo_InvalidTargetIndex_ReturnsError -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, OnGo_InvalidTargetIndex_ReturnsError, TestSize.Level0) -{ - ZLOGI("OnGo_InvalidTargetIndex_ReturnsError begin."); - MockWriter writer; - int result = bridge->OnGo(0, 15, writer); - EXPECT_EQ(result, -1); -} - -/** -* @tc.name: OnGo_StartGreaterThanTarget_ReturnsError -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, OnGo_StartGreaterThanTarget_ReturnsError, TestSize.Level0) -{ - ZLOGI("OnGo_StartGreaterThanTarget_ReturnsError begin."); - MockWriter writer; - int result = bridge->OnGo(5, 0, writer); - EXPECT_EQ(result, -1); -} - -/** -* @tc.name: OnGo_FillBlockFails_ReturnsPartialFill -* @tc.desc: -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(KvstoreDatashareBridgeVirtualTest, OnGo_FillBlockFails_ReturnsPartialFill, TestSize.Level0) -{ - ZLOGI("OnGo_FillBlockFails_ReturnsPartialFill begin."); - kvResultSet = std::make_shared(1); - bridge = std::make_shared(kvResultSet); - - MockWriter writer; - int result = bridge->OnGo(0, 5, writer); - EXPECT_EQ(result, 0); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/local_kv_store_counterfeit_unit_test.cpp b/kv_store/databaseutils/test/local_kv_store_counterfeit_unit_test.cpp deleted file mode 100644 index 930e0e74..00000000 --- a/kv_store/databaseutils/test/local_kv_store_counterfeit_unit_test.cpp +++ /dev/null @@ -1,1962 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "LocalKvStoreCounterfeitUnitTest" - -#include "block_data.h" -#include "distributed_kv_data_manager.h" -#include "log_print.h" -#include "types.h" -#include -#include -#include -#include - -using namespace testing::ext; -using namespace OHOS; -using namespace OHOS::DistributedKv; -class LocalKvStoreCounterfeitUnitTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - - static DistributedKvDataManager counterfeitTestManger_; - static std::shared_ptr counterfeitTestStore_; - static Status counterfeitTestStatus_; - static AppId counterfeitTestAppId_; - static StoreId counterfeitTestStoreId_; -}; -std::shared_ptr LocalKvStoreCounterfeitUnitTest::counterfeitTestStore_ = nullptr; -Status LocalKvStoreCounterfeitUnitTest::counterfeitTestStatus_ = Status::ERROR; -DistributedKvDataManager LocalKvStoreCounterfeitUnitTest::counterfeitTestManger_; -AppId LocalKvStoreCounterfeitUnitTest::counterfeitTestAppId_; -StoreId LocalKvStoreCounterfeitUnitTest::counterfeitTestStoreId_; - -void LocalKvStoreCounterfeitUnitTest::SetUpTestCase(void) -{ - mkdir("/data/service/el1/public/database/local", (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void LocalKvStoreCounterfeitUnitTest::TearDownTestCase(void) -{ - counterfeitTestManger_.CloseKvStore(counterfeitTestAppId_, counterfeitTestStore_); - counterfeitTestStore_ = nullptr; - counterfeitTestManger_.DeleteKvStore(counterfeitTestAppId_, - counterfeitTestStoreId_, "/data/service/el1/public/database/local"); - (void)remove("/data/service/el1/public/database/local/kvdb"); - (void)remove("/data/service/el1/public/database/local"); -} - -void LocalKvStoreCounterfeitUnitTest::SetUp(void) -{ - Options counterfeitOptions; - counterfeitOptions.securityLevel = S1; - counterfeitOptions.baseDir = std::string("/data/service/el1/public/database/local"); - counterfeitTestAppId_.appId = "local"; // define app name. - counterfeitTestStoreId_.storeId = "MAN"; // define kvstore(database) name - counterfeitTestManger_.DeleteKvStore(counterfeitTestAppId_, counterfeitTestStoreId_, counterfeitOptions.baseDir); - // [create and] open and initialize kvstore instance. - counterfeitTestStatus_ = counterfeitTestManger_.GetSingleKvStore(counterfeitOptions, - counterfeitTestAppId_, counterfeitTestStoreId_, counterfeitTestStore_); - ASSERT_EQ(Status::SUCCESS, counterfeitTestStatus_) << "wrong status"; - ASSERT_NE(nullptr, counterfeitTestStore_) << "kvStore is nullptr"; -} - -void LocalKvStoreCounterfeitUnitTest::TearDown(void) -{ - counterfeitTestManger_.CloseKvStore(counterfeitTestAppId_, counterfeitTestStore_); - counterfeitTestStore_ = nullptr; - counterfeitTestManger_.DeleteKvStore(counterfeitTestAppId_, counterfeitTestStoreId_); -} - -class DeviceObserverCounterfeitUnitTest : public KvStoreObserver { -public: - std::vector insertCounterfeitEntries_; - std::vector updateCounterfeitEntries_; - std::vector deleteCounterfeitEntries_; - std::string counterfeitDeviceId_; - bool isCounterfeitClear_ = false; - DeviceObserverCounterfeitUnitTest(); - ~DeviceObserverCounterfeitUnitTest() = default; - - void OnChange(const ChangeNotification &changeNotification); - - // reset the counterfeitCallCount_ to zero. - void ResetToZero(); - - uint32_t GetCallCount(uint32_t counterfeitTestValue = 1); - -private: - std::mutex counterfeitMutex_; - uint32_t counterfeitCallCount_ = 0; - BlockData counterfeitValue_ { 1, 0 }; -}; - -DeviceObserverCounterfeitUnitTest::DeviceObserverCounterfeitUnitTest() { } - -void DeviceObserverCounterfeitUnitTest::OnChange(const ChangeNotification &changeNotification) -{ - ZLOGD("begin."); - insertCounterfeitEntries_ = changeNotification.GetInsertEntries(); - updateCounterfeitEntries_ = changeNotification.GetUpdateEntries(); - deleteCounterfeitEntries_ = changeNotification.GetDeleteEntries(); - counterfeitDeviceId_ = changeNotification.GetDeviceId(); - isCounterfeitClear_ = changeNotification.IsClear(); - std::lock_guard guard(counterfeitMutex_); - ++counterfeitCallCount_; - counterfeitValue_.SetValue(counterfeitCallCount_); -} - -void DeviceObserverCounterfeitUnitTest::ResetToZero() -{ - std::lock_guard guard(counterfeitMutex_); - counterfeitCallCount_ = 0; - counterfeitValue_.Clear(0); -} - -uint32_t DeviceObserverCounterfeitUnitTest::GetCallCount(uint32_t counterfeitTestValue) -{ - int retryTimes = 0; - uint32_t callCount = 0; - while (retryTimes < counterfeitTestValue) { - callCount = counterfeitValue_.GetValue(); - if (callCount >= counterfeitTestValue) { - break; - } - std::lock_guard guard(counterfeitMutex_); - callCount = counterfeitValue_.GetValue(); - if (callCount >= counterfeitTestValue) { - break; - } - counterfeitValue_.Clear(callCount); - retryTimes++; - } - return callCount; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore001 - * @tc.desc: Subscribe success - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore001 begin."); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - auto counterfeitObserver = std::make_shared(); - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - counterfeitObserver = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore002 - * @tc.desc: Subscribe fail, counterfeitObserver is null - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore002 begin."); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - std::shared_ptr counterfeitObserver = nullptr; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::INVALID_ARGUMENT, counterfeitStatus) << "SubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore003 - * @tc.desc: Subscribe success and OnChange callback after put - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore003, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore003 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey = "Id1"; - Value counterfeitTestValue = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey, counterfeitTestValue); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - counterfeitObserver = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore004 - * @tc.desc: The same counterfeitObserver subscribe three times and OnChange callback after put - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore004, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore004 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey = "Id1"; - Value counterfeitTestValue = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey, counterfeitTestValue); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore005 - * @tc.desc: The different counterfeitObserver subscribe three times and OnChange callback after put - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore005, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore005 begin."); - auto observer1 = std::make_shared(); - auto observer2 = std::make_shared(); - auto observer3 = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, observer1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore failed, wrong"; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, observer2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore failed, wrong"; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, observer3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore failed, wrong"; - - Key counterfeitTestKey = "Id1"; - Value counterfeitTestValue = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey, counterfeitTestValue); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "Putting data to KvStore failed, wrong"; - ASSERT_EQ(static_cast(observer1->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer2->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer3->GetCallCount()), 1); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, observer1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, observer2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, observer3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore006 - * @tc.desc: Unsubscribe an counterfeitObserver and subscribe again - the map should be cleared after unsubscription. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore006, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore006 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - - Key counterfeitTestKey2 = "Id2"; - Value counterfeitTestValue2 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey2, counterfeitTestValue2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - - counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - Key counterfeitTestKey3 = "Id3"; - Value counterfeitTestValue3 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey3, counterfeitTestValue3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore007 - * @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is called multiple times after the put operation. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore007, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore007 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - - Key counterfeitTestKey2 = "Id2"; - Value counterfeitTestValue2 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey2, counterfeitTestValue2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - - Key counterfeitTestKey3 = "Id3"; - Value counterfeitTestValue3 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey3, counterfeitTestValue3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(3)), 3); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore008 -* @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is - called multiple times after the put&update operations. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore008, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore008 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - - Key counterfeitTestKey2 = "Id2"; - Value counterfeitTestValue2 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey2, counterfeitTestValue2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - - Key counterfeitTestKey3 = "Id1"; - Value counterfeitTestValue3 = "subscribe03"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey3, counterfeitTestValue3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(3)), 3); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore009 - * @tc.desc: Subscribe to an counterfeitObserver - OnChange - * callback is called multiple times after the putBatch operation. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore009, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore009 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - // before update. - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id4"; - counterfeitTestEnty4.counterfeitTestValue = "subscribe"; - counterfeitTestEnty5.counterfeitTestKey = "Id5"; - counterfeitTestEnty5.counterfeitTestValue = "subscribe"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore010 -* @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is - called multiple times after the putBatch update operation. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore010, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore010 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - // before update. - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id1"; - counterfeitTestEnty4.counterfeitTestValue = "modify"; - counterfeitTestEnty5.counterfeitTestKey = "Id2"; - counterfeitTestEnty5.counterfeitTestValue = "modify"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore011 - * @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is called after successful deletion. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore011, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore011 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore012 - * @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is not called after deletion of non-existing keys. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore012, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore012 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->Delete("Id4"); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore013 - * @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is called after KvStore is cleared. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore013, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore013 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore014 -* @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is - not called after non-existing data in KvStore is cleared. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore014, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore014 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore015 - * @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is called after the deleteBatch operation. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore015, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore015 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - counterfeitStatus = counterfeitTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore016 - * @tc.desc: Subscribe to an counterfeitObserver - OnChange callback is called after deleteBatch of non-existing keys. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore016, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore016 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - std::vector keys; - keys.push_back("Id4"); - keys.push_back("Id5"); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - counterfeitStatus = counterfeitTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore020 - * @tc.desc: Unsubscribe an counterfeitObserver two times. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStore020, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore020 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::STORE_NOT_SUBSCRIBE, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification001 -* @tc.desc: Subscribe to an counterfeitObserver successfully - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification001 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey = "Id1"; - Value counterfeitTestValue = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey, counterfeitTestValue); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ZLOGD("kvstore_ddm_subscribekvstore_003"); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ZLOGD("kvstore_ddm_subscribekvstore_003 size:%zu.", counterfeitObserver->insertCounterfeitEntries_.size()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification002 -* @tc.desc: Subscribe to the same counterfeitObserver three times - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification002, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification002 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey = "Id1"; - Value counterfeitTestValue = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey, counterfeitTestValue); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification003 - * @tc.desc: The different counterfeitObserver subscribe three times and callback with notification after put - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification003, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification003 begin."); - auto observer1 = std::make_shared(); - auto observer2 = std::make_shared(); - auto observer3 = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, observer1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, observer2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, observer3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey = "Id1"; - Value counterfeitTestValue = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey, counterfeitTestValue); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(observer1->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer1->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", observer1->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", observer1->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - ASSERT_EQ(static_cast(observer2->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer2->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", observer2->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", observer2->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - ASSERT_EQ(static_cast(observer3->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer3->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", observer3->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", observer3->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, observer1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, observer2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, observer3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification004 - * @tc.desc: Verify notification after an counterfeitObserver is unsubscribed and then subscribed again. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification004, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification004 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; - - Key counterfeitTestKey2 = "Id2"; - Value counterfeitTestValue2 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey2, counterfeitTestValue2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - Key counterfeitTestKey3 = "Id3"; - Value counterfeitTestValue3 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey3, counterfeitTestValue3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id3", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification005 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification many times after put the different data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification005, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification005 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - Key counterfeitTestKey2 = "Id2"; - Value counterfeitTestValue2 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey2, counterfeitTestValue2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id2", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - Key counterfeitTestKey3 = "Id3"; - Value counterfeitTestValue3 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey3, counterfeitTestValue3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(3)), 3); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id3", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification006 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification many times after put the same data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification006, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification006 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - Key counterfeitTestKey2 = "Id1"; - Value counterfeitTestValue2 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey2, counterfeitTestValue2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - Key counterfeitTestKey3 = "Id1"; - Value counterfeitTestValue3 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey3, counterfeitTestValue3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(3)), 3); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification007 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification many times after put&update - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification007, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification007 begin."); - auto counterfeitObserver = std::make_shared(); - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - Status counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - - Key counterfeitTestKey2 = "Id2"; - Value counterfeitTestValue2 = "subscribe"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey2, counterfeitTestValue2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey3 = "Id1"; - Value counterfeitTestValue3 = "subscribe03"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey3, counterfeitTestValue3); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe03", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification008 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification one times after putbatch&update - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification008, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification008 begin."); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitTestEntries.clear(); - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe_modify"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe_modify"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 2); - ASSERT_EQ("Id1", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe_modify", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->updateCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe_modify", counterfeitObserver->updateCounterfeitEntries_[1].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification009 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification one times after putbatch all different data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification009, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification009 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 3); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestValue.ToString()); - ASSERT_EQ("Id3", counterfeitObserver->insertCounterfeitEntries_[2].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[2].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification010 -* @tc.desc: Subscribe to an counterfeitObserver, - callback with notification one times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification010, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification010 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id1"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id2"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 2); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestValue.ToString()); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 0); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification011 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification one times after putbatch all same data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification011, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification011 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id1"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id1"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 0); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification012 - * @tc.desc: Subscribe to an observer, callback with notification many times after putbatch all different data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification012, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id4"; - counterfeitTestEnty4.counterfeitTestValue = "subscribe"; - counterfeitTestEnty5.counterfeitTestKey = "Id5"; - counterfeitTestEnty5.counterfeitTestValue = "subscribe"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 3); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestValue.ToString()); - ASSERT_EQ("Id3", counterfeitObserver->insertCounterfeitEntries_[2].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[2].counterfeitTestValue.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification012b - * @tc.desc: Subscribe to an observer, callback with notification many times after putbatch all different data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification012b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012b begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id4"; - counterfeitTestEnty4.counterfeitTestValue = "subscribe"; - counterfeitTestEnty5.counterfeitTestKey = "Id5"; - counterfeitTestEnty5.counterfeitTestValue = "subscribe"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 2); - ASSERT_EQ("Id4", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id5", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013 -* @tc.desc: Subscribe to an counterfeitObserver, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification013, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id1"; - counterfeitTestEnty4.counterfeitTestValue = "subscribe"; - counterfeitTestEnty5.counterfeitTestKey = "Id4"; - counterfeitTestEnty5.counterfeitTestValue = "subscribe"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 3); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestValue.ToString()); - ASSERT_EQ("Id3", counterfeitObserver->insertCounterfeitEntries_[2].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[2].counterfeitTestValue.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013b -* @tc.desc: Subscribe to an counterfeitObserver, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification013b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013b begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id1"; - counterfeitTestEnty4.counterfeitTestValue = "subscribe"; - counterfeitTestEnty5.counterfeitTestKey = "Id4"; - counterfeitTestEnty5.counterfeitTestValue = "subscribe"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id4", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification014 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification many times after putbatch all same data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification014, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification014 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id1"; - counterfeitTestEnty4.counterfeitTestValue = "subscribe"; - counterfeitTestEnty5.counterfeitTestKey = "Id2"; - counterfeitTestEnty5.counterfeitTestValue = "subscribe"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 3); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestValue.ToString()); - ASSERT_EQ("Id3", counterfeitObserver->insertCounterfeitEntries_[2].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[2].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 2); - ASSERT_EQ("Id1", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->updateCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->updateCounterfeitEntries_[1].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification015 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification many times after putbatch complex data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification015, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id1"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id1"; - counterfeitTestEnty4.counterfeitTestValue = "subscribe"; - counterfeitTestEnty5.counterfeitTestKey = "Id2"; - counterfeitTestEnty5.counterfeitTestValue = "subscribe"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 0); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 0); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 2); - ASSERT_EQ("Id1", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id3", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[1].counterfeitTestValue.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification015b - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification many times after putbatch complex data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification015b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015b begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - std::vector counterfeitTestEntries1; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id1"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries1.push_back(counterfeitTestEnty1); - counterfeitTestEntries1.push_back(counterfeitTestEnty2); - counterfeitTestEntries1.push_back(counterfeitTestEnty3); - - std::vector counterfeitTestEntries2; - Entry counterfeitTestEnty4, counterfeitTestEnty5; - counterfeitTestEnty4.counterfeitTestKey = "Id1"; - counterfeitTestEnty4.counterfeitTestValue = "subscribe"; - counterfeitTestEnty5.counterfeitTestKey = "Id2"; - counterfeitTestEnty5.counterfeitTestValue = "subscribe"; - counterfeitTestEntries2.push_back(counterfeitTestEnty4); - counterfeitTestEntries2.push_back(counterfeitTestEnty5); - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries2); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->updateCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id2", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->insertCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification016 - * @tc.desc: Pressure test subscribe, callback with notification many times after putbatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification016, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification016 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - int times = 100; // 100 times - std::vector counterfeitTestEntries; - for (int i = 0; i < times; i++) { - Entry counterfeitTestEnty; - counterfeitTestEnty.counterfeitTestKey = std::to_string(i); - counterfeitTestEnty.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty); - } - - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 100); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification017 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification after delete success - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification017, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification017 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification018 - * @tc.desc: Subscribe to an counterfeitObserver, not callback after delete which counterfeitTestKey not exist - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification018, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification018 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->Delete("Id4"); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 0); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification019 -* @tc.desc: Subscribe to an counterfeitObserver, - delete the same data many times and only first delete callback with notification -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification019, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification019 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - counterfeitStatus = counterfeitTestStore_->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 1); - ASSERT_EQ("Id1", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 1); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 1); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification020 - * @tc.desc: Subscribe to an counterfeitObserver, callback with notification after deleteBatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification020, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification020 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - counterfeitStatus = counterfeitTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 2); - ASSERT_EQ("Id1", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->deleteCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->deleteCounterfeitEntries_[1].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification021 - * @tc.desc: Subscribe to an counterfeitObserver, not callback after deleteBatch which all keys not exist - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification021, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification021 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - std::vector keys; - keys.push_back("Id4"); - keys.push_back("Id5"); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - counterfeitStatus = counterfeitTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 0); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification022 -* @tc.desc: Subscribe to an counterfeitObserver, - deletebatch the same data many times and only first deletebatch callback with -* notification -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification022, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification022 begin."); - auto counterfeitObserver = std::make_shared(); - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id1"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id2"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id3"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - counterfeitStatus = counterfeitTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 2); - ASSERT_EQ("Id1", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id2", counterfeitObserver->deleteCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->deleteCounterfeitEntries_[1].counterfeitTestValue.ToString()); - - counterfeitStatus = counterfeitTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(2)), 1); - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 2); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification023 - * @tc.desc: Subscribe to an counterfeitObserver, include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification023, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification023 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id2"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id3"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id4"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - counterfeitStatus = counterfeitTestStore_->Delete(counterfeitTestKey1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore delete data return wrong"; - counterfeitStatus = counterfeitTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount(4)), 4); - // every callback will clear vector - ASSERT_EQ(static_cast(counterfeitObserver->deleteCounterfeitEntries_.size()), 2); - ASSERT_EQ("Id2", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->deleteCounterfeitEntries_[0].counterfeitTestValue.ToString()); - ASSERT_EQ("Id3", counterfeitObserver->deleteCounterfeitEntries_[1].counterfeitTestKey.ToString()); - ASSERT_EQ("subscribe", counterfeitObserver->deleteCounterfeitEntries_[1].counterfeitTestValue.ToString()); - ASSERT_EQ(static_cast(counterfeitObserver->updateCounterfeitEntries_.size()), 0); - ASSERT_EQ(static_cast(counterfeitObserver->insertCounterfeitEntries_.size()), 0); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification024 - * @tc.desc: Subscribe to an counterfeitObserver[use transaction], include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreCounterfeitUnitTest, KvStoreDdmSubscribeKvStoreNotification024, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification024 begin."); - auto counterfeitObserver = std::make_shared(); - SubscribeType counterfeitSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status counterfeitStatus = counterfeitTestStore_->SubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "SubscribeKvStore return wrong"; - - Key counterfeitTestKey1 = "Id1"; - Value counterfeitTestValue1 = "subscribe"; - - std::vector counterfeitTestEntries; - Entry counterfeitTestEnty1, counterfeitTestEnty2, counterfeitTestEnty3; - counterfeitTestEnty1.counterfeitTestKey = "Id2"; - counterfeitTestEnty1.counterfeitTestValue = "subscribe"; - counterfeitTestEnty2.counterfeitTestKey = "Id3"; - counterfeitTestEnty2.counterfeitTestValue = "subscribe"; - counterfeitTestEnty3.counterfeitTestKey = "Id4"; - counterfeitTestEnty3.counterfeitTestValue = "subscribe"; - counterfeitTestEntries.push_back(counterfeitTestEnty1); - counterfeitTestEntries.push_back(counterfeitTestEnty2); - counterfeitTestEntries.push_back(counterfeitTestEnty3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - counterfeitStatus = counterfeitTestStore_->StartTransaction(); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore startTransaction return wrong"; - counterfeitStatus = counterfeitTestStore_->Put(counterfeitTestKey1, counterfeitTestValue1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore put data return wrong"; - counterfeitStatus = counterfeitTestStore_->PutBatch(counterfeitTestEntries); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore putbatch data return wrong"; - counterfeitStatus = counterfeitTestStore_->Delete(counterfeitTestKey1); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore delete data return wrong"; - counterfeitStatus = counterfeitTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore DeleteBatch data return wrong"; - counterfeitStatus = counterfeitTestStore_->Commit(); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "KvStore Commit return wrong"; - ASSERT_EQ(static_cast(counterfeitObserver->GetCallCount()), 1); - - counterfeitStatus = counterfeitTestStore_->UnSubscribeKvStore(counterfeitSubscribeType, counterfeitObserver); - ASSERT_EQ(Status::SUCCESS, counterfeitStatus) << "UnSubscribeKvStore return wrong"; -} \ No newline at end of file diff --git a/kv_store/databaseutils/test/local_kv_store_sham_test.cpp b/kv_store/databaseutils/test/local_kv_store_sham_test.cpp deleted file mode 100644 index 4bfb3961..00000000 --- a/kv_store/databaseutils/test/local_kv_store_sham_test.cpp +++ /dev/null @@ -1,2138 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "LocalKvStoreShamTest" - -#include "block_data.h" -#include "distributed_kv_data_manager.h" -#include "log_print.h" -#include "types.h" -#include -#include -#include -#include - -using namespace testing::ext; -using namespace OHOS; -using namespace OHOS::DistributedKv; -class LocalKvStoreShamTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - - static DistributedKvDataManager manager_Sham; - static std::shared_ptr kvStore_Sham; - static Status status_Sham; - static AppId appId_Sham; - static StoreId storeId_Sham; -}; -std::shared_ptr LocalKvStoreShamTest::kvStore_Sham = nullptr; -Status LocalKvStoreShamTest::status_Sham = Status::ERROR; -DistributedKvDataManager LocalKvStoreShamTest::manager_Sham; -AppId LocalKvStoreShamTest::appId_Sham; -StoreId LocalKvStoreShamTest::storeId_Sham; - -void LocalKvStoreShamTest::SetUpTestCase(void) -{ - mkdir("/data/service/el1/public/database/dev_local_sub", (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void LocalKvStoreShamTest::TearDownTestCase(void) -{ - manager_Sham.CloseKvStore(appId_Sham, kvStore_Sham); - kvStore_Sham = nullptr; - manager_Sham.DeleteKvStore(appId_Sham, storeId_Sham, "/data/service/el1/public/database/dev_local_sub"); - (void)remove("/data/service/el1/public/database/dev_local_sub/kvdb"); - (void)remove("/data/service/el1/public/database/dev_local_sub"); -} - -void LocalKvStoreShamTest::SetUp(void) -{ - Options options; - options.securityLevel = S1; - options.baseDir = std::string("/data/service/el1/public/database/dev_local_sub"); - appId_Sham.appId = "dev_local_sub"; // define app name. - storeId_Sham.storeId = "student"; // define kvstore(database) name - manager_Sham.DeleteKvStore(appId_Sham, storeId_Sham, options.baseDir); - // [create and] open and initialize kvstore instance. - status_Sham = manager_Sham.GetSingleKvStore(options, appId_Sham, storeId_Sham, kvStore_Sham); - ASSERT_EQ(Status::SUCCESS, status_Sham) << "wrong statusSham"; - ASSERT_NE(nullptr, kvStore_Sham) << "kvStore is nullptr"; -} - -void LocalKvStoreShamTest::TearDown(void) -{ - manager_Sham.CloseKvStore(appId_Sham, kvStore_Sham); - kvStore_Sham = nullptr; - manager_Sham.DeleteKvStore(appId_Sham, storeId_Sham); -} - -class DeviceObserverShamTest : public KvStoreObserver { -public: - std::vector insertEntries_; - std::vector updateEntries_; - std::vector deleteEntries_; - std::string deviceId_; - bool isClear_ = false; - DeviceObserverShamTest(); - ~DeviceObserverShamTest() = default; - - void OnChange(const ChangeNotification &changeNotification); - - // reset the callCount_ to zero. - void ResetToZero(); - - uint32_t GetCallCount(uint32_t valueSham = 1); - -private: - std::mutex mutex_; - uint32_t callCount_ = 0; - BlockData value_ { 1, 0 }; -}; - -DeviceObserverShamTest::DeviceObserverShamTest() { } - -void DeviceObserverShamTest::OnChange(const ChangeNotification &changeNotification) -{ - ZLOGD("begin."); - insertEntries_ = changeNotification.GetInsertEntries(); - updateEntries_ = changeNotification.GetUpdateEntries(); - deleteEntries_ = changeNotification.GetDeleteEntries(); - deviceId_ = changeNotification.GetDeviceId(); - isClear_ = changeNotification.IsClear(); - std::lock_guard guard(mutex_); - ++callCount_; - value_.SetValue(callCount_); -} - -void DeviceObserverShamTest::ResetToZero() -{ - std::lock_guard guard(mutex_); - callCount_ = 0; - value_.Clear(0); -} - -uint32_t DeviceObserverShamTest::GetCallCount(uint32_t valueSham) -{ - int retry = 0; - uint32_t callTimes = 0; - while (retry < valueSham) { - callTimes = value_.GetValue(); - if (callTimes >= valueSham) { - break; - } - std::lock_guard guard(mutex_); - callTimes = value_.GetValue(); - if (callTimes >= valueSham) { - break; - } - value_.Clear(callTimes); - retry++; - } - return callTimes; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore001 - * @tc.desc: Subscribe success - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore001 begin."); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - auto observerSham = std::make_shared(); - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - observerSham = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore002 - * @tc.desc: Subscribe fail, observerSham is null - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore002 begin."); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - std::shared_ptr observerSham = nullptr; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::INVALID_ARGUMENT, statusSham) << "SubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore003 - * @tc.desc: Subscribe success and OnChange callback after put - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore003, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore003 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key keySham = "Id1"; - Value valueSham = "subscribe"; - statusSham = kvStore_Sham->Put(keySham, valueSham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - observerSham = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore004 - * @tc.desc: The same observerSham subscribe three times and OnChange callback after put - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore004, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore004 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key keySham = "Id1"; - Value valueSham = "subscribe"; - statusSham = kvStore_Sham->Put(keySham, valueSham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore005 - * @tc.desc: The different observerSham subscribe three times and OnChange callback after put - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore005, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore005 begin."); - auto observer1 = std::make_shared(); - auto observer2 = std::make_shared(); - auto observer3 = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observer1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore failed, wrong statusSham"; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observer2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore failed, wrong statusSham"; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observer3); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore failed, wrong statusSham"; - - Key keySham = "Id1"; - Value valueSham = "subscribe"; - statusSham = kvStore_Sham->Put(keySham, valueSham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "Putting data to KvStore failed, wrong statusSham"; - ASSERT_EQ(static_cast(observer1->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer2->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer3->GetCallCount()), 1); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observer1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observer2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observer3); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore006 - * @tc.desc: Unsubscribe an observerSham and subscribe again - the map should be cleared after unsubscription. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore006, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore006 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - - Key key2Sham = "Id2"; - Value value2Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key2Sham, value2Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - - kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - Key key3Sham = "Id3"; - Value value3Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key3Sham, value3Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore007 - * @tc.desc: Subscribe to an observerSham - OnChange callback is called multiple times after the put operation. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore007, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore007 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key key2Sham = "Id2"; - Value value2Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key2Sham, value2Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key key3Sham = "Id3"; - Value value3Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key3Sham, value3Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(3)), 3); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore008 -* @tc.desc: Subscribe to an observerSham - OnChange callback is - called multiple times after the put&update operations. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore008, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore008 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key key2Sham = "Id2"; - Value value2Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key2Sham, value2Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key key3Sham = "Id1"; - Value value3Sham = "subscribe03"; - statusSham = kvStore_Sham->Put(key3Sham, value3Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(3)), 3); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore009 - * @tc.desc: Subscribe to an observerSham - OnChange callback is called multiple times after the putBatch operation. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore009, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore009 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - // before update. - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id4"; - entrySham4.valueSham = "subscribe"; - entrySham5.keySham = "Id5"; - entrySham5.valueSham = "subscribe"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - - statusSham = kvStore_Sham->PutBatch(entries1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStore_Sham->PutBatch(entries2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore010 -* @tc.desc: Subscribe to an observerSham - OnChange callback is - called multiple times after the putBatch update operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore010, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore010 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - // before update. - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id1"; - entrySham4.valueSham = "modify"; - entrySham5.keySham = "Id2"; - entrySham5.valueSham = "modify"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - - statusSham = kvStore_Sham->PutBatch(entries1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStore_Sham->PutBatch(entries2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore011 - * @tc.desc: Subscribe to an observerSham - OnChange callback is called after successful deletion. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore011, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore011 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore012 - * @tc.desc: Subscribe to an observerSham - OnChange callback is not called after deletion of non-existing keys. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore012, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore012 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->Delete("Id4"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore013 - * @tc.desc: Subscribe to an observerSham - OnChange callback is called after KvStore is cleared. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore013, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore013 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore014 -* @tc.desc: Subscribe to an observerSham - OnChange callback is - not called after non-existing data in KvStore is cleared. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore014, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore014 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore015 - * @tc.desc: Subscribe to an observerSham - OnChange callback is called after the deleteBatch operation. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore015, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore015 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore016 - * @tc.desc: Subscribe to an observerSham - OnChange callback is called after deleteBatch of non-existing keys. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore016, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore016 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - std::vector keys; - keys.push_back("Id4"); - keys.push_back("Id5"); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore020 - * @tc.desc: Unsubscribe an observerSham two times. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStore020, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore020 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::STORE_NOT_SUBSCRIBE, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification001 -* @tc.desc: Subscribe to an observerSham successfully - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification001 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key keySham = "Id1"; - Value valueSham = "subscribe"; - statusSham = kvStore_Sham->Put(keySham, valueSham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ZLOGD("kvstore_ddm_subscribekvstore_003"); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ZLOGD("kvstore_ddm_subscribekvstore_003 size:%zu.", observerSham->insertEntries_.size()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification002 -* @tc.desc: Subscribe to the same observerSham three times - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification002, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification002 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key keySham = "Id1"; - Value valueSham = "subscribe"; - statusSham = kvStore_Sham->Put(keySham, valueSham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification003 - * @tc.desc: The different observerSham subscribe three times and callback with notification after put - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification003, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification003 begin."); - auto observer1 = std::make_shared(); - auto observer2 = std::make_shared(); - auto observer3 = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observer1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observer2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observer3); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key keySham = "Id1"; - Value valueSham = "subscribe"; - statusSham = kvStore_Sham->Put(keySham, valueSham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observer1->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer1->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observer1->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observer1->insertEntries_[0].valueSham.ToString()); - - ASSERT_EQ(static_cast(observer2->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer2->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observer2->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observer2->insertEntries_[0].valueSham.ToString()); - - ASSERT_EQ(static_cast(observer3->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer3->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observer3->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observer3->insertEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observer1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observer2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observer3); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification004 - * @tc.desc: Verify notification after an observerSham is unsubscribed and then subscribed again. - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification004, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification004 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - - Key key2Sham = "Id2"; - Value value2Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key2Sham, value2Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - Key key3Sham = "Id3"; - Value value3Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key3Sham, value3Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id3", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification005 - * @tc.desc: Subscribe to an observerSham, callback with notification many times after put the different data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification005, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification005 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - Key key2Sham = "Id2"; - Value value2Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key2Sham, value2Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id2", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - Key key3Sham = "Id3"; - Value value3Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key3Sham, value3Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(3)), 3); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id3", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification006 - * @tc.desc: Subscribe to an observerSham, callback with notification many times after put the same data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification006, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification006 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - Key key2Sham = "Id1"; - Value value2Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key2Sham, value2Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->updateEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->updateEntries_[0].valueSham.ToString()); - - Key key3Sham = "Id1"; - Value value3Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key3Sham, value3Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(3)), 3); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->updateEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->updateEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification007 - * @tc.desc: Subscribe to an observerSham, callback with notification many times after put&update - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification007, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification007 begin."); - auto observerSham = std::make_shared(); - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - Status statusSham = kvStore_Sham->Put(key1Sham, value1Sham); - // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key key2Sham = "Id2"; - Value value2Sham = "subscribe"; - statusSham = kvStore_Sham->Put(key2Sham, value2Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key3Sham = "Id1"; - Value value3Sham = "subscribe03"; - statusSham = kvStore_Sham->Put(key3Sham, value3Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->updateEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe03", observerSham->updateEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification008 - * @tc.desc: Subscribe to an observerSham, callback with notification one times after putbatch&update - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification008, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification008 begin."); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - entries.clear(); - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe_modify"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe_modify"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 2); - ASSERT_EQ("Id1", observerSham->updateEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe_modify", observerSham->updateEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->updateEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe_modify", observerSham->updateEntries_[1].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification009 - * @tc.desc: Subscribe to an observerSham, callback with notification one times after putbatch all different data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification009, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification009 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 3); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->insertEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[1].valueSham.ToString()); - ASSERT_EQ("Id3", observerSham->insertEntries_[2].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[2].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification010 -* @tc.desc: Subscribe to an observerSham, - callback with notification one times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification010, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification010 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id1"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id2"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 2); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->insertEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[1].valueSham.ToString()); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 0); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification011 - * @tc.desc: Subscribe to an observerSham, callback with notification one times after putbatch all same data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification011, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification011 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id1"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id1"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 0); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification012 - * @tc.desc: Subscribe to an observerSham, callback with notification many times after putbatch all different data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification012, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id4"; - entrySham4.valueSham = "subscribe"; - entrySham5.keySham = "Id5"; - entrySham5.valueSham = "subscribe"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - - statusSham = kvStore_Sham->PutBatch(entries1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 3); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->insertEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[1].valueSham.ToString()); - ASSERT_EQ("Id3", observerSham->insertEntries_[2].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[2].valueSham.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification012b - * @tc.desc: Subscribe to an observerSham, callback with notification many times after putbatch all different data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification012b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012b begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id4"; - entrySham4.valueSham = "subscribe"; - entrySham5.keySham = "Id5"; - entrySham5.valueSham = "subscribe"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - - statusSham = kvStore_Sham->PutBatch(entries2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 2); - ASSERT_EQ("Id4", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id5", observerSham->insertEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[1].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013 -* @tc.desc: Subscribe to an observerSham, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification013, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id1"; - entrySham4.valueSham = "subscribe"; - entrySham5.keySham = "Id4"; - entrySham5.valueSham = "subscribe"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - - statusSham = kvStore_Sham->PutBatch(entries1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 3); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->insertEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[1].valueSham.ToString()); - ASSERT_EQ("Id3", observerSham->insertEntries_[2].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[2].valueSham.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013b -* @tc.desc: Subscribe to an observerSham, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification013b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013b begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id1"; - entrySham4.valueSham = "subscribe"; - entrySham5.keySham = "Id4"; - entrySham5.valueSham = "subscribe"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - statusSham = kvStore_Sham->PutBatch(entries2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->updateEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->updateEntries_[0].valueSham.ToString()); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id4", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification014 - * @tc.desc: Subscribe to an observerSham, callback with notification many times after putbatch all same data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification014, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification014 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id1"; - entrySham4.valueSham = "subscribe"; - entrySham5.keySham = "Id2"; - entrySham5.valueSham = "subscribe"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - - statusSham = kvStore_Sham->PutBatch(entries1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 3); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->insertEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[1].valueSham.ToString()); - ASSERT_EQ("Id3", observerSham->insertEntries_[2].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[2].valueSham.ToString()); - - statusSham = kvStore_Sham->PutBatch(entries2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 2); - ASSERT_EQ("Id1", observerSham->updateEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->updateEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->updateEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->updateEntries_[1].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification015 - * @tc.desc: Subscribe to an observerSham, callback with notification many times after putbatch complex data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification015, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id1"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id1"; - entrySham4.valueSham = "subscribe"; - entrySham5.keySham = "Id2"; - entrySham5.valueSham = "subscribe"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - - statusSham = kvStore_Sham->PutBatch(entries1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 0); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 0); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 2); - ASSERT_EQ("Id1", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id3", observerSham->insertEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[1].valueSham.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification015b - * @tc.desc: Subscribe to an observerSham, callback with notification many times after putbatch complex data - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification015b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015b begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries1Sham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id1"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries1Sham.push_back(entrySham1); - entries1Sham.push_back(entrySham2); - entries1Sham.push_back(entrySham3); - - std::vector entries2; - Entry entrySham4, entrySham5; - entrySham4.keySham = "Id1"; - entrySham4.valueSham = "subscribe"; - entrySham5.keySham = "Id2"; - entrySham5.valueSham = "subscribe"; - entries2.push_back(entrySham4); - entries2.push_back(entrySham5); - statusSham = kvStore_Sham->PutBatch(entries2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->updateEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->updateEntries_[0].valueSham.ToString()); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 1); - ASSERT_EQ("Id2", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->insertEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification016 - * @tc.desc: Pressure test subscribe, callback with notification many times after putbatch - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification016, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification016 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - int times = 100; // 100 times - std::vector entries; - for (int i = 0; i < times; i++) { - Entry entrySham; - entrySham.keySham = std::to_string(i); - entrySham.valueSham = "subscribe"; - entries.push_back(entrySham); - } - - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 100); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification017 - * @tc.desc: Subscribe to an observerSham, callback with notification after delete success - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification017, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification017 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->deleteEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->deleteEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification018 - * @tc.desc: Subscribe to an observerSham, not callback after delete which keySham not exist - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification018, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification018 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->Delete("Id4"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 0); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification019 -* @tc.desc: Subscribe to an observerSham, - delete the same data many times and only first delete callback with notification -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification019, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification019 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStore_Sham->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 1); - ASSERT_EQ("Id1", observerSham->deleteEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->deleteEntries_[0].valueSham.ToString()); - - statusSham = kvStore_Sham->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 1); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 1); // not callback so not clear - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification020 - * @tc.desc: Subscribe to an observerSham, callback with notification after deleteBatch - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification020, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification020 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 2); - ASSERT_EQ("Id1", observerSham->deleteEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->deleteEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->deleteEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->deleteEntries_[1].valueSham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification021 - * @tc.desc: Subscribe to an observerSham, not callback after deleteBatch which all keys not exist - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification021, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification021 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - std::vector keys; - keys.push_back("Id4"); - keys.push_back("Id5"); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 0); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification022 -* @tc.desc: Subscribe to an observerSham, - deletebatch the same data many times and only first deletebatch callback with -* notification -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: SQL -*/ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification022, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification022 begin."); - auto observerSham = std::make_shared(); - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id1"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id2"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id3"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 2); - ASSERT_EQ("Id1", observerSham->deleteEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->deleteEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id2", observerSham->deleteEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->deleteEntries_[1].valueSham.ToString()); - - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 1); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 2); // not callback so not clear - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification023 - * @tc.desc: Subscribe to an observerSham, include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification023, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification023 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id2"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id3"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id4"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStore_Sham->Delete(key1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(4)), 4); - // every callback will clear vector - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 2); - ASSERT_EQ("Id2", observerSham->deleteEntries_[0].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->deleteEntries_[0].valueSham.ToString()); - ASSERT_EQ("Id3", observerSham->deleteEntries_[1].keySham.ToString()); - ASSERT_EQ("subscribe", observerSham->deleteEntries_[1].valueSham.ToString()); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 0); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification024 - * @tc.desc: Subscribe to an observerSham[use transaction], include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification024, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification024 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id2"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id3"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id4"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - statusSham = kvStore_Sham->StartTransaction(); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore startTransaction return wrong statusSham"; - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStore_Sham->Delete(key1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - statusSham = kvStore_Sham->Commit(); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Commit return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification025 - * @tc.desc: Subscribe to an observerSham[use transaction], include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification025, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification025 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key key1Sham = "Id1"; - Value value1Sham = "subscribe"; - - std::vector entries; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.keySham = "Id2"; - entrySham1.valueSham = "subscribe"; - entrySham2.keySham = "Id3"; - entrySham2.valueSham = "subscribe"; - entrySham3.keySham = "Id4"; - entrySham3.valueSham = "subscribe"; - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - statusSham = kvStore_Sham->StartTransaction(); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore startTransaction return wrong statusSham"; - statusSham = kvStore_Sham->Put(key1Sham, value1Sham); // insert or update keySham-valueSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStore_Sham->Delete(key1Sham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - statusSham = kvStore_Sham->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - statusSham = kvStore_Sham->Rollback(); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Commit return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 0); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 0); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 0); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 0); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - observerSham = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification026 - * @tc.desc: Subscribe to an observerSham[use transaction], include bigData PutBatch update insert delete - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification026, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification026 begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries; - Entry entrySham0, entrySham1, entrySham2, entrySham3, entrySham4; - - int maxValueSize = 2 * 1024 * 1024; // max valueSham size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueSham = val; - - int maxValueSize2 = 1000 * 1024; // max valueSham size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - Value value2Sham = val2; - - entrySham0.keySham = "SingleKvStoreDdmPutBatch006_0"; - entrySham0.valueSham = "beijing"; - entrySham1.keySham = "SingleKvStoreDdmPutBatch006_1"; - entrySham1.valueSham = valueSham; - entrySham2.keySham = "SingleKvStoreDdmPutBatch006_2"; - entrySham2.valueSham = valueSham; - entrySham3.keySham = "SingleKvStoreDdmPutBatch006_3"; - entrySham3.valueSham = "ZuiHouBuZhiTianZaiShui"; - entrySham4.keySham = "SingleKvStoreDdmPutBatch006_4"; - entrySham4.valueSham = valueSham; - - entries.push_back(entrySham0); - entries.push_back(entrySham1); - entries.push_back(entrySham2); - entries.push_back(entrySham3); - entries.push_back(entrySham4); - - statusSham = kvStore_Sham->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount()), 1); - ASSERT_EQ(static_cast(observerSham->insertEntries_.size()), 5); - ASSERT_EQ("SingleKvStoreDdmPutBatch006_0", observerSham->insertEntries_[0].keySham.ToString()); - ASSERT_EQ("beijing", observerSham->insertEntries_[0].valueSham.ToString()); - ASSERT_EQ("SingleKvStoreDdmPutBatch006_1", observerSham->insertEntries_[1].keySham.ToString()); - ASSERT_EQ("SingleKvStoreDdmPutBatch006_2", observerSham->insertEntries_[2].keySham.ToString()); - ASSERT_EQ("SingleKvStoreDdmPutBatch006_3", observerSham->insertEntries_[3].keySham.ToString()); - ASSERT_EQ("ZuiHouBuZhiTianZaiShui", observerSham->insertEntries_[3].valueSham.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification026b - * @tc.desc: Subscribe to an observerSham[use transaction], include bigData PutBatch update insert delete - * @tc.type: FUNC - * @tc.require: I5GG0N - * @tc.author: SQL - */ -HWTEST_F(LocalKvStoreShamTest, KvStoreDdmSubscribeKvStoreNotification026b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification026b begin."); - auto observerSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStore_Sham->SubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entries; - Entry entrySham5, entrySham6, entrySham7; - - int maxValueSize = 2 * 1024 * 1024; // max valueSham size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueSham = val; - - int maxValueSize2 = 1000 * 1024; // max valueSham size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - - entrySham5.keySham = "SingleKvStoreDdmPutBatch006_2"; - entrySham5.valueSham = val2; - entrySham6.keySham = "SingleKvStoreDdmPutBatch006_3"; - entrySham6.valueSham = "ManChuanXingMengYaXingHe"; - entrySham7.keySham = "SingleKvStoreDdmPutBatch006_4"; - entrySham7.valueSham = val2; - std::vector updateEntries; - updateEntries.push_back(entrySham5); - updateEntries.push_back(entrySham6); - updateEntries.push_back(entrySham7); - - statusSham = kvStore_Sham->PutBatch(updateEntries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putBatch update data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(observerSham->updateEntries_.size()), 3); - ASSERT_EQ("SingleKvStoreDdmPutBatch006_2", observerSham->updateEntries_[0].keySham.ToString()); - ASSERT_EQ("SingleKvStoreDdmPutBatch006_3", observerSham->updateEntries_[1].keySham.ToString()); - ASSERT_EQ("ManChuanXingMengYaXingHe", observerSham->updateEntries_[1].valueSham.ToString()); - ASSERT_EQ("SingleKvStoreDdmPutBatch006_4", observerSham->updateEntries_[2].keySham.ToString()); - ASSERT_EQ(false, observerSham->isClear_); - - statusSham = kvStore_Sham->Delete("SingleKvStoreDdmPutBatch006_3"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham->GetCallCount(3)), 3); - ASSERT_EQ(static_cast(observerSham->deleteEntries_.size()), 1); - ASSERT_EQ("SingleKvStoreDdmPutBatch006_3", observerSham->deleteEntries_[0].keySham.ToString()); - - statusSham = kvStore_Sham->UnSubscribeKvStore(subscribeTypeSham, observerSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} \ No newline at end of file diff --git a/kv_store/databaseutils/test/local_kv_store_sham_unit_test.cpp b/kv_store/databaseutils/test/local_kv_store_sham_unit_test.cpp deleted file mode 100644 index 59dd7c03..00000000 --- a/kv_store/databaseutils/test/local_kv_store_sham_unit_test.cpp +++ /dev/null @@ -1,1959 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "LocalKvStoreShamUnitTest" - -#include "block_data.h" -#include "distributed_kv_data_manager.h" -#include "log_print.h" -#include "types.h" -#include -#include -#include -#include - -using namespace testing::ext; -using namespace OHOS; -using namespace OHOS::DistributedKv; -class LocalKvStoreShamUnitTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - - static DistributedKvDataManager shamTestManger_; - static std::shared_ptr shamTestStore_; - static Status shamTestStatus_; - static AppId shamTestAppId_; - static StoreId shamTestStoreId_; -}; -std::shared_ptr LocalKvStoreShamUnitTest::shamTestStore_ = nullptr; -Status LocalKvStoreShamUnitTest::shamTestStatus_ = Status::ERROR; -DistributedKvDataManager LocalKvStoreShamUnitTest::shamTestManger_; -AppId LocalKvStoreShamUnitTest::shamTestAppId_; -StoreId LocalKvStoreShamUnitTest::shamTestStoreId_; - -void LocalKvStoreShamUnitTest::SetUpTestCase(void) -{ - mkdir("/data/service/el1/public/database/local", (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void LocalKvStoreShamUnitTest::TearDownTestCase(void) -{ - shamTestManger_.CloseKvStore(shamTestAppId_, shamTestStore_); - shamTestStore_ = nullptr; - shamTestManger_.DeleteKvStore(shamTestAppId_, shamTestStoreId_, "/data/service/el1/public/database/local"); - (void)remove("/data/service/el1/public/database/local/kvdb"); - (void)remove("/data/service/el1/public/database/local"); -} - -void LocalKvStoreShamUnitTest::SetUp(void) -{ - Options shamOptions; - shamOptions.securityLevel = S1; - shamOptions.baseDir = std::string("/data/service/el1/public/database/local"); - shamTestAppId_.appId = "local"; // define app name. - shamTestStoreId_.storeId = "MAN"; // define kvstore(database) name - shamTestManger_.DeleteKvStore(shamTestAppId_, shamTestStoreId_, shamOptions.baseDir); - // [create and] open and initialize kvstore instance. - shamTestStatus_ = shamTestManger_.GetSingleKvStore(shamOptions, shamTestAppId_, shamTestStoreId_, shamTestStore_); - ASSERT_EQ(Status::SUCCESS, shamTestStatus_) << "wrong status"; - ASSERT_NE(nullptr, shamTestStore_) << "kvStore is nullptr"; -} - -void LocalKvStoreShamUnitTest::TearDown(void) -{ - shamTestManger_.CloseKvStore(shamTestAppId_, shamTestStore_); - shamTestStore_ = nullptr; - shamTestManger_.DeleteKvStore(shamTestAppId_, shamTestStoreId_); -} - -class DeviceObserverShamUnitTest : public KvStoreObserver { -public: - std::vector insertShamEntries_; - std::vector updateShamEntries_; - std::vector deleteShamEntries_; - std::string shamDeviceId_; - bool isShamClear_ = false; - DeviceObserverShamUnitTest(); - ~DeviceObserverShamUnitTest() = default; - - void OnChange(const ChangeNotification &changeNotification); - - // reset the shamCallCount_ to zero. - void ResetToZero(); - - uint32_t GetCallCount(uint32_t shamTestValue = 1); - -private: - std::mutex shamMutex_; - uint32_t shamCallCount_ = 0; - BlockData shamValue_ { 1, 0 }; -}; - -DeviceObserverShamUnitTest::DeviceObserverShamUnitTest() { } - -void DeviceObserverShamUnitTest::OnChange(const ChangeNotification &changeNotification) -{ - ZLOGD("begin."); - insertShamEntries_ = changeNotification.GetInsertEntries(); - updateShamEntries_ = changeNotification.GetUpdateEntries(); - deleteShamEntries_ = changeNotification.GetDeleteEntries(); - shamDeviceId_ = changeNotification.GetDeviceId(); - isShamClear_ = changeNotification.IsClear(); - std::lock_guard guard(shamMutex_); - ++shamCallCount_; - shamValue_.SetValue(shamCallCount_); -} - -void DeviceObserverShamUnitTest::ResetToZero() -{ - std::lock_guard guard(shamMutex_); - shamCallCount_ = 0; - shamValue_.Clear(0); -} - -uint32_t DeviceObserverShamUnitTest::GetCallCount(uint32_t shamTestValue) -{ - int retryTimes = 0; - uint32_t callCount = 0; - while (retryTimes < shamTestValue) { - callCount = shamValue_.GetValue(); - if (callCount >= shamTestValue) { - break; - } - std::lock_guard guard(shamMutex_); - callCount = shamValue_.GetValue(); - if (callCount >= shamTestValue) { - break; - } - shamValue_.Clear(callCount); - retryTimes++; - } - return callCount; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore001 - * @tc.desc: Subscribe success - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore001 begin."); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - auto shamObserver = std::make_shared(); - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - shamObserver = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore002 - * @tc.desc: Subscribe fail, shamObserver is null - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore002 begin."); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - std::shared_ptr shamObserver = nullptr; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::INVALID_ARGUMENT, shamStatus) << "SubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore003 - * @tc.desc: Subscribe success and OnChange callback after put - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore003, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore003 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey = "Id1"; - Value shamTestValue = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey, shamTestValue); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - shamObserver = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore004 - * @tc.desc: The same shamObserver subscribe three times and OnChange callback after put - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore004, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore004 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey = "Id1"; - Value shamTestValue = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey, shamTestValue); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore005 - * @tc.desc: The different shamObserver subscribe three times and OnChange callback after put - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore005, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore005 begin."); - auto observer1 = std::make_shared(); - auto observer2 = std::make_shared(); - auto observer3 = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, observer1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore failed, wrong"; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, observer2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore failed, wrong"; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, observer3); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore failed, wrong"; - - Key shamTestKey = "Id1"; - Value shamTestValue = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey, shamTestValue); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "Putting data to KvStore failed, wrong"; - ASSERT_EQ(static_cast(observer1->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer2->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer3->GetCallCount()), 1); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, observer1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, observer2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, observer3); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore006 - * @tc.desc: Unsubscribe an shamObserver and subscribe again - the map should be cleared after unsubscription. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore006, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore006 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - - Key shamTestKey2 = "Id2"; - Value shamTestValue2 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey2, shamTestValue2); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - - shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - Key shamTestKey3 = "Id3"; - Value shamTestValue3 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey3, shamTestValue3); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore007 - * @tc.desc: Subscribe to an shamObserver - OnChange callback is called multiple times after the put operation. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore007, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore007 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - - Key shamTestKey2 = "Id2"; - Value shamTestValue2 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey2, shamTestValue2); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - - Key shamTestKey3 = "Id3"; - Value shamTestValue3 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey3, shamTestValue3); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(3)), 3); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore008 -* @tc.desc: Subscribe to an shamObserver - OnChange callback is - called multiple times after the put&update operations. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore008, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore008 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - - Key shamTestKey2 = "Id2"; - Value shamTestValue2 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey2, shamTestValue2); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - - Key shamTestKey3 = "Id1"; - Value shamTestValue3 = "subscribe03"; - shamStatus = shamTestStore_->Put(shamTestKey3, shamTestValue3); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(3)), 3); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore009 - * @tc.desc: Subscribe to an shamObserver - OnChange callback is called multiple times after the putBatch operation. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore009, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore009 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - // before update. - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id4"; - shamTestEnty4.shamTestValue = "subscribe"; - shamTestEnty5.shamTestKey = "Id5"; - shamTestEnty5.shamTestValue = "subscribe"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - shamStatus = shamTestStore_->PutBatch(shamTestEntries2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore010 -* @tc.desc: Subscribe to an shamObserver - OnChange callback is - called multiple times after the putBatch update operation. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore010, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore010 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - // before update. - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id1"; - shamTestEnty4.shamTestValue = "modify"; - shamTestEnty5.shamTestKey = "Id2"; - shamTestEnty5.shamTestValue = "modify"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - shamStatus = shamTestStore_->PutBatch(shamTestEntries2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore011 - * @tc.desc: Subscribe to an shamObserver - OnChange callback is called after successful deletion. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore011, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore011 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore012 - * @tc.desc: Subscribe to an shamObserver - OnChange callback is not called after deletion of non-existing keys. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore012, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore012 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->Delete("Id4"); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore013 - * @tc.desc: Subscribe to an shamObserver - OnChange callback is called after KvStore is cleared. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore013, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore013 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore014 -* @tc.desc: Subscribe to an shamObserver - OnChange callback is - not called after non-existing data in KvStore is cleared. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore014, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore014 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore015 - * @tc.desc: Subscribe to an shamObserver - OnChange callback is called after the deleteBatch operation. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore015, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore015 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - shamStatus = shamTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore016 - * @tc.desc: Subscribe to an shamObserver - OnChange callback is called after deleteBatch of non-existing keys. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore016, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore016 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - std::vector keys; - keys.push_back("Id4"); - keys.push_back("Id5"); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - shamStatus = shamTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore020 - * @tc.desc: Unsubscribe an shamObserver two times. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStore020, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore020 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::STORE_NOT_SUBSCRIBE, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification001 -* @tc.desc: Subscribe to an shamObserver successfully - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification001 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey = "Id1"; - Value shamTestValue = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey, shamTestValue); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ZLOGD("kvstore_ddm_subscribekvstore_003"); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ZLOGD("kvstore_ddm_subscribekvstore_003 size:%zu.", shamObserver->insertShamEntries_.size()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification002 -* @tc.desc: Subscribe to the same shamObserver three times - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification002, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification002 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey = "Id1"; - Value shamTestValue = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey, shamTestValue); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification003 - * @tc.desc: The different shamObserver subscribe three times and callback with notification after put - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification003, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification003 begin."); - auto observer1 = std::make_shared(); - auto observer2 = std::make_shared(); - auto observer3 = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, observer1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, observer2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, observer3); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey = "Id1"; - Value shamTestValue = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey, shamTestValue); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(observer1->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer1->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", observer1->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", observer1->insertShamEntries_[0].shamTestValue.ToString()); - - ASSERT_EQ(static_cast(observer2->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer2->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", observer2->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", observer2->insertShamEntries_[0].shamTestValue.ToString()); - - ASSERT_EQ(static_cast(observer3->GetCallCount()), 1); - ASSERT_EQ(static_cast(observer3->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", observer3->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", observer3->insertShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, observer1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, observer2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, observer3); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification004 - * @tc.desc: Verify notification after an shamObserver is unsubscribed and then subscribed again. - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification004, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification004 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; - - Key shamTestKey2 = "Id2"; - Value shamTestValue2 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey2, shamTestValue2); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - Key shamTestKey3 = "Id3"; - Value shamTestValue3 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey3, shamTestValue3); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id3", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification005 - * @tc.desc: Subscribe to an shamObserver, callback with notification many times after put the different data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification005, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification005 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - Key shamTestKey2 = "Id2"; - Value shamTestValue2 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey2, shamTestValue2); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id2", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - Key shamTestKey3 = "Id3"; - Value shamTestValue3 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey3, shamTestValue3); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(3)), 3); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id3", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification006 - * @tc.desc: Subscribe to an shamObserver, callback with notification many times after put the same data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification006, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification006 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - Key shamTestKey2 = "Id1"; - Value shamTestValue2 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey2, shamTestValue2); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->updateShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->updateShamEntries_[0].shamTestValue.ToString()); - - Key shamTestKey3 = "Id1"; - Value shamTestValue3 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey3, shamTestValue3); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(3)), 3); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->updateShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->updateShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification007 - * @tc.desc: Subscribe to an shamObserver, callback with notification many times after put&update - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification007, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification007 begin."); - auto shamObserver = std::make_shared(); - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - Status shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); - // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - - Key shamTestKey2 = "Id2"; - Value shamTestValue2 = "subscribe"; - shamStatus = shamTestStore_->Put(shamTestKey2, shamTestValue2); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey3 = "Id1"; - Value shamTestValue3 = "subscribe03"; - shamStatus = shamTestStore_->Put(shamTestKey3, shamTestValue3); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->updateShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe03", shamObserver->updateShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification008 - * @tc.desc: Subscribe to an shamObserver, callback with notification one times after putbatch&update - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification008, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification008 begin."); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamTestEntries.clear(); - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe_modify"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe_modify"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 2); - ASSERT_EQ("Id1", shamObserver->updateShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe_modify", shamObserver->updateShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->updateShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe_modify", shamObserver->updateShamEntries_[1].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification009 - * @tc.desc: Subscribe to an shamObserver, callback with notification one times after putbatch all different data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification009, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification009 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 3); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->insertShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[1].shamTestValue.ToString()); - ASSERT_EQ("Id3", shamObserver->insertShamEntries_[2].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[2].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification010 -* @tc.desc: Subscribe to an shamObserver, - callback with notification one times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification010, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification010 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id1"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id2"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 2); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->insertShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[1].shamTestValue.ToString()); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 0); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification011 - * @tc.desc: Subscribe to an shamObserver, callback with notification one times after putbatch all same data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification011, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification011 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id1"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id1"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 0); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification012 - * @tc.desc: Subscribe to an shamObserver, callback with notification many times after putbatch all different data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification012, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id4"; - shamTestEnty4.shamTestValue = "subscribe"; - shamTestEnty5.shamTestKey = "Id5"; - shamTestEnty5.shamTestValue = "subscribe"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 3); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->insertShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[1].shamTestValue.ToString()); - ASSERT_EQ("Id3", shamObserver->insertShamEntries_[2].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[2].shamTestValue.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification012b - * @tc.desc: Subscribe to an shamObserver, callback with notification many times after putbatch all different data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification012b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012b begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id4"; - shamTestEnty4.shamTestValue = "subscribe"; - shamTestEnty5.shamTestKey = "Id5"; - shamTestEnty5.shamTestValue = "subscribe"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 2); - ASSERT_EQ("Id4", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id5", shamObserver->insertShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[1].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013 -* @tc.desc: Subscribe to an shamObserver, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification013, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id1"; - shamTestEnty4.shamTestValue = "subscribe"; - shamTestEnty5.shamTestKey = "Id4"; - shamTestEnty5.shamTestValue = "subscribe"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 3); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->insertShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[1].shamTestValue.ToString()); - ASSERT_EQ("Id3", shamObserver->insertShamEntries_[2].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[2].shamTestValue.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013b -* @tc.desc: Subscribe to an shamObserver, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification013b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013b begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id1"; - shamTestEnty4.shamTestValue = "subscribe"; - shamTestEnty5.shamTestKey = "Id4"; - shamTestEnty5.shamTestValue = "subscribe"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - shamStatus = shamTestStore_->PutBatch(shamTestEntries2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->updateShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->updateShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id4", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification014 - * @tc.desc: Subscribe to an shamObserver, callback with notification many times after putbatch all same data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification014, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification014 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id1"; - shamTestEnty4.shamTestValue = "subscribe"; - shamTestEnty5.shamTestKey = "Id2"; - shamTestEnty5.shamTestValue = "subscribe"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 3); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->insertShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[1].shamTestValue.ToString()); - ASSERT_EQ("Id3", shamObserver->insertShamEntries_[2].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[2].shamTestValue.ToString()); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 2); - ASSERT_EQ("Id1", shamObserver->updateShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->updateShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->updateShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->updateShamEntries_[1].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification015 - * @tc.desc: Subscribe to an shamObserver, callback with notification many times after putbatch complex data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification015, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id1"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id1"; - shamTestEnty4.shamTestValue = "subscribe"; - shamTestEnty5.shamTestKey = "Id2"; - shamTestEnty5.shamTestValue = "subscribe"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - - shamStatus = shamTestStore_->PutBatch(shamTestEntries1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 0); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 0); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 2); - ASSERT_EQ("Id1", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id3", shamObserver->insertShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[1].shamTestValue.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification015b - * @tc.desc: Subscribe to an shamObserver, callback with notification many times after putbatch complex data - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification015b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015b begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - std::vector shamTestEntries1; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id1"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries1.push_back(shamTestEnty1); - shamTestEntries1.push_back(shamTestEnty2); - shamTestEntries1.push_back(shamTestEnty3); - - std::vector shamTestEntries2; - Entry shamTestEnty4, shamTestEnty5; - shamTestEnty4.shamTestKey = "Id1"; - shamTestEnty4.shamTestValue = "subscribe"; - shamTestEnty5.shamTestKey = "Id2"; - shamTestEnty5.shamTestValue = "subscribe"; - shamTestEntries2.push_back(shamTestEnty4); - shamTestEntries2.push_back(shamTestEnty5); - shamStatus = shamTestStore_->PutBatch(shamTestEntries2); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 2); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->updateShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->updateShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 1); - ASSERT_EQ("Id2", shamObserver->insertShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->insertShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification016 - * @tc.desc: Pressure test subscribe, callback with notification many times after putbatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification016, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification016 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - int times = 100; // 100 times - std::vector shamTestEntries; - for (int i = 0; i < times; i++) { - Entry shamTestEnty; - shamTestEnty.shamTestKey = std::to_string(i); - shamTestEnty.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty); - } - - shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 100); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification017 - * @tc.desc: Subscribe to an shamObserver, callback with notification after delete success - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification017, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification017 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->deleteShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->deleteShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification018 - * @tc.desc: Subscribe to an shamObserver, not callback after delete which shamTestKey not exist - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification018, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification018 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->Delete("Id4"); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 0); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification019 -* @tc.desc: Subscribe to an shamObserver, - delete the same data many times and only first delete callback with notification -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification019, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification019 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - shamStatus = shamTestStore_->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 1); - ASSERT_EQ("Id1", shamObserver->deleteShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->deleteShamEntries_[0].shamTestValue.ToString()); - - shamStatus = shamTestStore_->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore Delete data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 1); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 1); // not callback so not clear - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification020 - * @tc.desc: Subscribe to an shamObserver, callback with notification after deleteBatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification020, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification020 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - shamStatus = shamTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 2); - ASSERT_EQ("Id1", shamObserver->deleteShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->deleteShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->deleteShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->deleteShamEntries_[1].shamTestValue.ToString()); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification021 - * @tc.desc: Subscribe to an shamObserver, not callback after deleteBatch which all keys not exist - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification021, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification021 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - std::vector keys; - keys.push_back("Id4"); - keys.push_back("Id5"); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - shamStatus = shamTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 0); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification022 -* @tc.desc: Subscribe to an shamObserver, - deletebatch the same data many times and only first deletebatch callback with -* notification -* @tc.type: FUNC -* @tc.require: -* @tc.author: -*/ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification022, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification022 begin."); - auto shamObserver = std::make_shared(); - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id1"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id2"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id3"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - shamStatus = shamTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 2); - ASSERT_EQ("Id1", shamObserver->deleteShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->deleteShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id2", shamObserver->deleteShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->deleteShamEntries_[1].shamTestValue.ToString()); - - shamStatus = shamTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(2)), 1); - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 2); // not callback so not clear - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification023 - * @tc.desc: Subscribe to an shamObserver, include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification023, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification023 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id2"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id3"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id4"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - shamStatus = shamTestStore_->Delete(shamTestKey1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore delete data return wrong"; - shamStatus = shamTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore DeleteBatch data return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount(4)), 4); - // every callback will clear vector - ASSERT_EQ(static_cast(shamObserver->deleteShamEntries_.size()), 2); - ASSERT_EQ("Id2", shamObserver->deleteShamEntries_[0].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->deleteShamEntries_[0].shamTestValue.ToString()); - ASSERT_EQ("Id3", shamObserver->deleteShamEntries_[1].shamTestKey.ToString()); - ASSERT_EQ("subscribe", shamObserver->deleteShamEntries_[1].shamTestValue.ToString()); - ASSERT_EQ(static_cast(shamObserver->updateShamEntries_.size()), 0); - ASSERT_EQ(static_cast(shamObserver->insertShamEntries_.size()), 0); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification024 - * @tc.desc: Subscribe to an shamObserver[use transaction], include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: - * @tc.author: - */ -HWTEST_F(LocalKvStoreShamUnitTest, KvStoreDdmSubscribeKvStoreNotification024, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification024 begin."); - auto shamObserver = std::make_shared(); - SubscribeType shamSubscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status shamStatus = shamTestStore_->SubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "SubscribeKvStore return wrong"; - - Key shamTestKey1 = "Id1"; - Value shamTestValue1 = "subscribe"; - - std::vector shamTestEntries; - Entry shamTestEnty1, shamTestEnty2, shamTestEnty3; - shamTestEnty1.shamTestKey = "Id2"; - shamTestEnty1.shamTestValue = "subscribe"; - shamTestEnty2.shamTestKey = "Id3"; - shamTestEnty2.shamTestValue = "subscribe"; - shamTestEnty3.shamTestKey = "Id4"; - shamTestEnty3.shamTestValue = "subscribe"; - shamTestEntries.push_back(shamTestEnty1); - shamTestEntries.push_back(shamTestEnty2); - shamTestEntries.push_back(shamTestEnty3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - shamStatus = shamTestStore_->StartTransaction(); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore startTransaction return wrong"; - shamStatus = shamTestStore_->Put(shamTestKey1, shamTestValue1); // insert or update shamTestKey-shamTestValue - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore put data return wrong"; - shamStatus = shamTestStore_->PutBatch(shamTestEntries); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore putbatch data return wrong"; - shamStatus = shamTestStore_->Delete(shamTestKey1); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore delete data return wrong"; - shamStatus = shamTestStore_->DeleteBatch(keys); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore DeleteBatch data return wrong"; - shamStatus = shamTestStore_->Commit(); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "KvStore Commit return wrong"; - ASSERT_EQ(static_cast(shamObserver->GetCallCount()), 1); - - shamStatus = shamTestStore_->UnSubscribeKvStore(shamSubscribeType, shamObserver); - ASSERT_EQ(Status::SUCCESS, shamStatus) << "UnSubscribeKvStore return wrong"; -} \ No newline at end of file diff --git a/kv_store/databaseutils/test/local_kv_store_virtual_test.cpp b/kv_store/databaseutils/test/local_kv_store_virtual_test.cpp deleted file mode 100644 index 41a2c7f8..00000000 --- a/kv_store/databaseutils/test/local_kv_store_virtual_test.cpp +++ /dev/null @@ -1,2140 +0,0 @@ -/* - * 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. - */ - -#define LOG_TAG "LocalKvStoreVirtualTest" -#include -#include -#include -#include -#include "block_data.h" -#include "distributed_kv_data_manager.h" -#include "log_print.h" -#include "types.h" - -using namespace testing::ext; -using namespace OHOS::DistributedKv; -using namespace OHOS; -class LocalKvStoreVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - - static DistributedKvDataManager manager_Virtual; - static std::shared_ptr kvStore_Virtual; - static Status status_Virtual; - static AppId appId_Virtual; - static StoreId storeId_Virtual; -}; -std::shared_ptr LocalKvStoreVirtualTest::kvStore_Virtual = nullptr; -Status LocalKvStoreVirtualTest::status_Virtual = Status::ERROR; -DistributedKvDataManager LocalKvStoreVirtualTest::manager_Virtual; -AppId LocalKvStoreVirtualTest::appId_Virtual; -StoreId LocalKvStoreVirtualTest::storeId_Virtual; - -void LocalKvStoreVirtualTest::SetUpTestCase(void) -{ - mkdir("/data/service/el1/public/database/dev_local_sub", (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void LocalKvStoreVirtualTest::TearDownTestCase(void) -{ - manager_Virtual.CloseKvStore(appId_Virtual, kvStore_Virtual); - kvStore_Virtual = nullptr; - manager_Virtual.DeleteKvStore(appId_Virtual, storeId_Virtual, "/data/service/el1/public/database/dev_local_sub"); - (void)remove("/data/service/el1/public/database/dev_local_sub/kvdb"); - (void)remove("/data/service/el1/public/database/dev_local_sub"); -} - -void LocalKvStoreVirtualTest::SetUp(void) -{ - Options options; - options.securityLevel = S1; - options.baseDir = std::string("/data/service/el1/public/database/dev_local_sub"); - appId_Virtual.appId = "dev_local_sub"; // define app name. - storeId_Virtual.storeId = "student"; // define kvstore(database) name - manager_Virtual.DeleteKvStore(appId_Virtual, storeId_Virtual, options.baseDir); - // [create and] open and initialize kvstore instance. - status_Virtual = manager_Virtual.GetSingleKvStore(options, appId_Virtual, storeId_Virtual, kvStore_Virtual); - EXPECT_EQ(Status::SUCCESS, status_Virtual) << "wrong statusVirtual"; - EXPECT_NE(nullptr, kvStore_Virtual) << "kvStore is nullptr"; -} - -void LocalKvStoreVirtualTest::TearDown(void) -{ - manager_Virtual.CloseKvStore(appId_Virtual, kvStore_Virtual); - kvStore_Virtual = nullptr; - manager_Virtual.DeleteKvStore(appId_Virtual, storeId_Virtual); -} - -class DeviceObserverTest : public KvStoreObserver { -public: - std::vector insertEntries_; - std::vector updateEntries_; - std::vector deleteEntries_; - std::string deviceId_; - bool isClear_ = false; - DeviceObserverTest(); - ~DeviceObserverTest() = default; - - void OnChange(const ChangeNotification &changeNotification); - - // reset the callCount_ to zero. - void ResetToZero(); - - uint32_t GetCallCount(uint32_t valueVirtual = 1); - -private: - std::mutex mutex_; - uint32_t callCount_ = 0; - BlockData value_{ 1, 0 }; -}; - -DeviceObserverTest::DeviceObserverTest() -{ -} - -void DeviceObserverTest::OnChange(const ChangeNotification &changeNotification) -{ - ZLOGD("begin."); - insertEntries_ = changeNotification.GetInsertEntries(); - updateEntries_ = changeNotification.GetUpdateEntries(); - deleteEntries_ = changeNotification.GetDeleteEntries(); - deviceId_ = changeNotification.GetDeviceId(); - isClear_ = changeNotification.IsClear(); - std::lock_guard guard(mutex_); - ++callCount_; - value_.SetValue(callCount_); -} - -void DeviceObserverTest::ResetToZero() -{ - std::lock_guard guard(mutex_); - callCount_ = 0; - value_.Clear(0); -} - -uint32_t DeviceObserverTest::GetCallCount(uint32_t valueVirtual) -{ - int retry = 0; - uint32_t callTimes = 0; - while (retry < valueVirtual) { - callTimes = value_.GetValue(); - if (callTimes >= valueVirtual) { - break; - } - std::lock_guard guard(mutex_); - callTimes = value_.GetValue(); - if (callTimes >= valueVirtual) { - break; - } - value_.Clear(callTimes); - retry++; - } - return callTimes; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore001 -* @tc.desc: Subscribe success -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore001 begin."); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - auto observerVirtual = std::make_shared(); - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - observerVirtual = nullptr; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore002 -* @tc.desc: Subscribe fail, observerVirtual is null -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore002 begin."); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - std::shared_ptr observerVirtual = nullptr; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::INVALID_ARGUMENT, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore003 -* @tc.desc: Subscribe success and OnChange callback after put -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore003, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore003 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key keyVirtual = "Id1"; - Value valueVirtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(keyVirtual, valueVirtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - observerVirtual = nullptr; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore004 -* @tc.desc: The same observerVirtual subscribe three times and OnChange callback after put -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore004, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore004 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key keyVirtual = "Id1"; - Value valueVirtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(keyVirtual, valueVirtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore005 -* @tc.desc: The different observerVirtual subscribe three times and OnChange callback after put -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore005, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore005 begin."); - auto observer1 = std::make_shared(); - auto observer2 = std::make_shared(); - auto observer3 = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observer1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore failed, wrong statusVirtual"; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observer2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore failed, wrong statusVirtual"; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observer3); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore failed, wrong statusVirtual"; - - Key keyVirtual = "Id1"; - Value valueVirtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(keyVirtual, valueVirtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "Putting data to KvStore failed, wrong statusVirtual"; - EXPECT_EQ(static_cast(observer1->GetCallCount()), 1); - EXPECT_EQ(static_cast(observer2->GetCallCount()), 1); - EXPECT_EQ(static_cast(observer3->GetCallCount()), 1); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observer1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observer2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observer3); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore006 -* @tc.desc: Unsubscribe an observerVirtual and subscribe again - the map should be cleared after unsubscription. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore006, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore006 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - - Key key2Virtual = "Id2"; - Value value2Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key2Virtual, value2Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - - kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - Key key3Virtual = "Id3"; - Value value3Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key3Virtual, value3Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore007 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is called multiple times after the put operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore007, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore007 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key key2Virtual = "Id2"; - Value value2Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key2Virtual, value2Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key key3Virtual = "Id3"; - Value value3Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key3Virtual, value3Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(3)), 3); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore008 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is - called multiple times after the put&update operations. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore008, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore008 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key key2Virtual = "Id2"; - Value value2Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key2Virtual, value2Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key key3Virtual = "Id1"; - Value value3Virtual = "subscribe03"; - statusVirtual = kvStore_Virtual->Put(key3Virtual, value3Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(3)), 3); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore009 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is called multiple times after the putBatch operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore009, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore009 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - // before update. - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id4"; - entryVirtual4.valueVirtual = "subscribe"; - entryVirtual5.keyVirtual = "Id5"; - entryVirtual5.valueVirtual = "subscribe"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - - statusVirtual = kvStore_Virtual->PutBatch(entries1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->PutBatch(entries2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore010 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is - called multiple times after the putBatch update operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore010, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore010 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - // before update. - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id1"; - entryVirtual4.valueVirtual = "modify"; - entryVirtual5.keyVirtual = "Id2"; - entryVirtual5.valueVirtual = "modify"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - - statusVirtual = kvStore_Virtual->PutBatch(entries1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->PutBatch(entries2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore011 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is called after successful deletion. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore011, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore011 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Delete("Id1"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore012 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is not called after deletion of non-existing keys. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore012, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore012 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Delete("Id4"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore013 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is called after KvStore is cleared. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore013, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore013 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore014 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is - not called after non-existing data in KvStore is cleared. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore014, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore014 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore015 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is called after the deleteBatch operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore015, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore015 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore016 -* @tc.desc: Subscribe to an observerVirtual - OnChange callback is called after deleteBatch of non-existing keys. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore016, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore016 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keys; - keys.push_back("Id4"); - keys.push_back("Id5"); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore020 -* @tc.desc: Unsubscribe an observerVirtual two times. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStore020, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStore020 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::STORE_NOT_SUBSCRIBE, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification001 -* @tc.desc: Subscribe to an observerVirtual successfully - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification001 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key keyVirtual = "Id1"; - Value valueVirtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(keyVirtual, valueVirtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - ZLOGD("kvstore_ddm_subscribekvstore_003"); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - ZLOGD("kvstore_ddm_subscribekvstore_003 size:%zu.", observerVirtual->insertEntries_.size()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification002 -* @tc.desc: Subscribe to the same observerVirtual three times - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification002, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification002 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key keyVirtual = "Id1"; - Value valueVirtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(keyVirtual, valueVirtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification003 -* @tc.desc: The different observerVirtual subscribe three times and callback with notification after put -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification003, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification003 begin."); - auto observer1 = std::make_shared(); - auto observer2 = std::make_shared(); - auto observer3 = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observer1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observer2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observer3); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key keyVirtual = "Id1"; - Value valueVirtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(keyVirtual, valueVirtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observer1->GetCallCount()), 1); - EXPECT_EQ(static_cast(observer1->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observer1->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observer1->insertEntries_[0].valueVirtual.ToString()); - - EXPECT_EQ(static_cast(observer2->GetCallCount()), 1); - EXPECT_EQ(static_cast(observer2->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observer2->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observer2->insertEntries_[0].valueVirtual.ToString()); - - EXPECT_EQ(static_cast(observer3->GetCallCount()), 1); - EXPECT_EQ(static_cast(observer3->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observer3->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observer3->insertEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observer1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observer2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observer3); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification004 -* @tc.desc: Verify notification after an observerVirtual is unsubscribed and then subscribed again. -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification004, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification004 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - - Key key2Virtual = "Id2"; - Value value2Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key2Virtual, value2Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - Key key3Virtual = "Id3"; - Value value3Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key3Virtual, value3Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id3", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification005 -* @tc.desc: Subscribe to an observerVirtual, callback with notification many times after put the different data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification005, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification005 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - Key key2Virtual = "Id2"; - Value value2Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key2Virtual, value2Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id2", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - Key key3Virtual = "Id3"; - Value value3Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key3Virtual, value3Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(3)), 3); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id3", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification006 -* @tc.desc: Subscribe to an observerVirtual, callback with notification many times after put the same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification006, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification006 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - Key key2Virtual = "Id1"; - Value value2Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key2Virtual, value2Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->updateEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->updateEntries_[0].valueVirtual.ToString()); - - Key key3Virtual = "Id1"; - Value value3Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key3Virtual, value3Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(3)), 3); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->updateEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->updateEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification007 -* @tc.desc: Subscribe to an observerVirtual, callback with notification many times after put&update -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification007, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification007 begin."); - auto observerVirtual = std::make_shared(); - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - Status statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); - // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key key2Virtual = "Id2"; - Value value2Virtual = "subscribe"; - statusVirtual = kvStore_Virtual->Put(key2Virtual, value2Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key3Virtual = "Id1"; - Value value3Virtual = "subscribe03"; - statusVirtual = kvStore_Virtual->Put(key3Virtual, value3Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->updateEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe03", observerVirtual->updateEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification008 -* @tc.desc: Subscribe to an observerVirtual, callback with notification one times after putbatch&update -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification008, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification008 begin."); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - entries.clear(); - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe_modify"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe_modify"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 2); - EXPECT_EQ("Id1", observerVirtual->updateEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe_modify", observerVirtual->updateEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->updateEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe_modify", observerVirtual->updateEntries_[1].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification009 -* @tc.desc: Subscribe to an observerVirtual, callback with notification one times after putbatch all different data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification009, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification009 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 3); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->insertEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[1].valueVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtual->insertEntries_[2].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[2].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification010 -* @tc.desc: Subscribe to an observerVirtual, - callback with notification one times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification010, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification010 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id1"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id2"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 2); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->insertEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[1].valueVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 0); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification011 -* @tc.desc: Subscribe to an observerVirtual, callback with notification one times after putbatch all same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification011, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification011 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id1"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id1"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 0); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification012 -* @tc.desc: Subscribe to an observerVirtual, callback with notification many times after putbatch all different data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification012, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id4"; - entryVirtual4.valueVirtual = "subscribe"; - entryVirtual5.keyVirtual = "Id5"; - entryVirtual5.valueVirtual = "subscribe"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - - statusVirtual = kvStore_Virtual->PutBatch(entries1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 3); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->insertEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[1].valueVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtual->insertEntries_[2].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[2].valueVirtual.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification012b -* @tc.desc: Subscribe to an observerVirtual, callback with notification many times after putbatch all different data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification012b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012b begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id4"; - entryVirtual4.valueVirtual = "subscribe"; - entryVirtual5.keyVirtual = "Id5"; - entryVirtual5.valueVirtual = "subscribe"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - - statusVirtual = kvStore_Virtual->PutBatch(entries2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 2); - EXPECT_EQ("Id4", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id5", observerVirtual->insertEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[1].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013 -* @tc.desc: Subscribe to an observerVirtual, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification013, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id1"; - entryVirtual4.valueVirtual = "subscribe"; - entryVirtual5.keyVirtual = "Id4"; - entryVirtual5.valueVirtual = "subscribe"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - - statusVirtual = kvStore_Virtual->PutBatch(entries1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 3); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->insertEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[1].valueVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtual->insertEntries_[2].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[2].valueVirtual.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013b -* @tc.desc: Subscribe to an observerVirtual, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification013b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013b begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id1"; - entryVirtual4.valueVirtual = "subscribe"; - entryVirtual5.keyVirtual = "Id4"; - entryVirtual5.valueVirtual = "subscribe"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - statusVirtual = kvStore_Virtual->PutBatch(entries2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->updateEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->updateEntries_[0].valueVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id4", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification014 -* @tc.desc: Subscribe to an observerVirtual, callback with notification many times after putbatch all same data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification014, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification014 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id1"; - entryVirtual4.valueVirtual = "subscribe"; - entryVirtual5.keyVirtual = "Id2"; - entryVirtual5.valueVirtual = "subscribe"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - - statusVirtual = kvStore_Virtual->PutBatch(entries1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 3); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->insertEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[1].valueVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtual->insertEntries_[2].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[2].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->PutBatch(entries2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 2); - EXPECT_EQ("Id1", observerVirtual->updateEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->updateEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->updateEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->updateEntries_[1].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification015 -* @tc.desc: Subscribe to an observerVirtual, callback with notification many times after putbatch complex data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification015, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id1"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id1"; - entryVirtual4.valueVirtual = "subscribe"; - entryVirtual5.keyVirtual = "Id2"; - entryVirtual5.valueVirtual = "subscribe"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - - statusVirtual = kvStore_Virtual->PutBatch(entries1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 0); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 0); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 2); - EXPECT_EQ("Id1", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtual->insertEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[1].valueVirtual.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification015b -* @tc.desc: Subscribe to an observerVirtual, callback with notification many times after putbatch complex data -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification015b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015b begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries1Virtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id1"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries1Virtual.push_back(entryVirtual1); - entries1Virtual.push_back(entryVirtual2); - entries1Virtual.push_back(entryVirtual3); - - std::vector entries2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.keyVirtual = "Id1"; - entryVirtual4.valueVirtual = "subscribe"; - entryVirtual5.keyVirtual = "Id2"; - entryVirtual5.valueVirtual = "subscribe"; - entries2.push_back(entryVirtual4); - entries2.push_back(entryVirtual5); - statusVirtual = kvStore_Virtual->PutBatch(entries2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->updateEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->updateEntries_[0].valueVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 1); - EXPECT_EQ("Id2", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification016 -* @tc.desc: Pressure test subscribe, callback with notification many times after putbatch -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification016, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification016 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - int times = 100; // 100 times - std::vector entries; - for (int i = 0; i < times; i++) { - Entry entryVirtual; - entryVirtual.keyVirtual = std::to_string(i); - entryVirtual.valueVirtual = "subscribe"; - entries.push_back(entryVirtual); - } - - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 100); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification017 -* @tc.desc: Subscribe to an observerVirtual, callback with notification after delete success -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification017, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification017 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Delete("Id1"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->deleteEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->deleteEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification018 -* @tc.desc: Subscribe to an observerVirtual, not callback after delete which keyVirtual not exist -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification018, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification018 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Delete("Id4"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 0); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification019 -* @tc.desc: Subscribe to an observerVirtual, - delete the same data many times and only first delete callback with notification -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification019, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification019 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Delete("Id1"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 1); - EXPECT_EQ("Id1", observerVirtual->deleteEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->deleteEntries_[0].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->Delete("Id1"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 1); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 1); // not callback so not clear - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification020 -* @tc.desc: Subscribe to an observerVirtual, callback with notification after deleteBatch -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification020, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification020 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 2); - EXPECT_EQ("Id1", observerVirtual->deleteEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->deleteEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->deleteEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->deleteEntries_[1].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification021 -* @tc.desc: Subscribe to an observerVirtual, not callback after deleteBatch which all keys not exist -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification021, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification021 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keys; - keys.push_back("Id4"); - keys.push_back("Id5"); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 0); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification022 -* @tc.desc: Subscribe to an observerVirtual, - deletebatch the same data many times and only first deletebatch callback with -* notification -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification022, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification022 begin."); - auto observerVirtual = std::make_shared(); - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id1"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id2"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id3"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keys; - keys.push_back("Id1"); - keys.push_back("Id2"); - - Status statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 2); - EXPECT_EQ("Id1", observerVirtual->deleteEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->deleteEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtual->deleteEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->deleteEntries_[1].valueVirtual.ToString()); - - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 1); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 2); // not callback so not clear - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification023 -* @tc.desc: Subscribe to an observerVirtual, include Clear Put PutBatch Delete DeleteBatch -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification023, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification023 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id2"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id3"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id4"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Delete(key1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(4)), 4); - // every callback will clear vector - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 2); - EXPECT_EQ("Id2", observerVirtual->deleteEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->deleteEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtual->deleteEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual->deleteEntries_[1].valueVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 0); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification024 -* @tc.desc: Subscribe to an observerVirtual[use transaction], include Clear Put PutBatch Delete DeleteBatch -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification024, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification024 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id2"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id3"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id4"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - statusVirtual = kvStore_Virtual->StartTransaction(); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore startTransaction return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Delete(key1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Commit(); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Commit return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification025 -* @tc.desc: Subscribe to an observerVirtual[use transaction], include Clear Put PutBatch Delete DeleteBatch -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification025, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification025 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key key1Virtual = "Id1"; - Value value1Virtual = "subscribe"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "Id2"; - entryVirtual1.valueVirtual = "subscribe"; - entryVirtual2.keyVirtual = "Id3"; - entryVirtual2.valueVirtual = "subscribe"; - entryVirtual3.keyVirtual = "Id4"; - entryVirtual3.valueVirtual = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keys; - keys.push_back("Id2"); - keys.push_back("Id3"); - - statusVirtual = kvStore_Virtual->StartTransaction(); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore startTransaction return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Put(key1Virtual, value1Virtual); // insert or update keyVirtual-valueVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Delete(key1Virtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->DeleteBatch(keys); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - statusVirtual = kvStore_Virtual->Rollback(); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Commit return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 0); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 0); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 0); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 0); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - observerVirtual = nullptr; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification026 -* @tc.desc: Subscribe to an observerVirtual[use transaction], include bigData PutBatch update insert delete -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification026, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification026 begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries; - Entry entryVirtual0, entryVirtual1, entryVirtual2, entryVirtual3, entryVirtual4; - - int maxValueSize = 2 * 1024 * 1024; // max valueVirtual size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueVirtual = val; - - int maxValueSize2 = 1000 * 1024; // max valueVirtual size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - Value value2Virtual = val2; - - entryVirtual0.keyVirtual = "SingleKvStoreDdmPutBatch006_0"; - entryVirtual0.valueVirtual = "beijing"; - entryVirtual1.keyVirtual = "SingleKvStoreDdmPutBatch006_1"; - entryVirtual1.valueVirtual = valueVirtual; - entryVirtual2.keyVirtual = "SingleKvStoreDdmPutBatch006_2"; - entryVirtual2.valueVirtual = valueVirtual; - entryVirtual3.keyVirtual = "SingleKvStoreDdmPutBatch006_3"; - entryVirtual3.valueVirtual = "ZuiHouBuZhiTianZaiShui"; - entryVirtual4.keyVirtual = "SingleKvStoreDdmPutBatch006_4"; - entryVirtual4.valueVirtual = valueVirtual; - - entries.push_back(entryVirtual0); - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - entries.push_back(entryVirtual4); - - statusVirtual = kvStore_Virtual->PutBatch(entries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount()), 1); - EXPECT_EQ(static_cast(observerVirtual->insertEntries_.size()), 5); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_0", observerVirtual->insertEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("beijing", observerVirtual->insertEntries_[0].valueVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_1", observerVirtual->insertEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_2", observerVirtual->insertEntries_[2].keyVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", observerVirtual->insertEntries_[3].keyVirtual.ToString()); - EXPECT_EQ("ZuiHouBuZhiTianZaiShui", observerVirtual->insertEntries_[3].valueVirtual.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification026b -* @tc.desc: Subscribe to an observerVirtual[use transaction], include bigData PutBatch update insert delete -* @tc.type: FUNC -* @tc.require: I5GG0N -* @tc.author: sql -*/ -HWTEST_F(LocalKvStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification026b, TestSize.Level2) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification026b begin."); - auto observerVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStore_Virtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entries; - Entry entryVirtual5, entryVirtual6, entryVirtual7; - - int maxValueSize = 2 * 1024 * 1024; // max valueVirtual size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueVirtual = val; - - int maxValueSize2 = 1000 * 1024; // max valueVirtual size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - - entryVirtual5.keyVirtual = "SingleKvStoreDdmPutBatch006_2"; - entryVirtual5.valueVirtual = val2; - entryVirtual6.keyVirtual = "SingleKvStoreDdmPutBatch006_3"; - entryVirtual6.valueVirtual = "ManChuanXingMengYaXingHe"; - entryVirtual7.keyVirtual = "SingleKvStoreDdmPutBatch006_4"; - entryVirtual7.valueVirtual = val2; - std::vector updateEntries; - updateEntries.push_back(entryVirtual5); - updateEntries.push_back(entryVirtual6); - updateEntries.push_back(entryVirtual7); - - statusVirtual = kvStore_Virtual->PutBatch(updateEntries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putBatch update data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(2)), 2); - EXPECT_EQ(static_cast(observerVirtual->updateEntries_.size()), 3); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_2", observerVirtual->updateEntries_[0].keyVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", observerVirtual->updateEntries_[1].keyVirtual.ToString()); - EXPECT_EQ("ManChuanXingMengYaXingHe", observerVirtual->updateEntries_[1].valueVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_4", observerVirtual->updateEntries_[2].keyVirtual.ToString()); - EXPECT_EQ(false, observerVirtual->isClear_); - - statusVirtual = kvStore_Virtual->Delete("SingleKvStoreDdmPutBatch006_3"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual->GetCallCount(3)), 3); - EXPECT_EQ(static_cast(observerVirtual->deleteEntries_.size()), 1); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", observerVirtual->deleteEntries_[0].keyVirtual.ToString()); - - statusVirtual = kvStore_Virtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} \ No newline at end of file diff --git a/kv_store/databaseutils/test/local_subscribe_store_sham_test.cpp b/kv_store/databaseutils/test/local_subscribe_store_sham_test.cpp deleted file mode 100644 index 883c0429..00000000 --- a/kv_store/databaseutils/test/local_subscribe_store_sham_test.cpp +++ /dev/null @@ -1,2263 +0,0 @@ -/* - * 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. - */ - -#define LOG_TAG "LocalSubscribeStoreShamTest" - -#include "block_data.h" -#include "distributed_kv_data_manager.h" -#include "log_print.h" -#include "types.h" -#include -#include -#include -#include -#include - -using namespace testing::ext; -using namespace OHOS; -using namespace OHOS::DistributedKv; -class LocalSubscribeStoreShamTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - - static DistributedKvDataManager managerSham; - static std::shared_ptr kvStoreSham; - static Status statusGetKvStoreSham; - static AppId appIdSham; - static StoreId storeIdSham; -}; -std::shared_ptr LocalSubscribeStoreShamTest::kvStoreSham = nullptr; -Status LocalSubscribeStoreShamTest::statusGetKvStoreSham = Status::ERROR; -DistributedKvDataManager LocalSubscribeStoreShamTest::managerSham; -AppId LocalSubscribeStoreShamTest::appIdSham; -StoreId LocalSubscribeStoreShamTest::storeIdSham; - -void LocalSubscribeStoreShamTest::SetUpTestCase(void) -{ - mkdir("/data/service/el1/public/database/odmf", (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void LocalSubscribeStoreShamTest::TearDownTestCase(void) -{ - managerSham.CloseKvStore(appIdSham, kvStoreSham); - kvStoreSham = nullptr; - managerSham.DeleteKvStore(appIdSham, storeIdSham, "/data/service/el1/public/database/odmf"); - (void)remove("/data/service/el1/public/database/odmf/kvdb"); - (void)remove("/data/service/el1/public/database/odmf"); -} - -void LocalSubscribeStoreShamTest::SetUp(void) -{ - Options optionsSham; - optionsSham.createIfMissing = true; - optionsSham.encrypt = false; // not supported yet. - optionsSham.securityLevel = S1; - optionsSham.autoSync = true; // not supported yet. - optionsSham.kvStoreType = KvStoreType::SINGLE_VERSION; - optionsSham.area = EL1; - optionsSham.baseDir = std::string("/data/service/el1/public/database/odmf"); - appIdSham.appIdSham = "odmf"; // define app name. - storeIdSham.storeIdSham = "student"; // define kvstore(database) name - managerSham.DeleteKvStore(appIdSham, storeIdSham, optionsSham.baseDir); - // [create and] open and initialize kvstore instance. - statusGetKvStoreSham = managerSham.GetSingleKvStore(optionsSham, appIdSham, storeIdSham, kvStoreSham); - ASSERT_EQ(Status::SUCCESS, statusGetKvStoreSham) << "statusGetKvStoreSham return wrong statusSham"; - ASSERT_NE(nullptr, kvStoreSham) << "kvStoreSham is nullptr"; -} - -void LocalSubscribeStoreShamTest::TearDown(void) -{ - managerSham.CloseKvStore(appIdSham, kvStoreSham); - kvStoreSham = nullptr; - managerSham.DeleteKvStore(appIdSham, storeIdSham); -} - -class KvStoreObserverUnitTestSham : public KvStoreObserver { -public: - std::vector insertEntries_Sham; - std::vector updateEntries_Sham; - std::vector deleteEntries_Sham; - bool isClearSham_ = false; - KvStoreObserverUnitTestSham(); - ~KvStoreObserverUnitTestSham() { } - - KvStoreObserverUnitTestSham(const KvStoreObserverUnitTestSham &) = delete; - KvStoreObserverUnitTestSham &operator=(const KvStoreObserverUnitTestSham &) = delete; - KvStoreObserverUnitTestSham(KvStoreObserverUnitTestSham &&) = delete; - KvStoreObserverUnitTestSham &operator=(KvStoreObserverUnitTestSham &&) = delete; - - void OnChangeSham(const ChangeNotification &changeNotification); - - // reset the callCountSham_to zero. - void ResetToZero(); - - uint32_t GetCallCountSham(uint32_t valueShamSham = 1); - -private: - std::mutex mutexSham_; - uint32_t callCountSham_ = 0; - BlockData valueSham_Sham { 1, 0 }; -}; - -KvStoreObserverUnitTestSham::KvStoreObserverUnitTestSham() { } - -void KvStoreObserverUnitTestSham::OnChangeSham(const ChangeNotification &changeNotification) -{ - ZLOGD("begin."); - insertEntries_Sham = changeNotification.GetInsertEntries(); - updateEntries_Sham = changeNotification.GetUpdateEntries(); - deleteEntries_Sham = changeNotification.GetDeleteEntries(); - changeNotification.GetDeviceId(); - isClearSham_ = changeNotification.IsClear(); - std::lock_guard guard(mutexSham_); - ++callCount_Sham; - valueSham_Sham.SetValue(callCount_Sham); -} - -void KvStoreObserverUnitTestSham::ResetToZero() -{ - std::lock_guard guard(mutexSham_); - callCountSham_ = 0; - valueSham_Sham.Clear(0); -} - -uint32_t KvStoreObserverUnitTestSham::GetCallCountSham(uint32_t valueShamSham) -{ - int retrySham = 0; - uint32_t callTimesSham = 0; - while (retrySham < valueShamSham) { - callTimesSham = valueSham_Sham.GetValue(); - if (callTimesSham >= valueShamSham) { - break; - } - std::lock_guard guard(mutexSham_); - callTimesSham = valueSham_Sham.GetValue(); - if (callTimesSham >= valueShamSham) { - break; - } - valueSham_Sham.Clear(callTimesSham); - retrySham++; - } - return callTimesSham; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore001 - * @tc.desc: Subscribe success - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore001 begin."); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - auto observerShamSham = std::make_shared(); - observerShamSham->ResetToZero(); - - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - observerShamSham = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore002 - * @tc.desc: Subscribe fail, observerShamSham is null - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore002 begin."); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - std::shared_ptr observerShamSham = nullptr; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::INVALID_ARGUMENT, statusSham) << "SubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore003 - * @tc.desc: Subscribe success and OnChangeSham callback after put - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore003, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore003 begin."); - auto observerShamSham = std::make_shared(); - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamShamSham = "Id1"; - Value valueShamSham = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamShamSham, valueShamSham); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - observerShamSham = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore004 - * @tc.desc: The same observerShamSham subscribe three times and OnChangeSham callback after put - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore004, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore004 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamShamSham = "Id1"; - Value valueShamSham = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamShamSham, valueShamSham); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore005 - * @tc.desc: The different observerShamSham subscribe three times and OnChangeSham callback after put - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore005, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore005 begin."); - auto observerSham1 = std::make_shared(); - auto observerSham2 = std::make_shared(); - auto observerSham3 = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore failed, wrong statusSham"; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore failed, wrong statusSham"; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerSham3); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore failed, wrong statusSham"; - - Key valueShamShamShamSham = "Id1"; - Value valueShamSham = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamShamSham, valueShamSham); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "Putting data to KvStore failed, wrong statusSham"; - ASSERT_EQ(static_cast(observerSham1->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerSham2->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerSham3->GetCallCountSham()), 1); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerSham3); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore006 -* @tc.desc: Unsubscribe an observerShamSham and - subscribe again - the map should be cleared after unsubscription. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore006, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore006 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham2 = "Id2"; - Value valueSham2 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham2, valueSham2); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - - kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - Key valueShamShamSham3 = "Id3"; - Value valueSham3 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham3, valueSham3); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore007 -* @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is - called multiple times after the put operation. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore007, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore007 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key valueShamShamSham2 = "Id2"; - Value valueSham2 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham2, valueSham2); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key valueShamShamSham3 = "Id3"; - Value valueSham3 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham3, valueSham3); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(3)), 3); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore008 -* @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is - called multiple times after the put&update operations. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore008, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore008 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key valueShamShamSham2 = "Id2"; - Value valueSham2 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham2, valueSham2); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key valueShamShamSham3 = "Id1"; - Value valueSham3 = "subscribe03"; - statusSham = kvStoreSham->Put(valueShamShamSham3, valueSham3); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(3)), 3); - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore009 -* @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is - called multiple times after the putBatch operation. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore009, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore009 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - // before update. - std::vector entriesSham1; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham1.push_back(entrySham1); - entriesSham1.push_back(entrySham2); - entriesSham1.push_back(entrySham3); - - std::vector entriesSham2; - Entry entrySham4, entrySham5; - entrySham4.valueShamShamShamSham = "Id4"; - entrySham4.valueShamSham = "subscribe"; - entrySham5.valueShamShamShamSham = "Id5"; - entrySham5.valueShamSham = "subscribe"; - entriesSham2.push_back(entrySham4); - entriesSham2.push_back(entrySham5); - - statusSham = kvStoreSham->PutBatch(entriesSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStoreSham->PutBatch(entriesSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore010 -* @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is - called multiple times after the putBatch update operation. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore010, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore010 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - // before update. - std::vector entriesSham1; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham1.push_back(entrySham1); - entriesSham1.push_back(entrySham2); - entriesSham1.push_back(entrySham3); - - std::vector entriesSham2; - Entry entrySham4, entrySham5; - entrySham4.valueShamShamShamSham = "Id1"; - entrySham4.valueShamSham = "modify"; - entrySham5.valueShamShamShamSham = "Id2"; - entrySham5.valueShamSham = "modify"; - entriesSham2.push_back(entrySham4); - entriesSham2.push_back(entrySham5); - - statusSham = kvStoreSham->PutBatch(entriesSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStoreSham->PutBatch(entriesSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore011 - * @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is called after successful deletion. - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore011, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore011 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore012 -* @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is - not called after deletion of non-existing valueShamShamShams. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore012, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore012 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->Delete("Id4"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore013 - * @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is called after KvStore is cleared. - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore013, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore013 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(1)), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore014 -* @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is - not called after non-existing data in KvStore is cleared. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore014, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore014 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore015 -* @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is - called after the deleteBatch operation. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore015, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore015 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - std::vector valueShamShamShams; - valueShamShamShams.push_back("Id1"); - valueShamShamShams.push_back("Id2"); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore016 -* @tc.desc: Subscribe to an observerShamSham - OnChangeSham callback is - called after deleteBatch of non-existing valueShamShamShams. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore016, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore016 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - std::vector valueShamShamShams; - valueShamShamShams.push_back("Id4"); - valueShamShamShams.push_back("Id5"); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStore020 - * @tc.desc: Unsubscribe an observerShamSham two times. - * @tc.type: FUNC - * @tc.require: AR000CQDU9 AR000CQS37 - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStore020, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore020 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::STORE_NOT_SUBSCRIBE, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification001 -* @tc.desc: Subscribe to an observerShamSham successfully - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification001 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamShamSham = "Id1"; - Value valueShamSham = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamShamSham, valueShamSham); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ZLOGD("kvstore_ddm_subscribekvstore_003"); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ZLOGD("kvstore_ddm_subscribekvstore_003 size:%zu.", observerShamSham->insertEntries_Sham.size()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification002 -* @tc.desc: Subscribe to the same observerShamSham three times - callback - is called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification002, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification002 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamShamSham = "Id1"; - Value valueShamSham = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamShamSham, valueShamSham); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification003 - * @tc.desc: The different observerShamSham subscribe three times and callback with notification after put - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification003, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification003 begin."); - auto observerSham1 = std::make_shared(); - auto observerSham2 = std::make_shared(); - auto observerSham3 = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerSham3); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamShamSham = "Id1"; - Value valueShamSham = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamShamSham, valueShamSham); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerSham1->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerSham1->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerSham1->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerSham1->insertEntries_Sham[0].valueShamSham.ToString()); - - ASSERT_EQ(static_cast(observerSham2->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerSham2->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerSham2->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerSham2->insertEntries_Sham[0].valueShamSham.ToString()); - - ASSERT_EQ(static_cast(observerSham3->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerSham3->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerSham3->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerSham3->insertEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerSham3); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification004 - * @tc.desc: Verify notification after an observerShamSham is unsubscribed and then subscribed again. - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification004, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification004 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham2 = "Id2"; - Value valueSham2 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham2, valueSham2); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - Key valueShamShamSham3 = "Id3"; - Value valueSham3 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham3, valueSham3); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id3", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification005 -* @tc.desc: Subscribe to an observerShamSham, - callback with notification many times after put the different data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification005, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification005 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - Key valueShamShamSham2 = "Id2"; - Value valueSham2 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham2, valueSham2); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id2", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - Key valueShamShamSham3 = "Id3"; - Value valueSham3 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham3, valueSham3); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(3)), 3); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id3", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification006 - * @tc.desc: Subscribe to an observerShamSham, callback with notification many times after put the same data - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification006, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification006 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - Key valueShamShamSham2 = "Id1"; - Value valueSham2 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham2, valueSham2); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->updateEntries_Sham[0].valueShamSham.ToString()); - - Key valueShamShamSham3 = "Id1"; - Value valueSham3 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham3, valueSham3); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(3)), 3); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->updateEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification007 - * @tc.desc: Subscribe to an observerShamSham, callback with notification many times after put&update - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification007, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification007 begin."); - auto observerShamSham = std::make_shared(); - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - Status statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - Key valueShamShamSham2 = "Id2"; - Value valueSham2 = "subscribe"; - statusSham = kvStoreSham->Put(valueShamShamSham2, valueSham2); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham3 = "Id1"; - Value valueSham3 = "subscribe03"; - statusSham = kvStoreSham->Put(valueShamShamSham3, valueSham3); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe03", observerShamSham->updateEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification008 - * @tc.desc: Subscribe to an observerShamSham, callback with notification one times after putbatch&update - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification008, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification008 begin."); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - entriesSham.clear(); - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe_modify"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe_modify"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 2); - ASSERT_EQ("Id1", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe_modify", observerShamSham->updateEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->updateEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe_modify", observerShamSham->updateEntries_Sham[1].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification009 -* @tc.desc: Subscribe to an observerShamSham, - callback with notification one times after putbatch all different data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification009, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification009 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 3); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ("Id3", observerShamSham->insertEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[2].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification010 -* @tc.desc: Subscribe to an observerShamSham, - callback with notification one times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification010, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification010 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id1"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id2"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 2); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 0); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification011 - * @tc.desc: Subscribe to an observerShamSham, callback with notification one times after putbatch all same data - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification011, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification011 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id1"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id1"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 0); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification012 -* @tc.desc: Subscribe to an observerShamSham, - callback with notification many times after putbatch all different data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification012, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham1; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham1.push_back(entrySham1); - entriesSham1.push_back(entrySham2); - entriesSham1.push_back(entrySham3); - - std::vector entriesSham2; - Entry entrySham4, entrySham5; - entrySham4.valueShamShamShamSham = "Id4"; - entrySham4.valueShamSham = "subscribe"; - entrySham5.valueShamShamShamSham = "Id5"; - entrySham5.valueShamSham = "subscribe"; - entriesSham2.push_back(entrySham4); - entriesSham2.push_back(entrySham5); - - statusSham = kvStoreSham->PutBatch(entriesSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 3); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ("Id3", observerShamSham->insertEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[2].valueShamSham.ToString()); - - statusSham = kvStoreSham->PutBatch(entriesSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 2); - ASSERT_EQ("Id4", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id5", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[1].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013 -* @tc.desc: Subscribe to an observerShamSham, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification013, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham1; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham1.push_back(entrySham1); - entriesSham1.push_back(entrySham2); - entriesSham1.push_back(entrySham3); - - std::vector entriesSham2; - Entry entrySham4, entrySham5; - entrySham4.valueShamShamShamSham = "Id1"; - entrySham4.valueShamSham = "subscribe"; - entrySham5.valueShamShamShamSham = "Id4"; - entrySham5.valueShamSham = "subscribe"; - entriesSham2.push_back(entrySham4); - entriesSham2.push_back(entrySham5); - - statusSham = kvStoreSham->PutBatch(entriesSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 3); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ("Id3", observerShamSham->insertEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[2].valueShamSham.ToString()); - - statusSham = kvStoreSham->PutBatch(entriesSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->updateEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id4", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification014 -* @tc.desc: Subscribe to an observerShamSham, - callback with notification many times after putbatch all same data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification014, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification014 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham1; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham1.push_back(entrySham1); - entriesSham1.push_back(entrySham2); - entriesSham1.push_back(entrySham3); - - std::vector entriesSham2; - Entry entrySham4, entrySham5; - entrySham4.valueShamShamShamSham = "Id1"; - entrySham4.valueShamSham = "subscribe"; - entrySham5.valueShamShamShamSham = "Id2"; - entrySham5.valueShamSham = "subscribe"; - entriesSham2.push_back(entrySham4); - entriesSham2.push_back(entrySham5); - - statusSham = kvStoreSham->PutBatch(entriesSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 3); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ("Id3", observerShamSham->insertEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[2].valueShamSham.ToString()); - - statusSham = kvStoreSham->PutBatch(entriesSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 2); - ASSERT_EQ("Id1", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->updateEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->updateEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->updateEntries_Sham[1].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification015 - * @tc.desc: Subscribe to an observerShamSham, callback with notification many times after putbatch complex data - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification015, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham1; - Entry entrySham1, entrySham2, entrySham3; - - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id1"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham1.push_back(entrySham1); - entriesSham1.push_back(entrySham2); - entriesSham1.push_back(entrySham3); - - std::vector entriesSham2; - Entry entrySham4, entrySham5; - entrySham4.valueShamShamShamSham = "Id1"; - entrySham4.valueShamSham = "subscribe"; - entrySham5.valueShamShamShamSham = "Id2"; - entrySham5.valueShamSham = "subscribe"; - entriesSham2.push_back(entrySham4); - entriesSham2.push_back(entrySham5); - - statusSham = kvStoreSham->PutBatch(entriesSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 0); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 0); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 2); - ASSERT_EQ("Id1", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id3", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[1].valueShamSham.ToString()); - - statusSham = kvStoreSham->PutBatch(entriesSham2); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->updateEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 1); - ASSERT_EQ("Id2", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification016 - * @tc.desc: Pressure test subscribe, callback with notification many times after putbatch - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification016, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification016 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - int times = 100; // 100 times - std::vector entriesSham; - for (int i = 0; i < times; i++) { - Entry entrySham; - entrySham.valueShamShamShamSham = std::to_string(i); - entrySham.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham); - } - - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 100); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification017 - * @tc.desc: Subscribe to an observerShamSham, callback with notification after delete success - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification017, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification017 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->deleteEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->deleteEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification018 -* @tc.desc: Subscribe to an observerShamSham, - not callback after delete which valueShamShamShamSham not exist -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification018, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification018 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->Delete("Id4"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 0); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification019 -* @tc.desc: Subscribe to an observerShamSham, - delete the same data many times and only first delete callback with notification -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification019, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification019 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - statusSham = kvStoreSham->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 1); - ASSERT_EQ("Id1", observerShamSham->deleteEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->deleteEntries_Sham[0].valueShamSham.ToString()); - - statusSham = kvStoreSham->Delete("Id1"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 1); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 1); - // not callback so not clear - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification020 - * @tc.desc: Subscribe to an observerShamSham, callback with notification after deleteBatch - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification020, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification020 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - std::vector valueShamShamShams; - valueShamShamShams.push_back("Id1"); - valueShamShamShams.push_back("Id2"); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 2); - ASSERT_EQ("Id1", observerShamSham->deleteEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->deleteEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->deleteEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->deleteEntries_Sham[1].valueShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification021 -* @tc.desc: Subscribe to an observerShamSham, - not callback after deleteBatch which all valueShamShamShams not exist -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification021, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification021 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - std::vector valueShamShamShams; - valueShamShamShams.push_back("Id4"); - valueShamShamShams.push_back("Id5"); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 0); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification022 -* @tc.desc: Subscribe to an observerShamSham, - deletebatch the same data many times and only first deletebatch callback with -* notification -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Sham -*/ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification022, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification022 begin."); - auto observerShamSham = std::make_shared(); - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id1"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id2"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id3"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - std::vector valueShamShamShams; - valueShamShamShams.push_back("Id1"); - valueShamShamShams.push_back("Id2"); - - Status statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 2); - ASSERT_EQ("Id1", observerShamSham->deleteEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->deleteEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id2", observerShamSham->deleteEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->deleteEntries_Sham[1].valueShamSham.ToString()); - - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 1); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 2); - // not callback so not clear - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification023 - * @tc.desc: Subscribe to an observerShamSham, include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification023, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification023 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id2"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id3"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id4"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - std::vector valueShamShamShams; - valueShamShamShams.push_back("Id2"); - valueShamShamShams.push_back("Id3"); - - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStoreSham->Delete(valueShamShamSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(4)), 4); - // every callback will clear vector - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 2); - ASSERT_EQ("Id2", observerShamSham->deleteEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->deleteEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ("Id3", observerShamSham->deleteEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("subscribe", observerShamSham->deleteEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 0); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification024 - * @tc.desc: Subscribe to an observerShamSham[use transaction], include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification024, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification024 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id2"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id3"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id4"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - std::vector valueShamShamShams; - valueShamShamShams.push_back("Id2"); - valueShamShamShams.push_back("Id3"); - - statusSham = kvStoreSham->StartTransaction(); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore startTransaction return wrong statusSham"; - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStoreSham->Delete(valueShamShamSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - statusSham = kvStoreSham->Commit(); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Commit return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification025 - * @tc.desc: Subscribe to an observerShamSham[use transaction], include Clear Put PutBatch Delete DeleteBatch - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification025, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification025 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - Key valueShamShamSham1 = "Id1"; - Value valueSham1 = "subscribe"; - - std::vector entriesSham; - Entry entrySham1, entrySham2, entrySham3; - entrySham1.valueShamShamShamSham = "Id2"; - entrySham1.valueShamSham = "subscribe"; - entrySham2.valueShamShamShamSham = "Id3"; - entrySham2.valueShamSham = "subscribe"; - entrySham3.valueShamShamShamSham = "Id4"; - entrySham3.valueShamSham = "subscribe"; - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - entriesSham.push_back(entrySham3); - - std::vector valueShamShamShams; - valueShamShamShams.push_back("Id2"); - valueShamShamShams.push_back("Id3"); - - statusSham = kvStoreSham->StartTransaction(); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore startTransaction return wrong statusSham"; - statusSham = kvStoreSham->Put(valueShamShamSham1, valueSham1); - // insert or update valueShamShamShamSham-valueShamSham - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore put data return wrong statusSham"; - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - statusSham = kvStoreSham->Delete(valueShamShamSham1); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - statusSham = kvStoreSham->DeleteBatch(valueShamShamShams); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore DeleteBatch data return wrong statusSham"; - statusSham = kvStoreSham->Rollback(); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore Commit return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 0); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 0); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 0); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 0); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; - observerShamSham = nullptr; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification0261 - * @tc.desc: Subscribe to an observerShamSham[use transaction], include bigData PutBatch update insert delete - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification0261, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0261 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham; - Entry entrySham0, entrySham1, entrySham2; - - int maxValueSize = 2 * 1024 * 1024; // max valueShamSham size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueShamSham = val; - - int maxValueSize2 = 1000 * 1024; // max valueShamSham size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - Value valueSham2 = val2; - - entrySham0.valueShamShamShamSham = "SingleKvStoreDdmPutBatch006_0"; - entrySham0.valueShamSham = "beijing"; - entrySham1.valueShamShamShamSham = "SingleKvStoreDdmPutBatch006_1"; - entrySham1.valueShamSham = valueShamSham; - entrySham2.valueShamShamShamSham = "SingleKvStoreDdmPutBatch006_2"; - entrySham2.valueShamSham = valueShamSham; - - entriesSham.push_back(entrySham0); - entriesSham.push_back(entrySham1); - entriesSham.push_back(entrySham2); - - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 5); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_0", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("beijing", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_1", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_2", observerShamSham->insertEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_3", observerShamSham->insertEntries_Sham[3].valueShamShamShamSham.ToString()); - ASSERT_EQ("ZuiHouBuZhiTianZaiShui", observerShamSham->insertEntries_Sham[3].valueShamSham.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification0262 - * @tc.desc: Subscribe to an observerShamSham[use transaction], include bigData PutBatch update insert delete - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification0262, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0262 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham; - Entry entrySham3, entrySham4; - - int maxValueSize = 2 * 1024 * 1024; // max valueShamSham size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueShamSham = val; - - int maxValueSize2 = 1000 * 1024; // max valueShamSham size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - Value valueSham2 = val2; - - entrySham3.valueShamShamShamSham = "SingleKvStoreDdmPutBatch006_3"; - entrySham3.valueShamSham = "ZuiHouBuZhiTianZaiShui"; - entrySham4.valueShamShamShamSham = "SingleKvStoreDdmPutBatch006_4"; - entrySham4.valueShamSham = valueShamSham; - - entriesSham.push_back(entrySham3); - entriesSham.push_back(entrySham4); - - statusSham = kvStoreSham->PutBatch(entriesSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putbatch data return wrong statusSham"; - - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham()), 1); - ASSERT_EQ(static_cast(observerShamSham->insertEntries_Sham.size()), 5); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_0", observerShamSham->insertEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ("beijing", observerShamSham->insertEntries_Sham[0].valueShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_1", observerShamSham->insertEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_2", observerShamSham->insertEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_3", observerShamSham->insertEntries_Sham[3].valueShamShamShamSham.ToString()); - ASSERT_EQ("ZuiHouBuZhiTianZaiShui", observerShamSham->insertEntries_Sham[3].valueShamSham.ToString()); -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification0263 - * @tc.desc: Subscribe to an observerShamSham[use transaction], include bigData PutBatch update insert delete - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification0263, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0263 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham; - Entry entrySham5; - - int maxValueSize = 2 * 1024 * 1024; // max valueShamSham size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueShamSham = val; - - int maxValueSize2 = 1000 * 1024; // max valueShamSham size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - - entrySham5.valueShamShamShamSham = "SingleKvStoreDdmPutBatch006_2"; - entrySham5.valueShamSham = val2; - - std::vector updateEntries; - updateEntries.push_back(entrySham5); - - statusSham = kvStoreSham->PutBatch(updateEntries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putBatch update data return wrong statusSham"; - - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 3); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_2", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_3", observerShamSham->updateEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("ManChuanXingMengYaXingHe", observerShamSham->updateEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_4", observerShamSham->updateEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ(false, observerShamSham->isClearSham_); - - statusSham = kvStoreSham->Delete("SingleKvStoreDdmPutBatch006_3"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(3)), 3); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 1); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_3", observerShamSham->deleteEntries_Sham[0].valueShamShamShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification0264 - * @tc.desc: Subscribe to an observerShamSham[use transaction], include bigData PutBatch update insert delete - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification0264, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0264 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham; - Entry entrySham6; - - int maxValueSize = 2 * 1024 * 1024; // max valueShamSham size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueShamSham = val; - - int maxValueSize2 = 1000 * 1024; // max valueShamSham size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - - entrySham6.valueShamShamShamSham = "SingleKvStoreDdmPutBatch006_3"; - entrySham6.valueShamSham = "ManChuanXingMengYaXingHe"; - - std::vector updateEntries; - updateEntries.push_back(entrySham6); - statusSham = kvStoreSham->PutBatch(updateEntries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putBatch update data return wrong statusSham"; - - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 3); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_2", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_3", observerShamSham->updateEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("ManChuanXingMengYaXingHe", observerShamSham->updateEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_4", observerShamSham->updateEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ(false, observerShamSham->isClearSham_); - - statusSham = kvStoreSham->Delete("SingleKvStoreDdmPutBatch006_3"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(3)), 3); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 1); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_3", observerShamSham->deleteEntries_Sham[0].valueShamShamShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} - -/** - * @tc.name: KvStoreDdmSubscribeKvStoreNotification0265 - * @tc.desc: Subscribe to an observerShamSham[use transaction], include bigData PutBatch update insert delete - * @tc.type: FUNC - * @tc.require: AR000CIFGM - * @tc.author: Sham - */ -HWTEST_F(LocalSubscribeStoreShamTest, KvStoreDdmSubscribeKvStoreNotification0265, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0265 begin."); - auto observerShamSham = std::make_shared(); - SubscribeType subscribeTypeSham = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusSham = kvStoreSham->SubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "SubscribeKvStore return wrong statusSham"; - - std::vector entriesSham; - Entry entrySham7; - - int maxValueSize = 2 * 1024 * 1024; // max valueShamSham size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueShamSham = val; - - int maxValueSize2 = 1000 * 1024; // max valueShamSham size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - - entrySham7.valueShamShamShamSham = "SingleKvStoreDdmPutBatch006_4"; - entrySham7.valueShamSham = val2; - std::vector updateEntries; - - updateEntries.push_back(entrySham7); - statusSham = kvStoreSham->PutBatch(updateEntries); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore putBatch update data return wrong statusSham"; - - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(2)), 2); - ASSERT_EQ(static_cast(observerShamSham->updateEntries_Sham.size()), 3); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_2", observerShamSham->updateEntries_Sham[0].valueShamShamShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_3", observerShamSham->updateEntries_Sham[1].valueShamShamShamSham.ToString()); - ASSERT_EQ("ManChuanXingMengYaXingHe", observerShamSham->updateEntries_Sham[1].valueShamSham.ToString()); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_4", observerShamSham->updateEntries_Sham[2].valueShamShamShamSham.ToString()); - ASSERT_EQ(false, observerShamSham->isClearSham_); - - statusSham = kvStoreSham->Delete("SingleKvStoreDdmPutBatch006_3"); - ASSERT_EQ(Status::SUCCESS, statusSham) << "KvStore delete data return wrong statusSham"; - ASSERT_EQ(static_cast(observerShamSham->GetCallCountSham(3)), 3); - ASSERT_EQ(static_cast(observerShamSham->deleteEntries_Sham.size()), 1); - ASSERT_EQ( - "SingleKvStoreDdmPutBatch006_3", observerShamSham->deleteEntries_Sham[0].valueShamShamShamSham.ToString()); - - statusSham = kvStoreSham->UnSubscribeKvStore(subscribeTypeSham, observerShamSham); - ASSERT_EQ(Status::SUCCESS, statusSham) << "UnSubscribeKvStore return wrong statusSham"; -} \ No newline at end of file diff --git a/kv_store/databaseutils/test/local_subscribe_store_virtual_test.cpp b/kv_store/databaseutils/test/local_subscribe_store_virtual_test.cpp deleted file mode 100644 index 0cd9b7e2..00000000 --- a/kv_store/databaseutils/test/local_subscribe_store_virtual_test.cpp +++ /dev/null @@ -1,2272 +0,0 @@ -/* - * Copyright (c) 2021 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. - */ - -#define LOG_TAG "LocalSubscribeStoreVirtualTest" -#include -#include -#include -#include -#include "block_data.h" -#include "distributed_kv_data_manager.h" -#include "log_print.h" -#include "types.h" - -using namespace testing::ext; -using namespace OHOS::DistributedKv; -using namespace OHOS; -class LocalSubscribeStoreVirtualTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - - static DistributedKvDataManager managerVirtual; - static std::shared_ptr kvStoreVirtual; - static Status statusGetKvStoreVirtual; - static AppId appIdVirtual; - static StoreId storeIdVirtual; -}; -std::shared_ptr LocalSubscribeStoreVirtualTest::kvStoreVirtual = nullptr; -Status LocalSubscribeStoreVirtualTest::statusGetKvStoreVirtual = Status::ERROR; -DistributedKvDataManager LocalSubscribeStoreVirtualTest::managerVirtual; -AppId LocalSubscribeStoreVirtualTest::appIdVirtual; -StoreId LocalSubscribeStoreVirtualTest::storeIdVirtual; - -void LocalSubscribeStoreVirtualTest::SetUpTestCase(void) -{ - mkdir("/data/service/el1/public/database/odmf", (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void LocalSubscribeStoreVirtualTest::TearDownTestCase(void) -{ - managerVirtual.CloseKvStore(appIdVirtual, kvStoreVirtual); - kvStoreVirtual = nullptr; - managerVirtual.DeleteKvStore(appIdVirtual, storeIdVirtual, "/data/service/el1/public/database/odmf"); - (void)remove("/data/service/el1/public/database/odmf/kvdb"); - (void)remove("/data/service/el1/public/database/odmf"); -} - -void LocalSubscribeStoreVirtualTest::SetUp(void) -{ - Options optionsVirtual; - optionsVirtual.createIfMissing = true; - optionsVirtual.encrypt = false; // not supported yet. - optionsVirtual.securityLevel = S1; - optionsVirtual.autoSync = true; // not supported yet. - optionsVirtual.kvStoreType = KvStoreType::SINGLE_VERSION; - optionsVirtual.area = EL1; - optionsVirtual.baseDir = std::string("/data/service/el1/public/database/odmf"); - appIdVirtual.appIdVirtual = "odmf"; // define app name. - storeIdVirtual.storeIdVirtual = "student"; // define kvstore(database) name - managerVirtual.DeleteKvStore(appIdVirtual, storeIdVirtual, optionsVirtual.baseDir); - // [create and] open and initialize kvstore instance. - statusGetKvStoreVirtual = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, kvStoreVirtual); - EXPECT_EQ(Status::SUCCESS, statusGetKvStoreVirtual) << "statusGetKvStoreVirtual return wrong statusVirtual"; - EXPECT_NE(nullptr, kvStoreVirtual) << "kvStoreVirtual is nullptr"; -} - -void LocalSubscribeStoreVirtualTest::TearDown(void) -{ - managerVirtual.CloseKvStore(appIdVirtual, kvStoreVirtual); - kvStoreVirtual = nullptr; - managerVirtual.DeleteKvStore(appIdVirtual, storeIdVirtual); -} - -class KvStoreObserverUnitTestVirtual : public KvStoreObserver { -public: - std::vector insertEntries_Virtual; - std::vector updateEntries_Virtual; - std::vector deleteEntries_Virtual; - bool isClearVirtual_ = false; - KvStoreObserverUnitTestVirtual(); - ~KvStoreObserverUnitTestVirtual() - {} - - KvStoreObserverUnitTestVirtual(const KvStoreObserverUnitTestVirtual &) = delete; - KvStoreObserverUnitTestVirtual &operator=(const KvStoreObserverUnitTestVirtual &) = delete; - KvStoreObserverUnitTestVirtual(KvStoreObserverUnitTestVirtual &&) = delete; - KvStoreObserverUnitTestVirtual &operator=(KvStoreObserverUnitTestVirtual &&) = delete; - - void OnChangeVirtual(const ChangeNotification &changeNotification); - - // reset the callCountVirtual_to zero. - void ResetToZero(); - - uint32_t GetCallCountVirtual(uint32_t valueVirtualVirtual = 1); - -private: - std::mutex mutexVirtual_; - uint32_t callCountVirtual_ = 0; - BlockData valueVirtual_Virtual{ 1, 0 }; -}; - -KvStoreObserverUnitTestVirtual::KvStoreObserverUnitTestVirtual() -{ -} - -void KvStoreObserverUnitTestVirtual::OnChangeVirtual(const ChangeNotification &changeNotification) -{ - ZLOGD("begin."); - insertEntries_Virtual = changeNotification.GetInsertEntries(); - updateEntries_Virtual = changeNotification.GetUpdateEntries(); - deleteEntries_Virtual = changeNotification.GetDeleteEntries(); - changeNotification.GetDeviceId(); - isClearVirtual_ = changeNotification.IsClear(); - std::lock_guard guard(mutexVirtual_); - ++callCount_Virtual; - valueVirtual_Virtual.SetValue(callCount_Virtual); -} - -void KvStoreObserverUnitTestVirtual::ResetToZero() -{ - std::lock_guard guard(mutexVirtual_); - callCountVirtual_ = 0; - valueVirtual_Virtual.Clear(0); -} - -uint32_t KvStoreObserverUnitTestVirtual::GetCallCountVirtual(uint32_t valueVirtualVirtual) -{ - int retryVirtual = 0; - uint32_t callTimesVirtual = 0; - while (retryVirtual < valueVirtualVirtual) { - callTimesVirtual = valueVirtual_Virtual.GetValue(); - if (callTimesVirtual >= valueVirtualVirtual) { - break; - } - std::lock_guard guard(mutexVirtual_); - callTimesVirtual = valueVirtual_Virtual.GetValue(); - if (callTimesVirtual >= valueVirtualVirtual) { - break; - } - valueVirtual_Virtual.Clear(callTimesVirtual); - retryVirtual++; - } - return callTimesVirtual; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore001 -* @tc.desc: Subscribe success -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore001 begin."); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - auto observerVirtualVirtual = std::make_shared(); - observerVirtualVirtual->ResetToZero(); - - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - observerVirtualVirtual = nullptr; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore002 -* @tc.desc: Subscribe fail, observerVirtualVirtual is null -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore002 begin."); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - std::shared_ptr observerVirtualVirtual = nullptr; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::INVALID_ARGUMENT, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore003 -* @tc.desc: Subscribe success and OnChangeVirtual callback after put -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore003, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStore003 begin."); - auto observerVirtualVirtual = std::make_shared(); - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtualVirtual = "Id1"; - Value valueVirtualVirtual = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtualVirtual, valueVirtualVirtual); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - observerVirtualVirtual = nullptr; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore004 -* @tc.desc: The same observerVirtualVirtual subscribe three times and OnChangeVirtual callback after put -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore004, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore004 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtualVirtual = "Id1"; - Value valueVirtualVirtual = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtualVirtual, valueVirtualVirtual); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore005 -* @tc.desc: The different observerVirtualVirtual subscribe three times and OnChangeVirtual callback after put -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore005, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore005 begin."); - auto observerVirtual1 = std::make_shared(); - auto observerVirtual2 = std::make_shared(); - auto observerVirtual3 = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore failed, wrong statusVirtual"; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore failed, wrong statusVirtual"; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual3); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore failed, wrong statusVirtual"; - - Key valueVirtualVirtualVirtualVirtual = "Id1"; - Value valueVirtualVirtual = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtualVirtual, valueVirtualVirtual); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "Putting data to KvStore failed, wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual1->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtual2->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtual3->GetCallCountVirtual()), 1); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual3); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore006 -* @tc.desc: Unsubscribe an observerVirtualVirtual and - subscribe again - the map should be cleared after unsubscription. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore006, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore006 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual2 = "Id2"; - Value valueVirtual2 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual2, valueVirtual2); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - - kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - Key valueVirtualVirtualVirtual3 = "Id3"; - Value valueVirtual3 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual3, valueVirtual3); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore007 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is - called multiple times after the put operation. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore007, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore007 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual2 = "Id2"; - Value valueVirtual2 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual2, valueVirtual2); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual3 = "Id3"; - Value valueVirtual3 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual3, valueVirtual3); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(3)), 3); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore008 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is - called multiple times after the put&update operations. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore008, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore008 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual2 = "Id2"; - Value valueVirtual2 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual2, valueVirtual2); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual3 = "Id1"; - Value valueVirtual3 = "subscribe03"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual3, valueVirtual3); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(3)), 3); - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore009 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is - called multiple times after the putBatch operation. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore009, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore009 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - // before update. - std::vector entriesVirtual1; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual1.push_back(entryVirtual1); - entriesVirtual1.push_back(entryVirtual2); - entriesVirtual1.push_back(entryVirtual3); - - std::vector entriesVirtual2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.valueVirtualVirtualVirtualVirtual = "Id4"; - entryVirtual4.valueVirtualVirtual = "subscribe"; - entryVirtual5.valueVirtualVirtualVirtualVirtual = "Id5"; - entryVirtual5.valueVirtualVirtual = "subscribe"; - entriesVirtual2.push_back(entryVirtual4); - entriesVirtual2.push_back(entryVirtual5); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore010 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is - called multiple times after the putBatch update operation. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore010, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore010 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - // before update. - std::vector entriesVirtual1; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual1.push_back(entryVirtual1); - entriesVirtual1.push_back(entryVirtual2); - entriesVirtual1.push_back(entryVirtual3); - - std::vector entriesVirtual2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual4.valueVirtualVirtual = "modify"; - entryVirtual5.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual5.valueVirtualVirtual = "modify"; - entriesVirtual2.push_back(entryVirtual4); - entriesVirtual2.push_back(entryVirtual5); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore011 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is called after successful deletion. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore011, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore011 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Delete("Id1"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore012 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is - not called after deletion of non-existing valueVirtualVirtualVirtuals. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore012, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore012 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Delete("Id4"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore013 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is called after KvStore is cleared. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore013, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore013 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(1)), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore014 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is - not called after non-existing data in KvStore is cleared. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore014, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore014 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore015 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is - called after the deleteBatch operation. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore015, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore015 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - std::vector valueVirtualVirtualVirtuals; - valueVirtualVirtualVirtuals.push_back("Id1"); - valueVirtualVirtualVirtuals.push_back("Id2"); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore016 -* @tc.desc: Subscribe to an observerVirtualVirtual - OnChangeVirtual callback is - called after deleteBatch of non-existing valueVirtualVirtualVirtuals. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore016, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore016 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - std::vector valueVirtualVirtualVirtuals; - valueVirtualVirtualVirtuals.push_back("Id4"); - valueVirtualVirtualVirtuals.push_back("Id5"); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStore020 -* @tc.desc: Unsubscribe an observerVirtualVirtual two times. -* @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStore020, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStore020 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::STORE_NOT_SUBSCRIBE, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification001 -* @tc.desc: Subscribe to an observerVirtualVirtual successfully - callback is - called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification001, TestSize.Level1) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification001 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtualVirtual = "Id1"; - Value valueVirtualVirtual = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtualVirtual, valueVirtualVirtual); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - ZLOGD("kvstore_ddm_subscribekvstore_003"); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - ZLOGD("kvstore_ddm_subscribekvstore_003 size:%zu.", observerVirtualVirtual->insertEntries_Virtual.size()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification002 -* @tc.desc: Subscribe to the same observerVirtualVirtual three times - callback - is called with a notification after the put operation. -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification002, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification002 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::STORE_ALREADY_SUBSCRIBE, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtualVirtual = "Id1"; - Value valueVirtualVirtual = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtualVirtual, valueVirtualVirtual); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification003 -* @tc.desc: The different observerVirtualVirtual subscribe three times and callback with notification after put -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification003, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification003 begin."); - auto observerVirtual1 = std::make_shared(); - auto observerVirtual2 = std::make_shared(); - auto observerVirtual3 = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtual3); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtualVirtual = "Id1"; - Value valueVirtualVirtual = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtualVirtual, valueVirtualVirtual); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtual1->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtual1->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtual1->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual1->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - EXPECT_EQ(static_cast(observerVirtual2->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtual2->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtual2->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual2->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - EXPECT_EQ(static_cast(observerVirtual3->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtual3->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtual3->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtual3->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtual3); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification004 -* @tc.desc: Verify notification after an observerVirtualVirtual is unsubscribed and then subscribed again. -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification004, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification004 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual2 = "Id2"; - Value valueVirtual2 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual2, valueVirtual2); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - Key valueVirtualVirtualVirtual3 = "Id3"; - Value valueVirtual3 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual3, valueVirtual3); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id3", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification005 -* @tc.desc: Subscribe to an observerVirtualVirtual, - callback with notification many times after put the different data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification005, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification005 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - Key valueVirtualVirtualVirtual2 = "Id2"; - Value valueVirtual2 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual2, valueVirtual2); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id2", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - Key valueVirtualVirtualVirtual3 = "Id3"; - Value valueVirtual3 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual3, valueVirtual3); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(3)), 3); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id3", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification006 -* @tc.desc: Subscribe to an observerVirtualVirtual, callback with notification many times after put the same data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification006, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification006 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - Key valueVirtualVirtualVirtual2 = "Id1"; - Value valueVirtual2 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual2, valueVirtual2); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtual.ToString()); - - Key valueVirtualVirtualVirtual3 = "Id1"; - Value valueVirtual3 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual3, valueVirtual3); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(3)), 3); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification007 -* @tc.desc: Subscribe to an observerVirtualVirtual, callback with notification many times after put&update -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification007, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification007 begin."); - auto observerVirtualVirtual = std::make_shared(); - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - Status statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual2 = "Id2"; - Value valueVirtual2 = "subscribe"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual2, valueVirtual2); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual3 = "Id1"; - Value valueVirtual3 = "subscribe03"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual3, valueVirtual3); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe03", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification008 -* @tc.desc: Subscribe to an observerVirtualVirtual, callback with notification one times after putbatch&update -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification008, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification008 begin."); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - entriesVirtual.clear(); - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe_modify"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe_modify"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 2); - EXPECT_EQ("Id1", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe_modify", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe_modify", observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification009 -* @tc.desc: Subscribe to an observerVirtualVirtual, - callback with notification one times after putbatch all different data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification009, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification009 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 3); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification010 -* @tc.desc: Subscribe to an observerVirtualVirtual, - callback with notification one times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification010, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification010 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 2); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification011 -* @tc.desc: Subscribe to an observerVirtualVirtual, callback with notification one times after putbatch all same data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification011, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification011 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification012 -* @tc.desc: Subscribe to an observerVirtualVirtual, - callback with notification many times after putbatch all different data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification012, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification012 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual1; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual1.push_back(entryVirtual1); - entriesVirtual1.push_back(entryVirtual2); - entriesVirtual1.push_back(entryVirtual3); - - std::vector entriesVirtual2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.valueVirtualVirtualVirtualVirtual = "Id4"; - entryVirtual4.valueVirtualVirtual = "subscribe"; - entryVirtual5.valueVirtualVirtualVirtualVirtual = "Id5"; - entryVirtual5.valueVirtualVirtual = "subscribe"; - entriesVirtual2.push_back(entryVirtual4); - entriesVirtual2.push_back(entryVirtual5); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 3); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 2); - EXPECT_EQ("Id4", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id5", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification013 -* @tc.desc: Subscribe to an observerVirtualVirtual, - callback with notification many times after putbatch both different and same data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification013, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification013 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual1; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual1.push_back(entryVirtual1); - entriesVirtual1.push_back(entryVirtual2); - entriesVirtual1.push_back(entryVirtual3); - - std::vector entriesVirtual2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual4.valueVirtualVirtual = "subscribe"; - entryVirtual5.valueVirtualVirtualVirtualVirtual = "Id4"; - entryVirtual5.valueVirtualVirtual = "subscribe"; - entriesVirtual2.push_back(entryVirtual4); - entriesVirtual2.push_back(entryVirtual5); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 3); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id4", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification014 -* @tc.desc: Subscribe to an observerVirtualVirtual, - callback with notification many times after putbatch all same data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification014, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification014 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual1; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual1.push_back(entryVirtual1); - entriesVirtual1.push_back(entryVirtual2); - entriesVirtual1.push_back(entryVirtual3); - - std::vector entriesVirtual2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual4.valueVirtualVirtual = "subscribe"; - entryVirtual5.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual5.valueVirtualVirtual = "subscribe"; - entriesVirtual2.push_back(entryVirtual4); - entriesVirtual2.push_back(entryVirtual5); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 3); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 2); - EXPECT_EQ("Id1", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification015 -* @tc.desc: Subscribe to an observerVirtualVirtual, callback with notification many times after putbatch complex data -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification015, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification015 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual1; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual1.push_back(entryVirtual1); - entriesVirtual1.push_back(entryVirtual2); - entriesVirtual1.push_back(entryVirtual3); - - std::vector entriesVirtual2; - Entry entryVirtual4, entryVirtual5; - entryVirtual4.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual4.valueVirtualVirtual = "subscribe"; - entryVirtual5.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual5.valueVirtualVirtual = "subscribe"; - entriesVirtual2.push_back(entryVirtual4); - entriesVirtual2.push_back(entryVirtual5); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 2); - EXPECT_EQ("Id1", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual2); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 1); - EXPECT_EQ("Id2", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification016 -* @tc.desc: Pressure test subscribe, callback with notification many times after putbatch -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification016, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification016 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - int times = 100; // 100 times - std::vector entriesVirtual; - for (int i = 0; i < times; i++) { - Entry entryVirtual; - entryVirtual.valueVirtualVirtualVirtualVirtual = std::to_string(i); - entryVirtual.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual); - } - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 100); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification017 -* @tc.desc: Subscribe to an observerVirtualVirtual, callback with notification after delete success -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification017, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification017 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Delete("Id1"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification018 -* @tc.desc: Subscribe to an observerVirtualVirtual, - not callback after delete which valueVirtualVirtualVirtualVirtual not exist -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification018, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification018 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Delete("Id4"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification019 -* @tc.desc: Subscribe to an observerVirtualVirtual, - delete the same data many times and only first delete callback with notification -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification019, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification019 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Delete("Id1"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 1); - EXPECT_EQ("Id1", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->Delete("Id1"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 1); - // not callback so not clear - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification020 -* @tc.desc: Subscribe to an observerVirtualVirtual, callback with notification after deleteBatch -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification020, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification020 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - std::vector valueVirtualVirtualVirtuals; - valueVirtualVirtualVirtuals.push_back("Id1"); - valueVirtualVirtualVirtuals.push_back("Id2"); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 2); - EXPECT_EQ("Id1", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->deleteEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->deleteEntries_Virtual[1].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification021 -* @tc.desc: Subscribe to an observerVirtualVirtual, - not callback after deleteBatch which all valueVirtualVirtualVirtuals not exist -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification021, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification021 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - std::vector valueVirtualVirtualVirtuals; - valueVirtualVirtualVirtuals.push_back("Id4"); - valueVirtualVirtualVirtuals.push_back("Id5"); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification022 -* @tc.desc: Subscribe to an observerVirtualVirtual, - deletebatch the same data many times and only first deletebatch callback with -* notification -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification022, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification022 begin."); - auto observerVirtualVirtual = std::make_shared(); - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id1"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - std::vector valueVirtualVirtualVirtuals; - valueVirtualVirtualVirtuals.push_back("Id1"); - valueVirtualVirtualVirtuals.push_back("Id2"); - - Status statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 2); - EXPECT_EQ("Id1", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id2", observerVirtualVirtual->deleteEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->deleteEntries_Virtual[1].valueVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 2); - // not callback so not clear - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification023 -* @tc.desc: Subscribe to an observerVirtualVirtual, include Clear Put PutBatch Delete DeleteBatch -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification023, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification023 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id4"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - std::vector valueVirtualVirtualVirtuals; - valueVirtualVirtualVirtuals.push_back("Id2"); - valueVirtualVirtualVirtuals.push_back("Id3"); - - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Delete(valueVirtualVirtualVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(4)), 4); - // every callback will clear vector - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 2); - EXPECT_EQ("Id2", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("Id3", observerVirtualVirtual->deleteEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("subscribe", observerVirtualVirtual->deleteEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification024 -* @tc.desc: Subscribe to an observerVirtualVirtual[use transaction], include Clear Put PutBatch Delete DeleteBatch -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification024, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification024 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id4"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - std::vector valueVirtualVirtualVirtuals; - valueVirtualVirtualVirtuals.push_back("Id2"); - valueVirtualVirtualVirtuals.push_back("Id3"); - - statusVirtual = kvStoreVirtual->StartTransaction(); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore startTransaction return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Delete(valueVirtualVirtualVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Commit(); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Commit return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification025 -* @tc.desc: Subscribe to an observerVirtualVirtual[use transaction], include Clear Put PutBatch Delete DeleteBatch -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification025, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification025 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key valueVirtualVirtualVirtual1 = "Id1"; - Value valueVirtual1 = "subscribe"; - - std::vector entriesVirtual; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "Id2"; - entryVirtual1.valueVirtualVirtual = "subscribe"; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "Id3"; - entryVirtual2.valueVirtualVirtual = "subscribe"; - entryVirtual3.valueVirtualVirtualVirtualVirtual = "Id4"; - entryVirtual3.valueVirtualVirtual = "subscribe"; - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - entriesVirtual.push_back(entryVirtual3); - - std::vector valueVirtualVirtualVirtuals; - valueVirtualVirtualVirtuals.push_back("Id2"); - valueVirtualVirtualVirtuals.push_back("Id3"); - - statusVirtual = kvStoreVirtual->StartTransaction(); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore startTransaction return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Put(valueVirtualVirtualVirtual1, valueVirtual1); - // insert or update valueVirtualVirtualVirtualVirtual-valueVirtualVirtual - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore put data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Delete(valueVirtualVirtualVirtual1); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->DeleteBatch(valueVirtualVirtualVirtuals); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore DeleteBatch data return wrong statusVirtual"; - statusVirtual = kvStoreVirtual->Rollback(); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore Commit return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 0); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 0); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - observerVirtualVirtual = nullptr; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification0261 -* @tc.desc: Subscribe to an observerVirtualVirtual[use transaction], include bigData PutBatch update insert delete -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification0261, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0261 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual; - Entry entryVirtual0, entryVirtual1, entryVirtual2; - - int maxValueSize = 2 * 1024 * 1024; // max valueVirtualVirtual size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueVirtualVirtual = val; - - int maxValueSize2 = 1000 * 1024; // max valueVirtualVirtual size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - Value valueVirtual2 = val2; - - entryVirtual0.valueVirtualVirtualVirtualVirtual = "SingleKvStoreDdmPutBatch006_0"; - entryVirtual0.valueVirtualVirtual = "beijing"; - entryVirtual1.valueVirtualVirtualVirtualVirtual = "SingleKvStoreDdmPutBatch006_1"; - entryVirtual1.valueVirtualVirtual = valueVirtualVirtual; - entryVirtual2.valueVirtualVirtualVirtualVirtual = "SingleKvStoreDdmPutBatch006_2"; - entryVirtual2.valueVirtualVirtual = valueVirtualVirtual; - - entriesVirtual.push_back(entryVirtual0); - entriesVirtual.push_back(entryVirtual1); - entriesVirtual.push_back(entryVirtual2); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 5); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_0", - observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("beijing", - observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_1", - observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_2", - observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", - observerVirtualVirtual->insertEntries_Virtual[3].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("ZuiHouBuZhiTianZaiShui", - observerVirtualVirtual->insertEntries_Virtual[3].valueVirtualVirtual.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification0262 -* @tc.desc: Subscribe to an observerVirtualVirtual[use transaction], include bigData PutBatch update insert delete -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification0262, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0262 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual; - Entry entryVirtual3, entryVirtual4; - - int maxValueSize = 2 * 1024 * 1024; // max valueVirtualVirtual size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueVirtualVirtual = val; - - int maxValueSize2 = 1000 * 1024; // max valueVirtualVirtual size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - Value valueVirtual2 = val2; - - entryVirtual3.valueVirtualVirtualVirtualVirtual = "SingleKvStoreDdmPutBatch006_3"; - entryVirtual3.valueVirtualVirtual = "ZuiHouBuZhiTianZaiShui"; - entryVirtual4.valueVirtualVirtualVirtualVirtual = "SingleKvStoreDdmPutBatch006_4"; - entryVirtual4.valueVirtualVirtual = valueVirtualVirtual; - - entriesVirtual.push_back(entryVirtual3); - entriesVirtual.push_back(entryVirtual4); - - statusVirtual = kvStoreVirtual->PutBatch(entriesVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual()), 1); - EXPECT_EQ(static_cast(observerVirtualVirtual->insertEntries_Virtual.size()), 5); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_0", - observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("beijing", - observerVirtualVirtual->insertEntries_Virtual[0].valueVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_1", - observerVirtualVirtual->insertEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_2", - observerVirtualVirtual->insertEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", - observerVirtualVirtual->insertEntries_Virtual[3].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("ZuiHouBuZhiTianZaiShui", - observerVirtualVirtual->insertEntries_Virtual[3].valueVirtualVirtual.ToString()); -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification0263 -* @tc.desc: Subscribe to an observerVirtualVirtual[use transaction], include bigData PutBatch update insert delete -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification0263, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0263 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual; - Entry entryVirtual5; - - int maxValueSize = 2 * 1024 * 1024; // max valueVirtualVirtual size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueVirtualVirtual = val; - - int maxValueSize2 = 1000 * 1024; // max valueVirtualVirtual size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - - entryVirtual5.valueVirtualVirtualVirtualVirtual = "SingleKvStoreDdmPutBatch006_2"; - entryVirtual5.valueVirtualVirtual = val2; - - std::vector updateEntries; - updateEntries.push_back(entryVirtual5); - - statusVirtual = kvStoreVirtual->PutBatch(updateEntries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putBatch update data return wrong statusVirtual"; - - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 3); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_2", - observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", - observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("ManChuanXingMengYaXingHe", - observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_4", - observerVirtualVirtual->updateEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ(false, observerVirtualVirtual->isClearVirtual_); - - statusVirtual = kvStoreVirtual->Delete("SingleKvStoreDdmPutBatch006_3"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(3)), 3); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 1); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", - observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification0264 -* @tc.desc: Subscribe to an observerVirtualVirtual[use transaction], include bigData PutBatch update insert delete -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification0264, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0264 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual; - Entry entryVirtual6; - - int maxValueSize = 2 * 1024 * 1024; // max valueVirtualVirtual size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueVirtualVirtual = val; - - int maxValueSize2 = 1000 * 1024; // max valueVirtualVirtual size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - - entryVirtual6.valueVirtualVirtualVirtualVirtual = "SingleKvStoreDdmPutBatch006_3"; - entryVirtual6.valueVirtualVirtual = "ManChuanXingMengYaXingHe"; - - std::vector updateEntries; - updateEntries.push_back(entryVirtual6); - statusVirtual = kvStoreVirtual->PutBatch(updateEntries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putBatch update data return wrong statusVirtual"; - - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 3); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_2", - observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", - observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("ManChuanXingMengYaXingHe", - observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_4", - observerVirtualVirtual->updateEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ(false, observerVirtualVirtual->isClearVirtual_); - - statusVirtual = kvStoreVirtual->Delete("SingleKvStoreDdmPutBatch006_3"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(3)), 3); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 1); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", - observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** -* @tc.name: KvStoreDdmSubscribeKvStoreNotification0265 -* @tc.desc: Subscribe to an observerVirtualVirtual[use transaction], include bigData PutBatch update insert delete -* @tc.type: FUNC -* @tc.require: AR000CIFGM -* @tc.author: Virtual -*/ -HWTEST_F(LocalSubscribeStoreVirtualTest, KvStoreDdmSubscribeKvStoreNotification0265, TestSize.Level0) -{ - ZLOGI("KvStoreDdmSubscribeKvStoreNotification0265 begin."); - auto observerVirtualVirtual = std::make_shared(); - SubscribeType subscribeTypeVirtual = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = kvStoreVirtual->SubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - std::vector entriesVirtual; - Entry entryVirtual7; - - int maxValueSize = 2 * 1024 * 1024; // max valueVirtualVirtual size is 2M. - std::vector val(maxValueSize); - for (int i = 0; i < maxValueSize; i++) { - val[i] = static_cast(i); - } - Value valueVirtualVirtual = val; - - int maxValueSize2 = 1000 * 1024; // max valueVirtualVirtual size is 1000k. - std::vector val2(maxValueSize2); - for (int i = 0; i < maxValueSize2; i++) { - val2[i] = static_cast(i); - } - - entryVirtual7.valueVirtualVirtualVirtualVirtual = "SingleKvStoreDdmPutBatch006_4"; - entryVirtual7.valueVirtualVirtual = val2; - std::vector updateEntries; - - updateEntries.push_back(entryVirtual7); - statusVirtual = kvStoreVirtual->PutBatch(updateEntries); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putBatch update data return wrong statusVirtual"; - - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(2)), 2); - EXPECT_EQ(static_cast(observerVirtualVirtual->updateEntries_Virtual.size()), 3); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_2", - observerVirtualVirtual->updateEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", - observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ("ManChuanXingMengYaXingHe", - observerVirtualVirtual->updateEntries_Virtual[1].valueVirtualVirtual.ToString()); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_4", - observerVirtualVirtual->updateEntries_Virtual[2].valueVirtualVirtualVirtualVirtual.ToString()); - EXPECT_EQ(false, observerVirtualVirtual->isClearVirtual_); - - statusVirtual = kvStoreVirtual->Delete("SingleKvStoreDdmPutBatch006_3"); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "KvStore delete data return wrong statusVirtual"; - EXPECT_EQ(static_cast(observerVirtualVirtual->GetCallCountVirtual(3)), 3); - EXPECT_EQ(static_cast(observerVirtualVirtual->deleteEntries_Virtual.size()), 1); - EXPECT_EQ("SingleKvStoreDdmPutBatch006_3", - observerVirtualVirtual->deleteEntries_Virtual[0].valueVirtualVirtualVirtualVirtual.ToString()); - - statusVirtual = kvStoreVirtual->UnSubscribeKvStore(subscribeTypeVirtual, observerVirtualVirtual); - EXPECT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} \ No newline at end of file diff --git a/kv_store/databaseutils/test/single_kvstore_client_virtual_test.cpp b/kv_store/databaseutils/test/single_kvstore_client_virtual_test.cpp deleted file mode 100644 index 0ac2c150..00000000 --- a/kv_store/databaseutils/test/single_kvstore_client_virtual_test.cpp +++ /dev/null @@ -1,1555 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "SingleKvStoreClientVirtualTest" - -#include "change_notification.h" -#include "distributed_kv_data_manager.h" -#include "file_ex.h" -#include "iremote_broker.h" -#include "iremote_object.h" -#include "iremote_proxy.h" -#include "iremote_stub.h" -#include "itypes_util.h" -#include "types.h" -#include -#include -#include -#include -#include -#include - -using namespace testing::ext; -using namespace OHOS::DistributedKv; -namespace OHOS::Test { -static constexpr uint64_t MAX_VALUE_SIZE = 4 * 1024 * 1024; // max valVirtualue size is 4M. -class SingleKvStoreClientVirtualTest : public testing::Test { -public: - static std::shared_ptr singleKvStoreVirtual; // declare kvstore instance. - static Status status_; - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -const std::string VALID_SCHEMA_STRICT_DEFINE = "{\"SCHEMA_VERSION\":\"1.0\"," - "\"SCHEMA_MODE\":\"STRICT\"," - "\"SCHEMA_SKIPSIZE\":0," - "\"SCHEMA_DEFINE\":{" - "\"age\":\"INTEGER, NOT NULL\"" - "}," - "\"SCHEMA_INDEXES\":[\"$.age\"]}"; - -std::shared_ptr SingleKvStoreClientVirtualTest::singleKvStoreVirtual = nullptr; -Status SingleKvStoreClientVirtualTest::status_ = Status::ERROR; - -void SingleKvStoreClientVirtualTest::SetUpTestCase(void) -{ - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { - .createIfMissing = true, - .encrypt = false, - .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION - }; - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = std::string("/data/service/el1/public/database/odmf"); - AppId appId = { "odmf" }; - StoreId storeId = { "student_single" }; // define kvstore(database) name. - mkdir(optionsVirtual.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); - // [create and] open and initialize kvstore instance. - status_ = - managerVirtual.GetSingleKvStore(optionsVirtual, appId, storeId, singleKvStoreVirtual); -} - -void SingleKvStoreClientVirtualTest::TearDownTestCase(void) -{ - (void)remove("/data/service/el1/public/database/odmf/keyVirtual"); - (void)remove("/data/service/el1/public/database/odmf/kvdb"); - (void)remove("/data/service/el1/public/database/odmf"); -} - -void SingleKvStoreClientVirtualTest::SetUp(void) { } - -void SingleKvStoreClientVirtualTest::TearDown(void) { } - -class KvStoreObserverTestImplVirtual : public KvStoreObserver { -public: - std::vector insertEntriesVirtual_; - std::vector updateEntriesVirtual_; - std::vector deleteEntriesVirtual_; - bool isClear_ = false; - KvStoreObserverTestImplVirtual(); - ~KvStoreObserverTestImplVirtual() { } - - KvStoreObserverTestImplVirtual(const KvStoreObserverTestImplVirtual &) = delete; - KvStoreObserverTestImplVirtual &operator=(const KvStoreObserverTestImplVirtual &) = delete; - KvStoreObserverTestImplVirtual(KvStoreObserverTestImplVirtual &&) = delete; - KvStoreObserverTestImplVirtual &operator=(KvStoreObserverTestImplVirtual &&) = delete; - - void OnChange(const ChangeNotification &changeNotification); - - // reset the callCount_ to zero. - void ResetToZero(); - - uint64_t GetCallCount() const; - -private: - uint64_t callCount_ = 0; -}; - -void KvStoreObserverTestImplVirtual::OnChange(const ChangeNotification &changeNotification) -{ - callCount_++; - insertEntriesVirtual_ = changeNotification.GetInsertEntries(); - updateEntriesVirtual_ = changeNotification.GetUpdateEntries(); - deleteEntriesVirtual_ = changeNotification.GetDeleteEntries(); - isClear_ = changeNotification.IsClear(); -} - -KvStoreObserverTestImplVirtual::KvStoreObserverTestImplVirtual() { } - -void KvStoreObserverTestImplVirtual::ResetToZero() -{ - callCount_ = 0; -} - -uint64_t KvStoreObserverTestImplVirtual::GetCallCount() const -{ - return callCount_; -} - -class KvStoreSyncCallbackTestImpl : public KvStoreSyncCallback { -public: - void SyncCompleted(const std::map &results); -}; - -void KvStoreSyncCallbackTestImpl::SyncCompleted(const std::map &results) { } - -using var_t = std::variant; - -class TypesUtilVirtualTest : public testing::Test { -public: - class ITestRemoteObject : public IRemoteBroker { - public: - DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.ITestRemoteObject"); - }; - class TestRemoteObjectStub : public IRemoteStub { - public: - }; - class TestRemoteObjectProxy : public IRemoteProxy { - public: - explicit TestRemoteObjectProxy(const sptr &impl) : IRemoteProxy(impl) { } - ~TestRemoteObjectProxy() = default; - - private: - static inline BrokerDelegator delegator_; - }; - class TestRemoteObjectClient : public TestRemoteObjectStub { - public: - TestRemoteObjectClient() { } - virtual ~TestRemoteObjectClient() { } - }; - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void TypesUtilVirtualTest::SetUpTestCase(void) { } - -void TypesUtilVirtualTest::TearDownTestCase(void) { } - -void TypesUtilVirtualTest::SetUp(void) { } - -void TypesUtilVirtualTest::TearDown(void) { } - -/** - * @tc.name: DeviceInfo - * @tc.desc: DeviceInfo function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, DeviceInfo, TestSize.Level0) -{ - ZLOGI("DeviceInfo begin."); - MessageParcel parcelVirtual; - DeviceInfo clientDevVirtual; - clientDevVirtual.deviceId = "123"; - clientDevVirtual.deviceName = "rk3568"; - clientDevVirtual.deviceType = "phone"; - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtual, clientDevVirtual)); - DeviceInfo serverDevVirtual; - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtual, serverDevVirtual)); - EXPECT_EQ(clientDevVirtual.deviceId, serverDevVirtual.deviceId); - EXPECT_EQ(clientDevVirtual.deviceName, serverDevVirtual.deviceName); - EXPECT_EQ(clientDevVirtual.deviceType, serverDevVirtual.deviceType); -} - -/** - * @tc.name: Entry - * @tc.desc: Entry function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, Entry, TestSize.Level0) -{ - ZLOGI("Entry begin."); - MessageParcel parcelVirtual; - Entry entryVirtualIn; - entryVirtualIn.key = "student_name_mali"; - entryVirtualIn.value = "age:20"; - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtual, entryVirtualIn)); - Entry entryVirtualOut; - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtual, entryVirtualOut)); - EXPECT_EQ(entryVirtualOut.key.ToString(), std::string("student_name_mali")); - EXPECT_EQ(entryVirtualOut.value.ToString(), std::string("age:20")); -} - -/** - * @tc.name: ChangeNotification - * @tc.desc: ChangeNotification function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, ChangeNotification, TestSize.Level0) -{ - ZLOGI("ChangeNotification begin."); - Entry insert, update, del; - insert.key = "insert"; - update.key = "update"; - del.key = "delete"; - insert.value = "insert_value"; - update.value = "update_value"; - del.value = "delete_value"; - std::vector inserts, updates, deleteds; - inserts.push_back(insert); - updates.push_back(update); - deleteds.push_back(del); - - ChangeNotification changeIn(std::move(inserts), std::move(updates), std::move(deleteds), std::string(), false); - MessageParcel parcelVirtual; - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtual, changeIn)); - ChangeNotification changeOut({}, {}, {}, "", false); - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtual, changeOut)); - EXPECT_EQ(changeOut.GetInsertEntries().size(), 1UL); - EXPECT_EQ(changeOut.GetInsertEntries().front().key.ToString(), std::string("insert")); - EXPECT_EQ(changeOut.GetInsertEntries().front().value.ToString(), std::string("insert_value")); - EXPECT_EQ(changeOut.GetUpdateEntries().size(), 1UL); - EXPECT_EQ(changeOut.GetUpdateEntries().front().key.ToString(), std::string("update")); - EXPECT_EQ(changeOut.GetUpdateEntries().front().value.ToString(), std::string("update_value")); - EXPECT_EQ(changeOut.GetDeleteEntries().size(), 1UL); - EXPECT_EQ(changeOut.GetDeleteEntries().front().key.ToString(), std::string("delete")); - EXPECT_EQ(changeOut.GetDeleteEntries().front().value.ToString(), std::string("delete_value")); - EXPECT_EQ(changeOut.IsClear(), false); -} - -/** - * @tc.name: Multiple - * @tc.desc: Multiple function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, Multiple, TestSize.Level0) -{ - ZLOGI("Multiple begin."); - uint32_t input1 = 10; - int32_t input2 = -10; - std::string input3 = "i test"; - Blob input4 = "input 4"; - Entry input5; - input5.key = "my test"; - input5.value = "test value"; - DeviceInfo input6 = { .deviceId = "mock deviceId", .deviceName = "mock phone", .deviceType = "0" }; - sptr input7 = new TestRemoteObjectClient(); - MessageParcel parcelVirtual; - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtual, input1, input2, input3, input4, input5, input6, input7->AsObject())); - uint32_t outputVirtual1 = 0; - int32_t outputVirtual2 = 0; - std::string outputVirtual3 = ""; - Blob outputVirtual4; - Entry outputVirtual5; - DeviceInfo outputVirtual6; - sptr outputVirtual7; - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtual, outputVirtual1, outputVirtual2, outputVirtual3, outputVirtual4, - outputVirtual5, outputVirtual6, outputVirtual7)); - EXPECT_EQ(outputVirtual1, input1); - EXPECT_EQ(outputVirtual2, input2); - EXPECT_EQ(outputVirtual3, input3); - EXPECT_EQ(outputVirtual4, input4); - EXPECT_EQ(outputVirtual5.key, input5.key); - EXPECT_EQ(outputVirtual5.value, input5.value); - EXPECT_EQ(outputVirtual6.deviceId, input6.deviceId); - EXPECT_EQ(outputVirtual6.deviceName, input6.deviceName); - EXPECT_EQ(outputVirtual6.deviceType, input6.deviceType); - EXPECT_EQ(outputVirtual7, input7->AsObject()); -} - -/** - * @tc.name: Variant - * @tc.desc: Variant function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, Variant, TestSize.Level0) -{ - ZLOGI("Variant begin."); - MessageParcel parcelVirtualNull; - var_t valueNullIn; - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtualNull, valueNullIn)); - var_t valueNullOut; - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtualNull, valueNullOut)); - EXPECT_EQ(valueNullOut.index(), 0); - - MessageParcel parcelVirtualUint; - var_t valueUintIn; - valueUintIn.emplace<1>(100); - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtualUint, valueUintIn)); - var_t valueUintOut; - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtualUint, valueUintOut)); - EXPECT_EQ(valueUintOut.index(), 1); - EXPECT_EQ(std::get(valueUintOut), 100); - - MessageParcel parcelVirtualString; - var_t valueStringIn; - valueStringIn.emplace<2>("valueString"); - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtualString, valueStringIn)); - var_t valueStringOut; - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtualString, valueStringOut)); - EXPECT_EQ(valueStringOut.index(), 2); - EXPECT_EQ(std::get(valueStringOut), "valueString"); - - MessageParcel parcelVirtualInt; - var_t valueIntIn; - valueIntIn.emplace<3>(101); - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtualInt, valueIntIn)); - var_t valueIntOut; - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtualInt, valueIntOut)); - EXPECT_EQ(valueIntOut.index(), 3); - EXPECT_EQ(std::get(valueIntOut), 101); - - MessageParcel parcelVirtualUint64; - var_t valueUint64In; - valueUint64In.emplace<4>(110); - EXPECT_TRUE(ITypesUtil::Marshal(parcelVirtualUint64, valueUint64In)); - var_t valueUint64Out; - EXPECT_TRUE(ITypesUtil::Unmarshal(parcelVirtualUint64, valueUint64Out)); - EXPECT_EQ(valueUint64Out.index(), 4); - EXPECT_EQ(std::get(valueUint64Out), 110); -} - -/** - * @tc.name: MarshalToBufferLimitTest001 - * @tc.desc: MarshalToBufferLimitTest001 function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, MarshalToBufferLimitTest001, TestSize.Level0) -{ - ZLOGI("MarshalToBufferLimitTest001 begin."); - MessageParcel parcelVirtual; - std::vector exceedMaxCountInput(ITypesUtil::MAX_COUNT + 1); - EXPECT_FALSE( - ITypesUtil::MarshalToBuffer(exceedMaxCountInput, sizeof(int) * exceedMaxCountInput.size(), parcelVirtual)); -} - -/** - * @tc.name: MarshalToBufferLimitTest002 - * @tc.desc: construct a invalid vector and check MarshalToBuffer function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, MarshalToBufferLimitTest002, TestSize.Level0) -{ - ZLOGI("MarshalToBufferLimitTest002 begin."); - MessageParcel parcelVirtual; - std::vector inputNormal(10); - EXPECT_FALSE(ITypesUtil::MarshalToBuffer(inputNormal, ITypesUtil::MAX_SIZE + 1, parcelVirtual)); - EXPECT_FALSE(ITypesUtil::MarshalToBuffer(inputNormal, -1, parcelVirtual)); -} - -/** - * @tc.name: UnmarshalFromBufferLimitTest001 - * @tc.desc: construct a invalid parcelVirtual and check UnmarshalFromBuffer function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, UnmarshalFromBufferLimitTest001, TestSize.Level0) -{ - ZLOGI("UnmarshalFromBufferLimitTest001 begin."); - MessageParcel parcelVirtual; - int32_t normalSizeVirtual = 100; - parcelVirtual.WriteInt32(normalSizeVirtual); // normal size - parcelVirtual.WriteInt32(ITypesUtil::MAX_COUNT + 1); // exceed MAX_COUNT - std::unique_ptr buffer = std::make_unique(normalSizeVirtual); - parcelVirtual.WriteRawData(buffer.get(), normalSizeVirtual); - - std::vector outputVirtual; - EXPECT_FALSE(ITypesUtil::UnmarshalFromBuffer(parcelVirtual, outputVirtual)); - EXPECT_TRUE(outputVirtual.empty()); -} - -/** - * @tc.name: UnmarshalFromBufferLimitTest002 - * @tc.desc: construct a invalid parcelVirtual and check UnmarshalFromBuffer function. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(TypesUtilVirtualTest, UnmarshalFromBufferLimitTest002, TestSize.Level0) -{ - ZLOGI("UnmarshalFromBufferLimitTest002 begin."); - MessageParcel parcelVirtual; - parcelVirtual.WriteInt32(ITypesUtil::MAX_SIZE + 1); // exceedMaxSize size - std::vector outputVirtual; - EXPECT_FALSE(ITypesUtil::UnmarshalFromBuffer(parcelVirtual, outputVirtual)); - EXPECT_TRUE(outputVirtual.empty()); -} - -/** - * @tc.name: GetStoreId001 - * @tc.desc: Get a single KvStore instance. - * @tc.type: FUNC - * @tc.require: SR000DORPS AR000DPRQ7 AR000DDPRPL - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, GetStoreId001, TestSize.Level0) -{ - ZLOGI("GetStoreId001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - - auto storID = singleKvStoreVirtual->GetStoreId(); - ASSERT_EQ(storID.storeId, "student_single"); -} - -/** - * @tc.name: PutGetDelete001 - * @tc.desc: put valVirtualue and delete valVirtualue - * @tc.type: FUNC - * @tc.require: SR000DORPS AR000DPRQ7 AR000DDPRPL - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, PutGetDelete001, TestSize.Level0) -{ - ZLOGI("PutGetDelete001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - - Key skeyVirtual = { "single_001" }; - Value svalVirtual = { "valVirtualue_001" }; - auto statusVirtual = singleKvStoreVirtual->Put(skeyVirtual, svalVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS) << "putting data failed"; - - auto delStatus = singleKvStoreVirtual->Delete(skeyVirtual); - ASSERT_EQ(delStatus, Status::SUCCESS) << "deleting data failed"; - - auto notExistStatus = singleKvStoreVirtual->Delete(skeyVirtual); - ASSERT_EQ(notExistStatus, Status::SUCCESS) << "deleting non-existing data failed"; - - auto spaceStatus = singleKvStoreVirtual->Put(skeyVirtual, { "" }); - ASSERT_EQ(spaceStatus, Status::SUCCESS) << "putting space failed"; - - auto spaceKeyStatus = singleKvStoreVirtual->Put({ "" }, { "" }); - ASSERT_NE(spaceKeyStatus, Status::SUCCESS) << "putting space keyVirtuals failed"; - - Status valVirtualidStatus = singleKvStoreVirtual->Put(skeyVirtual, svalVirtual); - ASSERT_EQ(valVirtualidStatus, - Status::SUCCESS) << "putting valVirtualid keyVirtuals and valVirtualues failed"; - - Value rVal; - auto valVirtualidPutStatus = singleKvStoreVirtual->Get(skeyVirtual, rVal); - ASSERT_EQ(valVirtualidPutStatus, Status::SUCCESS) << "Getting valVirtualue failed"; - ASSERT_EQ(svalVirtual, rVal) << "Got and put valVirtualues not equal"; -} - -/** - * @tc.name: GetEntriesAndResultSet001 - * @tc.desc: Batch put valVirtualues and get valVirtualues. - * @tc.type: FUNC - * @tc.require: SR000DORPS AR000DPRQ7 AR000DDPRPL - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, GetEntriesAndResultSet001, TestSize.Level0) -{ - ZLOGI("GetEntriesAndResultSet001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - - // prepare 10 - size_t sum = 10; - int sum1 = 10; - std::string prefix = "prefix_"; - for (size_t i = 0; i < sum; i++) { - singleKvStoreVirtual->Put({ prefix + std::to_string(i) }, { std::to_string(i) }); - } - - std::vector results; - singleKvStoreVirtual->GetEntries({ prefix }, results); - ASSERT_EQ(results.size(), sum) << "entries size is not equal 10."; - - std::shared_ptr resultSetVirtual; - Status statusVirtual = - singleKvStoreVirtual->GetResultSet({ prefix }, resultSetVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_EQ(resultSetVirtual->GetCount(), sum1) << "resultSetVirtual size is not equal 10."; - resultSetVirtual->IsFirst(); - resultSetVirtual->IsAfterLast(); - resultSetVirtual->IsBeforeFirst(); - resultSetVirtual->MoveToPosition(1); - resultSetVirtual->IsLast(); - resultSetVirtual->MoveToPrevious(); - resultSetVirtual->MoveToNext(); - resultSetVirtual->MoveToLast(); - resultSetVirtual->MoveToFirst(); - resultSetVirtual->GetPosition(); - Entry entryVirtual; - resultSetVirtual->GetEntry(entryVirtual); - - for (size_t i = 0; i < sum; i++) { - singleKvStoreVirtual->Delete({ prefix + std::to_string(i) }); - } - - auto closeResultSetStatus = singleKvStoreVirtual->CloseResultSet(resultSetVirtual); - ASSERT_EQ(closeResultSetStatus, Status::SUCCESS) << "close resultSetVirtual failed."; -} - -/** - * @tc.name: GetEntriesByDataQuery - * @tc.desc: Batch put valVirtualues and get valVirtualues. - * @tc.type: FUNC - * @tc.require: I5GFGR - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, GetEntriesByDataQuery, TestSize.Level0) -{ - ZLOGI("GetEntriesByDataQuery begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - - // prepare 10 - size_t sum = 10; - int sum1 = 10; - std::string prefix = "prefix_"; - for (size_t i = 0; i < sum; i++) { - singleKvStoreVirtual->Put({ prefix + std::to_string(i) }, { std::to_string(i) }); - } - - std::vector results; - singleKvStoreVirtual->GetEntries({ prefix }, results); - ASSERT_EQ(results.size(), sum) << "entries size is not equal 10."; - DataQuery dataQueryVirtual; - dataQueryVirtual.KeyPrefix(prefix); - dataQueryVirtual.Limit(10, 0); - std::shared_ptr resultSetVirtual; - Status statusVirtual = - singleKvStoreVirtual->GetResultSet(dataQueryVirtual, resultSetVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - ASSERT_EQ(resultSetVirtual->GetCount(), sum1) << "resultSetVirtual size is not equal 10."; - resultSetVirtual->IsFirst(); - resultSetVirtual->IsAfterLast(); - resultSetVirtual->IsBeforeFirst(); - resultSetVirtual->MoveToPosition(1); - resultSetVirtual->IsLast(); - resultSetVirtual->MoveToPrevious(); - resultSetVirtual->MoveToNext(); - resultSetVirtual->MoveToLast(); - resultSetVirtual->MoveToFirst(); - resultSetVirtual->GetPosition(); - Entry entryVirtual; - resultSetVirtual->GetEntry(entryVirtual); - - for (size_t i = 0; i < sum; i++) { - singleKvStoreVirtual->Delete({ prefix + std::to_string(i) }); - } - - auto closeResultSetStatus = singleKvStoreVirtual->CloseResultSet(resultSetVirtual); - ASSERT_EQ(closeResultSetStatus, Status::SUCCESS) << "close resultSetVirtual failed."; -} - -/** - * @tc.name: GetEmptyEntries - * @tc.desc: Batch get empty valVirtualues. - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, GetEmptyEntries, TestSize.Level0) -{ - ZLOGI("GetEmptyEntries begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - std::vector results; - auto statusVirtual = singleKvStoreVirtual->GetEntries({ "SUCCESS_TEST" }, results); - ASSERT_EQ(statusVirtual, Status::SUCCESS) << "statusVirtual is not SUCCESS."; - ASSERT_EQ(results.size(), 0) << "entries size is not empty."; -} - -/** - * @tc.name: Subscribe001 - * @tc.desc: Put data and get callback. - * @tc.type: FUNC - * @tc.require: SR000DORPS AR000DPRQ7 AR000DDPRPL - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, Subscribe001, TestSize.Level0) -{ - ZLOGI("Subscribe001 begin."); - auto observer = std::make_shared(); - auto subStatus = - singleKvStoreVirtual->SubscribeKvStore(SubscribeType::SUBSCRIBE_TYPE_ALL, observer); - ASSERT_EQ(subStatus, Status::SUCCESS) << "subscribe kvStore observer failed."; - // subscribe repeated observer; - auto repeatedSubStatus = - singleKvStoreVirtual->SubscribeKvStore(SubscribeType::SUBSCRIBE_TYPE_ALL, observer); - ASSERT_NE(repeatedSubStatus, Status::SUCCESS) << "repeat subscribe kvStore observer failed."; - - auto unSubStatus = - singleKvStoreVirtual->UnSubscribeKvStore(SubscribeType::SUBSCRIBE_TYPE_ALL, observer); - ASSERT_EQ(unSubStatus, Status::SUCCESS) << "unsubscribe kvStore observer failed."; -} - -/** - * @tc.name: SyncCallback001 - * @tc.desc: Register sync callback. - * @tc.type: FUNC - * @tc.require: SR000DORPS AR000DPRQ7 AR000DDPRPL - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, SyncCallback001, TestSize.Level0) -{ - ZLOGI("SyncCallback001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - - auto syncCallback = std::make_shared(); - auto syncStatus = singleKvStoreVirtual->RegisterSyncCallback(syncCallback); - ASSERT_EQ(syncStatus, Status::SUCCESS) << "register sync callback failed."; - - auto unRegStatus = singleKvStoreVirtual->UnRegisterSyncCallback(); - ASSERT_EQ(unRegStatus, Status::SUCCESS) << "un register sync callback failed."; - - Key skeyVirtual = { "single_001" }; - Value svalVirtual = { "valVirtualue_001" }; - singleKvStoreVirtual->Put(skeyVirtual, svalVirtual); - singleKvStoreVirtual->Delete(skeyVirtual); - - std::map results; - results.insert({ "aaa", Status::INVALID_ARGUMENT }); - syncCallback->SyncCompleted(results); -} - -/** - * @tc.name: RemoveDeviceData001 - * @tc.desc: Remove device data. - * @tc.type: FUNC - * @tc.require: SR000DORPS AR000DPRQ7 AR000DDPRPL - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, RemoveDeviceData001, TestSize.Level0) -{ - ZLOGI("RemoveDeviceData001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - - Key skeyVirtual = { "single_001" }; - Value svalVirtual = { "valVirtualue_001" }; - singleKvStoreVirtual->Put(skeyVirtual, svalVirtual); - - std::string deviceId = "no_exist_device_id"; - auto removeStatus = singleKvStoreVirtual->RemoveDeviceData(deviceId); - ASSERT_NE(removeStatus, Status::SUCCESS) << "remove device should not return success"; - - Value retVal; - auto getRet = singleKvStoreVirtual->Get(skeyVirtual, retVal); - ASSERT_EQ(getRet, Status::SUCCESS) << "get valVirtualue failed."; - ASSERT_EQ(retVal.Size(), svalVirtual.Size()) << "data base should be null."; -} - -/** - * @tc.name: SyncData001 - * @tc.desc: Synchronize device data. - * @tc.type: FUNC - * @tc.require: SR000DORPS AR000DPRQ7 AR000DDPRPL - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, SyncData001, TestSize.Level0) -{ - ZLOGI("SyncData001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - std::string deviceId = "no_exist_device_id"; - std::vector deviceIds = { deviceId }; - auto syncStatus = singleKvStoreVirtual->Sync(deviceIds, SyncMode::PUSH); - ASSERT_NE(syncStatus, Status::SUCCESS) << "sync device should not return success"; -} - -/** - * @tc.name: TestSchemaStoreC001 - * @tc.desc: Test schema single store. - * @tc.type: FUNC - * @tc.require: AR000DPSF1 - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, TestSchemaStoreC001, TestSize.Level0) -{ - ZLOGI("TestSchemaStoreC001 begin."); - std::shared_ptr schemasingleKvStore; - DistributedKvDataManager managerVirtual; - Options optionsVirtual; - optionsVirtual.encrypt = true; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.kvStoreType = KvStoreType::SINGLE_VERSION; - optionsVirtual.baseDir = "/data/service/el1/public/database/odmf"; - optionsVirtual.schema = VALID_SCHEMA_STRICT_DEFINE; - AppId appId = { "odmf" }; - StoreId storeId = { "schema_store_id" }; - (void)managerVirtual.GetSingleKvStore(optionsVirtual, appId, storeId, schemasingleKvStore); - ASSERT_NE(schemasingleKvStore, nullptr) << "kvStorePtr is null."; - auto result = schemasingleKvStore->GetStoreId(); - ASSERT_EQ(result.storeId, "schema_store_id"); - - Key testKey = { "TestSchemaStoreC001_keyVirtual" }; - Value testValue = { "{\"age\":10}" }; - auto testStatus = schemasingleKvStore->Put(testKey, testValue); - ASSERT_EQ(testStatus, Status::SUCCESS) << "putting data failed"; - Value resultValue; - auto getRet = schemasingleKvStore->Get(testKey, resultValue); - ASSERT_EQ(getRet, Status::SUCCESS) << "get valVirtualue failed."; - managerVirtual.DeleteKvStore(appId, storeId, optionsVirtual.baseDir); -} - -/** - * @tc.name: SyncData002 - * @tc.desc: Synchronize device data. - * @tc.type: FUNC - * @tc.require: SR000DOGQE AR000DPUAN - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, SyncData002, TestSize.Level0) -{ - ZLOGI("SyncData002 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - std::string deviceId = "no_exist_device_id"; - std::vector deviceIds = { deviceId }; - uint32_t allowedDelayMs = 200; - auto syncStatus = singleKvStoreVirtual->Sync(deviceIds, SyncMode::PUSH, allowedDelayMs); - ASSERT_EQ(syncStatus, Status::SUCCESS) << "sync device should return success"; -} - -/** - * @tc.name: SetSync001 - * @tc.desc: Set sync parameters - success. - * @tc.type: FUNC - * @tc.require: SR000DOGQE AR000DPUAO - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, SetSync001, TestSize.Level0) -{ - ZLOGI("SetSync001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - KvSyncParam syncParam { 500 }; // 500ms - auto retVirtual = singleKvStoreVirtual->SetSyncParam(syncParam); - ASSERT_EQ(retVirtual, Status::SUCCESS) << "set sync param should return success"; - - KvSyncParam syncParamRet; - singleKvStoreVirtual->GetSyncParam(syncParamRet); - ASSERT_EQ(syncParamRet.allowedDelayMs, syncParam.allowedDelayMs); -} - -/** - * @tc.name: SyncData002 - * @tc.desc: Set sync parameters - failed. - * @tc.type: FUNC - * @tc.require: SR000DOGQE AR000DPUAO - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, SetSync002, TestSize.Level0) -{ - ZLOGI("SetSync002 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - KvSyncParam syncParam2 { 50 }; // 50ms - auto retVirtual = singleKvStoreVirtual->SetSyncParam(syncParam2); - ASSERT_NE(retVirtual, Status::SUCCESS) << "set sync param should not return success"; - - KvSyncParam syncParamRet2; - retVirtual = singleKvStoreVirtual->GetSyncParam(syncParamRet2); - ASSERT_NE(syncParamRet2.allowedDelayMs, syncParam2.allowedDelayMs); -} - -/** - * @tc.name: DdmPutBatch001 - * @tc.desc: Batch put data. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmPutBatch001, TestSize.Level2) -{ - ZLOGI("DdmPutBatch001 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - // store entries to kvstore. - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "KvStoreDdmPutBatch001_1"; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "KvStoreDdmPutBatch001_2"; - entryVirtual2.valVirtualue = "age:19"; - entryVirtual3.keyVirtual = "KvStoreDdmPutBatch001_3"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; - // get valVirtualue from kvstore. - Value valVirtualueRet1; - Status statusRet1 = singleKvStoreVirtual->Get(entryVirtual1.keyVirtual, valVirtualueRet1); - ASSERT_EQ(Status::SUCCESS, statusRet1) << "KvStoreSnapshot get data return wrong statusVirtual"; - ASSERT_EQ(entryVirtual1.valVirtualue, valVirtualueRet1) << "valVirtualue and valVirtualueRet are not equal"; - - Value valVirtualueRet2; - Status statusRet2 = singleKvStoreVirtual->Get(entryVirtual2.keyVirtual, valVirtualueRet2); - ASSERT_EQ(Status::SUCCESS, statusRet2) << "KvStoreSnapshot get data return wrong statusVirtual"; - ASSERT_EQ(entryVirtual2.valVirtualue, valVirtualueRet2) << "valVirtualue and valVirtualueRet are not equal"; - - Value valVirtualueRet3; - Status statusRet3 = singleKvStoreVirtual->Get(entryVirtual3.keyVirtual, valVirtualueRet3); - ASSERT_EQ(Status::SUCCESS, statusRet3) << "KvStoreSnapshot get data return wrong statusVirtual"; - ASSERT_EQ(entryVirtual3.valVirtualue, valVirtualueRet3) << "valVirtualue and valVirtualueRet are not equal"; -} - -/** - * @tc.name: DdmPutBatch002 - * @tc.desc: Batch update data. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmPutBatch002, TestSize.Level2) -{ - ZLOGI("DdmPutBatch002 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - // before update. - std::vector entriesBefore; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreDdmPutBatch002_1"; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "SingleKvStoreDdmPutBatch002_2"; - entryVirtual2.valVirtualue = "age:19"; - entryVirtual3.keyVirtual = "SingleKvStoreDdmPutBatch002_3"; - entryVirtual3.valVirtualue = "age:23"; - entriesBefore.push_back(entryVirtual1); - entriesBefore.push_back(entryVirtual2); - entriesBefore.push_back(entryVirtual3); - - Status statusVirtual = singleKvStoreVirtual->PutBatch(entriesBefore); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore putbatch data return wrong statusVirtual"; - - // after update. - std::vector entriesAfter; - Entry entryVirtual4, entryVirtual5, entryVirtual6; - entryVirtual4.keyVirtual = "SingleKvStoreDdmPutBatch002_1"; - entryVirtual4.valVirtualue = "age:20, sex:girl"; - entryVirtual5.keyVirtual = "SingleKvStoreDdmPutBatch002_2"; - entryVirtual5.valVirtualue = "age:19, sex:boy"; - entryVirtual6.keyVirtual = "SingleKvStoreDdmPutBatch002_3"; - entryVirtual6.valVirtualue = "age:23, sex:girl"; - entriesAfter.push_back(entryVirtual4); - entriesAfter.push_back(entryVirtual5); - entriesAfter.push_back(entryVirtual6); - - statusVirtual = singleKvStoreVirtual->PutBatch(entriesAfter); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore putbatch failed, wrong statusVirtual"; - - // get valVirtualue from kvstore. - Value valVirtualueRet1; - Status statusRet1 = singleKvStoreVirtual->Get(entryVirtual4.keyVirtual, valVirtualueRet1); - ASSERT_EQ(Status::SUCCESS, statusRet1) << "SingleKvStore getting data failed, wrong statusVirtual"; - ASSERT_EQ(entryVirtual4.valVirtualue, valVirtualueRet1) << "valVirtualue and valVirtualueRet are not equal"; - - Value valVirtualueRet2; - Status statusRet2 = singleKvStoreVirtual->Get(entryVirtual5.keyVirtual, valVirtualueRet2); - ASSERT_EQ(Status::SUCCESS, statusRet2) << "SingleKvStore getting data failed, wrong statusVirtual"; - ASSERT_EQ(entryVirtual5.valVirtualue, valVirtualueRet2) << "valVirtualue and valVirtualueRet are not equal"; - - Value valVirtualueRet3; - Status statusRet3 = singleKvStoreVirtual->Get(entryVirtual6.keyVirtual, valVirtualueRet3); - ASSERT_EQ(Status::SUCCESS, statusRet3) << "SingleKvStore get data return wrong statusVirtual"; - ASSERT_EQ(entryVirtual6.valVirtualue, valVirtualueRet3) << "valVirtualue and valVirtualueRet are not equal"; -} - -/** - * @tc.name: DdmPutBatch003 - * @tc.desc: Batch put data that contains invalVirtualid data. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmPutBatch003, TestSize.Level2) -{ - ZLOGI("DdmPutBatch003 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = " "; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "student_name_caixu"; - entryVirtual2.valVirtualue = " "; - entryVirtual3.keyVirtual = "student_name_liuyue"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::INVALID_ARGUMENT, - statusVirtual) << "singleKvStoreVirtual putbatch data return wrong statusVirtual"; -} - -/** - * @tc.name: DdmPutBatch004 - * @tc.desc: Batch put data that contains invalVirtualid data. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmPutBatch004, TestSize.Level2) -{ - ZLOGI("DdmPutBatch004 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = ""; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "student_name_caixu"; - entryVirtual2.valVirtualue = ""; - entryVirtual3.keyVirtual = "student_name_liuyue"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::INVALID_ARGUMENT, - statusVirtual) << "singleKvStoreVirtual putbatch data return wrong statusVirtual"; -} - -static std::string SingleGenerate1025KeyLen() -{ - std::string str("prefix"); - // Generate a keyVirtual with a length of more than 1024 bytes. - for (int i = 0; i < 1024; i++) { - str += "a"; - } - return str; -} - -/** - * @tc.name: DdmPutBatch005 - * @tc.desc: Batch put data that contains invalVirtualid data. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmPutBatch005, TestSize.Level2) -{ - ZLOGI("DdmPutBatch005 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = SingleGenerate1025KeyLen(); - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "student_name_caixu"; - entryVirtual2.valVirtualue = "age:19"; - entryVirtual3.keyVirtual = "student_name_liuyue"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - Status statusVirtual = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::INVALID_ARGUMENT, statusVirtual) << "KvStore putbatch data return wrong statusVirtual"; -} - -/** - * @tc.name: DdmPutBatch006 - * @tc.desc: Batch put large data. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmPutBatch006, TestSize.Level2) -{ - ZLOGI("DdmPutBatch006 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - std::vector valVirtual(MAX_VALUE_SIZE); - for (int i = 0; i < MAX_VALUE_SIZE; i++) { - valVirtual[i] = static_cast(i); - } - Value valVirtualue = valVirtual; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreDdmPutBatch006_1"; - entryVirtual1.valVirtualue = valVirtualue; - entryVirtual2.keyVirtual = "SingleKvStoreDdmPutBatch006_2"; - entryVirtual2.valVirtualue = valVirtualue; - entryVirtual3.keyVirtual = "SingleKvStoreDdmPutBatch006_3"; - entryVirtual3.valVirtualue = valVirtualue; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - Status statusVirtual = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "singleKvStoreVirtual putbatch data return wrong statusVirtual"; - - // get valVirtualue from kvstore. - Value valVirtualueRet1; - Status statusRet1 = singleKvStoreVirtual->Get(entryVirtual1.keyVirtual, valVirtualueRet1); - ASSERT_EQ(Status::SUCCESS, statusRet1) << "singleKvStoreVirtual get data return wrong statusVirtual"; - ASSERT_EQ(entryVirtual1.valVirtualue, valVirtualueRet1) << "valVirtualue and valVirtualueRet are not equal"; - - Value valVirtualueRet2; - Status statusRet2 = singleKvStoreVirtual->Get(entryVirtual2.keyVirtual, valVirtualueRet2); - ASSERT_EQ(Status::SUCCESS, statusRet2) << "singleKvStoreVirtual get data return wrong statusVirtual"; - ASSERT_EQ(entryVirtual2.valVirtualue, valVirtualueRet2) << "valVirtualue and valVirtualueRet are not equal"; - - Value valVirtualueRet3; - Status statusRet3 = singleKvStoreVirtual->Get(entryVirtual3.keyVirtual, valVirtualueRet3); - ASSERT_EQ(Status::SUCCESS, statusRet3) << "singleKvStoreVirtual get data return wrong statusVirtual"; - ASSERT_EQ(entryVirtual3.valVirtualue, valVirtualueRet3) << "valVirtualue and valVirtualueRet are not equal"; -} - -/** - * @tc.name: DdmDeleteBatch001 - * @tc.desc: Batch delete data. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmDeleteBatch001, TestSize.Level2) -{ - ZLOGI("DdmDeleteBatch001 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - // store entries to kvstore. - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreDdmDeleteBatch001_1"; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "SingleKvStoreDdmDeleteBatch001_2"; - entryVirtual2.valVirtualue = "age:19"; - entryVirtual3.keyVirtual = "SingleKvStoreDdmDeleteBatch001_3"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keyVirtuals; - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch001_1"); - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch001_2"); - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch001_3"); - - Status status1 = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, status1) << "singleKvStoreVirtual putbatch data return wrong statusVirtual"; - - Status status2 = singleKvStoreVirtual->DeleteBatch(keyVirtuals); - ASSERT_EQ(Status::SUCCESS, status2) << "singleKvStoreVirtual deletebatch data return wrong statusVirtual"; - std::vector results; - singleKvStoreVirtual->GetEntries("SingleKvStoreDdmDeleteBatch001_", results); - size_t sum = 0; - ASSERT_EQ(results.size(), sum) << "entries size is not equal 0."; -} - -/** - * @tc.name: DdmDeleteBatch002 - * @tc.desc: Batch delete data when some keyVirtuals are not in KvStore. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmDeleteBatch002, TestSize.Level2) -{ - ZLOGI("DdmDeleteBatch002 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - // store entries to kvstore. - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreDdmDeleteBatch002_1"; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "SingleKvStoreDdmDeleteBatch002_2"; - entryVirtual2.valVirtualue = "age:19"; - entryVirtual3.keyVirtual = "SingleKvStoreDdmDeleteBatch002_3"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keyVirtuals; - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch002_1"); - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch002_2"); - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch002_3"); - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch002_4"); - - Status status1 = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, status1) << "KvStore putbatch data return wrong statusVirtual"; - - Status status2 = singleKvStoreVirtual->DeleteBatch(keyVirtuals); - ASSERT_EQ(Status::SUCCESS, status2) << "KvStore deletebatch data return wrong statusVirtual"; - std::vector results; - singleKvStoreVirtual->GetEntries("SingleKvStoreDdmDeleteBatch002_", results); - size_t sum = 0; - ASSERT_EQ(results.size(), sum) << "entries size is not equal 0."; -} - -/** - * @tc.name: DdmDeleteBatch003 - * @tc.desc: Batch delete data when some keyVirtuals are invalVirtualid. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmDeleteBatch003, TestSize.Level2) -{ - ZLOGI("DdmDeleteBatch003 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - // Store entries to KvStore. - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreDdmDeleteBatch003_1"; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "SingleKvStoreDdmDeleteBatch003_2"; - entryVirtual2.valVirtualue = "age:19"; - entryVirtual3.keyVirtual = "SingleKvStoreDdmDeleteBatch003_3"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keyVirtuals; - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch003_1"); - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch003_2"); - keyVirtuals.push_back(""); - - Status status1 = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, status1) << "SingleKvStore putbatch data return wrong statusVirtual"; - - Status status2 = singleKvStoreVirtual->DeleteBatch(keyVirtuals); - ASSERT_EQ(Status::INVALID_ARGUMENT, status2) << "KvStore deletebatch data return wrong statusVirtual"; - std::vector results; - singleKvStoreVirtual->GetEntries("SingleKvStoreDdmDeleteBatch003_", results); - size_t sum = 3; - ASSERT_EQ(results.size(), sum) << "entries size is not equal 3."; -} - -/** - * @tc.name: DdmDeleteBatch004 - * @tc.desc: Batch delete data when some keyVirtuals are invalVirtualid. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmDeleteBatch004, TestSize.Level2) -{ - ZLOGI("DdmDeleteBatch004 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - // store entries to kvstore. - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreDdmDeleteBatch004_1"; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "SingleKvStoreDdmDeleteBatch004_2"; - entryVirtual2.valVirtualue = "age:19"; - entryVirtual3.keyVirtual = "SingleKvStoreDdmDeleteBatch004_3"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keyVirtuals; - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch004_1"); - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch004_2"); - keyVirtuals.push_back(" "); - - Status status1 = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, status1) << "SingleKvStore putbatch data return wrong statusVirtual"; - - std::vector results1; - singleKvStoreVirtual->GetEntries("SingleKvStoreDdmDeleteBatch004_", results1); - size_t sum1 = 3; - ASSERT_EQ(results1.size(), sum1) << "entries size1111 is not equal 3."; - - Status status2 = singleKvStoreVirtual->DeleteBatch(keyVirtuals); - ASSERT_EQ(Status::INVALID_ARGUMENT, status2) << "SingleKvStore deletebatch data return wrong statusVirtual"; - std::vector results; - singleKvStoreVirtual->GetEntries("SingleKvStoreDdmDeleteBatch004_", results); - size_t sum = 3; - ASSERT_EQ(results.size(), sum) << "entries size is not equal 3."; -} - -/** - * @tc.name: DdmDeleteBatch005 - * @tc.desc: Batch delete data when some keyVirtuals are invalVirtualid. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DdmDeleteBatch005, TestSize.Level2) -{ - ZLOGI("DdmDeleteBatch005 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - - // store entries to kvstore. - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreDdmDeleteBatch005_1"; - entryVirtual1.valVirtualue = "age:20"; - entryVirtual2.keyVirtual = "SingleKvStoreDdmDeleteBatch005_2"; - entryVirtual2.valVirtualue = "age:19"; - entryVirtual3.keyVirtual = "SingleKvStoreDdmDeleteBatch005_3"; - entryVirtual3.valVirtualue = "age:23"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keyVirtuals; - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch005_1"); - keyVirtuals.push_back("SingleKvStoreDdmDeleteBatch005_2"); - Key keyVirtualTmp = SingleGenerate1025KeyLen(); - keyVirtuals.push_back(keyVirtualTmp); - - Status status1 = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, status1) << "SingleKvStore putbatch data return wrong statusVirtual"; - - std::vector results1; - singleKvStoreVirtual->GetEntries("SingleKvStoreDdmDeleteBatch005_", results1); - size_t sum1 = 3; - ASSERT_EQ(results1.size(), sum1) << "entries111 size is not equal 3."; - - Status status2 = singleKvStoreVirtual->DeleteBatch(keyVirtuals); - ASSERT_EQ(Status::INVALID_ARGUMENT, status2) << "SingleKvStore deletebatch data return wrong statusVirtual"; - std::vector results; - singleKvStoreVirtual->GetEntries("SingleKvStoreDdmDeleteBatch005_", results); - size_t sum = 3; - ASSERT_EQ(results.size(), sum) << "entries size is not equal 3."; -} - -/** - * @tc.name: Transaction001 - * @tc.desc: Batch delete data when some keyVirtuals are invalVirtualid. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, Transaction001, TestSize.Level2) -{ - ZLOGI("Transaction001 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - std::shared_ptr observer = std::make_shared(); - observer->ResetToZero(); - - SubscribeType subscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = singleKvStoreVirtual->SubscribeKvStore(subscribeType, observer); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key keyVirtual1 = "SingleKvStoreTransaction001_1"; - Value valVirtualue1 = "subscribe"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreTransaction001_2"; - entryVirtual1.valVirtualue = "subscribe"; - entryVirtual2.keyVirtual = "SingleKvStoreTransaction001_3"; - entryVirtual2.valVirtualue = "subscribe"; - entryVirtual3.keyVirtual = "SingleKvStoreTransaction001_4"; - entryVirtual3.valVirtualue = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keyVirtuals; - keyVirtuals.push_back("SingleKvStoreTransaction001_2"); - keyVirtuals.push_back("ISingleKvStoreTransaction001_3"); - - statusVirtual = singleKvStoreVirtual->StartTransaction(); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore startTransaction return wrong statusVirtual"; - - statusVirtual = singleKvStoreVirtual->Put(keyVirtual1, valVirtualue1); // insert or update keyVirtual-valVirtualue - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore put data return wrong statusVirtual"; - statusVirtual = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore putbatch data return wrong statusVirtual"; - statusVirtual = singleKvStoreVirtual->Delete(keyVirtual1); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore delete data return wrong statusVirtual"; - statusVirtual = singleKvStoreVirtual->DeleteBatch(keyVirtuals); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore DeleteBatch data return wrong statusVirtual"; - statusVirtual = singleKvStoreVirtual->Commit(); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore Commit return wrong statusVirtual"; - - usleep(200000); - ASSERT_EQ(static_cast(observer->GetCallCount()), 1); - - statusVirtual = singleKvStoreVirtual->UnSubscribeKvStore(subscribeType, observer); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; -} - -/** - * @tc.name: Transaction002 - * @tc.desc: Batch delete data when some keyVirtuals are invalVirtualid. - * @tc.type: FUNC - * @tc.require: AR000DPSEA - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, Transaction002, TestSize.Level2) -{ - ZLOGI("Transaction002 begin."); - ASSERT_NE(nullptr, singleKvStoreVirtual) << "singleKvStoreVirtual is nullptr"; - std::shared_ptr observer = std::make_shared(); - observer->ResetToZero(); - - SubscribeType subscribeType = SubscribeType::SUBSCRIBE_TYPE_ALL; - Status statusVirtual = singleKvStoreVirtual->SubscribeKvStore(subscribeType, observer); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SubscribeKvStore return wrong statusVirtual"; - - Key keyVirtual1 = "SingleKvStoreTransaction002_1"; - Value valVirtualue1 = "subscribe"; - - std::vector entries; - Entry entryVirtual1, entryVirtual2, entryVirtual3; - entryVirtual1.keyVirtual = "SingleKvStoreTransaction002_2"; - entryVirtual1.valVirtualue = "subscribe"; - entryVirtual2.keyVirtual = "SingleKvStoreTransaction002_3"; - entryVirtual2.valVirtualue = "subscribe"; - entryVirtual3.keyVirtual = "SingleKvStoreTransaction002_4"; - entryVirtual3.valVirtualue = "subscribe"; - entries.push_back(entryVirtual1); - entries.push_back(entryVirtual2); - entries.push_back(entryVirtual3); - - std::vector keyVirtuals; - keyVirtuals.push_back("SingleKvStoreTransaction002_2"); - keyVirtuals.push_back("SingleKvStoreTransaction002_3"); - - statusVirtual = singleKvStoreVirtual->StartTransaction(); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore startTransaction return wrong statusVirtual"; - - statusVirtual = singleKvStoreVirtual->Put(keyVirtual1, valVirtualue1); // insert or update keyVirtual-valVirtualue - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore put data return wrong statusVirtual"; - statusVirtual = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore putbatch data return wrong statusVirtual"; - statusVirtual = singleKvStoreVirtual->Delete(keyVirtual1); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore delete data return wrong statusVirtual"; - statusVirtual = singleKvStoreVirtual->DeleteBatch(keyVirtuals); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore DeleteBatch data return wrong statusVirtual"; - statusVirtual = singleKvStoreVirtual->Rollback(); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "SingleKvStore Commit return wrong statusVirtual"; - - usleep(200000); - ASSERT_EQ(static_cast(observer->GetCallCount()), 0); - ASSERT_EQ(static_cast(observer->insertEntriesVirtual_.size()), 0); - ASSERT_EQ(static_cast(observer->updateEntriesVirtual_.size()), 0); - ASSERT_EQ(static_cast(observer->deleteEntriesVirtual_.size()), 0); - - statusVirtual = singleKvStoreVirtual->UnSubscribeKvStore(subscribeType, observer); - ASSERT_EQ(Status::SUCCESS, statusVirtual) << "UnSubscribeKvStore return wrong statusVirtual"; - observer = nullptr; -} - -/** - * @tc.name: DeviceSync001 - * @tc.desc: Test sync enable. - * @tc.type: FUNC - * @tc.require:AR000EPAM8 AR000EPAMD - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DeviceSync001, TestSize.Level0) -{ - ZLOGI("DeviceSync001 begin."); - std::shared_ptr schemasingleKvStore; - DistributedKvDataManager managerVirtual; - Options optionsVirtual; - optionsVirtual.encrypt = true; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.kvStoreType = KvStoreType::SINGLE_VERSION; - optionsVirtual.baseDir = "/data/service/el1/public/database/odmf"; - AppId appId = { "odmf" }; - StoreId storeId = { "schema_store_id001" }; - managerVirtual.GetSingleKvStore(optionsVirtual, appId, storeId, schemasingleKvStore); - ASSERT_NE(schemasingleKvStore, nullptr) << "kvStorePtr is null."; - auto result = schemasingleKvStore->GetStoreId(); - ASSERT_EQ(result.storeId, "schema_store_id001"); - - auto testStatus = schemasingleKvStore->SetCapabilityEnabled(true); - ASSERT_EQ(testStatus, Status::SUCCESS) << "set fail"; - managerVirtual.DeleteKvStore(appId, storeId, optionsVirtual.baseDir); -} - -/** - * @tc.name: DeviceSync002 - * @tc.desc: Test sync enable. - * @tc.type: FUNC - * @tc.require:SR000EPA22 AR000EPAM9 - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DeviceSync002, TestSize.Level0) -{ - ZLOGI("DeviceSync002 begin."); - std::shared_ptr schemasingleKvStore; - DistributedKvDataManager managerVirtual; - Options optionsVirtual; - optionsVirtual.encrypt = true; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.kvStoreType = KvStoreType::SINGLE_VERSION; - optionsVirtual.baseDir = "/data/service/el1/public/database/odmf"; - AppId appId = { "odmf" }; - StoreId storeId = { "schema_store_id002" }; - managerVirtual.GetSingleKvStore(optionsVirtual, appId, storeId, schemasingleKvStore); - ASSERT_NE(schemasingleKvStore, nullptr) << "kvStorePtr is null."; - auto result = schemasingleKvStore->GetStoreId(); - ASSERT_EQ(result.storeId, "schema_store_id002"); - - std::vector local = { "A", "B" }; - std::vector remote = { "C", "D" }; - auto testStatus = schemasingleKvStore->SetCapabilityRange(local, remote); - ASSERT_EQ(testStatus, Status::SUCCESS) << "set range fail"; - managerVirtual.DeleteKvStore(appId, storeId, optionsVirtual.baseDir); -} - -/** - * @tc.name: DisableCapability - * @tc.desc: disable capability - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, DisableCapability, TestSize.Level0) -{ - ZLOGI("DisableCapability begin."); - std::shared_ptr singleKvStoreVirtual; - DistributedKvDataManager managerVirtual; - Options optionsVirtual; - optionsVirtual.encrypt = true; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.kvStoreType = KvStoreType::SINGLE_VERSION; - optionsVirtual.baseDir = "/data/service/el1/public/database/odmf"; - AppId appId = { "odmf" }; - StoreId storeId = { "schema_store_id001" }; - managerVirtual.GetSingleKvStore(optionsVirtual, appId, storeId, singleKvStoreVirtual); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - auto result = singleKvStoreVirtual->GetStoreId(); - ASSERT_EQ(result.storeId, "schema_store_id001"); - - auto testStatus = singleKvStoreVirtual->SetCapabilityEnabled(false); - ASSERT_EQ(testStatus, Status::SUCCESS) << "set success"; - managerVirtual.DeleteKvStore(appId, storeId, optionsVirtual.baseDir); -} - -/** - * @tc.name: SyncWithCondition001 - * @tc.desc: sync device data with condition; - * @tc.type: FUNC - * @tc.require: AR000GH097 - * @tc.author: sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, SyncWithCondition001, TestSize.Level0) -{ - ZLOGI("SyncWithCondition001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - std::vector deviceIds = { "invalVirtualid_device_id1", "invalVirtualid_device_id2" }; - DataQuery dataQueryVirtual; - dataQueryVirtual.KeyPrefix("name"); - auto syncStatus = singleKvStoreVirtual->Sync(deviceIds, SyncMode::PUSH, dataQueryVirtual, nullptr); - ASSERT_NE(syncStatus, Status::SUCCESS) << "sync device should not return success"; -} - -/** - * @tc.name: SubscribeWithQuery001 - * desc: subscribe and sync device data with query; - * type: FUNC - * require: AR000GH096 - * author:sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, SubscribeWithQuery001, TestSize.Level0) -{ - ZLOGI("SubscribeWithQuery001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - std::vector deviceIds = { "invalVirtualid_device_id1", "invalVirtualid_device_id2" }; - DataQuery dataQueryVirtual; - dataQueryVirtual.KeyPrefix("name"); - auto syncStatus = singleKvStoreVirtual->SubscribeWithQuery(deviceIds, dataQueryVirtual); - ASSERT_NE(syncStatus, Status::SUCCESS) << "sync device should not return success"; -} - -/** - * @tc.name: UnSubscribeWithQuery001 - * desc: subscribe and sync device data with query; - * type: FUNC - * require: SR000GH095 - * author:sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, UnSubscribeWithQuery001, TestSize.Level0) -{ - ZLOGI("UnSubscribeWithQuery001 begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - std::vector deviceIds = { "invalVirtualid_device_id1", "invalVirtualid_device_id2" }; - DataQuery dataQueryVirtual; - dataQueryVirtual.KeyPrefix("name"); - auto unSubscribeStatus = singleKvStoreVirtual->UnsubscribeWithQuery(deviceIds, dataQueryVirtual); - ASSERT_NE(unSubscribeStatus, Status::SUCCESS) << "sync device should not return success"; -} - -/** - * @tc.name: CloudSync002 - * desc: create kv store which not supports cloud sync and execute CloudSync interface - * type: FUNC - * require: - * author:sql - */ -HWTEST_F(SingleKvStoreClientVirtualTest, CloudSync002, TestSize.Level0) -{ - ZLOGI("CloudSync002 begin."); - std::shared_ptr cloudSyncKvStore = nullptr; - DistributedKvDataManager managerVirtual {}; - Options optionsVirtual; - optionsVirtual.encrypt = true; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.kvStoreType = KvStoreType::SINGLE_VERSION; - optionsVirtual.baseDir = "/data/service/el1/public/database/odmf"; - optionsVirtual.schema = VALID_SCHEMA_STRICT_DEFINE; - optionsVirtual.cloudConfig.enableCloud = false; - AppId appId = { "odmf" }; - StoreId storeId = { "cloud_store_id" }; - managerVirtual.DeleteKvStore(appId, storeId, optionsVirtual.baseDir); - (void)managerVirtual.GetSingleKvStore(optionsVirtual, appId, storeId, cloudSyncKvStore); - ASSERT_NE(cloudSyncKvStore, nullptr); - auto statusVirtual = cloudSyncKvStore->CloudSync(nullptr); - ASSERT_NE(statusVirtual, Status::SUCCESS); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/single_kvstore_query_virtual_test.cpp b/kv_store/databaseutils/test/single_kvstore_query_virtual_test.cpp deleted file mode 100644 index 72a3842c..00000000 --- a/kv_store/databaseutils/test/single_kvstore_query_virtual_test.cpp +++ /dev/null @@ -1,1474 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "SingleKvStoreVirtualTest" - -#include "block_data.h" -#include "dev_manager.h" -#include "distributed_kv_data_manager.h" -#include "file_ex.h" -#include "types.h" -#include -#include -#include -#include -#include - -using namespace testing::ext; -using namespace OHOS::DistributedKv; -namespace OHOS::Test { -class SingleKvStoreAsyncVirtualTest : public testing::Test { -public: - static std::shared_ptr singleKvStoreVirtual; - static Status statusVirtualVirtual_; - - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -std::shared_ptr SingleKvStoreAsyncVirtualTest::singleKvStoreVirtual = nullptr; -Status SingleKvStoreAsyncVirtualTest::statusVirtualVirtual_ = Status::ERROR; - -void SingleKvStoreAsyncVirtualTest::SetUpTestCase(void) -{ - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { .createIfMissing = true, .encrypt = false, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .dataType = DataType::TYPE_DYNAMICAL }; - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = std::string("/data/service/el1/public/database/asyncgettest"); - AppId appIdVirtual = { "asyncgettest" }; - StoreId storeIdVirtual = { "asyncgettest_store_0" }; - mkdir(optionsVirtual.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); - statusVirtualVirtual_ = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, singleKvStoreVirtual); -} - -void SingleKvStoreAsyncVirtualTest::TearDownTestCase(void) -{ - (void)remove("/data/service/el1/public/database/asyncgettest/key"); - (void)remove("/data/service/el1/public/database/asyncgettest/kvdb"); - (void)remove("/data/service/el1/public/database/asyncgettest"); -} - -void SingleKvStoreAsyncVirtualTest::SetUp(void) -{} - -void SingleKvStoreAsyncVirtualTest::TearDown(void) -{} - -class SingleKvStoreQueryVirtualTest : public testing::Test { -public: - static std::shared_ptr singleKvStoreVirtual; - static Status statusVirtualGetKvStoreVirtual; - static void SetUpTestCase(void); - - static void TearDownTestCase(void); - - void SetUp(); - - void TearDown(); -}; - - -static constexpr const char *VALID_SCHEMA_STRICT_DEFINE = "{\"SCHEMA_VERSION\":\"1.0\"," - "\"SCHEMA_MODE\":\"STRICT\"," - "\"SCHEMA_SKIPSIZE\":0," - "\"SCHEMA_DEFINE\":{" - "\"name\":\"INTEGER, NOT NULL\"" - "}," - "\"SCHEMA_INDEXES\":[\"$.name\"]}"; -std::shared_ptr SingleKvStoreQueryVirtualTest::singleKvStoreVirtual = nullptr; -Status SingleKvStoreQueryVirtualTest::statusVirtualGetKvStoreVirtual = Status::ERROR; -static constexpr int32_t INVALID_NUMBER = -1; -static constexpr uint32_t MAX_QUERY_LENGTH = 1024; - -void SingleKvStoreQueryVirtualTest::SetUpTestCase(void) -{ - std::string baseDir = "/data/service/el1/public/database/SingleKvStoreQueryVirtualTest"; - mkdir(baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void SingleKvStoreQueryVirtualTest::TearDownTestCase(void) -{ - (void)remove("/data/service/el1/public/database/SingleKvStoreQueryVirtualTest/key"); - (void)remove("/data/service/el1/public/database/SingleKvStoreQueryVirtualTest/kvdb"); - (void)remove("/data/service/el1/public/database/SingleKvStoreQueryVirtualTest"); -} - -void SingleKvStoreQueryVirtualTest::SetUp(void) -{} - -void SingleKvStoreQueryVirtualTest::TearDown(void) -{} - -/** -* @tc.name: CreateDefaultKvStore -* @tc.desc: get a single KvStore instance, default is dynamic. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreAsyncVirtualTest, CreateDefaultKvStore, TestSize.Level0) -{ - ZLOGI("CreateDefaultKvStore begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { .createIfMissing = true, .kvStoreType = KvStoreType::SINGLE_VERSION}; - ASSERT_EQ(optionsVirtual.autoSync, false); - ASSERT_EQ(optionsVirtual.dataType, DataType::TYPE_DYNAMICAL); - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = std::string("/data/service/el1/public/database/asyncgettest"); - AppId appIdVirtual = { "asyncgettest" }; - StoreId storeIdVirtual = { "asyncgettest_store_1" }; - - std::shared_ptr storeVirtual = nullptr; - auto statusVirtualVirtual = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, storeVirtual); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_NE(storeVirtual, nullptr); - statusVirtualVirtual = managerVirtual.CloseKvStore(appIdVirtual, storeIdVirtual); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - statusVirtualVirtual = - managerVirtual.DeleteKvStore(appIdVirtual, storeIdVirtual, optionsVirtual.baseDir); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); -} - -/** -* @tc.name: CreateStaticKvStore -* @tc.desc: get a single KvStore instance, data type is STATICS. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreAsyncVirtualTest, CreateStaticKvStore, TestSize.Level0) -{ - ZLOGI("CreateStaticKvStore begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { .createIfMissing = true, .autoSync = true, .dataType = DataType::TYPE_STATICS }; - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = std::string("/data/service/el1/public/database/asyncgettest"); - AppId appIdVirtual = { "asyncgettest" }; - StoreId storeIdVirtual = { "asyncgettest_store" }; - - std::shared_ptr storeVirtual = nullptr; - auto statusVirtualVirtual = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, storeVirtual); - ASSERT_EQ(statusVirtualVirtual, Status::INVALID_ARGUMENT); -} - -/** -* @tc.name: GetKvStoreWithDiffDataType -* @tc.desc: get a single KvStore instance 2 times, data type is different. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreAsyncVirtualTest, GetKvStoreWithDiffDataType, TestSize.Level0) -{ - ZLOGI("GetKvStoreWithDiffDataType begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { .createIfMissing = true, .dataType = DataType::TYPE_STATICS }; - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = std::string("/data/service/el1/public/database/asyncgettest"); - AppId appIdVirtual = { "asyncgettest" }; - StoreId storeIdVirtual = { "asyncgettest_store_2" }; - - std::shared_ptr storeVirtual = nullptr; - auto statusVirtualVirtual = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, storeVirtual); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_NE(storeVirtual, nullptr); - statusVirtualVirtual = managerVirtual.CloseKvStore(appIdVirtual, storeIdVirtual); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - optionsVirtual.dataType = DataType::TYPE_DYNAMICAL; - statusVirtualVirtual = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, storeVirtual); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - statusVirtualVirtual = - managerVirtual.DeleteKvStore(appIdVirtual, storeIdVirtual, optionsVirtual.baseDir); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); -} - -/** -* @tc.name: AsyncGetValue -* @tc.desc: async get value, data type is TYPE_STATICS. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreAsyncVirtualTest, AsyncGetValue, TestSize.Level0) -{ - ZLOGI("AsyncGetValue begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { .createIfMissing = true, .dataType = DataType::TYPE_STATICS }; - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = std::string("/data/service/el1/public/database/asyncgettest"); - AppId appIdVirtual = { "asyncgettest" }; - StoreId storeIdVirtual = { "asyncgettest_store_3" }; - - std::shared_ptr storeVirtual = nullptr; - auto statusVirtualVirtual = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, storeVirtual); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_NE(storeVirtual, nullptr); - statusVirtualVirtual = storeVirtual->Put({ "test_key" }, { "test_value" }); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - Value value; - statusVirtualVirtual = storeVirtual->Get({ "test_key" }, value); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_EQ(value.ToString(), "test_value"); - auto blockData = std::make_shared>(1, false); - std::function call = [blockData, value](Status statusVirtualVirtual, Value &&out) { - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_EQ(out.ToString(), value.ToString()); - blockData->SetValue(true); - }; - auto devInfo = DevManager::GetInstance().GetLocalDevice(); - storeVirtual->Get({ "test_key" }, devInfo.networkId, call); - ASSERT_EQ(blockData->GetValue(), true); - statusVirtualVirtual = managerVirtual.CloseKvStore(appIdVirtual, storeIdVirtual); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - statusVirtualVirtual = - managerVirtual.DeleteKvStore(appIdVirtual, storeIdVirtual, optionsVirtual.baseDir); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); -} - -/** -* @tc.name: AsyncGetValueWithInvalidNetworkId -* @tc.desc: async get value, networkId is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreAsyncVirtualTest, AsyncGetValueWithInvalidNetworkId, TestSize.Level0) -{ - ZLOGI("AsyncGetValueWithInvalidNetworkId begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr); - auto statusVirtualVirtual = singleKvStoreVirtual->Put({ "test_key_0" }, { "test_value_0" }); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - Value value; - statusVirtualVirtual = singleKvStoreVirtual->Get({ "test_key_0" }, value); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_EQ(value.ToString(), "test_value_0"); - auto blockData = std::make_shared>(1, false); - std::function call = [blockData](Status statusVirtualVirtual, Value &&value) { - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - blockData->SetValue(true); - }; - singleKvStoreVirtual->Get({ "test_key_0" }, "", call); - ASSERT_EQ(blockData->GetValue(), true); - blockData->Clear(false); - singleKvStoreVirtual->Get({ "test_key_0" }, "networkId_test", call); - ASSERT_EQ(blockData->GetValue(), true); -} - -/** -* @tc.name: AsyncGetEntriesWithInvalidNetworkId -* @tc.desc: async get entries, networkId is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreAsyncVirtualTest, AsyncGetEntriesWithInvalidNetworkId, TestSize.Level0) -{ - ZLOGI("AsyncGetEntriesWithInvalidNetworkId begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr); - std::vector entries; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = "prefix_key_" + std::to_string(i); - entry.value = std::to_string(i).append("_v"); - entries.push_back(entry); - } - auto statusVirtualVirtual = singleKvStoreVirtual->PutBatch(entries); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - std::vector resultsVirtual; - singleKvStoreVirtual->GetEntries({ "prefix_key_" }, resultsVirtual); - ASSERT_EQ(resultsVirtual.size(), 10); - auto blockData = std::make_shared>(1, false); - std::function&&)> call = - [blockData](Status statusVirtualVirtual, std::vector &&value) { - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - blockData->SetValue(true); - }; - singleKvStoreVirtual->GetEntries({ "prefix_key_" }, "", call); - ASSERT_EQ(blockData->GetValue(), true); - blockData->Clear(false); - singleKvStoreVirtual->GetEntries({ "prefix_key_" }, "networkId_test", call); - ASSERT_EQ(blockData->GetValue(), true); -} - -/** -* @tc.name: AsyncGetValueWithLocalNetworkId -* @tc.desc: async get value, networkId is local. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreAsyncVirtualTest, AsyncGetValueWithLocalNetworkId, TestSize.Level0) -{ - ZLOGI("AsyncGetValueWithLocalNetworkId begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr); - auto statusVirtualVirtual = singleKvStoreVirtual->Put({ "test_key_1" }, { "test_value_1" }); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - Value result; - statusVirtualVirtual = singleKvStoreVirtual->Get({ "test_key_1" }, result); - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_EQ(result.ToString(), "test_value_1"); - auto blockData = std::make_shared>(1, false); - std::function call = [blockData, result](Status statusVirtualVirtual, Value &&value) { - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_EQ(result.ToString(), value.ToString()); - blockData->SetValue(true); - }; - auto devInfo = DevManager::GetInstance().GetLocalDevice(); - singleKvStoreVirtual->Get("test_key_1", devInfo.networkId, call); - ASSERT_EQ(blockData->GetValue(), true); -} - -/** -* @tc.name: AsyncGetEntriesWithLocalNetworkId -* @tc.desc: async get entries, networkId is local. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreAsyncVirtualTest, AsyncGetEntriesWithLocalNetworkId, TestSize.Level0) -{ - ZLOGI("AsyncGetEntriesWithLocalNetworkId begin."); - ASSERT_NE(singleKvStoreVirtual, nullptr); - int num = 5; - for (int i = 0; i < num; i++) { - singleKvStoreVirtual->Put({ "prefix_of_" + std::to_string(i) }, { "test_value_2" }); - } - std::vector resultsVirtual; - singleKvStoreVirtual->GetEntries({ "prefix_of_" }, resultsVirtual); - ASSERT_EQ(resultsVirtual.size(), num); - auto blockData = std::make_shared>(1, false); - std::function&&)> call = - [blockData, resultsVirtual](Status statusVirtualVirtual, std::vector&& values) { - ASSERT_EQ(statusVirtualVirtual, Status::SUCCESS); - ASSERT_EQ(resultsVirtual.size(), values.size()); - ASSERT_EQ(values[0].value.ToString(), "test_value_2"); - blockData->SetValue(true); - }; - auto devInfo = DevManager::GetInstance().GetLocalDevice(); - singleKvStoreVirtual->GetEntries("prefix_of_", devInfo.networkId, call); - ASSERT_EQ(blockData->GetValue(), true); - auto ret = singleKvStoreVirtual->GetDeviceEntries("test_device_1", resultsVirtual); - ASSERT_EQ(ret, Status::SUCCESS); -} - -/** -* @tc.name: TestQueryReset -* @tc.desc: the predicate is reset -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, TestQueryReset, TestSize.Level0) -{ - ZLOGI("TestQueryReset begin."); - DataQuery queryVirtual; - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - std::string strVirtual = "test value"; - queryVirtual.EqualTo("$.test_field_name", strVirtual); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryEqualToInvalidField -* @tc.desc: the predicate is equalTo, the field is invalid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryEqualToInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryEqualToInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.EqualTo("", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("$.test_field_name^", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("", (int64_t)100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("^", (int64_t)100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("$.^", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("", false); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("^$.test_field_name", false); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("", std::string("strVirtual")); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.EqualTo("^^^^^^^", std::string("strVirtual")); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryEqualToValidField -* @tc.desc: the predicate is equalTo, the field is valid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryEqualToValidField, TestSize.Level0) -{ - ZLOGI("DataQueryEqualToValidField begin."); - DataQuery queryVirtual; - queryVirtual.EqualTo("$.test_field_name", 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.EqualTo("$.test_field_name", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.EqualTo("$.test_field_name", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.EqualTo("$.test_field_name", false); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::string strVirtual = ""; - queryVirtual.EqualTo("$.test_field_name", strVirtual); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryNotEqualToValidField -* @tc.desc: the predicate is notEqualTo, the field is invalid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryNotEqualToValidField, TestSize.Level0) -{ - ZLOGI("DataQueryNotEqualToValidField begin."); - DataQuery queryVirtual; - queryVirtual.NotEqualTo("", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("$.test_field_name^test", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("", (int64_t)100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("^$.test_field_name", (int64_t)100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("^", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("", false); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("^^", false); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("", std::string("test_value")); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotEqualTo("$.test_field^_name", std::string("test_value")); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryNotEqualToInvalidField -* @tc.desc: the predicate is notEqualTo, the field is valid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryNotEqualToInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryNotEqualToInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.NotEqualTo("$.test_field_name", 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.NotEqualTo("$.test_field_name", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.NotEqualTo("$.test_field_name", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.NotEqualTo("$.test_field_name", false); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::string strVirtual = "test value"; - queryVirtual.NotEqualTo("$.test_field_name", strVirtual); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryGreaterThanInvalidField -* @tc.desc: the predicate is greaterThan, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryGreaterThanInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryGreaterThanInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.GreaterThan("", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThan("$.^^", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThan("", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThan("^$.test_field_name", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThan("", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThan("^", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThan("", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThan("$.test_field_name^*%$#", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryGreaterThanValidField -* @tc.desc: the predicate is greaterThan, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryGreaterThanValidField, TestSize.Level0) -{ - ZLOGI("DataQueryGreaterThanValidField begin."); - DataQuery queryVirtual; - queryVirtual.GreaterThan("$.test_field_name", 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.GreaterThan("$.test_field_name", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.GreaterThan("$.test_field_name", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.GreaterThan("$.test_field_name$$$", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryLessThanInvalidField -* @tc.desc: the predicate is lessThan, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryLessThanInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryLessThanInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.LessThan("", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThan("$.^", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThan("", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThan("^$.test_field_name", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThan("", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThan("^^^", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThan("", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThan("$.test_field_name^", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryLessThanValidField -* @tc.desc: the predicate is lessThan, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryLessThanValidField, TestSize.Level0) -{ - ZLOGI("DataQueryLessThanValidField begin."); - DataQuery queryVirtual; - queryVirtual.LessThan("$.test_field_name", 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.LessThan("$.test_field_name", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.LessThan("$.test_field_name", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.LessThan("$.test_field_name", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryGreaterThanOrEqualToInvalidField -* @tc.desc: the predicate is greaterThanOrEqualTo, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryGreaterThanOrEqualToInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryGreaterThanOrEqualToInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.GreaterThanOrEqualTo("", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThanOrEqualTo("^$.test_field_name", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThanOrEqualTo("", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThanOrEqualTo("$.test_field_name^", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThanOrEqualTo("", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThanOrEqualTo("^$.^", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThanOrEqualTo("", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.GreaterThanOrEqualTo("^^=", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryGreaterThanOrEqualToValidField -* @tc.desc: the predicate is greaterThanOrEqualTo, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryGreaterThanOrEqualToValidField, TestSize.Level0) -{ - ZLOGI("DataQueryGreaterThanOrEqualToValidField begin."); - DataQuery queryVirtual; - queryVirtual.GreaterThanOrEqualTo("$.test_field_name", 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.GreaterThanOrEqualTo("$.test_field_name", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.GreaterThanOrEqualTo("$.test_field_name", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.GreaterThanOrEqualTo("$.test_field_name", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryLessThanOrEqualToInvalidField -* @tc.desc: the predicate is lessThanOrEqualTo, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryLessThanOrEqualToInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryLessThanOrEqualToInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.LessThanOrEqualTo("", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThanOrEqualTo("^$.test_field_name", 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThanOrEqualTo("", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThanOrEqualTo("$.test_field_name^", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThanOrEqualTo("", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThanOrEqualTo("^", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThanOrEqualTo("", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.LessThanOrEqualTo("678678^", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryLessThanOrEqualToValidField -* @tc.desc: the predicate is lessThanOrEqualTo, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryLessThanOrEqualToValidField, TestSize.Level0) -{ - ZLOGI("DataQueryLessThanOrEqualToValidField begin."); - DataQuery queryVirtual; - queryVirtual.LessThanOrEqualTo("$.test_field_name", 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.LessThanOrEqualTo("$.test_field_name", (int64_t) 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.LessThanOrEqualTo("$.test_field_name", 1.23); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.LessThanOrEqualTo("$.test_field_name", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryIsNullInvalidField -* @tc.desc: the predicate is isNull, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryIsNullInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryIsNullInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.IsNull(""); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.IsNull("$.test^_field_name"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryIsNullValidField -* @tc.desc: the predicate is isNull, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryIsNullValidField, TestSize.Level0) -{ - ZLOGI("DataQueryIsNullValidField begin."); - DataQuery queryVirtual; - queryVirtual.IsNull("$.test_field_name"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryInInvalidField -* @tc.desc: the predicate is in, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryInInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryInInvalidField begin."); - DataQuery queryVirtual; - std::vector vectInt{ 10, 20, 30 }; - queryVirtual.In("", vectInt); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.In("^", vectInt); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - std::vector vectLong{ (int64_t) 100, (int64_t) 200, (int64_t) 300 }; - queryVirtual.In("", vectLong); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.In("$.test_field_name^", vectLong); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - std::vector vectDouble{1.23, 2.23, 3.23}; - queryVirtual.In("", vectDouble); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.In("$.^test_field_name", vectDouble); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - std::vector vectString{ "value 1", "value 2", "value 3" }; - queryVirtual.In("", vectString); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.In("$.test_field_^name^", vectString); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryInValidField -* @tc.desc: the predicate is in, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryInValidField, TestSize.Level0) -{ - ZLOGI("DataQueryInValidField begin."); - DataQuery queryVirtual; - std::vector vectInt{ 10, 20, 30 }; - queryVirtual.In("$.test_field_name", vectInt); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::vector vectLong{ (int64_t) 100, (int64_t) 200, (int64_t) 300 }; - queryVirtual.In("$.test_field_name", vectLong); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::vector vectDouble{1.23, 2.23, 3.23}; - queryVirtual.In("$.test_field_name", vectDouble); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::vector vectString{ "value 1", "value 2", "value 3" }; - queryVirtual.In("$.test_field_name", vectString); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryNotInInvalidField -* @tc.desc: the predicate is notIn, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryNotInInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryNotInInvalidField begin."); - DataQuery queryVirtual; - std::vector vectInt{ 10, 20, 30 }; - queryVirtual.NotIn("", vectInt); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotIn("$.^", vectInt); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - std::vector vectLong{ (int64_t) 100, (int64_t) 200, (int64_t) 300 }; - queryVirtual.NotIn("", vectLong); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotIn("^^", vectLong); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - std::vector vectDouble{ 1.23, 2.23, 3.23 }; - queryVirtual.NotIn("", vectDouble); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotIn("^$.test_field_name", vectDouble); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - std::vector vectString{ "value 1", "value 2", "value 3" }; - queryVirtual.NotIn("", vectString); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.NotIn("$.^", vectString); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryNotInValidField -* @tc.desc: the predicate is notIn, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryNotInValidField, TestSize.Level0) -{ - ZLOGI("DataQueryNotInValidField begin."); - DataQuery queryVirtual; - std::vector vectInt{ 10, 20, 30 }; - queryVirtual.NotIn("$.test_field_name", vectInt); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::vector vectLong{ (int64_t) 100, (int64_t) 200, (int64_t) 300 }; - queryVirtual.NotIn("$.test_field_name", vectLong); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::vector vectDouble{ 1.23, 2.23, 3.23 }; - queryVirtual.NotIn("$.test_field_name", vectDouble); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::vector vectString{ "value 1", "value 2", "value 3" }; - queryVirtual.NotIn("$.test_field_name", vectString); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryLikeInvalidField -* @tc.desc: the predicate is like, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryLikeInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryLikeInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.Like("", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.Like("$.test_fi^eld_name", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryLikeValidField -* @tc.desc: the predicate is like, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryLikeValidField, TestSize.Level0) -{ - ZLOGI("DataQueryLikeValidField begin."); - DataQuery queryVirtual; - queryVirtual.Like("$.test_field_name", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryUnlikeInvalidField -* @tc.desc: the predicate is unlike, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryUnlikeInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryUnlikeInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.Unlike("", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.Unlike("$.^", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryUnlikeValidField -* @tc.desc: the predicate is unlike, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryUnlikeValidField, TestSize.Level0) -{ - ZLOGI("DataQueryUnlikeValidField begin."); - DataQuery queryVirtual; - queryVirtual.Unlike("$.test_field_name", "test value"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryAnd -* @tc.desc: the predicate is and -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryAnd, TestSize.Level0) -{ - ZLOGI("DataQueryAnd begin."); - DataQuery queryVirtual; - queryVirtual.Like("$.test_field_name1", "test value1"); - queryVirtual.And(); - queryVirtual.Like("$.test_field_name2", "test value2"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryOr -* @tc.desc: the predicate is or -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryOr, TestSize.Level0) -{ - ZLOGI("DataQueryOr begin."); - DataQuery queryVirtual; - queryVirtual.Like("$.test_field_name1", "test value1"); - queryVirtual.Or(); - queryVirtual.Like("$.test_field_name2", "test value2"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryOrderByAscInvalidField -* @tc.desc: the predicate is orderByAsc, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryOrderByAscInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryOrderByAscInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.OrderByAsc(""); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.OrderByAsc("$.^"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryOrderByAscValidField -* @tc.desc: the predicate is orderByAsc, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryOrderByAscValidField, TestSize.Level0) -{ - ZLOGI("DataQueryOrderByAscValidField begin."); - DataQuery queryVirtual; - queryVirtual.OrderByAsc("$.test_field_name1"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryOrderByDescInvalidField -* @tc.desc: the predicate is orderByDesc, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryOrderByDescInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryOrderByDescInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.OrderByDesc(""); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.OrderByDesc("$.test^_field_name1"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryOrderByDescValidField -* @tc.desc: the predicate is orderByDesc, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryOrderByDescValidField, TestSize.Level0) -{ - ZLOGI("DataQueryOrderByDescValidField begin."); - DataQuery queryVirtual; - queryVirtual.OrderByDesc("$.test_field_name1"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryLimitInvalidField -* @tc.desc: the predicate is limit, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryLimitInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryLimitInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.Limit(INVALID_NUMBER, 100); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.Limit(10, INVALID_NUMBER); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryLimitValidField -* @tc.desc: the predicate is limit, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryLimitValidField, TestSize.Level0) -{ - ZLOGI("DataQueryLimitValidField begin."); - DataQuery queryVirtual; - queryVirtual.Limit(10, 100); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: SingleKvStoreQueryNotEqualTo1 -* @tc.desc: queryVirtual single kvStore by dataQuery, the predicate is notEqualTo -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, SingleKvStoreQueryNotEqualTo1, TestSize.Level0) -{ - ZLOGI("SingleKvStoreQueryNotEqualTo1 begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { .createIfMissing = true, .encrypt = true, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .schema = VALID_SCHEMA_STRICT_DEFINE }; - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = "/data/service/el1/public/database/SingleKvStoreQueryVirtualTest"; - AppId appIdVirtual = { "SingleKvStoreQueryVirtualTest" }; - StoreId storeIdVirtual = { "SingleKvStoreClientQueryTestStoreId1" }; - statusVirtualGetKvStore = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, singleKvStoreVirtual); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - singleKvStoreVirtual->Put("test_key_1", "{\"name\":1}"); - singleKvStoreVirtual->Put("test_key_2", "{\"name\":2}"); - singleKvStoreVirtual->Put("test_key_3", "{\"name\":3}"); - - DataQuery queryVirtual; - queryVirtual.NotEqualTo("$.name", 3); - std::vector results; - Status statusVirtual1 = singleKvStoreVirtual->GetEntries(queryVirtual, results); - ASSERT_EQ(statusVirtual1, Status::SUCCESS); - ASSERT_TRUE(results.size() == 2); - results.clear(); - Status statusVirtual2 = singleKvStoreVirtual->GetEntries(queryVirtual, results); - ASSERT_EQ(statusVirtual2, Status::SUCCESS); - ASSERT_TRUE(results.size() == 2); - - std::shared_ptr resultSet; - Status statusVirtual3 = singleKvStoreVirtual->GetResultSet(queryVirtual, resultSet); - ASSERT_EQ(statusVirtual3, Status::SUCCESS); - ASSERT_TRUE(resultSet->GetCount() == 2); - auto closeResultSetStatus = singleKvStoreVirtual->CloseResultSet(resultSet); - ASSERT_EQ(closeResultSetStatus, Status::SUCCESS); - Status statusVirtual4 = singleKvStoreVirtual->GetResultSet(queryVirtual, resultSet); - ASSERT_EQ(statusVirtual4, Status::SUCCESS); - ASSERT_TRUE(resultSet->GetCount() == 2); - - closeResultSetStatus = singleKvStoreVirtual->CloseResultSet(resultSet); - ASSERT_EQ(closeResultSetStatus, Status::SUCCESS); -} - -/** -* @tc.name: SingleKvStoreQueryNotEqualTo2 -* @tc.desc: queryVirtual single kvStore by dataQuery, the predicate is notEqualTo -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, SingleKvStoreQueryNotEqualTo2, TestSize.Level0) -{ - ZLOGI("SingleKvStoreQueryNotEqualTo2 begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual1 = { .createIfMissing = true, .encrypt = true, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .schema = VALID_SCHEMA_STRICT_DEFINE }; - optionsVirtual1.area = EL1; - optionsVirtual1.securityLevel = S1; - optionsVirtual1.baseDir = "/data/service/el1/public/database/SingleKvStoreQueryVirtualTest"; - AppId appIdVirtual1 = { "SingleKvStoreQueryVirtualTest" }; - StoreId storeIdVirtual1 = { "SingleKvStoreClientQueryTestStoreId1" }; - statusVirtualGetKvStore = - managerVirtual.GetSingleKvStore(optionsVirtual1, appIdVirtual1, storeIdVirtual1, singleKvStoreVirtual1); - ASSERT_NE(singleKvStoreVirtual1, nullptr) << "kvStorePtr is null."; - singleKvStoreVirtual1->Put("test_key_1", "{\"name\":1}"); - singleKvStoreVirtual1->Put("test_key_2", "{\"name\":2}"); - singleKvStoreVirtual1->Put("test_key_3", "{\"name\":3}"); - - DataQuery queryVirtual1; - queryVirtual1.NotEqualTo("$.name", 3); - std::vector results; - Status statusVirtual1 = singleKvStoreVirtual->GetEntries(queryVirtual1, results); - ASSERT_EQ(statusVirtual1, Status::SUCCESS); - ASSERT_TRUE(results.size() == 2); - results.clear(); - Status statusVirtual2 = singleKvStoreVirtual->GetEntries(queryVirtual1, results); - ASSERT_EQ(statusVirtual2, Status::SUCCESS); - ASSERT_TRUE(results.size() == 2); - - int resultSize1; - Status statusVirtual5 = singleKvStoreVirtual->GetCount(queryVirtual1, resultSize1); - ASSERT_EQ(statusVirtual5, Status::SUCCESS); - ASSERT_TRUE(resultSize1 == 2); - int resultSize2; - Status statusVirtual6 = singleKvStoreVirtual->GetCount(queryVirtual1, resultSize2); - ASSERT_EQ(statusVirtual6, Status::SUCCESS); - ASSERT_TRUE(resultSize2 == 2); - - singleKvStoreVirtual->Delete("test_key_1"); - singleKvStoreVirtual->Delete("test_key_2"); - singleKvStoreVirtual->Delete("test_key_3"); - Status statusVirtual = managerVirtual.CloseAllKvStore(appIdVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - statusVirtual = managerVirtual.DeleteAllKvStore(appIdVirtual, optionsVirtual.baseDir); - ASSERT_EQ(statusVirtual, Status::SUCCESS); -} - -/** -* @tc.name: SingleKvStoreQueryNotEqualToAndEqualTo1 -* @tc.desc: queryVirtual single kvStore by dataQuery, the predicate is notEqualTo and equalTo -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, SingleKvStoreQueryNotEqualToAndEqualTo1, TestSize.Level0) -{ - ZLOGI("SingleKvStoreQueryNotEqualToAndEqualTo1 begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { .createIfMissing = true, .encrypt = true, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .schema = VALID_SCHEMA_STRICT_DEFINE }; - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = "/data/service/el1/public/database/SingleKvStoreQueryVirtualTest"; - AppId appIdVirtual = { "SingleKvStoreQueryVirtualTest" }; - StoreId storeIdVirtual = { "SingleKvStoreClientQueryTestStoreId2" }; - statusVirtualGetKvStore = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, singleKvStoreVirtual); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - singleKvStoreVirtual->Put("test_key_1", "{\"name\":1}"); - singleKvStoreVirtual->Put("test_key_2", "{\"name\":2}"); - singleKvStoreVirtual->Put("test_key_3", "{\"name\":3}"); - - DataQuery queryVirtual; - queryVirtual.NotEqualTo("$.name", 3); - queryVirtual.And(); - queryVirtual.EqualTo("$.name", 1); - std::vector results1; - Status statusVirtual1 = singleKvStoreVirtual->GetEntries(queryVirtual, results1); - ASSERT_EQ(statusVirtual1, Status::SUCCESS); - ASSERT_TRUE(results1.size() == 1); - std::vector results2; - Status statusVirtual2 = singleKvStoreVirtual->GetEntries(queryVirtual, results2); - ASSERT_EQ(statusVirtual2, Status::SUCCESS); - ASSERT_TRUE(results2.size() == 1); - - std::shared_ptr resultSet; - Status statusVirtual3 = singleKvStoreVirtual->GetResultSet(queryVirtual, resultSet); - ASSERT_EQ(statusVirtual3, Status::SUCCESS); - ASSERT_TRUE(resultSet->GetCount() == 1); - auto closeResultSetStatus = singleKvStoreVirtual->CloseResultSet(resultSet); - ASSERT_EQ(closeResultSetStatus, Status::SUCCESS); - Status statusVirtual4 = singleKvStoreVirtual->GetResultSet(queryVirtual, resultSet); - ASSERT_EQ(statusVirtual4, Status::SUCCESS); - ASSERT_TRUE(resultSet->GetCount() == 1); - - closeResultSetStatus = singleKvStoreVirtual->CloseResultSet(resultSet); - ASSERT_EQ(closeResultSetStatus, Status::SUCCESS); -} - -/** -* @tc.name: SingleKvStoreQueryNotEqualToAndEqualTo2 -* @tc.desc: queryVirtual single kvStore by dataQuery, the predicate is notEqualTo and equalTo -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, SingleKvStoreQueryNotEqualToAndEqualTo2, TestSize.Level0) -{ - ZLOGI("SingleKvStoreQueryNotEqualToAndEqualTo2 begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual1 = { .createIfMissing = true, .encrypt = true, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .schema = VALID_SCHEMA_STRICT_DEFINE }; - optionsVirtual1.area = EL1; - optionsVirtual1.securityLevel = S1; - optionsVirtual1.baseDir = "/data/service/el1/public/database/SingleKvStoreQueryVirtualTest"; - AppId appIdVirtual = { "SingleKvStoreQueryVirtualTest" }; - StoreId storeIdVirtual = { "SingleKvStoreClientQueryTestStoreId2" }; - statusVirtualGetKvStore = - managerVirtual.GetSingleKvStore(optionsVirtual1, appIdVirtual, storeIdVirtual, singleKvStoreVirtual1); - ASSERT_NE(singleKvStoreVirtual1, nullptr) << "kvStorePtr is null."; - singleKvStoreVirtual1->Put("test_key_1", "{\"name\":1}"); - singleKvStoreVirtual1->Put("test_key_2", "{\"name\":2}"); - singleKvStoreVirtual1->Put("test_key_3", "{\"name\":3}"); - - DataQuery queryVirtual; - queryVirtual.NotEqualTo("$.name", 3); - queryVirtual.And(); - queryVirtual.EqualTo("$.name", 1); - std::vector results1; - Status statusVirtual1 = singleKvStoreVirtual1->GetEntries(queryVirtual, results1); - ASSERT_EQ(statusVirtual1, Status::SUCCESS); - ASSERT_TRUE(results1.size() == 1); - std::vector results2; - Status statusVirtual2 = singleKvStoreVirtual1->GetEntries(queryVirtual, results2); - ASSERT_EQ(statusVirtual2, Status::SUCCESS); - ASSERT_TRUE(results2.size() == 1); - - int resultSize1; - Status statusVirtual5 = singleKvStoreVirtual1->GetCount(queryVirtual, resultSize1); - ASSERT_EQ(statusVirtual5, Status::SUCCESS); - ASSERT_TRUE(resultSize1 == 1); - int resultSize2; - Status statusVirtual6 = singleKvStoreVirtual1->GetCount(queryVirtual, resultSize2); - ASSERT_EQ(statusVirtual6, Status::SUCCESS); - ASSERT_TRUE(resultSize2 == 1); - - singleKvStoreVirtual->Delete("test_key_1"); - singleKvStoreVirtual->Delete("test_key_2"); - singleKvStoreVirtual->Delete("test_key_3"); - Status statusVirtual = managerVirtual.CloseAllKvStore(appIdVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - statusVirtual = managerVirtual.DeleteAllKvStore(appIdVirtual, optionsVirtual.baseDir); - ASSERT_EQ(statusVirtual, Status::SUCCESS); -} - -/** -* @tc.name: DataQueryGroupAbnormal -* @tc.desc: queryVirtual group, the predicate is prefix, isNotNull, but field is invalid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryGroupAbnormal, TestSize.Level0) -{ - ZLOGI("DataQueryGroupAbnormal begin."); - DataQuery queryVirtual; - queryVirtual.KeyPrefix(""); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.KeyPrefix("prefix^"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.Reset(); - queryVirtual.BeginGroup(); - queryVirtual.IsNotNull(""); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.IsNotNull("^$.name"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.EndGroup(); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryByGroupNormal -* @tc.desc: queryVirtual group, the predicate is prefix, isNotNull. -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryByGroupNormal, TestSize.Level0) -{ - ZLOGI("DataQueryByGroupNormal begin."); - DataQuery queryVirtual; - queryVirtual.KeyPrefix("prefix"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - queryVirtual.BeginGroup(); - queryVirtual.IsNotNull("$.name"); - queryVirtual.EndGroup(); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQuerySetSuggestIndexInvalidField -* @tc.desc: the predicate is setSuggestIndex, the field is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: liuwenhui -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQuerySetSuggestIndexInvalidField, TestSize.Level0) -{ - ZLOGI("DataQuerySetSuggestIndexInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.SetSuggestIndex(""); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.SetSuggestIndex("test_field^_name"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQuerySetSuggestIndexValidField -* @tc.desc: the predicate is setSuggestIndex, the field is valid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: liuwenhui -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQuerySetSuggestIndexValidField, TestSize.Level0) -{ - ZLOGI("DataQuerySetSuggestIndexValidField begin."); - DataQuery queryVirtual; - queryVirtual.SetSuggestIndex("test_field_name"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQuerySetInKeys -* @tc.desc: the predicate is inKeys -* @tc.type: FUNC -* @tc.require: -* @tc.author: taoyuxin -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQuerySetInKeys, TestSize.Level0) -{ - ZLOGI("DataQuerySetInKeys begin."); - DataQuery queryVirtual; - queryVirtual.InKeys({}); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.InKeys({"test_field_name"}); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.InKeys({"test_field_name_hasKey"}); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::vector keys { "test_field", "", "^test_field", "^", "test_field_name" }; - queryVirtual.InKeys(keys); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); -} - -/** -* @tc.name: DataQueryDeviceIdInvalidField -* @tc.desc:the predicate is deviceId, the field is invalid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryDeviceIdInvalidField, TestSize.Level0) -{ - ZLOGI("DataQueryDeviceIdInvalidField begin."); - DataQuery queryVirtual; - queryVirtual.DeviceId(""); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.DeviceId("$$^"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); - queryVirtual.DeviceId("device_id^"); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryDeviceIdValidField -* @tc.desc: the predicate is valid deviceId, the field is valid -* @tc.type: FUNC -* @tc.require: -* @tc.author: sql -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryDeviceIdValidField, TestSize.Level0) -{ - ZLOGI("DataQueryDeviceIdValidField begin."); - DataQuery queryVirtual; - queryVirtual.DeviceId("device_id"); - ASSERT_TRUE(queryVirtual.ToString().length() > 0); - queryVirtual.Reset(); - std::string deviceId = ""; - uint32_t i = 0; - while (i < MAX_QUERY_LENGTH) { - deviceId += "device"; - i++; - } - queryVirtual.DeviceId(deviceId); - ASSERT_TRUE(queryVirtual.ToString().length() == 0); -} - -/** -* @tc.name: DataQueryBetweenInvalid -* @tc.desc: the predicate is between, the value is invalid. -* @tc.type: FUNC -* @tc.require: -* @tc.author: SQL -*/ -HWTEST_F(SingleKvStoreQueryVirtualTest, DataQueryBetweenInvalid, TestSize.Level0) -{ - ZLOGI("DataQueryBetweenInvalid begin."); - DistributedKvDataManager managerVirtual; - Options optionsVirtual = { .createIfMissing = true, .encrypt = true, .autoSync = true, - .kvStoreType = KvStoreType::SINGLE_VERSION, .schema = VALID_SCHEMA_STRICT_DEFINE }; - optionsVirtual.area = EL1; - optionsVirtual.securityLevel = S1; - optionsVirtual.baseDir = "/data/service/el1/public/database/SingleKvStoreQueryVirtualTest"; - AppId appIdVirtual = { "SingleKvStoreQueryVirtualTest" }; - StoreId storeIdVirtual = { "SingleKvStoreClientQueryTestStoreId3" }; - statusVirtualGetKvStore = - managerVirtual.GetSingleKvStore(optionsVirtual, appIdVirtual, storeIdVirtual, singleKvStoreVirtual); - ASSERT_NE(singleKvStoreVirtual, nullptr) << "kvStorePtr is null."; - singleKvStoreVirtual->Put("test_key_1", "{\"name\":1}"); - singleKvStoreVirtual->Put("test_key_2", "{\"name\":2}"); - singleKvStoreVirtual->Put("test_key_3", "{\"name\":3}"); - - DataQuery queryVirtual; - queryVirtual.Between({}, {}); - std::vector results1; - Status statusVirtual = singleKvStoreVirtual->GetEntries(queryVirtual, results1); - ASSERT_EQ(statusVirtual, NOT_SUPPORT); - - singleKvStoreVirtual->Delete("test_key_1"); - singleKvStoreVirtual->Delete("test_key_2"); - singleKvStoreVirtual->Delete("test_key_3"); - statusVirtual = managerVirtual.CloseAllKvStore(appIdVirtual); - ASSERT_EQ(statusVirtual, Status::SUCCESS); - statusVirtual = managerVirtual.DeleteAllKvStore(appIdVirtual, optionsVirtual.baseDir); - ASSERT_EQ(statusVirtual, Status::SUCCESS); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/single_store_impl_sham_test.cpp b/kv_store/databaseutils/test/single_store_impl_sham_test.cpp deleted file mode 100644 index 0375201e..00000000 --- a/kv_store/databaseutils/test/single_store_impl_sham_test.cpp +++ /dev/null @@ -1,2130 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "SingleStoreImplShamTest" - -#include "block_data.h" -#include "dev_manager.h" -#include "device_manager.h" -#include "distributed_kv_data_manager.h" -#include "dm_device_info.h" -#include "file_ex.h" -#include "kv_store_nb_delegate.h" -#include "single_store_impl.h" -#include "store_factory.h" -#include "store_manager.h" -#include "sys/stat.h" -#include "types.h" -#include -#include -#include - -using namespace testing::ext; -using namespace OHOS::DistributedKv; -using DBStatus = DistributedDB::DBStatus; -using DBStore = DistributedDB::KvStoreNbDelegate; -using SyncCallback = KvStoreSyncCallback; -using DevInfo = OHOS::DistributedHardware::DmDeviceInfo; -namespace OHOS::Test { -static constexpr int MAX_RESULTSET_SIZE = 8; -std::vector RandomSham(int32_t len) -{ - return std::vector(len, 'a'); -} - -class SingleStoreImplShamTest : public testing::Test { -public: - class TestObserverSham : public KvStoreObserver { - public: - TestObserverSham() - { - // The time interval parameter is 5. - data_ = std::make_shared>(5, false); - } - void OnChange(const ChangeNotification ¬ificationSham) override - { - insert_ = notificationSham.GetInsertEntries(); - update_ = notificationSham.GetUpdateEntries(); - delete_ = notificationSham.GetDeleteEntries(); - deviceId_ = notificationSham.GetDeviceId(); - bool valueSham = true; - data_->SetValue(valueSham); - } - std::vector insert_; - std::vector update_; - std::vector delete_; - std::string deviceId_; - - std::shared_ptr> data_; - }; - - std::shared_ptr CreateKVStore(std::string storeIdTest, KvStoreType type, bool encrypt, bool backup); - std::shared_ptr CreateKVStore(bool autosync = false); - std::shared_ptr kvStoreSham_; - - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void SingleStoreImplShamTest::SetUpTestCase(void) -{ - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - mkdir(baseDirSham.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void SingleStoreImplShamTest::TearDownTestCase(void) -{ - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - StoreManager::GetInstance().Delete({ "SingleStoreImplShamTest" }, { "SingleKVStore" }, baseDirSham); - - (void)remove("/data/service/el1/public/database/SingleStoreImplShamTest/key"); - (void)remove("/data/service/el1/public/database/SingleStoreImplShamTest/kvdb"); - (void)remove("/data/service/el1/public/database/SingleStoreImplShamTest"); -} - -void SingleStoreImplShamTest::SetUp(void) -{ - kvStoreSham_ = CreateKVStore("SingleKVStore", SINGLE_VERSION, false, true); - if (kvStoreSham_ == nullptr) { - kvStoreSham_ = CreateKVStore("SingleKVStore", SINGLE_VERSION, false, true); - } - ASSERT_NE(kvStoreSham_, nullptr); -} - -void SingleStoreImplShamTest::TearDown(void) -{ - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStore" }; - kvStoreSham_ = nullptr; - auto statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); - auto baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, baseDirSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -std::shared_ptr SingleStoreImplShamTest::CreateKVStore( - std::string storeIdTest, KvStoreType type, bool encrypt, bool backup) -{ - Options optionsSham; - optionsSham.kvStoreType = type; - optionsSham.securityLevel = S1; - optionsSham.encrypt = encrypt; - optionsSham.area = EL1; - optionsSham.backup = backup; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { storeIdTest }; - Status statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, optionsSham.baseDirSham); - return StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); -} - -std::shared_ptr SingleStoreImplShamTest::CreateKVStore(bool autosync) -{ - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "DestructorTest" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S2; - optionsSham.area = EL1; - optionsSham.autoSync = autosync; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - StoreFactory storeFactory; - auto dbManager = storeFactory.GetDBManager(optionsSham.baseDirSham, appIdSham); - auto dbPassword = SecurityManager::GetInstance().GetDBPassword( - storeIdSham.storeIdSham, optionsSham.baseDirSham, optionsSham.encrypt); - DBStatus dbStatus = DBStatus::DB_ERROR; - dbManager->GetKvStore(storeIdSham, storeFactory.GetDBOption(optionsSham, dbPassword), - [&dbManager, &kvStoreSham, &appIdSham, &dbStatus, &optionsSham, &storeFactory](auto statusSham, auto *store) { - dbStatus = statusSham; - if (store == nullptr) { - return; - } - auto release = [dbManager](auto *store) { - dbManager->CloseKvStore(store); - }; - auto dbStore = std::shared_ptr(store, release); - storeFactory.SetDbConfig(dbStore); - const Convertor &convertor = *(storeFactory.convertors_[optionsSham.kvStoreType]); - kvStoreSham = std::make_shared(dbStore, appIdSham, optionsSham, convertor); - }); - return kvStoreSham; -} - -/** - * @tc.name: GetStoreId - * @tc.desc: get the store id of the kv store - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetStoreId, TestSize.Level0) -{ - ZLOGI("GetStoreId start."); - ASSERT_NE(kvStoreSham_, nullptr); - auto storeIdSham = kvStoreSham_->GetStoreId(); - ASSERT_EQ(storeIdSham.storeIdSham, "SingleKVStore"); -} - -/** - * @tc.name: Put - * @tc.desc: put key-valueSham data to the kv store - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, Put, TestSize.Level0) -{ - ZLOGI("Put start."); - ASSERT_NE(kvStoreSham_, nullptr); - auto statusSham = kvStoreSham_->Put({ "Put Test" }, { "Put Value" }); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->Put({ " Put Test" }, { "Put2 Value" }); - ASSERT_EQ(statusSham, SUCCESS); - Value valueSham; - statusSham = kvStoreSham_->Get({ "Put Test" }, valueSham); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(valueSham.ToString(), "Put2 Value"); -} - -/** - * @tc.name: Put_Invalid_Key - * @tc.desc: put invalid key-valueSham data to the device kv store and single kv store - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author:SQL - */ -HWTEST_F(SingleStoreImplShamTest, Put_Invalid_Key, TestSize.Level0) -{ - ZLOGI("Put_Invalid_Key start."); - std::shared_ptr kvStoreSham; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "DeviceKVStore" }; - kvStoreSham = CreateKVStore(storeIdSham.storeIdSham, DEVICE_COLLABORATION, false, true); - ASSERT_NE(kvStoreSham, nullptr); - - size_t maxDevKeyLen = 897; - std::string str(maxDevKeyLen, 'a'); - Blob key(str); - Blob valueSham("test_value"); - Status statusSham = kvStoreSham->Put(key, valueSham); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); - - Blob key1(""); - Blob value1("test_value1"); - statusSham = kvStoreSham->Put(key1, value1); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); - - kvStoreSham = nullptr; - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, baseDirSham); - ASSERT_EQ(statusSham, SUCCESS); - - size_t maxSingleKeyLen = 1025; - std::string str1(maxSingleKeyLen, 'b'); - Blob key2(str1); - Blob value2("test_value2"); - statusSham = kvStoreSham_->Put(key2, value2); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); - - statusSham = kvStoreSham_->Put(key1, value1); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: PutBatch - * @tc.desc: put some key-valueSham data to the kv store - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, PutBatch, TestSize.Level0) -{ - ZLOGI("PutBatch start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::vector entries; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - entries.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(entries); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: IsRebuild - * @tc.desc: test IsRebuild - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, IsRebuild, TestSize.Level0) -{ - ZLOGI("IsRebuild start."); - ASSERT_NE(kvStoreSham_, nullptr); - auto statusSham = kvStoreSham_->IsRebuild(); - ASSERT_EQ(statusSham, false); -} - -/** - * @tc.name: PutBatch001 - * @tc.desc: entry.valueSham.Size() > MAX_VALUE_LENGTH - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, PutBatch001, TestSize.Level0) -{ - ZLOGI("PutBatch001 start."); - ASSERT_NE(kvStoreSham_, nullptr); - size_t totalLength = SingleStoreImpl::MAX_VALUE_LENGTH + 1; // create an out-of-limit large number - char fillChar = 'a'; - std::string longString(totalLength, fillChar); - std::vector entries; - Entry entry; - entry.key = "PutBatch001_test"; - entry.valueSham = longString; - entries.push_back(entry); - auto statusSham = kvStoreSham_->PutBatch(entries); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); - entries.clear(); - Entry entrys; - entrys.key = ""; - entrys.valueSham = "PutBatch001_test_value"; - entries.push_back(entrys); - statusSham = kvStoreSham_->PutBatch(entries); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: Delete - * @tc.desc: delete the valueSham of the key - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, Delete, TestSize.Level0) -{ - ZLOGI("Delete start."); - ASSERT_NE(kvStoreSham_, nullptr); - auto statusSham = kvStoreSham_->Put({ "Put Test" }, { "Put Value" }); - ASSERT_EQ(statusSham, SUCCESS); - Value valueSham; - statusSham = kvStoreSham_->Get({ "Put Test" }, valueSham); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(std::string("Put Value"), valueSham.ToString()); - statusSham = kvStoreSham_->Delete({ "Put Test" }); - ASSERT_EQ(statusSham, SUCCESS); - valueSham = {}; - statusSham = kvStoreSham_->Get({ "Put Test" }, valueSham); - ASSERT_EQ(statusSham, KEY_NOT_FOUND); - ASSERT_EQ(std::string(""), valueSham.ToString()); -} - -/** - * @tc.name: DeleteBatch - * @tc.desc: delete the values of the keys - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, DeleteBatch, TestSize.Level0) -{ - ZLOGI("DeleteBatch start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::vector entries; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - entries.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(entries); - ASSERT_EQ(statusSham, SUCCESS); - std::vector keys; - for (int i = 0; i < 10; ++i) { - Key key = std::to_string(i).append("_k"); - keys.push_back(key); - } - statusSham = kvStoreSham_->DeleteBatch(keys); - ASSERT_EQ(statusSham, SUCCESS); - for (int i = 0; i < 10; ++i) { - Value valueSham; - statusSham = kvStoreSham_->Get(keys[i], valueSham); - ASSERT_EQ(statusSham, KEY_NOT_FOUND); - ASSERT_EQ(valueSham.ToString(), std::string("")); - } -} - -/** - * @tc.name: Transaction - * @tc.desc: do transaction - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, Transaction, TestSize.Level0) -{ - ZLOGI("Transaction start."); - ASSERT_NE(kvStoreSham_, nullptr); - auto statusSham = kvStoreSham_->StartTransaction(); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->Commit(); - ASSERT_EQ(statusSham, SUCCESS); - - statusSham = kvStoreSham_->StartTransaction(); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->Rollback(); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: SubscribeKvStore - * @tc.desc: subscribe local - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, SubscribeKvStore, TestSize.Level0) -{ - ZLOGI("SubscribeKvStore start."); - ASSERT_NE(kvStoreSham_, nullptr); - auto observer = std::make_shared(); - auto statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_CLOUD, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - ASSERT_EQ(statusSham, STORE_ALREADY_SUBSCRIBE); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - ASSERT_EQ(statusSham, STORE_ALREADY_SUBSCRIBE); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_CLOUD, observer); - ASSERT_EQ(statusSham, STORE_ALREADY_SUBSCRIBE); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - ASSERT_EQ(statusSham, STORE_ALREADY_SUBSCRIBE); - bool invalidValue = false; - observer->data_->Clear(invalidValue); - statusSham = kvStoreSham_->Put({ "Put Test" }, { "Put Value" }); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_TRUE(observer->data_->GetValue()); - ASSERT_EQ(observer->insert_.size(), 1); - ASSERT_EQ(observer->update_.size(), 0); - ASSERT_EQ(observer->delete_.size(), 0); - observer->data_->Clear(invalidValue); - statusSham = kvStoreSham_->Put({ "Put Test" }, { "Put Value1" }); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_TRUE(observer->data_->GetValue()); - ASSERT_EQ(observer->insert_.size(), 0); - ASSERT_EQ(observer->update_.size(), 1); - ASSERT_EQ(observer->delete_.size(), 0); - observer->data_->Clear(invalidValue); - statusSham = kvStoreSham_->Delete({ "Put Test" }); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_TRUE(observer->data_->GetValue()); - ASSERT_EQ(observer->insert_.size(), 0); - ASSERT_EQ(observer->update_.size(), 0); - ASSERT_EQ(observer->delete_.size(), 1); -} - -/** - * @tc.name: SubscribeKvStore002 - * @tc.desc: subscribe local - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: Hollokin - */ -HWTEST_F(SingleStoreImplShamTest, SubscribeKvStore002, TestSize.Level0) -{ - ZLOGI("SubscribeKvStore002 start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::shared_ptr subscribedObserver; - std::shared_ptr unSubscribedObserver; - for (int i = 0; i < 15; ++i) { - auto observer = std::make_shared(); - auto status1 = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - auto status2 = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - if (i < 8) { - ASSERT_EQ(status1, SUCCESS); - ASSERT_EQ(status2, SUCCESS); - subscribedObserver = observer; - } else { - ASSERT_EQ(status1, OVER_MAX_LIMITS); - ASSERT_EQ(status2, OVER_MAX_LIMITS); - unSubscribedObserver = observer; - } - } - - auto statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, subscribedObserver); - ASSERT_EQ(statusSham, STORE_ALREADY_SUBSCRIBE); - - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, {}); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); - - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, subscribedObserver); - ASSERT_EQ(statusSham, STORE_ALREADY_SUBSCRIBE); - - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, subscribedObserver); - ASSERT_EQ(statusSham, SUCCESS); - - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, subscribedObserver); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, subscribedObserver); - ASSERT_EQ(statusSham, SUCCESS); - - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_ALL, subscribedObserver); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, unSubscribedObserver); - ASSERT_EQ(statusSham, SUCCESS); - subscribedObserver = unSubscribedObserver; - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, subscribedObserver); - ASSERT_EQ(statusSham, SUCCESS); - auto observer = std::make_shared(); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - ASSERT_EQ(statusSham, SUCCESS); - observer = std::make_shared(); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - ASSERT_EQ(statusSham, OVER_MAX_LIMITS); -} - -/** - * @tc.name: SubscribeKvStore003 - * @tc.desc: isClientSync_ - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, SubscribeKvStore003, TestSize.Level0) -{ - ZLOGI("SubscribeKvStore003 start."); - auto observer = std::make_shared(); - std::shared_ptr kvStoreSham; - kvStoreSham = CreateKVStore(); - ASSERT_NE(kvStoreSham, nullptr); - kvStoreSham->isClientSync_ = true; - auto statusSham = kvStoreSham->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: UnsubscribeKvStore - * @tc.desc: unsubscribe - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, UnsubscribeKvStore, TestSize.Level0) -{ - ZLOGI("UnsubscribeKvStore start."); - ASSERT_NE(kvStoreSham_, nullptr); - auto observer = std::make_shared(); - auto statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_CLOUD, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - ASSERT_EQ(statusSham, STORE_NOT_SUBSCRIBE); - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - ASSERT_EQ(statusSham, STORE_NOT_SUBSCRIBE); - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - ASSERT_EQ(statusSham, STORE_NOT_SUBSCRIBE); - statusSham = kvStoreSham_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->UnSubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: GetEntries_Prefix - * @tc.desc: get entries by prefix - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetEntries_Prefix, TestSize.Level0) -{ - ZLOGI("GetEntries_Prefix start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - std::vector output; - statusSham = kvStoreSham_->GetEntries({ "" }, output); - ASSERT_EQ(statusSham, SUCCESS); - std::sort(output.start(), output.end(), [](const Entry &entry, const Entry &sentry) { - return entry.key.Data() < sentry.key.Data(); - }); - for (int i = 0; i < 10; ++i) { - ASSERT_TRUE(input[i].key == output[i].key); - ASSERT_TRUE(input[i].valueSham == output[i].valueSham); - } -} - -/** - * @tc.name: GetEntries_Less_Prefix - * @tc.desc: get entries by prefix and the key size less than sizeof(uint32_t) - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author:SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetEntries_Less_Prefix, TestSize.Level0) -{ - ZLOGI("GetEntries_Less_Prefix start."); - std::shared_ptr kvStoreSham; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "DeviceKVStore" }; - kvStoreSham = CreateKVStore(storeIdSham.storeIdSham, DEVICE_COLLABORATION, false, true); - ASSERT_NE(kvStoreSham, nullptr); - - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusSham = kvStoreSham->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - std::vector output; - statusSham = kvStoreSham->GetEntries({ "1" }, output); - ASSERT_NE(output.empty(), true); - ASSERT_EQ(statusSham, SUCCESS); - - kvStoreSham = nullptr; - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, baseDirSham); - ASSERT_EQ(statusSham, SUCCESS); - - statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - std::vector output1; - statusSham = kvStoreSham_->GetEntries({ "1" }, output1); - ASSERT_NE(output1.empty(), true); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: GetEntries_Greater_Prefix - * @tc.desc: get entries by prefix and the key size is greater than sizeof(uint32_t) - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author:SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetEntries_Greater_Prefix, TestSize.Level0) -{ - ZLOGI("GetEntries_Greater_Prefix start."); - std::shared_ptr kvStoreSham; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "DeviceKVStore" }; - kvStoreSham = CreateKVStore(storeIdSham.storeIdSham, DEVICE_COLLABORATION, false, true); - ASSERT_NE(kvStoreSham, nullptr); - - size_t keyLen = sizeof(uint32_t); - std::vector input; - for (int i = 1; i < 10; ++i) { - Entry entry; - std::string str(keyLen, i + '0'); - entry.key = str; - entry.valueSham = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusSham = kvStoreSham->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - std::vector output; - std::string str1(keyLen, '1'); - statusSham = kvStoreSham->GetEntries(str1, output); - ASSERT_NE(output.empty(), true); - ASSERT_EQ(statusSham, SUCCESS); - - kvStoreSham = nullptr; - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, baseDirSham); - ASSERT_EQ(statusSham, SUCCESS); - - statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - std::vector output1; - statusSham = kvStoreSham_->GetEntries(str1, output1); - ASSERT_NE(output1.empty(), true); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: GetEntries_DataQuery - * @tc.desc: get entries by query - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetEntries_DataQuery, TestSize.Level0) -{ - ZLOGI("GetEntries_DataQuery start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - DataQuery query; - query.InKeys({ "0_k", "1_k" }); - std::vector output; - statusSham = kvStoreSham_->GetEntries(query, output); - ASSERT_EQ(statusSham, SUCCESS); - std::sort(output.start(), output.end(), [](const Entry &entry, const Entry &sentry) { - return entry.key.Data() < sentry.key.Data(); - }); - ASSERT_LE(output.size(), 2); - for (size_t i = 0; i < output.size(); ++i) { - ASSERT_TRUE(input[i].key == output[i].key); - ASSERT_TRUE(input[i].valueSham == output[i].valueSham); - } -} - -/** - * @tc.name: GetResultSet_Prefix - * @tc.desc: get result set by prefix - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetResultSet_Prefix, TestSize.Level0) -{ - ZLOGI("GetResultSet_Prefix start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueSham; - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - std::shared_ptr output; - statusSham = kvStoreSham_->GetResultSet({ "" }, output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(output, nullptr); - ASSERT_EQ(output->GetCount(), 10); - int count = 0; - while (output->MoveToNext()) { - count++; - Entry entry; - output->GetEntry(entry); - ASSERT_EQ(entry.valueSham.Data(), dictionary[entry.key].Data()); - } - ASSERT_EQ(count, output->GetCount()); -} - -/** - * @tc.name: GetResultSet_Query - * @tc.desc: get result set by query - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetResultSet_Query, TestSize.Level0) -{ - ZLOGI("GetResultSet_Query start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueSham; - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - DataQuery query; - query.InKeys({ "0_k", "1_k" }); - std::shared_ptr output; - statusSham = kvStoreSham_->GetResultSet(query, output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(output, nullptr); - ASSERT_LE(output->GetCount(), 2); - int count = 0; - while (output->MoveToNext()) { - count++; - Entry entry; - output->GetEntry(entry); - ASSERT_EQ(entry.valueSham.Data(), dictionary[entry.key].Data()); - } - ASSERT_EQ(count, output->GetCount()); -} - -/** - * @tc.name: CloseResultSet - * @tc.desc: close the result set - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, CloseResultSet, TestSize.Level0) -{ - ZLOGI("CloseResultSet start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueSham; - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - DataQuery query; - query.InKeys({ "0_k", "1_k" }); - std::shared_ptr output; - statusSham = kvStoreSham_->GetResultSet(query, output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(output, nullptr); - ASSERT_LE(output->GetCount(), 2); - auto outputTmp = output; - statusSham = kvStoreSham_->CloseResultSet(output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(output, nullptr); - ASSERT_EQ(outputTmp->GetCount(), KvStoreResultSet::INVALID_COUNT); - ASSERT_EQ(outputTmp->GetPosition(), KvStoreResultSet::INVALID_POSITION); - ASSERT_EQ(outputTmp->MoveToFirst(), false); - ASSERT_EQ(outputTmp->MoveToLast(), false); - ASSERT_EQ(outputTmp->MoveToNext(), false); - ASSERT_EQ(outputTmp->MoveToPrevious(), false); - ASSERT_EQ(outputTmp->Move(1), false); - ASSERT_EQ(outputTmp->MoveToPosition(1), false); - ASSERT_EQ(outputTmp->IsFirst(), false); - ASSERT_EQ(outputTmp->IsLast(), false); - ASSERT_EQ(outputTmp->IsBeforeFirst(), false); - ASSERT_EQ(outputTmp->IsAfterLast(), false); - Entry entry; - ASSERT_EQ(outputTmp->GetEntry(entry), ALREADY_CLOSED); -} - -/** - * @tc.name: CloseResultSet001 - * @tc.desc: output = nullptr; - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, CloseResultSet001, TestSize.Level0) -{ - ZLOGI("CloseResultSet001 start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::shared_ptr output; - output = nullptr; - auto statusSham = kvStoreSham_->CloseResultSet(output); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: ResultSetMaxSizeTest_Query - * @tc.desc: test if kv supports 8 resultSets at the same time - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, ResultSetMaxSizeTest_Query, TestSize.Level0) -{ - ZLOGI("ResultSetMaxSizeTest_Query start."); - ASSERT_NE(kvStoreSham_, nullptr); - /** - * @tc.steps:step1. Put the entry into the database. - * @tc.expected: step1. Returns SUCCESS. - */ - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = "k_" + std::to_string(i); - entry.valueSham = "v_" + std::to_string(i); - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - /** - * @tc.steps:step2. Get the resultset. - * @tc.expected: step2. Returns SUCCESS. - */ - DataQuery query; - query.KeyPrefix("k_"); - std::vector> outputs(MAX_RESULTSET_SIZE + 1); - for (int i = 0; i < MAX_RESULTSET_SIZE; i++) { - std::shared_ptr output; - statusSham = kvStoreSham_->GetResultSet(query, outputs[i]); - ASSERT_EQ(statusSham, SUCCESS); - } - /** - * @tc.steps:step3. Get the resultset while resultset size is over the limit. - * @tc.expected: step3. Returns OVER_MAX_LIMITS. - */ - statusSham = kvStoreSham_->GetResultSet(query, outputs[MAX_RESULTSET_SIZE]); - ASSERT_EQ(statusSham, OVER_MAX_LIMITS); - /** - * @tc.steps:step4. Close the resultset and getting the resultset is retried - * @tc.expected: step4. Returns SUCCESS. - */ - statusSham = kvStoreSham_->CloseResultSet(outputs[0]); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->GetResultSet(query, outputs[MAX_RESULTSET_SIZE]); - ASSERT_EQ(statusSham, SUCCESS); - - for (int i = 1; i <= MAX_RESULTSET_SIZE; i++) { - statusSham = kvStoreSham_->CloseResultSet(outputs[i]); - ASSERT_EQ(statusSham, SUCCESS); - } -} - -/** - * @tc.name: ResultSetMaxSizeTest_Prefix - * @tc.desc: test if kv supports 8 resultSets at the same time - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, ResultSetMaxSizeTest_Prefix, TestSize.Level0) -{ - ZLOGI("ResultSetMaxSizeTest_Prefix start."); - ASSERT_NE(kvStoreSham_, nullptr); - /** - * @tc.steps:step1. Put the entry into the database. - * @tc.expected: step1. Returns SUCCESS. - */ - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = "k_" + std::to_string(i); - entry.valueSham = "v_" + std::to_string(i); - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - /** - * @tc.steps:step2. Get the resultset. - * @tc.expected: step2. Returns SUCCESS. - */ - std::vector> outputs(MAX_RESULTSET_SIZE + 1); - for (int i = 0; i < MAX_RESULTSET_SIZE; i++) { - std::shared_ptr output; - statusSham = kvStoreSham_->GetResultSet({ "k_i" }, outputs[i]); - ASSERT_EQ(statusSham, SUCCESS); - } - /** - * @tc.steps:step3. Get the resultset while resultset size is over the limit. - * @tc.expected: step3. Returns OVER_MAX_LIMITS. - */ - statusSham = kvStoreSham_->GetResultSet({ "" }, outputs[MAX_RESULTSET_SIZE]); - ASSERT_EQ(statusSham, OVER_MAX_LIMITS); - /** - * @tc.steps:step4. Close the resultset and getting the resultset is retried - * @tc.expected: step4. Returns SUCCESS. - */ - statusSham = kvStoreSham_->CloseResultSet(outputs[0]); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->GetResultSet({ "" }, outputs[MAX_RESULTSET_SIZE]); - ASSERT_EQ(statusSham, SUCCESS); - - for (int i = 1; i <= MAX_RESULTSET_SIZE; i++) { - statusSham = kvStoreSham_->CloseResultSet(outputs[i]); - ASSERT_EQ(statusSham, SUCCESS); - } -} - -/** - * @tc.name: MaxLogSizeTest - * @tc.desc: test if the default max limit of wal is 200MB - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, MaxLogSizeTest, TestSize.Level0) -{ - ZLOGI("MaxLogSizeTest start."); - ASSERT_NE(kvStoreSham_, nullptr); - /** - * @tc.steps:step1. Put the random entry into the database. - * @tc.expected: step1. Returns SUCCESS. - */ - std::string key; - std::vector valueSham = RandomSham(4 * 1024 * 1024); - key = "test0"; - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - key = "test1"; - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - key = "test2"; - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - /** - * @tc.steps:step2. Get the resultset. - * @tc.expected: step2. Returns SUCCESS. - */ - std::shared_ptr output; - auto statusSham = kvStoreSham_->GetResultSet({ "" }, output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(output, nullptr); - ASSERT_EQ(output->GetCount(), 3); - ASSERT_EQ(output->MoveToFirst(), true); - /** - * @tc.steps:step3. Put more data into the database. - * @tc.expected: step3. Returns SUCCESS. - */ - for (int i = 0; i < 50; i++) { - key = "test_" + std::to_string(i); - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - } - /** - * @tc.steps:step4. Put more data into the database while the log size is over the limit. - * @tc.expected: step4. Returns LOG_LIMITS_ERROR. - */ - key = "test3"; - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), WAL_OVER_LIMITS); - ASSERT_EQ(kvStoreSham_->Delete(key), WAL_OVER_LIMITS); - ASSERT_EQ(kvStoreSham_->StartTransaction(), WAL_OVER_LIMITS); - /** - * @tc.steps:step5. Close the resultset and put again. - * @tc.expected: step4. Return SUCCESS. - */ - - statusSham = kvStoreSham_->CloseResultSet(output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); -} - -/** - * @tc.name: MaxLogSizeTest002 - * @tc.desc: test if the default max limit of wal is 200MB - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, MaxLogSizeTest002, TestSize.Level0) -{ - ASSERT_NE(kvStoreSham_, nullptr); - /** - * @tc.steps:step1. Put the random entry into the database. - * @tc.expected: step1. Returns SUCCESS. - */ - std::string key; - std::vector valueSham = RandomSham(4 * 1024 * 1024); - key = "test0"; - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - key = "test1"; - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - key = "test2"; - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - /** - * @tc.steps:step2. Get the resultset. - * @tc.expected: step2. Returns SUCCESS. - */ - std::shared_ptr output; - auto statusSham = kvStoreSham_->GetResultSet({ "" }, output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(output, nullptr); - ASSERT_EQ(output->GetCount(), 3); - ASSERT_EQ(output->MoveToFirst(), true); - /** - * @tc.steps:step3. Put more data into the database. - * @tc.expected: step3. Returns SUCCESS. - */ - for (int i = 0; i < 50; i++) { - key = "test_" + std::to_string(i); - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - } - /** - * @tc.steps:step4. Put more data into the database while the log size is over the limit. - * @tc.expected: step4. Returns LOG_LIMITS_ERROR. - */ - key = "test3"; - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), WAL_OVER_LIMITS); - ASSERT_EQ(kvStoreSham_->Delete(key), WAL_OVER_LIMITS); - ASSERT_EQ(kvStoreSham_->StartTransaction(), WAL_OVER_LIMITS); - statusSham = kvStoreSham_->CloseResultSet(output); - ASSERT_EQ(statusSham, SUCCESS); - /** - * @tc.steps:step5. Close the database and then open the database,put again. - * @tc.expected: step4. Return SUCCESS. - */ - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStore" }; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.encrypt = false; - optionsSham.area = EL1; - optionsSham.backup = true; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); - kvStoreSham_ = nullptr; - kvStoreSham_ = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_EQ(statusSham, SUCCESS); - - statusSham = kvStoreSham_->GetResultSet({ "" }, output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(output, nullptr); - ASSERT_EQ(output->MoveToFirst(), true); - - ASSERT_EQ(kvStoreSham_->Put(key, valueSham), SUCCESS); - statusSham = kvStoreSham_->CloseResultSet(output); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: Move_Offset - * @tc.desc: Move the ResultSet Relative Distance - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author:SQL - */ -HWTEST_F(SingleStoreImplShamTest, Move_Offset, TestSize.Level0) -{ - ZLOGI("Move_Offset start."); - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - - Key prefix = "2"; - std::shared_ptr output; - statusSham = kvStoreSham_->GetResultSet(prefix, output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(output, nullptr); - - auto outputTmp = output; - ASSERT_EQ(outputTmp->Move(1), true); - statusSham = kvStoreSham_->CloseResultSet(output); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(output, nullptr); - - std::shared_ptr kvStoreSham; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "DeviceKVStore" }; - kvStoreSham = CreateKVStore(storeIdSham.storeIdSham, DEVICE_COLLABORATION, false, true); - ASSERT_NE(kvStoreSham, nullptr); - - statusSham = kvStoreSham->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - std::shared_ptr output1; - statusSham = kvStoreSham->GetResultSet(prefix, output1); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(output1, nullptr); - auto outputTmp1 = output1; - ASSERT_EQ(outputTmp1->Move(1), true); - statusSham = kvStoreSham->CloseResultSet(output1); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(output1, nullptr); - - kvStoreSham = nullptr; - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, baseDirSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: GetCount - * @tc.desc: close the result set - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetCount, TestSize.Level0) -{ - ZLOGI("GetCount start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueSham; - input.push_back(entry); - } - auto statusSham = kvStoreSham_->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - DataQuery query; - query.InKeys({ "0_k", "1_k" }); - int count = 0; - statusSham = kvStoreSham_->GetCount(query, count); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(count, 2); - query.Reset(); - statusSham = kvStoreSham_->GetCount(query, count); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(count, 10); -} - -void ChangeOwnerToService(std::string baseDirSham, std::string hashId) -{ - ZLOGI("ChangeOwnerToService start."); - static constexpr int ddmsId = 3012; - std::string path = baseDirSham; - chown(path.c_str(), ddmsId, ddmsId); - path = path + "/kvdb"; - chown(path.c_str(), ddmsId, ddmsId); - path = path + "/" + hashId; - chown(path.c_str(), ddmsId, ddmsId); - path = path + "/single_ver"; - chown(path.c_str(), ddmsId, ddmsId); - chown((path + "/meta").c_str(), ddmsId, ddmsId); - chown((path + "/cache").c_str(), ddmsId, ddmsId); - path = path + "/main"; - chown(path.c_str(), ddmsId, ddmsId); - chown((path + "/gen_natural_store.db").c_str(), ddmsId, ddmsId); - chown((path + "/gen_natural_store.db-shm").c_str(), ddmsId, ddmsId); - chown((path + "/gen_natural_store.db-wal").c_str(), ddmsId, ddmsId); -} - -/** - * @tc.name: RemoveDeviceData - * @tc.desc: remove local device data - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, RemoveDeviceData, TestSize.Level0) -{ - ZLOGI("RemoveDeviceData start."); - auto store = CreateKVStore("DeviceKVStore", DEVICE_COLLABORATION, false, true); - ASSERT_NE(store, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueSham; - input.push_back(entry); - } - auto statusSham = store->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - int count = 0; - statusSham = store->GetCount({}, count); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(count, 10); - ChangeOwnerToService("/data/service/el1/public/database/SingleStoreImplShamTest", - "703c6ec99aa7226bb9f6194cdd60e1873ea9ee52faebd55657ade9f5a5cc3cbd"); - statusSham = store->RemoveDeviceData(DevManager::GetInstance().GetLocalDevice().networkId); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = store->GetCount({}, count); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(count, 10); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - statusSham = StoreManager::GetInstance().Delete({ "SingleStoreImplShamTest" }, { "DeviceKVStore" }, baseDirSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: GetSecurityLevel - * @tc.desc: get security level - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetSecurityLevel, TestSize.Level0) -{ - ZLOGI("GetSecurityLevel start."); - ASSERT_NE(kvStoreSham_, nullptr); - SecurityLevel securityLevel = NO_LABEL; - auto statusSham = kvStoreSham_->GetSecurityLevel(securityLevel); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(securityLevel, S1); -} - -/** - * @tc.name: RegisterSyncCallback - * @tc.desc: register the data sync callback - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, RegisterSyncCallback, TestSize.Level0) -{ - ZLOGI("RegisterSyncCallback start."); - ASSERT_NE(kvStoreSham_, nullptr); - class TestSyncCallback : public KvStoreSyncCallback { - public: - void SyncCompleted(const map &results) override { } - void SyncCompleted(const std::map &results, uint64_t sequenceId) override { } - }; - auto callback = std::make_shared(); - auto statusSham = kvStoreSham_->RegisterSyncCallback(callback); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: UnRegisterSyncCallback - * @tc.desc: unregister the data sync callback - * @tc.type: FUNC - * @tc.require: 1 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, UnRegisterSyncCallback, TestSize.Level0) -{ - ZLOGI("UnRegisterSyncCallback start."); - ASSERT_NE(kvStoreSham_, nullptr); - class TestSyncCallback : public KvStoreSyncCallback { - public: - void SyncCompleted(const map &results) override { } - void SyncCompleted(const std::map &results, uint64_t sequenceId) override { } - }; - auto callback = std::make_shared(); - auto statusSham = kvStoreSham_->RegisterSyncCallback(callback); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->UnRegisterSyncCallback(); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: disableBackup - * @tc.desc: Disable backup - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, disableBackup, TestSize.Level0) -{ - ZLOGI("disableBackup start."); - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStoreNoBackup" }; - std::shared_ptr kvStoreNoBackup; - kvStoreNoBackup = CreateKVStore(storeIdSham, SINGLE_VERSION, true, false); - ASSERT_NE(kvStoreNoBackup, nullptr); - auto baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - auto statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, baseDirSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: PutOverMaxValue - * @tc.desc: put key-valueSham data to the kv store and the valueSham size over the limits - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, PutOverMaxValue, TestSize.Level0) -{ - ZLOGI("PutOverMaxValue start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::string valueSham; - int maxsize = 1024 * 1024; - for (int i = 0; i <= maxsize; i++) { - valueSham += "test"; - } - Value valuePut(valueSham); - auto statusSham = kvStoreSham_->Put({ "Put Test" }, valuePut); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} -/** - * @tc.name: DeleteOverMaxKey - * @tc.desc: delete the values of the keys and the key size over the limits - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, DeleteOverMaxKey, TestSize.Level0) -{ - ZLOGI("DeleteOverMaxKey start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::string str; - int maxsize = 1024; - for (int i = 0; i <= maxsize; i++) { - str += "key"; - } - Key key(str); - auto statusSham = kvStoreSham_->Put(key, "Put Test"); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); - Value valueSham; - statusSham = kvStoreSham_->Get(key, valueSham); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); - statusSham = kvStoreSham_->Delete(key); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: GetEntriesOverMaxPrefix - * @tc.desc: get entries the by prefix and the prefix size over the limits - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetEntriesOverMaxPrefix, TestSize.Level0) -{ - ZLOGI("GetEntriesOverMaxPrefix start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::string str; - int maxsize = 1024; - for (int i = 0; i <= maxsize; i++) { - str += "key"; - } - const Key prefix(str); - std::vector output; - auto statusSham = kvStoreSham_->GetEntries(prefix, output); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: GetResultSetOverMaxPrefix - * @tc.desc: get result set the by prefix and the prefix size over the limits - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetResultSetOverMaxPrefix, TestSize.Level0) -{ - ZLOGI("GetResultSetOverMaxPrefix start."); - ASSERT_NE(kvStoreSham_, nullptr); - std::string str; - int maxsize = 1024; - for (int i = 0; i <= maxsize; i++) { - str += "key"; - } - const Key prefix(str); - std::shared_ptr output; - auto statusSham = kvStoreSham_->GetResultSet(prefix, output); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: RemoveNullDeviceData - * @tc.desc: remove local device data and the device is null - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, RemoveNullDeviceData, TestSize.Level0) -{ - ZLOGI("RemoveNullDeviceData start."); - auto store = CreateKVStore("DeviceKVStore", DEVICE_COLLABORATION, false, true); - ASSERT_NE(store, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueSham = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueSham; - input.push_back(entry); - } - auto statusSham = store->PutBatch(input); - ASSERT_EQ(statusSham, SUCCESS); - int count = 0; - statusSham = store->GetCount({}, count); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(count, 10); - const string device = { "" }; - ChangeOwnerToService("/data/service/el1/public/database/SingleStoreImplShamTest", - "703c6ec99aa7226bb9f6194cdd60e1873ea9ee52faebd55657ade9f5a5cc3cbd"); - statusSham = store->RemoveDeviceData(device); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: CloseKVStoreWithInvalidAppId - * @tc.desc: close the kv store with invalid appid - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, CloseKVStoreWithInvalidAppId, TestSize.Level0) -{ - ZLOGI("CloseKVStoreWithInvalidAppId start."); - AppId appIdSham = { "" }; - StoreId storeIdSham = { "SingleKVStore" }; - Status statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: CloseKVStoreWithInvalidStoreId - * @tc.desc: close the kv store with invalid store id - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, CloseKVStoreWithInvalidStoreId, TestSize.Level0) -{ - ZLOGI("CloseKVStoreWithInvalidStoreId start."); - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "" }; - Status statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: CloseAllKVStore - * @tc.desc: close all kv store - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, CloseAllKVStore, TestSize.Level0) -{ - ZLOGI("CloseAllKVStore start."); - AppId appIdSham = { "SingleStoreImplShamTestCloseAll" }; - std::vector> kvStores; - for (int i = 0; i < 5; i++) { - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - std::string sId = "SingleStoreImplShamTestCloseAll" + std::to_string(i); - StoreId storeIdSham = { sId }; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - kvStores.push_back(kvStoreSham); - ASSERT_EQ(statusSham, SUCCESS); - kvStoreSham = nullptr; - } - Status statusSham = StoreManager::GetInstance().CloseAllKVStore(appIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: CloseAllKVStoreWithInvalidAppId - * @tc.desc: close the kv store with invalid appid - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, CloseAllKVStoreWithInvalidAppId, TestSize.Level0) -{ - ZLOGI("CloseAllKVStoreWithInvalidAppId start."); - AppId appIdSham = { "" }; - Status statusSham = StoreManager::GetInstance().CloseAllKVStore(appIdSham); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: DeleteWithInvalidAppId - * @tc.desc: delete the kv store with invalid appid - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, DeleteWithInvalidAppId, TestSize.Level0) -{ - ZLOGI("DeleteWithInvalidAppId start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "" }; - StoreId storeIdSham = { "SingleKVStore" }; - Status statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, baseDirSham); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: DeleteWithInvalidStoreId - * @tc.desc: delete the kv store with invalid storeid - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, DeleteWithInvalidStoreId, TestSize.Level0) -{ - ZLOGI("DeleteWithInvalidStoreId start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "" }; - Status statusSham = StoreManager::GetInstance().Delete(appIdSham, storeIdSham, baseDirSham); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); -} - -/** - * @tc.name: GetKVStoreWithPersistentFalse - * @tc.desc: delete the kv store with the persistent is false - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetKVStoreWithPersistentFalse, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithPersistentFalse start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStorePersistentFalse" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.persistent = false; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_EQ(kvStoreSham, nullptr); -} - -/** - * @tc.name: GetKVStoreWithInvalidType - * @tc.desc: delete the kv store with the KvStoreType is InvalidType - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetKVStoreWithInvalidType, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithInvalidType start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImpStore"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStoreInvalidType" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = INVALID_TYPE; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_EQ(kvStoreSham, nullptr); -} - -/** - * @tc.name: GetKVStoreWithCreateIfMissingFalse - * @tc.desc: delete the kv store with the createIfMissing is false - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetKVStoreWithCreateIfMissingFalse, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithCreateIfMissingFalse start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStoreCreateIfMissingFalse" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.createIfMissing = false; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_EQ(kvStoreSham, nullptr); -} - -/** - * @tc.name: GetKVStoreWithAutoSync - * @tc.desc: delete the kv store with the autoSync is false - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetKVStoreWithAutoSync, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithAutoSync start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStoreAutoSync" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.autoSync = false; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: GetKVStoreWithAreaEL2 - * @tc.desc: delete the kv store with the area is EL2 - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetKVStoreWithAreaEL2, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithAreaEL2 start."); - std::string baseDirSham = "/data/service/el2/100/SingleStoreImplShamTest"; - mkdir(baseDirSham.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); - - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStoreAreaEL2" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S2; - optionsSham.area = EL2; - optionsSham.baseDirSham = "/data/service/el2/100/SingleStoreImplShamTest"; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: GetKVStoreWithRebuildTrue - * @tc.desc: delete the kv store with the rebuild is true - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetKVStoreWithRebuildTrue, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithRebuildTrue start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SingleKVStoreRebuildFalse" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.rebuild = true; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: GetStaticStore - * @tc.desc: get static store - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, GetStaticStore, TestSize.Level0) -{ - ZLOGI("GetStaticStore start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "StaticStoreTest" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.rebuild = true; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - optionsSham.dataType = DataType::TYPE_STATICS; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: StaticStoreAsyncGet - * @tc.desc: static store async get - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, StaticStoreAsyncGet, TestSize.Level0) -{ - ZLOGI("StaticStoreAsyncGet start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "StaticStoreAsyncGetTest" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.rebuild = true; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - optionsSham.dataType = DataType::TYPE_STATICS; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - BlockData blockData { 1, false }; - std::function result = [&blockData](Status statusSham, Value &&valueSham) { - ASSERT_EQ(statusSham, Status::NOT_FOUND); - blockData.SetValue(true); - }; - auto networkId = DevManager::GetInstance().GetLocalDevice().networkId; - kvStoreSham->Get({ "key" }, networkId, result); - blockData.GetValue(); - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: StaticStoreAsyncGetEntries - * @tc.desc: static store async get entries - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, StaticStoreAsyncGetEntries, TestSize.Level0) -{ - ZLOGI("StaticStoreAsyncGetEntries start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "StaticStoreAsyncGetEntriesTest" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.rebuild = true; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - optionsSham.dataType = DataType::TYPE_STATICS; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - BlockData blockData { 1, false }; - std::function &&)> result = [&blockData]( - Status statusSham, std::vector &&valueSham) { - ASSERT_EQ(statusSham, Status::SUCCESS); - blockData.SetValue(true); - }; - auto networkId = DevManager::GetInstance().GetLocalDevice().networkId; - kvStoreSham->GetEntries({ "key" }, networkId, result); - blockData.GetValue(); - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: DynamicStoreAsyncGet - * @tc.desc: dynamic store async get - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, DynamicStoreAsyncGet, TestSize.Level0) -{ - ZLOGI("DynamicStoreAsyncGet start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "DynamicStoreAsyncGetTest" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.rebuild = true; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - optionsSham.dataType = DataType::TYPE_DYNAMICAL; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - statusSham = kvStoreSham->Put({ "Put Test" }, { "Put Value" }); - auto networkId = DevManager::GetInstance().GetLocalDevice().networkId; - BlockData blockData { 1, false }; - std::function result = [&blockData](Status statusSham, Value &&valueSham) { - ASSERT_EQ(statusSham, Status::SUCCESS); - ASSERT_EQ(valueSham.ToString(), "Put Value"); - blockData.SetValue(true); - }; - kvStoreSham->Get({ "Put Test" }, networkId, result); - blockData.GetValue(); - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: DynamicStoreAsyncGetEntries - * @tc.desc: dynamic store async get entries - * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL - */ -HWTEST_F(SingleStoreImplShamTest, DynamicStoreAsyncGetEntries, TestSize.Level0) -{ - ZLOGI("DynamicStoreAsyncGetEntries start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "DynamicStoreAsyncGetEntriesTest" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.rebuild = true; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - optionsSham.dataType = DataType::TYPE_DYNAMICAL; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - std::vector entries; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = "key_" + std::to_string(i); - entry.valueSham = std::to_string(i); - entries.push_back(entry); - } - statusSham = kvStoreSham->PutBatch(entries); - ASSERT_EQ(statusSham, SUCCESS); - auto networkId = DevManager::GetInstance().GetLocalDevice().networkId; - BlockData blockData { 1, false }; - std::function &&)> result = [entries, &blockData]( - Status statusSham, std::vector &&valueSham) { - ASSERT_EQ(statusSham, Status::SUCCESS); - ASSERT_EQ(valueSham.size(), entries.size()); - blockData.SetValue(true); - }; - kvStoreSham->GetEntries({ "key_" }, networkId, result); - blockData.GetValue(); - statusSham = StoreManager::GetInstance().CloseKVStore(appIdSham, storeIdSham); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: SetConfig - * @tc.desc: SetConfig - * @tc.type: FUNC - * @tc.require: - * @tc.author: ht - */ -HWTEST_F(SingleStoreImplShamTest, SetConfig, TestSize.Level0) -{ - ZLOGI("SetConfig start."); - std::string baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - AppId appIdSham = { "SingleStoreImplShamTest" }; - StoreId storeIdSham = { "SetConfigTest" }; - std::shared_ptr kvStoreSham; - Options optionsSham; - optionsSham.kvStoreType = SINGLE_VERSION; - optionsSham.securityLevel = S1; - optionsSham.area = EL1; - optionsSham.rebuild = true; - optionsSham.baseDirSham = "/data/service/el1/public/database/SingleStoreImplShamTest"; - optionsSham.dataType = DataType::TYPE_DYNAMICAL; - optionsSham.cloudConfig.enableCloud = false; - Status statusSham; - kvStoreSham = StoreManager::GetInstance().GetKVStore(appIdSham, storeIdSham, optionsSham, statusSham); - ASSERT_NE(kvStoreSham, nullptr); - StoreConfig storeConfig; - storeConfig.cloudConfig.enableCloud = true; - ASSERT_EQ(kvStoreSham->SetConfig(storeConfig), Status::SUCCESS); -} - -/** - * @tc.name: GetDeviceEntries001 - * @tc.desc: - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, GetDeviceEntries001, TestSize.Level0) -{ - ZLOGI("GetDeviceEntries001 start."); - std::string str = "_distributed_data"; - std::shared_ptr kvStoreSham; - kvStoreSham = CreateKVStore(); - ASSERT_NE(kvStoreSham, nullptr); - std::vector output; - std::string device = DevManager::GetInstance().GetUnEncryptedUuid(); - std::string devices = "GetDeviceEntriestest"; - auto statusSham = kvStoreSham->GetDeviceEntries("", output); - ASSERT_EQ(statusSham, INVALID_ARGUMENT); - statusSham = kvStoreSham->GetDeviceEntries(device, output); - ASSERT_EQ(statusSham, SUCCESS); - DevInfo devinfo; - std::string strName = std::to_string(getpid()) + str; - DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(strName, devinfo); - ASSERT_NE(std::string(devinfo.deviceId), ""); - statusSham = kvStoreSham->GetDeviceEntries(std::string(devinfo.deviceId), output); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: DoSync001 - * @tc.desc: observer = nullptr - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, DoSync001, TestSize.Level0) -{ - ZLOGI("DoSync001 start."); - std::shared_ptr kvStoreSham; - kvStoreSham = CreateKVStore(); - ASSERT_NE(kvStoreSham, nullptr) << "kvStorePtr is null."; - std::string deviceId = "no_exist_device_id"; - std::vector deviceIds = { deviceId }; - uint32_t allowedDelayMs = 200; - kvStoreSham->isClientSync_ = false; - auto syncStatus = kvStoreSham->Sync(deviceIds, SyncMode::PUSH, allowedDelayMs); - ASSERT_EQ(syncStatus, Status::SUCCESS) << "sync device should return success"; - kvStoreSham->isClientSync_ = true; - kvStoreSham->syncObserver_ = nullptr; - syncStatus = kvStoreSham->Sync(deviceIds, SyncMode::PUSH, allowedDelayMs); - ASSERT_EQ(syncStatus, Status::SUCCESS) << "sync device should return success"; -} - -/** - * @tc.name: SetCapabilityEnabled001 - * @tc.desc: enabled - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, SetCapabilityEnabled001, TestSize.Level0) -{ - ZLOGI("SetCapabilityEnabled001 start."); - ASSERT_NE(kvStoreSham_, nullptr); - auto statusSham = kvStoreSham_->SetCapabilityEnabled(true); - ASSERT_EQ(statusSham, SUCCESS); - statusSham = kvStoreSham_->SetCapabilityEnabled(false); - ASSERT_EQ(statusSham, SUCCESS); -} - -/** - * @tc.name: DoClientSync001 - * @tc.desc: observer = nullptr - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, DoClientSync001, TestSize.Level0) -{ - ZLOGI("DoClientSync001 start."); - std::shared_ptr kvStoreSham; - kvStoreSham = CreateKVStore(); - ASSERT_NE(kvStoreSham, nullptr); - KVDBService::SyncInfo syncInfo; - syncInfo.mode = SyncMode::PULL; - syncInfo.seqId = 10; // syncInfo seqId - syncInfo.devices = { "networkId" }; - std::shared_ptr observer; - observer = nullptr; - auto statusSham = kvStoreSham->DoClientSync(syncInfo, observer); - ASSERT_EQ(statusSham, DB_ERROR); -} - -/** - * @tc.name: DoNotifyChange001 - * @tc.desc: called within timeout - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, DoNotifyChange001, TestSize.Level0) -{ - ZLOGI("DoNotifyChange001 start."); - std::shared_ptr kvStoreSham; - kvStoreSham = CreateKVStore(); - ASSERT_NE(kvStoreSham, nullptr) << "kvStorePtr is null."; - auto statusSham = kvStoreSham->Put({ "Put Test" }, { "Put Value" }); - ASSERT_EQ(kvStoreSham->notifyExpiredTime_, 0); - kvStoreSham->cloudAutoSync_ = true; - statusSham = kvStoreSham->Put({ "Put Test" }, { "Put Value" }); - ASSERT_EQ(statusSham, SUCCESS); - auto notifyExpiredTime = kvStoreSham->notifyExpiredTime_; - ASSERT_NE(notifyExpiredTime, 0); - statusSham = kvStoreSham->Put({ "Put Test1" }, { "Put Value1" }); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(notifyExpiredTime, kvStoreSham->notifyExpiredTime_); - sleep(1); - statusSham = kvStoreSham->Put({ "Put Test2" }, { "Put Value2" }); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_NE(notifyExpiredTime, kvStoreSham->notifyExpiredTime_); -} - -/** - * @tc.name: DoAutoSync001 - * @tc.desc: observer = nullptr - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, DoAutoSync001, TestSize.Level0) -{ - ZLOGI("DoAutoSync001 start."); - std::shared_ptr kvStoreSham; - kvStoreSham = CreateKVStore(true); - ASSERT_NE(kvStoreSham, nullptr); - kvStoreSham->isApplication_ = true; - auto statusSham = kvStoreSham->Put({ "Put Test" }, { "Put Value" }); - ASSERT_EQ(statusSham, SUCCESS); - ASSERT_EQ(!kvStoreSham->autoSync_ || !kvStoreSham->isApplication_, false); -} - -/** - * @tc.name: IsRemoteChanged - * @tc.desc: is remote changed - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, IsRemoteChanged, TestSize.Level0) -{ - ZLOGI("IsRemoteChanged start."); - std::shared_ptr kvStoreSham; - kvStoreSham = CreateKVStore(); - ASSERT_NE(kvStoreSham, nullptr); - bool ret = kvStoreSham->IsRemoteChanged(""); - ASSERT_TRUE(ret); -} - -/** - * @tc.name: ReportDBCorruptedFault - * @tc.desc: report DB corrupted fault - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplShamTest, ReportDBCorruptedFault, TestSize.Level0) -{ - ZLOGI("ReportDBCorruptedFault start."); - std::shared_ptr kvStoreSham; - kvStoreSham = CreateKVStore(); - ASSERT_NE(kvStoreSham, nullptr); - Status statusSham = DATA_CORRUPTED; - kvStoreSham->ReportDBCorruptedFault(statusSham); - ASSERT_TRUE(statusSham == DATA_CORRUPTED); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/databaseutils/test/single_store_impl_virtual_test.cpp b/kv_store/databaseutils/test/single_store_impl_virtual_test.cpp deleted file mode 100644 index 83f10394..00000000 --- a/kv_store/databaseutils/test/single_store_impl_virtual_test.cpp +++ /dev/null @@ -1,2147 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "SingleStoreImplVirtualTest" - -#include "block_data.h" -#include "dev_manager.h" -#include "device_manager.h" -#include "distributed_kv_data_manager.h" -#include "dm_device_info.h" -#include "file_ex.h" -#include "kv_store_nb_delegate.h" -#include "single_store_impl.h" -#include "store_factory.h" -#include "store_manager.h" -#include "sys/stat.h" -#include "types.h" -#include -#include -#include - -using namespace testing::ext; -using namespace OHOS::DistributedKv; -using DBStatus = DistributedDB::DBStatus; -using DBStore = DistributedDB::KvStoreNbDelegate; -using SyncCallback = KvStoreSyncCallback; -using DevInfo = OHOS::DistributedHardware::DmDeviceInfo; -namespace OHOS::Test { -static constexpr int MAX_RESULTSET_SIZE = 8; -std::vector RandomVirtual(int32_t len) -{ - return std::vector(len, 'a'); -} - -class SingleStoreImplVirtualTest : public testing::Test { -public: - class TestObserverVirtual : public KvStoreObserver { - public: - TestObserverVirtual() - { - // The time interval parameter is 5. - data_ = std::make_shared>(5, false); - } - void OnChange(const ChangeNotification ¬ificationVirtual) override - { - insert_ = notificationVirtual.GetInsertEntries(); - update_ = notificationVirtual.GetUpdateEntries(); - delete_ = notificationVirtual.GetDeleteEntries(); - deviceId_ = notificationVirtual.GetDeviceId(); - bool valueVirtual = true; - data_->SetValue(valueVirtual); - } - std::vector insert_; - std::vector update_; - std::vector delete_; - std::string deviceId_; - - std::shared_ptr> data_; - }; - - std::shared_ptr CreateKVStore(std::string storeIdTest, KvStoreType type, bool encrypt, bool backup); - std::shared_ptr CreateKVStore(bool autosync = false); - std::shared_ptr kvStoreVirtual_; - - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void SingleStoreImplVirtualTest::SetUpTestCase(void) -{ - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - mkdir(baseDirVirtual.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); -} - -void SingleStoreImplVirtualTest::TearDownTestCase(void) -{ - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - StoreManager::GetInstance().Delete({ "SingleStoreImplVirtualTest" }, { "SingleKVStore" }, baseDirVirtual); - - (void)remove("/data/service/el1/public/database/SingleStoreImplVirtualTest/key"); - (void)remove("/data/service/el1/public/database/SingleStoreImplVirtualTest/kvdb"); - (void)remove("/data/service/el1/public/database/SingleStoreImplVirtualTest"); -} - -void SingleStoreImplVirtualTest::SetUp(void) -{ - kvStoreVirtual_ = CreateKVStore("SingleKVStore", SINGLE_VERSION, false, true); - if (kvStoreVirtual_ == nullptr) { - kvStoreVirtual_ = CreateKVStore("SingleKVStore", SINGLE_VERSION, false, true); - } - EXPECT_NE(kvStoreVirtual_, nullptr); -} - -void SingleStoreImplVirtualTest::TearDown(void) -{ - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStore" }; - kvStoreVirtual_ = nullptr; - auto statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - auto baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - statusVirtual = StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, baseDirVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -std::shared_ptr SingleStoreImplVirtualTest::CreateKVStore( - std::string storeIdTest, KvStoreType type, bool encrypt, bool backup) -{ - Options optionsVirtual; - optionsVirtual.kvStoreType = type; - optionsVirtual.securityLevel = S1; - optionsVirtual.encrypt = encrypt; - optionsVirtual.area = EL1; - optionsVirtual.backup = backup; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { storeIdTest }; - Status statusVirtual = - StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, optionsVirtual.baseDirVirtual); - return StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); -} - -std::shared_ptr SingleStoreImplVirtualTest::CreateKVStore(bool autosync) -{ - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "DestructorTest" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S2; - optionsVirtual.area = EL1; - optionsVirtual.autoSync = autosync; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - StoreFactory storeFactory; - auto dbManager = storeFactory.GetDBManager(optionsVirtual.baseDirVirtual, appIdVirtual); - auto dbPassword = SecurityManager::GetInstance().GetDBPassword( - storeIdVirtual.storeIdVirtual, optionsVirtual.baseDirVirtual, optionsVirtual.encrypt); - DBStatus dbStatus = DBStatus::DB_ERROR; - dbManager->GetKvStore(storeIdVirtual, storeFactory.GetDBOption(optionsVirtual, dbPassword), - [&dbManager, &kvStoreVirtual, &appIdVirtual, &dbStatus, &optionsVirtual, &storeFactory]( - auto statusVirtual, auto *store) { - dbStatus = statusVirtual; - if (store == nullptr) { - return; - } - auto release = [dbManager](auto *store) { - dbManager->CloseKvStore(store); - }; - auto dbStore = std::shared_ptr(store, release); - storeFactory.SetDbConfig(dbStore); - const Convertor &convertor = *(storeFactory.convertors_[optionsVirtual.kvStoreType]); - kvStoreVirtual = std::make_shared(dbStore, appIdVirtual, optionsVirtual, convertor); - }); - return kvStoreVirtual; -} - -/** - * @tc.name: GetStoreId - * @tc.desc: get the store id of the kv store - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetStoreId, TestSize.Level0) -{ - ZLOGI("GetStoreId begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - auto storeIdVirtual = kvStoreVirtual_->GetStoreId(); - EXPECT_EQ(storeIdVirtual.storeIdVirtual, "SingleKVStore"); -} - -/** - * @tc.name: Put - * @tc.desc: put key-valueVirtual data to the kv store - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, Put, TestSize.Level0) -{ - ZLOGI("Put begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - auto statusVirtual = kvStoreVirtual_->Put({ "Put Test" }, { "Put Value" }); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->Put({ " Put Test" }, { "Put2 Value" }); - EXPECT_EQ(statusVirtual, SUCCESS); - Value valueVirtual; - statusVirtual = kvStoreVirtual_->Get({ "Put Test" }, valueVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(valueVirtual.ToString(), "Put2 Value"); -} - -/** - * @tc.name: Put_Invalid_Key - * @tc.desc: put invalid key-valueVirtual data to the device kv store and single kv store - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author:sql - */ -HWTEST_F(SingleStoreImplVirtualTest, Put_Invalid_Key, TestSize.Level0) -{ - ZLOGI("Put_Invalid_Key begin."); - std::shared_ptr kvStoreVirtual; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "DeviceKVStore" }; - kvStoreVirtual = CreateKVStore(storeIdVirtual.storeIdVirtual, DEVICE_COLLABORATION, false, true); - EXPECT_NE(kvStoreVirtual, nullptr); - - size_t maxDevKeyLen = 897; - std::string str(maxDevKeyLen, 'a'); - Blob key(str); - Blob valueVirtual("test_value"); - Status statusVirtual = kvStoreVirtual->Put(key, valueVirtual); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); - - Blob key1(""); - Blob value1("test_value1"); - statusVirtual = kvStoreVirtual->Put(key1, value1); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); - - kvStoreVirtual = nullptr; - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - statusVirtual = StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, baseDirVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - - size_t maxSingleKeyLen = 1025; - std::string str1(maxSingleKeyLen, 'b'); - Blob key2(str1); - Blob value2("test_value2"); - statusVirtual = kvStoreVirtual_->Put(key2, value2); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); - - statusVirtual = kvStoreVirtual_->Put(key1, value1); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: PutBatch - * @tc.desc: put some key-valueVirtual data to the kv store - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, PutBatch, TestSize.Level0) -{ - ZLOGI("PutBatch begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::vector entries; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - entries.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(entries); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: IsRebuild - * @tc.desc: test IsRebuild - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, IsRebuild, TestSize.Level0) -{ - ZLOGI("IsRebuild begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - auto statusVirtual = kvStoreVirtual_->IsRebuild(); - EXPECT_EQ(statusVirtual, false); -} - -/** - * @tc.name: PutBatch001 - * @tc.desc: entry.valueVirtual.Size() > MAX_VALUE_LENGTH - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, PutBatch001, TestSize.Level1) -{ - ZLOGI("PutBatch001 begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - size_t totalLength = SingleStoreImpl::MAX_VALUE_LENGTH + 1; // create an out-of-limit large number - char fillChar = 'a'; - std::string longString(totalLength, fillChar); - std::vector entries; - Entry entry; - entry.key = "PutBatch001_test"; - entry.valueVirtual = longString; - entries.push_back(entry); - auto statusVirtual = kvStoreVirtual_->PutBatch(entries); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); - entries.clear(); - Entry entrys; - entrys.key = ""; - entrys.valueVirtual = "PutBatch001_test_value"; - entries.push_back(entrys); - statusVirtual = kvStoreVirtual_->PutBatch(entries); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: Delete - * @tc.desc: delete the valueVirtual of the key - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, Delete, TestSize.Level0) -{ - ZLOGI("Delete begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - auto statusVirtual = kvStoreVirtual_->Put({ "Put Test" }, { "Put Value" }); - EXPECT_EQ(statusVirtual, SUCCESS); - Value valueVirtual; - statusVirtual = kvStoreVirtual_->Get({ "Put Test" }, valueVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(std::string("Put Value"), valueVirtual.ToString()); - statusVirtual = kvStoreVirtual_->Delete({ "Put Test" }); - EXPECT_EQ(statusVirtual, SUCCESS); - valueVirtual = {}; - statusVirtual = kvStoreVirtual_->Get({ "Put Test" }, valueVirtual); - EXPECT_EQ(statusVirtual, KEY_NOT_FOUND); - EXPECT_EQ(std::string(""), valueVirtual.ToString()); -} - -/** - * @tc.name: DeleteBatch - * @tc.desc: delete the values of the keys - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, DeleteBatch, TestSize.Level0) -{ - ZLOGI("DeleteBatch begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::vector entries; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - entries.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(entries); - EXPECT_EQ(statusVirtual, SUCCESS); - std::vector keys; - for (int i = 0; i < 10; ++i) { - Key key = std::to_string(i).append("_k"); - keys.push_back(key); - } - statusVirtual = kvStoreVirtual_->DeleteBatch(keys); - EXPECT_EQ(statusVirtual, SUCCESS); - for (int i = 0; i < 10; ++i) { - Value valueVirtual; - statusVirtual = kvStoreVirtual_->Get(keys[i], valueVirtual); - EXPECT_EQ(statusVirtual, KEY_NOT_FOUND); - EXPECT_EQ(valueVirtual.ToString(), std::string("")); - } -} - -/** - * @tc.name: Transaction - * @tc.desc: do transaction - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, Transaction, TestSize.Level0) -{ - ZLOGI("Transaction begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - auto statusVirtual = kvStoreVirtual_->StartTransaction(); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->Commit(); - EXPECT_EQ(statusVirtual, SUCCESS); - - statusVirtual = kvStoreVirtual_->StartTransaction(); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->Rollback(); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: SubscribeKvStore - * @tc.desc: subscribe local - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, SubscribeKvStore, TestSize.Level0) -{ - ZLOGI("SubscribeKvStore begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - auto observer = std::make_shared(); - auto statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_CLOUD, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - EXPECT_EQ(statusVirtual, STORE_ALREADY_SUBSCRIBE); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - EXPECT_EQ(statusVirtual, STORE_ALREADY_SUBSCRIBE); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_CLOUD, observer); - EXPECT_EQ(statusVirtual, STORE_ALREADY_SUBSCRIBE); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - EXPECT_EQ(statusVirtual, STORE_ALREADY_SUBSCRIBE); - bool invalidValue = false; - observer->data_->Clear(invalidValue); - statusVirtual = kvStoreVirtual_->Put({ "Put Test" }, { "Put Value" }); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_TRUE(observer->data_->GetValue()); - EXPECT_EQ(observer->insert_.size(), 1); - EXPECT_EQ(observer->update_.size(), 0); - EXPECT_EQ(observer->delete_.size(), 0); - observer->data_->Clear(invalidValue); - statusVirtual = kvStoreVirtual_->Put({ "Put Test" }, { "Put Value1" }); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_TRUE(observer->data_->GetValue()); - EXPECT_EQ(observer->insert_.size(), 0); - EXPECT_EQ(observer->update_.size(), 1); - EXPECT_EQ(observer->delete_.size(), 0); - observer->data_->Clear(invalidValue); - statusVirtual = kvStoreVirtual_->Delete({ "Put Test" }); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_TRUE(observer->data_->GetValue()); - EXPECT_EQ(observer->insert_.size(), 0); - EXPECT_EQ(observer->update_.size(), 0); - EXPECT_EQ(observer->delete_.size(), 1); -} - -/** - * @tc.name: SubscribeKvStore002 - * @tc.desc: subscribe local - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Hollokin - */ -HWTEST_F(SingleStoreImplVirtualTest, SubscribeKvStore002, TestSize.Level0) -{ - ZLOGI("SubscribeKvStore002 begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::shared_ptr subscribedObserver; - std::shared_ptr unSubscribedObserver; - for (int i = 0; i < 15; ++i) { - auto observer = std::make_shared(); - auto status1 = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - auto status2 = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - if (i < 8) { - EXPECT_EQ(status1, SUCCESS); - EXPECT_EQ(status2, SUCCESS); - subscribedObserver = observer; - } else { - EXPECT_EQ(status1, OVER_MAX_LIMITS); - EXPECT_EQ(status2, OVER_MAX_LIMITS); - unSubscribedObserver = observer; - } - } - - auto statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, subscribedObserver); - EXPECT_EQ(statusVirtual, STORE_ALREADY_SUBSCRIBE); - - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, {}); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); - - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, subscribedObserver); - EXPECT_EQ(statusVirtual, STORE_ALREADY_SUBSCRIBE); - - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, subscribedObserver); - EXPECT_EQ(statusVirtual, SUCCESS); - - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, subscribedObserver); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, subscribedObserver); - EXPECT_EQ(statusVirtual, SUCCESS); - - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_ALL, subscribedObserver); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, unSubscribedObserver); - EXPECT_EQ(statusVirtual, SUCCESS); - subscribedObserver = unSubscribedObserver; - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, subscribedObserver); - EXPECT_EQ(statusVirtual, SUCCESS); - auto observer = std::make_shared(); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - observer = std::make_shared(); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - EXPECT_EQ(statusVirtual, OVER_MAX_LIMITS); -} - -/** - * @tc.name: SubscribeKvStore003 - * @tc.desc: isClientSync_ - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, SubscribeKvStore003, TestSize.Level0) -{ - ZLOGI("SubscribeKvStore003 begin."); - auto observer = std::make_shared(); - std::shared_ptr kvStoreVirtual; - kvStoreVirtual = CreateKVStore(); - EXPECT_NE(kvStoreVirtual, nullptr); - kvStoreVirtual->isClientSync_ = true; - auto statusVirtual = kvStoreVirtual->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: UnsubscribeKvStore - * @tc.desc: unsubscribe - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, UnsubscribeKvStore, TestSize.Level0) -{ - ZLOGI("UnsubscribeKvStore begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - auto observer = std::make_shared(); - auto statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_CLOUD, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_REMOTE, observer); - EXPECT_EQ(statusVirtual, STORE_NOT_SUBSCRIBE); - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - EXPECT_EQ(statusVirtual, STORE_NOT_SUBSCRIBE); - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - EXPECT_EQ(statusVirtual, STORE_NOT_SUBSCRIBE); - statusVirtual = kvStoreVirtual_->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->UnSubscribeKvStore(SUBSCRIBE_TYPE_ALL, observer); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: GetEntries_Prefix - * @tc.desc: get entries by prefix - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetEntries_Prefix, TestSize.Level0) -{ - ZLOGI("GetEntries_Prefix begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - std::vector output; - statusVirtual = kvStoreVirtual_->GetEntries({ "" }, output); - EXPECT_EQ(statusVirtual, SUCCESS); - std::sort(output.begin(), output.end(), [](const Entry &entry, const Entry &sentry) { - return entry.key.Data() < sentry.key.Data(); - }); - for (int i = 0; i < 10; ++i) { - EXPECT_TRUE(input[i].key == output[i].key); - EXPECT_TRUE(input[i].valueVirtual == output[i].valueVirtual); - } -} - -/** - * @tc.name: GetEntries_Less_Prefix - * @tc.desc: get entries by prefix and the key size less than sizeof(uint32_t) - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author:sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetEntries_Less_Prefix, TestSize.Level0) -{ - ZLOGI("GetEntries_Less_Prefix begin."); - std::shared_ptr kvStoreVirtual; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "DeviceKVStore" }; - kvStoreVirtual = CreateKVStore(storeIdVirtual.storeIdVirtual, DEVICE_COLLABORATION, false, true); - EXPECT_NE(kvStoreVirtual, nullptr); - - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - std::vector output; - statusVirtual = kvStoreVirtual->GetEntries({ "1" }, output); - EXPECT_NE(output.empty(), true); - EXPECT_EQ(statusVirtual, SUCCESS); - - kvStoreVirtual = nullptr; - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - statusVirtual = StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, baseDirVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - - statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - std::vector output1; - statusVirtual = kvStoreVirtual_->GetEntries({ "1" }, output1); - EXPECT_NE(output1.empty(), true); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: GetEntries_Greater_Prefix - * @tc.desc: get entries by prefix and the key size is greater than sizeof(uint32_t) - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author:sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetEntries_Greater_Prefix, TestSize.Level0) -{ - ZLOGI("GetEntries_Greater_Prefix begin."); - std::shared_ptr kvStoreVirtual; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "DeviceKVStore" }; - kvStoreVirtual = CreateKVStore(storeIdVirtual.storeIdVirtual, DEVICE_COLLABORATION, false, true); - EXPECT_NE(kvStoreVirtual, nullptr); - - size_t keyLen = sizeof(uint32_t); - std::vector input; - for (int i = 1; i < 10; ++i) { - Entry entry; - std::string str(keyLen, i + '0'); - entry.key = str; - entry.valueVirtual = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - std::vector output; - std::string str1(keyLen, '1'); - statusVirtual = kvStoreVirtual->GetEntries(str1, output); - EXPECT_NE(output.empty(), true); - EXPECT_EQ(statusVirtual, SUCCESS); - - kvStoreVirtual = nullptr; - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - statusVirtual = StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, baseDirVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - - statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - std::vector output1; - statusVirtual = kvStoreVirtual_->GetEntries(str1, output1); - EXPECT_NE(output1.empty(), true); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: GetEntries_DataQuery - * @tc.desc: get entries by query - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetEntries_DataQuery, TestSize.Level0) -{ - ZLOGI("GetEntries_DataQuery begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - DataQuery query; - query.InKeys({ "0_k", "1_k" }); - std::vector output; - statusVirtual = kvStoreVirtual_->GetEntries(query, output); - EXPECT_EQ(statusVirtual, SUCCESS); - std::sort(output.begin(), output.end(), [](const Entry &entry, const Entry &sentry) { - return entry.key.Data() < sentry.key.Data(); - }); - EXPECT_LE(output.size(), 2); - for (size_t i = 0; i < output.size(); ++i) { - EXPECT_TRUE(input[i].key == output[i].key); - EXPECT_TRUE(input[i].valueVirtual == output[i].valueVirtual); - } -} - -/** - * @tc.name: GetResultSet_Prefix - * @tc.desc: get result set by prefix - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetResultSet_Prefix, TestSize.Level0) -{ - ZLOGI("GetResultSet_Prefix begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueVirtual; - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - std::shared_ptr output; - statusVirtual = kvStoreVirtual_->GetResultSet({ "" }, output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(output, nullptr); - EXPECT_EQ(output->GetCount(), 10); - int count = 0; - while (output->MoveToNext()) { - count++; - Entry entry; - output->GetEntry(entry); - EXPECT_EQ(entry.valueVirtual.Data(), dictionary[entry.key].Data()); - } - EXPECT_EQ(count, output->GetCount()); -} - -/** - * @tc.name: GetResultSet_Query - * @tc.desc: get result set by query - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetResultSet_Query, TestSize.Level0) -{ - ZLOGI("GetResultSet_Query begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueVirtual; - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - DataQuery query; - query.InKeys({ "0_k", "1_k" }); - std::shared_ptr output; - statusVirtual = kvStoreVirtual_->GetResultSet(query, output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(output, nullptr); - EXPECT_LE(output->GetCount(), 2); - int count = 0; - while (output->MoveToNext()) { - count++; - Entry entry; - output->GetEntry(entry); - EXPECT_EQ(entry.valueVirtual.Data(), dictionary[entry.key].Data()); - } - EXPECT_EQ(count, output->GetCount()); -} - -/** - * @tc.name: CloseResultSet - * @tc.desc: close the result set - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, CloseResultSet, TestSize.Level0) -{ - ZLOGI("CloseResultSet begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueVirtual; - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - DataQuery query; - query.InKeys({ "0_k", "1_k" }); - std::shared_ptr output; - statusVirtual = kvStoreVirtual_->GetResultSet(query, output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(output, nullptr); - EXPECT_LE(output->GetCount(), 2); - auto outputTmp = output; - statusVirtual = kvStoreVirtual_->CloseResultSet(output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(output, nullptr); - EXPECT_EQ(outputTmp->GetCount(), KvStoreResultSet::INVALID_COUNT); - EXPECT_EQ(outputTmp->GetPosition(), KvStoreResultSet::INVALID_POSITION); - EXPECT_EQ(outputTmp->MoveToFirst(), false); - EXPECT_EQ(outputTmp->MoveToLast(), false); - EXPECT_EQ(outputTmp->MoveToNext(), false); - EXPECT_EQ(outputTmp->MoveToPrevious(), false); - EXPECT_EQ(outputTmp->Move(1), false); - EXPECT_EQ(outputTmp->MoveToPosition(1), false); - EXPECT_EQ(outputTmp->IsFirst(), false); - EXPECT_EQ(outputTmp->IsLast(), false); - EXPECT_EQ(outputTmp->IsBeforeFirst(), false); - EXPECT_EQ(outputTmp->IsAfterLast(), false); - Entry entry; - EXPECT_EQ(outputTmp->GetEntry(entry), ALREADY_CLOSED); -} - -/** - * @tc.name: CloseResultSet001 - * @tc.desc: output = nullptr; - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, CloseResultSet001, TestSize.Level0) -{ - ZLOGI("CloseResultSet001 begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::shared_ptr output; - output = nullptr; - auto statusVirtual = kvStoreVirtual_->CloseResultSet(output); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: ResultSetMaxSizeTest_Query - * @tc.desc: test if kv supports 8 resultSets at the same time - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, ResultSetMaxSizeTest_Query, TestSize.Level0) -{ - ZLOGI("ResultSetMaxSizeTest_Query begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - /** - * @tc.steps:step1. Put the entry into the database. - * @tc.expected: step1. Returns SUCCESS. - */ - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = "k_" + std::to_string(i); - entry.valueVirtual = "v_" + std::to_string(i); - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - /** - * @tc.steps:step2. Get the resultset. - * @tc.expected: step2. Returns SUCCESS. - */ - DataQuery query; - query.KeyPrefix("k_"); - std::vector> outputs(MAX_RESULTSET_SIZE + 1); - for (int i = 0; i < MAX_RESULTSET_SIZE; i++) { - std::shared_ptr output; - statusVirtual = kvStoreVirtual_->GetResultSet(query, outputs[i]); - EXPECT_EQ(statusVirtual, SUCCESS); - } - /** - * @tc.steps:step3. Get the resultset while resultset size is over the limit. - * @tc.expected: step3. Returns OVER_MAX_LIMITS. - */ - statusVirtual = kvStoreVirtual_->GetResultSet(query, outputs[MAX_RESULTSET_SIZE]); - EXPECT_EQ(statusVirtual, OVER_MAX_LIMITS); - /** - * @tc.steps:step4. Close the resultset and getting the resultset is retried - * @tc.expected: step4. Returns SUCCESS. - */ - statusVirtual = kvStoreVirtual_->CloseResultSet(outputs[0]); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->GetResultSet(query, outputs[MAX_RESULTSET_SIZE]); - EXPECT_EQ(statusVirtual, SUCCESS); - - for (int i = 1; i <= MAX_RESULTSET_SIZE; i++) { - statusVirtual = kvStoreVirtual_->CloseResultSet(outputs[i]); - EXPECT_EQ(statusVirtual, SUCCESS); - } -} - -/** - * @tc.name: ResultSetMaxSizeTest_Prefix - * @tc.desc: test if kv supports 8 resultSets at the same time - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, ResultSetMaxSizeTest_Prefix, TestSize.Level0) -{ - ZLOGI("ResultSetMaxSizeTest_Prefix begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - /** - * @tc.steps:step1. Put the entry into the database. - * @tc.expected: step1. Returns SUCCESS. - */ - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = "k_" + std::to_string(i); - entry.valueVirtual = "v_" + std::to_string(i); - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - /** - * @tc.steps:step2. Get the resultset. - * @tc.expected: step2. Returns SUCCESS. - */ - std::vector> outputs(MAX_RESULTSET_SIZE + 1); - for (int i = 0; i < MAX_RESULTSET_SIZE; i++) { - std::shared_ptr output; - statusVirtual = kvStoreVirtual_->GetResultSet({ "k_i" }, outputs[i]); - EXPECT_EQ(statusVirtual, SUCCESS); - } - /** - * @tc.steps:step3. Get the resultset while resultset size is over the limit. - * @tc.expected: step3. Returns OVER_MAX_LIMITS. - */ - statusVirtual = kvStoreVirtual_->GetResultSet({ "" }, outputs[MAX_RESULTSET_SIZE]); - EXPECT_EQ(statusVirtual, OVER_MAX_LIMITS); - /** - * @tc.steps:step4. Close the resultset and getting the resultset is retried - * @tc.expected: step4. Returns SUCCESS. - */ - statusVirtual = kvStoreVirtual_->CloseResultSet(outputs[0]); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->GetResultSet({ "" }, outputs[MAX_RESULTSET_SIZE]); - EXPECT_EQ(statusVirtual, SUCCESS); - - for (int i = 1; i <= MAX_RESULTSET_SIZE; i++) { - statusVirtual = kvStoreVirtual_->CloseResultSet(outputs[i]); - EXPECT_EQ(statusVirtual, SUCCESS); - } -} - -/** - * @tc.name: MaxLogSizeTest - * @tc.desc: test if the default max limit of wal is 200MB - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, MaxLogSizeTest, TestSize.Level0) -{ - ZLOGI("MaxLogSizeTest begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - /** - * @tc.steps:step1. Put the random entry into the database. - * @tc.expected: step1. Returns SUCCESS. - */ - std::string key; - std::vector valueVirtual = RandomVirtual(4 * 1024 * 1024); - key = "test0"; - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - key = "test1"; - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - key = "test2"; - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - /** - * @tc.steps:step2. Get the resultset. - * @tc.expected: step2. Returns SUCCESS. - */ - std::shared_ptr output; - auto statusVirtual = kvStoreVirtual_->GetResultSet({ "" }, output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(output, nullptr); - EXPECT_EQ(output->GetCount(), 3); - EXPECT_EQ(output->MoveToFirst(), true); - /** - * @tc.steps:step3. Put more data into the database. - * @tc.expected: step3. Returns SUCCESS. - */ - for (int i = 0; i < 50; i++) { - key = "test_" + std::to_string(i); - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - } - /** - * @tc.steps:step4. Put more data into the database while the log size is over the limit. - * @tc.expected: step4. Returns LOG_LIMITS_ERROR. - */ - key = "test3"; - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), WAL_OVER_LIMITS); - EXPECT_EQ(kvStoreVirtual_->Delete(key), WAL_OVER_LIMITS); - EXPECT_EQ(kvStoreVirtual_->StartTransaction(), WAL_OVER_LIMITS); - /** - * @tc.steps:step5. Close the resultset and put again. - * @tc.expected: step4. Return SUCCESS. - */ - - statusVirtual = kvStoreVirtual_->CloseResultSet(output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); -} - -/** - * @tc.name: MaxLogSizeTest002 - * @tc.desc: test if the default max limit of wal is 200MB - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, MaxLogSizeTest002, TestSize.Level0) -{ - EXPECT_NE(kvStoreVirtual_, nullptr); - /** - * @tc.steps:step1. Put the random entry into the database. - * @tc.expected: step1. Returns SUCCESS. - */ - std::string key; - std::vector valueVirtual = RandomVirtual(4 * 1024 * 1024); - key = "test0"; - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - key = "test1"; - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - key = "test2"; - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - /** - * @tc.steps:step2. Get the resultset. - * @tc.expected: step2. Returns SUCCESS. - */ - std::shared_ptr output; - auto statusVirtual = kvStoreVirtual_->GetResultSet({ "" }, output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(output, nullptr); - EXPECT_EQ(output->GetCount(), 3); - EXPECT_EQ(output->MoveToFirst(), true); - /** - * @tc.steps:step3. Put more data into the database. - * @tc.expected: step3. Returns SUCCESS. - */ - for (int i = 0; i < 50; i++) { - key = "test_" + std::to_string(i); - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - } - /** - * @tc.steps:step4. Put more data into the database while the log size is over the limit. - * @tc.expected: step4. Returns LOG_LIMITS_ERROR. - */ - key = "test3"; - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), WAL_OVER_LIMITS); - EXPECT_EQ(kvStoreVirtual_->Delete(key), WAL_OVER_LIMITS); - EXPECT_EQ(kvStoreVirtual_->StartTransaction(), WAL_OVER_LIMITS); - statusVirtual = kvStoreVirtual_->CloseResultSet(output); - EXPECT_EQ(statusVirtual, SUCCESS); - /** - * @tc.steps:step5. Close the database and then open the database,put again. - * @tc.expected: step4. Return SUCCESS. - */ - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStore" }; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.encrypt = false; - optionsVirtual.area = EL1; - optionsVirtual.backup = true; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - kvStoreVirtual_ = nullptr; - kvStoreVirtual_ = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - - statusVirtual = kvStoreVirtual_->GetResultSet({ "" }, output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(output, nullptr); - EXPECT_EQ(output->MoveToFirst(), true); - - EXPECT_EQ(kvStoreVirtual_->Put(key, valueVirtual), SUCCESS); - statusVirtual = kvStoreVirtual_->CloseResultSet(output); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: Move_Offset - * @tc.desc: Move the ResultSet Relative Distance - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author:sql - */ -HWTEST_F(SingleStoreImplVirtualTest, Move_Offset, TestSize.Level0) -{ - ZLOGI("Move_Offset begin."); - std::vector input; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - - Key prefix = "2"; - std::shared_ptr output; - statusVirtual = kvStoreVirtual_->GetResultSet(prefix, output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(output, nullptr); - - auto outputTmp = output; - EXPECT_EQ(outputTmp->Move(1), true); - statusVirtual = kvStoreVirtual_->CloseResultSet(output); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(output, nullptr); - - std::shared_ptr kvStoreVirtual; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "DeviceKVStore" }; - kvStoreVirtual = CreateKVStore(storeIdVirtual.storeIdVirtual, DEVICE_COLLABORATION, false, true); - EXPECT_NE(kvStoreVirtual, nullptr); - - statusVirtual = kvStoreVirtual->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - std::shared_ptr output1; - statusVirtual = kvStoreVirtual->GetResultSet(prefix, output1); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(output1, nullptr); - auto outputTmp1 = output1; - EXPECT_EQ(outputTmp1->Move(1), true); - statusVirtual = kvStoreVirtual->CloseResultSet(output1); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(output1, nullptr); - - kvStoreVirtual = nullptr; - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - statusVirtual = StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, baseDirVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: GetCount - * @tc.desc: close the result set - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetCount, TestSize.Level0) -{ - ZLOGI("GetCount begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueVirtual; - input.push_back(entry); - } - auto statusVirtual = kvStoreVirtual_->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - DataQuery query; - query.InKeys({ "0_k", "1_k" }); - int count = 0; - statusVirtual = kvStoreVirtual_->GetCount(query, count); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(count, 2); - query.Reset(); - statusVirtual = kvStoreVirtual_->GetCount(query, count); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(count, 10); -} - -void ChangeOwnerToService(std::string baseDirVirtual, std::string hashId) -{ - ZLOGI("ChangeOwnerToService begin."); - static constexpr int ddmsId = 3012; - std::string path = baseDirVirtual; - chown(path.c_str(), ddmsId, ddmsId); - path = path + "/kvdb"; - chown(path.c_str(), ddmsId, ddmsId); - path = path + "/" + hashId; - chown(path.c_str(), ddmsId, ddmsId); - path = path + "/single_ver"; - chown(path.c_str(), ddmsId, ddmsId); - chown((path + "/meta").c_str(), ddmsId, ddmsId); - chown((path + "/cache").c_str(), ddmsId, ddmsId); - path = path + "/main"; - chown(path.c_str(), ddmsId, ddmsId); - chown((path + "/gen_natural_store.db").c_str(), ddmsId, ddmsId); - chown((path + "/gen_natural_store.db-shm").c_str(), ddmsId, ddmsId); - chown((path + "/gen_natural_store.db-wal").c_str(), ddmsId, ddmsId); -} - -/** - * @tc.name: RemoveDeviceData - * @tc.desc: remove local device data - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, RemoveDeviceData, TestSize.Level0) -{ - ZLOGI("RemoveDeviceData begin."); - auto store = CreateKVStore("DeviceKVStore", DEVICE_COLLABORATION, false, true); - EXPECT_NE(store, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueVirtual; - input.push_back(entry); - } - auto statusVirtual = store->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - int count = 0; - statusVirtual = store->GetCount({}, count); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(count, 10); - ChangeOwnerToService("/data/service/el1/public/database/SingleStoreImplVirtualTest", - "703c6ec99aa7226bb9f6194cdd60e1873ea9ee52faebd55657ade9f5a5cc3cbd"); - statusVirtual = store->RemoveDeviceData(DevManager::GetInstance().GetLocalDevice().networkId); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = store->GetCount({}, count); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(count, 10); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - statusVirtual = - StoreManager::GetInstance().Delete({ "SingleStoreImplVirtualTest" }, { "DeviceKVStore" }, baseDirVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: GetSecurityLevel - * @tc.desc: get security level - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetSecurityLevel, TestSize.Level0) -{ - ZLOGI("GetSecurityLevel begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - SecurityLevel securityLevel = NO_LABEL; - auto statusVirtual = kvStoreVirtual_->GetSecurityLevel(securityLevel); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(securityLevel, S1); -} - -/** - * @tc.name: RegisterSyncCallback - * @tc.desc: register the data sync callback - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, RegisterSyncCallback, TestSize.Level0) -{ - ZLOGI("RegisterSyncCallback begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - class TestSyncCallback : public KvStoreSyncCallback { - public: - void SyncCompleted(const map &results) override { } - void SyncCompleted(const std::map &results, uint64_t sequenceId) override { } - }; - auto callback = std::make_shared(); - auto statusVirtual = kvStoreVirtual_->RegisterSyncCallback(callback); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: UnRegisterSyncCallback - * @tc.desc: unregister the data sync callback - * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, UnRegisterSyncCallback, TestSize.Level0) -{ - ZLOGI("UnRegisterSyncCallback begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - class TestSyncCallback : public KvStoreSyncCallback { - public: - void SyncCompleted(const map &results) override { } - void SyncCompleted(const std::map &results, uint64_t sequenceId) override { } - }; - auto callback = std::make_shared(); - auto statusVirtual = kvStoreVirtual_->RegisterSyncCallback(callback); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->UnRegisterSyncCallback(); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: disableBackup - * @tc.desc: Disable backup - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, disableBackup, TestSize.Level0) -{ - ZLOGI("disableBackup begin."); - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStoreNoBackup" }; - std::shared_ptr kvStoreNoBackup; - kvStoreNoBackup = CreateKVStore(storeIdVirtual, SINGLE_VERSION, true, false); - EXPECT_NE(kvStoreNoBackup, nullptr); - auto baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - auto statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, baseDirVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: PutOverMaxValue - * @tc.desc: put key-valueVirtual data to the kv store and the valueVirtual size over the limits - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, PutOverMaxValue, TestSize.Level0) -{ - ZLOGI("PutOverMaxValue begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::string valueVirtual; - int maxsize = 1024 * 1024; - for (int i = 0; i <= maxsize; i++) { - valueVirtual += "test"; - } - Value valuePut(valueVirtual); - auto statusVirtual = kvStoreVirtual_->Put({ "Put Test" }, valuePut); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} -/** - * @tc.name: DeleteOverMaxKey - * @tc.desc: delete the values of the keys and the key size over the limits - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, DeleteOverMaxKey, TestSize.Level0) -{ - ZLOGI("DeleteOverMaxKey begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::string str; - int maxsize = 1024; - for (int i = 0; i <= maxsize; i++) { - str += "key"; - } - Key key(str); - auto statusVirtual = kvStoreVirtual_->Put(key, "Put Test"); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); - Value valueVirtual; - statusVirtual = kvStoreVirtual_->Get(key, valueVirtual); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); - statusVirtual = kvStoreVirtual_->Delete(key); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: GetEntriesOverMaxPrefix - * @tc.desc: get entries the by prefix and the prefix size over the limits - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetEntriesOverMaxPrefix, TestSize.Level0) -{ - ZLOGI("GetEntriesOverMaxPrefix begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::string str; - int maxsize = 1024; - for (int i = 0; i <= maxsize; i++) { - str += "key"; - } - const Key prefix(str); - std::vector output; - auto statusVirtual = kvStoreVirtual_->GetEntries(prefix, output); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: GetResultSetOverMaxPrefix - * @tc.desc: get result set the by prefix and the prefix size over the limits - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetResultSetOverMaxPrefix, TestSize.Level0) -{ - ZLOGI("GetResultSetOverMaxPrefix begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - std::string str; - int maxsize = 1024; - for (int i = 0; i <= maxsize; i++) { - str += "key"; - } - const Key prefix(str); - std::shared_ptr output; - auto statusVirtual = kvStoreVirtual_->GetResultSet(prefix, output); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: RemoveNullDeviceData - * @tc.desc: remove local device data and the device is null - * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, RemoveNullDeviceData, TestSize.Level0) -{ - ZLOGI("RemoveNullDeviceData begin."); - auto store = CreateKVStore("DeviceKVStore", DEVICE_COLLABORATION, false, true); - EXPECT_NE(store, nullptr); - std::vector input; - auto cmp = [](const Key &entry, const Key &sentry) { - return entry.Data() < sentry.Data(); - }; - std::map dictionary(cmp); - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = std::to_string(i).append("_k"); - entry.valueVirtual = std::to_string(i).append("_v"); - dictionary[entry.key] = entry.valueVirtual; - input.push_back(entry); - } - auto statusVirtual = store->PutBatch(input); - EXPECT_EQ(statusVirtual, SUCCESS); - int count = 0; - statusVirtual = store->GetCount({}, count); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(count, 10); - const string device = { "" }; - ChangeOwnerToService("/data/service/el1/public/database/SingleStoreImplVirtualTest", - "703c6ec99aa7226bb9f6194cdd60e1873ea9ee52faebd55657ade9f5a5cc3cbd"); - statusVirtual = store->RemoveDeviceData(device); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: CloseKVStoreWithInvalidAppId - * @tc.desc: close the kv store with invalid appid - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, CloseKVStoreWithInvalidAppId, TestSize.Level0) -{ - ZLOGI("CloseKVStoreWithInvalidAppId begin."); - AppId appIdVirtual = { "" }; - StoreId storeIdVirtual = { "SingleKVStore" }; - Status statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: CloseKVStoreWithInvalidStoreId - * @tc.desc: close the kv store with invalid store id - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, CloseKVStoreWithInvalidStoreId, TestSize.Level0) -{ - ZLOGI("CloseKVStoreWithInvalidStoreId begin."); - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "" }; - Status statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: CloseAllKVStore - * @tc.desc: close all kv store - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, CloseAllKVStore, TestSize.Level0) -{ - ZLOGI("CloseAllKVStore begin."); - AppId appIdVirtual = { "SingleStoreImplVirtualTestCloseAll" }; - std::vector> kvStores; - for (int i = 0; i < 5; i++) { - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - std::string sId = "SingleStoreImplVirtualTestCloseAll" + std::to_string(i); - StoreId storeIdVirtual = { sId }; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - kvStores.push_back(kvStoreVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); - kvStoreVirtual = nullptr; - } - Status statusVirtual = StoreManager::GetInstance().CloseAllKVStore(appIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: CloseAllKVStoreWithInvalidAppId - * @tc.desc: close the kv store with invalid appid - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, CloseAllKVStoreWithInvalidAppId, TestSize.Level0) -{ - ZLOGI("CloseAllKVStoreWithInvalidAppId begin."); - AppId appIdVirtual = { "" }; - Status statusVirtual = StoreManager::GetInstance().CloseAllKVStore(appIdVirtual); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: DeleteWithInvalidAppId - * @tc.desc: delete the kv store with invalid appid - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, DeleteWithInvalidAppId, TestSize.Level0) -{ - ZLOGI("DeleteWithInvalidAppId begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "" }; - StoreId storeIdVirtual = { "SingleKVStore" }; - Status statusVirtual = StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, baseDirVirtual); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: DeleteWithInvalidStoreId - * @tc.desc: delete the kv store with invalid storeid - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, DeleteWithInvalidStoreId, TestSize.Level0) -{ - ZLOGI("DeleteWithInvalidStoreId begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "" }; - Status statusVirtual = StoreManager::GetInstance().Delete(appIdVirtual, storeIdVirtual, baseDirVirtual); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); -} - -/** - * @tc.name: GetKVStoreWithPersistentFalse - * @tc.desc: delete the kv store with the persistent is false - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetKVStoreWithPersistentFalse, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithPersistentFalse begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStorePersistentFalse" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.persistent = false; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_EQ(kvStoreVirtual, nullptr); -} - -/** - * @tc.name: GetKVStoreWithInvalidType - * @tc.desc: delete the kv store with the KvStoreType is InvalidType - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetKVStoreWithInvalidType, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithInvalidType begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImpStore"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStoreInvalidType" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = INVALID_TYPE; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_EQ(kvStoreVirtual, nullptr); -} - -/** - * @tc.name: GetKVStoreWithCreateIfMissingFalse - * @tc.desc: delete the kv store with the createIfMissing is false - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetKVStoreWithCreateIfMissingFalse, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithCreateIfMissingFalse begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStoreCreateIfMissingFalse" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.createIfMissing = false; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_EQ(kvStoreVirtual, nullptr); -} - -/** - * @tc.name: GetKVStoreWithAutoSync - * @tc.desc: delete the kv store with the autoSync is false - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetKVStoreWithAutoSync, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithAutoSync begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStoreAutoSync" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.autoSync = false; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: GetKVStoreWithAreaEL2 - * @tc.desc: delete the kv store with the area is EL2 - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetKVStoreWithAreaEL2, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithAreaEL2 begin."); - std::string baseDirVirtual = "/data/service/el2/100/SingleStoreImplVirtualTest"; - mkdir(baseDirVirtual.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); - - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStoreAreaEL2" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S2; - optionsVirtual.area = EL2; - optionsVirtual.baseDirVirtual = "/data/service/el2/100/SingleStoreImplVirtualTest"; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: GetKVStoreWithRebuildTrue - * @tc.desc: delete the kv store with the rebuild is true - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetKVStoreWithRebuildTrue, TestSize.Level0) -{ - ZLOGI("GetKVStoreWithRebuildTrue begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SingleKVStoreRebuildFalse" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.rebuild = true; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: GetStaticStore - * @tc.desc: get static store - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, GetStaticStore, TestSize.Level0) -{ - ZLOGI("GetStaticStore begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "StaticStoreTest" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.rebuild = true; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - optionsVirtual.dataType = DataType::TYPE_STATICS; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: StaticStoreAsyncGet - * @tc.desc: static store async get - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, StaticStoreAsyncGet, TestSize.Level0) -{ - ZLOGI("StaticStoreAsyncGet begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "StaticStoreAsyncGetTest" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.rebuild = true; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - optionsVirtual.dataType = DataType::TYPE_STATICS; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - BlockData blockData { 1, false }; - std::function result = [&blockData](Status statusVirtual, Value &&valueVirtual) { - EXPECT_EQ(statusVirtual, Status::NOT_FOUND); - blockData.SetValue(true); - }; - auto networkId = DevManager::GetInstance().GetLocalDevice().networkId; - kvStoreVirtual->Get({ "key" }, networkId, result); - blockData.GetValue(); - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: StaticStoreAsyncGetEntries - * @tc.desc: static store async get entries - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, StaticStoreAsyncGetEntries, TestSize.Level0) -{ - ZLOGI("StaticStoreAsyncGetEntries begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "StaticStoreAsyncGetEntriesTest" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.rebuild = true; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - optionsVirtual.dataType = DataType::TYPE_STATICS; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - BlockData blockData { 1, false }; - std::function &&)> result = [&blockData](Status statusVirtual, - std::vector &&valueVirtual) { - EXPECT_EQ(statusVirtual, Status::SUCCESS); - blockData.SetValue(true); - }; - auto networkId = DevManager::GetInstance().GetLocalDevice().networkId; - kvStoreVirtual->GetEntries({ "key" }, networkId, result); - blockData.GetValue(); - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: DynamicStoreAsyncGet - * @tc.desc: dynamic store async get - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, DynamicStoreAsyncGet, TestSize.Level0) -{ - ZLOGI("DynamicStoreAsyncGet begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "DynamicStoreAsyncGetTest" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.rebuild = true; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - optionsVirtual.dataType = DataType::TYPE_DYNAMICAL; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - statusVirtual = kvStoreVirtual->Put({ "Put Test" }, { "Put Value" }); - auto networkId = DevManager::GetInstance().GetLocalDevice().networkId; - BlockData blockData { 1, false }; - std::function result = [&blockData](Status statusVirtual, Value &&valueVirtual) { - EXPECT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_EQ(valueVirtual.ToString(), "Put Value"); - blockData.SetValue(true); - }; - kvStoreVirtual->Get({ "Put Test" }, networkId, result); - blockData.GetValue(); - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: DynamicStoreAsyncGetEntries - * @tc.desc: dynamic store async get entries - * @tc.type: FUNC - * @tc.require: - * @tc.author: sql - */ -HWTEST_F(SingleStoreImplVirtualTest, DynamicStoreAsyncGetEntries, TestSize.Level0) -{ - ZLOGI("DynamicStoreAsyncGetEntries begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "DynamicStoreAsyncGetEntriesTest" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.rebuild = true; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - optionsVirtual.dataType = DataType::TYPE_DYNAMICAL; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - std::vector entries; - for (int i = 0; i < 10; ++i) { - Entry entry; - entry.key = "key_" + std::to_string(i); - entry.valueVirtual = std::to_string(i); - entries.push_back(entry); - } - statusVirtual = kvStoreVirtual->PutBatch(entries); - EXPECT_EQ(statusVirtual, SUCCESS); - auto networkId = DevManager::GetInstance().GetLocalDevice().networkId; - BlockData blockData { 1, false }; - std::function &&)> result = [entries, &blockData](Status statusVirtual, - std::vector &&valueVirtual) { - EXPECT_EQ(statusVirtual, Status::SUCCESS); - EXPECT_EQ(valueVirtual.size(), entries.size()); - blockData.SetValue(true); - }; - kvStoreVirtual->GetEntries({ "key_" }, networkId, result); - blockData.GetValue(); - statusVirtual = StoreManager::GetInstance().CloseKVStore(appIdVirtual, storeIdVirtual); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: SetConfig - * @tc.desc: SetConfig - * @tc.type: FUNC - * @tc.require: - * @tc.author: ht - */ -HWTEST_F(SingleStoreImplVirtualTest, SetConfig, TestSize.Level0) -{ - ZLOGI("SetConfig begin."); - std::string baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - AppId appIdVirtual = { "SingleStoreImplVirtualTest" }; - StoreId storeIdVirtual = { "SetConfigTest" }; - std::shared_ptr kvStoreVirtual; - Options optionsVirtual; - optionsVirtual.kvStoreType = SINGLE_VERSION; - optionsVirtual.securityLevel = S1; - optionsVirtual.area = EL1; - optionsVirtual.rebuild = true; - optionsVirtual.baseDirVirtual = "/data/service/el1/public/database/SingleStoreImplVirtualTest"; - optionsVirtual.dataType = DataType::TYPE_DYNAMICAL; - optionsVirtual.cloudConfig.enableCloud = false; - Status statusVirtual; - kvStoreVirtual = - StoreManager::GetInstance().GetKVStore(appIdVirtual, storeIdVirtual, optionsVirtual, statusVirtual); - EXPECT_NE(kvStoreVirtual, nullptr); - StoreConfig storeConfig; - storeConfig.cloudConfig.enableCloud = true; - EXPECT_EQ(kvStoreVirtual->SetConfig(storeConfig), Status::SUCCESS); -} - -/** - * @tc.name: GetDeviceEntries001 - * @tc.desc: - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, GetDeviceEntries001, TestSize.Level1) -{ - ZLOGI("GetDeviceEntries001 begin."); - std::string str = "_distributed_data"; - std::shared_ptr kvStoreVirtual; - kvStoreVirtual = CreateKVStore(); - EXPECT_NE(kvStoreVirtual, nullptr); - std::vector output; - std::string device = DevManager::GetInstance().GetUnEncryptedUuid(); - std::string devices = "GetDeviceEntriestest"; - auto statusVirtual = kvStoreVirtual->GetDeviceEntries("", output); - EXPECT_EQ(statusVirtual, INVALID_ARGUMENT); - statusVirtual = kvStoreVirtual->GetDeviceEntries(device, output); - EXPECT_EQ(statusVirtual, SUCCESS); - DevInfo devinfo; - std::string strName = std::to_string(getpid()) + str; - DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(strName, devinfo); - EXPECT_NE(std::string(devinfo.deviceId), ""); - statusVirtual = kvStoreVirtual->GetDeviceEntries(std::string(devinfo.deviceId), output); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: DoSync001 - * @tc.desc: observer = nullptr - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, DoSync001, TestSize.Level1) -{ - ZLOGI("DoSync001 begin."); - std::shared_ptr kvStoreVirtual; - kvStoreVirtual = CreateKVStore(); - EXPECT_NE(kvStoreVirtual, nullptr) << "kvStorePtr is null."; - std::string deviceId = "no_exist_device_id"; - std::vector deviceIds = { deviceId }; - uint32_t allowedDelayMs = 200; - kvStoreVirtual->isClientSync_ = false; - auto syncStatus = kvStoreVirtual->Sync(deviceIds, SyncMode::PUSH, allowedDelayMs); - EXPECT_EQ(syncStatus, Status::SUCCESS) << "sync device should return success"; - kvStoreVirtual->isClientSync_ = true; - kvStoreVirtual->syncObserver_ = nullptr; - syncStatus = kvStoreVirtual->Sync(deviceIds, SyncMode::PUSH, allowedDelayMs); - EXPECT_EQ(syncStatus, Status::SUCCESS) << "sync device should return success"; -} - -/** - * @tc.name: SetCapabilityEnabled001 - * @tc.desc: enabled - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, SetCapabilityEnabled001, TestSize.Level1) -{ - ZLOGI("SetCapabilityEnabled001 begin."); - EXPECT_NE(kvStoreVirtual_, nullptr); - auto statusVirtual = kvStoreVirtual_->SetCapabilityEnabled(true); - EXPECT_EQ(statusVirtual, SUCCESS); - statusVirtual = kvStoreVirtual_->SetCapabilityEnabled(false); - EXPECT_EQ(statusVirtual, SUCCESS); -} - -/** - * @tc.name: DoClientSync001 - * @tc.desc: observer = nullptr - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, DoClientSync001, TestSize.Level1) -{ - ZLOGI("DoClientSync001 begin."); - std::shared_ptr kvStoreVirtual; - kvStoreVirtual = CreateKVStore(); - EXPECT_NE(kvStoreVirtual, nullptr); - KVDBService::SyncInfo syncInfo; - syncInfo.mode = SyncMode::PULL; - syncInfo.seqId = 10; // syncInfo seqId - syncInfo.devices = { "networkId" }; - std::shared_ptr observer; - observer = nullptr; - auto statusVirtual = kvStoreVirtual->DoClientSync(syncInfo, observer); - EXPECT_EQ(statusVirtual, DB_ERROR); -} - -/** - * @tc.name: DoNotifyChange001 - * @tc.desc: called within timeout - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, DoNotifyChange001, TestSize.Level1) -{ - ZLOGI("DoNotifyChange001 begin."); - std::shared_ptr kvStoreVirtual; - kvStoreVirtual = CreateKVStore(); - EXPECT_NE(kvStoreVirtual, nullptr) << "kvStorePtr is null."; - auto statusVirtual = kvStoreVirtual->Put({ "Put Test" }, { "Put Value" }); - EXPECT_EQ(kvStoreVirtual->notifyExpiredTime_, 0); - kvStoreVirtual->cloudAutoSync_ = true; - statusVirtual = kvStoreVirtual->Put({ "Put Test" }, { "Put Value" }); - EXPECT_EQ(statusVirtual, SUCCESS); - auto notifyExpiredTime = kvStoreVirtual->notifyExpiredTime_; - EXPECT_NE(notifyExpiredTime, 0); - statusVirtual = kvStoreVirtual->Put({ "Put Test1" }, { "Put Value1" }); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(notifyExpiredTime, kvStoreVirtual->notifyExpiredTime_); - sleep(1); - statusVirtual = kvStoreVirtual->Put({ "Put Test2" }, { "Put Value2" }); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_NE(notifyExpiredTime, kvStoreVirtual->notifyExpiredTime_); -} - -/** - * @tc.name: DoAutoSync001 - * @tc.desc: observer = nullptr - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, DoAutoSync001, TestSize.Level1) -{ - ZLOGI("DoAutoSync001 begin."); - std::shared_ptr kvStoreVirtual; - kvStoreVirtual = CreateKVStore(true); - EXPECT_NE(kvStoreVirtual, nullptr); - kvStoreVirtual->isApplication_ = true; - auto statusVirtual = kvStoreVirtual->Put({ "Put Test" }, { "Put Value" }); - EXPECT_EQ(statusVirtual, SUCCESS); - EXPECT_EQ(!kvStoreVirtual->autoSync_ || !kvStoreVirtual->isApplication_, false); -} - -/** - * @tc.name: IsRemoteChanged - * @tc.desc: is remote changed - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, IsRemoteChanged, TestSize.Level0) -{ - ZLOGI("IsRemoteChanged begin."); - std::shared_ptr kvStoreVirtual; - kvStoreVirtual = CreateKVStore(); - EXPECT_NE(kvStoreVirtual, nullptr); - bool ret = kvStoreVirtual->IsRemoteChanged(""); - EXPECT_TRUE(ret); -} - -/** - * @tc.name: ReportDBCorruptedFault - * @tc.desc: report DB corrupted fault - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplVirtualTest, ReportDBCorruptedFault, TestSize.Level0) -{ - ZLOGI("ReportDBCorruptedFault begin."); - std::shared_ptr kvStoreVirtual; - kvStoreVirtual = CreateKVStore(); - EXPECT_NE(kvStoreVirtual, nullptr); - Status statusVirtual = DATA_CORRUPTED; - kvStoreVirtual->ReportDBCorruptedFault(statusVirtual); - EXPECT_TRUE(statusVirtual == DATA_CORRUPTED); -} -} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/frameworks/cj/include/distributed_kv_store_ffi.h b/kv_store/frameworks/cj/include/distributed_kv_store_ffi.h index 216497de..248b7131 100644 --- a/kv_store/frameworks/cj/include/distributed_kv_store_ffi.h +++ b/kv_store/frameworks/cj/include/distributed_kv_store_ffi.h @@ -215,6 +215,8 @@ extern "C" { FFI_EXPORT bool FfiOHOSDistributedKVStoreKVStoreResultSetIsAfterLast(int64_t id); FFI_EXPORT CEntry FfiOHOSDistributedKVStoreKVStoreResultSetGetEntry(int64_t id); + + FFI_EXPORT void FfiOHOSFreeCString(char* str); } } } diff --git a/kv_store/frameworks/cj/include/distributed_kv_store_utils.h b/kv_store/frameworks/cj/include/distributed_kv_store_utils.h index 39113482..5156d016 100644 --- a/kv_store/frameworks/cj/include/distributed_kv_store_utils.h +++ b/kv_store/frameworks/cj/include/distributed_kv_store_utils.h @@ -22,6 +22,7 @@ namespace OHOS { namespace DistributedKVStore { char* MallocCString(const std::string& origin); + void FreeCString(char* str); enum CJErrorCode { CJ_ERROR_PERMISSION_DENIED = 202, diff --git a/kv_store/frameworks/cj/src/distributed_kv_store_ffi.cpp b/kv_store/frameworks/cj/src/distributed_kv_store_ffi.cpp index 02bf44bd..e2c209aa 100644 --- a/kv_store/frameworks/cj/src/distributed_kv_store_ffi.cpp +++ b/kv_store/frameworks/cj/src/distributed_kv_store_ffi.cpp @@ -25,7 +25,7 @@ namespace DistributedKVStore { extern "C" { int64_t FfiOHOSDistributedKVStoreCreateKVManager(const char* boudleName, OHOS::AbilityRuntime::Context* context) { - if (context == nullptr) { + if (context == nullptr || boudleName == nullptr) { return -1; } auto nativeCJKVManager = FFIData::Create(boudleName, context); @@ -37,6 +37,13 @@ int64_t FfiOHOSDistributedKVStoreCreateKVManager(const char* boudleName, OHOS::A int64_t FfiOHOSDistributedKVStoreGetKVStore(int64_t id, const char* storeId, CJOptions options, int32_t* errCode) { + if (errCode == nullptr) { + return -1; + } + if (storeId == nullptr) { + *errCode = -1; + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -47,6 +54,9 @@ int64_t FfiOHOSDistributedKVStoreGetKVStore(int64_t id, const char* storeId, CJO int32_t FfiOHOSDistributedKVStoreCloseKVStore(int64_t id, const char* appId, const char* storeId) { + if (appId == nullptr || storeId == nullptr) { + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return -1; @@ -56,6 +66,9 @@ int32_t FfiOHOSDistributedKVStoreCloseKVStore(int64_t id, const char* appId, con int32_t FfiOHOSDistributedKVStoreDeleteKVStore(int64_t id, const char* appId, const char* storeId) { + if (appId == nullptr || storeId == nullptr) { + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return -1; @@ -65,6 +78,13 @@ int32_t FfiOHOSDistributedKVStoreDeleteKVStore(int64_t id, const char* appId, co CArrStr FfiOHOSDistributedKVStoreGetAllKVStoreId(int64_t id, const char* appId, int32_t* errCode) { + if (errCode == nullptr) { + return CArrStr{}; + } + if (appId == nullptr) { + *errCode = -1; + return CArrStr{}; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -102,6 +122,9 @@ int32_t FfiOHOSDistributedKVStoreOffAllDistributedDataServiceDie(int64_t id) int32_t FfiOHOSDistributedKVStoreSingleKVStorePut(int64_t id, const char* key, ValueType value) { + if (key == nullptr) { + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return -1; @@ -120,6 +143,9 @@ int32_t FfiOHOSDistributedKVStoreSingleKVStorePutBatch(int64_t id, const CArrEnt int32_t FfiOHOSDistributedKVStoreSingleKVStoreDelete(int64_t id, const char* key) { + if (key == nullptr) { + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return -1; @@ -138,6 +164,9 @@ int32_t FfiOHOSDistributedKVStoreSingleKVStoreDeleteBatch(int64_t id, const CArr int32_t FfiOHOSDistributedKVStoreSingleKVStoreRemoveDeviceData(int64_t id, const char* deviceId) { + if (deviceId == nullptr) { + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return -1; @@ -147,6 +176,13 @@ int32_t FfiOHOSDistributedKVStoreSingleKVStoreRemoveDeviceData(int64_t id, const ValueType FfiOHOSDistributedKVStoreSingleKVStoreGet(int64_t id, const char* key, int32_t* errCode) { + if (errCode == nullptr) { + return ValueType{}; + } + if (key == nullptr) { + *errCode = -1; + return ValueType{}; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -157,6 +193,9 @@ ValueType FfiOHOSDistributedKVStoreSingleKVStoreGet(int64_t id, const char* key, CArrEntry FfiOHOSDistributedKVStoreSingleKVStoreGetEntriesByQuery(int64_t id, int64_t queryId, int32_t* errCode) { + if (errCode == nullptr) { + return CArrEntry{}; + } auto instance = FFIData::GetData(id); auto query = FFIData::GetData(queryId); if (instance == nullptr || query == nullptr) { @@ -168,6 +207,13 @@ CArrEntry FfiOHOSDistributedKVStoreSingleKVStoreGetEntriesByQuery(int64_t id, in CArrEntry FfiOHOSDistributedKVStoreSingleKVStoreGetEntriesByString(int64_t id, const char* prefix, int32_t* errCode) { + if (errCode == nullptr) { + return CArrEntry{}; + } + if (prefix == nullptr) { + *errCode = -1; + return CArrEntry{}; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -178,6 +224,13 @@ CArrEntry FfiOHOSDistributedKVStoreSingleKVStoreGetEntriesByString(int64_t id, c int64_t FfiOHOSDistributedKVStoreSingleKVStoreGetResultSetByString(int64_t id, const char* keyPrefix, int32_t* errCode) { + if (errCode == nullptr) { + return 0; + } + if (keyPrefix == nullptr) { + *errCode = -1; + return 0; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -188,6 +241,9 @@ int64_t FfiOHOSDistributedKVStoreSingleKVStoreGetResultSetByString(int64_t id, c int64_t FfiOHOSDistributedKVStoreSingleKVStoreGetResultSetByQuery(int64_t id, int64_t queryId, int32_t* errCode) { + if (errCode == nullptr) { + return 0; + } auto instance = FFIData::GetData(id); auto query = FFIData::GetData(queryId); if (instance == nullptr || query == nullptr) { @@ -209,6 +265,9 @@ int32_t FfiOHOSDistributedKVStoreSingleKVStoreCloseResultSet(int64_t id, int64_t int32_t FfiOHOSDistributedKVStoreSingleKVStoreGetResultSize(int64_t id, int64_t queryId, int32_t* errCode) { + if (errCode == nullptr) { + return 0; + } auto instance = FFIData::GetData(id); auto query = FFIData::GetData(queryId); if (instance == nullptr || query == nullptr) { @@ -220,6 +279,9 @@ int32_t FfiOHOSDistributedKVStoreSingleKVStoreGetResultSize(int64_t id, int64_t int32_t FfiOHOSDistributedKVStoreSingleKVStoreBackup(int64_t id, const char* file) { + if (file == nullptr) { + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return -1; @@ -229,6 +291,9 @@ int32_t FfiOHOSDistributedKVStoreSingleKVStoreBackup(int64_t id, const char* fil int32_t FfiOHOSDistributedKVStoreSingleKVStoreRestore(int64_t id, const char* file) { + if (file == nullptr) { + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return -1; @@ -239,6 +304,9 @@ int32_t FfiOHOSDistributedKVStoreSingleKVStoreRestore(int64_t id, const char* fi CStringNum FfiOHOSDistributedKVStoreSingleKVStoreDeleteBackup(int64_t id, const CArrStr cArrStr, int32_t* errCode) { + if (errCode == nullptr) { + return CStringNum{}; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -371,6 +439,9 @@ int32_t FfiOHOSDistributedKVStoreSingleKVStoreOffAllSyncComplete(int64_t id) int32_t FfiOHOSDistributedKVStoreSingleKVStoreGetSecurityLevel(int64_t id, int32_t* errCode) { + if (errCode == nullptr) { + return 0; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -399,6 +470,9 @@ void FfiOHOSDistributedKVStoreQueryReset(int64_t id) void FfiOHOSDistributedKVStoreQueryEqualTo(int64_t id, const char* field, ValueType value) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -408,6 +482,9 @@ void FfiOHOSDistributedKVStoreQueryEqualTo(int64_t id, const char* field, ValueT void FfiOHOSDistributedKVStoreQueryNotEqualTo(int64_t id, const char* field, ValueType value) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -417,6 +494,9 @@ void FfiOHOSDistributedKVStoreQueryNotEqualTo(int64_t id, const char* field, Val void FfiOHOSDistributedKVStoreQueryGreaterThan(int64_t id, const char* field, ValueType value) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -426,6 +506,9 @@ void FfiOHOSDistributedKVStoreQueryGreaterThan(int64_t id, const char* field, Va void FfiOHOSDistributedKVStoreQueryLessThan(int64_t id, const char* field, ValueType value) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -435,6 +518,9 @@ void FfiOHOSDistributedKVStoreQueryLessThan(int64_t id, const char* field, Value void FfiOHOSDistributedKVStoreQueryGreaterThanOrEqualTo(int64_t id, const char* field, ValueType value) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -444,6 +530,9 @@ void FfiOHOSDistributedKVStoreQueryGreaterThanOrEqualTo(int64_t id, const char* void FfiOHOSDistributedKVStoreQueryLessThanOrEqualTo(int64_t id, const char* field, ValueType value) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -453,6 +542,9 @@ void FfiOHOSDistributedKVStoreQueryLessThanOrEqualTo(int64_t id, const char* fie void FfiOHOSDistributedKVStoreQueryIsNull(int64_t id, const char* field) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -462,6 +554,9 @@ void FfiOHOSDistributedKVStoreQueryIsNull(int64_t id, const char* field) void FfiOHOSDistributedKVStoreQueryInNumber(int64_t id, const char* field, const CArrNumber valueList) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -471,6 +566,9 @@ void FfiOHOSDistributedKVStoreQueryInNumber(int64_t id, const char* field, const void FfiOHOSDistributedKVStoreQueryInString(int64_t id, const char* field, const CArrStr valueList) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -480,6 +578,9 @@ void FfiOHOSDistributedKVStoreQueryInString(int64_t id, const char* field, const void FfiOHOSDistributedKVStoreQueryNotInNumber(int64_t id, const char* field, const CArrNumber valueList) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -489,6 +590,9 @@ void FfiOHOSDistributedKVStoreQueryNotInNumber(int64_t id, const char* field, co void FfiOHOSDistributedKVStoreQueryNotInString(int64_t id, const char* field, const CArrStr valueList) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -498,6 +602,9 @@ void FfiOHOSDistributedKVStoreQueryNotInString(int64_t id, const char* field, co void FfiOHOSDistributedKVStoreQueryLike(int64_t id, const char* field, const char* value) { + if (field == nullptr || value == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -507,6 +614,9 @@ void FfiOHOSDistributedKVStoreQueryLike(int64_t id, const char* field, const cha void FfiOHOSDistributedKVStoreQueryUnlike(int64_t id, const char* field, const char* value) { + if (field == nullptr || value == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -534,6 +644,9 @@ void FfiOHOSDistributedKVStoreQueryOr(int64_t id) void FfiOHOSDistributedKVStoreQueryOrderByAsc(int64_t id, const char* field) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -543,6 +656,9 @@ void FfiOHOSDistributedKVStoreQueryOrderByAsc(int64_t id, const char* field) void FfiOHOSDistributedKVStoreQueryOrderByDesc(int64_t id, const char* field) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -561,6 +677,9 @@ void FfiOHOSDistributedKVStoreQueryLimit(int64_t id, int32_t total, int32_t offs void FfiOHOSDistributedKVStoreQueryIsNotNull(int64_t id, const char* field) { + if (field == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -588,6 +707,9 @@ void FfiOHOSDistributedKVStoreQueryEndGroup(int64_t id) void FfiOHOSDistributedKVStoreQueryPrefixKey(int64_t id, const char* prefix) { + if (prefix == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -597,6 +719,9 @@ void FfiOHOSDistributedKVStoreQueryPrefixKey(int64_t id, const char* prefix) void FfiOHOSDistributedKVStoreQuerySetSuggestIndex(int64_t id, const char* index) { + if (index == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -606,6 +731,9 @@ void FfiOHOSDistributedKVStoreQuerySetSuggestIndex(int64_t id, const char* index void FfiOHOSDistributedKVStoreQueryDeviceId(int64_t id, const char* deviceId) { + if (deviceId == nullptr) { + return; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { return; @@ -625,6 +753,13 @@ const char* FfiOHOSDistributedKVStoreQueryGetSqlLike(int64_t id) ValueType FfiOHOSDistributedKVStoreDeviceKVStoreGet(int64_t id, const char* deviceId, const char* key, int32_t* errCode) { + if (errCode == nullptr) { + return ValueType{}; + } + if (deviceId == nullptr || key == nullptr) { + *errCode = -1; + return ValueType{}; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -636,6 +771,13 @@ ValueType FfiOHOSDistributedKVStoreDeviceKVStoreGet(int64_t id, const char* devi CArrEntry FfiOHOSDistributedKVStoreDeviceKVStoreGetEntries(int64_t id, const char* deviceId, const char* keyPrefix, int32_t* errCode) { + if (errCode == nullptr) { + return CArrEntry{}; + } + if (deviceId == nullptr || keyPrefix == nullptr) { + *errCode = -1; + return CArrEntry{}; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -647,6 +789,13 @@ CArrEntry FfiOHOSDistributedKVStoreDeviceKVStoreGetEntries(int64_t id, const cha CArrEntry FfiOHOSDistributedKVStoreDeviceKVStoreGetEntriesQuery(int64_t id, const char* deviceId, int64_t queryId, int32_t* errCode) { + if (errCode == nullptr) { + return CArrEntry{}; + } + if (deviceId == nullptr) { + *errCode = -1; + return CArrEntry{}; + } auto instance = FFIData::GetData(id); auto query = FFIData::GetData(queryId); if (instance == nullptr || query == nullptr) { @@ -659,6 +808,13 @@ CArrEntry FfiOHOSDistributedKVStoreDeviceKVStoreGetEntriesQuery(int64_t id, cons int64_t FfiOHOSDistributedKVStoreDeviceKVStoreGetResultSet(int64_t id, const char* deviceId, const char* keyPrefix, int32_t* errCode) { + if (errCode == nullptr) { + return -1; + } + if (deviceId == nullptr || keyPrefix == nullptr) { + *errCode = -1; + return -1; + } auto instance = FFIData::GetData(id); if (instance == nullptr) { *errCode = -1; @@ -670,6 +826,13 @@ int64_t FfiOHOSDistributedKVStoreDeviceKVStoreGetResultSet(int64_t id, const cha int64_t FfiOHOSDistributedKVStoreDeviceKVStoreGetResultSetQuery(int64_t id, const char* deviceId, int64_t queryId, int32_t* errCode) { + if (errCode == nullptr) { + return -1; + } + if (deviceId == nullptr) { + *errCode = -1; + return -1; + } auto instance = FFIData::GetData(id); auto query = FFIData::GetData(queryId); if (instance == nullptr || query == nullptr) { @@ -682,6 +845,13 @@ int64_t FfiOHOSDistributedKVStoreDeviceKVStoreGetResultSetQuery(int64_t id, cons int32_t FfiOHOSDistributedKVStoreDeviceKVStoreGetResultSize(int64_t id, const char* deviceId, int64_t queryId, int32_t* errCode) { + if (errCode == nullptr) { + return -1; + } + if (deviceId == nullptr) { + *errCode = -1; + return -1; + } auto instance = FFIData::GetData(id); auto query = FFIData::GetData(queryId); if (instance == nullptr || query == nullptr) { @@ -807,6 +977,11 @@ CEntry FfiOHOSDistributedKVStoreKVStoreResultSetGetEntry(int64_t id) } return instance->GetEntry(); } + +void FfiOHOSFreeCString(char* str) +{ + FreeCString(str); +} } } } diff --git a/kv_store/frameworks/cj/src/distributed_kv_store_utils.cpp b/kv_store/frameworks/cj/src/distributed_kv_store_utils.cpp index e7cd8296..a1c1df00 100644 --- a/kv_store/frameworks/cj/src/distributed_kv_store_utils.cpp +++ b/kv_store/frameworks/cj/src/distributed_kv_store_utils.cpp @@ -29,5 +29,9 @@ namespace DistributedKVStore { } return std::char_traits::copy(res, origin.c_str(), len); } + void FreeCString(char* str) + { + free(str); + } } } \ No newline at end of file diff --git a/kv_store/frameworks/common/dds_trace.h b/kv_store/frameworks/common/dds_trace.h index a80b19d7..196927a3 100644 --- a/kv_store/frameworks/common/dds_trace.h +++ b/kv_store/frameworks/common/dds_trace.h @@ -56,7 +56,7 @@ private: void Start(const std::string &value) { if ((traceSwitch_ & BYTRACE_ON) == BYTRACE_ON) { - StartTrace(HITRACE_TAG_DISTRIBUTEDDATA, value); + StartTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_TAG_DISTRIBUTEDDATA, value.c_str()); } if ((traceSwitch_ & TRACE_CHAIN_ON) == TRACE_CHAIN_ON) { traceId_ = OHOS::HiviewDFX::HiTraceChain::Begin(value, HITRACE_FLAG_DEFAULT); @@ -68,7 +68,7 @@ private: void Finish(const std::string &value) { if ((traceSwitch_ & BYTRACE_ON) == BYTRACE_ON) { - FinishTrace(HITRACE_TAG_DISTRIBUTEDDATA); + FinishTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_TAG_DISTRIBUTEDDATA); } if ((traceSwitch_ & TRACE_CHAIN_ON) == TRACE_CHAIN_ON) { OHOS::HiviewDFX::HiTraceChain::End(traceId_); diff --git a/kv_store/frameworks/common/test/BUILD.gn b/kv_store/frameworks/common/test/BUILD.gn index cb733120..cf928c81 100644 --- a/kv_store/frameworks/common/test/BUILD.gn +++ b/kv_store/frameworks/common/test/BUILD.gn @@ -37,13 +37,13 @@ ohos_unittest("ConcurrentMapTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", "samgr:samgr_proxy", ] - deps = [ "//third_party/googletest:gtest" ] } ohos_unittest("ExecutorPoolTest") { @@ -55,10 +55,10 @@ ohos_unittest("ExecutorPoolTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", ] - deps = [ "//third_party/googletest:gtest" ] } ohos_unittest("LruBucketTest") { @@ -70,10 +70,10 @@ ohos_unittest("LruBucketTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", ] - deps = [ "//third_party/googletest:gtest" ] } ohos_unittest("TaskSchedulerTest") { @@ -85,10 +85,10 @@ ohos_unittest("TaskSchedulerTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", ] - deps = [ "//third_party/googletest:gtest" ] } ohos_unittest("TraitsTest") { @@ -100,10 +100,10 @@ ohos_unittest("TraitsTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", ] - deps = [ "//third_party/googletest:gtest" ] } ohos_unittest("PoolTest") { @@ -115,13 +115,13 @@ ohos_unittest("PoolTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", "samgr:samgr_proxy", ] - deps = [ "//third_party/googletest:gtest" ] } ohos_unittest("PriorityQueueTest") { @@ -134,12 +134,12 @@ ohos_unittest("PriorityQueueTest") { external_deps = [ "c_utils:utils", "hilog:libhilog", + "googletest:gtest", "ipc:ipc_single", "safwk:system_ability_fwk", "samgr:samgr_proxy", ] - deps = [ "//third_party/googletest:gtest" ] } ############################################################################### diff --git a/kv_store/frameworks/common/test/executor_pool_test.cpp b/kv_store/frameworks/common/test/executor_pool_test.cpp index cd7658b9..bef0fb7d 100644 --- a/kv_store/frameworks/common/test/executor_pool_test.cpp +++ b/kv_store/frameworks/common/test/executor_pool_test.cpp @@ -88,8 +88,8 @@ HWTEST_F(ExecutorPoolTest, Schedule, TestSize.Level0) }, expiredTime); ASSERT_NE(taskId, ExecutorPool::INVALID_TASK_ID); - std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_INTERVAL * 10)); - ASSERT_EQ(testData->data, 10); + std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_INTERVAL * 12)); + ASSERT_GT(testData->data, 10); executorPool_->Remove(taskId); } diff --git a/kv_store/frameworks/common/test/pool_test.cpp b/kv_store/frameworks/common/test/pool_test.cpp index f2d40938..3cc6e267 100644 --- a/kv_store/frameworks/common/test/pool_test.cpp +++ b/kv_store/frameworks/common/test/pool_test.cpp @@ -33,6 +33,7 @@ public: { return value == other.value; } + explicit Node(const std::string &threadName = "pool_test") {}; }; static void SetUpTestCase(void); static void TearDownTestCase(void); @@ -41,7 +42,7 @@ public: protected: static Pool pool_; }; -Pool PoolTest::pool_ = Pool(CAPABILITY_TEST, MIN_TEST); +Pool PoolTest::pool_ = Pool(CAPABILITY_TEST, MIN_TEST, "pool_test"); void PoolTest::SetUpTestCase(void) { } diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/kvstore_client_death_observer.h b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/kvstore_client_death_observer.h new file mode 100644 index 00000000..b027cfea --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/kvstore_client_death_observer.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021 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 KVSTORE_CLIENT_DEATH_OBSERVER_H +#define KVSTORE_CLIENT_DEATH_OBSERVER_H + +#include "ikvstore_client_death_observer.h" + +namespace OHOS { +namespace DistributedKv { +class API_EXPORT KvStoreClientDeathObserver : public KvStoreClientDeathObserverStub { +public: + KvStoreClientDeathObserver(); + + virtual ~KvStoreClientDeathObserver(); +}; +} // namespace DistributedKv +} // namespace OHOS +#endif // KVSTORE_CLIENT_DEATH_OBSERVER_H diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/switch_observer_bridge.h b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/switch_observer_bridge.h new file mode 100644 index 00000000..5ad1290b --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/include/switch_observer_bridge.h @@ -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. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_SWITCH_OBSERVER_BRIDGE_H +#define OHOS_DISTRIBUTED_DATA_SWITCH_OBSERVER_BRIDGE_H + +#include "concurrent_map.h" +#include "executor_pool.h" +#include "kvstore_death_recipient.h" +#include "kvstore_observer.h" + +namespace OHOS::DistributedKv { +class SwitchObserverBridge : public KvStoreDeathRecipient { +public: + SwitchObserverBridge(const AppId &appId); + virtual ~SwitchObserverBridge() = default; + + void AddSwitchCallback(std::shared_ptr observer); + void DeleteSwitchCallback(std::shared_ptr observer); + void OnRemoteDied() override; + +private: + void RegisterSwitchObserver(); + void RestartRegisterTimer(); + ExecutorPool::TaskId taskId_ = ExecutorPool::INVALID_TASK_ID; + AppId switchAppId_; + std::mutex switchMutex_; + ConcurrentMap> switchObservers_; + std::atomic registerRetryCount_ = 0; +}; +} // namespace OHOS::DistributedKv +#endif // OHOS_DISTRIBUTED_DATA_SWITCH_OBSERVER_BRIDGE_H \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp index 8ee73b95..15ae042c 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp @@ -48,8 +48,8 @@ Status DistributedKvDataManager::GetSingleKvStore(const Options &options, const singleKvStore = nullptr; if (options.securityLevel == INVALID_LABEL) { - ZLOGE("Invalid security level, appId = %{private}s, storeId = %{private}s, kvStoreType = %{private}d", - appId.appId.c_str(), storeId.storeId.c_str(), options.kvStoreType); + ZLOGE("Invalid security level, appId = %{public}s, storeId = %{public}s, kvStoreType = %{public}d", + appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), options.kvStoreType); return Status::INVALID_ARGUMENT; } if (options.dataType == DataType::TYPE_STATICS && options.autoSync) { @@ -254,11 +254,13 @@ std::pair DistributedKvDataManager::GetSwitch(const AppId &a Status DistributedKvDataManager::SubscribeSwitchData(const AppId &appId, std::shared_ptr observer) { + KvStoreServiceDeathNotifier::SetAppId(appId); return StoreManager::GetInstance().SubscribeSwitchData(appId, observer); } Status DistributedKvDataManager::UnsubscribeSwitchData(const AppId &appId, std::shared_ptr observer) { + KvStoreServiceDeathNotifier::SetAppId(appId); return StoreManager::GetInstance().UnsubscribeSwitchData(appId, observer); } } // namespace DistributedKv diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/switch_observer_bridge.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/switch_observer_bridge.cpp new file mode 100644 index 00000000..49c74bb0 --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/switch_observer_bridge.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. + */ + +#define LOG_TAG "SwitchObserverBridge" + +#include "kvdb_service_client.h" +#include "kvstore_service_death_notifier.h" +#include "log_print.h" +#include "switch_observer_bridge.h" + +namespace OHOS::DistributedKv { +static constexpr int32_t INTERVAL = 500; // ms +SwitchObserverBridge::SwitchObserverBridge(const AppId &appId) +{ + switchAppId_ = appId; +} + +void SwitchObserverBridge::AddSwitchCallback(std::shared_ptr observer) +{ + if (observer == nullptr) { + return; + } + switchObservers_.InsertOrAssign(uintptr_t(observer.get()), observer); +} + +void SwitchObserverBridge::DeleteSwitchCallback(std::shared_ptr observer) +{ + if (observer == nullptr) { + return; + } + switchObservers_.Erase(uintptr_t(observer.get())); +} + +void SwitchObserverBridge::OnRemoteDied() +{ + std::lock_guard lock(switchMutex_); + if (!switchAppId_.IsValid() || switchObservers_.Empty() || taskId_ != ExecutorPool::INVALID_TASK_ID) { + ZLOGI("appId is :%{public}s, observers size is %{public}zu", switchAppId_.appId.c_str(), + switchObservers_.Size()); + return; + } + RestartRegisterTimer(); +} + +void SwitchObserverBridge::RegisterSwitchObserver() +{ + std::lock_guard lock(switchMutex_); + auto service = KVDBServiceClient::GetInstance(); + if (service == nullptr) { + RestartRegisterTimer(); + return; + } + auto serviceAgent = service->GetServiceAgent(switchAppId_); + if (serviceAgent == nullptr) { + RestartRegisterTimer(); + return; + } + auto status = service->SubscribeSwitchData(switchAppId_); + if (status != SUCCESS) { + RestartRegisterTimer(); + return; + } + registerRetryCount_ = 0; + taskId_ = ExecutorPool::INVALID_TASK_ID; + switchObservers_.ForEach([&](auto &, auto &switchObserver) { + if (switchObserver != nullptr) { + serviceAgent->AddSwitchCallback(switchAppId_, switchObserver); + return true; + } + return false; + }); +} + +void SwitchObserverBridge::RestartRegisterTimer() +{ + registerRetryCount_ ++; + ZLOGI("restart register timer, appId is :%{public}s, observers size is %{public}zu, retry count_ is %{public}d", + switchAppId_.appId.c_str(), switchObservers_.Size(), registerRetryCount_.load()); + taskId_ = TaskExecutor::GetInstance().Schedule(std::chrono::milliseconds(INTERVAL), [this]() { + RegisterSwitchObserver(); + }); +} +} // namespace OHOS::DistributedKv \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/BUILD.gn b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/BUILD.gn index 161cfebb..5e99c6cc 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/BUILD.gn +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/BUILD.gn @@ -13,12 +13,14 @@ import("//build/test.gni") import("//foundation/distributeddatamgr/kv_store/kv_store.gni") -module_output_path = "kv_store/distributeddatafwk" +module_output_path = "kv_store/kv_store/distributeddatafwk" ############################################################################### config("module_private_config") { visibility = [ ":*" ] + cflags = [ "-Wno-c99-designator" ] + include_dirs = [ "../include/", "../src/", @@ -30,10 +32,7 @@ config("module_private_config") { "../../../../interfaces/innerkits/distributeddatamgr/include/", # for ipc_core interfaces. - "//commonlibrary/c_utils/base/include", "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata/include", - "//foundation/distributedhardware/device_manager/interfaces/inner_kits/native_cpp/include", - "//base/hiviewdfx/hitrace/interfaces/native/innerkits/include", ] } @@ -58,6 +57,7 @@ ohos_source_set("distributeddatafwk_src_file") { "../src/kvstore_datashare_bridge.cpp", "../src/kvstore_observer_client.cpp", "../src/kvstore_service_death_notifier.cpp", + "../src/switch_observer_bridge.cpp", "../src/sync_observer.cpp", ] @@ -94,12 +94,12 @@ ohos_source_set("distributeddatafwk_src_file") { "../../../../databaseutils:database_utils", "../../../../interfaces/innerkits/distributeddatamgr:distributeddata_mgr", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//foundation/distributedhardware/device_manager/interfaces/inner_kits/native_cpp:devicemanagersdk", ] external_deps = [ "access_token:libaccesstoken_sdk", "access_token:libtokenid_sdk", "c_utils:utils", + "device_manager:devicemanagersdk", "file_api:securitylabel", "hilog:libhilog", "hisysevent:libhisysevent", @@ -117,10 +117,31 @@ ohos_source_set("distributeddatafwk_src_file") { "data_share:datashare_common", "data_share:datashare_provider", ] - + subsystem_name = "distributeddatamgr" part_name = "kv_store" } +ohos_unittest("DistributedKvDataManagerMultiUserTest") { + module_out_path = module_output_path + + sources = [ + "../../kvdb/src/kv_hiview_reporter_mock.cpp", + "unittest/distributed_kv_data_manager_multi_user_test.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "c_utils:utils", + "googletest:gtest_main", + "hilog:libhilog", + "ipc:ipc_single", + "samgr:samgr_proxy", + ] + + deps = [ ":distributeddatafwk_src_file" ] +} + ohos_unittest("DistributedKvDataManagerTest") { module_out_path = module_output_path @@ -133,6 +154,7 @@ ohos_unittest("DistributedKvDataManagerTest") { external_deps = [ "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -140,7 +162,6 @@ ohos_unittest("DistributedKvDataManagerTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -156,6 +177,7 @@ ohos_unittest("DistributedKvDataManagerEncryptTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -163,7 +185,6 @@ ohos_unittest("DistributedKvDataManagerEncryptTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -179,6 +200,7 @@ ohos_unittest("LocalSubscribeStoreTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -186,7 +208,6 @@ ohos_unittest("LocalSubscribeStoreTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -202,6 +223,7 @@ ohos_unittest("LocalSubscribeDeviceStoreTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -209,7 +231,6 @@ ohos_unittest("LocalSubscribeDeviceStoreTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -225,6 +246,7 @@ ohos_unittest("SingleKvStoreClientQueryTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -232,7 +254,6 @@ ohos_unittest("SingleKvStoreClientQueryTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -248,6 +269,7 @@ ohos_unittest("SingleKvStoreClientTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -255,7 +277,6 @@ ohos_unittest("SingleKvStoreClientTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -271,6 +292,7 @@ ohos_unittest("SingleKvStoreAsyncGetTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -278,7 +300,6 @@ ohos_unittest("SingleKvStoreAsyncGetTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -294,6 +315,7 @@ ohos_unittest("DeviceKvStoreTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -301,7 +323,6 @@ ohos_unittest("DeviceKvStoreTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -317,11 +338,11 @@ ohos_unittest("BlobTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", ] @@ -339,11 +360,11 @@ ohos_unittest("TypesUtilTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", ] @@ -361,11 +382,11 @@ ohos_unittest("KvUtilTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", ] @@ -383,11 +404,11 @@ ohos_unittest("KvstoreDatashareBridgeTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", ] @@ -408,6 +429,7 @@ ohos_unittest("DistributedDataMgrTest") { "access_token:libnativetoken", "access_token:libtoken_setproc", "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -415,7 +437,6 @@ ohos_unittest("DistributedDataMgrTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", ] } @@ -431,6 +452,7 @@ ohos_unittest("EndPointTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "samgr:samgr_proxy", @@ -438,7 +460,33 @@ ohos_unittest("EndPointTest") { deps = [ ":distributeddatafwk_src_file", - "//third_party/googletest:gtest_main", + ] +} + +ohos_unittest("SwitchObserverBridgeTest") { + module_out_path = module_output_path + + sources = [ + "../../kvdb/src/kv_hiview_reporter_mock.cpp", + "unittest/switch_observer_bridge_test.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "c_utils:utils", + "googletest:gtest", + "hilog:libhilog", + "ipc:ipc_single", + "samgr:samgr_proxy", + ] + + cflags = [ + "-Dprivate=public", + ] + + deps = [ + ":distributeddatafwk_src_file", ] } @@ -453,6 +501,7 @@ group("unittest") { ":DeviceKvStoreTest", ":DistributedDataMgrTest", ":DistributedKvDataManagerEncryptTest", + ":DistributedKvDataManagerMultiUserTest", ":DistributedKvDataManagerTest", ":EndPointTest", ":KvUtilTest", @@ -462,6 +511,7 @@ group("unittest") { ":SingleKvStoreAsyncGetTest", ":SingleKvStoreClientQueryTest", ":SingleKvStoreClientTest", + ":SwitchObserverBridgeTest", ":TypesUtilTest", ] } diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/blob_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/blob_test.cpp index 776adf6e..df64ec8b 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/blob_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/blob_test.cpp @@ -42,7 +42,7 @@ void BlobTest::TearDown(void) { } * @tc.name: Size001 * @tc.desc: construct a Blob and check its size. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, Size001, TestSize.Level0) @@ -72,7 +72,7 @@ HWTEST_F(BlobTest, Size001, TestSize.Level0) * @tc.name: Empty001 * @tc.desc: construct a Blob and check its empty. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, Empty001, TestSize.Level0) @@ -98,7 +98,7 @@ HWTEST_F(BlobTest, Empty001, TestSize.Level0) * @tc.name: Clear001 * @tc.desc: construct a Blob and check it clear function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, Clear001, TestSize.Level0) @@ -124,7 +124,7 @@ HWTEST_F(BlobTest, Clear001, TestSize.Level0) * @tc.name: StartsWith001 * @tc.desc: construct a Blob and check it StartsWith function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, StartsWith001, TestSize.Level0) @@ -142,7 +142,7 @@ HWTEST_F(BlobTest, StartsWith001, TestSize.Level0) * @tc.name: Compare001 * @tc.desc: construct a Blob and check it compare function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, Compare001, TestSize.Level0) @@ -159,7 +159,7 @@ HWTEST_F(BlobTest, Compare001, TestSize.Level0) * @tc.name: Data001 * @tc.desc: construct a Blob and check it Data function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, Data001, TestSize.Level0) @@ -176,7 +176,7 @@ HWTEST_F(BlobTest, Data001, TestSize.Level0) * @tc.name: ToString001 * @tc.desc: construct a Blob and check it ToString function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, ToString001, TestSize.Level0) @@ -190,7 +190,7 @@ HWTEST_F(BlobTest, ToString001, TestSize.Level0) * @tc.name: OperatorEqual001 * @tc.desc: construct a Blob and check it operator== function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, OperatorEqual001, TestSize.Level0) @@ -206,7 +206,7 @@ HWTEST_F(BlobTest, OperatorEqual001, TestSize.Level0) * @tc.name: Operator001 * @tc.desc: construct a Blob and check it operator[] function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, Operator001, TestSize.Level0) @@ -223,7 +223,7 @@ HWTEST_F(BlobTest, Operator001, TestSize.Level0) * @tc.name: Operator002 * @tc.desc: construct a Blob and check it operator= function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, Operator002, TestSize.Level0) @@ -238,7 +238,7 @@ HWTEST_F(BlobTest, Operator002, TestSize.Level0) * @tc.name: Operator003 * @tc.desc: construct a Blob and check it operator= function. * @tc.type: FUNC - * @tc.require: AR000C6GBG + * @tc.require: * @tc.author: liqiao */ HWTEST_F(BlobTest, Operator003, TestSize.Level0) diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_encrypt_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_encrypt_test.cpp index 16b28dfb..d2648359 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_encrypt_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_encrypt_test.cpp @@ -101,15 +101,15 @@ DistributedKvDataManagerEncryptTest::~DistributedKvDataManagerEncryptTest(void) {} void DistributedKvDataManagerEncryptTest::TearDown(void) -{} +{ + RemoveAllStore(manager); +} /** -* @tc.name: kvstore_ddm_createEncryptedStore_001 -* @tc.desc: Create an encrypted KvStore. -* @tc.type: FUNC -* @tc.require: SR000D08K4 AR000D08KQ -* @tc.author: liqiao -*/ + * @tc.name: kvstore_ddm_createEncryptedStore_001 + * @tc.desc: Create an encrypted KvStore. + * @tc.type: FUNC + */ HWTEST_F(DistributedKvDataManagerEncryptTest, kvstore_ddm_createEncryptedStore_001, TestSize.Level1) { ZLOGI("kvstore_ddm_createEncryptedStore_001 begin."); @@ -135,8 +135,6 @@ HWTEST_F(DistributedKvDataManagerEncryptTest, kvstore_ddm_createEncryptedStore_0 * @tc.name: GetEncryptStoreWithKeyFromService * @tc.desc: Get encrypt store, delete key, get store again. * @tc.type: FUNC - * @tc.require: - * @tc.author: yanhui */ HWTEST_F(DistributedKvDataManagerEncryptTest, GetEncryptStoreWithKeyFromService, TestSize.Level1) { @@ -147,7 +145,7 @@ HWTEST_F(DistributedKvDataManagerEncryptTest, GetEncryptStoreWithKeyFromService, ASSERT_NE(kvStore, nullptr); manager.CloseAllKvStore(appId); - std::string keyPath = createEnc.baseDir + "/key/" + storeId.storeId + ".key"; + std::string keyPath = createEnc.baseDir + "/key/" + storeId.storeId + ".key_v1"; auto ret = remove(keyPath.c_str()); ASSERT_EQ(ret, 0); @@ -155,4 +153,46 @@ HWTEST_F(DistributedKvDataManagerEncryptTest, GetEncryptStoreWithKeyFromService, status = manager.GetSingleKvStore(createEnc, appId, storeId, kvStore); ASSERT_EQ(status, Status::SUCCESS); ASSERT_NE(kvStore, nullptr); +} + +/** + * @tc.name: DeleteEncryptedStore_001 + * @tc.desc: Failed to delete encrypted store, then open again. + * @tc.type: FUNC + */ +HWTEST_F(DistributedKvDataManagerEncryptTest, DeleteEncryptedStore_001, TestSize.Level1) +{ + ZLOGI("DeleteEncryptedStore_001 begin."); + std::shared_ptr kvStore; + Status status = manager.GetSingleKvStore(createEnc, appId, storeId, kvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(kvStore, nullptr); + + Key key = "age"; + Value value = "18"; + status = kvStore->Put(key, value); + EXPECT_EQ(Status::SUCCESS, status); + std::shared_ptr resultSet = nullptr; + kvStore->GetResultSet("", resultSet); + ASSERT_NE(resultSet, nullptr); + ASSERT_TRUE(resultSet->GetCount() == 1); + + // Database busy, delete failed + status = manager.DeleteKvStore(appId, storeId, createEnc.baseDir); + ASSERT_NE(status, Status::SUCCESS); + + kvStore->CloseResultSet(resultSet); + resultSet = nullptr; + manager.CloseAllKvStore(appId); + kvStore = nullptr; + // GetSingleKvStore successful, data still available + status = manager.GetSingleKvStore(createEnc, appId, storeId, kvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(kvStore, nullptr); + Value valueRet; + status = kvStore->Get(key, valueRet); + ASSERT_EQ(valueRet, value); + + status = manager.DeleteKvStore(appId, storeId, createEnc.baseDir); + ASSERT_EQ(status, Status::SUCCESS); } \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_multi_user_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_multi_user_test.cpp new file mode 100644 index 00000000..69791fe3 --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_multi_user_test.cpp @@ -0,0 +1,223 @@ +/* + * 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 "distributed_kv_data_manager.h" + +using namespace testing::ext; +using namespace OHOS::DistributedKv; +namespace OHOS::Test { +static constexpr const char *APP_ID = "kv_multi_user_test"; +static constexpr const char *FIRST_STORE = "firstStoreId"; +static constexpr const char *SECOND_STORE = "secondStoreId"; +static constexpr int32_t USER_ID = 100; +static constexpr const char *DATA_DIR = "/data/service/el1/100/database"; +class DistributedKvDataManagerMultiUserTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static DistributedKvDataManager manager; + static Options normalOptions; + static Options encryptOptions; + static AppId appId; + static StoreId firstStoreId; + static StoreId secondStoreId; +}; + +DistributedKvDataManager DistributedKvDataManagerMultiUserTest::manager; +Options DistributedKvDataManagerMultiUserTest::normalOptions; +Options DistributedKvDataManagerMultiUserTest::encryptOptions; +AppId DistributedKvDataManagerMultiUserTest::appId; +StoreId DistributedKvDataManagerMultiUserTest::firstStoreId; +StoreId DistributedKvDataManagerMultiUserTest::secondStoreId; + +void DistributedKvDataManagerMultiUserTest::SetUpTestCase(void) +{ + appId.appId = APP_ID; + firstStoreId.storeId = FIRST_STORE; + secondStoreId.storeId = SECOND_STORE; + + std::string dataDir = DATA_DIR + appId.appId; + mkdir(dataDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + + normalOptions.createIfMissing = true; + normalOptions.securityLevel = S1; + normalOptions.kvStoreType = SINGLE_VERSION; + normalOptions.area = EL1; + normalOptions.subUser = USER_ID; + normalOptions.baseDir = dataDir; + normalOptions.encrypt = false; + + encryptOptions.createIfMissing = true; + encryptOptions.securityLevel = S1; + encryptOptions.kvStoreType = SINGLE_VERSION; + encryptOptions.area = EL1; + encryptOptions.subUser = USER_ID; + encryptOptions.baseDir = dataDir; + encryptOptions.encrypt = true; +} + +void DistributedKvDataManagerMultiUserTest::TearDownTestCase(void) +{ + (void)remove(normalOptions.baseDir.c_str()); +} + +void DistributedKvDataManagerMultiUserTest::SetUp() +{ +} + +void DistributedKvDataManagerMultiUserTest::TearDown() +{ + manager.CloseAllKvStore(appId, USER_ID); + manager.DeleteAllKvStore(appId, normalOptions.baseDir, USER_ID); +} + +/** +* @tc.name: GetKvStoreTest001 +* @tc.desc: get normal kv store with sub user +* @tc.type: FUNC +*/ +HWTEST_F(DistributedKvDataManagerMultiUserTest, GetKvStoreTest001, TestSize.Level1) +{ + std::shared_ptr kvStore; + auto status = manager.GetSingleKvStore(normalOptions, appId, firstStoreId, kvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(kvStore, nullptr); +} + +/** +* @tc.name: GetKvStoreTest002 +* @tc.desc: get encrypt kv store with sub user +* @tc.type: FUNC +*/ +HWTEST_F(DistributedKvDataManagerMultiUserTest, GetKvStoreTest002, TestSize.Level1) +{ + std::shared_ptr kvStore; + auto status = manager.GetSingleKvStore(encryptOptions, appId, firstStoreId, kvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(kvStore, nullptr); +} + +/** +* @tc.name: GetAllKvStoreIdTest +* @tc.desc: get all store id with sub user +* @tc.type: FUNC +*/ +HWTEST_F(DistributedKvDataManagerMultiUserTest, GetAllKvStoreId001, TestSize.Level1) +{ + std::shared_ptr firstKvStore; + auto status = manager.GetSingleKvStore(normalOptions, appId, firstStoreId, firstKvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(firstKvStore, nullptr); + + std::shared_ptr secondKvStore; + status = manager.GetSingleKvStore(normalOptions, appId, secondStoreId, secondKvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(secondKvStore, nullptr); + + std::vector storeIds; + status = manager.GetAllKvStoreId(appId, storeIds, normalOptions.subUser); + ASSERT_EQ(status, Status::SUCCESS); + + ASSERT_EQ(storeIds.size(), static_cast(2)); + ASSERT_NE(storeIds[0].storeId, storeIds[1].storeId); + ASSERT_TRUE(storeIds[0].storeId == firstStoreId.storeId || storeIds[0].storeId == secondStoreId.storeId); + ASSERT_TRUE(storeIds[1].storeId == secondStoreId.storeId || storeIds[0].storeId == secondStoreId.storeId); +} + +/** +* @tc.name: CloseKvStoreTest001 +* @tc.desc: close kv store with sub user +* @tc.type: FUNC +*/ +HWTEST_F(DistributedKvDataManagerMultiUserTest, CloseKvStoreTest001, TestSize.Level1) +{ + std::shared_ptr kvStore; + auto status = manager.GetSingleKvStore(normalOptions, appId, firstStoreId, kvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(kvStore, nullptr); + + status = manager.CloseKvStore(appId, firstStoreId, normalOptions.subUser); + ASSERT_EQ(status, Status::SUCCESS); +} + +/** +* @tc.name: CloseKvStoreTest002 +* @tc.desc: close kv store with sub user +* @tc.type: FUNC +*/ +HWTEST_F(DistributedKvDataManagerMultiUserTest, CloseKvStoreTest002, TestSize.Level1) +{ + std::shared_ptr kvStore; + auto status = manager.GetSingleKvStore(normalOptions, appId, firstStoreId, kvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(kvStore, nullptr); + + status = manager.CloseKvStore(appId, kvStore); + ASSERT_EQ(status, Status::SUCCESS); +} + +/** +* @tc.name: CloseKvStoreTest003 +* @tc.desc: delete kv store with sub user +* @tc.type: FUNC +*/ +HWTEST_F(DistributedKvDataManagerMultiUserTest, CloseKvStoreTest003, TestSize.Level1) +{ + std::shared_ptr kvStore; + auto status = manager.GetSingleKvStore(normalOptions, appId, firstStoreId, kvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(kvStore, nullptr); + + status = manager.CloseKvStore(appId, firstStoreId, normalOptions.subUser); + ASSERT_EQ(status, Status::SUCCESS); + kvStore = nullptr; + + status = manager.DeleteKvStore(appId, firstStoreId, normalOptions.baseDir, normalOptions.subUser); + ASSERT_EQ(status, Status::SUCCESS); +} + +/** +* @tc.name: DeleteKvStoreTest002 +* @tc.desc: delete all kv store with sub user +* @tc.type: FUNC +*/ +HWTEST_F(DistributedKvDataManagerMultiUserTest, DeleteKvStoreTest002, TestSize.Level1) +{ + std::shared_ptr firstKvStore; + auto status = manager.GetSingleKvStore(normalOptions, appId, firstStoreId, firstKvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(firstKvStore, nullptr); + + std::shared_ptr secondKvStore; + status = manager.GetSingleKvStore(normalOptions, appId, secondStoreId, secondKvStore); + ASSERT_EQ(status, Status::SUCCESS); + ASSERT_NE(secondKvStore, nullptr); + + status = manager.CloseKvStore(appId, firstStoreId, normalOptions.subUser); + ASSERT_EQ(status, Status::SUCCESS); + firstKvStore = nullptr; + + status = manager.CloseKvStore(appId, secondStoreId, normalOptions.subUser); + ASSERT_EQ(status, Status::SUCCESS); + secondKvStore = nullptr; + + status = manager.DeleteAllKvStore(appId, normalOptions.baseDir, normalOptions.subUser); + ASSERT_EQ(status, Status::SUCCESS); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp index a35a2070..d88a0bfb 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp @@ -153,7 +153,7 @@ void DistributedKvDataManagerTest::TearDown(void) * @tc.name: GetKvStore001 * @tc.desc: Get an exist SingleKvStore * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetKvStore001, TestSize.Level1) @@ -174,7 +174,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStore001, TestSize.Level1) * @tc.name: GetKvStore002 * @tc.desc: Create and get a new SingleKvStore * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetKvStore002, TestSize.Level1) @@ -193,7 +193,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStore002, TestSize.Level1) * @tc.desc: Get a non-existing SingleKvStore, and the callback function should receive STORE_NOT_FOUND and * get a nullptr. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetKvStore003, TestSize.Level1) @@ -208,7 +208,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStore003, TestSize.Level1) * @tc.name: GetKvStore004 * @tc.desc: Create a SingleKvStore with an empty storeId, and the callback function should receive * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetKvStore004, TestSize.Level1) @@ -224,7 +224,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStore004, TestSize.Level1) * @tc.name: GetKvStore005 * @tc.desc: Get a SingleKvStore with an empty storeId, and the callback function should receive INVALID_ARGUMENT * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetKvStore005, TestSize.Level1) @@ -240,7 +240,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStore005, TestSize.Level1) * @tc.name: GetKvStore006 * @tc.desc: Create a SingleKvStore with a 65-byte storeId, and the callback function should receive INVALID_ARGUMENT * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetKvStore006, TestSize.Level1) @@ -256,7 +256,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStore006, TestSize.Level1) * @tc.name: GetKvStore007 * @tc.desc: Get a SingleKvStore with a 65-byte storeId, the callback function should receive INVALID_ARGUMENT * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetKvStore007, TestSize.Level1) @@ -350,7 +350,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStore010, TestSize.Level1) * @tc.desc: Get a SingleKvStore with a 64 * -byte storeId, the callback function should receive INVALID_ARGUMENT * @tc.type: FUNC -* @tc.require: SR000IIM2J AR000IIMLL +* @tc.require: * @tc.author: wangkai */ HWTEST_F(DistributedKvDataManagerTest, GetKvStoreInvalidSecurityLevel, TestSize.Level1) @@ -368,7 +368,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStoreInvalidSecurityLevel, TestSize. * @tc.name: GetAllKvStore001 * @tc.desc: Get all KvStore IDs when no KvStore exists, and the callback function should receive a 0-length vector. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetAllKvStore001, TestSize.Level1) @@ -384,7 +384,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetAllKvStore001, TestSize.Level1) * @tc.name: GetAllKvStore002 * @tc.desc: Get all SingleKvStore IDs when no KvStore exists, and the callback function should receive a empty vector. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, GetAllKvStore002, TestSize.Level1) @@ -434,7 +434,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetAllKvStore002, TestSize.Level1) * @tc.name: CloseKvStore001 * @tc.desc: Close an opened KVStore, and the callback function should return SUCCESS. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore001, TestSize.Level1) @@ -453,7 +453,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore001, TestSize.Level1) * @tc.name: CloseKvStore002 * @tc.desc: Close a closed SingleKvStore, and the callback function should return SUCCESS. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore002, TestSize.Level1) @@ -473,7 +473,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore002, TestSize.Level1) * @tc.name: CloseKvStore003 * @tc.desc: Close a SingleKvStore with an empty storeId, and the callback function should return INVALID_ARGUMENT. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore003, TestSize.Level1) @@ -487,7 +487,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore003, TestSize.Level1) * @tc.name: CloseKvStore004 * @tc.desc: Close a SingleKvStore with a 65-byte storeId, and the callback function should return INVALID_ARGUMENT. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore004, TestSize.Level1) @@ -501,7 +501,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore004, TestSize.Level1) * @tc.name: CloseKvStore005 * @tc.desc: Close a non-existing SingleKvStore, and the callback function should return STORE_NOT_OPEN. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore005, TestSize.Level1) @@ -515,7 +515,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseKvStore005, TestSize.Level1) * @tc.name: CloseKvStoreMulti001 * @tc.desc: Open a SingleKvStore several times and close them one by one. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000CSKRU +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseKvStoreMulti001, TestSize.Level1) @@ -542,7 +542,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseKvStoreMulti001, TestSize.Level1) * @tc.name: CloseKvStoreMulti002 * @tc.desc: Open a SingleKvStore several times and close them one by one. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000CSKRU +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseKvStoreMulti002, TestSize.Level1) @@ -580,7 +580,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseKvStoreMulti002, TestSize.Level1) * @tc.name: CloseAllKvStore001 * @tc.desc: Close all opened KvStores, and the callback function should return SUCCESS. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseAllKvStore001, TestSize.Level1) @@ -604,7 +604,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseAllKvStore001, TestSize.Level1) * @tc.name: CloseAllKvStore002 * @tc.desc: Close all KvStores which exist but are not opened, and the callback function should return STORE_NOT_OPEN. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, CloseAllKvStore002, TestSize.Level1) @@ -631,7 +631,7 @@ HWTEST_F(DistributedKvDataManagerTest, CloseAllKvStore002, TestSize.Level1) * @tc.name: DeleteKvStore001 * @tc.desc: Delete a closed KvStore, and the callback function should return SUCCESS. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore001, TestSize.Level1) @@ -653,7 +653,7 @@ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore001, TestSize.Level1) * @tc.name: DeleteKvStore002 * @tc.desc: Delete an opened SingleKvStore, and the callback function should return SUCCESS. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore002, TestSize.Level1) @@ -673,7 +673,7 @@ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore002, TestSize.Level1) * @tc.name: DeleteKvStore003 * @tc.desc: Delete a non-existing KvStore, and the callback function should return DB_ERROR. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore003, TestSize.Level1) @@ -687,7 +687,7 @@ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore003, TestSize.Level1) * @tc.name: DeleteKvStore004 * @tc.desc: Delete a KvStore with an empty storeId, and the callback function should return INVALID_ARGUMENT. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore004, TestSize.Level1) @@ -702,7 +702,7 @@ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore004, TestSize.Level1) * @tc.desc: Delete a KvStore with 65 bytes long storeId (which exceed storeId length limit). Should * return INVALID_ARGUMENT. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore005, TestSize.Level1) @@ -716,7 +716,7 @@ HWTEST_F(DistributedKvDataManagerTest, DeleteKvStore005, TestSize.Level1) * @tc.name: DeleteAllKvStore001 * @tc.desc: Delete all KvStores after closing all of them, and the callback function should return SUCCESS. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, DeleteAllKvStore001, TestSize.Level1) @@ -748,7 +748,7 @@ HWTEST_F(DistributedKvDataManagerTest, DeleteAllKvStore001, TestSize.Level1) * @tc.name: DeleteAllKvStore002 * @tc.desc: Delete all kvstore fail when any kvstore in the appId is not closed * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, DeleteAllKvStore002, TestSize.Level1) @@ -773,7 +773,7 @@ HWTEST_F(DistributedKvDataManagerTest, DeleteAllKvStore002, TestSize.Level1) * @tc.name: DeleteAllKvStore003 * @tc.desc: Delete all KvStores even if no KvStore exists in the appId. * @tc.type: FUNC -* @tc.require: SR000CQDU0 AR000BVTDM +* @tc.require: * @tc.author: liqiao */ HWTEST_F(DistributedKvDataManagerTest, DeleteAllKvStore003, TestSize.Level1) @@ -856,7 +856,7 @@ HWTEST_F(DistributedKvDataManagerTest, GetSwitchWithInvalidArg, TestSize.Level1) auto [status2, data2] = manager.GetSwitch({ "switches_test_appId" }, ""); ASSERT_EQ(status2, Status::INVALID_ARGUMENT); auto [status3, data3] = manager.GetSwitch({ "switches_test_appId" }, "networkId_test"); - ASSERT_EQ(status3, Status::INVALID_ARGUMENT); + ASSERT_EQ(status3, Status::PERMISSION_DENIED); } /** diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/end_point_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/end_point_test.cpp index 6dc32c9a..ead5ef87 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/end_point_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/end_point_test.cpp @@ -58,6 +58,7 @@ void EndPointTest::SetUpTestCase(void) options_.area = EL1; options_.baseDir = std::string("/data/service/el1/public/database/odmf"); options_.securityLevel = S1; + options_.isClientSync = true; mkdir(options_.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); AppId appId = { "odmf" }; StoreId storeId = { "student_device" }; // define kvstore(database) name. diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_device_store_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_device_store_test.cpp index 1da92832..e28207fb 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_device_store_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_device_store_test.cpp @@ -172,7 +172,7 @@ HWTEST_F(LocalSubscribeDeviceStoreTest, KvStoreDdmSubscribeKvStore001, TestSize. * @tc.name: KvStoreDdmSubscribeKvStore002 * @tc.desc: Subscribe fail, observer is null * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeDeviceStoreTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1) diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_store_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_store_test.cpp index 517324f2..f837d74b 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_store_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_store_test.cpp @@ -161,7 +161,7 @@ uint32_t KvStoreObserverUnitTest::GetCallCount(uint32_t value) * @tc.name: KvStoreDdmSubscribeKvStore001 * @tc.desc: Subscribe success * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore001, TestSize.Level1) @@ -184,7 +184,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore001, TestSize.Level1 * @tc.name: KvStoreDdmSubscribeKvStore002 * @tc.desc: Subscribe fail, observer is null * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1) @@ -200,7 +200,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore002, TestSize.Level1 * @tc.name: KvStoreDdmSubscribeKvStore003 * @tc.desc: Subscribe success and OnChange callback after put * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore003, TestSize.Level1) @@ -227,7 +227,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore003, TestSize.Level1 * @tc.name: KvStoreDdmSubscribeKvStore004 * @tc.desc: The same observer subscribe three times and OnChange callback after put * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore004, TestSize.Level2) @@ -256,7 +256,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore004, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore005 * @tc.desc: The different observer subscribe three times and OnChange callback after put * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore005, TestSize.Level2) @@ -293,7 +293,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore005, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore006 * @tc.desc: Unsubscribe an observer and subscribe again - the map should be cleared after unsubscription. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore006, TestSize.Level2) @@ -336,7 +336,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore006, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore007 * @tc.desc: Subscribe to an observer - OnChange callback is called multiple times after the put operation. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore007, TestSize.Level2) @@ -371,7 +371,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore007, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore008 * @tc.desc: Subscribe to an observer - OnChange callback is called multiple times after the put&update operations. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore008, TestSize.Level2) @@ -405,7 +405,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore008, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore009 * @tc.desc: Subscribe to an observer - OnChange callback is called multiple times after the putBatch operation. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore009, TestSize.Level2) @@ -452,7 +452,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore009, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore010 * @tc.desc: Subscribe to an observer - OnChange callback is called multiple times after the putBatch update operation. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore010, TestSize.Level2) @@ -499,7 +499,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore010, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore011 * @tc.desc: Subscribe to an observer - OnChange callback is called after successful deletion. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore011, TestSize.Level2) @@ -536,7 +536,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore011, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore012 * @tc.desc: Subscribe to an observer - OnChange callback is not called after deletion of non-existing keys. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore012, TestSize.Level2) @@ -573,7 +573,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore012, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore013 * @tc.desc: Subscribe to an observer - OnChange callback is called after KvStore is cleared. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore013, TestSize.Level2) @@ -608,7 +608,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore013, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore014 * @tc.desc: Subscribe to an observer - OnChange callback is not called after non-existing data in KvStore is cleared. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore014, TestSize.Level2) @@ -628,7 +628,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore014, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore015 * @tc.desc: Subscribe to an observer - OnChange callback is called after the deleteBatch operation. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore015, TestSize.Level2) @@ -670,7 +670,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore015, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore016 * @tc.desc: Subscribe to an observer - OnChange callback is called after deleteBatch of non-existing keys. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore016, TestSize.Level2) @@ -712,7 +712,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore016, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStore020 * @tc.desc: Unsubscribe an observer two times. * @tc.type: FUNC -* @tc.require: AR000CQDU9 AR000CQS37 +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore020, TestSize.Level2) @@ -733,7 +733,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStore020, TestSize.Level2 * @tc.name: KvStoreDdmSubscribeKvStoreNotification001 * @tc.desc: Subscribe to an observer successfully - callback is called with a notification after the put operation. * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification001, TestSize.Level1) @@ -763,7 +763,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification001, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification002 * @tc.desc: Subscribe to the same observer three times - callback is called with a notification after the put operation. * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification002, TestSize.Level2) @@ -795,7 +795,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification002, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification003 * @tc.desc: The different observer subscribe three times and callback with notification after put * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification003, TestSize.Level2) @@ -843,7 +843,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification003, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification004 * @tc.desc: Verify notification after an observer is unsubscribed and then subscribed again. * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification004, TestSize.Level2) @@ -895,7 +895,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification004, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification005 * @tc.desc: Subscribe to an observer, callback with notification many times after put the different data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification005, TestSize.Level2) @@ -941,7 +941,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification005, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification006 * @tc.desc: Subscribe to an observer, callback with notification many times after put the same data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification006, TestSize.Level2) @@ -987,7 +987,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification006, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification007 * @tc.desc: Subscribe to an observer, callback with notification many times after put&update * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification007, TestSize.Level2) @@ -1026,7 +1026,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification007, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification008 * @tc.desc: Subscribe to an observer, callback with notification one times after putbatch&update * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification008, TestSize.Level2) @@ -1077,7 +1077,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification008, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification009 * @tc.desc: Subscribe to an observer, callback with notification one times after putbatch all different data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification009, TestSize.Level2) @@ -1120,7 +1120,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification009, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification010 * @tc.desc: Subscribe to an observer, callback with notification one times after putbatch both different and same data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification010, TestSize.Level2) @@ -1163,7 +1163,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification010, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification011 * @tc.desc: Subscribe to an observer, callback with notification one times after putbatch all same data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification011, TestSize.Level2) @@ -1204,7 +1204,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification011, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification012 * @tc.desc: Subscribe to an observer, callback with notification many times after putbatch all different data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification012, TestSize.Level2) @@ -1265,7 +1265,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification012, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification013 * @tc.desc: Subscribe to an observer, callback with notification many times after putbatch both different and same data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification013, TestSize.Level2) @@ -1327,7 +1327,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification013, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification014 * @tc.desc: Subscribe to an observer, callback with notification many times after putbatch all same data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification014, TestSize.Level2) @@ -1388,7 +1388,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification014, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification015 * @tc.desc: Subscribe to an observer, callback with notification many times after putbatch complex data * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification015, TestSize.Level2) @@ -1450,7 +1450,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification015, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification016 * @tc.desc: Pressure test subscribe, callback with notification many times after putbatch * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification016, TestSize.Level2) @@ -1483,7 +1483,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification016, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification017 * @tc.desc: Subscribe to an observer, callback with notification after delete success * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification017, TestSize.Level2) @@ -1523,7 +1523,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification017, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification018 * @tc.desc: Subscribe to an observer, not callback after delete which key not exist * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification018, TestSize.Level2) @@ -1561,7 +1561,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification018, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification019 * @tc.desc: Subscribe to an observer, delete the same data many times and only first delete callback with notification * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification019, TestSize.Level2) @@ -1606,7 +1606,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification019, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification020 * @tc.desc: Subscribe to an observer, callback with notification after deleteBatch * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification020, TestSize.Level2) @@ -1653,7 +1653,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification020, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification021 * @tc.desc: Subscribe to an observer, not callback after deleteBatch which all keys not exist * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification021, TestSize.Level2) @@ -1697,7 +1697,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification021, Tes * @tc.desc: Subscribe to an observer, deletebatch the same data many times and only first deletebatch callback with * notification * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification022, TestSize.Level2) @@ -1749,7 +1749,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification022, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification023 * @tc.desc: Subscribe to an observer, include Clear Put PutBatch Delete DeleteBatch * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification023, TestSize.Level2) @@ -1805,7 +1805,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification023, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification024 * @tc.desc: Subscribe to an observer[use transaction], include Clear Put PutBatch Delete DeleteBatch * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification024, TestSize.Level2) @@ -1857,7 +1857,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification024, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification025 * @tc.desc: Subscribe to an observer[use transaction], include Clear Put PutBatch Delete DeleteBatch * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: liuyuhui */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification025, TestSize.Level2) @@ -1913,7 +1913,7 @@ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification025, Tes * @tc.name: KvStoreDdmSubscribeKvStoreNotification026 * @tc.desc: Subscribe to an observer[use transaction], include bigData PutBatch update insert delete * @tc.type: FUNC -* @tc.require: AR000CIFGM +* @tc.require: * @tc.author: dukaizhan */ HWTEST_F(LocalSubscribeStoreTest, KvStoreDdmSubscribeKvStoreNotification026, TestSize.Level2) diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/single_kvstore_client_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/single_kvstore_client_test.cpp index b720f9db..09652be7 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/single_kvstore_client_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/single_kvstore_client_test.cpp @@ -136,7 +136,7 @@ void KvStoreSyncCallbackTestImpl::SyncCompleted(const std::map deviceIds; + DataQuery dataQuery; + auto syncStatus = singleKvStore->Sync(deviceIds, SyncMode::PUSH, dataQuery, false, nullptr); + ASSERT_NE(syncStatus, Status::SUCCESS); +} + /** * @tc.name: SubscribeWithQuery001 * desc: subscribe and sync device data with query; * type: FUNC - * require: AR000GH096 + * require: * author:taoyuxin */ HWTEST_F(SingleKvStoreClientTest, SubscribeWithQuery001, TestSize.Level1) @@ -1178,7 +1192,7 @@ HWTEST_F(SingleKvStoreClientTest, SubscribeWithQuery001, TestSize.Level1) * @tc.name: UnSubscribeWithQuery001 * desc: subscribe and sync device data with query; * type: FUNC - * require: SR000GH095 + * require: * author:taoyuxin */ HWTEST_F(SingleKvStoreClientTest, UnSubscribeWithQuery001, TestSize.Level1) diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/switch_observer_bridge_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/switch_observer_bridge_test.cpp new file mode 100644 index 00000000..39bede15 --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/switch_observer_bridge_test.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 "switch_observer_bridge.h" + +#include + +namespace OHOS::Test { +using namespace testing::ext; +using namespace OHOS::DistributedKv; +class SwitchObserverBridgeTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void) {} + void SetUp() {} + void TearDown() {} + + static AppId invalidAppId_; + static AppId validAppId_; +}; + +AppId SwitchObserverBridgeTest::invalidAppId_; +AppId SwitchObserverBridgeTest::validAppId_; + +void SwitchObserverBridgeTest::SetUpTestCase(void) +{ + invalidAppId_.appId = ""; + validAppId_.appId = "SwitchObserverBridgeTest"; +} + +class SwitchObserverTest : public KvStoreObserver { +public: + void OnSwitchChange(const SwitchNotification ¬ification) override {} +}; + +/** +* @tc.name: AddAndDeleteSwitchCallbackTest001 +* @tc.desc: test add and delete switch callback +* @tc.type: FUNC +*/ +HWTEST_F(SwitchObserverBridgeTest, AddAndDeleteSwitchCallbackTest001, TestSize.Level1) +{ + std::shared_ptr switchBridge = std::make_shared(validAppId_); + + switchBridge->AddSwitchCallback(nullptr); + ASSERT_TRUE(switchBridge->switchObservers_.Empty()); + + std::shared_ptr observer = std::make_shared(); + switchBridge->AddSwitchCallback(observer); + ASSERT_FALSE(switchBridge->switchObservers_.Empty()); + + switchBridge->DeleteSwitchCallback(nullptr); + ASSERT_FALSE(switchBridge->switchObservers_.Empty()); + + switchBridge->DeleteSwitchCallback(observer); + ASSERT_TRUE(switchBridge->switchObservers_.Empty()); +} + +/** +* @tc.name: OnRemoteDiedTest001 +* @tc.desc: test on remote died +* @tc.type: FUNC +*/ +HWTEST_F(SwitchObserverBridgeTest, OnRemoteDiedTest001, TestSize.Level1) +{ + std::shared_ptr switchBridge = std::make_shared(invalidAppId_); + switchBridge->OnRemoteDied(); + ASSERT_FALSE(switchBridge->switchAppId_.IsValid()); + + switchBridge = std::make_shared(validAppId_); + switchBridge->OnRemoteDied(); + ASSERT_TRUE(switchBridge->switchAppId_.IsValid()); + ASSERT_TRUE(switchBridge->switchObservers_.Empty()); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/datamgr_service_proxy.h b/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/datamgr_service_proxy.h index 510647da..20831cc3 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/datamgr_service_proxy.h +++ b/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/datamgr_service_proxy.h @@ -22,10 +22,12 @@ public: ~DataMgrServiceProxy() = default; sptr GetFeatureInterface(const std::string &name) override; - Status RegisterClientDeathObserver(const AppId &appId, sptr observer) override; + Status RegisterClientDeathObserver(const AppId &appId, sptr observer, + const std::string &featureName = "") override; int32_t ClearAppStorage(const std::string &bundleName, int32_t userId, int32_t appIndex, int32_t tokenId) override; + int32_t Exit(const std::string &featureName) override; private: static inline BrokerDelegator delegator_; }; diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/distributeddata_ipc_interface_code.h b/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/distributeddata_ipc_interface_code.h index 4776377e..59bbc6c9 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/distributeddata_ipc_interface_code.h +++ b/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/distributeddata_ipc_interface_code.h @@ -24,6 +24,7 @@ enum class KvStoreDataServiceInterfaceCode : uint32_t { GET_FEATURE_INTERFACE = 0, REGISTERCLIENTDEATHOBSERVER, CLEAR_APP_STORAGE, + FEATURE_EXIT, SERVICE_CMD_LAST }; } // namespace OHOS::DistributedKv diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/ikvstore_data_service.h b/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/ikvstore_data_service.h index 8c30d51d..b660d7b9 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/ikvstore_data_service.h +++ b/kv_store/frameworks/innerkitsimpl/distributeddatasvc/include/ikvstore_data_service.h @@ -30,11 +30,14 @@ public: virtual sptr GetFeatureInterface(const std::string &name) = 0; - virtual Status RegisterClientDeathObserver(const AppId &appId, sptr observer) = 0; + virtual Status RegisterClientDeathObserver(const AppId &appId, sptr observer, + const std::string &featureName = "") = 0; virtual int32_t ClearAppStorage(const std::string &bundleName, int32_t userId, int32_t appIndex, int32_t tokenId) = 0; + virtual int32_t Exit(const std::string &featureName) = 0; + protected: static constexpr size_t MAX_IPC_CAPACITY = 800 * 1024; }; diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatasvc/src/datamgr_service_proxy.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatasvc/src/datamgr_service_proxy.cpp index 4eed48d7..0863f0ac 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatasvc/src/datamgr_service_proxy.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatasvc/src/datamgr_service_proxy.cpp @@ -61,7 +61,8 @@ sptr DataMgrServiceProxy::GetFeatureInterface(const std::string & return remoteObject; } -Status DataMgrServiceProxy::RegisterClientDeathObserver(const AppId &appId, sptr observer) +Status DataMgrServiceProxy::RegisterClientDeathObserver(const AppId &appId, sptr observer, + const std::string &featureName) { MessageParcel data; MessageParcel reply; @@ -82,6 +83,10 @@ Status DataMgrServiceProxy::RegisterClientDeathObserver(const AppId &appId, sptr ZLOGE("This observer is null"); return Status::INVALID_ARGUMENT; } + if (!data.WriteString(featureName)) { + ZLOGW("Failed to write featureName."); + return Status::IPC_ERROR; + } MessageOption mo { MessageOption::TF_SYNC }; int32_t error = Remote()->SendRequest( @@ -117,5 +122,10 @@ int32_t DataMgrServiceProxy::ClearAppStorage(const std::string &bundleName, int3 } return static_cast(reply.ReadInt32()); } + +int32_t DataMgrServiceProxy::Exit(const std::string &featureName) +{ + return Status::NOT_SUPPORT; +} } // namespace DistributedKv } // namespace OHOS diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h index cf438e9e..a0cd3d9e 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h @@ -34,6 +34,7 @@ public: std::string query; uint64_t syncId = 0; int32_t triggerMode = 0; + bool isRetry = true; }; enum PasswordType { BACKUP_SECRET_KEY = 0, diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/security_manager.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/security_manager.h index 22b56ea3..4bb3a903 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/security_manager.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/security_manager.h @@ -24,6 +24,25 @@ namespace OHOS::DistributedKv { class SecurityManager { public: + struct SecurityContent { + static constexpr size_t MAGIC_NUM = 4; + static constexpr uint8_t MAGIC_CHAR = 0x6A; + static constexpr uint32_t MAGIC_NUMBER = 0x6A6A6A6A; + static constexpr uint8_t INVALID_VERSION = 0x00; + static constexpr uint8_t CURRENT_VERSION = 0x01; + static constexpr int32_t NONCE_SIZE = 12; + static constexpr int32_t KEY_SIZE = 32; + + bool isNewStyle = true; + uint32_t magicNum = MAGIC_NUMBER; + uint8_t version = INVALID_VERSION; + std::vector time; + std::vector nonceValue; + // encryptValue contains version and time and key + std::vector encryptValue; + std::vector fullKeyValue; + }; + struct DBPassword { bool isKeyOutdated = false; DistributedDB::CipherPassword password; @@ -53,14 +72,12 @@ public: public: KeyFiles(const std::string &name, const std::string &path, bool openFile = true); ~KeyFiles(); - const std::string &GetKeyFilePath(); int32_t Lock(); int32_t UnLock(); int32_t DestroyLock(); private: int32_t FileLock(int32_t lockType); int32_t lockFd_ = -1; - std::string keyPath_; std::string lockFile_; }; @@ -81,27 +98,20 @@ public: void DelDBPassword(const std::string &name, const std::string &path); private: - static constexpr const char *ROOT_KEY_ALIAS = "distributeddb_client_root_key"; - static constexpr const char *HKS_BLOB_TYPE_NONCE = "Z5s0Bo571KoqwIi6"; - static constexpr const char *HKS_BLOB_TYPE_AAD = "distributeddata_client"; - static constexpr const char *SUFFIX_KEY = ".key"; - static constexpr const char *SUFFIX_KEY_LOCK = ".key_lock"; - static constexpr const char *KEY_DIR = "/key"; - static constexpr const char *SLASH = "/"; - static constexpr int KEY_SIZE = 32; - static constexpr int HOURS_PER_YEAR = (24 * 365); - SecurityManager(); ~SecurityManager(); - std::vector LoadKeyFromFile(const std::string &name, const std::string &path, bool &isOutdated); + std::vector Random(int32_t length); + bool LoadContent(SecurityContent &content, const std::string &path); + void LoadKeyFromFile(const std::string &path, SecurityContent &securityContent); + void LoadNewKey(const std::vector &content, SecurityContent &securityContent); + void LoadOldKey(const std::vector &content, SecurityContent &securityContent); bool SaveKeyToFile(const std::string &name, const std::string &path, std::vector &key); - std::vector Random(int32_t len); bool IsKeyOutdated(const std::vector &date); int32_t GenerateRootKey(); int32_t CheckRootKey(); bool Retry(); - std::vector Encrypt(const std::vector &key); - bool Decrypt(std::vector &source, std::vector &key); + bool Encrypt(const std::vector &key, SecurityContent &content); + bool Decrypt(SecurityContent &content); std::vector vecRootKeyAlias_{}; std::vector vecNonce_{}; @@ -109,4 +119,4 @@ private: std::atomic_bool hasRootKey_ = false; }; } // namespace OHOS::DistributedKv -#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_KVDB_SECURITY_MANAGER_H +#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_KVDB_SECURITY_MANAGER_H \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h index 4315696a..47777fb5 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h @@ -88,6 +88,8 @@ public: Status Sync(const std::vector &devices, SyncMode mode, uint32_t delay) override; Status Sync(const std::vector &devices, SyncMode mode, const DataQuery &query, std::shared_ptr syncCallback, uint32_t delay) override; + Status Sync(const std::vector &devices, SyncMode mode, const DataQuery &query, bool isRetry, + std::shared_ptr syncCallback) override; Status RegisterSyncCallback(std::shared_ptr callback) override; Status UnRegisterSyncCallback() override; Status SetSyncParam(const KvSyncParam &syncParam) override; @@ -117,7 +119,6 @@ private: (std::chrono::steady_clock::now() + std::chrono::milliseconds(offset)).time_since_epoch()) .count(); } - static constexpr int32_t INTEGRITY_CHECK_API_VERSION = 20; static constexpr uint32_t NOTIFY_INTERVAL = 200; // ms static constexpr size_t MAX_VALUE_LENGTH = 4 * 1024 * 1024; static constexpr size_t MAX_OBSERVER_SIZE = 8; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/store_manager.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/store_manager.h index 025895b3..48f727c1 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/store_manager.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/store_manager.h @@ -14,9 +14,13 @@ */ #ifndef OHOS_DISTRIBUTED_DATA_FRAMEWORKS_KVDB_STORE_MANAGER_H #define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_KVDB_STORE_MANAGER_H + +#include "concurrent_map.h" #include "single_kvstore.h" #include "kv_hiview_reporter.h" #include "store_factory.h" +#include "switch_observer_bridge.h" + namespace OHOS::DistributedKv { class StoreManager { public: @@ -35,6 +39,7 @@ public: private: std::shared_ptr OpenWithSecretKeyFromService(const AppId &appId, const StoreId &storeId, const Options &options, Status &status, StoreParams &storeParams); + ConcurrentMap> switchObservers_; }; -} +} // namespace OHOS::DistributedKv #endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_KVDB_STORE_MANAGER_H diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/kv_hiview_reporter.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/kv_hiview_reporter.cpp index abeacad5..c2755b9f 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/kv_hiview_reporter.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/kv_hiview_reporter.cpp @@ -18,16 +18,16 @@ #include "kv_hiview_reporter.h" #include #include +#include #include #include -#include -#include #include +#include #include "concurrent_map.h" #include "hisysevent_c.h" #include "log_print.h" -#include "types.h" #include "store_util.h" +#include "types.h" namespace OHOS::DistributedKv { static constexpr int MAX_TIME_BUF_LEN = 32; @@ -160,8 +160,8 @@ void KVDBFaultHiViewReporter::ReportFaultEvent(KVDBFaultEvent eventInfo) void KVDBFaultHiViewReporter::ReportCurruptedEvent(KVDBFaultEvent eventInfo) { if (eventInfo.appendix.empty() || eventInfo.storeName.empty()) { - ZLOGW("The dbPath or storeId is empty, dbPath:%{public}s, storeId:%{public}s", eventInfo.appendix.c_str(), - StoreUtil::Anonymous(eventInfo.storeName).c_str()); + ZLOGW("The dbPath or storeId is empty, dbPath:%{public}s, storeId:%{public}s", + StoreUtil::Anonymous(eventInfo.appendix).c_str(), StoreUtil::Anonymous(eventInfo.storeName).c_str()); return; } if (IsReportedCorruptedFault(eventInfo.bundleName, eventInfo.storeName, eventInfo.appendix)) { @@ -291,12 +291,12 @@ bool KVDBFaultHiViewReporter::IsReportedCorruptedFault(const std::string &appId, void KVDBFaultHiViewReporter::CreateCorruptedFlag(const std::string &dbPath, const std::string &storeId) { if (dbPath.empty() || storeId.empty()) { - ZLOGW("The dbPath or storeId is empty, dbPath:%{public}s, storeId:%{public}s", dbPath.c_str(), - StoreUtil::Anonymous(storeId).c_str()); + ZLOGW("The dbPath or storeId is empty, dbPath:%{public}s, storeId:%{public}s", + StoreUtil::Anonymous(dbPath).c_str(), StoreUtil::Anonymous(storeId).c_str()); return; } std::string flagFilename = dbPath + storeId + DB_CORRUPTED_POSTFIX; - int fd = creat(flagFilename.c_str(), S_IRWXU | S_IRWXG); + int fd = creat(flagFilename.c_str(), S_IRUSR | S_IWUSR); if (fd == -1) { ZLOGW("Creat corrupted flg fail, flgname=%{public}s, errno=%{public}d", StoreUtil::Anonymous(flagFilename).c_str(), errno); @@ -309,8 +309,8 @@ void KVDBFaultHiViewReporter::CreateCorruptedFlag(const std::string &dbPath, con void KVDBFaultHiViewReporter::DeleteCorruptedFlag(const std::string &dbPath, const std::string &storeId) { if (dbPath.empty() || storeId.empty()) { - ZLOGW("The dbPath or storeId is empty, dbPath:%{public}s, storeId:%{public}s", dbPath.c_str(), - StoreUtil::Anonymous(storeId).c_str()); + ZLOGW("The dbPath or storeId is empty, dbPath:%{public}s, storeId:%{public}s", + StoreUtil::Anonymous(dbPath).c_str(), StoreUtil::Anonymous(storeId).c_str()); return; } std::string flagFilename = dbPath + storeId + DB_CORRUPTED_POSTFIX; @@ -326,7 +326,7 @@ std::string KVDBFaultHiViewReporter::GetDBPath(const std::string &path, const st std::string reporterDir = ""; DistributedDB::KvStoreDelegateManager::GetDatabaseDir(storeId, reporterDir); reporterDir = path + "/kvdb/" + reporterDir + "/"; - return reporterDir; + return StoreUtil::Anonymous(reporterDir).c_str(); } std::string KVDBFaultHiViewReporter::GenerateAppendix(const KVDBFaultEvent &eventInfo) diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp index 5604fd76..88b5cd84 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp @@ -110,6 +110,7 @@ Status KVDBServiceClient::GetStoreIds(const AppId &appId, int32_t subUser, std:: reply, appId, StoreId(), subUser); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s", status, appId.appId.c_str()); + return static_cast(status); } ITypesUtil::Unmarshal(reply, storeIds); return static_cast(status); @@ -168,7 +169,7 @@ Status KVDBServiceClient::Sync(const AppId &appId, const StoreId &storeId, int32 { MessageParcel reply; int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_SYNC), reply, appId, storeId, - syncInfo.seqId, syncInfo.mode, syncInfo.devices, syncInfo.delay, syncInfo.query, subUser); + syncInfo.seqId, syncInfo.mode, syncInfo.devices, syncInfo.delay, syncInfo.query, subUser, syncInfo.isRetry); if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s, storeId:%{public}s, sequenceId:%{public}" PRIu64, status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), syncInfo.seqId); @@ -245,7 +246,7 @@ Status KVDBServiceClient::GetSyncParam(const AppId &appId, const StoreId &storeI if (status != SUCCESS) { ZLOGE("status:0x%{public}x, appId:%{public}s, storeId:%{public}s", status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str()); - return SUCCESS; + return static_cast(status); } ITypesUtil::Unmarshal(reply, syncParam.allowedDelayMs); return static_cast(status); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/process_system_api_adapter_impl.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/process_system_api_adapter_impl.cpp index 3ede302f..1c545cd2 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/process_system_api_adapter_impl.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/process_system_api_adapter_impl.cpp @@ -19,6 +19,7 @@ #include #include "log_print.h" #include "security_label.h" +#include "store_util.h" namespace OHOS::DistributedKv { using Label = DistributedDB::SecurityLabel; @@ -73,7 +74,8 @@ ProcessSystemApiAdapterImpl::DBStatus ProcessSystemApiAdapterImpl::SetSecurityOp if (!result) { auto fPath = filePath.substr(0, HEAD_SIZE) + REPLACE_CHAIN + filePath.substr(filePath.length() - END_SIZE, END_SIZE); - ZLOGE("Set label failed! level:%{public}s, file:%{public}s", secLevel.c_str(), fPath.c_str()); + ZLOGE("Set label failed! level:%{public}s, file:%{public}s", secLevel.c_str(), + StoreUtil::Anonymous(fPath).c_str()); return DBStatus::DB_ERROR; } return DBStatus::OK; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/security_manager.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/security_manager.cpp index 11d03ff5..60bfaa64 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/security_manager.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/security_manager.cpp @@ -12,13 +12,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define LOG_TAG "SECURITYMANAGER" +#define LOG_TAG "SecurityManager" + #include "security_manager.h" #include #include #include -#include #include #include @@ -30,7 +30,18 @@ #include "store_types.h" #include "store_util.h" #include "task_executor.h" + namespace OHOS::DistributedKv { +static constexpr int HOURS_PER_YEAR = (24 * 365); +static constexpr const char *ROOT_KEY_ALIAS = "distributeddb_client_root_key"; +static constexpr const char *HKS_BLOB_TYPE_NONCE = "Z5s0Bo571KoqwIi6"; +static constexpr const char *HKS_BLOB_TYPE_AAD = "distributeddata_client"; +static constexpr const char *SUFFIX_KEY = ".key"; +static constexpr const char *SUFFIX_KEY_V1 = ".key_v1"; +static constexpr const char *SUFFIX_KEY_LOCK = ".key_lock"; +static constexpr const char *KEY_DIR = "/key"; +static constexpr const char *SLASH = "/"; + SecurityManager::SecurityManager() { vecRootKeyAlias_ = std::vector(ROOT_KEY_ALIAS, ROOT_KEY_ALIAS + strlen(ROOT_KEY_ALIAS)); @@ -69,29 +80,75 @@ bool SecurityManager::Retry() return false; } -SecurityManager::DBPassword SecurityManager::GetDBPassword(const std::string &name, - const std::string &path, bool needCreate) +std::vector SecurityManager::Random(int32_t length) +{ + std::vector value(length, 0); + struct HksBlob blobValue = { .size = length, .data = &(value[0]) }; + auto ret = HksGenerateRandom(nullptr, &blobValue); + if (ret != HKS_SUCCESS) { + ZLOGE("HksGenerateRandom failed, status: %{public}d", ret); + return {}; + } + return value; +} + +bool SecurityManager::LoadContent(SecurityManager::SecurityContent &content, const std::string &path) +{ + if (!FileExists(path)) { + return false; + } + LoadKeyFromFile(path, content); + if (content.encryptValue.empty() || !Decrypt(content)) { + return false; + } + return true; +} + +SecurityManager::DBPassword SecurityManager::GetDBPassword(const std::string &name, const std::string &path, + bool needCreate) { - DBPassword dbPassword; KeyFiles keyFiles(name, path); KeyFilesAutoLock fileLock(keyFiles); - auto secKey = LoadKeyFromFile(name, path, dbPassword.isKeyOutdated); - std::vector key{}; - - if (secKey.empty() && needCreate) { - key = Random(KEY_SIZE); - if (!SaveKeyToFile(name, path, key)) { - secKey.assign(secKey.size(), 0); + DBPassword dbPassword; + auto oldKeyPath = path + KEY_DIR + SLASH + name + SUFFIX_KEY; + auto newKeyPath = path + KEY_DIR + SLASH + name + SUFFIX_KEY_V1; + SecurityContent content; + auto result = LoadContent(content, newKeyPath); + if (!result) { + content.isNewStyle = false; + result = LoadContent(content, oldKeyPath); + } + content.encryptValue.assign(content.encryptValue.size(), 0); + std::vector key; + if (result) { + size_t offset = 0; + if (content.isNewStyle && content.fullKeyValue.size() > (sizeof(time_t) / sizeof(uint8_t)) + 1) { + content.version = content.fullKeyValue[offset++]; + content.time.assign(content.fullKeyValue.begin() + offset, + content.fullKeyValue.begin() + offset + (sizeof(time_t) / sizeof(uint8_t))); + } + offset = content.isNewStyle ? (sizeof(time_t) / sizeof(uint8_t)) + 1 : 0; + if (content.fullKeyValue.size() > offset) { + key.assign(content.fullKeyValue.begin() + offset, content.fullKeyValue.end()); + } + // old security key file and update key file + if (!content.isNewStyle && !key.empty() && SaveKeyToFile(name, path, key)) { + StoreUtil::Remove(oldKeyPath); + } + content.fullKeyValue.assign(content.fullKeyValue.size(), 0); + } + if (!result && needCreate) { + key = Random(SecurityContent::KEY_SIZE); + if (key.empty() || !SaveKeyToFile(name, path, key)) { key.assign(key.size(), 0); return dbPassword; } + StoreUtil::Remove(oldKeyPath); } - - if ((!secKey.empty() && Decrypt(secKey, key)) || !key.empty()) { - dbPassword.SetValue(key.data(), key.size()); + if (!content.time.empty()) { + dbPassword.isKeyOutdated = IsKeyOutdated(content.time); } - - secKey.assign(secKey.size(), 0); + dbPassword.SetValue(key.data(), key.size()); key.assign(key.size(), 0); return dbPassword; } @@ -111,99 +168,116 @@ void SecurityManager::DelDBPassword(const std::string &name, const std::string & { KeyFiles keyFiles(name, path); KeyFilesAutoLock fileLock(keyFiles); - auto keyPath = keyFiles.GetKeyFilePath(); - StoreUtil::Remove(keyPath); + auto oldKeyPath = path + KEY_DIR + SLASH + name + SUFFIX_KEY; + auto newKeyPath = path + KEY_DIR + SLASH + name + SUFFIX_KEY_V1; + StoreUtil::Remove(oldKeyPath); + StoreUtil::Remove(newKeyPath); fileLock.UnLockAndDestroy(); } -std::vector SecurityManager::Random(int32_t len) +void SecurityManager::LoadKeyFromFile(const std::string &path, SecurityManager::SecurityContent &securityContent) { - std::random_device randomDevice; - std::uniform_int_distribution distribution(0, std::numeric_limits::max()); - std::vector key(len); - for (int32_t i = 0; i < len; i++) { - key[i] = static_cast(distribution(randomDevice)); + std::vector content; + auto loaded = LoadBufferFromFile(path, content); + if (!loaded) { + return; } - return key; + if (securityContent.isNewStyle) { + LoadNewKey(content, securityContent); + } else { + LoadOldKey(content, securityContent); + } + content.assign(content.size(), 0); } -std::vector SecurityManager::LoadKeyFromFile(const std::string &name, const std::string &path, - bool &isOutdated) +void SecurityManager::LoadNewKey(const std::vector &content, SecurityManager::SecurityContent &securityContent) { - auto keyPath = path + KEY_DIR + SLASH + name + SUFFIX_KEY; - if (!FileExists(keyPath)) { - return {}; - } - StoreUtil::RemoveRWXForOthers(path + KEY_DIR); - - std::vector content; - auto loaded = LoadBufferFromFile(keyPath, content); - if (!loaded) { - return {}; + if (content.size() < SecurityContent::MAGIC_NUM + SecurityContent::NONCE_SIZE + 1) { + return; } - - if (content.size() < (sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE + 1) { - return {}; + for (size_t index = 0; index < SecurityContent::MAGIC_NUM; ++index) { + if (content[index] != char(SecurityContent::MAGIC_CHAR)) { + return; + } } + size_t offset = SecurityContent::MAGIC_NUM; + securityContent.nonceValue.assign(content.begin() + offset, content.begin() + offset + SecurityContent::NONCE_SIZE); + offset += SecurityContent::NONCE_SIZE; + securityContent.encryptValue.assign(content.begin() + offset, content.end()); +} +void SecurityManager::LoadOldKey(const std::vector &content, SecurityManager::SecurityContent &securityContent) +{ size_t offset = 0; - if (content[offset] != char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE)) { - return {}; + if (content.size() < (sizeof(time_t) / sizeof(uint8_t)) + SecurityContent::KEY_SIZE + 1) { + return; } - - offset++; - std::vector date; - date.assign(content.begin() + offset, content.begin() + (sizeof(time_t) / sizeof(uint8_t)) + offset); - isOutdated = IsKeyOutdated(date); + if (content[offset] != char((sizeof(time_t) / sizeof(uint8_t)) + SecurityContent::KEY_SIZE)) { + return; + } + ++offset; + securityContent.time.assign(content.begin() + offset, content.begin() + + (sizeof(time_t) / sizeof(uint8_t)) + offset); offset += (sizeof(time_t) / sizeof(uint8_t)); - std::vector key{ content.begin() + offset, content.end() }; - content.assign(content.size(), 0); - return key; + securityContent.encryptValue.assign(content.begin() + offset, content.end()); } -bool SecurityManager::SaveKeyToFile(const std::string &name, const std::string &path, std::vector &key) +bool SecurityManager::SaveKeyToFile(const std::string &name, const std::string &path, + std::vector &key) { if (!hasRootKey_ && !Retry()) { ZLOGE("Failed! no root key and generation failed"); return false; } - auto secretKey = Encrypt(key); - if (secretKey.empty()) { - ZLOGE("Failed! encrypt failed"); + SecurityContent securityContent; + securityContent.version = SecurityContent::CURRENT_VERSION; + auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + securityContent.time = { reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time) }; + std::vector keyContent; + keyContent.push_back(securityContent.version); + keyContent.insert(keyContent.end(), securityContent.time.begin(), securityContent.time.end()); + keyContent.insert(keyContent.end(), key.begin(), key.end()); + if (!Encrypt(keyContent, securityContent)) { + keyContent.assign(keyContent.size(), 0); return false; } + keyContent.assign(keyContent.size(), 0); auto keyPath = path + KEY_DIR; StoreUtil::InitPath(keyPath); - std::vector content; - auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now()); - std::vector date(reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time)); - content.push_back(char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE)); - content.insert(content.end(), date.begin(), date.end()); - content.insert(content.end(), secretKey.begin(), secretKey.end()); - auto keyFullPath = keyPath + SLASH + name + SUFFIX_KEY; - auto ret = SaveBufferToFile(keyFullPath, content); - if (access(keyFullPath.c_str(), F_OK) == 0) { - StoreUtil::RemoveRWXForOthers(keyFullPath); + auto keyFullPath = keyPath + SLASH + name + SUFFIX_KEY_V1; + auto fd = open(keyFullPath.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + if (fd < 0) { + ZLOGE("Create file failed, ret:%{public}d", errno); + return false; } - content.assign(content.size(), 0); + std::string content(SecurityContent::MAGIC_NUM, static_cast(SecurityContent::MAGIC_CHAR)); + content.append(reinterpret_cast(securityContent.nonceValue.data()), + securityContent.nonceValue.size()); + content.append(reinterpret_cast(securityContent.encryptValue.data()), + securityContent.encryptValue.size()); + auto ret = SaveStringToFd(fd, content); + std::fill(content.begin(), content.end(), '\0'); + close(fd); if (!ret) { - ZLOGE("Client SaveSecretKey failed!"); + ZLOGE("Save key to file fail, ret:%{public}d", ret); return false; } + StoreUtil::RemoveRWXForOthers(keyFullPath); return ret; } -std::vector SecurityManager::Encrypt(const std::vector &key) +bool SecurityManager::Encrypt(const std::vector &key, SecurityManager::SecurityContent &content) { - struct HksBlob blobAad = { uint32_t(vecAad_.size()), vecAad_.data() }; - struct HksBlob blobNonce = { uint32_t(vecNonce_.size()), vecNonce_.data() }; - struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() }; - struct HksBlob plainKey = { uint32_t(key.size()), const_cast(key.data()) }; struct HksParamSet *params = nullptr; int32_t ret = HksInitParamSet(¶ms); if (ret != HKS_SUCCESS) { ZLOGE("HksInitParamSet failed, status: %{public}d", ret); - return {}; + return false; + } + content.nonceValue = Random(SecurityContent::NONCE_SIZE); + if (content.nonceValue.empty()) { + HksFreeParamSet(¶ms); + return false; } struct HksParam hksParam[] = { { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, @@ -211,50 +285,50 @@ std::vector SecurityManager::Encrypt(const std::vector &key) { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, - { .tag = HKS_TAG_NONCE, .blob = blobNonce }, - { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + { .tag = HKS_TAG_NONCE, .blob = { SecurityContent::NONCE_SIZE, &(content.nonceValue[0]) } }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = { uint32_t(vecAad_.size()), &(vecAad_[0]) } }, { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, }; ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); if (ret != HKS_SUCCESS) { ZLOGE("HksAddParams failed, status: %{public}d", ret); HksFreeParamSet(¶ms); - return {}; + return false; } - ret = HksBuildParamSet(¶ms); if (ret != HKS_SUCCESS) { ZLOGE("HksBuildParamSet failed, status: %{public}d", ret); HksFreeParamSet(¶ms); - return {}; + return false; } - uint8_t cipherBuf[256] = { 0 }; struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf }; + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() }; + struct HksBlob plainKey = { uint32_t(key.size()), const_cast(key.data()) }; ret = HksEncrypt(&rootKeyName, params, &plainKey, &cipherText); (void)HksFreeParamSet(¶ms); if (ret != HKS_SUCCESS) { ZLOGE("HksEncrypt failed, status: %{public}d", ret); - return {}; + return false; } - std::vector encryptedKey(cipherText.data, cipherText.data + cipherText.size); - (void)memset_s(cipherBuf, sizeof(cipherBuf), 0, sizeof(cipherBuf)); - return encryptedKey; + content.encryptValue = std::vector(cipherText.data, cipherText.data + cipherText.size); + std::fill(cipherBuf, cipherBuf + sizeof(cipherBuf), 0); + return true; } -bool SecurityManager::Decrypt(std::vector &source, std::vector &key) +bool SecurityManager::Decrypt(SecurityManager::SecurityContent &content) { - struct HksBlob blobAad = { uint32_t(vecAad_.size()), &(vecAad_[0]) }; - struct HksBlob blobNonce = { uint32_t(vecNonce_.size()), &(vecNonce_[0]) }; - struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), &(vecRootKeyAlias_[0]) }; - struct HksBlob encryptedKeyBlob = { uint32_t(source.size()), source.data() }; - struct HksParamSet *params = nullptr; int32_t ret = HksInitParamSet(¶ms); if (ret != HKS_SUCCESS) { ZLOGE("HksInitParamSet failed, status: %{public}d", ret); return false; } + struct HksBlob blobNonce = { .size = uint32_t(vecNonce_.size()), .data = &(vecNonce_[0]) }; + if (!(content.nonceValue.empty())) { + blobNonce.size = uint32_t(content.nonceValue.size()); + blobNonce.data = const_cast(&(content.nonceValue[0])); + } struct HksParam hksParam[] = { { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }, @@ -262,7 +336,7 @@ bool SecurityManager::Decrypt(std::vector &source, std::vector { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, { .tag = HKS_TAG_NONCE, .blob = blobNonce }, - { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = { uint32_t(vecAad_.size()), &(vecAad_[0]) } }, { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, }; ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); @@ -271,25 +345,25 @@ bool SecurityManager::Decrypt(std::vector &source, std::vector HksFreeParamSet(¶ms); return false; } - ret = HksBuildParamSet(¶ms); if (ret != HKS_SUCCESS) { ZLOGE("HksBuildParamSet failed, status: %{public}d", ret); HksFreeParamSet(¶ms); return false; } - uint8_t plainBuf[256] = { 0 }; struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf }; + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), &(vecRootKeyAlias_[0]) }; + struct HksBlob encryptedKeyBlob = { uint32_t(content.encryptValue.size()), + const_cast(content.encryptValue.data()) }; ret = HksDecrypt(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob); (void)HksFreeParamSet(¶ms); if (ret != HKS_SUCCESS) { ZLOGE("HksDecrypt, status: %{public}d", ret); return false; } - - key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size); - (void)memset_s(plainBuf, sizeof(plainBuf), 0, sizeof(plainBuf)); + content.fullKeyValue.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size); + std::fill(plainBuf, plainBuf + sizeof(plainBuf), 0); return true; } @@ -382,13 +456,12 @@ bool SecurityManager::IsKeyOutdated(const std::vector &date) SecurityManager::KeyFiles::KeyFiles(const std::string &name, const std::string &path, bool openFile) { - keyPath_ = path + KEY_DIR + SLASH + name + SUFFIX_KEY; lockFile_ = path + KEY_DIR + SLASH + name + SUFFIX_KEY_LOCK; StoreUtil::InitPath(path + KEY_DIR); if (!openFile) { return; } - lockFd_ = open(lockFile_.c_str(), O_RDONLY | O_CREAT, S_IRWXU | S_IRWXG); + lockFd_ = open(lockFile_.c_str(), O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR); if (lockFd_ < 0) { ZLOGE("Open failed, errno:%{public}d, path:%{public}s", errno, StoreUtil::Anonymous(lockFile_).c_str()); } @@ -403,11 +476,6 @@ SecurityManager::KeyFiles::~KeyFiles() lockFd_ = -1; } -const std::string &SecurityManager::KeyFiles::GetKeyFilePath() -{ - return keyPath_; -} - int32_t SecurityManager::KeyFiles::Lock() { return FileLock(LOCK_EX); @@ -454,6 +522,7 @@ SecurityManager::KeyFilesAutoLock::~KeyFilesAutoLock() { keyFiles_.UnLock(); } + int32_t SecurityManager::KeyFilesAutoLock::UnLockAndDestroy() { keyFiles_.UnLock(); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp index 928b1459..cff5bfb9 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp @@ -60,7 +60,7 @@ SingleStoreImpl::SingleStoreImpl( isApplication_ = true; apiVersion_ = options.apiVersion; } - if (!isApplication_ || (isApplication_ && (apiVersion_ >= INTEGRITY_CHECK_API_VERSION))) { + if (!isApplication_) { isCheckIntegrity_ = true; } } @@ -610,6 +610,19 @@ Status SingleStoreImpl::Sync(const std::vector &devices, SyncMode m return DoSync(syncInfo, syncCallback); } +Status SingleStoreImpl::Sync(const std::vector &devices, SyncMode mode, const DataQuery &query, + bool isRetry, std::shared_ptr syncCallback) +{ + DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__)); + KVDBService::SyncInfo syncInfo; + syncInfo.seqId = StoreUtil::GenSequenceId(); + syncInfo.mode = mode; + syncInfo.devices = devices; + syncInfo.query = query.ToString(); + syncInfo.isRetry = isRetry; + return DoSync(syncInfo, syncCallback); +} + Status SingleStoreImpl::CloudSync(const AsyncDetail &async) { DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__)); @@ -1101,7 +1114,7 @@ bool SingleStoreImpl::IsRebuild() void SingleStoreImpl::ReportDBFaultEvent(Status status, const std::string &functionName) const { Options options = { .encrypt = encrypt_, .autoSync = autoSync_, .securityLevel = securityLevel_, - .area = area_, .hapName = hapName_ }; + .area = area_, .hapName = hapName_, .baseDir = path_ }; ReportInfo reportInfo = { .options = options, .errorCode = status, .systemErrorNo = errno, .appId = appId_, .storeId = storeId_, .functionName = functionName }; KVDBFaultHiViewReporter::ReportKVFaultEvent(reportInfo); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp index e15c248c..e815ad2a 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp @@ -116,7 +116,8 @@ std::shared_ptr StoreFactory::GetOrOpenStore(const AppId &appId, status = StoreUtil::ConvertStatus(dbStatus); if (kvStore == nullptr) { ZLOGE("Failed! status:%{public}d appId:%{public}s storeId:%{public}s path:%{public}s", dbStatus, - appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), path.c_str()); + appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), + StoreUtil::Anonymous(path).c_str()); return !stores.empty(); } stores[key] = kvStore; @@ -133,9 +134,11 @@ Status StoreFactory::Delete(const AppId &appId, const StoreId &storeId, const st { Close(appId, storeId, subUser, true); auto dbManager = GetDBManager(path, appId, subUser); - auto status = dbManager->DeleteKvStore(storeId); - SecurityManager::GetInstance().DelDBPassword(storeId.storeId, path); - return StoreUtil::ConvertStatus(status); + Status status = StoreUtil::ConvertStatus(dbManager->DeleteKvStore(storeId)); + if (status == SUCCESS) { + SecurityManager::GetInstance().DelDBPassword(storeId.storeId, path); + } + return status; } Status StoreFactory::Close(const AppId &appId, const StoreId &storeId, int32_t subUser, bool isForce) @@ -193,6 +196,7 @@ StoreFactory::DBOption StoreFactory::GetDBOption(const Options &options, const D dbOption.rdconfig.readOnly = (options.role == VISITOR ? true : false); dbOption.isMemoryDb = (!options.persistent); dbOption.isEncryptedDb = options.encrypt; + dbOption.localOnly = !options.isClientSync; if (options.encrypt) { dbOption.cipher = DistributedDB::CipherType::AES_256_GCM; dbOption.passwd = dbPassword.password; @@ -204,12 +208,12 @@ StoreFactory::DBOption StoreFactory::GetDBOption(const Options &options, const D dbOption.conflictResolvePolicy = DistributedDB::LAST_WIN; } else if (options.kvStoreType == KvStoreType::LOCAL_ONLY) { dbOption.storageEngineType = DistributedDB::GAUSSDB_RD; + dbOption.localOnly = false; } dbOption.schema = options.schema; dbOption.createDirByStoreIdOnly = true; dbOption.secOption = StoreUtil::GetDBSecurity(options.securityLevel); - dbOption.localOnly = !options.syncable; dbOption.rdconfig.type = StoreUtil::GetDBIndexType(options.config.type); dbOption.rdconfig.pageSize = options.config.pageSize; dbOption.rdconfig.cacheSize = options.config.cacheSize; @@ -249,9 +253,9 @@ Status StoreFactory::RekeyRecover(const std::string &storeId, const std::string std::shared_ptr dbManager, const Options &options) { auto rekeyPath = path + "/rekey"; - auto keyName = path + "/key/" + storeId + ".key"; + auto keyName = path + "/key/" + storeId + ".key_v1"; auto reKeyFile = storeId + REKEY_NEW; - auto rekeyName = path + "/rekey/key/" + reKeyFile + ".key"; + auto rekeyName = path + "/rekey/key/" + reKeyFile + ".key_v1"; Status pwdValid = DB_ERROR; if (StoreUtil::IsFileExist(keyName)) { dbPassword = SecurityManager::GetInstance().GetDBPassword(storeId, path); @@ -293,7 +297,7 @@ bool StoreFactory::ExecuteRekey(const std::string &storeId, const std::string &p DBStore *dbStore) { std::string rekeyPath = path + "/rekey"; - std::string rekeyName = rekeyPath + "/key/" + storeId + REKEY_NEW + ".key"; + std::string rekeyName = rekeyPath + "/key/" + storeId + REKEY_NEW + ".key_v1"; (void)StoreUtil::InitPath(rekeyPath); auto newDbPassword = SecurityManager::GetInstance().GetDBPassword(storeId + REKEY_NEW, rekeyPath, true); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp index 5a8230b4..1484e74f 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp @@ -18,6 +18,7 @@ #include "backup_manager.h" #include "dev_manager.h" #include "kvdb_service_client.h" +#include "kvstore_service_death_notifier.h" #include "log_print.h" #include "security_manager.h" @@ -34,7 +35,8 @@ std::shared_ptr StoreManager::GetKVStore(const AppId &appId, cons { std::string path = options.GetDatabaseDir(); ZLOGD("appId:%{public}s, storeId:%{public}s type:%{public}d area:%{public}d dir:%{public}s", appId.appId.c_str(), - StoreUtil::Anonymous(storeId.storeId).c_str(), options.kvStoreType, options.area, path.c_str()); + StoreUtil::Anonymous(storeId.storeId).c_str(), options.kvStoreType, options.area, + StoreUtil::Anonymous(path).c_str()); status = ILLEGAL_STATE; if (!appId.IsValid() || !storeId.IsValid() || !options.IsValidType()) { ZLOGE("Params invalid type"); @@ -146,18 +148,16 @@ Status StoreManager::GetStoreIds(const AppId &appId, std::vector &store Status StoreManager::Delete(const AppId &appId, const StoreId &storeId, const std::string &path, int32_t subUser) { ZLOGD("appId:%{public}s, storeId:%{public}s dir:%{public}s", appId.appId.c_str(), - StoreUtil::Anonymous(storeId.storeId).c_str(), path.c_str()); + StoreUtil::Anonymous(storeId.storeId).c_str(), StoreUtil::Anonymous(path).c_str()); if (!appId.IsValid() || !storeId.IsValid()) { return INVALID_ARGUMENT; } - auto service = KVDBServiceClient::GetInstance(); if (service != nullptr) { service->Delete(appId, storeId, subUser); } auto status = StoreFactory::GetInstance().Delete(appId, storeId, path, subUser); - Options options = { .baseDir = path }; - ReportInfo reportInfo = { .options = options, .errorCode = status, .systemErrorNo = errno, + ReportInfo reportInfo = { .options = { .baseDir = path }, .errorCode = status, .systemErrorNo = errno, .appId = appId.appId, .storeId = storeId.storeId, .functionName = std::string(__FUNCTION__) }; if (status != SUCCESS) { KVDBFaultHiViewReporter::ReportKVFaultEvent(reportInfo); @@ -183,7 +183,7 @@ Status StoreManager::PutSwitch(const AppId &appId, const SwitchData &data) std::pair StoreManager::GetSwitch(const AppId &appId, const std::string &networkId) { ZLOGD("appId:%{public}s, networkId:%{public}s", appId.appId.c_str(), StoreUtil::Anonymous(networkId).c_str()); - if (!appId.IsValid() || DevManager::GetInstance().ToUUID(networkId).empty()) { + if (!appId.IsValid() || networkId.empty()) { return { INVALID_ARGUMENT, SwitchData() }; } auto service = KVDBServiceClient::GetInstance(); @@ -214,6 +214,14 @@ Status StoreManager::SubscribeSwitchData(const AppId &appId, std::shared_ptrAddSwitchCallback(appId.appId, observer); + switchObservers_.Compute(appId.appId, [appId, observer](auto &, auto &switchBridge) { + if (switchBridge == nullptr) { + switchBridge = std::make_shared(appId); + KvStoreServiceDeathNotifier::AddServiceDeathWatcher(switchBridge); + } + switchBridge->AddSwitchCallback(observer); + return true; + }); return SUCCESS; } @@ -236,6 +244,12 @@ Status StoreManager::UnsubscribeSwitchData(const AppId &appId, std::shared_ptrDeleteSwitchCallback(appId.appId, observer); + switchObservers_.ComputeIfPresent(appId.appId, [appId, observer](auto &, auto &switchBridge) { + if (switchBridge != nullptr) { + switchBridge->DeleteSwitchCallback(observer); + } + return true; + }); return SUCCESS; } -} // namespace OHOS::DistributedKv \ No newline at end of file +} \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_util.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_util.cpp index 0aee2fe1..5b260b0d 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_util.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_util.cpp @@ -27,9 +27,9 @@ constexpr mode_t DEFAULT_UMASK = 0002; constexpr int32_t HEAD_SIZE = 3; constexpr int32_t END_SIZE = 3; constexpr int32_t MIN_SIZE = HEAD_SIZE + END_SIZE + 3; +constexpr int32_t SERVICE_GID = 3012; constexpr const char *REPLACE_CHAIN = "***"; constexpr const char *DEFAULT_ANONYMOUS = "******"; -constexpr int32_t SERVICE_GID = 3012; std::atomic StoreUtil::sequenceId_ = 0; using DBStatus = DistributedDB::DBStatus; std::map StoreUtil::statusMap_ = { @@ -159,7 +159,7 @@ bool StoreUtil::InitPath(const std::string &path) return RemoveRWXForOthers(path); } if (mkdir(path.c_str(), (S_IRWXU | S_IRWXG)) != 0 && errno != EEXIST) { - ZLOGE("Mkdir error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("Mkdir error:%{public}d, path:%{public}s", errno, Anonymous(path).c_str()); return false; } Acl acl(path); @@ -174,9 +174,9 @@ bool StoreUtil::CreateFile(const std::string &name) if (access(name.c_str(), F_OK) == 0) { return RemoveRWXForOthers(name); } - int fp = open(name.c_str(), (O_WRONLY | O_CREAT), (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP)); + int fp = open(name.c_str(), (O_WRONLY | O_CREAT), (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)); if (fp < 0) { - ZLOGE("Fopen error:%{public}d, path:%{public}s", errno, name.c_str()); + ZLOGE("Fopen error:%{public}d, path:%{public}s", errno, Anonymous(name).c_str()); return false; } close(fp); @@ -188,7 +188,7 @@ std::vector StoreUtil::GetSubPath(const std::string &path) std::vector subPaths; DIR *dirp = opendir(path.c_str()); if (dirp == nullptr) { - ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, Anonymous(path).c_str()); return subPaths; } struct dirent *dp; @@ -206,7 +206,7 @@ std::vector StoreUtil::GetFiles(const std::string &path) std::vector fileInfos; DIR *dirp = opendir(path.c_str()); if (dirp == nullptr) { - ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, Anonymous(path).c_str()); return fileInfos; } struct dirent *dp; @@ -235,7 +235,8 @@ bool StoreUtil::Rename(const std::string &oldName, const std::string &newName) return false; } if (rename(oldName.c_str(), newName.c_str()) != 0) { - ZLOGE("The rename error:%{public}d, file:%{public}s->%{public}s", errno, oldName.c_str(), newName.c_str()); + ZLOGE("The rename error:%{public}d, file:%{public}s->%{public}s", errno, + Anonymous(oldName).c_str(), Anonymous(newName).c_str()); return false; } return true; @@ -258,7 +259,7 @@ bool StoreUtil::Remove(const std::string &path) return true; } if (remove(path.c_str()) != 0) { - ZLOGE("The remove error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("The remove error:%{public}d, path:%{public}s", errno, Anonymous(path).c_str()); return false; } return true; @@ -282,7 +283,7 @@ bool StoreUtil::RemoveRWXForOthers(const std::string &path) { struct stat buf; if (stat(path.c_str(), &buf) < 0) { - ZLOGI("The stat error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGI("The stat error:%{public}d, path:%{public}s", errno, Anonymous(path).c_str()); return true; } @@ -293,7 +294,7 @@ bool StoreUtil::RemoveRWXForOthers(const std::string &path) if (S_ISDIR(buf.st_mode)) { DIR *dirp = opendir(path.c_str()); if (dirp == nullptr) { - ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, Anonymous(path).c_str()); return false; } struct dirent *dp = nullptr; @@ -310,7 +311,7 @@ bool StoreUtil::RemoveRWXForOthers(const std::string &path) } if (chmod(path.c_str(), (buf.st_mode & ~S_IRWXO)) < 0) { - ZLOGE("The chmod error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("The chmod error:%{public}d, path:%{public}s", errno, Anonymous(path).c_str()); return false; } return true; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/task_executor.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/task_executor.cpp index af13f8c9..af4540d9 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/task_executor.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/task_executor.cpp @@ -77,7 +77,7 @@ void TaskExecutor::GenerateExecutors() { std::lock_guard lock(mtx_); if (pool_ == nullptr) { - pool_ = std::make_shared(MAX_THREADS, MIN_THREADS); + pool_ = std::make_shared(MAX_THREADS, MIN_THREADS, "TaskExecutor_KV"); } } } // namespace OHOS diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn b/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn index e05c20b2..eb36f150 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn @@ -55,6 +55,7 @@ ohos_source_set("kvdb_src_file") { "../../distributeddatafwk/src/kvstore_datashare_bridge.cpp", "../../distributeddatafwk/src/kvstore_observer_client.cpp", "../../distributeddatafwk/src/kvstore_service_death_notifier.cpp", + "../../distributeddatafwk/src/switch_observer_bridge.cpp", "../../distributeddatafwk/src/sync_observer.cpp", ] @@ -112,7 +113,7 @@ ohos_source_set("kvdb_src_file") { "data_share:datashare_common", "data_share:datashare_provider", ] - + subsystem_name = "distributeddatamgr" part_name = "kv_store" } @@ -127,8 +128,12 @@ ohos_unittest("SingleStoreImplTest") { configs = [ ":module_private_config" ] external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", + "access_token:libnativetoken", "c_utils:utils", "device_manager:devicemanagersdk", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", @@ -143,7 +148,6 @@ ohos_unittest("SingleStoreImplTest") { deps = [ ":kvdb_src_file", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", ] } @@ -159,6 +163,7 @@ ohos_unittest("StoreUtilTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", @@ -168,7 +173,6 @@ ohos_unittest("StoreUtilTest") { deps = [ ":kvdb_src_file", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", ] } @@ -184,6 +188,7 @@ ohos_unittest("BackupManagerTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", @@ -193,7 +198,6 @@ ohos_unittest("BackupManagerTest") { deps = [ ":kvdb_src_file", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", ] } @@ -209,6 +213,7 @@ ohos_unittest("DevManagerTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", @@ -218,7 +223,6 @@ ohos_unittest("DevManagerTest") { deps = [ ":kvdb_src_file", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", ] } @@ -236,6 +240,7 @@ ohos_unittest("DevManagerMockTest") { external_deps = [ "c_utils:utils", "device_manager:devicemanagersdk", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", @@ -245,7 +250,6 @@ ohos_unittest("DevManagerMockTest") { deps = [ ":kvdb_src_file", "${kv_store_base_path}/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", ] } @@ -261,6 +265,7 @@ ohos_unittest("SingleStoreImplGetTopTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "ipc:ipc_single", "safwk:system_ability_fwk", @@ -270,7 +275,6 @@ ohos_unittest("SingleStoreImplGetTopTest") { deps = [ ":kvdb_src_file", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", ] } @@ -286,7 +290,9 @@ ohos_unittest("StoreFactoryTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", + "huks:libhukssdk", "ipc:ipc_single", "safwk:system_ability_fwk", "samgr:samgr_proxy", @@ -295,7 +301,6 @@ ohos_unittest("StoreFactoryTest") { deps = [ ":kvdb_src_file", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", ] } @@ -308,6 +313,7 @@ ohos_unittest("SecurityManagerTest") { external_deps = [ "c_utils:utils", + "googletest:gtest", "hilog:libhilog", "huks:libhukssdk", "ipc:ipc_single", @@ -318,57 +324,6 @@ ohos_unittest("SecurityManagerTest") { deps = [ ":kvdb_src_file", "../../../libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", - ] -} - -ohos_unittest("SingleStorePerfPcTest") { - module_out_path = module_output_path - - sources = [ - "../../kvdb/src/kv_hiview_reporter_mock.cpp", - "single_store_perf_pc_test.cpp", - ] - - configs = [ ":module_private_config" ] - - external_deps = [ - "c_utils:utils", - "hilog:libhilog", - "ipc:ipc_single", - "safwk:system_ability_fwk", - "samgr:samgr_proxy", - ] - - deps = [ - ":kvdb_src_file", - "${kv_store_base_path}/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", - ] -} - -ohos_unittest("SingleStorePerfPhoneTest") { - module_out_path = module_output_path - - sources = [ - "../../kvdb/src/kv_hiview_reporter_mock.cpp", - "single_store_perf_phone_test.cpp", - ] - - configs = [ ":module_private_config" ] - - external_deps = [ - "c_utils:utils", - "hilog:libhilog", - "ipc:ipc_single", - "safwk:system_ability_fwk", - "samgr:samgr_proxy", - ] - - deps = [ - ":kvdb_src_file", - "${kv_store_base_path}/frameworks/libs/distributeddb/:distributeddb", - "//third_party/googletest:gtest", ] } @@ -382,6 +337,7 @@ ohos_unittest("StoreFactoryMockTest") { "../../distributeddatafwk/src/kvstore_observer_client.cpp", "../../distributeddatafwk/src/kvstore_service_death_notifier.cpp", "../../distributeddatafwk/src/sync_observer.cpp", + "../../distributeddatafwk/src/switch_observer_bridge.cpp", "../../kvdb/src/kv_hiview_reporter_mock.cpp", "../src/backup_manager.cpp", "../src/convertor.cpp", @@ -457,6 +413,7 @@ ohos_unittest("SingleStoreImplMockTest") { "../../distributeddatafwk/src/kvstore_datashare_bridge.cpp", "../../distributeddatafwk/src/kvstore_observer_client.cpp", "../../distributeddatafwk/src/kvstore_service_death_notifier.cpp", + "../../distributeddatafwk/src/switch_observer_bridge.cpp", "../../distributeddatafwk/src/sync_observer.cpp", "../../kvdb/src/kv_hiview_reporter_mock.cpp", "../src/backup_manager.cpp", @@ -529,6 +486,35 @@ ohos_unittest("SingleStoreImplMockTest") { use_exceptions = true } +ohos_unittest("KvHiviewReporterTest") { + module_out_path = module_output_path + sources = [ + "../../kvdb/src/kv_hiview_reporter.cpp", + "./mock/src/hisysevent_mock.cpp", + "kv_hiview_reporter_test.cpp", + "../src/store_util.cpp", + ] + configs = [ ":module_private_config" ] + deps = [ + "${kv_store_base_path}/frameworks/libs/distributeddb:distributeddb", + "${kv_store_base_path}/interfaces/innerkits/distributeddata:distributeddata_inner", + "${kv_store_base_path}/databaseutils:database_utils", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "hisysevent:libhisysevent", + "googletest:gmock_main", + "googletest:gtest_main", + ] + + defines = [ + "private=public", + "protected=public", + ] +} + ############################################################################### group("unittest") { testonly = true @@ -544,15 +530,9 @@ group("unittest") { ":StoreFactoryMockTest", ":StoreFactoryTest", ":StoreUtilTest", + ":KvHiviewReporterTest", ] - if (false) { - deps += [ - ":SingleStorePerfPcTest", - ":SingleStorePerfPhoneTest", - ] - } - if (!use_libfuzzer) { deps += [ ":SecurityManagerTest" ] } diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/backup_manager_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/backup_manager_test.cpp index fba0ad58..b8f0ef88 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/backup_manager_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/backup_manager_test.cpp @@ -496,7 +496,7 @@ HWTEST_F(BackupManagerTest, RestoreEncryptWithKeyFromService, TestSize.Level0) ASSERT_EQ(status, SUCCESS); // delete backup key - auto ret = remove((baseDir + "/key/Prefix_backup_SingleKVStoreEncrypt_testbackup.key").c_str()); + auto ret = remove((baseDir + "/key/Prefix_backup_SingleKVStoreEncrypt_testbackup.key_v1").c_str()); ASSERT_EQ(ret, 0); status = kvStoreEncrypt->Delete("Put Test"); ASSERT_EQ(status, SUCCESS); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/dev_manager_mock_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/dev_manager_mock_test.cpp index b84cdc1b..1cf1fb19 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/dev_manager_mock_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/dev_manager_mock_test.cpp @@ -47,8 +47,6 @@ void DevManagerMockTest::TearDown(void) { } * @tc.name: GetUnEncryptedUuid * @tc.desc: test GetUnEncryptedUuid get local device info fail * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL */ HWTEST_F(DevManagerMockTest, GetUnEncryptedUuid001, TestSize.Level1) { @@ -61,8 +59,6 @@ HWTEST_F(DevManagerMockTest, GetUnEncryptedUuid001, TestSize.Level1) * @tc.name: GetUnEncryptedUuid * @tc.desc: test GetUnEncryptedUuid networkid empty * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL */ HWTEST_F(DevManagerMockTest, GetUnEncryptedUuid002, TestSize.Level1) { @@ -75,8 +71,6 @@ HWTEST_F(DevManagerMockTest, GetUnEncryptedUuid002, TestSize.Level1) * @tc.name: GetLocalDevice * @tc.desc: test GetLocalDevice get local device info fail * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL */ HWTEST_F(DevManagerMockTest, GetLocalDevice, TestSize.Level1) { @@ -89,8 +83,6 @@ HWTEST_F(DevManagerMockTest, GetLocalDevice, TestSize.Level1) * @tc.name: GetRemoteDevices001 * @tc.desc: test GetRemoteDevices get trusted device fail * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL */ HWTEST_F(DevManagerMockTest, GetRemoteDevices001, TestSize.Level1) { @@ -103,8 +95,6 @@ HWTEST_F(DevManagerMockTest, GetRemoteDevices001, TestSize.Level1) * @tc.name: GetRemoteDevices002 * @tc.desc: test GetRemoteDevices get trusted device no remote device * @tc.type: FUNC - * @tc.require: - * @tc.author: SQL */ HWTEST_F(DevManagerMockTest, GetRemoteDevices002, TestSize.Level1) { diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/kv_hiview_reporter_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/kv_hiview_reporter_test.cpp new file mode 100644 index 00000000..5424c213 --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/kv_hiview_reporter_test.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. + */ + +#define LOG_TAG "KvHiviewReporterTest" +#include + +#include "include/hisysevent_mock.h" +#include "kv_hiview_reporter.h" +#include "log_print.h" +#include "types.h" +#include + +namespace OHOS::Test { +using namespace testing; +using namespace testing::ext; +using namespace OHOS::DistributedKv; + +static constexpr const char *BASE_DIR = "/data/service/el1/public/database/KvHiviewReporterTest/"; +static constexpr const char *STOREID = "test_storeId"; +static constexpr const char *DB_CORRUPTED_POSTFIX = ".corruptedflg"; + +class KvHiviewReporterTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + + void SetUp(); + void TearDown(); +}; + +void KvHiviewReporterTest::SetUpTestCase(void) +{ + auto ret = mkdir(BASE_DIR, (S_IRWXU)); + if (ret != 0) { + ZLOGE("Mkdir failed, result:%{public}d, path:%{public}s", ret, BASE_DIR); + } +} + +void KvHiviewReporterTest::TearDownTestCase(void) +{ + auto ret = remove(BASE_DIR); + if (ret != 0) { + ZLOGE("Remove failed, result:%{public}d, path:%{public}s", ret, BASE_DIR); + } +} + +void KvHiviewReporterTest::SetUp(void) { } + +void KvHiviewReporterTest::TearDown(void) { } + +/** + * @tc.name: CorruptedFlagTest001 + * @tc.desc: Create and delete corrupted flag + * @tc.type: FUNC + */ +HWTEST_F(KvHiviewReporterTest, CorruptedFlagTest001, TestSize.Level1) +{ + ZLOGI("CorruptedFlagTest001 begin."); + KVDBFaultHiViewReporter::CreateCorruptedFlag(BASE_DIR, STOREID); + std::string flagFilename = std::string(BASE_DIR) + std::string(STOREID) + std::string(DB_CORRUPTED_POSTFIX); + auto ret = access(flagFilename.c_str(), F_OK); + ASSERT_EQ(ret, 0); + KVDBFaultHiViewReporter::DeleteCorruptedFlag(BASE_DIR, STOREID); + ret = access(flagFilename.c_str(), F_OK); + ASSERT_NE(ret, 0); +} + +/** + * @tc.name: ReportKVFaultEvent001 + * @tc.desc: Execute the ReportFaultEvent method + * @tc.type: FUNC + */ +HWTEST_F(KvHiviewReporterTest, ReportKVFaultEvent001, TestSize.Level1) +{ + ZLOGI("ReportKVFaultEvent001 begin."); + HiSysEventMock mock; + EXPECT_CALL(mock, HiSysEvent_Write(_, _, _, _, _, _, _)).Times(1); + ReportInfo reportInfo; + KVDBFaultHiViewReporter::ReportKVFaultEvent(reportInfo); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/gdb/include/gdb_helper.h b/kv_store/frameworks/innerkitsimpl/kvdb/test/mock/include/hisysevent_mock.h similarity index 49% rename from relational_store/interfaces/inner_api/gdb/include/gdb_helper.h rename to kv_store/frameworks/innerkitsimpl/kvdb/test/mock/include/hisysevent_mock.h index f3f3e7f1..101037a2 100644 --- a/relational_store/interfaces/inner_api/gdb/include/gdb_helper.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/mock/include/hisysevent_mock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 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,19 +13,30 @@ * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_DB_HELPER_H -#define OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_DB_HELPER_H -#include +#ifndef HISYSEVENT_MOCK_H +#define HISYSEVENT_MOCK_H -#include "gdb_store_config.h" -#include "gdb_store.h" -#include "rdb_visibility.h" +#include +#include +#include -namespace OHOS::DistributedDataAip { -class GDBHelper { +#include "hisysevent_c.h" +class HiSysEventMock { public: - API_EXPORT static std::shared_ptr GetDBStore(const StoreConfig &config, int &errCode); - API_EXPORT static int DeleteDBStore(const StoreConfig &config); + static HiSysEventMock *GetMock() + { + return mock.load(); + } + + HiSysEventMock(); + ~HiSysEventMock(); + + MOCK_METHOD7(HiSysEvent_Write, + int(const char *func, int64_t line, const char *domain, const char *name, HiSysEventEventType type, + const HiSysEventParam params[], size_t size)); + +private: + static inline std::atomic mock = nullptr; }; -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_DB_HELPER_H + +#endif // HISYSEVENT_MOCK_H diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/mock/src/hisysevent_mock.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/mock/src/hisysevent_mock.cpp new file mode 100644 index 00000000..0023df32 --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/mock/src/hisysevent_mock.cpp @@ -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. + */ + +#include "include/hisysevent_mock.h" +#include + +HiSysEventMock::HiSysEventMock() +{ + mock.store(this); +} +HiSysEventMock::~HiSysEventMock() +{ + mock.store(nullptr); +} + +int HiSysEvent_Write(const char *func, int64_t line, const char *domain, const char *name, HiSysEventEventType type, + const HiSysEventParam params[], size_t size) +{ + return HiSysEventMock::GetMock()->HiSysEvent_Write(func, line, domain, name, type, params, size); +} diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/security_manager_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/security_manager_test.cpp index 23898f55..4492ee6f 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/security_manager_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/security_manager_test.cpp @@ -13,52 +13,462 @@ * limitations under the License. */ +#include "security_manager.h" + #include +#include + #include "block_data.h" -#include "log_print.h" -#include "security_manager.h" +#include "file_ex.h" +#include "hks_api.h" +#include "hks_param.h" #include "store_util.h" namespace OHOS::Test { using namespace testing::ext; using namespace OHOS::DistributedKv; + +static constexpr int32_t KEY_SIZE = 32; +static constexpr int32_t NONCE_SIZE = 12; +static constexpr int32_t LOOP_NUM = 2; +static constexpr const char *STORE_NAME = "test_store"; +static constexpr const char *BASE_DIR = "/data/service/el1/public/database/SecurityManagerTest"; +static constexpr const char *KEY_DIR = "/data/service/el1/public/database/SecurityManagerTest/key"; +static constexpr const char *KEY_FULL_PATH = "/data/service/el1/public/database/SecurityManagerTest/key/test_store.key"; +static constexpr const char *KEY_FULL_PATH_V1 = + "/data/service/el1/public/database/SecurityManagerTest/key/test_store.key_v1"; +static constexpr const char *LOCK_FULL_PATH = + "/data/service/el1/public/database/SecurityManagerTest/key/test_store.key_lock"; +static constexpr const char *ROOT_KEY_ALIAS = "distributeddb_client_root_key"; +static constexpr const char *HKS_BLOB_TYPE_NONCE = "Z5s0Bo571KoqwIi6"; +static constexpr const char *HKS_BLOB_TYPE_AAD = "distributeddata_client"; + class SecurityManagerTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); void SetUp(); void TearDown(); + + static std::vector Random(int32_t length); + static std::vector Encrypt(const std::vector &key, const std::vector &nonce); + static bool SaveKeyToOldFile(const std::vector &key); + static void GenerateRootKey(); + static void DeleteRootKey(); + + static std::vector vecRootKeyAlias_; + static std::vector vecNonce_; + static std::vector vecAad_; }; -void SecurityManagerTest::SetUpTestCase(void) { } +std::vector SecurityManagerTest::vecRootKeyAlias_ = + std::vector(ROOT_KEY_ALIAS, ROOT_KEY_ALIAS + strlen(ROOT_KEY_ALIAS)); +std::vector SecurityManagerTest::vecNonce_ = + std::vector(HKS_BLOB_TYPE_NONCE, HKS_BLOB_TYPE_NONCE + strlen(HKS_BLOB_TYPE_NONCE)); +std::vector SecurityManagerTest::vecAad_ = + std::vector(HKS_BLOB_TYPE_AAD, HKS_BLOB_TYPE_AAD + strlen(HKS_BLOB_TYPE_AAD)); + +void SecurityManagerTest::SetUpTestCase(void) +{ + mkdir(BASE_DIR, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + GenerateRootKey(); +} + +void SecurityManagerTest::TearDownTestCase(void) +{ + DeleteRootKey(); + (void)remove(BASE_DIR); +} + +void SecurityManagerTest::SetUp() +{ + mkdir(KEY_DIR, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); +} + +void SecurityManagerTest::TearDown() +{ + (void)remove(LOCK_FULL_PATH); + (void)remove(KEY_FULL_PATH); + (void)remove(KEY_FULL_PATH_V1); + (void)remove(KEY_DIR); +} + +std::vector SecurityManagerTest::Random(int32_t length) +{ + std::vector value(length, 0); + struct HksBlob blobValue = { .size = length, .data = &(value[0]) }; + auto ret = HksGenerateRandom(nullptr, &blobValue); + if (ret != HKS_SUCCESS) { + return {}; + } + return value; +} + +std::vector SecurityManagerTest::Encrypt(const std::vector &key, const std::vector &nonce) +{ + struct HksBlob blobAad = { uint32_t(vecAad_.size()), vecAad_.data() }; + struct HksBlob blobNonce = { uint32_t(nonce.size()), const_cast(nonce.data()) }; + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() }; + struct HksBlob plainKey = { uint32_t(key.size()), const_cast(key.data()) }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + return {}; + } + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_NONCE, .blob = blobNonce }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, + }; + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return {}; + } + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return {}; + } + uint8_t cipherBuf[256] = { 0 }; + struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf }; + ret = HksEncrypt(&rootKeyName, params, &plainKey, &cipherText); + (void)HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + return {}; + } + std::vector encryptedKey(cipherText.data, cipherText.data + cipherText.size); + std::fill(cipherBuf, cipherBuf + sizeof(cipherBuf), 0); + return encryptedKey; +} + +bool SecurityManagerTest::SaveKeyToOldFile(const std::vector &key) +{ + auto encryptKey = Encrypt(key, vecNonce_); + if (encryptKey.empty()) { + return false; + } + std::vector content; + auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now()); + std::vector date(reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time)); + content.push_back(char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE)); + content.insert(content.end(), date.begin(), date.end()); + content.insert(content.end(), encryptKey.begin(), encryptKey.end()); + return SaveBufferToFile(KEY_FULL_PATH, content); +} -void SecurityManagerTest::TearDownTestCase(void) { } +void SecurityManagerTest::GenerateRootKey() +{ + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + return; + } + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, + }; + + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return; + } -void SecurityManagerTest::SetUp(void) { } + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return; + } + ret = HksGenerateKey(&rootKeyName, params, nullptr); + HksFreeParamSet(¶ms); +} + +void SecurityManagerTest::DeleteRootKey() +{ + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + return; + } + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, + }; + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return; + } + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return; + } + ret = HksDeleteKey(&rootKeyName, params); + HksFreeParamSet(¶ms); +} -void SecurityManagerTest::TearDown(void) { } +/** + * @tc.name: GetDBPasswordTest001 + * @tc.desc: get password with first create and needCreate is false + * @tc.type: FUNC + */ +HWTEST_F(SecurityManagerTest, GetDBPasswordTest001, TestSize.Level0) +{ + auto dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); +} /** - * @tc.name: DBPasswordTest - * @tc.desc: Test DBPassword function + * @tc.name: GetDBPasswordTest002 + * @tc.desc: get password with key file exist and the key file is empty * @tc.type: FUNC */ -HWTEST_F(SecurityManagerTest, DBPasswordTest, TestSize.Level1) +HWTEST_F(SecurityManagerTest, GetDBPasswordTest002, TestSize.Level0) { - SecurityManager::DBPassword passwd; - EXPECT_FALSE(passwd.IsValid()); - std::vector key = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F - }; - passwd.SetValue(key.data(), key.size()); - EXPECT_TRUE(passwd.IsValid()); - EXPECT_EQ(passwd.GetSize(), 32); - auto newKey = passwd.GetData(); - EXPECT_EQ(newKey[0], 0x00); - passwd.Clear(); - EXPECT_FALSE(passwd.IsValid()); + std::vector content; + auto result = SaveBufferToFile(KEY_FULL_PATH, content); + ASSERT_TRUE(result); + + auto dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + result = SaveBufferToFile(KEY_FULL_PATH_V1, content); + ASSERT_TRUE(result); + + dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + SecurityManager::GetInstance().DelDBPassword(STORE_NAME, BASE_DIR); +} + +/** + * @tc.name: GetDBPasswordTest003 + * @tc.desc: get password with old key file exist and the old key file is invalid + * @tc.type: FUNC + */ +HWTEST_F(SecurityManagerTest, GetDBPasswordTest003, TestSize.Level0) +{ + auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now()); + std::vector date(reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time)); + // 1.the size of content is invalid + std::vector invalidContent1; + invalidContent1.push_back(char(sizeof(time_t) / sizeof(uint8_t))); + invalidContent1.insert(invalidContent1.end(), date.begin(), date.end()); + auto result = SaveBufferToFile(KEY_FULL_PATH, invalidContent1); + ASSERT_TRUE(result); + auto dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + auto invalidKey = Random(KEY_SIZE); + ASSERT_FALSE(invalidKey.empty()); + // 2.the pos 0 of content is invalid + std::vector invalidContent2; + invalidContent2.push_back(char((sizeof(time_t) / sizeof(uint8_t)))); + invalidContent2.insert(invalidContent2.end(), date.begin(), date.end()); + invalidContent2.insert(invalidContent2.end(), invalidKey.begin(), invalidKey.end()); + result = SaveBufferToFile(KEY_FULL_PATH, invalidContent2); + ASSERT_TRUE(result); + dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + // 3.the key of content decrypt fail + std::vector invalidContent3; + invalidContent3.push_back(char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE)); + invalidContent3.insert(invalidContent3.end(), date.begin(), date.end()); + invalidContent3.insert(invalidContent3.end(), invalidKey.begin(), invalidKey.end()); + result = SaveBufferToFile(KEY_FULL_PATH, invalidContent3); + ASSERT_TRUE(result); + dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + SecurityManager::GetInstance().DelDBPassword(STORE_NAME, BASE_DIR); +} + +/** + * @tc.name: GetDBPasswordTest004 + * @tc.desc: get password with new key file exist and the new key file is invalid + * @tc.type: FUNC + */ +HWTEST_F(SecurityManagerTest, GetDBPasswordTest004, TestSize.Level0) +{ + std::vector content; + + // 1.the size of content is invalid + content.push_back(char(SecurityManager::SecurityContent::MAGIC_CHAR)); + auto result = SaveBufferToFile(KEY_FULL_PATH_V1, content); + ASSERT_TRUE(result); + auto dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + // 2.the size of content is invalid + for (size_t index = 0; index < SecurityManager::SecurityContent::MAGIC_NUM - 1; ++index) { + content.push_back(char(SecurityManager::SecurityContent::MAGIC_CHAR)); + } + result = SaveBufferToFile(KEY_FULL_PATH_V1, content); + ASSERT_TRUE(result); + dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + // 3.the size of content is invalid + auto nonce = Random(NONCE_SIZE); + ASSERT_FALSE(nonce.empty()); + content.insert(content.end(), nonce.begin(), nonce.end()); + result = SaveBufferToFile(KEY_FULL_PATH_V1, content); + ASSERT_TRUE(result); + dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + // 4.the content decrypt fail + auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now()); + std::vector date(reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time)); + std::vector invalidContent = content; + invalidContent.insert(invalidContent.end(), date.begin(), date.end()); + result = SaveBufferToFile(KEY_FULL_PATH_V1, invalidContent); + ASSERT_TRUE(result); + dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + // 5.the content decrypt success and key is empty + std::vector keyContent; + keyContent.push_back(SecurityManager::SecurityContent::CURRENT_VERSION); + keyContent.insert(keyContent.end(), date.begin(), date.end()); + auto encryptValue = Encrypt(keyContent, nonce); + ASSERT_FALSE(encryptValue.empty()); + invalidContent = content; + invalidContent.insert(invalidContent.end(), encryptValue.begin(), encryptValue.end()); + result = SaveBufferToFile(KEY_FULL_PATH_V1, invalidContent); + ASSERT_TRUE(result); + dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); + + SecurityManager::GetInstance().DelDBPassword(STORE_NAME, BASE_DIR); +} + +/** + * @tc.name: GetDBPasswordTest005 + * @tc.desc: get password with first create and needCreate is true + * @tc.type: FUNC + */ +HWTEST_F(SecurityManagerTest, GetDBPasswordTest005, TestSize.Level0) +{ + auto dbPassword1 = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, true); + ASSERT_TRUE(dbPassword1.IsValid()); + + auto dbPassword2 = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_TRUE(dbPassword2.IsValid()); + + ASSERT_EQ(dbPassword2.GetSize(), dbPassword1.GetSize()); + + std::vector key1(dbPassword1.GetData(), dbPassword1.GetData() + dbPassword1.GetSize()); + std::vector key2(dbPassword2.GetData(), dbPassword2.GetData() + dbPassword2.GetSize()); + ASSERT_EQ(key1.size(), key2.size()); + + for (auto index = 0; index < key1.size(); ++index) { + ASSERT_EQ(key1[index], key2[index]); + } + + key1.assign(key1.size(), 0); + key2.assign(key2.size(), 0); + dbPassword1.Clear(); + dbPassword2.Clear(); + SecurityManager::GetInstance().DelDBPassword(STORE_NAME, BASE_DIR); +} + +/** + * @tc.name: GetDBPasswordTest006 + * @tc.desc: get password with old key file exit and update + * @tc.type: FUNC + */ +HWTEST_F(SecurityManagerTest, GetDBPasswordTest006, TestSize.Level0) +{ + auto key = Random(KEY_SIZE); + ASSERT_FALSE(key.empty()); + auto result = SaveKeyToOldFile(key); + ASSERT_TRUE(result); + + for (auto loop = 0; loop < LOOP_NUM; ++loop) { + auto dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, true); + ASSERT_TRUE(dbPassword.IsValid()); + ASSERT_EQ(dbPassword.GetSize(), key.size()); + std::vector password(dbPassword.GetData(), dbPassword.GetData() + dbPassword.GetSize()); + ASSERT_EQ(password.size(), key.size()); + for (auto index = 0; index < key.size(); ++index) { + ASSERT_EQ(password[index], key[index]); + } + password.assign(password.size(), 0); + dbPassword.Clear(); + } + + key.assign(key.size(), 0); + SecurityManager::GetInstance().DelDBPassword(STORE_NAME, BASE_DIR); +} + +/** + * @tc.name: SaveDBPasswordTest001 + * @tc.desc: save password + * @tc.type: FUNC + */ +HWTEST_F(SecurityManagerTest, SaveDBPasswordTest001, TestSize.Level0) +{ + auto key = Random(KEY_SIZE); + ASSERT_FALSE(key.empty()); + + DistributedDB::CipherPassword dbPassword1; + dbPassword1.SetValue(key.data(), key.size()); + ASSERT_EQ(dbPassword1.GetSize(), key.size()); + auto result = SecurityManager::GetInstance().SaveDBPassword(STORE_NAME, BASE_DIR, dbPassword1); + ASSERT_TRUE(result); + dbPassword1.Clear(); + + auto dbPassword2 = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, true); + ASSERT_TRUE(dbPassword2.IsValid()); + ASSERT_EQ(dbPassword2.GetSize(), key.size()); + std::vector password(dbPassword2.GetData(), dbPassword2.GetData() + dbPassword2.GetSize()); + ASSERT_EQ(password.size(), key.size()); + for (auto index = 0; index < key.size(); ++index) { + ASSERT_EQ(password[index], key[index]); + } + password.assign(password.size(), 0); + dbPassword2.Clear(); + key.assign(key.size(), 0); + SecurityManager::GetInstance().DelDBPassword(STORE_NAME, BASE_DIR); +} + +/** + * @tc.name: DelDBPasswordTest001 + * @tc.desc: delete password + * @tc.type: FUNC + */ +HWTEST_F(SecurityManagerTest, DelDBPasswordTest001, TestSize.Level0) +{ + auto dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, true); + ASSERT_TRUE(dbPassword.IsValid()); + dbPassword.Clear(); + + SecurityManager::GetInstance().DelDBPassword(STORE_NAME, BASE_DIR); + + dbPassword = SecurityManager::GetInstance().GetDBPassword(STORE_NAME, BASE_DIR, false); + ASSERT_FALSE(dbPassword.IsValid()); } /** @@ -72,8 +482,6 @@ HWTEST_F(SecurityManagerTest, KeyFilesMultiLockTest, TestSize.Level1) std::string dbName = "test1"; StoreUtil::InitPath(dbPath); SecurityManager::KeyFiles keyFiles(dbName, dbPath); - auto keyPath = keyFiles.GetKeyFilePath(); - EXPECT_EQ(keyPath, "/data/service/el1/public/database/SecurityManagerTest/key/test1.key"); auto ret = keyFiles.Lock(); EXPECT_EQ(ret, Status::SUCCESS); ret = keyFiles.Lock(); @@ -95,8 +503,6 @@ HWTEST_F(SecurityManagerTest, KeyFilesTest, TestSize.Level1) std::string dbName = "test2"; StoreUtil::InitPath(dbPath); SecurityManager::KeyFiles keyFiles(dbName, dbPath); - auto keyPath = keyFiles.GetKeyFilePath(); - EXPECT_EQ(keyPath, "/data/service/el1/public/database/SecurityManagerTest/key/test2.key"); keyFiles.Lock(); auto blockResult = std::make_shared>(1, false); std::thread thread([dbPath, dbName, blockResult]() { diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_mock_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_mock_test.cpp new file mode 100644 index 00000000..24629bb1 --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_mock_test.cpp @@ -0,0 +1,1262 @@ +/* + * 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 +#include +#include + +#include +#include + +#include "include/accesstoken_kit_mock.h" +#include "include/convertor_mock.h" +#include "include/dev_manager_mock.h" +#include "include/kvdb_notifier_client_mock.h" +#include "include/kvdb_service_client_mock.h" +#include "include/observer_bridge_mock.h" +#include "include/task_executor_mock.h" +#include "kvstore_observer.h" +#include "single_store_impl.h" +#include "store_factory.h" +#include "store_manager.h" + +namespace OHOS::DistributedKv { +using namespace std; +using namespace testing; +using namespace DistributedDB; +using namespace Security::AccessToken; + +static StoreId storeId = { "single_test" }; +static AppId appId = { "rekey" }; + +class SingleStoreImplMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + +public: + using DBStatus = DistributedDB::DBStatus; + using DBStore = DistributedDB::KvStoreNbDelegate; + using Observer = DistributedKv::KvStoreObserver; + static inline shared_ptr devManagerMock = nullptr; + static inline shared_ptr kVDBServiceClientMock = nullptr; + static inline shared_ptr kVDBNotifierClientMock = nullptr; + static inline shared_ptr observerBridgeMock = nullptr; + static inline shared_ptr taskExecutorMock = nullptr; + static inline shared_ptr accessTokenKitMock = nullptr; + static inline shared_ptr convertorMock = nullptr; + std::shared_ptr CreateKVStore(bool autosync = false, bool backup = true); +}; + +void SingleStoreImplMockTest::SetUp() { } + +void SingleStoreImplMockTest::TearDown() { } + +void SingleStoreImplMockTest::SetUpTestCase() +{ + GTEST_LOG_(INFO) << "SetUpTestCase enter"; + std::string baseDir = "/data/service/el1/public/database/SingleStoreImplTest"; + mkdir(baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + devManagerMock = make_shared(); + BDevManager::devManager = devManagerMock; + kVDBServiceClientMock = make_shared(); + BKVDBServiceClient::kVDBServiceClient = kVDBServiceClientMock; + kVDBNotifierClientMock = make_shared(); + BKVDBNotifierClient::kVDBNotifierClient = kVDBNotifierClientMock; + observerBridgeMock = make_shared(); + BObserverBridge::observerBridge = observerBridgeMock; + taskExecutorMock = make_shared(); + BTaskExecutor::taskExecutor = taskExecutorMock; + accessTokenKitMock = make_shared(); + BAccessTokenKit::accessTokenKit = accessTokenKitMock; + convertorMock = make_shared(); + BConvertor::convertor = convertorMock; +} + +void SingleStoreImplMockTest::TearDownTestCase() +{ + GTEST_LOG_(INFO) << "TearDownTestCase enter"; + BDevManager::devManager = nullptr; + devManagerMock = nullptr; + BKVDBServiceClient::kVDBServiceClient = nullptr; + kVDBServiceClientMock = nullptr; + BKVDBNotifierClient::kVDBNotifierClient = nullptr; + kVDBNotifierClientMock = nullptr; + BObserverBridge::observerBridge = nullptr; + observerBridgeMock = nullptr; + BTaskExecutor::taskExecutor = nullptr; + taskExecutorMock = nullptr; + BAccessTokenKit::accessTokenKit = nullptr; + accessTokenKitMock = nullptr; + BConvertor::convertor = nullptr; + convertorMock = nullptr; + std::string baseDir = "/data/service/el1/public/database/SingleStoreImplTest"; + (void)remove("/data/service/el1/public/database/SingleStoreImplTest"); +} + +std::shared_ptr SingleStoreImplMockTest::CreateKVStore(bool autosync, bool backup) +{ + AppId appId = { "SingleStoreImplTest" }; + StoreId storeId = { "DestructorTest" }; + std::shared_ptr kvStore; + Options options; + options.kvStoreType = SINGLE_VERSION; + options.securityLevel = S2; + options.area = EL1; + options.autoSync = autosync; + options.baseDir = "/data/service/el1/public/database/SingleStoreImplTest"; + options.backup = backup; + StoreFactory storeFactory; + auto dbManager = storeFactory.GetDBManager(options.baseDir, appId); + auto dbPassword = SecurityManager::GetInstance().GetDBPassword(storeId.storeId, options.baseDir, options.encrypt); + DBStatus dbStatus = DBStatus::DB_ERROR; + dbManager->GetKvStore(storeId, storeFactory.GetDBOption(options, dbPassword), + [&dbManager, &kvStore, &appId, &dbStatus, &options, &storeFactory](auto status, auto *store) { + dbStatus = status; + if (store == nullptr) { + return; + } + auto release = [dbManager](auto *store) { + dbManager->CloseKvStore(store); + }; + auto dbStore = std::shared_ptr(store, release); + storeFactory.SetDbConfig(dbStore); + const Convertor &convertor = *(storeFactory.convertors_[options.kvStoreType]); + kvStore = std::make_shared(dbStore, appId, options, convertor); + }); + return kvStore; +} + +/** + * @tc.name: IsRemoteChanged + * @tc.desc: is remote changed. + * @tc.type: FUNC + * @tc.require: + * @tc.author: cao zhijun + */ +HWTEST_F(SingleStoreImplMockTest, IsRemoteChanged, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin IsRemoteChanged"; + try { + EXPECT_CALL(*taskExecutorMock, Schedule(_, _, _, _)).Times(1); + std::shared_ptr kvStore; + kvStore = CreateKVStore(); + ASSERT_NE(kvStore, nullptr); + std::shared_ptr client = make_shared(nullptr); + ASSERT_NE(client, nullptr); + EXPECT_CALL(*devManagerMock, ToUUID(_)).WillOnce(Return("")); + bool ret = kvStore->IsRemoteChanged("123456789"); + EXPECT_TRUE(ret); + + EXPECT_CALL(*devManagerMock, ToUUID(_)).WillOnce(Return("123456789")); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + ret = kvStore->IsRemoteChanged("123456789"); + EXPECT_TRUE(ret); + + EXPECT_CALL(*devManagerMock, ToUUID(_)).WillOnce(Return("123456789")); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(client)); + EXPECT_CALL(*kVDBServiceClientMock, GetServiceAgent(_)).WillOnce(Return(nullptr)); + ret = kvStore->IsRemoteChanged("123456789"); + EXPECT_TRUE(ret); + + sptr testAgent = new (std::nothrow) KVDBNotifierClient(); + ASSERT_NE(testAgent, nullptr); + EXPECT_CALL(*devManagerMock, ToUUID(_)).WillOnce(Return("123456789")); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(client)); + EXPECT_CALL(*kVDBServiceClientMock, GetServiceAgent(_)).WillOnce(Return(testAgent)); + EXPECT_CALL(*kVDBNotifierClientMock, IsChanged(_, _)).WillOnce(Return(true)); + ret = kvStore->IsRemoteChanged("123456789"); + EXPECT_TRUE(ret); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by IsRemoteChanged."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end IsRemoteChanged"; +} + +/** + * @tc.name: OnRemoteDied + * @tc.desc: remote died. + * @tc.type: FUNC + * @tc.require: + * @tc.author: cao zhijun + */ +HWTEST_F(SingleStoreImplMockTest, OnRemoteDied, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin OnRemoteDied"; + try { + EXPECT_CALL(*taskExecutorMock, Schedule(_, _, _, _)).Times(1); + EXPECT_CALL(*accessTokenKitMock, GetTokenTypeFlag(_)).WillOnce(Return(TOKEN_INVALID)); + std::shared_ptr kvStore; + kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_FALSE(kvStore->isApplication_); + + kvStore->taskId_ = 1; + kvStore->OnRemoteDied(); + + kvStore->taskId_ = 0; + shared_ptr observer = make_shared(); + shared_ptr observer1 = make_shared(); + Convertor cvt; + Convertor cvt1; + shared_ptr obsBridge = make_shared(appId, storeId, 0, observer, cvt); + shared_ptr obsBridge1 = make_shared(appId, storeId, 0, observer1, cvt1); + + uint32_t firs = 0; + firs |= SUBSCRIBE_TYPE_REMOTE; + pair> one(0, obsBridge); + pair> two(firs, obsBridge1); + + kvStore->observers_.Insert(uintptr_t(observer.get()), one); + kvStore->observers_.Insert(uintptr_t(observer1.get()), two); + EXPECT_CALL(*observerBridgeMock, OnServiceDeath()).Times(1); + EXPECT_CALL(*taskExecutorMock, Schedule(_, _, _, _)).WillOnce(Return(1)); + kvStore->OnRemoteDied(); + kvStore->observers_.Erase(uintptr_t(observer.get())); + kvStore->observers_.Erase(uintptr_t(observer1.get())); + EXPECT_TRUE(kvStore->taskId_ == 1); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by OnRemoteDied."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end OnRemoteDied"; +} + +/** + * @tc.name: Register + * @tc.desc: register. + * @tc.type: FUNC + * @tc.require: + * @tc.author: cao zhijun + */ +HWTEST_F(SingleStoreImplMockTest, Register, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Register"; + try { + EXPECT_CALL(*taskExecutorMock, Schedule(_, _, _, _)).Times(1); + EXPECT_CALL(*accessTokenKitMock, GetTokenTypeFlag(_)).WillOnce(Return(TOKEN_HAP)); + std::shared_ptr kvStore; + kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_TRUE(kvStore->isApplication_); + + shared_ptr observer = make_shared(); + shared_ptr observer1 = make_shared(); + Convertor cvt; + Convertor cvt1; + shared_ptr obsBridge = make_shared(appId, storeId, 0, observer, cvt); + shared_ptr obsBridge1 = make_shared(appId, storeId, 0, observer1, cvt1); + + uint32_t firs = 0; + firs |= SUBSCRIBE_TYPE_CLOUD; + pair> one(0, obsBridge); + pair> two(firs, obsBridge1); + + kvStore->observers_.Insert(uintptr_t(observer.get()), one); + kvStore->observers_.Insert(uintptr_t(observer1.get()), two); + EXPECT_CALL(*observerBridgeMock, RegisterRemoteObserver(_)).WillOnce(Return(ERROR)); + EXPECT_CALL(*taskExecutorMock, Schedule(_, _, _, _)).WillOnce(Return(1)); + kvStore->Register(); + EXPECT_TRUE(kvStore->taskId_ == 1); + + EXPECT_CALL(*observerBridgeMock, RegisterRemoteObserver(_)).WillOnce(Return(SUCCESS)); + kvStore->Register(); + kvStore->observers_.Erase(uintptr_t(observer.get())); + kvStore->observers_.Erase(uintptr_t(observer1.get())); + EXPECT_TRUE(kvStore->taskId_ == 0); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Register."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Register"; +} + +/** +* @tc.name: Put_001 +* @tc.desc: Put. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, Put_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Put_001"; + try { + EXPECT_CALL(*taskExecutorMock, Schedule(_, _, _, _)).Times(1); + EXPECT_CALL(*accessTokenKitMock, GetTokenTypeFlag(_)).Times(AnyNumber()); + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + std::vector vect; + EXPECT_CALL(*convertorMock, ToLocalDBKey(_)).WillOnce(Return(vect)); + size_t maxTestKeyLen = 10; + std::string str(maxTestKeyLen, 'a'); + Blob key(str); + Blob value("test_value"); + Status status = kvStore->Put(key, value); + EXPECT_TRUE(status == INVALID_ARGUMENT); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Put_001."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Put_001"; +} + + +/** +* @tc.name: Put_002 +* @tc.desc: Put. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, Put_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Put_002"; + try { + EXPECT_CALL(*taskExecutorMock, Schedule(_, _, _, _)).Times(AnyNumber()); + EXPECT_CALL(*accessTokenKitMock, GetTokenTypeFlag(_)).Times(AnyNumber()); + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + std::vector vect{3, 8}; + EXPECT_CALL(*convertorMock, ToLocalDBKey(_)).WillOnce(Return(vect)); + size_t overlongTestKeyLen = 4 * 1024 * 1024 + 1; + std::string str(overlongTestKeyLen, 'b'); + Blob key1("key1"); + Blob value1(str); + Status status = kvStore->Put(key1, value1); + EXPECT_TRUE(status == INVALID_ARGUMENT); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Put_002."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Put_002"; +} + +/** +* @tc.name: PutBatch_001 +* @tc.desc: PutBatch. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, PutBatch_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin PutBatch_001"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_ = nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + std::vector in; + for (int i = 0; i < 2; ++i) { + Entry entry; + entry.key = std::to_string(i).append("_k"); + entry.value = std::to_string(i).append("_v"); + in.emplace_back(entry); + } + Status status = kvStore->PutBatch(in); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by PutBatch_001."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end PutBatch_001"; +} + +/** +* @tc.name: PutBatch_002 +* @tc.desc: PutBatch. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, PutBatch_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin PutBatch_002"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + std::vector in; + for (int i = 0; i < 2; ++i) { + Entry entry; + entry.key = std::to_string(i).append("_key"); + entry.value = std::to_string(i).append("_val"); + in.emplace_back(entry); + } + std::vector vect; + EXPECT_CALL(*convertorMock, ToLocalDBKey(_)).WillOnce(Return(vect)); + Status status = kvStore->PutBatch(in); + EXPECT_TRUE(status == INVALID_ARGUMENT); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by PutBatch_002."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end PutBatch_002"; +} + +/** +* @tc.name: PutBatch_003 +* @tc.desc: PutBatch. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, PutBatch_003, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin PutBatch_003"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + std::vector in; + for (int i = 0; i < 2; ++i) { + Entry entry; + entry.key = std::to_string(i).append("_key"); + entry.value = std::to_string(i).append("_val"); + in.emplace_back(entry); + } + std::vector vect; + EXPECT_CALL(*convertorMock, ToLocalDBKey(_)).WillOnce(Return(vect)); + Status status = kvStore->PutBatch(in); + EXPECT_TRUE(status == INVALID_ARGUMENT); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by PutBatch_003."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end PutBatch_003"; +} + +/** +* @tc.name: Delete +* @tc.desc: Delete Key. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, Delete, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Delete"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + Blob key1("key1"); + Status status = kvStore->Delete(key1); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Delete."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Delete"; +} + +/** +* @tc.name: DeleteBatch +* @tc.desc: DeleteBatch Keys. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, DeleteBatch, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin DeleteBatch"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + std::vector keys; + for (int i = 0; i < 2; ++i) { + Key key = std::to_string(i).append("_k"); + keys.emplace_back(key); + } + Status status = kvStore->DeleteBatch(keys); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by DeleteBatch."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end DeleteBatch"; +} + +/** +* @tc.name: StartTransaction +* @tc.desc: Start Transaction. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, StartTransaction, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin StartTransaction"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + Status status = kvStore->StartTransaction(); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by StartTransaction."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end StartTransaction"; +} + +/** +* @tc.name: Commit +* @tc.desc: Commit. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, Commit, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Commit"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + Status status = kvStore->Commit(); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Commit."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Commit"; +} + +/** +* @tc.name: Rollback +* @tc.desc: Rollback kvstore. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, Rollback, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Rollback"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + Status status = kvStore->Rollback(); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Rollback."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Rollback"; +} + +/** +* @tc.name: Get +* @tc.desc: Get. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, Get, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Get"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + size_t testKeyLen = 10; + std::string str(testKeyLen, 'a'); + Blob key(str); + Blob value("test_value"); + Status status = kvStore->Get(key, value); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Get."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Get"; +} + +/** +* @tc.name: GetEntries_001 +* @tc.desc: Get Entries. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, GetEntries_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin GetEntries_001"; + try { + std::vector vct; + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*convertorMock, GetPrefix(An())).WillOnce(Return(vct)); + Blob key("test"); + std::vector vecs; + for (int i = 0; i < 2; ++i) { + Entry entry; + entry.key = std::to_string(i).append("_key"); + entry.value = std::to_string(i).append("_val"); + vecs.emplace_back(entry); + } + Status status = kvStore->GetEntries(key, vecs); + EXPECT_TRUE(status == INVALID_ARGUMENT); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by GetEntries_001."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end GetEntries_001"; +} + +/** +* @tc.name: GetDeviceEntries +* @tc.desc: Get device entries. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, GetDeviceEntries, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin GetDeviceEntries"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + std::vector vcs; + for (int i = 0; i < 2; ++i) { + Entry entry; + entry.key = std::to_string(i).append("_key"); + entry.value = std::to_string(i).append("_val"); + vcs.emplace_back(entry); + } + std::string device = "test device"; + Status status = kvStore->GetDeviceEntries(device, vcs); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by GetDeviceEntries."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end GetDeviceEntries"; +} + +/** +* @tc.name: GetCount +* @tc.desc: Get count. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, GetCount, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin GetCount"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + DataQuery query; + int cnt = 0; + Status status = kvStore->GetCount(query, cnt); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by GetCount."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end GetCount"; +} + +/** +* @tc.name: GetCount +* @tc.desc: Get count. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, GetSecurityLevel, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin GetSecurityLevel"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + SecurityLevel securityLevel = NO_LABEL; + Status status = kvStore->GetSecurityLevel(securityLevel); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by GetSecurityLevel."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end GetSecurityLevel"; +} + +/** +* @tc.name: RemoveDeviceData_001 +* @tc.desc: Remove device data. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, RemoveDeviceData_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin RemoveDeviceData_001"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + kvStore->dbStore_= nullptr; + EXPECT_TRUE(kvStore->dbStore_ == nullptr); + Status status = kvStore->RemoveDeviceData("testdevice"); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by RemoveDeviceData_001."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end RemoveDeviceData_001"; +} + +/** +* @tc.name: RemoveDeviceData_002 +* @tc.desc: Remove device data. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, RemoveDeviceData_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin RemoveDeviceData_002"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + Status status = kvStore->RemoveDeviceData("testdevice"); + EXPECT_TRUE(status == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by RemoveDeviceData_002."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end RemoveDeviceData_002"; +} + +/** +* @tc.name: CloudSync_001 +* @tc.desc: Cloud sync. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, CloudSync_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin CloudSync_001"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + AsyncDetail asyncDetail; + Status status = kvStore->CloudSync(asyncDetail); + EXPECT_TRUE(status == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by CloudSync_001."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end CloudSync_001"; +} + +/** +* @tc.name: CloudSync_002 +* @tc.desc: Cloud sync. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, CloudSync_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin CloudSync_002"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + std::shared_ptr ser = make_shared(nullptr); + ASSERT_NE(ser, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(ser)); + EXPECT_CALL(*kVDBServiceClientMock, GetServiceAgent(_)).WillOnce(Return(nullptr)); + AsyncDetail asyncDetail; + Status status = kvStore->CloudSync(asyncDetail); + EXPECT_TRUE(status == ILLEGAL_STATE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by CloudSync_002."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end CloudSync_002"; +} + +/** +* @tc.name: SetSyncParam +* @tc.desc: Set sync param. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, SetSyncParam, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin SetSyncParam"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + KvSyncParam syncParam{ 500 }; + Status status = kvStore->SetSyncParam(syncParam); + EXPECT_TRUE(status == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by SetSyncParam."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end SetSyncParam"; +} + +/** +* @tc.name: GetSyncParam +* @tc.desc: Get sync param. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, GetSyncParam, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin GetSyncParam"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + KvSyncParam syncParam; + Status status = kvStore->GetSyncParam(syncParam); + EXPECT_TRUE(status == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by GetSyncParam."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end GetSyncParam"; +} + +/** +* @tc.name: SetCapabilityEnabled_001 +* @tc.desc: Set capability enabled. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, SetCapabilityEnabled_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin SetCapabilityEnabled_001"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + Status status = kvStore->SetCapabilityEnabled(false); + EXPECT_TRUE(status == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by SetCapabilityEnabled_001."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end SetCapabilityEnabled_001"; +} + +/** +* @tc.name: SetCapabilityEnabled_002 +* @tc.desc: Set capability enabled. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, SetCapabilityEnabled_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin SetCapabilityEnabled_002"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + std::shared_ptr service = make_shared(nullptr); + ASSERT_NE(service, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(service)); + Status status = kvStore->SetCapabilityEnabled(true); + EXPECT_TRUE(status == ERROR); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by SetCapabilityEnabled_002."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end SetCapabilityEnabled_002"; +} + +/** +* @tc.name: SetCapabilityRange +* @tc.desc: Set capability range. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, SetCapabilityRange, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin SetCapabilityRange"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + std::vector localLabels{"local", "near"}; + std::vector remoteLabels{"remote", "far"}; + Status status = kvStore->SetCapabilityRange(localLabels, remoteLabels); + EXPECT_TRUE(status == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by SetCapabilityRange."; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end SetCapabilityRange"; +} + +/** +* @tc.name: SubscribeWithQuery_001 +* @tc.desc: Subscribe with query. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, SubscribeWithQuery_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin SubscribeWithQuery_001"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + std::vector devices{"dev1", "dev2"}; + DataQuery query; + Status status = kvStore->SubscribeWithQuery(devices, query); + EXPECT_TRUE(status == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by SubscribeWithQuery_001"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end SubscribeWithQuery_001"; +} + +/** +* @tc.name: SubscribeWithQuery_002 +* @tc.desc: Subscribe with query. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, SubscribeWithQuery_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin SubscribeWithQuery_002"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + std::shared_ptr serv = make_shared(nullptr); + ASSERT_NE(serv, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(serv)); + EXPECT_CALL(*kVDBServiceClientMock, GetServiceAgent(_)).WillOnce(Return(nullptr)); + std::vector devices{"dev0", "dev1"}; + DataQuery query; + Status status = kvStore->SubscribeWithQuery(devices, query); + EXPECT_TRUE(status == ILLEGAL_STATE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by SubscribeWithQuery_002"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end SubscribeWithQuery_002"; +} + +/** +* @tc.name: UnsubscribeWithQuery_001 +* @tc.desc: Unsubscribe with query. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, UnsubscribeWithQuery_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin UnsubscribeWithQuery_001"; + try { + std::shared_ptr kvStore = CreateKVStore(false, false); + ASSERT_NE(kvStore, nullptr); + EXPECT_NE(kvStore->dbStore_, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + std::vector devs{"dev0", "dev1"}; + DataQuery quer; + Status status = kvStore->UnsubscribeWithQuery(devs, quer); + EXPECT_TRUE(status == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by UnsubscribeWithQuery_001"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end UnsubscribeWithQuery_001"; +} + +/** +* @tc.name: UnsubscribeWithQuery_002 +* @tc.desc: Unsubscribe with query. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, UnsubscribeWithQuery_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin UnsubscribeWithQuery_002"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + EXPECT_NE(kv->dbStore_, nullptr); + std::shared_ptr serv = make_shared(nullptr); + ASSERT_NE(serv, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(serv)); + EXPECT_CALL(*kVDBServiceClientMock, GetServiceAgent(_)).WillOnce(Return(nullptr)); + std::vector devs{"dev3", "dev4"}; + DataQuery quer; + Status status = kv->UnsubscribeWithQuery(devs, quer); + EXPECT_TRUE(status == ILLEGAL_STATE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by UnsubscribeWithQuery_002"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end UnsubscribeWithQuery_002"; +} + +/** +* @tc.name: Restore_001 +* @tc.desc: restore kv. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, Restore_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Restore_001"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + std::string baseDirect = "/data/service/el1/public/database/SingleStoreImplTest"; + std::string file = "test.txt"; + kv->isApplication_ = false; + Status status = kv->Restore(file, baseDirect); + EXPECT_TRUE(status != SUCCESS); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Restore_001"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Restore_001"; +} + +/** +* @tc.name: Restore_002 +* @tc.desc: restore kv. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, Restore_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin Restore_002"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + std::shared_ptr serv = make_shared(nullptr); + ASSERT_NE(serv, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(serv)); + std::string baseDirect = "/data/service/el1/public/database/SingleStoreImplTest"; + std::string file = "test1.txt"; + kv->isApplication_ = true; + kv->apiVersion_ = 15; // version + Status status = kv->Restore(file, baseDirect); + EXPECT_TRUE(status != SUCCESS); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by Restore_002"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end Restore_002"; +} + +/** +* @tc.name: GetResultSet +* @tc.desc: Get result Set. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, GetResultSet, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin GetResultSet"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + kv->dbStore_= nullptr; + EXPECT_TRUE(kv->dbStore_ == nullptr); + SingleStoreImpl::DBQuery dbQuer; + std::shared_ptr output; + Status status = kv->GetResultSet(dbQuer, output); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by GetResultSet"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end GetResultSet"; +} + +/** +* @tc.name: GetEntries +* @tc.desc: Get entries. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, GetEntries, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin GetEntries"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + kv->dbStore_= nullptr; + EXPECT_TRUE(kv->dbStore_ == nullptr); + std::vector vects; + SingleStoreImpl::DBQuery dbQuer; + Status status = kv->GetEntries(dbQuer, vects); + EXPECT_TRUE(status == ALREADY_CLOSED); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by GetEntries"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end GetEntries"; +} + +/** +* @tc.name: DoSync_001 +* @tc.desc: do sync. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, DoSync_001, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin DoSync_001"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + kv->isClientSync_ = false; + ASSERT_FALSE(kv->isClientSync_); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + SingleStoreImpl::SyncInfo syInfo; + std::shared_ptr obser; + auto res = kv->DoSync(syInfo, obser); + EXPECT_TRUE(res == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by DoSync_001"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end DoSync_001"; +} + +/** +* @tc.name: DoSync_002 +* @tc.desc: do sync. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, DoSync_002, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin DoSync_002"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + kv->isClientSync_ = false; + std::shared_ptr servic = make_shared(nullptr); + ASSERT_NE(servic, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(servic)); + EXPECT_CALL(*kVDBServiceClientMock, GetServiceAgent(_)).WillOnce(Return(nullptr)); + SingleStoreImpl::SyncInfo syInfo; + std::shared_ptr observer; + auto res = kv->DoSync(syInfo, observer); + EXPECT_TRUE(res == ILLEGAL_STATE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by DoSync_002"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end DoSync_002"; +} + +/** +* @tc.name: SetConfig +* @tc.desc: set config. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, SetConfig, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin SetConfig"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + EXPECT_CALL(*kVDBServiceClientMock, GetInstance()).WillOnce(Return(nullptr)); + StoreConfig storeConfig; + auto res = kv->SetConfig(storeConfig); + EXPECT_TRUE(res == SERVER_UNAVAILABLE); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by SetConfig"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end SetConfig"; +} + +/** +* @tc.name: DoNotifyChange +* @tc.desc: Do notify change. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, DoNotifyChange, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin DoNotifyChange"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + kv->cloudAutoSync_ = false; + kv->DoNotifyChange(); + EXPECT_TRUE(!kv->cloudAutoSync_); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by DoNotifyChange"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end DoNotifyChange"; +} + +/** +* @tc.name: IsRebuild +* @tc.desc: is rebuild. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(SingleStoreImplMockTest, IsRebuild, testing::ext::TestSize.Level1) +{ + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-begin IsRebuild"; + try { + std::shared_ptr kv = CreateKVStore(false, false); + ASSERT_NE(kv, nullptr); + kv->dbStore_= nullptr; + EXPECT_TRUE(kv->dbStore_ == nullptr); + auto res = kv->IsRebuild(); + EXPECT_FALSE(res); + } catch (...) { + EXPECT_TRUE(false); + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-an exception occurred by IsRebuild"; + } + GTEST_LOG_(INFO) << "SingleStoreImplMockTest-end IsRebuild"; +} +} // namespace OHOS::DistributedKv \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_test.cpp index 42188eb7..388652ca 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_test.cpp @@ -16,6 +16,8 @@ #include #include +#include "access_token.h" +#include "accesstoken_kit.h" #include "block_data.h" #include "dev_manager.h" #include "device_manager.h" @@ -23,14 +25,17 @@ #include "dm_device_info.h" #include "file_ex.h" #include "kv_store_nb_delegate.h" +#include "nativetoken_kit.h" #include "single_store_impl.h" #include "store_factory.h" #include "store_manager.h" #include "sys/stat.h" +#include "token_setproc.h" #include "types.h" using namespace testing::ext; using namespace OHOS::DistributedKv; +using namespace OHOS::Security::AccessToken; using DBStatus = DistributedDB::DBStatus; using DBStore = DistributedDB::KvStoreNbDelegate; using SyncCallback = KvStoreSyncCallback; @@ -73,6 +78,7 @@ public: void SetUp(); void TearDown(); + void SetNativeTokenId(); std::shared_ptr CreateKVStore(std::string storeIdTest, KvStoreType type, bool encrypt, bool backup); std::shared_ptr CreateKVStore(bool autosync = false); std::shared_ptr kvStore_; @@ -165,12 +171,32 @@ std::shared_ptr SingleStoreImplTest::CreateKVStore(bool autosyn return kvStore; } +void SingleStoreImplTest::SetNativeTokenId() +{ + std::string dumpInfo; + AtmToolsParamInfo info; + info.processName = "distributeddata"; + AccessTokenKit::DumpTokenInfo(info, dumpInfo); + size_t pos = dumpInfo.find("\"tokenID\": "); + if (pos == std::string::npos) { + return; + } + pos += std::string("\"tokenID\": ").length(); + std::string numStr; + while (pos < dumpInfo.length() && std::isdigit(dumpInfo[pos])) { + numStr += dumpInfo[pos]; + ++pos; + } + std::istringstream iss(numStr); + AccessTokenID tokenID; + iss >> tokenID; + SetSelfTokenID(tokenID); +} + /** * @tc.name: GetStoreId * @tc.desc: get the store id of the kv store * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, GetStoreId, TestSize.Level0) { @@ -195,8 +221,6 @@ HWTEST_F(SingleStoreImplTest, GetSubUser, TestSize.Level0) * @tc.name: Put * @tc.desc: put key-value data to the kv store * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, Put, TestSize.Level0) { @@ -215,8 +239,6 @@ HWTEST_F(SingleStoreImplTest, Put, TestSize.Level0) * @tc.name: Put_Invalid_Key * @tc.desc: put invalid key-value data to the device kv store and single kv store * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: wu fengshan */ HWTEST_F(SingleStoreImplTest, Put_Invalid_Key, TestSize.Level0) { @@ -260,8 +282,6 @@ HWTEST_F(SingleStoreImplTest, Put_Invalid_Key, TestSize.Level0) * @tc.name: PutBatch * @tc.desc: put some key-value data to the kv store * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, PutBatch, TestSize.Level0) { @@ -320,8 +340,6 @@ HWTEST_F(SingleStoreImplTest, PutBatch001, TestSize.Level1) * @tc.name: Delete * @tc.desc: delete the value of the key * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, Delete, TestSize.Level0) { @@ -344,8 +362,6 @@ HWTEST_F(SingleStoreImplTest, Delete, TestSize.Level0) * @tc.name: DeleteBatch * @tc.desc: delete the values of the keys * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, DeleteBatch, TestSize.Level0) { @@ -378,8 +394,6 @@ HWTEST_F(SingleStoreImplTest, DeleteBatch, TestSize.Level0) * @tc.name: Transaction * @tc.desc: do transaction * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, Transaction, TestSize.Level0) { @@ -399,8 +413,6 @@ HWTEST_F(SingleStoreImplTest, Transaction, TestSize.Level0) * @tc.name: SubscribeKvStore * @tc.desc: subscribe local * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, SubscribeKvStore, TestSize.Level0) { @@ -448,8 +460,6 @@ HWTEST_F(SingleStoreImplTest, SubscribeKvStore, TestSize.Level0) * @tc.name: SubscribeKvStore002 * @tc.desc: subscribe local * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Hollokin */ HWTEST_F(SingleStoreImplTest, SubscribeKvStore002, TestSize.Level0) { @@ -525,8 +535,6 @@ HWTEST_F(SingleStoreImplTest, SubscribeKvStore003, TestSize.Level0) * @tc.name: UnsubscribeKvStore * @tc.desc: unsubscribe * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, UnsubscribeKvStore, TestSize.Level0) { @@ -556,8 +564,6 @@ HWTEST_F(SingleStoreImplTest, UnsubscribeKvStore, TestSize.Level0) * @tc.name: GetEntries * @tc.desc: get entries by prefix * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, GetEntries_Prefix, TestSize.Level0) { @@ -587,8 +593,6 @@ HWTEST_F(SingleStoreImplTest, GetEntries_Prefix, TestSize.Level0) * @tc.name: GetEntries_Less_Prefix * @tc.desc: get entries by prefix and the key size less than sizeof(uint32_t) * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: wu fengshan */ HWTEST_F(SingleStoreImplTest, GetEntries_Less_Prefix, TestSize.Level0) { @@ -631,8 +635,6 @@ HWTEST_F(SingleStoreImplTest, GetEntries_Less_Prefix, TestSize.Level0) * @tc.name: GetEntries_Greater_Prefix * @tc.desc: get entries by prefix and the key size is greater than sizeof(uint32_t) * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: wu fengshan */ HWTEST_F(SingleStoreImplTest, GetEntries_Greater_Prefix, TestSize.Level0) { @@ -678,8 +680,6 @@ HWTEST_F(SingleStoreImplTest, GetEntries_Greater_Prefix, TestSize.Level0) * @tc.name: GetEntries * @tc.desc: get entries by query * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, GetEntries_DataQuery, TestSize.Level0) { @@ -712,8 +712,6 @@ HWTEST_F(SingleStoreImplTest, GetEntries_DataQuery, TestSize.Level0) * @tc.name: GetResultSet * @tc.desc: get result set by prefix * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, GetResultSet_Prefix, TestSize.Level0) { @@ -751,8 +749,6 @@ HWTEST_F(SingleStoreImplTest, GetResultSet_Prefix, TestSize.Level0) * @tc.name: GetResultSet * @tc.desc: get result set by query * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, GetResultSet_Query, TestSize.Level0) { @@ -792,8 +788,6 @@ HWTEST_F(SingleStoreImplTest, GetResultSet_Query, TestSize.Level0) * @tc.name: CloseResultSet * @tc.desc: close the result set * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, CloseResultSet, TestSize.Level0) { @@ -857,8 +851,6 @@ HWTEST_F(SingleStoreImplTest, CloseResultSet001, TestSize.Level0) * @tc.name: ResultSetMaxSizeTest * @tc.desc: test if kv supports 8 resultSets at the same time * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, ResultSetMaxSizeTest_Query, TestSize.Level0) { @@ -913,8 +905,6 @@ HWTEST_F(SingleStoreImplTest, ResultSetMaxSizeTest_Query, TestSize.Level0) * @tc.name: ResultSetMaxSizeTest * @tc.desc: test if kv supports 8 resultSets at the same time * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, ResultSetMaxSizeTest_Prefix, TestSize.Level0) { @@ -967,8 +957,6 @@ HWTEST_F(SingleStoreImplTest, ResultSetMaxSizeTest_Prefix, TestSize.Level0) * @tc.name: MaxLogSizeTest * @tc.desc: test if the default max limit of wal is 200MB * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, MaxLogSizeTest, TestSize.Level0) { @@ -1025,8 +1013,6 @@ HWTEST_F(SingleStoreImplTest, MaxLogSizeTest, TestSize.Level0) * @tc.name: MaxTest002 * @tc.desc: test if the default max limit of wal is 200MB * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, MaxLogSizeTest002, TestSize.Level0) { @@ -1105,8 +1091,6 @@ HWTEST_F(SingleStoreImplTest, MaxLogSizeTest002, TestSize.Level0) * @tc.name: Move_Offset * @tc.desc: Move the ResultSet Relative Distance * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: wu fengshan */ HWTEST_F(SingleStoreImplTest, Move_Offset, TestSize.Level0) { @@ -1162,8 +1146,6 @@ HWTEST_F(SingleStoreImplTest, Move_Offset, TestSize.Level0) * @tc.name: GetCount * @tc.desc: close the result set * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, GetCount, TestSize.Level0) { @@ -1218,8 +1200,6 @@ void ChangeOwnerToService(std::string baseDir, std::string hashId) * @tc.name: RemoveDeviceData * @tc.desc: remove local device data * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, RemoveDeviceData, TestSize.Level0) { @@ -1259,8 +1239,6 @@ HWTEST_F(SingleStoreImplTest, RemoveDeviceData, TestSize.Level0) * @tc.name: GetSecurityLevel * @tc.desc: get security level * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, GetSecurityLevel, TestSize.Level0) { @@ -1275,8 +1253,6 @@ HWTEST_F(SingleStoreImplTest, GetSecurityLevel, TestSize.Level0) * @tc.name: RegisterSyncCallback * @tc.desc: register the data sync callback * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, RegisterSyncCallback, TestSize.Level0) { @@ -1295,8 +1271,6 @@ HWTEST_F(SingleStoreImplTest, RegisterSyncCallback, TestSize.Level0) * @tc.name: UnRegisterSyncCallback * @tc.desc: unregister the data sync callback * @tc.type: FUNC - * @tc.require: I4XVQQ - * @tc.author: Sven Wang */ HWTEST_F(SingleStoreImplTest, UnRegisterSyncCallback, TestSize.Level0) { @@ -1317,8 +1291,6 @@ HWTEST_F(SingleStoreImplTest, UnRegisterSyncCallback, TestSize.Level0) * @tc.name: disableBackup * @tc.desc: Disable backup * @tc.type: FUNC - * @tc.require: - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, disableBackup, TestSize.Level0) { @@ -1338,8 +1310,6 @@ HWTEST_F(SingleStoreImplTest, disableBackup, TestSize.Level0) * @tc.name: PutOverMaxValue * @tc.desc: put key-value data to the kv store and the value size over the limits * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, PutOverMaxValue, TestSize.Level0) { @@ -1357,8 +1327,6 @@ HWTEST_F(SingleStoreImplTest, PutOverMaxValue, TestSize.Level0) * @tc.name: DeleteOverMaxKey * @tc.desc: delete the values of the keys and the key size over the limits * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, DeleteOverMaxKey, TestSize.Level0) { @@ -1382,8 +1350,6 @@ HWTEST_F(SingleStoreImplTest, DeleteOverMaxKey, TestSize.Level0) * @tc.name: GetEntriesOverMaxKey * @tc.desc: get entries the by prefix and the prefix size over the limits * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, GetEntriesOverMaxPrefix, TestSize.Level0) { @@ -1403,8 +1369,6 @@ HWTEST_F(SingleStoreImplTest, GetEntriesOverMaxPrefix, TestSize.Level0) * @tc.name: GetResultSetOverMaxPrefix * @tc.desc: get result set the by prefix and the prefix size over the limits * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, GetResultSetOverMaxPrefix, TestSize.Level0) { @@ -1424,8 +1388,6 @@ HWTEST_F(SingleStoreImplTest, GetResultSetOverMaxPrefix, TestSize.Level0) * @tc.name: RemoveNullDeviceData * @tc.desc: remove local device data and the device is null * @tc.type: FUNC - * @tc.require: I605H3 - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, RemoveNullDeviceData, TestSize.Level0) { @@ -1460,8 +1422,6 @@ HWTEST_F(SingleStoreImplTest, RemoveNullDeviceData, TestSize.Level0) * @tc.name: CloseKVStoreWithInvalidAppId * @tc.desc: close the kv store with invalid appid * @tc.type: FUNC - * @tc.require: - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, CloseKVStoreWithInvalidAppId, TestSize.Level0) { @@ -1475,8 +1435,6 @@ HWTEST_F(SingleStoreImplTest, CloseKVStoreWithInvalidAppId, TestSize.Level0) * @tc.name: CloseKVStoreWithInvalidStoreId * @tc.desc: close the kv store with invalid store id * @tc.type: FUNC - * @tc.require: - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, CloseKVStoreWithInvalidStoreId, TestSize.Level0) { @@ -1490,8 +1448,6 @@ HWTEST_F(SingleStoreImplTest, CloseKVStoreWithInvalidStoreId, TestSize.Level0) * @tc.name: CloseAllKVStore * @tc.desc: close all kv store * @tc.type: FUNC - * @tc.require: - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, CloseAllKVStore, TestSize.Level0) { @@ -1521,8 +1477,6 @@ HWTEST_F(SingleStoreImplTest, CloseAllKVStore, TestSize.Level0) * @tc.name: CloseAllKVStoreWithInvalidAppId * @tc.desc: close the kv store with invalid appid * @tc.type: FUNC - * @tc.require: - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, CloseAllKVStoreWithInvalidAppId, TestSize.Level0) { @@ -1535,8 +1489,6 @@ HWTEST_F(SingleStoreImplTest, CloseAllKVStoreWithInvalidAppId, TestSize.Level0) * @tc.name: DeleteWithInvalidAppId * @tc.desc: delete the kv store with invalid appid * @tc.type: FUNC - * @tc.require: - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, DeleteWithInvalidAppId, TestSize.Level0) { @@ -1551,8 +1503,6 @@ HWTEST_F(SingleStoreImplTest, DeleteWithInvalidAppId, TestSize.Level0) * @tc.name: DeleteWithInvalidStoreId * @tc.desc: delete the kv store with invalid storeid * @tc.type: FUNC - * @tc.require: - * @tc.author: Yang Qing */ HWTEST_F(SingleStoreImplTest, DeleteWithInvalidStoreId, TestSize.Level0) { @@ -1567,8 +1517,6 @@ HWTEST_F(SingleStoreImplTest, DeleteWithInvalidStoreId, TestSize.Level0) * @tc.name: GetKVStoreWithPersistentFalse * @tc.desc: delete the kv store with the persistent is false * @tc.type: FUNC - * @tc.require: - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, GetKVStoreWithPersistentFalse, TestSize.Level0) { @@ -1591,8 +1539,6 @@ HWTEST_F(SingleStoreImplTest, GetKVStoreWithPersistentFalse, TestSize.Level0) * @tc.name: GetKVStoreWithInvalidType * @tc.desc: delete the kv store with the KvStoreType is InvalidType * @tc.type: FUNC - * @tc.require: - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, GetKVStoreWithInvalidType, TestSize.Level0) { @@ -1614,8 +1560,6 @@ HWTEST_F(SingleStoreImplTest, GetKVStoreWithInvalidType, TestSize.Level0) * @tc.name: GetKVStoreWithCreateIfMissingFalse * @tc.desc: delete the kv store with the createIfMissing is false * @tc.type: FUNC - * @tc.require: - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, GetKVStoreWithCreateIfMissingFalse, TestSize.Level0) { @@ -1638,8 +1582,6 @@ HWTEST_F(SingleStoreImplTest, GetKVStoreWithCreateIfMissingFalse, TestSize.Level * @tc.name: GetKVStoreWithAutoSync * @tc.desc: delete the kv store with the autoSync is false * @tc.type: FUNC - * @tc.require: - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, GetKVStoreWithAutoSync, TestSize.Level0) { @@ -1664,8 +1606,6 @@ HWTEST_F(SingleStoreImplTest, GetKVStoreWithAutoSync, TestSize.Level0) * @tc.name: GetKVStoreWithAreaEL2 * @tc.desc: delete the kv store with the area is EL2 * @tc.type: FUNC - * @tc.require: - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, GetKVStoreWithAreaEL2, TestSize.Level0) { @@ -1691,8 +1631,6 @@ HWTEST_F(SingleStoreImplTest, GetKVStoreWithAreaEL2, TestSize.Level0) * @tc.name: GetKVStoreWithRebuildTrue * @tc.desc: delete the kv store with the rebuild is true * @tc.type: FUNC - * @tc.require: - * @tc.author: Wang Kai */ HWTEST_F(SingleStoreImplTest, GetKVStoreWithRebuildTrue, TestSize.Level0) { @@ -1717,8 +1655,6 @@ HWTEST_F(SingleStoreImplTest, GetKVStoreWithRebuildTrue, TestSize.Level0) * @tc.name: GetStaticStore * @tc.desc: get static store * @tc.type: FUNC - * @tc.require: - * @tc.author: zuojiangijang */ HWTEST_F(SingleStoreImplTest, GetStaticStore, TestSize.Level0) { @@ -1744,8 +1680,6 @@ HWTEST_F(SingleStoreImplTest, GetStaticStore, TestSize.Level0) * @tc.name: StaticStoreAsyncGet * @tc.desc: static store async get * @tc.type: FUNC - * @tc.require: - * @tc.author: zuojiangijang */ HWTEST_F(SingleStoreImplTest, StaticStoreAsyncGet, TestSize.Level0) { @@ -1779,8 +1713,6 @@ HWTEST_F(SingleStoreImplTest, StaticStoreAsyncGet, TestSize.Level0) * @tc.name: StaticStoreAsyncGetEntries * @tc.desc: static store async get entries * @tc.type: FUNC - * @tc.require: - * @tc.author: zuojiangijang */ HWTEST_F(SingleStoreImplTest, StaticStoreAsyncGetEntries, TestSize.Level0) { @@ -1815,8 +1747,6 @@ HWTEST_F(SingleStoreImplTest, StaticStoreAsyncGetEntries, TestSize.Level0) * @tc.name: DynamicStoreAsyncGet * @tc.desc: dynamic store async get * @tc.type: FUNC - * @tc.require: - * @tc.author: zuojiangijang */ HWTEST_F(SingleStoreImplTest, DynamicStoreAsyncGet, TestSize.Level0) { @@ -1852,8 +1782,6 @@ HWTEST_F(SingleStoreImplTest, DynamicStoreAsyncGet, TestSize.Level0) * @tc.name: DynamicStoreAsyncGetEntries * @tc.desc: dynamic store async get entries * @tc.type: FUNC - * @tc.require: - * @tc.author: zuojiangijang */ HWTEST_F(SingleStoreImplTest, DynamicStoreAsyncGetEntries, TestSize.Level0) { @@ -1898,8 +1826,6 @@ HWTEST_F(SingleStoreImplTest, DynamicStoreAsyncGetEntries, TestSize.Level0) * @tc.name: SetConfig * @tc.desc: SetConfig * @tc.type: FUNC - * @tc.require: - * @tc.author: ht */ HWTEST_F(SingleStoreImplTest, SetConfig, TestSize.Level0) { @@ -1930,7 +1856,8 @@ HWTEST_F(SingleStoreImplTest, SetConfig, TestSize.Level0) */ HWTEST_F(SingleStoreImplTest, GetDeviceEntries001, TestSize.Level1) { - std::string PKG_NAME_EX = "_distributed_data"; + SetNativeTokenId(); + std::string pkgNameEx = "_distributed_data"; std::shared_ptr kvStore; kvStore = CreateKVStore(); ASSERT_NE(kvStore, nullptr); @@ -1942,8 +1869,8 @@ HWTEST_F(SingleStoreImplTest, GetDeviceEntries001, TestSize.Level1) status = kvStore->GetDeviceEntries(device, output); ASSERT_EQ(status, SUCCESS); DevInfo devinfo; - std::string PKG_NAME = std::to_string(getpid()) + PKG_NAME_EX; - DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(PKG_NAME, devinfo); + std::string pkgName = std::to_string(getpid()) + pkgNameEx; + DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(pkgName, devinfo); ASSERT_NE(std::string(devinfo.deviceId), ""); status = kvStore->GetDeviceEntries(std::string(devinfo.deviceId), output); ASSERT_EQ(status, SUCCESS); @@ -2002,7 +1929,7 @@ HWTEST_F(SingleStoreImplTest, DoClientSync001, TestSize.Level1) std::shared_ptr observer; observer = nullptr; auto status = kvStore->DoClientSync(syncInfo, observer); - ASSERT_EQ(status, DB_ERROR); + ASSERT_EQ(status, ERROR); } /** @@ -2060,19 +1987,4 @@ HWTEST_F(SingleStoreImplTest, IsRemoteChanged, TestSize.Level0) bool ret = kvStore->IsRemoteChanged(""); ASSERT_TRUE(ret); } - -/** - * @tc.name: ReportDBFaultEvent - * @tc.desc: report DB corrupted fault - * @tc.type: FUNC - */ -HWTEST_F(SingleStoreImplTest, ReportDBFaultEvent, TestSize.Level0) -{ - std::shared_ptr kvStore; - kvStore = CreateKVStore(); - ASSERT_NE(kvStore, nullptr); - Status status = DATA_CORRUPTED; - kvStore->ReportDBFaultEvent(status, std::string(__FUNCTION__)); - EXPECT_TRUE(status == DATA_CORRUPTED); -} } // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_perf_pc_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_perf_pc_test.cpp index 1cae2361..09cee738 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_perf_pc_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_perf_pc_test.cpp @@ -163,7 +163,7 @@ static double TimeDiff(const struct timespec *beg, const struct timespec *end) * @tc.require: * @tc.author: Gang Wang */ -HWTEST_F(SingleStorePerfPcTest, HashIndexKVStoreTest001, TestSize.Level0) +HWTEST_F(SingleStorePerfPcTest, HashIndexKVStoreTest001, TestSize.Level1) { printf("HashIndexKVStoreTest001 BEGIN\n"); std::string strKey(8, 'k'); @@ -217,7 +217,7 @@ HWTEST_F(SingleStorePerfPcTest, HashIndexKVStoreTest001, TestSize.Level0) * @tc.require: * @tc.author: Gang Wang */ -HWTEST_F(SingleStorePerfPcTest, HashIndexKVStoreTest002, TestSize.Level0) +HWTEST_F(SingleStorePerfPcTest, HashIndexKVStoreTest002, TestSize.Level1) { printf("HashIndexKVStoreTest002 BEGIN\n"); std::string strKey(8, 'k'); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_perf_phone_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_perf_phone_test.cpp index 2ac13432..ede8256a 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_perf_phone_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_perf_phone_test.cpp @@ -41,6 +41,17 @@ std::shared_ptr store3; class SingleStorePerfPhoneTest : public testing::Test { public: + struct DataConfig { + int batch; + int count; + int size; + int ratio; + }; + + struct PresetResult { + std::string firstKey; + std::string lastKey; + }; std::shared_ptr CreateKVStore(std::string storeIdTest, KvStoreType type, bool encrypt, bool backup); static void SetUpTestCase(); static void TearDownTestCase(); @@ -76,7 +87,7 @@ string GetDate(char *cType, int iDay) char cTimePARTNUMBER[256] = ""; time_t rawtime; struct tm timeinfo{}; - rawtime = time(NULL) + iDay * 24 * 3600; // 24 hours a day, 3600 seconds per hour + rawtime = time(nullptr) + iDay * 24 * 3600; // 24 hours a day, 3600 seconds per hour localtime_r(&rawtime, &timeinfo); char buffer1[256]; size_t n = strftime(cTimePARTNUMBER, sizeof(buffer1), cType, &timeinfo); //20180623 @@ -100,39 +111,40 @@ string GetDate(char *cType, int iDay) * @details This function is responsible for writing a preset set of data to a specified * single-key value store based on a given batch, quantity, size, and ratio. */ -void PresetData(std::shared_ptr &store, int batch, int count, int size, int ratio, - std::string &firstKey, std::string &lastKey) +void PresetData(std::shared_ptr &store, + SingleStorePerfPhoneTest::DataConfig &config, SingleStorePerfPhoneTest::PresetResult &result) { std::ostringstream s; s << std::setw(16) << std::setfill('0') << 0; // 16 bytes string strDate; - string ss = to_string(size) + "K"; // The batches are iterated backward to generate data for different dates - for (int i = batch; i >= 1; i--) { - strDate = GetDate((char*)"%Y%m%d", -i); - for (int index = 1; index <= count; index++) { + // The batches are iterated backward to generate data for different dates + string ss = to_string(config.size) + "K"; + for (int i = config.batch; i >= 1; i--) { + strDate = GetDate(const_cast("%Y%m%d"), -i); + for (int index = 1; index <= config.count; index++) { // Produces a unique key string containing date, size, and index information string tmp = s.str() + "_" + ss + "_" + strDate + string(3 - to_string(index).length(), '0') + to_string(index); string val; // Generate random value string based on ratio If the ratio is 0, an empty string is generated - if (ratio != 0) { - val = GenerateRandomString((long)(size * 1024) / ratio); // 1024 bytes per 1K + if (config.ratio != 0) { + val = GenerateRandomString(static_cast(config.size * 1024) / config.ratio); // 1024 bytes per 1K } else { val = GenerateRandomString(0); } const DistributedDB::Key key = GenerateBytes(tmp); const DistributedDB::Value value = GenerateBytes(val); ASSERT_EQ(store->Put(key, value), SUCCESS); - if (i == batch && index == 1) { + if (i == config.batch && index == 1) { // Convert the contents of the key to std::string and assign it to the firstKey - firstKey = std::string(key.begin(), key.end()); + result.firstKey = std::string(key.begin(), key.end()); } - if (i == 1 && index == count) { - lastKey = std::string(key.begin(), key.end()); + if (i == 1 && index == config.count) { + result.lastKey = std::string(key.begin(), key.end()); } } } - printf("put success! \n"); + cout << "put success!" << endl; } /** @@ -146,8 +158,8 @@ void PresetData(std::shared_ptr &store, int batch, int count, int * @details This function is used to calculate the duration for obtaining data on a screen. * Data is obtained through multiple cycles and the average time is calculated. */ -void CalcRangeResultSetDuration(std::shared_ptr &store, int batch, int size, int count, - std::string firstKey, std::string lastKey) +void CalcRangeResultSetDuration(std::shared_ptr &store, + SingleStorePerfPhoneTest::DataConfig &config, SingleStorePerfPhoneTest::PresetResult &result) { // batch = totolCnt / (448/ 112) size(4 8) count (448 112) double dur = 0.0; @@ -158,22 +170,22 @@ void CalcRangeResultSetDuration(std::shared_ptr &store, int batch for (int n = 0; n < 100; ++n) { // 100 times DataQuery query; // The sequential query is carried out according to the actual business scenario - query.Between("", lastKey); + query.Between("", result.lastKey); std::shared_ptr readResultSet; ASSERT_EQ(store->GetResultSet(query, readResultSet), SUCCESS); ASSERT_TRUE(readResultSet != nullptr); - for (int ind = batch; ind >= 1; ind--) { + for (int ind = config.batch; ind >= 1; ind--) { struct timeval startTime{}; struct timeval endTime{}; (void) gettimeofday(&startTime, nullptr); - for (int i = 0; i < count; ++i) { // Loop through a screen of data + for (int i = 0; i < config.count; ++i) { // Loop through a screen of data readResultSet->MoveToNext(); // Move the read position to the next row. Entry entry; // Data is organized by entry definition. readResultSet->GetEntry(entry); } (void) gettimeofday(&endTime, nullptr); - double startUsec = (double) (startTime.tv_sec * 1000 * 1000) + (double) startTime.tv_usec; - double endUsec = (double) (endTime.tv_sec * 1000 * 1000) + (double) endTime.tv_usec; + double startUsec = static_cast((startTime.tv_sec * 1000 * 1000) + startTime.tv_usec); + double endUsec = static_cast((endTime.tv_sec * 1000 * 1000) + endTime.tv_usec); dur = endUsec - startUsec; totalTime += dur; avrTime = (dur / 1000); // 1000 is to convert ms @@ -184,9 +196,9 @@ void CalcRangeResultSetDuration(std::shared_ptr &store, int batch EXPECT_EQ(store->CloseResultSet(readResultSet), SUCCESS); readResultSet = nullptr; } - if (batch != 0) { + if (config.batch != 0) { // 100 is for unit conversion - avrTime = (((totalTime / batch) / 100) / 1000); // 1000 is to convert ms + avrTime = (((totalTime / config.batch) / 100) / 1000); // 1000 is to convert ms cout << "Scan Range ResultSet avg cost = " << avrTime << " ms." << endl; cout << "failCount: " << failCount << endl; EXPECT_LT(avrTime, 3.0); // 3.0 ms is upper bound on performance @@ -281,25 +293,31 @@ std::shared_ptr SingleStorePerfPhoneTest::CreateKVStore(std::stri * @tc.require: * @tc.author: Gang Wang */ -HWTEST_F(SingleStorePerfPhoneTest, Gallery1WThumbnailsKVStoreBetweenTest, TestSize.Level0) +HWTEST_F(SingleStorePerfPhoneTest, Gallery1WThumbnailsKVStoreBetweenTest, TestSize.Level1) { - int monthlyBatch = (int) (10000 / 112); - int annuallyBatch = (int) (10000 / 448); - int ratio = 1; - - printf("monthly start \n"); - std::string firstKey1; - std::string lastKey1; - PresetData(store1, monthlyBatch, 112, 8, ratio, firstKey1, lastKey1); - cout << "first key: " << firstKey1 << ", last key: " << lastKey1 << endl; - CalcRangeResultSetDuration(store1, monthlyBatch, 8, 112, firstKey1, lastKey1); + cout << "monthly start" << endl; + SingleStorePerfPhoneTest::DataConfig monthlyConfig = { + .batch = static_cast(10000 / 112), + .count = 112, + .size = 8, + .ratio = 1 + }; + SingleStorePerfPhoneTest::PresetResult result1; + PresetData(store1, monthlyConfig, result1); + cout << "first key: " << result1.firstKey << ", last key: " << result1.lastKey << endl; + CalcRangeResultSetDuration(store1, monthlyConfig, result1); - printf("annually start \n"); - std::string firstKey2; - std::string lastKey2; - PresetData(store2, annuallyBatch, 448, 4, ratio, firstKey2, lastKey2); - cout << "first key: " << firstKey2 << ", last key: " << lastKey2 << endl; - CalcRangeResultSetDuration(store2, annuallyBatch, 4, 448, firstKey2, lastKey2); + cout << "annually start" << endl; + SingleStorePerfPhoneTest::DataConfig annuallyConfig = { + .batch = static_cast(10000 / 448), + .count = 448, + .size = 4, + .ratio = 1 + }; + SingleStorePerfPhoneTest::PresetResult result2; + PresetData(store2, annuallyConfig, result2); + cout << "first key: " << result2.firstKey << ", last key: " << result2.lastKey << endl; + CalcRangeResultSetDuration(store2, annuallyConfig, result2); } /** @@ -310,24 +328,30 @@ HWTEST_F(SingleStorePerfPhoneTest, Gallery1WThumbnailsKVStoreBetweenTest, TestSi * @tc.require: * @tc.author: Gang Wang */ -HWTEST_F(SingleStorePerfPhoneTest, Gallery5WThumbnailsKVStoreBetweenTest, TestSize.Level0) +HWTEST_F(SingleStorePerfPhoneTest, Gallery5WThumbnailsKVStoreBetweenTest, TestSize.Level1) { - int monthlyBatch = (int) (50000 / 112); - int annuallyBatch = (int) (50000 / 448); - int ratio = 1; - - printf("monthly start \n"); - std::string firstKey1; - std::string lastKey1; - PresetData(store1, monthlyBatch, 112, 8, ratio, firstKey1, lastKey1); - cout << "first key: " << firstKey1 << ", last key: " << lastKey1 << endl; - CalcRangeResultSetDuration(store1, monthlyBatch, 8, 112, firstKey1, lastKey1); + cout << "monthly start" << endl; + SingleStorePerfPhoneTest::DataConfig monthlyConfig = { + .batch = static_cast(50000 / 112), + .count = 112, + .size = 8, + .ratio = 1 + }; + SingleStorePerfPhoneTest::PresetResult result1; + PresetData(store1, monthlyConfig, result1); + cout << "first key: " << result1.firstKey << ", last key: " << result1.lastKey << endl; + CalcRangeResultSetDuration(store1, monthlyConfig, result1); - printf("annually start \n"); - std::string firstKey2; - std::string lastKey2; - PresetData(store2, annuallyBatch, 448, 4, ratio, firstKey2, lastKey2); - cout << "first key: " << firstKey2 << ", last key: " << lastKey2 << endl; - CalcRangeResultSetDuration(store2, annuallyBatch, 4, 448, firstKey2, lastKey2); + cout << "annually start" << endl; + SingleStorePerfPhoneTest::DataConfig annuallyConfig = { + .batch = static_cast(50000 / 448), + .count = 448, + .size = 4, + .ratio = 1 + }; + SingleStorePerfPhoneTest::PresetResult result2; + PresetData(store2, annuallyConfig, result2); + cout << "first key: " << result2.firstKey << ", last key: " << result2.lastKey << endl; + CalcRangeResultSetDuration(store2, annuallyConfig, result2); } } // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/store_factory_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/store_factory_test.cpp index 9c932e50..9b3fcf2e 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/store_factory_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/store_factory_test.cpp @@ -22,6 +22,9 @@ #include "backup_manager.h" #include "file_ex.h" +#include "hks_api.h" +#include "hks_param.h" +#include "security_manager.h" #include "store_manager.h" #include "store_util.h" #include "sys/stat.h" @@ -39,6 +42,8 @@ static Options options = { .kvStoreType = SINGLE_VERSION, .baseDir = "/data/service/el1/public/database/rekey", }; +static constexpr const char *ROOT_KEY_ALIAS = "distributeddb_client_root_key"; +static constexpr const char *HKS_BLOB_TYPE_AAD = "distributeddata_client"; class StoreFactoryTest : public testing::Test { public: @@ -57,16 +62,26 @@ public: void TearDown(); std::chrono::system_clock::time_point GetDate(const std::string &name, const std::string &path); - bool ChangeKeyDate(const std::string &name, const std::string &path, int duration); + bool ChangeKeyDate(const std::string &name, const std::string &path, int duration, const std::vector &key); bool MoveToRekeyPath(Options options, StoreId storeId); std::shared_ptr GetDBManager(const std::string &path, const AppId &appId); DBOption GetOption(const Options &options, const DBPassword &dbPassword); DBStatus ChangeKVStoreDate(const std::string &storeId, std::shared_ptr dbManager, const Options &options, DBPassword &dbPassword, int time); bool ModifyDate(int time); + bool Encrypt(const std::vector &key, SecurityManager::SecurityContent &content); + bool Decrypt(const SecurityManager::SecurityContent &content, std::vector &key); static void DeleteKVStore(); + + static std::vector vecRootKeyAlias_; + static std::vector vecAad_; }; +std::vector StoreFactoryTest::vecRootKeyAlias_ = + std::vector(ROOT_KEY_ALIAS, ROOT_KEY_ALIAS + strlen(ROOT_KEY_ALIAS)); +std::vector StoreFactoryTest::vecAad_ = + std::vector(HKS_BLOB_TYPE_AAD, HKS_BLOB_TYPE_AAD + strlen(HKS_BLOB_TYPE_AAD)); + void StoreFactoryTest::SetUpTestCase(void) { } void StoreFactoryTest::TearDownTestCase(void) { } @@ -88,52 +103,173 @@ void StoreFactoryTest::DeleteKVStore() StoreManager::GetInstance().Delete(appId, storeId, options.baseDir); } +bool StoreFactoryTest::Encrypt(const std::vector &key, SecurityManager::SecurityContent &content) +{ + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + return false; + } + + uint8_t nonceValue[SecurityManager::SecurityContent::NONCE_SIZE] = {0}; + struct HksBlob blobNonce = { .size = SecurityManager::SecurityContent::NONCE_SIZE, .data = nonceValue }; + ret = HksGenerateRandom(nullptr, &blobNonce); + if (ret != HKS_SUCCESS) { + return false; + } + + struct HksBlob blobAad = { uint32_t(vecAad_.size()), vecAad_.data() }; + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), vecRootKeyAlias_.data() }; + struct HksBlob plainKey = { uint32_t(key.size()), const_cast(key.data()) }; + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_NONCE, .blob = blobNonce }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, + }; + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return false; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return false; + } + + uint8_t cipherBuf[256] = { 0 }; + struct HksBlob cipherText = { sizeof(cipherBuf), cipherBuf }; + ret = HksEncrypt(&rootKeyName, params, &plainKey, &cipherText); + (void)HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + return false; + } + std::vector nonceContent(blobNonce.data, blobNonce.data + blobNonce.size); + content.nonceValue = nonceContent; + std::vector encryptValue(cipherText.data, cipherText.data + cipherText.size); + content.encryptValue = encryptValue; + std::fill(cipherBuf, cipherBuf + sizeof(cipherBuf), 0); + return true; +} + +bool StoreFactoryTest::Decrypt(const SecurityManager::SecurityContent &content, std::vector &key) +{ + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + return false; + } + + struct HksBlob blobNonce = { .size = uint32_t(content.nonceValue.size()), + .data = const_cast(&(content.nonceValue[0])) }; + struct HksBlob blobAad = { uint32_t(vecAad_.size()), &(vecAad_[0]) }; + struct HksBlob rootKeyName = { uint32_t(vecRootKeyAlias_.size()), &(vecRootKeyAlias_[0]) }; + struct HksBlob encryptedKeyBlob = { uint32_t(content.encryptValue.size()), + const_cast(content.encryptValue.data()) }; + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_NONCE, .blob = blobNonce }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, + }; + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return false; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + HksFreeParamSet(¶ms); + return false; + } + + uint8_t plainBuf[256] = { 0 }; + struct HksBlob plainKeyBlob = { sizeof(plainBuf), plainBuf }; + ret = HksDecrypt(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob); + (void)HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + return false; + } + + key.assign(plainKeyBlob.data, plainKeyBlob.data + plainKeyBlob.size); + std::fill(plainBuf, plainBuf + sizeof(plainBuf), 0); + return true; +} + std::chrono::system_clock::time_point StoreFactoryTest::GetDate(const std::string &name, const std::string &path) { std::chrono::system_clock::time_point timePoint; - auto keyPath = path + "/key/" + name + ".key"; + auto keyPath = path + "/key/" + name + ".key_v1"; if (!OHOS::FileExists(keyPath)) { return timePoint; } - std::vector content; auto loaded = OHOS::LoadBufferFromFile(keyPath, content); if (!loaded) { return timePoint; } - constexpr uint32_t DATE_FILE_OFFSET = 1; - constexpr uint32_t DATE_FILE_LENGTH = sizeof(time_t) / sizeof(uint8_t); - std::vector date; - date.assign(content.begin() + DATE_FILE_OFFSET, content.begin() + DATE_FILE_LENGTH + DATE_FILE_OFFSET); - timePoint = std::chrono::system_clock::from_time_t(*reinterpret_cast(const_cast(&date[0]))); + SecurityManager::SecurityContent securityContent; + size_t offset = SecurityManager::SecurityContent::MAGIC_NUM; + securityContent.nonceValue.assign(content.begin() + offset, + content.begin() + offset + SecurityManager::SecurityContent::NONCE_SIZE); + offset += SecurityManager::SecurityContent::NONCE_SIZE; + securityContent.encryptValue.assign(content.begin() + offset, content.end()); + std::vector fullKey; + if (!Decrypt(securityContent, fullKey)) { + return timePoint; + } + offset = 0; + securityContent.version = fullKey[offset++]; + securityContent.time.assign(fullKey.begin() + offset, + fullKey.begin() + offset + (sizeof(time_t) / sizeof(uint8_t))); + timePoint = std::chrono::system_clock::from_time_t( + *reinterpret_cast(const_cast(securityContent.time.data()))); return timePoint; } -bool StoreFactoryTest::ChangeKeyDate(const std::string &name, const std::string &path, int duration) +bool StoreFactoryTest::ChangeKeyDate(const std::string &name, const std::string &path, int duration, + const std::vector &key) { - auto keyPath = path + "/key/" + name + ".key"; + auto keyPath = path + "/key/" + name + ".key_v1"; if (!OHOS::FileExists(keyPath)) { return false; } - - std::vector content; - auto loaded = OHOS::LoadBufferFromFile(keyPath, content); - if (!loaded) { - return false; - } + SecurityManager::SecurityContent securityContent; + securityContent.version = SecurityManager::SecurityContent::CURRENT_VERSION; auto time = std::chrono::system_clock::to_time_t( std::chrono::system_clock::system_clock::now() - std::chrono::hours(duration)); - std::vector date(reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time)); - std::copy(date.begin(), date.end(), ++content.begin()); - - auto saved = OHOS::SaveBufferToFile(keyPath, content); - return saved; + securityContent.time = { reinterpret_cast(&time), reinterpret_cast(&time) + sizeof(time) }; + std::vector keyContent; + keyContent.push_back(securityContent.version); + keyContent.insert(keyContent.end(), securityContent.time.begin(), securityContent.time.end()); + keyContent.insert(keyContent.end(), key.begin(), key.end()); + if (!Encrypt(keyContent, securityContent)) { + return false; + } + std::vector content; + for (size_t index = 0; index < SecurityManager::SecurityContent::MAGIC_NUM; ++index) { + content.push_back(char(SecurityManager::SecurityContent::MAGIC_CHAR)); + } + content.insert(content.end(), securityContent.nonceValue.begin(), securityContent.nonceValue.end()); + content.insert(content.end(), securityContent.encryptValue.begin(), securityContent.encryptValue.end()); + return OHOS::SaveBufferToFile(keyPath, content); } bool StoreFactoryTest::MoveToRekeyPath(Options options, StoreId storeId) { - std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key"; - std::string rekeyFileName = options.baseDir + "/rekey/key/" + storeId.storeId + ".new.key"; + std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key_v1"; + std::string rekeyFileName = options.baseDir + "/rekey/key/" + storeId.storeId + ".new.key_v1"; bool result = StoreUtil::Rename(keyFileName, rekeyFileName); if (!result) { return false; @@ -185,7 +321,9 @@ StoreFactoryTest::DBStatus StoreFactoryTest::ChangeKVStoreDate(const std::string status = dbStatus; store = dbStore; }); - if (!ChangeKeyDate(storeId, options.baseDir, time)) { + dbPassword = SecurityManager::GetInstance().GetDBPassword(storeId, options.baseDir, false); + std::vector key(dbPassword.GetData(), dbPassword.GetData() + dbPassword.GetSize()); + if (!ChangeKeyDate(storeId, options.baseDir, time, key)) { std::cout << "failed" << std::endl; } dbPassword = SecurityManager::GetInstance().GetDBPassword(storeId, options.baseDir, false); @@ -277,7 +415,7 @@ HWTEST_F(StoreFactoryTest, RekeyInterruptedWhileChangeKeyFile, TestSize.Level1) StoreManager::GetInstance().GetKVStore(appId, storeId, options, status); status = StoreManager::GetInstance().CloseKVStore(appId, storeId); ASSERT_EQ(status, SUCCESS); - std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key"; + std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key_v1"; auto isKeyExist = StoreUtil::IsFileExist(keyFileName); ASSERT_TRUE(isKeyExist); @@ -307,8 +445,8 @@ HWTEST_F(StoreFactoryTest, RekeyInterruptedBeforeChangeKeyFile, TestSize.Level1) StoreId newStoreId = { "newStore" }; StoreManager::GetInstance().GetKVStore(appId, newStoreId, options, status); - std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key"; - std::string mockKeyFileName = options.baseDir + "/key/" + newStoreId.storeId + ".key"; + std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key_v1"; + std::string mockKeyFileName = options.baseDir + "/key/" + newStoreId.storeId + ".key_v1"; StoreUtil::Rename(mockKeyFileName, keyFileName); StoreUtil::Remove(mockKeyFileName); auto isKeyExist = StoreUtil::IsFileExist(mockKeyFileName); @@ -343,7 +481,7 @@ HWTEST_F(StoreFactoryTest, RekeyNoPwdFile, TestSize.Level1) status = StoreManager::GetInstance().CloseKVStore(appId, storeId); ASSERT_EQ(status, SUCCESS); - std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key"; + std::string keyFileName = options.baseDir + "/key/" + storeId.storeId + ".key_v1"; StoreUtil::Remove(keyFileName); auto isKeyExist = StoreUtil::IsFileExist(keyFileName); diff --git a/kv_store/frameworks/jskitsimpl/distributeddata/include/js_const_properties.h b/kv_store/frameworks/jskitsimpl/distributeddata/include/js_const_properties.h index 367261d9..6d42a1d1 100644 --- a/kv_store/frameworks/jskitsimpl/distributeddata/include/js_const_properties.h +++ b/kv_store/frameworks/jskitsimpl/distributeddata/include/js_const_properties.h @@ -24,4 +24,4 @@ namespace OHOS::DistributedData { napi_status InitConstProperties(napi_env env, napi_value exports); } // namespace OHOS::DistributedData -#endif // OHOS_JS_CONST_PROPERTIES_H +#endif // OHOS_JS_CONST_PROPERTIES_H \ No newline at end of file diff --git a/kv_store/frameworks/jskitsimpl/distributeddata/include/js_util.h b/kv_store/frameworks/jskitsimpl/distributeddata/include/js_util.h index 12fce1a2..72241960 100644 --- a/kv_store/frameworks/jskitsimpl/distributeddata/include/js_util.h +++ b/kv_store/frameworks/jskitsimpl/distributeddata/include/js_util.h @@ -178,6 +178,7 @@ public: static bool IsNull(napi_env env, napi_value value); + static std::string Anonymous(const std::string &name); private: enum { /* std::map to js::tuple */ diff --git a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_manager.cpp b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_manager.cpp index 665f48f2..a01d3e5f 100644 --- a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_manager.cpp +++ b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_manager.cpp @@ -134,7 +134,8 @@ napi_value JsKVManager::GetKVStore(napi_env env, napi_callback_info info) ctxt->options.baseDir = kvm->param_->baseDir; ctxt->options.area = kvm->param_->area + 1; ctxt->options.hapName = kvm->param_->hapName; - ZLOGD("Options area:%{public}d dir:%{public}s", ctxt->options.area, ctxt->options.baseDir.c_str()); + ZLOGD("Options area:%{public}d dir:%{public}s", ctxt->options.area, + JSUtil::Anonymous(ctxt->options.baseDir).c_str()); std::shared_ptr kvStore; Status status = kvm->kvDataManager_.GetSingleKvStore(ctxt->options, appId, storeId, kvStore); if (status == CRYPT_ERROR) { @@ -231,7 +232,7 @@ napi_value JsKVManager::DeleteKVStore(napi_env env, napi_callback_info info) auto kvm = reinterpret_cast(ctxt->native); CHECK_ARGS_RETURN_VOID(ctxt, kvm != nullptr, "KVManager is null, failed!"); std::string databaseDir = kvm->param_->baseDir; - ZLOGD("DeleteKVStore databaseDir is: %{public}s", databaseDir.c_str()); + ZLOGD("DeleteKVStore databaseDir is: %{public}s", JSUtil::Anonymous(databaseDir).c_str()); Status status = kvm->kvDataManager_.DeleteKvStore(appId, storeId, databaseDir); ZLOGD("DeleteKvStore status:%{public}d", status); ctxt->status = (status == Status::SUCCESS) ? napi_ok : napi_generic_failure; diff --git a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_store.cpp b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_store.cpp index 0e76225f..89d9889d 100644 --- a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_store.cpp +++ b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_store.cpp @@ -18,11 +18,9 @@ #include "log_print.h" #include "napi_queue.h" #include "datashare_values_bucket.h" -#include "datashare_predicates.h" #include "single_kvstore.h" using namespace OHOS::DistributedKv; -using namespace OHOS::DataShare; namespace OHOS::DistributedData { inline static uint8_t UNVALID_SUBSCRIBE_TYPE = 255; diff --git a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_single_kv_store.cpp b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_single_kv_store.cpp index 841df33d..71f5f667 100644 --- a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_single_kv_store.cpp +++ b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_single_kv_store.cpp @@ -16,7 +16,6 @@ #include "js_single_kv_store.h" #include "js_util.h" #include "js_kv_store_resultset.h" -#include "datashare_predicates.h" #include "js_query.h" #include "log_print.h" #include "napi_queue.h" @@ -24,7 +23,6 @@ #include "kv_utils.h" using namespace OHOS::DistributedKv; -using namespace OHOS::DataShare; namespace OHOS::DistributedData { JsSingleKVStore::JsSingleKVStore(const std::string& storeId) : JsKVStore(storeId) diff --git a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_util.cpp b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_util.cpp index 964a6c38..1d220ab4 100644 --- a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_util.cpp +++ b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_util.cpp @@ -30,6 +30,11 @@ using namespace OHOS::DataShare; namespace OHOS::DistributedData { constexpr int32_t STR_MAX_LENGTH = 4096; constexpr size_t STR_TAIL_LENGTH = 1; +static constexpr int32_t HEAD_SIZE = 3; +static constexpr int32_t END_SIZE = 3; +static constexpr int32_t MIN_SIZE = 9; +static constexpr const char *REPLACE_CHAIN = "***"; +static constexpr const char *DEFAULT_ANONYMOUS = "******"; struct PredicatesProxy { std::shared_ptr predicates_; }; @@ -1117,7 +1122,7 @@ napi_status JSUtil::GetCurrentAbilityParam(napi_env env, ContextParam ¶m) param.hapName = hapInfo->moduleName; } ZLOGI("area:%{public}d hapName:%{public}s baseDir:%{public}s", param.area, param.hapName.c_str(), - param.baseDir.c_str()); + Anonymous(param.baseDir).c_str()); return napi_ok; } @@ -1172,4 +1177,17 @@ std::pair JSUtil::GetInnerValue( } return std::make_pair(napi_ok, inner); } + +std::string JSUtil::Anonymous(const std::string &name) +{ + if (name.length() <= HEAD_SIZE) { + return DEFAULT_ANONYMOUS; + } + + if (name.length() < MIN_SIZE) { + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN); + } + + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE)); +} } // namespace OHOS::DistributedData diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_kv_manager.h b/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_kv_manager.h index 61c5c3e0..1fd6e3d6 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_kv_manager.h +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_kv_manager.h @@ -63,7 +63,6 @@ private: std::shared_ptr uvQueue_; std::shared_ptr param_; static constexpr int MAX_APP_ID_LEN = 256; - static constexpr int API_20_VERSION = 20; }; } // namespace OHOS::DistributedKVStore #endif // OHOS_KV_MANAGER_H diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_util.h b/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_util.h index 59874055..3bb619a2 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_util.h +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_util.h @@ -220,6 +220,7 @@ public: static int32_t GetApiVersion(napi_env, napi_value value); + static std::string Anonymous(const std::string &name); private: enum { /* std::map to js::tuple */ diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/entry_point.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/entry_point.cpp index 9d9be5a4..085516fa 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/entry_point.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/entry_point.cpp @@ -28,20 +28,12 @@ static napi_value Init(napi_env env, napi_value exports) const napi_property_descriptor desc[] = { DECLARE_NAPI_FUNCTION("createKVManager", JsKVManager::CreateKVManager) }; - napi_status status = napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); - ZLOGI("Init createKVManager %{public}d", status); + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + napi_set_named_property(env, exports, "FieldNode", JsFieldNode::Constructor(env)); + napi_set_named_property(env, exports, "Schema", JsSchema::Constructor(env)); + napi_set_named_property(env, exports, "Query", JsQuery::Constructor(env)); + InitConstProperties(env, exports); - status = napi_set_named_property(env, exports, "FieldNode", JsFieldNode::Constructor(env)); - ZLOGI("Init FieldNode %{public}d", status); - - status = napi_set_named_property(env, exports, "Schema", JsSchema::Constructor(env)); - ZLOGI("Init Schema %{public}d", status); - - status = napi_set_named_property(env, exports, "Query", JsQuery::Constructor(env)); - ZLOGI("Init Query %{public}d", status); - - status = InitConstProperties(env, exports); - ZLOGI("Init Enumerate Constants %{public}d", status); return exports; } diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_const_properties.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_const_properties.cpp index aa9394d9..0e54930b 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_const_properties.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_const_properties.cpp @@ -41,7 +41,10 @@ static napi_value ExportConstants(napi_env env) constexpr int32_t MAX_BATCH_SIZE = 128; napi_value constants = nullptr; - napi_create_object(env, &constants); + napi_status status = napi_create_object(env, &constants); + if (status != napi_ok) { + return nullptr; + } SetNamedProperty(env, constants, "MAX_KEY_LENGTH", MAX_KEY_LENGTH); SetNamedProperty(env, constants, "MAX_VALUE_LENGTH", MAX_VALUE_LENGTH); SetNamedProperty(env, constants, "MAX_KEY_LENGTH_DEVICE", MAX_KEY_LENGTH_DEVICE); @@ -55,7 +58,10 @@ static napi_value ExportConstants(napi_env env) static napi_value ExportValueType(napi_env env) { napi_value valueType = nullptr; - napi_create_object(env, &valueType); + napi_status status = napi_create_object(env, &valueType); + if (status != napi_ok) { + return nullptr; + } SetNamedProperty(env, valueType, "STRING", (int32_t)JSUtil::STRING); SetNamedProperty(env, valueType, "INTEGER", (int32_t)JSUtil::INTEGER); SetNamedProperty(env, valueType, "FLOAT", (int32_t)JSUtil::FLOAT); @@ -69,7 +75,10 @@ static napi_value ExportValueType(napi_env env) static napi_value ExportSyncMode(napi_env env) { napi_value syncMode = nullptr; - napi_create_object(env, &syncMode); + napi_status status = napi_create_object(env, &syncMode); + if (status != napi_ok) { + return nullptr; + } SetNamedProperty(env, syncMode, "PULL_ONLY", (int32_t)SyncMode::PULL); SetNamedProperty(env, syncMode, "PUSH_ONLY", (int32_t)SyncMode::PUSH); SetNamedProperty(env, syncMode, "PUSH_PULL", (int32_t)SyncMode::PUSH_PULL); @@ -80,8 +89,10 @@ static napi_value ExportSyncMode(napi_env env) static napi_value ExportSubscribeType(napi_env env) { napi_value subscribeType = nullptr; - napi_create_object(env, &subscribeType); - + napi_status status = napi_create_object(env, &subscribeType); + if (status != napi_ok) { + return nullptr; + } SetNamedProperty(env, subscribeType, "SUBSCRIBE_TYPE_LOCAL", (int32_t)SUBSCRIBE_LOCAL); SetNamedProperty(env, subscribeType, "SUBSCRIBE_TYPE_REMOTE", (int32_t)SUBSCRIBE_REMOTE); SetNamedProperty(env, subscribeType, "SUBSCRIBE_TYPE_ALL", (int32_t)SUBSCRIBE_LOCAL_REMOTE); @@ -92,7 +103,10 @@ static napi_value ExportSubscribeType(napi_env env) static napi_value ExportKVStoreType(napi_env env) { napi_value kvStoreType = nullptr; - napi_create_object(env, &kvStoreType); + napi_status status = napi_create_object(env, &kvStoreType); + if (status != napi_ok) { + return nullptr; + } SetNamedProperty(env, kvStoreType, "DEVICE_COLLABORATION", (int32_t)KvStoreType::DEVICE_COLLABORATION); SetNamedProperty(env, kvStoreType, "SINGLE_VERSION", (int32_t)KvStoreType::SINGLE_VERSION); napi_object_freeze(env, kvStoreType); @@ -102,8 +116,10 @@ static napi_value ExportKVStoreType(napi_env env) static napi_value ExportSecurityLevel(napi_env env) { napi_value securityLevel = nullptr; - - napi_create_object(env, &securityLevel); + napi_status status = napi_create_object(env, &securityLevel); + if (status != napi_ok) { + return nullptr; + } SetNamedProperty(env, securityLevel, "S1", (int32_t)SecurityLevel::S1); SetNamedProperty(env, securityLevel, "S2", (int32_t)SecurityLevel::S2); SetNamedProperty(env, securityLevel, "S3", (int32_t)SecurityLevel::S3); diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_device_kv_store.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_device_kv_store.cpp index f3160dbc..9530ee70 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_device_kv_store.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_device_kv_store.cpp @@ -110,6 +110,9 @@ napi_value JsDeviceKVStore::Get(napi_env env, napi_callback_info info) OHOS::DistributedKv::Key key(deviceKey); OHOS::DistributedKv::Value value; auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } ASSERT_STATUS(ctxt, "kvStore->result() failed!"); bool isSchemaStore = reinterpret_cast(ctxt->native)->IsSchemaStore(); Status status = kvStore->Get(key, value); @@ -202,6 +205,9 @@ napi_value JsDeviceKVStore::GetEntries(napi_env env, napi_callback_info info) auto execute = [ctxt]() { auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } Status status = kvStore->GetEntries(ctxt->va.dataQuery, ctxt->entries); ZLOGD("kvStore->GetEntries() return %{public}d", status); ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? @@ -254,6 +260,9 @@ napi_value JsDeviceKVStore::GetResultSet(napi_env env, napi_callback_info info) auto execute = [ctxt]() { std::shared_ptr kvResultSet; auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } Status status = kvStore->GetResultSet(ctxt->va.dataQuery, kvResultSet); ZLOGD("kvStore->GetResultSet() return %{public}d", status); ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? @@ -297,6 +306,9 @@ napi_value JsDeviceKVStore::GetResultSize(napi_env env, napi_callback_info info) auto execute = [ctxt]() { auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } Status status = kvStore->GetCount(ctxt->va.dataQuery, ctxt->resultSize); ZLOGD("kvStore->GetCount() return %{public}d", status); ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_error_utils.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_error_utils.cpp index 09816ebb..d79c19b9 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_error_utils.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_error_utils.cpp @@ -26,16 +26,14 @@ static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = { { Status::STORE_NOT_OPEN, 0, "" }, { Status::STORE_ALREADY_SUBSCRIBE, 0, "" }, { Status::STORE_NOT_SUBSCRIBE, 0, "" }, - { Status::NOT_FOUND, 15100004, "Data not found." }, - { Status::STORE_META_CHANGED, 15100002, - "The options configuration changes when the API is called to obtain a KV store." }, + { Status::NOT_FOUND, 15100004, "Not found." }, + { Status::STORE_META_CHANGED, 15100002, "Open existed database with changed options." }, { Status::PERMISSION_DENIED, 202, "Permission denied" }, - { Status::CRYPT_ERROR, 15100006, "Unable to open the database." }, - { Status::OVER_MAX_LIMITS, 15100001, "Upper limit exceeded." }, + { Status::CRYPT_ERROR, 15100003, "Database corrupted." }, + { Status::OVER_MAX_LIMITS, 15100001, "Over max limits." }, { Status::ALREADY_CLOSED, 15100005, "Database or result set already closed." }, { Status::DATA_CORRUPTED, 15100003, "Database corrupted" }, - { Status::WAL_OVER_LIMITS, 14800047, "the WAL file size exceeds the default limit."}, - { Status::DB_CANT_OPEN, 15100006, "Unable to open the database." } + { Status::WAL_OVER_LIMITS, 14800047, "the WAL file size exceeds the default limit."} }; const std::optional GetJsErrorCode(int32_t errorCode) diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_field_node.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_field_node.cpp index d62f08c3..2354e4ed 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_field_node.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_field_node.cpp @@ -22,12 +22,16 @@ using namespace OHOS::DistributedKv; namespace OHOS::DistributedKVStore { -static std::string FIELD_NAME = "FIELD_NAME"; -static std::string VALUE_TYPE = "VALUE_TYPE"; -static std::string DEFAULT_VALUE = "DEFAULT_VALUE"; -static std::string IS_DEFAULT_VALUE = "IS_DEFAULT_VALUE"; -static std::string IS_NULLABLE = "IS_NULLABLE"; -static std::string CHILDREN = "CHILDREN"; +static constexpr const char* FIELD_NAME = "FIELD_NAME"; +static constexpr const char* VALUE_TYPE = "VALUE_TYPE"; +static constexpr const char* DEFAULT_VALUE = "DEFAULT_VALUE"; +static constexpr const char* IS_DEFAULT_VALUE = "IS_DEFAULT_VALUE"; +static constexpr const char* IS_NULLABLE = "IS_NULLABLE"; +static constexpr const char* CHILDREN = "CHILDREN"; +static constexpr const char* SPLIT = ","; +static constexpr const char* NOT_NULL = ", NOT NULL,"; +static constexpr const char* DEFAULT = " DEFAULT "; +static constexpr const char* MARK = "'"; std::map JsFieldNode::valueTypeToString_ = { { JSUtil::STRING, std::string("STRING") }, @@ -61,12 +65,11 @@ std::string JsFieldNode::GetFieldName() JsFieldNode::json JsFieldNode::GetValueForJson() { if (fields_.empty()) { + std::string jsonDesc = ToString(valueType_) + (isNullable_ ? SPLIT : NOT_NULL) + DEFAULT; if (valueType_ == JSUtil::STRING) { - return ToString(valueType_) + ToString(isNullable_ ? "," : ", NOT NULL,") + - " DEFAULT '" + ToString(defaultValue_) + "'"; + return jsonDesc += MARK + ToString(defaultValue_) + MARK; } - return ToString(valueType_) + ToString(isNullable_ ? "," : ", NOT NULL,") + - " DEFAULT " + ToString(defaultValue_); + return jsonDesc += ToString(defaultValue_); } json jsFields; diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_kv_manager.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_kv_manager.cpp index b2917179..71078694 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_kv_manager.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_kv_manager.cpp @@ -144,7 +144,8 @@ napi_value JsKVManager::GetKVStore(napi_env env, napi_callback_info info) ctxt->options.area = kvm->param_->area + 1; ctxt->options.hapName = kvm->param_->hapName; ctxt->options.apiVersion = kvm->param_->apiVersion; - ZLOGD("Options area:%{public}d dir:%{public}s", ctxt->options.area, ctxt->options.baseDir.c_str()); + ZLOGD("Options area:%{public}d dir:%{public}s", ctxt->options.area, + JSUtil::Anonymous(ctxt->options.baseDir).c_str()); std::shared_ptr kvStore; Status status = kvm->kvDataManager_.GetSingleKvStore(ctxt->options, appId, storeId, kvStore); if (status == DATA_CORRUPTED) { @@ -152,9 +153,6 @@ napi_value JsKVManager::GetKVStore(napi_env env, napi_callback_info info) status = kvm->kvDataManager_.GetSingleKvStore(ctxt->options, appId, storeId, kvStore); ZLOGE("Data has corrupted, rebuild db"); } - if (status == CRYPT_ERROR && kvm->param_->apiVersion < API_20_VERSION) { - status = DATA_CORRUPTED; - } ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; ctxt->kvStore->SetKvStorePtr(kvStore); @@ -245,7 +243,7 @@ napi_value JsKVManager::DeleteKVStore(napi_env env, napi_callback_info info) auto kvm = reinterpret_cast(ctxt->native); ASSERT_ARGS(ctxt, kvm != nullptr, "KVManager is null, failed!"); std::string databaseDir = kvm->param_->baseDir; - ZLOGD("DeleteKVStore databaseDir is: %{public}s", databaseDir.c_str()); + ZLOGD("DeleteKVStore databaseDir is: %{public}s", JSUtil::Anonymous(databaseDir).c_str()); Status status = kvm->kvDataManager_.DeleteKvStore(appId, storeId, databaseDir); ZLOGD("DeleteKvStore status:%{public}d", status); ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_schema.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_schema.cpp index 79a1337d..177d8c19 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_schema.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_schema.cpp @@ -25,13 +25,14 @@ using namespace OHOS::DistributedKv; using json = nlohmann::json; namespace OHOS::DistributedKVStore { -static std::string LABEL = "Schema"; -static std::string SCHEMA_VERSION = "SCHEMA_VERSION"; -static std::string SCHEMA_MODE = "SCHEMA_MODE"; -static std::string SCHEMA_DEFINE = "SCHEMA_DEFINE"; -static std::string SCHEMA_INDEXES = "SCHEMA_INDEXES"; -static std::string SCHEMA_SKIPSIZE = "SCHEMA_SKIPSIZE"; -static std::string DEFAULT_SCHEMA_VERSION = "1.0"; +static constexpr const char* SCHEMA_VERSION = "SCHEMA_VERSION"; +static constexpr const char* SCHEMA_MODE = "SCHEMA_MODE"; +static constexpr const char* SCHEMA_DEFINE = "SCHEMA_DEFINE"; +static constexpr const char* SCHEMA_INDEXES = "SCHEMA_INDEXES"; +static constexpr const char* SCHEMA_SKIPSIZE = "SCHEMA_SKIPSIZE"; +static constexpr const char* DEFAULT_SCHEMA_VERSION = "1.0"; +static constexpr const char* SCHEMA_STRICT = "STRICT"; +static constexpr const char* SCHEMA_COMPATIBLE = "COMPATIBLE"; JsSchema::JsSchema(napi_env env) : env_(env) @@ -234,7 +235,7 @@ std::string JsSchema::Dump() } json js = { { SCHEMA_VERSION, DEFAULT_SCHEMA_VERSION }, - { SCHEMA_MODE, (mode_ == SCHEMA_MODE_STRICT) ? "STRICT" : "COMPATIBLE" }, + { SCHEMA_MODE, (mode_ == SCHEMA_MODE_STRICT) ? SCHEMA_STRICT : SCHEMA_COMPATIBLE }, { SCHEMA_DEFINE, rootNode_->GetValueForJson() }, { SCHEMA_INDEXES, jsIndexes }, { SCHEMA_SKIPSIZE, skip_ }, diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_single_kv_store.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_single_kv_store.cpp index 1e3ffe49..1983175e 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_single_kv_store.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_single_kv_store.cpp @@ -16,7 +16,6 @@ #include "js_single_kv_store.h" #include "js_util.h" #include "js_kv_store_resultset.h" -#include "datashare_predicates.h" #include "js_query.h" #include "log_print.h" #include "napi_queue.h" @@ -24,7 +23,6 @@ #include "kv_utils.h" using namespace OHOS::DistributedKv; -using namespace OHOS::DataShare; namespace OHOS::DistributedKVStore { inline static uint8_t UNVALID_SUBSCRIBE_TYPE = 255; std::map JsSingleKVStore::onEventHandlers_ = { @@ -189,10 +187,7 @@ napi_value JsSingleKVStore::Put(napi_env env, napi_callback_info info) ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->value); if (ctxt->status != napi_ok) { ctxt->isThrowError = true; - napi_valuetype ntype = napi_undefined; - napi_typeof(env, argv[0], &ntype); - auto type = valueTypeToString_.find(ntype); - ThrowNapiError(env, Status::INVALID_ARGUMENT, "Parameter error:the type of value must be:" + type->second); + ThrowNapiError(env, Status::INVALID_ARGUMENT, "Parameter error: invalid value type"); return; } }); @@ -204,6 +199,9 @@ napi_value JsSingleKVStore::Put(napi_env env, napi_callback_info info) auto &kvStore = reinterpret_cast(ctxt->native)->kvStore_; DistributedKv::Value value = isSchemaStore ? DistributedKv::Blob(std::get(ctxt->value)) : JSUtil::VariantValue2Blob(ctxt->value); + if (kvStore == nullptr) { + return; + } Status status = kvStore->Put(key, value); ZLOGD("kvStore->Put return %{public}d", status); ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? @@ -908,6 +906,9 @@ napi_value JsSingleKVStore::Get(napi_env env, napi_callback_info info) OHOS::DistributedKv::Key key(ctxt->key); OHOS::DistributedKv::Value value; auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } bool isSchemaStore = reinterpret_cast(ctxt->native)->IsSchemaStore(); Status status = kvStore->Get(key, value); ZLOGD("kvStore->Get return %{public}d", status); @@ -991,6 +992,9 @@ napi_value JsSingleKVStore::GetEntries(napi_env env, napi_callback_info info) auto execute = [ctxt]() { auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } Status status = kvStore->GetEntries(ctxt->va.dataQuery, ctxt->entries); ZLOGD("kvStore->GetEntries() return %{public}d", status); ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? @@ -1041,6 +1045,9 @@ napi_value JsSingleKVStore::GetResultSet(napi_env env, napi_callback_info info) auto execute = [ctxt]() { std::shared_ptr kvResultSet; auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } Status status = kvStore->GetResultSet(ctxt->va.dataQuery, kvResultSet); ZLOGD("kvStore->GetResultSet() return %{public}d", status); @@ -1087,6 +1094,9 @@ napi_value JsSingleKVStore::CloseResultSet(napi_env env, napi_callback_info info auto execute = [ctxt]() { auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } auto resultSet = ctxt->resultSet->GetInstance(); ctxt->resultSet->SetInstance(nullptr); Status status = kvStore->CloseResultSet(resultSet); @@ -1126,6 +1136,9 @@ napi_value JsSingleKVStore::GetResultSize(napi_env env, napi_callback_info info) auto execute = [ctxt]() { auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } auto query = ctxt->query->GetDataQuery(); Status status = kvStore->GetCount(query, ctxt->resultSize); ZLOGD("kvStore->GetCount() return %{public}d", status); @@ -1163,6 +1176,9 @@ napi_value JsSingleKVStore::RemoveDeviceData(napi_env env, napi_callback_info in auto execute = [ctxt]() { auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } Status status = kvStore->RemoveDeviceData(ctxt->deviceId); ZLOGD("kvStore->RemoveDeviceData return %{public}d", status); ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? @@ -1234,6 +1250,9 @@ napi_value JsSingleKVStore::Sync(napi_env env, napi_callback_info info) (int)ctxt->deviceIdList.size(), ctxt->mode, ctxt->allowedDelayMs); auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return nullptr; + } Status status = Status::INVALID_ARGUMENT; if (ctxt->type == napi_object) { auto query = ctxt->query->GetDataQuery(); @@ -1272,6 +1291,9 @@ napi_value JsSingleKVStore::SetSyncParam(napi_env env, napi_callback_info info) auto execute = [ctxt]() { auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } KvSyncParam syncParam { ctxt->allowedDelayMs }; Status status = kvStore->SetSyncParam(syncParam); ZLOGD("kvStore->SetSyncParam return %{public}d", status); @@ -1296,6 +1318,9 @@ napi_value JsSingleKVStore::GetSecurityLevel(napi_env env, napi_callback_info in auto execute = [ctxt]() { auto kvStore = reinterpret_cast(ctxt->native)->GetKvStorePtr(); + if (kvStore == nullptr) { + return; + } Status status = kvStore->GetSecurityLevel(ctxt->securityLevel); ZLOGD("kvStore->GetSecurityLevel return %{public}d", status); ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp index 9087b7a2..6eae5779 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp @@ -27,6 +27,11 @@ namespace OHOS::DistributedKVStore { constexpr int32_t STR_MAX_LENGTH = 4096; constexpr size_t STR_TAIL_LENGTH = 1; +static constexpr int32_t HEAD_SIZE = 3; +static constexpr int32_t END_SIZE = 3; +static constexpr int32_t MIN_SIZE = 9; +static constexpr const char *REPLACE_CHAIN = "***"; +static constexpr const char *DEFAULT_ANONYMOUS = "******"; static constexpr JSUtil::JsFeatureSpace FEATURE_NAME_SPACES[] = { { "ohos.data.cloudData", "ZGF0YS5jbG91ZERhdGE=", false }, { "ohos.data.dataAbility", "ZGF0YS5kYXRhQWJpbGl0eQ==", false }, @@ -199,7 +204,7 @@ JSUtil::KvStoreVariant JSUtil::Blob2VariantValue(const DistributedKv::Blob& blob auto& data = blob.Data(); // number 2 means: valid Blob must have more than 2 bytes. if (data.size() < 1) { - ZLOGE("Blob have no data!"); + ZLOGD("Blob have no data!"); return JSUtil::KvStoreVariant(); } // number 1 means: skip the first byte, byte[0] is real data type. @@ -1248,7 +1253,7 @@ JSUtil::StatusMsg JSUtil::GetCurrentAbilityParam(napi_env env, ContextParam &par if (hapInfo != nullptr) { param.hapName = hapInfo->moduleName; } - ZLOGI("area:%{public}d hapName:%{public}s baseDir:%{public}s", param.area, param.hapName.c_str(), + ZLOGI("area:%{public}d hapName:%{public}s baseDir:%{public}s", param.area, Anonymous(param.hapName).c_str(), param.baseDir.c_str()); return napi_ok; @@ -1342,4 +1347,17 @@ std::pair JSUtil::GetInnerValue( } return std::make_pair(napi_ok, inner); } + +std::string JSUtil::Anonymous(const std::string &name) +{ + if (name.length() <= HEAD_SIZE) { + return DEFAULT_ANONYMOUS; + } + + if (name.length() < MIN_SIZE) { + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN); + } + + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE)); +} } // namespace OHOS::DistributedKVStore diff --git a/kv_store/frameworks/libs/distributeddb/BUILD.gn b/kv_store/frameworks/libs/distributeddb/BUILD.gn index 345756ce..41f46d87 100644 --- a/kv_store/frameworks/libs/distributeddb/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/BUILD.gn @@ -91,6 +91,7 @@ group("build_module") { deps = [ ":customtokenizer", ":distributeddb", + ":distributeddb_client", ] } @@ -115,6 +116,7 @@ ohos_shared_library("distributeddb") { "-fvisibility=hidden", "-Os", "-D_FORTIFY_SOURCE=2", + "-flto", ] deps = [ "gaussdb_rd:gaussdb_rd" ] @@ -124,11 +126,11 @@ ohos_shared_library("distributeddb") { "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "jsoncpp:jsoncpp", "zlib:shared_libz", ] public_external_deps = [ - "jsoncpp:jsoncpp", "openssl:libcrypto_shared", "sqlite:sqlite", ] @@ -175,6 +177,7 @@ ohos_shared_library("customtokenizer") { cflags_cc = [ "-fvisibility=hidden", "-Os", + "-D_FORTIFY_SOURCE=2", ] external_deps = [ @@ -188,3 +191,102 @@ ohos_shared_library("customtokenizer") { innerapi_tags = [ "platformsdk_indirect" ] part_name = "kv_store" } + +config("distributeddb_client_public_config") { + visibility = [ "*:*" ] + include_dirs = [ + "interfaces/include/relational", + "interfaces/include", + "include", + ] +} + +config("distributeddb_client_config") { + visibility = [ ":*" ] + include_dirs = [ + "interfaces/src/relational", + "common/include/cloud", + "common/include", + "interfaces/include", + "interfaces/include/cloud", + "include", + "storage/include", + "communicator/include", + "common/include/relational", + "storage/src/sqlite", + "storage/src", + "storage/src/kv", + "syncer/src", + "syncer/src/device", + "storage/src/sqlite/relational", + "storage/src/relational", + ] + + defines = [ + "_LARGEFILE64_SOURCE", + "_FILE_OFFSET_BITS=64", + "SQLITE_HAS_CODEC", + "SQLITE_ENABLE_JSON1", + "USING_HILOG_LOGGER", + "USE_SQLITE_SYMBOLS", + "USING_DB_JSON_EXTRACT_AUTOMATICALLY", + "JSONCPP_USE_BUILDER", + "OMIT_FLATBUFFER", + "OMIT_MULTI_VER", + "RELATIONAL_STORE", + "SQLITE_DISTRIBUTE_RELATIONAL", + "USE_DFX_ABILITY", + "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", + ] + if (is_debug) { + defines += [ "TRACE_SQLITE_EXECUTE" ] + } + if (is_ohos) { + defines += [ "USE_FFRT" ] + defines += [ "RDB_CLIENT" ] + } + if (kv_store_cloud) { + defines += [ "USE_DISTRIBUTEDDB_CLOUD" ] + } +} + +ohos_shared_library("distributeddb_client") { + branch_protector_ret = "pac_ret" + sanitize = { + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + sources = distributeddb_client_src + sources += distributeddb_base_src + configs = [ ":distributeddb_client_config" ] + public_configs = [ ":distributeddb_client_public_config" ] + + cflags_cc = [ + "-fvisibility=hidden", + "-Os", + "-D_FORTIFY_SOURCE=2", + "-flto", + ] + + external_deps = [ + "cJSON:cjson", + "c_utils:utils", + "ffrt:libffrt", + "hilog:libhilog", + "jsoncpp:jsoncpp", + ] + + public_external_deps = [ + "openssl:libcrypto_shared", + "sqlite:sqlite", + ] + + subsystem_name = "distributeddatamgr" + innerapi_tags = [ "platformsdk_indirect" ] + part_name = "kv_store" +} diff --git a/kv_store/frameworks/libs/distributeddb/common/include/auto_launch.h b/kv_store/frameworks/libs/distributeddb/common/include/auto_launch.h index 87b04304..372db884 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/auto_launch.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/auto_launch.h @@ -73,7 +73,7 @@ public: AutoLaunch() = default; - virtual ~AutoLaunch(); + ~AutoLaunch(); DISABLE_COPY_ASSIGN_MOVE(AutoLaunch); diff --git a/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h b/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h index 464bcc61..9a5a1734 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h @@ -17,7 +17,6 @@ #define CLOUD_DB_CONSTANT_H #include "cloud/cloud_store_types.h" -#include namespace DistributedDB { class CloudDbConstant { @@ -99,6 +98,7 @@ public: static constexpr const uint32_t ON_CHANGE_TRACKER = 0x1; static constexpr const uint32_t ON_CHANGE_P2P = 0x2; + static constexpr const uint32_t ON_CHANGE_KNOWLEDGE = 0x4; }; } // namespace DistributedDB #endif // CLOUD_DB_CONSTANT_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/include/concurrent_adapter.h b/kv_store/frameworks/libs/distributeddb/common/include/concurrent_adapter.h index 8c436567..cf387274 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/concurrent_adapter.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/concurrent_adapter.h @@ -39,6 +39,7 @@ public: #ifdef USE_FFRT static void AdapterAutoLock(ffrt::mutex &mutex); static void AdapterAutoUnLock(ffrt::mutex &mutex); + static void Stop(); #else static void AdapterAutoLock(std::mutex &mutex); static void AdapterAutoUnLock(std::mutex &mutex); diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_common.h b/kv_store/frameworks/libs/distributeddb/common/include/db_common.h index 5f056954..c2cf0d66 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_common.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_common.h @@ -145,7 +145,9 @@ public: static uint64_t EraseBit(uint64_t origin, uint64_t eraseBit); - static void LoadGrdLib(void); + static void *LoadGrdLib(void); + + static void UnLoadGrdLib(void *handle); static bool IsGrdLibLoaded(void); diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h b/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h index acbc03a8..45d8b83f 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h @@ -24,6 +24,7 @@ public: static constexpr const size_t MAX_KEY_SIZE = 1024; static constexpr const size_t MAX_VALUE_SIZE = 4 * 1024 * 1024; // 4M static constexpr const size_t MAX_SET_VALUE_SIZE = 64 * 1024 * 1024; // 64M + static constexpr const size_t MAX_FIELD_NUM = 2000; static constexpr const size_t MAX_BATCH_SIZE = 128; static constexpr const size_t MAX_DEV_LENGTH = 128; static constexpr const size_t MAX_TRANSACTION_KEY_VALUE_LENS = 512 * 1024 * 1024; // 512M @@ -62,30 +63,31 @@ public: static constexpr const uint64_t MAX_STORE_ID_LENGTH = 128; static constexpr const uint64_t MAX_SUB_USER_LENGTH = 128; - static const std::string MULTI_SUB_DIR; - static const std::string SINGLE_SUB_DIR; - static const std::string LOCAL_SUB_DIR; + static constexpr const char *MULTI_SUB_DIR = "multi_ver"; + static constexpr const char *SINGLE_SUB_DIR = "single_ver"; + static constexpr const char *LOCAL_SUB_DIR = "local"; - static const std::string MAINDB_DIR; - static const std::string METADB_DIR; - static const std::string CACHEDB_DIR; + static constexpr const char *MAINDB_DIR = "main"; + static constexpr const char *METADB_DIR = "meta"; + static constexpr const char *CACHEDB_DIR = "cache"; static constexpr const char *LOCAL_DATABASE_NAME = "local"; static constexpr const char *MULTI_VER_DATA_STORE = "multi_ver_data"; static constexpr const char *MULTI_VER_COMMIT_STORE = "commit_logs"; static constexpr const char *MULTI_VER_VALUE_STORE = "value_storage"; static constexpr const char *MULTI_VER_META_STORE = "meta_storage"; - static const std::string SINGLE_VER_DATA_STORE; - static const std::string SINGLE_VER_META_STORE; - static const std::string SINGLE_VER_CACHE_STORE; + static constexpr const char *SINGLE_VER_DATA_STORE = "gen_natural_store"; + static constexpr const char *SINGLE_VER_META_STORE = "meta"; + static constexpr const char *SINGLE_VER_CACHE_STORE = "cache"; static constexpr const char *SQLITE_URL_PRE = "file:"; static constexpr const char *DB_EXTENSION = ".db"; static constexpr const char *SQLITE_MEMDB_IDENTIFY = "?mode=memory&cache=shared"; static constexpr const char *SCHEMA_KEY = "schemaKey"; - static const std::string RELATIONAL_SCHEMA_KEY; - static const std::string RELATIONAL_TRACKER_SCHEMA_KEY; + static constexpr const char *RELATIONAL_SCHEMA_KEY = "relational_schema"; + static constexpr const char *RELATIONAL_TRACKER_SCHEMA_KEY = "relational_tracker_schema"; + static constexpr const char *RDB_KNOWLEDGE_SCHEMA_KEY = "rdbKnowledgeSchemaKey"; static constexpr const char *RD_KV_COLLECTION_MODE = "{\"mode\" : \"kv\"}"; static constexpr const char *RD_KV_HASH_COLLECTION_MODE = "{\"mode\" : \"kv\",\"indextype\" : \"hash\"}"; @@ -115,10 +117,11 @@ public: static constexpr const char *TRIGGER_REFERENCES_NEW = "NEW."; static constexpr const char *TRIGGER_REFERENCES_OLD = "OLD."; - static const std::string UPDATE_META_FUNC; + static constexpr const char *UPDATE_META_FUNC = "update_meta_within_trigger"; // Prefix Key in meta db static constexpr const char *DEVICEID_PREFIX_KEY = "deviceId"; + static constexpr const char *USERID_PREFIX_KEY = "userId"; static constexpr const char *QUERY_SYNC_PREFIX_KEY = "querySync"; static constexpr const char *DELETE_SYNC_PREFIX_KEY = "deleteSync"; @@ -154,12 +157,13 @@ public: static constexpr const int MAX_OBSERVER_COUNT = 8; // For relational - static const std::string SYSTEM_TABLE_PREFIX; + static constexpr const char *SYSTEM_TABLE_PREFIX = "naturalbase_rdb_"; static constexpr const char *RELATIONAL_PREFIX = "naturalbase_rdb_aux_"; static constexpr size_t RELATIONAL_PREFIX_SIZE = 20; - static const std::string TIMESTAMP_ALIAS; + static constexpr const char *TIMESTAMP_ALIAS = "naturalbase_rdb_aux_timestamp"; static constexpr const char *LOG_POSTFIX = "_log"; static constexpr const char *META_TABLE_POSTFIX = "metadata"; + static constexpr const char *KNOWLEDGE_TABLE_TYPE = "knowledge"; static constexpr const char *LOG_TABLE_VERSION_3 = "3.0"; static constexpr const char *LOG_TABLE_VERSION_5_1 = "5.01"; @@ -170,7 +174,7 @@ public: static constexpr const char *LOG_TABLE_VERSION_5_10 = "5.10"; // retain downloading asset in update trigger static constexpr const char *LOG_TABLE_VERSION_CURRENT = LOG_TABLE_VERSION_5_10; - static const std::string LOG_TABLE_VERSION_KEY; + static constexpr const char *LOG_TABLE_VERSION_KEY = "log_table_version"; static constexpr const char *REMOTE_DEVICE_SCHEMA_KEY_PREFIX = "remote_device_schema_"; @@ -200,6 +204,10 @@ public: static constexpr const char *KV_LOCAL_TABLE_NAME = "local_data"; static constexpr const char *ROWID = "rowid"; + + static constexpr const char *DEFAULT_USER = "default_user"; + + static constexpr const char *DISTRIBUTED_DEFAULT_APP_ID = "distributeddata"; }; } // namespace DistributedDB #endif // DISTRIBUTEDDB_CONSTANT_H diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h b/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h index ceb9841b..151dd7c2 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h @@ -189,6 +189,8 @@ constexpr const int E_DISTRIBUTED_SCHEMA_CHANGED = (E_BASE + 203); // Schema has constexpr const int E_TABLE_REFERENCE_CHANGED = (E_BASE + 204); // table reference is changed constexpr const int E_CLOUD_DISABLED = (E_BASE + 205); // The cloud switch has been turned off constexpr const int E_DISTRIBUTED_FIELD_DECREASE = (E_BASE + 206); // Sync fewer specified columns than last time +constexpr const int E_NO_TRUSTED_USER = (E_BASE + 207); // No trusted found before device sync +constexpr const int E_FEEDBACK_DB_CLOSING = (E_BASE + 208); // Db was closing feedback from remote device } // namespace DistributedDB #endif // DISTRIBUTEDDB_ERRNO_H diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_types.h b/kv_store/frameworks/libs/distributeddb/common/include/db_types.h index c6194dc6..f2eb264c 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_types.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_types.h @@ -183,5 +183,6 @@ struct DeviceTimeInfo { using ObserverAction = std::function; + } // namespace DistributedDB #endif // DISTRIBUTEDDB_TYPES_H diff --git a/kv_store/frameworks/libs/distributeddb/common/include/json_object.h b/kv_store/frameworks/libs/distributeddb/common/include/json_object.h index aa2b0a37..d742dab8 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/json_object.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/json_object.h @@ -75,7 +75,7 @@ public: int GetSubFieldPathAndType(const std::set &inPath, std::map &outSubPathType) const; // If inPath not refer to an array, return error. - int GetArraySize(const FieldPath &inPath, uint32_t &outSize) const; + int GetArraySize(const FieldPath &inPath, size_t &outSize) const; // If inPath not refer to an array, return error. If not all members are string or array type, return error. // If array-type member is empty, ignore. If not all members of the array-type member are string, return error. @@ -121,6 +121,9 @@ private: // create if path not exist int MoveToPath(const FieldPath &inPath, Json::Value *&exact, Json::Value *&nearest); + int JsonReaderParseInner(const std::unique_ptr &jsonReader, const char *begin, const char *end, + JSONCPP_STRING &errs); + static uint32_t maxNestDepth_; bool isValid_ = false; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/log_print.h b/kv_store/frameworks/libs/distributeddb/common/include/log_print.h index a7592f66..a4012d50 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/log_print.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/log_print.h @@ -33,9 +33,10 @@ public: LEVEL_ERROR, LEVEL_FATAL }; - + Logger() = default; virtual ~Logger() {}; static Logger *GetInstance(); + static void DeleteInstance(); static void RegisterLogger(Logger *logger); static void Log(Level level, const std::string &tag, const char *func, int line, const char *format, ...); diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/prepared_stmt.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/prepared_stmt.h index ddcdd9df..792eb184 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/relational/prepared_stmt.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/prepared_stmt.h @@ -43,8 +43,7 @@ public: int DeSerialize(Parcel &parcel); private: - static const int VERSION_1 = 1; - static const int CURRENT_VERSION = VERSION_1; + static const int CURRENT_VERSION = 1; ExecutorOperation opCode_ = ExecutorOperation::MIN_LIMIT; std::string sql_; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_row_data_set.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_row_data_set.h index 9a69db14..27376cec 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_row_data_set.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_row_data_set.h @@ -23,7 +23,7 @@ namespace DistributedDB { class RelationalRowDataSet { public: RelationalRowDataSet(); - virtual ~RelationalRowDataSet(); + ~RelationalRowDataSet(); RelationalRowDataSet(const RelationalRowDataSet &) = delete; RelationalRowDataSet &operator=(const RelationalRowDataSet &) = delete; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h index 3e664718..bf4afcc9 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h @@ -63,7 +63,8 @@ public: void SetReferenceProperty(const std::vector &referenceProperty); const std::vector &GetReferenceProperty() const; std::set GetSharedTableForChangeTable(std::set &changeTables) const; - std::set CompareReferenceProperty(const std::vector &others) const; + std::set CompareReferenceProperty(const std::vector &others, + bool &isRefNotSet) const; std::map> GetReachableRef(); std::map GetTableWeight(); @@ -77,6 +78,8 @@ public: std::vector GetSyncFieldInfo(const std::string &tableName, bool ignoreTableNonExist = true) const; DistributedTable GetDistributedTable(const std::string &table) const; + + std::map GetTableChangeStatus(const DistributedSchema &schema); private: int CompareAgainstSchemaObject(const std::string &inSchemaString, std::map &cmpRst) const; @@ -136,7 +139,7 @@ private: bool isValid_ = false; // set to true after parse success from string or add at least one relational table SchemaType schemaType_ = SchemaType::RELATIVE; // Default RELATIVE std::string schemaString_; // The minified and valid schemaString - std::string schemaVersion_ = SchemaConstant::SCHEMA_SUPPORT_VERSION_V2; // Default version 2.0 + std::string schemaVersion_ = std::string(SchemaConstant::SCHEMA_SUPPORT_VERSION_V2); // Default version 2.0 TableInfoMap tables_; TableInfoMap trackerTables_; std::vector referenceProperty_; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/table_info.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/table_info.h index 363cd74e..7d90ec51 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/relational/table_info.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/table_info.h @@ -30,6 +30,8 @@ namespace DistributedDB { using CompositeFields = std::vector; class FieldInfo { public: + FieldInfo() = default; + ~FieldInfo() = default; const std::string &GetFieldName() const; void SetFieldName(const std::string &fileName); const std::string &GetDataType() const; @@ -74,6 +76,8 @@ using FieldInfoMap = std::map using IndexInfoMap = std::map; class TableInfo { public: + TableInfo() = default; + ~TableInfo() = default; const std::string &GetTableName() const; const std::string &GetOriginTableName() const; bool GetSharedTableMark() const; @@ -139,6 +143,8 @@ public: std::vector GetSyncDistributedPk() const; const std::vector GetUniqueAndPkDefine() const; + + std::vector RemovePKCompositeFields(const std::vector &uniqueFields) const; private: void AddFieldDefineString(std::string &attrStr) const; void AddIndexDefineString(std::string &attrStr) const; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/tracker_table.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/tracker_table.h index e46e1e8f..22da2f28 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/relational/tracker_table.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/tracker_table.h @@ -30,7 +30,7 @@ enum class TriggerModeEnum; class TrackerTable { public: TrackerTable() = default; - virtual ~TrackerTable() {}; + ~TrackerTable() {}; std::string GetTableName() const; const std::set &GetTrackerColNames() const; @@ -49,6 +49,7 @@ public: const std::string GetTempTriggerName(TriggerMode::TriggerModeEnum mode) const; const std::string GetTempUpdateTriggerSql(bool incFlag = false) const; const std::string GetTempDeleteTriggerSql(bool incFlag = false) const; + const std::string GetTempUpdateLogCursorTriggerSql() const; void SetTableName(const std::string &tableName); void SetExtendNames(const std::set &colNames); void SetExtendName(const std::string &colName); @@ -58,13 +59,17 @@ public: bool IsChanging(const TrackerSchema &schema); int ReBuildTempTrigger(sqlite3 *db, TriggerMode::TriggerModeEnum mode, const AfterBuildAction &action); void SetTrackerAction(bool isTrackerAction); - + void SetTriggerObserver(bool isTriggerObserver); + void SetKnowledgeTable(bool isKnowledgeTable); + std::string GetOnChangeType() const; private: std::string tableName_; std::string extendColName_; std::set extendColNames_; std::set trackerColNames_; bool isTrackerAction_ = false; + bool isTriggerObserver_ = true; + bool isKnowledgeTable_ = false; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/common/include/schema_constant.h b/kv_store/frameworks/libs/distributeddb/common/include/schema_constant.h index 479a67fe..93f915bf 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/schema_constant.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/schema_constant.h @@ -17,46 +17,45 @@ #define SCHEMA_CONSTANT_H #include -#include // This header is supposed to be included only in source files. Do not include it in any header files. namespace DistributedDB { class SchemaConstant final { public: - static const std::string KEYWORD_SCHEMA_VERSION; - static const std::string KEYWORD_SCHEMA_MODE; - static const std::string KEYWORD_SCHEMA_DEFINE; - static const std::string KEYWORD_SCHEMA_INDEXES; - static const std::string KEYWORD_SCHEMA_SKIPSIZE; - static const std::string KEYWORD_SCHEMA_TYPE; - static const std::string KEYWORD_SCHEMA_TABLE; - static const std::string KEYWORD_INDEX; // For FlatBuffer-Schema - static const std::string KEYWORD_TABLE_MODE; + static constexpr const char *KEYWORD_SCHEMA_VERSION = "SCHEMA_VERSION"; + static constexpr const char *KEYWORD_SCHEMA_MODE = "SCHEMA_MODE"; + static constexpr const char *KEYWORD_SCHEMA_DEFINE = "SCHEMA_DEFINE"; + static constexpr const char *KEYWORD_SCHEMA_INDEXES = "SCHEMA_INDEXES"; + static constexpr const char *KEYWORD_SCHEMA_SKIPSIZE = "SCHEMA_SKIPSIZE"; + static constexpr const char *KEYWORD_SCHEMA_TYPE = "SCHEMA_TYPE"; + static constexpr const char *KEYWORD_SCHEMA_TABLE = "TABLES"; + static constexpr const char *KEYWORD_INDEX = "INDEX"; // For FlatBuffer-Schema + static constexpr const char *KEYWORD_TABLE_MODE = "TABLE_MODE"; - static const std::string KEYWORD_MODE_STRICT; - static const std::string KEYWORD_MODE_COMPATIBLE; + static constexpr const char *KEYWORD_MODE_STRICT = "STRICT"; + static constexpr const char *KEYWORD_MODE_COMPATIBLE = "COMPATIBLE"; - static const std::string KEYWORD_TYPE_BOOL; - static const std::string KEYWORD_TYPE_INTEGER; - static const std::string KEYWORD_TYPE_LONG; - static const std::string KEYWORD_TYPE_DOUBLE; - static const std::string KEYWORD_TYPE_STRING; - static const std::string KEYWORD_TYPE_BOOLEAN; + static constexpr const char *KEYWORD_TYPE_BOOL = "BOOL"; + static constexpr const char *KEYWORD_TYPE_INTEGER = "INTEGER"; + static constexpr const char *KEYWORD_TYPE_LONG = "LONG"; + static constexpr const char *KEYWORD_TYPE_DOUBLE = "DOUBLE"; + static constexpr const char *KEYWORD_TYPE_STRING = "STRING"; + static constexpr const char *KEYWORD_TYPE_BOOLEAN = "BOOLEAN"; - static const std::string KEYWORD_ATTR_NOT_NULL; - static const std::string KEYWORD_ATTR_DEFAULT; - static const std::string KEYWORD_ATTR_VALUE_NULL; - static const std::string KEYWORD_ATTR_VALUE_TRUE; - static const std::string KEYWORD_ATTR_VALUE_FALSE; + static constexpr const char *KEYWORD_ATTR_NOT_NULL = "NOT NULL"; + static constexpr const char *KEYWORD_ATTR_DEFAULT = "DEFAULT"; + static constexpr const char *KEYWORD_ATTR_VALUE_NULL = "null"; + static constexpr const char *KEYWORD_ATTR_VALUE_TRUE = "true"; + static constexpr const char *KEYWORD_ATTR_VALUE_FALSE = "false"; - static const std::string KEYWORD_TABLE_SPLIT_DEVICE; - static const std::string KEYWORD_TABLE_COLLABORATION; + static constexpr const char *KEYWORD_TABLE_SPLIT_DEVICE = "SPLIT_BY_DEVICE"; + static constexpr const char *KEYWORD_TABLE_COLLABORATION = "COLLABORATION"; - static const std::string KEYWORD_TYPE_RELATIVE; - static const std::string SCHEMA_SUPPORT_VERSION; - static const std::string SCHEMA_SUPPORT_VERSION_V2; - static const std::string SCHEMA_SUPPORT_VERSION_V2_1; - static const std::string SCHEMA_CURRENT_VERSION; + static constexpr const char *KEYWORD_TYPE_RELATIVE = "RELATIVE"; + static constexpr const char *SCHEMA_SUPPORT_VERSION = "1.0"; + static constexpr const char *SCHEMA_SUPPORT_VERSION_V2 = "2.0"; + static constexpr const char *SCHEMA_SUPPORT_VERSION_V2_1 = "2.1"; + static constexpr const char *SCHEMA_CURRENT_VERSION = SCHEMA_SUPPORT_VERSION_V2_1; static constexpr const char *REFERENCE_PROPERTY = "REFERENCE_PROPERTY"; static constexpr const char *SOURCE_TABLE_NAME = "SOURCE_TABLE_NAME"; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/schema_utils.h b/kv_store/frameworks/libs/distributeddb/common/include/schema_utils.h index e1aec19d..f9610033 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/schema_utils.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/schema_utils.h @@ -79,6 +79,8 @@ private: static int TransToString(const std::string &defaultContent, SchemaAttribute &outAttr); static int TransToBool(const std::string &defaultContent, SchemaAttribute &outAttr); + + static void TrimFiled(std::string &inString); }; } // namespace DistributedDB #endif // SCHEMA_UTILS_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/include/version.h b/kv_store/frameworks/libs/distributeddb/common/include/version.h index ca9d5d1b..d224e87c 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/version.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/version.h @@ -52,6 +52,7 @@ constexpr const uint32_t SOFTWARE_VERSION_RELEASE_10_0 = SOFTWARE_VERSION_BASE + constexpr const uint32_t SOFTWARE_VERSION_RELEASE_11_0 = SOFTWARE_VERSION_BASE + 11; // 11 for tenth released version constexpr const uint32_t SOFTWARE_VERSION_EARLIEST = SOFTWARE_VERSION_RELEASE_1_0; constexpr const uint32_t SOFTWARE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_11_0; +constexpr const uint32_t SOFTWARE_VERSION_MAX = UINT16_MAX; constexpr const int VERSION_INVALID = INT32_MAX; // Storage Related Version diff --git a/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp b/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp index 27721a64..0d9826e8 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp @@ -1039,9 +1039,9 @@ int AutoLaunch::GetAutoLaunchKVProperties(const AutoLaunchParam ¶m, propertiesPtr->SetIntProp(KvDBProperties::SECURITY_LABEL, param.option.secOption.securityLabel); propertiesPtr->SetIntProp(KvDBProperties::SECURITY_FLAG, param.option.secOption.securityFlag); } - propertiesPtr->SetBoolProp(KvDBProperties::COMPRESS_ON_SYNC, param.option.isNeedCompressOnSync); + propertiesPtr->SetBoolProp(DBProperties::COMPRESS_ON_SYNC, param.option.isNeedCompressOnSync); if (param.option.isNeedCompressOnSync) { - propertiesPtr->SetIntProp(KvDBProperties::COMPRESSION_RATE, + propertiesPtr->SetIntProp(DBProperties::COMPRESSION_RATE, ParamCheckUtils::GetValidCompressionRate(param.option.compressionRate)); } propertiesPtr->SetBoolProp(KvDBProperties::SYNC_DUAL_TUPLE_MODE, param.option.syncDualTupleMode); @@ -1071,6 +1071,11 @@ int AutoLaunch::GetAutoLaunchRelationProperties(const AutoLaunchParam ¶m, } propertiesPtr->SetCipherArgs(param.option.cipher, param.option.passwd, param.option.iterateTimes); } + propertiesPtr->SetBoolProp(DBProperties::COMPRESS_ON_SYNC, param.option.isNeedCompressOnSync); + if (param.option.isNeedCompressOnSync) { + propertiesPtr->SetIntProp(DBProperties::COMPRESSION_RATE, + ParamCheckUtils::GetValidCompressionRate(param.option.compressionRate)); + } return E_OK; } diff --git a/kv_store/frameworks/libs/distributeddb/common/src/cloud/assets_download_manager.cpp b/kv_store/frameworks/libs/distributeddb/common/src/cloud/assets_download_manager.cpp index c608ef2f..1f3ad794 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/cloud/assets_download_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/cloud/assets_download_manager.cpp @@ -15,7 +15,6 @@ #include "cloud/assets_download_manager.h" #include "cloud/cloud_db_constant.h" - #include "db_errno.h" #include "log_print.h" namespace DistributedDB { diff --git a/kv_store/frameworks/libs/distributeddb/common/src/concurrent_adapter.cpp b/kv_store/frameworks/libs/distributeddb/common/src/concurrent_adapter.cpp index 19198891..b0b99011 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/concurrent_adapter.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/concurrent_adapter.cpp @@ -62,6 +62,11 @@ void ConcurrentAdapter::AdapterAutoUnLock(ffrt::mutex &mutex) { mutex.unlock(); } + +void ConcurrentAdapter::Stop() +{ + ffrt::wait(); +} #else void ConcurrentAdapter::AdapterAutoLock(std::mutex &mutex) { diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp index e735fed7..36b6acc6 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp @@ -33,16 +33,9 @@ #include "query_sync_object.h" #include "hash.h" #include "runtime_context.h" -#include "value_hash_calc.h" namespace DistributedDB { namespace { - constexpr const int32_t HEAD_SIZE = 3; - constexpr const int32_t END_SIZE = 3; - constexpr const int32_t MIN_SIZE = HEAD_SIZE + END_SIZE + 3; - constexpr const char *REPLACE_CHAIN = "***"; - constexpr const char *DEFAULT_ANONYMOUS = "******"; - void RemoveFiles(const std::list &fileList, OS::FileType type) { for (const auto &item : fileList) { @@ -68,12 +61,10 @@ namespace { } } } - const std::string HEX_CHAR_MAP = "0123456789abcdef"; const std::string CAP_HEX_CHAR_MAP = "0123456789ABCDEF"; } static std::atomic_bool g_isGrdLoaded = false; -static std::mutex g_mutex; int DBCommon::CreateDirectory(const std::string &directory) { @@ -87,12 +78,6 @@ int DBCommon::CreateDirectory(const std::string &directory) return E_OK; } -void DBCommon::StringToVector(const std::string &src, std::vector &dst) -{ - dst.resize(src.size()); - dst.assign(src.begin(), src.end()); -} - void DBCommon::VectorToString(const std::vector &src, std::string &dst) { dst.clear(); @@ -142,57 +127,6 @@ void DBCommon::PrintHexVector(const std::vector &data, int line, const return; } -std::string DBCommon::TransferHashString(const std::string &devName) -{ - if (devName.empty()) { - return ""; - } - std::vector devVect(devName.begin(), devName.end()); - std::vector hashVect; - int errCode = CalcValueHash(devVect, hashVect); - if (errCode != E_OK) { - return ""; - } - - return std::string(hashVect.begin(), hashVect.end()); -} - -std::string DBCommon::TransferStringToHex(const std::string &origStr) -{ - if (origStr.empty()) { - return ""; - } - - std::string tmp; - for (auto item : origStr) { - unsigned char currentByte = static_cast(item); - tmp.push_back(HEX_CHAR_MAP[currentByte >> 4]); // high 4 bits to one hex. - tmp.push_back(HEX_CHAR_MAP[currentByte & 0x0F]); // low 4 bits to one hex. - } - return tmp; -} - -int DBCommon::CalcValueHash(const std::vector &value, std::vector &hashValue) -{ - ValueHashCalc hashCalc; - int errCode = hashCalc.Initialize(); - if (errCode != E_OK) { - return -E_INTERNAL_ERROR; - } - - errCode = hashCalc.Update(value); - if (errCode != E_OK) { - return -E_INTERNAL_ERROR; - } - - errCode = hashCalc.GetResult(hashValue); - if (errCode != E_OK) { - return -E_INTERNAL_ERROR; - } - - return E_OK; -} - int DBCommon::CreateStoreDirectory(const std::string &directory, const std::string &identifierName, const std::string &subDir, bool isCreate) { @@ -346,19 +280,6 @@ std::string DBCommon::StringMasking(const std::string &oriStr, size_t remain) return oriStr; } -std::string DBCommon::StringMiddleMasking(const std::string &name) -{ - if (name.length() <= HEAD_SIZE) { - return DEFAULT_ANONYMOUS; - } - - if (name.length() < MIN_SIZE) { - return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN); - } - - return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE)); -} - std::string DBCommon::GetDistributedTableName(const std::string &device, const std::string &tableName) { if (!RuntimeContext::GetInstance()->ExistTranslateDevIdCallback()) { @@ -399,57 +320,6 @@ void DBCommon::GetDeviceFromName(const std::string &deviceTableName, std::string } } -std::string DBCommon::TrimSpace(const std::string &input) -{ - std::string res; - res.reserve(input.length()); - bool isPreSpace = true; - for (char c : input) { - if (std::isspace(c)) { - isPreSpace = true; - } else { - if (!res.empty() && isPreSpace) { - res += ' '; - } - res += c; - isPreSpace = false; - } - } - res.shrink_to_fit(); - return res; -} - -void DBCommon::RTrim(std::string &oriString) -{ - if (oriString.empty()) { - return; - } - oriString.erase(oriString.find_last_not_of(" ") + 1); -} - -namespace { -bool CharIn(char c, const std::string &pattern) -{ - return std::any_of(pattern.begin(), pattern.end(), [c] (char p) { - return c == p; - }); -} -} - -bool DBCommon::HasConstraint(const std::string &sql, const std::string &keyWord, const std::string &prePattern, - const std::string &nextPattern) -{ - size_t pos = 0; - while ((pos = sql.find(keyWord, pos)) != std::string::npos) { - if (pos >= 1 && CharIn(sql[pos - 1], prePattern) && ((pos + keyWord.length() == sql.length()) || - ((pos + keyWord.length() < sql.length()) && CharIn(sql[pos + keyWord.length()], nextPattern)))) { - return true; - } - pos++; - } - return false; -} - bool DBCommon::IsSameCipher(CipherType srcType, CipherType inputType) { // At present, the default type is AES-256-GCM. @@ -464,33 +334,6 @@ bool DBCommon::IsSameCipher(CipherType srcType, CipherType inputType) return false; } -std::string DBCommon::ToLowerCase(const std::string &str) -{ - std::string res(str.length(), ' '); - std::transform(str.begin(), str.end(), res.begin(), ::tolower); - return res; -} - -std::string DBCommon::ToUpperCase(const std::string &str) -{ - std::string res(str.length(), ' '); - std::transform(str.begin(), str.end(), res.begin(), ::toupper); - return res; -} - -bool DBCommon::CaseInsensitiveCompare(const std::string &first, const std::string &second) -{ - return (strcasecmp(first.c_str(), second.c_str()) == 0); -} - -bool DBCommon::CheckIsAlnumOrUnderscore(const std::string &text) -{ - auto iter = std::find_if_not(text.begin(), text.end(), [](char c) { - return (std::isalnum(c) || c == '_'); - }); - return iter == text.end(); -} - bool DBCommon::CheckQueryWithoutMultiTable(const Query &query) { if (!QuerySyncObject::GetQuerySyncObject(query).empty()) { @@ -763,21 +606,28 @@ uint64_t DBCommon::EraseBit(uint64_t origin, uint64_t eraseBit) return origin & (~eraseBit); } -void DBCommon::LoadGrdLib(void) +void *DBCommon::LoadGrdLib(void) { - std::lock_guard lock(g_mutex); - static std::once_flag loadOnceFlag; - std::call_once(loadOnceFlag, []() { #ifndef _WIN32 - if (!g_isGrdLoaded) { - if (dlopen("libarkdata_db_core.z.so", RTLD_LAZY) != NULL) { - g_isGrdLoaded = true; - } else { - LOGW("[DBCommon] unable to load grd lib, errno: %d, %s", errno, dlerror()); - } - } + auto handle = dlopen("libarkdata_db_core.z.so", RTLD_LAZY); + if (handle == nullptr) { + LOGW("[DBCommon] unable to load grd lib, errno: %d, %s", errno, dlerror()); + return nullptr; + } + return handle; +#else + return nullptr; +#endif +} + +void DBCommon::UnLoadGrdLib(void *handle) +{ +#ifndef _WIN32 + if (handle == nullptr) { + return; + } + dlclose(handle); #endif - }); } bool DBCommon::IsGrdLibLoaded(void) @@ -804,11 +654,6 @@ bool DBCommon::CheckCloudSyncConfigValid(const CloudSyncConfig &config) return true; } -std::string DBCommon::GetCursorKey(const std::string &tableName) -{ - return std::string(DBConstant::RELATIONAL_PREFIX) + "cursor_" + ToLowerCase(tableName); -} - bool DBCommon::ConvertToUInt64(const std::string &str, uint64_t &value) { auto [ptr, errCode] = std::from_chars(str.data(), str.data() + str.size(), value); diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_common_client.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_common_client.cpp new file mode 100644 index 00000000..7312f3ad --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/common/src/db_common_client.cpp @@ -0,0 +1,182 @@ +/* + * 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 "db_common.h" +#include "value_hash_calc.h" + +namespace DistributedDB { +namespace { + constexpr const int32_t HEAD_SIZE = 3; + constexpr const int32_t END_SIZE = 3; + constexpr const int32_t MIN_SIZE = HEAD_SIZE + END_SIZE + 3; + constexpr const char *REPLACE_CHAIN = "***"; + constexpr const char *DEFAULT_ANONYMOUS = "******"; + + const std::string HEX_CHAR_MAP = "0123456789abcdef"; +} + +void DBCommon::StringToVector(const std::string &src, std::vector &dst) +{ + dst.resize(src.size()); + dst.assign(src.begin(), src.end()); +} + +std::string DBCommon::StringMiddleMasking(const std::string &name) +{ + if (name.length() <= HEAD_SIZE) { + return DEFAULT_ANONYMOUS; + } + + if (name.length() < MIN_SIZE) { + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN); + } + + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE)); +} + +void DBCommon::RTrim(std::string &oriString) +{ + if (oriString.empty()) { + return; + } + oriString.erase(oriString.find_last_not_of(" ") + 1); +} + +bool DBCommon::CheckIsAlnumOrUnderscore(const std::string &text) +{ + auto iter = std::find_if_not(text.begin(), text.end(), [](char c) { + return (std::isalnum(c) || c == '_'); + }); + return iter == text.end(); +} + +std::string DBCommon::ToLowerCase(const std::string &str) +{ + std::string res(str.length(), ' '); + std::transform(str.begin(), str.end(), res.begin(), ::tolower); + return res; +} + +std::string DBCommon::ToUpperCase(const std::string &str) +{ + std::string res(str.length(), ' '); + std::transform(str.begin(), str.end(), res.begin(), ::toupper); + return res; +} + +int DBCommon::CalcValueHash(const std::vector &value, std::vector &hashValue) +{ + ValueHashCalc hashCalc; + int errCode = hashCalc.Initialize(); + if (errCode != E_OK) { + return -E_INTERNAL_ERROR; + } + + errCode = hashCalc.Update(value); + if (errCode != E_OK) { + return -E_INTERNAL_ERROR; + } + + errCode = hashCalc.GetResult(hashValue); + if (errCode != E_OK) { + return -E_INTERNAL_ERROR; + } + + return E_OK; +} + + +namespace { +bool CharIn(char c, const std::string &pattern) +{ + return std::any_of(pattern.begin(), pattern.end(), [c] (char p) { + return c == p; + }); +} +} +bool DBCommon::HasConstraint(const std::string &sql, const std::string &keyWord, const std::string &prePattern, + const std::string &nextPattern) +{ + size_t pos = 0; + while ((pos = sql.find(keyWord, pos)) != std::string::npos) { + if (pos >= 1 && CharIn(sql[pos - 1], prePattern) && ((pos + keyWord.length() == sql.length()) || + ((pos + keyWord.length() < sql.length()) && CharIn(sql[pos + keyWord.length()], nextPattern)))) { + return true; + } + pos++; + } + return false; +} + +std::string DBCommon::TransferStringToHex(const std::string &origStr) +{ + if (origStr.empty()) { + return ""; + } + + std::string tmp; + for (auto item : origStr) { + unsigned char currentByte = static_cast(item); + tmp.push_back(HEX_CHAR_MAP[currentByte >> 4]); // high 4 bits to one hex. + tmp.push_back(HEX_CHAR_MAP[currentByte & 0x0F]); // low 4 bits to one hex. + } + return tmp; +} + +std::string DBCommon::GetCursorKey(const std::string &tableName) +{ + return std::string(DBConstant::RELATIONAL_PREFIX) + "cursor_" + ToLowerCase(tableName); +} + +std::string DBCommon::TrimSpace(const std::string &input) +{ + std::string res; + res.reserve(input.length()); + bool isPreSpace = true; + for (char c : input) { + if (std::isspace(c)) { + isPreSpace = true; + } else { + if (!res.empty() && isPreSpace) { + res += ' '; + } + res += c; + isPreSpace = false; + } + } + res.shrink_to_fit(); + return res; +} + +std::string DBCommon::TransferHashString(const std::string &devName) +{ + if (devName.empty()) { + return ""; + } + std::vector devVect(devName.begin(), devName.end()); + std::vector hashVect; + int errCode = CalcValueHash(devVect, hashVect); + if (errCode != E_OK) { + return ""; + } + + return std::string(hashVect.begin(), hashVect.end()); +} + +bool DBCommon::CaseInsensitiveCompare(const std::string &first, const std::string &second) +{ + return (strcasecmp(first.c_str(), second.c_str()) == 0); +} +} // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp deleted file mode 100644 index b24c170d..00000000 --- a/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2021 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 "db_constant.h" - -namespace DistributedDB { -const std::string DBConstant::MULTI_SUB_DIR = "multi_ver"; -const std::string DBConstant::SINGLE_SUB_DIR = "single_ver"; -const std::string DBConstant::LOCAL_SUB_DIR = "local"; -const std::string DBConstant::MAINDB_DIR = "main"; -const std::string DBConstant::METADB_DIR = "meta"; -const std::string DBConstant::CACHEDB_DIR = "cache"; -const std::string DBConstant::SYSTEM_TABLE_PREFIX = "naturalbase_rdb_"; -const std::string DBConstant::RELATIONAL_SCHEMA_KEY = "relational_schema"; -const std::string DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY = "relational_tracker_schema"; -const std::string DBConstant::LOG_TABLE_VERSION_KEY = "log_table_version"; -const std::string DBConstant::TIMESTAMP_ALIAS = "naturalbase_rdb_aux_timestamp"; -const std::string DBConstant::UPDATE_META_FUNC = "update_meta_within_trigger"; -const std::string DBConstant::SINGLE_VER_DATA_STORE = "gen_natural_store"; -const std::string DBConstant::SINGLE_VER_META_STORE = "meta"; -const std::string DBConstant::SINGLE_VER_CACHE_STORE = "cache"; -} diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp index a207b4da..c06b461b 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp @@ -126,25 +126,25 @@ void DBDfxAdapter::ReportBehavior(const ReportTask &reportTask) void DBDfxAdapter::StartTrace(const std::string &action) { - ::StartTrace(HITRACE_LABEL, action); + ::StartTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_LABEL, action.c_str()); } void DBDfxAdapter::FinishTrace() { - ::FinishTrace(HITRACE_LABEL); + ::FinishTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_LABEL); } void DBDfxAdapter::StartTracing() { #ifdef TRACE_SQLITE_EXECUTE - ::StartTrace(HITRACE_LABEL, SQLITE_EXECUTE); + ::StartTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_LABEL, SQLITE_EXECUTE.c_str()); #endif } void DBDfxAdapter::FinishTracing() { #ifdef TRACE_SQLITE_EXECUTE - ::FinishTrace(HITRACE_LABEL); + ::FinishTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_LABEL); #endif } diff --git a/kv_store/frameworks/libs/distributeddb/common/src/json_object.cpp b/kv_store/frameworks/libs/distributeddb/common/src/json_object.cpp index 49c9616c..caf7ce2d 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/json_object.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/json_object.cpp @@ -112,6 +112,16 @@ JsonObject::JsonObject(const Json::Value &value) : isValid_(true), value_(value) { } +int JsonObject::JsonReaderParseInner(const std::unique_ptr &jsonReader, const char *begin, + const char *end, JSONCPP_STRING &errs) +{ + if (!jsonReader->parse(begin, end, &value_, &errs)) { + value_ = Json::Value(); + return -E_JSON_PARSE_FAIL; + } + return E_OK; +} + int JsonObject::Parse(const std::string &inString) { // The jsoncpp lib parser in strict mode will still regard root type jsonarray as valid, but we require jsonobject @@ -126,7 +136,6 @@ int JsonObject::Parse(const std::string &inString) errCode, nestDepth, maxNestDepth_); return -E_JSON_PARSE_FAIL; } -#ifdef JSONCPP_USE_BUILDER JSONCPP_STRING errs; Json::CharReaderBuilder builder; Json::CharReaderBuilder::strictMode(&builder.settings_); @@ -136,19 +145,11 @@ int JsonObject::Parse(const std::string &inString) auto begin = reinterpret_cast(inString.c_str()); auto end = reinterpret_cast(inString.c_str() + inString.length()); - if (!jsonReader->parse(begin, end, &value_, &errs)) { - value_ = Json::Value(); - LOGE("[Json][Parse] Parse string to JsonValue fail, reason=%s.", errs.c_str()); - return -E_JSON_PARSE_FAIL; - } -#else - Json::Reader reader(Json::Features::strictMode()); - if (!reader.parse(inString, value_, false)) { - value_ = Json::Value(); - LOGE("[Json][Parse] Parse string to JsonValue fail, reason=%s.", reader.getFormattedErrorMessages().c_str()); - return -E_JSON_PARSE_FAIL; + errCode = JsonReaderParseInner(jsonReader, begin, end, errs); + if (errCode != E_OK) { + LOGE("[Json][Parse] Parse string to JsonValue fail"); + return errCode; } -#endif // The jsoncpp lib parser in strict mode will still regard root type jsonarray as valid, but we require jsonobject if (value_.type() != Json::ValueType::objectValue) { value_ = Json::Value(); @@ -183,7 +184,6 @@ int JsonObject::Parse(const uint8_t *dataBegin, const uint8_t *dataEnd) errCode, nestDepth, maxNestDepth_); return -E_JSON_PARSE_FAIL; } -#ifdef JSONCPP_USE_BUILDER std::string jsonStr(dataBegin, dataEnd); auto begin = jsonStr.c_str(); auto end = jsonStr.c_str() + jsonStr.size(); @@ -195,22 +195,11 @@ int JsonObject::Parse(const uint8_t *dataBegin, const uint8_t *dataEnd) builder[JSON_CONFIG_REJECT_DUP_KEYS] = false; std::unique_ptr const jsonReader(builder.newCharReader()); // The endDoc parameter of reader::parse refer to the byte after the string itself - if (!jsonReader->parse(begin, end, &value_, &errs)) { - value_ = Json::Value(); - LOGE("[Json][Parse] Parse dataRange to JsonValue fail, reason=%s.", errs.c_str()); - return -E_JSON_PARSE_FAIL; - } -#else - Json::Reader reader(Json::Features::strictMode()); - auto begin = reinterpret_cast(dataBegin); - auto end = reinterpret_cast(dataEnd); - // The endDoc parameter of reader::parse refer to the byte after the string itself - if (!reader.parse(begin, end, value_, false)) { - value_ = Json::Value(); - LOGE("[Json][Parse] Parse dataRange to JsonValue fail, reason=%s.", reader.getFormattedErrorMessages().c_str()); - return -E_JSON_PARSE_FAIL; + errCode = JsonReaderParseInner(jsonReader, begin, end, errs); + if (errCode != E_OK) { + LOGE("[Json][Parse] Parse dataRange to JsonValue fail"); + return errCode; } -#endif // The jsoncpp lib parser in strict mode will still regard root type jsonarray as valid, but we require jsonobject if (value_.type() != Json::ValueType::objectValue) { value_ = Json::Value(); @@ -390,7 +379,7 @@ int JsonObject::GetSubFieldPathAndType(const std::set &inPath, return E_OK; } -int JsonObject::GetArraySize(const FieldPath &inPath, uint32_t &outSize) const +int JsonObject::GetArraySize(const FieldPath &inPath, size_t &outSize) const { if (!isValid_) { LOGE("[Json][GetArraySize] Not Valid Yet."); diff --git a/kv_store/frameworks/libs/distributeddb/common/src/log_print.cpp b/kv_store/frameworks/libs/distributeddb/common/src/log_print.cpp index 372ea9b8..e1ca3dab 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/log_print.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/log_print.cpp @@ -27,6 +27,8 @@ namespace DistributedDB { Logger *Logger::logHandler = nullptr; const std::string Logger::PRIVATE_TAG = "s{private}"; +static std::mutex g_logInstanceLock; +static std::atomic g_logInstance = nullptr; class HiLogger : public Logger { public: @@ -65,17 +67,26 @@ public: Logger *Logger::GetInstance() { - static std::mutex logInstanceLock; - static std::atomic logInstance = nullptr; // For Double-Checked Locking, we need check logInstance twice - if (logInstance == nullptr) { - std::lock_guard lock(logInstanceLock); - if (logInstance == nullptr) { + if (g_logInstance == nullptr) { + std::lock_guard lock(g_logInstanceLock); + if (g_logInstance == nullptr) { // Here, we new logInstance to print log, if new failed, we can do nothing. - logInstance = new (std::nothrow) HiLogger; + g_logInstance = new (std::nothrow) HiLogger; } } - return logInstance; + return g_logInstance; +} + +void Logger::DeleteInstance() +{ + std::lock_guard lock(g_logInstanceLock); + if (g_logInstance == nullptr) { + return; + } + delete g_logInstance.load(); + g_logInstance = nullptr; + logHandler = nullptr; } void Logger::RegisterLogger(Logger *logger) diff --git a/kv_store/frameworks/libs/distributeddb/common/src/param_check_utils.cpp b/kv_store/frameworks/libs/distributeddb/common/src/param_check_utils.cpp index 5fdf237a..868448d1 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/param_check_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/param_check_utils.cpp @@ -211,24 +211,16 @@ uint8_t ParamCheckUtils::GetValidCompressionRate(uint8_t compressionRate) { // Valid when between 1 and 100. When compressionRate is invalid, change it to default rate. if (compressionRate < 1 || compressionRate > DBConstant::DEFAULT_COMPTRESS_RATE) { - LOGD("Invalid compression rate:%" PRIu8, compressionRate); + LOGW("Invalid compression rate:%" PRIu8, compressionRate); compressionRate = DBConstant::DEFAULT_COMPTRESS_RATE; } return compressionRate; } -bool ParamCheckUtils::CheckRelationalTableName(const std::string &tableName) -{ - if (!DBCommon::CheckIsAlnumOrUnderscore(tableName)) { - return false; - } - return tableName.compare(0, DBConstant::SYSTEM_TABLE_PREFIX.size(), DBConstant::SYSTEM_TABLE_PREFIX) != 0; -} - bool ParamCheckUtils::CheckTableReference(const std::vector &tableReferenceProperty) { if (tableReferenceProperty.empty()) { - LOGI("[CheckTableReference] tableReferenceProperty is empty"); + LOGI("[CheckTableReference] empty"); return true; } diff --git a/relational_store/frameworks/native/gdb/src/transaction.cpp b/kv_store/frameworks/libs/distributeddb/common/src/param_check_utils_client.cpp similarity index 57% rename from relational_store/frameworks/native/gdb/src/transaction.cpp rename to kv_store/frameworks/libs/distributeddb/common/src/param_check_utils_client.cpp index f3e2eedb..b813ff76 100644 --- a/relational_store/frameworks/native/gdb/src/transaction.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/param_check_utils_client.cpp @@ -12,21 +12,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "gdb_errors.h" -#include "gdb_transaction.h" -namespace OHOS::DistributedDataAip { -std::pair> Transaction::Create(std::shared_ptr conn) -{ - if (creator_ != nullptr) { - return creator_(std::move(conn)); - } - return { E_ERROR, nullptr }; -} +#include "param_check_utils.h" -int32_t Transaction::RegisterCreator(Creator creator) +#include "db_common.h" + +namespace DistributedDB { +bool ParamCheckUtils::CheckRelationalTableName(const std::string &tableName) { - creator_ = std::move(creator); - return E_OK; + if (!DBCommon::CheckIsAlnumOrUnderscore(tableName)) { + return false; + } + return tableName.compare(0, strlen(DBConstant::SYSTEM_TABLE_PREFIX), DBConstant::SYSTEM_TABLE_PREFIX) != 0; } -} // namespace OHOS::DistributedDataAip +} // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp b/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp index 7fe6fd38..788376b3 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp @@ -117,10 +117,8 @@ int MakeDBDirectory(const std::string &directory) { int errCode = mkdir(directory.c_str()); if (errCode < 0) { - // 3 means one-third - std::string str = directory.length() == 0 ? "empty directory path" : - directory.substr(0, directory.length() / 3) + "*****" + directory.substr((2 * directory.length()) / 3); - LOGE("[MakeDir] Make directory fail:%d, directory path: %s", errno, str.c_str()); + LOGE("[MakeDir] Make directory fail:%d, %s", errno, + directory.empty() ? "empty directory path" : "directory path error"); return -E_SYSTEM_API_FAIL; } return E_OK; @@ -129,10 +127,10 @@ int MakeDBDirectory(const std::string &directory) int RemoveDBDirectory(const std::string &directory) { #ifdef DB_DEBUG_ENV - LOGD("---> remove db directory: %s", directory.c_str()); + LOGD("---> remove db directory"); #endif int ret = rmdir(directory.c_str()); - LOGI("CheckPathExistence %s ret:%d error %d", directory.c_str(), ret, errno); + LOGI("CheckPathExistence ret:%d error %d", ret, errno); return ret; } @@ -239,13 +237,12 @@ static int GetFilePathAttr(const std::string &topPath, const std::string &relati std::string findPath = std::string(topPath) + "\\*.*"; intptr_t handle = _findfirst(findPath.c_str(), &file); if (handle < 0) { - LOGE("Open dir error:%s %d.", topPath.c_str(), errno); + LOGE("Open dir error: %d.", errno); return -E_INVALID_PATH; } int errCode = E_OK; std::string fileAbsName; struct _stat64 fileStat; - LOGE("find first file %s %s relativePath %s", topPath.c_str(), file.name, relativePath.c_str()); FileAttr fileAttr; do { @@ -260,7 +257,7 @@ static int GetFilePathAttr(const std::string &topPath, const std::string &relati fileAbsName = topPath + "/" + file.name; errCode = _stat64(fileAbsName.c_str(), &fileStat); if (errCode != 0) { - LOGE("[GetFileAttr]Get file stat failed, %s error = %d.", fileAbsName.c_str(), errno); + LOGE("[GetFileAttr]Get file stat failed, error = %d.", errCode); errCode = -E_INVALID_PATH; break; } @@ -269,20 +266,15 @@ static int GetFilePathAttr(const std::string &topPath, const std::string &relati } fileAttr.fileLen = static_cast(fileStat.st_size); files.push_back(fileAttr); - LOGE("find fileAbsName file %s %s %d relativePath %s", topPath.c_str(), file.name, - file.attrib, relativePath.c_str()); if (fileAttr.fileType == PATH) { errCode = GetFilePathAttr(fileAbsName, relativePath + file.name + "/", files, isNeedAllPath); if (errCode != E_OK) { - LOGE("[GetFileAttr]GetFilePathAttr finish, %s error = %d.", topPath.c_str(), errCode); - printf("GetFilePathAttr the finish %s error:%d\n", topPath.c_str(), errCode); + LOGE("[GetFileAttr]GetFilePathAttr failed, error = %d.", errCode); break; } } } while (_findnext(handle, &file) == 0); _findclose(handle); - LOGE("[GetFileAttr]GetFilePathAttr finish, %s error = %d.", topPath.c_str(), errCode); - printf("GetFilePathAttr the finish end %s error:%d\n", topPath.c_str(), errCode); return errCode; } @@ -437,10 +429,8 @@ int MakeDBDirectory(const std::string &directory) { int errCode = mkdir(directory.c_str(), (S_IRWXU | S_IRWXG)); // The permission is 770 for linux based os if (errCode < 0) { - // 3 means one-third - std::string str = directory.length() == 0 ? "empty directory path" : - directory.substr(0, directory.length() / 3) + "*****" + directory.substr((2 * directory.length()) / 3); - LOGE("[MakeDir] Make directory fail:%d, directory path: %s", errno, str.c_str()); + LOGE("[MakeDir] Make directory fail:%d, %s", errno, + directory.empty() ? "empty directory path" : "directory path error"); return -E_SYSTEM_API_FAIL; } return E_OK; diff --git a/kv_store/frameworks/libs/distributeddb/common/src/relational/prepared_stmt.cpp b/kv_store/frameworks/libs/distributeddb/common/src/relational/prepared_stmt.cpp index da455627..ff26de01 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/relational/prepared_stmt.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/relational/prepared_stmt.cpp @@ -111,33 +111,30 @@ int PreparedStmt::DeSerialize(Parcel &parcel) return -E_PARSE_FAIL; } - // VERSION 1 - if (version >= VERSION_1) { - // opcode - int opCode = 0; - (void)parcel.ReadInt(opCode); - if (parcel.IsError() || opCode <= MIN_LIMIT || opCode >= MAX_LIMIT) { - return -E_PARSE_FAIL; - } - opCode_ = static_cast(opCode); + // opcode + int opCode = 0; + (void)parcel.ReadInt(opCode); + if (parcel.IsError() || opCode <= MIN_LIMIT || opCode >= MAX_LIMIT) { + return -E_PARSE_FAIL; + } + opCode_ = static_cast(opCode); - // sql - (void)parcel.ReadString(sql_); + // sql + (void)parcel.ReadString(sql_); - // bindArgs - int argsCount = 0; - (void)parcel.ReadInt(argsCount); - if (parcel.IsError() || argsCount < 0 || argsCount > static_cast(DBConstant::MAX_SQL_ARGS_COUNT)) { + // bindArgs + int argsCount = 0; + (void)parcel.ReadInt(argsCount); + if (parcel.IsError() || argsCount < 0 || argsCount > static_cast(DBConstant::MAX_SQL_ARGS_COUNT)) { + return -E_PARSE_FAIL; + } + for (int i = 0; i < argsCount; ++i) { + std::string bindArg; + (void)parcel.ReadString(bindArg); + if (parcel.IsError()) { return -E_PARSE_FAIL; } - for (int i = 0; i < argsCount; ++i) { - std::string bindArg; - (void)parcel.ReadString(bindArg); - if (parcel.IsError()) { - return -E_PARSE_FAIL; - } - bindArgs_.emplace_back(std::move(bindArg)); - } + bindArgs_.emplace_back(std::move(bindArg)); } parcel.EightByteAlign(); diff --git a/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp b/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp index f555ad2d..d274ac22 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp @@ -279,16 +279,17 @@ std::set RelationalSchemaObject::GetSharedTableForChangeTable(std:: } std::set RelationalSchemaObject::CompareReferenceProperty( - const std::vector &others) const + const std::vector &others, bool &isRefNotSet) const { std::set changeTables; + isRefNotSet = referenceProperty_.empty(); PropertyCompare(referenceProperty_, others, changeTables); PropertyCompare(others, referenceProperty_, changeTables); if (!changeTables.empty()) { // get shared tables std::set sharedTables = GetSharedTableForChangeTable(changeTables); changeTables.insert(sharedTables.begin(), sharedTables.end()); } - LOGI("[CompareReferenceProperty] changeTables size = %zu", changeTables.size()); + LOGI("[CompareReferenceProperty] size = %zu", changeTables.size()); return changeTables; } @@ -366,7 +367,7 @@ int GetMemberFromJsonObject(const JsonObject &inJsonObject, const std::string &f { if (!inJsonObject.IsFieldPathExist(FieldPath {fieldName})) { if (isNecessary) { - LOGE("[RelationalSchema][Parse] Get schema %s not exist. isNecessary: %d", fieldName.c_str(), isNecessary); + LOGE("[RelationalSchema][Parse] Get schema not exist. isNecessary: %d", isNecessary); return -E_SCHEMA_PARSE_FAIL; } return -E_NOT_FOUND; @@ -375,19 +376,19 @@ int GetMemberFromJsonObject(const JsonObject &inJsonObject, const std::string &f FieldType fieldType; int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {fieldName}, fieldType); if (errCode != E_OK) { - LOGE("[RelationalSchema][Parse] Get schema %s fieldType failed: %d.", fieldName.c_str(), errCode); + LOGE("[RelationalSchema][Parse] Get schema fieldType failed: %d.", errCode); return -E_SCHEMA_PARSE_FAIL; } if (fieldType != expectType) { - LOGE("[RelationalSchema][Parse] Expect %s fieldType %d but: %d.", fieldName.c_str(), + LOGE("[RelationalSchema][Parse] Expect fieldType %d but: %d.", static_cast(expectType), static_cast(fieldType)); return -E_SCHEMA_PARSE_FAIL; } errCode = inJsonObject.GetFieldValueByFieldPath(FieldPath {fieldName}, fieldValue); if (errCode != E_OK) { - LOGE("[RelationalSchema][Parse] Get schema %s value failed: %d.", fieldName.c_str(), errCode); + LOGE("[RelationalSchema][Parse] Get schema value failed: %d.", errCode); return -E_SCHEMA_PARSE_FAIL; } return E_OK; @@ -1520,5 +1521,25 @@ DistributedTable RelationalSchemaObject::GetDistributedTable(const std::string & } return *match; } + +std::map RelationalSchemaObject::GetTableChangeStatus(const DistributedSchema &schema) +{ + std::map res; + std::map, CaseInsensitiveComparator> tableSchema; + for (const auto &table : dbSchema_.tables) { + tableSchema[table.tableName] = table.fields; + } + for (const auto &table : schema.tables) { + if (tableSchema.find(table.tableName) == tableSchema.end()) { + res[table.tableName] = true; + continue; + } + if (CheckDistributedFieldChange(tableSchema[table.tableName], table.fields)) { + res[table.tableName] = true; + continue; + } + } + return res; +} } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/src/relational/table_info.cpp b/kv_store/frameworks/libs/distributeddb/common/src/relational/table_info.cpp index 6a644e60..99f9ce13 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/relational/table_info.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/relational/table_info.cpp @@ -290,6 +290,11 @@ const std::vector &TableInfo::GetFieldInfos() const if (!fieldInfos_.empty() && fieldInfos_.size() == fields_.size()) { return fieldInfos_; } + if (fields_.size() > DBConstant::MAX_FIELD_NUM) { + LOGE("The number of fields is too large: %zu.", fields_.size()); + fieldInfos_.clear(); + return fieldInfos_; + } fieldInfos_.resize(fields_.size()); if (fieldInfos_.size() != fields_.size()) { LOGE("GetField error, alloc memory failed."); @@ -566,15 +571,34 @@ int TableInfo::CompareCompositeFields(const CompositeFields &local, const Compos return -E_RELATIONAL_TABLE_EQUAL; } +std::vector TableInfo::RemovePKCompositeFields(const std::vector &uniqueFields) const +{ + std::vector uniqueDefines; + for (const auto &compositeFields : uniqueFields) { + bool hasPrimaryKey = false; + for (const auto &fieldName : compositeFields) { + if (IsPrimaryKey(fieldName)) { + hasPrimaryKey = true; + break; + } + } + if (!hasPrimaryKey) { + uniqueDefines.push_back(compositeFields); + } + } + return uniqueDefines; +} + int TableInfo::CompareWithTableUnique(const std::vector &inTableUnique) const { - if (uniqueDefines_.size() != inTableUnique.size()) { + std::vector uniqueDefines = RemovePKCompositeFields(uniqueDefines_); + std::vector curTableUnique = RemovePKCompositeFields(inTableUnique); + if (uniqueDefines.size() != curTableUnique.size()) { return -E_RELATIONAL_TABLE_INCOMPATIBLE; } - - auto itLocal = uniqueDefines_.begin(); - auto itInTable = inTableUnique.begin(); - while (itLocal != uniqueDefines_.end()) { + auto itLocal = uniqueDefines.begin(); + auto itInTable = curTableUnique.begin(); + while (itLocal != uniqueDefines.end()) { if (CompareCompositeFields(*itLocal, *itInTable) != -E_RELATIONAL_TABLE_EQUAL) { return -E_RELATIONAL_TABLE_INCOMPATIBLE; } diff --git a/kv_store/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp b/kv_store/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp index 685740d9..d5b2c546 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp @@ -81,7 +81,7 @@ const std::string TrackerTable::GetExtendAssignValSql(bool isDelete) const const std::string TrackerTable::GetDiffTrackerValSql() const { if (trackerColNames_.empty() || isTrackerAction_) { - return isTrackerAction_ ? "1" : "0"; + return isTrackerAction_ ? GetOnChangeType() : "0"; } std::string sql = " CASE WHEN ("; size_t index = 0; @@ -92,7 +92,7 @@ const std::string TrackerTable::GetDiffTrackerValSql() const } index++; } - sql += ") THEN 1 ELSE 0 END"; + sql += ") THEN " + GetOnChangeType() + " ELSE 0 END"; return sql; } @@ -213,7 +213,7 @@ const std::string TrackerTable::GetTempInsertTriggerSql(bool incFlag) const sql += "cursor=" + CloudStorageUtils::GetSelectIncCursorSql(tableName_) + " WHERE"; } sql += " hash_key = NEW.hash_key;\n"; - if (!IsEmpty()) { + if (!IsEmpty() && isTriggerObserver_) { sql += "SELECT server_observer('" + tableName_ + "', 1);"; } sql += "\nEND;"; @@ -244,7 +244,7 @@ const std::string TrackerTable::GetTempUpdateTriggerSql(bool incFlag) const sql += "cursor=" + CloudStorageUtils::GetSelectIncCursorSql(tableName_) + " WHERE"; } sql += " data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";\n"; - if (!IsEmpty()) { + if (!IsEmpty() && isTriggerObserver_) { sql += "SELECT server_observer('" + tableName_ + "', " + GetDiffTrackerValSql() + ");"; } sql += "\nEND;"; @@ -277,13 +277,27 @@ const std::string TrackerTable::GetTempDeleteTriggerSql(bool incFlag) const sql.pop_back(); } sql += " WHERE data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";\n"; - if (!IsEmpty()) { + if (!IsEmpty() && isTriggerObserver_) { sql += "SELECT server_observer('" + tableName_ + "', 1);"; } sql += "\nEND;"; return sql; } +const std::string TrackerTable::GetTempUpdateLogCursorTriggerSql() const +{ + std::string sql = "CREATE TEMP TRIGGER IF NOT EXISTS " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName_; + sql += "LOG_ON_UPDATE_TEMP AFTER UPDATE ON " + DBCommon::GetLogTableName(tableName_); + sql += " WHEN (SELECT 1 FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata" + + " WHERE key = 'log_trigger_switch' AND value = 'false')\n"; + sql += "BEGIN\n"; + sql += CloudStorageUtils::GetCursorIncSql(tableName_) + "\n"; + sql += "UPDATE " + DBCommon::GetLogTableName(tableName_) + " SET "; + sql += "cursor=" + CloudStorageUtils::GetSelectIncCursorSql(tableName_) + " WHERE data_key = OLD.data_key;\n"; + sql += "END;"; + return sql; +} + void TrackerTable::SetTableName(const std::string &tableName) { tableName_ = tableName; @@ -382,5 +396,21 @@ void TrackerTable::SetTrackerAction(bool isTrackerAction) { isTrackerAction_ = isTrackerAction; } + +void TrackerTable::SetTriggerObserver(bool isTriggerObserver) +{ + isTriggerObserver_ = isTriggerObserver; +} + +void TrackerTable::SetKnowledgeTable(bool isKnowledgeTable) +{ + isKnowledgeTable_ = isKnowledgeTable; +} + +std::string TrackerTable::GetOnChangeType() const +{ + return isKnowledgeTable_ ? std::to_string(CloudDbConstant::ON_CHANGE_KNOWLEDGE) : + std::to_string(CloudDbConstant::ON_CHANGE_TRACKER); +} } #endif diff --git a/kv_store/frameworks/libs/distributeddb/common/src/schema_constant.cpp b/kv_store/frameworks/libs/distributeddb/common/src/schema_constant.cpp index 9f1dab2a..7fb32fc1 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/schema_constant.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/schema_constant.cpp @@ -16,41 +16,6 @@ #include "schema_constant.h" namespace DistributedDB { -const std::string SchemaConstant::KEYWORD_SCHEMA_VERSION = "SCHEMA_VERSION"; -const std::string SchemaConstant::KEYWORD_SCHEMA_MODE = "SCHEMA_MODE"; -const std::string SchemaConstant::KEYWORD_SCHEMA_DEFINE = "SCHEMA_DEFINE"; -const std::string SchemaConstant::KEYWORD_SCHEMA_INDEXES = "SCHEMA_INDEXES"; -const std::string SchemaConstant::KEYWORD_SCHEMA_SKIPSIZE = "SCHEMA_SKIPSIZE"; -const std::string SchemaConstant::KEYWORD_SCHEMA_TYPE = "SCHEMA_TYPE"; -const std::string SchemaConstant::KEYWORD_SCHEMA_TABLE = "TABLES"; -const std::string SchemaConstant::KEYWORD_INDEX = "INDEX"; // For FlatBuffer-Schema -const std::string SchemaConstant::KEYWORD_TABLE_MODE = "TABLE_MODE"; - -const std::string SchemaConstant::KEYWORD_MODE_STRICT = "STRICT"; -const std::string SchemaConstant::KEYWORD_MODE_COMPATIBLE = "COMPATIBLE"; - -const std::string SchemaConstant::KEYWORD_TYPE_BOOL = "BOOL"; -const std::string SchemaConstant::KEYWORD_TYPE_INTEGER = "INTEGER"; -const std::string SchemaConstant::KEYWORD_TYPE_LONG = "LONG"; -const std::string SchemaConstant::KEYWORD_TYPE_DOUBLE = "DOUBLE"; -const std::string SchemaConstant::KEYWORD_TYPE_STRING = "STRING"; -const std::string SchemaConstant::KEYWORD_TYPE_BOOLEAN = "BOOLEAN"; - -const std::string SchemaConstant::KEYWORD_ATTR_NOT_NULL = "NOT NULL"; -const std::string SchemaConstant::KEYWORD_ATTR_DEFAULT = "DEFAULT"; -const std::string SchemaConstant::KEYWORD_ATTR_VALUE_NULL = "null"; -const std::string SchemaConstant::KEYWORD_ATTR_VALUE_TRUE = "true"; -const std::string SchemaConstant::KEYWORD_ATTR_VALUE_FALSE = "false"; - -const std::string SchemaConstant::KEYWORD_TABLE_SPLIT_DEVICE = "SPLIT_BY_DEVICE"; -const std::string SchemaConstant::KEYWORD_TABLE_COLLABORATION = "COLLABORATION"; - -const std::string SchemaConstant::KEYWORD_TYPE_RELATIVE = "RELATIVE"; -const std::string SchemaConstant::SCHEMA_SUPPORT_VERSION = "1.0"; -const std::string SchemaConstant::SCHEMA_SUPPORT_VERSION_V2 = "2.0"; -const std::string SchemaConstant::SCHEMA_SUPPORT_VERSION_V2_1 = "2.1"; -const std::string SchemaConstant::SCHEMA_CURRENT_VERSION = SCHEMA_SUPPORT_VERSION_V2_1; - const uint32_t SchemaConstant::SCHEMA_META_FEILD_COUNT_MAX = 5; const uint32_t SchemaConstant::SCHEMA_META_FEILD_COUNT_MIN = 3; const uint32_t SchemaConstant::SCHEMA_FEILD_NAME_LENGTH_MAX = 64; diff --git a/kv_store/frameworks/libs/distributeddb/common/src/schema_negotiate.cpp b/kv_store/frameworks/libs/distributeddb/common/src/schema_negotiate.cpp index 2efd5f39..3300e643 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/schema_negotiate.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/schema_negotiate.cpp @@ -37,14 +37,23 @@ SyncOpinion SchemaNegotiate::MakeLocalSyncOpinion(const SchemaObject &localSchem LOGE("[Schema][Opinion] Remote-type=%" PRIu8 " unrecognized.", remoteSchemaType); return SyncOpinion{false, true, true}; } - // 2. If local-type is KV(Here remote-type is within recognized), Always permit sync. + // 2. If local-type is KV(Here remote-type is within recognized), always permit sync unless remote is JSON. if (localType == SchemaType::NONE) { LOGI("[Schema][Opinion] Local-type KV."); + if (remoteType == SchemaType::JSON) { + LOGE("[Schema][Opinion] Not support sync between KV(local) and JSON(remote)"); + return SyncOpinion{false, true, true}; + } return SyncOpinion{true, false, false}; } - // 3. If remote-type is KV(Here local-type can only be JSON or FLATBUFFER), Always permit sync but need check. + // 3. If remote-type is KV(Here local-type can only be JSON or FLATBUFFER), + // always permit sync unless remote is JSON, but need check. if (remoteType == SchemaType::NONE) { LOGI("[Schema][Opinion] Remote-type KV."); + if (localType == SchemaType::JSON) { + LOGE("[Schema][Opinion] Not support sync between KV(remote) and JSON(local)"); + return SyncOpinion{false, true, true}; + } return SyncOpinion{true, false, true}; } // 4. If local-type differ with remote-type(Here both type can only be JSON or FLATBUFFER), Do not permit sync. diff --git a/kv_store/frameworks/libs/distributeddb/common/src/schema_object.cpp b/kv_store/frameworks/libs/distributeddb/common/src/schema_object.cpp index 2488b497..c4e90c65 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/schema_object.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/schema_object.cpp @@ -605,7 +605,7 @@ int SchemaObject::CheckSchemaDefineItemDecideAttribute(const JsonObject& inJsonO // The ParseAndCheckSchemaAttribute do not cope with isIndexable field. Need to set it true here outAttr.isIndexable = true; } else if (inType == FieldType::LEAF_FIELD_ARRAY) { - uint32_t arraySize = 0; + size_t arraySize = 0; errCode = inJsonObject.GetArraySize(inPath, arraySize); if (errCode != E_OK) { LOGE("[Schema][CheckItemDecideAttr] Internal Error: GetArraySize Fail."); diff --git a/kv_store/frameworks/libs/distributeddb/common/src/schema_utils.cpp b/kv_store/frameworks/libs/distributeddb/common/src/schema_utils.cpp index f4814779..2c662207 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/schema_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/schema_utils.cpp @@ -31,14 +31,6 @@ namespace { { return (std::isalnum(character) || character == '_'); } - void TrimFiled(std::string &inString) - { - inString.erase(0, inString.find_first_not_of("\r\t ")); - size_t temp = inString.find_last_not_of("\r\t "); - if (temp < inString.size()) { - inString.erase(temp + 1); - } - } // TYPE, [NOT NULL,] [DEFAULT X] // DEFAULT at last @@ -70,13 +62,13 @@ int SchemaUtils::MakeTrans(const std::string &oriContent, size_t &pos) { if (isspace(oriContent[pos])) { return COLUMN_BLANK; - } else if (oriContent.compare(pos, SchemaConstant::KEYWORD_ATTR_NOT_NULL.size(), + } else if (oriContent.compare(pos, strlen(SchemaConstant::KEYWORD_ATTR_NOT_NULL), SchemaConstant::KEYWORD_ATTR_NOT_NULL) == 0) { - pos = pos + SchemaConstant::KEYWORD_ATTR_NOT_NULL.size() - 1; + pos = pos + strlen(SchemaConstant::KEYWORD_ATTR_NOT_NULL) - 1; return COLUMN_NOT_NULL; - } else if (oriContent.compare(pos, SchemaConstant::KEYWORD_ATTR_DEFAULT.size(), + } else if (oriContent.compare(pos, strlen(SchemaConstant::KEYWORD_ATTR_DEFAULT), SchemaConstant::KEYWORD_ATTR_DEFAULT) == 0) { - pos = pos + SchemaConstant::KEYWORD_ATTR_DEFAULT.size() - 1; + pos = pos + strlen(SchemaConstant::KEYWORD_ATTR_DEFAULT) - 1; return COLUMN_DEFAULT; } else if (std::isalnum(oriContent[pos]) || oriContent[pos] == '\'' || oriContent[pos] == '+' || oriContent[pos] == '-') { @@ -449,13 +441,6 @@ int SchemaUtils::CheckFieldName(const FieldName &inName) return E_OK; } -std::string SchemaUtils::Strip(const std::string &inString) -{ - std::string stripRes = inString; - TrimFiled(stripRes); - return stripRes; -} - std::string SchemaUtils::StripNameSpace(const std::string &inFullName) { auto pos = inFullName.find_last_of('.'); @@ -465,22 +450,6 @@ std::string SchemaUtils::StripNameSpace(const std::string &inFullName) return inFullName.substr(pos + 1); } -std::string SchemaUtils::FieldTypeString(FieldType inType) -{ - static std::map fieldTypeMapString = { - {FieldType::LEAF_FIELD_NULL, "NULL"}, - {FieldType::LEAF_FIELD_BOOL, "BOOL"}, - {FieldType::LEAF_FIELD_INTEGER, "INTEGER"}, - {FieldType::LEAF_FIELD_LONG, "LONG"}, - {FieldType::LEAF_FIELD_DOUBLE, "DOUBLE"}, - {FieldType::LEAF_FIELD_STRING, "STRING"}, - {FieldType::LEAF_FIELD_ARRAY, "ARRAY"}, - {FieldType::LEAF_FIELD_OBJECT, "LEAF_OBJECT"}, - {FieldType::INTERNAL_FIELD_OBJECT, "INTERNAL_OBJECT"}, - }; - return fieldTypeMapString[inType]; -} - std::string SchemaUtils::SchemaTypeString(SchemaType inType) { static std::map schemaTypeMapString { @@ -515,50 +484,4 @@ void SchemaUtils::TransTrackerSchemaToLower(const TrackerSchema &srcSchema, Trac destSchema.trackerColNames.insert(DBCommon::ToLowerCase(srcName)); } } - -int SchemaUtils::ExtractJsonObj(const JsonObject &inJsonObject, const std::string &field, - JsonObject &out) -{ - FieldType fieldType; - auto fieldPath = FieldPath {field}; - int errCode = inJsonObject.GetFieldTypeByFieldPath(fieldPath, fieldType); - if (errCode != E_OK) { - LOGE("[SchemaUtils][ExtractJsonObj] Get schema %s fieldType failed: %d.", field.c_str(), errCode); - return -E_SCHEMA_PARSE_FAIL; - } - if (FieldType::INTERNAL_FIELD_OBJECT != fieldType) { - LOGE("[SchemaUtils][ExtractJsonObj] Expect %s Object but %s.", field.c_str(), - SchemaUtils::FieldTypeString(fieldType).c_str()); - return -E_SCHEMA_PARSE_FAIL; - } - errCode = inJsonObject.GetObjectByFieldPath(fieldPath, out); - if (errCode != E_OK) { - LOGE("[SchemaUtils][ExtractJsonObj] Get schema %s value failed: %d.", field.c_str(), errCode); - return -E_SCHEMA_PARSE_FAIL; - } - return E_OK; -} - -int SchemaUtils::ExtractJsonObjArray(const JsonObject &inJsonObject, const std::string &field, - std::vector &out) -{ - FieldType fieldType; - auto fieldPath = FieldPath {field}; - int errCode = inJsonObject.GetFieldTypeByFieldPath(fieldPath, fieldType); - if (errCode != E_OK) { - LOGE("[SchemaUtils][ExtractJsonObj] Get schema %s fieldType failed: %d.", field.c_str(), errCode); - return -E_SCHEMA_PARSE_FAIL; - } - if (FieldType::LEAF_FIELD_ARRAY != fieldType) { - LOGE("[SchemaUtils][ExtractJsonObj] Expect %s Object but %s.", field.c_str(), - SchemaUtils::FieldTypeString(fieldType).c_str()); - return -E_SCHEMA_PARSE_FAIL; - } - errCode = inJsonObject.GetObjectArrayByFieldPath(fieldPath, out); - if (errCode != E_OK) { - LOGE("[SchemaUtils][ExtractJsonObj] Get schema %s value failed: %d.", field.c_str(), errCode); - return -E_SCHEMA_PARSE_FAIL; - } - return E_OK; -} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/common/src/schema_utils_client.cpp b/kv_store/frameworks/libs/distributeddb/common/src/schema_utils_client.cpp new file mode 100644 index 00000000..a981890b --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/common/src/schema_utils_client.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 "schema_utils.h" +namespace DistributedDB { +void SchemaUtils::TrimFiled(std::string &inString) +{ + inString.erase(0, inString.find_first_not_of("\r\t ")); + size_t temp = inString.find_last_not_of("\r\t "); + if (temp < inString.size()) { + inString.erase(temp + 1); + } +} + +std::string SchemaUtils::Strip(const std::string &inString) +{ + std::string stripRes = inString; + TrimFiled(stripRes); + return stripRes; +} + +std::string SchemaUtils::FieldTypeString(FieldType inType) +{ + static std::map fieldTypeMapString = { + {FieldType::LEAF_FIELD_NULL, "NULL"}, + {FieldType::LEAF_FIELD_BOOL, "BOOL"}, + {FieldType::LEAF_FIELD_INTEGER, "INTEGER"}, + {FieldType::LEAF_FIELD_LONG, "LONG"}, + {FieldType::LEAF_FIELD_DOUBLE, "DOUBLE"}, + {FieldType::LEAF_FIELD_STRING, "STRING"}, + {FieldType::LEAF_FIELD_ARRAY, "ARRAY"}, + {FieldType::LEAF_FIELD_OBJECT, "LEAF_OBJECT"}, + {FieldType::INTERNAL_FIELD_OBJECT, "INTERNAL_OBJECT"}, + }; + return fieldTypeMapString[inType]; +} + +int SchemaUtils::ExtractJsonObj(const JsonObject &inJsonObject, const std::string &field, + JsonObject &out) +{ + FieldType fieldType; + auto fieldPath = FieldPath {field}; + int errCode = inJsonObject.GetFieldTypeByFieldPath(fieldPath, fieldType); + if (errCode != E_OK) { + LOGE("[SchemaUtils][ExtractJsonObj] Get schema fieldType failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + if (FieldType::INTERNAL_FIELD_OBJECT != fieldType) { + LOGE("[SchemaUtils][ExtractJsonObj] Expect Object but %s.", + SchemaUtils::FieldTypeString(fieldType).c_str()); + return -E_SCHEMA_PARSE_FAIL; + } + errCode = inJsonObject.GetObjectByFieldPath(fieldPath, out); + if (errCode != E_OK) { + LOGE("[SchemaUtils][ExtractJsonObj] Get schema value failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + return E_OK; +} + +int SchemaUtils::ExtractJsonObjArray(const JsonObject &inJsonObject, const std::string &field, + std::vector &out) +{ + FieldType fieldType; + auto fieldPath = FieldPath {field}; + int errCode = inJsonObject.GetFieldTypeByFieldPath(fieldPath, fieldType); + if (errCode != E_OK) { + LOGE("[SchemaUtils][ExtractJsonObjArray] Get schema fieldType failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + if (FieldType::LEAF_FIELD_ARRAY != fieldType) { + LOGE("[SchemaUtils][ExtractJsonObjArray] Expect Array but %s.", + SchemaUtils::FieldTypeString(fieldType).c_str()); + return -E_SCHEMA_PARSE_FAIL; + } + errCode = inJsonObject.GetObjectArrayByFieldPath(fieldPath, out); + if (errCode != E_OK) { + LOGE("[SchemaUtils][ExtractJsonObjArray] Get schema value failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + return E_OK; +} +} // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/common/src/user_change_monitor.cpp b/kv_store/frameworks/libs/distributeddb/common/src/user_change_monitor.cpp index 4a1dabc8..8d0769ff 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/user_change_monitor.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/user_change_monitor.cpp @@ -46,6 +46,7 @@ int UserChangeMonitor::Start() void UserChangeMonitor::Stop() { + std::shared_lock lockGuard(userChangeMonitorLock_); if (!isStarted_) { return; } diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/combine_status.h b/kv_store/frameworks/libs/distributeddb/communicator/include/combine_status.h index 931f84ce..1f602e88 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/combine_status.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/combine_status.h @@ -26,6 +26,8 @@ namespace DistributedDB { */ class CombineStatus { public: + CombineStatus() = default; + ~CombineStatus() = default; void UpdateProgressId(uint64_t inProgressId); uint64_t GetProgressId() const; bool CheckProgress(); diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/communicator_aggregator.h b/kv_store/frameworks/libs/distributeddb/communicator/include/communicator_aggregator.h index 6034cb15..25cec9c9 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/communicator_aggregator.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/communicator_aggregator.h @@ -39,8 +39,10 @@ class CommunicatorLinker; struct TaskConfig { bool nonBlock = true; + bool isRetryTask = true; uint32_t timeout = 0u; Priority prio = Priority::NORMAL; + AccessInfos infos; }; /* @@ -93,6 +95,8 @@ public: std::shared_ptr GetExtendHeaderHandle(const ExtendInfo ¶mInfo); void ClearOnlineLabel() override; + + void ResetRetryCount(); private: // Working in a dedicated thread void SendDataRoutine(); @@ -104,23 +108,22 @@ private: void NotifySendableToAllCommunicator(); // Call from Adapter by register these function - void OnBytesReceive(const std::string &srcTarget, const uint8_t *bytes, uint32_t length, - const DataUserInfoProc &userInfoProc); + void OnBytesReceive(const ReceiveBytesInfo &receiveBytesInfo, const DataUserInfoProc &userInfoProc); void OnTargetChange(const std::string &target, bool isConnect); void OnSendable(const std::string &target); - void OnFragmentReceive(const std::string &srcTarget, const uint8_t *bytes, uint32_t length, - const ParseResult &inResult, const DataUserInfoProc &userInfoProc); + void OnFragmentReceive(const ReceiveBytesInfo &receiveBytesInfo, const ParseResult &inResult, + const DataUserInfoProc &userInfoProc); int OnCommLayerFrameReceive(const std::string &srcTarget, const ParseResult &inResult); - int OnAppLayerFrameReceive(const std::string &srcTarget, const uint8_t *bytes, - uint32_t length, const ParseResult &inResult, const DataUserInfoProc &userInfoProc); - int OnAppLayerFrameReceive(const std::string &srcTarget, SerialBuffer *&inFrameBuffer, + int OnAppLayerFrameReceive(const ReceiveBytesInfo &receiveBytesInfo, const ParseResult &inResult, + const DataUserInfoProc &userInfoProc); + int OnAppLayerFrameReceive(const ReceiveBytesInfo &receiveBytesInfo, SerialBuffer *&inFrameBuffer, const ParseResult &inResult, const DataUserInfoProc &userInfoProc); // Function with suffix NoMutex should be called with mutex in the caller - int TryDeliverAppLayerFrameToCommunicatorNoMutex(const std::string &srcTarget, SerialBuffer *&inFrameBuffer, - const LabelType &toLabel, const std::string &userId = ""); + int TryDeliverAppLayerFrameToCommunicatorNoMutex(const DataUserInfoProc &userInfoProc, + const std::string &srcTarget, SerialBuffer *&inFrameBuffer, const LabelType &toLabel, const UserInfo &userInfo); // Auxiliary function for cutting short primary function int RegCallbackToAdapter(); @@ -131,8 +134,9 @@ private: // Feedback related functions void TriggerVersionNegotiation(const std::string &dstTarget); void TryToFeedbackWhenCommunicatorNotFound(const std::string &dstTarget, const LabelType &dstLabel, - const SerialBuffer *inOriFrame); - void TriggerCommunicatorNotFoundFeedback(const std::string &dstTarget, const LabelType &dstLabel, Message* &oriMsg); + const SerialBuffer *inOriFrame, int inErrCode); + void TriggerCommunicatorNotFoundFeedback(const std::string &dstTarget, const LabelType &dstLabel, Message* &oriMsg, + int sendErrNo); // Record the protocol version of remote target. void SetRemoteCommunicatorVersion(const std::string &target, uint16_t version); @@ -164,7 +168,11 @@ private: uint64_t IncreaseSendSequenceId(const std::string &target); int GetDataUserId(const ParseResult &inResult, const LabelType &toLabel, const DataUserInfoProc &userInfoProc, - std::string &userId); + const std::string &device, UserInfo &userInfo); + + int ReTryDeliverAppLayerFrameOnCommunicatorNotFound(const ReceiveBytesInfo &receiveBytesInfo, + SerialBuffer *&inFrameBuffer, const ParseResult &inResult, const DataUserInfoProc &userInfoProc, + const UserInfo &userInfo); DECLARE_OBJECT_TAG(CommunicatorAggregator); diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/frame_retainer.h b/kv_store/frameworks/libs/distributeddb/communicator/include/frame_retainer.h index 4a7c80e9..79837f45 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/frame_retainer.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/frame_retainer.h @@ -29,12 +29,14 @@ class SerialBuffer; // Forward Declarations struct FrameInfo { SerialBuffer *buffer = nullptr; std::string srcTarget; + std::string sendUser; LabelType commLabel; uint32_t frameId = 0u; }; struct RetainWork { SerialBuffer *buffer = nullptr; + std::string sendUser; uint32_t frameId = 0u; uint32_t remainTime = 0u; // in second }; diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/iadapter.h b/kv_store/frameworks/libs/distributeddb/communicator/include/iadapter.h index d9273d82..fb8a271b 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/iadapter.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/iadapter.h @@ -29,8 +29,15 @@ struct DataUserInfoProc { uint32_t length = 0; std::shared_ptr processCommunicator = nullptr; }; +struct ReceiveBytesInfo { + const uint8_t *bytes = nullptr; + const std::string srcTarget; + uint32_t length = 0; + bool isNeedGetUserInfo = true; +}; + // SendableCallback only notify when status changed from unsendable to sendable -using BytesReceiveCallback = std::function; using TargetChangeCallback = std::function; using SendableCallback = std::function; @@ -61,6 +68,8 @@ public: // Return 0 as success. Return negative as error virtual int SendBytes(const std::string &dstTarget, const uint8_t *bytes, uint32_t length, uint32_t totalLength) = 0; + virtual int SendBytes(const DeviceInfos &deviceInfos, const uint8_t *bytes, uint32_t length, + uint32_t totalLength) = 0; // Pass nullptr as inHandle to do unReg if need (inDecRef also nullptr) // Return 0 as success. Return negative as error diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/icommunicator.h b/kv_store/frameworks/libs/distributeddb/communicator/include/icommunicator.h index 4b73ab32..364750d1 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/icommunicator.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/icommunicator.h @@ -26,12 +26,13 @@ namespace DistributedDB { // inMsg is heap memory, its ownership transfers by calling OnMessageCallback -using OnMessageCallback = std::function; +using OnMessageCallback = std::function; constexpr uint32_t SEND_TIME_OUT = 3000; // 3s struct SendConfig { bool nonBlock = false; bool isNeedExtendHead = false; + bool isRetryTask = true; uint32_t timeout = SEND_TIME_OUT; ExtendInfo paramInfo; }; @@ -82,7 +83,11 @@ public: // Return 0 as success. Return negative as error virtual int SendMessage(const std::string &dstTarget, const Message *inMsg, const SendConfig &config) = 0; virtual int SendMessage(const std::string &dstTarget, const Message *inMsg, const SendConfig &config, - const OnSendEnd &onEnd) = 0; // HW Code Regulation do not allow to use default parameters on virtual function + const OnSendEnd &onEnd) = 0; // Code Regulation do not allow to use default parameters on virtual function + + virtual std::string GetTargetUserId(const ExtendInfo ¶mInfo) const = 0; + + virtual bool ExchangeClosePending(bool expected) = 0; virtual ~ICommunicator() {}; }; diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/message.h b/kv_store/frameworks/libs/distributeddb/communicator/include/message.h index 416e0831..7e6fb17a 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/message.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/message.h @@ -142,6 +142,11 @@ public: target_ = inTarget; } + void SetSenderUserId(const std::string &userId) + { + senderUserId_ = userId; + } + void SetPriority(Priority inPriority) { prio_ = inPriority; @@ -185,6 +190,11 @@ public: return target_; } + std::string GetSenderUserId() const + { + return senderUserId_; + } + Priority GetPriority() const { return prio_; @@ -197,7 +207,8 @@ public: bool IsFeedbackError() const { - return (errorNo_ == E_FEEDBACK_UNKNOWN_MESSAGE || errorNo_ == E_FEEDBACK_COMMUNICATOR_NOT_FOUND); + return (errorNo_ == E_FEEDBACK_UNKNOWN_MESSAGE || errorNo_ == E_FEEDBACK_COMMUNICATOR_NOT_FOUND || + errorNo_ == E_FEEDBACK_DB_CLOSING); } private: @@ -212,6 +223,7 @@ private: // Field carry supplemental info std::string target_; + std::string senderUserId_; Priority prio_ = Priority::LOW; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/network_adapter.h b/kv_store/frameworks/libs/distributeddb/communicator/include/network_adapter.h index 06ebd559..fc1c390a 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/network_adapter.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/network_adapter.h @@ -46,6 +46,8 @@ public: int SendBytes(const std::string &dstTarget, const uint8_t *bytes, uint32_t length, uint32_t totalLength) override; + int SendBytes(const DeviceInfos &deviceInfos, const uint8_t *bytes, uint32_t length, + uint32_t totalLength) override; int RegBytesReceiveCallback(const BytesReceiveCallback &onReceive, const Finalizer &inOper) override; int RegTargetChangeCallback(const TargetChangeCallback &onChange, const Finalizer &inOper) override; diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/parse_result.h b/kv_store/frameworks/libs/distributeddb/communicator/include/parse_result.h index 2186bbb9..9cf5cdb7 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/parse_result.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/parse_result.h @@ -23,6 +23,9 @@ namespace DistributedDB { class ParseResult { public: + ParseResult() = default; + ~ParseResult() = default; + void SetFrameId(uint32_t inFrameId) { frameId_ = inFrameId; diff --git a/kv_store/frameworks/libs/distributeddb/communicator/include/send_task_scheduler.h b/kv_store/frameworks/libs/distributeddb/communicator/include/send_task_scheduler.h index d5a7553a..d1b30194 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/include/send_task_scheduler.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/include/send_task_scheduler.h @@ -23,6 +23,7 @@ #include #include #include "communicator_type_define.h" +#include "iprocess_communicator.h" #include "macro_utils.h" namespace DistributedDB { @@ -39,6 +40,8 @@ struct SendTask { OnSendEnd onEnd; uint32_t frameId = 0u; bool isValid = true; + bool isRetryTask = true; + AccessInfos infos; }; struct SendTaskInfo { diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator.cpp index 608adaf9..5c721205 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator.cpp @@ -20,7 +20,7 @@ namespace DistributedDB { Communicator::Communicator(CommunicatorAggregator *inCommAggregator, const LabelType &inLabel) - : commAggrHandle_(inCommAggregator), commLabel_(inLabel) + : commAggrHandle_(inCommAggregator), commLabel_(inLabel), dbClosePending_(false) { RefObject::IncObjRef(commAggrHandle_); // Rely on CommunicatorAggregator, hold its reference. } @@ -130,7 +130,9 @@ int Communicator::SendMessage(const std::string &dstTarget, const Message *inMsg return errCode; } - TaskConfig taskConfig {config.nonBlock, config.timeout, inMsg->GetPriority()}; + TaskConfig taskConfig {config.nonBlock, config.isRetryTask, config.timeout, inMsg->GetPriority()}; + taskConfig.infos = {config.paramInfo.appId, config.paramInfo.storeId, config.paramInfo.userId, + config.paramInfo.subUserId}; errCode = commAggrHandle_->ScheduleSendTask(dstTarget, buffer, FrameType::APPLICATION_MESSAGE, taskConfig, onEnd); if (errCode == E_OK) { // if ok, free inMsg, otherwise the caller should take over inMsg @@ -144,29 +146,43 @@ int Communicator::SendMessage(const std::string &dstTarget, const Message *inMsg return errCode; } -void Communicator::OnBufferReceive(const std::string &srcTarget, const SerialBuffer *inBuf) +int Communicator::OnBufferReceive(const std::string &srcTarget, const SerialBuffer *inBuf, + const std::string &sendUser) { std::lock_guard messageHandleLockGuard(messageHandleMutex_); - if (srcTarget.size() != 0 && inBuf != nullptr && onMessageHandle_) { + if (!srcTarget.empty() && inBuf != nullptr && onMessageHandle_) { int error = E_OK; // if error is not E_OK, null pointer will be returned Message *message = ProtocolProto::ToMessage(inBuf, error); - delete inBuf; - inBuf = nullptr; // message is not nullptr if error is E_OK or error is E_NOT_REGISTER. // for the former case the message will be handled and release by sync module. // for the latter case the message is released in TriggerUnknownMessageFeedback. if (error != E_OK) { LOGE("[Comm][Receive] ToMessage fail, label=%.3s, error=%d.", VEC_TO_STR(commLabel_), error); + delete inBuf; + inBuf = nullptr; if (error == -E_VERSION_NOT_SUPPORT) { TriggerVersionNegotiation(srcTarget); } else if (error == -E_NOT_REGISTER) { TriggerUnknownMessageFeedback(srcTarget, message); } - return; + return E_OK; } + if (message->GetMessageType() == TYPE_REQUEST && ExchangeClosePending(false)) { + delete message; + message = nullptr; + LOGW("[Comm][Receive] db closing label=%.3s", VEC_TO_STR(commLabel_)); + return -E_FEEDBACK_DB_CLOSING; + } + message->SetSenderUserId(sendUser); LOGI("[Comm][Receive] label=%.3s, srcTarget=%s{private}.", VEC_TO_STR(commLabel_), srcTarget.c_str()); - onMessageHandle_(srcTarget, message); + error = onMessageHandle_(srcTarget, message); + if (error == -E_FEEDBACK_DB_CLOSING) { + return -E_FEEDBACK_DB_CLOSING; + } + delete inBuf; + inBuf = nullptr; + return E_OK; } else { LOGE("[Comm][Receive] label=%.3s, src.size=%zu or buf or handle invalid.", VEC_TO_STR(commLabel_), srcTarget.size()); @@ -175,6 +191,7 @@ void Communicator::OnBufferReceive(const std::string &srcTarget, const SerialBuf inBuf = nullptr; } } + return E_OK; } void Communicator::OnConnectChange(const std::string &target, bool isConnect) @@ -226,7 +243,7 @@ void Communicator::TriggerVersionNegotiation(const std::string &dstTarget) return; } - TaskConfig config{true, 0, Priority::HIGH}; + TaskConfig config{true, true, 0, Priority::HIGH}; errCode = commAggrHandle_->ScheduleSendTask(dstTarget, buffer, FrameType::EMPTY, config); if (errCode != E_OK) { LOGE("[Comm][TrigVer] Send empty frame fail, errCode=%d", errCode); @@ -259,7 +276,7 @@ void Communicator::TriggerUnknownMessageFeedback(const std::string &dstTarget, M return; } - TaskConfig config{true, 0, Priority::HIGH}; + TaskConfig config{true, true, 0, Priority::HIGH}; errCode = commAggrHandle_->ScheduleSendTask(dstTarget, buffer, FrameType::APPLICATION_MESSAGE, config); if (errCode != E_OK) { LOGE("[Comm][TrigFeedback] Send unknown message feedback frame fail, errCode=%d", errCode); @@ -269,5 +286,19 @@ void Communicator::TriggerUnknownMessageFeedback(const std::string &dstTarget, M } } +std::string Communicator::GetTargetUserId(const ExtendInfo ¶mInfo) const +{ + std::shared_ptr extendHandle = commAggrHandle_->GetExtendHeaderHandle(paramInfo); + if (extendHandle == nullptr) { + return DBConstant::DEFAULT_USER; + } + return extendHandle->GetTargetUserId(); +} + +bool Communicator::ExchangeClosePending(bool expected) +{ + bool curVal = !expected; + return dbClosePending_.compare_exchange_strong(curVal, expected); +} DEFINE_OBJECT_TAG_FACILITIES(Communicator) } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator.h b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator.h index 976ce0ae..b6b9aa49 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator.h +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator.h @@ -56,7 +56,7 @@ public: const OnSendEnd &onEnd) override; // Call by CommunicatorAggregator directly - void OnBufferReceive(const std::string &srcTarget, const SerialBuffer *inBuf); + int OnBufferReceive(const std::string &srcTarget, const SerialBuffer *inBuf, const std::string &sendUser); // Call by CommunicatorAggregator directly void OnConnectChange(const std::string &target, bool isConnect); @@ -67,6 +67,9 @@ public: // Call by CommunicatorAggregator directly LabelType GetCommunicatorLabel() const; + std::string GetTargetUserId(const ExtendInfo ¶mInfo) const override; + + bool ExchangeClosePending(bool expected) override; private: void TriggerVersionNegotiation(const std::string &dstTarget); void TriggerUnknownMessageFeedback(const std::string &dstTarget, Message* &oriMsg); @@ -81,6 +84,7 @@ private: OnMessageCallback onMessageHandle_; OnConnectCallback onConnectHandle_; std::function onSendableHandle_; + std::atomic dbClosePending_; Finalizer onMessageFinalizer_; Finalizer onConnectFinalizer_; Finalizer onSendableFinalizer_; diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp index ea724de9..14171fa3 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp @@ -276,7 +276,7 @@ void CommunicatorAggregator::ActivateCommunicator(const LabelType &commLabel, co // Do Redeliver, the communicator is responsible to deal with the frame std::list framesToRedeliver = retainer_.FetchFramesForSpecificCommunicator(commLabel); for (auto &entry : framesToRedeliver) { - commMap_[userId].at(commLabel).first->OnBufferReceive(entry.srcTarget, entry.buffer); + commMap_[userId].at(commLabel).first->OnBufferReceive(entry.srcTarget, entry.buffer, entry.sendUser); } } @@ -326,7 +326,7 @@ int CommunicatorAggregator::ScheduleSendTask(const std::string &dstTarget, Seria std::lock_guard autoLock(sendRecordMutex_); sendRecord_[info.frameId] = {}; } - SendTask task{inBuff, dstTarget, onEnd, info.frameId, true}; + SendTask task{inBuff, dstTarget, onEnd, info.frameId, true, inConfig.isRetryTask, inConfig.infos}; if (inConfig.nonBlock) { errCode = scheduler_.AddSendTaskIntoSchedule(task, inConfig.prio); } else { @@ -337,7 +337,8 @@ int CommunicatorAggregator::ScheduleSendTask(const std::string &dstTarget, Seria return errCode; } TriggerSendData(); - LOGI("[CommAggr][Create] Exit ok, dev=%.3s, frameId=%u", dstTarget.c_str(), info.frameId); + LOGI("[CommAggr][Create] Exit ok, dev=%.3s, frameId=%u, isRetry=%d", dstTarget.c_str(), info.frameId, + task.isRetryTask); return E_OK; } @@ -384,12 +385,13 @@ void CommunicatorAggregator::SendPacketsAndDisposeTask(const SendTask &inTask, u startIndex = sendRecord_[inTask.frameId].sendIndex; } uint64_t currentSendSequenceId = IncreaseSendSequenceId(inTask.dstTarget); + DeviceInfos deviceInfos = {inTask.dstTarget, inTask.infos, inTask.isRetryTask}; for (uint32_t index = startIndex; index < static_cast(eachPacket.size()) && inTask.isValid; ++index) { auto &entry = eachPacket[index]; LOGI("[CommAggr][SendPackets] DoSendBytes, dstTarget=%s{private}, extendHeadLength=%" PRIu32 ", packetLength=%" PRIu32 ".", inTask.dstTarget.c_str(), entry.second.first, entry.second.second); ProtocolProto::DisplayPacketInformation(entry.first + entry.second.first, entry.second.second); - errCode = adapterHandle_->SendBytes(inTask.dstTarget, entry.first, entry.second.second, totalLength); + errCode = adapterHandle_->SendBytes(deviceInfos, entry.first, entry.second.second, totalLength); { std::lock_guard autoLock(sendRecordMutex_); sendRecord_[inTask.frameId].sendIndex = index; @@ -483,24 +485,26 @@ void CommunicatorAggregator::NotifySendableToAllCommunicator() } } -void CommunicatorAggregator::OnBytesReceive(const std::string &srcTarget, const uint8_t *bytes, uint32_t length, +void CommunicatorAggregator::OnBytesReceive(const ReceiveBytesInfo &receiveBytesInfo, const DataUserInfoProc &userInfoProc) { - ProtocolProto::DisplayPacketInformation(bytes, length); + ProtocolProto::DisplayPacketInformation(receiveBytesInfo.bytes, receiveBytesInfo.length); ParseResult packetResult; - int errCode = ProtocolProto::CheckAndParsePacket(srcTarget, bytes, length, packetResult); + int errCode = ProtocolProto::CheckAndParsePacket(receiveBytesInfo.srcTarget, receiveBytesInfo.bytes, + receiveBytesInfo.length, packetResult); if (errCode != E_OK) { LOGE("[CommAggr][Receive] Parse packet fail, errCode=%d.", errCode); if (errCode == -E_VERSION_NOT_SUPPORT) { - TriggerVersionNegotiation(srcTarget); + TriggerVersionNegotiation(receiveBytesInfo.srcTarget); } return; } // Update version of remote target - SetRemoteCommunicatorVersion(srcTarget, packetResult.GetDbVersion()); + SetRemoteCommunicatorVersion(receiveBytesInfo.srcTarget, packetResult.GetDbVersion()); if (dbStatusAdapter_ != nullptr) { - dbStatusAdapter_->SetRemoteOptimizeCommunication(srcTarget, !packetResult.IsSendLabelExchange()); + dbStatusAdapter_->SetRemoteOptimizeCommunication(receiveBytesInfo.srcTarget, + !packetResult.IsSendLabelExchange()); } if (packetResult.GetFrameTypeInfo() == FrameType::EMPTY) { // Empty frame will never be fragmented LOGI("[CommAggr][Receive] Empty frame, just ignore in this version of distributeddb."); @@ -508,14 +512,14 @@ void CommunicatorAggregator::OnBytesReceive(const std::string &srcTarget, const } if (packetResult.IsFragment()) { - OnFragmentReceive(srcTarget, bytes, length, packetResult, userInfoProc); + OnFragmentReceive(receiveBytesInfo, packetResult, userInfoProc); } else if (packetResult.GetFrameTypeInfo() != FrameType::APPLICATION_MESSAGE) { - errCode = OnCommLayerFrameReceive(srcTarget, packetResult); + errCode = OnCommLayerFrameReceive(receiveBytesInfo.srcTarget, packetResult); if (errCode != E_OK) { LOGE("[CommAggr][Receive] CommLayer receive fail, errCode=%d.", errCode); } } else { - errCode = OnAppLayerFrameReceive(srcTarget, bytes, length, packetResult, userInfoProc); + errCode = OnAppLayerFrameReceive(receiveBytesInfo, packetResult, userInfoProc); if (errCode != E_OK) { LOGE("[CommAggr][Receive] AppLayer receive fail, errCode=%d.", errCode); } @@ -570,12 +574,13 @@ void CommunicatorAggregator::OnSendable(const std::string &target) TriggerSendData(); } -void CommunicatorAggregator::OnFragmentReceive(const std::string &srcTarget, const uint8_t *bytes, uint32_t length, +void CommunicatorAggregator::OnFragmentReceive(const ReceiveBytesInfo &receiveBytesInfo, const ParseResult &inResult, const DataUserInfoProc &userInfoProc) { int errorNo = E_OK; ParseResult frameResult; - SerialBuffer *frameBuffer = combiner_.AssembleFrameFragment(bytes, length, inResult, frameResult, errorNo); + SerialBuffer *frameBuffer = combiner_.AssembleFrameFragment(receiveBytesInfo.bytes, receiveBytesInfo.length, + inResult, frameResult, errorNo); if (errorNo != E_OK) { LOGE("[CommAggr][Receive] Combine fail, errCode=%d.", errorNo); return; @@ -591,20 +596,20 @@ void CommunicatorAggregator::OnFragmentReceive(const std::string &srcTarget, con delete frameBuffer; frameBuffer = nullptr; if (errCode == -E_VERSION_NOT_SUPPORT) { - TriggerVersionNegotiation(srcTarget); + TriggerVersionNegotiation(receiveBytesInfo.srcTarget); } return; } if (frameResult.GetFrameTypeInfo() != FrameType::APPLICATION_MESSAGE) { - errCode = OnCommLayerFrameReceive(srcTarget, frameResult); + errCode = OnCommLayerFrameReceive(receiveBytesInfo.srcTarget, frameResult); if (errCode != E_OK) { LOGE("[CommAggr][Receive] CommLayer receive fail after combination, errCode=%d.", errCode); } delete frameBuffer; frameBuffer = nullptr; } else { - errCode = OnAppLayerFrameReceive(srcTarget, frameBuffer, frameResult, userInfoProc); + errCode = OnAppLayerFrameReceive(receiveBytesInfo, frameBuffer, frameResult, userInfoProc); if (errCode != E_OK) { LOGE("[CommAggr][Receive] AppLayer receive fail after combination, errCode=%d.", errCode); } @@ -633,15 +638,15 @@ int CommunicatorAggregator::OnCommLayerFrameReceive(const std::string &srcTarget return E_OK; } -int CommunicatorAggregator::OnAppLayerFrameReceive(const std::string &srcTarget, const uint8_t *bytes, - uint32_t length, const ParseResult &inResult, const DataUserInfoProc &userInfoProc) +int CommunicatorAggregator::OnAppLayerFrameReceive(const ReceiveBytesInfo &receiveBytesInfo, + const ParseResult &inResult, const DataUserInfoProc &userInfoProc) { SerialBuffer *buffer = new (std::nothrow) SerialBuffer(); if (buffer == nullptr) { LOGE("[CommAggr][AppReceive] New SerialBuffer fail."); return -E_OUT_OF_MEMORY; } - int errCode = buffer->SetExternalBuff(bytes, length - inResult.GetPaddingLen(), + int errCode = buffer->SetExternalBuff(receiveBytesInfo.bytes, receiveBytesInfo.length - inResult.GetPaddingLen(), ProtocolProto::GetAppLayerFrameHeaderLength()); if (errCode != E_OK) { LOGE("[CommAggr][AppReceive] SetExternalBuff fail, errCode=%d.", errCode); @@ -649,7 +654,7 @@ int CommunicatorAggregator::OnAppLayerFrameReceive(const std::string &srcTarget, buffer = nullptr; return -E_INTERNAL_ERROR; } - return OnAppLayerFrameReceive(srcTarget, buffer, inResult, userInfoProc); + return OnAppLayerFrameReceive(receiveBytesInfo, buffer, inResult, userInfoProc); } // In early time, we cover "OnAppLayerFrameReceive" totally by commMapMutex_, then search communicator, if not found, @@ -670,58 +675,42 @@ int CommunicatorAggregator::OnAppLayerFrameReceive(const std::string &srcTarget, // Note: during this period, commMap_ maybe changed, and communicator not found before may exist now. // 3:Search communicator under commMapMutex_ again, if found then deliver frame to that communicator and end. // 4:If still not found, retain this frame if need or otherwise send CommunicatorNotFound feedback. -int CommunicatorAggregator::OnAppLayerFrameReceive(const std::string &srcTarget, SerialBuffer *&inFrameBuffer, - const ParseResult &inResult, const DataUserInfoProc &userInfoProc) +int CommunicatorAggregator::OnAppLayerFrameReceive(const ReceiveBytesInfo &receiveBytesInfo, + SerialBuffer *&inFrameBuffer, const ParseResult &inResult, const DataUserInfoProc &userInfoProc) { LabelType toLabel = inResult.GetCommLabel(); - std::string userId; - int ret = GetDataUserId(inResult, toLabel, userInfoProc, userId); - if (ret != E_OK) { - LOGE("[CommAggr][AppReceive] get data user id err, ret=%d", ret); - delete inFrameBuffer; - inFrameBuffer = nullptr; - return ret; + UserInfo userInfo = { .sendUser = DBConstant::DEFAULT_USER }; + if (receiveBytesInfo.isNeedGetUserInfo) { + int ret = GetDataUserId(inResult, toLabel, userInfoProc, receiveBytesInfo.srcTarget, userInfo); + if (ret != E_OK || userInfo.sendUser.empty()) { + LOGE("[CommAggr][AppReceive] get data user id err, ret=%d, empty receiveUser=%d, empty sendUser=%d", ret, + userInfo.receiveUser.empty(), userInfo.sendUser.empty()); + delete inFrameBuffer; + inFrameBuffer = nullptr; + return ret != E_OK ? ret : -E_NO_TRUSTED_USER; + } } { std::lock_guard commMapLockGuard(commMapMutex_); - int errCode = TryDeliverAppLayerFrameToCommunicatorNoMutex(srcTarget, inFrameBuffer, toLabel, userId); + int errCode = TryDeliverAppLayerFrameToCommunicatorNoMutex(userInfoProc, receiveBytesInfo.srcTarget, + inFrameBuffer, toLabel, userInfo); if (errCode == E_OK) { // Attention: Here is equal to E_OK return E_OK; + } else if (errCode == -E_FEEDBACK_DB_CLOSING) { + TryToFeedbackWhenCommunicatorNotFound(receiveBytesInfo.srcTarget, toLabel, inFrameBuffer, + E_FEEDBACK_DB_CLOSING); + delete inFrameBuffer; + inFrameBuffer = nullptr; + return errCode; // The caller will display errCode in log } } LOGI("[CommAggr][AppReceive] Communicator of %.3s not found or nonactivated.", VEC_TO_STR(toLabel)); - int errCode = -E_NOT_FOUND; - { - std::lock_guard onCommLackLockGuard(onCommLackMutex_); - if (onCommLackHandle_) { - errCode = onCommLackHandle_(toLabel, userId); - LOGI("[CommAggr][AppReceive] On CommLack End."); // Log in case callback block this thread - } else { - LOGI("[CommAggr][AppReceive] CommLackHandle invalid currently."); - } - } - // Here we have to lock commMapMutex_ and search communicator again. - std::lock_guard commMapLockGuard(commMapMutex_); - int errCodeAgain = TryDeliverAppLayerFrameToCommunicatorNoMutex(srcTarget, inFrameBuffer, toLabel, userId); - if (errCodeAgain == E_OK) { // Attention: Here is equal to E_OK. - LOGI("[CommAggr][AppReceive] Communicator of %.3s found after try again(rare case).", VEC_TO_STR(toLabel)); - return E_OK; - } - // Here, communicator is still not found, retain or discard according to the result of onCommLackHandle_ - if (errCode != E_OK) { - TryToFeedbackWhenCommunicatorNotFound(srcTarget, toLabel, inFrameBuffer); - delete inFrameBuffer; - inFrameBuffer = nullptr; - return errCode; // The caller will display errCode in log - } - // Do Retention, the retainer is responsible to deal with the frame - retainer_.RetainFrame(FrameInfo{inFrameBuffer, srcTarget, toLabel, inResult.GetFrameId()}); - inFrameBuffer = nullptr; - return E_OK; + return ReTryDeliverAppLayerFrameOnCommunicatorNotFound(receiveBytesInfo, inFrameBuffer, inResult, userInfoProc, + userInfo); } int CommunicatorAggregator::GetDataUserId(const ParseResult &inResult, const LabelType &toLabel, - const DataUserInfoProc &userInfoProc, std::string &userId) + const DataUserInfoProc &userInfoProc, const std::string &device, UserInfo &userInfo) { if (userInfoProc.processCommunicator == nullptr) { LOGE("[CommAggr][GetDataUserId] processCommunicator is nullptr"); @@ -729,30 +718,34 @@ int CommunicatorAggregator::GetDataUserId(const ParseResult &inResult, const Lab } std::string label(toLabel.begin(), toLabel.end()); std::vector userInfos; - DBStatus ret = userInfoProc.processCommunicator->GetDataUserInfo(userInfoProc.data, userInfoProc.length, label, - userInfos); + DataUserInfo dataUserInfo = {userInfoProc.data, userInfoProc.length, label, device}; + DBStatus ret = userInfoProc.processCommunicator->GetDataUserInfo(dataUserInfo, userInfos); LOGI("[CommAggr][GetDataUserId] get data user info, ret=%d", ret); if (ret == NO_PERMISSION) { LOGE("[CommAggr][GetDataUserId] userId dismatched, drop packet"); return ret; } - if (userInfos.size() >= 1) { - userId = userInfos[0].receiveUser; + if (!userInfos.empty()) { + userInfo = userInfos[0]; } else { LOGW("[CommAggr][GetDataUserId] userInfos is empty"); } return E_OK; } -int CommunicatorAggregator::TryDeliverAppLayerFrameToCommunicatorNoMutex(const std::string &srcTarget, - SerialBuffer *&inFrameBuffer, const LabelType &toLabel, const std::string &userId) +int CommunicatorAggregator::TryDeliverAppLayerFrameToCommunicatorNoMutex(const DataUserInfoProc &userInfoProc, + const std::string &srcTarget, SerialBuffer *&inFrameBuffer, const LabelType &toLabel, const UserInfo &userInfo) { // Ignore nonactivated communicator, which is regarded as inexistent - if (commMap_[userId].count(toLabel) != 0 && commMap_[userId].at(toLabel).second) { - commMap_[userId].at(toLabel).first->OnBufferReceive(srcTarget, inFrameBuffer); + const std::string &sendUser = userInfo.sendUser; + const std::string &receiveUser = userInfo.receiveUser; + if (commMap_[receiveUser].count(toLabel) != 0 && commMap_[receiveUser].at(toLabel).second) { + int ret = commMap_[receiveUser].at(toLabel).first->OnBufferReceive(srcTarget, inFrameBuffer, sendUser); // Frame handed over to communicator who is responsible to delete it. The frame is deleted here after return. - inFrameBuffer = nullptr; - return E_OK; + if (ret == E_OK) { + inFrameBuffer = nullptr; + } + return ret; } Communicator *communicator = nullptr; bool isEmpty = false; @@ -762,7 +755,7 @@ int CommunicatorAggregator::TryDeliverAppLayerFrameToCommunicatorNoMutex(const s communicator = entry.second.first; isEmpty = userCommMap.first.empty(); LOGW("[CommAggr][TryDeliver] Found communicator of %s, but required user is %s", - userCommMap.first.c_str(), userId.c_str()); + userCommMap.first.c_str(), receiveUser.c_str()); break; } } @@ -770,10 +763,12 @@ int CommunicatorAggregator::TryDeliverAppLayerFrameToCommunicatorNoMutex(const s break; } } - if (communicator != nullptr && (userId.empty() || isEmpty)) { - communicator->OnBufferReceive(srcTarget, inFrameBuffer); - inFrameBuffer = nullptr; - return E_OK; + if (communicator != nullptr && (receiveUser.empty() || isEmpty)) { + int ret = communicator->OnBufferReceive(srcTarget, inFrameBuffer, sendUser); + if (ret == E_OK) { + inFrameBuffer = nullptr; + } + return ret; } LOGE("[CommAggr][TryDeliver] Communicator not found"); return -E_NOT_FOUND; @@ -783,9 +778,8 @@ int CommunicatorAggregator::RegCallbackToAdapter() { RefObject::IncObjRef(this); // Reference to be hold by adapter int errCode = adapterHandle_->RegBytesReceiveCallback( - [this](const std::string &srcTarget, const uint8_t *bytes, uint32_t length, - const DataUserInfoProc &userInfoProc) { - OnBytesReceive(srcTarget, bytes, length, userInfoProc); + [this](const ReceiveBytesInfo &receiveBytesInfo, const DataUserInfoProc &userInfoProc) { + OnBytesReceive(receiveBytesInfo, userInfoProc); }, [this]() { RefObject::DecObjRef(this); }); if (errCode != E_OK) { RefObject::DecObjRef(this); // Rollback in case reg failed @@ -804,11 +798,9 @@ int CommunicatorAggregator::RegCallbackToAdapter() RefObject::IncObjRef(this); // Reference to be hold by adapter errCode = adapterHandle_->RegSendableCallback([this](const std::string &target, int deviceCommErrCode) { LOGI("[CommAggr] Send able dev=%.3s, deviceCommErrCode=%d", target.c_str(), deviceCommErrCode); - if (deviceCommErrCode == E_OK) { - (void)IncreaseSendSequenceId(target); - OnSendable(target); - } + (void)IncreaseSendSequenceId(target); scheduler_.SetDeviceCommErrCode(target, deviceCommErrCode); + OnSendable(target); }, [this]() { RefObject::DecObjRef(this); }); if (errCode != E_OK) { @@ -862,7 +854,7 @@ void CommunicatorAggregator::TriggerVersionNegotiation(const std::string &dstTar return; } - TaskConfig config{true, 0, Priority::HIGH}; + TaskConfig config{true, true, 0, Priority::HIGH}; errCode = ScheduleSendTask(dstTarget, buffer, FrameType::EMPTY, config); if (errCode != E_OK) { LOGE("[CommAggr][TrigVer] Send empty frame fail, errCode=%d", errCode); @@ -873,7 +865,7 @@ void CommunicatorAggregator::TriggerVersionNegotiation(const std::string &dstTar } void CommunicatorAggregator::TryToFeedbackWhenCommunicatorNotFound(const std::string &dstTarget, - const LabelType &dstLabel, const SerialBuffer *inOriFrame) + const LabelType &dstLabel, const SerialBuffer *inOriFrame, int inErrCode) { if (!isCommunicatorNotFoundFeedbackEnable_ || dstTarget.empty() || inOriFrame == nullptr) { return; @@ -887,11 +879,11 @@ void CommunicatorAggregator::TryToFeedbackWhenCommunicatorNotFound(const std::st return; } // Message is release in TriggerCommunicatorNotFoundFeedback - TriggerCommunicatorNotFoundFeedback(dstTarget, dstLabel, message); + TriggerCommunicatorNotFoundFeedback(dstTarget, dstLabel, message, inErrCode); } void CommunicatorAggregator::TriggerCommunicatorNotFoundFeedback(const std::string &dstTarget, - const LabelType &dstLabel, Message* &oriMsg) + const LabelType &dstLabel, Message* &oriMsg, int sendErrNo) { if (oriMsg == nullptr || oriMsg->GetMessageType() != TYPE_REQUEST) { LOGI("[CommAggr][TrigNotFound] Do nothing for message with type not request."); @@ -903,7 +895,7 @@ void CommunicatorAggregator::TriggerCommunicatorNotFoundFeedback(const std::stri LOGI("[CommAggr][TrigNotFound] Do communicator not found feedback with target=%s{private}.", dstTarget.c_str()); oriMsg->SetMessageType(TYPE_RESPONSE); - oriMsg->SetErrorNo(E_FEEDBACK_COMMUNICATOR_NOT_FOUND); + oriMsg->SetErrorNo(sendErrNo); int errCode = E_OK; SerialBuffer *buffer = ProtocolProto::BuildFeedbackMessageFrame(oriMsg, dstLabel, errCode); @@ -914,7 +906,7 @@ void CommunicatorAggregator::TriggerCommunicatorNotFoundFeedback(const std::stri return; } - TaskConfig config{true, 0, Priority::HIGH}; + TaskConfig config{true, true, 0, Priority::HIGH}; errCode = ScheduleSendTask(dstTarget, buffer, FrameType::APPLICATION_MESSAGE, config); if (errCode != E_OK) { LOGE("[CommAggr][TrigNotFound] Send communicator not found feedback frame fail, errCode=%d", errCode); @@ -1102,12 +1094,12 @@ void CommunicatorAggregator::RetrySendTaskIfNeed(const std::string &target, uint std::lock_guard autoLock(retryCountMutex_); retryCount_[target] = 0; } else { + RetrySendTask(target, sendSequenceId); if (sendSequenceId != GetSendSequenceId(target)) { LOGD("[CommAggr] %.3s Send sequence id has changed", target.c_str()); return; } scheduler_.DelayTaskByTarget(target); - RetrySendTask(target, sendSequenceId); } } @@ -1170,5 +1162,51 @@ void CommunicatorAggregator::ClearOnlineLabel() } commLinker_->ClearOnlineLabel(); } + +int CommunicatorAggregator::ReTryDeliverAppLayerFrameOnCommunicatorNotFound(const ReceiveBytesInfo &receiveBytesInfo, + SerialBuffer *&inFrameBuffer, const ParseResult &inResult, const DataUserInfoProc &userInfoProc, + const UserInfo &userInfo) +{ + LabelType toLabel = inResult.GetCommLabel(); + int errCode = -E_NOT_FOUND; + { + std::lock_guard onCommLackLockGuard(onCommLackMutex_); + if (onCommLackHandle_) { + errCode = onCommLackHandle_(toLabel, userInfo.receiveUser); + LOGI("[CommAggr][AppReceive] On CommLack End."); // Log in case callback block this thread + } else { + LOGI("[CommAggr][AppReceive] CommLackHandle invalid currently."); + } + } + // Here we have to lock commMapMutex_ and search communicator again. + std::lock_guard commMapLockGuard(commMapMutex_); + int errCodeAgain = TryDeliverAppLayerFrameToCommunicatorNoMutex(userInfoProc, receiveBytesInfo.srcTarget, + inFrameBuffer, toLabel, userInfo); + if (errCodeAgain == E_OK) { // Attention: Here is equal to E_OK. + LOGI("[CommAggr][AppReceive] Communicator of %.3s found after try again(rare case).", VEC_TO_STR(toLabel)); + return E_OK; + } + // Here, communicator is still not found, retain or discard according to the result of onCommLackHandle_ + if (errCode != E_OK || errCodeAgain == -E_FEEDBACK_DB_CLOSING) { + TryToFeedbackWhenCommunicatorNotFound(receiveBytesInfo.srcTarget, toLabel, inFrameBuffer, + errCodeAgain == -E_FEEDBACK_DB_CLOSING ? E_FEEDBACK_DB_CLOSING : E_FEEDBACK_COMMUNICATOR_NOT_FOUND); + if (inFrameBuffer != nullptr) { + delete inFrameBuffer; + inFrameBuffer = nullptr; + } + return errCode == E_OK ? errCodeAgain : errCode; // The caller will display errCode in log + } + // Do Retention, the retainer is responsible to deal with the frame + retainer_.RetainFrame(FrameInfo{inFrameBuffer, receiveBytesInfo.srcTarget, userInfo.sendUser, toLabel, + inResult.GetFrameId()}); + inFrameBuffer = nullptr; + return E_OK; +} + +void CommunicatorAggregator::ResetRetryCount() +{ + std::lock_guard autoLock(retryCountMutex_); + retryCount_.clear(); +} DEFINE_OBJECT_TAG_FACILITIES(CommunicatorAggregator) } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_linker.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_linker.cpp index 3bf8832b..83513365 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_linker.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_linker.cpp @@ -394,7 +394,7 @@ void CommunicatorLinker::SendLabelExchange(const std::string &toTarget, SerialBu int error = E_OK; SerialBuffer *cloneBuffer = inBuff->Clone(error); - TaskConfig config{true, 0, Priority::HIGH}; + TaskConfig config{true, true, 0, Priority::HIGH}; int errCode = aggregator_->ScheduleSendTask(toTarget, inBuff, FrameType::COMMUNICATION_LABEL_EXCHANGE, config); if (errCode == E_OK) { // Send ok, go on to wait ack, and maybe resend @@ -452,7 +452,7 @@ void CommunicatorLinker::SendLabelExchangeAck(const std::string &toTarget, Seria return; } - TaskConfig config{true, 0, Priority::HIGH}; + TaskConfig config{true, true, 0, Priority::HIGH}; int errCode = aggregator_->ScheduleSendTask(toTarget, inBuff, FrameType::COMMUNICATION_LABEL_EXCHANGE_ACK, config); if (errCode == E_OK) { // Send ok, finish event diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/frame_retainer.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/frame_retainer.cpp index fc0eb0bb..b1b42011 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/frame_retainer.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/frame_retainer.cpp @@ -85,7 +85,7 @@ void FrameRetainer::RetainFrame(const FrameInfo &inFrame) if (inFrame.buffer == nullptr) { return; // Never gonna happen } - RetainWork work{inFrame.buffer, inFrame.frameId, MAX_RETAIN_TIME}; + RetainWork work{inFrame.buffer, inFrame.sendUser, inFrame.frameId, MAX_RETAIN_TIME}; if (work.buffer->GetSize() > MAX_RETAIN_FRAME_SIZE) { LOGE("[Retainer][Retain] Frame size=%u over limit=%u.", work.buffer->GetSize(), MAX_RETAIN_FRAME_SIZE); delete work.buffer; @@ -140,7 +140,7 @@ std::list FrameRetainer::FetchFramesForSpecificCommunicator(const Lab for (auto &entry : fetchOrder) { RetainWork &work = perLabel[entry.second][entry.first]; LogRetainInfo("[Retainer][Fetch] FETCH-OUT", inCommLabel, entry.second, entry.first, work); - outFrameList.emplace_back(FrameInfo{work.buffer, entry.second, inCommLabel, work.frameId}); + outFrameList.emplace_back(FrameInfo{work.buffer, entry.second, work.sendUser, inCommLabel, work.frameId}); // Update statistics totalSizeByByte_ -= work.buffer->GetSize(); totalRetainFrames_--; diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/network_adapter.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/network_adapter.cpp index d3071c96..6a4ac21b 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/network_adapter.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/network_adapter.cpp @@ -104,7 +104,7 @@ int NetworkAdapter::StartAdapter() // so processCommunicator_ won't be null void NetworkAdapter::StopAdapter() { - LOGI("[NAdapt][Stop] Enter, ProcessLabel=%s.", processLabel_.c_str()); + LOGI("[NAdapt][Stop] Enter."); processCommunicator_->RegOnSendAble(nullptr); DBStatus errCode = processCommunicator_->RegOnDeviceChange(nullptr); if (errCode != DBStatus::OK) { @@ -232,15 +232,21 @@ int NetworkAdapter::GetLocalIdentity(std::string &outTarget) } int NetworkAdapter::SendBytes(const std::string &dstTarget, const uint8_t *bytes, uint32_t length, uint32_t totalLength) +{ + DeviceInfos dstDevInfo; + dstDevInfo.identifier = dstTarget; + return SendBytes(dstDevInfo, bytes, length, totalLength); +} + +int NetworkAdapter::SendBytes(const DeviceInfos &deviceInfos, const uint8_t *bytes, uint32_t length, + uint32_t totalLength) { if (bytes == nullptr || length == 0) { return -E_INVALID_ARGS; } - LOGI("[NAdapt][SendBytes] Enter, to=%s{private}, length=%u, totalLength=%u", dstTarget.c_str(), length, + LOGI("[NAdapt][SendBytes] Enter, to=%s{private}, length=%u, totalLength=%u", deviceInfos.identifier.c_str(), length, totalLength); - DeviceInfos dstDevInfo; - dstDevInfo.identifier = dstTarget; - DBStatus errCode = processCommunicator_->SendData(dstDevInfo, bytes, length, + DBStatus errCode = processCommunicator_->SendData(deviceInfos, bytes, length, totalLength > length ? totalLength : length); if (errCode == DBStatus::RATE_LIMIT) { LOGD("[NAdapt][SendBytes] rate limit!"); @@ -253,7 +259,7 @@ int NetworkAdapter::SendBytes(const std::string &dstTarget, const uint8_t *bytes // OnDeviceChangeHandler is reused but check the existence of peer process is done outerly. // Since this thread is the sending_thread of the CommunicatorAggregator, // We need an async task which bring about dependency on the lifecycle of this NetworkAdapter Object. - CheckDeviceOfflineAfterSendFail(dstDevInfo); + CheckDeviceOfflineAfterSendFail(deviceInfos); return static_cast(errCode); } return E_OK; @@ -284,11 +290,16 @@ void NetworkAdapter::OnDataReceiveHandler(const DeviceInfos &srcDevInfo, const u return; } uint32_t headLength = 0; - DBStatus errCode = processCommunicator_->GetDataHeadInfo(data, length, headLength); + DataHeadInfo dataHeadInfo = {data, length, srcDevInfo.identifier}; + DBStatus errCode = processCommunicator_->GetDataHeadInfo(dataHeadInfo, headLength); LOGI("[NAdapt][OnDataRecv] Enter, from=%s{private}, extendHeadLength=%u, totalLength=%u", srcDevInfo.identifier.c_str(), headLength, length); + bool isNeedGetUserInfo = headLength != 0; if (errCode != OK) { - LOGW("[NAdapt][OnDataRecv] get data head info err, drop packet, errCode=%d", errCode); + LOGW("[NAdapt][OnDataRecv] get data head info err, errCode=%d", errCode); + if (errCode == LOW_VERSION_TARGET) { + isNeedGetUserInfo = true; + } } if (headLength >= length) { LOGW("[NAdapt][OnDataRecv] head len is too big, drop packet"); @@ -301,7 +312,9 @@ void NetworkAdapter::OnDataReceiveHandler(const DeviceInfos &srcDevInfo, const u return; } DataUserInfoProc userInfoProc = {data, length, processCommunicator_}; - onReceiveHandle_(srcDevInfo.identifier, data + headLength, length - headLength, userInfoProc); + ReceiveBytesInfo receiveBytesInfo = {data + headLength, srcDevInfo.identifier, length - headLength, + isNeedGetUserInfo}; + onReceiveHandle_(receiveBytesInfo, userInfoProc); } // These code is compensation for the probable defect of IProcessCommunicator implementation. // As described in the agreement, for the missed online situation, we check the source dev when received. diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.cpp index d5339ebb..158ef713 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/protocol_proto.cpp @@ -360,12 +360,14 @@ int ProtocolProto::CombinePacketIntoFrame(SerialBuffer *inFrame, const uint8_t * { // inFrame is the destination, pktBytes and pktLength are the source, fragOffset and fragLength give the boundary // Firstly: Check the length relation of source, even this check is not supposed to fail - if (sizeof(CommPhyHeader) + sizeof(CommPhyOptHeader) + fragLength > pktLength) { + if (sizeof(CommPhyHeader) + sizeof(CommPhyOptHeader) + fragLength > pktLength || + sizeof(CommPhyHeader) + static_cast(fragOffset) + static_cast(fragLength) > UINT32_MAX) { return -E_LENGTH_ERROR; } // Secondly: Check the length relation of destination, even this check is not supposed to fail auto frameByteLen = inFrame->GetWritableBytesForEntireFrame(); - if (sizeof(CommPhyHeader) + fragOffset + fragLength > frameByteLen.second) { + if (frameByteLen.first == nullptr || sizeof(CommPhyHeader) + fragOffset + fragLength > frameByteLen.second || + sizeof(CommPhyHeader) + fragOffset > frameByteLen.second) { return -E_LENGTH_ERROR; } // Finally: Do Combination! @@ -715,7 +717,8 @@ bool ProtocolProto::IsSupportMessageVersion(uint16_t version) bool ProtocolProto::IsFeedbackErrorMessage(uint32_t errorNo) { - return (errorNo == E_FEEDBACK_UNKNOWN_MESSAGE || errorNo == E_FEEDBACK_COMMUNICATOR_NOT_FOUND); + return (errorNo == E_FEEDBACK_UNKNOWN_MESSAGE || errorNo == E_FEEDBACK_COMMUNICATOR_NOT_FOUND || + errorNo == E_FEEDBACK_DB_CLOSING); } int ProtocolProto::ParseCommPhyHeaderCheckMagicAndVersion(const uint8_t *bytes, uint32_t length) diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/send_task_scheduler.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/send_task_scheduler.cpp index d3df2bab..abdae735 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/send_task_scheduler.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/send_task_scheduler.cpp @@ -318,5 +318,28 @@ void SendTaskScheduler::SetDeviceCommErrCode(const std::string &target, int devi { std::lock_guard overallLockGuard(overallMutex_); deviceCommErrCodeMap_[target] = deviceCommErrCode; + if (deviceCommErrCode == E_OK) { + return; + } + for (const auto &priority : priorityOrder_) { + if (taskCountByPrio_[priority] == 0 || + taskGroupByPrio_[priority].find(target) == taskGroupByPrio_[priority].end()) { + // No task of this priority or target + continue; + } + for (auto &sendTask : taskGroupByPrio_[priority][target]) { + if (sendTask.isRetryTask) { + continue; + } + LOGI("[Scheduler][SetDeviceCommErrCode] Erase task that do not allow retries, target=%.3s", + target.c_str()); + sendTask.isValid = false; + if (sendTask.onEnd) { + LOGI("[Scheduler][SetDeviceCommErrCode] On Send End, target=%.3s", target.c_str()); + sendTask.onEnd(deviceCommErrCodeMap_[target], true); + sendTask.onEnd = nullptr; + } + } + } } } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/distributeddb.gni b/kv_store/frameworks/libs/distributeddb/distributeddb.gni index def61407..42d57698 100644 --- a/kv_store/frameworks/libs/distributeddb/distributeddb.gni +++ b/kv_store/frameworks/libs/distributeddb/distributeddb.gni @@ -26,8 +26,8 @@ distributeddb_src = [ "${distributeddb_path}/common/src/data_compression.cpp", "${distributeddb_path}/common/src/data_value.cpp", "${distributeddb_path}/common/src/db_common.cpp", + "${distributeddb_path}/common/src/db_common_client.cpp", "${distributeddb_path}/common/src/db_base64_utils.cpp", - "${distributeddb_path}/common/src/db_constant.cpp", "${distributeddb_path}/common/src/db_dfx_adapter.cpp", "${distributeddb_path}/common/src/db_dump_helper.cpp", "${distributeddb_path}/common/src/evloop/src/event_impl.cpp", @@ -43,6 +43,7 @@ distributeddb_src = [ "${distributeddb_path}/common/src/log_print.cpp", "${distributeddb_path}/common/src/notification_chain.cpp", "${distributeddb_path}/common/src/param_check_utils.cpp", + "${distributeddb_path}/common/src/param_check_utils_client.cpp", "${distributeddb_path}/common/src/parcel.cpp", "${distributeddb_path}/common/src/performance_analysis.cpp", "${distributeddb_path}/common/src/platform_specific.cpp", @@ -62,6 +63,7 @@ distributeddb_src = [ "${distributeddb_path}/common/src/schema_negotiate.cpp", "${distributeddb_path}/common/src/schema_object.cpp", "${distributeddb_path}/common/src/schema_utils.cpp", + "${distributeddb_path}/common/src/schema_utils_client.cpp", "${distributeddb_path}/common/src/semaphore_utils.cpp", "${distributeddb_path}/common/src/task_pool.cpp", "${distributeddb_path}/common/src/task_pool_impl.cpp", @@ -96,10 +98,11 @@ distributeddb_src = [ "${distributeddb_path}/interfaces/src/relational/relational_store_changed_data_impl.cpp", "${distributeddb_path}/interfaces/src/relational/relational_store_delegate_impl.cpp", "${distributeddb_path}/interfaces/src/relational/relational_store_manager.cpp", - "${distributeddb_path}/interfaces/src/relational/relational_store_sqlite_ext.cpp", + "${distributeddb_path}/interfaces/src/relational/relational_store_manager_client.cpp", "${distributeddb_path}/interfaces/src/runtime_config.cpp", "${distributeddb_path}/storage/src/cloud/cloud_meta_data.cpp", "${distributeddb_path}/storage/src/cloud/cloud_storage_utils.cpp", + "${distributeddb_path}/storage/src/cloud/cloud_storage_utils_client.cpp", "${distributeddb_path}/storage/src/cloud/cloud_upload_recorder.cpp", "${distributeddb_path}/storage/src/cloud/schema_mgr.cpp", "${distributeddb_path}/storage/src/data_transformer.cpp", @@ -171,6 +174,7 @@ distributeddb_src = [ "${distributeddb_path}/storage/src/sqlite/relational/sqlite_relational_store.cpp", "${distributeddb_path}/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp", "${distributeddb_path}/storage/src/sqlite/relational/sqlite_relational_utils.cpp", + "${distributeddb_path}/storage/src/sqlite/relational/sqlite_relational_utils_client.cpp", "${distributeddb_path}/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp", "${distributeddb_path}/storage/src/sqlite/relational/sqlite_single_ver_relational_continue_token.cpp", "${distributeddb_path}/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp", @@ -201,6 +205,7 @@ distributeddb_src = [ "${distributeddb_path}/storage/src/sqlite/sqlite_storage_engine.cpp", "${distributeddb_path}/storage/src/sqlite/sqlite_storage_executor.cpp", "${distributeddb_path}/storage/src/sqlite/sqlite_utils.cpp", + "${distributeddb_path}/storage/src/sqlite/sqlite_utils_client.cpp", "${distributeddb_path}/storage/src/sqlite/sqlite_utils_extend.cpp", "${distributeddb_path}/storage/src/storage_engine.cpp", "${distributeddb_path}/storage/src/storage_engine_manager.cpp", @@ -252,6 +257,7 @@ distributeddb_src = [ "${distributeddb_path}/syncer/src/sync_config.cpp", "${distributeddb_path}/syncer/src/sync_operation.cpp", "${distributeddb_path}/syncer/src/time_helper.cpp", + "${distributeddb_path}/syncer/src/time_helper_client.cpp", ] distributeddb_cloud_src = [ @@ -263,6 +269,7 @@ distributeddb_cloud_src = [ "${distributeddb_path}/syncer/src/cloud/cloud_locker.cpp", "${distributeddb_path}/syncer/src/cloud/cloud_syncer.cpp", "${distributeddb_path}/syncer/src/cloud/cloud_syncer_extend.cpp", + "${distributeddb_path}/syncer/src/cloud/cloud_syncer_extend_extend.cpp", "${distributeddb_path}/syncer/src/cloud/cloud_sync_state_machine.cpp", "${distributeddb_path}/syncer/src/cloud/cloud_sync_tag_assets.cpp", "${distributeddb_path}/syncer/src/cloud/cloud_sync_utils.cpp", @@ -300,3 +307,32 @@ distributeddb_src_rd = [ "${distributeddb_path}/gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.cpp", "${distributeddb_path}/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp", ] + +distributeddb_base_src = [ + "${distributeddb_path}/common/src/concurrent_adapter.cpp", + "${distributeddb_path}/common/src/db_common_client.cpp", + "${distributeddb_path}/common/src/json_object.cpp", + "${distributeddb_path}/common/src/log_print.cpp", + "${distributeddb_path}/common/src/param_check_utils_client.cpp", + "${distributeddb_path}/common/src/platform_specific.cpp", + "${distributeddb_path}/common/src/relational/relational_schema_object.cpp", + "${distributeddb_path}/common/src/relational/table_info.cpp", + "${distributeddb_path}/common/src/relational/tracker_table.cpp", + "${distributeddb_path}/common/src/schema_constant.cpp", + "${distributeddb_path}/common/src/schema_utils_client.cpp", + "${distributeddb_path}/interfaces/src/relational/relational_store_manager_client.cpp", + "${distributeddb_path}/interfaces/src/kv_store_errno.cpp", + "${distributeddb_path}/storage/src/cloud/cloud_storage_utils_client.cpp", + "${distributeddb_path}/storage/src/sqlite/relational/cloud_sync_log_table_manager.cpp", + "${distributeddb_path}/storage/src/sqlite/relational/simple_tracker_log_table_manager.cpp", + "${distributeddb_path}/storage/src/sqlite/relational/split_device_log_table_manager.cpp", + "${distributeddb_path}/storage/src/sqlite/relational/sqlite_relational_utils_client.cpp", + "${distributeddb_path}/storage/src/sqlite/sqlite_log_table_manager.cpp", + "${distributeddb_path}/storage/src/sqlite/sqlite_utils_client.cpp", + "${distributeddb_path}/syncer/src/time_helper_client.cpp", +] + +distributeddb_client_src = [ + "${distributeddb_path}/interfaces/src/relational/knowledge_source_utils.cpp", + "${distributeddb_path}/interfaces/src/relational/relational_store_sqlite_ext.cpp", +] \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/grd_api_manager.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/grd_api_manager.h index 7acb79c2..2ef9eb06 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/grd_api_manager.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/grd_api_manager.h @@ -56,7 +56,7 @@ typedef int32_t (*KVBatchPushback)(const void *key, uint32_t keyLen, const void GRD_KVBatchT *batch); typedef int32_t (*KVBatchPut)(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch); typedef int32_t (*KVBatchDel)(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch); -typedef int32_t (*KVBatchDestory)(GRD_KVBatchT *batch); +typedef int32_t (*KVBatchDestroy)(GRD_KVBatchT *batch); struct GRD_APIInfo { DBOpen DBOpenApi = nullptr; DBClose DBCloseApi = nullptr; @@ -89,9 +89,11 @@ struct GRD_APIInfo { KVBatchPushback KVBatchPushbackApi = nullptr; KVBatchDel KVBatchPutApi = nullptr; KVBatchDel KVBatchDelApi = nullptr; - KVBatchDestory KVBatchDestoryApi = nullptr; + KVBatchDestroy KVBatchDestroyApi = nullptr; }; -GRD_APIInfo GetApiInfoInstance(); +GRD_APIInfo *GetApiInfo(); +void GetApiInfoInstance(void); void InitApiInfo(const char *configStr); +void UnloadApiInfo(GRD_APIInfo *GRD_DBApiInfo); } // namespace DocumentDB #endif // __cplusplus diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/grd_api_manager.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/grd_api_manager.cpp index 4352bf10..884613d2 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/grd_api_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/grd_api_manager.cpp @@ -33,6 +33,8 @@ #ifndef _WIN32 static void *g_library = nullptr; +static int g_openCount = 0; +static std::mutex g_apiInfoMutex; #endif static bool g_isGmdbLib = false; @@ -69,7 +71,7 @@ void GRD_DBApiInitCommon(GRD_APIInfo &GRD_DBApiInfo) GRD_DBApiInfo.KVBatchPushbackApi = GRD_KVBatchPushbackInner; GRD_DBApiInfo.KVBatchPutApi = GRD_KVBatchPutInner; GRD_DBApiInfo.KVBatchDelApi = GRD_KVBatchDelInner; - GRD_DBApiInfo.KVBatchDestoryApi = GRD_KVBatchDestroyInner; + GRD_DBApiInfo.KVBatchDestroyApi = GRD_KVBatchDestroyInner; } void GRD_DBApiInitEnhance(GRD_APIInfo &GRD_DBApiInfo) @@ -106,7 +108,7 @@ void GRD_DBApiInitEnhance(GRD_APIInfo &GRD_DBApiInfo) GRD_DBApiInfo.KVBatchPushbackApi = (KVBatchPushback)dlsym(g_library, "GRD_KVBatchPushback"); GRD_DBApiInfo.KVBatchPutApi = (KVBatchPut)dlsym(g_library, "GRD_KVBatchPut"); GRD_DBApiInfo.KVBatchDelApi = (KVBatchDel)dlsym(g_library, "GRD_KVBatchDel"); - GRD_DBApiInfo.KVBatchDestoryApi = (KVBatchDestory)dlsym(g_library, "GRD_KVBatchDestroy"); + GRD_DBApiInfo.KVBatchDestroyApi = (KVBatchDestroy)dlsym(g_library, "GRD_KVBatchDestroy"); #endif } @@ -115,18 +117,44 @@ void InitApiInfo(const char *configStr) g_isGmdbLib = (configStr != nullptr); } -GRD_APIInfo GetApiInfoInstance() +static GRD_APIInfo GRD_ApiInfo; + +GRD_APIInfo *GetApiInfo(void) +{ + return &GRD_ApiInfo; +} + +void GetApiInfoInstance(void) { - GRD_APIInfo GRD_TempApiStruct; #ifndef _WIN32 + std::lock_guard lock(g_apiInfoMutex); + g_openCount++; + if (g_library != nullptr) { + return; + } std::string libPath = g_isGmdbLib ? "libarkdata_db_core.z.so" : "libgaussdb_rd.z.so"; g_library = dlopen(libPath.c_str(), RTLD_LAZY); if (!g_library) { - GRD_DBApiInitCommon(GRD_TempApiStruct); // When calling specific function, read whether init is successful. + GRD_DBApiInitCommon(GRD_ApiInfo); // When calling specific function, read whether init is successful. } else { - GRD_DBApiInitEnhance(GRD_TempApiStruct); + GRD_DBApiInitEnhance(GRD_ApiInfo); + } +#endif +} + +void UnloadApiInfo(GRD_APIInfo *GRD_DBApiInfo) +{ +#ifndef _WIN32 + std::lock_guard lock(g_apiInfoMutex); + g_openCount--; + if (g_library == nullptr) { + return; + } + if (g_openCount == 0) { + dlclose(g_library); + *GRD_DBApiInfo = {0}; + g_library = nullptr; } #endif - return GRD_TempApiStruct; } } // namespace DocumentDB diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api.cpp index 07e5a1e8..e54b4e58 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api.cpp @@ -23,80 +23,82 @@ #include "rd_log_print.h" using namespace DocumentDB; -static GRD_APIInfo GRD_DBApiInfo; +static GRD_APIInfo *GRD_DBApiInfo = GetApiInfo(); GRD_API int32_t GRD_DBOpen(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB **db) { - if (GRD_DBApiInfo.DBOpenApi == nullptr) { - InitApiInfo(configStr); - GRD_DBApiInfo = GetApiInfoInstance(); - } - if (GRD_DBApiInfo.DBOpenApi == nullptr) { + InitApiInfo(configStr); + GetApiInfoInstance(); + if (GRD_DBApiInfo->DBOpenApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DBApiInfo.DBOpenApi(dbPath, configStr, flags, db); + int32_t ret = GRD_DBApiInfo->DBOpenApi(dbPath, configStr, flags, db); + if (ret != GRD_OK) { + GLOGE("Fail to open db"); + UnloadApiInfo(GRD_DBApiInfo); + return ret; + } + return ret; } GRD_API int32_t GRD_DBClose(GRD_DB *db, uint32_t flags) { - if (GRD_DBApiInfo.DBCloseApi == nullptr) { - GRD_DBApiInfo = GetApiInfoInstance(); - } - if (GRD_DBApiInfo.DBCloseApi == nullptr) { + if (GRD_DBApiInfo->DBCloseApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DBApiInfo.DBCloseApi(db, flags); + int32_t ret = GRD_DBApiInfo->DBCloseApi(db, flags); + if (ret != GRD_OK) { + GLOGE("Fail to close db"); + } + UnloadApiInfo(GRD_DBApiInfo); + return ret; } GRD_API int32_t GRD_DBBackup(GRD_DB *db, const char *backupDbFile, uint8_t *encryptedKey, uint32_t encryptedKeyLen) { - if (GRD_DBApiInfo.DBBackupApi == nullptr) { - GRD_DBApiInfo = GetApiInfoInstance(); - } - if (GRD_DBApiInfo.DBBackupApi == nullptr) { + if (GRD_DBApiInfo->DBBackupApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } GRD_CipherInfoT cipherInfo = {.hexPassword = nullptr}; - return GRD_DBApiInfo.DBBackupApi(db, backupDbFile, &cipherInfo); + return GRD_DBApiInfo->DBBackupApi(db, backupDbFile, &cipherInfo); } GRD_API int32_t GRD_DBRestore(const char *dbFile, const char *backupDbFile, uint8_t *decryptedKey, uint32_t decryptedKeyLen) { - if (GRD_DBApiInfo.DBRestoreApi == nullptr) { - GRD_DBApiInfo = GetApiInfoInstance(); - } - if (GRD_DBApiInfo.DBRestoreApi == nullptr) { + // db restore operation will start after dbclose, should reload so to link api func + GetApiInfoInstance(); + if (GRD_DBApiInfo->DBRestoreApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); + UnloadApiInfo(GRD_DBApiInfo); return GRD_INNER_ERR; } GRD_CipherInfoT cipherInfo = {.hexPassword = nullptr}; - return GRD_DBApiInfo.DBRestoreApi(dbFile, backupDbFile, &cipherInfo); + int32_t ret = GRD_DBApiInfo->DBRestoreApi(dbFile, backupDbFile, &cipherInfo); + if (ret != GRD_OK) { + GLOGE("Fail to restore db"); + } + UnloadApiInfo(GRD_DBApiInfo); + return ret; } GRD_API int32_t GRD_Flush(GRD_DB *db, uint32_t flags) { - if (GRD_DBApiInfo.FlushApi == nullptr) { - GRD_DBApiInfo = GetApiInfoInstance(); - } - if (GRD_DBApiInfo.FlushApi == nullptr) { + if (GRD_DBApiInfo->FlushApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DBApiInfo.FlushApi(db, flags); + return GRD_DBApiInfo->FlushApi(db, flags); } GRD_API int32_t GRD_IndexPreload(GRD_DB *db, const char *collectionName) { - if (GRD_DBApiInfo.IndexPreloadApi == nullptr) { - GRD_DBApiInfo = GetApiInfoInstance(); - } - if (GRD_DBApiInfo.IndexPreloadApi == nullptr) { + if (GRD_DBApiInfo->IndexPreloadApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DBApiInfo.IndexPreloadApi(db, collectionName); + return GRD_DBApiInfo->IndexPreloadApi(db, collectionName); } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_document_api.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_document_api.cpp index accc95d7..56451d8b 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_document_api.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_document_api.cpp @@ -23,91 +23,70 @@ #include "rd_log_print.h" using namespace DocumentDB; -static GRD_APIInfo GRD_DocApiInfo; +static GRD_APIInfo *GRD_DocApiInfo = GetApiInfo(); GRD_API int32_t GRD_CreateCollection(GRD_DB *db, const char *collectionName, const char *optionStr, uint32_t flags) { - if (GRD_DocApiInfo.CreateCollectionApi == nullptr) { - GRD_DocApiInfo = GetApiInfoInstance(); - } - if (GRD_DocApiInfo.CreateCollectionApi == nullptr) { + if (GRD_DocApiInfo->CreateCollectionApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DocApiInfo.CreateCollectionApi(db, collectionName, optionStr, flags); + return GRD_DocApiInfo->CreateCollectionApi(db, collectionName, optionStr, flags); } GRD_API int32_t GRD_DropCollection(GRD_DB *db, const char *collectionName, uint32_t flags) { - if (GRD_DocApiInfo.DropCollectionApi == nullptr) { - GRD_DocApiInfo = GetApiInfoInstance(); - } - if (GRD_DocApiInfo.DropCollectionApi == nullptr) { + if (GRD_DocApiInfo->DropCollectionApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DocApiInfo.DropCollectionApi(db, collectionName, flags); + return GRD_DocApiInfo->DropCollectionApi(db, collectionName, flags); } GRD_API int32_t GRD_UpdateDoc(GRD_DB *db, const char *collectionName, const char *filter, const char *update, uint32_t flags) { - if (GRD_DocApiInfo.UpdateDocApi == nullptr) { - GRD_DocApiInfo = GetApiInfoInstance(); - } - if (GRD_DocApiInfo.UpdateDocApi == nullptr) { + if (GRD_DocApiInfo->UpdateDocApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DocApiInfo.UpdateDocApi(db, collectionName, filter, update, flags); + return GRD_DocApiInfo->UpdateDocApi(db, collectionName, filter, update, flags); } GRD_API int32_t GRD_UpsertDoc(GRD_DB *db, const char *collectionName, const char *filter, const char *document, uint32_t flags) { - if (GRD_DocApiInfo.UpsertDocApi == nullptr) { - GRD_DocApiInfo = GetApiInfoInstance(); - } - if (GRD_DocApiInfo.UpsertDocApi == nullptr) { + if (GRD_DocApiInfo->UpsertDocApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DocApiInfo.UpsertDocApi(db, collectionName, filter, document, flags); + return GRD_DocApiInfo->UpsertDocApi(db, collectionName, filter, document, flags); } GRD_API int32_t GRD_InsertDoc(GRD_DB *db, const char *collectionName, const char *document, uint32_t flags) { - if (GRD_DocApiInfo.InsertDocApi == nullptr) { - GRD_DocApiInfo = GetApiInfoInstance(); - } - if (GRD_DocApiInfo.InsertDocApi == nullptr) { + if (GRD_DocApiInfo->InsertDocApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DocApiInfo.InsertDocApi(db, collectionName, document, flags); + return GRD_DocApiInfo->InsertDocApi(db, collectionName, document, flags); } GRD_API int32_t GRD_DeleteDoc(GRD_DB *db, const char *collectionName, const char *filter, uint32_t flags) { - if (GRD_DocApiInfo.DeleteDocApi == nullptr) { - GRD_DocApiInfo = GetApiInfoInstance(); - } - if (GRD_DocApiInfo.DeleteDocApi == nullptr) { + if (GRD_DocApiInfo->DeleteDocApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DocApiInfo.DeleteDocApi(db, collectionName, filter, flags); + return GRD_DocApiInfo->DeleteDocApi(db, collectionName, filter, flags); } GRD_API int32_t GRD_FindDoc(GRD_DB *db, const char *collectionName, Query query, uint32_t flags, GRD_ResultSet **resultSet) { - if (GRD_DocApiInfo.FindDocApi == nullptr) { - GRD_DocApiInfo = GetApiInfoInstance(); - } - if (GRD_DocApiInfo.FindDocApi == nullptr) { + if (GRD_DocApiInfo->FindDocApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DocApiInfo.FindDocApi(db, collectionName, query, flags, resultSet); + return GRD_DocApiInfo->FindDocApi(db, collectionName, query, flags, resultSet); } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_resultset_api.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_resultset_api.cpp index 5e905677..39e31272 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_resultset_api.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_resultset_api.cpp @@ -21,76 +21,58 @@ #include "rd_log_print.h" using namespace DocumentDB; -static GRD_APIInfo GRD_ResultSetApiInfo; +static GRD_APIInfo *GRD_ResultSetApiInfo = GetApiInfo(); GRD_API int32_t GRD_Next(GRD_ResultSet *resultSet) { - if (GRD_ResultSetApiInfo.NextApi == nullptr) { - GRD_ResultSetApiInfo = GetApiInfoInstance(); - } - if (GRD_ResultSetApiInfo.NextApi == nullptr) { + if (GRD_ResultSetApiInfo->NextApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_ResultSetApiInfo.NextApi(resultSet); + return GRD_ResultSetApiInfo->NextApi(resultSet); } GRD_API int32_t GRD_GetValue(GRD_ResultSet *resultSet, char **value) { - if (GRD_ResultSetApiInfo.GetValueApi == nullptr) { - GRD_ResultSetApiInfo = GetApiInfoInstance(); - } - if (GRD_ResultSetApiInfo.GetValueApi == nullptr) { + if (GRD_ResultSetApiInfo->GetValueApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_ResultSetApiInfo.GetValueApi(resultSet, value); + return GRD_ResultSetApiInfo->GetValueApi(resultSet, value); } GRD_API int32_t GRD_FreeValue(char *value) { - if (GRD_ResultSetApiInfo.FreeValueApi == nullptr) { - GRD_ResultSetApiInfo = GetApiInfoInstance(); - } - if (GRD_ResultSetApiInfo.FreeValueApi == nullptr) { + if (GRD_ResultSetApiInfo->FreeValueApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_ResultSetApiInfo.FreeValueApi(value); + return GRD_ResultSetApiInfo->FreeValueApi(value); } GRD_API int32_t GRD_FreeResultSet(GRD_ResultSet *resultSet) { - if (GRD_ResultSetApiInfo.FreeResultSetApi == nullptr) { - GRD_ResultSetApiInfo = GetApiInfoInstance(); - } - if (GRD_ResultSetApiInfo.FreeResultSetApi == nullptr) { + if (GRD_ResultSetApiInfo->FreeResultSetApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_ResultSetApiInfo.FreeResultSetApi(resultSet); + return GRD_ResultSetApiInfo->FreeResultSetApi(resultSet); } GRD_API int32_t GRD_Prev(GRD_ResultSet *resultSet) { - if (GRD_ResultSetApiInfo.PrevApi == nullptr) { - GRD_ResultSetApiInfo = GetApiInfoInstance(); - } - if (GRD_ResultSetApiInfo.PrevApi == nullptr) { + if (GRD_ResultSetApiInfo->PrevApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_ResultSetApiInfo.PrevApi(resultSet); + return GRD_ResultSetApiInfo->PrevApi(resultSet); } GRD_API int32_t GRD_Fetch(GRD_ResultSet *resultSet, GRD_KVItemT *key, GRD_KVItemT *value) { - if (GRD_ResultSetApiInfo.FetchApi == nullptr) { - GRD_ResultSetApiInfo = GetApiInfoInstance(); - } - if (GRD_ResultSetApiInfo.FetchApi == nullptr) { + if (GRD_ResultSetApiInfo->FetchApi == nullptr) { GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_ResultSetApiInfo.FetchApi(resultSet, key, value); + return GRD_ResultSetApiInfo->FetchApi(resultSet, key, value); } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/kv/grd_kv_api.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/kv/grd_kv_api.cpp index 7f441a65..0693a05f 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/kv/grd_kv_api.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/kv/grd_kv_api.cpp @@ -21,150 +21,111 @@ #include "rd_log_print.h" using namespace DocumentDB; -static GRD_APIInfo GRD_KVApiInfo; +static GRD_APIInfo *GRD_KVApiInfo = GetApiInfo(); GRD_API int32_t GRD_KVPut(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, const GRD_KVItemT *value) { - if (GRD_KVApiInfo.KVPutApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVPutApi == nullptr) { + if (GRD_KVApiInfo->KVPutApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVPutApi(db, collectionName, key, value); + return GRD_KVApiInfo->KVPutApi(db, collectionName, key, value); } GRD_API int32_t GRD_KVGet(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, const GRD_KVItemT *value) { - if (GRD_KVApiInfo.KVGetApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVGetApi == nullptr) { + if (GRD_KVApiInfo->KVGetApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVGetApi(db, collectionName, key, value); + return GRD_KVApiInfo->KVGetApi(db, collectionName, key, value); } GRD_API int32_t GRD_KVDel(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key) { - if (GRD_KVApiInfo.KVDelApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVDelApi == nullptr) { + if (GRD_KVApiInfo->KVDelApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVDelApi(db, collectionName, key); + return GRD_KVApiInfo->KVDelApi(db, collectionName, key); } GRD_API int32_t GRD_KVScan(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, GRD_KvScanModeE mode, GRD_ResultSet **resultSet) { - if (GRD_KVApiInfo.KVScanApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVScanApi == nullptr) { + if (GRD_KVApiInfo->KVScanApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVScanApi(db, collectionName, key, mode, resultSet); + return GRD_KVApiInfo->KVScanApi(db, collectionName, key, mode, resultSet); } GRD_API int32_t GRD_KVFilter(GRD_DB *db, const char *collectionName, const GRD_FilterOptionT *scanParams, GRD_ResultSet **resultSet) { - if (GRD_KVApiInfo.KVFilterApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVFilterApi == nullptr) { + if (GRD_KVApiInfo->KVFilterApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVFilterApi(db, collectionName, scanParams, resultSet); + return GRD_KVApiInfo->KVFilterApi(db, collectionName, scanParams, resultSet); } GRD_API int32_t GRD_KVGetSize(GRD_ResultSet *resultSet, uint32_t *keyLen, uint32_t *valueLen) { - if (GRD_KVApiInfo.KVGetSizeApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVGetSizeApi == nullptr) { + if (GRD_KVApiInfo->KVGetSizeApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVGetSizeApi(resultSet, keyLen, valueLen); + return GRD_KVApiInfo->KVGetSizeApi(resultSet, keyLen, valueLen); } GRD_API int32_t GRD_GetItem(GRD_ResultSet *resultSet, void *key, void *value) { - if (GRD_KVApiInfo.GetItemApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.GetItemApi == nullptr) { + if (GRD_KVApiInfo->GetItemApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.GetItemApi(resultSet, key, value); + return GRD_KVApiInfo->GetItemApi(resultSet, key, value); } GRD_API int32_t GRD_KVFreeItem(GRD_KVItemT *item) { - if (GRD_KVApiInfo.KVFreeItemApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVFreeItemApi == nullptr) { + if (GRD_KVApiInfo->KVFreeItemApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVFreeItemApi(item); + return GRD_KVApiInfo->KVFreeItemApi(item); } GRD_API int32_t GRD_KVBatchPrepare(uint16_t itemNum, GRD_KVBatchT **batch) { - if (GRD_KVApiInfo.KVBatchPrepareApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVBatchPrepareApi == nullptr) { + if (GRD_KVApiInfo->KVBatchPrepareApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVBatchPrepareApi(itemNum, batch); + return GRD_KVApiInfo->KVBatchPrepareApi(itemNum, batch); } GRD_API int32_t GRD_KVBatchPushback(const void *key, uint32_t keyLen, const void *data, uint32_t dataLen, GRD_KVBatchT *batch) { - if (GRD_KVApiInfo.KVBatchPushbackApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVBatchPushbackApi == nullptr) { + if (GRD_KVApiInfo->KVBatchPushbackApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVBatchPushbackApi(key, keyLen, data, dataLen, batch); + return GRD_KVApiInfo->KVBatchPushbackApi(key, keyLen, data, dataLen, batch); } GRD_API int32_t GRD_KVBatchPut(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch) { - if (GRD_KVApiInfo.KVBatchPutApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVBatchPutApi == nullptr) { + if (GRD_KVApiInfo->KVBatchPutApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVBatchPutApi(db, collectionName, batch); + return GRD_KVApiInfo->KVBatchPutApi(db, collectionName, batch); } GRD_API int32_t GRD_KVBatchDel(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch) { - if (GRD_KVApiInfo.KVBatchDelApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVBatchDelApi == nullptr) { + if (GRD_KVApiInfo->KVBatchDelApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVBatchDelApi(db, collectionName, batch); + return GRD_KVApiInfo->KVBatchDelApi(db, collectionName, batch); } GRD_API int32_t GRD_KVBatchDestroy(GRD_KVBatchT *batch) { - if (GRD_KVApiInfo.KVBatchDestoryApi == nullptr) { - GRD_KVApiInfo = GetApiInfoInstance(); - } - if (GRD_KVApiInfo.KVBatchDestoryApi == nullptr) { + if (GRD_KVApiInfo->KVBatchDestroyApi == nullptr) { return GRD_INNER_ERR; } - return GRD_KVApiInfo.KVBatchDestoryApi(batch); + return GRD_KVApiInfo->KVBatchDestroyApi(batch); } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_key.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_key.cpp index 1666428a..eb2d2a20 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_key.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_key.cpp @@ -16,6 +16,7 @@ #include #include +#include #include "doc_errno.h" #include "rd_log_print.h" @@ -31,11 +32,18 @@ static int InitDocIdFromOid(DocKey &docKey) if (nowTime < 0) { return -E_INNER_ERROR; } - uint32_t now = (uint32_t)nowTime; - uint16_t iv = g_oIdIncNum++; + uint64_t nowTemp = static_cast(nowTime); + if (nowTemp > UINT32_MAX) { + GLOGE("Time overflows 32-bit range. nowTemp = %" PRIu64, nowTemp); + return -E_INNER_ERROR; + } + uint32_t now = static_cast(nowTemp); + uint16_t iv = g_oIdIncNum; // The maximum number of autoincrements is 65535, and if it is exceeded, it becomes 0. - if (g_oIdIncNum > MAX_NUMBER_OF_AUTOINCREMENTS) { + if (g_oIdIncNum == MAX_NUMBER_OF_AUTOINCREMENTS) { g_oIdIncNum = UINT_ZERO; + } else { + g_oIdIncNum++; } char *idTemp = new char[GRD_DOC_OID_HEX_SIZE + 1]; if (sprintf_s(idTemp, GRD_DOC_OID_HEX_SIZE + 1, "%08x%04x", now, iv) < 0) { diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp index 27bef4c1..c40cc76b 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp @@ -232,7 +232,7 @@ int RDSQLiteUtils::ExecSql(sqlite3 *db, const std::string &sql) char *errMsg = nullptr; int errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &errMsg); if (errCode != SQLITE_OK && errMsg != nullptr) { - GLOGE("Execute sql failed. %d err: %s", errCode, errMsg); + GLOGE("Execute sql failed. %d", errCode); } sqlite3_free(errMsg); diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/BUILD.gn b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/BUILD.gn index 8979be7d..98590b27 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/BUILD.gn @@ -12,7 +12,7 @@ # limitations under the License. import("//build/test.gni") -module_output_path = "kv_store/kv_store/gaussdb_rd" +module_output_path = "kv_store/gaussdb_rd" ############################################################################### config("module_private_config") { @@ -77,19 +77,15 @@ ohos_source_set("src_file") { configs = [ ":module_private_config" ] - deps = [ - "//third_party/googletest:gtest_main", - "//third_party/sqlite:sqlite", - ] - - configs += [ "//third_party/cJSON:cJSON_config" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps += [ "//third_party/cJSON:cjson" ] external_deps = [ + "cJSON:cjson", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "sqlite:sqlite", ] subsystem_name = "distributeddatamgr" @@ -117,23 +113,18 @@ template("gaussdb_rd_unittest") { debug = false } - deps += [ - ":src_file", - "//third_party/googletest:gmock_main", - "//third_party/googletest:gtest_main", - "//third_party/sqlite:sqlite", - ] - configs += [ "//third_party/cJSON:cJSON_config" ] + deps += [ ":src_file" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps += [ - "//third_party/cJSON:cjson", - "//third_party/openssl:libcrypto_shared", - ] external_deps = [ + "cJSON:cjson", "c_utils:utils", + "googletest:gmock_main", + "googletest:gtest_main", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] } } @@ -173,9 +164,8 @@ gaussdb_rd_unittest("DocumentDBDeleteTest") { ############################################################################### group("unittest") { testonly = true - deps = [ "//third_party/googletest:gmock" ] - deps += [ + deps = [ ":DocumentDBApiTest", ":DocumentDBCollectionTest", ":DocumentDBDataTest", diff --git a/kv_store/frameworks/libs/distributeddb/include/types_export.h b/kv_store/frameworks/libs/distributeddb/include/types_export.h index 73abe2cd..e8e1eb65 100644 --- a/kv_store/frameworks/libs/distributeddb/include/types_export.h +++ b/kv_store/frameworks/libs/distributeddb/include/types_export.h @@ -244,6 +244,11 @@ struct StoreInfo { std::string userId; std::string appId; std::string storeId; + + bool operator<(const StoreInfo &other) const + { + return std::tie(userId, appId, storeId) < std::tie(other.userId, other.appId, other.storeId); + } }; using TranslateToDeviceIdCallback = std::function; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h index 06f39763..50137d38 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h @@ -49,6 +49,14 @@ struct ClearMetaDataOption { std::set tableNameList; // an empty set means clearing meta data on all tables }; +enum class ClearKvMetaOpType : uint64_t { + CLEAN_CLOUD_WATERMARK = 0x01, // clear watermark of device to cloud sync +}; + +struct ClearKvMetaDataOption { + ClearKvMetaOpType type = ClearKvMetaOpType::CLEAN_CLOUD_WATERMARK; +}; + enum class AssetOpType { NO_CHANGE = 0, INSERT, @@ -210,6 +218,7 @@ struct CloudSyncConfig { int32_t maxUploadCount = 30; // default max upload 30 records int32_t maxUploadSize = 1024 * 512 * 3; // default max upload 1024 * 512 * 3 = 1.5m int32_t maxRetryConflictTimes = -1; // default max retry -1 is unlimited retry times + bool isSupportEncrypt = false; // default encryption is not supported }; struct AsyncDownloadAssetsConfig { diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/iprocess_communicator.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/iprocess_communicator.h index 0fdb757a..e72fd36d 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/iprocess_communicator.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/iprocess_communicator.h @@ -24,9 +24,18 @@ #include "store_types.h" namespace DistributedDB { +struct AccessInfos { + std::string appId; + std::string storeId; + std::string userId; + std::string subUserId; +}; + // The DeviceInfos may contain other fields(Can only be auxiliary information) besides identifier field in the future. struct DeviceInfos { std::string identifier; // An unique and fixed identifier representing a device, such as UUID. + AccessInfos callee; // A message frame's access info. + bool isRetryTask = true; }; struct ExtendInfo { @@ -37,8 +46,22 @@ struct ExtendInfo { std::string subUserId; }; +struct DataHeadInfo { + const uint8_t *data = nullptr; + uint32_t totalLen; + std::string device; +}; + +struct DataUserInfo { + const uint8_t *data = nullptr; + uint32_t totalLen; + const std::string label; + const std::string device; +}; + struct UserInfo { std::string receiveUser; + std::string sendUser; }; class ExtendHeaderHandle { @@ -60,6 +83,11 @@ public: { return OK; }; + + virtual std::string GetTargetUserId() + { + return ""; + } }; // In OnDeviceChange, all field of devInfo should be valid, isOnline true for online and false for offline. @@ -169,14 +197,13 @@ public: headLength = 0; return OK; } - virtual DBStatus GetDataHeadInfo(const uint8_t *data, uint32_t totalLen, uint32_t &headLength) + virtual DBStatus GetDataHeadInfo(DataHeadInfo dataHeadInfo, uint32_t &headLength) { headLength = 0; return OK; } // return NO_PERMISSION while no need to handle the dataBuff if remote device userId is not mate with local userId - virtual DBStatus GetDataUserInfo(const uint8_t *data, uint32_t totalLen, const std::string &label, - std::vector &userInfos) + virtual DBStatus GetDataUserInfo(DataUserInfo dataUserInfo, std::vector &userInfos) { return OK; } diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_delegate_manager.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_delegate_manager.h index d09f6c65..864d858b 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_delegate_manager.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_delegate_manager.h @@ -59,7 +59,7 @@ public: // Close a KvStore, return OK if close success. DB_API DBStatus CloseKvStore(KvStoreDelegate *kvStore); - DB_API DBStatus CloseKvStore(KvStoreNbDelegate *kvStore); + DB_API DBStatus CloseKvStore(KvStoreNbDelegate *kvStore, bool isCloseImmediately = true); // Used to delete a KvStore, return OK if delete success. DB_API DBStatus DeleteKvStore(const std::string &storeId); @@ -124,6 +124,8 @@ private: bool GetKvStoreParamCheck(const std::string &storeId, const KvStoreNbDelegate::Option &option, const std::function &callback) const; DBStatus SetObserverNotifier(KvStoreNbDelegate *kvStore, const KvStoreNbDelegate::Option &option); + void GetKvStoreInner(const std::string &storeId, const KvStoreNbDelegate::Option &option, + const std::function &callback, void *handle); const std::string &GetKvStorePath() const; static const std::string DEFAULT_PROCESS_APP_ID; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h index e9b3f73a..8c63e761 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h @@ -204,11 +204,23 @@ public: const std::function &devicesMap)> &onComplete, const Query &query, bool wait) = 0; + DB_API virtual DBStatus Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete) + { + return OK; + }; + // Sync with device, provides sync count information - DB_API virtual DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) = 0; + DB_API virtual DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) + { + return OK; + }; // Cancel sync by syncId - DB_API virtual DBStatus CancelSync(uint32_t syncId) = 0; + DB_API virtual DBStatus CancelSync(uint32_t syncId) + { + return OK; + }; // Check the integrity of this kvStore. DB_API virtual DBStatus CheckIntegrity() const = 0; @@ -306,12 +318,20 @@ public: // If device is empty, it would return all the entries which was written by local device. DB_API virtual DBStatus GetDeviceEntries(const std::string &device, std::vector &entries) const = 0; - DB_API virtual DatabaseStatus GetDatabaseStatus() const = 0; + DB_API virtual DatabaseStatus GetDatabaseStatus() const + { + return {}; + } DB_API virtual DBStatus OperateDataStatus([[gnu::unused]] uint32_t dataOperator) { return OK; } + + DB_API virtual DBStatus ClearMetaData([[gnu::unused]] ClearKvMetaDataOption option) + { + return OK; + } }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_client.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_client.h index c2cd1a65..aa94d296 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_client.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_client.h @@ -58,4 +58,19 @@ DB_API void RegisterDbHook(sqlite3 *db); DB_API void UnregisterDbHook(sqlite3 *db); DB_API DistributedDB::DBStatus CreateDataChangeTempTrigger(sqlite3 *db); + +namespace DistributedDB { +struct KnowledgeSourceSchema { + std::string tableName; + std::set extendColNames; + std::set knowledgeColNames; +}; +} + +DB_API DistributedDB::DBStatus SetKnowledgeSourceSchema(sqlite3 *db, + const DistributedDB::KnowledgeSourceSchema &schema); + +DB_API DistributedDB::DBStatus CleanDeletedData(sqlite3 *db, const std::string &tableName, uint64_t cursor); + +DB_API void Clean(bool isOpenSslClean); #endif // RELATIONAL_STORE_CLIENT_H diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h index d005d85a..78f69dfa 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h @@ -42,6 +42,8 @@ public: CipherPassword passwd; uint32_t iterateTimes = 0; DistributedTableMode tableMode = DistributedTableMode::SPLIT_BY_DEVICE; + bool isNeedCompressOnSync = false; + uint8_t compressionRate = 100; // Valid in [1, 100] }; struct StoreConfig { @@ -151,7 +153,8 @@ public: return {}; } - DB_API virtual DBStatus SetDistributedSchema([[gnu::unused]] const DistributedSchema &schema) + DB_API virtual DBStatus SetDistributedSchema([[gnu::unused]] const DistributedSchema &schema, + [[gnu::unused]] bool isForceUpgrade = false) { return OK; } @@ -165,6 +168,11 @@ public: { return OK; } + + DB_API virtual int32_t GetDeviceSyncTaskCount() + { + return 0; + } protected: virtual DBStatus RemoveDeviceDataInner(const std::string &device, ClearMode mode) = 0; virtual DBStatus CreateDistributedTableInner(const std::string &tableName, TableSyncType type) = 0; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_sqlite_ext.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_sqlite_ext.h index ab2f5ded..e788a68f 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_sqlite_ext.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_sqlite_ext.h @@ -15,7 +15,7 @@ #ifndef RELATIONAL_STORE_EXT_H #define RELATIONAL_STORE_EXT_H -#define SQLITE3_HW_EXPORT_SYMBOLS +#define SQLITE3_EXTRA_EXPORT_SYMBOLS // using the "sqlite3sym.h" in OHOS #ifndef USE_SQLITE_SYMBOLS @@ -29,6 +29,7 @@ struct sqlite3_api_routines_relational { int (*open)(const char *, sqlite3 **); int (*open16)(const void *, sqlite3 **); int (*open_v2)(const char *, sqlite3 **, int, const char *); + int (*is_support_binlog)(const char*); }; extern const struct sqlite3_api_routines_relational *sqlite3_export_relational_symbols; @@ -36,15 +37,20 @@ extern const struct sqlite3_api_routines_relational *sqlite3_export_relational_s #ifdef sqlite3_open #undef sqlite3_open #endif -#define sqlite3_open sqlite3_export_relational_symbols->open +#define sqlite3_open sqlite3_export_relational_symbols->open #ifdef sqlite3_open16 #undef sqlite3_open16 #endif -#define sqlite3_open16 sqlite3_export_relational_symbols->open16 +#define sqlite3_open16 sqlite3_export_relational_symbols->open16 #ifdef sqlite3_open_v2 #undef sqlite3_open_v2 #endif -#define sqlite3_open_v2 sqlite3_export_relational_symbols->open_v2 +#define sqlite3_open_v2 sqlite3_export_relational_symbols->open_v2 + +#ifdef sqlite3_is_support_binlog +#undef sqlite3_is_support_binlog +#endif +#define sqlite3_is_support_binlog sqlite3_export_relational_symbols->is_support_binlog #endif // RELATIONAL_STORE_EXT_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h index a75a5b42..41ddacd8 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h @@ -94,6 +94,7 @@ enum DBStatus { CLOUD_DISABLED, // the cloud switch has been turned off DISTRIBUTED_FIELD_DECREASE, // sync fewer specified columns than last time SKIP_ASSET, // workaround status for contact app assets download failure, need to ignore these failures + LOW_VERSION_TARGET, // The target device is a low version device BUTT_STATUS = 27394048 // end of status }; @@ -200,6 +201,7 @@ struct DeviceSyncOption { Query query; // isQuery must be set to true if the query is set bool isQuery = false; bool isWait = true; + bool isRetry = true; }; struct DeviceSyncInfo { @@ -258,6 +260,7 @@ static constexpr const char *SQLITE = "sqlite"; struct ChangeProperties { bool isTrackedDataChange = false; bool isP2pSyncDataChange = false; + bool isKnowledgeDataChange = false; }; enum IndexType : uint32_t { @@ -318,5 +321,18 @@ enum class DataOperator : uint32_t { UPDATE_TIME = 0x01, RESET_UPLOAD_CLOUD = 0x02 }; + +struct DeviceSyncTarget { + std::string device; + std::string userId; + DeviceSyncTarget(std::string device, std::string userId) : device(std::move(device)), userId(std::move(userId)) {} + bool operator<(const DeviceSyncTarget& other) const + { + if (device == other.device) { + return userId < other.userId; + } + return device < other.device; + } +}; } // namespace DistributedDB #endif // KV_STORE_TYPE_H diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp index f81b4791..82ec35f2 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp @@ -106,10 +106,10 @@ void InitPropWithNbOption(KvDBProperties &properties, const std::string &storePa if (option.isEncryptedDb) { properties.SetPassword(option.cipher, option.passwd); } - properties.SetBoolProp(KvDBProperties::COMPRESS_ON_SYNC, option.isNeedCompressOnSync); + properties.SetBoolProp(DBProperties::COMPRESS_ON_SYNC, option.isNeedCompressOnSync); if (option.isNeedCompressOnSync) { properties.SetIntProp( - KvDBProperties::COMPRESSION_RATE, ParamCheckUtils::GetValidCompressionRate(option.compressionRate)); + DBProperties::COMPRESSION_RATE, ParamCheckUtils::GetValidCompressionRate(option.compressionRate)); } properties.SetBoolProp(KvDBProperties::SYNC_DUAL_TUPLE_MODE, option.syncDualTupleMode); properties.SetBoolProp(KvDBProperties::LOCAL_ONLY, option.localOnly); @@ -304,28 +304,19 @@ bool KvStoreDelegateManager::GetKvStoreParamCheck(const std::string &storeId, co return true; } -void KvStoreDelegateManager::GetKvStore(const std::string &storeId, const KvStoreNbDelegate::Option &option, - const std::function &callback) +void KvStoreDelegateManager::GetKvStoreInner(const std::string &storeId, const KvStoreNbDelegate::Option &option, + const std::function &callback, void *handle) { - if (!GetKvStoreParamCheck(storeId, option, callback)) { - return; - } - auto tmpOption = option; - if (tmpOption.storageEngineType == std::string(GAUSSDB_RD)) { - DBCommon::LoadGrdLib(); - if (!DBCommon::IsGrdLibLoaded()) { - tmpOption.storageEngineType = std::string(SQLITE); - } - } // check if schema is supported and valid SchemaObject schema; - DBStatus retCode = CheckAndGetSchema(tmpOption.isMemoryDb, tmpOption.schema, schema); + DBStatus retCode = CheckAndGetSchema(option.isMemoryDb, option.schema, schema); if (retCode != OK) { + DBCommon::UnLoadGrdLib(handle); callback(retCode, nullptr); return; } KvDBProperties properties; - InitPropWithNbOption(properties, GetKvStorePath(), schema, tmpOption); + InitPropWithNbOption(properties, GetKvStorePath(), schema, option); DbIdParam dbIdParam = {appId_, userId_, storeId, subUser_, instanceId_}; DBCommon::SetDatabaseIds(properties, dbIdParam); @@ -333,6 +324,7 @@ void KvStoreDelegateManager::GetKvStore(const std::string &storeId, const KvStor IKvDBConnection *conn = GetOneConnectionWithRetry(properties, errCode); DBStatus status = TransferDBErrno(errCode); if (conn == nullptr) { + DBCommon::UnLoadGrdLib(handle); callback(status, nullptr); return; } @@ -341,13 +333,15 @@ void KvStoreDelegateManager::GetKvStore(const std::string &storeId, const KvStor if (kvStore == nullptr) { conn->Close(); conn = nullptr; + DBCommon::UnLoadGrdLib(handle); callback(DB_ERROR, nullptr); return; } - - status = SetObserverNotifier(kvStore, tmpOption); + kvStore->SetHandle(handle); + status = SetObserverNotifier(kvStore, option); if (status != OK) { CloseKvStore(kvStore); + DBCommon::UnLoadGrdLib(handle); callback(status, nullptr); return; } @@ -355,12 +349,29 @@ void KvStoreDelegateManager::GetKvStore(const std::string &storeId, const KvStor bool enAutoSync = false; (void)conn->Pragma(PRAGMA_AUTO_SYNC, static_cast(&enAutoSync)); - SecurityOption secOption = tmpOption.secOption; + SecurityOption secOption = option.secOption; (void)conn->Pragma(PRAGMA_TRIGGER_TO_MIGRATE_DATA, &secOption); callback(OK, kvStore); } +void KvStoreDelegateManager::GetKvStore(const std::string &storeId, const KvStoreNbDelegate::Option &option, + const std::function &callback) +{ + if (!GetKvStoreParamCheck(storeId, option, callback)) { + return; + } + auto tmpOption = option; + void *handle = nullptr; + if (tmpOption.storageEngineType == std::string(GAUSSDB_RD)) { + handle = DBCommon::LoadGrdLib(); + if (handle == nullptr) { + tmpOption.storageEngineType = std::string(SQLITE); + } + } + return GetKvStoreInner(storeId, tmpOption, callback, handle); +} + DBStatus KvStoreDelegateManager::CloseKvStore(KvStoreDelegate *kvStore) { #ifndef OMIT_MULTI_VER @@ -384,14 +395,14 @@ DBStatus KvStoreDelegateManager::CloseKvStore(KvStoreDelegate *kvStore) #endif } -DBStatus KvStoreDelegateManager::CloseKvStore(KvStoreNbDelegate *kvStore) +DBStatus KvStoreDelegateManager::CloseKvStore(KvStoreNbDelegate *kvStore, bool isCloseImmediately) { if (kvStore == nullptr) { return INVALID_ARGS; } auto kvStoreImpl = static_cast(kvStore); - DBStatus status = kvStoreImpl->Close(); + DBStatus status = kvStoreImpl->Close(isCloseImmediately); if (status == BUSY) { LOGD("NbDelegateImpl is busy now."); return BUSY; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp index 008c33e8..b24958fb 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp @@ -78,8 +78,12 @@ KvStoreNbDelegateImpl::~KvStoreNbDelegateImpl() LOGF("[KvStoreNbDelegate] Can't release directly"); return; } - conn_ = nullptr; +#ifndef _WIN32 + std::lock_guard lock(libMutex_); + DBCommon::UnLoadGrdLib(dlHandle_); + dlHandle_ = nullptr; +#endif } DBStatus KvStoreNbDelegateImpl::Get(const Key &key, Value &value) const @@ -425,7 +429,7 @@ DBStatus KvStoreNbDelegateImpl::RegisterDeviceObserver(const Key &key, unsigned mode, key, [observer, storeId](const KvDBCommitNotifyData ¬ifyData) { KvStoreChangedDataImpl data(¬ifyData); - LOGD("[KvStoreNbDelegate][RegisterDeviceObserver] Trigger [%s] on change", storeId.c_str()); + LOGD("[KvStoreNbDelegate][RegisterDeviceObserver] Trigger on change"); observer->OnChange(data); }, errCode); @@ -467,7 +471,7 @@ DBStatus KvStoreNbDelegateImpl::RegisterCloudObserver(const Key &key, unsigned i ObserverAction action = [observer, storeId]( const std::string &device, ChangedData &&changedData, bool isChangedData) { if (isChangedData) { - LOGD("[KvStoreNbDelegate][RegisterCloudObserver] Trigger [%s] on change", storeId.c_str()); + LOGD("[KvStoreNbDelegate][RegisterCloudObserver] Trigger on change"); observer->OnChange(Origin::ORIGIN_CLOUD, device, std::move(changedData)); } }; @@ -505,7 +509,7 @@ DBStatus KvStoreNbDelegateImpl::UnRegisterDeviceObserver(const KvStoreObserver * std::lock_guard lockGuard(observerMapLock_); auto iter = observerMap_.find(observer); if (iter == observerMap_.end()) { - LOGE("[KvStoreNbDelegate] [%s] Observer has not been registered!", storeId_.c_str()); + LOGE("[KvStoreNbDelegate] Observer has not been registered!"); return NOT_FOUND; } @@ -524,7 +528,7 @@ DBStatus KvStoreNbDelegateImpl::UnRegisterCloudObserver(const KvStoreObserver *o std::lock_guard lockGuard(observerMapLock_); auto iter = cloudObserverMap_.find(observer); if (iter == cloudObserverMap_.end()) { - LOGW("[KvStoreNbDelegate] [%s] CloudObserver has not been registered!", storeId_.c_str()); + LOGW("[KvStoreNbDelegate] CloudObserver has not been registered!"); return NOT_FOUND; } int errCode = conn_->UnRegisterObserverAction(observer); @@ -589,39 +593,13 @@ DBStatus KvStoreNbDelegateImpl::Sync(const std::vector &devices, Sy const std::function &devicesMap)> &onComplete, const Query &query, bool wait) { - if (conn_ == nullptr) { - LOGE("%s", INVALID_CONNECTION); - return DB_ERROR; - } - if (mode > SYNC_MODE_PUSH_PULL) { - LOGE("not support other mode"); - return NOT_SUPPORT; - } - - QuerySyncObject querySyncObj(query); - if (!querySyncObj.GetRelationTableNames().empty()) { - LOGE("check query table names from tables failed!"); - return NOT_SUPPORT; - } - - if (!DBCommon::CheckQueryWithoutMultiTable(query)) { - LOGE("not support for invalid query"); - return NOT_SUPPORT; - } - if (querySyncObj.GetSortType() != SortType::NONE || querySyncObj.IsQueryByRange()) { - LOGE("not support order by timestamp and query by range"); - return NOT_SUPPORT; - } - PragmaSync pragmaData( - devices, mode, querySyncObj, [this, onComplete](const std::map &statuses) { - OnSyncComplete(statuses, onComplete); - }, wait); - int errCode = conn_->Pragma(PRAGMA_SYNC_DEVICES, &pragmaData); - if (errCode < E_OK) { - LOGE("[KvStoreNbDelegate] QuerySync data failed:%d", errCode); - return TransferDBErrno(errCode); - } - return OK; + DeviceSyncOption option; + option.devices = devices; + option.mode = mode; + option.isQuery = true; + option.query = query; + option.isWait = wait; + return Sync(option, onComplete); } void KvStoreNbDelegateImpl::OnDeviceSyncProcess(const std::map &processMap, @@ -683,6 +661,51 @@ DBStatus KvStoreNbDelegateImpl::Sync(const DeviceSyncOption &option, const Devic return OK; } +DBStatus KvStoreNbDelegateImpl::Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete) +{ + if (conn_ == nullptr) { + LOGE("%s", INVALID_CONNECTION); + return DB_ERROR; + } + if (option.mode > SYNC_MODE_PUSH_PULL) { + LOGE("not support other mode"); + return NOT_SUPPORT; + } + + int errCode = E_OK; + if (option.isQuery) { + QuerySyncObject querySyncObj(option.query); + if (!querySyncObj.GetRelationTableNames().empty()) { + LOGE("check query table names from tables failed!"); + return NOT_SUPPORT; + } + + if (!DBCommon::CheckQueryWithoutMultiTable(option.query)) { + LOGE("not support for invalid query"); + return NOT_SUPPORT; + } + if (querySyncObj.GetSortType() != SortType::NONE || querySyncObj.IsQueryByRange()) { + LOGE("not support order by timestamp and query by range"); + return NOT_SUPPORT; + } + PragmaSync pragmaData(option, querySyncObj, [this, onComplete](const std::map &statuses) { + OnSyncComplete(statuses, onComplete); + }); + errCode = conn_->Pragma(PRAGMA_SYNC_DEVICES, &pragmaData); + } else { + PragmaSync pragmaData(option, [this, onComplete](const std::map &statuses) { + OnSyncComplete(statuses, onComplete); + }); + errCode = conn_->Pragma(PRAGMA_SYNC_DEVICES, &pragmaData); + } + if (errCode != E_OK) { + LOGE("[KvStoreNbDelegate] QuerySync data failed:%d", errCode); + return TransferDBErrno(errCode); + } + return OK; +} + DBStatus KvStoreNbDelegateImpl::CancelSync(uint32_t syncId) { if (conn_ == nullptr) { @@ -894,10 +917,10 @@ void KvStoreNbDelegateImpl::SetReleaseFlag(bool flag) releaseFlag_ = flag; } -DBStatus KvStoreNbDelegateImpl::Close() +DBStatus KvStoreNbDelegateImpl::Close(bool isCloseImmediately) { if (conn_ != nullptr) { - int errCode = KvDBManager::ReleaseDatabaseConnection(conn_); + int errCode = KvDBManager::ReleaseDatabaseConnection(conn_, isCloseImmediately); if (errCode == -E_BUSY) { LOGI("[KvStoreNbDelegate] Busy for close"); return BUSY; @@ -954,7 +977,7 @@ DBStatus KvStoreNbDelegateImpl::GetInner(const IOption &option, const Key &key, } if (errCode != -E_NOT_FOUND) { - LOGE("[KvStoreNbDelegate] [%s] Get the data failed:%d", storeId_.c_str(), errCode); + LOGE("[KvStoreNbDelegate] Get the data failed:%d", errCode); } return TransferDBErrno(errCode); } @@ -1372,6 +1395,24 @@ std::pair> KvStoreNbDelegateImpl::G res.first = TransferDBErrno(errCode); return res; } + +DBStatus KvStoreNbDelegateImpl::ClearMetaData(ClearKvMetaDataOption option) +{ + if (option.type != ClearKvMetaOpType::CLEAN_CLOUD_WATERMARK) { + return NOT_SUPPORT; + } + if (conn_ == nullptr) { + LOGE("%s", INVALID_CONNECTION); + return DB_ERROR; + } + int errCode = conn_->ClearCloudWatermark(); + if (errCode == E_OK) { + LOGI("[KvStoreNbDelegate][%.3s] clear kv cloud watermark success", storeId_.c_str()); + } else { + LOGE("[KvStoreNbDelegate][%.3s] clear kv cloud watermark failed:%d", storeId_.c_str(), errCode); + } + return TransferDBErrno(errCode); +} #endif DBStatus KvStoreNbDelegateImpl::OperateDataStatus(uint32_t dataOperator) @@ -1388,4 +1429,12 @@ DBStatus KvStoreNbDelegateImpl::OperateDataStatus(uint32_t dataOperator) } return TransferDBErrno(errCode); } + +void KvStoreNbDelegateImpl::SetHandle(void *handle) +{ +#ifndef _WIN32 + std::lock_guard lock(libMutex_); + dlHandle_ = handle; +#endif +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h index 6ec08032..88323d87 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h @@ -124,7 +124,7 @@ public: void SetReleaseFlag(bool flag); - DBStatus Close(); + DBStatus Close(bool isCloseImmediately = true); // Sync function interface, if wait set true, this function will be blocked until sync finished. // Param query used to filter the records to be synchronized. @@ -136,6 +136,9 @@ public: // Sync with devices, provides sync count information DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) override; + DBStatus Sync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete) override; + // Cancel sync by syncId DBStatus CancelSync(uint32_t syncId) override; @@ -192,9 +195,14 @@ public: DBStatus SetCloudSyncConfig(const CloudSyncConfig &config) override; std::pair> GetCloudVersion(const std::string &device) override; + + DBStatus ClearMetaData(ClearKvMetaDataOption option) override; #endif DBStatus OperateDataStatus(uint32_t dataOperator) override; + + void SetHandle(void *handle); + private: DBStatus GetInner(const IOption &option, const Key &key, Value &value) const; DBStatus PutInner(const IOption &option, const Key &key, const Value &value); @@ -222,6 +230,10 @@ private: IKvDBConnection *conn_; std::string storeId_; bool releaseFlag_; +#ifndef _WIN32 + mutable std::mutex libMutex_; + void *dlHandle_ = nullptr; +#endif std::mutex observerMapLock_; std::map observerMap_; std::map cloudObserverMap_; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/knowledge_source_utils.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/knowledge_source_utils.cpp new file mode 100644 index 00000000..4a496f44 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/knowledge_source_utils.cpp @@ -0,0 +1,339 @@ +/* + * 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 "knowledge_source_utils.h" + +#include "db_common.h" +#include "db_errno.h" +#include "simple_tracker_log_table_manager.h" +#include "sqlite_relational_utils.h" +#include "sqlite_utils.h" + +namespace DistributedDB { +namespace { +int GenLogForExistData(sqlite3 *db, const TableInfo &table, std::unique_ptr &manager) +{ + SQLiteRelationalUtils::GenLogParam param = {db, false, true}; + return SQLiteRelationalUtils::GeneLogInfoForExistedData("", table, manager, param); +} + +TrackerTable GetTrackerTable(const KnowledgeSourceSchema &schema) +{ + TrackerTable trackerTable; + trackerTable.SetTableName(schema.tableName); + trackerTable.SetExtendNames(schema.extendColNames); + trackerTable.SetTrackerNames(schema.knowledgeColNames); + trackerTable.SetTriggerObserver(false); + trackerTable.SetKnowledgeTable(true); + return trackerTable; +} + +TrackerSchema GetTrackerSchema(const KnowledgeSourceSchema &schema) +{ + TrackerSchema trackerSchema; + trackerSchema.tableName = schema.tableName; + trackerSchema.extendColNames = schema.extendColNames; + trackerSchema.trackerColNames = schema.knowledgeColNames; + return trackerSchema; +} +} + +int KnowledgeSourceUtils::SetKnowledgeSourceSchema(sqlite3 *db, const KnowledgeSourceSchema &schema) +{ + int errCode = SQLiteUtils::BeginTransaction(db, TransactType::IMMEDIATE); + if (errCode != E_OK) { + LOGE("Begin transaction failed %d when set knowledge schema", errCode); + return errCode; + } + errCode = SetKnowledgeSourceSchemaInner(db, schema); + int ret; + if (errCode != E_OK) { + ret = SQLiteUtils::RollbackTransaction(db); + } else { + ret = SQLiteUtils::CommitTransaction(db); + } + LOGI("Set knowledge source schema res %d, commit or rollback ret %d", errCode, ret); + return errCode == E_OK ? ret : errCode; +} + +int KnowledgeSourceUtils::CleanDeletedData(sqlite3 *db, const std::string &tableName, uint64_t cursor) +{ + bool isExist = false; + auto errCode = SQLiteUtils::CheckTableExists(db, DBCommon::GetLogTableName(tableName), isExist); + if (errCode != E_OK) { + return errCode; + } + if (!isExist) { + LOGI("Clean delete data with no exist log, ori table %s len %zu", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size()); + return E_OK; + } + errCode = SQLiteRelationalUtils::CleanTrackerData(db, tableName, static_cast(cursor), true); + if (errCode != E_OK) { + return errCode; + } + auto count = sqlite3_changes64(db); + LOGI("Clean delete data success, table %s len %zu cursor %" PRIu64 " delete count %" PRId64, + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), cursor, count); + return errCode; +} + +int KnowledgeSourceUtils::SetKnowledgeSourceSchemaInner(sqlite3 *db, const KnowledgeSourceSchema &schema) +{ + bool isExist = false; + auto errCode = SQLiteUtils::CheckTableExists(db, schema.tableName, isExist); + if (errCode != E_OK) { + return errCode; + } + if (!isExist) { + LOGE("Set not exist table's knowledge schema"); + return -E_INVALID_ARGS; + } + errCode = InitMeta(db, schema.tableName); + if (errCode != E_OK) { + return errCode; + } + RelationalSchemaObject knowledgeSchema; + std::tie(errCode, knowledgeSchema) = GetKnowledgeSourceSchema(db); + if (errCode != E_OK) { + return errCode; + } + TableInfo tableInfo; + errCode = SQLiteUtils::AnalysisSchema(db, schema.tableName, tableInfo); + if (errCode != E_OK) { + return errCode; + } + tableInfo.SetTrackerTable(GetTrackerTable(schema)); + bool isChanged = false; + std::tie(errCode, isChanged) = CheckSchemaValidAndChangeStatus(db, knowledgeSchema, schema, tableInfo); + if (errCode != E_OK) { + return errCode; + } + if (!isChanged) { + LOGI("Knowledge schema is no change, table %s len %zu", + DBCommon::StringMiddleMasking(schema.tableName).c_str(), schema.tableName.size()); + std::unique_ptr tableManager = std::make_unique(); + tableManager->CheckAndCreateTrigger(db, tableInfo, ""); + return E_OK; + } + errCode = InitLogTable(db, schema, tableInfo); + if (errCode != E_OK) { + return errCode; + } + knowledgeSchema.InsertTrackerSchema(GetTrackerSchema(schema)); + return SaveKnowledgeSourceSchema(db, knowledgeSchema); +} + +int KnowledgeSourceUtils::RemoveKnowledgeTableSchema(sqlite3 *db, const std::string &tableName) +{ + int errCode = E_OK; + RelationalSchemaObject knowledgeSchema; + std::tie(errCode, knowledgeSchema) = GetKnowledgeSourceSchema(db); + if (errCode != E_OK) { + return errCode; + } + knowledgeSchema.RemoveRelationalTable(tableName); + return SaveKnowledgeSourceSchema(db, knowledgeSchema); +} + +int KnowledgeSourceUtils::InitMeta(sqlite3 *db, const std::string &table) +{ + int errCode = SQLiteRelationalUtils::CreateRelationalMetaTable(db); + if (errCode != E_OK) { + LOGE("Create relational store meta table failed. err=%d", errCode); + return errCode; + } + errCode = SQLiteRelationalUtils::InitKnowledgeTableTypeToMeta(db, false, table); + if (errCode != E_OK) { + LOGE("Init table type to meta err:%d", errCode); + return errCode; + } + return SQLiteRelationalUtils::InitCursorToMeta(db, false, table); +} + +std::pair KnowledgeSourceUtils::CheckSchemaValidAndChangeStatus(sqlite3 *db, + const RelationalSchemaObject &knowledgeSchema, + const KnowledgeSourceSchema &schema, const TableInfo &tableInfo) +{ + std::pair res = {E_OK, false}; + auto &[errCode, isChange] = res; + if (!IsSchemaValid(schema, tableInfo)) { + errCode = -E_INVALID_ARGS; + return res; + } + RelationalSchemaObject rdbSchema; + std::tie(errCode, rdbSchema) = GetRDBSchema(db, false); + if (errCode != E_OK) { + return res; + } + if (IsTableInRDBSchema(schema.tableName, rdbSchema, false)) { + errCode = -E_INVALID_ARGS; + return res; + } + std::tie(errCode, rdbSchema) = GetRDBSchema(db, true); + if (errCode != E_OK) { + return res; + } + if (IsTableInRDBSchema(schema.tableName, rdbSchema, true)) { + errCode = -E_INVALID_ARGS; + return res; + } + isChange = IsSchemaChange(knowledgeSchema, schema); + return res; +} + +bool KnowledgeSourceUtils::IsSchemaValid(const KnowledgeSourceSchema &schema, const TableInfo &tableInfo) +{ + auto fields = tableInfo.GetFields(); + for (const auto &col : schema.knowledgeColNames) { + if (fields.find(col) == fields.end()) { + LOGE("Not exist knowledge col %s %zu table %s %zu", + DBCommon::StringMiddleMasking(col).c_str(), col.size(), + DBCommon::StringMiddleMasking(schema.tableName).c_str(), schema.tableName.size()); + return false; + } + } + for (const auto &col : schema.extendColNames) { + if (fields.find(col) == fields.end()) { + LOGE("Not exist extend col %s %zu table %s %zu", + DBCommon::StringMiddleMasking(col).c_str(), col.size(), + DBCommon::StringMiddleMasking(schema.tableName).c_str(), schema.tableName.size()); + return false; + } + } + return true; +} + +bool KnowledgeSourceUtils::IsTableInRDBSchema(const std::string &table, const RelationalSchemaObject &rdbSchema, + bool isTracker) +{ + if (isTracker) { + auto trackerTable = rdbSchema.GetTrackerTable(table); + if (!trackerTable.GetTableName().empty()) { + LOGE("Table %s len %zu was tracker table", DBCommon::StringMiddleMasking(table).c_str(), table.size()); + return true; + } + return false; + } + auto tableInfo = rdbSchema.GetTable(table); + if (!tableInfo.GetTableName().empty()) { + LOGE("Table %s len %zu was distributed table, type %d", DBCommon::StringMiddleMasking(table).c_str(), + table.size(), static_cast(tableInfo.GetTableSyncType())); + return true; + } + return false; +} + +bool KnowledgeSourceUtils::IsSchemaChange(const RelationalSchemaObject &dbSchema, const KnowledgeSourceSchema &schema) +{ + auto trackerTable = dbSchema.GetTrackerTable(schema.tableName); + if (trackerTable.IsEmpty()) { + LOGI("Check knowledge schema was change by first set"); + return true; + } + const auto &dbExtendsNames = trackerTable.GetExtendNames(); + if (dbExtendsNames != schema.extendColNames) { + LOGI("Check knowledge schema was change by extend col old %zu new %zu", + dbExtendsNames.size(), schema.extendColNames.size()); + return true; + } + const auto &dbTrackerCols = trackerTable.GetTrackerColNames(); + if (dbTrackerCols != schema.knowledgeColNames) { + LOGI("Check knowledge schema was change by knowledge col old %zu new %zu", + dbTrackerCols.size(), schema.knowledgeColNames.size()); + return true; + } + return false; +} + +int KnowledgeSourceUtils::InitLogTable(sqlite3 *db, const KnowledgeSourceSchema &schema, const TableInfo &tableInfo) +{ + std::unique_ptr tableManager = std::make_unique(); + auto errCode = tableManager->CreateRelationalLogTable(db, tableInfo); + if (errCode != E_OK) { + return errCode; + } + errCode = GenLogForExistData(db, tableInfo, tableManager); + if (errCode != E_OK) { + LOGE("Gen log failed %d", errCode); + return errCode; + } + errCode = SQLiteRelationalUtils::SetLogTriggerStatus(db, true); + if (errCode != E_OK) { + return errCode; + } + return tableManager->AddRelationalLogTableTrigger(db, tableInfo, ""); +} + +std::pair KnowledgeSourceUtils::GetKnowledgeSourceSchema(sqlite3 *db) +{ + std::pair res; + auto &[errCode, rdbSchema] = res; + const std::string knowledgeKey(DBConstant::RDB_KNOWLEDGE_SCHEMA_KEY); + const Key schemaKey(knowledgeKey.begin(), knowledgeKey.end()); + Value schemaVal; + errCode = SQLiteRelationalUtils::GetKvData(db, false, schemaKey, schemaVal); // save schema to meta_data + if (errCode == -E_NOT_FOUND) { + LOGD("Not found knowledge schema in db"); + errCode = E_OK; + return res; + } + if (errCode != E_OK) { + LOGE("Get knowledge schema from meta table failed. %d", errCode); + return res; + } + std::string schemaJson(schemaVal.begin(), schemaVal.end()); + errCode = rdbSchema.ParseFromTrackerSchemaString(schemaJson); + return res; +} + +std::pair KnowledgeSourceUtils::GetRDBSchema(sqlite3 *db, bool isTracker) +{ + std::pair res; + auto &[errCode, rdbSchema] = res; + std::string schemaKey = isTracker ? DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY : DBConstant::RELATIONAL_SCHEMA_KEY; + const Key schema(schemaKey.begin(), schemaKey.end()); + Value schemaVal; + errCode = SQLiteRelationalUtils::GetKvData(db, false, schema, schemaVal); // save schema to meta_data + if (errCode == -E_NOT_FOUND) { + LOGD("Not found rdb schema in db"); + errCode = E_OK; + return res; + } + if (errCode != E_OK) { + LOGE("Get rdb schema from meta table failed. %d", errCode); + return res; + } + std::string schemaJson(schemaVal.begin(), schemaVal.end()); + if (isTracker) { + errCode = rdbSchema.ParseFromTrackerSchemaString(schemaJson); + } else { + errCode = rdbSchema.ParseFromSchemaString(schemaJson); + } + return res; +} + +int KnowledgeSourceUtils::SaveKnowledgeSourceSchema(sqlite3 *db, const RelationalSchemaObject &schema) +{ + const std::string knowledgeKey(DBConstant::RDB_KNOWLEDGE_SCHEMA_KEY); + const Key schemaKey(knowledgeKey.begin(), knowledgeKey.end()); + Value schemaVal; + DBCommon::StringToVector(schema.ToSchemaString(), schemaVal); + int errCode = SQLiteRelationalUtils::PutKvData(db, false, schemaKey, schemaVal); // save schema to meta_data + if (errCode != E_OK) { + LOGE("Save schema to meta table failed. %d", errCode); + } + return errCode; +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/knowledge_source_utils.h b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/knowledge_source_utils.h new file mode 100644 index 00000000..7e8beaf8 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/knowledge_source_utils.h @@ -0,0 +1,55 @@ +/* + * 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 KNOWLEDGE_SOURCE_UTILS_H +#define KNOWLEDGE_SOURCE_UTILS_H + +#include "relational_schema_object.h" +#include "relational_store_client.h" + +namespace DistributedDB { +class KnowledgeSourceUtils { +public: + static int SetKnowledgeSourceSchema(sqlite3 *db, const KnowledgeSourceSchema &schema); + + static int RemoveKnowledgeTableSchema(sqlite3 *db, const std::string &tableName); + + static int CleanDeletedData(sqlite3 *db, const std::string &tableName, uint64_t cursor); +protected: + static int SetKnowledgeSourceSchemaInner(sqlite3 *db, const KnowledgeSourceSchema &schema); + + static int InitMeta(sqlite3 *db, const std::string &table); + + static std::pair GetKnowledgeSourceSchema(sqlite3 *db); + + static std::pair GetRDBSchema(sqlite3 *db, bool isTracker); + + static int SaveKnowledgeSourceSchema(sqlite3 *db, const RelationalSchemaObject &schema); + + static std::pair CheckSchemaValidAndChangeStatus(sqlite3 *db, + const RelationalSchemaObject &knowledgeSchema, + const KnowledgeSourceSchema &schema, const TableInfo &tableInfo); + + static bool IsSchemaValid(const KnowledgeSourceSchema &schema, const TableInfo &tableInfo); + + static bool IsTableInRDBSchema(const std::string &table, const RelationalSchemaObject &rdbSchema, bool isTracker); + + static bool IsSchemaChange(const RelationalSchemaObject &dbSchema, const KnowledgeSourceSchema &schema); + + static int InitLogTable(sqlite3 *db, const KnowledgeSourceSchema &schema, const TableInfo &tableInfo); +}; +} + +#endif // KNOWLEDGE_SOURCE_UTILS_H diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp index cf405a1e..a68cca1f 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp @@ -391,7 +391,7 @@ DBStatus RelationalStoreDelegateImpl::UpsertData(const std::string &tableName, c return OK; } -DBStatus RelationalStoreDelegateImpl::SetDistributedSchema(const DistributedSchema &schema) +DBStatus RelationalStoreDelegateImpl::SetDistributedSchema(const DistributedSchema &schema, bool isForceUpgrade) { if (conn_ == nullptr) { LOGE("[RelationalStore Delegate] Invalid connection for setting db schema!"); @@ -411,9 +411,10 @@ DBStatus RelationalStoreDelegateImpl::SetDistributedSchema(const DistributedSche LOGW("[RelationalStore Delegate] Get storeInfo failed %d", errCode); return TransferDBErrno(errCode); } - errCode = conn_->SetDistributedDbSchema(schema); - LOGI("[RelationalStore Delegate] %s %s SetDistributedSchema errCode:%d", - DBCommon::StringMiddleMasking(appId).c_str(), DBCommon::StringMiddleMasking(storeId).c_str(), errCode); + errCode = conn_->SetDistributedDbSchema(schema, isForceUpgrade); + LOGI("[RelationalStore Delegate] %s %s SetDistributedSchema errCode:%d, force upgrade: %d", + DBCommon::StringMiddleMasking(appId).c_str(), DBCommon::StringMiddleMasking(storeId).c_str(), errCode, + isForceUpgrade); return TransferDBErrno(errCode); } @@ -563,6 +564,7 @@ DBStatus RelationalStoreDelegateImpl::ClearWatermark(const ClearMetaDataOption & } return OK; } + #endif DBStatus RelationalStoreDelegateImpl::SetStoreConfig(const StoreConfig &config) @@ -595,5 +597,16 @@ DBStatus RelationalStoreDelegateImpl::OperateDataStatus(uint32_t dataOperator) } return OK; } + +int32_t RelationalStoreDelegateImpl::GetDeviceSyncTaskCount() +{ + if (conn_ == nullptr) { + LOGW("[RelationalStore Delegate] Invalid connection for get device sync task count."); + return 0; + } + int32_t count = conn_->GetDeviceSyncTaskCount(); + LOGI("[RelationalStore Delegate] Get device sync task count %" PRId32, count); + return count; +} } // namespace DistributedDB #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h index caea7eb5..de6060d9 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h @@ -69,7 +69,7 @@ public: DBStatus UpsertData(const std::string &tableName, const std::vector &records, RecordStatus status) override; - DBStatus SetDistributedSchema(const DistributedSchema &schema) override; + DBStatus SetDistributedSchema(const DistributedSchema &schema, bool isForceUpgrade) override; std::pair GetDownloadingAssetsCount() override; @@ -95,6 +95,7 @@ public: DBStatus ClearMetaData(const ClearMetaDataOption &option) override; #endif + int32_t GetDeviceSyncTaskCount() override; private: static void OnSyncComplete(const std::map> &devicesStatus, const SyncStatusCallback &onComplete); diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp index f72eeb1e..bce7713e 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp @@ -22,7 +22,6 @@ #include "db_dfx_adapter.h" #include "db_errno.h" #include "cloud/cloud_db_constant.h" -#include "cloud/cloud_storage_utils.h" #include "kv_store_errno.h" #include "log_print.h" #include "param_check_utils.h" @@ -38,6 +37,24 @@ namespace DistributedDB { namespace { const int GET_CONNECT_RETRY = 3; const int RETRY_GET_CONN_INTER = 30; + +DBStatus InitProperties(const RelationalStoreDelegate::Option &option, RelationalDBProperties &properties) +{ + properties.SetIntProp(RelationalDBProperties::DISTRIBUTED_TABLE_MODE, static_cast(option.tableMode)); + properties.SetBoolProp(RelationalDBProperties::SYNC_DUAL_TUPLE_MODE, option.syncDualTupleMode); + if (option.isEncryptedDb) { + if (!ParamCheckUtils::CheckEncryptedParameter(option.cipher, option.passwd) || option.iterateTimes == 0) { + return INVALID_ARGS; + } + properties.SetCipherArgs(option.cipher, option.passwd, option.iterateTimes); + } + properties.SetBoolProp(DBProperties::COMPRESS_ON_SYNC, option.isNeedCompressOnSync); + if (option.isNeedCompressOnSync) { + properties.SetIntProp( + DBProperties::COMPRESSION_RATE, ParamCheckUtils::GetValidCompressionRate(option.compressionRate)); + } + return OK; +} } RelationalStoreManager::RelationalStoreManager(const std::string &appId, const std::string &userId, int32_t instanceId) @@ -99,16 +116,11 @@ DB_API DBStatus RelationalStoreManager::OpenStore(const std::string &path, const RelationalDBProperties properties; properties.SetStringProp(RelationalDBProperties::DATA_DIR, canonicalDir); - properties.SetIntProp(RelationalDBProperties::DISTRIBUTED_TABLE_MODE, static_cast(option.tableMode)); properties.SetIdentifier(userId_, appId_, storeId, subUser_, instanceId_); - properties.SetBoolProp(RelationalDBProperties::SYNC_DUAL_TUPLE_MODE, option.syncDualTupleMode); - if (option.isEncryptedDb) { - if (!ParamCheckUtils::CheckEncryptedParameter(option.cipher, option.passwd) || option.iterateTimes == 0) { - return INVALID_ARGS; - } - properties.SetCipherArgs(option.cipher, option.passwd, option.iterateTimes); + auto ret = InitProperties(option, properties); + if (ret != OK) { + return ret; } - int errCode = E_OK; auto *conn = GetOneConnectionWithRetry(properties, errCode); if (conn == nullptr) { @@ -158,78 +170,6 @@ std::string RelationalStoreManager::GetDistributedTableName(const std::string &d return DBCommon::GetDistributedTableName(device, tableName); } -DB_API std::string RelationalStoreManager::GetDistributedLogTableName(const std::string &tableName) -{ - return DBCommon::GetLogTableName(tableName); -} - -static int GetCollateTypeByName(const std::map &collateTypeMap, - const std::string &name, CollateType &collateType) -{ - auto it = collateTypeMap.find(name); - if (it == collateTypeMap.end()) { - LOGW("collate map doesn't contain primary key we need"); - collateType = CollateType::COLLATE_NONE; - return E_OK; - } - if (static_cast(it->second) >= static_cast(CollateType::COLLATE_BUTT)) { - LOGE("collate type is invalid"); - return -E_INVALID_ARGS; - } - collateType = it->second; - return E_OK; -} - -DB_API std::vector RelationalStoreManager::CalcPrimaryKeyHash(const std::map &primaryKey, - const std::map &collateTypeMap) -{ - std::vector result; - if (primaryKey.empty()) { - LOGW("primaryKey is empty"); - return result; - } - int errCode = E_OK; - CollateType collateType = CollateType::COLLATE_NONE; - if (primaryKey.size() == 1) { - auto iter = primaryKey.begin(); - Field field = {iter->first, static_cast(iter->second.index()), true, false}; - if (GetCollateTypeByName(collateTypeMap, iter->first, collateType) != E_OK) { - return result; - } - errCode = CloudStorageUtils::CalculateHashKeyForOneField(field, primaryKey, false, collateType, result); - if (errCode != E_OK) { - // never happen - LOGE("calc hash fail when there is one primary key errCode = %d", errCode); - } - } else { - std::vector tempRes; - std::map pkOrderByUpperName; - for (const auto &item : primaryKey) { // we sort by upper case name in log table when calculate hash - pkOrderByUpperName[DBCommon::ToUpperCase(item.first)] = item.second; - } - - for (const auto &item : pkOrderByUpperName) { - std::vector temp; - Field field = {DBCommon::ToLowerCase(item.first), static_cast(item.second.index()), true, false}; - if (GetCollateTypeByName(collateTypeMap, DBCommon::ToLowerCase(item.first), collateType) != E_OK) { - return result; - } - errCode = CloudStorageUtils::CalculateHashKeyForOneField(field, primaryKey, false, collateType, temp); - if (errCode != E_OK) { - // never happen - LOGE("calc hash fail when there is more than one primary key errCode = %d", errCode); - return result; - } - tempRes.insert(tempRes.end(), temp.begin(), temp.end()); - } - errCode = DBCommon::CalcValueHash(tempRes, result); - if (errCode != E_OK) { - LOGE("calc hash fail when calc the composite primary key errCode = %d", errCode); - } - } - return result; -} - void RelationalStoreManager::SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback) { RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(callback, DBTypeInner::DB_RELATION); diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager_client.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager_client.cpp new file mode 100644 index 00000000..1540f46b --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager_client.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. + */ +#ifdef RELATIONAL_STORE +#include "relational_store_manager.h" + +#include "db_common.h" +#include "cloud/cloud_storage_utils.h" + +namespace DistributedDB { +DB_API std::string RelationalStoreManager::GetDistributedLogTableName(const std::string &tableName) +{ + return DBCommon::GetLogTableName(tableName); +} + +static int GetCollateTypeByName(const std::map &collateTypeMap, + const std::string &name, CollateType &collateType) +{ + auto it = collateTypeMap.find(name); + if (it == collateTypeMap.end()) { + LOGW("collate map doesn't contain primary key we need"); + collateType = CollateType::COLLATE_NONE; + return E_OK; + } + if (static_cast(it->second) >= static_cast(CollateType::COLLATE_BUTT)) { + LOGE("collate type is invalid"); + return -E_INVALID_ARGS; + } + collateType = it->second; + return E_OK; +} + +DB_API std::vector RelationalStoreManager::CalcPrimaryKeyHash(const std::map &primaryKey, + const std::map &collateTypeMap) +{ + std::vector result; + if (primaryKey.empty()) { + LOGW("primaryKey is empty"); + return result; + } + int errCode = E_OK; + CollateType collateType = CollateType::COLLATE_NONE; + if (primaryKey.size() == 1) { + auto iter = primaryKey.begin(); + Field field = {iter->first, static_cast(iter->second.index()), true, false}; + if (GetCollateTypeByName(collateTypeMap, iter->first, collateType) != E_OK) { + return result; + } + errCode = CloudStorageUtils::CalculateHashKeyForOneField(field, primaryKey, false, collateType, result); + if (errCode != E_OK) { + // never happen + LOGE("calc hash fail when there is one primary key errCode = %d", errCode); + } + } else { + std::vector tempRes; + std::map pkOrderByUpperName; + for (const auto &item : primaryKey) { // we sort by upper case name in log table when calculate hash + pkOrderByUpperName[DBCommon::ToUpperCase(item.first)] = item.second; + } + + for (const auto &item : pkOrderByUpperName) { + std::vector temp; + Field field = {DBCommon::ToLowerCase(item.first), static_cast(item.second.index()), true, false}; + if (GetCollateTypeByName(collateTypeMap, DBCommon::ToLowerCase(item.first), collateType) != E_OK) { + return result; + } + errCode = CloudStorageUtils::CalculateHashKeyForOneField(field, primaryKey, false, collateType, temp); + if (errCode != E_OK) { + // never happen + LOGE("calc hash fail when there is more than one primary key errCode = %d", errCode); + return result; + } + tempRes.insert(tempRes.end(), temp.begin(), temp.end()); + } + errCode = DBCommon::CalcValueHash(tempRes, result); + if (errCode != E_OK) { + LOGE("calc hash fail when calc the composite primary key errCode = %d", errCode); + } + } + return result; +} +} // namespace DistributedDB +#endif diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp index 54cd766c..e0c5a8c7 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp @@ -12,8 +12,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef _WIN32 +#include +#endif #include #include +#include #include #include #include @@ -24,6 +28,7 @@ #include "concurrent_adapter.h" #include "db_common.h" #include "db_constant.h" +#include "knowledge_source_utils.h" #include "kv_store_errno.h" #include "param_check_utils.h" #include "platform_specific.h" @@ -64,13 +69,20 @@ using namespace DistributedDB::OS; using namespace DistributedDB; namespace { +const std::string DISTRIBUTED_TABLE_MODE = "distributed_table_mode"; +static std::mutex g_binlogInitMutex; +static int g_binlogInit = -1; +constexpr const char *COMPRESS_WHITELIST[] = {"test.db"}; constexpr int E_OK = 0; constexpr int E_ERROR = 1; constexpr int STR_TO_LL_BY_DEVALUE = 10; constexpr int BUSY_TIMEOUT = 2000; // 2s. constexpr int MAX_BLOB_READ_SIZE = 5 * 1024 * 1024; // 5M limit const std::string DEVICE_TYPE = "device"; +const std::string KNOWLEDGE_TYPE = "knowledge"; const std::string SYNC_TABLE_TYPE = "sync_table_type_"; +const std::string KNOWLEDGE_CURSOR = "knowledge_cursor_"; +const std::string COMPRESS_VFS = "compressvfs"; class ValueHashCalc { public: ValueHashCalc() {}; @@ -308,8 +320,8 @@ class TimeHelperManager { public: static TimeHelperManager *GetInstance() { - static auto instance = new TimeHelperManager(); - return instance; + static TimeHelperManager instance; + return &instance; } void AddStore(const std::string &storeId) @@ -559,7 +571,7 @@ int GetLocalTimeOffsetFromMeta(sqlite3 *db, TimeOffset &offset) int GetTableModeFromMeta(sqlite3 *db, DistributedTableMode &mode) { - std::string keyStr = RelationalDBProperties::DISTRIBUTED_TABLE_MODE; + std::string keyStr = DISTRIBUTED_TABLE_MODE; int64_t dbVal = 0; int errCode = GetNumValueFromMeta(db, keyStr, dbVal); if (errCode != E_OK) { @@ -694,6 +706,7 @@ void CloudDataChangedObserver(sqlite3_context *ctx, int argc, sqlite3_value **ar auto changeStatus = static_cast(sqlite3_value_int(argv[3])); // 3 is param index bool isTrackerChange = (changeStatus & CloudDbConstant::ON_CHANGE_TRACKER) != 0; bool isP2pChange = (changeStatus & CloudDbConstant::ON_CHANGE_P2P) != 0; + bool isKnowledgeDataChange = (changeStatus & CloudDbConstant::ON_CHANGE_KNOWLEDGE) != 0; bool isExistObserver = false; { std::lock_guard lock(g_clientObserverMutex); @@ -707,10 +720,12 @@ void CloudDataChangedObserver(sqlite3_context *ctx, int argc, sqlite3_value **ar if (itTable != g_clientChangedDataMap[hashFileName].tableData.end()) { itTable->second.isTrackedDataChange |= isTrackerChange; itTable->second.isP2pSyncDataChange |= isP2pChange; + itTable->second.isKnowledgeDataChange |= isKnowledgeDataChange; } else { DistributedDB::ChangeProperties properties = { .isTrackedDataChange = isTrackerChange, - .isP2pSyncDataChange = isP2pChange + .isP2pSyncDataChange = isP2pChange, + .isKnowledgeDataChange = isKnowledgeDataChange }; g_clientChangedDataMap[hashFileName].tableData.insert_or_assign(tableName, properties); } @@ -834,7 +849,7 @@ std::string GetInsertTrigger(const std::string &tableName, bool isRowid, const s insertTrigger += "SELECT data_change('" + tableName + "', 'rowid', NEW._rowid_, 0);\n"; } else { insertTrigger += "SELECT data_change('" + tableName + "', "; - insertTrigger += "(SELECT name as a FROM pragma_table_info('" + tableName + "') WHERE pk=1), "; + insertTrigger += "'" + primaryKey + "', "; insertTrigger += "NEW." + primaryKey + ", 0);\n"; } insertTrigger += "END;"; @@ -851,7 +866,7 @@ std::string GetUpdateTrigger(const std::string &tableName, bool isRowid, const s updateTrigger += "SELECT data_change('" + tableName + "', 'rowid', NEW._rowid_, 1);\n"; } else { updateTrigger += "SELECT data_change('" + tableName + "', "; - updateTrigger += "(SELECT name as a FROM pragma_table_info('" + tableName + "') WHERE pk=1), "; + updateTrigger += "'" + primaryKey + "', "; updateTrigger += "NEW." + primaryKey + ", 1);\n"; } updateTrigger += "END;"; @@ -868,7 +883,7 @@ std::string GetDeleteTrigger(const std::string &tableName, bool isRowid, const s deleteTrigger += "SELECT data_change('" + tableName + "', 'rowid', OLD._rowid_, 2);\n"; } else { deleteTrigger += "SELECT data_change('" + tableName + "', "; - deleteTrigger += "(SELECT name as a FROM pragma_table_info('" + tableName + "') WHERE pk=1), "; + deleteTrigger += "'" + primaryKey + "', "; deleteTrigger += "OLD." + primaryKey + ", 2);\n"; } deleteTrigger += "END;"; @@ -1310,6 +1325,75 @@ void HandleDropCloudSyncTable(sqlite3 *db, const std::string &tableName) (void)sqlite3_finalize(statement); } +bool ClearMetaField(sqlite3 *db, const std::string &fieldName) +{ + std::vector key(fieldName.begin(), fieldName.end()); + std::string sql = "DELETE FROM naturalbase_rdb_aux_metadata WHERE key = ?;"; + sqlite3_stmt *statement = nullptr; + int errCode = sqlite3_prepare_v2(db, sql.c_str(), -1, &statement, nullptr); + if (errCode != SQLITE_OK) { + (void)sqlite3_finalize(statement); + return false; + } + + if (fieldName.rfind(KNOWLEDGE_CURSOR, 0) != std::string::npos) { + if (sqlite3_bind_text(statement, 1, fieldName.c_str(), fieldName.length(), + SQLITE_TRANSIENT) != SQLITE_OK) { + (void)sqlite3_finalize(statement); + return false; + } + } else { + if (sqlite3_bind_blob(statement, 1, static_cast(key.data()), key.size(), + SQLITE_TRANSIENT) != SQLITE_OK) { + (void)sqlite3_finalize(statement); + return false; + } + } + + int ret = sqlite3_step(statement); + (void)sqlite3_finalize(statement); + if (ret != SQLITE_DONE) { + LOGW("ClearMetaField step err: %d", ret); + return false; + } + return true; +} + +void HandleDropKnowledgeTable(sqlite3 *db, const std::string &tableName) +{ + // drop inverted table + std::string sql = "DROP TABLE IF EXISTS " + tableName + "_inverted;"; + (void)sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); + + // drop log table + std::string logTblName = std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log"; + sql = "DROP TABLE IF EXISTS " + logTblName + ";"; + (void)sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); + + // remove knowledge cursor + std::string keyStr = KNOWLEDGE_CURSOR + tableName; + if (!ClearMetaField(db, keyStr)) { + LOGW("Remove knowledge cursor unsucc"); + } + + // remove data cursor + keyStr = std::string(DBConstant::RELATIONAL_PREFIX) + "cursor_" + tableName; + if (!ClearMetaField(db, keyStr)) { + LOGW("Remove data cursor unsucc"); + } + + // remove table type meta + keyStr = SYNC_TABLE_TYPE + tableName; + if (!ClearMetaField(db, keyStr)) { + LOGW("Remove table type unsucc"); + } + + int errCode = KnowledgeSourceUtils::RemoveKnowledgeTableSchema(db, tableName); + if (errCode != E_OK) { + LOGW("Remove knowledge table schema unsucc, err: %d", errCode); + } +} + int HandleDropLogicDeleteData(sqlite3 *db, const std::string &tableName, uint64_t cursor) { LOGI("DropLogicDeleteData on table:%s length:%d cursor:%" PRIu64, @@ -1410,7 +1494,7 @@ void ClearTheLogAfterDropTable(sqlite3 *db, const char *tableName, const char *s if (tableType == DEVICE_TYPE) { RegisterGetSysTime(db); RegisterGetLastTime(db); - std::string targetFlag = "flag|0x01"; + std::string targetFlag = "flag|0x03"; std::string originalFlag = "flag&0x01=0x0"; auto tableMode = DistributedTableMode::COLLABORATION; (void)GetTableModeFromMeta(db, tableMode); @@ -1422,6 +1506,8 @@ void ClearTheLogAfterDropTable(sqlite3 *db, const char *tableName, const char *s ", timestamp=get_sys_time(0) WHERE " + originalFlag + " AND timestamp<" + std::to_string(dropTimeStamp); (void)sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); + } else if (tableType == KNOWLEDGE_TYPE) { + HandleDropKnowledgeTable(db, tableStr); } else { HandleDropCloudSyncTable(db, tableStr); } @@ -1550,11 +1636,39 @@ void PostHandle(bool isExists, sqlite3 *db) (void)ExecuteRawSQL(db, recursiveTrigger); } +void GetFtsTableInfos(sqlite3 *db, std::set &tableInfos) +{ + std::string sql = "SELECT name FROM main.sqlite_master WHERE type = 'table' AND sql LIKE 'CREATE VIRTUAL TABLE%'"; + sqlite3_stmt *stmt = nullptr; + int errCode = GetStatement(db, sql, stmt); + if (errCode != E_OK) { + LOGW("Prepare get fts table statement failed. err=%d", errCode); + return; + } + while ((errCode = StepWithRetry(stmt)) != SQLITE_DONE) { + if (errCode != SQLITE_ROW) { + LOGW("Get fts table info failed. err=%d", errCode); + ResetStatement(stmt); + return; + } + std::string tableName; + GetColumnTextValue(stmt, 0, tableName); + tableInfos.insert(tableName); + tableInfos.insert(tableName + "_config"); + tableInfos.insert(tableName + "_data"); + tableInfos.insert(tableName + "_docsize"); + tableInfos.insert(tableName + "_idx"); + } + ResetStatement(stmt); +} + int GetTableInfos(sqlite3 *db, std::map &tableInfos) { if (db == nullptr) { return -E_ERROR; } + std::set ftsTableInfos; + GetFtsTableInfos(db, ftsTableInfos); std::string sql = "SELECT name FROM main.sqlite_master WHERE type = 'table'"; sqlite3_stmt *stmt = nullptr; int errCode = GetStatement(db, sql, stmt); @@ -1570,7 +1684,8 @@ int GetTableInfos(sqlite3 *db, std::map &tableInfos) std::string tableName; GetColumnTextValue(stmt, 0, tableName); if (tableName.empty() || !ParamCheckUtils::CheckRelationalTableName(tableName) || - tableName.find("sqlite_") == 0 || tableName.find("naturalbase_") == 0) { + tableName.find("sqlite_") == 0 || tableName.find("naturalbase_") == 0 || + ftsTableInfos.find(tableName) != ftsTableInfos.end()) { continue; } tableInfos.insert(std::make_pair(tableName, true)); @@ -1628,10 +1743,29 @@ SQLITE_API int sqlite3_open16_relational(const void *filename, sqlite3 **ppDb) return err; } +static bool IsSupportCompressVfs(const char *filePath) +{ + if (filePath == nullptr) { + return false; + } + std::string filePathStr(filePath); + auto filename = filePathStr.substr(filePathStr.rfind("/") + 1, filePathStr.size()); + for (auto whiteItem : COMPRESS_WHITELIST) { + if (filename == std::string(whiteItem)) { + return true; + } + } + return false; +} + SQLITE_API int sqlite3_open_v2_relational(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs) { bool isExists = (access(filename, 0) == 0); - int err = sqlite3_open_v2(filename, ppDb, flags, zVfs); + const char *vfsOption = zVfs; + if (zVfs != nullptr && std::string(zVfs) == COMPRESS_VFS && !IsSupportCompressVfs(filename)) { + vfsOption = nullptr; + } + int err = sqlite3_open_v2(filename, ppDb, flags, vfsOption); if (err != SQLITE_OK) { return err; } @@ -1639,6 +1773,35 @@ SQLITE_API int sqlite3_open_v2_relational(const char *filename, sqlite3 **ppDb, return err; } +static bool IsBinlogSupported() +{ +#ifndef _WIN32 + auto handle = dlopen("libarkdata_db_core.z.so", RTLD_LAZY); + if (handle != nullptr) { + dlclose(handle); + return true; + } +#endif + return false; +} + +SQLITE_API int sqlite3_is_support_binlog_relational(const char *filename) +{ + if (filename == nullptr) { + return SQLITE_ERROR; + } + if (g_binlogInit == -1) { + std::lock_guard lock(g_binlogInitMutex); + if (g_binlogInit == -1) { + g_binlogInit = static_cast(IsBinlogSupported()); + } + } + if (g_binlogInit == static_cast(true)) { + return SQLITE_OK; + } + return SQLITE_ERROR; +} + DB_API DistributedDB::DBStatus RegisterClientObserver(sqlite3 *db, const ClientObserver &clientObserver) { std::string fileName; @@ -1670,10 +1833,19 @@ DB_API DistributedDB::DBStatus UnRegisterClientObserver(sqlite3 *db) return DistributedDB::DB_ERROR; } - std::lock_guard lock(g_clientObserverMutex); - auto it = g_clientObserverMap.find(hashFileName); - if (it != g_clientObserverMap.end()) { - g_clientObserverMap.erase(it); + { + std::lock_guard lock(g_clientObserverMutex); + auto it = g_clientObserverMap.find(hashFileName); + if (it != g_clientObserverMap.end()) { + g_clientObserverMap.erase(it); + } + } + { + std::lock_guard lock(g_clientChangedDataMutex); + auto it = g_clientChangedDataMap.find(hashFileName); + if (it != g_clientChangedDataMap.end()) { + g_clientChangedDataMap[hashFileName].tableData.clear(); + } } return DistributedDB::OK; } @@ -1751,7 +1923,6 @@ DB_API DistributedDB::DBStatus UnregisterStoreObserver(sqlite3 *db) std::string fileName; if (!GetDbFileName(db, fileName)) { LOGD("[UnregisterAllStoreObserver] StoreObserver is invalid."); - return DistributedDB::INVALID_ARGS; } @@ -1831,7 +2002,54 @@ DB_API DistributedDB::DBStatus CreateDataChangeTempTrigger(sqlite3 *db) { return DistributedDB::TransferDBErrno(CreateTempTrigger(db)); } -// hw export the symbols + +DistributedDB::DBStatus SetKnowledgeSourceSchema(sqlite3 *db, const DistributedDB::KnowledgeSourceSchema &schema) +{ + if (db == nullptr) { + LOGE("Can't set knowledge source schema with null db"); + return INVALID_ARGS; + } + int errCode = KnowledgeSourceUtils::SetKnowledgeSourceSchema(db, schema); + if (errCode == DistributedDB::E_OK) { + LOGI("Set knowledge source schema success, table %s len %zu", + DBCommon::StringMiddleMasking(schema.tableName).c_str(), schema.tableName.size()); + } else { + LOGE("Set knowledge source schema failed %d, table %s len %zu", + errCode, DBCommon::StringMiddleMasking(schema.tableName).c_str(), schema.tableName.size()); + } + return TransferDBErrno(errCode); +} + +DistributedDB::DBStatus CleanDeletedData(sqlite3 *db, const std::string &tableName, uint64_t cursor) +{ + if (db == nullptr) { + LOGE("Can't clean deleted data with null db"); + return INVALID_ARGS; + } + if (cursor > static_cast(INT64_MAX)) { + LOGW("Cursor is too large %" PRIu64, cursor); + cursor = 0; + } + int errCode = KnowledgeSourceUtils::CleanDeletedData(db, tableName, cursor); + if (errCode != DistributedDB::E_OK) { + LOGE("Clean delete data failed %d, table %s len %zu cursor " PRIu64, + errCode, DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), cursor); + } + return TransferDBErrno(errCode); +} + +void Clean(bool isOpenSslClean) +{ +#ifdef USE_FFRT + ConcurrentAdapter::Stop(); +#endif + if (isOpenSslClean) { + OPENSSL_cleanup(); + } + Logger::DeleteInstance(); +} + +// export the symbols #ifdef SQLITE_DISTRIBUTE_RELATIONAL #if defined(__GNUC__) # define EXPORT_SYMBOLS __attribute__ ((visibility ("default"))) @@ -1845,20 +2063,23 @@ struct sqlite3_api_routines_relational { int (*open)(const char *, sqlite3 **); int (*open16)(const void *, sqlite3 **); int (*open_v2)(const char *, sqlite3 **, int, const char *); + int (*is_support_binlog)(const char*); }; typedef struct sqlite3_api_routines_relational sqlite3_api_routines_relational; -static const sqlite3_api_routines_relational sqlite3HwApis = { +static const sqlite3_api_routines_relational sqlite3Apis = { #ifdef SQLITE_DISTRIBUTE_RELATIONAL sqlite3_open_relational, sqlite3_open16_relational, - sqlite3_open_v2_relational + sqlite3_open_v2_relational, + sqlite3_is_support_binlog_relational #else + 0, 0, 0, 0 #endif }; -EXPORT_SYMBOLS const sqlite3_api_routines_relational *sqlite3_export_relational_symbols = &sqlite3HwApis; +EXPORT_SYMBOLS const sqlite3_api_routines_relational *sqlite3_export_relational_symbols = &sqlite3Apis; #endif diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h index 012ba84c..8bcebd1e 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h @@ -62,6 +62,8 @@ public: // Get meta data associated with the given key. int GetMetaData(const Key &key, Value &value) const override; + int GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const override; + // Put meta data as a key-value entry. int PutMetaData(const Key &key, const Value &value) override; @@ -137,11 +139,11 @@ public: // recycling the write handle void SetReusedHandle(StorageExecutor *handle); - int StartTransaction(TransactType type) override; + int StartTransaction(TransactType type, bool isAsyncDownload = false) override; - int Commit() override; + int Commit(bool isAsyncDownload = false) override; - int Rollback() override; + int Rollback(bool isAsyncDownload = false) override; int GetUploadCount(const QuerySyncObject &query, const Timestamp ×tamp, bool isCloudForcePush, bool isCompensatedTask, int64_t &count) override; @@ -270,6 +272,8 @@ public: int GetLockStatusByGid(const std::string &tableName, const std::string &gid, LockStatus &status) override; bool IsExistTableContainAssets() override; + + int GetCompressionOption(bool &needCompressOnSync, uint8_t &compressionRate) const override; protected: int FillReferenceData(CloudSyncData &syncData); @@ -298,6 +302,8 @@ private: OperatePerm perm = OperatePerm::NORMAL_PERM) const; SQLiteSingleVerRelationalStorageExecutor *GetHandleExpectTransaction(bool isWrite, int &errCode, OperatePerm perm = OperatePerm::NORMAL_PERM) const; + SQLiteSingleVerRelationalStorageExecutor *GetHandleExpectTransactionForAsyncDownload(bool isWrite, int &errCode, + OperatePerm perm = OperatePerm::NORMAL_PERM) const; void ReleaseHandle(SQLiteSingleVerRelationalStorageExecutor *&handle) const; // get @@ -340,6 +346,12 @@ private: void SaveCursorChange(const std::string &tableName, uint64_t currCursor); + int CommitForAsyncDownload(); + + int RollbackForAsyncDownload(); + + int StartTransactionForAsyncDownload(TransactType type); + // data std::shared_ptr storageEngine_ = nullptr; std::function onSchemaChanged_; @@ -363,7 +375,9 @@ private: mutable bool isCachedOption_; SQLiteSingleVerRelationalStorageExecutor *transactionHandle_ = nullptr; + SQLiteSingleVerRelationalStorageExecutor *asyncDownloadTransactionHandle_ = nullptr; mutable std::shared_mutex transactionMutex_; // used for transaction + mutable std::shared_mutex asyncDownloadtransactionMutex_; // used for async download transaction SchemaMgr schemaMgr_; mutable std::shared_mutex schemaMgrMutex_; diff --git a/kv_store/frameworks/libs/distributeddb/sqlite_adapter/src/tokenizer_export_type.h b/kv_store/frameworks/libs/distributeddb/sqlite_adapter/src/tokenizer_export_type.h index 97b04188..46ee1afb 100644 --- a/kv_store/frameworks/libs/distributeddb/sqlite_adapter/src/tokenizer_export_type.h +++ b/kv_store/frameworks/libs/distributeddb/sqlite_adapter/src/tokenizer_export_type.h @@ -23,6 +23,7 @@ extern "C" { #endif #define GRD_OK 0 +#define GRD_INVALID_ARGS (-3000) #define GRD_API_NOT_SUPPORT (-8888) #define GRD_NO_DATA (-11000) #define GRD_FAILED_MEMORY_ALLOCATE (-13000) @@ -42,6 +43,12 @@ typedef enum GRD_CutMode { CUT_BUTT // INVALID TokenizeMode } GRD_CutModeE; +typedef enum GRD_CutScene { + DEFAULT = 0, + SEARCH = 1, + SCENE_BUTT // INVALID mode +} GRD_CutSceneE; + typedef enum GRD_ExtractMode { EXTRACT_TF_IDF = 0, EXTRACT_BUTT // INVALID ExtractMode @@ -54,6 +61,7 @@ typedef struct GRD_TokenizerParam { typedef struct GRD_CutOption { bool needPreProcess; + GRD_CutSceneE cutScene; } GRD_CutOptionT; typedef struct GRD_ExtractOption { diff --git a/kv_store/frameworks/libs/distributeddb/sqlite_adapter/src/tokenizer_sqlite.cpp b/kv_store/frameworks/libs/distributeddb/sqlite_adapter/src/tokenizer_sqlite.cpp index c2d6b4e6..1b541792 100644 --- a/kv_store/frameworks/libs/distributeddb/sqlite_adapter/src/tokenizer_sqlite.cpp +++ b/kv_store/frameworks/libs/distributeddb/sqlite_adapter/src/tokenizer_sqlite.cpp @@ -24,18 +24,52 @@ SQLITE_EXTENSION_INIT1 using namespace CNTokenizer; +typedef struct Fts5TokenizerParam { + uint32_t magicCode = 0; + GRD_CutScene cutScene = DEFAULT; +} Fts5TokenizerParamT; + static std::mutex g_mtx; -static uint32_t g_magicCode = 0x12345678; static uint32_t g_refCount = 0; constexpr int FTS5_MAX_VERSION = 2; +constexpr int CUSTOM_TOKENIZER_PARAM_NUM = 2; +constexpr int MAGIC_CODE = 0x12345678; +constexpr const char *CUT_SCENE_PARAM_NAME = "cut_mode"; +constexpr const char *CUT_SCENE_SHORT_WORDS = "short_words"; +constexpr const char *CUT_SCENE_DEFAULT = "default"; int fts5_customtokenizer_xCreate(void *sqlite3, const char **azArg, int nArg, Fts5Tokenizer **ppOut) { (void)sqlite3; std::lock_guard lock(g_mtx); + auto *pFts5TokenizerParam = new Fts5TokenizerParamT; + pFts5TokenizerParam->magicCode = MAGIC_CODE; + if (nArg != 0 && nArg != CUSTOM_TOKENIZER_PARAM_NUM) { + sqlite3_log(SQLITE_ERROR, "invalid args num"); + delete pFts5TokenizerParam; + return SQLITE_ERROR; + } + if (nArg == CUSTOM_TOKENIZER_PARAM_NUM) { + std::string paramKey = std::string(azArg[0]); + std::string paramValue = std::string(azArg[1]); + if (paramKey != CUT_SCENE_PARAM_NAME) { + sqlite3_log(SQLITE_ERROR, "invalid arg name"); + delete pFts5TokenizerParam; + return SQLITE_ERROR; + } + if (paramValue == CUT_SCENE_SHORT_WORDS) { + pFts5TokenizerParam->cutScene = SEARCH; + } else if (paramValue == CUT_SCENE_DEFAULT) { + pFts5TokenizerParam->cutScene = DEFAULT; + } else { + sqlite3_log(SQLITE_ERROR, "invalid arg value of cut scene"); + delete pFts5TokenizerParam; + return SQLITE_ERROR; + } + } g_refCount++; if (g_refCount != 1) { // 说明已经初始化过了,直接返回 - *ppOut = (Fts5Tokenizer *)&g_magicCode; + *ppOut = (Fts5Tokenizer *)pFts5TokenizerParam; return SQLITE_OK; } @@ -43,9 +77,10 @@ int fts5_customtokenizer_xCreate(void *sqlite3, const char **azArg, int nArg, Ft int ret = GRD_TokenizerInit(NULL, NULL, param); if (ret != GRD_OK) { sqlite3_log(ret, "GRD_TokenizerInit wrong"); + delete pFts5TokenizerParam; return ret; } - *ppOut = (Fts5Tokenizer *)&g_magicCode; // 需要保证*ppOut不为NULL,否则会使用默认分词器而不是自定的 + *ppOut = (Fts5Tokenizer *)pFts5TokenizerParam; // 需要保证*ppOut不为NULL,否则会使用默认分词器而不是自定的 return SQLITE_OK; } @@ -70,6 +105,11 @@ static char *CpyStr(const char *pText, int nText) int fts5_customtokenizer_xTokenize( Fts5Tokenizer *tokenizer_ptr, void *pCtx, int flags, const char *pText, int nText, XTokenFn xToken) { + Fts5TokenizerParamT *pFts5TokenizerParam = (Fts5TokenizerParamT *)tokenizer_ptr; + if (pFts5TokenizerParam == nullptr || pFts5TokenizerParam->magicCode != MAGIC_CODE) { + sqlite3_log(GRD_INVALID_ARGS, "The tokenizer is not initialized"); + return GRD_INVALID_ARGS; + } if (nText == 0) { return SQLITE_OK; } @@ -78,7 +118,7 @@ int fts5_customtokenizer_xTokenize( sqlite3_log(GRD_FAILED_MEMORY_ALLOCATE, "CpyStr wrong"); return GRD_FAILED_MEMORY_ALLOCATE; } - GRD_CutOptionT option = {false}; + GRD_CutOptionT option = {false, pFts5TokenizerParam->cutScene}; GRD_WordEntryListT *entryList = nullptr; int ret = GRD_TokenizerCut(ptr, option, &entryList); if (ret != GRD_OK) { @@ -109,11 +149,16 @@ int fts5_customtokenizer_xTokenize( void fts5_customtokenizer_xDelete(Fts5Tokenizer *tokenizer_ptr) { std::lock_guard lock(g_mtx); + Fts5TokenizerParamT *pFts5TokenizerParam = (Fts5TokenizerParamT *)tokenizer_ptr; + if (pFts5TokenizerParam != nullptr) { + delete pFts5TokenizerParam; + pFts5TokenizerParam = nullptr; + } g_refCount--; if (g_refCount != 0) { // 说明还有其他的地方在使用,不能释放资源 return; } - (void)GRD_TokenizerDestroy(tokenizer_ptr); + (void)GRD_TokenizerDestroy(nullptr); } /* @@ -121,20 +166,18 @@ void fts5_customtokenizer_xDelete(Fts5Tokenizer *tokenizer_ptr) ** If an error occurs, return NULL and leave an error in the database ** handle (accessible using sqlite3_errcode()/errmsg()). */ -static int fts5_api_from_db(sqlite3 *db, fts5_api **ppApi) +static int get_fts5_api(sqlite3 *db, fts5_api **api) { - sqlite3_stmt *pStmt = 0; - int rc; - - *ppApi = 0; - rc = sqlite3_prepare(db, "SELECT fts5(?1)", -1, &pStmt, 0); - if (rc == SQLITE_OK) { - sqlite3_bind_pointer(pStmt, 1, reinterpret_cast(ppApi), "fts5_api_ptr", 0); - (void)sqlite3_step(pStmt); - rc = sqlite3_finalize(pStmt); + sqlite3_stmt *stmt = nullptr; + *api = nullptr; + int ret = sqlite3_prepare(db, "SELECT fts5(?1)", -1, &stmt, 0); + if (ret != SQLITE_OK) { + sqlite3_log(ret, "sqlite3_prepare wrong"); + return ret; } - - return rc; + sqlite3_bind_pointer(stmt, 1, reinterpret_cast(api), "fts5_api_ptr", 0); + (void)sqlite3_step(stmt); + return sqlite3_finalize(stmt); } int sqlite3_customtokenizer_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi) @@ -145,13 +188,13 @@ int sqlite3_customtokenizer_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api fts5_tokenizer tokenizer = { fts5_customtokenizer_xCreate, fts5_customtokenizer_xDelete, fts5_customtokenizer_xTokenize}; - fts5_api *fts5api; - rc = fts5_api_from_db(db, &fts5api); + fts5_api *fts5api = nullptr; + rc = get_fts5_api(db, &fts5api); if (rc != SQLITE_OK) { - sqlite3_log(rc, "fts5_api_from_db wrong"); + sqlite3_log(rc, "get_fts5_api wrong"); return rc; } - if (fts5api == 0 || fts5api->iVersion < FTS5_MAX_VERSION) { + if (fts5api == nullptr || fts5api->iVersion < FTS5_MAX_VERSION) { sqlite3_log(SQLITE_ERROR, "sqlite3_customtokenizer_init wrong"); return SQLITE_ERROR; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/db_properties.h b/kv_store/frameworks/libs/distributeddb/storage/include/db_properties.h index dee39e70..0c9653bf 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/db_properties.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/db_properties.h @@ -67,6 +67,9 @@ public: static constexpr const char *DATABASE_TYPE = "databaseType"; + static constexpr const char *COMPRESS_ON_SYNC = "needCompressOnSync"; + static constexpr const char *COMPRESSION_RATE = "compressionRate"; + protected: std::map stringProperties_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h b/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h index 3f56d255..531b0dca 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h @@ -116,11 +116,11 @@ public: virtual int GetCloudTableSchema(const TableName &tableName, TableSchema &tableSchema) = 0; - virtual int StartTransaction(TransactType type) = 0; + virtual int StartTransaction(TransactType type, bool isAsyncDownload = false) = 0; - virtual int Commit() = 0; + virtual int Commit(bool isAsyncDownload = false) = 0; - virtual int Rollback() = 0; + virtual int Rollback(bool isAsyncDownload = false) = 0; virtual int GetUploadCount(const QuerySyncObject &query, const Timestamp ×tamp, bool isCloudForcePush, bool isCompensatedTask, int64_t &count) = 0; diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h b/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h index d9c8a60e..b102ffb9 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h @@ -100,7 +100,7 @@ public: virtual int SetConflictNotifier(int conflictType, const KvDBConflictAction &action) = 0; // Close and release the connection. - virtual int Close() = 0; + virtual int Close(bool isCloseImmediately = true) = 0; virtual std::string GetIdentifier() const = 0; @@ -171,6 +171,8 @@ public: virtual bool IsRebuild() const = 0; + virtual int ClearCloudWatermark() = 0; + virtual int OperateDataStatus(uint32_t dataOperator) = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h b/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h index 4cabb6b1..6a74a50c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h @@ -54,6 +54,8 @@ public: // Get meta data associated with the given key. virtual int GetMetaData(const Key &key, Value &value) const = 0; + virtual int GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const = 0; + // Put meta data as a key-value entry. virtual int PutMetaData(const Key &key, const Value &value, bool isInTransaction) = 0; diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_manager.h b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_manager.h index 88f028cd..4191a3a6 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_manager.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_manager.h @@ -41,7 +41,7 @@ public: bool isNeedIfOpened = true); // used to close the connection. - static int ReleaseDatabaseConnection(IKvDBConnection *connection); + static int ReleaseDatabaseConnection(IKvDBConnection *connection, bool isCloseImmediately = true); // used to delete a kvdb with the given property. static int RemoveDatabase(const KvDBProperties &property); diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_pragma.h b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_pragma.h index dd47e8fd..6283ca9f 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_pragma.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_pragma.h @@ -64,6 +64,7 @@ struct PragmaSync { onComplete_(onComplete), wait_(wait), isQuerySync_(true), + isRetry_(true), query_(query) { } @@ -76,6 +77,7 @@ struct PragmaSync { onComplete_(onComplete), wait_(wait), isQuerySync_(false), + isRetry_(true), query_(Query::Select()) { } @@ -85,6 +87,7 @@ struct PragmaSync { mode_(option.mode), wait_(option.isWait), isQuerySync_(option.isQuery), + isRetry_(true), onSyncProcess_(onProcess) { if (!isQuerySync_) { @@ -98,16 +101,45 @@ struct PragmaSync { mode_(option.mode), wait_(option.isWait), isQuerySync_(false), + isRetry_(true), query_(Query::Select()), onSyncProcess_(onProcess) { } + PragmaSync(const DeviceSyncOption &option, const QuerySyncObject &query, + const std::function &devicesMap)> &onComplete) + : devices_(option.devices), + mode_(option.mode), + onComplete_(onComplete), + wait_(option.isWait), + isQuerySync_(option.isQuery), + isRetry_(option.isRetry) + { + if (!isQuerySync_) { + return; + } + query_ = query; + } + + PragmaSync(const DeviceSyncOption &option, + const std::function &devicesMap)> &onComplete) + : devices_(option.devices), + mode_(option.mode), + onComplete_(onComplete), + wait_(option.isWait), + isQuerySync_(false), + isRetry_(option.isRetry), + query_(Query::Select()) + { + } + std::vector devices_; int mode_; std::function &devicesMap)> onComplete_; bool wait_; bool isQuerySync_; + bool isRetry_; QuerySyncObject query_; DeviceSyncProcessCallback onSyncProcess_; }; diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_properties.h b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_properties.h index 36179cec..766de8c3 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_properties.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_properties.h @@ -64,8 +64,6 @@ public: static const std::string CONFLICT_RESOLVE_POLICY; static const std::string CHECK_INTEGRITY; static const std::string RM_CORRUPTED_DB; - static const std::string COMPRESS_ON_SYNC; - static const std::string COMPRESSION_RATE; static const std::string LOCAL_ONLY; static const std::string SHARED_MODE; diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h index 13652f3b..acb034d7 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h @@ -76,7 +76,7 @@ public: virtual int GetDownloadingAssetsCount(int32_t &count) = 0; - virtual int SetDistributedDbSchema(const DistributedSchema &schema) = 0; + virtual int SetDistributedDbSchema(const DistributedSchema &schema, bool isForceUpgrade) = 0; virtual int SetTableMode(DistributedTableMode tableMode) = 0; @@ -100,6 +100,8 @@ public: virtual SyncProcess GetCloudTaskStatus(uint64_t taskId) = 0; #endif virtual int OperateDataStatus(uint32_t dataOperator) = 0; + + virtual int32_t GetDeviceSyncTaskCount() = 0; protected: // Get the stashed 'RelationalDB_ pointer' without ref. template diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h b/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h index 2ccc6c7c..c98d1fe6 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h @@ -33,7 +33,7 @@ namespace DistributedDB { class StorageProxy { public: StorageProxy(ICloudSyncStorageInterface *iCloud); - virtual ~StorageProxy() {}; + ~StorageProxy() {}; static std::shared_ptr GetCloudDb(ICloudSyncStorageInterface *iCloud); @@ -51,11 +51,11 @@ public: int SetCloudWaterMark(const std::string &tableName, std::string &cloudMark); - int StartTransaction(TransactType type = TransactType::DEFERRED); + int StartTransaction(TransactType type = TransactType::DEFERRED, bool isAsyncDownload = false); - int Commit(); + int Commit(bool isAsyncDownload = false); - int Rollback(); + int Rollback(bool isAsyncDownload = false); int GetUploadCount(const std::string &tableName, const Timestamp ×tamp, const bool isCloudForcePush, int64_t &count); @@ -188,6 +188,8 @@ public: int GetLockStatusByGid(const std::string &tableName, const std::string &gid, LockStatus &status); bool IsExistTableContainAssets(); + + bool GetTransactionExeFlag(); protected: void Init(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp index ee7540a2..05d175be 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp @@ -200,90 +200,6 @@ int CloudStorageUtils::BindAsset(int index, const VBucket &vBucket, const Field return errCode; } -int CloudStorageUtils::Int64ToVector(const VBucket &vBucket, const Field &field, CollateType collateType, - std::vector &value) -{ - (void)collateType; - int64_t val = 0; - if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { - return -E_CLOUD_ERROR; - } - DBCommon::StringToVector(std::to_string(val), value); - return E_OK; -} - -int CloudStorageUtils::BoolToVector(const VBucket &vBucket, const Field &field, CollateType collateType, - std::vector &value) -{ - (void)collateType; - bool val = false; - if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { // LCOV_EXCL_BR_LINE - return -E_CLOUD_ERROR; - } - DBCommon::StringToVector(std::to_string(val ? 1 : 0), value); - return E_OK; -} - -int CloudStorageUtils::DoubleToVector(const VBucket &vBucket, const Field &field, CollateType collateType, - std::vector &value) -{ - (void)collateType; - double val = 0.0; - if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { // LCOV_EXCL_BR_LINE - return -E_CLOUD_ERROR; - } - std::ostringstream s; - s << val; - DBCommon::StringToVector(s.str(), value); - return E_OK; -} - -int CloudStorageUtils::TextToVector(const VBucket &vBucket, const Field &field, CollateType collateType, - std::vector &value) -{ - std::string val; - if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { - return -E_CLOUD_ERROR; - } - if (collateType == CollateType::COLLATE_NOCASE) { - std::transform(val.begin(), val.end(), val.begin(), ::toupper); - } else if (collateType == CollateType::COLLATE_RTRIM) { - DBCommon::RTrim(val); - } - - DBCommon::StringToVector(val, value); - return E_OK; -} - -int CloudStorageUtils::BlobToVector(const VBucket &vBucket, const Field &field, CollateType collateType, - std::vector &value) -{ - (void)collateType; - if (field.type == TYPE_INDEX) { // LCOV_EXCL_BR_LINE - return CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, value); - } else if (field.type == TYPE_INDEX) { - Asset val; - if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { // LCOV_EXCL_BR_LINE - return -E_CLOUD_ERROR; - } - int errCode = RuntimeContext::GetInstance()->AssetToBlob(val, value); - if (errCode != E_OK) { // LCOV_EXCL_BR_LINE - LOGE("asset to blob fail, %d", errCode); - } - return errCode; - } else { - Assets val; - if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { // LCOV_EXCL_BR_LINE - return -E_CLOUD_ERROR; - } - int errCode = RuntimeContext::GetInstance()->AssetsToBlob(val, value); - if (errCode != E_OK) { // LCOV_EXCL_BR_LINE - LOGE("assets to blob fail, %d", errCode); - } - return errCode; - } -} - std::set CloudStorageUtils::GetCloudPrimaryKey(const TableSchema &tableSchema) { std::set pkSet; @@ -627,38 +543,6 @@ bool CloudStorageUtils::IsAssets(const Type &type) return type.index() == TYPE_INDEX; } -int CloudStorageUtils::CalculateHashKeyForOneField(const Field &field, const VBucket &vBucket, bool allowEmpty, - CollateType collateType, std::vector &hashValue) -{ - Type type; - bool isExisted = GetTypeCaseInsensitive(field.colName, vBucket, type); - if (allowEmpty && !isExisted) { - return E_OK; // if vBucket from cloud doesn't contain primary key and allowEmpty, no need to calculate hash - } - static std::map &)>> toVecFunc = { - { TYPE_INDEX, &CloudStorageUtils::Int64ToVector }, - { TYPE_INDEX, &CloudStorageUtils::BoolToVector }, - { TYPE_INDEX, &CloudStorageUtils::DoubleToVector }, - { TYPE_INDEX, &CloudStorageUtils::TextToVector }, - { TYPE_INDEX, &CloudStorageUtils::BlobToVector }, - { TYPE_INDEX, &CloudStorageUtils::BlobToVector }, - { TYPE_INDEX, &CloudStorageUtils::BlobToVector }, - }; - auto it = toVecFunc.find(field.type); - if (it == toVecFunc.end()) { - LOGE("unknown cloud type when convert field to vector."); - return -E_CLOUD_ERROR; - } - std::vector value; - int errCode = it->second(vBucket, field, collateType, value); - if (errCode != E_OK) { - LOGE("convert cloud field fail, %d", errCode); - return errCode; - } - return DBCommon::CalcValueHash(value, hashValue); -} - bool CloudStorageUtils::IsAssetsContainDuplicateAsset(Assets &assets) { std::set set; @@ -786,50 +670,6 @@ bool CloudStorageUtils::CheckAssetStatus(const Assets &assets) return true; } -std::string CloudStorageUtils::GetTableRefUpdateSql(const TableInfo &table, OpType opType) -{ - std::string sql; - std::string rowid = std::string(DBConstant::SQLITE_INNER_ROWID); - for (const auto &reference : table.GetTableReference()) { - if (reference.columns.empty()) { - return ""; - } - std::string sourceLogName = DBCommon::GetLogTableName(reference.sourceTableName); - sql += " UPDATE " + sourceLogName + " SET timestamp=get_raw_sys_time(), flag=flag|0x02 WHERE "; - int index = 0; - for (const auto &itCol : reference.columns) { - if (opType != OpType::UPDATE) { - continue; - } - if (index++ != 0) { - sql += " OR "; - } - sql += " (OLD." + itCol.second + " IS NOT " + " NEW." + itCol.second + ")"; - } - if (opType == OpType::UPDATE) { - sql += " AND "; - } - sql += " (flag&0x08=0x00) AND data_key IN (SELECT " + sourceLogName + ".data_key FROM " + sourceLogName + - " LEFT JOIN " + reference.sourceTableName + " ON " + sourceLogName + ".data_key = " + - reference.sourceTableName + "." + rowid + " WHERE "; - index = 0; - for (const auto &itCol : reference.columns) { - if (index++ != 0) { - sql += " OR "; - } - if (opType == OpType::UPDATE) { - sql += itCol.first + "=OLD." + itCol.second + " OR " + itCol.first + "=NEW." + itCol.second; - } else if (opType == OpType::INSERT) { - sql += itCol.first + "=NEW." + itCol.second; - } else if (opType == OpType::DELETE) { - sql += itCol.first + "=OLD." + itCol.second; - } - } - sql += ");"; - } - return sql; -} - std::string CloudStorageUtils::GetLeftJoinLogSql(const std::string &tableName, bool logAsTableA) { std::string sql; @@ -843,16 +683,6 @@ std::string CloudStorageUtils::GetLeftJoinLogSql(const std::string &tableName, b return sql; } -std::string CloudStorageUtils::GetUpdateLockChangedSql() -{ - return " status = CASE WHEN status == 2 THEN 3 ELSE status END"; -} - -std::string CloudStorageUtils::GetDeleteLockChangedSql() -{ - return " status = CASE WHEN status == 2 or status == 3 THEN 1 ELSE status END"; -} - bool CloudStorageUtils::ChkFillCloudAssetParam(const CloudSyncBatch &data, int errCode) { if (data.assets.empty()) { @@ -1028,34 +858,6 @@ bool CloudStorageUtils::CheckCloudSchemaFields(const TableSchema &tableSchema, c return true; } -void CloudStorageUtils::TransferFieldToLower(VBucket &vBucket) -{ - for (auto it = vBucket.begin(); it != vBucket.end();) { - std::string lowerField(it->first.length(), ' '); - std::transform(it->first.begin(), it->first.end(), lowerField.begin(), ::tolower); - if (lowerField != it->first) { - vBucket[lowerField] = std::move(vBucket[it->first]); - vBucket.erase(it++); - } else { - it++; - } - } -} - -bool CloudStorageUtils::GetTypeCaseInsensitive(const std::string &fieldName, const VBucket &vBucket, Type &data) -{ - auto tmpFieldName = fieldName; - auto tmpVBucket = vBucket; - std::transform(tmpFieldName.begin(), tmpFieldName.end(), tmpFieldName.begin(), ::tolower); - TransferFieldToLower(tmpVBucket); - auto it = tmpVBucket.find(tmpFieldName); - if (it == tmpVBucket.end()) { - return false; - } - data = it->second; - return true; -} - int CloudStorageUtils::BindUpdateLogStmtFromVBucket(const VBucket &vBucket, const TableSchema &tableSchema, const std::vector &colNames, sqlite3_stmt *updateLogStmt) { @@ -1502,26 +1304,6 @@ bool CloudStorageUtils::IsSystemRecord(const Key &key) return keyStr.find(prefixKey) == 0; } -std::string CloudStorageUtils::GetSelectIncCursorSql(const std::string &tableName) -{ - return "(SELECT value FROM " + DBCommon::GetMetaTableName() + " WHERE key=x'" + - DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "')"; -} - -std::string CloudStorageUtils::GetCursorIncSql(const std::string &tableName) -{ - return "UPDATE " + DBCommon::GetMetaTableName() + " SET value=value+1 WHERE key=x'" + - DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "';"; -} - -std::string CloudStorageUtils::GetCursorIncSqlWhenAllow(const std::string &tableName) -{ - std::string prefix = DBConstant::RELATIONAL_PREFIX; - return "UPDATE " + prefix + "metadata" + " SET value= case when (select 1 from " + - prefix + "metadata" + " where key='cursor_inc_flag' AND value = 'true') then value + 1" + - " else value end WHERE key=x'" + DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "';"; -} - std::string CloudStorageUtils::GetCursorUpgradeSql(const std::string &tableName) { return "INSERT OR REPLACE INTO " + DBCommon::GetMetaTableName() + "(key,value) VALUES (x'" + diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils_client.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils_client.cpp new file mode 100644 index 00000000..ee25dbe6 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils_client.cpp @@ -0,0 +1,248 @@ +/* + * 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 "cloud/cloud_storage_utils.h" + +#include +#include "db_common.h" +#include "runtime_context.h" + +namespace DistributedDB { +int CloudStorageUtils::Int64ToVector(const VBucket &vBucket, const Field &field, CollateType collateType, + std::vector &value) +{ + (void)collateType; + int64_t val = 0; + if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { + return -E_CLOUD_ERROR; + } + DBCommon::StringToVector(std::to_string(val), value); + return E_OK; +} + +int CloudStorageUtils::BoolToVector(const VBucket &vBucket, const Field &field, CollateType collateType, + std::vector &value) +{ + (void)collateType; + bool val = false; + if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { // LCOV_EXCL_BR_LINE + return -E_CLOUD_ERROR; + } + DBCommon::StringToVector(std::to_string(val ? 1 : 0), value); + return E_OK; +} + +int CloudStorageUtils::DoubleToVector(const VBucket &vBucket, const Field &field, CollateType collateType, + std::vector &value) +{ + (void)collateType; + double val = 0.0; + if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { // LCOV_EXCL_BR_LINE + return -E_CLOUD_ERROR; + } + std::ostringstream s; + s << val; + DBCommon::StringToVector(s.str(), value); + return E_OK; +} + +int CloudStorageUtils::TextToVector(const VBucket &vBucket, const Field &field, CollateType collateType, + std::vector &value) +{ + std::string val; + if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { + return -E_CLOUD_ERROR; + } + if (collateType == CollateType::COLLATE_NOCASE) { + std::transform(val.begin(), val.end(), val.begin(), ::toupper); + } else if (collateType == CollateType::COLLATE_RTRIM) { + DBCommon::RTrim(val); + } + + DBCommon::StringToVector(val, value); + return E_OK; +} + +int CloudStorageUtils::BlobToVector(const VBucket &vBucket, const Field &field, CollateType collateType, + std::vector &value) +{ + (void)collateType; + if (field.type == TYPE_INDEX) { // LCOV_EXCL_BR_LINE + return CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, value); + } else if (field.type == TYPE_INDEX) { + Asset val; + if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { // LCOV_EXCL_BR_LINE + return -E_CLOUD_ERROR; + } +#ifdef RDB_CLIENT + return E_OK; +#else + int errCode = RuntimeContext::GetInstance()->AssetToBlob(val, value); + if (errCode != E_OK) { // LCOV_EXCL_BR_LINE + LOGE("asset to blob fail, %d", errCode); + } + return errCode; +#endif + } else { + Assets val; + if (CloudStorageUtils::GetValueFromVBucket(field.colName, vBucket, val) != E_OK) { // LCOV_EXCL_BR_LINE + return -E_CLOUD_ERROR; + } +#ifdef RDB_CLIENT + return E_OK; +#else + int errCode = RuntimeContext::GetInstance()->AssetsToBlob(val, value); + if (errCode != E_OK) { // LCOV_EXCL_BR_LINE + LOGE("assets to blob fail, %d", errCode); + } + return errCode; +#endif + } +} + +int CloudStorageUtils::CalculateHashKeyForOneField(const Field &field, const VBucket &vBucket, bool allowEmpty, + CollateType collateType, std::vector &hashValue) +{ + Type type; + bool isExisted = GetTypeCaseInsensitive(field.colName, vBucket, type); + if (allowEmpty && !isExisted) { + return E_OK; // if vBucket from cloud doesn't contain primary key and allowEmpty, no need to calculate hash + } + static std::map &)>> toVecFunc = { + { TYPE_INDEX, &CloudStorageUtils::Int64ToVector }, + { TYPE_INDEX, &CloudStorageUtils::BoolToVector }, + { TYPE_INDEX, &CloudStorageUtils::DoubleToVector }, + { TYPE_INDEX, &CloudStorageUtils::TextToVector }, + { TYPE_INDEX, &CloudStorageUtils::BlobToVector }, + { TYPE_INDEX, &CloudStorageUtils::BlobToVector }, + { TYPE_INDEX, &CloudStorageUtils::BlobToVector }, + }; + auto it = toVecFunc.find(field.type); + if (it == toVecFunc.end()) { + LOGE("unknown cloud type when convert field to vector."); + return -E_CLOUD_ERROR; + } + std::vector value; + int errCode = it->second(vBucket, field, collateType, value); + if (errCode != E_OK) { + LOGE("convert cloud field fail, %d", errCode); + return errCode; + } + return DBCommon::CalcValueHash(value, hashValue); +} + +void CloudStorageUtils::TransferFieldToLower(VBucket &vBucket) +{ + for (auto it = vBucket.begin(); it != vBucket.end();) { + std::string lowerField(it->first.length(), ' '); + std::transform(it->first.begin(), it->first.end(), lowerField.begin(), ::tolower); + if (lowerField != it->first) { + vBucket[lowerField] = std::move(vBucket[it->first]); + vBucket.erase(it++); + } else { + it++; + } + } +} + +bool CloudStorageUtils::GetTypeCaseInsensitive(const std::string &fieldName, const VBucket &vBucket, Type &data) +{ + auto tmpFieldName = fieldName; + auto tmpVBucket = vBucket; + std::transform(tmpFieldName.begin(), tmpFieldName.end(), tmpFieldName.begin(), ::tolower); + TransferFieldToLower(tmpVBucket); + auto it = tmpVBucket.find(tmpFieldName); + if (it == tmpVBucket.end()) { + return false; + } + data = it->second; + return true; +} + +std::string CloudStorageUtils::GetSelectIncCursorSql(const std::string &tableName) +{ + return "(SELECT value FROM " + DBCommon::GetMetaTableName() + " WHERE key=x'" + + DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "')"; +} + +std::string CloudStorageUtils::GetCursorIncSql(const std::string &tableName) +{ + return "UPDATE " + DBCommon::GetMetaTableName() + " SET value=value+1 WHERE key=x'" + + DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "';"; +} + +std::string CloudStorageUtils::GetCursorIncSqlWhenAllow(const std::string &tableName) +{ + std::string prefix = DBConstant::RELATIONAL_PREFIX; + return "UPDATE " + prefix + "metadata" + " SET value= case when (select 1 from " + + prefix + "metadata" + " where key='cursor_inc_flag' AND value = 'true') then value + 1" + + " else value end WHERE key=x'" + DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "';"; +} + +std::string CloudStorageUtils::GetUpdateLockChangedSql() +{ + return " status = CASE WHEN status == 2 THEN 3 ELSE status END"; +} + +std::string CloudStorageUtils::GetDeleteLockChangedSql() +{ + return " status = CASE WHEN status == 2 or status == 3 THEN 1 ELSE status END"; +} + +std::string CloudStorageUtils::GetTableRefUpdateSql(const TableInfo &table, OpType opType) +{ + std::string sql; + std::string rowid = std::string(DBConstant::SQLITE_INNER_ROWID); + for (const auto &reference : table.GetTableReference()) { + if (reference.columns.empty()) { + return ""; + } + std::string sourceLogName = DBCommon::GetLogTableName(reference.sourceTableName); + sql += " UPDATE " + sourceLogName + " SET timestamp=get_raw_sys_time(), flag=flag|0x02 WHERE "; + int index = 0; + for (const auto &itCol : reference.columns) { + if (opType != OpType::UPDATE) { + continue; + } + if (index++ != 0) { + sql += " OR "; + } + sql += " (OLD." + itCol.second + " IS NOT " + " NEW." + itCol.second + ")"; + } + if (opType == OpType::UPDATE) { + sql += " AND "; + } + sql += " (flag&0x08=0x00) AND data_key IN (SELECT " + sourceLogName + ".data_key FROM " + sourceLogName + + " LEFT JOIN " + reference.sourceTableName + " ON " + sourceLogName + ".data_key = " + + reference.sourceTableName + "." + rowid + " WHERE "; + index = 0; + for (const auto &itCol : reference.columns) { + if (index++ != 0) { + sql += " OR "; + } + if (opType == OpType::UPDATE) { + sql += itCol.first + "=OLD." + itCol.second + " OR " + itCol.first + "=NEW." + itCol.second; + } else if (opType == OpType::INSERT) { + sql += itCol.first + "=NEW." + itCol.second; + } else if (opType == OpType::DELETE) { + sql += itCol.first + "=OLD." + itCol.second; + } + } + sql += ");"; + } + return sql; +} +} diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h b/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h index e6847b34..b055c37f 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h @@ -59,7 +59,8 @@ enum class LogInfoFlag : uint32_t { FLAG_LOGIC_DELETE_FOR_LOGOUT = 0x800, FLAG_ASSET_DOWNLOADING_FOR_ASYNC = 0x1000, FLAG_LOGIN_USER = 0x2000, // same hash key, login user's data - FLAG_CLOUD_UPDATE_LOCAL = 0x4000, + FLAG_CLOUD_UPDATE_LOCAL = 0x4000, // 1 indicates an update on the cloud side, and 0 indicates data inserted on the + // cloud side or data operated locally }; struct RowDataWithLog { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp index 4dc8f24f..f27f602b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp @@ -198,6 +198,11 @@ int RdSingleVerNaturalStore::GetMetaData(const Key &key, Value &value) const return -E_NOT_SUPPORT; } +int RdSingleVerNaturalStore::GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const +{ + return -E_NOT_SUPPORT; +} + int RdSingleVerNaturalStore::PutMetaData(const Key &key, const Value &value, bool isInTransaction) { return -E_NOT_SUPPORT; @@ -585,4 +590,12 @@ void RdSingleVerNaturalStore::InitDataBaseOption(const KvDBProperties &kvDBProp, void RdSingleVerNaturalStore::SetReceiveDataInterceptor(const DataInterceptor &interceptor) { } + +CloudSyncConfig RdSingleVerNaturalStore::GetCloudSyncConfig() const +{ + // Implement the pure virtual function in the base class SyncAbleKvDB. + // Currently, rd does not have this function, so return the default value of CloudSyncConfig. + CloudSyncConfig config; + return config; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.h index 0fbfe896..80d90313 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.h @@ -60,6 +60,8 @@ public: int GetMetaData(const Key &key, Value &value) const override; + int GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const override; + int PutMetaData(const Key &key, const Value &value, bool isInTransaction) override; // Delete multiple meta data records in a transaction. @@ -144,6 +146,8 @@ public: void CommitNotify(int notifyEvent, KvDBCommitNotifyFilterAbleData *data) override; void SetReceiveDataInterceptor(const DataInterceptor &interceptor) override; + + CloudSyncConfig GetCloudSyncConfig() const override; private: int PreCheckRdImport(std::string &storePath); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp index 4faa13d9..2c43b9c3 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp @@ -463,7 +463,7 @@ int RdSingleVerNaturalStoreConnection::RegisterLifeCycleCallback(const DatabaseL } // Called when Close and delete the connection. -int RdSingleVerNaturalStoreConnection::PreClose() +int RdSingleVerNaturalStoreConnection::PreClose(bool isCloseImmediately) { // check if result set closed std::lock_guard lock(kvDbResultSetsMutex_); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.h index e8b76c5a..cc7866e4 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.h @@ -90,7 +90,7 @@ public: int RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier) override; // Called when Close and delete the connection. - int PreClose() override; + int PreClose(bool isCloseImmediately) override; int CheckIntegrity() const override; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp index 17adfff9..bb51a0fb 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp @@ -273,6 +273,7 @@ int RdSingleVerResultSet::MoveTo(int position) const int RdSingleVerResultSet::MoveToFirst() { + std::lock_guard lockGuard(mutex_); if (!isMovedBefore_) { return MoveToNext(); } @@ -299,6 +300,7 @@ int RdSingleVerResultSet::MoveToFirst() int RdSingleVerResultSet::MoveToLast() { + std::lock_guard lockGuard(mutex_); int errCode = E_OK; do { errCode = MoveToNext(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp index 6996332e..efcf423d 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp @@ -46,13 +46,14 @@ int RdSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *& return ret; } GRD_DB *db = nullptr; - ret = TryToOpenMainDatabase(isWrite, db); + auto option = GetOption(); + ret = TryToOpenMainDatabase(isWrite, db, option); if (ret != E_OK) { LOGE("[RdSingleVerStorageEngine] GRD_DBOPEN FAILED:%d", ret); return ret; } - if (!option_.readOnly) { - std::string tableMode = GetTableMode(option_.isHashTable); + if (!option.readOnly) { + std::string tableMode = GetTableMode(option.isHashTable); ret = RdCreateCollection(db, SYNC_COLLECTION_NAME, tableMode.c_str(), 0); if (ret != E_OK) { LOGE("[RdSingleVerStorageEngine] GRD_CreateCollection SYNC_COLLECTION_NAME FAILED %d", ret); @@ -71,8 +72,8 @@ int RdSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *& (void)RdDBClose(db, GRD_DB_CLOSE_IGNORE_ERROR); return -E_OUT_OF_MEMORY; } - if (OS::CheckPathExistence(option_.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) && - OS::RemoveFile(option_.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) != E_OK) { + if (OS::CheckPathExistence(option.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) && + OS::RemoveFile(option.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) != E_OK) { LOGE("Finish to create the complete database, but delete token fail! errCode = [E_SYSTEM_API_FAIL]"); delete handle; handle = nullptr; @@ -124,7 +125,7 @@ int RdSingleVerStorageEngine::CreateNewDirsAndSetSecOpt() const return CreateNewDirsAndSetSecOption(option_); } -int RdSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, GRD_DB *&db) +int RdSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, GRD_DB *&db, OpenDbProperties &optionTemp) { // Only could get the main database handle in the uninitialized and the main status. if (GetEngineState() != EngineState::INVALID && GetEngineState() != EngineState::MAINDB) { @@ -132,10 +133,10 @@ int RdSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, GRD_DB *&db) return -E_EKEYREVOKED; } - option_.uri = GetDbDir(option_.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + + optionTemp.uri = GetDbDir(optionTemp.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; + SetUri(optionTemp.uri); - OpenDbProperties optionTemp = option_; if (!isWrite) { optionTemp.createIfNecessary = false; } @@ -150,17 +151,6 @@ int RdSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, GRD_DB *&db) return errCode; } -int RdSingleVerStorageEngine::GetDbHandle(bool isWrite, const SecurityOption &secOpt, GRD_DB *&dbHandle) -{ - int errCode = TryToOpenMainDatabase(isWrite, dbHandle); - LOGD("Finish to open the main database, write[%d], label[%d], flag[%d], id[%.6s], errCode[%d]", isWrite, - secOpt.securityLabel, secOpt.securityFlag, hashIdentifier_.c_str(), errCode); - if (!(ParamCheckUtils::IsS3SECEOpt(secOpt) && errCode == -E_EKEYREVOKED)) { - return errCode; - } - return -E_NOT_SUPPORT; -} - int RdSingleVerStorageEngine::PreCreateExecutor(bool isWrite) { if (!isWrite) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.h index 4b7887eb..dafd3975 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.h @@ -46,9 +46,7 @@ private: int CreateNewDirsAndSetSecOpt() const; - int TryToOpenMainDatabase(bool isWrite, GRD_DB *&db); - - int GetDbHandle(bool isWrite, const SecurityOption &secOpt, GRD_DB *&dbHandle); + int TryToOpenMainDatabase(bool isWrite, GRD_DB *&db, OpenDbProperties &optionTemp); int OpenGrdDb(const OpenDbProperties &option, GRD_DB *&db); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.cpp index 0cfce6b0..51d32dcb 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.cpp @@ -248,7 +248,6 @@ int RdKVBatchPushback(GRD_KVBatchT *batch, const Key &key, const Value &value) innerVal.data = (void *)&value[0]; innerVal.dataLen = (uint32_t)value.size(); } - int ret = TransferGrdErrno( GRD_KVBatchPushback(innerKey.data, innerKey.dataLen, innerVal.data, innerVal.dataLen, batch)); if (ret != E_OK) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.cpp index 13c4cf90..71654c04 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.cpp @@ -422,4 +422,13 @@ void GenericKvDB::MarkRebuild() { isRebuild_ = true; } + +int GenericKvDB::PreClose() +{ + if (connectionCount_.load() == 1) { + return E_OK; + } + // it will not cause busy when close db, only to verify the last conn + return -E_BUSY; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.h b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.h index 042e4bbd..4b9bbd5c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.h @@ -134,6 +134,8 @@ public: virtual void ResetSyncStatus(); void MarkRebuild() override; + + virtual int PreClose(); protected: // Create a connection object, no DB ref increased. virtual GenericKvDBConnection *NewConnection(int &errCode) = 0; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.cpp index 74fabd6e..957d0dc8 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.cpp @@ -175,7 +175,7 @@ int GenericKvDBConnection::SetConflictNotifier(int conflictType, const KvDBConfl return -E_NOT_SUPPORT; } -int GenericKvDBConnection::Close() +int GenericKvDBConnection::Close(bool isCloseImmediately) { if (kvDB_ == nullptr) { return -E_INVALID_CONNECTION; @@ -190,7 +190,7 @@ int GenericKvDBConnection::Close() return -E_BUSY; } - int errCode = PreClose(); + int errCode = PreClose(isCloseImmediately); if (errCode != E_OK) { LOGE("Close connection failed, err:'%d'.", errCode); return errCode; @@ -214,9 +214,9 @@ int GenericKvDBConnection::Pragma(int cmd, void *parameter) return -E_NOT_SUPPORT; } -int GenericKvDBConnection::PreClose() +int GenericKvDBConnection::PreClose(bool isCloseImmediately) { - return E_OK; + return kvDB_->PreClose(); } void GenericKvDBConnection::SetSafeDeleted() @@ -457,6 +457,11 @@ bool GenericKvDBConnection::IsRebuild() const return isRebuild_; } +int GenericKvDBConnection::ClearCloudWatermark() +{ + return -E_NOT_SUPPORT; +} + int GenericKvDBConnection::OperateDataStatus([[gnu::unused]] uint32_t dataOperator) { return -E_NOT_SUPPORT; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.h index e752a7dd..fe37fc77 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.h @@ -44,7 +44,7 @@ public: int SetConflictNotifier(int conflictType, const KvDBConflictAction &action) override; // Close and release the connection. - int Close() final; + int Close(bool isCloseImmediately = true) final override; std::string GetIdentifier() const override; @@ -113,6 +113,8 @@ public: bool IsRebuild() const override; + int ClearCloudWatermark() override; + int OperateDataStatus(uint32_t dataOperator) override; protected: // Get the stashed 'KvDB_ pointer' without ref. @@ -133,7 +135,7 @@ protected: bool IsObserverEmpty(); // Called in Close(), overriding of Close() is forbidden. - virtual int PreClose(); + virtual int PreClose(bool isCloseImmediately); GenericKvDB *kvDB_; std::atomic isExclusive_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_manager.cpp index 68d23e50..d2a39449 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_manager.cpp @@ -293,16 +293,16 @@ bool KvDBManager::CheckOpenDBOptionWithCached(const KvDBProperties &properties, return false; } - bool compressOnSyncUser = properties.GetBoolProp(KvDBProperties::COMPRESS_ON_SYNC, false); - bool compressOnSyncGet = kvDB->GetMyProperties().GetBoolProp(KvDBProperties::COMPRESS_ON_SYNC, false); + bool compressOnSyncUser = properties.GetBoolProp(DBProperties::COMPRESS_ON_SYNC, false); + bool compressOnSyncGet = kvDB->GetMyProperties().GetBoolProp(DBProperties::COMPRESS_ON_SYNC, false); if (compressOnSyncUser != compressOnSyncGet) { LOGE("Failed to check compress option, the input %d not match with cached %d.", compressOnSyncUser, compressOnSyncGet); return false; } if (compressOnSyncUser) { - int compressRateUser = properties.GetIntProp(KvDBProperties::COMPRESSION_RATE, 0); - int compressRateGet = kvDB->GetMyProperties().GetIntProp(KvDBProperties::COMPRESSION_RATE, 0); + int compressRateUser = properties.GetIntProp(DBProperties::COMPRESSION_RATE, 0); + int compressRateGet = kvDB->GetMyProperties().GetIntProp(DBProperties::COMPRESSION_RATE, 0); if (compressRateUser != compressRateGet) { LOGE("Failed to check compress rate, the input %d not match with cached %d.", compressRateUser, compressRateGet); @@ -364,7 +364,7 @@ IKvDBConnection *KvDBManager::GetDatabaseConnection(const KvDBProperties &proper return connection; } -int KvDBManager::ReleaseDatabaseConnection(IKvDBConnection *connection) +int KvDBManager::ReleaseDatabaseConnection(IKvDBConnection *connection, bool isCloseImmediately) { if (connection == nullptr) { return -E_INVALID_DB; @@ -376,7 +376,7 @@ int KvDBManager::ReleaseDatabaseConnection(IKvDBConnection *connection) return -E_OUT_OF_MEMORY; } manager->EnterDBOpenCloseProcess(identifier); - int errCode = connection->Close(); + int errCode = connection->Close(isCloseImmediately); manager->ExitDBOpenCloseProcess(identifier); if (errCode != E_OK) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_properties.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_properties.cpp index 6e655bba..ae8c6d12 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_properties.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_properties.cpp @@ -28,8 +28,6 @@ const std::string KvDBProperties::SECURITY_FLAG = "securityFlag"; const std::string KvDBProperties::CONFLICT_RESOLVE_POLICY = "conflictResolvePolicy"; const std::string KvDBProperties::CHECK_INTEGRITY = "checkIntegrity"; const std::string KvDBProperties::RM_CORRUPTED_DB = "rmCorruptedDb"; -const std::string KvDBProperties::COMPRESS_ON_SYNC = "needCompressOnSync"; -const std::string KvDBProperties::COMPRESSION_RATE = "compressionRate"; const std::string KvDBProperties::LOCAL_ONLY = "localOnly"; const std::string KvDBProperties::SHARED_MODE = "sharedMode"; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.cpp index ae6511bb..a8dbabc3 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.cpp @@ -92,7 +92,7 @@ void SyncAbleKvDB::Close() } // Start a sync action. -int SyncAbleKvDB::Sync(const ISyncer::SyncParma &parma, uint64_t connectionId) +int SyncAbleKvDB::Sync(const ISyncer::SyncParam &parma, uint64_t connectionId) { if (!started_) { int errCode = StartSyncer(); @@ -206,13 +206,13 @@ int SyncAbleKvDB::StartSyncerWithNoLock(bool isCheckSyncActive, bool isNeedActiv // active to non_active userChangeListener_ = RuntimeContext::GetInstance()->RegisterUserChangedListener( [this](void *) { ChangeUserListener(); }, UserChangeMonitor::USER_ACTIVE_TO_NON_ACTIVE_EVENT); - LOGI("[KVDB] [StartSyncerWithNoLock] [%.3s] After RegisterUserChangedListener", label.c_str()); + LOGI("[KVDB] [StartSyncerWithNoLock] [%.3s]", label.c_str()); } else if (isSyncDualTupleMode && (userChangeListener_ == nullptr)) { EventType event = isNeedActive ? UserChangeMonitor::USER_ACTIVE_EVENT : UserChangeMonitor::USER_NON_ACTIVE_EVENT; userChangeListener_ = RuntimeContext::GetInstance()->RegisterUserChangedListener( [this](void *) { UserChangeHandle(); }, event); - LOGI("[KVDB] [StartSyncerWithNoLock] [%.3s] After RegisterUserChangedListener event=%d", label.c_str(), event); + LOGI("[KVDB] [StartSyncerWithNoLock] [%.3s] event=%d", label.c_str(), event); } return errCode; } @@ -599,6 +599,30 @@ CloudSyncer *SyncAbleKvDB::GetAndIncCloudSyncer() return cloudSyncer_; } +bool SyncAbleKvDB::ExchangeClosePending(bool expected) +{ + return syncer_.ExchangeClosePending(expected); +} + +int SyncAbleKvDB::PreClose() +{ + if (GenericKvDB::PreClose() == E_OK) { + int32_t taskCount = GetTaskCount(); + if (taskCount > 0) { + LOGI("[PreClose] task count:%d", taskCount); + return -E_BUSY; + } + ExchangeClosePending(true); + taskCount = GetTaskCount(); + if (taskCount > 0) { + LOGI("[PreClose] task count:%d.", taskCount); + ExchangeClosePending(false); + return -E_BUSY; + } + } + return E_OK; +} + #ifdef USE_DISTRIBUTEDDB_CLOUD void SyncAbleKvDB::FillSyncInfo(const CloudSyncOption &option, const SyncProcessCallback &onProcess, CloudSyncer::CloudTaskInfo &info) diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.h b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.h index 8167cb6d..0ecdf791 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.h @@ -43,7 +43,7 @@ public: void Close() override; // Start a sync action. - int Sync(const ISyncer::SyncParma &parma, uint64_t connectionId); + int Sync(const ISyncer::SyncParam &parma, uint64_t connectionId); // Cancel a sync action. int CancelSync(uint32_t syncId); @@ -109,6 +109,9 @@ public: int32_t GetTaskCount(); + virtual CloudSyncConfig GetCloudSyncConfig() const = 0; + + int PreClose() override; #ifdef USE_DISTRIBUTEDDB_CLOUD int Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess); @@ -155,6 +158,7 @@ protected: protected: virtual std::map GetDataBaseSchemas(); + bool ExchangeClosePending(bool expected); #ifdef USE_DISTRIBUTEDDB_CLOUD virtual bool CheckSchemaSupportForCloudSync() const; #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb_connection.cpp index 94275ffe..a9444d47 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb_connection.cpp @@ -145,11 +145,12 @@ int SyncAbleKvDBConnection::PragmaSyncAction(const PragmaSync *syncParameter) IncObjRef(this); } - ISyncer::SyncParma syncParam; + ISyncer::SyncParam syncParam; syncParam.devices = syncParameter->devices_; syncParam.mode = syncParameter->mode_; syncParam.wait = syncParameter->wait_; syncParam.isQuerySync = syncParameter->isQuerySync_; + syncParam.isRetry = syncParameter->isRetry_; syncParam.syncQuery = syncParameter->query_; syncParam.onFinalize = [this]() { DecObjRef(this); }; if (syncParameter->onComplete_) { @@ -418,7 +419,8 @@ int SyncAbleKvDBConnection::Sync(const CloudSyncOption &option, const SyncProces int securityLabel = INVALID_SEC_LABEL; int securityFlag = INVALID_SEC_FLAG; GetSecurityOption(securityLabel, securityFlag); - if (securityLabel == S4) { + CloudSyncConfig config = kvDB->GetCloudSyncConfig(); + if ((securityLabel == S4) && (!config.isSupportEncrypt)) { LOGE("The current data does not support synchronization."); return -E_SECURITY_OPTION_CHECK_ERROR; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_vacuum.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_vacuum.cpp index 9014b470..89b08264 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_vacuum.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_vacuum.cpp @@ -283,7 +283,7 @@ void MultiVerVacuum::VacuumTaskExecutor() } } // No thread will remove entry from dbMapVacuumTask_, so here is concurrency safe. - LOGI("[Vacuum][Executor] Execute vacuum task for database=%s.", nextDatabase.c_str()); + LOGI("[Vacuum][Executor] Execute vacuum task for database."); ExecuteSpecificVacuumTask(dbMapVacuumTask_[nextDatabase]); // Awake foreground thread at this task switch point vacuumTaskCv_.notify_all(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.cpp index 2f57b7bf..6cdb7485 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.cpp @@ -543,19 +543,28 @@ int SingleVerDatabaseOper::RunRekeyLogic(CipherType type, const CipherPassword & int errCode = SQLiteUtils::OpenDatabase(option, db); if (errCode != E_OK) { LOGE("[RunRekeyLogic] Open database new connect fail!, errCode = [%d]", errCode); - goto END; + return errCode; } - - errCode = SQLiteUtils::Rekey(db, passwd); - if (errCode != E_OK) { - LOGE("[RunRekeyLogic] Rekey fail!, errCode = [%d]", errCode); - goto END; + errCode = RunRekeyLogicInner(type, db, passwd); + if (db != nullptr) { + (void)sqlite3_close_v2(db); + db = nullptr; } + return errCode; +} +int SingleVerDatabaseOper::RunRekeyLogicInner(CipherType type, sqlite3 *db, const CipherPassword &passwd) +{ // Release all the connections, update the passwd and re-initialize the storage engine. storageEngine_->Release(); - singleVerNaturalStore_->GetDbPropertyForUpdate().SetPassword(type, passwd); - errCode = InitStorageEngine(); + int rekeyRet = SQLiteUtils::Rekey(db, passwd); + if (rekeyRet != E_OK) { + LOGE("[RunRekeyLogic] Rekey fail!, errCode = [%d]", rekeyRet); + } else { + singleVerNaturalStore_->GetDbPropertyForUpdate().SetPassword(type, passwd); + } + + int errCode = InitStorageEngine(); if (errCode != E_OK) { LOGE("Init storage engine while rekey open failed:%d", errCode); } @@ -565,12 +574,6 @@ int SingleVerDatabaseOper::RunRekeyLogic(CipherType type, const CipherPassword & LOGI("Rekey successfully, locked state init state successfully, need ignore open file failed!"); errCode = -E_FORBID_CACHEDB; } - -END: - if (db != nullptr) { - (void)sqlite3_close_v2(db); - db = nullptr; - } - return errCode; + return rekeyRet == E_OK ? errCode : rekeyRet; } } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.h b/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.h index b670b0d9..626b1706 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.h @@ -74,6 +74,8 @@ private: int BackupDatabase(const ImportFileInfo &info) const; + int RunRekeyLogicInner(CipherType type, sqlite3 *db, const CipherPassword &passwd); + SQLiteSingleVerNaturalStore *singleVerNaturalStore_; SQLiteStorageEngine *storageEngine_; }; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_store_instance.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_store_instance.cpp index 5a700760..546d28df 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_store_instance.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_store_instance.cpp @@ -67,7 +67,7 @@ int RelationalStoreInstance::ReleaseDataBaseConnection(RelationalStoreConnection static IRelationalStore *GetFromCache(const RelationalDBProperties &properties, int &errCode) { errCode = E_OK; - std::string identifier = properties.GetStringProp(RelationalDBProperties::IDENTIFIER_DATA, ""); + std::string identifier = properties.GetStringProp(RelationalDBProperties::DATA_DIR, ""); std::lock_guard lockGuard(storeLock_); auto iter = dbs_.find(identifier); if (iter == dbs_.end()) { @@ -88,14 +88,14 @@ static IRelationalStore *GetFromCache(const RelationalDBProperties &properties, // Save to IKvDB to the global map void RelationalStoreInstance::RemoveKvDBFromCache(const RelationalDBProperties &properties) { - std::string identifier = properties.GetStringProp(RelationalDBProperties::IDENTIFIER_DATA, ""); + std::string identifier = properties.GetStringProp(RelationalDBProperties::DATA_DIR, ""); std::lock_guard lockGuard(storeLock_); dbs_.erase(identifier); } void RelationalStoreInstance::SaveRelationalDBToCache(IRelationalStore *store, const RelationalDBProperties &properties) { - std::string identifier = properties.GetStringProp(RelationalDBProperties::IDENTIFIER_DATA, ""); + std::string identifier = properties.GetStringProp(RelationalDBProperties::DATA_DIR, ""); std::lock_guard lockGuard(storeLock_); if (dbs_.count(identifier) == 0) { dbs_.insert(std::pair(identifier, store)); @@ -186,6 +186,22 @@ int CheckCompatibility(const RelationalDBProperties &prop, const RelationalDBPro LOGE("Failed to check dual tuple sync mode for rdb."); return -E_MODE_MISMATCH; } + bool compressOnSyncUser = prop.GetBoolProp(DBProperties::COMPRESS_ON_SYNC, false); + bool compressOnSyncGet = existedProp.GetBoolProp(DBProperties::COMPRESS_ON_SYNC, false); + if (compressOnSyncUser != compressOnSyncGet) { + LOGE("Failed to check compress option, the input %d not match with cached %d.", compressOnSyncUser, + compressOnSyncGet); + return -E_INVALID_ARGS; + } + if (compressOnSyncUser) { + int compressRateUser = prop.GetIntProp(DBProperties::COMPRESSION_RATE, 0); + int compressRateGet = existedProp.GetIntProp(DBProperties::COMPRESSION_RATE, 0); + if (compressRateUser != compressRateGet) { + LOGE("Failed to check compress rate, the input %d not match with cached %d.", compressRateUser, + compressRateGet); + return -E_INVALID_ARGS; + } + } return E_OK; } } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage.cpp index b0bde0a8..68b16f4d 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage.cpp @@ -84,7 +84,7 @@ std::vector RelationalSyncAbleStorage::GetIdentifier() const std::vector RelationalSyncAbleStorage::GetDualTupleIdentifier() const { - std::string identifier = storageEngine_->GetProperties().GetStringProp( + std::string identifier = storageEngine_->GetRelationalProperties().GetStringProp( DBProperties::DUAL_TUPLE_IDENTIFIER_DATA, ""); std::vector identifierVect(identifier.begin(), identifier.end()); return identifierVect; @@ -102,10 +102,9 @@ void RelationalSyncAbleStorage::GetMaxTimestamp(Timestamp ×tamp) const errCode = handle->GetMaxTimestamp(storageEngine_->GetSchema().GetTableNames(), timestamp); if (errCode != E_OK) { LOGE("GetMaxTimestamp failed, errCode:%d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } ReleaseHandle(handle); - return; } int RelationalSyncAbleStorage::GetMaxTimestamp(const std::string &tableName, Timestamp ×tamp) const @@ -119,7 +118,7 @@ int RelationalSyncAbleStorage::GetMaxTimestamp(const std::string &tableName, Tim errCode = handle->GetMaxTimestamp({ tableName }, timestamp); if (errCode != E_OK) { LOGE("GetMaxTimestamp failed, errCode:%d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } ReleaseHandle(handle); return errCode; @@ -135,7 +134,7 @@ SQLiteSingleVerRelationalStorageExecutor *RelationalSyncAbleStorage::GetHandle(b auto handle = static_cast( storageEngine_->FindExecutor(isWrite, perm, errCode)); if (handle == nullptr) { - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } return handle; } @@ -179,9 +178,6 @@ void RelationalSyncAbleStorage::ReleaseHandle(SQLiteSingleVerRelationalStorageEx // Get meta data associated with the given key. int RelationalSyncAbleStorage::GetMetaData(const Key &key, Value &value) const { - if (storageEngine_ == nullptr) { - return -E_INVALID_DB; - } if (key.size() > DBConstant::MAX_KEY_SIZE) { return -E_INVALID_ARGS; } @@ -192,7 +188,25 @@ int RelationalSyncAbleStorage::GetMetaData(const Key &key, Value &value) const } errCode = handle->GetKvData(key, value); if (errCode != E_OK && errCode != -E_NOT_FOUND) { - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); + } + ReleaseHandle(handle); + return errCode; +} + +int RelationalSyncAbleStorage::GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const +{ + if (keyPrefix.size() > DBConstant::MAX_KEY_SIZE) { + return -E_INVALID_ARGS; + } + int errCode = E_OK; + auto handle = GetHandle(false, errCode, OperatePerm::NORMAL_PERM); + if (handle == nullptr) { + return errCode; + } + errCode = handle->GetKvDataByPrefixKey(keyPrefix, data); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } ReleaseHandle(handle); return errCode; @@ -201,9 +215,6 @@ int RelationalSyncAbleStorage::GetMetaData(const Key &key, Value &value) const // Put meta data as a key-value entry. int RelationalSyncAbleStorage::PutMetaData(const Key &key, const Value &value) { - if (storageEngine_ == nullptr) { - return -E_INVALID_DB; - } int errCode = E_OK; auto *handle = GetHandle(true, errCode, OperatePerm::NORMAL_PERM); if (handle == nullptr) { @@ -213,7 +224,7 @@ int RelationalSyncAbleStorage::PutMetaData(const Key &key, const Value &value) errCode = handle->PutKvData(key, value); // meta doesn't need time. if (errCode != E_OK) { LOGE("Put kv data err:%d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } ReleaseHandle(handle); return errCode; @@ -249,7 +260,7 @@ int RelationalSyncAbleStorage::PutMetaData(const Key &key, const Value &value, b errCode = handle->PutKvData(key, value); if (errCode != E_OK) { LOGE("Put kv data err:%d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } if (!isInTransaction) { ReleaseHandle(handle); @@ -260,9 +271,6 @@ int RelationalSyncAbleStorage::PutMetaData(const Key &key, const Value &value, b // Delete multiple meta data records in a transaction. int RelationalSyncAbleStorage::DeleteMetaData(const std::vector &keys) { - if (storageEngine_ == nullptr) { - return -E_INVALID_DB; - } for (const auto &key : keys) { if (key.empty() || key.size() > DBConstant::MAX_KEY_SIZE) { return -E_INVALID_ARGS; @@ -279,7 +287,7 @@ int RelationalSyncAbleStorage::DeleteMetaData(const std::vector &keys) if (errCode != E_OK) { handle->Rollback(); LOGE("[SinStore] DeleteMetaData failed, errCode = %d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } else { handle->Commit(); } @@ -290,9 +298,6 @@ int RelationalSyncAbleStorage::DeleteMetaData(const std::vector &keys) // Delete multiple meta data records with key prefix in a transaction. int RelationalSyncAbleStorage::DeleteMetaDataByPrefixKey(const Key &keyPrefix) const { - if (storageEngine_ == nullptr) { - return -E_INVALID_DB; - } if (keyPrefix.empty() || keyPrefix.size() > DBConstant::MAX_KEY_SIZE) { return -E_INVALID_ARGS; } @@ -306,7 +311,7 @@ int RelationalSyncAbleStorage::DeleteMetaDataByPrefixKey(const Key &keyPrefix) c errCode = handle->DeleteMetaDataByPrefixKey(keyPrefix); if (errCode != E_OK) { LOGE("[SinStore] DeleteMetaData by prefix key failed, errCode = %d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } ReleaseHandle(handle); return errCode; @@ -315,9 +320,6 @@ int RelationalSyncAbleStorage::DeleteMetaDataByPrefixKey(const Key &keyPrefix) c // Get all meta data keys. int RelationalSyncAbleStorage::GetAllMetaKeys(std::vector &keys) const { - if (storageEngine_ == nullptr) { - return -E_INVALID_DB; - } int errCode = E_OK; auto *handle = GetHandle(true, errCode, OperatePerm::NORMAL_PERM); if (handle == nullptr) { @@ -326,7 +328,7 @@ int RelationalSyncAbleStorage::GetAllMetaKeys(std::vector &keys) const errCode = handle->GetAllMetaKeys(keys); if (errCode != E_OK) { - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } ReleaseHandle(handle); return errCode; @@ -594,8 +596,8 @@ int RelationalSyncAbleStorage::SaveSyncDataItems(const QueryObject &object, std: data.tableName = query.GetTableName(); // SPLIT_BY_DEVICE trigger observer with device, userId, appId and storeId, so trigger with isChangeData false // COLLABORATION trigger observer with changeData, so trigger with isChangeData true - TriggerObserverAction(deviceName, std::move(data), - GetDbProperties().GetDistributedTableMode() == DistributedTableMode::COLLABORATION, Origin::ORIGIN_REMOTE); + TriggerObserverAction(deviceName, std::move(data), storageEngine_->GetRelationalProperties() + .GetDistributedTableMode() == DistributedTableMode::COLLABORATION, Origin::ORIGIN_REMOTE); } ReleaseHandle(handle); @@ -613,7 +615,7 @@ int RelationalSyncAbleStorage::PutSyncData(const QueryObject &query, std::vector int errCode = SaveSyncDataItems(query, dataItems, deviceName); // Currently true to check value content if (errCode != E_OK) { LOGE("[Relational] PutSyncData errCode:%d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } return errCode; } @@ -637,7 +639,7 @@ int RelationalSyncAbleStorage::GetSecurityOption(SecurityOption &option) const option = securityOption_; return E_OK; } - std::string dbPath = storageEngine_->GetProperties().GetStringProp(DBProperties::DATA_DIR, ""); + std::string dbPath = storageEngine_->GetRelationalProperties().GetStringProp(DBProperties::DATA_DIR, ""); int errCode = RuntimeContext::GetInstance()->GetSecurityOption(dbPath, securityOption_); if (errCode == E_OK) { option = securityOption_; @@ -683,7 +685,7 @@ int RelationalSyncAbleStorage::InterceptData(std::vector &en int RelationalSyncAbleStorage::CreateDistributedDeviceTable(const std::string &device, const RelationalSyncStrategy &syncStrategy) { - auto mode = storageEngine_->GetProperties().GetDistributedTableMode(); + auto mode = storageEngine_->GetRelationalProperties().GetDistributedTableMode(); if (mode != DistributedTableMode::SPLIT_BY_DEVICE) { LOGD("No need create device table in COLLABORATION mode."); return E_OK; @@ -698,7 +700,7 @@ int RelationalSyncAbleStorage::CreateDistributedDeviceTable(const std::string &d errCode = handle->StartTransaction(TransactType::IMMEDIATE); if (errCode != E_OK) { LOGE("Start transaction failed:%d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); ReleaseHandle(handle); return errCode; } @@ -866,7 +868,7 @@ int RelationalSyncAbleStorage::CheckAndInitQueryCondition(QueryObject &query) co errCode = handle->CheckQueryObjectLegal(table, query, schema.GetSchemaVersion()); if (errCode != E_OK) { LOGE("Check relational query condition failed. %d", errCode); - TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + TriggerCloseAutoLaunchConn(storageEngine_->GetRelationalProperties()); } ReleaseHandle(handle); @@ -1027,15 +1029,18 @@ void RelationalSyncAbleStorage::ReleaseRemoteQueryContinueToken(ContinueToken &t StoreInfo RelationalSyncAbleStorage::GetStoreInfo() const { StoreInfo info = { - storageEngine_->GetProperties().GetStringProp(DBProperties::USER_ID, ""), - storageEngine_->GetProperties().GetStringProp(DBProperties::APP_ID, ""), - storageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, "") + storageEngine_->GetRelationalProperties().GetStringProp(DBProperties::USER_ID, ""), + storageEngine_->GetRelationalProperties().GetStringProp(DBProperties::APP_ID, ""), + storageEngine_->GetRelationalProperties().GetStringProp(DBProperties::STORE_ID, "") }; return info; } -int RelationalSyncAbleStorage::StartTransaction(TransactType type) +int RelationalSyncAbleStorage::StartTransaction(TransactType type, bool isAsyncDownload) { + if (isAsyncDownload) { + return StartTransactionForAsyncDownload(type); + } if (storageEngine_ == nullptr) { return -E_INVALID_DB; } @@ -1060,8 +1065,11 @@ int RelationalSyncAbleStorage::StartTransaction(TransactType type) return errCode; } -int RelationalSyncAbleStorage::Commit() +int RelationalSyncAbleStorage::Commit(bool isAsyncDownload) { + if (isAsyncDownload) { + return CommitForAsyncDownload(); + } std::unique_lock lock(transactionMutex_); if (transactionHandle_ == nullptr) { LOGE("relation database is null or the transaction has not been started"); @@ -1074,8 +1082,11 @@ int RelationalSyncAbleStorage::Commit() return errCode; } -int RelationalSyncAbleStorage::Rollback() +int RelationalSyncAbleStorage::Rollback(bool isAsyncDownload) { + if (isAsyncDownload) { + return RollbackForAsyncDownload(); + } std::unique_lock lock(transactionMutex_); if (transactionHandle_ == nullptr) { LOGE("Invalid handle for rollback or the transaction has not been started."); @@ -1126,10 +1137,6 @@ int RelationalSyncAbleStorage::GetUploadCount(const QuerySyncObject &query, cons int RelationalSyncAbleStorage::GetCloudData(const TableSchema &tableSchema, const QuerySyncObject &querySyncObject, const Timestamp &beginTime, ContinueToken &continueStmtToken, CloudSyncData &cloudDataResult) { - if (transactionHandle_ == nullptr) { - LOGE("the transaction has not been started"); - return -E_INVALID_DB; - } SyncTimeRange syncTimeRange = { .beginTime = beginTime }; QuerySyncObject query = querySyncObject; query.SetSchema(GetSchemaInfo()); @@ -1153,18 +1160,23 @@ int RelationalSyncAbleStorage::GetCloudDataNext(ContinueToken &continueStmtToken if (!token->CheckValid()) { return -E_INVALID_ARGS; } - if (transactionHandle_ == nullptr) { - LOGE("the transaction has not been started, release the token"); + int errCode = E_OK; + auto *handle = GetHandleExpectTransaction(false, errCode); + if (handle == nullptr) { + LOGE("Invalid handle, release the token, %d", errCode); ReleaseCloudDataToken(continueStmtToken); return -E_INVALID_DB; } cloudDataResult.isShared = IsSharedTable(cloudDataResult.tableName); auto config = GetCloudSyncConfig(); - transactionHandle_->SetUploadConfig(config.maxUploadCount, config.maxUploadSize); - int errCode = transactionHandle_->GetSyncCloudData(uploadRecorder_, cloudDataResult, *token); + handle->SetUploadConfig(config.maxUploadCount, config.maxUploadSize); + errCode = handle->GetSyncCloudData(uploadRecorder_, cloudDataResult, *token); LOGI("mode:%d upload data, ins:%zu, upd:%zu, del:%zu, lock:%zu", cloudDataResult.mode, cloudDataResult.insData.extend.size(), cloudDataResult.updData.extend.size(), cloudDataResult.delData.extend.size(), cloudDataResult.lockData.extend.size()); + if (transactionHandle_ == nullptr) { + ReleaseHandle(handle); + } if (errCode != -E_UNFINISHED) { delete token; token = nullptr; @@ -1469,7 +1481,7 @@ void RelationalSyncAbleStorage::EraseDataChangeCallback(uint64_t connectionId) auto it = dataChangeCallbackMap_.find(connectionId); if (it != dataChangeCallbackMap_.end()) { dataChangeCallbackMap_.erase(it); - LOGI("erase all observer for this delegate."); + LOGI("erase all observer, %" PRIu64, connectionId); } }, nullptr, &dataChangeCallbackMap_); ADAPTER_WAIT(handle); @@ -1980,229 +1992,5 @@ int RelationalSyncAbleStorage::ClearUnLockingNoNeedCompensated() ReleaseHandle(handle); return errCode; } - -int RelationalSyncAbleStorage::GetCloudTableWithoutShared(std::vector &tables) -{ - const auto tableInfos = GetSchemaInfo().GetTables(); - for (const auto &[tableName, info] : tableInfos) { - if (info.GetSharedTableMark()) { - continue; - } - TableSchema schema; - int errCode = GetCloudTableSchema(tableName, schema); - if (errCode == -E_NOT_FOUND) { - continue; - } - if (errCode != E_OK) { - LOGW("[RDBStorage] Get cloud table failed %d", errCode); - return errCode; - } - tables.push_back(schema); - } - return E_OK; -} - -int RelationalSyncAbleStorage::GetCompensatedSyncQueryInner(SQLiteSingleVerRelationalStorageExecutor *handle, - const std::vector &tables, std::vector &syncQuery, bool isQueryDownloadRecords) -{ - int errCode = E_OK; - errCode = handle->StartTransaction(TransactType::IMMEDIATE); - if (errCode != E_OK) { - return errCode; - } - for (const auto &table : tables) { - if (!CheckTableSupportCompensatedSync(table)) { - continue; - } - - std::vector syncDataPk; - errCode = handle->GetWaitCompensatedSyncDataPk(table, syncDataPk, isQueryDownloadRecords); - if (errCode != E_OK) { - LOGW("[RDBStorageEngine] Get wait compensated sync data failed, continue! errCode=%d", errCode); - errCode = E_OK; - continue; - } - if (syncDataPk.empty()) { - // no data need to compensated sync - continue; - } - errCode = CloudStorageUtils::GetSyncQueryByPk(table.name, syncDataPk, false, syncQuery); - if (errCode != E_OK) { - LOGW("[RDBStorageEngine] Get compensated sync query happen error, ignore it! errCode = %d", errCode); - errCode = E_OK; - continue; - } - } - if (errCode == E_OK) { - errCode = handle->Commit(); - if (errCode != E_OK) { - LOGE("[RDBStorageEngine] commit failed %d when get compensated sync query", errCode); - } - } else { - int ret = handle->Rollback(); - if (ret != E_OK) { - LOGW("[RDBStorageEngine] rollback failed %d when get compensated sync query", ret); - } - } - return errCode; -} - -int RelationalSyncAbleStorage::CreateTempSyncTriggerInner(SQLiteSingleVerRelationalStorageExecutor *handle, - const std::string &tableName, bool flag) -{ - TrackerTable trackerTable = storageEngine_->GetTrackerSchema().GetTrackerTable(tableName); - if (trackerTable.IsEmpty()) { - trackerTable.SetTableName(tableName); - } - return handle->CreateTempSyncTrigger(trackerTable, flag); -} - -bool RelationalSyncAbleStorage::CheckTableSupportCompensatedSync(const TableSchema &table) -{ - auto it = std::find_if(table.fields.begin(), table.fields.end(), [](const auto &field) { - return field.primary && (field.type == TYPE_INDEX || field.type == TYPE_INDEX || - field.type == TYPE_INDEX); - }); - if (it != table.fields.end()) { - LOGI("[RDBStorageEngine] Table contain not support pk field type, ignored"); - return false; - } - // check whether reference exist - std::map> tableReference; - int errCode = RelationalSyncAbleStorage::GetTableReference(table.name, tableReference); - if (errCode != E_OK) { - LOGW("[RDBStorageEngine] Get table reference failed! errCode = %d", errCode); - return false; - } - if (!tableReference.empty()) { - LOGI("[RDBStorageEngine] current table exist reference property"); - return false; - } - return true; -} - -int RelationalSyncAbleStorage::MarkFlagAsConsistent(const std::string &tableName, const DownloadData &downloadData, - const std::set &gidFilters) -{ - if (transactionHandle_ == nullptr) { - LOGE("the transaction has not been started"); - return -E_INVALID_DB; - } - int errCode = transactionHandle_->MarkFlagAsConsistent(tableName, downloadData, gidFilters); - if (errCode != E_OK) { - LOGE("[RelationalSyncAbleStorage] mark flag as consistent failed.%d", errCode); - } - return errCode; -} - -CloudSyncConfig RelationalSyncAbleStorage::GetCloudSyncConfig() const -{ - std::lock_guard autoLock(configMutex_); - return cloudSyncConfig_; -} - -void RelationalSyncAbleStorage::SetCloudSyncConfig(const CloudSyncConfig &config) -{ - std::lock_guard autoLock(configMutex_); - cloudSyncConfig_ = config; -} - -bool RelationalSyncAbleStorage::IsTableExistReference(const std::string &table) -{ - // check whether reference exist - std::map> tableReference; - int errCode = RelationalSyncAbleStorage::GetTableReference(table, tableReference); - if (errCode != E_OK) { - LOGW("[RDBStorageEngine] Get table reference failed! errCode = %d", errCode); - return false; - } - return !tableReference.empty(); -} - -bool RelationalSyncAbleStorage::IsTableExistReferenceOrReferenceBy(const std::string &table) -{ - // check whether reference or reference by exist - if (storageEngine_ == nullptr) { - LOGE("[IsTableExistReferenceOrReferenceBy] storage is null when get reference gid"); - return false; - } - RelationalSchemaObject schema = storageEngine_->GetSchema(); - auto referenceProperty = schema.GetReferenceProperty(); - if (referenceProperty.empty()) { - return false; - } - auto [sourceTableName, errCode] = GetSourceTableName(table); - if (errCode != E_OK) { - return false; - } - for (const auto &property : referenceProperty) { - if (DBCommon::CaseInsensitiveCompare(property.sourceTableName, sourceTableName) || - DBCommon::CaseInsensitiveCompare(property.targetTableName, sourceTableName)) { - return true; - } - } - return false; -} - -void RelationalSyncAbleStorage::ReleaseUploadRecord(const std::string &tableName, const CloudWaterType &type, - Timestamp localMark) -{ - uploadRecorder_.ReleaseUploadRecord(tableName, type, localMark); -} - -int RelationalSyncAbleStorage::ReviseLocalModTime(const std::string &tableName, - const std::vector &revisedData) -{ - if (storageEngine_ == nullptr) { - LOGE("[ReviseLocalModTime] Storage is null"); - return -E_INVALID_DB; - } - int errCode = E_OK; - auto writeHandle = static_cast( - storageEngine_->FindExecutor(true, OperatePerm::NORMAL_PERM, errCode)); - if (writeHandle == nullptr) { - LOGE("[ReviseLocalModTime] Get write handle fail: %d", errCode); - return errCode; - } - errCode = writeHandle->StartTransaction(TransactType::IMMEDIATE); - if (errCode != E_OK) { - LOGE("[ReviseLocalModTime] Start Transaction fail: %d", errCode); - ReleaseHandle(writeHandle); - return errCode; - } - errCode = writeHandle->ReviseLocalModTime(tableName, revisedData); - if (errCode != E_OK) { - LOGE("[ReviseLocalModTime] Revise local modify time fail: %d", errCode); - writeHandle->Rollback(); - ReleaseHandle(writeHandle); - return errCode; - } - errCode = writeHandle->Commit(); - ReleaseHandle(writeHandle); - return errCode; -} - -int RelationalSyncAbleStorage::GetCursor(const std::string &tableName, uint64_t &cursor) -{ - if (transactionHandle_ == nullptr) { - LOGE("[RelationalSyncAbleStorage] the transaction has not been started"); - return -E_INVALID_DB; - } - return transactionHandle_->GetCursor(tableName, cursor); -} - -int RelationalSyncAbleStorage::GetLocalDataCount(const std::string &tableName, int &dataCount, - int &logicDeleteDataCount) -{ - int errCode = E_OK; - auto *handle = GetHandle(false, errCode); - if (handle == nullptr || errCode != E_OK) { - LOGE("[RelationalSyncAbleStorage] Get handle failed when get local data count: %d", errCode); - return errCode; - } - errCode = handle->GetLocalDataCount(tableName, dataCount, logicDeleteDataCount); - ReleaseHandle(handle); - return errCode; -} } #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage_extend.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage_extend.cpp index 4e98a047..cc970468 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage_extend.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage_extend.cpp @@ -181,68 +181,61 @@ int RelationalSyncAbleStorage::FillCloudAssetForAsyncDownload(const std::string LOGE("[RelationalSyncAbleStorage]storage is null when fill asset for async download"); return -E_INVALID_DB; } - int errCode = E_OK; - auto *handle = GetHandle(true, errCode); - if (handle == nullptr) { - LOGE("executor is null when fill asset for async download."); - return errCode; + if (asyncDownloadTransactionHandle_ == nullptr) { + LOGE("the transaction has not been started when fill asset for async download."); + return -E_INVALID_DB; } TableSchema tableSchema; - errCode = GetCloudTableSchema(tableName, tableSchema); + int errCode = GetCloudTableSchema(tableName, tableSchema); if (errCode != E_OK) { - ReleaseHandle(handle); - LOGE("Get cloud schema failed when fill cloud asset, %d, tableName:%s, length:%zu", - errCode, DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size()); + LOGE("Get cloud schema failed when fill cloud asset, %d", errCode); return errCode; } uint64_t currCursor = DBConstant::INVALID_CURSOR; - errCode = handle->FillCloudAssetForDownload(tableSchema, asset, isDownloadSuccess, currCursor); + errCode = asyncDownloadTransactionHandle_->FillCloudAssetForDownload( + tableSchema, asset, isDownloadSuccess, currCursor); if (errCode != E_OK) { - LOGE("fill cloud asset for download failed:%d, tableName:%s, length:%zu", - errCode, DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size()); + LOGE("fill cloud asset for async download failed.%d", errCode); } - SaveCursorChange(tableName, currCursor); - ReleaseHandle(handle); return errCode; } int RelationalSyncAbleStorage::UpdateRecordFlagForAsyncDownload(const std::string &tableName, bool recordConflict, const LogInfo &logInfo) { - int errCode = E_OK; - auto *handle = GetHandle(true, errCode); - if (handle == nullptr) { - LOGE("executor is null when update flag for async download."); + if (asyncDownloadTransactionHandle_ == nullptr) { + LOGE("[RelationalSyncAbleStorage] the transaction has not been started"); + return -E_INVALID_DB; + } + TableSchema tableSchema; + GetCloudTableSchema(tableName, tableSchema); + std::vector assets; + int errCode = asyncDownloadTransactionHandle_->GetDownloadAssetRecordsByGid(tableSchema, logInfo.cloudGid, assets); + if (errCode != E_OK) { + LOGE("[RelationalSyncAbleStorage] get download asset by gid %s failed %d", logInfo.cloudGid.c_str(), errCode); return errCode; } + bool isInconsistency = !assets.empty(); UpdateRecordFlagStruct updateRecordFlag = { .tableName = tableName, .isRecordConflict = recordConflict, - .isInconsistency = false + .isInconsistency = isInconsistency }; std::string sql = CloudStorageUtils::GetUpdateRecordFlagSql(updateRecordFlag, logInfo); - errCode = handle->UpdateRecordFlag(tableName, sql, logInfo); - if (errCode != E_OK) { - LOGE("update flag for async download failed:%d, tableName:%s, length:%zu", - errCode, DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size()); - } - ReleaseHandle(handle); - return errCode; + return asyncDownloadTransactionHandle_->UpdateRecordFlag(tableName, sql, logInfo); } int RelationalSyncAbleStorage::SetLogTriggerStatusForAsyncDownload(bool status) { int errCode = E_OK; - auto *handle = GetHandle(false, errCode); + auto *handle = GetHandleExpectTransactionForAsyncDownload(false, errCode); if (handle == nullptr) { - LOGE("executor is null when set trigger status for async download."); return errCode; } errCode = handle->SetLogTriggerStatus(status); - if (errCode != E_OK) { - LOGE("set trigger status for async download failed:%d"); + if (asyncDownloadTransactionHandle_ == nullptr) { + ReleaseHandle(handle); } - ReleaseHandle(handle); return errCode; } @@ -330,5 +323,314 @@ bool RelationalSyncAbleStorage::IsSetDistributedSchema(const std::string &tableN } return true; } + +int RelationalSyncAbleStorage::CommitForAsyncDownload() +{ + std::unique_lock lock(asyncDownloadtransactionMutex_); + if (asyncDownloadTransactionHandle_ == nullptr) { + LOGE("relation database is null or the transaction has not been started"); + return -E_INVALID_DB; + } + int errCode = asyncDownloadTransactionHandle_->Commit(); + ReleaseHandle(asyncDownloadTransactionHandle_); + asyncDownloadTransactionHandle_ = nullptr; + LOGD("connection commit transaction!"); + return errCode; +} + +int RelationalSyncAbleStorage::RollbackForAsyncDownload() +{ + std::unique_lock lock(asyncDownloadtransactionMutex_); + if (asyncDownloadTransactionHandle_ == nullptr) { + LOGE("Invalid handle for rollback or the transaction has not been started."); + return -E_INVALID_DB; + } + + int errCode = asyncDownloadTransactionHandle_->Rollback(); + ReleaseHandle(asyncDownloadTransactionHandle_); + asyncDownloadTransactionHandle_ = nullptr; + LOGI("connection rollback transaction!"); + return errCode; +} + +SQLiteSingleVerRelationalStorageExecutor *RelationalSyncAbleStorage::GetHandleExpectTransactionForAsyncDownload( + bool isWrite, int &errCode, OperatePerm perm) const +{ + if (storageEngine_ == nullptr) { + errCode = -E_INVALID_DB; + return nullptr; + } + if (asyncDownloadTransactionHandle_ != nullptr) { + return asyncDownloadTransactionHandle_; + } + auto handle = static_cast( + storageEngine_->FindExecutor(isWrite, perm, errCode)); + if (errCode != E_OK) { + ReleaseHandle(handle); + handle = nullptr; + } + return handle; +} + +int RelationalSyncAbleStorage::StartTransactionForAsyncDownload(TransactType type) +{ + if (storageEngine_ == nullptr) { + return -E_INVALID_DB; + } + std::unique_lock lock(asyncDownloadtransactionMutex_); + if (asyncDownloadTransactionHandle_ != nullptr) { + LOGD("async download transaction started already."); + return -E_TRANSACT_STATE; + } + int errCode = E_OK; + auto *handle = static_cast( + storageEngine_->FindExecutor(type == TransactType::IMMEDIATE, OperatePerm::NORMAL_PERM, errCode)); + if (handle == nullptr) { + ReleaseHandle(handle); + return errCode; + } + errCode = handle->StartTransaction(type); + if (errCode != E_OK) { + ReleaseHandle(handle); + return errCode; + } + asyncDownloadTransactionHandle_ = handle; + return errCode; +} + +int RelationalSyncAbleStorage::GetCloudTableWithoutShared(std::vector &tables) +{ + const auto tableInfos = GetSchemaInfo().GetTables(); + for (const auto &[tableName, info] : tableInfos) { + if (info.GetSharedTableMark()) { + continue; + } + TableSchema schema; + int errCode = GetCloudTableSchema(tableName, schema); + if (errCode == -E_NOT_FOUND) { + continue; + } + if (errCode != E_OK) { + LOGW("[RDBStorage] Get cloud table failed %d", errCode); + return errCode; + } + tables.push_back(schema); + } + return E_OK; +} + +int RelationalSyncAbleStorage::GetCompensatedSyncQueryInner(SQLiteSingleVerRelationalStorageExecutor *handle, + const std::vector &tables, std::vector &syncQuery, bool isQueryDownloadRecords) +{ + int errCode = E_OK; + errCode = handle->StartTransaction(TransactType::IMMEDIATE); + if (errCode != E_OK) { + return errCode; + } + for (const auto &table : tables) { + if (!CheckTableSupportCompensatedSync(table)) { + continue; + } + + std::vector syncDataPk; + errCode = handle->GetWaitCompensatedSyncDataPk(table, syncDataPk, isQueryDownloadRecords); + if (errCode != E_OK) { + LOGW("[RDBStorageEngine] Get wait compensated sync data failed, continue! errCode=%d", errCode); + errCode = E_OK; + continue; + } + if (syncDataPk.empty()) { + // no data need to compensated sync + continue; + } + errCode = CloudStorageUtils::GetSyncQueryByPk(table.name, syncDataPk, false, syncQuery); + if (errCode != E_OK) { + LOGW("[RDBStorageEngine] Get compensated sync query happen error, ignore it! errCode = %d", errCode); + errCode = E_OK; + continue; + } + } + if (errCode == E_OK) { + errCode = handle->Commit(); + if (errCode != E_OK) { + LOGE("[RDBStorageEngine] commit failed %d when get compensated sync query", errCode); + } + } else { + int ret = handle->Rollback(); + if (ret != E_OK) { + LOGW("[RDBStorageEngine] rollback failed %d when get compensated sync query", ret); + } + } + return errCode; +} + +int RelationalSyncAbleStorage::CreateTempSyncTriggerInner(SQLiteSingleVerRelationalStorageExecutor *handle, + const std::string &tableName, bool flag) +{ + TrackerTable trackerTable = storageEngine_->GetTrackerSchema().GetTrackerTable(tableName); + if (trackerTable.IsEmpty()) { + trackerTable.SetTableName(tableName); + } + return handle->CreateTempSyncTrigger(trackerTable, flag); +} + +bool RelationalSyncAbleStorage::CheckTableSupportCompensatedSync(const TableSchema &table) +{ + auto it = std::find_if(table.fields.begin(), table.fields.end(), [](const auto &field) { + return field.primary && (field.type == TYPE_INDEX || field.type == TYPE_INDEX || + field.type == TYPE_INDEX); + }); + if (it != table.fields.end()) { + LOGI("[RDBStorageEngine] Table contain not support pk field type, ignored"); + return false; + } + // check whether reference exist + std::map> tableReference; + int errCode = RelationalSyncAbleStorage::GetTableReference(table.name, tableReference); + if (errCode != E_OK) { + LOGW("[RDBStorageEngine] Get table reference failed! errCode = %d", errCode); + return false; + } + if (!tableReference.empty()) { + LOGI("[RDBStorageEngine] current table exist reference property"); + return false; + } + return true; +} + +int RelationalSyncAbleStorage::MarkFlagAsConsistent(const std::string &tableName, const DownloadData &downloadData, + const std::set &gidFilters) +{ + if (transactionHandle_ == nullptr) { + LOGE("the transaction has not been started"); + return -E_INVALID_DB; + } + int errCode = transactionHandle_->MarkFlagAsConsistent(tableName, downloadData, gidFilters); + if (errCode != E_OK) { + LOGE("[RelationalSyncAbleStorage] mark flag as consistent failed.%d", errCode); + } + return errCode; +} + +CloudSyncConfig RelationalSyncAbleStorage::GetCloudSyncConfig() const +{ + std::lock_guard autoLock(configMutex_); + return cloudSyncConfig_; +} + +void RelationalSyncAbleStorage::SetCloudSyncConfig(const CloudSyncConfig &config) +{ + std::lock_guard autoLock(configMutex_); + cloudSyncConfig_ = config; + LOGI("[RelationalSyncAbleStorage] SetCloudSyncConfig value:[%" PRId32 ", %" PRId32 ", %" PRId32 ", %d]", + cloudSyncConfig_.maxUploadCount, cloudSyncConfig_.maxUploadSize, + cloudSyncConfig_.maxRetryConflictTimes, cloudSyncConfig_.isSupportEncrypt); +} + +bool RelationalSyncAbleStorage::IsTableExistReference(const std::string &table) +{ + // check whether reference exist + std::map> tableReference; + int errCode = RelationalSyncAbleStorage::GetTableReference(table, tableReference); + if (errCode != E_OK) { + LOGW("[RDBStorageEngine] Get table reference failed! errCode = %d", errCode); + return false; + } + return !tableReference.empty(); +} + +bool RelationalSyncAbleStorage::IsTableExistReferenceOrReferenceBy(const std::string &table) +{ + // check whether reference or reference by exist + if (storageEngine_ == nullptr) { + LOGE("[IsTableExistReferenceOrReferenceBy] storage is null when get reference gid"); + return false; + } + RelationalSchemaObject schema = storageEngine_->GetSchema(); + auto referenceProperty = schema.GetReferenceProperty(); + if (referenceProperty.empty()) { + return false; + } + auto [sourceTableName, errCode] = GetSourceTableName(table); + if (errCode != E_OK) { + return false; + } + for (const auto &property : referenceProperty) { + if (DBCommon::CaseInsensitiveCompare(property.sourceTableName, sourceTableName) || + DBCommon::CaseInsensitiveCompare(property.targetTableName, sourceTableName)) { + return true; + } + } + return false; +} + +void RelationalSyncAbleStorage::ReleaseUploadRecord(const std::string &tableName, const CloudWaterType &type, + Timestamp localMark) +{ + uploadRecorder_.ReleaseUploadRecord(tableName, type, localMark); +} + +int RelationalSyncAbleStorage::ReviseLocalModTime(const std::string &tableName, + const std::vector &revisedData) +{ + if (storageEngine_ == nullptr) { + LOGE("[ReviseLocalModTime] Storage is null"); + return -E_INVALID_DB; + } + int errCode = E_OK; + auto writeHandle = static_cast( + storageEngine_->FindExecutor(true, OperatePerm::NORMAL_PERM, errCode)); + if (writeHandle == nullptr) { + LOGE("[ReviseLocalModTime] Get write handle fail: %d", errCode); + return errCode; + } + errCode = writeHandle->StartTransaction(TransactType::IMMEDIATE); + if (errCode != E_OK) { + LOGE("[ReviseLocalModTime] Start Transaction fail: %d", errCode); + ReleaseHandle(writeHandle); + return errCode; + } + errCode = writeHandle->ReviseLocalModTime(tableName, revisedData); + if (errCode != E_OK) { + LOGE("[ReviseLocalModTime] Revise local modify time fail: %d", errCode); + writeHandle->Rollback(); + ReleaseHandle(writeHandle); + return errCode; + } + errCode = writeHandle->Commit(); + ReleaseHandle(writeHandle); + return errCode; +} + +int RelationalSyncAbleStorage::GetCursor(const std::string &tableName, uint64_t &cursor) +{ + if (transactionHandle_ == nullptr) { + LOGE("[RelationalSyncAbleStorage] the transaction has not been started"); + return -E_INVALID_DB; + } + return transactionHandle_->GetCursor(tableName, cursor); +} + +int RelationalSyncAbleStorage::GetLocalDataCount(const std::string &tableName, int &dataCount, + int &logicDeleteDataCount) +{ + int errCode = E_OK; + auto *handle = GetHandle(false, errCode); + if (handle == nullptr || errCode != E_OK) { + LOGE("[RelationalSyncAbleStorage] Get handle failed when get local data count: %d", errCode); + return errCode; + } + errCode = handle->GetLocalDataCount(tableName, dataCount, logicDeleteDataCount); + ReleaseHandle(handle); + return errCode; +} + +int RelationalSyncAbleStorage::GetCompressionOption(bool &needCompressOnSync, uint8_t &compressionRate) const +{ + needCompressOnSync = storageEngine_->GetRelationalProperties().GetBoolProp(DBProperties::COMPRESS_ON_SYNC, false); + compressionRate = storageEngine_->GetRelationalProperties().GetIntProp(DBProperties::COMPRESSION_RATE, + DBConstant::DEFAULT_COMPTRESS_RATE); + return E_OK; +} } #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store.cpp index b19356bf..0ef50e29 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store.cpp @@ -52,7 +52,7 @@ int SingleVerNaturalStore::RemoveKvDB(const KvDBProperties &properties) std::string storeDir; GenericKvDB::GetStoreDirectory(properties, KvDBProperties::SINGLE_VER_TYPE_SQLITE, storeDir, storeOnlyDir); - const std::vector> dbDir { + const std::vector> dbDir { { DBConstant::MAINDB_DIR, DBConstant::SINGLE_VER_DATA_STORE }, { DBConstant::METADB_DIR, DBConstant::SINGLE_VER_META_STORE }, { DBConstant::CACHEDB_DIR, DBConstant::SINGLE_VER_CACHE_STORE } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/collaboration_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/collaboration_log_table_manager.cpp index fdb5cab8..9176bf6c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/collaboration_log_table_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/collaboration_log_table_manager.cpp @@ -127,8 +127,9 @@ std::string CollaborationLogTableManager::GetPrimaryKeySql(const TableInfo &tabl void CollaborationLogTableManager::GetIndexSql(const TableInfo &table, std::vector &schema) { SqliteLogTableManager::GetIndexSql(table, schema); - std::string dataKeyIndex = "CREATE INDEX IF NOT EXISTS " + std::string(DBConstant::RELATIONAL_PREFIX) + - "datakey_index ON " + GetLogTableName(table) + "(data_key);"; + const std::string tableName = GetLogTableName(table); + std::string dataKeyIndex = "CREATE INDEX IF NOT EXISTS " + + tableName + "_datakey_index ON " + tableName + "(data_key);"; schema.emplace_back(dataKeyIndex); } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/log_table_manager_factory.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/log_table_manager_factory.cpp index a6f613f1..6967950a 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/log_table_manager_factory.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/log_table_manager_factory.cpp @@ -16,19 +16,22 @@ #include "log_table_manager_factory.h" #include "cloud_sync_log_table_manager.h" #include "collaboration_log_table_manager.h" +#include "device_tracker_log_table_manager.h" #include "split_device_log_table_manager.h" namespace DistributedDB { -std::unique_ptr LogTableManagerFactory::GetTableManager(DistributedTableMode mode, - TableSyncType syncType) +std::unique_ptr LogTableManagerFactory::GetTableManager(const TableInfo &tableInfo, + DistributedTableMode mode, TableSyncType syncType) { if (syncType == CLOUD_COOPERATION) { return std::make_unique(); - } else { - if (mode == DistributedTableMode::COLLABORATION) { - return std::make_unique(); - } + } + if (!tableInfo.GetTrackerTable().IsEmpty()) { + return std::make_unique(); + } + if (mode == DistributedTableMode::SPLIT_BY_DEVICE) { return std::make_unique(); } + return std::make_unique(); } } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/log_table_manager_factory.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/log_table_manager_factory.h index b31f9d50..623f7852 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/log_table_manager_factory.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/log_table_manager_factory.h @@ -24,7 +24,8 @@ namespace DistributedDB { class LogTableManagerFactory final { public: - static std::unique_ptr GetTableManager(DistributedTableMode mode, TableSyncType syncType); + static std::unique_ptr GetTableManager(const TableInfo &tableInfo, + DistributedTableMode mode, TableSyncType syncType); private: LogTableManagerFactory() {} diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.cpp index 66c55e4b..b53a3ef8 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.cpp @@ -76,7 +76,8 @@ std::string SimpleTrackerLogTableManager::GetInsertTrigger(const TableInfo &tabl insertTrigger += CalcPrimaryKeyHash("NEW.", table, identity) + ", '', "; insertTrigger += table.GetTrackerTable().GetAssignValSql(); insertTrigger += ", " + CloudStorageUtils::GetSelectIncCursorSql(tableName) + ", '', '', 0);\n"; - insertTrigger += "SELECT client_observer('" + tableName + "', NEW._rowid_, 0, 1"; + insertTrigger += "SELECT client_observer('" + tableName + "', NEW._rowid_, 0, "; + insertTrigger += table.GetTrackerTable().GetOnChangeType(); insertTrigger += ");\n"; insertTrigger += "END;"; return insertTrigger; @@ -103,7 +104,8 @@ std::string SimpleTrackerLogTableManager::GetUpdateTrigger(const TableInfo &tabl updateTrigger += table.GetTrackerTable().GetExtendAssignValSql(); updateTrigger += table.GetTrackerTable().GetDiffIncCursorSql(tableName); updateTrigger += " WHERE data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";\n"; - updateTrigger += "SELECT client_observer('" + tableName + "', OLD." + std::string(DBConstant::SQLITE_INNER_ROWID); + updateTrigger += "SELECT client_observer('" + tableName + "', OLD." + + std::string(DBConstant::SQLITE_INNER_ROWID); updateTrigger += ", 1, "; updateTrigger += table.GetTrackerTable().GetDiffTrackerValSql(); updateTrigger += ");"; @@ -131,7 +133,7 @@ std::string SimpleTrackerLogTableManager::GetDeleteTrigger(const TableInfo &tabl deleteTrigger += " WHERE data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";"; // -1 is rowid when data is deleted, 2 means change type is delete(ClientChangeType) deleteTrigger += "SELECT client_observer('" + tableName + "', -1, 2, "; - deleteTrigger += table.GetTrackerTable().IsEmpty() ? "0" : "1"; + deleteTrigger += table.GetTrackerTable().IsEmpty() ? "0" : table.GetTrackerTable().GetOnChangeType(); deleteTrigger += ");\n"; deleteTrigger += "END;"; return deleteTrigger; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.h index 4460a866..58626799 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.h @@ -27,7 +27,6 @@ public: // The parameter "references" is "", "NEW." or "OLD.". "identity" is a hash string that identifies a device. std::string CalcPrimaryKeyHash(const std::string &references, const TableInfo &table, const std::string &identity) override; - private: void GetIndexSql(const TableInfo &table, std::vector &schema) override; std::string GetPrimaryKeySql(const TableInfo &table) override; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp index 9c25c59b..5f6d1d8d 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp @@ -128,7 +128,7 @@ int SqliteRelationalDatabaseUpgrader::UpgradeTrigger(const std::string &logTable TableInfo tableInfo = table.second; tableInfo.SetTrackerTable(trackerSchemaObj.GetTrackerTable(table.first)); tableInfo.SetDistributedTable(schemaObj.GetDistributedTable(table.first)); - auto manager = LogTableManagerFactory::GetTableManager(mode, tableInfo.GetTableSyncType()); + auto manager = LogTableManagerFactory::GetTableManager(tableInfo, mode, tableInfo.GetTableSyncType()); errCode = manager->AddRelationalLogTableTrigger(db_, tableInfo, ""); if (errCode != E_OK) { LOGE("[Relational][Upgrade] recreate distributed trigger failed. err:%d", errCode); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp index 5f5c320f..070deaf8 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp @@ -22,6 +22,7 @@ #include "db_errno.h" #include "log_print.h" #include "db_types.h" +#include "res_finalizer.h" #include "sqlite_log_table_manager.h" #include "sqlite_relational_utils.h" #include "sqlite_relational_store_connection.h" @@ -224,7 +225,8 @@ int SQLiteRelationalStore::SaveTableModeToMeta(DistributedTableMode mode) int SQLiteRelationalStore::SaveLogTableVersionToMeta() { LOGD("save log table version to meta table, version: %s", DBConstant::LOG_TABLE_VERSION_CURRENT); - const Key logVersionKey(DBConstant::LOG_TABLE_VERSION_KEY.begin(), DBConstant::LOG_TABLE_VERSION_KEY.end()); + const Key logVersionKey(DBConstant::LOG_TABLE_VERSION_KEY, + DBConstant::LOG_TABLE_VERSION_KEY + strlen(DBConstant::LOG_TABLE_VERSION_KEY)); Value logVersion; int errCode = storageEngine_->GetMetaData(logVersionKey, logVersion); if (errCode != E_OK && errCode != -E_NOT_FOUND) { @@ -256,7 +258,7 @@ int SQLiteRelationalStore::CleanDistributedDeviceTable() std::string deviceHash; std::string tableName; DBCommon::GetDeviceFromName(deviceTableName, deviceHash, tableName); - syncAbleEngine_->EraseDeviceWaterMark(deviceHash, false, tableName); + errCode = syncAbleEngine_->EraseDeviceWaterMark(deviceHash, false, tableName); if (errCode != E_OK) { LOGE("Erase water mark failed:%d", errCode); return errCode; @@ -359,7 +361,7 @@ void SQLiteRelationalStore::ReleaseHandle(SQLiteSingleVerRelationalStorageExecut } } -int SQLiteRelationalStore::Sync(const ISyncer::SyncParma &syncParam, uint64_t connectionId) +int SQLiteRelationalStore::Sync(const ISyncer::SyncParam &syncParam, uint64_t connectionId) { return syncAbleEngine_->Sync(syncParam, connectionId); } @@ -448,7 +450,7 @@ int SQLiteRelationalStore::CreateDistributedTable(const std::string &tableName, } } - auto mode = sqliteStorageEngine_->GetProperties().GetDistributedTableMode(); + auto mode = sqliteStorageEngine_->GetRelationalProperties().GetDistributedTableMode(); std::string localIdentity; // collaboration mode need local identify if (mode == DistributedTableMode::COLLABORATION) { int errCode = syncAbleEngine_->GetLocalIdentity(localIdentity); @@ -461,6 +463,8 @@ int SQLiteRelationalStore::CreateDistributedTable(const std::string &tableName, schemaChanged, syncType, trackerSchemaChanged); if (errCode != E_OK) { LOGE("Create distributed table failed. %d", errCode); + } else { + CleanDirtyLogIfNeed(tableName); } if (schemaChanged) { LOGD("Notify schema changed."); @@ -549,7 +553,7 @@ int SQLiteRelationalStore::ClearCloudWatermark(const std::set &tabl int SQLiteRelationalStore::RemoveDeviceData() { - auto mode = static_cast(sqliteStorageEngine_->GetProperties().GetIntProp( + auto mode = static_cast(sqliteStorageEngine_->GetRelationalProperties().GetIntProp( RelationalDBProperties::DISTRIBUTED_TABLE_MODE, static_cast(DistributedTableMode::SPLIT_BY_DEVICE))); if (mode == DistributedTableMode::COLLABORATION) { LOGE("Not support remove all device data in collaboration mode."); @@ -600,7 +604,7 @@ int SQLiteRelationalStore::RemoveDeviceData() int SQLiteRelationalStore::RemoveDeviceData(const std::string &device, const std::string &tableName) { - auto mode = static_cast(sqliteStorageEngine_->GetProperties().GetIntProp( + auto mode = static_cast(sqliteStorageEngine_->GetRelationalProperties().GetIntProp( RelationalDBProperties::DISTRIBUTED_TABLE_MODE, static_cast(DistributedTableMode::SPLIT_BY_DEVICE))); if (mode == DistributedTableMode::COLLABORATION) { LOGE("Not support remove device data in collaboration mode."); @@ -684,13 +688,15 @@ int SQLiteRelationalStore::StartLifeCycleTimer(const DatabaseLifeCycleNotifier & if (lifeCycleNotifier_) { // normal identifier mode std::string identifier; - if (sqliteStorageEngine_->GetProperties().GetBoolProp(DBProperties::SYNC_DUAL_TUPLE_MODE, false)) { - identifier = sqliteStorageEngine_->GetProperties().GetStringProp( + if (sqliteStorageEngine_->GetRelationalProperties().GetBoolProp( + DBProperties::SYNC_DUAL_TUPLE_MODE, false)) { + identifier = sqliteStorageEngine_->GetRelationalProperties().GetStringProp( DBProperties::DUAL_TUPLE_IDENTIFIER_DATA, ""); } else { - identifier = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::IDENTIFIER_DATA, ""); + identifier = sqliteStorageEngine_->GetRelationalProperties().GetStringProp( + DBProperties::IDENTIFIER_DATA, ""); } - auto userId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::USER_ID, ""); + auto userId = sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::USER_ID, ""); lifeCycleNotifier_(identifier, userId); } return 0; @@ -766,12 +772,12 @@ int SQLiteRelationalStore::ResetLifeCycleTimer() std::string SQLiteRelationalStore::GetStorePath() const { - return sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::DATA_DIR, ""); + return sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::DATA_DIR, ""); } RelationalDBProperties SQLiteRelationalStore::GetProperties() const { - return sqliteStorageEngine_->GetProperties(); + return sqliteStorageEngine_->GetRelationalProperties(); } void SQLiteRelationalStore::StopSync(uint64_t connectionId) @@ -786,10 +792,10 @@ void SQLiteRelationalStore::Dump(int fd) std::string storeId = ""; std::string label = ""; if (sqliteStorageEngine_ != nullptr) { - userId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::USER_ID, ""); - appId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::APP_ID, ""); - storeId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, ""); - label = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::IDENTIFIER_DATA, ""); + userId = sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::USER_ID, ""); + appId = sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::APP_ID, ""); + storeId = sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::STORE_ID, ""); + label = sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::IDENTIFIER_DATA, ""); } label = DBCommon::TransferStringToHex(label); DBDumpHelper::Dump(fd, "\tdb userId = %s, appId = %s, storeId = %s, label = %s\n", userId.c_str(), appId.c_str(), @@ -851,9 +857,9 @@ int SQLiteRelationalStore::EraseAllDeviceWatermark(const std::vectorGetProperties().GetStringProp(DBProperties::USER_ID, ""), - sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::APP_ID, ""), - sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, "") }; + StoreInfo info = { sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::USER_ID, ""), + sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::APP_ID, ""), + sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::STORE_ID, "") }; if (RuntimeContext::GetInstance()->TranslateDeviceId(device, info, devTableName) != E_OK) { devTableName = hashDev; } @@ -1147,7 +1153,7 @@ int SQLiteRelationalStore::Sync(const CloudSyncOption &option, const SyncProcess LOGI("sync mode:%d, pri:%d, comp:%d", option.mode, option.priorityTask, option.compensatedSyncOnly); if (option.compensatedSyncOnly) { CloudSyncer::CloudTaskInfo info = CloudSyncUtils::InitCompensatedSyncTaskInfo(option, onProcess); - info.storeId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, ""); + info.storeId = sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::STORE_ID, ""); cloudSyncer_->GenerateCompensatedSync(info); return E_OK; } @@ -1192,7 +1198,9 @@ int SQLiteRelationalStore::CheckBeforeSync(const CloudSyncOption &option) if (errCode != E_OK && errCode != -E_NOT_SUPPORT) { return -E_SECURITY_OPTION_CHECK_ERROR; } - if (errCode == E_OK && securityOption.securityLabel == S4) { + CloudSyncConfig config = storageEngine_->GetCloudSyncConfig(); + if ((errCode == E_OK) && (securityOption.securityLabel == S4) && (!config.isSupportEncrypt)) { + LOGE("[RelationalStore] The current data does not support synchronization."); return -E_SECURITY_OPTION_CHECK_ERROR; } return E_OK; @@ -1340,7 +1348,7 @@ void SQLiteRelationalStore::FillSyncInfo(const CloudSyncOption &option, const Sy info.users.emplace_back(""); info.lockAction = option.lockAction; info.merge = option.merge; - info.storeId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, ""); + info.storeId = sqliteStorageEngine_->GetRelationalProperties().GetStringProp(DBProperties::STORE_ID, ""); info.prepareTraceId = option.prepareTraceId; info.asyncDownloadAssets = option.asyncDownloadAssets; } @@ -1359,8 +1367,14 @@ int SQLiteRelationalStore::SetTrackerTable(const TrackerSchema &trackerSchema) auto *handle = GetHandle(true, errCode); if (handle != nullptr) { handle->CheckAndCreateTrigger(tableInfo); + // Try clear historical mismatched log, which usually do not occur and apply to tracker table only. + if (isNoTableInSchema) { + handle->ClearLogOfMismatchedData(trackerSchema.tableName); + } + handle->RecoverNullExtendLog(trackerSchema, tableInfo.GetTrackerTable()); ReleaseHandle(handle); } + CleanDirtyLogIfNeed(trackerSchema.tableName); return E_OK; } errCode = sqliteStorageEngine_->UpdateExtendField(trackerSchema); @@ -1370,7 +1384,11 @@ int SQLiteRelationalStore::SetTrackerTable(const TrackerSchema &trackerSchema) return errCode; } if (isNoTableInSchema) { - return sqliteStorageEngine_->SetTrackerTable(trackerSchema, tableInfo, isFirstCreate); + errCode = sqliteStorageEngine_->SetTrackerTable(trackerSchema, tableInfo, isFirstCreate); + if (errCode == E_OK) { + CleanDirtyLogIfNeed(trackerSchema.tableName); + } + return errCode; } sqliteStorageEngine_->CacheTrackerSchema(trackerSchema); errCode = CreateDistributedTable(trackerSchema.tableName, tableInfo.GetTableSyncType(), true); @@ -1385,22 +1403,27 @@ int SQLiteRelationalStore::SetTrackerTable(const TrackerSchema &trackerSchema) int SQLiteRelationalStore::CheckTrackerTable(const TrackerSchema &trackerSchema, TableInfo &table, bool &isNoTableInSchema, bool &isFirstCreate) { - const RelationalSchemaObject &tracker = sqliteStorageEngine_->GetTrackerSchema(); + const RelationalSchemaObject tracker = sqliteStorageEngine_->GetTrackerSchema(); isFirstCreate = tracker.GetTrackerTable(trackerSchema.tableName).GetTableName().empty(); RelationalSchemaObject localSchema = sqliteStorageEngine_->GetSchema(); table = localSchema.GetTable(trackerSchema.tableName); TrackerTable trackerTable; trackerTable.Init(trackerSchema); int errCode = E_OK; + auto *handle = GetHandle(true, errCode); + if (handle == nullptr) { + return errCode; + } + ResFinalizer finalizer([this, handle]() { + SQLiteSingleVerRelationalStorageExecutor *releaseHandle = handle; + ReleaseHandle(releaseHandle); + }); + bool isOnceDrop = false; + (void)handle->IsTableOnceDropped(trackerSchema.tableName, isOnceDrop); if (table.Empty()) { isNoTableInSchema = true; table.SetTableSyncType(TableSyncType::CLOUD_COOPERATION); - auto *handle = GetHandle(true, errCode); - if (handle == nullptr) { - return errCode; - } errCode = handle->AnalysisTrackerTable(trackerTable, table); - ReleaseHandle(handle); if (errCode != E_OK) { LOGE("[CheckTrackerTable] analysis table schema failed %d.", errCode); return errCode; @@ -1413,7 +1436,8 @@ int SQLiteRelationalStore::CheckTrackerTable(const TrackerSchema &trackerSchema, return errCode; } } - if (!trackerSchema.isForceUpgrade && !tracker.GetTrackerTable(trackerSchema.tableName).IsChanging(trackerSchema)) { + if (!trackerSchema.isForceUpgrade && !tracker.GetTrackerTable(trackerSchema.tableName).IsChanging(trackerSchema) + && !isOnceDrop) { LOGW("[CheckTrackerTable] tracker schema is no change, table[%s [%zu]]", DBCommon::StringMiddleMasking(trackerSchema.tableName).c_str(), trackerSchema.tableName.size()); return -E_IGNORE_DATA; @@ -1430,8 +1454,8 @@ int SQLiteRelationalStore::ExecuteSql(const SqlCondition &condition, std::vector return sqliteStorageEngine_->ExecuteSql(condition, records); } -int SQLiteRelationalStore::CleanWaterMark(SQLiteSingleVerRelationalStorageExecutor *&handle, - std::set &clearWaterMarkTable) +int SQLiteRelationalStore::CleanWaterMarkInner(SQLiteSingleVerRelationalStorageExecutor *&handle, + const std::set &clearWaterMarkTable) { int errCode = E_OK; for (const auto &tableName : clearWaterMarkTable) { @@ -1462,7 +1486,29 @@ int SQLiteRelationalStore::CleanWaterMark(SQLiteSingleVerRelationalStorageExecut return errCode; } -int SQLiteRelationalStore::SetReference(const std::vector &tableReferenceProperty) +std::function SQLiteRelationalStore::CleanWaterMark(const std::set clearWaterMarkTables) +{ + return [this, clearWaterMarkTables]()->int { + int errCode = E_OK; + auto *handle = GetHandle(true, errCode); + if (handle == nullptr) { + LOGE("[SQLiteRelationalStore] get handle failed:%d", errCode); + return errCode; + } + storageEngine_->SetReusedHandle(handle); + errCode = CleanWaterMarkInner(handle, clearWaterMarkTables); + storageEngine_->SetReusedHandle(nullptr); + ReleaseHandle(handle); + if (errCode != E_OK) { + LOGE("[SQLiteRelationalStore] SetReference clear water mark failed, errCode = %d", errCode); + } + LOGI("[SQLiteRelationalStore] SetReference clear water mark success"); + return errCode; + }; +} + +int SQLiteRelationalStore::SetReferenceInner(const std::vector &tableReferenceProperty, + std::set &clearWaterMarkTables) { SQLiteSingleVerRelationalStorageExecutor *handle = nullptr; int errCode = GetHandleAndStartTransaction(handle); @@ -1470,7 +1516,6 @@ int SQLiteRelationalStore::SetReference(const std::vector clearWaterMarkTables; RelationalSchemaObject schema; errCode = sqliteStorageEngine_->SetReference(tableReferenceProperty, handle, clearWaterMarkTables, schema); if (errCode != E_OK && errCode != -E_TABLE_REFERENCE_CHANGED) { @@ -1480,20 +1525,6 @@ int SQLiteRelationalStore::SetReference(const std::vectorSetReusedHandle(handle); - int ret = CleanWaterMark(handle, clearWaterMarkTables); - if (ret != E_OK) { - LOGE("[SQLiteRelationalStore] SetReference failed, errCode = %d", ret); - storageEngine_->SetReusedHandle(nullptr); - (void)handle->Rollback(); - ReleaseHandle(handle); - return ret; - } - storageEngine_->SetReusedHandle(nullptr); - LOGI("[SQLiteRelationalStore] SetReference clear water mark success"); - } - int ret = handle->Commit(); ReleaseHandle(handle); if (ret == E_OK) { @@ -1504,6 +1535,28 @@ int SQLiteRelationalStore::SetReference(const std::vector &tableReferenceProperty) +{ + std::set clearWaterMarkTables; + int errCode = SetReferenceInner(tableReferenceProperty, clearWaterMarkTables); + if (errCode != E_OK && errCode != -E_TABLE_REFERENCE_CHANGED) { + LOGE("[SQLiteRelationalStore] SetReference failed, errCode = %d", errCode); + return errCode; + } + std::function clearWaterMarkFunc = [] { return E_OK; }; + if (!clearWaterMarkTables.empty()) { + clearWaterMarkFunc = CleanWaterMark(clearWaterMarkTables); + } + if (errCode == -E_TABLE_REFERENCE_CHANGED) { + int ret = E_OK; +#ifdef USE_DISTRIBUTEDDB_CLOUD + ret = cloudSyncer_->StopSyncTask(clearWaterMarkFunc); +#endif + return ret != E_OK ? ret : errCode; + } + return E_OK; +} + int SQLiteRelationalStore::InitTrackerSchemaFromMeta() { int errCode = sqliteStorageEngine_->GetOrInitTrackerSchemaFromMeta(); @@ -1730,6 +1783,8 @@ int SQLiteRelationalStore::SetCloudSyncConfig(const CloudSyncConfig &config) return -E_INVALID_DB; } storageEngine_->SetCloudSyncConfig(config); + LOGI("[RelationalStore][SetCloudSyncConfig] value:[%" PRId32 ", %" PRId32 ", %" PRId32 ", %d]", + config.maxUploadCount, config.maxUploadSize, config.maxRetryConflictTimes, config.isSupportEncrypt); return E_OK; } @@ -1739,13 +1794,13 @@ SyncProcess SQLiteRelationalStore::GetCloudTaskStatus(uint64_t taskId) } #endif -int SQLiteRelationalStore::SetDistributedSchema(const DistributedSchema &schema) +int SQLiteRelationalStore::SetDistributedSchema(const DistributedSchema &schema, bool isForceUpgrade) { if (sqliteStorageEngine_ == nullptr || storageEngine_ == nullptr) { LOGE("[RelationalStore] engine was not initialized"); return -E_INVALID_DB; } - auto mode = sqliteStorageEngine_->GetProperties().GetDistributedTableMode(); + auto mode = sqliteStorageEngine_->GetRelationalProperties().GetDistributedTableMode(); std::string localIdentity; // collaboration mode need local identify if (mode == DistributedTableMode::COLLABORATION) { int errCode = syncAbleEngine_->GetLocalIdentity(localIdentity); @@ -1753,7 +1808,7 @@ int SQLiteRelationalStore::SetDistributedSchema(const DistributedSchema &schema) LOGW("Get local identity failed: %d", errCode); } } - auto [errCode, isSchemaChange] = sqliteStorageEngine_->SetDistributedSchema(schema, localIdentity); + auto [errCode, isSchemaChange] = sqliteStorageEngine_->SetDistributedSchema(schema, localIdentity, isForceUpgrade); if (errCode != E_OK) { return errCode; } @@ -1801,7 +1856,7 @@ int SQLiteRelationalStore::SetTableMode(DistributedTableMode tableMode) LOGE("[RelationalStore][SetTableMode] sqliteStorageEngine was not initialized"); return -E_INVALID_DB; } - if (sqliteStorageEngine_->GetProperties().GetDistributedTableMode() != tableMode) { + if (sqliteStorageEngine_->GetRelationalProperties().GetDistributedTableMode() != tableMode) { auto schema = sqliteStorageEngine_->GetSchema(); for (const auto &tableMap : schema.GetTables()) { if (tableMap.second.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { @@ -1811,7 +1866,7 @@ int SQLiteRelationalStore::SetTableMode(DistributedTableMode tableMode) } } } - RelationalDBProperties properties = sqliteStorageEngine_->GetProperties(); + RelationalDBProperties properties = sqliteStorageEngine_->GetRelationalProperties(); properties.SetIntProp(RelationalDBProperties::DISTRIBUTED_TABLE_MODE, static_cast(tableMode)); sqliteStorageEngine_->SetProperties(properties); LOGI("[RelationalStore][SetTableMode] Set table mode to %d successful", static_cast(tableMode)); @@ -1828,6 +1883,11 @@ int SQLiteRelationalStore::OperateDataStatus(uint32_t dataOperator) LOGE("[RelationalStore] sqliteStorageEngine was not initialized when operate data status"); return -E_INVALID_DB; } + if (syncAbleEngine_ == nullptr) { + LOGE("[RelationalStore] syncAbleEngine was not initialized when operate data status"); + return -E_INVALID_DB; + } + auto virtualTime = syncAbleEngine_->GetTimestamp(); auto schema = sqliteStorageEngine_->GetSchema(); std::vector operateTables; for (const auto &tableMap : schema.GetTables()) { @@ -1835,10 +1895,10 @@ int SQLiteRelationalStore::OperateDataStatus(uint32_t dataOperator) operateTables.push_back(tableMap.second.GetTableName()); } } - return OperateDataStatusInner(operateTables); + return OperateDataStatusInner(operateTables, virtualTime); } -int SQLiteRelationalStore::OperateDataStatusInner(const std::vector &tables) const +int SQLiteRelationalStore::OperateDataStatusInner(const std::vector &tables, uint64_t virtualTime) const { int errCode = E_OK; SQLiteSingleVerRelationalStorageExecutor *handle = GetHandle(true, errCode); @@ -1860,7 +1920,7 @@ int SQLiteRelationalStore::OperateDataStatusInner(const std::vector ReleaseHandle(handle); return errCode; } - errCode = SQLiteRelationalUtils::OperateDataStatus(db, tables); + errCode = SQLiteRelationalUtils::OperateDataStatus(db, tables, virtualTime); if (errCode == E_OK) { errCode = handle->Commit(); if (errCode != E_OK) { @@ -1875,5 +1935,59 @@ int SQLiteRelationalStore::OperateDataStatusInner(const std::vector ReleaseHandle(handle); return errCode; } + +int32_t SQLiteRelationalStore::GetDeviceSyncTaskCount() const +{ + if (syncAbleEngine_ == nullptr) { + LOGW("[RelationalStore] syncAbleEngine was not initialized when get device sync task count"); + return 0; + } + return syncAbleEngine_->GetDeviceSyncTaskCount(); +} + +void SQLiteRelationalStore::CleanDirtyLogIfNeed(const std::string &tableName) const +{ + int errCode = E_OK; + SQLiteSingleVerRelationalStorageExecutor *handle = GetHandle(true, errCode); + if (handle == nullptr) { + LOGW("[RDBStore][ClearDirtyLog] Get handle failed %d", errCode); + return; + } + ResFinalizer finalizer([this, handle]() { + SQLiteSingleVerRelationalStorageExecutor *releaseHandle = handle; + ReleaseHandle(releaseHandle); + }); + sqlite3 *db = nullptr; + errCode = handle->GetDbHandle(db); + if (errCode != E_OK) { + LOGW("[RDBStore][ClearDirtyLog] Get db handle failed %d", errCode); + return; + } + bool isExistDirtyLog = false; + std::tie(errCode, isExistDirtyLog) = SQLiteRelationalUtils::CheckExistDirtyLog(db, tableName); + if (errCode != E_OK) { + LOGW("[RDBStore][ClearDirtyLog] Check dirty log failed %d", errCode); + return; + } + if (!isExistDirtyLog) { + return; + } + auto obj = GetSchemaObj(); + if (!obj.IsSchemaValid()) { + return; + } + errCode = SQLiteRelationalUtils::CleanDirtyLog(db, tableName, obj); + if (errCode != E_OK) { + LOGW("[RDBStore][ClearDirtyLog] Clean dirty log failed %d", errCode); + } +} + +RelationalSchemaObject SQLiteRelationalStore::GetSchemaObj() const +{ + if (storageEngine_ == nullptr) { + return {}; + } + return storageEngine_->GetSchemaInfo(); +} } // namespace DistributedDB #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h index 95fd3a85..f4ac621d 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h @@ -46,7 +46,7 @@ public: SQLiteSingleVerRelationalStorageExecutor *GetHandle(bool isWrite, int &errCode) const; void ReleaseHandle(SQLiteSingleVerRelationalStorageExecutor *&handle) const; - int Sync(const ISyncer::SyncParma &syncParam, uint64_t connectionId); + int Sync(const ISyncer::SyncParam &syncParam, uint64_t connectionId); void ReleaseDBConnection(uint64_t connectionId, RelationalStoreConnection *connection); @@ -91,11 +91,13 @@ public: int SetReference(const std::vector &tableReferenceProperty); + std::function CleanWaterMark(const std::set clearWaterMarkTables); + int Pragma(PragmaCmd cmd, PragmaData &pragmaData); int UpsertData(RecordStatus status, const std::string &tableName, const std::vector &records); - int SetDistributedSchema(const DistributedSchema &schema); + int SetDistributedSchema(const DistributedSchema &schema, bool isForceUpgrade); int GetDownloadingAssetsCount(int32_t &count); @@ -120,7 +122,9 @@ public: #endif int OperateDataStatus(uint32_t dataOperator); -private: + + int32_t GetDeviceSyncTaskCount() const; +protected: void ReleaseResources(); // 1 store 1 connection @@ -166,7 +170,8 @@ private: int CheckTableName(const std::vector &tableNames); - int CleanWaterMark(SQLiteSingleVerRelationalStorageExecutor *&handle, std::set &clearWaterMarkTable); + int CleanWaterMarkInner(SQLiteSingleVerRelationalStorageExecutor *&handle, + const std::set &clearWaterMarkTable); int InitTrackerSchemaFromMeta(); @@ -192,6 +197,9 @@ private: int CheckTrackerTable(const TrackerSchema &trackerSchema, TableInfo &table, bool &isNoTableInSchema, bool &isFirstCreate); + int SetReferenceInner(const std::vector &tableReferenceProperty, + std::set &clearWaterMarkTables); + #ifdef USE_DISTRIBUTEDDB_CLOUD void FillSyncInfo(const CloudSyncOption &option, const SyncProcessCallback &onProcess, CloudSyncer::CloudTaskInfo &info); @@ -199,7 +207,11 @@ private: int CheckCloudSchema(const DataBaseSchema &schema); #endif - int OperateDataStatusInner(const std::vector &tables) const; + int OperateDataStatusInner(const std::vector &tables, uint64_t virtualTime) const; + + void CleanDirtyLogIfNeed(const std::string &tableName) const; + + RelationalSchemaObject GetSchemaObj() const; // use for sync Interactive std::shared_ptr syncAbleEngine_ = nullptr; // For storage operate sync function // use ref obj same as kv diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp index 774fe957..48d4e797 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp @@ -254,7 +254,7 @@ int SQLiteRelationalStoreConnection::SyncToDevice(SyncInfo &info) return -E_INVALID_CONNECTION; } - ISyncer::SyncParma syncParam; + ISyncer::SyncParam syncParam; syncParam.devices = info.devices; syncParam.mode = info.mode; syncParam.wait = info.wait; @@ -486,14 +486,14 @@ SyncProcess SQLiteRelationalStoreConnection::GetCloudTaskStatus(uint64_t taskId) } #endif -int SQLiteRelationalStoreConnection::SetDistributedDbSchema(const DistributedSchema &schema) +int SQLiteRelationalStoreConnection::SetDistributedDbSchema(const DistributedSchema &schema, bool isForceUpgrade) { auto *store = GetDB(); if (store == nullptr) { LOGE("[RelationalConnection] store is null when set distributed schema"); return -E_INVALID_CONNECTION; } - return store->SetDistributedSchema(SQLiteRelationalUtils::FilterRepeatDefine(schema)); + return store->SetDistributedSchema(SQLiteRelationalUtils::FilterRepeatDefine(schema), isForceUpgrade); } int SQLiteRelationalStoreConnection::GetDownloadingAssetsCount(int32_t &count) @@ -525,5 +525,15 @@ int SQLiteRelationalStoreConnection::OperateDataStatus(uint32_t dataOperator) } return store->OperateDataStatus(dataOperator); } + +int32_t SQLiteRelationalStoreConnection::GetDeviceSyncTaskCount() +{ + auto *store = GetDB(); + if (store == nullptr) { + LOGE("[RelationalConnection] store is null when get device sync task count."); + return 0; + } + return store->GetDeviceSyncTaskCount(); +} } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h index 70dcf9d4..10dc6cba 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h @@ -58,7 +58,7 @@ public: int UpsertData(RecordStatus status, const std::string &tableName, const std::vector &records) override; - int SetDistributedDbSchema(const DistributedSchema &schema) override; + int SetDistributedDbSchema(const DistributedSchema &schema, bool isForceUpgrade) override; int GetDownloadingAssetsCount(int32_t &count) override; @@ -84,6 +84,8 @@ public: #endif int OperateDataStatus(uint32_t dataOperator) override; + + int32_t GetDeviceSyncTaskCount() override; protected: int Pragma(int cmd, void *parameter) override; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp index 74df0413..487ae2f0 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp @@ -283,8 +283,8 @@ int SQLiteRelationalUtils::GetTypeValByStatement(sqlite3_stmt *stmt, int cid, Ty typeVal = static_cast(sqlite3_column_int64(stmt, cid)); break; } - if (strcasecmp(declType, SchemaConstant::KEYWORD_TYPE_BOOL.c_str()) == 0 || - strcasecmp(declType, SchemaConstant::KEYWORD_TYPE_BOOLEAN.c_str()) == 0) { // LCOV_EXCL_BR_LINE + if (strcasecmp(declType, SchemaConstant::KEYWORD_TYPE_BOOL) == 0 || + strcasecmp(declType, SchemaConstant::KEYWORD_TYPE_BOOLEAN) == 0) { // LCOV_EXCL_BR_LINE typeVal = static_cast(sqlite3_column_int(stmt, cid)); break; } @@ -395,21 +395,6 @@ void SQLiteRelationalUtils::AddUpgradeSqlToList(const TableInfo &tableInfo, } } -int SQLiteRelationalUtils::AnalysisTrackerTable(sqlite3 *db, const TrackerTable &trackerTable, TableInfo &tableInfo) -{ - int errCode = SQLiteUtils::AnalysisSchema(db, trackerTable.GetTableName(), tableInfo, true); - if (errCode != E_OK) { - LOGE("analysis table schema failed %d.", errCode); - return errCode; - } - tableInfo.SetTrackerTable(trackerTable); - errCode = tableInfo.CheckTrackerTable(); - if (errCode != E_OK) { - LOGE("check tracker table schema failed %d.", errCode); - } - return errCode; -} - int SQLiteRelationalUtils::QueryCount(sqlite3 *db, const std::string &tableName, int64_t &count) { std::string sql = "SELECT COUNT(1) FROM " + tableName ; @@ -473,10 +458,8 @@ void GetFieldsNeedContain(const TableInfo &tableInfo, const std::vector &requiredNotNullFields) { // should not decrease distributed field - for (const auto &syncField : syncFields) { - if (!tableInfo.IsPrimaryKey(syncField.GetFieldName())) { - fieldsNotDecrease.insert(syncField.GetFieldName()); - } + for (const auto &field : tableInfo.GetSyncField()) { + fieldsNotDecrease.insert(field); } const std::vector &uniqueDefines = tableInfo.GetUniqueDefine(); for (const auto &compositeFields : uniqueDefines) { @@ -528,12 +511,37 @@ bool IsMarkUniqueColumnInvalid(const TableInfo &tableInfo, const std::vector &distributedPk, const std::vector &originFields) +{ + if (distributedPk.empty()) { + return false; + } + auto uniqueAndPkDefine = tableInfo.GetUniqueAndPkDefine(); + if (IsMarkUniqueColumnInvalid(tableInfo, originFields)) { + LOGE("Mark more than one unique column specified in auto increment table: %s, tableName len: %zu", + DBCommon::StringMiddleMasking(tableInfo.GetTableName()).c_str(), tableInfo.GetTableName().length()); + return true; + } + auto find = std::any_of(uniqueAndPkDefine.begin(), uniqueAndPkDefine.end(), [&distributedPk](const auto &item) { + // unique index field count should be same + return item.size() == distributedPk.size() && distributedPk == DBCommon::TransformToCaseInsensitive(item); + }); + bool isMissMatch = !find; + if (isMissMatch) { + LOGE("Miss match distributed pk size %zu in auto increment table %s", distributedPk.size(), + DBCommon::StringMiddleMasking(tableInfo.GetTableName()).c_str()); + } + return isMissMatch; +} + +bool IsDistributedPkInvalid(const TableInfo &tableInfo, + const std::set &distributedPk, + const std::vector &originFields, bool isForceUpgrade) { auto lastDistributedPk = DBCommon::TransformToCaseInsensitive(tableInfo.GetSyncDistributedPk()); - if (!lastDistributedPk.empty() && distributedPk != lastDistributedPk) { + if (!isForceUpgrade && !lastDistributedPk.empty() && distributedPk != lastDistributedPk) { LOGE("distributed pk has change last %zu now %zu", lastDistributedPk.size(), distributedPk.size()); return true; } @@ -545,25 +553,7 @@ bool IsDistributedPkInvalid(const TableInfo &tableInfo, return true; } if (tableInfo.GetAutoIncrement()) { - if (distributedPk.empty()) { - return false; - } - auto uniqueAndPkDefine = tableInfo.GetUniqueAndPkDefine(); - if (IsMarkUniqueColumnInvalid(tableInfo, originFields)) { - LOGE("Mark more than one unique column specified in auto increment table: %s, tableName len: %zu", - DBCommon::StringMiddleMasking(tableInfo.GetTableName()).c_str(), tableInfo.GetTableName().length()); - return true; - } - auto find = std::any_of(uniqueAndPkDefine.begin(), uniqueAndPkDefine.end(), [&distributedPk](const auto &item) { - // unique index field count should be same - return item.size() == distributedPk.size() && distributedPk == DBCommon::TransformToCaseInsensitive(item); - }); - bool isMissMatch = !find; - if (isMissMatch) { - LOGE("Miss match distributed pk size %zu in auto increment table %s", distributedPk.size(), - DBCommon::StringMiddleMasking(tableInfo.GetTableName()).c_str()); - } - return isMissMatch; + return IsDistributedPKInvalidInAutoIncrementTable(tableInfo, distributedPk, originFields); } for (const auto &field : originFields) { bool isLocalPk = tableInfo.IsPrimaryKey(field.colName); @@ -603,7 +593,7 @@ bool IsDistributedSchemaSupport(const TableInfo &tableInfo, const std::vector &syncFields, - const std::vector &fields) + const std::vector &fields, bool isForceUpgrade) { if (fields.empty()) { LOGE("fields cannot be empty"); @@ -627,7 +617,7 @@ int CheckDistributedSchemaFields(const TableInfo &tableInfo, const std::vector fieldsNeedContain; @@ -642,7 +632,7 @@ int CheckDistributedSchemaFields(const TableInfo &tableInfo, const std::vector, CaseInsensitiveComparator> tableSchemaMap; - for (const auto &table : schema.tables) { - tableSchemaMap[table.tableName] = table.fields; - } - for (const auto &table : localSchema.tables) { - if (tableSchemaMap.find(table.tableName) == tableSchemaMap.end()) { - LOGE("[RDBUtils][CheckDistributedSchemaTables] table [%s [%zu]] missing", - DBCommon::StringMiddleMasking(table.tableName).c_str(), table.tableName.size()); - return -E_DISTRIBUTED_FIELD_DECREASE; - } - } - return E_OK; -} - int SQLiteRelationalUtils::CheckDistributedSchemaValid(const RelationalSchemaObject &schemaObj, - const DistributedSchema &schema, SQLiteSingleVerRelationalStorageExecutor *executor) + const DistributedSchema &schema, bool isForceUpgrade, SQLiteSingleVerRelationalStorageExecutor *executor) { if (executor == nullptr) { LOGE("[RDBUtils][CheckDistributedSchemaValid] executor is null"); @@ -687,11 +656,6 @@ int SQLiteRelationalUtils::CheckDistributedSchemaValid(const RelationalSchemaObj LOGE("[RDBUtils][CheckDistributedSchemaValid] sqlite handle failed %d", errCode); return errCode; } - errCode = CheckDistributedSchemaTables(schemaObj, schema); - if (errCode != E_OK) { - LOGE("[RDBUtils][CheckDistributedSchemaValid] Check tables fail %d", errCode); - return errCode; - } for (const auto &table : schema.tables) { if (table.tableName.empty()) { LOGE("[RDBUtils][CheckDistributedSchemaValid] Table name cannot be empty"); @@ -706,7 +670,7 @@ int SQLiteRelationalUtils::CheckDistributedSchemaValid(const RelationalSchemaObj } tableInfo.SetDistributedTable(schemaObj.GetDistributedTable(table.tableName)); errCode = CheckDistributedSchemaFields(tableInfo, schemaObj.GetSyncFieldInfo(table.tableName, false), - table.fields); + table.fields, isForceUpgrade); if (errCode != E_OK) { LOGE("[CheckDistributedSchema] Check fields of [%s [%zu]] fail", DBCommon::StringMiddleMasking(table.tableName).c_str(), table.tableName.size()); @@ -813,13 +777,11 @@ int SQLiteRelationalUtils::GetLogInfoPre(sqlite3_stmt *queryStmt, DistributedTab return errCode; } -int SQLiteRelationalUtils::OperateDataStatus(sqlite3 *db, const std::vector &tables) +int SQLiteRelationalUtils::OperateDataStatus(sqlite3 *db, const std::vector &tables, uint64_t virtualTime) { - auto [errCode, time] = GetCurrentVirtualTime(db); - if (errCode != E_OK) { - return errCode; - } + auto time = std::to_string(virtualTime); LOGI("[SQLiteRDBUtils] %zu tables wait for update time to %s", tables.size(), time.c_str()); + int errCode = E_OK; for (const auto &table : tables) { errCode = UpdateLocalDataModifyTime(db, table, time); if (errCode != E_OK) { @@ -859,43 +821,98 @@ int SQLiteRelationalUtils::UpdateLocalDataModifyTime(sqlite3 *db, const std::str return errCode; } -int SQLiteRelationalUtils::GetMetaLocalTimeOffset(sqlite3 *db, int64_t &timeOffset) +std::pair SQLiteRelationalUtils::CheckExistDirtyLog(sqlite3 *db, const std::string &oriTable) +{ + std::pair res; + auto &[errCode, isExist] = res; + if (db == nullptr) { + errCode = -E_INVALID_DB; + return res; + } + auto logTable = DBCommon::GetLogTableName(oriTable); + bool isCreate = false; + errCode = SQLiteUtils::CheckTableExists(db, logTable, isCreate); + if (!isCreate) { + return res; + } + std::string sql = "SELECT count(1) FROM (SELECT data_key FROM " + logTable + " " + "WHERE data_key != -1 GROUP BY data_key HAVING count(1) > 1)"; + return ExecuteCheckSql(db, sql); +} + +std::pair SQLiteRelationalUtils::ExecuteCheckSql(sqlite3 *db, const std::string &sql) +{ + bool isExist = false; + int errCode = ExecuteSql(db, sql, [&isExist](sqlite3_stmt *stmt) { + auto count = static_cast(sqlite3_column_int64(stmt, 0)); + if (count > 0) { + isExist = true; + LOGW("[SQLiteRDBUtils] Exist %" PRId64 " duplicate log", count); + } + }); + return {errCode, isExist}; +} + +int SQLiteRelationalUtils::ExecuteSql(sqlite3 *db, const std::string &sql, + const std::function &checkFunc) { - std::string sql = "SELECT value FROM " + DBCommon::GetMetaTableName() + " WHERE key=x'" + - DBCommon::TransferStringToHex(std::string(DBConstant::LOCALTIME_OFFSET_KEY)) + "';"; sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(db, sql, stmt); if (errCode != E_OK) { + LOGE("[SQLiteRDBUtils] Get check stmt failed %d", errCode); return errCode; } - int ret = E_OK; - errCode = SQLiteUtils::StepWithRetry(stmt); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - timeOffset = static_cast(sqlite3_column_int64(stmt, 0)); - if (timeOffset < 0) { - LOGE("[SQLiteRDBUtils] TimeOffset %" PRId64 "is invalid.", timeOffset); - SQLiteUtils::ResetStatement(stmt, true, ret); - return -E_INTERNAL_ERROR; + ResFinalizer finalizer([stmt]() { + int resetRet = E_OK; + sqlite3_stmt *releaseStmt = stmt; + SQLiteUtils::ResetStatement(releaseStmt, true, resetRet); + }); + errCode = SQLiteUtils::StepNext(stmt); + if (errCode == E_OK) { + if (checkFunc != nullptr) { + checkFunc(stmt); } + } else if (errCode == -E_FINISHED) { errCode = E_OK; } - SQLiteUtils::ResetStatement(stmt, true, ret); - return errCode != E_OK ? errCode : ret; + return errCode; } -std::pair SQLiteRelationalUtils::GetCurrentVirtualTime(sqlite3 *db) +int SQLiteRelationalUtils::CleanDirtyLog(sqlite3 *db, const std::string &oriTable, const RelationalSchemaObject &obj) { - int64_t localTimeOffset = 0; - std::pair res; - auto &[errCode, time] = res; - errCode = GetMetaLocalTimeOffset(db, localTimeOffset); - if (errCode != E_OK) { - LOGE("[SQLiteRDBUtils] Failed to get local timeOffset.%d", errCode); - return res; + TableInfo tableInfo; + tableInfo.SetDistributedTable(obj.GetDistributedTable(oriTable)); + auto distributedPk = tableInfo.GetSyncDistributedPk(); + if (distributedPk.empty()) { + return E_OK; } - Timestamp currentSysTime = TimeHelper::GetSysCurrentTime(); - Timestamp currentLocalTime = currentSysTime + static_cast(localTimeOffset); - time = std::to_string(currentLocalTime); - return res; + auto logTable = DBCommon::GetLogTableName(oriTable); + int errCode = E_OK; + std::string sql = "DELETE FROM " + logTable + " WHERE hash_key IN " + "(SELECT hash_key FROM (SELECT data_key, hash_key, extend_field FROM " + logTable + + " WHERE data_key IN(SELECT data_key FROM " + logTable + " GROUP BY data_key HAVING count(1)>1)" + " AND data_key != -1) AS log, '" + oriTable + + "' WHERE log.data_key = '" + oriTable + "'.rowid AND log.hash_key != " + + SqliteLogTableManager::CalcPkHash(oriTable + ".", distributedPk) + ")"; + errCode = ExecuteSql(db, sql, nullptr); + if (errCode == E_OK) { + LOGI("[SQLiteRDBUtils] Clean %d dirty hash log", sqlite3_changes(db)); + } + return errCode; +} + +int SQLiteRelationalUtils::ExecuteListAction(const std::vector> &actions) +{ + int errCode = E_OK; + for (const auto &action : actions) { + if (action == nullptr) { + continue; + } + errCode = action(); + if (errCode != E_OK) { + return errCode; + } + } + return errCode; } } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.h index 80d37b46..24f07674 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.h @@ -52,7 +52,7 @@ public: static int GetCursor(sqlite3 *db, const std::string &tableName, uint64_t &cursor); static int CheckDistributedSchemaValid(const RelationalSchemaObject &schemaObj, const DistributedSchema &schema, - SQLiteSingleVerRelationalStorageExecutor *executor); + bool isForceUpgrade, SQLiteSingleVerRelationalStorageExecutor *executor); static DistributedSchema FilterRepeatDefine(const DistributedSchema &schema); @@ -63,11 +63,48 @@ public: static int GetLogInfoPre(sqlite3_stmt *queryStmt, DistributedTableMode mode, const DataItem &dataItem, LogInfo &logInfoGet); - static int OperateDataStatus(sqlite3 *db, const std::vector &tables); + static int OperateDataStatus(sqlite3 *db, const std::vector &tables, uint64_t virtualTime); static int GetMetaLocalTimeOffset(sqlite3 *db, int64_t &timeOffset); static std::pair GetCurrentVirtualTime(sqlite3 *db); + + static int CreateRelationalMetaTable(sqlite3 *db); + + static int GetKvData(sqlite3 *db, bool isMemory, const Key &key, Value &value); + static int PutKvData(sqlite3 *db, bool isMemory, const Key &key, const Value &value); + + static int InitCursorToMeta(sqlite3 *db, bool isMemory, const std::string &tableName); + static int InitKnowledgeTableTypeToMeta(sqlite3 *db, bool isMemory, const std::string &tableName); + static int SetLogTriggerStatus(sqlite3 *db, bool status); + + struct GenLogParam { + sqlite3 *db = nullptr; + bool isMemory = false; + bool isTrackerTable = false; + }; + + static int GeneTimeStrForLog(const TableInfo &tableInfo, GenLogParam ¶m, std::string &timeStr); + + static int GeneLogInfoForExistedData(const std::string &identity, const TableInfo &tableInfo, + std::unique_ptr &logMgrPtr, GenLogParam ¶m); + + static int GetExistedDataTimeOffset(sqlite3 *db, const std::string &tableName, bool isMem, int64_t &timeOffset); + + static std::string GetExtendValue(const TrackerTable &trackerTable); + + static int CleanTrackerData(sqlite3 *db, const std::string &tableName, int64_t cursor, bool isOnlyTrackTable); + + static std::pair CheckExistDirtyLog(sqlite3 *db, const std::string &oriTable); + + static int CleanDirtyLog(sqlite3 *db, const std::string &oriTable, const RelationalSchemaObject &obj); + + static std::pair ExecuteCheckSql(sqlite3 *db, const std::string &sql); + + static int ExecuteSql(sqlite3 *db, const std::string &sql, + const std::function &checkFunc); + + static int ExecuteListAction(const std::vector> &actions); private: static int BindExtendStatementByType(sqlite3_stmt *statement, int cid, Type &typeVal); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils_client.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils_client.cpp new file mode 100644 index 00000000..d2fd1f42 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils_client.cpp @@ -0,0 +1,335 @@ +/* + * 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 "sqlite_relational_utils.h" +#include "db_common.h" +#include "time_helper.h" + +namespace DistributedDB { +int SQLiteRelationalUtils::CreateRelationalMetaTable(sqlite3 *db) +{ + std::string sql = + "CREATE TABLE IF NOT EXISTS " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata(" \ + "key BLOB PRIMARY KEY NOT NULL," \ + "value BLOB);"; + int errCode = SQLiteUtils::ExecuteRawSQL(db, sql); + if (errCode != E_OK) { + LOGE("[SQLite] execute create table sql failed, err=%d", errCode); + } + return errCode; +} + +int SQLiteRelationalUtils::GetKvData(sqlite3 *db, bool isMemory, const Key &key, Value &value) +{ + static const std::string SELECT_META_VALUE_SQL = "SELECT value FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + + "metadata WHERE key=?;"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(db, SELECT_META_VALUE_SQL, statement); + if (errCode != E_OK) { + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } + + errCode = SQLiteUtils::BindBlobToStatement(statement, 1, key, false); // first arg. + if (errCode != E_OK) { + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } + + errCode = SQLiteUtils::StepWithRetry(statement, isMemory); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = -E_NOT_FOUND; + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } + + errCode = SQLiteUtils::GetColumnBlobValue(statement, 0, value); // only one result. + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); +} + +int SQLiteRelationalUtils::PutKvData(sqlite3 *db, bool isMemory, const Key &key, const Value &value) +{ + static const std::string INSERT_META_SQL = "INSERT OR REPLACE INTO " + std::string(DBConstant::RELATIONAL_PREFIX) + + "metadata VALUES(?,?);"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(db, INSERT_META_SQL, statement); + if (errCode != E_OK) { + return errCode; + } + + errCode = SQLiteUtils::BindBlobToStatement(statement, 1, key, false); // 1 means key index + if (errCode != E_OK) { + LOGE("[SingleVerExe][BindPutKv]Bind key error:%d", errCode); + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } + + errCode = SQLiteUtils::BindBlobToStatement(statement, 2, value, true); // 2 means value index + if (errCode != E_OK) { + LOGE("[SingleVerExe][BindPutKv]Bind value error:%d", errCode); + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } + errCode = SQLiteUtils::StepWithRetry(statement, isMemory); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + } + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); +} + +int SQLiteRelationalUtils::InitCursorToMeta(sqlite3 *db, bool isMemory, const std::string &tableName) +{ + Value key; + Value cursor; + DBCommon::StringToVector(DBCommon::GetCursorKey(tableName), key); + int errCode = GetKvData(db, isMemory, key, cursor); + if (errCode == -E_NOT_FOUND) { + DBCommon::StringToVector(std::string("0"), cursor); + errCode = PutKvData(db, isMemory, key, cursor); + if (errCode != E_OK) { + LOGE("Init cursor to meta table failed. %d", errCode); + } + return errCode; + } + if (errCode != E_OK) { + LOGE("Get cursor from meta table failed. %d", errCode); + } + return errCode; +} + +int SQLiteRelationalUtils::InitKnowledgeTableTypeToMeta(sqlite3 *db, bool isMemory, const std::string &tableName) +{ + std::string tableTypeKey = "sync_table_type_" + tableName; + Value key; + DBCommon::StringToVector(tableTypeKey, key); + Value value; + int errCode = GetKvData(db, isMemory, key, value); + if (errCode == -E_NOT_FOUND) { + DBCommon::StringToVector(DBConstant::KNOWLEDGE_TABLE_TYPE, value); + errCode = PutKvData(db, isMemory, key, value); + if (errCode != E_OK) { + LOGE("Init table type to meta table failed. %d", errCode); + return errCode; + } + } + if (errCode != E_OK) { + LOGE("Get table type from meta table failed. %d", errCode); + } + return errCode; +} + +int SQLiteRelationalUtils::SetLogTriggerStatus(sqlite3 *db, bool status) +{ + const std::string key = "log_trigger_switch"; + std::string val = status ? "true" : "false"; + std::string sql = "INSERT OR REPLACE INTO " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata" + + " VALUES ('" + key + "', '" + val + "')"; + int errCode = SQLiteUtils::ExecuteRawSQL(db, sql); + if (errCode != E_OK) { + LOGE("Set log trigger to %s failed. errCode=%d", val.c_str(), errCode); + } + return errCode; +} + +int SQLiteRelationalUtils::GeneLogInfoForExistedData(const std::string &identity, const TableInfo &tableInfo, + std::unique_ptr &logMgrPtr, GenLogParam ¶m) +{ + std::string tableName = tableInfo.GetTableName(); + std::string timeStr; + int errCode = GeneTimeStrForLog(tableInfo, param, timeStr); + if (errCode != E_OK) { + return errCode; + } + errCode = SetLogTriggerStatus(param.db, false); + if (errCode != E_OK) { + return errCode; + } + std::string logTable = DBConstant::RELATIONAL_PREFIX + tableName + "_log"; + std::string rowid = std::string(DBConstant::SQLITE_INNER_ROWID); + uint32_t flagVal = static_cast(LogInfoFlag::FLAG_LOCAL); + if (tableInfo.GetTableSyncType() == TableSyncType::CLOUD_COOPERATION) { + flagVal = flagVal | static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_INCONSISTENCY); + } + std::string flag = std::to_string(flagVal); + TrackerTable trackerTable = tableInfo.GetTrackerTable(); + trackerTable.SetTableName(tableName); + const std::string prefix = "a."; + std::string calPrimaryKeyHash = logMgrPtr->CalcPrimaryKeyHash(prefix, tableInfo, identity); + std::string sql = "INSERT OR REPLACE INTO " + logTable + " SELECT " + rowid + ", '', '', " + timeStr + " + " + + rowid + ", " + timeStr + " + " + rowid + ", " + flag + ", " + calPrimaryKeyHash + ", '', "; + sql += GetExtendValue(tableInfo.GetTrackerTable()); + sql += ", 0, '', '', 0 FROM '" + tableName + "' AS a "; + if (param.isTrackerTable) { + sql += " WHERE 1 = 1;"; + } else { + sql += "WHERE NOT EXISTS (SELECT 1 FROM " + logTable + " WHERE data_key = a._rowid_);"; + } + errCode = trackerTable.ReBuildTempTrigger(param.db, TriggerMode::TriggerModeEnum::INSERT, [db = param.db, &sql]() { + int ret = SQLiteUtils::ExecuteRawSQL(db, sql); + if (ret != E_OK) { + LOGE("Failed to initialize cloud type log data.%d", ret); + } + return ret; + }); + return errCode; +} + +int SQLiteRelationalUtils::GetExistedDataTimeOffset(sqlite3 *db, const std::string &tableName, bool isMem, + int64_t &timeOffset) +{ + std::string sql = "SELECT get_sys_time(0) - max(" + std::string(DBConstant::SQLITE_INNER_ROWID) + ") - 1 FROM '" + + tableName + "';"; + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != E_OK) { + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(stmt, isMem); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + timeOffset = static_cast(sqlite3_column_int64(stmt, 0)); + errCode = E_OK; + } + int ret = E_OK; + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode != E_OK ? errCode : ret; +} + +std::string SQLiteRelationalUtils::GetExtendValue(const TrackerTable &trackerTable) +{ + std::string extendValue; + const std::set &extendNames = trackerTable.GetExtendNames(); + if (!extendNames.empty()) { + extendValue += "json_object("; + for (const auto &extendName : extendNames) { + extendValue += "'" + extendName + "'," + extendName + ","; + } + extendValue.pop_back(); + extendValue += ")"; + } else { + extendValue = "''"; + } + return extendValue; +} + +int SQLiteRelationalUtils::CleanTrackerData(sqlite3 *db, const std::string &tableName, int64_t cursor, + bool isOnlyTrackTable) +{ + std::string sql; + if (isOnlyTrackTable) { + sql = "DELETE FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log"; + } else { + sql = "UPDATE " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log SET extend_field = NULL"; + } + sql += " where data_key = -1 and cursor <= ?;"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, statement); + if (errCode != E_OK) { // LCOV_EXCL_BR_LINE + LOGE("get clean tracker data stmt failed %d.", errCode); + return errCode; + } + errCode = SQLiteUtils::BindInt64ToStatement(statement, 1, cursor); + int ret = E_OK; + if (errCode != E_OK) { // LCOV_EXCL_BR_LINE + LOGE("bind clean tracker data stmt failed %d.", errCode); + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(statement); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { // LCOV_EXCL_BR_LINE + errCode = E_OK; + } else { + LOGE("clean tracker step failed: %d.", errCode); + } + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode == E_OK ? ret : errCode; +} + + +int SQLiteRelationalUtils::AnalysisTrackerTable(sqlite3 *db, const TrackerTable &trackerTable, TableInfo &tableInfo) +{ + int errCode = SQLiteUtils::AnalysisSchema(db, trackerTable.GetTableName(), tableInfo, true); + if (errCode != E_OK) { + LOGE("analysis table schema failed %d.", errCode); + return errCode; + } + tableInfo.SetTrackerTable(trackerTable); + errCode = tableInfo.CheckTrackerTable(); + if (errCode != E_OK) { + LOGE("check tracker table schema failed %d.", errCode); + } + return errCode; +} + +int SQLiteRelationalUtils::GetMetaLocalTimeOffset(sqlite3 *db, int64_t &timeOffset) +{ + std::string sql = "SELECT value FROM " + DBCommon::GetMetaTableName() + " WHERE key=x'" + + DBCommon::TransferStringToHex(std::string(DBConstant::LOCALTIME_OFFSET_KEY)) + "';"; + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != E_OK) { + return errCode; + } + int ret = E_OK; + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + timeOffset = static_cast(sqlite3_column_int64(stmt, 0)); + if (timeOffset < 0) { + LOGE("[SQLiteRDBUtils] TimeOffset %" PRId64 "is invalid.", timeOffset); + SQLiteUtils::ResetStatement(stmt, true, ret); + return -E_INTERNAL_ERROR; + } + errCode = E_OK; + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + timeOffset = 0; + errCode = E_OK; + } + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode != E_OK ? errCode : ret; +} + +std::pair SQLiteRelationalUtils::GetCurrentVirtualTime(sqlite3 *db) +{ + int64_t localTimeOffset = 0; + std::pair res; + auto &[errCode, time] = res; + errCode = GetMetaLocalTimeOffset(db, localTimeOffset); + if (errCode != E_OK) { + LOGE("[SQLiteRDBUtils] Failed to get local timeOffset.%d", errCode); + return res; + } + Timestamp currentSysTime = TimeHelper::GetSysCurrentTime(); + Timestamp currentLocalTime = currentSysTime + static_cast(localTimeOffset); + time = std::to_string(currentLocalTime); + return res; +} + +int SQLiteRelationalUtils::GeneTimeStrForLog(const TableInfo &tableInfo, GenLogParam ¶m, std::string &timeStr) +{ + if (tableInfo.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { + auto [errCode, time] = GetCurrentVirtualTime(param.db); + if (errCode != E_OK) { + LOGE("Failed to get current virtual time.%d", errCode); + return errCode; + } + timeStr = time; + } else { + int64_t timeOffset = 0; + std::string tableName = tableInfo.GetTableName(); + int errCode = GetExistedDataTimeOffset(param.db, tableName, param.isMemory, timeOffset); + if (errCode != E_OK) { + return errCode; + } + timeStr = std::to_string(timeOffset); + } + return E_OK; +} +} // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp index 04415fc8..554cb3f4 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp @@ -34,13 +34,13 @@ SQLiteSingleRelationalStorageEngine::~SQLiteSingleRelationalStorageEngine() StorageExecutor *SQLiteSingleRelationalStorageEngine::NewSQLiteStorageExecutor(sqlite3 *dbHandle, bool isWrite, bool isMemDb) { - auto mode = properties_.GetDistributedTableMode(); + auto mode = GetRelationalProperties().GetDistributedTableMode(); return new (std::nothrow) SQLiteSingleVerRelationalStorageExecutor(dbHandle, isWrite, mode); } int SQLiteSingleRelationalStorageEngine::Upgrade(sqlite3 *db) { - int errCode = CreateRelationalMetaTable(db); + int errCode = SQLiteRelationalUtils::CreateRelationalMetaTable(db); if (errCode != E_OK) { LOGE("Create relational store meta table failed. err=%d", errCode); return errCode; @@ -92,7 +92,7 @@ int SQLiteSingleRelationalStorageEngine::RegisterFunction(sqlite3 *db) const int SQLiteSingleRelationalStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *&handle) { sqlite3 *db = nullptr; - int errCode = SQLiteUtils::OpenDatabase(option_, db, false); + int errCode = SQLiteUtils::OpenDatabase(GetOption(), db, false); if (errCode != E_OK) { return errCode; } @@ -151,7 +151,8 @@ const std::string SYNC_TABLE_TYPE = "sync_table_type_"; int SaveSchemaToMetaTable(SQLiteSingleVerRelationalStorageExecutor *handle, const RelationalSchemaObject &schema) { - const Key schemaKey(DBConstant::RELATIONAL_SCHEMA_KEY.begin(), DBConstant::RELATIONAL_SCHEMA_KEY.end()); + const Key schemaKey(DBConstant::RELATIONAL_SCHEMA_KEY, + DBConstant::RELATIONAL_SCHEMA_KEY + strlen(DBConstant::RELATIONAL_SCHEMA_KEY)); Value schemaVal; auto schemaStr = schema.ToSchemaString(); if (schemaStr.size() > SchemaConstant::SCHEMA_STRING_SIZE_LIMIT) { @@ -169,8 +170,8 @@ int SaveSchemaToMetaTable(SQLiteSingleVerRelationalStorageExecutor *handle, cons int SaveTrackerSchemaToMetaTable(SQLiteSingleVerRelationalStorageExecutor *handle, const RelationalSchemaObject &schema) { - const Key schemaKey(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.begin(), - DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.end()); + const Key schemaKey(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY, + DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY + strlen(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY)); Value schemaVal; DBCommon::StringToVector(schema.ToSchemaString(), schemaVal); int errCode = handle->PutKvData(schemaKey, schemaVal); // save schema to meta_data @@ -248,7 +249,7 @@ int SQLiteSingleRelationalStorageEngine::CreateDistributedSharedTable(SQLiteSing table.SetOriginTableName(tableName); table.SetSharedTableMark(true); table.SetTableSyncType(tableSyncType); - table.SetTrackerTable(trackerSchema_.GetTrackerTable(sharedTableName)); + table.SetTrackerTable(GetTrackerSchema().GetTrackerTable(sharedTableName)); if (!table.GetTrackerTable().IsEmpty() && tableSyncType == TableSyncType::DEVICE_COOPERATION) { // LCOV_EXCL_BR_LINE LOGE("current is trackerTable, not support creating device distributed table."); return -E_NOT_SUPPORT; @@ -305,7 +306,7 @@ int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(const std::strin int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(SQLiteSingleVerRelationalStorageExecutor *&handle, bool isUpgraded, const std::string &identity, TableInfo &table, RelationalSchemaObject &schema) { - auto mode = properties_.GetDistributedTableMode(); + auto mode = GetRelationalProperties().GetDistributedTableMode(); TableSyncType tableSyncType = table.GetTableSyncType(); std::string tableName = table.GetTableName(); int errCode = handle->InitCursorToMeta(tableName); @@ -354,7 +355,7 @@ int SQLiteSingleRelationalStorageEngine::UpgradeDistributedTable(const std::stri return errCode; } - auto mode = properties_.GetDistributedTableMode(); + auto mode = GetRelationalProperties().GetDistributedTableMode(); errCode = handle->UpgradeDistributedTable(tableName, mode, schemaChanged, schema, syncType); if (errCode != E_OK) { LOGE("Upgrade distributed table failed. %d", errCode); @@ -392,7 +393,7 @@ int SQLiteSingleRelationalStorageEngine::CleanDistributedDeviceTable(std::vector errCode = handle->CheckAndCleanDistributedTable(schema_.GetTableNames(), missingTables); if (errCode == E_OK) { if (missingTables.empty()) { - LOGI("Check missing distributed table is empty."); + LOGI("Missing table is empty."); ReleaseExecutor(handle); return errCode; } @@ -436,22 +437,16 @@ const RelationalDBProperties &SQLiteSingleRelationalStorageEngine::GetProperties return properties_; } -void SQLiteSingleRelationalStorageEngine::SetProperties(const RelationalDBProperties &properties) +const RelationalDBProperties SQLiteSingleRelationalStorageEngine::GetRelationalProperties() const { - properties_ = properties; + std::lock_guard lock(propertiesMutex_); + return properties_; } -int SQLiteSingleRelationalStorageEngine::CreateRelationalMetaTable(sqlite3 *db) +void SQLiteSingleRelationalStorageEngine::SetProperties(const RelationalDBProperties &properties) { - std::string sql = - "CREATE TABLE IF NOT EXISTS " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata(" \ - "key BLOB PRIMARY KEY NOT NULL," \ - "value BLOB);"; - int errCode = SQLiteUtils::ExecuteRawSQL(db, sql); - if (errCode != E_OK) { - LOGE("[SQLite] execute create table sql failed, err=%d", errCode); - } - return errCode; + std::lock_guard lock(propertiesMutex_); + properties_ = properties; } int SQLiteSingleRelationalStorageEngine::SetTrackerTable(const TrackerSchema &schema, const TableInfo &tableInfo, @@ -463,29 +458,23 @@ int SQLiteSingleRelationalStorageEngine::SetTrackerTable(const TrackerSchema &sc if (handle == nullptr) { return errCode; } + ResFinalizer finalizer([&handle, this] { this->ReleaseExecutor(handle); }); errCode = handle->StartTransaction(TransactType::IMMEDIATE); if (errCode != E_OK) { - ReleaseExecutor(handle); return errCode; } - RelationalSchemaObject tracker = trackerSchema_; + RelationalSchemaObject tracker = GetTrackerSchema(); tracker.InsertTrackerSchema(schema); int ret = handle->CreateTrackerTable(tracker.GetTrackerTable(schema.tableName), tableInfo, isFirstCreate); if (ret != E_OK && ret != -E_WITH_INVENTORY_DATA) { (void)handle->Rollback(); - ReleaseExecutor(handle); return ret; } - Key key; - DBCommon::StringToVector(SYNC_TABLE_TYPE + schema.tableName, key); - Value value; - DBCommon::StringToVector(tableInfo.GetTableSyncType() == DEVICE_COOPERATION ? DEVICE_TYPE : CLOUD_TYPE, value); - errCode = handle->PutKvData(key, value); + errCode = SaveSyncTableTypeAndDropFlagToMeta(handle, schema.tableName, tableInfo.GetTableSyncType()); if (errCode != E_OK) { LOGE("[SetTrackerTable] Save sync type to meta table failed: %d", errCode); (void)handle->Rollback(); - ReleaseExecutor(handle); return errCode; } @@ -495,23 +484,21 @@ int SQLiteSingleRelationalStorageEngine::SetTrackerTable(const TrackerSchema &sc errCode = SaveTrackerSchemaToMetaTable(handle, tracker); if (errCode != E_OK) { (void)handle->Rollback(); - ReleaseExecutor(handle); return errCode; } errCode = handle->Commit(); if (errCode != E_OK) { - ReleaseExecutor(handle); return errCode; } - trackerSchema_ = tracker; - ReleaseExecutor(handle); + SetTrackerSchema(tracker); return ret; } void SQLiteSingleRelationalStorageEngine::CacheTrackerSchema(const TrackerSchema &schema) { + std::lock_guard lock(trackerSchemaMutex_); trackerSchema_.InsertTrackerSchema(schema); if (!schema.isTrackAction && schema.trackerColNames.empty()) { // if isTrackAction be false and trackerColNames is empty, will remove the tracker schema. @@ -551,7 +538,7 @@ int SQLiteSingleRelationalStorageEngine::GetOrInitTrackerSchemaFromMeta() return errCode; } } - trackerSchema_ = trackerSchema; + SetTrackerSchema(trackerSchema); ReleaseExecutor(handle); return E_OK; } @@ -564,7 +551,7 @@ int SQLiteSingleRelationalStorageEngine::SaveTrackerSchema(const std::string &ta if (handle == nullptr) { return errCode; } - RelationalSchemaObject tracker = trackerSchema_; + RelationalSchemaObject tracker = GetTrackerSchema(); errCode = SaveTrackerSchemaToMetaTable(handle, tracker); if (errCode != E_OK || !isFirstCreate) { ReleaseExecutor(handle); @@ -633,10 +620,9 @@ int SQLiteSingleRelationalStorageEngine::SetReference(const std::vectorGetClearWaterMarkTables(tableReferenceProperty, schema, clearWaterMarkTables); - if (errCode != E_OK) { - return errCode; + int res = handle->GetClearWaterMarkTables(tableReferenceProperty, schema, clearWaterMarkTables); + if (res != E_OK && res != -E_TABLE_REFERENCE_CHANGED) { + return res; } schema.SetReferenceProperty(tableReferenceProperty); errCode = SaveSchemaToMetaTable(handle, schema); @@ -644,7 +630,7 @@ int SQLiteSingleRelationalStorageEngine::SetReference(const std::vector& oldExtendColNames = oldTrackerTable.GetExtendNames(); const std::string lowVersionExtendColName = oldTrackerTable.GetExtendName(); @@ -1093,17 +1086,22 @@ int SQLiteSingleRelationalStorageEngine::UpdateExtendField(const DistributedDB:: return errCode; } } + + // Try clear historical mismatched log, which usually do not occur and apply to tracker table only. + if (GetSchema().GetTable(schema.tableName).Empty()) { + handle->ClearLogOfMismatchedData(schema.tableName); + } return handle->Commit(); } std::pair SQLiteSingleRelationalStorageEngine::SetDistributedSchema(const DistributedSchema &schema, - const std::string &localIdentity) + const std::string &localIdentity, bool isForceUpgrade) { std::lock_guard autoLock(createDistributedTableMutex_); auto schemaObj = GetSchema(); std::pair res = {E_OK, schemaObj.CheckDistributedSchemaChange(schema)}; auto &[errCode, isSchemaChange] = res; - if (properties_.GetDistributedTableMode() == DistributedTableMode::SPLIT_BY_DEVICE) { + if (GetRelationalProperties().GetDistributedTableMode() == DistributedTableMode::SPLIT_BY_DEVICE) { LOGE("tableMode SPLIT_BY_DEVICE not support set distributed schema"); errCode = -E_NOT_SUPPORT; return res; @@ -1116,7 +1114,7 @@ std::pair SQLiteSingleRelationalStorageEngine::SetDistributedSchema(c LOGE("new schema version no upgrade old:%" PRIu32 " new:%" PRIu32, localSchema.version, schema.version); errCode = -E_INVALID_ARGS; } else { - errCode = SetDistributedSchemaInner(schemaObj, schema, localIdentity); + errCode = SetDistributedSchemaInner(schemaObj, schema, localIdentity, isForceUpgrade); } if (errCode == E_OK) { SetSchema(schemaObj); @@ -1125,7 +1123,7 @@ std::pair SQLiteSingleRelationalStorageEngine::SetDistributedSchema(c } int SQLiteSingleRelationalStorageEngine::SetDistributedSchemaInner(RelationalSchemaObject &schemaObj, - const DistributedSchema &schema, const std::string &localIdentity) + const DistributedSchema &schema, const std::string &localIdentity, bool isForceUpgrade) { int errCode = E_OK; auto *handle = static_cast(FindExecutor(true, OperatePerm::NORMAL_PERM, @@ -1142,39 +1140,54 @@ int SQLiteSingleRelationalStorageEngine::SetDistributedSchemaInner(RelationalSch if (errCode != E_OK) { return errCode; } - errCode = SQLiteRelationalUtils::CheckDistributedSchemaValid(schemaObj, schema, handle); + errCode = SetDistributedSchemaInTraction(schemaObj, schema, localIdentity, isForceUpgrade, *handle); if (errCode != E_OK) { (void)handle->Rollback(); return errCode; } + return handle->Commit(); +} + +int SQLiteSingleRelationalStorageEngine::SetDistributedSchemaInTraction(RelationalSchemaObject &schemaObj, + const DistributedSchema &schema, const std::string &localIdentity, bool isForceUpgrade, + SQLiteSingleVerRelationalStorageExecutor &handle) +{ + int errCode = SQLiteRelationalUtils::CheckDistributedSchemaValid(schemaObj, schema, isForceUpgrade, &handle); + if (errCode != E_OK) { + return errCode; + } + auto changeStatus = schemaObj.GetTableChangeStatus(schema); schemaObj.SetDistributedSchema(schema); for (const auto &table : schema.tables) { + if (!changeStatus[table.tableName]) { + continue; + } TableInfo tableInfo = schemaObj.GetTable(table.tableName); + tableInfo.SetTrackerTable(GetTrackerSchema().GetTrackerTable(table.tableName)); if (tableInfo.Empty()) { continue; } tableInfo.SetDistributedTable(schemaObj.GetDistributedTable(table.tableName)); - errCode = handle->RenewTableTrigger(schemaObj.GetTableMode(), tableInfo, tableInfo.GetTableSyncType(), + errCode = handle.RenewTableTrigger(schemaObj.GetTableMode(), tableInfo, tableInfo.GetTableSyncType(), localIdentity); if (errCode != E_OK) { - LOGE("Failed to refresh trigger while setting up distributed schema: %d", errCode); - (void)handle->Rollback(); + LOGE("Failed to refresh %s:%zu trigger while setting up distributed schema: %d", + DBCommon::StringMiddleMasking(table.tableName).c_str(), table.tableName.size(), errCode); return errCode; } - errCode = handle->UpdateHashKey(schemaObj.GetTableMode(), tableInfo, tableInfo.GetTableSyncType()); + errCode = handle.UpdateHashKey(schemaObj.GetTableMode(), tableInfo, tableInfo.GetTableSyncType(), + localIdentity); if (errCode != E_OK) { - LOGE("Failed to update hash_key while setting up distributed schema: %d", errCode); - (void)handle->Rollback(); + LOGE("Failed to update %s:%zu hash_key while setting up distributed schema: %d", + DBCommon::StringMiddleMasking(table.tableName).c_str(), table.tableName.size(), errCode); return errCode; } } - errCode = SaveSchemaToMetaTable(handle, schemaObj); + errCode = SaveSchemaToMetaTable(&handle, schemaObj); if (errCode != E_OK) { LOGE("Save schema to meta table for set distributed schema failed. %d", errCode); - (void)handle->Rollback(); - return errCode; } - return handle->Commit(); + return errCode; } } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h index ce9b1709..61588301 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h @@ -41,6 +41,7 @@ public: int CleanDistributedDeviceTable(std::vector &missingTables); const RelationalDBProperties &GetProperties() const; + const RelationalDBProperties GetRelationalProperties() const; void SetProperties(const RelationalDBProperties &properties); int SetTrackerTable(const TrackerSchema &schema, const TableInfo &tableInfo, bool isFirstCreate); @@ -50,6 +51,7 @@ public: int ExecuteSql(const SqlCondition &condition, std::vector &records); RelationalSchemaObject GetTrackerSchema() const; + void SetTrackerSchema(const RelationalSchemaObject &trackerSchema); int CleanTrackerData(const std::string &tableName, int64_t cursor); int SetReference(const std::vector &tableReferenceProperty, @@ -62,7 +64,8 @@ public: const std::map &sharedTableOriginNames); int UpdateExtendField(const TrackerSchema &schema); - std::pair SetDistributedSchema(const DistributedSchema &schema, const std::string &localIdentity); + std::pair SetDistributedSchema(const DistributedSchema &schema, const std::string &localIdentity, + bool isForceUpgrade); protected: StorageExecutor *NewSQLiteStorageExecutor(sqlite3 *dbHandle, bool isWrite, bool isMemDb) override; int Upgrade(sqlite3 *db) override; @@ -85,8 +88,6 @@ private: int CreateDistributedSharedTable(SQLiteSingleVerRelationalStorageExecutor *&handle, const std::string &tableName, const std::string &sharedTableName, TableSyncType syncType, RelationalSchemaObject &schema); - int CreateRelationalMetaTable(sqlite3 *db); - int CleanTrackerDeviceTable(const std::vector &tableNames, RelationalSchemaObject &trackerSchemaObj, SQLiteSingleVerRelationalStorageExecutor *&handle); @@ -125,14 +126,19 @@ private: const std::map &alterTableNames, const RelationalSchemaObject &schema); int SetDistributedSchemaInner(RelationalSchemaObject &schemaObj, const DistributedSchema &schema, - const std::string &localIdentity); + const std::string &localIdentity, bool isForceUpgrade); + + int SetDistributedSchemaInTraction(RelationalSchemaObject &schemaObj, const DistributedSchema &schema, + const std::string &localIdentity, bool isForceUpgrade, SQLiteSingleVerRelationalStorageExecutor &handle); RelationalSchemaObject schema_; RelationalSchemaObject trackerSchema_; mutable std::mutex schemaMutex_; + mutable std::mutex trackerSchemaMutex_; RelationalDBProperties properties_; std::mutex createDistributedTableMutex_; + mutable std::mutex propertiesMutex_; }; } // namespace DistributedDB #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp index 439a6305..182b00b7 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp @@ -142,93 +142,14 @@ int CheckTableConstraint(const TableInfo &table, DistributedTableMode mode, Tabl return E_OK; } -namespace { -int GetExistedDataTimeOffset(sqlite3 *db, const std::string &tableName, bool isMem, int64_t &timeOffset) -{ - std::string sql = "SELECT get_sys_time(0) - max(" + std::string(DBConstant::SQLITE_INNER_ROWID) + ") - 1 FROM '" + - tableName + "';"; - sqlite3_stmt *stmt = nullptr; - int errCode = SQLiteUtils::GetStatement(db, sql, stmt); - if (errCode != E_OK) { - return errCode; - } - errCode = SQLiteUtils::StepWithRetry(stmt, isMem); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - timeOffset = static_cast(sqlite3_column_int64(stmt, 0)); - errCode = E_OK; - } - int ret = E_OK; - SQLiteUtils::ResetStatement(stmt, true, ret); - return errCode != E_OK ? errCode : ret; -} -} - -std::string GetExtendValue(const TrackerTable &trackerTable) -{ - std::string extendValue; - const std::set &extendNames = trackerTable.GetExtendNames(); - if (!extendNames.empty()) { - extendValue += "json_object("; - for (const auto &extendName : extendNames) { - extendValue += "'" + extendName + "'," + extendName + ","; - } - extendValue.pop_back(); - extendValue += ")"; - } else { - extendValue = "''"; - } - return extendValue; -} - -int SQLiteSingleVerRelationalStorageExecutor::GeneLogInfoForExistedDataInner(sqlite3 *db, const std::string &identity, - const TableInfo &tableInfo, std::unique_ptr &logMgrPtr, bool isTrackerTable) -{ - std::string tableName = tableInfo.GetTableName(); - int64_t timeOffset = 0; - int errCode = GetExistedDataTimeOffset(db, tableName, isMemDb_, timeOffset); - if (errCode != E_OK) { - return errCode; - } - errCode = SetLogTriggerStatus(false); - if (errCode != E_OK) { - return errCode; - } - std::string timeOffsetStr = std::to_string(timeOffset); - std::string logTable = DBConstant::RELATIONAL_PREFIX + tableName + "_log"; - std::string rowid = std::string(DBConstant::SQLITE_INNER_ROWID); - std::string flag = std::to_string(static_cast(LogInfoFlag::FLAG_LOCAL) | - static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_INCONSISTENCY)); - TrackerTable trackerTable = tableInfo.GetTrackerTable(); - trackerTable.SetTableName(tableName); - const std::string prefix = "a."; - std::string calPrimaryKeyHash = logMgrPtr->CalcPrimaryKeyHash(prefix, tableInfo, identity); - std::string sql = "INSERT OR REPLACE INTO " + logTable + " SELECT " + rowid + - ", '', '', " + timeOffsetStr + " + " + rowid + ", " + - timeOffsetStr + " + " + rowid + ", " + flag + ", " + calPrimaryKeyHash + ", '', "; - sql += GetExtendValue(tableInfo.GetTrackerTable()); - sql += ", 0, '', '', 0 FROM '" + tableName + "' AS a "; - if (isTrackerTable) { - sql += " WHERE 1 = 1;"; - } else { - sql += "WHERE NOT EXISTS (SELECT 1 FROM " + logTable + " WHERE data_key = a._rowid_);"; - } - errCode = trackerTable.ReBuildTempTrigger(db, TriggerMode::TriggerModeEnum::INSERT, [db, &sql]() { - int ret = SQLiteUtils::ExecuteRawSQL(db, sql); - if (ret != E_OK) { - LOGE("Failed to initialize cloud type log data.%d", ret); - } - return ret; - }); - return errCode; -} - int SQLiteSingleVerRelationalStorageExecutor::GeneLogInfoForExistedData(sqlite3 *db, const std::string &identity, const TableInfo &tableInfo, std::unique_ptr &logMgrPtr, bool isTrackerTable) { if (tableInfo.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { return UpdateTrackerTable(db, identity, tableInfo, logMgrPtr, false); } - return GeneLogInfoForExistedDataInner(db, identity, tableInfo, logMgrPtr, isTrackerTable); + SQLiteRelationalUtils::GenLogParam param = {db, isMemDb_, isTrackerTable}; + return SQLiteRelationalUtils::GeneLogInfoForExistedData(identity, tableInfo, logMgrPtr, param); } int SQLiteSingleVerRelationalStorageExecutor::ResetLogStatus(std::string &tableName) @@ -299,11 +220,7 @@ int SQLiteSingleVerRelationalStorageExecutor::CreateRelationalLogTable(Distribut { // create log table std::unique_ptr tableManager; - if (!table.GetTrackerTable().IsEmpty() && table.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { - tableManager = std::make_unique(); - } else { - tableManager = LogTableManagerFactory::GetTableManager(mode, table.GetTableSyncType()); - } + tableManager = LogTableManagerFactory::GetTableManager(table, mode, table.GetTableSyncType()); if (tableManager == nullptr) { LOGE("[CreateRelationalLogTable] get table manager failed"); return -E_INVALID_DB; @@ -314,7 +231,14 @@ int SQLiteSingleVerRelationalStorageExecutor::CreateRelationalLogTable(Distribut return errCode; } std::string tableName = table.GetTableName(); - if (!isUpgraded) { + bool isOnceDropped = false; + (void)IsTableOnceDropped(tableName, isOnceDropped); + if (isOnceDropped) { + SQLiteRelationalUtils::GenLogParam param = { + dbHandle_, isMemDb_, table.GetTrackerTable().GetTableName().empty() + }; + errCode = SQLiteRelationalUtils::GeneLogInfoForExistedData(identity, table, tableManager, param); + } else if (!isUpgraded) { if (table.GetTrackerTable().GetTableName().empty()) { errCode = GeneLogInfoForExistedData(dbHandle_, identity, table, tableManager, false); } else if (table.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { @@ -324,10 +248,6 @@ int SQLiteSingleVerRelationalStorageExecutor::CreateRelationalLogTable(Distribut // tracker table -> distributed cloud table errCode = ResetLogStatus(tableName); } - } else { - if (table.GetTrackerTable().GetTableName().empty()) { - errCode = GeneLogInfoForExistedDataInner(dbHandle_, identity, table, tableManager, false); - } } if (errCode != E_OK) { LOGE("[CreateDistributedTable] generate log isUpgraded %d failed %d.", static_cast(isUpgraded), errCode); @@ -427,16 +347,27 @@ int SQLiteSingleVerRelationalStorageExecutor::UpgradeDistributedTable(const std: // new table should has same or compatible upgrade TableInfo tableInfo = schema.GetTable(tableName); errCode = tableInfo.CompareWithTable(newTableInfo, schema.GetSchemaVersion()); - if (errCode == -E_RELATIONAL_TABLE_INCOMPATIBLE) { - LOGE("[UpgradeDistributedTable] Not support with incompatible upgrade."); - return -E_SCHEMA_MISMATCH; - } else if (errCode == -E_RELATIONAL_TABLE_EQUAL) { - LOGD("[UpgradeDistributedTable] schema has not changed."); - // update table if tableName changed - schema.RemoveRelationalTable(tableName); - tableInfo.SetTableName(tableName); - schema.AddRelationalTable(tableInfo); - return E_OK; + bool onceDropped = false; + int ret = IsTableOnceDropped(tableName, onceDropped); + if (ret != E_OK) { + LOGE("[UpgradeDistributedTable] Get table %s dropped status fail %d.", + DBCommon::StringMiddleMasking(tableName).c_str(), ret); + return ret; + } + LOGI("[UpgradeDistributedTable] table name is %s length is %zu, the dropped status is %d, errCode is %d", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), onceDropped, errCode); + if (!onceDropped) { + if (errCode == -E_RELATIONAL_TABLE_INCOMPATIBLE) { + LOGE("[UpgradeDistributedTable] Not support with incompatible upgrade."); + return -E_SCHEMA_MISMATCH; + } else if (errCode == -E_RELATIONAL_TABLE_EQUAL) { + LOGD("[UpgradeDistributedTable] schema has not changed."); + // update table if tableName changed + schema.RemoveRelationalTable(tableName); + tableInfo.SetTableName(tableName); + schema.AddRelationalTable(tableInfo); + return E_OK; + } } schemaChanged = true; @@ -765,63 +696,19 @@ static size_t GetDataItemSerialSize(DataItem &item, size_t appendLen) int SQLiteSingleVerRelationalStorageExecutor::GetKvData(const Key &key, Value &value) const { - static const std::string SELECT_META_VALUE_SQL = "SELECT value FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + - "metadata WHERE key=?;"; - sqlite3_stmt *statement = nullptr; - int errCode = SQLiteUtils::GetStatement(dbHandle_, SELECT_META_VALUE_SQL, statement); - if (errCode != E_OK) { - goto END; - } - - errCode = SQLiteUtils::BindBlobToStatement(statement, 1, key, false); // first arg. - if (errCode != E_OK) { - goto END; - } - - errCode = SQLiteUtils::StepWithRetry(statement, isMemDb_); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = -E_NOT_FOUND; - goto END; - } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - goto END; - } + return SQLiteRelationalUtils::GetKvData(dbHandle_, isMemDb_, key, value); +} - errCode = SQLiteUtils::GetColumnBlobValue(statement, 0, value); // only one result. -END: - int ret = E_OK; - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode != E_OK ? errCode : ret; +int SQLiteSingleVerRelationalStorageExecutor::GetKvDataByPrefixKey(const Key &keyPrefix, + std::map &data) const +{ + std::string metaTableName = std::string(DBConstant::RELATIONAL_PREFIX) + "metadata"; + return SqliteMetaExecutor::GetMetaDataByPrefixKey(dbHandle_, isMemDb_, metaTableName, keyPrefix, data); } int SQLiteSingleVerRelationalStorageExecutor::PutKvData(const Key &key, const Value &value) const { - static const std::string INSERT_META_SQL = "INSERT OR REPLACE INTO " + std::string(DBConstant::RELATIONAL_PREFIX) + - "metadata VALUES(?,?);"; - sqlite3_stmt *statement = nullptr; - int errCode = SQLiteUtils::GetStatement(dbHandle_, INSERT_META_SQL, statement); - if (errCode != E_OK) { - return errCode; - } - - errCode = SQLiteUtils::BindBlobToStatement(statement, 1, key, false); // 1 means key index - if (errCode != E_OK) { - LOGE("[SingleVerExe][BindPutKv]Bind key error:%d", errCode); - goto ERROR; - } - - errCode = SQLiteUtils::BindBlobToStatement(statement, 2, value, true); // 2 means value index - if (errCode != E_OK) { - LOGE("[SingleVerExe][BindPutKv]Bind value error:%d", errCode); - goto ERROR; - } - errCode = SQLiteUtils::StepWithRetry(statement, isMemDb_); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - } -ERROR: - int ret = E_OK; - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode != E_OK ? errCode : ret; + return SQLiteRelationalUtils::PutKvData(dbHandle_, isMemDb_, key, value); } int SQLiteSingleVerRelationalStorageExecutor::DeleteMetaData(const std::vector &keys) const @@ -1008,10 +895,8 @@ int SQLiteSingleVerRelationalStorageExecutor::CheckDataConflictDefeated(const Da isDefeated = false; // no need to solve conflict except miss query data return E_OK; } - if (!isExist || dataItem.dev != logInfoGet.device) { - // defeated if item timestamp is earlier than raw data - isDefeated = (dataItem.timestamp <= logInfoGet.timestamp); - } + // defeated if item timestamp is earlier than raw data + isDefeated = (dataItem.timestamp < logInfoGet.timestamp); return E_OK; } @@ -1365,6 +1250,7 @@ int SQLiteSingleVerRelationalStorageExecutor::IsTableOnceDropped(const std::stri int errCode = GetKvData(key, value); if (errCode == E_OK) { onceDropped = true; + LOGW("[RDBExecutor] Table %s once dropped!", DBCommon::StringMiddleMasking(tableName).c_str()); return E_OK; } else if (errCode == -E_NOT_FOUND) { onceDropped = false; @@ -1422,7 +1308,7 @@ int SQLiteSingleVerRelationalStorageExecutor::CheckAndCleanDistributedTable(cons } missingTables.emplace_back(tableName); } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - LOGE("Check distributed table failed. %d", errCode); + LOGE("[CheckAndCleanDisTable]Check distributed table failed. %d", errCode); break; } errCode = E_OK; // Check result ok for distributed table is still exists @@ -1545,15 +1431,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetMaxTimestamp(const std::vector< int SQLiteSingleVerRelationalStorageExecutor::SetLogTriggerStatus(bool status) { - const std::string key = "log_trigger_switch"; - std::string val = status ? "true" : "false"; - std::string sql = "INSERT OR REPLACE INTO " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata" + - " VALUES ('" + key + "', '" + val + "')"; - int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); - if (errCode != E_OK) { - LOGE("Set log trigger to %s failed. errCode=%d", val.c_str(), errCode); - } - return errCode; + return SQLiteRelationalUtils::SetLogTriggerStatus(dbHandle_, status); } namespace { @@ -1810,6 +1688,16 @@ int SQLiteSingleVerRelationalStorageExecutor::CleanCloudDataAndLogOnUserTable(co return errCode; } +int SQLiteSingleVerRelationalStorageExecutor::GetFlagIsLocalCount(const std::string &logTableName, int32_t &count) +{ + std::string sql = "SELECT count(*) from " + logTableName + " WHERE FLAG&0x02 = 0x02;"; + int errCode = SQLiteUtils::GetCountBySql(dbHandle_, sql, count); + if (errCode != E_OK) { + LOGW("[RDBExecutor] get mark local count from log table failed: %d", errCode); + } + return errCode; +} + int SQLiteSingleVerRelationalStorageExecutor::ChangeCloudDataFlagOnLogTable(const std::string &logTableName) { std::string cleanLogSql = "UPDATE " + logTableName + " SET " + CloudDbConstant::FLAG + " = " + @@ -1845,7 +1733,7 @@ int SQLiteSingleVerRelationalStorageExecutor::SetDataOnUserTableWithLogicDelete( // here just clear updateCursor func, fail will not influence other function (void)CreateFuncUpdateCursor(context, nullptr); if (errCode != E_OK) { - LOGE("Failed to change cloud data flag on usertable, %d.", errCode); + LOGE("Failed to change cloud data flag on userTable, %d.", errCode); return errCode; } // clear some column when data is logicDelete or physical delete @@ -1853,7 +1741,7 @@ int SQLiteSingleVerRelationalStorageExecutor::SetDataOnUserTableWithLogicDelete( " = '', " + SHARING_RESOURCE + " = '' WHERE (" + FLAG_IS_LOGIC_DELETE + ") OR (" + DATA_IS_DELETE + ");"; errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); if (errCode != E_OK) { - LOGE("Failed to deal logic delete data flag on usertable, %d.", errCode); + LOGE("Failed to deal logic delete data flag on userTable, %d.", errCode); return errCode; } LOGI("removeData on userTable:%s length:%zu finish and cursor is %llu.", @@ -2014,19 +1902,67 @@ int SQLiteSingleVerRelationalStorageExecutor::GetLockStatusByGid(const std::stri } int SQLiteSingleVerRelationalStorageExecutor::UpdateHashKey(DistributedTableMode mode, const TableInfo &tableInfo, - TableSyncType syncType) + TableSyncType syncType, const std::string &localIdentity) { - auto tableManager = LogTableManagerFactory::GetTableManager(mode, syncType); + if (tableInfo.GetIdentifyKey().size() == 1u && tableInfo.GetIdentifyKey().at(0) == "rowid") { + return UpdateHashKeyWithOutPk(mode, tableInfo, syncType, localIdentity); + } + auto tableManager = LogTableManagerFactory::GetTableManager(tableInfo, mode, syncType); auto logName = DBCommon::GetLogTableName(tableInfo.GetTableName()); - std::string sql = "UPDATE " + logName + " SET hash_key = hash_key || '_old' where data_key in " + - "(select _rowid_ from '" + tableInfo.GetTableName() + "');"; + std::string sql = "UPDATE OR REPLACE " + logName + " SET hash_key = hash_key || '_old' where data_key in " + + "(select _rowid_ from '" + tableInfo.GetTableName() + "') AND device = '';"; int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); if (errCode != E_OK) { return errCode; } - sql = "UPDATE " + logName + " SET hash_key = data.hash_value FROM (SELECT _rowid_, " + + sql = "UPDATE OR REPLACE " + logName + " SET hash_key = data.hash_value FROM (SELECT _rowid_, " + tableManager->CalcPrimaryKeyHash("dataTable.", tableInfo, "") + " AS hash_value " + - "FROM '" + tableInfo.GetTableName() + "' AS dataTable) AS data WHERE data._rowid_ = " + logName + ".data_key;"; + "FROM '" + tableInfo.GetTableName() + "' AS dataTable) AS data WHERE data._rowid_ = " + logName + + ".data_key AND device = '';"; + return SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); +} + +int SQLiteSingleVerRelationalStorageExecutor::UpdateHashKeyWithOutPk( + DistributedTableMode mode, const TableInfo &tableInfo, TableSyncType syncType, const std::string &localIdentity) +{ + auto tableManager = LogTableManagerFactory::GetTableManager(tableInfo, mode, syncType); + auto logName = DBCommon::GetLogTableName(tableInfo.GetTableName()); + std::string extendStr = "_tmp"; + std::string tmpTable = logName + extendStr; + std::string sql = tableManager->GetCreateRelationalLogTableSql(tableInfo, extendStr); + int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + if (errCode != E_OK) { + return errCode; + } + sql = "INSERT OR REPLACE INTO " + tmpTable + " SELECT * FROM " + logName + " WHERE data_key != -1;"; + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + if (errCode != E_OK) { + return errCode; + } + + sql = "UPDATE " + logName + " SET flag = flag | 0x01, data_key = -1 WHERE data_key IN " + "(SELECT _rowid_ FROM '" + + tableInfo.GetTableName() + "');"; + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + if (errCode != E_OK) { + return errCode; + } + + sql = "UPDATE " + tmpTable + " SET hash_key = data.hash_value FROM (SELECT _rowid_, " + + tableManager->CalcPrimaryKeyHash("dataTable.", tableInfo, localIdentity) + " AS hash_value " + "FROM '" + + tableInfo.GetTableName() + "' AS dataTable) AS data WHERE data._rowid_ = " + tmpTable + + ".data_key AND device = '';"; + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + if (errCode != E_OK) { + return errCode; + } + + sql = "INSERT OR REPLACE INTO " + logName + " SELECT * FROM " + tmpTable + ";"; + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + if (errCode != E_OK) { + return errCode; + } + + sql = "DROP TABLE " + tmpTable + ";"; return SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.h index 8acac8e9..c4287638 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.h @@ -80,6 +80,7 @@ public: // operation of meta data int GetKvData(const Key &key, Value &value) const; + int GetKvDataByPrefixKey(const Key &keyPrefix, std::map &data) const; int PutKvData(const Key &key, const Value &value) const; int DeleteMetaData(const std::vector &keys) const; int DeleteMetaDataByPrefixKey(const Key &keyPrefix) const; @@ -225,7 +226,7 @@ public: void SetUploadConfig(int32_t maxUploadCount, int32_t maxUploadSize); - int InitCursorToMeta(const std::string &tableName); + int InitCursorToMeta(const std::string &tableName) const; void SetTableSchema(const TableSchema &tableSchema); @@ -235,10 +236,12 @@ public: int GetCloudDataCount(const std::string &tableName, DownloadData &downloadData, int64_t &count); - int UpdateExtendField(const std::string &tableName, const std::set &extendColNames); + int UpdateExtendField(const std::string &tableName, const std::set &extendColNames, + const std::string &condition = ""); int UpdateDeleteDataExtendField(const std::string &tableName, const std::string &lowVersionExtendColName, const std::set &oldExtendColNames, const std::set &extendColNames); + int GetDownloadingAssetsCount(const TableSchema &tableSchema, int32_t &totalCount); int GetDownloadingCount(const std::string &tableName, int32_t &count); @@ -261,10 +264,22 @@ public: int CompareSchemaTableColumns(const std::string &tableName); - int UpdateHashKey(DistributedTableMode mode, const TableInfo &tableInfo, TableSyncType syncType); + int UpdateHashKey(DistributedTableMode mode, const TableInfo &tableInfo, TableSyncType syncType, + const std::string &localIdentity); void SetTableMode(DistributedTableMode mode); + + int GetFlagIsLocalCount(const std::string &logTableName, int32_t &count); + + void ClearLogOfMismatchedData(const std::string &tableName); + + int IsTableOnceDropped(const std::string &tableName, bool &onceDropped); + + void RecoverNullExtendLog(const TrackerSchema &trackerSchema, const TrackerTable &table); private: + int UpdateHashKeyWithOutPk(DistributedTableMode mode, const TableInfo &tableInfo, TableSyncType syncType, + const std::string &localIdentity); + int DoCleanLogs(const std::vector &tableNameList, const RelationalSchemaObject &localSchema); int DoCleanLogAndData(const std::vector &tableNameList, @@ -329,9 +344,6 @@ private: int GeneLogInfoForExistedData(sqlite3 *db, const std::string &identity, const TableInfo &tableInfo, std::unique_ptr &logMgrPtr, bool isTrackerTable); - int GeneLogInfoForExistedDataInner(sqlite3 *db, const std::string &identity, const TableInfo &tableInfo, - std::unique_ptr &logMgrPtr, bool isTrackerTable); - int CleanExtendAndCursorForDeleteData(const std::string &tableName); int GetCloudDataForSync(const CloudUploadRecorder &uploadRecorder, sqlite3_stmt *statement, @@ -418,8 +430,6 @@ private: int DeleteCloudData(const std::string &tableName, const VBucket &vBucket, const TableSchema &tableSchema, const TrackerTable &trackerTable); - int IsTableOnceDropped(const std::string &tableName, bool &onceDropped); - int OnlyUpdateLogTable(const VBucket &vBucket, const TableSchema &tableSchema, OpType opType); int BindUpdateVersionStatement(const VBucket &vBucket, const Bytes &hashKey, sqlite3_stmt *&stmt); @@ -526,6 +536,8 @@ private: bool AbortGetDownloadAssetGidIfNeed(const TableSchema &tableSchema, const std::string &gid, bool abortWithLimit, uint32_t &count); + int RecoverNullExtendLogInner(const TrackerSchema &trackerSchema, const TrackerTable &table); + static constexpr const char *CONSISTENT_FLAG = "0x20"; static constexpr const char *UPDATE_FLAG_CLOUD = "flag = 0"; static constexpr const char *UPDATE_FLAG_WAIT_COMPENSATED_SYNC = "flag = flag | 0x10"; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor_extend.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor_extend.cpp index 007fe7e5..e429a600 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor_extend.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor_extend.cpp @@ -369,11 +369,18 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanLogs(const std::vector &extendColNames) + const std::set &extendColNames, const std::string &condition) { bool isLogTableExist = false; int errCode = SQLiteUtils::CheckTableExists(dbHandle_, DBCommon::GetLogTableName(tableName), isLogTableExist); @@ -1822,6 +1820,7 @@ int SQLiteSingleVerRelationalStorageExecutor::UpdateExtendField(const std::strin } sql.pop_back(); sql += ") from " + tableName + " as data where log.data_key = data." + std::string(DBConstant::SQLITE_INNER_ROWID); + sql += condition; sqlite3_stmt *stmt = nullptr; errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); if (errCode != E_OK) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp index 73cb0655..dad09030 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp @@ -418,8 +418,8 @@ int SQLiteSingleVerRelationalStorageExecutor::GetOrInitTrackerSchemaFromMeta(Rel if (!schema.ToSchemaString().empty()) { return E_OK; } - const Key schemaKey(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.begin(), - DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.end()); + const Key schemaKey(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY, + DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY + strlen(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY)); Value schemaVal; int errCode = GetKvData(schemaKey, schemaVal); // save schema to meta_data if (errCode != E_OK) { @@ -480,7 +480,8 @@ int SQLiteSingleVerRelationalStorageExecutor::GetClearWaterMarkTables( const std::vector &tableReferenceProperty, const RelationalSchemaObject &schema, std::set &clearWaterMarkTables) { - std::set changeTables = schema.CompareReferenceProperty(tableReferenceProperty); + bool isRefNotSet = false; + std::set changeTables = schema.CompareReferenceProperty(tableReferenceProperty, isRefNotSet); for (const auto &table : changeTables) { std::string logTableName = DBCommon::GetLogTableName(table); bool isExists = false; @@ -505,8 +506,10 @@ int SQLiteSingleVerRelationalStorageExecutor::GetClearWaterMarkTables( clearWaterMarkTables.insert(table); } } - LOGI("[GetClearWaterMarkTables] clearWaterMarkTables size = %zu.", clearWaterMarkTables.size()); - return E_OK; + LOGI("[GetClearWaterMarkTables] clearWaterMarkTables size = %zu, changeTables size = %zu, isFirst:%d.", + clearWaterMarkTables.size(), changeTables.size(), isRefNotSet); + // If reference set for the first time and has no data, or the reference has not changed, return E_OK. + return ((isRefNotSet && clearWaterMarkTables.empty()) || changeTables.empty()) ? E_OK : -E_TABLE_REFERENCE_CHANGED; } int SQLiteSingleVerRelationalStorageExecutor::UpgradedLogForExistedData(const TableInfo &tableInfo, bool schemaChanged) @@ -614,34 +617,7 @@ int SQLiteSingleVerRelationalStorageExecutor::ClearAllTempSyncTrigger() int SQLiteSingleVerRelationalStorageExecutor::CleanTrackerData(const std::string &tableName, int64_t cursor, bool isOnlyTrackTable) { - std::string sql; - if (isOnlyTrackTable) { - sql = "DELETE FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log"; - } else { - sql = "UPDATE " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log SET extend_field = NULL"; - } - sql += " where data_key = -1 and cursor <= ?;"; - sqlite3_stmt *statement = nullptr; - int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, statement); - if (errCode != E_OK) { // LCOV_EXCL_BR_LINE - LOGE("get clean tracker data stmt failed %d.", errCode); - return errCode; - } - errCode = SQLiteUtils::BindInt64ToStatement(statement, 1, cursor); - int ret = E_OK; - if (errCode != E_OK) { // LCOV_EXCL_BR_LINE - LOGE("bind clean tracker data stmt failed %d.", errCode); - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode; - } - errCode = SQLiteUtils::StepWithRetry(statement); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { // LCOV_EXCL_BR_LINE - errCode = E_OK; - } else { - LOGE("clean tracker step failed: %d.", errCode); - } - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode == E_OK ? ret : errCode; + return SQLiteRelationalUtils::CleanTrackerData(dbHandle_, tableName, cursor, isOnlyTrackTable); } int SQLiteSingleVerRelationalStorageExecutor::CreateSharedTable(const TableSchema &tableSchema) @@ -774,8 +750,12 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanShareTableDataAndLog(const { int errCode = E_OK; for (const auto &tableName: tableNameList) { + int32_t count = 0; + std::string logTableName = DBCommon::GetLogTableName(tableName); + (void)GetFlagIsLocalCount(logTableName, count); + LOGI("[DoCleanShareTableDataAndLog]flag is local in table:%s, len:%zu, count:%d, before remove device data.", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), count); if (isLogicDelete_) { - std::string logTableName = DBCommon::GetLogTableName(tableName); errCode = SetDataOnShareTableWithLogicDelete(tableName, logTableName); } else { errCode = CleanShareTable(tableName); @@ -785,6 +765,9 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanShareTableDataAndLog(const DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), isLogicDelete_ ? 1 : 0, errCode); return errCode; } + (void)GetFlagIsLocalCount(logTableName, count); + LOGI("[DoCleanShareTableDataAndLog]flag is local in table:%s, len:%zu, count:%d, after remove device data.", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), count); } return errCode; } @@ -1144,7 +1127,7 @@ int SQLiteSingleVerRelationalStorageExecutor::BindStmtWithCloudGidInner(const st int SQLiteSingleVerRelationalStorageExecutor::RenewTableTrigger(DistributedTableMode mode, const TableInfo &tableInfo, TableSyncType syncType, const std::string &localIdentity) { - auto tableManager = LogTableManagerFactory::GetTableManager(mode, syncType); + auto tableManager = LogTableManagerFactory::GetTableManager(tableInfo, mode, syncType); return tableManager->AddRelationalLogTableTrigger(dbHandle_, tableInfo, localIdentity); } @@ -1850,6 +1833,10 @@ void SQLiteSingleVerRelationalStorageExecutor::MarkFlagAsUploadFinished(const st sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(dbHandle_, CloudStorageUtils::GetUpdateUploadFinishedSql(tableName, isExistAssetsDownload), stmt); + if (errCode != E_OK) { + LOGW("[Storage Executor] Get statement fail! errCode:%d", errCode); + return; + } int index = 1; errCode = SQLiteUtils::BindInt64ToStatement(stmt, index++, timestamp); if (errCode != E_OK) { @@ -2005,5 +1992,106 @@ void SQLiteSingleVerRelationalStorageExecutor::CheckAndCreateTrigger(const Table auto tableManager = std::make_unique(); tableManager->CheckAndCreateTrigger(dbHandle_, table, ""); } + +void SQLiteSingleVerRelationalStorageExecutor::ClearLogOfMismatchedData(const std::string &tableName) +{ + bool isLogTableExist = false; + int errCode = SQLiteUtils::CheckTableExists(dbHandle_, DBCommon::GetLogTableName(tableName), isLogTableExist); + if (!isLogTableExist) { + return; + } + std::string sql = "SELECT data_key from " + DBCommon::GetLogTableName(tableName) + " WHERE data_key NOT IN " + + "(SELECT _rowid_ FROM " + tableName + ") AND data_key != -1"; + sqlite3_stmt *stmt = nullptr; + errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); + if (errCode != E_OK) { + LOGW("[RDBExecutor][ClearMisLog] Get stmt failed, %d", errCode); + return; + } + std::vector dataKeys; + std::string misDataKeys = "("; + errCode = SQLiteUtils::StepWithRetry(stmt, false); + while (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + int dataKey = sqlite3_column_int64(stmt, 0); + dataKeys.push_back(dataKey); + misDataKeys += std::to_string(dataKey) + ","; + errCode = SQLiteUtils::StepWithRetry(stmt, false); + } + SQLiteUtils::ResetStatement(stmt, true, errCode); + stmt = nullptr; + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + LOGW("[RDBExecutor][ClearMisLog] Step failed. %d", errCode); + return; + } + if (dataKeys.empty()) { + return; + } + misDataKeys.pop_back(); + misDataKeys += ")"; + LOGW("[RDBExecutor][ClearMisLog] Mismatched:%s", misDataKeys.c_str()); + std::string delSql = "DELETE FROM " + DBCommon::GetLogTableName(tableName) + " WHERE data_key IN " + misDataKeys; + errCode = SQLiteUtils::GetStatement(dbHandle_, delSql, stmt); + if (errCode != E_OK) { + LOGW("[RDBExecutor][ClearMisLog] Get del stmt failed, %d", errCode); + return; + } + errCode = SQLiteUtils::StepWithRetry(stmt, false); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + LOGW("[RDBExecutor][ClearMisLog] Step del failed, %d", errCode); + } + SQLiteUtils::ResetStatement(stmt, true, errCode); +} + +void SQLiteSingleVerRelationalStorageExecutor::RecoverNullExtendLog(const TrackerSchema &trackerSchema, + const TrackerTable &table) +{ + if (trackerSchema.extendColNames.empty()) { + return; + } + std::string sql = "SELECT COUNT(1) FROM " + DBCommon::GetLogTableName(trackerSchema.tableName) + + " WHERE (json_valid(extend_field) = 0 OR json_type(extend_field) IS NOT 'object') AND data_key != -1"; + if (!SQLiteRelationalUtils::ExecuteCheckSql(dbHandle_, sql).second) { + return; + } + auto errCode = SQLiteUtils::BeginTransaction(dbHandle_, TransactType::IMMEDIATE); + if (errCode != E_OK) { + LOGE("[RDBExecutor][RecoverTracker] Begin transaction fail %d", errCode); + return; + } + errCode = RecoverNullExtendLogInner(trackerSchema, table); + int changeRow = 0; + if (errCode == E_OK) { + changeRow = sqlite3_changes(dbHandle_); + errCode = SQLiteUtils::CommitTransaction(dbHandle_); + } else { + (void)SQLiteUtils::RollbackTransaction(dbHandle_); + } + LOGI("[RDBExecutor][RecoverTracker] Recover tracker[%s][%zu] finished[%d] changeRow[%d]", + DBCommon::StringMiddleMasking(trackerSchema.tableName).c_str(), trackerSchema.tableName.size(), + errCode, changeRow); +} + +int SQLiteSingleVerRelationalStorageExecutor::RecoverNullExtendLogInner(const TrackerSchema &trackerSchema, + const TrackerTable &table) +{ + std::vector> actions; + actions.emplace_back([this]() { + return SetLogTriggerStatus(false); + }); + actions.emplace_back([this, &table]() { + return SQLiteUtils::ExecuteRawSQL(dbHandle_, table.GetTempUpdateLogCursorTriggerSql()); + }); + actions.emplace_back([this, &trackerSchema]() { + return UpdateExtendField(trackerSchema.tableName, trackerSchema.extendColNames, + " AND (json_valid(log.extend_field) = 0 OR json_type(log.extend_field) IS NOT 'object')"); + }); + actions.emplace_back([this]() { + return ClearAllTempSyncTrigger(); + }); + actions.emplace_back([this]() { + return SetLogTriggerStatus(true); + }); + return SQLiteRelationalUtils::ExecuteListAction(actions); +} } // namespace DistributedDB #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.cpp index 5569bfa9..f384da23 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.cpp @@ -50,11 +50,8 @@ int SqliteCloudKvExecutorUtils::GetCloudData(const CloudSyncConfig &config, cons } while (errCode == E_OK); LOGI("[SqliteCloudKvExecutorUtils] Get cloud sync data, insData:%u, upData:%u, delLog:%u errCode:%d total:%" PRIu32, data.insData.record.size(), data.updData.record.size(), data.delData.extend.size(), errCode, totalSize); - if (errCode != -E_UNFINISHED) { - token.ReleaseCloudQueryStmt(); - } else if (isMemory && UpdateBeginTimeForMemoryDB(token, data)) { - token.ReleaseCloudQueryStmt(); - } + UpdateBeginTime(token, data); + token.ReleaseCloudQueryStmt(); return errCode; } @@ -73,7 +70,7 @@ Timestamp SqliteCloudKvExecutorUtils::GetMaxTimeStamp(const std::vector return maxTimeStamp; } -bool SqliteCloudKvExecutorUtils::UpdateBeginTimeForMemoryDB(SQLiteSingleVerContinueToken &token, +void SqliteCloudKvExecutorUtils::UpdateBeginTime(SQLiteSingleVerContinueToken &token, const CloudSyncData &data) { Timestamp maxTimeStamp = 0; @@ -93,10 +90,9 @@ bool SqliteCloudKvExecutorUtils::UpdateBeginTimeForMemoryDB(SQLiteSingleVerConti } if (maxTimeStamp > token.GetQueryBeginTime()) { token.SetNextBeginTime("", maxTimeStamp); - return true; + return; } - LOGW("[SqliteCloudKvExecutorUtils] The start time of the in memory database has not been updated."); - return false; + LOGW("[SqliteCloudKvExecutorUtils] The start time of the database has not been updated."); } int SqliteCloudKvExecutorUtils::GetCloudDataForSync(const CloudSyncConfig &config, const CloudUploadRecorder &recorder, @@ -817,6 +813,20 @@ int SqliteCloudKvExecutorUtils::BindSyncDataStmt(sqlite3_stmt *dataStmt, const D return errCode; } +int64_t SqliteCloudKvExecutorUtils::GetModifyTime(int64_t timestamp) +{ + uint64_t curTime = 0; + int64_t modifyTime = timestamp; + if (TimeHelper::GetSysCurrentRawTime(curTime) == E_OK) { + if (curTime < static_cast(INT64_MAX)) { + if (modifyTime > static_cast(curTime)) { + modifyTime = static_cast(curTime); + } + } + } + return modifyTime; +} + int SqliteCloudKvExecutorUtils::BindCloudDataStmt(sqlite3_stmt *dataStmt, const DataItem &dataItem, int &index) { int errCode = SQLiteUtils::BindInt64ToStatement(dataStmt, index++, dataItem.modifyTime); @@ -922,6 +932,9 @@ int SqliteCloudKvExecutorUtils::FillCloudGid(const FillGidParam ¶m, const Cl auto [db, ignoreEmptyGid] = param; sqlite3_stmt *logStmt = nullptr; int errCode = SQLiteUtils::GetStatement(db, GetOperateLogSql(TransToOpType(type)), logStmt); + if (errCode != E_OK) { + return errCode; + } ResFinalizer finalizerData([logStmt]() { sqlite3_stmt *statement = logStmt; int ret = E_OK; @@ -960,10 +973,9 @@ int SqliteCloudKvExecutorUtils::FillCloudGid(const FillGidParam ¶m, const Cl SQLiteUtils::ResetStatement(logStmt, false, errCode); MarkUploadSuccess(param, data, user, i); // ignored version record - if (i >= data.timestamp.size()) { - continue; + if (i < data.timestamp.size()) { + recorder.RecordUploadRecord(CloudDbConstant::CLOUD_KV_TABLE_NAME, data.hashKey[i], type, data.timestamp[i]); } - recorder.RecordUploadRecord(CloudDbConstant::CLOUD_KV_TABLE_NAME, data.hashKey[i], type, data.timestamp[i]); } return E_OK; } @@ -1029,9 +1041,11 @@ int SqliteCloudKvExecutorUtils::BindUpdateTimestampStmt(sqlite3_stmt *dataStmt, LOGE("[SqliteCloudKvExecutorUtils] Bind timestamp failed %d", errCode); return errCode; } - errCode = SQLiteUtils::BindInt64ToStatement(dataStmt, currentBindIndex++, dataItem.modifyTime); + int64_t modifyTime = GetModifyTime(dataItem.modifyTime); + errCode = SQLiteUtils::BindInt64ToStatement(dataStmt, currentBindIndex++, modifyTime); if (errCode != E_OK) { LOGE("[SqliteCloudKvExecutorUtils] Bind modifyTime failed %d", errCode); + return errCode; } errCode = SQLiteUtils::BindBlobToStatement(dataStmt, currentBindIndex++, dataItem.hashKey); if (errCode != E_OK) { @@ -1069,8 +1083,9 @@ std::pair SqliteCloudKvExecutorUtils::GetDataItem(int index, Down if (dataItem.origDev == dev) { dataItem.origDev = ""; } - dataItem.timestamp = static_cast(static_cast(dataItem.modifyTime) + downloadData.timeOffset); - dataItem.writeTimestamp = dataItem.timestamp; // writeTimestamp is process conflict time + int64_t timestamp = GetModifyTime(dataItem.modifyTime); + dataItem.timestamp = static_cast(timestamp + downloadData.timeOffset); + dataItem.writeTimestamp = static_cast(timestamp); // writeTimestamp is process conflict time return res; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.h index ca747b65..d256c579 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.h @@ -61,6 +61,7 @@ public: static int QueryCloudGid(sqlite3 *db, bool isMemory, const std::string &user, const QuerySyncObject &querySyncObject, std::vector &cloudGid); + private: using UploadDetail = std::pair; static int GetCloudDataForSync(const CloudSyncConfig &config, const CloudUploadRecorder &recorder, @@ -156,10 +157,12 @@ private: static Timestamp GetMaxTimeStamp(const std::vector &dataExtend); - static bool UpdateBeginTimeForMemoryDB(SQLiteSingleVerContinueToken &token, const CloudSyncData &data); + static void UpdateBeginTime(SQLiteSingleVerContinueToken &token, const CloudSyncData &data); static int BindFillGidLogStmt(sqlite3_stmt *logStmt, const std::string &user, const DataItem &dataItem, const VBucket &uploadExtend, const CloudWaterType &type); + + static int64_t GetModifyTime(int64_t timestamp); private: static void MarkUploadSuccess(const FillGidParam ¶m, const CloudSyncBatch &data, const std::string &user, size_t dataIndex); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.cpp index 25e473f2..ecdf5a42 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.cpp @@ -86,8 +86,11 @@ int SqliteCloudKvStore::GetCloudTableSchema(const TableName &tableName, return -E_NOT_FOUND; } -int SqliteCloudKvStore::StartTransaction(TransactType type) +int SqliteCloudKvStore::StartTransaction(TransactType type, bool isAsyncDownload) { + if (isAsyncDownload) { + return StartTransactionForAsyncDownload(type); + } { std::lock_guard autoLock(transactionMutex_); if (transactionHandle_ != nullptr) { @@ -110,8 +113,11 @@ int SqliteCloudKvStore::StartTransaction(TransactType type) return errCode; } -int SqliteCloudKvStore::Commit() +int SqliteCloudKvStore::Commit(bool isAsyncDownload) { + if (isAsyncDownload) { + return CommitForAsyncDownload(); + } SQLiteSingleVerStorageExecutor *handle; { std::lock_guard autoLock(transactionMutex_); @@ -128,8 +134,11 @@ int SqliteCloudKvStore::Commit() return errCode; } -int SqliteCloudKvStore::Rollback() +int SqliteCloudKvStore::Rollback(bool isAsyncDownload) { + if (isAsyncDownload) { + return RollbackForAsyncDownload(); + } SQLiteSingleVerStorageExecutor *handle; { std::lock_guard autoLock(transactionMutex_); @@ -146,18 +155,81 @@ int SqliteCloudKvStore::Rollback() return errCode; } +int SqliteCloudKvStore::StartTransactionForAsyncDownload(TransactType type) +{ + { + std::lock_guard autoLock(transactionMutex_); + if (asyncDownloadTransactionHandle_ != nullptr) { + LOGW("[SqliteCloudKvStore] async download transaction has been started"); + return E_OK; + } + } + auto [errCode, handle] = storageHandle_->GetStorageExecutor(type == TransactType::IMMEDIATE); + if (errCode != E_OK) { + return errCode; + } + if (handle == nullptr) { + LOGE("[SqliteCloudKvStore] get handle return null"); + return -E_INTERNAL_ERROR; + } + errCode = handle->StartTransaction(type); + std::lock_guard autoLock(transactionMutex_); + asyncDownloadTransactionHandle_ = handle; + LOGD("[SqliteCloudKvStore] start async download transaction!"); + return errCode; +} + +int SqliteCloudKvStore::CommitForAsyncDownload() +{ + SQLiteSingleVerStorageExecutor *handle; + { + std::lock_guard autoLock(transactionMutex_); + if (asyncDownloadTransactionHandle_ == nullptr) { + LOGW("[SqliteCloudKvStore] no need to commit, transaction has not been started"); + return E_OK; + } + handle = asyncDownloadTransactionHandle_; + asyncDownloadTransactionHandle_ = nullptr; + } + int errCode = handle->Commit(); + storageHandle_->RecycleStorageExecutor(handle); + LOGD("[SqliteCloudKvStore] commit transaction!"); + return errCode; +} + +int SqliteCloudKvStore::RollbackForAsyncDownload() +{ + SQLiteSingleVerStorageExecutor *handle; + { + std::lock_guard autoLock(transactionMutex_); + if (asyncDownloadTransactionHandle_ == nullptr) { + LOGW("[SqliteCloudKvStore] no need to rollback, transaction has not been started"); + return E_OK; + } + handle = asyncDownloadTransactionHandle_; + asyncDownloadTransactionHandle_ = nullptr; + } + int errCode = handle->Rollback(); + storageHandle_->RecycleStorageExecutor(handle); + LOGD("[SqliteCloudKvStore] rollback transaction!"); + return errCode; +} + int SqliteCloudKvStore::GetUploadCount([[gnu::unused]] const QuerySyncObject &query, const Timestamp ×tamp, bool isCloudForcePush, [[gnu::unused]] bool isCompensatedTask, int64_t &count) { - auto [db, isMemory] = GetTransactionDbHandleAndMemoryStatus(); - if (db == nullptr) { + auto [db, handle] = GetTransactionDbHandleAndMemoryStatus(false); + if (db == nullptr || handle == nullptr) { LOGE("[SqliteCloudKvStore] get upload count without transaction"); return -E_INTERNAL_ERROR; } int errCode = E_OK; - std::tie(errCode, count) = SqliteCloudKvExecutorUtils::CountCloudData(db, isMemory, timestamp, user_, + std::tie(errCode, count) = SqliteCloudKvExecutorUtils::CountCloudData(db, handle->IsMemory(), timestamp, user_, isCloudForcePush); + if (transactionHandle_ == nullptr) { + storageHandle_->RecycleStorageExecutor(handle); + } return errCode; } @@ -165,15 +237,18 @@ int SqliteCloudKvStore::GetAllUploadCount(const QuerySyncObject &query, const std::vector ×tampVec, bool isCloudForcePush, [[gnu::unused]] bool isCompensatedTask, int64_t &count) { - auto [db, isMemory] = GetTransactionDbHandleAndMemoryStatus(); - if (db == nullptr) { + auto [db, handle] = GetTransactionDbHandleAndMemoryStatus(false); + if (db == nullptr || handle == nullptr) { LOGE("[SqliteCloudKvStore] get upload count without transaction"); return -E_INTERNAL_ERROR; } int errCode = E_OK; QuerySyncObject queryObj = query; - std::tie(errCode, count) = SqliteCloudKvExecutorUtils::CountAllCloudData({ db, isMemory }, timestampVec, user_, - isCloudForcePush, queryObj); + std::tie(errCode, count) = SqliteCloudKvExecutorUtils::CountAllCloudData( + {db, handle->IsMemory()}, timestampVec, user_, isCloudForcePush, queryObj); + if (transactionHandle_ == nullptr) { + storageHandle_->RecycleStorageExecutor(handle); + } return errCode; } @@ -205,14 +280,17 @@ int SqliteCloudKvStore::GetCloudDataNext(ContinueToken &continueStmtToken, Cloud LOGE("[SqliteCloudKvStore] token is invalid"); return -E_INVALID_ARGS; } - auto [db, isMemory] = GetTransactionDbHandleAndMemoryStatus(); - if (db == nullptr) { + auto [db, handle] = GetTransactionDbHandleAndMemoryStatus(false); + if (db == nullptr || handle == nullptr) { LOGE("[SqliteCloudKvStore] the transaction has not been started, release the token"); ReleaseCloudDataToken(continueStmtToken); return -E_INTERNAL_ERROR; } - int errCode = SqliteCloudKvExecutorUtils::GetCloudData(GetCloudSyncConfig(), {db, isMemory}, recorder_, *token, - cloudDataResult); + int errCode = SqliteCloudKvExecutorUtils::GetCloudData( + GetCloudSyncConfig(), {db, handle->IsMemory()}, recorder_, *token, cloudDataResult); + if (transactionHandle_ == nullptr) { + storageHandle_->RecycleStorageExecutor(handle); + } if (errCode != -E_UNFINISHED) { ReleaseCloudDataToken(continueStmtToken); } else { @@ -239,25 +317,32 @@ int SqliteCloudKvStore::ReleaseCloudDataToken(ContinueToken &continueStmtToken) int SqliteCloudKvStore::GetInfoByPrimaryKeyOrGid([[gnu::unused]] const std::string &tableName, const VBucket &vBucket, DataInfoWithLog &dataInfoWithLog, [[gnu::unused]] VBucket &assetInfo) { - auto [db, isMemory] = GetTransactionDbHandleAndMemoryStatus(); - if (db == nullptr) { + auto [db, handle] = GetTransactionDbHandleAndMemoryStatus(false); + if (db == nullptr || handle == nullptr) { LOGE("[SqliteCloudKvStore] the transaction has not been started"); return -E_INTERNAL_ERROR; } int errCode = E_OK; - std::tie(errCode, dataInfoWithLog) = SqliteCloudKvExecutorUtils::GetLogInfo(db, isMemory, vBucket, user_); + std::tie(errCode, dataInfoWithLog) = SqliteCloudKvExecutorUtils::GetLogInfo(db, handle->IsMemory(), vBucket, user_); + if (transactionHandle_ == nullptr) { + storageHandle_->RecycleStorageExecutor(handle); + } return errCode; } int SqliteCloudKvStore::PutCloudSyncData([[gnu::unused]] const std::string &tableName, DownloadData &downloadData) { - auto [db, isMemory] = GetTransactionDbHandleAndMemoryStatus(); - if (db == nullptr) { + auto [db, handle] = GetTransactionDbHandleAndMemoryStatus(true); + if (db == nullptr || handle == nullptr) { LOGE("[SqliteCloudKvStore] the transaction has not been started"); return -E_INTERNAL_ERROR; } downloadData.timeOffset = storageHandle_->GetLocalTimeOffsetForCloud(); - return SqliteCloudKvExecutorUtils::PutCloudData(db, isMemory, downloadData); + int ret = SqliteCloudKvExecutorUtils::PutCloudData(db, handle->IsMemory(), downloadData); + if (transactionHandle_ == nullptr) { + storageHandle_->RecycleStorageExecutor(handle); + } + return ret; } int SqliteCloudKvStore::UpdateAssetStatusForAssetOnly(const std::string &tableName, VBucket &asset) @@ -273,26 +358,11 @@ int SqliteCloudKvStore::FillCloudLogAndAsset(OpType opType, const CloudSyncData LOGE("[SqliteCloudKvStore] get handle failed %d when fill log", errCode); return errCode; } - if (handle->IsMemory()) { - errCode = Commit(); - if (errCode != E_OK) { - LOGE("[SqliteCloudKvStore] commit failed %d before fill log", errCode); - storageHandle_->RecycleStorageExecutor(handle); - return errCode; - } - } sqlite3 *db = nullptr; (void)handle->GetDbHandle(db); errCode = SqliteCloudKvExecutorUtils::FillCloudLog({db, ignoreEmptyGid}, opType, data, user_, recorder_); - int ret = E_OK; - if (handle->IsMemory()) { - ret = StartTransaction(TransactType::DEFERRED); - if (ret != E_OK) { - LOGE("[SqliteCloudKvStore] restart transaction failed %d", ret); - } - } storageHandle_->RecycleStorageExecutor(handle); - return errCode == E_OK ? ret : errCode; + return errCode; } void SqliteCloudKvStore::FilterCloudVersionPrefixKey(std::vector> &changeValList) @@ -421,15 +491,26 @@ void SqliteCloudKvStore::SetUser(const std::string &user) user_ = user; } -std::pair SqliteCloudKvStore::GetTransactionDbHandleAndMemoryStatus() +std::pair SqliteCloudKvStore::GetTransactionDbHandleAndMemoryStatus( + bool isWrite) { std::lock_guard autoLock(transactionMutex_); if (transactionHandle_ == nullptr) { - return {nullptr, false}; + if (storageHandle_ == nullptr) { + return {nullptr, nullptr}; + } + auto [errCode, handle] = storageHandle_->GetStorageExecutor(isWrite); + if (errCode != E_OK) { + LOGE("[SqliteCloudKvStore] get handle failed %d when fill log", errCode); + return {nullptr, nullptr}; + } + sqlite3 *db = nullptr; + (void)handle->GetDbHandle(db); + return {db, handle}; } sqlite3 *db = nullptr; (void)transactionHandle_->GetDbHandle(db); - return {db, transactionHandle_->IsMemory()}; + return {db, transactionHandle_}; } void SqliteCloudKvStore::RegisterObserverAction(const KvStoreObserver *observer, const ObserverAction &action) @@ -552,6 +633,8 @@ void SqliteCloudKvStore::SetCloudSyncConfig(const CloudSyncConfig &config) { std::lock_guard autoLock(configMutex_); config_ = config; + LOGI("[SqliteCloudKvStore] SetCloudSyncConfig value:[%" PRId32 ", %" PRId32 ", %" PRId32 ", %d]", + config_.maxUploadCount, config_.maxUploadSize, config_.maxRetryConflictTimes, config_.isSupportEncrypt); } CloudSyncConfig SqliteCloudKvStore::GetCloudSyncConfig() const diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.h index 2f3c98b1..9e0841d3 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.h @@ -37,11 +37,11 @@ public: int GetCloudTableSchema(const TableName &tableName, TableSchema &tableSchema) override; - int StartTransaction(TransactType type) override; + int StartTransaction(TransactType type, bool isAsyncDownload = false) override; - int Commit() override; + int Commit(bool isAsyncDownload = false) override; - int Rollback() override; + int Rollback(bool isAsyncDownload = false) override; int GetUploadCount(const QuerySyncObject &query, const Timestamp ×tamp, bool isCloudForcePush, bool isCompensatedTask, int64_t &count) override; @@ -124,7 +124,7 @@ public: int OperateDataStatus(uint32_t dataOperator); private: - std::pair GetTransactionDbHandleAndMemoryStatus(); + std::pair GetTransactionDbHandleAndMemoryStatus(bool isWrite); static void FillTimestamp(Timestamp rawSystemTime, Timestamp virtualTime, CloudSyncBatch &syncBatch); @@ -137,6 +137,12 @@ private: int OperateDataStatusInner(SQLiteSingleVerStorageExecutor *handle, const std::string ¤tVirtualTime, const std::string ¤tTime, uint32_t dataOperator); + int CommitForAsyncDownload(); + + int RollbackForAsyncDownload(); + + int StartTransactionForAsyncDownload(TransactType type); + KvStorageHandle *storageHandle_; std::mutex schemaMutex_; @@ -144,6 +150,7 @@ private: mutable std::mutex transactionMutex_; SQLiteSingleVerStorageExecutor *transactionHandle_; + SQLiteSingleVerStorageExecutor *asyncDownloadTransactionHandle_ = nullptr; std::string user_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp index edbd2681..b612ab10 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp @@ -18,7 +18,7 @@ namespace DistributedDB { namespace { - const int MAX_FIELD_NUM_IN_ONE_STATEMENT = 100; + const unsigned int MAX_FIELD_NUM_IN_ONE_STATEMENT = 100u; } int SqliteLogTableManager::AddRelationalLogTableTrigger(sqlite3 *db, const TableInfo &table, @@ -52,9 +52,9 @@ int SqliteLogTableManager::AddRelationalLogTableTrigger(sqlite3 *db, const Table return E_OK; } -int SqliteLogTableManager::CreateRelationalLogTable(sqlite3 *db, const TableInfo &table) +std::string SqliteLogTableManager::GetCreateRelationalLogTableSql(const TableInfo &table, const std::string &extendStr) { - const std::string tableName = GetLogTableName(table); + const std::string tableName = GetLogTableName(table) + extendStr; std::string primaryKey = GetPrimaryKeySql(table); std::string createTableSql = "CREATE TABLE IF NOT EXISTS " + tableName + "(" \ @@ -72,6 +72,12 @@ int SqliteLogTableManager::CreateRelationalLogTable(sqlite3 *db, const TableInfo "sharing_resource TEXT DEFAULT ''," + \ "status INT DEFAULT 0," + \ primaryKey + ");"; + return createTableSql; +} + +int SqliteLogTableManager::CreateRelationalLogTable(sqlite3 *db, const TableInfo &table) +{ + std::string createTableSql = GetCreateRelationalLogTableSql(table); std::vector logTableSchema; logTableSchema.emplace_back(createTableSql); GetIndexSql(table, logTableSchema); @@ -114,12 +120,12 @@ void SqliteLogTableManager::GetIndexSql(const TableInfo &table, std::vector &pk); protected: virtual void GetIndexSql(const TableInfo &table, std::vector &schema); std::string GetLogTableName(const TableInfo &table) const; @@ -48,8 +52,6 @@ protected: static std::string GetUpdateWithAssignSql(const TableInfo &table, const std::string &emptyValue, const std::string &matchValue, const std::string &missMatchValue); - - static std::string CalcPkHash(const std::string &references, const std::vector &pk); private: virtual std::string GetInsertTrigger(const TableInfo &table, const std::string &identity) = 0; virtual std::string GetUpdateTrigger(const TableInfo &table, const std::string &identity) = 0; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.cpp index e9f2e26b..612af826 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.cpp @@ -111,4 +111,45 @@ int SqliteMetaExecutor::GetExistsDevicesFromMeta(sqlite3 *dbHandle, MetaMode met } return errCode; } + +int SqliteMetaExecutor::GetMetaDataByPrefixKey(sqlite3 *dbHandle, bool isMemDb, const std::string &metaTableName, + const Key &keyPrefix, std::map &data) +{ + std::string sql = "SELECT key,value FROM " + metaTableName + " WHERE key >= ? AND key <= ?;"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(dbHandle, sql, statement); + if (errCode != E_OK) { + LOGE("[SqliteMetaExecutor][GetMetaDataByPrefixKey] Get statement failed:%d", errCode); + return errCode; + } + + errCode = SQLiteUtils::BindPrefixKey(statement, 1, keyPrefix); // 1 is first arg. + if (errCode != E_OK) { + LOGE("[SqliteMetaExecutor][GetMetaDataByPrefixKey] Bind prefix key failed:%d", errCode); + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } + do { + errCode = SQLiteUtils::StepWithRetry(statement, isMemDb); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + break; + } + Key key; + errCode = SQLiteUtils::GetColumnBlobValue(statement, 0, key); // 0 is key. + if (errCode != E_OK) { + LOGE("[SqliteMetaExecutor][GetMetaDataByPrefixKey] Get key failed:%d", errCode); + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } + Value value; + errCode = SQLiteUtils::GetColumnBlobValue(statement, 1, value); // 1 is value. + if (errCode != E_OK) { + LOGE("[SqliteMetaExecutor][GetMetaDataByPrefixKey] Get value failed:%d", errCode); + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); + } + data[key] = value; + } while (errCode == E_OK); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + } + return SQLiteUtils::ProcessStatementErrCode(statement, true, errCode); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.h index f2890e7b..0fcd3f35 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_meta_executor.h @@ -33,6 +33,9 @@ public: static int GetExistsDevicesFromMeta(sqlite3 *dbHandle, MetaMode metaMode, bool isMemDb, std::set &devices); + + static int GetMetaDataByPrefixKey(sqlite3 *dbHandle, bool isMemDb, const std::string &metaTableName, + const Key &keyPrefix, std::map &data); private: static constexpr const char *SELECT_ATTACH_META_KEYS_BY_PREFIX = "SELECT key FROM meta.meta_data where key like ?;"; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp index 1ca08459..3b96a982 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp @@ -15,6 +15,7 @@ #include "sqlite_query_helper.h" #include +#include #include "db_common.h" #include "db_constant.h" @@ -93,7 +94,9 @@ std::string GetSelectAndFromClauseForRDB(const std::string &tableName, const std std::string sql = "SELECT b.data_key," "b.device," "b.ori_device," - "b.timestamp as " + DBConstant::TIMESTAMP_ALIAS + "," + "b.timestamp as "; + sql.append(DBConstant::TIMESTAMP_ALIAS); + sql += "," "b.wtimestamp," "b.flag," "b.hash_key,"; @@ -106,13 +109,13 @@ std::string GetSelectAndFromClauseForRDB(const std::string &tableName, const std sql.pop_back(); } sql += " FROM '" + tableName + "' AS a INNER JOIN " + DBConstant::RELATIONAL_PREFIX + tableName + "_log AS b " - "ON a." + std::string(DBConstant::SQLITE_INNER_ROWID) + "=b.data_key "; + "ON a." + DBConstant::SQLITE_INNER_ROWID + "=b.data_key "; return sql; } std::string GetTimeRangeClauseForRDB() { - return " AND (" + DBConstant::TIMESTAMP_ALIAS + ">=? AND " + DBConstant::TIMESTAMP_ALIAS + "=? AND " + DBConstant::TIMESTAMP_ALIAS + " sql = GetSelectAndFromClauseForRDB(tableName_, fieldNames); sql += GetMissQueryFlagClauseForRDB(); sql += GetTimeRangeClauseForRDB(); - sql += "ORDER BY " + DBConstant::TIMESTAMP_ALIAS + " ASC;"; + sql += "ORDER BY "; + sql.append(DBConstant::TIMESTAMP_ALIAS); + sql += " ASC;"; return E_OK; } @@ -998,7 +1003,9 @@ std::string GetRelationalSyncDataQueryHeader(const std::vector &fie std::string sql = "SELECT b.data_key," "b.device," "b.ori_device," - "b.timestamp as " + DBConstant::TIMESTAMP_ALIAS + "," + "b.timestamp as "; + sql.append(DBConstant::TIMESTAMP_ALIAS); + sql += "," "b.wtimestamp," "b.flag," "b.hash_key,"; @@ -1018,7 +1025,9 @@ std::string GetRelationalCloudSyncDataQueryHeader(const std::vector &fiel std::string sql = "SELECT b.data_key," "b.device," "b.ori_device," - "b.timestamp as " + DBConstant::TIMESTAMP_ALIAS + "," + "b.timestamp as "; + sql.append(DBConstant::TIMESTAMP_ALIAS); + sql += "," "b.wtimestamp," "b.flag," "b.hash_key," @@ -1051,7 +1060,9 @@ int SqliteQueryHelper::GetRelationalSyncDataQuerySqlWithLimit(const std::vector< sql = GetRelationalSyncDataQueryHeader(fieldNames); sql += " FROM '" + tableName_ + "' AS a INNER JOIN "; sql += DBConstant::RELATIONAL_PREFIX + tableName_ + "_log"; - sql += " AS b ON (a." + std::string(DBConstant::SQLITE_INNER_ROWID) + " = b.data_key)"; + sql += " AS b ON (a."; + sql.append(DBConstant::SQLITE_INNER_ROWID); + sql += " = b.data_key)"; sql += " WHERE (b.flag&0x03=0x02)"; querySql_.clear(); // clear local query sql format diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp index 7476c791..81f825be 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp @@ -534,7 +534,10 @@ int SQLiteSingleVerNaturalStore::GetMetaData(const Key &key, Value &value) const int errCode = E_OK; SecurityOption option; - (void)GetSecurityOption(option); + errCode = GetSecurityOption(option); + if (errCode != E_OK) { + LOGW("Get security option failed when get meta data: %d", errCode); + } bool isWrite = (option.securityLabel >= S3) && (option.securityFlag == SECE); // meta in S3 SECE open meta.db, should use write handle auto handle = GetHandle(isWrite, errCode); @@ -549,6 +552,34 @@ int SQLiteSingleVerNaturalStore::GetMetaData(const Key &key, Value &value) const return errCode; } +int SQLiteSingleVerNaturalStore::GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const +{ + if (storageEngine_ == nullptr) { + return -E_INVALID_DB; + } + if (keyPrefix.size() > DBConstant::MAX_KEY_SIZE) { + return -E_INVALID_ARGS; + } + + int errCode = E_OK; + SecurityOption option; + errCode = GetSecurityOption(option); + if (errCode != E_OK) { + LOGW("Get security option failed when get meta data by prefix key: %d", errCode); + } + bool isWrite = (option.securityLabel >= S3) && (option.securityFlag == SECE); + // meta in S3 SECE open meta.db, should use write handle + auto handle = GetHandle(isWrite, errCode); + if (handle == nullptr) { + return errCode; + } + + errCode = handle->GetMetaDataByPrefixKey(keyPrefix, data); + ReleaseHandle(handle); + HeartBeatForLifeCycle(); + return errCode; +} + int SQLiteSingleVerNaturalStore::PutMetaData(const Key &key, const Value &value, bool isInTransaction) { (void)isInTransaction; @@ -1022,12 +1053,12 @@ int SQLiteSingleVerNaturalStore::RemoveDeviceData(const std::string &deviceName, errCode = removeFunc(); } else { #ifdef USE_DISTRIBUTEDDB_CLOUD - errCode = syncer->CleanKvCloudData(removeFunc); + errCode = syncer->StopSyncTask(removeFunc); DecObjRef(syncer); #endif } if (errCode != E_OK) { - LOGE("[SingleVerNStore] CleanKvCloudData with notify failed:%d", errCode); + LOGE("[SingleVerNStore] StopSyncTask with notify failed:%d", errCode); } return errCode; } @@ -1042,12 +1073,12 @@ int SQLiteSingleVerNaturalStore::RemoveDeviceData(const std::string &deviceName, errCode = removeFunc(); } else { #ifdef USE_DISTRIBUTEDDB_CLOUD - errCode = syncer->CleanKvCloudData(removeFunc); + errCode = syncer->StopSyncTask(removeFunc); DecObjRef(syncer); #endif } if (errCode != E_OK) { - LOGE("[SingleVerNStore] CleanKvCloudData with mode [%d] failed:%d", mode, errCode); + LOGE("[SingleVerNStore] StopSyncTask with mode [%d] failed:%d", mode, errCode); return errCode; } #ifdef USE_DISTRIBUTEDDB_CLOUD @@ -1071,12 +1102,12 @@ int SQLiteSingleVerNaturalStore::RemoveDeviceData(const std::string &deviceName, errCode = removeFunc(); } else { #ifdef USE_DISTRIBUTEDDB_CLOUD - errCode = syncer->CleanKvCloudData(removeFunc); + errCode = syncer->StopSyncTask(removeFunc); DecObjRef(syncer); #endif } if (errCode != E_OK) { - LOGE("[SingleVerNStore] CleanKvCloudData with user and mode [%d] failed:%d", mode, errCode); + LOGE("[SingleVerNStore] StopSyncTask with user and mode [%d] failed:%d", mode, errCode); return errCode; } #ifdef USE_DISTRIBUTEDDB_CLOUD @@ -1868,7 +1899,7 @@ int SQLiteSingleVerNaturalStore::GetKvDBSize(const KvDBProperties &properties, u std::string storeIdentDir; GenericKvDB::GetStoreDirectory(properties, KvDBProperties::SINGLE_VER_TYPE_SQLITE, storeIdentDir, storeOnlyIdentDir); - const std::vector> dbDir { + const std::vector> dbDir { {DBConstant::MAINDB_DIR, DBConstant::SINGLE_VER_DATA_STORE}, {DBConstant::METADB_DIR, DBConstant::SINGLE_VER_META_STORE}, {DBConstant::CACHEDB_DIR, DBConstant::SINGLE_VER_CACHE_STORE}}; @@ -1893,7 +1924,7 @@ void SQLiteSingleVerNaturalStore::AsyncDataMigration(SQLiteSingleVerStorageEngin std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_DELEGATE_CALLBACK_TIME)); bool isLocked = RuntimeContext::GetInstance()->IsAccessControlled(); if (!isLocked) { - LOGI("Begin to migrate cache data to manDb asynchronously!"); + LOGI("[AsyncDataMigration] Begin"); // we can't use engineMutex_ here, because ExecuteMigration will call GetHandle, it will lead to crash at // engineMutex_.lock_shared (void)StorageEngineManager::ExecuteMigration(storageEngine); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h index 9de2a68f..441f4ffb 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h @@ -65,6 +65,8 @@ public: int GetMetaData(const Key &key, Value &value) const override; + int GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const override; + int PutMetaData(const Key &key, const Value &value, bool isInTransaction) override; // Delete multiple meta data records in a transaction. @@ -229,6 +231,8 @@ public: int SetCloudSyncConfig(const CloudSyncConfig &config); + CloudSyncConfig GetCloudSyncConfig() const override; + uint64_t GetTimestampFromDB() override; // for test mock @@ -238,6 +242,11 @@ public: } int OperateDataStatus(uint32_t dataOperator); + +#ifdef USE_DISTRIBUTEDDB_CLOUD + int ClearCloudWatermark(); + std::function ClearCloudWatermarkInner(); +#endif protected: void AsyncDataMigration(SQLiteSingleVerStorageEngine *storageEngine) const; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp index d6f817e9..ec08451a 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp @@ -99,15 +99,18 @@ int SQLiteSingleVerNaturalStoreConnection::Get(const IOption &option, const Key } DBDfxAdapter::StartTracing(); - { - // need to check if the transaction started - std::lock_guard lock(transactionMutex_); - if (writeHandle_ != nullptr) { - LOGD("Transaction started already."); - Timestamp recordTimestamp; - errCode = writeHandle_->GetKvData(dataType, key, value, recordTimestamp); - DBDfxAdapter::FinishTracing(); - return errCode; + bool isInWhitelist = IsInWhitelist(); + // need to check if the transaction started + if (!isInWhitelist || (isInWhitelist && transactionExeFlag_.load())) { + { + std::lock_guard lock(transactionMutex_); + if (writeHandle_ != nullptr) { + LOGD("Transaction started already."); + Timestamp recordTimestamp; + errCode = writeHandle_->GetKvData(dataType, key, value, recordTimestamp); + DBDfxAdapter::FinishTracing(); + return errCode; + } } } @@ -324,13 +327,7 @@ int SQLiteSingleVerNaturalStoreConnection::Pragma(int cmd, void *parameter) int errCode = E_OK; switch (cmd) { case PRAGMA_RM_DEVICE_DATA: { - SQLiteSingleVerNaturalStore *naturalStore = GetDB(); - if (naturalStore == nullptr) { - return -E_INVALID_DB; - } - auto deviceName = static_cast(parameter); - errCode = naturalStore->RemoveDeviceData(*deviceName, false, false); - break; + return RemoveDeviceDataByCmd(parameter); } case PRAGMA_GET_IDENTIFIER_OF_DEVICE: { if (parameter == nullptr) { @@ -664,7 +661,7 @@ int SQLiteSingleVerNaturalStoreConnection::RegisterLifeCycleCallback(const Datab return static_cast(kvDB_)->RegisterLifeCycleCallback(notifier); } -int SQLiteSingleVerNaturalStoreConnection::PreClose() +int SQLiteSingleVerNaturalStoreConnection::PreClose(bool isCloseImmediately) { // check if result set closed { @@ -675,6 +672,14 @@ int SQLiteSingleVerNaturalStoreConnection::PreClose() } } + // check if sync task finish + if (!isCloseImmediately) { + int ret = kvDB_->PreClose(); + if (ret != E_OK) { + return ret; + } + } + // check if transaction closed { std::lock_guard transactionLock(transactionMutex_); @@ -1076,8 +1081,8 @@ int SQLiteSingleVerNaturalStoreConnection::SaveEntryNormally(DataItem &dataItem) if (maxTimestamp > currentMaxTimestamp_) { currentMaxTimestamp_ = maxTimestamp; } - } else { - LOGE("Save entry failed, err:%d", errCode); + } else if (errCode != -E_NOT_FOUND) { + LOGE("[Normal] Save err:%d", errCode); } return errCode; } @@ -2000,6 +2005,16 @@ int SQLiteSingleVerNaturalStoreConnection::SetCloudSyncConfig(const CloudSyncCon } return naturalStore->SetCloudSyncConfig(config); } + +int SQLiteSingleVerNaturalStoreConnection::ClearCloudWatermark() +{ + auto naturalStore = GetDB(); + if (naturalStore == nullptr) { + LOGE("[SingleVerConnection] DB is null when clear cloud watermark"); + return -E_INVALID_DB; + } + return naturalStore->ClearCloudWatermark(); +} #endif void SQLiteSingleVerNaturalStoreConnection::RecordTimeIntoDataItem(Timestamp existCreateTime, DataItem &dataItem, @@ -2062,5 +2077,25 @@ int SQLiteSingleVerNaturalStoreConnection::OperateDataStatus(uint32_t dataOperat } return naturalStore->OperateDataStatus(dataOperator); } + +int SQLiteSingleVerNaturalStoreConnection::RemoveDeviceDataByCmd(void *parameter) +{ + auto naturalStore = GetDB(); + if (naturalStore == nullptr || parameter == nullptr) { + return -E_INVALID_DB; + } + auto deviceName = static_cast(parameter); + return naturalStore->RemoveDeviceData(*deviceName, false, false); +} + +bool SQLiteSingleVerNaturalStoreConnection::IsInWhitelist() const +{ + if (kvDB_ == nullptr) { + return false; + } + + std::string appId = kvDB_->GetMyProperties().GetStringProp(DBProperties::APP_ID, ""); + return appId == DBConstant::DISTRIBUTED_DEFAULT_APP_ID; +} DEFINE_OBJECT_TAG_FACILITIES(SQLiteSingleVerNaturalStoreConnection) } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h index 1b6b3f03..1fd695ce 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h @@ -98,7 +98,7 @@ public: int RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier) override; // Called when Close and delete the connection. - int PreClose() override; + int PreClose(bool isCloseImmediately) override; int CheckIntegrity() const override; @@ -122,6 +122,8 @@ public: int GetCloudVersion(const std::string &device, std::map &versionMap) override; int SetCloudSyncConfig(const CloudSyncConfig &config) override; + + int ClearCloudWatermark() override; #endif int OperateDataStatus(uint32_t dataOperator) override; @@ -229,6 +231,10 @@ private: void RecordTimeIntoDataItem(Timestamp existCreateTime, DataItem &dataItem, SQLiteSingleVerNaturalStore &naturalStore); + int RemoveDeviceDataByCmd(void *parameter); + + bool IsInWhitelist() const; + DECLARE_OBJECT_TAG(SQLiteSingleVerNaturalStoreConnection); // ResultSet Related Info diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_extend.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_extend.cpp index ba52b0e0..75c1a244 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_extend.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_extend.cpp @@ -314,8 +314,8 @@ int SQLiteSingleVerNaturalStore::DeleteMetaDataByPrefixKey(const Key &keyPrefix) int SQLiteSingleVerNaturalStore::GetCompressionOption(bool &needCompressOnSync, uint8_t &compressionRate) const { - needCompressOnSync = GetDbProperties().GetBoolProp(KvDBProperties::COMPRESS_ON_SYNC, false); - compressionRate = GetDbProperties().GetIntProp(KvDBProperties::COMPRESSION_RATE, + needCompressOnSync = GetDbProperties().GetBoolProp(DBProperties::COMPRESS_ON_SYNC, false); + compressionRate = GetDbProperties().GetIntProp(DBProperties::COMPRESSION_RATE, DBConstant::DEFAULT_COMPTRESS_RATE); return E_OK; } @@ -427,14 +427,15 @@ int SQLiteSingleVerNaturalStore::AddSubscribe(const std::string &subscribeId, co int SQLiteSingleVerNaturalStore::SetMaxLogSize(uint64_t limit) { - LOGI("Set the max log size to %" PRIu64, limit); + if (maxLogSize_ != limit) { + LOGI("Set the max log size to %" PRIu64, limit); + } maxLogSize_.store(limit); return E_OK; } int SQLiteSingleVerNaturalStore::SetMaxValueSize(uint32_t maxValueSize) { - LOGI("Set the max value size to %" PRIu32, maxValueSize); storageEngine_->SetMaxValueSize(maxValueSize); return E_OK; } @@ -687,6 +688,17 @@ int SQLiteSingleVerNaturalStore::SetCloudSyncConfig(const CloudSyncConfig &confi return E_OK; } +CloudSyncConfig SQLiteSingleVerNaturalStore::GetCloudSyncConfig() const +{ + std::lock_guard autoLock(cloudStoreMutex_); + if (sqliteCloudKvStore_ == nullptr) { + LOGE("[SingleVerNStore] DB is null when get config"); + CloudSyncConfig config; + return config; + } + return sqliteCloudKvStore_->GetCloudSyncConfig(); +} + int SQLiteSingleVerNaturalStore::OperateDataStatus(uint32_t dataOperator) { std::lock_guard autoLock(cloudStoreMutex_); @@ -696,4 +708,55 @@ int SQLiteSingleVerNaturalStore::OperateDataStatus(uint32_t dataOperator) } return sqliteCloudKvStore_->OperateDataStatus(dataOperator); } + +#ifdef USE_DISTRIBUTEDDB_CLOUD +int SQLiteSingleVerNaturalStore::ClearCloudWatermark() +{ + auto syncer = GetAndIncCloudSyncer(); + if (syncer == nullptr) { + LOGE("[SingleVerNStore] Cloud syncer was not initialized"); + return -E_INVALID_DB; + } + auto clearFunc = ClearCloudWatermarkInner(); + int errCode = syncer->ClearCloudWatermark(clearFunc); + if (errCode != E_OK) { + LOGE("[SingleVerNStore] Clear cloud watermark failed: %d", errCode); + DecObjRef(syncer); + return errCode; + } + CleanAllWaterMark(); + DecObjRef(syncer); + return errCode; +} + +std::function SQLiteSingleVerNaturalStore::ClearCloudWatermarkInner() +{ + return [this]()->int { + int errCode = E_OK; + SQLiteSingleVerStorageExecutor *handle = GetHandle(true, errCode); + if (handle == nullptr) { + LOGE("[SingleVerNStore] get handle failed when clear cloud watermark:%d.", errCode); + return errCode; + } + errCode = handle->StartTransaction(TransactType::IMMEDIATE); + if (errCode != E_OK) { + LOGE("[SingleVerNStore] start transaction failed when clear cloud watermark:%d.", errCode); + ReleaseHandle(handle); + return errCode; + } + errCode = handle->ClearCloudWatermark(); + if (errCode != E_OK) { + LOGE("[SingleVerNStore] clear cloud watermark failed: %d", errCode); + (void)handle->Rollback(); + } else { + errCode = handle->Commit(); + if (errCode != E_OK) { + LOGE("[SingleVerNStore] transaction commit failed %d in RemoveDeviceData.", errCode); + } + } + ReleaseHandle(handle); + return errCode; + }; +} +#endif } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp index 01f68d75..9fbb18ba 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp @@ -569,7 +569,7 @@ StorageExecutor *SQLiteSingleVerStorageEngine::NewSQLiteStorageExecutor(sqlite3 return executor; } -int SQLiteSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, sqlite3 *&db) +int SQLiteSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, sqlite3 *&db, OpenDbProperties &option) { // Only could get the main database handle in the uninitialized and the main status. if (GetEngineState() != EngineState::INVALID && GetEngineState() != EngineState::MAINDB) { @@ -577,17 +577,18 @@ int SQLiteSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, sqlite3 *& return -E_EKEYREVOKED; } - if (!option_.isMemDb) { - option_.uri = GetDbDir(option_.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + + if (!option.isMemDb) { + option.uri = GetDbDir(option_.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; + SetUri(option.uri); } - OpenDbProperties optionTemp = option_; if (!isWrite) { - optionTemp.createIfNecessary = false; + option.createIfNecessary = false; + SetCreateIfNecessary(option.createIfNecessary); } - int errCode = SQLiteUtils::OpenDatabase(optionTemp, db); + int errCode = SQLiteUtils::OpenDatabase(option, db); if (errCode != E_OK) { if (errno == EKEYREVOKED) { LOGI("Failed to open the main database for key revoked[%d]", errCode); @@ -600,7 +601,7 @@ int SQLiteSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, sqlite3 *& // Set the engine state to main status for that the main database is valid. SetEngineState(EngineState::MAINDB); - if (OS::CheckPathExistence(GetDbDir(option_.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + + if (OS::CheckPathExistence(GetDbDir(option.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::DB_EXTENSION)) { // In status cacheDb crash errCode = AttachMainDbAndCacheDb(db, EngineState::MAINDB); @@ -616,15 +617,16 @@ int SQLiteSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, sqlite3 *& return errCode; } -int SQLiteSingleVerStorageEngine::GetDbHandle(bool isWrite, const SecurityOption &secOpt, sqlite3 *&dbHandle) +int SQLiteSingleVerStorageEngine::GetDbHandle(bool isWrite, sqlite3 *&dbHandle, OpenDbProperties &option) { - int errCode = TryToOpenMainDatabase(isWrite, dbHandle); - LOGD("Finish to open the main database, write[%d], label[%d], flag[%d], id[%.6s], errCode[%d]", isWrite, + int errCode = TryToOpenMainDatabase(isWrite, dbHandle, option); + const auto &secOpt = option.securityOpt; + LOGD("Finish to open the main database, write[%d], label[%d], flag[%d], id[%.6s], errCode[%d]", isWrite, secOpt.securityLabel, secOpt.securityFlag, hashIdentifier_.c_str(), errCode); if (!(ParamCheckUtils::IsS3SECEOpt(secOpt) && errCode == -E_EKEYREVOKED)) { return errCode; } - std::string cacheDbPath = GetDbDir(option_.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + + std::string cacheDbPath = GetDbDir(option.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::DB_EXTENSION; if (!isWrite || GetEngineState() != EngineState::INVALID || OS::CheckPathExistence(cacheDbPath)) { @@ -633,7 +635,7 @@ int SQLiteSingleVerStorageEngine::GetDbHandle(bool isWrite, const SecurityOption return -E_EKEYREVOKED; } - errCode = GetCacheDbHandle(dbHandle); + errCode = GetCacheDbHandle(dbHandle, option); if (errCode != E_OK) { LOGE("singleVerStorageEngine::GetDbHandle get cache handle fail! errCode = [%d]", errCode); return errCode; @@ -671,25 +673,23 @@ const std::string CREATE_CACHE_SYNC_TABLE_SQL = // Warning: Use error passwd create cache database can not check, it will create error passwd cache db, // And make migrate data failed! This cache db will not be open correctly. -int SQLiteSingleVerStorageEngine::GetCacheDbHandle(sqlite3 *&db) +int SQLiteSingleVerStorageEngine::GetCacheDbHandle(sqlite3 *&db, OpenDbProperties &option) { - option_.uri = GetDbDir(option_.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + + option.uri = GetDbDir(option.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::DB_EXTENSION; + SetUri(option.uri); // creatTable - option_.sqls = { - CacheDbSqls::CREATE_CACHE_LOCAL_TABLE_SQL, - CacheDbSqls::CREATE_CACHE_SYNC_TABLE_SQL - }; + option.sqls = {CacheDbSqls::CREATE_CACHE_LOCAL_TABLE_SQL, CacheDbSqls::CREATE_CACHE_SYNC_TABLE_SQL}; + SetSQL(option.sqls); - if (!option_.createIfNecessary) { - std::string mainDbPtah = GetDbDir(option_.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + + if (!option.createIfNecessary) { + std::string mainDbPath = GetDbDir(option.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; - if (!OS::CheckPathExistence(mainDbPtah)) { // Whether to create a cacheDb is based on whether the mainDb exists + if (!OS::CheckPathExistence(mainDbPath)) { // Whether to create a cacheDb is based on whether the mainDb exists return -E_INVALID_DB; } } - OpenDbProperties option = option_; // copy for no change it option.createIfNecessary = true; int errCode = SQLiteUtils::OpenDatabase(option, db); if (errCode != E_OK) { @@ -727,7 +727,8 @@ void SQLiteSingleVerStorageEngine::ClearCorruptedFlag() isCorrupted_ = false; } -int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite, SecurityOption &existedSecOpt) +int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite, SecurityOption &existedSecOpt, + OpenDbProperties &option) { // Assume that create the write executor firstly and the write one we will not be released. // If the write one would be released in the future, should take care the pass through. @@ -735,12 +736,12 @@ int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite, SecurityOption return E_OK; } - if (option_.isMemDb) { + if (option.isMemDb) { return E_OK; } // check sqlite open ok - int errCode = CheckStoreStatus(option_); + int errCode = CheckStoreStatus(option); if (errCode != E_OK) { return errCode; } @@ -755,8 +756,9 @@ int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite, SecurityOption // Judge whether need update the security option of the engine. // Should update the security in the import or rekey scene(inner) or exist is not set. - if (IsUseExistedSecOption(existedSecOpt, option_.securityOpt)) { - option_.securityOpt = existedSecOpt; + if (IsUseExistedSecOption(existedSecOpt, option.securityOpt)) { + option.securityOpt = existedSecOpt; + SetSecurityOption(existedSecOpt); } else { isNeedUpdateSecOpt_ = true; } @@ -767,7 +769,7 @@ int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite, SecurityOption } if (!isUpdated_) { - errCode = SQLiteSingleVerDatabaseUpgrader::TransferDatabasePath(option_.subdir, option_); + errCode = SQLiteSingleVerDatabaseUpgrader::TransferDatabasePath(option.subdir, option); if (errCode != E_OK) { LOGE("[PreCreateExecutor] Transfer Db file path failed[%d].", errCode); return errCode; @@ -778,17 +780,18 @@ int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite, SecurityOption } int SQLiteSingleVerStorageEngine::EndCreateExecutor(sqlite3 *db, SecurityOption existedSecOpt, bool isWrite, - bool isDetachMeta) + bool isDetachMeta, OpenDbProperties &option) { - if (option_.isMemDb || !isWrite) { + if (option.isMemDb || !isWrite) { return E_OK; } - int errCode = SQLiteSingleVerDatabaseUpgrader::SetSecOption(option_.subdir, option_.securityOpt, existedSecOpt, + int errCode = SQLiteSingleVerDatabaseUpgrader::SetSecOption(option.subdir, option.securityOpt, existedSecOpt, isNeedUpdateSecOpt_); if (errCode != E_OK) { if (errCode == -E_NOT_SUPPORT) { - option_.securityOpt = SecurityOption(); + option.securityOpt = SecurityOption(); + SetSecurityOption(option.securityOpt); errCode = E_OK; } LOGE("SetSecOption failed:%d", errCode); @@ -797,8 +800,8 @@ int SQLiteSingleVerStorageEngine::EndCreateExecutor(sqlite3 *db, SecurityOption // after setting secOption, the database file operation ends // database create completed, delete the token - if (OS::CheckPathExistence(option_.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) && - OS::RemoveFile(option_.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) != E_OK) { + if (OS::CheckPathExistence(option.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) && + OS::RemoveFile(option.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) != E_OK) { LOGE("Finish to create the complete database, but delete token fail! errCode = [E_SYSTEM_API_FAIL]"); return -E_SYSTEM_API_FAIL; } @@ -813,21 +816,21 @@ int SQLiteSingleVerStorageEngine::EndCreateExecutor(sqlite3 *db, SecurityOption } errCode = SqliteLogTableManager::CreateKvSyncLogTable(db); if (errCode != E_OK) { - LOGE("[SQLiteSingleVerStorageEngine] create cloud log table failed, errCode = [%d]", errCode); + LOGE("[SqlSinEngine] create cloud log table failed, errCode = [%d]", errCode); } else { - LOGI("[SQLiteSingleVerStorageEngine] create cloud log table success"); + LOGI("[SqlSinEngine] create cloud log table success"); } return errCode; } int SQLiteSingleVerStorageEngine::TryAttachMetaDb(const SecurityOption &existedSecOpt, sqlite3 *&dbHandle, - bool &isAttachMeta, bool &isNeedDetachMeta) + bool &isAttachMeta, bool &isNeedDetachMeta, OpenDbProperties &option) { bool isCurrentSESECE = ParamCheckUtils::IsS3SECEOpt(existedSecOpt); - bool isOpenSESECE = ParamCheckUtils::IsS3SECEOpt(option_.securityOpt); + bool isOpenSESECE = ParamCheckUtils::IsS3SECEOpt(option.securityOpt); // attach or not depend on its true secOpt, but it's not permit while option_.secOpt different from true secOpt - if ((!option_.isMemDb) && (isOpenSESECE || (isNeedUpdateSecOpt_ && isCurrentSESECE))) { - int errCode = AttachMetaDatabase(dbHandle, option_); + if ((!option.isMemDb) && (isOpenSESECE || (isNeedUpdateSecOpt_ && isCurrentSESECE))) { + int errCode = AttachMetaDatabase(dbHandle, option); if (errCode != E_OK) { (void)sqlite3_close_v2(dbHandle); dbHandle = nullptr; @@ -842,33 +845,34 @@ int SQLiteSingleVerStorageEngine::TryAttachMetaDb(const SecurityOption &existedS int SQLiteSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *&handle) { SecurityOption existedSecOpt; - int errCode = PreCreateExecutor(isWrite, existedSecOpt); + auto option = GetOption(); + int errCode = PreCreateExecutor(isWrite, existedSecOpt, option); if (errCode != E_OK) { return errCode; } sqlite3 *dbHandle = nullptr; - errCode = GetDbHandle(isWrite, option_.securityOpt, dbHandle); + errCode = GetDbHandle(isWrite, dbHandle, option); if (errCode != E_OK) { return errCode; } bool isAttachMeta = false; bool isDetachMeta = false; - errCode = TryAttachMetaDb(existedSecOpt, dbHandle, isAttachMeta, isDetachMeta); + errCode = TryAttachMetaDb(existedSecOpt, dbHandle, isAttachMeta, isDetachMeta, option); if (errCode != E_OK) { return errCode; } - RegisterFunctionIfNeed(dbHandle); - errCode = Upgrade(dbHandle); + RegisterFunctionIfNeed(dbHandle, option); + errCode = UpgradeInner(dbHandle, option); if (errCode != E_OK) { (void)sqlite3_close_v2(dbHandle); dbHandle = nullptr; return errCode; } - errCode = EndCreateExecutor(dbHandle, existedSecOpt, isWrite, isDetachMeta); + errCode = EndCreateExecutor(dbHandle, existedSecOpt, isWrite, isDetachMeta, option); if (errCode != E_OK) { LOGE("After create executor, set security option incomplete!"); (void)sqlite3_close_v2(dbHandle); @@ -876,7 +880,7 @@ int SQLiteSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecuto return errCode; } - handle = NewSQLiteStorageExecutor(dbHandle, isWrite, option_.isMemDb); + handle = NewSQLiteStorageExecutor(dbHandle, isWrite, option.isMemDb); if (handle == nullptr) { LOGE("New SQLiteStorageExecutor[%d] for the pool failed.", isWrite); (void)sqlite3_close_v2(dbHandle); @@ -890,30 +894,30 @@ int SQLiteSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecuto return E_OK; } -int SQLiteSingleVerStorageEngine::Upgrade(sqlite3 *db) +int SQLiteSingleVerStorageEngine::UpgradeInner(sqlite3 *db, const OpenDbProperties &option) { if (isUpdated_ || GetEngineState() == EngineState::CACHEDB) { return E_OK; } std::unique_ptr upgrader; - LOGD("[SqlSingleEngine][Upgrade] NewSchemaStrSize=%zu", option_.schema.size()); - if (option_.schema.empty()) { - upgrader = std::make_unique(db, option_.securityOpt, option_.isMemDb); + LOGD("[SqlSingleEngine][Upgrade] NewSchemaStrSize=%zu", option.schema.size()); + if (option.schema.empty()) { + upgrader = std::make_unique(db, option.securityOpt, option.isMemDb); } else { SchemaObject schema; - int errCode = schema.ParseFromSchemaString(option_.schema); + int errCode = schema.ParseFromSchemaString(option.schema); if (errCode != E_OK) { LOGE("Upgrader failed while parsing the origin schema:%d", errCode); return errCode; } upgrader = std::make_unique(db, schema, - option_.securityOpt, option_.isMemDb); + option.securityOpt, option.isMemDb); } - std::string mainDbDir = GetDbDir(option_.subdir, DbType::MAIN); + std::string mainDbDir = GetDbDir(option.subdir, DbType::MAIN); std::string mainDbFilePath = mainDbDir + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; - SecurityOption secOpt = option_.securityOpt; + SecurityOption secOpt = option.securityOpt; int errCode = E_OK; if (isNeedUpdateSecOpt_) { errCode = GetPathSecurityOption(mainDbFilePath, secOpt); @@ -926,8 +930,8 @@ int SQLiteSingleVerStorageEngine::Upgrade(sqlite3 *db) } } - upgrader->SetMetaUpgrade(secOpt, option_.securityOpt, option_.subdir); - upgrader->SetSubdir(option_.subdir); + upgrader->SetMetaUpgrade(secOpt, option.securityOpt, option.subdir); + upgrader->SetSubdir(option.subdir); errCode = upgrader->Upgrade(); if (errCode != E_OK) { LOGE("Single ver database upgrade failed:%d", errCode); @@ -943,11 +947,11 @@ int SQLiteSingleVerStorageEngine::Upgrade(sqlite3 *db) // Attention: This function should be called before "Upgrade". // Attention: This function should be called for each executor on the sqlite3 handle that the executor binds to. -void SQLiteSingleVerStorageEngine::RegisterFunctionIfNeed(sqlite3 *dbHandle) const +void SQLiteSingleVerStorageEngine::RegisterFunctionIfNeed(sqlite3 *dbHandle, const OpenDbProperties &option) const { // This function should accept a sqlite3 handle with no perception of database classification. That is, if it is // not a newly created database, the meta-Table should exist and can be accessed. - std::string schemaStr = option_.schema; + std::string schemaStr = option.schema; if (schemaStr.empty()) { // If schema from GetKvStore::Option is empty, we have to try to load it from database. ReadOnly mode if exist; int errCode = SQLiteUtils::GetSchema(dbHandle, schemaStr); @@ -1063,7 +1067,9 @@ void SQLiteSingleVerStorageEngine::InitConflictNotifiedFlag(SingleVerNaturalStor void SQLiteSingleVerStorageEngine::SetMaxValueSize(uint32_t maxValueSize) { - LOGI("Set the max value size to %" PRIu32, maxValueSize); + if (maxValueSize_ != maxValueSize) { + LOGI("Set the max value size to %" PRIu32, maxValueSize); + } maxValueSize_ = maxValueSize; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.h index 8c07dff2..0f784f39 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.h @@ -69,16 +69,21 @@ public: protected: virtual StorageExecutor *NewSQLiteStorageExecutor(sqlite3 *dbHandle, bool isWrite, bool isMemDb) override; - int Upgrade(sqlite3 *db) override; + int UpgradeInner(sqlite3 *db, const OpenDbProperties &option); int CreateNewExecutor(bool isWrite, StorageExecutor *&handle) override; + virtual int TryToOpenMainDatabase(bool isWrite, sqlite3 *&db, OpenDbProperties &option); + + int GetCacheDbHandle(sqlite3 *&db, OpenDbProperties &option); + ExecutorState executorState_; private: // For executor. - int PreCreateExecutor(bool isWrite, SecurityOption &existedSecOpt); - int EndCreateExecutor(sqlite3 *db, SecurityOption existedSecOpt, bool isWrite, bool isDetachMeta); + int PreCreateExecutor(bool isWrite, SecurityOption &existedSecOpt, OpenDbProperties &option); + int EndCreateExecutor(sqlite3 *db, SecurityOption existedSecOpt, bool isWrite, bool isDetachMeta, + OpenDbProperties &option); int ReInit() override; int ReleaseExecutor(SQLiteSingleVerStorageExecutor *&handle); int ReleaseHandleTransiently(SQLiteSingleVerStorageExecutor *&handle, uint64_t idleTime, @@ -100,15 +105,13 @@ private: std::set &removeDevices, bool &isNeedHash) const; // For db. - int TryToOpenMainDatabase(bool isWrite, sqlite3 *&db); - int GetCacheDbHandle(sqlite3 *&db); - int GetDbHandle(bool isWrite, const SecurityOption &secOpt, sqlite3 *&dbHandle); + int GetDbHandle(bool isWrite, sqlite3 *&dbHandle, OpenDbProperties &option); int AttachMetaDatabase(sqlite3 *dbHandle, const OpenDbProperties &option) const; int AttachMainDbAndCacheDb(SQLiteSingleVerStorageExecutor *handle, EngineState stateBeforeMigrate); int AttachMainDbAndCacheDb(sqlite3 *dbHandle, EngineState stateBeforeMigrate) const; - void RegisterFunctionIfNeed(sqlite3 *dbHandle) const; + void RegisterFunctionIfNeed(sqlite3 *dbHandle, const OpenDbProperties &option) const; int TryAttachMetaDb(const SecurityOption &existedSecOpt, sqlite3 *&dbHandle, bool &isAttachMeta, - bool &isNeedDetachMeta); + bool &isNeedDetachMeta, OpenDbProperties &option); // For secOpt. int CreateNewDirsAndSetSecOpt() const; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp index a99a3c62..3cc5c82b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp @@ -17,7 +17,6 @@ #include -#include "cloud/cloud_store_types.h" #include "db_constant.h" #include "db_common.h" #include "db_errno.h" @@ -238,7 +237,6 @@ int SQLiteSingleVerStorageExecutor::GetKvDataByHashKey(const Key &hashKey, Singl result.origDevice = std::string(origDevVect.begin(), origDevVect.end()); } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { errCode = -E_NOT_FOUND; - goto END; } END: diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h index 5156b1db..16c1022c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h @@ -54,6 +54,8 @@ public: // Get all the meta keys. int GetAllMetaKeys(std::vector &keys) const; + int GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const; + int GetAllSyncedEntries(const std::string &hashDev, std::vector &entries) const; int SaveSyncDataItem(DataItem &dataItem, const DeviceInfo &deviceInfo, @@ -198,6 +200,8 @@ public: int CreateCloudLogTable(); int GetEntries(const std::string &device, std::vector &entries) const; + + int ClearCloudWatermark(); protected: virtual int SaveKvData(SingleVerDataType type, const Key &key, const Value &value, Timestamp timestamp); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_extend.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_extend.cpp index 3ee2eb31..56bcff67 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_extend.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_extend.cpp @@ -482,4 +482,15 @@ bool SQLiteSingleVerStorageExecutor::IsFromDataOwner(const DataItem &itemGet, co return itemGet.dev == syncDev || (conflictResolvePolicy_ == DENY_OTHER_DEV_AMEND_CUR_DEV_DATA && itemGet.origDev == syncDev); } + +int SQLiteSingleVerStorageExecutor::ClearCloudWatermark() +{ + return CloudExcuteRemoveOrUpdate(REMOVE_CLOUD_ALL_HWM_DATA_SQL, "", "", true); +} + +int SQLiteSingleVerStorageExecutor::GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const +{ + std::string metaTableName = "meta_data"; + return SqliteMetaExecutor::GetMetaDataByPrefixKey(dbHandle_, isMemDb_, metaTableName, keyPrefix, data); +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h index 6d5cdc2d..016b6361 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h @@ -376,7 +376,7 @@ namespace DistributedDB { constexpr const char *UPDATE_TIMESTAMP = "UPDATE sync_data SET timestamp=?, modify_time=? WHERE hash_key=?"; constexpr const char *SELECT_SYNC_ENTRIES_BY_DEVICE_SQL = - "SELECT key,value FROM sync_data WHERE device=? AND flag&0x200=0"; + "SELECT key,value FROM sync_data WHERE device=? AND flag&0x200=0 AND flag&0x01=0"; constexpr const char *SELECT_COMPENSATE_SYNC_KEY_SQL = "SELECT key FROM sync_data left join naturalbase_kv_aux_sync_data_log as log_table on sync_data.hash_key" diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_subscribe.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_subscribe.cpp index af2d7635..1ad553a0 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_subscribe.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_subscribe.cpp @@ -162,9 +162,10 @@ int SQLiteSingleVerStorageExecutor::AddSubscribeTrigger(QueryObject &query, cons } // check if sqlite function is registered or not sqlite3_stmt *stmt = nullptr; - errCode = SQLiteUtils::GetStatement(dbHandle_, "SELECT " + DBConstant::UPDATE_META_FUNC + "('K', 0);", stmt); + errCode = SQLiteUtils::GetStatement(dbHandle_, + "SELECT " + std::string(DBConstant::UPDATE_META_FUNC) + "('K', 0);", stmt); if (errCode != E_OK) { - LOGE("sqlite function %s has not been created.", DBConstant::UPDATE_META_FUNC.c_str()); + LOGE("sqlite function update_meta_within_trigger has not been created."); return -E_NOT_SUPPORT; } SQLiteUtils::ResetStatement(stmt, true, errCode); @@ -201,7 +202,7 @@ int SQLiteSingleVerStorageExecutor::RemoveSubscribeTrigger(const std::vector> g_serverChangedDataMap; } -namespace TriggerMode { -const std::map TRIGGER_MODE_MAP = { - {TriggerModeEnum::NONE, ""}, - {TriggerModeEnum::INSERT, "INSERT"}, - {TriggerModeEnum::UPDATE, "UPDATE"}, - {TriggerModeEnum::DELETE, "DELETE"}, -}; - -std::string GetTriggerModeString(TriggerModeEnum mode) -{ - auto it = TRIGGER_MODE_MAP.find(mode); - return (it == TRIGGER_MODE_MAP.end()) ? "" : it->second; -} -} - std::string SQLiteUtils::Anonymous(const std::string &name) { if (name.length() <= HEAD_SIZE) { @@ -119,6 +95,7 @@ void SQLiteUtils::SqliteLogCallback(void *data, int err, const char *msg) { bool verboseLog = (data != nullptr); auto errType = static_cast(err); + bool isWarningDump = errType == (SQLITE_WARNING | (2 << 8)); // SQLITE_WARNING_DUMP std::string logMsg = msg == nullptr ? "NULL" : msg; errType &= 0xFF; if (IsNeedSkipLog(errType, logMsg.c_str())) { @@ -129,7 +106,8 @@ void SQLiteUtils::SqliteLogCallback(void *data, int err, const char *msg) if (verboseLog) { LOGD("[SQLite] Error[%d] sys[%d] %s ", err, errno, sqlite3_errstr(err)); } - } else if (errType == SQLITE_WARNING || errType == SQLITE_IOERR || errType == SQLITE_CANTOPEN) { + } else if ((errType == SQLITE_WARNING && !isWarningDump) || + errType == SQLITE_IOERR || errType == SQLITE_CANTOPEN) { LOGI("[SQLite] Error[%d], sys[%d], %s, msg: %s ", err, errno, sqlite3_errstr(err), SQLiteUtils::Anonymous(logMsg).c_str()); } else { @@ -179,9 +157,6 @@ END: (void)sqlite3_close_v2(dbTemp); dbTemp = nullptr; } - struct stat curStat; - stat(fileUrl.c_str(), &curStat); - LOGI("[SQLite] open database result: %d, inode: %llu", errCode, curStat.st_ino); return errCode; } @@ -232,150 +207,6 @@ END: return errCode; } -int SQLiteUtils::GetStatement(sqlite3 *db, const std::string &sql, sqlite3_stmt *&statement) -{ - if (db == nullptr) { - LOGE("Invalid db for statement"); - return -E_INVALID_DB; - } - // Prepare the new statement only when the input parameter is not null - if (statement != nullptr) { - return E_OK; - } - int errCode = sqlite3_prepare_v2(db, sql.c_str(), NO_SIZE_LIMIT, &statement, nullptr); - if (errCode != SQLITE_OK) { - LOGE("Prepare SQLite statement failed:%d, sys:%d", errCode, errno); - errCode = SQLiteUtils::MapSQLiteErrno(errCode); - SQLiteUtils::ResetStatement(statement, true, errCode); - return errCode; - } - - if (statement == nullptr) { - return -E_INVALID_DB; - } - - return E_OK; -} - -int SQLiteUtils::BindTextToStatement(sqlite3_stmt *statement, int index, const std::string &str) -{ - if (statement == nullptr) { - return -E_INVALID_ARGS; - } - - int errCode = sqlite3_bind_text(statement, index, str.c_str(), str.length(), SQLITE_TRANSIENT); - if (errCode != SQLITE_OK) { - LOGE("[SQLiteUtil][Bind text]Failed to bind the value:%d", errCode); - return SQLiteUtils::MapSQLiteErrno(errCode); - } - - return E_OK; -} - -int SQLiteUtils::BindInt64ToStatement(sqlite3_stmt *statement, int index, int64_t value) -{ - // statement check outSide - int errCode = sqlite3_bind_int64(statement, index, value); - if (errCode != SQLITE_OK) { - LOGE("[SQLiteUtil][Bind int64]Failed to bind the value:%d", errCode); - return SQLiteUtils::MapSQLiteErrno(errCode); - } - - return E_OK; -} - -int SQLiteUtils::BindBlobToStatement(sqlite3_stmt *statement, int index, const std::vector &value, - bool permEmpty) -{ - if (statement == nullptr) { - return -E_INVALID_ARGS; - } - - // Check empty value. - if (value.empty() && !permEmpty) { - LOGI("[SQLiteUtil][Bind blob]Invalid value"); - return -E_INVALID_ARGS; - } - - int errCode; - if (value.empty()) { - errCode = sqlite3_bind_zeroblob(statement, index, -1); // -1 for zero-length blob. - } else { - errCode = sqlite3_bind_blob(statement, index, static_cast(value.data()), - value.size(), SQLITE_TRANSIENT); - } - - if (errCode != SQLITE_OK) { - LOGE("[SQLiteUtil][Bind blob]Failed to bind the value:%d", errCode); - return SQLiteUtils::MapSQLiteErrno(errCode); - } - - return E_OK; -} - -void SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool isNeedFinalize, int &errCode) -{ - ResetStatement(statement, isNeedFinalize, false, errCode); -} - -void SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool isNeedFinalize, bool isIgnoreResetRet, int &errCode) -{ - if (statement == nullptr) { - return; - } - - int innerCode = SQLITE_OK; - // if need finalize the statement, just goto finalize. - if (!isNeedFinalize) { - // reset the statement firstly. - innerCode = sqlite3_reset(statement); - if (innerCode != SQLITE_OK && !isIgnoreResetRet) { - LOGE("[SQLiteUtils] reset statement error:%d, sys:%d", innerCode, errno); - isNeedFinalize = true; - } else { - sqlite3_clear_bindings(statement); - } - } - - if (isNeedFinalize) { - int finalizeResult = sqlite3_finalize(statement); - if (finalizeResult != SQLITE_OK) { - LOGE("[SQLiteUtils] finalize statement error:%d, sys:%d", finalizeResult, errno); - innerCode = finalizeResult; - } - statement = nullptr; - } - - if (innerCode != SQLITE_OK) { // the sqlite error code has higher priority. - errCode = SQLiteUtils::MapSQLiteErrno(innerCode); - } -} - -int SQLiteUtils::StepWithRetry(sqlite3_stmt *statement, bool isMemDb) -{ - if (statement == nullptr) { - return -E_INVALID_ARGS; - } - - int errCode = E_OK; - int retryCount = 0; - do { - errCode = sqlite3_step(statement); - if ((errCode == SQLITE_LOCKED) && isMemDb) { - std::this_thread::sleep_for(std::chrono::microseconds(BUSY_SLEEP_TIME)); - retryCount++; - } else { - break; - } - } while (retryCount <= MAX_STEP_TIMES); - - if (errCode != SQLITE_DONE && errCode != SQLITE_ROW) { - LOGE("[SQLiteUtils] Step error:%d, sys:%d", errCode, errno); - } - - return SQLiteUtils::MapSQLiteErrno(errCode); -} - int SQLiteUtils::BindPrefixKey(sqlite3_stmt *statement, int index, const Key &keyPrefix) { if (statement == nullptr) { @@ -415,57 +246,6 @@ int SQLiteUtils::BindPrefixKey(sqlite3_stmt *statement, int index, const Key &ke return E_OK; } -int SQLiteUtils::BeginTransaction(sqlite3 *db, TransactType type) -{ - if (type == TransactType::IMMEDIATE) { - return ExecuteRawSQL(db, BEGIN_IMMEDIATE_SQL, true); - } - - return ExecuteRawSQL(db, BEGIN_SQL, true); -} - -int SQLiteUtils::CommitTransaction(sqlite3 *db) -{ - return ExecuteRawSQL(db, COMMIT_SQL, true); -} - -int SQLiteUtils::RollbackTransaction(sqlite3 *db) -{ - return ExecuteRawSQL(db, ROLLBACK_SQL, true); -} - -int SQLiteUtils::ExecuteRawSQL(sqlite3 *db, const std::string &sql, bool ignoreResetFail) -{ - if (db == nullptr) { - return -E_INVALID_DB; - } - - sqlite3_stmt *stmt = nullptr; - int errCode = SQLiteUtils::GetStatement(db, sql, stmt); - if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) { - LOGE("[SQLiteUtils][ExecuteSQL] prepare statement failed(%d), sys(%d)", errCode, errno); - return errCode; - } - - do { - errCode = SQLiteUtils::StepWithRetry(stmt); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - break; - } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - LOGE("[SQLiteUtils][ExecuteSQL] execute statement failed(%d), sys(%d)", errCode, errno); - break; - } - } while (true); - - int ret = E_OK; - SQLiteUtils::ResetStatement(stmt, true, ret); - if (!ignoreResetFail && ret != E_OK) { - return errCode != E_OK ? errCode : ret; - } - return errCode; -} - int SQLiteUtils::SetKey(sqlite3 *db, CipherType type, const CipherPassword &passwd, bool setWal, uint32_t iterTimes) { if (db == nullptr) { @@ -516,57 +296,6 @@ int SQLiteUtils::SetKey(sqlite3 *db, CipherType type, const CipherPassword &pass return errCode; } -int SQLiteUtils::GetColumnBlobValue(sqlite3_stmt *statement, int index, std::vector &value) -{ - if (statement == nullptr) { - return -E_INVALID_ARGS; - } - - int keySize = sqlite3_column_bytes(statement, index); - if (keySize < 0) { - LOGW("[SQLiteUtils][Column blob] size less than zero:%d", keySize); - value.resize(0); - return E_OK; - } - auto keyRead = static_cast(sqlite3_column_blob(statement, index)); - if (keySize == 0 || keyRead == nullptr) { - value.resize(0); - } else { - if (keySize > MAX_BLOB_READ_SIZE) { - LOGW("[SQLiteUtils][Column blob] size over limit:%d", keySize); - keySize = MAX_BLOB_READ_SIZE + 1; - } - value.resize(keySize); - value.assign(keyRead, keyRead + keySize); - } - return E_OK; -} - -int SQLiteUtils::GetColumnTextValue(sqlite3_stmt *statement, int index, std::string &value) -{ - if (statement == nullptr) { - return -E_INVALID_ARGS; - } - - int valSize = sqlite3_column_bytes(statement, index); - if (valSize < 0) { - LOGW("[SQLiteUtils][Column Text] size less than zero:%d", valSize); - value = {}; - return E_OK; - } - const unsigned char *val = sqlite3_column_text(statement, index); - if (valSize == 0 || val == nullptr) { - value = {}; - return E_OK; - } - value = std::string(reinterpret_cast(val)); - if (valSize > MAX_TEXT_READ_SIZE) { - LOGW("[SQLiteUtils][Column text] size over limit:%d", valSize); - value.resize(MAX_TEXT_READ_SIZE + 1); // Reset value size to invalid - } - return E_OK; -} - int SQLiteUtils::AttachNewDatabase(sqlite3 *db, CipherType type, const CipherPassword &password, const std::string &attachDbAbsPath, const std::string &attachAsName) { @@ -713,265 +442,7 @@ int SQLiteUtils::CheckIntegrity(sqlite3 *db, const std::string &sql) SQLiteUtils::ResetStatement(statement, true, ret); return errCode != E_OK ? errCode : ret; } -#ifdef RELATIONAL_STORE - -namespace { // anonymous namespace for schema analysis -int AnalysisSchemaSqlAndTrigger(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive) -{ - std::string sql = "SELECT type, sql FROM sqlite_master WHERE tbl_name = ? "; - if (!caseSensitive) { - sql += "COLLATE NOCASE"; - } - sqlite3_stmt *statement = nullptr; - int errCode = SQLiteUtils::GetStatement(db, sql, statement); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] Prepare the analysis schema sql and trigger statement error:%d", errCode); - return errCode; - } - errCode = SQLiteUtils::BindTextToStatement(statement, 1, tableName); - int ret = E_OK; - if (errCode != E_OK) { - LOGE("[AnalysisSchema] Bind table name failed:%d", errCode); - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode; - } - - errCode = -E_NOT_FOUND; - do { - int err = SQLiteUtils::StepWithRetry(statement); - if (err == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - break; - } else if (err == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - errCode = E_OK; - std::string type; - (void) SQLiteUtils::GetColumnTextValue(statement, 0, type); - if (type == "table") { - std::string createTableSql; - (void) SQLiteUtils::GetColumnTextValue(statement, 1, createTableSql); // 1 means create table sql - table.SetCreateTableSql(createTableSql); - } - } else { - LOGE("[AnalysisSchema] Step for the analysis create table sql and trigger failed:%d", err); - errCode = SQLiteUtils::MapSQLiteErrno(err); - break; - } - } while (true); - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode != E_OK ? errCode : ret; -} - -int GetSchemaIndexList(sqlite3 *db, const std::string &tableName, std::vector &indexList, - std::vector &uniqueList) -{ - std::string sql = "pragma index_list('" + tableName + "')"; - sqlite3_stmt *statement = nullptr; - int errCode = SQLiteUtils::GetStatement(db, sql, statement); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] Prepare the get schema index list statement error:%d", errCode); - return errCode; - } - - do { - errCode = SQLiteUtils::StepWithRetry(statement); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - break; - } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - std::string indexName; - (void) SQLiteUtils::GetColumnTextValue(statement, 1, indexName); // 1 means index name - int unique = sqlite3_column_int64(statement, 2); // 2 means index type, whether unique - if (unique == 0) { // 0 means index created by user declare - indexList.push_back(indexName); - } else if (unique == 1) { // 1 means an unique define - uniqueList.push_back(indexName); - } - } else { - LOGW("[AnalysisSchema] Step for the get schema index list failed:%d", errCode); - break; - } - } while (true); - int ret = E_OK; - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode != E_OK ? errCode : ret; -} - -int AnalysisSchemaIndexDefine(sqlite3 *db, const std::string &indexName, CompositeFields &indexDefine) -{ - auto sql = "pragma index_info('" + indexName + "')"; - sqlite3_stmt *statement = nullptr; - int errCode = SQLiteUtils::GetStatement(db, sql, statement); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] Prepare the analysis schema index statement error:%d", errCode); - return errCode; - } - - do { - errCode = SQLiteUtils::StepWithRetry(statement); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - break; - } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - std::string indexField; - (void) SQLiteUtils::GetColumnTextValue(statement, 2, indexField); // 2 means index's column name. - indexDefine.push_back(indexField); - } else { - LOGW("[AnalysisSchema] Step for the analysis schema index failed:%d", errCode); - break; - } - } while (true); - - int ret = E_OK; - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode != E_OK ? errCode : ret; -} - -int AnalysisSchemaIndex(sqlite3 *db, const std::string &tableName, TableInfo &table) -{ - std::vector indexList; - std::vector uniqueList; - int errCode = GetSchemaIndexList(db, tableName, indexList, uniqueList); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] get schema index list failed."); - return errCode; - } - - for (const auto &indexName : indexList) { - CompositeFields indexDefine; - errCode = AnalysisSchemaIndexDefine(db, indexName, indexDefine); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] analysis schema index columns failed."); - return errCode; - } - table.AddIndexDefine(indexName, indexDefine); - } - std::vector uniques; - for (const auto &uniqueName : uniqueList) { - CompositeFields uniqueDefine; - errCode = AnalysisSchemaIndexDefine(db, uniqueName, uniqueDefine); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] analysis schema unique columns failed."); - return errCode; - } - uniques.push_back(uniqueDefine); - } - table.SetUniqueDefine(uniques); - return E_OK; -} - -void SetPrimaryKeyCollateType(const std::string &sql, FieldInfo &field) -{ - std::string upperFieldName = DBCommon::ToUpperCase(field.GetFieldName()); - if (DBCommon::HasConstraint(sql, "PRIMARY KEY COLLATE NOCASE", " ", " ,)") || - DBCommon::HasConstraint(sql, upperFieldName + " TEXT COLLATE NOCASE", " (,", " ,")) { - field.SetCollateType(CollateType::COLLATE_NOCASE); - } else if (DBCommon::HasConstraint(sql, "PRIMARY KEY COLLATE RTRIM", " ", " ,)") || - DBCommon::HasConstraint(sql, upperFieldName + " TEXT COLLATE RTRIM", " (,", " ,")) { - field.SetCollateType(CollateType::COLLATE_RTRIM); - } -} - -int SetFieldInfo(sqlite3_stmt *statement, TableInfo &table) -{ - FieldInfo field; - field.SetColumnId(sqlite3_column_int(statement, 0)); // 0 means column id index - - std::string tmpString; - (void) SQLiteUtils::GetColumnTextValue(statement, 1, tmpString); // 1 means column name index - if (!DBCommon::CheckIsAlnumOrUnderscore(tmpString)) { - LOGE("[AnalysisSchema] unsupported field name."); - return -E_NOT_SUPPORT; - } - field.SetFieldName(tmpString); - - (void) SQLiteUtils::GetColumnTextValue(statement, 2, tmpString); // 2 means datatype index - field.SetDataType(tmpString); - - field.SetNotNull(static_cast(sqlite3_column_int64(statement, 3))); // 3 means whether null index - - (void) SQLiteUtils::GetColumnTextValue(statement, 4, tmpString); // 4 means default value index - if (!tmpString.empty()) { - field.SetDefaultValue(tmpString); - } - - int keyIndex = sqlite3_column_int(statement, 5); // 5 means primary key index - if (keyIndex != 0) { // not 0 means is a primary key - table.SetPrimaryKey(field.GetFieldName(), keyIndex); - SetPrimaryKeyCollateType(table.GetCreateTableSql(), field); - } - table.AddField(field); - return E_OK; -} -} // end of anonymous namespace for schema analysis - -int SQLiteUtils::AnalysisSchemaFieldDefine(sqlite3 *db, const std::string &tableName, TableInfo &table) -{ - std::string sql = "pragma table_info('" + tableName + "')"; - sqlite3_stmt *statement = nullptr; - int errCode = SQLiteUtils::GetStatement(db, sql, statement); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] Prepare the analysis schema field statement error:%d", errCode); - return errCode; - } - - do { - errCode = SQLiteUtils::StepWithRetry(statement); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - break; - } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - errCode = SetFieldInfo(statement, table); - if (errCode != E_OK) { - break; - } - } else { - LOGW("[AnalysisSchema] Step for the analysis schema field failed:%d", errCode); - break; - } - } while (true); - - if (table.GetPrimaryKey().empty()) { - table.SetPrimaryKey("rowid", 1); - } - - int ret = E_OK; - SQLiteUtils::ResetStatement(statement, true, ret); - return errCode != E_OK ? errCode : ret; -} - -int SQLiteUtils::AnalysisSchema(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive) -{ - if (db == nullptr) { - return -E_INVALID_DB; - } - - if (!DBCommon::CheckIsAlnumOrUnderscore(tableName)) { - LOGE("[AnalysisSchema] unsupported table name."); - return -E_NOT_SUPPORT; - } - - int errCode = AnalysisSchemaSqlAndTrigger(db, tableName, table, caseSensitive); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] Analysis sql and trigger failed. errCode = [%d]", errCode); - return errCode; - } - - errCode = AnalysisSchemaIndex(db, tableName, table); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] Analysis index failed."); - return errCode; - } - - errCode = AnalysisSchemaFieldDefine(db, tableName, table); - if (errCode != E_OK) { - LOGE("[AnalysisSchema] Analysis field failed."); - return errCode; - } - - table.SetTableName(tableName); - return E_OK; -} -#endif #ifndef OMIT_ENCRYPT int SQLiteUtils::ExportDatabase(sqlite3 *db, CipherType type, const CipherPassword &passwd, const std::string &newDbName) @@ -1159,39 +630,6 @@ int SQLiteUtils::SetUserVer(sqlite3 *db, int version) return SQLiteUtils::ExecuteRawSQL(db, userVersionSql); } -int SQLiteUtils::MapSQLiteErrno(int errCode) -{ - switch (errCode) { - case SQLITE_OK: - return E_OK; - case SQLITE_IOERR: - if (errno == EKEYREVOKED) { - return -E_EKEYREVOKED; - } - break; - case SQLITE_CORRUPT: - case SQLITE_NOTADB: - return -E_INVALID_PASSWD_OR_CORRUPTED_DB; - case SQLITE_LOCKED: - case SQLITE_BUSY: - return -E_BUSY; - case SQLITE_ERROR: - if (errno == EKEYREVOKED) { - return -E_EKEYREVOKED; - } - break; - case SQLITE_AUTH: - return -E_DENIED_SQL; - case SQLITE_CONSTRAINT: - return -E_CONSTRAINT; - case SQLITE_CANTOPEN: - return -E_SQLITE_CANT_OPEN; - default: - break; - } - return -errCode; -} - int SQLiteUtils::SetBusyTimeout(sqlite3 *db, int timeout) { if (db == nullptr) { @@ -1289,7 +727,7 @@ int SQLiteUtils::GetSchema(sqlite3 *db, std::string &strSchema) bool isExists = false; int errCode = CheckTableExists(db, "meta_data", isExists); if (errCode != E_OK || !isExists) { - LOGW("meta table may has not been created, err=%d, isExists=%d", errCode, isExists); + LOGW("[GetSchema] err=%d, meta=%d", errCode, isExists); return errCode; } @@ -1827,11 +1265,11 @@ END: int SQLiteUtils::RegisterMetaDataUpdateFunction(sqlite3 *db) { - int errCode = sqlite3_create_function_v2(db, DBConstant::UPDATE_META_FUNC.c_str(), + int errCode = sqlite3_create_function_v2(db, DBConstant::UPDATE_META_FUNC, 2, // 2: argc for register function SQLITE_UTF8 | SQLITE_DETERMINISTIC, db, &SQLiteUtils::UpdateMetaDataWithinTrigger, nullptr, nullptr, nullptr); if (errCode != SQLITE_OK) { - LOGE("sqlite3_create_function_v2 about %s returned %d", DBConstant::UPDATE_META_FUNC.c_str(), errCode); + LOGE("sqlite3_create_function_v2 about update_meta_within_trigger returned %d", errCode); } return SQLiteUtils::MapSQLiteErrno(errCode); } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h index 1953db51..69b1a18c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h @@ -213,6 +213,8 @@ public: static int UpdateLocalDataModifyTime(sqlite3 *db, const std::string &virtualTime, const std::string &modifyTime); static int UpdateLocalDataCloudFlag(sqlite3 *db); + + static int ProcessStatementErrCode(sqlite3_stmt *&statement, bool isNeedFinalize, int errCode); private: static int CreateDataBase(const OpenDbProperties &properties, sqlite3 *&dbTemp, bool setWal); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_client.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_client.cpp new file mode 100644 index 00000000..a6779791 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_client.cpp @@ -0,0 +1,651 @@ +/* + * 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 "sqlite_utils.h" + +#include "db_common.h" +#include "platform_specific.h" + +namespace DistributedDB { +namespace { + const int BUSY_SLEEP_TIME = 50; // sleep for 50us + const int NO_SIZE_LIMIT = -1; + const int MAX_STEP_TIMES = 8000; + const std::string BEGIN_SQL = "BEGIN TRANSACTION"; + const std::string BEGIN_IMMEDIATE_SQL = "BEGIN IMMEDIATE TRANSACTION"; + const std::string COMMIT_SQL = "COMMIT TRANSACTION"; + const std::string ROLLBACK_SQL = "ROLLBACK TRANSACTION"; + const int MAX_BLOB_READ_SIZE = 64 * 1024 * 1024; // 64M limit + const int MAX_TEXT_READ_SIZE = 5 * 1024 * 1024; // 5M limit + + const constexpr char *CHECK_TABLE_CREATED = "SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE " \ + "type='table' AND (tbl_name=? COLLATE NOCASE));"; + const constexpr char *CHECK_META_DB_TABLE_CREATED = "SELECT EXISTS(SELECT 1 FROM meta.sqlite_master WHERE " \ + "type='table' AND (tbl_name=? COLLATE NOCASE));"; +} + +namespace TriggerMode { +const std::map TRIGGER_MODE_MAP = { + {TriggerModeEnum::NONE, ""}, + {TriggerModeEnum::INSERT, "INSERT"}, + {TriggerModeEnum::UPDATE, "UPDATE"}, + {TriggerModeEnum::DELETE, "DELETE"}, +}; + +std::string GetTriggerModeString(TriggerModeEnum mode) +{ + auto it = TRIGGER_MODE_MAP.find(mode); + return (it == TRIGGER_MODE_MAP.end()) ? "" : it->second; +} +} + +int SQLiteUtils::StepWithRetry(sqlite3_stmt *statement, bool isMemDb) +{ + if (statement == nullptr) { + return -E_INVALID_ARGS; + } + + int errCode = E_OK; + int retryCount = 0; + do { + errCode = sqlite3_step(statement); + if ((errCode == SQLITE_LOCKED) && isMemDb) { + std::this_thread::sleep_for(std::chrono::microseconds(BUSY_SLEEP_TIME)); + retryCount++; + } else { + break; + } + } while (retryCount <= MAX_STEP_TIMES); + + if (errCode != SQLITE_DONE && errCode != SQLITE_ROW) { + LOGE("[SQLiteUtils] Step error:%d, sys:%d", errCode, errno); + } + + return SQLiteUtils::MapSQLiteErrno(errCode); +} + +int SQLiteUtils::BeginTransaction(sqlite3 *db, TransactType type) +{ + if (type == TransactType::IMMEDIATE) { + return ExecuteRawSQL(db, BEGIN_IMMEDIATE_SQL, true); + } + + return ExecuteRawSQL(db, BEGIN_SQL, true); +} + +int SQLiteUtils::CommitTransaction(sqlite3 *db) +{ + return ExecuteRawSQL(db, COMMIT_SQL, true); +} + +int SQLiteUtils::RollbackTransaction(sqlite3 *db) +{ + return ExecuteRawSQL(db, ROLLBACK_SQL, true); +} + +int SQLiteUtils::ExecuteRawSQL(sqlite3 *db, const std::string &sql, bool ignoreResetFail) +{ + if (db == nullptr) { + return -E_INVALID_DB; + } + + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) { + LOGE("[SQLiteUtils][ExecuteSQL] prepare statement failed(%d), sys(%d)", errCode, errno); + return errCode; + } + + do { + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + break; + } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + LOGE("[SQLiteUtils][ExecuteSQL] execute statement failed(%d), sys(%d)", errCode, errno); + break; + } + } while (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)); + + int ret = E_OK; + SQLiteUtils::ResetStatement(stmt, true, ret); + if (!ignoreResetFail && ret != E_OK) { + return errCode != E_OK ? errCode : ret; + } + return errCode; +} + +int SQLiteUtils::MapSQLiteErrno(int errCode) +{ + switch (errCode) { + case SQLITE_OK: + return E_OK; + case SQLITE_IOERR: + if (errno == EKEYREVOKED) { + return -E_EKEYREVOKED; + } + break; + case SQLITE_CORRUPT: + case SQLITE_NOTADB: + return -E_INVALID_PASSWD_OR_CORRUPTED_DB; + case SQLITE_LOCKED: + case SQLITE_BUSY: + return -E_BUSY; + case SQLITE_ERROR: + if (errno == EKEYREVOKED) { + return -E_EKEYREVOKED; + } + break; + case SQLITE_AUTH: + return -E_DENIED_SQL; + case SQLITE_CONSTRAINT: + return -E_CONSTRAINT; + case SQLITE_CANTOPEN: + return -E_SQLITE_CANT_OPEN; + default: + break; + } + return -errCode; +} + +int SQLiteUtils::GetStatement(sqlite3 *db, const std::string &sql, sqlite3_stmt *&statement) +{ + if (db == nullptr) { + LOGE("Invalid db for statement"); + return -E_INVALID_DB; + } + // Prepare the new statement only when the input parameter is not null + if (statement != nullptr) { + return E_OK; + } + int errCode = sqlite3_prepare_v2(db, sql.c_str(), NO_SIZE_LIMIT, &statement, nullptr); + if (errCode != SQLITE_OK) { + LOGE("Prepare SQLite statement failed:%d, sys:%d", errCode, errno); + errCode = SQLiteUtils::MapSQLiteErrno(errCode); + SQLiteUtils::ResetStatement(statement, true, errCode); + return errCode; + } + + if (statement == nullptr) { + return -E_INVALID_DB; + } + + return E_OK; +} + +void SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool isNeedFinalize, int &errCode) +{ + ResetStatement(statement, isNeedFinalize, false, errCode); +} + +void SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool isNeedFinalize, bool isIgnoreResetRet, int &errCode) +{ + if (statement == nullptr) { + return; + } + + int innerCode = SQLITE_OK; + // if need finalize the statement, just goto finalize. + if (!isNeedFinalize) { + // reset the statement firstly. + innerCode = sqlite3_reset(statement); + if (innerCode != SQLITE_OK && !isIgnoreResetRet) { + LOGE("[SQLiteUtils] reset statement error:%d, sys:%d", innerCode, errno); + isNeedFinalize = true; + } else { + sqlite3_clear_bindings(statement); + } + } + + if (isNeedFinalize) { + int finalizeResult = sqlite3_finalize(statement); + if (finalizeResult != SQLITE_OK) { + LOGE("[SQLiteUtils] finalize statement error:%d, sys:%d", finalizeResult, errno); + innerCode = finalizeResult; + } + statement = nullptr; + } + + if (innerCode != SQLITE_OK) { // the sqlite error code has higher priority. + errCode = SQLiteUtils::MapSQLiteErrno(innerCode); + } +} + +#ifdef RELATIONAL_STORE +namespace { // anonymous namespace for schema analysis +int AnalysisSchemaSqlAndTrigger(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive) +{ + std::string sql = "SELECT type, sql FROM sqlite_master WHERE tbl_name = ? "; + if (!caseSensitive) { + sql += "COLLATE NOCASE"; + } + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, statement); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] Prepare the analysis schema sql and trigger statement error:%d", errCode); + return errCode; + } + errCode = SQLiteUtils::BindTextToStatement(statement, 1, tableName); + int ret = E_OK; + if (errCode != E_OK) { + LOGE("[AnalysisSchema] Bind table name failed:%d", errCode); + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode; + } + + errCode = -E_NOT_FOUND; + int err = SQLiteUtils::MapSQLiteErrno(SQLITE_ROW); + do { + err = SQLiteUtils::StepWithRetry(statement); + if (err == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + break; + } else if (err == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + errCode = E_OK; + std::string type; + (void) SQLiteUtils::GetColumnTextValue(statement, 0, type); + if (type == "table") { + std::string createTableSql; + (void) SQLiteUtils::GetColumnTextValue(statement, 1, createTableSql); // 1 means create table sql + table.SetCreateTableSql(createTableSql); + } + } else { + LOGE("[AnalysisSchema] Step for the analysis create table sql and trigger failed:%d", err); + errCode = err; + break; + } + } while (err == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)); + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode != E_OK ? errCode : ret; +} + +int AnalysisSchemaIndexDefine(sqlite3 *db, const std::string &indexName, CompositeFields &indexDefine) +{ + auto sql = "pragma index_info('" + indexName + "')"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, statement); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] Prepare the analysis schema index statement error:%d", errCode); + return errCode; + } + + do { + errCode = SQLiteUtils::StepWithRetry(statement); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + break; + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + std::string indexField; + (void) SQLiteUtils::GetColumnTextValue(statement, 2, indexField); // 2 means index's column name. + indexDefine.push_back(indexField); + } else { + LOGW("[AnalysisSchema] Step for the analysis schema index failed:%d", errCode); + break; + } + } while (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)); + + int ret = E_OK; + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode != E_OK ? errCode : ret; +} + +int GetSchemaIndexList(sqlite3 *db, const std::string &tableName, std::vector &indexList, + std::vector &uniqueList) +{ + std::string sql = "pragma index_list('" + tableName + "')"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, statement); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] Prepare the get schema index list statement error:%d", errCode); + return errCode; + } + + do { + errCode = SQLiteUtils::StepWithRetry(statement); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + break; + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + std::string indexName; + (void) SQLiteUtils::GetColumnTextValue(statement, 1, indexName); // 1 means index name + int unique = sqlite3_column_int64(statement, 2); // 2 means index type, whether unique + if (unique == 0) { // 0 means index created by user declare + indexList.push_back(indexName); + } else if (unique == 1) { // 1 means an unique define + uniqueList.push_back(indexName); + } + } else { + LOGW("[AnalysisSchema] Step for the get schema index list failed:%d", errCode); + break; + } + } while (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)); + int ret = E_OK; + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode != E_OK ? errCode : ret; +} + +int AnalysisSchemaIndex(sqlite3 *db, const std::string &tableName, TableInfo &table) +{ + std::vector indexList; + std::vector uniqueList; + int errCode = GetSchemaIndexList(db, tableName, indexList, uniqueList); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] get schema index list failed."); + return errCode; + } + + for (const auto &indexName : indexList) { + CompositeFields indexDefine; + errCode = AnalysisSchemaIndexDefine(db, indexName, indexDefine); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] analysis schema index columns failed."); + return errCode; + } + table.AddIndexDefine(indexName, indexDefine); + } + + std::vector uniques; + for (const auto &uniqueName : uniqueList) { + CompositeFields uniqueDefine; + errCode = AnalysisSchemaIndexDefine(db, uniqueName, uniqueDefine); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] analysis schema unique columns failed."); + return errCode; + } + uniques.push_back(uniqueDefine); + } + table.SetUniqueDefine(uniques); + return E_OK; +} + +void SetPrimaryKeyCollateType(const std::string &sql, FieldInfo &field) +{ + std::string upperFieldName = DBCommon::ToUpperCase(field.GetFieldName()); + if (DBCommon::HasConstraint(sql, "PRIMARY KEY COLLATE NOCASE", " ", " ,)") || + DBCommon::HasConstraint(sql, upperFieldName + " TEXT COLLATE NOCASE", " (,", " ,")) { + field.SetCollateType(CollateType::COLLATE_NOCASE); + } else if (DBCommon::HasConstraint(sql, "PRIMARY KEY COLLATE RTRIM", " ", " ,)") || + DBCommon::HasConstraint(sql, upperFieldName + " TEXT COLLATE RTRIM", " (,", " ,")) { + field.SetCollateType(CollateType::COLLATE_RTRIM); + } +} + +int SetFieldInfo(sqlite3_stmt *statement, TableInfo &table) +{ + FieldInfo field; + field.SetColumnId(sqlite3_column_int(statement, 0)); // 0 means column id index + + std::string tmpString; + (void) SQLiteUtils::GetColumnTextValue(statement, 1, tmpString); // 1 means column name index + if (!DBCommon::CheckIsAlnumOrUnderscore(tmpString)) { + LOGE("[AnalysisSchema] unsupported field name."); + return -E_NOT_SUPPORT; + } + field.SetFieldName(tmpString); + + (void) SQLiteUtils::GetColumnTextValue(statement, 2, tmpString); // 2 means datatype index + field.SetDataType(tmpString); + + field.SetNotNull(static_cast(sqlite3_column_int64(statement, 3))); // 3 means whether null index + + (void) SQLiteUtils::GetColumnTextValue(statement, 4, tmpString); // 4 means default value index + if (!tmpString.empty()) { + field.SetDefaultValue(tmpString); + } + + int keyIndex = sqlite3_column_int(statement, 5); // 5 means primary key index + if (keyIndex != 0) { // not 0 means is a primary key + table.SetPrimaryKey(field.GetFieldName(), keyIndex); + SetPrimaryKeyCollateType(table.GetCreateTableSql(), field); + } + table.AddField(field); + return E_OK; +} +} // end of anonymous namespace for schema analysis + +int SQLiteUtils::AnalysisSchemaFieldDefine(sqlite3 *db, const std::string &tableName, TableInfo &table) +{ + std::string sql = "pragma table_info('" + tableName + "')"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, statement); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] Prepare the analysis schema field statement error:%d", errCode); + return errCode; + } + + do { + errCode = SQLiteUtils::StepWithRetry(statement); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + break; + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + errCode = SetFieldInfo(statement, table); + if (errCode != E_OK) { + break; + } + } else { + LOGW("[AnalysisSchema] Step for the analysis schema field failed:%d", errCode); + break; + } + } while (errCode == E_OK); + + if (table.GetPrimaryKey().empty()) { + table.SetPrimaryKey("rowid", 1); + } + + int ret = E_OK; + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode != E_OK ? errCode : ret; +} + +int SQLiteUtils::AnalysisSchema(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive) +{ + if (db == nullptr) { + return -E_INVALID_DB; + } + + if (!DBCommon::CheckIsAlnumOrUnderscore(tableName)) { + LOGE("[AnalysisSchema] unsupported table name."); + return -E_NOT_SUPPORT; + } + + int errCode = AnalysisSchemaSqlAndTrigger(db, tableName, table, caseSensitive); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] Analysis sql and trigger failed. errCode = [%d]", errCode); + return errCode; + } + + errCode = AnalysisSchemaIndex(db, tableName, table); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] Analysis index failed."); + return errCode; + } + + errCode = AnalysisSchemaFieldDefine(db, tableName, table); + if (errCode != E_OK) { + LOGE("[AnalysisSchema] Analysis field failed."); + return errCode; + } + + table.SetTableName(tableName); + return E_OK; +} +#endif + +int SQLiteUtils::BindTextToStatement(sqlite3_stmt *statement, int index, const std::string &str) +{ + if (statement == nullptr) { + return -E_INVALID_ARGS; + } + + int errCode = sqlite3_bind_text(statement, index, str.c_str(), str.length(), SQLITE_TRANSIENT); + if (errCode != SQLITE_OK) { + LOGE("[SQLiteUtil][Bind text]Failed to bind the value:%d", errCode); + return SQLiteUtils::MapSQLiteErrno(errCode); + } + + return E_OK; +} + +int SQLiteUtils::ProcessStatementErrCode(sqlite3_stmt *&statement, bool isNeedFinalize, int errCode) +{ + int ret = E_OK; + SQLiteUtils::ResetStatement(statement, isNeedFinalize, ret); + return errCode != E_OK ? errCode : ret; +} + +int SQLiteUtils::CheckTableExists(sqlite3 *db, const std::string &tableName, bool &isCreated, bool isCheckMeta) +{ + if (db == nullptr) { + return -1; + } + + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, isCheckMeta ? CHECK_META_DB_TABLE_CREATED : CHECK_TABLE_CREATED, stmt); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) { + LOGE("Get check table statement failed. err=%d", errCode); + return errCode; + } + + errCode = SQLiteUtils::BindTextToStatement(stmt, 1, tableName); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) { + LOGE("Bind table name to statement failed. err=%d", errCode); + return ProcessStatementErrCode(stmt, true, errCode); + } + + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + LOGE("Check table exists failed. err=%d", errCode); // should always return a row data + return ProcessStatementErrCode(stmt, true, errCode); + } + errCode = E_OK; + isCreated = (sqlite3_column_int(stmt, 0) == 1); + return ProcessStatementErrCode(stmt, true, errCode); +} + +int SQLiteUtils::BindBlobToStatement(sqlite3_stmt *statement, int index, const std::vector &value, + bool permEmpty) +{ + if (statement == nullptr) { + return -E_INVALID_ARGS; + } + + // Check empty value. + if (value.empty() && !permEmpty) { + LOGI("[SQLiteUtil][Bind blob]Invalid value"); + return -E_INVALID_ARGS; + } + + int errCode; + if (value.empty()) { + errCode = sqlite3_bind_zeroblob(statement, index, -1); // -1 for zero-length blob. + } else { + errCode = sqlite3_bind_blob(statement, index, static_cast(value.data()), + value.size(), SQLITE_TRANSIENT); + } + + if (errCode != SQLITE_OK) { + LOGE("[SQLiteUtil][Bind blob]Failed to bind the value:%d", errCode); + return SQLiteUtils::MapSQLiteErrno(errCode); + } + + return E_OK; +} + +int SQLiteUtils::GetColumnTextValue(sqlite3_stmt *statement, int index, std::string &value) +{ + if (statement == nullptr) { + return -E_INVALID_ARGS; + } + + int valSize = sqlite3_column_bytes(statement, index); + if (valSize < 0) { + LOGW("[SQLiteUtils][Column Text] size less than zero:%d", valSize); + value = {}; + return E_OK; + } + const unsigned char *val = sqlite3_column_text(statement, index); + if (valSize == 0 || val == nullptr) { + value = {}; + return E_OK; + } + value = std::string(reinterpret_cast(val)); + if (valSize > MAX_TEXT_READ_SIZE) { + LOGW("[SQLiteUtils][Column text] size over limit:%d", valSize); + value.resize(MAX_TEXT_READ_SIZE + 1); // Reset value size to invalid + } + return E_OK; +} + +int SQLiteUtils::GetColumnBlobValue(sqlite3_stmt *statement, int index, std::vector &value) +{ + if (statement == nullptr) { + return -E_INVALID_ARGS; + } + + int keySize = sqlite3_column_bytes(statement, index); + if (keySize < 0) { + LOGW("[SQLiteUtils][Column blob] size less than zero:%d", keySize); + value.resize(0); + return E_OK; + } + auto keyRead = static_cast(sqlite3_column_blob(statement, index)); + if (keySize == 0 || keyRead == nullptr) { + value.resize(0); + } else { + if (keySize > MAX_BLOB_READ_SIZE) { + LOGW("[SQLiteUtils][Column blob] size over limit:%d", keySize); + keySize = MAX_BLOB_READ_SIZE + 1; + } + value.resize(keySize); + value.assign(keyRead, keyRead + keySize); + } + return E_OK; +} + +int SQLiteUtils::GetCountBySql(sqlite3 *db, const std::string &sql, int &count) +{ + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][GetCountBySql] Get stmt failed when get local data count: %d", errCode); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(stmt, false); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + count = static_cast(sqlite3_column_int(stmt, 0)); + errCode = E_OK; + } else { + LOGE("[SQLiteUtils][GetCountBySql] Query local data count failed: %d", errCode); + } + int ret = E_OK; + SQLiteUtils::ResetStatement(stmt, true, ret); + if (ret != E_OK) { + LOGE("[SQLiteUtils][GetCountBySql] Reset stmt failed when get local data count: %d", ret); + } + return errCode != E_OK ? errCode : ret; +} + +int SQLiteUtils::BindInt64ToStatement(sqlite3_stmt *statement, int index, int64_t value) +{ + // statement check outSide + int errCode = sqlite3_bind_int64(statement, index, value); + if (errCode != SQLITE_OK) { + LOGE("[SQLiteUtil][Bind int64]Failed to bind the value:%d", errCode); + return SQLiteUtils::MapSQLiteErrno(errCode); + } + + return E_OK; +} +} // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp index 2164d187..7100ec78 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp @@ -46,11 +46,6 @@ namespace { const std::string WAL_MODE_SQL = "PRAGMA journal_mode=WAL;"; const std::string SHA1_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA1;"; const std::string SHA256_ALGO_REKEY_SQL = "PRAGMA codec_rekey_hmac_algo=SHA256;"; - - const constexpr char *CHECK_TABLE_CREATED = "SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE " \ - "type='table' AND (tbl_name=? COLLATE NOCASE));"; - const constexpr char *CHECK_META_DB_TABLE_CREATED = "SELECT EXISTS(SELECT 1 FROM meta.sqlite_master WHERE " \ - "type='table' AND (tbl_name=? COLLATE NOCASE));"; } struct ValueParseCache { @@ -648,38 +643,6 @@ int SQLiteUtils::UpdateCipherShaAlgo(sqlite3 *db, bool setWal, CipherType type, return Rekey(db, passwd); } -int SQLiteUtils::CheckTableExists(sqlite3 *db, const std::string &tableName, bool &isCreated, bool isCheckMeta) -{ - if (db == nullptr) { - return -1; - } - - sqlite3_stmt *stmt = nullptr; - int errCode = SQLiteUtils::GetStatement(db, isCheckMeta ? CHECK_META_DB_TABLE_CREATED : CHECK_TABLE_CREATED, stmt); - if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) { - LOGE("Get check table statement failed. err=%d", errCode); - return errCode; - } - - errCode = SQLiteUtils::BindTextToStatement(stmt, 1, tableName); - if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) { - LOGE("Bind table name to statement failed. err=%d", errCode); - goto END; - } - - errCode = SQLiteUtils::StepWithRetry(stmt); - if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - LOGE("Check table exists failed. err=%d", errCode); // should always return a row data - goto END; - } - errCode = E_OK; - isCreated = (sqlite3_column_int(stmt, 0) == 1); -END: - int ret = E_OK; - SQLiteUtils::ResetStatement(stmt, true, ret); - return errCode != E_OK ? errCode : ret; -} - int SQLiteUtils::StepNext(sqlite3_stmt *stmt, bool isMemDb) { if (stmt == nullptr) { @@ -694,29 +657,6 @@ int SQLiteUtils::StepNext(sqlite3_stmt *stmt, bool isMemDb) return errCode; } -int SQLiteUtils::GetCountBySql(sqlite3 *db, const std::string &sql, int &count) -{ - sqlite3_stmt *stmt = nullptr; - int errCode = SQLiteUtils::GetStatement(db, sql, stmt); - if (errCode != E_OK) { - LOGE("[SQLiteUtils][GetCountBySql] Get stmt failed when get local data count: %d", errCode); - return errCode; - } - errCode = SQLiteUtils::StepWithRetry(stmt, false); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - count = static_cast(sqlite3_column_int(stmt, 0)); - errCode = E_OK; - } else { - LOGE("[SQLiteUtils][GetCountBySql] Query local data count failed: %d", errCode); - } - int ret = E_OK; - SQLiteUtils::ResetStatement(stmt, true, ret); - if (ret != E_OK) { - LOGE("[SQLiteUtils][GetCountBySql] Reset stmt failed when get local data count: %d", ret); - } - return errCode != E_OK ? errCode : ret; -} - bool SQLiteUtils::IsStmtReadOnly(sqlite3_stmt *statement) { if (statement == nullptr) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp index 7536ee53..b691cd14 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp @@ -16,6 +16,7 @@ #include "storage_engine.h" #include +#include #include "db_common.h" #include "db_errno.h" @@ -37,11 +38,14 @@ StorageEngine::StorageEngine() perm_(OperatePerm::NORMAL_PERM), operateAbort_(false), isExistConnection_(false), + readPendingCount_(0), + externalReadPendingCount_(0), engineState_(EngineState::INVALID) {} StorageEngine::~StorageEngine() { + LOGI("[StorageEngine] close executor"); CloseExecutor(); } @@ -55,13 +59,15 @@ int StorageEngine::InitAllReadWriteExecutor() return InitReadWriteExecutors(); } -OpenDbProperties StorageEngine::GetOption() +OpenDbProperties StorageEngine::GetOption() const { + std::lock_guard autoLock(optionMutex_); return option_; } int StorageEngine::InitReadWriteExecutors() { + PrintDbFileMsg(true); int errCode = E_OK; std::scoped_lock initLock(writeMutex_, readMutex_); // only for create the database avoid the minimum number is 0. @@ -199,42 +205,91 @@ StorageExecutor *StorageEngine::FindWriteExecutor(OperatePerm perm, int &errCode StorageExecutor *StorageEngine::FindReadExecutor(OperatePerm perm, int &errCode, int waitTime, bool isExternal) { - std::unique_lock lock(readMutex_); - errCode = -E_BUSY; - if (perm_ == OperatePerm::DISABLE_PERM || perm_ != perm) { - LOGI("Not permitted to get the executor[%u]", static_cast(perm_)); - return nullptr; - } - - std::list &readUsingList = isExternal ? externalReadUsingList_ : readUsingList_; - std::list &readIdleList = isExternal ? externalReadIdleList_ : readIdleList_; - if (waitTime <= 0) { // non-blocking. - if (readIdleList.empty() && - readIdleList.size() + readUsingList.size() == engineAttr_.maxReadNum) { + auto &pendingCount = isExternal ? externalReadPendingCount_ : readPendingCount_; + bool isNeedCreate = false; + { + std::unique_lock lock(readMutex_); + errCode = -E_BUSY; + if (perm_ == OperatePerm::DISABLE_PERM || perm_ != perm) { + LOGI("Not permitted to get the executor[%u]", static_cast(perm_)); return nullptr; } - return FetchStorageExecutor(false, readIdleList, readUsingList, errCode, isExternal); + std::list &readUsingList = isExternal ? externalReadUsingList_ : readUsingList_; + std::list &readIdleList = isExternal ? externalReadIdleList_ : readIdleList_; + if (waitTime <= 0) { // non-blocking. + auto pending = static_cast(pendingCount.load()); + if (readIdleList.empty() && readUsingList.size() + pending == engineAttr_.maxReadNum) { + return nullptr; + } + } else { + // Not prohibited and there is an available handle + uint32_t maxReadHandleNum = isExternal ? 1 : engineAttr_.maxReadNum; + bool result = readCondition_.wait_for(lock, std::chrono::seconds(waitTime), + [this, &perm, &readUsingList, &readIdleList, &maxReadHandleNum, &pendingCount]() { + auto pending = static_cast(pendingCount.load()); + bool isHandleLessMax; + if (readIdleList.size() > pending) { + // readIdleList.size() + readUsingList.size() - 1 should not greater than maxReadHandleNum + // -1 because handle will use from idle list + isHandleLessMax = readIdleList.size() + readUsingList.size() < maxReadHandleNum + 1; + } else { + isHandleLessMax = pending + readUsingList.size() < maxReadHandleNum; + } + return (perm_ == OperatePerm::NORMAL_PERM || perm_ == perm) && (isHandleLessMax || operateAbort_); + }); + if (operateAbort_) { + LOGI("Abort find read executor and busy for operate!"); + return nullptr; + } + if (!result) { + LOGI("Get read handle result[%d], permissType[%u], operType[%u], read[%zu-%zu-%" PRIu32 "]" + "pending count[%d]", result, static_cast(perm_), static_cast(perm), + readIdleList.size(), readUsingList.size(), engineAttr_.maxReadNum, pendingCount.load()); + return nullptr; + } + } + pendingCount++; + isNeedCreate = readIdleList.size() < static_cast(pendingCount.load()); } + auto executor = FetchReadStorageExecutor(errCode, isExternal, isNeedCreate); + readCondition_.notify_all(); + return executor; +} - // Not prohibited and there is an available handle - uint32_t maxReadHandleNum = isExternal ? 1 : engineAttr_.maxReadNum; - bool result = readCondition_.wait_for(lock, std::chrono::seconds(waitTime), - [this, &perm, &readUsingList, &readIdleList, &maxReadHandleNum]() { - return (perm_ == OperatePerm::NORMAL_PERM || perm_ == perm) && - (!readIdleList.empty() || (readIdleList.size() + readUsingList.size() < maxReadHandleNum) || - operateAbort_); - }); - if (operateAbort_) { - LOGI("Abort find read executor and busy for operate!"); - return nullptr; +StorageExecutor *StorageEngine::FetchReadStorageExecutor(int &errCode, bool isExternal, bool isNeedCreate) +{ + StorageExecutor *handle = nullptr; + if (isNeedCreate) { + errCode = CreateNewExecutor(false, handle); } - if (!result) { - LOGI("Get read handle result[%d], permissType[%u], operType[%u], read[%zu-%zu-%" PRIu32 "]", result, - static_cast(perm_), static_cast(perm), readIdleList.size(), readUsingList.size(), - engineAttr_.maxReadNum); - return nullptr; + std::unique_lock lock(readMutex_); + auto &pendingCount = isExternal ? externalReadPendingCount_ : readPendingCount_; + pendingCount--; + if (isNeedCreate) { + auto &usingList = isExternal ? externalReadUsingList_ : readUsingList_; + if ((errCode != E_OK) || (handle == nullptr)) { + if (errCode != -E_EKEYREVOKED) { + return nullptr; + } + LOGE("Key revoked status, couldn't create the new executor"); + if (!usingList.empty()) { + LOGE("Can't create new executor for revoked"); + errCode = -E_BUSY; + } + return nullptr; + } + AddStorageExecutor(handle, isExternal); } - return FetchStorageExecutor(false, readIdleList, readUsingList, errCode, isExternal); + auto &usingList = isExternal ? externalReadUsingList_ : readUsingList_; + auto &idleList = isExternal ? externalReadIdleList_ : readIdleList_; + auto item = idleList.front(); + usingList.push_back(item); + idleList.remove(item); + if (!isEnhance_) { + LOGD("Get executor[0] from [%.3s]", hashIdentifier_.c_str()); + } + errCode = E_OK; + return item; } void StorageEngine::Recycle(StorageExecutor *&handle, bool isExternal) @@ -263,21 +318,25 @@ void StorageEngine::Recycle(StorageExecutor *&handle, bool isExternal) idleCondition_.notify_all(); } } else { - std::unique_lock lock(readMutex_); - std::list &readUsingList = isExternal ? externalReadUsingList_ : readUsingList_; - std::list &readIdleList = isExternal ? externalReadIdleList_ : readIdleList_; - auto iter = std::find(readUsingList.begin(), readUsingList.end(), handle); - if (iter != readUsingList.end()) { - readUsingList.remove(handle); - if (!readIdleList.empty()) { - delete handle; - handle = nullptr; - return; + StorageExecutor *releaseHandle = nullptr; + { + std::unique_lock lock(readMutex_); + std::list &readUsingList = isExternal ? externalReadUsingList_ : readUsingList_; + std::list &readIdleList = isExternal ? externalReadIdleList_ : readIdleList_; + auto iter = std::find(readUsingList.begin(), readUsingList.end(), handle); + if (iter != readUsingList.end()) { + readUsingList.remove(handle); + if (!readIdleList.empty()) { + releaseHandle = handle; + handle = nullptr; + } else { + handle->Reset(); + readIdleList.push_back(handle); + readCondition_.notify_one(); + } } - handle->Reset(); - readIdleList.push_back(handle); - readCondition_.notify_one(); } + delete releaseHandle; } handle = nullptr; } @@ -449,6 +508,7 @@ void StorageEngine::CloseExecutor() ClearHandleList(readIdleList_); ClearHandleList(externalReadIdleList_); } + PrintDbFileMsg(false); } StorageExecutor *StorageEngine::FetchStorageExecutor(bool isWrite, std::list &idleList, @@ -526,4 +586,72 @@ void StorageEngine::SetSchemaChangedCallback(const std::function &cal std::unique_lock lock(schemaChangedMutex_); schemaChangedFunc_ = callback; } + +void StorageEngine::PrintDbFileMsg(bool isOpen) +{ + OpenDbProperties option = GetOption(); + std::string dbFilePath = option.uri; + if (option.isMemDb || dbFilePath.empty()) { + return; + } + struct stat dbFileStat; + if (memset_s(&dbFileStat, sizeof(struct stat), 0, sizeof(struct stat)) != E_OK) { + LOGW("init db file stat fail"); + return; + } + stat(dbFilePath.c_str(), &dbFileStat); + std::string dbWalFilePath = dbFilePath + "-wal"; + struct stat dbWalFileStat; + if (memset_s(&dbWalFileStat, sizeof(struct stat), 0, sizeof(struct stat)) != E_OK) { + LOGW("init db wal file stat fail"); + return; + } + stat(dbWalFilePath.c_str(), &dbWalFileStat); + std::string dbShmFilePath = dbFilePath + "-shm"; + struct stat dbShmFileStat; + if (memset_s(&dbShmFileStat, sizeof(struct stat), 0, sizeof(struct stat)) != E_OK) { + LOGW("init db shm file stat fail"); + return; + } + stat(dbShmFilePath.c_str(), &dbShmFileStat); + std::string dbDwrFilePath = dbFilePath + "-dwr"; + struct stat dbDwrFileStat; + if (memset_s(&dbDwrFileStat, sizeof(struct stat), 0, sizeof(struct stat)) != E_OK) { + LOGW("init db dwr file stat fail"); + return; + } + stat(dbDwrFilePath.c_str(), &dbDwrFileStat); + std::string stage = isOpen ? "before open db," : "after close db,"; +#ifdef __linux__ + LOGI("%s db file: [size: %lld, mtime: %lld, inode: %llu], db-wal file: [size: %lld, mtime: %lld, inode: %llu], " + "db-shm file: [size: %lld, mtime: %lld, inode: %llu], db-dwr file: [size: %lld, mtime: %lld, inode: %llu]", + stage.c_str(), dbFileStat.st_size, dbFileStat.st_mtim.tv_sec, dbFileStat.st_ino, dbWalFileStat.st_size, + dbWalFileStat.st_mtim.tv_sec, dbWalFileStat.st_ino, dbShmFileStat.st_size, dbShmFileStat.st_mtim.tv_sec, + dbShmFileStat.st_ino, dbDwrFileStat.st_size, dbDwrFileStat.st_mtim.tv_sec, dbDwrFileStat.st_ino); +#endif +} + +void StorageEngine::SetUri(const std::string &uri) +{ + std::lock_guard autoLock(optionMutex_); + option_.uri = uri; +} + +void StorageEngine::SetSQL(const std::vector &sql) +{ + std::lock_guard autoLock(optionMutex_); + option_.sqls = sql; +} + +void StorageEngine::SetSecurityOption(const SecurityOption &option) +{ + std::lock_guard autoLock(optionMutex_); + option_.securityOpt = option; +} + +void StorageEngine::SetCreateIfNecessary(bool isCreateIfNecessary) +{ + std::lock_guard autoLock(optionMutex_); + option_.createIfNecessary = isCreateIfNecessary; +} } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.h index 98085581..cf3c514b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.h @@ -94,7 +94,7 @@ public: int InitAllReadWriteExecutor(); - OpenDbProperties GetOption(); + OpenDbProperties GetOption() const; protected: virtual int CreateNewExecutor(bool isWrite, StorageExecutor *&handle) = 0; @@ -107,6 +107,12 @@ protected: int InitReadWriteExecutors(); + void SetUri(const std::string &uri); + void SetSQL(const std::vector &sql); + void SetSecurityOption(const SecurityOption &option); + void SetCreateIfNecessary(bool isCreateIfNecessary); + + mutable std::mutex optionMutex_; OpenDbProperties option_; StorageEngineAttr engineAttr_; @@ -138,8 +144,12 @@ private: StorageExecutor *FindWriteExecutor(OperatePerm perm, int &errCode, int waitTime, bool isExternal = false); StorageExecutor *FindReadExecutor(OperatePerm perm, int &errCode, int waitTime, bool isExternal = false); + StorageExecutor *FetchReadStorageExecutor(int &errCode, bool isExternal, bool isNeedCreate); + virtual void ClearCorruptedFlag(); + void PrintDbFileMsg(bool isOpen); + static const int MAX_WAIT_TIME; static const int MAX_WRITE_SIZE; static const int MAX_READ_SIZE; @@ -167,6 +177,9 @@ private: std::mutex idleMutex_; std::condition_variable idleCondition_; + std::atomic readPendingCount_; + std::atomic externalReadPendingCount_; + EngineState engineState_; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp index 0899eafe..ff7526fc 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp @@ -71,10 +71,6 @@ int StorageProxy::GetLocalWaterMarkByMode(const std::string &tableName, CloudWat if (cloudMetaData_ == nullptr) { return -E_INVALID_DB; } - if (transactionExeFlag_.load() && isWrite_.load()) { - LOGE("the write transaction has been started, can not get meta"); - return -E_BUSY; - } return cloudMetaData_->GetLocalWaterMarkByType(AppendWithUserIfNeed(tableName), mode, localMark); } @@ -122,41 +118,41 @@ int StorageProxy::SetCloudWaterMark(const std::string &tableName, std::string &c return cloudMetaData_->SetCloudWaterMark(AppendWithUserIfNeed(tableName), cloudMark); } -int StorageProxy::StartTransaction(TransactType type) +int StorageProxy::StartTransaction(TransactType type, bool isAsyncDownload) { std::shared_lock readLock(storeMutex_); if (store_ == nullptr) { return -E_INVALID_DB; } - int errCode = store_->StartTransaction(type); - if (errCode == E_OK) { + int errCode = store_->StartTransaction(type, isAsyncDownload); + if (errCode == E_OK && !isAsyncDownload) { transactionExeFlag_.store(true); isWrite_.store(type == TransactType::IMMEDIATE); } return errCode; } -int StorageProxy::Commit() +int StorageProxy::Commit(bool isAsyncDownload) { std::shared_lock readLock(storeMutex_); if (store_ == nullptr) { return -E_INVALID_DB; } - int errCode = store_->Commit(); - if (errCode == E_OK) { + int errCode = store_->Commit(isAsyncDownload); + if (errCode == E_OK && !isAsyncDownload) { transactionExeFlag_.store(false); } return errCode; } -int StorageProxy::Rollback() +int StorageProxy::Rollback(bool isAsyncDownload) { std::shared_lock readLock(storeMutex_); if (store_ == nullptr) { return -E_INVALID_DB; } - int errCode = store_->Rollback(); - if (errCode == E_OK) { + int errCode = store_->Rollback(isAsyncDownload); + if (errCode == E_OK && !isAsyncDownload) { transactionExeFlag_.store(false); } return errCode; @@ -169,10 +165,6 @@ int StorageProxy::GetUploadCount(const QuerySyncObject &query, const bool isClou if (store_ == nullptr) { return -E_INVALID_DB; } - if (!transactionExeFlag_.load()) { - LOGE("the transaction has not been started"); - return -E_TRANSACT_STATE; - } std::vector timeStampVec; std::vector waterTypeVec = DBCommon::GetWaterTypeVec(); for (size_t i = 0; i < waterTypeVec.size(); i++) { @@ -196,10 +188,6 @@ int StorageProxy::GetUploadCount(const std::string &tableName, const Timestamp & if (store_ == nullptr) { return -E_INVALID_DB; } - if (!transactionExeFlag_.load()) { - LOGE("the transaction has not been started"); - return -E_TRANSACT_STATE; - } QuerySyncObject query; query.SetTableName(tableName); return store_->GetUploadCount(query, localMark, isCloudForcePush, false, count); @@ -212,10 +200,6 @@ int StorageProxy::GetUploadCount(const QuerySyncObject &query, const Timestamp & if (store_ == nullptr) { return -E_INVALID_DB; } - if (!transactionExeFlag_.load()) { - LOGE("the transaction has not been started"); - return -E_TRANSACT_STATE; - } return store_->GetUploadCount(query, localMark, isCloudForcePush, isCompensatedTask, count); } @@ -234,10 +218,6 @@ int StorageProxy::GetCloudData(const QuerySyncObject &querySyncObject, const Tim if (store_ == nullptr) { return -E_INVALID_DB; } - if (!transactionExeFlag_.load()) { - LOGE("the transaction has not been started"); - return -E_TRANSACT_STATE; - } TableSchema tableSchema; int errCode = store_->GetCloudTableSchema(querySyncObject.GetRelationTableName(), tableSchema); if (errCode != E_OK) { @@ -252,10 +232,6 @@ int StorageProxy::GetCloudDataNext(ContinueToken &continueStmtToken, CloudSyncDa if (store_ == nullptr) { return -E_INVALID_DB; } - if (!transactionExeFlag_.load()) { - LOGE("the transaction has not been started"); - return -E_TRANSACT_STATE; - } return store_->GetCloudDataNext(continueStmtToken, cloudDataResult); } @@ -523,10 +499,6 @@ int StorageProxy::FillCloudLogAndAsset(OpType opType, const CloudSyncData &data) if (store_ == nullptr) { return -E_INVALID_DB; } - if (!transactionExeFlag_.load()) { - LOGE("the transaction has not been started"); - return -E_TRANSACT_STATE; - } return store_->FillCloudLogAndAsset(opType, data, true, false); } @@ -872,4 +844,10 @@ bool StorageProxy::IsExistTableContainAssets() } return store_->IsExistTableContainAssets(); } + +bool StorageProxy::GetTransactionExeFlag() +{ + std::shared_lock readLock(storeMutex_); + return transactionExeFlag_.load(); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.cpp index 620302dd..e20d9858 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.cpp @@ -43,7 +43,7 @@ SyncAbleEngine::~SyncAbleEngine() } // Start a sync action. -int SyncAbleEngine::Sync(const ISyncer::SyncParma &parm, uint64_t connectionId) +int SyncAbleEngine::Sync(const ISyncer::SyncParam &parm, uint64_t connectionId) { if (!started_) { int errCode = StartSyncer(); @@ -121,13 +121,13 @@ int SyncAbleEngine::StartSyncerWithNoLock(bool isCheckSyncActive, bool isNeedAct // active to non_active userChangeListener_ = RuntimeContext::GetInstance()->RegisterUserChangedListener( [this](void *) { ChangeUserListener(); }, UserChangeMonitor::USER_ACTIVE_TO_NON_ACTIVE_EVENT); - LOGI("[StartSyncerWithNoLock] [%.3s] After RegisterUserChangedListener", label.c_str()); + LOGI("[StartSyncerWithNoLock] [%.3s]", label.c_str()); } else if (isSyncDualTupleMode && (userChangeListener_ == nullptr)) { EventType event = isNeedActive ? UserChangeMonitor::USER_ACTIVE_EVENT : UserChangeMonitor::USER_NON_ACTIVE_EVENT; userChangeListener_ = RuntimeContext::GetInstance()->RegisterUserChangedListener( [this](void *) { UserChangeHandle(); }, event); - LOGI("[StartSyncerWithNoLock] [%.3s] After RegisterUserChangedListener event=%d", label.c_str(), event); + LOGI("[StartSyncerWithNoLock] [%.3s] event=%d", label.c_str(), event); } return errCode; } @@ -291,4 +291,13 @@ int SyncAbleEngine::GetHashDeviceId(const std::string &clientId, std::string &ha } return syncer_.GetHashDeviceId(clientId, hashDevId); } + +int SyncAbleEngine::GetDeviceSyncTaskCount() +{ + if (NeedStartSyncer()) { + LOGW("[SyncAbleEngine] Syncer not start when get device sync task count"); + return 0; + } + return syncer_.GetTaskCount(); +} } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.h index f1ab74cd..307d2033 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_engine.h @@ -29,7 +29,7 @@ public: ~SyncAbleEngine(); // Start a sync action. - int Sync(const ISyncer::SyncParma &parm, uint64_t connectionId); + int Sync(const ISyncer::SyncParam &parm, uint64_t connectionId); void WakeUpSyncer(); void Close(); @@ -50,6 +50,8 @@ public: uint64_t connectionId, std::shared_ptr &result); int GetHashDeviceId(const std::string &clientId, std::string &hashDevId); + + int GetDeviceSyncTaskCount(); private: // Start syncer int StartSyncer(bool isCheckSyncActive = false, bool isNeedActive = true); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/include/isyncer.h b/kv_store/frameworks/libs/distributeddb/syncer/include/isyncer.h index 61e0c44c..426f83df 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/include/isyncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/include/isyncer.h @@ -35,7 +35,7 @@ struct SyncerBasicInfo { }; class ISyncer { public: - struct SyncParma { + struct SyncParam { std::vector devices; std::function &devicesMap)> onComplete; SyncStatusCallback relationOnComplete; @@ -43,6 +43,7 @@ public: int mode = 0; bool wait = false; bool isQuerySync = false; + bool isRetry = true; QuerySyncObject syncQuery; DeviceSyncProcessCallback onSyncProcess; }; @@ -65,8 +66,8 @@ public: const std::function &)> &onComplete, const std::function &onFinalize, bool wait) = 0; - // Sync function. use SyncParma to reduce parameter. - virtual int Sync(const SyncParma ¶m, uint64_t connectionId) = 0; + // Sync function. use SyncParam to reduce parameter. + virtual int Sync(const SyncParam ¶m, uint64_t connectionId) = 0; // Cancel sync function. virtual int CancelSync(uint32_t syncId) = 0; @@ -139,6 +140,8 @@ public: virtual int64_t GetLocalTimeOffset() = 0; virtual int32_t GetTaskCount() = 0; + + virtual bool ExchangeClosePending(bool expected) = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/include/syncer_proxy.h b/kv_store/frameworks/libs/distributeddb/syncer/include/syncer_proxy.h index 0f6d5bc7..481d592d 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/include/syncer_proxy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/include/syncer_proxy.h @@ -45,8 +45,8 @@ public: const std::function &)> &onComplete, const std::function &onFinalize, bool wait) override; - // Sync function. use SyncParma to reduce parameter. - int Sync(const SyncParma ¶m, uint64_t connectionId) override; + // Sync function. use SyncParam to reduce parameter. + int Sync(const SyncParam ¶m, uint64_t connectionId) override; // Cancel sync function. int CancelSync(uint32_t syncId) override; @@ -121,6 +121,8 @@ public: int64_t GetLocalTimeOffset() override; int32_t GetTaskCount() override; + + bool ExchangeClosePending(bool expected) override; private: std::mutex syncerLock_; std::shared_ptr syncer_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp index 992b60b5..6e549656 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp @@ -17,6 +17,7 @@ #include "cloud/cloud_storage_utils.h" #include "db_common.h" #include "db_errno.h" +#include "kv_store_errno.h" #include "log_print.h" namespace DistributedDB { @@ -92,11 +93,21 @@ void CloudDBProxy::RecordSyncDataTimeStampLog(std::vector &data, InnerA static_cast(action), data.size(), first, last); } +void CloudDBProxy::FillErrorToExtend(int error, std::vector &extend) +{ + for (auto &item : extend) { + if (item.find(CloudDbConstant::ERROR_FIELD) == item.end()) { + item[CloudDbConstant::ERROR_FIELD] = static_cast(TransferDBErrno(error)); + } + } +} + int CloudDBProxy::BatchInsert(const std::string &tableName, std::vector &record, std::vector &extend, Info &uploadInfo, uint32_t &retryCount) { std::shared_lock readLock(cloudMutex_); if (iCloudDb_ == nullptr) { + FillErrorToExtend(static_cast(-E_CLOUD_ERROR), extend); return -E_CLOUD_ERROR; } std::shared_ptr cloudDb = iCloudDb_; @@ -115,6 +126,7 @@ int CloudDBProxy::BatchUpdate(const std::string &tableName, std::vector { std::shared_lock readLock(cloudMutex_); if (iCloudDb_ == nullptr) { + FillErrorToExtend(static_cast(-E_CLOUD_ERROR), extend); return -E_CLOUD_ERROR; } std::shared_ptr cloudDb = iCloudDb_; @@ -133,6 +145,7 @@ int CloudDBProxy::BatchDelete(const std::string &tableName, std::vector { std::shared_lock readLock(cloudMutex_); if (iCloudDb_ == nullptr) { + FillErrorToExtend(static_cast(-E_CLOUD_ERROR), extend); return -E_CLOUD_ERROR; } std::shared_ptr context = std::make_shared(); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h index c6380557..2383c018 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h @@ -198,6 +198,8 @@ protected: static void RecordSyncDataTimeStampLog(std::vector &data, InnerActionCode action); + void FillErrorToExtend(int error, std::vector &extend); + mutable std::shared_mutex cloudMutex_; mutable std::shared_mutex assetLoaderMutex_; std::shared_ptr iCloudDb_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp index f6bcc943..ff6262cc 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp @@ -238,8 +238,8 @@ int CloudSyncUtils::CheckCloudSyncDataValid(const CloudSyncData &uploadData, con int64_t syncDataCount = static_cast(insRecordLen) + static_cast(updRecordLen) + static_cast(delRecordLen); if (syncDataCount > count) { - LOGE("[CloudSyncUtils] Size of a batch of sync data is greater than upload data size. count %d", count); - return -E_INTERNAL_ERROR; + LOGW("[CloudSyncUtils] Size of a batch of sync data is greater than upload data size. insRecordLen:%zu, " + "updRecordLen:%zu, delRecordLen:%zu, count %d", insRecordLen, updRecordLen, delRecordLen, count); } return E_OK; } @@ -477,7 +477,7 @@ int CloudSyncUtils::FillAssetIdToAssets(CloudSyncBatch &data, int errorCode, con } auto extendIt = data.extend[i].find(col); if (extendIt == data.extend[i].end()) { - LOGI("[CloudSyncUtils] Asset field name can not find in extend. key is:%s.", col.c_str()); + LOGI("[CloudSyncUtils] Asset field name can not find in extend."); it = data.assets[i].erase(it); continue; } @@ -669,7 +669,9 @@ void CloudSyncUtils::CheckQueryCloudData(std::string &traceId, DownloadData &dow } std::string gid; (void)CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::GID_FIELD, data, gid); - if (!isVersionExist || !isContainAllPk) { + bool isDelete = true; + (void)CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::DELETE_FIELD, data, isDelete); + if (!isDelete && (!isVersionExist || !isContainAllPk)) { LOGE("[CloudSyncer] Invalid data from cloud, no version[%d], lost primary key[%d], gid[%s], traceId[%s]", static_cast(!isVersionExist), static_cast(!isContainAllPk), gid.c_str(), traceId.c_str()); } @@ -1005,4 +1007,55 @@ int CloudSyncUtils::ClearCloudWatermark(const std::vector &tableNam return storageProxy->Commit(); } + +bool CloudSyncUtils::HaveReferenceOrReferenceByTable( + const CloudSyncer::CloudTaskInfo &taskInfo, std::shared_ptr &storageProxy) +{ + for (size_t i = 0u; i < taskInfo.table.size(); ++i) { + if (storageProxy->IsTableExistReferenceOrReferenceBy(taskInfo.table[i])) { + return true; + } + } + return false; +} + +int CloudSyncUtils::StartTransactionIfNeed( + const CloudSyncer::CloudTaskInfo &taskInfo, std::shared_ptr &storageProxy) +{ + bool isStartTransaction = true; + if (taskInfo.table.size() <= 1u || !HaveReferenceOrReferenceByTable(taskInfo, storageProxy)) { + // only one table or no reference table, no need to start transaction. + isStartTransaction = false; + } + return isStartTransaction ? storageProxy->StartTransaction() : E_OK; +} + +void CloudSyncUtils::EndTransactionIfNeed( + const int &errCode, const CloudSyncer::CloudTaskInfo &taskInfo, std::shared_ptr &storageProxy) +{ + if (!storageProxy->GetTransactionExeFlag()) { + // no need to end transaction. + return; + } + if (errCode == E_OK || errCode == -E_TASK_PAUSED) { + int commitErrorCode = storageProxy->Commit(); + if (commitErrorCode != E_OK) { + LOGE("[CloudSyncer] cannot commit transaction: %d.", commitErrorCode); + } + } else { + int rollBackErrorCode = storageProxy->Rollback(); + if (rollBackErrorCode != E_OK) { + LOGE("[CloudSyncer] cannot roll back transaction: %d.", rollBackErrorCode); + } + } +} + +bool CloudSyncUtils::CanStartAsyncDownload(int scheduleCount) +{ + if (!RuntimeContext::GetInstance()->GetAssetsDownloadManager()->CanStartNewTask()) { + LOGW("[CloudSyncer] Too many download tasks"); + return false; + } + return scheduleCount <= 0; +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h index b8960b60..6f74ab32 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h @@ -140,6 +140,17 @@ public: static int ClearCloudWatermark(const std::vector &tableNameList, std::shared_ptr &storageProxy); + + static bool HaveReferenceOrReferenceByTable( + const CloudSyncer::CloudTaskInfo &taskInfo, std::shared_ptr &storageProxy); + + static int StartTransactionIfNeed( + const CloudSyncer::CloudTaskInfo &taskInfo, std::shared_ptr &storageProxy); + + static void EndTransactionIfNeed( + const int &errCode, const CloudSyncer::CloudTaskInfo &taskInfo, std::shared_ptr &storageProxy); + + static bool CanStartAsyncDownload(int scheduleCount); private: static void InsertOrReplaceChangedDataByType(ChangeType type, std::vector &pkVal, ChangedData &changedData); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp index d0c91c94..7a774ae1 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp @@ -46,6 +46,7 @@ CloudSyncer::CloudSyncer( policy_(policy), asyncTaskId_(INVALID_TASK_ID), cancelAsyncTask_(false), + scheduleTaskCount_(0), waitDownloadListener_(nullptr) { if (storageProxy_ != nullptr) { @@ -227,6 +228,7 @@ int CloudSyncer::DoSync(TaskId taskId) } bool needUpload = true; bool isNeedFirstDownload = false; + bool isLockAction = IsLockInDownload(); { std::lock_guard autoLock(dataLock_); if (currentContext_.strategy != nullptr) { @@ -234,13 +236,13 @@ int CloudSyncer::DoSync(TaskId taskId) } // 1. if the locker is already exist, directly reuse the lock, no need do the first download // 2. if the task(resume task) is already be tagged need upload data, no need do the first download - isNeedFirstDownload = (currentContext_.locker == nullptr) && (!currentContext_.isNeedUpload); + isNeedFirstDownload = (currentContext_.locker == nullptr) && (!currentContext_.isNeedUpload) && + isLockAction; } - int errCode = E_OK; bool isFirstDownload = true; if (isNeedFirstDownload) { // do first download - errCode = DoDownloadInNeed(taskInfo, needUpload, isFirstDownload); + int errCode = DoDownloadInNeed(taskInfo, needUpload, isFirstDownload); SetTaskFailed(taskId, errCode); if (errCode != E_OK) { SyncMachineDoFinished(); @@ -264,8 +266,7 @@ int CloudSyncer::DoSync(TaskId taskId) currentContext_.isFirstDownload = isFirstDownload; currentContext_.isRealNeedUpload = needUpload; } - errCode = DoSyncInner(taskInfo); - return errCode; + return DoSyncInner(taskInfo); } int CloudSyncer::PrepareAndUpload(const CloudTaskInfo &taskInfo, size_t index) @@ -306,7 +307,7 @@ int CloudSyncer::DoUploadInNeed(const CloudTaskInfo &taskInfo, const bool needUp return E_OK; } storageProxy_->BeforeUploadTransaction(); - int errCode = storageProxy_->StartTransaction(); + int errCode = CloudSyncUtils::StartTransactionIfNeed(taskInfo, storageProxy_); if (errCode != E_OK) { LOGE("[CloudSyncer] start transaction failed before doing upload."); return errCode; @@ -332,17 +333,7 @@ int CloudSyncer::DoUploadInNeed(const CloudTaskInfo &taskInfo, const bool needUp std::lock_guard autoLock(dataLock_); resumeTaskInfos_[taskInfo.taskId].upload = true; } - if (errCode == E_OK || errCode == -E_TASK_PAUSED) { - int commitErrorCode = storageProxy_->Commit(); - if (commitErrorCode != E_OK) { - LOGE("[CloudSyncer] cannot commit transaction: %d.", commitErrorCode); - } - } else { - int rollBackErrorCode = storageProxy_->Rollback(); - if (rollBackErrorCode != E_OK) { - LOGE("[CloudSyncer] cannot roll back transaction: %d.", rollBackErrorCode); - } - } + CloudSyncUtils::EndTransactionIfNeed(errCode, taskInfo, storageProxy_); return errCode; } @@ -443,7 +434,9 @@ CloudSyncEvent CloudSyncer::SyncMachineDoFinished() taskInfo = cloudTaskInfos_[currentContext_.currentTaskId]; } taskInfo.status = ProcessStatus::FINISHED; - currentContext_.notifier->NotifyProcess(taskInfo, {}, true); + if (currentContext_.notifier != nullptr) { + currentContext_.notifier->NotifyProcess(taskInfo, {}, true); + } { std::lock_guard autoLock(dataLock_); cloudTaskInfos_[currentContext_.currentTaskId].errCode = E_OK; @@ -884,7 +877,7 @@ int CloudSyncer::SaveData(CloudSyncer::TaskId taskId, SyncParam ¶m) param.info.downLoadInfo.successCount += param.downloadData.data.size(); // Get latest cloudWaterMark VBucket &lastData = param.downloadData.data.back(); - if (!IsQueryListEmpty(taskId) && param.isLastBatch) { + if (!IsNeedProcessCloudCursor(taskId) && param.isLastBatch) { // the last batch of cursor in the conditional query is useless param.cloudWaterMark = {}; } else { @@ -1229,9 +1222,11 @@ int CloudSyncer::DoBatchUpload(CloudSyncData &uploadData, UploadParam &uploadPar if (errCode != E_OK) { return errCode; } - bool lastBatch = (innerProcessInfo.upLoadInfo.successCount + innerProcessInfo.upLoadInfo.failCount) == + bool lastBatch = (innerProcessInfo.upLoadInfo.successCount + innerProcessInfo.upLoadInfo.failCount) >= innerProcessInfo.upLoadInfo.total; if (lastBatch) { + innerProcessInfo.upLoadInfo.total = + (innerProcessInfo.upLoadInfo.successCount + innerProcessInfo.upLoadInfo.failCount); innerProcessInfo.tableStatus = ProcessStatus::FINISHED; } // After each batch upload successed, call NotifyProcess @@ -1252,7 +1247,7 @@ int CloudSyncer::PutWaterMarkAfterBatchUpload(const std::string &tableName, Uplo storageProxy_->ReleaseUploadRecord(tableName, uploadParam.mode, uploadParam.localMark); // if we use local cover cloud strategy, it won't update local water mark also. if (IsModeForcePush(uploadParam.taskId) || (IsPriorityTask(uploadParam.taskId) && - !IsQueryListEmpty(uploadParam.taskId))) { + !IsNeedProcessCloudCursor(uploadParam.taskId))) { return E_OK; } errCode = storageProxy_->PutWaterMarkByMode(tableName, uploadParam.mode, uploadParam.localMark); @@ -1349,7 +1344,7 @@ int CloudSyncer::SaveCloudWaterMark(const TableName &tableName, const TaskId tas cloudWaterMark = currentContext_.cloudWaterMarks[currentContext_.currentUserIndex][tableName]; isUpdateCloudCursor = currentContext_.strategy->JudgeUpdateCursor(); } - isUpdateCloudCursor = isUpdateCloudCursor && !(IsPriorityTask(taskId) && !IsQueryListEmpty(taskId)); + isUpdateCloudCursor = isUpdateCloudCursor && !(IsPriorityTask(taskId) && !IsNeedProcessCloudCursor(taskId)); if (isUpdateCloudCursor) { int errCode = storageProxy_->SetCloudWaterMark(tableName, cloudWaterMark); if (errCode != E_OK) { @@ -1402,11 +1397,11 @@ int CloudSyncer::PreHandleData(VBucket &datum, const std::vector &p if (!std::get<2>(fieldIndex)) { // 2 is index of mandatory flag continue; } - LOGE("[CloudSyncer] Cloud data do not contain expected field: %s.", std::get<0>(fieldIndex).c_str()); + LOGE("[CloudSyncer] Cloud data do not contain expected field."); return -E_CLOUD_ERROR; } if (datum[std::get<0>(fieldIndex)].index() != static_cast(std::get<1>(fieldIndex))) { - LOGE("[CloudSyncer] Cloud data's field: %s, doesn't has expected type.", std::get<0>(fieldIndex).c_str()); + LOGE("[CloudSyncer] Cloud data's field, doesn't has expected type."); return -E_CLOUD_ERROR; } } @@ -1722,7 +1717,6 @@ int CloudSyncer::ClearCloudWatermark(const std::vector &tableNameLi int CloudSyncer::CleanWaterMarkInMemory(const std::set &tableNameList) { - std::lock_guard lock(syncMutex_); for (const auto &tableName: tableNameList) { int ret = storageProxy_->CleanWaterMarkInMemory(tableName); if (ret != E_OK) { @@ -1756,7 +1750,7 @@ int CloudSyncer::CommitDownloadResult(const DownloadItem &downloadItem, InnerPro uint32_t successCount = 0u; int ret = E_OK; if (info.isAsyncDownload) { - ret = CommitDownloadAssetsForAsyncDownload(downloadItem, info, commitList, successCount); + ret = HandleDownloadResultForAsyncDownload(downloadItem, info, commitList, successCount); } else { ret = HandleDownloadResult(downloadItem, info, commitList, successCount); } @@ -2061,21 +2055,19 @@ int CloudSyncer::DownloadOneAssetRecord(const std::set &dupHashKeySet, cons int CloudSyncer::GetSyncParamForDownload(TaskId taskId, SyncParam ¶m) { - int ret = E_OK; if (IsCurrentTableResume(taskId, false)) { std::lock_guard autoLock(dataLock_); if (resumeTaskInfos_[taskId].syncParam.tableName == currentContext_.tableName) { param = resumeTaskInfos_[taskId].syncParam; resumeTaskInfos_[taskId].syncParam = {}; - ret = storageProxy_->GetCloudWaterMark(param.tableName, param.cloudWaterMark); + int ret = storageProxy_->GetCloudWaterMark(param.tableName, param.cloudWaterMark); if (ret != E_OK) { - LOGE("[CloudSyncer] Cannot get cloud water level from cloud meta data when table is resume: %d.", ret); + LOGW("[CloudSyncer] Cannot get cloud water level from cloud meta data when table is resume: %d.", ret); } - LOGD("[CloudSyncer] Get sync param from cache"); return E_OK; } } - ret = GetCurrentTableName(param.tableName); + int ret = GetCurrentTableName(param.tableName); if (ret != E_OK) { LOGE("[CloudSyncer] Invalid table name for syncing: %d", ret); return ret; @@ -2088,12 +2080,14 @@ int CloudSyncer::GetSyncParamForDownload(TaskId taskId, SyncParam ¶m) LOGE("[CloudSyncer] Cannot get primary column names: %d", ret); return ret; } + std::shared_ptr notifier = nullptr; { std::lock_guard autoLock(dataLock_); currentContext_.assetFields[currentContext_.tableName] = assetFields; + notifier = currentContext_.notifier; } param.isSinglePrimaryKey = CloudSyncUtils::IsSinglePrimaryKey(param.pkColNames); - if (!IsModeForcePull(taskId) && (!IsPriorityTask(taskId) || IsQueryListEmpty(taskId))) { + if (!IsModeForcePull(taskId) && (!IsPriorityTask(taskId) || IsNeedProcessCloudCursor(taskId))) { ret = storageProxy_->GetCloudWaterMark(param.tableName, param.cloudWaterMark); if (ret != E_OK) { LOGE("[CloudSyncer] Cannot get cloud water level from cloud meta data: %d.", ret); @@ -2102,7 +2096,7 @@ int CloudSyncer::GetSyncParamForDownload(TaskId taskId, SyncParam ¶m) ReloadCloudWaterMarkIfNeed(param.tableName, param.cloudWaterMark); } } - currentContext_.notifier->GetDownloadInfoByTableName(param.info); + notifier->GetDownloadInfoByTableName(param.info); auto queryObject = GetQuerySyncObject(param.tableName); param.isAssetsOnly = queryObject.IsAssetsOnly(); param.groupNum = queryObject.GetGroupNum(); @@ -2139,7 +2133,11 @@ int CloudSyncer::DownloadDataFromCloud(TaskId taskId, SyncParam ¶m, bool isF param.cloudWaterMarkForAssetsOnly = param.cloudWaterMark; } int ret = QueryCloudData(taskId, param.info.tableName, param.cloudWaterMark, param.downloadData); - CloudSyncUtils::CheckQueryCloudData(cloudTaskInfos_[taskId].prepareTraceId, param.downloadData, param.pkColNames); + { + std::lock_guard autoLock(dataLock_); + CloudSyncUtils::CheckQueryCloudData( + cloudTaskInfos_[taskId].prepareTraceId, param.downloadData, param.pkColNames); + } if (ret == -E_QUERY_END) { // Won't break here since downloadData may not be null param.isLastBatch = true; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h index 0d773580..d6bc53b3 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h @@ -62,7 +62,9 @@ public: int ClearCloudWatermark(const std::vector &tableNameList); - int CleanKvCloudData(std::function &removeFunc); + int StopSyncTask(std::function &removeFunc); + + int StopTaskBeforeSetReference(std::function &setReferenceFunc); int CleanWaterMarkInMemory(const std::set &tableNameList); @@ -93,6 +95,8 @@ public: void SetGenCloudVersionCallback(const GenerateCloudVersionCallback &callback); SyncProcess GetCloudTaskStatus(uint64_t taskId) const; + + int ClearCloudWatermark(std::function &clearFunc); protected: struct TaskContext { TaskId currentTaskId = 0u; @@ -279,6 +283,9 @@ protected: int HandleDownloadResult(const DownloadItem &downloadItem, InnerProcessInfo &info, DownloadCommitList &commitList, uint32_t &successCount); + int HandleDownloadResultForAsyncDownload(const DownloadItem &downloadItem, InnerProcessInfo &info, + DownloadCommitList &commitList, uint32_t &successCount); + int FillDownloadExtend(TaskId taskId, const std::string &tableName, const std::string &cloudWaterMark, VBucket &extend); @@ -414,6 +421,8 @@ protected: bool IsNeedGetLocalWater(TaskId taskId); + bool IsNeedProcessCloudCursor(TaskId taskId); + void SetProxyUser(const std::string &user); void MergeTaskInfo(const std::shared_ptr &cloudSchema, TaskId taskId); @@ -516,8 +525,6 @@ protected: bool IsCurrentAsyncDownloadTask(); - bool CanStartAsyncDownload() const; - int GetCloudGidAndFillExtend(TaskId taskId, const std::string &tableName, QuerySyncObject &obj, VBucket &extend); int QueryCloudGidForAssetsOnly( @@ -543,6 +550,12 @@ protected: static void ModifyDownLoadInfoCount(const int errorCode, InnerProcessInfo &info); + void ChangeProcessStatusAndNotifyIfNeed(UploadParam &uploadParam, InnerProcessInfo &info); + + void ExecuteAsyncDownloadAssets(TaskId taskId); + + bool IsCloudForcePush(TaskId taskId); + mutable std::mutex dataLock_; TaskId lastTaskId_; std::multimap> taskQueue_; @@ -576,6 +589,7 @@ protected: std::condition_variable asyncTaskCv_; TaskId asyncTaskId_; std::atomic cancelAsyncTask_; + std::atomic scheduleTaskCount_; std::mutex listenerMutex_; NotificationChain::Listener *waitDownloadListener_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp index 1e9c5350..336a7608 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp @@ -107,8 +107,7 @@ int CloudSyncer::FillDownloadExtend(TaskId taskId, const std::string &tableName, int CloudSyncer::GetCloudGid(TaskId taskId, const std::string &tableName, QuerySyncObject &obj) { std::vector cloudGid; - bool isCloudForcePush = cloudTaskInfos_[taskId].mode == SYNC_MODE_CLOUD_FORCE_PUSH; - int errCode = storageProxy_->GetCloudGid(obj, isCloudForcePush, IsCompensatedTask(taskId), cloudGid); + int errCode = storageProxy_->GetCloudGid(obj, IsCloudForcePush(taskId), IsCompensatedTask(taskId), cloudGid); if (errCode != E_OK) { LOGE("[CloudSyncer] Failed to get cloud gid, %d.", errCode); } else if (!cloudGid.empty()) { @@ -121,8 +120,7 @@ int CloudSyncer::GetCloudGid(TaskId taskId, const std::string &tableName, QueryS int CloudSyncer::GetCloudGid( TaskId taskId, const std::string &tableName, QuerySyncObject &obj, std::vector &cloudGid) { - bool isCloudForcePush = cloudTaskInfos_[taskId].mode == SYNC_MODE_CLOUD_FORCE_PUSH; - int errCode = storageProxy_->GetCloudGid(obj, isCloudForcePush, IsCompensatedTask(taskId), cloudGid); + int errCode = storageProxy_->GetCloudGid(obj, IsCloudForcePush(taskId), IsCompensatedTask(taskId), cloudGid); if (errCode != E_OK) { LOGE("[CloudSyncer] Failed to get cloud gid, taskid:%" PRIu64 ", table name: %s, length: %zu, %d.", taskId, DBCommon::StringMiddleMasking(tableName).c_str(), tableName.length(), errCode); @@ -602,8 +600,8 @@ void CloudSyncer::GenerateCompensatedSync(CloudTaskInfo &taskInfo) { std::vector syncQuery; std::vector users; - int errCode = - CloudSyncUtils::GetQueryAndUsersForCompensatedSync(CanStartAsyncDownload(), storageProxy_, users, syncQuery); + int errCode = CloudSyncUtils::GetQueryAndUsersForCompensatedSync( + CloudSyncUtils::CanStartAsyncDownload(scheduleTaskCount_), storageProxy_, users, syncQuery); if (errCode != E_OK) { LOGW("[CloudSyncer] get query for compensated sync failed! errCode = %d", errCode); return; @@ -702,12 +700,10 @@ int CloudSyncer::UpdateFlagForSavedRecord(const SyncParam ¶m) downloadList = currentContext_.assetDownloadList; } std::set downloadGid; - std::set consistentGid; for (const auto &tuple : downloadList) { if (CloudSyncUtils::IsContainDownloading(tuple)) { downloadGid.insert(std::get(tuple)); } - consistentGid.insert(std::get(tuple)); } if (IsCurrentAsyncDownloadTask()) { int errCode = storageProxy_->MarkFlagAsAssetAsyncDownload(param.tableName, param.downloadData, downloadGid); @@ -716,7 +712,7 @@ int CloudSyncer::UpdateFlagForSavedRecord(const SyncParam ¶m) return errCode; } } - return storageProxy_->MarkFlagAsConsistent(param.tableName, param.downloadData, consistentGid); + return storageProxy_->MarkFlagAsConsistent(param.tableName, param.downloadData, downloadGid); } int CloudSyncer::BatchDelete(Info &deleteInfo, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo) @@ -773,11 +769,12 @@ void CloudSyncer::DoNotifyInNeed(const CloudSyncer::TaskId &taskId, const std::v const bool isFirstDownload) { bool isNeedNotify = false; + bool isLockAction = IsLockInDownload(); { std::lock_guard autoLock(dataLock_); // only when the first download and the task no need upload actually, notify the process, otherwise, // the process will notify in the upload procedure, which can guarantee the notify order of the tables - isNeedNotify = isFirstDownload && !currentContext_.isNeedUpload; + isNeedNotify = isFirstDownload && !currentContext_.isNeedUpload && isLockAction; } if (!isNeedNotify) { return; @@ -1068,6 +1065,12 @@ bool CloudSyncer::IsQueryListEmpty(TaskId taskId) }); } +bool CloudSyncer::IsNeedProcessCloudCursor(TaskId taskId) +{ + // Compensated task no need to save/get cloud cursor + return IsQueryListEmpty(taskId) && !IsCompensatedTask(taskId); +} + bool CloudSyncer::IsNeedLock(const UploadParam ¶m) { return param.lockAction == LockAction::INSERT && param.mode == CloudWaterType::INSERT; @@ -1083,6 +1086,15 @@ std::pair CloudSyncer::GetLocalWater(const std::string &tableNam return res; } +void CloudSyncer::ChangeProcessStatusAndNotifyIfNeed(UploadParam &uploadParam, InnerProcessInfo &info) +{ + if (info.tableStatus == ProcessStatus::FINISHED) { + // if process here, the process should't be finished and notify. + info.tableStatus = ProcessStatus::PROCESSING; + NotifyInBatchUpload(uploadParam, info, false); + } +} + int CloudSyncer::HandleBatchUpload(UploadParam &uploadParam, InnerProcessInfo &info, CloudSyncData &uploadData, ContinueToken &continueStmtToken, std::vector &revisedData) { @@ -1090,6 +1102,7 @@ int CloudSyncer::HandleBatchUpload(UploadParam &uploadParam, InnerProcessInfo &i uint32_t batchIndex = GetCurrentTableUploadBatchIndex(); bool isLocked = false; while (!CloudSyncUtils::CheckCloudSyncDataEmpty(uploadData)) { + ChangeProcessStatusAndNotifyIfNeed(uploadParam, info); revisedData.insert(revisedData.end(), uploadData.revisedData.begin(), uploadData.revisedData.end()); ret = PreProcessBatchUpload(uploadParam, info, uploadData); if (ret != E_OK) { @@ -1397,7 +1410,7 @@ std::string CloudSyncer::GetStoreIdByTask(TaskId taskId) return cloudTaskInfos_[taskId].storeId; } -int CloudSyncer::CleanKvCloudData(std::function &removeFunc) +int CloudSyncer::StopSyncTask(std::function &removeFunc) { hasKvRemoveTask = true; CloudSyncer::TaskId currentTask; @@ -1406,7 +1419,7 @@ int CloudSyncer::CleanKvCloudData(std::function &removeFunc) std::lock_guard autoLock(dataLock_); currentTask = currentContext_.currentTaskId; } - if (currentTask != INVALID_TASK_ID) { + if (currentTask != INVALID_TASK_ID || asyncTaskId_ != INVALID_TASK_ID) { StopAllTasks(-E_CLOUD_ERROR); } int errCode = E_OK; @@ -1664,55 +1677,15 @@ void CloudSyncer::TriggerAsyncDownloadAssetsInTaskIfNeed(bool isFirstDownload) } } if (isFirstDownload) { + bool isLockAction = IsLockInDownload(); std::lock_guard autoLock(dataLock_); - if (currentContext_.isNeedUpload) { + if (currentContext_.isNeedUpload && isLockAction) { return; } } TriggerAsyncDownloadAssetsIfNeed(); } -void CloudSyncer::TriggerAsyncDownloadAssetsIfNeed() -{ - if (!storageProxy_->IsExistTableContainAssets()) { - LOGD("[CloudSyncer] No exist table contain assets, skip async download asset check"); - return; - } - TaskId taskId = INVALID_TASK_ID; - { - std::lock_guard autoLock(dataLock_); - if (asyncTaskId_ != INVALID_TASK_ID || closed_) { - LOGI("[CloudSyncer] No need generate async task now asyncTaskId %" PRIu64 " closed %d", - static_cast(asyncTaskId_), static_cast(closed_)); - return; - } - lastTaskId_--; - if (lastTaskId_ == INVALID_TASK_ID) { - lastTaskId_ = UINT64_MAX; - } - asyncTaskId_ = lastTaskId_; - taskId = asyncTaskId_; - IncObjRef(this); - } - int errCode = RuntimeContext::GetInstance()->ScheduleTask([taskId, this]() { - LOGI("[CloudSyncer] Exec asyncTaskId %" PRIu64 " begin", taskId); - BackgroundDownloadAssetsTask(); - LOGI("[CloudSyncer] Exec asyncTaskId %" PRIu64 " finished", taskId); - { - std::lock_guard autoLock(dataLock_); - asyncTaskId_ = INVALID_TASK_ID; - } - asyncTaskCv_.notify_all(); - DecObjRef(this); - }); - if (errCode == E_OK) { - LOGI("[CloudSyncer] Schedule asyncTaskId %" PRIu64 " success", taskId); - } else { - LOGW("[CloudSyncer] Schedule BackgroundDownloadAssetsTask failed %d", errCode); - DecObjRef(this); - } -} - void CloudSyncer::BackgroundDownloadAssetsTask() { // remove listener first @@ -1883,7 +1856,6 @@ int CloudSyncer::TagDownloadAssetsForAssetOnly( LOGE("[CloudSyncer] Invalid primary key type in TagStatus, it's Nil."); return -E_INTERNAL_ERROR; } - std::map downloadAssetsMap{}; ret = CloudSyncUtils::GetDownloadAssetsOnlyMapFromDownLoadData(idx, param, downloadAssetsMap); if (ret != E_OK) { @@ -1967,7 +1939,6 @@ int CloudSyncer::SetAssetsMapAndEraseDataForAssetsOnly( return -E_ASSET_NOT_FOUND_FOR_DOWN_ONLY; } } - for (auto iter = downloadData.begin(); iter != downloadData.end();) { std::string gidStr; int ret = CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::GID_FIELD, *iter, gidStr); @@ -2059,15 +2030,6 @@ bool CloudSyncer::IsCurrentAsyncDownloadTask() return cloudTaskInfos_[currentContext_.currentTaskId].asyncDownloadAssets; } -bool CloudSyncer::CanStartAsyncDownload() const -{ - if (!RuntimeContext::GetInstance()->GetAssetsDownloadManager()->CanStartNewTask()) { - LOGW("[CloudSyncer] Too many download tasks"); - return false; - } - return asyncTaskId_ == INVALID_TASK_ID; -} - void CloudSyncer::NotifyChangedDataWithDefaultDev(ChangedData &&changedData) { auto table = changedData.tableName; @@ -2148,8 +2110,8 @@ bool CloudSyncer::TryToInitQueryAndUserListForCompensatedSync(TaskId triggerTask { std::vector syncQuery; std::vector users; - int errCode = - CloudSyncUtils::GetQueryAndUsersForCompensatedSync(CanStartAsyncDownload(), storageProxy_, users, syncQuery); + int errCode = CloudSyncUtils::GetQueryAndUsersForCompensatedSync( + CloudSyncUtils::CanStartAsyncDownload(scheduleTaskCount_), storageProxy_, users, syncQuery); if (errCode != E_OK) { LOGW("[CloudSyncer] get query for compensated sync failed! errCode = %d", errCode); // if failed, finshed the task directly. @@ -2174,4 +2136,16 @@ bool CloudSyncer::TryToInitQueryAndUserListForCompensatedSync(TaskId triggerTask cloudTaskInfos_[triggerTaskId].queryList.push_back(syncQuery[0]); return true; } + +int CloudSyncer::ClearCloudWatermark(std::function &clearFunc) +{ + std::lock_guard lock(syncMutex_); + return clearFunc(); +} + +bool CloudSyncer::IsCloudForcePush(TaskId taskId) +{ + std::lock_guard autoLock(dataLock_); + return cloudTaskInfos_[taskId].mode == SYNC_MODE_CLOUD_FORCE_PUSH; +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend_extend.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend_extend.cpp new file mode 100644 index 00000000..ae9558e7 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend_extend.cpp @@ -0,0 +1,121 @@ +/* + * 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 "cloud_syncer.h" + +#include +#include +#include + +#include "cloud/cloud_db_constant.h" +#include "cloud/cloud_storage_utils.h" +#include "cloud/icloud_db.h" +#include "cloud_sync_tag_assets.h" +#include "cloud_sync_utils.h" +#include "db_errno.h" +#include "kv_store_errno.h" +#include "log_print.h" +#include "res_finalizer.h" +#include "runtime_context.h" +#include "store_types.h" +#include "strategy_factory.h" +#include "version.h" + +namespace DistributedDB { +int CloudSyncer::HandleDownloadResultForAsyncDownload(const DownloadItem &downloadItem, InnerProcessInfo &info, + DownloadCommitList &commitList, uint32_t &successCount) +{ + int errCode = storageProxy_->StartTransaction(TransactType::IMMEDIATE, true); + if (errCode != E_OK) { + LOGE("[CloudSyncer] start transaction Failed before handle async download."); + return errCode; + } + errCode = CommitDownloadAssetsForAsyncDownload(downloadItem, info, commitList, successCount); + if (errCode != E_OK) { + successCount = 0; + int ret = E_OK; + if (errCode == -E_REMOVE_ASSETS_FAILED) { + // remove assets failed no effect to asset status, just commit + ret = storageProxy_->Commit(true); + LOGE("[CloudSyncer] commit async download assets failed %d commit ret %d", errCode, ret); + } else { + ret = storageProxy_->Rollback(true); + LOGE("[CloudSyncer] commit async download assets failed %d rollback ret %d", errCode, ret); + } + return errCode; + } + errCode = storageProxy_->Commit(true); + if (errCode != E_OK) { + successCount = 0; + LOGE("[CloudSyncer] commit async download assets failed %d", errCode); + } + return errCode; +} + +void CloudSyncer::TriggerAsyncDownloadAssetsIfNeed() +{ + if (!storageProxy_->IsExistTableContainAssets()) { + LOGD("[CloudSyncer] No exist table contain assets, skip async download asset check"); + return; + } + TaskId taskId = INVALID_TASK_ID; + { + std::lock_guard autoLock(dataLock_); + if (asyncTaskId_ != INVALID_TASK_ID || closed_) { + LOGI("[CloudSyncer] No need generate async task now asyncTaskId %" PRIu64 " closed %d", + asyncTaskId_, static_cast(closed_)); + return; + } + lastTaskId_--; + if (lastTaskId_ == INVALID_TASK_ID) { + lastTaskId_ = UINT64_MAX; + } + taskId = lastTaskId_; + IncObjRef(this); + } + int errCode = RuntimeContext::GetInstance()->ScheduleTask([taskId, this]() { + LOGI("[CloudSyncer] Exec asyncTaskId %" PRIu64 " begin", taskId); + ExecuteAsyncDownloadAssets(taskId); + LOGI("[CloudSyncer] Exec asyncTaskId %" PRIu64 " finished", taskId); + scheduleTaskCount_--; + DecObjRef(this); + }); + if (errCode == E_OK) { + LOGI("[CloudSyncer] Schedule asyncTaskId %" PRIu64 " success", taskId); + scheduleTaskCount_++; + } else { + LOGW("[CloudSyncer] Schedule BackgroundDownloadAssetsTask failed %d", errCode); + DecObjRef(this); + } +} + +void CloudSyncer::ExecuteAsyncDownloadAssets(TaskId taskId) +{ + { + std::lock_guard autoLock(dataLock_); + if (asyncTaskId_ != INVALID_TASK_ID || closed_) { + LOGI("[CloudSyncer] No need exec async task now asyncTaskId %" PRIu64 " closed %d", + asyncTaskId_, static_cast(closed_)); + return; + } + asyncTaskId_ = taskId; + } + BackgroundDownloadAssetsTask(); + { + std::lock_guard autoLock(dataLock_); + asyncTaskId_ = INVALID_TASK_ID; + } + asyncTaskCv_.notify_all(); +} +} // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/ability_sync.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/ability_sync.cpp index 7a4af6fa..795f8764 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/ability_sync.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/ability_sync.cpp @@ -402,6 +402,9 @@ int AbilitySync::SyncStart(uint32_t sessionId, uint32_t sequenceId, uint16_t rem message->SetSequenceId(sequenceId); SendConfig conf; SetSendConfigParam(storageInterface_->GetDbProperties(), deviceId_, false, SEND_TIME_OUT, conf); + if (context != nullptr) { + conf.isRetryTask = context->IsRetryTask(); + } errCode = communicator_->SendMessage(deviceId_, message, conf, handler); if (errCode != E_OK) { LOGE("[AbilitySync][SyncStart] SendPacket failed, err %d", errCode); @@ -423,7 +426,7 @@ int AbilitySync::AckRecv(const Message *message, ISyncTaskContext *context) } uint32_t remoteSoftwareVersion = packet->GetSoftwareVersion(); context->SetRemoteSoftwareVersion(remoteSoftwareVersion); - metadata_->SetRemoteSchemaVersion(context->GetDeviceId(), remoteSoftwareVersion); + metadata_->SetRemoteSoftwareVersion(context->GetDeviceId(), context->GetTargetUserId(), remoteSoftwareVersion); if (remoteSoftwareVersion > SOFTWARE_VERSION_RELEASE_2_0) { errCode = AckRecvWithHighVersion(message, context, packet); } else { @@ -518,7 +521,7 @@ void AbilitySync::SetAbilitySyncFinishedStatus(bool syncFinished, ISyncTaskConte if (syncFinished && !context.IsSchemaCompatible()) { // LCOV_EXCL_BR_LINE return; } - int errCode = metadata_->SetAbilitySyncFinishMark(deviceId_, syncFinished); + int errCode = metadata_->SetAbilitySyncFinishMark(deviceId_, context.GetTargetUserId(), syncFinished); if (errCode != E_OK) { LOGW("[AbilitySync] Set ability sync finish mark failed %d", errCode); } @@ -1155,10 +1158,11 @@ int AbilitySync::HandleRequestRecv(const Message *message, ISyncTaskContext *con ackCode = -E_SECURITY_OPTION_CHECK_ERROR; } if (ackCode == E_OK && remoteSoftwareVersion > SOFTWARE_VERSION_RELEASE_3_0) { - ackCode = metadata_->SetDbCreateTime(deviceId_, packet->GetDbCreateTime(), true); + ackCode = metadata_->SetDbCreateTime(deviceId_, context->GetTargetUserId(), packet->GetDbCreateTime(), true); } if (ackCode == E_OK && remoteSoftwareVersion >= SOFTWARE_VERSION_RELEASE_9_0) { - ackCode = metadata_->SetRemoteSchemaVersion(context->GetDeviceId(), packet->GetSchemaVersion()); + ackCode = metadata_->SetRemoteSchemaVersion(context->GetDeviceId(), context->GetTargetUserId(), + packet->GetSchemaVersion()); } AbilitySyncAckPacket ackPacket; if (IsSingleRelationalVer()) { @@ -1334,7 +1338,7 @@ int AbilitySync::AckRecvWithHighVersion(const Message *message, ISyncTaskContext std::pair schemaSyncStatus; int errCode = E_OK; if (context->GetRemoteSoftwareVersion() > SOFTWARE_VERSION_RELEASE_3_0) { - errCode = metadata_->SetDbCreateTime(deviceId_, packet->GetDbCreateTime(), true); + errCode = metadata_->SetDbCreateTime(deviceId_, context->GetTargetUserId(), packet->GetDbCreateTime(), true); if (errCode != E_OK) { LOGE("[AbilitySync][AckRecv] set db create time failed,errCode=%d", errCode); context->SetTaskErrCode(errCode); @@ -1378,7 +1382,7 @@ bool AbilitySync::IsBothKvAndOptAbilitySync(uint32_t remoteVersion, SchemaType l void AbilitySync::InitAbilitySyncFinishStatus(ISyncTaskContext &context) { - if (!metadata_->IsAbilitySyncFinish(context.GetDeviceId())) { + if (!metadata_->IsAbilitySyncFinish(context.GetDeviceId(), context.GetTargetUserId())) { return; } LOGI("[AbilitySync] Mark ability sync finish from db status"); @@ -1398,7 +1402,17 @@ void AbilitySync::InitRemoteDBAbility(ISyncTaskContext &context) return; } context.SetDbAbility(ability); - auto version = static_cast(metadata_->GetRemoteSoftwareVersion(context.GetDeviceId())); + auto version = static_cast(metadata_->GetRemoteSoftwareVersion(context.GetDeviceId(), + context.GetTargetUserId())); + // 111 trunk ver record schema version as software version + // should clear it and do ability sync again + if (version > SOFTWARE_VERSION_MAX) { + context.SetRemoteSoftwareVersion(SOFTWARE_VERSION_RELEASE_9_0); // remote version is greater than 109 + SetAbilitySyncFinishedStatus(false, context); + (void)metadata_->SetRemoteSoftwareVersion(deviceId_, context.GetTargetUserId(), SOFTWARE_VERSION_RELEASE_9_0); + LOGW("[AbilitySync] Remote schema version is invalid[% " PRIu32 "]", version); + return; + } if (version > 0) { context.SetRemoteSoftwareVersion(version); } @@ -1408,7 +1422,8 @@ void AbilitySync::RecordAbilitySyncFinish(uint64_t remoteSchemaVersion, ISyncTas { SetAbilitySyncFinishedStatus(true, context); if (context.GetRemoteSoftwareVersion() >= SOFTWARE_VERSION_RELEASE_9_0) { // LCOV_EXCL_BR_LINE - (void)metadata_->SetRemoteSchemaVersion(deviceId_, remoteSchemaVersion); + (void)metadata_->SetRemoteSchemaVersion(deviceId_, context.GetTargetUserId(), remoteSchemaVersion); } + (void)metadata_->SetRemoteSoftwareVersion(deviceId_, context.GetTargetUserId(), context.GetRemoteSoftwareVersion()); } } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/communicator_proxy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/communicator_proxy.cpp index 15327f25..08e6a794 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/communicator_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/communicator_proxy.cpp @@ -272,4 +272,35 @@ void CommunicatorProxy::Dump(int fd) DBDumpHelper::Dump(fd, "\t\ttarget = %s, label = %s\n", target.c_str(), label.c_str()); } } + +std::string CommunicatorProxy::GetTargetUserId(const ExtendInfo ¶mInfo) const +{ + ICommunicator *targetCommunicator = nullptr; + { + std::lock_guard lock(devCommMapLock_); + if (devCommMap_.count(paramInfo.dstTarget) != 0) { + targetCommunicator = devCommMap_.at(paramInfo.dstTarget).second; + RefObject::IncObjRef(targetCommunicator); + } + } + if (targetCommunicator != nullptr) { + std::string targetUserId = targetCommunicator->GetTargetUserId(paramInfo); + RefObject::DecObjRef(targetCommunicator); + return targetUserId; + } + + if (mainComm_ != nullptr) { + return mainComm_->GetTargetUserId(paramInfo); + } + + return ""; +} + +bool CommunicatorProxy::ExchangeClosePending(bool expected) +{ + if (mainComm_ != nullptr) { + return mainComm_->ExchangeClosePending(expected); + } + return false; +} } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/communicator_proxy.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/communicator_proxy.h index fafd852f..06340788 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/communicator_proxy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/communicator_proxy.h @@ -55,6 +55,10 @@ public: void Dump(int fd); + std::string GetTargetUserId(const ExtendInfo ¶mInfo) const override; + + bool ExchangeClosePending(bool expected) override; + private: ICommunicator *mainComm_; mutable std::mutex devCommMapLock_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.cpp index 772dee8f..426d110a 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.cpp @@ -150,7 +150,7 @@ int GenericSyncer::Sync(const std::vector &devices, int mode, const std::function &)> &onComplete, const std::function &onFinalize, bool wait = false) { - SyncParma param; + SyncParam param; param.devices = devices; param.mode = mode; param.onComplete = onComplete; @@ -161,7 +161,7 @@ int GenericSyncer::Sync(const std::vector &devices, int mode, int GenericSyncer::Sync(const InternalSyncParma ¶m) { - SyncParma syncParam; + SyncParam syncParam; syncParam.devices = param.devices; syncParam.mode = param.mode; syncParam.isQuerySync = param.isQuerySync; @@ -169,12 +169,12 @@ int GenericSyncer::Sync(const InternalSyncParma ¶m) return Sync(syncParam); } -int GenericSyncer::Sync(const SyncParma ¶m) +int GenericSyncer::Sync(const SyncParam ¶m) { return Sync(param, DBConstant::IGNORE_CONNECTION_ID); } -int GenericSyncer::Sync(const SyncParma ¶m, uint64_t connectionId) +int GenericSyncer::Sync(const SyncParam ¶m, uint64_t connectionId) { int errCode = SyncPreCheck(param); if (errCode != E_OK) { @@ -232,10 +232,10 @@ int GenericSyncer::CancelSync(uint32_t syncId) return E_OK; } -int GenericSyncer::PrepareSync(const SyncParma ¶m, uint32_t syncId, uint64_t connectionId) +int GenericSyncer::PrepareSync(const SyncParam ¶m, uint32_t syncId, uint64_t connectionId) { auto *operation = - new (std::nothrow) SyncOperation(syncId, param.devices, param.mode, param.onComplete, param.wait); + new (std::nothrow) SyncOperation(syncId, param); if (operation == nullptr) { SubQueuedSyncSize(); return -E_OUT_OF_MEMORY; @@ -246,8 +246,8 @@ int GenericSyncer::PrepareSync(const SyncParma ¶m, uint32_t syncId, uint64_t std::lock_guard autoLock(syncerLock_); PerformanceAnalysis::GetInstance()->StepTimeRecordStart(PT_TEST_RECORDS::RECORD_SYNC_TOTAL); InitSyncOperation(operation, param); - LOGI("[Syncer] GenerateSyncId %" PRIu32 ", mode = %d, wait = %d, label = %s, devices = %s", syncId, param.mode, - param.wait, label_.c_str(), GetSyncDevicesStr(param.devices).c_str()); + LOGI("[Syncer] GenerateSyncId %" PRIu32 ", mode = %d, wait = %d, label = %.3s, devices = %s, isRetry = %d", + syncId, param.mode, param.wait, label_.c_str(), GetSyncDevicesStr(param.devices).c_str(), param.isRetry); engine = syncEngine_; RefObject::IncObjRef(engine); } @@ -528,7 +528,7 @@ bool GenericSyncer::IsValidMode(int mode) const return true; } -int GenericSyncer::SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, ISyncInterface *storage) const +int GenericSyncer::SyncConditionCheck(const SyncParam ¶m, const ISyncEngine *engine, ISyncInterface *storage) const { (void)param; (void)engine; @@ -871,7 +871,7 @@ int GenericSyncer::StatusCheck() const return E_OK; } -int GenericSyncer::SyncPreCheck(const SyncParma ¶m) const +int GenericSyncer::SyncPreCheck(const SyncParam ¶m) const { ISyncEngine *engine = nullptr; ISyncInterface *storage = nullptr; @@ -903,7 +903,7 @@ int GenericSyncer::SyncPreCheck(const SyncParma ¶m) const return errCode; } -void GenericSyncer::InitSyncOperation(SyncOperation *operation, const SyncParma ¶m) +void GenericSyncer::InitSyncOperation(SyncOperation *operation, const SyncParam ¶m) { if (syncInterface_ == nullptr) { LOGE("[GenericSyncer] [InitSyncOperation] syncInterface_ is nullptr."); @@ -1073,7 +1073,7 @@ int GenericSyncer::CloseInner(bool isClosedOperation) { std::lock_guard lock(syncerLock_); if (!initialized_) { - LOGW("[Syncer] Syncer[%s] don't need to close, because it has not been init", label_.c_str()); + LOGW("[Syncer] CloseInner[%.3s] don't close", label_.c_str()); return -E_NOT_INIT; } initialized_ = false; @@ -1114,7 +1114,7 @@ int GenericSyncer::GetSyncDataSize(const std::string &device, size_t &size) cons syncInterface_->IncRefCount(); metadata = metadata_; } - metadata->GetLocalWaterMark(device, localWaterMark); + metadata->GetLocalWaterMark(device, "", localWaterMark); uint32_t expectedMtuSize = DEFAULT_MTU_SIZE; DataSizeSpecInfo syncDataSizeInfo = {expectedMtuSize, static_cast(MAX_TIMESTAMP)}; std::vector outData; @@ -1207,7 +1207,7 @@ int GenericSyncer::GetWatermarkInfo(const std::string &device, WatermarkInfo &in } else { dev = device; } - return metadata->GetWaterMarkInfoFromDB(dev, devNeedHash, info); + return metadata->GetWaterMarkInfoFromDB(dev, DBConstant::DEFAULT_USER, devNeedHash, info); } int GenericSyncer::UpgradeSchemaVerInMeta() @@ -1245,7 +1245,7 @@ void GenericSyncer::ResetTimeSyncMarkByTimeChange(std::shared_ptr &met } int errCode = metadata->ClearAllTimeSyncFinishMark(); if (errCode != E_OK) { - LOGW("[GenericSyncer] %s clear time sync finish mark failed %d", label_.c_str(), errCode); + LOGW("[GenericSyncer] %.3s clear time sync finish mark failed %d", label_.c_str(), errCode); } else { LOGD("[GenericSyncer] ClearAllTimeSyncFinishMark finish"); RuntimeContext::GetInstance()->ResetDBTimeChangeStatus(storage.GetIdentifier()); @@ -1298,4 +1298,20 @@ int32_t GenericSyncer::GetTaskCount() RefObject::DecObjRef(syncEngine); return count; } + +bool GenericSyncer::ExchangeClosePending(bool expected) +{ + ISyncEngine *syncEngine = nullptr; + { + std::lock_guard lock(syncerLock_); + if (syncEngine_ == nullptr) { + return false; + } + syncEngine = syncEngine_; + RefObject::IncObjRef(syncEngine); + } + bool res = syncEngine->ExchangeClosePending(expected); + RefObject::DecObjRef(syncEngine); + return res; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.h index 183fbb1f..0f002124 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.h @@ -50,10 +50,10 @@ public: const std::function &)> &onComplete, const std::function &onFinalize, bool wait) override; - // Sync function. use SyncParma to reduce parameter. - int Sync(const SyncParma ¶m); + // Sync function. use SyncParam to reduce parameter. + int Sync(const SyncParam ¶m); - int Sync(const SyncParma ¶m, uint64_t connectionId) override; + int Sync(const SyncParam ¶m, uint64_t connectionId) override; // Cancel sync function. int CancelSync(uint32_t syncId) override; @@ -118,6 +118,8 @@ public: int64_t GetLocalTimeOffset() override; int32_t GetTaskCount() override; + + bool ExchangeClosePending(bool expected) override; protected: // trigger query auto sync or auto subscribe @@ -128,7 +130,7 @@ protected: // Create a sync engine, if has memory error, will return nullptr. virtual ISyncEngine *CreateSyncEngine() = 0; - virtual int PrepareSync(const SyncParma ¶m, uint32_t syncId, uint64_t connectionId); + virtual int PrepareSync(const SyncParam ¶m, uint32_t syncId, uint64_t connectionId); // Add a Sync Operation, after call this function, the operation will be start virtual void AddSyncOperation(ISyncEngine *engine, SyncOperation *operation); @@ -157,7 +159,7 @@ protected: // Check if the mode arg is valid bool IsValidMode(int mode) const; - virtual int SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, ISyncInterface *storage) const; + virtual int SyncConditionCheck(const SyncParam ¶m, const ISyncEngine *engine, ISyncInterface *storage) const; // Check if the devices arg is valid bool IsValidDevices(const std::vector &devices) const; @@ -185,11 +187,11 @@ protected: std::string GetSyncDevicesStr(const std::vector &devices) const; - void InitSyncOperation(SyncOperation *operation, const SyncParma ¶m); + void InitSyncOperation(SyncOperation *operation, const SyncParam ¶m); int StatusCheck() const; - int SyncPreCheck(const SyncParma ¶m) const; + int SyncPreCheck(const SyncParam ¶m) const; int BuildSyncEngine(); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_engine.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_engine.h index 3859a900..0c652a39 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_engine.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_engine.h @@ -104,6 +104,10 @@ public: virtual void ClearAllSyncTaskByDevice(const std::string &deviceId) = 0; virtual int32_t GetResponseTaskCount() = 0; + + virtual int32_t GetRemoteQueryTaskCount() = 0; + + virtual bool ExchangeClosePending(bool expected) = 0; protected: ~ISyncEngine() override {}; }; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_task_context.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_task_context.h index 91ed8893..bc3b5c5c 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_task_context.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_task_context.h @@ -35,7 +35,7 @@ public: enum TASK_EXEC_STATUS { INIT, RUNNING, FAILED, FINISHED }; // Initialize the context - virtual int Initialize(const std::string &deviceId, ISyncInterface *syncInterface, + virtual int Initialize(const DeviceSyncTarget &target, ISyncInterface *syncInterface, const std::shared_ptr &metadata, ICommunicator *communicator) = 0; // Add a sync task target with the operation to the queue @@ -76,6 +76,10 @@ public: // Get the current task deviceId. virtual std::string GetDeviceId() const = 0; + virtual std::string GetTargetUserId() const = 0; + + virtual void SetTargetUserId(const std::string &userId) = 0; + virtual void SetTaskExecStatus(int status) = 0; virtual int GetTaskExecStatus() const = 0; @@ -188,6 +192,8 @@ public: virtual void TimeChange() = 0; virtual int32_t GetResponseTaskCount() = 0; + + virtual bool IsRetryTask() const = 0; protected: virtual ~ISyncTaskContext() {}; }; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.cpp index 80fc35ac..e6e6d68f 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.cpp @@ -70,59 +70,85 @@ int Metadata::Initialize(ISyncInterface* storage) return LoadAllMetadata(); } -int Metadata::SaveTimeOffset(const DeviceID &deviceId, TimeOffset inValue) +int Metadata::SaveTimeOffset(const DeviceID &deviceId, const DeviceID &userId, TimeOffset inValue) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); metadata.timeOffset = inValue; metadata.lastUpdateTime = TimeHelper::GetSysCurrentTime(); LOGD("Metadata::SaveTimeOffset = %" PRId64 " dev %s", inValue, STR_MASK(deviceId)); - return SaveMetaDataValue(deviceId, metadata); + return SaveMetaDataValue(deviceId, userId, metadata); } -void Metadata::GetTimeOffset(const DeviceID &deviceId, TimeOffset &outValue) +void Metadata::GetTimeOffset(const DeviceID &deviceId, const DeviceID &userId, TimeOffset &outValue) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); outValue = metadata.timeOffset; } -void Metadata::GetLocalWaterMark(const DeviceID &deviceId, uint64_t &outValue) +void Metadata::GetLocalWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); outValue = metadata.localWaterMark; } -int Metadata::SaveLocalWaterMark(const DeviceID &deviceId, uint64_t inValue) +int Metadata::SaveLocalWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t inValue) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); metadata.localWaterMark = inValue; LOGD("Metadata::SaveLocalWaterMark = %" PRIu64, inValue); - return SaveMetaDataValue(deviceId, metadata); + return SaveMetaDataValue(deviceId, userId, metadata); } -void Metadata::GetPeerWaterMark(const DeviceID &deviceId, uint64_t &outValue, bool isNeedHash) +void Metadata::GetPeerWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue, bool isNeedHash) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, isNeedHash); + GetMetaDataValue(deviceId, userId, metadata, isNeedHash); outValue = metadata.peerWaterMark; } -int Metadata::SavePeerWaterMark(const DeviceID &deviceId, uint64_t inValue, bool isNeedHash) +int Metadata::SavePeerWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t inValue, bool isNeedHash) { - MetaDataValue metadata; + std::map metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, isNeedHash); - metadata.peerWaterMark = inValue; - LOGD("Metadata::SavePeerWaterMark = %" PRIu64, inValue); - return SaveMetaDataValue(deviceId, metadata, isNeedHash); + int errCode = E_OK; + if (!userId.empty()) { + MetaDataValue oneMetadata; + GetMetaDataValue(deviceId, userId, oneMetadata, isNeedHash); + DeviceID hashId; + Key key; + GetHashDeviceId(deviceId, userId, hashId, isNeedHash); + DBCommon::StringToVector(hashId, key); + metadata[key] = oneMetadata; + } else { + errCode = GetMetaDataFromDBByPrefixKey(deviceId, isNeedHash, metadata); + if (errCode != E_OK) { + return errCode; + } + } + + for (auto &oneMetadata : metadata) { + oneMetadata.second.peerWaterMark = inValue; + LOGD("Metadata::SavePeerWaterMark = %" PRIu64, inValue); + Value metadataValue; + errCode = SerializeMetaData(oneMetadata.second, metadataValue); + if (errCode != E_OK) { + return errCode; + } + errCode = SetMetadataToDb(oneMetadata.first, metadataValue); + if (errCode != E_OK) { + return errCode; + } + } + return E_OK; } int Metadata::SaveLocalTimeOffset(TimeOffset timeOffset, bool saveIntoDb) @@ -153,10 +179,11 @@ TimeOffset Metadata::GetLocalTimeOffset() const int Metadata::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash) { - return EraseDeviceWaterMark(deviceId, isNeedHash, ""); + return EraseDeviceWaterMark(deviceId, "", isNeedHash, ""); } -int Metadata::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, const std::string &tableName) +int Metadata::EraseDeviceWaterMark(const std::string &deviceId, const std::string &userId, bool isNeedHash, + const std::string &tableName) { // reload meta data again (void)LoadAllMetadata(); @@ -164,19 +191,19 @@ int Metadata::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, // try to erase all the waterMark // erase deleteSync recv waterMark WaterMark waterMark = 0; - int errCodeDeleteSync = SetRecvDeleteSyncWaterMark(deviceId, waterMark, isNeedHash); + int errCodeDeleteSync = SetRecvDeleteSyncWaterMark(deviceId, userId, waterMark, isNeedHash); if (errCodeDeleteSync != E_OK) { LOGE("[Metadata] erase deleteWaterMark failed errCode:%d", errCodeDeleteSync); return errCodeDeleteSync; } // erase querySync recv waterMark - int errCodeQuerySync = ResetRecvQueryWaterMark(deviceId, tableName, isNeedHash); + int errCodeQuerySync = ResetRecvQueryWaterMark(deviceId, userId, tableName, isNeedHash); if (errCodeQuerySync != E_OK) { LOGE("[Metadata] erase queryWaterMark failed errCode:%d", errCodeQuerySync); return errCodeQuerySync; } // peerWaterMark must be erased at last - int errCode = SavePeerWaterMark(deviceId, 0, isNeedHash); + int errCode = SavePeerWaterMark(deviceId, userId, 0, isNeedHash); if (errCode != E_OK) { LOGE("[Metadata] erase peerWaterMark failed errCode:%d", errCode); return errCode; @@ -198,7 +225,8 @@ Timestamp Metadata::GetLastLocalTime() const return lastLocalTime_; } -int Metadata::SaveMetaDataValue(const DeviceID &deviceId, const MetaDataValue &inValue, bool isNeedHash) +int Metadata::SaveMetaDataValue(const DeviceID &deviceId, const DeviceID &userId, const MetaDataValue &inValue, + bool isNeedHash) { std::vector value; int errCode = SerializeMetaData(inValue, value); @@ -207,7 +235,7 @@ int Metadata::SaveMetaDataValue(const DeviceID &deviceId, const MetaDataValue &i } DeviceID hashDeviceId; - GetHashDeviceId(deviceId, hashDeviceId, isNeedHash); + GetHashDeviceId(deviceId, userId, hashDeviceId, isNeedHash); std::vector key; DBCommon::StringToVector(hashDeviceId, key); errCode = SetMetadataToDb(key, value); @@ -217,9 +245,10 @@ int Metadata::SaveMetaDataValue(const DeviceID &deviceId, const MetaDataValue &i return errCode; } -int Metadata::GetMetaDataValue(const DeviceID &deviceId, MetaDataValue &outValue, bool isNeedHash) +int Metadata::GetMetaDataValue(const DeviceID &deviceId, const DeviceID &userId, MetaDataValue &outValue, + bool isNeedHash) { - int errCode = GetMetaDataValueFromDB(deviceId, isNeedHash, outValue); + int errCode = GetMetaDataValueFromDB(deviceId, userId, isNeedHash, outValue); if (errCode == -E_NOT_FOUND && RuntimeContext::GetInstance()->IsTimeChanged()) { outValue = {}; outValue.syncMark = static_cast(SyncMark::SYNC_MARK_TIME_CHANGE); @@ -257,6 +286,14 @@ int Metadata::GetMetadataFromDb(const std::vector &key, std::vectorGetMetaData(key, outValue); } +int Metadata::GetMetadataFromDbByPrefixKey(const Key &keyPrefix, std::map &data) const +{ + if (naturalStoragePtr_ == nullptr) { + return -E_INVALID_DB; + } + return naturalStoragePtr_->GetMetaDataByPrefixKey(keyPrefix, data); +} + int Metadata::SetMetadataToDb(const std::vector &key, const std::vector &inValue) { if (naturalStoragePtr_ == nullptr) { @@ -326,51 +363,54 @@ int Metadata::LoadAllMetadata() return InitLocalMetaData(); } -void Metadata::GetHashDeviceId(const DeviceID &deviceId, DeviceID &hashDeviceId, bool isNeedHash) +void Metadata::GetHashDeviceId(const DeviceID &deviceId, const DeviceID &userId, DeviceID &hashDeviceId, + bool isNeedHash) { if (!isNeedHash) { - hashDeviceId = DBConstant::DEVICEID_PREFIX_KEY + deviceId; + hashDeviceId = DBConstant::DEVICEID_PREFIX_KEY + deviceId + DBConstant::USERID_PREFIX_KEY + userId; return; } - if (deviceIdToHashDeviceIdMap_.count(deviceId) == 0) { - hashDeviceId = DBConstant::DEVICEID_PREFIX_KEY + DBCommon::TransferHashString(deviceId); - deviceIdToHashDeviceIdMap_.insert(std::pair(deviceId, hashDeviceId)); + DeviceSyncTarget deviceInfo(deviceId, userId); + if (deviceIdToHashDeviceIdMap_.count(deviceInfo) == 0) { + hashDeviceId = DBConstant::DEVICEID_PREFIX_KEY + DBCommon::TransferHashString(deviceId) + + DBConstant::USERID_PREFIX_KEY + userId; + deviceIdToHashDeviceIdMap_.insert(std::pair(deviceInfo, hashDeviceId)); } else { - hashDeviceId = deviceIdToHashDeviceIdMap_[deviceId]; + hashDeviceId = deviceIdToHashDeviceIdMap_[deviceInfo]; } } int Metadata::GetRecvQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, WaterMark &waterMark) + const std::string &deviceId, const std::string &userId, WaterMark &waterMark) { QueryWaterMark queryWaterMark; - int errCode = querySyncWaterMarkHelper_.GetQueryWaterMark(queryIdentify, deviceId, queryWaterMark); + int errCode = querySyncWaterMarkHelper_.GetQueryWaterMark(queryIdentify, deviceId, userId, queryWaterMark); if (errCode != E_OK) { return errCode; } WaterMark peerWaterMark; - GetPeerWaterMark(deviceId, peerWaterMark); + GetPeerWaterMark(deviceId, userId, peerWaterMark); waterMark = std::max(queryWaterMark.recvWaterMark, peerWaterMark); return E_OK; } int Metadata::SetRecvQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, const WaterMark &waterMark) + const std::string &deviceId, const std::string &userId, const WaterMark &waterMark) { - return querySyncWaterMarkHelper_.SetRecvQueryWaterMark(queryIdentify, deviceId, waterMark); + return querySyncWaterMarkHelper_.SetRecvQueryWaterMark(queryIdentify, deviceId, userId, waterMark); } int Metadata::GetSendQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, WaterMark &waterMark, bool isAutoLift) + const std::string &deviceId, const std::string &userId, WaterMark &waterMark, bool isAutoLift) { QueryWaterMark queryWaterMark; - int errCode = querySyncWaterMarkHelper_.GetQueryWaterMark(queryIdentify, deviceId, queryWaterMark); + int errCode = querySyncWaterMarkHelper_.GetQueryWaterMark(queryIdentify, deviceId, userId, queryWaterMark); if (errCode != E_OK) { return errCode; } if (isAutoLift) { WaterMark localWaterMark; - GetLocalWaterMark(deviceId, localWaterMark); + GetLocalWaterMark(deviceId, userId, localWaterMark); waterMark = std::max(queryWaterMark.sendWaterMark, localWaterMark); } else { waterMark = queryWaterMark.sendWaterMark; @@ -379,15 +419,16 @@ int Metadata::GetSendQueryWaterMark(const std::string &queryIdentify, } int Metadata::SetSendQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, const WaterMark &waterMark) + const std::string &deviceId, const std::string &userId, const WaterMark &waterMark) { - return querySyncWaterMarkHelper_.SetSendQueryWaterMark(queryIdentify, deviceId, waterMark); + return querySyncWaterMarkHelper_.SetSendQueryWaterMark(queryIdentify, deviceId, userId, waterMark); } -int Metadata::GetLastQueryTime(const std::string &queryIdentify, const std::string &deviceId, Timestamp ×tamp) +int Metadata::GetLastQueryTime(const std::string &queryIdentify, const std::string &deviceId, const std::string &userId, + Timestamp ×tamp) { QueryWaterMark queryWaterMark; - int errCode = querySyncWaterMarkHelper_.GetQueryWaterMark(queryIdentify, deviceId, queryWaterMark); + int errCode = querySyncWaterMarkHelper_.GetQueryWaterMark(queryIdentify, deviceId, userId, queryWaterMark); if (errCode != E_OK) { return errCode; } @@ -395,22 +436,23 @@ int Metadata::GetLastQueryTime(const std::string &queryIdentify, const std::stri return E_OK; } -int Metadata::SetLastQueryTime(const std::string &queryIdentify, const std::string &deviceId, +int Metadata::SetLastQueryTime(const std::string &queryIdentify, const std::string &deviceId, const std::string &userId, const Timestamp ×tamp) { - return querySyncWaterMarkHelper_.SetLastQueryTime(queryIdentify, deviceId, timestamp); + return querySyncWaterMarkHelper_.SetLastQueryTime(queryIdentify, deviceId, userId, timestamp); } -int Metadata::GetSendDeleteSyncWaterMark(const DeviceID &deviceId, WaterMark &waterMark, bool isAutoLift) +int Metadata::GetSendDeleteSyncWaterMark(const DeviceID &deviceId, const DeviceID &userId, WaterMark &waterMark, + bool isAutoLift) { DeleteWaterMark deleteWaterMark; - int errCode = querySyncWaterMarkHelper_.GetDeleteSyncWaterMark(deviceId, deleteWaterMark); + int errCode = querySyncWaterMarkHelper_.GetDeleteSyncWaterMark(deviceId, userId, deleteWaterMark); if (errCode != E_OK) { return errCode; } if (isAutoLift) { WaterMark localWaterMark; - GetLocalWaterMark(deviceId, localWaterMark); + GetLocalWaterMark(deviceId, userId, localWaterMark); waterMark = std::max(deleteWaterMark.sendWaterMark, localWaterMark); } else { waterMark = deleteWaterMark.sendWaterMark; @@ -418,39 +460,41 @@ int Metadata::GetSendDeleteSyncWaterMark(const DeviceID &deviceId, WaterMark &wa return E_OK; } -int Metadata::SetSendDeleteSyncWaterMark(const DeviceID &deviceId, const WaterMark &waterMark) +int Metadata::SetSendDeleteSyncWaterMark(const DeviceID &deviceId, const DeviceID &userId, const WaterMark &waterMark) { - return querySyncWaterMarkHelper_.SetSendDeleteSyncWaterMark(deviceId, waterMark); + return querySyncWaterMarkHelper_.SetSendDeleteSyncWaterMark(deviceId, userId, waterMark); } -int Metadata::GetRecvDeleteSyncWaterMark(const DeviceID &deviceId, WaterMark &waterMark) +int Metadata::GetRecvDeleteSyncWaterMark(const DeviceID &deviceId, const DeviceID &userId, WaterMark &waterMark) { DeleteWaterMark deleteWaterMark; - int errCode = querySyncWaterMarkHelper_.GetDeleteSyncWaterMark(deviceId, deleteWaterMark); + int errCode = querySyncWaterMarkHelper_.GetDeleteSyncWaterMark(deviceId, userId, deleteWaterMark); if (errCode != E_OK) { return errCode; } WaterMark peerWaterMark; - GetPeerWaterMark(deviceId, peerWaterMark); + GetPeerWaterMark(deviceId, userId, peerWaterMark); waterMark = std::max(deleteWaterMark.recvWaterMark, peerWaterMark); return E_OK; } -int Metadata::SetRecvDeleteSyncWaterMark(const DeviceID &deviceId, const WaterMark &waterMark, bool isNeedHash) +int Metadata::SetRecvDeleteSyncWaterMark(const DeviceID &deviceId, const DeviceID &userId, const WaterMark &waterMark, + bool isNeedHash) { - return querySyncWaterMarkHelper_.SetRecvDeleteSyncWaterMark(deviceId, waterMark, isNeedHash); + return querySyncWaterMarkHelper_.SetRecvDeleteSyncWaterMark(deviceId, userId, waterMark, isNeedHash); } -int Metadata::ResetRecvQueryWaterMark(const DeviceID &deviceId, const std::string &tableName, bool isNeedHash) +int Metadata::ResetRecvQueryWaterMark(const DeviceID &deviceId, const DeviceID &userId, const std::string &tableName, + bool isNeedHash) { - return querySyncWaterMarkHelper_.ResetRecvQueryWaterMark(deviceId, tableName, isNeedHash); + return querySyncWaterMarkHelper_.ResetRecvQueryWaterMark(deviceId, userId, tableName, isNeedHash); } -void Metadata::GetDbCreateTime(const DeviceID &deviceId, uint64_t &outValue) +void Metadata::GetDbCreateTime(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue) { std::lock_guard lockGuard(metadataLock_); MetaDataValue metadata; - int errCode = GetMetaDataValue(deviceId, metadata, true); + int errCode = GetMetaDataValue(deviceId, userId, metadata, true); if (errCode == E_OK) { outValue = metadata.dbCreateTime; return; @@ -459,11 +503,11 @@ void Metadata::GetDbCreateTime(const DeviceID &deviceId, uint64_t &outValue) LOGI("Metadata::GetDbCreateTime, not found dev = %s dbCreateTime", STR_MASK(deviceId)); } -int Metadata::SetDbCreateTime(const DeviceID &deviceId, uint64_t inValue, bool isNeedHash) +int Metadata::SetDbCreateTime(const DeviceID &deviceId, const DeviceID &userId, uint64_t inValue, bool isNeedHash) { std::lock_guard lockGuard(metadataLock_); MetaDataValue metadata; - int errCode = GetMetaDataValue(deviceId, metadata, isNeedHash); + int errCode = GetMetaDataValue(deviceId, userId, metadata, isNeedHash); if (errCode == E_OK) { if (metadata.dbCreateTime != 0 && metadata.dbCreateTime != inValue) { metadata.clearDeviceDataMark = REMOVE_DEVICE_DATA_MARK; @@ -478,26 +522,26 @@ int Metadata::SetDbCreateTime(const DeviceID &deviceId, uint64_t inValue, bool i } metadata.dbCreateTime = inValue; - return SaveMetaDataValue(deviceId, metadata, isNeedHash); + return SaveMetaDataValue(deviceId, userId, metadata, isNeedHash); } -int Metadata::ResetMetaDataAfterRemoveData(const DeviceID &deviceId) +int Metadata::ResetMetaDataAfterRemoveData(const DeviceID &deviceId, const DeviceID &userId) { std::lock_guard lockGuard(metadataLock_); MetaDataValue metadata; - int errCode = GetMetaDataValue(deviceId, metadata, true); + int errCode = GetMetaDataValue(deviceId, userId, metadata, true); if (errCode == E_OK) { metadata.clearDeviceDataMark = 0; - return SaveMetaDataValue(deviceId, metadata, true); + return SaveMetaDataValue(deviceId, userId, metadata, true); } return errCode; } -void Metadata::GetRemoveDataMark(const DeviceID &deviceId, uint64_t &outValue) +void Metadata::GetRemoveDataMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue) { std::lock_guard lockGuard(metadataLock_); MetaDataValue metadata; - int errCode = GetMetaDataValue(deviceId, metadata, true); + int errCode = GetMetaDataValue(deviceId, userId, metadata, true); if (errCode == E_OK) { outValue = metadata.clearDeviceDataMark; return; @@ -601,12 +645,13 @@ void Metadata::UnlockWaterMark() const waterMarkMutex_.unlock(); } -int Metadata::GetWaterMarkInfoFromDB(const std::string &dev, bool isNeedHash, WatermarkInfo &info) +int Metadata::GetWaterMarkInfoFromDB(const std::string &dev, const std::string &userId, bool isNeedHash, + WatermarkInfo &info) { // read from db avoid watermark update in diff process std::lock_guard lockGuard(metadataLock_); MetaDataValue metadata; - int errCode = GetMetaDataValue(dev, metadata, isNeedHash); + int errCode = GetMetaDataValue(dev, userId, metadata, isNeedHash); if (errCode == -E_NOT_FOUND) { LOGD("[Metadata] not found meta value"); return E_OK; @@ -707,41 +752,41 @@ void Metadata::ClearMetaDataValue(uint32_t innerClearAction, MetaDataValue &meta } } -int Metadata::SetAbilitySyncFinishMark(const std::string &deviceId, bool finish) +int Metadata::SetAbilitySyncFinishMark(const std::string &deviceId, const std::string &userId, bool finish) { - return SetSyncMark(deviceId, SyncMark::SYNC_MARK_ABILITY_SYNC, finish); + return SetSyncMark(deviceId, userId, SyncMark::SYNC_MARK_ABILITY_SYNC, finish); } -bool Metadata::IsAbilitySyncFinish(const std::string &deviceId) +bool Metadata::IsAbilitySyncFinish(const std::string &deviceId, const std::string &userId) { - return IsContainSyncMark(deviceId, SyncMark::SYNC_MARK_ABILITY_SYNC); + return IsContainSyncMark(deviceId, userId, SyncMark::SYNC_MARK_ABILITY_SYNC); } -int Metadata::SetTimeSyncFinishMark(const std::string &deviceId, bool finish) +int Metadata::SetTimeSyncFinishMark(const std::string &deviceId, const std::string &userId, bool finish) { - return SetSyncMark(deviceId, SyncMark::SYNC_MARK_TIME_SYNC, finish); + return SetSyncMark(deviceId, userId, SyncMark::SYNC_MARK_TIME_SYNC, finish); } -int Metadata::SetTimeChangeMark(const std::string &deviceId, bool change) +int Metadata::SetTimeChangeMark(const std::string &deviceId, const std::string &userId, bool change) { - return SetSyncMark(deviceId, SyncMark::SYNC_MARK_TIME_CHANGE, change); + return SetSyncMark(deviceId, userId, SyncMark::SYNC_MARK_TIME_CHANGE, change); } -bool Metadata::IsTimeSyncFinish(const std::string &deviceId) +bool Metadata::IsTimeSyncFinish(const std::string &deviceId, const std::string &userId) { - return IsContainSyncMark(deviceId, SyncMark::SYNC_MARK_TIME_SYNC); + return IsContainSyncMark(deviceId, userId, SyncMark::SYNC_MARK_TIME_SYNC); } -bool Metadata::IsTimeChange(const std::string &deviceId) +bool Metadata::IsTimeChange(const std::string &deviceId, const std::string &userId) { - return IsContainSyncMark(deviceId, SyncMark::SYNC_MARK_TIME_CHANGE); + return IsContainSyncMark(deviceId, userId, SyncMark::SYNC_MARK_TIME_CHANGE); } -int Metadata::SetSyncMark(const std::string &deviceId, SyncMark syncMark, bool finish) +int Metadata::SetSyncMark(const std::string &deviceId, const std::string &userId, SyncMark syncMark, bool finish) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); auto mark = static_cast(syncMark); if (finish) { metadata.syncMark |= mark; @@ -750,56 +795,56 @@ int Metadata::SetSyncMark(const std::string &deviceId, SyncMark syncMark, bool f } LOGD("[Metadata] Mark:%" PRIx64 " sync finish:%d sync mark:%" PRIu64, mark, static_cast(finish), metadata.syncMark); - return SaveMetaDataValue(deviceId, metadata); + return SaveMetaDataValue(deviceId, userId, metadata); } -bool Metadata::IsContainSyncMark(const std::string &deviceId, SyncMark syncMark) +bool Metadata::IsContainSyncMark(const std::string &deviceId, const std::string &userId, SyncMark syncMark) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); auto mark = static_cast(syncMark); return (metadata.syncMark & mark) == mark; } -int Metadata::SetRemoteSchemaVersion(const std::string &deviceId, uint64_t schemaVersion) +int Metadata::SetRemoteSchemaVersion(const std::string &deviceId, const std::string &userId, uint64_t schemaVersion) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); metadata.remoteSchemaVersion = schemaVersion; LOGI("[Metadata] Set %.3s schema version %" PRIu64, deviceId.c_str(), schemaVersion); - int errCode = SaveMetaDataValue(deviceId, metadata); + int errCode = SaveMetaDataValue(deviceId, userId, metadata); if (errCode != E_OK) { LOGW("[Metadata] Set remote schema version failed"); } return errCode; } -uint64_t Metadata::GetRemoteSchemaVersion(const std::string &deviceId) +uint64_t Metadata::GetRemoteSchemaVersion(const std::string &deviceId, const std::string &userId) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); LOGI("[Metadata] Get %.3s schema version %" PRIu64, deviceId.c_str(), metadata.remoteSchemaVersion); return metadata.remoteSchemaVersion; } -int Metadata::SetSystemTimeOffset(const std::string &deviceId, int64_t systemTimeOffset) +int Metadata::SetSystemTimeOffset(const std::string &deviceId, const std::string &userId, int64_t systemTimeOffset) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); metadata.systemTimeOffset = systemTimeOffset; LOGI("[Metadata] Set %.3s systemTimeOffset %" PRId64, deviceId.c_str(), systemTimeOffset); - return SaveMetaDataValue(deviceId, metadata); + return SaveMetaDataValue(deviceId, userId, metadata); } -int64_t Metadata::GetSystemTimeOffset(const std::string &deviceId) +int64_t Metadata::GetSystemTimeOffset(const std::string &deviceId, const std::string &userId) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); LOGI("[Metadata] Get %.3s systemTimeOffset %" PRId64, deviceId.c_str(), metadata.systemTimeOffset); return metadata.systemTimeOffset; } @@ -939,11 +984,12 @@ int Metadata::InitLocalMetaData() return errCode; } -int Metadata::GetMetaDataValueFromDB(const std::string &deviceId, bool isNeedHash, MetaDataValue &metaDataValue) +int Metadata::GetMetaDataValueFromDB(const std::string &deviceId, const std::string &userId, bool isNeedHash, + MetaDataValue &metaDataValue) { DeviceID hashDeviceId; Key devKey; - GetHashDeviceId(deviceId, hashDeviceId, isNeedHash); + GetHashDeviceId(deviceId, userId, hashDeviceId, isNeedHash); DBCommon::StringToVector(hashDeviceId, devKey); return GetMetaDataValueFromDB(devKey, metaDataValue); @@ -960,21 +1006,52 @@ int Metadata::GetMetaDataValueFromDB(const Key &key, MetaDataValue &metaDataValu return DeSerializeMetaData(value, metaDataValue); } -uint64_t Metadata::GetRemoteSoftwareVersion(const std::string &deviceId) +int Metadata::GetMetaDataFromDBByPrefixKey(const std::string &deviceId, bool isNeedHash, + std::map &metaData) +{ + DeviceID hashId; + Key keyPrefix; + GetHashDeviceId(deviceId, "", hashId, isNeedHash); + DBCommon::StringToVector(hashId, keyPrefix); + + std::map data; + int errCode = GetMetadataFromDbByPrefixKey(keyPrefix, data); + if (errCode != E_OK) { + if (errCode == -E_NOT_FOUND) { + MetaDataValue oneMetaData; + metaData[keyPrefix] = oneMetaData; + return E_OK; + } + LOGE("[Metadata] Get metadata from db by prefix key failed %d", errCode); + return errCode; + } + for (const auto &oneData : data) { + MetaDataValue metaDataValue; + errCode = DeSerializeMetaData(oneData.second, metaDataValue); + if (errCode != E_OK) { + LOGE("[Metadata] DeSerialize meta data failed %d", errCode); + return errCode; + } + metaData[oneData.first] = metaDataValue; + } + return E_OK; +} + +uint64_t Metadata::GetRemoteSoftwareVersion(const std::string &deviceId, const std::string &userId) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); return metadata.remoteSoftwareVersion; } -int Metadata::SetRemoteSoftwareVersion(const std::string &deviceId, uint64_t version) +int Metadata::SetRemoteSoftwareVersion(const std::string &deviceId, const std::string &userId, uint64_t version) { MetaDataValue metadata; std::lock_guard lockGuard(metadataLock_); - GetMetaDataValue(deviceId, metadata, true); + GetMetaDataValue(deviceId, userId, metadata, true); metadata.remoteSoftwareVersion = version; LOGI("[Metadata] Set %.3s version %" PRId64, deviceId.c_str(), version); - return SaveMetaDataValue(deviceId, metadata); + return SaveMetaDataValue(deviceId, userId, metadata); } } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.h index 4df789a0..038747e6 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.h @@ -67,17 +67,17 @@ public: int Initialize(ISyncInterface *storage); - int SaveTimeOffset(const DeviceID &deviceId, TimeOffset inValue); + int SaveTimeOffset(const DeviceID &deviceId, const DeviceID &userId, TimeOffset inValue); - void GetTimeOffset(const DeviceID &deviceId, TimeOffset &outValue); + void GetTimeOffset(const DeviceID &deviceId, const DeviceID &userId, TimeOffset &outValue); - virtual void GetLocalWaterMark(const DeviceID &deviceId, uint64_t &outValue); + virtual void GetLocalWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue); - int SaveLocalWaterMark(const DeviceID &deviceId, uint64_t inValue); + int SaveLocalWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t inValue); - void GetPeerWaterMark(const DeviceID &deviceId, uint64_t &outValue, bool isNeedHash = true); + void GetPeerWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue, bool isNeedHash = true); - int SavePeerWaterMark(const DeviceID &deviceId, uint64_t inValue, bool isNeedHash); + int SavePeerWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t inValue, bool isNeedHash); int SaveLocalTimeOffset(TimeOffset timeOffset, bool saveIntoDb = true); @@ -85,52 +85,56 @@ public: int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash); - int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, const std::string &tableName); + int EraseDeviceWaterMark(const std::string &deviceId, const std::string &userId, bool isNeedHash, + const std::string &tableName); void SetLastLocalTime(Timestamp lastLocalTime); Timestamp GetLastLocalTime() const; int SetSendQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, const WaterMark &waterMark); + const std::string &deviceId, const std::string &userId, const WaterMark &waterMark); // the querySync's sendWatermark will increase by the device watermark // if the sendWatermark less than device watermark int GetSendQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, WaterMark &waterMark, bool isAutoLift = true); + const std::string &deviceId, const std::string &userId, WaterMark &waterMark, bool isAutoLift = true); int SetRecvQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, const WaterMark &waterMark); + const std::string &deviceId, const std::string &userId, const WaterMark &waterMark); // the querySync's recvWatermark will increase by the device watermark // if the watermark less than device watermark int GetRecvQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, WaterMark &waterMark); + const std::string &deviceId, const std::string &userId, WaterMark &waterMark); virtual int SetLastQueryTime(const std::string &queryIdentify, const std::string &deviceId, - const Timestamp ×tamp); + const std::string &userId, const Timestamp ×tamp); - virtual int GetLastQueryTime(const std::string &queryIdentify, const std::string &deviceId, Timestamp ×tamp); + virtual int GetLastQueryTime(const std::string &queryIdentify, const std::string &deviceId, + const std::string &userId, Timestamp ×tamp); - int SetSendDeleteSyncWaterMark(const std::string &deviceId, const WaterMark &waterMark); + int SetSendDeleteSyncWaterMark(const std::string &deviceId, const std::string &userId, const WaterMark &waterMark); // the deleteSync's sendWatermark will increase by the device watermark // if the sendWatermark less than device watermark - int GetSendDeleteSyncWaterMark(const std::string &deviceId, WaterMark &waterMark, bool isAutoLift = true); + int GetSendDeleteSyncWaterMark(const std::string &deviceId, const std::string &userId, WaterMark &waterMark, + bool isAutoLift = true); - int SetRecvDeleteSyncWaterMark(const std::string &deviceId, const WaterMark &waterMark, bool isNeedHash = true); + int SetRecvDeleteSyncWaterMark(const std::string &deviceId, const std::string &userId, const WaterMark &waterMark, + bool isNeedHash = true); // the deleteSync's recvWatermark will increase by the device watermark // if the recvWatermark less than device watermark - int GetRecvDeleteSyncWaterMark(const std::string &deviceId, WaterMark &waterMark); + int GetRecvDeleteSyncWaterMark(const std::string &deviceId, const std::string &userId, WaterMark &waterMark); - void GetDbCreateTime(const DeviceID &deviceId, uint64_t &outValue); + void GetDbCreateTime(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue); - int SetDbCreateTime(const DeviceID &deviceId, uint64_t inValue, bool isNeedHash); + int SetDbCreateTime(const DeviceID &deviceId, const DeviceID &userId, uint64_t inValue, bool isNeedHash); - int ResetMetaDataAfterRemoveData(const DeviceID &deviceId); + int ResetMetaDataAfterRemoveData(const DeviceID &deviceId, const DeviceID &userId); - void GetRemoveDataMark(const DeviceID &deviceId, uint64_t &outValue); + void GetRemoveDataMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue); // always get value from db, value updated from storage trigger uint64_t GetQueryLastTimestamp(const DeviceID &deviceId, const std::string &queryId) const; @@ -145,45 +149,46 @@ public: void UnlockWaterMark() const; - int GetWaterMarkInfoFromDB(const std::string &dev, bool isNeedHash, WatermarkInfo &info); + int GetWaterMarkInfoFromDB(const std::string &dev, const std::string &userId, bool isNeedHash, WatermarkInfo &info); int ClearAllAbilitySyncFinishMark(); - int SetAbilitySyncFinishMark(const std::string &deviceId, bool finish); + int SetAbilitySyncFinishMark(const std::string &deviceId, const std::string &userId, bool finish); - bool IsAbilitySyncFinish(const std::string &deviceId); + bool IsAbilitySyncFinish(const std::string &deviceId, const std::string &userId); int ClearAllTimeSyncFinishMark(); - int SetTimeSyncFinishMark(const std::string &deviceId, bool finish); + int SetTimeSyncFinishMark(const std::string &deviceId, const std::string &userId, bool finish); - int SetTimeChangeMark(const std::string &deviceId, bool change); + int SetTimeChangeMark(const std::string &deviceId, const std::string &userId, bool change); - bool IsTimeSyncFinish(const std::string &deviceId); + bool IsTimeSyncFinish(const std::string &deviceId, const std::string &userId); - bool IsTimeChange(const std::string &deviceId); + bool IsTimeChange(const std::string &deviceId, const std::string &userId); - int SetRemoteSchemaVersion(const std::string &deviceId, uint64_t schemaVersion); + int SetRemoteSchemaVersion(const std::string &deviceId, const std::string &userId, uint64_t schemaVersion); - uint64_t GetRemoteSchemaVersion(const std::string &deviceId); + uint64_t GetRemoteSchemaVersion(const std::string &deviceId, const std::string &userId); - int SetSystemTimeOffset(const std::string &deviceId, int64_t systemTimeOffset); + int SetSystemTimeOffset(const std::string &deviceId, const std::string &userId, int64_t systemTimeOffset); - int64_t GetSystemTimeOffset(const std::string &deviceId); + int64_t GetSystemTimeOffset(const std::string &deviceId, const std::string &userId); std::pair GetLocalSchemaVersion(); int SetLocalSchemaVersion(uint64_t schemaVersion); - uint64_t GetRemoteSoftwareVersion(const std::string &deviceId); + uint64_t GetRemoteSoftwareVersion(const std::string &deviceId, const std::string &userId); - int SetRemoteSoftwareVersion(const std::string &deviceId, uint64_t version); + int SetRemoteSoftwareVersion(const std::string &deviceId, const std::string &userId, uint64_t version); private: - int SaveMetaDataValue(const DeviceID &deviceId, const MetaDataValue &inValue, bool isNeedHash = true); + int SaveMetaDataValue(const DeviceID &deviceId, const DeviceID &userId, const MetaDataValue &inValue, + bool isNeedHash = true); // sync module need hash devices id - int GetMetaDataValue(const DeviceID &deviceId, MetaDataValue &outValue, bool isNeedHash); + int GetMetaDataValue(const DeviceID &deviceId, const DeviceID &userId, MetaDataValue &outValue, bool isNeedHash); static int SerializeMetaData(const MetaDataValue &inValue, std::vector &outValue); @@ -191,6 +196,8 @@ private: int GetMetadataFromDb(const std::vector &key, std::vector &outValue) const; + int GetMetadataFromDbByPrefixKey(const Key &keyPrefix, std::map &data) const; + int SetMetadataToDb(const std::vector &key, const std::vector &inValue); int64_t StringToLong(const std::vector &value) const; @@ -199,14 +206,15 @@ private: int LoadAllMetadata(); - void GetHashDeviceId(const DeviceID &deviceId, DeviceID &hashDeviceId, bool isNeedHash); + void GetHashDeviceId(const DeviceID &deviceId, const DeviceID &userId, DeviceID &hashDeviceId, bool isNeedHash); // reset the waterMark to zero - int ResetRecvQueryWaterMark(const DeviceID &deviceId, const std::string &tableName, bool isNeedHash); + int ResetRecvQueryWaterMark(const DeviceID &deviceId, const DeviceID &userId, const std::string &tableName, + bool isNeedHash); - int SetSyncMark(const std::string &deviceId, SyncMark syncMark, bool finish); + int SetSyncMark(const std::string &deviceId, const std::string &userId, SyncMark syncMark, bool finish); - bool IsContainSyncMark(const std::string &deviceId, SyncMark syncMark); + bool IsContainSyncMark(const std::string &deviceId, const std::string &userId, SyncMark syncMark); int SaveLocalMetaData(const LocalMetaData &localMetaData); @@ -233,9 +241,12 @@ private: int InitLocalMetaData(); - int GetMetaDataValueFromDB(const std::string &deviceId, bool isNeedHash, MetaDataValue &metaDataValue); + int GetMetaDataValueFromDB(const std::string &deviceId, const std::string &userId, bool isNeedHash, + MetaDataValue &metaDataValue); int GetMetaDataValueFromDB(const Key &key, MetaDataValue &metaDataValue); + int GetMetaDataFromDBByPrefixKey(const std::string &deviceId, bool isNeedHash, + std::map &metaData); // store localTimeOffset in ram; if change, should add a lock first, change here and metadata, // then release lock @@ -246,7 +257,7 @@ private: // if changed, it should be locked from save-to-db to change-in-memory.save to db must be first, // if save to db fail, it will not be changed in memory. mutable std::mutex metadataLock_; - std::map deviceIdToHashDeviceIdMap_; + std::map deviceIdToHashDeviceIdMap_; // store localTimeOffset in ram, used to make timestamp increase mutable std::mutex lastLocalTimeLock_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/multiver/multi_ver_sync_state_machine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/multiver/multi_ver_sync_state_machine.cpp index 49df30b6..e658e17b 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/multiver/multi_ver_sync_state_machine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/multiver/multi_ver_sync_state_machine.cpp @@ -74,7 +74,8 @@ int MultiVerSyncStateMachine::Initialize(ISyncTaskContext *context, ISyncInterfa multiVerDataSync_ = std::make_unique(); valueSliceSync_ = std::make_unique(); - errCode = timeSync_->Initialize(communicator, metadata, syncInterface, context->GetDeviceId()); + errCode = timeSync_->Initialize(communicator, metadata, syncInterface, context->GetDeviceId(), + context->GetTargetUserId()); if (errCode != E_OK) { LOGE("timeSync_->Initialize failed err %d", errCode); goto ERROR_OUT; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/query_sync_water_mark_helper.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/query_sync_water_mark_helper.cpp index c708137c..61b961ab 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/query_sync_water_mark_helper.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/query_sync_water_mark_helper.cpp @@ -50,6 +50,14 @@ int QuerySyncWaterMarkHelper::GetMetadataFromDb(const std::vector &key, return storage_->GetMetaData(key, outValue); } +int QuerySyncWaterMarkHelper::GetMetadataByPrefixKeyFromDb(const Key &prefixKey, std::map &data) +{ + if (storage_ == nullptr) { + return -E_INVALID_DB; + } + return storage_->GetMetaDataByPrefixKey(prefixKey, data); +} + int QuerySyncWaterMarkHelper::SetMetadataToDb(const std::vector &key, const std::vector &inValue) { if (storage_ == nullptr) { @@ -105,25 +113,25 @@ int QuerySyncWaterMarkHelper::GetQueryWaterMarkInCacheAndDb(const std::string &c } int QuerySyncWaterMarkHelper::GetQueryWaterMark(const std::string &queryIdentify, const std::string &deviceId, - QueryWaterMark &queryWaterMark) + const std::string &userId, QueryWaterMark &queryWaterMark) { - std::string cacheKey = GetHashQuerySyncDeviceId(deviceId, queryIdentify); + std::string cacheKey = GetHashQuerySyncDeviceId(deviceId, userId, queryIdentify); std::lock_guard autoLock(queryWaterMarkLock_); return GetQueryWaterMarkInCacheAndDb(cacheKey, queryWaterMark); } int QuerySyncWaterMarkHelper::SetRecvQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, const WaterMark &waterMark) + const std::string &deviceId, const std::string &userId, const WaterMark &waterMark) { - std::string cacheKey = GetHashQuerySyncDeviceId(deviceId, queryIdentify); + std::string cacheKey = GetHashQuerySyncDeviceId(deviceId, userId, queryIdentify); std::lock_guard autoLock(queryWaterMarkLock_); return SetRecvQueryWaterMarkWithoutLock(cacheKey, waterMark); } int QuerySyncWaterMarkHelper::SetLastQueryTime(const std::string &queryIdentify, - const std::string &deviceId, const Timestamp ×tamp) + const std::string &deviceId, const std::string &userId, const Timestamp ×tamp) { - std::string cacheKey = GetHashQuerySyncDeviceId(deviceId, queryIdentify); + std::string cacheKey = GetHashQuerySyncDeviceId(deviceId, userId, queryIdentify); std::lock_guard autoLock(queryWaterMarkLock_); QueryWaterMark queryWaterMark; int errCode = GetQueryWaterMarkInCacheAndDb(cacheKey, queryWaterMark); @@ -147,9 +155,9 @@ int QuerySyncWaterMarkHelper::SetRecvQueryWaterMarkWithoutLock(const std::string } int QuerySyncWaterMarkHelper::SetSendQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, const WaterMark &waterMark) + const std::string &deviceId, const std::string &userId, const WaterMark &waterMark) { - std::string cacheKey = GetHashQuerySyncDeviceId(deviceId, queryIdentify); + std::string cacheKey = GetHashQuerySyncDeviceId(deviceId, userId, queryIdentify); QueryWaterMark queryWaterMark; std::lock_guard autoLock(queryWaterMarkLock_); int errCode = GetQueryWaterMarkInCacheAndDb(cacheKey, queryWaterMark); @@ -265,31 +273,36 @@ uint64_t QuerySyncWaterMarkHelper::CalculateQueryWaterMarkSize(const QueryWaterM return length; } -DeviceID QuerySyncWaterMarkHelper::GetHashQuerySyncDeviceId(const DeviceID &deviceId, const DeviceID &queryId) +DeviceID QuerySyncWaterMarkHelper::GetHashQuerySyncDeviceId(const DeviceID &deviceId, const DeviceID &userId, + const DeviceID &queryId) { std::lock_guard autoLock(queryWaterMarkLock_); DeviceID hashQuerySyncId; - if (deviceIdToHashQuerySyncIdMap_[deviceId].count(queryId) == 0) { + DeviceSyncTarget deviceInfo(deviceId, userId); + if (deviceIdToHashQuerySyncIdMap_[deviceInfo].count(queryId) == 0) { // do not modify this - hashQuerySyncId = DBConstant::QUERY_SYNC_PREFIX_KEY + DBCommon::TransferHashString(deviceId) + queryId; - deviceIdToHashQuerySyncIdMap_[deviceId][queryId] = hashQuerySyncId; + hashQuerySyncId = DBConstant::QUERY_SYNC_PREFIX_KEY + DBCommon::TransferHashString(deviceId) + queryId + + DBConstant::USERID_PREFIX_KEY + userId; + deviceIdToHashQuerySyncIdMap_[deviceInfo][queryId] = hashQuerySyncId; } else { - hashQuerySyncId = deviceIdToHashQuerySyncIdMap_[deviceId][queryId]; + hashQuerySyncId = deviceIdToHashQuerySyncIdMap_[deviceInfo][queryId]; } return hashQuerySyncId; } -int QuerySyncWaterMarkHelper::GetDeleteSyncWaterMark(const std::string &deviceId, DeleteWaterMark &deleteWaterMark) +int QuerySyncWaterMarkHelper::GetDeleteSyncWaterMark(const std::string &deviceId, const std::string &userId, + DeleteWaterMark &deleteWaterMark) { - std::string hashId = GetHashDeleteSyncDeviceId(deviceId); + std::string hashId = GetHashDeleteSyncDeviceId(deviceId, userId); // lock prevent different thread visit deleteSyncCache_ std::lock_guard autoLock(deleteSyncLock_); return GetDeleteWaterMarkFromCache(hashId, deleteWaterMark); } -int QuerySyncWaterMarkHelper::SetSendDeleteSyncWaterMark(const DeviceID &deviceId, const WaterMark &waterMark) +int QuerySyncWaterMarkHelper::SetSendDeleteSyncWaterMark(const DeviceID &deviceId, const std::string &userId, + const WaterMark &waterMark) { - std::string hashId = GetHashDeleteSyncDeviceId(deviceId); + std::string hashId = GetHashDeleteSyncDeviceId(deviceId, userId); DeleteWaterMark deleteWaterMark; // lock prevent different thread visit deleteSyncCache_ std::lock_guard autoLock(deleteSyncLock_); @@ -301,19 +314,35 @@ int QuerySyncWaterMarkHelper::SetSendDeleteSyncWaterMark(const DeviceID &deviceI return UpdateDeleteSyncCacheAndSave(hashId, deleteWaterMark); } -int QuerySyncWaterMarkHelper::SetRecvDeleteSyncWaterMark(const DeviceID &deviceId, const WaterMark &waterMark, - bool isNeedHash) +int QuerySyncWaterMarkHelper::SetRecvDeleteSyncWaterMark(const DeviceID &deviceId, const std::string &userId, + const WaterMark &waterMark, bool isNeedHash) { - std::string hashId = GetHashDeleteSyncDeviceId(deviceId, isNeedHash); - DeleteWaterMark deleteWaterMark; + std::string hashId = GetHashDeleteSyncDeviceId(deviceId, userId, isNeedHash); // lock prevent different thread visit deleteSyncCache_ std::lock_guard autoLock(deleteSyncLock_); - int errCode = GetDeleteWaterMarkFromCache(hashId, deleteWaterMark); + int errCode = E_OK; + std::map deleteWaterMarks; + if (!userId.empty()) { + DeleteWaterMark deleteWaterMark; + Key dbKey; + DBCommon::StringToVector(hashId, dbKey); + errCode = GetDeleteWaterMarkFromCache(hashId, deleteWaterMark); + deleteWaterMark.recvWaterMark = waterMark; + deleteWaterMarks[dbKey] = deleteWaterMark; + } else { + errCode = GetDeleteWatersMarkFromDB(hashId, deleteWaterMarks); + } if (errCode != E_OK) { return errCode; } - deleteWaterMark.recvWaterMark = waterMark; - return UpdateDeleteSyncCacheAndSave(hashId, deleteWaterMark); + for (auto &deleteWaterMark : deleteWaterMarks) { + deleteWaterMark.second.recvWaterMark = waterMark; + errCode = UpdateDeleteSyncCacheAndSave(hashId, deleteWaterMark.second); + if (errCode != E_OK) { + return errCode; + } + } + return E_OK; } int QuerySyncWaterMarkHelper::UpdateDeleteSyncCacheAndSave(const std::string &dbKey, @@ -354,6 +383,34 @@ int QuerySyncWaterMarkHelper::GetDeleteWaterMarkFromDB(const DeviceID &hashDevic return DeSerializeDeleteWaterMark(dbValue, deleteWaterMark); } +int QuerySyncWaterMarkHelper::GetDeleteWatersMarkFromDB(const DeviceID &hashId, + std::map &deleteWaterMarks) +{ + Key dbKeyPrefix; + DBCommon::StringToVector(hashId, dbKeyPrefix); + // search in db + std::map dbData; + int errCode = GetMetadataByPrefixKeyFromDb(dbKeyPrefix, dbData); + if (errCode == -E_NOT_FOUND) { + DeleteWaterMark deleteWaterMark; + deleteWaterMarks[dbKeyPrefix] = deleteWaterMark; + return E_OK; + } + if (errCode != E_OK) { + return errCode; + } + // serialize value + for (const auto &oneDbData : dbData) { + DeleteWaterMark deleteWaterMark; + errCode = DeSerializeDeleteWaterMark(oneDbData.second, deleteWaterMark); + if (errCode != E_OK) { + return errCode; + } + deleteWaterMarks[oneDbData.first] = deleteWaterMark; + } + return E_OK; +} + int QuerySyncWaterMarkHelper::SaveDeleteWaterMarkToDB(const DeviceID &hashDeviceId, const DeleteWaterMark &deleteWaterMark) { @@ -373,16 +430,18 @@ int QuerySyncWaterMarkHelper::SaveDeleteWaterMarkToDB(const DeviceID &hashDevice return errCode; } -DeviceID QuerySyncWaterMarkHelper::GetHashDeleteSyncDeviceId(const DeviceID &deviceId, bool isNeedHash) +DeviceID QuerySyncWaterMarkHelper::GetHashDeleteSyncDeviceId(const DeviceID &deviceId, const DeviceID &userId, + bool isNeedHash) { DeviceID hashDeleteSyncId; + DeviceSyncTarget deviceInfo(deviceId, userId); std::lock_guard autoLock(deleteSyncLock_); - if (deviceIdToHashDeleteSyncIdMap_.count(deviceId) == 0) { + if (deviceIdToHashDeleteSyncIdMap_.count(deviceInfo) == 0) { hashDeleteSyncId = DBConstant::DELETE_SYNC_PREFIX_KEY + - (isNeedHash ? DBCommon::TransferHashString(deviceId) : deviceId); - deviceIdToHashDeleteSyncIdMap_.insert(std::pair(deviceId, hashDeleteSyncId)); + (isNeedHash ? DBCommon::TransferHashString(deviceId) : deviceId) + DBConstant::USERID_PREFIX_KEY + userId; + deviceIdToHashDeleteSyncIdMap_.insert(std::pair(deviceInfo, hashDeleteSyncId)); } else { - hashDeleteSyncId = deviceIdToHashDeleteSyncIdMap_[deviceId]; + hashDeleteSyncId = deviceIdToHashDeleteSyncIdMap_[deviceInfo]; } return hashDeleteSyncId; } @@ -484,8 +543,8 @@ int QuerySyncWaterMarkHelper::RemoveLeastUsedQuerySyncItems(const std::vector autoLock(queryWaterMarkLock_); @@ -496,6 +555,9 @@ int QuerySyncWaterMarkHelper::ResetRecvQueryWaterMark(const DeviceID &deviceId, std::string hexTableName = DBCommon::TransferStringToHex(hashTableName); prefixKeyStr += hexTableName; } + if (!userId.empty()) { + prefixKeyStr += DBConstant::USERID_PREFIX_KEY + userId; + } // remove in db Key prefixKey; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/query_sync_water_mark_helper.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/query_sync_water_mark_helper.h index 6c576a2b..1e96e746 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/query_sync_water_mark_helper.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/query_sync_water_mark_helper.h @@ -50,23 +50,25 @@ public: int Initialize(ISyncInterface *storage); - int GetQueryWaterMark(const std::string &queryIdentify, const std::string &deviceId, + int GetQueryWaterMark(const std::string &queryIdentify, const std::string &deviceId, const std::string &userId, QueryWaterMark &queryWaterMark); int SetSendQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, const WaterMark &waterMark); + const std::string &deviceId, const std::string &userId, const WaterMark &waterMark); int SetRecvQueryWaterMark(const std::string &queryIdentify, - const std::string &deviceId, const WaterMark &waterMark); + const std::string &deviceId, const std::string &userId, const WaterMark &waterMark); int SetLastQueryTime(const std::string &queryIdentify, - const std::string &deviceId, const Timestamp ×tamp); + const std::string &deviceId, const std::string &userId, const Timestamp ×tamp); - int GetDeleteSyncWaterMark(const std::string &deviceId, DeleteWaterMark &deleteWaterMark); + int GetDeleteSyncWaterMark(const std::string &deviceId, const std::string &userId, + DeleteWaterMark &deleteWaterMark); - int SetSendDeleteSyncWaterMark(const std::string &deviceId, const WaterMark &waterMark); + int SetSendDeleteSyncWaterMark(const std::string &deviceId, const std::string &userId, const WaterMark &waterMark); - int SetRecvDeleteSyncWaterMark(const std::string &deviceId, const WaterMark &waterMark, bool isNeedHash); + int SetRecvDeleteSyncWaterMark(const std::string &deviceId, const std::string &userId, const WaterMark &waterMark, + bool isNeedHash); // this function will read deleteWaterMark from db by it's deleteWaterMarkKey // and then serialize it and put to cache @@ -76,7 +78,8 @@ public: int RemoveLeastUsedQuerySyncItems(const std::vector &querySyncIds); // reset the waterMark to zero - int ResetRecvQueryWaterMark(const DeviceID &deviceId, const std::string &tableName, bool isNeedHash); + int ResetRecvQueryWaterMark(const DeviceID &deviceId, const DeviceID &userId, const std::string &tableName, + bool isNeedHash); static std::string GetQuerySyncPrefixKey(); @@ -86,6 +89,8 @@ private: int GetMetadataFromDb(const std::vector &key, std::vector &outValue); + int GetMetadataByPrefixKeyFromDb(const Key &prefixKey, std::map &data); + int SetMetadataToDb(const std::vector &key, const std::vector &inValue); int DeleteMetaDataFromDB(const std::vector &keys) const; @@ -107,7 +112,7 @@ private: // get the querySync hashId in cache_ or generate one and then put it in to cache_ // the hashId is made up of "QUERY_SYNC_PREFIX_KEY" + hash(deviceId) + queryId - DeviceID GetHashQuerySyncDeviceId(const DeviceID &deviceId, const DeviceID &queryId); + DeviceID GetHashQuerySyncDeviceId(const DeviceID &deviceId, const DeviceID &userId, const DeviceID &queryId); // put queryWaterMark to lru cache_ and then save to db int UpdateCacheAndSave(const std::string &cacheKey, QueryWaterMark &queryWaterMark); @@ -118,12 +123,14 @@ private: // get the deleteSync hashId in cache_ or generate one and then put it in to cache_ // the hashId is made up of "DELETE_SYNC_PREFIX_KEY" + hash(deviceId) - DeviceID GetHashDeleteSyncDeviceId(const DeviceID &deviceId, bool isNeedHash = true); + DeviceID GetHashDeleteSyncDeviceId(const DeviceID &deviceId, const DeviceID &userId, bool isNeedHash = true); int SaveDeleteWaterMarkToDB(const DeviceID &hashDeviceId, const DeleteWaterMark &deleteWaterMark); int GetDeleteWaterMarkFromDB(const DeviceID &hashDeviceId, DeleteWaterMark &deleteWaterMark); + int GetDeleteWatersMarkFromDB(const DeviceID &hashId, std::map &deleteWaterMarks); + // put queryWaterMark to lru cache_ and then save to db int UpdateDeleteSyncCacheAndSave(const std::string &dbKey, const DeleteWaterMark &deleteWaterMark); @@ -143,11 +150,11 @@ private: // because it will change the eliminationChain // and the queryWaterMark use a LRU Map to store in ram std::mutex queryWaterMarkLock_; - std::map> deviceIdToHashQuerySyncIdMap_; + std::map> deviceIdToHashQuerySyncIdMap_; // also store deleteKeyWaterMark should add a lock std::mutex deleteSyncLock_; - std::map deviceIdToHashDeleteSyncIdMap_; + std::map deviceIdToHashDeleteSyncIdMap_; ISyncInterface *storage_; }; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor.cpp index 3d69bcf1..0ecc1db3 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor.cpp @@ -105,8 +105,6 @@ int RemoteExecutor::ReceiveMessage(const std::string &targetDev, Message *inMsg) } if (closed_) { LOGD("[RemoteExecutor][ReceiveMessageInner] db is closing ignore msg"); - delete inMsg; - inMsg = nullptr; return -E_BUSY; } RefObject::IncObjRef(this); @@ -1040,4 +1038,10 @@ int RemoteExecutor::CheckRemoteRecvData(const std::string &device, SyncGenericIn } return -E_SECURITY_OPTION_CHECK_ERROR; } + +int32_t RemoteExecutor::GetTaskCount() const +{ + std::lock_guard autoLock(taskLock_); + return static_cast(taskMap_.size()); // max taskMap_ size is 32 +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor.h index 62544a17..11fce635 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor.h @@ -72,6 +72,7 @@ public: void NotifyConnectionClosed(uint64_t connectionId); + int32_t GetTaskCount() const; protected: virtual void ParseOneRequestMessage(const std::string &device, Message *inMsg); @@ -147,7 +148,7 @@ private: static int CheckRemoteRecvData(const std::string &device, SyncGenericInterface *storage, int32_t remoteSecLabel, uint32_t remoteVersion); - std::mutex taskLock_; + mutable std::mutex taskLock_; std::map> searchTaskQueue_; // key is device, value is sessionId queue std::map> deviceWorkingSet_; // key is device, value is sessionId set std::map taskMap_; // key is sessionId diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_message_schedule.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_message_schedule.cpp index da64cdb2..d558c325 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_message_schedule.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_message_schedule.cpp @@ -93,8 +93,8 @@ void SingleVerDataMessageSchedule::ScheduleInfoHandle(bool isNeedHandleStatus, b ClearMsgMapWithNoLock(); expectedSequenceId_ = 1; } else { - LOGI("[DataMsgSchedule] DealMsg seqId=%" PRIu32 " finishedPacketId=%" PRIu64 " ok,label=%s,dev=%s", - expectedSequenceId_, finishedPacketId_, label_.c_str(), STR_MASK(deviceId_)); + LOGI("[DataMsgSchedule] DealMsg seqId=%" PRIu32 " finishedPacketId=%" PRIu64 " ok, dev=%s", + expectedSequenceId_, finishedPacketId_, STR_MASK(deviceId_)); expectedSequenceId_++; } } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_packet.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_packet.h index 0f0d5433..18cedc19 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_packet.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_packet.h @@ -31,12 +31,11 @@ using SendDataItem = SingleVerKvEntry *; class DataRequestPacket { public: DataRequestPacket() {}; - virtual ~DataRequestPacket(); + ~DataRequestPacket(); void SetData(std::vector &data); const std::vector &GetData() const; - const std::vector &GetCompressedData() const; void SetCompressData(std::vector &compressData); @@ -160,7 +159,7 @@ protected: class DataAckPacket { public: DataAckPacket() {}; - virtual ~DataAckPacket() {}; + ~DataAckPacket() {}; void SetData(const uint64_t data); @@ -230,7 +229,7 @@ private: class ControlAckPacket { public: ControlAckPacket() {}; - virtual ~ControlAckPacket() {}; + ~ControlAckPacket() {}; void SetPacketHead(int recvCode, uint32_t version, int32_t controlCmd, uint32_t flag); int32_t GetRecvCode() const; uint32_t GetVersion() const; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.cpp index 84f35ce3..22914de3 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.cpp @@ -181,9 +181,11 @@ int SingleVerDataSync::TryContinueSync(SingleVerSyncTaskContext *context, const } if (context->IsQuerySync() && storage_->GetInterfaceType() == ISyncInterface::SYNC_RELATION) { Timestamp dbLastQueryTime = 0; - int errCode = metadata_->GetLastQueryTime(context->GetQuerySyncId(), context->GetDeviceId(), dbLastQueryTime); + int errCode = metadata_->GetLastQueryTime(context->GetQuerySyncId(), context->GetDeviceId(), + context->GetTargetUserId(), dbLastQueryTime); if (errCode == E_OK && dbLastQueryTime < lastQueryTime) { - errCode = metadata_->SetLastQueryTime(context->GetQuerySyncId(), context->GetDeviceId(), lastQueryTime); + errCode = metadata_->SetLastQueryTime(context->GetQuerySyncId(), context->GetDeviceId(), + context->GetTargetUserId(), lastQueryTime); } if (errCode != E_OK) { return errCode; @@ -242,6 +244,7 @@ int SingleVerDataSync::Send(SingleVerSyncTaskContext *context, const Message *me } SendConfig sendConfig; SetSendConfigParam(storage_->GetDbProperties(), context->GetDeviceId(), false, SEND_TIME_OUT, sendConfig); + sendConfig.isRetryTask = context->IsRetryTask(); int errCode = communicateHandle_->SendMessage(context->GetDeviceId(), message, sendConfig, handler); if (errCode != E_OK) { LOGE("[DataSync][Send] send message failed, errCode=%d", errCode); @@ -350,7 +353,7 @@ int SingleVerDataSync::GetUnsyncData(SingleVerSyncTaskContext *context, std::vec GetLocalDeleteSyncWaterMark(context, deletedStartMark); Timestamp lastQueryTimestamp = 0; int errCode = metadata_->GetLastQueryTime(context->GetQuerySyncId(), context->GetDeviceId(), - lastQueryTimestamp); + context->GetTargetUserId(), lastQueryTimestamp); if (errCode != E_OK) { return errCode; } @@ -473,7 +476,7 @@ int SingleVerDataSync::SaveLocalWaterMark(SyncType syncType, const SingleVerSync return E_OK; } } - errCode = metadata_->SaveLocalWaterMark(deviceId, dataTimeRange.endTime); + errCode = metadata_->SaveLocalWaterMark(deviceId, context->GetTargetUserId(), dataTimeRange.endTime); } else { bool isNeedUpdateMark = true; bool isNeedUpdateDeleteMark = true; @@ -490,7 +493,8 @@ int SingleVerDataSync::SaveLocalWaterMark(SyncType syncType, const SingleVerSync } if (isNeedUpdateMark) { LOGD("label=%s,dev=%s,endTime=%" PRIu64, label_.c_str(), STR_MASK(GetDeviceId()), dataTimeRange.endTime); - errCode = metadata_->SetSendQueryWaterMark(queryId, deviceId, dataTimeRange.endTime); + errCode = metadata_->SetSendQueryWaterMark(queryId, deviceId, context->GetTargetUserId(), + dataTimeRange.endTime); if (errCode != E_OK) { LOGE("[DataSync][SaveLocalWaterMark] save query metadata watermark failed,errCode=%d", errCode); return errCode; @@ -499,7 +503,8 @@ int SingleVerDataSync::SaveLocalWaterMark(SyncType syncType, const SingleVerSync if (isNeedUpdateDeleteMark) { LOGD("label=%s,dev=%s,deleteEndTime=%" PRIu64, label_.c_str(), STR_MASK(GetDeviceId()), dataTimeRange.deleteEndTime); - errCode = metadata_->SetSendDeleteSyncWaterMark(context->GetDeleteSyncId(), dataTimeRange.deleteEndTime); + errCode = metadata_->SetSendDeleteSyncWaterMark(context->GetDeleteSyncId(), context->GetTargetUserId(), + dataTimeRange.deleteEndTime); } } if (errCode != E_OK) { @@ -509,34 +514,36 @@ int SingleVerDataSync::SaveLocalWaterMark(SyncType syncType, const SingleVerSync } void SingleVerDataSync::GetPeerWaterMark(SyncType syncType, const std::string &queryIdentify, - const DeviceID &deviceId, WaterMark &waterMark) const + const DeviceID &deviceId, const DeviceID &userId, WaterMark &waterMark) const { if (syncType != SyncType::QUERY_SYNC_TYPE) { - metadata_->GetPeerWaterMark(deviceId, waterMark); + metadata_->GetPeerWaterMark(deviceId, userId, waterMark); return; } - metadata_->GetRecvQueryWaterMark(queryIdentify, deviceId, waterMark); + metadata_->GetRecvQueryWaterMark(queryIdentify, deviceId, userId, waterMark); } -void SingleVerDataSync::GetPeerDeleteSyncWaterMark(const DeviceID &deviceId, WaterMark &waterMark) +void SingleVerDataSync::GetPeerDeleteSyncWaterMark(const DeviceID &deviceId, const DeviceID &userId, + WaterMark &waterMark) { - metadata_->GetRecvDeleteSyncWaterMark(deviceId, waterMark); + metadata_->GetRecvDeleteSyncWaterMark(deviceId, userId, waterMark); } void SingleVerDataSync::GetLocalDeleteSyncWaterMark(const SingleVerSyncTaskContext *context, WaterMark &waterMark) const { - metadata_->GetSendDeleteSyncWaterMark(context->GetDeleteSyncId(), waterMark, context->IsAutoLiftWaterMark()); + metadata_->GetSendDeleteSyncWaterMark(context->GetDeleteSyncId(), context->GetTargetUserId(), waterMark, + context->IsAutoLiftWaterMark()); } void SingleVerDataSync::GetLocalWaterMark(SyncType syncType, const std::string &queryIdentify, const SingleVerSyncTaskContext *context, WaterMark &waterMark) const { if (syncType != SyncType::QUERY_SYNC_TYPE) { - metadata_->GetLocalWaterMark(context->GetDeviceId(), waterMark); + metadata_->GetLocalWaterMark(context->GetDeviceId(), context->GetTargetUserId(), waterMark); return; } - metadata_->GetSendQueryWaterMark(queryIdentify, context->GetDeviceId(), + metadata_->GetSendQueryWaterMark(queryIdentify, context->GetDeviceId(), context->GetTargetUserId(), waterMark, context->IsAutoLiftWaterMark()); } @@ -547,7 +554,7 @@ int SingleVerDataSync::RemoveDeviceDataHandle(SingleVerSyncTaskContext *context, std::lock_guard autoLock(removeDeviceDataLock_); if (context->GetRemoteSoftwareVersion() > SOFTWARE_VERSION_RELEASE_3_0) { uint64_t clearDeviceDataMark = 0; - metadata_->GetRemoveDataMark(context->GetDeviceId(), clearDeviceDataMark); + metadata_->GetRemoveDataMark(context->GetDeviceId(), context->GetTargetUserId(), clearDeviceDataMark); isNeedClearRemoteData = (clearDeviceDataMark == REMOVE_DEVICE_DATA_MARK); } else { const DataRequestPacket *packet = message->GetObject(); @@ -558,7 +565,8 @@ int SingleVerDataSync::RemoveDeviceDataHandle(SingleVerSyncTaskContext *context, SyncType curType = SyncOperation::GetSyncType(packet->GetMode()); WaterMark packetLocalMark = packet->GetLocalWaterMark(); WaterMark peerMark = 0; - GetPeerWaterMark(curType, context->GetQuerySyncId(), context->GetDeviceId(), peerMark); + GetPeerWaterMark(curType, context->GetQuerySyncId(), context->GetDeviceId(), context->GetTargetUserId(), + peerMark); isNeedClearRemoteData = ((packetLocalMark == 0) && (peerMark != 0)); } if (!isNeedClearRemoteData) { @@ -574,11 +582,11 @@ int SingleVerDataSync::RemoveDeviceDataHandle(SingleVerSyncTaskContext *context, } if (context->GetRemoteSoftwareVersion() == SOFTWARE_VERSION_EARLIEST) { // avoid repeat clear in ack - metadata_->SaveLocalWaterMark(context->GetDeviceId(), 0); + metadata_->SaveLocalWaterMark(context->GetDeviceId(), context->GetTargetUserId(), 0); } } if (context->GetRemoteSoftwareVersion() > SOFTWARE_VERSION_RELEASE_3_0) { - errCode = metadata_->ResetMetaDataAfterRemoveData(context->GetDeviceId()); + errCode = metadata_->ResetMetaDataAfterRemoveData(context->GetDeviceId(), context->GetTargetUserId()); if (errCode != E_OK) { (void)SendDataAck(context, message, errCode, maxSendDataTime); return errCode; @@ -595,7 +603,7 @@ int SingleVerDataSync::DealRemoveDeviceDataByAck(SingleVerSyncTaskContext *conte SyncType curType = (context->IsQuerySync()) ? SyncType::QUERY_SYNC_TYPE : SyncType::MANUAL_FULL_SYNC_TYPE; if (context->GetRemoteSoftwareVersion() > SOFTWARE_VERSION_RELEASE_3_0) { uint64_t clearDeviceDataMark = 0; - metadata_->GetRemoveDataMark(context->GetDeviceId(), clearDeviceDataMark); + metadata_->GetRemoveDataMark(context->GetDeviceId(), context->GetTargetUserId(), clearDeviceDataMark); isNeedClearRemoteData = (clearDeviceDataMark != 0); } else if (reserved.empty()) { WaterMark localMark = 0; @@ -604,7 +612,7 @@ int SingleVerDataSync::DealRemoveDeviceDataByAck(SingleVerSyncTaskContext *conte } else { WaterMark peerMark = 0; GetPeerWaterMark(curType, context->GetQuerySyncId(), - context->GetDeviceId(), peerMark); + context->GetDeviceId(), context->GetTargetUserId(), peerMark); isNeedClearRemoteData = ((reserved[ACK_PACKET_RESERVED_INDEX_LOCAL_WATER_MARK] == 0) && (peerMark != 0)); } if (!isNeedClearRemoteData) { @@ -618,7 +626,7 @@ int SingleVerDataSync::DealRemoveDeviceDataByAck(SingleVerSyncTaskContext *conte return errCode; } if (context->GetRemoteSoftwareVersion() > SOFTWARE_VERSION_RELEASE_3_0) { - errCode = metadata_->ResetMetaDataAfterRemoveData(context->GetDeviceId()); + errCode = metadata_->ResetMetaDataAfterRemoveData(context->GetDeviceId(), context->GetTargetUserId()); } return errCode; } @@ -669,7 +677,7 @@ void SingleVerDataSync::FillDataRequestPacket(DataRequestPacket *packet, SingleV (void)storage_->GetCompressionOption(needCompressOnSync, compressionRate); std::string id = context->GetQuerySyncId(); GetLocalWaterMark(curType, id, context, localMark); - GetPeerWaterMark(curType, id, context->GetDeviceId(), peerMark); + GetPeerWaterMark(curType, id, context->GetDeviceId(), context->GetTargetUserId(), peerMark); GetLocalDeleteSyncWaterMark(context, deleteMark); if (((mode != SyncModeType::RESPONSE_PULL && sendCode == E_OK)) || (mode == SyncModeType::RESPONSE_PULL && sendCode == SEND_FINISHED)) { @@ -692,7 +700,7 @@ void SingleVerDataSync::FillDataRequestPacket(DataRequestPacket *packet, SingleV packet->SetQueryId(context->GetQuerySyncId()); CompressAlgorithm curAlgo = context->ChooseCompressAlgo(); // empty compress data should not mark compress - if (!syncData.compressedEntries.empty() && needCompressOnSync && curAlgo != CompressAlgorithm::NONE) { + if (!packet->GetCompressData().empty() && needCompressOnSync && curAlgo != CompressAlgorithm::NONE) { packet->SetCompressDataMark(); packet->SetCompressAlgo(curAlgo); } @@ -802,7 +810,7 @@ int SingleVerDataSync::PullRequestStart(SingleVerSyncTaskContext *context) WaterMark localMark = 0; WaterMark deleteMark = 0; GetPeerWaterMark(syncType, context->GetQuerySyncId(), - context->GetDeviceId(), peerMark); + context->GetDeviceId(), context->GetTargetUserId(), peerMark); GetLocalWaterMark(syncType, context->GetQuerySyncId(), context, localMark); GetLocalDeleteSyncWaterMark(context, deleteMark); uint32_t version = std::min(context->GetRemoteSoftwareVersion(), SOFTWARE_VERSION_CURRENT); @@ -892,11 +900,12 @@ void SingleVerDataSync::UpdatePeerWaterMark(SyncType syncType, const std::string } int errCode = E_OK; if (syncType != SyncType::QUERY_SYNC_TYPE) { - errCode = metadata_->SavePeerWaterMark(context->GetDeviceId(), peerWatermark, true); + errCode = metadata_->SavePeerWaterMark(context->GetDeviceId(), context->GetTargetUserId(), peerWatermark, true); } else { if (peerWatermark != 0) { LOGD("label=%s,dev=%s,endTime=%" PRIu64, label_.c_str(), STR_MASK(GetDeviceId()), peerWatermark); - errCode = metadata_->SetRecvQueryWaterMark(queryId, context->GetDeviceId(), peerWatermark); + errCode = metadata_->SetRecvQueryWaterMark(queryId, context->GetDeviceId(), context->GetTargetUserId(), + peerWatermark); if (errCode != E_OK) { LOGE("[DataSync][UpdatePeerWaterMark] save query peer water mark failed,errCode=%d", errCode); } @@ -904,7 +913,8 @@ void SingleVerDataSync::UpdatePeerWaterMark(SyncType syncType, const std::string if (peerDeletedWatermark != 0) { LOGD("label=%s,dev=%s,peerDeletedTime=%" PRIu64, label_.c_str(), STR_MASK(GetDeviceId()), peerDeletedWatermark); - errCode = metadata_->SetRecvDeleteSyncWaterMark(context->GetDeleteSyncId(), peerDeletedWatermark); + errCode = metadata_->SetRecvDeleteSyncWaterMark(context->GetDeleteSyncId(), context->GetTargetUserId(), + peerDeletedWatermark); } } if (errCode != E_OK) { @@ -1293,7 +1303,7 @@ void SingleVerDataSync::GetPullEndWatermark(const SingleVerSyncTaskContext *cont if ((mode == SyncModeType::PULL) || (mode == SyncModeType::PUSH_AND_PULL)) { WaterMark endMark = packet->GetEndWaterMark(); TimeOffset offset; - metadata_->GetTimeOffset(context->GetDeviceId(), offset); + metadata_->GetTimeOffset(context->GetDeviceId(), context->GetTargetUserId(), offset); pullEndWatermark = endMark - static_cast(offset); LOGD("[DataSync][PullEndWatermark] packetEndMark=%" PRIu64 ",offset=%" PRId64 ",endWaterMark=%" PRIu64 "," "label=%s,dev=%s", endMark, offset, pullEndWatermark, label_.c_str(), STR_MASK(GetDeviceId())); @@ -1542,9 +1552,9 @@ bool SingleVerDataSync::WaterMarkErrHandle(SyncType syncType, SingleVerSyncTaskC WaterMark packetDeletedMark = packet->GetDeletedWaterMark(); WaterMark peerMark = 0; WaterMark deletedMark = 0; - GetPeerWaterMark(syncType, packet->GetQueryId(), context->GetDeviceId(), peerMark); + GetPeerWaterMark(syncType, packet->GetQueryId(), context->GetDeviceId(), context->GetTargetUserId(), peerMark); if (syncType == SyncType::QUERY_SYNC_TYPE) { - GetPeerDeleteSyncWaterMark(context->GetDeleteSyncId(), deletedMark); + GetPeerDeleteSyncWaterMark(context->GetDeleteSyncId(), context->GetTargetUserId(), deletedMark); } if (syncType != SyncType::QUERY_SYNC_TYPE && packetLocalMark > peerMark) { LOGI("[DataSync][DataRequestRecv] packetLocalMark=%" PRIu64 ",current=%" PRIu64, packetLocalMark, peerMark); @@ -1569,7 +1579,7 @@ int SingleVerDataSync::CheckSchemaStrategy(SingleVerSyncTaskContext *context, co if (packet == nullptr) { return -E_INVALID_ARGS; } - if (metadata_->IsAbilitySyncFinish(deviceId_)) { + if (metadata_->IsAbilitySyncFinish(deviceId_, context->GetTargetUserId())) { return E_OK; } auto query = packet->GetQuery(); @@ -1611,16 +1621,16 @@ void SingleVerDataSync::SetAckPacket(DataAckPacket &ackPacket, SingleVerSyncTask WaterMark localMark = 0; GetLocalWaterMark(curType, packet->GetQueryId(), context, localMark); ackPacket.SetRecvCode(recvCode); - UpdateWaterMark isUpdateWaterMark; - SyncTimeRange dataTime = SingleVerDataSyncUtils::GetRecvDataTimeRange( - SyncOperation::GetSyncType(packet->GetMode()), packet->GetData(), isUpdateWaterMark); + WaterMark mark = 0; + GetPeerWaterMark(curType, packet->GetQueryId(), context->GetDeviceId(), context->GetTargetUserId(), mark); + WaterMark deletedPeerMark = 0; + GetPeerDeleteSyncWaterMark(context->GetDeleteSyncId(), context->GetTargetUserId(), deletedPeerMark); + SyncTimeRange dataTime = {.endTime = mark, .deleteEndTime = deletedPeerMark}; bool isPacketWaterLower = false; // send ack packet if ((recvCode == E_OK) && (maxSendDataTime != 0)) { ackPacket.SetData(maxSendDataTime + 1); // + 1 to next start } else if (recvCode != WATER_MARK_INVALID) { - WaterMark mark = 0; - GetPeerWaterMark(curType, packet->GetQueryId(), context->GetDeviceId(), mark); if (recvCode == -E_NEED_ABILITY_SYNC && packet->GetLocalWaterMark() < mark) { LOGI("[DataSync][SetAckPacket] packetLocalMark=%" PRIu64 ",lockMark=%" PRIu64, packet->GetLocalWaterMark(), mark); @@ -1641,8 +1651,6 @@ void SingleVerDataSync::SetAckPacket(DataAckPacket &ackPacket, SingleVerSyncTask } // while recv is not E_OK, data is peerMark, reserve[2] is deletedPeerMark value if (curType == SyncType::QUERY_SYNC_TYPE && recvCode != WATER_MARK_INVALID) { - WaterMark deletedPeerMark; - GetPeerDeleteSyncWaterMark(context->GetDeleteSyncId(), deletedPeerMark); if (recvCode == -E_NEED_ABILITY_SYNC && packet->GetDeletedWaterMark() < deletedPeerMark) { LOGI("[DataSync][SetAckPacket] packetDeletedMark=%" PRIu64 ",deletedMark=%" PRIu64, packet->GetDeletedWaterMark(), deletedPeerMark); @@ -1654,6 +1662,7 @@ void SingleVerDataSync::SetAckPacket(DataAckPacket &ackPacket, SingleVerSyncTask } ackPacket.SetReserved(reserved); ackPacket.SetVersion(version); + UpdateWaterMark isUpdateWaterMark = {true, true}; if (isPacketWaterLower) { UpdatePeerWaterMarkInner(*packet, dataTime, isUpdateWaterMark, context); } @@ -1725,7 +1734,7 @@ int SingleVerDataSync::RemoveDeviceDataIfNeed(SingleVerSyncTaskContext *context) } uint64_t clearRemoteDataMark = 0; std::lock_guard autoLock(removeDeviceDataLock_); - metadata_->GetRemoveDataMark(context->GetDeviceId(), clearRemoteDataMark); + metadata_->GetRemoveDataMark(context->GetDeviceId(), context->GetTargetUserId(), clearRemoteDataMark); if (clearRemoteDataMark == 0) { return E_OK; } @@ -1738,7 +1747,7 @@ int SingleVerDataSync::RemoveDeviceDataIfNeed(SingleVerSyncTaskContext *context) } } if (clearRemoteDataMark == REMOVE_DEVICE_DATA_MARK) { - errCode = metadata_->ResetMetaDataAfterRemoveData(context->GetDeviceId()); + errCode = metadata_->ResetMetaDataAfterRemoveData(context->GetDeviceId(), context->GetTargetUserId()); if (errCode != E_OK) { LOGE("set %s removeDataWaterMark to false failed,errCode=%d", STR_MASK(GetDeviceId()), errCode); return errCode; @@ -1758,7 +1767,7 @@ void SingleVerDataSync::FillRequestReSendPacket(SingleVerSyncTaskContext *contex SingleVerDataSyncUtils::SetDataRequestCommonInfo(*context, *storage_, *packet, metadata_); SyncType curType = (context->IsQuerySync()) ? SyncType::QUERY_SYNC_TYPE : SyncType::MANUAL_FULL_SYNC_TYPE; WaterMark peerMark = 0; - GetPeerWaterMark(curType, context->GetQuerySyncId(), context->GetDeviceId(), + GetPeerWaterMark(curType, context->GetQuerySyncId(), context->GetDeviceId(), context->GetTargetUserId(), peerMark); uint32_t version = std::min(context->GetRemoteSoftwareVersion(), SOFTWARE_VERSION_CURRENT); // transfer reSend mode, RESPONSE_PULL transfer to push or query push @@ -1795,7 +1804,7 @@ void SingleVerDataSync::FillRequestReSendPacket(SingleVerSyncTaskContext *contex uint8_t compressionRate = DBConstant::DEFAULT_COMPTRESS_RATE; (void)storage_->GetCompressionOption(needCompressOnSync, compressionRate); CompressAlgorithm curAlgo = context->ChooseCompressAlgo(); - if (needCompressOnSync && curAlgo != CompressAlgorithm::NONE) { + if (!packet->GetCompressData().empty() && needCompressOnSync && curAlgo != CompressAlgorithm::NONE) { packet->SetCompressDataMark(); packet->SetCompressAlgo(curAlgo); } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.h index 1e07eb1a..ec1279f2 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.h @@ -174,9 +174,9 @@ protected: SyncTimeRange dataTimeRange, bool isCheckBeforUpdate = false) const; void GetPeerWaterMark(SyncType syncType, const std::string &queryIdentify, const DeviceID &deviceId, - WaterMark &waterMark) const; + const DeviceID &userId, WaterMark &waterMark) const; - void GetPeerDeleteSyncWaterMark(const DeviceID &deviceId, WaterMark &waterMark); + void GetPeerDeleteSyncWaterMark(const DeviceID &deviceId, const DeviceID &userId, WaterMark &waterMark); int RemoveDeviceDataHandle(SingleVerSyncTaskContext *context, const Message *message, WaterMark maxSendDataTime); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.cpp index 986d841b..73e33e72 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.cpp @@ -494,7 +494,7 @@ int SingleVerDataSyncUtils::RunPermissionCheckInner(const SingleVerSyncTaskConte } int errCode = RuntimeContext::GetInstance()->RunPermissionCheck(param, flag); if (errCode != E_OK) { - LOGE("[DataSync][RunPermissionCheck] check failed flag=%" PRIu8 ",Label=%s,dev=%s", flag, label.c_str(), + LOGE("[DataSync][RunPermissionCheck] check failed flag=%" PRIu8 ",dev=%s", flag, STR_MASK(context->GetDeviceId())); } return errCode; @@ -536,7 +536,7 @@ void SingleVerDataSyncUtils::SetDataRequestCommonInfo(const SingleVerSyncTaskCon const SyncGenericInterface &storage, DataRequestPacket &packet, std::shared_ptr &metadata) { packet.SetSenderTimeOffset(metadata->GetLocalTimeOffset()); - packet.SetSystemTimeOffset(metadata->GetSystemTimeOffset(context.GetDeviceId())); + packet.SetSystemTimeOffset(metadata->GetSystemTimeOffset(context.GetDeviceId(), context.GetTargetUserId())); if (context.GetRemoteSoftwareVersion() < SOFTWARE_VERSION_RELEASE_9_0) { return; } @@ -564,7 +564,7 @@ int SingleVerDataSyncUtils::SchemaVersionMatchCheck(const SingleVerSyncTaskConte if (context.GetRemoteSoftwareVersion() < SOFTWARE_VERSION_RELEASE_9_0) { return E_OK; } - auto remoteSchemaVersion = metadata->GetRemoteSchemaVersion(context.GetDeviceId()); + auto remoteSchemaVersion = metadata->GetRemoteSchemaVersion(context.GetDeviceId(), context.GetTargetUserId()); if (remoteSchemaVersion != packet.GetSchemaVersion()) { LOGE("[DataSync] remote schema version misMatch, need ability sync again, packet %" PRIu64 " cache %" PRIu64, packet.GetSchemaVersion(), remoteSchemaVersion); @@ -578,7 +578,7 @@ int SingleVerDataSyncUtils::GetUnsyncTotal(const SingleVerSyncTaskContext *conte { SyncTimeRange waterRange; WaterMark startMark = context->GetInitWaterMark(); - if ((waterRange.endTime == 0) || (startMark > waterRange.endTime)) { + if (waterRange.endTime == 0 || startMark > waterRange.endTime) { return E_OK; } @@ -590,8 +590,8 @@ int SingleVerDataSyncUtils::GetUnsyncTotal(const SingleVerSyncTaskContext *conte int SingleVerDataSyncUtils::GetUnsyncTotal(const SingleVerSyncTaskContext *context, const SyncGenericInterface *storage, SyncTimeRange &waterMarkInfo, uint32_t &total) { - int errCode; - SyncType curType = (context->IsQuerySync()) ? SyncType::QUERY_SYNC_TYPE : SyncType::MANUAL_FULL_SYNC_TYPE; + int errCode = E_OK; + SyncType curType = (context->IsQuerySync() ? SyncType::QUERY_SYNC_TYPE : SyncType::MANUAL_FULL_SYNC_TYPE); if (curType != SyncType::QUERY_SYNC_TYPE) { errCode = storage->GetUnSyncTotal(waterMarkInfo.beginTime, waterMarkInfo.endTime, total); } else { @@ -599,7 +599,7 @@ int SingleVerDataSyncUtils::GetUnsyncTotal(const SingleVerSyncTaskContext *conte errCode = storage->GetUnSyncTotal(queryObj, waterMarkInfo, total); } if (errCode != E_OK) { - LOGE("[DataSync][GetUnsyncTotal] Get unsync data num failed,errCode=%d", errCode); + LOGE("[DataSync][GetUnsyncTotal] Get unsync data num failed, errCode=%d", errCode); } return errCode; } @@ -632,7 +632,7 @@ void SingleVerDataSyncUtils::UpdateSyncProcess(SingleVerSyncTaskContext *context void SingleVerDataSyncUtils::CacheInitWaterMark(SingleVerSyncTaskContext *context, SingleVerDataSync *dataSync) { - SyncType curType = (context->IsQuerySync()) ? SyncType::QUERY_SYNC_TYPE : SyncType::MANUAL_FULL_SYNC_TYPE; + SyncType curType = (context->IsQuerySync() ? SyncType::QUERY_SYNC_TYPE : SyncType::MANUAL_FULL_SYNC_TYPE); WaterMark startMark = 0; dataSync->GetLocalWaterMark(curType, context->GetQuerySyncId(), context, startMark); context->SetInitWaterMark(startMark); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_kv_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_kv_syncer.cpp index 31ac7c4b..55070d2d 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_kv_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_kv_syncer.cpp @@ -167,7 +167,7 @@ void SingleVerKVSyncer::RemoteDataChanged(const std::string &device) static_cast(syncEngine_)->PutUnfinishedSubQueries(device, syncQueries); } -int SingleVerKVSyncer::SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, +int SingleVerKVSyncer::SyncConditionCheck(const SyncParam ¶m, const ISyncEngine *engine, ISyncInterface *storage) const { if (!param.isQuerySync) { @@ -203,7 +203,7 @@ void SingleVerKVSyncer::TriggerSubscribe(const std::string &device, const QueryS int retCode = RuntimeContext::GetInstance()->ScheduleTask([this, device, query] { std::vector devices; devices.push_back(device); - SyncParma param; + SyncParam param; param.devices = devices; param.mode = SyncModeType::AUTO_SUBSCRIBE_QUERY; param.onComplete = nullptr; @@ -266,7 +266,8 @@ void SingleVerKVSyncer::TriggerSubQuerySync(const std::vector &devi std::string queryId = query.GetIdentify(); WaterMark queryWaterMark = 0; uint64_t lastTimestamp = metadata->GetQueryLastTimestamp(device, queryId); - errCode = metadata->GetSendQueryWaterMark(queryId, device, queryWaterMark, false); + // Auto sync does not support multi-user sync, The userId param is set to "". + errCode = metadata->GetSendQueryWaterMark(queryId, device, "", queryWaterMark, false); if (errCode != E_OK) { LOGE("[Syncer] get queryId=%s,dev=%s watermark failed", STR_MASK(queryId), STR_MASK(device)); continue; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_kv_syncer.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_kv_syncer.h index f2f6ca27..9c8c435f 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_kv_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_kv_syncer.h @@ -38,7 +38,7 @@ public: SyncerBasicInfo DumpSyncerBasicInfo() override; protected: - int SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, ISyncInterface *storage) const override; + int SyncConditionCheck(const SyncParam ¶m, const ISyncEngine *engine, ISyncInterface *storage) const override; // Init the Sync engine int InitSyncEngine(ISyncInterface *syncInterface) override; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_relational_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_relational_syncer.cpp index e392bb45..402cef51 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_relational_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_relational_syncer.cpp @@ -30,7 +30,7 @@ int SingleVerRelationalSyncer::Initialize(ISyncInterface *syncInterface, bool is RegisterSchemaChangedCallback(callback); } -int SingleVerRelationalSyncer::Sync(const SyncParma ¶m, uint64_t connectionId) +int SingleVerRelationalSyncer::Sync(const SyncParam ¶m, uint64_t connectionId) { int errCode = QuerySyncPreCheck(param); if (errCode != E_OK) { @@ -39,7 +39,7 @@ int SingleVerRelationalSyncer::Sync(const SyncParma ¶m, uint64_t connectionI return GenericSyncer::Sync(param, connectionId); } -int SingleVerRelationalSyncer::PrepareSync(const SyncParma ¶m, uint32_t syncId, uint64_t connectionId) +int SingleVerRelationalSyncer::PrepareSync(const SyncParam ¶m, uint32_t syncId, uint64_t connectionId) { if (syncInterface_ == nullptr) { LOGE("[SingleVerRelationalSyncer] [PrepareSync] syncInterface_ is nullptr."); @@ -71,10 +71,10 @@ int SingleVerRelationalSyncer::PrepareSync(const SyncParma ¶m, uint32_t sync return E_OK; } -int SingleVerRelationalSyncer::GenerateEachSyncTask(const SyncParma ¶m, uint32_t syncId, +int SingleVerRelationalSyncer::GenerateEachSyncTask(const SyncParam ¶m, uint32_t syncId, const std::vector &tablesQuery, uint64_t connectionId, std::set &subSyncIdSet) { - SyncParma subParam = param; + SyncParam subParam = param; subParam.isQuerySync = true; int errCode = E_OK; for (const QuerySyncObject &table : tablesQuery) { @@ -103,7 +103,7 @@ int SingleVerRelationalSyncer::GenerateEachSyncTask(const SyncParma ¶m, uint } void SingleVerRelationalSyncer::DoOnSubSyncComplete(const uint32_t subSyncId, const uint32_t syncId, - const SyncParma ¶m, const std::map &devicesMap) + const SyncParam ¶m, const std::map &devicesMap) { bool allFinish = true; { @@ -133,7 +133,7 @@ void SingleVerRelationalSyncer::DoRollBack(std::set &subSyncIdSet) } } -void SingleVerRelationalSyncer::DoOnComplete(const SyncParma ¶m, uint32_t syncId) +void SingleVerRelationalSyncer::DoOnComplete(const SyncParam ¶m, uint32_t syncId) { if (!param.relationOnComplete) { return; @@ -180,7 +180,7 @@ void SingleVerRelationalSyncer::SchemaChangeCallback() } } -int SingleVerRelationalSyncer::SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, +int SingleVerRelationalSyncer::SyncConditionCheck(const SyncParam ¶m, const ISyncEngine *engine, ISyncInterface *storage) const { if (!param.isQuerySync) { @@ -217,7 +217,7 @@ int SingleVerRelationalSyncer::SyncConditionCheck(const SyncParma ¶m, const return E_OK; } -int SingleVerRelationalSyncer::QuerySyncPreCheck(const SyncParma ¶m) const +int SingleVerRelationalSyncer::QuerySyncPreCheck(const SyncParam ¶m) const { if (!param.isQuerySync) { return E_OK; @@ -237,7 +237,7 @@ int SingleVerRelationalSyncer::QuerySyncPreCheck(const SyncParma ¶m) const return E_OK; } -std::vector SingleVerRelationalSyncer::GetQuerySyncObject(const SyncParma ¶m) +std::vector SingleVerRelationalSyncer::GetQuerySyncObject(const SyncParam ¶m) { std::vector res; auto tables = param.syncQuery.GetRelationTableNames(); @@ -250,5 +250,22 @@ std::vector SingleVerRelationalSyncer::GetQuerySyncObject(const } return res; } + +int32_t SingleVerRelationalSyncer::GetTaskCount() +{ + int32_t count = GenericSyncer::GetTaskCount(); + ISyncEngine *syncEngine = nullptr; + { + std::lock_guard lock(syncerLock_); + if (syncEngine_ == nullptr) { + return count; + } + syncEngine = syncEngine_; + RefObject::IncObjRef(syncEngine); + } + count += syncEngine->GetRemoteQueryTaskCount(); + RefObject::DecObjRef(syncEngine); + return count; +} } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_relational_syncer.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_relational_syncer.h index df637af8..9b0fc38d 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_relational_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_relational_syncer.h @@ -24,35 +24,36 @@ public: int Initialize(ISyncInterface *syncInterface, bool isNeedActive) override; - // Sync function. use SyncParma to reduce parameter. - int Sync(const SyncParma ¶m, uint64_t connectionId) override; + // Sync function. use SyncParam to reduce parameter. + int Sync(const SyncParam ¶m, uint64_t connectionId) override; void EnableAutoSync(bool enable) override; void LocalDataChanged(int notifyEvent) override; + int32_t GetTaskCount() override; protected: - int PrepareSync(const SyncParma ¶m, uint32_t syncId, uint64_t connectionId) override; + int PrepareSync(const SyncParam ¶m, uint32_t syncId, uint64_t connectionId) override; - int SyncConditionCheck(const SyncParma ¶m, const ISyncEngine *engine, ISyncInterface *storage) const override; + int SyncConditionCheck(const SyncParam ¶m, const ISyncEngine *engine, ISyncInterface *storage) const override; private: - int GenerateEachSyncTask(const SyncParma ¶m, uint32_t syncId, + int GenerateEachSyncTask(const SyncParam ¶m, uint32_t syncId, const std::vector &tablesQuery, uint64_t connectionId, std::set &subSyncIdSet); void DoRollBack(std::set &subSyncIdSet); - void DoOnComplete(const SyncParma ¶m, uint32_t syncId); + void DoOnComplete(const SyncParam ¶m, uint32_t syncId); void DoOnSubSyncComplete(const uint32_t subSyncId, const uint32_t syncId, - const SyncParma ¶m, const std::map &devicesMap); + const SyncParam ¶m, const std::map &devicesMap); void SchemaChangeCallback(); - int QuerySyncPreCheck(const SyncParma ¶m) const; + int QuerySyncPreCheck(const SyncParam ¶m) const; - static std::vector GetQuerySyncObject(const SyncParma ¶m); + static std::vector GetQuerySyncObject(const SyncParam ¶m); mutable std::mutex syncMapLock_; std::map> fullSyncIdMap_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_engine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_engine.cpp index c5254c5a..a27883b7 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_engine.cpp @@ -63,7 +63,7 @@ void SingleVerSyncEngine::EnableClearRemoteStaleData(bool enable) int SingleVerSyncEngine::StartAutoSubscribeTimer(const ISyncInterface &syncInterface) { if (syncInterface.IsSupportSubscribe() == -E_NOT_SUPPORT) { - LOGI("[StartAutoSubscribeTimer] no need to start subscribe timer"); + LOGI("[StartAutoSubscribeTimer] no need start"); return E_OK; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.cpp index 205ca3da..c5122a6c 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.cpp @@ -49,6 +49,7 @@ namespace { {State::TIME_SYNC, Event::TIME_SYNC_FINISHED_EVENT, State::ABILITY_SYNC}, {State::TIME_SYNC, Event::TIME_OUT_EVENT, State::SYNC_TIME_OUT}, {State::TIME_SYNC, Event::INNER_ERR_EVENT, State::INNER_ERR}, + {State::TIME_SYNC, Event::NEED_RESYNC_EVENT, State::TIME_SYNC}, // In ABILITY_SYNC state, compare version num and schema {State::ABILITY_SYNC, Event::VERSION_NOT_SUPPOR_EVENT, State::INNER_ERR}, @@ -56,6 +57,7 @@ namespace { {State::ABILITY_SYNC, Event::TIME_OUT_EVENT, State::SYNC_TIME_OUT}, {State::ABILITY_SYNC, Event::INNER_ERR_EVENT, State::INNER_ERR}, {State::ABILITY_SYNC, Event::CONTROL_CMD_EVENT, State::SYNC_CONTROL_CMD}, + {State::ABILITY_SYNC, Event::NEED_RESYNC_EVENT, State::ABILITY_SYNC}, // In START_INITIACTIVE_DATA_SYNC state, send a sync request, and send first packt of data sync {State::START_INITIACTIVE_DATA_SYNC, Event::NEED_ABILITY_SYNC_EVENT, State::ABILITY_SYNC}, @@ -64,6 +66,7 @@ namespace { {State::START_INITIACTIVE_DATA_SYNC, Event::SEND_FINISHED_EVENT, State::START_PASSIVE_DATA_SYNC}, {State::START_INITIACTIVE_DATA_SYNC, Event::RE_SEND_DATA_EVENT, State::START_INITIACTIVE_DATA_SYNC}, {State::START_INITIACTIVE_DATA_SYNC, Event::NEED_TIME_SYNC_EVENT, State::TIME_SYNC}, + {State::START_INITIACTIVE_DATA_SYNC, Event::NEED_RESYNC_EVENT, State::START_INITIACTIVE_DATA_SYNC}, // In START_PASSIVE_DATA_SYNC state, do response pull request, and send first packt of data sync {State::START_PASSIVE_DATA_SYNC, Event::SEND_FINISHED_EVENT, State::START_PASSIVE_DATA_SYNC}, @@ -73,6 +76,7 @@ namespace { {State::START_PASSIVE_DATA_SYNC, Event::NEED_ABILITY_SYNC_EVENT, State::ABILITY_SYNC}, {State::START_PASSIVE_DATA_SYNC, Event::RE_SEND_DATA_EVENT, State::START_PASSIVE_DATA_SYNC}, {State::START_PASSIVE_DATA_SYNC, Event::NEED_TIME_SYNC_EVENT, State::TIME_SYNC}, + {State::START_PASSIVE_DATA_SYNC, Event::NEED_RESYNC_EVENT, State::START_PASSIVE_DATA_SYNC}, // In WAIT_FOR_RECEIVE_DATA_FINISH, {State::WAIT_FOR_RECEIVE_DATA_FINISH, Event::RECV_FINISHED_EVENT, State::SYNC_TASK_FINISHED}, @@ -80,11 +84,13 @@ namespace { {State::WAIT_FOR_RECEIVE_DATA_FINISH, Event::TIME_OUT_EVENT, State::SYNC_TIME_OUT}, {State::WAIT_FOR_RECEIVE_DATA_FINISH, Event::INNER_ERR_EVENT, State::INNER_ERR}, {State::WAIT_FOR_RECEIVE_DATA_FINISH, Event::NEED_ABILITY_SYNC_EVENT, State::ABILITY_SYNC}, + {State::WAIT_FOR_RECEIVE_DATA_FINISH, Event::NEED_RESYNC_EVENT, State::START_PASSIVE_DATA_SYNC}, {State::SYNC_CONTROL_CMD, Event::SEND_FINISHED_EVENT, State::SYNC_TASK_FINISHED}, {State::SYNC_CONTROL_CMD, Event::TIME_OUT_EVENT, State::SYNC_TIME_OUT}, {State::SYNC_CONTROL_CMD, Event::INNER_ERR_EVENT, State::INNER_ERR}, {State::SYNC_CONTROL_CMD, Event::NEED_ABILITY_SYNC_EVENT, State::ABILITY_SYNC}, + {State::SYNC_CONTROL_CMD, Event::NEED_RESYNC_EVENT, State::SYNC_CONTROL_CMD}, // In SYNC_TASK_FINISHED, {State::SYNC_TASK_FINISHED, Event::ALL_TASK_FINISHED_EVENT, State::IDLE}, @@ -138,7 +144,8 @@ int SingleVerSyncStateMachine::Initialize(ISyncTaskContext *context, ISyncInterf return -E_OUT_OF_MEMORY; } - errCode = timeSync_->Initialize(communicator, metaData, syncInterface, context->GetDeviceId()); + errCode = timeSync_->Initialize(communicator, metaData, syncInterface, context->GetDeviceId(), + context->GetTargetUserId()); if (errCode != E_OK) { goto ERROR_OUT; } @@ -184,6 +191,10 @@ int SingleVerSyncStateMachine::ReceiveMessageCallback(Message *inMsg) LOGE("[StateMachine] message pre check failed"); return errCode; } + if (context_->IsNeedRetrySync(inMsg->GetErrorNo(), inMsg->GetMessageType())) { + SwitchStateAndStep(NEED_RESYNC_EVENT); + return E_OK; + } switch (inMsg->GetMessageId()) { case TIME_SYNC_MESSAGE: errCode = TimeMarkSyncRecv(inMsg); @@ -482,7 +493,7 @@ Event SingleVerSyncStateMachine::DoTimeSync() const SyncTaskContext::CommErrHandlerFunc(ret, context, requestSessionId, isDirectEnd); }; } - int errCode = timeSync_->SyncStart(handler, context_->GetRequestSessionId()); + int errCode = timeSync_->SyncStart(handler, context_->GetRequestSessionId(), context_->IsRetryTask()); if (errCode == E_OK) { return Event::WAIT_ACK_EVENT; } @@ -537,6 +548,7 @@ Event SingleVerSyncStateMachine::GetEventAfterTimeSync(int mode) const Event SingleVerSyncStateMachine::DoSyncTaskFinished() { StopWatchDog(); + context_->ResetResyncTimes(); if (dataSync_ == nullptr || communicator_ == nullptr || syncContext_ == nullptr) { LOGE("[SingleVerSyncStateMachine] [DoSyncTaskFinished] dataSync_ or communicator_ or syncContext_ is nullptr."); return TransformErrCodeToEvent(-E_OUT_OF_MEMORY); @@ -882,7 +894,8 @@ int SingleVerSyncStateMachine::GetSyncOperationStatus(int errCode) const { -E_DENIED_SQL, SyncOperation::OP_DENIED_SQL }, { -E_REMOTE_OVER_SIZE, SyncOperation::OP_MAX_LIMITS }, { -E_INVALID_PASSWD_OR_CORRUPTED_DB, SyncOperation::OP_NOTADB_OR_CORRUPTED }, - { -E_DISTRIBUTED_SCHEMA_NOT_FOUND, SyncOperation::OP_SCHEMA_INCOMPATIBLE } + { -E_DISTRIBUTED_SCHEMA_NOT_FOUND, SyncOperation::OP_SCHEMA_INCOMPATIBLE }, + { -E_FEEDBACK_DB_CLOSING, SyncOperation::OP_DB_CLOSING }, }; const auto &result = std::find_if(std::begin(stateNodes), std::end(stateNodes), [errCode](const auto &node) { return node.errCode == errCode; @@ -1244,15 +1257,15 @@ void SingleVerSyncStateMachine::ControlAckRecvErrCodeHandle(int errCode) } } -void SingleVerSyncStateMachine::GetLocalWaterMark(const DeviceID &deviceId, uint64_t &outValue) +void SingleVerSyncStateMachine::GetLocalWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue) { - metadata_->GetLocalWaterMark(deviceId, outValue); + metadata_->GetLocalWaterMark(deviceId, userId, outValue); } -int SingleVerSyncStateMachine::GetSendQueryWaterMark(const std::string &queryId, const DeviceID &deviceId, - bool isAutoLift, uint64_t &outValue) +int SingleVerSyncStateMachine::GetSendQueryWaterMark(const std::string &queryId, const DeviceID &deviceId, + const DeviceID &userId, bool isAutoLift, uint64_t &outValue) { - return metadata_->GetSendQueryWaterMark(queryId, deviceId, outValue, isAutoLift); + return metadata_->GetSendQueryWaterMark(queryId, deviceId, userId, outValue, isAutoLift); } void SingleVerSyncStateMachine::ResponsePullError(int errCode, bool ignoreInnerErr) diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.h index f026d976..23d6c9f1 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.h @@ -67,6 +67,7 @@ public: RE_SEND_DATA_EVENT, CONTROL_CMD_EVENT, NEED_TIME_SYNC_EVENT, + NEED_RESYNC_EVENT, ANY_EVENT }; SingleVerSyncStateMachine(); @@ -92,10 +93,10 @@ public: bool IsNeedTriggerQueryAutoSync(Message *inMsg, QuerySyncObject &query) override; - void GetLocalWaterMark(const DeviceID &deviceId, uint64_t &outValue); + void GetLocalWaterMark(const DeviceID &deviceId, const DeviceID &userId, uint64_t &outValue); - int GetSendQueryWaterMark(const std::string &queryId, const DeviceID &deviceId, bool isAutoLift, - uint64_t &outValue); + int GetSendQueryWaterMark(const std::string &queryId, const DeviceID &deviceId, const DeviceID &userId, + bool isAutoLift, uint64_t &outValue); void InnerErrorAbort(uint32_t sessionId) override; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.cpp index 9ef63989..3279bf16 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.cpp @@ -39,10 +39,10 @@ SingleVerSyncTaskContext::~SingleVerSyncTaskContext() subManager_ = nullptr; } -int SingleVerSyncTaskContext::Initialize(const std::string &deviceId, ISyncInterface *syncInterface, +int SingleVerSyncTaskContext::Initialize(const DeviceSyncTarget &target, ISyncInterface *syncInterface, const std::shared_ptr &metadata, ICommunicator *communicator) { - if (deviceId.empty() || syncInterface == nullptr || metadata == nullptr || + if (target.device.empty() || syncInterface == nullptr || metadata == nullptr || communicator == nullptr) { LOGE("[SingleVerSyncTaskContext] [Initialize] parameter is invalid."); return -E_INVALID_ARGS; @@ -52,7 +52,8 @@ int SingleVerSyncTaskContext::Initialize(const std::string &deviceId, ISyncInter LOGE("[SingleVerSyncTaskContext] [Initialize] stateMachine_ is nullptr."); return -E_OUT_OF_MEMORY; } - deviceId_ = deviceId; + deviceId_ = target.device; + targetUserId_ = target.userId; std::vector dbIdentifier = syncInterface->GetIdentifier(); dbIdentifier.resize(3); // only show 3 bytes syncActionName_ = DBDfxAdapter::SYNC_ACTION + "_" + @@ -518,14 +519,14 @@ int SingleVerSyncTaskContext::GetCorrectedSendWaterMarkForCurrentTask(const Sync if (operation != nullptr && operation->IsQuerySync()) { LOGD("Is QuerySync"); int errCode = static_cast(stateMachine_)->GetSendQueryWaterMark( - operation->GetQueryId(), deviceId_, + operation->GetQueryId(), deviceId_, targetUserId_, lastFullSyncTaskStatus_ == SyncOperation::OP_FINISHED_ALL, waterMark); if (errCode != E_OK) { return errCode; } } else { LOGD("Not QuerySync"); - static_cast(stateMachine_)->GetLocalWaterMark(deviceId_, waterMark); + static_cast(stateMachine_)->GetLocalWaterMark(deviceId_, targetUserId_, waterMark); } return E_OK; } @@ -644,4 +645,30 @@ int32_t SingleVerSyncTaskContext::GetResponseTaskCount() } return taskCount; } + +bool SingleVerSyncTaskContext::IsNeedRetrySync(int errNo, uint16_t messageType) +{ + if (errNo != E_FEEDBACK_DB_CLOSING || messageType != TYPE_RESPONSE) { + return false; + } + uint32_t cur = ++resyncTimes_; + LOGI("[IsNeedRetrySync]%u", cur); + return cur <= MANUAL_RETRY_TIMES; +} + +void SingleVerSyncTaskContext::ResetResyncTimes() +{ + resyncTimes_ = 0; +} + +bool SingleVerSyncTaskContext::IsRetryTask() const +{ + SyncOperation *operation = GetAndIncSyncOperation(); + if (operation == nullptr) { + return true; + } + bool isRetryTask = operation->IsRetryTask(); + RefObject::DecObjRef(operation); + return isRetryTask; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.h index 0cb30f51..cf4b89c5 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.h @@ -40,7 +40,7 @@ public: DISABLE_COPY_ASSIGN_MOVE(SingleVerSyncTaskContext); // Init SingleVerSyncTaskContext - int Initialize(const std::string &deviceId, ISyncInterface *syncInterface, + int Initialize(const DeviceSyncTarget &target, ISyncInterface *syncInterface, const std::shared_ptr &metadata, ICommunicator *communicator) override; // Add a sync task target with the operation to the queue @@ -147,6 +147,10 @@ public: int32_t GetResponseTaskCount() override; + bool IsNeedRetrySync(int errNo, uint16_t messageType); + void ResetResyncTimes(); + + bool IsRetryTask() const override; protected: ~SingleVerSyncTaskContext() override; void CopyTargetData(const ISyncTarget *target, const TaskParam &taskParam) override; @@ -167,7 +171,7 @@ private: ContinueToken token_; WaterMark endMark_; - volatile uint32_t responseSessionId_ = 0; + std::atomic responseSessionId_ = 0; bool needClearRemoteStaleData_; mutable std::mutex securityOptionMutex_; @@ -191,6 +195,8 @@ private: // Initial Water Mark when the sync task launched. WaterMark initWaterMark_ = 0; WaterMark initDeletedMark_ = 0; + + std::atomic resyncTimes_ = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_syncer.cpp index 322f2dca..b7e63c90 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_syncer.cpp @@ -66,7 +66,7 @@ int SingleVerSyncer::EraseDeviceWaterMark(const std::string &deviceId, bool isNe storage = syncInterface_; storage->IncRefCount(); } - int errCode = metadata->EraseDeviceWaterMark(deviceId, isNeedHash, tableName); + int errCode = metadata->EraseDeviceWaterMark(deviceId, "", isNeedHash, tableName); storage->DecRefCount(); return errCode; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.cpp index 5d4a60e5..6cf1d614 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.cpp @@ -101,13 +101,13 @@ int SyncEngine::Initialize(ISyncInterface *syncInterface, const std::shared_ptr< } metadata_ = metadata; isActive_ = true; - LOGI("[SyncEngine] Engine [%s] init ok", label_.c_str()); + LOGI("[SyncEngine] Engine [%.3s] init ok", label_.c_str()); return E_OK; } int SyncEngine::Close() { - LOGI("[SyncEngine] SyncEngine [%s] close enter!", label_.c_str()); + LOGI("[SyncEngine] [%.3s] close enter!", label_.c_str()); isActive_ = false; UnRegCommunicatorsCallback(); StopAutoSubscribeTimer(); @@ -152,7 +152,7 @@ int SyncEngine::Close() executor = nullptr; } ClearInnerResource(); - LOGI("[SyncEngine] SyncEngine [%s] closed!", label_.c_str()); + LOGI("[SyncEngine] [%.3s] closed!", label_.c_str()); return E_OK; } @@ -296,12 +296,8 @@ int SyncEngine::InitComunicator(const ISyncInterface *syncInterface) return errCode; } - errCode = communicator_->RegOnMessageCallback( - [this](const std::string &targetDev, Message *inMsg) { MessageReciveCallback(targetDev, inMsg); }, []() {}); + errCode = RegCallbackOnInitComunicator(communicatorAggregator, syncInterface); if (errCode != E_OK) { - LOGE("[SyncEngine] SyncRequestCallback register failed! err = %d", errCode); - communicatorAggregator->ReleaseCommunicator(communicator_, GetUserId(syncInterface)); - communicator_ = nullptr; return errCode; } { @@ -322,14 +318,23 @@ int SyncEngine::InitComunicator(const ISyncInterface *syncInterface) int SyncEngine::AddSyncOperForContext(const std::string &deviceId, SyncOperation *operation) { + if (syncInterface_ == nullptr) { + LOGE("[SyncEngine][AddSyncOperForContext] sync interface has not initialized"); + return -E_INVALID_DB; + } + bool isSyncDualTupleMode = syncInterface_->GetDbProperties().GetBoolProp(DBProperties::SYNC_DUAL_TUPLE_MODE, false); + std::string targetUserId = DBConstant::DEFAULT_USER; + if (isSyncDualTupleMode) { + targetUserId = GetTargetUserId(deviceId); + } int errCode = E_OK; ISyncTaskContext *context = nullptr; { std::lock_guard lock(contextMapLock_); - context = FindSyncTaskContext(deviceId); + context = FindSyncTaskContext({deviceId, targetUserId}); if (context == nullptr) { if (!IsKilled()) { - context = GetSyncTaskContext(deviceId, errCode); + context = GetSyncTaskContext({deviceId, targetUserId}, errCode); } if (context == nullptr) { return errCode; @@ -417,7 +422,7 @@ int SyncEngine::DealMsgUtilQueueEmpty() // it will deal with the first message in queue, we should increase object reference counts and sure that resources // could be prevented from destroying by other threads. do { - ISyncTaskContext *nextContext = GetContextForMsg(inMsg->GetTarget(), errCode); + ISyncTaskContext *nextContext = GetContextForMsg({inMsg->GetTarget(), inMsg->GetSenderUserId()}, errCode); if (errCode != E_OK) { break; } @@ -434,12 +439,12 @@ int SyncEngine::DealMsgUtilQueueEmpty() return errCode; } -ISyncTaskContext *SyncEngine::GetContextForMsg(const std::string &targetDev, int &errCode) +ISyncTaskContext *SyncEngine::GetContextForMsg(const DeviceSyncTarget &target, int &errCode) { ISyncTaskContext *context = nullptr; { std::lock_guard lock(contextMapLock_); - context = FindSyncTaskContext(targetDev); + context = FindSyncTaskContext(target); if (context != nullptr) { // LCOV_EXCL_BR_LINE if (context->IsKilled()) { errCode = -E_OBJ_IS_KILLED; @@ -450,7 +455,7 @@ ISyncTaskContext *SyncEngine::GetContextForMsg(const std::string &targetDev, int errCode = -E_OBJ_IS_KILLED; return nullptr; } - context = GetSyncTaskContext(targetDev, errCode); + context = GetSyncTaskContext(target, errCode); if (context == nullptr) { return nullptr; } @@ -490,7 +495,7 @@ int SyncEngine::ScheduleDealMsg(ISyncTaskContext *context, Message *inMsg) return errCode; } -void SyncEngine::MessageReciveCallback(const std::string &targetDev, Message *inMsg) +int SyncEngine::MessageReciveCallback(const std::string &targetDev, Message *inMsg) { IncExecTaskCount(); int errCode = MessageReciveCallbackInner(targetDev, inMsg); @@ -502,6 +507,7 @@ void SyncEngine::MessageReciveCallback(const std::string &targetDev, Message *in DecExecTaskCount(); LOGE("[SyncEngine] MessageReciveCallback failed!"); } + return errCode; } int SyncEngine::MessageReciveCallbackInner(const std::string &targetDev, Message *inMsg) @@ -514,6 +520,9 @@ int SyncEngine::MessageReciveCallbackInner(const std::string &targetDev, Message LOGE("[SyncEngine] engine is closing, ignore msg"); return -E_BUSY; } + if (inMsg->GetMessageType() == TYPE_REQUEST && ExchangeClosePending(false)) { + return -E_FEEDBACK_DB_CLOSING; + } if (inMsg->GetMessageId() == REMOTE_EXECUTE_MESSAGE) { return HandleRemoteExecutorMsg(targetDev, inMsg); } @@ -535,7 +544,7 @@ int SyncEngine::MessageReciveCallbackInner(const std::string &targetDev, Message return -E_BUSY; } - if (execTaskCount_ > MAX_EXEC_NUM) { + if (GetExecTaskCount() > MAX_EXEC_NUM) { PutMsgIntoQueue(targetDev, inMsg, msgSize); // task dont exec here DecExecTaskCount(); @@ -544,7 +553,7 @@ int SyncEngine::MessageReciveCallbackInner(const std::string &targetDev, Message } int errCode = E_OK; - ISyncTaskContext *nextContext = GetContextForMsg(targetDev, errCode); + ISyncTaskContext *nextContext = GetContextForMsg({targetDev, inMsg->GetSenderUserId()}, errCode); if (errCode != E_OK) { return errCode; } @@ -598,9 +607,16 @@ int SyncEngine::GetMsgSize(const Message *inMsg) const } } -ISyncTaskContext *SyncEngine::FindSyncTaskContext(const std::string &deviceId) +ISyncTaskContext *SyncEngine::FindSyncTaskContext(const DeviceSyncTarget &target) { - auto iter = syncTaskContextMap_.find(deviceId); + if (target.userId == DBConstant::DEFAULT_USER) { + for (auto &[key, value] : syncTaskContextMap_) { + if (key.device == target.device) { + return value; + } + } + } + auto iter = syncTaskContextMap_.find(target); if (iter != syncTaskContextMap_.end()) { ISyncTaskContext *context = iter->second; return context; @@ -608,24 +624,30 @@ ISyncTaskContext *SyncEngine::FindSyncTaskContext(const std::string &deviceId) return nullptr; } -ISyncTaskContext *SyncEngine::GetSyncTaskContextAndInc(const std::string &deviceId) +std::vector SyncEngine::GetSyncTaskContextAndInc(const std::string &deviceId) { - ISyncTaskContext *context = nullptr; + std::vector contexts; std::lock_guard lock(contextMapLock_); - context = FindSyncTaskContext(deviceId); - if (context == nullptr) { - LOGI("[SyncEngine] dev=%s, context is null, no need to clear sync operation", STR_MASK(deviceId)); - return nullptr; - } - if (context->IsKilled()) { // LCOV_EXCL_BR_LINE - LOGI("[SyncEngine] context is killing"); - return nullptr; + for (const auto &iter : syncTaskContextMap_) { + if (iter.first.device != deviceId) { + continue; + } + if (iter.second == nullptr) { + LOGI("[SyncEngine] dev=%s, user=%s, context is null, no need to clear sync operation", STR_MASK(deviceId), + iter.first.userId.c_str()); + continue; + } + if (iter.second->IsKilled()) { // LCOV_EXCL_BR_LINE + LOGI("[SyncEngine] context is killing"); + continue; + } + RefObject::IncObjRef(iter.second); + contexts.push_back(iter.second); } - RefObject::IncObjRef(context); - return context; + return contexts; } -ISyncTaskContext *SyncEngine::GetSyncTaskContext(const std::string &deviceId, int &errCode) +ISyncTaskContext *SyncEngine::GetSyncTaskContext(const DeviceSyncTarget &target, int &errCode) { auto storage = GetAndIncSyncInterface(); if (storage == nullptr) { @@ -639,19 +661,19 @@ ISyncTaskContext *SyncEngine::GetSyncTaskContext(const std::string &deviceId, in LOGE("[SyncEngine] SyncTaskContext alloc failed, may be no memory available!"); return nullptr; } - errCode = context->Initialize(deviceId, storage, metadata_, communicatorProxy_); + errCode = context->Initialize(target, storage, metadata_, communicatorProxy_); if (errCode != E_OK) { - LOGE("[SyncEngine] context init failed err %d, dev %s", errCode, STR_MASK(deviceId)); + LOGE("[SyncEngine] context init failed err %d, dev %s", errCode, STR_MASK(target.device)); RefObject::DecObjRef(context); storage->DecRefCount(); context = nullptr; return nullptr; } - syncTaskContextMap_.insert(std::pair(deviceId, context)); + syncTaskContextMap_.insert(std::pair(target, context)); // IncRef for SyncEngine to make sure SyncEngine is valid when context access RefObject::IncObjRef(this); - context->OnLastRef([this, deviceId, storage]() { - LOGD("[SyncEngine] SyncTaskContext for id %s finalized", STR_MASK(deviceId)); + context->OnLastRef([this, target, storage]() { + LOGD("[SyncEngine] SyncTaskContext for id %s finalized", STR_MASK(target.device)); RefObject::DecObjRef(this); storage->DecRefCount(); }); @@ -859,8 +881,6 @@ void SyncEngine::OfflineHandleByDevice(const std::string &deviceId, ISyncInterfa DBInfo dbInfo; static_cast(storage)->GetDBInfo(dbInfo); RuntimeContext::GetInstance()->RemoveRemoteSubscribe(dbInfo, deviceId); - // get context and Inc context if context is not nullptr - ISyncTaskContext *context = GetSyncTaskContextAndInc(deviceId); { std::lock_guard lock(communicatorProxyLock_); if (communicatorProxy_ == nullptr) { @@ -868,25 +888,30 @@ void SyncEngine::OfflineHandleByDevice(const std::string &deviceId, ISyncInterfa } if (communicatorProxy_->IsDeviceOnline(deviceId)) { // LCOV_EXCL_BR_LINE LOGI("[SyncEngine] target dev=%s is online, no need to clear task.", STR_MASK(deviceId)); - RefObject::DecObjRef(context); return; } } // means device is offline, clear local subscribe - subManager_->ClearLocalSubscribeQuery(deviceId); - // clear sync task - if (context != nullptr) { - context->ClearAllSyncTask(); - RefObject::DecObjRef(context); + // get context and Inc context if context is not nullptr + std::vector contexts = GetSyncTaskContextAndInc(deviceId); + for (const auto &context : contexts) { + subManager_->ClearLocalSubscribeQuery(deviceId); + // clear sync task + if (context != nullptr) { + context->ClearAllSyncTask(); + RefObject::DecObjRef(context); + } } } void SyncEngine::ClearAllSyncTaskByDevice(const std::string &deviceId) { - ISyncTaskContext *context = GetSyncTaskContextAndInc(deviceId); - if (context != nullptr) { - context->ClearAllSyncTask(); - RefObject::DecObjRef(context); + std::vector contexts = GetSyncTaskContextAndInc(deviceId); + for (const auto &context : contexts) { + if (context != nullptr) { + context->ClearAllSyncTask(); + RefObject::DecObjRef(context); + } } } @@ -932,7 +957,9 @@ ICommunicator *SyncEngine::AllocCommunicator(const std::string &identifier, int } errCode = communicator->RegOnMessageCallback( - [this](const std::string &targetDev, Message *inMsg) { MessageReciveCallback(targetDev, inMsg); }, []() {}); + [this](const std::string &targetDev, Message *inMsg) { + return MessageReciveCallback(targetDev, inMsg); + }, []() {}); if (errCode != E_OK) { LOGE("[SyncEngine] SyncRequestCallback register failed in SetEqualIdentifier! err = %d", errCode); communicatorAggregator->ReleaseCommunicator(communicator, userId); @@ -1095,6 +1122,12 @@ void SyncEngine::DecExecTaskCount() execTaskCv_.notify_all(); } +uint32_t SyncEngine::GetExecTaskCount() +{ + std::lock_guard autoLock(execTaskCountLock_); + return execTaskCount_; +} + void SyncEngine::Dump(int fd) { { @@ -1376,4 +1409,70 @@ uint32_t SyncEngine::GetTimeout(const std::string &dev) RefObject::DecObjRef(communicator); return timeout; } + +std::string SyncEngine::GetTargetUserId(const std::string &dev) +{ + std::string targetUserId; + ICommunicator *communicator = nullptr; + { + std::lock_guard autoLock(communicatorProxyLock_); + if (communicatorProxy_ == nullptr) { + LOGW("[SyncEngine] Communicator is null when get target user"); + return targetUserId; + } + communicator = communicatorProxy_; + RefObject::IncObjRef(communicator); + } + DBProperties properties = syncInterface_->GetDbProperties(); + ExtendInfo extendInfo; + extendInfo.appId = properties.GetStringProp(DBProperties::APP_ID, ""); + extendInfo.userId = properties.GetStringProp(DBProperties::USER_ID, ""); + extendInfo.storeId = properties.GetStringProp(DBProperties::STORE_ID, ""); + extendInfo.dstTarget = dev; + extendInfo.subUserId = properties.GetStringProp(DBProperties::SUB_USER, ""); + targetUserId = communicator->GetTargetUserId(extendInfo); + RefObject::DecObjRef(communicator); + return targetUserId; +} + +int SyncEngine::RegCallbackOnInitComunicator(ICommunicatorAggregator *communicatorAggregator, + const ISyncInterface *syncInterface) +{ + int errCode = communicator_->RegOnMessageCallback( + [this](const std::string &targetDev, Message *inMsg) { + return MessageReciveCallback(targetDev, inMsg); + }, []() {}); + if (errCode != E_OK) { + LOGE("[SyncEngine] SyncRequestCallback register failed! err = %d", errCode); + communicatorAggregator->ReleaseCommunicator(communicator_, GetUserId(syncInterface)); + communicator_ = nullptr; + return errCode; + } + return E_OK; +} + +int32_t SyncEngine::GetRemoteQueryTaskCount() +{ + auto executor = GetAndIncRemoteExector(); + if (executor == nullptr) { + LOGW("[SyncEngine] RemoteExecutor is null when get remote query task count"); + RefObject::DecObjRef(executor); + return 0; + } + auto count = executor->GetTaskCount(); + RefObject::DecObjRef(executor); + return count; +} + +bool SyncEngine::ExchangeClosePending(bool expected) +{ + if (communicator_ == nullptr) { + return false; + } + auto communicator = communicator_; + RefObject::IncObjRef(communicator); + int res = communicator->ExchangeClosePending(expected); + RefObject::DecObjRef(communicator); + return res; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.h index 78c93192..0f7ab3ed 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.h @@ -137,13 +137,17 @@ public: void TimeChange() override; int32_t GetResponseTaskCount() override; + + int32_t GetRemoteQueryTaskCount() override; + + bool ExchangeClosePending(bool expected) override; protected: // Create a context virtual ISyncTaskContext *CreateSyncTaskContext(const ISyncInterface &syncInterface) = 0; // Find SyncTaskContext from the map - ISyncTaskContext *FindSyncTaskContext(const std::string &deviceId); - ISyncTaskContext *GetSyncTaskContextAndInc(const std::string &deviceId); + ISyncTaskContext *FindSyncTaskContext(const DeviceSyncTarget &target); + std::vector GetSyncTaskContextAndInc(const std::string &deviceId); void GetQueryAutoSyncParam(const std::string &device, const QuerySyncObject &query, InternalSyncParma &outParam); void GetSubscribeSyncParam(const std::string &device, const QuerySyncObject &query, InternalSyncParma &outParam); @@ -151,12 +155,12 @@ protected: ISyncInterface *GetAndIncSyncInterface(); void SetSyncInterface(ISyncInterface *syncInterface); - ISyncTaskContext *GetSyncTaskContext(const std::string &deviceId, int &errCode); + ISyncTaskContext *GetSyncTaskContext(const DeviceSyncTarget &target, int &errCode); std::mutex storageMutex_; ISyncInterface *syncInterface_; // Used to store all send sync task infos (such as pull sync response, and push sync request) - std::map syncTaskContextMap_; + std::map syncTaskContextMap_; std::mutex contextMapLock_; std::shared_ptr subManager_; std::function queryAutoSyncCallback_; @@ -181,7 +185,7 @@ private: void ScheduleTaskOut(ISyncTaskContext *context, const ICommunicator *communicator); // wrapper of MessageReciveCallbackTask - void MessageReciveCallback(const std::string &targetDev, Message *inMsg); + int MessageReciveCallback(const std::string &targetDev, Message *inMsg); // Sync Request Callback int MessageReciveCallbackInner(const std::string &targetDev, Message *inMsg); @@ -201,7 +205,7 @@ private: // Handle message in order. int ScheduleDealMsg(ISyncTaskContext *context, Message *inMsg); - ISyncTaskContext *GetContextForMsg(const std::string &targetDev, int &errCode); + ISyncTaskContext *GetContextForMsg(const DeviceSyncTarget &target, int &errCode); ICommunicator *AllocCommunicator(const std::string &identifier, int &errCode, std::string userId = ""); @@ -217,6 +221,8 @@ private: void DecExecTaskCount(); + uint32_t GetExecTaskCount(); + RemoteExecutor *GetAndIncRemoteExector(); void SetRemoteExector(RemoteExecutor *executor); @@ -237,6 +243,10 @@ private: uint32_t GetTimeout(const std::string &dev); + int RegCallbackOnInitComunicator(ICommunicatorAggregator *communicatorAggregator, + const ISyncInterface *syncInterface); + + std::string GetTargetUserId(const std::string &dev); ICommunicator *communicator_; DeviceManager *deviceManager_; std::function onRemoteDataChanged_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.cpp index 4fd93de5..1fd82b4f 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.cpp @@ -285,6 +285,16 @@ std::string SyncTaskContext::GetDeviceId() const return deviceId_; } +std::string SyncTaskContext::GetTargetUserId() const +{ + return targetUserId_; +} + +void SyncTaskContext::SetTargetUserId(const std::string &userId) +{ + targetUserId_ = userId; +} + void SyncTaskContext::SetTaskExecStatus(int status) { taskExecStatus_ = status; @@ -493,9 +503,14 @@ void SyncTaskContext::CommErrHandlerFunc(int errCode, ISyncTaskContext *context, RefObject::IncObjRef(context); } - static_cast(context)->CommErrHandlerFuncInner(errCode, static_cast(sessionId), - isDirectEnd); - RefObject::DecObjRef(context); + int ret = RuntimeContext::GetInstance()->ScheduleTask([context, errCode, sessionId, isDirectEnd]() { + static_cast(context)->CommErrHandlerFuncInner(errCode, static_cast(sessionId), + isDirectEnd); + RefObject::DecObjRef(context); + }); + if (ret != E_OK) { + RefObject::DecObjRef(context); + } } void SyncTaskContext::SetRemoteSoftwareVersion(uint32_t version) diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.h index 42d53e7d..7885b91f 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.h @@ -78,6 +78,10 @@ public: // Get the current task deviceId. std::string GetDeviceId() const override; + std::string GetTargetUserId() const override; + + void SetTargetUserId(const std::string &userId) override; + // Set the sync task queue exec status void SetTaskExecStatus(int status) override; @@ -260,6 +264,7 @@ protected: volatile int status_; volatile int taskExecStatus_; std::string deviceId_; + std::string targetUserId_; std::string syncActionName_; ISyncInterface *syncInterface_; ICommunicator *communicator_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/syncer_proxy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/syncer_proxy.cpp index 0c8d6fd6..cabd4bf1 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/syncer_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/syncer_proxy.cpp @@ -64,7 +64,7 @@ int SyncerProxy::Sync(const std::vector &devices, int mode, return syncer_->Sync(devices, mode, onComplete, onFinalize, wait); } -int SyncerProxy::Sync(const SyncParma &parma, uint64_t connectionId) +int SyncerProxy::Sync(const SyncParam &parma, uint64_t connectionId) { if (syncer_ == nullptr) { return -E_NOT_INIT; @@ -289,4 +289,12 @@ int32_t SyncerProxy::GetTaskCount() } return syncer_->GetTaskCount(); } + +bool SyncerProxy::ExchangeClosePending(bool expected) +{ + if (syncer_ == nullptr) { + return false; + } + return syncer_->ExchangeClosePending(expected); +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.cpp index 43bd032e..ae0e841c 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.cpp @@ -179,7 +179,7 @@ int TimeSync::RegisterTransformFunc() } int TimeSync::Initialize(ICommunicator *communicator, const std::shared_ptr &metadata, - const ISyncInterface *storage, const DeviceID &deviceId) + const ISyncInterface *storage, const DeviceID &deviceId, const DeviceID &userId) { if ((communicator == nullptr) || (storage == nullptr) || (metadata == nullptr)) { return -E_INVALID_ARGS; @@ -191,6 +191,7 @@ int TimeSync::Initialize(ICommunicator *communicator, const std::shared_ptr(); int errCode = timeHelper_->Initialize(storage, metadata_); @@ -205,7 +206,7 @@ int TimeSync::Initialize(ICommunicator *communicator, const std::shared_ptrIsTimeSyncFinish(deviceId_); + isSynced_ = metadata_->IsTimeSyncFinish(deviceId_, userId_); return errCode; } @@ -225,7 +226,7 @@ void TimeSync::Finalize() LOGD("[TimeSync] Finalized!"); } -int TimeSync::SyncStart(const CommErrHandler &handler, uint32_t sessionId) +int TimeSync::SyncStart(const CommErrHandler &handler, uint32_t sessionId, bool isRetryTask) { isOnline_ = true; TimeSyncPacket packet; @@ -250,7 +251,7 @@ int TimeSync::SyncStart(const CommErrHandler &handler, uint32_t sessionId) message = nullptr; return errCode; } - errCode = SendMessageWithSendEnd(message, handler); + errCode = SendMessageWithSendEnd(message, handler, isRetryTask); if (errCode != E_OK) { delete message; message = nullptr; @@ -369,10 +370,11 @@ int TimeSync::DeSerialization(const uint8_t *buffer, uint32_t length, Message *i int TimeSync::AckRecv(const Message *message, uint32_t targetSessionId) { // only check when sessionId is not 0, because old version timesync sessionId is 0. - if (message != nullptr && message->GetSessionId() != 0 && - message->GetErrorNo() == E_FEEDBACK_COMMUNICATOR_NOT_FOUND && message->GetSessionId() == targetSessionId) { - LOGE("[AbilitySync][AckMsgCheck] Remote db is closed"); - return -E_FEEDBACK_COMMUNICATOR_NOT_FOUND; + if (message != nullptr && message->GetSessionId() != 0 && message->GetSessionId() == targetSessionId) { + if (message->GetErrorNo() == E_FEEDBACK_COMMUNICATOR_NOT_FOUND) { + LOGE("[AbilitySync][AckMsgCheck] Remote db is closed"); + return -E_FEEDBACK_COMMUNICATOR_NOT_FOUND; + } } if (!IsPacketValid(message, TYPE_RESPONSE)) { return -E_INVALID_ARGS; @@ -446,9 +448,9 @@ int TimeSync::RequestRecv(const Message *message) return errCode; } -int TimeSync::SaveTimeOffset(const DeviceID &deviceID, TimeOffset timeOffset) +int TimeSync::SaveTimeOffset(const DeviceID &deviceID, const DeviceID &userId, TimeOffset timeOffset) { - return metadata_->SaveTimeOffset(deviceID, timeOffset); + return metadata_->SaveTimeOffset(deviceID, userId, timeOffset); } std::pair TimeSync::CalculateTimeOffset(const TimeSyncPacket &timeSyncInfo) @@ -456,9 +458,9 @@ std::pair TimeSync::CalculateTimeOffset(const TimeSyncPa TimeOffset roundTrip = static_cast((timeSyncInfo.GetSourceTimeEnd() - timeSyncInfo.GetSourceTimeBegin()) - (timeSyncInfo.GetTargetTimeEnd() - timeSyncInfo.GetTargetTimeBegin())); TimeOffset offset1 = static_cast(timeSyncInfo.GetTargetTimeBegin() - - timeSyncInfo.GetSourceTimeBegin() - (roundTrip / TRIP_DIV_HALF)); - TimeOffset offset2 = static_cast(timeSyncInfo.GetTargetTimeEnd() + (roundTrip / TRIP_DIV_HALF) - - timeSyncInfo.GetSourceTimeEnd()); + timeSyncInfo.GetSourceTimeBegin()) - (roundTrip / TRIP_DIV_HALF); + TimeOffset offset2 = static_cast(timeSyncInfo.GetTargetTimeEnd() - timeSyncInfo.GetSourceTimeEnd()) + + (roundTrip / TRIP_DIV_HALF); TimeOffset offset = (offset1 / TRIP_DIV_HALF) + (offset2 / TRIP_DIV_HALF); LOGD("TimeSync::CalculateTimeOffset roundTrip= %" PRId64 ", offset1 = %" PRId64 ", offset2 = %" PRId64 ", offset = %" PRId64, roundTrip, offset1, offset2, offset); @@ -481,10 +483,12 @@ bool TimeSync::IsPacketValid(const Message *inMsg, uint16_t messageType) return true; } -int TimeSync::SendPacket(const DeviceID &deviceId, const Message *message, const CommErrHandler &handler) +int TimeSync::SendPacket(const DeviceID &deviceId, const Message *message, const CommErrHandler &handler, + bool isRetryTask) { SendConfig conf; timeHelper_->SetSendConfig(deviceId, false, SEND_TIME_OUT, conf); + conf.isRetryTask = isRetryTask; int errCode = communicateHandle_->SendMessage(deviceId, message, conf, handler); if (errCode != E_OK) { LOGE("[TimeSync] SendPacket failed, err %d", errCode); @@ -546,7 +550,7 @@ int TimeSync::GetTimeOffset(TimeOffset &outOffset, uint32_t timeout, uint32_t se return -E_BUSY; } retryTime_ = 0; - metadata_->GetTimeOffset(deviceId_, outOffset); + metadata_->GetTimeOffset(deviceId_, userId_, outOffset); return E_OK; } @@ -617,7 +621,7 @@ bool TimeSync::IsClosed() const return closed_ ; } -int TimeSync::SendMessageWithSendEnd(const Message *message, const CommErrHandler &handler) +int TimeSync::SendMessageWithSendEnd(const Message *message, const CommErrHandler &handler, bool isRetryTask) { std::shared_ptr timeSyncPtr = shared_from_this(); auto sessionId = message->GetSessionId(); @@ -634,7 +638,7 @@ int TimeSync::SendMessageWithSendEnd(const Message *message, const CommErrHandle if (handler != nullptr) { handler(errCode, isDirectEnd); } - }); + }, isRetryTask); } Timestamp TimeSync::GetSourceBeginTime(Timestamp packetBeginTime, uint32_t sessionId) @@ -692,16 +696,16 @@ void TimeSync::ReTimeSyncIfNeed(const TimeSyncPacket &ackPacket) } // reset time change by time sync - int errCode = metadata_->SetTimeChangeMark(deviceId_, false); + int errCode = metadata_->SetTimeChangeMark(deviceId_, userId_, false); if (errCode != E_OK) { - LOGW("[TimeSync] Mark dev %.3s no time change failed %d", deviceId_.c_str(), errCode); + LOGW("[TimeSync] Mark dev %.3s_%.3s no time change failed %d", deviceId_.c_str(), userId_.c_str(), errCode); } } bool TimeSync::CheckReTimeSyncIfNeedWithLowVersion(TimeOffset timeOffsetIgnoreRtt) { TimeOffset metadataTimeOffset; - metadata_->GetTimeOffset(deviceId_, metadataTimeOffset); + metadata_->GetTimeOffset(deviceId_, userId_, metadataTimeOffset); return (std::abs(metadataTimeOffset) >= INT64_MAX / 2) || // 2 is half of INT64_MAX (std::abs(metadataTimeOffset - timeOffsetIgnoreRtt) > MAX_TIME_OFFSET_NOISE); } @@ -719,10 +723,11 @@ int TimeSync::SaveOffsetWithAck(const TimeSyncPacket &ackPacket) // calculate timeoffset of two devices auto [offset, rtt] = CalculateTimeOffset(ackPacket); TimeOffset rawOffset = CalculateRawTimeOffset(ackPacket, offset); - LOGD("TimeSync::AckRecv, dev = %s{private}, sEnd = %" PRIu64 ", tEnd = %" PRIu64 ", sBegin = %" PRIu64 + LOGD("TimeSync::AckRecv, dev = %s{private}_%s{private}, sEnd = %" PRIu64 ", tEnd = %" PRIu64 ", sBegin = %" PRIu64 ", tBegin = %" PRIu64 ", offset = %" PRId64 ", rawOffset = %" PRId64 ", requestLocalOffset = %" PRId64 ", responseLocalOffset = %" PRId64, deviceId_.c_str(), + userId_.c_str(), ackPacket.GetSourceTimeEnd(), ackPacket.GetTargetTimeEnd(), ackPacket.GetSourceTimeBegin(), @@ -733,11 +738,11 @@ int TimeSync::SaveOffsetWithAck(const TimeSyncPacket &ackPacket) ackPacket.GetResponseLocalOffset()); // save timeoffset into metadata, maybe a block action - int errCode = SaveTimeOffset(deviceId_, offset); + int errCode = SaveTimeOffset(deviceId_, userId_, offset); if (errCode != E_OK) { return errCode; } - errCode = metadata_->SetSystemTimeOffset(deviceId_, rawOffset); + errCode = metadata_->SetSystemTimeOffset(deviceId_, userId_, rawOffset); if (errCode != E_OK) { return errCode; } @@ -793,7 +798,7 @@ void TimeSync::SetTimeSyncFinishIfNeed() if (errCode != E_OK) { return; } - int64_t systemTimeOffset = metadata_->GetSystemTimeOffset(deviceId_); + int64_t systemTimeOffset = metadata_->GetSystemTimeOffset(deviceId_, userId_); LOGD("[TimeSync] Check db offset %" PRId64 " cache offset %" PRId64, systemTimeOffset, info.systemTimeOffset); if (!CheckSkipTimeSync(info) || (IsNeedSync() && std::abs(systemTimeOffset - info.systemTimeOffset) >= MAX_TIME_OFFSET_NOISE)) { @@ -804,7 +809,7 @@ void TimeSync::SetTimeSyncFinishIfNeed() SetTimeSyncFinishInner(true); } if (systemTimeOffset != info.systemTimeOffset) { - errCode = metadata_->SetSystemTimeOffset(deviceId_, info.systemTimeOffset); + errCode = metadata_->SetSystemTimeOffset(deviceId_, userId_, info.systemTimeOffset); if (errCode != E_OK) { return; } @@ -825,7 +830,7 @@ int TimeSync::GenerateTimeOffsetIfNeed(TimeOffset systemOffset, TimeOffset sende } auto [errCode, info] = RuntimeContext::GetInstance()->GetDeviceTimeInfo(deviceId_); bool syncFinish = !IsNeedSync(); - bool timeChange = metadata_->IsTimeChange(deviceId_); + bool timeChange = metadata_->IsTimeChange(deviceId_, userId_); // avoid local time change but remote record time sync finish // should return re time sync, after receive time sync request, reset time change mark // we think offset is ok when local time sync to remote @@ -842,11 +847,11 @@ int TimeSync::GenerateTimeOffsetIfNeed(TimeOffset systemOffset, TimeOffset sende // Sender's deltaTime = Sender's systemOffset - requestLocalOffset + responseLocalOffset // Receiver's deltaTime = -Sender's deltaTime = -Sender's systemOffset + requestLocalOffset - responseLocalOffset TimeOffset offset = -systemOffset + senderLocalOffset - metadata_->GetLocalTimeOffset(); - errCode = metadata_->SetSystemTimeOffset(deviceId_, -systemOffset); + errCode = metadata_->SetSystemTimeOffset(deviceId_, userId_, -systemOffset); if (errCode != E_OK) { return errCode; } - errCode = metadata_->SaveTimeOffset(deviceId_, offset); + errCode = metadata_->SaveTimeOffset(deviceId_, userId_, offset); if (errCode != E_OK) { return errCode; } @@ -863,10 +868,10 @@ void TimeSync::SetTimeSyncFinishInner(bool finish) if (IsRemoteLowVersion(SOFTWARE_VERSION_RELEASE_9_0)) { return; } - int errCode = metadata_->SetTimeSyncFinishMark(deviceId_, finish); + int errCode = metadata_->SetTimeSyncFinishMark(deviceId_, userId_, finish); if (errCode != E_OK) { - LOGW("[TimeSync] Set %.3s time sync finish %d mark failed %d", deviceId_.c_str(), static_cast(finish), - errCode); + LOGW("[TimeSync] Set %.3s_%.3s time sync finish %d mark failed %d", deviceId_.c_str(), userId_.c_str(), + static_cast(finish), errCode); } } } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.h index b8ec7991..01ca6156 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.h @@ -82,9 +82,10 @@ public: static int DeSerialization(const uint8_t *buffer, uint32_t length, Message *inMsg); // register to communicator int Initialize(ICommunicator *communicator, const std::shared_ptr &metadata, - const ISyncInterface *storage, const DeviceID &deviceId); + const ISyncInterface *storage, const DeviceID &deviceId, const DeviceID &userId); - virtual int SyncStart(const CommErrHandler &handler = nullptr, uint32_t sessionId = 0); // send timesync request + // send timesync request + virtual int SyncStart(const CommErrHandler &handler = nullptr, uint32_t sessionId = 0, bool isRetryTask = true); int AckRecv(const Message *message, uint32_t targetSessionId = 0); @@ -121,9 +122,10 @@ protected: void Finalize(); - int SaveTimeOffset(const DeviceID &deviceID, TimeOffset timeOffset); + int SaveTimeOffset(const DeviceID &deviceID, const DeviceID &userId, TimeOffset timeOffset); - int SendPacket(const DeviceID &deviceId, const Message *message, const CommErrHandler &handler = nullptr); + int SendPacket(const DeviceID &deviceId, const Message *message, const CommErrHandler &handler = nullptr, + bool isRetryTask = true); int TimeSyncDriver(TimerId timerId); @@ -131,7 +133,7 @@ protected: bool IsClosed() const; - int SendMessageWithSendEnd(const Message *message, const CommErrHandler &handler); + int SendMessageWithSendEnd(const Message *message, const CommErrHandler &handler, bool isRetryTask); Timestamp GetSourceBeginTime(Timestamp packetBeginTime, uint32_t sessionId); @@ -153,6 +155,7 @@ protected: std::shared_ptr metadata_; std::unique_ptr timeHelper_; DeviceID deviceId_; + DeviceID userId_; int retryTime_; TimerId driverTimerId_; TimerAction driverCallback_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.cpp index 0e68d5fe..c8719e1d 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.cpp @@ -32,7 +32,24 @@ SyncOperation::SyncOperation(uint32_t syncId, const std::vector &de semaphore_(nullptr), query_(QuerySyncObject()), isQuerySync_(false), - isAutoSubscribe_(false) + isAutoSubscribe_(false), + isRetry_(true) +{ +} + +SyncOperation::SyncOperation(uint32_t syncId, const ISyncer::SyncParam ¶m) + : devices_(param.devices), + syncId_(syncId), + mode_(param.mode), + userCallback_(param.onComplete), + isBlockSync_(param.wait), + isAutoSync_(false), + isFinished_(false), + semaphore_(nullptr), + query_(QuerySyncObject()), + isQuerySync_(false), + isAutoSubscribe_(false), + isRetry_(param.isRetry) { } @@ -445,6 +462,7 @@ DBStatus SyncOperation::DBStatusTrans(int operationStatus) { static_cast(OP_USER_CHANGED), USER_CHANGED }, { static_cast(OP_DENIED_SQL), NO_PERMISSION }, { static_cast(OP_NOTADB_OR_CORRUPTED), INVALID_PASSWD_OR_CORRUPTED_DB }, + { static_cast(OP_DB_CLOSING), OK }, { static_cast(OP_FAILED), DB_ERROR }, }; const auto &result = std::find_if(std::begin(syncOperationStatusNodes), std::end(syncOperationStatusNodes), @@ -486,5 +504,10 @@ std::string SyncOperation::GetFinishDetailMsg(const std::map & msg.pop_back(); return msg; } + +bool SyncOperation::IsRetryTask() const +{ + return isRetry_; +} DEFINE_OBJECT_TAG_FACILITIES(SyncOperation) } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.h b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.h index f3f00a5d..3b68919d 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.h @@ -23,6 +23,7 @@ #include #include "ikvdb_sync_interface.h" +#include "isyncer.h" #include "notification_chain.h" #include "query_sync_object.h" #include "ref_object.h" @@ -57,6 +58,7 @@ public: OP_USER_CHANGED, OP_DENIED_SQL, OP_NOTADB_OR_CORRUPTED, + OP_DB_CLOSING, }; using UserCallback = std::function)>; @@ -66,6 +68,8 @@ public: SyncOperation(uint32_t syncId, const std::vector &devices, int mode, const UserCallback &userCallback, bool isBlockSync); + SyncOperation(uint32_t syncId, const ISyncer::SyncParam ¶m); + DISABLE_COPY_ASSIGN_MOVE(SyncOperation); // Init the status for callback @@ -119,6 +123,8 @@ public: // Check if All devices sync finished. bool CheckIsAllFinished() const; + bool IsRetryTask() const; + // For query sync void SetQuery(const QuerySyncObject &query); void GetQuery(QuerySyncObject &targetObject) const; @@ -200,6 +206,8 @@ private: volatile bool isAutoSubscribe_; + volatile bool isRetry_; + // record identifier used to call ScheduleQueuedTask in SyncOperation::Finished std::string identifier_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/time_helper.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/time_helper.cpp index f82841dc..1984d1f2 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/time_helper.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/time_helper.cpp @@ -20,33 +20,8 @@ #include "platform_specific.h" namespace DistributedDB { -std::mutex TimeHelper::systemTimeLock_; -Timestamp TimeHelper::lastSystemTimeUs_ = 0; -Timestamp TimeHelper::currentIncCount_ = 0; std::atomic TimeHelper::lastMonotonicTime_ = 0; -Timestamp TimeHelper::GetSysCurrentTime() -{ - uint64_t curTime = 0; - std::lock_guard lock(systemTimeLock_); - int errCode = OS::GetCurrentSysTimeInMicrosecond(curTime); - if (errCode != E_OK) { - return INVALID_TIMESTAMP; - } - - // If GetSysCurrentTime in 1us, we need increase the currentIncCount_ - if (curTime == lastSystemTimeUs_) { - // if the currentIncCount_ has been increased MAX_INC_COUNT, keep the currentIncCount_ - if (currentIncCount_ < MAX_INC_COUNT) { - currentIncCount_++; - } - } else { - lastSystemTimeUs_ = curTime; - currentIncCount_ = 0; - } - return (curTime * TO_100_NS) + currentIncCount_; // Currently Timestamp is uint64_t -} - int TimeHelper::GetSysCurrentRawTime(uint64_t &curTime) { int errCode = OS::GetCurrentSysTimeInMicrosecond(curTime); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/time_helper_client.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/time_helper_client.cpp new file mode 100644 index 00000000..5f9bde2e --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/time_helper_client.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 "time_helper.h" + +#include "platform_specific.h" + +namespace DistributedDB { +std::mutex TimeHelper::systemTimeLock_; +Timestamp TimeHelper::lastSystemTimeUs_ = 0; +Timestamp TimeHelper::currentIncCount_ = 0; + +Timestamp TimeHelper::GetSysCurrentTime() +{ + uint64_t curTime = 0; + std::lock_guard lock(systemTimeLock_); + int errCode = OS::GetCurrentSysTimeInMicrosecond(curTime); + if (errCode != E_OK) { + return INVALID_TIMESTAMP; + } + + // If GetSysCurrentTime in 1us, we need increase the currentIncCount_ + if (curTime == lastSystemTimeUs_) { + // if the currentIncCount_ has been increased MAX_INC_COUNT, keep the currentIncCount_ + if (currentIncCount_ < MAX_INC_COUNT) { + currentIncCount_++; + } + } else { + lastSystemTimeUs_ = curTime; + currentIncCount_ = 0; + } + return (curTime * TO_100_NS) + currentIncCount_; // Currently Timestamp is uint64_t +} +} // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/BUILD.gn index d27aba5b..51484e15 100644 --- a/kv_store/frameworks/libs/distributeddb/test/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/BUILD.gn @@ -13,7 +13,7 @@ import("//build/test.gni") import("../distributeddb.gni") -module_output_path = "kv_store/kv_store/distributeddb" +module_output_path = "kv_store/distributeddb" ############################################################################### config("gaussdb_rd_config") { @@ -126,18 +126,24 @@ ohos_source_set("src_file") { sources = distributeddb_src sources += distributeddb_cloud_src + sources += distributeddb_client_src sources += [ "unittest/common/common/basic_unit_test.cpp", "unittest/common/common/distributeddb_data_generate_unit_test.cpp", + "unittest/common/common/distributeddb_tools_unit_client_test.cpp", "unittest/common/common/distributeddb_tools_unit_test.cpp", "unittest/common/common/kv_general_ut.cpp", "unittest/common/common/native_sqlite.cpp", "unittest/common/common/rdb_data_generator.cpp", + "unittest/common/common/rdb_data_generator_client.cpp", "unittest/common/common/rdb_general_ut.cpp", "unittest/common/common/system_time.cpp", "unittest/common/common/thread_pool_test_stub.cpp", "unittest/common/interfaces/process_system_api_adapter_impl.cpp", + "unittest/common/storage/virtual_sqlite_relational_store.cpp", + "unittest/common/storage/virtual_sqlite_storage_engine.cpp", "unittest/common/syncer/cloud/cloud_db_data_utils.cpp", + "unittest/common/syncer/cloud/cloud_db_sync_utils_client_test.cpp", "unittest/common/syncer/cloud/cloud_db_sync_utils_test.cpp", "unittest/common/syncer/cloud/virtual_asset_loader.cpp", "unittest/common/syncer/cloud/virtual_cloud_data_translate.cpp", @@ -155,22 +161,12 @@ ohos_source_set("src_file") { configs = [ ":module_private_config" ] - branch_protector_ret = "pac_ret" - sanitize = { - ubsan = true - boundary_sanitize = true - cfi = true - cfi_cross_dso = true - debug = false - } - ldflags = [ "-Wl,--exclude-libs,ALL" ] deps = [ "../gaussdb_rd:gaussdb_rd" ] configs += [ ":gaussdb_rd_config" ] public_configs = [ ":gaussdb_rd_public_config" ] external_deps = [ - "cJSON:cjson", "c_utils:utils", "ffrt:libffrt", "googletest:gmock_main", @@ -183,6 +179,7 @@ ohos_source_set("src_file") { "sqlite:sqlite", "zlib:libz", ] + subsystem_name = "distributeddatamgr" part_name = "kv_store" } @@ -880,6 +877,18 @@ distributeddb_unittest("DistributedDBKVDataStatusTest") { [ "unittest/common/store_test/kv/distributeddb_kv_data_status_test.cpp" ] } +distributeddb_unittest("DistributedDBKvMultiUserSyncTest") { + sources = [ + "unittest/common/store_test/kv/distracteddb_kv_multi_user_sync_test.cpp", + ] +} + +distributeddb_unittest("DistributedDBRDBMultiUserSyncTest") { + sources = [ + "unittest/common/store_test/rdb/distracteddb_rdb_multi_user_sync_test.cpp", + ] +} + distributeddb_unittest("DistributedDBBasicRDBTest") { sources = [ "unittest/common/store_test/rdb/distributeddb_basic_rdb_test.cpp" ] @@ -891,12 +900,234 @@ distributeddb_unittest("DistributedDBRDBDataStatusTest") { ] } +distributeddb_unittest("DistributedDBKVCompressTest") { + sources = + [ "unittest/common/store_test/kv/distributeddb_kv_compress_test.cpp" ] +} + +distributeddb_unittest("DistributedDBAbnormalKVSyncTest") { + sources = [ + "unittest/common/store_test/kv/distributeddb_abnormal_kv_sync_test.cpp", + ] +} + +distributeddb_unittest("DistributedDBKvDeviceSyncTest") { + sources = + [ "unittest/common/store_test/kv/distributeddb_kv_device_sync_test.cpp" ] +} + +distributeddb_unittest("DistributedDBRDBCompressTest") { + sources = + [ "unittest/common/store_test/rdb/distributeddb_rdb_compress_test.cpp" ] +} + +distributeddb_unittest("DistributedDBRDBDropTableTest") { + sources = + [ "unittest/common/store_test/rdb/distributeddb_rdb_drop_table_test.cpp" ] +} + +distributeddb_unittest("DistributedDBRDBUpgradeTest") { + sources = + [ "unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp" ] +} + +config("tokenizer_config_unittest") { + visibility = [ ":*" ] + include_dirs = [ "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include" ] + + defines = [ + "SQLITE_ENABLE_SNAPSHOT", + "SQLITE_HAS_CODEC", + "SQLITE_ENABLE_JSON1", + "USING_HILOG_LOGGER", + "USE_SQLITE_SYMBOLS", + "SQLITE_ENABLE_DROPTABLE_CALLBACK", + ] +} + +ohos_unittest("tokenizer_test") { + branch_protector_ret = "pac_ret" + + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + + module_out_path = module_output_path + + sources = [ "unittest/common/tokenizer/sqlite_adapter_test.cpp" ] + sources += [ "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/src/log_print.cpp" ] + + configs = [ ":tokenizer_config_unittest" ] + cflags_cc = [] + + external_deps = [ + "c_utils:utils", + "ffrt:libffrt", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", + "zlib:libz", + ] +} + +distributeddb_unittest("DistributedDBRDBKnowledgeTest") { + sources = + [ "unittest/common/store_test/rdb/distributeddb_rdb_knowledge_test.cpp" ] +} + +############################################################################### +config("distributeddb_client_module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "./unittest/common/common", + "./unittest/common/syncer", + "./unittest/common/syncer/cloud", + "./unittest/common/interfaces", + "../include", + "../interfaces/include", + "../interfaces/include/cloud", + "../interfaces/include/relational", + "../interfaces/src", + "../interfaces/src/relational", + "../common/include", + "../common/include/cloud", + "../common/include/relational", + "../communicator/include", + "../communicator/src", + "../storage/include", + "../storage/src", + "../storage/src/kv", + "../storage/src/relational", + "../storage/src/sqlite", + "../storage/src/sqlite/relational", + "../syncer/include", + "../syncer/src", + "../syncer/src/cloud", + "../syncer/src/device", + "../gaussdb_rd/include", + ] + + defines = [ + "_LARGEFILE64_SOURCE", + "_FILE_OFFSET_BITS=64", + "SQLITE_HAS_CODEC", + "SQLITE_ENABLE_JSON1", + "USING_HILOG_LOGGER", + "USE_SQLITE_SYMBOLS", + "USING_DB_JSON_EXTRACT_AUTOMATICALLY", + "JSONCPP_USE_BUILDER", + "OMIT_FLATBUFFER", + "OMIT_MULTI_VER", + "RELATIONAL_STORE", + "SQLITE_DISTRIBUTE_RELATIONAL", + "USE_DFX_ABILITY", + "SQLITE_ENABLE_DROPTABLE_CALLBACK", + "OPENSSL_SUPPRESS_DEPRECATED", + ] + if (is_ohos) { + defines += [ "USE_FFRT" ] + defines += [ "RDB_CLIENT" ] + } +} + +ohos_source_set("distributeddb_client_src_file") { + testonly = true + + sources = distributeddb_client_src + sources += distributeddb_base_src + sources += [ + "unittest/common/common/distributeddb_tools_unit_client_test.cpp", + "unittest/common/common/rdb_data_generator_client.cpp", + "unittest/common/common/system_time.cpp", + "unittest/common/syncer/cloud/cloud_db_sync_utils_client_test.cpp", + ] + + configs = [ ":distributeddb_client_module_private_config" ] + + branch_protector_ret = "pac_ret" + sanitize = { + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + ldflags = [ "-Wl,--exclude-libs,ALL" ] + deps = [ "../gaussdb_rd:gaussdb_rd" ] + configs += [ ":gaussdb_rd_config" ] + public_configs = [ ":gaussdb_rd_public_config" ] + + external_deps = [ + "c_utils:utils", + "ffrt:libffrt", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", + "zlib:libz", + ] + subsystem_name = "distributeddatamgr" + part_name = "kv_store" +} + +template("distributeddb_client_unittest") { + ohos_unittest(target_name) { + forward_variables_from(invoker, "*") + module_out_path = module_output_path + if (!defined(deps)) { + deps = [] + } + if (!defined(external_deps)) { + external_deps = [] + } + configs = [ ":distributeddb_client_module_private_config" ] + deps += [ + ":distributeddb_client_src_file", + "../gaussdb_rd:gaussdb_rd", + ] + + ldflags = [ "-Wl,--exclude-libs,ALL" ] + + external_deps = [ + "c_utils:utils", + "ffrt:libffrt", + "googletest:gmock_main", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", + "zlib:libz", + ] + } +} + +distributeddb_client_unittest("DistributedDBRDBKnowledgeClientTest") { + sources = [ "unittest/common/store_test/rdb/distributeddb_rdb_knowledge_client_test.cpp" ] +} + ############################################################################### group("unittest") { testonly = true deps = [] deps += [ ":DistributedDBAbilitySyncTest", + ":DistributedDBAbnormalKVSyncTest", ":DistributedDBAutoLaunchUnitTest", ":DistributedDBBasicKVTest", ":DistributedDBBasicRDBTest", @@ -967,7 +1198,9 @@ group("unittest") { ":DistributedDBInterfacesTransactionSyncDBTest", ":DistributedDBInterfacesTransactionTest", ":DistributedDBJsonPrecheckUnitTest", + ":DistributedDBKVCompressTest", ":DistributedDBKVDataStatusTest", + ":DistributedDBKvMultiUserSyncTest", ":DistributedDBMetaDataTest", ":DistributedDBMockSyncModuleTest", ":DistributedDBMultiVerP2PSyncTest", @@ -975,7 +1208,13 @@ group("unittest") { ":DistributedDBNotificationChainTest", ":DistributedDBParcelTest", ":DistributedDBRDBCollaborationTest", + ":DistributedDBRDBCompressTest", ":DistributedDBRDBDataStatusTest", + ":DistributedDBRDBDropTableTest", + ":DistributedDBRDBKnowledgeClientTest", + ":DistributedDBRDBKnowledgeTest", + ":DistributedDBRDBMultiUserSyncTest", + ":DistributedDBRDBUpgradeTest", ":DistributedDBRelationalCloudSyncableStorageTest", ":DistributedDBRelationalEncryptedDbTest", ":DistributedDBRelationalGetDataTest", @@ -1022,6 +1261,7 @@ group("unittest") { ":DistributedDBTimeSyncTest", ":DistributedInterfacesRelationalTest", ":RuntimeContextProcessSystemApiAdapterImplTest", + ":tokenizer_test", ] if (defined(global_parts_info.distributeddatamgr_kv_store_lite)) { diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/BUILD.gn index 40519259..9c8f158a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/BUILD.gn @@ -106,16 +106,14 @@ ohos_fuzztest("CloudsyncFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "../../../../distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/cloudsync_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/cloudsync_fuzzer.cpp index a0bc7988..6bdc6d64 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/cloudsync_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/cloudsync_fuzzer.cpp @@ -18,6 +18,7 @@ #include "cloud/cloud_db_constant.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" +#include "fuzzer/FuzzedDataProvider.h" #include "fuzzer_data.h" #include "kv_store_nb_delegate.h" #include "log_print.h" @@ -123,22 +124,22 @@ public: delegate->CreateDistributedTable(g_table, CLOUD_COOPERATION); } - static void InitDbData(sqlite3 *&db, const uint8_t *data, size_t size) + static void InitDbData(sqlite3 *&db, FuzzedDataProvider &fdp) { sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(db, g_insertLocalDataSql, stmt); if (errCode != E_OK) { return; } - FuzzerData fuzzerData(data, size); - uint32_t len = fuzzerData.GetUInt32() % MOD; + size_t size = fdp.ConsumeIntegralInRange(0, MOD); for (size_t i = 0; i <= size; ++i) { - std::string idStr = fuzzerData.GetString(len); + std::string idStr = fdp.ConsumeRandomLengthString(); errCode = SQLiteUtils::BindTextToStatement(stmt, 1, idStr); if (errCode != E_OK) { break; } - std::vector photo = fuzzerData.GetSequence(fuzzerData.GetInt()); + int photoSize = fdp.ConsumeIntegralInRange(1, MOD); + std::vector photo = fdp.ConsumeBytes(photoSize); errCode = SQLiteUtils::BindBlobToStatement(stmt, 2, photo); // 2 is index of photo if (errCode != E_OK) { break; @@ -160,25 +161,22 @@ public: return asset; } - void InitDbAsset(const uint8_t *data, size_t size) + void InitDbAsset(FuzzedDataProvider &fdp) { - if (data == nullptr || size == 0) { - return; - } sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(db_, g_insertLocalAssetSql, stmt); if (errCode != E_OK) { return; } - FuzzerData fuzzerData(data, size); - uint32_t len = fuzzerData.GetUInt32() % MOD; + size_t size = fdp.ConsumeIntegralInRange(0, MOD); for (size_t i = 0; i <= size; ++i) { - std::string idStr = fuzzerData.GetString(len); + std::string idStr = fdp.ConsumeRandomLengthString(); errCode = SQLiteUtils::BindTextToStatement(stmt, 1, idStr); if (errCode != E_OK) { break; } - std::vector photo = fuzzerData.GetSequence(fuzzerData.GetInt()); + size_t photoSize = fdp.ConsumeIntegralInRange(1, MOD); + std::vector photo = fdp.ConsumeBytes(photoSize); errCode = SQLiteUtils::BindBlobToStatement(stmt, 2, photo); // 2 is index of photo if (errCode != E_OK) { break; @@ -446,79 +444,69 @@ public: kvDelegatePtrS2_->Get(key, actualValue); } - void RandomModeSync(const uint8_t *data, size_t size) + void RandomModeSync(FuzzedDataProvider &fdp) { - if (size == 0) { - BlockSync(); - return; - } - auto mode = static_cast(data[0]); + size_t syncModeLen = sizeof(SyncMode); + auto mode = static_cast(fdp.ConsumeIntegralInRange(0, syncModeLen)); LOGI("[RandomModeSync] select mode %d", static_cast(mode)); BlockSync(mode); } - void DataChangeSync(const uint8_t *data, size_t size) + void DataChangeSync(FuzzedDataProvider &fdp) { SetCloudDbSchema(delegate_); - if (size == 0) { - return; - } - InitDbData(db_, data, size); + InitDbData(db_, fdp); BlockSync(); - FuzzerData fuzzerData(data, size); CloudSyncConfig config; - int maxUploadSize = fuzzerData.GetInt(); - int maxUploadCount = fuzzerData.GetInt(); + int maxUploadSize = fdp.ConsumeIntegral(); + int maxUploadCount = fdp.ConsumeIntegral(); config.maxUploadSize = maxUploadSize; config.maxUploadCount = maxUploadCount; delegate_->SetCloudSyncConfig(config); kvDelegatePtrS1_->SetCloudSyncConfig(config); - uint32_t len = fuzzerData.GetUInt32() % MOD; - std::string version = fuzzerData.GetString(len); + uint32_t len = fdp.ConsumeIntegralInRange(0, MOD); + std::string version = fdp.ConsumeRandomLengthString(); kvDelegatePtrS1_->SetGenCloudVersionCallback([version](const std::string &origin) { return origin + version; }); KvNormalSync(); - int count = fuzzerData.GetInt(); + int count = fdp.ConsumeIntegral(); kvDelegatePtrS1_->GetCount(Query::Select(), count); - std::string device = fuzzerData.GetString(len); + std::string device = fdp.ConsumeRandomLengthString(); kvDelegatePtrS1_->GetCloudVersion(device); - std::vector devices = fuzzerData.GetStringVector(len); + std::vector devices; + for (uint32_t i = 0; i< len; i++) { + devices.push_back(fdp.ConsumeRandomLengthString()); + } OptionBlockSync(devices); } - void InitAssets(const uint8_t *data, size_t size) + void InitAssets(FuzzedDataProvider &fdp) { - FuzzerData fuzzerData(data, size); - uint32_t len = fuzzerData.GetUInt32() % MOD; + size_t size = fdp.ConsumeIntegralInRange(0, MOD); for (size_t i = 0; i <= size; ++i) { - std::string nameStr = fuzzerData.GetString(len); - localAssets_.push_back(GenAsset(nameStr, std::to_string(data[0]))); + std::string nameStr = fdp.ConsumeRandomLengthString(MOD); + localAssets_.push_back(GenAsset(nameStr, fdp.ConsumeBytesAsString(1))); } } - void AssetChangeSync(const uint8_t *data, size_t size) + void AssetChangeSync(FuzzedDataProvider &fdp) { SetCloudDbSchema(delegate_); - if (size == 0) { - return; - } - InitAssets(data, size); - InitDbAsset(data, size); + InitAssets(fdp); + InitDbAsset(fdp); BlockSync(); } - void RandomModeRemoveDeviceData(const uint8_t *data, size_t size) + void RandomModeRemoveDeviceData(FuzzedDataProvider &fdp) { - if (size == 0) { - return; - } SetCloudDbSchema(delegate_); int64_t cloudCount = 10; int64_t paddingSize = 10; InsertCloudTableRecord(0, cloudCount, paddingSize, false); BlockSync(); - auto mode = static_cast(data[0]); + size_t modeLen = sizeof(ClearMode); + auto mode = static_cast(fdp.ConsumeIntegralInRange(0, modeLen)); LOGI("[RandomModeRemoveDeviceData] select mode %d", static_cast(mode)); if (mode == DEFAULT) { return; @@ -564,17 +552,17 @@ void TearDown() } } -void CombineTest(const uint8_t *data, size_t size) +void CombineTest(FuzzedDataProvider &fdp) { if (g_cloudSyncTest == nullptr) { return; } g_cloudSyncTest->NormalSync(); g_cloudSyncTest->KvNormalSync(); - g_cloudSyncTest->RandomModeSync(data, size); - g_cloudSyncTest->DataChangeSync(data, size); - g_cloudSyncTest->AssetChangeSync(data, size); - g_cloudSyncTest->RandomModeRemoveDeviceData(data, size); + g_cloudSyncTest->RandomModeSync(fdp); + g_cloudSyncTest->DataChangeSync(fdp); + g_cloudSyncTest->AssetChangeSync(fdp); + g_cloudSyncTest->RandomModeRemoveDeviceData(fdp); } } @@ -582,7 +570,8 @@ void CombineTest(const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { OHOS::Setup(); - OHOS::CombineTest(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::CombineTest(fdp); OHOS::TearDown(); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn index d4743910..03868e80 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("DelegateFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -107,16 +100,14 @@ ohos_fuzztest("DelegateFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/delegate_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/delegate_fuzzer.cpp index 3d07c641..82e8b8eb 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/delegate_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/delegate_fuzzer.cpp @@ -16,22 +16,24 @@ #include "delegate_fuzzer.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" +#include "fuzzer/FuzzedDataProvider.h" using namespace DistributedDB; using namespace DistributedDBTest; namespace OHOS { +static constexpr const int HUNDRED = 100; static constexpr const int MOD = 1024; // 1024 is mod static constexpr const int PASSWDLEN = 20; // 20 is passwdlen -std::vector CreateEntries(const uint8_t *data, size_t size, std::vector& keys) +std::vector CreateEntries(FuzzedDataProvider &fdp, std::vector& keys) { std::vector entries; // key'length is less than 1024. - auto count = static_cast(std::min(size, size_t(MOD))); + auto count = fdp.ConsumeIntegralInRange(0, size_t(MOD)); for (int i = 1; i < count; i++) { Entry entry; - entry.key = std::vector(data, data + 1); - entry.value = std::vector(data, data + size); + entry.key = fdp.ConsumeBytes(i); + entry.value = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, MOD)); keys.push_back(entry.key); entries.push_back(entry); } @@ -53,21 +55,25 @@ KvStoreDelegate *PrepareKvStore(KvStoreConfig &config, KvStoreDelegate::Option & return kvDelegatePtr; } -void EncryptOperation(const uint8_t *data, size_t size, KvStoreDelegate *kvDelegatePtr) +void EncryptOperation(FuzzedDataProvider &fdp, KvStoreDelegate *kvDelegatePtr) { if (kvDelegatePtr == nullptr) { return; } CipherPassword passwd; - int len = static_cast(std::min(size, size_t(PASSWDLEN))); - passwd.SetValue(data, len); + size_t data_size = fdp.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val = static_cast(new uint8_t[data_size]); + fdp.ConsumeData(val, data_size); + passwd.SetValue(val, data_size); + delete[] static_cast(val); + val = nullptr; kvDelegatePtr->Rekey(passwd); - bool autoSync = (size == 0) ? true : data[0]; + bool autoSync = fdp.ConsumeBool(); PragmaData praData = static_cast(&autoSync); kvDelegatePtr->Pragma(AUTO_SYNC, praData); } -void CombineTest(const uint8_t *data, KvStoreDelegate *kvDelegatePtr) +void CombineTest(FuzzedDataProvider &fdp, KvStoreDelegate *kvDelegatePtr) { if (kvDelegatePtr == nullptr) { return; @@ -75,11 +81,11 @@ void CombineTest(const uint8_t *data, KvStoreDelegate *kvDelegatePtr) kvDelegatePtr->GetStoreId(); kvDelegatePtr->Rollback(); kvDelegatePtr->Commit(); - auto type = static_cast(data[0]); + auto type = static_cast(fdp.ConsumeIntegral()); kvDelegatePtr->SetConflictResolutionPolicy(type, nullptr); } -void MultiCombineFuzzer(const uint8_t *data, size_t size, KvStoreDelegate::Option &option) +void MultiCombineFuzzer(FuzzedDataProvider &fdp, KvStoreDelegate::Option &option) { KvStoreConfig config; KvStoreDelegate *kvDelegatePtr = PrepareKvStore(config, option); @@ -91,8 +97,8 @@ void MultiCombineFuzzer(const uint8_t *data, size_t size, KvStoreDelegate::Optio } kvDelegatePtr->RegisterObserver(observer); - Key key = std::vector(data, data + (size % 1024)); /* 1024 is max */ - Value value = std::vector(data, data + size); + Key key = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, MOD)); + Value value = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, HUNDRED)); kvDelegatePtr->Put(key, value); kvDelegatePtr->StartTransaction(); KvStoreSnapshotDelegate *kvStoreSnapshotPtr = nullptr; @@ -113,17 +119,17 @@ void MultiCombineFuzzer(const uint8_t *data, size_t size, KvStoreDelegate::Optio kvDelegatePtr->Delete(key); kvStoreSnapshotPtr->Get(key, valueCallback); std::vector keys; - kvDelegatePtr->PutBatch(CreateEntries(data, size, keys)); - Key keyPrefix = std::vector(data, data + 1); + kvDelegatePtr->PutBatch(CreateEntries(fdp, keys)); + Key keyPrefix = fdp.ConsumeBytes(1); kvStoreSnapshotPtr->GetEntries(keyPrefix, [](DBStatus status, const std::vector &entries) { (void) entries.size(); }); if (option.isEncryptedDb) { - EncryptOperation(data, size, kvDelegatePtr); + EncryptOperation(fdp, kvDelegatePtr); } kvDelegatePtr->DeleteBatch(keys); kvDelegatePtr->Clear(); - CombineTest(data, kvDelegatePtr); + CombineTest(fdp, kvDelegatePtr); kvDelegatePtr->UnRegisterObserver(observer); delete observer; observer = nullptr; @@ -139,8 +145,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { CipherPassword passwd; KvStoreDelegate::Option option = {true, true, false, CipherType::DEFAULT, passwd}; - OHOS::MultiCombineFuzzer(data, size, option); + FuzzedDataProvider fdp(data, size); + OHOS::MultiCombineFuzzer(fdp, option); option = {true, false, false, CipherType::DEFAULT, passwd}; - OHOS::MultiCombineFuzzer(data, size, option); + OHOS::MultiCombineFuzzer(fdp, option); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn index 2b4a6b6c..7be09eb0 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn @@ -56,14 +56,6 @@ ohos_fuzztest("FileOperFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", - "//third_party/googletest/googletest/include/gtest", ] cflags = [ @@ -88,13 +80,6 @@ ohos_fuzztest("FileOperFuzzTest") { "fileoper_fuzzer.cpp", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] - defines = [ "SQLITE_ENABLE_SNAPSHOT", "_LARGEFILE64_SOURCE", @@ -115,9 +100,14 @@ ohos_fuzztest("FileOperFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] + deps = [ "../../../../distributeddb:distributeddb" ] + external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/fileoper_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/fileoper_fuzzer.cpp index 05532d00..e11e2e2d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/fileoper_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/fileoper_fuzzer.cpp @@ -16,27 +16,30 @@ #include "fileoper_fuzzer.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" +#include "fuzzer/FuzzedDataProvider.h" #include "process_communicator_test_stub.h" using namespace DistributedDB; using namespace DistributedDBTest; namespace OHOS { +static constexpr const int PASSWDLEN = 20; // 20 is passwdlen +static constexpr const int MOD = 1024; static auto g_kvManager = KvStoreDelegateManager("APP_ID", "USER_ID"); -std::vector CreateEntries(const uint8_t* data, size_t size) +std::vector CreateEntries(FuzzedDataProvider &fdp) { std::vector entries; - auto count = static_cast(std::min(size, size_t(1024))); + auto count = fdp.ConsumeIntegralInRange(0, MOD); for (int i = 1; i < count; i++) { Entry entry; - entry.key = std::vector (data, data + i); - entry.value = std::vector (data, data + size); + entry.key = fdp.ConsumeBytes(i); + entry.value = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, MOD)); entries.push_back(entry); } return entries; } -void SingerVerExportAndImport(const uint8_t* data, size_t size, const std::string& testDir) +void SingerVerExportAndImport(FuzzedDataProvider &fdp, const std::string& testDir) { KvStoreNbDelegate::Option nbOption = {true, false, true}; KvStoreNbDelegate *kvNbDelegatePtr = nullptr; @@ -50,13 +53,18 @@ void SingerVerExportAndImport(const uint8_t* data, size_t size, const std::strin if (kvNbDelegatePtr == nullptr) { return; } - kvNbDelegatePtr->PutBatch(CreateEntries(data, size)); + kvNbDelegatePtr->PutBatch(CreateEntries(fdp)); - std::string rawString(reinterpret_cast(data), size); - std::string singleExportFileName = testDir + "/" + rawString; + std::string rawString = fdp.ConsumeRandomLengthString(); + std::string singleExportFileName = testDir + "/" + rawString; CipherPassword passwd; - passwd.SetValue(data, size); + size_t size = fdp.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val = static_cast(new uint8_t[size]); + fdp.ConsumeData(val, size); + passwd.SetValue(val, size); + delete[] static_cast(val); + val = nullptr; kvNbDelegatePtr->Export(singleExportFileName, passwd); kvNbDelegatePtr->Import(singleExportFileName, passwd); @@ -64,10 +72,15 @@ void SingerVerExportAndImport(const uint8_t* data, size_t size, const std::strin g_kvManager.DeleteKvStore("distributed_file_oper_single"); } -void MultiVerExportAndImport(const uint8_t* data, size_t size, const std::string& testDir) +void MultiVerExportAndImport(FuzzedDataProvider &fdp, const std::string& testDir) { CipherPassword passwd; - passwd.SetValue(data, size); + size_t size = fdp.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val = static_cast(new uint8_t[size]); + fdp.ConsumeData(val, size); + passwd.SetValue(val, size); + delete[] static_cast(val); + val = nullptr; KvStoreDelegate::Option option = {true, false, true, CipherType::DEFAULT, passwd}; KvStoreDelegate *kvDelegatePtr = nullptr; g_kvManager.GetKvStore("distributed_file_oper_multi", option, @@ -79,8 +92,9 @@ void MultiVerExportAndImport(const uint8_t* data, size_t size, const std::string if (kvDelegatePtr == nullptr) { return; } - kvDelegatePtr->PutBatch(CreateEntries(data, size)); - std::string rawString(reinterpret_cast(data), size); + kvDelegatePtr->PutBatch(CreateEntries(fdp)); + std::string rawString = fdp.ConsumeRandomLengthString(); + std::string multiExportFileName = testDir + "/" + rawString; kvDelegatePtr->Export(multiExportFileName, passwd); kvDelegatePtr->Import(multiExportFileName, passwd); @@ -97,8 +111,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) OHOS::g_kvManager.SetKvStoreConfig(config); OHOS::g_kvManager.SetProcessLabel("FUZZ", "DISTRIBUTEDDB"); OHOS::g_kvManager.SetProcessCommunicator(std::make_shared()); - OHOS::SingerVerExportAndImport(data, size, config.dataDir); - OHOS::MultiVerExportAndImport(data, size, config.dataDir); + FuzzedDataProvider provider(data, size); + OHOS::SingerVerExportAndImport(provider, config.dataDir); + OHOS::MultiVerExportAndImport(provider, config.dataDir); DistributedDBToolsTest::RemoveTestDbFiles(config.dataDir); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn index 4c14ac15..02b0ef60 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("ImportFileFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -108,16 +101,14 @@ ohos_fuzztest("ImportFileFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/importfile_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/importfile_fuzzer.cpp index 4ada93f7..f29e8265 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/importfile_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/importfile_fuzzer.cpp @@ -17,6 +17,7 @@ #include #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" +#include "fuzzer/FuzzedDataProvider.h" #include "platform_specific.h" #include "process_communicator_test_stub.h" @@ -27,14 +28,20 @@ using namespace std; static KvStoreConfig g_config; namespace OHOS { -void SingerVerImport(const uint8_t *data, size_t size, const std::string &importFile) +static constexpr const int PASSWDLEN = 20; // 20 is passwdlen +void SingerVerImport(FuzzedDataProvider &provider, const std::string &importFile) { static auto kvManager = KvStoreDelegateManager("APP_ID", "USER_ID"); kvManager.SetKvStoreConfig(g_config); kvManager.SetProcessLabel("FUZZ", "DISTRIBUTEDDB"); kvManager.SetProcessCommunicator(std::make_shared()); CipherPassword passwd; - passwd.SetValue(data, size); + size_t size = provider.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val = static_cast(new uint8_t[size]); + provider.ConsumeData(val, size); + passwd.SetValue(val, size); + delete[] static_cast(val); + val = nullptr; KvStoreNbDelegate::Option option = {true, false, true, CipherType::DEFAULT, passwd}; KvStoreNbDelegate *kvNbDelegatePtr = nullptr; @@ -53,14 +60,15 @@ void SingerVerImport(const uint8_t *data, size_t size, const std::string &import kvManager.DeleteKvStore("distributed_import_single"); } -bool MakeImportFile(const uint8_t *data, size_t size, const std::string &realPath) +bool MakeImportFile(FuzzedDataProvider &provider, const std::string &realPath) { std::ofstream ofs(realPath, std::ofstream::out); if (!ofs.is_open()) { LOGE("the file open failed"); return false; } - ofs.write(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); + ofs.write(rawString.c_str(), rawString.length()); return true; } } @@ -68,15 +76,16 @@ bool MakeImportFile(const uint8_t *data, size_t size, const std::string &realPat /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + FuzzedDataProvider provider(data, size); std::string dataDir; - std::string testDataDir(data, data + size); + std::string testDataDir = provider.ConsumeRandomLengthString(); DistributedDBToolsTest::TestDirInit(dataDir); g_config.dataDir = dataDir; std::string path = dataDir + "/fuzz" + testDataDir; std::string realPath; OS::GetRealPath(path, realPath); - if (OHOS::MakeImportFile(data, size, realPath)) { - OHOS::SingerVerImport(data, size, realPath); + if (OHOS::MakeImportFile(provider, realPath)) { + OHOS::SingerVerImport(provider, realPath); } DistributedDBToolsTest::RemoveTestDbFiles(dataDir); diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn index b7dd8237..1a211a69 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("IProcessCommunicatorFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -107,16 +100,14 @@ ohos_fuzztest("IProcessCommunicatorFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/iprocesscommunicator_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/iprocesscommunicator_fuzzer.cpp index 89abb799..e315045b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/iprocesscommunicator_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/iprocesscommunicator_fuzzer.cpp @@ -17,6 +17,7 @@ #include #include "distributeddb_tools_test.h" #include "db_info_handle.h" +#include "fuzzer/FuzzedDataProvider.h" #include "iprocess_communicator.h" #include "iprocess_system_api_adapter.h" #include "runtime_config.h" @@ -87,12 +88,18 @@ public: onDeviceChange_(devInfo, isOnline); } - void FuzzOnDataReceive(const DistributedDB::DeviceInfos &devInfo, const uint8_t* data, size_t size) + void FuzzOnDataReceive(const DistributedDB::DeviceInfos &devInfo, FuzzedDataProvider &provider) { if (onDataReceive_ == nullptr) { return; } + size_t dataLen = 1024; + uint32_t size = provider.ConsumeIntegralInRange(0, dataLen);; + uint8_t* data = static_cast(new uint8_t[size]); + provider.ConsumeData(data, size); onDataReceive_(devInfo, data, size); + delete[] static_cast(data); + data = nullptr; } private: @@ -147,10 +154,10 @@ public: } }; -void CommunicatorFuzzer(const uint8_t *data, size_t size) +void CommunicatorFuzzer(FuzzedDataProvider &provider) { static auto kvManager = KvStoreDelegateManager("APP_ID", "USER_ID"); - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); KvStoreDelegateManager::SetProcessLabel(rawString, "defaut"); auto communicator = std::make_shared(); KvStoreDelegateManager::SetProcessCommunicator(communicator); @@ -173,7 +180,7 @@ void CommunicatorFuzzer(const uint8_t *data, size_t size) } }); DeviceInfos device = {"defaut"}; - communicator->FuzzOnDataReceive(device, data, size); + communicator->FuzzOnDataReceive(device, provider); if (kvNbDelegatePtr != nullptr) { kvManager.CloseKvStore(kvNbDelegatePtr); kvManager.DeleteKvStore(rawString); @@ -188,6 +195,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) if (size < 4) { return 0; } - OHOS::CommunicatorFuzzer(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::CommunicatorFuzzer(fdp); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/BUILD.gn index cffe3bff..4c7f7bc9 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/BUILD.gn @@ -77,16 +77,14 @@ ohos_source_set("src_file") { configs = [ ":module_private_config" ] - deps = [ "//third_party/sqlite:sqlite" ] - - configs += [ "//third_party/cJSON:cJSON_config" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps += [ "//third_party/cJSON:cjson" ] external_deps = [ + "cJSON:cjson", "c_utils:utils", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "sqlite:sqlite", ] subsystem_name = "distributeddatamgr" @@ -104,21 +102,16 @@ ohos_fuzztest("JsonFuzzTest") { external_deps = [] } configs = [ ":module_private_config" ] - deps += [ - ":src_file", - "//third_party/sqlite:sqlite", - ] - configs += [ "//third_party/cJSON:cJSON_config" ] + deps += [ ":src_file" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps += [ - "//third_party/cJSON:cjson", - "//third_party/openssl:libcrypto_shared", - ] external_deps = [ + "cJSON:cjson", "c_utils:utils", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] cflags = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.cpp index 7671d045..ea7e6b9a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.cpp @@ -28,6 +28,7 @@ #include #include +#include "fuzzer/FuzzedDataProvider.h" #include "grd_base/grd_db_api.h" #include "grd_base/grd_error.h" #include "grd_base/grd_resultset_api.h" @@ -332,14 +333,14 @@ void InsertDocFourFuzz(const std::string &longId, const std::string &documentDat GRD_InsertDoc(g_db, COLLECTION_NAME, document52, 0); } -void InsertDocFuzz(const uint8_t *data, size_t size) +void InsertDocFuzz(FuzzedDataProvider &provider) { - std::string collectionNameData(reinterpret_cast(data), size); + std::string collectionNameData = provider.ConsumeRandomLengthString(); const char *collectionNameVal = collectionNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); + std::string optionStrData = provider.ConsumeRandomLengthString(); const char *optionStrVal = optionStrData.data(); GRD_CreateCollection(g_db, collectionNameVal, optionStrVal, 0); - std::string documentData(reinterpret_cast(data), size); + std::string documentData = provider.ConsumeRandomLengthString(); const char *documentVal = documentData.data(); GRD_InsertDoc(g_db, collectionNameVal, documentVal, 0); GRD_InsertDoc(g_db, collectionNameVal, documentVal, 0); @@ -898,10 +899,10 @@ void FindDocFuzzPlus(const std::string &input) } } // namespace -void FindDocFuzz(const uint8_t *data, size_t size) +void FindDocFuzz(FuzzedDataProvider &provider) { GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{\"field\":\"" + input + "\"}"; GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); Query query = { inputJson.c_str(), inputJson.c_str() }; @@ -911,6 +912,7 @@ void FindDocFuzz(const uint8_t *data, size_t size) GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet); GRD_FreeResultSet(resultSet); resultSet = nullptr; + size_t size = provider.ConsumeIntegral(); GRD_FindDoc(g_db, input.c_str(), query, size, &resultSet); GRD_FreeResultSet(resultSet); GRD_FindDoc(nullptr, input.c_str(), query, 1, &resultSet); @@ -1067,10 +1069,10 @@ void UpdateDocFilterFuzz() GRD_DropCollection(g_db, COLLECTION_NAME, 0); } -void UpdateDocFuzz(const uint8_t *data, size_t size) +void UpdateDocFuzz(FuzzedDataProvider &provider) { GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{\"_id\":\"2\", \"field\": \"aaa\", " "\"subject\":\"aaaaaaaaaaa\", \"test1\": true, " "\"test2\": null}"; @@ -1132,10 +1134,10 @@ void UpsertDocNewFuzz(const std::string &input, GRD_DB *db1) GRD_UpsertDoc(db1, "student", R""({"_id":"10002"})"", updateDocNew.c_str(), 1); } -void UpsertDocFuzz(const uint8_t *data, size_t size) +void UpsertDocFuzz(FuzzedDataProvider &provider) { GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJsonNoId = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; std::string inputJson = "{\"_id\":\"1\", \"field\": " + input + "}"; @@ -1229,10 +1231,10 @@ void DeleteDocResultFuzz(const std::string &input) GRD_FreeResultSet(resultSet); } -void DeleteDocFuzz(const uint8_t *data, size_t size) +void DeleteDocFuzz(FuzzedDataProvider &provider) { GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{\"field\":" + input + "}"; GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); GRD_DeleteDoc(g_db, input.c_str(), "{}", 0); @@ -1357,10 +1359,10 @@ void FindAndReleaseFuzz(std::string document, std::string filter, Query query, c FindAndRelease(query); } -void NextFuzz(const uint8_t *data, size_t size) +void NextFuzz(FuzzedDataProvider &provider) { GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{" + input + "}"; GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); Query query = { inputJson.c_str(), "{}" }; @@ -1379,15 +1381,16 @@ void NextFuzz(const uint8_t *data, size_t size) query.filter = "{\"field\": [\"field2\", null, \"abc\", 123]}"; FindAndRelease(query); std::string document = "{\"field\": [\"" + input + "\",\"" + input + "\",\"" + input + "\"]}"; + size_t size = provider.ConsumeIntegral(); std::string filter = "{\"field." + std::to_string(size) + "\":\"" + input + "\"}"; FindAndReleaseFuzz(document, filter, query, input); GRD_DropCollection(g_db, COLLECTION_NAME, 0); } -void GetValueFuzz(const uint8_t *data, size_t size) +void GetValueFuzz(FuzzedDataProvider &provider) { GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{" + input + "}"; GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); char *value = nullptr; @@ -1436,12 +1439,12 @@ void DbOpenOneFuzz(GRD_DB *dbVal) DbOpenCloseFuzz(path.c_str(), R""({"redopubbufsize":16385})"", dbVal); } -void DbOpenFuzz(const uint8_t *data, size_t size) +void DbOpenFuzz(FuzzedDataProvider &provider) { - std::string dbFileData(reinterpret_cast(data), size); + std::string dbFileData = provider.ConsumeRandomLengthString(); std::string realDbFileData = DB_DIR_PATH + dbFileData; const char *dbFileVal = realDbFileData.data(); - std::string configStrData(reinterpret_cast(data), size); + std::string configStrData = provider.ConsumeRandomLengthString(); const char *configStrVal = configStrData.data(); GRD_DB *dbVal = nullptr; @@ -1493,12 +1496,12 @@ void DbOpenFuzz(const uint8_t *data, size_t size) DbOpenOneFuzz(dbVal); } -void DbCloseFuzz(const uint8_t *data, size_t size) +void DbCloseFuzz(FuzzedDataProvider &provider) { - std::string dbFileData(reinterpret_cast(data), size); + std::string dbFileData = provider.ConsumeRandomLengthString(); std::string realDbFileData = DB_DIR_PATH + dbFileData; const char *dbFileVal = realDbFileData.data(); - std::string configStrData(reinterpret_cast(data), size); + std::string configStrData = provider.ConsumeRandomLengthString(); const char *configStrVal = configStrData.data(); GRD_DB *dbVal = nullptr; DbOpenCloseFuzz(dbFileVal, configStrVal, dbVal); @@ -1527,11 +1530,11 @@ void DbCloseResultSetFuzz() } } -void CreateCollectionFuzz(const uint8_t *data, size_t size) +void CreateCollectionFuzz(FuzzedDataProvider &provider) { - std::string collectionNameData(reinterpret_cast(data), size); + std::string collectionNameData = provider.ConsumeRandomLengthString(); const char *collectionNameVal = collectionNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); + std::string optionStrData = provider.ConsumeRandomLengthString(); const char *optionStrVal = optionStrData.data(); GRD_CreateCollection(nullptr, collectionNameVal, optionStrVal, 0); GRD_CreateCollection(g_db, collectionNameVal, optionStrVal, 0); @@ -1552,25 +1555,22 @@ void CreateCollectionFuzz(const uint8_t *data, size_t size) GRD_DropCollection(g_db, collectionNameVal, 0); } -void DropCollectionFuzz(const uint8_t *data, size_t size) +void DropCollectionFuzz(FuzzedDataProvider &provider) { - std::string collectionNameData(reinterpret_cast(data), size); + std::string collectionNameData = provider.ConsumeRandomLengthString(); const char *collectionNameVal = collectionNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); + std::string optionStrData = provider.ConsumeRandomLengthString(); const char *optionStrVal = optionStrData.data(); GRD_CreateCollection(g_db, collectionNameVal, optionStrVal, 0); GRD_DropCollection(nullptr, collectionNameVal, 0); GRD_DropCollection(g_db, collectionNameVal, 0); } -void DbFlushFuzz(const uint8_t *data, size_t size) +void DbFlushFuzz(FuzzedDataProvider &provider) { - if (data == nullptr) { - return; - } GRD_DB *db = nullptr; GRD_DB *db2 = nullptr; - const uint32_t flags = *data; + const uint32_t flags = provider.ConsumeIntegral(); int ret = GRD_DBOpen(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db); if (ret == GRD_OK) { GRD_Flush(db, flags); @@ -1684,23 +1684,23 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Run your code on data */ OHOS::SetUpTestCase(); - - OHOS::DbOpenFuzz(data, size); - OHOS::CreateCollectionFuzz(data, size); - OHOS::DropCollectionFuzz(data, size); - OHOS::InsertDocFuzz(data, size); - OHOS::FindDocFuzz(data, size); - OHOS::UpdateDocFuzz(data, size); - OHOS::UpsertDocFuzz(data, size); - OHOS::DeleteDocFuzz(data, size); - OHOS::NextFuzz(data, size); - OHOS::GetValueFuzz(data, size); + FuzzedDataProvider provider(data, size); + OHOS::DbOpenFuzz(provider); + OHOS::CreateCollectionFuzz(provider); + OHOS::DropCollectionFuzz(provider); + OHOS::InsertDocFuzz(provider); + OHOS::FindDocFuzz(provider); + OHOS::UpdateDocFuzz(provider); + OHOS::UpsertDocFuzz(provider); + OHOS::DeleteDocFuzz(provider); + OHOS::NextFuzz(provider); + OHOS::GetValueFuzz(provider); OHOS::FreeResultSetFuzz(); OHOS::TestGrdDbApGrdGetItem002Fuzz(); OHOS::TestGrdKvBatchCoupling003Fuzz(); - OHOS::DbCloseFuzz(data, size); + OHOS::DbCloseFuzz(provider); OHOS::DbCloseResultSetFuzz(); - OHOS::DbFlushFuzz(data, size); + OHOS::DbFlushFuzz(provider); OHOS::TearDownTestCase(); return 0; diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/BUILD.gn index e1df9821..eb3f7f09 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/BUILD.gn @@ -77,16 +77,14 @@ ohos_source_set("src_file") { configs = [ ":module_private_config" ] - deps = [ "//third_party/sqlite:sqlite" ] - - configs += [ "//third_party/cJSON:cJSON_config" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps += [ "//third_party/cJSON:cjson" ] external_deps = [ + "cJSON:cjson", "c_utils:utils", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "sqlite:sqlite", ] subsystem_name = "distributeddatamgr" @@ -104,21 +102,16 @@ ohos_fuzztest("JsonInnerFuzzTest") { external_deps = [] } configs = [ ":module_private_config" ] - deps += [ - ":src_file", - "//third_party/sqlite:sqlite", - ] - configs += [ "//third_party/cJSON:cJSON_config" ] + deps += [ ":src_file" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps += [ - "//third_party/cJSON:cjson", - "//third_party/openssl:libcrypto_shared", - ] external_deps = [ + "cJSON:cjson", "c_utils:utils", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] cflags = [ diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.cpp index ce3d7570..5b79f758 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.cpp @@ -28,6 +28,7 @@ #include #include +#include "fuzzer/FuzzedDataProvider.h" #include "grd_base/grd_db_api.h" #include "grd_base/grd_error.h" #include "grd_base/grd_resultset_api.h" @@ -341,14 +342,14 @@ void InsertDocFourFuzz(const std::string &longId, const std::string &documentDat GRD_InsertDocInner(g_db, COLLECTION_NAME, document52, 0); } -void InsertDocFuzz(const uint8_t *data, size_t size) +void InsertDocFuzz(FuzzedDataProvider &provider) { - std::string collectionNameData(reinterpret_cast(data), size); + std::string collectionNameData = provider.ConsumeRandomLengthString(); const char *collectionNameVal = collectionNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); + std::string optionStrData = provider.ConsumeRandomLengthString(); const char *optionStrVal = optionStrData.data(); GRD_CreateCollectionInner(g_db, collectionNameVal, optionStrVal, 0); - std::string documentData(reinterpret_cast(data), size); + std::string documentData = provider.ConsumeRandomLengthString(); const char *documentVal = documentData.data(); GRD_InsertDocInner(g_db, collectionNameVal, documentVal, 0); GRD_InsertDocInner(g_db, collectionNameVal, documentVal, 0); @@ -907,10 +908,10 @@ void FindDocFuzzPlus(const std::string &input) } } // namespace -void FindDocFuzz(const uint8_t *data, size_t size) +void FindDocFuzz(FuzzedDataProvider &provider) { GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{\"field\":\"" + input + "\"}"; GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); Query query = { inputJson.c_str(), inputJson.c_str() }; @@ -920,6 +921,7 @@ void FindDocFuzz(const uint8_t *data, size_t size) GRD_FindDocInner(g_db, COLLECTION_NAME, query, 1, &resultSet); GRD_FreeResultSetInner(resultSet); resultSet = nullptr; + size_t size = provider.ConsumeIntegral(); GRD_FindDocInner(g_db, input.c_str(), query, size, &resultSet); GRD_FreeResultSetInner(resultSet); GRD_FindDocInner(nullptr, input.c_str(), query, 1, &resultSet); @@ -1076,10 +1078,10 @@ void UpdateDocFilterFuzz() GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); } -void UpdateDocFuzz(const uint8_t *data, size_t size) +void UpdateDocFuzz(FuzzedDataProvider &provider) { GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{\"_id\":\"2\", \"field\": \"aaa\", " "\"subject\":\"aaaaaaaaaaa\", \"test1\": true, " "\"test2\": null}"; @@ -1141,10 +1143,10 @@ void UpsertDocNewFuzz(const std::string &input, GRD_DB *db1) GRD_UpsertDocInner(db1, "student", R""({"_id":"10002"})"", updateDocNew.c_str(), 1); } -void UpsertDocFuzz(const uint8_t *data, size_t size) +void UpsertDocFuzz(FuzzedDataProvider &provider) { GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJsonNoId = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; std::string inputJson = "{\"_id\":\"1\", \"field\": " + input + "}"; @@ -1238,10 +1240,10 @@ void DeleteDocResultFuzz(const std::string &input) GRD_FreeResultSetInner(resultSet); } -void DeleteDocFuzz(const uint8_t *data, size_t size) +void DeleteDocFuzz(FuzzedDataProvider &provider) { GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{\"field\":" + input + "}"; GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); GRD_DeleteDocInner(g_db, input.c_str(), "{}", 0); @@ -1366,10 +1368,10 @@ void FindAndReleaseFuzz(std::string document, std::string filter, Query query, c FindAndRelease(query); } -void NextFuzz(const uint8_t *data, size_t size) +void NextFuzz(FuzzedDataProvider &provider) { GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{" + input + "}"; GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); Query query = { inputJson.c_str(), "{}" }; @@ -1388,15 +1390,16 @@ void NextFuzz(const uint8_t *data, size_t size) query.filter = "{\"field\": [\"field2\", null, \"abc\", 123]}"; FindAndRelease(query); std::string document = "{\"field\": [\"" + input + "\",\"" + input + "\",\"" + input + "\"]}"; + size_t size = provider.ConsumeIntegral(); std::string filter = "{\"field." + std::to_string(size) + "\":\"" + input + "\"}"; FindAndReleaseFuzz(document, filter, query, input); GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); } -void GetValueFuzz(const uint8_t *data, size_t size) +void GetValueFuzz(FuzzedDataProvider &provider) { GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); - std::string input(reinterpret_cast(data), size); + std::string input = provider.ConsumeRandomLengthString(); std::string inputJson = "{" + input + "}"; GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); char *value = nullptr; @@ -1445,12 +1448,12 @@ void DbOpenOneFuzz(GRD_DB *dbVal) DbOpenCloseFuzz(path.c_str(), R""({"redopubbufsize":16385})"", dbVal); } -void DbOpenFuzz(const uint8_t *data, size_t size) +void DbOpenFuzz(FuzzedDataProvider &provider) { - std::string dbFileData(reinterpret_cast(data), size); + std::string dbFileData = provider.ConsumeRandomLengthString(); std::string realDbFileData = DB_DIR_PATH + dbFileData; const char *dbFileVal = realDbFileData.data(); - std::string configStrData(reinterpret_cast(data), size); + std::string configStrData = provider.ConsumeRandomLengthString(); const char *configStrVal = configStrData.data(); GRD_DB *dbVal = nullptr; @@ -1502,12 +1505,12 @@ void DbOpenFuzz(const uint8_t *data, size_t size) DbOpenOneFuzz(dbVal); } -void DbCloseFuzz(const uint8_t *data, size_t size) +void DbCloseFuzz(FuzzedDataProvider &provider) { - std::string dbFileData(reinterpret_cast(data), size); + std::string dbFileData = provider.ConsumeRandomLengthString(); std::string realDbFileData = DB_DIR_PATH + dbFileData; const char *dbFileVal = realDbFileData.data(); - std::string configStrData(reinterpret_cast(data), size); + std::string configStrData = provider.ConsumeRandomLengthString(); const char *configStrVal = configStrData.data(); GRD_DB *dbVal = nullptr; DbOpenCloseFuzz(dbFileVal, configStrVal, dbVal); @@ -1536,11 +1539,11 @@ void DbCloseResultSetFuzz() } } -void CreateCollectionFuzz(const uint8_t *data, size_t size) +void CreateCollectionFuzz(FuzzedDataProvider &provider) { - std::string collectionNameData(reinterpret_cast(data), size); + std::string collectionNameData = provider.ConsumeRandomLengthString(); const char *collectionNameVal = collectionNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); + std::string optionStrData = provider.ConsumeRandomLengthString(); const char *optionStrVal = optionStrData.data(); GRD_CreateCollectionInner(nullptr, collectionNameVal, optionStrVal, 0); GRD_CreateCollectionInner(g_db, collectionNameVal, optionStrVal, 0); @@ -1561,25 +1564,22 @@ void CreateCollectionFuzz(const uint8_t *data, size_t size) GRD_DropCollectionInner(g_db, collectionNameVal, 0); } -void DropCollectionFuzz(const uint8_t *data, size_t size) +void DropCollectionFuzz(FuzzedDataProvider &provider) { - std::string collectionNameData(reinterpret_cast(data), size); + std::string collectionNameData = provider.ConsumeRandomLengthString(); const char *collectionNameVal = collectionNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); + std::string optionStrData = provider.ConsumeRandomLengthString(); const char *optionStrVal = optionStrData.data(); GRD_CreateCollectionInner(g_db, collectionNameVal, optionStrVal, 0); GRD_DropCollectionInner(nullptr, collectionNameVal, 0); GRD_DropCollectionInner(g_db, collectionNameVal, 0); } -void DbFlushFuzz(const uint8_t *data, size_t size) +void DbFlushFuzz(FuzzedDataProvider &provider) { - if (data == nullptr) { - return; - } GRD_DB *db = nullptr; GRD_DB *db2 = nullptr; - const uint32_t flags = *data; + const uint32_t flags = provider.ConsumeIntegral(); int ret = GRD_DBOpenInner(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db); if (ret == GRD_OK) { GRD_FlushInner(db, flags); @@ -1693,23 +1693,23 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Run your code on data */ OHOS::SetUpTestCase(); - - OHOS::DbOpenFuzz(data, size); - OHOS::CreateCollectionFuzz(data, size); - OHOS::DropCollectionFuzz(data, size); - OHOS::InsertDocFuzz(data, size); - OHOS::FindDocFuzz(data, size); - OHOS::UpdateDocFuzz(data, size); - OHOS::UpsertDocFuzz(data, size); - OHOS::DeleteDocFuzz(data, size); - OHOS::NextFuzz(data, size); - OHOS::GetValueFuzz(data, size); + FuzzedDataProvider provider(data, size); + OHOS::DbOpenFuzz(provider); + OHOS::CreateCollectionFuzz(provider); + OHOS::DropCollectionFuzz(provider); + OHOS::InsertDocFuzz(provider); + OHOS::FindDocFuzz(provider); + OHOS::UpdateDocFuzz(provider); + OHOS::UpsertDocFuzz(provider); + OHOS::DeleteDocFuzz(provider); + OHOS::NextFuzz(provider); + OHOS::GetValueFuzz(provider); OHOS::FreeResultSetFuzz(); OHOS::TestGrdDbApGrdGetItem002Fuzz(); OHOS::TestGrdKvBatchCoupling003Fuzz(); - OHOS::DbCloseFuzz(data, size); + OHOS::DbCloseFuzz(provider); OHOS::DbCloseResultSetFuzz(); - OHOS::DbFlushFuzz(data, size); + OHOS::DbFlushFuzz(provider); OHOS::TearDownTestCase(); return 0; diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn index 327c6593..4bc1b4b9 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("KvDelegateManagerFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -108,16 +101,14 @@ ohos_fuzztest("KvDelegateManagerFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/kvdelegatemanager_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/kvdelegatemanager_fuzzer.cpp index 31429f8d..72d4b065 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/kvdelegatemanager_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/kvdelegatemanager_fuzzer.cpp @@ -20,6 +20,7 @@ #include #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" +#include "fuzzer/FuzzedDataProvider.h" #include "kv_store_delegate_manager.h" #include "log_print.h" #include "runtime_config.h" @@ -31,27 +32,13 @@ class KvDelegateManagerFuzzer { namespace OHOS { using namespace DistributedDB; using namespace DistributedDBTest; - +static constexpr const int MOD = 1024; // 1024 is mod KvStoreDelegateManager g_mgr("APP_ID", "USER_ID"); const std::string DUMP_DISTRIBUTED_DB = "--database"; -std::string GetString(const uint8_t *data, size_t size, size_t len, uint32_t &start) -{ - std::string res; - if (size == 0) { - return ""; - } - if (start >= size || start + len >= size) { - return std::string(data, data + size - 1); - } - res = std::string(data + start, data + start + len - 1); - start += len; - return res; -} - -void GetAutoLaunchOption(const uint8_t* data, size_t size, AutoLaunchOption &option) +void GetAutoLaunchOption(FuzzedDataProvider &fdp, AutoLaunchOption &option) { - std::string randomStr = size == 0 ? "" : std::string(data, data + size - 1); + std::string randomStr = fdp.ConsumeRandomLengthString(); option.schema = randomStr; option.observer = nullptr; option.notifier = nullptr; @@ -68,11 +55,11 @@ void RuntimeConfigFuzz() RuntimeConfig::Dump(handle, params); } -void CallbackFuzz(const uint8_t *data, std::string storeId) +void CallbackFuzz(FuzzedDataProvider &fdp, std::string storeId) { - uint64_t diskSize = static_cast(*data); + uint64_t diskSize = fdp.ConsumeIntegral(); g_mgr.GetKvStoreDiskSize(storeId, diskSize); - bool isPermissionCheck = static_cast(*data); + bool isPermissionCheck = fdp.ConsumeBool(); auto permissionCheckCallback = [isPermissionCheck](const std::string &userId, const std::string &appId, const std::string &storeId, uint8_t flag) -> bool { return isPermissionCheck; }; (void) KvStoreDelegateManager::SetPermissionCheckCallback(permissionCheckCallback); @@ -81,38 +68,38 @@ void CallbackFuzz(const uint8_t *data, std::string storeId) return isPermissionCheck; }; (void) KvStoreDelegateManager::SetPermissionCheckCallback(permissionCheckCallbackV2); - bool isSyncActivationCheck = static_cast(*data); + bool isSyncActivationCheck = fdp.ConsumeBool(); auto syncActivationCheck = [isSyncActivationCheck](const std::string &userId, const std::string &appId, const std::string &storeId) -> bool { return isSyncActivationCheck; }; KvStoreDelegateManager::SetSyncActivationCheckCallback(syncActivationCheck); KvStoreDelegateManager::NotifyUserChanged(); } -void CombineTest(const uint8_t *data, size_t size) +void CombineTest(FuzzedDataProvider &fdp) { LOGD("Begin KvDelegateManagerFuzzer"); std::string path; DistributedDBToolsTest::TestDirInit(path); const int paramCount = 3; + size_t size = fdp.ConsumeIntegralInRange(paramCount, MOD); for (size_t len = 1; len < (size / paramCount); len++) { - uint32_t start = 0; - std::string appId = GetString(data, size, len, start); - std::string userId = GetString(data, size, len, start); - std::string storeId = GetString(data, size, len, start); + std::string appId = fdp.ConsumeRandomLengthString(); + std::string userId = fdp.ConsumeRandomLengthString(); + std::string storeId = fdp.ConsumeRandomLengthString(); std::string dir; (void) KvStoreDelegateManager::GetDatabaseDir(storeId, appId, userId, dir); (void) KvStoreDelegateManager::GetDatabaseDir(storeId, dir); (void) KvStoreDelegateManager::SetProcessLabel(appId, userId); - bool syncDualTupleMode = static_cast(*data); + bool syncDualTupleMode = fdp.ConsumeBool(); (void) KvStoreDelegateManager::GetKvStoreIdentifier(userId, appId, storeId, syncDualTupleMode); AutoLaunchOption option; - GetAutoLaunchOption(data, size, option); + GetAutoLaunchOption(fdp, option); option.dataDir = path; (void) KvStoreDelegateManager::EnableKvStoreAutoLaunch(userId, appId, storeId, option, nullptr); (void) KvStoreDelegateManager::DisableKvStoreAutoLaunch(userId, appId, storeId); - CallbackFuzz(data, storeId); - std::string targetDev = GetString(data, size, len, start); - bool isCheckOk = static_cast(*data); + CallbackFuzz(fdp, storeId); + std::string targetDev = fdp.ConsumeRandomLengthString(); + bool isCheckOk = fdp.ConsumeBool(); auto databaseStatusNotifyCallback = [userId, appId, storeId, targetDev, &isCheckOk] ( const std::string ¬ifyUserId, const std::string ¬ifyAppId, const std::string ¬ifyStoreId, const std::string &deviceId, bool onlineStatus) -> void { @@ -133,6 +120,7 @@ void CombineTest(const uint8_t *data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - OHOS::CombineTest(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::CombineTest(fdp); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn index 9e2b8423..69557fe0 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("KvStoreResultSetFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -108,16 +101,14 @@ ohos_fuzztest("KvStoreResultSetFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/kvstoreresultset_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/kvstoreresultset_fuzzer.cpp index a4a71e39..29570c39 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/kvstoreresultset_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/kvstoreresultset_fuzzer.cpp @@ -16,6 +16,7 @@ #include "kvstoreresultset_fuzzer.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" +#include "fuzzer/FuzzedDataProvider.h" #include "process_communicator_test_stub.h" using namespace DistributedDB; @@ -24,7 +25,8 @@ using namespace std; namespace OHOS { static auto g_kvManager = KvStoreDelegateManager("APP_ID", "USER_ID"); -void ResultSetFuzzer(const uint8_t* data, size_t size) +static constexpr const int MOD = 1024; // 1024 is mod +void ResultSetFuzzer(FuzzedDataProvider &fdp) { KvStoreNbDelegate::Option option = {true, false, true}; KvStoreNbDelegate *kvNbDelegatePtr = nullptr; @@ -41,11 +43,10 @@ void ResultSetFuzzer(const uint8_t* data, size_t size) Key testKey; Value testValue; + size_t size = fdp.ConsumeIntegralInRange(0, MOD); for (size_t i = 0; i < size; i++) { - testKey.clear(); - testValue.clear(); - testKey.push_back(data[i]); - testValue.push_back(data[i]); + testKey = fdp.ConsumeBytes(1); + testValue = fdp.ConsumeBytes(1); kvNbDelegatePtr->Put(testKey, testValue); } @@ -63,7 +64,7 @@ void ResultSetFuzzer(const uint8_t* data, size_t size) if (size == 0) { return; } - auto pos = KvStoreResultSetFuzzer::U32_AT(data) % size; + auto pos = fdp.ConsumeIntegralInRange(0, size); readResultSet->MoveToPosition(pos++); readResultSet->Move(0 - pos); readResultSet->IsFirst(); @@ -88,7 +89,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) KvStoreConfig config; DistributedDBToolsTest::TestDirInit(config.dataDir); OHOS::g_kvManager.SetKvStoreConfig(config); - OHOS::ResultSetFuzzer(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::ResultSetFuzzer(fdp); DistributedDBToolsTest::RemoveTestDbFiles(config.dataDir); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn index 72448092..768ee303 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("NbDelegateFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -108,16 +101,14 @@ ohos_fuzztest("NbDelegateFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/nbdelegate_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/nbdelegate_fuzzer.cpp index 0370e56f..ebe6e161 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/nbdelegate_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/nbdelegate_fuzzer.cpp @@ -17,6 +17,7 @@ #include #include "distributeddb_tools_test.h" #include "fuzzer_data.h" +#include "fuzzer/FuzzedDataProvider.h" #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" #include "kv_store_observer.h" @@ -29,7 +30,9 @@ class KvStoreNbDelegateCURDFuzzer { namespace OHOS { using namespace DistributedDB; using namespace DistributedDBTest; - +static constexpr const int HUNDRED = 100; +static constexpr const int MOD = 1024; +static constexpr const int PASSWDLEN = 20; class KvStoreObserverFuzzTest : public DistributedDB::KvStoreObserver { public: KvStoreObserverFuzzTest(); @@ -105,16 +108,16 @@ bool KvStoreObserverFuzzTest::IsCleared() const return isCleared_; } -std::vector CreateEntries(const uint8_t *data, size_t size, std::vector &keys) +std::vector CreateEntries(FuzzedDataProvider &fdp, std::vector &keys) { std::vector entries; // key'length is less than 1024. - auto count = static_cast(std::min(size, size_t(1024))); + auto count = fdp.ConsumeIntegralInRange(0, 1024); for (int i = 1; i < count; i++) { Entry entry; - entry.key = std::vector(data, data + i); + entry.key = fdp.ConsumeBytes(i); keys.push_back(entry.key); - entry.value = std::vector(data, data + size); + entry.value = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, HUNDRED)); entries.push_back(entry); } return entries; @@ -181,59 +184,53 @@ void TestCRUD(const Key &key, const Value &value, KvStoreNbDelegate *kvNbDelegat kvNbDelegatePtr->Get(key, valueRead); } -void GetDeviceEntriesTest(const uint8_t *data, size_t size, KvStoreNbDelegate *kvNbDelegatePtr) +void GetDeviceEntriesTest(FuzzedDataProvider &fdp, KvStoreNbDelegate *kvNbDelegatePtr) { - FuzzerData fuzzerData(data, size); - uint32_t len = fuzzerData.GetUInt32(); const int lenMod = 30; // 30 is mod for string vector size - std::string device = fuzzerData.GetString(len % lenMod); + std::string device = fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, lenMod)); kvNbDelegatePtr->GetWatermarkInfo(device); kvNbDelegatePtr->GetSyncDataSize(device); std::vector vect; kvNbDelegatePtr->GetDeviceEntries(device, vect); } -void RemoveDeviceDataByMode(const uint8_t *data, size_t size, KvStoreNbDelegate *kvNbDelegatePtr) +void RemoveDeviceDataByMode(FuzzedDataProvider &fdp, KvStoreNbDelegate *kvNbDelegatePtr) { - if (size == 0) { - return; - } - auto mode = static_cast(data[0]); + auto mode = static_cast(fdp.ConsumeIntegral()); LOGI("[RemoveDeviceDataByMode] select mode %d", static_cast(mode)); if (mode == DEFAULT) { return; } - FuzzerData fuzzerData(data, size); - uint32_t len = fuzzerData.GetUInt32(); const int lenMod = 30; // 30 is mod for string vector size - std::string device = fuzzerData.GetString(len % lenMod); - std::string user = fuzzerData.GetString(len % lenMod); + std::string device = fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, lenMod)); + std::string user = fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, lenMod)); kvNbDelegatePtr->RemoveDeviceData(); kvNbDelegatePtr->RemoveDeviceData(device, mode); kvNbDelegatePtr->RemoveDeviceData(device, user, mode); } -void FuzzCURD(const uint8_t *data, size_t size, KvStoreNbDelegate *kvNbDelegatePtr) +void FuzzCURD(FuzzedDataProvider &fdp, KvStoreNbDelegate *kvNbDelegatePtr) { auto observer = new (std::nothrow) KvStoreObserverFuzzTest; if ((observer == nullptr) || (kvNbDelegatePtr == nullptr)) { return; } - Key key = std::vector(data, data + (size % 1024)); /* 1024 is max */ - Value value = std::vector(data, data + size); - kvNbDelegatePtr->RegisterObserver(key, size, observer); - kvNbDelegatePtr->SetConflictNotifier(size, [](const KvStoreNbConflictData &data) { + + Key key = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, MOD));/* 1024 is max */ + Value value = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, MOD)); + kvNbDelegatePtr->RegisterObserver(key, fdp.ConsumeIntegral(), observer); + kvNbDelegatePtr->SetConflictNotifier(fdp.ConsumeIntegral(), [](const KvStoreNbConflictData &data) { (void)data.GetType(); }); TestCRUD(key, value, kvNbDelegatePtr); kvNbDelegatePtr->StartTransaction(); std::vector keys; - std::vector tmp = CreateEntries(data, size, keys); + std::vector tmp = CreateEntries(fdp, keys); kvNbDelegatePtr->PutBatch(tmp); if (!keys.empty()) { /* random deletePublic updateTimestamp 2 */ - bool deletePublic = (size > 3u) ? (data[0] > data[1]) : true; // use index 0 and 1 - bool updateTimestamp = (size > 3u) ? (data[2] > data[1]) : true; // use index 2 and 1 + bool deletePublic = fdp.ConsumeBool(); // use index 0 and 1 + bool updateTimestamp = fdp.ConsumeBool(); // use index 2 and 1 kvNbDelegatePtr->UnpublishToLocal(keys[0], deletePublic, updateTimestamp); } kvNbDelegatePtr->DeleteBatch(keys); @@ -250,36 +247,40 @@ void FuzzCURD(const uint8_t *data, size_t size, KvStoreNbDelegate *kvNbDelegateP kvNbDelegatePtr->CheckIntegrity(); FuzzSetInterceptorTest(kvNbDelegatePtr); if (!keys.empty()) { - bool deleteLocal = (size > 3u) ? (data[0] > data[1]) : true; // use index 0 and 1 - bool updateTimestamp = (size > 3u) ? (data[2] > data[1]) : true; // use index 2 and 1 + bool deleteLocal = fdp.ConsumeBool(); // use index 0 and 1 + bool updateTimestamp = fdp.ConsumeBool(); // use index 2 and 1 /* random deletePublic updateTimestamp 2 */ kvNbDelegatePtr->PublishLocal(keys[0], deleteLocal, updateTimestamp, nullptr); } kvNbDelegatePtr->DeleteBatch(keys); kvNbDelegatePtr->GetTaskCount(); - std::string rawString(reinterpret_cast(data), size); + std::string rawString = fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, MOD)); kvNbDelegatePtr->RemoveDeviceData(rawString); - RemoveDeviceDataByMode(data, size, kvNbDelegatePtr); - GetDeviceEntriesTest(data, size, kvNbDelegatePtr); + RemoveDeviceDataByMode(fdp, kvNbDelegatePtr); + GetDeviceEntriesTest(fdp, kvNbDelegatePtr); } -void EncryptOperation(const uint8_t *data, size_t size, std::string &DirPath, KvStoreNbDelegate *kvNbDelegatePtr) +void EncryptOperation(FuzzedDataProvider &fdp, std::string &DirPath, KvStoreNbDelegate *kvNbDelegatePtr) { if (kvNbDelegatePtr == nullptr) { return; } CipherPassword passwd; - int len = static_cast(std::min(size, size_t(20))); - passwd.SetValue(data, len); + size_t size = fdp.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val = static_cast(new uint8_t[size]); + fdp.ConsumeData(val, size); + passwd.SetValue(val, size); + delete[] static_cast(val); + val = nullptr; kvNbDelegatePtr->Rekey(passwd); - len = static_cast(std::min(size, size_t(100))); // set min 100 - std::string fileName(data, data + len); + int len = fdp.ConsumeIntegralInRange(0, 100); // set min 100 + std::string fileName = fdp.ConsumeRandomLengthString(len); std::string mulitExportFileName = DirPath + "/" + fileName + ".db"; kvNbDelegatePtr->Export(mulitExportFileName, passwd); kvNbDelegatePtr->Import(mulitExportFileName, passwd); } -void CombineTest(const uint8_t *data, size_t size, KvStoreNbDelegate::Option &option) +void CombineTest(FuzzedDataProvider &fdp, KvStoreNbDelegate::Option &option) { static auto kvManager = KvStoreDelegateManager("APP_ID", "USER_ID"); KvStoreConfig config; @@ -292,9 +293,9 @@ void CombineTest(const uint8_t *data, size_t size, KvStoreNbDelegate::Option &op kvNbDelegatePtr = kvNbDelegate; } }); - FuzzCURD(data, size, kvNbDelegatePtr); + FuzzCURD(fdp, kvNbDelegatePtr); if (option.isEncryptedDb) { - EncryptOperation(data, size, config.dataDir, kvNbDelegatePtr); + EncryptOperation(fdp, config.dataDir, kvNbDelegatePtr); } kvManager.CloseKvStore(kvNbDelegatePtr); kvManager.DeleteKvStore("distributed_nb_delegate_test"); @@ -306,8 +307,9 @@ void CombineTest(const uint8_t *data, size_t size, KvStoreNbDelegate::Option &op extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { DistributedDB::KvStoreNbDelegate::Option option = {true, false, false}; - OHOS::CombineTest(data, size, option); + FuzzedDataProvider fdp(data, size); + OHOS::CombineTest(fdp, option); option = {true, true, false}; - OHOS::CombineTest(data, size, option); + OHOS::CombineTest(fdp, option); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn index cdb448f9..a182a25e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("ParseCkeckFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -108,16 +101,14 @@ ohos_fuzztest("ParseCkeckFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/parseckeck_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/parseckeck_fuzzer.cpp index 9ad5ca65..4e119bca 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/parseckeck_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/parseckeck_fuzzer.cpp @@ -15,6 +15,7 @@ #include "parseckeck_fuzzer.h" #include "distributeddb_tools_test.h" +#include "fuzzer/FuzzedDataProvider.h" #include "schema_object.h" #include "schema_utils.h" @@ -24,12 +25,12 @@ using namespace DistributedDBTest; static KvStoreConfig g_config; namespace OHOS { -void GetSchmaKvstore(const uint8_t* data, size_t size) +void GetSchmaKvstore(FuzzedDataProvider &fdp) { static auto kvManager = KvStoreDelegateManager("APP_ID", "USER_ID"); kvManager.SetKvStoreConfig(g_config); KvStoreNbDelegate::Option option = {true, false, false}; - std::string schemaString(reinterpret_cast(data), size); + std::string schemaString = fdp.ConsumeRandomLengthString(); option.schema = schemaString; KvStoreNbDelegate *kvNbDelegatePtr = nullptr; @@ -44,41 +45,41 @@ void GetSchmaKvstore(const uint8_t* data, size_t size) kvManager.DeleteKvStore("distributed_nb_get_schemakvstore"); } -void ParseSchemaString(const uint8_t* data, size_t size) +void ParseSchemaString(FuzzedDataProvider &fdp) { - std::string schemaString(reinterpret_cast(data), size); + std::string schemaString = fdp.ConsumeRandomLengthString(); SchemaObject schemaOri; schemaOri.ParseFromSchemaString(schemaString); schemaOri.CompareAgainstSchemaString(schemaString); } -void CompareSchemaString(const uint8_t* data, size_t size) +void CompareSchemaString(FuzzedDataProvider &fdp) { // beginning half / 2 - std::string schemaString(data, data + (size / 2)); + std::string schemaString = fdp.ConsumeRandomLengthString(); // ending half / 2 ~ end. - std::string schemaString2(data + (size / 2), data + size); + std::string schemaString2 = fdp.ConsumeRandomLengthString(); SchemaObject schemaOri; schemaOri.ParseFromSchemaString(schemaString); schemaOri.ParseFromSchemaString(schemaString2); } -void CheckFieldName(const uint8_t* data, size_t size) +void CheckFieldName(FuzzedDataProvider &fdp) { - std::string schemaAttrString(reinterpret_cast(data), size); + std::string schemaAttrString = fdp.ConsumeRandomLengthString(); SchemaUtils::CheckFieldName(schemaAttrString); } -void ParseFieldPath(const uint8_t* data, size_t size) +void ParseFieldPath(FuzzedDataProvider &fdp) { - std::string schemaAttrString(reinterpret_cast(data), size); + std::string schemaAttrString = fdp.ConsumeRandomLengthString(); FieldPath outPath; SchemaUtils::ParseAndCheckFieldPath(schemaAttrString, outPath); } -void CheckSchemaAttribute(const uint8_t* data, size_t size) +void CheckSchemaAttribute(FuzzedDataProvider &fdp) { - std::string schemaAttrString(reinterpret_cast(data), size); + std::string schemaAttrString = fdp.ConsumeRandomLengthString(); SchemaAttribute outAttr; SchemaUtils::ParseAndCheckSchemaAttribute(schemaAttrString, outAttr); SchemaUtils::ParseAndCheckSchemaAttribute(schemaAttrString, outAttr); @@ -89,12 +90,13 @@ void CheckSchemaAttribute(const uint8_t* data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { DistributedDBToolsTest::TestDirInit(g_config.dataDir); - OHOS::GetSchmaKvstore(data, size); - OHOS::ParseSchemaString(data, size); - OHOS::CompareSchemaString(data, size); - OHOS::CheckFieldName(data, size); - OHOS::ParseFieldPath(data, size); - OHOS::CheckSchemaAttribute(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::GetSchmaKvstore(fdp); + OHOS::ParseSchemaString(fdp); + OHOS::CompareSchemaString(fdp); + OHOS::CheckFieldName(fdp); + OHOS::ParseFieldPath(fdp); + OHOS::CheckSchemaAttribute(fdp); DistributedDBToolsTest::RemoveTestDbFiles(g_config.dataDir); return 0; diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn index a0423aac..6553991c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("QueryFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -108,16 +101,14 @@ ohos_fuzztest("QueryFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/query_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/query_fuzzer.cpp index 11085e24..283c638c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/query_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/query_fuzzer.cpp @@ -15,6 +15,7 @@ #include "query_fuzzer.h" #include "fuzzer_data.h" +#include "fuzzer/FuzzedDataProvider.h" #include "get_query_info.h" using namespace DistributedDB; @@ -25,106 +26,120 @@ namespace { } namespace OHOS { -void FuzzEqualTo(const uint8_t* data, size_t size) +void FuzzEqualTo(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); - Query query = Query::Select().EqualTo(rawString, static_cast(size)); + std::string rawString = provider.ConsumeRandomLengthString(); + int size = provider.ConsumeIntegral(); + Query query = Query::Select().EqualTo(rawString, size); } -void FuzzNotEqualTo(const uint8_t* data, size_t size) +void FuzzNotEqualTo(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); Query query = Query::Select().NotEqualTo(TEST_FIELD_NAME, rawString); } -void FuzzGreaterThan(const uint8_t* data, size_t size) +void FuzzGreaterThan(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); - Query query = Query::Select().GreaterThan(rawString, static_cast(QueryFuzzer::U32_AT(data))); + std::string rawString = provider.ConsumeRandomLengthString(); + int size = provider.ConsumeIntegral(); + Query query = Query::Select().GreaterThan(rawString, size); } -void FuzzLessThan(const uint8_t* data, size_t size) +void FuzzLessThan(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); Query query = Query::Select().LessThan(TEST_FIELD_NAME, rawString); } -void FuzzGreaterThanOrEqualTo(const uint8_t* data, size_t size) +void FuzzGreaterThanOrEqualTo(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); + size_t size = provider.ConsumeIntegral(); Query query = Query::Select().GreaterThanOrEqualTo(rawString, static_cast(size)); } -void FuzzLessThanOrEqualTo(const uint8_t* data, size_t size) +void FuzzLessThanOrEqualTo(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); Query query = Query::Select().LessThanOrEqualTo(TEST_FIELD_NAME, rawString); } -void FuzzOrderBy(const uint8_t* data, size_t size) +void FuzzOrderBy(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); (void)Query::Select().GreaterThanOrEqualTo(rawString, true); (void)Query::Select().GreaterThanOrEqualTo(rawString, false); } -void FuzzLimit(const uint8_t* data, size_t size) +void FuzzLimit(FuzzedDataProvider &provider) { - Query query = Query::Select().Limit(static_cast(size), static_cast(QueryFuzzer::U32_AT(data))); + int size1 = provider.ConsumeIntegral(); + int size2 = provider.ConsumeIntegral(); + Query query = Query::Select().Limit(size1, size2); } -void FuzzLike(const uint8_t* data, size_t size) +void FuzzLike(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); Query query = Query::Select().Like(rawString, rawString); } -void FuzzNotLike(const uint8_t* data, size_t size) +void FuzzNotLike(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); Query query = Query::Select().NotLike(TEST_FIELD_NAME, rawString); } -void FuzzIn(const uint8_t* data, size_t size) +void FuzzIn(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); std::vector values; // 512 max size - for (int i = 0; i < static_cast(QueryFuzzer::U32_AT(data) % 512); i++) { + int maxSize = 512; + int size = provider.ConsumeIntegralInRange(0, maxSize); + for (int i = 0; i < size; i++) { values.push_back(rawString); } Query query = Query::Select().In(TEST_FIELD_NAME, values); } -void FuzzNotIn(const uint8_t* data, size_t size) +void FuzzNotIn(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); std::vector values; // 512 max size - for (int i = 0; i < static_cast(size % 512); i++) { + int maxSize = 512; + int size = provider.ConsumeIntegralInRange(0, maxSize); + for (int i = 0; i < size; i++) { values.push_back(rawString); } Query query = Query::Select().NotIn(TEST_FIELD_NAME, values); } -void FuzzIsNull(const uint8_t* data, size_t size) +void FuzzIsNull(FuzzedDataProvider &provider) { - std::string rawString(reinterpret_cast(data), size); + std::string rawString = provider.ConsumeRandomLengthString(); Query query = Query::Select().IsNull(rawString); } -void FuzzAssetsOnly(const uint8_t *data, size_t size) +void FuzzAssetsOnly(FuzzedDataProvider &provider) { - DistributedDBTest::FuzzerData fuzzerData(data, size); - uint32_t len = fuzzerData.GetUInt32(); const int lenMod = 30; // 30 is mod for string vector size - std::string tableName = fuzzerData.GetString(len % lenMod); - std::string fieldName = fuzzerData.GetString(len % lenMod); + std::string tableName = provider.ConsumeRandomLengthString(provider.ConsumeIntegralInRange(0, lenMod)); + std::string fieldName = provider.ConsumeRandomLengthString(provider.ConsumeIntegralInRange(0, lenMod)); std::map> assets; - assets[fuzzerData.GetString(len % lenMod)] = fuzzerData.GetStringSet(len % lenMod); + std::set set; + // 512 max size + size_t maxSize = 512; + size_t size = provider.ConsumeIntegralInRange(0, maxSize); + for (size_t i = 1; i <= size; i++) { + set.insert(provider.ConsumeRandomLengthString(provider.ConsumeIntegralInRange(0, i))); + } + assets[provider.ConsumeRandomLengthString(provider.ConsumeIntegralInRange(0, lenMod))] = set; Query query = Query::Select().From(tableName) .BeginGroup() - .EqualTo(fieldName, fuzzerData.GetInt()) + .EqualTo(fieldName, provider.ConsumeIntegral()) .And() .AssetsOnly(assets) .EndGroup(); @@ -138,21 +153,22 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) if (size < 4) { return 0; } + FuzzedDataProvider provider(data, size); // Run your code on data - OHOS::FuzzEqualTo(data, size); - OHOS::FuzzNotEqualTo(data, size); - OHOS::FuzzGreaterThan(data, size); - OHOS::FuzzLessThan(data, size); - OHOS::FuzzGreaterThanOrEqualTo(data, size); - OHOS::FuzzLessThanOrEqualTo(data, size); - OHOS::FuzzOrderBy(data, size); - OHOS::FuzzLimit(data, size); - OHOS::FuzzLike(data, size); - OHOS::FuzzNotLike(data, size); - OHOS::FuzzIn(data, size); - OHOS::FuzzNotIn(data, size); - OHOS::FuzzIsNull(data, size); - OHOS::FuzzAssetsOnly(data, size); + OHOS::FuzzEqualTo(provider); + OHOS::FuzzNotEqualTo(provider); + OHOS::FuzzGreaterThan(provider); + OHOS::FuzzLessThan(provider); + OHOS::FuzzGreaterThanOrEqualTo(provider); + OHOS::FuzzLessThanOrEqualTo(provider); + OHOS::FuzzOrderBy(provider); + OHOS::FuzzLimit(provider); + OHOS::FuzzLike(provider); + OHOS::FuzzNotLike(provider); + OHOS::FuzzIn(provider); + OHOS::FuzzNotIn(provider); + OHOS::FuzzIsNull(provider); + OHOS::FuzzAssetsOnly(provider); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn index 97f3b495..4f4ff294 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("ReKeyFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -108,16 +101,14 @@ ohos_fuzztest("ReKeyFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/rekey_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/rekey_fuzzer.cpp index 229b7c26..36ccb87a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/rekey_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/rekey_fuzzer.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "fuzzer/FuzzedDataProvider.h" #include "rekey_fuzzer.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" @@ -22,25 +23,33 @@ using namespace DistributedDBTest; namespace OHOS { static auto g_kvManager = KvStoreDelegateManager("APP_ID", "USER_ID"); -std::vector CreateEntries(const uint8_t* data, size_t size) +static constexpr const int MOD = 1024; // 1024 is mod + +static constexpr const int PASSWDLEN = 20; +std::vector CreateEntries(FuzzedDataProvider &provider) { std::vector entries; - auto count = static_cast(std::min(size, size_t(1024))); + auto count =provider.ConsumeIntegralInRange(0, MOD); for (int i = 1; i < count; i++) { Entry entry; - entry.key = std::vector (data, data + i); - entry.value = std::vector (data, data + size); + entry.key = provider.ConsumeBytes(i); + entry.value = provider.ConsumeBytes(provider.ConsumeIntegral()); entries.push_back(entry); } return entries; } -void SingerVerReKey(const uint8_t* data, size_t size) +void SingerVerReKey(FuzzedDataProvider &provider) { CipherPassword passwd; // div 2 -> half - passwd.SetValue(data, (size / 2)); + size_t size = provider.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val = static_cast(new uint8_t[size]); + provider.ConsumeData(val, size); + passwd.SetValue(val, size); + delete[] static_cast(val); + val = nullptr; KvStoreNbDelegate::Option nbOption = {true, false, true, CipherType::DEFAULT, passwd}; KvStoreNbDelegate *kvNbDelegatePtr = nullptr; @@ -53,18 +62,28 @@ void SingerVerReKey(const uint8_t* data, size_t size) }); if (kvNbDelegatePtr != nullptr) { - kvNbDelegatePtr->PutBatch(CreateEntries(data, size)); - passwd.SetValue(data, size); + kvNbDelegatePtr->PutBatch(CreateEntries(provider)); + size_t size2 = provider.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val2 = static_cast(new uint8_t[size2]); + provider.ConsumeData(val2, size2); + passwd.SetValue(val2, size2); + delete[] static_cast(val2); + val2 = nullptr; kvNbDelegatePtr->Rekey(passwd); g_kvManager.CloseKvStore(kvNbDelegatePtr); } } -void MultiVerVerReKey(const uint8_t* data, size_t size) +void MultiVerVerReKey(FuzzedDataProvider &fdp) { CipherPassword passwd; // div 2 -> half - passwd.SetValue(data, (size / 2)); + size_t size = fdp.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val = static_cast(new uint8_t[size]); + fdp.ConsumeData(val, size); + passwd.SetValue(val, size); + delete[] static_cast(val); + val = nullptr; KvStoreNbDelegate::Option nbOption = {true, false, true, CipherType::DEFAULT, passwd}; KvStoreNbDelegate *kvNbDelegatePtr = nullptr; @@ -77,9 +96,14 @@ void MultiVerVerReKey(const uint8_t* data, size_t size) }); if (kvNbDelegatePtr != nullptr) { - kvNbDelegatePtr->PutBatch(CreateEntries(data, size)); + kvNbDelegatePtr->PutBatch(CreateEntries(fdp)); CipherPassword passwdTwo; - passwdTwo.SetValue(data, size); + size_t size2 = fdp.ConsumeIntegralInRange(0, PASSWDLEN); + uint8_t* val2 = static_cast(new uint8_t[size2]); + fdp.ConsumeData(val2, size2); + passwdTwo.SetValue(val2, size2); + delete[] static_cast(val2); + val2 = nullptr; kvNbDelegatePtr->Rekey(passwdTwo); g_kvManager.CloseKvStore(kvNbDelegatePtr); } @@ -92,8 +116,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) KvStoreConfig config; DistributedDBToolsTest::TestDirInit(config.dataDir); OHOS::g_kvManager.SetKvStoreConfig(config); - OHOS::SingerVerReKey(data, size); - OHOS::MultiVerVerReKey(data, size); + FuzzedDataProvider provider(data, size); + OHOS::SingerVerReKey(provider); + OHOS::MultiVerVerReKey(provider); DistributedDBToolsTest::RemoveTestDbFiles(config.dataDir); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn index 7b09db2d..8a3bf163 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("RelationalstoredelegateFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -112,16 +105,14 @@ ohos_fuzztest("RelationalstoredelegateFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/relationalstoredelegate_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/relationalstoredelegate_fuzzer.cpp index e9f6f191..62339e92 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/relationalstoredelegate_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/relationalstoredelegate_fuzzer.cpp @@ -33,7 +33,7 @@ namespace OHOS { using namespace DistributedDB; using namespace DistributedDBTest; using namespace DistributedDBUnitTest; - +static constexpr const int MOD = 3; constexpr const char *DB_SUFFIX = ".db"; constexpr const char *STORE_ID = "Relational_Store_ID"; const std::string DEVICE_A = "DEVICE_A"; @@ -142,7 +142,7 @@ void TestDistributedSchema(FuzzedDataProvider *fdp) g_delegate->SetDistributedSchema(schema); } -void CombineTest(const uint8_t *data, size_t size) +void CombineTest(FuzzedDataProvider &fdp) { auto observer = new (std::nothrow) DistributedDB::StoreObserver; if (observer == nullptr) { @@ -155,29 +155,25 @@ void CombineTest(const uint8_t *data, size_t size) return; } g_delegate->RegisterObserver(observer); - FuzzerData fuzzerData(data, size); - uint32_t len = fuzzerData.GetUInt32(); - const int lenMod = 30; // 30 is mod for string vector size - std::string tableName = fuzzerData.GetString(len % lenMod); + uint32_t len = fdp.ConsumeIntegral(); + std::string tableName = fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, MOD)); g_delegate->CreateDistributedTable(tableName); - std::vector device = fuzzerData.GetStringVector(len % lenMod); - Query query = Query::Select(); - int index = len % 3; // 3 is the mod - SyncMode mode = SyncMode::SYNC_MODE_PUSH_ONLY; - if (index == 1) { - mode = SyncMode::SYNC_MODE_PULL_ONLY; - } else if (index == 2) { // 2 is the remainder - mode = SyncMode::SYNC_MODE_PUSH_PULL; + std::vector device; + size_t size = fdp.ConsumeIntegralInRange(0, MOD); + for (int i = 0; i < size; i++) { + device.push_back(fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, MOD))); } + Query query = Query::Select(); + SyncMode mode = len % MOD == 1 ? SyncMode::SYNC_MODE_PULL_ONLY : SyncMode::SYNC_MODE_PUSH_PULL; SyncStatusCallback callback = nullptr; g_delegate->Sync(device, mode, query, callback, len % 2); // 2 is mod num for wait parameter g_delegate->GetCloudSyncTaskCount(); - std::set extendColNames = {fuzzerData.GetString(len % lenMod)}; - std::set trackerColNames = fuzzerData.GetStringSet(len % lenMod); - bool isLogicDeleted = static_cast(*data); - FuzzedDataProvider fdp(data, size); - MultiCombineTest(&fdp, tableName, extendColNames, trackerColNames, isLogicDeleted); + std::string extendName = fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, MOD)); + std::set extendColNames = {extendName}; + std::string trackName = fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, MOD)); + std::set trackerColNames = {trackName}; + MultiCombineTest(&fdp, tableName, extendColNames, trackerColNames, fdp.ConsumeBool()); std::string deviceId = device.size() > 0 ? device[0] : tableName; g_delegate->RemoveDeviceData(); g_delegate->RemoveDeviceData(deviceId); @@ -201,7 +197,8 @@ void CombineTest(const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { OHOS::Setup(); - OHOS::CombineTest(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::CombineTest(fdp); OHOS::TearDown(); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn index 6087cf01..46bc9b0e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("RelationalstoremanagerFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -112,16 +105,14 @@ ohos_fuzztest("RelationalstoremanagerFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn index 9d39da2d..4f7911af 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("SchemaDelegateFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ "-g", @@ -108,16 +101,14 @@ ohos_fuzztest("SchemaDelegateFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/BUILD.gn index 40b2edce..9ee04e9a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/BUILD.gn @@ -74,6 +74,7 @@ ohos_fuzztest("StorageFuzzTest") { sources = distributeddb_src sources += distributeddb_cloud_src + sources += distributeddb_client_src sources += [ "../../../test/fuzztest/common/distributeddb_tools_test.cpp", "../../../test/fuzztest/common/fuzzer_data.cpp", @@ -102,16 +103,14 @@ ohos_fuzztest("StorageFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "../../../../distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/project.xml b/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/project.xml index 798d910c..115a0101 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/project.xml +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/project.xml @@ -18,7 +18,7 @@ 1000 - 30 + 1800 4096 diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/storage_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/storage_fuzzer.cpp index 6c34394c..cb45c7ba 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/storage_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/storage_fuzzer.cpp @@ -26,6 +26,7 @@ #include "distributeddb_tools_test.h" #include "log_print.h" #include "fuzzer_data.h" +#include "fuzzer/FuzzedDataProvider.h" #include "relational_store_client.h" #include "relational_store_delegate.h" #include "relational_store_manager.h" @@ -62,7 +63,8 @@ static std::condition_variable g_cv; static bool g_alreadyNotify = false; DistributedDB::StoreObserver::StoreChangedInfo g_changedData; static constexpr const int MOD = 1000; // 1000 is mod -static constexpr const int MODNUM = 10; +static constexpr const int DIVNUM = 10; +static constexpr const int COUNT_MOD = 50000; // 50000 is mod of count class StorageFuzzer { public: @@ -98,14 +100,13 @@ public: } } - void FuzzTest(const uint8_t* data, size_t size) + void FuzzTest(FuzzedDataProvider &fdp) { - FuzzerData fuzzData(data, size); - if (!SetAndGetLocalWaterMark(TABLE_NAME_1, fuzzData.GetUInt64())) { + if (!SetAndGetLocalWaterMark(TABLE_NAME_1, fdp.ConsumeIntegral())) { LOGE("Set and get local watermark unsuccess"); return; } - std::string cloudMark = fuzzData.GetString(size); + std::string cloudMark = fdp.ConsumeRandomLengthString(); if (!SetAndGetCloudWaterMark(TABLE_NAME_1, cloudMark)) { LOGE("Set and get cloud watermark unsuccess"); return; @@ -224,12 +225,12 @@ void TearDown() DistributedDBToolsTest::RemoveTestDbFiles(g_testDir); } -void CombineTest(const uint8_t* data, size_t size) +void CombineTest(FuzzedDataProvider &fdp) { if (g_storageFuzzerTest == nullptr) { return; } - g_storageFuzzerTest->FuzzTest(data, size); + g_storageFuzzerTest->FuzzTest(fdp); } class ClientStoreObserver : public StoreObserver { @@ -269,7 +270,7 @@ void CreateTableForStoreObserver(sqlite3 *db, const std::string &tableName) RdbTestUtils::ExecSql(db, sql); } -void InitLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint64_t num) +void InitLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint32_t num) { for (size_t i = 0; i < num; ++i) { std::string sql = "insert or replace into " + tableName + " VALUES('" + std::to_string(i) + "', 'zhangsan');"; @@ -279,10 +280,10 @@ void InitLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint64_t nu RdbTestUtils::ExecSql(db, sql); } -void InitDataStatus(const std::string &tableName, int count, sqlite3 *db) +void InitDataStatus(const std::string &tableName, uint32_t count, sqlite3 *db) { int type = 4; // the num of different status - for (int i = 1; i <= (type * count) % MODNUM; i++) { + for (uint32_t i = 1; i <= (type * count) / DIVNUM; i++) { std::string sql = "INSERT INTO " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" + std::to_string(i) + "');"; RdbTestUtils::ExecSql(db, sql); @@ -334,7 +335,7 @@ void StoreObserverFuzz(const std::string &tableName) sqlite3_close_v2(db); } -void DropLogicDeletedDataFuzz(std::string tableName, uint64_t num) +void DropLogicDeletedDataFuzz(std::string tableName, uint32_t num) { sqlite3 *db = RdbTestUtils::CreateDataBase(g_dbDir + STOREID + DBSUFFIX); InitLogicDeleteData(db, tableName, num); @@ -342,7 +343,7 @@ void DropLogicDeletedDataFuzz(std::string tableName, uint64_t num) sqlite3_close_v2(db); } -void LockAndUnLockFuzz(std::string tableName, int count) +void LockAndUnLockFuzz(std::string tableName, uint32_t count) { sqlite3 *db = RdbTestUtils::CreateDataBase(g_dbDir + STOREID + DBSUFFIX); InitDataStatus(tableName, count, db); @@ -353,16 +354,15 @@ void LockAndUnLockFuzz(std::string tableName, int count) sqlite3_close_v2(db); } -void CombineClientFuzzTest(const uint8_t *data, size_t size) +void CombineClientFuzzTest(FuzzedDataProvider &fdp) { - FuzzerData fuzzerData(data, size); - uint32_t len = fuzzerData.GetUInt32() % MOD; - std::string tableName = fuzzerData.GetString(len); + uint32_t len = fdp.ConsumeIntegralInRange(0, MOD); + std::string tableName = fdp.ConsumeRandomLengthString(len); ClientObserverFuzz(tableName); StoreObserverFuzz(tableName); - uint64_t num = fuzzerData.GetUInt64(); + uint32_t num = fdp.ConsumeIntegralInRange(0, COUNT_MOD); DropLogicDeletedDataFuzz(tableName, num); - int count = fuzzerData.GetInt(); + uint32_t count = fdp.ConsumeIntegralInRange(0, COUNT_MOD); LockAndUnLockFuzz(tableName, count); } } @@ -371,8 +371,9 @@ void CombineClientFuzzTest(const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { OHOS::Setup(); - OHOS::CombineTest(data, size); - OHOS::CombineClientFuzzTest(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::CombineTest(fdp); + OHOS::CombineClientFuzzTest(fdp); OHOS::TearDown(); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn index 29eaa198..78afaaf7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn @@ -56,14 +56,7 @@ ohos_fuzztest("SyncFuzzTest") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", ] cflags = [ @@ -112,16 +105,14 @@ ohos_fuzztest("SyncFuzzTest") { "USE_DISTRIBUTEDDB_CLOUD", ] - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] + deps = [ "../../../../distributeddb:distributeddb" ] external_deps = [ "c_utils:utils", "hilog:libhilog", + "jsoncpp:jsoncpp", + "openssl:libcrypto_shared", + "sqlite:sqlite", "zlib:shared_libz", ] } diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/sync_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/sync_fuzzer.cpp index 6553bec8..b51ae7a2 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/sync_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/sync_fuzzer.cpp @@ -19,6 +19,7 @@ #include "db_common.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" +#include "fuzzer/FuzzedDataProvider.h" #include "virtual_communicator_aggregator.h" #include "kv_store_nb_delegate.h" #include "kv_virtual_device.h" @@ -28,7 +29,9 @@ namespace OHOS { using namespace DistributedDB; using namespace DistributedDBTest; - +static constexpr const int MOD = 1024; // 1024 is mod +static constexpr const int HUNDRED = 100; +static constexpr const int TEN = 10; /* Keep C++ file names the same as the class name. */ class SyncFuzzer { }; @@ -88,36 +91,37 @@ void TearDownTestCase() } } -std::vector CreateEntries(const uint8_t* data, size_t size, std::vector keys) +std::vector CreateEntries(FuzzedDataProvider &fdp, std::vector keys) { std::vector entries; // key'length is less than 1024. - auto count = static_cast(std::min(size, size_t(1024))); + auto count = fdp.ConsumeIntegralInRange(0, MOD); for (int i = 1; i < count; i++) { Entry entry; - entry.key = std::vector(data, data + i); + entry.key = fdp.ConsumeBytes(1); keys.push_back(entry.key); - entry.value = std::vector(data, data + size); + size_t size = fdp.ConsumeIntegralInRange(0, MOD); + entry.value = fdp.ConsumeBytes(size); entries.push_back(entry); } return entries; } -void NormalSyncPush(const uint8_t* data, size_t size, bool isWithQuery = false) +void NormalSyncPush(FuzzedDataProvider &fdp, bool isWithQuery = false) { SetUpTestcase(); if (g_kvDelegatePtr == nullptr) { return; } std::vector keys; - std::vector tmp = CreateEntries(data, size, keys); + std::vector tmp = CreateEntries(fdp, keys); g_kvDelegatePtr->PutBatch(tmp); std::vector devices; devices.push_back(g_deviceB->GetDeviceId()); std::map result; if (isWithQuery) { - int len = std::min(size, size_t(100)); - Key tmpKey = std::vector(data, data + len); + int len = fdp.ConsumeIntegralInRange(0, MOD); + Key tmpKey = fdp.ConsumeBytes(len); Query query = Query::Select().PrefixKey(tmpKey); DistributedDBToolsTest::SyncTestWithQuery(g_kvDelegatePtr, devices, SYNC_MODE_PUSH_ONLY, result, query); } else { @@ -126,14 +130,14 @@ void NormalSyncPush(const uint8_t* data, size_t size, bool isWithQuery = false) TearDownTestCase(); } -void NormalSyncPull(const uint8_t* data, size_t size, bool isWithQuery = false) +void NormalSyncPull(FuzzedDataProvider &fdp, bool isWithQuery = false) { SetUpTestcase(); if (g_kvDelegatePtr == nullptr) { return; } std::vector keys; - std::vector tmp = CreateEntries(data, size, keys); + std::vector tmp = CreateEntries(fdp, keys); g_kvDelegatePtr->PutBatch(tmp); int i = 0; for (auto &item : tmp) { @@ -149,8 +153,8 @@ void NormalSyncPull(const uint8_t* data, size_t size, bool isWithQuery = false) devices.push_back(g_deviceB->GetDeviceId()); std::map result; if (isWithQuery) { - int len = std::min(size, size_t(100)); - Key tmpKey = std::vector(data, data + len); + int len = fdp.ConsumeIntegralInRange(0, HUNDRED); + Key tmpKey = fdp.ConsumeBytes(len); Query query = Query::Select().PrefixKey(tmpKey); DistributedDBToolsTest::SyncTestWithQuery(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result, query); } else { @@ -159,21 +163,20 @@ void NormalSyncPull(const uint8_t* data, size_t size, bool isWithQuery = false) TearDownTestCase(); } -void NormalSyncPushAndPull(const uint8_t* data, size_t size, bool isWithQuery = false) +void NormalSyncPushAndPull(FuzzedDataProvider &fdp, bool isWithQuery = false) { SetUpTestcase(); if (g_kvDelegatePtr == nullptr) { return; } std::vector keys; - std::vector tmp = CreateEntries(data, size, keys); + std::vector tmp = CreateEntries(fdp, keys); g_kvDelegatePtr->PutBatch(tmp); std::vector devices; devices.push_back(g_deviceB->GetDeviceId()); std::map result; if (isWithQuery) { - int len = std::min(size, size_t(100)); - Key tmpKey = std::vector(data, data + len); + Key tmpKey = fdp.ConsumeBytes(fdp.ConsumeIntegralInRange(0, HUNDRED)); Query query = Query::Select().PrefixKey(tmpKey); DistributedDBToolsTest::SyncTestWithQuery(g_kvDelegatePtr, devices, SYNC_MODE_PUSH_PULL, result, query); } else { @@ -182,7 +185,7 @@ void NormalSyncPushAndPull(const uint8_t* data, size_t size, bool isWithQuery = TearDownTestCase(); } -void SubscribeOperation(const uint8_t* data, size_t size) +void SubscribeOperation(FuzzedDataProvider &fdp) { SetUpTestcase(); if (g_kvDelegatePtr == nullptr) { @@ -193,9 +196,11 @@ void SubscribeOperation(const uint8_t* data, size_t size) Query query2 = Query::Select().EqualTo("$.field_name1", 1).Limit(20, 0); g_kvDelegatePtr->SubscribeRemoteQuery(devices, nullptr, query2, true); std::set keys; - int count = std::min(size, size_t(3)); + int countMax = 3; + int count = fdp.ConsumeIntegralInRange(0, countMax); + int byteLen = 1; for (int i = 0; i < count; i++) { - Key tmpKey = std::vector(data + i, data + i + 1); + Key tmpKey = fdp.ConsumeBytes(byteLen); keys.insert(tmpKey); } Query query = Query::Select().InKeys(keys); @@ -205,49 +210,42 @@ void SubscribeOperation(const uint8_t* data, size_t size) TearDownTestCase(); } -void OtherOperation(const uint8_t* data, size_t size) +void OtherOperation(FuzzedDataProvider &fdp) { SetUpTestcase(); if (g_kvDelegatePtr == nullptr) { return; } - int len = std::min(size, size_t(10)); - std::string tmpIdentifier(data, data + len); + std::string tmpIdentifier = fdp.ConsumeRandomLengthString(TEN); std::vector targets; - int j = 0; - int count = std::min(size, size_t(4)); + int countMax = 4; + int count = fdp.ConsumeIntegralInRange(0, countMax); for (int i = 0; i < count; i++) { - std::string tmpStr(data + j, data + j + 1); - j = j + 10; // target size is 10 + std::string tmpStr = fdp.ConsumeBytesAsString(1); targets.push_back(tmpStr); - if ((1 + j) >= static_cast(size)) { - break; - } } g_kvDelegatePtr->SetEqualIdentifier(tmpIdentifier, targets); TearDownTestCase(); } -void PragmaOperation(const uint8_t* data, size_t size) +void PragmaOperation(FuzzedDataProvider &fdp) { SetUpTestcase(); if (g_kvDelegatePtr == nullptr) { return; } - bool autoSync = (size == 0) ? true : data[0]; + bool autoSync = fdp.ConsumeBool(); PragmaData praData = static_cast(&autoSync); g_kvDelegatePtr->Pragma(AUTO_SYNC, praData); PragmaDeviceIdentifier param1; - int len = std::min(size, size_t(100)); - std::string tmpStr(data, data + len); + std::string tmpStr = fdp.ConsumeRandomLengthString(fdp.ConsumeIntegralInRange(0, HUNDRED)); param1.deviceID = tmpStr; PragmaData input = static_cast(¶m1); g_kvDelegatePtr->Pragma(GET_IDENTIFIER_OF_DEVICE, input); PragmaEntryDeviceIdentifier param2; - len = std::min(size, size_t(10)); // use min 10 - param2.key.assign(data, data + len); + param2.key = fdp.ConsumeBytes(TEN); param2.origDevice = false; input = static_cast(¶m2); g_kvDelegatePtr->Pragma(GET_DEVICE_IDENTIFIER_OF_ENTRY, input); @@ -256,11 +254,7 @@ void PragmaOperation(const uint8_t* data, size_t size) input = static_cast(&size2); g_kvDelegatePtr->Pragma(GET_QUEUED_SYNC_SIZE, input); - int limit = 1; // init 1 - if (size > sizeof(int)) { - auto *r = reinterpret_cast(data); - limit = *r; - } + int limit = fdp.ConsumeIntegral(); input = static_cast(&limit); g_kvDelegatePtr->Pragma(SET_QUEUED_SYNC_LIMIT, input); @@ -270,21 +264,21 @@ void PragmaOperation(const uint8_t* data, size_t size) TearDownTestCase(); } -void FuzzSync(const uint8_t* data, size_t size) +void FuzzSync(FuzzedDataProvider &fdp) { KvStoreConfig config; DistributedDBToolsTest::TestDirInit(config.dataDir); g_mgr.SetKvStoreConfig(config); InitEnv(); - NormalSyncPush(data, size); - NormalSyncPull(data, size); - NormalSyncPushAndPull(data, size); - NormalSyncPush(data, size, true); - NormalSyncPull(data, size, true); - NormalSyncPushAndPull(data, size, true); - SubscribeOperation(data, size); - OtherOperation(data, size); - PragmaOperation(data, size); + NormalSyncPush(fdp); + NormalSyncPull(fdp); + NormalSyncPushAndPull(fdp); + NormalSyncPush(fdp, true); + NormalSyncPull(fdp, true); + NormalSyncPushAndPull(fdp, true); + SubscribeOperation(fdp); + OtherOperation(fdp); + PragmaOperation(fdp); FinalizeEnv(); DistributedDBToolsTest::RemoveTestDbFiles(config.dataDir); } @@ -293,7 +287,8 @@ void FuzzSync(const uint8_t* data, size_t size) /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - OHOS::FuzzSync(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::FuzzSync(fdp); return 0; } diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/moduletest/BUILD.gn index b7349f0c..ba382575 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/BUILD.gn @@ -49,13 +49,9 @@ config("module_private_config") { "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/interfaces/src", # "../adapter/include/communicator", - "//developtools/liblog", "common/distributeddb/include", "include", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata/include", - "//third_party/openssl/include/", ] defines = [ @@ -89,14 +85,15 @@ ohos_moduletest("DistributeddbKvTransactionTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -114,14 +111,15 @@ ohos_moduletest("DistributeddbKvTransactionPerfTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -137,14 +135,15 @@ ohos_moduletest("DistributeddbKvConcurrencyCrudTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -160,14 +159,15 @@ ohos_moduletest("DistributeddbKvBatchCrudTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -183,14 +183,15 @@ ohos_moduletest("DistributeddbKvCreateTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -206,14 +207,15 @@ ohos_moduletest("DistributeddbKvCrudTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -229,14 +231,15 @@ ohos_moduletest("DistributeddbKvObserverTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -252,14 +255,15 @@ ohos_moduletest("DistributeddbKvObserverSnapTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -274,14 +278,15 @@ ohos_moduletest("DistributeddbKvBackupTest") { sources += mul_sources configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -297,14 +302,15 @@ ohos_moduletest("DistributeddbKvRealdelTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -322,14 +328,15 @@ ohos_moduletest("DistributeddbNbCreateTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -346,14 +353,15 @@ ohos_moduletest("DistributeddbNbCrudTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -370,14 +378,15 @@ ohos_moduletest("DistributeddbNbObserverTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -396,14 +405,15 @@ ohos_moduletest("DistributeddbNbCursorTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -422,14 +432,15 @@ ohos_moduletest("DistributeddbNbBackupTest") { deps = [ "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -447,14 +458,15 @@ ohos_moduletest("DistributeddbNbBatchCrudTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -472,14 +484,15 @@ ohos_moduletest("DistributeddbNbLocalBatchCrudTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -496,14 +509,15 @@ ohos_moduletest("DistributeddbNbSchemaDbTest") { sources += mul_sources configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -521,14 +535,15 @@ ohos_moduletest("DistributeddbNbPredicateQueryTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -546,14 +561,15 @@ ohos_moduletest("DistributeddbNbPredicateQueryExpandTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -571,14 +587,15 @@ ohos_moduletest("DistributeddbNbAutolaunchTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -596,14 +613,15 @@ ohos_moduletest("DistributedbNbDbDamageTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -621,14 +639,15 @@ ohos_moduletest("DistributeddbNbCrudPowerTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -646,14 +665,15 @@ ohos_moduletest("DistributeddbNbSchemaTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -671,14 +691,15 @@ ohos_moduletest("DistributeddbNbSchemaUpgradeTest") { configs = [ ":module_private_config" ] deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/googletest:gtest_main", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", + "../../../distributeddb:distributeddb", ] external_deps = [ "c_utils:utils", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "openssl:libcrypto_shared", + "sqlite:sqlite", ] part_name = "datamgr_service" } @@ -686,13 +707,8 @@ ohos_moduletest("DistributeddbNbSchemaUpgradeTest") { ############################################################################### group("moduletest") { testonly = true - deps = [ - "//third_party/googletest:gmock", - "//third_party/googletest:gtest_main", - "//third_party/sqlite:sqlite", - ] - deps += [ + deps = [ ":DistributedbNbDbDamageTest", ":DistributeddbKvBackupTest", ":DistributeddbKvBatchCrudTest", diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/include/distributeddb_data_generator.h b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/include/distributeddb_data_generator.h index e348cc49..a6ebb858 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/include/distributeddb_data_generator.h +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/include/distributeddb_data_generator.h @@ -430,8 +430,8 @@ const std::string IMAGE_VALUE_PRE = {"\"_id\":23,\"local_media_id\":0," \ "\"orientation\":0,\"latitude\":0,\"longitude\":0,\"datetaken\":1514792938000," \ "\"bucket_id\":771419238,\"bucket_display_name\":\"MagazineUnlock\",\"duration\":0," \ "\"resolution\":\"1440x2560\",\"media_type\":1,\"storage_id\":65537,\"width\":1440," \ - "\"height\":2560,\"is_hdr\":0,\"is_hw_privacy\":0,\"hw_voice_offset\":0,\"is_hw_favorite\":0," \ - "\"hw_image_refocus\":0,\"is_hw_burst\":0,\"hw_rectify_offset\":0,\"contenturi\":\"\"," \ + "\"height\":2560,\"is_hdr\":0,\"is_privacy\":0,\"voice_offset\":0,\"is_favorite\":0," \ + "\"image_refocus\":0,\"is_burst\":0,\"rectify_offset\":0,\"contenturi\":\"\"," \ "\"hash\":\"e46cf1bb4773421fbded2e2583fe7130\",\"special_file_list\":0,\"special_file_type\":0," \ "\"special_file_offset\":0,\"relative_bucket_id\":1793967153,\"albumId\":\"default-album-3\",\"fileType\":1," \ "\"fileId\":0,\"videoThumbId\":0,\"thumbId\":0,\"lcdThumbId\":0,\"thumbType\":3,\"localThumbPath\":\"\"," \ diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_constant.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_constant.cpp index 6c3b1187..923b21f4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_constant.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_constant.cpp @@ -16,7 +16,7 @@ #include "distributeddb_nb_test_tools.h" namespace DistributedDBDataGenerator { -#ifndef HW_USING_LABEL_FUNC_IN_RELEASE_VERSION +#ifndef USING_LABEL_FUNC_IN_RELEASE_VERSION const std::string DistributedDBConstant::NB_DIRECTOR = "/data/test/nbstub/"; // default work dir. #else // default work dir by label in phone requested by fbe. diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/basic_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/basic_unit_test.cpp index c775dd24..a7adbc01 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/basic_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/basic_unit_test.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #include "basic_unit_test.h" +#include "platform_specific.h" namespace DistributedDB { using namespace testing::ext; @@ -35,6 +36,11 @@ void BasicUnitTest::TearDownTestCase() void BasicUnitTest::SetUp() { + if (OS::CheckPathExistence(g_testDir)) { // if test dir exist, delete it and printf log + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); + LOGE("[BasicUnitTest] The previous test case not clean db files."); + } + RuntimeContext::GetInstance()->ClearAllDeviceTimeInfo(); DistributedDBToolsUnitTest::PrintTestCaseInfo(); ASSERT_EQ(communicatorAggregator_, nullptr); communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); @@ -48,7 +54,10 @@ void BasicUnitTest::TearDown() LOGE("[BasicUnitTest] Rm test db files error."); } RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAdapter(nullptr); communicatorAggregator_ = nullptr; + RuntimeContext::GetInstance()->ClearAllDeviceTimeInfo(); + RuntimeContext::GetInstance()->SetTimeChanged(false); } int BasicUnitTest::InitDelegate(const StoreInfo &info, const std::string &deviceId) @@ -77,8 +86,10 @@ std::string BasicUnitTest::GetDevice(const StoreInfo &info) const std::lock_guard autoLock(deviceMutex_); auto iter = deviceMap_.find(info); if (iter == deviceMap_.end()) { - LOGW("[BasicUnitTest] Not exist device app %s store %s user %s", info.appId.c_str(), - info.storeId.c_str(), info.userId.c_str()); + LOGW("[BasicUnitTest] Not exist device app %s store %s user %s", + info.appId.c_str(), + info.storeId.c_str(), + info.userId.c_str()); return ""; } return iter->second; @@ -88,7 +99,56 @@ void BasicUnitTest::SetDevice(const StoreInfo &info, const std::string &device) { std::lock_guard autoLock(deviceMutex_); deviceMap_[info] = device; - LOGW("[BasicUnitTest] Set device app %s store %s user %s device %s", info.appId.c_str(), - info.storeId.c_str(), info.userId.c_str(), device.c_str()); + LOGW("[BasicUnitTest] Set device app %s store %s user %s device %s", + info.appId.c_str(), + info.storeId.c_str(), + info.userId.c_str(), + device.c_str()); +} + +StoreInfo BasicUnitTest::GetStoreInfo1() +{ + StoreInfo info; + info.userId = DistributedDBUnitTest::USER_ID; + info.storeId = DistributedDBUnitTest::STORE_ID_1; + info.appId = DistributedDBUnitTest::APP_ID; + return info; +} + +StoreInfo BasicUnitTest::GetStoreInfo2() +{ + StoreInfo info; + info.userId = DistributedDBUnitTest::USER_ID; + info.storeId = DistributedDBUnitTest::STORE_ID_2; + info.appId = DistributedDBUnitTest::APP_ID; + return info; +} + +StoreInfo BasicUnitTest::GetStoreInfo3() +{ + StoreInfo info; + info.userId = DistributedDBUnitTest::USER_ID; + info.storeId = DistributedDBUnitTest::STORE_ID_3; + info.appId = DistributedDBUnitTest::DISTRIBUTED_APP_ID; + return info; +} + +void BasicUnitTest::SetProcessCommunicator(const std::shared_ptr &processCommunicator) +{ + processCommunicator_ = processCommunicator; +} + +uint64_t BasicUnitTest::GetAllSendMsgSize() const +{ + if (communicatorAggregator_ == nullptr) { + return 0u; + } + return communicatorAggregator_->GetAllSendMsgSize(); +} + +void BasicUnitTest::RegBeforeDispatch(const std::function &beforeDispatch) +{ + ASSERT_NE(communicatorAggregator_, nullptr); + communicatorAggregator_->RegBeforeDispatch(beforeDispatch); } -} \ No newline at end of file +} // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/basic_unit_test.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/basic_unit_test.h index 0dfa21ac..240b4ac4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/basic_unit_test.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/basic_unit_test.h @@ -35,17 +35,18 @@ protected: virtual int CloseDelegate(const StoreInfo &info) = 0; virtual void CloseAllDelegate() = 0; std::string GetDevice(const StoreInfo &info) const; + void SetProcessCommunicator(const std::shared_ptr &processCommunicator); + uint64_t GetAllSendMsgSize() const; + void RegBeforeDispatch(const std::function &beforeDispatch); + static StoreInfo GetStoreInfo1(); + static StoreInfo GetStoreInfo2(); + static StoreInfo GetStoreInfo3(); void SetDevice(const StoreInfo &info, const std::string &device); static std::string GetTestDir(); - struct StoreComparator { - bool operator() (const StoreInfo &source, const StoreInfo &target) const - { - return source.userId < target.userId || source.appId < target.appId || source.storeId < target.storeId; - } - }; VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; + std::shared_ptr processCommunicator_ = nullptr; mutable std::mutex deviceMutex_; - std::map deviceMap_; + std::map deviceMap_; }; } #endif // BASIC_UNIT_TEST_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_auto_launch_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_auto_launch_test.cpp index 080be572..1e321405 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_auto_launch_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_auto_launch_test.cpp @@ -201,7 +201,7 @@ static void SetLifeCycleTime(const KvDBProperties &prop) * @tc.name: AutoLaunch001 * @tc.desc: basic enable/disable func * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch001, TestSize.Level3) @@ -256,7 +256,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch001, TestSize.Level3) * @tc.name: AutoLaunch002 * @tc.desc: online callback * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch002, TestSize.Level3) @@ -333,7 +333,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch002, TestSize.Level3) * @tc.name: AutoLaunch003 * @tc.desc: CommunicatorLackCallback * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch003, TestSize.Level3) @@ -410,7 +410,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch003, TestSize.Level3) * @tc.name: AutoLaunch004 * @tc.desc: basic enable/disable func * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch004, TestSize.Level3) @@ -477,7 +477,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch004, TestSize.Level3) * @tc.name: AutoLaunch005 * @tc.desc: online device before enable * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch005, TestSize.Level3) @@ -549,7 +549,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch005, TestSize.Level3) * @tc.name: AutoLaunch006 * @tc.desc: online callback * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch006, TestSize.Level3) @@ -662,7 +662,7 @@ bool AutoLaunchCallBackBadParam(const std::string &identifier, AutoLaunchParam & * @tc.name: AutoLaunch007 * @tc.desc: enhancement callback return true * @tc.type: FUNC - * @tc.require: AR000EPARJ + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch007, TestSize.Level3) @@ -726,7 +726,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch007, TestSize.Level3) * @tc.name: AutoLaunch008 * @tc.desc: enhancement callback return false * @tc.type: FUNC - * @tc.require: AR000EPARJ + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch008, TestSize.Level3) @@ -765,7 +765,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch008, TestSize.Level3) * @tc.name: AutoLaunch009 * @tc.desc: enhancement callback return bad param * @tc.type: FUNC - * @tc.require: AR000EPARJ + * @tc.require: */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch009, TestSize.Level3) { @@ -806,7 +806,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch009, TestSize.Level3) * @tc.name: AutoLaunch010 * @tc.desc: enhancement nullptr callback * @tc.type: FUNC - * @tc.require: AR000EPARJ + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch010, TestSize.Level3) @@ -846,7 +846,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch010, TestSize.Level3) * @tc.name: AutoLaunch011 * @tc.desc: enhancement GetKvStoreIdentifier * @tc.type: FUNC - * @tc.require: AR000EPARJ + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch011, TestSize.Level3) @@ -863,7 +863,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch011, TestSize.Level3) * @tc.name: AutoLaunch012 * @tc.desc: CommunicatorLackCallback * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch012, TestSize.Level3) @@ -937,7 +937,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch012, TestSize.Level3) * @tc.name: AutoLaunch013 * @tc.desc: online callback * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch013, TestSize.Level3) @@ -1023,7 +1023,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch013, TestSize.Level3) * @tc.name: AutoLaunch014 * @tc.desc: enhancement callback and release auto launch connection * @tc.type: FUNC - * @tc.require: AR000I0EKP + * @tc.require: */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch014, TestSize.Level3) { @@ -1075,7 +1075,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch014, TestSize.Level3) * @tc.name: AutoLaunch015 * @tc.desc: release auto launch connection when autolaunch execute * @tc.type: FUNC - * @tc.require: AR000I0EKP + * @tc.require: */ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch015, TestSize.Level3) { @@ -1152,3 +1152,32 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunchRelational001, TestSize.Leve mode = std::static_pointer_cast(ptr)->GetDistributedTableMode(); EXPECT_EQ(mode, DistributedTableMode::COLLABORATION); } + +void GetAutoLaunchPropertiesTest(DBTypeInner type) +{ + AutoLaunchOption defaultOption; + defaultOption.compressionRate = 100; // compress rate is 100 + AutoLaunchParam param = {USER_ID, APP_ID, STORE_ID_0, defaultOption, nullptr, "", ""}; + std::shared_ptr ptr; + int errCode = AutoLaunch::GetAutoLaunchProperties(param, type, false, ptr); + ASSERT_EQ(errCode, E_OK); + ASSERT_NE(ptr, nullptr); + EXPECT_EQ(ptr->GetIntProp(DBProperties::COMPRESSION_RATE, 0), 0); + param.option.isNeedCompressOnSync = true; + errCode = AutoLaunch::GetAutoLaunchProperties(param, type, false, ptr); + ASSERT_EQ(errCode, E_OK); + ASSERT_NE(ptr, nullptr); + EXPECT_EQ(ptr->GetIntProp(DBProperties::COMPRESSION_RATE, 0), defaultOption.compressionRate); +} + +/** + * @tc.name: GetAutoLaunchProperties001 + * @tc.desc: test GetAutoLaunchProperties will give back the correct tableMode + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBAutoLaunchUnitTest, GetAutoLaunchProperties001, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(GetAutoLaunchPropertiesTest(DBTypeInner::DB_KV)); + ASSERT_NO_FATAL_FAILURE(GetAutoLaunchPropertiesTest(DBTypeInner::DB_RELATION)); +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp index 797bb30b..468af7d1 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp @@ -78,7 +78,7 @@ void DistributedDBCommonTest::TearDown(void) * @tc.name: RemoveAllFilesOfDirectory * @tc.desc: Test delete all file and dir. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, RemoveAllFilesOfDirectory, TestSize.Level1) @@ -118,7 +118,7 @@ HWTEST_F(DistributedDBCommonTest, InvalidArgsTest001, TestSize.Level1) * @tc.name: SameProcessReLockFile * @tc.desc: Test same process repeat lock same file. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, SameProcessReLockFile, TestSize.Level1) @@ -149,7 +149,7 @@ HWTEST_F(DistributedDBCommonTest, SameProcessReLockFile, TestSize.Level1) * @tc.name: SameProcessReUnLockFile * @tc.desc: Test same process repeat lock same file. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, SameProcessReUnLockFile, TestSize.Level1) @@ -175,7 +175,7 @@ HWTEST_F(DistributedDBCommonTest, SameProcessReUnLockFile, TestSize.Level1) * @tc.name: CalcFileSizeTest * @tc.desc: Test the file size for function test and the performance test. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBCommonTest, CalcFileSizeTest, TestSize.Level1) @@ -216,7 +216,7 @@ void createStepFlag(int step) * @tc.name: DiffProcessLockFile * @tc.desc: Test different process repeat lock same file. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, DiffProcessLockFile, TestSize.Level1) @@ -251,7 +251,7 @@ HWTEST_F(DistributedDBCommonTest, DiffProcessLockFile, TestSize.Level1) * @tc.name: DiffProcessLockFileBlocked * @tc.desc: Test different process repeat lock same file. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, DiffProcessLockFileBlocked, TestSize.Level1) @@ -293,7 +293,7 @@ HWTEST_F(DistributedDBCommonTest, DiffProcessLockFileBlocked, TestSize.Level1) * @tc.name: DiffProcessGetDBBlocked * @tc.desc: Test block other process get kvstore when db locked. * @tc.type: FUNC - * @tc.require: AR000CQDV7 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, DiffProcessGetDBBlocked, TestSize.Level1) @@ -338,7 +338,7 @@ HWTEST_F(DistributedDBCommonTest, DiffProcessGetDBBlocked, TestSize.Level1) * @tc.name: DiffProcessDeleteDBBlocked * @tc.desc: Test block other process delete kvstore when db locked. * @tc.type: FUNC - * @tc.require: AR000CQDV7 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, DiffProcessDeleteDBBlocked, TestSize.Level1) @@ -386,7 +386,7 @@ HWTEST_F(DistributedDBCommonTest, DiffProcessDeleteDBBlocked, TestSize.Level1) * @tc.name: DiffProcessGetDBBlocked001 * @tc.desc: Test block other process get kvstore when db locked. * @tc.type: FUNC - * @tc.require: AR000CQDV7 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, DiffProcessGetDBBlocked001, TestSize.Level1) @@ -432,7 +432,7 @@ HWTEST_F(DistributedDBCommonTest, DiffProcessGetDBBlocked001, TestSize.Level1) * @tc.name: DiffProcessGetDB * @tc.desc: Test block other process get kvstore. * @tc.type: FUNC - * @tc.require: AR000CQDV7 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, DiffProcessGetDB, TestSize.Level1) @@ -467,7 +467,7 @@ HWTEST_F(DistributedDBCommonTest, DiffProcessGetDB, TestSize.Level1) * @tc.name: DiffProcessDeleteDB * @tc.desc: Test block other process delete kvstore. * @tc.type: FUNC - * @tc.require: AR000CQDV7 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, DiffProcessDeleteDB, TestSize.Level1) @@ -505,7 +505,7 @@ HWTEST_F(DistributedDBCommonTest, DiffProcessDeleteDB, TestSize.Level1) * @tc.name: DiffProcessGetAndDeleteDB * @tc.desc: Test block other process delete kvstore. * @tc.type: FUNC - * @tc.require: AR000CQDV7 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBCommonTest, DiffProcessGetAndDeleteDB, TestSize.Level1) @@ -567,7 +567,7 @@ HWTEST_F(DistributedDBCommonTest, PerformanceAnalysisTest001, TestSize.Level1) t1.join(); t2.join(); } - EXPECT_EQ(count1, count1); + EXPECT_EQ(count2, threadCount); EXPECT_EQ(count1, threadCount); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_compression_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_compression_test.cpp index 1d48c7a6..204da2a7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_compression_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_compression_test.cpp @@ -80,7 +80,7 @@ void DistributedDBDataCompressionTest::TearDown(void) * @tc.name: DataCompression1 * @tc.desc: To test the function compress and uncompress works well in normal situation. * @tc.type: FUNC - * @tc.require: AR000G3QTT + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBDataCompressionTest, DataCompression1, TestSize.Level1) @@ -112,7 +112,7 @@ HWTEST_F(DistributedDBDataCompressionTest, DataCompression1, TestSize.Level1) * @tc.name: DataCompression2 * @tc.desc: To test uncompress failed when compressed is destroyed. * @tc.type: FUNC - * @tc.require: AR000G3QTT + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBDataCompressionTest, DataCompression2, TestSize.Level1) @@ -149,7 +149,7 @@ HWTEST_F(DistributedDBDataCompressionTest, DataCompression2, TestSize.Level1) * @tc.desc: To test uncompress works when bufferLen is larger but under 30M limit, and uncompress failed when bufferLen is beyond the 30M limit. * @tc.type: FUNC - * @tc.require: AR000G3QTT + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBDataCompressionTest, DataCompression3, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.h index 259d7a48..e1901797 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.h @@ -24,6 +24,7 @@ namespace DistributedDBUnitTest { // define some variables to init a KvStoreDelegateManager object. const std::string APP_ID = "app0"; +const std::string DISTRIBUTED_APP_ID = "distributeddata"; const std::string SCHEMA_APP_ID = "app1"; const std::string USER_ID = "user0"; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_json_precheck_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_json_precheck_unit_test.cpp index 2182da8b..b445cadd 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_json_precheck_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_json_precheck_unit_test.cpp @@ -92,7 +92,7 @@ void DistributedDBJsonPrecheckUnitTest::SetUp() * @tc.name: Precheck Valid String 001 * @tc.desc: json string is legal * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseValidString001, TestSize.Level1) @@ -111,15 +111,20 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseValidString001, TestSize.Level1 * @tc.expected: step2. Parsing result failed. */ JsonObject tempObj; + LOGI("ori json is %s", JSON_STRING1.c_str()); int stepTwo = tempObj.Parse(JSON_STRING1); EXPECT_TRUE(stepTwo != E_OK); + std::string json = R"([{"field1":"123"}])"; + std::vector data(json.begin(), json.end()); + EXPECT_EQ(tempObj.Parse(data), -E_JSON_PARSE_FAIL); + EXPECT_EQ(tempObj.Parse(json), -E_JSON_PARSE_FAIL); } /** * @tc.name: Precheck Valid String 002 * @tc.desc: json string is legal * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseValidString002, TestSize.Level1) @@ -138,6 +143,7 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseValidString002, TestSize.Level1 * @tc.expected: step2. Parsing result success. */ JsonObject tempObj; + LOGI("ori json is %s", JSON_STRING3.c_str()); int stepTwo = tempObj.Parse(JSON_STRING3); EXPECT_TRUE(stepTwo == E_OK); } @@ -146,7 +152,7 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseValidString002, TestSize.Level1 * @tc.name: Precheck invalid String 001 * @tc.desc: The json string has been detected illegal before exceeding the specified nesting depth. * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString001, TestSize.Level1) @@ -156,6 +162,7 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString001, TestSize.Leve * @tc.expected: step1. Parsing result failed. */ JsonObject tempObj; + LOGI("ori json is %s", JSON_STRING2.c_str()); int stepOne = tempObj.Parse(JSON_STRING2); EXPECT_TRUE(stepOne != E_OK); } @@ -164,7 +171,7 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString001, TestSize.Leve * @tc.name: Precheck invalid String 002 * @tc.desc: The json string has been detected illegal before exceeding the specified nesting depth. * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString002, TestSize.Level1) @@ -174,6 +181,7 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString002, TestSize.Leve * @tc.expected: step1. Parsing result failed. */ JsonObject tempObj; + LOGI("ori json is %s", JSON_STRING4.c_str()); int stepOne = tempObj.Parse(JSON_STRING4); EXPECT_TRUE(stepOne != E_OK); } @@ -182,7 +190,7 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString002, TestSize.Leve * @tc.name: Precheck invalid String 003 * @tc.desc: The json string has been detected illegal before exceeding the specified nesting depth. * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString003, TestSize.Level1) @@ -192,6 +200,7 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString003, TestSize.Leve * @tc.expected: step1. return value > 10. */ int errCode = E_OK; + LOGI("ori json is %s", JSON_STRING5.c_str()); int stepOne = static_cast(JsonObject::CalculateNestDepth(JSON_STRING5, errCode)); EXPECT_TRUE(errCode == E_OK); EXPECT_TRUE(stepOne > MAX_DEPTH_FOR_TEST); @@ -204,4 +213,244 @@ HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseInvalidString003, TestSize.Leve int stepTwo = tempObj.Parse(JSON_STRING5); EXPECT_TRUE(stepTwo != E_OK); } + +/** + * @tc.name: ParseDuplicativeString001 + * @tc.desc: The json string has more than one field with same name. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseDuplicativeString001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Parse json. + * @tc.expected: step1. return ok. + */ + std::string json = R"({"field1":"123", "field2": true, "field1": 123})"; + LOGI("ori json is %s", json.c_str()); + JsonObject object; + EXPECT_EQ(object.JsonObject::Parse(json), E_OK); + /** + * @tc.steps: step2. Check field. + * @tc.expected: step2. field1 is 123, field2 is True. + */ + FieldValue value; + EXPECT_EQ(object.GetFieldValueByFieldPath({"field1"}, value), E_OK); + EXPECT_EQ(value.integerValue, 123); + EXPECT_EQ(object.GetFieldValueByFieldPath({"field2"}, value), E_OK); + EXPECT_TRUE(value.boolValue); +} + +/** + * @tc.name: ParseString001 + * @tc.desc: Parse none obj json string. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseString001, TestSize.Level0) +{ + std::string nonJson = R"("field1":123)"; + LOGI("ori json is %s", nonJson.c_str()); + JsonObject object; + std::vector data(nonJson.begin(), nonJson.end()); + EXPECT_EQ(object.Parse(data), -E_JSON_PARSE_FAIL); + EXPECT_TRUE(object.ToString().empty()); +} + +/** + * @tc.name: ParseString002 + * @tc.desc: Parse double and long. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseString002, TestSize.Level0) +{ + std::string json = R"({"field1":429496729500, "field2":11.1})"; + LOGI("ori json is %s", json.c_str()); + JsonObject object; + std::vector data(json.begin(), json.end()); + EXPECT_EQ(object.Parse(data), E_OK); + FieldValue value; + EXPECT_EQ(object.GetFieldValueByFieldPath({"field1"}, value), E_OK); + EXPECT_EQ(value.longValue, 429496729500); + EXPECT_EQ(object.GetFieldValueByFieldPath({"field2"}, value), E_OK); + EXPECT_NE(value.doubleValue, 0); +} + +/** + * @tc.name: ParseString003 + * @tc.desc: Parse obj. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseString003, TestSize.Level0) +{ + std::string json = R"({"field1":42949672950, "field2":{"field3":123}})"; + LOGI("ori json is %s", json.c_str()); + JsonObject object; + std::vector data(json.begin(), json.end()); + EXPECT_EQ(object.Parse(data), E_OK); + std::set outSubPath; + std::map outSubPathType; + EXPECT_EQ(object.GetSubFieldPath({"field1"}, outSubPath), -E_NOT_SUPPORT); + EXPECT_EQ(object.GetSubFieldPathAndType({"field1"}, outSubPathType), -E_NOT_SUPPORT); + EXPECT_EQ(object.GetSubFieldPath({"field2"}, outSubPath), E_OK); + EXPECT_EQ(object.GetSubFieldPathAndType({"field2"}, outSubPathType), E_OK); + std::set actualPath = {{"field2", "field3"}}; + EXPECT_EQ(outSubPath, actualPath); + FieldPath inPath; + EXPECT_EQ(object.GetSubFieldPath(inPath, outSubPath), E_OK); + EXPECT_EQ(object.GetSubFieldPathAndType(inPath, outSubPathType), E_OK); +} + +/** + * @tc.name: ParseString004 + * @tc.desc: Parse array. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseString004, TestSize.Level0) +{ + std::string json = R"({"field1":["123"], "field3":"field3"})"; + LOGI("ori json is %s", json.c_str()); + JsonObject object; + std::vector data(json.begin(), json.end()); + EXPECT_EQ(object.Parse(data), E_OK); + size_t size = 0u; + EXPECT_EQ(object.GetArraySize({"field3"}, size), -E_NOT_SUPPORT); + EXPECT_EQ(object.GetArraySize({"field1"}, size), E_OK); + EXPECT_EQ(size, 1u); + FieldPath inPath; + EXPECT_EQ(object.GetArraySize(inPath, size), -E_NOT_SUPPORT); + std::vector> content; + EXPECT_EQ(object.GetArrayContentOfStringOrStringArray({"field1"}, content), E_OK); + std::vector> actual = {{"123"}}; + EXPECT_EQ(content, actual); + EXPECT_EQ(object.GetArrayContentOfStringOrStringArray(inPath, content), -E_NOT_SUPPORT); +} + +/** + * @tc.name: ParseString005 + * @tc.desc: Parse array. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, ParseString005, TestSize.Level0) +{ + std::string json = R"({"field1":["123", null, ["456", 789]], "field3":"field3"})"; + LOGI("ori json is %s", json.c_str()); + JsonObject object; + EXPECT_EQ(object.Parse(json), E_OK); + std::vector> content; + EXPECT_EQ(object.GetArrayContentOfStringOrStringArray({"field1"}, content), -E_NOT_SUPPORT); + + json = R"({"field1":[["456", "789"], []], "field3":"field3"})"; + object = {}; + EXPECT_EQ(object.Parse(json), E_OK); + EXPECT_EQ(object.GetArrayContentOfStringOrStringArray({"field1"}, content), E_OK); + EXPECT_EQ(content.size(), 1u); +} + +/** + * @tc.name: BuildObj001 + * @tc.desc: Build json obj. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, BuildObj001, TestSize.Level0) +{ + LOGI("ori json is empty"); + JsonObject obj; + FieldValue val; + val.boolValue = true; + EXPECT_EQ(obj.InsertField({"bool_field"}, FieldType::LEAF_FIELD_BOOL, val), E_OK); + val.stringValue = "str"; + EXPECT_EQ(obj.InsertField({"str_field"}, FieldType::LEAF_FIELD_STRING, val), E_OK); + val.integerValue = INT32_MAX; + EXPECT_EQ(obj.InsertField({"int_field"}, FieldType::LEAF_FIELD_INTEGER, val), E_OK); + val.longValue = INT64_MAX; + EXPECT_EQ(obj.InsertField({"long_field"}, FieldType::LEAF_FIELD_LONG, val), E_OK); + val.doubleValue = 3.1415; + EXPECT_EQ(obj.InsertField({"double_field"}, FieldType::LEAF_FIELD_DOUBLE, val), E_OK); + EXPECT_EQ(obj.InsertField({"null_field"}, FieldType::LEAF_FIELD_NULL, val), E_OK); + EXPECT_EQ(obj.InsertField({"array_field"}, FieldType::LEAF_FIELD_ARRAY, val), -E_INVALID_ARGS); + EXPECT_EQ(obj.InsertField({"obj_field"}, FieldType::LEAF_FIELD_OBJECT, val), E_OK); + EXPECT_EQ(obj.InsertField({"array_field"}, FieldType::LEAF_FIELD_OBJECT, val), E_OK); + EXPECT_EQ(obj.InsertField({"array_field", "array_inner"}, FieldType::LEAF_FIELD_OBJECT, val), E_OK); + EXPECT_EQ(obj.InsertField({"array_field", "array_inner", "inner"}, FieldType::LEAF_FIELD_OBJECT, val), E_OK); + EXPECT_EQ(obj.DeleteField({"obj_field"}), E_OK); + LOGI("json is %s", obj.ToString().c_str()); +} + +/** + * @tc.name: BuildObj002 + * @tc.desc: Build json obj. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, BuildObj002, TestSize.Level0) +{ + std::string json = R"({"array_field":[]})"; + LOGI("ori json is %s", json.c_str()); + JsonObject obj; + EXPECT_EQ(obj.Parse(json), E_OK); + FieldValue val; + val.stringValue = "str"; + EXPECT_EQ(obj.InsertField({"array_field1"}, FieldType::LEAF_FIELD_STRING, val, true), E_OK); + EXPECT_EQ(obj.InsertField({"array_field2"}, FieldType::LEAF_FIELD_STRING, val), E_OK); + EXPECT_EQ(obj.InsertField({"array_field"}, FieldType::LEAF_FIELD_STRING, val, true), E_OK); + EXPECT_EQ(obj.InsertField({"array_field"}, FieldType::LEAF_FIELD_STRING, val), E_OK); + LOGI("json is %s", obj.ToString().c_str()); +} + +/** + * @tc.name: BuildObj003 + * @tc.desc: Build json obj by insert invalid obj. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, BuildObj003, TestSize.Level0) +{ + JsonObject invalidOriObj; + JsonObject invalidInsertObj; + EXPECT_EQ(invalidOriObj.InsertField({}, invalidInsertObj), -E_INVALID_ARGS); + JsonObject validInsertObj; + std::string json = R"({"field1":"field1Val"})"; + validInsertObj.Parse(json); + EXPECT_EQ(invalidOriObj.InsertField({}, validInsertObj), -E_INVALID_ARGS); + FieldPath invalidPath; + invalidPath.resize(101); // 101 is invalid depth + EXPECT_EQ(invalidOriObj.InsertField(invalidPath, invalidInsertObj), -E_INVALID_ARGS); + EXPECT_EQ(invalidOriObj.InsertField(invalidPath, validInsertObj), -E_INVALID_ARGS); +} + +/** + * @tc.name: BuildObj004 + * @tc.desc: Build json valid obj by insert valid obj. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBJsonPrecheckUnitTest, BuildObj004, TestSize.Level0) +{ + JsonObject validOriObj; + std::string json = R"({"field1":"field1Val", "array":[]})"; + validOriObj.Parse(json); + JsonObject insertVal; + insertVal.Parse(json); + EXPECT_EQ(validOriObj.InsertField({"field2"}, insertVal), E_OK); + JsonObject inValidOriObj; + EXPECT_EQ(inValidOriObj.InsertField({"field2"}, insertVal), E_OK); + EXPECT_EQ(validOriObj.InsertField({"array"}, insertVal), E_OK); + EXPECT_EQ(validOriObj.InsertField({"array"}, insertVal, false), E_OK); + EXPECT_EQ(validOriObj.InsertField({"field3"}, insertVal, false), E_OK); + EXPECT_EQ(validOriObj.InsertField({"field1"}, insertVal), -E_JSON_INSERT_PATH_EXIST); +} #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_notification_chain_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_notification_chain_test.cpp index 7208d445..d55f8dfb 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_notification_chain_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_notification_chain_test.cpp @@ -100,7 +100,7 @@ void DistributedDBNotificationChainTest::TearDown(void) * @tc.name: RegisterEvent001 * @tc.desc: Register an exits event. * @tc.type: FUNC - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBNotificationChainTest, RegisterEvent001, TestSize.Level0) @@ -117,7 +117,7 @@ HWTEST_F(DistributedDBNotificationChainTest, RegisterEvent001, TestSize.Level0) * @tc.name: RegisterListener001 * @tc.desc: Register and unregister a listener. * @tc.type: FUNC - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBNotificationChainTest, RegisterListener001, TestSize.Level0) @@ -144,7 +144,7 @@ HWTEST_F(DistributedDBNotificationChainTest, RegisterListener001, TestSize.Level * @tc.name: NotifyEvent001 * @tc.desc: notify an event to listener. * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBNotificationChainTest, NotifyEvent001, TestSize.Level0) @@ -172,7 +172,7 @@ HWTEST_F(DistributedDBNotificationChainTest, NotifyEvent001, TestSize.Level0) * @tc.name: UnRegisterEvent001 * @tc.desc: unregister a invalid event. * @tc.type: FUNC - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBNotificationChainTest, UnRegisterEvent001, TestSize.Level0) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_parcel_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_parcel_unit_test.cpp index 4a95864e..d57d4dec 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_parcel_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_parcel_unit_test.cpp @@ -53,7 +53,7 @@ void DistributedDBParcelTest::TearDown(void) * @tc.name: WriteInt001 * @tc.desc: write and read a integer. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteInt001, TestSize.Level1) @@ -110,7 +110,7 @@ HWTEST_F(DistributedDBParcelTest, WriteInt001, TestSize.Level1) * @tc.name: WriteVector001 * @tc.desc: write and read a vector. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector001, TestSize.Level1) @@ -145,7 +145,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector001, TestSize.Level1) * @tc.name: WriteVector002 * @tc.desc: write and read an empty vector. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector002, TestSize.Level1) @@ -180,7 +180,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector002, TestSize.Level1) * @tc.name: WriteVector003 * @tc.desc: write and read a vector. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector003, TestSize.Level1) @@ -215,7 +215,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector003, TestSize.Level1) * @tc.name: WriteVector004 * @tc.desc: write and read an empty vector. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector004, TestSize.Level1) @@ -250,7 +250,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector004, TestSize.Level1) * @tc.name: WriteVector005 * @tc.desc: write and read a vector. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector005, TestSize.Level1) @@ -286,7 +286,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector005, TestSize.Level1) * @tc.name: WriteVector006 * @tc.desc: write and read an empty vector. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector006, TestSize.Level1) @@ -321,7 +321,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector006, TestSize.Level1) * @tc.name: WriteVector007 * @tc.desc: write and read a vector, insert a wrong len. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector007, TestSize.Level1) @@ -361,7 +361,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector007, TestSize.Level1) * @tc.name: WriteVector008 * @tc.desc: write and read a vector, insert a wrong len. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector008, TestSize.Level1) @@ -401,7 +401,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector008, TestSize.Level1) * @tc.name: WriteVector009 * @tc.desc: write and read a vector, insert a wrong len. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector009, TestSize.Level1) @@ -443,7 +443,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector009, TestSize.Level1) * @tc.name: WriteVector010 * @tc.desc: write and read a vector, vector len is INT_MAX. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteVector010, TestSize.Level2) @@ -469,7 +469,7 @@ HWTEST_F(DistributedDBParcelTest, WriteVector010, TestSize.Level2) * @tc.name: WriteString001 * @tc.desc: write and read a string normally. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteString001, TestSize.Level1) @@ -503,7 +503,7 @@ HWTEST_F(DistributedDBParcelTest, WriteString001, TestSize.Level1) * @tc.name: WriteString002 * @tc.desc: write and read a string, insert a wrong len. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteString002, TestSize.Level1) @@ -543,7 +543,7 @@ HWTEST_F(DistributedDBParcelTest, WriteString002, TestSize.Level1) * @tc.name: WriteString003 * @tc.desc: write and read a string, insert a wrong len. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteString003, TestSize.Level1) @@ -583,7 +583,7 @@ HWTEST_F(DistributedDBParcelTest, WriteString003, TestSize.Level1) * @tc.name: WriteString004 * @tc.desc: write and read a string, string is empty. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteString004, TestSize.Level1) @@ -617,7 +617,7 @@ HWTEST_F(DistributedDBParcelTest, WriteString004, TestSize.Level1) * @tc.name: WriteString005 * @tc.desc: write and read a string, insert a INT_MAX len. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteString005, TestSize.Level1) @@ -657,7 +657,7 @@ HWTEST_F(DistributedDBParcelTest, WriteString005, TestSize.Level1) * @tc.name: WriteString006 * @tc.desc: write and read a string, string size is INT_MAX. * @tc.type: FUNC - * @tc.require: AR000CQE0U + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBParcelTest, WriteString006, TestSize.Level2) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp index e1ea4bc8..31f6b798 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp @@ -291,7 +291,7 @@ void DistributedDBRelationalSchemaObjectTest::TearDown() * @tc.name: RelationalSchemaParseTest001 * @tc.desc: Test relational schema parse from json string * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest001, TestSize.Level1) @@ -319,7 +319,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest001, * @tc.name: RelationalSchemaParseTest002 * @tc.desc: Test relational schema parse from invalid json string * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest002, TestSize.Level1) @@ -385,7 +385,7 @@ std::string GenerateFromTableStr(const std::string &tableStr) * @tc.name: RelationalSchemaParseTest003 * @tc.desc: Test relational schema parse from invalid json string * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest003, TestSize.Level1) @@ -534,7 +534,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest007, * @tc.name: RelationalSchemaCompareTest001 * @tc.desc: Test relational schema negotiate with same schema string * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest001, TestSize.Level1) @@ -554,7 +554,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest001 * @tc.name: RelationalSchemaCompareTest002 * @tc.desc: Test relational schema v2.1 negotiate with same schema string * @tc.type: FUNC - * @tc.require: AR000H2PKN + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest002, TestSize.Level1) @@ -574,7 +574,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest002 * @tc.name: RelationalSchemaCompareTest003 * @tc.desc: Test relational schema v2.1 negotiate with schema v2.0 * @tc.type: FUNC - * @tc.require: AR000H2PKN + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest003, TestSize.Level1) @@ -592,7 +592,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest003 * @tc.name: RelationalSchemaCompareTest004 * @tc.desc: Test relational schema v2.0 negotiate with schema v2.1 * @tc.type: FUNC - * @tc.require: AR000H2PKN + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest004, TestSize.Level1) @@ -610,7 +610,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest004 * @tc.name: RelationalSchemaCompareTest005 * @tc.desc: Test collaboration relational schema negotiate with other table mode * @tc.type: FUNC - * @tc.require: AR000H2PKN + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest005, TestSize.Level1) @@ -629,7 +629,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest005 * @tc.name: RelationalTableCompareTest001 * @tc.desc: Test relational schema negotiate with same schema string * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalTableCompareTest001, TestSize.Level1) @@ -670,7 +670,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalTableCompareTest001, * @tc.name: RelationalSchemaOpinionTest001 * @tc.desc: Test relational schema sync opinion * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaOpinionTest001, TestSize.Level1) @@ -703,7 +703,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaOpinionTest001 * @tc.name: RelationalSchemaNegotiateTest001 * @tc.desc: Test relational schema negotiate * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaNegotiateTest001, TestSize.Level1) @@ -728,7 +728,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaNegotiateTest0 * @tc.name: TableCompareTest001 * @tc.desc: Test table compare * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, TableCompareTest001, TestSize.Level1) @@ -834,7 +834,7 @@ int TableCompareTest(sqlite3 *db, const std::string &sql1, const std::string &sq * @tc.name: TableCompareTest001 * @tc.desc: Test table compare with default value * @tc.type: FUNC - * @tc.require: AR000GK58I + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, TableCompareTest002, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_object_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_object_test.cpp index 388d6597..b43442be 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_object_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_object_test.cpp @@ -383,17 +383,21 @@ std::string SchemaSwitchMode(const std::string &oriSchemaStr) { std::string resultSchemaStr = oriSchemaStr; auto iterForStrict = std::search(resultSchemaStr.begin(), resultSchemaStr.end(), - SchemaConstant::KEYWORD_MODE_STRICT.begin(), SchemaConstant::KEYWORD_MODE_STRICT.end()); + SchemaConstant::KEYWORD_MODE_STRICT, + SchemaConstant::KEYWORD_MODE_STRICT + strlen(SchemaConstant::KEYWORD_MODE_STRICT)); auto iterForCompatible = std::search(resultSchemaStr.begin(), resultSchemaStr.end(), - SchemaConstant::KEYWORD_MODE_COMPATIBLE.begin(), SchemaConstant::KEYWORD_MODE_COMPATIBLE.end()); + SchemaConstant::KEYWORD_MODE_COMPATIBLE, + SchemaConstant::KEYWORD_MODE_COMPATIBLE + strlen(SchemaConstant::KEYWORD_MODE_COMPATIBLE)); if (iterForStrict != resultSchemaStr.end()) { - resultSchemaStr.replace(iterForStrict, iterForStrict + SchemaConstant::KEYWORD_MODE_STRICT.size(), - SchemaConstant::KEYWORD_MODE_COMPATIBLE.begin(), SchemaConstant::KEYWORD_MODE_COMPATIBLE.end()); + resultSchemaStr.replace(iterForStrict, iterForStrict + strlen(SchemaConstant::KEYWORD_MODE_STRICT), + SchemaConstant::KEYWORD_MODE_COMPATIBLE, + SchemaConstant::KEYWORD_MODE_COMPATIBLE + strlen(SchemaConstant::KEYWORD_MODE_COMPATIBLE)); return resultSchemaStr; } if (iterForCompatible != resultSchemaStr.end()) { - resultSchemaStr.replace(iterForCompatible, iterForCompatible + SchemaConstant::KEYWORD_MODE_COMPATIBLE.size(), - SchemaConstant::KEYWORD_MODE_STRICT.begin(), SchemaConstant::KEYWORD_MODE_STRICT.end()); + resultSchemaStr.replace(iterForCompatible, iterForCompatible + strlen(SchemaConstant::KEYWORD_MODE_COMPATIBLE), + SchemaConstant::KEYWORD_MODE_STRICT, + SchemaConstant::KEYWORD_MODE_STRICT + strlen(SchemaConstant::KEYWORD_MODE_STRICT)); return resultSchemaStr; } return oriSchemaStr; @@ -417,7 +421,7 @@ void DistributedDBSchemaObjectTest::SetUp() * @tc.name: Parse Valid Schema 001 * @tc.desc: Parse Valid Schema * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, ParseValidSchema001, TestSize.Level1) @@ -459,7 +463,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, ParseValidSchema001, TestSize.Level1) * @tc.name: Parse Invalid Schema 001 * @tc.desc: Parse Invalid Schema * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, ParseInvalidSchema001, TestSize.Level1) @@ -509,7 +513,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, ParseInvalidSchema001, TestSize.Level1) * @tc.name: Parse Invalid Schema 002 * @tc.desc: Parse Invalid Schema * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, ParseInvalidSchema002, TestSize.Level1) @@ -559,7 +563,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, ParseInvalidSchema002, TestSize.Level1) * @tc.name: Parse Invalid Schema 003 * @tc.desc: Parse Invalid Schema * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, ParseInvalidSchema003, TestSize.Level1) @@ -609,7 +613,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, ParseInvalidSchema003, TestSize.Level1) * @tc.name: Compare Equal Exactly 001 * @tc.desc: Compare Equal Exactly * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, CompareEqualExactly001, TestSize.Level1) @@ -630,7 +634,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, CompareEqualExactly001, TestSize.Level1) * @tc.name: Compare Unequal Compatible 001 * @tc.desc: Compare Unequal Compatible * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, CompareUnequalCompatible001, TestSize.Level1) @@ -665,7 +669,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, CompareUnequalCompatible001, TestSize.Le * @tc.name: Compare Unequal Compatible Upgrade 001 * @tc.desc: Compare Unequal Compatible Upgrade * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, CompareUnequalCompatibleUpgrade001, TestSize.Level1) @@ -700,7 +704,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, CompareUnequalCompatibleUpgrade001, Test * @tc.name: Compare Unequal Incompatible 001 * @tc.desc: Compare Unequal Incompatible * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, CompareUnequalIncompatible001, TestSize.Level1) @@ -775,7 +779,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, CompareUnequalIncompatible001, TestSize. * @tc.name: Check Value 001 * @tc.desc: Check value both in strict and compatible mode * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, CheckValue001, TestSize.Level1) @@ -855,7 +859,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, CheckValue001, TestSize.Level1) * @tc.name: Check Value 002 * @tc.desc: Check value that has offset * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, CheckValue002, TestSize.Level1) @@ -889,7 +893,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, CheckValue002, TestSize.Level1) * @tc.name: Value Edit 001 * @tc.desc: Edit the value in right way * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, ValueEdit001, TestSize.Level1) @@ -937,7 +941,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, ValueEdit001, TestSize.Level1) * @tc.name: Value Edit 002 * @tc.desc: Edit the value in wrong way * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, ValueEdit002, TestSize.Level1) @@ -992,7 +996,7 @@ void CheckValueLackField(const SchemaObject &schema, const std::string &oriValue * @tc.name: Value LackField 001 * @tc.desc: check the value which lack field * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, ValueLackField001, TestSize.Level1) @@ -1051,7 +1055,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, ValueLackField001, TestSize.Level1) * @tc.name: Value LackField 002 * @tc.desc: check the value which lack field * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBSchemaObjectTest, ValueLackField002, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_unit_test.cpp index d69bfe94..05983611 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_unit_test.cpp @@ -180,7 +180,7 @@ void PreBoolDataForParseAndCheckSchemaAttribute003() * @tc.name: ParseAndCheckSchemaAttribute001 * @tc.desc: Ability to recognize and parse the correct schema attribute format * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckSchemaAttribute001, TestSize.Level1) @@ -232,7 +232,7 @@ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckSchemaAttribute001, TestSize.Lev * @tc.name: ParseAndCheckSchemaAttribute002 * @tc.desc: Can identify the wrong schema attribute format and report an error. * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckSchemaAttribute002, TestSize.Level1) @@ -286,7 +286,7 @@ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckSchemaAttribute002, TestSize.Lev * @tc.name: ParseAndCheckSchemaAttribute003 * @tc.desc: Can correctly interpret the meaning of each keyword of the schema attribute * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckSchemaAttribute003, TestSize.Level1) @@ -315,7 +315,7 @@ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckSchemaAttribute003, TestSize.Lev * @tc.name: ParseAndCheckSchemaAttribute004 * @tc.desc: Can correctly identify the meaning of the schema attribute field that is incorrectly parsed * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckSchemaAttribute004, TestSize.Level1) @@ -364,7 +364,7 @@ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckSchemaAttribute004, TestSize.Lev * @tc.name: CheckFieldName001 * @tc.desc: Correctly identify field names * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBSchemalTest, CheckFieldName001, TestSize.Level1) @@ -389,7 +389,7 @@ HWTEST_F(DistributedDBSchemalTest, CheckFieldName001, TestSize.Level1) * @tc.name: CheckFieldName002 * @tc.desc: Identify illegal field name * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBSchemalTest, CheckFieldName002, TestSize.Level1) @@ -416,7 +416,7 @@ HWTEST_F(DistributedDBSchemalTest, CheckFieldName002, TestSize.Level1) * @tc.name: ParseAndCheckFieldPath001 * @tc.desc: Correctly identify and parse shema index fields * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckFieldPath001, TestSize.Level1) @@ -473,7 +473,7 @@ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckFieldPath001, TestSize.Level1) * @tc.name: ParseAndCheckFieldPath002 * @tc.desc: Correctly identify illegal shema index fields * @tc.type: FUNC - * @tc.require: AR000DR9K3 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckFieldPath002, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_thread_pool_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_thread_pool_test.cpp index 560ba2ab..e862e876 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_thread_pool_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_thread_pool_test.cpp @@ -166,7 +166,7 @@ void SetTimer(int &timerCount, TimerId &timer) * @tc.name: ScheduleTask001 * @tc.desc: Test schedule task by thread pool * @tc.type: FUNC - * @tc.require: AR000I0KU9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBThreadPoolTest, ScheduleTask001, TestSize.Level1) @@ -207,7 +207,7 @@ HWTEST_F(DistributedDBThreadPoolTest, ScheduleTask001, TestSize.Level1) * @tc.name: SetTimer001 * @tc.desc: Test set timer by thread pool * @tc.type: FUNC - * @tc.require: AR000I0KU9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBThreadPoolTest, SetTimer001, TestSize.Level1) @@ -250,7 +250,7 @@ HWTEST_F(DistributedDBThreadPoolTest, SetTimer001, TestSize.Level1) * @tc.name: SetTimer002 * @tc.desc: Test repeat setting timer * @tc.type: FUNC - * @tc.require: AR000I0KU9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBThreadPoolTest, SetTimer002, TestSize.Level1) @@ -283,7 +283,7 @@ HWTEST_F(DistributedDBThreadPoolTest, SetTimer002, TestSize.Level1) * @tc.name: SetTimer003 * @tc.desc: Test set timer and finalize is null * @tc.type: FUNC - * @tc.require: AR000I0KU9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBThreadPoolTest, SetTimer003, TestSize.Level1) @@ -310,7 +310,7 @@ HWTEST_F(DistributedDBThreadPoolTest, SetTimer003, TestSize.Level1) * @tc.name: SetTimer004 * @tc.desc: Test remove timer function * @tc.type: FUNC - * @tc.require: AR000I0KU9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBThreadPoolTest, SetTimer004, TestSize.Level2) @@ -350,7 +350,7 @@ HWTEST_F(DistributedDBThreadPoolTest, SetTimer004, TestSize.Level2) * @tc.name: SetTimer005 * @tc.desc: Test repeat remove timer * @tc.type: FUNC - * @tc.require: AR000I0KU9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBThreadPoolTest, SetTimer005, TestSize.Level1) @@ -394,7 +394,7 @@ HWTEST_F(DistributedDBThreadPoolTest, SetTimer005, TestSize.Level1) * @tc.name: SetTimer006 * @tc.desc: Test repeat remove timer when time action finished * @tc.type: FUNC - * @tc.require: AR000I0KU9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBThreadPoolTest, SetTimer006, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_client_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_client_test.cpp new file mode 100644 index 00000000..a76a7064 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_client_test.cpp @@ -0,0 +1,182 @@ +/* + * 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 "distributeddb_tools_unit_test.h" +#include "platform_specific.h" + +using namespace DistributedDB; + +namespace DistributedDBUnitTest { +int DistributedDBToolsUnitTest::GetCurrentDir(std::string &dir) +{ + static const int maxFileLength = 1024; + dir = ""; + char buffer[maxFileLength] = {0}; + int length = readlink("/proc/self/exe", buffer, maxFileLength); + if (length < 0 || length >= maxFileLength) { + LOGE("read directory err length:%d", length); + return -E_LENGTH_ERROR; + } + LOGD("DIR = %s", buffer); + dir = buffer; + if (dir.rfind("/") == std::string::npos && dir.rfind("\\") == std::string::npos) { + LOGE("current patch format err"); + return -E_INVALID_PATH; + } + + if (dir.rfind("/") != std::string::npos) { + dir.erase(dir.rfind("/") + 1); + } + return E_OK; +} + +void DistributedDBToolsUnitTest::TestDirInit(std::string &dir) +{ + if (GetCurrentDir(dir) != E_OK) { + dir = "/"; + } + + dir.append("testDbDir"); + DIR *dirTmp = opendir(dir.c_str()); + if (dirTmp == nullptr) { + if (OS::MakeDBDirectory(dir) != 0) { + LOGI("MakeDirectory err!"); + dir = "/"; + return; + } + } else { + closedir(dirTmp); + } +} + +int DistributedDBToolsUnitTest::RemoveTestDbFiles(const std::string &dir) +{ + bool isExisted = OS::CheckPathExistence(dir); + if (!isExisted) { + return E_OK; + } + + int nFile = 0; + std::string dirName; + struct dirent *direntPtr = nullptr; + DIR *dirPtr = opendir(dir.c_str()); + if (dirPtr == nullptr) { + LOGE("opendir error!"); + return -E_INVALID_PATH; + } + while (true) { + direntPtr = readdir(dirPtr); + // condition to exit the loop + if (direntPtr == nullptr) { + break; + } + // only remove all *.db files + std::string str(direntPtr->d_name); + if (str == "." || str == "..") { + continue; + } + dirName.clear(); + dirName.append(dir).append("/").append(str); + if (direntPtr->d_type == DT_DIR) { + RemoveTestDbFiles(dirName); + rmdir(dirName.c_str()); + } else if (remove(dirName.c_str()) != 0) { + LOGI("remove file: %s failed!", dirName.c_str()); + continue; + } + nFile++; + } + closedir(dirPtr); + LOGI("Total %d test db files are removed!", nFile); + return 0; +} + +sqlite3 *RelationalTestUtils::CreateDataBase(const std::string &dbUri) +{ + LOGD("Create database: %s", dbUri.c_str()); + sqlite3 *db = nullptr; + if (int r = sqlite3_open_v2(dbUri.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr) != SQLITE_OK) { + LOGE("Open database [%s] failed. %d", dbUri.c_str(), r); + if (db != nullptr) { + (void)sqlite3_close_v2(db); + db = nullptr; + } + } + return db; +} + +int RelationalTestUtils::ExecSql(sqlite3 *db, const std::string &sql) +{ + if (db == nullptr || sql.empty()) { + return -E_INVALID_ARGS; + } + char *errMsg = nullptr; + int errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &errMsg); + if (errCode != SQLITE_OK && errMsg != nullptr) { + LOGE("Execute sql failed. %d err: %s", errCode, errMsg); + } + sqlite3_free(errMsg); + return errCode; +} + +int RelationalTestUtils::ExecSql(sqlite3 *db, const std::string &sql, + const std::function &bindCallback, const std::function &resultCallback) +{ + if (db == nullptr || sql.empty()) { + return -E_INVALID_ARGS; + } + + bool bindFinish = true; + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != E_OK) { + goto END; + } + + do { + if (bindCallback) { + errCode = bindCallback(stmt); + if (errCode != E_OK && errCode != -E_UNFINISHED) { + goto END; + } + bindFinish = (errCode != -E_UNFINISHED); // continue bind if unfinished + } + + bool isStepFinished = false; + while (!isStepFinished) { + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; // Step finished + isStepFinished = true; + break; + } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + goto END; // Step return error + } + if (resultCallback == nullptr) { + continue; + } + errCode = resultCallback(stmt); + if (errCode != E_OK) { + goto END; + } + } + SQLiteUtils::ResetStatement(stmt, false, errCode); + } while (!bindFinish); + +END: + SQLiteUtils::ResetStatement(stmt, true, errCode); + return errCode; +} +} // namespace DistributedDBUnitTest diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp index 9469dd06..253f8149 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp @@ -224,90 +224,6 @@ int DistributedDBToolsUnitTest::GetResourceDir(std::string& dir) return E_OK; } -int DistributedDBToolsUnitTest::GetCurrentDir(std::string &dir) -{ - static const int maxFileLength = 1024; - dir = ""; - char buffer[maxFileLength] = {0}; - int length = readlink("/proc/self/exe", buffer, maxFileLength); - if (length < 0 || length >= maxFileLength) { - LOGE("read directory err length:%d", length); - return -E_LENGTH_ERROR; - } - LOGD("DIR = %s", buffer); - dir = buffer; - if (dir.rfind("/") == std::string::npos && dir.rfind("\\") == std::string::npos) { - LOGE("current patch format err"); - return -E_INVALID_PATH; - } - - if (dir.rfind("/") != std::string::npos) { - dir.erase(dir.rfind("/") + 1); - } - return E_OK; -} - -void DistributedDBToolsUnitTest::TestDirInit(std::string &dir) -{ - if (GetCurrentDir(dir) != E_OK) { - dir = "/"; - } - - dir.append("testDbDir"); - DIR *dirTmp = opendir(dir.c_str()); - if (dirTmp == nullptr) { - if (OS::MakeDBDirectory(dir) != 0) { - LOGI("MakeDirectory err!"); - dir = "/"; - return; - } - } else { - closedir(dirTmp); - } -} - -int DistributedDBToolsUnitTest::RemoveTestDbFiles(const std::string &dir) -{ - bool isExisted = OS::CheckPathExistence(dir); - if (!isExisted) { - return E_OK; - } - - int nFile = 0; - std::string dirName; - struct dirent *direntPtr = nullptr; - DIR *dirPtr = opendir(dir.c_str()); - if (dirPtr == nullptr) { - LOGE("opendir error!"); - return -E_INVALID_PATH; - } - while (true) { - direntPtr = readdir(dirPtr); - // condition to exit the loop - if (direntPtr == nullptr) { - break; - } - // only remove all *.db files - std::string str(direntPtr->d_name); - if (str == "." || str == "..") { - continue; - } - dirName.clear(); - dirName.append(dir).append("/").append(str); - if (direntPtr->d_type == DT_DIR) { - RemoveTestDbFiles(dirName); - rmdir(dirName.c_str()); - } else if (remove(dirName.c_str()) != 0) { - LOGI("remove file: %s failed!", dirName.c_str()); - continue; - } - nFile++; - } - closedir(dirPtr); - LOGI("Total %d test db files are removed!", nFile); - return 0; -} - #ifndef OMIT_MULTI_VER void DistributedDBToolsUnitTest::KvStoreDelegateCallback( DBStatus statusSrc, KvStoreDelegate *kvStoreSrc, DBStatus &statusDst, KvStoreDelegate *&kvStoreDst) @@ -1033,6 +949,30 @@ DBStatus DistributedDBToolsUnitTest::SyncTest(KvStoreNbDelegate* delegate, return callStatus; } +DBStatus DistributedDBToolsUnitTest::SyncTest(DistributedDB::KvStoreNbDelegate* delegate, + const DistributedDB::DeviceSyncOption& option, std::map& statuses) +{ + statuses.clear(); + DBStatus callStatus = delegate->Sync(option, [&statuses, this](const std::map& statusMap) { + std::unique_lock innerlock(this->syncLock_); + statuses = statusMap; + this->syncCondVar_.notify_one(); + }); + if (!option.isWait) { + std::unique_lock lock(syncLock_); + syncCondVar_.wait(lock, [callStatus, &statuses]() { + if (callStatus != OK) { + return true; + } + if (!statuses.empty()) { + return true; + } + return false; + }); + } + return callStatus; +} + static bool WaitUntilReady(DBStatus status, const std::map &syncProcessMap) { if (status != OK) { @@ -1064,7 +1004,8 @@ DBStatus DistributedDBToolsUnitTest::SyncTest(KvStoreNbDelegate *delegate, Devic if (!option.isWait) { std::unique_lock lock(this->syncLock_); - this->syncCondVar_.wait(lock, [status, &syncProcessMap]() { + uint32_t waitTime = 30; // 30s + this->syncCondVar_.wait_for(lock, std::chrono::seconds(waitTime), [status, &syncProcessMap]() { return WaitUntilReady(status, syncProcessMap); }); } @@ -1154,81 +1095,6 @@ int DistributedDBToolsUnitTest::BuildMessage(const DataSyncMessageInfo &messageI return E_OK; } -sqlite3 *RelationalTestUtils::CreateDataBase(const std::string &dbUri) -{ - LOGD("Create database: %s", dbUri.c_str()); - sqlite3 *db = nullptr; - if (int r = sqlite3_open_v2(dbUri.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr) != SQLITE_OK) { - LOGE("Open database [%s] failed. %d", dbUri.c_str(), r); - if (db != nullptr) { - (void)sqlite3_close_v2(db); - db = nullptr; - } - } - return db; -} - -int RelationalTestUtils::ExecSql(sqlite3 *db, const std::string &sql) -{ - if (db == nullptr || sql.empty()) { - return -E_INVALID_ARGS; - } - char *errMsg = nullptr; - int errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &errMsg); - if (errCode != SQLITE_OK && errMsg != nullptr) { - LOGE("Execute sql failed. %d err: %s", errCode, errMsg); - } - sqlite3_free(errMsg); - return errCode; -} - -int RelationalTestUtils::ExecSql(sqlite3 *db, const std::string &sql, - const std::function &bindCallback, const std::function &resultCallback) -{ - if (db == nullptr || sql.empty()) { - return -E_INVALID_ARGS; - } - - bool bindFinish = true; - sqlite3_stmt *stmt = nullptr; - int errCode = SQLiteUtils::GetStatement(db, sql, stmt); - if (errCode != E_OK) { - goto END; - } - - do { - if (bindCallback) { - errCode = bindCallback(stmt); - if (errCode != E_OK && errCode != -E_UNFINISHED) { - goto END; - } - bindFinish = (errCode != -E_UNFINISHED); // continue bind if unfinished - } - - while (true) { - errCode = SQLiteUtils::StepWithRetry(stmt); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; // Step finished - break; - } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - goto END; // Step return error - } - if (resultCallback == nullptr) { - continue; - } - errCode = resultCallback(stmt); - if (errCode != E_OK) { - goto END; - } - } - SQLiteUtils::ResetStatement(stmt, false, errCode); - } while (!bindFinish); - -END: - SQLiteUtils::ResetStatement(stmt, true, errCode); - return errCode; -} - void RelationalTestUtils::CreateDeviceTable(sqlite3 *db, const std::string &table, const std::string &device) { ASSERT_NE(db, nullptr); @@ -1661,6 +1527,14 @@ DistributedDB::ICloudSyncStorageHook *RelationalTestUtils::GetRDBStorageHook(con return static_cast(engine); } +void RelationalTestUtils::CheckIndexCount(sqlite3 *db, const std::string &table, size_t expect) +{ + TableInfo info; + ASSERT_EQ(SQLiteUtils::AnalysisSchema(db, table, info), E_OK); + auto index = info.GetIndexDefine(); + EXPECT_EQ(index.size(), expect); +} + bool RelationalStoreObserverUnitTest::IsAssetChange(const std::string &table) const { auto changeData = savedChangedData_.find(table); @@ -1715,4 +1589,29 @@ void DistributedDBToolsUnitTest::BlockSync(KvStoreNbDelegate *delegate, Distribu }); } } + +std::pair RelationalTestUtils::GetMaxTimestamp(sqlite3 *db, const std::string &oriTable) +{ + std::pair res; + auto &[errCode, timestamp] = res; + std::string sql = "SELECT MAX(timestamp) FROM " + std::string(DistributedDB::DBConstant::RELATIONAL_PREFIX) + + oriTable + "_log"; + sqlite3_stmt *stmt = nullptr; + errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != E_OK) { + LOGE("Get max timestamp stmt failed %d", errCode); + return res; + } + errCode = SQLiteUtils::StepWithRetry(stmt, false); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + timestamp = static_cast(sqlite3_column_int64(stmt, 0)); + errCode = E_OK; + } + int ret = E_OK; + SQLiteUtils::ResetStatement(stmt, true, ret); + if (errCode == E_OK) { + errCode = ret; + } + return res; +} } // namespace DistributedDBUnitTest diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h index 704df20d..b12ad575 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h @@ -159,6 +159,9 @@ public: const std::vector& devices, DistributedDB::SyncMode mode, std::map& statuses, const DistributedDB::Query &query); + DistributedDB::DBStatus SyncTest(DistributedDB::KvStoreNbDelegate* delegate, + const DistributedDB::DeviceSyncOption& option, std::map& statuses); + DistributedDB::DBStatus SyncTest(DistributedDB::KvStoreNbDelegate* delegate, DistributedDB::DeviceSyncOption option, std::map &syncProcessMap); @@ -385,6 +388,8 @@ public: static bool IsExistEmptyHashAsset(const DistributedDB::Assets &assets); static DistributedDB::ICloudSyncStorageHook *GetRDBStorageHook(const std::string &userId, const std::string &appId, const std::string &storeId, const std::string &dbPath); + static void CheckIndexCount(sqlite3 *db, const std::string &table, size_t expect); + static std::pair GetMaxTimestamp(sqlite3 *db, const std::string &oriTable); }; class DBInfoHandleTest : public DistributedDB::DBInfoHandle { diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/evloop_timer_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/evloop_timer_unit_test.cpp index a020e68e..4d4f9e40 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/evloop_timer_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/evloop_timer_unit_test.cpp @@ -103,7 +103,7 @@ void DistributedDBEventLoopTimerTest::TearDown(void) * @tc.name: EventLoopTimerTest001 * @tc.desc: Create and destroy the event loop object. * @tc.type: FUNC - * @tc.require: AR000CKRTB AR000CQE0C + * @tc.require: * @tc.author: fangyi */ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest001, TestSize.Level0) @@ -131,7 +131,7 @@ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest001, TestSize.Level0 * @tc.name: EventLoopTimerTest002 * @tc.desc: Start and stop the loop * @tc.type: FUNC - * @tc.require: AR000CKRTB AR000CQE0C + * @tc.require: * @tc.author: fangyi */ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest002, TestSize.Level1) @@ -165,7 +165,7 @@ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest002, TestSize.Level1 * @tc.name: EventLoopTimerTest003 * @tc.desc: Create and destroy a timer object. * @tc.type: FUNC - * @tc.require: AR000CKRTB AR000CQE0C + * @tc.require: * @tc.author: fangyi */ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest003, TestSize.Level0) @@ -198,7 +198,7 @@ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest003, TestSize.Level0 * @tc.name: EventLoopTimerTest004 * @tc.desc: Start a timer * @tc.type: FUNC - * @tc.require: AR000CKRTB AR000CQE0C + * @tc.require: * @tc.author: fangyi */ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest004, TestSize.Level1) @@ -254,7 +254,7 @@ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest004, TestSize.Level1 * @tc.name: EventLoopTimerTest005 * @tc.desc: Stop a timer * @tc.type: FUNC - * @tc.require: AR000CKRTB AR000CQE0C + * @tc.require: * @tc.author: fangyi */ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest005, TestSize.Level1) @@ -314,7 +314,7 @@ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest005, TestSize.Level1 * @tc.name: EventLoopTimerTest006 * @tc.desc: Stop a timer * @tc.type: FUNC - * @tc.require: AR000CKRTB AR000CQE0C + * @tc.require: * @tc.author: fangyi */ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest006, TestSize.Level1) @@ -371,7 +371,7 @@ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest006, TestSize.Level1 * @tc.name: EventLoopTimerTest007 * @tc.desc: Modify a timer * @tc.type: FUNC - * @tc.require: AR000CKRTB AR000CQE0C + * @tc.require: * @tc.author: fangyi */ HWTEST_F(DistributedDBEventLoopTimerTest, EventLoopTimerTest007, TestSize.Level2) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.cpp index cf413c03..3fb17c5b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.cpp @@ -14,12 +14,15 @@ */ #include "kv_general_ut.h" +#include "kv_store_errno.h" +#include "storage_engine_manager.h" #include "virtual_cloud_db.h" namespace DistributedDB { void KVGeneralUt::SetUp() { virtualCloudDb_ = std::make_shared(); + CloseAllDelegate(); BasicUnitTest::SetUp(); } @@ -49,6 +52,9 @@ int KVGeneralUt::InitDelegate(const StoreInfo &info) LOGE("[KVGeneralUt] Init delegate failed %d", static_cast(status)); return -E_INTERNAL_ERROR; } + if (processCommunicator_ != nullptr) { + manager.SetProcessCommunicator(processCommunicator_); + } stores_[info] = store; LOGI("[KVGeneralUt] Init delegate app %s store %s user %s success", info.appId.c_str(), info.storeId.c_str(), info.userId.c_str()); @@ -105,24 +111,6 @@ KvStoreConfig KVGeneralUt::GetKvStoreConfig() return config; } -StoreInfo KVGeneralUt::GetStoreInfo1() -{ - StoreInfo info; - info.userId = DistributedDBUnitTest::USER_ID; - info.storeId = DistributedDBUnitTest::STORE_ID_1; - info.appId = DistributedDBUnitTest::APP_ID; - return info; -} - -StoreInfo KVGeneralUt::GetStoreInfo2() -{ - StoreInfo info; - info.userId = DistributedDBUnitTest::USER_ID; - info.storeId = DistributedDBUnitTest::STORE_ID_2; - info.appId = DistributedDBUnitTest::APP_ID; - return info; -} - KvStoreNbDelegate *KVGeneralUt::GetDelegate(const DistributedDB::StoreInfo &info) const { std::lock_guard autoLock(storeMutex_); @@ -206,4 +194,103 @@ void KVGeneralUt::BlockCloudSync(const StoreInfo &from, const std::string &devic syncOption.devices.push_back("cloud"); tool_.BlockSync(fromStore, DBStatus::OK, syncOption, expectRet); } + +std::pair KVGeneralUt::GetRemoteSoftwareVersion(const StoreInfo &info, const std::string &dev, + const std::string &user) +{ + uint64_t version = 0; + int errCode = QueryMetaValue(info, dev, user, + [&version](const std::shared_ptr &metadata, const std::string &device, + const std::string &userId) { + version = metadata->GetRemoteSoftwareVersion(device, userId); + return E_OK; + }); + return {TransferDBErrno(errCode), version}; +} + +std::pair KVGeneralUt::GetRemoteSchemaVersion(const StoreInfo &info, const std::string &dev, + const std::string &user) +{ + uint64_t version = 0; + int errCode = QueryMetaValue(info, dev, user, + [&version](const std::shared_ptr &metadata, const std::string &device, + const std::string &userId) { + version = metadata->GetRemoteSchemaVersion(device, userId); + return E_OK; + }); + return {TransferDBErrno(errCode), version}; +} + +DBStatus KVGeneralUt::SetRemoteSoftwareVersion(const StoreInfo &info, const std::string &dev, const std::string &user, + uint64_t version) +{ + int errCode = QueryMetaValue(info, dev, user, + [version](const std::shared_ptr &metadata, const std::string &device, + const std::string &userId) { + return metadata->SetRemoteSoftwareVersion(device, userId, version); + }); + return TransferDBErrno(errCode); +} + +std::pair KVGeneralUt::GetLocalSchemaVersion(const DistributedDB::StoreInfo &info) +{ + uint64_t version = 0; + int errCode = QueryMetaValue(info, "", "", + [&version](const std::shared_ptr &metadata, const std::string &device, + const std::string &userId) { + auto [ret, schemaVersion] = metadata->GetLocalSchemaVersion(); + version = schemaVersion; + return ret; + }); + return {TransferDBErrno(errCode), version}; +} + +int KVGeneralUt::QueryMetaValue(const StoreInfo &info, const std::string &dev, const std::string &user, + const std::function &, const std::string &, const std::string &)> &queryFunc) +{ + int errCode = E_OK; + auto properties = GetDBProperties(info); + auto store = new(std::nothrow) SQLiteSingleVerNaturalStore; + if (store == nullptr) { + errCode = -E_INVALID_ARGS; + LOGI("[KVGeneralUt] create natural store failed with oom"); + return errCode; + } + errCode = store->Open(properties); + if (errCode != E_OK) { + RefObject::KillAndDecObjRef(store); + return errCode; + } + auto meta = std::make_shared(); + errCode = meta->Initialize(store); + if (errCode != E_OK) { + store->Close(); + RefObject::KillAndDecObjRef(store); + return errCode; + } + if (queryFunc) { + errCode = queryFunc(meta, dev, user); + } + meta = nullptr; + store->Close(); + RefObject::KillAndDecObjRef(store); + return errCode; +} + +KvDBProperties KVGeneralUt::GetDBProperties(const StoreInfo &info) +{ + KvDBProperties properties; + properties.SetStringProp(KvDBProperties::DATA_DIR, GetTestDir()); + properties.SetStringProp(KvDBProperties::STORE_ID, info.storeId); + KvStoreNbDelegate::Option option; + std::lock_guard autoLock(storeMutex_); + if (option_.has_value()) { + option = option_.value(); + } + auto idDir = DBCommon::TransferStringToHex(DBCommon::GetStoreIdentifier(info, "", option.syncDualTupleMode, false)); + properties.SetStringProp(KvDBProperties::IDENTIFIER_DIR, idDir); + properties.SetStringProp(KvDBProperties::IDENTIFIER_DATA, idDir + "KVGeneralUt"); + properties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); + return properties; +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.h index 7f228eb4..42ea1bc5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/kv_general_ut.h @@ -36,12 +36,22 @@ protected: DBStatus GetDeviceEntries(KvStoreNbDelegate *delegate, const std::string &deviceId, bool isSelfDevice, std::vector &entries); void BlockCloudSync(const StoreInfo &from, const std::string &deviceId, DBStatus expectRet = DBStatus::OK); + std::pair GetRemoteSoftwareVersion(const StoreInfo &info, const std::string &dev, + const std::string &user); + std::pair GetRemoteSchemaVersion(const StoreInfo &info, const std::string &dev, + const std::string &user); + DBStatus SetRemoteSoftwareVersion(const StoreInfo &info, const std::string &dev, + const std::string &user, uint64_t version); + std::pair GetLocalSchemaVersion(const StoreInfo &info); + int QueryMetaValue(const StoreInfo &info, const std::string &dev, const std::string &user, + const std::function &, const std::string &, + const std::string &)> &queryFunc); + + KvDBProperties GetDBProperties(const StoreInfo &info); static KvStoreConfig GetKvStoreConfig(); - static StoreInfo GetStoreInfo1(); - static StoreInfo GetStoreInfo2(); mutable std::mutex storeMutex_; std::optional option_; - std::map stores_; + std::map stores_; DistributedDBUnitTest::DistributedDBToolsUnitTest tool_; std::shared_ptr virtualCloudDb_; }; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/process_communicator_test_stub.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/process_communicator_test_stub.h index 4d420a1f..7573930e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/process_communicator_test_stub.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/process_communicator_test_stub.h @@ -86,8 +86,13 @@ public: isCommErr = commErr; } - DBStatus GetDataUserInfo(const uint8_t *data, uint32_t totalLen, const std::string &label, - std::vector &userInfos) override + DBStatus GetDataHeadInfo(DataHeadInfo dataHeadInfo, uint32_t &headLength) override + { + headLength = dataHeadInfo_.second; + return dataHeadInfo_.first; + } + + DBStatus GetDataUserInfo(DataUserInfo dataUserInfo, std::vector &userInfos) override { userInfos = userInfos_; return OK; @@ -97,9 +102,15 @@ public: { userInfos_ = userInfos; } + + void SetDataHeadInfo(std::pair dataHeadInfo) + { + dataHeadInfo_ = dataHeadInfo; + } private: bool isCommErr = false; std::vector userInfos_; + std::pair dataHeadInfo_; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator.cpp index 3bbe98f7..ec8cf040 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator.cpp @@ -65,22 +65,6 @@ int RDBDataGenerator::InitTable(const TableSchema &table, bool notNullWithStr, b return errCode; } -std::string RDBDataGenerator::GetTypeText(int type) -{ - switch (type) { - case DistributedDB::TYPE_INDEX: - return "INTEGER"; - case DistributedDB::TYPE_INDEX: - return "TEXT"; - case DistributedDB::TYPE_INDEX: - return "ASSETS"; - case DistributedDB::TYPE_INDEX: - return "ASSET"; - default: - return ""; - } -} - DistributedDB::DBStatus RDBDataGenerator::InsertCloudDBData(int64_t begin, int64_t count, int64_t gidStart, const DistributedDB::DataBaseSchema &schema, const std::shared_ptr &virtualCloudDb) @@ -141,6 +125,15 @@ DistributedDB::Type RDBDataGenerator::GetColValueByType(int64_t index, const Dis case DistributedDB::TYPE_INDEX: value = GenerateAsset(index, field); break; + case DistributedDB::TYPE_INDEX: + value = static_cast(index); + break; + case DistributedDB::TYPE_INDEX: + value = static_cast(index); + break; + case DistributedDB::TYPE_INDEX: + value = GenerateBytes(index); + break; } return value; } @@ -480,45 +473,9 @@ DistributedDB::TableSchema RDBDataGenerator::FlipTableSchema(const DistributedDB return res; } -int RDBDataGenerator::InitDatabaseWithSchemaInfo(const UtDateBaseSchemaInfo &schemaInfo, sqlite3 &db) -{ - int errCode = RelationalTestUtils::ExecSql(&db, "PRAGMA journal_mode=WAL;"); - if (errCode != SQLITE_OK) { - LOGE("[RDBDataGenerator] Execute sql failed %d", errCode); - return errCode; - } - for (const auto &tableInfo : schemaInfo.tablesInfo) { - errCode = InitTableWithSchemaInfo(tableInfo, db); - if (errCode != SQLITE_OK) { - LOGE("[RDBDataGenerator] Init table failed %d, %s", errCode, tableInfo.name.c_str()); - break; - } - } - return errCode; -} - -int RDBDataGenerator::InitTableWithSchemaInfo(const UtTableSchemaInfo &tableInfo, sqlite3 &db) +Bytes RDBDataGenerator::GenerateBytes(int64_t index) { - std::string sql = "CREATE TABLE IF NOT EXISTS " + tableInfo.name + "("; - for (const auto &fieldInfo : tableInfo.fieldInfo) { - sql += "'" + fieldInfo.field.colName + "' " + GetTypeText(fieldInfo.field.type); - if (fieldInfo.field.primary) { - sql += " PRIMARY KEY"; - if (fieldInfo.isAutoIncrement) { - sql += " AUTOINCREMENT"; - } - } - if (!fieldInfo.field.nullable && fieldInfo.field.type == TYPE_INDEX) { - sql += " NOT NULL ON CONFLICT IGNORE"; - } - sql += ","; - } - sql.pop_back(); - sql += ");"; - int errCode = RelationalTestUtils::ExecSql(&db, sql); - if (errCode != SQLITE_OK) { - LOGE("[RDBDataGenerator] Execute sql failed %d, sql is %s", errCode, sql.c_str()); - } - return errCode; + std::string str = std::to_string(index); + return std::vector(str.begin(), str.end()); } } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator.h index 3adad88b..8d8455ca 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator.h @@ -104,6 +104,7 @@ private: static void FillTypeIntoDataValue(const DistributedDB::Field &field, const DistributedDB::Type &type, DistributedDB::VirtualRowData &virtualRow); + static DistributedDB::Bytes GenerateBytes(int64_t index); }; } #endif // RDB_DATA_GENERATE_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator_client.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator_client.cpp new file mode 100644 index 00000000..52ec4693 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_data_generator_client.cpp @@ -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. + */ + +#include "rdb_data_generator.h" + +#include "distributeddb_tools_unit_test.h" +#include "log_print.h" + +namespace DistributedDBUnitTest { +using namespace DistributedDB; +std::string RDBDataGenerator::GetTypeText(int type) +{ + switch (type) { + case DistributedDB::TYPE_INDEX: + return "INTEGER"; + case DistributedDB::TYPE_INDEX: + return "TEXT"; + case DistributedDB::TYPE_INDEX: + return "ASSETS"; + case DistributedDB::TYPE_INDEX: + return "ASSET"; + case DistributedDB::TYPE_INDEX: + return "DOUBLE"; + case DistributedDB::TYPE_INDEX: + return "BLOB"; + default: + return ""; + } +} + +int RDBDataGenerator::InitDatabaseWithSchemaInfo(const UtDateBaseSchemaInfo &schemaInfo, sqlite3 &db) +{ + int errCode = RelationalTestUtils::ExecSql(&db, "PRAGMA journal_mode=WAL;"); + if (errCode != SQLITE_OK) { + LOGE("[RDBDataGenerator] Execute sql failed %d", errCode); + return errCode; + } + for (const auto &tableInfo : schemaInfo.tablesInfo) { + errCode = InitTableWithSchemaInfo(tableInfo, db); + if (errCode != SQLITE_OK) { + LOGE("[RDBDataGenerator] Init table failed %d, %s", errCode, tableInfo.name.c_str()); + break; + } + } + return errCode; +} + +int RDBDataGenerator::InitTableWithSchemaInfo(const UtTableSchemaInfo &tableInfo, sqlite3 &db) +{ + std::string sql = "CREATE TABLE IF NOT EXISTS " + tableInfo.name + "("; + for (const auto &fieldInfo : tableInfo.fieldInfo) { + sql += "'" + fieldInfo.field.colName + "' " + GetTypeText(fieldInfo.field.type); + if (fieldInfo.field.primary) { + sql += " PRIMARY KEY"; + if (fieldInfo.isAutoIncrement) { + sql += " AUTOINCREMENT"; + } + } + if (!fieldInfo.field.nullable) { + sql += " NOT NULL ON CONFLICT IGNORE"; + } + sql += ","; + } + sql.pop_back(); + sql += ");"; + int errCode = RelationalTestUtils::ExecSql(&db, sql); + if (errCode != SQLITE_OK) { + LOGE("[RDBDataGenerator] Execute sql failed %d, sql is %s", errCode, sql.c_str()); + } + return errCode; +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.cpp index 142941a8..831e0a33 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.cpp @@ -14,20 +14,28 @@ */ #include "rdb_general_ut.h" #include "rdb_data_generator.h" +#include "runtime_config.h" +#include "sqlite_relational_utils.h" +#include "virtual_cloud_data_translate.h" using namespace DistributedDBUnitTest; namespace DistributedDB { +const std::string CIPHER_CONFIG_SQL = "PRAGMA codec_cipher='aes-256-gcm';"; +const std::string KDF_ITER_CONFIG_SQL = "PRAGMA codec_kdf_iter=5000;"; +const std::string SHA256_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA256;"; + const Field intField = {"id", TYPE_INDEX, true, false}; const Field stringField = {"name", TYPE_INDEX, false, false}; const Field boolField = {"gender", TYPE_INDEX, false, true}; const Field doubleField = {"height", TYPE_INDEX, false, true}; const Field bytesField = {"photo", TYPE_INDEX, false, true}; -const Field assetsField = {"assert", TYPE_INDEX, false, true}; +const Field assetField = {"assert", TYPE_INDEX, false, true}; +const Field assetsField = {"asserts", TYPE_INDEX, false, true}; const std::vector g_defaultFiledInfo = { {intField, true}, {stringField, false}, {boolField, false}, - {doubleField, false}, {bytesField, false}, {assetsField, false}, + {doubleField, false}, {bytesField, false}, {assetField, false}, {assetsField, false}, }; UtDateBaseSchemaInfo g_defaultSchemaInfo = { @@ -39,47 +47,60 @@ UtDateBaseSchemaInfo g_defaultSchemaInfo = { int RDBGeneralUt::InitDelegate(const StoreInfo &info) { - std::string storePath = GetTestDir() + "/" + info.storeId + ".db"; - sqlite3 *db = RelationalTestUtils::CreateDataBase(storePath); - if (db == nullptr) { - LOGE("[RDBGeneralUt] Create database failed %s", storePath.c_str()); - return -E_INVALID_DB; - } - UtDateBaseSchemaInfo schemaInfo = GetTableSchemaInfo(info); - int errCode = RDBDataGenerator::InitDatabaseWithSchemaInfo(schemaInfo, *db); - if (errCode != SQLITE_OK) { - LOGE("[RDBGeneralUt] Init database failed %d", errCode); - return errCode; + InitDatabase(info); + { + std::lock_guard autoLock(storeMutex_); + if (stores_.find(info) != stores_.end()) { + return E_OK; + } } - RelationalStoreManager mgr(info.appId, info.userId); - RelationalStoreDelegate *delegate = nullptr; - errCode = mgr.OpenStore(storePath, info.storeId, option_, delegate); + auto [errCode, delegate] = OpenRDBStore(info); if ((errCode != E_OK )|| (delegate == nullptr)) { LOGE("[RDBGeneralUt] Open store failed %d", errCode); return errCode; } { - std::lock_guard lock(storeMutex_); + std::lock_guard autoLock(storeMutex_); stores_[info] = delegate; - sqliteDb_[info] = db; } + LOGI("[RDBGeneralUt] Init delegate app %s store %s user %s success", info.appId.c_str(), + info.storeId.c_str(), info.userId.c_str()); return E_OK; } +std::pair RDBGeneralUt::OpenRDBStore(const StoreInfo &info) +{ + std::pair res; + auto &[errCode, delegate] = res; + delegate = nullptr; + std::string storePath = GetTestDir() + "/" + info.storeId + ".db"; + RelationalStoreManager mgr(info.appId, info.userId); + RelationalStoreDelegate::Option option = GetOption(); + errCode = mgr.OpenStore(storePath, info.storeId, option, delegate); + return res; +} + void RDBGeneralUt::SetOption(const RelationalStoreDelegate::Option& option) { + std::lock_guard autoLock(storeMutex_); option_ = option; } -void RDBGeneralUt::AddSchemaInfo(const StoreInfo &info, const DistributedDBUnitTest::UtDateBaseSchemaInfo &schemaInfo) +RelationalStoreDelegate::Option RDBGeneralUt::GetOption() const { - std::lock_guard lock(storeMutex_); + std::lock_guard autoLock(storeMutex_); + return option_; +} + +void RDBGeneralUt::SetSchemaInfo(const StoreInfo &info, const DistributedDBUnitTest::UtDateBaseSchemaInfo &schemaInfo) +{ + std::lock_guard autoLock(storeMutex_); schemaInfoMap_[info] = schemaInfo; } -UtDateBaseSchemaInfo RDBGeneralUt::GetTableSchemaInfo(const StoreInfo &info) +UtDateBaseSchemaInfo RDBGeneralUt::GetTableSchemaInfo(const StoreInfo &info) const { - std::lock_guard lock(storeMutex_); + std::lock_guard autoLock(storeMutex_); auto iter = schemaInfoMap_.find(info); if (iter != schemaInfoMap_.end()) { return iter->second; @@ -87,7 +108,7 @@ UtDateBaseSchemaInfo RDBGeneralUt::GetTableSchemaInfo(const StoreInfo &info) return g_defaultSchemaInfo; } -DataBaseSchema RDBGeneralUt::GetSchema(const StoreInfo &info) +DataBaseSchema RDBGeneralUt::GetSchema(const StoreInfo &info) const { UtDateBaseSchemaInfo schemaInfo = GetTableSchemaInfo(info); DataBaseSchema schema; @@ -103,7 +124,7 @@ DataBaseSchema RDBGeneralUt::GetSchema(const StoreInfo &info) return schema; } -TableSchema RDBGeneralUt::GetTableSchema(const StoreInfo &info, const std::string &tableName) +TableSchema RDBGeneralUt::GetTableSchema(const StoreInfo &info, const std::string &tableName) const { UtDateBaseSchemaInfo schemaInfo = GetTableSchemaInfo(info); for (auto &item : schemaInfo.tablesInfo) { @@ -123,7 +144,7 @@ TableSchema RDBGeneralUt::GetTableSchema(const StoreInfo &info, const std::strin } std::vector RDBGeneralUt::GetAllTrackerSchema(const StoreInfo &info, - const std::vector &tables) + const std::vector &tables) const { UtDateBaseSchemaInfo schemaInfo = GetTableSchemaInfo(info); std::vector res; @@ -145,7 +166,7 @@ std::vector RDBGeneralUt::GetAllTrackerSchema(const StoreInfo &in int RDBGeneralUt::CloseDelegate(const StoreInfo &info) { - std::lock_guard lock(storeMutex_); + std::lock_guard autoLock(storeMutex_); auto storeIter = stores_.find(info); if (storeIter != stores_.end()) { RelationalStoreManager mgr(info.appId, info.userId); @@ -163,12 +184,14 @@ int RDBGeneralUt::CloseDelegate(const StoreInfo &info) if (schemaIter != schemaInfoMap_.end()) { schemaInfoMap_.erase(schemaIter); } + LOGI("[RDBGeneralUt] Close delegate app %s store %s user %s success", info.appId.c_str(), + info.storeId.c_str(), info.userId.c_str()); return E_OK; } void RDBGeneralUt::CloseAllDelegate() { - std::lock_guard lock(storeMutex_); + std::lock_guard autoLock(storeMutex_); for (auto &iter : sqliteDb_) { sqlite3_close_v2(iter.second); iter.second = nullptr; @@ -181,36 +204,65 @@ void RDBGeneralUt::CloseAllDelegate() } stores_.clear(); schemaInfoMap_.clear(); + isDbEncrypted_ = false; + LOGI("[RDBGeneralUt] Close all delegate success"); } void RDBGeneralUt::SetUp() { BasicUnitTest::SetUp(); + RuntimeConfig::SetCloudTranslate(std::make_shared()); + { + std::lock_guard autoLock(storeMutex_); + virtualCloudDb_ = std::make_shared(); + virtualAssetLoader_ = std::make_shared(); + } } void RDBGeneralUt::TearDown() { CloseAllDelegate(); + { + std::lock_guard autoLock(storeMutex_); + virtualCloudDb_ = nullptr; + virtualAssetLoader_ = nullptr; + } BasicUnitTest::TearDown(); } int RDBGeneralUt::InitDatabase(const StoreInfo &info) { - auto schema = GetSchema(info); - auto db = GetSqliteHandle(info); + std::string storePath = GetTestDir() + "/" + info.storeId + ".db"; + sqlite3 *db = RelationalTestUtils::CreateDataBase(storePath); if (db == nullptr) { - LOGE("[RDBGeneralUt] Get null sqlite when init database"); + LOGE("[RDBGeneralUt] Create database failed %s", storePath.c_str()); return -E_INVALID_DB; } - auto errCode = RDBDataGenerator::InitDatabase(schema, *db); - if (errCode != E_OK) { - LOGE("[RDBGeneralUt] Init db failed %d app %s store %s user %s", errCode, info.appId.c_str(), - info.storeId.c_str(), info.userId.c_str()); + int errCode = E_OK; + if (GetIsDbEncrypted()) { + errCode = EncryptedDb(db); + if (errCode != E_OK) { + return errCode; + } } - return errCode; + UtDateBaseSchemaInfo schemaInfo = GetTableSchemaInfo(info); + errCode = RDBDataGenerator::InitDatabaseWithSchemaInfo(schemaInfo, *db); + if (errCode != SQLITE_OK) { + LOGE("[RDBGeneralUt] Init database failed %d", errCode); + return errCode; + } + { + std::lock_guard autoLock(storeMutex_); + if (sqliteDb_.find(info) != sqliteDb_.end()) { + sqlite3_close_v2(db); + return E_OK; + } + sqliteDb_[info] = db; + } + return E_OK; } -sqlite3 *RDBGeneralUt::GetSqliteHandle(const StoreInfo &info) +sqlite3 *RDBGeneralUt::GetSqliteHandle(const StoreInfo &info) const { std::lock_guard autoLock(storeMutex_); auto db = sqliteDb_.find(info); @@ -241,6 +293,16 @@ int RDBGeneralUt::InsertLocalDBData(int64_t begin, int64_t count, const StoreInf return errCode; } +int RDBGeneralUt::ExecuteSQL(const std::string &sql, const StoreInfo &info) +{ + auto db = GetSqliteHandle(info); + if (db == nullptr) { + LOGE("[RDBGeneralUt] Get null sqlite when insert data"); + return -E_INVALID_DB; + } + return SQLiteUtils::ExecuteRawSQL(db, sql); +} + int RDBGeneralUt::CreateDistributedTable(const StoreInfo &info, const std::string &table, TableSyncType type) { auto store = GetDelegate(info); @@ -253,6 +315,8 @@ int RDBGeneralUt::CreateDistributedTable(const StoreInfo &info, const std::strin LOGE("[RDBGeneralUt] Create distributed table failed %d app %s store %s user %s", errCode, info.appId.c_str(), info.storeId.c_str(), info.userId.c_str()); } + LOGI("[RDBGeneralUt] Create distributed table success, app %s store %s user %s", info.appId.c_str(), + info.storeId.c_str(), info.userId.c_str()); return errCode; } @@ -266,7 +330,8 @@ int RDBGeneralUt::SetDistributedTables(const StoreInfo &info, const std::vector< return errCode; } } - if (option_.tableMode != DistributedTableMode::COLLABORATION) { + RelationalStoreDelegate::Option option = GetOption(); + if (option.tableMode != DistributedTableMode::COLLABORATION) { return E_OK; } auto store = GetDelegate(info); @@ -280,37 +345,51 @@ int RDBGeneralUt::SetDistributedTables(const StoreInfo &info, const std::vector< LOGE("[RDBGeneralUt] Set distributed schema failed %d app %s store %s user %s", errCode, info.appId.c_str(), info.storeId.c_str(), info.userId.c_str()); } + LOGI("[RDBGeneralUt] Set distributed table success, app %s store %s user %s", info.appId.c_str(), + info.storeId.c_str(), info.userId.c_str()); return errCode; } -RelationalStoreDelegate *RDBGeneralUt::GetDelegate(const StoreInfo &info) +RelationalStoreDelegate *RDBGeneralUt::GetDelegate(const StoreInfo &info) const { std::lock_guard autoLock(storeMutex_); auto db = stores_.find(info); if (db == stores_.end()) { LOGE("[RDBGeneralUt] Not exist delegate app %s store %s user %s", info.appId.c_str(), - info.storeId.c_str(), info.userId.c_str()); + info.storeId.c_str(), info.userId.c_str()); return nullptr; } return db->second; } void RDBGeneralUt::BlockPush(const StoreInfo &from, const StoreInfo &to, const std::string &table, DBStatus expectRet) +{ + ASSERT_NO_FATAL_FAILURE(BlockSync(from, to, table, SYNC_MODE_PUSH_ONLY, expectRet)); +} + +void RDBGeneralUt::BlockPull(const StoreInfo &from, const StoreInfo &to, const std::string &table, DBStatus expectRet) +{ + ASSERT_NO_FATAL_FAILURE(BlockSync(from, to, table, SYNC_MODE_PULL_ONLY, expectRet)); +} + +void RDBGeneralUt::BlockSync(const StoreInfo &from, const StoreInfo &to, const std::string &table, SyncMode mode, + DBStatus expectRet) { auto store = GetDelegate(from); ASSERT_NE(store, nullptr); auto toDevice = GetDevice(to); ASSERT_FALSE(toDevice.empty()); Query query = Query::Select(table); - DistributedDBToolsUnitTest::BlockSync(*store, query, SYNC_MODE_PUSH_ONLY, expectRet, {toDevice}); + ASSERT_NO_FATAL_FAILURE(DistributedDBToolsUnitTest::BlockSync(*store, query, mode, expectRet, {toDevice})); } -int RDBGeneralUt::CountTableData(const StoreInfo &info, const std::string &table) +int RDBGeneralUt::CountTableData(const StoreInfo &info, const std::string &table, const std::string &condition) { - return CountTableDataByDev(info, table, ""); + return CountTableDataByDev(info, table, "", condition); } -int RDBGeneralUt::CountTableDataByDev(const StoreInfo &info, const std::string &table, const std::string &dev) +int RDBGeneralUt::CountTableDataByDev(const StoreInfo &info, const std::string &table, const std::string &dev, + const std::string &condition) { auto db = GetSqliteHandle(info); if (db == nullptr) { @@ -329,9 +408,18 @@ int RDBGeneralUt::CountTableDataByDev(const StoreInfo &info, const std::string & } std::string cntSql = "SELECT count(*) FROM '" + table + "'"; + if (!condition.empty() || !dev.empty()) { + cntSql.append(" WHERE "); + } + if (!condition.empty()) { + cntSql.append(condition); + if (!dev.empty()) { + cntSql.append(" AND "); + } + } if (!dev.empty()) { auto hex = DBCommon::TransferStringToHex(DBCommon::TransferHashString(dev)); - cntSql.append(" WHERE device='").append(hex).append("'"); + cntSql.append("device='").append(hex).append("'"); } sqlite3_stmt *stmt = nullptr; errCode = SQLiteUtils::GetStatement(db, cntSql, stmt); @@ -353,7 +441,7 @@ int RDBGeneralUt::CountTableDataByDev(const StoreInfo &info, const std::string & return count; } -int RDBGeneralUt::SetTrackerTables(const StoreInfo &info, const std::vector &tables) +int RDBGeneralUt::SetTrackerTables(const StoreInfo &info, const std::vector &tables, bool isForce) { auto store = GetDelegate(info); if (store == nullptr) { @@ -362,7 +450,9 @@ int RDBGeneralUt::SetTrackerTables(const StoreInfo &info, const std::vectorSetTrackerTable(trackerTable); + auto temp = trackerTable; + temp.isForceUpgrade = isForce; + auto errCode = store->SetTrackerTable(temp); if (errCode != E_OK) { LOGE("[RDBGeneralUt] Set tracker table %s failed %d app %s store %s user %s", trackerTable.tableName.c_str(), errCode, @@ -374,4 +464,133 @@ int RDBGeneralUt::SetTrackerTables(const StoreInfo &info, const std::vector RDBGeneralUt::GetVirtualCloudDb() const +{ + std::lock_guard autoLock(storeMutex_); + return virtualCloudDb_; +} + +std::shared_ptr RDBGeneralUt::GetVirtualAssetLoader() const +{ + std::lock_guard autoLock(storeMutex_); + return virtualAssetLoader_; +} + +void RDBGeneralUt::SetCloudDbConfig(const StoreInfo &info) const +{ + auto delegate = GetDelegate(info); + ASSERT_NE(delegate, nullptr); + std::shared_ptr virtualCloudDb = GetVirtualCloudDb(); + std::shared_ptr virtualAssetLoader = GetVirtualAssetLoader(); + ASSERT_NE(virtualCloudDb, nullptr); + ASSERT_NE(virtualAssetLoader, nullptr); + ASSERT_EQ(delegate->SetCloudDB(virtualCloudDb), DBStatus::OK); + ASSERT_EQ(delegate->SetIAssetLoader(virtualAssetLoader), DBStatus::OK); + ASSERT_EQ(delegate->SetCloudDbSchema(GetSchema(info)), DBStatus::OK); + LOGI("[RDBGeneralUt] Set cloud db config success, app %s store %s user %s", info.appId.c_str(), + info.storeId.c_str(), info.userId.c_str()); +} + +void RDBGeneralUt::CloudBlockSync(const StoreInfo &info, const Query &query, DBStatus exceptStatus, + DBStatus callbackExpect) +{ + LOGI("[RDBGeneralUt] Begin cloud sync, app %s store %s user %s", info.appId.c_str(), + info.storeId.c_str(), info.userId.c_str()); + auto delegate = GetDelegate(info); + ASSERT_NE(delegate, nullptr); + RelationalTestUtils::CloudBlockSync(query, delegate, exceptStatus, callbackExpect); +} + +int RDBGeneralUt::GetCloudDataCount(const std::string &tableName) const +{ + VBucket extend; + extend[CloudDbConstant::CURSOR_FIELD] = std::to_string(0); + int realCount = 0; + std::vector data; + std::shared_ptr virtualCloudDb = GetVirtualCloudDb(); + if (virtualCloudDb == nullptr) { + LOGE("[RDBGeneralUt] virtual cloud db is nullptr"); + return -1; + } + virtualCloudDb->Query(tableName, extend, data); + for (size_t j = 0; j < data.size(); ++j) { + auto entry = data[j].find(CloudDbConstant::DELETE_FIELD); + if (entry != data[j].end() && std::get(entry->second)) { + continue; + } + realCount++; + } + LOGI("[RDBGeneralUt] Count cloud table %s success, count %d", tableName.c_str(), realCount); + return realCount; +} + +void RDBGeneralUt::SetIsDbEncrypted(bool isdbEncrypted) +{ + isDbEncrypted_ = isdbEncrypted; +} + +bool RDBGeneralUt::GetIsDbEncrypted() const +{ + return isDbEncrypted_; +} + +int RDBGeneralUt::EncryptedDb(sqlite3 *db) +{ + std::string passwd(PASSWD_VECTOR.begin(), PASSWD_VECTOR.end()); + int rc = sqlite3_key(db, passwd.c_str(), passwd.size()); + if (rc != SQLITE_OK) { + sqlite3_close(db); + LOGE("sqlite3_key failed, %d, passwd is %s.", rc, passwd.c_str()); + return -E_INVALID_DB; + } + char *errMsg = nullptr; + int errCode = sqlite3_exec(db, CIPHER_CONFIG_SQL.c_str(), nullptr, nullptr, &errMsg); + if (errCode != SQLITE_OK || errMsg != nullptr) { + LOGE("set cipher failed: %d, cipher is %s.", errCode, CIPHER_CONFIG_SQL.c_str()); + sqlite3_close(db); + sqlite3_free(errMsg); + return -E_INVALID_DB; + } + errMsg = nullptr; + errCode = sqlite3_exec(db, KDF_ITER_CONFIG_SQL.c_str(), nullptr, nullptr, &errMsg); + if (errCode != SQLITE_OK || errMsg != nullptr) { + LOGE("set iterTimes failed: %d, iterTimes is %s.", errCode, KDF_ITER_CONFIG_SQL.c_str()); + sqlite3_close(db); + sqlite3_free(errMsg); + return -E_INVALID_DB; + } + errCode = sqlite3_exec(db, SHA256_ALGO_SQL.c_str(), nullptr, nullptr, &errMsg); + if (errCode != SQLITE_OK || errMsg != nullptr) { + LOGE("set codec_hmac_algo failed: %d, codec_hmac_algo is %s.", errCode, SHA256_ALGO_SQL.c_str()); + sqlite3_close(db); + sqlite3_free(errMsg); + return -E_INVALID_DB; + } + return E_OK; +} + +void RDBGeneralUt::RemoteQuery(const StoreInfo &from, const StoreInfo &to, const std::string &sql, DBStatus expectRet) +{ + auto store = GetDelegate(from); + ASSERT_NE(store, nullptr); + auto toDevice = GetDevice(to); + ASSERT_FALSE(toDevice.empty()); + RemoteCondition condition; + condition.sql = sql; + std::shared_ptr resultSet = nullptr; + EXPECT_EQ(store->RemoteQuery(toDevice, condition, DBConstant::MAX_TIMEOUT, resultSet), expectRet); + EXPECT_NE(resultSet, nullptr); +} + +int RDBGeneralUt::PutMetaData(const StoreInfo &store, const Key &key, const Value &value) +{ + auto db = GetSqliteHandle(store); + if (db == nullptr) { + LOGE("[RDBGeneralUt] Get null sqlite when put meta data userId[%s] appId[%s] storeId[%s]", + store.userId.c_str(), store.appId.c_str(), store.storeId.c_str()); + return -E_INTERNAL_ERROR; + } + return SQLiteRelationalUtils::PutKvData(db, false, key, value); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.h index 1397fcd7..6eebce0a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/rdb_general_ut.h @@ -19,10 +19,12 @@ #include "basic_unit_test.h" #include "rdb_data_generator.h" #include "relational_store_manager.h" +#include "virtual_asset_loader.h" namespace DistributedDB { const std::string g_defaultTable1 = "defaultTable1"; const std::string g_defaultTable2 = "defaultTable2"; +const std::vector PASSWD_VECTOR = {'P', 'a', 's', 's', 'w', 'o', 'r', 'd', '@', '1'}; class RDBGeneralUt : public BasicUnitTest { public: @@ -30,45 +32,80 @@ public: void TearDown() override; protected: int InitDelegate(const StoreInfo &info) override; + std::pair OpenRDBStore(const StoreInfo &info); int CloseDelegate(const StoreInfo &info) override; void CloseAllDelegate() override; // If SetOption is not invoked before InitDelegate is invoked, the default data of Option is used to open store. void SetOption(const RelationalStoreDelegate::Option& option); - // If AddSchemaInfo is not invoked before InitDelegate is invoked, g_defaultSchemaInfo is used to create table. - void AddSchemaInfo(const StoreInfo &info, const DistributedDBUnitTest::UtDateBaseSchemaInfo& schemaInfo); - DataBaseSchema GetSchema(const StoreInfo &info); - TableSchema GetTableSchema(const StoreInfo &info, const std::string &tableName = g_defaultTable1); - std::vector GetAllTrackerSchema(const StoreInfo &info, const std::vector &tables); + // If SetSchemaInfo is not invoked before InitDelegate is invoked, g_defaultSchemaInfo is used to create table. + void SetSchemaInfo(const StoreInfo &info, const DistributedDBUnitTest::UtDateBaseSchemaInfo& schemaInfo); + + DistributedDBUnitTest::UtDateBaseSchemaInfo GetTableSchemaInfo(const StoreInfo &info) const; + DataBaseSchema GetSchema(const StoreInfo &info) const; + TableSchema GetTableSchema(const StoreInfo &info, const std::string &tableName = g_defaultTable1) const; + std::vector GetAllTrackerSchema(const StoreInfo &info, const std::vector &tables) const; + sqlite3 *GetSqliteHandle(const StoreInfo &info) const; + RelationalStoreDelegate *GetDelegate(const StoreInfo &info) const; + RelationalStoreDelegate::Option GetOption() const; int InitDatabase(const StoreInfo &info); int InsertLocalDBData(int64_t begin, int64_t count, const StoreInfo &info); + int ExecuteSQL(const std::string &sql, const StoreInfo &info); + int CreateDistributedTable(const StoreInfo &info, const std::string &table, TableSyncType type = TableSyncType::DEVICE_COOPERATION); int SetDistributedTables(const StoreInfo &info, const std::vector &tables, TableSyncType type = TableSyncType::DEVICE_COOPERATION); + // use for device to device sync void BlockPush(const StoreInfo &from, const StoreInfo &to, const std::string &table, DBStatus expectRet = DBStatus::OK); - DistributedDBUnitTest::UtDateBaseSchemaInfo GetTableSchemaInfo(const StoreInfo &info); - sqlite3 *GetSqliteHandle(const StoreInfo &info); - RelationalStoreDelegate *GetDelegate(const StoreInfo &info); + void BlockPull(const StoreInfo &from, const StoreInfo &to, const std::string &table, + DBStatus expectRet = DBStatus::OK); - int CountTableData(const StoreInfo &info, const std::string &table); + int CountTableData(const StoreInfo &info, const std::string &table, const std::string &condition = ""); - int CountTableDataByDev(const StoreInfo &info, const std::string &table, const std::string &dev); + int CountTableDataByDev(const StoreInfo &info, const std::string &table, const std::string &dev, + const std::string &condition = ""); - int SetTrackerTables(const StoreInfo &info, const std::vector &tables); + int SetTrackerTables(const StoreInfo &info, const std::vector &tables, bool isForce = false); + + // use for cloud sync + std::shared_ptr GetVirtualCloudDb() const; + + std::shared_ptr GetVirtualAssetLoader() const; + + void CloudBlockSync(const StoreInfo &from, const Query &query, DBStatus exceptStatus = OK, + DBStatus callbackExpect = OK); + + void SetCloudDbConfig(const StoreInfo &info) const; + + int GetCloudDataCount(const std::string &tableName) const; + + void SetIsDbEncrypted(bool isdbEncrypted); + bool GetIsDbEncrypted() const; + int EncryptedDb(sqlite3 *db); + + void BlockSync(const StoreInfo &from, const StoreInfo &to, const std::string &table, SyncMode mode, + DBStatus expectRet); + + void RemoteQuery(const StoreInfo &from, const StoreInfo &to, const std::string &sql, DBStatus expectRet); + + int PutMetaData(const StoreInfo &store, const Key &key, const Value &value); - RelationalStoreDelegate::Option option_; mutable std::mutex storeMutex_; - std::map stores_; - std::map sqliteDb_; - std::map schemaInfoMap_; + std::map stores_; + std::map sqliteDb_; + std::map schemaInfoMap_; + std::shared_ptr virtualCloudDb_ = nullptr; + std::shared_ptr virtualAssetLoader_ = nullptr; + RelationalStoreDelegate::Option option_; + bool isDbEncrypted_ = false; }; } #endif // RDB_GENERAL_UT_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/adapter_stub.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/adapter_stub.cpp index 0d2f5c9d..1efe7b63 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/adapter_stub.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/adapter_stub.cpp @@ -122,6 +122,12 @@ int AdapterStub::SendBytes(const std::string &dstTarget, const uint8_t *bytes, u return E_OK; } +int AdapterStub::SendBytes(const DeviceInfos &deviceInfos, const uint8_t *bytes, uint32_t length, + uint32_t totalLength) +{ + return AdapterStub::SendBytes(deviceInfos.identifier, bytes, length, totalLength); +} + int AdapterStub::RegBytesReceiveCallback(const BytesReceiveCallback &onReceive, const Finalizer &inOper) { std::lock_guard onReceiveLockGuard(onReceiveMutex_); @@ -209,12 +215,17 @@ void AdapterStub::DeliverBytes(const std::string &srcTarget, const uint8_t *byte uint32_t headLength = 0; GetDataHeadInfo(bytes, headLength); std::vector userInfos; - GetDataUserInfo(bytes, userInfos); + if (userInfo_.empty()) { + GetDataUserInfo(bytes, userInfos); + } else { + userInfos = userInfo_; + } std::shared_ptr processCommunicator = std::make_shared(); processCommunicator->SetDataUserInfo(userInfos); DataUserInfoProc userInfoProc = {bytes, length, processCommunicator}; - onReceiveHandle_(srcTarget, bytes + headLength, length - headLength, userInfoProc); + ReceiveBytesInfo receiveBytesInfo = {bytes + headLength, srcTarget, length - headLength, headLength != 0}; + onReceiveHandle_(receiveBytesInfo, userInfoProc); } } @@ -242,6 +253,7 @@ void AdapterStub::GetDataUserInfo(const uint8_t *data, std::vector &us break; } userInfo.receiveUser.push_back(info->userId[i]); + userInfo.sendUser.push_back(info->userId[i]); } userInfos.push_back(userInfo); } @@ -449,4 +461,14 @@ void AdapterStub::ApplySendBitError(const uint8_t *bytes, uint32_t length) phyHeader->checkSum = HostToNet(CalculateXorSum(bytes + LENGTH_BEFORE_SUM_RANGE, length - LENGTH_BEFORE_SUM_RANGE)); } +} + +void AdapterStub::SetUserInfo(const std::vector &userInfo) +{ + userInfo_ = userInfo; +} + +std::vector AdapterStub::GetUserInfo() +{ + return userInfo_; } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/adapter_stub.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/adapter_stub.h index 13c8396f..4d719aad 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/adapter_stub.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/adapter_stub.h @@ -42,6 +42,8 @@ public: int GetLocalIdentity(std::string &outTarget) override; int SendBytes(const std::string &dstTarget, const uint8_t *bytes, uint32_t length, uint32_t totalLength) override; + int SendBytes(const DeviceInfos &deviceInfos, const uint8_t *bytes, uint32_t length, + uint32_t totalLength) override; int RegBytesReceiveCallback(const BytesReceiveCallback &onReceive, const Finalizer &inOper) override; int RegTargetChangeCallback(const TargetChangeCallback &onChange, const Finalizer &inOper) override; @@ -85,6 +87,9 @@ public: void SimulateSendBitErrorInPaddingLenField(bool doFlag, uint8_t inPaddingLen); void SimulateSendBitErrorInMessageIdField(bool doFlag, uint32_t inMessageId); void ForkSendBytes(const OnSendBytes &onSendBytes); + + void SetUserInfo(const std::vector &userInfo); + std::vector GetUserInfo(); private: void Connect(AdapterStub *inStub); void Disconnect(AdapterStub *inStub); @@ -137,6 +142,8 @@ private: std::mutex sendBytesMutex_; OnSendBytes onSendBytes_; + + std::vector userInfo_; }; } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp index 9b0b725a..923f1421 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp @@ -56,12 +56,12 @@ void DistributedDBCommunicatorDeepTest::SetUpTestCase(void) * @tc.setup: Create and init CommunicatorAggregator and AdapterStub */ LOGI("[UT][DeepTest][SetUpTestCase] Enter."); - bool errCode = SetUpEnv(g_envDeviceA, DEVICE_NAME_A); - ASSERT_EQ(errCode, true); - errCode = SetUpEnv(g_envDeviceB, DEVICE_NAME_B); - ASSERT_EQ(errCode, true); - errCode = SetUpEnv(g_envDeviceC, DEVICE_NAME_C); - ASSERT_EQ(errCode, true); + bool isSuccess = SetUpEnv(g_envDeviceA, DEVICE_NAME_A); + ASSERT_EQ(isSuccess, true); + isSuccess = SetUpEnv(g_envDeviceB, DEVICE_NAME_B); + ASSERT_EQ(isSuccess, true); + isSuccess = SetUpEnv(g_envDeviceC, DEVICE_NAME_C); + ASSERT_EQ(isSuccess, true); DoRegTransformFunction(); CommunicatorAggregator::EnableCommunicatorNotFoundFeedback(false); } @@ -129,6 +129,9 @@ void DistributedDBCommunicatorDeepTest::TearDown() * @tc.teardown: Release communicator AA, AB, BB, BC, CC, CA */ ReleaseAllCommunicator(); + g_envDeviceA.commAggrHandle->ResetRetryCount(); + g_envDeviceB.commAggrHandle->ResetRetryCount(); + g_envDeviceC.commAggrHandle->ResetRetryCount(); std::this_thread::sleep_for(std::chrono::milliseconds(200)); // Wait 200 ms to make sure all thread quiet } @@ -136,7 +139,7 @@ void DistributedDBCommunicatorDeepTest::TearDown() * @tc.name: WaitAndRetrySend 001 * @tc.desc: Test send retry semantic * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorDeepTest, WaitAndRetrySend001, TestSize.Level2) @@ -145,10 +148,12 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, WaitAndRetrySend001, TestSize.Level2 Message *msgForBB = nullptr; g_commBB->RegOnMessageCallback([&msgForBB](const std::string &srcTarget, Message *inMsg) { msgForBB = inMsg; + return E_OK; }, nullptr); Message *msgForCA = nullptr; g_commCA->RegOnMessageCallback([&msgForCA](const std::string &srcTarget, Message *inMsg) { msgForCA = inMsg; + return E_OK; }, nullptr); /** @@ -169,7 +174,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, WaitAndRetrySend001, TestSize.Level2 */ Message *msgForAB = BuildRegedTinyMessage(); ASSERT_NE(msgForAB, nullptr); - SendConfig conf = {true, false, 0}; + SendConfig conf = {true, false, true, 0}; int errCode = g_commAB->SendMessage(DEVICE_NAME_B, msgForAB, conf); EXPECT_EQ(errCode, E_OK); @@ -195,6 +200,61 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, WaitAndRetrySend001, TestSize.Level2 // CleanUp AdapterStub::DisconnectAdapterStub(g_envDeviceA.adapterHandle, g_envDeviceB.adapterHandle); + AdapterStub::DisconnectAdapterStub(g_envDeviceA.adapterHandle, g_envDeviceC.adapterHandle); +} + +/** + * @tc.name: WaitAndRetrySend002 + * @tc.desc: Test send return retry but task not retry + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCommunicatorDeepTest, WaitAndRetrySend002, TestSize.Level2) +{ + // Preset + Message *msgForCA = nullptr; + g_commCA->RegOnMessageCallback([&msgForCA](const std::string &srcTarget, Message *inMsg) { + msgForCA = inMsg; + return E_OK; + }, nullptr); + + /** + * @tc.steps: step1. connect device A with device B + */ + AdapterStub::ConnectAdapterStub(g_envDeviceA.adapterHandle, g_envDeviceC.adapterHandle); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); // Wait 200 ms to make sure quiet + + /** + * @tc.steps: step2. device A simulate send retry + */ + g_envDeviceA.adapterHandle->SimulateSendRetry(DEVICE_NAME_B); + + /** + * @tc.steps: step3. device A send message to device B using communicator AB + * @tc.expected: step3. communicator BB received no message + */ + Message *msgForAB = BuildRegedTinyMessage(); + ASSERT_NE(msgForAB, nullptr); + SendConfig conf = {true, false, false, 0}; + OnSendEnd onSendEnd = [](int, int) { + LOGI("[WaitAndRetrySend002] on send end."); + }; + int errCode = g_commAB->SendMessage(DEVICE_NAME_B, msgForAB, conf, onSendEnd); + EXPECT_EQ(errCode, E_OK); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Wait 100 ms + EXPECT_EQ(msgForCA, nullptr); + + /** + * @tc.steps: step4. device A simulate sendable feedback + * @tc.expected: step4. communicator BB received the message + */ + g_envDeviceA.adapterHandle->SimulateSendRetryClear(DEVICE_NAME_B); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Wait 100 ms + + // CleanUp + AdapterStub::DisconnectAdapterStub(g_envDeviceA.adapterHandle, g_envDeviceC.adapterHandle); } static int CreateBufferThenAddIntoScheduler(SendTaskScheduler &scheduler, const std::string &dstTarget, Priority inPrio) @@ -223,7 +283,7 @@ static int CreateBufferThenAddIntoScheduler(SendTaskScheduler &scheduler, const * @tc.name: SendSchedule 001 * @tc.desc: Test schedule in Priority order than in send order * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorDeepTest, SendSchedule001, TestSize.Level2) @@ -322,7 +382,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, SendSchedule001, TestSize.Level2) * @tc.name: Fragment 001 * @tc.desc: Test fragmentation in send and receive * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment001, TestSize.Level2) @@ -331,6 +391,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment001, TestSize.Level2) Message *recvMsgForBB = nullptr; g_commBB->RegOnMessageCallback([&recvMsgForBB](const std::string &srcTarget, Message *inMsg) { recvMsgForBB = inMsg; + return E_OK; }, nullptr); /** @@ -345,7 +406,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment001, TestSize.Level2) const uint32_t dataLength = 13 * 1024 * 1024; // 13 MB, 1024 is scale Message *sendMsgForAB = BuildRegedGiantMessage(dataLength); ASSERT_NE(sendMsgForAB, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commAB->SendMessage(DEVICE_NAME_B, sendMsgForAB, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(2600)); // Wait 2600 ms to make sure send done @@ -377,7 +438,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment001, TestSize.Level2) * @tc.name: Fragment 002 * @tc.desc: Test fragmentation in partial loss * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment002, TestSize.Level2) @@ -386,6 +447,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment002, TestSize.Level2) Message *recvMsgForCC = nullptr; g_commCC->RegOnMessageCallback([&recvMsgForCC](const std::string &srcTarget, Message *inMsg) { recvMsgForCC = inMsg; + return E_OK; }, nullptr); /** @@ -406,7 +468,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment002, TestSize.Level2) uint32_t dataLength = 13 * 1024 * 1024; // 13 MB, 1024 is scale Message *sendMsgForBC = BuildRegedGiantMessage(dataLength); ASSERT_NE(sendMsgForBC, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commBC->SendMessage(DEVICE_NAME_C, sendMsgForBC, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(2600)); // Wait 2600 ms to make sure send done @@ -443,7 +505,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment002, TestSize.Level2) * @tc.name: Fragment 003 * @tc.desc: Test fragmentation simultaneously * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment003, TestSize.Level3) @@ -454,6 +516,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment003, TestSize.Level3) delete inMsg; inMsg = nullptr; count.fetch_add(1, std::memory_order_seq_cst); + return E_OK; }; g_commBB->RegOnMessageCallback(callback, nullptr); g_commBC->RegOnMessageCallback(callback, nullptr); @@ -477,7 +540,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment003, TestSize.Level3) uint32_t dataLength = 23 * 1024 * 1024; // 23 MB, 1024 is scale Message *sendMsgForAB = BuildRegedGiantMessage(dataLength); ASSERT_NE(sendMsgForAB, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commAB->SendMessage(DEVICE_NAME_B, sendMsgForAB, conf); EXPECT_EQ(errCode, E_OK); @@ -507,7 +570,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment003, TestSize.Level3) * @tc.name: Fragment 004 * @tc.desc: Test fragmentation in send and receive when rate limit * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment004, TestSize.Level2) @@ -518,6 +581,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment004, TestSize.Level2) Message *recvMsgForBB = nullptr; g_commBB->RegOnMessageCallback([&recvMsgForBB](const std::string &srcTarget, Message *inMsg) { recvMsgForBB = inMsg; + return E_OK; }, nullptr); AdapterStub::ConnectAdapterStub(g_envDeviceA.adapterHandle, g_envDeviceB.adapterHandle); std::atomic count = 0; @@ -535,7 +599,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment004, TestSize.Level2) const uint32_t dataLength = 13 * 1024 * 1024; // 13 MB, 1024 is scale Message *sendMsg = BuildRegedGiantMessage(dataLength); ASSERT_NE(sendMsg, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commAB->SendMessage(DEVICE_NAME_B, sendMsg, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::seconds(1)); // Wait 1s to make sure send done @@ -589,7 +653,7 @@ void ClearPreviousTestCaseInfluence() * @tc.name: ReliableOnline 001 * @tc.desc: Test device online reliability * @tc.type: FUNC - * @tc.require: AR000BVDGJ AR000CQE0N + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorDeepTest, ReliableOnline001, TestSize.Level2) @@ -649,7 +713,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, ReliableOnline001, TestSize.Level2) * @tc.name: NetworkAdapter001 * @tc.desc: Test networkAdapter start func * @tc.type: FUNC - * @tc.require: AR000BVDGJ + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter001, TestSize.Level1) @@ -715,7 +779,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter001, TestSize.Level1) * @tc.name: NetworkAdapter002 * @tc.desc: Test networkAdapter get mtu func * @tc.type: FUNC - * @tc.require: AR000BVDGJ + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter002, TestSize.Level1) @@ -746,7 +810,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter002, TestSize.Level1) * @tc.name: NetworkAdapter003 * @tc.desc: Test networkAdapter get timeout func * @tc.type: FUNC - * @tc.require: AR000BVDGJ + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter003, TestSize.Level1) @@ -775,7 +839,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter003, TestSize.Level1) * @tc.name: NetworkAdapter004 * @tc.desc: Test networkAdapter send bytes func * @tc.type: FUNC - * @tc.require: AR000BVDGJ + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter004, TestSize.Level1) @@ -836,7 +900,7 @@ void InitAdapter(const std::shared_ptr &adapter, * @tc.name: NetworkAdapter005 * @tc.desc: Test networkAdapter receive data func * @tc.type: FUNC - * @tc.require: AR000BVDGJ + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter005, TestSize.Level1) @@ -857,15 +921,15 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter005, TestSize.Level1) /** * @tc.steps: step2. adapter recv data with no permission */ - EXPECT_CALL(*processCommunicator, GetDataHeadInfo).WillRepeatedly([](const uint8_t *, uint32_t, uint32_t &) { + EXPECT_CALL(*processCommunicator, GetDataHeadInfo).WillRepeatedly([](DataHeadInfo, uint32_t &) { return NO_PERMISSION; }); onDataReceive(deviceInfos, data.get(), 1); - EXPECT_CALL(*processCommunicator, GetDataHeadInfo).WillRepeatedly([](const uint8_t *, uint32_t, uint32_t &) { + EXPECT_CALL(*processCommunicator, GetDataHeadInfo).WillRepeatedly([](DataHeadInfo, uint32_t &) { return OK; }); EXPECT_CALL(*processCommunicator, GetDataUserInfo).WillRepeatedly( - [](const uint8_t *, uint32_t, const std::string &, std::vector &userInfos) { + [](DataUserInfo, std::vector &userInfos) { UserInfo userId = {"1"}; userInfos.emplace_back(userId); return OK; @@ -874,7 +938,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter005, TestSize.Level1) * @tc.steps: step3. adapter recv data with no callback */ onDataReceive(deviceInfos, data.get(), 1); - adapter->RegBytesReceiveCallback([](const std::string &, const uint8_t *, uint32_t, const DataUserInfoProc &) { + adapter->RegBytesReceiveCallback([](const ReceiveBytesInfo &, const DataUserInfoProc &) { }, nullptr); onDataReceive(deviceInfos, data.get(), 1); RuntimeContext::GetInstance()->StopTaskPool(); @@ -884,7 +948,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter005, TestSize.Level1) * @tc.name: NetworkAdapter006 * @tc.desc: Test networkAdapter device change func * @tc.type: FUNC - * @tc.require: AR000BVDGJ + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter006, TestSize.Level1) @@ -933,7 +997,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter006, TestSize.Level1) * @tc.name: NetworkAdapter007 * @tc.desc: Test networkAdapter recv invalid head length * @tc.type: FUNC - * @tc.require: AR000BVDGJ + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter007, TestSize.Level1) @@ -948,7 +1012,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter007, TestSize.Level1) * @tc.steps: step1. GetDataHeadInfo return invalid headLen * @tc.expected: step1. adapter check this len */ - EXPECT_CALL(*processCommunicator, GetDataHeadInfo).WillOnce([](const uint8_t *, uint32_t, uint32_t &headLen) { + EXPECT_CALL(*processCommunicator, GetDataHeadInfo).WillOnce([](DataHeadInfo, uint32_t &headLen) { headLen = UINT32_MAX; return OK; }); @@ -957,14 +1021,16 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter007, TestSize.Level1) * @tc.expected: step2. BytesReceive never call */ int callByteReceiveCount = 0; - int res = adapter->RegBytesReceiveCallback([&callByteReceiveCount](const std::string &, const uint8_t *, uint32_t, + int res = adapter->RegBytesReceiveCallback([&callByteReceiveCount](const ReceiveBytesInfo &, const DataUserInfoProc &) { + LOGD("callByteReceiveCount++;"); callByteReceiveCount++; }, nullptr); EXPECT_EQ(res, E_OK); std::vector data = { 1u }; DeviceInfos deviceInfos; onDataReceive(deviceInfos, data.data(), 1u); + LOGD("callByteReceiveCount++%d;", callByteReceiveCount); EXPECT_EQ(callByteReceiveCount, 0); } @@ -999,7 +1065,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, RetrySendExceededLimit001, TestSize. const uint32_t dataLength = 13 * 1024 * 1024; // 13 MB, 1024 is scale Message *sendMsg = BuildRegedGiantMessage(dataLength); ASSERT_NE(sendMsg, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commAB->SendMessage(DEVICE_NAME_B, sendMsg, conf, sendResultNotifier); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::seconds(1)); // Wait 1s to make sure send done @@ -1044,7 +1110,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, RetrySendExceededLimit002, TestSize. const uint32_t dataLength = 13 * 1024 * 1024; // 13 MB, 1024 is scale Message *sendMsg = BuildRegedGiantMessage(dataLength); ASSERT_NE(sendMsg, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; EXPECT_EQ(g_commAB->SendMessage(DEVICE_NAME_B, sendMsg, conf, sendResultNotifier), E_OK); std::this_thread::sleep_for(std::chrono::seconds(1)); // Wait 1s to make sure send done diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_send_receive_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_send_receive_test.cpp index b3f7e8ff..615ec7d7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_send_receive_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_send_receive_test.cpp @@ -138,13 +138,14 @@ static void CheckRecvMessage(Message *recvMsg, bool isEmpty, uint32_t msgId, uin [&srcTargetFor##src##label, &recvMsgFor##src##label](const std::string &srcTarget, Message *inMsg) { \ srcTargetFor##src##label = srcTarget; \ recvMsgFor##src##label = inMsg; \ + return E_OK; \ }, nullptr); /** * @tc.name: Send And Receive 001 * @tc.desc: Test send and receive based on equipment communicator * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive001, TestSize.Level1) @@ -165,7 +166,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive001, TestSize.L */ Message *msgForAA = BuildRegedTinyMessage(); ASSERT_NE(msgForAA, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0, {}}; int errCode = g_commAA->SendMessage(DEVICE_NAME_B, msgForAA, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(200)); // sleep 200 ms @@ -193,7 +194,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive001, TestSize.L * @tc.name: Send And Receive 002 * @tc.desc: Test send oversize message will fail * @tc.type: FUNC - * @tc.require: AR000BVDGK AR000CQE0O + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive002, TestSize.Level1) @@ -209,7 +210,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive002, TestSize.L */ Message *msgForAA = BuildRegedOverSizeMessage(); ASSERT_NE(msgForAA, nullptr); - SendConfig conf = {true, false, 0}; + SendConfig conf = {true, false, true, 0}; int errCode = g_commAA->SendMessage(DEVICE_NAME_B, msgForAA, conf); EXPECT_NE(errCode, E_OK); delete msgForAA; @@ -223,7 +224,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive002, TestSize.L * @tc.name: Send And Receive 003 * @tc.desc: Test send unregistered message will fail * @tc.type: FUNC - * @tc.require: AR000BVDGK AR000CQE0O + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive003, TestSize.Level1) @@ -239,7 +240,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive003, TestSize.L */ Message *msgForAA = BuildUnRegedTinyMessage(); ASSERT_NE(msgForAA, nullptr); - SendConfig conf = {true, false, 0}; + SendConfig conf = {true, false, true, 0}; int errCode = g_commAA->SendMessage(DEVICE_NAME_B, msgForAA, conf); EXPECT_NE(errCode, E_OK); delete msgForAA; @@ -292,13 +293,13 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive004, TestSize.L ASSERT_NE(msgForAAUser1, nullptr); Message *msgForAAUser2 = BuildRegedGiantMessage(HUGE_SIZE + HUGE_SIZE); ASSERT_NE(msgForAAUser2, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commAA->SendMessage(DEVICE_NAME_B, msgForAA, conf); EXPECT_EQ(errCode, E_OK); - SendConfig confUser1 = {false, true, 0, {"appId", "storeId", USER_ID_1, "DeviceB", ""}}; + SendConfig confUser1 = {false, true, true, 0, {"appId", "storeId", USER_ID_1, "DeviceB", ""}}; errCode = g_commAA->SendMessage(DEVICE_NAME_B, msgForAAUser1, confUser1); EXPECT_EQ(errCode, E_OK); - SendConfig confUser2 = {false, true, 0, {"appId", "storeId", USER_ID_2, "DeviceB", ""}}; + SendConfig confUser2 = {false, true, true, 0, {"appId", "storeId", USER_ID_2, "DeviceB", ""}}; errCode = g_commAA->SendMessage(DEVICE_NAME_B, msgForAAUser2, confUser2); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); @@ -324,7 +325,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceive004, TestSize.L * @tc.name: Send Flow Control 001 * @tc.desc: Test send in nonblock way * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl001, TestSize.Level1) @@ -357,7 +358,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl001, TestSize. while (true) { Message *msgForBA = BuildRegedHugeMessage(); ASSERT_NE(msgForBA, nullptr); - SendConfig conf = {true, false, 0}; + SendConfig conf = {true, false, true, 0}; int errCode = g_commBA->SendMessage(DEVICE_NAME_A, msgForBA, conf); if (errCode == E_OK) { sendCount++; @@ -388,7 +389,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl001, TestSize. * @tc.name: Send Flow Control 002 * @tc.desc: Test send in block(without timeout) way * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl002, TestSize.Level1) @@ -422,7 +423,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl002, TestSize. while (sendCount < SEND_COUNT_GOAL) { Message *msgForBA = BuildRegedHugeMessage(); ASSERT_NE(msgForBA, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commBA->SendMessage(DEVICE_NAME_A, msgForBA, conf); if (errCode != E_OK) { delete msgForBA; @@ -454,7 +455,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl002, TestSize. * @tc.name: Send Flow Control 003 * @tc.desc: Test send in block(with timeout) way * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl003, TestSize.Level1) @@ -488,7 +489,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl003, TestSize. while (sendCnt < SEND_COUNT_GOAL) { Message *msgForBA = BuildRegedHugeMessage(); ASSERT_NE(msgForBA, nullptr); - SendConfig conf = {false, false, 100}; + SendConfig conf = {false, false, true, 100}; int errCode = g_commBA->SendMessage(DEVICE_NAME_A, msgForBA, conf); // 100 ms timeout if (errCode != E_OK) { delete msgForBA; @@ -520,7 +521,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendFlowControl003, TestSize. * @tc.name: Receive Check 001 * @tc.desc: Receive packet field check * @tc.type: FUNC - * @tc.require: AR000BVRNU AR000CQE0J + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, ReceiveCheck001, TestSize.Level1) @@ -533,6 +534,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, ReceiveCheck001, TestSize.Lev delete inMsg; inMsg = nullptr; } + return E_OK; }, nullptr); AdapterStub::ConnectAdapterStub(g_envDeviceA.adapterHandle, g_envDeviceB.adapterHandle); @@ -542,7 +544,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, ReceiveCheck001, TestSize.Lev */ g_envDeviceB.adapterHandle->SimulateSendBitErrorInMagicField(true, 0xFFFF); Message *msgForBA = BuildRegedTinyMessage(); - SendConfig conf = {true, false, 0}; + SendConfig conf = {true, false, true, 0}; int errCode = g_commBA->SendMessage(DEVICE_NAME_A, msgForBA, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(100)); @@ -581,7 +583,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, ReceiveCheck001, TestSize.Lev * @tc.name: Receive Check 002 * @tc.desc: Receive packet field check * @tc.type: FUNC - * @tc.require: AR000BVRNU AR000CQE0J + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, ReceiveCheck002, TestSize.Level1) @@ -594,6 +596,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, ReceiveCheck002, TestSize.Lev delete inMsg; inMsg = nullptr; } + return E_OK; }, nullptr); AdapterStub::ConnectAdapterStub(g_envDeviceA.adapterHandle, g_envDeviceB.adapterHandle); @@ -603,7 +606,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, ReceiveCheck002, TestSize.Lev */ g_envDeviceB.adapterHandle->SimulateSendBitErrorInPacketLenField(true, 0xFFFF); Message *msgForBA = BuildRegedTinyMessage(); - SendConfig conf = {true, false, 0}; + SendConfig conf = {true, false, true, 0}; int errCode = g_commBA->SendMessage(DEVICE_NAME_A, msgForBA, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(100)); @@ -642,7 +645,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, ReceiveCheck002, TestSize.Lev * @tc.name: Send Result Notify 001 * @tc.desc: Test send result notify * @tc.type: FUNC - * @tc.require: AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendResultNotify001, TestSize.Level1) @@ -664,7 +667,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendResultNotify001, TestSize */ Message *msgForAA = BuildRegedTinyMessage(); ASSERT_NE(msgForAA, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commAA->SendMessage(DEVICE_NAME_B, msgForAA, conf, sendResultNotifier); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Sleep 100 ms @@ -693,7 +696,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendResultNotify001, TestSize * @tc.name: Message Feedback 001 * @tc.desc: Test feedback not support messageid and communicator not found * @tc.type: FUNC - * @tc.require: AR000CQE0M + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, MessageFeedback001, TestSize.Level1) @@ -715,7 +718,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, MessageFeedback001, TestSize. */ Message *msgForBB = BuildRegedTinyMessage(); ASSERT_NE(msgForBB, nullptr); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; int errCode = g_commBB->SendMessage(DEVICE_NAME_A, msgForBB, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Sleep 100 ms @@ -765,7 +768,7 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, MessageFeedback001, TestSize. * @tc.name: SendAndReceiveWithExtendHead001 * @tc.desc: Test fill extendHead func * @tc.type: FUNC - * @tc.require: AR000BVDGI AR000CQE0M + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceiveWithExtendHead001, TestSize.Level1) @@ -786,7 +789,9 @@ HWTEST_F(DistributedDBCommunicatorSendReceiveTest, SendAndReceiveWithExtendHead0 */ Message *msgForAA = BuildAppLayerFrameMessage(); ASSERT_NE(msgForAA, nullptr); - SendConfig conf = {false, true, 0, {"appId", "storeId", "", "DeviceB"}}; + UserInfo userInfo = {"", "userId"}; + g_envDeviceB.adapterHandle->SetUserInfo({userInfo}); + SendConfig conf = {false, true, true, 0, {"appId", "storeId", "", "DeviceB"}}; int errCode = g_commAA->SendMessage(DEVICE_NAME_B, msgForAA, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(200)); // sleep 200 ms diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_test.cpp index 8cda98e6..3106e52a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_test.cpp @@ -15,6 +15,7 @@ #include #include +#include "communicator.h" #include "db_common.h" #include "db_errno.h" #include "distributeddb_communicator_common.h" @@ -100,7 +101,7 @@ void DistributedDBCommunicatorTest::TearDown() * @tc.name: Communicator Management 001 * @tc.desc: Test alloc and release communicator * @tc.type: FUNC - * @tc.require: AR000BVDGG AR000CQE0L + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorTest, CommunicatorManagement001, TestSize.Level1) @@ -215,7 +216,7 @@ static void ConnectWaitDisconnect() * @tc.name: Online And Offline 001 * @tc.desc: Test functionality triggered by physical devices online and offline * @tc.type: FUNC - * @tc.require: AR000BVRNS AR000CQE0H + * @tc.require: * @tc.author: wudongxing */ HWTEST_F(DistributedDBCommunicatorTest, OnlineAndOffline001, TestSize.Level1) @@ -323,7 +324,7 @@ HWTEST_F(DistributedDBCommunicatorTest, OnlineAndOffline001, TestSize.Level1) * @tc.name: Online And Offline 002 * @tc.desc: Test functionality triggered by alloc and release communicator * @tc.type: FUNC - * @tc.require: AR000BVRNT AR000CQE0I + * @tc.require: * @tc.author: wudongxing */ HWTEST_F(DistributedDBCommunicatorTest, OnlineAndOffline002, TestSize.Level1) @@ -492,7 +493,7 @@ void TestRemoteRestart() * @tc.name: Online And Offline 003 * @tc.desc: Test functionality triggered by remote restart * @tc.type: FUNC - * @tc.require: AR000CQE0I + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, OnlineAndOffline003, TestSize.Level1) @@ -504,7 +505,7 @@ HWTEST_F(DistributedDBCommunicatorTest, OnlineAndOffline003, TestSize.Level1) * @tc.name: Online And Offline 004 * @tc.desc: Test functionality triggered by remote restart with thread pool * @tc.type: FUNC - * @tc.require: AR000CQE0I + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, OnlineAndOffline004, TestSize.Level1) @@ -519,7 +520,7 @@ HWTEST_F(DistributedDBCommunicatorTest, OnlineAndOffline004, TestSize.Level1) * @tc.name: Report Device Connect Change 001 * @tc.desc: Test CommunicatorAggregator support report device connect change event * @tc.type: FUNC - * @tc.require: AR000DR9KV + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorTest, ReportDeviceConnectChange001, TestSize.Level1) @@ -584,7 +585,7 @@ LabelType ToLabelType(uint64_t commLabel) * @tc.name: Report Communicator Not Found 001 * @tc.desc: Test CommunicatorAggregator support report communicator not found event * @tc.type: FUNC - * @tc.require: AR000DR9KV + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorTest, ReportCommunicatorNotFound001, TestSize.Level1) @@ -614,7 +615,7 @@ HWTEST_F(DistributedDBCommunicatorTest, ReportCommunicatorNotFound001, TestSize. ASSERT_NOT_NULL_AND_ACTIVATE(commAA, ""); Message *msgForAA = BuildRegedTinyMessage(); ASSERT_NE(msgForAA, nullptr); - SendConfig conf = {true, false, 0}; + SendConfig conf = {true, false, true, 0}; errCode = commAA->SendMessage(DEVICE_NAME_B, msgForAA, conf); EXPECT_EQ(errCode, E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Sleep 100 ms @@ -630,6 +631,7 @@ HWTEST_F(DistributedDBCommunicatorTest, ReportCommunicatorNotFound001, TestSize. Message *recvMsgForBA = nullptr; commBA->RegOnMessageCallback([&recvMsgForBA](const std::string &srcTarget, Message *inMsg) { recvMsgForBA = inMsg; + return E_OK; }, nullptr); commBA->Activate(USER_ID_1); std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Sleep 100 ms @@ -647,7 +649,7 @@ HWTEST_F(DistributedDBCommunicatorTest, ReportCommunicatorNotFound001, TestSize. Message *msgFor##src##label = BuildRegedTinyMessage(); \ ASSERT_NE(msgFor##src##label, nullptr); \ msgFor##src##label->SetSessionId(session); \ - SendConfig conf = {true, false, 0}; \ + SendConfig conf = {true, false, true, 0}; \ errCode = comm##src##label->SendMessage(DEVICE_NAME_##dst, msgFor##src##label, conf); \ EXPECT_EQ(errCode, E_OK); \ } @@ -656,7 +658,7 @@ HWTEST_F(DistributedDBCommunicatorTest, ReportCommunicatorNotFound001, TestSize. { \ Message *msgFor##src##label = BuildRegedGiantMessage(size); \ ASSERT_NE(msgFor##src##label, nullptr); \ - SendConfig conf = {false, false, 0}; \ + SendConfig conf = {false, false, true, 0}; \ errCode = comm##src##label->SendMessage(DEVICE_NAME_##dst, msgFor##src##label, conf); \ EXPECT_EQ(errCode, E_OK); \ } @@ -673,13 +675,14 @@ HWTEST_F(DistributedDBCommunicatorTest, ReportCommunicatorNotFound001, TestSize. [&srcTargetFor##src##label, &recvMsgFor##src##label](const std::string &srcTarget, Message *inMsg) { \ srcTargetFor##src##label = srcTarget; \ recvMsgFor##src##label = inMsg; \ + return E_OK; \ }, nullptr); /** * @tc.name: ReDeliver Message 001 * @tc.desc: Test CommunicatorAggregator support redeliver message * @tc.type: FUNC - * @tc.require: AR000DR9KV + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorTest, ReDeliverMessage001, TestSize.Level1) @@ -762,7 +765,7 @@ HWTEST_F(DistributedDBCommunicatorTest, ReDeliverMessage001, TestSize.Level1) * @tc.name: ReDeliver Message 002 * @tc.desc: Test CommunicatorAggregator support redeliver message by order * @tc.type: FUNC - * @tc.require: AR000DR9KV + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorTest, ReDeliverMessage002, TestSize.Level1) @@ -814,6 +817,7 @@ HWTEST_F(DistributedDBCommunicatorTest, ReDeliverMessage002, TestSize.Level1) std::vector> msgCallbackForBA; commBA->RegOnMessageCallback([&msgCallbackForBA](const std::string &srcTarget, Message *inMsg) { msgCallbackForBA.push_back({srcTarget, inMsg}); + return E_OK; }, nullptr); commBA->Activate(); std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Sleep 100 ms @@ -842,7 +846,7 @@ HWTEST_F(DistributedDBCommunicatorTest, ReDeliverMessage002, TestSize.Level1) * @tc.name: ReDeliver Message 003 * @tc.desc: For observe memory in unusual scenario * @tc.type: FUNC - * @tc.require: AR000DR9KV + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBCommunicatorTest, ReDeliverMessage003, TestSize.Level2) @@ -940,7 +944,7 @@ namespace { * @tc.name: CommunicationOptimization001 * @tc.desc: Test notify with isSupport true. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization001, TestSize.Level3) @@ -1019,7 +1023,7 @@ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization001, TestSize.L * @tc.name: CommunicationOptimization002 * @tc.desc: Test notify with isSupport true and can offline by device change. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization002, TestSize.Level3) @@ -1077,7 +1081,7 @@ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization002, TestSize.L * @tc.name: CommunicationOptimization003 * @tc.desc: Test notify with isSupport false. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization003, TestSize.Level3) @@ -1146,7 +1150,7 @@ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization003, TestSize.L * @tc.name: CommunicationOptimization004 * @tc.desc: Test notify with isSupport false and it be will changed by communication. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization004, TestSize.Level3) @@ -1195,7 +1199,7 @@ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization004, TestSize.L * @tc.name: CommunicationOptimization005 * @tc.desc: Test notify with isSupport false and send label exchange. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization005, TestSize.Level3) @@ -1248,7 +1252,7 @@ HWTEST_F(DistributedDBCommunicatorTest, CommunicationOptimization005, TestSize.L * @tc.name: DbStatusAdapter001 * @tc.desc: Test notify with isSupport false. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter001, TestSize.Level1) @@ -1307,7 +1311,7 @@ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter001, TestSize.Level1) * @tc.name: DbStatusAdapter002 * @tc.desc: Test adapter clear cache. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter002, TestSize.Level1) { @@ -1326,7 +1330,7 @@ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter002, TestSize.Level1) { * @tc.name: DbStatusAdapter003 * @tc.desc: Test adapter get local dbInfo. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter003, TestSize.Level1) { @@ -1347,7 +1351,7 @@ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter003, TestSize.Level1) { * @tc.name: DbStatusAdapter004 * @tc.desc: Test adapter clear cache will get callback. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter004, TestSize.Level1) @@ -1390,7 +1394,7 @@ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter004, TestSize.Level1) * @tc.name: DbStatusAdapter005 * @tc.desc: Test adapter is need auto sync. * @tc.type: FUNC - * @tc.require: AR000HGD0B + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter005, TestSize.Level1) @@ -1410,4 +1414,39 @@ HWTEST_F(DistributedDBCommunicatorTest, DbStatusAdapter005, TestSize.Level1) adapterA->SetDBInfoHandle(nullptr); EXPECT_EQ(adapterA->IsNeedAutoSync(USER_ID, APP_ID, STORE_ID_1, deviceB), true); } + +/** + * @tc.name: AbnormalCommunicatorTest001 + * @tc.desc: Test communicator abnormal. + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBCommunicatorTest, AbnormalCommunicatorTest001, TestSize.Level1) +{ + ICommunicator *commAA = nullptr; + g_envDeviceA.commAggrHandle->ReleaseCommunicator(commAA); + EXPECT_EQ(commAA, nullptr); + int errCode = E_OK; + commAA = g_envDeviceA.commAggrHandle->AllocCommunicator(LABEL_A, errCode); + SendConfig conf = {true, false, true, 0}; + Message *msgForAA = nullptr; + errCode = commAA->SendMessage(DEVICE_NAME_A, msgForAA, conf); + EXPECT_NE(errCode, E_OK); + msgForAA = BuildRegedTinyMessage(); + ASSERT_NE(msgForAA, nullptr); + errCode = commAA->SendMessage("", msgForAA, conf); + EXPECT_NE(errCode, E_OK); + errCode = commAA->SendMessage(DEVICE_NAME_B, msgForAA, conf); + EXPECT_EQ(errCode, E_OK); + EXPECT_EQ(commAA->GetTargetUserId({}), std::string("")); + g_envDeviceA.commAggrHandle->ClearOnlineLabel(); + std::vector label; + auto aggregator = std::make_shared(); + ASSERT_NE(aggregator, nullptr); + auto communicator = std::make_shared(aggregator.get(), label); + ASSERT_NE(communicator, nullptr); + EXPECT_EQ(communicator->GetTargetUserId({}), DBConstant::DEFAULT_USER); + g_envDeviceA.commAggrHandle->ReleaseCommunicator(commAA); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/mock_process_communicator.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/mock_process_communicator.h index 0c60f3ea..24e46f61 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/mock_process_communicator.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/mock_process_communicator.h @@ -30,8 +30,8 @@ public: MOCK_METHOD0(GetLocalDeviceInfos, DeviceInfos()); MOCK_METHOD0(GetRemoteOnlineDeviceInfosList, std::vector()); MOCK_METHOD1(IsSameProcessLabelStartedOnPeerDevice, bool(const DeviceInfos &)); - MOCK_METHOD3(GetDataHeadInfo, DBStatus(const uint8_t *, uint32_t, uint32_t &)); - MOCK_METHOD4(GetDataUserInfo, DBStatus(const uint8_t *, uint32_t, const std::string &, std::vector &)); + MOCK_METHOD2(GetDataUserInfo, DBStatus(DataUserInfo, std::vector &)); + MOCK_METHOD2(GetDataHeadInfo, DBStatus(DataHeadInfo, uint32_t &)); }; } #endif // MOCK_PROCESS_COMMUNICATOR_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_reference_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_reference_test.cpp index 97d452cb..b411d4d8 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_reference_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_reference_test.cpp @@ -20,7 +20,9 @@ #include "db_constant.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" +#include "relational_store_delegate_impl.h" #include "relational_store_manager.h" +#include "virtual_communicator_aggregator.h" using namespace testing::ext; using namespace DistributedDB; @@ -35,6 +37,7 @@ namespace { std::string g_storePath; DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); RelationalStoreDelegate *g_delegate = nullptr; + VirtualCommunicatorAggregator *g_communicatorAggregator = nullptr; class DistributedDBCloudInterfacesReferenceTest : public testing::Test { public: @@ -59,6 +62,9 @@ namespace { void DistributedDBCloudInterfacesReferenceTest::SetUp(void) { + g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(g_communicatorAggregator != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator); sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath); ASSERT_NE(db, nullptr); EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); @@ -74,6 +80,7 @@ namespace { EXPECT_EQ(g_mgr.CloseStore(g_delegate), OK); g_delegate = nullptr; DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); } /** @@ -493,7 +500,7 @@ namespace { * @tc.require: * @tc.author: zhangshjie */ - HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest010, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest010, TestSize.Level1) { NormalSetReferenceTest(true); } @@ -541,11 +548,7 @@ namespace { * @tc.expected: step3. Return OK or PROPERTY_CHANGED. */ tableReferenceProperty.targetTableName = "t3"; - if (isTableEmpty) { - EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); - } else { - EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); - } + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); /** * @tc.steps:step4. set reference again with different column reference @@ -553,11 +556,7 @@ namespace { */ columns["id"] = "value"; tableReferenceProperty.columns = columns; - if (isTableEmpty) { - EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); - } else { - EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); - } + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); } @@ -569,7 +568,7 @@ namespace { * @tc.require: * @tc.author: zhangshjie */ - HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest011, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest011, TestSize.Level1) { ReferenceChangeTest(true); } @@ -581,7 +580,7 @@ namespace { * @tc.require: * @tc.author: zhangshjie */ - HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest012, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest012, TestSize.Level1) { ReferenceChangeTest(false); } @@ -593,7 +592,7 @@ namespace { * @tc.require: * @tc.author: zhangshjie */ - HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest013, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest013, TestSize.Level1) { /** * @tc.steps:step1. prepare table and distributed table @@ -669,7 +668,7 @@ namespace { * @tc.require: * @tc.author: zhangshjie */ - HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest014, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest014, TestSize.Level1) { /** * @tc.steps:step1. prepare table and distributed table @@ -755,7 +754,7 @@ namespace { * @tc.require: * @tc.author: zhangshjie */ - HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest015, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest015, TestSize.Level1) { /** * @tc.steps:step1. prepare table and distributed table @@ -802,7 +801,7 @@ namespace { * @tc.require: * @tc.author: zhangshjie */ - HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest016, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest016, TestSize.Level1) { /** * @tc.steps:step1. prepare table and distributed table, then set reference t1->t2 @@ -843,7 +842,7 @@ namespace { */ tableReferenceProperty.sourceTableName = "t2"; tableReferenceProperty.targetTableName = "t3"; - EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); } /** @@ -884,4 +883,36 @@ namespace { tableReferenceProperty.columns = columns; EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); } + + /** + * @tc.name: FuncExceptionTest001 + * @tc.desc: Test the interception expection of the delegate interface when the conn is empty. + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, FuncExceptionTest001, TestSize.Level1) + { + RelationalStoreConnection *iConn = nullptr; + std::string iPath = ""; + auto iDelegate = std::make_shared(iConn, iPath); + EXPECT_EQ(iDelegate->SetStoreConfig({}), OK); + EXPECT_EQ(iDelegate->SetStoreConfig({DistributedTableMode::COLLABORATION}), DB_ERROR); + + ClearMetaDataOption iOption; + iOption.tableNameList.insert(STORE_ID); + #ifdef USE_DISTRIBUTEDDB_CLOUD + EXPECT_EQ(iDelegate->ClearMetaData(iOption), NOT_SUPPORT); + iOption.tableNameList.clear(); + EXPECT_EQ(iDelegate->ClearMetaData(iOption), DB_ERROR); + #endif + iOption.mode = ClearMetaDataMode::BUTT; + EXPECT_EQ(iDelegate->ClearMetaData(iOption), INVALID_ARGS); + + EXPECT_EQ(iDelegate->GetDownloadingAssetsCount().first, DB_ERROR); + EXPECT_EQ(iDelegate->SetDistributedSchema({}, false), DB_ERROR); + + iDelegate->SetReleaseFlag(false); + iDelegate = nullptr; + } } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_client_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_client_test.cpp new file mode 100644 index 00000000..050b2233 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_client_test.cpp @@ -0,0 +1,1477 @@ +/* + * 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 "cloud_db_sync_utils_test.h" +#include "cloud_sync_log_table_manager.h" +#include "distributeddb_tools_unit_test.h" +#include "relational_store_client.h" +#include "simple_tracker_log_table_manager.h" +#include "sqlite_relational_utils.h" +#include "table_info.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; +using namespace std; + +namespace { +constexpr const char *DB_SUFFIX = ".db"; +constexpr const char *STORE_ID = "Relational_Store_ID"; +std::string g_dbDir; +std::string g_testDir; + +constexpr int E_ERROR = 1; +const int WAIT_TIME = 1000; // 1000ms +constexpr static uint64_t TO_100_NS = 10; // 1us to 100ns +const uint64_t MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS = 1000000; +std::mutex g_mutex; +std::condition_variable g_cv; +bool g_alreadyNotify = false; + +class DistributedDBCloudInterfacesRelationalExtClientTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp() override; + void TearDown() override; + void CheckTriggerObserverTest002(const std::string &tableName, std::atomic &count); + + void ClientObserverFunc(ClientChangedData &clientChangedData) + { + for (const auto &tableEntry : clientChangedData.tableData) { + LOGD("client observer fired, table: %s", tableEntry.first.c_str()); + triggerTableData_.insert_or_assign(tableEntry.first, tableEntry.second); + } + triggeredCount_++; + { + std::unique_lock lock(g_mutex); + g_alreadyNotify = true; + } + g_cv.notify_one(); + } + + void ClientObserverFunc2(ClientChangedData &clientChangedData) + { + triggeredCount2_++; + { + std::unique_lock lock(g_mutex); + g_alreadyNotify = true; + } + g_cv.notify_one(); + } + + void CheckTriggerTableData(size_t dataSize, const std::string &tableName, ChangeProperties &properties, + int triggerCount) + { + ASSERT_EQ(triggerTableData_.size(), dataSize); + EXPECT_EQ(triggerTableData_.begin()->first, tableName); + EXPECT_EQ(triggerTableData_.begin()->second.isTrackedDataChange, properties.isTrackedDataChange); + EXPECT_EQ(triggeredCount_, triggerCount); + } + + void WaitAndResetNotify() + { + std::unique_lock lock(g_mutex); + WaitAndResetNotifyWithLock(lock); + } + + void WaitAndResetNotifyWithLock(std::unique_lock &lock) + { + g_cv.wait(lock, []() { + return g_alreadyNotify; + }); + g_alreadyNotify = false; + } + + std::map triggerTableData_; + int triggeredCount_ = 0; + int triggeredCount2_ = 0; +}; + +void DistributedDBCloudInterfacesRelationalExtClientTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + LOGD("Test dir is %s", g_testDir.c_str()); + g_dbDir = g_testDir + "/"; + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); +} + +void DistributedDBCloudInterfacesRelationalExtClientTest::TearDownTestCase(void) +{ +} + +void DistributedDBCloudInterfacesRelationalExtClientTest::SetUp() +{ +} + +void DistributedDBCloudInterfacesRelationalExtClientTest::TearDown() +{ + g_alreadyNotify = false; + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); +} + +void DistributedDBCloudInterfacesRelationalExtClientTest::CheckTriggerObserverTest002(const std::string &tableName, + std::atomic &count) +{ + count++; + ASSERT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(triggerTableData_.begin()->first, tableName); + EXPECT_EQ(triggerTableData_.begin()->second.isTrackedDataChange, false); + EXPECT_EQ(triggeredCount_, count); +} + +static int GetCurrentSysTimeIn100Ns(uint64_t &outTime) +{ + struct timeval rawTime; + int errCode = gettimeofday(&rawTime, nullptr); + if (errCode < 0) { + return -E_ERROR; + } + outTime = static_cast(rawTime.tv_sec) * MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS + + static_cast(rawTime.tv_usec); + outTime *= TO_100_NS; + return E_OK; +} + +static void ExecSqlAndWaitForObserver(sqlite3 *db, const std::string &sql, std::unique_lock &lock) +{ + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + g_cv.wait(lock, []() { + return g_alreadyNotify; + }); + g_alreadyNotify = false; +} + +/** + * @tc.name: GetRawSysTimeTest001 + * @tc.desc: Test get_raw_sys_time has been registered in sqlite + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, GetRawSysTimeTest001, TestSize.Level0) +{ + const std::string sql = "select get_raw_sys_time();"; + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + uint64_t curTime = 0; + int errCode = GetCurrentSysTimeIn100Ns(curTime); + EXPECT_EQ(errCode, E_OK); + errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [curTime] (sqlite3_stmt *stmt) { + EXPECT_GT(static_cast(sqlite3_column_int64(stmt, 0)), curTime); + return E_OK; + }); + EXPECT_EQ(errCode, SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +static void PrepareData(const std::vector &tableNames, bool primaryKeyIsRowId, + DistributedDB::TableSyncType tableSyncType, bool userDefineRowid = true, bool createDistributeTable = true) +{ + /** + * @tc.steps:step1. create db, create table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + std::string sql; + for (const auto &tableName : tableNames) { + if (primaryKeyIsRowId) { + sql = "create table " + tableName + "(rowid INTEGER primary key, id int, name TEXT);"; + } else { + if (userDefineRowid) { + sql = "create table " + tableName + "(rowid int, id int, name TEXT, PRIMARY KEY(id));"; + } else { + sql = "create table " + tableName + "(id int, name TEXT, PRIMARY KEY(id));"; + } + } + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + + /** + * @tc.steps:step2. create distributed table. + * @tc.expected: step2. return ok. + */ + if (createDistributeTable) { + for (const auto &tableName : tableNames) { + TableInfo table; + table.SetTableName(tableName); + table.SetTableSyncType(tableSyncType); + std::unique_ptr tableManager = std::make_unique(); + EXPECT_NE(tableManager, nullptr); + EXPECT_EQ(SQLiteUtils::AnalysisSchema(db, tableName, table), E_OK); + std::vector fieldInfos = table.GetFieldInfos(); + EXPECT_EQ(SQLiteRelationalUtils::CreateRelationalMetaTable(db), E_OK); + EXPECT_EQ(SQLiteRelationalUtils::InitCursorToMeta(db, false, tableName), E_OK); + EXPECT_EQ(tableManager->CreateRelationalLogTable(db, table), E_OK); + EXPECT_EQ(tableManager->AddRelationalLogTableTrigger(db, table, ""), E_OK); + EXPECT_EQ(SQLiteRelationalUtils::SetLogTriggerStatus(db, true), E_OK); + } + } + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +static void SaveTrackerSchemaToMetaTable(sqlite3 *db, const std::string tableName, const TableInfo &tableInfo) +{ + RelationalSchemaObject tracker; + tracker.SetTableMode(DistributedDB::DistributedTableMode::SPLIT_BY_DEVICE); + tracker.RemoveRelationalTable(tableName); + tracker.AddRelationalTable(tableInfo); + const Key schemaKey(DBConstant::RELATIONAL_SCHEMA_KEY, + DBConstant::RELATIONAL_SCHEMA_KEY + strlen(DBConstant::RELATIONAL_SCHEMA_KEY)); + Value schemaVal; + auto schemaStr = tracker.ToSchemaString(); + EXPECT_FALSE(schemaStr.size() > SchemaConstant::SCHEMA_STRING_SIZE_LIMIT); + DBCommon::StringToVector(schemaStr, schemaVal); + EXPECT_EQ(SQLiteRelationalUtils::PutKvData(db, false, schemaKey, schemaVal), E_OK); +} + +static void SetTracerSchema(const std::vector &tableNames, DistributedDB::TableSyncType tableSyncType) +{ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + for (const auto &tableName : tableNames) { + TableInfo tableInfo; + tableInfo.SetTableName(tableName); + tableInfo.SetTableSyncType(tableSyncType); + std::unique_ptr tableManager = std::make_unique(); + EXPECT_NE(tableManager, nullptr); + TrackerSchema schema; + schema.tableName = tableName; + schema.extendColNames = {"id"}; + schema.trackerColNames = {"name"}; + TrackerTable trackerTable; + trackerTable.Init(schema); + EXPECT_EQ(SQLiteRelationalUtils::AnalysisTrackerTable(db, trackerTable, tableInfo), E_OK); + EXPECT_EQ(tableManager->CreateRelationalLogTable(db, tableInfo), E_OK); + EXPECT_EQ(SQLiteRelationalUtils::InitCursorToMeta(db, false, tableName), E_OK); + EXPECT_EQ(SQLiteRelationalUtils::SetLogTriggerStatus(db, true), E_OK); + EXPECT_EQ(tableManager->AddRelationalLogTableTrigger(db, tableInfo, ""), E_OK); + SaveTrackerSchemaToMetaTable(db, tableName, tableInfo); + } + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: InsertTriggerTest003 + * @tc.desc: Test insert trigger in sqlite when use "insert or replace" + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, InsertTriggerTest003, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION); + + /** + * @tc.steps:step2. insert data into sync_data. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + std::string sql = "insert into " + tableName + " VALUES(2, 1, 'zhangsan1');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + // update cloud_gid in log table + std::string gid = "test_gid"; + sql = "update " + DBCommon::GetLogTableName(tableName) + " set cloud_gid = '" + gid + "'"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + // use insert or replace to update data + sql = "insert or replace into " + tableName + " VALUES(3, 1, 'zhangsan1');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + /** + * @tc.steps:step3. select data from log table. + * @tc.expected: step3. return ok. + */ + sql = "select data_key, device, ori_device, flag, cloud_gid from " + DBCommon::GetLogTableName(tableName); + int resultCount = 0; + int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [&resultCount, gid] (sqlite3_stmt *stmt) { + EXPECT_EQ(sqlite3_column_int64(stmt, 0), 2); // 2 is row id + std::string device = ""; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, device), E_OK); + EXPECT_EQ(device, ""); + std::string oriDevice = ""; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 2, oriDevice), E_OK); // 2 is column index + EXPECT_EQ(oriDevice, ""); + + EXPECT_EQ(sqlite3_column_int(stmt, 3), 0x02|0x20); // 3 is column index flag == 0x02|0x20 + std::string gidStr; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 4, gidStr), E_OK); // 4 is column index + EXPECT_EQ(gid, gidStr); + resultCount++; + return E_OK; + }); + EXPECT_EQ(errCode, SQLITE_OK); + EXPECT_EQ(resultCount, 1); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +static void UpdateTriggerTest(bool primaryKeyIsRowId) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, primaryKeyIsRowId, DistributedDB::CLOUD_COOPERATION); + + /** + * @tc.steps:step2. insert data into sync_data_tmp. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + std::string sql = "insert into " + tableName + " VALUES(2, 1, 'zhangsan');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + /** + * @tc.steps:step3. update data. + * @tc.expected: step3. return ok. + */ + std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); + sql = "update " + tableName + " set name = 'lisi';"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + /** + * @tc.steps:step4. select data from log table. + * @tc.expected: step4. return ok. + */ + sql = "select * from " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log;"; + uint64_t curTime = 0; + int errCode = GetCurrentSysTimeIn100Ns(curTime); + EXPECT_EQ(errCode, E_OK); + + int resultCount = 0; + errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [curTime, &resultCount, primaryKeyIsRowId] ( + sqlite3_stmt *stmt) { + if (primaryKeyIsRowId) { + EXPECT_EQ(sqlite3_column_int64(stmt, 0), 2); // 2 is row id + } else { + EXPECT_EQ(sqlite3_column_int64(stmt, 0), 1); // 1 is row id + } + + EXPECT_EQ(sqlite3_column_int(stmt, 5), 0x02|0x20); // 5 is column index, flag == 0x02|0x20 + + std::string device = ""; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, device), E_OK); + EXPECT_EQ(device, ""); + std::string oriDevice = ""; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 2, oriDevice), E_OK); // 2 is column index + EXPECT_EQ(oriDevice, ""); + + int64_t timestamp = sqlite3_column_int64(stmt, 3); // 3 is column index + int64_t wtimestamp = sqlite3_column_int64(stmt, 4); // 4 is column index + int64_t diff = MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS * TO_100_NS; + EXPECT_TRUE(timestamp - wtimestamp > diff); + EXPECT_TRUE(static_cast(curTime - timestamp) < diff); + + resultCount++; + return E_OK; + }); + EXPECT_EQ(errCode, SQLITE_OK); + EXPECT_EQ(resultCount, 1); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: UpdateTriggerTest001 + * @tc.desc: Test update trigger in sqlite for primary key is not row id + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, UpdateTriggerTest001, TestSize.Level1) +{ + UpdateTriggerTest(false); +} + +/** + * @tc.name: UpdateTriggerTest002 + * @tc.desc: Test update trigger in sqlite for primary key is row id + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, UpdateTriggerTest002, TestSize.Level1) +{ + UpdateTriggerTest(true); +} + +/** + * @tc.name: DeleteTriggerTest001 + * @tc.desc: Test delete trigger in sqlite + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, DeleteTriggerTest001, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, true, DistributedDB::CLOUD_COOPERATION); + + /** + * @tc.steps:step2. insert data into sync_data. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + std::string sql = "insert into " + tableName + " VALUES(2, 1, 'zhangsan');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + /** + * @tc.steps:step3. delete data. + * @tc.expected: step3. return ok. + */ + std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); + sql = "delete from " + tableName + " where name = 'zhangsan';"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + /** + * @tc.steps:step4. select data from log table. + * @tc.expected: step4. return ok. + */ + sql = "select * from " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log;"; + uint64_t curTime = 0; + int errCode = GetCurrentSysTimeIn100Ns(curTime); + EXPECT_EQ(errCode, E_OK); + + int resultCount = 0; + errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [curTime, &resultCount] (sqlite3_stmt *stmt) { + EXPECT_EQ(sqlite3_column_int64(stmt, 0), -1); + EXPECT_EQ(sqlite3_column_int(stmt, 5), 3); // 5 is column index, flag == 3 + + std::string device = "de"; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, device), E_OK); + EXPECT_EQ(device, ""); + std::string oriDevice = "de"; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 2, oriDevice), E_OK); // 2 is column index + EXPECT_EQ(oriDevice, ""); + + int64_t timestamp = sqlite3_column_int64(stmt, 3); // 3 is column index + int64_t wtimestamp = sqlite3_column_int64(stmt, 4); // 4 is column index + int64_t diff = MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS * TO_100_NS; + EXPECT_TRUE(timestamp - wtimestamp > diff); + EXPECT_TRUE(static_cast(curTime - timestamp) < diff); + + resultCount++; + return E_OK; + }); + EXPECT_EQ(errCode, SQLITE_OK); + EXPECT_EQ(resultCount, 1); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: TriggerObserverTest001 + * @tc.desc: Test invalid args for RegisterClientObserver and UnRegisterClientObserver + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, TriggerObserverTest001, TestSize.Level0) +{ + /** + * @tc.steps:step1. call RegisterClientObserver and UnRegisterClientObserver with db = nullptr. + * @tc.expected: step1. return INVALID_ARGS. + */ + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(nullptr, clientObserver), INVALID_ARGS); + EXPECT_EQ(UnRegisterClientObserver(nullptr), INVALID_ARGS); + + /** + * @tc.steps:step2. call RegisterClientObserver with nullptr clientObserver. + * @tc.expected: step2. return INVALID_ARGS. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + EXPECT_EQ(RegisterClientObserver(db, nullptr), INVALID_ARGS); + + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: TriggerObserverTest002 + * @tc.desc: Test trigger client observer in sqlite + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, TriggerObserverTest002, TestSize.Level0) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false); + + /** + * @tc.steps:step2. register client observer. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + RegisterDbHook(db); + + /** + * @tc.steps:step3. insert data into sync_data, check observer. + * @tc.expected: step3. check observer ok. + */ + std::string sql = "insert into " + tableName + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + WaitAndResetNotify(); + std::atomic count = 0; // 0 is observer triggered counts + CheckTriggerObserverTest002(tableName, count); + + /** + * @tc.steps:step4. update data, check observer. + * @tc.expected: step4. check observer ok. + */ + sql = "update " + tableName + " set name = 'lisi1' where id = 2;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + WaitAndResetNotify(); + CheckTriggerObserverTest002(tableName, count); + + /** + * @tc.steps:step4. delete data, check observer. + * @tc.expected: step4. check observer ok. + */ + sql = "delete from " + tableName + " where id = 3;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + WaitAndResetNotify(); + CheckTriggerObserverTest002(tableName, count); + + /** + * @tc.steps:step5. register another observer, update data, check observer. + * @tc.expected: step5. check observer ok. + */ + triggeredCount_ = 0; + ClientObserver clientObserver2 = + std::bind(&DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc2, this, + std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver2), OK); + RegisterDbHook(db); + sql = "update " + tableName + " set name = 'lisi2' where id = 2;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + WaitAndResetNotify(); + EXPECT_EQ(triggeredCount_, 0); + EXPECT_EQ(triggeredCount2_, 1); + + /** + * @tc.steps:step6. UnRegisterClientObserver, update data, check observer. + * @tc.expected: step6. check observer ok. + */ + triggeredCount2_ = 0; + EXPECT_EQ(UnRegisterClientObserver(db), OK); + sql = "update " + tableName + " set name = 'lisi3' where id = 2;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + EXPECT_EQ(triggeredCount2_, 0); // observer2 will not be triggered + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: TriggerObserverTest003 + * @tc.desc: Test RegisterClientObserver and UnRegisterClientObserver concurrently + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, TriggerObserverTest003, TestSize.Level1) +{ + for (int i = 0; i < 1000; i++) { // 1000 is loop times + std::thread t1 ([this]() { + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind( + &DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc, this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); + }); + + std::thread t2 ([this]() { + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind( + &DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc2, this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); + }); + + t1.join(); + t2.join(); + } +} + +/** + * @tc.name: TriggerObserverTest004 + * @tc.desc: Test batch insert/update/delete data then trigger client observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, TriggerObserverTest004, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false); + + /** + * @tc.steps:step2. register client observer. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + RegisterDbHook(db); + + /** + * @tc.steps:step3. insert data into sync_data, check observer. + * @tc.expected: step3. check observer ok. + */ + std::string sql; + int dataCounts = 1000; // 1000 is count of insert options. + for (int i = 1; i <= dataCounts; i++) { + sql = "insert into " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" + std::to_string(i) + "');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + std::unique_lock lock(g_mutex); + bool isEqual = g_cv.wait_for(lock, std::chrono::seconds(1), [this, dataCounts]() { // 1 is wait time + return triggeredCount_ == dataCounts; + }); + EXPECT_EQ(isEqual, true); + WaitAndResetNotifyWithLock(lock); + ASSERT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(triggerTableData_.begin()->first, tableName); + EXPECT_EQ(triggeredCount_, dataCounts); + + /** + * @tc.steps:step4. insert or replace, check observer. + * @tc.expected: step5. check observer ok. + */ + triggeredCount_ = 0; + sql = "insert or replace into " + tableName + " VALUES(1000, 'lisi');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + isEqual = g_cv.wait_for(lock, std::chrono::seconds(1), [this]() { // 1 is wait time + return triggeredCount_ == 1; + }); + EXPECT_EQ(isEqual, true); + WaitAndResetNotifyWithLock(lock); + EXPECT_EQ(triggeredCount_, 1); // 1 is trigger times, first delete then insert + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: TriggerObserverTest005 + * @tc.desc: Test commit and rollback for one table then trigger client observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, TriggerObserverTest005, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false); + + /** + * @tc.steps:step2. register client observer. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + RegisterDbHook(db); + + /** + * @tc.steps:step3. begin transaction and commit. + * @tc.expected: step3. check observer ok. + */ + std::string sql = "begin;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + int dataCounts = 1000; // 1000 is count of insert options. + for (int i = 1; i <= dataCounts; i++) { + sql = "insert into " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" + std::to_string(i) + "');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + sql = "commit;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + WaitAndResetNotify(); + ASSERT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(triggerTableData_.begin()->first, tableName); + EXPECT_EQ(triggeredCount_, 1); + + /** + * @tc.steps:step4. begin transaction and rollback. + * @tc.expected: step3. check observer ok. + */ + triggerTableData_.clear(); + triggeredCount_ = 0; + sql = "begin;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + for (int i = dataCounts + 1; i <= 2 * dataCounts; i++) { // 2 is double dataCounts + sql = "insert into " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" + std::to_string(i) + "');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + sql = "rollback;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + EXPECT_TRUE(triggerTableData_.empty()); + EXPECT_EQ(triggeredCount_, 0); + + /** + * @tc.steps:step5. insert or replace, check observer. + * @tc.expected: step5. check observer ok. + */ + triggeredCount_ = 0; + sql = "insert or replace into " + tableName + " VALUES(1000, 'lisi');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + WaitAndResetNotify(); + EXPECT_EQ(triggeredCount_, 1); // 1 is trigger times, first delete then insert + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: TriggerObserverTest006 + * @tc.desc: Test commit and rollback for multi-table then trigger client observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, TriggerObserverTest006, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName1 = "sync_data1"; + const std::string tableName2 = "sync_data2"; + PrepareData({tableName1, tableName2}, false, DistributedDB::CLOUD_COOPERATION, false); + + /** + * @tc.steps:step2. register client observer. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + RegisterDbHook(db); + + /** + * @tc.steps:step3. begin transaction and commit. + * @tc.expected: step3. check observer ok. + */ + std::string sql = "insert into " + tableName1 + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + WaitAndResetNotify(); + ASSERT_EQ(triggerTableData_.size(), 1u); // 1 is table size + EXPECT_EQ(triggerTableData_.begin()->first, tableName1); + EXPECT_EQ(triggeredCount_, 1); // 1 is trigger count + + /** + * @tc.steps:step4. UnRegisterClientObserver and insert table2. + * @tc.expected: step3. check observer ok. + */ + triggerTableData_.clear(); + triggeredCount_ = 0; + EXPECT_EQ(UnRegisterClientObserver(db), OK); + sql = "insert into " + tableName2 + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + EXPECT_TRUE(triggerTableData_.empty()); + EXPECT_EQ(triggeredCount_, 0); + + /** + * @tc.steps:step5. RegisterClientObserver again and insert table1, check observer. + * @tc.expected: step5. check observer ok. + */ + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + RegisterDbHook(db); + sql = "insert into " + tableName1 + " VALUES(7, 'zhangjiu');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + WaitAndResetNotify(); + ASSERT_EQ(triggerTableData_.size(), 1u); // 1 is table size + EXPECT_EQ(triggerTableData_.begin()->first, tableName1); + EXPECT_EQ(triggeredCount_, 1); // 1 is trigger count + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: TriggerObserverTest007 + * @tc.desc: Test trigger client observer in tracker table + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, TriggerObserverTest007, TestSize.Level0) +{ + /** + * @tc.steps:step1. prepare data and set trackerTable + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false); + SetTracerSchema({tableName}, DistributedDB::CLOUD_COOPERATION); + + /** + * @tc.steps:step2. register client observer. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + RegisterDbHook(db); + + /** + * @tc.steps:step3. insert data into sync_data, check observer. + * @tc.expected: step3. check observer ok. + */ + std::string sql = "insert into " + tableName + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');"; + std::unique_lock lock(g_mutex); + ExecSqlAndWaitForObserver(db, sql, lock); + ChangeProperties properties; + properties.isTrackedDataChange = true; + int triggerCount = 1; + CheckTriggerTableData(1u, tableName, properties, triggerCount); + + /** + * @tc.steps:step4. update data, check observer. + * @tc.expected: step4. check observer ok. + */ + sql = "update " + tableName + " set name = 'lisi1' where id = 2;"; + ExecSqlAndWaitForObserver(db, sql, lock); + CheckTriggerTableData(1u, tableName, properties, ++triggerCount); + + /** + * @tc.steps:step5. update to the same data again, check observer. + * @tc.expected: step5. check observer ok. + */ + sql = "update " + tableName + " set name = 'lisi1' where id = 2;"; + ExecSqlAndWaitForObserver(db, sql, lock); + properties.isTrackedDataChange = false; + CheckTriggerTableData(1u, tableName, properties, ++triggerCount); + + /** + * @tc.steps:step6. update to the same data again, set name is NULL, check observer. + * @tc.expected: step6. check observer ok. + */ + sql = "update " + tableName + " set name = NULL where id = 2;"; + ExecSqlAndWaitForObserver(db, sql, lock); + properties.isTrackedDataChange = true; + CheckTriggerTableData(1u, tableName, properties, ++triggerCount); + + /** + * @tc.steps:step7. update to the same data again, set name is empty, check observer. + * @tc.expected: step7. check observer ok. + */ + sql = "update " + tableName + " set name = '' where id = 2;"; + ExecSqlAndWaitForObserver(db, sql, lock); + CheckTriggerTableData(1u, tableName, properties, ++triggerCount); + + /** + * @tc.steps:step8. delete data, check observer. + * @tc.expected: step8. check observer ok. + */ + sql = "delete from " + tableName + " where id = 2;"; + ExecSqlAndWaitForObserver(db, sql, lock); + CheckTriggerTableData(1u, tableName, properties, ++triggerCount); + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: TriggerObserverTest008 + * @tc.desc: Test trigger client observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, TriggerObserverTest008, TestSize.Level0) +{ + /** + * @tc.steps:step1. prepare data + * @tc.expected: step1. return ok. + */ + const std::string tableName1 = "table1"; + PrepareData({tableName1}, false, DistributedDB::CLOUD_COOPERATION, false, true); + const std::string tableName2 = "table2"; + PrepareData({tableName2}, false, DistributedDB::CLOUD_COOPERATION, false, true); + + /** + * @tc.steps:step2. register client observer. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtClientTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + + /** + * @tc.steps:step3. insert data into sync_data, check observer. + * @tc.expected: step3. check observer ok. + */ + std::string sql = "insert into " + tableName1 + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + EXPECT_EQ(triggerTableData_.size(), 0u); + + /** + * @tc.steps:step4. re-register client observer and register hook + * @tc.expected: step4. return ok. + */ + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + RegisterDbHook(db); + + /** + * @tc.steps:step5. insert data into sync_data, check observer. + * @tc.expected: step5. check observer ok. + */ + sql = "insert into " + tableName2 + " VALUES(4, 'aaa');"; + std::unique_lock lock(g_mutex); + ExecSqlAndWaitForObserver(db, sql, lock); + EXPECT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +void InitLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint64_t num) +{ + for (size_t i = 0; i < num; ++i) { + std::string sql = "insert or replace into " + tableName + " VALUES('" + std::to_string(i) + "', 'zhangsan');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + std::string sql = "update " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log" + + " SET flag = flag | 0x08"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); +} + +void CheckLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint64_t expectNum) +{ + std::string sql = "select count(*) from " + std::string(DBConstant::RELATIONAL_PREFIX) + tableName + "_log" + " where flag&0x08=0x08 and flag&0x01=0"; + sqlite3_stmt *stmt = nullptr; + EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + uint64_t count = static_cast(sqlite3_column_int64(stmt, 0)); + EXPECT_EQ(count, expectNum); + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + stmt = nullptr; + sql = "select count(*) from " + tableName; + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + uint64_t count = static_cast(sqlite3_column_int64(stmt, 0)); + EXPECT_EQ(count, expectNum); + } + SQLiteUtils::ResetStatement(stmt, true, errCode); +} + +/** + * @tc.name: DropDeleteData001 + * @tc.desc: Test trigger client observer in tracker table + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, DropDeleteData001, TestSize.Level0) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false); + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + uint64_t num = 10; + InitLogicDeleteData(db, tableName, num); + + /** + * @tc.steps:step2. db handle is nullptr + * @tc.expected: step2. return INVALID_ARGS. + */ + EXPECT_EQ(DropLogicDeletedData(nullptr, tableName, 0u), INVALID_ARGS); + + /** + * @tc.steps:step3. tableName is empty + * @tc.expected: step3. return INVALID_ARGS. + */ + EXPECT_EQ(DropLogicDeletedData(db, "", 0u), INVALID_ARGS); + + /** + * @tc.steps:step4. tableName is no exist + * @tc.expected: step4. return INVALID_ARGS. + */ + EXPECT_EQ(DropLogicDeletedData(db, tableName + "_", 0u), DB_ERROR); + + /** + * @tc.steps:step5. cursor is 0 + * @tc.expected: step5. return OK. + */ + EXPECT_EQ(DropLogicDeletedData(db, tableName, 0u), OK); + CheckLogicDeleteData(db, tableName, 0u); + + /** + * @tc.steps:step6. init data again, and cursor is 15 + * @tc.expected: step6. return OK. + */ + uint64_t cursor = 15; + InitLogicDeleteData(db, tableName, num); + EXPECT_EQ(DropLogicDeletedData(db, tableName, cursor), OK); + CheckLogicDeleteData(db, tableName, cursor - num); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +void InitDataStatus(const std::string &tableName, int count, sqlite3 *db) +{ + int type = 4; // the num of different status + for (int i = 1; i <= type * count; i++) { + std::string sql = "INSERT INTO " + tableName + " VALUES(" + std::to_string(i) + ", 'zhangsan" + + std::to_string(i) + "');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + std::string countStr = std::to_string(count); + std::string sql = "UPDATE " + DBCommon::GetLogTableName(tableName) + " SET status=(CASE WHEN data_key<=" + + countStr + " THEN 0 WHEN data_key>" + countStr + " AND data_key<=2*" + countStr + " THEN 1 WHEN data_key>2*" + + countStr + " AND data_key<=3*" + countStr + " THEN 2 ELSE 3 END)"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); +} + +void CheckDataStatus(const std::string &tableName, const std::string &condition, sqlite3 *db, int64_t expect) +{ + std::string sql = "SELECT count(1) FROM " + DBCommon::GetLogTableName(tableName) + " WHERE " + condition; + sqlite3_stmt *stmt = nullptr; + EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + int64_t count = static_cast(sqlite3_column_int64(stmt, 0)); + EXPECT_EQ(count, expect); + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); +} + +/** + * @tc.name: LockDataTest001 + * @tc.desc: Test status after lock + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, LockDataTest001, TestSize.Level1) +{ + /** + * @tc.steps:step1. init data and lock, hashKey has no matching data + * @tc.expected: step1. return NOT_FOUND. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false); + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + int count = 10; + InitDataStatus(tableName, count, db); + std::vector> hashKey; + hashKey.push_back({'1'}); + EXPECT_EQ(Lock(tableName, hashKey, db), NOT_FOUND); + + /** + * @tc.steps:step2. init data and lock, hashKey has matching data + * @tc.expected: step2. return OK. + */ + hashKey.clear(); + CloudDBSyncUtilsTest::GetHashKey(tableName, " 1=1 ", db, hashKey); + EXPECT_EQ(Lock(tableName, hashKey, db), OK); + + /** + * @tc.steps:step3. check status + * @tc.expected: step3. return OK. + */ + CheckDataStatus(tableName, " status = 2 and data_key <= 10 ", db, count); + CheckDataStatus(tableName, " status = 3 and data_key <= 20 ", db, count); + CheckDataStatus(tableName, " status = 2 ", db, count + count); + CheckDataStatus(tableName, " status = 3 ", db, count + count); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} + +/** + * @tc.name: LockDataTest002 + * @tc.desc: Test status after unLock + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, LockDataTest002, TestSize.Level1) +{ + /** + * @tc.steps:step1. init data and unLock, there is data to be compensated for + * @tc.expected: step1. return WAIT_COMPENSATED_SYNC. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false); + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + int count = 10; + InitDataStatus(tableName, count, db); + std::vector> hashKey; + CloudDBSyncUtilsTest::GetHashKey(tableName, " 1=1 ", db, hashKey); + EXPECT_EQ(UnLock(tableName, hashKey, db), WAIT_COMPENSATED_SYNC); + + /** + * @tc.steps:step2. check status + * @tc.expected: step2. return OK. + */ + CheckDataStatus(tableName, " status = 0 and data_key <= 10 ", db, count); + CheckDataStatus(tableName, " status = 1 and data_key <= 20 ", db, count); + CheckDataStatus(tableName, " status = 0 ", db, count + count); + CheckDataStatus(tableName, " status = 1 ", db, count + count); + + /** + * @tc.steps:step3. unLock again, there is data to be compensated for + * @tc.expected: step3. return WAIT_COMPENSATED_SYNC. + */ + EXPECT_EQ(UnLock(tableName, hashKey, db), WAIT_COMPENSATED_SYNC); + + /** + * @tc.steps:step4. unLock again, there is no data to be compensated for + * @tc.expected: step4. return OK. + */ + std::string sql = "update " + DBCommon::GetLogTableName(tableName) + " SET status=0"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + EXPECT_EQ(UnLock(tableName, hashKey, db), OK); + + /** + * @tc.steps:step5. unLock again, hashKey has matching data + * @tc.expected: step5. return NOT_FOUND. + */ + hashKey.clear(); + hashKey.push_back({'1'}); + EXPECT_EQ(UnLock(tableName, hashKey, db), NOT_FOUND); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} + +DistributedDB::StoreObserver::StoreChangedInfo g_changedData; + +class MockStoreObserver : public StoreObserver { +public: + virtual ~MockStoreObserver() {}; + void OnChange(StoreChangedInfo &&data) override + { + g_changedData = data; + std::unique_lock lock(g_mutex); + g_cv.notify_one(); + g_alreadyNotify = true; + }; +}; + +void CreateTableForStoreObserver(sqlite3 *db, const std::string tableName) +{ + std::string sql = "create table " + tableName + "(id INTEGER primary key, name TEXT);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "create table no_" + tableName + "(id INTEGER, name TEXT);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "create table mult_" + tableName + "(id INTEGER, name TEXT, age int, "; + sql += "PRIMARY KEY (id, name));"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); +} + +void PrepareDataForStoreObserver(sqlite3 *db, const std::string &tableName, int begin, int dataCounts) +{ + std::string sql = "begin;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + for (int i = begin; i < begin + dataCounts; i++) { + sql = "insert into " + tableName + " VALUES(" + std::to_string(i + 1) + ", 'zhangsan" + + std::to_string(i + 1) + "');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "insert into no_" + tableName +" VALUES(" + std::to_string(i + 1) + ", 'zhangsan" + + std::to_string(i + 1) + "');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "insert into mult_" + tableName + " VALUES(" + std::to_string(i + 1) + ", 'zhangsan"; + sql += std::to_string(i + 1) + "', 18);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + for (int i = begin; i < dataCounts / 2 + begin; i++) { // 2 is half + sql = "update " + tableName + " set name = 'lisi' where id = " + std::to_string(i + 1) + ";"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "update no_" + tableName + " set name = 'lisi' where _rowid_ = " + std::to_string(i + 1) + ";"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "update mult_" + tableName + " set age = 20 where id = " + std::to_string(i + 1); + sql += " and name = 'zhangsan" + std::to_string(i + 1) + "';"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + for (int i = dataCounts / 2 + begin; i < dataCounts + begin; i++) { // 2 is half + sql = "delete from " + tableName + " where id = " + std::to_string(i + 1) + ";"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "delete from no_" + tableName + " where _rowid_ = " + std::to_string(i + 1) + ";"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "delete from mult_" + tableName + " where id = " + std::to_string(i + 1); + sql += " and name = 'zhangsan" + std::to_string(i + 1) + "';"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + sql = "commit;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); +} + +void CheckChangedData(int num, int times = 0, int offset = 0) +{ + if (num == 1) { + for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_INSERT].size(); i++) { + EXPECT_EQ(std::get(g_changedData[num].primaryData[ChangeType::OP_INSERT][i - 1][0]), + static_cast(i + offset - times * 5)); // 5 is rowid times + } + for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_DELETE].size(); i++) { + EXPECT_EQ(std::get(g_changedData[num].primaryData[ChangeType::OP_DELETE][i - 1][0]), + static_cast(i + offset + 5)); // 5 is offset + } + return; + } + for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_INSERT].size(); i++) { + EXPECT_EQ(std::get(g_changedData[num].primaryData[ChangeType::OP_INSERT][i - 1][0]), + static_cast(i + offset)); + } + for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_UPDATE].size(); i++) { + EXPECT_EQ(std::get(g_changedData[num].primaryData[ChangeType::OP_UPDATE][i - 1][0]), + static_cast(i + offset)); + } + for (size_t i = 1; i <= g_changedData[num].primaryData[ChangeType::OP_DELETE].size(); i++) { + EXPECT_EQ(std::get(g_changedData[num].primaryData[ChangeType::OP_DELETE][i - 1][0]), + static_cast(i + offset + 5)); // 5 is offset + } +} + +/** + * @tc.name: RegisterStoreObserverTest001 + * @tc.desc: Test commit for three table then trigger store observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, RegisterStoreObserverTest001, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare db and create table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + std::string tableName = "primary_test"; + CreateTableForStoreObserver(db, tableName); + + /** + * @tc.steps:step2. register store observer and check onchange. + * @tc.expected: step2. return ok. + */ + auto storeObserver = std::make_shared(); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK); + RegisterDbHook(db); + EXPECT_TRUE(g_changedData.empty()); + int dataCounts = 10; // 10 is count of insert options. + int begin = 0; + PrepareDataForStoreObserver(db, tableName, begin, dataCounts); + { + std::unique_lock lock(g_mutex); + g_cv.wait(lock, []() { + return g_alreadyNotify; + }); + g_alreadyNotify = false; + } + EXPECT_EQ(g_changedData[0].tableName, "primary_test"); + CheckChangedData(0); + EXPECT_EQ(g_changedData[1].tableName, "no_primary_test"); + CheckChangedData(1); + EXPECT_EQ(g_changedData[2].tableName, "mult_primary_test"); // 2 is mult primary table + CheckChangedData(2); // 2 is mult primary table + g_changedData.clear(); + + /** + * @tc.steps:step3. unregister store observer and update data check onchange. + * @tc.expected: step3. return ok. + */ + EXPECT_EQ(UnregisterStoreObserver(db), OK); + begin = 10; // 10 is begin id + PrepareDataForStoreObserver(db, tableName, begin, dataCounts); + EXPECT_TRUE(g_changedData.empty()); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: RegisterStoreObserverTest002 + * @tc.desc: Test commit for three table then trigger client observer when register then create table + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, RegisterStoreObserverTest002, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare db and register store observer then create table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + auto storeObserver = std::make_shared(); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK); + RegisterDbHook(db); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + std::string tableName = "primary_test"; + CreateTableForStoreObserver(db, tableName); + + /** + * @tc.steps:step2. update data and check onchange. + * @tc.expected: step2. return ok. + */ + EXPECT_TRUE(g_changedData.empty()); + int dataCounts = 10; // 10 is count of insert options. + int begin = 0; + PrepareDataForStoreObserver(db, tableName, begin, dataCounts); + WaitAndResetNotify(); + EXPECT_EQ(g_changedData[0].tableName, "primary_test"); + CheckChangedData(0); + EXPECT_EQ(g_changedData[1].tableName, "no_primary_test"); + CheckChangedData(1); + EXPECT_EQ(g_changedData[2].tableName, "mult_primary_test"); // 2 is mult primary table + CheckChangedData(2); // 2 is mult primary table + g_changedData.clear(); + + /** + * @tc.steps:step3. unregister store observer and update data check onchange. + * @tc.expected: step3. return ok. + */ + EXPECT_EQ(UnregisterStoreObserver(db), OK); + begin = 10; // 11 is begin id + PrepareDataForStoreObserver(db, tableName, begin, dataCounts); + EXPECT_TRUE(g_changedData.empty()); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: RegisterStoreObserverTest003 + * @tc.desc: Test commit for three table then trigger client observer when register two observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, RegisterStoreObserverTest003, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare db and register store observer then create table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + auto storeObserver1 = std::make_shared(); + auto storeObserver2 = std::make_shared(); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver1), OK); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver2), OK); + RegisterDbHook(db); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + std::string tableName = "primary_test"; + CreateTableForStoreObserver(db, tableName); + + /** + * @tc.steps:step2. update data and check onchange. + * @tc.expected: step2. return ok. + */ + EXPECT_TRUE(g_changedData.empty()); + int dataCounts = 10; // 10 is count of insert options. + int begin = 0; + PrepareDataForStoreObserver(db, tableName, begin, dataCounts); + WaitAndResetNotify(); + EXPECT_EQ(g_changedData[0].tableName, "primary_test"); + CheckChangedData(0); + EXPECT_EQ(g_changedData[1].tableName, "no_primary_test"); + CheckChangedData(1); + EXPECT_EQ(g_changedData[2].tableName, "mult_primary_test"); // 2 is mult primary table + CheckChangedData(2); // 2 is mult primary table + g_changedData.clear(); + + /** + * @tc.steps:step3. unregister store observer and update data check onchange. + * @tc.expected: step3. return ok. + */ + EXPECT_EQ(UnregisterStoreObserver(db, storeObserver1), OK); + begin = 10; // 11 is begin id + PrepareDataForStoreObserver(db, tableName, begin, dataCounts); + EXPECT_EQ(g_changedData[0].tableName, "primary_test"); + CheckChangedData(0, 1, dataCounts); + EXPECT_EQ(g_changedData[1].tableName, "no_primary_test"); + CheckChangedData(1, 1, dataCounts); + EXPECT_EQ(g_changedData[2].tableName, "mult_primary_test"); // 2 is mult primary table + CheckChangedData(2, 1, dataCounts); // 2 is mult primary table + g_changedData.clear(); + + EXPECT_EQ(UnregisterStoreObserver(db, storeObserver2), OK); + begin = 20; // 21 is begin id + PrepareDataForStoreObserver(db, tableName, begin, dataCounts); + EXPECT_TRUE(g_changedData.empty()); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: RegisterStoreObserverTest004 + * @tc.desc: Test register two same observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtClientTest, RegisterStoreObserverTest004, TestSize.Level1) +{ + /** + * @tc.steps:step1. prepare db and register store observer then create table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + auto storeObserver = std::make_shared(); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp index 363c76a2..e54e58b3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp @@ -455,7 +455,7 @@ void UpdateTriggerTest(bool primaryKeyIsRowId) * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, UpdateTriggerTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, UpdateTriggerTest001, TestSize.Level1) { UpdateTriggerTest(false); } @@ -467,7 +467,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, UpdateTriggerTest001, Te * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, UpdateTriggerTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, UpdateTriggerTest002, TestSize.Level1) { UpdateTriggerTest(true); } @@ -479,7 +479,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, UpdateTriggerTest002, Te * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, DeleteTriggerTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, DeleteTriggerTest001, TestSize.Level1) { /** * @tc.steps:step1. prepare data. @@ -566,13 +566,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest001, EXPECT_NE(db, nullptr); EXPECT_EQ(RegisterClientObserver(db, nullptr), INVALID_ARGS); - /** - * @tc.steps:step3. call RegisterClientObserver and UnRegisterClientObserver with closed db handle. - * @tc.expected: step3. return INVALID_ARGS. - */ EXPECT_EQ(sqlite3_close_v2(db), E_OK); - EXPECT_EQ(RegisterClientObserver(db, clientObserver), INVALID_ARGS); - EXPECT_EQ(UnRegisterClientObserver(db), INVALID_ARGS); } /** @@ -983,6 +977,62 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest007, EXPECT_EQ(sqlite3_close_v2(db), E_OK); } +/** + * @tc.name: TriggerObserverTest008 + * @tc.desc: Test trigger client observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest008, TestSize.Level0) +{ + /** + * @tc.steps:step1. prepare data + * @tc.expected: step1. return ok. + */ + const std::string tableName1 = "table1"; + PrepareData({tableName1}, false, DistributedDB::CLOUD_COOPERATION, false, true); + const std::string tableName2 = "table2"; + PrepareData({tableName2}, false, DistributedDB::CLOUD_COOPERATION, false, true); + + /** + * @tc.steps:step2. register client observer. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + + /** + * @tc.steps:step3. insert data into sync_data, check observer. + * @tc.expected: step3. check observer ok. + */ + std::string sql = "insert into " + tableName1 + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + EXPECT_EQ(triggerTableData_.size(), 0u); + + /** + * @tc.steps:step4. re-register client observer and register hook + * @tc.expected: step4. return ok. + */ + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + RegisterDbHook(db); + + /** + * @tc.steps:step5. insert data into sync_data, check observer. + * @tc.expected: step5. check observer ok. + */ + sql = "insert into " + tableName2 + " VALUES(4, 'aaa');"; + std::unique_lock lock(g_mutex); + ExecSqlAndWaitForObserver(db, sql, lock); + EXPECT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + void InitLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint64_t num) { for (size_t i = 0; i < num; ++i) { @@ -1078,7 +1128,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, DropDeleteData001, TestS * @tc.require: * @tc.author: */ -HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest001, TestSize.Level1) { std::map ans; #ifdef USE_FFRT @@ -1143,7 +1193,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest001, TestSize.Le * @tc.require: * @tc.author: */ -HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest002, TestSize.Level1) { std::map ans; #ifdef USE_FFRT @@ -1216,7 +1266,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest002, TestSize.Le * @tc.require: * @tc.author: */ -HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest003, TestSize.Level1) { size_t count = 0; size_t num = 3000; @@ -1276,6 +1326,10 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, AbnormalDelegateTest001, * @tc.expected: step2. return ok. */ auto delegateImpl = static_cast(delegate); + ClearMetaDataOption option; + EXPECT_EQ(delegateImpl->ClearMetaData(option), OK); + option.tableNameList.insert("asdad"); + EXPECT_EQ(delegateImpl->ClearMetaData(option), NOT_SUPPORT); status = delegateImpl->Close(); EXPECT_EQ(status, OK); @@ -1345,7 +1399,7 @@ void CheckDataStatus(const std::string &tableName, const std::string &condition, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, LockDataTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, LockDataTest001, TestSize.Level1) { /** * @tc.steps:step1. init data and lock, hashKey has no matching data @@ -1387,7 +1441,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, LockDataTest001, TestSiz * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, LockDataTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, LockDataTest002, TestSize.Level1) { /** * @tc.steps:step1. init data and unLock, there is data to be compensated for @@ -1724,6 +1778,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, RegisterStoreObserverTes begin = 20; // 21 is begin id PrepareDataForStoreObserver(db, tableName, begin, dataCounts); EXPECT_TRUE(g_changedData.empty()); + UnregisterDbHook(db); EXPECT_EQ(sqlite3_close_v2(db), E_OK); } @@ -1852,4 +1907,168 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, AbnormalDelegateImplTest EXPECT_EQ(g_mgr.CloseStore(delegate), OK); delegate = nullptr; } + +/** + * @tc.name: FuncExceptionTest001 + * @tc.desc: Test the interception expection of the interface + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FuncExceptionTest001, TestSize.Level1) +{ + std::shared_ptr iStoreObserver = nullptr; + EXPECT_EQ(RegisterStoreObserver(nullptr, iStoreObserver), INVALID_ARGS); + EXPECT_EQ(UnregisterStoreObserver(nullptr, iStoreObserver), INVALID_ARGS); + iStoreObserver = std::make_shared(); + EXPECT_EQ(RegisterStoreObserver(nullptr, iStoreObserver), INVALID_ARGS); + EXPECT_EQ(UnregisterStoreObserver(nullptr, iStoreObserver), INVALID_ARGS); + + EXPECT_EQ(RelationalStoreManager::CalcPrimaryKeyHash({}, {}).size(), 0u); + std::map pkMap1 = {{"fielddInt", 0L}}; + std::map ctMap1 = {{"fielddInt", CollateType::COLLATE_BUTT}}; + std::vector result = RelationalStoreManager::CalcPrimaryKeyHash(pkMap1, ctMap1); + EXPECT_TRUE(result.empty()); + + std::map pkMap2 = {{"FIELDINT", 0L}, {"FIELDSTR", std::string("FIELDSTR")}}; + std::map ctMap2; + ctMap2.insert_or_assign("fieldint", CollateType::COLLATE_BUTT); + ctMap2.insert_or_assign("fieldstr", CollateType::COLLATE_BUTT); + result = RelationalStoreManager::CalcPrimaryKeyHash(pkMap2, ctMap2); + EXPECT_TRUE(result.empty()); + + ctMap2.insert_or_assign("fieldint", CollateType::COLLATE_NOCASE); + ctMap2.insert_or_assign("fieldstr", CollateType::COLLATE_NOCASE); + result = RelationalStoreManager::CalcPrimaryKeyHash(pkMap2, ctMap2); + EXPECT_FALSE(result.empty()); + + std::map entries2; + pkMap2.insert_or_assign("FIELDINT", entries2); + result = RelationalStoreManager::CalcPrimaryKeyHash(pkMap2, ctMap2); + EXPECT_TRUE(result.empty()); +} + +/** + * @tc.name: CleanTest001 + * @tc.desc: Test calling the Clean interface twice + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, CleanTest001, TestSize.Level0) +{ + Logger *loggerInstance = Logger::GetInstance(); + ASSERT_NE(loggerInstance, nullptr); + Clean(true); + Clean(false); + loggerInstance = nullptr; + Logger *newLoggerInstance = Logger::GetInstance(); + ASSERT_NE(newLoggerInstance, nullptr); +} + +/** + * @tc.name: CreateTempTriggerTest001 + * @tc.desc: Test create data change temp trigger. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, CreateTempTriggerTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. create db and fts table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + std::string tableName = "table1"; + std::string sql = "CREATE VIRTUAL TABLE IF NOT EXISTS " + tableName + " USING fts4(content);"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + /** + * @tc.steps: step2. create temp trigger on table. + * @tc.expected: step2. return ok. + */ + EXPECT_EQ(CreateDataChangeTempTrigger(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: CreateTempTriggerTest002 + * @tc.desc: Test create data change temp trigger + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, CreateTempTriggerTest002, TestSize.Level0) +{ + /** + * @tc.steps: step1. create db and fts table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + std::string tableName = "table1"; + std::string sql = "create virtual table if not exists " + tableName + " using fts4(content);"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + /** + * @tc.steps: step2. create temp trigger on table. + * @tc.expected: step2. return ok. + */ + auto storeObserver = std::make_shared(); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK); + RegisterDbHook(db); + g_changedData.clear(); + /** + * @tc.steps: step3. insert data and check changed data. + * @tc.expected: step3. return ok. + */ + sql = "insert into " + tableName + "_content values(1, '123456');"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + ASSERT_EQ(g_changedData.size(), 1u); + EXPECT_EQ(g_changedData.front().tableName, tableName + "_content"); + ASSERT_EQ(g_changedData.front().primaryData[OP_INSERT].size(), 1u); + EXPECT_EQ(UnregisterStoreObserver(db, storeObserver), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: CreateTempTriggerTest003 + * @tc.desc: Test monitoring of virtual table data + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, CreateTempTriggerTest003, TestSize.Level0) +{ + /** + * @tc.steps: step1. create db and fts table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + std::string tableName = "table1"; + std::string sql = "create virtual table if not exists " + tableName + " using fts4(content);"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + /** + * @tc.steps: step2. create temp trigger on table. + * @tc.expected: step2. return ok. + */ + auto storeObserver = std::make_shared(); + EXPECT_EQ(RegisterStoreObserver(db, storeObserver), OK); + RegisterDbHook(db); + g_changedData.clear(); + /** + * @tc.steps: step3. insert data and check changed data. + * @tc.expected: step3. return ok. + */ + sql = "insert into " + tableName + " values(12345);"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + ASSERT_FALSE(g_changedData.empty()); + EXPECT_EQ(g_changedData.front().tableName, tableName + "_content"); + ASSERT_EQ(g_changedData.front().primaryData[OP_INSERT].size(), 1u); + EXPECT_EQ(UnregisterStoreObserver(db, storeObserver), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp index 61168fdf..a033481a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp @@ -634,7 +634,7 @@ namespace { * @tc.require: * @tc.author: huangboxin */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest001, TestSize.Level1) { int64_t paddingSize = 10; int localCount = 10; @@ -667,7 +667,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: huangboxin */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest002, TestSize.Level1) { int64_t paddingSize = 10; int localCount = 10; @@ -696,7 +696,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: huangboxin */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest003, TestSize.Level1) { /** * @tc.steps: step1. make data: 10 records on local and 20 records on cloud @@ -776,7 +776,7 @@ static CloudSyncOption GetSyncOption() * @tc.require: * @tc.author: huangboxin */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, GetCloudSyncTaskCountTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, GetCloudSyncTaskCountTest001, TestSize.Level1) { InitGetCloudSyncTaskCountTest001(db); Query query = Query::Select().FromTable(g_tables); @@ -849,7 +849,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, GetCloudSyn * @tc.require: * @tc.author: huangboxin */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest004, TestSize.Level1) { DataBaseSchema dataBaseSchema; TableSchema tableSchema1 = { @@ -872,7 +872,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest005, TestSize.Level1) { /** * @tc.steps: step1. cloud and device data is same @@ -909,7 +909,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest006, TestSize.Level1) { /** * @tc.steps: step1. make data: 10 records on local @@ -945,7 +945,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest007, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest007, TestSize.Level1) { /** * @tc.steps: step1. make data: 10 records on local @@ -996,7 +996,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest008, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest008, TestSize.Level1) { /** * @tc.steps: step1. make data: 10 records on local @@ -1051,7 +1051,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest009, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest009, TestSize.Level1) { /** * @tc.steps: step1. make data: 10 records on local @@ -1083,7 +1083,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest010, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest010, TestSize.Level1) { /** * @tc.steps: step1. make data: 10 records on local @@ -1118,7 +1118,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest011, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest011, TestSize.Level1) { /** * @tc.steps: step1. make data: 10 records on local @@ -1158,7 +1158,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest012, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest012, TestSize.Level1) { /** * @tc.steps: step1. make data: 20 records on local @@ -1204,7 +1204,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest013, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest013, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1258,7 +1258,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest014, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest014, TestSize.Level1) { /** * @tc.steps: step1. make data: 20 records on local @@ -1296,7 +1296,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest015, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest015, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1333,7 +1333,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest016, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest016, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1380,7 +1380,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest017, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest017, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1421,7 +1421,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest018, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest018, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1464,7 +1464,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest019, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest019, TestSize.Level1) { /** * @tc.steps: step1. make data: 20 records on local @@ -1496,7 +1496,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest020, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest020, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1544,7 +1544,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest021, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest021, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1598,7 +1598,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest022, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest022, TestSize.Level1) { /** * @tc.steps: step1. make data: 20 records on local @@ -1638,7 +1638,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest023, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest023, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1714,7 +1714,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest024, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest024, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1767,7 +1767,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: suyuchen */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest025, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest025, TestSize.Level1) { /** * @tc.steps: step1. Set logicDelete @@ -1819,7 +1819,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest026, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest026, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1860,7 +1860,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest027, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest027, TestSize.Level1) { /** * @tc.steps: step1. make data: 20 records on cloud @@ -1895,7 +1895,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest028, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest028, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1954,7 +1954,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest029, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest029, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -2012,7 +2012,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.require: * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest030, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest030, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_set_cloud_schema_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_set_cloud_schema_test.cpp index 1853d157..4fc9e2cb 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_set_cloud_schema_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_set_cloud_schema_test.cpp @@ -921,7 +921,7 @@ namespace { * @tc.require: * @tc.author: chenchaohao */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest010, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest010, TestSize.Level1) { /** * @tc.steps:step1. use SetCloudDbSchema @@ -1082,7 +1082,7 @@ namespace { * @tc.require: * @tc.author: chenchaohao */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest013, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest013, TestSize.Level1) { /** * @tc.steps:step1. use SetCloudDbSchema @@ -1186,7 +1186,7 @@ namespace { * @tc.require: * @tc.author: chenchaohao */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync001, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync001, TestSize.Level1) { /** * @tc.steps:step1. use set shared table without primary key @@ -1218,7 +1218,7 @@ namespace { * @tc.require: * @tc.author: chenchaohao */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync002, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync002, TestSize.Level1) { /** * @tc.steps:step1. use set shared table @@ -1260,7 +1260,7 @@ namespace { * @tc.require: * @tc.author: bty */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync003, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync003, TestSize.Level1) { /** * @tc.steps:step1. insert local shared table records and sync @@ -1312,7 +1312,7 @@ namespace { * @tc.require: * @tc.author: chenchaohao */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync004, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync004, TestSize.Level1) { /** * @tc.steps:step1. use set shared table @@ -1354,7 +1354,7 @@ namespace { * @tc.require: * @tc.author: chenchaohao */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync006, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync006, TestSize.Level1) { /** * @tc.steps:step1. set shared table and sync @@ -1533,7 +1533,7 @@ namespace { * @tc.require: * @tc.author: bty */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync007, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync007, TestSize.Level1) { /** * @tc.steps:step1. init cloud share data contains sharing_resource @@ -1572,7 +1572,7 @@ namespace { * @tc.require: * @tc.author: bty */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync008, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync008, TestSize.Level1) { /** * @tc.steps:step1. init cloud data and sync @@ -1634,7 +1634,7 @@ namespace { * @tc.require: * @tc.author: bty */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync009, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync009, TestSize.Level1) { /** * @tc.steps:step1. init cloud data and sync @@ -1697,7 +1697,7 @@ namespace { * @tc.require: * @tc.author: bty */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync010, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync010, TestSize.Level1) { /** * @tc.steps:step1. init cloud share data and sync @@ -1754,7 +1754,7 @@ namespace { * @tc.require: * @tc.author: bty */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync011, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync011, TestSize.Level1) { /** * @tc.steps:step1. init cloud data and sync @@ -1811,7 +1811,7 @@ namespace { * @tc.require: * @tc.author: bty */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync012, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync012, TestSize.Level1) { /** * @tc.steps:step1. init local share data and sync @@ -1851,7 +1851,7 @@ namespace { * @tc.require: * @tc.author: bty */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync013, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync013, TestSize.Level1) { /** * @tc.steps:step1. init cloud data and sync @@ -1899,7 +1899,7 @@ namespace { * @tc.require: * @tc.author: wangxiangdong */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync014, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync014, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -1951,7 +1951,7 @@ namespace { * @tc.require: * @tc.author: wangxiangdong */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync015, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync015, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -2027,7 +2027,7 @@ namespace { * @tc.require: * @tc.author: wangxiangdong */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync016, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync016, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -2092,7 +2092,7 @@ namespace { * @tc.require: * @tc.author: luoguo */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync017, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync017, TestSize.Level1) { /** * @tc.steps: step1. Set data is logicDelete @@ -2174,7 +2174,7 @@ namespace { * @tc.require: * @tc.author: wangxiangdong */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync019, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync019, TestSize.Level1) { /** * @tc.steps:step1. init cloud data and sync @@ -2209,7 +2209,7 @@ namespace { * @tc.require: * @tc.author: liaoyonghuang */ - HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetTrackerTable001, TestSize.Level0) + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetTrackerTable001, TestSize.Level1) { /** * @tc.steps:step1. init cloud data diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_auto_launch_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_auto_launch_test.cpp index cacbdb4a..c6ac19b0 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_auto_launch_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_auto_launch_test.cpp @@ -192,7 +192,7 @@ void DistributedDBInterfacesAutoLaunchTest::TearDown(void) * @tc.name: EnableKvStoreAutoLaunch001 * @tc.desc: Enable the kvstore with the diff parameters. * @tc.type: FUNC - * @tc.require: AR000DR9KU + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch001, TestSize.Level1) @@ -250,7 +250,7 @@ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch001, Test * @tc.name: EnableKvStoreAutoLaunch002 * @tc.desc: Enable the kv store auto launch for the change of createIfNecessary. * @tc.type: FUNC - * @tc.require: AR000DR9KU + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch002, TestSize.Level1) @@ -405,7 +405,7 @@ void TriggerAutoLaunch(const std::string &storeId, bool isWriteCovered) * @tc.name: EnableKvStoreAutoLaunch003 * @tc.desc: test the data change and the notifier of the auto open for no data changed. * @tc.type: FUNC - * @tc.require: AR000DR9KU + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch003, TestSize.Level2) @@ -425,7 +425,7 @@ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch003, Test * @tc.name: EnableKvStoreAutoLaunch004 * @tc.desc: test the data change and the notifier of the auto open for data changed. * @tc.type: FUNC - * @tc.require: AR000DR9KU + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch004, TestSize.Level2) @@ -445,7 +445,7 @@ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch004, Test * @tc.name: EnableKvStoreAutoLaunch005 * @tc.desc: Test enable the same database twice. * @tc.type: FUNC - * @tc.require: AR000DR9KU + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch005, TestSize.Level1) @@ -476,7 +476,7 @@ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch005, Test * @tc.name: EnableKvStoreAutoLaunch005 * @tc.desc: test the over limits for the enable list. * @tc.type: FUNC - * @tc.require: AR000DR9KU + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, EnableKvStoreAutoLaunch006, TestSize.Level2) @@ -549,7 +549,7 @@ void SetAutoLaunchLifeCycleTime(const std::string &storeId, uint32_t time) * @tc.name: EnableKvStoreAutoLaunch007 * @tc.desc: test the over limits for the enable list. * @tc.type: FUNC - * @tc.require: AR000DR9KU + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, DisableKvStoreAutoLaunch001, TestSize.Level3) @@ -590,7 +590,7 @@ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, DisableKvStoreAutoLaunch001, Tes * @tc.name: AutoLaunchLifeCycle001 * @tc.desc: test the auto closed for the database auto launched by the msg. * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, AutoLaunchLifeCycle001, TestSize.Level3) @@ -693,7 +693,7 @@ void DelayAutoLaunchCycle(const std::string &storeId, bool isWrite) * @tc.name: AutoLaunchLifeCycle002 * @tc.desc: test the over limits for the enable list. * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, AutoLaunchLifeCycle002, TestSize.Level3) @@ -713,7 +713,7 @@ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, AutoLaunchLifeCycle002, TestSize * @tc.name: AutoLaunchLifeCycle003 * @tc.desc: test the life cycle of the auto launched database in the sync reading scene. * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesAutoLaunchTest, AutoLaunchLifeCycle003, TestSize.Level3) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_syncdb_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_syncdb_test.cpp index d15bab16..78ed6933 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_syncdb_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_syncdb_test.cpp @@ -145,7 +145,7 @@ void DistributedDBInterfacesDataOperationSyncDBTest::TearDown(void) * @tc.name: Put001 * @tc.desc: Put a data(non-empty key, non-empty value) into an exist distributed db * @tc.type: FUNC - * @tc.require: AR000CQDTM AR000CQS3R + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Put001, TestSize.Level1) @@ -172,7 +172,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Put001, TestSize.Level1 * @tc.name: Put002 * @tc.desc: Put a data(empty key) into an exist distributed db * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Put002, TestSize.Level1) @@ -191,7 +191,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Put002, TestSize.Level1 * @tc.name: Put003 * @tc.desc: Put a data(non-empty key, empty value) into an exist distributed db * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Put003, TestSize.Level1) @@ -211,7 +211,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Put003, TestSize.Level1 * @tc.name: Put004 * @tc.desc: Put data into the multiversion database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Put004, TestSize.Level1) @@ -274,7 +274,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Put004, TestSize.Level1 * @tc.name: Clear001 * @tc.desc: Clear the data from an exist distributed db * @tc.type: FUNC - * @tc.require: AR000CQDTM AR000CQS3R + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Clear001, TestSize.Level1) @@ -306,7 +306,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Clear001, TestSize.Leve * @tc.name: PutBatch001 * @tc.desc: Putbatch data into the multiversion database * @tc.type: FUNC - * @tc.require: AR000CQDTM AR000CQS3R + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, PutBatch001, TestSize.Level1) @@ -349,7 +349,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, PutBatch001, TestSize.L * @tc.name: PutBatch002 * @tc.desc: PutBatch modified data into the multiversion database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, PutBatch002, TestSize.Level1) @@ -391,7 +391,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, PutBatch002, TestSize.L * @tc.name: Delete001 * @tc.desc: Delete existed data from the multiversion database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Delete001, TestSize.Level1) @@ -422,7 +422,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Delete001, TestSize.Lev * @tc.name: Delete002 * @tc.desc: Delete non-existed data from the multiversion database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Delete002, TestSize.Level1) @@ -445,7 +445,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, Delete002, TestSize.Lev * @tc.name: DeleteBatch001 * @tc.desc: Delete the existed batch data from the multiversion database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, DeleteBatch001, TestSize.Level1) @@ -488,7 +488,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, DeleteBatch001, TestSiz * @tc.name: DeleteBatch002 * @tc.desc: Delete the non-existed batch data from the multiversion database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, DeleteBatch002, TestSize.Level1) @@ -514,7 +514,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, DeleteBatch002, TestSiz * @tc.name: GetEntries001 * @tc.desc: Get the batch data from the non-empty database by the prefix key. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetEntries001, TestSize.Level1) @@ -553,7 +553,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetEntries001, TestSize * @tc.name: GetEntries002 * @tc.desc: Get all the data(empty prefixkey) from the empty database. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetEntries002, TestSize.Level1) @@ -578,7 +578,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetEntries002, TestSize * @tc.name: GetEntries003 * @tc.desc: Get all the data(empty prefixkey) from the database. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetEntries003, TestSize.Level1) @@ -640,7 +640,7 @@ static void TestSnapshotCreateAndRelease() * @tc.name: GetSnapshot001 * @tc.desc: Get observer is empty, whether you get the snapshot. * @tc.type: FUNC - * @tc.require: AR000BVRNF AR000CQDTI + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshot001, TestSize.Level1) @@ -657,7 +657,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshot001, TestSiz * @tc.name: GetSnapshot002 * @tc.desc: Get observer is not empty, whether you get the snapshot. * @tc.type: FUNC - * @tc.require: AR000BVRNF AR000CQDTI + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshot002, TestSize.Level1) @@ -691,7 +691,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshot002, TestSiz * @tc.name: ReleaseSnapshot001 * @tc.desc: To test the function of releasing an empty snapshot. * @tc.type: FUNC - * @tc.require: AR000BVRNF AR000CQDTI + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, ReleaseSnapshot001, TestSize.Level1) @@ -709,7 +709,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, ReleaseSnapshot001, Tes * @tc.name: ReleaseSnapshot002 * @tc.desc: Release the obtained snapshot object that is not empty. * @tc.type: FUNC - * @tc.require: AR000BVRNF AR000CQDTI + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, ReleaseSnapshot002, TestSize.Level1) @@ -866,7 +866,7 @@ static void TestSnapshotEntryDelete() * @tc.desc: Obtain data from the obtained snapshot object and test the impact of the write * database on the snapshot obtained after the snapshot is obtained. * @tc.type: FUNC - * @tc.require: AR000BVRNH AR000CQDTJ + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshotEntry001, TestSize.Level1) @@ -879,7 +879,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshotEntry001, Te * @tc.name: get_snapshot_entry_002 * @tc.desc: Read the data of the invalid key from the obtained snapshot object. * @tc.type: FUNC - * @tc.require: AR000BVRNH AR000CQDTJ + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshotEntry002, TestSize.Level1) @@ -1100,7 +1100,7 @@ static void SnapshotTestPreEntriesDelete() * @tc.name: GetSnapshotEntries001 * @tc.desc: To test the function of obtaining full data when keyPrefix is set to null. * @tc.type: FUNC - * @tc.require: AR000BVRNI AR000CQDTK + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshotEntries001, TestSize.Level1) @@ -1237,7 +1237,7 @@ static void SnapshotTestEmptyPreEntriesDelete() * @tc.name: GetSnapshotEntries002 * @tc.desc: To test the function of obtaining the prefix data when keyPrefix is set to a non-empty value. * @tc.type: FUNC - * @tc.require: AR000BVRNI AR000CQDTK + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshotEntries002, TestSize.Level1) @@ -1251,7 +1251,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshotEntries002, * @tc.name: GetSnapshotEntries003 * @tc.desc: To test whether data can be obtained when keyPrefix is set to an ultra-long key. * @tc.type: FUNC - * @tc.require: AR000BVRNI AR000CQDTK + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshotEntries003, TestSize.Level1) @@ -1297,7 +1297,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, GetSnapshotEntries003, * @tc.name: TestTransactionException001 * @tc.desc: An exception occurred while the test transaction was executing. * @tc.type: FUNC - * @tc.require: AR000C0F0F AR000CQDTN or SR000BVRNJ + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, TransactionException001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_test.cpp index f6d10ef0..0a80081f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_test.cpp @@ -407,7 +407,7 @@ void DistributedDBInterfacesDataOperationTest::TearDown(void) * @tc.name: Put001 * @tc.desc: Put a data(non-empty key, non-empty value) into an exist distributed db * @tc.type: FUNC - * @tc.require: AR000CQDTM AR000CQS3Q + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, Put001, TestSize.Level1) @@ -435,7 +435,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, Put001, TestSize.Level1) * @tc.name: Put002 * @tc.desc: Put a data(empty key) into an exist distributed db * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, Put002, TestSize.Level1) @@ -454,7 +454,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, Put002, TestSize.Level1) * @tc.name: Put003 * @tc.desc: Put a data(non-empty key, empty value) into an exist distributed db * @tc.type: FUNC - * @tc.require: AR000CQDTM AR000CQS3Q + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, Put003, TestSize.Level1) @@ -474,7 +474,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, Put003, TestSize.Level1) * @tc.name: Put004 * @tc.desc: Put data into the local database * @tc.type: FUNC - * @tc.require: AR000CQDVD AR000CQS3Q + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, Put004, TestSize.Level1) @@ -537,7 +537,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, Put004, TestSize.Level1) * @tc.name: Clear001 * @tc.desc: Clear the data from an exist distributed db * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, Clear001, TestSize.Level1) @@ -570,7 +570,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, Clear001, TestSize.Level1) * @tc.name: PutBatch001 * @tc.desc: Putbatch data into the local database * @tc.type: FUNC - * @tc.require: AR000BVDFE AR000CQDVC + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, PutBatch001, TestSize.Level1) @@ -613,7 +613,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, PutBatch001, TestSize.Level1) * @tc.name: PutBatch002 * @tc.desc: PutBatch modified data into the local database * @tc.type: FUNC - * @tc.require: AR000BVDFE AR000CQDVC + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, PutBatch002, TestSize.Level1) @@ -655,7 +655,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, PutBatch002, TestSize.Level1) * @tc.name: Delete001 * @tc.desc: Delete existed data from the local database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, Delete001, TestSize.Level1) @@ -686,7 +686,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, Delete001, TestSize.Level1) * @tc.name: Delete002 * @tc.desc: Delete non-existed data from the local database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, Delete002, TestSize.Level1) @@ -709,7 +709,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, Delete002, TestSize.Level1) * @tc.name: DeleteBatch001 * @tc.desc: Delete the existed batch data from the local database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, DeleteBatch001, TestSize.Level1) @@ -752,7 +752,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, DeleteBatch001, TestSize.Leve * @tc.name: DeleteBatch002 * @tc.desc: Delete the non-existed batch data from the local database * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, DeleteBatch002, TestSize.Level1) @@ -778,7 +778,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, DeleteBatch002, TestSize.Leve * @tc.name: GetEntries001 * @tc.desc: Get the batch data from the non-empty database by the prefix key. * @tc.type: FUNC - * @tc.require: AR000C6TUQ AR000CQDV3 + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntries001, TestSize.Level1) @@ -817,7 +817,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntries001, TestSize.Level * @tc.name: GetEntries002 * @tc.desc: Get all the data(empty prefixkey) from the empty database. * @tc.type: FUNC - * @tc.require: AR000C6TUQ AR000CQDV3 + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntries002, TestSize.Level1) @@ -842,7 +842,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntries002, TestSize.Level * @tc.name: GetEntries003 * @tc.desc: Get all the data(empty prefixkey) from the database. * @tc.type: FUNC - * @tc.require: AR000C6TUQ AR000CQDV3 + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntries003, TestSize.Level1) @@ -878,7 +878,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntries003, TestSize.Level * @tc.name: GetSnapshot001 * @tc.desc: Get observer is empty, whether you get the snapshot. * @tc.type: FUNC - * @tc.require: AR000BVRNF AR000CQDTI + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetSnapshot001, TestSize.Level1) @@ -895,7 +895,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetSnapshot001, TestSize.Leve * @tc.name: GetSnapshot002 * @tc.desc: Get observer is not empty, whether you get the snapshot. * @tc.type: FUNC - * @tc.require: AR000BVRNF AR000CQDTI + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetSnapshot002, TestSize.Level1) @@ -929,7 +929,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetSnapshot002, TestSize.Leve * @tc.name: ReleaseSnapshot001 * @tc.desc: To test the function of releasing an empty snapshot. * @tc.type: FUNC - * @tc.require: AR000BVRNF AR000CQDTI + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationTest, ReleaseSnapshot001, TestSize.Level1) @@ -947,7 +947,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, ReleaseSnapshot001, TestSize. * @tc.name: ReleaseSnapshot002 * @tc.desc: Release the obtained snapshot object that is not empty. * @tc.type: FUNC - * @tc.require: AR000BVRNF AR000CQDTI + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDataOperationTest, ReleaseSnapshot002, TestSize.Level1) @@ -959,7 +959,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, ReleaseSnapshot002, TestSize. * @tc.name: SetConflictResolutionPolicySuccessTest001 * @tc.desc: Verify SetConflictResolutionPolicy() return OK with valid input. * @tc.type: FUNC - * @tc.require: AR000CQE12 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesDataOperationTest, SetConflictResolutionPolicySuccessTest001, TestSize.Level1) @@ -981,7 +981,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, SetConflictResolutionPolicySu * @tc.name: SetConflictResolutionPolicyFailedTest001 * @tc.desc: Verify SetConflictResolutionPolicy() return INVALID_ARGS with invalid input. * @tc.type: FUNC - * @tc.require: AR000CQE12 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesDataOperationTest, SetConflictResolutionPolicyFailedTest001, TestSize.Level1) @@ -1004,7 +1004,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, SetConflictResolutionPolicyFa * @tc.name: GetEntriesWithQuery001 * @tc.desc: check query_format. * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntriesWithQuery001, TestSize.Level1) @@ -1096,7 +1096,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntriesWithQuery001, TestS * @tc.name: GetEntriesWithQuery002 * @tc.desc: GetEntries(const Query &query, std::vector &entries) interface test. * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntriesWithQuery002, TestSize.Level1) @@ -1142,7 +1142,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntriesWithQuery002, TestS * @tc.name: GetEntriesWithQuery003 * @tc.desc: GetEntries(const Query &query, std::vector &entries) interface test. * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntriesWithQuery003, TestSize.Level1) @@ -1181,7 +1181,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntriesWithQuery003, TestS * @tc.name: GetEntriesWithQuery004 * @tc.desc: GetEntries(const Query &query, std::vector &entries) interface test. * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntriesWithQuery004, TestSize.Level1) @@ -1230,7 +1230,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, GetEntriesWithQuery004, TestS * @tc.name: QueryIsNotNull001 * @tc.desc: IsNotNull interface normal function * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryIsNotNull001, TestSize.Level1) @@ -1286,7 +1286,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryIsNotNull001, TestSize.L * @tc.name: QueryPreFixKey001 * @tc.desc: Normal function of query by prefix key * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryPreFixKey001, TestSize.Level1) @@ -1368,7 +1368,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryPreFixKey001, TestSize.L * @tc.name: QueryPreFixKey003 * @tc.desc: For special key prefix combination condition of query * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryPreFixKey003, TestSize.Level1) @@ -1431,7 +1431,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryPreFixKey003, TestSize.L * @tc.name: QueryPreFixKey004 * @tc.desc: Query a prefix that does not exist * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryPreFixKey004, TestSize.Level1) @@ -1476,7 +1476,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryPreFixKey004, TestSize.L * @tc.name: QueryGroup001 * @tc.desc: Query group nomal ability to change operation priority * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryGroup001, TestSize.Level1) @@ -1552,7 +1552,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryGroup001, TestSize.Level * @tc.name: QueryGroup002 * @tc.desc: Test for illegal Group query object * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryGroup002, TestSize.Level1) @@ -1630,7 +1630,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryGroup002, TestSize.Level * @tc.name: QueryGroup003 * @tc.desc: Query expressions containing nested parentheses * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryGroup003, TestSize.Level1) @@ -1678,7 +1678,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, QueryGroup003, TestSize.Level * @tc.name: multiOrderBy001 * @tc.desc: Test multiple orderby conditions together to query * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, multiOrderBy001, TestSize.Level1) @@ -1723,7 +1723,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, multiOrderBy001, TestSize.Lev * @tc.name: multiOrderBy001 * @tc.desc: For multiple order query. * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, PreifxAndOrderBy001, TestSize.Level1) @@ -1774,7 +1774,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, PreifxAndOrderBy001, TestSize * @tc.name: PrefixAndOther001 * @tc.desc: Combination of prefix query and logical filtering * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesDataOperationTest, PrefixAndOther001, TestSize.Level1) @@ -1811,7 +1811,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, PrefixAndOther001, TestSize.L * @tc.name: InKeys001 * @tc.desc: InKeys query base function * @tc.type: FUNC - * @tc.require: AR000GOH06 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeys001, TestSize.Level1) @@ -1873,7 +1873,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeys001, TestSize.Level1) * @tc.name: InKeysLimit001 * @tc.desc: InKeys query limit verification * @tc.type: FUNC - * @tc.require: AR000GOH06 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeysLimit001, TestSize.Level1) @@ -1928,7 +1928,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeysLimit001, TestSize.Leve * @tc.name: InKeysAndOther001 * @tc.desc: Combination of InKeys query and logical filtering * @tc.type: FUNC - * @tc.require: AR000GOH06 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeysAndOther001, TestSize.Level1) @@ -1987,7 +1987,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeysAndOther001, TestSize.L * @tc.name: InKeysAndOther002 * @tc.desc: Combination of InKeys query and logical filtering * @tc.type: FUNC - * @tc.require: AR000GOH06 + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeysAndOther002, TestSize.Level1) @@ -2028,10 +2028,10 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeysAndOther002, TestSize.L * @tc.name: WriteTimeSort001 * @tc.desc: For prefixKey query with orderBy writeTime asc * @tc.type: FUNC - * @tc.require: SR000H5U55 + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort001, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort001, TestSize.Level1) { /** * @tc.steps: step1. Create a database And Preset Data @@ -2103,10 +2103,10 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort001, TestSize.Le * @tc.name: WriteTimeSort002 * @tc.desc: For prefixKey query with orderBy writeTime asc * @tc.type: FUNC - * @tc.require: SR000H5U55 + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort002, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort002, TestSize.Level1) { /** * @tc.steps: step1. Create a database And Preset Data @@ -2168,10 +2168,10 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort002, TestSize.Le * @tc.name: WriteTimeSort003 * @tc.desc: For prefixKey query with orderBy writeTime desc * @tc.type: FUNC - * @tc.require: SR000H5U55 + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort003, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort003, TestSize.Level1) { /** * @tc.steps: step1. Create a database And Preset Data @@ -2243,10 +2243,10 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort003, TestSize.Le * @tc.name: WriteTimeSort004 * @tc.desc: For prefixKey query with orderBy writeTime asc * @tc.type: FUNC - * @tc.require: SR000H5U55 + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort004, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort004, TestSize.Level1) { /** * @tc.steps: step1. Create a database And Preset Data @@ -2320,10 +2320,10 @@ void CheckResultSize(KvStoreResultSet *resultSet, const std::vector &expect * @tc.name: WriteTimeSort005 * @tc.desc: For inkeys query with orderBy writeTime asc * @tc.type: FUNC - * @tc.require: SR000H5U55 + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort005, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort005, TestSize.Level1) { /** * @tc.steps: step1. Create a database And Preset Data @@ -2393,10 +2393,10 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort005, TestSize.Le * @tc.name: WriteTimeSort006 * @tc.desc: For inkeys query with orderBy writeTime desc * @tc.type: FUNC - * @tc.require: SR000H5U55 + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort006, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort006, TestSize.Level1) { /** * @tc.steps: step1. Create a database And Preset Data @@ -2466,7 +2466,7 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort006, TestSize.Le * @tc.name: WriteTimeSort007 * @tc.desc: For unsupport query when getEntries * @tc.type: FUNC - * @tc.require: SR000H5U55 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBInterfacesDataOperationTest, WriteTimeSort007, TestSize.Level0) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp index 982cf0ea..282cd502 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp @@ -54,13 +54,13 @@ namespace { std::string identifierName = DBCommon::TransferStringToHex(hashIdentifierName); std::string filePath = g_testDir + "/" + identifierName + "/"; if (databaseType == DBConstant::DB_TYPE_LOCAL) { // local - filePath += (DBConstant::LOCAL_SUB_DIR + "/" + DBConstant::LOCAL_DATABASE_NAME + + filePath += (std::string(DBConstant::LOCAL_SUB_DIR) + "/" + DBConstant::LOCAL_DATABASE_NAME + DBConstant::DB_EXTENSION); } else if (databaseType == DBConstant::DB_TYPE_SINGLE_VER) { // single ver - filePath += (DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::MAINDB_DIR + "/" + + filePath += (std::string(DBConstant::SINGLE_SUB_DIR) + "/" + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION); } else if (databaseType == DBConstant::DB_TYPE_MULTI_VER) { // multi ver - filePath += (DBConstant::MULTI_SUB_DIR + "/" + DBConstant::MULTI_VER_DATA_STORE + + filePath += (std::string(DBConstant::MULTI_SUB_DIR) + "/" + DBConstant::MULTI_VER_DATA_STORE + DBConstant::DB_EXTENSION); } else { filePath = ""; @@ -136,7 +136,7 @@ void DistributedDBInterfacesDatabaseCorruptTest::TearDown(void) * @tc.name: DatabaseCorruptionHandleTest001 * @tc.desc: Check the corruption detect without setting the corrupt handler. * @tc.type: FUNC - * @tc.require: AR000D487C SR000D4878 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest001, TestSize.Level3) @@ -180,7 +180,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes * @tc.name: DatabaseCorruptionHandleTest002 * @tc.desc: Get kv store through different parameters for the same storeID. * @tc.type: FUNC - * @tc.require: AR000D487C SR000D4878 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest002, TestSize.Level1) @@ -252,7 +252,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes * @tc.name: DatabaseCorruptionHandleTest003 * @tc.desc: Test the CloseKvStore Interface and check whether the database file can be closed. * @tc.type: FUNC - * @tc.require: AR000D487C SR000D4878 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest003, TestSize.Level1) @@ -325,7 +325,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes * @tc.name: DatabaseCorruptionHandleTest004 * @tc.desc: Test the DeleteKvStore Interface and check whether the database files can be removed. * @tc.type: FUNC - * @tc.require: AR000D487C SR000D4878 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest004, TestSize.Level1) @@ -385,7 +385,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes * @tc.name: DatabaseCorruptionHandleTest005 * @tc.desc: Test the DeleteKvStore Interface and check whether the database files can be removed. * @tc.type: FUNC - * @tc.require: AR000D487C SR000D4878 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTest005, TestSize.Level1) @@ -565,7 +565,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseRebuildTest001, Tes * @tc.name: DatabaseIntegrityCheck001 * @tc.desc: Test the integrity check option. * @tc.type: FUNC - * @tc.require: AR000D487C SR000D4878 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseIntegrityCheck001, TestSize.Level2) @@ -581,7 +581,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseIntegrityCheck001, * @tc.name: DatabaseIntegrityCheck002 * @tc.desc: Test the integrity check interface. * @tc.type: FUNC - * @tc.require: AR000D487C SR000D4878 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseIntegrityCheck002, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp index a6c0eb51..f8307e0d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp @@ -124,7 +124,7 @@ void DistributedDBInterfacesDatabaseRdKernelTest::TearDown(void) * @tc.name: GetKvStore003 * @tc.desc: Get kv store through different SecurityOption, abnormal or normal. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: * @tc.author: liuwenkai */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore003, TestSize.Level1) @@ -192,7 +192,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore003, TestSize.Le * @tc.name: GetKvStore004 * @tc.desc: Get kv store parameters with Observer and Notifier, then trigger callback. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: * @tc.author: liuwenkai */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore004, TestSize.Level1) @@ -509,7 +509,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStoreWithInvalidOptio * @tc.name: RepeatCloseKvStore001 * @tc.desc: Close the kv store repeatedly and check the database. * @tc.type: FUNC - * @tc.require: AR000C2F0C AR000CQDV7 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, RepeatCloseKvStore001, TestSize.Level2) @@ -564,7 +564,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, RepeatCloseKvStore001, Tes * @tc.name: CreatKvStoreWithSchema001 * @tc.desc: Create non-memory KvStore with schema, check if create success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, CreatKvStoreWithSchema001, TestSize.Level1) @@ -586,7 +586,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, CreatKvStoreWithSchema001, * @tc.name: OpenKvStoreWithStoreOnly001 * @tc.desc: open the kv store with the option that createDirByStoreIdOnly is true. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, OpenKvStoreWithStoreOnly001, TestSize.Level1) @@ -623,7 +623,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, OpenKvStoreWithStoreOnly00 * @tc.name: GetDBWhileOpened001 * @tc.desc: open the kv store with the option that createDirByStoreIdOnly is true. * @tc.type: FUNC - * @tc.require: AR000E8S2V + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetDBWhileOpened001, TestSize.Level1) @@ -728,7 +728,7 @@ namespace { * @tc.name: FreqOpenCloseDel001 * @tc.desc: Open/close/delete the kv store concurrently. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, FreqOpenCloseDel001, TestSize.Level2) @@ -740,7 +740,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, FreqOpenCloseDel001, TestS * @tc.name: FreqOpenClose001 * @tc.desc: Open and close the kv store concurrently. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, FreqOpenClose001, TestSize.Level2) @@ -752,7 +752,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, FreqOpenClose001, TestSize * @tc.name: CheckKvStoreDir001 * @tc.desc: Delete the kv store with the option that createDirByStoreIdOnly is true. * @tc.type: FUNC - * @tc.require: AR000CQDV7 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, CheckKvStoreDir001, TestSize.Level1) @@ -788,7 +788,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, CheckKvStoreDir001, TestSi * @tc.name: CompressionRate1 * @tc.desc: Open the kv store with invalid compressionRate and open successfully. * @tc.type: FUNC - * @tc.require: AR000G3QTT + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, CompressionRate1, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_test.cpp index 77952bc6..9aca7bed 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_test.cpp @@ -357,7 +357,7 @@ void DistributedDBInterfacesDatabaseTest::TearDown(void) * @tc.name: GetKvStore001 * @tc.desc: Get kv store through different parameters. * @tc.type: FUNC - * @tc.require: AR000CQDV4 AR000CQS3P + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetKvStore001, TestSize.Level1) @@ -484,7 +484,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetKvStore001, TestSize.Level1) * @tc.name: GetKvStore002 * @tc.desc: Get kv store through different parameters for the same storeID. * @tc.type: FUNC - * @tc.require: AR000CQDV5 AR000CQS3P + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetKvStore002, TestSize.Level1) @@ -553,7 +553,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetKvStore002, TestSize.Level1) * @tc.name: GetKvStore003 * @tc.desc: Get kv store through different SecurityOption, abnormal or normal. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: * @tc.author: liuwenkai */ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetKvStore003, TestSize.Level1) @@ -623,7 +623,7 @@ static void NotifierCallback(const KvStoreNbConflictData &data) * @tc.name: GetKvStore004 * @tc.desc: Get kv store parameters with Observer and Notifier, then trigger callback. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: * @tc.author: liuwenkai */ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetKvStore004, TestSize.Level1) @@ -685,7 +685,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetKvStore004, TestSize.Level1) * @tc.name: CloseKvStore001 * @tc.desc: Test the CloseKvStore Interface and check whether the database file can be closed. * @tc.type: FUNC - * @tc.require: AR000CQDV6 AR000CQS3P + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDatabaseTest, CloseKvStore001, TestSize.Level1) @@ -731,7 +731,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, CloseKvStore001, TestSize.Level1) * @tc.name: DeleteKvStore001 * @tc.desc: Test the DeleteKvStore Interface and check whether the database files can be removed. * @tc.type: FUNC - * @tc.require: AR000C2F0C AR000CQDV7 + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesDatabaseTest, DeleteKvStore001, TestSize.Level1) @@ -808,7 +808,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, DeleteKvStore001, TestSize.Level1) * @tc.name: RepeatCloseKvStore001 * @tc.desc: Close the kv store repeatedly and check the database. * @tc.type: FUNC - * @tc.require: AR000C2F0C AR000CQDV7 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseTest, RepeatCloseKvStore001, TestSize.Level2) @@ -863,7 +863,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, RepeatCloseKvStore001, TestSize.Le * @tc.name: CreatKvStoreWithSchema001 * @tc.desc: Create non-memory KvStore with schema, check if create success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseTest, CreatKvStoreWithSchema001, TestSize.Level1) @@ -925,7 +925,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, CreatKvStoreWithSchema001, TestSiz * @tc.name: CreatKvStoreWithSchema002 * @tc.desc: Create memory KvStore with schema, check if create success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseTest, CreatKvStoreWithSchema002, TestSize.Level1) @@ -955,7 +955,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, CreatKvStoreWithSchema002, TestSiz * @tc.name: OpenKvStoreWithSchema001 * @tc.desc: open an opened kvstore(non-memory, no-schema) with schema, check if open success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema001, TestSize.Level1) @@ -1030,7 +1030,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema001, TestSize * @tc.name: OpenKvStoreWithSchema002 * @tc.desc: open an opened kvstore(non-memory, schema) with schema, check if open success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema002, TestSize.Level1) @@ -1051,7 +1051,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema002, TestSize * @tc.name: OpenKvStoreWithSchema003 * @tc.desc: open an opened kvstore(memory) with different schemas, check if open success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema003, TestSize.Level1) @@ -1098,7 +1098,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema003, TestSize * @tc.name: OpenKvStoreWithSchema004 * @tc.desc: open a totally closed schema-kvstore(non-memory) with different schemas, check if open success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema004, TestSize.Level1) @@ -1123,7 +1123,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema004, TestSize * @tc.name: OpenKvStoreWithSchema005 * @tc.desc: open a totally closed non-schema-kvstore(non-memory) with different schemas, check if open success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema005, TestSize.Level1) @@ -1146,7 +1146,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema005, TestSize * @tc.name: OpenKvStoreWithSchema006 * @tc.desc: open a memory non-schema-kvstore with different schemas, check if open success. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: weifeng */ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema006, TestSize.Level1) @@ -1200,7 +1200,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithSchema006, TestSize * @tc.name: OpenKvStoreWithStoreOnly001 * @tc.desc: open the kv store with the option that createDirByStoreIdOnly is true. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithStoreOnly001, TestSize.Level1) @@ -1236,7 +1236,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, OpenKvStoreWithStoreOnly001, TestS * @tc.name: GetDBWhileOpened001 * @tc.desc: open the kv store with the option that createDirByStoreIdOnly is true. * @tc.type: FUNC - * @tc.require: AR000E8S2V + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetDBWhileOpened001, TestSize.Level1) @@ -1340,7 +1340,7 @@ namespace { * @tc.name: FreqOpenCloseDel001 * @tc.desc: Open/close/delete the kv store concurrently. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseTest, FreqOpenCloseDel001, TestSize.Level2) @@ -1352,7 +1352,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, FreqOpenCloseDel001, TestSize.Leve * @tc.name: FreqOpenClose001 * @tc.desc: Open and close the kv store concurrently. * @tc.type: FUNC - * @tc.require: AR000DR9K2 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseTest, FreqOpenClose001, TestSize.Level2) @@ -1364,7 +1364,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, FreqOpenClose001, TestSize.Level2) * @tc.name: CheckKvStoreDir001 * @tc.desc: Delete the kv store with the option that createDirByStoreIdOnly is true. * @tc.type: FUNC - * @tc.require: AR000CQDV7 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesDatabaseTest, CheckKvStoreDir001, TestSize.Level1) @@ -1399,7 +1399,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, CheckKvStoreDir001, TestSize.Level * @tc.name: CompressionRate1 * @tc.desc: Open the kv store with invalid compressionRate and open successfully. * @tc.type: FUNC - * @tc.require: AR000G3QTT + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBInterfacesDatabaseTest, CompressionRate1, TestSize.Level1) @@ -1515,8 +1515,68 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, KvObserver001, TestSize.Level0) observer.OnChange(changedData); RelationalStoreChangedDataImpl storeChangedData(""); observer.OnChange(storeChangedData); + observer.StoreObserver::OnChange(storeChangedData); StoreObserver::StoreChangedInfo info; observer.OnChange(std::move(info)); + StoreObserver::StoreChangedInfo info1; + observer.StoreObserver::OnChange(std::move(info1)); ChangedData simpleData; observer.OnChange(Origin::ORIGIN_ALL, "", std::move(simpleData)); + ChangedData simpleData1; + observer.StoreObserver::OnChange(Origin::ORIGIN_ALL, "", std::move(simpleData1)); + EXPECT_EQ(observer.StoreObserver::GetCallbackDetailsType(), static_cast(CallbackDetailsType::DEFAULT)); +} + +void AsyncGet001CheckRes(int count, const Key &key) +{ + for (int i = 0; i < count; ++i) { + std::vector entries; + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(key, entries), OK); + for (const auto &item : entries) { + EXPECT_EQ(VALUE_1, item.value); + } + } +} + +/** + * @tc.name: AsyncGet001 + * @tc.desc: Test get data by diff thread at the same time. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBInterfacesDatabaseTest, AsyncGet001, TestSize.Level4) +{ + /** + * @tc.steps: step1. Open the kv store with the option that comressionRate is invalid. + * @tc.expected: step1. Open kv store successfully. Returns OK. + */ + KvStoreNbDelegate::Option option; + const std::string storeId("AsyncGet001"); + g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + /** + * @tc.steps: step2. Get key in diff thead. + * @tc.expected: step2. Returns OK. + */ + const Key key = {'k', '1'}; + EXPECT_EQ(g_kvNbDelegatePtr->Put(key, VALUE_1), OK); + const int count = 1000; + std::thread t1([&key]() { + AsyncGet001CheckRes(count, key); + }); + std::thread t2([&key]() { + AsyncGet001CheckRes(count, key); + }); + std::thread t3([&key]() { + AsyncGet001CheckRes(count, key); + }); + t1.join(); + t2.join(); + t3.join(); + + g_mgr.CloseKvStore(g_kvNbDelegatePtr); + g_kvNbDelegatePtr = nullptr; + EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_device_identifier_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_device_identifier_test.cpp index d3e1b821..f0f16ad6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_device_identifier_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_device_identifier_test.cpp @@ -124,7 +124,7 @@ void DistributedDBDeviceIdentifierTest::TearDown(void) * @tc.desc: Set pragma to be GET_DEVICE_IDENTIFIER_OF_ENTRY, * set Key to be null and origDevice to be false, expect return INVALID_ARGS. * @tc.type: FUNC - * @tc.require: AR000D08KV + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier001, TestSize.Level1) @@ -152,7 +152,7 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier001, TestSize.Level1 * @tc.desc: Set pragma to be GET_DEVICE_IDENTIFIER_OF_ENTRY, * set Key to be null and origDevice to be true, expect return INVALID_ARGS. * @tc.type: FUNC - * @tc.require: AR000D08KV + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier002, TestSize.Level1) @@ -180,7 +180,7 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier002, TestSize.Level1 * @tc.desc: Set pragma to be GET_DEVICE_IDENTIFIER_OF_ENTRY and origDevice to be false. * Check if a non-existing key will return NOT_FOUND. * @tc.type: FUNC - * @tc.require: AR000D08KV + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier003, TestSize.Level1) @@ -206,7 +206,7 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier003, TestSize.Level1 * @tc.desc: Set pragma to be GET_DEVICE_IDENTIFIER_OF_ENTRY and origDevice to be true. * Check if a non-existing key will return NOT_FOUND. * @tc.type: FUNC - * @tc.require: AR000D08KV + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier004, TestSize.Level1) @@ -231,7 +231,7 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier004, TestSize.Level1 * @tc.name: DeviceIdentifier005 * @tc.desc: Set pragma to be GET_DEVICE_IDENTIFIER_OF_ENTRY and origDevice to be false. check if returns OK. * @tc.type: FUNC - * @tc.require: AR000D08KV + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier005, TestSize.Level1) @@ -256,7 +256,7 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier005, TestSize.Level1 * @tc.name: DeviceIdentifier006 * @tc.desc: Set pragma to be GET_DEVICE_IDENTIFIER_OF_ENTRY and origDevice to be true. check if returns OK. * @tc.type: FUNC - * @tc.require: AR000D08KV + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier006, TestSize.Level1) @@ -281,7 +281,7 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier006, TestSize.Level1 * @tc.name: DeviceIdentifier007 * @tc.desc: Set pragma to be GET_IDENTIFIER_OF_DEVICE. check if empty deviceID returns INVALID_ARGS. * @tc.type: FUNC - * @tc.require: AR000D08KV + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier007, TestSize.Level1) @@ -300,7 +300,7 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier007, TestSize.Level1 * @tc.name: DeviceIdentifier008 * @tc.desc: Set pragma to be GET_IDENTIFIER_OF_DEVICE. check if deviceIdentifier matches deviceID. * @tc.type: FUNC - * @tc.require: AR000D08KV + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBDeviceIdentifierTest, DeviceIdentifier008, TestSize.Level1) @@ -629,6 +629,18 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, StorageEngineTest005, TestSize.Level ASSERT_NE(storageEngine, nullptr); EXPECT_EQ(storageEngine->CheckEngineOption(g_property), E_OK); RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); + /** + * @tc.steps: step1. set max value size + * @tc.expected: step1. Expect return OK + */ + uint32_t valSize = 64 * 1024 * 1024; + PragmaData input = static_cast(&valSize); + EXPECT_TRUE(g_kvNbDelegatePtr->Pragma(SET_MAX_VALUE_SIZE, input) == OK); + /** + * @tc.steps: step2. set max value size again + * @tc.expected: step2. Expect return OK + */ + EXPECT_EQ(g_kvNbDelegatePtr->Pragma(SET_MAX_VALUE_SIZE, input), OK); } /** @@ -762,4 +774,39 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, StorageEngineTest008, TestSize.Level subs.push_back(sub); EXPECT_EQ(g_store->RemoveSubscribe(subs), -1); storageEngine->Release(); +} + +/** + * @tc.name: StorageEngineTest009 + * @tc.desc: Test pragma + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBDeviceIdentifierTest, StorageEngineTest009, TestSize.Level0) +{ + /** + * @tc.steps: step1. Remove device data with null db + * @tc.expected: step1. Return -E_INVALID_DB + */ + PragmaData input = nullptr; + auto con = std::make_shared(nullptr); + EXPECT_EQ(con->Pragma(RM_DEVICE_DATA, input), -E_INVALID_DB); + /** + * @tc.steps: step2. Remove device data with null + * @tc.expected: step2. Return DB_ERROR + */ + auto store = new(std::nothrow) SQLiteSingleVerNaturalStore(); + con->SetSafeDeleted(); + con = std::make_shared(store); + EXPECT_EQ(con->Pragma(RM_DEVICE_DATA, input), -E_INVALID_DB); + /** + * @tc.steps: step3. Remove device data with dev + * @tc.expected: step3. Return -E_NOT_INIT + */ + std::string dev = "dev"; + input = static_cast(&dev); + EXPECT_EQ(con->Pragma(RM_DEVICE_DATA, input), -E_NOT_INIT); + con = nullptr; + RefObject::KillAndDecObjRef(store); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_database_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_database_test.cpp index 244b0dff..4d868fae 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_database_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_database_test.cpp @@ -204,7 +204,7 @@ void DistributedDBInterfacesEncryptDatabaseTest::CheckRekeyWithExistedObserver(b * @tc.name: LocalDatabaseRekeyCheck001 * @tc.desc: Attempt to rekey while another delegate is existed. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, LocalDatabaseRekeyCheck001, TestSize.Level1) @@ -233,7 +233,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, LocalDatabaseRekeyCheck001, * @tc.name: LocalDatabaseRekeyCheck002 * @tc.desc: Attempt to rekey while the snapshot is existed. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, LocalDatabaseRekeyCheck002, TestSize.Level1) @@ -262,7 +262,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, LocalDatabaseRekeyCheck002, * @tc.name: MultiVerRekeyCheck001 * @tc.desc: Attempt to rekey while another delegate is existed. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, MultiVerRekeyCheck001, TestSize.Level1) @@ -291,7 +291,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, MultiVerRekeyCheck001, Test * @tc.name: MultiVerRekeyCheck002 * @tc.desc: Attempt to rekey while the snapshot is existed. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, MultiVerRekeyCheck002, TestSize.Level1) @@ -320,7 +320,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, MultiVerRekeyCheck002, Test * @tc.name: MultiVerRekeyCheck003 * @tc.desc: Attempt to rekey while the observer is existed. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, MultiVerRekeyCheck003, TestSize.Level1) @@ -376,7 +376,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, ExportAndImportCheck001, Te * @tc.name: SingleVerRekeyCheck001 * @tc.desc: Attempt to rekey while another delegate is existed. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, SingleVerRekeyCheck001, TestSize.Level1) @@ -428,7 +428,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, SingleVerRekeyCheck001, Tes * @tc.name: SingleVerRekeyCheck002 * @tc.desc: Attempt to rekey when the observer exists. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, SingleVerRekeyCheck002, TestSize.Level1) @@ -483,7 +483,7 @@ static void NotifierCallback(const KvStoreNbConflictData &data) * @tc.name: SingleVerRekeyCheck003 * @tc.desc: Attempt to rekey while the conflict notifier is set. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, SingleVerRekeyCheck003, TestSize.Level1) @@ -529,7 +529,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, SingleVerRekeyCheck003, Tes * @tc.name: SingleVerRekeyCheck004 * @tc.desc: Test rekey and removeDeviceData * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBInterfacesEncryptDatabaseTest, SingleVerRekeyCheck004, TestSize.Level3) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_delegate_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_delegate_test.cpp index 1d15ede5..96d4b864 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_delegate_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_encrypt_delegate_test.cpp @@ -144,7 +144,7 @@ void DistributedDBInterfacesEncryptDelegateTest::TearDown(void) {} * @tc.name: EncryptedDbOperation001 * @tc.desc: Test the single version db encrypted function. * @tc.type: FUNC - * @tc.require: AR000CQDT5 AR000CQDT6 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbOperation001, TestSize.Level1) @@ -222,7 +222,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbOperation001, Te * @tc.name: EncryptedDbOperation002 * @tc.desc: Test the local db encrypted function. * @tc.type: FUNC - * @tc.require: AR000CQDT5 AR000CQDT6 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbOperation002, TestSize.Level1) @@ -303,7 +303,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbOperation002, Te * @tc.name: EncryptedDbOperation003 * @tc.desc: Test the multi version db encrypted function. * @tc.type: FUNC - * @tc.require: AR000CQDT5 AR000CQDT6 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbOperation003, TestSize.Level1) @@ -385,7 +385,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbOperation003, Te * @tc.name: EncryptedDbSwitch001 * @tc.desc: Test the single version db for Rekey function. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch001, TestSize.Level1) @@ -451,7 +451,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch001, TestS * @tc.name: EncryptedDbSwitch002 * @tc.desc: Test the single version db Rekey function return BUSY because of multiple instances. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch002, TestSize.Level1) @@ -486,7 +486,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch002, TestS * @tc.name: EncryptedDbSwitch003 * @tc.desc: Test the single version db Rekey function return BUSY because of observer. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch003, TestSize.Level1) @@ -518,7 +518,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch003, TestS * @tc.name: EncryptedDbSwitch004 * @tc.desc: Test the single version db Rekey function return BUSY because of conflict notifier. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch004, TestSize.Level1) @@ -546,7 +546,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch004, TestS * @tc.name: EncryptedDbSwitch009 * @tc.desc: Test the single version db Rekey function from password1 to password2. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch009, TestSize.Level1) @@ -583,7 +583,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch009, TestS * @tc.name: EncryptedDbSwitch010 * @tc.desc: Test the single version db Rekey function from encrypted db unencrypted db . * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch010, TestSize.Level1) @@ -618,7 +618,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch010, TestS * @tc.name: EncryptedDbSwitch011 * @tc.desc: Test the single version db Rekey function from unencrypted db to encrypted db. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch011, TestSize.Level1) @@ -655,7 +655,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch011, TestS * @tc.name: EncryptedDbSwitch012 * @tc.desc: Test the local db Rekey function from password1 to password2. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch012, TestSize.Level1) @@ -704,7 +704,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch012, TestS * @tc.name: EncryptedDbSwitch013 * @tc.desc: Test the local db Rekey function from encrypted db unencrypted db . * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch013, TestSize.Level1) @@ -751,7 +751,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch013, TestS * @tc.name: EncryptedDbSwitch014 * @tc.desc: Test the local db Rekey function from unencrypted db to encrypted db. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch014, TestSize.Level1) @@ -799,7 +799,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch014, TestS * @tc.name: EncryptedDbSwitch015 * @tc.desc: Test the multi version db Rekey function from password1 to password2. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch015, TestSize.Level1) @@ -851,7 +851,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch015, TestS * @tc.name: EncryptedDbSwitch016 * @tc.desc: Test the multi version db Rekey function from encrypted db unencrypted db . * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch016, TestSize.Level1) @@ -898,7 +898,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch016, TestS * @tc.name: EncryptedDbSwitch017 * @tc.desc: Test the multi version db Rekey function from unencrypted db to encrypted db. * @tc.type: FUNC - * @tc.require: AR000CQDT7 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch017, TestSize.Level1) @@ -947,7 +947,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, EncryptedDbSwitch017, TestS * @tc.name: OpenEncryptedDb001 * @tc.desc: Test create an encrypted database successfully. * @tc.type: FUNC - * @tc.require: AR000CQDT5 AR000CQDT6 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, OpenEncryptedDb001, TestSize.Level1) @@ -985,7 +985,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, OpenEncryptedDb001, TestSiz * @tc.name: OpenEncryptedDb002 * @tc.desc: Test create an encrypted database failed. * @tc.type: FUNC - * @tc.require: AR000CQDT8 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, OpenEncryptedDb002, TestSize.Level1) @@ -1025,7 +1025,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, OpenEncryptedDb002, TestSiz * @tc.name: OpenEncryptedDb003 * @tc.desc: Test reopen an encrypted database successfully. * @tc.type: FUNC - * @tc.require: AR000CQDT8 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, OpenEncryptedDb003, TestSize.Level1) @@ -1077,7 +1077,7 @@ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, OpenEncryptedDb003, TestSiz * @tc.name: OpenEncryptedDb004 * @tc.desc: Test reopen an encrypted database failed. * @tc.type: FUNC - * @tc.require: AR000CQDT8 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesEncryptDelegateTest, OpenEncryptedDb004, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_rd_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_rd_test.cpp index 2c6befc7..882ebdd6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_rd_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_rd_test.cpp @@ -122,6 +122,8 @@ void DistributedDBInterfacesImportAndExportRdTest::TearDownTestCase(void) if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error!"); } + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAdapter(nullptr); RuntimeContext::GetInstance()->StopTaskPool(); // wait for all thread exit } @@ -241,7 +243,7 @@ int DistributedDBInterfacesImportAndExportRdTest::ModifyDataInPage(int modifyPos { FILE *fp = fopen(modifyFile, "rb+"); if (fp == nullptr) { - printf("Failed to open file"); + LOGE("Failed to open file"); return 1; } (void)fseek(fp, modifyPos, SEEK_SET); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp index 47a57962..dfd62a2e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp @@ -143,7 +143,7 @@ void DistributedDBInterfacesImportAndExportTest::TearDown(void) * @tc.name: NormalExport001 * @tc.desc: The data of the current version of the board is exported and the package file is single. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, NormalExport001, TestSize.Level1) @@ -191,7 +191,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, NormalExport001, TestSize.L * @tc.name: UndisturbedlSingleExport001 * @tc.desc: Check that the export action is an independent transaction. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, UndisturbedlSingleExport001, TestSize.Level1) @@ -264,7 +264,7 @@ static void GetSnapshotUnitTest(KvStoreDelegate *&kvDelegatePtr, KvStoreSnapshot * @tc.name: UndisturbedlMultiExport001 * @tc.desc: Check that the export action is an independent transaction. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, UndisturbedlMultiExport001, TestSize.Level1) @@ -336,7 +336,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, UndisturbedlMultiExport001, * @tc.name: ExportParameterCheck001 * @tc.desc: Check the verification of abnormal interface parameters. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExportParameterCheck001, TestSize.Level1) @@ -405,7 +405,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExportParameterCheck001, Te * @tc.name: ExportParameterCheck002 * @tc.desc: Check the verification of abnormal interface parameters. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExportParameterCheck002, TestSize.Level1) @@ -480,7 +480,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExportParameterCheck002, Te * @tc.name: NormalImport001 * @tc.desc: Normal import capability for single version, parameter verification capability * @tc.type: FUNC - * @tc.require: AR000D487A + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, NormalImport001, TestSize.Level1) @@ -539,7 +539,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, NormalImport001, TestSize.L * @tc.name: NormalImport002 * @tc.desc: Normal import capability for multi version, parameter verification capability * @tc.type: FUNC - * @tc.require: AR000D487A + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, NormalImport002, TestSize.Level1) @@ -605,7 +605,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, NormalImport002, TestSize.L * @tc.name: ExceptionFileImport001 * @tc.desc: Normal import capability for single version, parameter verification capability * @tc.type: FUNC - * @tc.require: AR000D487A + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExceptionFileImport001, TestSize.Level1) @@ -658,7 +658,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExceptionFileImport001, Tes * @tc.name: ExceptionFileImport002 * @tc.desc: Normal import capability for multi version, parameter verification capability * @tc.type: FUNC - * @tc.require: AR000D487A + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExceptionFileImport002, TestSize.Level1) @@ -690,7 +690,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExceptionFileImport002, Tes * @tc.name: ExceptionFileImport003 * @tc.desc: The data of the current version of the board is exported and the package file is single. * @tc.type: FUNC - * @tc.require: AR000D487A + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExceptionFileImport003, TestSize.Level1) @@ -750,7 +750,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExceptionFileImport003, Tes * @tc.name: ExceptionFileImport004 * @tc.desc: The data of the current version of the board is exported and the package file is single. * @tc.type: FUNC - * @tc.require: AR000D487A + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ExceptionFileImport004, TestSize.Level1) @@ -851,7 +851,7 @@ static void TryDbForPasswordIndependence001() * @tc.name: PasswordIndependence001 * @tc.desc: The data of the current version of the board is exported and the package file is single. * @tc.type: FUNC - * @tc.require: AR000D487B + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, PasswordIndependence001, TestSize.Level1) @@ -938,7 +938,7 @@ static void TryDbForPasswordIndependence002() * @tc.name: PasswordIndependence002 * @tc.desc: The data of the current version of the board is exported and the package file is single. * @tc.type: FUNC - * @tc.require: AR000D487B + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, PasswordIndependence002, TestSize.Level1) @@ -996,7 +996,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, PasswordIndependence002, Te * @tc.name: PasswordIndependence002 * @tc.desc: The data of the current version of the board is exported and the package file is single. * @tc.type: FUNC - * @tc.require: AR000D487B + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, PasswordIndependence003, TestSize.Level1) @@ -1061,7 +1061,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, PasswordIndependence003, Te * @tc.name: SeparaDbExportAndImport * @tc.desc: Import and export after Separate database. * @tc.type: FUNC - * @tc.require: AR000D487B + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, SeparaDbExportAndImport, TestSize.Level1) @@ -1120,7 +1120,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, SeparaDbExportAndImport, Te * @tc.name: SeparaDbExportAndImport * @tc.desc: Import and export after Separate database. * @tc.type: FUNC - * @tc.require: AR000D487B + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesImportAndExportTest, SeparaDbNoPasswdRekey, TestSize.Level1) @@ -1374,7 +1374,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ImportTest001, TestSize.Lev * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBInterfacesImportAndExportTest, CheckSecurityLabel001, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesImportAndExportTest, CheckSecurityLabel001, TestSize.Level1) { std::shared_ptr adapter = std::make_shared(); RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(adapter); @@ -1421,7 +1421,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, CheckSecurityLabel001, Test * @tc.require: * @tc.author: liuhongyang */ -HWTEST_F(DistributedDBInterfacesImportAndExportTest, CheckSecurityLabel002, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesImportAndExportTest, CheckSecurityLabel002, TestSize.Level1) { std::shared_ptr adapter = std::make_shared(); RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(adapter); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_index_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_index_unit_test.cpp index 1054a2f7..b65a08d6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_index_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_index_unit_test.cpp @@ -53,13 +53,13 @@ namespace { string identifierName = DBCommon::TransferStringToHex(hashIdentifierName); string filePath = g_testDir + "/" + identifierName + "/"; if (databaseType == DBConstant::DB_TYPE_LOCAL) { // local - filePath += (DBConstant::LOCAL_SUB_DIR + "/" + DBConstant::LOCAL_DATABASE_NAME + + filePath += (std::string(DBConstant::LOCAL_SUB_DIR) + "/" + DBConstant::LOCAL_DATABASE_NAME + DBConstant::DB_EXTENSION); } else if (databaseType == DBConstant::DB_TYPE_SINGLE_VER) { // single ver - filePath += (DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::MAINDB_DIR + "/" + + filePath += (std::string(DBConstant::SINGLE_SUB_DIR) + "/" + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION); } else if (databaseType == DBConstant::DB_TYPE_MULTI_VER) { // multi ver - filePath += (DBConstant::MULTI_SUB_DIR + "/" + DBConstant::MULTI_VER_DATA_STORE + + filePath += (std::string(DBConstant::MULTI_SUB_DIR) + "/" + DBConstant::MULTI_VER_DATA_STORE + DBConstant::DB_EXTENSION); } else { filePath = ""; @@ -285,7 +285,7 @@ namespace { * @tc.name: CrudIndex001 * @tc.desc: Test whether adding index is normal * @tc.type: FUNC - * @tc.require: AR000DR9K8 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CrudIndex001, TestSize.Level1) @@ -352,7 +352,7 @@ namespace { * @tc.name: CrudIndex002 * @tc.desc: Test whether deleting index is normal * @tc.type: FUNC - * @tc.require: AR000DR9K8 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CrudIndex002, TestSize.Level1) @@ -420,7 +420,7 @@ namespace { * @tc.name: CrudIndex003 * @tc.desc: Test whether updating index is normal * @tc.type: FUNC - * @tc.require: AR000DR9K8 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CrudIndex003, TestSize.Level1) @@ -499,7 +499,7 @@ namespace { * @tc.name: CreateIndex001 * @tc.desc: Test whether the index creation is normal * @tc.type: FUNC - * @tc.require: AR000DR9K9 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CreateIndex001, TestSize.Level1) @@ -569,7 +569,7 @@ namespace { * @tc.name: CreateIndex002 * @tc.desc: Test whether it is possible to insert 32 four-level indexes with each filed being 64. * @tc.type: FUNC - * @tc.require: AR000DR9K9 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CreateIndex002, TestSize.Level1) @@ -618,7 +618,7 @@ namespace { * @tc.name: Check schema skipsize 001 * @tc.desc: When SCHEMA_SKIPSIZE is not defined, check if the default is 0 * @tc.type: FUNC - * @tc.require: AR000DR9K9 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CheckSchemaSkipsize001, TestSize.Level1) @@ -658,7 +658,7 @@ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CheckSchemaSkipsize001, TestSize. * @tc.name: Check schema skipsize 002 * @tc.desc: SCHEMA_SKIPSIZE range is [0,4MB-2] * @tc.type: FUNC - * @tc.require: AR000DR9K9 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CheckSchemaSkipsize002, TestSize.Level1) @@ -740,7 +740,7 @@ namespace { * @tc.desc: When "SCHEMA_SKIPSIZE" is greater than or equal to the size of Value, * the Value verification must fail * @tc.type: FUNC - * @tc.require: AR000DR9K9 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CheckSchemaSkipsize003, TestSize.Level1) @@ -782,7 +782,7 @@ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CheckSchemaSkipsize003, TestSize. * @tc.desc: When the SCHEMA_SKIPSIZE definitions of two Schemas are different, * they will be regarded as inconsistent and incompatible * @tc.type: FUNC - * @tc.require: AR000DR9K9 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBInterfacesIndexUnitTest, SchemaCompareSkipsize004, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_log_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_log_test.cpp index c64cfb6c..b07666e6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_log_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_log_test.cpp @@ -60,7 +60,8 @@ HWTEST_F(DistributedDBInterfacesLogTest, DBFactoryTest001, TestSize.Level1) { DistributedTableMode mode = DistributedTableMode::COLLABORATION; TableSyncType tableSyncType = TableSyncType::DEVICE_COOPERATION; - auto tableManager = LogTableManagerFactory::GetTableManager(mode, tableSyncType); + TableInfo tableInfo; + auto tableManager = LogTableManagerFactory::GetTableManager(tableInfo, mode, tableSyncType); EXPECT_TRUE(tableManager != nullptr); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_extend_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_extend_test.cpp index 4a75ff22..1eb88f91 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_extend_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_extend_test.cpp @@ -690,7 +690,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, UpdateKey003, TestSize.Lev * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, BlockTimer001, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, BlockTimer001, TestSize.Level1) { /** * @tc.steps:step1. Create database. @@ -932,7 +932,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, SyncRangeQuery001, TestSiz * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, OptionModeValidCheck001, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, OptionModeValidCheck001, TestSize.Level1) { /** * @tc.steps:step1. Get the nb delegate. @@ -1164,23 +1164,9 @@ HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, AbnormalKvStoreTest003, Te EXPECT_EQ(kvStoreObj.GetCompensatedSyncQuery(syncQuery, users, true), E_OK); /** - * @tc.steps: step2. Call interfaces when class para is null. + * @tc.steps: step2. Get and set Schema with different para when class para is null. * @tc.expected: step2. return failInfo. */ - DataInfoWithLog log; - EXPECT_EQ(kvStoreObj.GetInfoByPrimaryKeyOrGid(tableName, vBucket, log, vBucket), -E_INTERNAL_ERROR); - DownloadData downloadData; - EXPECT_EQ(kvStoreObj.PutCloudSyncData(tableName, downloadData), -E_INTERNAL_ERROR); - Timestamp timestamp = 0; - int64_t count = 0; - EXPECT_EQ(kvStoreObj.GetUploadCount(query, timestamp, true, true, count), -E_INTERNAL_ERROR); - std::vector timestampVec; - EXPECT_EQ(kvStoreObj.GetAllUploadCount(query, timestampVec, true, true, count), -E_INTERNAL_ERROR); - - /** - * @tc.steps: step3. Get and set Schema with different para when class para is null. - * @tc.expected: step3. return failInfo. - */ TableSchema tableSchema; EXPECT_EQ(kvStoreObj.GetCloudTableSchema(tableName, tableSchema), -E_NOT_FOUND); CloudSyncData cloudDataResult; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_local_batch_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_local_batch_test.cpp index 9eb5ac60..ff1baa1e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_local_batch_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_local_batch_test.cpp @@ -129,7 +129,7 @@ void DistributedDBInterfacesNBDelegateLocalBatchTest::TearDown(void) * @tc.name: PutLocalBatch001 * @tc.desc: This test case use to verify the PutLocalBatch interface function * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, PutLocalBatch001, TestSize.Level1) @@ -217,7 +217,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, PutLocalBatch002, Test * @tc.name: SingleVerPutLocalBatch001 * @tc.desc: Check for illegal parameters * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch001, TestSize.Level1) @@ -259,7 +259,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch * @tc.name: SingleVerPutLocalBatch002 * @tc.desc: PutLocalBatch normal insert function test. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch002, TestSize.Level1) @@ -324,7 +324,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch * @tc.name: SingleVerPutLocalBatch003 * @tc.desc: Check interface atomicity * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch003, TestSize.Level1) @@ -398,7 +398,7 @@ static void PreparePutLocalBatch004(vector &entrys1, vector &entry * @tc.name: SingleVerPutLocalBatch004 * @tc.desc: Check interface data insertion and update functions. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch004, TestSize.Level1) @@ -671,7 +671,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch * @tc.name: SingleVerDeleteLocalBatch001 * @tc.desc: Check for illegal parameters. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerDeleteLocalBatch001, TestSize.Level1) @@ -770,7 +770,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerDeleteLocalBa * @tc.name: SingleVerDeleteLocalBatch002 * @tc.desc: Check normal delete batch ability. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerDeleteLocalBatch002, TestSize.Level1) @@ -988,7 +988,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerDeleteLocalBa * @tc.name: SingleVerPutLocalBatchObserver001 * @tc.desc: Test the observer function of PutLocalBatch() interface. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatchObserver001, TestSize.Level1) @@ -1055,7 +1055,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch * @tc.name: SingleVerPutLocalBatchObserver002 * @tc.desc: Test the observer function of PutLocalBatch() for invalid input. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatchObserver002, TestSize.Level4) @@ -1131,7 +1131,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch * @tc.name: SingleVerPutLocalBatchObserver003 * @tc.desc: Test the observer function of PutLocalBatch() update function. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatchObserver003, TestSize.Level1) @@ -1199,7 +1199,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch * @tc.name: SingleVerPutLocalBatchObserver004 * @tc.desc: Test the observer function of PutLocalBatch(), same keys handle. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatchObserver004, TestSize.Level1) @@ -1275,7 +1275,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerPutLocalBatch * @tc.name: SingleVerDeleteLocalBatchObserver001 * @tc.desc: Test the observer function of DeleteLocalBatch() interface. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerDeleteLocalBatchObserver001, TestSize.Level1) @@ -1337,7 +1337,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, SingleVerDeleteLocalBa * @tc.name: LocalDataBatchNotCheckSchema001 * @tc.desc: Local data does not check schema. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, LocalDataBatchNotCheckSchema001, TestSize.Level1) @@ -1410,7 +1410,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, LocalDataBatchNotCheck * @tc.name: LocalDataBatchNotCheckReadOnly001 * @tc.desc: Local data does not check readOnly. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesNBDelegateLocalBatchTest, LocalDataBatchNotCheckReadOnly001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_schema_put_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_schema_put_test.cpp index 06b91ce1..1e126901 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_schema_put_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_schema_put_test.cpp @@ -203,7 +203,7 @@ void DistributedDBInterfacesNBDelegateSchemaPutTest::TearDown(void) * @tc.name: PutValueStrictSchemaCheck001 * @tc.desc: Check the value in the strict schema mode. * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, PutValueStrictSchemaCheck001, TestSize.Level1) @@ -246,7 +246,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, PutValueStrictSchemaChe * @tc.name: PutValueReadOnlyCheck001 * @tc.desc: Test writing the data into the no-schema kvStore which has schema originally. * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, PutValueCompaSchemaCheck001, TestSize.Level1) @@ -285,7 +285,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, PutValueCompaSchemaChec * @tc.name: PutValueReadOnlyCheck001 * @tc.desc: Test writing the data into the no-schema kvStore which has schema originally. * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, PutValueReadOnlyCheck001, TestSize.Level1) @@ -321,7 +321,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, PutValueReadOnlyCheck00 * @tc.name: QueryDeleted001 * @tc.desc: Test the query in the deleted scene. * @tc.type: FUNC - * @tc.require: AR000DR9K5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBDelegateSchemaPutTest, QueryDeleted001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp index eec05b15..c49d39f8 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp @@ -260,7 +260,7 @@ void DistributedDBInterfacesNBDelegateTest::TearDown(void) * @tc.name: CombineTest001 * @tc.desc: Test the NbDelegate for combined operation. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest001, TestSize.Level1) @@ -367,7 +367,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest001, TestSize.Level1) * @tc.name: CombineTest002 * @tc.desc: Test the NbDelegate for combined operation, try to use GAUSSDB_RD. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhujinlin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest002, TestSize.Level1) @@ -381,7 +381,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest002, TestSize.Level1) g_mgr.GetKvStore("distributed_nb_delegate_test_rd", option, g_kvNbDelegateCallback); ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); EXPECT_TRUE(g_kvDelegateStatus == OK); - std::string keyStr("acd"); + std::string keyStr("key"); Key key(keyStr.begin(), keyStr.end()); std::string valueStr("acd"); Value value(valueStr.begin(), valueStr.end()); @@ -426,7 +426,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest002, TestSize.Level1) * @tc.name: CombineTest003 * @tc.desc: Test the NbDelegate for combined operation, try to use GAUSSDB_RD and index type with hash. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhujinlin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest003, TestSize.Level1) @@ -486,7 +486,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest003, TestSize.Level1) * @tc.name: CreateMemoryDb001 * @tc.desc: Create memory database after. * @tc.type: FUNC - * @tc.require: AR000CRAKN + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDb001, TestSize.Level1) @@ -529,7 +529,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDb001, TestSize.Leve * @tc.name: CreateMemoryDb002 * @tc.desc: The MemoryDB cannot be created or open, when the physical database has been opened * @tc.type: FUNC - * @tc.require: AR000CRAKN + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDb002, TestSize.Level1) @@ -562,7 +562,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDb002, TestSize.Leve * @tc.name: CreateMemoryDb003 * @tc.desc: The physical database cannot be created or open, when the MemoryDB has been opened. * @tc.type: FUNC - * @tc.require: AR000CRAKN + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDb003, TestSize.Level1) @@ -593,7 +593,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDb003, TestSize.Leve * @tc.name: OperMemoryDbData001 * @tc.desc: Operate memory database * @tc.type: FUNC - * @tc.require: AR000CRAKN + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, OperMemoryDbData001, TestSize.Level1) @@ -654,7 +654,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, OperMemoryDbData001, TestSize.Le * @tc.name: CloseMemoryDb001 * @tc.desc: Operate memory database after reopen memory database * @tc.type: FUNC - * @tc.require: AR000CRAKN + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CloseMemoryDb001, TestSize.Level1) @@ -705,7 +705,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CloseMemoryDb001, TestSize.Level * @tc.name: ResultSetTest001 * @tc.desc: Test the NbDelegate for result set function. * @tc.type: FUNC - * @tc.require: AR000D08KT + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, ResultSetTest001, TestSize.Level1) @@ -793,7 +793,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, ResultSetTest001, TestSize.Level * @tc.name: PutBatchVerify001 * @tc.desc: This test case use to verify the putBatch interface function * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, PutBatchVerify001, TestSize.Level1) @@ -885,7 +885,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, PutBatchVerify002, TestSize.Leve * @tc.name: SingleVerPutBatch001 * @tc.desc: Check for illegal parameters * @tc.type: FUNC - * @tc.require: AR000DPTQ8 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatch001, TestSize.Level1) @@ -927,7 +927,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatch001, TestSize.L * @tc.name: SingleVerPutBatch002 * @tc.desc: PutBatch normal insert function test. * @tc.type: FUNC - * @tc.require: AR000DPTQ8 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatch002, TestSize.Level1) @@ -992,7 +992,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatch002, TestSize.L * @tc.name: SingleVerPutBatch003 * @tc.desc: Check interface atomicity * @tc.type: FUNC - * @tc.require: AR000DPTQ8 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatch003, TestSize.Level1) @@ -1066,7 +1066,7 @@ static void PreparePutBatch004(vector &entrys1, vector &entrys2, v * @tc.name: SingleVerPutBatch004 * @tc.desc: Check interface data insertion and update functions. * @tc.type: FUNC - * @tc.require: AR000DPTQ8 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatch004, TestSize.Level1) @@ -1435,7 +1435,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatch009, TestSize.L * @tc.name: SingleVerDeleteBatch001 * @tc.desc: Check for illegal parameters. * @tc.type: FUNC - * @tc.require: AR000DPTQ8 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerDeleteBatch001, TestSize.Level1) @@ -1537,7 +1537,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerDeleteBatch001, TestSiz * @tc.name: SingleVerDeleteBatch002 * @tc.desc: Check normal delete batch ability. * @tc.type: FUNC - * @tc.require: AR000DPTQ8 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerDeleteBatch002, TestSize.Level1) @@ -1793,7 +1793,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerDeleteBatch007, TestSiz * @tc.name: SingleVerPutBatchObserver001 * @tc.desc: Test the observer function of PutBatch() interface. * @tc.type: FUNC - * @tc.require: AR000DPTTA + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatchObserver001, TestSize.Level1) @@ -1861,7 +1861,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatchObserver001, Te * @tc.name: SingleVerPutBatchObserver002 * @tc.desc: Test the observer function of PutBatch() for invalid input. * @tc.type: FUNC - * @tc.require: AR000DPTTA + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatchObserver002, TestSize.Level4) @@ -1936,7 +1936,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatchObserver002, Te * @tc.name: SingleVerPutBatchObserver003 * @tc.desc: Test the observer function of PutBatch() update function. * @tc.type: FUNC - * @tc.require: AR000DPTTA + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatchObserver003, TestSize.Level1) @@ -2003,7 +2003,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatchObserver003, Te * @tc.name: SingleVerPutBatchObserver004 * @tc.desc: Test the observer function of PutBatch(), same keys handle. * @tc.type: FUNC - * @tc.require: AR000DPTTA + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatchObserver004, TestSize.Level1) @@ -2078,7 +2078,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerPutBatchObserver004, Te * @tc.name: SingleVerDeleteBatchObserver001 * @tc.desc: Test the observer function of DeleteBatch() interface. * @tc.type: FUNC - * @tc.require: AR000DPTTA + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerDeleteBatchObserver001, TestSize.Level1) @@ -2139,7 +2139,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerDeleteBatchObserver001, * @tc.name: SingleVerConcurrentPut001 * @tc.desc: Test put the data concurrently, and check the timestamp. * @tc.type: FUNC - * @tc.require: AR000DPTTA + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerConcurrentPut001, TestSize.Level4) @@ -2185,7 +2185,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerConcurrentPut001, TestS * @tc.name: SingleVerGetLocalEntries001 * @tc.desc: Test GetLocalEntries interface for the single ver database. * @tc.type: FUNC - * @tc.require: AR000DPTTA + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerGetLocalEntries001, TestSize.Level1) @@ -2274,7 +2274,7 @@ static vector PreDataForQueryByPreFixKey() * @tc.name: QueryPreFixKey002 * @tc.desc: The query method without filtering the field can query non-schma databases * @tc.type: FUNC - * @tc.require: AR000EPARK + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, QueryPreFixKey002, TestSize.Level1) @@ -2325,7 +2325,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, QueryPreFixKey002, TestSize.Leve * @tc.name: SingleVerGetSecurityOption001 * @tc.desc: Test GetSecurityOption interface for the single ver database. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: * @tc.author: liuwenkai */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerGetSecurityOption001, TestSize.Level1) @@ -2373,7 +2373,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerGetSecurityOption001, T * @tc.name: SingleVerGetSecurityOption002 * @tc.desc: Test GetSecurityOption interface for the single ver database. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: * @tc.author: liuwenkai */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerGetSecurityOption002, TestSize.Level1) @@ -2601,7 +2601,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, MaxLogCheckPoint001, TestSize.Le * @tc.name: CreateMemoryDbWithoutPath * @tc.desc: Create memory database without path. * @tc.type: FUNC - * @tc.require: AR000CRAKN + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDbWithoutPath, TestSize.Level1) @@ -2623,7 +2623,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDbWithoutPath, TestS * @tc.name: OpenStorePathCheckTest001 * @tc.desc: Test open store with same label but different path. * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, OpenStorePathCheckTest001, TestSize.Level1) @@ -2674,7 +2674,7 @@ std::string GetRealFileUrl(const std::string &dbPath, const std::string &appId, * @tc.name: BusyTest001 * @tc.desc: Test put kv data while another thread holds the transaction for one second * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, BusyTest001, TestSize.Level1) @@ -2842,4 +2842,164 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, RemoveDeviceDataTest001, TestSiz FreeVirtualDevice(g_deviceC); FreeVirtualDevice(g_deviceD); } + +/** + * @tc.name: RekeyTest001 + * @tc.desc: Test rekey with multi db handles. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonnghuang + */ +HWTEST_F(DistributedDBInterfacesNBDelegateTest, RekeyTest001, TestSize.Level1) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + CipherPassword passwd; + const std::vector PASSWD_VECTOR_1 = {'P', 'a', 's', 's', 'w', 'o', 'r', 'd', '@', '1', '2', '3'}; + const std::vector PASSWD_VECTOR_2 = {'P', 'a', 's', 's', 'w', 'o', 'r', 'd', '@', '0', '0', '0'}; + const std::vector PASSWD_VECTOR_3 = {'P', 'a', 's', 's', 'w', 'o', 'r', 'd', '@', '0', '0', '1'}; + KvStoreNbDelegate::Option option = {true, false, true}; + (void)passwd.SetValue(PASSWD_VECTOR_1.data(), PASSWD_VECTOR_1.size()); + option.passwd = passwd; + g_mgr.SetKvStoreConfig(g_config); + g_mgr.GetKvStore("rekeyTest001", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + KvStoreNbDelegate *kvNbDelegatePtr001 = g_kvNbDelegatePtr; + + /** + * @tc.steps:step2. Rekey. + * @tc.expected: step2. Returns OK. + */ + (void)passwd.SetValue(PASSWD_VECTOR_2.data(), PASSWD_VECTOR_2.size()); + kvNbDelegatePtr001->Rekey(passwd); + + /** + * @tc.steps:step3. Open DB and rekey. + * @tc.expected: step3. Returns not OK. + */ + sqlite3 *db = nullptr; + int flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + const auto &dbPath = g_testDir + + "/cf479925e0691d2df83f095db294ee671a7a8f38e7527fef0dd1b40f8e3cb476/single_ver/main/gen_natural_store.db"; + int rc = sqlite3_open_v2(dbPath.c_str(), &db, flag, nullptr); + EXPECT_TRUE(rc == SQLITE_OK); + (void)passwd.SetValue(PASSWD_VECTOR_3.data(), PASSWD_VECTOR_3.size()); + EXPECT_FALSE(kvNbDelegatePtr001->Rekey(passwd) == OK); + g_mgr.CloseKvStore(kvNbDelegatePtr001); + sqlite3_close(db); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: RekeyTest002 + * @tc.desc: Test normal rekey. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBInterfacesNBDelegateTest, RekeyTest002, TestSize.Level0) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + CipherPassword passwd; + const std::vector PASSWD_VECTOR = {'P', 'a', 's', 's', 'w', 'o', 'r', 'd', '@', '1', '2', '3'}; + KvStoreNbDelegate::Option option = {true, false, true}; + (void)passwd.SetValue(PASSWD_VECTOR.data(), PASSWD_VECTOR.size()); + option.passwd = passwd; + g_mgr.SetKvStoreConfig(g_config); + g_mgr.GetKvStore("rekeyTest002", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps:step2. Rekey. + * @tc.expected: step2. Returns OK. + */ + const std::vector NEW_PASSWD_VECTOR = {'P', 'a', 's', 's', 'w', 'o', 'r', 'd', '@', '1', '1', '1'}; + (void)passwd.SetValue(NEW_PASSWD_VECTOR.data(), NEW_PASSWD_VECTOR.size()); + EXPECT_TRUE(g_kvNbDelegatePtr->Rekey(passwd) == OK); + g_mgr.CloseKvStore(g_kvNbDelegatePtr); + g_kvNbDelegatePtr = nullptr; + option.passwd = passwd; + g_mgr.GetKvStore("rekeyTest002", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + g_mgr.CloseKvStore(g_kvNbDelegatePtr); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: SetAndGetHandleTest001 + * @tc.desc: Test SetHandle and GetHandle. + * @tc.type: FUNC + * @tc.require: + * @tc.author: lideshi + */ +HWTEST_F(DistributedDBInterfacesNBDelegateTest, SetAndGetHandleTest001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + KvStoreNbDelegate::Option option = {true, false, false}; + option.storageEngineType = GAUSSDB_RD; + g_mgr.GetKvStore("distributed_nb_delegate_test_rd", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + auto kvStoreImpl = static_cast(g_kvNbDelegatePtr); + void *handle = DBCommon::LoadGrdLib(); + kvStoreImpl->SetHandle(handle); + DBCommon::UnLoadGrdLib(nullptr); + DBCommon::UnLoadGrdLib(handle); + handle = nullptr; + /** + * @tc.steps:step2. Close the kv store. + * @tc.expected: step2. Results OK and delete successfully. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_nb_delegate_test_rd"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: SetAndGetHandleTest002 + * @tc.desc: Test multi get delegate. + * @tc.type: FUNC + * @tc.require: + * @tc.author: lideshi + */ +HWTEST_F(DistributedDBInterfacesNBDelegateTest, SetAndGetHandleTest002, TestSize.Level0) +{ + const std::string dbName = "storeId"; + + KvStoreNbDelegate::Option option = {true, false, false}; + option.storageEngineType = GAUSSDB_RD; + static int openCount = 2; // test open count 2 + + std::vector delegates; + KvStoreDelegateManager g_mgrTest("app1", "user1"); + g_mgrTest.SetKvStoreConfig(g_config); + for (int i = 0; i < openCount; i++) { + KvStoreNbDelegate *delegate = nullptr; + DBStatus kvDelegateStatus = INVALID_ARGS; + auto callback1 = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback, placeholders::_1, + placeholders::_2, std::ref(kvDelegateStatus), std::ref(delegate)); + g_mgrTest.GetKvStore(dbName + std::to_string(i), option, callback1); + ASSERT_TRUE(delegate != nullptr); + EXPECT_TRUE(kvDelegateStatus == OK); + delegates.push_back(delegate); + } + + for (int i = 0; i < openCount; i++) { + EXPECT_EQ(g_mgrTest.CloseKvStore(delegates[i]), OK); + EXPECT_EQ(g_mgrTest.DeleteKvStore(dbName + std::to_string(i)), OK); + delegates[i] = nullptr; + } +} } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_publish_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_publish_test.cpp index 46fff6d3..f0e9bcfd 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_publish_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_publish_test.cpp @@ -120,7 +120,7 @@ void DistributedDBInterfacesNBPublishTest::TearDown(void) {} * @tc.name: SingleVerPublishKey001 * @tc.desc: Publish nonexistent key * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey001, TestSize.Level1) @@ -207,7 +207,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey001, TestSize. * @tc.name: SingleVerPublishKey002 * @tc.desc: Publish no conflict key without deleting key from local table * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey002, TestSize.Level1) @@ -284,7 +284,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey002, TestSize. * @tc.name: SingleVerPublishKey003 * @tc.desc: Publish no conflict key with deleting key from local table * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey003, TestSize.Level1) @@ -360,7 +360,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey003, TestSize. * @tc.name: SingleVerPublishKey004 * @tc.desc: Publish conflict key and update timestamp * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey004, TestSize.Level1) @@ -438,7 +438,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey004, TestSize. * @tc.name: SingleVerPublishKey005 * @tc.desc: Publish conflict key but do not update timestamp * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey005, TestSize.Level1) @@ -515,7 +515,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey005, TestSize. * @tc.name: SingleVerPublishKey006 * @tc.desc: Publish no conflict key and onConflict() not null * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey006, TestSize.Level1) @@ -556,7 +556,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey006, TestSize. * @tc.name: SingleVerPublishKey007 * @tc.desc: Publish conflict key and onConflict() not null * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey007, TestSize.Level1) @@ -604,7 +604,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey007, TestSize. * @tc.name: SingleVerPublishKey008 * @tc.desc: Publish conflict key and onConflict() not null, need update timestamp * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey008, TestSize.Level1) @@ -652,7 +652,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey008, TestSize. * @tc.name: SingleVerPublishKey009 * @tc.desc: Publish conflict key (deleted) and onConflict() not null * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey009, TestSize.Level1) @@ -699,7 +699,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey009, TestSize. * @tc.name: SingleVerPublishKey010 * @tc.desc: Publish conflict key (deleted) and onConflict() not null, need update timestamp * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey010, TestSize.Level1) @@ -746,7 +746,7 @@ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey010, TestSize. * @tc.name: SingleVerPublishKey011 * @tc.desc: Publish conflict key (deleted) and onConflict() not null, put(k1,v1) in callback method * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBPublishTest, SingleVerPublishKey011, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_transaction_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_transaction_test.cpp index 0df4a6c9..44427f4a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_transaction_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_transaction_test.cpp @@ -157,7 +157,7 @@ void DistributedDBInterfacesNBTransactionTest::TearDown(void) {} * @tc.name: start001 * @tc.desc: Test the nb transaction start twice. * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, start001, TestSize.Level1) @@ -189,7 +189,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, start001, TestSize.Level1) * @tc.name: start002 * @tc.desc: Test the nb transaction begin and end not match. * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, start002, TestSize.Level1) @@ -239,7 +239,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, start002, TestSize.Level1) * @tc.name: start003 * @tc.desc: Test the nb transaction rollback automatically when db close. * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, start003, TestSize.Level1) @@ -291,7 +291,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, start003, TestSize.Level1) * @tc.name: start004 * @tc.desc: Test the nb operations return BUSY after transaction started. * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, start004, TestSize.Level4) @@ -345,7 +345,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, start004, TestSize.Level4) * @tc.name: commit001 * @tc.desc: Test the nb transaction commit without start. * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit001, TestSize.Level1) @@ -370,7 +370,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit001, TestSize.Level1) * @tc.name: commit002 * @tc.desc: Test the nb transaction commit twice. * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit002, TestSize.Level1) @@ -425,7 +425,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit002, TestSize.Level1) * @tc.name: commit003 * @tc.desc: Test the entry size exceed the maximum limit in one transaction * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit003, TestSize.Level1) @@ -498,7 +498,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit003, TestSize.Level1) * @tc.name: commit004 * @tc.desc: Test the nb normal operations in one transaction * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit004, TestSize.Level1) @@ -584,7 +584,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit004, TestSize.Level1) * @tc.name: commit005 * @tc.desc: Test the conflict data report normally in one transaction * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit005, TestSize.Level1) @@ -651,7 +651,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit005, TestSize.Level1) * @tc.name: commit006 * @tc.desc: Test the conflict data report and observer function both be normal in one transaction * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit006, TestSize.Level1) @@ -725,7 +725,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, commit006, TestSize.Level1) * @tc.name: rollback001 * @tc.desc: Test the transaction rollback without start. * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback001, TestSize.Level1) @@ -750,7 +750,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback001, TestSize.Level1) * @tc.name: rollback002 * @tc.desc: Test the transaction rollback twice * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback002, TestSize.Level1) @@ -785,7 +785,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback002, TestSize.Level1) * @tc.name: rollback003 * @tc.desc: Test the Put operation rollback * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback003, TestSize.Level1) @@ -833,7 +833,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback003, TestSize.Level1) * @tc.name: rollback004 * @tc.desc: Test the PutBatch operation rollback * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback004, TestSize.Level1) @@ -885,7 +885,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback004, TestSize.Level1) * @tc.name: rollback005 * @tc.desc: Test the modify operation rollback * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback005, TestSize.Level1) @@ -933,7 +933,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback005, TestSize.Level1) * @tc.name: rollback006 * @tc.desc: Test the Delete operation rollback * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback006, TestSize.Level1) @@ -981,7 +981,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback006, TestSize.Level1) * @tc.name: rollback007 * @tc.desc: Test the DeleteBatch operation rollback * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback007, TestSize.Level1) @@ -1030,7 +1030,7 @@ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback007, TestSize.Level1) * @tc.name: rollback008 * @tc.desc: Test the multiple operations rollback * @tc.type: FUNC - * @tc.require: AR000DPTQ9 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBInterfacesNBTransactionTest, rollback008, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_unpublish_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_unpublish_test.cpp index 5958850d..012539dd 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_unpublish_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_unpublish_test.cpp @@ -137,7 +137,7 @@ void DistributedDBInterfacesNBUnpublishTest::TearDown(void) * @tc.name: CombineTest001 * @tc.desc: Test unpublish one nonexistent data. * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey001, TestSize.Level1) @@ -202,7 +202,7 @@ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey001, TestS * @tc.name: SingleVerUnPublishKey002 * @tc.desc: Test unpublish existent data(no conflict with the local data). * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey002, TestSize.Level1) @@ -279,7 +279,7 @@ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey002, TestS * @tc.name: SingleVerUnPublishKey003 * @tc.desc: Test unpublish one existent data(conflict with the local data). * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey003, TestSize.Level1) @@ -360,7 +360,7 @@ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey003, TestS * @tc.name: SingleVerUnPublishKey004 * @tc.desc: Test unpublish one deleted data(no conflict with the local data). * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey004, TestSize.Level1) @@ -399,7 +399,7 @@ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey004, TestS * @tc.name: SingleVerUnPublishKey005 * @tc.desc: Test unpublish one existent data(conflict with the local data). * @tc.type: FUNC - * @tc.require: AR000DPTQ5 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBUnpublishTest, SingleVerUnPublishKey005, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_query_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_query_test.cpp index 6935d672..23daa5db 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_query_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_query_test.cpp @@ -138,7 +138,7 @@ void DistributedDBInterfacesQueryTest::TearDown(void) * @tc.name: Query001 * @tc.desc: Check the legal single query operation to see if the generated container is correct * @tc.type: FUNC - * @tc.require: AR000DR9K6 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesQueryTest, Query001, TestSize.Level1) @@ -193,7 +193,7 @@ HWTEST_F(DistributedDBInterfacesQueryTest, Query001, TestSize.Level1) * @tc.name: Query002 * @tc.desc: Check for illegal query conditions * @tc.type: FUNC - * @tc.require: AR000DR9K6 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesQueryTest, Query002, TestSize.Level1) @@ -211,7 +211,7 @@ HWTEST_F(DistributedDBInterfacesQueryTest, Query002, TestSize.Level1) * @tc.name: Query003 * @tc.desc: Check combination condition * @tc.type: FUNC - * @tc.require: AR000DR9K6 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesQueryTest, Query003, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_register_syncdb_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_register_syncdb_test.cpp index 37d80108..3c1e61c2 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_register_syncdb_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_register_syncdb_test.cpp @@ -178,7 +178,7 @@ void DistributedDBInterfacesRegisterSyncDBTest::TearDown(void) * @tc.name: RegisterObserver001 * @tc.desc: normal register observer success. * @tc.type: FUNC - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver001, TestSize.Level1) @@ -190,7 +190,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver001, TestSiz * @tc.name: RegisterObserver002 * @tc.desc: register(null object) observer success * @tc.type: FUNC - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver002, TestSize.Level1) @@ -202,7 +202,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver002, TestSiz * @tc.name: RegisterObserver003 * @tc.desc: Test the new data and check the processing result of the callback function. * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver003, TestSize.Level1) @@ -238,7 +238,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver003, TestSiz * @tc.name: RegisterObserver004 * @tc.desc: register observer success and putbach callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver004, TestSize.Level1) @@ -279,7 +279,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver004, TestSiz * @tc.name: RegisterObserver005 * @tc.desc: register observer success and putbach callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver005, TestSize.Level1) @@ -328,7 +328,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver005, TestSiz * @tc.name: RegisterObserver006 * @tc.desc: register observer success and update callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver006, TestSize.Level1) @@ -370,7 +370,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver006, TestSiz * @tc.name: RegisterObserver007 * @tc.desc: register observer success and delete callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver007, TestSize.Level1) @@ -410,7 +410,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver007, TestSiz * @tc.name: RegisterObserver008 * @tc.desc: register observer success and delete callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver008, TestSize.Level1) @@ -445,7 +445,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver008, TestSiz * @tc.name: RegisterObserver009 * @tc.desc: register observer success and deletebatch callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver009, TestSize.Level1) @@ -490,7 +490,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver009, TestSiz * @tc.name: RegisterObserver010 * @tc.desc: register observer success and delete callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver010, TestSize.Level1) @@ -539,7 +539,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver010, TestSiz * @tc.name: RegisterObserver011 * @tc.desc: register observer success and DeleteBatch callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver011, TestSize.Level1) @@ -578,7 +578,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver011, TestSiz * @tc.name: RegisterObserver012 * @tc.desc: register observer success and clear callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver012, TestSize.Level1) @@ -623,7 +623,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver012, TestSiz * @tc.name: RegisterObserver013 * @tc.desc: register observer success and clear callback * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver013, TestSize.Level1) @@ -656,7 +656,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver013, TestSiz * @tc.desc: Test the function of modifying a record, adding a record, * deleting a record, and checking the processing result of the callback function. * @tc.type: FUNC - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver014, TestSize.Level1) @@ -781,7 +781,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, RegisterObserver014, TestSiz /** * @tc.name: SnapshotRegisterObserver001 * @tc.desc: register a normal observer for snapshot - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver001, TestSize.Level1) @@ -799,7 +799,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver001, /** * @tc.name: SnapshotRegisterObserver002 * @tc.desc: register a null observer for snapshot register a null observer for snapshot - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver002, TestSize.Level1) @@ -817,7 +817,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver002, /** * @tc.name: SnapshotRegisterObserver003 * @tc.desc: register observer success and put callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver003, TestSize.Level1) @@ -863,7 +863,7 @@ static void CreatEntrysData(size_t size, uint8_t value, vector &entries) /** * @tc.name: SnapshotRegisterObserver004 * @tc.desc: register observer success and putBatch callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver004, TestSize.Level1) @@ -898,7 +898,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver004, /** * @tc.name: SnapshotRegisterObserver005 * @tc.desc: register observer success and putBatch callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver005, TestSize.Level1) @@ -940,7 +940,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver005, /** * @tc.name: SnapshotRegisterObserver006 * @tc.desc: register observer success and update callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver006, TestSize.Level1) @@ -982,7 +982,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver006, /** * @tc.name: SnapshotRegisterObserver007 * @tc.desc: register observer success and Delete callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver007, TestSize.Level1) @@ -1020,7 +1020,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver007, /** * @tc.name: SnapshotRegisterObserver008 * @tc.desc: register observer success and Delete null value callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver008, TestSize.Level1) @@ -1054,7 +1054,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver008, /** * @tc.name: SnapshotRegisterObserver009 * @tc.desc: register observer success and DeleteBatch callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver009, TestSize.Level1) @@ -1097,7 +1097,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver009, /** * @tc.name: SnapshotRegisterObserver010 * @tc.desc: register observer success and DeleteBatch callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver010, TestSize.Level1) @@ -1150,7 +1150,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver010, /** * @tc.name: SnapshotRegisterObserver011 * @tc.desc: register observer success and DeleteBatch callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver011, TestSize.Level1) @@ -1190,7 +1190,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver011, /** * @tc.name: SnapshotRegisterObserver012 * @tc.desc: register observer success and Clear callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver012, TestSize.Level1) @@ -1232,7 +1232,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver012, /** * @tc.name: SnapshotRegisterObserver013 * @tc.desc: register observer success and Clear callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver013, TestSize.Level1) @@ -1263,7 +1263,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver013, /** * @tc.name: SnapshotRegisterObserver014 * @tc.desc: register observer success and operate callback - * @tc.require: AR000BVDFQ AR000CQDVJ + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver014, TestSize.Level1) @@ -1388,7 +1388,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotRegisterObserver014, /** * @tc.name: UnRegisterObserver001 * @tc.desc: Unregister a normal observer - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, UnRegisterObserver001, TestSize.Level1) @@ -1409,7 +1409,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, UnRegisterObserver001, TestS /** * @tc.name: UnRegisterObserver002 * @tc.desc: Unregister a null observer - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, UnRegisterObserver002, TestSize.Level1) @@ -1424,7 +1424,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, UnRegisterObserver002, TestS /** * @tc.name: UnRegisterObserver003 * @tc.desc: Unregister a unregister observer - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, UnRegisterObserver003, TestSize.Level1) @@ -1439,7 +1439,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, UnRegisterObserver003, TestS /** * @tc.name: UnRegisterObserver004 * @tc.desc: Unregister a and check callback - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, UnRegisterObserver004, TestSize.Level1) @@ -1588,7 +1588,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, UnRegisterObserver004, TestS /** * @tc.name: SnapshotUnRegisterObserver001 * @tc.desc: Unregister a snapshot observer - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotUnRegisterObserver001, TestSize.Level1) @@ -1606,7 +1606,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotUnRegisterObserver00 /** * @tc.name: SnapshotUnRegisterObserver002 * @tc.desc: Unregister a null snapshot observer - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotUnRegisterObserver002, TestSize.Level1) @@ -1623,7 +1623,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotUnRegisterObserver00 /** * @tc.name: SnapshotUnRegisterObserver003 * @tc.desc: Unregister a unregister snapshot observer - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotUnRegisterObserver003, TestSize.Level1) @@ -1682,7 +1682,7 @@ static void SnapshotUnRegisterObserver004Inner() /** * @tc.name: SnapshotUnRegisterObserver004 * @tc.desc: Check a unregister snapshot observer - * @tc.require: AR000BVDFP AR000CQDVI + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, SnapshotUnRegisterObserver004, TestSize.Level1) @@ -1817,7 +1817,7 @@ static void CheckObserverCallback(const Entry &entryB) * @tc.desc: Test whether the data change notification can obtain these changes * when the database is added, deleted, or modified. * @tc.type: FUNC - * @tc.require: AR000BVDFR AR000CQDVK + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, GetObserverData001, TestSize.Level1) @@ -1848,7 +1848,7 @@ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, GetObserverData001, TestSize * when the value of observer is not empty * when a snapshot is obtained and the database data changes. * @tc.type: FUNC - * @tc.require: AR000C06UT AR000CQDTG + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesRegisterSyncDBTest, GetSnapshotObserverData001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp index c72e1205..c89e04db 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp @@ -243,7 +243,7 @@ void NoramlCreateDistributedTableTest(TableSyncType tableSyncType) * @tc.name: RelationalStoreTest001 * @tc.desc: Test open store and create distributed db with DEVICE_COOPERATION type * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest001, TestSize.Level1) @@ -255,7 +255,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest001, TestSize * @tc.name: RelationalStoreTest001 * @tc.desc: Test open store and create distributed db with CLOUD_COOPERATION type * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest001_1, TestSize.Level1) @@ -267,7 +267,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest001_1, TestSi * @tc.name: RelationalStoreTest002 * @tc.desc: Test open store with invalid path or store ID * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest002, TestSize.Level1) @@ -319,7 +319,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest002, TestSize * @tc.name: RelationalStoreTest003 * @tc.desc: Test open store with journal_mode is not WAL * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest003, TestSize.Level1) @@ -392,7 +392,7 @@ void CreateDistributedTableOverLimitTest(TableSyncType tableSyncTpe) * @tc.name: RelationalStoreTest004 * @tc.desc: Test create distributed table with over limit for DEVICE_COOPERATION type * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest004, TestSize.Level1) @@ -436,7 +436,8 @@ void CreateDistributedTableInvalidArgsTest(TableSyncType tableSyncType) * @tc.steps:step3. Create distributed table with invalid table name * @tc.expected: step3. Create distributed table failed. */ - EXPECT_NE(delegate->CreateDistributedTable(DBConstant::SYSTEM_TABLE_PREFIX + "_tmp", tableSyncType), OK); + EXPECT_NE(delegate->CreateDistributedTable(std::string(DBConstant::SYSTEM_TABLE_PREFIX) + "_tmp", tableSyncType), + OK); EXPECT_EQ(delegate->CreateDistributedTable("Handle-J@^.", tableSyncType), INVALID_ARGS); EXPECT_EQ(delegate->CreateDistributedTable("sync_data", @@ -469,7 +470,7 @@ void CreateDistributedTableInvalidArgsTest(TableSyncType tableSyncType) * @tc.name: RelationalStoreTest005 * @tc.desc: Test create distributed table with invalid table name or invalid table sync type * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest005, TestSize.Level1) @@ -540,7 +541,7 @@ void CreateDistributedTableNonPrimaryKeyTest(TableSyncType tableSyncType) * @tc.name: RelationalStoreTest006 * @tc.desc: Test create distributed table with non primary key schema * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest006, TestSize.Level1) @@ -582,7 +583,7 @@ void CreateDistributedTableInvalidFieldTest(TableSyncType tableSyncType) * @tc.name: RelationalStoreTest007 * @tc.desc: Test create distributed table with table has invalid field name * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest007, TestSize.Level1) @@ -624,7 +625,7 @@ void CreateDistributedTableCompositePKTest(TableSyncType tableSyncType, int expe * @tc.name: RelationalStoreTest008 * @tc.desc: Test create distributed table with table has composite primary keys for DEVICE_COOPERATION * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest008, TestSize.Level1) @@ -667,7 +668,7 @@ void CreateDistributedTableWithHistoryDataTest(TableSyncType tableSyncType) * @tc.name: RelationalStoreTest009 * @tc.desc: Test create distributed table with table has history data for DEVICE_COOPERATION * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest009, TestSize.Level1) @@ -742,11 +743,84 @@ void TableModifyTest(const std::string &modifySql, TableSyncType tableSyncType, EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); } +/** + * @tc.name: RelationalStoreTest010 + * @tc.desc: Test opening libraries with the same name in different paths. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest010, TestSize.Level0) +{ + /** + * @tc.steps:step1. Prepare db file + * @tc.expected: step1. Return OK. + */ + std::string dbPath1 = g_dbDir + "path1/"; + ASSERT_EQ(OS::MakeDBDirectory(dbPath1), E_OK); + sqlite3 *db1 = RelationalTestUtils::CreateDataBase(dbPath1 + STORE_ID + DB_SUFFIX); + ASSERT_NE(db1, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db1, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db1, NORMAL_CREATE_NO_UNIQUE), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db1), SQLITE_OK); + std::string dbPath2 = g_dbDir + "path2/"; + ASSERT_EQ(OS::MakeDBDirectory(dbPath2), E_OK); + sqlite3 *db2 = RelationalTestUtils::CreateDataBase(dbPath2 + STORE_ID + DB_SUFFIX); + ASSERT_NE(db2, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db2, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db2, NORMAL_CREATE_NO_UNIQUE), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db2), SQLITE_OK); + /** + * @tc.steps:step2. open db + * @tc.expected: step2. Return OK. + */ + RelationalStoreDelegate *delegate1 = nullptr; + DBStatus status1 = g_mgr.OpenStore(dbPath1 + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate1); + EXPECT_EQ(status1, OK); + ASSERT_NE(delegate1, nullptr); + RelationalStoreDelegate *delegate2 = nullptr; + DBStatus status2 = g_mgr.OpenStore(dbPath2 + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate2); + EXPECT_EQ(status2, OK); + ASSERT_NE(delegate2, nullptr); + /** + * @tc.steps:step3. create table + * @tc.expected: step3. Return OK. + */ + SqlCondition sqlCondition1; + std::vector records1; + sqlCondition1.sql = "create table if not exists table1(id int);"; + EXPECT_EQ(delegate1->ExecuteSql(sqlCondition1, records1), OK); + SqlCondition sqlCondition2; + std::vector records2; + sqlCondition2.sql = "create table if not exists table2(id int);"; + EXPECT_EQ(delegate2->ExecuteSql(sqlCondition2, records2), OK); + /** + * @tc.steps:step4. check table + * @tc.expected: step4. Return OK. + */ + db1 = RelationalTestUtils::CreateDataBase(dbPath1 + STORE_ID + DB_SUFFIX); + std::string sql1 = "select count(*) from sqlite_master where type = 'table' and name = 'table1'"; + int tableCount1 = 0; + EXPECT_EQ(SQLiteUtils::GetCountBySql(db1, sql1, tableCount1), E_OK); + EXPECT_EQ(tableCount1, 1); + EXPECT_EQ(sqlite3_close_v2(db1), SQLITE_OK); + db2 = RelationalTestUtils::CreateDataBase(dbPath2 + STORE_ID + DB_SUFFIX); + std::string sql2 = "select count(*) from sqlite_master where type = 'table' and name = 'table2'"; + int tableCount2 = 0; + EXPECT_EQ(SQLiteUtils::GetCountBySql(db2, sql2, tableCount2), E_OK); + EXPECT_EQ(tableCount2, 1); + EXPECT_EQ(sqlite3_close_v2(db2), SQLITE_OK); + status1 = g_mgr.CloseStore(delegate1); + EXPECT_EQ(status1, OK); + status2 = g_mgr.CloseStore(delegate2); + EXPECT_EQ(status2, OK); +} + /** * @tc.name: RelationalTableModifyTest001 * @tc.desc: Test modify distributed table with compatible upgrade * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest001, TestSize.Level1) @@ -759,7 +833,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest001, Te * @tc.name: RelationalTableModifyTest002 * @tc.desc: Test modify distributed table with incompatible upgrade * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest002, TestSize.Level1) @@ -772,7 +846,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest002, Te * @tc.name: RelationalTableModifyTest003 * @tc.desc: Test modify distributed table with incompatible upgrade * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest003, TestSize.Level1) @@ -885,7 +959,7 @@ void UpgradeDistributedTableTest(TableSyncType tableSyncType) * @tc.name: RelationalTableModifyTest004 * @tc.desc: Test upgrade distributed table with device table exists * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest004, TestSize.Level1) @@ -909,7 +983,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest004_1, * @tc.name: RelationalTableModifyTest005 * @tc.desc: Test modify distributed table with compatible upgrade * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest005, TestSize.Level1) @@ -1106,7 +1180,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, TableConstraintsTest002, TestSiz * @tc.name: RelationalRemoveDeviceDataTest001 * @tc.desc: Test remove device data * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest001, TestSize.Level1) @@ -1223,7 +1297,7 @@ void AddErrorTrigger(sqlite3 *db, const std::string &name) * @tc.name: RelationalRemoveDeviceDataTest002 * @tc.desc: Test remove device data and syn * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest002, TestSize.Level1) @@ -1344,7 +1418,7 @@ void TestRemoveDeviceDataWithCallback(bool removeAll) * @tc.name: RelationalRemoveDeviceDataTest003 * @tc.desc: Test remove all device data and sync again * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest003, TestSize.Level1) @@ -1356,7 +1430,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest00 * @tc.name: RelationalRemoveDeviceDataTest004 * @tc.desc: Test remove one device data and sync again * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest004, TestSize.Level1) @@ -1368,7 +1442,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest00 * @tc.name: RelationalRemoveDeviceDataTest005 * @tc.desc: Test remove device data with invalid param * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest005, TestSize.Level1) @@ -1417,7 +1491,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest00 * @tc.name: RelationalRemoveDeviceDataTest006 * @tc.desc: Test remove device data with busy * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest006, TestSize.Level1) @@ -1464,7 +1538,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest00 * @tc.name: RelationalOpenStorePathCheckTest001 * @tc.desc: Test open store with same label but different path. * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalOpenStorePathCheckTest001, TestSize.Level1) @@ -1493,14 +1567,14 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalOpenStorePathCheckTest RelationalStoreDelegate *delegate2 = nullptr; status = g_mgr.OpenStore(dir2 + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate2); - EXPECT_EQ(status, INVALID_ARGS); - ASSERT_EQ(delegate2, nullptr); + EXPECT_EQ(status, OK); + ASSERT_NE(delegate2, nullptr); status = g_mgr.CloseStore(delegate1); EXPECT_EQ(status, OK); status = g_mgr.CloseStore(delegate2); - EXPECT_EQ(status, INVALID_ARGS); + EXPECT_EQ(status, OK); } HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalOpenStorePressureTest001, TestSize.Level1) @@ -1628,7 +1702,7 @@ namespace { * @tc.require: * @tc.author: lianhuix */ -HWTEST_F(DistributedDBInterfacesRelationalTest, SqliteKeyWordTest001, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTest, SqliteKeyWordTest001, TestSize.Level1) { sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); ASSERT_NE(db, nullptr); @@ -1682,7 +1756,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, SqliteKeyWordTest001, TestSize.L * @tc.name: GetDistributedTableName001 * @tc.desc: Test get distributed table name * @tc.type: FUNC - * @tc.require: AR000GK58F + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBInterfacesRelationalTest, GetDistributedTableName001, TestSize.Level1) @@ -1753,7 +1827,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest001, T * @tc.require: * @tc.author: zhangshjie */ -HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest002, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest002, TestSize.Level1) { /** * @tc.steps:step1. Prepare db file @@ -1834,7 +1908,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest002, T * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest003, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest003, TestSize.Level1) { /** * @tc.steps:step1. Prepare db file @@ -2058,4 +2132,60 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, StoreId001, TestSize.Level0) EXPECT_NE(RelationalStoreManager::GetRelationalStoreIdentifier(USER_ID, USER_ID, APP_ID, STORE_ID_1, true), ""); EXPECT_NE(RelationalStoreManager::GetRelationalStoreIdentifier(USER_ID, USER_ID, APP_ID, storeIdWithDot, true), ""); } + +/** + * @tc.name: GetDbHandleConcurrentlyTest001 + * @tc.desc: Test get db handle concurrently + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, GetDbHandleConcurrentlyTest001, TestSize.Level1) +{ + /** + * @tc.steps:step1. Prepare db file + * @tc.expected: step1. Return OK. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + ASSERT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_NO_UNIQUE), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + /** + * @tc.steps:step2. open relational store + * @tc.expected: step2. Return OK. + */ + RelationalStoreDelegate *delegate = nullptr; + DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate); + EXPECT_EQ(status, OK); + ASSERT_NE(delegate, nullptr); + /** + * @tc.steps:step3. open relational store + * @tc.expected: step3. Return OK. + */ + std::string tableName = "sync_data"; + int executeTime = 100; + std::thread thread1([&, this]() { + for (int i = 0; i < executeTime; i++) { + DistributedDB::SqlCondition sqlCondition; + std::vector records = {}; + sqlCondition.sql = "BEGIN IMMEDIATE TRANSACTION;"; + EXPECT_EQ(delegate->ExecuteSql(sqlCondition, records), E_OK); + sqlCondition.sql = "DROP TABLE IF EXISTS " + DBCommon::GetLogTableName(tableName); + EXPECT_EQ(delegate->ExecuteSql(sqlCondition, records), E_OK); + sqlCondition.sql = "COMMIT;"; + EXPECT_EQ(delegate->ExecuteSql(sqlCondition, records), E_OK); + } + }); + std::thread thread2([&, this]() { + for (int i = 0; i < executeTime; i++) { + status = delegate->CreateDistributedTable(tableName, DistributedDB::CLOUD_COOPERATION); + EXPECT_EQ(status, OK); + } + }); + thread1.join(); + thread2.join(); + status = g_mgr.CloseStore(delegate); + EXPECT_EQ(status, OK); +} } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp index 14765c0c..8e865b54 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp @@ -46,6 +46,7 @@ namespace { const string TABLE_NAME3 = "worKer3"; DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); RelationalStoreDelegate *g_delegate = nullptr; + VirtualCommunicatorAggregator *g_communicatorAggregator = nullptr; sqlite3 *g_db = nullptr; const int HALF = 2; @@ -149,7 +150,7 @@ namespace { while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { std::string extendVal; EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 0, extendVal), E_OK); - ASSERT_NE(num, 0ul); + ASSERT_NE(num, 0uL); EXPECT_EQ(extendVal, "Local" + std::to_string(index % num)); std::string cursorVal; EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, cursorVal), E_OK); @@ -222,8 +223,8 @@ namespace { * @tc.steps:step3. check tracker schema * @tc.expected: step3. Return OK. */ - const Key schemaKey(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.begin(), - DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.end()); + const Key schemaKey(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY, + DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY + strlen(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY)); sql = "SELECT value FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata WHERE key=?;"; sqlite3_stmt *stmt = nullptr; EXPECT_EQ(SQLiteUtils::GetStatement(g_db, sql, stmt), E_OK); @@ -268,6 +269,9 @@ namespace { void DistributedDBInterfacesRelationalTrackerTableTest::SetUp(void) { + g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(g_communicatorAggregator != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator); if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error."); } @@ -277,6 +281,7 @@ namespace { void DistributedDBInterfacesRelationalTrackerTableTest::TearDown(void) { DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); } void SetTrackerTableTest(const TrackerSchema &schema, DBStatus expect) @@ -316,7 +321,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest001, * @tc.steps:step3. table name is illegal table name * @tc.expected: step3. Return INVALID_ARGS. */ - schema.tableName = DBConstant::SYSTEM_TABLE_PREFIX + "_1"; + schema.tableName = std::string(DBConstant::SYSTEM_TABLE_PREFIX) + "_1"; EXPECT_EQ(g_delegate->SetTrackerTable(schema), INVALID_ARGS); CloseStore(); } @@ -346,12 +351,13 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest002, SetTrackerTableTest(schema, SCHEMA_MISMATCH); /** - * @tc.steps:step1. param valid but extend name is empty - * @tc.expected: step1. Return OK. + * @tc.steps:step3. param valid but extend name is empty + * @tc.expected: step3. Return OK. */ schema.trackerColNames = LOCAL_TABLE_TRACKER_NAME_SET2; schema.extendColNames = {}; SetTrackerTableTest(schema, OK); + SetTrackerTableTest(schema, OK); } /** @@ -361,7 +367,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest002, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest003, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest003, TestSize.Level1) { /** * @tc.steps:step1. tracker col name is no exist @@ -403,7 +409,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest003, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest005, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest005, TestSize.Level1) { /** * @tc.steps:step1. SetTrackerTable twice in same delegate @@ -454,7 +460,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest005, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest006, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest006, TestSize.Level1) { /** * @tc.steps:step1. SetTrackerTable @@ -698,7 +704,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest010, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest011, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest011, TestSize.Level1) { /** * @tc.steps:step1. SetTrackerTable on table2 @@ -756,7 +762,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest011, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest012, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest012, TestSize.Level1) { /** * @tc.steps:step1. SetTrackerTable on table2 @@ -851,7 +857,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest013, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest014, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest014, TestSize.Level1) { /** * @tc.steps:step1. CreateDistributedTable on table2 @@ -894,7 +900,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest014, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest015, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest015, TestSize.Level1) { /** * @tc.steps:step1. CreateDistributedTable on table2 @@ -944,7 +950,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest015, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest016, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest016, TestSize.Level1) { /** * @tc.steps:step1. SetTrackerTable on table2 @@ -979,7 +985,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest016, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest017, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest017, TestSize.Level1) { /** * @tc.steps:step1. SetTrackerTable on table2 @@ -1038,7 +1044,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest017, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest018, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest018, TestSize.Level1) { /** * @tc.steps:step1. Create DEVICE_COOPERATION DistributedTable @@ -1192,7 +1198,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest021, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest022, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest022, TestSize.Level1) { CheckDropTableAndReopenDb(true); } @@ -1819,6 +1825,14 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, ExecuteSql010, TestS condition.readOnly = true; EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); EXPECT_EQ(records.size(), num); + + /** + * @tc.steps:step3. ExecuteSql again + * @tc.expected: step3. Return OK. + */ + records.clear(); + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + EXPECT_EQ(records.size(), num); CloseStore(); } @@ -1878,7 +1892,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, ExecuteSql011, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest026, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest026, TestSize.Level1) { /** * @tc.steps:step1. SetTrackerTable on table2 @@ -1916,7 +1930,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest026, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest027, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest027, TestSize.Level1) { /** * @tc.steps:step1. create distributed table on table2 with case different @@ -1971,7 +1985,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest027, * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest028, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest028, TestSize.Level1) { /** * @tc.steps:step1. trackerColNames is empty @@ -2312,7 +2326,7 @@ void SetLowVersionSchema(sqlite3 *db, const std::string &extendColName) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest036, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest036, TestSize.Level1) { /** * @tc.steps:step1. Init db and init extend field to old version data @@ -2732,6 +2746,96 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest045, CloseStore(); } +/** + * @tc.name: TrackerTableTest046 + * @tc.desc: Test clear log of mismatched data + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest046, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable on table2 + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + int num = 10; + BatchInsertTableName2Data(num); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), WITH_INVENTORY_DATA); + + /** + * @tc.steps:step2. Recreate table2 by rename + * @tc.expected: step2. Return OK. + */ + std::string sql = "ALTER TABLE " + TABLE_NAME2 + " RENAME TO xxx"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(g_db, sql), E_OK); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(g_db, CREATE_LOCAL_PK_TABLE_SQL), E_OK); + sql = "INSERT INTO " + TABLE_NAME2 + " SELECT id,name,height,photo,asserts,age FROM xxx"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(g_db, sql), E_OK); + sql = "DROP TABLE xxx"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(g_db, sql), E_OK); + sql = "DELETE FROM " + TABLE_NAME2 + " WHERE id in ('7', '9')"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(g_db, sql), E_OK); + + /** + * @tc.steps:step3. Set tracker and check log count + * @tc.expected: step3. Return OK. + */ + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + sql = "select count(*) from " + DBCommon::GetLogTableName(TABLE_NAME2); + num = 8; + EXPECT_EQ(sqlite3_exec(g_db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(num), nullptr), SQLITE_OK); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest047 + * @tc.desc: Test recover log for extend_field is NULL + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest047, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable on table2 + * @tc.expected: step1. Return WITH_INVENTORY_DATA. + */ + CreateMultiTable(); + OpenStore(); + int num = 10; + BatchInsertTableName2Data(num); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), WITH_INVENTORY_DATA); + + /** + * @tc.steps:step2. Construct a log with invalid extend_field + * @tc.expected: step2. Return OK. + */ + std::string sql = "UPDATE " + DBCommon::GetLogTableName(TABLE_NAME2) + " SET extend_field = NULL" + " WHERE data_key=1"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(g_db, sql), E_OK); + std::string querySql = "select count(*) from " + DBCommon::GetLogTableName(TABLE_NAME2) + + " WHERE json_type(extend_field) IS 'object'"; + num = 9; + EXPECT_EQ(sqlite3_exec(g_db, querySql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(num), nullptr), SQLITE_OK); + + /** + * @tc.steps:step3. Set tracker and check log count + * @tc.expected: step3. Return OK. + */ + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + num = 10; + EXPECT_EQ(sqlite3_exec(g_db, querySql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(num), nullptr), SQLITE_OK); + CloseStore(); +} + /** * @tc.name: SchemaStrTest001 * @tc.desc: Test open reOpen stroe when schemaStr is empty @@ -2739,7 +2843,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest045, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, SchemaStrTest001, TestSize.Level0) +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, SchemaStrTest001, TestSize.Level1) { /** * @tc.steps:step1. set empty for relational schema str, reopen store diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_resultset_performance.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_resultset_performance.cpp index cf01fce8..512c7204 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_resultset_performance.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_resultset_performance.cpp @@ -112,7 +112,7 @@ void DistributedDBInterfacesNBResultsetPerfTest::TearDown(void) * @tc.name: ResultSetPerfTest001 * @tc.desc: Test the NbDelegate for result set function. * @tc.type: FUNC - * @tc.require: AR000D08KT + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBInterfacesNBResultsetPerfTest, ResultSetPerfTest001, TestSize.Level4) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_schema_database_upgrade_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_schema_database_upgrade_test.cpp index 9587a2c4..85ecb941 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_schema_database_upgrade_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_schema_database_upgrade_test.cpp @@ -80,18 +80,20 @@ namespace { std::string SchemaSwitchMode(const std::string &oriSchemaStr) { std::string resStr = oriSchemaStr; - auto iterStrict = std::search(resStr.begin(), resStr.end(), SchemaConstant::KEYWORD_MODE_STRICT.begin(), - SchemaConstant::KEYWORD_MODE_STRICT.end()); - auto iterCompatible = std::search(resStr.begin(), resStr.end(), SchemaConstant::KEYWORD_MODE_COMPATIBLE.begin(), - SchemaConstant::KEYWORD_MODE_COMPATIBLE.end()); + auto iterStrict = std::search(resStr.begin(), resStr.end(), SchemaConstant::KEYWORD_MODE_STRICT, + SchemaConstant::KEYWORD_MODE_STRICT + strlen(SchemaConstant::KEYWORD_MODE_STRICT)); + auto iterCompatible = std::search(resStr.begin(), resStr.end(), SchemaConstant::KEYWORD_MODE_COMPATIBLE, + SchemaConstant::KEYWORD_MODE_COMPATIBLE + strlen(SchemaConstant::KEYWORD_MODE_COMPATIBLE)); if (iterStrict != resStr.end()) { - resStr.replace(iterStrict, iterStrict + SchemaConstant::KEYWORD_MODE_STRICT.size(), - SchemaConstant::KEYWORD_MODE_COMPATIBLE.begin(), SchemaConstant::KEYWORD_MODE_COMPATIBLE.end()); + resStr.replace(iterStrict, iterStrict + strlen(SchemaConstant::KEYWORD_MODE_STRICT), + SchemaConstant::KEYWORD_MODE_COMPATIBLE, + SchemaConstant::KEYWORD_MODE_COMPATIBLE + strlen(SchemaConstant::KEYWORD_MODE_COMPATIBLE)); return resStr; } if (iterCompatible != resStr.end()) { - resStr.replace(iterCompatible, iterCompatible + SchemaConstant::KEYWORD_MODE_COMPATIBLE.size(), - SchemaConstant::KEYWORD_MODE_STRICT.begin(), SchemaConstant::KEYWORD_MODE_STRICT.end()); + resStr.replace(iterCompatible, iterCompatible + strlen(SchemaConstant::KEYWORD_MODE_COMPATIBLE), + SchemaConstant::KEYWORD_MODE_STRICT, + SchemaConstant::KEYWORD_MODE_STRICT + strlen(SchemaConstant::KEYWORD_MODE_STRICT)); return resStr; } return oriSchemaStr; @@ -182,7 +184,7 @@ void DistributedDBInterfacesSchemaDatabaseUpgradeTest::TearDown(void) * @tc.name: UpgradeFromKv001 * @tc.desc: Schema database upgrade from kv database, exist value match compatible schema(mismatch strict schema) * @tc.type: FUNC - * @tc.require: AR000F3OPD + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBInterfacesSchemaDatabaseUpgradeTest, UpgradeFromKv001, TestSize.Level1) @@ -241,7 +243,7 @@ HWTEST_F(DistributedDBInterfacesSchemaDatabaseUpgradeTest, UpgradeFromKv001, Tes * @tc.name: UpgradeFromKv002 * @tc.desc: Schema database upgrade from kv database, exist value mismatch compatible schema * @tc.type: FUNC - * @tc.require: AR000F3OPD + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBInterfacesSchemaDatabaseUpgradeTest, UpgradeFromKv002, TestSize.Level1) @@ -326,7 +328,7 @@ void TestUpgradeFromSchema(const std::string &storeId, const std::vector &fileNames) * @tc.name: GetKvStoreDiskSize001 * @tc.desc: ROM space occupied by applications in the distributed database can be calculated. * @tc.type: FUNC - * @tc.require: AR000CQDTD + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize001, TestSize.Level1) @@ -221,7 +221,7 @@ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize001, Test * @tc.name: GetKvStoreDiskSize002 * @tc.desc: Obtain the size of the opened database. * @tc.type: FUNC - * @tc.require: AR000CQDTD + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize002, TestSize.Level2) @@ -321,7 +321,7 @@ static void DeleteFile(const std::string &fileUrl) * @tc.name: GetKvStoreDiskSize003 * @tc.desc: Verification exception parameters * @tc.type: FUNC - * @tc.require: AR000CQDTD + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize003, TestSize.Level1) @@ -395,7 +395,7 @@ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize003, Test * @tc.name: GetKvStoreDiskSize004 * @tc.desc: Calculate memory database size * @tc.type: FUNC - * @tc.require: AR000CQDTD + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize004, TestSize.Level1) @@ -453,7 +453,7 @@ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, GetKvStoreDiskSize004, Test * @tc.name: DeleteDbByStoreId001 * @tc.desc: Delete database by storeId. * @tc.type: FUNC - * @tc.require: AR000CQDTD + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, DeleteDbByStoreId001, TestSize.Level1) @@ -526,7 +526,7 @@ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, DeleteDbByStoreId001, TestS * @tc.name: DeleteDbByStoreId002 * @tc.desc: Delete database by not exist storeId. * @tc.type: FUNC - * @tc.require: AR000CQDTD + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBInterfacesSpaceManagementTest, DeleteDbByStoreId002, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_optimization_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_optimization_test.cpp index 3f8e6078..8a07f889 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_optimization_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_optimization_test.cpp @@ -88,7 +88,7 @@ void DistributedDBInterfacesTransactionOptimizationTest::TearDown(void) * @tc.name: BatchOperationsOfSyncAndLocal001 * @tc.desc: Verify the batch put and query functions of the sync and local data in the same transaction. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, SyncAndLocalBatchOperations001, TestSize.Level1) @@ -166,7 +166,7 @@ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, SyncAndLocalBatchOp * @tc.name: SyncAndLocalSingleOperations001 * @tc.desc: Verify the single put and query functions of the sync and local data in the same transaction. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, SyncAndLocalSingleOperations001, TestSize.Level1) @@ -233,7 +233,7 @@ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, SyncAndLocalSingleO * @tc.name: DeleteInTransaction001 * @tc.desc: Verify that the sync and local functions can be deleted in the same transaction. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, DeleteInTransaction001, TestSize.Level1) @@ -296,7 +296,7 @@ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, DeleteInTransaction * @tc.name: DeleteBatchInTransaction001 * @tc.desc: Local data does not check readOnly. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, DeleteBatchInTransaction001, TestSize.Level1) @@ -370,7 +370,7 @@ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, DeleteBatchInTransa * @tc.name: SyncAndLocalObserver001 * @tc.desc: Verify the observer functions of the sync and local data in the same transaction. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, SyncAndLocalObserver001, TestSize.Level1) @@ -458,7 +458,7 @@ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, SyncAndLocalObserve * @tc.name: OnlyDeleteInTransaction001 * @tc.desc: Verify the observer functions of delete operation in the transaction. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, OnlyDeleteInTransaction001, TestSize.Level1) @@ -553,7 +553,7 @@ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, OnlyDeleteInTransac * @tc.name: SyncAndLocalObserver002 * @tc.desc: Verify the observer functions of the sync and local data in the same transaction. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, SyncAndLocalObserver002, TestSize.Level1) @@ -638,7 +638,7 @@ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, SyncAndLocalObserve * @tc.name: PutRollback001 * @tc.desc: Verify that a transaction can be rolled back after data is put. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, PutRollback001, TestSize.Level1) @@ -721,7 +721,7 @@ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, PutRollback001, Tes * @tc.name: PutBatchRollback001 * @tc.desc: Verify that a transaction can be rolled back after data is put. * @tc.type: FUNC - * @tc.require: AR000EPAS8 + * @tc.require: * @tc.author: changguicai */ HWTEST_F(DistributedDBInterfacesTransactionOptimizationTest, PutBatchRollback001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_syncdb_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_syncdb_test.cpp index 87cd87e3..5fae1dc8 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_syncdb_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_syncdb_test.cpp @@ -100,7 +100,7 @@ void DistributedDBInterfacesTransactionSyncDBTest::TearDown(void) * @tc.name: StartTransaction001 * @tc.desc: Test that can't call StartTransaction interface repeatedly. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, StartTransaction001, TestSize.Level1) @@ -120,7 +120,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, StartTransaction001, Test * @tc.name: StartTransaction002 * @tc.desc: Test that call StartTransaction and commit interface normally. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, StartTransaction002, TestSize.Level1) @@ -140,7 +140,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, StartTransaction002, Test * @tc.name: StartTransaction003 * @tc.desc: Test that call StartTransaction and rolback interface normally. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, StartTransaction003, TestSize.Level1) @@ -160,7 +160,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, StartTransaction003, Test * @tc.name: StartTransaction004 * @tc.desc: Test that call StartTransaction and rolback interface normally. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, StartTransaction004, TestSize.Level1) @@ -193,7 +193,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, StartTransaction004, Test * @tc.name: Commit001 * @tc.desc: Test that can't commit Transaction before it start. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit001, TestSize.Level1) @@ -209,7 +209,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit001, TestSize.Level * @tc.name: Commit002 * @tc.desc: Test that can't commit Transaction repeatedly even if it start normally. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit002, TestSize.Level1) @@ -233,7 +233,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit002, TestSize.Level * @tc.name: Commit003 * @tc.desc: Test that can commit Transaction after put record. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit003, TestSize.Level1) @@ -261,7 +261,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit003, TestSize.Level * @tc.name: Commit004 * @tc.desc: Test that can commit Transaction after update record. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit004, TestSize.Level1) @@ -289,7 +289,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit004, TestSize.Level * @tc.name: Commit005 * @tc.desc: Test that can commit Transaction after delete record. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit005, TestSize.Level1) @@ -317,7 +317,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit005, TestSize.Level * @tc.name: Commit006 * @tc.desc: Test that can commit Transaction after clear all the records. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit006, TestSize.Level1) @@ -345,7 +345,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit006, TestSize.Level * @tc.name: Commit007 * @tc.desc: Test that can commit Transaction after delete and update db. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit007, TestSize.Level1) @@ -377,7 +377,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit007, TestSize.Level * @tc.name: Commit008 * @tc.desc: Test that can commit Transaction after clear and new add records. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit008, TestSize.Level1) @@ -410,7 +410,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, Commit008, TestSize.Level * @tc.desc: Test if new commit records and logs generated * when a transaction rollback-ed * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack001, TestSize.Level1) @@ -426,7 +426,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack001, TestSize.Lev * @tc.name: RollBack002 * @tc.desc: rollback a transaction two times * @tc.type: FUNC -* @tc.require: AR000BVRNM AR000CQDTQ +* @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack002, TestSize.Level1) @@ -450,7 +450,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack002, TestSize.Lev * @tc.name: RollBack003 * @tc.desc: insert a data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack003, TestSize.Level1) @@ -478,7 +478,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack003, TestSize.Lev * @tc.name: RollBack004 * @tc.desc: update a data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack004, TestSize.Level1) @@ -510,7 +510,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack004, TestSize.Lev * @tc.name: RollBack005 * @tc.desc: delete an exist data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack005, TestSize.Level1) @@ -542,7 +542,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack005, TestSize.Lev * @tc.name: RollBack006 * @tc.desc: clear db and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack006, TestSize.Level1) @@ -574,7 +574,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack006, TestSize.Lev * @tc.name: RollBack007 * @tc.desc: delete a exist data and update a data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack007, TestSize.Level1) @@ -610,7 +610,7 @@ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack007, TestSize.Lev * @tc.name: RollBack008 * @tc.desc: clear db and insert a data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionSyncDBTest, RollBack008, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_test.cpp index 9a2720c7..90eb5a26 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_transaction_test.cpp @@ -100,7 +100,7 @@ void DistributedDBInterfacesTransactionTest::TearDown(void) * @tc.name: StartTransaction001 * @tc.desc: Test that can't call StartTransaction interface repeatedly. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction001, TestSize.Level1) @@ -120,7 +120,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction001, TestSize.L * @tc.name: StartTransaction002 * @tc.desc: Test that call StartTransaction and commit interface normally. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction002, TestSize.Level1) @@ -140,7 +140,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction002, TestSize.L * @tc.name: StartTransaction003 * @tc.desc: Test that call StartTransaction and rolback interface normally. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction003, TestSize.Level1) @@ -160,7 +160,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction003, TestSize.L * @tc.name: StartTransaction004 * @tc.desc: Test that call StartTransaction and rolback interface normally. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction004, TestSize.Level1) @@ -193,7 +193,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction004, TestSize.L * @tc.name: StartTransaction005 * @tc.desc: Test that can't call StartTransaction interface repeatedly for different kv store. * @tc.type: FUNC - * @tc.require: AR000BVRNK AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction005, TestSize.Level3) @@ -221,7 +221,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, StartTransaction005, TestSize.L * @tc.name: Commit001 * @tc.desc: Test that can't commit Transaction before it start. * @tc.type: FUNC - * @tc.require: AR000CQDTO AR000CQDTP + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit001, TestSize.Level1) @@ -237,7 +237,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit001, TestSize.Level1) * @tc.name: Commit002 * @tc.desc: Test that can't commit Transaction repeatedly even if it start normally. * @tc.type: FUNC - * @tc.require: AR000CQDTO AR000CQDTP + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit002, TestSize.Level1) @@ -261,7 +261,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit002, TestSize.Level1) * @tc.name: Commit003 * @tc.desc: Test that can commit Transaction after put record. * @tc.type: FUNC - * @tc.require: AR000CQDTO AR000CQDTP + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit003, TestSize.Level1) @@ -289,7 +289,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit003, TestSize.Level1) * @tc.name: Commit004 * @tc.desc: Test that can commit Transaction after update record. * @tc.type: FUNC - * @tc.require: AR000CQDTO AR000CQDTP + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit004, TestSize.Level1) @@ -321,7 +321,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit004, TestSize.Level1) * @tc.name: Commit005 * @tc.desc: Test that can commit Transaction after delete record. * @tc.type: FUNC - * @tc.require: AR000CQDTO AR000CQDTP + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit005, TestSize.Level1) @@ -349,7 +349,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit005, TestSize.Level1) * @tc.name: Commit006 * @tc.desc: Test that can commit Transaction after clear all the records. * @tc.type: FUNC - * @tc.require: AR000CQDTO + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit006, TestSize.Level1) @@ -377,7 +377,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit006, TestSize.Level1) * @tc.name: Commit007 * @tc.desc: Test that can commit Transaction after delete and update db. * @tc.type: FUNC - * @tc.require: AR000CQDTO AR000CQDTP + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit007, TestSize.Level1) @@ -409,7 +409,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit007, TestSize.Level1) * @tc.name: Commit008 * @tc.desc: Test that can commit Transaction after clear and new add records. * @tc.type: FUNC - * @tc.require: AR000CQDTO AR000CQDTP + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit008, TestSize.Level1) @@ -442,7 +442,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Commit008, TestSize.Level1) * @tc.desc: Test if new commit records and logs generated * when a transaction rollback-ed * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback001, TestSize.Level1) @@ -458,7 +458,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback001, TestSize.Level1) * @tc.name: RollBack002 * @tc.desc: rollback a transaction two times * @tc.type: FUNC -* @tc.require: AR000BVRNM AR000CQDTQ +* @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback002, TestSize.Level1) @@ -482,7 +482,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback002, TestSize.Level1) * @tc.name: RollBack003 * @tc.desc: insert a data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback003, TestSize.Level1) @@ -510,7 +510,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback003, TestSize.Level1) * @tc.name: RollBack004 * @tc.desc: update a data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback004, TestSize.Level1) @@ -542,7 +542,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback004, TestSize.Level1) * @tc.name: RollBack005 * @tc.desc: delete a exist data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback005, TestSize.Level1) @@ -574,7 +574,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback005, TestSize.Level1) * @tc.name: RollBack006 * @tc.desc: clear db and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback006, TestSize.Level1) @@ -606,7 +606,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback006, TestSize.Level1) * @tc.name: RollBack007 * @tc.desc: delete a exist data and update a data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback007, TestSize.Level1) @@ -642,7 +642,7 @@ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback007, TestSize.Level1) * @tc.name: RollBack008 * @tc.desc: clear db and insert a data and rollback * @tc.type: FUNC - * @tc.require: AR000BVRNM AR000CQDTQ + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBInterfacesTransactionTest, Rollback008, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp index 1b535aa9..2259d5bf 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp @@ -78,7 +78,7 @@ void RuntimeContextProcessSystemApiAdapterImplTest::SetUp(void) * @tc.name: SetSecurityOption001 * @tc.desc: Set SecurityOption. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: */ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SetSecurityOption001, TestSize.Level1) { @@ -104,7 +104,7 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SetSecurityOption001, Te * @tc.name: GetSecurityOption001 * @tc.desc: Get SecurityOption. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: */ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, GetSecurityOption001, TestSize.Level1) { @@ -130,7 +130,7 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, GetSecurityOption001, Te * @tc.name: RegisterLockStatusLister001 * @tc.desc: Register a listener. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: */ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, RegisterLockStatusLister001, TestSize.Level1) { @@ -188,7 +188,7 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, RegisterLockStatusLister * @tc.name: IsAccessControlled001 * @tc.desc: Get Access Lock Status. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: */ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, IsAccessControlled001, TestSize.Level1) { @@ -214,7 +214,7 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, IsAccessControlled001, T * @tc.name: CheckDeviceSecurityAbility001 * @tc.desc: Check device security ability. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: */ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, CheckDeviceSecurityAbility001, TestSize.Level1) { @@ -271,7 +271,7 @@ void CheckDeviceSecurityAbility002() * @tc.name: CheckDeviceSecurityAbility002 * @tc.desc: Check device security ability with getkvstore frequency. * @tc.type: FUNC - * @tc.require: AR000EV1G2 + * @tc.require: */ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, CheckDeviceSecurityAbility002, TestSize.Level1) { @@ -307,7 +307,7 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SetSystemApiAdapterTest0 * @tc.type: FUNC * @tc.require: */ -HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade001, TestSize.Level0) +HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade001, TestSize.Level1) { /** * @tc.steps: step1. set g_adapter and open with s1 @@ -352,7 +352,7 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade001 * @tc.type: FUNC * @tc.require: */ -HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade002, TestSize.Level0) +HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade002, TestSize.Level1) { /** * @tc.steps: step1. set g_adapter and open with s1 @@ -391,7 +391,7 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade002 * @tc.type: FUNC * @tc.require: */ -HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade003, TestSize.Level0) +HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade003, TestSize.Level1) { /** * @tc.steps: step1. set g_adapter and open with not set diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp index 0c84743a..78129b10 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp @@ -460,7 +460,7 @@ Assets DistributedDBCloudAssetsOperationSyncTest::GenerateAssets(const Asset &te * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation001, TestSize.Level1) { const int actualCount = 10; const int deleteDataCount = 5; @@ -493,7 +493,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation001, T * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation002, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation002, TestSize.Level1) { const int actualCount = 1; InsertUserTableRecord(tableName_, 0, actualCount); @@ -520,7 +520,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation002, T * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation003, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation003, TestSize.Level1) { InsertUserTableRecord(tableName_, 0, 1); // 1 is count int uploadCount = 0; @@ -585,7 +585,7 @@ void DistributedDBCloudAssetsOperationSyncTest::LocalAssetRemoveTest() * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation004, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation004, TestSize.Level1) { LocalAssetRemoveTest(); } @@ -614,7 +614,7 @@ void DistributedDBCloudAssetsOperationSyncTest::UpdateAssetWhenSyncUpload() * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation005, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation005, TestSize.Level1) { /** * @tc.steps:step1. Insert 60 records. @@ -691,7 +691,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation005, T * @tc.require: * @tc.author: lijun */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation006, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation006, TestSize.Level1) { const int actualCount = 5; InsertUserTableRecord(tableName_, 0, actualCount); @@ -719,7 +719,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation006, T * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation007, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation007, TestSize.Level1) { /** * @tc.steps:step1. Insert 5 records and sync. @@ -757,7 +757,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation007, T * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation008, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation008, TestSize.Level1) { /** * @tc.steps:step1. Insert 5 records and sync. @@ -802,7 +802,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation008, T * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation009, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation009, TestSize.Level1) { /** * @tc.steps:step1. Insert 5 records and sync. @@ -914,7 +914,7 @@ void DistributedDBCloudAssetsOperationSyncTest::PrepareForAssetOperation010() * @tc.require: * @tc.author: liufuchenxing */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation010, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation010, TestSize.Level1) { /** * @tc.steps:step1. prepare local and cloud asset data. @@ -988,7 +988,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, TestOpenDatabaseBusy001, Tes * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation011, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation011, TestSize.Level1) { /** * @tc.steps:step1. Insert 5 records and sync. @@ -1048,7 +1048,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation011, T * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation012, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation012, TestSize.Level1) { RuntimeContext::GetInstance()->SetBatchDownloadAssets(true); LocalAssetRemoveTest(); @@ -1087,7 +1087,7 @@ void DistributedDBCloudAssetsOperationSyncTest::UpdateLocalAssetRecord(const std * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation013, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation013, TestSize.Level1) { /** * @tc.steps:step1. Insert local and cloud asset data and sync. @@ -1122,7 +1122,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation013, T * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation014, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation014, TestSize.Level1) { /** * @tc.steps:step1. Insert 5 records and sync. @@ -1158,7 +1158,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation014, T * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord001, TestSize.Level1) { const int actualCount = 1; InsertUserTableRecord(tableName_, 0, actualCount); @@ -1191,7 +1191,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord001, TestSize.Le * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord002, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord002, TestSize.Level1) { const int actualCount = 1; InsertUserTableRecord(tableName_, 0, actualCount); @@ -1214,7 +1214,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord002, TestSize.Le * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord003, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord003, TestSize.Level1) { const int actualCount = 1; InsertUserTableRecord(tableName_, 0, actualCount); @@ -1234,7 +1234,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord003, TestSize.Le * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord004, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord004, TestSize.Level1) { RuntimeContext::GetInstance()->SetBatchDownloadAssets(true); const int actualCount = 10; @@ -1259,7 +1259,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, IgnoreRecord004, TestSize.Le * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertData001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertData001, TestSize.Level1) { // insert id 0 to local const int actualCount = 1; @@ -1286,7 +1286,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertData001, TestSize.Leve * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertData002, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertData002, TestSize.Level1) { /** * @tc.steps:step1. Insert 5 records and sync. @@ -1345,7 +1345,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertData002, TestSize.Leve * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetConflict001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetConflict001, TestSize.Level1) { // cloud and local insert same data const int actualCount = 1; @@ -1416,7 +1416,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertDataInvalid001, TestSi * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertDataInvalid002, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertDataInvalid002, TestSize.Level1) { VBucket record; record["id"] = std::to_string(0); @@ -1474,7 +1474,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertDataInvalid002, TestSi * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, DownloadAssetStatusTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, DownloadAssetStatusTest004, TestSize.Level1) { /** * @tc.steps:step1. cloud assets {0, 1} @@ -1645,7 +1645,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest002, TestSiz * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest003, TestSize.Level1) { /** * @tc.steps:step1. Insert 100 records. @@ -1684,7 +1684,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest003, TestSiz * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest004, TestSize.Level1) { /** * @tc.steps:step1. Insert 100 records and sync to cloud. @@ -1732,7 +1732,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest004, TestSiz * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, BatchNormalDownloadAsset001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, BatchNormalDownloadAsset001, TestSize.Level1) { RuntimeContext::GetInstance()->SetBatchDownloadAssets(true); PrepareDataInCloud(); @@ -1752,7 +1752,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, BatchNormalDownloadAsset001, * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, BatchAbnormalDownloadAsset001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, BatchAbnormalDownloadAsset001, TestSize.Level1) { RuntimeContext::GetInstance()->SetBatchDownloadAssets(true); PrepareDataInCloud(); @@ -1788,7 +1788,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, BatchAbnormalDownloadAsset00 * @tc.require: * @tc.author: lg */ -HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithLogFlag001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithLogFlag001, TestSize.Level1) { /** * @tc.steps:step1. Insert 5 records and sync. diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp index efe57233..9321daee 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp @@ -665,7 +665,7 @@ void DistributedDBCloudCheckSyncTest::CheckDownloadInfo(const Info &actualDownlo * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest001, TestSize.Level1) { // prepare data const int actualCount = 10; @@ -693,7 +693,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest001, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest002, TestSize.Level1) { // prepare data const int actualCount = 1; @@ -719,7 +719,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest002, TestSize.Level0) * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest003, TestSize.Level1) { // prepare data const int actualCount = 1; @@ -748,7 +748,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest003, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest004, TestSize.Level1) { // prepare data const int actualCount = 1; @@ -775,7 +775,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest004, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest005, TestSize.Level1) { /** * @tc.steps:step1. init data and sync @@ -815,7 +815,7 @@ void DistributedDBCloudCheckSyncTest::InitDataAndSync() * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest006, TestSize.Level1) { /** * @tc.steps:step1. init data and sync @@ -890,7 +890,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest006, TestSize.Level0) * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest007, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest007, TestSize.Level1) { /** * @tc.steps:step1. init data and sync @@ -965,7 +965,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest007, TestSize.Level0) * @tc.require: * @tc.author: suyuchen */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest008, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest008, TestSize.Level1) { /** * @tc.steps: step1. insert 35 records to user table @@ -1048,7 +1048,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest008, TestSize.Level0) * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest009, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest009, TestSize.Level1) { /** * @tc.steps: step1. insert 1 record to user table @@ -1102,7 +1102,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest009, TestSize.Level0) * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest010, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest010, TestSize.Level1) { /** * @tc.steps: step1. insert 1 record to user table @@ -1134,7 +1134,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest010, TestSize.Level0) RelationalStoreDelegate::Option option; ASSERT_EQ(mgr_->OpenStore(storePath_, STORE_ID_1, option, delegate_), DBStatus::OK); ASSERT_NE(delegate_, nullptr); - ASSERT_EQ(delegate_->CreateDistributedTable(tableName_, CLOUD_COOPERATION), DBStatus::SCHEMA_MISMATCH); + ASSERT_EQ(delegate_->CreateDistributedTable(tableName_, CLOUD_COOPERATION), DBStatus::OK); ASSERT_EQ(delegate_->SetCloudDB(virtualCloudDb_), DBStatus::OK); ASSERT_EQ(delegate_->SetIAssetLoader(virtualAssetLoader_), DBStatus::OK); DataBaseSchema dataBaseSchema = GetSchema(); @@ -1157,7 +1157,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest010, TestSize.Level0) * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest011, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest011, TestSize.Level1) { /** * @tc.steps: step1. insert 1 record to user table @@ -1208,7 +1208,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest011, TestSize.Level0) * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest012, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest012, TestSize.Level1) { /** * @tc.steps: step1. insert 1 record to user table @@ -1261,6 +1261,66 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest012, TestSize.Level0) CheckCloudTableCount(tableName_, 1); } +/** + * @tc.name: CloudSyncTest013 + * @tc.desc: insert data before re-SetDistributedTable and sync is ok + * @tc.type: FUNC + * @tc.require: + * @tc.author: tankaisheng + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest013, TestSize.Level0) +{ + /** + * @tc.steps: step1. insert 1 record to user table + * @tc.expected: step1. OK. + */ + const int actualCount = 10; + InsertUserTableRecord(tableName_, actualCount); + /** + * @tc.steps: step2. sync data to cloud + * @tc.expected: step2. OK. + */ + Query query = Query::Select().FromTable({ tableName_ }); + BlockSync(query, delegate_, g_actualDBStatus); + CheckCloudTableCount(tableName_, 10); + /** + * @tc.steps: step3. drop data table then close db + * @tc.expected: step3. OK. + */ + std::string deleteSql = "DROP TABLE IF EXISTS " + tableName_ + ";"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, deleteSql), DBStatus::OK); + EXPECT_EQ(mgr_->CloseStore(delegate_), DBStatus::OK); + delegate_ = nullptr; + /** + * @tc.steps: step4. recreate data table and reopen database + * @tc.expected: step4. OK. + */ + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, g_createSQL), DBStatus::OK); + RelationalStoreDelegate::Option option; + ASSERT_EQ(mgr_->OpenStore(storePath_, STORE_ID_1, option, delegate_), DBStatus::OK); + ASSERT_NE(delegate_, nullptr); + ASSERT_EQ(delegate_->SetCloudDB(virtualCloudDb_), DBStatus::OK); + ASSERT_EQ(delegate_->SetIAssetLoader(virtualAssetLoader_), DBStatus::OK); + DataBaseSchema dataBaseSchema = GetSchema(); + ASSERT_EQ(delegate_->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(communicatorAggregator_ != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_); + /** + * @tc.steps: step5. insert data to new table + * @tc.expected: step5. OK. + */ + int begin = 0; + InsertUserTableRecord(tableName_, actualCount, begin); + /** + * @tc.steps: step6. sync and cloud data should be deleted + * @tc.expected: step6. OK. + */ + ASSERT_EQ(delegate_->CreateDistributedTable(tableName_, CLOUD_COOPERATION), DBStatus::OK); + BlockSync(query, delegate_, g_actualDBStatus); + CheckCloudTableCount(tableName_, 10); +} + /** * @tc.name: CloudSyncObserverTest001 * @tc.desc: test cloud sync multi observer @@ -1268,7 +1328,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest012, TestSize.Level0) * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncObserverTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncObserverTest001, TestSize.Level1) { // prepare data const int actualCount = 10; @@ -1341,7 +1401,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncObserverTest001, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest001, TestSize.Level1) { /** * @tc.steps:step1. insert user table record and query in 3 records, then priority sync. @@ -1403,7 +1463,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest001, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest002, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -1487,7 +1547,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest002, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest003, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -1518,7 +1578,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest003, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest004, TestSize.Level1) { /** * @tc.steps:step1. insert user non-primarykey table record. @@ -1553,7 +1613,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest004, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest005, TestSize.Level1) { /** * @tc.steps:step1. insert user non-primarykey table record. @@ -1580,7 +1640,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest005, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest006, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -1644,7 +1704,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest006, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest007, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest007, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -1707,7 +1767,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest007, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest008, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest008, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -1769,7 +1829,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest008, TestSize.Lev * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest009, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest009, TestSize.Level1) { /** * @tc.steps:step1. insert user table record and query in 3 records, then priority sync. @@ -1803,7 +1863,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest009, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest010, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest010, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -1844,7 +1904,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest010, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest011, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest011, TestSize.Level1) { /** * @tc.steps:step1. insert cloud table record. @@ -1909,7 +1969,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest011, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest012, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest012, TestSize.Level1) { /** * @tc.steps:step1. insert cloud table record. @@ -1947,7 +2007,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest012, TestSize.Lev * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest013, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest013, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -2063,7 +2123,7 @@ void DistributedDBCloudCheckSyncTest::CheckUploadInfoAfterSync(int recordCount, * @tc.require: * @tc.author: suyue */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest014, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest014, TestSize.Level1) { /** * @tc.steps:step1. insert data and sync pause. @@ -2134,7 +2194,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest014, TestSize.Lev * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest015, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest015, TestSize.Level1) { /** * @tc.steps:step1. insert data and sync pause. @@ -2206,7 +2266,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest015, TestSize.Lev * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest016, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest016, TestSize.Level1) { /** * @tc.steps:step1. insert cloud table record. @@ -2248,7 +2308,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest016, TestSize.Lev * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest001, TestSize.Level1) { bool logicDelete = true; auto data = static_cast(&logicDelete); @@ -2268,7 +2328,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest001, TestSize.Level * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest002, TestSize.Level1) { bool logicDelete = false; auto data = static_cast(&logicDelete); @@ -2285,7 +2345,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest002, TestSize.Level * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest003, TestSize.Level1) { /** * @tc.steps:step1. register observer. @@ -2357,7 +2417,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest003, TestSize.Level * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest004, TestSize.Level1) { /** * @tc.steps:step1. set logic delete @@ -2405,7 +2465,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest005, TestSize.Level * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest006, TestSize.Level1) { /** * @tc.steps:step1. set logic delete @@ -2452,7 +2512,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest006, TestSize.Level * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest008, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest008, TestSize.Level1) { /** * @tc.steps:step1. Insert user table record with flag 0x800. Insert cloud table record. @@ -2514,7 +2574,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, LockActionTest001, TestSize.Level0) * @tc.name: LogicCreateRepeatedTableNameTest001 * @tc.desc: test create repeated table name with different cases * @tc.type: FUNC - * @tc.require:DTS2023120705927 + * @tc.require: * @tc.author: wangxiangdong */ HWTEST_F(DistributedDBCloudCheckSyncTest, LogicCreateRepeatedTableNameTest001, TestSize.Level0) @@ -2534,7 +2594,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, LogicCreateRepeatedTableNameTest001, T * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest001, TestSize.Level1) { /** * @tc.steps:step1. insert cloud records @@ -2564,7 +2624,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest001, TestSize.Level0) * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest002, TestSize.Level1) { /** * @tc.steps:step1. insert cloud records @@ -2603,7 +2663,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest002, TestSize.Level0) * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest003, TestSize.Level1) { /** * @tc.steps:step1. insert local records @@ -2642,7 +2702,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, SaveCursorTest003, TestSize.Level0) * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudCheckSyncTest, RangeQuerySyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, RangeQuerySyncTest001, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -2691,7 +2751,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, RangeQuerySyncTest002, TestSize.Level1 * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudCheckSyncTest, SameDataSync001, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, SameDataSync001, TestSize.Level1) { /** * @tc.steps:step1. insert cloud records, cloud has two batch id:0-4 @@ -2779,7 +2839,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, SameDataSync002, TestSize.Level1) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudCheckSyncTest, CreateDistributedTable001, TestSize.Level0) +HWTEST_F(DistributedDBCloudCheckSyncTest, CreateDistributedTable001, TestSize.Level1) { const std::string table = "CreateDistributedTable001"; const std::string createSQL = diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp index 04f5cfd8..89262003 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp @@ -1160,7 +1160,7 @@ namespace { * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest001, TestSize.Level1) { int64_t paddingSize = 10; int64_t cloudCount = 20; @@ -1202,7 +1202,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest001, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest002, TestSize.Level1) { int64_t localCount = 20; int64_t cloudCount = 10; @@ -1230,7 +1230,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest002, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest003, TestSize.Level1) { int64_t paddingSize = 10; int cloudCount = 20; @@ -1288,7 +1288,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest003, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest004, TestSize.Level1) { int64_t paddingSize = 1024 * 8; vector threads; @@ -1309,7 +1309,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest004, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest005, TestSize.Level1) { Query query = Query::Select().FromTable(g_tables).OrderBy("123", true); ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), @@ -1328,7 +1328,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest005, TestS * @tc.require: * @tc.author: wanyi */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest006, TestSize.Level1) { int64_t paddingSize = 10; int cloudCount = 20; @@ -1399,7 +1399,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest007, TestS * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest008, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest008, TestSize.Level1) { ASSERT_EQ(g_delegate->SetCloudDB(nullptr), OK); // it will not happen because cloudb has been set in SetUp() Query query = Query::Select().FromTable({g_tableName3}); @@ -1415,7 +1415,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest008, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest009, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest009, TestSize.Level1) { int64_t paddingSize = 10; int cloudCount = 20; @@ -1442,7 +1442,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest009, TestS CloseDb(); } -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest0010, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest0010, TestSize.Level1) { int64_t paddingSize = 10; int cloudCount = 20; @@ -1478,7 +1478,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest0010, Test * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest011, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest011, TestSize.Level1) { Query query = Query::Select().FromTable({g_tableName1, g_tableName1}); bool syncFinish = false; @@ -1501,12 +1501,11 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest011, TestS cv.wait(uniqueLock, [&syncFinish]() { return syncFinish; }); - RuntimeContext::GetInstance()->StopTaskPool(); EXPECT_EQ(callCount, 2); // 2 is onProcess count CloseDb(); } -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest012, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest012, TestSize.Level1) { int64_t localCount = 20; int64_t cloudCount = 10; @@ -1537,7 +1536,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest012, TestS * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest013, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest013, TestSize.Level1) { /** * @tc.steps: insert some data into cloud db @@ -1625,7 +1624,7 @@ void TestSyncForStatus(RelationalStoreDelegate *delegate, DBStatus expectStatus) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest015, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest015, TestSize.Level1) { g_virtualCloudDb->SetActionStatus(CLOUD_NETWORK_ERROR); TestSyncForStatus(g_delegate, CLOUD_NETWORK_ERROR); @@ -1653,7 +1652,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest015, TestS * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest014, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest014, TestSize.Level1) { auto adapter = std::make_shared(); RuntimeConfig::SetProcessSystemAPIAdapter(adapter); @@ -1702,7 +1701,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest014, TestS * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest016, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest016, TestSize.Level1) { int64_t localCount = 10; int64_t paddingSize = 10; @@ -1736,7 +1735,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest016, TestS * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest017, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest017, TestSize.Level1) { /** * @tc.steps: step1. make data: 20 records on local, 20 records on cloud @@ -1769,7 +1768,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest017, TestS * @tc.require: * @tc.author: wanyi */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DataNotifier001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DataNotifier001, TestSize.Level1) { int64_t paddingSize = 10; int localCount = 20; @@ -1805,7 +1804,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest001, * @tc.require: * @tc.author: huangboxin */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, MannualNotify001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, MannualNotify001, TestSize.Level1) { int64_t paddingSize = 10; int localCount = 10; @@ -1903,7 +1902,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudProcessNotify001, * @tc.require: * @tc.author: huangboxin */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest002, TestSize.Level1) { int64_t paddingSize = 10; int localCount = 3; @@ -1921,7 +1920,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest002, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest003, TestSize.Level1) { int64_t paddingSize = 10; int localCount = 3; @@ -1961,7 +1960,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest003, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest004, TestSize.Level1) { int64_t paddingSize = 10; int localCount = 3; @@ -2000,7 +1999,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest004, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest005, TestSize.Level1) { /** * @tc.steps:step1. Construct local data with asset names and hashes consistent with the cloud @@ -2058,7 +2057,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest005, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest006, TestSize.Level1) { /** * @tc.steps:step1. Construct local data with NULL asset and the local count is greater than the cloud @@ -2087,7 +2086,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest006, * @tc.require: * @tc.author: wanyi */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest007, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest007, TestSize.Level1) { /** * @tc.steps:step1. local asset contain an asset which has a corresponding asset in cloud @@ -2149,7 +2148,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest007, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest001, TestSize.Level1) { /** * @tc.steps:step1. Set different status out of parameters, and the code returns OK @@ -2189,7 +2188,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest001, T * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest008, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest008, TestSize.Level1) { /** * @tc.steps:step1. prepare asset data @@ -2240,7 +2239,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest008, * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest009, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest009, TestSize.Level1) { // insert 3 data with asset 3 data without asset into local // sync them to cloud @@ -2264,7 +2263,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest009, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest002, TestSize.Level1) { /** * @tc.steps:step1. Set different status out of parameters, and the code returns CLOUD_ERROR @@ -2304,7 +2303,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest002, T * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest003, TestSize.Level1) { /** * @tc.steps:step1. Init data and sync @@ -2343,7 +2342,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest003, T * @tc.require: * @tc.author: liufuchenxing */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest004, TestSize.Level1) { /** * @tc.steps:step1. Init data and sync @@ -2389,7 +2388,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, DownloadAssetTest004, T * @tc.require: * @tc.author: wanyi */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, SchemaTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, SchemaTest001, TestSize.Level1) { /** * @tc.steps:step1. Create table with Cloud cooperation mode @@ -2412,7 +2411,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, SchemaTest001, TestSize * @tc.require: * @tc.author: wanyi */ -HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, SchemaTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, SchemaTest002, TestSize.Level1) { /** * @tc.steps:step1. Create table with DEVICE_COOPERATION mode @@ -2463,5 +2462,107 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudCursorTest001, Tes SQLiteUtils::ResetStatement(stmt, true, errCode); CloseDb(); } + +/* + * @tc.name: RDBSupportEncryptTest001 + * @tc.desc: Test sync when security label is not set and different encryption para is set + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, RDBSupportEncryptTest001, TestSize.Level1) +{ + /** + * @tc.steps: step1. sync when security label is not set and encryption is not supported + * @tc.expected: step1. return ok. + */ + auto adapter = std::make_shared(); + RuntimeConfig::SetProcessSystemAPIAdapter(adapter); + Query query = Query::Select().FromTable({g_tableName3}); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), OK); + + /** + * @tc.steps: step2. sync when security label is not set and encryption is supported + * @tc.expected: step2. return ok. + */ + CloudSyncConfig config; + config.isSupportEncrypt = true; + g_delegate->SetCloudSyncConfig(config); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), OK); + RuntimeConfig::SetProcessSystemAPIAdapter(nullptr); + CloseDb(); +} + +/* + * @tc.name: RDBSupportEncryptTest002 + * @tc.desc: Test sync when security label is S4 and different encryption para is set + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, RDBSupportEncryptTest002, TestSize.Level0) +{ + /** + * @tc.steps: step1. sync when security label is S4 and encryption is not supported + * @tc.expected: step1. return SECURITY_OPTION_CHECK_ERROR. + */ + auto adapter = std::make_shared(); + RuntimeConfig::SetProcessSystemAPIAdapter(adapter); + Query query = Query::Select().FromTable({g_tableName3}); + adapter->ForkGetSecurityOption([](const std::string&, SecurityOption &option) { + option.securityLabel = S4; + return OK; + }); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), + SECURITY_OPTION_CHECK_ERROR); + + /** + * @tc.steps: step2. sync when security label is S4 and encryption is supported + * @tc.expected: step2. return OK. + */ + CloudSyncConfig config; + config.isSupportEncrypt = true; + g_delegate->SetCloudSyncConfig(config); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), OK); + + /** + * @tc.steps: step3. sync when isSupportEncrypt is set to false for the second time + * @tc.expected: step3. return SECURITY_OPTION_CHECK_ERROR. + */ + config.isSupportEncrypt = false; + g_delegate->SetCloudSyncConfig(config); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), + SECURITY_OPTION_CHECK_ERROR); + RuntimeConfig::SetProcessSystemAPIAdapter(nullptr); + CloseDb(); +} + +/* + * @tc.name: RDBSupportEncryptTest003 + * @tc.desc: Test sync when SecurityOption is not supported and different encryption para is set + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, RDBSupportEncryptTest003, TestSize.Level1) +{ + /** + * @tc.steps: step1. sync when unable to get security options + * @tc.expected: step1. return OK whether or not encryption is supported. + */ + auto adapter = std::make_shared(); + RuntimeConfig::SetProcessSystemAPIAdapter(adapter); + Query query = Query::Select().FromTable({g_tableName3}); + adapter->ForkGetSecurityOption([](const std::string&, SecurityOption &option) { + return NOT_SUPPORT; + }); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), OK); + CloudSyncConfig config; + config.isSupportEncrypt = true; + g_delegate->SetCloudSyncConfig(config); + EXPECT_EQ(g_delegate->Sync({DEVICE_CLOUD}, SYNC_MODE_CLOUD_MERGE, query, nullptr, g_syncWaitTime), OK); + RuntimeConfig::SetProcessSystemAPIAdapter(nullptr); + CloseDb(); +} } #endif // RELATIONAL_STORE diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp index 4df121dd..c5f5d056 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp @@ -337,7 +337,7 @@ namespace { std::vector keys; EXPECT_EQ(obj.DeleteMetaData(keys), -E_INVALID_DB); EXPECT_EQ(obj.GetAllMetaKeys(keys), -E_INVALID_DB); - Key key; + Key key = {'k'}; Value value; EXPECT_EQ(obj.GetMetaData(key, value), -E_INVALID_DB); EXPECT_EQ(obj.PutMetaData(key, value), -E_INVALID_DB); @@ -350,9 +350,6 @@ namespace { int64_t count; EXPECT_EQ(obj.GetUploadCount(querySync, timestamp, true, true, count), -E_INVALID_DB); TableSchema tableSchema; - ContinueToken token; - CloudSyncData data; - EXPECT_EQ(obj.GetCloudData(tableSchema, querySync, timestamp, token, data), -E_INVALID_DB); std::vector timestampVec; EXPECT_EQ(obj.GetAllUploadCount(querySync, timestampVec, true, true, count), -E_INVALID_DB); std::vector cloudGid; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_reference_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_reference_sync_test.cpp index c87512c8..81592c87 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_reference_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_reference_sync_test.cpp @@ -432,7 +432,7 @@ std::vector DistributedDBCloudReferenceSyncTest::InitMultiTable(int * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest001, TestSize.Level1) { std::vector tableNames = { parentTableName_, childTableName_ }; Query query = Query::Select().FromTable(tableNames); @@ -458,7 +458,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest001, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest002, TestSize.Level1) { std::vector tableNames = { sharedParentTableName_, sharedChildTableName_ }; Query query = Query::Select().FromTable(tableNames); @@ -484,7 +484,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest002, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest003, TestSize.Level1) { std::vector tableNames = { childTableName_, parentTableName_ }; Query query = Query::Select().FromTable(tableNames); @@ -510,7 +510,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest003, TestSize.Level0) * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest004, TestSize.Level1) { /** * @tc.steps: step1. cloud insert records then sync, check distributed shared table @@ -558,7 +558,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest004, TestSize.Level0) * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest005, TestSize.Level1) { /** * @tc.steps: step1. user insert records then sync, check distributed shared table @@ -599,7 +599,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest005, TestSize.Level0) * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest006, TestSize.Level1) { /** * @tc.steps: step1. user insert records then sync, check distributed shared table @@ -628,7 +628,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest006, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest007, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest007, TestSize.Level1) { /** * @tc.steps: step1. user insert records then sync, check distributed shared table @@ -652,7 +652,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest007, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest008, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest008, TestSize.Level1) { /** * @tc.steps: step1. open store with dot store id @@ -740,7 +740,7 @@ void ComplexReferenceCheck001SetReference(RelationalStoreDelegate *delegate) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck001, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck001, TestSize.Level1) { auto tableName = InitMultiTable(8); // 8 table ComplexReferenceCheck001SetReference(delegate_); @@ -796,7 +796,7 @@ void ComplexReferenceCheck002SetReference(RelationalStoreDelegate *delegate) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck002, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck002, TestSize.Level1) { auto tableName = InitMultiTable(5); // 5 table ASSERT_EQ(delegate_->SetCloudDbSchema(GetSchema(tableName)), DBStatus::OK); @@ -848,7 +848,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck002, TestSize * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck003, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck003, TestSize.Level1) { /** * @tc.steps: step1. init reference table, and reopen db @@ -915,7 +915,7 @@ HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck003, TestSize * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck004, TestSize.Level0) +HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck004, TestSize.Level1) { /** * @tc.steps: step1. init table and set reference twice diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp index 8f076089..74b5dea7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp @@ -488,7 +488,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest013, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest013, TestSize.Level1) { VbucketWithoutPrimaryDataTest(PrimaryKeyType::COMPOSITE_PRIMARY_KEY); } @@ -618,7 +618,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest018, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest018, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(name text primary key, age TEXT COLLATE NOCASE);"; std::string insertSql = "insert into " + g_tableName + " values('abcd', '10');"; @@ -633,7 +633,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest019, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest019, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(NAME text collate NOCASE, age text," + "primary key(name, age));"; @@ -649,7 +649,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest020, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest020, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(NAME text collate NOCASE, age text," + "primary key(name, age));"; @@ -665,7 +665,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest021, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest021, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(NAME text collate NOCASE, age text collate nocase," + "primary key(name, age));"; @@ -681,7 +681,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest022, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest022, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE RTRIM, age text);"; std::string insertSql = "insert into " + g_tableName + " values('abcd ', '10');"; @@ -696,7 +696,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest023, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest023, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE RTRIM, age text);"; std::string insertSql = "insert into " + g_tableName + " values('abcd_', '10');"; @@ -711,7 +711,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest024, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest024, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(name text primary key COLLATE rtrim);"; std::string insertSql = "insert into " + g_tableName + " values('abcd ');"; @@ -726,7 +726,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest025, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest025, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(name text primary key, age TEXT COLLATE rtrim);"; std::string insertSql = "insert into " + g_tableName + " values('abcd ', '10');"; @@ -741,7 +741,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest026, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest026, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(NAME text collate RTRIM, age text," + "primary key(name, age));"; @@ -757,7 +757,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest027, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest027, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(NAME text collate rtrim, age text," + "primary key(name, age));"; @@ -773,7 +773,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest028, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetInfoByPrimaryKeyOrGidTest028, TestSize.Level1) { std::string createSql = "create table " + g_tableName + "(NAME text collate rtrim, age text collate rtrim," + "primary key(name, age));"; @@ -863,7 +863,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest001, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest001, TestSize.Level1) { SaveCloudDataTest(PrimaryKeyType::NO_PRIMARY_KEY); // there is one log record with cloud_gid = abcd3(id = 7 will delete first, then insert again) @@ -886,7 +886,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest002, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest002, TestSize.Level1) { SaveCloudDataTest(PrimaryKeyType::NO_PRIMARY_KEY, GidType::GID_MISMATCH); } @@ -898,7 +898,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest003, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest003, TestSize.Level1) { SaveCloudDataTest(PrimaryKeyType::NO_PRIMARY_KEY, GidType::GID_EMPTY, true, true, -E_CLOUD_ERROR); } @@ -910,7 +910,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest004, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest004, TestSize.Level1) { SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY); } @@ -922,7 +922,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest005, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest005, TestSize.Level1) { SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_MISMATCH); } @@ -934,7 +934,7 @@ namespace { * @tc.require: * @tc.author: zhangshijie */ - HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest006, TestSize.Level0) + HWTEST_F(DistributedDBCloudSaveCloudDataTest, PutCloudSyncDataTest006, TestSize.Level1) { SaveCloudDataTest(PrimaryKeyType::SINGLE_PRIMARY_KEY, GidType::GID_EMPTY, true, true, -E_CLOUD_ERROR); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_task_merge_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_task_merge_test.cpp index f991b716..65b1b03e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_task_merge_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_task_merge_test.cpp @@ -277,7 +277,7 @@ SyncProcessCallback DistributedDBCloudTaskMergeTest::GetProcessCallback( * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTaskMergeTest, CloudSyncMergeTaskTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudTaskMergeTest, CloudSyncMergeTaskTest001, TestSize.Level1) { /** * @tc.steps:step1. insert user table record. @@ -481,7 +481,7 @@ HWTEST_F(DistributedDBCloudTaskMergeTest, CloudSyncMergeTaskTest003, TestSize.Le * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudTaskMergeTest, CloudSyncMergeTaskTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudTaskMergeTest, CloudSyncMergeTaskTest004, TestSize.Level1) { size_t finishCount = 0u; std::mutex callbackMutex; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_file_package_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_file_package_test.cpp index 2df279cf..64713e47 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_file_package_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_file_package_test.cpp @@ -177,7 +177,7 @@ void DistributedDBFilePackageTest::TearDown(void) * @tc.name: PackageFileTest001 * @tc.desc: Test file package and unpack functions. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest001, TestSize.Level1) @@ -195,7 +195,7 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest001, TestSize.Level1) * @tc.name: PackageFileTest002 * @tc.desc: Test file package if source path is not exist. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest002, TestSize.Level1) @@ -209,7 +209,7 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest002, TestSize.Level1) * @tc.name: PackageFileTest003 * @tc.desc: Test file package if result path is not exist. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest003, TestSize.Level1) @@ -223,7 +223,7 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest003, TestSize.Level1) * @tc.name: PackageFileTest004 * @tc.desc: Test file package if source path is empty. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest004, TestSize.Level1) @@ -249,7 +249,7 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest004, TestSize.Level1) * @tc.name: PackageFileTest005 * @tc.desc: Test file unpack if source file is not exist. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest005, TestSize.Level1) @@ -263,7 +263,7 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest005, TestSize.Level1) * @tc.name: PackageFileTest006 * @tc.desc: Test file unpack if result path is not exist. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest006, TestSize.Level1) @@ -280,7 +280,7 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest006, TestSize.Level1) * @tc.name: PackageFileTest007 * @tc.desc: Test file unpack if magic check failed. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest007, TestSize.Level1) @@ -304,7 +304,7 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest007, TestSize.Level1) * @tc.name: PackageFileTest008 * @tc.desc: Test file unpack if checksum check failed. * @tc.type: FUNC - * @tc.require: AR000D4879 + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest008, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_multi_ver_vacuum_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_multi_ver_vacuum_test.cpp index d6d3e570..cf57108b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_multi_ver_vacuum_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_multi_ver_vacuum_test.cpp @@ -51,7 +51,7 @@ namespace { bool CheckVacuumTaskStatus(const MultiVerVacuum &inVacuum, const string &inDbIdentifier, VacuumTaskStatus expectStatus, uint8_t repeatLimit = 5, uint32_t repeatInterval = 100) // 5 times, 100 ms { - return RepeatCheckAsyncResult([inVacuum, inDbIdentifier, expectStatus]()->bool { + return RepeatCheckAsyncResult([&inVacuum, &inDbIdentifier, expectStatus]()->bool { VacuumTaskStatus outStatus = VacuumTaskStatus::RUN_WAIT; int errCode = inVacuum.QueryStatus(inDbIdentifier, outStatus); return errCode == E_OK && outStatus == expectStatus; @@ -89,7 +89,7 @@ void DistributedDBMultiVerVacuumTest::TearDown() * @tc.name: SingleTaskNormalStatusSwitch001 * @tc.desc: Test status switch for single task under normal operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch001, TestSize.Level2) @@ -156,7 +156,7 @@ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch001, TestS * @tc.name: SingleTaskNormalStatusSwitch002 * @tc.desc: Test status switch for single task under normal operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch002, TestSize.Level2) @@ -223,7 +223,7 @@ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch002, TestS * @tc.name: SingleTaskNormalStatusSwitch003 * @tc.desc: Test status switch for single task under normal operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch003, TestSize.Level2) @@ -289,7 +289,7 @@ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch003, TestS * @tc.name: SingleTaskNormalStatusSwitch004 * @tc.desc: Test status switch for single task under normal operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch004, TestSize.Level2) @@ -347,7 +347,7 @@ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskNormalStatusSwitch004, TestS * @tc.name: SingleTaskAbnormalStatusSwitch001 * @tc.desc: Test status switch for single task under abnormal operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskAbnormalStatusSwitch001, TestSize.Level2) @@ -486,7 +486,7 @@ namespace { * @tc.name: SingleTaskConcurrentStatusSwitch001 * @tc.desc: Test status switch for single task under Concurrent operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskConcurrentStatusSwitch001, TestSize.Level2) @@ -542,7 +542,7 @@ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskConcurrentStatusSwitch001, T * @tc.name: SingleTaskWriteHandleOccupy001 * @tc.desc: Test write handle occupy for single task under normal operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskWriteHandleOccupy001, TestSize.Level2) @@ -602,7 +602,7 @@ HWTEST_F(DistributedDBMultiVerVacuumTest, SingleTaskWriteHandleOccupy001, TestSi * @tc.name: MultipleTaskNormalStatusSwitch001 * @tc.desc: Test status switch for multiple task under normal operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, MultipleTaskNormalStatusSwitch001, TestSize.Level1) @@ -673,7 +673,7 @@ HWTEST_F(DistributedDBMultiVerVacuumTest, MultipleTaskNormalStatusSwitch001, Tes * @tc.name: MultipleTaskNormalStatusSwitch002 * @tc.desc: Test status switch for multiple task under normal operation * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerVacuumTest, MultipleTaskNormalStatusSwitch002, TestSize.Level2) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_query_object_helper_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_query_object_helper_test.cpp index 8b987e9b..5d07611e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_query_object_helper_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_query_object_helper_test.cpp @@ -110,7 +110,7 @@ void DistributedDBQueryObjectHelperTest::TearDown(void) * @tc.name: Query001 * @tc.desc: Check the legal single query operation to see if the generated container is correct * @tc.type: FUNC - * @tc.require: AR000DR9K6 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBQueryObjectHelperTest, Query001, TestSize.Level1) @@ -161,7 +161,7 @@ HWTEST_F(DistributedDBQueryObjectHelperTest, Query001, TestSize.Level1) * @tc.name: Query002 * @tc.desc: Check for illegal query conditions can not get helper transfer to sql * @tc.type: FUNC - * @tc.require: AR000DR9K6 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBQueryObjectHelperTest, Query002, TestSize.Level1) @@ -193,7 +193,7 @@ HWTEST_F(DistributedDBQueryObjectHelperTest, Query002, TestSize.Level1) * @tc.name: Query003 * @tc.desc: Check combination condition transfer to sql * @tc.type: FUNC - * @tc.require: AR000DR9K6 + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBQueryObjectHelperTest, Query003, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_rdb_collaboration_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_rdb_collaboration_test.cpp index ee47387e..ef6c883f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_rdb_collaboration_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_rdb_collaboration_test.cpp @@ -195,7 +195,7 @@ void DistributedDBRDBCollaborationTest::CloseDb() * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema001, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema001, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -236,7 +236,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema001, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema002, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema002, TestSize.Level1) { /** * @tc.steps: step1. Create cloud table in SPLIT_BY_DEVICE @@ -265,7 +265,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema002, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema003, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema003, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -374,7 +374,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema005, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema006, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema006, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -456,7 +456,7 @@ std::string GetTriggerSql(const std::string &tableName, const std::string &trigg * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema007, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema007, TestSize.Level1) { /** * @tc.steps: step1. Prepare db @@ -510,7 +510,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema007, TestSize.Level0) * @tc.require: * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema008, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema008, TestSize.Level1) { /** * @tc.steps: step1. Prepare db @@ -645,7 +645,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema012, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema013, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema013, TestSize.Level1) { /** * @tc.steps: step1. Create device table @@ -690,7 +690,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema013, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema014, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema014, TestSize.Level1) { /** * @tc.steps: step1. Create auto increment table and specified pk, distributed schema without not null field @@ -743,7 +743,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema014, TestSize.Level0) * @tc.require: * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema015, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema015, TestSize.Level1) { /** * @tc.steps: step1. Prepare db, tableMode is COLLABORATION @@ -841,7 +841,7 @@ int GetHashKey(sqlite3 *db, const std::string &tableName, std::vectorSetDistributedSchema(schema2), OK); + EXPECT_EQ(delegate_->SetDistributedSchema(schema2, true), OK); std::vector newHashKeys2; EXPECT_EQ(GetHashKey(db_, tableName, newHashKeys2), E_OK); ASSERT_EQ(newHashKeys2.size(), static_cast(dataCount)); @@ -1048,7 +1048,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema021, TestSize.Level1) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema022, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema022, TestSize.Level1) { /** * @tc.steps: step1. Create device table named keywords. @@ -1088,13 +1088,13 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema023, TestSize.Level0) /** * @tc.steps: step2. decrease tables of input parameter to set distributed schema - * @tc.expected: step2. return DISTRIBUTED_FIELD_DECREASE + * @tc.expected: step2. return OK */ distributedSchema = {2, {{CLOUD_SYNC_TABLE, {{"pk", true}, {"int_field2", false}}}}}; - EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), DISTRIBUTED_FIELD_DECREASE); - distributedSchema = {2, {{DEVICE_SYNC_TABLE, {{"pk", true}, {"int_field1", true}}}, + EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK); + distributedSchema = {3, {{DEVICE_SYNC_TABLE, {{"pk", true}, {"int_field1", true}}}, {DEVICE_SYNC_TABLE_UPGRADE, {{"pk", true}, {"int_field2", false}}}}}; - EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), DISTRIBUTED_FIELD_DECREASE); + EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK); } /** @@ -1104,7 +1104,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema023, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema024, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema024, TestSize.Level1) { /** * @tc.steps: step1. set distributed schema for the first time @@ -1143,6 +1143,108 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema024, TestSize.Level0) EXPECT_EQ(res, OVER_MAX_LIMITS); } +/** + * @tc.name: SetSchema025 + * @tc.desc: Test SetDistributedSchema with isForceUpgrade. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema025, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create device table and cloud table in COLLABORATION + * @tc.expected: step1.ok + */ + ASSERT_NO_FATAL_FAILURE(InitDelegate()); + EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK); + DistributedSchema distributedSchema1 = {1, {{DEVICE_SYNC_TABLE, {{"pk", true}, {"int_field1", true}}}}}; + EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema1), OK); + /** + * @tc.steps: step2. Set distributed schema with isForceUpgrade + * @tc.expected: step2.ok + */ + DistributedSchema distributedSchema2 = {2, {{DEVICE_SYNC_TABLE, {{"pk", true}}}}}; + EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema2, true), OK); +} + +/** + * @tc.name: SetSchema026 + * @tc.desc: Test SetDistributedSchema with conflict log. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema026, TestSize.Level0) +{ + /** + * @tc.steps: step1. Prepare db, tableMode is COLLABORATION + * @tc.expected: step1.ok + */ + ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION)); + std::string createSql = "CREATE TABLE IF NOT EXISTS table_pk_int(integer_field INTEGER PRIMARY KEY AUTOINCREMENT," + "int_field INT UNIQUE);"; + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, createSql), E_OK); + EXPECT_EQ(delegate_->CreateDistributedTable("table_pk_int", TableSyncType::DEVICE_COOPERATION), OK); + /** + * @tc.steps: step2. Set Distributed Schema + * @tc.expected: step2. return OK + */ + DistributedSchema distributedSchema = {1, { + {"table_pk_int", { + {"integer_field", true}, + {"int_field", true} + }}} + }; + EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK); + /** + * @tc.steps: step3. Local insert (1, 2), (2, 1) and delete (1, 2) + * @tc.expected: step3. return OK + */ + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, "INSERT INTO table_pk_int VALUES(1, 2)"), E_OK); + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, "INSERT INTO table_pk_int VALUES(2, 1)"), E_OK); + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, "DELETE FROM table_pk_int WHERE integer_field = 1"), E_OK); + /** + * @tc.steps: step4. Upgrade Distributed Schema and mark int_field specified + * @tc.expected: step4. return OK + */ + distributedSchema = {2, { + {"table_pk_int", { + {"integer_field", false}, + {"int_field", true, true} + }}} + }; + EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema, true), OK); +} + +/** + * @tc.name: SetSchema027 + * @tc.desc: Test two table create distributed table. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema027, TestSize.Level0) +{ + /** + * @tc.steps: step1. Prepare db create two table + * @tc.expected: step1.ok + */ + ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::COLLABORATION)); + std::string createSql = "CREATE TABLE IF NOT EXISTS table1(integer_field INTEGER PRIMARY KEY AUTOINCREMENT," + "int_field INT UNIQUE);"; + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, createSql), E_OK); + EXPECT_EQ(delegate_->CreateDistributedTable("table1", TableSyncType::DEVICE_COOPERATION), OK); + createSql = "CREATE TABLE IF NOT EXISTS table2(integer_field INTEGER PRIMARY KEY AUTOINCREMENT," + "int_field INT UNIQUE);"; + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, createSql), E_OK); + EXPECT_EQ(delegate_->CreateDistributedTable("table2", TableSyncType::DEVICE_COOPERATION), OK); + auto table1 = std::string(DBConstant::RELATIONAL_PREFIX).append("table1_log"); + auto table2 = std::string(DBConstant::RELATIONAL_PREFIX).append("table2_log"); + RelationalTestUtils::CheckIndexCount(db_, table1, 3u); // 3 is index count + RelationalTestUtils::CheckIndexCount(db_, table2, 3u); // 3 is index count +} + /** * @tc.name: NormalSync001 * @tc.desc: Test set distributed schema and sync. @@ -1150,7 +1252,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetSchema024, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync001, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync001, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1185,7 +1287,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync001, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync002, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync002, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1231,7 +1333,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync002, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync003, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync003, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1303,7 +1405,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync004, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync005, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync005, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1359,7 +1461,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync005, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync006, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync006, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1406,7 +1508,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync006, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync007, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync007, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1460,7 +1562,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync007, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync008, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync008, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1506,7 +1608,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync008, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync009, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync009, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1601,7 +1703,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync010, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync011, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync011, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1636,7 +1738,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync011, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync012, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync012, TestSize.Level1) { /** * @tc.steps: step1. Create auto increment table and unique index @@ -1698,7 +1800,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync012, TestSize.Level0) * @tc.require: * @tc.author: lg */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync013, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync013, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1752,7 +1854,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync013, TestSize.Level0) * @tc.require: * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync014, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync014, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1813,7 +1915,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync014, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync015, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync015, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1881,7 +1983,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync015, TestSize.Level0) * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync016, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync016, TestSize.Level1) { /** * @tc.steps: step1. Prepare db, tableMode is COLLABORATION @@ -1922,7 +2024,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync016, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync017, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync017, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -1975,7 +2077,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync017, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync018, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync018, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -2030,7 +2132,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync018, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync019, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync019, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -2072,7 +2174,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync019, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync020, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync020, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -2111,7 +2213,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync020, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync021, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync021, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -2165,7 +2267,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync021, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync022, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync022, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -2226,7 +2328,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync022, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync023, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync023, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -2277,7 +2379,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync023, TestSize.Level0) * @tc.require: * @tc.author: lg */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync024, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync024, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION @@ -2340,7 +2442,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync024, TestSize.Level0) * @tc.require: * @tc.author: liuhongyang */ -HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync025, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync025, TestSize.Level1) { /** * @tc.steps: step1. Create SPLIT_BY_DEVICE tables @@ -2417,7 +2519,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, NormalSync025, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, SetStoreConfig001, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, SetStoreConfig001, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in SPLIT_BY_DEVICE @@ -2489,6 +2591,48 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetStoreConfig003, TestSize.Level0) EXPECT_EQ(delegate_->SetStoreConfig({DistributedTableMode::SPLIT_BY_DEVICE}), NOT_SUPPORT); } +/** + * @tc.name: SetStoreConfig004 + * @tc.desc: Test properties for concurrent get and set operations + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBRDBCollaborationTest, SetStoreConfig004, TestSize.Level2) +{ + /** + * @tc.steps: step1. Create device table and cloud table in SPLIT_BY_DEVICE + * @tc.expected: step1.ok + */ + ASSERT_NO_FATAL_FAILURE(InitDelegate(DistributedTableMode::SPLIT_BY_DEVICE)); + /** + * @tc.steps: step2. Set store config. + * @tc.expected: step2.ok + */ + EXPECT_EQ(delegate_->SetStoreConfig({DistributedTableMode::COLLABORATION}), OK); + auto schema = GetSchema(); + auto distributedSchema = RDBDataGenerator::ParseSchema(schema, true); + deviceB_->SetDistributedSchema(distributedSchema); + EXPECT_EQ(delegate_->CreateDistributedTable(DEVICE_SYNC_TABLE, TableSyncType::DEVICE_COOPERATION), OK); + EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK); + /** + * @tc.steps: step3. check for concurrent interface calls + * @tc.expected: step3.ok + */ + std::thread t1([this, distributedSchema]() { + for (size_t i = 0; i < 10000; i++) { + EXPECT_EQ(delegate_->SetDistributedSchema(distributedSchema), OK); + } + }); + std::thread t2([this, distributedSchema]() { + for (size_t i = 0; i < 10000; i++) { + EXPECT_EQ(delegate_->SetStoreConfig({DistributedTableMode::COLLABORATION}), OK); + } + }); + t1.join(); + t2.join(); +} + /** * @tc.name: InvalidSync001 * @tc.desc: Test remote set empty distributed schema and sync. @@ -2496,7 +2640,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, SetStoreConfig003, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRDBCollaborationTest, InvalidSync001, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, InvalidSync001, TestSize.Level1) { /** * @tc.steps: step1. Remote device set empty distributed schema @@ -2655,7 +2799,7 @@ HWTEST_F(DistributedDBRDBCollaborationTest, InvalidSync004, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRDBCollaborationTest, InvalidSync005, TestSize.Level0) +HWTEST_F(DistributedDBRDBCollaborationTest, InvalidSync005, TestSize.Level1) { /** * @tc.steps: step1. Create device table and cloud table in COLLABORATION diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp index 237415df..24dfac79 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp @@ -95,7 +95,8 @@ void CreateLogTable(const std::string &tableName) sqlite3 *db = nullptr; ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); auto tableManager = - LogTableManagerFactory::GetTableManager(DistributedTableMode::COLLABORATION, TableSyncType::CLOUD_COOPERATION); + LogTableManagerFactory::GetTableManager(table, DistributedTableMode::COLLABORATION, + TableSyncType::CLOUD_COOPERATION); int errCode = tableManager->CreateRelationalLogTable(db, table); EXPECT_EQ(errCode, E_OK); sqlite3_close(db); @@ -470,6 +471,50 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, MetaDataTest002, TestS EXPECT_EQ(g_cloudStore->GetMetaData(maxKey, value), -E_INVALID_ARGS); } +/** + * @tc.name: MetaDataTest003 + * @tc.desc: The GetMetaData concurrent execute + * @tc.type: FUNC + * @tc.require: + * @tc.author: tankaisheng + */ +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, MetaDataTest003, TestSize.Level0) +{ + /** + * @tc.steps: step1. put data + * @tc.expected: OK. + */ + const std::string str(DBConstant::MAX_KEY_SIZE, 'k'); + const Key key(str.begin(), str.end()); + EXPECT_EQ(g_cloudStore->PutMetaData(key, VALUE_2), E_OK); + + /** + * @tc.steps: step2. concurrent execute get data + * @tc.expected: OK. + */ + const int threadCount = 10; + std::vector threads; + std::vector results(threadCount); + + auto worker = [](ICloudSyncStorageInterface* cloudStore, const Key& key, std::vector& results, int index) { + Value value; + EXPECT_EQ(cloudStore->GetMetaData(key, value), E_OK); + results[index] = value; + }; + + for (int i = 0; i < threadCount; ++i) { + threads.emplace_back(worker, g_cloudStore, key, std::ref(results), i); + } + + for (auto& thread : threads) { + thread.join(); + } + + for (const auto& value : results) { + EXPECT_EQ(value, VALUE_2); + } +} + /** * @tc.name: TransactionTest001 * @tc.desc: No write transaction in the current store, meta interface can called @@ -614,7 +659,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, TransactionTest004, Te * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount001, TestSize.Level1) { /** * @tc.steps: Table does not exist @@ -648,7 +693,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount001, Tes * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount002, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount002, TestSize.Level1) { CreateLogTable(g_tableName); int64_t insCount = 100; @@ -657,11 +702,9 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount002, Tes int64_t resCount = 0; /** - * @tc.steps: GetUploadCount must be called under transaction - * @tc.expected: return -E_TRANSACT_STATE. + * @tc.steps: GetUploadCount can be called under read transaction + * @tc.expected: return -E_OK. */ - EXPECT_EQ(g_storageProxy->GetUploadCount(g_tableName, g_startTime, false, resCount), -E_TRANSACT_STATE); - int timeOffset = 30; EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); EXPECT_EQ(g_storageProxy->GetUploadCount(g_tableName, g_startTime + timeOffset, false, resCount), E_OK); @@ -687,7 +730,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount002, Tes * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount003, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount003, TestSize.Level1) { CreateLogTable(g_tableName); int64_t insCount = 100; @@ -696,11 +739,9 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount003, Tes int64_t resCount = 0; /** - * @tc.steps: GetUploadCount must be called under transaction - * @tc.expected: return -E_TRANSACT_STATE. + * @tc.steps: GetUploadCount can be called under transaction + * @tc.expected: return E_OK. */ - EXPECT_EQ(g_storageProxy->GetUploadCount(g_tableName, g_startTime, false, resCount), -E_TRANSACT_STATE); - EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); EXPECT_EQ(g_storageProxy->GetUploadCount(g_tableName, g_startTime, false, resCount), E_OK); EXPECT_EQ(resCount, insCount); @@ -761,7 +802,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount004, Tes * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid001, TestSize.Level1) { CreateLogTable(g_tableName); int64_t insCount = 100; @@ -847,7 +888,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid001, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData003, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData003, TestSize.Level1) { CreateLogTable(g_tableName); int64_t insCount = 1024; @@ -879,7 +920,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData003, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData004, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData004, TestSize.Level1) { CreateLogTable(g_tableName); int64_t insCount = 10; @@ -906,6 +947,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData004, TestS EXPECT_EQ(asserts->second.index(), static_cast(TYPE_INDEX)); } EXPECT_EQ(g_storageProxy->Commit(), E_OK); + EXPECT_EQ(g_storageProxy->ReleaseContinueToken(token), E_OK); } /** @@ -915,7 +957,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData004, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData005, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData005, TestSize.Level1) { CreateLogTable(g_tableName); int64_t insCount = 1024; @@ -935,7 +977,8 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData005, TestS * @tc.steps: GetCloudDataNext after the transaction ends, token will released internally * @tc.expected: return -E_INVALID_DB. */ - ASSERT_EQ(g_cloudStore->GetCloudDataNext(token, cloudSyncData), -E_INVALID_DB); + ASSERT_EQ(g_cloudStore->GetCloudDataNext(token, cloudSyncData), -E_UNFINISHED); + EXPECT_EQ(g_storageProxy->ReleaseContinueToken(token), E_OK); } /** @@ -945,7 +988,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData005, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData006, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData006, TestSize.Level1) { /** * @tc.steps:step1. Init data and set asset status to invalid num @@ -970,6 +1013,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData006, TestS EXPECT_EQ(g_storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); ASSERT_EQ(g_storageProxy->GetCloudData(g_tableName, g_startTime, token, cloudSyncData), -E_CLOUD_ERROR); EXPECT_EQ(g_storageProxy->Rollback(), E_OK); + EXPECT_EQ(g_storageProxy->ReleaseContinueToken(token), E_OK); } /** @@ -979,7 +1023,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData006, TestS * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData008, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData008, TestSize.Level1) { /** * @tc.steps:step1. table1 @@ -1027,6 +1071,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData008, TestS std::vector cloudGid; EXPECT_EQ(g_storageProxy->GetCloudGid(obj, false, false, cloudGid), E_OK); EXPECT_EQ(g_storageProxy->Commit(), E_OK); + EXPECT_EQ(g_storageProxy->ReleaseContinueToken(token), E_OK); } /** @@ -1036,7 +1081,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData008, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetInfoByPrimaryKeyOrGid001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetInfoByPrimaryKeyOrGid001, TestSize.Level1) { int64_t insCount = 100; int64_t photoSize = 10; @@ -1094,7 +1139,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetInfoByPrimaryKeyOrG EXPECT_EQ(g_storageProxy->Commit(), E_OK); } -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncData001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncData001, TestSize.Level1) { int64_t insCount = 10; int64_t photoSize = 10; @@ -1111,9 +1156,10 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncData001, T CloudSyncData cloudSyncData; ASSERT_EQ(g_storageProxy->GetCloudData(g_tableName, 0L, token, cloudSyncData), E_OK); EXPECT_EQ(g_storageProxy->Commit(), E_OK); + EXPECT_EQ(g_storageProxy->ReleaseContinueToken(token), E_OK); } -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset001, TestSize.Level1) { int64_t insCount = 10; int64_t photoSize = 10; @@ -1127,7 +1173,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset001, Tes fillCloudAssetTest(insCount, AssetStatus::ABNORMAL, true); } -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset002, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset002, TestSize.Level1) { int64_t insCount = 10; int64_t photoSize = 10; @@ -1188,7 +1234,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset002, Tes * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset003, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset003, TestSize.Level1) { int64_t insCount = 2; int64_t photoSize = 10; @@ -1240,7 +1286,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset003, Tes * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset004, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset004, TestSize.Level1) { int64_t insCount = 2; int64_t photoSize = 10; @@ -1395,7 +1441,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, CalPrimaryKeyHash002, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudVersion001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudVersion001, TestSize.Level1) { /** * @tc.steps: step1. init data @@ -1464,7 +1510,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudVersion001, T * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncVersion001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncVersion001, TestSize.Level1) { /** * @tc.steps: step1. table type is shareTable, but downloadData is not contains version @@ -1506,7 +1552,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncVersion001 * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncVersion002, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncVersion002, TestSize.Level1) { /** * @tc.steps: step1. table type is shareTable, but downloadData is not contains version @@ -1536,7 +1582,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncVersion002 EXPECT_EQ(g_storageProxy->Commit(), E_OK); } -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, getAsset001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, getAsset001, TestSize.Level1) { /** * @tc.steps: step1. both gid and hashKey are empty @@ -1596,7 +1642,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, getAsset001, TestSize. EXPECT_EQ(g_storageProxy->Commit(), E_OK); } -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, getAsset002, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, getAsset002, TestSize.Level1) { /** * @tc.steps: step1. hashKey is 2, or gid is 4 @@ -1648,7 +1694,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, getAsset002, TestSize. * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData007, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData007, TestSize.Level1) { /** * @tc.steps:step1. Init data and set asset status to abnormal @@ -1684,7 +1730,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData007, TestS * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, ContainAssetsTable001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, ContainAssetsTable001, TestSize.Level1) { ASSERT_NE(g_storageProxy, nullptr); EXPECT_FALSE(g_storageProxy->IsExistTableContainAssets()); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_encrypted_db_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_encrypted_db_test.cpp index f1321ccd..7a155c9d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_encrypted_db_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_encrypted_db_test.cpp @@ -147,7 +147,7 @@ void DistributedDBRelationalEncryptedDbTest::TearDown(void) * @tc.name: OpenEncryptedDBWithoutPasswd_001 * @tc.desc: Open encrypted db without password in collaboration mode. * @tc.type: FUNC - * @tc.require: AR000H68LL + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithoutPasswdInCollMode_001, TestSize.Level1) @@ -181,7 +181,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithoutPasswdInC * @tc.name: OpenEncryptedDBWithoutPasswdInSplitMode_001 * @tc.desc: Open encrypted db without password in split mode. * @tc.type: FUNC - * @tc.require: AR000H68LL + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithoutPasswdInSplitMode_001, TestSize.Level1) @@ -215,7 +215,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithoutPasswdInS * @tc.name: OpenEncryptedDBWithPasswdInSplitMode_001 * @tc.desc: Open encrypted db with password in split mode. * @tc.type: FUNC - * @tc.require: AR000H68LL + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithPasswdInSplitMode_001, TestSize.Level1) @@ -273,7 +273,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithPasswdInSpli * @tc.name: OpenEncryptedDBWithInvalidParameters_001 * @tc.desc: Open encrypted db with invalid parameters in split mode. * @tc.type: FUNC - * @tc.require: AR000H68LL + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithInvalidParameters_001, TestSize.Level1) @@ -317,7 +317,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithInvalidParam * @tc.name: OpenEncryptedDBWithCustomizedIterTimes_001 * @tc.desc: Open encrypted db with customized iterate times. * @tc.type: FUNC - * @tc.require: AR000H68LL + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithCustomizedIterTimes_001, TestSize.Level1) @@ -375,7 +375,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithCustomizedIt * @tc.name: RekeyAfterOpenStore_001 * @tc.desc: Rekey after open store. * @tc.type: FUNC - * @tc.require: AR000H68LL + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RekeyAfterOpenStore_001, TestSize.Level1) @@ -404,7 +404,8 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RekeyAfterOpenStore_001, TestSi EXPECT_EQ(g_mgr.OpenStore(g_storePath, g_storeID, option1, g_delegate), DBStatus::OK); ASSERT_NE(g_delegate, nullptr); ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName), DBStatus::OK); - + EXPECT_EQ(g_mgr.CloseStore(g_delegate), DBStatus::OK); + g_delegate = nullptr; std::thread t1([db] { std::string sql = "PARGMA rekey=" + REKEY_KEY; EXPECT_EQ(sqlite3_rekey(db, REKEY_KEY.data(), REKEY_KEY.size()), SQLITE_OK); @@ -412,22 +413,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RekeyAfterOpenStore_001, TestSi t1.join(); /** - * @tc.steps: step3. Get sync data. - * @tc.expected: Failed. - */ - auto store = GetRelationalStore(); - ASSERT_NE(store, nullptr); - ContinueToken token = nullptr; - QueryObject query(Query::Select(g_tableName)); - std::vector entries; - EXPECT_NE(store->GetSyncData(query, SyncTimeRange {}, DataSizeSpecInfo {}, token, entries), E_OK); - - RefObject::DecObjRef(g_store); - g_mgr.CloseStore(g_delegate); - g_delegate = nullptr; - - /** - * @tc.steps: step4. Open store with new key. + * @tc.steps: step3. Open store with new key. * @tc.expected: Succeed. */ option1.passwd = g_rekeyPasswd; @@ -436,11 +422,14 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RekeyAfterOpenStore_001, TestSi ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName), DBStatus::OK); /** - * @tc.steps: step5. Get sync data. + * @tc.steps: step4. Get sync data. * @tc.expected: Succeed. */ - store = GetRelationalStore(); + auto store = GetRelationalStore(); ASSERT_NE(store, nullptr); + ContinueToken token = nullptr; + QueryObject query(Query::Select(g_tableName)); + std::vector entries; EXPECT_EQ(store->GetSyncData(query, SyncTimeRange {}, DataSizeSpecInfo {}, token, entries), E_OK); FreeEntires(entries); sqlite3_close(db); @@ -451,7 +440,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RekeyAfterOpenStore_001, TestSi * @tc.name: OpenEncryptedDBWithDifferentPasswd_001 * @tc.desc: Open encrypted db with different password in split mode. * @tc.type: FUNC - * @tc.require: AR000H68LL + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithDifferentPasswd_001, TestSize.Level1) @@ -468,6 +457,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithDifferentPas "PRAGMA journal_mode=WAL;" "CREATE TABLE " + g_tableName + "(key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, value INTEGER);"; ExecSqlAndAssertOK(db, sql); + sqlite3_close(db); /** * @tc.steps: step2. Open store. @@ -504,14 +494,13 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, OpenEncryptedDBWithDifferentPas EXPECT_NE(delegate, nullptr); EXPECT_EQ(g_mgr.CloseStore(delegate), DBStatus::OK); - sqlite3_close(db); } /** * @tc.name: RemoteQueryForEncryptedDb_001 * @tc.desc: Exec remote query on encrypted db. * @tc.type: FUNC - * @tc.require: AR000H68LL + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RemoteQueryForEncryptedDb_001, TestSize.Level1) @@ -530,6 +519,7 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RemoteQueryForEncryptedDb_001, "PRAGMA journal_mode=WAL;" "CREATE TABLE " + g_tableName + "(key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, value INTEGER);"; ExecSqlAndAssertOK(db, sql); + sqlite3_close(db); /** * @tc.steps: step2. Open store and create distributed table. @@ -553,19 +543,23 @@ HWTEST_F(DistributedDBRelationalEncryptedDbTest, RemoteQueryForEncryptedDb_001, /** * @tc.steps: step4. Rekey. */ + EXPECT_EQ(g_mgr.CloseStore(g_delegate), OK); + g_delegate = nullptr; + ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); std::thread t1([db] { std::string sql = "PARGMA rekey=" + REKEY_KEY; EXPECT_EQ(sqlite3_rekey(db, REKEY_KEY.data(), REKEY_KEY.size()), SQLITE_OK); }); t1.join(); - + sqlite3_close(db); + EXPECT_EQ(g_mgr.OpenStore(g_storePath, g_storeID, option, g_delegate), DBStatus::OK); + ASSERT_NE(g_delegate, nullptr); /** * @tc.steps: step5. Remote query. * @tc.expected: Return INVALID_PASSWD_OR_CORRUPTED_DB. */ - EXPECT_EQ(g_delegate->RemoteQuery("deviceA", RemoteCondition {}, invalidTime, result), + EXPECT_NE(g_delegate->RemoteQuery("deviceA", RemoteCondition {}, invalidTime, result), DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB); - sqlite3_close(db); } #endif // RELATIONAL_STORE #endif // OMIT_ENCRYPT diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp index 942d22b9..add7db47 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp @@ -324,7 +324,7 @@ void DistributedDBRelationalGetDataTest::TearDown(void) * @tc.name: LogTbl1 * @tc.desc: When put sync data to relational store, trigger generate log. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, LogTbl1, TestSize.Level1) @@ -356,7 +356,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, LogTbl1, TestSize.Level1) * @tc.name: GetSyncData1 * @tc.desc: GetSyncData interface * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetSyncData1, TestSize.Level1) @@ -408,7 +408,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetSyncData1, TestSize.Level1) * @tc.name: GetSyncData2 * @tc.desc: GetSyncData interface. For overlarge data(over 4M), ignore it. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetSyncData2, TestSize.Level1) @@ -451,7 +451,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetSyncData2, TestSize.Level1) * @tc.name: GetSyncData3 * @tc.desc: GetSyncData interface. For deleted data. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetSyncData3, TestSize.Level1) @@ -543,7 +543,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetSyncData3, TestSize.Level1) * @tc.name: GetQuerySyncData1 * @tc.desc: GetSyncData interface. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetQuerySyncData1, TestSize.Level1) @@ -586,7 +586,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetQuerySyncData1, TestSize.Level1) * @tc.name: GetQuerySyncData2 * @tc.desc: GetSyncData interface. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetQuerySyncData2, TestSize.Level1) @@ -655,7 +655,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetQuerySyncData2, TestSize.Level1) * @tc.name: GetIncorrectTypeData1 * @tc.desc: GetSyncData and PutSyncDataWithQuery interface. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetIncorrectTypeData1, TestSize.Level1) @@ -745,7 +745,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetIncorrectTypeData1, TestSize.Lev * @tc.name: UpdateData1 * @tc.desc: UpdateData succeed when the table has primary key. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, UpdateData1, TestSize.Level1) @@ -831,7 +831,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, UpdateData1, TestSize.Level1) * @tc.name: UpdateDataWithMulDevData1 * @tc.desc: UpdateData succeed when there is multiple devices data exists. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, UpdateDataWithMulDevData1, TestSize.Level1) @@ -897,7 +897,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, UpdateDataWithMulDevData1, TestSize * @tc.name: MissQuery1 * @tc.desc: Check REMOTE_DEVICE_DATA_MISS_QUERY flag succeed. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, MissQuery1, TestSize.Level1) @@ -1004,7 +1004,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, MissQuery1, TestSize.Level1) * @tc.name: CompatibleData1 * @tc.desc: Check compatibility. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, CompatibleData1, TestSize.Level1) @@ -1091,7 +1091,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, CompatibleData1, TestSize.Level1) * @tc.name: GetDataSortByTime1 * @tc.desc: All query get data sort by time asc. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetDataSortByTime1, TestSize.Level1) @@ -1156,7 +1156,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetDataSortByTime1, TestSize.Level1 * @tc.name: SameFieldWithLogTable1 * @tc.desc: Get query data OK when the table has same field with log table. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, SameFieldWithLogTable1, TestSize.Level1) @@ -1200,7 +1200,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, SameFieldWithLogTable1, TestSize.Le * @tc.name: CompatibleData2 * @tc.desc: Check compatibility. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, CompatibleData2, TestSize.Level1) @@ -1254,7 +1254,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, CompatibleData2, TestSize.Level1) * @tc.name: PutSyncDataConflictDataTest001 * @tc.desc: Check put with conflict sync data. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lianhuix */ HWTEST_F(DistributedDBRelationalGetDataTest, PutSyncDataConflictDataTest001, TestSize.Level1) @@ -1307,7 +1307,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, PutSyncDataConflictDataTest001, Tes * @tc.name: SaveNonexistDevdata1 * @tc.desc: Save non-exist device data and check errCode. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, SaveNonexistDevdata1, TestSize.Level1) @@ -1362,7 +1362,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, SaveNonexistDevdata1, TestSize.Leve * @tc.name: GetMaxTimestamp1 * @tc.desc: Get max timestamp. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetMaxTimestamp1, TestSize.Level1) @@ -1434,7 +1434,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetMaxTimestamp1, TestSize.Level1) * @tc.name: NoPkData1 * @tc.desc: For no pk data. * @tc.type: FUNC - * @tc.require: AR000GK58H + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, NoPkData1, TestSize.Level1) @@ -1528,7 +1528,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, NoPkData1, TestSize.Level1) * @tc.name: GetAfterDropTable1 * @tc.desc: Get data after drop table. * @tc.type: FUNC - * @tc.require: AR000H2QPN + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalGetDataTest, GetAfterDropTable1, TestSize.Level1) @@ -1627,7 +1627,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, SetNextBeginTime001, TestSize.Level * @tc.name: CloseStore001 * @tc.desc: Test Relational Store Close Action. * @tc.type: FUNC - * @tc.require: AR000H2QPN + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalGetDataTest, CloseStore001, TestSize.Level1) @@ -1739,7 +1739,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, ReleaseContinueTokenTest001, TestSi * @tc.name: StopSync001 * @tc.desc: Test Relational Stop Sync Action. * @tc.type: FUNC - * @tc.require: AR000H2QPN + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalGetDataTest, StopSync001, TestSize.Level1) @@ -1780,7 +1780,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, StopSync001, TestSize.Level1) * @tc.name: EraseDeviceWaterMark001 * @tc.desc: Test Relational erase water mark. * @tc.type: FUNC - * @tc.require: AR000H2QPN + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalGetDataTest, EraseDeviceWaterMark001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_remote_query_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_remote_query_test.cpp index 90aa72bf..bdf6f57a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_remote_query_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_remote_query_test.cpp @@ -168,7 +168,7 @@ void DistributedDBRelationalRemoteQueryTest::TearDown(void) * @tc.name: NormalQuery1 * @tc.desc: Normal query. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, NormalQuery1, TestSize.Level1) @@ -208,7 +208,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, NormalQuery1, TestSize.Level1) * @tc.name: NormalQuery1 * @tc.desc: test sql len is larger than 100,0000 * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, NormalQuery2, TestSize.Level1) @@ -227,7 +227,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, NormalQuery2, TestSize.Level1) * @tc.name: BoolQuery1 * @tc.desc: Query bool. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, BoolQuery1, TestSize.Level1) @@ -294,7 +294,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, BoolQuery1, TestSize.Level1) * @tc.name: BlobQuery1 * @tc.desc: Query blob. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, BlobQuery1, TestSize.Level1) @@ -341,7 +341,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, BlobQuery1, TestSize.Level1) * @tc.name: InsertQuery1 * @tc.desc: Query with insert statement. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, InsertQuery1, TestSize.Level1) @@ -403,7 +403,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, InsertQuery1, TestSize.Level1) * @tc.name: NonexistentTable1 * @tc.desc: Nonexistent table or column. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, NonexistentTable1, TestSize.Level1) @@ -435,7 +435,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, NonexistentTable1, TestSize.Lev * @tc.name: PreparedStmtSerialize * @tc.desc: Test the serialization and deserialization of PreparedStmt. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, PreparedStmtSerialize, TestSize.Level1) @@ -478,7 +478,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, PreparedStmtSerialize, TestSize * @tc.name: ComplexQuery1 * @tc.desc: Complex query with join or aggregate func. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, ComplexQuery1, TestSize.Level1) @@ -519,7 +519,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, ComplexQuery1, TestSize.Level1) * @tc.name: LargeAmountOfData1 * @tc.desc: Large Amount Of Data. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, LargeAmountOfData1, TestSize.Level1) @@ -572,7 +572,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, LargeAmountOfData1, TestSize.Le * @tc.name: OverSize1 * @tc.desc: Over size. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, OverSize1, TestSize.Level1) @@ -614,7 +614,7 @@ HWTEST_F(DistributedDBRelationalRemoteQueryTest, OverSize1, TestSize.Level1) * @tc.name: RemoteQueryForNotDistributedDb * @tc.desc: Not create distributed table, exec remote query. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalRemoteQueryTest, RemoteQueryForNotDistributedDb, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_result_set_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_result_set_test.cpp index e3b17420..53ab0915 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_result_set_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_result_set_test.cpp @@ -116,7 +116,7 @@ void DistributedDBRelationalResultSetTest::TearDown(void) * @tc.name: SerializeAndDeserialize * @tc.desc: Serialize and deserialize. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalResultSetTest, SerializeAndDeserialize, TestSize.Level1) @@ -189,7 +189,7 @@ HWTEST_F(DistributedDBRelationalResultSetTest, SerializeAndDeserialize, TestSize * @tc.name: Put * @tc.desc: Test put into result set * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalResultSetTest, Put, TestSize.Level1) @@ -225,7 +225,7 @@ HWTEST_F(DistributedDBRelationalResultSetTest, Put, TestSize.Level1) * @tc.name: EmptyResultSet * @tc.desc: Empty result set. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalResultSetTest, EmptyResultSet, TestSize.Level1) @@ -263,7 +263,7 @@ HWTEST_F(DistributedDBRelationalResultSetTest, EmptyResultSet, TestSize.Level1) * @tc.name: NormalResultSet * @tc.desc: Normal result set. * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalResultSetTest, NormalResultSet, TestSize.Level1) @@ -436,4 +436,74 @@ HWTEST_F(DistributedDBRelationalResultSetTest, ResultSetTest002, TestSize.Level0 delete resultSet; } + +/** + * @tc.name: BinlogSupportTest001 + * @tc.desc: Test binlog support API return values as expected + * @tc.type: FUNC + * @tc.require: + * @tc.author: hongyangliu + */ +HWTEST_F(DistributedDBRelationalResultSetTest, BinlogSupportTest001, TestSize.Level0) +{ + EXPECT_EQ(sqlite3_is_support_binlog(nullptr), SQLITE_ERROR); + EXPECT_EQ(sqlite3_is_support_binlog(""), sqlite3_is_support_binlog(" ")); +} + +/** + * @tc.name: CompressSupportTest001 + * @tc.desc: Test sqlite open with different vfs option return values as expected + * @tc.type: FUNC + * @tc.require: + * @tc.author: hongyangliu + */ +HWTEST_F(DistributedDBRelationalResultSetTest, CompressSupportTest001, TestSize.Level0) +{ + sqlite3 *db = nullptr; + uint32_t openOption = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX; + /** + * @tc.steps: step1. sqlite open with both filepath and vfs as null + * @tc.expected: no crash + */ + ASSERT_NO_FATAL_FAILURE(sqlite3_open_v2(nullptr, &db, openOption, nullptr)); + sqlite3_close_v2(db); + db = nullptr; + /** + * @tc.steps: step2. sqlite open with null filepath and random vfs + * @tc.expected: no crash + */ + ASSERT_NO_FATAL_FAILURE(sqlite3_open_v2(nullptr, &db, openOption, "non-exist")); + sqlite3_close_v2(db); + db = nullptr; + /** + * @tc.steps: step3. sqlite open with null filepath and compress vfs + * @tc.expected: no crash + */ + ASSERT_NO_FATAL_FAILURE(sqlite3_open_v2(nullptr, &db, openOption, "compressvfs")); + sqlite3_close_v2(db); + db = nullptr; + /** + * @tc.steps: step4. sqlite open with a regular file with no vfs + * @tc.expected: open ok + */ + EXPECT_EQ(sqlite3_open_v2(g_storePath.c_str(), &db, openOption, nullptr), SQLITE_OK); + sqlite3_close_v2(db); + db = nullptr; + /** + * @tc.steps: step5. sqlite open with a non-whitelist file using compress vfs + * @tc.expected: open ok + */ + std::string nonWhiteDb = g_testDir + "/nonWhiteList.db"; + EXPECT_EQ(sqlite3_open_v2(nonWhiteDb.c_str(), &db, openOption, "compressvfs"), SQLITE_OK); + sqlite3_close_v2(db); + db = nullptr; + /** + * @tc.steps: step6. sqlite open with a whitelist file using compress vfs + * @tc.expected: no crash + */ + std::string whitelistDb = g_testDir + "/test.db"; + ASSERT_NO_FATAL_FAILURE(sqlite3_open_v2(whitelistDb.c_str(), &db, openOption, "compressvfs")); + sqlite3_close_v2(db); + db = nullptr; +} #endif diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_schema_analysis_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_schema_analysis_test.cpp index e96c0eb5..37419b12 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_schema_analysis_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_schema_analysis_test.cpp @@ -113,7 +113,7 @@ TableInfo AnalysisTable(const std::string &name, const std::string &sql) * @tc.name: AnalysisTable001 * @tc.desc: Analysis with table which has one primary key * @tc.type: FUNC - * @tc.require: AR000H2PKN + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBRelationalSchemaAnalysisTest, AnalysisTable001, TestSize.Level1) @@ -126,7 +126,7 @@ HWTEST_F(DistributedDBRelationalSchemaAnalysisTest, AnalysisTable001, TestSize.L * @tc.name: AnalysisTable002 * @tc.desc: Analysis with table which has multi primary key * @tc.type: FUNC - * @tc.require: AR000H2PKN + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBRelationalSchemaAnalysisTest, AnalysisTable002, TestSize.Level1) @@ -139,7 +139,7 @@ HWTEST_F(DistributedDBRelationalSchemaAnalysisTest, AnalysisTable002, TestSize.L * @tc.name: AnalysisTable003 * @tc.desc: Analysis with table which has no primary key * @tc.type: FUNC - * @tc.require: AR000H2PKN + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBRelationalSchemaAnalysisTest, AnalysisTable003, TestSize.Level1) @@ -152,7 +152,7 @@ HWTEST_F(DistributedDBRelationalSchemaAnalysisTest, AnalysisTable003, TestSize.L * @tc.name: AnalysisTable003 * @tc.desc: Analysis with table which has no primary key * @tc.type: FUNC - * @tc.require: AR000H2PKN + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBRelationalSchemaAnalysisTest, AnalysisTable004, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_syncable_storage_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_syncable_storage_test.cpp index f6ebd0ae..ba44c736 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_syncable_storage_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_syncable_storage_test.cpp @@ -19,6 +19,8 @@ #include "distributeddb_tools_unit_test.h" #include "relational_sync_able_storage.h" #include "sqlite_single_relational_storage_engine.h" +#include "sqlite_relational_store_connection.h" +#include "sqlite_relational_utils.h" #include "sqlite_utils.h" using namespace testing::ext; @@ -120,4 +122,104 @@ HWTEST_F(DistributedDBRelationalSyncableStorageTest, SchemaRefTest001, TestSize. RefObject::DecObjRef(syncAbleStorage); EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); } + +/** + * @tc.name: FuncExceptionTest001 + * @tc.desc: Test the interception expection of the delegate interface when the store is empty. + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBRelationalSyncableStorageTest, FuncExceptionTest001, TestSize.Level1) +{ + auto conn = std::make_shared(nullptr); + EXPECT_EQ(conn->Close(), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->GetIdentifier().size(), 0u); + EXPECT_EQ(conn->CreateDistributedTable("", {}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->RemoveDeviceData(), -E_INVALID_CONNECTION); + +#ifdef USE_DISTRIBUTEDB_CLOUD + EXPECT_EQ(conn->GetCloudSyncTaskCount(), -1); + EXPECT_EQ(conn->DoClean({}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->ClearCloudWatermark({}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->SetCloudDB({}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->PrepareAndSetCloudDbSchema({}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->SetIAssetLoader({}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->SetCloudSyncConfig({}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->Sync({}, {}, 0L), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->GetCloudTaskStatus(0u).errCode, DB_ERROR); +#endif + EXPECT_EQ(conn->RemoveDeviceData({}), -E_INVALID_CONNECTION); + std::vector devices; + Query query; + RelationalStoreConnection::SyncInfo syncInfo{devices, {}, nullptr, query, true}; + EXPECT_EQ(conn->SyncToDevice(syncInfo), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->RegisterLifeCycleCallback({}), -E_INVALID_CONNECTION); + std::shared_ptr resultSet = nullptr; + EXPECT_EQ(conn->RemoteQuery({}, {}, 0u, resultSet), -E_INVALID_CONNECTION); + std::string userId; + std::string appId; + std::string storeId; + EXPECT_EQ(conn->GetStoreInfo(userId, appId, storeId), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->SetTrackerTable({}), -E_INVALID_CONNECTION); + std::vector records; + EXPECT_EQ(conn->ExecuteSql({}, records), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->SetReference({}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->CleanTrackerData({}, 0L), -E_INVALID_CONNECTION); + PragmaData pragmaData; + PragmaCmd cmd = AUTO_SYNC; + EXPECT_EQ(conn->Pragma(cmd, pragmaData), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->UpsertData({}, {}, {}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->SetDistributedDbSchema({}, false), -E_INVALID_CONNECTION); + int32_t count; + EXPECT_EQ(conn->GetDownloadingAssetsCount(count), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->SetTableMode({}), -E_INVALID_CONNECTION); + EXPECT_EQ(conn->OperateDataStatus(0u), -E_INVALID_CONNECTION); + conn = nullptr; +} + +/** + * @tc.name: FuncExceptionTest002 + * @tc.desc: Test the interception expection of the delegate interface when the store is empty. + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBRelationalSyncableStorageTest, FuncExceptionTest002, TestSize.Level1) +{ + sqlite3 *db = nullptr; + int64_t timeOffset; + EXPECT_EQ(SQLiteRelationalUtils::GetExistedDataTimeOffset(db, {}, false, timeOffset), -E_INVALID_DB); + std::unique_ptr logMgrPtr = nullptr; + SQLiteRelationalUtils::GenLogParam param; + param.db = db; + EXPECT_EQ(SQLiteRelationalUtils::GeneLogInfoForExistedData({}, {}, logMgrPtr, param), -E_INVALID_DB); + EXPECT_EQ(SQLiteRelationalUtils::SetLogTriggerStatus(db, false), -E_INVALID_DB); + EXPECT_EQ(SQLiteRelationalUtils::InitCursorToMeta(db, false, {}), -E_INVALID_DB); + EXPECT_EQ(SQLiteRelationalUtils::PutKvData(db, false, {}, {}), -E_INVALID_DB); + Value value; + EXPECT_EQ(SQLiteRelationalUtils::GetKvData(db, false, {}, value), -E_INVALID_DB); + EXPECT_EQ(SQLiteRelationalUtils::CreateRelationalMetaTable(db), -E_INVALID_DB); + EXPECT_EQ(SQLiteRelationalUtils::GetCurrentVirtualTime(db).first, -E_INVALID_DB); + int64_t tOffset; + EXPECT_EQ(SQLiteRelationalUtils::GetMetaLocalTimeOffset(db, tOffset), -E_INVALID_DB); + EXPECT_EQ(SQLiteRelationalUtils::OperateDataStatus(db, {}, 0), E_OK); + uint64_t cursor; + EXPECT_EQ(SQLiteRelationalUtils::GetCursor(db, {}, cursor), -E_INVALID_DB); + int64_t count; + EXPECT_EQ(SQLiteRelationalUtils::QueryCount(db, {}, count), -E_INVALID_DB); + + LogInfo logInfo; + EXPECT_EQ(SQLiteRelationalUtils::GetLogInfoPre(nullptr, {}, {}, logInfo), -E_INVALID_ARGS); + DistributedSchema schema; + schema.tables.push_back({STORE_ID, {}}); + schema.tables.push_back({STORE_ID, {}}); + EXPECT_NE(SQLiteRelationalUtils::FilterRepeatDefine(schema).tables.size(), 0u); + EXPECT_EQ(SQLiteRelationalUtils::CheckDistributedSchemaValid({}, {}, false, nullptr), -E_INVALID_ARGS); + auto executor = + std::make_shared(db, true, DistributedTableMode::COLLABORATION); + EXPECT_EQ(SQLiteRelationalUtils::CheckDistributedSchemaValid({}, {}, false, executor.get()), -E_NOT_FOUND); + int32_t localCount = 0; + EXPECT_EQ(executor->GetFlagIsLocalCount("tableName", localCount), -E_INVALID_DB); +} #endif // RELATIONAL_STORE diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_register_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_register_test.cpp index b929172e..6b549353 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_register_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_register_test.cpp @@ -122,7 +122,7 @@ void DistributedDBSqliteRegisterTest::TearDown() * @tc.name: JsonExtract001 * @tc.desc: test json_extract_by_path function in sqlite * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBSqliteRegisterTest, JsonExtract001, TestSize.Level1) @@ -143,7 +143,7 @@ HWTEST_F(DistributedDBSqliteRegisterTest, JsonExtract001, TestSize.Level1) * @tc.name: JsonExtract002 * @tc.desc: test json_extract_by_path function in sqlite * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBSqliteRegisterTest, JsonExtract002, TestSize.Level1) @@ -164,7 +164,7 @@ HWTEST_F(DistributedDBSqliteRegisterTest, JsonExtract002, TestSize.Level1) * @tc.name: JsonExtract003 * @tc.desc: test json_extract_by_path function in sqlite * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBSqliteRegisterTest, JsonExtract003, TestSize.Level1) @@ -185,7 +185,7 @@ HWTEST_F(DistributedDBSqliteRegisterTest, JsonExtract003, TestSize.Level1) * @tc.name: CalcHashValue001 * @tc.desc: test calc_hash_key function in sqlite * @tc.type: FUNC - * @tc.require: AR000DR9K7 + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributedDBSqliteRegisterTest, CalcHashValue001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_utils_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_utils_test.cpp index e8da4e9f..b8fa175c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_utils_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_utils_test.cpp @@ -18,6 +18,7 @@ #include "distributeddb_tools_unit_test.h" #include "native_sqlite.h" #include "platform_specific.h" +#include "sqlite_cloud_kv_executor_utils.h" #include "sqlite_import.h" #include "sqlite_log_table_manager.h" @@ -386,3 +387,42 @@ HWTEST_F(DistributedDBSqliteUtilsTest, AbnormalBranchErrAfterClose, TestSize.Lev EXPECT_EQ(-SQLITE_MISUSE, SQLiteUtils::GetLogTableVersion(g_db, strSchema)); EXPECT_EQ(-SQLITE_MISUSE, SQLiteUtils::CheckTableExists(g_db, tableName, isEmpty)); } + +/** + * @tc.name: AbnormalSqliteCloudKvExecutorUtilsTest001 + * @tc.desc: Test sqlite cloud kv executor utils abnormal + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBSqliteUtilsTest, AbnormalSqliteCloudKvExecutorUtilsTest001, TestSize.Level1) +{ + SqliteCloudKvExecutorUtils cloudKvObj; + sqlite3 *db = nullptr; + CloudSyncData data; + CloudUploadRecorder recorder; + + uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + std::string fileUrl = g_testDir + "/test.db"; + EXPECT_EQ(sqlite3_open_v2(fileUrl.c_str(), &db, flag, nullptr), SQLITE_OK); + ASSERT_NE(db, nullptr); + + data.isCloudVersionRecord = false; + int ret = cloudKvObj.FillCloudLog({db, true}, OpType::INSERT, data, "", recorder); + EXPECT_EQ(ret, -1); // -1 for table not exist + + std::vector dataVector; + ret = cloudKvObj.GetWaitCompensatedSyncDataPk(db, true, dataVector); + EXPECT_NE(ret, E_OK); + std::vector dataUser; + ret = cloudKvObj.GetWaitCompensatedSyncDataUserId(db, true, dataUser); + EXPECT_NE(ret, E_OK); + ret = cloudKvObj.GetWaitCompensatedSyncData(db, true, dataVector, dataUser); + EXPECT_NE(ret, E_OK); + std::vector gid; + std::string user("USER"); + QuerySyncObject query; + ret = cloudKvObj.QueryCloudGid(db, true, user, query, gid); + EXPECT_NE(ret, E_OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_commit_storage_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_commit_storage_test.cpp index 85c0633d..fc3fa50a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_commit_storage_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_commit_storage_test.cpp @@ -330,7 +330,7 @@ void DistributedDBStorageCommitStorageTest::TearDown(void) * @tc.name: MultiVerCommitStorage001 * @tc.desc: Open a commit storage when it has been opened. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage001, TestSize.Level1) @@ -348,7 +348,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage001, TestSi * @tc.name: MultiVerCommitStorage002 * @tc.desc: Remove a commit storage database, then try to add, delete and query commit, set and get header. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage002, TestSize.Level1) @@ -397,7 +397,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage002, TestSi * @tc.name: MultiVerCommitStorage003 * @tc.desc: Insert a commit to commit storage, and get it. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage003, TestSize.Level1) @@ -423,7 +423,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage003, TestSi * @tc.name: MultiVerCommitStorage004 * @tc.desc: Set header of commit storage, and get it. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage004, TestSize.Level1) @@ -455,7 +455,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage004, TestSi * @tc.name: MultiVerCommitStorage005 * @tc.desc: Delete the header commit, test if it can be get, and get the new header. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage005, TestSize.Level1) @@ -513,7 +513,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage005, TestSi * @tc.name: MultiVerCommitStorage006 * @tc.desc: Add commit with empty commit ID, and it will not be added. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage006, TestSize.Level1) @@ -532,7 +532,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage006, TestSi * @tc.name: MultiVerCommitStorage008 * @tc.desc: Add commit with the same commit ID as its left parent, and it will not be added. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage008, TestSize.Level1) @@ -565,7 +565,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage008, TestSi * @tc.name: MultiVerCommitStorage009 * @tc.desc: Add commit with the same commit ID as its right parent, and it will not be added. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage009, TestSize.Level1) @@ -598,7 +598,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage009, TestSi * @tc.name: MultiVerCommitStorage010 * @tc.desc: Add commit whose left parent and right parent is the same, and it will not be added. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage010, TestSize.Level1) @@ -637,7 +637,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage010, TestSi * @tc.name: MultiVerCommitStorage011 * @tc.desc: Add commit with a non exist left parent, and it will not be added. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage011, TestSize.Level1) @@ -662,7 +662,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage011, TestSi * @tc.name: MultiVerCommitStorage012 * @tc.desc: Add commit with a non exist right parent, and it will not be added. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage012, TestSize.Level1) @@ -687,7 +687,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage012, TestSi * @tc.name: MultiVerCommitStorage013 * @tc.desc: Delete a commit which is not header, and it will not be deleted. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage013, TestSize.Level1) @@ -732,7 +732,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage013, TestSi * @tc.name: MultiVerCommitStorage014 * @tc.desc: Set unexist commit to header, and it will not success. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage014, TestSize.Level1) @@ -745,7 +745,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage014, TestSi * @tc.name: MultiVerCommitStorage015 * @tc.desc: SDetermine whether commit exists * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage015, TestSize.Level1) @@ -760,7 +760,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage015, TestSi * @tc.name: MultiVerCommitStorage016 * @tc.desc: Get latest commit of each device from commit storage * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage016, TestSize.Level1) @@ -790,7 +790,7 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage016, TestSi * @tc.name: MultiVerCommitStorage017 * @tc.desc: Get commit tree from commit storage by latest commits * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage017, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp index 81dc4b45..2db7b5d4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp @@ -130,7 +130,7 @@ void DistributedDBStorageDataOperationTest::TearDown(void) * @tc.name: Insert001 * @tc.desc: Insert a record into a distributed db * @tc.type: FUNC - * @tc.require: AR000CQDV8 AR000CQDVB + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageDataOperationTest, Insert001, TestSize.Level1) @@ -169,7 +169,7 @@ HWTEST_F(DistributedDBStorageDataOperationTest, Insert001, TestSize.Level1) * @tc.name: InsertBatch001 * @tc.desc: Insert some records into a distributed db * @tc.type: FUNC - * @tc.require: AR000CQDV9 AR000CQDVE + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageDataOperationTest, InsertBatch001, TestSize.Level1) @@ -221,7 +221,7 @@ HWTEST_F(DistributedDBStorageDataOperationTest, InsertBatch001, TestSize.Level1) * @tc.name: Clear001 * @tc.desc: Clear some records from a distributed db * @tc.type: FUNC - * @tc.require: AR000BVTO6 AR000CQDVA + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageDataOperationTest, Clear001, TestSize.Level1) @@ -289,7 +289,7 @@ HWTEST_F(DistributedDBStorageDataOperationTest, Clear001, TestSize.Level1) * @tc.name: Delete001 * @tc.desc: Delete a record from a distributed db * @tc.type: FUNC - * @tc.require: AR000CQDVF AR000CQDVB + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageDataOperationTest, Delete001, TestSize.Level1) @@ -367,7 +367,7 @@ HWTEST_F(DistributedDBStorageDataOperationTest, Delete001, TestSize.Level1) * @tc.name: DeleteBatch001 * @tc.desc: Delete some records from a distributed db * @tc.type: FUNC - * @tc.require: AR000CQDVG AR000CQDVB + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageDataOperationTest, DeleteBatch001, TestSize.Level1) @@ -503,7 +503,7 @@ static void CheckRecoverData(const Value &savedValue, std::mapRelease(); +} + +/** + * @tc.name: AbnormalPut001 + * @tc.desc: Insert data when the test table does not exist + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageQuerySyncTest, AbnormalPut001, TestSize.Level1) +{ + std::string path = g_testDir + "/TestQuerySync/" + DBConstant::SINGLE_SUB_DIR + "/main/gen_natural_store.db"; + sqlite3 *db = nullptr; + ASSERT_EQ(sqlite3_open_v2(path.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr), SQLITE_OK); + char *errMsg = nullptr; + EXPECT_EQ(sqlite3_exec(db, "DROP TABLE sync_data", nullptr, nullptr, &errMsg), 0); + IOption option; + option.dataType = IOption::SYNC_DATA; + Key key; + Value value; + DistributedDBToolsUnitTest::GetRandomKeyValue(key); + DistributedDBToolsUnitTest::GetRandomKeyValue(value); + EXPECT_NE(g_connection->Put(option, key, value), E_OK); + sqlite3_close(db); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_register_observer_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_register_observer_test.cpp index 4e9b1588..8c9cd0af 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_register_observer_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_register_observer_test.cpp @@ -189,7 +189,7 @@ void DistributedDBStorageRdRegisterObserverTest::TearDown(void) * @tc.name: RegisterObserver001 * @tc.desc: Register a NULL pointer as an observer * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver001, TestSize.Level1) @@ -220,7 +220,7 @@ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver001, TestSi * @tc.name: RegisterObserver010 * @tc.desc: Register an observer for the local sync database change and the local database change of a specified key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver010, TestSize.Level1) @@ -244,7 +244,7 @@ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver010, TestSi * @tc.name: RegisterObserver011 * @tc.desc: Register an observer for the remote sync database change and the local database change of a specified key * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver011, TestSize.Level1) @@ -268,7 +268,7 @@ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver011, TestSi * @tc.name: RegisterObserver012 * @tc.desc: Register an observer for the local sync database change and the local database change of any key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver012, TestSize.Level1) @@ -292,7 +292,7 @@ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver012, TestSi * @tc.name: RegisterObserver013 * @tc.desc: Register an observer for the remote sync database change and the local database change of any key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver013, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_result_and_json_optimize_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_result_and_json_optimize_test.cpp index 68d1d7e8..165df1e9 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_result_and_json_optimize_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_result_and_json_optimize_test.cpp @@ -126,7 +126,7 @@ void DistributedDBStorageRdResultAndJsonOptimizeTest::TearDown(void) * @tc.name: ResultSetOpen001 * @tc.desc: Test the RdSingleVerResultSet Open function * @tc.type: FUNC - * @tc.require: AR000F3OP0 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetOpen001, TestSize.Level1) @@ -166,7 +166,7 @@ HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetOpen001, Test * @tc.name: ResultSetGetCount001 * @tc.desc: Test the RdSingleVerResultSet GetCount function. * @tc.type: FUNC - * @tc.require: AR000F3OP0 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetGetCount001, TestSize.Level1) @@ -199,7 +199,7 @@ HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetGetCount001, * @tc.name: ResultSetMoveTo001 * @tc.desc: Test the RdSingleVerResultSet MoveTo And GetPosition function. * @tc.type: FUNC - * @tc.require: AR000F3OP0 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetMoveTo001, TestSize.Level1) @@ -274,7 +274,7 @@ HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetMoveTo001, Te * @tc.name: ResultSetGetEntry001 * @tc.desc: Test the RdSingleVerResultSet GetEntry function. * @tc.type: FUNC - * @tc.require: AR000F3OP0 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetGetEntry001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_test.cpp index 00d14c38..eaf19025 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_test.cpp @@ -92,7 +92,7 @@ void DistributedDBStorageRdSingleVerNaturalStoreTest::TearDown(void) * @tc.name: SyncDatabaseOperate001 * @tc.desc: To test the function of inserting data of the local device in the synchronization database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate001, TestSize.Level1) @@ -148,7 +148,7 @@ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate001 * @tc.name: SyncDatabaseOperate003 * @tc.desc: test the delete operation in sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate003, TestSize.Level1) @@ -181,7 +181,7 @@ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate003 * @tc.name: SyncDatabaseOperate005 * @tc.desc: test the reading for sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate005, TestSize.Level1) @@ -216,7 +216,7 @@ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate005 * @tc.name: SyncDatabaseOperate006 * @tc.desc: test the get entries for sync database * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate006, TestSize.Level1) @@ -258,5 +258,19 @@ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, ExportBusy001, TestSiz EXPECT_EQ(g_store->Export(g_testDir, password), -E_READ_ONLY); g_store->ReEnableConnection(OperatePerm::NORMAL_WRITE); } + +/** + * @tc.name: GetCloudSyncConfigTest001 + * @tc.desc: Test GetCloudSyncConfig interface of RdSingleVerNaturalStore + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, GetCloudSyncConfigTest001, TestSize.Level1) +{ + ASSERT_NE(g_store, nullptr); + CloudSyncConfig config = g_store->GetCloudSyncConfig(); + EXPECT_EQ(config.isSupportEncrypt, false); +} } #endif // USE_RD_KERNEL \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_testcase.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_testcase.cpp index 9fbd3958..060a6fbf 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_testcase.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_testcase.cpp @@ -31,7 +31,7 @@ namespace { * @tc.name: SyncDatabaseOperate001 * @tc.desc: To test the function of inserting data of the local device in the synchronization database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: huangboxin */ void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate001(RdSingleVerNaturalStore *&store, @@ -46,7 +46,7 @@ void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate001 * @tc.name: SyncDatabaseOperate003 * @tc.desc: test the delete operation in sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: huangboxin */ void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate003(RdSingleVerNaturalStore *&store, @@ -61,7 +61,7 @@ void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate003 * @tc.name: SyncDatabaseOperate005 * @tc.desc: test the reading for sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: huangboxin */ void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate005(RdSingleVerNaturalStore *&store, @@ -76,7 +76,7 @@ void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate005 * @tc.name: SyncDatabaseOperate006 * @tc.desc: test the get entries for sync database * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: huangboxin */ void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate006(RdSingleVerNaturalStore *&store, diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp index 296b6f33..5a7669e7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp @@ -377,7 +377,7 @@ static void SyncDeleteFromDiffDevConflictData(const int deltaTime) * @tc.name: ConflictNotificationTest001 * @tc.desc: Put a non-conflict key and expect no conflict being triggered. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest001, TestSize.Level1) @@ -400,7 +400,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest001, * @tc.name: ConflictNotificationTest002 * @tc.desc: Put a native conflict key and expect native conflict being triggered. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest002, TestSize.Level1) @@ -429,7 +429,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest002, * @tc.name: ConflictNotificationTest003 * @tc.desc: Put a data then delete it. Expect native conflict being triggered. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest003, TestSize.Level1) @@ -458,7 +458,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest003, * @tc.name: ConflictNotificationTest004 * @tc.desc: Sync a data then put a data with the same key. Expect native conflict being triggered. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest004, TestSize.Level1) @@ -491,7 +491,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest004, * @tc.name: ConflictNotificationTest005 * @tc.desc: Get a Sync data then delete it. Expect to see native conflict. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest005, TestSize.Level1) @@ -523,7 +523,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest005, * @tc.name: ConflictNotificationTest006 * @tc.desc: Get a sync data without local key that conflicts with it. Expect to see no conflict. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest006, TestSize.Level1) @@ -546,7 +546,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest006, * @tc.name: ConflictNotificationTest007 * @tc.desc: Sync-sync data conflict. Expect to see foreign conflict and the winner has larger time tag. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest007, TestSize.Level1) @@ -564,7 +564,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest007, * @tc.name: ConflictNotificationTest008 * @tc.desc: Sync-sync data conflict. Expect to see foreign conflict and the winner has larger time tag. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest008, TestSize.Level1) @@ -583,7 +583,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest008, * @tc.desc: Sync a data to the device. Sync another data with the same key and the time tag +DATA_TIME_LAG us. * Expect to see native conflict and the first data being deleted. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest009, TestSize.Level1) @@ -607,7 +607,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest009, * @tc.desc: Sync a data to the device. Sync another data with the same key and the time tag -DATA_TIME_LAG us. * Expect to see native conflict and the second data being deleted. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest010, TestSize.Level1) @@ -630,7 +630,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest010, * @tc.name: ConflictNotificationTest011 * @tc.desc: Sync-sync multi-origin conflict. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest011, TestSize.Level1) @@ -653,7 +653,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest011, * @tc.name: ConflictNotificationTest012 * @tc.desc: Sync-sync multi-origin conflict. * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest012, TestSize.Level1) @@ -675,7 +675,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest012, * @tc.name: ConflictNotificationTest013 * @tc.desc: Sync-sync multi-origin conflict with deleted data * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest013, TestSize.Level1) @@ -698,7 +698,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest013, * @tc.name: ConflictNotificationTest014 * @tc.desc: Sync-sync multi-origin conflict with deleted data * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: maokeheng */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest014, TestSize.Level1) @@ -720,7 +720,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest014, * @tc.name: ConflictNotificationTest015 * @tc.desc: put same record for conflict notification function * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest015, TestSize.Level1) @@ -747,7 +747,7 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest015, * @tc.name: ConflictNotificationTest016 * @tc.desc: put record for conflict notification function * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest016, TestSize.Level1) @@ -811,7 +811,7 @@ namespace { * @tc.name: ConflictNotificationTest017 * @tc.desc: put record for conflict notification function * @tc.type: FUNC - * @tc.require: AR000CQS3U + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest017, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_observer_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_observer_test.cpp index 6bd85113..25f811c1 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_observer_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_observer_test.cpp @@ -329,7 +329,7 @@ void DistributedDBStorageRegisterObserverTest::TearDown(void) * @tc.name: RegisterObserver001 * @tc.desc: Register a NULL pointer as an observer * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver001, TestSize.Level1) @@ -359,7 +359,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver001, TestSize * @tc.name: RegisterObserver002 * @tc.desc: Register an observer for the local database change of a specified key * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver002, TestSize.Level1) @@ -402,7 +402,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver002, TestSize * @tc.name: RegisterObserver003 * @tc.desc: Register an observer for the local sync database change of a specified key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver003, TestSize.Level1) @@ -445,7 +445,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver003, TestSize * @tc.name: RegisterObserver004 * @tc.desc: Register an observer for the remote sync database change of a specified key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver004, TestSize.Level1) @@ -472,7 +472,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver004, TestSize * @tc.name: RegisterObserver005 * @tc.desc: Register an observer for the sync database change of a specified key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver005, TestSize.Level1) @@ -496,7 +496,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver005, TestSize * @tc.name: RegisterObserver006 * @tc.desc: Register an observer for the local database change of any key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver006, TestSize.Level1) @@ -519,7 +519,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver006, TestSize * @tc.name: RegisterObserver007 * @tc.desc: Register an observer for the local sync database change of any key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver007, TestSize.Level1) @@ -542,7 +542,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver007, TestSize * @tc.name: RegisterObserver008 * @tc.desc: Register an observer for the remote sync database change of any key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver008, TestSize.Level1) @@ -565,7 +565,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver008, TestSize * @tc.name: RegisterObserver009 * @tc.desc: Register an observer for the sync database change of any key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver009, TestSize.Level1) @@ -589,7 +589,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver009, TestSize * @tc.name: RegisterObserver010 * @tc.desc: Register an observer for the local sync database change and the local database change of a specified key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver010, TestSize.Level1) @@ -612,7 +612,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver010, TestSize * @tc.name: RegisterObserver011 * @tc.desc: Register an observer for the remote sync database change and the local database change of a specified key * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver011, TestSize.Level1) @@ -635,7 +635,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver011, TestSize * @tc.name: RegisterObserver012 * @tc.desc: Register an observer for the local sync database change and the local database change of any key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver012, TestSize.Level1) @@ -658,7 +658,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver012, TestSize * @tc.name: RegisterObserver013 * @tc.desc: Register an observer for the remote sync database change and the local database change of any key. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver013, TestSize.Level1) @@ -711,7 +711,7 @@ static void PreSyncDataForRegisterObserver014(Timestamp time, vector & * @tc.name: RegisterObserver014 * @tc.desc: Sync multiple records to the sync database * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver014, TestSize.Level1) @@ -781,7 +781,7 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver014, TestSize * @tc.name: RegisterObserver015 * @tc.desc: Sync multiple records to the sync database, and remove them. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: liujialei */ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver015, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_resultset_and_json_optimize.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_resultset_and_json_optimize.cpp index 934a502c..21c97b5d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_resultset_and_json_optimize.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_resultset_and_json_optimize.cpp @@ -127,7 +127,7 @@ void DistributedDBStorageResultAndJsonOptimizeTest::TearDown(void) * @tc.name: ResultSetOpen001 * @tc.desc: Test the SQLiteSingleVerResultSet Open function * @tc.type: FUNC - * @tc.require: AR000F3OP0 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBStorageResultAndJsonOptimizeTest, ResultSetOpen001, TestSize.Level1) @@ -167,7 +167,7 @@ HWTEST_F(DistributedDBStorageResultAndJsonOptimizeTest, ResultSetOpen001, TestSi * @tc.name: ResultSetGetCount001 * @tc.desc: Test the SQLiteSingleVerResultSet GetCount function. * @tc.type: FUNC - * @tc.require: AR000F3OP0 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBStorageResultAndJsonOptimizeTest, ResultSetGetCount001, TestSize.Level1) @@ -200,7 +200,7 @@ HWTEST_F(DistributedDBStorageResultAndJsonOptimizeTest, ResultSetGetCount001, Te * @tc.name: ResultSetMoveTo001 * @tc.desc: Test the SQLiteSingleVerResultSet MoveTo And GetPosition function. * @tc.type: FUNC - * @tc.require: AR000F3OP0 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBStorageResultAndJsonOptimizeTest, ResultSetMoveTo001, TestSize.Level1) @@ -275,7 +275,7 @@ HWTEST_F(DistributedDBStorageResultAndJsonOptimizeTest, ResultSetMoveTo001, Test * @tc.name: ResultSetGetEntry001 * @tc.desc: Test the SQLiteSingleVerResultSet GetEntry function. * @tc.type: FUNC - * @tc.require: AR000F3OP0 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBStorageResultAndJsonOptimizeTest, ResultSetGetEntry001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_natural_store_testcase.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_natural_store_testcase.cpp index 5d7e5381..2298e0e6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_natural_store_testcase.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_natural_store_testcase.cpp @@ -40,7 +40,7 @@ namespace { * @tc.name: GetSyncData001 * @tc.desc: To test the function of querying the data in the time stamp range in the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData001(SQLiteSingleVerNaturalStore *&store, @@ -80,7 +80,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData001(SQLiteSin * @tc.name: GetSyncData002 * @tc.desc: Test the function that the database does not query the data in the time stamp range. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData002(SQLiteSingleVerNaturalStore *&store, @@ -119,7 +119,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData002(SQLiteSin * @tc.desc: To test the function of querying data when the timestamp range * in the data obtaining interface is invalid. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData003(SQLiteSingleVerNaturalStore *&store, @@ -162,7 +162,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData003(SQLiteSin * @tc.name: GetSyncData004 * @tc.desc: To the test database Subcon reading, a large number of data records exist in the time stamp range. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData004(SQLiteSingleVerNaturalStore *&store, @@ -226,7 +226,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData004(SQLiteSin * @tc.desc: In the test database, if a large number of data records exist * in the time stamp range, a packet is read successfully. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData005(SQLiteSingleVerNaturalStore *&store, @@ -264,7 +264,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData005(SQLiteSin * @tc.desc: To test the function of reading data when the time stamp range in the database * is greater than the value of blockSize. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData006(SQLiteSingleVerNaturalStore *&store, @@ -301,7 +301,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetSyncData006(SQLiteSin * @tc.name: PutSyncData001 * @tc.desc: To test the function of synchronizing the new data of the remote device that synchronizes the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::PutSyncData001(SQLiteSingleVerNaturalStore *&store, @@ -396,7 +396,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::PutSyncData001(SQLiteSin * @tc.desc: To test the function of synchronizing data from the remote device * to the local device after the data is deleted from the remote device. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::PutSyncData002(SQLiteSingleVerNaturalStore *&store, @@ -480,7 +480,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::PutSyncData002(SQLiteSin * @tc.desc: To test the function of synchronizing the mixed data of the added * and deleted data from the remote device to the local device. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::PutSyncData003(SQLiteSingleVerNaturalStore *&store, @@ -558,7 +558,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::PutSyncData003(SQLiteSin * @tc.name: PutMetaData001 * @tc.desc: Test metadata insertion and modification. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::PutMetaData001(SQLiteSingleVerNaturalStore *&store, @@ -571,7 +571,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::PutMetaData001(SQLiteSin * @tc.name: GetMetaData001 * @tc.desc: To test the function of reading the metadata of a key in the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetMetaData001(SQLiteSingleVerNaturalStore *&store, @@ -589,7 +589,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetMetaData001(SQLiteSin * @tc.name: DeleteMetaData001 * @tc.desc: To test the function of deleting the metadata with prefix key in the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteMetaData001(SQLiteSingleVerNaturalStore *&store, @@ -607,7 +607,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteMetaData001(SQLite * @tc.name: GetCurrentMaxTimestamp001 * @tc.desc: To test the function of obtaining the maximum timestamp when a record exists in the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetCurrentMaxTimestamp001(SQLiteSingleVerNaturalStore *&store, @@ -652,7 +652,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetCurrentMaxTimestamp00 * @tc.name: GetCurrentMaxTimestamp002 * @tc.desc: Obtain the maximum timestamp when no record exists in the test record library. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetCurrentMaxTimestamp002(SQLiteSingleVerNaturalStore *&store) @@ -670,7 +670,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::GetCurrentMaxTimestamp00 * @tc.name: LocalDatabaseOperate001 * @tc.desc: Test the function of inserting data in the local database of the NaturalStore. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::LocalDatabaseOperate001(SQLiteSingleVerNaturalStore *&store, @@ -685,7 +685,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::LocalDatabaseOperate001( * @tc.name: LocalDatabaseOperate002 * @tc.desc: Test the function of deleting data from the local database of the NaturalStore. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::LocalDatabaseOperate002(SQLiteSingleVerNaturalStore *&store, @@ -700,7 +700,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::LocalDatabaseOperate002( * @tc.name: LocalDatabaseOperate003 * @tc.desc: To test the function of reading data from the local database of the NaturalStore. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::LocalDatabaseOperate003(SQLiteSingleVerNaturalStore *&store, @@ -715,7 +715,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::LocalDatabaseOperate003( * @tc.name: SyncDatabaseOperate001 * @tc.desc: To test the function of inserting data of the local device in the synchronization database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate001(SQLiteSingleVerNaturalStore *&store, @@ -730,7 +730,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate001(S * @tc.name: SyncDatabaseOperate002 * @tc.desc: test the put operation after data synced from other devices. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate002(SQLiteSingleVerNaturalStore *&store, @@ -780,7 +780,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate002(S * @tc.name: SyncDatabaseOperate003 * @tc.desc: test the delete operation in sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate003(SQLiteSingleVerNaturalStore *&store, @@ -795,7 +795,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate003(S * @tc.name: SyncDatabaseOperate004 * @tc.desc: test the delete for the data from other devices in sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate004(SQLiteSingleVerNaturalStore *&store, @@ -842,7 +842,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate004(S * @tc.name: SyncDatabaseOperate005 * @tc.desc: test the reading for sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate005(SQLiteSingleVerNaturalStore *&store, @@ -857,7 +857,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate005(S * @tc.name: SyncDatabaseOperate006 * @tc.desc: test the get entries for sync database * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate006(SQLiteSingleVerNaturalStore *&store, @@ -918,7 +918,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::SyncDatabaseOperate006(S * @tc.name: ClearRemoteData001 * @tc.desc: test the clear data synced from the remote by device. * @tc.type: FUNC - * @tc.require: AR000CIFDA AR000CQS3T + * @tc.require: * @tc.author: wangbingquan */ void DistributedDBStorageSingleVerNaturalStoreTestCase::ClearRemoteData001(SQLiteSingleVerNaturalStore *&store, @@ -988,7 +988,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::ClearRemoteData001(SQLit * @tc.name: DeleteUserKeyValue001 * @tc.desc: When a user deletes a data record, the system clears the user record. * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue001(SQLiteSingleVerNaturalStore *&store, @@ -1032,7 +1032,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue001(SQ * @tc.name: MemoryDbDeleteUserKeyValue001 * @tc.desc: When a user deletes a data record, the system clears the user record. * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::MemoryDbDeleteUserKeyValue001( @@ -1076,7 +1076,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::MemoryDbDeleteUserKeyVal * @tc.name: DeleteUserKeyValue002 * @tc.desc: After the synchronization library data is deleted locally, add the same key data locally. * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue002(SQLiteSingleVerNaturalStore *&store, @@ -1123,7 +1123,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue002(SQ * @tc.name: DeleteUserKeyValue003 * @tc.desc: After the synchronization database data is deleted locally, the same key data is added from the remote end. * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue003(SQLiteSingleVerNaturalStore *&store, @@ -1206,7 +1206,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue003(SQ * @tc.name: DeleteUserKeyValue004 * @tc.desc: Changes in key after remote delete data syncs to local * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue004(SQLiteSingleVerNaturalStore *&store, @@ -1255,7 +1255,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue004(SQ * @tc.name: MemoryDbDeleteUserKeyValue004 * @tc.desc: Changes in key after remote delete data syncs to local * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::MemoryDbDeleteUserKeyValue004( @@ -1301,7 +1301,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::MemoryDbDeleteUserKeyVal * @tc.name: DeleteUserKeyValue005 * @tc.desc: New unified key data locally after remote delete data syncs to local * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue005(SQLiteSingleVerNaturalStore *&store, @@ -1358,7 +1358,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue005(SQ * @tc.name: MemoryDbDeleteUserKeyValue005 * @tc.desc: New unified key data locally after remote delete data syncs to local * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::MemoryDbDeleteUserKeyValue005( @@ -1413,7 +1413,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::MemoryDbDeleteUserKeyVal * @tc.desc: After the remote delete data is synced to the local, * the same key data is added from the remote other devices * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ void DistributedDBStorageSingleVerNaturalStoreTestCase::DeleteUserKeyValue006(SQLiteSingleVerNaturalStore *&store, diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_upgrade_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_upgrade_test.cpp index 9603da7e..6f87fad2 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_upgrade_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_upgrade_test.cpp @@ -327,7 +327,7 @@ void DistributedDBStorageSingleVerUpgradeTest::TearDown(void) * @tc.name: UpgradeTest001 * @tc.desc: Test the NbDelegate upgrade from the old version V1. * @tc.type: FUNC - * @tc.require: AR000DPTQ7 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest001, TestSize.Level0) @@ -373,7 +373,7 @@ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest001, TestSize.Leve * @tc.name: UpgradeTest002 * @tc.desc: Test the NbDelegate upgrade from the old version V2. * @tc.type: FUNC - * @tc.require: AR000DPTQ7 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest002, TestSize.Level2) @@ -418,7 +418,7 @@ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest002, TestSize.Leve * @tc.name: UpgradeTest003 * @tc.desc: Test the NbDelegate upgrade from the old version V2 with schema. * @tc.type: FUNC - * @tc.require: AR000DPTQ7 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest003, TestSize.Level2) @@ -480,7 +480,7 @@ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest003, TestSize.Leve * @tc.name: UpgradeTest004 * @tc.desc: Test the NbDelegate upgrade from the old version V2 while secOption from NOT_SET to S3SECE. * @tc.type: FUNC - * @tc.require: AR000DPTQ7 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest004, TestSize.Level2) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp index 1103b7aa..7e976f91 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp @@ -793,7 +793,11 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, PragmaTest001, EXPECT_EQ(g_connection->Pragma(PRAGMA_PUBLISH_LOCAL, nullptr), -E_INVALID_ARGS); EXPECT_EQ(g_connection->Pragma(PRAGMA_GET_DEVICE_IDENTIFIER_OF_ENTRY, nullptr), -E_INVALID_ARGS); EXPECT_EQ(g_connection->Pragma(PRAGMA_SET_MAX_LOG_LIMIT, nullptr), -E_INVALID_ARGS); + uint64_t val = 0x400000ULL; + PragmaData logLimit = static_cast(&val); + EXPECT_EQ(g_connection->Pragma(PRAGMA_SET_MAX_LOG_LIMIT, logLimit), OK); EXPECT_EQ(g_connection->Pragma(PRAGMA_GET_IDENTIFIER_OF_DEVICE, nullptr), -E_INVALID_ARGS); + EXPECT_EQ(g_connection->Pragma(PRAGMA_SET_MAX_LOG_LIMIT, logLimit), OK); /** * @tc.steps: step2. the option is invalid diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_store_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_store_test.cpp index 4f428d68..95fd5dae 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_store_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_store_test.cpp @@ -92,7 +92,7 @@ void DistributedDBStorageSQLiteSingleVerNaturalStoreTest::TearDown(void) * @tc.name: GetSyncData001 * @tc.desc: To test the function of querying the data in the time stamp range in the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData001, TestSize.Level1) @@ -110,7 +110,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData001, Te * @tc.name: GetSyncData002 * @tc.desc: Test the function that the database does not query the data in the time stamp range. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData002, TestSize.Level1) @@ -130,7 +130,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData002, Te * @tc.desc: To test the function of querying data when the timestamp range * in the data obtaining interface is invalid. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData003, TestSize.Level1) @@ -147,7 +147,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData003, Te * @tc.name: GetSyncData004 * @tc.desc: To the test database Subcon reading, a large number of data records exist in the time stamp range. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData004, TestSize.Level1) @@ -171,7 +171,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData004, Te * @tc.desc: In the test database, if a large number of data records exist * in the time stamp range, a packet is read successfully. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData005, TestSize.Level1) @@ -189,7 +189,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData005, Te * @tc.desc: To test the function of reading data when the time stamp range in the database * is greater than the value of blockSize. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData006, TestSize.Level1) @@ -206,7 +206,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetSyncData006, Te * @tc.name: PutSyncData001 * @tc.desc: To test the function of synchronizing the new data of the remote device that synchronizes the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, PutSyncData001, TestSize.Level1) @@ -253,7 +253,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, PutSyncData001, Te * @tc.desc: To test the function of synchronizing data from the remote device * to the local device after the data is deleted from the remote device. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, PutSyncData002, TestSize.Level1) @@ -291,7 +291,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, PutSyncData002, Te * @tc.desc: To test the function of synchronizing the mixed data of the added * and deleted data from the remote device to the local device. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, PutSyncData003, TestSize.Level1) @@ -323,7 +323,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, PutSyncData003, Te * @tc.name: PutMetaData001 * @tc.desc: Test metadata insertion and modification. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, PutMetaData001, TestSize.Level1) @@ -376,7 +376,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, PutMetaData001, Te * @tc.name: GetMetaData001 * @tc.desc: To test the function of reading the metadata of a key in the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetMetaData001, TestSize.Level1) @@ -429,7 +429,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetMetaData001, Te * @tc.name: DeleteMetaData001 * @tc.desc: * @tc.name: To test the function of deleting the metadata with prefix key in the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteMetaData001, TestSize.Level1) @@ -454,7 +454,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteMetaData001, * @tc.name: GetCurrentMaxTimestamp001 * @tc.desc: To test the function of obtaining the maximum timestamp when a record exists in the database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetCurrentMaxTimestamp001, TestSize.Level1) @@ -479,7 +479,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetCurrentMaxTimes * @tc.name: GetCurrentMaxTimestamp002 * @tc.desc: Obtain the maximum timestamp when no record exists in the test record library. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetCurrentMaxTimestamp002, TestSize.Level1) @@ -495,7 +495,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, GetCurrentMaxTimes * @tc.name: LocalDatabaseOperate001 * @tc.desc: Test the function of inserting data in the local database of the NaturalStore. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, LocalDatabaseOperate001, TestSize.Level1) @@ -551,7 +551,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, LocalDatabaseOpera * @tc.name: LocalDatabaseOperate002 * @tc.desc: Test the function of deleting data from the local database of the NaturalStore. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, LocalDatabaseOperate002, TestSize.Level1) @@ -607,7 +607,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, LocalDatabaseOpera * @tc.name: LocalDatabaseOperate003 * @tc.desc: To test the function of reading data from the local database of the NaturalStore. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, LocalDatabaseOperate003, TestSize.Level1) @@ -663,7 +663,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, LocalDatabaseOpera * @tc.name: SyncDatabaseOperate001 * @tc.desc: To test the function of inserting data of the local device in the synchronization database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperate001, TestSize.Level1) @@ -719,7 +719,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperat * @tc.name: SyncDatabaseOperate002 * @tc.desc: test the put operation after data synced from other devices. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperate002, TestSize.Level1) @@ -746,7 +746,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperat * @tc.name: SyncDatabaseOperate003 * @tc.desc: test the delete operation in sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperate003, TestSize.Level1) @@ -779,7 +779,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperat * @tc.name: SyncDatabaseOperate004 * @tc.desc: test the delete for the data from other devices in sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperate004, TestSize.Level1) @@ -803,7 +803,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperat * @tc.name: SyncDatabaseOperate005 * @tc.desc: test the reading for sync database. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperate005, TestSize.Level1) @@ -838,7 +838,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperat * @tc.name: SyncDatabaseOperate006 * @tc.desc: test the get entries for sync database * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperate006, TestSize.Level1) @@ -869,7 +869,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, SyncDatabaseOperat * @tc.name: ClearRemoteData001 * @tc.desc: test the clear data synced from the remote by device. * @tc.type: FUNC - * @tc.require: AR000CIFDA AR000CQS3T + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, ClearRemoteData001, TestSize.Level1) @@ -899,7 +899,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, ClearRemoteData001 * @tc.name: DeleteUserKeyValue001 * @tc.desc: When a user deletes a data record, the system clears the user record. * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue001, TestSize.Level1) @@ -920,7 +920,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue * @tc.name: DeleteUserKeyValue002 * @tc.desc: After the synchronization library data is deleted locally, add the same key data locally. * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue002, TestSize.Level1) @@ -949,7 +949,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue * @tc.name: DeleteUserKeyValue003 * @tc.desc: After the synchronization database data is deleted locally, the same key data is added from the remote end. * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue003, TestSize.Level1) @@ -990,7 +990,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue * @tc.name: DeleteUserKeyValue004 * @tc.desc: Changes in key after remote delete data syncs to local * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue004, TestSize.Level1) @@ -1014,7 +1014,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue * @tc.name: DeleteUserKeyValue005 * @tc.desc: New unified key data locally after remote delete data syncs to local * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue005, TestSize.Level1) @@ -1043,7 +1043,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue * @tc.desc: After the remote delete data is synced to the local, * the same key data is added from the remote other devices * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: sunpeng */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue006, TestSize.Level1) @@ -1083,7 +1083,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, DeleteUserKeyValue * @tc.name: EraseDeviceWaterMark001 * @tc.desc: Test erase water mark * @tc.type: FUNC - * @tc.require: AR000CKRTC AR000CQE0D + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, EraseDeviceWaterMark001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_storage_engine_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_storage_engine_test.cpp index 5b8da298..c6b7495a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_storage_engine_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_storage_engine_test.cpp @@ -17,7 +17,10 @@ #include "db_common.h" #include "distributeddb_storage_single_ver_natural_store_testcase.h" +#include "process_system_api_adapter_impl.h" +#include "single_ver_utils.h" #include "storage_engine_manager.h" +#include "virtual_sqlite_storage_engine.h" using namespace testing::ext; using namespace DistributedDB; @@ -51,6 +54,51 @@ namespace { static_cast(StorageEngineManager::GetStorageEngine(g_property, errCode)); EXPECT_EQ(errCode, E_OK); } + + void PrepareEnv() + { + sqlite3 *db; + ASSERT_TRUE(sqlite3_open_v2((g_testDir + g_databaseName).c_str(), + &db, SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr) == SQLITE_OK); + ASSERT_TRUE(SQLiteUtils::ExecuteRawSQL(db, ADD_SYNC) == E_OK); + ASSERT_TRUE(SQLiteUtils::ExecuteRawSQL(db, INSERT_SQL) == E_OK); + sqlite3_close_v2(db); + } + + OpenDbProperties GetProperties(bool isMem, const SecurityOption &option, bool createIfNecessary) + { + OpenDbProperties properties; + properties.uri = DistributedDB::GetDatabasePath(g_property); + properties.createIfNecessary = createIfNecessary; + properties.subdir = DistributedDB::GetSubDirPath(g_property); + properties.isMemDb = isMem; + properties.securityOpt = option; + return properties; + } + + int InitVirtualEngine(const std::shared_ptr &engine, + bool isMem, const SecurityOption &option, bool createIfNecessary, const StorageEngineAttr &poolSize) + { + auto properties = GetProperties(isMem, option, createIfNecessary); + return engine->InitSQLiteStorageEngine(poolSize, properties, ""); + } + + std::pair> GetVirtualEngineWithSecurity( + uint32_t maxRead, bool isMem, const SecurityOption &option, bool createIfNecessary) + { + std::pair> res; + auto &[errCode, engine] = res; + engine = std::make_shared(); + StorageEngineAttr poolSize = {1, 1, 1, maxRead}; // at most 1 write. + errCode = InitVirtualEngine(engine, isMem, option, createIfNecessary, poolSize); + return res; + } + + std::pair> GetVirtualEngine(uint32_t maxRead = 1, + bool isMem = false, bool createIfNecessary = false) + { + return GetVirtualEngineWithSecurity(maxRead, isMem, {}, createIfNecessary); + } } class DistributedDBStorageSQLiteSingleVerStorageEngineTest : public testing::Test { @@ -106,6 +154,7 @@ void DistributedDBStorageSQLiteSingleVerStorageEngineTest::TearDown(void) g_connection = nullptr; } g_store = nullptr; + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); } /** @@ -221,3 +270,327 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, DataTest003, Test invalidConnection = nullptr; ASSERT_EQ(invalidConnection, nullptr); } + +/** + * @tc.name: ExecutorTest001 + * @tc.desc: Test find executor after disable engine + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest001, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + SQLiteSingleVerStorageEngine *storageEngine = nullptr; + GetStorageEngine(storageEngine); + ASSERT_NE(storageEngine, nullptr); + EXPECT_EQ(storageEngine->TryToDisable(false), E_OK); + int errCode = E_OK; + EXPECT_EQ(storageEngine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode), nullptr); + storageEngine->Release(); + storageEngine = nullptr; +} + +/** + * @tc.name: ExecutorTest002 + * @tc.desc: Test find executor success + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest002, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + SQLiteSingleVerStorageEngine *storageEngine = nullptr; + GetStorageEngine(storageEngine); + int errCode = E_OK; + auto executor1 = storageEngine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode); + EXPECT_NE(executor1, nullptr); + auto executor2 = storageEngine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode); + EXPECT_NE(executor2, nullptr); + storageEngine->Recycle(executor1); + storageEngine->Recycle(executor2); + EXPECT_EQ(storageEngine->FindExecutor(false, OperatePerm::DISABLE_PERM, errCode), nullptr); + storageEngine->Release(); + storageEngine = nullptr; +} + +/** + * @tc.name: ExecutorTest003 + * @tc.desc: Test find executor abnormal + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest003, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + auto [errCode, engine] = GetVirtualEngine(); + ASSERT_EQ(errCode, E_OK); + auto executor1 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 0); + EXPECT_NE(executor1, nullptr); + auto executor2 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 0); + EXPECT_EQ(executor2, nullptr); + engine->Recycle(executor1); + engine->Release(); +} + +/** + * @tc.name: ExecutorTest004 + * @tc.desc: Test find executor abnormal + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest004, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + auto [errCode, engine] = GetVirtualEngine(3); // max read is 3 + ASSERT_EQ(errCode, E_OK); + auto mockFunc = [](bool, StorageExecutor *&handle) { + handle = nullptr; + return -E_EKEYREVOKED; + }; + auto executor0 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 0); + EXPECT_NE(executor0, nullptr); + /** + * @tc.steps:step1. create new handle with mock func + * @tc.expected: step1. create failed. + */ + engine->ForkNewExecutorMethod(mockFunc); + auto executor1 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 0); + EXPECT_EQ(executor1, nullptr); + EXPECT_EQ(errCode, -E_BUSY); + /** + * @tc.steps:step2. create new handle with normal func + * @tc.expected: step2. create ok. + */ + engine->ForkNewExecutorMethod(nullptr); + executor1 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 0); + EXPECT_NE(executor1, nullptr); + /** + * @tc.steps:step3. create new handle with mock func + * @tc.expected: step3. create failed. + */ + engine->ForkNewExecutorMethod([](bool, StorageExecutor *&handle) { + handle = nullptr; + return -E_BUSY; + }); + auto executor2 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 0); + EXPECT_EQ(executor2, nullptr); + engine->Recycle(executor1); + engine->Recycle(executor0); + engine->Release(); +} + +/** + * @tc.name: ExecutorTest005 + * @tc.desc: Test find executor abnormal + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest005, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + auto [errCode, engine] = GetVirtualEngine(2); // max read is 2 + ASSERT_EQ(errCode, E_OK); + engine->SetEnhance(true); + /** + * @tc.steps:step1. create new handle without mock func + * @tc.expected: step1. create ok. + */ + auto executor0 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 0); + EXPECT_NE(executor0, nullptr); + /** + * @tc.steps:step2. create new handle with mock func, mock func will release executor + * @tc.expected: step2. create fail. + */ + engine->ForkNewExecutorMethod([executor = executor0, enginePtr = engine](bool, StorageExecutor *&handle) { + StorageExecutor *executorPtr = executor; + enginePtr->Recycle(executorPtr); + handle = nullptr; + return -E_EKEYREVOKED; + }); + auto executor1 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 0); + EXPECT_EQ(executor1, nullptr); + engine->Release(); + engine->ForkNewExecutorMethod(nullptr); +} + +/** + * @tc.name: ExecutorTest006 + * @tc.desc: Test find executor abnormal when get executor timeout and operate abort + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest006, TestSize.Level4) +{ + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + auto [errCode, engine] = GetVirtualEngine(1); // max read is 1 + ASSERT_EQ(errCode, E_OK); + /** + * @tc.steps:step1. create new handle + * @tc.expected: step1. create ok. + */ + auto executor0 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode); + EXPECT_NE(executor0, nullptr); + /** + * @tc.steps:step2. create new handle again + * @tc.expected: step2. create failed by timeout. + */ + auto executor1 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 1); // max wait 1s + EXPECT_EQ(executor1, nullptr); + /** + * @tc.steps:step3. create new handle again and async mark operate abort + * @tc.expected: step3. create failed by operate abort. + */ + std::thread t([enginePtr = engine]() { + std::this_thread::sleep_for(std::chrono::seconds(1)); + enginePtr->Abort(); + }); + executor1 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode, false, 5); // max wait 5s + EXPECT_EQ(executor1, nullptr); + t.join(); + engine->Recycle(executor0); + engine->Release(); +} + +/** + * @tc.name: ExecutorTest007 + * @tc.desc: Test diff executor pool will not recycle others pool's executor + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest007, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + auto [errCode, engine1] = GetVirtualEngine(1); // max read is 1 + ASSERT_EQ(errCode, E_OK); + auto [ret, engine2] = GetVirtualEngine(1); // max read is 1 + ASSERT_EQ(ret, E_OK); + /** + * @tc.steps:step1. create new handle + * @tc.expected: step1. create ok. + */ + auto executor1 = engine1->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode); + EXPECT_NE(executor1, nullptr); + /** + * @tc.steps:step2. create new handle + * @tc.expected: step2. create ok. + */ + auto tmp = executor1; + engine2->Recycle(tmp); + engine1->Recycle(executor1); + EXPECT_EQ(executor1, nullptr); + engine1->Release(); + engine2->Release(); +} + +/** + * @tc.name: ExecutorTest008 + * @tc.desc: Test mem executor pool + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest008, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + auto [errCode, engine1] = GetVirtualEngine(1, true); // max read is 1 + /** + * @tc.steps:step1. create new handle + * @tc.expected: step1. create ok. + */ + auto executor1 = engine1->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode); + EXPECT_NE(executor1, nullptr); + engine1->Recycle(executor1); + engine1->CallSetSQL({}); + engine1->Release(); +} + +/** + * @tc.name: ExecutorTest009 + * @tc.desc: Test cache executor pool + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest009, TestSize.Level0) +{ + auto systemApi = std::make_shared(); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(systemApi); + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + SecurityOption option = {S3, SECE}; + auto [errCode, engine] = GetVirtualEngineWithSecurity(2, false, option, true); // max read is 2 + /** + * @tc.steps:step1. create new handle + * @tc.expected: step1. create ok. + */ + auto executor1 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode); + EXPECT_NE(executor1, nullptr); + /** + * @tc.steps:step2. create new handle with fork open main failed + * @tc.expected: step2. create failed because of read handle was not allowed. + */ + engine->ForkOpenMainDatabaseMethod([executor1, enginePtr = engine](bool, sqlite3 *&db, OpenDbProperties &) { + StorageExecutor *executor = executor1; + enginePtr->Recycle(executor); + db = nullptr; + return -E_EKEYREVOKED; + }); + auto executor2 = engine->FindExecutor(false, OperatePerm::NORMAL_PERM, errCode); + EXPECT_EQ(executor2, nullptr); + engine->ForkOpenMainDatabaseMethod(nullptr); + engine->Recycle(executor2); + engine->Release(); +} + +/** + * @tc.name: ExecutorTest010 + * @tc.desc: Test cache executor pool + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, ExecutorTest010, TestSize.Level0) +{ + auto systemApi = std::make_shared(); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(systemApi); + ASSERT_NO_FATAL_FAILURE(PrepareEnv()); + CopyCacheDb(); + SecurityOption option = {S3, SECE}; + auto [errCode, engine] = GetVirtualEngineWithSecurity(2, false, option, true); // max read is 2 + ASSERT_EQ(errCode, E_OK); + /** + * @tc.steps:step1. create new handle with create if necessary + * @tc.expected: step1. create ok. + */ + auto properties = GetProperties(false, option, true); + auto [ret, handle] = engine->GetCacheHandle(properties); + EXPECT_EQ(ret, E_OK); + if (handle != nullptr) { + EXPECT_EQ(sqlite3_close_v2(handle), SQLITE_OK); + } + /** + * @tc.steps:step2. create new handle without create if necessary + * @tc.expected: step2. create ok. + */ + properties = GetProperties(false, option, false); + std::tie(ret, handle) = engine->GetCacheHandle(properties); + EXPECT_EQ(ret, E_OK); + if (handle != nullptr) { + EXPECT_EQ(sqlite3_close_v2(handle), SQLITE_OK); + } + /** + * @tc.steps:step3. create new handle without create if necessary and dir was removed + * @tc.expected: step3. create failed. + */ + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); + properties.createIfNecessary = false; + std::tie(ret, handle) = engine->GetCacheHandle(properties); + EXPECT_EQ(ret, -E_INVALID_DB); + engine->Release(); +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp index b03b1886..7a3079c2 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp @@ -217,7 +217,7 @@ void DistributedDBStorageSubscribeQueryTest::TearDown() * @tc.name: CheckAndInitQueryCondition001 * @tc.desc: Check the condition is legal or not with json schema * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, CheckAndInitQueryCondition001, TestSize.Level1) @@ -280,7 +280,7 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, CheckAndInitQueryCondition001, * @tc.name: CheckAndInitQueryCondition002 * @tc.desc: Check the condition always illegal with flatbuffer schema * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, CheckAndInitQueryCondition002, TestSize.Level1) @@ -318,7 +318,7 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, CheckAndInitQueryCondition002, * @tc.name: CheckAndInitQueryCondition003 * @tc.desc: Check the condition always illegal with flatbuffer schema * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, CheckAndInitQueryCondition003, TestSize.Level1) @@ -361,7 +361,7 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, CheckAndInitQueryCondition003, * @tc.name: PutSyncDataTestWithQuery * @tc.desc: put remote devices sync data(get by query sync or subscribe) with query. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery, TestSize.Level1) @@ -414,7 +414,7 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery, TestS * @tc.name: PutSyncDataTestWithQuery002 * @tc.desc: put remote devices sync data(timestamp is smaller then DB data) with query. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery002, TestSize.Level1) @@ -472,7 +472,7 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery002, Te * @tc.name: PutSyncDataTestWithQuery003 * @tc.desc: put remote devices sync data(with same timestamp in DB data but different devices) with query. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery003, TestSize.Level1) @@ -529,7 +529,7 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery003, Te * @tc.name: PutSyncDataTestWithQuery004 * @tc.desc: put remote devices sync data(with same timestamp in DB data but different devices) with query. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery004, TestSize.Level1) @@ -585,7 +585,7 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, PutSyncDataTestWithQuery004, Te * @tc.name: AddSubscribeTest001 * @tc.desc: Add subscribe with query * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, AddSubscribeTest001, TestSize.Level1) @@ -640,7 +640,7 @@ HWTEST_F(DistributedDBStorageSubscribeQueryTest, AddSubscribeTest001, TestSize.L * @tc.name: AddSubscribeTest002 * @tc.desc: Add subscribe with same query not failed * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xulianhui */ HWTEST_F(DistributedDBStorageSubscribeQueryTest, AddSubscribeTest002, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_transaction_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_transaction_data_test.cpp index ac6beeb3..68b0b397 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_transaction_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_transaction_data_test.cpp @@ -293,7 +293,7 @@ void DistributedDBStorageTransactionDataTest::TearDown(void) * @tc.name: StorageInsert001 * @tc.desc: Put the non-empty key, non-empty value into the database. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsert001, TestSize.Level1) @@ -335,7 +335,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsert001, TestSize.Lev * @tc.name: StorageInsert002 * @tc.desc: Put the empty key, non-empty value into the database. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsert002, TestSize.Level1) @@ -354,7 +354,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsert002, TestSize.Lev * @tc.name: StorageInsert003 * @tc.desc: Put the non-empty key, empty value into the database. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsert003, TestSize.Level1) @@ -380,7 +380,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsert003, TestSize.Lev * @tc.name: StorageUpdate001 * @tc.desc: Update the value to non-empty * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdate001, TestSize.Level1) @@ -410,7 +410,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdate001, TestSize.Lev * @tc.name: StorageUpdate002 * @tc.desc: Update the value to empty * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdate002, TestSize.Level1) @@ -439,7 +439,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdate002, TestSize.Lev * @tc.name: StorageDelete001 * @tc.desc: Delete the existed data * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDelete001, TestSize.Level1) @@ -466,7 +466,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDelete001, TestSize.Lev * @tc.name: StorageDelete002 * @tc.desc: Delete the non-existed data * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDelete002, TestSize.Level1) @@ -490,7 +490,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDelete002, TestSize.Lev * @tc.name: StorageDelete003 * @tc.desc: Delete the invalid key data * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDelete003, TestSize.Level1) @@ -507,7 +507,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDelete003, TestSize.Lev * @tc.name: StorageClear001 * @tc.desc: Clear the data * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageClear001, TestSize.Level1) @@ -535,7 +535,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageClear001, TestSize.Leve * @tc.name: StorageInsertBatch001 * @tc.desc: Put the valid batch data * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsertBatch001, TestSize.Level1) @@ -565,7 +565,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsertBatch001, TestSiz * @tc.name: StorageInsertBatch002 * @tc.desc: Put the partially valid batch data * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsertBatch002, TestSize.Level1) @@ -593,7 +593,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageInsertBatch002, TestSiz * @tc.name: StorageUpdateBatch001 * @tc.desc: Update the batch data * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdateBatch001, TestSize.Level1) @@ -633,7 +633,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdateBatch001, TestSiz * @tc.name: StorageUpdateBatch002 * @tc.desc: Update the batch data(partially invalid data) * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdateBatch002, TestSize.Level1) @@ -675,7 +675,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageUpdateBatch002, TestSiz * @tc.name: StorageDeleteBatch001 * @tc.desc: Delete the batch data * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDeleteBatch001, TestSize.Level1) @@ -711,7 +711,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDeleteBatch001, TestSiz * @tc.name: StorageDeleteBatch002 * @tc.desc: Delete the batch data(partially non-existed) * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDeleteBatch002, TestSize.Level1) @@ -749,7 +749,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDeleteBatch002, TestSiz * @tc.name: StorageDeleteBatch003 * @tc.desc: Delete the batch data(partially invalid) * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDeleteBatch003, TestSize.Level1) @@ -787,7 +787,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageDeleteBatch003, TestSiz * @tc.name: StorageTransactionCombo001 * @tc.desc: Multiple operation within the transaction * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageTransactionCombo001, TestSize.Level1) @@ -853,7 +853,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, StorageTransactionCombo001, Te * @tc.name: TransactionRollback001 * @tc.desc: Multiple operation within the transaction * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionRollback001, TestSize.Level1) @@ -887,7 +887,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionRollback001, TestSi * @tc.name: TransactionGetCommitData001 * @tc.desc: Get the commit data of one transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionGetCommitData001, TestSize.Level1) @@ -940,7 +940,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionGetCommitData001, T * @tc.name: TransactionSqliteKvEntry001 * @tc.desc: Serialize the kv entry and deserialize the data. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionSqliteKvEntry001, TestSize.Level1) @@ -994,7 +994,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionSqliteKvEntry001, T * @tc.name: TransactionPutForeignData001 * @tc.desc: Put the remote commit data into the current device database. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: huangnaigu */ HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionPutForeignData001, TestSize.Level1) @@ -1044,7 +1044,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, TransactionPutForeignData001, * @tc.name: DefaultConflictResolution001 * @tc.desc: Merge data without conflicts * @tc.type: FUNC - * @tc.require: AR000CQE13 AR000CQE14 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution001, TestSize.Level1) @@ -1073,7 +1073,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution001, * @tc.name: DefaultConflictResolution002 * @tc.desc: Merge data with conflicts ,no clear operation in the external data and local data * @tc.type: FUNC - * @tc.require: AR000CQE13 AR000CQE14 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution002, TestSize.Level1) @@ -1175,7 +1175,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution002, * @tc.name: DefaultConflictResolution003 * @tc.desc: Merge data with conflicts, clear operation is in the external data * @tc.type: FUNC - * @tc.require: AR000CQE13 AR000CQE14 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution003, TestSize.Level2) @@ -1226,7 +1226,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution003, * @tc.name: DefaultConflictResolution004 * @tc.desc: Merge data with conflicts, clear operation is in the local data * @tc.type: FUNC - * @tc.require: AR000CQE13 AR000CQE14 + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution004, TestSize.Level2) @@ -1288,7 +1288,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, DefaultConflictResolution004, * @tc.name: CommitTimestamp001 * @tc.desc: Test the timestamp of the native commit. * @tc.type: FUNC - * @tc.require: AR000CQE11 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionDataTest, CommitTimestamp001, TestSize.Level2) @@ -1419,7 +1419,7 @@ static bool PutSecondSyncCommitData(const MultiVerCommitNode &multiVerCommit, Mu * @tc.name: CommitTimestamp002 * @tc.desc: Test the timestamp of the native commits. * @tc.type: FUNC - * @tc.require: AR000CQE11 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionDataTest, CommitTimestamp002, TestSize.Level1) @@ -1467,7 +1467,7 @@ static void ReleaseKvEntries(std::vector &entries) * @tc.name: CommitTimestamp003 * @tc.desc: Test the timestamp of the foreign commits. * @tc.type: FUNC - * @tc.require: AR000CQE11 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionDataTest, CommitTimestamp003, TestSize.Level1) @@ -1511,7 +1511,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, CommitTimestamp003, TestSize.L * @tc.name: CommitTimestamp004 * @tc.desc: Test the timestamp of the merge commits. * @tc.type: FUNC - * @tc.require: AR000CQE11 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionDataTest, CommitTimestamp004, TestSize.Level1) @@ -1562,7 +1562,7 @@ HWTEST_F(DistributedDBStorageTransactionDataTest, CommitTimestamp004, TestSize.L * @tc.name: GetBranchTag * @tc.desc: Test the branch tag of the commits. * @tc.type: FUNC - * @tc.require: AR000CQE11 + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionDataTest, GetBranchTag001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_transaction_record_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_transaction_record_test.cpp index 54333d7b..81c15441 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_transaction_record_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_transaction_record_test.cpp @@ -82,7 +82,7 @@ void DistributedDBStorageTransactionRecordTest::TearDown(void) * @tc.name: MultiverStorage001 * @tc.desc: test the putting non empty data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage001, TestSize.Level1) @@ -127,7 +127,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage001, TestSize * @tc.name: MultiverStorage002 * @tc.desc: test the putting data(empty key) with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage002, TestSize.Level1) @@ -160,7 +160,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage002, TestSize * @tc.name: MultiverStorage003 * @tc.desc: test the putting data(empty value) with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage003, TestSize.Level1) @@ -201,7 +201,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage003, TestSize * @tc.name: MultiverStorage004 * @tc.desc: Update the data value to non-empty with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage004, TestSize.Level1) @@ -255,7 +255,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage004, TestSize * @tc.name: MultiverStorage005 * @tc.desc: Update the data value to empty with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage005, TestSize.Level1) @@ -305,7 +305,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage005, TestSize * @tc.name: MultiverStorage006 * @tc.desc: Delete the existed data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage006, TestSize.Level1) @@ -358,7 +358,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage006, TestSize * @tc.name: MultiverStorage007 * @tc.desc: Delete the non-existed data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage007, TestSize.Level1) @@ -399,7 +399,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage007, TestSize * @tc.name: MultiverStorage008 * @tc.desc: Delete an empty key with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage008, TestSize.Level1) @@ -454,7 +454,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage008, TestSize * @tc.name: MultiverStorage009 * @tc.desc: Clear the existed data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage009, TestSize.Level1) @@ -509,7 +509,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage009, TestSize * @tc.name: MultiverStorage010 * @tc.desc: Get the existed data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage010, TestSize.Level1) @@ -532,7 +532,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage010, TestSize * @tc.name: MultiverStorage011 * @tc.desc: Get the non-existed data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage011, TestSize.Level1) @@ -564,7 +564,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage011, TestSize * @tc.name: MultiverStorage012 * @tc.desc: Get the empty-key data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage012, TestSize.Level1) @@ -597,7 +597,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage012, TestSize * @tc.name: MultiverStorage013 * @tc.desc: Get the deleted data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage013, TestSize.Level1) @@ -630,7 +630,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage013, TestSize * @tc.name: MultiverStorage014 * @tc.desc: Get the modified data with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage014, TestSize.Level1) @@ -666,7 +666,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage014, TestSize * @tc.name: MultiverStorage015 * @tc.desc: Get the data after clear with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage015, TestSize.Level1) @@ -700,7 +700,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage015, TestSize * @tc.name: MultiverStorage016 * @tc.desc: Get the new inserted data after clear with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage016, TestSize.Level1) @@ -742,7 +742,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage016, TestSize * @tc.name: MultiverStorage017 * @tc.desc: Get the new inserted data after delete with the transaction. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage017, TestSize.Level1) @@ -787,7 +787,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage017, TestSize * @tc.name: MultiverStorage018 * @tc.desc: Get the batch inserted data through the non-empty prefix key. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage018, TestSize.Level1) @@ -829,7 +829,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage018, TestSize * @tc.name: MultiverStorage019 * @tc.desc: Get the non-existed data through the non-empty prefix key. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage019, TestSize.Level1) @@ -860,7 +860,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage019, TestSize * @tc.name: MultiverStorage020 * @tc.desc: Get all the data through the empty prefix key. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage020, TestSize.Level1) @@ -896,7 +896,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage020, TestSize * @tc.name: MultiverStorage021 * @tc.desc: Get the data through the empty prefix key for multiple put the same key data. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage021, TestSize.Level1) @@ -930,7 +930,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage021, TestSize * @tc.name: MultiverStorage022 * @tc.desc: Get the data through the empty prefix key for deleted data. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage022, TestSize.Level1) @@ -967,7 +967,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage022, TestSize * @tc.name: MultiverStorage023 * @tc.desc: Get the data through the empty prefix key for updated data. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage023, TestSize.Level1) @@ -1011,7 +1011,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage023, TestSize * @tc.name: MultiverStorage024 * @tc.desc: Get the data through the empty prefix key for cleared data. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage024, TestSize.Level1) @@ -1047,7 +1047,7 @@ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage024, TestSize * @tc.name: MultiverStorage025 * @tc.desc: Get the data through the put, delete, re-put operation. * @tc.type: FUNC - * @tc.require: AR000C6TRV AR000CQDTM + * @tc.require: * @tc.author: wangbingquan */ HWTEST_F(DistributedDBStorageTransactionRecordTest, MultiverStorage025, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_relational_store.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_relational_store.cpp new file mode 100644 index 00000000..f187b6e0 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_relational_store.cpp @@ -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. + */ +#include "virtual_sqlite_relational_store.h" + +namespace DistributedDB { +void VirtualSqliteRelationalStore::SetStorageEngine(const std::shared_ptr &engine) +{ + sqliteStorageEngine_ = engine; +} + +int VirtualSqliteRelationalStore::CallCheckTrackerTable(const TrackerSchema &trackerSchema, TableInfo &table, + bool &isNoTableInSchema, bool &isFirstCreate) +{ + return CheckTrackerTable(trackerSchema, table, isNoTableInSchema, isFirstCreate); +} + +void VirtualSqliteRelationalStore::CallCleanDirtyLogIfNeed(const std::string &tableName) const +{ + CleanDirtyLogIfNeed(tableName); +} + +RelationalSchemaObject VirtualSqliteRelationalStore::CallGetSchemaObj() const +{ + return GetSchemaObj(); +} +} // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_relational_store.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_relational_store.h new file mode 100644 index 00000000..92442e88 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_relational_store.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 VIRTUAL_SQLITE_RELATIONAL_STORE_H +#define VIRTUAL_SQLITE_RELATIONAL_STORE_H + +#include "sqlite_relational_store.h" + +namespace DistributedDB { +class VirtualSqliteRelationalStore : public SQLiteRelationalStore { +public: + VirtualSqliteRelationalStore() = default; + ~VirtualSqliteRelationalStore() override = default; + + void SetStorageEngine(const std::shared_ptr &engine); + + int CallCheckTrackerTable(const TrackerSchema &trackerSchema, TableInfo &table, bool &isNoTableInSchema, + bool &isFirstCreate); + + void CallCleanDirtyLogIfNeed(const std::string &tableName) const; + + RelationalSchemaObject CallGetSchemaObj() const; +}; +} // namespace DistributedDB +#endif // VIRTUAL_SQLITE_RELATIONAL_STORE_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_storage_engine.cpp new file mode 100644 index 00000000..e7bb4d18 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_storage_engine.cpp @@ -0,0 +1,76 @@ +/* + * 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 "virtual_sqlite_storage_engine.h" + +namespace DistributedDB { +void VirtualSingleVerStorageEngine::ForkNewExecutorMethod(const NewExecutorMethod &method) +{ + std::lock_guard autoLock(functionMutex_); + forkNewFunc_ = method; +} + +void VirtualSingleVerStorageEngine::ForkOpenMainDatabaseMethod(const OpenMainDatabaseMethod &method) +{ + std::lock_guard autoLock(functionMutex_); + forkOpenMainFunc_ = method; +} + +void VirtualSingleVerStorageEngine::SetMaxNum(int maxRead, int maxWrite) +{ + engineAttr_.maxReadNum = maxRead; + engineAttr_.maxWriteNum = maxWrite; +} + +void VirtualSingleVerStorageEngine::SetEnhance(bool isEnhance) +{ + isEnhance_ = isEnhance; +} + +void VirtualSingleVerStorageEngine::CallSetSQL(const std::vector &sql) +{ + SetSQL(sql); +} + +std::pair VirtualSingleVerStorageEngine::GetCacheHandle(OpenDbProperties &option) +{ + std::pair res; + auto &[errCode, db] = res; + errCode = SQLiteSingleVerStorageEngine::GetCacheDbHandle(db, option); + return res; +} + +int VirtualSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *&handle) +{ + { + std::lock_guard autoLock(functionMutex_); + if (forkNewFunc_ != nullptr) { + return forkNewFunc_(isWrite, handle); + } + } + return SQLiteSingleVerStorageEngine::CreateNewExecutor(isWrite, handle); +} + +int VirtualSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, sqlite3 *&db, OpenDbProperties &option) +{ + { + std::lock_guard autoLock(functionMutex_); + if (forkOpenMainFunc_ != nullptr) { + return forkOpenMainFunc_(isWrite, db, option); + } + } + return SQLiteSingleVerStorageEngine::TryToOpenMainDatabase(isWrite, db, option); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_storage_engine.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_storage_engine.h new file mode 100644 index 00000000..d1956d84 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/virtual_sqlite_storage_engine.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 VIRTUAL_SQLITE_STORAGE_ENGINE_H +#define VIRTUAL_SQLITE_STORAGE_ENGINE_H + +#include "sqlite_single_ver_storage_engine.h" + +namespace DistributedDB { +class VirtualSingleVerStorageEngine : public SQLiteSingleVerStorageEngine { +public: + using NewExecutorMethod = std::function; + using OpenMainDatabaseMethod = std::function; + void ForkNewExecutorMethod(const NewExecutorMethod &method); + void ForkOpenMainDatabaseMethod(const OpenMainDatabaseMethod &method); + void SetMaxNum(int maxRead, int maxWrite); + void SetEnhance(bool isEnhance); + void CallSetSQL(const std::vector &sql); + std::pair GetCacheHandle(OpenDbProperties &option); +protected: + int CreateNewExecutor(bool isWrite, DistributedDB::StorageExecutor *&handle) override; + int TryToOpenMainDatabase(bool isWrite, sqlite3 *&db, OpenDbProperties &option) override; +private: + std::mutex functionMutex_; + NewExecutorMethod forkNewFunc_; + OpenMainDatabaseMethod forkOpenMainFunc_; +}; +} +#endif // VIRTUAL_SQLITE_STORAGE_ENGINE_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distracteddb_kv_multi_user_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distracteddb_kv_multi_user_sync_test.cpp new file mode 100644 index 00000000..a931eefe --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distracteddb_kv_multi_user_sync_test.cpp @@ -0,0 +1,378 @@ +/* + * 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 "kv_general_ut.h" +#include "process_communicator_test_stub.h" + +namespace DistributedDB { +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +class DistributedDBKvMultiUserSyncTest : public KVGeneralUt { +protected: + void PrepareData(); + void SyncStep1(); + void SyncStep2(); + void SyncStep3(); + static void SetTargetUserId(const std::string &deviceId, const std::string &userId); + static constexpr const char *DEVICE_A = "DEVICE_A"; + static constexpr const char *DEVICE_B = "DEVICE_B"; + static constexpr const char *USER_ID_1 = "USER_ID_1"; + static constexpr const char *USER_ID_2 = "USER_ID_2"; + static constexpr const char *USER_ID_3 = "USER_ID_3"; +}; + +void CheckData(KvStoreNbDelegate *delegate, const Key &key, const Value &expectValue) +{ + Value actualValue; + if (expectValue.empty()) { + EXPECT_EQ(delegate->Get(key, actualValue), NOT_FOUND); + } else { + EXPECT_EQ(delegate->Get(key, actualValue), OK); + EXPECT_EQ(actualValue, expectValue); + } +} + +void DistributedDBKvMultiUserSyncTest::SetTargetUserId(const std::string &deviceId, const std::string &userId) +{ + ICommunicatorAggregator *communicatorAggregator = nullptr; + RuntimeContext::GetInstance()->GetCommunicatorAggregator(communicatorAggregator); + ASSERT_NE(communicatorAggregator, nullptr); + auto virtualCommunicatorAggregator = static_cast(communicatorAggregator); + auto communicator = static_cast(virtualCommunicatorAggregator->GetCommunicator(deviceId)); + ASSERT_NE(communicator, nullptr); + communicator->SetTargetUserId(userId); +} + +void DistributedDBKvMultiUserSyncTest::PrepareData() +{ + KvStoreNbDelegate::Option option; + option.syncDualTupleMode = true; + SetOption(option); + + StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + + StoreInfo storeInfo2 = {USER_ID_2, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_A), E_OK); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + + EXPECT_EQ(store1->Put(KEY_1, VALUE_1), OK); + EXPECT_EQ(store1->Put(KEY_2, VALUE_2), OK); + EXPECT_EQ(store1->Put(KEY_3, VALUE_3), OK); + EXPECT_EQ(store2->Put(KEY_4, VALUE_4), OK); + + CheckData(store1, KEY_1, VALUE_1); + CheckData(store1, KEY_2, VALUE_2); + CheckData(store1, KEY_3, VALUE_3); + CheckData(store2, KEY_4, VALUE_4); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo2), E_OK); +} + +void DistributedDBKvMultiUserSyncTest::SyncStep1() +{ + StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + + StoreInfo storeInfo3 = {USER_ID_1, STORE_ID_2, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo3, DEVICE_B), E_OK); + auto store3 = GetDelegate(storeInfo3); + ASSERT_NE(store3, nullptr); + + SetTargetUserId(DEVICE_A, USER_ID_1); + SetTargetUserId(DEVICE_B, USER_ID_1); + BlockPush(storeInfo1, storeInfo3); + + CheckData(store3, KEY_1, VALUE_1); + CheckData(store3, KEY_2, VALUE_2); + CheckData(store3, KEY_3, VALUE_3); + + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo3), E_OK); +} + +void DistributedDBKvMultiUserSyncTest::SyncStep2() +{ + StoreInfo storeInfo2 = {USER_ID_2, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_A), E_OK); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + + StoreInfo storeInfo4 = {USER_ID_2, STORE_ID_2, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo4, DEVICE_B), E_OK); + auto store4 = GetDelegate(storeInfo4); + ASSERT_NE(store4, nullptr); + + SetTargetUserId(DEVICE_A, USER_ID_2); + SetTargetUserId(DEVICE_B, USER_ID_2); + BlockPush(storeInfo2, storeInfo4); + + CheckData(store4, KEY_1, {}); + CheckData(store4, KEY_2, {}); + CheckData(store4, KEY_3, {}); + CheckData(store4, KEY_4, VALUE_4); + + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo2), E_OK); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo4), E_OK); +} + +void DistributedDBKvMultiUserSyncTest::SyncStep3() +{ + StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + + StoreInfo storeInfo4 = {USER_ID_2, STORE_ID_2, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo4, DEVICE_B), E_OK); + auto store4 = GetDelegate(storeInfo4); + ASSERT_NE(store4, nullptr); + + SetTargetUserId(DEVICE_A, USER_ID_2); + SetTargetUserId(DEVICE_B, USER_ID_1); + BlockPush(storeInfo1, storeInfo4); + + CheckData(store4, KEY_1, VALUE_1); + CheckData(store4, KEY_2, VALUE_2); + CheckData(store4, KEY_3, VALUE_3); + CheckData(store4, KEY_4, VALUE_4); + + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo4), E_OK); +} + +/** + * @tc.name: NormalSyncTest001 + * @tc.desc: Test normal sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBKvMultiUserSyncTest, NormalSyncTest001, TestSize.Level1) +{ + /** + * @tc.steps: step1. (devA, user1) put 3 records, (devA, user2) put 1 record + * @tc.expected: step1. OK. + */ + PrepareData(); + /** + * @tc.steps: step2. (devA, user1) sync to (devB, user1) + * @tc.expected: step2. OK. + */ + SyncStep1(); + /** + * @tc.steps: step3. (devA, user2) put 3 records, (devB, user2) put 1 record + * @tc.expected: step3. OK. + */ + SyncStep2(); + /** + * @tc.steps: step4. (devA, user1) put 3 records, (devB, user2) put 1 record + * @tc.expected: step4. OK. + */ + SyncStep3(); +} + +/** + * @tc.name: NormalSyncTest002 + * @tc.desc: Test sync with low version target. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBKvMultiUserSyncTest, NormalSyncTest002, TestSize.Level0) +{ + /** + * @tc.steps: step1. Init process communicator + * @tc.expected: step1. OK. + */ + KvStoreNbDelegate::Option option; + option.syncDualTupleMode = true; + SetOption(option); + std::shared_ptr processCommunicator = + std::make_shared(); + processCommunicator->SetDataHeadInfo({DBStatus::LOW_VERSION_TARGET, 0u}); + SetProcessCommunicator(processCommunicator); + + /** + * @tc.steps: step2. (devA, user1) put 1 record and sync to (devB, user2) + * @tc.expected: step2. OK. + */ + StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + EXPECT_EQ(store1->Put(KEY_1, VALUE_1), OK); + + StoreInfo storeInfo2 = {USER_ID_2, STORE_ID_2, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_B), E_OK); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + + SetTargetUserId(DEVICE_A, USER_ID_2); + SetTargetUserId(DEVICE_B, USER_ID_1); + UserInfo userInfo = {.receiveUser = USER_ID_2, .sendUser = USER_ID_1}; + processCommunicator->SetDataUserInfo({{userInfo}}); + BlockPush(storeInfo1, storeInfo2); + + CheckData(store2, KEY_1, VALUE_1); + + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo2), E_OK); + + /** + * @tc.steps: step3. (devA, user1) put 1 record and sync to (devB, user3) + * @tc.expected: step3. OK. + */ + StoreInfo storeInfo3 = {USER_ID_3, STORE_ID_2, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo3, DEVICE_B), E_OK); + auto store3 = GetDelegate(storeInfo3); + ASSERT_NE(store3, nullptr); + + EXPECT_EQ(store1->Put(KEY_2, VALUE_2), OK); + + SetTargetUserId(DEVICE_A, USER_ID_3); + SetTargetUserId(DEVICE_B, USER_ID_1); + userInfo = {.receiveUser = USER_ID_3, .sendUser = USER_ID_1}; + processCommunicator->SetDataUserInfo({{userInfo}}); + BlockPush(storeInfo1, storeInfo3); + + CheckData(store3, KEY_2, VALUE_2); + + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo3), E_OK); +} + +/** + * @tc.name: NormalSyncTest003 + * @tc.desc: deviceA:user1 put 2 records and sync to deviceB, deviceA:user1 delete 1 records, deviceA:user2 put + * 2 records and sync to deviceB, deviceA:user1 sync to deviceB. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBKvMultiUserSyncTest, NormalSyncTest003, TestSize.Level0) +{ + /** + * @tc.steps: step1. set option + * @tc.expected: step1. OK. + */ + KvStoreNbDelegate::Option option; + option.syncDualTupleMode = true; + option.conflictResolvePolicy = DEVICE_COLLABORATION; + SetOption(option); + + /** + * @tc.steps: step2. deviceA:user1 put 10 records and sync to deviceB, deviceA:user1 delete 1 records + * @tc.expected: step2. OK. + */ + StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + EXPECT_EQ(store1->Put(KEY_1, VALUE_1), OK); + EXPECT_EQ(store1->Put(KEY_2, VALUE_2), OK); + + StoreInfo storeInfo3 = {USER_ID_3, STORE_ID_2, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo3, DEVICE_B), E_OK); + auto store3 = GetDelegate(storeInfo3); + ASSERT_NE(store3, nullptr); + + SetTargetUserId(DEVICE_A, USER_ID_3); + SetTargetUserId(DEVICE_B, USER_ID_1); + BlockPush(storeInfo1, storeInfo3); + EXPECT_EQ(store1->Delete(KEY_1), OK); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + + /** + * @tc.steps: step3. deviceA:user2 put 2 records and sync to deviceB + * @tc.expected: step3. OK. + */ + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + + StoreInfo storeInfo2 = {USER_ID_2, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_A), E_OK); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + EXPECT_EQ(store2->Put(KEY_1, VALUE_1), OK); + EXPECT_EQ(store2->Put(KEY_2, VALUE_2), OK); + + SetTargetUserId(DEVICE_A, USER_ID_3); + SetTargetUserId(DEVICE_B, USER_ID_2); + BlockPush(storeInfo2, storeInfo3); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo2), E_OK); + + /** + * @tc.steps: step4. deviceA:user1 sync to deviceB. + * @tc.expected: step4. OK. + */ + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + BlockPush(storeInfo1, storeInfo3); + Value actualValue; + EXPECT_EQ(store3->Get(KEY_1, actualValue), NOT_FOUND); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo3), E_OK); +} + +/** + * @tc.name: InvalidSync001 + * @tc.desc: Test sync with empty target user. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBKvMultiUserSyncTest, InvalidSync001, TestSize.Level0) +{ + /** + * @tc.steps: step1. (devA, user1) put 3 records, (devA, user2) put 1 record + * @tc.expected: step1. OK. + */ + KvStoreNbDelegate::Option option; + option.syncDualTupleMode = true; + SetOption(option); + StoreInfo storeInfo1 = {USER_ID_1, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + + StoreInfo storeInfo2 = {USER_ID_2, STORE_ID_1, APP_ID}; + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_B), E_OK); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + + EXPECT_EQ(store1->Put(KEY_1, VALUE_1), OK); + EXPECT_EQ(store1->Put(KEY_2, VALUE_2), OK); + EXPECT_EQ(store1->Put(KEY_3, VALUE_3), OK); + EXPECT_EQ(store2->Put(KEY_4, VALUE_4), OK); + + CheckData(store1, KEY_1, VALUE_1); + CheckData(store1, KEY_2, VALUE_2); + CheckData(store1, KEY_3, VALUE_3); + CheckData(store2, KEY_4, VALUE_4); + /** + * @tc.steps: step2. set empty target user and sync + * @tc.expected: step2. return OK. + */ + SetTargetUserId(DEVICE_A, ""); + BlockPush(storeInfo1, storeInfo2); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo2), E_OK); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_abnormal_kv_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_abnormal_kv_sync_test.cpp new file mode 100644 index 00000000..d1074edd --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_abnormal_kv_sync_test.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 "kv_general_ut.h" + +namespace DistributedDB { +using namespace testing::ext; + +class DistributedDBAbnormalKVSyncTest : public KVGeneralUt { +public: + void SetUp() override; +}; + +void DistributedDBAbnormalKVSyncTest::SetUp() +{ + KVGeneralUt::SetUp(); + auto storeInfo1 = GetStoreInfo1(); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, "dev1"), E_OK); + auto storeInfo2 = GetStoreInfo2(); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, "dev2"), E_OK); +} + +/** + * @tc.name: SyncWithInvalidSoftwareVersionTest001 + * @tc.desc: Test ability sync after software version is invalid. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBAbnormalKVSyncTest, SyncWithInvalidSoftwareVersionTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. open store and sync first + * @tc.expected: step1. sync ok. + */ + auto storeInfo1 = GetStoreInfo1(); + auto storeInfo2 = GetStoreInfo2(); + BlockPush(storeInfo1, storeInfo2); + /** + * @tc.steps: step2. set version invalid and sync again after reopen store + * @tc.expected: step2. sync ok. + */ + ASSERT_EQ(SetRemoteSoftwareVersion(storeInfo1, "dev2", DBConstant::DEFAULT_USER, INT32_MAX), OK); + KVGeneralUt::CloseDelegate(storeInfo1); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, "dev1"), E_OK); + std::atomic msgCount = 0; + RegBeforeDispatch([&msgCount](const std::string &dev, const Message *inMsg) { + if (dev != "dev2" || inMsg->GetMessageId() != ABILITY_SYNC_MESSAGE) { + return; + } + msgCount++; + }); + BlockPush(storeInfo1, storeInfo2); + RegBeforeDispatch(nullptr); + EXPECT_GT(msgCount, 0); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_basic_kv_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_basic_kv_test.cpp index 416d4ead..5795aca7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_basic_kv_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_basic_kv_test.cpp @@ -29,6 +29,8 @@ void DistributedDBBasicKVTest::SetUp() ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, "dev1"), E_OK); auto storeInfo2 = GetStoreInfo2(); ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, "dev2"), E_OK); + auto storeInfo3 = GetStoreInfo3(); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo3, "dev3"), E_OK); } /** @@ -56,5 +58,63 @@ HWTEST_F(DistributedDBBasicKVTest, ExampleSync001, TestSize.Level0) Value actualValue; EXPECT_EQ(store2->Get({'k'}, actualValue), OK); EXPECT_EQ(actualValue, expectValue); + /** + * @tc.steps: step2. dev2's schemaVersion and softwareVersion both equal to dev1's meta + * @tc.expected: step2. version both equal. + */ + auto [errCode, version] = GetRemoteSoftwareVersion(storeInfo1, "dev2", DBConstant::DEFAULT_USER); + EXPECT_EQ(errCode, OK); + EXPECT_EQ(version, static_cast(SOFTWARE_VERSION_CURRENT)); + std::tie(errCode, version) = GetRemoteSchemaVersion(storeInfo1, "dev2", DBConstant::DEFAULT_USER); + EXPECT_EQ(errCode, OK); + EXPECT_NE(version, 0); + uint64_t store2SchemaVersion = 0; + std::tie(errCode, store2SchemaVersion) = GetLocalSchemaVersion(storeInfo2); + EXPECT_EQ(errCode, E_OK); + EXPECT_EQ(version, store2SchemaVersion); +} + +/** + * @tc.name: WhitelistKvGet001 + * @tc.desc: Test kv get interface for whitelist. + * @tc.type: FUNC + * @tc.require: + * @tc.author: xd + */ +HWTEST_F(DistributedDBBasicKVTest, WhitelistKvGet001, TestSize.Level0) +{ + /** + * @tc.steps: step1. set whitelist appId, put (k,v) + * @tc.expected: step1. get (k,v) result. + */ + auto storeInfo3 = GetStoreInfo3(); + auto store3 = GetDelegate(storeInfo3); + ASSERT_NE(store3, nullptr); + Value expectValue = {'v'}; + EXPECT_EQ(store3->Put({'k'}, expectValue), OK); + Value actualValue; + EXPECT_EQ(store3->Get({'k'}, actualValue), OK); + EXPECT_EQ(actualValue, expectValue); + /** + * @tc.steps: step2. with transaction, set whitelist appId, put (k2,v) + * @tc.expected: step2. get (k2,v) result. + */ + store3->StartTransaction(); + EXPECT_EQ(store3->Put({'k', '2'}, expectValue), OK); + Value actualValue2; + EXPECT_EQ(store3->Get({'k', '2'}, actualValue2), OK); + EXPECT_EQ(actualValue2, expectValue); + store3->Commit(); + /** + * @tc.steps: step3. do not set whitelist appId, put (k,v) + * @tc.expected: step3. get (k,v) result. + */ + auto storeInfo2 = GetStoreInfo2(); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + EXPECT_EQ(store2->Put({'k'}, expectValue), OK); + Value actualValue3; + EXPECT_EQ(store2->Get({'k'}, actualValue3), OK); + EXPECT_EQ(actualValue3, expectValue); } } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_compress_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_compress_test.cpp new file mode 100644 index 00000000..1a3ad888 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_compress_test.cpp @@ -0,0 +1,101 @@ +/* + * 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 "kv_general_ut.h" + +namespace DistributedDB { +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +class DistributedDBKVCompressTest : public KVGeneralUt { +public: + void SetUp() override; +protected: + void PrepareEnv(bool isNeedCompressOnSync); + void TriggerPutAndSync(); + static constexpr const char *DEVICE_A = "DEVICE_A"; + static constexpr const char *DEVICE_B = "DEVICE_B"; +}; + +void DistributedDBKVCompressTest::SetUp() +{ + KVGeneralUt::SetUp(); +} + +void DistributedDBKVCompressTest::PrepareEnv(bool isNeedCompressOnSync) +{ + KVGeneralUt::CloseAllDelegate(); + KvStoreNbDelegate::Option option; + option.isNeedCompressOnSync = isNeedCompressOnSync; + option.compressionRate = 100; // compress rate is 100 + SetOption(option); + auto storeInfo1 = GetStoreInfo1(); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + auto storeInfo2 = GetStoreInfo2(); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_B), E_OK); +} + +void DistributedDBKVCompressTest::TriggerPutAndSync() +{ + auto storeInfo1 = GetStoreInfo1(); + auto storeInfo2 = GetStoreInfo2(); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + Value expectValue(DBConstant::MAX_VALUE_SIZE, 'v'); + EXPECT_EQ(store1->Put({'k'}, expectValue), OK); + BlockPush(storeInfo1, storeInfo2); + Value actualValue; + EXPECT_EQ(store2->Get({'k'}, actualValue), OK); + EXPECT_EQ(actualValue, expectValue); +} + +/** + * @tc.name: SyncTest001 + * @tc.desc: Test sync with compress. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBKVCompressTest, SyncTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Open store with compress + * @tc.expected: step1. Open ok + */ + ASSERT_NO_FATAL_FAILURE(PrepareEnv(true)); + /** + * @tc.steps: step2. dev1 put (k,v) and sync to dev2 + * @tc.expected: step2. sync should return OK and dev2 exist (k,v). + */ + auto size1 = GetAllSendMsgSize(); + ASSERT_NO_FATAL_FAILURE(TriggerPutAndSync()); + auto size2 = GetAllSendMsgSize(); + /** + * @tc.steps: step3. Open store without compress + * @tc.expected: step3. Open ok + */ + ASSERT_NO_FATAL_FAILURE(PrepareEnv(false)); + /** + * @tc.steps: step4. dev1 put (k,v) and sync to dev2 + * @tc.expected: step4. sync should return OK and dev2 exist (k,v). + */ + auto size3 = GetAllSendMsgSize(); + ASSERT_NO_FATAL_FAILURE(TriggerPutAndSync()); + auto size4 = GetAllSendMsgSize(); + EXPECT_LE(size2 - size1, size4 - size3); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_data_status_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_data_status_test.cpp index 71a331d6..51b0651d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_data_status_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_data_status_test.cpp @@ -19,7 +19,7 @@ namespace DistributedDB { using namespace testing::ext; using namespace DistributedDB; using namespace DistributedDBUnitTest; - + class DistributedDBKVDataStatusTest : public KVGeneralUt { public: void SetUp() override; @@ -29,7 +29,7 @@ protected: static constexpr const char *DEVICE_C = "DEVICE_C"; static const uint32_t INVALID_DATA_OPERATOR = 0; }; - + void DistributedDBKVDataStatusTest::SetUp() { KVGeneralUt::SetUp(); @@ -38,7 +38,7 @@ void DistributedDBKVDataStatusTest::SetUp() auto storeInfo2 = GetStoreInfo2(); ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_B), E_OK); } - + /** * @tc.name: OperateDataStatus001 * @tc.desc: Test sync from dev1 to dev2 after operate valid data status. @@ -86,7 +86,7 @@ HWTEST_F(DistributedDBKVDataStatusTest, OperateDataStatus001, TestSize.Level0) EXPECT_EQ(store2->Get({'k'}, actualValue), OK); EXPECT_EQ(actualValue, expectValue); } - + /** * @tc.name: OperateDataStatus002 * @tc.desc: Test sync from dev1 to dev2 after operate invalid data status. @@ -175,6 +175,49 @@ HWTEST_F(DistributedDBKVDataStatusTest, OperateDataStatus003, TestSize.Level0) EXPECT_EQ(entries.size(), 0u); // 0 record } +/** + * @tc.name: OperateDataStatus004 + * @tc.desc: Test sync with delete data. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBKVDataStatusTest, OperateDataStatus004, TestSize.Level0) +{ + /** + * @tc.steps: step1. dev1 put (k,v) and sync to dev2 + * @tc.expected: step1. sync should return OK and dev2 exist (k,v). + */ + auto storeInfo1 = GetStoreInfo1(); + auto storeInfo2 = GetStoreInfo2(); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + Value expectValue = {'v'}; + EXPECT_EQ(store1->Put({'k'}, expectValue), OK); + BlockPush(storeInfo1, storeInfo2); + EXPECT_EQ(store1->Delete({'k'}), OK); + BlockPush(storeInfo1, storeInfo2); + /** + * @tc.steps: step2. dev1 modify deviceId and operate data status RESET_UPLOAD_CLOUD + * @tc.expected: step2. OK. + */ + ASSERT_EQ(KVGeneralUt::CloseDelegate(storeInfo1), E_OK); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_C), E_OK); + store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + EXPECT_EQ(store1->OperateDataStatus(static_cast(DataOperator::RESET_UPLOAD_CLOUD)), OK); + /** + * @tc.steps: step3. dev1 sync to dev2 + * @tc.expected: step3. sync should return OK and dev2 get entries by device return NOT_FOUND. + */ + BlockPush(storeInfo1, storeInfo2); + std::vector entries; + EXPECT_EQ(KVGeneralUt::GetDeviceEntries(store2, std::string(DEVICE_C), false, entries), NOT_FOUND); + EXPECT_EQ(entries.size(), 0u); // 0 record +} + #ifdef USE_DISTRIBUTEDDB_CLOUD /** * @tc.name: CloudOperateDataStatus001 diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_device_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_device_sync_test.cpp new file mode 100644 index 00000000..c936faec --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/kv/distributeddb_kv_device_sync_test.cpp @@ -0,0 +1,145 @@ +/* + * 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 "kv_general_ut.h" +#include "kv_store_nb_delegate_impl.h" + +namespace DistributedDB { + using namespace testing::ext; + using namespace DistributedDB; + using namespace DistributedDBUnitTest; + +class DistributedDBKvDeviceSyncTest : public KVGeneralUt { +public: + void SetUp() override; +protected: + static constexpr const char *DEVICE_A = "DEVICE_A"; + static constexpr const char *DEVICE_B = "DEVICE_B"; + DistributedDBToolsUnitTest g_tool; +}; + +void DistributedDBKvDeviceSyncTest::SetUp() +{ + KVGeneralUt::SetUp(); + auto storeInfo1 = GetStoreInfo1(); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK); + auto storeInfo2 = GetStoreInfo2(); + ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_B), E_OK); +} + +/** + * @tc.name: NormalSyncTest001 + * @tc.desc: Test normal sync without retry. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBKvDeviceSyncTest, NormalSyncTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. dev1 put (k,v) + * @tc.expected: step1. return OK + */ + auto storeInfo1 = GetStoreInfo1(); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + Key key = {'k'}; + Value expectValue = {'v'}; + EXPECT_EQ(store1->Put(key, expectValue), OK); + /** + * @tc.steps: step2. dev1 sync to dev2 + * @tc.expected: step2. return OK and dev2 exist (k,v) + */ + DeviceSyncOption option; + option.devices = {DEVICE_B}; + option.mode = SYNC_MODE_PUSH_ONLY; + option.isRetry = false; + std::map syncRet; + EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), OK); + for (const auto &ret : syncRet) { + EXPECT_EQ(ret.first, DEVICE_B); + EXPECT_EQ(ret.second, OK); + } + auto storeInfo2 = GetStoreInfo2(); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + Value actualValue; + EXPECT_EQ(store2->Get(key, actualValue), OK); + EXPECT_EQ(actualValue, expectValue); +} + +/** + * @tc.name: AbnormalKvSyncTest001 + * @tc.desc: Test sync with invalid args. + * @tc.type: FUNC + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBKvDeviceSyncTest, AbnormalKvSyncTest001, TestSize.Level1) +{ + /** + * @tc.steps: step1. dev1 put (k,v) + * @tc.expected: step1. return OK + */ + auto storeInfo1 = GetStoreInfo1(); + auto store1 = GetDelegate(storeInfo1); + ASSERT_NE(store1, nullptr); + Key key = {'k'}; + Value expectValue = {'v'}; + EXPECT_EQ(store1->Put(key, expectValue), OK); + /** + * @tc.steps: step2. dev1 sync to dev2 with invalid mode + * @tc.expected: step2. return NOT_SUPPORT + */ + DeviceSyncOption option; + option.devices = {DEVICE_B}; + option.mode = SYNC_MODE_CLOUD_MERGE; + option.isRetry = false; + std::map syncRet; + EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), NOT_SUPPORT); + auto storeInfo2 = GetStoreInfo2(); + auto store2 = GetDelegate(storeInfo2); + ASSERT_NE(store2, nullptr); + Value actualValue; + EXPECT_EQ(store2->Get(key, actualValue), NOT_FOUND); + option.mode = SYNC_MODE_PUSH_PULL; + /** + * @tc.steps: step3. dev1 sync to dev2 with invalid query + * @tc.expected: step3. return NOT_SUPPORT + */ + option.isQuery = true; + option.query = Query::Select().FromTable({"table1", "table2"}); + EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), NOT_SUPPORT); + EXPECT_EQ(store2->Get(key, actualValue), NOT_FOUND); + option.query = Query::Select().From("A").From("B"); + EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), NOT_SUPPORT); + EXPECT_EQ(store2->Get(key, actualValue), NOT_FOUND); + /** + * @tc.steps: step4. dev1 sync to dev2 with empty devices + * @tc.expected: step4. return NOT_SUPPORT + */ + option.devices.clear(); + option.isQuery = false; + EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), INVALID_ARGS); + EXPECT_EQ(store2->Get(key, actualValue), NOT_FOUND); + /** + * @tc.steps: step5. dev1 sync to dev2 after close db + * @tc.expected: step5. return DB_ERROR + */ + auto kvStoreImpl = static_cast(store1); + EXPECT_EQ(kvStoreImpl->Close(), OK); + EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), DB_ERROR); + EXPECT_EQ(store2->Get(key, actualValue), NOT_FOUND); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distracteddb_rdb_multi_user_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distracteddb_rdb_multi_user_sync_test.cpp new file mode 100644 index 00000000..686790f4 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distracteddb_rdb_multi_user_sync_test.cpp @@ -0,0 +1,141 @@ +/* + * 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 "rdb_general_ut.h" + +namespace DistributedDB { + using namespace testing::ext; + using namespace DistributedDB; + using namespace DistributedDBUnitTest; + +class DistributedDBRDBMultiUserSyncTest : public RDBGeneralUt { +public: + void SetUp() override; +protected: + static constexpr const char *DEVICE_SYNC_TABLE = "DEVICE_SYNC_TABLE"; + static constexpr const char *DEVICE_A = "DEVICE_A"; + static constexpr const char *DEVICE_B = "DEVICE_B"; + static constexpr const char *USER_ID_1 = "userId1"; + static constexpr const char *USER_ID_2 = "userId2"; + static UtDateBaseSchemaInfo GetDefaultSchema(); + static UtTableSchemaInfo GetTableSchema(const std::string &table, bool noPk = false); + static void SetTargetUserId(const std::string &deviceId, const std::string &userId); +}; + +void DistributedDBRDBMultiUserSyncTest::SetUp() +{ + RDBGeneralUt::SetUp(); + RelationalStoreDelegate::Option option; + option.syncDualTupleMode = true; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); +} + +UtDateBaseSchemaInfo DistributedDBRDBMultiUserSyncTest::GetDefaultSchema() +{ + UtDateBaseSchemaInfo info; + info.tablesInfo.push_back(GetTableSchema(DEVICE_SYNC_TABLE)); + return info; +} + +UtTableSchemaInfo DistributedDBRDBMultiUserSyncTest::GetTableSchema(const std::string &table, bool noPk) +{ + UtTableSchemaInfo tableSchema; + tableSchema.name = table; + UtFieldInfo fieldId; + fieldId.field.colName = "id"; + fieldId.field.type = TYPE_INDEX; + if (!noPk) { + fieldId.field.primary = true; + } + tableSchema.fieldInfo.push_back(fieldId); + UtFieldInfo fieldName; + fieldName.field.colName = "name"; + fieldName.field.type = TYPE_INDEX; + tableSchema.fieldInfo.push_back(fieldName); + return tableSchema; +} + +void DistributedDBRDBMultiUserSyncTest::SetTargetUserId(const std::string &deviceId, const std::string &userId) +{ + ICommunicatorAggregator *communicatorAggregator = nullptr; + RuntimeContext::GetInstance()->GetCommunicatorAggregator(communicatorAggregator); + ASSERT_NE(communicatorAggregator, nullptr); + auto virtualCommunicatorAggregator = static_cast(communicatorAggregator); + auto communicator = static_cast(virtualCommunicatorAggregator->GetCommunicator(deviceId)); + ASSERT_NE(communicator, nullptr); + communicator->SetTargetUserId(userId); +} + +HWTEST_F(DistributedDBRDBMultiUserSyncTest, NormalSyncTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Prepare db and data. + * @tc.expected: step1. Ok + */ + StoreInfo deviceAStore1 = {USER_ID_1, APP_ID, STORE_ID_1}; + StoreInfo deviceAStore2 = {USER_ID_2, APP_ID, STORE_ID_2}; + StoreInfo deviceBStore = {USER_ID_1, APP_ID, STORE_ID_3}; + + SetSchemaInfo(deviceAStore1, GetDefaultSchema()); + SetSchemaInfo(deviceAStore2, GetDefaultSchema()); + SetSchemaInfo(deviceBStore, GetDefaultSchema()); + + ASSERT_EQ(BasicUnitTest::InitDelegate(deviceAStore1, DEVICE_A), E_OK); + ASSERT_EQ(BasicUnitTest::InitDelegate(deviceAStore2, DEVICE_A), E_OK); + ASSERT_EQ(BasicUnitTest::InitDelegate(deviceBStore, DEVICE_B), E_OK); + + ASSERT_EQ(SetDistributedTables(deviceAStore1, {DEVICE_SYNC_TABLE}), E_OK); + ASSERT_EQ(SetDistributedTables(deviceAStore2, {DEVICE_SYNC_TABLE}), E_OK); + ASSERT_EQ(SetDistributedTables(deviceBStore, {DEVICE_SYNC_TABLE}), E_OK); + + InsertLocalDBData(0, 1, deviceAStore1); + InsertLocalDBData(0, 1, deviceAStore2); + sqlite3 *dbA2 = GetSqliteHandle(deviceAStore2); + std::string updateSql = "update " + std::string(DEVICE_SYNC_TABLE) + " set name = 'new_name' where id = 0;"; + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(dbA2, updateSql), E_OK); + + ASSERT_EQ(RDBGeneralUt::CloseDelegate(deviceAStore1), OK); + ASSERT_EQ(RDBGeneralUt::CloseDelegate(deviceAStore2), OK); + /** + * @tc.steps: step2. Sync from db2 of deviceA to deviceB. + * @tc.expected: step2. Ok + */ + ASSERT_EQ(BasicUnitTest::InitDelegate(deviceAStore2, DEVICE_A), E_OK); + SetTargetUserId(DEVICE_A, USER_ID_1); + SetTargetUserId(DEVICE_B, USER_ID_2); + BlockPush(deviceAStore2, deviceBStore, DEVICE_SYNC_TABLE); + ASSERT_EQ(RDBGeneralUt::CloseDelegate(deviceAStore2), OK); + /** + * @tc.steps: step3. Sync from db1 of deviceA to deviceB. + * @tc.expected: step3. Ok + */ + ASSERT_EQ(BasicUnitTest::InitDelegate(deviceAStore1, DEVICE_A), E_OK); + SetTargetUserId(DEVICE_A, USER_ID_1); + SetTargetUserId(DEVICE_B, USER_ID_1); + BlockPush(deviceAStore1, deviceBStore, DEVICE_SYNC_TABLE); + ASSERT_EQ(RDBGeneralUt::CloseDelegate(deviceAStore1), OK); + /** + * @tc.steps: step4. Check data in deviceB. + * @tc.expected: step4. Ok + */ + std::string checkSql = "select count(*) from " + std::string(DEVICE_SYNC_TABLE) + " where name = 'new_name';"; + sqlite3 *dbB = GetSqliteHandle(deviceBStore); + int actualCount = 0; + ASSERT_EQ(SQLiteUtils::GetCountBySql(dbB, checkSql, actualCount), E_OK); + EXPECT_EQ(actualCount, 1); + ASSERT_EQ(RDBGeneralUt::CloseDelegate(deviceBStore), OK); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_basic_rdb_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_basic_rdb_test.cpp index ba3a7cbe..a0ef9225 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_basic_rdb_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_basic_rdb_test.cpp @@ -14,6 +14,7 @@ */ #include "rdb_general_ut.h" +#include "sqlite_relational_utils.h" using namespace testing::ext; using namespace DistributedDB; @@ -54,7 +55,7 @@ HWTEST_F(DistributedDBBasicRDBTest, InitDelegateExample001, TestSize.Level0) * @tc.expected: step1. Ok */ StoreInfo info1 = {USER_ID, APP_ID, STORE_ID_1}; - EXPECT_EQ(RDBGeneralUt::InitDelegate(info1), E_OK); + EXPECT_EQ(BasicUnitTest::InitDelegate(info1, "dev1"), E_OK); DataBaseSchema actualSchemaInfo = RDBGeneralUt::GetSchema(info1); ASSERT_EQ(actualSchemaInfo.tables.size(), 2u); EXPECT_EQ(actualSchemaInfo.tables[0].name, g_defaultTable1); @@ -70,11 +71,11 @@ HWTEST_F(DistributedDBBasicRDBTest, InitDelegateExample001, TestSize.Level0) UtDateBaseSchemaInfo schemaInfo = { .tablesInfo = {{.name = DEVICE_SYNC_TABLE, .fieldInfo = filedInfo}} }; - RDBGeneralUt::AddSchemaInfo(info1, schemaInfo); + RDBGeneralUt::SetSchemaInfo(info1, schemaInfo); RelationalStoreDelegate::Option option; option.tableMode = DistributedTableMode::COLLABORATION; SetOption(option); - EXPECT_EQ(RDBGeneralUt::InitDelegate(info1), E_OK); + EXPECT_EQ(BasicUnitTest::InitDelegate(info1, "dev1"), E_OK); StoreInfo info2 = {USER_ID, APP_ID, STORE_ID_2}; schemaInfo = { @@ -83,12 +84,140 @@ HWTEST_F(DistributedDBBasicRDBTest, InitDelegateExample001, TestSize.Level0) {.name = CLOUD_SYNC_TABLE, .fieldInfo = filedInfo}, } }; - RDBGeneralUt::AddSchemaInfo(info2, schemaInfo); - EXPECT_EQ(RDBGeneralUt::InitDelegate(info2), E_OK); + RDBGeneralUt::SetSchemaInfo(info2, schemaInfo); + EXPECT_EQ(BasicUnitTest::InitDelegate(info2, "dev2"), E_OK); actualSchemaInfo = RDBGeneralUt::GetSchema(info2); ASSERT_EQ(actualSchemaInfo.tables.size(), schemaInfo.tablesInfo.size()); EXPECT_EQ(actualSchemaInfo.tables[1].name, CLOUD_SYNC_TABLE); TableSchema actualTableInfo = RDBGeneralUt::GetTableSchema(info2, CLOUD_SYNC_TABLE); EXPECT_EQ(actualTableInfo.fields.size(), filedInfo.size()); } + +/** + * @tc.name: RdbSyncExample001 + * @tc.desc: Test insert data and sync from dev1 to dev2. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBBasicRDBTest, RdbSyncExample001, TestSize.Level0) +{ + /** + * @tc.steps: step1. dev1 insert data. + * @tc.expected: step1. Ok + */ + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + auto info1 = GetStoreInfo1(); + ASSERT_EQ(BasicUnitTest::InitDelegate(info1, "dev1"), E_OK); + auto info2 = GetStoreInfo2(); + ASSERT_EQ(BasicUnitTest::InitDelegate(info2, "dev2"), E_OK); + InsertLocalDBData(0, 2, info1); + EXPECT_EQ(RDBGeneralUt::CountTableData(info1, g_defaultTable1), 2); + EXPECT_EQ(RDBGeneralUt::CountTableData(info2, g_defaultTable1), 0); + + /** + * @tc.steps: step2. create distributed tables and sync to dev1. + * @tc.expected: step2. Ok + */ + ASSERT_EQ(SetDistributedTables(info1, {g_defaultTable1}), E_OK); + ASSERT_EQ(SetDistributedTables(info2, {g_defaultTable1}), E_OK); + BlockPush(info1, info2, g_defaultTable1); + EXPECT_EQ(RDBGeneralUt::CountTableData(info2, g_defaultTable1), 2); +} + +#ifdef USE_DISTRIBUTEDDB_CLOUD +/** + * @tc.name: RdbCloudSyncExample001 + * @tc.desc: Test cloud sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBBasicRDBTest, RdbCloudSyncExample001, TestSize.Level0) +{ + /** + * @tc.steps: step1. sync dev1 data to cloud. + * @tc.expected: step1. Ok + */ + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + auto info1 = GetStoreInfo1(); + ASSERT_EQ(BasicUnitTest::InitDelegate(info1, "dev1"), E_OK); + InsertLocalDBData(0, 2, info1); + EXPECT_EQ(RDBGeneralUt::CountTableData(info1, g_defaultTable1), 2); + + ASSERT_EQ(SetDistributedTables(info1, {g_defaultTable1}, TableSyncType::CLOUD_COOPERATION), E_OK); + RDBGeneralUt::SetCloudDbConfig(info1); + Query query = Query::Select().FromTable({g_defaultTable1}); + RDBGeneralUt::CloudBlockSync(info1, query); + EXPECT_EQ(RDBGeneralUt::GetCloudDataCount(g_defaultTable1), 2); +} + +/** + * @tc.name: RdbCloudSyncExample002 + * @tc.desc: Test cloud insert data and cloud sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBBasicRDBTest, RdbCloudSyncExample002, TestSize.Level0) +{ + /** + * @tc.steps: step1. cloud insert data. + * @tc.expected: step1. Ok + */ + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + auto info1 = GetStoreInfo1(); + ASSERT_EQ(BasicUnitTest::InitDelegate(info1, "dev1"), E_OK); + ASSERT_EQ(SetDistributedTables(info1, {g_defaultTable1}, TableSyncType::CLOUD_COOPERATION), E_OK); + RDBGeneralUt::SetCloudDbConfig(info1); + std::shared_ptr virtualCloudDb = RDBGeneralUt::GetVirtualCloudDb(); + ASSERT_NE(virtualCloudDb, nullptr); + EXPECT_EQ(RDBDataGenerator::InsertCloudDBData(0, 20, 0, RDBGeneralUt::GetSchema(info1), virtualCloudDb), OK); + EXPECT_EQ(RDBGeneralUt::GetCloudDataCount(g_defaultTable1), 20); + EXPECT_EQ(RDBGeneralUt::CountTableData(info1, g_defaultTable1), 0); + + /** + * @tc.steps: step2. cloud sync data to dev1. + * @tc.expected: step2. Ok + */ + Query query = Query::Select().FromTable({g_defaultTable1}); + RDBGeneralUt::CloudBlockSync(info1, query); + EXPECT_EQ(RDBGeneralUt::CountTableData(info1, g_defaultTable1), 20); +} +#endif // USE_DISTRIBUTEDDB_CLOUD + +/** + * @tc.name: RdbUtilsTest001 + * @tc.desc: Test rdb utils execute actions. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBBasicRDBTest, RdbUtilsTest001, TestSize.Level0) +{ + std::vector> actions; + /** + * @tc.steps: step1. execute null actions no effect ret. + * @tc.expected: step1. E_OK + */ + actions.emplace_back(nullptr); + EXPECT_EQ(SQLiteRelationalUtils::ExecuteListAction(actions), E_OK); + /** + * @tc.steps: step2. execute abort when action return error. + * @tc.expected: step2. -E_INVALID_ARGS + */ + actions.clear(); + actions.emplace_back([]() { + return -E_INVALID_ARGS; + }); + actions.emplace_back([]() { + return -E_NOT_SUPPORT; + }); + EXPECT_EQ(SQLiteRelationalUtils::ExecuteListAction(actions), -E_INVALID_ARGS); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_compress_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_compress_test.cpp new file mode 100644 index 00000000..a8c07347 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_compress_test.cpp @@ -0,0 +1,401 @@ +/* + * 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 "rdb_general_ut.h" +#include "relational_store_delegate_impl.h" +#include "single_ver_relational_syncer.h" +#include "sqlite_relational_store.h" +#include "sqlite_relational_store_connection.h" +#include "sync_able_engine.h" +#include "mock_sync_engine.h" + +namespace DistributedDB { +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +class DistributedDBRDBCompressTest : public RDBGeneralUt { +public: + void SetUp() override; +protected: + void InitOption(DistributedTableMode tableMode, bool isNeedCompressOnSync, uint8_t compressRate); + void InitInfo(const StoreInfo &info, const char *dev, DistributedTableMode tableMode, + bool isNeedCompressOnSync, uint8_t compressRate); + void SimpleSyncTest(bool store1Compress, bool store2Compress, uint8_t store1Rate, uint8_t store2Rate, + SyncMode mode); + void CompressTest(bool store1Compress, bool store2Compress, uint8_t store1Rate, + uint8_t store2Rate, SyncMode mode); + static UtDateBaseSchemaInfo GetDefaultSchema(); + static UtTableSchemaInfo GetTableSchema(const std::string &table); + static std::string GetInsertSQL(); + static std::string GetConditionSQL(); + static constexpr const char *DEVICE_SYNC_TABLE = "DEVICE_SYNC_TABLE"; + static constexpr const char *DEVICE_A = "DEVICE_A"; + static constexpr const char *DEVICE_B = "DEVICE_B"; + const StoreInfo info1_ = {USER_ID, APP_ID, STORE_ID_1}; + const StoreInfo info2_ = {USER_ID, APP_ID, STORE_ID_2}; + std::atomic mode_ = DistributedTableMode::COLLABORATION; +}; + +void DistributedDBRDBCompressTest::SetUp() +{ + mode_ = DistributedTableMode::COLLABORATION; + RDBGeneralUt::SetUp(); + SetSchemaInfo(info1_, GetDefaultSchema()); + SetSchemaInfo(info2_, GetDefaultSchema()); +} + +void DistributedDBRDBCompressTest::InitOption(DistributedTableMode tableMode, bool isNeedCompressOnSync, + uint8_t compressRate) +{ + RelationalStoreDelegate::Option option; + option.tableMode = tableMode; + option.isNeedCompressOnSync = isNeedCompressOnSync; + option.compressionRate = compressRate; + SetOption(option); +} + +void DistributedDBRDBCompressTest::InitInfo(const StoreInfo &info, const char *dev, DistributedTableMode tableMode, + bool isNeedCompressOnSync, uint8_t compressRate) +{ + InitOption(tableMode, isNeedCompressOnSync, compressRate); + ASSERT_EQ(BasicUnitTest::InitDelegate(info, dev), E_OK); + ASSERT_EQ(SetDistributedTables(info, {DEVICE_SYNC_TABLE}), E_OK); +} + +UtDateBaseSchemaInfo DistributedDBRDBCompressTest::GetDefaultSchema() +{ + UtDateBaseSchemaInfo info; + info.tablesInfo.push_back(GetTableSchema(DEVICE_SYNC_TABLE)); + return info; +} + +UtTableSchemaInfo DistributedDBRDBCompressTest::GetTableSchema(const std::string &table) +{ + UtTableSchemaInfo tableSchema; + tableSchema.name = table; + UtFieldInfo field; + field.field.colName = "id"; + field.field.type = TYPE_INDEX; + field.field.primary = true; + tableSchema.fieldInfo.push_back(field); + field.field.colName = "val"; + field.field.type = TYPE_INDEX; + field.field.primary = false; + tableSchema.fieldInfo.push_back(field); + return tableSchema; +} + +std::string DistributedDBRDBCompressTest::GetInsertSQL() +{ + std::string sql = "INSERT OR REPLACE INTO "; + sql.append(DEVICE_SYNC_TABLE).append("(id, val) VALUES(1, '"); + for (size_t i = 0; i < 1000; ++i) { // 1000 is data len + sql.append("v"); + } + sql.append("')"); + return sql; +} + +std::string DistributedDBRDBCompressTest::GetConditionSQL() +{ + std::string condition = " id=1 AND val='"; + for (size_t i = 0; i < 1000; ++i) { // 1000 is data len + condition.append("v"); + } + condition.append("' "); + return condition; +} + +void DistributedDBRDBCompressTest::SimpleSyncTest(bool store1Compress, bool store2Compress, uint8_t store1Rate, + uint8_t store2Rate, SyncMode mode) +{ + LOGI("SimpleSyncTest begin store1Compress %d store2Compress %d store1Rate %" PRIu8 " store2Rate %" PRIu8, + store1Compress, store2Compress, store1Rate, store2Rate); + RDBGeneralUt::CloseAllDelegate(); + SetSchemaInfo(info1_, GetDefaultSchema()); + SetSchemaInfo(info2_, GetDefaultSchema()); + /** + * @tc.steps: step1. Init store1 and store2. + * @tc.expected: step1. Ok + */ + ASSERT_NO_FATAL_FAILURE(InitInfo(info1_, DEVICE_A, mode_, store1Compress, + store1Rate)); + ASSERT_NO_FATAL_FAILURE(InitInfo(info2_, DEVICE_B, mode_, store2Compress, + store2Rate)); + /** + * @tc.steps: step2. Store1 insert local data. + * @tc.expected: step2. Ok + */ + ExecuteSQL(GetInsertSQL(), info1_); + /** + * @tc.steps: step3. DEV_A sync to DEV_B. + * @tc.expected: step3. Ok + */ + if (mode == SYNC_MODE_PUSH_ONLY) { + ASSERT_NO_FATAL_FAILURE(BlockPush(info1_, info2_, DEVICE_SYNC_TABLE)); + } else if (mode == SYNC_MODE_PULL_ONLY) { + ASSERT_NO_FATAL_FAILURE(BlockPull(info2_, info1_, DEVICE_SYNC_TABLE)); + } + /** + * @tc.steps: step4. Check store2's data. + * @tc.expected: step4. Exist 1 row + */ + if (mode_ == DistributedTableMode::COLLABORATION) { + EXPECT_EQ(CountTableData(info2_, DEVICE_SYNC_TABLE, GetConditionSQL()), 1); + } else if (mode_ == DistributedTableMode::SPLIT_BY_DEVICE) { + EXPECT_EQ(CountTableData(info2_, + DBCommon::GetDistributedTableName(DEVICE_A, DEVICE_SYNC_TABLE), GetConditionSQL()), 1); + } +} + +void DistributedDBRDBCompressTest::CompressTest(bool store1Compress, bool store2Compress, uint8_t store1Rate, + uint8_t store2Rate, SyncMode mode) +{ + /** + * @tc.steps: step1. Store1 sync to store2 with compress. + * @tc.expected: step1. Sync ok + */ + auto size1 = GetAllSendMsgSize(); + SimpleSyncTest(store1Compress, store2Compress, store1Rate, store2Rate, mode); // both compress rate is 100 + auto size2 = GetAllSendMsgSize(); + /** + * @tc.steps: step2. Store1 sync to store2 without compress. + * @tc.expected: step2. Sync ok and + */ + auto size3 = GetAllSendMsgSize(); + SimpleSyncTest(store1Compress, store2Compress, store1Rate, store2Rate, mode); // both compress rate is 100 + auto size4 = GetAllSendMsgSize(); + EXPECT_LE(size2 - size1, size4 - size3); +} + +/** + * @tc.name: RDBCompressSync001 + * @tc.desc: Test collaboration table push sync with compress. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBCompressSync001, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(CompressTest(true, true, 100, 100, SyncMode::SYNC_MODE_PUSH_ONLY)); +} + +/** + * @tc.name: RDBCompressSync002 + * @tc.desc: Test collaboration table pull sync with compress. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBCompressSync002, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(CompressTest(true, true, 100, 100, SyncMode::SYNC_MODE_PULL_ONLY)); +} + +/** + * @tc.name: RDBCompressSync003 + * @tc.desc: Test split table push sync with compress. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBCompressSync003, TestSize.Level1) +{ + mode_ = DistributedTableMode::SPLIT_BY_DEVICE; + ASSERT_NO_FATAL_FAILURE(CompressTest(true, true, 100, 100, SyncMode::SYNC_MODE_PUSH_ONLY)); +} + +/** + * @tc.name: RDBCompressSync004 + * @tc.desc: Test split table pull sync with compress. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBCompressSync004, TestSize.Level1) +{ + mode_ = DistributedTableMode::SPLIT_BY_DEVICE; + ASSERT_NO_FATAL_FAILURE(CompressTest(true, true, 100, 100, SyncMode::SYNC_MODE_PULL_ONLY)); +} + +/** + * @tc.name: RDBCompressSync005 + * @tc.desc: Test collaboration table push sync with compress but remote is not compress. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBCompressSync005, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(CompressTest(true, false, 100, 100, SyncMode::SYNC_MODE_PUSH_ONLY)); +} + +/** + * @tc.name: RDBCompressSync006 + * @tc.desc: Test collaboration table pull sync with compress but remote is not compress. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBCompressSync006, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(CompressTest(true, false, 100, 100, SyncMode::SYNC_MODE_PULL_ONLY)); +} + +/** + * @tc.name: RDBInvalidCompress001 + * @tc.desc: Test open store with invalid compress option. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBInvalidCompress001, TestSize.Level0) +{ + ASSERT_NO_FATAL_FAILURE(InitInfo(info1_, DEVICE_A, mode_, true, 0)); + RDBGeneralUt::CloseAllDelegate(); + ASSERT_NO_FATAL_FAILURE(InitInfo(info1_, DEVICE_A, mode_, true, 101)); // compress rate is 101 + RDBGeneralUt::CloseAllDelegate(); + ASSERT_NO_FATAL_FAILURE(InitInfo(info1_, DEVICE_A, mode_, false, 0)); + RDBGeneralUt::CloseAllDelegate(); + ASSERT_NO_FATAL_FAILURE(InitInfo(info1_, DEVICE_A, mode_, false, 101)); // compress rate is 101 +} + +/** + * @tc.name: RDBInvalidCompress001 + * @tc.desc: Test open store with invalid compress option. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBInvalidCompress002, TestSize.Level0) +{ + /** + * @tc.steps: step1. Open store1 with compress and rate1. + * @tc.expected: step1. Open ok + */ + ASSERT_NO_FATAL_FAILURE(InitInfo(info1_, DEVICE_A, mode_, true, 1)); + /** + * @tc.steps: step2. Open store1 with compress and rate2. + * @tc.expected: step2. Open failed by conflict with cache + */ + InitOption(mode_, true, 2); // compress rate is 2 + auto [errCode, delegate] = OpenRDBStore(info1_); + EXPECT_EQ(errCode, INVALID_ARGS); + EXPECT_EQ(delegate, nullptr); + /** + * @tc.steps: step3. Open store1 without compress and rate1. + * @tc.expected: step3. Open failed by conflict with cache + */ + InitOption(mode_, false, 1); // compress rate is 1 + std::tie(errCode, delegate) = OpenRDBStore(info1_); + EXPECT_EQ(errCode, INVALID_ARGS); + EXPECT_EQ(delegate, nullptr); + InitOption(mode_, true, 100); // compress rate is 100 + std::tie(errCode, delegate) = OpenRDBStore(info1_); + EXPECT_EQ(errCode, INVALID_ARGS); + EXPECT_EQ(delegate, nullptr); + /** + * @tc.steps: step4. Open store1 without compress and rate100 after close store1. + * @tc.expected: step4. Open ok + */ + RDBGeneralUt::CloseAllDelegate(); + /** + * @tc.steps: step5. Open store1 without compress and rate100. + * @tc.expected: step5. Open ok + */ + ASSERT_NO_FATAL_FAILURE(InitInfo(info1_, DEVICE_A, mode_, false, 100)); // compress rate is 100 + InitOption(mode_, false, 2); // compress rate is 2 + std::tie(errCode, delegate) = OpenRDBStore(info1_); + EXPECT_EQ(errCode, OK); + ASSERT_NE(delegate, nullptr); + RelationalStoreManager mgr(info1_.appId, info1_.userId); + mgr.CloseStore(delegate); +} + +/** + * @tc.name: RDBGetDevTaskCount001 + * @tc.desc: Test get dev task count when sync. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, RDBGetDevTaskCount001, TestSize.Level0) +{ + std::atomic checkFlag = false; + RegBeforeDispatch([this, &checkFlag](const std::string &dev, const Message *inMsg) { + if (dev != DEVICE_B || inMsg->GetMessageId() != QUERY_SYNC_MESSAGE) { + return; + } + if (checkFlag) { + return; + } + checkFlag = true; + auto store1 = GetDelegate(info1_); + ASSERT_NE(store1, nullptr); + EXPECT_GT(store1->GetDeviceSyncTaskCount(), 0); + auto store2 = GetDelegate(info2_); + ASSERT_NE(store2, nullptr); + EXPECT_GT(store2->GetDeviceSyncTaskCount(), 0); + }); + CompressTest(true, true, 100, 100, SyncMode::SYNC_MODE_PULL_ONLY); + RegBeforeDispatch(nullptr); +} + +/** + * @tc.name: VerifyDeviceSyncTaskCountAfterRemoteQuery001 + * @tc.desc: Test get device task count when remote query. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, VerifyDeviceSyncTaskCountAfterRemoteQuery001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Init store1 and store2. + * @tc.expected: step1. Ok + */ + RDBGeneralUt::CloseAllDelegate(); + SetSchemaInfo(info1_, GetDefaultSchema()); + SetSchemaInfo(info2_, GetDefaultSchema()); + ASSERT_NO_FATAL_FAILURE(InitInfo(info1_, DEVICE_A, mode_, true, 100)); // compress rate is 100 + ASSERT_NO_FATAL_FAILURE(InitInfo(info2_, DEVICE_B, mode_, true, 100)); // compress rate is 100 + std::atomic msgCount = 0; + RegBeforeDispatch([this, &msgCount](const std::string &dev, const Message *inMsg) { + if (dev != DEVICE_A || inMsg->GetMessageId() != REMOTE_EXECUTE_MESSAGE) { + return; + } + auto store1 = GetDelegate(info1_); + ASSERT_NE(store1, nullptr); + EXPECT_GT(store1->GetDeviceSyncTaskCount(), 0); + msgCount++; + }); + RemoteQuery(info1_, info2_, "SELECT * FROM DEVICE_SYNC_TABLE", OK); + RegBeforeDispatch(nullptr); + EXPECT_GT(msgCount, 0); +} + +/** + * @tc.name: VerifyInvalidGetDeviceSyncTaskCount001 + * @tc.desc: Test abnormal get device task count. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBCompressTest, VerifyInvalidGetDeviceSyncTaskCount001, TestSize.Level0) +{ + RelationalStoreDelegateImpl delegate; + EXPECT_EQ(delegate.GetDeviceSyncTaskCount(), 0); + SyncAbleEngine engine(nullptr); + EXPECT_EQ(engine.GetDeviceSyncTaskCount(), 0); + SQLiteRelationalStore store; + EXPECT_EQ(store.GetDeviceSyncTaskCount(), 0); + SQLiteRelationalStoreConnection connection(nullptr); + EXPECT_EQ(connection.GetDeviceSyncTaskCount(), 0); + MockSyncEngine syncEngine; + EXPECT_EQ(syncEngine.GetRemoteQueryTaskCount(), 0); + SingleVerRelationalSyncer syncer; + EXPECT_EQ(syncer.GetTaskCount(), 0); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_data_status_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_data_status_test.cpp index 920ece0a..6a1c7784 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_data_status_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_data_status_test.cpp @@ -19,14 +19,18 @@ namespace DistributedDB { using namespace testing::ext; using namespace DistributedDB; using namespace DistributedDBUnitTest; - + class DistributedDBRDBDataStatusTest : public RDBGeneralUt { public: void SetUp() override; protected: void PrepareTableBasicEnv(bool createWithTracker = false); + void PrepareBasicTableByType(TableSyncType type); + void PrepareBasicTableByType(const std::vector &tables, TableSyncType type); void DataStatusComplexTest(bool testWithTracker); static UtDateBaseSchemaInfo GetDefaultSchema(); + static UtTableSchemaInfo GetTableSchema(const std::string &table, bool noPk = false); + void InitCollaborationDelegate(); static constexpr const char *DEVICE_SYNC_TABLE = "DEVICE_SYNC_TABLE"; static constexpr const char *DEVICE_A = "DEVICE_A"; static constexpr const char *DEVICE_B = "DEVICE_B"; @@ -34,28 +38,35 @@ protected: StoreInfo info1_ = {USER_ID, APP_ID, STORE_ID_1}; StoreInfo info2_ = {USER_ID, APP_ID, STORE_ID_2}; }; - + void DistributedDBRDBDataStatusTest::SetUp() { RDBGeneralUt::SetUp(); - AddSchemaInfo(info1_, GetDefaultSchema()); - AddSchemaInfo(info2_, GetDefaultSchema()); + SetSchemaInfo(info1_, GetDefaultSchema()); + SetSchemaInfo(info2_, GetDefaultSchema()); } - + UtDateBaseSchemaInfo DistributedDBRDBDataStatusTest::GetDefaultSchema() { UtDateBaseSchemaInfo info; - UtTableSchemaInfo table; - table.name = DEVICE_SYNC_TABLE; + info.tablesInfo.push_back(GetTableSchema(DEVICE_SYNC_TABLE)); + return info; +} + +UtTableSchemaInfo DistributedDBRDBDataStatusTest::GetTableSchema(const std::string &table, bool noPk) +{ + UtTableSchemaInfo tableSchema; + tableSchema.name = table; UtFieldInfo field; field.field.colName = "id"; field.field.type = TYPE_INDEX; - field.field.primary = true; - table.fieldInfo.push_back(field); - info.tablesInfo.push_back(table); - return info; + if (!noPk) { + field.field.primary = true; + } + tableSchema.fieldInfo.push_back(field); + return tableSchema; } - + void DistributedDBRDBDataStatusTest::PrepareTableBasicEnv(bool createWithTracker) { /** @@ -92,7 +103,35 @@ void DistributedDBRDBDataStatusTest::PrepareTableBasicEnv(bool createWithTracker ASSERT_NE(store, nullptr); EXPECT_EQ(store->OperateDataStatus(static_cast(DataOperator::UPDATE_TIME)), OK); } - + +void DistributedDBRDBDataStatusTest::PrepareBasicTableByType(TableSyncType type) +{ + ASSERT_NO_FATAL_FAILURE(PrepareBasicTableByType({DEVICE_SYNC_TABLE}, type)); +} + +void DistributedDBRDBDataStatusTest::PrepareBasicTableByType(const std::vector &tables, + TableSyncType type) +{ + /** + * @tc.steps: step1. Call InitDelegate interface with default split table mode. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(BasicUnitTest::InitDelegate(info1_, DEVICE_A), E_OK); + ASSERT_EQ(BasicUnitTest::InitDelegate(info2_, DEVICE_B), E_OK); + /** + * @tc.steps: step2. Set distributed tables. + * @tc.expected: step2. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, tables, type), E_OK); + ASSERT_EQ(SetDistributedTables(info2_, tables, type), E_OK); + ASSERT_EQ(SetTrackerTables(info1_, tables), E_OK); + /** + * @tc.steps: step3. Insert local data. + * @tc.expected: step3. Ok + */ + InsertLocalDBData(0, 1, info1_); +} + void DistributedDBRDBDataStatusTest::DataStatusComplexTest(bool testWithTracker) { RelationalStoreDelegate::Option option; @@ -116,7 +155,16 @@ void DistributedDBRDBDataStatusTest::DataStatusComplexTest(bool testWithTracker) */ EXPECT_EQ(CountTableDataByDev(info2_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), DEVICE_C), 1); } - + +void DistributedDBRDBDataStatusTest::InitCollaborationDelegate() +{ + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + ASSERT_EQ(BasicUnitTest::InitDelegate(info1_, DEVICE_A), E_OK); + ASSERT_EQ(BasicUnitTest::InitDelegate(info2_, DEVICE_B), E_OK); +} + /** * @tc.name: SplitTable001 * @tc.desc: Test split table sync after update time. @@ -133,8 +181,8 @@ HWTEST_F(DistributedDBRDBDataStatusTest, SplitTable001, TestSize.Level0) */ BlockPush(info1_, info2_, DEVICE_SYNC_TABLE); } - - + + /** * @tc.name: SplitTable002 * @tc.desc: Test split table sync with diff dev after update time. @@ -206,4 +254,352 @@ HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable003, TestSize.Level0) { DataStatusComplexTest(true); } + +/** + * @tc.name: CollaborationTable004 + * @tc.desc: Test collaboration search table sync after update time. + * @tc.type: FUNC + * @tc.require: + * @tc.author: tankaisheng + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable004, TestSize.Level0) +{ + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + ASSERT_NO_FATAL_FAILURE(PrepareBasicTableByType(DEVICE_COOPERATION)); + /** + * @tc.steps: step1. DEV_A sync to DEV_B. + * @tc.expected: step1. Ok + */ + BlockPush(info1_, info2_, DEVICE_SYNC_TABLE); +} + +/** + * @tc.name: CollaborationTable005 + * @tc.desc: Test collaboration no pk table set schema twice. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable005, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create no pk table and set as distributed table. + * @tc.expected: step1. Ok + */ + UtDateBaseSchemaInfo info; + info.tablesInfo.push_back(GetTableSchema("new_table", true)); + SetSchemaInfo(info1_, info); + SetSchemaInfo(info2_, info); + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + ASSERT_NO_FATAL_FAILURE(PrepareBasicTableByType({"new_table"}, DEVICE_COOPERATION)); + /** + * @tc.steps: step2. Update distributed table by create more table. + * @tc.expected: step2. Ok + */ + info.tablesInfo.push_back(GetTableSchema(DEVICE_SYNC_TABLE)); + SetSchemaInfo(info1_, info); + SetSchemaInfo(info2_, info); + ASSERT_NO_FATAL_FAILURE(PrepareBasicTableByType({"new_table", DEVICE_SYNC_TABLE}, DEVICE_COOPERATION)); +} + +/** + * @tc.name: CollaborationTable006 + * @tc.desc: Test device collaboration and search table sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable006, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + /** + * @tc.steps: step1. Set distributed tables and Tracker tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, {DEVICE_SYNC_TABLE}, DEVICE_COOPERATION), E_OK); + ASSERT_EQ(SetTrackerTables(info2_, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert data and sync. + * @tc.expected: step2. SCHEMA_MISMATCH + */ + InsertLocalDBData(0, 1, info1_); + BlockPush(info1_, info2_, DEVICE_SYNC_TABLE, SCHEMA_MISMATCH); +} + +/** + * @tc.name: CollaborationTable007 + * @tc.desc: Test device collaboration search table and search table sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable007, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + /** + * @tc.steps: step1. Set distributed tables and Tracker tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, {DEVICE_SYNC_TABLE}, DEVICE_COOPERATION), E_OK); + ASSERT_EQ(SetTrackerTables(info1_, {DEVICE_SYNC_TABLE}), E_OK); + ASSERT_EQ(SetTrackerTables(info2_, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert data and sync. + * @tc.expected: step2. SCHEMA_MISMATCH + */ + InsertLocalDBData(0, 1, info1_); + BlockPush(info1_, info2_, DEVICE_SYNC_TABLE, SCHEMA_MISMATCH); +} + +/** + * @tc.name: CollaborationTable008 + * @tc.desc: Test device collaboration and cloud collaboration search table sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable008, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + /** + * @tc.steps: step1. Set distributed tables and Tracker tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, {DEVICE_SYNC_TABLE}, DEVICE_COOPERATION), E_OK); + ASSERT_EQ(SetDistributedTables(info2_, {DEVICE_SYNC_TABLE}, CLOUD_COOPERATION), E_OK); + ASSERT_EQ(SetTrackerTables(info2_, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert data and sync. + * @tc.expected: step2. NOT_SUPPORT + */ + InsertLocalDBData(0, 1, info1_); + BlockPush(info1_, info2_, DEVICE_SYNC_TABLE, NOT_SUPPORT); +} + +/** + * @tc.name: CollaborationTable009 + * @tc.desc: Test device collaboration search table and cloud collaboration search table sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable009, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + /** + * @tc.steps: step1. Set distributed tables and Tracker tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, {DEVICE_SYNC_TABLE}, DEVICE_COOPERATION), E_OK); + ASSERT_EQ(SetTrackerTables(info1_, {DEVICE_SYNC_TABLE}), E_OK); + ASSERT_EQ(SetDistributedTables(info2_, {DEVICE_SYNC_TABLE}, CLOUD_COOPERATION), E_OK); + ASSERT_EQ(SetTrackerTables(info2_, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert data and sync. + * @tc.expected: step2. NOT_SUPPORT + */ + InsertLocalDBData(0, 1, info1_); + BlockPush(info1_, info2_, DEVICE_SYNC_TABLE, NOT_SUPPORT); +} + +/** + * @tc.name: CollaborationTable010 + * @tc.desc: Test device collaboration and cloud collaboration able sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable010, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + /** + * @tc.steps: step1. Set distributed tables and Tracker tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, {DEVICE_SYNC_TABLE}, CLOUD_COOPERATION), E_OK); + ASSERT_EQ(SetDistributedTables(info2_, {DEVICE_SYNC_TABLE}, DEVICE_COOPERATION), E_OK); + /** + * @tc.steps: step2. Insert data and sync. + * @tc.expected: step2. NOT_SUPPORT + */ + InsertLocalDBData(0, 1, info1_); + auto store = GetDelegate(info1_); + ASSERT_NE(store, nullptr); + auto toDevice = GetDevice(info2_); + ASSERT_FALSE(toDevice.empty()); + Query query = Query::Select(DEVICE_SYNC_TABLE); + DBStatus callStatus = store->Sync({toDevice}, SYNC_MODE_PUSH_ONLY, query, nullptr, true); + EXPECT_EQ(callStatus, NOT_SUPPORT); +} + +/** + * @tc.name: CollaborationTable011 + * @tc.desc: Test cloud collaboration table and device collaboration search table sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable011, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + /** + * @tc.steps: step1. Set distributed tables and Tracker tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, {DEVICE_SYNC_TABLE}, CLOUD_COOPERATION), E_OK); + ASSERT_EQ(SetDistributedTables(info2_, {DEVICE_SYNC_TABLE}, DEVICE_COOPERATION), E_OK); + ASSERT_EQ(SetTrackerTables(info2_, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert data and sync. + * @tc.expected: step2. NOT_SUPPORT + */ + InsertLocalDBData(0, 1, info1_); + auto store = GetDelegate(info1_); + ASSERT_NE(store, nullptr); + auto toDevice = GetDevice(info2_); + ASSERT_FALSE(toDevice.empty()); + Query query = Query::Select(DEVICE_SYNC_TABLE); + DBStatus callStatus = store->Sync({toDevice}, SYNC_MODE_PUSH_ONLY, query, nullptr, true); + EXPECT_EQ(callStatus, NOT_SUPPORT); +} + +/** + * @tc.name: CollaborationTable012 + * @tc.desc: Test cloud collaboration and search table sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable012, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + /** + * @tc.steps: step1. Set distributed tables and Tracker tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, {DEVICE_SYNC_TABLE}, CLOUD_COOPERATION), E_OK); + ASSERT_EQ(SetTrackerTables(info2_, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert data and sync. + * @tc.expected: step2. NOT_SUPPORT + */ + InsertLocalDBData(0, 1, info1_); + auto store = GetDelegate(info1_); + ASSERT_NE(store, nullptr); + auto toDevice = GetDevice(info2_); + ASSERT_FALSE(toDevice.empty()); + Query query = Query::Select(DEVICE_SYNC_TABLE); + DBStatus callStatus = store->Sync({toDevice}, SYNC_MODE_PUSH_ONLY, query, nullptr, true); + EXPECT_EQ(callStatus, NOT_SUPPORT); +} + +/** + * @tc.name: CollaborationTable013 + * @tc.desc: Test cloud collaboration search table and search table sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CollaborationTable013, TestSize.Level1) +{ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + /** + * @tc.steps: step1. Set distributed tables and Tracker tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(SetDistributedTables(info1_, {DEVICE_SYNC_TABLE}, CLOUD_COOPERATION), E_OK); + ASSERT_EQ(SetTrackerTables(info1_, {DEVICE_SYNC_TABLE}), E_OK); + ASSERT_EQ(SetTrackerTables(info2_, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert data and sync. + * @tc.expected: step2. NOT_SUPPORT + */ + InsertLocalDBData(0, 1, info1_); + auto store = GetDelegate(info1_); + ASSERT_NE(store, nullptr); + auto toDevice = GetDevice(info2_); + ASSERT_FALSE(toDevice.empty()); + Query query = Query::Select(DEVICE_SYNC_TABLE); + DBStatus callStatus = store->Sync({toDevice}, SYNC_MODE_PUSH_ONLY, query, nullptr, true); + EXPECT_EQ(callStatus, NOT_SUPPORT); +} + +/** + * @tc.name: CreateDistributedTableTest001 + * @tc.desc: Test CreateDistributedTable interface after re-create table. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBRDBDataStatusTest, CreateDistributedTableTest001, TestSize.Level0) +{ + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + ASSERT_NO_FATAL_FAILURE(PrepareTableBasicEnv()); + EXPECT_EQ(RDBGeneralUt::CreateDistributedTable(info1_, {DEVICE_SYNC_TABLE}), E_OK); + + /** + * @tc.steps: step1. Drop table, and create same table that unique field are added. + * @tc.expected: step1. Ok + */ + sqlite3 *db = GetSqliteHandle(info1_); + ASSERT_NE(db, nullptr); + std::string newSql = "DROP TABLE DEVICE_SYNC_TABLE;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, newSql), SQLITE_OK); + newSql = "CREATE TABLE IF NOT EXISTS DEVICE_SYNC_TABLE('id' INTEGER PRIMARY KEY, new_field INTEGER UNIQUE);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, newSql), SQLITE_OK); + + /** + * @tc.steps: step2. Create distributed table. + * @tc.expected: step2. OK + */ + EXPECT_EQ(RDBGeneralUt::CreateDistributedTable(info1_, {DEVICE_SYNC_TABLE}), E_OK); +} + +/** + * @tc.name: TimeCheck001 + * @tc.desc: Test operate data status after modify time. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBDataStatusTest, TimeCheck001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create distributed table and insert local data. + */ + ASSERT_NO_FATAL_FAILURE(InitCollaborationDelegate()); + EXPECT_EQ(RDBGeneralUt::CreateDistributedTable(info1_, {DEVICE_SYNC_TABLE}), E_OK); + InsertLocalDBData(0, 1, info1_); + /** + * @tc.steps: step2. Get last max timestamp. + * @tc.expected: step2. Ok + */ + sqlite3 *db = GetSqliteHandle(info1_); + ASSERT_NE(db, nullptr); + auto [errCode, t1] = RelationalTestUtils::GetMaxTimestamp(db, DEVICE_SYNC_TABLE); + EXPECT_EQ(errCode, E_OK); + /** + * @tc.steps: step3. Modify time offset and operator data status. + * @tc.expected: step3. Ok + */ + std::string sql = "INSERT OR REPLACE INTO " + std::string(DBConstant::RELATIONAL_PREFIX) + + "metadata VALUES('localTimeOffset', '100000')"; + ASSERT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + auto store = GetDelegate(info1_); + ASSERT_NE(store, nullptr); + EXPECT_EQ(store->OperateDataStatus(static_cast(DataOperator::UPDATE_TIME)), OK); + /** + * @tc.steps: step4. Check timestamp should not decrease. + * @tc.expected: step4. Ok + */ + auto [ret, t2] = RelationalTestUtils::GetMaxTimestamp(db, DEVICE_SYNC_TABLE); + EXPECT_EQ(ret, E_OK); + EXPECT_GE(t2, t1); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_drop_table_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_drop_table_test.cpp new file mode 100644 index 00000000..53228a3a --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_drop_table_test.cpp @@ -0,0 +1,278 @@ +/* + * 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 "rdb_general_ut.h" +#include "sqlite_relational_utils.h" +#include "virtual_sqlite_relational_store.h" +namespace DistributedDB { +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +class DistributedDBRDBDropTableTest : public RDBGeneralUt { +public: + void SetUp() override; +protected: + void PrepareEnv(const StoreInfo &info, bool createTracker = false, bool createDistributedTable = false); + static UtDateBaseSchemaInfo GetDefaultSchema(); + static UtDateBaseSchemaInfo GetUniqueSchema(); + static UtTableSchemaInfo GetTableSchema(const std::string &table, bool isPkUuid); + static constexpr const char *DEVICE_SYNC_TABLE = "DEVICE_SYNC_TABLE"; + static constexpr const char *DEVICE_A = "DEVICE_A"; + static constexpr const char *DEVICE_B = "DEVICE_B"; + StoreInfo info1_ = {USER_ID, APP_ID, STORE_ID_1}; + StoreInfo info2_ = {USER_ID, APP_ID, STORE_ID_2}; +}; + +void DistributedDBRDBDropTableTest::SetUp() +{ + RDBGeneralUt::SetUp(); + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); +} + +void DistributedDBRDBDropTableTest::PrepareEnv(const StoreInfo &info, bool createTracker, bool createDistributedTable) +{ + ASSERT_EQ(ExecuteSQL("CREATE TABLE IF NOT EXISTS" + " DEVICE_SYNC_TABLE(id INTEGER PRIMARY KEY AUTOINCREMENT, uuid INTEGER UNIQUE)", info), E_OK); + if (createTracker) { + ASSERT_EQ(SetTrackerTables(info, {DEVICE_SYNC_TABLE}), E_OK); + } + if (createDistributedTable) { + ASSERT_EQ(SetDistributedTables(info, {DEVICE_SYNC_TABLE}), E_OK); + } +} + +UtDateBaseSchemaInfo DistributedDBRDBDropTableTest::GetDefaultSchema() +{ + UtDateBaseSchemaInfo info; + info.tablesInfo.push_back(GetTableSchema(DEVICE_SYNC_TABLE, false)); + return info; +} + +UtDateBaseSchemaInfo DistributedDBRDBDropTableTest::GetUniqueSchema() +{ + UtDateBaseSchemaInfo info; + info.tablesInfo.push_back(GetTableSchema(DEVICE_SYNC_TABLE, true)); + return info; +} + +UtTableSchemaInfo DistributedDBRDBDropTableTest::GetTableSchema(const std::string &table, bool isPkUuid) +{ + UtTableSchemaInfo tableSchema; + tableSchema.name = table; + UtFieldInfo field; + field.field.type = TYPE_INDEX; + field.field.primary = isPkUuid; + field.field.colName = "uuid"; + tableSchema.fieldInfo.push_back(field); + return tableSchema; +} + +/** + * @tc.name: SyncAfterDrop001 + * @tc.desc: Test sync success after drop table. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBDropTableTest, SyncAfterDrop001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create table and set distributed tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(BasicUnitTest::InitDelegate(info1_, DEVICE_A), E_OK); + SetSchemaInfo(info1_, GetDefaultSchema()); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_, true)); + EXPECT_EQ(ExecuteSQL("INSERT OR REPLACE INTO DEVICE_SYNC_TABLE VALUES(1, 100)", info1_), E_OK); + EXPECT_EQ(CountTableData(info1_, DEVICE_SYNC_TABLE, "id=1"), 1); + ASSERT_EQ(BasicUnitTest::InitDelegate(info2_, DEVICE_B), E_OK); + SetSchemaInfo(info2_, GetUniqueSchema()); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info2_, true, true)); + /** + * @tc.steps: step2. Recreate table and set distributed tables. + * @tc.expected: step2. Ok + */ + EXPECT_EQ(ExecuteSQL("DROP TABLE DEVICE_SYNC_TABLE", info1_), E_OK); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_)); + EXPECT_EQ(ExecuteSQL("INSERT OR REPLACE INTO DEVICE_SYNC_TABLE VALUES(1, 100)", info1_), E_OK); + SetSchemaInfo(info1_, GetUniqueSchema()); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_, true, true)); + /** + * @tc.steps: step3. Sync. + * @tc.expected: step3. Ok + */ + BlockSync(info1_, info2_, DEVICE_SYNC_TABLE, SyncMode::SYNC_MODE_PUSH_ONLY, OK); +} + +/** + * @tc.name: SyncAfterDrop002 + * @tc.desc: Test sync success after drop table. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBDropTableTest, SyncAfterDrop002, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create table and set distributed tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(BasicUnitTest::InitDelegate(info1_, DEVICE_A), E_OK); + SetSchemaInfo(info1_, GetDefaultSchema()); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_, true)); + EXPECT_EQ(ExecuteSQL("INSERT OR REPLACE INTO DEVICE_SYNC_TABLE VALUES(1, 100)", info1_), E_OK); + ASSERT_EQ(BasicUnitTest::InitDelegate(info2_, DEVICE_B), E_OK); + SetSchemaInfo(info2_, GetUniqueSchema()); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info2_, true, true)); + /** + * @tc.steps: step2. Recreate table and set distributed tables and insert dirty data. + * @tc.expected: step2. Ok + */ + EXPECT_EQ(ExecuteSQL("DROP TABLE DEVICE_SYNC_TABLE", info1_), E_OK); + std::string sql = "INSERT OR REPLACE INTO " + DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) + + "(data_key, timestamp, wtimestamp, flag, hash_key, extend_field) " + "VALUES(1, 1, 1, 0x02, 'error_hash1', '100')"; + EXPECT_EQ(ExecuteSQL(sql, info1_), E_OK); + sql = "INSERT OR REPLACE INTO " + DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) + + "(data_key, timestamp, wtimestamp, flag, hash_key, extend_field) " + "VALUES(1, 2, 2, 0x02, 'error_hash2', 200)"; + EXPECT_EQ(ExecuteSQL(sql, info1_), E_OK); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_)); + EXPECT_EQ(ExecuteSQL("INSERT OR REPLACE INTO DEVICE_SYNC_TABLE VALUES(1, 100)", info1_), E_OK); + SetSchemaInfo(info1_, GetUniqueSchema()); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_, false, true)); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_, true, false)); + /** + * @tc.steps: step3. Sync. + * @tc.expected: step3. Ok + */ + BlockSync(info1_, info2_, DEVICE_SYNC_TABLE, SyncMode::SYNC_MODE_PUSH_ONLY, OK); + EXPECT_EQ(CountTableData(info1_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), "hash_key='error_hash1'"), 0); + EXPECT_EQ(CountTableData(info1_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), "hash_key='error_hash2'"), 0); +} + +/** + * @tc.name: SetTrackerAfterDrop001 + * @tc.desc: Test set tracker success after drop table. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBDropTableTest, SetTrackerAfterDrop001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create table and set tracker table. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(BasicUnitTest::InitDelegate(info1_, DEVICE_A), E_OK); + SetSchemaInfo(info1_, GetDefaultSchema()); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_, true)); + /** + * @tc.steps: step2. Recreate table and set tracker table with force. + * @tc.expected: step2. Ok + */ + EXPECT_EQ(ExecuteSQL("DROP TABLE DEVICE_SYNC_TABLE", info1_), E_OK); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_)); + ASSERT_EQ(SetTrackerTables(info1_, {DEVICE_SYNC_TABLE}, true), E_OK); +} + +/** + * @tc.name: InvalidCleanTracker001 + * @tc.desc: Test clean tracker with invalid obj. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBDropTableTest, InvalidCleanTracker001, TestSize.Level0) +{ + VirtualSqliteRelationalStore store; + auto schemaObj = store.CallGetSchemaObj(); + EXPECT_FALSE(schemaObj.IsSchemaValid()); + TrackerSchema schema; + TableInfo info; + bool isNoTableInSchema = false; + bool isFirstCreate = false; + RelationalDBProperties properties; + auto engine = std::make_shared(properties); + store.SetStorageEngine(engine); + engine->SetEngineState(EngineState::ENGINE_BUSY); + EXPECT_EQ(store.CallCheckTrackerTable(schema, info, isNoTableInSchema, isFirstCreate), -E_BUSY); + EXPECT_FALSE(isNoTableInSchema); + EXPECT_TRUE(isFirstCreate); + store.CallCleanDirtyLogIfNeed(DEVICE_SYNC_TABLE); +} + +/** + * @tc.name: CleanDirtyLog001 + * @tc.desc: Test clean dirty log by utils. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBDropTableTest, CleanDirtyLog001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create table and set distributed tables. + * @tc.expected: step1. Ok + */ + ASSERT_EQ(BasicUnitTest::InitDelegate(info1_, DEVICE_A), E_OK); + SetSchemaInfo(info1_, GetUniqueSchema()); + ASSERT_NO_FATAL_FAILURE(PrepareEnv(info1_, true, true)); + /** + * @tc.steps: step2. Execute sql with invalid db. + * @tc.expected: step2. Fail + */ + auto res = SQLiteRelationalUtils::CheckExistDirtyLog(nullptr, DEVICE_SYNC_TABLE); + EXPECT_EQ(res.first, -E_INVALID_DB); + EXPECT_FALSE(res.second); + EXPECT_EQ(SQLiteRelationalUtils::ExecuteSql(nullptr, "", nullptr), -E_INVALID_DB); + /** + * @tc.steps: step3. Check dirty log with no exist table. + * @tc.expected: step3. No exist dirty log + */ + auto handle = GetSqliteHandle(info1_); + ASSERT_NE(handle, nullptr); + res = SQLiteRelationalUtils::CheckExistDirtyLog(handle, "NO_EXISTS_TABLE"); + EXPECT_EQ(res.first, E_OK); + EXPECT_FALSE(res.second); + /** + * @tc.steps: step4. Insert data and dirty log. + * @tc.expected: step4. Ok + */ + EXPECT_EQ(ExecuteSQL("INSERT OR REPLACE INTO DEVICE_SYNC_TABLE VALUES(1, 100)", info1_), E_OK); + std::string sql = "INSERT OR REPLACE INTO " + DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) + + "(data_key, timestamp, wtimestamp, flag, hash_key, extend_field) " + "VALUES(1, 1, 1, 0x02, 'error_hash1', '100')"; + EXPECT_EQ(ExecuteSQL(sql, info1_), E_OK); + EXPECT_EQ(CountTableData(info1_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), "hash_key='error_hash1'"), 1); + EXPECT_EQ(CountTableData(info1_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), "data_key='1'"), 2); // 2 log + /** + * @tc.steps: step5. Clean dirty log. + * @tc.expected: step5. Ok and no exist dirty log + */ + RelationalSchemaObject obj; + EXPECT_EQ(SQLiteRelationalUtils::CleanDirtyLog(handle, DEVICE_SYNC_TABLE, obj), E_OK); + EXPECT_EQ(CountTableData(info1_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), "hash_key='error_hash1'"), 1); + EXPECT_EQ(CountTableData(info1_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), "data_key='1'"), 2); // 2 log + obj.SetDistributedSchema(RDBDataGenerator::ParseSchema(GetSchema(info1_))); + EXPECT_EQ(SQLiteRelationalUtils::CleanDirtyLog(handle, DEVICE_SYNC_TABLE, obj), E_OK); + EXPECT_EQ(CountTableData(info1_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), "hash_key='error_hash1'"), 0); + EXPECT_EQ(CountTableData(info1_, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), "data_key='1'"), 1); + /** + * @tc.steps: step6. Clean no exist table dirty log. + * @tc.expected: step6. Fail + */ + EXPECT_EQ(ExecuteSQL("DROP TABLE DEVICE_SYNC_TABLE", info1_), E_OK); + EXPECT_EQ(SQLiteRelationalUtils::CleanDirtyLog(handle, DEVICE_SYNC_TABLE, obj), -1); // -1 is default error +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_knowledge_client_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_knowledge_client_test.cpp new file mode 100644 index 00000000..68c74e3b --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_knowledge_client_test.cpp @@ -0,0 +1,255 @@ +/* + * 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 "cloud_sync_log_table_manager.h" +#include "distributeddb_tools_unit_test.h" +#include "rdb_data_generator.h" +#include "relational_store_client.h" +#include "sqlite_relational_utils.h" +#include "table_info.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +namespace { + constexpr const char *DB_SUFFIX = ".db"; + constexpr const char *STORE_ID = "Relational_Store_ID"; + std::string g_dbDir; + std::string g_testDir; +} + +namespace { +class DistributedDBRDBKnowledgeClientTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp() override; + void TearDown() override; +protected: + static UtTableSchemaInfo GetTableSchema(const std::string &table); + static void SaveSchemaToMetaTable(sqlite3 *db, const std::string tableName, const TableInfo &tableInfo); + static void CreateDistributedTable(const std::vector &tableNames, + DistributedDB::TableSyncType tableSyncType); + static constexpr const char *KNOWLEDGE_TABLE = "KNOWLEDGE_TABLE"; + static constexpr const char *SYNC_TABLE = "SYNC_TABLE"; +}; + + +void DistributedDBRDBKnowledgeClientTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + LOGD("Test dir is %s", g_testDir.c_str()); + g_dbDir = g_testDir + "/"; + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); +} + +void DistributedDBRDBKnowledgeClientTest::TearDownTestCase(void) +{ +} + +void DistributedDBRDBKnowledgeClientTest::SetUp() +{ +} + +void DistributedDBRDBKnowledgeClientTest::TearDown() +{ + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); +} + +UtTableSchemaInfo DistributedDBRDBKnowledgeClientTest::GetTableSchema(const std::string &table) +{ + UtTableSchemaInfo tableSchema; + tableSchema.name = table; + UtFieldInfo field; + field.field.colName = "id"; + field.field.type = TYPE_INDEX; + field.field.primary = true; + tableSchema.fieldInfo.push_back(field); + field.field.primary = false; + field.field.colName = "int_field1"; + tableSchema.fieldInfo.push_back(field); + field.field.colName = "int_field2"; + tableSchema.fieldInfo.push_back(field); + field.field.colName = "int_field3"; + tableSchema.fieldInfo.push_back(field); + return tableSchema; +} + +void DistributedDBRDBKnowledgeClientTest::SaveSchemaToMetaTable(sqlite3 *db, const std::string tableName, + const TableInfo &tableInfo) +{ + RelationalSchemaObject schema; + schema.SetTableMode(DistributedDB::DistributedTableMode::SPLIT_BY_DEVICE); + schema.RemoveRelationalTable(tableName); + schema.AddRelationalTable(tableInfo); + + const Key schemaKey(DBConstant::RELATIONAL_SCHEMA_KEY, + DBConstant::RELATIONAL_SCHEMA_KEY + strlen(DBConstant::RELATIONAL_SCHEMA_KEY)); + Value schemaVal; + auto schemaStr = schema.ToSchemaString(); + EXPECT_FALSE(schemaStr.size() > SchemaConstant::SCHEMA_STRING_SIZE_LIMIT); + DBCommon::StringToVector(schemaStr, schemaVal); + EXPECT_EQ(SQLiteRelationalUtils::PutKvData(db, false, schemaKey, schemaVal), E_OK); +} + +void DistributedDBRDBKnowledgeClientTest::CreateDistributedTable(const std::vector &tableNames, + DistributedDB::TableSyncType tableSyncType) +{ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + for (const auto &tableName : tableNames) { + TableInfo tableInfo; + tableInfo.SetTableName(tableName); + tableInfo.SetTableSyncType(tableSyncType); + TrackerTable table111; + tableInfo.SetTrackerTable(table111); + DistributedTable distributedTable; + distributedTable.tableName = tableName; + tableInfo.SetDistributedTable(distributedTable); + std::unique_ptr tableManager = std::make_unique(); + EXPECT_NE(tableManager, nullptr); + EXPECT_EQ(SQLiteUtils::AnalysisSchema(db, tableName, tableInfo), E_OK); + std::vector fieldInfos = tableInfo.GetFieldInfos(); + EXPECT_EQ(SQLiteRelationalUtils::CreateRelationalMetaTable(db), E_OK); + EXPECT_EQ(SQLiteRelationalUtils::InitCursorToMeta(db, false, tableName), E_OK); + EXPECT_EQ(tableManager->CreateRelationalLogTable(db, tableInfo), E_OK); + EXPECT_EQ(tableManager->AddRelationalLogTableTrigger(db, tableInfo, ""), E_OK); + SQLiteRelationalUtils::SetLogTriggerStatus(db, true); + SaveSchemaToMetaTable(db, tableName, tableInfo); + } + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +void InsertDBData(const std::string &tableName, int count, sqlite3 *db) +{ + for (int i = 1; i <= count; i++) { + std::string sql = "INSERT INTO " + tableName + " VALUES(" + std::to_string(i) + ',' + std::to_string(i) + ',' + + std::to_string(i) + ',' + std::to_string(i) + ");"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } +} + +/** + * @tc.name: SetKnowledge001 + * @tc.desc: Test set knowledge schema. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBKnowledgeClientTest, SetKnowledge001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set knowledge source schema and clean deleted data. + * @tc.expected: step1. Ok + */ + UtTableSchemaInfo tableInfo = GetTableSchema(KNOWLEDGE_TABLE); + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + RDBDataGenerator::InitTableWithSchemaInfo(tableInfo, *db); + KnowledgeSourceSchema schema; + schema.tableName = KNOWLEDGE_TABLE; + schema.extendColNames.insert("id"); + schema.knowledgeColNames.insert("int_field1"); + schema.knowledgeColNames.insert("int_field2"); + EXPECT_EQ(SetKnowledgeSourceSchema(db, schema), OK); + EXPECT_EQ(CleanDeletedData(db, schema.tableName, 0u), OK); + /** + * @tc.steps: step2. Clean deleted data after insert one data. + * @tc.expected: step2. Ok + */ + InsertDBData(schema.tableName, 1, db); + EXPECT_EQ(CleanDeletedData(db, schema.tableName, 0u), OK); + /** + * @tc.steps: step3. Clean deleted data after delete one data. + * @tc.expected: step3. Ok + */ + std::string sql = std::string("DELETE FROM ").append(KNOWLEDGE_TABLE).append(" WHERE 1=1"); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + EXPECT_EQ(CleanDeletedData(db, schema.tableName, 10u), OK); // delete which cursor less than 10 + + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} + +/** + * @tc.name: SetKnowledge002 + * @tc.desc: Test set knowledge schema with invalid args. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBKnowledgeClientTest, SetKnowledge002, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set knowledge source schema and clean deleted data with null db. + * @tc.expected: step1. INVALID_ARGS + */ + KnowledgeSourceSchema schema; + schema.tableName = KNOWLEDGE_TABLE; + schema.extendColNames.insert("id"); + schema.knowledgeColNames.insert("int_field1"); + schema.knowledgeColNames.insert("int_field2"); + EXPECT_EQ(SetKnowledgeSourceSchema(nullptr, schema), INVALID_ARGS); + EXPECT_EQ(CleanDeletedData(nullptr, schema.tableName, 0u), INVALID_ARGS); + /** + * @tc.steps: step2. Set knowledge source schema and clean deleted data with null db. + * @tc.expected: step2. INVALID_ARGS + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + ASSERT_NE(db, nullptr); + schema.tableName = "UNKNOWN_TABLE"; + EXPECT_EQ(SetKnowledgeSourceSchema(db, schema), INVALID_ARGS); + EXPECT_EQ(CleanDeletedData(db, schema.tableName, 0u), OK); + + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} + +/** + * @tc.name: SetKnowledge003 + * @tc.desc: Test set knowledge schema after create distributed table. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBKnowledgeClientTest, SetKnowledge003, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create distributed table. + * @tc.expected: step1. Ok + */ + UtTableSchemaInfo tableInfo1 = GetTableSchema(KNOWLEDGE_TABLE); + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + RDBDataGenerator::InitTableWithSchemaInfo(tableInfo1, *db); + UtTableSchemaInfo tableInfo2 = GetTableSchema(SYNC_TABLE); + RDBDataGenerator::InitTableWithSchemaInfo(tableInfo2, *db); + CreateDistributedTable({SYNC_TABLE}, DistributedDB::CLOUD_COOPERATION); + + /** + * @tc.steps: step2. Set knowledge source schema. + * @tc.expected: step2. INVALID_ARGS + */ + KnowledgeSourceSchema schema; + schema.tableName = KNOWLEDGE_TABLE; + schema.extendColNames.insert("id"); + schema.knowledgeColNames.insert("int_field1"); + schema.knowledgeColNames.insert("int_field2"); + schema.tableName = SYNC_TABLE; + EXPECT_EQ(SetKnowledgeSourceSchema(db, schema), INVALID_ARGS); + + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_knowledge_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_knowledge_test.cpp new file mode 100644 index 00000000..ebb6f5c5 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_knowledge_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 "rdb_general_ut.h" +#include "relational_store_client.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +namespace { +class DistributedDBRDBKnowledgeTest : public RDBGeneralUt { +public: + void SetUp() override; +protected: + static UtDateBaseSchemaInfo GetDefaultSchema(); + static UtTableSchemaInfo GetTableSchema(const std::string &table); + static KnowledgeSourceSchema GetKnowledgeSchema(); + static constexpr const char *KNOWLEDGE_TABLE = "KNOWLEDGE_TABLE"; + static constexpr const char *SYNC_TABLE = "SYNC_TABLE"; + StoreInfo info1_ = {USER_ID, APP_ID, STORE_ID_1}; +}; + +void DistributedDBRDBKnowledgeTest::SetUp() +{ + RDBGeneralUt::SetUp(); + SetSchemaInfo(info1_, GetDefaultSchema()); + InitDatabase(info1_); +} + +UtDateBaseSchemaInfo DistributedDBRDBKnowledgeTest::GetDefaultSchema() +{ + UtDateBaseSchemaInfo info; + info.tablesInfo.push_back(GetTableSchema(KNOWLEDGE_TABLE)); + return info; +} + +UtTableSchemaInfo DistributedDBRDBKnowledgeTest::GetTableSchema(const std::string &table) +{ + UtTableSchemaInfo tableSchema; + tableSchema.name = table; + UtFieldInfo field; + field.field.colName = "id"; + field.field.type = TYPE_INDEX; + field.field.primary = true; + tableSchema.fieldInfo.push_back(field); + field.field.primary = false; + field.field.colName = "int_field1"; + tableSchema.fieldInfo.push_back(field); + field.field.colName = "int_field2"; + tableSchema.fieldInfo.push_back(field); + field.field.colName = "int_field3"; + tableSchema.fieldInfo.push_back(field); + return tableSchema; +} + +KnowledgeSourceSchema DistributedDBRDBKnowledgeTest::GetKnowledgeSchema() +{ + KnowledgeSourceSchema schema; + schema.extendColNames.insert("id"); + schema.knowledgeColNames.insert("int_field1"); + schema.knowledgeColNames.insert("int_field2"); + schema.tableName = SYNC_TABLE; + return schema; +} + +/** + * @tc.name: SetKnowledge001 + * @tc.desc: Test set knowledge schema. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBKnowledgeTest, SetKnowledge001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set knowledge source schema and clean deleted data. + * @tc.expected: step1. Ok + */ + auto db = GetSqliteHandle(info1_); + ASSERT_NE(db, nullptr); + KnowledgeSourceSchema schema; + schema.tableName = KNOWLEDGE_TABLE; + schema.extendColNames.insert("id"); + schema.knowledgeColNames.insert("int_field1"); + schema.knowledgeColNames.insert("int_field2"); + EXPECT_EQ(SetKnowledgeSourceSchema(db, schema), OK); + EXPECT_EQ(CleanDeletedData(db, schema.tableName, 0u), OK); + /** + * @tc.steps: step2. Clean deleted data after insert one data. + * @tc.expected: step2. Ok + */ + EXPECT_EQ(InsertLocalDBData(0, 1, info1_), E_OK); + EXPECT_EQ(CleanDeletedData(db, schema.tableName, 0u), OK); + /** + * @tc.steps: step3. Clean deleted data after delete one data. + * @tc.expected: step3. Ok + */ + std::string sql = std::string("DELETE FROM ").append(KNOWLEDGE_TABLE).append(" WHERE 1=1"); + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + EXPECT_EQ(CleanDeletedData(db, schema.tableName, 10u), OK); // delete which cursor less than 10 +} + +/** + * @tc.name: SetKnowledge002 + * @tc.desc: Test set knowledge schema with invalid args. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBKnowledgeTest, SetKnowledge002, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set knowledge source schema and clean deleted data with null db. + * @tc.expected: step1. INVALID_ARGS + */ + KnowledgeSourceSchema schema; + schema.tableName = KNOWLEDGE_TABLE; + schema.extendColNames.insert("id"); + schema.knowledgeColNames.insert("int_field1"); + schema.knowledgeColNames.insert("int_field2"); + EXPECT_EQ(SetKnowledgeSourceSchema(nullptr, schema), INVALID_ARGS); + EXPECT_EQ(CleanDeletedData(nullptr, schema.tableName, 0u), INVALID_ARGS); + /** + * @tc.steps: step2. Set knowledge source schema and clean deleted data with null db. + * @tc.expected: step2. INVALID_ARGS + */ + auto db = GetSqliteHandle(info1_); + ASSERT_NE(db, nullptr); + schema.tableName = "UNKNOWN_TABLE"; + EXPECT_EQ(SetKnowledgeSourceSchema(db, schema), INVALID_ARGS); + EXPECT_EQ(CleanDeletedData(db, schema.tableName, 0u), OK); +} + +/** + * @tc.name: SetKnowledge003 + * @tc.desc: Test set knowledge schema after create distributed table. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBKnowledgeTest, SetKnowledge003, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create distributed table. + * @tc.expected: step1. Ok + */ + UtDateBaseSchemaInfo info; + info.tablesInfo.push_back(GetTableSchema(KNOWLEDGE_TABLE)); + info.tablesInfo.push_back(GetTableSchema(SYNC_TABLE)); + SetSchemaInfo(info1_, info); + ASSERT_EQ(DistributedDB::RDBGeneralUt::InitDelegate(info1_), E_OK); + ASSERT_EQ(CreateDistributedTable(info1_, SYNC_TABLE), E_OK); + /** + * @tc.steps: step2. Set knowledge source schema. + * @tc.expected: step2. INVALID_ARGS + */ + auto db = GetSqliteHandle(info1_); + ASSERT_NE(db, nullptr); + EXPECT_EQ(SetKnowledgeSourceSchema(db, GetKnowledgeSchema()), INVALID_ARGS); +} + +/** + * @tc.name: SetKnowledge004 + * @tc.desc: Test set knowledge schema after create tracker table. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBKnowledgeTest, SetKnowledge004, TestSize.Level0) +{ + /** + * @tc.steps: step1. Create tracker table. + * @tc.expected: step1. Ok + */ + UtDateBaseSchemaInfo info; + info.tablesInfo.push_back(GetTableSchema(SYNC_TABLE)); + info.tablesInfo.push_back(GetTableSchema(KNOWLEDGE_TABLE)); + SetSchemaInfo(info1_, info); + ASSERT_EQ(DistributedDB::RDBGeneralUt::InitDelegate(info1_), E_OK); + ASSERT_EQ(DistributedDB::RDBGeneralUt::SetTrackerTables(info1_, {SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Set knowledge source schema. + * @tc.expected: step2. INVALID_ARGS + */ + auto db = GetSqliteHandle(info1_); + ASSERT_NE(db, nullptr); + EXPECT_EQ(SetKnowledgeSourceSchema(db, GetKnowledgeSchema()), INVALID_ARGS); +} + +/** + * @tc.name: SetKnowledge005 + * @tc.desc: Test set knowledge schema and then drop table. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyuchen + */ +HWTEST_F(DistributedDBRDBKnowledgeTest, SetKnowledge005, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set knowledge source schema and clean deleted data. + * @tc.expected: step1. Ok + */ + auto db = GetSqliteHandle(info1_); + ASSERT_NE(db, nullptr); + KnowledgeSourceSchema schema; + schema.tableName = KNOWLEDGE_TABLE; + schema.extendColNames.insert("id"); + schema.knowledgeColNames.insert("int_field1"); + schema.knowledgeColNames.insert("int_field2"); + EXPECT_EQ(SetKnowledgeSourceSchema(db, schema), OK); + + /** + * @tc.steps: step2. Create inverted table. + * @tc.expected: step2. ok + */ + std::string inverted = std::string(KNOWLEDGE_TABLE) + "_inverted"; + std::string sql = "CREATE VIRTUAL TABLE IF NOT EXISTS " + inverted + " USING fts3(col1, col2);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + + sql = "SELECT count(*) FROM " + inverted + ";"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + + /** + * @tc.steps: step3. Drop knowledge table. + * @tc.expected: step3. ok + */ + sql = "DROP TABLE IF EXISTS " + std::string(KNOWLEDGE_TABLE) + ";"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + + /** + * @tc.steps: step4. Inverted table not exist. + * @tc.expected: step4. ok + */ + sql = "SELECT count(*) FROM " + inverted + ";"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_ERROR); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp new file mode 100644 index 00000000..f3c51b40 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/store_test/rdb/distributeddb_rdb_upgrade_test.cpp @@ -0,0 +1,148 @@ +/* + * 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 "rdb_general_ut.h" +#include "sqlite_relational_utils.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +namespace { +class DistributedDBRDBUpgradeTest : public RDBGeneralUt { +public: + void SetUp() override; + void TearDown() override; +protected: + void InitUpgradeDelegate(); + void InitNoJsonTrackerSchema(); + static constexpr const char *DEVICE_SYNC_TABLE = "DEVICE_SYNC_TABLE"; +}; + +void DistributedDBRDBUpgradeTest::SetUp() +{ + RDBGeneralUt::SetUp(); +} + +void DistributedDBRDBUpgradeTest::TearDown() +{ + RDBGeneralUt::TearDown(); +} + +void DistributedDBRDBUpgradeTest::InitUpgradeDelegate() +{ + RelationalStoreDelegate::Option option; + option.tableMode = DistributedTableMode::COLLABORATION; + SetOption(option); + auto info1 = GetStoreInfo1(); + const std::vector filedInfo = { + {{"id", TYPE_INDEX, true, false}, true}, {{"name1", TYPE_INDEX, false, true}, false}, + {{"name2", TYPE_INDEX, false, true}, false} + }; + UtDateBaseSchemaInfo schemaInfo = { + .tablesInfo = {{.name = DEVICE_SYNC_TABLE, .fieldInfo = filedInfo}} + }; + RDBGeneralUt::SetSchemaInfo(info1, schemaInfo); + ASSERT_EQ(BasicUnitTest::InitDelegate(info1, "dev1"), E_OK); +} + +void DistributedDBRDBUpgradeTest::InitNoJsonTrackerSchema() +{ + std::string keyStr = "relational_tracker_schema"; + Key key(keyStr.begin(), keyStr.end()); + std::string schemaStr = R"({"SCHEMA_TYPE":"TRACKER","TABLES":[ + {"NAME": "DEVICE_SYNC_TABLE", "EXTEND_NAME": "id", + "TRACKER_NAMES": ["id", "name1", "name2"], "TRACKER_ACTION": false}]})"; + Value value(schemaStr.begin(), schemaStr.end()); + ASSERT_EQ(PutMetaData(GetStoreInfo1(), key, value), E_OK); +} + +/** + * @tc.name: UpgradeTracker001 + * @tc.desc: Test rdb upgrade extend field from no json to json. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBUpgradeTest, UpgradeTracker001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Init delegate and set tracker schema. + * @tc.expected: step1. Ok + */ + ASSERT_NO_FATAL_FAILURE(InitUpgradeDelegate()); + auto info1 = GetStoreInfo1(); + EXPECT_EQ(SetTrackerTables(info1, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert local data and log, low version schema. + * @tc.expected: step2. Ok + */ + InsertLocalDBData(0, 1, info1); + std::string sql = "UPDATE " + DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) + " SET extend_field=1"; + EXPECT_EQ(ExecuteSQL(sql, info1), E_OK); + ASSERT_NO_FATAL_FAILURE(InitNoJsonTrackerSchema()); + EXPECT_EQ(CloseDelegate(info1), E_OK); + ASSERT_NO_FATAL_FAILURE(InitUpgradeDelegate()); + /** + * @tc.steps: step3. Set tracker table and create distributed table. + * @tc.expected: step3. Ok + */ + auto store = GetDelegate(info1); + ASSERT_NE(store, nullptr); + EXPECT_EQ(CreateDistributedTable(info1, DEVICE_SYNC_TABLE), E_OK); + EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), + " json_valid(extend_field) = 0"), 0); + EXPECT_EQ(SetTrackerTables(info1, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step4. Check log extend field. + * @tc.expected: step4. Ok + */ + EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), + " json_type(extend_field) = 'object'"), 1); + EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), + " json_valid(extend_field) = 0"), 0); +} + +/** + * @tc.name: UpgradeTracker002 + * @tc.desc: Test rdb upgrade extend field is no json format. + * @tc.type: FUNC + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRDBUpgradeTest, UpgradeTracker002, TestSize.Level0) +{ + /** + * @tc.steps: step1. Init delegate and set tracker schema. + * @tc.expected: step1. Ok + */ + ASSERT_NO_FATAL_FAILURE(InitUpgradeDelegate()); + auto info1 = GetStoreInfo1(); + EXPECT_EQ(SetTrackerTables(info1, {DEVICE_SYNC_TABLE}), E_OK); + /** + * @tc.steps: step2. Insert local data and log update extend_field to empty str. + * @tc.expected: step2. Ok + */ + InsertLocalDBData(0, 1, info1); + std::string sql = "UPDATE " + DBCommon::GetLogTableName(DEVICE_SYNC_TABLE) + " SET extend_field=''"; + EXPECT_EQ(ExecuteSQL(sql, info1), E_OK); + EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), + " json_valid(extend_field) = 0"), 1); + /** + * @tc.steps: step3. Set tracker again and check log. + * @tc.expected: step3. Ok + */ + EXPECT_EQ(SetTrackerTables(info1, {DEVICE_SYNC_TABLE}), E_OK); + EXPECT_EQ(CountTableData(info1, DBCommon::GetLogTableName(DEVICE_SYNC_TABLE), + " json_valid(extend_field) = 0"), 0); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_client_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_client_test.cpp new file mode 100644 index 00000000..2dc60fb5 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_client_test.cpp @@ -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. + */ +#include "cloud_db_sync_utils_test.h" + +namespace DistributedDB { + void CloudDBSyncUtilsTest::GetHashKey(const std::string &tableName, const std::string &condition, sqlite3 *db, + std::vector> &hashKey) + { + sqlite3_stmt *stmt = nullptr; + std::string sql = "select hash_key from " + DBCommon::GetLogTableName(tableName) + " where " + condition; + EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + std::vector blob; + EXPECT_EQ(SQLiteUtils::GetColumnBlobValue(stmt, 0, blob), E_OK); + hashKey.push_back(blob); + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + } +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_test.cpp index 479520ad..b4c904c6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_test.cpp @@ -328,19 +328,4 @@ namespace DistributedDB { EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback, reinterpret_cast(count), nullptr), SQLITE_OK); } - - void CloudDBSyncUtilsTest::GetHashKey(const std::string &tableName, const std::string &condition, sqlite3 *db, - std::vector> &hashKey) - { - sqlite3_stmt *stmt = nullptr; - std::string sql = "select hash_key from " + DBCommon::GetLogTableName(tableName) + " where " + condition; - EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); - while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - std::vector blob; - EXPECT_EQ(SQLiteUtils::GetColumnBlobValue(stmt, 0, blob), E_OK); - hashKey.push_back(blob); - } - int errCode; - SQLiteUtils::ResetStatement(stmt, true, errCode); - } } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_async_download_assets_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_async_download_assets_test.cpp index e5a6d4c4..76ca2402 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_async_download_assets_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_async_download_assets_test.cpp @@ -16,8 +16,10 @@ #include "cloud/assets_download_manager.h" #include "cloud/cloud_storage_utils.h" +#include "cloud/mock_icloud_sync_storage_interface.h" #include "cloud/virtual_asset_loader.h" #include "cloud/virtual_cloud_data_translate.h" +#include "cloud/virtual_cloud_syncer.h" #include "cloud_db_sync_utils_test.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" @@ -63,6 +65,8 @@ protected: void CloseDb(); void DoSkipAssetDownload(SkipAssetTestParamT param); void UpdateLocalData(sqlite3 *&db, const std::string &tableName, int32_t begin, int32_t end); + void DeleteLocalData(sqlite3 *&db, const std::string &tableName); + void CheckLogTable(sqlite3 *&db, const std::string &tableName, int count); void UpdateLocalAndCheckUploadCount(const bool &isAsync, const int &dataCount, const int &expectCount); std::string storePath_; sqlite3 *db_ = nullptr; @@ -273,7 +277,7 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncDownloadAssetConfig001, * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncDownloadAssetConfig002, TestSize.Level0) +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncDownloadAssetConfig002, TestSize.Level1) { /** * @tc.steps: step1. Set valid param twice @@ -338,7 +342,7 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncDownloadAssetConfig002, * @tc.require: * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncDownloadAssetConfig003, TestSize.Level0) +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncDownloadAssetConfig003, TestSize.Level1) { /** * @tc.steps: step1. Insert cloud data @@ -401,7 +405,7 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, FinishListener001, TestSize. * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncComplexDownload001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncComplexDownload001, TestSize.Level1) { /** * @tc.steps: step1. Set max download task 1 @@ -439,7 +443,7 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncComplexDownload001, Tes * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncComplexDownload002, TestSize.Level0) +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncComplexDownload002, TestSize.Level1) { /** * @tc.steps: step1. Set max download task 1 @@ -545,7 +549,7 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload001, Te * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload002, TestSize.Level0) +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload002, TestSize.Level1) { /** * @tc.steps: step1. Insert cloud data @@ -633,7 +637,7 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload003, Te * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload004, TestSize.Level0) +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload004, TestSize.Level1) { /** * @tc.steps: step1. Set async config @@ -736,7 +740,7 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload005, Te * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncNormalDownload001, TestSize.Level0) +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncNormalDownload001, TestSize.Level1) { /** * @tc.steps: step1. Register observer @@ -821,7 +825,6 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncNormalDownload002, Test * @tc.expected: step5. Download task changes from 1 to 0 */ auto manager = RuntimeContext::GetInstance()->GetAssetsDownloadManager(); - EXPECT_EQ(manager->GetCurrentDownloadCount(), 1u); std::this_thread::sleep_for(std::chrono::seconds(1)); EXPECT_EQ(manager->GetCurrentDownloadCount(), 0u); /** @@ -996,6 +999,44 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncNormalDownload004, Test virtualAssetLoader_->ForkDownload(nullptr); } +/** + * @tc.name: AsyncNormalDownload005 + * @tc.desc: Test concurrent async download of assets and sync data. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncNormalDownload005, TestSize.Level1) +{ + /** + * @tc.steps: step1. Set max download task 1 + * @tc.expected: step1. ok + */ + AsyncDownloadAssetsConfig config; + config.maxDownloadTask = 12; + EXPECT_EQ(RuntimeConfig::SetAsyncDownloadAssetsConfig(config), OK); + /** + * @tc.steps: step2. Insert cloud data and sync concurrently + * @tc.expected: step2. ok + */ + const int cloudCount = 200; + auto schema = GetSchema(); + int threadNum = 10; + CloudSyncOption option = GetAsyncCloudSyncOption(); + thread *syncThreads[threadNum]; + for (int i = 0; i < threadNum; i++) { + syncThreads[i] = new thread([&]() { + EXPECT_EQ(RDBDataGenerator::InsertCloudDBData(0, cloudCount, 0, schema, virtualCloudDb_), OK); + RelationalTestUtils::CloudBlockSync(option, delegate_); + DeleteLocalData(db_, "AsyncDownloadAssetsTest"); + }); + } + for (auto &thread : syncThreads) { + thread->join(); + delete thread; + } +} + /** * @tc.name: AsyncAbnormalDownload006 * @tc.desc: Test abnormal async download. @@ -1067,6 +1108,21 @@ void DistributedDBCloudAsyncDownloadAssetsTest::UpdateLocalData( LOGW("update local data finished"); } +void DistributedDBCloudAsyncDownloadAssetsTest::DeleteLocalData(sqlite3 *&db, const std::string &tableName) +{ + const string sql = "delete from " + tableName + " where pk >= 0;"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + LOGW("delete local data finished"); +} + +void DistributedDBCloudAsyncDownloadAssetsTest::CheckLogTable(sqlite3 *&db, const std::string &tableName, int count) +{ + const string sql = "select COUNT(*) from " + DBCommon::GetLogTableName(tableName) + " where data_key>0;"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(count), nullptr), SQLITE_OK); + LOGW("check log table finished"); +} + void DistributedDBCloudAsyncDownloadAssetsTest::UpdateLocalAndCheckUploadCount(const bool &isAsync, const int &dataCount, const int &expectCount) { @@ -1141,7 +1197,7 @@ void DistributedDBCloudAsyncDownloadAssetsTest::UpdateLocalAndCheckUploadCount(c HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload007, TestSize.Level1) { int cloudCount = 10; - UpdateLocalAndCheckUploadCount(true, cloudCount, cloudCount); + EXPECT_NO_FATAL_FAILURE(UpdateLocalAndCheckUploadCount(true, cloudCount, cloudCount)); } /** @@ -1253,10 +1309,10 @@ void DistributedDBCloudAsyncDownloadAssetsTest::DoSkipAssetDownload(SkipAssetTes HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, SkipAssetDownloadTest001, TestSize.Level1) { /** - * @tc.expected: step1. sync return OK, and has 0 inconsistent records + * @tc.expected: step1. sync return OK, and has 1 inconsistent records */ SkipAssetTestParamT param = {.downloadRes = SKIP_ASSET, .useBatch = true, .useAsync = true, - .startIndex = 0, .expectInconsistentCount = 0, .expectSyncRes = OK}; + .startIndex = 0, .expectInconsistentCount = 1, .expectSyncRes = OK}; DoSkipAssetDownload(param); } @@ -1348,4 +1404,161 @@ HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload008, Te EXPECT_EQ(downloadCount, cloudCount); virtualAssetLoader_->ForkBatchDownload(nullptr); } + +/** + * @tc.name: AsyncAbnormalDownload010 + * @tc.desc: Test assets is async downloading when delete local data. + * @tc.type: FUNC + * @tc.require: + * @tc.author: tankaisheng + */ +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload010, TestSize.Level1) +{ + /** + * @tc.steps: step1. Set max download task 1 + * @tc.expected: step1. ok + */ + AsyncDownloadAssetsConfig config; + config.maxDownloadTask = 1; + config.maxDownloadAssetsCount = 2; + EXPECT_EQ(RuntimeConfig::SetAsyncDownloadAssetsConfig(config), OK); + /** + * @tc.steps: step2. Insert cloud data + * @tc.expected: step2. ok + */ + const int cloudCount = 2000; + auto schema = GetSchema(); + EXPECT_EQ(RDBDataGenerator::InsertCloudDBData(0, cloudCount, 0, schema, virtualCloudDb_), OK); + /** + * @tc.steps: step3. Sync + * @tc.expected: step3. ok + */ + CloudSyncOption option = GetAsyncCloudSyncOption(); + RelationalTestUtils::CloudBlockSync(option, delegate_); + /** + * @tc.steps: step4. Delete local data. + * @tc.expected: step4. ok + */ + DeleteLocalData(db_, "AsyncDownloadAssetsTest"); + /** + * @tc.steps: step5. Check log table. + * @tc.expected: step5. ok + */ + CheckLogTable(db_, "AsyncDownloadAssetsTest", 0); +} + +/** + * @tc.name: TriggerAsyncTask001 + * @tc.desc: Test trigger async task. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, TriggerAsyncTask001, TestSize.Level1) +{ + auto storage = std::make_shared(); + ASSERT_NE(storage, nullptr); + auto proxy = StorageProxy::GetCloudDb(storage.get()); + ASSERT_NE(proxy, nullptr); + auto syncer = new(std::nothrow) VirtualCloudSyncer(proxy); + ASSERT_NE(syncer, nullptr); + /** + * @tc.steps: step1. Trigger async task with not exist table contain assets. + */ + syncer->TriggerAsyncTask(); + /** + * @tc.steps: step2. Trigger async task with exist table contain assets. + */ + EXPECT_CALL(*storage, IsExistTableContainAssets).WillRepeatedly(testing::Return(true)); + EXPECT_CALL(*storage, GetDownloadAssetTable).WillRepeatedly([]() { + std::pair> res; + return res; + }); + syncer->TriggerAsyncTask(); + syncer->WaitTaskFinished(); + /** + * @tc.steps: step3. Async trigger and wait finished. + */ + std::thread t1([syncer]() { + for (int i = 0; i < 1000; ++i) { + syncer->TriggerAsyncTask(); + } + }); + std::thread t2([syncer]() { + for (int i = 0; i < 1000; ++i) { + syncer->WaitTaskFinished(); + } + }); + t1.join(); + t2.join(); + syncer->Close(); + RefObject::KillAndDecObjRef(syncer); +} + +/** + * @tc.name: AsyncAbnormalDownload011 + * @tc.desc: Test set reference when async downloading. + * @tc.type: FUNC + * @tc.require: + * @tc.author: tankaisheng + */ +HWTEST_F(DistributedDBCloudAsyncDownloadAssetsTest, AsyncAbnormalDownload011, TestSize.Level1) +{ + /** + * @tc.steps: step1. Set max download task 1 + * @tc.expected: step1. ok + */ + AsyncDownloadAssetsConfig config; + config.maxDownloadTask = 1; + config.maxDownloadAssetsCount = 2; + EXPECT_EQ(RuntimeConfig::SetAsyncDownloadAssetsConfig(config), OK); + /** + * @tc.steps: step2. Insert cloud data + * @tc.expected: step2. ok + */ + const int cloudCount = 100; + auto schema = GetSchema(); + EXPECT_EQ(RDBDataGenerator::InsertCloudDBData(0, cloudCount, 0, schema, virtualCloudDb_), OK); + /** + * @tc.steps: step3. Fork download set reference + * @tc.expected: step3. ok + */ + TableReferenceProperty tableReferenceProperty; + tableReferenceProperty.sourceTableName = "AsyncDownloadAssetsTest"; + tableReferenceProperty.targetTableName = "TABLE1"; + std::map columns; + columns["int_field"] = "int_field"; + tableReferenceProperty.columns = columns; + CloudSyncOption option = GetAsyncCloudSyncOption(); + + std::mutex mtx; + std::condition_variable cv; + bool t2_started = false; + + std::thread t1([this, option, &mtx, &cv, &t2_started]() { + { + std::unique_lock lock(mtx); + t2_started = true; + cv.notify_one(); + } + RelationalTestUtils::CloudBlockSync(option, delegate_); + }); + + std::thread t2([this, tableReferenceProperty, &mtx, &cv, &t2_started] { + std::unique_lock lock(mtx); + cv.wait(lock, [&]{ return t2_started; }); + EXPECT_EQ(delegate_->SetReference({tableReferenceProperty}), OK); + }); + + t1.join(); + t2.join(); + /** + * @tc.steps: step5. Check download count + * @tc.expected: step5. ok + */ + auto [status, downloadCount] = delegate_->GetDownloadingAssetsCount(); + EXPECT_EQ(status, OK); + EXPECT_NE(downloadCount, 0); + virtualAssetLoader_->ForkBatchDownload(nullptr); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_syncer_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_syncer_test.cpp index 514201fd..2628a7d2 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_syncer_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_syncer_test.cpp @@ -315,7 +315,7 @@ void DistributedDBCloudKvSyncerTest::CheckUploadAbnormal(OpType opType, int64_t * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync001, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync001, TestSize.Level1) { auto cloudHook = (ICloudSyncStorageHook *) singleStore_->GetCloudKvStore(); ASSERT_NE(cloudHook, nullptr); @@ -346,14 +346,14 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync001, TestSize.Level0) cloudHook->SetSyncFinishHook([&syncCnt, this] { LOGD("sync finish times:%d", ++syncCnt); if (syncCnt == 1) { // 1 is the first sync - CheckUploadAbnormal(OpType::UPDATE, 1L); // 1 is expected count + CheckUploadAbnormal(OpType::UPDATE, 1L, true); // 1 is expected count } else { CheckUploadAbnormal(OpType::UPDATE, 1L, true); // 1 is expected count } comSyncCv.notify_all(); }); BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); - BlockCompensatedSync(syncCnt, 2); // 2 is sync times + BlockCompensatedSync(syncCnt, 1); // 2 is sync times virtualCloudDb_->ForkUpload(nullptr); cloudHook->SetSyncFinishHook(nullptr); } @@ -365,7 +365,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync001, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync002, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync002, TestSize.Level1) { auto cloudHook = (ICloudSyncStorageHook *) singleStore_->GetCloudKvStore(); ASSERT_NE(cloudHook, nullptr); @@ -423,7 +423,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync002, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync003, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync003, TestSize.Level1) { auto cloudHook = (ICloudSyncStorageHook *) singleStore_->GetCloudKvStore(); ASSERT_NE(cloudHook, nullptr); @@ -480,7 +480,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync003, TestSize.Level0) * @tc.require: * @tc.author: chenghuitao */ -HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync004, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync004, TestSize.Level1) { /** * @tc.steps:step1. Device A inserts data and synchronizes @@ -502,7 +502,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync004, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync005, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync005, TestSize.Level1) { /** * @tc.steps:step1. Put 1 record to cloud @@ -571,7 +571,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, QueryParsingProcessTest001, TestSize.Le * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvSyncerTest, UploadFinished001, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, UploadFinished001, TestSize.Level1) { Key key = {'k'}; Value value = {'v'}; @@ -602,7 +602,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, UploadFinished001, TestSize.Level0) * @tc.require: * @tc.author: liufuchenxing */ -HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers001, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers001, TestSize.Level1) { Key key = {'k'}; Value value = {'v'}; @@ -649,7 +649,7 @@ void DistributedDBCloudKvSyncerTest::PutKvBatchDataAndSyncCloud(CloudSyncOption * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers002, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers002, TestSize.Level1) { /** * @tc.steps: step1. kvDelegatePtrS1_ put 200 data and sync to cloud. @@ -732,7 +732,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers002, TestSize.Leve * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers003, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers003, TestSize.Level1) { /** * @tc.steps: step1. put k v by user1. @@ -788,7 +788,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers003, TestSize.Leve * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers004, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers004, TestSize.Level1) { /** * @tc.steps: step1. put k v by user1 and sync to cloud. @@ -835,7 +835,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers004, TestSize.Leve * @tc.require: * @tc.author: suyue */ -HWTEST_F(DistributedDBCloudKvSyncerTest, AbnormalCloudKvExecutorTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, AbnormalCloudKvExecutorTest001, TestSize.Level1) { /** * @tc.steps: step1. Call PutCloudData interface with different opType when para is invalid. @@ -900,7 +900,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, AbnormalCloudKvExecutorTest002, TestSiz /** * @tc.steps: step2. open db and Call FillCloudLog. - * @tc.expected: step2. return E_OK. + * @tc.expected: step2. return -SQLITE_ERROR, because the table is not exist. */ uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; std::string fileUrl = g_testDir + "/test.db"; @@ -909,9 +909,9 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, AbnormalCloudKvExecutorTest002, TestSiz data.isCloudVersionRecord = true; ret = cloudKvObj.FillCloudLog({db, true}, OpType::INSERT, data, "", recorder); - EXPECT_EQ(ret, E_OK); + EXPECT_EQ(ret, -SQLITE_ERROR); ret = cloudKvObj.FillCloudLog({db, true}, OpType::DELETE, data, "", recorder); - EXPECT_EQ(ret, E_OK); + EXPECT_EQ(ret, -SQLITE_ERROR); EXPECT_EQ(sqlite3_close_v2(db), E_OK); } @@ -922,7 +922,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, AbnormalCloudKvExecutorTest002, TestSiz * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBCloudKvSyncerTest, DeviceCollaborationTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, DeviceCollaborationTest001, TestSize.Level1) { /** * @tc.steps: step1. open db with DEVICE_COLLABORATION. @@ -973,7 +973,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, DeviceCollaborationTest001, TestSize.Le * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudKvSyncerTest, DeviceCollaborationTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, DeviceCollaborationTest002, TestSize.Level1) { /** * @tc.steps: step1. open db with DEVICE_COLLABORATION. @@ -1069,7 +1069,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, DeviceCollaborationTest003, TestSize.Le * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithKvAndCloud001, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithKvAndCloud001, TestSize.Level1) { /** * @tc.steps: step1. put k1 v1 by user1 and sync between devices. @@ -1111,4 +1111,58 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithKvAndCloud001, TestSize.Level0) EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue), OK); EXPECT_EQ(actualValue, value2); } + +/** + * @tc.name: ClearCloudWatermarkTest001. + * @tc.desc: Test clear kv cloud watermark + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudKvSyncerTest, ClearCloudWatermarkTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. put (k1, v1)(k2, v2) and sync + * @tc.expected: step1. return ok. + */ + EXPECT_EQ(kvDelegatePtrS1_->Put(KEY_1, VALUE_1), OK); + EXPECT_EQ(kvDelegatePtrS2_->Put(KEY_2, VALUE_2), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + /** + * @tc.steps: step1. clear kv cloud watermark. + * @tc.expected: step1. return ok. + */ + ClearKvMetaDataOption option; + option.type = ClearKvMetaOpType::CLEAN_CLOUD_WATERMARK; + EXPECT_EQ(kvDelegatePtrS1_->ClearMetaData(option), OK); + EXPECT_EQ(kvDelegatePtrS2_->ClearMetaData(option), OK); +} + +/** + * @tc.name: UploadBlockTest001. + * @tc.desc: Test upload block and put get data + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBCloudKvSyncerTest, UploadBlockTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. put (k1, v1) + * @tc.expected: step1. return ok. + */ + EXPECT_EQ(kvDelegatePtrS1_->Put(KEY_1, VALUE_1), OK); + /** + * @tc.steps: step2. fork upload and sync + * @tc.expected: step2. return ok. + */ + virtualCloudDb_->ForkUpload([this](const std::string &, VBucket &) { + EXPECT_EQ(kvDelegatePtrS1_->Put(KEY_2, VALUE_2), OK); + Value value; + EXPECT_EQ(kvDelegatePtrS1_->Get(KEY_2, value), OK); + EXPECT_EQ(value, VALUE_2); + }); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp index a5b82a24..16758ec3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp @@ -397,7 +397,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync001, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync002, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync002, TestSize.Level1) { /** * @tc.steps: step1. store1 put (k1,v1) store2 put (k2,v2) @@ -459,7 +459,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync002, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync003, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync003, TestSize.Level1) { /** * @tc.steps: step1. store1 put (k1,v1) store2 put (k1,v2) @@ -496,7 +496,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync003, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync004, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync004, TestSize.Level1) { /** * @tc.steps: step1. store1 put (k1,v1) and both sync @@ -555,7 +555,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync005, TestSize.Level1) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync006, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync006, TestSize.Level1) { Key k1 = {'k', '1'}; Key k2 = {'k', '2'}; @@ -581,7 +581,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync006, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync007, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync007, TestSize.Level1) { Key k1 = {'k', '1'}; Key k2 = {'k', '2'}; @@ -611,7 +611,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync007, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync008, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync008, TestSize.Level1) { Key k1 = {'k', '1'}; Value v1 = {'v', '1'}; @@ -636,7 +636,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync008, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync009, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync009, TestSize.Level1) { Key k1 = {'k', '1'}; Key k2 = {'k', '2'}; @@ -663,7 +663,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync009, TestSize.Level0) * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync010, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync010, TestSize.Level1) { // add , sync to cloud with user1 Key key1 = {'k', '1'}; @@ -710,7 +710,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync010, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync011, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync011, TestSize.Level1) { std::shared_ptr g_adapter = std::make_shared(); RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); @@ -732,7 +732,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync011, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync012, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync012, TestSize.Level1) { KvStoreNbDelegate *memoryDB1 = nullptr; KvStoreNbDelegate::Option option1; @@ -760,7 +760,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync012, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync013, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync013, TestSize.Level1) { KvStoreNbDelegate* kvDelegatePtrS3_ = nullptr; KvStoreNbDelegate::Option option; @@ -819,7 +819,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync014, TestSize.Level1) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync015, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync015, TestSize.Level1) { Key key = {'k'}; Value expectValue = {'v'}; @@ -848,7 +848,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync015, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync016, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync016, TestSize.Level1) { Key key = {'k', '1'}; Value value1 = {'v', '1'}; @@ -878,7 +878,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync016, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync017, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync017, TestSize.Level1) { Key key = {'k'}; Value value = {'v'}; @@ -897,7 +897,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync017, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync018, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync018, TestSize.Level1) { /** * @tc.steps:step1. Get two Memory DB. @@ -955,7 +955,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync018, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync019, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync019, TestSize.Level1) { Key k1 = {'k', '1'}; Value v1 = {'v', '1'}; @@ -974,7 +974,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync019, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync020, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync020, TestSize.Level1) { /** * @tc.steps:step1. Inserts a piece of data. @@ -1009,7 +1009,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync020, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync021, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync021, TestSize.Level1) { /** * @tc.steps:step1. store2 GetCloudVersion. @@ -1094,7 +1094,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync022, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync023, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync023, TestSize.Level1) { Key k1 = {'k', '1'}; Value v1 = {'v', '1'}; @@ -1116,7 +1116,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync023, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync024, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync024, TestSize.Level1) { /** * @tc.steps:step1. Device A inserts data and synchronizes, then Device B synchronizes. @@ -1155,7 +1155,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync024, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync025, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync025, TestSize.Level1) { virtualCloudDb_->SetBlockTime(1000); // block query 1000ms auto option = g_CloudSyncoption; @@ -1173,7 +1173,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync025, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync026, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync026, TestSize.Level1) { /** * @tc.steps:step1. Create a database with the DEVICE_COLLABORATION mode on device1. @@ -1216,7 +1216,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync026, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync027, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync027, TestSize.Level1) { /** * @tc.steps:step1. put 1 record and sync. @@ -1246,7 +1246,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync027, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync028, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync028, TestSize.Level1) { /** * @tc.steps:step1. put 1 record and sync. @@ -1327,7 +1327,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync029, TestSize.Level3) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync030, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync030, TestSize.Level1) { /** * @tc.steps:step1. Create a database. @@ -1373,7 +1373,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync030, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync031, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync031, TestSize.Level1) { /** * @tc.steps:step1. put 1 record and sync. @@ -1404,7 +1404,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync031, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync032, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync032, TestSize.Level1) { /** * @tc.steps:step1. put 10 records. @@ -1451,7 +1451,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync032, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync033, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync033, TestSize.Level1) { /** * @tc.steps:step1. put local records {k1, v1} {k2, v2} and sync to cloud. @@ -1496,7 +1496,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync033, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync034, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync034, TestSize.Level1) { /** * @tc.steps:step1. put data which size > maxUploadSize. @@ -1542,7 +1542,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync034, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync035, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync035, TestSize.Level1) { /** * @tc.steps:step1. put local records {k1, v1} and sync to cloud. @@ -1597,7 +1597,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync035, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync036, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync036, TestSize.Level1) { /** * @tc.steps:step1. put data and SetCloudSyncConfig. @@ -1624,7 +1624,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync036, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync037, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync037, TestSize.Level1) { /** * @tc.steps:step1. deviceA put {k1, v1} and sync to cloud. @@ -1670,7 +1670,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync037, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync038, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync038, TestSize.Level1) { /** * @tc.steps:step1. deviceA put {k1, v1} and sync to cloud. @@ -1720,7 +1720,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync038, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync039, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync039, TestSize.Level1) { /** * @tc.steps:step1. deviceA put {k1, v1} {k2, v2} and sync to cloud. @@ -1774,7 +1774,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync039, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync040, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync040, TestSize.Level1) { /** * @tc.steps:step1. deviceA put {k1, v1} and sync to cloud. @@ -1860,7 +1860,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync041, TestSize.Level1) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync042, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync042, TestSize.Level1) { /** * @tc.steps:step1. put 10 records. @@ -1921,7 +1921,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync042, TestSize.Level0) * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync043, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync043, TestSize.Level1) { /** * @tc.steps:step1. put 10 records. @@ -1977,7 +1977,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync043, TestSize.Level0) * @tc.require: * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync044, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync044, TestSize.Level1) { /** * @tc.steps: step1. store1 put (k1,v1) and (k2,v2) @@ -2033,7 +2033,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync044, TestSize.Level0) * @tc.require: * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync045, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync045, TestSize.Level1) { /** * @tc.steps:step1. put 10 records. @@ -2072,7 +2072,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync045, TestSize.Level0) * @tc.require: * @tc.author: chenghuitao */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync046, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync046, TestSize.Level1) { /** * @tc.steps: step1. store1 put (k1,v1) and (k2,v2) @@ -2128,7 +2128,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync046, TestSize.Level0) * @tc.require: * @tc.author: suyue */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync047, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync047, TestSize.Level1) { /** * @tc.steps: step1. put 20 records. @@ -2179,7 +2179,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync047, TestSize.Level0) * @tc.require: * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync048, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync048, TestSize.Level1) { /** * @tc.steps: step1. deviceB put {k1, v1} {k2, v2} and sync to cloud @@ -2220,7 +2220,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync048, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync049, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync049, TestSize.Level1) { /** * @tc.steps: step1. put {k, v} @@ -2282,7 +2282,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync049, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync050, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync050, TestSize.Level1) { /** * @tc.steps: step1. Set the retry count to 1 @@ -2332,7 +2332,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync050, TestSize.Level0) * @tc.require: * @tc.author: suyuchen */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync051, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync051, TestSize.Level1) { /** * @tc.steps: step1. Set the retry count to 0 @@ -2382,7 +2382,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync051, TestSize.Level0) * @tc.require: * @tc.author: suyuchen */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync052, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync052, TestSize.Level1) { /** * @tc.steps: step1. Set the retry count to 2 @@ -2434,7 +2434,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync052, TestSize.Level0) * @tc.require: * @tc.author: suyuchen */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync053, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync053, TestSize.Level1) { /** * @tc.steps: step1. Set the retry count to 0 @@ -2487,4 +2487,197 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync053, TestSize.Level0) } virtualCloudDb_->ForkInsertConflict(nullptr); } + +/** + * @tc.name: NormalSync054 + * @tc.desc: test get and put interface execute + * @tc.type: FUNC + * @tc.require: + * @tc.author: tankaisheng + */ +HWTEST_F(DistributedDBCloudKvTest, NormalSync054, TestSize.Level1) +{ + /** + * @tc.steps:step1. deviceA put {k1, v1} and sync to cloud. + * @tc.expected: step1. ok. + */ + communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); + Key key = {'k', '1'}; + Value expectValue1 = {'v', '1'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, expectValue1), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + + /** + * @tc.steps:step2. deviceB sync to cloud. + * @tc.expected: step2. ok. + */ + communicatorAggregator_->SetLocalDeviceId("DEVICES_B"); + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + Value actualValue1; + EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue1), OK); + EXPECT_EQ(actualValue1, expectValue1); + + EXPECT_EQ(kvDelegatePtrS2_->StartTransaction(), OK); + EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue1), OK); + EXPECT_EQ(actualValue1, expectValue1); + EXPECT_TRUE(kvDelegatePtrS2_->Commit() == OK); +} + +/** + * @tc.name: KvSupportEncryptTest001 + * @tc.desc: Test sync when different security label and encryption para is set + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudKvTest, KvSupportEncryptTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. sync when security label is S4 and encryption is not supported + * @tc.expected: step1. return SECURITY_OPTION_CHECK_ERROR. + */ + std::shared_ptr g_adapter = std::make_shared(); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); + KvStoreNbDelegate* kvDelegatePtrS3_ = nullptr; + KvStoreNbDelegate::Option option; + option.secOption.securityLabel = S4; + EXPECT_EQ(GetKvStore(kvDelegatePtrS3_, STORE_ID_3, option), OK); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, SECURITY_OPTION_CHECK_ERROR); + + /** + * @tc.steps: step2. sync when security label is S4 and encryption is supported + * @tc.expected: step2. return OK. + */ + CloudSyncConfig config; + config.isSupportEncrypt = true; + kvDelegatePtrS3_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, OK); + CloseKvStore(kvDelegatePtrS3_, STORE_ID_3); + + /** + * @tc.steps: step3. sync when security label is not set and encryption is supported + * @tc.expected: step3. return ok. + */ + kvDelegatePtrS1_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + + /** + * @tc.steps: step4. sync when security label is not set and encryption is not supported + * @tc.expected: step4. return ok. + */ + config.isSupportEncrypt = false; + kvDelegatePtrS1_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); +} + +/** + * @tc.name: KvSupportEncryptTest002 + * @tc.desc: Test sync when encryption para is set multiple times + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudKvTest, KvSupportEncryptTest002, TestSize.Level1) +{ + /** + * @tc.steps: step1. sync when isSupportEncrypt is set to true for the first time + * @tc.expected: step1. return OK. + */ + std::shared_ptr g_adapter = std::make_shared(); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); + KvStoreNbDelegate* kvDelegatePtrS3_ = nullptr; + KvStoreNbDelegate::Option option; + option.secOption.securityLabel = S4; + EXPECT_EQ(GetKvStore(kvDelegatePtrS3_, STORE_ID_3, option), OK); + CloudSyncConfig config; + config.isSupportEncrypt = true; + kvDelegatePtrS3_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, OK); + + /** + * @tc.steps: step2. sync when isSupportEncrypt is set to false for the second time + * @tc.expected: step2. return SECURITY_OPTION_CHECK_ERROR. + */ + config.isSupportEncrypt = false; + kvDelegatePtrS3_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, SECURITY_OPTION_CHECK_ERROR); + + /** + * @tc.steps: step3. sync when isSupportEncrypt is set to true for the third time + * @tc.expected: step3. return OK. + */ + config.isSupportEncrypt = true; + kvDelegatePtrS3_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, OK); + CloseKvStore(kvDelegatePtrS3_, STORE_ID_3); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); +} + +/** + * @tc.name: KvSupportEncryptTest003 + * @tc.desc: Test GetCloudSyncConfig when GetCloudKvStore is nullptr + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudKvTest, KvSupportEncryptTest003, TestSize.Level1) +{ + SQLiteSingleVerNaturalStore store; + EXPECT_EQ(store.GetCloudKvStore(), nullptr); + CloudSyncConfig config = store.GetCloudSyncConfig(); + EXPECT_EQ(config.isSupportEncrypt, false); +} + +/** + * @tc.name: KvSupportEncryptTest004 + * @tc.desc: Test sync when security label change and different encryption para is set + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudKvTest, KvSupportEncryptTest004, TestSize.Level1) +{ + /** + * @tc.steps: step1. sync when security label is S2 and different encryption para is set + * @tc.expected: step1. return OK. + */ + std::shared_ptr g_adapter = std::make_shared(); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); + KvStoreNbDelegate* kvDelegatePtrS3_ = nullptr; + KvStoreNbDelegate::Option option; + option.secOption.securityLabel = S2; + EXPECT_EQ(GetKvStore(kvDelegatePtrS3_, STORE_ID_3, option), OK); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, OK); + CloudSyncConfig config; + config.isSupportEncrypt = true; + kvDelegatePtrS3_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, OK); + CloseKvStore(kvDelegatePtrS3_, STORE_ID_3); + + /** + * @tc.steps: step2. sync when security label is S4 and different encryption para is set + * @tc.expected: step2. support encrypt return OK, not support encrypt return SECURITY_OPTION_CHECK_ERROR. + */ + option.secOption.securityLabel = S4; + EXPECT_EQ(GetKvStore(kvDelegatePtrS3_, STORE_ID_3, option), OK); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, SECURITY_OPTION_CHECK_ERROR); + config.isSupportEncrypt = true; + kvDelegatePtrS3_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, OK); + CloseKvStore(kvDelegatePtrS3_, STORE_ID_3); + + /** + * @tc.steps: step3. sync when security label is S1 and different encryption para is set + * @tc.expected: step3. return OK. + */ + option.secOption.securityLabel = S1; + EXPECT_EQ(GetKvStore(kvDelegatePtrS3_, STORE_ID_3, option), OK); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, OK); + config.isSupportEncrypt = true; + kvDelegatePtrS3_->SetCloudSyncConfig(config); + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, OK); + CloseKvStore(kvDelegatePtrS3_, STORE_ID_3); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); +} } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kvstore_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kvstore_test.cpp index 95797c58..2cd4b6e4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kvstore_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kvstore_test.cpp @@ -27,6 +27,7 @@ #include "virtual_communicator_aggregator.h" #include "virtual_cloud_db.h" #include "sqlite_utils.h" +#include "time_helper.h" using namespace testing::ext; using namespace DistributedDB; using namespace DistributedDBUnitTest; @@ -105,6 +106,8 @@ void DistributedDBCloudKvStoreTest::TearDownTestCase() if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error!"); } + g_CloudSyncoption.users.clear(); + g_CloudSyncoption.devices.clear(); } void DistributedDBCloudKvStoreTest::SetUp() @@ -1448,7 +1451,7 @@ HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest013, TestSize.Level0) */ Key k1 = {'k', '1'}; Value v1 = {'v', '1'}; - deviceB_->PutData(k1, v1, 1u, 0); // 1 is current timestamp + deviceB_->PutData(k1, v1, TimeHelper::GetSysCurrentTime() + TimeHelper::BASE_OFFSET, 0); /** * @tc.steps: step2. sync between devices * * @tc.expected: step2. insert successfully @@ -1889,7 +1892,7 @@ HWTEST_F(DistributedDBCloudKvStoreTest, ObserverDataChangeTest002, TestSize.Leve Value actualValue; EXPECT_EQ(kvDelegatePtrS2_->Get(k1, actualValue), OK) ; EXPECT_EQ(actualValue, v1); - + std::this_thread::sleep_for(std::chrono::milliseconds(1)); // sleep for 1ms Key k2 = {'k', '2'}; Value v2 = {'v', '2'}; ASSERT_EQ(kvDelegatePtrS1_->Put(k1, v2), OK); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_only_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_only_test.cpp index 6af3557f..8e021817 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_only_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_only_test.cpp @@ -785,7 +785,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly001, * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly002, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -824,7 +824,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly002, * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly003, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -883,7 +883,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly003, * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly004, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly004, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -946,7 +946,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly004, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly005, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly005, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -974,7 +974,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly005, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly006, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly006, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -988,7 +988,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly006, * @tc.steps:step2. Download assets which cloud no found * @tc.expected: step2. return ASSET_NOT_FOUND_FOR_DOWN_ONLY. */ - std::vector inValue = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};; + std::vector inValue = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; std::map> assets; assets["assets"] = {ASSET_COPY.name + "10"}; Query query = Query::Select().From(ASSETS_TABLE_NAME).In("id", inValue).And().AssetsOnly(assets); @@ -1002,7 +1002,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly006, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly007, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly007, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1063,7 +1063,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly007, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly008, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly008, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1077,7 +1077,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly008, * @tc.steps:step2. Download assets which local no found * @tc.expected: step2. return ASSET_NOT_FOUND_FOR_DOWN_ONLY. */ - std::vector inValue = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};; + std::vector inValue = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; std::map> assets; assets["assets"] = {ASSET_COPY.name + "0"}; std::map> assets1; @@ -1094,7 +1094,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly008, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly009, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly009, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1124,7 +1124,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly009, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly010, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly010, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1178,7 +1178,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly010, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly011, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly011, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1264,7 +1264,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly012, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly013, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly013, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1295,7 +1295,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly013, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly014, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly014, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1323,7 +1323,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly014, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly015, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly015, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1388,7 +1388,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly015, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly016, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly016, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1437,7 +1437,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly016, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly017, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly017, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1472,7 +1472,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly017, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly018, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly018, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1512,7 +1512,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly018, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly019, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly019, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1540,7 +1540,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly019, * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly020, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly020, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1601,7 +1601,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly020, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly021, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly021, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1633,7 +1633,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly021, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly022, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly022, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1663,7 +1663,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly022, * @tc.require: * @tc.author: luoguo */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly023, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly023, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -1685,5 +1685,78 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly023, EndGroup().And().BeginGroup().EqualTo("id", 0).And().AssetsOnly(assets1).EndGroup(); PriorityLevelSync(2, query, SyncMode::SYNC_MODE_CLOUD_FORCE_PULL, DBStatus::OK); } + +/** + * @tc.name: DownloadAssetsOnly024 + * @tc.desc: test download task stop after the reference is set + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, DownloadAssetsOnly024, TestSize.Level1) +{ + /** + * @tc.steps:step1. init data + * @tc.expected: step1. return OK. + */ + int dataCount = 10; + InsertCloudDBData(0, dataCount, 0, ASSETS_TABLE_NAME); + /** + * @tc.steps:step2. Set reference + * @tc.expected: step2. return OK. + */ + TableReferenceProperty tableReferenceProperty; + tableReferenceProperty.sourceTableName = NO_PRIMARY_TABLE; + tableReferenceProperty.targetTableName = COMPOUND_PRIMARY_TABLE; + std::map columns; + columns[COL_ID] = COL_ID; + tableReferenceProperty.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); + columns[COL_NAME] = COL_NAME; + tableReferenceProperty.columns = columns; + int cnt = 0; + int downCnt = 2; + /** + * @tc.steps:step3. fork download, set reference during downloading + * @tc.expected: step3. return OK. + */ + g_virtualAssetLoader->ForkDownload([&cnt, &tableReferenceProperty, downCnt]( + const std::string &tableName, std::map &) { + cnt++; + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + if (cnt != downCnt) { + return; + } + std::thread t1([&tableReferenceProperty]() { + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); + }); + t1.detach(); + }); + /** + * @tc.steps:step4. sync and check download count + * @tc.expected: step4. return OK. + */ + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::CLOUD_ERROR); + EXPECT_NE(cnt, 0); + EXPECT_NE(cnt, dataCount); +} + +/** + * @tc.name: SetAssetsConfig001 + * @tc.desc: Test set async download assets config + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsOnlyTest, SetAssetsConfig001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Set valid param + * @tc.expected: step1. ok + */ + AsyncDownloadAssetsConfig config; + config.maxDownloadTask = 10; + EXPECT_EQ(RuntimeConfig::SetAsyncDownloadAssetsConfig(config), OK); +} } // namespace #endif // RELATIONAL_STORE diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_test.cpp index f47b0b18..214dec31 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_test.cpp @@ -135,16 +135,20 @@ void GetCloudDbSchema(DataBaseSchema &dataBaseSchema) dataBaseSchema.tables.push_back(assetsTableSchema); } -void GenerateDataRecords( - int64_t begin, int64_t count, int64_t gidStart, std::vector &record, std::vector &extend) +std::pair, std::vector> GenerateDataRecords(int64_t begin, int64_t count, + int64_t gidStart, bool hasAsset) { + std::pair, std::vector> res; + auto &[record, extend] = res; for (int64_t i = begin; i < begin + count; i++) { Assets assets; - Asset asset = ASSET_COPY; - asset.name = ASSET_COPY.name + std::to_string(i); - assets.emplace_back(asset); - asset.name = ASSET_COPY.name + std::to_string(i) + "_copy"; - assets.emplace_back(asset); + if (hasAsset) { + Asset asset = ASSET_COPY; + asset.name = ASSET_COPY.name + std::to_string(i); + assets.emplace_back(asset); + asset.name = ASSET_COPY.name + std::to_string(i) + "_copy"; + assets.emplace_back(asset); + } VBucket data; data.insert_or_assign(COL_ID, i); data.insert_or_assign(COL_NAME, "name" + std::to_string(i)); @@ -161,6 +165,13 @@ void GenerateDataRecords( log.insert_or_assign(CloudDbConstant::GID_FIELD, std::to_string(i + gidStart)); extend.push_back(log); } + return res; +} + +void GenerateDataRecords( + int64_t begin, int64_t count, int64_t gidStart, std::vector &record, std::vector &extend) +{ + std::tie(record, extend) = GenerateDataRecords(begin, count, gidStart, true); } void InsertLocalData(sqlite3 *&db, int64_t begin, int64_t count, const std::string &tableName, bool isAssetNull = true) @@ -281,11 +292,10 @@ void CheckLockStatus(sqlite3 *db, int startId, int endId, LockStatus lockStatus) } } -void InsertCloudDBData(int64_t begin, int64_t count, int64_t gidStart, const std::string &tableName) +void InsertCloudDBData(int64_t begin, int64_t count, int64_t gidStart, const std::string &tableName, + bool hasAsset = true) { - std::vector record; - std::vector extend; - GenerateDataRecords(begin, count, gidStart, record, extend); + auto [record, extend] = GenerateDataRecords(begin, count, gidStart, hasAsset); if (tableName == ASSETS_TABLE_NAME_SHARED) { for (auto &vBucket: record) { vBucket.insert_or_assign(CloudDbConstant::CLOUD_OWNER, std::string("cloudA")); @@ -802,7 +812,7 @@ void DistributedDBCloudSyncerDownloadAssetsTest::DataStatusTest007() * @tc.require: * @tc.author: liufuchenxing */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest001, TestSize.Level1) { /** * @tc.steps:step1. Mock asset download interface. @@ -844,7 +854,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId001, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -872,7 +882,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId001, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId002, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -899,7 +909,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId002, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId003, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -926,7 +936,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId003, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId004, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId004, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -953,7 +963,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId004, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId005, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId005, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -980,7 +990,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId005, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId006, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId006, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -1007,7 +1017,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId006, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId007, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId007, TestSize.Level1) { CloudSyncConfig config; config.maxUploadCount = 200; // max upload 200 @@ -1062,7 +1072,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId007, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId008, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId008, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -1096,7 +1106,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId008, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId009, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId009, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -1122,7 +1132,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId009, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId010, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId010, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -1149,7 +1159,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId010, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId011, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId011, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -1173,7 +1183,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId011, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId012, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId012, TestSize.Level1) { /** * @tc.steps:step1. set extend size missing then sync, check the asseid. @@ -1211,7 +1221,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId012, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId013, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId013, TestSize.Level1) { /** * @tc.steps:step1. local insert data and sync, then delete local data and insert new data @@ -1241,7 +1251,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId013, TestSize.Le * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId014, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId014, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -1299,7 +1309,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId014, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId015, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId015, TestSize.Level1) { /** * @tc.steps:step1. local insert data and fork batchinsert return CLOUD_NETWORK_ERROR, then sync @@ -1349,7 +1359,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId015, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId016, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId016, TestSize.Level1) { /** * @tc.steps:step1. local insert data and sync, then delete last local data @@ -1377,7 +1387,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId016, TestSize.Le * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId017, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId017, TestSize.Level1) { /** * @tc.steps:step1. local insert data and sync,check cursor. @@ -1403,7 +1413,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId017, TestSize.Le * @tc.require: * @tc.author: zhaoliang */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId018, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId018, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync, check the local assetId. @@ -1429,7 +1439,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId018, TestSize.Le * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest002, TestSize.Level1) { /** * @tc.steps:step1. Mock asset download return CLOUD_ERROR. @@ -1466,7 +1476,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest003, TestSize.Level1) { /** * @tc.steps:step1. Mock asset download return CLOUD_ERROR. @@ -1508,7 +1518,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest004, TestSize.Level1) { /** * @tc.steps:step1. Mock asset download return CLOUD_ERROR. @@ -1548,7 +1558,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest005, TestSize.Level1) { /** * @tc.steps:step1. init data and sync @@ -1591,7 +1601,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId019, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId019, TestSize.Level1) { /** * @tc.steps:step1. local insert assets and sync. @@ -1618,7 +1628,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId019, TestSize.Le * @tc.require: * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId020, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId020, TestSize.Level1) { CloudSyncConfig config; config.maxUploadCount = 200; // max upload 200 @@ -1695,7 +1705,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId020, TestSize.Le * @tc.require: * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId021, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId021, TestSize.Level1) { CloudSyncConfig config; config.maxUploadCount = 200; // max upload 200 @@ -1741,7 +1751,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId021, TestSize.Le * @tc.require: * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId022, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId022, TestSize.Level1) { CloudSyncConfig config; config.maxUploadCount = 200; // max upload 200 @@ -1787,7 +1797,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId022, TestSize.Le * @tc.require: * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId023, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId023, TestSize.Level1) { /** * @tc.steps:step1. set extend size missing then sync, check the asseid. @@ -1827,7 +1837,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId023, TestSize.Le * @tc.require: * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId024, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId024, TestSize.Level1) { /** * @tc.steps:step1. set extend size missing then sync, check the asseid. @@ -1867,7 +1877,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId024, TestSize.Le * @tc.require: * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId025, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId025, TestSize.Level1) { CloudSyncConfig config; config.maxUploadCount = 200; // max upload 200 @@ -1945,7 +1955,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId025, TestSize.Le * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest001, TestSize.Level1) { /** * @tc.steps:step1. init data for the different asset, sync and check flag @@ -1977,7 +1987,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest001, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest002, TestSize.Level1) { /** * @tc.steps:step1. init data for the same asset, sync and check flag @@ -2008,7 +2018,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest002, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest003, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -2083,7 +2093,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest003, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest004, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -2147,7 +2157,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest004, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest005, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -2205,7 +2215,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest005, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest006, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -2265,7 +2275,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest006, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest001, TestSize.Level1) { DataStatusTest001(false); } @@ -2277,7 +2287,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest001, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest002, TestSize.Level1) { DataStatusTest001(true); } @@ -2289,7 +2299,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest002, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest003, TestSize.Level1) { DataStatusTest003(); } @@ -2301,7 +2311,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest003, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest004, TestSize.Level1) { DataStatusTest004(); } @@ -2313,7 +2323,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest004, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest005, TestSize.Level1) { DataStatusTest005(); } @@ -2325,7 +2335,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest005, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest006, TestSize.Level1) { DataStatusTest006(); } @@ -2337,7 +2347,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest006, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest007, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest007, TestSize.Level1) { DataStatusTest007(); } @@ -2349,7 +2359,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest007, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest008, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest008, TestSize.Level1) { /** * @tc.steps:step1. init local data @@ -2402,7 +2412,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest008, Test * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest001, TestSize.Level1) { RuntimeContext::GetInstance()->SetBatchDownloadAssets(true); /** @@ -2440,7 +2450,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest001, TestS * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest002, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -2491,7 +2501,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest002, TestS * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest003, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -2557,13 +2567,46 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest003, TestS g_virtualAssetLoader->SetRemoveLocalAssetsCallback(nullptr); } +/** + * @tc.name: DownloadAssetTest004 + * @tc.desc: Test asset download failed with no asset data + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest004, TestSize.Level1) +{ + /** + * @tc.steps:step1. init data + * @tc.expected: step1. return OK. + */ + int cloudCount = 10; // 10 is num of cloud + InsertCloudDBData(0, cloudCount, 0, ASSETS_TABLE_NAME, true); + InsertCloudDBData(cloudCount, cloudCount, cloudCount, ASSETS_TABLE_NAME, false); + /** + * @tc.steps:step2. Set asset download status error and sync + * @tc.expected: step2. sync successful but download assets fail. + */ + g_virtualAssetLoader->SetDownloadStatus(DBStatus::CLOUD_ERROR); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::CLOUD_ERROR); + /** + * @tc.steps:step3. Check FLAG_DEVICE_CLOUD_INCONSISTENCY data + * @tc.expected: step3. 10 data is cloud consistency because no asset. + */ + std::string logName = DBCommon::GetLogTableName(ASSETS_TABLE_NAME); + std::string sql = "SELECT COUNT(1) FROM " + logName + " WHERE flag & 0x20 = 0"; + int count = 0; + ASSERT_EQ(SQLiteUtils::GetCountBySql(db, sql, count), E_OK); + EXPECT_EQ(count, cloudCount); +} + /** * @tc.name: RecordLockFuncTest001 * @tc.desc: UNLOCKING->UNLOCKING Synchronous download failure wholly. * @tc.type: FUNC * @tc.author: lijun */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, RecordLockFuncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, RecordLockFuncTest001, TestSize.Level1) { /** * @tc.steps:step1. init local data @@ -2638,7 +2681,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, RecordLockFuncTest001, Test * @tc.type: FUNC * @tc.author: lijun */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, RecordLockFuncTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, RecordLockFuncTest002, TestSize.Level1) { /** * @tc.steps:step1. init local data, modify data Status and initiate synchronization @@ -2839,7 +2882,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, CloudTaskStatusTest002, Tes * @tc.require: * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, CompensatedSyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, CompensatedSyncTest001, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -2897,5 +2940,56 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, CompensatedSyncTest001, Tes EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, reinterpret_cast(0u), nullptr), SQLITE_OK); } + +/** + * @tc.name: CloudCooperationTrackerTableSync001 + * @tc.desc: test CLOUD_COOPERATION tracker table sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: tankaisheng + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, CloudCooperationTrackerTableSync001, TestSize.Level1) +{ + /** + * @tc.steps:step1. init data + * @tc.expected: step1. return OK. + */ + int dataCount = 120; + InsertCloudDBData(0, dataCount, 0, ASSETS_TABLE_NAME); + TrackerSchema trackerSchema = { + .tableName = ASSETS_TABLE_NAME, .extendColNames = {"int_field1"}, .trackerColNames = {"int_field1"}}; + g_delegate->SetTrackerTable(trackerSchema); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::OK); +} + +/** + * @tc.name: FillAssetId026 + * @tc.desc: Test if assetId is null when removedevicedata in FLAG_AND_DATA + * @tc.type: FUNC + * @tc.require: + * @tc.author: tankaisheng + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId026, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert assets and sync, check the local assetId. + * @tc.expected: step1. return OK. + */ + int localCount = 10; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); + + /** + * @tc.steps:step2. remove device data then check record. + * @tc.expected: step2. return OK. + */ + g_delegate->RemoveDeviceData("", FLAG_AND_DATA); + CheckLocaLAssets(ASSETS_TABLE_NAME, "", {}); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); + g_delegate->RemoveDeviceData("", CLEAR_SHARED_TABLE); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); +} } // namespace #endif // RELATIONAL_STORE diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp index af0442cd..2736b6bc 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp @@ -236,9 +236,9 @@ static void Expect2GetInfoByPrimaryKeyOrGidCall() HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockTest001, TestSize.Level1) { TaskId taskId = 1u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); @@ -288,10 +288,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockTest001, TestSize.Lev HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockTest002, TestSize.Level1) { TaskId taskId = 6u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); @@ -334,10 +334,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockTest002, TestSize.Lev HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest002, TestSize.Level1) { TaskId taskId = 1u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -367,10 +367,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest002, TestSiz HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest003, TestSize.Level1) { TaskId taskId = 1u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -425,10 +425,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest003, TestSiz HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest00302, TestSize.Level1) { TaskId taskId = 4u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -469,10 +469,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest00302, TestS HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest004, TestSize.Level1) { TaskId taskId = 1u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -514,10 +514,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest004, TestSiz HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest00402, TestSize.Level1) { TaskId taskId = 3u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -570,10 +570,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest00402, TestS HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest005, TestSize.Level1) { TaskId taskId = 1u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -602,10 +602,10 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest005, TestSiz HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockTest006, TestSize.Level1) { TaskId taskId = 1u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); @@ -720,14 +720,14 @@ static void ExpectGetInfoByPrimaryKeyOrGidCall() HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockTest007, TestSize.Level1) { TaskId taskId = 1u; - EXPECT_CALL(*g_iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly([](const QuerySyncObject &, const Timestamp &, bool, bool, int64_t &count) { count = 1; return E_OK; }); - EXPECT_CALL(*g_iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*g_iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*g_iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*g_iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_lock_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_lock_test.cpp index 5a900ecc..49ed8e24 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_lock_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_lock_test.cpp @@ -77,6 +77,7 @@ std::shared_ptr g_virtualCloudDb; std::shared_ptr g_virtualAssetLoader; std::shared_ptr g_virtualCloudDataTranslate; SyncProcess g_syncProcess; +std::vector> g_allSyncProcess; std::condition_variable g_processCondition; std::mutex g_processMutex; IRelationalStore *g_store = nullptr; @@ -187,6 +188,7 @@ void DistributedDBCloudSyncerLockTest::Init() g_virtualCloudDb = make_shared(); g_virtualAssetLoader = make_shared(); g_syncProcess = {}; + g_allSyncProcess = {}; ASSERT_EQ(g_delegate->SetCloudDB(g_virtualCloudDb), DBStatus::OK); ASSERT_EQ(g_delegate->SetIAssetLoader(g_virtualAssetLoader), DBStatus::OK); DataBaseSchema dataBaseSchema; @@ -324,6 +326,7 @@ void DistributedDBCloudSyncerLockTest::CallSync(const CloudSyncOption &option, D bool finish = false; SyncProcess last; auto callback = [&last, &cv, &dataMutex, &finish](const std::map &process) { + g_allSyncProcess.push_back(process); for (const auto &item: process) { if (item.second.process == DistributedDB::FINISHED) { { @@ -461,7 +464,7 @@ void DistributedDBCloudSyncerLockTest::CheckUploadAbnormal(OpType opType, int64_ * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, RDBUnlockCloudSync001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, RDBUnlockCloudSync001, TestSize.Level1) { /** * @tc.steps:step1. init data and sync with none lock @@ -471,8 +474,13 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, RDBUnlockCloudSync001, TestSize.Level int localCount = 10; InsertLocalData(0, cloudCount, ASSETS_TABLE_NAME, true); InsertCloudDBData(0, localCount, 0, ASSETS_TABLE_NAME); + int queryIdx = 0; + g_virtualCloudDb->ForkQuery([&queryIdx](const std::string &, VBucket &) { + queryIdx++; + }); CloudSyncOption option = PrepareOption(Query::Select().FromTable({ ASSETS_TABLE_NAME }), LockAction::NONE); CallSync(option); + EXPECT_EQ(queryIdx, 1L); /** * @tc.steps:step2. insert or replace, check version @@ -486,6 +494,48 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, RDBUnlockCloudSync001, TestSize.Level reinterpret_cast(cloudCount), nullptr), SQLITE_OK); } +/** + * @tc.name: RDBUnlockCloudSync002 + * @tc.desc: Test sync with multi table + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerLockTest, RDBUnlockCloudSync002, TestSize.Level1) +{ + /** + * @tc.steps:step1. init data and sync with none lock + * @tc.expected: step1. return ok. + */ + std::string tableName = "tea"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "CREATE TABLE IF NOT EXISTS tea(" + COL_ID + " INTEGER PRIMARY KEY," + + COL_NAME + " TEXT ," + COL_ASSET + " ASSET," + COL_ASSETS + " ASSETS" + ");"), SQLITE_OK); + ASSERT_EQ(g_delegate->CreateDistributedTable(tableName, CLOUD_COOPERATION), DBStatus::OK); + DataBaseSchema dataBaseSchema; + GetCloudDbSchema(dataBaseSchema); + TableSchema teaSchema = {.name = tableName, .sharedTableName = tableName + "_shared", + .fields = CLOUD_FIELDS}; + dataBaseSchema.tables.push_back(teaSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + int cloudCount = 10; + InsertCloudDBData(0, cloudCount, 0, ASSETS_TABLE_NAME); + InsertCloudDBData(0, cloudCount, 0, tableName); + int queryIdx = 0; + g_virtualCloudDb->ForkQuery([&queryIdx](const std::string &, VBucket &) { + queryIdx++; + }); + + /** + * @tc.steps:step2. sync and check process count + * @tc.expected: step2. return ok. + */ + CloudSyncOption option = + PrepareOption(Query::Select().FromTable({ ASSETS_TABLE_NAME, tableName }), LockAction::NONE); + CallSync(option); + EXPECT_EQ(queryIdx, 2L); + EXPECT_EQ(g_allSyncProcess.size(), 4u); +} + /** * @tc.name: RDBLockSyncTest001 * @tc.desc: Test sync deleted data which status is LOCKING. @@ -527,7 +577,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, RDBLockSyncTest001, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync001, TestSize.Level1) { /** * @tc.steps:step1. init data and set hook before upload, update cloud data which gid is 1 @@ -563,7 +613,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync001, TestSize.Lev * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync002, TestSize.Level1) { TestConflictSync001(true); } @@ -575,7 +625,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync002, TestSize.Lev * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync003, TestSize.Level1) { TestConflictSync001(false); } @@ -587,7 +637,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync003, TestSize.Lev * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync004, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, RDBConflictCloudSync004, TestSize.Level1) { /** * @tc.steps:step1. init data and sync @@ -687,7 +737,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest001, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest002, TestSize.Level1) { /** * @tc.steps:step1. init data @@ -714,6 +764,12 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest002, TestSize.Level0) index++; }); CallSync(option); + /** + * @tc.steps:step3. sync again and check cursor + * @tc.expected: step3. return ok. + */ + index = 0; + CallSync(option); } /** @@ -723,7 +779,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest002, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest001, TestSize.Level1) { /** * @tc.steps:step1. init cloud assert {a, b1, b2} @@ -755,7 +811,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest001, TestSize. * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest002, TestSize.Level1) { /** * @tc.steps:step1. init cloud assert {a, b1, b2} and sync to local @@ -821,7 +877,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest002, TestSize. * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest003, TestSize.Level1) { /** * @tc.steps:step1. init cloud assert {a, b1, b2} and sync to local @@ -877,7 +933,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest003, TestSize. * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, RecordConflictTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, RecordConflictTest001, TestSize.Level1) { /** * @tc.steps:step1. init data and sync @@ -926,7 +982,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, RecordConflictTest001, TestSize.Level * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest003, TestSize.Level1) { /** * @tc.steps:step1. init cloud data and sync @@ -969,7 +1025,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest003, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest004, TestSize.Level1) { /** * @tc.steps:step1. init cloud data @@ -1009,7 +1065,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest004, TestSize.Level0) * @tc.require: * @tc.author: suyue */ -HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest006, TestSize.Level1) { RuntimeContext::GetInstance()->SetBatchDownloadAssets(true); /** @@ -1067,7 +1123,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest006, TestSize.Level0) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync001, TestSize.Level1) { /** * @tc.steps:step1. insert local data and sync @@ -1099,7 +1155,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync001, TestSize.Level g_cloudStoreHook->SetSyncFinishHook([&callCount, this]() { LOGD("sync finish times:%d", ++callCount); if (callCount == 1) { // 1 is the normal sync - CheckUploadAbnormal(OpType::UPDATE, 1L); // 1 is expected count + CheckUploadAbnormal(OpType::UPDATE, 1L, true); // 1 is expected count } else { CheckUploadAbnormal(OpType::UPDATE, 1L, true); // 1 is expected count } @@ -1109,7 +1165,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync001, TestSize.Level { std::unique_lock lock(g_processMutex); bool result = g_processCondition.wait_for(lock, std::chrono::seconds(WAIT_TIME), - [&callCount]() { return callCount == 2; }); // 2 is sync times + [&callCount]() { return callCount == 1; }); // 2 is sync times ASSERT_EQ(result, true); } } @@ -1121,7 +1177,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync001, TestSize.Level * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync002, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync002, TestSize.Level1) { /** * @tc.steps:step1. insert a and sync @@ -1177,7 +1233,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync002, TestSize.Level * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync003, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync003, TestSize.Level1) { /** * @tc.steps:step1. insert local data and sync @@ -1234,7 +1290,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync003, TestSize.Level * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudSyncerLockTest, ReviseLocalModTimeTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, ReviseLocalModTimeTest001, TestSize.Level1) { /** * @tc.steps:step1. insert local data @@ -1272,7 +1328,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, ReviseLocalModTimeTest001, TestSize.L * @tc.require: * @tc.author: suyue */ -HWTEST_F(DistributedDBCloudSyncerLockTest, RemoveAssetsFailTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, RemoveAssetsFailTest001, TestSize.Level1) { /** * @tc.steps:step1. insert local and sync @@ -1459,7 +1515,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, UnLockSyncTest001, TestSize.Level1) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudSyncerLockTest, TaskIdTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudSyncerLockTest, TaskIdTest001, TestSize.Level1) { /** * @tc.steps:step1. insert cloud and sync diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_progress_manager_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_progress_manager_test.cpp index 182583cd..17de7d59 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_progress_manager_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_progress_manager_test.cpp @@ -55,7 +55,7 @@ void DistributedDBCloudSyncerProgressManagerTest::TearDown(void) * @tc.name: SyncerMgrCheck001 * @tc.desc: Test case1 about Synchronization parameter * @tc.type: FUNC - * @tc.require: SR000HPUOS + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck001, TestSize.Level1) @@ -77,11 +77,11 @@ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck001, TestSiz EXPECT_CALL(*idb, HeartBeat()).WillRepeatedly(Return(OK)); EXPECT_CALL(*idb, Lock()).WillRepeatedly(Return(std::pair(OK, 10))); EXPECT_CALL(*idb, UnLock()).WillRepeatedly(Return(OK)); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData).WillRepeatedly(Return(E_OK)); @@ -115,7 +115,7 @@ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck001, TestSiz * @tc.name: SyncerMgrCheck002 * @tc.desc: Test case2 about Synchronization parameter * @tc.type: FUNC - * @tc.require: SR000HPUOS + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck002, TestSize.Level1) @@ -134,11 +134,11 @@ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck002, TestSiz EXPECT_CALL(*idb, HeartBeat()).WillRepeatedly(Return(OK)); EXPECT_CALL(*idb, Lock()).WillRepeatedly(Return(std::pair(OK, 10))); EXPECT_CALL(*idb, UnLock()).WillRepeatedly(Return(OK)); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData).WillRepeatedly(Return(E_OK)); @@ -173,7 +173,7 @@ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck002, TestSiz * @tc.name: SyncerMgrCheck003 * @tc.desc: Test case2 about Synchronization parameter * @tc.type: FUNC - * @tc.require: SR000HPUOS + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck003, TestSize.Level1) @@ -191,11 +191,11 @@ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck003, TestSiz EXPECT_CALL(*idb, HeartBeat()).WillRepeatedly(Return(OK)); EXPECT_CALL(*idb, Lock()).WillRepeatedly(Return(std::pair(OK, 10))); EXPECT_CALL(*idb, UnLock()).WillRepeatedly(Return(OK)); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, PutCloudSyncData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData).WillRepeatedly(Return(E_OK)); @@ -222,7 +222,7 @@ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck003, TestSiz * @tc.desc: Test the number of queues * @tc.type: FUNC - * @tc.require: SR000HPUOS + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck004, TestSize.Level1) @@ -263,7 +263,7 @@ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck004, TestSiz * @tc.name: SyncerMgrCheck005 * @tc.desc: Test Single-threaded execution of tasks * @tc.type: FUNC - * @tc.require: SR000HPUOS + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck005, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_upload_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_upload_test.cpp index 5ca1769f..892c099b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_upload_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_upload_test.cpp @@ -43,12 +43,12 @@ const int COUNT = 1000; static void CommonExpectCall(MockICloudSyncStorageInterface *iCloud) { - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ReleaseCloudDataToken(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDataNext(_, _)).WillRepeatedly(Return(E_OK)); @@ -151,7 +151,7 @@ void DistributedDBCloudSyncerUploadTest::CheckUploadFinish(TestCloudSyncer &clou * @tc.name: UploadModeCheck001 * @tc.desc: Test different strategies of sync task call DoUpload() * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck001, TestSize.Level1) @@ -165,10 +165,10 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck001, TestSize.Level1 EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); @@ -210,7 +210,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck001, TestSize.Level1 * @tc.name: UploadModeCheck002 * @tc.desc: Test case1 about getting water mark * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck002, TestSize.Level1) @@ -222,10 +222,10 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck002, TestSize.Level1 cloudSyncer->SetMockICloudDB(idb); TaskId taskId = 2u; - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); @@ -247,7 +247,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck002, TestSize.Level1 * @tc.name: UploadModeCheck003 * @tc.desc: Test case2 about getting water mark * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck003, TestSize.Level1) @@ -258,10 +258,10 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck003, TestSize.Level1 std::shared_ptr idb = std::make_shared(); cloudSyncer->SetMockICloudDB(idb); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); @@ -284,7 +284,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck003, TestSize.Level1 * @tc.name: UploadModeCheck004 * @tc.desc: Test case1 about Getting upload count * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck004, TestSize.Level1) @@ -296,10 +296,10 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck004, TestSize.Level1 cloudSyncer->SetMockICloudDB(idb); cloudSyncer->InitCloudSyncer(3u, SYNC_MODE_CLOUD_FORCE_PUSH); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); // 1. Failed to get total data count @@ -319,7 +319,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck004, TestSize.Level1 * @tc.name: UploadModeCheck005 * @tc.desc: Test case2 about Getting upload count * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck005, TestSize.Level1) @@ -331,10 +331,10 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck005, TestSize.Level1 cloudSyncer->SetMockICloudDB(idb); cloudSyncer->InitCloudSyncer(3u, SYNC_MODE_CLOUD_FORCE_PUSH); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _, _)).WillRepeatedly(Return(E_OK)); @@ -369,7 +369,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck005, TestSize.Level1 * @tc.name: UploadModeCheck006 * @tc.desc: Test case1 about CloudSyncData * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck006, TestSize.Level1) @@ -384,12 +384,12 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck006, TestSize.Level1 EXPECT_CALL(*idb, BatchInsert(_, _, _)).WillRepeatedly(Return(OK)); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ReleaseCloudDataToken(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetAllUploadCount(_, _, _, _, _)) .WillRepeatedly([](const QuerySyncObject &, const std::vector &, bool, bool, int64_t & count) { @@ -425,7 +425,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck006, TestSize.Level1 * @tc.name: UploadModeCheck007 * @tc.desc: Test case2 about CloudSyncData * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck007, TestSize.Level1) @@ -476,7 +476,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck007, TestSize.Level1 return E_OK; }); int errCode = cloudSyncer->CallDoUpload(5u); - EXPECT_EQ(errCode, -E_INTERNAL_ERROR); + EXPECT_EQ(errCode, -E_CLOUD_ERROR); RuntimeContext::GetInstance()->StopTaskPool(); cloudSyncer->CallClose(); @@ -490,7 +490,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck007, TestSize.Level1 * @tc.name: UploadModeCheck008 * @tc.desc: Test case3 about CloudSyncData * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck008, TestSize.Level1) @@ -505,12 +505,12 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck008, TestSize.Level1 EXPECT_CALL(*idb, BatchInsert(_, _, _)).WillRepeatedly(Return(OK)); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ReleaseCloudDataToken(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetAllUploadCount(_, _, _, _, _)) .WillRepeatedly([](const QuerySyncObject &, const std::vector &, bool, bool, int64_t & count) { @@ -548,7 +548,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck008, TestSize.Level1 * @tc.name: UploadModeCheck009 * @tc.desc: Test case about CloudSyncData * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck009, TestSize.Level1) @@ -610,7 +610,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck009, TestSize.Level1 * @tc.name: UploadModeCheck017 * @tc.desc: Test case about CloudSyncData * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck017, TestSize.Level1) @@ -660,7 +660,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck017, TestSize.Level1 * @tc.name: UploadModeCheck010 * @tc.desc: Test case1 about batch api in upload * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck010, TestSize.Level1) @@ -683,7 +683,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck010, TestSize.Level1 cloudDataResult = uploadData; return E_OK; }); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetAllUploadCount(_, _, _, _, _)) @@ -691,8 +691,8 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck010, TestSize.Level1 count = 3000; return E_OK; }); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDataNext(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDbSchema(_)).WillRepeatedly(Return(E_OK)); @@ -717,7 +717,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck010, TestSize.Level1 * @tc.name: UploadModeCheck011 * @tc.desc: Test case2 about batch api in upload * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck011, TestSize.Level1) @@ -732,7 +732,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck011, TestSize.Level1 PrepareRecord(tmp, assets); cloudSyncer->InitCloudSyncer(6u, SYNC_MODE_CLOUD_FORCE_PUSH); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetAllUploadCount(_, _, _, _, _)) @@ -740,8 +740,8 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck011, TestSize.Level1 count = 3000; return E_OK; }); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDataNext(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDbSchema(_)).WillRepeatedly(Return(E_OK)); @@ -777,7 +777,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck011, TestSize.Level1 * @tc.name: UploadModeCheck012 * @tc.desc: Test case2 about batch api in upload * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck012, TestSize.Level1) @@ -789,7 +789,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck012, TestSize.Level1 cloudSyncer->SetMockICloudDB(idb); cloudSyncer->InitCloudSyncer(6u, SYNC_MODE_CLOUD_FORCE_PUSH); - EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, StartTransaction(_, false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetAllUploadCount(_, _, _, _, _)) @@ -797,8 +797,8 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck012, TestSize.Level1 count = 3000; return E_OK; }); - EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, Rollback()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Commit(false)).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*iCloud, Rollback(false)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDataNext(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDbSchema(_)).WillRepeatedly(Return(E_OK)); @@ -842,7 +842,7 @@ void MockMethod014(MockICloudSyncStorageInterface *iCloud) * @tc.name: UploadModeCheck014 * @tc.desc: Test case2 about upload when batch api are partially successful. * @tc.type: FUNC - * @tc.require: AR000HSNJO + * @tc.require: * @tc.author: huangboxin */ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck014, TestSize.Level1) @@ -940,7 +940,7 @@ void SetFuncs015(MockICloudSyncStorageInterface *iCloud, std::shared_ptrCallDoUpload(5u, true); - EXPECT_EQ(errCode, -E_INTERNAL_ERROR); + EXPECT_EQ(errCode, -E_CLOUD_ERROR); RuntimeContext::GetInstance()->StopTaskPool(); EXPECT_EQ(callCount, 1); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_compound_primary_key_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_compound_primary_key_sync_test.cpp index 3a1922ec..39a1fcdf 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_compound_primary_key_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_compound_primary_key_sync_test.cpp @@ -143,7 +143,7 @@ namespace { * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest001, TestSize.Level1) { /** * @tc.steps:step1. insert cloud data and merge @@ -167,7 +167,7 @@ HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest001, Te * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest002, TestSize.Level1) { /** * @tc.steps:step1. insert cloud data and merge @@ -200,7 +200,7 @@ HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest002, Te * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest003, TestSize.Level1) { /** * @tc.steps:step1. insert cloud data and merge @@ -233,7 +233,7 @@ HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest003, Te * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest004, TestSize.Level1) { /** * @tc.steps:step1. insert cloud asset and merge @@ -257,7 +257,7 @@ HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest004, Te * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest005, TestSize.Level1) { /** * @tc.steps:step1. insert cloud asset and merge @@ -290,7 +290,7 @@ HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest005, Te * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableCompoundPrimaryKeySyncTest, CloudSyncTest006, TestSize.Level1) { /** * @tc.steps:step1. insert cloud asset and merge diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp index 182f342b..5a678c60 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp @@ -208,7 +208,7 @@ namespace { * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest001, TestSize.Level1) { /** * @tc.steps:step1. insert cloud data and merge @@ -232,7 +232,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest001, Tes * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest002, TestSize.Level1) { /** * @tc.steps:step1. insert cloud data and merge @@ -265,7 +265,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest002, Tes * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest003, TestSize.Level1) { /** * @tc.steps:step1. insert cloud data and merge @@ -298,7 +298,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest003, Tes * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest004, TestSize.Level1) { /** * @tc.steps:step1. insert cloud asset and merge @@ -322,7 +322,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest004, Tes * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest005, TestSize.Level1) { /** * @tc.steps:step1. insert cloud asset and merge @@ -355,7 +355,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest005, Tes * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest006, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest006, TestSize.Level1) { /** * @tc.steps:step1. insert cloud asset and merge @@ -388,7 +388,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest006, Tes * @tc.require: * @tc.author: chenchaohao */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest007, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest007, TestSize.Level1) { /** * @tc.steps:step1. insert cloud asset and merge @@ -422,7 +422,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest007, Tes * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest001, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest001, TestSize.Level1) { std::vector expectProperties = { g_onChangeProperties, g_unChangeProperties, g_onChangeProperties @@ -438,7 +438,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest002, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest002, TestSize.Level1) { std::vector expectProperties = { g_onChangeProperties, g_unChangeProperties, g_onChangeProperties @@ -454,7 +454,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest003, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest003, TestSize.Level1) { std::vector expectProperties = { g_unChangeProperties, g_unChangeProperties, g_unChangeProperties @@ -470,7 +470,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest004, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest004, TestSize.Level1) { std::vector expectProperties = { g_onChangeProperties, g_onChangeProperties, g_onChangeProperties @@ -486,7 +486,7 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest005, TestSize.Level1) { std::vector expectProperties = { g_unChangeProperties, g_unChangeProperties, g_unChangeProperties diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h index 0c41d704..3361f518 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h @@ -27,9 +27,9 @@ public: MOCK_METHOD1(SetCloudDbSchema, int(const DataBaseSchema &)); MOCK_METHOD1(GetCloudDbSchema, int(std::shared_ptr &)); MOCK_METHOD2(GetCloudTableSchema, int(const TableName &, TableSchema &)); - MOCK_METHOD1(StartTransaction, int(TransactType)); - MOCK_METHOD0(Commit, int(void)); - MOCK_METHOD0(Rollback, int(void)); + MOCK_METHOD2(StartTransaction, int(TransactType, bool)); + MOCK_METHOD1(Commit, int(bool)); + MOCK_METHOD1(Rollback, int(bool)); MOCK_METHOD5(GetUploadCount, int(const QuerySyncObject &, const Timestamp &, bool, bool, int64_t &)); MOCK_METHOD5(GetAllUploadCount, int(const QuerySyncObject &, const std::vector &, bool, bool, int64_t &)); @@ -57,6 +57,7 @@ public: MOCK_METHOD3(GetLocalDataCount, int(const std::string &, int &, int &)); MOCK_METHOD0(GetDownloadAssetTable, std::pair>(void)); MOCK_METHOD2(GetDownloadAssetRecords, std::pair>(const std::string &, int64_t)); + MOCK_METHOD0(IsExistTableContainAssets, bool(void)); }; } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.cpp index cbcc3581..21d970db 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.cpp @@ -126,4 +126,14 @@ void VirtualCloudSyncer::PauseCurrentTask() cloudTaskInfos_[currentContext_.currentTaskId].pause = true; LOGD("[CloudSyncer] Mark taskId %" PRIu64 " paused success", currentContext_.currentTaskId); } + +void VirtualCloudSyncer::TriggerAsyncTask() +{ + CloudSyncer::TriggerAsyncDownloadAssetsIfNeed(); +} + +void VirtualCloudSyncer::WaitTaskFinished() +{ + CloudSyncer::WaitCurTaskFinished(); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.h index 5ffb2c21..8b2479bd 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_syncer.h @@ -48,6 +48,10 @@ public: OpType &strategyOpResult); void PauseCurrentTask(); + + void TriggerAsyncTask(); + + void WaitTaskFinished(); private: std::function downloadFunc_; std::function downloadInNeedFunc_; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_ability_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_ability_sync_test.cpp index 7cc95252..4534c5de 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_ability_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_ability_sync_test.cpp @@ -112,7 +112,7 @@ void DistributedDBAbilitySyncTest::TearDown(void) * @tc.name: RequestPacketTest001 * @tc.desc: Verify RequestPacketSerialization and RequestPacketDeSerialization function. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, RequestPacketTest001, TestSize.Level0) @@ -169,7 +169,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, RequestPacketTest001, TestSize.Level0) * @tc.name: RequestPacketTest002 * @tc.desc: Verify RequestPacketSerialization and RequestPacketDeSerialization function when version not support. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, RequestPacketTest002, TestSize.Level0) @@ -215,7 +215,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, RequestPacketTest002, TestSize.Level0) * @tc.name: RequestPacketTest003 * @tc.desc: Verify RequestPacketSerialization and RequestPacketDeSerialization function. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, RequestPacketTest003, TestSize.Level0) @@ -272,7 +272,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, RequestPacketTest003, TestSize.Level0) * @tc.name: RequestPacketTest004 * @tc.desc: Verify RequestPacketSerialization and RequestPacketDeSerialization function. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, RequestPacketTest004, TestSize.Level0) @@ -329,7 +329,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, RequestPacketTest004, TestSize.Level0) * @tc.name: AckPacketTest001 * @tc.desc: Verify AckPacketSerialization and AckPacketDeSerialization function. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, AckPacketTest001, TestSize.Level0) @@ -386,7 +386,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, AckPacketTest001, TestSize.Level0) * @tc.name: SyncStartTest001 * @tc.desc: Verify Ability sync SyncStart function. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, SyncStart001, TestSize.Level0) @@ -419,7 +419,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, SyncStart001, TestSize.Level0) * @tc.name: RequestReceiveTest001 * @tc.desc: Verify Ability RequestReceive callback. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, RequestReceiveTest001, TestSize.Level0) @@ -490,7 +490,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, RequestReceiveTest001, TestSize.Level0) * @tc.name: AckReceiveTest001 * @tc.desc: Verify Ability AckReceive callback. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, AckReceiveTest001, TestSize.Level0) @@ -534,9 +534,9 @@ HWTEST_F(DistributedDBAbilitySyncTest, AckReceiveTest001, TestSize.Level0) * @tc.expected: step5. AckRecv return ok GetRemoteSoftwareVersion is SOFTWARE_VERSION_CURRENT * IsSchemaCompatible true; */ - EXPECT_EQ(async.AckRecv(&msg1, context), E_OK); + EXPECT_EQ(async.AckRecv(&msg1, context), -E_SCHEMA_MISMATCH); EXPECT_TRUE(context->GetRemoteSoftwareVersion() == SOFTWARE_VERSION_CURRENT); - EXPECT_TRUE(context->GetTaskErrCode() != -E_SCHEMA_MISMATCH); + EXPECT_TRUE(context->GetTaskErrCode() == -E_SCHEMA_MISMATCH); /** * @tc.steps: step6. call RequestRecv, SetSchema "" @@ -544,7 +544,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, AckReceiveTest001, TestSize.Level0) */ packet1.SetSchema(""); msg1.SetCopiedObject(packet1); - EXPECT_EQ(async.AckRecv(&msg1, context), E_OK); + EXPECT_EQ(async.AckRecv(&msg1, context), -E_SCHEMA_MISMATCH); /** * @tc.steps: step7. call AckRecv, set inMsg sendCode -E_VERSION_NOT_SUPPORT @@ -561,7 +561,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, AckReceiveTest001, TestSize.Level0) * @tc.name: AckReceiveTest002 * @tc.desc: Verify Ability RDB AckReceive callback. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBAbilitySyncTest, AckReceiveTest002, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_anti_dos_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_anti_dos_sync_test.cpp index d4c4985c..97a459c9 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_anti_dos_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_anti_dos_sync_test.cpp @@ -158,7 +158,7 @@ void DistributeddbAntiDosSyncTest::TearDown(void) * @tc.desc: Whether function run normally when the amount of message is lower than the maximum of threads * and the whole length of message is lower than the maximum size of queue. * @tc.type: FUNC - * @tc.require: AR000D08KU + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributeddbAntiDosSyncTest, AntiDosAttackSync001, TestSize.Level3) @@ -204,7 +204,7 @@ HWTEST_F(DistributeddbAntiDosSyncTest, AntiDosAttackSync001, TestSize.Level3) * @tc.desc: Check if the enqueued and dequeue are normal when the whole length of messages is lower than * maximum size of queue. * @tc.type: FUNC - * @tc.require: AR000D08KU + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributeddbAntiDosSyncTest, AntiDosAttackSync002, TestSize.Level3) @@ -269,7 +269,7 @@ HWTEST_F(DistributeddbAntiDosSyncTest, AntiDosAttackSync002, TestSize.Level3) * @tc.name: Anti Dos attack Sync 003 * @tc.desc: Whether message enter and drop when all threads hang. * @tc.type: FUNC - * @tc.require: AR000D08KU + * @tc.require: * @tc.author: yiguang */ HWTEST_F(DistributeddbAntiDosSyncTest, AntiDosAttackSync003, TestSize.Level3) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_communicator_proxy_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_communicator_proxy_test.cpp index 1f8149d9..8e53b94f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_communicator_proxy_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_communicator_proxy_test.cpp @@ -135,7 +135,7 @@ void DistributedDBCommunicatorProxyTest::TearDown(void) * @tc.name: Interface set equal 001 * @tc.desc: Test set equal identifier from interface. * @tc.type: FUNC - * @tc.require: AR000F4GVG + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBCommunicatorProxyTest, InterfaceSetEqualId001, TestSize.Level1) @@ -167,7 +167,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, InterfaceSetEqualId001, TestSize.Le * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCommunicatorProxyTest, InterfaceSetEqualId002, TestSize.Level0) +HWTEST_F(DistributedDBCommunicatorProxyTest, InterfaceSetEqualId002, TestSize.Level1) { /** * @tc.steps: step1. Get DB of user1 @@ -209,7 +209,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, InterfaceSetEqualId002, TestSize.Le * @tc.name: Register callback 001 * @tc.desc: Test register callback from CommunicatorProxy. * @tc.type: FUNC - * @tc.require: AR000F4GVG + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBCommunicatorProxyTest, RegCallBack001, TestSize.Level1) @@ -248,7 +248,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, RegCallBack001, TestSize.Level1) * @tc.name: Activate 001 * @tc.desc: Test Activate called from CommunicatorProxy. * @tc.type: FUNC - * @tc.require: AR000F4GVG + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBCommunicatorProxyTest, Activate001, TestSize.Level1) @@ -266,7 +266,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, Activate001, TestSize.Level1) * @tc.name: Get mtu 001 * @tc.desc: Test mtu called from CommunicatorProxy. * @tc.type: FUNC - * @tc.require: AR000F4GVG + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBCommunicatorProxyTest, GetMtu001, TestSize.Level1) @@ -290,7 +290,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, GetMtu001, TestSize.Level1) * @tc.name: Get local identify 001 * @tc.desc: Test Get local identify from CommunicatorProxy. * @tc.type: FUNC - * @tc.require: AR000F4GVG + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBCommunicatorProxyTest, GetLocalIdentity001, TestSize.Level1) @@ -309,7 +309,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, GetLocalIdentity001, TestSize.Level * @tc.name: Get remote version 001 * @tc.desc: Test Get remote version from CommunicatorProxy. * @tc.type: FUNC - * @tc.require: AR000F4GVG + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBCommunicatorProxyTest, GetRemoteVersion001, TestSize.Level1) @@ -346,7 +346,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, GetRemoteVersion001, TestSize.Level * @tc.name: Send message 001 * @tc.desc: Test Send message from CommunicatorProxy. * @tc.type: FUNC - * @tc.require: AR000F4GVG + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBCommunicatorProxyTest, SendMessage001, TestSize.Level1) @@ -355,7 +355,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, SendMessage001, TestSize.Level1) * @tc.steps: step1. Call SendMessage from CommProxy with param DEVICE_B. * @tc.expected: step1. MainComm's SendMessage willed called and return E_OK. */ - SendConfig conf = {true, false, 0}; + SendConfig conf = {true, false, true, 0}; EXPECT_CALL(mainComm_, SendMessage(DEVICE_B, _, _, _)).WillOnce(Return(E_OK)); EXPECT_EQ(commProxy_->SendMessage(DEVICE_B, nullptr, conf, nullptr), E_OK); @@ -371,7 +371,7 @@ HWTEST_F(DistributedDBCommunicatorProxyTest, SendMessage001, TestSize.Level1) * @tc.name: Get timeout time 001 * @tc.desc: Test get timeout called from CommunicatorProxy. * @tc.type: FUNC - * @tc.require: AR000F4GVG + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBCommunicatorProxyTest, GetTimeout001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_meta_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_meta_data_test.cpp index e8fd625c..f6da7658 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_meta_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_meta_data_test.cpp @@ -28,6 +28,8 @@ using namespace DistributedDBUnitTest; namespace { constexpr const char *DEVICE_A = "deviceA"; constexpr const char *DEVICE_B = "deviceB"; +constexpr const char *USER_A = "userA"; +constexpr const char *USER_B = "userB"; class DistributedDBMetaDataTest : public testing::Test { public: static void SetUpTestCase(); @@ -104,43 +106,43 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest001, TestSize.Level0) * @tc.steps: step1. Check ability sync finish before set mark. * @tc.expected: step1. Default all ability sync finish is false. */ - EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A)); - EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_B)); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, "")); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_B, "")); /** * @tc.steps: step2. Set A ability sync finish. * @tc.expected: step2. A is finish B is not finish. */ - EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_A, true), E_OK); - EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A)); - EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_B)); + EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_A, "", true), E_OK); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, "")); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_B, "")); /** * @tc.steps: step3. Set B ability sync finish. * @tc.expected: step3. A and B is finish. */ - EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_B, true), E_OK); - EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A)); - EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_B)); + EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_B, "", true), E_OK); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, "")); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_B, "")); /** * @tc.steps: step4. Set A ability sync not finish. * @tc.expected: step4. A is not finish B is finish. */ - EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_A, false), E_OK); - EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A)); - EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_B)); + EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_A, "", false), E_OK); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, "")); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_B, "")); /** * @tc.steps: step5. Clear all time sync finish. * @tc.expected: step5. A and B is finish. */ EXPECT_EQ(metadata_->ClearAllTimeSyncFinishMark(), E_OK); - EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A)); - EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_B)); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, "")); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_B, "")); /** * @tc.steps: step6. Clear all ability sync finish. * @tc.expected: step6. A and B is not finish. */ EXPECT_EQ(metadata_->ClearAllAbilitySyncFinishMark(), E_OK); - EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A)); - EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_B)); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, "")); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_B, "")); } /** @@ -156,36 +158,36 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest002, TestSize.Level0) * @tc.steps: step1. Check time sync finish before set mark. * @tc.expected: step1. Default all time sync finish is false. */ - EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A)); - EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_B)); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, "")); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_B, "")); /** * @tc.steps: step2. Set A time sync finish. * @tc.expected: step2. A is finish B is not finish. */ - EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_A, true), E_OK); - EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_A)); - EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_B)); + EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_A, "", true), E_OK); + EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_A, "")); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_B, "")); /** * @tc.steps: step3. Set B time sync finish. * @tc.expected: step3. A and B is finish. */ - EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_B, true), E_OK); - EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_A)); - EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_B)); + EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_B, "", true), E_OK); + EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_A, "")); + EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_B, "")); /** * @tc.steps: step4. Set A time sync not finish. * @tc.expected: step4. A is not finish B is finish. */ - EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_A, false), E_OK); - EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A)); - EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_B)); + EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_A, "", false), E_OK); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, "")); + EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_B, "")); /** * @tc.steps: step5. Clear all time sync finish. * @tc.expected: step5. A and B is not finish. */ EXPECT_EQ(metadata_->ClearAllTimeSyncFinishMark(), E_OK); - EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A)); - EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_B)); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, "")); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_B, "")); } /** @@ -201,22 +203,22 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest003, TestSize.Level0) * @tc.steps: step1. Check remote schema version before set version. * @tc.expected: step1. Default all version is zero. */ - EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A), 0u); - EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_B), 0u); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, ""), 0u); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_B, ""), 0u); /** * @tc.steps: step2. Set A schema version. * @tc.expected: step2. A is finish B is not finish. */ - EXPECT_EQ(metadata_->SetRemoteSchemaVersion(DEVICE_A, SOFTWARE_VERSION_CURRENT), E_OK); - EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A), SOFTWARE_VERSION_CURRENT); - EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_B), 0u); + EXPECT_EQ(metadata_->SetRemoteSchemaVersion(DEVICE_A, "", SOFTWARE_VERSION_CURRENT), E_OK); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, ""), SOFTWARE_VERSION_CURRENT); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_B, ""), 0u); /** * @tc.steps: step3. Clear all ability sync finish. * @tc.expected: step3. A and B version is zero. */ EXPECT_EQ(metadata_->ClearAllAbilitySyncFinishMark(), E_OK); - EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A), 0u); - EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_B), 0u); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, ""), 0u); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_B, ""), 0u); } /** @@ -232,23 +234,23 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest004, TestSize.Level0) * @tc.steps: step1. Check remote schema version before set version. * @tc.expected: step1. Default all version is zero. */ - EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A), 0u); - EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_B), 0u); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, ""), 0u); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_B, ""), 0u); /** * @tc.steps: step2. Set A schema version. * @tc.expected: step2. A is finish B is not finish. */ const int64_t offset = 100u; - EXPECT_EQ(metadata_->SetSystemTimeOffset(DEVICE_A, offset), E_OK); - EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A), offset); - EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_B), 0u); + EXPECT_EQ(metadata_->SetSystemTimeOffset(DEVICE_A, "", offset), E_OK); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, ""), offset); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_B, ""), 0u); /** * @tc.steps: step3. Clear all time sync finish. * @tc.expected: step3. A and B system time offset is zero. */ EXPECT_EQ(metadata_->ClearAllTimeSyncFinishMark(), E_OK); - EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A), 0u); - EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_B), 0u); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, ""), 0u); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_B, ""), 0u); } /** @@ -290,7 +292,8 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest006, TestSize.Level0) * @tc.steps: step1. Set storage ability sync finish. * @tc.expected: step1. A is finish. */ - std::string hashDeviceId = DBConstant::DEVICEID_PREFIX_KEY + DBCommon::TransferHashString(DEVICE_A); + std::string hashDeviceId = DBConstant::DEVICEID_PREFIX_KEY + DBCommon::TransferHashString(DEVICE_A) + + DBConstant::USERID_PREFIX_KEY + ""; MetaDataValue metaDataValue; GetMetaDataValue(hashDeviceId, metaDataValue); EXPECT_EQ(metaDataValue.syncMark & static_cast(SyncMark::SYNC_MARK_ABILITY_SYNC), 0u); @@ -300,13 +303,13 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest006, TestSize.Level0) * @tc.steps: step2. Check ability sync finish by meta. * @tc.expected: step2. A is finish because meta data is loaded from db. */ - EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A)); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, "")); /** * @tc.steps: step3. Erase water mark and check again. * @tc.expected: step3. A is finish because meta data is loaded from db. */ EXPECT_EQ(metadata_->EraseDeviceWaterMark(DEVICE_A, true), E_OK); - EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A)); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, "")); } /** @@ -323,7 +326,7 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest007, TestSize.Level0) * @tc.expected: step1. B is change because of time change. */ RuntimeContext::GetInstance()->SetTimeChanged(true); - EXPECT_TRUE(metadata_->IsTimeChange(DEVICE_B)); + EXPECT_TRUE(metadata_->IsTimeChange(DEVICE_B, "")); RuntimeContext::GetInstance()->SetTimeChanged(false); RuntimeContext::GetInstance()->StopTimeTickMonitorIfNeed(); } @@ -376,9 +379,512 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest009, TestSize.Level0) * @tc.expected: step1. B is change because of time change. */ RuntimeContext::GetInstance()->SetTimeChanged(true); - EXPECT_EQ(metadata_->SetDbCreateTime(DEVICE_B, 10u, true), E_OK); - EXPECT_TRUE(metadata_->IsTimeChange(DEVICE_B)); + EXPECT_EQ(metadata_->SetDbCreateTime(DEVICE_B, "", 10u, true), E_OK); + EXPECT_TRUE(metadata_->IsTimeChange(DEVICE_B, "")); RuntimeContext::GetInstance()->SetTimeChanged(false); RuntimeContext::GetInstance()->StopTimeTickMonitorIfNeed(); } -} \ No newline at end of file + +/** + * @tc.name: MetadataTest010 + * @tc.desc: Test metadata set and get ability sync mark. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest010, TestSize.Level0) +{ + /** + * @tc.steps: step1. Check ability sync finish before set mark. + * @tc.expected: step1. Default all ability sync finish is false. + */ + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step2. Set user A ability sync finish. + * @tc.expected: step2. user A is finish user B is not finish. + */ + EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_A, USER_A, true), E_OK); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step3. Set user B ability sync finish. + * @tc.expected: step3. user A and user B is finish. + */ + EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_A, USER_B, true), E_OK); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step4. Set user A ability sync not finish. + * @tc.expected: step4. user A is not finish user B is finish. + */ + EXPECT_EQ(metadata_->SetAbilitySyncFinishMark(DEVICE_A, USER_A, false), E_OK); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step5. Clear all time sync finish. + * @tc.expected: step5. user A and user B unchanged. + */ + EXPECT_EQ(metadata_->ClearAllTimeSyncFinishMark(), E_OK); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step6. Clear all ability sync finish. + * @tc.expected: step6. user A and user B is not finish. + */ + EXPECT_EQ(metadata_->ClearAllAbilitySyncFinishMark(), E_OK); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); +} + +/** + * @tc.name: MetadataTest011 + * @tc.desc: Test metadata set and get time sync mark. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest011, TestSize.Level0) +{ + /** + * @tc.steps: step1. Check time sync finish before set mark. + * @tc.expected: step1. Default all time sync finish is false. + */ + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_A)); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step2. Set user A time sync finish. + * @tc.expected: step2. user A is finish user B is not finish. + */ + EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_A, USER_A, true), E_OK); + EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_A)); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step3. Set user B time sync finish. + * @tc.expected: step3. user A and user B is finish. + */ + EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_A, USER_B, true), E_OK); + EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_A)); + EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step4. Set user A time sync not finish. + * @tc.expected: step4. user A is not finish user B is finish. + */ + EXPECT_EQ(metadata_->SetTimeSyncFinishMark(DEVICE_A, USER_A, false), E_OK); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_A)); + EXPECT_TRUE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_B)); + /** + * @tc.steps: step5. Clear all time sync finish. + * @tc.expected: step5. user A and user B is not finish. + */ + EXPECT_EQ(metadata_->ClearAllTimeSyncFinishMark(), E_OK); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_A)); + EXPECT_FALSE(metadata_->IsTimeSyncFinish(DEVICE_A, USER_B)); +} + +/** + * @tc.name: MetadataTest012 + * @tc.desc: Test metadata set remote schema version. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest012, TestSize.Level0) +{ + /** + * @tc.steps: step1. Check remote schema version before set version. + * @tc.expected: step1. Default all version is zero. + */ + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, USER_A), 0u); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, USER_B), 0u); + /** + * @tc.steps: step2. Set user A schema version. + * @tc.expected: step2. user A is finish user B is not finish. + */ + EXPECT_EQ(metadata_->SetRemoteSchemaVersion(DEVICE_A, USER_A, SOFTWARE_VERSION_CURRENT), E_OK); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, USER_A), SOFTWARE_VERSION_CURRENT); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, USER_B), 0u); + /** + * @tc.steps: step3. Clear all ability sync finish. + * @tc.expected: step3. user A and user B version is zero. + */ + EXPECT_EQ(metadata_->ClearAllAbilitySyncFinishMark(), E_OK); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, USER_A), 0u); + EXPECT_EQ(metadata_->GetRemoteSchemaVersion(DEVICE_A, USER_B), 0u); +} + +/** + * @tc.name: MetadataTest013 + * @tc.desc: Test metadata set remote system time off set. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest013, TestSize.Level0) +{ + /** + * @tc.steps: step1. Check remote schema version before set version. + * @tc.expected: step1. Default all version is zero. + */ + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, USER_A), 0u); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, USER_B), 0u); + /** + * @tc.steps: step2. Set user A schema version. + * @tc.expected: step2. user A is finish user B is not finish. + */ + const int64_t offset = 100u; + EXPECT_EQ(metadata_->SetSystemTimeOffset(DEVICE_A, USER_A, offset), E_OK); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, USER_A), offset); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, USER_B), 0u); + /** + * @tc.steps: step3. Clear all time sync finish. + * @tc.expected: step3. user A and user B system time offset is zero. + */ + EXPECT_EQ(metadata_->ClearAllTimeSyncFinishMark(), E_OK); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, USER_A), 0u); + EXPECT_EQ(metadata_->GetSystemTimeOffset(DEVICE_A, USER_B), 0u); +} + +/** + * @tc.name: MetadataTest014 + * @tc.desc: Test metadata remove device data with reload. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest014, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set storage ability sync finish. + * @tc.expected: step1. user A and B finish. + */ + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_FALSE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); + + /** + * @tc.steps: step2. Check ability sync finish by meta. + * @tc.expected: step2. user A and B is finish because meta data is loaded from db. + */ + std::string hashDeviceIdA = DBConstant::DEVICEID_PREFIX_KEY + DBCommon::TransferHashString(DEVICE_A) + + DBConstant::USERID_PREFIX_KEY + USER_A; + MetaDataValue metaDataValueA; + GetMetaDataValue(hashDeviceIdA, metaDataValueA); + EXPECT_EQ(metaDataValueA.syncMark & static_cast(SyncMark::SYNC_MARK_ABILITY_SYNC), 0u); + metaDataValueA.syncMark = static_cast(SyncMark::SYNC_MARK_ABILITY_SYNC); + PutMetaDataValue(hashDeviceIdA, metaDataValueA); + + std::string hashDeviceIdB = DBConstant::DEVICEID_PREFIX_KEY + DBCommon::TransferHashString(DEVICE_A) + + DBConstant::USERID_PREFIX_KEY + USER_B; + MetaDataValue metaDataValueB; + GetMetaDataValue(hashDeviceIdB, metaDataValueB); + EXPECT_EQ(metaDataValueB.syncMark & static_cast(SyncMark::SYNC_MARK_ABILITY_SYNC), 0u); + metaDataValueB.syncMark = static_cast(SyncMark::SYNC_MARK_ABILITY_SYNC); + PutMetaDataValue(hashDeviceIdB, metaDataValueB); + + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); + + /** + * @tc.steps: step3. Erase water mark and check again. + * @tc.expected: step3. user A and B is finish because meta data is loaded from db. + */ + EXPECT_EQ(metadata_->EraseDeviceWaterMark(DEVICE_A, true), E_OK); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_A)); + EXPECT_TRUE(metadata_->IsAbilitySyncFinish(DEVICE_A, USER_B)); +} + +/** + * @tc.name: MetadataTest015 + * @tc.desc: Test metadata init with time change if need. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest015, TestSize.Level0) +{ + /** + * @tc.steps: step1. Check time sync finish by meta. + * @tc.expected: step1. user A and B is change because of time change. + */ + RuntimeContext::GetInstance()->SetTimeChanged(true); + EXPECT_TRUE(metadata_->IsTimeChange(DEVICE_B, USER_A)); + EXPECT_TRUE(metadata_->IsTimeChange(DEVICE_B, USER_B)); + RuntimeContext::GetInstance()->SetTimeChanged(false); + RuntimeContext::GetInstance()->StopTimeTickMonitorIfNeed(); +} + +/** + * @tc.name: MetadataTest016 + * @tc.desc: Test metaData init correctly + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest016, TestSize.Level1) +{ + /** + * @tc.steps: step1. init meta data + * @tc.expected: step1. E_OK + */ + Metadata meta; + VirtualSingleVerSyncDBInterface storage; + WaterMark setWaterMark = 1; + ASSERT_EQ(meta.Initialize(&storage), E_OK); + + /** + * @tc.steps: step2. meta save and get waterMark + * @tc.expected: step2. expect get the same waterMark + */ + EXPECT_EQ(meta.SaveLocalWaterMark(DEVICE_A, USER_A, setWaterMark), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark(DEVICE_A, USER_B, setWaterMark), E_OK); + WaterMark getWaterMark = 0; + meta.GetLocalWaterMark(DEVICE_A, USER_A, getWaterMark); + EXPECT_EQ(getWaterMark, setWaterMark); + meta.GetLocalWaterMark(DEVICE_A, USER_B, getWaterMark); + EXPECT_EQ(getWaterMark, setWaterMark); + + /** + * @tc.steps: step3. init again + * @tc.expected: step3. E_OK + */ + Metadata anotherMeta; + ASSERT_EQ(anotherMeta.Initialize(&storage), E_OK); + + /** + * @tc.steps: step4. get waterMark again + * @tc.expected: step4. expect get the same waterMark + */ + anotherMeta.GetLocalWaterMark(DEVICE_A, USER_A, getWaterMark); + EXPECT_EQ(getWaterMark, setWaterMark); + anotherMeta.GetLocalWaterMark(DEVICE_A, USER_B, getWaterMark); + EXPECT_EQ(getWaterMark, setWaterMark); +} + +/** + * @tc.name: MetadataTest017 + * @tc.desc: Test metaData save and get queryWaterMark. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest017, TestSize.Level1) +{ + /** + * @tc.steps: step1. save receive and send watermark + * @tc.expected: step1. E_OK + */ + WaterMark w1 = 1; + EXPECT_EQ(metadata_->SetRecvQueryWaterMark("Q1", DEVICE_A, USER_A, w1), E_OK); + EXPECT_EQ(metadata_->SetSendQueryWaterMark("Q1", DEVICE_A, USER_A, w1), E_OK); + WaterMark w2 = 2; + EXPECT_EQ(metadata_->SetRecvQueryWaterMark("Q1", DEVICE_A, USER_B, w2), E_OK); + EXPECT_EQ(metadata_->SetSendQueryWaterMark("Q1", DEVICE_A, USER_B, w2), E_OK); + /** + * @tc.steps: step2. get receive and send watermark + * @tc.expected: step2. E_OK and get the latest value + */ + WaterMark w = 0; + EXPECT_EQ(metadata_->GetRecvQueryWaterMark("Q1", DEVICE_A, USER_A, w), E_OK); + EXPECT_EQ(w1, w); + EXPECT_EQ(metadata_->GetSendQueryWaterMark("Q1", DEVICE_A, USER_A, w), E_OK); + EXPECT_EQ(w1, w); + EXPECT_EQ(metadata_->GetRecvQueryWaterMark("Q1", DEVICE_A, USER_B, w), E_OK); + EXPECT_EQ(w2, w); + EXPECT_EQ(metadata_->GetSendQueryWaterMark("Q1", DEVICE_A, USER_B, w), E_OK); + EXPECT_EQ(w2, w); + /** + * @tc.steps: step3. set peer and local watermark + * @tc.expected: step3. E_OK + */ + WaterMark w3 = 3; + EXPECT_EQ(metadata_->SaveLocalWaterMark(DEVICE_A, USER_A, w3), E_OK); + EXPECT_EQ(metadata_->SavePeerWaterMark(DEVICE_A, USER_A, w3, true), E_OK); + WaterMark w4 = 4; + EXPECT_EQ(metadata_->SaveLocalWaterMark(DEVICE_A, USER_B, w4), E_OK); + EXPECT_EQ(metadata_->SavePeerWaterMark(DEVICE_A, USER_B, w4, true), E_OK); + /** + * @tc.steps: step4. get receive and send watermark + * @tc.expected: step4. E_OK and get the w1 + */ + EXPECT_EQ(metadata_->GetRecvQueryWaterMark("Q1", DEVICE_A, USER_A, w), E_OK); + EXPECT_EQ(w3, w); + EXPECT_EQ(metadata_->GetSendQueryWaterMark("Q1", DEVICE_A, USER_A, w), E_OK); + EXPECT_EQ(w3, w); + EXPECT_EQ(metadata_->GetRecvQueryWaterMark("Q1", DEVICE_A, USER_B, w), E_OK); + EXPECT_EQ(w4, w); + EXPECT_EQ(metadata_->GetSendQueryWaterMark("Q1", DEVICE_A, USER_B, w), E_OK); + EXPECT_EQ(w4, w); + /** + * @tc.steps: step5. set peer and local watermark + * @tc.expected: step5. E_OK + */ + WaterMark w5 = 5; + EXPECT_EQ(metadata_->SaveLocalWaterMark(DEVICE_B, USER_A, w5), E_OK); + EXPECT_EQ(metadata_->SavePeerWaterMark(DEVICE_B, USER_A, w5, true), E_OK); + WaterMark w6 = 6; + EXPECT_EQ(metadata_->SaveLocalWaterMark(DEVICE_B, USER_B, w6), E_OK); + EXPECT_EQ(metadata_->SavePeerWaterMark(DEVICE_B, USER_B, w6, true), E_OK); + /** + * @tc.steps: step6. get receive and send watermark + * @tc.expected: step6. E_OK and get the w3 + */ + EXPECT_EQ(metadata_->GetRecvQueryWaterMark("Q2", DEVICE_B, USER_A, w), E_OK); + EXPECT_EQ(w5, w); + EXPECT_EQ(metadata_->GetSendQueryWaterMark("Q2", DEVICE_B, USER_A, w), E_OK); + EXPECT_EQ(w5, w); + EXPECT_EQ(metadata_->GetRecvQueryWaterMark("Q2", DEVICE_B, USER_B, w), E_OK); + EXPECT_EQ(w6, w); + EXPECT_EQ(metadata_->GetSendQueryWaterMark("Q2", DEVICE_B, USER_B, w), E_OK); + EXPECT_EQ(w6, w); + /** + * @tc.steps: step7. get not exit receive and send watermark + * @tc.expected: step7. E_OK and get the 0 + */ + EXPECT_EQ(metadata_->GetRecvQueryWaterMark("Q3", "D3", "U3", w), E_OK); + EXPECT_EQ(w, 0u); + EXPECT_EQ(metadata_->GetSendQueryWaterMark("Q3", "D3", "U3", w), E_OK); + EXPECT_EQ(w, 0u); +} + +/** + * @tc.name: MetadataTest018 + * @tc.desc: Test metaData get and set dbCreateTime. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest018, TestSize.Level1) +{ + /** + * @tc.steps: step1. set dbCreateTime + * @tc.expected: step1. E_OK + */ + EXPECT_EQ(metadata_->SetDbCreateTime(DEVICE_A, USER_A, 10u, true), E_OK); + EXPECT_EQ(metadata_->SetDbCreateTime(DEVICE_A, USER_B, 20u, true), E_OK); + /** + * @tc.steps: step2. check dbCreateTime + * @tc.expected: step2. E_OK + */ + uint64_t curDbCreatTime = 0; + metadata_->GetDbCreateTime(DEVICE_A, USER_A, curDbCreatTime); + EXPECT_EQ(curDbCreatTime, 10u); + metadata_->GetDbCreateTime(DEVICE_A, USER_B, curDbCreatTime); + EXPECT_EQ(curDbCreatTime, 20u); + /** + * @tc.steps: step3. user A change dbCreateTime and check + * @tc.expected: step3. E_OK + */ + EXPECT_EQ(metadata_->SetDbCreateTime(DEVICE_A, USER_A, 30u, true), E_OK); + uint64_t clearDeviceDataMark = INT_MAX; + metadata_->GetRemoveDataMark(DEVICE_A, USER_A, clearDeviceDataMark); + EXPECT_EQ(clearDeviceDataMark, 1u); + EXPECT_EQ(metadata_->ResetMetaDataAfterRemoveData(DEVICE_A, USER_A), E_OK); + metadata_->GetRemoveDataMark(DEVICE_A, USER_A, clearDeviceDataMark); + EXPECT_EQ(clearDeviceDataMark, 0u); + metadata_->GetDbCreateTime(DEVICE_A, USER_A, curDbCreatTime); + EXPECT_EQ(curDbCreatTime, 30u); + + /** + * @tc.steps: step4. user B unchanged dbCreateTime and check + * @tc.expected: step4. E_OK + */ + metadata_->GetRemoveDataMark(DEVICE_A, USER_B, clearDeviceDataMark); + EXPECT_EQ(clearDeviceDataMark, 0u); + metadata_->GetDbCreateTime(DEVICE_A, USER_B, curDbCreatTime); + EXPECT_EQ(curDbCreatTime, 20u); +} + +/** + * @tc.name: MetadataTest019 + * @tc.desc: Test metaData save and get deleteWaterMark. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest019, TestSize.Level1) +{ + /** + * @tc.steps: step1. save receive and send watermark + * @tc.expected: step1. E_OK + */ + WaterMark w1 = 1; + EXPECT_EQ(metadata_->SetRecvDeleteSyncWaterMark(DEVICE_A, USER_A, w1), E_OK); + EXPECT_EQ(metadata_->SetSendDeleteSyncWaterMark(DEVICE_A, USER_A, w1), E_OK); + WaterMark w2 = 2; + EXPECT_EQ(metadata_->SetRecvDeleteSyncWaterMark(DEVICE_A, USER_B, w2), E_OK); + EXPECT_EQ(metadata_->SetSendDeleteSyncWaterMark(DEVICE_A, USER_B, w2), E_OK); + + /** + * @tc.steps: step2. get receive and send watermark + * @tc.expected: step2. E_OK and get the latest value + */ + WaterMark w = 0; + EXPECT_EQ(metadata_->GetRecvDeleteSyncWaterMark(DEVICE_A, USER_A, w), E_OK); + EXPECT_EQ(w1, w); + EXPECT_EQ(metadata_->GetSendDeleteSyncWaterMark(DEVICE_A, USER_A, w), E_OK); + EXPECT_EQ(w1, w); + EXPECT_EQ(metadata_->GetRecvDeleteSyncWaterMark(DEVICE_A, USER_B, w), E_OK); + EXPECT_EQ(w2, w); + EXPECT_EQ(metadata_->GetSendDeleteSyncWaterMark(DEVICE_A, USER_B, w), E_OK); + EXPECT_EQ(w2, w); + + /** + * @tc.steps: step3. set peer and local watermark + * @tc.expected: step3. E_OK + */ + WaterMark w3 = 3; + WaterMark w4 = 4; + EXPECT_EQ(metadata_->SaveLocalWaterMark(DEVICE_A, USER_A, w3), E_OK); + EXPECT_EQ(metadata_->SavePeerWaterMark(DEVICE_A, USER_A, w4, true), E_OK); + WaterMark w5 = 5; + WaterMark w6 = 6; + EXPECT_EQ(metadata_->SaveLocalWaterMark(DEVICE_A, USER_B, w5), E_OK); + EXPECT_EQ(metadata_->SavePeerWaterMark(DEVICE_A, USER_B, w6, true), E_OK); + + /** + * @tc.steps: step4. get receive and send watermark + * @tc.expected: step4. E_OK and get the w1 + */ + EXPECT_EQ(metadata_->GetSendDeleteSyncWaterMark(DEVICE_A, USER_A, w), E_OK); + EXPECT_EQ(w3, w); + EXPECT_EQ(metadata_->GetRecvDeleteSyncWaterMark(DEVICE_A, USER_A, w), E_OK); + EXPECT_EQ(w4, w); + EXPECT_EQ(metadata_->GetSendDeleteSyncWaterMark(DEVICE_A, USER_B, w), E_OK); + EXPECT_EQ(w5, w); + EXPECT_EQ(metadata_->GetRecvDeleteSyncWaterMark(DEVICE_A, USER_B, w), E_OK); + EXPECT_EQ(w6, w); + + /** + * @tc.steps: step5. set peer and local watermark + * @tc.expected: step5. E_OK + */ + WaterMark w7 = 7; + EXPECT_EQ(metadata_->SaveLocalWaterMark(DEVICE_B, USER_A, w7), E_OK); + EXPECT_EQ(metadata_->SavePeerWaterMark(DEVICE_B, USER_A, w7, true), E_OK); + WaterMark w8 = 8; + EXPECT_EQ(metadata_->SaveLocalWaterMark(DEVICE_B, USER_B, w8), E_OK); + EXPECT_EQ(metadata_->SavePeerWaterMark(DEVICE_B, USER_B, w8, true), E_OK); + + /** + * @tc.steps: step6. get receive and send watermark + * @tc.expected: step6. E_OK and get the w3 + */ + EXPECT_EQ(metadata_->GetRecvDeleteSyncWaterMark(DEVICE_B, USER_A, w), E_OK); + EXPECT_EQ(w7, w); + EXPECT_EQ(metadata_->GetSendDeleteSyncWaterMark(DEVICE_B, USER_A, w), E_OK); + EXPECT_EQ(w7, w); + EXPECT_EQ(metadata_->GetRecvDeleteSyncWaterMark(DEVICE_B, USER_B, w), E_OK); + EXPECT_EQ(w8, w); + EXPECT_EQ(metadata_->GetSendDeleteSyncWaterMark(DEVICE_B, USER_B, w), E_OK); + EXPECT_EQ(w8, w); + + /** + * @tc.steps: step7. get not exit receive and send watermark + * @tc.expected: step7. E_OK and get the 0 + */ + EXPECT_EQ(metadata_->GetRecvDeleteSyncWaterMark("D3", USER_A, w), E_OK); + EXPECT_EQ(w, 0u); + EXPECT_EQ(metadata_->GetSendDeleteSyncWaterMark("D3", USER_A, w), E_OK); + EXPECT_EQ(w, 0u); +} +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp index 827a7b8e..de2a4dc6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp @@ -108,7 +108,7 @@ void Init(MockSingleVerStateMachine &stateMachine, MockSyncTaskContext &syncTask { std::shared_ptr metadata = std::make_shared(); ASSERT_EQ(metadata->Initialize(&dbSyncInterface), E_OK); - (void)syncTaskContext.Initialize("device", &dbSyncInterface, metadata, &communicator); + (void)syncTaskContext.Initialize({"device", ""}, &dbSyncInterface, metadata, &communicator); (void)stateMachine.Initialize(&syncTaskContext, &dbSyncInterface, metadata, &communicator); } @@ -117,7 +117,7 @@ void Init(MockSingleVerStateMachine &stateMachine, MockSyncTaskContext *syncTask { std::shared_ptr metadata = std::make_shared(); ASSERT_EQ(metadata->Initialize(dbSyncInterface), E_OK); - (void)syncTaskContext->Initialize("device", dbSyncInterface, metadata, &communicator); + (void)syncTaskContext->Initialize({"device", ""}, dbSyncInterface, metadata, &communicator); (void)stateMachine.Initialize(syncTaskContext, dbSyncInterface, metadata, &communicator); } @@ -319,6 +319,10 @@ void SyncLifeTest003() { VirtualCommunicatorAggregator *virtualCommunicatorAggregator = new VirtualCommunicatorAggregator(); ASSERT_NE(virtualCommunicatorAggregator, nullptr); + bool isAlloc = false; + virtualCommunicatorAggregator->SetAllocCommunicatorCallback([&isAlloc](const std::string &userId) { + isAlloc = true; + }); RuntimeContext::GetInstance()->SetCommunicatorAggregator(virtualCommunicatorAggregator); TestInterface *syncDBInterface = new TestInterface(); ASSERT_NE(syncDBInterface, nullptr); @@ -333,11 +337,13 @@ void SyncLifeTest003() virtualCommunicatorAggregator->OnlineDevice(DEVICE_B); syncDBInterface->TestLocalChange(); virtualCommunicatorAggregator->OfflineDevice(DEVICE_B); + virtualCommunicatorAggregator->SetAllocCommunicatorCallback(nullptr); EXPECT_EQ(syncDBInterface->Close(), E_OK); RefObject::KillAndDecObjRef(syncDBInterface); std::this_thread::sleep_for(std::chrono::seconds(1)); RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); RuntimeContext::GetInstance()->StopTaskPool(); + EXPECT_TRUE(isAlloc); } void MockRemoteQuery002() @@ -368,7 +374,7 @@ void TimeSync001() const int timeDriverMs = 100; for (int i = 0; i < loopCount; ++i) { MockTimeSync timeSync; - EXPECT_EQ(timeSync.Initialize(communicator, metadata, storage, "DEVICES_A"), E_OK); + EXPECT_EQ(timeSync.Initialize(communicator, metadata, storage, "DEVICES_A", ""), E_OK); EXPECT_CALL(timeSync, SyncStart).WillRepeatedly(Return(E_OK)); timeSync.ModifyTimer(timeDriverMs); std::this_thread::sleep_for(std::chrono::milliseconds(timeDriverMs)); @@ -409,7 +415,7 @@ void DistributedDBMockSyncModuleTest::TearDown(void) * @tc.name: StateMachineCheck001 * @tc.desc: Test machine do timeout when has same timerId. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck001, TestSize.Level1) @@ -432,7 +438,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck001, TestSize.Level1) * @tc.name: StateMachineCheck002 * @tc.desc: Test machine do timeout when has diff timerId. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck002, TestSize.Level1) @@ -455,7 +461,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck002, TestSize.Level1) * @tc.name: StateMachineCheck003 * @tc.desc: Test machine exec next task when queue not empty. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck003, TestSize.Level1) @@ -486,7 +492,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck003, TestSize.Level1) * @tc.name: StateMachineCheck004 * @tc.desc: Test machine deal time sync ack failed. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck004, TestSize.Level1) @@ -511,7 +517,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck004, TestSize.Level1) * @tc.name: StateMachineCheck005 * @tc.desc: Test machine recv errCode. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck005, TestSize.Level1) @@ -539,7 +545,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck005, TestSize.Level1) * @tc.name: StateMachineCheck006 * @tc.desc: Test machine exec next task when queue not empty to empty. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck006, TestSize.Level1) @@ -569,7 +575,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck006, TestSize.Level1) * @tc.name: StateMachineCheck007 * @tc.desc: Test machine DoSaveDataNotify in another thread. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck007, TestSize.Level3) @@ -596,7 +602,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck007, TestSize.Level3) * @tc.name: StateMachineCheck008 * @tc.desc: test machine process when last sync task send packet failed. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck008, TestSize.Level1) @@ -614,7 +620,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck008, TestSize.Level1) * @tc.name: StateMachineCheck009 * @tc.desc: test machine process when last sync task send packet failed. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck009, TestSize.Level1) @@ -633,7 +639,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck009, TestSize.Level1) * @tc.name: StateMachineCheck010 * @tc.desc: test machine process when error happened in response pull. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck010, TestSize.Level1) @@ -652,7 +658,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck010, TestSize.Level1) * @tc.name: StateMachineCheck011 * @tc.desc: test machine process when error happened in response pull. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck011, TestSize.Level1) @@ -672,7 +678,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck011, TestSize.Level1) * @tc.name: StateMachineCheck012 * @tc.desc: Verify Ability LastNotify AckReceive callback. * @tc.type: FUNC - * @tc.require: AR000DR9K4 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck012, TestSize.Level1) @@ -698,7 +704,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck012, TestSize.Level1) * @tc.name: StateMachineCheck013 * @tc.desc: test kill syncTaskContext. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck013, TestSize.Level1) @@ -710,7 +716,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck013, TestSize.Level1) * @tc.name: StateMachineCheck014 * @tc.desc: test machine stop save notify without start. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck014, TestSize.Level1) @@ -724,7 +730,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck014, TestSize.Level1) * @tc.name: DataSyncCheck001 * @tc.desc: Test dataSync recv error ack. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck001, TestSize.Level1) @@ -741,7 +747,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck001, TestSize.Level1) * @tc.name: DataSyncCheck002 * @tc.desc: Test dataSync recv notify ack. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck002, TestSize.Level1) @@ -758,7 +764,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck002, TestSize.Level1) * @tc.name: DataSyncCheck003 * @tc.desc: Test dataSync recv notify ack. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck003, TestSize.Level1) @@ -781,8 +787,8 @@ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck003, TestSize.Level1) message->SetCopiedObject(packet); mockSyncTaskContext.SetQuerySync(true); - EXPECT_CALL(*mockMetadata, GetLastQueryTime(_, _, _)).WillOnce(Return(E_OK)); - EXPECT_CALL(*mockMetadata, SetLastQueryTime(_, _, _)) + EXPECT_CALL(*mockMetadata, GetLastQueryTime(_, _, _, _)).WillOnce(Return(E_OK)); + EXPECT_CALL(*mockMetadata, SetLastQueryTime(_, _, _, _)) .WillOnce([&dataTimeRange]( const std::string &queryIdentify, const std::string &deviceId, const Timestamp ×tamp) { EXPECT_EQ(timestamp, dataTimeRange.endTime); @@ -819,11 +825,38 @@ HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck004, TestSize.Level1) RefObject::KillAndDecObjRef(communicator); } +/** + * @tc.name: DataSyncCheck004 + * @tc.desc: Test dataSync do ability sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: lg + */ +HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck005, TestSize.Level1) +{ + MockSingleVerDataSync mockDataSync; + auto mockMetadata = std::make_shared(); + MockSyncTaskContext mockSyncTaskContext; + SyncTimeRange dataTimeRange = {1, 0, 1, 0}; + mockDataSync.CallUpdateSendInfo(dataTimeRange, &mockSyncTaskContext); + + VirtualRelationalVerSyncDBInterface storage; + MockCommunicator communicator; + std::shared_ptr metadata = std::static_pointer_cast(mockMetadata); + mockDataSync.Initialize(&storage, &communicator, metadata, "deviceId"); + + EXPECT_CALL(*mockMetadata, GetLocalWaterMark(_, _, _)).WillOnce(Return()); + std::vector reserved; + mockDataSync.CallDealRemoveDeviceDataByAck(&mockSyncTaskContext, 1, reserved); + reserved.push_back(1); + mockDataSync.CallDealRemoveDeviceDataByAck(&mockSyncTaskContext, 1, reserved); +} + /** * @tc.name: AutoLaunchCheck001 * @tc.desc: Test autoLaunch close connection. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, AutoLaunchCheck001, TestSize.Level1) @@ -835,7 +868,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, AutoLaunchCheck001, TestSize.Level1) * @tc.name: AutoLaunchCheck002 * @tc.desc: Test autoLaunch receive diff userId. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, AutoLaunchCheck002, TestSize.Level1) @@ -857,7 +890,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, AutoLaunchCheck002, TestSize.Level1) * @tc.name: SyncDataSync001 * @tc.desc: Test request start when RemoveDeviceDataIfNeed failed. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncDataSync001, TestSize.Level1) @@ -874,7 +907,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncDataSync001, TestSize.Level1) * @tc.name: SyncDataSync002 * @tc.desc: Test pull request start when RemoveDeviceDataIfNeed failed. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncDataSync002, TestSize.Level1) @@ -891,7 +924,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncDataSync002, TestSize.Level1) * @tc.name: SyncDataSync003 * @tc.desc: Test call RemoveDeviceDataIfNeed in diff thread. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncDataSync003, TestSize.Level1) @@ -907,14 +940,14 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncDataSync003, TestSize.Level1) const std::string deviceId = "deviceId"; dataSync.Initialize(&storage, &communicator, metadata, deviceId); syncTaskContext.SetRemoteSoftwareVersion(SOFTWARE_VERSION_CURRENT); - syncTaskContext.Initialize(deviceId, &storage, metadata, &communicator); + syncTaskContext.Initialize({deviceId, ""}, &storage, metadata, &communicator); syncTaskContext.EnableClearRemoteStaleData(true); /** * @tc.steps: step1. set diff db createtime for rebuild label in meta */ - metadata->SetDbCreateTime(deviceId, 1, true); // 1 is old db createTime - metadata->SetDbCreateTime(deviceId, 2, true); // 1 is new db createTime + metadata->SetDbCreateTime(deviceId, "", 1, true); // 1 is old db createTime + metadata->SetDbCreateTime(deviceId, "", 2, true); // 1 is new db createTime DistributedDB::Key k1 = {'k', '1'}; DistributedDB::Value v1 = {'v', '1'}; @@ -948,7 +981,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncDataSync003, TestSize.Level1) * @tc.name: AbilitySync001 * @tc.desc: Test abilitySync abort when recv error. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync001, TestSize.Level1) @@ -970,7 +1003,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync001, TestSize.Level1) * @tc.name: AbilitySync002 * @tc.desc: Test abilitySync abort when save meta failed. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync002, TestSize.Level1) @@ -1007,7 +1040,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync002, TestSize.Level1) * @tc.name: AbilitySync002 * @tc.desc: Test abilitySync when offline. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync003, TestSize.Level1) @@ -1039,7 +1072,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync003, TestSize.Level1) * @tc.name: AbilitySync004 * @tc.desc: Test abilitySync when offline. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync004, TestSize.Level1) @@ -1051,7 +1084,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, AbilitySync004, TestSize.Level1) * @tc.name: SyncLifeTest001 * @tc.desc: Test syncer alive when thread still exist. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest001, TestSize.Level3) @@ -1063,7 +1096,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest001, TestSize.Level3) * @tc.name: SyncLifeTest002 * @tc.desc: Test autosync when thread still exist. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest002, TestSize.Level3) @@ -1075,7 +1108,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest002, TestSize.Level3) * @tc.name: SyncLifeTest003 * @tc.desc: Test syncer localdatachange when store is destructor * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest003, TestSize.Level3) @@ -1087,7 +1120,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest003, TestSize.Level3) * @tc.name: SyncLifeTest004 * @tc.desc: Test syncer remote data change. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest004, TestSize.Level3) @@ -1119,7 +1152,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest004, TestSize.Level3) * @tc.name: SyncLifeTest005 * @tc.desc: Test syncer remote device offline. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest005, TestSize.Level3) @@ -1205,7 +1238,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest006, TestSize.Level1) * @tc.name: MessageScheduleTest001 * @tc.desc: Test MessageSchedule stop timer when no message. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, MessageScheduleTest001, TestSize.Level1) @@ -1230,7 +1263,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, MessageScheduleTest001, TestSize.Level * @tc.name: SyncEngineTest001 * @tc.desc: Test SyncEngine receive message when closing. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncEngineTest001, TestSize.Level1) @@ -1285,7 +1318,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncEngineTest001, TestSize.Level1) * @tc.name: SyncEngineTest002 * @tc.desc: Test SyncEngine add sync operation. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncEngineTest002, TestSize.Level1) @@ -1349,7 +1382,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncEngineTest002, TestSize.Level1) * @tc.name: SyncEngineTest003 * @tc.desc: Test SyncEngine add block sync operation. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncEngineTest003, TestSize.Level1) @@ -1383,7 +1416,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncEngineTest004, TestSize.Level0) auto *enginePtr = new (std::nothrow) MockSyncEngine(); ASSERT_NE(enginePtr, nullptr); int errCode = E_OK; - auto *context = enginePtr->CallGetSyncTaskContext("dev", errCode); + auto *context = enginePtr->CallGetSyncTaskContext({"dev", "user"}, errCode); EXPECT_EQ(context, nullptr); EXPECT_EQ(errCode, -E_INVALID_DB); RefObject::KillAndDecObjRef(enginePtr); @@ -1439,11 +1472,58 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncEngineTest005, TestSize.Level0) virtualCommunicatorAggregator = nullptr; } +/** + * @tc.name: SyncEngineTest006 + * @tc.desc: Test find context with default user. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBMockSyncModuleTest, SyncEngineTest006, TestSize.Level0) +{ + /** + * @tc.steps: step1. Init engine. + * @tc.expected: step1. ok + */ + std::unique_ptr enginePtr = std::make_unique(); + MockKvSyncInterface syncDBInterface; + KvDBProperties kvDBProperties; + std::string userId = "user_1"; + kvDBProperties.SetStringProp(DBProperties::USER_ID, userId); + std::vector identifier(COMM_LABEL_LENGTH, 1u); + syncDBInterface.SetIdentifier(identifier); + syncDBInterface.SetDbProperties(kvDBProperties); + std::shared_ptr metaData = std::make_shared(); + metaData->Initialize(&syncDBInterface); + VirtualCommunicatorAggregator *virtualCommunicatorAggregator = new VirtualCommunicatorAggregator(); + ASSERT_NE(virtualCommunicatorAggregator, nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(virtualCommunicatorAggregator); + ISyncEngine::InitCallbackParam param = { nullptr, nullptr, nullptr }; + enginePtr->Initialize(&syncDBInterface, metaData, param); + /** + * @tc.steps: step2. Insert context with userId. + * @tc.expected: step2. ok + */ + EXPECT_CALL(*enginePtr, CreateSyncTaskContext(_)) + .WillRepeatedly(Return(new (std::nothrow) SingleVerKvSyncTaskContext())); + int errCode = E_OK; + std::string deviceId = "deviceB"; + auto *context1 = enginePtr->CallGetSyncTaskContext({deviceId, userId}, errCode); + ASSERT_NE(context1, nullptr); + /** + * @tc.steps: step3. Find context with default user. + * @tc.expected: step3. ok + */ + auto context2 = enginePtr->CallFindSyncTaskContext({deviceId, DBConstant::DEFAULT_USER}); + EXPECT_EQ(context1, context2); + enginePtr->Close(); +} + /** * @tc.name: remote query packet 001 * @tc.desc: Test RemoteExecutorRequestPacket Serialization And DeSerialization * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, RemoteQueryPacket001, TestSize.Level1) @@ -1484,7 +1564,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, RemoteQueryPacket001, TestSize.Level1) * @tc.name: remote query packet 002 * @tc.desc: Test RemoteExecutorAckPacket Serialization And DeSerialization * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, RemoteQueryPacket002, TestSize.Level1) @@ -1525,7 +1605,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, RemoteQueryPacket002, TestSize.Level1) * @tc.name: remote query packet 003 * @tc.desc: Test RemoteExecutorRequestPacket Serialization with invalid args * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBMockSyncModuleTest, RemoteQueryPacket003, TestSize.Level1) @@ -1578,7 +1658,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, RemoteQueryPacket003, TestSize.Level1) * @tc.name: remote query packet 004 * @tc.desc: Test RemoteExecutorRequestPacket Deserialization with invalid args * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBMockSyncModuleTest, RemoteQueryPacket004, TestSize.Level1) @@ -1625,7 +1705,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, RemoteQueryPacket004, TestSize.Level1) * @tc.name: SingleVerKvEntryTest001 * @tc.desc: Test SingleVerKvEntry Serialize and DeSerialize. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SingleVerKvEntryTest001, TestSize.Level1) @@ -1650,7 +1730,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SingleVerKvEntryTest001, TestSize.Leve * @tc.name: mock remote query 001 * @tc.desc: Test RemoteExecutor receive msg when closing * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, MockRemoteQuery001, TestSize.Level3) @@ -1679,7 +1759,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, MockRemoteQuery001, TestSize.Level3) * @tc.name: mock remote query 002 * @tc.desc: Test RemoteExecutor response failed when closing * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, MockRemoteQuery002, TestSize.Level3) @@ -1691,7 +1771,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, MockRemoteQuery002, TestSize.Level3) * @tc.name: SyncTaskContextCheck001 * @tc.desc: test context check task can be skipped in push mode. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck001, TestSize.Level1) @@ -1700,7 +1780,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck001, TestSize.Leve MockCommunicator communicator; VirtualSingleVerSyncDBInterface dbSyncInterface; std::shared_ptr metadata = std::make_shared(); - (void)syncTaskContext.Initialize("device", &dbSyncInterface, metadata, &communicator); + (void)syncTaskContext.Initialize({"device", ""}, &dbSyncInterface, metadata, &communicator); syncTaskContext.SetLastFullSyncTaskStatus(SyncOperation::Status::OP_FINISHED_ALL); syncTaskContext.CallSetSyncMode(static_cast(SyncModeType::PUSH)); EXPECT_EQ(syncTaskContext.CallIsCurrentSyncTaskCanBeSkipped(), true); @@ -1710,7 +1790,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck001, TestSize.Leve * @tc.name: SyncTaskContextCheck002 * @tc.desc: test context check task can be skipped in push mode. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck002, TestSize.Level1) @@ -1766,7 +1846,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck002, TestSize.Leve * @tc.name: SyncTaskContextCheck003 * @tc.desc: test context call on sync task add. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck003, TestSize.Level1) @@ -1804,7 +1884,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck003, TestSize.Leve * @tc.name: SyncTaskContextCheck004 * @tc.desc: test context add sync task should not cancel current task. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck004, TestSize.Level1) @@ -1838,7 +1918,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck004, TestSize.Leve * @tc.name: SyncTaskContextCheck005 * @tc.desc: test context call get query id async. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck005, TestSize.Level1) @@ -1853,7 +1933,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck005, TestSize.Leve VirtualSingleVerSyncDBInterface dbSyncInterface; std::shared_ptr metadata = std::make_shared(); ASSERT_EQ(metadata->Initialize(&dbSyncInterface), E_OK); - (void)context->Initialize("device", &dbSyncInterface, metadata, &communicator); + (void)context->Initialize({"device", ""}, &dbSyncInterface, metadata, &communicator); (void)stateMachine.Initialize(context, &dbSyncInterface, metadata, &communicator); for (int i = 0; i < 100; ++i) { // 100 sync target @@ -1894,7 +1974,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck005, TestSize.Leve * @tc.name: SyncTaskContextCheck006 * @tc.desc: test context call get query id async. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck006, TestSize.Level1) @@ -1909,7 +1989,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck006, TestSize.Leve VirtualSingleVerSyncDBInterface dbSyncInterface; std::shared_ptr metadata = std::make_shared(); ASSERT_EQ(metadata->Initialize(&dbSyncInterface), E_OK); - (void)context->Initialize("device", &dbSyncInterface, metadata, communicator); + (void)context->Initialize({"device", ""}, &dbSyncInterface, metadata, communicator); /** * @tc.steps: step2. add sync target into context */ @@ -1949,7 +2029,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck007, TestSize.Leve VirtualRelationalVerSyncDBInterface dbSyncInterface; std::shared_ptr metadata = std::make_shared(); ASSERT_EQ(metadata->Initialize(&dbSyncInterface), E_OK); - (void)context->Initialize("device", &dbSyncInterface, metadata, &communicator); + (void)context->Initialize({"device", ""}, &dbSyncInterface, metadata, &communicator); (void)stateMachine.Initialize(context, &dbSyncInterface, metadata, &communicator); /** * @tc.steps: step2. prepare table and query @@ -1984,7 +2064,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck007, TestSize.Leve * @tc.name: TimeChangeListenerTest001 * @tc.desc: Test RegisterTimeChangedLister. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, TimeChangeListenerTest001, TestSize.Level1) @@ -2014,7 +2094,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, TimeChangeListenerTest001, TestSize.Le * @tc.name: TimeChangeListenerTest002 * @tc.desc: Test TimeChange. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, TimeChangeListenerTest002, TestSize.Level1) @@ -2049,7 +2129,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, TimeChangeListenerTest002, TestSize.Le * @tc.name: SyncerCheck001 * @tc.desc: Test syncer call set sync retry before init. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck001, TestSize.Level1) @@ -2061,7 +2141,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck001, TestSize.Level1) * @tc.name: SyncerCheck002 * @tc.desc: Test syncer call get timestamp with close and open. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck002, TestSize.Level1) @@ -2106,7 +2186,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck002, TestSize.Level1) * @tc.name: SyncerCheck003 * @tc.desc: Test syncer query auto sync. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, DISABLE_SyncerCheck003, TestSize.Level1) @@ -2140,7 +2220,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, DISABLE_SyncerCheck003, TestSize.Level * @tc.name: SyncerCheck004 * @tc.desc: Test syncer call status check. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck004, TestSize.Level1) @@ -2153,7 +2233,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck004, TestSize.Level1) * @tc.name: SyncerCheck005 * @tc.desc: Test syncer call erase watermark without storage. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck005, TestSize.Level1) @@ -2169,7 +2249,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck005, TestSize.Level1) * @tc.name: SyncerCheck006 * @tc.desc: Test syncer call init with busy. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck006, TestSize.Level1) @@ -2188,7 +2268,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck006, TestSize.Level1) * @tc.name: SyncerCheck007 * @tc.desc: Test syncer get sync data size without syncer lock. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck007, TestSize.Level1) @@ -2196,7 +2276,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck007, TestSize.Level1) MockSingleVerKVSyncer syncer; auto mockMeta = std::make_shared(); auto metadata = std::static_pointer_cast(mockMeta); - EXPECT_CALL(*mockMeta, GetLocalWaterMark).WillRepeatedly([&syncer](const DeviceID &, uint64_t &) { + EXPECT_CALL(*mockMeta, GetLocalWaterMark).WillRepeatedly([&syncer](const DeviceID &, const DeviceID &, uint64_t &) { syncer.TestSyncerLock(); }); syncer.SetMetadata(metadata); @@ -2213,7 +2293,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck007, TestSize.Level1) * @tc.name: SyncerCheck008 * @tc.desc: Test syncer call set sync retry before init. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck008, TestSize.Level1) @@ -2258,7 +2338,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck008, TestSize.Level1) * @tc.name: SessionId001 * @tc.desc: Test syncer call set sync retry before init. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SessionId001, TestSize.Level1) @@ -2275,7 +2355,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SessionId001, TestSize.Level1) * @tc.name: TimeSync001 * @tc.desc: Test syncer call set sync retry before init. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, TimeSync001, TestSize.Level1) @@ -2300,7 +2380,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, TimeSync002, TestSize.Level1) MockTimeSync timeSync; EXPECT_CALL(timeSync, SyncStart).WillRepeatedly(Return(E_OK)); - EXPECT_EQ(timeSync.Initialize(communicator, metadata, storage, "DEVICES_A"), E_OK); + EXPECT_EQ(timeSync.Initialize(communicator, metadata, storage, "DEVICES_A", ""), E_OK); const int loopCount = 100; const int timeDriverMs = 10; for (int i = 0; i < loopCount; ++i) { @@ -2342,7 +2422,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, TimeSync003, TestSize.Level0) * @tc.name: SyncContextCheck001 * @tc.desc: Test context time out logic. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SyncContextCheck001, TestSize.Level1) @@ -2362,7 +2442,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncContextCheck001, TestSize.Level1) * @tc.name: SingleVerDataSyncUtils001 * @tc.desc: Test translate item got diff timestamp. * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBMockSyncModuleTest, SingleVerDataSyncUtils001, TestSize.Level1) @@ -2371,7 +2451,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SingleVerDataSyncUtils001, TestSize.Le MockCommunicator communicator; VirtualSingleVerSyncDBInterface dbSyncInterface; std::shared_ptr metadata = std::make_shared(); - (void)context.Initialize("device", &dbSyncInterface, metadata, &communicator); + (void)context.Initialize({"device", ""}, &dbSyncInterface, metadata, &communicator); std::vector data; for (int i = 0; i < 2; ++i) { // loop 2 times @@ -2401,4 +2481,25 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTimerResetTest001, TestSize.Level1 EXPECT_EQ(stateMachine.CallPrepareNextSyncTask(), E_OK); stateMachine.CallStopWatchDog(); } + +/** + * @tc.name: SingleVerSyncStateMachineTest001 + * @tc.desc: Test it will return ok when sync with a timer already exists. + * @tc.type: FUNC + * @tc.require: + * @tc.author: lg + */ +HWTEST_F(DistributedDBMockSyncModuleTest, SingleVerSyncStateMachineTest001, TestSize.Level1) +{ + MockSingleVerStateMachine stateMachine; + std::shared_ptr metaData = std::make_shared(); + EXPECT_EQ(stateMachine.Initialize(nullptr, nullptr, metaData, nullptr), -E_INVALID_ARGS); + MockSyncTaskContext syncTaskContext; + MockCommunicator communicator; + VirtualSingleVerSyncDBInterface dbSyncInterface; + EXPECT_EQ(stateMachine.Initialize(&syncTaskContext, &dbSyncInterface, metaData, &communicator), -E_INVALID_ARGS); + Init(stateMachine, syncTaskContext, communicator, dbSyncInterface); + stateMachine.CallSyncStepInner(); + stateMachine.CallSetCurStateErrStatus(); +} } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_multi_ver_p2p_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_multi_ver_p2p_sync_test.cpp index 82172bb5..3bf10752 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_multi_ver_p2p_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_multi_ver_p2p_sync_test.cpp @@ -236,7 +236,7 @@ static DBStatus GetData(KvStoreDelegate *kvStore, const Key &key, Value &value) * @tc.name: Transaction Sync 001 * @tc.desc: Verify put transaction sync function. * @tc.type: FUNC - * @tc.require: AR000BVRO4 AR000CQE0K + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, TransactionSync001, TestSize.Level2) @@ -298,7 +298,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, TransactionSync001, TestSize.Level2) * @tc.name: Transaction Sync 002 * @tc.desc: Verify delete transaction sync function. * @tc.type: FUNC - * @tc.require: AR000BVRO4 AR000CQE0K + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, TransactionSync002, TestSize.Level2) @@ -359,7 +359,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, TransactionSync002, TestSize.Level2) * @tc.name: Transaction Sync 003 * @tc.desc: Verify update transaction sync function. * @tc.type: FUNC - * @tc.require: AR000BVRO4 AR000CQE0K + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, TransactionSync003, TestSize.Level2) @@ -420,7 +420,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, TransactionSync003, TestSize.Level2) * @tc.name: Metadata 001 * @tc.desc: Verify metadata add and update function * @tc.type: FUNC - * @tc.require: AR000CQE0P AR000CQE0S + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, Metadata001, TestSize.Level1) @@ -473,7 +473,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, Metadata001, TestSize.Level1) * @tc.name: Isolation Sync 001 * @tc.desc: Verify add sync isolation between different kvstore. * @tc.type: FUNC - * @tc.require: AR000BVDGP + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, IsolationSync001, TestSize.Level2) @@ -515,7 +515,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, IsolationSync001, TestSize.Level2) * @tc.name: Isolation Sync 002 * @tc.desc: Verify update sync isolation between different kvstore. * @tc.type: FUNC - * @tc.require: AR000BVDGP + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, IsolationSync002, TestSize.Level2) @@ -560,7 +560,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, IsolationSync002, TestSize.Level2) * @tc.name: Isolation Sync 003 * @tc.desc: Verify delete sync isolation between different kvstore. * @tc.type: FUNC - * @tc.require: AR000BVDGP + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, IsolationSync003, TestSize.Level2) @@ -627,7 +627,7 @@ static bool IsTimeSyncPacketEqual(const TimeSyncPacket &inPacketA, const TimeSyn * @tc.name: Timesync Packet 001 * @tc.desc: Verify TimesyncPacket Serialization and DeSerialization * @tc.type: FUNC - * @tc.require: AR000BVRNU AR000CQE0J + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, TimesyncPacket001, TestSize.Level1) @@ -793,7 +793,7 @@ static bool IsCommitHistorySyncRequestPacketEqual(const CommitHistorySyncRequest * @tc.name: Commit History Sync Request Packet 001 * @tc.desc: Verify CommitHistorySyncRequestPacket Serialization and DeSerialization * @tc.type: FUNC - * @tc.require: AR000BVRNU AR000CQE0J + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, CommitHistorySyncRequestPacket001, TestSize.Level1) @@ -909,7 +909,7 @@ static bool IsCommitHistorySyncAckPacketEqual(const CommitHistorySyncAckPacket & * @tc.name: Commit History Sync Ack Packet 001 * @tc.desc: Verify CommitHistorySyncAckPacket Serialization and DeSerialization * @tc.type: FUNC - * @tc.require: AR000BVRNU AR000CQE0J + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, CommitHistorySyncAckPacket001, TestSize.Level1) @@ -990,7 +990,7 @@ static bool IsMultiVerRequestPacketEqual(const MultiVerRequestPacket &inPacketA, * @tc.name: MultiVerValueObject Request Packet 001 * @tc.desc: Verify MultiVerRequestPacket Serialization and DeSerialization * @tc.type: FUNC - * @tc.require: AR000BVRNU AR000CQE0J + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, MultiVerRequestPacket001, TestSize.Level1) @@ -1100,7 +1100,7 @@ static bool IsMultiVerAckPacketEqual(const MultiVerAckPacket &inPacketA, const M * @tc.name: MultiVerValueObject Ack Packet 001 * @tc.desc: Verify MultiVerAckPacket Serialization and DeSerialization * @tc.type: FUNC - * @tc.require: AR000BVRNU AR000CQE0J + * @tc.require: * @tc.author: xiaozhenjian */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, MultiVerAckPacket001, TestSize.Level1) @@ -1171,7 +1171,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, MultiVerAckPacket001, TestSize.Level1 * @tc.name: Simple Data Sync 001 * @tc.desc: Verify normal simple data sync function. * @tc.type: FUNC - * @tc.require: AR000BVDGR + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, SimpleDataSync001, TestSize.Level2) @@ -1215,7 +1215,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, SimpleDataSync001, TestSize.Level2) * @tc.name: Big Data Sync 001 * @tc.desc: Verify normal big data sync function. * @tc.type: FUNC - * @tc.require: AR000BVDGR + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, BigDataSync001, TestSize.Level2) @@ -1263,7 +1263,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, BigDataSync001, TestSize.Level2) * @tc.name: Limit Data Sync 001 * @tc.desc: Verify normal limit data sync function. * @tc.type: FUNC - * @tc.require: AR000BVDGR + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, LimitDataSync001, TestSize.Level2) @@ -1314,7 +1314,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, LimitDataSync001, TestSize.Level2) * @tc.name: Multi Record 001 * @tc.desc: Verify normal multi record sync function. * @tc.type: FUNC - * @tc.require: AR000BVDGR + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, MultiRecord001, TestSize.Level2) @@ -1402,7 +1402,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, MultiRecord001, TestSize.Level2) * @tc.name: Net Disconnect Sync 001 * @tc.desc: Test exception sync when net disconnected. * @tc.type: FUNC - * @tc.require: AR000BVDGR + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, NetDisconnectSync001, TestSize.Level3) @@ -1505,7 +1505,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, NetDisconnectSync001, TestSize.Level3 * @tc.name: SyncQueue006 * @tc.desc: multi version not support sync queue * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, SyncQueue006, TestSize.Level3) @@ -1531,7 +1531,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, SyncQueue006, TestSize.Level3) * @tc.name: PermissionCheck001 * @tc.desc: deviceA permission check not pass * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, PermissionCheck001, TestSize.Level2) @@ -1591,7 +1591,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, PermissionCheck001, TestSize.Level2) * @tc.name: PermissionCheck002 * @tc.desc: deviceB deviceC permission check not pass * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBMultiVerP2PSyncTest, PermissionCheck002, TestSize.Level2) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp index 62b44139..9c71b2b5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp @@ -544,10 +544,10 @@ void DistributedDBRelationalMultiUserTest::TearDown(void) * @tc.name: multi user 001 * @tc.desc: Test multi user change for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser001, TestSize.Level1) { /** * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active @@ -617,10 +617,10 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser001, TestSize.Level0) * @tc.name: multi user 002 * @tc.desc: Test multi user not change for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser002, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser002, TestSize.Level1) { /** * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active @@ -696,7 +696,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser002, TestSize.Level0) * @tc.name: multi user 003 * @tc.desc: enhancement callback return true in multiuser mode for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser003, TestSize.Level3) @@ -775,7 +775,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser003, TestSize.Level3) * @tc.name: multi user 004 * @tc.desc: test NotifyUserChanged func when all db in normal sync mode for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser004, TestSize.Level0) @@ -813,7 +813,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser004, TestSize.Level0) * @tc.name: multi user 005 * @tc.desc: test NotifyUserChanged and close db concurrently for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser005, TestSize.Level0) @@ -852,10 +852,10 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser005, TestSize.Level0) * @tc.name: multi user 006 * @tc.desc: test NotifyUserChanged and block sync concurrently for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser006, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser006, TestSize.Level1) { TestSyncWithUserChange(true, false); } @@ -864,10 +864,10 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser006, TestSize.Level0) * @tc.name: multi user 007 * @tc.desc: test NotifyUserChanged and non-block sync concurrently for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser007, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser007, TestSize.Level1) { TestSyncWithUserChange(false, false); } @@ -876,7 +876,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser007, TestSize.Level0) * @tc.name: multi user 008 * @tc.desc: test NotifyUserChanged and remote query concurrently for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser008, TestSize.Level1) @@ -915,10 +915,10 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser008, TestSize.Level1) * @tc.name: multi user 009 * @tc.desc: test user change and remote query concurrently for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser009, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser009, TestSize.Level1) { TestSyncWithUserChange(false, true); } @@ -927,7 +927,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser009, TestSize.Level0) * @tc.name: multi user 010 * @tc.desc: test check sync active twice when open store * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser010, TestSize.Level1) @@ -964,7 +964,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser010, TestSize.Level1) * @tc.name: multi user 011 * @tc.desc: test use different option to open store for rdb * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser011, TestSize.Level1) @@ -985,7 +985,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser011, TestSize.Level1) * @tc.name: multi user 012 * @tc.desc: test dont check sync active when open store with normal store * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser012, TestSize.Level1) @@ -1012,7 +1012,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser012, TestSize.Level1) * @tc.name: multi user 013 * @tc.desc: test dont check sync active when open store with normal store * @tc.type: FUNC - * @tc.require: AR000GK58G + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser013, TestSize.Level1) @@ -1082,7 +1082,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser014, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt001, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -1125,7 +1125,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt001, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt002, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt002, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -1167,7 +1167,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt002, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt003, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt003, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -1209,7 +1209,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt003, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt004, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt004, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -1251,7 +1251,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt004, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt005, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt005, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -1295,7 +1295,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt005, TestSize.Level0) * @tc.require: * @tc.author: suyue */ -HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt006, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt006, TestSize.Level1) { /** * @tc.steps: step1. openStore and insert data @@ -1344,7 +1344,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt006, TestSize.Level0) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRelationalMultiUserTest, SubUserAutoLaunchTest001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, SubUserAutoLaunchTest001, TestSize.Level1) { /** * @tc.steps: step1. Prepare db1 and db2 with subUser @@ -1407,7 +1407,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, SubUserAutoLaunchTest001, TestSiz * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBRelationalMultiUserTest, DropDistributedTableTest001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, DropDistributedTableTest001, TestSize.Level1) { /** * @tc.steps: step1. Prepare db1 and db2. @@ -1462,7 +1462,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, DropDistributedTableTest001, Test * @tc.require: * @tc.author: zqq */ -HWTEST_F(DistributedDBRelationalMultiUserTest, DeleteTest001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalMultiUserTest, DeleteTest001, TestSize.Level1) { /** * @tc.steps: step1. Prepare db2. diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp index 81936211..7c2745e5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp @@ -926,10 +926,10 @@ void DistributedDBRelationalVerP2PSyncTest::TearDown(void) * @tc.name: Normal Sync 001 * @tc.desc: Test normal push sync for add data. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync001, TestSize.Level1) { std::map dataMap; PrepareEnvironment(dataMap, {g_deviceB}); @@ -943,10 +943,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync001, TestSize.Level0) * @tc.name: Normal Sync 002 * @tc.desc: Test normal pull sync for add data. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync002, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync002, TestSize.Level1) { std::map dataMap; PrepareEnvironment(dataMap, {g_deviceB}); @@ -961,7 +961,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync002, TestSize.Level0) * @tc.name: Normal Sync 003 * @tc.desc: Test normal push sync for update data. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync003, TestSize.Level1) @@ -985,7 +985,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync003, TestSize.Level1) * @tc.name: Normal Sync 004 * @tc.desc: Test normal push sync for delete data. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync004, TestSize.Level1) @@ -1014,10 +1014,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync004, TestSize.Level1) * @tc.name: Normal Sync 005 * @tc.desc: Test normal push sync for add data. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync005, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync005, TestSize.Level1) { std::map dataMap; PrepareVirtualEnvironment(dataMap, {g_deviceB}); @@ -1038,7 +1038,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync005, TestSize.Level0) * @tc.name: Normal Sync 006 * @tc.desc: Test normal pull sync for add data. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync006, TestSize.Level1) @@ -1055,7 +1055,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync006, TestSize.Level1) * @tc.name: Normal Sync 007 * @tc.desc: Test normal sync for miss query data. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync007, TestSize.Level1) @@ -1088,10 +1088,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync007, TestSize.Level1) * @tc.name: Normal Sync 008 * @tc.desc: Test encry db sync for delete table; * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync008, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync008, TestSize.Level1) { /** * @tc.steps: step1. open rdb store, create distribute table, insert data and sync to deviceB @@ -1123,10 +1123,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync008, TestSize.Level0) * @tc.name: Normal Sync 009 * @tc.desc: Test normal push sync for while create distribute table * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync009, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync009, TestSize.Level1) { std::map dataMap; PrepareEnvironment(dataMap, {g_deviceB}); @@ -1174,7 +1174,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync009, TestSize.Level0) * @tc.name: AutoLaunchSync 001 * @tc.desc: Test rdb autoLaunch success when callback return true. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync001, TestSize.Level3) @@ -1241,7 +1241,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync001, TestSize.Leve * @tc.name: AutoLaunchSync 002 * @tc.desc: Test rdb autoLaunch failed when callback return false. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync002, TestSize.Level3) @@ -1289,7 +1289,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync002, TestSize.Leve * @tc.name: AutoLaunchSync 003 * @tc.desc: Test rdb autoLaunch failed when callback is nullptr. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync003, TestSize.Level3) @@ -1349,7 +1349,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync004, TestSize.Leve int currentStatus = 0; const AutoLaunchNotifier notifier = [¤tStatus](const std::string &userId, const std::string &appId, const std::string &storeId, AutoLaunchStatus status) { - printf("SET STATUS = %d\n", static_cast(status)); + LOGD("SET STATUS = %d\n", static_cast(status)); currentStatus = static_cast(status); }; const AutoLaunchRequestCallback callback = [¬ifier](const std::string &identifier, AutoLaunchParam ¶m) { @@ -1389,7 +1389,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync004, TestSize.Leve * @tc.name: Ability Sync 001 * @tc.desc: Test ability sync success when has same schema. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync001, TestSize.Level1) @@ -1408,7 +1408,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync001, TestSize.Level1) * @tc.name: Ability Sync 002 * @tc.desc: Test ability sync failed when has different schema. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync002, TestSize.Level1) @@ -1442,7 +1442,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync002, TestSize.Level1) * @tc.name: Ability Sync 003 * @tc.desc: Test ability sync failed when has different schema. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync003, TestSize.Level1) @@ -1494,7 +1494,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync003, TestSize.Level1) * @tc.name: Ability Sync 004 * @tc.desc: Test ability sync failed when one device hasn't distributed table. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync004, TestSize.Level1) @@ -1534,7 +1534,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync005, TestSize.Level1) * @tc.name: WaterMark 001 * @tc.desc: Test sync success after erase waterMark. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, WaterMark001, TestSize.Level1) @@ -1557,7 +1557,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, WaterMark001, TestSize.Level1) * @tc.name: pressure sync 001 * @tc.desc: Test rdb sync different table at same time * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, PressureSync001, TestSize.Level1) @@ -1613,7 +1613,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, PressureSync001, TestSize.Level1 * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer001, TestSize.Level1) { /** * @tc.steps: step1. device A create table and device B insert data and device C don't insert data @@ -1640,7 +1640,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer001, TestSize.Level0) * @tc.name: relation observer 002 * @tc.desc: Test rdb observer ok in autolauchCallback scene * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer002, TestSize.Level3) @@ -1704,7 +1704,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer002, TestSize.Level3) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer003, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer003, TestSize.Level1) { /** * @tc.steps: step1. device A create table and device B insert data and device C don't insert data @@ -1754,7 +1754,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer003, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer004, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer004, TestSize.Level1) { /** * @tc.steps: step1. device A create table and device B insert data and device C don't insert data @@ -1789,7 +1789,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer004, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer005, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer005, TestSize.Level1) { /** * @tc.steps: step1. device A create table and device B insert data and device C don't insert data @@ -2069,7 +2069,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer008, TestSize.Level3) * @tc.name: remote query 001 * @tc.desc: Test rdb remote query * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery001, TestSize.Level1) @@ -2089,7 +2089,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery001, TestSize.Level1) * @tc.name: remote query 002 * @tc.desc: Test rdb remote query * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery002, TestSize.Level1) @@ -2109,7 +2109,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery002, TestSize.Level1) * @tc.name: remote query 003 * @tc.desc: Test rdb remote query but query not data * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery003, TestSize.Level1) @@ -2130,7 +2130,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery003, TestSize.Level1) * @tc.name: remote query 004 * @tc.desc: Test rdb queue size * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery004, TestSize.Level3) @@ -2169,7 +2169,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery004, TestSize.Level3) * @tc.name: remote query 005 * @tc.desc: Test rdb remote query timeout by invalid message * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery005, TestSize.Level1) @@ -2193,7 +2193,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery005, TestSize.Level1) * @tc.name: remote query 006 * @tc.desc: Test rdb remote query commfailure by offline * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery006, TestSize.Level1) @@ -2230,7 +2230,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery006, TestSize.Level1) * @tc.name: remote query 007 * @tc.desc: Test rdb remote query failed by permission check * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery007, TestSize.Level1) @@ -2258,7 +2258,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery007, TestSize.Level1) * @tc.name: remote query 008 * @tc.desc: Test rdb remote query timeout but not effected by invalid message * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery008, TestSize.Level1) @@ -2304,7 +2304,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery008, TestSize.Level1) * @tc.name: remote query 009 * @tc.desc: Test rdb remote query busy before timeout * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery009, TestSize.Level1) @@ -2337,7 +2337,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery009, TestSize.Level1) * @tc.name: remote query 010 * @tc.desc: Test rdb remote query with kv db * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery010, TestSize.Level1) @@ -2357,7 +2357,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery010, TestSize.Level1) * @tc.name: remote query 010 * @tc.desc: Test rdb remote query with error sql * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery011, TestSize.Level1) @@ -2377,7 +2377,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery011, TestSize.Level1) * @tc.name: remote query 012 * @tc.desc: Test rdb remote query with invalid dev * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery012, TestSize.Level1) @@ -2400,7 +2400,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery012, TestSize.Level1) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery013, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery013, TestSize.Level1) { std::map dataMap; PrepareEnvironment(dataMap, {g_deviceB}); @@ -2416,10 +2416,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery013, TestSize.Level0) * @tc.name: RelationalPemissionTest001 * @tc.desc: deviceB PermissionCheck not pass test, SYNC_MODE_PUSH_ONLY * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest001, TestSize.Level1) { /** * @tc.steps: step1. SetPermissionCheckCallback @@ -2461,10 +2461,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest001, Test * @tc.name: RelationalPemissionTest002 * @tc.desc: deviceB PermissionCheck not pass test, SYNC_MODE_PULL_ONLY * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest002, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest002, TestSize.Level1) { /** * @tc.steps: step1. SetPermissionCheckCallback @@ -2506,10 +2506,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest002, Test * @tc.name: RelationalPemissionTest003 * @tc.desc: deviceB PermissionCheck not pass test, flag CHECK_FLAG_SPONSOR * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest003, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest003, TestSize.Level1) { /** * @tc.steps: step1. SetPermissionCheckCallback @@ -2551,10 +2551,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest003, Test * @tc.name: RelationalPemissionTest004 * @tc.desc: deviceB PermissionCheck pass test. deviceC not pass, SYNC_MODE_PUSH_ONLY * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest004, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest004, TestSize.Level1) { /** * @tc.steps: step1. SetPermissionCheckCallback @@ -2607,7 +2607,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RelationalPemissionTest004, Test * @tc.name: SecurityOptionCheck001 * @tc.desc: Test sync failed when getSecurityOption return error * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, SecurityOptionCheck001, TestSize.Level1) @@ -2641,7 +2641,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, SecurityOptionCheck001, TestSize * @tc.name: SecurityOptionCheck002 * @tc.desc: Test remote query failed when getSecurityOption return error * @tc.type: FUNC -* @tc.require: AR000GK58G +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, SecurityOptionCheck002, TestSize.Level1) @@ -2678,10 +2678,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, SecurityOptionCheck002, TestSize * @tc.name: OrderbyWriteTimeSync001 * @tc.desc: sync query with order by writeTime * @tc.type: FUNC -* @tc.require: AR000H5VLO +* @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, OrderbyWriteTimeSync001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, OrderbyWriteTimeSync001, TestSize.Level1) { std::map dataMap; PrepareEnvironment(dataMap, {g_deviceB}); @@ -2694,7 +2694,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, OrderbyWriteTimeSync001, TestSiz * @tc.name: RDBSecurityOptionCheck001 * @tc.desc: Test sync with security option. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RDBSecurityOptionCheck001, TestSize.Level3) @@ -2706,7 +2706,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RDBSecurityOptionCheck001, TestS * @tc.name: RDBSecurityOptionCheck002 * @tc.desc: Test remote query with security option. * @tc.type: FUNC -* @tc.require: AR000GK58N +* @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RDBSecurityOptionCheck002, TestSize.Level1) @@ -2718,10 +2718,10 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RDBSecurityOptionCheck002, TestS * @tc.name: EncryptedAlgoUpgrade001 * @tc.desc: Test upgrade encrypted db can sync normally * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, EncryptedAlgoUpgrade001, TestSize.Level0) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, EncryptedAlgoUpgrade001, TestSize.Level1) { if (g_rdbDelegatePtr != nullptr) { LOGD("CloseStore Start"); @@ -2769,7 +2769,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, EncryptedAlgoUpgrade001, TestSiz * @tc.name: AutoLaunchSyncAfterRekey_001 * @tc.desc: Test auto launch sync ok after rekey. * @tc.type: FUNC -* @tc.require: AR000H68LL +* @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSyncAfterRekey_001, TestSize.Level3) @@ -2784,10 +2784,8 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSyncAfterRekey_001, Te * @tc.steps: step2. set auto launch callBack */ AutoLaunchParam encryptedParam { USER_ID, APP_ID, STORE_ID_1, AutoLaunchOption {}, nullptr, g_dbDir }; - encryptedParam.option.isEncryptedDb = true; - encryptedParam.option.cipher = CipherType::DEFAULT; - encryptedParam.option.passwd = g_correctPasswd; - encryptedParam.option.iterateTimes = DEFAULT_ITER; + encryptedParam.option = {.isEncryptedDb = true, .cipher = CipherType::DEFAULT, .passwd = g_correctPasswd, + .iterateTimes = DEFAULT_ITER}; AutoLaunchRequestCallback callback = [&encryptedParam](const std::string &identifier, AutoLaunchParam ¶m) { if (g_id != identifier) { return false; @@ -2807,7 +2805,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSyncAfterRekey_001, Te LabelType labelType(g_id.begin(), g_id.end()); g_communicatorAggregator->RunCommunicatorLackCallback(labelType); std::this_thread::sleep_for(std::chrono::seconds(1)); - + RuntimeConfig::ReleaseAutoLaunch(USER_ID, APP_ID, STORE_ID_1, DBType::DB_RELATION); /** * @tc.steps: step5. Rekey */ @@ -2823,6 +2821,8 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSyncAfterRekey_001, Te /** * @tc.steps: step6. Call sync expect sync failed */ + g_communicatorAggregator->RunCommunicatorLackCallback(labelType); + std::this_thread::sleep_for(std::chrono::seconds(1)); Query query = Query::Select(g_tableName); EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK); size_t count = 0; @@ -2849,83 +2849,11 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSyncAfterRekey_001, Te std::this_thread::sleep_for(std::chrono::minutes(1)); sqlite3_close(db); db = nullptr; + g_mgr.SetAutoLaunchRequestCallback(nullptr); } /** -* @tc.name: AutoLaunchSyncAfterRekey_002 -* @tc.desc: Test auto launch close check after rekey. -* @tc.type: FUNC -* @tc.require: AR000H68LL -* @tc.author: zhangqiquan -*/ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSyncAfterRekey_002, TestSize.Level3) -{ - /** - * @tc.steps: step1. open rdb store, create distribute table and insert data - */ - std::map dataMap; - PrepareVirtualEnvironment(dataMap, {g_deviceB}); - /** - * @tc.steps: step2. set auto launch callBack - */ - AutoLaunchParam encryptedParam { USER_ID, APP_ID, STORE_ID_1, AutoLaunchOption {}, nullptr, g_dbDir }; - encryptedParam.option.isEncryptedDb = true; - encryptedParam.option.cipher = CipherType::DEFAULT; - encryptedParam.option.passwd = g_correctPasswd; - encryptedParam.option.iterateTimes = DEFAULT_ITER; - AutoLaunchRequestCallback callback = [&encryptedParam](const std::string &identifier, AutoLaunchParam ¶m) { - param = encryptedParam; - return true; - }; - RelationalStoreManager::SetAutoLaunchRequestCallback(callback); - /** - * @tc.steps: step3. close store ensure communicator has closed - */ - g_mgr.CloseStore(g_rdbDelegatePtr); - g_rdbDelegatePtr = nullptr; - /** - * @tc.steps: step4. RunCommunicatorLackCallback to autolaunch store - */ - LabelType labelType(g_id.begin(), g_id.end()); - g_communicatorAggregator->RunCommunicatorLackCallback(labelType); - std::this_thread::sleep_for(std::chrono::seconds(2)); // wait 2s for auto launch - /** - * @tc.steps: step5. Rekey - */ - sqlite3 *db = nullptr; - EXPECT_EQ(GetDB(db), SQLITE_OK); - std::string sql = "PARGMA rekey=" + REKEY_KEY; - EXPECT_EQ(sqlite3_rekey(db, REKEY_KEY.data(), REKEY_KEY.size()), SQLITE_OK); - g_isAfterRekey = true; - - RelationalDBProperties properties; - properties.SetStringProp(DBProperties::USER_ID, USER_ID); - properties.SetStringProp(DBProperties::APP_ID, APP_ID); - properties.SetStringProp(DBProperties::STORE_ID, STORE_ID_1); - properties.SetIntProp(DBProperties::AUTO_LAUNCH_ID, 7); // 7: invalid AUTO LAUNCH ID - const string &id = RelationalStoreManager::GetRelationalStoreIdentifier(USER_ID, APP_ID, STORE_ID_1); - properties.SetStringProp(DBProperties::IDENTIFIER_DATA, id); - RuntimeContext::GetInstance()->CloseAutoLaunchConnection(DBTypeInner::DB_RELATION, properties); - - encryptedParam.option.passwd = g_rekeyPasswd; - RelationalStoreManager::SetAutoLaunchRequestCallback(callback); - g_communicatorAggregator->RunCommunicatorLackCallback(labelType); - std::this_thread::sleep_for(std::chrono::seconds(2)); // wait 2s for auto launch - - Query query = Query::Select(g_tableName); - EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK); - size_t count = 0; - GetCount(db, "SELECT count(*) FROM sqlite_master WHERE name='" + GetDeviceTableName(g_tableName) + "';", count); - EXPECT_EQ(count, 0u); - - OpenStore(); - std::this_thread::sleep_for(std::chrono::minutes(1)); - sqlite3_close(db); - db = nullptr; -} - -/** -* @tc.name: AutoLaunchSyncAfterRekey_002 +* @tc.name: SyncTargetTest001 * @tc.desc: Test AddSyncTarget will not cause heap_use_after_free * @tc.type: FUNC * @tc.require: diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_dlp_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_dlp_test.cpp index 936df57c..9241d5e6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_dlp_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_dlp_test.cpp @@ -15,16 +15,20 @@ #include #include +#include #include #include "db_constant.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" +#include "generic_single_ver_kv_entry.h" #include "kv_store_nb_delegate.h" #include "kv_virtual_device.h" +#include "mock_sync_task_context.h" #include "platform_specific.h" #include "relational_store_manager.h" #include "runtime_config.h" +#include "single_ver_data_sync_utils.h" using namespace testing::ext; using namespace DistributedDB; @@ -36,8 +40,10 @@ namespace { VirtualCommunicatorAggregator* g_communicatorAggregator = nullptr; const std::string DEVICE_A = "real_device"; const std::string DEVICE_B = "deviceB"; + const std::string DEVICE_C = "deviceC"; const std::string KEY_INSTANCE_ID = "INSTANCE_ID"; KvVirtualDevice *g_deviceB = nullptr; + KvVirtualDevice *g_deviceC = nullptr; DistributedDBToolsUnitTest g_tool; DBStatus OpenDelegate(const std::string &dlpPath, KvStoreNbDelegate *&delegatePtr, @@ -107,7 +113,14 @@ namespace { } } +class MockVirtualSingleVerSyncDBInterface : public VirtualSingleVerSyncDBInterface { +public: + MOCK_CONST_METHOD1(GetSecurityOption, int(SecurityOption &)); +}; + class DistributedDBSingleVerDLPTest : public testing::Test { +public: + MockVirtualSingleVerSyncDBInterface *syncInterfaceC = nullptr; public: static void SetUpTestCase(void); static void TearDownTestCase(void); @@ -147,9 +160,14 @@ void DistributedDBSingleVerDLPTest::SetUp(void) DistributedDBToolsUnitTest::PrintTestCaseInfo(); g_deviceB = new (std::nothrow) KvVirtualDevice(DEVICE_B); ASSERT_TRUE(g_deviceB != nullptr); + g_deviceC = new (std::nothrow) KvVirtualDevice(DEVICE_C); + ASSERT_TRUE(g_deviceC != nullptr); VirtualSingleVerSyncDBInterface *syncInterfaceB = new (std::nothrow) VirtualSingleVerSyncDBInterface(); ASSERT_TRUE(syncInterfaceB != nullptr); ASSERT_EQ(g_deviceB->Initialize(g_communicatorAggregator, syncInterfaceB), E_OK); + syncInterfaceC = new (std::nothrow) MockVirtualSingleVerSyncDBInterface(); + ASSERT_TRUE(syncInterfaceC != nullptr); + ASSERT_EQ(g_deviceC->Initialize(g_communicatorAggregator, syncInterfaceC), E_OK); } void DistributedDBSingleVerDLPTest::TearDown(void) @@ -158,6 +176,10 @@ void DistributedDBSingleVerDLPTest::TearDown(void) delete g_deviceB; g_deviceB = nullptr; } + if (g_deviceC != nullptr) { + delete g_deviceC; + g_deviceC = nullptr; + } PermissionCheckCallbackV3 nullCallback = nullptr; RuntimeConfig::SetPermissionCheckCallback(nullCallback); SyncActivationCheckCallbackV2 activeCallBack = nullptr; @@ -169,7 +191,7 @@ void DistributedDBSingleVerDLPTest::TearDown(void) * @tc.name: SameDelegateTest001 * @tc.desc: Test kv delegate open with diff instanceID. * @tc.type: FUNC - * @tc.require: SR000H0JSC + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerDLPTest, SameDelegateTest001, TestSize.Level1) @@ -208,7 +230,7 @@ HWTEST_F(DistributedDBSingleVerDLPTest, SameDelegateTest001, TestSize.Level1) * @tc.name: SameDelegateTest002 * @tc.desc: Test rdb delegate open with diff instanceID. * @tc.type: FUNC - * @tc.require: SR000H0JSC + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerDLPTest, SameDelegateTest002, TestSize.Level1) @@ -231,7 +253,7 @@ HWTEST_F(DistributedDBSingleVerDLPTest, SameDelegateTest002, TestSize.Level1) * @tc.name: DlpDelegateCRUDTest001 * @tc.desc: Test dlp delegate crud function. * @tc.type: FUNC - * @tc.require: SR000H0JSC + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerDLPTest, DlpDelegateCRUDTest001, TestSize.Level1) @@ -264,7 +286,7 @@ HWTEST_F(DistributedDBSingleVerDLPTest, DlpDelegateCRUDTest001, TestSize.Level1) * @tc.name: SandboxDelegateSync001 * @tc.desc: Test dlp delegate sync function. * @tc.type: FUNC - * @tc.require: SR000H0JSC + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerDLPTest, SandboxDelegateSync001, TestSize.Level1) @@ -310,7 +332,7 @@ HWTEST_F(DistributedDBSingleVerDLPTest, SandboxDelegateSync001, TestSize.Level1) * @tc.name: SandboxDelegateSync002 * @tc.desc: Test dlp delegate sync active if callback return true. * @tc.type: FUNC - * @tc.require: SR000H0JSC + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerDLPTest, SandboxDelegateSync002, TestSize.Level1) @@ -334,4 +356,104 @@ HWTEST_F(DistributedDBSingleVerDLPTest, SandboxDelegateSync002, TestSize.Level1) EXPECT_EQ(result[DEVICE_B], OK); CloseDelegate(delegatePtr1, mgr1, STORE_ID_1); +} + +/** + * @tc.name: SingleVerUtilsTest001 + * @tc.desc: Test single verification utils function. + * @tc.type: FUNC + * @tc.require: + * @tc.author: lg + */ +HWTEST_F(DistributedDBSingleVerDLPTest, SingleVerUtilsTest001, TestSize.Level0) +{ + bool isCheckStatus; + EXPECT_EQ(SingleVerDataSyncUtils::QuerySyncCheck(nullptr, isCheckStatus), -E_INVALID_ARGS); + MockSyncTaskContext context; + context.SetQuerySync(true); + context.SetRemoteSoftwareVersion(SOFTWARE_VERSION_RELEASE_1_0); + EXPECT_EQ(SingleVerDataSyncUtils::QuerySyncCheck(&context, isCheckStatus), OK); + context.SetRemoteSoftwareVersion(SOFTWARE_VERSION_RELEASE_3_0); + EXPECT_EQ(SingleVerDataSyncUtils::QuerySyncCheck(&context, isCheckStatus), OK); + EXPECT_EQ(SingleVerDataSyncUtils::RequestQueryCheck(nullptr, nullptr), -E_INVALID_ARGS); + + std::string deviceId; + SecurityOption option; + EXPECT_EQ(SingleVerDataSyncUtils::IsPermitRemoteDeviceRecvData(deviceId, option, nullptr), false); + EXPECT_CALL(*syncInterfaceC, GetSecurityOption(testing::_)).WillOnce(testing::Return(-E_INVALID_DB)); + EXPECT_EQ(SingleVerDataSyncUtils::IsPermitRemoteDeviceRecvData(deviceId, option, syncInterfaceC), false); + EXPECT_CALL(*syncInterfaceC, GetSecurityOption(testing::_)).WillRepeatedly(testing::Return(E_OK)); + EXPECT_EQ(SingleVerDataSyncUtils::IsPermitRemoteDeviceRecvData(deviceId, option, syncInterfaceC), false); + std::vector outData = {nullptr}; + SingleVerDataSyncUtils::TransDbDataItemToSendDataItem(deviceId, outData); + SingleVerDataSyncUtils::TransSendDataItemToLocal(&context, deviceId, outData); + int errNo = E_OK; + auto communicator = g_communicatorAggregator->AllocCommunicator(12345, errNo); + EXPECT_EQ(SingleVerDataSyncUtils::CheckPermitReceiveData(&context, communicator, syncInterfaceC), false); + EXPECT_CALL(*syncInterfaceC, GetSecurityOption(testing::_)).WillRepeatedly(testing::Return(-E_NOT_SUPPORT)); + EXPECT_EQ(SingleVerDataSyncUtils::CheckPermitReceiveData(&context, communicator, syncInterfaceC), true); + option.securityLabel = SecurityLabel::S0; + context.SetRemoteSeccurityOption(option); + EXPECT_CALL(*syncInterfaceC, GetSecurityOption(testing::_)) + .WillRepeatedly(testing::Invoke([](SecurityOption &option) { + option.securityLabel = SecurityLabel::S1; + return E_OK; + })); + EXPECT_EQ(SingleVerDataSyncUtils::CheckPermitReceiveData(&context, communicator, syncInterfaceC), true); + EXPECT_CALL(*syncInterfaceC, GetSecurityOption(testing::_)) + .WillRepeatedly(testing::Invoke([](SecurityOption &option) { + option.securityLabel = SecurityLabel::S1; + return E_OK; + })); + option.securityLabel = FAILED_GET_SEC_CLASSIFICATION; + context.SetRemoteSeccurityOption(option); + EXPECT_EQ(SingleVerDataSyncUtils::CheckPermitReceiveData(&context, communicator, syncInterfaceC), false); + EXPECT_CALL(*syncInterfaceC, GetSecurityOption(testing::_)).Times(testing::AtLeast(0)); + g_communicatorAggregator->ReleaseCommunicator(communicator); +} + +/** + * @tc.name: SingleVerUtilsTest002 + * @tc.desc: Test single verification utils function. + * @tc.type: FUNC + * @tc.require: + * @tc.author: lg + */ +HWTEST_F(DistributedDBSingleVerDLPTest, SingleVerUtilsTest002, TestSize.Level0) +{ + MockSyncTaskContext context; + context.SetRemoteSoftwareVersion(SOFTWARE_VERSION_RELEASE_3_0); + context.SetTaskErrCode(-E_EKEYREVOKED); + context.SetMode(SyncModeType::PUSH_AND_PULL); + SingleVerDataSyncUtils::PushAndPullKeyRevokHandle(&context); + EXPECT_EQ(SingleVerDataSyncUtils::GetReSendMode(SyncModeType::RESPONSE_PULL, 1, SyncType::QUERY_SYNC_TYPE), + SyncModeType::QUERY_PUSH); + EXPECT_EQ(SingleVerDataSyncUtils::GetReSendMode(SyncModeType::QUERY_PUSH_PULL, 1, SyncType::QUERY_SYNC_TYPE), + SyncModeType::QUERY_PUSH_PULL); + EXPECT_EQ(SingleVerDataSyncUtils::GetReSendMode(SyncModeType::QUERY_PUSH_PULL, 0, SyncType::QUERY_SYNC_TYPE), + SyncModeType::QUERY_PUSH); + EXPECT_EQ( + SingleVerDataSyncUtils::GetControlCmdType(SyncModeType::QUERY_PUSH_PULL), ControlCmdType::INVALID_CONTROL_CMD); + EXPECT_EQ(SingleVerDataSyncUtils::GetModeByControlCmdType(ControlCmdType::INVALID_CONTROL_CMD), + SyncModeType::INVALID_MODE); + EXPECT_EQ(SingleVerDataSyncUtils::GetModeByControlCmdType(ControlCmdType::UNSUBSCRIBE_QUERY_CMD), + SyncModeType::UNSUBSCRIBE_QUERY); + QuerySyncObject query; + EXPECT_EQ(SingleVerDataSyncUtils::IsNeedTriggerQueryAutoSync(nullptr, query), false); + Message msg; + msg.SetMessageId(CONTROL_SYNC_MESSAGE); + msg.SetMessageType(TYPE_REQUEST); + EXPECT_EQ(SingleVerDataSyncUtils::IsNeedTriggerQueryAutoSync(&msg, query), false); + std::vector inData = {nullptr}; + SingleVerDataSyncUtils::GetMaxSendDataTime(inData); + UpdateWaterMark isUpdate; + auto kvEnv = new (std::nothrow) GenericSingleVerKvEntry(); + inData.push_back(kvEnv); + SingleVerDataSyncUtils::GetFullSyncDataTimeRange(inData, 100, isUpdate); + SingleVerDataSyncUtils::GetQuerySyncDataTimeRange(inData, 100, 100, isUpdate); + DataItem dataItem; + dataItem.flag = DataItem::DELETE_FLAG; + kvEnv->SetEntryData(std::move(dataItem)); + SingleVerDataSyncUtils::GetQuerySyncDataTimeRange(inData, 100, 100, isUpdate); + delete kvEnv; } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_sub_user_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_sub_user_test.cpp index d21c470e..1f612d0e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_sub_user_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_sub_user_test.cpp @@ -467,21 +467,19 @@ HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserPermissionCheck, TestSiz EXPECT_EQ(OpenDelegate("/subUser1", delegatePtr1, mgr1), OK); ASSERT_NE(delegatePtr1, nullptr); - DBStatus status = OK; std::vector devices; devices.push_back(g_deviceB->GetDeviceId()); Key key = {'1'}; Value value = {'1'}; g_deviceB->PutData(key, value, 0, 0); - ASSERT_TRUE(status == OK); /** * @tc.steps: step3. deviceB push data * @tc.expected: step3. return PERMISSION_CHECK_FORBID_SYNC. */ std::map result; - status = g_tool.SyncTest(delegatePtr1, devices, SYNC_MODE_PUSH_ONLY, result); + DBStatus status = g_tool.SyncTest(delegatePtr1, devices, SYNC_MODE_PUSH_ONLY, result); ASSERT_TRUE(status == OK); std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); @@ -697,7 +695,7 @@ HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserDelegateCRUDTest002, Tes * @tc.require: * @tc.author: zhaoliang */ -HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserDelegateCloudSyncTest001, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserDelegateCloudSyncTest001, TestSize.Level1) { KvStoreDelegateManager mgr1(APP_ID, USER_ID, SUB_USER_1, INSTANCE_ID_1); KvStoreNbDelegate *delegatePtr1 = nullptr; @@ -737,7 +735,7 @@ HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserDelegateCloudSyncTest001 * @tc.require: * @tc.author: zhaoliang */ -HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserDelegateCloudSyncTest002, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiSubUserTest, SubUserDelegateCloudSyncTest002, TestSize.Level1) { RelationalStoreManager mgr1(APP_ID, USER_ID, SUB_USER_1, INSTANCE_ID_1); RelationalStoreDelegate *rdbDelegatePtr1 = nullptr; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp index 89da1671..f21a0ba7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp @@ -297,10 +297,10 @@ void TestSyncWithUserChange(bool wait) * @tc.name: multi user 001 * @tc.desc: Test multi user change * @tc.type: FUNC - * @tc.require: AR000CQS3S SR000CQE0B + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser001, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser001, TestSize.Level1) { /** * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active @@ -373,10 +373,10 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser001, TestSize.Level0) * @tc.name: multi user 002 * @tc.desc: Test multi user not change * @tc.type: FUNC - * @tc.require: AR000CQS3S SR000CQE0B + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser002, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser002, TestSize.Level1) { /** * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active @@ -445,7 +445,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser002, TestSize.Level0) * @tc.name: multi user 003 * @tc.desc: enhancement callback return true in multiuser mode * @tc.type: FUNC - * @tc.require: AR000EPARJ + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser003, TestSize.Level3) @@ -509,10 +509,10 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser003, TestSize.Level3) * @tc.name: MultiUser004 * @tc.desc: CommunicatorLackCallback in multi user mode * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser004, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser004, TestSize.Level1) { /** * @tc.steps: step1. set SyncActivationCheckCallback and only userId2 can active @@ -585,10 +585,10 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser004, TestSize.Level0) * @tc.name: MultiUser005 * @tc.desc: test NotifyUserChanged func when all db in normal sync mode * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser005, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser005, TestSize.Level1) { /** * @tc.steps: step1. openstore1 and openstore2 in normal sync mode @@ -620,10 +620,10 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser005, TestSize.Level0) * @tc.name: MultiUser006 * @tc.desc: test NotifyUserChanged and close db concurrently * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser006, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser006, TestSize.Level1) { /** * @tc.steps: step1. set SyncActivationCheckCallback and only userId1 can active @@ -656,7 +656,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser006, TestSize.Level0) * @tc.name: MultiUser007 * @tc.desc: test NotifyUserChanged and rekey db concurrently * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser007, TestSize.Level0) @@ -693,10 +693,10 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser007, TestSize.Level0) * @tc.name: MultiUser008 * @tc.desc: test NotifyUserChanged and block sync concurrently * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhuwentao */ -HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser008, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser008, TestSize.Level1) { TestSyncWithUserChange(true); } @@ -705,7 +705,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser008, TestSize.Level0) * @tc.name: MultiUser009 * @tc.desc: test NotifyUserChanged and non-block sync concurrently * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser009, TestSize.Level0) @@ -717,7 +717,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser009, TestSize.Level0) * @tc.name: MultiUser010 * @tc.desc: test NotifyUserChanged and non-block sync with multi devices concurrently * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser010, TestSize.Level3) @@ -786,7 +786,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser010, TestSize.Level3) * @tc.name: MultiUser011 * @tc.desc: test check sync active twice when open store * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser011, TestSize.Level1) @@ -819,7 +819,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser011, TestSize.Level1) * @tc.name: MultiUser012 * @tc.desc: test NotifyUserChanged and SetEqualIdentifier sync concurrently * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser012, TestSize.Level1) @@ -856,7 +856,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser012, TestSize.Level1) * @tc.name: MultiUser013 * @tc.desc: test dont check sync active when open store with normal store * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser013, TestSize.Level1) @@ -883,7 +883,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser013, TestSize.Level1) * @tc.name: MultiUser014 * @tc.desc: test active callback call count * @tc.type: FUNC - * @tc.require: AR000E8S2T + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser014, TestSize.Level1) @@ -916,7 +916,7 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser014, TestSize.Level1) * @tc.require: * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser015, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser015, TestSize.Level1) { /** * @tc.steps: step1. create sub user KvStoreDelegateManager diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp index e27cf38a..f19e07cf 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp @@ -281,7 +281,7 @@ void DistributedDBSingleVerP2PComplexSyncTest::TearDown(void) * @tc.name: SaveDataNotify001 * @tc.desc: Test SaveDataNotify function, delay < 30s should sync ok, > 36 should timeout * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SaveDataNotify001, TestSize.Level3) @@ -353,7 +353,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SaveDataNotify001, TestSize.L * @tc.name: SametimeSync001 * @tc.desc: Test 2 device sync with each other * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SametimeSync001, TestSize.Level3) @@ -415,7 +415,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SametimeSync001, TestSize.Lev * @tc.name: SametimeSync002 * @tc.desc: Test 2 device sync with each other with water error * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SametimeSync002, TestSize.Level3) @@ -484,7 +484,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SametimeSync002, TestSize.Lev * @tc.name: DatabaseOnlineCallback001 * @tc.desc: check database status notify online callback * @tc.type: FUNC - * @tc.require: AR000CQS3S SR000CQE0B + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DatabaseOnlineCallback001, TestSize.Level1) @@ -517,7 +517,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DatabaseOnlineCallback001, Te * @tc.name: DatabaseOfflineCallback001 * @tc.desc: check database status notify online callback * @tc.type: FUNC - * @tc.require: AR000CQS3S SR000CQE0B + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DatabaseOfflineCallback001, TestSize.Level1) @@ -550,7 +550,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DatabaseOfflineCallback001, T * @tc.name: CloseSync001 * @tc.desc: Test 2 delegate close when sync * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, CloseSync001, TestSize.Level3) @@ -608,7 +608,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, CloseSync001, TestSize.Level3 * @tc.name: CloseSync002 * @tc.desc: Test 1 delegate close when in time sync * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, CloseSync002, TestSize.Level3) @@ -660,7 +660,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, CloseSync002, TestSize.Level3 * @tc.name: OrderbyWriteTimeSync001 * @tc.desc: sync query with order by writeTime * @tc.type: FUNC - * @tc.require: AR000H5VLO + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, OrderbyWriteTimeSync001, TestSize.Level0) @@ -680,7 +680,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, OrderbyWriteTimeSync001, Test * @tc.name: Device Offline Sync 001 * @tc.desc: Test push sync when device offline * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DeviceOfflineSync001, TestSize.Level1) @@ -757,7 +757,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DeviceOfflineSync001, TestSiz * @tc.name: Device Offline Sync 002 * @tc.desc: Test pull sync when device offline * @tc.type: FUNC - * @tc.require: AR000CCPOM + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DeviceOfflineSync002, TestSize.Level1) @@ -831,7 +831,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DeviceOfflineSync002, TestSiz * @tc.name: EncryptedAlgoUpgrade001 * @tc.desc: Test upgrade encrypted db can sync normally * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, EncryptedAlgoUpgrade001, TestSize.Level3) @@ -954,7 +954,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, RemoveDeviceData002, TestSize * @tc.name: DataSync001 * @tc.desc: Test Data Sync when Initialize * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync001, TestSize.Level1) @@ -976,7 +976,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync001, TestSize.Level1) * @tc.name: DataSync002 * @tc.desc: Test active sync with invalid param in DataSync Class * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync002, TestSize.Level1) @@ -997,7 +997,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync002, TestSize.Level1) * @tc.name: DataSync003 * @tc.desc: Test receive invalid request data packet in DataSync Class * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync003, TestSize.Level1) @@ -1015,7 +1015,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync003, TestSize.Level1) * @tc.name: DataSync004 * @tc.desc: Test receive invalid ack packet in DataSync Class * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync004, TestSize.Level1) @@ -1036,7 +1036,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync004, TestSize.Level1) * @tc.name: DataSync005 * @tc.desc: Test receive invalid notify packet in DataSync Class * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync005, TestSize.Level1) @@ -1048,7 +1048,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync005, TestSize.Level1) * @tc.name: DataSync006 * @tc.desc: Test control start with invalid param in DataSync Class * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync006, TestSize.Level1) @@ -1076,7 +1076,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync006, TestSize.Level1) * @tc.name: DataSync007 * @tc.desc: Test receive invalid control packet in DataSync Class * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync007, TestSize.Level1) @@ -1096,7 +1096,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync007, TestSize.Level1) * @tc.name: DataSync008 * @tc.desc: Test pull null msg in dataQueue in DataSync Class * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync008, TestSize.Level1) @@ -1108,7 +1108,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DataSync008, TestSize.Level1) * @tc.name: SyncRetry001 * @tc.desc: use sync retry sync use push * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry001, TestSize.Level3) @@ -1152,7 +1152,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry001, TestSize.Level3 * @tc.name: SyncRetry002 * @tc.desc: use sync retry sync use pull * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry002, TestSize.Level3) @@ -1191,7 +1191,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry002, TestSize.Level3 * @tc.name: SyncRetry003 * @tc.desc: use sync retry sync use push by compress * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry003, TestSize.Level3) @@ -1250,7 +1250,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry003, TestSize.Level3 * @tc.name: SyncRetry004 * @tc.desc: use query sync retry sync use push * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry004, TestSize.Level3) @@ -1301,7 +1301,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry004, TestSize.Level3 * @tc.name: SyncRetry005 * @tc.desc: use sync retry sync use pull by compress * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry005, TestSize.Level3) @@ -1354,7 +1354,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SyncRetry005, TestSize.Level3 * @tc.name: ReSetWatchDogTest001 * @tc.desc: trigger resetWatchDog while pull * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, ReSetWaterDogTest001, TestSize.Level3) @@ -1651,7 +1651,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, RebuildSync004, TestSize.Leve * @tc.name: RemoveDeviceData001 * @tc.desc: call rekey and removeDeviceData Concurrently * @tc.type: FUNC - * @tc.require: AR000D487B + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, RemoveDeviceData001, TestSize.Level1) @@ -1695,7 +1695,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, RemoveDeviceData001, TestSize * @tc.name: DeviceOfflineSyncTask001 * @tc.desc: Test sync task when device offline and close db Concurrently * @tc.type: FUNC - * @tc.require: AR000HI2JS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DeviceOfflineSyncTask001, TestSize.Level3) @@ -1850,7 +1850,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, GetSyncDataFail001, TestSize. * @tc.name: GetSyncDataFail002 * @tc.desc: test get sync data failed when sync with large data * @tc.type: FUNC - * @tc.require: AR000D487B + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, GetSyncDataFail002, TestSize.Level1) @@ -2025,7 +2025,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, InterceptDataFail001, TestSiz * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, InterceptDataFail002, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, InterceptDataFail002, TestSize.Level1) { ASSERT_TRUE(g_kvDelegatePtr != nullptr); /** diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_permission_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_permission_sync_test.cpp index 2068e73e..63051fec 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_permission_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_permission_sync_test.cpp @@ -150,7 +150,7 @@ void DistributedDBSingleVerP2PPermissionSyncTest::TearDown(void) * @tc.name: PermissionCheck001 * @tc.desc: deviceA PermissionCheck not pass test, SYNC_MODE_PUSH_ONLY * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck001, TestSize.Level3) @@ -213,7 +213,7 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck001, TestSi * @tc.name: PermissionCheck002 * @tc.desc: deviceA PermissionCheck not pass test, SYNC_MODE_PULL_ONLY * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck002, TestSize.Level3) @@ -235,7 +235,6 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck002, TestSi EXPECT_EQ(g_mgr.SetPermissionCheckCallback(permissionCheckCallback), OK); - DBStatus status = OK; std::vector devices; devices.push_back(g_deviceB->GetDeviceId()); devices.push_back(g_deviceC->GetDeviceId()); @@ -253,14 +252,13 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck002, TestSi Key key2 = {'2'}; Value value2 = {'2'}; g_deviceC->PutData(key2, value2, 0, 0); - ASSERT_TRUE(status == OK); /** * @tc.steps: step3. deviceA call pull sync * @tc.expected: step3. sync should return OK. */ std::map result; - status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result); + DBStatus status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result); ASSERT_TRUE(status == OK); /** @@ -283,7 +281,7 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck002, TestSi * @tc.name: PermissionCheck003 * @tc.desc: deviceA PermissionCheck not pass test, SYNC_MODE_PUSH_PULL * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck003, TestSize.Level3) @@ -372,7 +370,7 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck003, TestSi * @tc.name: PermissionCheck004 * @tc.desc: deviceB and deviceC PermissionCheck not pass test, SYNC_MODE_PUSH_ONLY * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck004, TestSize.Level3) @@ -435,7 +433,7 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck004, TestSi * @tc.name: PermissionCheck005 * @tc.desc: deviceB and deviceC PermissionCheck not pass test, SYNC_MODE_PULL_ONLY * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck005, TestSize.Level3) @@ -456,7 +454,6 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck005, TestSi }; EXPECT_EQ(g_mgr.SetPermissionCheckCallback(permissionCheckCallback), OK); - DBStatus status = OK; std::vector devices; devices.push_back(g_deviceB->GetDeviceId()); devices.push_back(g_deviceC->GetDeviceId()); @@ -474,14 +471,13 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck005, TestSi Key key2 = {'2'}; Value value2 = {'2'}; g_deviceC->PutData(key2, value2, 0, 0); - ASSERT_TRUE(status == OK); /** * @tc.steps: step3. deviceA call pull sync * @tc.expected: step3. sync should return OK. */ std::map result; - status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result); + DBStatus status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result); ASSERT_TRUE(status == OK); /** @@ -504,7 +500,7 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck005, TestSi * @tc.name: PermissionCheck006 * @tc.desc: deviceA PermissionCheck deviceB not pass, deviceC pass * @tc.type: FUNC - * @tc.require: AR000EJJOJ + * @tc.require: * @tc.author: wangchuanqing */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck006, TestSize.Level3) @@ -571,7 +567,7 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck006, TestSi * @tc.name: PermissionCheck007 * @tc.desc: deviceA PermissionCheck, deviceB not pass, deviceC pass in SYNC_MODE_AUTO_PUSH * @tc.type: FUNC - * @tc.require: AR000G3RLS + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck007, TestSize.Level3) @@ -626,12 +622,12 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck007, TestSi } /** -+ * @tc.name: PermissionCheck008 -+ * @tc.desc: deviceA PermissionCheck, deviceB not pass, deviceC pass in SYNC_MODE_AUTO_PULL -+ * @tc.type: FUNC -+ * @tc.require: AR000G3RLS -+ * @tc.author: zhangqiquan -+ */ + * @tc.name: PermissionCheck008 + * @tc.desc: deviceA PermissionCheck, deviceB not pass, deviceC pass in SYNC_MODE_AUTO_PULL + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck008, TestSize.Level3) { /** @@ -650,7 +646,6 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck008, TestSi } }; EXPECT_EQ(g_mgr.SetPermissionCheckCallback(permissionCheckCallback), OK); - DBStatus status = OK; std::vector devices; devices.push_back(g_deviceB->GetDeviceId()); devices.push_back(g_deviceC->GetDeviceId()); @@ -668,14 +663,13 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck008, TestSi Key key2 = {'2'}; Value value2 = {'2'}; g_deviceC->PutData(key2, value2, 0, 0); - ASSERT_TRUE(status == OK); /** * @tc.steps: step3. deviceA call push sync * @tc.expected: step3. sync should return OK. */ std::map result; - status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result); + DBStatus status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result); ASSERT_TRUE(status == OK); std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); @@ -706,7 +700,7 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck008, TestSi * @tc.name: PermissionCheck009 * @tc.desc: different runpermissioncheck call return different value * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck009, TestSize.Level3) @@ -777,7 +771,7 @@ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck009, TestSi * @tc.name: PermissionCheck010 * @tc.desc: permission check cost lot of time and return false * @tc.type: FUNC - * @tc.require: AR000D4876 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PPermissionSyncTest, PermissionCheck010, TestSize.Level3) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp index 6c5e788d..0927c57c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp @@ -199,13 +199,14 @@ void InitSchemaDb() g_schemaMgr.GetKvStore(SCHEMA_STORE_ID, option, g_schemaKvDelegateCallback); ASSERT_TRUE(g_schemaKvDelegateStatus == OK); ASSERT_TRUE(g_schemaKvDelegatePtr != nullptr); + g_deviceB->SetSchema(option.schema); } /** * @tc.name: Normal Sync 001 * @tc.desc: Test normal push sync for keyprefix data. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync001, TestSize.Level1) @@ -267,7 +268,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync001, TestSize.Level1) * @tc.name: Normal Sync 002 * @tc.desc: Test normal push sync for limit and offset. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync002, TestSize.Level1) @@ -327,7 +328,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync002, TestSize.Level1) * @tc.name: Normal Sync 001 * @tc.desc: Test normal push_and_pull sync for keyprefix data. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync003, TestSize.Level1) @@ -401,7 +402,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync003, TestSize.Level1) * @tc.name: Normal Sync 001 * @tc.desc: Test normal pull sync for keyprefix data. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync004, TestSize.Level1) @@ -469,7 +470,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync004, TestSize.Level1) * @tc.name: NormalSync005 * @tc.desc: Test normal push sync for inkeys query. * @tc.type: FUNC - * @tc.require: AR000GOHO7 + * @tc.require: * @tc.author: lidongwei */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync005, TestSize.Level1) @@ -772,7 +773,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, QueryAckPacketTest001, TestSize * @tc.name: GetQueryWaterMark 001 * @tc.desc: Test metaData save and get queryWaterMark. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark001, TestSize.Level1) @@ -792,17 +793,17 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark001, TestSize. * @tc.expected: step2. E_OK */ WaterMark w1 = 1; - EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D1", w1), E_OK); - EXPECT_EQ(meta.SetSendQueryWaterMark("Q1", "D1", w1), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D1", "", w1), E_OK); + EXPECT_EQ(meta.SetSendQueryWaterMark("Q1", "D1", "", w1), E_OK); /** * @tc.steps: step3. get receive and send watermark * @tc.expected: step3. E_OK and get the latest value */ WaterMark w = 0; - EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", w), E_OK); + EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", "", w), E_OK); EXPECT_EQ(w1, w); - EXPECT_EQ(meta.GetSendQueryWaterMark("Q1", "D1", w), E_OK); + EXPECT_EQ(meta.GetSendQueryWaterMark("Q1", "D1", "", w), E_OK); EXPECT_EQ(w1, w); /** @@ -810,16 +811,16 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark001, TestSize. * @tc.expected: step4. E_OK */ WaterMark w2 = 2; - EXPECT_EQ(meta.SaveLocalWaterMark("D1", w2), E_OK); - EXPECT_EQ(meta.SavePeerWaterMark("D1", w2, true), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark("D1", "", w2), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D1", "", w2, true), E_OK); /** * @tc.steps: step5. get receive and send watermark * @tc.expected: step5. E_OK and get the w1 */ - EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", w), E_OK); + EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", "", w), E_OK); EXPECT_EQ(w2, w); - EXPECT_EQ(meta.GetSendQueryWaterMark("Q1", "D1", w), E_OK); + EXPECT_EQ(meta.GetSendQueryWaterMark("Q1", "D1", "", w), E_OK); EXPECT_EQ(w2, w); /** @@ -827,25 +828,25 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark001, TestSize. * @tc.expected: step6. E_OK */ WaterMark w3 = 3; - EXPECT_EQ(meta.SaveLocalWaterMark("D2", w3), E_OK); - EXPECT_EQ(meta.SavePeerWaterMark("D2", w3, true), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark("D2", "", w3), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D2", "", w3, true), E_OK); /** * @tc.steps: step7. get receive and send watermark * @tc.expected: step7. E_OK and get the w3 */ - EXPECT_EQ(meta.GetRecvQueryWaterMark("Q2", "D2", w), E_OK); + EXPECT_EQ(meta.GetRecvQueryWaterMark("Q2", "D2", "", w), E_OK); EXPECT_EQ(w3, w); - EXPECT_EQ(meta.GetSendQueryWaterMark("Q2", "D2", w), E_OK); + EXPECT_EQ(meta.GetSendQueryWaterMark("Q2", "D2", "", w), E_OK); EXPECT_EQ(w3, w); /** * @tc.steps: step8. get not exit receive and send watermark * @tc.expected: step8. E_OK and get the 0 */ - EXPECT_EQ(meta.GetRecvQueryWaterMark("Q3", "D3", w), E_OK); + EXPECT_EQ(meta.GetRecvQueryWaterMark("Q3", "D3", "", w), E_OK); EXPECT_EQ(w, 0u); - EXPECT_EQ(meta.GetSendQueryWaterMark("Q3", "D3", w), E_OK); + EXPECT_EQ(meta.GetSendQueryWaterMark("Q3", "D3", "", w), E_OK); EXPECT_EQ(w, 0u); } @@ -853,7 +854,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark001, TestSize. * @tc.name: GetQueryWaterMark 002 * @tc.desc: Test metaData save and get queryWaterMark after push or pull mode. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark002, TestSize.Level1) @@ -873,25 +874,25 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark002, TestSize. * @tc.expected: step2. E_OK */ WaterMark w1 = 2; - EXPECT_EQ(meta.SaveLocalWaterMark("D1", w1), E_OK); - EXPECT_EQ(meta.SavePeerWaterMark("D1", w1, true), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark("D1", "", w1), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D1", "", w1, true), E_OK); /** * @tc.steps: step2. save receive and send watermark * @tc.expected: step2. E_OK */ WaterMark w2 = 1; - EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D1", w2), E_OK); - EXPECT_EQ(meta.SetSendQueryWaterMark("Q1", "D1", w2), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D1", "", w2), E_OK); + EXPECT_EQ(meta.SetSendQueryWaterMark("Q1", "D1", "", w2), E_OK); /** * @tc.steps: step3. get receive and send watermark * @tc.expected: step3. E_OK and get the bigger value */ WaterMark w = 0; - EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", w), E_OK); + EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", "", w), E_OK); EXPECT_EQ(w1, w); - EXPECT_EQ(meta.GetSendQueryWaterMark("Q1", "D1", w), E_OK); + EXPECT_EQ(meta.GetSendQueryWaterMark("Q1", "D1", "", w), E_OK); EXPECT_EQ(w1, w); } @@ -912,13 +913,13 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark003, TestSize. const std::string DEVICE_B = "DEVICE_B"; TimeOffset offset = 100; // 100: offset - meta.SaveTimeOffset(DEVICE_B, offset); + meta.SaveTimeOffset(DEVICE_B, "", offset); WaterMark w1 = 2; // 2: watermark - meta.SavePeerWaterMark(DBCommon::TransferHashString(DEVICE_B), w1, false); + meta.SavePeerWaterMark(DBCommon::TransferHashString(DEVICE_B), "", w1, false); TimeOffset offsetGot; - meta.GetTimeOffset(DEVICE_B, offsetGot); + meta.GetTimeOffset(DEVICE_B, "", offsetGot); EXPECT_EQ(offsetGot, offset); } @@ -926,7 +927,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryWaterMark003, TestSize. * @tc.name: GetDeleteWaterMark001 * @tc.desc: Test metaData save and get deleteWaterMark. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteWaterMark001, TestSize.Level1) @@ -949,17 +950,17 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteWaterMark001, TestSize const WaterMark maxWaterMark = 1000u; std::thread recvThread([&meta, &device, &maxWaterMark]() { for (WaterMark expectRecv = 0u; expectRecv < maxWaterMark; ++expectRecv) { - EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark(device, expectRecv), E_OK); + EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark(device, "", expectRecv), E_OK); WaterMark actualRecv = 0u; - EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark(device, actualRecv), E_OK); + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark(device, "", actualRecv), E_OK); EXPECT_EQ(actualRecv, expectRecv); } }); std::thread sendThread([&meta, &device, &maxWaterMark]() { for (WaterMark expectSend = 0u; expectSend < maxWaterMark; ++expectSend) { - EXPECT_EQ(meta.SetSendDeleteSyncWaterMark(device, expectSend), E_OK); + EXPECT_EQ(meta.SetSendDeleteSyncWaterMark(device, "", expectSend), E_OK); WaterMark actualSend = 0u; - EXPECT_EQ(meta.GetSendDeleteSyncWaterMark(device, actualSend), E_OK); + EXPECT_EQ(meta.GetSendDeleteSyncWaterMark(device, "", actualSend), E_OK); EXPECT_EQ(actualSend, expectSend); } }); @@ -971,7 +972,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteWaterMark001, TestSize * @tc.name: ClearQueryWaterMark 001 * @tc.desc: Test metaData clear watermark function. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark001, TestSize.Level1) @@ -991,7 +992,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark001, TestSiz * @tc.expected: step2. E_OK */ WaterMark w1 = 1; - EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D1", w1), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D1", "", w1), E_OK); /** * @tc.steps: step3. erase peer watermark @@ -1004,7 +1005,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark001, TestSiz * @tc.expected: step4. E_OK receive watermark is zero */ WaterMark w2 = -1; - EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", w2), E_OK); + EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", "", w2), E_OK); EXPECT_EQ(w2, 0u); /** @@ -1012,14 +1013,14 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark001, TestSiz * @tc.expected: step5. E_OK */ WaterMark w3 = 2; - EXPECT_EQ(meta.SavePeerWaterMark("D1", w3, true), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D1", "", w3, true), E_OK); /** * @tc.steps: step6. get receive watermark * @tc.expected: step6. E_OK receive watermark is peer watermark */ WaterMark w4 = -1; - EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", w4), E_OK); + EXPECT_EQ(meta.GetRecvQueryWaterMark("Q1", "D1", "", w4), E_OK); EXPECT_EQ(w4, w3); } @@ -1027,7 +1028,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark001, TestSiz * @tc.name: ClearQueryWaterMark 002 * @tc.desc: Test metaData clear watermark function. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark002, TestSize.Level1) @@ -1047,9 +1048,9 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark002, TestSiz * @tc.expected: step2. E_OK */ WaterMark w1 = 1; - EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D1", w1), E_OK); - EXPECT_EQ(meta.SetRecvQueryWaterMark("Q2", "D1", w1), E_OK); - EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D2", w1), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D1", "", w1), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark("Q2", "D1", "", w1), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark("Q1", "D2", "", w1), E_OK); /** * @tc.steps: step3. erase peer watermark, make sure data remove in db @@ -1064,13 +1065,13 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark002, TestSiz * @tc.expected: step4. E_OK receive watermark is zero */ WaterMark w2 = -1; - EXPECT_EQ(anotherMeta.GetRecvQueryWaterMark("Q1", "D1", w2), E_OK); + EXPECT_EQ(anotherMeta.GetRecvQueryWaterMark("Q1", "D1", "", w2), E_OK); EXPECT_EQ(w2, 0u); w2 = -1; - EXPECT_EQ(anotherMeta.GetRecvQueryWaterMark("Q2", "D1", w2), E_OK); + EXPECT_EQ(anotherMeta.GetRecvQueryWaterMark("Q2", "D1", "", w2), E_OK); EXPECT_EQ(w2, 0u); w2 = -1; - EXPECT_EQ(anotherMeta.GetRecvQueryWaterMark("Q1", "D2", w2), E_OK); + EXPECT_EQ(anotherMeta.GetRecvQueryWaterMark("Q1", "D2", "", w2), E_OK); EXPECT_EQ(w2, w1); } @@ -1078,7 +1079,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark002, TestSiz * @tc.name: ClearQueryWaterMark 003 * @tc.desc: Test metaData clear watermark busy. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark003, TestSize.Level1) @@ -1103,7 +1104,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearQueryWaterMark003, TestSiz * @tc.name: GetQueryLastTimestamp001 * @tc.desc: Test function of GetQueryLastTimestamp. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryLastTimestamp001, TestSize.Level1) @@ -1191,7 +1192,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetQueryLastTimestamp002, TestS * @tc.name: MetaDataExceptionBranch001 * @tc.desc: Test execption branch of meata data. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangshijie */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, MetaDataExceptionBranch001, TestSize.Level1) @@ -1207,7 +1208,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, MetaDataExceptionBranch001, Tes uint64_t val = 99; // 99 is the initial value of outValue uint64_t outValue = val; - meta.GetRemoveDataMark("D1", outValue); + meta.GetRemoveDataMark("D1", "", outValue); EXPECT_EQ(outValue, 0u); /** @@ -1215,21 +1216,21 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, MetaDataExceptionBranch001, Tes * @tc.expected: step2. out value = 0 */ outValue = val; - meta.GetDbCreateTime("D1", outValue); + meta.GetDbCreateTime("D1", "", outValue); EXPECT_EQ(outValue, 0u); /** * @tc.steps: step3. call ResetMetaDataAfterRemoveData with a device not in map * @tc.expected: step3. return -E_NOT_FOUND */ - EXPECT_EQ(meta.ResetMetaDataAfterRemoveData("D1"), -E_NOT_FOUND); + EXPECT_EQ(meta.ResetMetaDataAfterRemoveData("D1", ""), -E_NOT_FOUND); } /** * @tc.name: GetDeleteKeyWaterMark 001 * @tc.desc: Test metaData save and get deleteWaterMark. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteKeyWaterMark001, TestSize.Level1) @@ -1249,17 +1250,17 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteKeyWaterMark001, TestS * @tc.expected: step2. E_OK */ WaterMark w1 = 1; - EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark("D1", w1), E_OK); - EXPECT_EQ(meta.SetSendDeleteSyncWaterMark("D1", w1), E_OK); + EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark("D1", "", w1), E_OK); + EXPECT_EQ(meta.SetSendDeleteSyncWaterMark("D1", "", w1), E_OK); /** * @tc.steps: step3. get receive and send watermark * @tc.expected: step3. E_OK and get the latest value */ WaterMark w = 0; - EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", w), E_OK); + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", "", w), E_OK); EXPECT_EQ(w1, w); - EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D1", w), E_OK); + EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D1", "", w), E_OK); EXPECT_EQ(w1, w); /** @@ -1267,16 +1268,16 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteKeyWaterMark001, TestS * @tc.expected: step4. E_OK */ WaterMark w2 = 2; - EXPECT_EQ(meta.SaveLocalWaterMark("D1", w2), E_OK); - EXPECT_EQ(meta.SavePeerWaterMark("D1", w2, true), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark("D1", "", w2), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D1", "", w2, true), E_OK); /** * @tc.steps: step5. get receive and send watermark - * @tc.expected: step5. E_OK and get the w1 + * @tc.expected: step5. E_OK and get the w2 */ - EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", w), E_OK); + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", "", w), E_OK); EXPECT_EQ(w2, w); - EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D1", w), E_OK); + EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D1", "", w), E_OK); EXPECT_EQ(w2, w); /** @@ -1284,25 +1285,25 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteKeyWaterMark001, TestS * @tc.expected: step6. E_OK */ WaterMark w3 = 3; - EXPECT_EQ(meta.SaveLocalWaterMark("D2", w3), E_OK); - EXPECT_EQ(meta.SavePeerWaterMark("D2", w3, true), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark("D2", "", w3), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D2", "", w3, true), E_OK); /** * @tc.steps: step7. get receive and send watermark * @tc.expected: step7. E_OK and get the w3 */ - EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D2", w), E_OK); + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D2", "", w), E_OK); EXPECT_EQ(w3, w); - EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D2", w), E_OK); + EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D2", "", w), E_OK); EXPECT_EQ(w3, w); /** * @tc.steps: step8. get not exit receive and send watermark * @tc.expected: step8. E_OK and get the 0 */ - EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D3", w), E_OK); + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D3", "", w), E_OK); EXPECT_EQ(w, 0u); - EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D3", w), E_OK); + EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D3", "", w), E_OK); EXPECT_EQ(w, 0u); } @@ -1310,7 +1311,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteKeyWaterMark001, TestS * @tc.name: GetDeleteKeyWaterMark 002 * @tc.desc: Test metaData save and get deleteWaterMark after push or pull mode. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteKeyWaterMark002, TestSize.Level1) @@ -1330,25 +1331,25 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteKeyWaterMark002, TestS * @tc.expected: step2. E_OK */ WaterMark w1 = 3; - EXPECT_EQ(meta.SaveLocalWaterMark("D1", w1), E_OK); - EXPECT_EQ(meta.SavePeerWaterMark("D1", w1, true), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark("D1", "", w1), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D1", "", w1, true), E_OK); /** * @tc.steps: step2. save receive and send watermark * @tc.expected: step2. E_OK */ WaterMark w2 = 1; - EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark("D1", w2), E_OK); - EXPECT_EQ(meta.SetSendDeleteSyncWaterMark("D1", w2), E_OK); + EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark("D1", "", w2), E_OK); + EXPECT_EQ(meta.SetSendDeleteSyncWaterMark("D1", "", w2), E_OK); /** * @tc.steps: step3. get receive and send watermark * @tc.expected: step3. E_OK and get the bigger value */ WaterMark w = 0; - EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", w), E_OK); + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", "", w), E_OK); EXPECT_EQ(w1, w); - EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D1", w), E_OK); + EXPECT_EQ(meta.GetSendDeleteSyncWaterMark("D1", "", w), E_OK); EXPECT_EQ(w1, w); } @@ -1356,7 +1357,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, GetDeleteKeyWaterMark002, TestS * @tc.name: ClearDeleteKeyWaterMark 001 * @tc.desc: Test metaData clear watermark function. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearDeleteKeyWaterMark001, TestSize.Level1) @@ -1376,7 +1377,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearDeleteKeyWaterMark001, Tes * @tc.expected: step2. E_OK */ WaterMark w1 = 1; - EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark("D1", w1), E_OK); + EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark("D1", "", w1), E_OK); /** * @tc.steps: step3. erase peer watermark @@ -1389,7 +1390,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearDeleteKeyWaterMark001, Tes * @tc.expected: step4. E_OK receive watermark is zero */ WaterMark w2 = -1; - EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", w2), E_OK); + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", "", w2), E_OK); EXPECT_EQ(w2, 0u); /** @@ -1397,14 +1398,14 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearDeleteKeyWaterMark001, Tes * @tc.expected: step5. E_OK */ WaterMark w3 = 2; - EXPECT_EQ(meta.SavePeerWaterMark("D1", w3, true), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D1", "", w3, true), E_OK); /** * @tc.steps: step6. get receive watermark * @tc.expected: step6. E_OK receive watermark is peer watermark */ WaterMark w4 = -1; - EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", w4), E_OK); + EXPECT_EQ(meta.GetRecvDeleteSyncWaterMark("D1", "", w4), E_OK); EXPECT_EQ(w4, w3); } @@ -1412,7 +1413,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, ClearDeleteKeyWaterMark001, Tes * @tc.name: VerifyCacheAndDb 001 * @tc.desc: Test metaData watermark cache and db are consistent and correct. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDataQuerySync001, TestSize.Level1) @@ -1435,16 +1436,16 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDataQuerySync001, Tes * @tc.expected: step2. E_OK */ WaterMark deleteWaterMark = 1; - EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark(deviceId, deleteWaterMark), E_OK); - EXPECT_EQ(meta.SetSendDeleteSyncWaterMark(deviceId, deleteWaterMark), E_OK); + EXPECT_EQ(meta.SetRecvDeleteSyncWaterMark(deviceId, "", deleteWaterMark), E_OK); + EXPECT_EQ(meta.SetSendDeleteSyncWaterMark(deviceId, "", deleteWaterMark), E_OK); /** * @tc.steps: step3. save querySync watermark * @tc.expected: step2. E_OK */ WaterMark queryWaterMark = 2; - EXPECT_EQ(meta.SetRecvQueryWaterMark(queryId, deviceId, queryWaterMark), E_OK); - EXPECT_EQ(meta.SetSendQueryWaterMark(queryId, deviceId, queryWaterMark), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark(queryId, deviceId, "", queryWaterMark), E_OK); + EXPECT_EQ(meta.SetSendQueryWaterMark(queryId, deviceId, "", queryWaterMark), E_OK); /** * @tc.steps: step4. initialize meta with storage @@ -1458,18 +1459,18 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDataQuerySync001, Tes * @tc.expected: step5. E_OK and waterMark equal to deleteWaterMark */ WaterMark waterMark; - EXPECT_EQ(anotherMeta.GetRecvDeleteSyncWaterMark(deviceId, waterMark), E_OK); + EXPECT_EQ(anotherMeta.GetRecvDeleteSyncWaterMark(deviceId, "", waterMark), E_OK); EXPECT_EQ(waterMark, deleteWaterMark); - EXPECT_EQ(anotherMeta.GetSendDeleteSyncWaterMark(deviceId, waterMark), E_OK); + EXPECT_EQ(anotherMeta.GetSendDeleteSyncWaterMark(deviceId, "", waterMark), E_OK); EXPECT_EQ(waterMark, deleteWaterMark); /** * @tc.steps: step6. verify query sync data * @tc.expected: step6. E_OK and waterMark equal to queryWaterMark */ - EXPECT_EQ(anotherMeta.GetRecvQueryWaterMark(queryId, deviceId, waterMark), E_OK); + EXPECT_EQ(anotherMeta.GetRecvQueryWaterMark(queryId, deviceId, "", waterMark), E_OK); EXPECT_EQ(waterMark, queryWaterMark); - EXPECT_EQ(anotherMeta.GetSendQueryWaterMark(queryId, deviceId, waterMark), E_OK); + EXPECT_EQ(anotherMeta.GetSendQueryWaterMark(queryId, deviceId, "", waterMark), E_OK); EXPECT_EQ(waterMark, queryWaterMark); } @@ -1477,7 +1478,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDataQuerySync001, Tes * @tc.name: VerifyLruMap 001 * @tc.desc: Test metaData watermark cache lru ability. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyLruMap001, TestSize.Level1) @@ -1529,7 +1530,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyLruMap001, TestSize.Level * @tc.name: VerifyMetaDataInit 001 * @tc.desc: Test metaData init correctly * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDataInit001, TestSize.Level1) @@ -1551,12 +1552,12 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDataInit001, TestSize * @tc.steps: step2. meta save and get waterMark * @tc.expected: step2. expect get the same waterMark */ - EXPECT_EQ(meta.SaveLocalWaterMark(deviceA, setWaterMark), E_OK); - EXPECT_EQ(meta.SaveLocalWaterMark(deviceB, setWaterMark), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark(deviceA, "", setWaterMark), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark(deviceB, "", setWaterMark), E_OK); WaterMark getWaterMark = 0; - meta.GetLocalWaterMark(deviceA, getWaterMark); + meta.GetLocalWaterMark(deviceA, "", getWaterMark); EXPECT_EQ(getWaterMark, setWaterMark); - meta.GetLocalWaterMark(deviceB, getWaterMark); + meta.GetLocalWaterMark(deviceB, "", getWaterMark); EXPECT_EQ(getWaterMark, setWaterMark); @@ -1571,9 +1572,9 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDataInit001, TestSize * @tc.steps: step4. get waterMark again * @tc.expected: step4. expect get the same waterMark */ - anotherMeta.GetLocalWaterMark(deviceA, getWaterMark); + anotherMeta.GetLocalWaterMark(deviceA, "", getWaterMark); EXPECT_EQ(getWaterMark, setWaterMark); - anotherMeta.GetLocalWaterMark(deviceB, getWaterMark); + anotherMeta.GetLocalWaterMark(deviceB, "", getWaterMark); EXPECT_EQ(getWaterMark, setWaterMark); } @@ -1594,7 +1595,7 @@ void InitVerifyStorageEnvironment(Metadata &meta, VirtualSingleVerSyncDBInterfac for (uint32_t i = startCount; i < maxStoreItems; i++) { std::string queryId = std::to_string(i); WaterMark recvWaterMark = i + 1; - EXPECT_EQ(meta.SetRecvQueryWaterMark(queryId, deviceId, recvWaterMark), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark(queryId, deviceId, "", recvWaterMark), E_OK); } } } @@ -1603,7 +1604,7 @@ void InitVerifyStorageEnvironment(Metadata &meta, VirtualSingleVerSyncDBInterfac * @tc.name: VerifyManagerQuerySyncStorage 001 * @tc.desc: Test metaData remove least used querySync storage items. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage001, TestSize.Level3) @@ -1622,7 +1623,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage00 */ std::string newQueryId = std::to_string(maxStoreItems); WaterMark newWaterMark = maxStoreItems + 1; - EXPECT_EQ(meta.SetRecvQueryWaterMark(newQueryId, deviceId, newWaterMark), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark(newQueryId, deviceId, "", newWaterMark), E_OK); /** * @tc.steps: step4. touch the first item @@ -1630,7 +1631,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage00 */ std::string firstItemKey = std::to_string(startCount); WaterMark firstWaterMark = 11u; - EXPECT_EQ(meta.SetRecvQueryWaterMark(firstItemKey, deviceId, firstWaterMark), E_OK); + EXPECT_EQ(meta.SetRecvQueryWaterMark(firstItemKey, deviceId, "", firstWaterMark), E_OK); /** * @tc.steps: step5. initialize new meta with storage @@ -1644,7 +1645,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage00 * @tc.expected: step6. E_OK it still exist */ WaterMark exceptWaterMark; - EXPECT_EQ(newMeta.GetRecvQueryWaterMark(firstItemKey, deviceId, exceptWaterMark), E_OK); + EXPECT_EQ(newMeta.GetRecvQueryWaterMark(firstItemKey, deviceId, "", exceptWaterMark), E_OK); EXPECT_EQ(exceptWaterMark, firstWaterMark); /** @@ -1653,7 +1654,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage00 */ WaterMark secondWaterMark; std::string secondQueryId = std::to_string(startCount + 1); - EXPECT_EQ(newMeta.GetRecvQueryWaterMark(secondQueryId, deviceId, secondWaterMark), E_OK); + EXPECT_EQ(newMeta.GetRecvQueryWaterMark(secondQueryId, deviceId, "", secondWaterMark), E_OK); EXPECT_EQ(secondWaterMark, 0u); } @@ -1661,7 +1662,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage00 * @tc.name: VerifyMetaDbCreateTime 001 * @tc.desc: Test metaData get and set cbCreateTime. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDbCreateTime001, TestSize.Level1) @@ -1679,33 +1680,33 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDbCreateTime001, Test * @tc.expected: step4. E_OK */ WaterMark value = 2; - EXPECT_EQ(meta.SaveLocalWaterMark("D1", value), E_OK); - EXPECT_EQ(meta.SavePeerWaterMark("D1", value, true), E_OK); - EXPECT_EQ(meta.SetDbCreateTime("D1", 10u, true), E_OK); + EXPECT_EQ(meta.SaveLocalWaterMark("D1", "", value), E_OK); + EXPECT_EQ(meta.SavePeerWaterMark("D1", "", value, true), E_OK); + EXPECT_EQ(meta.SetDbCreateTime("D1", "", 10u, true), E_OK); /** * @tc.steps: step3. check peer and local watermark and dbCreateTime * @tc.expected: step4. E_OK */ WaterMark curValue = 0; - meta.GetLocalWaterMark("D1", curValue); + meta.GetLocalWaterMark("D1", "", curValue); EXPECT_EQ(value, curValue); - meta.GetPeerWaterMark("D1", curValue); + meta.GetPeerWaterMark("D1", "", curValue); EXPECT_EQ(value, curValue); uint64_t curDbCreatTime = 0; - meta.GetDbCreateTime("D1", curDbCreatTime); + meta.GetDbCreateTime("D1", "", curDbCreatTime); EXPECT_EQ(curDbCreatTime, 10u); /** * @tc.steps: step3. change dbCreateTime and check * @tc.expected: step4. E_OK */ - EXPECT_EQ(meta.SetDbCreateTime("D1", 20u, true), E_OK); + EXPECT_EQ(meta.SetDbCreateTime("D1", "", 20u, true), E_OK); uint64_t clearDeviceDataMark = INT_MAX; - meta.GetRemoveDataMark("D1", clearDeviceDataMark); + meta.GetRemoveDataMark("D1", "", clearDeviceDataMark); EXPECT_EQ(clearDeviceDataMark, 1u); - EXPECT_EQ(meta.ResetMetaDataAfterRemoveData("D1"), E_OK); - meta.GetRemoveDataMark("D1", clearDeviceDataMark); + EXPECT_EQ(meta.ResetMetaDataAfterRemoveData("D1", ""), E_OK); + meta.GetRemoveDataMark("D1", "", clearDeviceDataMark); EXPECT_EQ(clearDeviceDataMark, 0u); - meta.GetDbCreateTime("D1", curDbCreatTime); + meta.GetDbCreateTime("D1", "", curDbCreatTime); EXPECT_EQ(curDbCreatTime, 20u); } @@ -1713,7 +1714,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyMetaDbCreateTime001, Test * @tc.name: VerifyManagerQuerySyncStorage 002 * @tc.desc: Test metaData remove least used querySync storage items when exit wrong data. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage002, TestSize.Level3) @@ -1750,7 +1751,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage00 */ std::string firstItemKey = std::to_string(startCount); WaterMark exceptWaterMark; - EXPECT_EQ(newMeta.GetRecvQueryWaterMark(firstItemKey, deviceId, exceptWaterMark), E_OK); + EXPECT_EQ(newMeta.GetRecvQueryWaterMark(firstItemKey, deviceId, "", exceptWaterMark), E_OK); EXPECT_EQ(exceptWaterMark, 1u); } @@ -1758,7 +1759,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage00 * @tc.name: AllPredicateQuerySync001 * @tc.desc: Test normal push sync for AllPredicate data. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync001, TestSize.Level1) @@ -1826,7 +1827,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync001, TestS * @tc.name: AllPredicateQuerySync002 * @tc.desc: Test wrong query param push sync for AllPredicate data. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync002, TestSize.Level1) @@ -1857,7 +1858,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync002, TestS * @tc.name: AllPredicateQuerySync003 * @tc.desc: Test normal push sync for AllPredicate data with limit * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync003, TestSize.Level1) @@ -1924,7 +1925,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync003, TestS * @tc.name: AllPredicateQuerySync004 * @tc.desc: Test normal pull sync for AllPredicate data. * @tc.type: FUNC - * @tc.require: AR000FN6G9 + * @tc.require: * @tc.author: zhuwentao */ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync004, TestSize.Level1) @@ -1933,7 +1934,6 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync004, TestS * @tc.steps: step1. InitSchemaDb */ InitSchemaDb(); - DBStatus status = OK; std::vector devices; devices.push_back(g_deviceB->GetDeviceId()); @@ -1946,10 +1946,8 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync004, TestS for (int i = 0; i < dataSize; i++) { key.push_back(i); g_deviceB->PutData(key, value, 10 + i, 0); - ASSERT_TRUE(status == OK); key.pop_back(); } - ASSERT_TRUE(status == OK); /** * @tc.steps: step3. deviceA call query sync and wait @@ -1957,7 +1955,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, AllPredicateQuerySync004, TestS */ Query query = Query::Select().EqualTo("$.field_name1", 1); std::map result; - status = g_tool.SyncTest(g_schemaKvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result, query); + DBStatus status = g_tool.SyncTest(g_schemaKvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result, query); ASSERT_TRUE(status == OK); /** diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_simple_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_simple_sync_test.cpp index 929482aa..91360dae 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_simple_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_simple_sync_test.cpp @@ -795,7 +795,7 @@ HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, NormalSync010, TestSize.Level1 * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, NormalSync011, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, NormalSync011, TestSize.Level1) { DBStatus status = OK; std::vector devices; @@ -845,7 +845,7 @@ HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, NormalSync011, TestSize.Level0 * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, NormalSync012, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, NormalSync012, TestSize.Level1) { /** * @tc.steps: step1. prepare env @@ -1019,7 +1019,6 @@ HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, LimitDataSync002, TestSize.Lev ASSERT_TRUE(result.size() == devices.size()); for (const auto &pair : result) { LOGD("dev %s, status %d", pair.first.c_str(), pair.second); - printf("dev %s, status %d", pair.first.c_str(), pair.second); EXPECT_TRUE(pair.second == OK); } } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subscribe_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subscribe_sync_test.cpp index bb9b2db6..12499bdc 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subscribe_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subscribe_sync_test.cpp @@ -149,11 +149,13 @@ void DistributedDBSingleVerP2PSubscribeSyncTest::SetUp(void) ASSERT_TRUE(g_deviceB != nullptr); VirtualSingleVerSyncDBInterface *syncInterfaceB = new (std::nothrow) VirtualSingleVerSyncDBInterface(); ASSERT_TRUE(syncInterfaceB != nullptr); + syncInterfaceB->SetSchemaInfo(SCHEMA_STRING); ASSERT_EQ(g_deviceB->Initialize(g_communicatorAggregator, syncInterfaceB), E_OK); g_deviceC = new (std::nothrow) KvVirtualDevice(DEVICE_C); ASSERT_TRUE(g_deviceC != nullptr); VirtualSingleVerSyncDBInterface *syncInterfaceC = new (std::nothrow) VirtualSingleVerSyncDBInterface(); ASSERT_TRUE(syncInterfaceC != nullptr); + syncInterfaceC->SetSchemaInfo(SCHEMA_STRING); ASSERT_EQ(g_deviceC->Initialize(g_communicatorAggregator, syncInterfaceC), E_OK); } @@ -1134,6 +1136,7 @@ KvVirtualDevice *CreateKvVirtualDevice(const std::string &deviceName) device = nullptr; break; } + interface->SetSchemaInfo(SCHEMA_STRING); EXPECT_EQ(device->Initialize(g_communicatorAggregator, interface), E_OK); } while (false); return device; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp index c0c4c4a2..39f9c185 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp @@ -399,7 +399,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck005, TestSize.Lev * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck006, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck006, TestSize.Level1) { ASSERT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr), OK); ASSERT_EQ(g_mgr.DeleteKvStore(STORE_ID), OK); @@ -445,7 +445,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck006, TestSize.Lev * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck007, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck007, TestSize.Level1) { /** * @tc.steps: step1. fork check device security ability @@ -483,7 +483,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck007, TestSize.Lev * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck008, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck008, TestSize.Level1) { auto adapter = std::make_shared(); RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(adapter); @@ -928,7 +928,7 @@ void DistributedDBSingleVerP2PSyncCheckTest::CancelTestEnd(std::vector &e * @tc.require: * @tc.author: lijun */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcessCancel001, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcessCancel001, TestSize.Level1) { DeviceSyncOption option; std::vector entries; @@ -2082,7 +2082,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, DelaySync001, TestSize.Level3) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVAbilitySyncOpt001, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVAbilitySyncOpt001, TestSize.Level1) { /** * @tc.steps: step1. record packet @@ -2181,7 +2181,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt001, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt002, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt002, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -2232,7 +2232,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt002, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt003, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt003, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -2269,7 +2269,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt003, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt004, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt004, TestSize.Level1) { /** * @tc.steps: step1. deviceA call sync and wait @@ -2305,7 +2305,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt004, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt005, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt005, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -2340,7 +2340,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt005, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt006, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt006, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -2385,7 +2385,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt006, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt007, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt007, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -2406,6 +2406,8 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt007, TestSize.Level0) CipherPassword passwd; EXPECT_EQ(g_kvDelegatePtr->Export(singleExportFileName, passwd), OK); EXPECT_EQ(g_kvDelegatePtr->Import(singleExportFileName, passwd), OK); + // Wait until all the packets arrive. + std::this_thread::sleep_for(std::chrono::seconds(1)); /** * @tc.steps: step4. reopen kv store and sync again * @tc.expected: step4. reopen OK and sync success, no negotiation packet. @@ -2423,7 +2425,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt007, TestSize.Level0) * @tc.require: * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt008, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt008, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -2460,7 +2462,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt008, TestSize.Level0) * @tc.require: * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVTimeChange001, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVTimeChange001, TestSize.Level1) { /** * @tc.steps: step1. record packet which send to B @@ -2498,6 +2500,164 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVTimeChange001, TestSize.Level g_communicatorAggregator->RegOnDispatch(nullptr); } +/** + * @tc.name: KVSyncOpt009 + * @tc.desc: check resync when message return E_FEEDBACK_DB_CLOSING + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt009, TestSize.Level0) +{ + /** + * @tc.steps: step1. ack message return E_FEEDBACK_DB_CLOSING once + */ + std::atomic messageCount = 0; + bool isResync = false; + g_communicatorAggregator->RegOnDispatch([&isResync, &messageCount](const std::string &dev, Message *msg) { + if (dev != DEVICE_B && msg->GetMessageType() == TYPE_RESPONSE && !isResync) { + msg->SetErrorNo(E_FEEDBACK_DB_CLOSING); + isResync = true; + } + messageCount++; + }); + /** + * @tc.steps: step2. deviceA call sync and wait + * @tc.expected: step2. sync should return OK. + */ + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + Sync(devices, OK); + int pkCnt = 8; + EXPECT_EQ(messageCount, pkCnt); + EXPECT_TRUE(isResync); + g_communicatorAggregator->RegOnDispatch(nullptr); +} + +/** + * @tc.name: KVSyncOpt010 + * @tc.desc: check resync limit exceeded + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt010, TestSize.Level0) +{ + /** + * @tc.steps: step1. ack message always return E_FEEDBACK_DB_CLOSING + */ + std::atomic messageCount = 0; + g_communicatorAggregator->RegOnDispatch([&messageCount](const std::string &dev, Message *msg) { + if (dev != DEVICE_B && msg->GetMessageType() == TYPE_RESPONSE) { + msg->SetErrorNo(E_FEEDBACK_DB_CLOSING); + } + messageCount++; + }); + /** + * @tc.steps: step2. deviceA call sync and wait + * @tc.expected: step2. sync should ignore E_FEEDBACK_DB_CLOSING when exceeded resync limit + */ + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + Sync(devices, OK); + int pkCnt = 8; + EXPECT_EQ(messageCount, pkCnt); + g_communicatorAggregator->RegOnDispatch(nullptr); +} + +/** + * @tc.name: KVSyncOpt011 + * @tc.desc: check close db return busy + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt011, TestSize.Level2) +{ + /** + * @tc.steps: step1. deviceA call sync and wait on RegOnDispatch + * @tc.expected: step1. sync should return OK. + */ + std::atomic messageCount = 0; + std::atomic signo = 0; + std::mutex mutex; + std::condition_variable cv; + int waitTime = 2; + g_communicatorAggregator->RegOnDispatch([&messageCount, &signo, &mutex, &cv, waitTime]( + const std::string &dev, Message *msg) { + messageCount++; + if (messageCount.load() == 1) { // 1 is onDispatch times + std::unique_lock lock(mutex); + signo++; + cv.notify_one(); + cv.wait_for(lock, std::chrono::seconds(waitTime), [&signo]() { + return signo == 2; // 2 is notify times + }); + } + }); + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + std::thread t1([&devices]() { + Sync(devices, OK); + }); + + /** + * @tc.steps: step2. close db + * @tc.expected: step2. return BUSY. + */ + { + std::unique_lock lock(mutex); + cv.wait_for(lock, std::chrono::seconds(waitTime), [&signo]() { + return signo == 1; // 1 is notify times + }); + } + EXPECT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr, false), BUSY); + { + std::unique_lock lock(mutex); + signo++; + cv.notify_one(); + } + t1.join(); + /** + * @tc.steps: step3. wait task count to 0, close db + * @tc.expected: step3. return OK. + */ + std::this_thread::sleep_for(std::chrono::seconds(waitTime)); + g_communicatorAggregator->RegOnDispatch(nullptr); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr, false), OK); + g_kvDelegatePtr = nullptr; + ASSERT_TRUE(g_mgr.DeleteKvStore(STORE_ID) == OK); +} + +/** + * @tc.name: KVSyncOpt012 + * @tc.desc: check message errcode always E_FEEDBACK_DB_CLOSING + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt012, TestSize.Level0) +{ + /** + * @tc.steps: step1. message always return E_FEEDBACK_DB_CLOSING + */ + std::atomic messageCount = 0; + g_communicatorAggregator->RegOnDispatch([&messageCount](const std::string &dev, Message *msg) { + msg->SetErrorNo(E_FEEDBACK_DB_CLOSING); + messageCount++; + }); + /** + * @tc.steps: step2. deviceA call sync and wait + * @tc.expected: step2. sync should ignore E_FEEDBACK_DB_CLOSING when exceeded resync limit + */ + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + Sync(devices, OK); + int pkCnt = 8; + EXPECT_EQ(messageCount, pkCnt); + g_communicatorAggregator->RegOnDispatch(nullptr); +} + /** * @tc.name: KVTimeChange002 * @tc.desc: test NotifyTimestampChanged will not stuck when notify delegate with no metadata @@ -2505,7 +2665,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVTimeChange001, TestSize.Level * @tc.require: * @tc.author: liuhongyang */ -HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVTimeChange002, TestSize.Level0) +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVTimeChange002, TestSize.Level1) { /** * @tc.steps: step1. open a new store with STORE_ID_3 diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_syncer_device_manager_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_syncer_device_manager_test.cpp index 5b76ae62..f50e74d6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_syncer_device_manager_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_syncer_device_manager_test.cpp @@ -122,7 +122,7 @@ void DistributedDBSyncerDeviceManagerTest::TearDown(void) * @tc.name: Online Callback 001 * @tc.desc: Test DeviceManager device online callback function. * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSyncerDeviceManagerTest, OnlineCallback001, TestSize.Level0) @@ -152,7 +152,7 @@ HWTEST_F(DistributedDBSyncerDeviceManagerTest, OnlineCallback001, TestSize.Level * @tc.name: Offline Callback 001 * @tc.desc: Test DeviceManager device offline callback function. * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSyncerDeviceManagerTest, OfflineCallback001, TestSize.Level0) @@ -182,7 +182,7 @@ HWTEST_F(DistributedDBSyncerDeviceManagerTest, OfflineCallback001, TestSize.Leve * @tc.name: Get Devices 001 * @tc.desc: Test DeviceManager GetDevices function. * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSyncerDeviceManagerTest, GetDevices001, TestSize.Level0) @@ -213,7 +213,7 @@ HWTEST_F(DistributedDBSyncerDeviceManagerTest, GetDevices001, TestSize.Level0) * @tc.name: Send BroadCast 001 * @tc.desc: Test DeviceManager SendBroadCast function. * @tc.type: FUNC - * @tc.require: AR000CKRTD AR000CQE0E + * @tc.require: * @tc.author: xushaohua */ HWTEST_F(DistributedDBSyncerDeviceManagerTest, SendBroadCast001, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_time_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_time_sync_test.cpp index 245e1074..239af306 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_time_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_time_sync_test.cpp @@ -130,7 +130,7 @@ void DistributedDBTimeSyncTest::TearDown(void) * @tc.name: NormalSync001 * @tc.desc: Verify time sync function is normal between two time sync instance with different timestamp. * @tc.type: FUNC - * @tc.require: AR000C05EP AR000CQE0G + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBTimeSyncTest, NormalSync001, TestSize.Level0) @@ -148,7 +148,7 @@ HWTEST_F(DistributedDBTimeSyncTest, NormalSync001, TestSize.Level0) TimeHelper::GetSysCurrentTime() + TimeHelper::BASE_OFFSET + offsetA, 0); int errCode; // initialize timeSyncA - errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_TRUE(errCode == E_OK); g_metadataB->Initialize(g_syncInterfaceB); @@ -157,13 +157,13 @@ HWTEST_F(DistributedDBTimeSyncTest, NormalSync001, TestSize.Level0) g_syncInterfaceB->PutData(DistributedDBUnitTest::KEY_1, DistributedDBUnitTest::VALUE_1, TimeHelper::GetSysCurrentTime() + TimeHelper::BASE_OFFSET + offsetB, 0); // initialize timeSyncB - errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A); + errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A, ""); EXPECT_TRUE(errCode == E_OK); /** * @tc.steps: step3. Register the OnMessageCallback to virtual communicator */ - g_syncTaskContext->Initialize(DEVICE_B, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); + g_syncTaskContext->Initialize({DEVICE_B, ""}, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); g_virtualCommunicator->SetTimeSync(g_timeSyncA.get(), g_timeSyncB.get(), DEVICE_A, g_syncTaskContext); /** @@ -181,7 +181,7 @@ HWTEST_F(DistributedDBTimeSyncTest, NormalSync001, TestSize.Level0) * @tc.name: NormalSync002 * @tc.desc: Verify time sync function is normal between two time sync instance with the same timestamp. * @tc.type: FUNC - * @tc.require: AR000C05EP AR000CQE0G + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBTimeSyncTest, NormalSync002, TestSize.Level0) @@ -193,17 +193,17 @@ HWTEST_F(DistributedDBTimeSyncTest, NormalSync002, TestSize.Level0) g_metadataA->Initialize(g_syncInterfaceA); int errCode; // initialize timeSyncA - errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_TRUE(errCode == E_OK); g_metadataB->Initialize(g_syncInterfaceB); // initialize timeSyncB - errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A); + errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A, ""); EXPECT_TRUE(errCode == E_OK); /** * @tc.steps: step2. Register the OnMessageCallback to virtual communicator */ - g_syncTaskContext->Initialize(DEVICE_B, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); + g_syncTaskContext->Initialize({DEVICE_B, ""}, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); g_virtualCommunicator->SetTimeSync(g_timeSyncA.get(), g_timeSyncB.get(), DEVICE_A, g_syncTaskContext); /** * @tc.steps: step3. Fetch timeOffset value @@ -220,7 +220,7 @@ HWTEST_F(DistributedDBTimeSyncTest, NormalSync002, TestSize.Level0) * @tc.name: NormalSync003 * @tc.desc: Verify time sync function is normal between two time sync instance with different localTimeOffset. * @tc.type: FUNC - * @tc.require: AR000C05EP AR000CQE0G + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBTimeSyncTest, NormalSync003, TestSize.Level0) @@ -239,7 +239,7 @@ HWTEST_F(DistributedDBTimeSyncTest, NormalSync003, TestSize.Level0) int errCode; // initialize timeSyncA - errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_TRUE(errCode == E_OK); // set timeOffset for timeSyncA @@ -248,12 +248,12 @@ HWTEST_F(DistributedDBTimeSyncTest, NormalSync003, TestSize.Level0) g_metadataB->SaveLocalTimeOffset(offsetB); // initialize timeSyncB - errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A); + errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A, ""); EXPECT_TRUE(errCode == E_OK); /** * @tc.steps: step3. Register the OnMessageCallback to virtual communicator */ - g_syncTaskContext->Initialize(DEVICE_B, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); + g_syncTaskContext->Initialize({DEVICE_B, ""}, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); g_virtualCommunicator->SetTimeSync(g_timeSyncA.get(), g_timeSyncB.get(), DEVICE_A, g_syncTaskContext); /** * @tc.steps: step4. Fetch timeOffset value @@ -270,7 +270,7 @@ HWTEST_F(DistributedDBTimeSyncTest, NormalSync003, TestSize.Level0) * @tc.name: NetDisconnetSyncTest001 * @tc.desc: Verify time sync function return failed when the virtual communicator disabled. * @tc.type: FUNC - * @tc.require: AR000C05EP AR000CQE0G + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBTimeSyncTest, NetDisconnetSyncTest001, TestSize.Level0) @@ -282,15 +282,15 @@ HWTEST_F(DistributedDBTimeSyncTest, NetDisconnetSyncTest001, TestSize.Level0) g_metadataA->Initialize(g_syncInterfaceA); int errCode; // initialize timeSyncA - errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_TRUE(errCode == E_OK); g_metadataB->Initialize(g_syncInterfaceB); // initialize timeSyncB - errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A); + errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A, ""); EXPECT_TRUE(errCode == E_OK); - g_syncTaskContext->Initialize(DEVICE_B, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); + g_syncTaskContext->Initialize({DEVICE_B, ""}, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); g_virtualCommunicator->SetTimeSync(g_timeSyncA.get(), g_timeSyncB.get(), DEVICE_A, g_syncTaskContext); /** * @tc.steps: step2. Disable the virtual communicator @@ -308,7 +308,7 @@ HWTEST_F(DistributedDBTimeSyncTest, NetDisconnetSyncTest001, TestSize.Level0) * @tc.name: InvalidMessgeTest001 * @tc.desc: Verify RequestReceive() return failed with invalid input. * @tc.type: FUNC - * @tc.require: AR000C05EP AR000CQE0G + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBTimeSyncTest, InvalidMessgeTest001, TestSize.Level0) @@ -320,12 +320,12 @@ HWTEST_F(DistributedDBTimeSyncTest, InvalidMessgeTest001, TestSize.Level0) g_metadataA->Initialize(g_syncInterfaceA); int errCode; // initialize timeSyncA - errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_TRUE(errCode == E_OK); g_metadataB->Initialize(g_syncInterfaceB); // initialize timeSyncB - errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A); + errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A, ""); EXPECT_TRUE(errCode == E_OK); g_virtualCommunicator->SetTimeSync(g_timeSyncA.get(), g_timeSyncB.get(), DEVICE_A, g_syncTaskContext); @@ -339,7 +339,7 @@ HWTEST_F(DistributedDBTimeSyncTest, InvalidMessgeTest001, TestSize.Level0) */ msg->SetMessageId(TIME_SYNC_MESSAGE); msg->SetMessageType(TYPE_REQUEST); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; errCode = g_virtualCommunicator->SendMessage(DEVICE_B, msg, conf); EXPECT_TRUE(errCode == -E_INVALID_ARGS); @@ -376,7 +376,7 @@ HWTEST_F(DistributedDBTimeSyncTest, InvalidMessgeTest001, TestSize.Level0) * @tc.name: InvalidMessgeTest002 * @tc.desc: Verify AckRec() return failed with invalid input. * @tc.type: FUNC - * @tc.require: AR000C05EP AR000CQE0G + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBTimeSyncTest, InvalidMessgeTest002, TestSize.Level0) @@ -388,14 +388,14 @@ HWTEST_F(DistributedDBTimeSyncTest, InvalidMessgeTest002, TestSize.Level0) g_metadataA->Initialize(g_syncInterfaceA); int errCode; // initialize timeSyncA - errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_TRUE(errCode == E_OK); g_metadataB->Initialize(g_syncInterfaceB); // initialize timeSyncB - errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A); + errCode = g_timeSyncB->Initialize(g_virtualCommunicator, g_metadataB, g_syncInterfaceB, DEVICE_A, ""); EXPECT_TRUE(errCode == E_OK); - g_syncTaskContext->Initialize(DEVICE_B, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); + g_syncTaskContext->Initialize({DEVICE_B, ""}, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); g_virtualCommunicator->SetTimeSync(g_timeSyncA.get(), g_timeSyncB.get(), DEVICE_A, g_syncTaskContext); Message *msg = new (std::nothrow) Message(); @@ -407,7 +407,7 @@ HWTEST_F(DistributedDBTimeSyncTest, InvalidMessgeTest002, TestSize.Level0) */ msg->SetMessageId(TIME_SYNC_MESSAGE); msg->SetMessageType(TYPE_RESPONSE); - SendConfig conf = {false, false, 0}; + SendConfig conf = {false, false, true, 0}; errCode = g_virtualCommunicator->SendMessage(DEVICE_A, msg, conf); EXPECT_TRUE(errCode == -E_INVALID_ARGS); @@ -444,7 +444,7 @@ HWTEST_F(DistributedDBTimeSyncTest, InvalidMessgeTest002, TestSize.Level0) * @tc.name: SyncTimeout001 * @tc.desc: Verify the timeout scenario for time sync. * @tc.type: FUNC - * @tc.require: AR000C05EP AR000CQE0G + * @tc.require: * @tc.author: wumin */ HWTEST_F(DistributedDBTimeSyncTest, SyncTimeout001, TestSize.Level2) @@ -452,14 +452,14 @@ HWTEST_F(DistributedDBTimeSyncTest, SyncTimeout001, TestSize.Level2) // initialize timeSyncA g_metadataA->Initialize(g_syncInterfaceA); int errCode; - errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_TRUE(errCode == E_OK); /** * @tc.steps: step1. Initialize the syncTaskContext * @tc.expected: step1. Initialize syncTaskContext successfully */ - errCode = g_syncTaskContext->Initialize(DEVICE_B, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); + errCode = g_syncTaskContext->Initialize({DEVICE_B, ""}, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); EXPECT_TRUE(errCode == E_OK); /** * @tc.steps: step2. Start the time syc task invoking StartSync() method @@ -481,14 +481,14 @@ HWTEST_F(DistributedDBTimeSyncTest, CheckRemoteVersion001, TestSize.Level0) { // initialize timeSyncA g_metadataA->Initialize(g_syncInterfaceA); - int errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + int errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_EQ(errCode, E_OK); /** * @tc.steps: step1. Initialize the syncTaskContext * @tc.expected: step1. Initialize syncTaskContext successfully */ - errCode = g_syncTaskContext->Initialize(DEVICE_B, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); + errCode = g_syncTaskContext->Initialize({DEVICE_B, ""}, g_syncInterfaceA, g_metadataA, g_virtualCommunicator); EXPECT_EQ(errCode, E_OK); /** * @tc.steps: step2. Check remote version @@ -512,18 +512,18 @@ HWTEST_F(DistributedDBTimeSyncTest, SetTimeSyncFinish001, TestSize.Level0) * @tc.expected: step1. Initialize successfully */ EXPECT_EQ(g_metadataA->Initialize(g_syncInterfaceA), E_OK); - EXPECT_EQ(g_metadataA->SetTimeSyncFinishMark(DEVICE_B, true), E_OK); - int errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + EXPECT_EQ(g_metadataA->SetTimeSyncFinishMark(DEVICE_B, "", true), E_OK); + int errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B, ""); EXPECT_EQ(errCode, E_OK); /** * @tc.steps: step2. Set time sync finish * @tc.expected: step2. meta is not finish because time sync cache is finish */ - EXPECT_EQ(g_metadataA->SetTimeSyncFinishMark(DEVICE_B, false), E_OK); + EXPECT_EQ(g_metadataA->SetTimeSyncFinishMark(DEVICE_B, "", false), E_OK); DeviceTimeInfo info; RuntimeContext::GetInstance()->SetDeviceTimeInfo(DEVICE_B, info); g_timeSyncA->SetTimeSyncFinishIfNeed(); - EXPECT_FALSE(g_metadataA->IsTimeSyncFinish(DEVICE_B)); + EXPECT_FALSE(g_metadataA->IsTimeSyncFinish(DEVICE_B, "")); RuntimeContext::GetInstance()->ClearAllDeviceTimeInfo(); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.cpp index b68cae6e..fc2806f7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.cpp @@ -27,6 +27,7 @@ GenericVirtualDevice::GenericVirtualDevice(std::string deviceId) metadata_(nullptr), deviceId_(std::move(deviceId)), remoteDeviceId_("real_device"), + targetUserId_("targetUser"), context_(nullptr), onRemoteDataChanged_(nullptr), subManager_(nullptr), @@ -110,7 +111,7 @@ int GenericVirtualDevice::Initialize(VirtualCommunicatorAggregator *comAggregato } communicateHandle_->RegOnMessageCallback( std::bind(&GenericVirtualDevice::MessageCallback, this, std::placeholders::_1, std::placeholders::_2), []() {}); - context_->Initialize(remoteDeviceId_, storage_, metadata_, communicateHandle_); + context_->Initialize({remoteDeviceId_, targetUserId_}, storage_, metadata_, communicateHandle_); context_->SetRetryStatus(SyncTaskContext::NO_NEED_RETRY); context_->RegOnSyncTask(std::bind(&GenericVirtualDevice::StartResponseTask, this)); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.h index 462dd694..62dd5989 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.h @@ -56,6 +56,7 @@ protected: std::shared_ptr metadata_; std::string deviceId_; std::string remoteDeviceId_; + std::string targetUserId_; SyncTaskContext *context_; std::function onRemoteDataChanged_; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/kv_virtual_device.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/kv_virtual_device.cpp index c2b58e7b..1d6c4320 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/kv_virtual_device.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/kv_virtual_device.cpp @@ -151,4 +151,10 @@ void KvVirtualDevice::SetPushNotifier(const std::function(storage_); syncAble->SetPushNotifier(pushNotifier); } + +void KvVirtualDevice::SetSchema(const std::string &schema) +{ + auto *syncAble = static_cast(storage_); + syncAble->SetSchemaInfo(schema); +} } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/kv_virtual_device.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/kv_virtual_device.h index 80e266c4..8f7f392a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/kv_virtual_device.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/kv_virtual_device.h @@ -45,6 +45,8 @@ public: void EraseWaterMark(const std::string &dev); void SetPushNotifier(const std::function &pushNotifier); + + void SetSchema(const std::string &schema); }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_communicator.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_communicator.h index d0340cf8..54204f3e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_communicator.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_communicator.h @@ -35,6 +35,8 @@ public: MOCK_METHOD2(RegOnMessageCallback, int(const OnMessageCallback &, const Finalizer &)); MOCK_METHOD1(Activate, void(const std::string &)); MOCK_CONST_METHOD1(IsDeviceOnline, bool(const std::string &)); + MOCK_CONST_METHOD1(GetTargetUserId, std::string(const ExtendInfo &)); + MOCK_METHOD1(ExchangeClosePending, bool(bool)); }; } // namespace DistributedDB #endif // #define MOCK_COMMUNICATOR_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_meta_data.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_meta_data.h index b9a29d0d..10605c1c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_meta_data.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_meta_data.h @@ -21,11 +21,11 @@ namespace DistributedDB { class MockMetadata : public Metadata { public: - MOCK_METHOD3(SetLastQueryTime, int(const std::string &, const std::string &, const Timestamp &)); + MOCK_METHOD4(SetLastQueryTime, int(const std::string &, const std::string &, const std::string &, const Timestamp &)); - MOCK_METHOD3(GetLastQueryTime, int(const std::string &, const std::string &, Timestamp &)); + MOCK_METHOD4(GetLastQueryTime, int(const std::string &, const std::string &, const std::string &, Timestamp &)); - MOCK_METHOD2(GetLocalWaterMark, void(const DeviceID &, uint64_t &)); + MOCK_METHOD3(GetLocalWaterMark, void(const DeviceID &, const DeviceID &, uint64_t &)); }; } // namespace DistributedDB #endif // #define MOCK_META_DATA_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_data_sync.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_data_sync.h index c8d28c51..dc3e0d2f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_data_sync.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_data_sync.h @@ -53,6 +53,12 @@ public: } MOCK_METHOD1(RemoveDeviceDataIfNeed, int(SingleVerSyncTaskContext *)); + + int CallDealRemoveDeviceDataByAck( + SingleVerSyncTaskContext *context, WaterMark ackWaterMark, const std::vector &reserved) + { + return SingleVerDataSync::DealRemoveDeviceDataByAck(context, ackWaterMark, reserved); + } }; } // namespace DistributedDB #endif // #define MOCK_SINGLE_VER_DATA_SYNC_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_state_machine.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_state_machine.h index 1509eb63..3687d29f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_state_machine.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_state_machine.h @@ -87,6 +87,16 @@ public: return saveDataNotifyRefCount_; } + void CallSyncStepInner() + { + SingleVerSyncStateMachine::SyncStepInner(); + } + + void CallSetCurStateErrStatus() + { + SingleVerSyncStateMachine::SetCurStateErrStatus(); + } + MOCK_METHOD1(SwitchStateAndStep, void(uint8_t)); MOCK_METHOD0(PrepareNextSyncTask, int(void)); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_sync_engine.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_sync_engine.h index 1545ea63..86ae48f4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_sync_engine.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_sync_engine.h @@ -29,9 +29,14 @@ public: subManager_ = std::make_shared(); } - ISyncTaskContext *CallGetSyncTaskContext(const std::string &deviceId, int &errCode) + ISyncTaskContext *CallGetSyncTaskContext(const DeviceSyncTarget &target, int &errCode) { - return SyncEngine::GetSyncTaskContext(deviceId, errCode); + return SyncEngine::GetSyncTaskContext(target, errCode); + } + + ISyncTaskContext *CallFindSyncTaskContext(const DeviceSyncTarget &target) + { + return SyncEngine::FindSyncTaskContext(target); } }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_time_sync.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_time_sync.h index 43e89b65..d2b9b350 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_time_sync.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_time_sync.h @@ -48,7 +48,7 @@ public: return TimeSync::CalculateTimeOffset(timeSyncInfo); } - MOCK_METHOD2(SyncStart, int(const CommErrHandler &, uint32_t)); + MOCK_METHOD3(SyncStart, int(const CommErrHandler &, uint32_t, bool)); }; } #endif // MOCK_TIME_SYNC_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.cpp index 9d6df07d..8544372f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.cpp @@ -209,7 +209,7 @@ VirtualCommunicator::~VirtualCommunicator() VirtualCommunicator::VirtualCommunicator(const std::string &deviceId, VirtualCommunicatorAggregator *communicatorAggregator) - : deviceId_(deviceId), communicatorAggregator_(communicatorAggregator) + : deviceId_(deviceId), communicatorAggregator_(communicatorAggregator), targetUserId_(DBConstant::DEFAULT_USER) { } @@ -221,7 +221,7 @@ int VirtualCommunicator::TranslateMsg(const Message *inMsg, Message *&outMsg) if (errCode != E_OK) { return errCode; } - + sendMsgSize_ += buffer->GetSize(); outMsg = ProtocolProto::ToMessage(buffer, errCode); delete buffer; buffer = nullptr; @@ -236,4 +236,24 @@ void VirtualCommunicator::SetDropMessageTypeByDevice(MessageId msgid, uint32_t d dropMsgTimes_ = 0; } } + +std::string VirtualCommunicator::GetTargetUserId(const ExtendInfo ¶mInfo) const +{ + return targetUserId_; +} + +void VirtualCommunicator::SetTargetUserId(const std::string &userId) +{ + targetUserId_ = userId; +} + +uint64_t VirtualCommunicator::GetSendMsgSize() const +{ + return sendMsgSize_; +} + +bool VirtualCommunicator::ExchangeClosePending(bool expected) +{ + return false; +} } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.h index f904df09..56ea144a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.h @@ -83,11 +83,15 @@ public: void SetRemoteVersion(uint16_t remoteVersion); + std::string GetTargetUserId(const ExtendInfo ¶mInfo) const override; + + void SetTargetUserId(const std::string &userId); + + uint64_t GetSendMsgSize() const; + + bool ExchangeClosePending(bool expected) override; private: - int TimeSync(); - int DataSync(); - int WaterMarkSync(); - static int TranslateMsg(const Message *inMsg, Message *&outMsg); + int TranslateMsg(const Message *inMsg, Message *&outMsg); mutable std::mutex onMessageLock_; OnMessageCallback onMessage_; @@ -112,6 +116,9 @@ private: uint32_t mtuSize_ = 5 * 1024 * 1024; // 5 * 1024 * 1024B uint16_t remoteVersion_ = UINT16_MAX; + + std::string targetUserId_; + std::atomic sendMsgSize_ = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.cpp index ddc3d9c5..7715083e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.cpp @@ -211,6 +211,7 @@ void VirtualCommunicatorAggregator::DispatchMessageInner(const std::string &srcT uint32_t messageId = inMsg->GetMessageId(); Message *msg = const_cast(inMsg); msg->SetTarget(srcTarget); + msg->SetSenderUserId(communicator->GetTargetUserId({})); RefObject::IncObjRef(communicator); auto onDispatch = onDispatch_; bool isNeedDelay = ((sendDelayTime_ > 0) && (delayTimes_ > 0) && (messageId == delayMessageId_) && @@ -416,4 +417,14 @@ void VirtualCommunicatorAggregator::SetRemoteDeviceId(const std::string &dev) remoteDeviceId_ = dev; LOGI("[VirtualCommunicatorAggregator] Set dev %s", dev.c_str()); } + +uint64_t VirtualCommunicatorAggregator::GetAllSendMsgSize() const +{ + uint64_t size = 0; + std::lock_guard lock(communicatorsLock_); + for (const auto &communicator : communicators_) { + size += communicator.second->GetSendMsgSize(); + } + return size; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.h index b92e4884..10e26d45 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.h @@ -107,6 +107,8 @@ public: void SetRemoteDeviceId(const std::string &dev); + uint64_t GetAllSendMsgSize() const; + ~VirtualCommunicatorAggregator() override = default; VirtualCommunicatorAggregator() = default; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp index d2fea14c..8c5d8f1e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp @@ -225,6 +225,19 @@ int VirtualRelationalVerSyncDBInterface::GetMetaData(const Key &key, Value &valu return -E_NOT_FOUND; } +int VirtualRelationalVerSyncDBInterface::GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const +{ + for (const auto &metadata : metadata_) { + if (metadata.first.size() < keyPrefix.size()) { + continue; + } + if (std::equal(keyPrefix.begin(), keyPrefix.end(), metadata.first.begin())) { + data[metadata.first] = metadata.second; + } + } + return data.empty() ? -E_NOT_FOUND : E_OK; +} + int VirtualRelationalVerSyncDBInterface::PutMetaData(const Key &key, const Value &value, bool isInTransaction) { (void)isInTransaction; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.h index d1ea9561..6eab384b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.h @@ -73,6 +73,8 @@ public: int GetMetaData(const Key &key, Value &value) const override; + int GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const override; + int PutMetaData(const Key &key, const Value &value, bool isInTransaction) override; int DeleteMetaData(const std::vector &keys) override; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp index 8ca7d89a..0266fece 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp @@ -102,6 +102,22 @@ int VirtualSingleVerSyncDBInterface::GetMetaData(const Key &key, Value &value) c return -E_NOT_FOUND; } +int VirtualSingleVerSyncDBInterface::GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const +{ + if (readBusy_) { + return -E_BUSY; + } + for (const auto &metadata : metadata_) { + if (metadata.first.size() < keyPrefix.size()) { + continue; + } + if (std::equal(keyPrefix.begin(), keyPrefix.end(), metadata.first.begin())) { + data[metadata.first] = metadata.second; + } + } + return data.empty() ? -E_NOT_FOUND : E_OK; +} + int VirtualSingleVerSyncDBInterface::PutMetaData(const Key &key, const Value &value, bool isInTransaction) { (void)isInTransaction; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h index 20927700..0efa8628 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h @@ -54,6 +54,8 @@ public: int GetMetaData(const Key& key, Value& value) const override; + int GetMetaDataByPrefixKey(const Key &keyPrefix, std::map &data) const override; + int PutMetaData(const Key& key, const Value& value, bool isInTransaction) override; int DeleteMetaData(const std::vector &keys) override; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_time_sync_communicator.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_time_sync_communicator.cpp index 6890e94b..2890d210 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_time_sync_communicator.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_time_sync_communicator.cpp @@ -151,4 +151,14 @@ void VirtualTimeSyncCommunicator::SetRemoteVersion(uint16_t remoteVersion) { version_ = remoteVersion; } + +std::string VirtualTimeSyncCommunicator::GetTargetUserId(const ExtendInfo ¶mInfo) const +{ + return ""; +} + +bool VirtualTimeSyncCommunicator::ExchangeClosePending(bool expected) +{ + return false; +} } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_time_sync_communicator.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_time_sync_communicator.h index 0478c24c..57672ae9 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_time_sync_communicator.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_time_sync_communicator.h @@ -72,6 +72,9 @@ public: void SetRemoteVersion(uint16_t remoteVersion); + std::string GetTargetUserId(const ExtendInfo ¶mInfo) const override; + + bool ExchangeClosePending(bool expected) override; private: TimeSync *srcTimeSync_; TimeSync *dstTimeSync_; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/tokenizer/sqlite_adapter_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/tokenizer/sqlite_adapter_test.cpp new file mode 100644 index 00000000..ea5dbd4a --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/tokenizer/sqlite_adapter_test.cpp @@ -0,0 +1,349 @@ +/* + * 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 "log_print.h" +#ifndef USE_SQLITE_SYMBOLS +#include "sqlite3.h" +#else +#include "sqlite3sym.h" +#endif + +using namespace std; +using namespace testing::ext; +using namespace DistributedDB; + +class SqliteAdapterTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void SqliteAdapterTest::SetUpTestCase(void) +{} + +void SqliteAdapterTest::TearDownTestCase(void) +{} + +void SqliteAdapterTest::SetUp() +{} + +void SqliteAdapterTest::TearDown() +{} + +using Clock = std::chrono::system_clock; + +static bool g_needSkip = false; + +static void HandleRc(sqlite3 *db, int rc) +{ + if (rc != SQLITE_OK) { + LOGE("Failed!!!!!!!!!! rc: %d", rc); + g_needSkip = true; + } +} +static sqlite3 *g_sqliteDb = nullptr; +static char *g_errMsg = nullptr; + +static int Callback(void *data, int argc, char **argv, char **colName) +{ + for (int i = 0; i < argc; i++) { + LOGD("%s = %s\n", colName[i], argv[i] ? argv[i] : "nullptr"); + } + return 0; // 返回 0 表示继续执行查询 +} + +static int QueryCallback(void *data, int argc, char **argv, char **colName) +{ + if (argc != 1) { + return 0; + } + auto expectCount = reinterpret_cast(data); + int base = 10; + EXPECT_EQ(expectCount, strtol(argv[0], nullptr, base)); + return 0; +} + +static void SQLTest(const char *sql) +{ + if (g_needSkip) { + // 蓝区没有so导致失败,直接跳过测试 + return; + } + int errCode = sqlite3_exec(g_sqliteDb, sql, Callback, nullptr, &g_errMsg); + if (errCode != SQLITE_OK) { + if (g_errMsg != nullptr) { + LOGE("SQL error: %s\n", g_errMsg); + sqlite3_free(g_errMsg); + g_errMsg = nullptr; + ASSERT_TRUE(false); + } + } +} + +static int g_rank = 0; +static const char *g_dbPath = "test.db"; + +/** + * @tc.name: SqliteAdapterTest001 + * @tc.desc: Get blob size over limit + * @tc.type: FUNC + * @tc.require: + * @tc.author: wanghaishuo + */ +HWTEST_F(SqliteAdapterTest, SqliteAdapterTest001, TestSize.Level0) +{ + // Save any error messages + char *zErrMsg = nullptr; + + // Save the connection result + int rc = sqlite3_open_v2(g_dbPath, &g_sqliteDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); + HandleRc(g_sqliteDb, rc); + + auto before = Clock::now(); + + rc = sqlite3_db_config(g_sqliteDb, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, nullptr); + HandleRc(g_sqliteDb, rc); + + rc = sqlite3_load_extension(g_sqliteDb, "libcustomtokenizer.z.so", nullptr, nullptr); + HandleRc(g_sqliteDb, rc); + + // create fts table + string sql = "CREATE VIRTUAL TABLE example USING fts5(name, content, tokenize = 'customtokenizer')"; + rc = sqlite3_exec(g_sqliteDb, sql.c_str(), Callback, 0, &zErrMsg); + HandleRc(g_sqliteDb, rc); + + const char *SQLINSERT1 = + "INSERT INTO example(name, content) VALUES('文档1', '这是一个测试文档,用于测试中文文本的分词和索引。');"; + SQLTest(SQLINSERT1); + const char *SQLINSERT2 = + "INSERT INTO example(name, content) VALUES('文档2', '我们将使用这个示例来演示如何在SQLite中进行全文搜索。');"; + SQLTest(SQLINSERT2); + const char *SQLINSERT3 = + "INSERT INTO example(name, content) VALUES('文档3', 'ICU分词器能够很好地处理中文文本的分词和分析。');"; + SQLTest(SQLINSERT3); + const char *SQLINSERT4 = "INSERT INTO example(name, content) VALUES('uksdhf', '');"; + SQLTest(SQLINSERT4); + const char *SQLINSERT5 = "INSERT INTO example(name, content) VALUES('', '');"; + SQLTest(SQLINSERT5); + const char *SQLQUERY1 = "SELECT * FROM example WHERE example MATCH '分* OR SQLite';"; + SQLTest(SQLQUERY1); + + const char *SQLQUERY2 = "SELECT * FROM example WHERE example MATCH '分词' ORDER BY rank;"; + SQLTest(SQLQUERY2); + + const char *SQLQUERY3 = "SELECT * FROM example WHERE name MATCH 'uksdhf';"; + SQLTest(SQLQUERY3); + + const char *SQLDROP = "DROP TABLE IF EXISTS example;"; + SQLTest(SQLDROP); + + // Close the connection + sqlite3_close(g_sqliteDb); +} + +/** + * @tc.name: SqliteAdapterTest002 + * @tc.desc: Test cut for short words + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(SqliteAdapterTest, SqliteAdapterTest002, TestSize.Level0) +{ + /** + * @tc.steps: step1. prepare db + * @tc.expected: step1. OK. + */ + // Save any error messages + char *zErrMsg = nullptr; + + // Save the connection result + int rc = sqlite3_open_v2(g_dbPath, &g_sqliteDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); + HandleRc(g_sqliteDb, rc); + + rc = sqlite3_db_config(g_sqliteDb, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, nullptr); + HandleRc(g_sqliteDb, rc); + + rc = sqlite3_load_extension(g_sqliteDb, "libcustomtokenizer.z.so", nullptr, nullptr); + HandleRc(g_sqliteDb, rc); + /** + * @tc.steps: step2. create table + * @tc.expected: step2. OK. + */ + string sql = "CREATE VIRTUAL TABLE example USING fts5(content, tokenize = 'customtokenizer cut_mode short_words')"; + rc = sqlite3_exec(g_sqliteDb, sql.c_str(), Callback, 0, &zErrMsg); + HandleRc(g_sqliteDb, rc); + /** + * @tc.steps: step3. insert records + * @tc.expected: step3. OK. + */ + std::vector records = { + "电子邮件", + "这是一封电子邮件", + "这是一封关于少数民族的电子邮件", + "华中师范大学是一所位于武汉市的全日制综合性师范大学", + "中华人民共和国", + "武汉市长江大桥Wuhan Yangtze River Bridge是武汉市最长的桥" + }; + for (const auto &record : records) { + std::string insertSql = "insert into example values('" + record + "');"; + SQLTest(insertSql.c_str()); + } + /** + * @tc.steps: step4. test cut for short words + * @tc.expected: step4. OK. + */ + std::vector> expectResult = { + {"电子", 3}, {"邮件", 3}, {"电子邮件", 3}, {"少数", 1}, {"民族", 1}, {"少数民族", 1}, {"华中", 1}, + {"中师", 1}, {"师范", 1}, {"共和", 1}, {"共和国", 1}, {"人民共和国", 0}, {"Yangtze", 1}, {"Wuhan", 1}, + {"市长", 0} + }; + // 蓝区没有so导致失败,直接跳过测试 + if (!g_needSkip) { + for (const auto &[word, expectMatchNum] : expectResult) { + std::string querySql = "SELECT count(*) FROM example WHERE content MATCH '" + word + "';"; + EXPECT_EQ(sqlite3_exec(g_sqliteDb, querySql.c_str(), QueryCallback, + reinterpret_cast(expectMatchNum), nullptr), SQLITE_OK); + } + } + + const char *SQLDROP = "DROP TABLE IF EXISTS example;"; + SQLTest(SQLDROP); + EXPECT_EQ(sqlite3_close(g_sqliteDb), SQLITE_OK); +} + +/** + * @tc.name: SqliteAdapterTest003 + * @tc.desc: Test invalid args + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(SqliteAdapterTest, SqliteAdapterTest003, TestSize.Level0) +{ + /** + * @tc.steps: step1. prepare db + * @tc.expected: step1. OK. + */ + // Save any error messages + char *zErrMsg = nullptr; + + // Save the connection result + int rc = sqlite3_open_v2(g_dbPath, &g_sqliteDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); + HandleRc(g_sqliteDb, rc); + + rc = sqlite3_db_config(g_sqliteDb, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, nullptr); + HandleRc(g_sqliteDb, rc); + + rc = sqlite3_load_extension(g_sqliteDb, "libcustomtokenizer.z.so", nullptr, nullptr); + HandleRc(g_sqliteDb, rc); + /** + * @tc.steps: step2. create table which invalid args + * @tc.expected: step2. return SQLITE_ERROR. + */ + string sql = "CREATE VIRTUAL TABLE example USING fts5(content, tokenize = 'customtokenizer cut_mode')"; + rc = sqlite3_exec(g_sqliteDb, sql.c_str(), Callback, 0, &zErrMsg); + EXPECT_EQ(SQLITE_ERROR, rc); + + sql = "CREATE VIRTUAL TABLE example USING fts5(content, tokenize = 'customtokenizer cut_mode xxx xxx')"; + rc = sqlite3_exec(g_sqliteDb, sql.c_str(), Callback, 0, &zErrMsg); + EXPECT_EQ(SQLITE_ERROR, rc); + + sql = "CREATE VIRTUAL TABLE example USING fts5(content, tokenize = 'customtokenizer cut_mode xxx')"; + rc = sqlite3_exec(g_sqliteDb, sql.c_str(), Callback, 0, &zErrMsg); + EXPECT_EQ(SQLITE_ERROR, rc); + + sql = "CREATE VIRTUAL TABLE example USING fts5(content, tokenize = 'customtokenizer xxx short_words')"; + rc = sqlite3_exec(g_sqliteDb, sql.c_str(), Callback, 0, &zErrMsg); + EXPECT_EQ(SQLITE_ERROR, rc); + + const char *SQLDROP = "DROP TABLE IF EXISTS example;"; + SQLTest(SQLDROP); + EXPECT_EQ(sqlite3_close(g_sqliteDb), SQLITE_OK); +} + +/** + * @tc.name: SqliteAdapterTest004 + * @tc.desc: Test cut_mode default + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(SqliteAdapterTest, SqliteAdapterTest004, TestSize.Level0) +{ + /** + * @tc.steps: step1. prepare db + * @tc.expected: step1. OK. + */ + // Save any error messages + char *zErrMsg = nullptr; + + // Save the connection result + int rc = sqlite3_open_v2(g_dbPath, &g_sqliteDb, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); + HandleRc(g_sqliteDb, rc); + + rc = sqlite3_db_config(g_sqliteDb, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, nullptr); + HandleRc(g_sqliteDb, rc); + + rc = sqlite3_load_extension(g_sqliteDb, "libcustomtokenizer.z.so", nullptr, nullptr); + HandleRc(g_sqliteDb, rc); + /** + * @tc.steps: step2. create table + * @tc.expected: step2. OK. + */ + string sql = "CREATE VIRTUAL TABLE example USING fts5(content, tokenize = 'customtokenizer cut_mode default')"; + rc = sqlite3_exec(g_sqliteDb, sql.c_str(), Callback, 0, &zErrMsg); + HandleRc(g_sqliteDb, rc); + /** + * @tc.steps: step3. insert records + * @tc.expected: step3. OK. + */ + std::vector records = { + "电子邮件", + "这是一封电子邮件", + "这是一封关于少数民族的电子邮件" + }; + for (const auto &record : records) { + std::string insertSql = "insert into example values('" + record + "');"; + SQLTest(insertSql.c_str()); + } + /** + * @tc.steps: step4. test cut for short words + * @tc.expected: step4. OK. + */ + std::vector> expectResult = { + {"电子", 0}, {"邮件", 0}, {"电子邮件", 3}, {"少数", 0}, {"民族", 0}, {"少数民族", 1} + }; + // 蓝区没有so导致失败,直接跳过测试 + if (!g_needSkip) { + for (const auto &[word, expectMatchNum] : expectResult) { + std::string querySql = "SELECT count(*) FROM example WHERE content MATCH '" + word + "';"; + EXPECT_EQ(sqlite3_exec(g_sqliteDb, querySql.c_str(), QueryCallback, + reinterpret_cast(expectMatchNum), nullptr), SQLITE_OK); + } + } + + const char *SQLDROP = "DROP TABLE IF EXISTS example;"; + SQLTest(SQLDROP); + EXPECT_EQ(sqlite3_close(g_sqliteDb), SQLITE_OK); +} \ No newline at end of file diff --git a/kv_store/interfaces/innerkits/distributeddata/BUILD.gn b/kv_store/interfaces/innerkits/distributeddata/BUILD.gn index 0cda2969..6f290b29 100644 --- a/kv_store/interfaces/innerkits/distributeddata/BUILD.gn +++ b/kv_store/interfaces/innerkits/distributeddata/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2022-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 @@ -11,11 +11,10 @@ # See the License for the specific language governing permissions and # limitations under the License. import("//build/ohos.gni") -import("//foundation/distributeddatamgr/data_share/datashare.gni") import("//foundation/distributeddatamgr/kv_store/kv_store.gni") group("build_module") { - deps = [] + deps = [ ":distributeddata_inner_executor" ] if (!use_platform_win && !use_platforn_mac) { deps += [ ":distributeddata_client_sync", @@ -39,8 +38,6 @@ config("distributeddatafwk_config") { "../../../frameworks/common", "../../../frameworks/innerkitsimpl/kvdb/include", "../../../frameworks/innerkitsimpl/kvdb/src", - "${datashare_innerapi_path}/common/include", - "${datashare_innerapi_path}/provider/include", ] } @@ -68,6 +65,7 @@ old_source_config = [ "../../../frameworks/innerkitsimpl/distributeddatafwk/src/kvstore_datashare_bridge.cpp", "../../../frameworks/innerkitsimpl/distributeddatafwk/src/kvstore_observer_client.cpp", "../../../frameworks/innerkitsimpl/distributeddatafwk/src/kvstore_service_death_notifier.cpp", + "../../../frameworks/innerkitsimpl/distributeddatafwk/src/switch_observer_bridge.cpp", "../../../frameworks/innerkitsimpl/distributeddatafwk/src/sync_observer.cpp", "include/types.h", ] @@ -103,6 +101,7 @@ external_deps_config = [ "access_token:libaccesstoken_sdk", "access_token:libtokenid_sdk", "c_utils:utils", + "data_share:datashare_common_lite", "device_manager:devicemanagersdk", "hisysevent:libhisysevent", "hitrace:hitrace_meter", @@ -157,11 +156,15 @@ ohos_shared_library("distributeddata_client_sync") { sources = [ "${kv_store_base_path}/frameworks/innerkitsimpl/kvdb/src/process_communication_impl.cpp", "${kv_store_base_path}/frameworks/innerkitsimpl/kvdb/src/process_system_api_adapter_impl.cpp", + "${kv_store_base_path}/frameworks/innerkitsimpl/kvdb/src/store_util.cpp", ] cflags = [ "-Wno-c99-designator" ] configs = [ ":distributeddatafwk_config" ] - deps = [ "${kv_store_base_path}/frameworks/libs/distributeddb:distributeddb" ] + deps = [ + "${kv_store_base_path}/databaseutils:database_utils", + "${kv_store_base_path}/frameworks/libs/distributeddb:distributeddb" + ] external_deps = [ "c_utils:utils", @@ -211,3 +214,49 @@ ohos_static_library("kvdb_inner_lite") { subsystem_name = "distributeddatamgr" part_name = "kv_store" } + +config("distributeddata_common_public_config") { + visibility = [ ":*" ] + + include_dirs = [ + "include", + "../../../frameworks/common", + ] + + if (use_platform_win) { + cflags = [ "-includewin_glibc.h" ] + } else if (use_platforn_mac || is_ios || is_mac) { + cflags = [ "-includemac_glibc.h" ] + } + + if (use_platform_win || use_platforn_mac || is_ios || is_mac) { + include_dirs += [ + "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/mock", + ] + } +} + +ohos_static_library("distributeddata_inner_executor") { + branch_protector_ret = "pac_ret" + sanitize = { + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + public_configs = [ ":distributeddata_common_public_config" ] + cflags = [ "-Wno-c99-designator" ] + + if (use_platform_win) { + sources = [ + "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/mock/win_glibc.cpp", + ] + } else if (use_platforn_mac || is_ios || is_mac) { + sources = [ + "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/mock/mac_glibc.cpp", + ] + } + subsystem_name = "distributeddatamgr" + part_name = "kv_store" +} diff --git a/kv_store/interfaces/innerkits/distributeddata/include/executor.h b/kv_store/interfaces/innerkits/distributeddata/include/executor.h index 3d2c49bc..aa4c1bf4 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/executor.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/executor.h @@ -52,9 +52,9 @@ public: } }; - Executor() - : thread_([this] { - pthread_setname_np(pthread_self(), "OS_TaskExecutor"); + Executor(const std::string &threadName) + : thread_([this, threadName] { + pthread_setname_np(pthread_self(), threadName.c_str()); Run(); self_ = nullptr; }) diff --git a/kv_store/interfaces/innerkits/distributeddata/include/executor_pool.h b/kv_store/interfaces/innerkits/distributeddata/include/executor_pool.h index 8357b84c..84488b14 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/executor_pool.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/executor_pool.h @@ -40,8 +40,8 @@ public: static constexpr Duration INVALID_DELAY = std::chrono::seconds(0); static constexpr TaskId INVALID_TASK_ID = static_cast(0l); - ExecutorPool(size_t max, size_t min) - : pool_(max, min), delayTasks_(InnerTask(), NextTimer), taskId_(INVALID_TASK_ID) + ExecutorPool(size_t max, size_t min, const std::string &threadName = "DB_TaskExecutor") + : pool_(max, min, threadName), delayTasks_(InnerTask(), NextTimer), taskId_(INVALID_TASK_ID) { // When max equals 1, timer thread schedules and executes tasks. if (max > 1) { diff --git a/kv_store/interfaces/innerkits/distributeddata/include/pool.h b/kv_store/interfaces/innerkits/distributeddata/include/pool.h index 063158bf..276cdc9b 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/pool.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/pool.h @@ -18,11 +18,13 @@ #include #include #include +#include namespace OHOS { template class Pool { public: - Pool(uint32_t capability, uint32_t min) : capability_(capability), min_(min) {} + Pool(uint32_t capability, uint32_t min, const std::string &threadName) : capability_(capability), min_(min), + threadName_(threadName) {} std::shared_ptr Get(bool isForce = false) { @@ -31,7 +33,7 @@ public: if (!isForce && current_ >= capability_) { return nullptr; } - auto cur = new Node(); + auto cur = new Node(threadName_); idle_ = cur; current_++; } @@ -123,7 +125,8 @@ private: struct Node { Node *prev = nullptr; Node *next = nullptr; - std::shared_ptr data = std::make_shared(); + std::shared_ptr data; + Node(const std::string &threadName) : data(std::make_shared(threadName)) {}; }; uint32_t capability_; @@ -132,6 +135,7 @@ private: Node *idle_ = nullptr; Node *busy_ = nullptr; std::mutex mutex_; + std::string threadName_; }; } // namespace OHOS diff --git a/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h b/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h index 3fe5de78..0412ace9 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h @@ -197,6 +197,27 @@ public: return Status::SUCCESS; } + /** + * @brief Sync store with other devices only syncing the data which is satisfied with the condition. + * + * This is an asynchronous method. + * sync will fail if there is a syncing operation in progress. + * + * @param devices Device list to sync. + * @param mode Mode can be set to SyncMode::PUSH, SyncMode::PULL and SyncMode::PUSH_PULL. + * PUSH_PULL will firstly push all not-local store to listed devices, + * then pull these stores back. + * @param query The query condition. + * @param isRetry The send data is need retry. + * @param syncCallback The callback will be called when sync finished. + * @return Return SUCCESS for success, others for failure. + */ + virtual Status Sync(const std::vector &devices, SyncMode mode, const DataQuery &query, bool isRetry, + std::shared_ptr syncCallback) + { + return Status::SUCCESS; + } + /** * @brief Sync store with other device, while delay is 0. */ diff --git a/kv_store/interfaces/jskits/distributedkvstore/BUILD.gn b/kv_store/interfaces/jskits/distributedkvstore/BUILD.gn index 67bc0b79..2e262876 100644 --- a/kv_store/interfaces/jskits/distributedkvstore/BUILD.gn +++ b/kv_store/interfaces/jskits/distributedkvstore/BUILD.gn @@ -82,6 +82,7 @@ ohos_shared_library("distributedkvstore") { "common_event_service:cesfwk_innerkits", "hilog:libhilog", "ipc:ipc_single", + "json:nlohmann_json_static", "napi:ace_napi", ] diff --git a/kv_store/kvstoremock/distributeddb/BUILD.gn b/kv_store/kvstoremock/distributeddb/BUILD.gn index a65a8765..c690b4f6 100644 --- a/kv_store/kvstoremock/distributeddb/BUILD.gn +++ b/kv_store/kvstoremock/distributeddb/BUILD.gn @@ -94,7 +94,6 @@ config("distrdb_config") { visibility = [ ":*" ] include_dirs = distrdb_Dir include_dirs += [ - "//third_party/jsoncpp/include", "//third_party/zlib", "//third_party/sqlite/include", "//third_party/bounds_checking_function/include", @@ -128,7 +127,6 @@ ohos_shared_library("distributeddb_mock") { "//third_party/sqlite:sqlite_sdk", "//third_party/zlib:shared_libz", ] - if (use_platform_win) { libs = [ "//prebuilts/mingw-w64/ohos/linux-x86_64/clang-mingw/x86_64-w64-mingw32/lib/libws2_32.a" ] deps += [ @@ -138,7 +136,6 @@ ohos_shared_library("distributeddb_mock") { deps += [ "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_mac" ] } - configs += [ "//third_party/jsoncpp:jsoncpp_config" ] cflags = [ "-Wno-c99-designator" ] subsystem_name = "distributeddatamgr" part_name = "kv_store" diff --git a/kv_store/kvstoremock/distributeddb/distributeddataservice/adapter/autils/constant.h b/kv_store/kvstoremock/distributeddb/distributeddataservice/adapter/autils/constant.h index 1217102b..18325635 100644 --- a/kv_store/kvstoremock/distributeddb/distributeddataservice/adapter/autils/constant.h +++ b/kv_store/kvstoremock/distributeddb/distributeddataservice/adapter/autils/constant.h @@ -136,7 +136,6 @@ public: KVSTORE_API static const int MAX_OPEN_KVSTORES; - // name for process label (bus name for communication). compatible with HwDDMP KVSTORE_API static const std::string ROOT_KEY_GENERATED; }; diff --git a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp index 24a55d58..abcdfc15 100644 --- a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp +++ b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp @@ -65,7 +65,8 @@ std::shared_ptr StoreFactory::GetOrOpenStore(const AppId &appId, status = StoreUtil::ConvertStatus(dbStatus); if (kvStore == nullptr) { ZLOGE("Failed! status:%{public}d appId:%{public}s storeId:%{public}s path:%{public}s", dbStatus, - appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), options.baseDir.c_str()); + appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), + StoreUtil::Anonymous(options.baseDir).c_str()); return !stores.empty(); } isCreate = true; diff --git a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp index 922252d1..a355f7fe 100644 --- a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp +++ b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp @@ -29,7 +29,8 @@ std::shared_ptr StoreManager::GetKVStore(const AppId &appId, cons const Options &options, Status &status) { ZLOGD("appId:%{public}s, storeId:%{public}s type:%{public}d area:%{public}d dir:%{public}s", appId.appId.c_str(), - StoreUtil::Anonymous(storeId.storeId).c_str(), options.kvStoreType, options.area, options.baseDir.c_str()); + StoreUtil::Anonymous(storeId.storeId).c_str(), options.kvStoreType, options.area, + StoreUtil::Anonymous(options.baseDir).c_str()); status = ILLEGAL_STATE; if (!appId.IsValid() || !storeId.IsValid() || !options.IsValidType()) { status = INVALID_ARGUMENT; @@ -80,7 +81,7 @@ Status StoreManager::CloseAllKVStore(const AppId &appId, int32_t subUser) Status StoreManager::Delete(const AppId &appId, const StoreId &storeId, const std::string &path, int32_t subUser) { ZLOGD("appId:%{public}s, storeId:%{public}s dir:%{public}s", appId.appId.c_str(), - StoreUtil::Anonymous(storeId.storeId).c_str(), path.c_str()); + StoreUtil::Anonymous(storeId.storeId).c_str(), StoreUtil::Anonymous(path).c_str()); if (!appId.IsValid() || !storeId.IsValid()) { return INVALID_ARGUMENT; } diff --git a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_util.cpp b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_util.cpp index f08d93cf..76b09da1 100644 --- a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_util.cpp +++ b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_util.cpp @@ -170,12 +170,12 @@ bool StoreUtil::InitPath(const std::string &path) umask(DEFAULT_UMASK); #ifdef IS_WINDOWS if (mkdir(path.c_str()) != 0 && errno != EEXIST) { - ZLOGE("mkdir error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("mkdir error:%{public}d, path:%{public}s", errno, StoreUtil::Anonymous(path).c_str()); return false; } #else if (mkdir(path.c_str(), MODE) != 0 && errno != EEXIST) { - ZLOGE("mkdir error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("mkdir error:%{public}d, path:%{public}s", errno, StoreUtil::Anonymous(path).c_str()); return false; } #endif @@ -187,7 +187,7 @@ bool StoreUtil::CreateFile(const std::string &name) umask(DEFAULT_UMASK); int fp = open(name.c_str(), (O_WRONLY | O_CREAT)); if (fp < 0) { - ZLOGE("The fopen error:%{public}d, path:%{public}s", errno, name.c_str()); + ZLOGE("The fopen error:%{public}d, path:%{public}s", errno, StoreUtil::Anonymous(name).c_str()); return false; } close(fp); @@ -199,7 +199,7 @@ std::vector StoreUtil::GetSubPath(const std::string &path) std::vector subPaths; DIR *dirp = opendir(path.c_str()); if (dirp == nullptr) { - ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, StoreUtil::Anonymous(path).c_str()); return subPaths; } struct dirent *dp; @@ -215,7 +215,7 @@ std::vector StoreUtil::GetFiles(const std::string &path) std::vector fileInfos; DIR *dirp = opendir(path.c_str()); if (dirp == nullptr) { - ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("The opendir error:%{public}d, path:%{public}s", errno, StoreUtil::Anonymous(path).c_str()); return fileInfos; } struct dirent *dp; @@ -264,7 +264,7 @@ bool StoreUtil::Remove(const std::string &path) return true; } if (remove(path.c_str()) != 0) { - ZLOGE("The remove error:%{public}d, path:%{public}s", errno, path.c_str()); + ZLOGE("The remove error:%{public}d, path:%{public}s", errno, StoreUtil::Anonymous(path).c_str()); return false; } return true; diff --git a/kv_store/kvstoremock/frameworks/jskitsimpl/distributeddata/src/js_util.cpp b/kv_store/kvstoremock/frameworks/jskitsimpl/distributeddata/src/js_util.cpp index a30db825..43794e45 100644 --- a/kv_store/kvstoremock/frameworks/jskitsimpl/distributeddata/src/js_util.cpp +++ b/kv_store/kvstoremock/frameworks/jskitsimpl/distributeddata/src/js_util.cpp @@ -28,6 +28,11 @@ namespace OHOS::DistributedData { constexpr int32_t STR_MAX_LENGTH = 4096; constexpr size_t STR_TAIL_LENGTH = 1; constexpr mode_t MODE = 0755; +static constexpr int32_t HEAD_SIZE = 3; +static constexpr int32_t END_SIZE = 3; +static constexpr int32_t MIN_SIZE = 9; +static constexpr const char *REPLACE_CHAIN = "***"; +static constexpr const char *DEFAULT_ANONYMOUS = "******"; struct PredicatesProxy { std::shared_ptr predicates_; }; @@ -1115,7 +1120,7 @@ napi_status JSUtil::GetCurrentAbilityParam(napi_env env, ContextParam ¶m) param.area = DistributedKv::Area::EL1; param.baseDir = baseDir + "\\HuaweiDevEcoStudioDatabases"; if (mkdir(param.baseDir.c_str()) != 0) { - ZLOGE("mkdir error:%{public}d, path:%{public}s", errno, param.baseDir.c_str()); + ZLOGE("mkdir error:%{public}d, path:%{public}s", errno, Anonymous(param.baseDir).c_str()); } #else std::string baseDir = getenv("LOGNAME"); @@ -1126,12 +1131,12 @@ napi_status JSUtil::GetCurrentAbilityParam(napi_env env, ContextParam ¶m) param.area = DistributedKv::Area::EL1; param.baseDir = baseDir + "/HuaweiDevEcoStudioDatabases"; if (mkdir(param.baseDir.c_str(), MODE) != 0) { - ZLOGE("mkdir error:%{public}d, path:%{public}s", errno, param.baseDir.c_str()); + ZLOGE("mkdir error:%{public}d, path:%{public}s", errno, Anonymous(param.baseDir).c_str()); } #endif param.hapName = "com.example.myapplication"; ZLOGI("area:%{public}d hapName:%{public}s baseDir:%{public}s", param.area, param.hapName.c_str(), - param.baseDir.c_str()); + Anonymous(param.baseDir).c_str()); return napi_ok; } @@ -1204,4 +1209,17 @@ std::pair JSUtil::GetInnerValue( } return std::make_pair(napi_ok, inner); } + +std::string JSUtil::Anonymous(const std::string &name) +{ + if (name.length() <= HEAD_SIZE) { + return DEFAULT_ANONYMOUS; + } + + if (name.length() < MIN_SIZE) { + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN); + } + + return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE)); +} } // namespace OHOS::DistributedData diff --git a/kv_store/kvstoremock/interfaces/innerkits/distributeddata/BUILD.gn b/kv_store/kvstoremock/interfaces/innerkits/distributeddata/BUILD.gn index 58ce9c9a..81d16508 100644 --- a/kv_store/kvstoremock/interfaces/innerkits/distributeddata/BUILD.gn +++ b/kv_store/kvstoremock/interfaces/innerkits/distributeddata/BUILD.gn @@ -121,7 +121,6 @@ ohos_shared_library("distributeddata_inner_mock") { "//foundation/arkui/napi:ace_napi", "//foundation/distributeddatamgr/kv_store/kvstoremock/distributeddb:distributeddb_mock", "//third_party/bounds_checking_function:libsec_static", - "//third_party/jsoncpp:jsoncpp_static", "//third_party/libuv:uv", "//third_party/sqlite:sqlite_sdk", ] diff --git a/kv_store/kvstoremock/interfaces/jskits/distributeddata/BUILD.gn b/kv_store/kvstoremock/interfaces/jskits/distributeddata/BUILD.gn index 43e78696..42514dd5 100644 --- a/kv_store/kvstoremock/interfaces/jskits/distributeddata/BUILD.gn +++ b/kv_store/kvstoremock/interfaces/jskits/distributeddata/BUILD.gn @@ -13,7 +13,6 @@ import("//build/ohos.gni") import("//build/ohos/ace/ace.gni") -import("//foundation/distributeddatamgr/data_share/datashare.gni") import("//foundation/distributeddatamgr/kv_store/kv_store.gni") base_output_path = get_label_info(":distributed_data_js", "target_out_dir") @@ -41,8 +40,6 @@ if (use_platform_win || use_platforn_mac) { "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata/include", "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/mock/base", "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/mock", - "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common/include", - "//foundation/distributeddatamgr/data_share/interfaces/inner_api/provider/include", "//commonlibrary/c_utils/base/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/include", ] @@ -76,6 +73,10 @@ if (use_platform_win || use_platforn_mac) { "//third_party/libuv:uv", ] + external_deps = [ + "data_share:datashare_common_lite", + ] + if (use_platform_win) { defines = [ "IS_WINDOWS" ] deps += [ diff --git a/kv_store/kvstoremock/interfaces/jskits/distributedkvstore/BUILD.gn b/kv_store/kvstoremock/interfaces/jskits/distributedkvstore/BUILD.gn index 440314fc..c3f7410e 100644 --- a/kv_store/kvstoremock/interfaces/jskits/distributedkvstore/BUILD.gn +++ b/kv_store/kvstoremock/interfaces/jskits/distributedkvstore/BUILD.gn @@ -13,7 +13,6 @@ import("//build/ohos.gni") import("//build/ohos/ace/ace.gni") -import("//foundation/distributeddatamgr/data_share/datashare.gni") import("//foundation/distributeddatamgr/kv_store/kv_store.gni") base_output_path = get_label_info(":distributed_kvstore_js", "target_out_dir") @@ -32,7 +31,6 @@ group("build_module") { if (use_platform_win || use_platforn_mac) { ohos_shared_library("distributedkvstore") { include_dirs = [ - "//third_party/json/single_include", "//third_party/libuv/include", "//third_party/node/src", "//foundation/distributeddatamgr/kv_store", @@ -42,8 +40,6 @@ if (use_platform_win || use_platforn_mac) { "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata/include", "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/mock/base", "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/mock", - "//foundation/distributeddatamgr/data_share/interfaces/inner_api/common/include", - "//foundation/distributeddatamgr/data_share/interfaces/inner_api/provider/include", "//commonlibrary/c_utils/base/include", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/include", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework/include/utils", @@ -81,6 +77,11 @@ if (use_platform_win || use_platforn_mac) { "//third_party/libuv:uv", ] + external_deps = [ + "data_share:datashare_common_lite", + "json:nlohmann_json_static", + ] + if (use_platform_win) { defines = [ "IS_WINDOWS" ] deps += [ diff --git a/kv_store/test/distributedtest/single_kvstore_client/BUILD.gn b/kv_store/test/distributedtest/single_kvstore_client/BUILD.gn index 10750dcf..e0bdf48d 100644 --- a/kv_store/test/distributedtest/single_kvstore_client/BUILD.gn +++ b/kv_store/test/distributedtest/single_kvstore_client/BUILD.gn @@ -31,15 +31,16 @@ config("module_private_config") { common_deps = [ "${kv_store_base_path}/frameworks/libs/distributeddb:distributeddb", "${kv_store_base_path}/interfaces/innerkits/distributeddata:distributeddata_inner", - "${third_party_path}/googletest:gtest", ] common_external_deps = [ "access_token:libaccesstoken_sdk", - "access_token:libnativetoken", + "access_token:libnativetoken_shared", "access_token:libtoken_setproc", "c_utils:utils", + "cJSON:cjson", "device_manager:devicemanagersdk", + "googletest:gtest", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", diff --git a/kv_store/test/fuzztest/blob_fuzzer/blob_fuzzer.cpp b/kv_store/test/fuzztest/blob_fuzzer/blob_fuzzer.cpp index ae960965..b625187d 100644 --- a/kv_store/test/fuzztest/blob_fuzzer/blob_fuzzer.cpp +++ b/kv_store/test/fuzztest/blob_fuzzer/blob_fuzzer.cpp @@ -17,7 +17,7 @@ #include #include - +#include "fuzzer/FuzzedDataProvider.h" #include "securec.h" #include "types.h" #include "blob.h" @@ -59,29 +59,27 @@ void BlobOption(const Blob &blob) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Run your code on data */ - std::string fuzzStr(reinterpret_cast(data), size); - std::vector fuzzVec(fuzzStr.begin(), fuzzStr.end()); + FuzzedDataProvider fuzzer(data, size); + size_t blobSize = fuzzer.ConsumeIntegralInRange(1, 50); + std::vector fuzzVec = fuzzer.ConsumeBytes(blobSize); - int count = 10; - char str[count + 1]; - auto ret = memcpy_s(str, count + 1, data, std::min(static_cast(count + 1), size)); - if (ret != EOK) { - return 0; - } - str[count] = '\0'; - Blob blob1(str); - blob1 = str; - Blob blob2(fuzzStr); - blob2 = fuzzStr; + std::string str1 = fuzzer.ConsumeRandomLengthString(); + Blob blob1(str1.c_str()); + std::string str2 = fuzzer.ConsumeRandomLengthString(); + blob1 = str2.c_str(); + Blob blob2(fuzzer.ConsumeRandomLengthString()); + blob2 = fuzzer.ConsumeRandomLengthString(); Blob blob3(fuzzVec); - Blob blob4(str, count + 1); + std::string str3 = fuzzer.ConsumeRandomLengthString(); + Blob blob4(str3.c_str(), str3.length() + 1); Blob blob5(blob4); Blob blob6(std::move(blob5)); Blob blob7 = blob6; blob7 = Blob(blob6); + int count = 10; auto buffer = std::make_unique(count); uint8_t *writePtr = buffer.get(); - Blob blob8(fuzzStr); + Blob blob8(fuzzer.ConsumeRandomLengthString()); blob8.WriteToBuffer(writePtr, count); OHOS::BlobOption(blob8); diff --git a/kv_store/test/fuzztest/devicekvstore_fuzzer/devicekvstore_fuzzer.cpp b/kv_store/test/fuzztest/devicekvstore_fuzzer/devicekvstore_fuzzer.cpp index 3684d081..b406ba3a 100644 --- a/kv_store/test/fuzztest/devicekvstore_fuzzer/devicekvstore_fuzzer.cpp +++ b/kv_store/test/fuzztest/devicekvstore_fuzzer/devicekvstore_fuzzer.cpp @@ -19,6 +19,7 @@ #include #include "distributed_kv_data_manager.h" +#include "fuzzer/FuzzedDataProvider.h" #include "store_errno.h" using namespace OHOS; @@ -84,20 +85,20 @@ void TearDown(void) (void)remove("/data/service/el1/public/database/devicekvstorefuzzertest"); } -void PutFuzz(const uint8_t *data, size_t size) +void PutFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); Key key = { skey }; Value val = { svalue }; deviceKvStore_->Put(key, val); deviceKvStore_->Delete(key); } -void PutBatchFuzz(const uint8_t *data, size_t size) +void PutBatchFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); std::vector entries; std::vector keys; Entry entry1; @@ -119,10 +120,10 @@ void PutBatchFuzz(const uint8_t *data, size_t size) deviceKvStore_->DeleteBatch(keys); } -void GetFuzz(const uint8_t *data, size_t size) +void GetFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); Key key = { skey }; Value val = { svalue }; Value val1; @@ -131,9 +132,9 @@ void GetFuzz(const uint8_t *data, size_t size) deviceKvStore_->Delete(key); } -void GetEntriesFuzz1(const uint8_t *data, size_t size) +void GetEntriesFuzz1(FuzzedDataProvider &provider) { - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); std::string keys = "test_"; size_t sum = 10; std::vector results; @@ -146,9 +147,9 @@ void GetEntriesFuzz1(const uint8_t *data, size_t size) } } -void GetEntriesFuzz2(const uint8_t *data, size_t size) +void GetEntriesFuzz2(FuzzedDataProvider &provider) { - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); DataQuery dataQuery; dataQuery.KeyPrefix(prefix); std::string keys = "test_"; @@ -163,12 +164,12 @@ void GetEntriesFuzz2(const uint8_t *data, size_t size) } } -void SyncCallbackFuzz(const uint8_t *data, size_t size) +void SyncCallbackFuzz(FuzzedDataProvider &provider) { auto syncCallback = std::make_shared(); deviceKvStore_->RegisterSyncCallback(syncCallback); - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); DataQuery dataQuery; dataQuery.KeyPrefix(prefix); std::string keys = "test_"; @@ -186,11 +187,11 @@ void SyncCallbackFuzz(const uint8_t *data, size_t size) deviceKvStore_->UnRegisterSyncCallback(); } -void GetResultSetFuzz1(const uint8_t *data, size_t size) +void GetResultSetFuzz1(FuzzedDataProvider &provider) { - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); std::string keys = "test_"; - int position = static_cast(size); + int position = provider.ConsumeIntegral(); std::shared_ptr resultSet; size_t sum = 10; for (size_t i = 0; i < sum; i++) { @@ -209,9 +210,9 @@ void GetResultSetFuzz1(const uint8_t *data, size_t size) } } -void GetResultSetFuzz2(const uint8_t *data, size_t size) +void GetResultSetFuzz2(FuzzedDataProvider &provider) { - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); DataQuery dataQuery; dataQuery.KeyPrefix(prefix); std::string keys = "test_"; @@ -227,9 +228,9 @@ void GetResultSetFuzz2(const uint8_t *data, size_t size) } } -void GetResultSetFuzz3(const uint8_t *data, size_t size) +void GetResultSetFuzz3(FuzzedDataProvider &provider) { - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); DataQuery dataQuery; dataQuery.KeyPrefix(prefix); std::string keys = "test_"; @@ -244,7 +245,7 @@ void GetResultSetFuzz3(const uint8_t *data, size_t size) return; } int cnt = resultSet->GetCount(); - if (static_cast(size) != cnt) { + if (cnt != sum) { return; } resultSet->GetPosition(); @@ -277,10 +278,10 @@ void GetResultSetFuzz3(const uint8_t *data, size_t size) } } -void GetCountFuzz1(const uint8_t *data, size_t size) +void GetCountFuzz1(FuzzedDataProvider &provider) { int count; - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); DataQuery query; query.KeyPrefix(prefix); std::string keys = "test_"; @@ -294,12 +295,12 @@ void GetCountFuzz1(const uint8_t *data, size_t size) } } -void GetCountFuzz2(const uint8_t *data, size_t size) +void GetCountFuzz2(FuzzedDataProvider &provider) { int count; size_t sum = 10; std::vector keys; - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); for (size_t i = 0; i < sum; i++) { keys.push_back(prefix); } @@ -315,14 +316,14 @@ void GetCountFuzz2(const uint8_t *data, size_t size) } } -void SyncFuzz1(const uint8_t *data, size_t size) +void SyncFuzz1(FuzzedDataProvider &provider) { size_t sum = 10; std::string skey = "test_"; for (size_t i = 0; i < sum; i++) { deviceKvStore_->Put(skey + std::to_string(i), skey + std::to_string(i)); } - std::string deviceId(data, data + size); + std::string deviceId = provider.ConsumeRandomLengthString(); std::vector deviceIds = { deviceId }; uint32_t allowedDelayMs = 200; deviceKvStore_->Sync(deviceIds, SyncMode::PUSH, allowedDelayMs); @@ -331,14 +332,14 @@ void SyncFuzz1(const uint8_t *data, size_t size) } } -void SyncFuzz2(const uint8_t *data, size_t size) +void SyncFuzz2(FuzzedDataProvider &provider) { size_t sum = 10; std::string skey = "test_"; for (size_t i = 0; i < sum; i++) { deviceKvStore_->Put(skey + std::to_string(i), skey + std::to_string(i)); } - std::string deviceId(data, data + size); + std::string deviceId = provider.ConsumeRandomLengthString(); std::vector deviceIds = { deviceId }; DataQuery dataQuery; dataQuery.KeyPrefix("name"); @@ -348,9 +349,9 @@ void SyncFuzz2(const uint8_t *data, size_t size) } } -void SubscribeKvStoreFuzz(const uint8_t *data, size_t size) +void SubscribeKvStoreFuzz(FuzzedDataProvider &provider) { - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); DataQuery dataQuery; dataQuery.KeyPrefix(prefix); std::string keys = "test_"; @@ -366,10 +367,10 @@ void SubscribeKvStoreFuzz(const uint8_t *data, size_t size) } } -void RemoveDeviceDataFuzz(const uint8_t *data, size_t size) +void RemoveDeviceDataFuzz(FuzzedDataProvider &provider) { size_t sum = 10; - std::string deviceId(data, data + size); + std::string deviceId = provider.ConsumeRandomLengthString(); std::vector input; auto cmp = [](const Key &entry, const Key &sentry) { return entry.Data() < sentry.Data(); }; std::map dictionary(cmp); @@ -389,11 +390,11 @@ void RemoveDeviceDataFuzz(const uint8_t *data, size_t size) } } -void GetSecurityLevelFuzz(const uint8_t *data, size_t size) +void GetSecurityLevelFuzz(FuzzedDataProvider &provider) { size_t sum = 10; std::vector keys; - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); for (size_t i = 0; i < sum; i++) { keys.push_back(prefix); } @@ -408,11 +409,11 @@ void GetSecurityLevelFuzz(const uint8_t *data, size_t size) } } -void SyncParamFuzz(const uint8_t *data, size_t size) +void SyncParamFuzz(FuzzedDataProvider &provider) { size_t sum = 10; std::vector keys; - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); for (size_t i = 0; i < sum; i++) { keys.push_back(prefix); } @@ -432,11 +433,11 @@ void SyncParamFuzz(const uint8_t *data, size_t size) } } -void SetCapabilityEnabledFuzz(const uint8_t *data, size_t size) +void SetCapabilityEnabledFuzz(FuzzedDataProvider &provider) { size_t sum = 10; std::vector keys; - std::string prefix(data, data + size); + std::string prefix = provider.ConsumeRandomLengthString(); for (size_t i = 0; i < sum; i++) { keys.push_back(prefix); } @@ -453,17 +454,17 @@ void SetCapabilityEnabledFuzz(const uint8_t *data, size_t size) } } -void SetCapabilityRangeFuzz(const uint8_t *data, size_t size) +void SetCapabilityRangeFuzz(FuzzedDataProvider &provider) { - std::string label(data, data + size); + std::string label = provider.ConsumeRandomLengthString(); std::vector local = { label + "_local1", label + "_local2" }; std::vector remote = { label + "_remote1", label + "_remote2" }; deviceKvStore_->SetCapabilityRange(local, remote); } -void SubscribeWithQueryFuzz(const uint8_t *data, size_t size) +void SubscribeWithQueryFuzz(FuzzedDataProvider &provider) { - std::string deviceId(data, data + size); + std::string deviceId = provider.ConsumeRandomLengthString(); std::vector deviceIds = { deviceId + "_1", deviceId + "_2" }; DataQuery dataQuery; dataQuery.KeyPrefix("name"); @@ -471,9 +472,9 @@ void SubscribeWithQueryFuzz(const uint8_t *data, size_t size) deviceKvStore_->UnsubscribeWithQuery(deviceIds, dataQuery); } -void UnSubscribeWithQueryFuzz(const uint8_t *data, size_t size) +void UnSubscribeWithQueryFuzz(FuzzedDataProvider &provider) { - std::string deviceId(data, data + size); + std::string deviceId = provider.ConsumeRandomLengthString(); std::vector deviceIds = { deviceId + "_1", deviceId + "_2" }; DataQuery dataQuery; dataQuery.KeyPrefix("name"); @@ -485,28 +486,29 @@ void UnSubscribeWithQueryFuzz(const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Run your code on data */ + FuzzedDataProvider provider(data, size); OHOS::SetUpTestCase(); - OHOS::PutFuzz(data, size); - OHOS::PutBatchFuzz(data, size); - OHOS::GetFuzz(data, size); - OHOS::GetEntriesFuzz1(data, size); - OHOS::GetEntriesFuzz2(data, size); - OHOS::GetResultSetFuzz1(data, size); - OHOS::GetResultSetFuzz2(data, size); - OHOS::GetResultSetFuzz3(data, size); - OHOS::GetCountFuzz1(data, size); - OHOS::GetCountFuzz2(data, size); - OHOS::SyncFuzz1(data, size); - OHOS::SyncFuzz2(data, size); - OHOS::SubscribeKvStoreFuzz(data, size); - OHOS::RemoveDeviceDataFuzz(data, size); - OHOS::GetSecurityLevelFuzz(data, size); - OHOS::SyncCallbackFuzz(data, size); - OHOS::SyncParamFuzz(data, size); - OHOS::SetCapabilityEnabledFuzz(data, size); - OHOS::SetCapabilityRangeFuzz(data, size); - OHOS::SubscribeWithQueryFuzz(data, size); - OHOS::UnSubscribeWithQueryFuzz(data, size); + OHOS::PutFuzz(provider); + OHOS::PutBatchFuzz(provider); + OHOS::GetFuzz(provider); + OHOS::GetEntriesFuzz1(provider); + OHOS::GetEntriesFuzz2(provider); + OHOS::GetResultSetFuzz1(provider); + OHOS::GetResultSetFuzz2(provider); + OHOS::GetResultSetFuzz3(provider); + OHOS::GetCountFuzz1(provider); + OHOS::GetCountFuzz2(provider); + OHOS::SyncFuzz1(provider); + OHOS::SyncFuzz2(provider); + OHOS::SubscribeKvStoreFuzz(provider); + OHOS::RemoveDeviceDataFuzz(provider); + OHOS::GetSecurityLevelFuzz(provider); + OHOS::SyncCallbackFuzz(provider); + OHOS::SyncParamFuzz(provider); + OHOS::SetCapabilityEnabledFuzz(provider); + OHOS::SetCapabilityRangeFuzz(provider); + OHOS::SubscribeWithQueryFuzz(provider); + OHOS::UnSubscribeWithQueryFuzz(provider); OHOS::TearDown(); return 0; } \ No newline at end of file diff --git a/kv_store/test/fuzztest/distributedkvdatamanager_fuzzer/distributedkvdatamanager_fuzzer.cpp b/kv_store/test/fuzztest/distributedkvdatamanager_fuzzer/distributedkvdatamanager_fuzzer.cpp index 6bfec15d..dbfdddca 100644 --- a/kv_store/test/fuzztest/distributedkvdatamanager_fuzzer/distributedkvdatamanager_fuzzer.cpp +++ b/kv_store/test/fuzztest/distributedkvdatamanager_fuzzer/distributedkvdatamanager_fuzzer.cpp @@ -18,6 +18,7 @@ #include #include "distributed_kv_data_manager.h" +#include "fuzzer/FuzzedDataProvider.h" #include "kvstore_death_recipient.h" #include "kvstore_observer.h" #include "types.h" @@ -91,10 +92,10 @@ void TearDown(void) (void)remove("/data/service/el1/public/database/distributedkvdatamanagerfuzzertest"); } -void GetKvStoreFuzz(const uint8_t *data, size_t size) +void GetKvStoreFuzz(FuzzedDataProvider &provider) { StoreId storeId; - storeId.storeId = std::string(data, data + size); + storeId.storeId = provider.ConsumeRandomLengthString(); std::shared_ptr notExistKvStore; manager.GetSingleKvStore(create, appId, storeId, notExistKvStore); std::shared_ptr existKvStore; @@ -103,13 +104,13 @@ void GetKvStoreFuzz(const uint8_t *data, size_t size) manager.DeleteKvStore(appId, storeId); } -void GetAllKvStoreFuzz(const uint8_t *data, size_t size) +void GetAllKvStoreFuzz(FuzzedDataProvider &provider) { std::vector storeIds; manager.GetAllKvStoreId(appId, storeIds); std::shared_ptr KvStore; - std::string storeId_base(data, data + size); + std::string storeId_base = provider.ConsumeRandomLengthString(); int sum = 10; for (int i = 0; i < sum; i++) { StoreId storeId; @@ -122,10 +123,10 @@ void GetAllKvStoreFuzz(const uint8_t *data, size_t size) manager.GetAllKvStoreId(appId, storeIds); } -void CloseKvStoreFuzz(const uint8_t *data, size_t size) +void CloseKvStoreFuzz(FuzzedDataProvider &provider) { StoreId storeId; - storeId.storeId = std::string(data, data + size); + storeId.storeId = provider.ConsumeRandomLengthString(); manager.CloseKvStore(appId, storeId); std::shared_ptr kvStore; manager.GetSingleKvStore(create, appId, storeId, kvStore); @@ -133,10 +134,10 @@ void CloseKvStoreFuzz(const uint8_t *data, size_t size) manager.CloseKvStore(appId, storeId); } -void DeleteKvStoreFuzz(const uint8_t *data, size_t size) +void DeleteKvStoreFuzz(FuzzedDataProvider &provider) { StoreId storeId; - storeId.storeId = std::string(data, data + size); + storeId.storeId = provider.ConsumeRandomLengthString(); manager.DeleteKvStore(appId, storeId, create.baseDir); std::shared_ptr kvStore; @@ -147,14 +148,14 @@ void DeleteKvStoreFuzz(const uint8_t *data, size_t size) manager.CloseKvStore(appId, storeId); } -void DeleteAllKvStoreFuzz1(const uint8_t *data, size_t size) +void DeleteAllKvStoreFuzz1(FuzzedDataProvider &provider) { std::vector storeIds; manager.GetAllKvStoreId(appId, storeIds); manager.DeleteAllKvStore(appId, create.baseDir); std::shared_ptr KvStore; - std::string storeId_base(data, data + size); + std::string storeId_base = provider.ConsumeRandomLengthString(); int sum = 10; for (int i = 0; i < sum; i++) { StoreId storeId; @@ -166,13 +167,13 @@ void DeleteAllKvStoreFuzz1(const uint8_t *data, size_t size) manager.DeleteAllKvStore(appId, create.baseDir); } -void DeleteAllKvStoreFuzz2(const uint8_t *data, size_t size) +void DeleteAllKvStoreFuzz2(FuzzedDataProvider &provider) { std::vector storeIds; manager.GetAllKvStoreId(appId, storeIds); std::shared_ptr KvStore; - std::string storeId_base(data, data + size); + std::string storeId_base = provider.ConsumeRandomLengthString(); manager.GetSingleKvStore(create, appId, storeIdTest, KvStore); manager.CloseKvStore(appId, storeIdTest); int sum = 10; @@ -184,13 +185,13 @@ void DeleteAllKvStoreFuzz2(const uint8_t *data, size_t size) manager.DeleteAllKvStore(appId, create.baseDir); } -void DeleteAllKvStoreFuzz3(const uint8_t *data, size_t size) +void DeleteAllKvStoreFuzz3(FuzzedDataProvider &provider) { std::vector storeIds; manager.GetAllKvStoreId(appId, storeIds); std::shared_ptr KvStore; - std::string storeId_base(data, data + size); + std::string storeId_base = provider.ConsumeRandomLengthString(); int sum = 10; for (int i = 0; i < sum; i++) { StoreId storeId; @@ -214,10 +215,10 @@ void UnRegisterKvStoreServiceDeathRecipientFuzz() kvStoreDeathRecipient->OnRemoteDied(); } -void PutSwitchFuzz(const uint8_t *data, size_t size) +void PutSwitchFuzz(FuzzedDataProvider &provider) { - std::string appIds(data, data + size); - uint32_t input = static_cast(size); + std::string appIds = provider.ConsumeRandomLengthString(); + uint32_t input = provider.ConsumeIntegral(); SwitchData switchData; switchData.value = input; switchData.length = input & 0xFFFF; @@ -225,48 +226,57 @@ void PutSwitchFuzz(const uint8_t *data, size_t size) manager.PutSwitch({ "distributed_device_profile_service" }, switchData); } -void GetSwitchFuzz(const uint8_t *data, size_t size) +void GetSwitchFuzz(FuzzedDataProvider &provider) { - std::string appIds(data, data + size); - std::string networkId(data, data + size); + std::string appIds = provider.ConsumeRandomLengthString(); + std::string networkId = provider.ConsumeRandomLengthString(); manager.GetSwitch({ appIds }, networkId); manager.GetSwitch({ "distributed_device_profile_service" }, networkId); } -void SubscribeSwitchDataFuzz(const uint8_t *data, size_t size) +void SubscribeSwitchDataFuzz(FuzzedDataProvider &provider) { - std::string appIds(data, data + size); + std::string appIds = provider.ConsumeRandomLengthString(); std::shared_ptr observer = std::make_shared(); manager.SubscribeSwitchData({ appIds }, observer); } -void UnsubscribeSwitchDataFuzz(const uint8_t *data, size_t size) +void UnsubscribeSwitchDataFuzz(FuzzedDataProvider &provider) { - std::string appIds(data, data + size); + std::string appIds = provider.ConsumeRandomLengthString(); std::shared_ptr observer = std::make_shared(); manager.SubscribeSwitchData({ appIds }, observer); manager.UnsubscribeSwitchData({ appIds }, observer); } + +void SetExecutorsFuzz(FuzzedDataProvider &provider) +{ + size_t max = provider.ConsumeIntegral(); + size_t min = provider.ConsumeIntegral(); + auto executors = std::make_shared(max, min); + manager.SetExecutors(executors); +} } // namespace OHOS /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Run your code on data */ + FuzzedDataProvider provider(data, size); OHOS::SetUpTestCase(); - OHOS::GetKvStoreFuzz(data, size); - OHOS::GetAllKvStoreFuzz(data, size); - OHOS::CloseKvStoreFuzz(data, size); - OHOS::DeleteKvStoreFuzz(data, size); - OHOS::DeleteAllKvStoreFuzz1(data, size); - OHOS::DeleteAllKvStoreFuzz2(data, size); - OHOS::DeleteAllKvStoreFuzz3(data, size); + OHOS::GetKvStoreFuzz(provider); + OHOS::GetAllKvStoreFuzz(provider); + OHOS::CloseKvStoreFuzz(provider); + OHOS::DeleteKvStoreFuzz(provider); + OHOS::DeleteAllKvStoreFuzz1(provider); + OHOS::DeleteAllKvStoreFuzz2(provider); + OHOS::DeleteAllKvStoreFuzz3(provider); OHOS::RegisterKvStoreServiceDeathRecipientFuzz(); OHOS::UnRegisterKvStoreServiceDeathRecipientFuzz(); - OHOS::PutSwitchFuzz(data, size); - OHOS::GetSwitchFuzz(data, size); - OHOS::SubscribeSwitchDataFuzz(data, size); - OHOS::UnsubscribeSwitchDataFuzz(data, size); + OHOS::PutSwitchFuzz(provider); + OHOS::GetSwitchFuzz(provider); + OHOS::SubscribeSwitchDataFuzz(provider); + OHOS::UnsubscribeSwitchDataFuzz(provider); OHOS::TearDown(); return 0; } \ No newline at end of file diff --git a/kv_store/test/fuzztest/distributedkvdataservice_fuzzer/distributedkvdataservice_fuzzer.cpp b/kv_store/test/fuzztest/distributedkvdataservice_fuzzer/distributedkvdataservice_fuzzer.cpp deleted file mode 100644 index 60ae617f..00000000 --- a/kv_store/test/fuzztest/distributedkvdataservice_fuzzer/distributedkvdataservice_fuzzer.cpp +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (c) 2021 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 "distributedkvdataservice_fuzzer.h" - -#include "distributed_kv_data_manager.h" -#include "kvstore_death_recipient.h" -#include "kvstore_observer.h" -#include "types.h" -#include -#include - -using namespace OHOS; -using namespace OHOS::DistributedKv; - -class DistributedKvDataServiceFuzzer { - /* Keep C++ file names the same as the class name */ -}; - -namespace OHOS { - -static std::shared_ptr singleKvStore = nullptr; -static distributedkvdataservice service; -static AppId appIdTest; -static StoreId storeIdTest; -static Options createTest; -static Options noCreate; -static UserId userId; - -class MyDeathRecipient : public KvStoreDeathRecipient { -public: - MyDeathRecipient() { } - virtual ~MyDeathRecipient() { } - void OnRemoteDied() override { } -}; - -class SwitchDataObserver : public KvStoreObserver { -public: - void OnSwitchChange(const SwitchNotification ¬ification) override - { - blockData_.SetValue(notification); - } - - SwitchNotification Get() - { - return blockData_.GetValue(); - } - -private: - BlockData blockData_ { 1, SwitchNotification() }; -}; - -void SetUpTestCase(void) -{ - userId.userId = "account"; - appIdTest.appId = "distributedkvdataservicefuzzertest"; - createTest.createIfMissing = true; - createTest.encrypt = false; - createTest.autoSync = true; - createTest.kvStoreType = SINGLE_VERSION; - createTest.area = EL1; - createTest.baseDir = std::string("/data/service/el1/public/database/") + appIdTest.appId; - mkdir(createTest.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); - - service.CloseAllKvStore(appIdTest); - service.DeleteAllKvStore(appIdTest, createTest.baseDir); -} - -void TearDown(void) -{ - service.CloseAllKvStore(appIdTest); - service.DeleteAllKvStore(appIdTest, createTest.baseDir); - (void)remove("/data/service/el1/public/database/distributedkvdataservicefuzzertest/key"); - (void)remove("/data/service/el1/public/database/distributedkvdataservicefuzzertest/kvdb"); - (void)remove("/data/service/el1/public/database/distributedkvdataservicefuzzertest"); -} - -void GetKvStoreFuzzTest(const uint8_t *data, size_t size) -{ - StoreId storeId; - storeId.storeId = std::string(data, data + size); - std::shared_ptr notExistKvStore; - service.GetSingleKvStore(createTest, appIdTest, storeId, notExistKvStore); - std::shared_ptr existKvStore; - service.GetSingleKvStore(noCreate, appIdTest, storeId, existKvStore); - service.CloseKvStore(appIdTest, storeId); - service.DeleteKvStore(appIdTest, storeId); -} - -void GetAllKvStoreFuzzTest(const uint8_t *data, size_t size) -{ - std::vector storeIds; - service.GetAllKvStoreId(appIdTest, storeIds); - - std::shared_ptr KvStore; - std::string storeIdBase(data, data + size); - int sum = 10; - - for (int i = 0; i < sum; i++) { - StoreId storeId; - storeId.storeId = storeIdBase + "_" + std::to_string(i); - service.GetSingleKvStore(createTest, appIdTest, storeId, KvStore); - } - service.GetAllKvStoreId(appIdTest, storeIds); - service.CloseAllKvStore(appIdTest); - - service.GetAllKvStoreId(appIdTest, storeIds); -} - -void CloseKvStoreFuzzTest(const uint8_t *data, size_t size) -{ - StoreId storeId; - storeId.storeId = std::string(data, data + size); - service.CloseKvStore(appIdTest, storeId); - std::shared_ptr kvStoreImpl; - service.GetSingleKvStore(createTest, appIdTest, storeId, kvStoreImpl); - service.CloseKvStore(appIdTest, storeId); - service.CloseKvStore(appIdTest, storeId); -} - -void DeleteKvStoreFuzzTest(const uint8_t *data, size_t size) -{ - StoreId storeId; - storeId.storeId = std::string(data, data + size); - service.DeleteKvStore(appIdTest, storeId, createTest.baseDir); - - std::shared_ptr kvStoreImpl; - service.GetSingleKvStore(createTest, appIdTest, storeId, kvStoreImpl); - service.CloseKvStore(appIdTest, storeId); - service.DeleteKvStore(appIdTest, storeId, createTest.baseDir); - - service.CloseKvStore(appIdTest, storeId); -} - -void DeleteAllKvStoreFuzz1Test(const uint8_t *data, size_t size) -{ - std::vector storeIds; - service.GetAllKvStoreId(appIdTest, storeIds); - - service.DeleteAllKvStore(appIdTest, createTest.baseDir); - std::shared_ptr KvStore; - std::string storeIdBase(data, data + size); - - int sum = 10; - for (int i = 0; i < sum; i++) { - StoreId storeId; - storeId.storeId = storeIdBase + "_" + std::to_string(i); - service.GetSingleKvStore(createTest, appIdTest, storeId, KvStore); - - service.CloseKvStore(appIdTest, storeId); - } - service.DeleteAllKvStore(appIdTest, createTest.baseDir); -} - -void DeleteAllKvStoreFuzz2Test(const uint8_t *data, size_t size) -{ - std::vector storeIds; - service.GetAllKvStoreId(appIdTest, storeIds); - - std::shared_ptr KvStore; - std::string storeIdBase(data, data + size); - service.GetSingleKvStore(create, appIdTest, storeIdTest, KvStore); - service.CloseKvStore(appIdTest, storeIdTest); - int sum = 10; - - for (int i = 0; i < sum; i++) { - StoreId storeId; - storeId.storeId = storeIdBase + "_" + std::to_string(i); - service.GetSingleKvStore(create, appIdTest, storeId, KvStore); - } - service.DeleteAllKvStore(appIdTest, createTest.baseDir); -} - -void DeleteAllKvStoreFuzz3Test(const uint8_t *data, size_t size) -{ - std::vector storeIds; - service.GetAllKvStoreId(appIdTest, storeIds); - - std::shared_ptr KvStore; - std::string storeIdBase(data, data + size); - int sum = 10; - for (int i = 0; i < sum; i++) { - StoreId storeId; - storeId.storeId = storeIdBase + "_" + std::to_string(i); - service.GetSingleKvStore(create, appIdTest, storeId, KvStore); - } - service.DeleteAllKvStore(appIdTest, createTest.baseDir); -} - -void RegisterKvStoreServiceDeathRecipientFuzzTest() -{ - std::shared_ptr kvStoreDeathRecipientImpl = std::make_shared(); - service.RegisterKvStoreServiceDeathRecipient(kvStoreDeathRecipientImpl); - kvStoreDeathRecipientImpl->OnRemoteDied(); -} - -void UnRegisterKvStoreServiceDeathRecipientFuzzTest() -{ - std::shared_ptr kvStoreDeathRecipientImpl = std::make_shared(); - - service.UnRegisterKvStoreServiceDeathRecipient(kvStoreDeathRecipientImpl); - kvStoreDeathRecipientImpl->OnRemoteDied(); -} - -void PutSwitchFuzzTest(const uint8_t *data, size_t size) -{ - std::string appIds(data, data + size); - uint32_t input = static_cast(size); - SwitchData switchData11; - switchData11.value = input; - switchData11.length = input & 0xFFFF; - - service.PutSwitch({ appIds }, switchData11); - service.PutSwitch({ "distributed_device_profile_service" }, switchData11); -} - -void GetSwitchFuzzTest(const uint8_t *data, size_t size) -{ - std::string appIds(data, data + size); - std::string networkId(data, data + size); - - service.GetSwitch({ appIds }, networkId); - service.GetSwitch({ "distributed_device_profile_service" }, networkId); -} - -void SubscribeSwitchDataFuzzTest(const uint8_t *data, size_t size) -{ - std::string appIds(data, data + size); - std::shared_ptr dataObserver = std::make_shared(); - - service.SubscribeSwitchData({ appIds }, dataObserver); -} - -void UnsubscribeSwitchDataFuzzTest(const uint8_t *data, size_t size) -{ - std::string appIds(data, data + size); - std::shared_ptr dataObserver = std::make_shared(); - - service.SubscribeSwitchData({ appIds }, dataObserver); - service.UnsubscribeSwitchData({ appIds }, dataObserver); -} -} // namespace OHOS - -/* Fuzzer entry point */ -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - /* Run your code on data */ - OHOS::SetUpTestCase(); - OHOS::GetKvStoreFuzzTest(data, size); - OHOS::GetAllKvStoreFuzzTest(data, size); - OHOS::CloseKvStoreFuzzTest(data, size); - OHOS::DeleteKvStoreFuzzTest(data, size); - OHOS::DeleteAllKvStoreFuzz1Test(data, size); - OHOS::DeleteAllKvStoreFuzz2Test(data, size); - OHOS::DeleteAllKvStoreFuzz3Test(data, size); - OHOS::RegisterKvStoreServiceDeathRecipientFuzzTest(); - OHOS::UnRegisterKvStoreServiceDeathRecipientFuzzTest(); - OHOS::PutSwitchFuzzTest(data, size); - OHOS::GetSwitchFuzzTest(data, size); - OHOS::SubscribeSwitchDataFuzzTest(data, size); - OHOS::UnsubscribeSwitchDataFuzzTest(data, size); - OHOS::TearDown(); - return 0; -} \ No newline at end of file diff --git a/kv_store/test/fuzztest/jsonservice_fuzzer/BUILD.gn b/kv_store/test/fuzztest/jsonservice_fuzzer/BUILD.gn deleted file mode 100644 index eeae1c09..00000000 --- a/kv_store/test/fuzztest/jsonservice_fuzzer/BUILD.gn +++ /dev/null @@ -1,147 +0,0 @@ -# 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. - -import("//build/config/features.gni") -import("//build/test.gni") - -module_output_path = "kv_store/kv_store" - -############################################################################### -config("module_private_config") { - visibility = [ ":*" ] - - include_dirs = [ - "../../../gaussdb_rd/include", - "../../../gaussdb_rd/src/common/include", - "../../../gaussdb_rd/src/executor/include", - "../../../gaussdb_rd/src/executor/document", - "../../../gaussdb_rd/src/oh_adapter/include", - "../../../gaussdb_rd/src/oh_adapter/src", - "../../../gaussdb_rd/src/interface/include", - ] - - defines = [ - "SQLITE_ENABLE_SNAPSHOT", - "SQLITE_HAS_CODEC", - "SQLITE_ENABLE_JSON1", - "USING_HILOG_LOGGER", - "USE_SQLITE_SYMBOLS", - "SQLITE_ENABLE_DROPTABLE_CALLBACK", - ] -} - -############################################################################### -ohos_source_set("src_file") { - testonly = true - - sources = [ - "../../../gaussdb_rd/src/common/src/collection_option.cpp", - "../../../gaussdb_rd/src/common/src/db_config.cpp", - "../../../gaussdb_rd/src/common/src/grd_api_manager.cpp", - "../../../gaussdb_rd/src/common/src/json_common.cpp", - "../../../gaussdb_rd/src/common/src/os_api.cpp", - "../../../gaussdb_rd/src/common/src/rd_log_print.cpp", - "../../../gaussdb_rd/src/executor/base/grd_db_api.cpp", - "../../../gaussdb_rd/src/executor/document/check_common.cpp", - "../../../gaussdb_rd/src/executor/document/grd_document_api.cpp", - "../../../gaussdb_rd/src/executor/document/grd_document_api_inner.cpp", - "../../../gaussdb_rd/src/executor/document/grd_resultset_api.cpp", - "../../../gaussdb_rd/src/executor/document/grd_resultset_api_inner.cpp", - "../../../gaussdb_rd/src/executor/kv/grd_kv_api.cpp", - "../../../gaussdb_rd/src/executor/kv/grd_kv_api_inner.cpp", - "../../../gaussdb_rd/src/interface/src/collection.cpp", - "../../../gaussdb_rd/src/interface/src/doc_errno.cpp", - "../../../gaussdb_rd/src/interface/src/document_key.cpp", - "../../../gaussdb_rd/src/interface/src/document_store.cpp", - "../../../gaussdb_rd/src/interface/src/document_store_manager.cpp", - "../../../gaussdb_rd/src/interface/src/projection_tree.cpp", - "../../../gaussdb_rd/src/interface/src/result_set.cpp", - "../../../gaussdb_rd/src/interface/src/result_set_common.cpp", - "../../../gaussdb_rd/src/oh_adapter/src/kv_store_manager.cpp", - "../../../gaussdb_rd/src/oh_adapter/src/rd_json_object.cpp", - "../../../gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp", - "../../../gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.cpp", - ] - - configs = [ ":module_private_config" ] - - deps = [ "//third_party/sqlite:sqlite" ] - - configs += [ "//third_party/cJSON:cJSON_config" ] - ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps += [ "//third_party/cJSON:cjson" ] - external_deps = [ - "c_utils:utils", - "hilog:libhilog", - "hisysevent:libhisysevent", - "hitrace:hitrace_meter", - ] - - subsystem_name = "distributeddatamgr" - part_name = "kv_store" -} - -ohos_fuzztest("JsonServiceFuzzTest") { - module_out_path = module_output_path - fuzz_config_file = "../jsonservice_fuzzer" - - if (!defined(deps)) { - deps = [] - } - if (!defined(external_deps)) { - external_deps = [] - } - configs = [ ":module_private_config" ] - deps += [ - ":src_file", - "//third_party/sqlite:sqlite", - ] - configs += [ "//third_party/cJSON:cJSON_config" ] - ldflags = [ "-Wl,--exclude-libs,ALL" ] - deps += [ - "//third_party/cJSON:cjson", - "//third_party/openssl:libcrypto_shared", - ] - external_deps = [ - "c_utils:utils", - "hilog:libhilog", - "hisysevent:libhisysevent", - "hitrace:hitrace_meter", - ] - - cflags = [ - "-g", - "-O0", - "-Wno-unused-variable", - "-fno-omit-frame-pointer", - "--coverage", - ] - - ldflags += [ "--coverage" ] - - cflags_cc = [ "--coverage" ] - - sources = [ "jsonservice_fuzzer.cpp" ] -} - -############################################################################### - -group("fuzztest") { - testonly = true - deps = [] - deps += [ - # deps file - ":JsonServiceFuzzTest", - ] -} -############################################################################### diff --git a/kv_store/test/fuzztest/jsonservice_fuzzer/jsonservice_fuzzer.cpp b/kv_store/test/fuzztest/jsonservice_fuzzer/jsonservice_fuzzer.cpp deleted file mode 100644 index 2650f074..00000000 --- a/kv_store/test/fuzztest/jsonservice_fuzzer/jsonservice_fuzzer.cpp +++ /dev/null @@ -1,1671 +0,0 @@ -/* - * 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 "jsonservice_fuzzer.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "grd_base/grd_db_api.h" -#include "grd_base/grd_error.h" -#include "grd_base/grd_resultset_api.h" -#include "grd_documentVirtual/grd_documentVirtual_api.h" -#include "grd_kv/grd_kv_api.h" -#include "grd_resultset_inner.h" -#include "securec.h" -#include -#include -#include -#include -#include - -const char *TEST_DB = "./data"; -const char *TEST_FILE = "./data/testfile"; -const char *COLLECT_NAME = "collectionname"; -const char *OPTION_STRING = "{ \"maxdoc\" : 1000}"; -const char *CONFIG_STRING = "{}"; -const char *DB_DIR_PATH = "./data/"; -const char *NO_EXIST_COLLECTION_NAME = "no_exisit"; -const int NUM_THREE = 3; -const int SMALL_PREFIX_LENGTH = 5; -const int NUM_FIFTEEN = 15; -const int NUM_NINETY_EIGHT = 98; -const int BATCH_COUNT = 100; -const int LESS_HALF_BYTES = 511; -const int HALF_BYTES = 512; -const int MORE_HALF_BYTES = 513; -const int HALF_HALF_BYTES = 256; -const int MORE_HALF_HALF_BYTES = 257; -const int MAX_LEN_NUM = 600; -const int LESS_MIDDLE_SIZE_TEST = 899; -const int MIDDLE_SIZE_TEST = 900; -const int MAX_SIZE_NUM_TEST = 1000; -const int ONE_BYTES = 1024; -const int CURSOR_COUNT_TEST = 50000; -const int VECTOR_SIZE = 100000; - -static GRD_DB *g_datatest = nullptr; - -namespace OHOS { -namespace { -int RemoveDirTest(const char *dirTest) -{ - if (dirTest == nullptr) { - return -1; - } - struct stat dirStatus; - if (stat(dirTest, &dirStatus) < 0) { - return -1; - } - if (access(dirTest, F_OK) != 0) { - return 0; - } - char dirNameVirtual[PATH_MAX]; - DIR *dirPtrTest = nullptr; - struct dirent *dr = nullptr; - if (S_ISREG(dirStatus.st_mode)) { // normal file - remove(dirTest); - } else if (S_ISDIR(dirStatus.st_mode)) { - dirPtrTest = opendir(dirTest); - while ((dr = readdir(dirPtrTest)) != nullptr) { - // ignore . and .. - if ((strcmp(".", dr->d_name) == 0) || (strcmp("..", dr->d_name) == 0)) { - continue; - } - if (sprintf_s(dirNameVirtual, sizeof(dirNameVirtual), "%s / %s", dirTest, dr->d_name) < 0) { - (void)RemoveDirTest(dirNameVirtual); - closedir(dirPtrTest); - rmdir(dirTest); - return -1; - } - (void)RemoveDirTest(dirNameVirtual); - } - closedir(dirPtrTest); - rmdir(dirTest); // remove empty dirTest - } else { - return -1; - } - return 0; -} - -void MakeDirctionary(const char *dirTest) -{ - std::string tmpPathVirtual; - const char *pcur = dirTest; - - while (*pcur++ != '\0') { - tmpPathVirtual.push_back(*(pcur - 1)); - if ((*pcur == '/' || *pcur == '\0') && access(tmpPathVirtual.c_str(), 0) != 0 && !tmpPathVirtual.empty()) { - if (mkdir(tmpPathVirtual.c_str(), (S_IRUSR | S_IWUSR | S_IXUSR)) != 0) { - return; - } - } - } -} - -std::string GetMaxString() -{ - std::string str = "{"; - for (int i = 0; i <= MAX_SIZE_NUM_TEST; i++) { - for (int j = 0; j <= MAX_LEN_NUM; j++) { - str += "a"; - } - } - return str + "}"; -} -} // namespace - -void InsertDocOneFuzzTest(const std::string &documentVirtualData) -{ - std::string documentVirtual2 = "{\"id\":2,\"field\":\"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual2.c_str(), 0); - std::string documentVirtual3 = "{\"id\":true,\"field\":\"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual3.c_str(), 0); - std::string documentVirtual4 = "{\"id\" : null, \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual4.c_str(), 0); - std::string documentVirtual5 = "{\"id\" : [\"2\"], \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual5.c_str(), 0); - std::string documentVirtual6 = "{\"id\" : {\"val\" : \"2\"}, \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual6.c_str(), 0); - std::string documentVirtual7 = "{\"id\" : \"3\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual7.c_str(), 0); - std::string documentVirtual9 = "{\"id\" : \"4\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(NULL, COLLECT_NAME, documentVirtual9.c_str(), 0); - std::string documentVirtual10 = "{\"id\" : \"5\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, NULL, documentVirtual10.c_str(), 0); - std::string documentVirtual12 = "{\"id\" : \"6\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual12.c_str(), 1); - std::string documentVirtual13 = "{\"id\" : \"7\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual13.c_str(), INT_MAX); - std::string documentVirtual14 = "{\"id\" : \"8\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual14.c_str(), INT_MIN); - GRD_InsertDocument(g_datatest, NULL, NULL, 0); - std::string documentVirtual15 = "{\"id\" : \"9\", \"name\" : \"" + documentVirtualData + "\"}"; - std::string collectName2(HALF_BYTES, 'a'); - GRD_InsertDocument(g_datatest, collectName2.c_str(), documentVirtual15.c_str(), 0); - const char *collectName = "collection@!#"; - std::string documentVirtual18 = "{\"id\" : \"18\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual18.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual19.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual20.c_str(), 0); - std::string documentVirtual21 = "{\"id\" : \"21\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, collectName, documentVirtual21.c_str(), GRD_OK); - std::string collectName1(HALF_HALF_BYTES, 'k'); -} - -void InsertDocTwoFuzzTest(const std::string &documentVirtualData) -{ - std::string documentVirtualPart1 = "{ \"id\" : \"15\", \"textVal\" : \" "; - std::string documentVirtualPart2 = "\" }"; - std::string jsonVal = - std::string(HALF_BYTES * ONE_BYTES - documentVirtualPart1.size() - documentVirtualPart2.size(), 'k'); - std::string documentVirtual = documentVirtualPart1 + jsonVal + documentVirtualPart2; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual.c_str(), 0); - std::string jsonVal2 = - std::string(HALF_BYTES * ONE_BYTES - 1 - documentVirtualPart1.size() - documentVirtualPart2.size(), 'k'); - std::string documentVirtual21 = documentVirtualPart1 + jsonVal2 + documentVirtualPart2; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual21.c_str(), 0); - std::string documentVirtual22 = "{\"id\" : \"16\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual22.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual23.c_str(), 0); - std::string documentVirtual24 = documentVirtualData; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual24.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual25.c_str(), 0); - std::string collectName3 = std::string(HALF_HALF_BYTES, 'k'); - std::string documentVirtual26 = "{\"id\" : \"22\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, collectName3.c_str(), documentVirtual26.c_str(), GRD_OK); - std::string collectName4 = "Aads_sd__23Asb_"; - std::string documentVirtual27 = "{\"id\" : \"23\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, collectName4.c_str(), documentVirtual27.c_str(), GRD_OK); - std::string collectName5 = "GRD_collectName"; - std::string documentVirtual28 = "{\"id\" : \"24\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_CreateCollect(g_datatest, collectName5.c_str(), "", 0); - GRD_InsertDocument(g_datatest, collectName5.c_str(), documentVirtual28.c_str(), 0); - collectName5 = "GM_SYS__collectName"; - std::string documentVirtual29 = "{\"id\" : \"24_2\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_CreateCollect(g_datatest, collectName5.c_str(), "", 0); - GRD_InsertDocument(g_datatest, collectName5.c_str(), documentVirtual29.c_str(), 0); - - collectName5 = "grd_collectName"; - std::string documentVirtual30 = "{\"id\" : \"24_3\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_CreateCollect(g_datatest, collectName5.c_str(), "", 0); - GRD_InsertDocument(g_datatest, collectName5.c_str(), documentVirtual30.c_str(), 0); -} - -void InsertDocThreeFuzzTest(const std::string &documentVirtualData) -{ - std::string collectName5 = "gm_sys_collectName"; - std::string documentVirtual31 = "{\"id\" : \"24_4\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_CreateCollect(g_datatest, collectName5.c_str(), "", 0); - GRD_InsertDocument(g_datatest, collectName5.c_str(), documentVirtual31.c_str(), 0); - - collectName5 = "gM_sYs_collectName"; - std::string documentVirtual32 = "{\"id\" : \"24_5\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_CreateCollect(g_datatest, collectName5.c_str(), "", 0); - GRD_InsertDocument(g_datatest, collectName5.c_str(), documentVirtual32.c_str(), 0); - - collectName5 = "gRd_collectName"; - std::string documentVirtual33 = "{\"id\" : \"24_6\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_CreateCollect(g_datatest, collectName5.c_str(), "", 0); - GRD_InsertDocument(g_datatest, collectName5.c_str(), documentVirtual33.c_str(), 0); - - collectName5 = "gRd@collectName"; - std::string documentVirtual34 = "{\"id\" : \"24_7\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_CreateCollect(g_datatest, collectName5.c_str(), "", 0); - GRD_InsertDocument(g_datatest, collectName5.c_str(), documentVirtual34.c_str(), 0); - - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual35.c_str(), 0); - - std::string documentVirtual36 = "{\"id\" : \"36_4\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_CreateCollect(g_datatest, collectName5.c_str(), "", 0); - GRD_InsertDocument(g_datatest, collectName5.c_str(), documentVirtual36.c_str(), 0); - - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual36.c_str(), 0); - std::string documentVirtual37 = "{\"id\" : \"37_4\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual37.c_str(), 0); - std::string documentVirtual38 = "{\"id\" : \"38_8\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual38.c_str(), 0); -} - -void InsertDocFourFuzzTest(const std::string &longId, const std::string &documentVirtualData) -{ - std::string documentVirtual39 = - "{\"id\" : \"35\", \"A_aBdk_324_\" : \"" + documentVirtualData + - "\", \"name\" : \"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual39.c_str(), 0); - - std::string documentVirtual40 = "{\"id\" : \"35_2\", \"1A_aBdk_324_\" : \"" + documentVirtualData + - "\", " - "\"name\" : \"" + - documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual40.c_str(), 0); - std::string documentVirtual41 = "{\"id\" : \"36_0\", \"stringType\" : \"" + documentVirtualData + - documentVirtualData + ", \"objectType\" : {\"A\" : 3}}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual41.c_str(), 0); - - std::string documentVirtual42 = "({\"id\" : \"38_0\", \"field2\" : 1.7693" + longId + "13486232e308})"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual42.c_str(), 0); - std::string documentVirtual43 = - "({\"id\" : \"38_1\", \"t1\" : {\"field2\" : 1.797" + longId + "693134862e308}})"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual43.c_str(), 0); - std::string documentVirtual44 = "({\"id\" : \"38_2\", \"t1\" : [1, 2, 1.797313486" + longId + "232e308]})"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual44.c_str(), 0); - std::string documentVirtual45 = "({\"id\" : \"38_3\", \"t1\" : [1, 2, -1.79763486167" + longId + "E+308]})"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual45.c_str(), 0); - std::string documentVirtual46 = - "({\"id\" : \"38_4\", \"t1\" : [1, 2, -1." + longId + "79763486231570E+308]})"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual46.c_str(), 0); - std::string documentVirtual47 = - "({\"id\" : \"38_5\", \"t1\" : [1, 2, 1.79769313486" + longId + "2370E+308]})"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual47.c_str(), 0); - - std::string doc1 = "{\"id\" : "; - std::string doc2 = "\""; - std::string doc4 = "\""; - std::string doc5 = ", \"name\" : \"" + documentVirtualData + "\"}"; - std::string documentVirtualMiddle(MIDDLE_SIZE_TEST, 'k'); - std::string documentVirtual48 = doc1 + doc2 + documentVirtualMiddle + doc4 + doc5; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual48.c_str(), 0); - std::string documentVirtualMiddle2(MAX_SIZE_NUM_TEST, 'k'); - documentVirtual48 = doc1 + doc2 + documentVirtualMiddle2 + doc4 + doc5; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual48.c_str(), 0); - - std::string documentVirtual49 = "({\"id\":\"0123\", \"num\":\"" + documentVirtualData + "\"})"; - std::string documentVirtual50 = "({\"id\":\"0123\", \"NUM\":\"" + documentVirtualData + "\"})"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual49.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual50.c_str(), 0); - - std::string documentVirtual51 = "({\"id\":\"0123\", \"num.\":\"" + documentVirtualData + "\"})"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual51.c_str(), 0); - - const char *documentVirtual52 = R""({})""; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual52, 0); -} - -void InsertDocFuzzTest(const uint8_t *data, size_t size) -{ - std::string collectNameData(reinterpret_cast(data), size); - const char *collectNameVal = collectNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); - const char *optionStrVal = optionStrData.data(); - GRD_CreateCollect(g_datatest, collectNameVal, optionStrVal, 0); - std::string documentVirtualData(reinterpret_cast(data), size); - const char *documentVirtualVal = documentVirtualData.data(); - GRD_InsertDocument(g_datatest, collectNameVal, documentVirtualVal, 0); - GRD_InsertDocument(g_datatest, collectNameVal, documentVirtualVal, 0); - std::string strJson = "{" + documentVirtualData + "}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, strJson.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, strJson.c_str(), 0); - std::string stringJson2 = "{\"id\":\"1\",\"field\":\"" + documentVirtualData + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, stringJson2.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, stringJson2.c_str(), 0); - std::string longId = "1"; - for (int i = 0; i < MAX_SIZE_NUM_TEST; i++) { - longId += "1"; - } - longId = "{\"id\":\"" + longId + "\",\"field\":\"field_id\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, longId.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, "{\"id\":123}", 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, "{\"field1.field2.field&*^&3\":\"anc\"}", 0); - InsertDocOneFuzzTest(documentVirtualData); - InsertDocTwoFuzzTest(documentVirtualData); - InsertDocThreeFuzzTest(documentVirtualData); - InsertDocFourFuzzTest(longId, documentVirtualData); - - const char *documentVirtual53 = R""({"empty" : null})""; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual53, 0); - GRD_DropCollect(g_datatest, collectNameVal, 0); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - - std::string documentVirtualNew1 = "{\"id\" : "; - std::string documentVirtualNew2 = "\""; - std::string documentVirtualNew3 = "\""; - std::string documentVirtualNew4 = ", \"name\" : \"Ori\"}"; - std::string documentVirtual = documentVirtualNew1 + - documentVirtualNew2 + documentVirtualData + documentVirtualNew3 + documentVirtualNew4; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual.c_str(), 0); -} - -static const char *DOCU1 = "{\"id\" : \"1\", \"name\":\"doc1\",\"item\":\"journal\",\"person\":\ - {\"school\":\"AB\", \"age\" : 51}}"; -static const char *DOCU2 = "{\"id\" : \"2\", \"name\":\"doc2\",\"item\": 1, \"person\":\ - [1, \"my string\", {\"school\":\"AB\", \"age\" : 51}, true, {\"school\":\"CD\", \"age\" : 15}, false]}"; -static const char *DOCU3 = "{\"id\" : \"3\", \"name\":\"doc3\",\"item\":\"notebook\",\"person\":\ - [{\"school\":\"C\", \"age\" : 5}]}"; -static const char *DOCU4 = "{\"id\" : \"4\", \"name\":\"doc4\",\"item\":\"paper\",\"person\":\ - {\"grade\" : 1, \"school\":\"A\", \"age\" : 18}}"; -static const char *DOCU5 = "{\"id\" : \"5\", \"name\":\"doc5\",\"item\":\"journal\",\"person\":\ - [{\"sex\" : \"woma\", \"school\" : \"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; -static const char *DOCU6 = "{\"id\" : \"6\", \"name\":\"doc6\",\"item\":false,\"person\":\ - [{\"school\":\"B\", \"teacher\" : \"mike\", \"age\" : 15},\ - {\"school\":\"C\", \"teacher\" : \"moon\", \"age\" : 20}]}"; - -static const char *DOCU7 = "{\"id\" : \"7\", \"name\":\"doc7\",\"item\":\"fruit\",\"other_Info\":\ - [{\"school\":\"BX\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; -static const char *DOCU8 = "{\"id\" : \"8\", \"name\":\"doc8\",\"item\":true,\"person\":\ - [{\"school\":\"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; -static const char *DOCU9 = "{\"id\" : \"9\", \"name\":\"doc9\",\"item\": true}"; -static const char *DOCU10 = "{\"id\" : \"10\", \"name\":\"doc10\", \"parent\" : \"kate\"}"; -static const char *DOCU11 = "{\"id\" : \"11\", \"name\":\"doc11\", \"other\" : \"null\"}"; -static const char *DOCU12 = "{\"id\" : \"12\", \"name\":\"doc12\",\"other\" : null}"; -static const char *DOCU13 = "{\"id\" : \"13\", \"name\":\"doc13\",\"item\" : \"shoes\",\"person\":\ - {\"school\":\"AB\", \"age\" : 15}}"; -static const char *DOCU14 = "{\"id\" : \"14\", \"name\":\"doc14\",\"item\" : true,\"person\":\ - [{\"school\":\"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 85}]}"; -static const char *DOCU15 = "{\"id\" : \"15\", \"name\":\"doc15\",\"person\":[{\"school\":\"C\", \"age\" : " - "5}]}"; -static const char *DOCU16 = "{\"id\" : \"16\", \"name\":\"doc16\", \"nested1\":{\"nested2\":{\"nested3\":\ - {\"nested4\":\"ABC\", \"field2\":\"CCC\"}}}}"; -static const char *DOCU17 = "{\"id\" : \"17\", \"name\":\"doc17\",\"person\":\"oh,ok\"}"; -static const char *DOCU18 = "{\"id\" : \"18\", \"name\":\"doc18\",\"item\" : \"mobile phone\",\"person\":\ - {\"school\":\"DD\", \"age\":66}, \"color\":\"blue\"}"; -static const char *DOCU19 = "{\"id\" : \"19\", \"name\":\"doc19\",\"ITEM\" : true,\"PERSONINFO\":\ - {\"school\":\"AB\", \"age\":15}}"; -static const char *DOCU20 = "{\"id\" : \"20\", \"name\":\"doc20\",\"ITEM\" : true,\"person\":\ - [{\"SCHOOL\":\"B\", \"AGE\":15}, {\"SCHOOL\":\"C\", \"AGE\":35}]}"; -static const char *DOCU23 = "{\"id\" : \"23\", \"name\":\"doc22\",\"ITEM\" : " - "true,\"person\":[{\"school\":\"b\", \"age\":15}, [{\"school\":\"doc23\"}, 10, " - "{\"school\":\"doc23\"}, true, {\"school\":\"y\"}], {\"school\":\"b\"}]}"; -static std::vector g_datatest = { DOCU1, DOCU2, DOCU3, DOCU4, DOCU5, - DOCU6, DOCU7, DOCU8, DOCU9, DOCU10, DOCU11, DOCU12, DOCU13, - DOCU14, DOCU15, DOCU16, DOCU17, DOCU18, DOCU19, DOCU20, DOCU23 }; - -namespace { -static void InsertData(GRD_DB *g_datatest, const char *collectName) -{ - for (const auto &item : g_datatest) { - GRD_InsertDocument(g_datatest, collectName, item, 0); - } -} - -void SetUpTestCase() -{ - (void)RemoveDirTest(TEST_DB); - MakeDirctionary(TEST_DB); - GRD_DBOpen(TEST_FILE, CONFIG_STRING, GRD_OPEN_CREATE, &g_datatest); - InsertData(g_datatest, COLLECT_NAME); - GRD_CreateCollect(g_datatest, COLLECT_NAME, OPTION_STRING, 0); -} - -void TearDownTestCase() -{ - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - GRD_DBClose(g_datatest, GRD_CLOSE); - (void)RemoveDirTest(TEST_DB); - g_datatest = nullptr; -} - -void FindDocumentResultSetFuzzTest(const char *colName, const std::string &filt, const std::string &projectInfo) -{ - GRD_ResultSet *reSet = nullptr; - Query query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, colName, query, 1, &reSet); - if (reSet != nullptr) { - GRD_Next(reSet); - char *valueResult = nullptr; - GRD_GetVal(reSet, &valueResult); - } - GRD_FreeRe(reSet); -} - -void FindDocumentWithFlagFuzzTest(const std::string &filt, const std::string &projectInfo, int flag) -{ - GRD_ResultSet *reSet = nullptr; - Query query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, flag, &reSet); - GRD_Next(reSet); - char *value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); -} - -void FindDocumentNextTwiceFuzzTest(const std::string &filt, const std::string &projectInfo) -{ - GRD_ResultSet *reSet = nullptr; - Query query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_Next(reSet); - GRD_Next(reSet); - char *value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); -} - -void FindDocumentZeroFuzzTest(const std::string &input) -{ - std::string filt = "{\"id\" : \"6\"}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - filt = "{\"id\" : \"6\", \"name\":\"" + input + "\"}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - filt = "{\"name\":\"" + input + "\"}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - filt = "{\"id\" : \"" + input + "\"}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - filt = "{\"id\" : 1}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - filt = "{\"id\" : [\"" + input + "\", 1]}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - filt = "{\"id\" : {\"" + input + "\" : \"1\"}}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - filt = "{\"id\" : true}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - filt = "{\"id\" : null}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - - const char *colName1 = "grd_type"; - const char *colName2 = "GM_SYS_sysfff"; - filt = "{\"id\" : \"1\"}"; - FindDocumentResultSetFuzzTest(colName1, filt, R"({})"); - FindDocumentResultSetFuzzTest(colName2, filt, R"({})"); - - filt = "{\"id\" : \"100\"}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); -} - -void FindDocumentOneFuzzTest() -{ - std::string filt = "{\"id\" : \"6\"}"; - GRD_ResultSet *reSet = nullptr; - GRD_ResultSet *reSet2 = nullptr; - Query query = { filt.c_str(), "{}" }; - const char *collectName = "DocumentDBFindTest024"; - GRD_CreateCollect(g_datatest, collectName, "", 0); - InsertData(g_datatest, collectName); - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_FindDocument(g_datatest, collectName, query, 1, &reSet2); - - GRD_Next(reSet); - char *value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - - GRD_Next(reSet2); - char *value2 = nullptr; - GRD_GetVal(reSet2, &value2); - GRD_FreeVal(value2); - - GRD_Next(reSet); - GRD_Next(reSet2); - GRD_GetVal(reSet, &value); - GRD_GetVal(reSet2, &value); - GRD_FreeRe(reSet); - GRD_FreeRe(reSet2); - GRD_DropCollect(g_datatest, collectName, 0); - - filt = "{\"id\" : \"16\"}"; - reSet = nullptr; - std::string projectInfo = "{\"name\": true, \"nested1.nested2.nested3.nested4\":true}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_Next(reSet); - value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - GRD_FreeRe(reSet); - - projectInfo = "{\"name\": true, \"nested1\":{\"nested2\":{\"nested3\":{\"nested4\":true}}}}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - GRD_FreeRe(reSet); -} - -void FindDocumentTwoFuzzTest(const std::string &input) -{ - GRD_ResultSet *reSet = nullptr; - std::string projectInfo = "{\"name\": 0, \"nested1.nested2.nested3.nested4\":0}"; - std::string filt = "{\"id\" : \"16\"}"; - Query query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_Next(reSet); - char *value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); - - projectInfo = "{\"name\": \"" + input + "\", \"nested1.nested2.nested3.nested4\":\"" + input + "\"}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, projectInfo); - - filt = "{\"id\" : \"7\"}"; - reSet = nullptr; - projectInfo = "{\"name\": true, \"other_Info\":true, \"non_exist_field\":true}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_Next(reSet); - value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); - - projectInfo = "{\"name\": true, \"other_Info\":true, \" item \":true}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, projectInfo); -} - -void FindDocumentThreeFuzzTest(const std::string &input) -{ - std::string filt = "{\"id\" : \"7\"}"; - GRD_ResultSet *reSet = nullptr; - std::string projectInfo = "{\"name\": true, \"other_Info.non_exist_field\":true}"; - Query query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_Next(reSet); - char *value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); - projectInfo = "{\"name\": true, \"other_Info\":{\"non_exist_field\":true}}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, projectInfo); - projectInfo = "{\"name\": true, \"other_Info.0\": true}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, projectInfo); - filt = "{\"id\" : \"4\"}"; - reSet = nullptr; - projectInfo = "{\"person\": true, \"person.grade\": true}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - - filt = "{\"id\" : \"7\"}"; - projectInfo = "{\"non_exist_field\":true}"; - int flag = 0; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - flag = 1; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - filt = "{\"id\" : \"7\"}"; - projectInfo = "{\"name\":true, \"item\":true}"; - flag = 0; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - flag = 1; - projectInfo = "{\"name\": " + input + ", \"item\": " + input + "}"; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - filt = "{\"id\" : \"7\"}"; - projectInfo = "{\"name\":false, \"item\":false}"; - flag = 0; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - flag = 1; - projectInfo = "{\"name\": " + input + ", \"item\": " + input + "}"; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - filt = "{\"id\" : \"4\"}"; - flag = 0; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - projectInfo = "{\"name\": false, \"person.grade1\": false, \ - \"person.shool1\": false, \"person.age1\": false}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, projectInfo); -} - -void FindDocumentFourFuzzTest(const std::string &input) -{ - std::string filt = "{\"id\" : \"4\"}"; - std::string projectInfo = - "{\"name\": " + input + ", \"person.school\": " + input + ", \"person.age\": " + input + "}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, projectInfo); - - filt = "{\"id\" : \"17\"}"; - GRD_ResultSet *reSet = nullptr; - Query query = { filt.c_str(), "{}" }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, GRD_DOC_ID_DISPLAY, &reSet); - GRD_Next(reSet); - char *value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - GRD_FreeRe(reSet); - - reSet = nullptr; - query = { filt.c_str(), "{}" }; - GRD_FindDocument(g_datatest, "", query, 0, &reSet); - GRD_FindDocument(g_datatest, nullptr, query, 0, &reSet); - - filt = "{\"id\" : \"4\"}"; - reSet = nullptr; - projectInfo = "{\"name\":" + input + ", \"person\":0, \"item\":" + input + "}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - - projectInfo = "{\"name\":true, \"person\":0, \"item\":true}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - - projectInfo = "{\"name\":\"\", \"person\":0, \"item\":\"\"}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - - projectInfo = "{\"name\":false, \"person\":1, \"item\":false"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - - projectInfo = "{\"name\":false, \"person\":-1.123, \"item\":false"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - - projectInfo = "{\"name\":false, \"person\":true, \"item\":false"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); -} - -void FindDocumentFiveFuzzTest(const std::string &input) -{ - std::string filt = "{\"id\" : \"6\"}"; - std::string projectInfo = "{\"name\":false, \"person\": 0, \"item\":0}"; - int flag = 0; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - - filt = "{\"id\" : \"18\"}"; - projectInfo = "{\"name\":true, \"person.age\": \"\", \"item\":1, \"color\":10, \"nonExist\" : " - "-100}"; - flag = 0; - FindDocumentWithFlagFuzzTest(filt, projectInfo, flag); - - GRD_ResultSet *reSet = nullptr; - projectInfo = "{\"person\":[true, " + input + "]}"; - flag = 1; - Query query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, flag, &reSet); - projectInfo = "{\"person\":null}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, flag, &reSet); - reSet = nullptr; - projectInfo = "{\"Name\":true, \"person.age\": \"\", \"item\":" + input + ", \"COLOR\":" + input + - ", \"nonExist\" : " - "" + - input + "}"; - flag = 0; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, flag, &reSet); - GRD_Next(reSet); - GRD_FreeRe(reSet); - - reSet = nullptr; - projectInfo = "{\"Name\":" + input + ", \"person.age\": false, \"person.SCHOOL\": false, \"item\":\ - false, \"COLOR\":false, \"nonExist\" : false}"; - query = { filt.c_str(), projectInfo.c_str() }; - char *value = nullptr; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_Next(reSet); - GRD_FreeRe(reSet); - - filt = "{\"id\" : \"18\"}"; - reSet = nullptr; - query = { filt.c_str(), "{}" }; - std::string collectName1(LESS_HALF_BYTES, 'a'); - GRD_FindDocument(g_datatest, collectName1.c_str(), query, 1, &reSet); - GRD_FreeRe(reSet); -} - -void FindDocumentSixFuzzTest(const std::string &input) -{ - std::string collectName2(HALF_BYTES, 'a'); - std::string filt = "{\"id\" : \"18\"}"; - Query query = { filt.c_str(), "{}" }; - GRD_ResultSet *reSet = nullptr; - GRD_FindDocument(g_datatest, collectName2.c_str(), query, 1, &reSet); - GRD_FindDocument(g_datatest, "", query, 1, &reSet); - - reSet = nullptr; - std::string projectInfo = "{}"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, NUM_THREE, &reSet); - GRD_FindDocument(g_datatest, COLLECT_NAME, query, INT_MAX, &reSet); - GRD_FindDocument(g_datatest, COLLECT_NAME, query, INT_MIN, &reSet); - GRD_FindDocument(nullptr, COLLECT_NAME, query, 0, &reSet); - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, nullptr); - query = { nullptr, nullptr }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - - std::string documentVirtual1 = "{\"id\" : "; - std::string documentVirtual2 = "\""; - std::string documentVirtual4 = "\""; - std::string documentVirtual5 = "}"; - std::string documentVirtualMiddle(MIDDLE_SIZE_TEST, 'k'); - filt = documentVirtual1 + documentVirtual2 + documentVirtualMiddle + documentVirtual4 + documentVirtual5; - reSet = nullptr; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - std::string documentVirtualMiddle2(LESS_MIDDLE_SIZE_TEST, 'k'); - filt = documentVirtual1 + documentVirtual2 + documentVirtualMiddle2 + documentVirtual4 + documentVirtual5; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_FreeRe(reSet); - - filt = "{\"person\" : {\"school\":\"" + input + "\"}}"; - FindDocumentNextTwiceFuzzTest(filt, R"({})"); - - projectInfo = "{\"version\": " + input + "}"; - FindDocumentNextTwiceFuzzTest(filt, projectInfo); - - projectInfo = "({\"a00001\":" + input + ", \"a00001\":" + input + "})"; - FindDocumentNextTwiceFuzzTest(filt, projectInfo); - - projectInfo = "({\"abc123_.\":" + input + "})"; - FindDocumentNextTwiceFuzzTest(filt, projectInfo); - - filt = "({\"abc123_.\":" + input + "})"; - FindDocumentNextTwiceFuzzTest(filt, projectInfo); -} - -void FindDocumentSevenFuzzTest(const std::string &input) -{ - std::string documentVirtual064 = "{\"id\" : \"64\", \"a\":" + input + ", \"doc64\" : " + input + "}"; - std::string documentVirtual063 = "{\"id\" : \"63\", \"a\":" + input + ", \"doc63\" : " + input + "}"; - std::string documentVirtual062 = "{\"id\" : \"62\", \"a\":" + input + ", \"doc62\" : " + input + "}"; - std::string documentVirtual061 = "{\"id\" : \"61\", \"a\":" + input + ", \"doc61\" : " + input + "}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual064.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual063.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual062.c_str(), 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual061.c_str(), 0); - std::string filt = "{\"a\":" + input + "}"; - GRD_ResultSet *reSet = nullptr; - std::string projectInfo = R"({})"; - Query query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_Next(reSet); - char *value = nullptr; - GRD_GetVal(reSet, &value); - - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); -} - -void FindDocumentFuzzTestPlus(const std::string &input) -{ - FindDocumentZeroFuzzTest(input); - std::string filt = "{\"id\" : \"6\"}"; - FindDocumentResultSetFuzzTest(COLLECT_NAME, filt, R"({})"); - FindDocumentOneFuzzTest(); - FindDocumentTwoFuzzTest(input); - FindDocumentThreeFuzzTest(input); - FindDocumentFourFuzzTest(input); - FindDocumentFiveFuzzTest(input); - FindDocumentSixFuzzTest(input); - FindDocumentSevenFuzzTest(input); - - std::string documentVirtual = "{\"a\":" + input + ", \"doc64\" : " + input + "}"; - filt = "{\"b\":" + input + "}"; - GRD_Upsert(g_datatest, COLLECT_NAME, filt.c_str(), documentVirtual.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, filt.c_str(), documentVirtual.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, filt.c_str(), documentVirtual.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, filt.c_str(), documentVirtual.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, filt.c_str(), documentVirtual.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, filt.c_str(), documentVirtual.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, filt.c_str(), documentVirtual.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, filt.c_str(), documentVirtual.c_str(), 0); - filt = "{\"a\":" + input + "}"; - GRD_ResultSet *reSet = nullptr; - std::string projectInfo = R"({})"; - Query query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_Next(reSet); - GRD_Next(reSet); - GRD_Next(reSet); - GRD_Next(reSet); - GRD_Next(reSet); - GRD_Next(reSet); - GRD_Next(reSet); - GRD_Next(reSet); - GRD_Next(reSet); - GRD_FreeRe(reSet); - filt = "{\"a\":" + input + "}"; - reSet = nullptr; - projectInfo = R"({})"; - query = { filt.c_str(), projectInfo.c_str() }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - GRD_Next(reSet); - char *valueNew = nullptr; - GRD_GetVal(reSet, &valueNew); - GRD_FreeVal(valueNew); - GRD_FreeRe(reSet); - filt = "{\"person\" : {\"school\":" + input + "}" + "}"; - FindDocumentNextTwiceFuzzTest(filt, R"({})"); -} -} // namespace - -void FindDocumentFuzzTest(const uint8_t *data, size_t size) -{ - GRD_CreateCollect(g_datatest, COLLECT_NAME, OPTION_STRING, 0); - std::string input(reinterpret_cast(data), size); - std::string inputJson11 = "{\"field\":\"" + input + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - Query query = { inputJson11.c_str(), inputJson11.c_str() }; - GRD_ResultSet *reSet = nullptr; - // ResultSet conflict - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_FreeRe(reSet); - reSet = nullptr; - GRD_FindDocument(g_datatest, input.c_str(), query, size, &reSet); - GRD_FreeRe(reSet); - GRD_FindDocument(nullptr, input.c_str(), query, 1, &reSet); - query.filt = nullptr; - GRD_FindDocument(g_datatest, input.c_str(), query, 1, &reSet); - inputJson11 = "{\"field\": 0, \"field2\":" + input + "}"; - query.filt = "{}"; - query.project = inputJson11.c_str(); - reSet = nullptr; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_FreeRe(reSet); - inputJson11 = "{\"" + input + "\": 0}"; - query.project = inputJson11.c_str(); - reSet = nullptr; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_FreeRe(reSet); - inputJson11 = "{\"field\":[\"aaa\"," + input + "]}"; - reSet = nullptr; - query.project = inputJson11.c_str(); - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_FreeRe(reSet); - query.filt = "{\"field\": false}"; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_FreeRe(reSet); - FindDocumentFuzzTestPlus(input); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); -} - -void UpdateDocOneFuzzTest(std::string s, const std::string &input) -{ - std::string inputJson11 = "{\"field5\": \"" + s + "\"}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field5\": \"" + s + s + "\"}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1\": [\"field2\", {\"field3\":\"" + input + "\"}]}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"name\":\"doc6\", \"c0\" : {\"c1\" : true } }"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"name\":\"doc6\"}", inputJson11.c_str(), 1); - inputJson11 = "{\"name\":\"doc7\", \"c0\" : {\"c1\" : null } }"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"name\":\"doc7\"}", inputJson11.c_str(), 1); - inputJson11 = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"name\":\"doc8\"}", inputJson11.c_str(), 1); - - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - GRD_UpDoc(g_datatest, inputJson11.c_str(), "{}", "{}", 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, input.c_str(), "{}", 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, "{}", input.c_str(), 0); - GRD_UpDoc(nullptr, COLLECT_NAME, "{}", "{}", 0); - inputJson11 = "{\"id\":\"2\", \"field\":" + input + "}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field\":" + input + "}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1.field2.field3.field4.field5.field6\":" + input + "}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1\": {\"field2\": {\"field3\": {\"field4\": {\"field5\":" + input + "}}}}}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - s.clear(); - for (int i = 0; i < ((ONE_BYTES * ONE_BYTES) - 1) - NUM_FIFTEEN; i++) { - s += 'a'; - } - inputJson11 = "{\"field5\": \"" + s + "\"}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field5\": \"" + s + s + "\"}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1\": [\"field2\", {\"field3\":\"" + input + "\"}]}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"name\":\"doc6\", \"c0\" : {\"c1\" : true } }"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"name\":\"doc6\"}", "{\"c0.c1\":false}", 1); - inputJson11 = "{\"name\":\"doc7\", \"c0\" : {\"c1\" : null } }"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"name\":\"doc7\"}", "{\"c0.c1\":null}", 1); - inputJson11 = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"name\":\"doc8\"}", "{\"c0.0\":\"ac\"}", 1); -} - -void UpdateDocTwoFuzzTest(const char *newCollName, std::string s, const std::string &input) -{ - std::string inputJson11 = "{\"field5\": \"" + s + "\"}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field5\": \"" + s + s + "\"}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1\": [\"field2\", {\"field3\":\"" + input + "\"}]}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"name\":\"doc6\", \"c0\" : {\"c1\" : true } }"; - GRD_UpDoc(g_datatest, newCollName, "{\"name\":\"doc6\"}", inputJson11.c_str(), 1); - inputJson11 = "{\"name\":\"doc7\", \"c0\" : {\"c1\" : null } }"; - GRD_UpDoc(g_datatest, newCollName, "{\"name\":\"doc7\"}", inputJson11.c_str(), 1); - inputJson11 = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; - GRD_UpDoc(g_datatest, newCollName, "{\"name\":\"doc8\"}", inputJson11.c_str(), 1); - - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - GRD_UpDoc(g_datatest, inputJson11.c_str(), "{}", "{}", 0); - GRD_UpDoc(g_datatest, newCollName, input.c_str(), "{}", 0); - GRD_UpDoc(g_datatest, newCollName, "{}", input.c_str(), 0); - GRD_UpDoc(nullptr, newCollName, "{}", "{}", 0); - inputJson11 = "{\"id\":\"2\", \"field\":" + input + "}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field\":" + input + "}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1.field2.field3.field4.field5.field6\":" + input + "}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1\": {\"field2\": {\"field3\": {\"field4\": {\"field5\":" + input + "}}}}}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - s.clear(); - for (int i = 0; i < ((ONE_BYTES * ONE_BYTES) - 1) - NUM_FIFTEEN; i++) { - s += 'a'; - } - inputJson11 = "{\"field5\": \"" + s + "\"}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field5\": \"" + s + s + "\"}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1\": [\"field2\", {\"field3\":\"" + input + "\"}]}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"name\":\"doc6\", \"c0\" : {\"c1\" : true } }"; - GRD_InsertDocument(g_datatest, newCollName, inputJson11.c_str(), 0); - GRD_UpDoc(g_datatest, newCollName, "{\"name\":\"doc6\"}", "{\"c0.c1\":false}", 1); - inputJson11 = "{\"name\":\"doc7\", \"c0\" : {\"c1\" : null } }"; - GRD_InsertDocument(g_datatest, newCollName, inputJson11.c_str(), 0); - GRD_UpDoc(g_datatest, newCollName, "{\"name\":\"doc7\"}", "{\"c0.c1\":null}", 1); - inputJson11 = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; - GRD_InsertDocument(g_datatest, newCollName, inputJson11.c_str(), 0); - GRD_UpDoc(g_datatest, newCollName, "{\"name\":\"doc8\"}", "{\"c0.0\":\"ac\"}", 1); -} - -void UpdateDocFilterFuzzTest() -{ - const char *filt = "{\"id\" : \"1\"}"; - const char *updata2 = "{\"objectInfo.child.child\" : {\"child\":{\"child\":null}}}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, filt, updata2, 0); - - const char *filt1 = "{\"id\" : \"1\"}"; - const char *updata1 = "{\"id\" : \"6\"}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, filt1, updata1, 0); - - const char *filt2 = "{\"id\" : \"1\"}"; - const char *updata3 = "{\"age$\" : \"21\"}"; - const char *updata4 = "{\"bonus..traffic\" : 100}"; - const char *updata5 = "{\"0item\" : 100}"; - const char *updata6 = "{\"item\" : 1.79769313486232e308}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, filt2, updata3, 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, filt2, updata4, 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, filt2, updata5, 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, filt2, updata6, 0); - - const char *filt3 = "{\"id\" : \"1\"}"; - const char *updata7 = "{\"age\" : 21}"; - GRD_UpDoc(g_datatest, NULL, filt3, updata7, 0); - GRD_UpDoc(g_datatest, "", filt3, updata7, 0); - GRD_UpDoc(NULL, COLLECT_NAME, filt3, updata7, 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, NULL, updata7, 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, filt3, NULL, 0); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); -} - -void UpdateDocFuzzTest(const uint8_t *data, size_t size) -{ - GRD_CreateCollect(g_datatest, COLLECT_NAME, OPTION_STRING, 0); - std::string input(reinterpret_cast(data), size); - std::string inputJson11 = "{\"id\":\"2\", \"field\": \"aaa\", " - "\"subject\":\"aaaaaaaaaaa\", \"test1\": true, " - "\"test2\": null}"; - - GRD_UpDoc(g_datatest, inputJson11.c_str(), "{}", "{}", 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, input.c_str(), "{}", 0); - GRD_UpDoc(g_datatest, COLLECT_NAME, "{}", input.c_str(), 0); - GRD_UpDoc(nullptr, COLLECT_NAME, "{}", "{}", 0); - inputJson11 = "{\"id\":\"2\", \"field\":" + input + "}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field\":" + input + "}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1.field2.field3.field4.field5.field6\":" + input + "}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1\": {\"field2\": {\"field3\": {\"field4\": {\"field5\":" + input + "}}}}}"; - GRD_UpDoc(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - std::string s; - for (int i = 0; i < ((ONE_BYTES * ONE_BYTES) - 1) - NUM_FIFTEEN; i++) { - s += 'a'; - } - UpdateDocOneFuzzTest(s, input); - - const char *newCollName = "./student"; - GRD_UpDoc(g_datatest, inputJson11.c_str(), "{}", "{}", 0); - GRD_UpDoc(g_datatest, newCollName, input.c_str(), "{}", 0); - GRD_UpDoc(g_datatest, newCollName, "{}", input.c_str(), 0); - GRD_UpDoc(nullptr, newCollName, "{}", "{}", 0); - inputJson11 = "{\"id\":\"2\", \"field\":" + input + "}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field\":" + input + "}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1.field2.field3.field4.field5.field6\":" + input + "}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field1\": {\"field2\": {\"field3\": {\"field4\": {\"field5\":" + input + "}}}}}"; - GRD_UpDoc(g_datatest, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - s.clear(); - for (int i = 0; i < ((ONE_BYTES * ONE_BYTES) - 1) - NUM_FIFTEEN; i++) { - s += 'a'; - } - - UpdateDocTwoFuzzTest(newCollName, s, input); - UpdateDocFilterFuzzTest(); -} - -void UpsertNewFuzzTest(const std::string &input, GRD_DB *db1) -{ - GRD_CreateCollect(g_datatest, "student", "", 0); - std::string documentVirtualNew = - "{\"name\": {\"first\":[\"XXX\", \"BBB\", \"CCC\"], \"last\":\"moray\", \"field\":" + input + "}"; - std::string updateDocNew = R""({"name.last.AA.B":"Mnado"})""; - GRD_Upsert(g_datatest, "student", R""({"id":"10001"})"", documentVirtualNew.c_str(), 0); - GRD_Upsert(db1, "student", R""({"id":"10001"})"", updateDocNew.c_str(), 1); - GRD_DropCollect(g_datatest, "student", 0); - - GRD_CreateCollect(g_datatest, "student", "", 0); - documentVirtualNew = "{\"name\":[\"Tmn\", \"BB\", \"Alice\"], \"field\":" + input + "}"; - updateDocNew = R""({"name.first":"GG"})""; - GRD_Upsert(g_datatest, "student", R""({"id":"10002"})"", documentVirtualNew.c_str(), 0); - GRD_Upsert(db1, "student", R""({"id":"10002"})"", updateDocNew.c_str(), 1); -} - -void UpsertFuzzTest(const uint8_t *data, size_t size) -{ - GRD_CreateCollect(g_datatest, COLLECT_NAME, OPTION_STRING, 0); - std::string input(reinterpret_cast(data), size); - std::string inputJson11NoId = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; - std::string inputJson11 = "{\"id\":\"1\", \"field\": " + input + "}"; - - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - GRD_Upsert(g_datatest, input.c_str(), "{}", "{}", 0); - GRD_Upsert(g_datatest, COLLECT_NAME, inputJson11.c_str(), "{}", 0); - inputJson11 = "{\"id\":\"1\", \"field\":" + input + "}"; - GRD_Upsert(g_datatest, COLLECT_NAME, "{\"id\":\"1\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"id\":\"1\", \"field\":\"" + input + "\"}"; - GRD_Upsert(g_datatest, COLLECT_NAME, "{\"id\":\"1\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field\":" + input + "}"; - GRD_Upsert(g_datatest, COLLECT_NAME, "{\"id\":\"1\"}", inputJson11.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - GRD_Upsert(g_datatest, COLLECT_NAME, "{\"id\":\"1\"}", inputJson11.c_str(), 1); - GRD_Upsert(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 1); - GRD_Upsert(nullptr, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), 1); - GRD_Upsert(g_datatest, COLLECT_NAME, nullptr, inputJson11.c_str(), 1); - GRD_Upsert(g_datatest, COLLECT_NAME, "{\"id\":\"2\"}", inputJson11.c_str(), BATCH_COUNT); - - const char *newCollName = "./student"; - GRD_DB *db1 = nullptr; - GRD_CreateCollect(db1, newCollName, "", 0); - GRD_InsertDocument(db1, newCollName, inputJson11.c_str(), 0); - GRD_Upsert(db1, input.c_str(), "{}", "{}", 0); - GRD_Upsert(db1, newCollName, inputJson11.c_str(), "{}", 0); - inputJson11 = "{\"id\":\"1\", \"field\":" + input + "}"; - GRD_Upsert(db1, newCollName, "{\"id\":\"1\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"id\":\"1\", \"field\":\"" + input + "\"}"; - GRD_Upsert(db1, newCollName, "{\"id\":\"1\"}", inputJson11.c_str(), 0); - inputJson11 = "{\"field\":" + input + "}"; - GRD_Upsert(db1, newCollName, "{\"id\":\"1\"}", inputJson11.c_str(), 0); - GRD_Upsert(db1, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 0); - GRD_Upsert(db1, newCollName, "{\"id\":\"1\"}", inputJson11.c_str(), 1); - GRD_Upsert(db1, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 1); - GRD_Upsert(db1, newCollName, "{\"id\":\"newID1999\"}", inputJson11NoId.c_str(), 0); - GRD_Upsert(db1, newCollName, "{\"id\":\"newID1999a\"}", inputJson11NoId.c_str(), 1); - GRD_Upsert(nullptr, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), 1); - GRD_Upsert(db1, newCollName, nullptr, inputJson11.c_str(), 1); - GRD_Upsert(db1, newCollName, "{\"id\":\"2\"}", inputJson11.c_str(), BATCH_COUNT); - GRD_DropCollect(db1, newCollName, 0); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - - UpsertNewFuzzTest(input, db1); -} - -void DelDocResultFuzzTest(const std::string &input) -{ - const char *filt = "{\"age\" : 15}"; - GRD_DelDoc(g_datatest, COLLECT_NAME, filt, 0); - const char *filt1 = "{\"id\" : \"1\", \"age\" : 15}"; - GRD_DelDoc(g_datatest, COLLECT_NAME, filt1, 0); - std::string filt2 = "{\"id\" : \"1\", \"name\" : " + input + "}"; - GRD_DelDoc(g_datatest, COLLECT_NAME, filt2.c_str(), 1); - GRD_DelDoc(g_datatest, NULL, filt2.c_str(), 0); - GRD_DelDoc(g_datatest, "", filt2.c_str(), 1); - GRD_DelDoc(g_datatest, COLLECT_NAME, filt2.c_str(), 0); - - const char *filt3 = "{\"id\" : \"1\"}"; - GRD_ResultSet *reSet = nullptr; - Query query = { filt3, "{}" }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_DelDoc(g_datatest, COLLECT_NAME, filt3, 0); - - const char *filt4 = "{\"id\" : \"1\"}"; - std::string collectName1(LESS_HALF_BYTES, 'a'); - GRD_CreateCollect(g_datatest, collectName1.c_str(), "", 0); - GRD_DelDoc(g_datatest, collectName1.c_str(), filt4, 0); - GRD_DropCollect(g_datatest, collectName1.c_str(), 0); - GRD_FreeRe(reSet); - - GRD_DelDoc(NULL, COLLECT_NAME, filt2.c_str(), 0); - GRD_DelDoc(g_datatest, NULL, filt2.c_str(), 0); - GRD_DelDoc(g_datatest, "", filt2.c_str(), 0); - GRD_DelDoc(g_datatest, COLLECT_NAME, NULL, 0); - GRD_DelDoc(g_datatest, COLLECT_NAME, "", 0); - GRD_DelDoc(g_datatest, "notExisted", filt2.c_str(), 0); - - std::vector filtVec = { R"({"id" : 1})", R"({"id":[1, 2]})", R"({"id" : {"t1" : 1}})", - R"({"id":null})", R"({"id":true})", R"({"id" : 1.333})", R"({"id" : -2.0})" }; - for (const auto &item : filtVec) { - GRD_DelDoc(g_datatest, COLLECT_NAME, item.c_str(), 0); - } - GRD_DelDoc(g_datatest, COLLECT_NAME, filt2.c_str(), 0); - - std::string filt5 = "{\"subject.info\" : \"" + input + "\"}"; - reSet = nullptr; - query = { filt2.c_str(), "{}" }; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_DelDoc(g_datatest, COLLECT_NAME, filt5.c_str(), 0); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - GRD_FreeRe(reSet); -} - -void DelDocFuzzTest(const uint8_t *data, size_t size) -{ - GRD_CreateCollect(g_datatest, COLLECT_NAME, OPTION_STRING, 0); - std::string input(reinterpret_cast(data), size); - std::string inputJson11 = "{\"field\":" + input + "}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - GRD_DelDoc(g_datatest, input.c_str(), "{}", 0); - GRD_DelDoc(g_datatest, nullptr, "{}", 0); - std::string longName = ""; - for (int i = 0; i < MORE_HALF_BYTES; i++) { - longName += 'a'; - } - GRD_DelDoc(g_datatest, "grd_name", "{}", 0); - GRD_DelDoc(g_datatest, longName.c_str(), "{}", 0); - GRD_DelDoc(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - inputJson11 = "{\"field1\":" + input + "}"; - GRD_DelDoc(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - inputJson11 = "{\"field\":\"" + input + "\"}"; - GRD_DelDoc(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - inputJson11 = "{\"field1\":\"" + input + "\"}"; - GRD_DelDoc(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - - const char *documentVirtual1 = "{ \ - \"id\" : \"1\", \ - \"name\": \"xiaoming\", \ - \"address\": \"beijing\", \ - \"age\" : 15, \ - \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ - \"subject\": [\"math\", \"English\", \"music\", {\"info\" : \"exam\"}] \ - }"; - const char *documentVirtual2 = "{ \ - \"id\" : \"2\", \ - \"name\": \"ori\", \ - \"address\": \"beijing\", \ - \"age\" : 15, \ - \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ - \"subject\": [\"math\", \"English\", \"music\"] \ - }"; - const char *documentVirtual3 = "{ \ - \"id\" : \"3\", \ - \"name\": \"David\", \ - \"address\": \"beijing\", \ - \"age\" : 15, \ - \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ - \"subject\": [\"Sing\", \"Jump\", \"Rap\", \"BasketBall\"] \ - }"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual1, 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual2, 0); - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual3, 0); - GRD_DelDoc(g_datatest, COLLECT_NAME, "{}", 0); - - DelDocResultFuzzTest(input); -} - -namespace { -void FindAndRelease(Query query) -{ - GRD_ResultSet *reSet = nullptr; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_Next(reSet); - char *value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); - reSet = nullptr; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 0, &reSet); - GRD_Next(reSet); - value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); - - const char *newCollName = "./student"; - reSet = nullptr; - GRD_FindDocument(g_datatest, newCollName, query, 1, &reSet); - GRD_Next(reSet); - value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); - reSet = nullptr; - GRD_FindDocument(g_datatest, newCollName, query, 0, &reSet); - GRD_Next(reSet); - value = nullptr; - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); -} -} // namespace - -void FindAndReleaseFuzzTest(std::string documentVirtual, std::string filt, Query query, const std::string &input) -{ - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual.c_str(), 0); - query.filt = filt.c_str(); - query.project = "{\"field\": 0}"; - FindAndRelease(query); - documentVirtual = "{\"field1.field2\" [false], \"field1.field2.field3\": [3], " - "\"field1.field4\": [null]}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual.c_str(), 0); - query.filt = documentVirtual.c_str(); - query.project = "{\"field\": 0}"; - FindAndRelease(query); - query.project = "{\"field\": 1}"; - FindAndRelease(query); - query.project = "{\"field.field2\": 1}"; - FindAndRelease(query); - documentVirtual = "{\"field1\": {\"field2\": [{\"field3\":\"" + input + "\"}]}}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, documentVirtual.c_str(), 0); - filt = "{\"field1.field2.field3\":\"" + input + "\"}"; - query.filt = filt.c_str(); - query.project = "{\"field1.field2\": 1}"; - FindAndRelease(query); - query.project = "{\"field1.field2\": 0}"; - FindAndRelease(query); - query.project = "{\"field1.field3\": 1}"; - FindAndRelease(query); - query.project = "{\"field1.field3\": 0}"; - FindAndRelease(query); - query.project = "{\"field1.field2.field3\": 0, \"field1.field2.field3\": 0}"; - FindAndRelease(query); - std::string project = "{\"field1\": \"" + input + "\"}"; - query.project = project.c_str(); - FindAndRelease(query); - project = "{\"" + input + "\": true, \"" + input + "\": false}"; - query.project = project.c_str(); - FindAndRelease(query); -} - -void NextFuzzTest(const uint8_t *data, size_t size) -{ - GRD_CreateCollect(g_datatest, COLLECT_NAME, OPTION_STRING, 0); - std::string input(reinterpret_cast(data), size); - std::string inputJson11 = "{" + input + "}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - Query query = { inputJson11.c_str(), "{}" }; - FindAndRelease(query); - std::string stringJson2 = "{ \"id\":\"1\", \"field\":\"" + input + "\"}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, stringJson2.c_str(), 0); - query.filt = "{\"id\": \"1\"}"; - FindAndRelease(query); - std::string filt2 = "{ \"id\":\"1\", \"field\":\"" + input + " invalid\"}"; - query.filt = filt2.c_str(); - FindAndRelease(query); - query.filt = "{\"id\": \"3\"}"; - FindAndRelease(query); - std::string stringJson3 = "{ \"id\":\"2\", \"field\": [\"field2\", null, \"abc\", 123]}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, stringJson3.c_str(), 0); - query.filt = "{\"field\": [\"field2\", null, \"abc\", 123]}"; - FindAndRelease(query); - std::string documentVirtual = "{\"field\": [\"" + input + "\",\"" + input + "\",\"" + input + "\"]}"; - std::string filt = "{\"field." + std::to_string(size) + "\":\"" + input + "\"}"; - FindAndReleaseFuzzTest(documentVirtual, filt, query, input); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); -} - -void GetValueFuzzTest(const uint8_t *data, size_t size) -{ - GRD_CreateCollect(g_datatest, COLLECT_NAME, OPTION_STRING, 0); - std::string input(reinterpret_cast(data), size); - std::string inputJson11 = "{" + input + "}"; - GRD_InsertDocument(g_datatest, COLLECT_NAME, inputJson11.c_str(), 0); - char *value = nullptr; - Query query = { inputJson11.c_str(), "{}" }; - GRD_ResultSet *reSet = nullptr; - GRD_FindDocument(g_datatest, COLLECT_NAME, query, 1, &reSet); - GRD_GetVal(reSet, &value); - GRD_Next(reSet); - GRD_GetVal(reSet, &value); - GRD_FreeVal(value); - GRD_FreeRe(reSet); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); -} - -void FreeReFuzzTest() -{ - GRD_ResultSet *reSet = nullptr; - GRD_FreeRe(reSet); - reSet = new GRD_ResultSet; - reSet->reSet_ = DocumentDB::ResultSet(); - GRD_FreeRe(reSet); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); -} - -void DbOpenCloseFuzzTest(const char *dbFileVal, const char *configStr, GRD_DB *dbVal) -{ - int ret = GRD_DBOpen(dbFileVal, configStr, GRD_OPEN_CREATE, &dbVal); - if (ret == GRD_OK) { - GRD_DBClose(dbVal, GRD_CLOSE); - } -} - -void DbOpenOneFuzzTest(GRD_DB *dbVal) -{ - std::string path = "./documentVirtualFuzzTest.db"; - int ret = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_ONLY, &dbVal); - if (ret == GRD_OK) { - GRD_DBClose(dbVal, GRD_CLOSE); - } - (void)remove(path.c_str()); - - path = "./documentVirtual.db"; - DbOpenCloseFuzzTest(path.c_str(), R""({"pageSize":64, "redopubbufsize":4033})"", dbVal); - DbOpenCloseFuzzTest(path.c_str(), R""({"pageSize":64, "redopubbufsize":4032})"", dbVal); - DbOpenCloseFuzzTest(path.c_str(), R""({"redopubbufsize":255})"", dbVal); - DbOpenCloseFuzzTest(path.c_str(), R""({"redopubbufsize":16385})"", dbVal); -} - -void DbOpenFuzzTestTest(const uint8_t *data, size_t size) -{ - std::string dbFileData(reinterpret_cast(data), size); - std::string realDbFileData = DB_DIR_PATH + dbFileData; - const char *dbFileVal = realDbFileData.data(); - std::string configStrData(reinterpret_cast(data), size); - const char *configStrVal = configStrData.data(); - GRD_DB *dbVal = nullptr; - - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - std::string stringMax = getMaxString(); - const char *configStrMaxLen = stringMax.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrMaxLen, dbVal); - - std::string fieldStringValue = "{\"bufferPoolSize\": \"1024.5\"}"; - const char *configStrStringValue = fieldStringValue.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrStringValue, dbVal); - - std::string fieldBoolValue = "{\"bufferPoolSize\":}"; - const char *configStrBool = fieldBoolValue.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrBool, dbVal); - - std::string fieldStringValueAppend = "{\"bufferPoolSize\":\"8192\"}"; - const char *configStrStr = fieldStringValueAppend.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrStr, dbVal); - - std::string fieldStringValueFlush = "{\"bufferPoolSize\":\"8192\",\"redoFlushBtTrx\":\"1\"}"; - const char *configStrFlush = fieldStringValueFlush.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrFlush, dbVal); - - std::string fieldStringValueRedoBufsize = "{\"bufferPoolSize\":\"8192\",\"redoBufSize\":\"16384\"}"; - const char *configStrBs = fieldStringValueRedoBufsize.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrBs, dbVal); - - std::string fieldStringValueMaxConnNum = "{\"bufferPoolSize\":\"8192\",\"maxConnNum\":\"1024\"}"; - const char *configStrMcn = fieldStringValueMaxConnNum.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrMcn, dbVal); - - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - std::string fieldStringValueAll = "{\"bufferPoolSize\":\"8192\",\"redoFlushBtTrx\":\"1\",\"redoBufSize\":" - "\"16384\",\"maxConnNum\":\"1024\"}"; - const char *configStrAll = fieldStringValueAll.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrAll, dbVal); - - std::string fieldLowNumber = "{\"bufferPoolSize\": 102}"; - const char *configStrLowNumber = fieldLowNumber.data(); - DbOpenCloseFuzzTest(dbFileVal, configStrLowNumber, dbVal); - - int ret = GRD_DBOpen(nullptr, configStrVal, GRD_OPEN_CREATE, &dbVal); - if (ret == GRD_OK) { - GRD_DBClose(nullptr, GRD_CLOSE); - } - DbOpenCloseFuzzTest(dbFileVal, configStrVal, dbVal); - - DbOpenOneFuzzTest(dbVal); -} - -void DbCloseFuzzTest(const uint8_t *data, size_t size) -{ - std::string dbFileData(reinterpret_cast(data), size); - std::string realDbFileData = DB_DIR_PATH + dbFileData; - const char *dbFileVal = realDbFileData.data(); - std::string configStrData(reinterpret_cast(data), size); - const char *configStrVal = configStrData.data(); - GRD_DB *dbVal = nullptr; - DbOpenCloseFuzzTest(dbFileVal, configStrVal, dbVal); -} - -void DbCloseResultSetFuzzTest() -{ - GRD_DB *db = nullptr; - GRD_DB *db2 = nullptr; - int ret = GRD_DBOpen(TEST_FILE, CONFIG_STRING, GRD_OPEN_CREATE, &db); - int errCode = GRD_DBOpen(TEST_FILE, CONFIG_STRING, GRD_OPEN_CREATE, &db2); - if (ret == GRD_OK) { - GRD_CreateCollect(db, "collection1", "{\"maxdoc\" : 5}", 0); - - GRD_ResultSet *reSet = nullptr; - Query query = { "{}", "{}" }; - GRD_FindDocument(db, "collection1", query, 0, &reSet); - - GRD_FreeRe(reSet); - - GRD_DBClose(db, GRD_CLOSE); - } - - if (errCode == GRD_OK) { - GRD_DBClose(db2, GRD_CLOSE); - } -} - -void CreateCollectionFuzzTest(const uint8_t *data, size_t size) -{ - std::string collectNameData(reinterpret_cast(data), size); - const char *collectNameVal = collectNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); - const char *optionStrVal = optionStrData.data(); - GRD_CreateCollect(nullptr, collectNameVal, optionStrVal, 0); - GRD_CreateCollect(g_datatest, collectNameVal, optionStrVal, 0); - const char *optionStr = nullptr; - GRD_CreateCollect(g_datatest, COLLECT_NAME, optionStr, 0); - GRD_CreateCollect(g_datatest, COLLECT_NAME, "{\"maxdoc\":5, \"unexpected_max_doc\":32}", 0); - GRD_CreateCollect(g_datatest, COLLECT_NAME, "{}", 0); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - std::string optStr = "{\"maxdoc\":" + optionStrData + "}"; - GRD_CreateCollect(g_datatest, COLLECT_NAME, optStr.c_str(), 0); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - GRD_CreateCollect(g_datatest, COLLECT_NAME, optStr.c_str(), MAX_SIZE_NUM_TEST); - optStr = "{\"maxdoc\": 5}"; - GRD_CreateCollect(g_datatest, COLLECT_NAME, optStr.c_str(), 0); - GRD_CreateCollect(g_datatest, COLLECT_NAME, optStr.c_str(), 1); - GRD_DropCollect(g_datatest, COLLECT_NAME, 0); - GRD_DropCollect(g_datatest, COLLECT_NAME, MAX_SIZE_NUM_TEST); - GRD_DropCollect(g_datatest, collectNameVal, 0); -} - -void DropCollectFuzzTest(const uint8_t *data, size_t size) -{ - std::string collectNameData(reinterpret_cast(data), size); - const char *collectNameVal = collectNameData.data(); - std::string optionStrData(reinterpret_cast(data), size); - const char *optionStrVal = optionStrData.data(); - GRD_CreateCollect(g_datatest, collectNameVal, optionStrVal, 0); - GRD_DropCollect(nullptr, collectNameVal, 0); - GRD_DropCollect(g_datatest, collectNameVal, 0); -} - -void DbFlushFuzzTest(const uint8_t *data, size_t size) -{ - if (data == nullptr) { - return; - } - GRD_DB *db = nullptr; - GRD_DB *db2 = nullptr; - const uint32_t flags = *data; - int ret = GRD_DBOpen(TEST_FILE, CONFIG_STRING, GRD_OPEN_CREATE, &db); - if (ret == GRD_OK) { - GRD_Flush(db, flags); - GRD_DBClose(db, GRD_CLOSE); - } - GRD_Flush(db2, flags); -} - -void TestGrdDbApGrdGetItem002FuzzTest() -{ - const char *config = CONFIG_STRING; - GRD_DB *db = nullptr; - DbOpenCloseFuzzTest(TEST_FILE, config, db); - GRD_Preload(nullptr, COLLECT_NAME); - GRD_Preload(nullptr, "invalid_name"); - GRD_Preload(g_datatest, COLLECT_NAME); - std::string smallPrefix = std::string(SMALL_PREFIX_LENGTH, 'a'); - for (uint32_t i = 0; i < NUM_NINETY_EIGHT; ++i) { - std::string v = smallPrefix + std::to_string(i); - GRD_KVItem key = { &i, sizeof(uint32_t) }; - GRD_KVItem value = { reinterpret_cast(v.data()), static_cast(v.size()) + 1 }; - GRD_KVPut(g_datatest, COLLECT_NAME, &key, &value); - - GRD_KVItem getValue = { nullptr, 0 }; - GRD_KVGet(g_datatest, COLLECT_NAME, &key, &getValue); - GRD_KVFreeItem(&getValue); - - GRD_KVDel(g_datatest, COLLECT_NAME, &key); - } - GRD_Flush(g_datatest, 1); - - uint32_t begin = 0, end = MAX_SIZE_NUM_TEST; - GRD_FilterOptionT option = {}; - option.mode = KV_SCAN_RANGE; - option.begin = { &begin, sizeof(uint32_t) }; - option.end = { &end, sizeof(uint32_t) }; - GRD_ResultSet *reSet = nullptr; - GRD_KVFilter(g_datatest, COLLECT_NAME, &option, &reSet); - - uint32_t keySize, valueSize; - GRD_KVGetSize(reSet, &keySize, &valueSize); - - reSet = nullptr; - uint32_t i = 32; - GRD_KVItem key = { &i, sizeof(uint32_t) }; - GRD_KVScan(g_datatest, COLLECT_NAME, &key, KV_SCAN_EQUAL_OR_LESS_KEY, &reSet); - - GRD_Prev(reSet); - GRD_Next(reSet); - - GRD_FreeRe(reSet); -} - -void TestGrdKvBatchCoupling003FuzzTest() -{ - const char *config = CONFIG_STRING; - GRD_DB *db = nullptr; - DbOpenCloseFuzzTest(TEST_FILE, config, db); - - GRD_ResultSet *reSet = nullptr; - GRD_KVScan(g_datatest, COLLECT_NAME, nullptr, KV_SCAN_PREFIX, &reSet); - - for (uint32_t i = 0; i < CURSOR_COUNT_TEST; i++) { - GRD_Next(reSet); - } - - GRD_KVBatchT *batchDel = nullptr; - std::vector keySet; - std::vector valueSet; - for (uint32_t i = 0; i < VECTOR_SIZE; i++) { - std::string key(MAX_SIZE_NUM_TEST, 'a'); - key += std::to_string(i); - keySet.emplace_back(key); - std::string value = std::to_string(i); - valueSet.emplace_back(value); - } - - for (int j = 0; j < BATCH_COUNT; j++) { - GRD_KVBatchPrepare(BATCH_COUNT, &batchDel); - GRD_KVBatchPut(g_datatest, COLLECT_NAME, batchDel); - for (uint16_t i = 0; i < BATCH_COUNT; i++) { - char *batchKey = const_cast(keySet[CURSOR_COUNT_TEST + j * BATCH_COUNT + i].c_str()); - char *batchValue = const_cast(valueSet[CURSOR_COUNT_TEST + j * BATCH_COUNT + i].c_str()); - GRD_KVBatchPushback(static_cast(batchKey), - static_cast(keySet[CURSOR_COUNT_TEST + j * BATCH_COUNT + i].length()) + 1, - static_cast(batchValue), - static_cast(valueSet[CURSOR_COUNT_TEST + j * BATCH_COUNT + i].length()) + 1, - batchDel); - } - - GRD_KVBatchDel(g_datatest, COLLECT_NAME, batchDel); - - GRD_KVBatchDestroy(batchDel); - } - - GRD_Next(reSet); - GRD_KVItem keyItem = { nullptr, 0 }; - GRD_KVItem valueItem = { nullptr, 0 }; - GRD_Fetch(reSet, &keyItem, &valueItem); - GRD_KVFreeItem(&keyItem); - GRD_KVFreeItem(&valueItem); - GRD_FreeRe(reSet); -} -} // namespace OHOS - -/* FuzzTester entry point */ -extern "C" { -int LLVMFuzzTesterTestOneInput(const uint8_t *data, size_t size) -{ - /* Run your code on data */ - OHOS::SetUpTestCase(); - - OHOS::DbOpenFuzzTestTest(data, size); - OHOS::CreateCollectionFuzzTest(data, size); - OHOS::DropCollectFuzzTest(data, size); - OHOS::InsertDocFuzzTest(data, size); - OHOS::FindDocumentFuzzTest(data, size); - OHOS::UpdateDocFuzzTest(data, size); - OHOS::UpsertFuzzTest(data, size); - OHOS::DelDocFuzzTest(data, size); - OHOS::NextFuzzTest(data, size); - OHOS::GetValueFuzzTest(data, size); - OHOS::FreeReFuzzTest(); - OHOS::TestGrdDbApGrdGetItem002FuzzTest(); - OHOS::TestGrdKvBatchCoupling003FuzzTest(); - OHOS::DbCloseFuzzTest(data, size); - OHOS::DbCloseResultSetFuzzTest(); - OHOS::DbFlushFuzzTest(data, size); - - OHOS::TearDownTestCase(); - return 0; -} -} diff --git a/kv_store/test/fuzztest/kvsync_fuzzer/BUILD.gn b/kv_store/test/fuzztest/kvsync_fuzzer/BUILD.gn deleted file mode 100644 index 7e65b4a2..00000000 --- a/kv_store/test/fuzztest/kvsync_fuzzer/BUILD.gn +++ /dev/null @@ -1,130 +0,0 @@ -# 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. - -#####################hydra-fuzz################### -import("//build/config/features.gni") -import("//build/test.gni") -import("../../../distributeddb.gni") - -##############################fuzztest########################################## -ohos_fuzztest("KvsyncFuzzTest") { - module_out_path = "kv_store/kv_store" - - include_dirs = [ - "../../../test/fuzztest/common", - "../../../test/unittest/common/common", - "../../../test/unittest/common/syncer", - "../../../test/unittest/common/syncer/kv", - "../../../test/unittest/common/storage", - "../../../include", - "../../../interfaces/include", - "../../../interfaces/include/kv", - "../../../interfaces/include/relational", - "../../../interfaces/src", - "../../../interfaces/src/relational", - "../../../storage/include", - "../../../storage/src", - "../../../storage/src/kv", - "../../../storage/src/kv", - "../../../storage/src/gaussdb_rd", - "../../../storage/src/multiver", - "../../../storage/src/operation", - "../../../storage/src/relational", - "../../../storage/src/sqlite", - "../../../storage/src/sqlite/kv", - "../../../storage/src/sqlite/relational", - "../../../storage/src/upgrader", - "../../../common/include", - "../../../common/include/kv", - "../../../common/include/relational", - "../../../common/src", - "../../../common/src/kv", - "../../../communicator/include", - "../../../communicator/src", - "../../../syncer/include", - "../../../syncer/src", - "../../../syncer/src/kv", - "../../../syncer/src/device", - "../../../syncer/src/device/multiver", - "../../../syncer/src/device/singlever", - ] - - cflags = [ - "-g", - "-O0", - "-Wno-unused-variable", - "-fno-omit-frame-pointer", - "--coverage", - ] - - ldflags = [ "--coverage" ] - - cflags_cc = [ "--coverage" ] - - fuzz_config_file = "../kvsync_fuzzer" - - sources = distributeddb_src - sources += [ - "../../../test/fuzztest/common/distributeddb_tools_test.cpp", - "../../../test/fuzztest/common/fuzzer_data.cpp", - "../../../test/fuzztest/kvsync_fuzzer/kvsync_fuzzer.cpp", - "../../../test/unittest/common/common/distributeddb_data_generate_unit_test.cpp", - "../../../test/unittest/common/syncer/kv/virtual_asset_loader.cpp", - "../../../test/unittest/common/syncer/kv/virtual_kv_data_translate.cpp", - "../../../test/unittest/common/syncer/kv/virtual_kv_db.cpp", - ] - - defines = [ - "SQLITE_ENABLE_SNAPSHOT", - "_LARGEFILE64_SOURCE", - "_FILE_OFFSET_BITS=64", - "SQLITE_HAS_CODEC", - "SQLITE_ENABLE_JSON1", - "USING_HILOG_LOGGER", - "USE_SQLITE_SYMBOLS", - "USING_DB_JSON_EXTRACT_AUTOMATICALLY", - "LOW_LEVEL_MEM_DEV", - "JSONCPP_USE_BUILDER", - "OMIT_FLATBUFFER", - "OMIT_MULTI_VER", - "RELATIONAL_STORE", - "SQLITE_DISTRIBUTE_RELATIONAL", - "SQLITE_EXPORT_SYMBOLS", - "SQLITE_ENABLE_DROPTABLE_CALLBACK", - "OPENSSL_SUPPRESS_DEPRECATED", - ] - - deps = [ - "../../../../distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - "//third_party/sqlite:sqlite", - ] - - external_deps = [ - "c_utils:utils", - "hilog:libhilog", - "zlib:shared_libz", - ] -} - -############################################################################### - -group("fuzztest") { - testonly = true - deps = [] - deps += [ - # deps file - ":KvsyncFuzzTest", - ] -} diff --git a/kv_store/test/fuzztest/kvsync_fuzzer/kvsync_fuzzer.cpp b/kv_store/test/fuzztest/kvsync_fuzzer/kvsync_fuzzer.cpp deleted file mode 100644 index 23947830..00000000 --- a/kv_store/test/fuzztest/kvsync_fuzzer/kvsync_fuzzer.cpp +++ /dev/null @@ -1,561 +0,0 @@ -/* - * Copyright (c) 2023 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "kvsync_fuzzer.h" -#include "kv/kv_dbtypes.h" -#include "kv/kv_dbconstant.h" -#include "distributeddbvData_generate_unit_test.h" -#include "distributeddbtools_test.h" -#include "fuzzer_vData.h" -#include "kv_store_nb_kvDelegate.h" -#include "logprint.h" -#include "relational_store_kvDelegate.h" -#include "relational_store_manager.h" -#include "runtime_kvConfig.h" -#include "time_helper.h" -#include "virtual_assetTest_loader.h" -#include "virtual_kv_vData_translate.h" -#include "virtual_kv_db.h" - -namespace OHOS { -using namespace DistributedDB; -using namespace DistributedDBTest; - -static constexpr const int MOD = 1000; // 1000 is mod -class KvSyncContext { -public: - void WaitForFinishTest() - { - std::unique_lock unique(mutex); - LOGI("begin wait"); - cv.wait_for(unique, std::chrono::milliseconds(DBConstant::MAX_TIMEOUT), [this]() { - return finished; - }); - LOGI("end wait"); - } - - void FinishAndNotifyTest() - { - { - std::lock_guard autoLock(mutex); - finished = true; - } - cv.notify_one(); - } - -private: - std::condition_variable cv; - std::mutex mutex; - bool finished = false; -}; -class KvSyncTest { -public: - static void ExecSqlFuzz(sqlite3 *db, const std::string &sql) - { - if (db == nullptr || sql.empty()) { - return; - } - int errCodeTest = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); - if (errCodeTest != SQLITE_OK) { - LOGE("Execute sql failed. err: %d", errCodeTest); - } - } - - static void CreateTableFuzz(sqlite3 *&db) - { - ExecSqlFuzz(db, "PRAGMA journal_modeTest=WAL;"); - ExecSqlFuzz(db, gcreateLocalTableSql); - } - - static void SetKvDbSchemaFuzz(RelationalStoreDelegate *kvDelegate) - { - DataBaseSchema vDataSchema; - const std::vector kvFiled = { - {"name", TYPE_INDEX, true}, {"height", TYPE_INDEX}, - {"married", TYPE_INDEX}, {"photoTest", TYPE_INDEX, false, false}, - {"assert", TYPE_INDEX}, {"asserts", TYPE_INDEX}, {"age", TYPE_INDEX} - }; - TableSchema tableSchemaTest = { - .name = gtable, - .fieldTests = kvFiled - }; - vDataSchema.tables.push_back(tableSchemaTest); - kvDelegate->SetKvDbSchemaFuzz(vDataSchema); - kvDelegate->CreateDistributedTable(gtable, CLOUD_COOPERATION); - } - - static void InitDbData(sqlite3 *&db, const uint8_t *vData, size_t size) - { - sqlite3_stmt *stmt = nullptr; - int errCodeTest = SQLiteUtils::GetStatement(db, ginsertLocalDataSql, stmt); - if (errCodeTest != E_OK) { - return; - } - FuzzerData fuzzerDataTest(vData, size); - uint32_t len = fuzzerDataTest.GetUInt32() % MOD; - for (size_t i = 0; i <= size; ++i) { - std::string idStr = fuzzerDataTest.GetString(len); - errCodeTest = SQLiteUtils::BindTextToStatement(stmt, 1, idStr); - if (errCodeTest != E_OK) { - break; - } - std::vector photoTest = fuzzerDataTest.GetSequence(fuzzerDataTest.GetInt()); - errCodeTest = SQLiteUtils::BindBlobToStatement(stmt, 2, photoTest); // 2 is index of photoTest - if (errCodeTest != E_OK) { - break; - } - errCodeTest = SQLiteUtils::StepWithRetry(stmt); - if (errCodeTest != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - break; - } - SQLiteUtils::ResetStatement(stmt, false, errCodeTest); - } - SQLiteUtils::ResetStatement(stmt, true, errCodeTest); - } - - static Asset GenAsset(const std::string &name, const std::string &hash) - { - Asset assetTest; - assetTest.name = name; - assetTest.hash = hash; - return assetTest; - } - - void InitDbAssetFuzz(const uint8_t *vData, size_t size) - { - if (vData == nullptr || size == 0) { - return; - } - sqlite3_stmt *stmt = nullptr; - int errCodeTest = SQLiteUtils::GetStatement(db, ginsertLocalAssetSql, stmt); - if (errCodeTest != E_OK) { - return; - } - FuzzerData fuzzerDataTest(vData, size); - uint32_t len = fuzzerDataTest.GetUInt32() % MOD; - for (size_t i = 0; i <= size; ++i) { - std::string idStr = fuzzerDataTest.GetString(len); - errCodeTest = SQLiteUtils::BindTextToStatement(stmt, 1, idStr); - if (errCodeTest != E_OK) { - break; - } - std::vector photoTest = fuzzerDataTest.GetSequence(fuzzerDataTest.GetInt()); - errCodeTest = SQLiteUtils::BindBlobToStatement(stmt, 2, photoTest); // 2 is index of photoTest - if (errCodeTest != E_OK) { - break; - } - std::vector assetTest; - RuntimeContext::GetInstance()->AssetToBlob(localAssets[i % size], assetTest); - errCodeTest = SQLiteUtils::BindBlobToStatement(stmt, 3, assetTest); // 3 is index of assert - if (errCodeTest != E_OK) { - break; - } - - std::vector assetTestVec(localAssets.begin() + (i % size), localAssets.end()); - RuntimeContext::GetInstance()->AssetsToBlob(assetTestVec, assetTest); - errCodeTest = SQLiteUtils::BindBlobToStatement(stmt, 4, assetTest); // 4 is index of asserts - if (errCodeTest != E_OK) { - break; - } - errCodeTest = SQLiteUtils::StepWithRetry(stmt); - if (errCodeTest != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - break; - } - SQLiteUtils::ResetStatement(stmt, false, errCodeTest); - } - SQLiteUtils::ResetStatement(stmt, true, errCodeTest); - } - - void InsertKvTableRecordFuzz(int64_t begin, int64_t count, int64_t photoTestSize, bool assetTestIsNull) - { - std::vector photoTest(photoTestSize, 'v'); - std::vector record1; - std::vector extend1; - double randomHeight = 166.0; // 166.0 is random double value - int64_t randomAge = 13L; // 13 is random int64_t value - Timestamp now = TimeHelper::GetSysCurrentTime(); - for (int64_t i = begin; i < begin + count; ++i) { - VBucket vData; - vData.insert_or_assign("name", "Kv" + std::to_string(i)); - vData.insert_or_assign("height", randomHeight); - vData.insert_or_assign("married", false); - vData.insert_or_assign("photoTest", photoTest); - vData.insert_or_assign("age", randomAge); - Asset assetTest = gkvAsset; - assetTest.name = assetTest.name + std::to_string(i); - assetTestIsNull ? vData.insert_or_assign("assert", Nil()) : vData.insert_or_assign("assert", assetTest); - record1.push_back(vData); - VBucket log; - log.insert_or_assign(KvDbConstant::CREATE_FIELD, - static_cast(now / KvDbConstant::TEN_THOUSAND + i)); - log.insert_or_assign(KvDbConstant::MODIFY_FIELD, - static_cast(now / KvDbConstant::TEN_THOUSAND + i)); - log.insert_or_assign(KvDbConstant::DELETE_FIELD, false); - extend1.push_back(log); - } - examKvDb->BatchInsert(gtable, std::move(record1), extend1); - LOGD("insert kv record worker1[primary key]:[kv%" PRId64 " - kv%" PRId64 ")", begin, count); - std::this_thread::sleep_for(std::chrono::milliseconds(count)); - } - - void SetUp() - { - DistributedDBToolsTest::TestDirInit(testDir); - storePathTest = testDir + "/" + gstoreId + gdbSuffix; - LOGI("The test db is:%s", testDir.c_str()); - RuntimeConfig::SetKvTranslate(std::make_shared()); - LOGD("Test dir is %s", testDir.c_str()); - db = RdbTestUtils::CreateDataBase(storePathTest); - if (db == nullptr) { - return; - } - CreateTableFuzz(db); - mgr = std::make_shared("APP_ID", "USER_ID"); - RelationalStoreDelegate::Option optionTest; - mgr->OpenStore(storePathTest, "STORE_ID", optionTest, kvDelegate); - gKvSyncOption.modeTest = SyncMode::SYNC_MODE_CLOUD_MERGE; - gKvSyncOption.users.push_back(DistributedDBUnitTest::USER_ID); - gKvSyncOption.devices.push_back("kv"); - kvConfig.vDataDir = testDir; - gmgr.SetKvStoreConfig(kvConfig); - KvStoreNbDelegate::Option optionTest1; - GetKvStoreFuzz(kvDelegatePtrS1, DistributedDBUnitTest::STORE_ID_1, optionTest1); - KvStoreNbDelegate::Option optionTest2; - GetKvStoreFuzz(kvDelegatePtrS2, DistributedDBUnitTest::STORE_ID_2, optionTest2); - examKvDb = std::make_shared(); - examKvDb1 = std::make_shared(); - examKvDb2 = std::make_shared(); - virtualAssetLoader = std::make_shared(); - kvDelegate->SetKvDB(examKvDb); - kvDelegate->SetIAssetLoader(virtualAssetLoader); - } - - void TearDown() - { - if (kvDelegate != nullptr) { - DBStatus errCodeTest = mgr->CloseStore(kvDelegate); - LOGI("kvDelegate close with errCodeTest %d", static_cast(errCodeTest)); - kvDelegate = nullptr; - } - if (db != nullptr) { - int errCodeTest = sqlite3_close_v2(db); - LOGI("sqlite close with errCodeTest %d", errCodeTest); - } - examKvDb = nullptr; - CloseKvStoreFuzz(kvDelegatePtrS1, DistributedDBUnitTest::STORE_ID_1); - CloseKvStoreFuzz(kvDelegatePtrS2, DistributedDBUnitTest::STORE_ID_2); - examKvDb1 = nullptr; - examKvDb2 = nullptr; - virtualAssetLoader = nullptr; - if (DistributedDBToolsTest::RemoveTestDbFiles(testDir) != 0) { - LOGE("rm test db files error."); - } - } - - void KvBlockSyncFuzz(KvStoreNbDelegate *kvDelegate, DBStatus expectDBStatus, KvSyncOption optionTest, - int expectSyncResult = OK) - { - if (kvDelegate == nullptr) { - return; - } - std::mutex virDataMutex; - std::condition_variable cv; - bool finish = false; - SyncProcess last; - auto callback = [expectDBStatus, &last, &cv, &virDataMutex, &finish, &optionTest]( - const std::map &process) { - size_t notifyCnt = 0; - for (const auto &item : process) { - LOGD("user = %s, dbStatus = %d", item.first.c_str(), item.second.process); - if (item.second.process != DistributedDB::FINISHED) { - continue; - } - { - std::lock_guard autoLock(virDataMutex); - notifyCnt++; - std::set userSet(optionTest.users.begin(), optionTest.users.end()); - if (notifyCnt == userSet.size()) { - finish = true; - last = item.second; - cv.notify_one(); - } - } - } - }; - auto result = kvDelegate->Sync(optionTest, callback); - if (result == OK) { - std::unique_lock unique(virDataMutex); - cv.wait(unique, [&finish]() { - return finish; - }); - } - lastProcess = last; - } - - static DataBaseSchema GetDataBaseSchema(bool invalidSchema) - { - DataBaseSchema schemaTest; - TableSchema tableSchemaTest; - tableSchemaTest.name = invalidSchema ? "invalid_schemaTest_name" : KvDbConstant::CLOUD_KV_TABLE_NAME; - Field fieldTest; - fieldTest.colName = KvDbConstant::CLOUD_KV_FIELD_KEY; - fieldTest.type = TYPE_INDEX; - fieldTest.primary = true; - fieldTest.colName = KvDbConstant::CLOUD_KV_FIELD_DEVICE; - fieldTest.primary = false; - tableSchemaTest.fieldTests.push_back(fieldTest); - tableSchemaTest.fieldTests.push_back(fieldTest); - fieldTest.colName = KvDbConstant::CLOUD_KV_FIELD_ORI_DEVICE; - tableSchemaTest.fieldTests.push_back(fieldTest); - fieldTest.colName = KvDbConstant::CLOUD_KV_FIELD_VALUE; - tableSchemaTest.fieldTests.push_back(fieldTest); - fieldTest.colName = KvDbConstant::CLOUD_KV_FIELD_DEVICE_CREATE_TIME; - fieldTest.type = TYPE_INDEX; - tableSchemaTest.fieldTests.push_back(fieldTest); - schemaTest.tables.push_back(tableSchemaTest); - return schemaTest; - } - - void GetKvStoreFuzz(KvStoreNbDelegate *&kvDelegate, const std::string &storeId, KvDelegate::Option optionTest, - int securityLabel = NOT_SET, bool invalidSchema = false) - { - DBStatus openRet = OK; - optionTest.secOption.securityLabel = securityLabel; - gmgr.GetKvStoreFuzz(storeId, optionTest, [&openRet, &kvDelegate](KvStoreNbDelegate *openDelegate) { - openRet = dbStatus; - kvDelegate = openDelegate; - }); - if (kvDelegate == nullptr) { - return; - } - std::map schemaTests; - schemaTests[DistributedDBUnitTest::USER_ID] = GetDataBaseSchema(invalidSchema); - schemaTests[USER_ID] = GetDataBaseSchema(invalidSchema); - kvDelegate->SetKvDbSchemaFuzz(schemaTests); - std::map> kvDbs; - kvDbs[DistributedDBUnitTest::USER_ID] = examKvDb1; - kvDbs[USER_ID] = examKvDb2; - kvDelegate->SetKvDB(kvDbs); - } - - static void CloseKvStoreFuzz(KvStoreNbDelegate *&kvDelegate, const std::string &storeId) - { - if (kvDelegate != nullptr) { - gmgr.CloseKvStoreFuzz(kvDelegate); - kvDelegate = nullptr; - DBStatus dbStatus = gmgr.DeleteKvStore(storeId); - LOGD("delete kv store dbStatus %d store %s", dbStatus, storeId.c_str()); - } - } - - void BlockSyncFuzz(SyncMode modeTest = SYNC_MODE_CLOUD_MERGE) - { - Query dbQuery = Query::Select().FromTable({ gtable }); - auto kvContext = std::make_shared(); - auto callback = [kvContext](const std::map &onProcess) { - for (const auto &item : onProcess) { - if (item.second.process == ProcessStatus::FINISHED) { - kvContext->FinishAndNotifyTest(); - } - } - }; - DBStatus dbStatus = kvDelegate->Sync({gdeviceKv}, modeTest, dbQuery, callback, DBConstant::MAX_TIMEOUT); - if (dbStatus != OK) { - return; - } - kvContext->WaitForFinishTest(); - } - - void OptionBlockSyncFuzz(const std::vector &devices, SyncMode modeTest = SYNC_MODE_CLOUD_MERGE) - { - Query dbQuery = Query::Select().FromTable({ gtable }); - auto kvContext = std::make_shared(); - auto callback = [kvContext](const std::map &onProcess) { - for (const auto &item : onProcess) { - if (item.second.process == ProcessStatus::FINISHED) { - kvContext->FinishAndNotifyTest(); - } - } - }; - KvSyncOption optionTest; - optionTest.modeTest = modeTest; - optionTest.devices = devices; - optionTest.dbQuery = dbQuery; - optionTest.waitTime = DBConstant::MAX_TIMEOUT; - DBStatus dbStatus = kvDelegate->Sync(optionTest, callback); - if (dbStatus != OK) { - return; - } - kvContext->WaitForFinishTest(); - } - - void NormalSync() - { - BlockSyncFuzz(); - SetKvDbSchemaFuzz(kvDelegate); - BlockSyncFuzz(); - } - - void KvNormalSync() - { - Key key = {'k'}; - Value expectValue = {'v'}; - kvDelegatePtrS1->Put(key, expectValue); - KvBlockSyncFuzz(kvDelegatePtrS1, OK, gKvSyncOption); - KvBlockSyncFuzz(kvDelegatePtrS2, OK, gKvSyncOption); - Value actualValue; - kvDelegatePtrS2->Get(key, actualValue); - } - - void RandomModeSyncFuzz(const uint8_t *vData, size_t size) - { - if (size == 0) { - BlockSyncFuzz(); - return; - } - auto modeTest = static_cast(vData[0]); - LOGI("[RandomModeSyncFuzz] select modeTest %d", static_cast(modeTest)); - BlockSyncFuzz(modeTest); - } - - void DataChangeSyncFuzz(const uint8_t *vData, size_t size) - { - SetKvDbSchemaFuzz(kvDelegate); - if (size == 0) { - return; - } - InitDbData(db, vData, size); - BlockSyncFuzz(); - FuzzerData fuzzerDataTest(vData, size); - KvSyncConfig kvConfig; - int maxUploadSize11 = fuzzerDataTest.GetInt(); - int maxUploadCount = fuzzerDataTest.GetInt(); - kvConfig.maxUploadSize11 = maxUploadSize11; - kvConfig.maxUploadCount = maxUploadCount; - kvDelegate->SetKvSyncConfig(kvConfig); - kvDelegatePtrS1->SetKvSyncConfig(kvConfig); - uint32_t len = fuzzerDataTest.GetUInt32() % MOD; - std::string version = fuzzerDataTest.GetString(len); - kvDelegatePtrS1->SetGenKvVersionCallback([version](const std::string &origin) { - return origin + version; - }); - KvNormalSync(); - int count = fuzzerDataTest.GetInt(); - kvDelegatePtrS1->GetCount(Query::Select(), count); - std::string device = fuzzerDataTest.GetString(len); - kvDelegatePtrS1->GetKvVersion(device); - std::vector devices = fuzzerDataTest.GetStringVector(len); - OptionBlockSyncFuzz(devices); - } - - void InitAssetsFuzz(const uint8_t *vData, size_t size) - { - FuzzerData fuzzerDataTest(vData, size); - uint32_t len = fuzzerDataTest.GetUInt32() % MOD; - for (size_t i = 0; i <= size; ++i) { - std::string nameStr = fuzzerDataTest.GetString(len); - localAssets.push_back(GenAsset(nameStr, std::to_string(vData[0]))); - } - } - - void AssetChangeSyncFuzz(const uint8_t *vData, size_t size) - { - SetKvDbSchemaFuzz(kvDelegate); - if (size == 0) { - return; - } - InitAssetsFuzz(vData, size); - InitDbAssetFuzz(vData, size); - BlockSyncFuzz(); - } - - void RandomModeRemoveDeviceDataFuzz(const uint8_t *vData, size_t size) - { - if (size == 0) { - return; - } - SetKvDbSchemaFuzz(kvDelegate); - int64_t kvCount = 10; - int64_t paddingSize = 10; - InsertKvTableRecordFuzz(0, kvCount, paddingSize, false); - BlockSyncFuzz(); - auto modeTest = static_cast(vData[0]); - LOGI("[RandomModeRemoveDeviceDataFuzz] select modeTest %d", static_cast(modeTest)); - if (modeTest == DEFAULT) { - return; - } - std::string device = ""; - kvDelegate->RemoveDeviceData(device, modeTest); - } -private: - std::string testDir; - std::string storePathTest; - sqlite3 *db = nullptr; - RelationalStoreDelegate *kvDelegate = nullptr; - KvStoreNbDelegate* kvDelegatePtrS1 = nullptr; - KvStoreNbDelegate* kvDelegatePtrS2 = nullptr; - std::shared_ptr examKvDb; - std::shared_ptr examKvDb1 = nullptr; - std::shared_ptr examKvDb2 = nullptr; - std::shared_ptr virtualAssetLoader; - std::shared_ptr mgr; - KvStoreConfig kvConfig; - SyncProcess lastProcess; - Assets localAssets; -}; -KvSyncTest *g_kvSyncFuzzTest = nullptr; - -void Setup() -{ - LOGI("Set up"); - g_kvSyncFuzzTest = new(std::nothrow) KvSyncTest(); - if (g_kvSyncFuzzTest == nullptr) { - return; - } - g_kvSyncFuzzTest->SetUp(); -} - -void TearDown() -{ - LOGI("Tear down"); - g_kvSyncFuzzTest->TearDown(); - if (g_kvSyncFuzzTest != nullptr) { - delete g_kvSyncFuzzTest; - g_kvSyncFuzzTest = nullptr; - } -} - -void CombineFuzzTest(const uint8_t *vData, size_t size) -{ - if (g_kvSyncFuzzTest == nullptr) { - return; - } - g_kvSyncFuzzTest->NormalSync(); - g_kvSyncFuzzTest->KvNormalSync(); - g_kvSyncFuzzTest->RandomModeSyncFuzz(vData, size); - g_kvSyncFuzzTest->DataChangeSyncFuzz(vData, size); - g_kvSyncFuzzTest->AssetChangeSyncFuzz(vData, size); - g_kvSyncFuzzTest->RandomModeRemoveDeviceDataFuzz(vData, size); -} -} - -/* Fuzzer entry point */ -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *vData, size_t size) -{ - OHOS::Setup(); - OHOS::CombineFuzzTest(vData, size); - OHOS::TearDown(); - return 0; -} diff --git a/kv_store/test/fuzztest/kvsync_fuzzer/project.xml b/kv_store/test/fuzztest/kvsync_fuzzer/project.xml deleted file mode 100644 index 1bd6e94e..00000000 --- a/kv_store/test/fuzztest/kvsync_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 600 - - 4096 - - diff --git a/kv_store/test/fuzztest/singlekvstorestub_fuzzer/BUILD.gn b/kv_store/test/fuzztest/kvutil_fuzzer/BUILD.gn similarity index 82% rename from kv_store/test/fuzztest/singlekvstorestub_fuzzer/BUILD.gn rename to kv_store/test/fuzztest/kvutil_fuzzer/BUILD.gn index d735c3c1..7c09246a 100644 --- a/kv_store/test/fuzztest/singlekvstorestub_fuzzer/BUILD.gn +++ b/kv_store/test/fuzztest/kvutil_fuzzer/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2024 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 @@ -16,7 +16,7 @@ import("//build/config/features.gni") import("//build/test.gni") ##############################fuzztest########################################## -ohos_fuzztest("SingleKvStoreStubFuzzTest") { +ohos_fuzztest("KvUtilFuzzTest") { module_out_path = "kv_store/kv_store" include_dirs = [ @@ -26,7 +26,7 @@ ohos_fuzztest("SingleKvStoreStubFuzzTest") { "../../../interfaces/innerkits/distributeddata/include", ] - fuzz_config_file = "../../../test/fuzztest/singlekvstorestub_fuzzer" + fuzz_config_file = "../../../test/fuzztest/kvutil_fuzzer" cflags = [ "-g", @@ -36,14 +36,18 @@ ohos_fuzztest("SingleKvStoreStubFuzzTest") { "-Wno-c99-designator", ] - sources = [ "singlekvstorestub_fuzzer.cpp" ] - - deps = [] + sources = [ + "kvutil_fuzzer.cpp", + ] external_deps = [ "c_utils:utils", + "data_share:datashare_common", + "data_share:datashare_provider", "hilog:libhilog", + "ipc:ipc_single", "kv_store:distributeddata_inner", + "kv_store:distributeddb", ] } @@ -53,7 +57,7 @@ group("fuzztest") { deps = [] deps += [ # deps file - ":SingleKvStoreStubFuzzTest", + ":KvUtilFuzzTest", ] } ############################################################################### diff --git a/kv_store/test/fuzztest/kvutil_fuzzer/corpus/init b/kv_store/test/fuzztest/kvutil_fuzzer/corpus/init new file mode 100644 index 00000000..7ade8a0f --- /dev/null +++ b/kv_store/test/fuzztest/kvutil_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ \ No newline at end of file diff --git a/kv_store/test/fuzztest/kvutil_fuzzer/kvutil_fuzzer.cpp b/kv_store/test/fuzztest/kvutil_fuzzer/kvutil_fuzzer.cpp new file mode 100644 index 00000000..0dafc3dd --- /dev/null +++ b/kv_store/test/fuzztest/kvutil_fuzzer/kvutil_fuzzer.cpp @@ -0,0 +1,181 @@ +/* + * 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 "kvutil_fuzzer.h" + +#include +#include +#include +#include "distributed_kv_data_manager.h" +#include "fuzzer/FuzzedDataProvider.h" +#include "datashare_predicates.h" +#include "datashare_values_bucket.h" +#include "store_errno.h" +#include "kv_utils.h" + +using namespace OHOS; +using namespace OHOS::DistributedKv; +using namespace OHOS::DataShare; +namespace OHOS { +using ValueType = std::variant>; +static std::shared_ptr singleKvStore_ = nullptr; +static constexpr const char *KEY = "key"; +static constexpr const char *VALUE = "value"; +static constexpr const char *PREFIX = "test_"; +enum DataType { + STRING = 1, + INT64, + BOOL, + DOUBLE, + VECTOR_INT64, +}; + +void SetUpTestCase(void) +{ + DistributedKvDataManager manager; + Options options = { + .createIfMissing = true, + .encrypt = false, + .autoSync = true, + .securityLevel = S1, + .kvStoreType = KvStoreType::SINGLE_VERSION + }; + options.area = EL1; + AppId appId = { "kvstorefuzzertest" }; + options.baseDir = std::string("/data/service/el1/public/database/") + appId.appId; + /* define kvstore(database) name. */ + StoreId storeId = { "fuzzer_single" }; + mkdir(options.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); + /* [create and] open and initialize kvstore instance. */ + manager.GetSingleKvStore(options, appId, storeId, singleKvStore_); +} + +void TearDown(void) +{ + (void)remove("/data/service/el1/public/database/kvutilfuzzertest/key"); + (void)remove("/data/service/el1/public/database/kvutilfuzzertest/kvdb"); + (void)remove("/data/service/el1/public/database/kvutilfuzzertest"); +} + +void ToResultSetBridgeFuzz(FuzzedDataProvider &provider) +{ + std::string skey; + std::string svalue; + Entry entry; + std::vector entries; + std::vector keys; + int sum = provider.ConsumeIntegralInRange(0, 10); + for (size_t i = 0; i < sum; i++) { + skey = provider.ConsumeRandomLengthString(); + svalue = provider.ConsumeRandomLengthString(); + entry.key = {PREFIX + skey}; + entry.value = {PREFIX + svalue}; + entries.push_back(entry); + keys.push_back(entry.key); + } + singleKvStore_->PutBatch(entries); + std::shared_ptr resultSet = nullptr; + DataSharePredicates predicates; + predicates.KeyPrefix("test"); + DataQuery query; + auto status = KvUtils::ToQuery(predicates, query); + if (status == Status::SUCCESS) { + status = singleKvStore_->GetResultSet(query, resultSet); + } + KvUtils::ToResultSetBridge(resultSet); + singleKvStore_->DeleteBatch(keys); +} + +void ToEntryFuzz(FuzzedDataProvider &provider) +{ + DataShareValuesBucket bucket {}; + if (provider.ConsumeBool()) { + bucket.Put(KEY, provider.ConsumeRandomLengthString()); + bucket.Put(VALUE, provider.ConsumeRandomLengthString()); + } + auto entry = KvUtils::ToEntry(bucket); +} + +ValueType CreateData(int32_t type, FuzzedDataProvider &provider) +{ + ValueType data; + switch (type) { + case DataType::STRING: + data = provider.ConsumeRandomLengthString(); + break; + case DataType::INT64: + data = provider.ConsumeIntegral(); + break; + case DataType::BOOL: + data = provider.ConsumeBool(); + break; + case DataType::DOUBLE: + data = provider.ConsumeFloatingPoint(); + break; + case DataType::VECTOR_INT64: + data = provider.ConsumeRemainingBytes(); + break; + default: + data = {}; + break; + } + return data; +} + +void ToEntriesFuzz(FuzzedDataProvider &provider) +{ + std::vector buckets; + const uint8_t bucketCount = provider.ConsumeIntegralInRange(1, 10); + DataShareValuesBucket bucket; + ValueType key; + ValueType value; + for (int i = 1; i < bucketCount; ++i) { + auto keyType = provider.ConsumeIntegralInRange(1, 5); + auto valueType = provider.ConsumeIntegralInRange(1, 5); + key = CreateData(keyType, provider); + value = CreateData(valueType, provider); + bucket.Put(KEY, key); + bucket.Put(VALUE, value); + buckets.push_back(std::move(bucket)); + } + auto entry = KvUtils::ToEntries(buckets); +} + +void GetKeysFuzz(FuzzedDataProvider &provider) +{ + std::vector keys; + keys.push_back(provider.ConsumeRandomLengthString()); + keys.push_back(provider.ConsumeRandomLengthString()); + keys.push_back(provider.ConsumeRandomLengthString()); + DataSharePredicates predicates; + predicates.InKeys(keys); + std::vector kvKeys; + KvUtils::GetKeys(predicates, kvKeys); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + /* Run your code on data */ + FuzzedDataProvider provider(data, size); + OHOS::SetUpTestCase(); + OHOS::ToResultSetBridgeFuzz(provider); + OHOS::ToEntryFuzz(provider); + OHOS::ToEntriesFuzz(provider); + OHOS::GetKeysFuzz(provider); + OHOS::TearDown(); + return 0; +} \ No newline at end of file diff --git a/kv_store/test/fuzztest/kvutil_fuzzer/kvutil_fuzzer.h b/kv_store/test/fuzztest/kvutil_fuzzer/kvutil_fuzzer.h new file mode 100644 index 00000000..c2d7e4ab --- /dev/null +++ b/kv_store/test/fuzztest/kvutil_fuzzer/kvutil_fuzzer.h @@ -0,0 +1,22 @@ +/* + * 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 KVUTIL_FUZZER_H +#define KVUTIL_FUZZER_H + +#define FUZZ_PROJECT_NAME "kvutil_fuzzer" + +#endif // KVUTIL_FUZZER_H + diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/project.xml b/kv_store/test/fuzztest/kvutil_fuzzer/project.xml similarity index 95% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/project.xml rename to kv_store/test/fuzztest/kvutil_fuzzer/project.xml index 6e8ad2cf..66e1dcac 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/project.xml +++ b/kv_store/test/fuzztest/kvutil_fuzzer/project.xml @@ -1,5 +1,5 @@ - + + + + LICENSE + + + + + + + + + + \ No newline at end of file diff --git a/relational_store/bundle.json b/relational_store/bundle.json index 81a4db74..efbedbbb 100644 --- a/relational_store/bundle.json +++ b/relational_store/bundle.json @@ -52,6 +52,7 @@ "access_token", "common_event_service", "c_utils", + "data_share", "device_manager", "eventhandler", "hilog", @@ -66,11 +67,10 @@ "icu", "sqlite", "file_api", - "json" + "json", + "runtime_core" ], - "third_party": [ - "sqlite" - ] + "third_party": [ "sqlite" ] }, "build": { "sub_component": [ @@ -79,8 +79,8 @@ "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb_data_share_adapter:rdb_data_share_adapter", "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb:native_rdb", "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/cloud_data:clouddata", - "//foundation/distributeddatamgr/relational_store/interfaces/ndk/src:native_rdb_ndk", - "//foundation/distributeddatamgr/relational_store/frameworks/cj:cj_relational_store_ffi", + "//foundation/distributeddatamgr/relational_store/interfaces/rdb_ndk_utils:native_rdb_ndk_utils", + "//foundation/distributeddatamgr/relational_store/interfaces/ndk:native_rdb_ndk", "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/dataability:dataability", "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/rdb:rdb", "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/rdb:napi_rdb", @@ -89,12 +89,13 @@ "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/common:commontype_napi", "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/sendablerelationalstore:sendablerelationalstore", "//foundation/distributeddatamgr/relational_store/frameworks/native/icu:build_module", - "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/gdb:native_graphstore", - "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/graphstore:graphstore" + "//foundation/distributeddatamgr/relational_store/frameworks/native/obs_mgr_adapter:rdb_obs_mgr_adapter", + "//foundation/distributeddatamgr/relational_store/frameworks/native/rdb_crypt:relational_store_crypt", + "//foundation/distributeddatamgr/relational_store/frameworks/js/ani/relationalstore:relationalstore_ani_package" ], "inner_kits": [ { - "name": "//foundation/distributeddatamgr/relational_store/interfaces/ndk/src:native_rdb_ndk", + "name": "//foundation/distributeddatamgr/relational_store/interfaces/ndk:native_rdb_ndk", "header": { "header_files": [ "oh_predicates.h", @@ -107,6 +108,15 @@ "header_base": "//foundation/distributeddatamgr/relational_store/interfaces/ndk/include" } }, + { + "name": "//foundation/distributeddatamgr/relational_store/interfaces/rdb_ndk_utils:native_rdb_ndk_utils", + "header": { + "header_files": [ + "rdb_ndk_utils.h" + ], + "header_base": "//foundation/distributeddatamgr/relational_store/interfaces/rdb_ndk_utils/include" + } + }, { "name": "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb:native_rdb", "header": { @@ -114,6 +124,7 @@ "abs_rdb_predicates.h", "abs_result_set.h", "abs_shared_result_set.h", + "knowledge_types.h", "rdb_common.h", "rdb_errno.h", "rdb_helper.h", @@ -180,21 +191,10 @@ } }, { - "name": "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/gdb:native_graphstore", + "name": "//foundation/distributeddatamgr/relational_store/frameworks/cj:cj_relational_store_ffi", "header": { - "header_files": [ - "edge.h", - "gdb_errors.h", - "gdb_helper.h", - "gdb_store.h", - "gdb_store_config.h", - "gdb_transaction.h", - "path.h", - "path_segment.h", - "result.h", - "vertex.h" - ], - "header_base": "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/gdb/include" + "header_files": [], + "header_base": "//foundation/distributeddatamgr/relational_store/frameworks/cj/include" } } ], @@ -206,18 +206,22 @@ "//foundation/distributeddatamgr/relational_store/test/js/relationalstore:unittest", "//foundation/distributeddatamgr/relational_store/test/js/clouddata:cloudtest", "//foundation/distributeddatamgr/relational_store/test/ndk:unittest", + "//foundation/distributeddatamgr/relational_store/test/ndk:fuzztest", + "//foundation/distributeddatamgr/relational_store/test/ets/cloud_data:stage_unittest", "//foundation/distributeddatamgr/relational_store/test/native/appdatafwk:unittest", + "//foundation/distributeddatamgr/relational_store/test/native/clouddata:fuzztest", "//foundation/distributeddatamgr/relational_store/test/native/clouddata:unittest", "//foundation/distributeddatamgr/relational_store/test/native/dataability:unittest", "//foundation/distributeddatamgr/relational_store/test/native/rdb:unittest", + "//foundation/distributeddatamgr/relational_store/test/native/rdb/unittest/mock_obs_manage_test:unittest", + "//foundation/distributeddatamgr/relational_store/test/native/rdb/unittest/dynamic_load_test:unittest", + "//foundation/distributeddatamgr/relational_store/test/native/rdb/unittest/sqlite_statement_test:unittest", + "//foundation/distributeddatamgr/relational_store/test/native/rdb/unittest/mockservice:unittest", "//foundation/distributeddatamgr/relational_store/test/native/rdb:fuzztest", "//foundation/distributeddatamgr/relational_store/test/native/rdb_data_ability_adapter:unittest", "//foundation/distributeddatamgr/relational_store/test/native/rdb_data_share_adapter:unittest", "//foundation/distributeddatamgr/relational_store/test/native/rdb:distributedtest", - "//foundation/distributeddatamgr/relational_store/test/native/gdb:unittest", - "//foundation/distributeddatamgr/relational_store/test/native/gdb:fuzztest", - "//foundation/distributeddatamgr/relational_store/test/js/gdb:performancetest", - "//foundation/distributeddatamgr/relational_store/test/js/gdb:unittest" + "//foundation/distributeddatamgr/relational_store/test/ets/relational_store:stage_unittest" ] } } diff --git a/relational_store/frameworks/cj/BUILD.gn b/relational_store/frameworks/cj/BUILD.gn index 4a01d574..3450a166 100644 --- a/relational_store/frameworks/cj/BUILD.gn +++ b/relational_store/frameworks/cj/BUILD.gn @@ -55,6 +55,7 @@ ohos_shared_library("cj_relational_store_ffi") { "common_event_service:cesfwk_innerkits", "hilog:libhilog", "hitrace:hitrace_meter", + "ipc:ipc_single", "napi:ace_napi", "napi:cj_bind_ffi", "napi:cj_bind_native", diff --git a/relational_store/frameworks/cj/include/relational_store_ffi.h b/relational_store/frameworks/cj/include/relational_store_ffi.h index 9fb62f3c..a499e27c 100644 --- a/relational_store/frameworks/cj/include/relational_store_ffi.h +++ b/relational_store/frameworks/cj/include/relational_store_ffi.h @@ -216,7 +216,7 @@ FFI_EXPORT void FfiOHOSRelationalStoreExecuteSqlBindArgs( FFI_EXPORT ValuesBucket FfiOHOSRelationalStoreGetRow(int64_t id, int32_t *errCode); FFI_EXPORT int32_t FfiOHOSRelationalStoreOn( - int64_t id, const char *event, bool interProcess, void (*callback)(), void (*callbackRef)()); + int64_t id, const char *event, bool interProcess, int64_t callback, void (*callbackRef)()); FFI_EXPORT int32_t FfiOHOSRelationalStoreOnArrStr(int64_t id, int32_t subscribeType, int64_t callbackId); @@ -224,7 +224,7 @@ FFI_EXPORT int32_t FfiOHOSRelationalStoreOnChangeInfo(int64_t id, int32_t subscr FFI_EXPORT int32_t FfiOHOSRelationalStoreOnProgressDetails(int64_t id, int64_t callbackId); -FFI_EXPORT int32_t FfiOHOSRelationalStoreOff(int64_t id, const char *event, bool interProcess, void (*callback)()); +FFI_EXPORT int32_t FfiOHOSRelationalStoreOff(int64_t id, const char *event, bool interProcess, int64_t callback); FFI_EXPORT int32_t FfiOHOSRelationalStoreOffAll(int64_t id, const char *event, bool interProcess); diff --git a/relational_store/frameworks/cj/include/relational_store_impl_rdbpredicatesproxy.h b/relational_store/frameworks/cj/include/relational_store_impl_rdbpredicatesproxy.h index 0fb1ce6d..1f3616be 100644 --- a/relational_store/frameworks/cj/include/relational_store_impl_rdbpredicatesproxy.h +++ b/relational_store/frameworks/cj/include/relational_store_impl_rdbpredicatesproxy.h @@ -97,8 +97,32 @@ public: void NotEqualTo(const char *field, ValueType value); + void NotContains(const char* field, const char* value); + + void NotLike(const char* field, const char* value); + std::shared_ptr GetPredicates(); + void LessThanOrEqualToEx(const char *field, const ValueTypeEx *value); + + void EqualToEx(const char *field, const ValueTypeEx *value); + + void GreaterThanOrEqualToEx(const char *field, const ValueTypeEx *value); + + void GreaterThanEx(const char *field, const ValueTypeEx *value); + + void NotBetweenEx(const char *field, const ValueTypeEx *lowValue, const ValueTypeEx *highValue); + + void LessThanEx(const char *field, const ValueTypeEx *value); + + void BetweenEx(const char *field, const ValueTypeEx *lowValue, const ValueTypeEx *highValue); + + void InEx(const char *field, ValueTypeEx *values, int64_t valuesSize); + + void NotInEx(const char *field, ValueTypeEx *values, int64_t valuesSize); + + void NotEqualToEx(const char *field, const ValueTypeEx *value); + private: std::shared_ptr predicates_; diff --git a/relational_store/frameworks/cj/include/relational_store_impl_rdbstore.h b/relational_store/frameworks/cj/include/relational_store_impl_rdbstore.h index b2edd3f3..7e05d9a1 100644 --- a/relational_store/frameworks/cj/include/relational_store_impl_rdbstore.h +++ b/relational_store/frameworks/cj/include/relational_store_impl_rdbstore.h @@ -34,7 +34,7 @@ namespace Relational { class RdbStoreObserverImpl : public DistributedRdb::RdbStoreObserver { public: enum FuncType : int32_t { NoParam = 0, ParamArrStr, ParamChangeInfo }; - RdbStoreObserverImpl(std::function *callback, const std::function &callbackRef); + RdbStoreObserverImpl(int64_t callback, const std::function &callbackRef); RdbStoreObserverImpl(int64_t id, FuncType type, int32_t mode = DistributedRdb::REMOTE); ~RdbStoreObserverImpl() override = default; void OnChange() override @@ -59,10 +59,10 @@ public: { return callbackId; }; - std::function *GetCallBack(); + int64_t GetCallBack(); private: - std::function *m_callback = nullptr; + int64_t m_callback = 0; std::function m_callbackRef = nullptr; int32_t mode_ = DistributedRdb::REMOTE; int64_t callbackId = 0; @@ -126,21 +126,21 @@ public: NativeRdb::ConflictResolution conflictResolution, int32_t *errCode); std::shared_ptr QuerySql(const char *sql, ValueType *bindArgs, int64_t size); void ExecuteSql(const char *sql, ValueType *bindArgs, int64_t bindArgsSize, int32_t *errCode); - int32_t RegisterObserver(const char *event, bool interProcess, std::function *callback, + int32_t RegisterObserver(const char *event, bool interProcess, int64_t callback, const std::function &callbackRef); int32_t RegisteredObserver(DistributedRdb::SubscribeOption option, std::map>> &observers, - std::function *callback, const std::function &callbackRef); + int64_t callback, const std::function &callbackRef); int32_t RegisterObserverArrStr(int32_t subscribeType, int64_t callbackId); int32_t RegisterObserverChangeInfo(int32_t subscribeType, int64_t callbackId); int32_t RegisterObserverProgressDetails(int64_t callbackId); bool HasRegisteredObserver( - std::function *callback, std::list> &observers); - int32_t UnRegisterObserver(const char *event, bool interProcess, std::function *callback); + int64_t callback, std::list> &observers); + int32_t UnRegisterObserver(const char *event, bool interProcess, int64_t callback); int32_t UnRegisterAllObserver(const char *event, bool interProcess); int32_t UnRegisteredObserver(DistributedRdb::SubscribeOption option, std::map>> &observers, - std::function *callback); + int64_t callback); int32_t UnRegisteredAllObserver(DistributedRdb::SubscribeOption option, std::map>> &observers); int32_t UnRegisterObserverArrStrChangeInfo(int32_t subscribeType, int64_t callbackId); @@ -151,6 +151,13 @@ public: int32_t GetVersion(int32_t &errCode); void SetVersion(int32_t value, int32_t &errCode); ModifyTime GetModifyTime(char *cTable, char *cColumnName, CArrPRIKeyType &cPrimaryKeys, int32_t &errCode); + int32_t GetRebuilt(); + int64_t InsertEx(const char *table, ValuesBucketEx valuesBucket, int32_t conflict, int32_t *errCode); + int32_t UpdateEx(ValuesBucketEx valuesBucket, RdbPredicatesImpl &predicates, + NativeRdb::ConflictResolution conflictResolution, int32_t *errCode); + int32_t BatchInsertEx(int64_t &insertNum, const char *tableName, ValuesBucketEx *valuesBuckets, int64_t valuesSize); + std::shared_ptr QuerySqlEx(const char *sql, ValueTypeEx *bindArgs, int64_t size); + void ExecuteSqlEx(const char *sql, ValueTypeEx *bindArgs, int64_t bindArgsSize, int32_t *errCode); private: friend class OHOS::FFI::RuntimeType; @@ -167,9 +174,13 @@ private: int64_t GetRdbStore(OHOS::AbilityRuntime::Context *context, StoreConfig config, int32_t *errCode); +int64_t GetRdbStoreEx(OHOS::AbilityRuntime::Context *context, const StoreConfigEx *config, int32_t *errCode); + void DeleteRdbStore(OHOS::AbilityRuntime::Context *context, const char *name, int32_t *errCode); void DeleteRdbStoreConfig(OHOS::AbilityRuntime::Context *context, StoreConfig config, int32_t *errCode); + +void DeleteRdbStoreConfigEx(OHOS::AbilityRuntime::Context *context, const StoreConfigEx *config, int32_t *errCode); } // namespace Relational } // namespace OHOS diff --git a/relational_store/frameworks/cj/include/relational_store_impl_resultsetproxy.h b/relational_store/frameworks/cj/include/relational_store_impl_resultsetproxy.h index 041f4f0b..f7750328 100644 --- a/relational_store/frameworks/cj/include/relational_store_impl_resultsetproxy.h +++ b/relational_store/frameworks/cj/include/relational_store_impl_resultsetproxy.h @@ -87,6 +87,10 @@ public: ValuesBucket GetRow(int32_t *rtnCode); + ValuesBucketEx GetRowEx(int32_t *rtnCode); + + ValueTypeEx GetValue(int32_t columnIndex, int32_t* rtnCode); + std::shared_ptr resultSetValue; private: diff --git a/relational_store/frameworks/cj/include/relational_store_utils.h b/relational_store/frameworks/cj/include/relational_store_utils.h index c76fc437..6a3d1c0c 100644 --- a/relational_store/frameworks/cj/include/relational_store_utils.h +++ b/relational_store/frameworks/cj/include/relational_store_utils.h @@ -23,8 +23,36 @@ namespace OHOS { namespace Relational { +#define ERROR_VALUE (-1) + char *MallocCString(const std::string &origin); +struct CArrUI8 { + uint8_t *head; + int64_t size; +}; + +struct CArrFloat { + float *head; + int64_t size; +}; + +struct CArrStr { + char **head; + int64_t size; +}; + +struct CryptoParam { + CArrUI8 encryptKey; + int32_t iterNum; + int32_t encryptAlgo; + int32_t hmacAlgo; + int32_t kdfAlgo; + uint32_t cryptoPageSize; +}; + +OHOS::NativeRdb::RdbStoreConfig::CryptoParam ToCCryptoParam(CryptoParam param); + struct StoreConfig { char *name; int32_t securityLevel; @@ -35,6 +63,24 @@ struct StoreConfig { bool autoCleanDirtyData; }; +struct StoreConfigEx { + char *name; + int32_t securityLevel; + bool encrypt; + char *dataGroupId; + char *customDir; + char *rootDir; + bool isSearchable; + bool autoCleanDirtyData; + bool allowRebuild; + bool isReadOnly; + CArrStr pluginLibs; + CryptoParam cryptoParam; + bool vector; + int32_t tokenizer; + bool persist; +}; + struct Asset { const char *name; const char *uri; @@ -50,16 +96,6 @@ struct Assets { int64_t size; }; -struct CArrUI8 { - uint8_t *head; - int64_t size; -}; - -struct CArrStr { - char **head; - int64_t size; -}; - CArrStr VectorToCArrStr(const std::vector &devices); std::vector CArrStrToVector(CArrStr carr); @@ -75,7 +111,38 @@ struct ValueType { uint8_t tag; }; -enum TagType { TYPE_NULL, TYPE_INT, TYPE_DOU, TYPE_STR, TYPE_BOOL, TYPE_BLOB, TYPE_ASSET, TYPE_ASSETS }; +struct BigInt { + CArrUI8 value; + bool sign; +}; + +struct ValueTypeEx { + int64_t integer; + double dou; + char *string; + bool boolean; + CArrUI8 uint8Array; + Asset asset; + Assets assets; + CArrFloat floatArray; + BigInt bigInt; + uint8_t tag; +}; + +std::vector CArrUI8ToVector(CArrUI8 carr); + +enum TagType { + TYPE_NULL, + TYPE_INT, + TYPE_DOU, + TYPE_STR, + TYPE_BOOL, + TYPE_BLOB, + TYPE_ASSET, + TYPE_ASSETS, + TYPE_FLOATARR, + TYPE_BIGINT +}; struct ValuesBucket { char **key; @@ -83,8 +150,16 @@ struct ValuesBucket { int64_t size; }; +struct ValuesBucketEx { + char **key; + ValueTypeEx *value; + int64_t size; +}; + NativeRdb::ValueObject ValueTypeToValueObject(const ValueType &value); +NativeRdb::ValueObject ValueTypeExToValueObject(const ValueTypeEx &value); + struct CArrInt32 { int32_t *head; int64_t size; @@ -98,6 +173,8 @@ struct CArrSyncResult { ValueType ValueObjectToValueType(const NativeRdb::ValueObject &object); +ValueTypeEx ValueObjectToValueTypeEx(const NativeRdb::ValueObject &object); + struct RetPRIKeyType { int64_t integer; double dou; diff --git a/relational_store/frameworks/cj/src/relational_store_ffi.cpp b/relational_store/frameworks/cj/src/relational_store_ffi.cpp index f986a755..81ff6c78 100644 --- a/relational_store/frameworks/cj/src/relational_store_ffi.cpp +++ b/relational_store/frameworks/cj/src/relational_store_ffi.cpp @@ -22,8 +22,6 @@ #include "napi_rdb_js_utils.h" #include "rdb_errno.h" #include "relational_store_utils.h" -#include "rdb_errno.h" -#include "js_utils.h" using namespace OHOS::FFI; @@ -35,6 +33,12 @@ int64_t FfiOHOSRelationalStoreGetRdbStore(OHOS::AbilityRuntime::Context *context return GetRdbStore(context, config, errCode); } +FFI_EXPORT int64_t FfiOHOSRelationalStoreGetRdbStoreEx(OHOS::AbilityRuntime::Context *context, + const StoreConfigEx *config, int32_t *errCode) +{ + return GetRdbStoreEx(context, config, errCode); +} + void FfiOHOSRelationalStoreDeleteRdbStore(OHOS::AbilityRuntime::Context *context, const char *name, int32_t *errCode) { DeleteRdbStore(context, name, errCode); @@ -46,6 +50,12 @@ void FfiOHOSRelationalStoreDeleteRdbStoreConfig( DeleteRdbStoreConfig(context, config, errCode); } +void FfiOHOSRelationalStoreDeleteRdbStoreConfigEx( + OHOS::AbilityRuntime::Context *context, const StoreConfigEx *config, int32_t *errCode) +{ + DeleteRdbStoreConfigEx(context, config, errCode); +} + int64_t FfiOHOSRelationalStoreRdbPredicatesConstructor(const char *tableName) { auto nativeRdbPredicates = FFIData::Create(tableName); @@ -265,6 +275,16 @@ int32_t FfiOHOSRelationalStoreLessThanOrEqualTo(int64_t id, const char *field, V return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreLessThanOrEqualToEx(int64_t id, const char *field, const ValueTypeEx *value) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->LessThanOrEqualToEx(field, value); + return 0; +} + int32_t FfiOHOSRelationalStoreEqualTo(int64_t id, const char *field, ValueType value) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -275,6 +295,16 @@ int32_t FfiOHOSRelationalStoreEqualTo(int64_t id, const char *field, ValueType v return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreEqualToEx(int64_t id, const char *field, const ValueTypeEx *value) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->EqualToEx(field, value); + return 0; +} + int32_t FfiOHOSRelationalStoreGreaterThanOrEqualTo(int64_t id, const char *field, ValueType value) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -285,6 +315,16 @@ int32_t FfiOHOSRelationalStoreGreaterThanOrEqualTo(int64_t id, const char *field return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreGreaterThanOrEqualToEx(int64_t id, const char *field, const ValueTypeEx *value) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->GreaterThanOrEqualToEx(field, value); + return 0; +} + int32_t FfiOHOSRelationalStoreGreaterThan(int64_t id, const char *field, ValueType value) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -295,6 +335,16 @@ int32_t FfiOHOSRelationalStoreGreaterThan(int64_t id, const char *field, ValueTy return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreGreaterThanEx(int64_t id, const char *field, const ValueTypeEx *value) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->GreaterThanEx(field, value); + return 0; +} + int32_t FfiOHOSRelationalStoreNotBetween(int64_t id, const char *field, ValueType lowValue, ValueType highValue) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -305,6 +355,17 @@ int32_t FfiOHOSRelationalStoreNotBetween(int64_t id, const char *field, ValueTyp return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreNotBetweenEx(int64_t id, const char *field, const ValueTypeEx *lowValue, + const ValueTypeEx *highValue) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->NotBetweenEx(field, lowValue, highValue); + return 0; +} + int32_t FfiOHOSRelationalStoreLessThan(int64_t id, const char *field, ValueType value) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -315,6 +376,16 @@ int32_t FfiOHOSRelationalStoreLessThan(int64_t id, const char *field, ValueType return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreLessThanEx(int64_t id, const char *field, const ValueTypeEx *value) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->LessThanEx(field, value); + return 0; +} + int32_t FfiOHOSRelationalStoreBetween(int64_t id, const char *field, ValueType lowValue, ValueType highValue) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -325,6 +396,17 @@ int32_t FfiOHOSRelationalStoreBetween(int64_t id, const char *field, ValueType l return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreBetweenEx(int64_t id, const char *field, const ValueTypeEx *lowValue, + const ValueTypeEx *highValue) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->BetweenEx(field, lowValue, highValue); + return 0; +} + int32_t FfiOHOSRelationalStoreIn(int64_t id, const char *field, ValueType *values, int64_t valuesSize) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -335,6 +417,16 @@ int32_t FfiOHOSRelationalStoreIn(int64_t id, const char *field, ValueType *value return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreInEx(int64_t id, const char *field, ValueTypeEx *values, int64_t valuesSize) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->InEx(field, values, valuesSize); + return 0; +} + int32_t FfiOHOSRelationalStoreNotIn(int64_t id, const char *field, ValueType *values, int64_t valuesSize) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -345,6 +437,16 @@ int32_t FfiOHOSRelationalStoreNotIn(int64_t id, const char *field, ValueType *va return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreNotInEx(int64_t id, const char *field, ValueTypeEx *values, int64_t valuesSize) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->NotInEx(field, values, valuesSize); + return 0; +} + int32_t FfiOHOSRelationalStoreNotEqualTo(int64_t id, const char *field, ValueType value) { auto nativeRdbPredicates = FFIData::GetData(id); @@ -355,9 +457,23 @@ int32_t FfiOHOSRelationalStoreNotEqualTo(int64_t id, const char *field, ValueTyp return 0; } +FFI_EXPORT int32_t FfiOHOSRelationalStoreNotEqualToEx(int64_t id, const char *field, const ValueTypeEx *value) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->NotEqualToEx(field, value); + return 0; +} + + int64_t FfiOHOSRelationalStoreQuery( int64_t id, int64_t predicatesId, char **columns, int64_t columnsSize, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = -1; @@ -370,8 +486,7 @@ int64_t FfiOHOSRelationalStoreQuery( } auto resultSet = nativeRdbStore->Query(*nativeRdbPredicates, columns, columnsSize); if (resultSet == nullptr) { - // If the API version is greater than or equal to 20, throw E_ALREADY_CLOSED. - *errCode = (AppDataMgrJsKit::JSUtils::GetHapVersion() >= 20) ? NativeRdb::E_ALREADY_CLOSED : NativeRdb::E_ERROR; + *errCode = RelationalStoreJsKit::E_INNER_ERROR; return -1; } else { *errCode = RelationalStoreJsKit::OK; @@ -408,6 +523,9 @@ int64_t FfiOHOSRelationalStoreRemoteQuery( int64_t FfiOHOSRelationalStoreDelete(int64_t id, int64_t predicatesId, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = -1; @@ -507,6 +625,9 @@ int32_t FfiOHOSRelationalStoreBeginTransaction(int64_t id) int64_t FfiOHOSRelationalStoreInsert( int64_t id, const char *table, ValuesBucket valuesBucket, int32_t conflict, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = -1; @@ -515,9 +636,26 @@ int64_t FfiOHOSRelationalStoreInsert( return nativeRdbStore->Insert(table, valuesBucket, conflict, errCode); } +FFI_EXPORT int64_t FfiOHOSRelationalStoreInsertEx( + int64_t id, const char *table, ValuesBucketEx valuesBucket, int32_t conflict, int32_t *errCode) +{ + if (errCode == nullptr) { + return -1; + } + auto nativeRdbStore = FFIData::GetData(id); + if (nativeRdbStore == nullptr) { + *errCode = -1; + return -1; + } + return nativeRdbStore->InsertEx(table, valuesBucket, conflict, errCode); +} + int64_t FfiOHOSRelationalStoreUpdate(int64_t id, ValuesBucket valuesBucket, int64_t predicatesId, NativeRdb::ConflictResolution conflictResolution, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeRdbStore = FFIData::GetData(id); auto nativeRdbSPredicates = FFIData::GetData(predicatesId); if (nativeRdbStore == nullptr || nativeRdbSPredicates == nullptr) { @@ -527,8 +665,26 @@ int64_t FfiOHOSRelationalStoreUpdate(int64_t id, ValuesBucket valuesBucket, int6 return nativeRdbStore->Update(valuesBucket, *nativeRdbSPredicates, conflictResolution, errCode); } +FFI_EXPORT int64_t FfiOHOSRelationalStoreUpdateEx(int64_t id, ValuesBucketEx valuesBucket, int64_t predicatesId, + NativeRdb::ConflictResolution conflictResolution, int32_t *errCode) +{ + if (errCode == nullptr) { + return -1; + } + auto nativeRdbStore = FFIData::GetData(id); + auto nativeRdbSPredicates = FFIData::GetData(predicatesId); + if (nativeRdbStore == nullptr || nativeRdbSPredicates == nullptr) { + *errCode = -1; + return -1; + } + return nativeRdbStore->UpdateEx(valuesBucket, *nativeRdbSPredicates, conflictResolution, errCode); +} + void FfiOHOSRelationalStoreExecuteSql(int64_t id, const char *sql, int32_t *errCode) { + if (errCode == nullptr) { + return; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = -1; @@ -539,6 +695,9 @@ void FfiOHOSRelationalStoreExecuteSql(int64_t id, const char *sql, int32_t *errC CArrSyncResult FfiOHOSRelationalStoreSync(int64_t id, int32_t mode, int64_t predicatesId, int32_t *errCode) { + if (errCode == nullptr) { + return CArrSyncResult{ nullptr, nullptr, 0 }; + } auto nativeRdbStore = FFIData::GetData(id); auto nativeRdbPredicates = FFIData::GetData(predicatesId); if (nativeRdbStore == nullptr || nativeRdbPredicates == nullptr) { @@ -559,6 +718,9 @@ CArrStr FfiOHOSRelationalStoreGetAllColumnNames(int64_t id) int32_t FfiOHOSRelationalStoreGetColumnCount(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -569,6 +731,9 @@ int32_t FfiOHOSRelationalStoreGetColumnCount(int64_t id, int32_t *errCode) int32_t FfiOHOSRelationalStoreGetRowCount(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -579,6 +744,9 @@ int32_t FfiOHOSRelationalStoreGetRowCount(int64_t id, int32_t *errCode) int32_t FfiOHOSRelationalStoreGetRowIndex(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -589,6 +757,9 @@ int32_t FfiOHOSRelationalStoreGetRowIndex(int64_t id, int32_t *errCode) bool FfiOHOSRelationalStoreIsAtFirstRow(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -600,6 +771,9 @@ bool FfiOHOSRelationalStoreIsAtFirstRow(int64_t id, int32_t *errCode) bool FfiOHOSRelationalStoreIsAtLastRow(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -611,6 +785,9 @@ bool FfiOHOSRelationalStoreIsAtLastRow(int64_t id, int32_t *errCode) bool FfiOHOSRelationalStoreIsEnded(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -622,6 +799,9 @@ bool FfiOHOSRelationalStoreIsEnded(int64_t id, int32_t *errCode) bool FfiOHOSRelationalStoreIsStarted(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -633,6 +813,9 @@ bool FfiOHOSRelationalStoreIsStarted(int64_t id, int32_t *errCode) bool FfiOHOSRelationalStoreIsClosed(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -644,6 +827,9 @@ bool FfiOHOSRelationalStoreIsClosed(int64_t id, int32_t *errCode) double FfiOHOSRelationalStoreGetDouble(int64_t id, int32_t columnIndex, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return -1; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -654,6 +840,9 @@ double FfiOHOSRelationalStoreGetDouble(int64_t id, int32_t columnIndex, int32_t bool FfiOHOSRelationalStoreGoToRow(int64_t id, int32_t position, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -664,6 +853,9 @@ bool FfiOHOSRelationalStoreGoToRow(int64_t id, int32_t position, int32_t *rtnCod bool FfiOHOSRelationalStoreGoToPreviousRow(int64_t id, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -674,6 +866,9 @@ bool FfiOHOSRelationalStoreGoToPreviousRow(int64_t id, int32_t *rtnCode) bool FfiOHOSRelationalStoreGoToLastRow(int64_t id, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -684,6 +879,9 @@ bool FfiOHOSRelationalStoreGoToLastRow(int64_t id, int32_t *rtnCode) char *FfiOHOSRelationalStoreGetColumnName(int64_t id, int32_t columnIndex, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return nullptr; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -694,6 +892,9 @@ char *FfiOHOSRelationalStoreGetColumnName(int64_t id, int32_t columnIndex, int32 bool FfiOHOSRelationalStoreIsColumnNull(int64_t id, int32_t columnIndex, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -704,6 +905,9 @@ bool FfiOHOSRelationalStoreIsColumnNull(int64_t id, int32_t columnIndex, int32_t Asset FfiOHOSRelationalStoreGetAsset(int64_t id, int32_t columnIndex, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return Asset{ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, 0 }; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -723,6 +927,9 @@ int32_t FfiOHOSRelationalStoreClose(int64_t id) int32_t FfiOHOSRelationalStoreGetColumnIndex(int64_t id, char *columnName, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return -1; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -733,6 +940,9 @@ int32_t FfiOHOSRelationalStoreGetColumnIndex(int64_t id, char *columnName, int32 char *FfiOHOSRelationalStoreGetString(int64_t id, int32_t columnIndex, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return nullptr; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -743,6 +953,9 @@ char *FfiOHOSRelationalStoreGetString(int64_t id, int32_t columnIndex, int32_t * bool FfiOHOSRelationalStoreGoToFirstRow(int64_t id, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -753,6 +966,9 @@ bool FfiOHOSRelationalStoreGoToFirstRow(int64_t id, int32_t *rtnCode) int64_t FfiOHOSRelationalStoreGetLong(int64_t id, int32_t columnIndex, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return -1; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -763,6 +979,9 @@ int64_t FfiOHOSRelationalStoreGetLong(int64_t id, int32_t columnIndex, int32_t * bool FfiOHOSRelationalStoreGoToNextRow(int64_t id, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -773,6 +992,9 @@ bool FfiOHOSRelationalStoreGoToNextRow(int64_t id, int32_t *rtnCode) CArrUI8 FfiOHOSRelationalStoreGetBlob(int64_t id, int32_t columnIndex, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return CArrUI8{ nullptr, 0 }; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -783,6 +1005,9 @@ CArrUI8 FfiOHOSRelationalStoreGetBlob(int64_t id, int32_t columnIndex, int32_t * bool FfiOHOSRelationalStoreGoTo(int64_t id, int32_t offset, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return false; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -793,6 +1018,9 @@ bool FfiOHOSRelationalStoreGoTo(int64_t id, int32_t offset, int32_t *rtnCode) Assets FfiOHOSRelationalStoreGetAssets(int64_t id, int32_t columnIndex, int32_t *rtnCode) { + if (rtnCode == nullptr) { + return Assets{ nullptr, 0 }; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *rtnCode = -1; @@ -803,6 +1031,9 @@ Assets FfiOHOSRelationalStoreGetAssets(int64_t id, int32_t columnIndex, int32_t ValuesBucket FfiOHOSRelationalStoreGetRow(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return ValuesBucket{ nullptr, nullptr, 0 }; + } auto nativeResultSet = FFIData::GetData(id); if (nativeResultSet == nullptr) { *errCode = -1; @@ -811,6 +1042,32 @@ ValuesBucket FfiOHOSRelationalStoreGetRow(int64_t id, int32_t *errCode) return nativeResultSet->GetRow(errCode); } +FFI_EXPORT ValuesBucketEx FfiOHOSRelationalStoreGetRowEx(int64_t id, int32_t *errCode) +{ + if (errCode == nullptr) { + return ValuesBucketEx{ nullptr, nullptr, 0 }; + } + auto nativeResultSet = FFIData::GetData(id); + if (nativeResultSet == nullptr) { + *errCode = -1; + return ValuesBucketEx{ nullptr, nullptr, 0 }; + } + return nativeResultSet->GetRowEx(errCode); +} + +FFI_EXPORT ValueTypeEx FfiOHOSRelationalStoreResultSetGetValue(int64_t id, int32_t columnIndex, int32_t* errCode) +{ + if (errCode == nullptr) { + return ValueTypeEx{ 0 }; + } + auto nativeResultSet = FFIData::GetData(id); + if (nativeResultSet == nullptr) { + *errCode = -1; + return ValueTypeEx{ 0 }; + } + return nativeResultSet->GetValue(columnIndex, errCode); +} + int32_t FfiOHOSRelationalStoreCleanDirtyData(int64_t id, const char *tableName, uint64_t cursor) { auto nativeRdbStore = FFIData::GetData(id); @@ -823,6 +1080,9 @@ int32_t FfiOHOSRelationalStoreCleanDirtyData(int64_t id, const char *tableName, int32_t FfiOHOSRelationalStoreBatchInsert( int64_t id, const char *tableName, ValuesBucket *values, int64_t valuesSize, int64_t *insertNum) { + if (insertNum == nullptr) { + return -1; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { return -1; @@ -830,8 +1090,24 @@ int32_t FfiOHOSRelationalStoreBatchInsert( return nativeRdbStore->BatchInsert(*insertNum, tableName, values, valuesSize); } +FFI_EXPORT int32_t FfiOHOSRelationalStoreBatchInsertEx( + int64_t id, const char *tableName, ValuesBucketEx *values, int64_t valuesSize, int64_t *insertNum) +{ + if (insertNum == nullptr) { + return -1; + } + auto nativeRdbStore = FFIData::GetData(id); + if (nativeRdbStore == nullptr) { + return -1; + } + return nativeRdbStore->BatchInsertEx(*insertNum, tableName, values, valuesSize); +} + int64_t FfiOHOSRelationalStoreQuerySql(int64_t id, const char *sql, ValueType *bindArgs, int64_t size, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = RelationalStoreJsKit::E_INNER_ERROR; @@ -852,9 +1128,38 @@ int64_t FfiOHOSRelationalStoreQuerySql(int64_t id, const char *sql, ValueType *b return nativeResultSet->GetID(); } +FFI_EXPORT int64_t FfiOHOSRelationalStoreQuerySqlEx(int64_t id, const char *sql, ValueTypeEx *bindArgs, int64_t size, + int32_t *errCode) +{ + if (errCode == nullptr) { + return -1; + } + auto nativeRdbStore = FFIData::GetData(id); + if (nativeRdbStore == nullptr) { + *errCode = RelationalStoreJsKit::E_INNER_ERROR; + return -1; + } + auto resultSet = nativeRdbStore->QuerySqlEx(sql, bindArgs, size); + if (resultSet == nullptr) { + *errCode = RelationalStoreJsKit::E_INNER_ERROR; + return -1; + } else { + *errCode = RelationalStoreJsKit::OK; + } + auto nativeResultSet = FFIData::Create(resultSet); + if (nativeResultSet == nullptr) { + *errCode = -1; + return -1; + } + return nativeResultSet->GetID(); +} + void FfiOHOSRelationalStoreExecuteSqlBindArgs( int64_t id, char *sql, ValueType *bindArgs, int64_t bindArgsSize, int32_t *errCode) { + if (errCode == nullptr) { + return; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = -1; @@ -863,15 +1168,29 @@ void FfiOHOSRelationalStoreExecuteSqlBindArgs( nativeRdbStore->ExecuteSql(sql, bindArgs, bindArgsSize, errCode); } +FFI_EXPORT void FfiOHOSRelationalStoreExecuteSqlBindArgsEx( + int64_t id, char *sql, ValueTypeEx *bindArgs, int64_t bindArgsSize, int32_t *errCode) +{ + if (errCode == nullptr) { + return; + } + auto nativeRdbStore = FFIData::GetData(id); + if (nativeRdbStore == nullptr) { + *errCode = -1; + return; + } + nativeRdbStore->ExecuteSqlEx(sql, bindArgs, bindArgsSize, errCode); +} + int32_t FfiOHOSRelationalStoreOn( - int64_t id, const char *event, bool interProcess, void (*callback)(), void (*callbackRef)()) + int64_t id, const char *event, bool interProcess, int64_t callback, void (*callbackRef)()) { auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { return -1; } auto onChange = [lambda = CJLambda::Create(callbackRef)]() -> void { lambda(); }; - return nativeRdbStore->RegisterObserver(event, interProcess, (std::function *)(callback), onChange); + return nativeRdbStore->RegisterObserver(event, interProcess, callback, onChange); } int32_t FfiOHOSRelationalStoreOnArrStr(int64_t id, int32_t subscribeType, int64_t callbackId) @@ -901,13 +1220,13 @@ int32_t FfiOHOSRelationalStoreOnProgressDetails(int64_t id, int64_t callbackId) return nativeRdbStore->RegisterObserverProgressDetails(callbackId); } -int32_t FfiOHOSRelationalStoreOff(int64_t id, const char *event, bool interProcess, void (*callback)()) +int32_t FfiOHOSRelationalStoreOff(int64_t id, const char *event, bool interProcess, int64_t callback) { auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { return -1; } - return nativeRdbStore->UnRegisterObserver(event, interProcess, (std::function *)(callback)); + return nativeRdbStore->UnRegisterObserver(event, interProcess, callback); } int32_t FfiOHOSRelationalStoreOffAll(int64_t id, const char *event, bool interProcess) @@ -975,6 +1294,9 @@ int32_t FfiOHOSRelationalStoreCloudSync(int64_t id, int32_t mode, CArrStr tables int32_t FfiOHOSRelationalStoreGetVersion(int64_t id, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = -1; @@ -985,6 +1307,9 @@ int32_t FfiOHOSRelationalStoreGetVersion(int64_t id, int32_t *errCode) void FfiOHOSRelationalStoreSetVersion(int64_t id, int32_t value, int32_t *errCode) { + if (errCode == nullptr) { + return; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = -1; @@ -996,6 +1321,9 @@ void FfiOHOSRelationalStoreSetVersion(int64_t id, int32_t value, int32_t *errCod ModifyTime FfiOHOSRelationalStoreGetModifyTime( int64_t id, char *cTable, char *cColumnName, CArrPRIKeyType cPrimaryKeys, int32_t *errCode) { + if (errCode == nullptr) { + return ModifyTime{ 0 }; + } auto nativeRdbStore = FFIData::GetData(id); if (nativeRdbStore == nullptr) { *errCode = -1; @@ -1003,6 +1331,39 @@ ModifyTime FfiOHOSRelationalStoreGetModifyTime( } return nativeRdbStore->GetModifyTime(cTable, cColumnName, cPrimaryKeys, *errCode); } + +FFI_EXPORT int32_t FfiOHOSRelationalStoreRdbPredicatesNotContains(int64_t id, const char *field, const char *value) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->NotContains(field, value); + return 0; +} + +FFI_EXPORT int32_t FfiOHOSRelationalStoreRdbPredicatesNotLike(int64_t id, const char *field, const char *value) +{ + auto nativeRdbPredicates = FFIData::GetData(id); + if (nativeRdbPredicates == nullptr) { + return -1; + } + nativeRdbPredicates->NotLike(field, value); + return 0; +} + +FFI_EXPORT int32_t FfiOHOSRelationalStoreRdbStoreGetRebuilt(int64_t id, int32_t *errCode) +{ + if (errCode == nullptr) { + return -1; + } + auto nativeRdbStore = FFIData::GetData(id); + if (nativeRdbStore == nullptr) { + *errCode = -1; + return 0; + } + return nativeRdbStore->GetRebuilt(); +} } } // namespace Relational } // namespace OHOS diff --git a/relational_store/frameworks/cj/src/relational_store_impl_rdbpredicatesproxy.cpp b/relational_store/frameworks/cj/src/relational_store_impl_rdbpredicatesproxy.cpp index eefe118d..a16988f6 100644 --- a/relational_store/frameworks/cj/src/relational_store_impl_rdbpredicatesproxy.cpp +++ b/relational_store/frameworks/cj/src/relational_store_impl_rdbpredicatesproxy.cpp @@ -20,6 +20,9 @@ namespace OHOS { namespace Relational { RdbPredicatesImpl::RdbPredicatesImpl(const char* tableName) { + if (tableName == nullptr) { + return; + } std::string str = tableName; predicates_ = std::make_shared(str); } @@ -47,36 +50,57 @@ namespace Relational { for (int64_t i = 0; i < devicesSize; i++) { devices.push_back(devicesArray[i]); } + if (predicates_ == nullptr) { + return; + } predicates_->InDevices(devices); } void RdbPredicatesImpl::InAllDevices() { + if (predicates_ == nullptr) { + return; + } predicates_->InAllDevices(); } void RdbPredicatesImpl::BeginWrap() { + if (predicates_ == nullptr) { + return; + } predicates_->BeginWrap(); } void RdbPredicatesImpl::EndWrap() { + if (predicates_ == nullptr) { + return; + } predicates_->EndWrap(); } void RdbPredicatesImpl::Or() { + if (predicates_ == nullptr) { + return; + } predicates_->Or(); } void RdbPredicatesImpl::And() { + if (predicates_ == nullptr) { + return; + } predicates_->And(); } void RdbPredicatesImpl::Contains(const char* field, const char* value) { + if (field == nullptr || value == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; std::string cvalue = value; predicates_->Contains(cfield, cvalue); @@ -84,6 +108,9 @@ namespace Relational { void RdbPredicatesImpl::BeginsWith(const char* field, const char* value) { + if (field == nullptr || value == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; std::string cvalue = value; predicates_->BeginsWith(cfield, cvalue); @@ -91,6 +118,9 @@ namespace Relational { void RdbPredicatesImpl::EndsWith(const char* field, const char* value) { + if (field == nullptr || value == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; std::string cvalue = value; predicates_->EndsWith(cfield, cvalue); @@ -98,18 +128,27 @@ namespace Relational { void RdbPredicatesImpl::IsNull(const char* field) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; predicates_->IsNull(cfield); } void RdbPredicatesImpl::IsNotNull(const char* field) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; predicates_->IsNotNull(cfield); } void RdbPredicatesImpl::Like(const char* field, const char* value) { + if (field == nullptr || value == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; std::string cvalue = value; predicates_->Like(cfield, cvalue); @@ -117,6 +156,9 @@ namespace Relational { void RdbPredicatesImpl::Glob(const char* field, const char* value) { + if (field == nullptr || value == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; std::string cvalue = value; predicates_->Glob(cfield, cvalue); @@ -124,35 +166,56 @@ namespace Relational { void RdbPredicatesImpl::OrderByAsc(const char* field) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; predicates_->OrderByAsc(cfield); } void RdbPredicatesImpl::OrderByDesc(const char* field) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; predicates_->OrderByDesc(cfield); } void RdbPredicatesImpl::Distinct() { + if (predicates_ == nullptr) { + return; + } predicates_->Distinct(); } void RdbPredicatesImpl::LimitAs(int32_t value) { + if (predicates_ == nullptr) { + return; + } predicates_->Limit(value); } void RdbPredicatesImpl::OffsetAs(int32_t rowOffset) { + if (predicates_ == nullptr) { + return; + } predicates_->Offset(rowOffset); } void RdbPredicatesImpl::GroupBy(const char** fieldsArray, int64_t fieldsSize) { + if (fieldsArray == nullptr || predicates_ == nullptr) { + return; + } std::vector fields; for (int64_t i = 0; i < fieldsSize; i++) { + if (fieldsArray[i] == nullptr) { + return; + } fields.push_back(fieldsArray[i]); } predicates_->GroupBy(fields); @@ -160,63 +223,162 @@ namespace Relational { void RdbPredicatesImpl::IndexedBy(const char* field) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; predicates_->IndexedBy(cfield); } void RdbPredicatesImpl::LessThanOrEqualTo(const char* field, ValueType value) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; NativeRdb::ValueObject valueObject = ValueTypeToValueObject(value); predicates_->LessThanOrEqualTo(cfield, valueObject); } + void RdbPredicatesImpl::LessThanOrEqualToEx(const char* field, const ValueTypeEx *value) + { + if (field == nullptr || value == nullptr || predicates_ == nullptr) { + return; + } + std::string cfield = field; + NativeRdb::ValueObject valueObject = ValueTypeExToValueObject(*value); + predicates_->LessThanOrEqualTo(cfield, valueObject); + } + void RdbPredicatesImpl::EqualTo(const char* field, ValueType value) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; NativeRdb::ValueObject valueObject = ValueTypeToValueObject(value); predicates_->EqualTo(cfield, valueObject); } + + void RdbPredicatesImpl::EqualToEx(const char* field, const ValueTypeEx *value) + { + if (field == nullptr || predicates_ == nullptr || value == nullptr) { + return; + } + std::string cfield = field; + NativeRdb::ValueObject valueObject = ValueTypeExToValueObject(*value); + predicates_->EqualTo(cfield, valueObject); + } void RdbPredicatesImpl::GreaterThanOrEqualTo(const char* field, ValueType value) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; NativeRdb::ValueObject valueObject = ValueTypeToValueObject(value); predicates_->GreaterThanOrEqualTo(cfield, valueObject); } + void RdbPredicatesImpl::GreaterThanOrEqualToEx(const char* field, const ValueTypeEx *value) + { + if (field == nullptr || predicates_ == nullptr || value == nullptr) { + return; + } + std::string cfield = field; + NativeRdb::ValueObject valueObject = ValueTypeExToValueObject(*value); + predicates_->GreaterThanOrEqualTo(cfield, valueObject); + } + void RdbPredicatesImpl::GreaterThan(const char* field, ValueType value) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; NativeRdb::ValueObject valueObject = ValueTypeToValueObject(value); predicates_->GreaterThan(cfield, valueObject); } + void RdbPredicatesImpl::GreaterThanEx(const char* field, const ValueTypeEx *value) + { + if (field == nullptr || predicates_ == nullptr || value == nullptr) { + return; + } + std::string cfield = field; + NativeRdb::ValueObject valueObject = ValueTypeExToValueObject(*value); + predicates_->GreaterThan(cfield, valueObject); + } + void RdbPredicatesImpl::NotBetween(const char* field, ValueType lowValue, ValueType highValue) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; NativeRdb::ValueObject lowValueObject = ValueTypeToValueObject(lowValue); NativeRdb::ValueObject highValueObject = ValueTypeToValueObject(highValue); predicates_->NotBetween(cfield, lowValueObject, highValueObject); } + void RdbPredicatesImpl::NotBetweenEx(const char* field, const ValueTypeEx *lowValue, const ValueTypeEx *highValue) + { + if (field == nullptr || predicates_ == nullptr || lowValue == nullptr || highValue == nullptr) { + return; + } + std::string cfield = field; + NativeRdb::ValueObject lowValueObject = ValueTypeExToValueObject(*lowValue); + NativeRdb::ValueObject highValueObject = ValueTypeExToValueObject(*highValue); + predicates_->NotBetween(cfield, lowValueObject, highValueObject); + } + void RdbPredicatesImpl::Between(const char* field, ValueType lowValue, ValueType highValue) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; NativeRdb::ValueObject lowValueObject = ValueTypeToValueObject(lowValue); NativeRdb::ValueObject highValueObject = ValueTypeToValueObject(highValue); predicates_->Between(cfield, lowValueObject, highValueObject); } + void RdbPredicatesImpl::BetweenEx(const char* field, const ValueTypeEx *lowValue, const ValueTypeEx *highValue) + { + if (field == nullptr || predicates_ == nullptr || lowValue == nullptr || highValue == nullptr) { + return; + } + std::string cfield = field; + NativeRdb::ValueObject lowValueObject = ValueTypeExToValueObject(*lowValue); + NativeRdb::ValueObject highValueObject = ValueTypeExToValueObject(*highValue); + predicates_->Between(cfield, lowValueObject, highValueObject); + } + void RdbPredicatesImpl::LessThan(const char* field, ValueType value) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; NativeRdb::ValueObject valueObject = ValueTypeToValueObject(value); predicates_->LessThan(cfield, valueObject); } + void RdbPredicatesImpl::LessThanEx(const char *field, const ValueTypeEx *value) + { + if (field == nullptr || predicates_ == nullptr || value == nullptr) { + return; + } + std::string cfield = field; + NativeRdb::ValueObject valueObject = ValueTypeExToValueObject(*value); + predicates_->LessThan(cfield, valueObject); + } + void RdbPredicatesImpl::In(const char* field, ValueType* values, int64_t valuesSize) { + if (field == nullptr || predicates_ == nullptr || values == nullptr) { + return; + } std::string cfield = field; std::vector valueObjects = std::vector(); for (int64_t i = 0; i < valuesSize; i++) { @@ -225,8 +387,24 @@ namespace Relational { predicates_->In(cfield, valueObjects); } + void RdbPredicatesImpl::InEx(const char* field, ValueTypeEx* values, int64_t valuesSize) + { + if (field == nullptr || predicates_ == nullptr || values == nullptr) { + return; + } + std::string cfield = field; + std::vector valueObjects = std::vector(); + for (int64_t i = 0; i < valuesSize; i++) { + valueObjects.push_back(ValueTypeExToValueObject(values[i])); + } + predicates_->In(cfield, valueObjects); + } + void RdbPredicatesImpl::NotIn(const char* field, ValueType* values, int64_t valuesSize) { + if (field == nullptr || predicates_ == nullptr || values == nullptr) { + return; + } std::string cfield = field; std::vector valueObjects = std::vector(); for (int64_t i = 0; i < valuesSize; i++) { @@ -235,11 +413,57 @@ namespace Relational { predicates_->NotIn(cfield, valueObjects); } + void RdbPredicatesImpl::NotInEx(const char* field, ValueTypeEx* values, int64_t valuesSize) + { + if (field == nullptr || predicates_ == nullptr || values == nullptr) { + return; + } + std::string cfield = field; + std::vector valueObjects = std::vector(); + for (int64_t i = 0; i < valuesSize; i++) { + valueObjects.push_back(ValueTypeExToValueObject(values[i])); + } + predicates_->NotIn(cfield, valueObjects); + } + void RdbPredicatesImpl::NotEqualTo(const char* field, ValueType value) { + if (field == nullptr || predicates_ == nullptr) { + return; + } std::string cfield = field; NativeRdb::ValueObject valueObject = ValueTypeToValueObject(value); predicates_->NotEqualTo(cfield, valueObject); } + + void RdbPredicatesImpl::NotEqualToEx(const char* field, const ValueTypeEx *value) + { + if (field == nullptr || predicates_ == nullptr || value == nullptr) { + return; + } + std::string cfield = field; + NativeRdb::ValueObject valueObject = ValueTypeExToValueObject(*value); + predicates_->NotEqualTo(cfield, valueObject); + } + + void RdbPredicatesImpl::NotContains(const char* field, const char* value) + { + if (field == nullptr || predicates_ == nullptr || value == nullptr) { + return; + } + std::string cfield = field; + std::string cvalue = value; + predicates_->NotContains(cfield, cvalue); + } + + void RdbPredicatesImpl::NotLike(const char* field, const char* value) + { + if (field == nullptr || predicates_ == nullptr || value == nullptr) { + return; + } + std::string cfield = field; + std::string cvalue = value; + predicates_->NotLike(field, value); + } } } \ No newline at end of file diff --git a/relational_store/frameworks/cj/src/relational_store_impl_rdbstore.cpp b/relational_store/frameworks/cj/src/relational_store_impl_rdbstore.cpp index 44af5f03..5a3e44c8 100644 --- a/relational_store/frameworks/cj/src/relational_store_impl_rdbstore.cpp +++ b/relational_store/frameworks/cj/src/relational_store_impl_rdbstore.cpp @@ -31,7 +31,6 @@ #include "rdb_common.h" #include "native_log.h" #include "relational_store_impl_rdbstore.h" -#include "js_utils.h" #ifndef PATH_SPLIT #define PATH_SPLIT '/' @@ -108,8 +107,33 @@ namespace Relational { int64_t mapSize = valuesBucket.size; NativeRdb::ValuesBucket nativeValuesBucket = NativeRdb::ValuesBucket(); + if (valuesBucket.value == nullptr || valuesBucket.key == nullptr) { + return nativeValuesBucket; + } for (int64_t i = 0; i < mapSize; i++) { NativeRdb::ValueObject valueObject = ValueTypeToValueObject(valuesBucket.value[i]); + if (valuesBucket.key[i] == nullptr) { + return nativeValuesBucket; + } + std::string keyStr = valuesBucket.key[i]; + nativeValuesBucket.Put(keyStr, valueObject); + } + return nativeValuesBucket; + } + + NativeRdb::ValuesBucket ConvertFromValueBucketEx(ValuesBucketEx valuesBucket) + { + int64_t mapSize = valuesBucket.size; + NativeRdb::ValuesBucket nativeValuesBucket = NativeRdb::ValuesBucket(); + + if (valuesBucket.value == nullptr || valuesBucket.key == nullptr) { + return nativeValuesBucket; + } + for (int64_t i = 0; i < mapSize; i++) { + NativeRdb::ValueObject valueObject = ValueTypeExToValueObject(valuesBucket.value[i]); + if (valuesBucket.key[i] == nullptr) { + return nativeValuesBucket; + } std::string keyStr = valuesBucket.key[i]; nativeValuesBucket.Put(keyStr, valueObject); } @@ -119,8 +143,14 @@ namespace Relational { std::shared_ptr RdbStoreImpl::Query(RdbPredicatesImpl &predicates, char** column, int64_t columnSize) { + if (column == nullptr) { + return nullptr; + } std::vector columnsVector = std::vector(); for (int64_t i = 0; i < columnSize; i++) { + if (column[i] == nullptr) { + return nullptr; + } columnsVector.push_back(std::string(column[i])); } auto resultSet = rdbStore_->Query(*(predicates.GetPredicates()), columnsVector); @@ -130,11 +160,20 @@ namespace Relational { std::shared_ptr RdbStoreImpl::RemoteQuery(char* device, RdbPredicatesImpl &predicates, char** column, int64_t columnSize) { + if (column == nullptr) { + return nullptr; + } std::vector columnsVector; for (int64_t i = 0; i < columnSize; i++) { + if (column[i] == nullptr) { + return nullptr; + } columnsVector.push_back(std::string(column[i])); } int32_t errCode; + if (predicates.GetPredicates() == nullptr) { + return nullptr; + } auto resultSet = rdbStore_->RemoteQuery(std::string(device), *(predicates.GetPredicates()), columnsVector, errCode); return resultSet; @@ -143,6 +182,9 @@ namespace Relational { int32_t RdbStoreImpl::Update(ValuesBucket valuesBucket, RdbPredicatesImpl &predicates, NativeRdb::ConflictResolution conflictResolution, int32_t *errCode) { + if (errCode == nullptr || rdbStore_ == nullptr || predicates.GetPredicates() == nullptr) { + return -1; + } int32_t affectedRows; NativeRdb::ValuesBucket nativeValuesBucket = ConvertFromValueBucket(valuesBucket); *errCode = rdbStore_->UpdateWithConflictResolution(affectedRows, predicates.GetPredicates()->GetTableName(), @@ -151,8 +193,25 @@ namespace Relational { return affectedRows; } + int32_t RdbStoreImpl::UpdateEx(ValuesBucketEx valuesBucket, RdbPredicatesImpl &predicates, + NativeRdb::ConflictResolution conflictResolution, int32_t *errCode) + { + if (errCode == nullptr || rdbStore_ == nullptr || predicates.GetPredicates() == nullptr) { + return -1; + } + int32_t affectedRows; + NativeRdb::ValuesBucket nativeValuesBucket = ConvertFromValueBucketEx(valuesBucket); + *errCode = rdbStore_->UpdateWithConflictResolution(affectedRows, predicates.GetPredicates()->GetTableName(), + nativeValuesBucket, predicates.GetPredicates()->GetWhereClause(), predicates.GetPredicates()->GetBindArgs(), + conflictResolution); + return affectedRows; + } + int RdbStoreImpl::Delete(RdbPredicatesImpl &predicates, int32_t *errCode) { + if (errCode == nullptr || rdbStore_ == nullptr || predicates.GetPredicates() == nullptr) { + return -1; + } int deletedRows = 0; *errCode = rdbStore_->Delete(deletedRows, *(predicates.GetPredicates())); return deletedRows; @@ -160,8 +219,14 @@ namespace Relational { int32_t RdbStoreImpl::SetDistributedTables(char** tables, int64_t tablesSize) { + if (tables == nullptr || rdbStore_ == nullptr) { + return -1; + } std::vector tablesVector; for (int64_t i = 0; i < tablesSize; i++) { + if (tables[i] == nullptr) { + return -1; + } tablesVector.push_back(std::string(tables[i])); } return rdbStore_->SetDistributedTables(tablesVector, DistributedRdb::DISTRIBUTED_DEVICE, @@ -170,8 +235,14 @@ namespace Relational { int32_t RdbStoreImpl::SetDistributedTables(char** tables, int64_t tablesSize, int32_t type) { + if (tables == nullptr || rdbStore_ == nullptr) { + return -1; + } std::vector tablesVector; for (int64_t i = 0; i < tablesSize; i++) { + if (tables[i] == nullptr) { + return -1; + } tablesVector.push_back(std::string(tables[i])); } return rdbStore_->SetDistributedTables(tablesVector, type, DistributedRdb::DistributedConfig{false}); @@ -180,8 +251,14 @@ namespace Relational { int32_t RdbStoreImpl::SetDistributedTables(char** tables, int64_t tablesSize, int32_t type, DistributedRdb::DistributedConfig &distributedConfig) { + if (tables == nullptr || rdbStore_ == nullptr) { + return -1; + } std::vector tablesVector; for (int64_t i = 0; i < tablesSize; i++) { + if (tables[i] == nullptr) { + return -1; + } tablesVector.push_back(std::string(tables[i])); } return rdbStore_->SetDistributedTables(tablesVector, type, distributedConfig); @@ -189,31 +266,49 @@ namespace Relational { int32_t RdbStoreImpl::RollBack() { + if (rdbStore_ == nullptr) { + return -1; + } return rdbStore_->RollBack(); } int32_t RdbStoreImpl::Commit() { + if (rdbStore_ == nullptr) { + return -1; + } return rdbStore_->Commit(); } int32_t RdbStoreImpl::BeginTransaction() { + if (rdbStore_ == nullptr) { + return -1; + } return rdbStore_->BeginTransaction(); } int32_t RdbStoreImpl::Backup(const char* destName) { + if (rdbStore_ == nullptr || destName == nullptr) { + return -1; + } return rdbStore_->Backup(destName, newKey); } int32_t RdbStoreImpl::Restore(const char* srcName) { + if (rdbStore_ == nullptr || srcName == nullptr) { + return -1; + } return rdbStore_->Restore(srcName, newKey); } char* RdbStoreImpl::ObtainDistributedTableName(const char* device, const char* table) { + if (rdbStore_ == nullptr || device == nullptr || table == nullptr) { + return nullptr; + } int errCode = RelationalStoreJsKit::E_INNER_ERROR; std::string tableName = rdbStore_->ObtainDistributedTableName(device, table, errCode); return MallocCString(tableName); @@ -221,11 +316,17 @@ namespace Relational { int32_t RdbStoreImpl::Emit(const char* event) { + if (rdbStore_ == nullptr || event == nullptr) { + return -1; + } return rdbStore_->Notify(event); } int64_t RdbStoreImpl::Insert(const char* table, ValuesBucket valuesBucket, int32_t conflict, int32_t *errCode) { + if (rdbStore_ == nullptr || table == nullptr || errCode == nullptr) { + return -1; + } std::string tableName = table; int64_t result; NativeRdb::ValuesBucket nativeValuesBucket = ConvertFromValueBucket(valuesBucket); @@ -234,14 +335,33 @@ namespace Relational { return result; } + int64_t RdbStoreImpl::InsertEx(const char* table, ValuesBucketEx valuesBucket, int32_t conflict, int32_t *errCode) + { + if (rdbStore_ == nullptr || table == nullptr || errCode == nullptr) { + return -1; + } + std::string tableName = table; + int64_t result; + NativeRdb::ValuesBucket nativeValuesBucket = ConvertFromValueBucketEx(valuesBucket); + *errCode = rdbStore_->InsertWithConflictResolution(result, tableName, + nativeValuesBucket, NativeRdb::ConflictResolution(conflict)); + return result; + } + void RdbStoreImpl::ExecuteSql(const char* sql, int32_t *errCode) { - *errCode = rdbStore_->ExecuteSql(sql, bindArgs); + if (rdbStore_ == nullptr || sql == nullptr || errCode == nullptr) { + return; + } + *errCode = rdbStore_->ExecuteSql(sql, std::vector()); } int32_t RdbStoreImpl::CleanDirtyData(const char* tableName, uint64_t cursor) { + if (rdbStore_ == nullptr || tableName == nullptr) { + return -1; + } int32_t rtnCode = rdbStore_->CleanDirtyData(tableName, cursor); return rtnCode; } @@ -249,6 +369,9 @@ namespace Relational { int32_t RdbStoreImpl::BatchInsert(int64_t &insertNum, const char* tableName, ValuesBucket* valuesBuckets, int64_t valuesSize) { + if (rdbStore_ == nullptr || tableName == nullptr || valuesBuckets == nullptr) { + return -1; + } std::vector valuesVector; std::string tableNameStr = tableName; if (tableNameStr.empty()) { @@ -262,14 +385,39 @@ namespace Relational { return rtnCode; } + int32_t RdbStoreImpl::BatchInsertEx(int64_t &insertNum, const char* tableName, ValuesBucketEx* valuesBuckets, + int64_t valuesSize) + { + if (rdbStore_ == nullptr || tableName == nullptr || valuesBuckets == nullptr) { + return -1; + } + std::vector valuesVector; + std::string tableNameStr = tableName; + if (tableNameStr.empty()) { + return RelationalStoreJsKit::E_PARAM_ERROR; + } + for (int64_t i = 0; i < valuesSize; i++) { + NativeRdb::ValuesBucket nativeValuesBucket = ConvertFromValueBucketEx(valuesBuckets[i]); + valuesVector.push_back(nativeValuesBucket); + } + int32_t rtnCode = rdbStore_->BatchInsert(insertNum, tableNameStr, valuesVector); + return rtnCode; + } + CArrSyncResult RdbStoreImpl::Sync(int32_t mode, RdbPredicatesImpl &predicates) { DistributedRdb::SyncOption option; option.mode = static_cast(mode); option.isBlock = true; DistributedRdb::SyncResult resMap; + if (rdbStore_ == nullptr) { + return CArrSyncResult{nullptr, nullptr, -1}; + } rdbStore_->Sync(option, *(predicates.GetPredicates()), [&resMap](const DistributedRdb::SyncResult &result) { resMap = result; }); + if (resMap.size() == 0) { + return CArrSyncResult{nullptr, nullptr, -1}; + } char** resultStr = static_cast(malloc(resMap.size() * sizeof(char*))); int32_t* resultNum = static_cast(malloc(resMap.size() * sizeof(int32_t))); if (resultStr == nullptr || resultNum == nullptr) { @@ -288,6 +436,9 @@ namespace Relational { std::shared_ptr RdbStoreImpl::QuerySql(const char *sql, ValueType *bindArgs, int64_t size) { + if (sql == nullptr || bindArgs == nullptr || rdbStore_ == nullptr) { + return nullptr; + } std::string tmpSql = sql; std::vector tmpBindArgs = std::vector(); for (int64_t i = 0; i < size; i++) { @@ -297,8 +448,25 @@ namespace Relational { return result; } + std::shared_ptr RdbStoreImpl::QuerySqlEx(const char *sql, ValueTypeEx *bindArgs, int64_t size) + { + if (sql == nullptr || bindArgs == nullptr || rdbStore_ == nullptr) { + return nullptr; + } + std::string tmpSql = sql; + std::vector tmpBindArgs = std::vector(); + for (int64_t i = 0; i < size; i++) { + tmpBindArgs.push_back(ValueTypeExToValueObject(bindArgs[i])); + } + auto result = rdbStore_->QueryByStep(tmpSql, tmpBindArgs); + return result; + } + void RdbStoreImpl::ExecuteSql(const char* sql, ValueType* bindArgs, int64_t bindArgsSize, int32_t *errCode) { + if (sql == nullptr || bindArgs == nullptr || rdbStore_ == nullptr || errCode == nullptr) { + return; + } std::vector bindArgsObjects = std::vector(); for (int64_t i = 0; i < bindArgsSize; i++) { bindArgsObjects.push_back(ValueTypeToValueObject(bindArgs[i])); @@ -306,7 +474,19 @@ namespace Relational { *errCode = rdbStore_->ExecuteSql(sql, bindArgsObjects); } - int32_t RdbStoreImpl::RegisterObserver(const char *event, bool interProcess, std::function *callback, + void RdbStoreImpl::ExecuteSqlEx(const char* sql, ValueTypeEx* bindArgs, int64_t bindArgsSize, int32_t *errCode) + { + if (sql == nullptr || bindArgs == nullptr || rdbStore_ == nullptr || errCode == nullptr) { + return; + } + std::vector bindArgsObjects = std::vector(); + for (int64_t i = 0; i < bindArgsSize; i++) { + bindArgsObjects.push_back(ValueTypeExToValueObject(bindArgs[i])); + } + *errCode = rdbStore_->ExecuteSql(sql, bindArgsObjects); + } + + int32_t RdbStoreImpl::RegisterObserver(const char *event, bool interProcess, int64_t callback, const std::function& callbackRef) { DistributedRdb::SubscribeOption option; @@ -319,16 +499,19 @@ namespace Relational { return RegisteredObserver(option, localSharedObservers_, callback, callbackRef); } - bool isSameFunction(const std::function *f1, const std::function *f2) + bool isSameFunction(int64_t f1, int64_t f2) { return f1 == f2; } bool RdbStoreImpl::HasRegisteredObserver( - std::function *callback, + int64_t callback, std::list> &observers) { for (auto &it : observers) { + if (it == nullptr) { + return false; + } if (isSameFunction(callback, it->GetCallBack())) { return true; } @@ -336,14 +519,14 @@ namespace Relational { return false; } - RdbStoreObserverImpl::RdbStoreObserverImpl(std::function *callback, + RdbStoreObserverImpl::RdbStoreObserverImpl(int64_t callback, const std::function& callbackRef) { m_callback = callback; m_callbackRef = callbackRef; } - std::function *RdbStoreObserverImpl::GetCallBack() + int64_t RdbStoreObserverImpl::GetCallBack() { return m_callback; } @@ -351,12 +534,15 @@ namespace Relational { int32_t RdbStoreImpl::RegisteredObserver( DistributedRdb::SubscribeOption option, std::map>> &observers, - std::function *callback, const std::function& callbackRef) + int64_t callback, const std::function& callbackRef) { observers.try_emplace(option.event); if (!HasRegisteredObserver(callback, observers[option.event])) { auto localObserver = std::make_shared(callback, callbackRef); - int32_t errCode = rdbStore_->Subscribe(option, localObserver.get()); + if (rdbStore_ == nullptr) { + return -1; + } + int32_t errCode = rdbStore_->Subscribe(option, localObserver); if (errCode != NativeRdb::E_OK) { return errCode; } @@ -376,10 +562,13 @@ namespace Relational { option.event = "dataChange"; auto observer = std::make_shared(callbackId, RdbStoreObserverImpl::ParamArrStr, mode); int32_t errCode = NativeRdb::E_OK; + if (rdbStore_ == nullptr) { + return -1; + } if (option.mode == DistributedRdb::SubscribeMode::LOCAL_DETAIL) { errCode = rdbStore_->SubscribeObserver(option, observer); } else { - errCode = rdbStore_->Subscribe(option, observer.get()); + errCode = rdbStore_->Subscribe(option, observer); } if (errCode == NativeRdb::E_OK) { observers_[mode].push_back(observer); @@ -396,10 +585,13 @@ namespace Relational { option.event = "dataChange"; auto observer = std::make_shared(callbackId, RdbStoreObserverImpl::ParamChangeInfo, mode); int32_t errCode = NativeRdb::E_OK; + if (rdbStore_ == nullptr) { + return -1; + } if (option.mode == DistributedRdb::SubscribeMode::LOCAL_DETAIL) { errCode = rdbStore_->SubscribeObserver(option, observer); } else { - errCode = rdbStore_->Subscribe(option, observer.get()); + errCode = rdbStore_->Subscribe(option, observer); } if (errCode == NativeRdb::E_OK) { observers_[mode].push_back(observer); @@ -411,6 +603,9 @@ namespace Relational { int32_t RdbStoreImpl::RegisterObserverProgressDetails(int64_t callbackId) { auto observer = std::make_shared(callbackId); + if (rdbStore_ == nullptr) { + return -1; + } int errCode = rdbStore_->RegisterAutoSyncCallback(observer); if (errCode == NativeRdb::E_OK) { syncObservers_.push_back(observer); @@ -419,7 +614,7 @@ namespace Relational { return errCode; } - int32_t RdbStoreImpl::UnRegisterObserver(const char *event, bool interProcess, std::function *callback) + int32_t RdbStoreImpl::UnRegisterObserver(const char *event, bool interProcess, int64_t callback) { DistributedRdb::SubscribeOption option; option.event = event; @@ -433,7 +628,7 @@ namespace Relational { int32_t RdbStoreImpl::UnRegisteredObserver(DistributedRdb::SubscribeOption option, std::map>> &observers, - std::function *callback) + int64_t callback) { auto obs = observers.find(option.event); if (obs == observers.end()) { @@ -444,7 +639,7 @@ namespace Relational { auto &list = obs->second; for (auto it = list.begin(); it != list.end(); it++) { if (isSameFunction(callback, (*it)->GetCallBack())) { - int errCode = rdbStore_->UnSubscribe(option, it->get()); + int errCode = rdbStore_->UnSubscribe(option, *it); if (errCode != RelationalStoreJsKit::OK) { return errCode; } @@ -462,6 +657,9 @@ namespace Relational { int32_t RdbStoreImpl::UnRegisterAllObserver(const char *event, bool interProcess) { DistributedRdb::SubscribeOption option; + if (event == nullptr) { + return -1; + } option.event = event; interProcess ? option.mode = DistributedRdb::SubscribeMode::LOCAL_SHARED : option.mode = DistributedRdb::SubscribeMode::LOCAL; @@ -505,10 +703,13 @@ namespace Relational { continue; } int errCode = NativeRdb::E_OK; + if (rdbStore_ == nullptr) { + return -1; + } if (option.mode == DistributedRdb::SubscribeMode::LOCAL_DETAIL) { errCode = rdbStore_->UnsubscribeObserver(option, *it); } else { - errCode = rdbStore_->UnSubscribe(option, it->get()); + errCode = rdbStore_->UnSubscribe(option, *it); } if (errCode != NativeRdb::E_OK) { return errCode; @@ -530,10 +731,13 @@ namespace Relational { continue; } int errCode = NativeRdb::E_OK; + if (rdbStore_ == nullptr) { + return -1; + } if (option.mode == DistributedRdb::SubscribeMode::LOCAL_DETAIL) { errCode = rdbStore_->UnsubscribeObserver(option, *it); } else { - errCode = rdbStore_->UnSubscribe(option, it->get()); + errCode = rdbStore_->UnSubscribe(option, *it); } if (errCode != NativeRdb::E_OK) { return errCode; @@ -555,6 +759,9 @@ namespace Relational { continue; } + if (rdbStore_ == nullptr) { + return -1; + } int32_t errCode = rdbStore_->UnregisterAutoSyncCallback(*it); if (errCode != NativeRdb::E_OK) { return errCode; @@ -571,6 +778,9 @@ namespace Relational { it = syncObservers_.erase(it); continue; } + if (rdbStore_ == nullptr) { + return -1; + } int32_t errCode = rdbStore_->UnregisterAutoSyncCallback(*it); if (errCode != NativeRdb::E_OK) { return errCode; @@ -589,6 +799,9 @@ namespace Relational { auto cFunc = reinterpret_cast(callbackId); auto async = [ lambda = CJLambda::Create(cFunc)](const DistributedRdb::Details &details) -> void { lambda(ToCProgressDetails(details)); }; + if (rdbStore_ == nullptr) { + return -1; + } int32_t errCode = rdbStore_->Sync(option, arr, async); return errCode; } @@ -596,12 +809,18 @@ namespace Relational { int32_t RdbStoreImpl::GetVersion(int32_t& errCode) { int32_t version = 0; + if (rdbStore_ == nullptr) { + return -1; + } errCode = rdbStore_->GetVersion(version); return version; } void RdbStoreImpl::SetVersion(int32_t value, int32_t &errCode) { + if (rdbStore_ == nullptr) { + return; + } errCode = rdbStore_->SetVersion(value); } @@ -611,6 +830,9 @@ namespace Relational { std::string tableName = cTables; std::string columnName = cColumnName; std::vector keys = CArrPRIKeyTypeToPRIKeyArray(cPrimaryKeys); + if (rdbStore_ == nullptr) { + return ModifyTime{0}; + } std::map map = rdbStore_->GetModifyTime(tableName, columnName, keys); if (map.empty()) { @@ -620,6 +842,16 @@ namespace Relational { return MapToModifyTime(map, errCode); } + int32_t RdbStoreImpl::GetRebuilt() + { + auto rebuilt = NativeRdb::RebuiltType::NONE; + if (rdbStore_ == nullptr) { + return -1; + } + rdbStore_->GetRebuilt(rebuilt); + return static_cast(rebuilt); + } + int32_t GetRealPath(AppDataMgrJsKit::JSUtils::RdbConfig &rdbConfig, const AppDataMgrJsKit::JSUtils::ContextParam ¶m, std::shared_ptr abilitycontext) @@ -688,6 +920,25 @@ namespace Relational { rdbConfig.customDir = config.customDir; } + void initRdbConfigEx(AppDataMgrJsKit::JSUtils::RdbConfig &rdbConfig, const StoreConfigEx &config) + { + rdbConfig.isEncrypt = config.encrypt; + rdbConfig.isSearchable = config.isSearchable; + rdbConfig.isAutoClean = config.autoCleanDirtyData; + rdbConfig.securityLevel = static_cast(config.securityLevel); + rdbConfig.dataGroupId = config.dataGroupId; + rdbConfig.name = config.name; + rdbConfig.customDir = config.customDir; + rdbConfig.rootDir = config.rootDir; + rdbConfig.vector = config.vector; + rdbConfig.allowRebuild = config.allowRebuild; + rdbConfig.isReadOnly = config.isReadOnly; + rdbConfig.pluginLibs = CArrStrToVector(config.pluginLibs); + rdbConfig.cryptoParam = ToCCryptoParam(config.cryptoParam); + rdbConfig.tokenizer = static_cast(config.tokenizer); + rdbConfig.persist = config.persist; + } + NativeRdb::RdbStoreConfig getRdbStoreConfig(const AppDataMgrJsKit::JSUtils::RdbConfig &rdbConfig, const AppDataMgrJsKit::JSUtils::ContextParam ¶m) { @@ -710,9 +961,44 @@ namespace Relational { return rdbStoreConfig; } + NativeRdb::RdbStoreConfig getRdbStoreConfigEx(const AppDataMgrJsKit::JSUtils::RdbConfig &rdbConfig, + const AppDataMgrJsKit::JSUtils::ContextParam ¶m) + { + NativeRdb::RdbStoreConfig rdbStoreConfig(rdbConfig.path); + rdbStoreConfig.SetEncryptStatus(rdbConfig.isEncrypt); + rdbStoreConfig.SetSearchable(rdbConfig.isSearchable); + rdbStoreConfig.SetIsVector(rdbConfig.vector); + rdbStoreConfig.SetDBType(rdbConfig.vector ? NativeRdb::DB_VECTOR : NativeRdb::DB_SQLITE); + rdbStoreConfig.SetStorageMode(rdbConfig.persist ? NativeRdb::StorageMode::MODE_DISK : + NativeRdb::StorageMode::MODE_MEMORY); + rdbStoreConfig.SetAutoClean(rdbConfig.isAutoClean); + rdbStoreConfig.SetSecurityLevel(rdbConfig.securityLevel); + rdbStoreConfig.SetDataGroupId(rdbConfig.dataGroupId); + rdbStoreConfig.SetName(rdbConfig.name); + rdbStoreConfig.SetCustomDir(rdbConfig.customDir); + rdbStoreConfig.SetAllowRebuild(rdbConfig.allowRebuild); + rdbStoreConfig.SetReadOnly(rdbConfig.isReadOnly); + rdbStoreConfig.SetIntegrityCheck(NativeRdb::IntegrityCheck::NONE); + rdbStoreConfig.SetTokenizer(rdbConfig.tokenizer); + + if (!param.bundleName.empty()) { + rdbStoreConfig.SetBundleName(param.bundleName); + } + rdbStoreConfig.SetModuleName(param.moduleName); + rdbStoreConfig.SetArea(param.area); + rdbStoreConfig.SetPluginLibs(rdbConfig.pluginLibs); + rdbStoreConfig.SetHaMode(rdbConfig.haMode); + + rdbStoreConfig.SetCryptoParam(rdbConfig.cryptoParam); + return rdbStoreConfig; + } + int64_t GetRdbStore(OHOS::AbilityRuntime::Context* context, StoreConfig config, int32_t *errCode) { + if (errCode == nullptr) { + return -1; + } if (context == nullptr) { *errCode = -1; return -1; @@ -742,9 +1028,51 @@ namespace Relational { return nativeRdbStore->GetID(); } + int64_t GetRdbStoreEx(OHOS::AbilityRuntime::Context* context, const StoreConfigEx *config, + int32_t *errCode) + { + if (errCode == nullptr) { + return -1; + } + if (context == nullptr) { + *errCode = ERROR_VALUE; + return ERROR_VALUE; + } + auto abilitycontext = std::make_shared(context->shared_from_this()); + AppDataMgrJsKit::JSUtils::ContextParam param; + initContextParam(param, abilitycontext); + AppDataMgrJsKit::JSUtils::RdbConfig rdbConfig; + initRdbConfigEx(rdbConfig, *config); + if (!rdbConfig.cryptoParam.IsValid()) { + *errCode = RelationalStoreJsKit::E_PARAM_ERROR; + return ERROR_VALUE; + } + + *errCode = GetRealPath(rdbConfig, param, abilitycontext); + if (*errCode != NativeRdb::E_OK) { + return ERROR_VALUE; + } + + DefaultOpenCallback callback; + auto rdbStore = + NativeRdb::RdbHelper::GetRdbStore(getRdbStoreConfigEx(rdbConfig, param), -1, callback, *errCode); + if (*errCode != 0) { + return ERROR_VALUE; + } + auto nativeRdbStore = FFIData::Create(rdbStore); + if (nativeRdbStore == nullptr) { + *errCode = ERROR_VALUE; + return ERROR_VALUE; + } + return nativeRdbStore->GetID(); + } + void DeleteRdbStore(OHOS::AbilityRuntime::Context* context, const char* name, int32_t *errCode) { + if (errCode == nullptr) { + return; + } if (context == nullptr) { *errCode = -1; return; @@ -759,15 +1087,16 @@ namespace Relational { if (*errCode != NativeRdb::E_OK) { return; } - // If the API version is greater than or equal to 20, close the connection. - bool isClose = (AppDataMgrJsKit::JSUtils::GetHapVersion() >= 20); - *errCode = NativeRdb::RdbHelper::DeleteRdbStore(rdbConfig.path, isClose); + *errCode = NativeRdb::RdbHelper::DeleteRdbStore(rdbConfig.path, false); return; } void DeleteRdbStoreConfig(OHOS::AbilityRuntime::Context* context, StoreConfig config, int32_t *errCode) { + if (errCode == nullptr) { + return; + } if (context == nullptr) { *errCode = -1; return; @@ -782,9 +1111,31 @@ namespace Relational { if (*errCode != NativeRdb::E_OK) { return; } - // If the API version is greater than or equal to 20, close the connection. - bool isClose = (AppDataMgrJsKit::JSUtils::GetHapVersion() >= 20); - *errCode = NativeRdb::RdbHelper::DeleteRdbStore(rdbConfig.path, isClose); + *errCode = NativeRdb::RdbHelper::DeleteRdbStore(rdbConfig.path, false); + return; + } + + void DeleteRdbStoreConfigEx(OHOS::AbilityRuntime::Context* context, const StoreConfigEx *config, + int32_t *errCode) + { + if (errCode == nullptr) { + return; + } + if (context == nullptr || config == nullptr) { + *errCode = ERROR_VALUE; + return; + } + auto abilitycontext = std::make_shared(context->shared_from_this()); + AppDataMgrJsKit::JSUtils::ContextParam param; + initContextParam(param, abilitycontext); + AppDataMgrJsKit::JSUtils::RdbConfig rdbConfig; + initRdbConfigEx(rdbConfig, *config); + + *errCode = GetRealPath(rdbConfig, param, abilitycontext); + if (*errCode != NativeRdb::E_OK) { + return; + } + *errCode = NativeRdb::RdbHelper::DeleteRdbStore(rdbConfig.path, false); return; } } diff --git a/relational_store/frameworks/cj/src/relational_store_impl_resultsetproxy.cpp b/relational_store/frameworks/cj/src/relational_store_impl_resultsetproxy.cpp index 368d7937..531d0159 100644 --- a/relational_store/frameworks/cj/src/relational_store_impl_resultsetproxy.cpp +++ b/relational_store/frameworks/cj/src/relational_store_impl_resultsetproxy.cpp @@ -39,6 +39,9 @@ namespace Relational { CArrStr ResultSetImpl::GetAllColumnNames() { std::vector colNames; + if (resultSetValue == nullptr) { + return CArrStr{nullptr, 0}; + } int errCode = resultSetValue->GetAllColumnNames(colNames); if (errCode != RelationalStoreJsKit::OK) { LOGE("GetAllColumnNames failed code: %{public}d", errCode); @@ -67,6 +70,9 @@ namespace Relational { int32_t ResultSetImpl::GetColumnCount() { int32_t count = 0; + if (resultSetValue == nullptr) { + return count; + } int errCode = resultSetValue->GetColumnCount(count); if (errCode != RelationalStoreJsKit::OK) { LOGE("GetColumnCount failed code:%{public}d", errCode); @@ -77,6 +83,9 @@ namespace Relational { int32_t ResultSetImpl::GetRowCount() { int32_t result; + if (resultSetValue == nullptr) { + return -1; + } int errCode = resultSetValue->GetRowCount(result); if (errCode != RelationalStoreJsKit::OK) { LOGE("GetRowCount failed code:%{public}d", errCode); @@ -87,6 +96,9 @@ namespace Relational { int32_t ResultSetImpl::GetRowIndex() { int32_t result; + if (resultSetValue == nullptr) { + return -1; + } int errCode = resultSetValue->GetRowIndex(result); if (errCode != RelationalStoreJsKit::OK) { LOGE("GetRowIndex failed code:%{public}d", errCode); @@ -97,6 +109,9 @@ namespace Relational { bool ResultSetImpl::IsAtFirstRow() { bool result = false; + if (resultSetValue == nullptr) { + return result; + } int errCode = resultSetValue->IsAtFirstRow(result); if (errCode != RelationalStoreJsKit::OK) { LOGE("IsAtFirstRow failed code:%{public}d", errCode); @@ -107,6 +122,9 @@ namespace Relational { bool ResultSetImpl::IsAtLastRow() { bool result = false; + if (resultSetValue == nullptr) { + return result; + } int errCode = resultSetValue->IsAtLastRow(result); if (errCode != RelationalStoreJsKit::OK) { LOGE("IsAtLastRow failed code:%{public}d", errCode); @@ -117,6 +135,9 @@ namespace Relational { bool ResultSetImpl::IsEnded() { bool result = false; + if (resultSetValue == nullptr) { + return result; + } int errCode = resultSetValue->IsEnded(result); if (errCode != RelationalStoreJsKit::OK) { LOGE("IsEnded failed code:%{public}d", errCode); @@ -128,6 +149,9 @@ namespace Relational { bool ResultSetImpl::IsStarted() { bool result = false; + if (resultSetValue == nullptr) { + return result; + } int errCode = resultSetValue->IsStarted(result); if (errCode != RelationalStoreJsKit::OK) { LOGE("IsBegin failed code:%{public}d", errCode); @@ -137,30 +161,45 @@ namespace Relational { bool ResultSetImpl::IsClosed() { + if (resultSetValue == nullptr) { + return false; + } return resultSetValue->IsClosed(); } double ResultSetImpl::GetDouble(int32_t columnIndex, int32_t* rtnCode) { double result = 0.0; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return result; + } *rtnCode = resultSetValue->GetDouble(columnIndex, result); return result; } bool ResultSetImpl::GoToRow(int32_t position, int32_t* rtnCode) { + if (resultSetValue == nullptr || rtnCode == nullptr) { + return false; + } *rtnCode = resultSetValue->GoToRow(position); return *rtnCode == RelationalStoreJsKit::OK; } bool ResultSetImpl::GoToPreviousRow(int32_t* rtnCode) { + if (resultSetValue == nullptr || rtnCode == nullptr) { + return false; + } *rtnCode = resultSetValue->GoToPreviousRow(); return *rtnCode == RelationalStoreJsKit::OK; } bool ResultSetImpl::GoToLastRow(int32_t* rtnCode) { + if (resultSetValue == nullptr || rtnCode == nullptr) { + return false; + } *rtnCode = resultSetValue->GoToLastRow(); return *rtnCode == RelationalStoreJsKit::OK; } @@ -168,6 +207,9 @@ namespace Relational { char* ResultSetImpl::GetColumnName(int32_t columnIndex, int32_t* rtnCode) { std::string result; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return nullptr; + } *rtnCode = resultSetValue->GetColumnName(columnIndex, result); if (*rtnCode != RelationalStoreJsKit::OK) { LOGE("IsAtLastRow failed code:%{public}d", *rtnCode); @@ -178,6 +220,9 @@ namespace Relational { bool ResultSetImpl::IsColumnNull(int32_t columnIndex, int32_t* rtnCode) { bool result; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return false; + } *rtnCode = resultSetValue->IsColumnNull(columnIndex, result); return result; } @@ -185,6 +230,9 @@ namespace Relational { Asset ResultSetImpl::GetAsset(int32_t columnIndex, int32_t* rtnCode) { NativeRdb::ValueObject::Asset asset; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return Asset{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, 0}; + } *rtnCode = resultSetValue->GetAsset(columnIndex, asset); if (*rtnCode != RelationalStoreJsKit::OK) { return Asset{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, 0}; @@ -203,12 +251,18 @@ namespace Relational { int32_t ResultSetImpl::Close() { + if (resultSetValue == nullptr) { + return -1; + } return resultSetValue->Close(); } int32_t ResultSetImpl::GetColumnIndex(char* columnName, int32_t* rtnCode) { int32_t result = -1; + if (resultSetValue == nullptr || rtnCode == nullptr || columnName == nullptr) { + return result; + } *rtnCode = resultSetValue->GetColumnIndex(columnName, result); // If the API version is less than 13, directly return. if (AppDataMgrJsKit::JSUtils::GetHapVersion() < 13 || (*rtnCode == NativeRdb::E_INVALID_ARGS)) { @@ -220,18 +274,27 @@ namespace Relational { char* ResultSetImpl::GetString(int32_t columnIndex, int32_t* rtnCode) { std::string result; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return nullptr; + } *rtnCode = resultSetValue->GetString(columnIndex, result); return MallocCString(result); } bool ResultSetImpl::GoToFirstRow(int32_t* rtnCode) { + if (resultSetValue == nullptr || rtnCode == nullptr) { + return false; + } *rtnCode = resultSetValue->GoToFirstRow(); return *rtnCode == RelationalStoreJsKit::OK; } int64_t ResultSetImpl::GetLong(int32_t columnIndex, int32_t* rtnCode) { + if (resultSetValue == nullptr || rtnCode == nullptr) { + return -1; + } int64_t result; *rtnCode = resultSetValue->GetLong(columnIndex, result); return result; @@ -239,6 +302,9 @@ namespace Relational { bool ResultSetImpl::GoToNextRow(int32_t* rtnCode) { + if (resultSetValue == nullptr || rtnCode == nullptr) { + return false; + } *rtnCode = resultSetValue->GoToNextRow(); return *rtnCode == RelationalStoreJsKit::OK; } @@ -246,6 +312,9 @@ namespace Relational { CArrUI8 ResultSetImpl::GetBlob(int32_t columnIndex, int32_t* rtnCode) { std::vector vec; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return CArrUI8{nullptr, 0}; + } *rtnCode = resultSetValue->GetBlob(columnIndex, vec); if (*rtnCode != RelationalStoreJsKit::OK || vec.size() == 0) { return CArrUI8{nullptr, 0}; @@ -262,6 +331,9 @@ namespace Relational { bool ResultSetImpl::GoTo(int32_t offset, int32_t* rtnCode) { + if (resultSetValue == nullptr || rtnCode == nullptr) { + return false; + } *rtnCode = resultSetValue->GoTo(offset); return *rtnCode == RelationalStoreJsKit::OK; } @@ -269,6 +341,9 @@ namespace Relational { Assets ResultSetImpl::GetAssets(int32_t columnIndex, int32_t* rtnCode) { std::vector assets; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return Assets{nullptr, 0}; + } *rtnCode = resultSetValue->GetAssets(columnIndex, assets); if (*rtnCode != RelationalStoreJsKit::OK || assets.size() == 0) { return Assets{nullptr, 0}; @@ -294,6 +369,9 @@ namespace Relational { ValuesBucket ResultSetImpl::GetRow(int32_t* rtnCode) { NativeRdb::RowEntity rowEntity; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return ValuesBucket{nullptr, nullptr, 0}; + } *rtnCode = resultSetValue->GetRow(rowEntity); if (*rtnCode != E_OK) { return ValuesBucket{nullptr, nullptr, 0}; @@ -321,5 +399,55 @@ namespace Relational { } return result; } + + ValuesBucketEx ResultSetImpl::GetRowEx(int32_t* rtnCode) + { + NativeRdb::RowEntity rowEntity; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return ValuesBucketEx{nullptr, nullptr, 0}; + } + *rtnCode = resultSetValue->GetRow(rowEntity); + if (*rtnCode != E_OK) { + return ValuesBucketEx{nullptr, nullptr, 0}; + } + const std::map map = rowEntity.Get(); + size_t size = map.size(); + if (size == 0) { + return ValuesBucketEx{nullptr, nullptr, 0}; + } + ValuesBucketEx result = ValuesBucketEx { + .key = static_cast(malloc(sizeof(char*) * size)), + .value = static_cast(malloc(sizeof(ValueTypeEx) * size)), + .size = size + }; + if (result.key == nullptr || result.value == nullptr) { + free(result.key); + free(result.value); + return ValuesBucketEx{nullptr, nullptr, ERROR_VALUE}; + } + int64_t i = 0; + for (auto &t : map) { + result.key[i] = MallocCString(t.first); + result.value[i] = ValueObjectToValueTypeEx(t.second); + i++; + } + return result; + } + + ValueTypeEx ResultSetImpl::GetValue(int32_t columnIndex, int32_t* rtnCode) + { + NativeRdb::ValueObject object; + if (resultSetValue == nullptr || rtnCode == nullptr) { + return ValueTypeEx{ 0 }; + } + *rtnCode = NativeRdb::E_ALREADY_CLOSED; + if (resultSetValue != nullptr) { + *rtnCode = resultSetValue->Get(columnIndex, object); + } + if (*rtnCode != E_OK) { + return ValueTypeEx{ 0 }; + } + return ValueObjectToValueTypeEx(object); + } } } \ No newline at end of file diff --git a/relational_store/frameworks/cj/src/relational_store_utils.cpp b/relational_store/frameworks/cj/src/relational_store_utils.cpp index bf7df7f7..35bb53e7 100644 --- a/relational_store/frameworks/cj/src/relational_store_utils.cpp +++ b/relational_store/frameworks/cj/src/relational_store_utils.cpp @@ -17,8 +17,23 @@ #include "native_log.h" #include "rdb_store.h" +const int64_t UI64TOUI8 = 8; +const int64_t BITNUMOFUI64 = 64; + namespace OHOS { namespace Relational { + OHOS::NativeRdb::RdbStoreConfig::CryptoParam ToCCryptoParam(CryptoParam param) + { + auto cryptoParam = OHOS::NativeRdb::RdbStoreConfig::CryptoParam(); + cryptoParam.iterNum = param.iterNum; + cryptoParam.encryptAlgo = param.encryptAlgo; + cryptoParam.hmacAlgo = param.hmacAlgo; + cryptoParam.kdfAlgo = param.kdfAlgo; + cryptoParam.cryptoPageSize = param.cryptoPageSize; + cryptoParam.encryptKey_ = CArrUI8ToVector(param.encryptKey); + return cryptoParam; + } + char* MallocCString(const std::string& origin) { if (origin.empty()) { @@ -35,6 +50,9 @@ namespace Relational { NativeRdb::ValueObject ValueTypeToValueObjectBlob(const ValueType& value) { std::vector blob = std::vector(); + if (value.Uint8Array.head == nullptr) { + return NativeRdb::ValueObject(blob); + } for (int64_t j = 0; j < value.Uint8Array.size; j++) { blob.push_back(value.Uint8Array.head[j]); } @@ -61,6 +79,9 @@ namespace Relational { NativeRdb::ValueObject ValueTypeToValueObjectAssets(const ValueType& value) { std::vector assets = std::vector(); + if (value.assets.head == nullptr) { + return assets; + } for (int64_t j = 0; j < value.assets.size; j++) { Asset asset = value.assets.head[j]; std::string modifyTime = asset.modifyTime; @@ -97,6 +118,10 @@ namespace Relational { break; } case TYPE_STR: { + if (value.string == nullptr) { + LOGE("string value is nullptr"); + break; + } valueObject = NativeRdb::ValueObject(value.string); break; } @@ -123,6 +148,152 @@ namespace Relational { return valueObject; } + NativeRdb::ValueObject ValueTypeExToValueObjectBlob(const ValueTypeEx& value) + { + std::vector blob = std::vector(); + if (value.uint8Array.head == nullptr) { + LOGE("the array head is nullptr"); + return NativeRdb::ValueObject(blob); + } + for (int64_t j = 0; j < value.uint8Array.size; j++) { + blob.push_back(value.uint8Array.head[j]); + } + return NativeRdb::ValueObject(blob); + } + + NativeRdb::ValueObject ValueTypeExToValueObjectAsset(const ValueTypeEx& value) + { + std::string modifyTime = value.asset.modifyTime; + std::string size = value.asset.size; + NativeRdb::ValueObject::Asset asset = { + .status = value.asset.status, + .name = value.asset.name, + .uri = value.asset.uri, + .createTime = value.asset.createTime, + .modifyTime = modifyTime, + .size = size, + .hash = modifyTime + "_" + size, + .path = value.asset.path + }; + return NativeRdb::ValueObject(asset); + } + + NativeRdb::ValueObject ValueTypeExToValueObjectAssets(const ValueTypeEx& value) + { + std::vector assets = std::vector(); + if (value.assets.head == nullptr) { + LOGE("the assets head is nullptr"); + return NativeRdb::ValueObject(assets); + } + for (int64_t j = 0; j < value.assets.size; j++) { + Asset asset = value.assets.head[j]; + std::string modifyTime = asset.modifyTime; + std::string size = asset.size; + NativeRdb::ValueObject::Asset nativeAsset = { + .status = asset.status, + .name = asset.name, + .uri = asset.uri, + .createTime = asset.createTime, + .modifyTime = modifyTime, + .size = size, + .hash = modifyTime + "_" + size, + .path = asset.path + }; + assets.push_back(nativeAsset); + } + return NativeRdb::ValueObject(assets); + } + + NativeRdb::ValueObject ValueTypeExToValueObjectFloatArr(const ValueTypeEx& value) + { + std::vector arr = std::vector(); + if (value.floatArray.head == nullptr) { + LOGE("the floatArray head is nullptr"); + return NativeRdb::ValueObject(arr); + } + for (int64_t j = 0; j < value.floatArray.size; j++) { + arr.push_back(value.floatArray.head[j]); + } + return NativeRdb::ValueObject(arr); + } + + NativeRdb::ValueObject ValueTypeExToValueObjectBigInt(const ValueTypeEx& value) + { + std::vector arr = std::vector(); + int64_t firstSize = (value.bigInt.value.size % UI64TOUI8 == 0) ? UI64TOUI8 : + (value.bigInt.value.size % UI64TOUI8); + for (int64_t i = 0; i < ((value.bigInt.value.size + UI64TOUI8 - 1) / UI64TOUI8); i++) { + uint64_t tempValue = 0; + if (i == 0) { + for (int64_t j = 0; j < firstSize; j++) { + tempValue |= + (static_cast(value.bigInt.value.head[j]) << (UI64TOUI8 * (firstSize -j - 1))); + } + } else { + for (int64_t j = 0; j < UI64TOUI8; j++) { + tempValue |= + (static_cast(value.bigInt.value.head[UI64TOUI8 * (i - 1) + firstSize + j]) << + (UI64TOUI8 * ((value.bigInt.value.size - (UI64TOUI8 * (i - 1) + firstSize + j) - 1) % + UI64TOUI8))); + } + } + arr.push_back(tempValue); + } + return NativeRdb::ValueObject(NativeRdb::ValueObject::BigInt(static_cast(value.bigInt.sign), + std::move(arr))); + } + + NativeRdb::ValueObject ValueTypeExToValueObject(const ValueTypeEx& value) + { + NativeRdb::ValueObject valueObject; + switch (value.tag) { + case TYPE_NULL: { + valueObject = NativeRdb::ValueObject(); + break; + } + case TYPE_INT: { + valueObject = NativeRdb::ValueObject(value.integer); + break; + } + case TYPE_DOU: { + valueObject = NativeRdb::ValueObject(value.dou); + break; + } + case TYPE_STR: { + valueObject = NativeRdb::ValueObject(value.string); + break; + } + case TYPE_BOOL: { + valueObject = NativeRdb::ValueObject(value.boolean); + break; + } + case TYPE_BLOB: { + valueObject = ValueTypeExToValueObjectBlob(value); + break; + } + case TYPE_ASSET: { + valueObject = ValueTypeExToValueObjectAsset(value); + break; + } + case TYPE_ASSETS: { + valueObject = ValueTypeExToValueObjectAssets(value); + break; + } + case TYPE_FLOATARR: { + valueObject = ValueTypeExToValueObjectFloatArr(value); + break; + } + case TYPE_BIGINT: { + valueObject = ValueTypeExToValueObjectBigInt(value); + break; + } + default: + valueObject = NativeRdb::ValueObject(); + break; + } + return valueObject; + } + ValueType ValueObjectToValueTypeAsset(const NativeRdb::ValueObject& object) { NativeRdb::ValueObject::Asset val; @@ -143,6 +314,9 @@ namespace Relational { { NativeRdb::ValueObject::Assets val; object.GetAssets(val); + if (val.size() == 0) { + return ValueType {.assets = Assets{nullptr, -1}, .tag = TYPE_ASSETS}; + } Assets assets = Assets {.head = static_cast(malloc(val.size() * sizeof(Asset))), .size = val.size()}; if (assets.head == nullptr) { return ValueType {.assets = Assets{nullptr, -1}, .tag = TYPE_ASSETS}; @@ -189,6 +363,9 @@ namespace Relational { case NativeRdb::ValueObject::TYPE_BLOB: { std::vector val; object.GetBlob(val); + if (val.size() == 0) { + return ValueType {.Uint8Array = CArrUI8 {nullptr, -1}, .tag = TYPE_BLOB}; + } CArrUI8 arr = CArrUI8 {.head = static_cast(malloc(val.size() * sizeof(uint8_t))), .size = val.size()}; if (arr.head == nullptr) { @@ -209,6 +386,141 @@ namespace Relational { } } + ValueTypeEx ValueObjectToValueTypeExBlob(const NativeRdb::ValueObject& object) + { + std::vector val = static_cast>(object); + auto size = val.size(); + if (size == 0) { + return ValueTypeEx {.uint8Array = CArrUI8 {nullptr, ERROR_VALUE}, .tag = TYPE_BLOB}; + } + CArrUI8 arr = CArrUI8 {.head = static_cast(malloc(size * sizeof(uint8_t))), + .size = size}; + if (arr.head == nullptr) { + return ValueTypeEx {.uint8Array = CArrUI8 {nullptr, ERROR_VALUE}, .tag = TYPE_BLOB}; + } + for (size_t i = 0; i < size; i++) { + arr.head[i] = val[i]; + } + return ValueTypeEx {.uint8Array = arr, .tag = TYPE_BLOB}; + } + + ValueTypeEx ValueObjectToValueTypeExAsset(const NativeRdb::ValueObject& object) + { + NativeRdb::ValueObject::Asset val = static_cast(object); + Asset asset = Asset { + .name = MallocCString(val.name), + .uri = MallocCString(val.uri), + .path = MallocCString(val.path), + .createTime = MallocCString(val.createTime), + .modifyTime = MallocCString(val.modifyTime), + .size = MallocCString(val.size), + .status = val.status + }; + return ValueTypeEx {.asset = asset, .tag = TYPE_ASSET}; + } + + ValueTypeEx ValueObjectToValueTypeExAssets(const NativeRdb::ValueObject& object) + { + NativeRdb::ValueObject::Assets val = static_cast(object); + if (val.size() == 0) { + return ValueTypeEx {.assets = Assets{nullptr, ERROR_VALUE}, .tag = TYPE_ASSETS}; + } + Assets assets = Assets {.head = static_cast(malloc(val.size() * sizeof(Asset))), .size = val.size()}; + if (assets.head == nullptr) { + return ValueTypeEx {.assets = Assets{nullptr, ERROR_VALUE}, .tag = TYPE_ASSETS}; + } + for (std::size_t i = 0; i < val.size(); i++) { + assets.head[i] = Asset { + .name = MallocCString(val[i].name), + .uri = MallocCString(val[i].uri), + .path = MallocCString(val[i].path), + .createTime = MallocCString(val[i].createTime), + .modifyTime = MallocCString(val[i].modifyTime), + .size = MallocCString(val[i].size), + .status = static_cast(val[i].status) + }; + } + return ValueTypeEx {.assets = assets, .tag = TYPE_ASSETS}; + } + + ValueTypeEx ValueObjectToValueTypeExFloatArray(const NativeRdb::ValueObject& object) + { + std::vector val = static_cast>(object); + auto size = val.size(); + if (size == 0) { + return ValueTypeEx {.floatArray = CArrFloat {nullptr, ERROR_VALUE}, .tag = TYPE_FLOATARR}; + } + CArrFloat arr = CArrFloat {.head = static_cast(malloc(size * sizeof(float))), + .size = size}; + if (arr.head == nullptr) { + return ValueTypeEx {.floatArray = CArrFloat {nullptr, ERROR_VALUE}, .tag = TYPE_FLOATARR}; + } + for (size_t i = 0; i < size; i++) { + arr.head[i] = val[i]; + } + return ValueTypeEx {.floatArray = arr, .tag = TYPE_FLOATARR}; + } + + ValueTypeEx ValueObjectToValueTypeExBigInt(const NativeRdb::ValueObject& object) + { + NativeRdb::ValueObject::BigInt bigInt = static_cast(object); + int32_t sign = bigInt.Sign(); + std::vector value = bigInt.Value(); + size_t size = value.size(); + if (size == 0) { + return ValueTypeEx {.bigInt = BigInt {CArrUI8 {nullptr, ERROR_VALUE}, ERROR_VALUE}, .tag = TYPE_BIGINT}; + } + uint8_t *head = static_cast(calloc(UI64TOUI8 * size, sizeof(uint8_t))); + if (head == nullptr) { + return ValueTypeEx {.bigInt = BigInt {CArrUI8 {nullptr, ERROR_VALUE}, ERROR_VALUE}, .tag = TYPE_BIGINT}; + } + for (size_t i = 0; i < size; i++) { + for (size_t j = 0; j < UI64TOUI8; j++) { + head[UI64TOUI8 * i + j] |= (value[i] >> (BITNUMOFUI64 - (UI64TOUI8 * (j + 1)))); + } + } + return ValueTypeEx {.bigInt = BigInt {CArrUI8 {head, UI64TOUI8 * size}, sign}, .tag = TYPE_BIGINT}; + } + + ValueTypeEx ValueObjectToValueTypeEx(const NativeRdb::ValueObject& object) + { + switch (object.GetType()) { + case NativeRdb::ValueObject::TYPE_NULL: + return ValueTypeEx {.tag = TYPE_NULL}; + case NativeRdb::ValueObject::TYPE_INT: { + return ValueTypeEx {.integer = static_cast(object), .tag = TYPE_INT}; + } + case NativeRdb::ValueObject::TYPE_DOUBLE: { + return ValueTypeEx {.dou = static_cast(object), .tag = TYPE_DOU}; + } + case NativeRdb::ValueObject::TYPE_STRING: { + return ValueTypeEx {.string = MallocCString(static_cast(object)), .tag = TYPE_STR}; + } + case NativeRdb::ValueObject::TYPE_BOOL: { + return ValueTypeEx {.boolean = static_cast(object), .tag = TYPE_BOOL}; + } + case NativeRdb::ValueObject::TYPE_BLOB: { + return ValueObjectToValueTypeExBlob(object); + } + case NativeRdb::ValueObject::TYPE_ASSET: { + return ValueObjectToValueTypeExAsset(object); + } + case NativeRdb::ValueObject::TYPE_ASSETS: { + return ValueObjectToValueTypeExAssets(object); + } + case NativeRdb::ValueObject::TYPE_VECS: { + return ValueObjectToValueTypeExFloatArray(object); + } + case NativeRdb::ValueObject::TYPE_BIGINT: { + return ValueObjectToValueTypeExBigInt(object); + } + case NativeRdb::ValueObject::TYPE_BUTT: + return ValueTypeEx {.tag = 128}; + default: + return ValueTypeEx {.tag = TYPE_NULL}; + } + } + CArrStr VectorToCArrStr(const std::vector &devices) { CArrStr cArrStr{0}; @@ -239,6 +551,15 @@ namespace Relational { return arr; } + std::vector CArrUI8ToVector(CArrUI8 carr) + { + std::vector arr; + for (int i = 0; i < carr.size; i++) { + arr.push_back(carr.head[i]); + } + return arr; + } + std::variant RetPRIKeyTypeToVariant(RetPRIKeyType &value) { switch (value.tag) { @@ -282,6 +603,9 @@ namespace Relational { { ModifyTime modifyTime{0}; modifyTime.size = static_cast(map.size()); + if (modifyTime.size == 0) { + return ModifyTime{0}; + } modifyTime.key = static_cast(malloc(sizeof(RetPRIKeyType) * modifyTime.size)); modifyTime.value = static_cast(malloc(sizeof(uint64_t) * modifyTime.size)); if (modifyTime.key == nullptr || modifyTime.value == nullptr) { diff --git a/relational_store/frameworks/common/include/delay_actuator.h b/relational_store/frameworks/common/include/delay_actuator.h new file mode 100644 index 00000000..efb8a4e3 --- /dev/null +++ b/relational_store/frameworks/common/include/delay_actuator.h @@ -0,0 +1,200 @@ +/* +* 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 COMMON_RDB_INCLUDE_DELAY_ACTUATOR_H +#define COMMON_RDB_INCLUDE_DELAY_ACTUATOR_H +#include +#include +#include "executor_pool.h" +namespace OHOS { +class ActuatorBase : public std::enable_shared_from_this { +public: + static constexpr uint32_t DEFAULT_FIRST_DELAY_INTERVAL = 0; + static constexpr uint32_t DEFAULT_MIN_EXECUTE_INTERVAL = 200; + static constexpr uint32_t DEFAULT_MAX_EXECUTE_INTERVAL = 500; + static const uint32_t INVALID_INTERVAL = UINT32_MAX; + void SetExecutorPool(std::shared_ptr pool) + { + pool_ = std::move(pool); + } + void Suspend() + { + isSuspend_ = true; + } + void Active() + { + isSuspend_ = false; + } + + class Defer final { + public: + Defer(std::vector> actuators) : actuators_(std::move(actuators)) + { + for (auto actuator : actuators_) { + if (actuator) { + actuator->Suspend(); + actuator->StopTimer(false); + } + } + } + Defer(std::shared_ptr actuator) : Defer(std::vector>({actuator})) + {} + ~Defer() + { + for (auto actuator : actuators_) { + if (actuator) { + actuator->Active(); + actuator->StartTimer(); + } + } + } + Defer(const Defer &defer) = delete; + Defer(Defer &&defer) = delete; + Defer &operator=(const Defer &defer) = delete; + Defer &operator=(Defer &&defer) = delete; + void *operator new(size_t size) = delete; + void *operator new[](size_t size) = delete; + void operator delete(void *) = delete; + void operator delete[](void *) = delete; + + private: + std::vector> actuators_; + }; +protected: + ActuatorBase(uint32_t firstInterval = DEFAULT_FIRST_DELAY_INTERVAL, + uint32_t minInterval = DEFAULT_MIN_EXECUTE_INTERVAL, uint32_t maxInterval = DEFAULT_MAX_EXECUTE_INTERVAL) + : firstDelayInterval_(firstInterval), minExecuteInterval_(minInterval), maxExecuteInterval_(maxInterval) + { + } + virtual ~ActuatorBase() + { + StopTimer(true); + } + + void StartTimer() + { + std::lock_guard lock(mutex_); + if (pool_ == nullptr || isSuspend_) { + return; + } + auto weakThis = weak_from_this(); + if (forceTaskId_ == Executor::INVALID_TASK_ID && maxExecuteInterval_ != INVALID_INTERVAL) { + forceTaskId_ = pool_->Schedule(std::chrono::milliseconds(maxExecuteInterval_), [weakThis]() { + auto self = weakThis.lock(); + if (self != nullptr) { + self->ExecuteTask(); + self->lastExecuteTimePoint_ = GetTimeStamp(); + } + }); + } + if (firstDelayInterval_ == INVALID_INTERVAL || minExecuteInterval_ == INVALID_INTERVAL) { + return; + } + if (delayTaskId_ == Executor::INVALID_TASK_ID) { + delayTaskId_ = + pool_->Schedule(std::chrono::milliseconds(lastExecuteTimePoint_ <= GetTimeStamp() - minExecuteInterval_ + ? firstDelayInterval_ + : minExecuteInterval_), + [weakThis]() { + auto self = weakThis.lock(); + if (self != nullptr) { + self->ExecuteTask(); + self->lastExecuteTimePoint_ = GetTimeStamp(); + } + }); + } else { + delayTaskId_ = pool_->Reset(delayTaskId_, std::chrono::milliseconds(minExecuteInterval_)); + } + } + void StopTimer(bool wait) + { + std::lock_guard lock(mutex_); + if (pool_ != nullptr) { + pool_->Remove(forceTaskId_, wait); + pool_->Remove(delayTaskId_, wait); + } + forceTaskId_ = Executor::INVALID_TASK_ID; + delayTaskId_ = Executor::INVALID_TASK_ID; + } + + virtual void ExecuteTask() {}; + static inline uint64_t GetTimeStamp() + { + return std::chrono::duration_cast( + std::chrono::steady_clock::now().time_since_epoch()) + .count(); + } +private: + ExecutorPool::TaskId delayTaskId_ = ExecutorPool::INVALID_TASK_ID; + ExecutorPool::TaskId forceTaskId_ = ExecutorPool::INVALID_TASK_ID; + std::shared_ptr pool_ = nullptr; + bool isSuspend_ = false; + std::atomic_uint64_t lastExecuteTimePoint_ = 0; + uint32_t const firstDelayInterval_ = DEFAULT_FIRST_DELAY_INTERVAL; + uint32_t const minExecuteInterval_ = DEFAULT_MIN_EXECUTE_INTERVAL; + uint32_t const maxExecuteInterval_ = DEFAULT_MAX_EXECUTE_INTERVAL; + mutable std::mutex mutex_; +}; + +template, class Task = std::function> +class DelayActuator : public ActuatorBase { +public: + DelayActuator(MergeFunc mergeFunc = nullptr, uint32_t firstInterval = DEFAULT_FIRST_DELAY_INTERVAL, + uint32_t minInterval = DEFAULT_MIN_EXECUTE_INTERVAL, uint32_t maxInterval = DEFAULT_MAX_EXECUTE_INTERVAL) + : ActuatorBase(firstInterval, minInterval, maxInterval), data_(T()), mergeFunc_(mergeFunc) + { + } + ~DelayActuator() {} + + void SetTask(Task task) + { + task_ = std::move(task); + } + template + void Execute(D &&value) + { + { + std::lock_guard lock(mutex_); + if (mergeFunc_) { + mergeFunc_(data_, std::forward(value)); + } else { + data_ = T{std::move(value)}; + } + } + StartTimer(); + } + +private: + Task task_; + T data_; + MergeFunc mergeFunc_; + std::mutex mutex_; + + void ExecuteTask() override + { + StopTimer(false); + T data; + { + std::lock_guard lock(mutex_); + data = std::move(data_); + data_ = T(); + } + if (task_) { + task_(std::move(data)); + } + } +}; +} // namespace OHOS +#endif // COMMON_RDB_INCLUDE_DELAY_ACTUATOR_H \ No newline at end of file diff --git a/relational_store/frameworks/common/include/logger.h b/relational_store/frameworks/common/include/logger.h index 848ebc57..821f0e6e 100644 --- a/relational_store/frameworks/common/include/logger.h +++ b/relational_store/frameworks/common/include/logger.h @@ -39,20 +39,6 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() return { LOG_CORE, 0xD001650, "SRdb" }; } } // namespace Rdb - -namespace GraphStoreJsKit { -static inline OHOS::HiviewDFX::HiLogLabel LogLabel() -{ - return { LOG_CORE, 0xD001660, "GdbJS" }; -} -} // namespace GraphStoreJsKit - -namespace DistributedDataAip { -static inline OHOS::HiviewDFX::HiLogLabel LogLabel() -{ - return { LOG_CORE, 0xD001660, "GdbNative" }; -} -} // namespace DistributedDataAip } // namespace OHOS #define LOG_DEBUG(fmt, ...) \ diff --git a/relational_store/interfaces/inner_api/gdb/BUILD.gn b/relational_store/frameworks/js/ani/relationalstore/BUILD.gn similarity index 30% rename from relational_store/interfaces/inner_api/gdb/BUILD.gn rename to relational_store/frameworks/js/ani/relationalstore/BUILD.gn index c593c4a0..f3e7cd53 100644 --- a/relational_store/interfaces/inner_api/gdb/BUILD.gn +++ b/relational_store/frameworks/js/ani/relationalstore/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2024 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 @@ -10,73 +10,74 @@ # 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/config/components/ets_frontend/ets2abc_config.gni") import("//build/ohos.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") -config("native_gdb_public_config") { - visibility = [ ":*" ] - include_dirs = [ - "${relational_store_innerapi_path}/gdb/include", - "${relational_store_innerapi_path}/rdb/include", +ohos_shared_library("relationalstore_ani") { + sources = [ + "src/ani_rdb_entry.cpp", + "src/ani_rdb_error.cpp", + "src/ani_rdb_predicates.cpp", + "src/ani_rdb_store.cpp", + "src/ani_rdb_store_helper.cpp", + "src/ani_result_set.cpp", + "src/ani_utils.cpp", ] -} - -ohos_shared_library("native_graphstore") { - public_configs = [ ":native_gdb_public_config" ] - sanitize = { - boundary_sanitize = true - ubsan = true - cfi = true - cfi_cross_dso = true - debug = false - } - cflags_cc = [ "-fvisibility=hidden" ] include_dirs = [ + "./include", "${relational_store_common_path}/include", - "${relational_store_native_path}/gdb/adapter/include", - "${relational_store_native_path}/gdb/include", - "${relational_store_native_path}/rdb/include", ] - sources = [ - "${relational_store_native_path}/gdb/adapter/src/grd_adapter.cpp", - "${relational_store_native_path}/gdb/adapter/src/grd_adapter_manager.cpp", - "${relational_store_native_path}/gdb/src/connection.cpp", - "${relational_store_native_path}/gdb/src/connection_pool.cpp", - "${relational_store_native_path}/gdb/src/db_helper.cpp", - "${relational_store_native_path}/gdb/src/db_store_impl.cpp", - "${relational_store_native_path}/gdb/src/db_store_manager.cpp", - "${relational_store_native_path}/gdb/src/edge.cpp", - "${relational_store_native_path}/gdb/src/full_result.cpp", - "${relational_store_native_path}/gdb/src/gdb_utils.cpp", - "${relational_store_native_path}/gdb/src/graph_connection.cpp", - "${relational_store_native_path}/gdb/src/graph_statement.cpp", - "${relational_store_native_path}/gdb/src/path.cpp", - "${relational_store_native_path}/gdb/src/path_segment.cpp", - "${relational_store_native_path}/gdb/src/store_config.cpp", - "${relational_store_native_path}/gdb/src/trans_db.cpp", - "${relational_store_native_path}/gdb/src/transaction.cpp", - "${relational_store_native_path}/gdb/src/transaction_impl.cpp", - "${relational_store_native_path}/gdb/src/vertex.cpp", - "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", - "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", - "${relational_store_native_path}/rdb/src/rdb_time_utils.cpp", - "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", - "${relational_store_native_path}/rdb/src/string_utils.cpp", + + deps = [ + "${relational_store_innerapi_path}/rdb:native_rdb", + "${relational_store_innerapi_path}/rdb_data_share_adapter:rdb_data_share_adapter", ] - deps = [] + external_deps = [ + "ability_runtime:abilitykit_native", + "ability_runtime:appkit_native", + "ability_runtime:wantagent_innerkits", "c_utils:utils", - "file_api:securitylabel", + "data_share:datashare_common_lite", "hilog:libhilog", - "hisysevent:libhisysevent", - "hitrace:hitrace_meter", - "huks:libhukssdk", - "json:nlohmann_json_static", + "runtime_core:ani", + "samgr:samgr_proxy", ] - if (arkdata_db_core_is_exists) { - defines = [ "ARKDATA_DB_CORE_IS_EXISTS" ] + + sanitize = { + boundary_sanitize = true + ubsan = true + cfi = true + cfi_cross_dso = true + debug = false } + + subsystem_name = "distributeddatamgr" + part_name = "relational_store" + output_extension = "so" +} + +generate_static_abc("relationalstore_abc") { + base_url = "./ets" + files = [ "./ets/@ohos.data.relationalStore.ets" ] + dst_file = "$target_out_dir/relationalstore.abc" + out_puts = [ "$target_out_dir/relationalstore.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/relationalstore.abc" +} + +ohos_prebuilt_etc("relationalstore_abc_etc") { + source = "$target_out_dir/relationalstore.abc" + module_install_dir = "framework" subsystem_name = "distributeddatamgr" part_name = "relational_store" + deps = [ ":relationalstore_abc" ] +} + +group("relationalstore_ani_package") { + deps = [ + ":relationalstore_abc_etc", + ":relationalstore_ani", + ] } diff --git a/relational_store/frameworks/js/ani/relationalstore/ets/@ohos.data.relationalStore.ets b/relational_store/frameworks/js/ani/relationalstore/ets/@ohos.data.relationalStore.ets new file mode 100644 index 00000000..a8228a4a --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/ets/@ohos.data.relationalStore.ets @@ -0,0 +1,393 @@ +/* + * 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 { AsyncCallback, Callback } from '@ohos.base' +import Context from 'application.BaseContext' +import dataSharePredicates from '@ohos.data.dataSharePredicates'; +import { BusinessError } from '@ohos.base'; + +export default namespace relationalStore { + + loadLibrary("relationalstore_ani") + + export enum AssetStatus { + ASSET_NORMAL, + ASSET_INSERT, + ASSET_UPDATE, + ASSET_DELETE, + ASSET_ABNORMAL, + ASSET_DOWNLOADING + } + + export interface Asset { + name: string; + uri: string; + path: string; + createTime: string; + modifyTime: string; + size: string; + status?: AssetStatus; + } + + type Assets = Asset[]; + + type ValueType = null | number | string | boolean | Uint8Array | Asset | Assets | Float32Array | bigint; + + export type ValuesBucket = Record; + + class Cleaner { + static callback(cleaner: Cleaner): void { + cleaner.clean() + } + + constructor(targetPtr: long) { + this.targetPtr = targetPtr + } + + native clean(): void + private targetPtr: long = 0 + } + + class FinalizationAgent { + constructor(obj: T, ptr: long) { + this.register(obj, ptr); + } + + register(obj: T, ptr: long): void { + this.unregisterToken = {}; + this.cleaner = new Cleaner(ptr); + finalizer.register(obj, this.cleaner!, this.unregisterToken); + } + + unregister(): void { + finalizer.unregister(this.unregisterToken); + } + + private cleaner: Cleaner | null = null; + private unregisterToken: object; + } + + let finalizer = new FinalizationRegistry(Cleaner.callback) + + export class RdbPredicates { + private nativePtr: long = 0 + private fzAgent: FinalizationAgent + + constructor(name: string) { + this.initNativePredicates(name) + this.initFinalizer() + } + + private initFinalizer() :void { + this.fzAgent = new FinalizationAgent(this, this.nativePtr) + } + private native initNativePredicates(name: string): void; + } + + export interface ResultSet { + getColumnIndex(columnName: string): number; + getString(columnIndex: number): string; + getLong(columnIndex: number): number; + goToFirstRow(): boolean; + } + + class ResultSetInner implements ResultSet { + private nativePtr: long = 0; + private fzAgent: FinalizationAgent + + private initFinalizer() :void { + this.fzAgent = new FinalizationAgent(this, this.nativePtr) + } + + native getColumnIndex(columnName: string): number; + native getString(columnIndex: number): string; + native getLong(columnIndex: number): number; + native goToFirstRow(): boolean; + } + + export enum SecurityLevel { + S1 = 1, + S2 = 2, + S3 = 3, + S4 = 4 + } + + export interface StoreConfig { + name: string; + securityLevel: SecurityLevel; + encrypt?: boolean; + dataGroupId?: string; + customDir?: string; + autoCleanDirtyData?: boolean; + isSearchable?: boolean; + allowRebuild?: boolean; + vector?: boolean; + isReadOnly?: boolean; + pluginLibs?: Array; + haMode?: HAMode; + cryptoParam?: CryptoParam; + } + + export enum HAMode { + SINGLE = 0, + MAIN_REPLICA + } + + export interface CryptoParam { + encryptionKey: Uint8Array; + iterationCount?: number; + encryptionAlgo?: EncryptionAlgo; + hmacAlgo?: HmacAlgo; + kdfAlgo?: KdfAlgo; + cryptoPageSize?: number; + } + + export enum EncryptionAlgo { + AES_256_GCM = 0, + AES_256_CBC + } + + export enum HmacAlgo { + SHA1 = 0, + SHA256, + SHA512 + } + + export enum KdfAlgo { + KDF_SHA1 = 0, + KDF_SHA256, + KDF_SHA512 + } + + export interface RdbStore { + batchInsert(table: string, values: Array, callback: AsyncCallback): void; + batchInsert(table: string, values: Array): Promise; + batchInsertSync(table: string, values: Array): number; + + deleteSync(predicates: RdbPredicates): number; + delete(predicates: RdbPredicates): Promise; + delete(predicates: RdbPredicates, callback: AsyncCallback): void; + delete(table: string, predicates: dataSharePredicates.DataSharePredicates): Promise; + delete(table: string, predicates: dataSharePredicates.DataSharePredicates, callback: AsyncCallback): void; + + executeSql(sql: string, callback: AsyncCallback): void; + executeSql(sql: string, bindArgs: Array, callback: AsyncCallback): void; + executeSql(sql: string, bindArgs?: Array): Promise; + + beginTransaction(): void; + commit(): void; + rollBack(): void; + + querySqlSync(sql: string, bindArgs?: Array): ResultSet; + } + + class RdbStoreInner implements RdbStore { + private nativePtr: long = 0; + private fzAgent: FinalizationAgent + + private initFinalizer() :void { + this.fzAgent = new FinalizationAgent(this, this.nativePtr) + } + + batchInsert(table: string, values: Array, callback: AsyncCallback): void { + let cb = (): Object => { + let num = this.batchInsertSync(table, values) + return num as Object + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + let error = new BusinessError + error.code = 0 + callback(error, v as number) + }); + p1.catch((err: NullishType): void => { + callback(err as BusinessError, 0 as number) + }); + } + + batchInsert(table: string, values: Array): Promise { + let p = new Promise((resolve: (value: number) => void, reject: (error: Object) => void): void => { + let cb = (): Object => { + let num = this.batchInsertSync(table, values) + return num as Object + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + resolve(v as number); + }); + p1.catch((err: NullishType): void => { + reject(err as Error); + }); + }); + return p + } + native batchInsertSync(table: string, values: Array): number; + + native deleteSync(predicates: RdbPredicates): number; + + delete(predicates: RdbPredicates): Promise { + let p = new Promise((resolve: (data: number) => void, reject: (error: Object) => void): void => { + let cb = (): Object => { + let num = this.deleteSync(predicates) + return num as Object + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + resolve(v as number); + }); + p1.catch((err: NullishType): void => { + reject(err as Error); + }); + }); + return p + } + + delete(predicates: RdbPredicates, callback: AsyncCallback): void { + let cb = (): Object => { + let num = this.deleteSync(predicates) + return num as Object + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + let error = new BusinessError + error.code = 0 + callback(error, v as number) + }); + p1.catch((err: NullishType): void => { + callback(err as BusinessError, 0 as number) + }); + } + + private native deleteShareSync(table: string, predicates: dataSharePredicates.DataSharePredicates): number; + + delete(table: string, predicates: dataSharePredicates.DataSharePredicates): Promise { + let p = new Promise((resolve: (data: number) => void, reject: (error: Object) => void): void => { + let cb = (): Object => { + let num = this.deleteShareSync(table, predicates) + return num as Object + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + resolve(v as number); + }); + p1.catch((err: NullishType): void => { + reject(err as Error); + }); + }); + return p + } + + delete(table: string, predicates: dataSharePredicates.DataSharePredicates, callback: AsyncCallback): void { + let cb = (): Object => { + let num = this.deleteShareSync(table, predicates) + return num as Object + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + let error = new BusinessError + error.code = 0 + callback(error, v as number) + }); + p1.catch((err: NullishType): void => { + callback(err as BusinessError, 0 as number) + }); + } + + executeSql(sql: string, callback: AsyncCallback): void { + let cb = (): undefined => { + this.executeSqlSync(sql) + return undefined + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + let error = new BusinessError + error.code = 0 + callback(error, undefined) + }); + p1.catch((err: NullishType): void => { + callback(err as BusinessError, undefined) + }); + } + + executeSql(sql: string, bindArgs: Array, callback: AsyncCallback): void { + let cb = (): undefined => { + this.executeSqlSync(sql, bindArgs) + return undefined + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + let error = new BusinessError + error.code = 0 + callback(error, undefined) + }); + p1.catch((err: NullishType): void => { + callback(err as BusinessError, undefined) + }); + } + + executeSql(sql: string, bindArgs?: Array): Promise { + let p = new Promise((resolve: (v: NullishType) => void, reject: (error: Object) => void): void => { + let cb = (): undefined => { + this.executeSqlSync(sql, bindArgs) + return undefined + } + let p1 = taskpool.execute(cb); + p1.then((v: NullishType): void => { + resolve(v); + }); + p1.catch((err: NullishType): void => { + reject(err as Error); + }); + }); + return p + } + + private native executeSqlSync(sql: string, args?: Array): void; + + native beginTransaction(): void; + native commit(): void; + native rollBack(): void; + + native querySqlSync(sql: string, bindArgs?: Array): ResultSet; + } + + export native function getRdbStoreSync(context: Context, config: StoreConfig): RdbStore + + export function getRdbStore(context: Context, config: StoreConfig, callback: AsyncCallback): void { + let p1 = taskpool.execute(getRdbStoreSync, context, config); + p1.then((rdb: NullishType): void => { + let error = new BusinessError + error.code = 0 + callback(error, rdb as RdbStore) + }); + p1.catch((err: NullishType): void => { + let rdb = new RdbStoreInner() + callback(err as BusinessError, rdb) + }); + } + export function getRdbStore(context: Context, config: StoreConfig): Promise { + let p = new Promise((resolve: (value: RdbStore) => void, reject: (error: Object) => void): void => { + let p1 = taskpool.execute(getRdbStoreSync, context, config); + p1.then((rdb: NullishType): void => { + resolve(rdb as RdbStore); + }); + p1.catch((err: NullishType): void => { + reject(err as Object); + }); + }); + return p + } +} + diff --git a/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_error.h b/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_error.h new file mode 100644 index 00000000..f5bc981b --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_error.h @@ -0,0 +1,51 @@ +/* + * 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 ANI_RDB_ERROR_H +#define ANI_RDB_ERROR_H + +#include +#include +#include +#include +#include "logger.h" +#include "rdb_errno.h" + +namespace OHOS { +namespace RelationalStoreAniKit { +constexpr int MAX_INPUT_COUNT = 10; +constexpr int OK = 0; +constexpr int ERR = -1; + +constexpr int E_NON_SYSTEM_APP_ERROR = 202; +constexpr int E_PARAM_ERROR = 401; +constexpr int E_INNER_ERROR = 14800000; +constexpr int E_NOT_STAGE_MODE = 14801001; +constexpr int E_DATA_GROUP_ID_INVALID = 14801002; + +struct JsErrorCode { + int32_t status; + int32_t jsCode; + const char *message; +}; +const std::optional GetJsErrorCode(int32_t errorCode); +ani_object GetAniBusinessError(ani_env *env, int32_t errorCode); +void ThrowBusinessError(ani_env *env, int32_t status); +void ThrowBusinessError(ani_env *env, int32_t status, std::string message); + +} // namespace RelationalStoreAniKit +} // namespace OHOS + +#endif // ANI_RDB_ERROR_H + diff --git a/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_predicates.h b/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_predicates.h new file mode 100644 index 00000000..80cf4a68 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_predicates.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 ANI_RDB_PREDICATES_H +#define ANI_RDB_PREDICATES_H + +#include "abs_rdb_predicates.h" +#include "ani_utils.h" +#include "rdb_predicates.h" + +namespace OHOS { +namespace RelationalStoreAniKit { + +class PredicatesProxy : public NativeObject { +public: + std::shared_ptr predicates; +}; + +ani_status PredicatesInit(ani_env *env); + +} // namespace RelationalStoreAniKit +} // namespace OHOS + +#endif // ANI_RDB_PREDICATES_H + diff --git a/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_store.h b/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_store.h new file mode 100644 index 00000000..dd684a74 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_store.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 ANI_RDB_STORE_H +#define ANI_RDB_STORE_H + +#include +#include "ani_utils.h" +#include "rdb_store.h" + +namespace OHOS { +namespace RelationalStoreAniKit { + +using namespace OHOS::NativeRdb; + +class RdbStoreProxy : public NativeObject { +public: + std::shared_ptr nativeRdb; +}; +ani_status RdbStoreInit(ani_env *env); + +} // namespace RelationalStoreAniKit +} // namespace OHOS +#endif // ANI_RDB_STORE_H + diff --git a/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_store_helper.h b/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_store_helper.h new file mode 100644 index 00000000..a4384c59 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/include/ani_rdb_store_helper.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 ANI_RDB_STORE_HELPER_H +#define ANI_RDB_STORE_HELPER_H + +#include +#include + +namespace OHOS { +namespace RelationalStoreAniKit { + +using namespace OHOS::NativeRdb; + +ani_status RdbStoreHelperInit(ani_env *env); + +} // namespace RelationalStoreAniKit +} // namespace OHOS +#endif // ANI_RDB_STORE_HELPER_H + diff --git a/relational_store/frameworks/js/ani/relationalstore/include/ani_result_set.h b/relational_store/frameworks/js/ani/relationalstore/include/ani_result_set.h new file mode 100644 index 00000000..6c786f7a --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/include/ani_result_set.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 ANI_RESULT_SET_H +#define ANI_RESULT_SET_H + +#include "ani_utils.h" +#include "rdb_helper.h" + +namespace OHOS { +namespace RelationalStoreAniKit { + +class ResultSetProxy : public NativeObject { +public: + std::shared_ptr resultset; +}; + +ani_status ResultSetInit(ani_env *env); + +} // namespace RelationalStoreAniKit +} // namespace OHOS + +#endif //ANI_RESULT_SET_H + diff --git a/relational_store/frameworks/js/ani/relationalstore/include/ani_utils.h b/relational_store/frameworks/js/ani/relationalstore/include/ani_utils.h new file mode 100644 index 00000000..0b29da95 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/include/ani_utils.h @@ -0,0 +1,297 @@ +/* + * 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 ANI_UTILS_H +#define ANI_UTILS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class AniObjectUtils { +public: + static ani_object Create(ani_env *env, const char *nsName, const char *clsName, ...) + { + ani_object nullobj{}; + + if (env == nullptr) { + return nullobj; + } + + ani_namespace ns; + if (ANI_OK != env->FindNamespace(nsName, &ns)) { + return nullobj; + } + + ani_class cls; + if (ANI_OK != env->Namespace_FindClass(ns, clsName, &cls)) { + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + return nullobj; + } + return obj; + } + + static ani_object Create(ani_env *env, const char *clsName, ...) + { + ani_object nullobj{}; + + if (env == nullptr) { + return nullobj; + } + + ani_class cls; + if (ANI_OK != env->FindClass(clsName, &cls)) { + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + return nullobj; + } + return obj; + } + + static ani_object Create(ani_env *env, ani_class cls, ...) + { + ani_object nullobj{}; + + if (env == nullptr) { + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "", nullptr, &ctor)) { + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, cls); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + return nullobj; + } + return obj; + } + + static ani_status CallObjMethod(ani_env *env, const char *ns, const char *cls, const char *method, ani_object obj) + { + if (env == nullptr) { + return ANI_ERROR; + } + + ani_namespace nameSpace; + auto status = env->FindNamespace(ns, &nameSpace); + if (status != ANI_OK) { + return status; + } + + ani_class clazz; + status = env->Namespace_FindClass(nameSpace, cls, &clazz); + if (status != ANI_OK) { + return status; + } + + ani_method objMethod; + status = env->Class_FindMethod(clazz, method, ":V", &objMethod); + if (status != ANI_OK) { + return status; + } + status = env->Object_CallMethod_Void(obj, objMethod); + return status; + } + + template + static ani_status Wrap(ani_env *env, ani_object object, T *nativePtr, const char *propName = "nativePtr") + { + return env->Object_SetFieldByName_Long(object, propName, reinterpret_cast(nativePtr)); + } + + template + static T* Unwrap(ani_env *env, ani_object object, const char *propName = "nativePtr") + { + ani_long nativePtr; + if (ANI_OK != env->Object_GetFieldByName_Long(object, propName, &nativePtr)) { + return nullptr; + } + return reinterpret_cast(nativePtr); + } +}; + +class AniStringUtils { +public: + static std::string ToStd(ani_env *env, ani_string ani_str) + { + if (env == nullptr) { + return std::string(); + } + + ani_size strSize = 0; + auto status = env->String_GetUTF8Size(ani_str, &strSize); + if (ANI_OK != status) { + return std::string(); + } + + std::vector buffer(strSize + 1); // +1 for null terminator + char *utf8Buffer = buffer.data(); + + // String_GetUTF8 Supportted by https://gitee.com/openharmony/arkcompiler_runtime_core/pulls/3416 + ani_size bytesWritten = 0; + status = env->String_GetUTF8(ani_str, utf8Buffer, strSize + 1, &bytesWritten); + if (ANI_OK != status) { + return std::string(); + } + + utf8Buffer[bytesWritten] = '\0'; + std::string content = std::string(utf8Buffer); + return content; + } + + static ani_string ToAni(ani_env *env, const std::string& str) + { + if (env == nullptr) { + return nullptr; + } + ani_string aniStr = nullptr; + if (ANI_OK != env->String_NewUTF8(str.data(), str.size(), &aniStr)) { + return nullptr; + } + return aniStr; + } +}; + +class UnionAccessor { +public: + UnionAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) + { + if (env == nullptr) { + throw std::runtime_error("env is nullptr"); + } + } + + bool IsInstanceOf(const std::string& cls_name) + { + ani_class cls; + env_->FindClass(cls_name.c_str(), &cls); + + ani_boolean ret; + env_->Object_InstanceOf(obj_, cls, &ret); + return ret; + } + + template + bool IsInstanceOfType(); + + template + bool TryConvert(T &value); + + template + bool TryConvertVariant(std::variant &value) + { + return GetNativeValue(value); + } + + template + bool GetNativeValue(T &value) + { + return false; + } + + template + bool GetNativeValue(T &value) + { + First cValue; + auto ret = TryConvert(cValue); + if (ret == true) { + value = cValue; + return ret; + } + return GetNativeValue(value); + } + + template + bool TryConvertArray(std::vector &value); + + bool GetObjectRefPropertyByName(std::string clsName, const char *name, ani_ref &val); + bool GetObjectStringPropertyByName(std::string clsName, const char *name, std::string &val); + bool GetObjectEnumValuePropertyByName(std::string clsName, const char *name, ani_int &val, bool optional = false); + ani_ref AniIteratorNext(ani_ref interator, bool &isSuccess); + +private: + ani_env *env_; + ani_object obj_; +}; + +class OptionalAccessor { +public: + OptionalAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) + { + if (env == nullptr) { + throw std::runtime_error("env is nullptr"); + } + } + + bool IsUndefined() + { + ani_boolean isUndefined; + env_->Reference_IsUndefined(obj_, &isUndefined); + return isUndefined; + } + + template + std::optional Convert(); + +private: + ani_env *env_; + ani_object obj_; +}; + +class NativeObject { +public: + virtual ~NativeObject() = default; +}; + +ani_status CleanerInit(ani_env *env); +#endif diff --git a/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_entry.cpp b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_entry.cpp new file mode 100644 index 00000000..ac264374 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_entry.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. + */ + +#define LOG_TAG "AniResultSet" +#include +#include +#include "ani_rdb_predicates.h" +#include "ani_rdb_store_helper.h" +#include "ani_result_set.h" +#include "ani_utils.h" +#include "logger.h" + +using namespace OHOS::Rdb; +using namespace OHOS::RelationalStoreAniKit; + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + if (vm == nullptr) { + LOG_ERROR("vm is nullptr."); + return ANI_ERROR; + } + + ani_env *env; + auto status = vm->GetEnv(ANI_VERSION_1, &env); + if (ANI_OK != status) { + LOG_ERROR("Unsupported ANI_VERSION_1 errcode %{public}d", status); + return ANI_ERROR; + } + + status = ResultSetInit(env); + if (ANI_OK != status) { + LOG_ERROR("ResultSetInit failed errcode %{public}d", status); + return ANI_ERROR; + } + + status = RdbStoreHelperInit(env); + if (ANI_OK != status) { + LOG_ERROR("RdbStoreHelperInit failed errcode %{public}d", status); + return ANI_ERROR; + } + + status = RdbStoreInit(env); + if (ANI_OK != status) { + LOG_ERROR("RdbStoreInit failed errcode %{public}d", status); + return ANI_ERROR; + } + + status = PredicatesInit(env); + if (ANI_OK != status) { + LOG_ERROR("PredicatesInit failed errcode %{public}d", status); + return ANI_ERROR; + } + + status = CleanerInit(env); + if (ANI_OK != status) { + LOG_ERROR("CleanerInit failed errcode %{public}d", status); + return ANI_ERROR; + } + + *result = ANI_VERSION_1; + return ANI_OK; +} + diff --git a/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_error.cpp b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_error.cpp new file mode 100644 index 00000000..a9bee4a2 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_error.cpp @@ -0,0 +1,178 @@ +/* + * 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. + */ + +#define LOG_TAG "AniRdbError" +#include "ani_rdb_error.h" +#include "logger.h" + +#include +#include +#include + +namespace OHOS { +namespace RelationalStoreAniKit { +using JsErrorCode = OHOS::RelationalStoreAniKit::JsErrorCode; +using namespace OHOS::Rdb; +static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = { + { E_NOT_STAGE_MODE, 14801001, "Only supported in stage mode." }, + { E_DATA_GROUP_ID_INVALID, 14801002, "The data group id is invalid." }, + { NativeRdb::E_NOT_SELECT, 14800019, "The SQL must be a query statement." }, + { NativeRdb::E_COLUMN_OUT_RANGE, 14800013, "Column out of bounds." }, + { NativeRdb::E_INVALID_FILE_PATH, 14800010, "Invalid database path." }, + { NativeRdb::E_ROW_OUT_RANGE, 14800012, "Row out of bounds." }, + { NativeRdb::E_NO_ROW_IN_QUERY, 14800018, "No data meets the condition." }, + { NativeRdb::E_ALREADY_CLOSED, 14800014, "Already closed." }, + { NativeRdb::E_DATABASE_BUSY, 14800015, "The database does not respond." }, + { NativeRdb::E_WAL_SIZE_OVER_LIMIT, 14800047, "The WAL file size over default limit." }, + { NativeRdb::E_GET_DATAOBSMGRCLIENT_FAIL, 14801050, "Failed to get DataObsMgrClient." }, + { NativeRdb::E_TYPE_MISMATCH, 14800051, "The type of the distributed table does not match." }, + { NativeRdb::E_SQLITE_FULL, 14800029, "SQLite: The database is full." }, + { NativeRdb::E_NOT_SUPPORT_THE_SQL, 14800021, "SQLite: Generic error."}, + { NativeRdb::E_ATTACHED_DATABASE_EXIST, 14800016, "The database is already attached." }, + { NativeRdb::E_SQLITE_ERROR, 14800021, "SQLite: Generic error." }, + { NativeRdb::E_SQLITE_CORRUPT, 14800011, "Database corrupted." }, + { NativeRdb::E_SQLITE_ABORT, 14800022, "SQLite: Callback routine requested an abort." }, + { NativeRdb::E_SQLITE_PERM, 14800023, "SQLite: Access permission denied." }, + { NativeRdb::E_SQLITE_BUSY, 14800024, "SQLite: The database file is locked." }, + { NativeRdb::E_SQLITE_LOCKED, 14800025, "SQLite: A table in the database is locked." }, + { NativeRdb::E_SQLITE_NOMEM, 14800026, "SQLite: The database is out of memory." }, + { NativeRdb::E_SQLITE_READONLY, 14800027, "SQLite: Attempt to write a readonly database." }, + { NativeRdb::E_SQLITE_IOERR, 14800028, "SQLite: Some kind of disk I/O error occurred." }, + { NativeRdb::E_SQLITE_CANTOPEN, 14800030, "SQLite: Unable to open the database file." }, + { NativeRdb::E_SQLITE_TOOBIG, 14800031, "SQLite: TEXT or BLOB exceeds size limit." }, + { NativeRdb::E_SQLITE_CONSTRAINT, 14800032, "SQLite: Abort due to constraint violation." }, + { NativeRdb::E_SQLITE_MISMATCH, 14800033, "SQLite: Data type mismatch." }, + { NativeRdb::E_SQLITE_MISUSE, 14800034, "SQLite: Library used incorrectly." }, + { NativeRdb::E_CONFIG_INVALID_CHANGE, 14800017, "Config changed." }, + { NativeRdb::E_NOT_SUPPORT, 801, "Capability not support." }, +}; + +const std::optional GetJsErrorCode(int32_t errorCode) +{ + auto jsErrorCode = JsErrorCode{ errorCode, -1, "" }; + auto iter = std::lower_bound(JS_ERROR_CODE_MSGS, + JS_ERROR_CODE_MSGS + sizeof(JS_ERROR_CODE_MSGS) / sizeof(JS_ERROR_CODE_MSGS[0]), jsErrorCode, + [](const JsErrorCode &jsErrorCode1, const JsErrorCode &jsErrorCode2) { + return jsErrorCode1.status < jsErrorCode2.status; + }); + if (iter < JS_ERROR_CODE_MSGS + sizeof(JS_ERROR_CODE_MSGS) / sizeof(JS_ERROR_CODE_MSGS[0]) && + iter->status == errorCode) { + return *iter; + } + return std::nullopt; +} + +ani_object CreateBusinessErrorObj(ani_env *env, int32_t code, const std::string &msg) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return nullptr; + } + ani_string message; + auto status = env->String_NewUTF8(msg.c_str(), msg.size(), &message); + if (ANI_OK != status) { + LOG_ERROR("String_NewUTF8 failed, errcode %{public}d.", status); + return nullptr; + } + static const char *businessErrorName = "L@ohos/base/BusinessError;"; + ani_class cls; + status = env->FindClass(businessErrorName, &cls); + if (ANI_OK != status) { + LOG_ERROR("Not found class '%{public}s' errcode %{public}d.", businessErrorName, status); + return nullptr; + } + ani_method ctor; + status = env->Class_FindMethod(cls, "", ":V", &ctor); + if (ANI_OK != status) { + LOG_ERROR("Not found ctor of '%{public}s' errcode %{public}d.", businessErrorName, status); + return nullptr; + } + ani_object businessErrorObject; + status = env->Object_New(cls, ctor, &businessErrorObject); + if (ANI_OK != status) { + LOG_ERROR("Can not create business error errcode %{public}d.", status); + return nullptr; + } + status = env->Object_SetFieldByName_Double(businessErrorObject, "code", code); + if (ANI_OK != status) { + LOG_ERROR("Can not set business error code errcode %{public}d.", status); + return nullptr; + } + status = env->Object_SetPropertyByName_Ref(businessErrorObject, "message", message); + if (ANI_OK != status) { + LOG_ERROR("Can not set business error message errcode %{public}d.", status); + return businessErrorObject; + } + + return businessErrorObject; +} + +ani_object GetAniBusinessError(ani_env *env, int32_t errorCode) +{ + auto errInfo = GetJsErrorCode(errorCode); + auto code_ = E_INNER_ERROR; + auto msg_ = "Inner error. Inner code is " + std::to_string(errorCode % E_INNER_ERROR); + if (errInfo.has_value()) { + auto aniError = errInfo.value(); + code_ = aniError.jsCode; + msg_ = aniError.message; + } + + return CreateBusinessErrorObj(env, code_, msg_); +} + +void ThrowBusinessError(ani_env *env, int32_t status) +{ + if (NativeRdb::E_OK == status) { + return; + } + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return; + } + ani_object businessError = GetAniBusinessError(env, status); + if (nullptr == businessError) { + LOG_ERROR("Can not get business error."); + } else { + auto status = env->ThrowError(static_cast(businessError)); + if (status != ANI_OK) { + LOG_ERROR("ThrowError err %{public}d.", status); + } + } +} + +void ThrowBusinessError(ani_env *env, int32_t status, std::string message) +{ + if (OK == status) { + return; + } + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return; + } + ani_object businessError = CreateBusinessErrorObj(env, status, message); + if (nullptr == businessError) { + LOG_ERROR("Can not get business error."); + } else { + auto status = env->ThrowError(static_cast(businessError)); + if (status != ANI_OK) { + LOG_ERROR("ThrowError err %{public}d.", status); + } + } +} + +} // namespace RelationalStoreAniKit +} // namespace OHOS + diff --git a/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_predicates.cpp b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_predicates.cpp new file mode 100644 index 00000000..71bea7e8 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_predicates.cpp @@ -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. + */ + +#define LOG_TAG "AniRdbPredicates" +#include +#include +#include + +#include "logger.h" +#include "rdb_errno.h" +#include "ani_utils.h" +#include "ani_rdb_predicates.h" +#include "ani_rdb_error.h" + +namespace OHOS { +namespace RelationalStoreAniKit { + +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; + +void InitNativePredicates(ani_env *env, ani_object object, ani_string tableName) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return; + } + auto proxy = new PredicatesProxy(); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr."); + return; + } + auto tname = AniStringUtils::ToStd(env, tableName); + proxy->predicates = std::make_shared(tname); + + ani_status status = env->Object_SetFieldByName_Long(object, "nativePtr", reinterpret_cast(proxy)); + if (ANI_OK != status) { + delete proxy; + LOG_ERROR("[ANI] Failed to set nativePtr to predicates object."); + } +} +ani_status PredicatesInit(ani_env *env) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return ANI_ERROR; + } + + static const char *namespaceName = "L@ohos/data/relationalStore/relationalStore;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(namespaceName, &ns)) { + LOG_ERROR("Not found '%{public}s'", namespaceName); + return ANI_ERROR; + } + + ani_class cls; + const char *className = "LRdbPredicates;"; + if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) { + LOG_ERROR("Not found '%{public}s'", className); + return ANI_ERROR; + } + + std::array methods = { + ani_native_function {"initNativePredicates", nullptr, reinterpret_cast(InitNativePredicates)}, + }; + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + LOG_ERROR("Cannot bind native methods to '%{public}s'", className); + return ANI_ERROR; + } + return ANI_OK; +} + +} // namespace RelationalStoreAniKit +} // namespace OHOS + diff --git a/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_store.cpp b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_store.cpp new file mode 100644 index 00000000..946050ca --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_store.cpp @@ -0,0 +1,322 @@ +/* + * 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. + */ + +#define LOG_TAG "AniRdbStore" +#include +#include +#include + +#include "logger.h" +#include "rdb_errno.h" +#include "ani_utils.h" +#include "ani_result_set.h" +#include "ani_rdb_error.h" +#include "ani_rdb_store_helper.h" +#include "ani_rdb_predicates.h" +#include "rdb_utils.h" + +namespace OHOS { +namespace RelationalStoreAniKit { + +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; + +bool ConvertBindArgs(ani_env *env, ani_object args, std::vector &bindArgs, bool isOptional) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return false; + } + if (isOptional) { + ani_boolean isUndefined = true; + env->Reference_IsUndefined(args, &isUndefined); + if (isUndefined) { + bindArgs.clear(); + return true; + } + } + std::vector valRefs; + UnionAccessor array2Ref(env, args); + bool convertArrayOk = array2Ref.TryConvert(valRefs); + if (!convertArrayOk) { + LOG_ERROR("conver array fail"); + return false; + } + for (const auto& ref : valRefs) { + ani_object valObject = static_cast(ref); + ValueObject valueObject; + UnionAccessor unionAccessor(env, valObject); + bool convertOk = false; + convertOk = unionAccessor.TryConvertVariant(valueObject.value); + if (convertOk) { + bindArgs.push_back(std::move(valueObject)); + } else { + LOG_ERROR("conver ValueObject fail"); + return false; + } + } + return true; +} + +void ExecuteSqlSync(ani_env *env, ani_object object, ani_string sql, ani_object args) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return; + } + + std::vector bindArgs; + + bool convertOk = ConvertBindArgs(env, args, bindArgs, true); + if (!convertOk) { + LOG_ERROR("args conver fail"); + ThrowBusinessError(env, E_PARAM_ERROR, "Unknown parameters."); + return; + } + + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->nativeRdb == nullptr) { + LOG_ERROR("RdbStore should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized."); + return; + } + auto sqlStr = AniStringUtils::ToStd(env, sql); + auto status = proxy->nativeRdb->ExecuteSql(sqlStr, bindArgs); + ThrowBusinessError(env, status); +} + +void BeginTransaction(ani_env *env, ani_object object) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->nativeRdb == nullptr) { + LOG_ERROR("RdbStore should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized."); + return; + } + auto status = proxy->nativeRdb->BeginTransaction(); + ThrowBusinessError(env, status); +} + +void Commit(ani_env *env, ani_object object) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->nativeRdb == nullptr) { + LOG_ERROR("RdbStore should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized."); + return; + } + auto status = proxy->nativeRdb->Commit(); + ThrowBusinessError(env, status); +} + +void RollBack(ani_env *env, ani_object object) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->nativeRdb == nullptr) { + LOG_ERROR("RdbStore should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized."); + return; + } + auto status = proxy->nativeRdb->RollBack(); + ThrowBusinessError(env, status); +} + +ani_double BatchInsert(ani_env *env, ani_object object, ani_string tableName, ani_object values) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return 0; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->nativeRdb == nullptr) { + LOG_ERROR("RdbStore should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized."); + return 0; + } + auto name = AniStringUtils::ToStd(env, tableName); + std::vector valRefs; + UnionAccessor array2Ref(env, values); + array2Ref.TryConvert(valRefs); + ValuesBuckets vbs; + for (const auto& ref : valRefs) { + ani_object recordObj = static_cast(ref); + UnionAccessor recordAccessor(env, recordObj); + ValuesBucket valuesBucket; + recordAccessor.TryConvert(valuesBucket); + vbs.Put(valuesBucket); + } + auto [status, ret] = proxy->nativeRdb->BatchInsert(name, vbs); + ThrowBusinessError(env, status); + return ret; +} + +ani_double DeleteSync(ani_env *env, ani_object object, ani_object predicates) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return 0; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->nativeRdb == nullptr) { + LOG_ERROR("RdbStore should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized."); + return 0; + } + auto nativePredicates = AniObjectUtils::Unwrap(env, predicates); + if (nativePredicates == nullptr || nativePredicates->predicates == nullptr) { + LOG_ERROR("Predicates should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "Predicates uninitialized."); + return 0; + } + int rows = 0; + auto status = proxy->nativeRdb->Delete(rows, *(nativePredicates->predicates)); + ThrowBusinessError(env, status); + return rows; +} + +ani_double DeleteShareSync(ani_env *env, ani_object object, ani_string tableName, ani_object dataSharePredicates) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return 0; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->nativeRdb == nullptr) { + LOG_ERROR("RdbStore should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized."); + return 0; + } + + std::string name = AniStringUtils::ToStd(env, tableName); + + auto cppDataSharePredicates = AniObjectUtils::Unwrap(env, dataSharePredicates); + if (cppDataSharePredicates == nullptr) { + LOG_ERROR("Predicates should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "Predicates uninitialized."); + return 0; + } + RdbPredicates rdbPredicates = RdbDataShareAdapter::RdbUtils::ToPredicates(*cppDataSharePredicates, name); + int rows = 0; + auto status = proxy->nativeRdb->Delete(rows, rdbPredicates); + ThrowBusinessError(env, status); + return rows; +} + +ani_object QuerySqlSync(ani_env *env, ani_object object, ani_string sql, ani_object args) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return nullptr; + } + std::vector bindArgs; + auto sqlStr = AniStringUtils::ToStd(env, sql); + + if (!ConvertBindArgs(env, args, bindArgs, true)) { + LOG_ERROR("args conver fail"); + return nullptr; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->nativeRdb == nullptr) { + ThrowBusinessError(env, E_INNER_ERROR, "RdbStore uninitialized."); + return nullptr; + } + auto resultsetProxy = new ResultSetProxy(); + if (resultsetProxy == nullptr) { + ThrowBusinessError(env, E_INNER_ERROR, "Proxy is nullptr."); + return nullptr; + } + resultsetProxy->resultset = proxy->nativeRdb->QueryByStep(sqlStr, bindArgs); + if (resultsetProxy->resultset == nullptr) { + delete resultsetProxy; + ThrowBusinessError(env, E_INNER_ERROR, "QueryByStep returned nullptr."); + return nullptr; + } + + static const char *namespaceName = "L@ohos/data/relationalStore/relationalStore;"; + static const char *className = "LResultSetInner;"; + static const char *initFinalizer = "initFinalizer"; + ani_object obj = AniObjectUtils::Create(env, namespaceName, className); + if (nullptr == obj) { + delete resultsetProxy; + ThrowBusinessError(env, E_INNER_ERROR, "Create ResultSet failed.class: LResultSetInner;"); + return nullptr; + } + ani_status status = AniObjectUtils::Wrap(env, obj, resultsetProxy); + if (ANI_OK != status) { + delete resultsetProxy; + ThrowBusinessError(env, E_INNER_ERROR, "Wrap ResultSet failed.class: LResultSetInner;"); + return nullptr; + } + status = AniObjectUtils::CallObjMethod(env, namespaceName, className, initFinalizer, obj); + if (ANI_OK != status) { + ThrowBusinessError(env, E_INNER_ERROR, "init ResultSet finalizer failed.class: LResultSetInner;"); + return nullptr; + } + return obj; +} + +ani_status RdbStoreInit(ani_env *env) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return ANI_ERROR; + } + static const char *namespaceName = "L@ohos/data/relationalStore/relationalStore;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(namespaceName, &ns)) { + LOG_ERROR("Not found '%{public}s'", namespaceName); + return ANI_ERROR; + } + + static const char *clsName = "LRdbStoreInner;"; + ani_class cls; + if (ANI_OK != env->Namespace_FindClass(ns, clsName, &cls)) { + LOG_ERROR("Not found '%{public}s'", clsName); + return ANI_ERROR; + } + + std::array methods = { + ani_native_function {"batchInsertSync", nullptr, reinterpret_cast(BatchInsert)}, + ani_native_function {"beginTransaction", nullptr, reinterpret_cast(BeginTransaction)}, + ani_native_function {"commit", ":V", reinterpret_cast(Commit)}, + ani_native_function {"rollBack", nullptr, reinterpret_cast(RollBack)}, + ani_native_function {"executeSqlSync", nullptr, reinterpret_cast(ExecuteSqlSync)}, + ani_native_function {"deleteSync", nullptr, reinterpret_cast(DeleteSync)}, + ani_native_function {"deleteShareSync", nullptr, reinterpret_cast(DeleteShareSync)}, + ani_native_function {"querySqlSync", nullptr, reinterpret_cast(QuerySqlSync)}, + }; + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + LOG_ERROR("Cannot bind native methods to '%{public}s'", clsName); + return ANI_ERROR; + } + return ANI_OK; +} + + +} // namespace RelationalStoreAniKit +} // namespace OHOS + diff --git a/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_store_helper.cpp b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_store_helper.cpp new file mode 100644 index 00000000..ef5a9532 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/src/ani_rdb_store_helper.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. + */ + +#define LOG_TAG "AniRdbStoreHelper" +#include +#include +#include + +#include "logger.h" +#include "rdb_errno.h" +#include "ani_utils.h" +#include "ani_result_set.h" +#include "ani_rdb_error.h" +#include "ani_rdb_store_helper.h" +#include "rdb_sql_utils.h" + +namespace OHOS { +namespace RelationalStoreAniKit { + +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; + +class DefaultOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &rdbStore) override + { + return E_OK; + } + int OnUpgrade(RdbStore &rdbStore, int oldVersion, int newVersion) override + { + return E_OK; + } +}; + +static ani_object GetRdbStoreSync([[maybe_unused]] ani_env *env, ani_object context, ani_object config) +{ + DefaultOpenCallback callback; + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return nullptr; + } + int errCode = OK; + auto proxy = new RdbStoreProxy(); + if (proxy == nullptr) { + LOG_ERROR("new RdbStoreProxy failed."); + return nullptr; + } + int errorCode = RdbSqlUtils::CreateDirectory("/data/storage/el2/database/rdb"); + if (errorCode != E_OK) { + delete proxy; + ThrowBusinessError(env, E_INNER_ERROR, "CreateDirectory failed."); + return nullptr; + } + auto rdbConfig = RdbStoreConfig("/data/storage/el2/database/rdb/test.db"); + proxy->nativeRdb = RdbHelper::GetRdbStore(rdbConfig, -1, callback, errCode); + if (proxy->nativeRdb == nullptr) { + delete proxy; + ThrowBusinessError(env, E_INNER_ERROR, "RdbHelper returned nullptr."); + return nullptr; + } + static const char *namespaceName = "L@ohos/data/relationalStore/relationalStore;"; + static const char *className = "LRdbStoreInner;"; + static const char *initFinalizer = "initFinalizer"; + ani_object obj = AniObjectUtils::Create(env, namespaceName, className); + if (nullptr == obj) { + delete proxy; + LOG_ERROR("[ANI] Failed to create class '%{public}s' obj", className); + ThrowBusinessError(env, E_INNER_ERROR, "ANI create class."); + return nullptr; + } + ani_status status = AniObjectUtils::Wrap(env, obj, proxy); + if (ANI_OK != status) { + delete proxy; + LOG_ERROR("[ANI] Failed to wrap for class '%{public}s'", className); + ThrowBusinessError(env, E_INNER_ERROR, "ANI SetField."); + return nullptr; + } + status = AniObjectUtils::CallObjMethod(env, namespaceName, className, initFinalizer, obj); + if (ANI_OK != status) { + LOG_ERROR("[ANI] Failed to initFinalizer for class '%{public}s'.", className); + ThrowBusinessError(env, E_INNER_ERROR, "init rdbStore finalizer failed."); + return nullptr; + } + return obj; +} + +ani_status RdbStoreHelperInit(ani_env *env) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return ANI_ERROR; + } + + static const char *namespaceName = "L@ohos/data/relationalStore/relationalStore;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(namespaceName, &ns)) { + LOG_ERROR("Not found '%{public}s'", namespaceName); + return ANI_ERROR; + } + + std::array functions = { + ani_native_function {"getRdbStoreSync", nullptr, reinterpret_cast(GetRdbStoreSync)}, + }; + if (ANI_OK != env->Namespace_BindNativeFunctions(ns, functions.data(), functions.size())) { + LOG_ERROR("Cannot bind native functions to '%{public}s'", namespaceName); + return ANI_ERROR; + } + return ANI_OK; +} + +} // namespace RelationalStoreAniKit +} // namespace OHOS + diff --git a/relational_store/frameworks/js/ani/relationalstore/src/ani_result_set.cpp b/relational_store/frameworks/js/ani/relationalstore/src/ani_result_set.cpp new file mode 100644 index 00000000..b1391d52 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/src/ani_result_set.cpp @@ -0,0 +1,141 @@ +/* + * 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. + */ + +#define LOG_TAG "AniResultSet" +#include +#include +#include + +#include "logger.h" +#include "rdb_errno.h" +#include "ani_utils.h" +#include "ani_result_set.h" +#include "ani_rdb_error.h" + +namespace OHOS { +namespace RelationalStoreAniKit { + +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; + +ani_double GetColumnIndex(ani_env *env, ani_object object, ani_string col_name) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return 0; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->resultset == nullptr) { + LOG_ERROR("ResultSet should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "ResultSet uninitialized."); + return 0; + } + auto name = AniStringUtils::ToStd(env, col_name); + int index; + auto status = proxy->resultset->GetColumnIndex(name, index); + ThrowBusinessError(env, status); + return index; +} + +ani_double GetLong(ani_env *env, ani_object object, ani_double index) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return 0; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->resultset == nullptr) { + LOG_ERROR("ResultSet should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "ResultSet uninitialized."); + return 0; + } + int64_t ret; + auto status = proxy->resultset->GetLong(index, ret); + ThrowBusinessError(env, status); + return ret; +} + +ani_string GetString(ani_env *env, ani_object object, ani_double index) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return nullptr; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->resultset == nullptr) { + LOG_ERROR("ResultSet should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "ResultSet uninitialized."); + return nullptr; + } + std::string ret; + auto status = proxy->resultset->GetString(index, ret); + ThrowBusinessError(env, status); + ani_string retStr; + env->String_NewUTF8(ret.c_str(), ret.size(), &retStr); + return retStr; +} + +ani_boolean GoToFirstRow(ani_env *env, ani_object object) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return false; + } + auto proxy = AniObjectUtils::Unwrap(env, object); + if (proxy == nullptr || proxy->resultset == nullptr) { + LOG_ERROR("ResultSet should be initialized properly."); + ThrowBusinessError(env, E_INNER_ERROR, "ResultSet uninitialized."); + return false; + } + auto status = proxy->resultset->GoToFirstRow(); + return (status == ANI_OK); +} + +ani_status ResultSetInit(ani_env *env) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return ANI_ERROR; + } + static const char *namespaceName = "L@ohos/data/relationalStore/relationalStore;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(namespaceName, &ns)) { + LOG_ERROR("Not found '%{public}s", namespaceName); + return ANI_ERROR; + } + + ani_class cls; + const char *className = "LResultSetInner;"; + if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) { + LOG_ERROR("Not found '%{public}s", className); + return ANI_ERROR; + } + + std::array methods = { + ani_native_function {"getColumnIndex", nullptr, reinterpret_cast(GetColumnIndex)}, + ani_native_function {"getLong", nullptr, reinterpret_cast(GetLong)}, + ani_native_function {"getString", nullptr, reinterpret_cast(GetString)}, + ani_native_function {"goToFirstRow", nullptr, reinterpret_cast(GoToFirstRow)}, + }; + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + LOG_ERROR("Cannot bind native methods to '%{public}s", className); + return ANI_ERROR; + } + return ANI_OK; +} + +} // namespace RelationalStoreAniKit +} // namespace OHOS + diff --git a/relational_store/frameworks/js/ani/relationalstore/src/ani_utils.cpp b/relational_store/frameworks/js/ani/relationalstore/src/ani_utils.cpp new file mode 100644 index 00000000..5c184260 --- /dev/null +++ b/relational_store/frameworks/js/ani/relationalstore/src/ani_utils.cpp @@ -0,0 +1,636 @@ +/* + * 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. + */ + +#define LOG_TAG "AniUtils" +#include "ani_utils.h" +#include "asset_value.h" +#include "big_integer.h" +#include "values_bucket.h" +#include "logger.h" + +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; + + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Boolean;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Int;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/Double;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType() +{ + return IsInstanceOf("Lstd/core/String;"); +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_GetPropertyByName_Ref failed"); + return false; + } + value.push_back(ref); + } + LOG_DEBUG("convert ref array ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_GetPropertyByName_Ref failed"); + return false; + } + ani_boolean val; + if (ANI_OK != env_->Object_CallMethodByName_Boolean(static_cast(ref), "unboxed", nullptr, &val)) { + LOG_ERROR("Object_CallMethodByName_Boolean unbox failed"); + return false; + } + value.push_back(static_cast(val)); + } + LOG_DEBUG("convert bool array ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_GetPropertyByName_Ref failed"); + return false; + } + ani_int intValue; + if (ANI_OK != env_->Object_CallMethodByName_Int(static_cast(ref), "unboxed", nullptr, &intValue)) { + LOG_ERROR("Object_CallMethodByName_Int unbox failed"); + return false; + } + value.push_back(static_cast(intValue)); + } + LOG_DEBUG("convert int array ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_GetPropertyByName_Ref failed"); + return false; + } + ani_double val; + if (ANI_OK != env_->Object_CallMethodByName_Double(static_cast(ref), "unboxed", nullptr, &val)) { + LOG_ERROR("Object_CallMethodByName_Double unbox failed"); + return false; + } + value.push_back(static_cast(val)); + } + LOG_DEBUG("convert double array ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_ref buffer; + if (ANI_OK != env_->Object_GetFieldByName_Ref(obj_, "buffer", &buffer)) { + LOG_ERROR("Object_GetFieldByName_Ref failed"); + return false; + } + void* data; + size_t size; + if (ANI_OK != env_->ArrayBuffer_GetInfo(static_cast(buffer), &data, &size)) { + LOG_ERROR("ArrayBuffer_GetInfo failed"); + return false; + } + for (size_t i = 0; i < size; i++) { + value.push_back(static_cast(data)[i]); + } + LOG_DEBUG("convert uint8 array ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_ref buffer; + if (ANI_OK != env_->Object_GetFieldByName_Ref(obj_, "buffer", &buffer)) { + LOG_ERROR("Object_GetFieldByName_Ref failed"); + return false; + } + void* data; + size_t size; + if (ANI_OK != env_->ArrayBuffer_GetInfo(static_cast(buffer), &data, &size)) { + LOG_ERROR("ArrayBuffer_GetInfo failed"); + return false; + } + auto count = size / sizeof(float); + for (size_t i = 0; i < count; i++) { + value.push_back(static_cast(data)[i]); + } + LOG_DEBUG("convert float array ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvertArray(std::vector &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + LOG_ERROR("Object_GetPropertyByName_Double length failed"); + return false; + } + + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + LOG_ERROR("Object_CallMethodByName_Ref failed"); + return false; + } + value.push_back(AniStringUtils::ToStd(env_, static_cast(ref))); + } + LOG_DEBUG("convert string array ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvert(int &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_int aniValue; + auto ret = env_->Object_CallMethodByName_Int(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast(aniValue); + LOG_DEBUG("convert int ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvert(std::monostate &value) +{ + ani_boolean isNull = false; + auto status = env_->Reference_IsNull(static_cast(obj_), &isNull); + if (ANI_OK == status) { + if (isNull) { + value = std::monostate(); + LOG_DEBUG("convert null ok."); + return true; + } + } + return false; +} + +template<> +bool UnionAccessor::TryConvert(int64_t &value) +{ + return false; +} + +template<> +bool UnionAccessor::TryConvert(double &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast(aniValue); + LOG_DEBUG("convert double ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvert(std::string &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + value = AniStringUtils::ToStd(env_, static_cast(obj_)); + LOG_DEBUG("convert string ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvert(bool &value) +{ + if (!IsInstanceOfType()) { + return false; + } + + ani_boolean aniValue; + auto ret = env_->Object_CallMethodByName_Boolean(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast(aniValue); + LOG_DEBUG("convert bool ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvert>(std::vector &value) +{ + if (!IsInstanceOf("Lescompat/Uint8Array;")) { + return false; + } + return TryConvertArray(value); +} + +bool UnionAccessor::GetObjectRefPropertyByName(std::string clsName, const char *name, ani_ref &val) +{ + ani_class cls; + env_->FindClass(clsName.c_str(), &cls); + ani_method getter; + if (ANI_OK != env_->Class_FindGetter(cls, name, &getter)) { + LOG_ERROR("GetObjectRefPropertyByName Class_FindGetter failed"); + return false; + } + ani_ref ref; + if (ANI_OK != env_->Object_CallMethod_Ref(obj_, getter, &ref)) { + LOG_ERROR("GetObjectRefPropertyByName Object_CallMethod_Ref failed"); + return false; + } + val = ref; + return true; +} + +bool UnionAccessor::GetObjectStringPropertyByName(std::string clsName, const char *name, std::string &val) +{ + ani_ref ref; + auto isOk = GetObjectRefPropertyByName(clsName, name, ref); + if (!isOk) { + LOG_ERROR("GetObjectRefPropertyByName failed"); + return false; + } + val = AniStringUtils::ToStd(env_, static_cast(ref)); + return true; +} + +bool UnionAccessor::GetObjectEnumValuePropertyByName( + std::string clsName, const char *name, ani_int &val, bool optional) +{ + ani_ref ref; + auto isOk = GetObjectRefPropertyByName(clsName, name, ref); + if (!isOk) { + LOG_ERROR("GetObjectRefPropertyByName failed"); + return false; + } + if (optional) { + ani_boolean isUndefined; + auto err = env_->Reference_IsUndefined(ref, &isUndefined); + if (err != ANI_OK) { + LOG_ERROR("Reference_IsUndefined fail."); + return false; + } + if (isUndefined) { + LOG_DEBUG("Optional enum item undefined."); + return true; + } + } + ani_int enumValue; + auto status = env_->EnumItem_GetValue_Int(static_cast(ref), &enumValue); + if (status != ANI_OK) { + LOG_ERROR("EnumItem_GetValue_Int failed"); + return false; + } + val = enumValue; + return true; +} + +template<> +bool UnionAccessor::TryConvert(AssetValue &value) +{ + std::string clsName = "L@ohos/data/relationalStore/relationalStore/Asset;"; + if (!IsInstanceOf(clsName)) { + return false; + } + auto isOk = GetObjectStringPropertyByName(clsName, "name", value.name); + if (!isOk) { + return false; + } + isOk = GetObjectStringPropertyByName(clsName, "uri", value.uri); + if (!isOk) { + return false; + } + isOk = GetObjectStringPropertyByName(clsName, "path", value.path); + if (!isOk) { + return false; + } + isOk = GetObjectStringPropertyByName(clsName, "createTime", value.createTime); + if (!isOk) { + return false; + } + isOk = GetObjectStringPropertyByName(clsName, "modifyTime", value.modifyTime); + if (!isOk) { + return false; + } + isOk = GetObjectStringPropertyByName(clsName, "size", value.size); + if (!isOk) { + return false; + } + ani_int enumVal = 0; + isOk = GetObjectEnumValuePropertyByName(clsName, "status", enumVal, true); + if (!isOk) { + return false; + } + value.status = static_cast(enumVal); + if (value.status != AssetValue::STATUS_DELETE) { + value.status = AssetValue::STATUS_UNKNOWN; + } + value.hash = value.modifyTime + "_" + value.size; + LOG_DEBUG("convert asset ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvert>(std::vector &value) +{ + std::string clsName = "[L@ohos/data/relationalStore/relationalStore/Asset;"; + if (!IsInstanceOf(clsName)) { + return false; + } + ani_size arrayLength; + auto status = env_->Array_GetLength(static_cast(obj_), &arrayLength); + if (status != ANI_OK) { + LOG_ERROR("Array_GetLength failed"); + return false; + } + for (int i = 0; i < int(arrayLength); i++) { + ani_ref result; + status = env_->Array_Get_Ref(static_cast(obj_), i, &result); + if (status != ANI_OK) { + LOG_ERROR("Array_Get_Ref failed"); + return false; + } + ani_object asset = static_cast(result); + UnionAccessor sub(env_, asset); + AssetValue val; + auto isOk = sub.TryConvert(val); + if (!isOk) { + return false; + } + value.push_back(val); + } + LOG_DEBUG("convert assets ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvert>(std::vector &value) +{ + if (!IsInstanceOf("Lescompat/Float32Array;")) { + return false; + } + return TryConvertArray(value); +} + +template<> +bool UnionAccessor::TryConvert(BigInteger &value) +{ + std::string clsName = "Lescompat/BigInt;"; + ani_class cls; + auto status = env_->FindClass(clsName.c_str(), &cls); + if (status != ANI_OK) { + LOG_ERROR("FindClass failed"); + return false; + } + + ani_boolean ret; + env_->Object_InstanceOf(obj_, cls, &ret); + if (!ret) { + return false; + } + + ani_method getLongMethod; + if (ANI_OK != env_->Class_FindMethod(cls, "getLong", ":J", &getLongMethod)) { + LOG_ERROR("Class_FindMethod failed"); + return false; + } + + ani_long longNum; + if (ANI_OK != env_->Object_CallMethod_Long(obj_, getLongMethod, &longNum)) { + LOG_ERROR("Object_CallMethod_Long failed"); + return false; + } + value = BigInteger(longNum); + LOG_DEBUG("convert bigint ok."); + return true; +} + +template<> +bool UnionAccessor::TryConvert>(std::vector &value) +{ + if (!IsInstanceOf("Lescompat/Array;")) { + return false; + } + return TryConvertArray(value); +} + +ani_ref UnionAccessor::AniIteratorNext(ani_ref interator, bool &isSuccess) +{ + ani_ref next; + ani_boolean done; + if (ANI_OK != env_->Object_CallMethodByName_Ref(static_cast(interator), "next", nullptr, &next)) { + LOG_ERROR("Failed to get next key"); + isSuccess = false; + return nullptr; + } + + if (ANI_OK != env_->Object_GetFieldByName_Boolean(static_cast(next), "done", &done)) { + LOG_ERROR("Failed to check iterator done"); + isSuccess = false; + return nullptr; + } + if (done) { + return nullptr; + } + return next; +} + +template<> +bool UnionAccessor::TryConvert(ValuesBucket &value) +{ + if (!IsInstanceOf("Lescompat/Record;")) { + return false; + } + ani_ref keys; + auto status = env_->Object_CallMethodByName_Ref(obj_, "keys", ":Lescompat/IterableIterator;", &keys); + if (status != ANI_OK) { + LOG_ERROR("Object_CallMethodByName_Ref failed"); + } + bool success = true; + ani_ref next = AniIteratorNext(keys, success); + while (next) { + ani_ref key_value; + if (ANI_OK != env_->Object_GetFieldByName_Ref(static_cast(next), "value", &key_value)) { + LOG_ERROR("Failed to get key value"); + success = false; + break; + } + + ani_ref valueObj; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", nullptr, &valueObj, key_value)) { + LOG_ERROR("Failed to get value for key"); + success = false; + break; + } + ani_object recordValue = static_cast(valueObj); + UnionAccessor sub(env_, recordValue); + ValueObject val; + success = sub.TryConvertVariant(val.value); + if (success) { + value.Put(AniStringUtils::ToStd(env_, static_cast(key_value)), val); + } else { + LOG_ERROR("Failed to convert AssetValue"); + break; + } + next = AniIteratorNext(keys, success); + } + return success; +} + +template<> +std::optional OptionalAccessor::Convert() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "doubleValue", nullptr, &aniValue); + if (ret != ANI_OK) { + return std::nullopt; + } + auto value = static_cast(aniValue); + return value; +} + +template<> +std::optional OptionalAccessor::Convert() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_size strSize; + env_->String_GetUTF8Size(static_cast(obj_), &strSize); + + std::vector buffer(strSize + 1); + char* utf8_buffer = buffer.data(); + + ani_size bytes_written = 0; + env_->String_GetUTF8(static_cast(obj_), utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + return content; +} + +static void CleanNativePtr(ani_env *env, ani_object object) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return; + } + ani_long ptr = 0; + if (ANI_OK != env->Object_GetFieldByName_Long(object, "targetPtr", &ptr)) { + LOG_ERROR("Can not get targetPtr."); + return; + } + delete reinterpret_cast(ptr); +} + +ani_status CleanerInit(ani_env *env) +{ + if (env == nullptr) { + LOG_ERROR("env is nullptr."); + return ANI_ERROR; + } + + static const char *namespaceName = "L@ohos/data/relationalStore/relationalStore;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(namespaceName, &ns)) { + LOG_ERROR("Not found '%{public}s", namespaceName); + return ANI_ERROR; + } + + ani_class cls; + const char *className = "LCleaner;"; + if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) { + LOG_ERROR("Not found '%{public}s", className); + return ANI_ERROR; + } + + std::array methods = { + ani_native_function {"clean", nullptr, reinterpret_cast(CleanNativePtr)}, + }; + if (ANI_OK != env->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + LOG_ERROR("Cannot bind native methods to '%{public}s", className); + return ANI_ERROR; + } + return ANI_OK; +} diff --git a/relational_store/frameworks/js/napi/cloud_data/BUILD.gn b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn index b9ffc946..ab1021d6 100644 --- a/relational_store/frameworks/js/napi/cloud_data/BUILD.gn +++ b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn @@ -32,18 +32,19 @@ ohos_shared_library("clouddata") { "${cloud_data_napi_path}/src/js_error_utils.cpp", "${cloud_data_napi_path}/src/napi_queue.cpp", "${cloud_data_native_path}/src/cloud_manager.cpp", + "${cloud_data_native_path}/src/cloud_notifier_stub.cpp", "${cloud_data_native_path}/src/cloud_service_proxy.cpp", "${cloud_data_native_path}/src/cloud_types_util.cpp", "${relational_store_napi_path}/common/src/js_df_manager.cpp", + "${relational_store_napi_path}/common/src/js_scope.cpp", "${relational_store_napi_path}/common/src/js_utils.cpp", + "${relational_store_napi_path}/common/src/js_uv_queue.cpp", ] include_dirs = [ "include", "${relational_store_js_common_path}/include", "${cloud_data_native_path}/include", - "${datashare_path}/provider/include", - "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_innerapi_path}/rdb/include", "${relational_store_innerapi_path}/cloud_data/include", @@ -58,9 +59,12 @@ ohos_shared_library("clouddata") { "ability_runtime:abilitykit_native", "ability_runtime:napi_base_context", "c_utils:utils", + "data_share:datashare_common_lite", + "eventhandler:libeventhandler", "hilog:libhilog", "hitrace:hitrace_meter", "ipc:ipc_core", + "kv_store:datamgr_common", "napi:ace_napi", "samgr:samgr_proxy", ] diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_utils.h b/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_utils.h index ca8651c4..9c3b16c1 100644 --- a/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_utils.h +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_utils.h @@ -65,6 +65,15 @@ napi_value Convert2JSValue(napi_env env, const StatisticInfo &value); template<> napi_value Convert2JSValue(napi_env env, const CloudSyncInfo &value); + +template<> +napi_value Convert2JSValue(napi_env env, const DistributedRdb::Statistic &value); + +template<> +napi_value Convert2JSValue(napi_env env, const DistributedRdb::TableDetail &value); + +template<> +napi_value Convert2JSValue(napi_env env, const DistributedRdb::ProgressDetail &value); }; // namespace JSUtils } // namespace OHOS::AppDataMgrJsKit #endif // CLOUD_DATA_JS_CLOUD_UTILS_H \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_config.h b/relational_store/frameworks/js/napi/cloud_data/include/js_config.h index f299f1e6..6d36cb98 100644 --- a/relational_store/frameworks/js/napi/cloud_data/include/js_config.h +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_config.h @@ -18,8 +18,11 @@ #include "cloud_manager.h" #include "js_const_properties.h" +#include "js_uv_queue.h" +#include "napi_queue.h" namespace OHOS::CloudData { +using namespace OHOS::AppDataMgrJsKit; class JsConfig { public: JsConfig(); @@ -56,6 +59,18 @@ public: static napi_value QueryStatistics(napi_env env, napi_callback_info info); static napi_value SetGlobalCloudStrategy(napi_env env, napi_callback_info info); static napi_value QueryLastSyncInfo(napi_env env, napi_callback_info info); + static napi_value CloudSync(napi_env env, napi_callback_info info); +private: + struct CloudSyncContext : public ContextBase { + std::string bundleName; + std::string storeId; + int32_t syncMode; + napi_ref asyncHolder = nullptr; + std::shared_ptr queue; + }; + static void HandleCloudSyncArgs(napi_env env, napi_callback_info info, std::shared_ptr ctxt); + static uint32_t GetSeqNum(); + static std::atomic seqNum_; }; } // namespace OHOS::CloudData diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_utils.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_utils.cpp index 722e1b58..df2b8696 100644 --- a/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_utils.cpp +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_utils.cpp @@ -269,5 +269,50 @@ napi_value Convert2JSValue(napi_env env, const CloudSyncInfo &value) napi_set_named_property(env, jsValue, "syncStatus", Convert2JSValue(env, value.syncStatus)); return jsValue; } + +template<> +napi_value Convert2JSValue(napi_env env, const DistributedRdb::Statistic &value) +{ + std::vector descriptors = { + DECLARE_JS_PROPERTY(env, "total", value.total), + DECLARE_JS_PROPERTY(env, "success", value.success), + DECLARE_JS_PROPERTY(env, "successful", value.success), + DECLARE_JS_PROPERTY(env, "failed", value.failed), + DECLARE_JS_PROPERTY(env, "remained", value.untreated), + }; + napi_value object = nullptr; + NAPI_CALL_RETURN_ERR( + napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); + return object; +} + +template<> +napi_value Convert2JSValue(napi_env env, const DistributedRdb::TableDetail &value) +{ + std::vector descriptors = { + DECLARE_JS_PROPERTY(env, "upload", value.upload), + DECLARE_JS_PROPERTY(env, "download", value.download), + }; + + napi_value object = nullptr; + NAPI_CALL_RETURN_ERR( + napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); + return object; +} + +template<> +napi_value Convert2JSValue(napi_env env, const DistributedRdb::ProgressDetail &value) +{ + std::vector descriptors = { + DECLARE_JS_PROPERTY(env, "schedule", value.progress), + DECLARE_JS_PROPERTY(env, "code", value.code), + DECLARE_JS_PROPERTY(env, "details", value.details), + }; + + napi_value object = nullptr; + NAPI_CALL_RETURN_ERR( + napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); + return object; +} }; // namespace JSUtils } // namespace OHOS::AppDataMgrJsKit diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp index b840645d..30686bd3 100644 --- a/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp @@ -26,11 +26,10 @@ #include "js_strategy_context.h" #include "js_utils.h" #include "logger.h" -#include "napi_queue.h" using namespace OHOS::Rdb; using namespace OHOS::CloudData; -using namespace OHOS::AppDataMgrJsKit; +std::atomic JsConfig::seqNum_{}; JsConfig::JsConfig() { } @@ -435,6 +434,10 @@ napi_value JsConfig::New(napi_env env, napi_callback_info info) } auto finalize = [](napi_env env, void *data, void *hint) { + if (data == nullptr) { + LOG_ERROR("data is nullptr."); + return; + } auto tid = JSDFManager::GetInstance().GetFreedTid(data); if (tid != 0) { LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); @@ -510,6 +513,97 @@ napi_value JsConfig::QueryLastSyncInfo(napi_env env, napi_callback_info info) return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); } +void JsConfig::HandleCloudSyncArgs(napi_env env, napi_callback_info info, std::shared_ptr ctxt) +{ + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { + // less required 4 arguments :: + ASSERT_BUSINESS_ERR(ctxt, argc >= 4, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + // 0 is the index of argument bundleName + int status = JSUtils::Convert2Value(env, argv[0], ctxt->bundleName); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, + "The type of bundleName must be string and not empty."); + // 1 is the index of argument storeId + status = JSUtils::Convert2Value(env, argv[1], ctxt->storeId); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, + "The type of storeId must be string and not empty."); + // 2 is the index of argument syncMode + status = JSUtils::Convert2ValueExt(env, argv[2], ctxt->syncMode); + ASSERT_BUSINESS_ERR( + ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of syncMode must be number."); + // 3 is the index of argument progress, it should be a founction + napi_valuetype valueType = napi_undefined; + napi_status ret = napi_typeof(env, argv[3], &valueType); + ASSERT_BUSINESS_ERR( + ctxt, ret == napi_ok && valueType == napi_function, Status::INVALID_ARGUMENT, + "The type of progress should be function."); + ASSERT_BUSINESS_ERR( + ctxt, napi_create_reference(env, argv[3], 1, &ctxt->asyncHolder) == napi_ok, // 3 means the progress + Status::INVALID_ARGUMENT, "create refrence failed."); + }, true); +} + +/* + * [JS API Prototype] + * [Promise] + * cloudSync(bundleName: string, storeId: string, mode: relationalStore.SyncMode, + * progress: Callback: Promise; + */ +napi_value JsConfig::CloudSync(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + ctxt->queue = std::make_shared(env); + HandleCloudSyncArgs(env, info, ctxt); + ASSERT_NULL(!ctxt->isThrowError, "CloudSync exit"); + + auto execute = [ctxt]() { + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (proxy == nullptr) { + if (state != CloudService::SERVER_UNAVAILABLE) { + state = CloudService::NOT_SUPPORT; + } + ctxt->status = (GenerateNapiError(state, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + return; + } + auto async = [ctxt, queue = ctxt->queue, cb = ctxt->asyncHolder](const DistributedRdb::Details &details) { + if (queue == nullptr || cb == nullptr) { + return; + } + bool repeate = !details.empty() && details.begin()->second.progress != DistributedRdb::SYNC_FINISH; + queue->AsyncCallInOrder({ cb, repeate }, [details](napi_env env, int &argc, napi_value *argv) -> void { + argc = 1; + argv[0] = details.empty() ? nullptr : JSUtils::Convert2JSValue(env, details.begin()->second); + }); + }; + CloudService::Option option; + option.syncMode = ctxt->syncMode; + option.seqNum = GetSeqNum(); + auto status = proxy->CloudSync(ctxt->bundleName, ctxt->storeId, option, async); + if (status == Status::INVALID_ARGUMENT) { + status = Status::INVALID_ARGUMENT_V20; + } + ctxt->status = + (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; + }; + auto output = [env, ctxt](napi_value &result) { + if (ctxt->status != napi_ok && ctxt->asyncHolder != nullptr) { + napi_delete_reference(env, ctxt->asyncHolder); + } + napi_get_undefined(env, &result); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +uint32_t JsConfig::GetSeqNum() +{ + uint32_t value = ++seqNum_; + if (value == 0) { + value = ++seqNum_; + } + return value; +} + napi_value JsConfig::InitConfig(napi_env env, napi_value exports) { auto lambda = []() -> std::vector { @@ -523,6 +617,7 @@ napi_value JsConfig::InitConfig(napi_env env, napi_value exports) DECLARE_NAPI_STATIC_FUNCTION("queryStatistics", JsConfig::QueryStatistics), DECLARE_NAPI_STATIC_FUNCTION("setGlobalCloudStrategy", JsConfig::SetGlobalCloudStrategy), DECLARE_NAPI_STATIC_FUNCTION("queryLastSyncInfo", JsConfig::QueryLastSyncInfo), + DECLARE_NAPI_STATIC_FUNCTION("cloudSync", JsConfig::CloudSync), }; return properties; }; diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_error_utils.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_error_utils.cpp index 5445becc..c99cac0d 100644 --- a/relational_store/frameworks/js/napi/cloud_data/src/js_error_utils.cpp +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_error_utils.cpp @@ -27,7 +27,8 @@ static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = { { Status::INVALID_ARGUMENT, 401, "Parameter error." }, { Status::NOT_SUPPORT, 801, "Not support." }, { Status::PERMISSION_DENIED, 202, "Permission denied, non-system app called system api." }, - { Status::CLOUD_CONFIG_PERMISSION_DENIED, 201, "Permission denied." } + { Status::CLOUD_CONFIG_PERMISSION_DENIED, 201, "Permission denied." }, + { Status::INVALID_ARGUMENT_V20, 14800001, "Invalid args." } }; const std::optional GetJsErrorCode(int32_t errorCode) diff --git a/relational_store/frameworks/js/napi/cloud_extension/BUILD.gn b/relational_store/frameworks/js/napi/cloud_extension/BUILD.gn index 93e7217a..572bbab8 100644 --- a/relational_store/frameworks/js/napi/cloud_extension/BUILD.gn +++ b/relational_store/frameworks/js/napi/cloud_extension/BUILD.gn @@ -13,7 +13,6 @@ import("//build/config/components/ets_frontend/es2abc_config.gni") import("//build/ohos.gni") -import("//foundation/arkui/ace_engine/ace_config.gni") es2abc_gen_abc("gen_cloud_extension_abc") { src_js = rebase_path("cloud_extension_stub.js") diff --git a/relational_store/frameworks/js/napi/common/include/js_uv_queue.h b/relational_store/frameworks/js/napi/common/include/js_uv_queue.h index c99ff5ca..71de0ece 100644 --- a/relational_store/frameworks/js/napi/common/include/js_uv_queue.h +++ b/relational_store/frameworks/js/napi/common/include/js_uv_queue.h @@ -71,10 +71,7 @@ private: static napi_value Resolved(napi_env env, napi_callback_info info); static napi_value Rejected(napi_env env, napi_callback_info info); static napi_value Future(napi_env env, napi_callback_info info, bool exception); - static void DoWork(uv_work_t *work); static void DoExecute(uv_work_t *work); - static void DoUvCallback(uv_work_t *work, int status); - static void DoUvPromise(uv_work_t *work, int status); struct UvEntry { napi_env env_ = nullptr; @@ -93,9 +90,8 @@ private: Result *StealResult(); int32_t GetArgv(napi_value *argv, int32_t max); }; - static Task GenCallbackTask(std::shared_ptr entry); - + static Task GenPromiseTask(std::shared_ptr entry); napi_env env_ = nullptr; uv_loop_s *loop_ = nullptr; std::shared_ptr handler_; diff --git a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_const_properties.h b/relational_store/frameworks/js/napi/common/mock/include/mock.h similarity index 68% rename from relational_store/frameworks/js/napi/graphstore/include/napi_gdb_const_properties.h rename to relational_store/frameworks/js/napi/common/mock/include/mock.h index 02e400e9..03ed7faa 100644 --- a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_const_properties.h +++ b/relational_store/frameworks/js/napi/common/mock/include/mock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 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 @@ -12,15 +12,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef SEND_EVENT_MOCK_H +#define SEND_EVENT_MOCK_H +#include -#ifndef OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_CONST_PROPERTIES_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_CONST_PROPERTIES_H - -#include "napi/native_common.h" +#include "event_handler.h" #include "napi/native_api.h" +#include "napi/native_common.h" #include "napi/native_node_api.h" -namespace OHOS::GraphStoreJsKit { -napi_status InitConstProperties(napi_env env, napi_value exports); -} -#endif \ No newline at end of file +napi_status SendEventMock( + napi_env env, const std::function &cb, napi_event_priority priority, const char *name); +#endif //SEND_EVENT_MOCK_H \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/common/mock/include/napi_async_proxy.h b/relational_store/frameworks/js/napi/common/mock/include/napi_async_proxy.h index e3ac9bc5..65d997cb 100644 --- a/relational_store/frameworks/js/napi/common/mock/include/napi_async_proxy.h +++ b/relational_store/frameworks/js/napi/common/mock/include/napi_async_proxy.h @@ -14,6 +14,7 @@ */ #ifndef PREFERENCES_JSKIT_NAPI_ASYNC_PROXY_H #define PREFERENCES_JSKIT_NAPI_ASYNC_PROXY_H +#include #include #include "napi/native_api.h" @@ -61,7 +62,7 @@ public: public: void Init(napi_env env, napi_callback_info info) { - asyncContext = new T(); + asyncContext = new (std::nothrow) T(); if (asyncContext == nullptr) { return; } @@ -101,6 +102,41 @@ public: parserThis(asyncContext->env, thisObj, asyncContext); } + static void OnComplete(napi_env env, napi_status status, void *data) + { + if (data == nullptr) { + return; + } + T *context = (T *)data; + napi_value output = nullptr; + int completeStatus = context->completeFunc(context, output); + napi_value result[RESULT_COUNT] = { 0 }; + if (context->execStatus == OK && completeStatus == OK) { + napi_get_undefined(env, &result[0]); + result[1] = output; + } else { + napi_value message = nullptr; + napi_create_string_utf8(env, "async call failed", NAPI_AUTO_LENGTH, &message); + napi_create_error(env, nullptr, message, &result[0]); + napi_get_undefined(env, &result[1]); + } + if (context->deferred) { + // promise + if (context->execStatus == OK && completeStatus == OK) { + napi_resolve_deferred(env, context->deferred, result[1]); + } else { + napi_reject_deferred(env, context->deferred, result[0]); + } + } else { + // callback + napi_value callback = nullptr; + napi_get_reference_value(env, context->callbackRef, &callback); + napi_value callbackResult = nullptr; + napi_call_function(env, nullptr, callback, RESULT_COUNT, result, &callbackResult); + } + delete context; + } + napi_value DoAsyncWork(std::string resourceName, NapiAsyncExecute execFunc, NapiAsyncComplete completeFunc) { if (asyncContext == nullptr) { @@ -118,42 +154,18 @@ public: napi_create_string_utf8(asyncContext->env, resourceName.c_str(), NAPI_AUTO_LENGTH, &resource); asyncContext->execFunc = execFunc; asyncContext->completeFunc = completeFunc; - NAPI_CALL_BASE(asyncContext->env, napi_create_async_work(asyncContext->env, nullptr, resource, - [](napi_env env, void *data) { - T *context = (T *)data; - context->execStatus = context->execFunc(context); - }, - [](napi_env env, napi_status status, void *data) { - T *context = (T *)data; - napi_value output = nullptr; - int completeStatus = context->completeFunc(context, output); - napi_value result[RESULT_COUNT] = { 0 }; - if (context->execStatus == OK && completeStatus == OK) { - napi_get_undefined(env, &result[0]); - result[1] = output; - } else { - napi_value message = nullptr; - napi_create_string_utf8(env, "async call failed", NAPI_AUTO_LENGTH, &message); - napi_create_error(env, nullptr, message, &result[0]); - napi_get_undefined(env, &result[1]); - } - if (context->deferred) { - // promise - if (context->execStatus == OK && completeStatus == OK) { - napi_resolve_deferred(env, context->deferred, result[1]); - } else { - napi_reject_deferred(env, context->deferred, result[0]); + NAPI_CALL_BASE(asyncContext->env, + napi_create_async_work( + asyncContext->env, nullptr, resource, + [](napi_env env, void *data) { + if (data == nullptr) { + return; } - } else { - // callback - napi_value callback = nullptr; - napi_get_reference_value(env, context->callbackRef, &callback); - napi_value callbackResult = nullptr; - napi_call_function(env, nullptr, callback, RESULT_COUNT, result, &callbackResult); - } - delete context; - }, - (void *)asyncContext, &asyncContext->work), ret); + T *context = (T *)data; + context->execStatus = context->execFunc(context); + }, + OnComplete, (void *)asyncContext, &asyncContext->work), + ret); NAPI_CALL_BASE(asyncContext->env, napi_queue_async_work(asyncContext->env, asyncContext->work), ret); return ret; } diff --git a/relational_store/frameworks/js/napi/common/mock/src/js_ability.cpp b/relational_store/frameworks/js/napi/common/mock/src/js_ability.cpp index 069015e2..5b1c873c 100644 --- a/relational_store/frameworks/js/napi/common/mock/src/js_ability.cpp +++ b/relational_store/frameworks/js/napi/common/mock/src/js_ability.cpp @@ -33,7 +33,7 @@ Context::Context() #ifdef WINDOWS_PLATFORM baseDir = getenv("TEMP"); if (!baseDir.empty()) { - databaseDir_ = baseDir + "\\HuaweiDevEcoStudioDatabases"; + databaseDir_ = baseDir + "\\Databases"; } #endif @@ -41,7 +41,7 @@ Context::Context() baseDir = getenv("LOGNAME"); baseDir = "/Users/" + baseDir + "/Library/Caches"; if (!baseDir.empty()) { - databaseDir_ = baseDir + "/HuaweiDevEcoStudioDatabases"; + databaseDir_ = baseDir + "/Databases"; } #endif bundleName_ = "com.example.myapplication"; diff --git a/relational_store/frameworks/js/napi/common/mock/src/mock.cpp b/relational_store/frameworks/js/napi/common/mock/src/mock.cpp new file mode 100644 index 00000000..756d797f --- /dev/null +++ b/relational_store/frameworks/js/napi/common/mock/src/mock.cpp @@ -0,0 +1,72 @@ +/* + * 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 "mock.h" +#include "uv.h" + +struct UvEntry { + std::function callback; +}; +napi_status SendEventMock(napi_env env, + const std::function& cb, + napi_event_priority priority, + const char* name) +{ + if (env == nullptr || !cb || priority < napi_eprio_vip || priority > napi_eprio_idle) { + return napi_status::napi_invalid_arg; + } + + uv_loop_s *loop = nullptr; + napi_get_uv_event_loop(env, &loop); + if (loop == nullptr) { + return napi_status::napi_invalid_arg; + } + + uv_work_t *work = new (std::nothrow) uv_work_t; + if (work == nullptr) { + return napi_status::napi_invalid_arg; + } + auto entry = new (std::nothrow) UvEntry(); + if (entry == nullptr) { + delete work; + return napi_status::napi_invalid_arg; + } + entry->callback = cb; + work->data = entry; + + int ret = uv_queue_work(loop, work, [](uv_work_t *data) { + return; + }, [](uv_work_t *work, int status) { + if (work == nullptr) { + return; + } + if (work->data == nullptr) { + delete work; + return; + } + auto entry = static_cast(work->data); + if (entry->callback) { + entry->callback(); + } + delete entry; + delete work; + return; + }); + if (ret < 0) { + delete entry; + delete work; + return napi_status::napi_invalid_arg; + } + return napi_ok; +} \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/common/src/js_sendable_utils.cpp b/relational_store/frameworks/js/napi/common/src/js_sendable_utils.cpp index 935e2882..bd7dfaf9 100644 --- a/relational_store/frameworks/js/napi/common/src/js_sendable_utils.cpp +++ b/relational_store/frameworks/js/napi/common/src/js_sendable_utils.cpp @@ -39,7 +39,10 @@ napi_value JSUtils::Convert2Sendable(napi_env env, const std::vector &v LOG_ERROR("napi_create_sendable_arraybuffer failed %{public}d", status); return nullptr; } - if (value.size() != 0) { + if (value.size() > 0) { + if (native == nullptr) { + return nullptr; + } std::copy(value.begin(), value.end(), static_cast(native)); } status = napi_create_sendable_typedarray(env, napi_uint8_array, value.size(), buffer, 0, &jsValue); @@ -85,7 +88,10 @@ napi_value JSUtils::Convert2Sendable(napi_env env, const std::vector &val LOG_ERROR("napi_create_sendable_arraybuffer failed %{public}d", status); return nullptr; } - if (value.size() != 0) { + if (value.size() > 0) { + if (native == nullptr) { + return nullptr; + } std::copy(value.begin(), value.end(), static_cast(native)); } status = napi_create_sendable_typedarray(env, napi_float32_array, value.size(), buffer, 0, &jsValue); @@ -183,6 +189,9 @@ napi_value JSUtils::ToSendableTypedArray(napi_env env, napi_value jsValue) status = napi_create_sendable_arraybuffer(env, length, (void **)&native, &buffer); ASSERT(status == napi_ok, "napi_create_sendable_arraybuffer failed", nullptr); if (length > 0) { + if (native == nullptr || tmp == nullptr) { + return nullptr; + } errno_t result = memcpy_s(native, length, tmp, length); if (result != EOK) { LOG_ERROR("memcpy_s failed, result is %{public}d", result); diff --git a/relational_store/frameworks/js/napi/common/src/js_utils.cpp b/relational_store/frameworks/js/napi/common/src/js_utils.cpp index 188c459f..66210da2 100644 --- a/relational_store/frameworks/js/napi/common/src/js_utils.cpp +++ b/relational_store/frameworks/js/napi/common/src/js_utils.cpp @@ -43,7 +43,6 @@ static constexpr JSUtils::JsFeatureSpace FEATURE_NAME_SPACES[] = { { "ohos.data.dataShare", "ZGF0YS5kYXRhU2hhcmU=", false }, { "ohos.data.distributedDataObject", "ZGF0YS5kaXN0cmlidXRlZERhdGFPYmplY3Q=", false }, { "ohos.data.distributedKVStore", "ZGF0YS5kaXN0cmlidXRlZEtWU3RvcmU=", false }, - { "ohos.data.graphStore", "ZGF0YS5ncmFwaFN0b3Jl", true }, { "ohos.data.rdb", "ZGF0YS5yZGI=", true }, { "ohos.data.relationalStore", "ZGF0YS5yZWxhdGlvbmFsU3RvcmU=", true }, }; @@ -376,6 +375,9 @@ napi_value JSUtils::Convert2JSValue(napi_env env, const std::vector &va if (status != napi_ok) { return nullptr; } + if (value.size() > 0 && native == nullptr) { + return nullptr; + } for (size_t i = 0; i < value.size(); i++) { *(static_cast(native) + i) = value[i]; } @@ -445,7 +447,7 @@ napi_value JSUtils::Convert2JSValue(napi_env env, const std::vector &valu if (status != napi_ok) { return nullptr; } - if (native == nullptr) { + if (value.size() > 0 && native == nullptr) { return nullptr; } for (size_t i = 0; i < value.size(); i++) { @@ -680,6 +682,7 @@ napi_value JSUtils::ToJsTypedArray(napi_env env, napi_value sendableValue) status = napi_create_arraybuffer(env, length, (void **)&native, &buffer); ASSERT(status == napi_ok, "napi_create_arraybuffer failed", nullptr); if (length > 0) { + ASSERT(native != nullptr && tmp != nullptr, "native is nullptr.", nullptr); errno_t result = memcpy_s(native, length, tmp, length); if (result != EOK) { LOG_ERROR("memcpy_s failed, result is %{public}d", result); diff --git a/relational_store/frameworks/js/napi/common/src/js_uv_queue.cpp b/relational_store/frameworks/js/napi/common/src/js_uv_queue.cpp index 7996b287..b6a67f2f 100644 --- a/relational_store/frameworks/js/napi/common/src/js_uv_queue.cpp +++ b/relational_store/frameworks/js/napi/common/src/js_uv_queue.cpp @@ -19,6 +19,7 @@ #include "js_scope.h" #include "logger.h" +#include "napi/native_node_api.h" namespace OHOS::AppDataMgrJsKit { using namespace OHOS::Rdb; constexpr size_t ARGC_MAX = 6; @@ -39,21 +40,11 @@ UvQueue::~UvQueue() void UvQueue::AsyncCall(UvCallback callback, Args args, Result result) { - if (loop_ == nullptr || callback.IsNull()) { - LOG_ERROR("loop_ or callback is nullptr."); - return; - } - uv_work_t *work = new (std::nothrow) uv_work_t; - if (work == nullptr) { - LOG_ERROR("No memory for uv_work_t."); - return; - } - auto entry = new (std::nothrow) UvEntry(); - if (entry == nullptr) { - delete work; - LOG_ERROR("No memory for UvEntry."); + if (callback.IsNull()) { + LOG_ERROR("callback is nullptr."); return; } + auto entry = std::make_shared(); entry->env_ = env_; entry->object_ = callback.object_; entry->callback_ = callback.callback_; @@ -61,12 +52,9 @@ void UvQueue::AsyncCall(UvCallback callback, Args args, Result result) entry->getter_ = std::move(callback.getter_); entry->args_ = std::move(args); entry->result_ = std::move(result); - work->data = entry; - int ret = uv_queue_work(loop_, work, DoWork, DoUvCallback); - if (ret < 0) { - LOG_ERROR("uv_queue_work failed, errCode:%{public}d", ret); - delete entry; - delete work; + auto status = napi_send_event(env_, GenCallbackTask(entry), napi_eprio_immediate); + if (status != napi_ok) { + LOG_ERROR("Failed to SendEvent, status:%{public}d", status); } } @@ -95,30 +83,17 @@ void UvQueue::AsyncCallInOrder(UvCallback callback, Args args, Result result) void UvQueue::AsyncPromise(UvPromise promise, UvQueue::Args args) { - if (loop_ == nullptr || promise.IsNull()) { - LOG_ERROR("loop_ or promise is nullptr."); - return; - } - uv_work_t *work = new (std::nothrow) uv_work_t; - if (work == nullptr) { - LOG_ERROR("No memory for uv_work_t."); - return; - } - auto entry = new (std::nothrow) UvEntry(); - if (entry == nullptr) { - delete work; - LOG_ERROR("No memory for UvEntry."); + if (promise.IsNull()) { + LOG_ERROR("promise is nullptr."); return; } + auto entry = std::make_shared(); entry->env_ = env_; entry->defer_ = promise.defer_; entry->args_ = std::move(args); - work->data = entry; - int ret = uv_queue_work(loop_, work, DoWork, DoUvPromise); - if (ret < 0) { - LOG_ERROR("uv_queue_work failed, errCode:%{public}d", ret); - delete entry; - delete work; + auto status = napi_send_event(env_, GenPromiseTask(entry), napi_eprio_immediate); + if (status != napi_ok) { + LOG_ERROR("Failed to SendEvent, status:%{public}d", status); } } @@ -170,7 +145,7 @@ napi_value UvQueue::Future(napi_env env, napi_callback_info info, bool exception napi_value argv[ARGC_MAX] = { nullptr }; void *data = nullptr; auto status = napi_get_cb_info(env, info, &argc, argv, nullptr, &data); - if (status != napi_ok) { + if (status != napi_ok || data == nullptr) { return nullptr; } auto *entry = static_cast(data); @@ -181,45 +156,17 @@ napi_value UvQueue::Future(napi_env env, napi_callback_info info, bool exception return nullptr; } -void UvQueue::DoWork(uv_work_t *work) -{ -} - void UvQueue::DoExecute(uv_work_t *work) { + if (work == nullptr) { + return; + } Task *task = static_cast(work->data); work->data = nullptr; (*task)(); delete task; } -void UvQueue::DoUvCallback(uv_work_t *work, int status) -{ - std::shared_ptr entry(static_cast(work->data), [work](UvEntry *data) { - delete data; - delete work; - }); - - GenCallbackTask(entry)(); -} - -void UvQueue::DoUvPromise(uv_work_t *work, int status) -{ - std::shared_ptr entry(static_cast(work->data), [work](UvEntry *data) { - delete data; - delete work; - }); - - Scope scope(entry->env_); - napi_value argv[ARG_BUTT] = { nullptr }; - auto argc = entry->GetArgv(argv, ARG_BUTT); - if (argv[ARG_ERROR] != nullptr || argc != ARG_BUTT) { - napi_reject_deferred(entry->env_, entry->defer_, argv[ARG_ERROR]); - } else { - napi_resolve_deferred(entry->env_, entry->defer_, argv[ARG_DATA]); - } -} - UvQueue::Task UvQueue::GenCallbackTask(std::shared_ptr entry) { return [entry]() { @@ -247,6 +194,23 @@ UvQueue::Task UvQueue::GenCallbackTask(std::shared_ptr entry) }; } +UvQueue::Task UvQueue::GenPromiseTask(std::shared_ptr entry) +{ + return [entry]() { + if (entry == nullptr) { + return; + } + Scope scope(entry->env_); + napi_value argv[ARG_BUTT] = { nullptr }; + auto argc = entry->GetArgv(argv, ARG_BUTT); + if (argv[ARG_ERROR] != nullptr || argc != ARG_BUTT) { + napi_reject_deferred(entry->env_, entry->defer_, argv[ARG_ERROR]); + } else { + napi_resolve_deferred(entry->env_, entry->defer_, argv[ARG_DATA]); + } + }; +} + UvQueue::UvEntry::~UvEntry() { } @@ -315,8 +279,16 @@ void UvQueue::UvEntry::BindPromise(napi_value promise) auto object = StealResult(); napi_value argv[ARGC_MAX] = { nullptr }; - napi_create_function(env_, RESOLVED, RESOLVED_SIZE, Resolved, object, &argv[0]); - napi_create_function(env_, REJECTED, REJECTED_SIZE, Rejected, object, &argv[1]); + auto resolvedStatus = napi_create_function(env_, RESOLVED, RESOLVED_SIZE, Resolved, object, &argv[0]); + auto rejectedStatus = napi_create_function(env_, REJECTED, REJECTED_SIZE, Rejected, object, &argv[1]); + if (resolvedStatus != napi_ok || rejectedStatus != napi_ok) { + if (object) { + delete object; + } + LOG_ERROR("napi_create_function failed. resolvedStat:%{public}d, rejectedStat:%{public}d", resolvedStatus, + rejectedStatus); + return; + } napi_value result = nullptr; // Enter 2 parameters argv[0] and argv[1] status = napi_call_function(env_, promise, then, 2, argv, &result); @@ -330,7 +302,11 @@ UvQueue::Result *UvQueue::UvEntry::StealResult() if (!result_) { return nullptr; } - auto *result = new Result(); + auto *result = new (std::nothrow) Result(); + if (result == nullptr) { + LOG_ERROR("No memory for Result."); + return nullptr; + } *result = std::move(result_); return result; } diff --git a/relational_store/frameworks/js/napi/dataability/BUILD.gn b/relational_store/frameworks/js/napi/dataability/BUILD.gn index 4dc0670f..1259ccf0 100644 --- a/relational_store/frameworks/js/napi/dataability/BUILD.gn +++ b/relational_store/frameworks/js/napi/dataability/BUILD.gn @@ -45,6 +45,7 @@ ohos_shared_library("dataability") { external_deps = [ "hilog:libhilog", + "ipc:ipc_single", "napi:ace_napi", ] diff --git a/relational_store/frameworks/js/napi/dataability/include/napi_async_proxy.h b/relational_store/frameworks/js/napi/dataability/include/napi_async_proxy.h deleted file mode 100644 index b28d5168..00000000 --- a/relational_store/frameworks/js/napi/dataability/include/napi_async_proxy.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2021 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 PREFERENCES_JSKIT_NAPI_ASYNC_PROXY_H -#define PREFERENCES_JSKIT_NAPI_ASYNC_PROXY_H -#include - -#include "napi/native_api.h" -#include "napi/native_common.h" -#include "napi/native_node_api.h" -#include "securec.h" - -namespace OHOS { -namespace AppDataMgrJsKit { -constexpr int MAX_INPUT_COUNT = 10; -constexpr int OK = 0; -constexpr int ERR = -1; - -// T inherits AysncContext -template -class NapiAsyncProxy { -public: - constexpr static int RESULT_COUNT = 2; - using InputParser = void (*)(const napi_env &, const napi_value &, T *); - using NapiAsyncExecute = int (*)(T *); - using NapiAsyncComplete = int (*)(T *, napi_value &); - - // AsyncContext base - struct AysncContext { - AysncContext() - { - } - virtual ~AysncContext() - { - if (env == nullptr) { - return; - } - napi_delete_async_work(env, work); - napi_delete_reference(env, callbackRef); - } - napi_env env = nullptr; - napi_callback_info info = nullptr; - napi_async_work work = nullptr; - napi_deferred deferred = nullptr; - napi_ref callbackRef = nullptr; - NapiAsyncExecute execFunc = nullptr; - int execStatus = ERR; - NapiAsyncComplete completeFunc = nullptr; - void *boundObj = nullptr; - }; - -public: - void Init(napi_env env, napi_callback_info info) - { - asyncContext = new T(); - if (asyncContext == nullptr) { - return; - } - asyncContext->env = env; - asyncContext->info = info; - } - - ~NapiAsyncProxy() - { - if (asyncContext == nullptr) { - return; - } - - delete asyncContext; - asyncContext = nullptr; - } - - static void DefParserThis(const napi_env &env, const napi_value &self, T *context) - { - napi_unwrap(env, self, &context->boundObj); - } - - void ParseInputs(const std::vector &parsers, InputParser parserThis = DefParserThis) - { - if (asyncContext == nullptr) { - return; - } - - napi_value thisObj = nullptr; - size_t argc = parsers.size() + 1; - napi_value args[MAX_INPUT_COUNT] = { 0 }; - napi_get_cb_info(asyncContext->env, asyncContext->info, &argc, args, &thisObj, nullptr); - for (size_t i = 0; i < argc && argc <= MAX_INPUT_COUNT; i++) { - if (i >= parsers.size()) { - napi_valuetype valueType = napi_undefined; - napi_typeof(asyncContext->env, args[i], &valueType); - if (valueType == napi_function) { - napi_create_reference(asyncContext->env, args[i], 1, &asyncContext->callbackRef); - } - break; - } - auto *parserFunction = parsers[i]; - if (parserFunction != nullptr) { - parserFunction(asyncContext->env, args[i], this->asyncContext); - } - } - parserThis(asyncContext->env, thisObj, asyncContext); - } - - napi_value DoAsyncWork(std::string resourceName, NapiAsyncExecute execFunc, NapiAsyncComplete completeFunc) - { - if (asyncContext == nullptr) { - return nullptr; - } - - napi_value ret = nullptr; - if (asyncContext->callbackRef == nullptr) { - napi_create_promise(asyncContext->env, &asyncContext->deferred, &ret); - } else { - napi_get_undefined(asyncContext->env, &ret); - } - - napi_value resource = nullptr; - napi_create_string_utf8(asyncContext->env, resourceName.c_str(), NAPI_AUTO_LENGTH, &resource); - asyncContext->execFunc = execFunc; - asyncContext->completeFunc = completeFunc; - NAPI_CALL_BASE(asyncContext->env, napi_create_async_work(asyncContext->env, nullptr, resource, - [](napi_env env, void *data) { - T *context = (T *)data; - context->execStatus = context->execFunc(context); - }, - [](napi_env env, napi_status status, void *data) { - T *context = (T *)data; - napi_value output = nullptr; - int completeStatus = context->completeFunc(context, output); - napi_value result[RESULT_COUNT] = { 0 }; - if (context->execStatus == OK && completeStatus == OK) { - napi_get_undefined(env, &result[0]); - result[1] = output; - } else { - napi_value message = nullptr; - napi_create_string_utf8(env, "async call failed", NAPI_AUTO_LENGTH, &message); - napi_create_error(env, nullptr, message, &result[0]); - napi_get_undefined(env, &result[1]); - } - if (context->deferred) { - // promise - if (context->execStatus == OK && completeStatus == OK) { - napi_resolve_deferred(env, context->deferred, result[1]); - } else { - napi_reject_deferred(env, context->deferred, result[0]); - } - } else { - // callback - napi_value callback = nullptr; - napi_get_reference_value(env, context->callbackRef, &callback); - napi_value callbackResult = nullptr; - napi_call_function(env, nullptr, callback, RESULT_COUNT, result, &callbackResult); - } - delete context; - }, - (void *)asyncContext, &asyncContext->work), ret); - NAPI_CALL_BASE(asyncContext->env, napi_queue_async_work(asyncContext->env, asyncContext->work), ret); - return ret; - } - -private: - T *asyncContext; -}; -} // namespace AppDataMgrJsKit -} // namespace OHOS -#endif diff --git a/relational_store/frameworks/js/napi/dataability/include/napi_data_ability_predicates.h b/relational_store/frameworks/js/napi/dataability/include/napi_data_ability_predicates.h index cbe35b56..43981161 100644 --- a/relational_store/frameworks/js/napi/dataability/include/napi_data_ability_predicates.h +++ b/relational_store/frameworks/js/napi/dataability/include/napi_data_ability_predicates.h @@ -90,8 +90,9 @@ private: } // namespace OHOS EXTERN_C_START -__attribute__((visibility("default"))) napi_value NAPI_OHOS_Data_DataAbilityJsKit_DataAbilityPredicatesProxy_NewInstance( - napi_env env, OHOS::NativeRdb::DataAbilityPredicates *predicates); +__attribute__((visibility("default"))) + napi_value NAPI_OHOS_Data_DataAbilityJsKit_DataAbilityPredicatesProxy_NewInstance( + napi_env env, OHOS::NativeRdb::DataAbilityPredicates *predicates); __attribute__((visibility("default"))) OHOS::NativeRdb::DataAbilityPredicates * NAPI_OHOS_Data_DataAbilityJsKit_DataAbilityPredicatesProxy_GetNativeObject(const napi_env env, const napi_value arg); diff --git a/relational_store/frameworks/js/napi/dataability/src/napi_data_ability_predicates.cpp b/relational_store/frameworks/js/napi/dataability/src/napi_data_ability_predicates.cpp index 9b505673..ea5dd04c 100644 --- a/relational_store/frameworks/js/napi/dataability/src/napi_data_ability_predicates.cpp +++ b/relational_store/frameworks/js/napi/dataability/src/napi_data_ability_predicates.cpp @@ -12,13 +12,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #define LOG_TAG "DataAbilityPredicatesProxy" #include "napi_data_ability_predicates.h" #include "js_df_manager.h" #include "js_utils.h" #include "logger.h" -#include "napi_async_proxy.h" #include "napi_predicates_utils.h" using namespace OHOS::Rdb; @@ -137,7 +137,7 @@ napi_value DataAbilityPredicatesProxy::NewInstance( DataAbilityPredicatesProxy *proxy = nullptr; status = napi_unwrap(env, instance, reinterpret_cast(&proxy)); - if (status != napi_ok) { + if (status != napi_ok || proxy == nullptr) { LOG_ERROR("DataAbilityPredicatesProxy native instance is nullptr! napi_status:%{public}d!", status); return instance; } @@ -168,6 +168,9 @@ void DataAbilityPredicatesProxy::Destructor(napi_env env, void *nativeObject, vo LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(nativeObject) & LOWER_24_BITS_MASK); } DataAbilityPredicatesProxy *proxy = static_cast(nativeObject); + if (proxy == nullptr) { + return; + } proxy->predicates_ = std::move(nullptr); delete proxy; } @@ -176,8 +179,9 @@ DataAbilityPredicatesProxy::~DataAbilityPredicatesProxy() { } -DataAbilityPredicatesProxy::DataAbilityPredicatesProxy() : predicates_(new DataAbilityPredicates()) +DataAbilityPredicatesProxy::DataAbilityPredicatesProxy() { + predicates_ = std::make_shared(); } std::shared_ptr DataAbilityPredicatesProxy::GetNativePredicates( @@ -805,8 +809,9 @@ napi_value DataAbilityPredicatesProxy::IsSorted(napi_env env, napi_callback_info } // namespace OHOS EXTERN_C_START -__attribute__((visibility("default"))) napi_value NAPI_OHOS_Data_DataAbilityJsKit_DataAbilityPredicatesProxy_NewInstance( - napi_env env, OHOS::NativeRdb::DataAbilityPredicates *predicates) +__attribute__((visibility("default"))) + napi_value NAPI_OHOS_Data_DataAbilityJsKit_DataAbilityPredicatesProxy_NewInstance( + napi_env env, OHOS::NativeRdb::DataAbilityPredicates *predicates) { return OHOS::DataAbilityJsKit::DataAbilityPredicatesProxy::NewInstance( env, std::shared_ptr(predicates)); diff --git a/relational_store/frameworks/js/napi/dataability/src/napi_predicates_utils.cpp b/relational_store/frameworks/js/napi/dataability/src/napi_predicates_utils.cpp index 1a3f4fae..d51c35dd 100644 --- a/relational_store/frameworks/js/napi/dataability/src/napi_predicates_utils.cpp +++ b/relational_store/frameworks/js/napi/dataability/src/napi_predicates_utils.cpp @@ -45,9 +45,11 @@ napi_value CreateRdbPredicates(napi_env env, napi_callback_info info) NAPI_ASSERT(env, valueType == napi_object, "Table name should be an object."); DataAbilityPredicatesProxy *dataAbilityPredicatesProxy = nullptr; NAPI_CALL(env, napi_unwrap(env, args[1], reinterpret_cast(&dataAbilityPredicatesProxy))); - + NAPI_ASSERT(env, dataAbilityPredicatesProxy != nullptr, "napi_unwrap failed."); auto absPredicates = dataAbilityPredicatesProxy->GetPredicates(); - auto predicates = new NativeRdb::RdbPredicates(tableName); + NAPI_ASSERT(env, absPredicates != nullptr, "absPredicates is nullptr."); + auto predicates = new (std::nothrow) NativeRdb::RdbPredicates(tableName); + NAPI_ASSERT(env, predicates != nullptr, "No memory for RdbPredicates."); NativeRdb::PredicatesUtils::SetWhereClauseAndArgs( predicates, absPredicates->GetWhereClause(), absPredicates->GetBindArgs()); NativeRdb::PredicatesUtils::SetAttributes(predicates, absPredicates->IsDistinct(), absPredicates->GetIndex(), diff --git a/relational_store/frameworks/js/napi/graphstore/include/gdb_common.h b/relational_store/frameworks/js/napi/graphstore/include/gdb_common.h deleted file mode 100644 index 3ba24093..00000000 --- a/relational_store/frameworks/js/napi/graphstore/include/gdb_common.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_COMMON_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_COMMON_H -#include - -namespace OHOS::GraphStoreJsKit { -enum ColumnType : uint32_t { - - /** - * GRAPH_DB_DATATYPE_LONG: means the column type of the specified column is long. - * - * @syscap - * @since 16 - */ - GRAPH_DB_DATATYPE_LONG = 0, - - /** - * GRAPH_DB_DATATYPE_DOUBLE: means the column type of the specified column is double. - * - * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core - * @since 16 - */ - GRAPH_DB_DATATYPE_DOUBLE, - - /** - * GRAPH_DB_DATATYPE_STRING: means the column type of the specified column is string. - * - * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core - * @since 16 - */ - GRAPH_DB_DATATYPE_STRING, - - /** - * GRAPH_DB_DATATYPE_JSONSTR: means the column type of the specified column is string with json format. - * - * @syscap SystemCapability.DistributedDataManager.DataIntelligence.Core - * @since 16 - */ - GRAPH_DB_DATATYPE_JSONSTR, - - GRAPH_DB_DATATYPE_NULL, -}; -} - -#endif \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/include/js_proxy.h b/relational_store/frameworks/js/napi/graphstore/include/js_proxy.h deleted file mode 100644 index 9bbf5b85..00000000 --- a/relational_store/frameworks/js/napi/graphstore/include/js_proxy.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -* 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 OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_JS_PROXY_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_JS_PROXY_H -#include -namespace OHOS::GraphStoreJsKit { -template -class JSCreator { -public: - // This method will be used to call different subclasses for implementation - virtual std::shared_ptr Create() = 0; - -protected: - // It is not allowed to directly use parent class objects for construction and destruction - JSCreator() = default; - ~JSCreator() = default; -}; - -template -class JSProxy { -public: - void SetInstance(std::shared_ptr instance) - { - instance_ = std::move(instance); - } - - std::shared_ptr GetInstance() const - { - return instance_; - } - -protected: - // It is not allowed to directly use parent class objects for construction and destruction - JSProxy() = default; - ~JSProxy() = default; - -private: - std::shared_ptr instance_; -}; - -template -class JSEntity : public JSCreator, public JSProxy { -protected: - // It is not allowed to directly use parent class objects for construction and destruction - JSEntity() = default; - ~JSEntity() = default; -}; -} // namespace OHOS::JSProxy -#endif // OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_JS_PROXY_H diff --git a/relational_store/frameworks/js/napi/graphstore/include/napi_async_call.h b/relational_store/frameworks/js/napi/graphstore/include/napi_async_call.h deleted file mode 100644 index 160200e6..00000000 --- a/relational_store/frameworks/js/napi/graphstore/include/napi_async_call.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_ASYNC_CALL_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_ASYNC_CALL_H - -#include -#include -#include -#include -#include - -#include "gdb_errors.h" -#include "logger.h" -#include "napi/native_api.h" -#include "napi/native_common.h" -#include "napi/native_node_api.h" -#include "napi_gdb_error.h" - -namespace OHOS::GraphStoreJsKit { -using InputAction = std::function; -using OutputAction = std::function; -using ExecuteAction = std::function; -extern bool g_async; -extern bool g_sync; -#define AIP_ASYNC &g_async -#define AIP_SYNC &g_sync - -#define ASYNC_CALL(env, ctx) AsyncCall::Call(env, ctx, __FUNCTION__) -class ContextBase { -public: - struct RecordData { - std::atomic_uint64_t times_{0}; - int64_t lastTime_ = 0; - RecordData() = default; - RecordData(const RecordData &record) - { - times_.store(record.times_); - lastTime_ = record.lastTime_; - } - RecordData& operator= (const RecordData &record) - { - times_.store(record.times_); - lastTime_ = record.lastTime_; - return *this; - } - }; - void SetAction(napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output); - void SetAll(napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output); - void SetError(std::shared_ptr error); - virtual ~ContextBase(); - - napi_env env_ = nullptr; - bool isAsync_ = true; - void *boundObj = nullptr; - std::shared_ptr error; - std::shared_ptr executed_; - const char *fun = nullptr; - - napi_ref self_ = nullptr; - napi_ref callback_ = nullptr; - napi_deferred defer_ = nullptr; - napi_async_work work_ = nullptr; - - int execCode_ = OK; - OutputAction output_ = nullptr; - ExecuteAction exec_ = nullptr; - napi_value result_ = nullptr; - std::shared_ptr keep_; -}; - -class AsyncCall final { -public: - static napi_value Call(napi_env env, std::shared_ptr context, const char *fun); - -private: - enum { ARG_ERROR, ARG_DATA, ARG_BUTT }; - using RecordData = ContextBase::RecordData; - struct Record { - public: - RecordData total_; - RecordData completed_; - uint64_t reportTimes_ = 0; - std::shared_ptr executed_ = std::make_shared(); - }; - static constexpr uint64_t EXCEPT_DELTA = 20; - static void OnExecute(napi_env env, void *data); - static void OnComplete(napi_env env, void *data); - static void OnReturn(napi_env env, napi_status status, void *data); - static void OnComplete(napi_env env, napi_status status, void *data); - static void SetBusinessError(napi_env env, std::shared_ptr error, napi_value *businessError); - static napi_value Async(napi_env env, std::shared_ptr context); - static napi_value Sync(napi_env env, std::shared_ptr context); - static thread_local Record record_; -}; -} // namespace OHOS::GraphStoreJsKit -#endif \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_context.h b/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_context.h deleted file mode 100644 index cd39f8a2..00000000 --- a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_context.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -* 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 OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_CONTEXT_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_CONTEXT_H - -#include "full_result.h" -#include "gdb_store.h" -#include "gdb_store_config.h" -#include "napi_async_call.h" - -namespace OHOS { -namespace GraphStoreJsKit { -using namespace OHOS::DistributedDataAip; -struct GdbStoreContextBase : public ContextBase { - std::shared_ptr StealGdbStore() - { - auto gdb = std::move(gdbStore); - gdbStore = nullptr; - return gdb; - } - std::shared_ptr gdbStore = nullptr; -}; - -struct ContextParam { - std::string bundleName; - std::string moduleName; - std::string baseDir; - int32_t area = 2; - bool isSystemApp = false; - bool isStageMode = true; -}; - -struct GdbStoreContext : public GdbStoreContextBase { - std::string device; - std::string gql; - std::vector columns; - int64_t int64Output; - int intOutput; - ContextParam param; - StoreConfig config; - std::shared_ptr result; - std::vector keys; - std::string key; - std::string aliasName; - std::string pathName; - std::string srcName; - std::string columnName; - int32_t enumArg; - uint64_t cursor = UINT64_MAX; - int64_t txId = 0; - napi_ref asyncHolder = nullptr; - bool isQueryGql = false; - uint32_t expiredTime = 0; - - GdbStoreContext() : int64Output(0), intOutput(0), enumArg(-1) - { - } - virtual ~GdbStoreContext() - { - } -}; - -struct CreateTransactionContext : public GdbStoreContextBase { - std::shared_ptr transaction; -}; -} // namespace GraphStoreJsKit -} // namespace OHOS -#endif \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_error.h b/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_error.h deleted file mode 100644 index 82c1fe92..00000000 --- a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_error.h +++ /dev/null @@ -1,179 +0,0 @@ -/* -* 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 OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_ERROR_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_ERROR_H - -#include -#include -#include -#include - -#include "logger.h" - -namespace OHOS::GraphStoreJsKit { -constexpr int MAX_INPUT_COUNT = 10; -constexpr int OK = 0; -constexpr int ERR = -1; - -constexpr int E_NON_SYSTEM_APP_ERROR = 202; -constexpr int E_PARAM_ERROR = 401; -constexpr int E_INNER_ERROR = 31300000; - -struct JsErrorCode { - int32_t status; - int32_t jsCode; - std::string_view message; -}; -std::optional GetJsErrorCode(int32_t errorCode); - -#define GDB_REVT_NOTHING -#define GDB_DO_NOTHING - -#define GDB_NAPI_ASSERT_BASE(env, assertion, error, retVal) \ - do { \ - if (!(assertion)) { \ - if ((error) == nullptr) { \ - LOG_ERROR("throw error: error message is empty"); \ - napi_throw_error((env), nullptr, "error message is empty"); \ - return retVal; \ - } \ - LOG_ERROR("throw error: code = %{public}d , message = %{public}s", (error)->GetCode(), \ - (error)->GetMessage().c_str()); \ - napi_throw_error((env), std::to_string((error)->GetCode()).c_str(), (error)->GetMessage().c_str()); \ - return retVal; \ - } \ - } while (0) - -#define GDB_NAPI_ASSERT(env, assertion, error) GDB_NAPI_ASSERT_BASE(env, assertion, error, nullptr) - -#define CHECK_RETURN_CORE(assertion, theCall, revt) \ - do { \ - if (!(assertion)) { \ - theCall; \ - return revt; \ - } \ - } while (0) - -#define CHECK_RETURN_SET_E(assertion, paramError) \ - CHECK_RETURN_CORE(assertion, context->SetError(paramError), GDB_REVT_NOTHING) - -#define CHECK_RETURN_SET(assertion, paramError) CHECK_RETURN_CORE(assertion, context->SetError(paramError), ERR) - -#define CHECK_RETURN_NULL(assertion) CHECK_RETURN_CORE(assertion, GDB_REVT_NOTHING, nullptr) - -#define CHECK_RETURN_ERR(assertion) CHECK_RETURN_CORE(assertion, GDB_REVT_NOTHING, ERR) - -#define CHECK_RETURN(assertion) CHECK_RETURN_CORE(assertion, GDB_REVT_NOTHING, GDB_REVT_NOTHING) - -class Error { -public: - virtual ~Error() = default; - virtual std::string GetMessage() = 0; - virtual int GetCode() = 0; -}; - -class InnerError : public Error { -public: - explicit InnerError(int code) - { - auto errorMsg = GetJsErrorCode(code); - if (errorMsg.has_value()) { - const auto &napiError = errorMsg.value(); - code_ = napiError.jsCode; - msg_ = napiError.message; - } else { - code_ = E_INNER_ERROR; - msg_ = "Inner error. Inner code is " + std::to_string(code % E_INNER_ERROR); - } - } - - explicit InnerError(const std::string &msg) - { - code_ = E_INNER_ERROR; - msg_ = std::string("Inner error. ") + msg; - } - - std::string GetMessage() override - { - return msg_; - } - - int GetCode() override - { - return code_; - } - -private: - int code_; - std::string msg_; -}; - -class ParamError : public Error { -public: - ParamError(const std::string &needed, const std::string &mustbe) - { - msg_ = "Parameter error. The " + needed + " must be " + mustbe; - }; - - explicit ParamError(const std::string &errMsg) - { - msg_ = "Parameter error." + errMsg; - } - - std::string GetMessage() override - { - return msg_; - }; - - int GetCode() override - { - return E_PARAM_ERROR; - }; - -private: - std::string msg_; -}; - -class NonSystemError : public Error { -public: - NonSystemError() = default; - std::string GetMessage() override - { - return "Permission verification failed, application which is not a system application uses system API."; - } - int GetCode() override - { - return E_NON_SYSTEM_APP_ERROR; - } -}; - -class ParamNumError : public Error { -public: - explicit ParamNumError(std::string wantNum) : wantNum(std::move(wantNum)) {}; - std::string GetMessage() override - { - return "Parameter error. Need " + wantNum + " parameter(s)!"; - }; - int GetCode() override - { - return E_PARAM_ERROR; - }; - -private: - std::string wantNum; -}; -} // namespace OHOS::GraphStoreJsKit - -#endif // GDB_JS_NAPI_ERROR_H \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_js_utils.h b/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_js_utils.h deleted file mode 100644 index db292630..00000000 --- a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_js_utils.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_JS_UTILS_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_JS_UTILS_H -#include "full_result.h" -#include "gdb_store_config.h" -#include "js_utils.h" -#include "logger.h" -#include "napi_gdb_context.h" - -namespace OHOS::AppDataMgrJsKit::JSUtils { -using namespace GraphStoreJsKit; -using StoreConfig = DistributedDataAip::StoreConfig; -using Vertex = OHOS::DistributedDataAip::Vertex; -using Edge = OHOS::DistributedDataAip::Edge; -using PathSegment = OHOS::DistributedDataAip::PathSegment; -using Path = OHOS::DistributedDataAip::Path; - -#define GRAPH_ASSERT(condition, message, retVal) \ - do { \ - if (!(condition)) { \ - LOG_ERROR("test (" #condition ") failed: " message); \ - return retVal; \ - } \ - } while (0) - -#define NAPI_CALL_RETURN_ERR(theCall, retVal) \ - do { \ - if ((theCall) != napi_ok) { \ - return retVal; \ - } \ - } while (0) - -#ifndef PATH_SPLIT -#define PATH_SPLIT '/' -#endif - -static inline OHOS::HiviewDFX::HiLogLabel LogLabel() -{ - return { LOG_CORE, 0xD001660, "GdbJSUtils" }; -} - -template<> -int32_t Convert2Value(napi_env env, napi_value jsValue, ContextParam &context); - -template<> -int32_t Convert2Value(napi_env env, napi_value jsValue, StoreConfig &config); - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &result); - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &value); - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &edge); - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &pathSegment); - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &path); - -std::tuple> GetRealPath(StoreConfig &config, ContextParam ¶m); -} // namespace OHOS::AppDataMgrJsKit::JSUtils - -#endif \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_store.h b/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_store.h deleted file mode 100644 index 24ee51a9..00000000 --- a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_store.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -* 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 OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_STORE_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_STORE_H - -#include -#include -#include -#include - -#include "gdb_store.h" -#include "js_proxy.h" -#include "js_uv_queue.h" -#include "napi/native_api.h" -#include "napi/native_common.h" -#include "napi/native_node_api.h" - -namespace OHOS::GraphStoreJsKit { -using namespace DistributedDataAip; -#define ASSERT_CALL(env, theCall, object) \ - do { \ - if ((theCall) != napi_ok) { \ - delete (object); \ - GET_AND_THROW_LAST_ERROR((env)); \ - return nullptr; \ - } \ - } while (0) - -using Descriptor = std::function(void)>; -class GdbStoreProxy : public GraphStoreJsKit::JSProxy { -public: - static void Init(napi_env env, napi_value exports); - static napi_value NewInstance(napi_env env, std::shared_ptr value, bool isSystemAppCalled); - GdbStoreProxy(); - ~GdbStoreProxy(); - GdbStoreProxy(std::shared_ptr gdbStore); - GdbStoreProxy &operator=(std::shared_ptr GdbStore); - bool IsSystemAppCalled(); - static constexpr int32_t MAX_GQL_LEN = 1024 * 1024; - -private: - static napi_value Initialize(napi_env env, napi_callback_info info); - static napi_value Read(napi_env env, napi_callback_info info); - static napi_value Write(napi_env env, napi_callback_info info); - static napi_value CreateTransaction(napi_env env, napi_callback_info info); - static napi_value Close(napi_env env, napi_callback_info info); - - static Descriptor GetDescriptors(); - - static napi_value New(napi_env env, napi_callback_info info); - static void Destructor(napi_env env, void *nativeObject, void *finalize_hint); - - bool isSystemAppCalled_ = false; - std::shared_ptr queue_; -}; -} // namespace OHOS::GraphStoreJsKit -#endif \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/src/napi_async_call.cpp b/relational_store/frameworks/js/napi/graphstore/src/napi_async_call.cpp deleted file mode 100644 index 9b045ae8..00000000 --- a/relational_store/frameworks/js/napi/graphstore/src/napi_async_call.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "GdbAsyncCall" -#include "napi_async_call.h" - -#include "db_trace.h" -#include "js_native_api_types.h" -#include "logger.h" - -namespace OHOS::GraphStoreJsKit { -bool g_async = true; // do not reset the value, used in DECLARE_NAPI_FUNCTION_WITH_DATA only -bool g_sync = false; // do not reset the value, used in DECLARE_NAPI_FUNCTION_WITH_DATA only -thread_local AsyncCall::Record AsyncCall::record_; -void ContextBase::SetAction( - napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output) -{ - env_ = env; - size_t argc = MAX_INPUT_COUNT; - napi_value self = nullptr; - napi_value argv[MAX_INPUT_COUNT] = { nullptr }; - void *data = nullptr; - napi_status status = napi_get_cb_info(env, info, &argc, argv, &self, &data); - if (status == napi_ok && argc > 0) { - napi_valuetype valueType = napi_undefined; - status = napi_typeof(env, argv[argc - 1], &valueType); - if (status == napi_ok && valueType == napi_function) { - LOG_DEBUG("asyncCall set callback"); - if (argc == 1) { - error = std::make_shared("1"); - } else { - status = napi_create_reference(env, argv[argc - 1], 1, &callback_); - argc = argc - 1; - } - } - } - if (data) { - isAsync_ = *reinterpret_cast(data); - } - - // int -->input_(env, argc, argv, self) - if (status == napi_ok) { - input(env, argc, argv, self); - } else { - error = std::make_shared("Failed to set action."); - } - - // if input return is not ok, then napi_throw_error context error - GDB_NAPI_ASSERT_BASE(env, error == nullptr, error, NAPI_RETVAL_NOTHING); - output_ = std::move(output); - exec_ = std::move(exec); - napi_create_reference(env, self, 1, &self_); -} - -void ContextBase::SetAll( - napi_env env, napi_callback_info info, InputAction input, ExecuteAction exec, OutputAction output) -{ - env_ = env; - size_t argc = MAX_INPUT_COUNT; - napi_value self = nullptr; - napi_value argv[MAX_INPUT_COUNT] = { nullptr }; - NAPI_CALL_RETURN_VOID(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); - - // int -->input_(env, argc, argv, self) - input(env, argc, argv, self); - - // if input return is not ok, then napi_throw_error context error - GDB_NAPI_ASSERT_BASE(env, error == nullptr, error, NAPI_RETVAL_NOTHING); - output_ = std::move(output); - exec_ = std::move(exec); - napi_create_reference(env, self, 1, &self_); -} - -void ContextBase::SetError(std::shared_ptr err) -{ - error = err; -} - -ContextBase::~ContextBase() -{ - if (env_ == nullptr) { - return; - } - if (work_ != nullptr) { - napi_delete_async_work(env_, work_); - work_ = nullptr; - } - if (callback_ != nullptr) { - napi_delete_reference(env_, callback_); - callback_ = nullptr; - } - napi_delete_reference(env_, self_); - env_ = nullptr; -} - -void AsyncCall::SetBusinessError(napi_env env, std::shared_ptr error, napi_value *businessError) -{ - LOG_DEBUG("SetBusinessError enter"); - // if error is not inner error - if (error != nullptr) { - napi_value code = nullptr; - napi_value msg = nullptr; - napi_create_int32(env, error->GetCode(), &code); - napi_create_string_utf8(env, error->GetMessage().c_str(), NAPI_AUTO_LENGTH, &msg); - napi_create_error(env, code, msg, businessError); - } -} - -napi_value AsyncCall::Call(napi_env env, std::shared_ptr context, const char *fun) -{ - record_.total_.times_++; - record_.total_.lastTime_ = - std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) - .count(); - context->executed_ = record_.executed_; - context->fun = (fun == nullptr || fun[0] == '\0') ? "RelationalStoreAsyncCall" : fun; - return context->isAsync_ ? Async(env, context) : Sync(env, context); -} - -napi_value AsyncCall::Async(napi_env env, std::shared_ptr context) -{ - napi_value promise = nullptr; - if (context->callback_ == nullptr) { - napi_status status = napi_create_promise(env, &context->defer_, &promise); - GDB_NAPI_ASSERT_BASE(env, status == napi_ok, - std::make_shared("failed(" + std::to_string(status) + ") to create promise"), nullptr); - } else { - napi_get_undefined(env, &promise); - } - context->keep_ = context; - napi_value resource = nullptr; - napi_create_string_utf8(env, context->fun, NAPI_AUTO_LENGTH, &resource); - // create async work, execute function is OnExecute, complete function is OnComplete - napi_create_async_work(env, nullptr, resource, AsyncCall::OnExecute, AsyncCall::OnComplete, - reinterpret_cast(context.get()), &context->work_); - // add async work to execute queue - auto status = napi_queue_async_work_with_qos(env, context->work_, napi_qos_user_initiated); - if (status != napi_ok) { - napi_get_undefined(env, &promise); - } - auto report = (record_.total_.times_.load() - record_.completed_.times_.load()) / EXCEPT_DELTA; - if (report > record_.reportTimes_ && record_.executed_ != nullptr) { - LOG_WARN("Warning:Times:(C:%{public}" PRId64 ", E:%{public}" PRId64 ", F:%{public}" PRId64 ") Last time(" - "C:%{public}" PRId64 ", E:%{public}" PRId64 ", F:%{public}" PRId64 ")", - record_.total_.times_.load(), record_.executed_->times_.load(), record_.completed_.times_.load(), - record_.total_.lastTime_, record_.executed_->lastTime_, record_.completed_.lastTime_); - } - record_.reportTimes_ = report; - return promise; -} - -napi_value AsyncCall::Sync(napi_env env, std::shared_ptr context) -{ - OnExecute(env, reinterpret_cast(context.get())); - OnComplete(env, reinterpret_cast(context.get())); - if (context->execCode_ != DistributedDataAip::E_OK) { - napi_value error; - SetBusinessError(env, context->error, &error); - napi_throw(env, error); - } - return context->result_; -} - -void AsyncCall::OnExecute(napi_env env, void *data) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - ContextBase *context = reinterpret_cast(data); - if (context->executed_ != nullptr) { - context->executed_->times_++; - context->executed_->lastTime_ = - std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) - .count(); - } - if (context->error == nullptr && context->exec_) { - context->execCode_ = context->exec_(); - } - context->exec_ = nullptr; -} - -void AsyncCall::OnComplete(napi_env env, void *data) -{ - ContextBase *context = reinterpret_cast(data); - if (context->execCode_ != DistributedDataAip::E_OK) { - context->SetError(std::make_shared(context->execCode_)); - } - // if async execute status is not napi_ok then un-execute out function - if ((context->error == nullptr) && context->output_) { - context->output_(env, context->result_); - } - context->output_ = nullptr; - record_.completed_.times_++; - record_.completed_.lastTime_ = - std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) - .count(); -} - -void AsyncCall::OnComplete(napi_env env, napi_status status, void *data) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - OnComplete(env, data); - OnReturn(env, status, data); -} - -void AsyncCall::OnReturn(napi_env env, napi_status status, void *data) -{ - ContextBase *context = reinterpret_cast(data); - napi_value result[ARG_BUTT] = { 0 }; - // if out function status is ok then async renturn output data, else return error. - if (context->error == nullptr) { - napi_get_undefined(env, &result[ARG_ERROR]); - if (context->result_ != nullptr) { - result[ARG_DATA] = context->result_; - } else { - napi_get_undefined(env, &result[ARG_DATA]); - } - } else { - SetBusinessError(env, context->error, &result[ARG_ERROR]); - napi_get_undefined(env, &result[ARG_DATA]); - } - if (context->defer_ != nullptr) { - // promise - if (status == napi_ok && (context->error == nullptr)) { - napi_resolve_deferred(env, context->defer_, result[ARG_DATA]); - } else { - napi_reject_deferred(env, context->defer_, result[ARG_ERROR]); - } - } else { - // callback - napi_value callback = nullptr; - napi_get_reference_value(env, context->callback_, &callback); - napi_value returnValue = nullptr; - napi_call_function(env, nullptr, callback, ARG_BUTT, result, &returnValue); - } - context->keep_.reset(); -} -} // namespace OHOS::GraphStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_const_properties.cpp b/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_const_properties.cpp deleted file mode 100644 index 124243c1..00000000 --- a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_const_properties.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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 "napi_gdb_const_properties.h" - -#include "gdb_common.h" -#include "gdb_store.h" -#include "js_utils.h" - -namespace OHOS::GraphStoreJsKit { -using namespace AppDataMgrJsKit; -using namespace DistributedDataAip; -#define SET_NAPI_PROPERTY(object, prop, value) \ - napi_set_named_property((env), (object), (prop), JSUtils::Convert2JSValue((env), (value))) - -static napi_value ExportSecurityLevel(napi_env env) -{ - napi_value securityLevel = nullptr; - napi_create_object(env, &securityLevel); - - SET_NAPI_PROPERTY(securityLevel, "S1", 1); - SET_NAPI_PROPERTY(securityLevel, "S2", 2); - SET_NAPI_PROPERTY(securityLevel, "S3", 3); - SET_NAPI_PROPERTY(securityLevel, "S4", 4); - - napi_object_freeze(env, securityLevel); - return securityLevel; -} - -napi_status InitConstProperties(napi_env env, napi_value exports) -{ - const napi_property_descriptor properties[] = { - DECLARE_NAPI_PROPERTY("SecurityLevel", ExportSecurityLevel(env)), - }; - - size_t count = sizeof(properties) / sizeof(properties[0]); - return napi_define_properties(env, exports, count, properties); -} -} // namespace OHOS::GraphStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_error.cpp b/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_error.cpp deleted file mode 100644 index 042c9c64..00000000 --- a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_error.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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 "napi_gdb_error.h" - -#include - -#include "gdb_errors.h" - -namespace OHOS::GraphStoreJsKit { -using namespace DistributedDataAip; -static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = { - { E_INVALID_ARGS, 401, "Parameter error." }, - { E_GRD_DATA_CORRUPTED, 31300001, "Database corrupted." }, - { E_GRD_DB_INSTANCE_ABNORMAL, 31300002, "Already closed." }, - { E_DATABASE_BUSY, 31300003, "The database is busy." }, - { E_GRD_FAILED_MEMORY_ALLOCATE, 31300004, "The database is out of memory." }, - { E_GRD_DISK_SPACE_FULL, 31300005, "The database is full." }, - { E_GRD_DUPLICATE_PARAM, 31300006, - "A duplicate graph name, vertex or edge type, or vertex or edge property name exists." }, - { E_GRD_UNDEFINED_PARAM, 31300007, - "The graph name, vertex or edge type, or vertex or edge property is not defined." }, - { E_GRD_INVALID_NAME, 31300008, - "The graph name, vertex or edge type, or vertex or edge property name does not conform to constraints." }, - { E_GRD_SYNTAX_ERROR, 31300009, "The GQL statement syntax error." }, - { E_GRD_SEMANTIC_ERROR, 31300010, "The GQL statement semantic error." }, - { E_GRD_OVER_LIMIT, 31300012, - "The number of graph names, vertex or edge types, or vertex or edge properties exceeds the limit." }, - { E_GRD_DATA_CONFLICT, 31300013, "A conflicting constraint already exists." }, - { E_DBPATH_ACCESS_FAILED, 31300014, "Invalid database path." }, - { E_CONFIG_INVALID_CHANGE, 31300015, "Config changed." }, -}; - -std::optional GetJsErrorCode(int32_t errorCode) -{ - auto jsErrorCode = JsErrorCode{ errorCode, -1, "" }; - auto iter = std::lower_bound(JS_ERROR_CODE_MSGS, - JS_ERROR_CODE_MSGS + sizeof(JS_ERROR_CODE_MSGS) / sizeof(JS_ERROR_CODE_MSGS[0]), jsErrorCode, - [](const JsErrorCode &jsErrorCode1, const JsErrorCode &jsErrorCode2) { - return jsErrorCode1.status < jsErrorCode2.status; - }); - if (iter < JS_ERROR_CODE_MSGS + sizeof(JS_ERROR_CODE_MSGS) / sizeof(JS_ERROR_CODE_MSGS[0]) && - iter->status == errorCode) { - return *iter; - } - return std::nullopt; -} -} // namespace OHOS::GraphStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_js_utils.cpp b/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_js_utils.cpp deleted file mode 100644 index 3034bc9c..00000000 --- a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_js_utils.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* -* 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. -*/ -#define LOG_TAG "GdbJSUtil" -#include "napi_gdb_js_utils.h" - -#include "gdb_utils.h" -#include "js_ability.h" -#include "securec.h" - -namespace OHOS::AppDataMgrJsKit::JSUtils { -constexpr int MAX_PATH_LENGTH = 1024; - -int32_t GetCurrentAbilityParam(napi_env env, napi_value jsValue, ContextParam ¶m) -{ - std::shared_ptr context = JSAbility::GetCurrentAbility(env, jsValue); - if (context == nullptr) { - return napi_invalid_arg; - } - param.baseDir = context->GetDatabaseDir(); - param.moduleName = context->GetModuleName(); - param.area = context->GetArea(); - param.bundleName = context->GetBundleName(); - param.isSystemApp = context->IsSystemAppCalled(); - return napi_ok; -} - -template<> -int32_t Convert2Value(napi_env env, napi_value jsValue, ContextParam ¶m) -{ - if (jsValue == nullptr) { - LOG_INFO("hasProp is false -> fa stage"); - param.isStageMode = false; - return GetCurrentAbilityParam(env, jsValue, param); - } - - int32_t status = GetNamedProperty(env, jsValue, "stageMode", param.isStageMode); - ASSERT(status == napi_ok, "get stageMode param failed", napi_invalid_arg); - if (!param.isStageMode) { - LOG_WARN("isStageMode is false -> fa stage"); - return GetCurrentAbilityParam(env, jsValue, param); - } - LOG_DEBUG("stage mode branch"); - status = GetNamedProperty(env, jsValue, "databaseDir", param.baseDir); - ASSERT(status == napi_ok, "get databaseDir failed.", napi_invalid_arg); - status = GetNamedProperty(env, jsValue, "area", param.area, true); - ASSERT(status == napi_ok, "get area failed.", napi_invalid_arg); - - napi_value hapInfo = nullptr; - GetNamedProperty(env, jsValue, "currentHapModuleInfo", hapInfo); - if (hapInfo != nullptr) { - status = GetNamedProperty(env, hapInfo, "name", param.moduleName); - ASSERT(status == napi_ok, "get currentHapModuleInfo.name failed.", napi_invalid_arg); - } - - napi_value appInfo = nullptr; - GetNamedProperty(env, jsValue, "applicationInfo", appInfo); - if (appInfo != nullptr) { - status = GetNamedProperty(env, appInfo, "name", param.bundleName); - ASSERT(status == napi_ok, "get applicationInfo.name failed.", napi_invalid_arg); - status = GetNamedProperty(env, appInfo, "systemApp", param.isSystemApp, true); - ASSERT(status == napi_ok, "get applicationInfo.systemApp failed.", napi_invalid_arg); - int32_t hapVersion = JSAbility::GetHapVersion(env, jsValue); - JSUtils::SetHapVersion(hapVersion); - } - return napi_ok; -} - -template<> -int32_t Convert2Value(napi_env env, napi_value jsValue, StoreConfig &config) -{ - std::string name; - auto status = GetNamedProperty(env, jsValue, "name", name); - ASSERT(OK == status, "get name failed.", napi_invalid_arg); - config.SetName(name); - - int32_t securityLevel; - status = GetNamedProperty(env, jsValue, "securityLevel", securityLevel); - ASSERT(OK == status, "get securityLevel failed.", napi_invalid_arg); - config.SetSecurityLevel(securityLevel); - - bool isEncrypt = false; - status = GetNamedProperty(env, jsValue, "encrypt", isEncrypt, true); - ASSERT(OK == status, "get encrypt failed.", napi_invalid_arg); - config.SetEncryptStatus(isEncrypt); - return napi_ok; -} - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &result) -{ - std::vector descriptors = { - DECLARE_JS_PROPERTY(env, "records", result->GetAllData()), - }; - - napi_value object = nullptr; - NAPI_CALL_RETURN_ERR( - napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); - return object; -} - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &vertex) -{ - std::vector descriptors = { - DECLARE_JS_PROPERTY(env, "vid", vertex->GetId()), - DECLARE_JS_PROPERTY(env, "labels", vertex->GetLabels()), - DECLARE_JS_PROPERTY(env, "properties", vertex->GetProperties()), - }; - - napi_value object = nullptr; - NAPI_CALL_RETURN_ERR( - napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); - return object; -} - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &edge) -{ - std::vector descriptors = { - DECLARE_JS_PROPERTY(env, "eid", edge->GetId()), - DECLARE_JS_PROPERTY(env, "type", edge->GetLabel()), - DECLARE_JS_PROPERTY(env, "startVid", edge->GetSourceId()), - DECLARE_JS_PROPERTY(env, "endVid", edge->GetTargetId()), - DECLARE_JS_PROPERTY(env, "properties", edge->GetProperties()), - }; - - napi_value object = nullptr; - NAPI_CALL_RETURN_ERR( - napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); - return object; -} - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &pathSegment) -{ - std::vector descriptors = { - DECLARE_JS_PROPERTY(env, "start", pathSegment->GetSourceVertex()), - DECLARE_JS_PROPERTY(env, "end", pathSegment->GetTargetVertex()), - DECLARE_JS_PROPERTY(env, "edge", pathSegment->GetEdge()), - }; - - napi_value object = nullptr; - NAPI_CALL_RETURN_ERR( - napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); - return object; -} - -template<> -napi_value Convert2JSValue(napi_env env, const std::shared_ptr &path) -{ - std::vector descriptors = { - DECLARE_JS_PROPERTY(env, "start", path->GetStart()), - DECLARE_JS_PROPERTY(env, "end", path->GetEnd()), - DECLARE_JS_PROPERTY(env, "length", path->GetPathLength()), - DECLARE_JS_PROPERTY(env, "segments", path->GetSegments()), - }; - - napi_value object = nullptr; - NAPI_CALL_RETURN_ERR( - napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); - return object; -} - -std::tuple> GetRealPath(StoreConfig &config, ContextParam ¶m) -{ - CHECK_RETURN_CORE(config.GetName().find(PATH_SPLIT) == std::string::npos, GDB_DO_NOTHING, - std::make_tuple(ERR, std::make_shared("StoreConfig.name", "a database name without path."))); - std::string databaseDir; - databaseDir.append(param.baseDir).append("/gdb"); - auto errorCode = DistributedDataAip::GdbUtils::CreateDirectory(databaseDir); - std::string realPath = databaseDir + "/" + config.GetName(); - CHECK_RETURN_CORE(errorCode == E_OK && realPath.length() <= MAX_PATH_LENGTH, GDB_DO_NOTHING, - std::make_tuple(ERR, std::make_shared("database path", "a valid path."))); - config.SetPath(databaseDir); - return std::make_tuple(E_OK, nullptr); -} -} \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_store.cpp b/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_store.cpp deleted file mode 100644 index 9a05f8c5..00000000 --- a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_store.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* -* 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. -*/ -#define LOG_TAG "GdbStoreProxy" -#include "napi_gdb_store.h" - -#include -#include -#include -#include - -#include "db_trace.h" -#include "js_utils.h" -#include "logger.h" -#include "napi_gdb_context.h" -#include "napi_gdb_error.h" -#include "napi_gdb_js_utils.h" -#include "napi_gdb_transaction.h" - -namespace OHOS::GraphStoreJsKit { - -GdbStoreProxy::GdbStoreProxy() -{ -} - -GdbStoreProxy::~GdbStoreProxy() -{ -} - -GdbStoreProxy::GdbStoreProxy(std::shared_ptr gdbStore) -{ - if (GetInstance() == gdbStore) { - return; - } - SetInstance(std::move(gdbStore)); -} - -GdbStoreProxy &GdbStoreProxy::operator=(std::shared_ptr gdbStore) -{ - if (GetInstance() == gdbStore) { - return *this; - } - SetInstance(std::move(gdbStore)); - return *this; -} - -bool GdbStoreProxy::IsSystemAppCalled() -{ - return isSystemAppCalled_; -} - -Descriptor GdbStoreProxy::GetDescriptors() -{ - return []() -> std::vector { - std::vector properties = { - DECLARE_NAPI_FUNCTION("read", Read), - DECLARE_NAPI_FUNCTION("write", Write), - DECLARE_NAPI_FUNCTION("createTransaction", CreateTransaction), - DECLARE_NAPI_FUNCTION("close", Close), - }; - return properties; - }; -} - -void GdbStoreProxy::Init(napi_env env, napi_value exports) -{ - auto jsCtor = OHOS::AppDataMgrJsKit::JSUtils::DefineClass( - env, "ohos.data.graphStore", "GraphStore", GetDescriptors(), Initialize); - NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, exports, "GraphStore", jsCtor)); -} - -void GdbStoreProxy::Destructor(napi_env env, void *nativeObject, void *finalize_hint) -{ - auto *obj = static_cast(nativeObject); - delete obj; -} - -napi_value GdbStoreProxy::New(napi_env env, napi_callback_info info) -{ - size_t argc = 1; - napi_value argv[1] = { 0 }; - napi_value thisVar = nullptr; - napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr); - - // get native object - auto *obj = new GdbStoreProxy(); - ASSERT_CALL(env, - napi_wrap(env, thisVar, obj, GdbStoreProxy::Destructor, - nullptr, // finalize_hint - nullptr), - obj); - return thisVar; -} - -napi_value GdbStoreProxy::Initialize(napi_env env, napi_callback_info info) -{ - napi_value self = nullptr; - NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &self, nullptr)); - auto finalize = [](napi_env env, void *data, void *hint) { - if (data != hint) { - LOG_ERROR("GdbStoreProxy memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, uintptr_t(data), - uintptr_t(hint)); - return; - } - GdbStoreProxy *proxy = reinterpret_cast(data); - proxy->SetInstance(nullptr); - delete proxy; - }; - auto *proxy = new (std::nothrow) GdbStoreProxy(); - if (proxy == nullptr) { - return nullptr; - } - napi_status status = napi_wrap(env, self, proxy, finalize, proxy, nullptr); - if (status != napi_ok) { - LOG_ERROR("GdbStoreProxy napi_wrap failed! code:%{public}d!", status); - finalize(env, proxy, proxy); - return nullptr; - } - return self; -} - -napi_value GdbStoreProxy::NewInstance(napi_env env, std::shared_ptr value, bool isSystemAppCalled) -{ - if (value == nullptr) { - LOG_ERROR("dbstore is nullptr"); - return nullptr; - } - napi_value cons = OHOS::AppDataMgrJsKit::JSUtils::GetClass(env, "ohos.data.graphStore", "GraphStore"); - if (cons == nullptr) { - LOG_ERROR("Constructor of ResultSet is nullptr!"); - return nullptr; - } - - napi_value instance = nullptr; - auto status = napi_new_instance(env, cons, 0, nullptr, &instance); - if (status != napi_ok) { - LOG_ERROR("GdbStoreProxy::NewInstance napi_new_instance failed! code:%{public}d!", status); - return nullptr; - } - - GdbStoreProxy *proxy = nullptr; - status = napi_unwrap(env, instance, reinterpret_cast(&proxy)); - if (proxy == nullptr) { - LOG_ERROR("GdbStoreProxy::NewInstance native instance is nullptr! code:%{public}d!", status); - return instance; - } - proxy->queue_ = std::make_shared(env); - proxy->SetInstance(std::move(value)); - proxy->isSystemAppCalled_ = isSystemAppCalled; - return instance; -} - -GdbStoreProxy *GetNativeInstance(napi_env env, napi_value self) -{ - GdbStoreProxy *proxy = nullptr; - napi_status status = napi_unwrap(env, self, reinterpret_cast(&proxy)); - if (proxy == nullptr) { - LOG_ERROR("GdbStoreProxy native instance is nullptr! code:%{public}d!", status); - return nullptr; - } - return proxy; -} - -int ParseThis(const napi_env &env, const napi_value &self, const std::shared_ptr &context) -{ - GdbStoreProxy *obj = GetNativeInstance(env, self); - CHECK_RETURN_SET(obj != nullptr, std::make_shared("GdbStore", "not nullptr.")); - CHECK_RETURN_SET(obj->GetInstance() != nullptr, std::make_shared(E_GRD_DB_INSTANCE_ABNORMAL)); - context->boundObj = obj; - context->gdbStore = obj->GetInstance(); - return OK; -} - -int ParseGql(const napi_env env, const napi_value arg, const std::shared_ptr &context) -{ - context->gql = OHOS::AppDataMgrJsKit::JSUtils::Convert2String(env, arg); - CHECK_RETURN_SET(!context->gql.empty(), std::make_shared("gql", "not empty")); - CHECK_RETURN_SET(context->gql.size() <= GdbStoreProxy::MAX_GQL_LEN, - std::make_shared("gql", "too long")); - return OK; -} - -napi_value GdbStoreProxy::Read(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(argc == 1, std::make_shared(" 1 ")); - CHECK_RETURN(OK == ParseThis(env, self, context)); - CHECK_RETURN(OK == ParseGql(env, argv[0], context)); - }; - auto exec = [context]() -> int { - CHECK_RETURN_ERR(context->gdbStore != nullptr); - auto queryResult = context->StealGdbStore()->QueryGql(context->gql); - context->result = queryResult.second; - context->intOutput = queryResult.first; - return OK; - }; - auto output = [context](napi_env env, napi_value &result) { - result = AppDataMgrJsKit::JSUtils::Convert2JSValue(env, context->result); - CHECK_RETURN_SET_E(context->intOutput == OK, std::make_shared(context->intOutput)); - }; - context->SetAction(env, info, input, exec, output); - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} - -napi_value GdbStoreProxy::Write(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(argc == 1, std::make_shared(" 1 ")); - CHECK_RETURN(OK == ParseThis(env, self, context)); - CHECK_RETURN(OK == ParseGql(env, argv[0], context)); - }; - auto exec = [context]() -> int { - CHECK_RETURN_ERR(context->gdbStore != nullptr); - auto executeResult = context->StealGdbStore()->ExecuteGql(context->gql); - context->result = executeResult.second; - context->intOutput = executeResult.first; - return OK; - }; - auto output = [context](napi_env env, napi_value &result) { - result = AppDataMgrJsKit::JSUtils::Convert2JSValue(env, context->result); - CHECK_RETURN_SET_E(context->intOutput == OK, std::make_shared(context->intOutput)); - }; - context->SetAction(env, info, input, exec, output); - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} - -napi_value GdbStoreProxy::CreateTransaction(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(argc == 0, std::make_shared(" 0 ")); - CHECK_RETURN(OK == ParseThis(env, self, context)); - }; - auto exec = [context]() -> int { - CHECK_RETURN_ERR(context->gdbStore != nullptr); - int32_t code = E_ERROR; - std::tie(code, context->transaction) = context->StealGdbStore()->CreateTransaction(); - if (code != E_OK) { - context->transaction = nullptr; - return code; - } - return context->transaction != nullptr ? OK : E_ERROR; - }; - auto output = [context](napi_env env, napi_value &result) { - result = GdbTransactionProxy::NewInstance(env, context->transaction); - CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_INNER_ERROR)); - }; - context->SetAction(env, info, input, exec, output); - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} - -napi_value GdbStoreProxy::Close(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - GdbStoreProxy *proxy = GetNativeInstance(env, self); - CHECK_RETURN_SET(proxy != nullptr, std::make_shared("GdbStore", "not nullptr.")); - if (proxy->GetInstance() == nullptr) { - LOG_WARN("GdbStoreProxy native instance is nullptr!"); - return OK; - } - context->boundObj = proxy; - context->gdbStore = proxy->GetInstance(); - - auto *obj = reinterpret_cast(context->boundObj); - obj->SetInstance(nullptr); - return OK; - }; - auto exec = [context]() -> int { - context->gdbStore = nullptr; - return OK; - }; - auto output = [context](napi_env env, napi_value &result) { - napi_status status = napi_get_undefined(env, &result); - CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); - }; - context->SetAction(env, info, input, exec, output); - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} -} // namespace OHOS::GraphStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_store_helper.cpp b/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_store_helper.cpp deleted file mode 100644 index 50f5df70..00000000 --- a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_store_helper.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* -* 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. -*/ -#define LOG_TAG "GdbStoreHelperProxy" -#include "napi_gdb_store_helper.h" - -#include - -#include "db_trace.h" -#include "gdb_helper.h" -#include "logger.h" -#include "napi_gdb_context.h" -#include "napi_gdb_js_utils.h" -#include "napi_gdb_store.h" - -namespace OHOS::GraphStoreJsKit { -using namespace OHOS::DistributedDataAip; - -static constexpr int MAX_GDB_DB_NAME_LENGTH = 128; - -bool IsValidDbName(const std::string &name) -{ - if (name.empty() || name.size() > MAX_GDB_DB_NAME_LENGTH) { - return false; - } - const std::regex pattern("^[a-zA-Z0-9_]+$"); - return std::regex_match(name, pattern); -} - -napi_value GetStore(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context, info](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(argc == 2, std::make_shared(" 2 ")); - int errCode = AppDataMgrJsKit::JSUtils::Convert2Value(env, argv[0], context->param); - CHECK_RETURN_SET_E(OK == errCode, std::make_shared("Illegal context.")); - CHECK_RETURN_SET_E(context->param.isSystemApp, std::make_shared()); - errCode = AppDataMgrJsKit::JSUtils::Convert2Value(env, argv[1], context->config); - CHECK_RETURN_SET_E(OK == errCode, std::make_shared("Illegal StoreConfig or name.")); - CHECK_RETURN_SET_E(IsValidDbName(context->config.GetName()), std::make_shared("Illegal name.")); - auto [code, err] = AppDataMgrJsKit::JSUtils::GetRealPath(context->config, context->param); - CHECK_RETURN_SET_E(OK == code, err); - context->config.SetBundleName(context->param.bundleName); - }; - auto exec = [context]() -> int { - context->gdbStore = GDBHelper::GetDBStore(context->config, context->intOutput); - return OK; - }; - auto output = [context](napi_env env, napi_value &result) { - CHECK_RETURN_SET_E(context->intOutput == OK, std::make_shared(context->intOutput)); - result = GdbStoreProxy::NewInstance(env, context->gdbStore, context->param.isSystemApp); - CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_INNER_ERROR)); - }; - context->SetAction(env, info, input, exec, output); - - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} - -napi_value DeleteStore(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context, info](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(argc == 2, std::make_shared(" 2 ")); - int errCode = AppDataMgrJsKit::JSUtils::Convert2Value(env, argv[0], context->param); - CHECK_RETURN_SET_E(OK == errCode, std::make_shared("Illegal context.")); - CHECK_RETURN_SET_E(context->param.isSystemApp, std::make_shared()); - errCode = AppDataMgrJsKit::JSUtils::Convert2Value(env, argv[1], context->config); - CHECK_RETURN_SET_E(OK == errCode, std::make_shared("Illegal StoreConfig or name.")); - CHECK_RETURN_SET_E(IsValidDbName(context->config.GetName()), std::make_shared("Illegal name.")); - auto [code, err] = AppDataMgrJsKit::JSUtils::GetRealPath(context->config, context->param); - CHECK_RETURN_SET_E(OK == code, err); - }; - auto exec = [context]() -> int { - context->intOutput = GDBHelper::DeleteDBStore(context->config); - return OK; - }; - auto output = [context](napi_env env, napi_value &result) { - CHECK_RETURN_SET_E(context->intOutput == OK, std::make_shared(context->intOutput)); - }; - context->SetAction(env, info, input, exec, output); - - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} - -napi_value InitGdbHelper(napi_env env, napi_value exports) -{ - napi_property_descriptor properties[] = { - DECLARE_NAPI_FUNCTION_WITH_DATA("getStore", GetStore, AIP_ASYNC), - DECLARE_NAPI_FUNCTION_WITH_DATA("deleteStore", DeleteStore, AIP_ASYNC), - }; - NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(*properties), properties)); - return exports; -} -} // namespace OHOS::GraphStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_transaction.cpp b/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_transaction.cpp deleted file mode 100644 index 00d55c10..00000000 --- a/relational_store/frameworks/js/napi/graphstore/src/napi_gdb_transaction.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* -* 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. -*/ -#define LOG_TAG "GdbTransactionProxy" -#include "napi_gdb_transaction.h" - -#include -#include -#include -#include - -#include "db_trace.h" -#include "js_utils.h" -#include "logger.h" -#include "napi_gdb_context.h" -#include "napi_gdb_error.h" -#include "napi_gdb_js_utils.h" - -namespace OHOS::GraphStoreJsKit { -#define ASSERT_RETURN_SET_ERROR(assertion, paramError) \ - CHECK_RETURN_CORE(assertion, SetError(paramError), ERR) - -constexpr int32_t MAX_GQL_LEN = 1024 * 1024; - -constexpr const char *SPACE_NAME = "ohos.data.graphStore"; -constexpr const char *CLASS_NAME = "Transaction"; - -struct TransactionContext : public ContextBase { - void GetInstance(napi_value self) - { - auto status = napi_unwrap(env_, self, reinterpret_cast(&boundObj)); - if (status != napi_ok || boundObj == nullptr) { - LOG_ERROR("GdbTransactionProxy native instance is nullptr! code:%{public}d!", status); - return; - } - transaction_ = reinterpret_cast(boundObj)->GetInstance(); - } - std::shared_ptr StealTransaction() - { - auto trans = std::move(transaction_); - transaction_ = nullptr; - return trans; - } - std::shared_ptr transaction_ = nullptr; -}; - -GdbTransactionProxy::~GdbTransactionProxy() -{ -} - -GdbTransactionProxy::GdbTransactionProxy(std::shared_ptr gdbTransaction) -{ - if (GetInstance() == gdbTransaction) { - return; - } - SetInstance(std::move(gdbTransaction)); -} - -napi_value GdbTransactionProxy::Initialize(napi_env env, napi_callback_info info) -{ - napi_value self = nullptr; - NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &self, nullptr)); - auto *proxy = new (std::nothrow) GdbTransactionProxy(); - if (proxy == nullptr) { - return nullptr; - } - auto finalize = [](napi_env env, void *data, void *hint) { - if (data != hint) { - LOG_ERROR("memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, - uintptr_t(data), uintptr_t(hint)); - return; - } - GdbTransactionProxy *proxy = reinterpret_cast(data); - proxy->SetInstance(nullptr); - delete proxy; - }; - napi_status status = napi_wrap(env, self, proxy, finalize, proxy, nullptr); - if (status != napi_ok) { - LOG_ERROR("napi_wrap failed! code:%{public}d!", status); - finalize(env, proxy, proxy); - return nullptr; - } - return self; -} - -void GdbTransactionProxy::Init(napi_env env, napi_value exports) -{ - auto lambda = []() -> std::vector { - std::vector properties = { - DECLARE_NAPI_FUNCTION("read", Read), - DECLARE_NAPI_FUNCTION("write", Write), - DECLARE_NAPI_FUNCTION("commit", Commit), - DECLARE_NAPI_FUNCTION("rollback", Rollback), - }; - return properties; - }; - auto jsCtor = AppDataMgrJsKit::JSUtils::DefineClass(env, SPACE_NAME, CLASS_NAME, lambda, Initialize); - NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, exports, CLASS_NAME, jsCtor)); -} - -napi_value GdbTransactionProxy::NewInstance(napi_env env, std::shared_ptr value) -{ - if (value == nullptr) { - LOG_ERROR("value is nullptr"); - return nullptr; - } - napi_value cons = AppDataMgrJsKit::JSUtils::GetClass(env, SPACE_NAME, CLASS_NAME); - if (cons == nullptr) { - LOG_ERROR("Constructor of Transaction is nullptr!"); - return nullptr; - } - - napi_value instance = nullptr; - auto status = napi_new_instance(env, cons, 0, nullptr, &instance); - if (status != napi_ok) { - LOG_ERROR("create new instance failed! code:%{public}d!", status); - return nullptr; - } - - GdbTransactionProxy *proxy = nullptr; - status = napi_unwrap(env, instance, reinterpret_cast(&proxy)); - if (status != napi_ok || proxy == nullptr) { - LOG_ERROR("native instance is nullptr! code:%{public}d!", status); - return instance; - } - proxy->SetInstance(std::move(value)); - return instance; -} - -struct ReadWriteContext : public TransactionContext { - int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self) - { - ASSERT_RETURN_SET_ERROR(argc == 1, std::make_shared(" 1 ")); - GetInstance(self); - ASSERT_RETURN_SET_ERROR(transaction_ != nullptr, std::make_shared("transaction", "not nullptr.")); - gql = AppDataMgrJsKit::JSUtils::Convert2String(env, argv[0]); - ASSERT_RETURN_SET_ERROR(!gql.empty(), std::make_shared("gql", "not empty")); - ASSERT_RETURN_SET_ERROR(gql.size() <= MAX_GQL_LEN, - std::make_shared("gql", "too long")); - return OK; - } - std::string gql; - std::shared_ptr result; - int32_t errCode; -}; - -napi_value GdbTransactionProxy::Read(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - context->Parse(env, argc, argv, self); - }; - auto exec = [context]() -> int { - CHECK_RETURN_ERR(context->transaction_ != nullptr); - std::tie(context->errCode, context->result) = context->StealTransaction()->Query(context->gql); - return context->errCode; - }; - auto output = [context](napi_env env, napi_value &result) { - result = AppDataMgrJsKit::JSUtils::Convert2JSValue(env, context->result); - CHECK_RETURN_SET_E(context->errCode == OK, std::make_shared(context->errCode)); - }; - context->SetAction(env, info, input, exec, output); - - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} - -napi_value GdbTransactionProxy::Write(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - context->Parse(env, argc, argv, self); - }; - auto exec = [context]() -> int { - CHECK_RETURN_ERR(context->transaction_ != nullptr); - std::tie(context->errCode, context->result) = context->StealTransaction()->Execute(context->gql); - return context->errCode; - }; - auto output = [context](napi_env env, napi_value &result) { - result = AppDataMgrJsKit::JSUtils::Convert2JSValue(env, context->result); - CHECK_RETURN_SET_E(context->errCode == OK, std::make_shared(context->errCode)); - }; - context->SetAction(env, info, input, exec, output); - - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} - -struct CommitRollbackContext : public TransactionContext { - int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self) - { - GetInstance(self); - ASSERT_RETURN_SET_ERROR(transaction_ != nullptr, std::make_shared("transaction", "a transaction.")); - return OK; - } -}; - -napi_value GdbTransactionProxy::Commit(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - context->Parse(env, argc, argv, self); - }; - auto exec = [context]() -> int { - CHECK_RETURN_ERR(context->transaction_ != nullptr); - return context->StealTransaction()->Commit(); - }; - auto output = [context](napi_env env, napi_value &result) { - napi_status status = napi_get_undefined(env, &result); - CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); - }; - context->SetAction(env, info, input, exec, output); - - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} - -napi_value GdbTransactionProxy::Rollback(napi_env env, napi_callback_info info) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - context->Parse(env, argc, argv, self); - }; - auto exec = [context]() -> int { - CHECK_RETURN_ERR(context->transaction_ != nullptr); - return context->StealTransaction()->Rollback(); - }; - auto output = [context](napi_env env, napi_value &result) { - napi_status status = napi_get_undefined(env, &result); - CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); - }; - context->SetAction(env, info, input, exec, output); - - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - return ASYNC_CALL(env, context); -} -} // namespace OHOS::GraphStoreJsKit diff --git a/relational_store/frameworks/js/napi/rdb/BUILD.gn b/relational_store/frameworks/js/napi/rdb/BUILD.gn index db0236f0..7b122293 100644 --- a/relational_store/frameworks/js/napi/rdb/BUILD.gn +++ b/relational_store/frameworks/js/napi/rdb/BUILD.gn @@ -24,7 +24,9 @@ ohos_copy("relational_store_declaration") { ohos_shared_library("napi_rdb") { sources = [ "../common/src/js_df_manager.cpp", + "../common/src/js_scope.cpp", "../common/src/js_utils.cpp", + "../common/src/js_uv_queue.cpp", "src/napi_async_call.cpp", "src/napi_rdb_const_properties.cpp", "src/napi_rdb_js_utils.cpp", @@ -32,14 +34,12 @@ ohos_shared_library("napi_rdb") { "src/napi_rdb_store.cpp", "src/napi_rdb_store_helper.cpp", "src/napi_result_set.cpp", - "src/napi_uv_queue.cpp", "src/napi_values_bucket.cpp", ] if (is_mingw || is_mac) { include_dirs = [ "mock/include", - "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_js_common_path}/mock/include", "${relational_store_napi_path}/rdb/mock/include", @@ -71,12 +71,13 @@ ohos_shared_library("napi_rdb") { "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb:native_rdb", ] - external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps = [ + "bounds_checking_function:libsec_static", + "kv_store:datamgr_common", + ] } else { include_dirs = [ "include", - "${datashare_path}/common/include/", - "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_js_common_path}/include", "${relational_store_napi_path}/rdb/include", @@ -100,8 +101,12 @@ ohos_shared_library("napi_rdb") { "bounds_checking_function:libsec_shared", "c_utils:utils", "common_event_service:cesfwk_innerkits", + "data_share:datashare_common_lite", + "eventhandler:libeventhandler", "hilog:libhilog", "hitrace:hitrace_meter", + "ipc:ipc_single", + "kv_store:datamgr_common", "napi:ace_napi", ] } @@ -151,7 +156,6 @@ ohos_shared_library("rdb") { } else { include_dirs = [ "include", - "${datashare_path}/common/include/", "${relational_store_js_common_path}/include", "${relational_store_napi_path}/rdb/include", ] @@ -168,6 +172,7 @@ ohos_shared_library("rdb") { "ability_runtime:abilitykit_native", "ability_runtime:napi_base_context", "c_utils:utils", + "data_share:datashare_common_lite", "hilog:libhilog", "hitrace:hitrace_meter", "napi:ace_napi", diff --git a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_error.h b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_error.h index 79e174a4..9c3a913c 100644 --- a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_error.h +++ b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_error.h @@ -168,19 +168,6 @@ public: }; }; -class DbCorruptedError : public Error { -public: - DbCorruptedError() = default; - std::string GetMessage() override - { - return "Failed open database, database corrupted."; - }; - int GetCode() override - { - return E_DB_CORRUPTED; - }; -}; - class ResultGetError : public Error { public: ResultGetError() = default; diff --git a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_store_observer.h b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_store_observer.h index 5b14315a..53f5504a 100644 --- a/relational_store/frameworks/js/napi/rdb/include/napi_rdb_store_observer.h +++ b/relational_store/frameworks/js/napi/rdb/include/napi_rdb_store_observer.h @@ -15,17 +15,23 @@ #ifndef NAPI_RDB_STORE_OBSERVER_H #define NAPI_RDB_STORE_OBSERVER_H - -#include "napi_uv_queue.h" +#include "js_uv_queue.h" #include "rdb_types.h" -namespace OHOS::RdbJsKit { -class NapiRdbStoreObserver : public DistributedRdb::RdbStoreObserver, public NapiUvQueue { +namespace OHOS::RdbJsKit { +using namespace OHOS::AppDataMgrJsKit; +class NapiRdbStoreObserver : public DistributedRdb::RdbStoreObserver, + public std::enable_shared_from_this { public: - explicit NapiRdbStoreObserver(napi_env env, napi_value callback); + explicit NapiRdbStoreObserver(napi_value callback, std::shared_ptr uvQueue); virtual ~NapiRdbStoreObserver() noexcept; - + bool operator==(napi_value value); void OnChange(const std::vector &devices) override; + void Clear(); + +private: + std::shared_ptr uvQueue_; + napi_ref callback_; }; } // namespace OHOS::RdbJsKit #endif diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_async_call.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_async_call.cpp index 8d23e929..0b41ed4c 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_async_call.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_async_call.cpp @@ -30,13 +30,14 @@ void BaseContext::SetAction( napi_value self = nullptr; napi_value argv[MAX_INPUT_COUNT] = { nullptr }; NAPI_CALL_RETURN_VOID(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); - napi_valuetype valueType = napi_undefined; - napi_typeof(env, argv[argc - 1], &valueType); - if (valueType == napi_function) { - LOG_DEBUG("AsyncCall set callback"); - NAPI_CALL_RETURN_VOID(env, napi_create_reference(env, argv[argc - 1], 1, &callback_)); - argc = argc - 1; + if (argc > 0) { + napi_typeof(env, argv[argc - 1], &valueType); + if (valueType == napi_function) { + LOG_DEBUG("AsyncCall set callback"); + NAPI_CALL_RETURN_VOID(env, napi_create_reference(env, argv[argc - 1], 1, &callback_)); + argc = argc - 1; + } } // int -->input_(env, argc, argv, self) int status = input(env, argc, argv, self); diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_predicates.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_predicates.cpp index 5ec99f3b..b6d6abee 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_predicates.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_predicates.cpp @@ -177,7 +177,7 @@ napi_value RdbPredicatesProxy::NewInstance(napi_env env, std::shared_ptr(&proxy)); - if (status != napi_ok) { + if (status != napi_ok || proxy == nullptr) { LOG_ERROR("RdbPredicatesProxy::NewInstance native instance is nullptr! napi_status:%{public}d!", status); return instance; } @@ -193,6 +193,9 @@ void RdbPredicatesProxy::Destructor(napi_env env, void *nativeObject, void *) LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(nativeObject) & LOWER_24_BITS_MASK); } RdbPredicatesProxy *proxy = static_cast(nativeObject); + if (proxy == nullptr) { + return; + } proxy->predicates_ = std::move(nullptr); delete proxy; } diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp index 7d3bfdcb..95e2ee26 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp @@ -153,6 +153,9 @@ napi_value RdbStoreProxy::InnerInitialize(napi_env env, napi_callback_info info, napi_value self = nullptr; NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &self, nullptr)); auto finalize = [](napi_env env, void *data, void *hint) { + if (data == nullptr) { + return; + } auto tid = JSDFManager::GetInstance().GetFreedTid(data); if (tid != 0) { LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); @@ -586,7 +589,6 @@ napi_value RdbStoreProxy::BatchInsert(napi_env env, napi_callback_info info) }; auto output = [context](napi_env env, napi_value &result) -> int { napi_status status = napi_create_int64(env, context->insertNum, &result); - LOG_DEBUG("RdbStoreProxy::BatchInsert end. tableName is: %{public}s.", context->tableName.c_str()); return (status == napi_ok) ? OK : ERR; }; context->SetAction(env, info, input, exec, output); @@ -744,8 +746,8 @@ napi_value RdbStoreProxy::QuerySql(napi_env env, napi_callback_info info) }; auto exec = [context]() { RdbStoreProxy *obj = reinterpret_cast(context->boundObj); -#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr); +#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) context->resultSet = obj->rdbStore_->QueryByStep(context->sql, context->columns); LOG_ERROR("RdbStoreProxy::QuerySql is nullptr ? %{public}d ", context->resultSet == nullptr); return (context->resultSet != nullptr) ? OK : ERR; @@ -1053,7 +1055,7 @@ napi_value RdbStoreProxy::IsInTransaction(napi_env env, napi_callback_info info) napi_value thisObj = nullptr; napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr); RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj); - NAPI_ASSERT(env, rdbStoreProxy != nullptr, "RdbStoreProxy is nullptr"); + NAPI_ASSERT(env, rdbStoreProxy != nullptr && rdbStoreProxy->rdbStore_ != nullptr, "RdbStoreProxy is nullptr"); bool out = rdbStoreProxy->rdbStore_->IsInTransaction(); LOG_DEBUG("RdbStoreProxy::IsInTransaction out is : %{public}d.", out); return JSUtils::Convert2JSValue(env, out); @@ -1113,7 +1115,7 @@ napi_value RdbStoreProxy::SetDistributedTables(napi_env env, napi_callback_info auto exec = [context]() { LOG_DEBUG("RdbStoreProxy::SetDistributedTables Async."); RdbStoreProxy *obj = reinterpret_cast(context->boundObj); - if (obj == nullptr || obj->rdbStore_.get() == nullptr) { + if (obj == nullptr || obj->rdbStore_ == nullptr) { return ERR; } int res = obj->rdbStore_->SetDistributedTables(context->tablesName); @@ -1147,7 +1149,7 @@ napi_value RdbStoreProxy::ObtainDistributedTableName(napi_env env, napi_callback LOG_DEBUG("RdbStoreProxy::ObtainDistributedTableName Async."); RdbStoreProxy *obj = reinterpret_cast(context->boundObj); int errCode = E_ERROR; - if (obj == nullptr || obj->rdbStore_.get() == nullptr) { + if (obj == nullptr || obj->rdbStore_ == nullptr) { return ERR; } auto name = obj->rdbStore_->ObtainDistributedTableName(context->device, context->tableName, errCode); @@ -1186,9 +1188,11 @@ napi_value RdbStoreProxy::Sync(napi_env env, napi_callback_info info) SyncOption option; option.mode = static_cast(context->enumArg); option.isBlock = true; - if (obj == nullptr || obj->rdbStore_.get() == nullptr) { + if (obj == nullptr || obj->rdbStore_ == nullptr || context->predicatesProxy == nullptr || + context->predicatesProxy->GetPredicates() == nullptr) { return ERR; } + int res = obj->rdbStore_->Sync(option, *context->predicatesProxy->GetPredicates(), [context](const SyncResult &result) { context->syncResult = result; }); LOG_INFO("RdbStoreProxy::Sync res is : %{public}d.", res); @@ -1236,8 +1240,9 @@ void RdbStoreProxy::OnDataChangeEvent(napi_env env, size_t argc, napi_value *arg } SubscribeOption option; option.mode = static_cast(mode); - auto observer = std::make_shared(env, argv[1]); - int errCode = rdbStore_->Subscribe(option, observer.get()); + auto uvQueue = std::make_shared(env); + auto observer = std::make_shared(argv[1], uvQueue); + int errCode = rdbStore_->Subscribe(option, observer); if (errCode != E_OK) { LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: subscribe failed."); return; @@ -1277,7 +1282,8 @@ void RdbStoreProxy::OffDataChangeEvent(napi_env env, size_t argc, napi_value *ar LOG_ERROR("RdbStoreProxy::OnDataChangeEvent: rdbStore_ invalid."); return; } - rdbStore_->UnSubscribe(option, it->get()); + rdbStore_->UnSubscribe(option, *it); + (*it)->Clear(); observers_[mode].erase(it); LOG_INFO("RdbStoreProxy::OffDataChangeEvent: unsubscribe success."); return; diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_observer.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_observer.cpp index 216e2f65..d672249d 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_observer.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store_observer.cpp @@ -22,24 +22,47 @@ using namespace OHOS::Rdb; using namespace OHOS::AppDataMgrJsKit; namespace OHOS::RdbJsKit { -NapiRdbStoreObserver::NapiRdbStoreObserver(napi_env env, napi_value callback) : NapiUvQueue(env, callback) +NapiRdbStoreObserver::NapiRdbStoreObserver(napi_value callback, std::shared_ptr uvQueue) : uvQueue_(uvQueue) { + napi_create_reference(uvQueue_->GetEnv(), callback, 1, &callback_); } NapiRdbStoreObserver::~NapiRdbStoreObserver() noexcept { } +bool NapiRdbStoreObserver::operator==(napi_value value) +{ + return JSUtils::Equal(uvQueue_->GetEnv(), callback_, value); +} + void NapiRdbStoreObserver::OnChange(const std::vector &devices) { - LOG_INFO("NapiRdbStoreObserver::OnChange begin."); - CallFunction([devices](napi_env env, int &argc, napi_value *argv) { - argc = 1; - if (argv == nullptr) { - LOG_ERROR("NapiRdbStoreObserver::CallFunction error."); - return; + LOG_INFO("NapiRdbStoreObserver::OnChange begin"); + auto uvQueue = uvQueue_; + if (uvQueue == nullptr) { + return; + } + uvQueue->AsyncCall({ [observer = shared_from_this()](napi_env env) -> napi_value { + if (observer->callback_ == nullptr) { + return nullptr; } - argv[0] = JSUtils::Convert2JSValue(env, devices); - }); + napi_value callback = nullptr; + napi_get_reference_value(env, observer->callback_, &callback); + return callback; + } }, + [devices](napi_env env, int &argc, napi_value *argv) { + argc = 1; + argv[0] = JSUtils::Convert2JSValue(env, devices); + }); +} + +void NapiRdbStoreObserver::Clear() +{ + if (callback_ == nullptr) { + return; + } + napi_delete_reference(uvQueue_->GetEnv(), callback_); + callback_ = nullptr; } } // namespace OHOS::RdbJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_result_set.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_result_set.cpp index 1c47039c..a338a56e 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_result_set.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_result_set.cpp @@ -178,6 +178,9 @@ napi_value ResultSetProxy::InnerInitialize(napi_env env, napi_callback_info info } proxy->apiversion = version; auto finalize = [](napi_env env, void *data, void *hint) { + if (data == nullptr) { + return; + } auto tid = JSDFManager::GetInstance().GetFreedTid(data); if (tid != 0) { LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_uv_queue.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_uv_queue.cpp deleted file mode 100644 index 9badcf03..00000000 --- a/relational_store/frameworks/js/napi/rdb/src/napi_uv_queue.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2022 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. - */ -#define LOG_TAG "NapiUvQueue" -#include "napi_uv_queue.h" - -#include "logger.h" -#include "uv.h" - -namespace OHOS::RdbJsKit { -using namespace OHOS::Rdb; - -NapiUvQueue::NapiUvQueue(napi_env env, napi_value callback) - : env_(env) -{ - napi_create_reference(env, callback, 1, &callback_); - napi_get_uv_event_loop(env, &loop_); -} - -NapiUvQueue::~NapiUvQueue() -{ - napi_delete_reference(env_, callback_); -} - -bool NapiUvQueue::operator==(napi_value value) -{ - napi_value callback = nullptr; - napi_get_reference_value(env_, callback_, &callback); - - bool isEquals = false; - napi_strict_equals(env_, value, callback, &isEquals); - return isEquals; -} - -void NapiUvQueue::CallFunction(NapiArgsGenerator genArgs) -{ - uv_work_t *work = new (std::nothrow) uv_work_t; - if (work == nullptr) { - return; - } - work->data = this; - this->args = std::move(genArgs); - - int ret = uv_queue_work(loop_, work, [](uv_work_t* work) {}, [](uv_work_t* work, int st) { - auto queue = static_cast(work->data); - napi_handle_scope scope = nullptr; - napi_open_handle_scope(queue->env_, &scope); - if (scope == nullptr) { - delete work; - return; - } - int argc = 0; - napi_value argv[MAX_CALLBACK_ARG_NUM] = { nullptr }; - if (queue->args) { - queue->args(queue->env_, argc, argv); - } - - napi_value callback = nullptr; - napi_get_reference_value(queue->env_, queue->callback_, &callback); - napi_value global = nullptr; - napi_get_global(queue->env_, &global); - napi_value result = nullptr; - napi_status status = napi_call_function(queue->env_, global, callback, argc, argv, &result); - if (status != napi_ok) { - LOG_ERROR("napi_call_function failed, status=%{public}d", status); - } - napi_close_handle_scope(queue->env_, scope); - delete work; - }); - if (ret < 0) { - LOG_ERROR("uv_queue_work failed, errCode:%{public}d", ret); - delete static_cast(work->data); - delete work; - } -} -} // namespace OHOS::RdbJsKit diff --git a/relational_store/frameworks/js/napi/relationalstore/BUILD.gn b/relational_store/frameworks/js/napi/relationalstore/BUILD.gn index 6578c664..65f511aa 100644 --- a/relational_store/frameworks/js/napi/relationalstore/BUILD.gn +++ b/relational_store/frameworks/js/napi/relationalstore/BUILD.gn @@ -30,8 +30,10 @@ sources = [ "src/entry_point.cpp", "src/napi_async_call.cpp", "src/napi_rdb_const_properties.cpp", + "src/napi_rdb_context.cpp", "src/napi_rdb_error.cpp", "src/napi_rdb_js_utils.cpp", + "src/napi_rdb_log_observer.cpp", "src/napi_rdb_predicates.cpp", "src/napi_rdb_sendable_utils.cpp", "src/napi_rdb_statistics_observer.cpp", @@ -39,15 +41,12 @@ sources = [ "src/napi_rdb_store_helper.cpp", "src/napi_result_set.cpp", "src/napi_transaction.cpp", - "src/napi_uv_queue.cpp", ] if (is_ohos) { ohos_shared_library("relationalstore") { include_dirs = [ "include", - "${datashare_path}/common/include/", - "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_js_common_path}/include", "${relational_store_napi_path}/relationalstore/include", @@ -73,9 +72,12 @@ if (is_ohos) { "bounds_checking_function:libsec_shared", "c_utils:utils", "common_event_service:cesfwk_innerkits", + "data_share:datashare_common_lite", "eventhandler:libeventhandler", "hilog:libhilog", "hitrace:hitrace_meter", + "ipc:ipc_single", + "kv_store:datamgr_common", "napi:ace_napi", ] @@ -87,7 +89,6 @@ if (is_ohos) { ohos_shared_library("relationalstore") { include_dirs = [ "mock/include", - "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_js_common_path}/mock/include", "${relational_store_napi_path}/relationalstore/mock/include", @@ -115,7 +116,10 @@ if (is_ohos) { "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb:native_rdb", ] - external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps = [ + "bounds_checking_function:libsec_static", + "kv_store:datamgr_common", + ] subsystem_name = "distributeddatamgr" part_name = "relational_store" @@ -125,7 +129,6 @@ if (is_ohos) { ohos_shared_library("relationalstore") { include_dirs = [ "mock/include", - "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_js_common_path}/mock/include", "${relational_store_napi_path}/relationalstore/mock/include", @@ -137,6 +140,7 @@ if (is_ohos) { cflags_cc = [ "-std=c++17", "-stdlib=libc++", + "-Dnapi_send_event=SendEventMock", ] buildos = "mac" @@ -145,7 +149,10 @@ if (is_ohos) { "CROSS_PLATFORM", ] - sources += [ "${relational_store_js_common_path}/mock/src/js_ability.cpp" ] + sources += [ + "${relational_store_js_common_path}/mock/src/mock.cpp", + "${relational_store_js_common_path}/mock/src/js_ability.cpp", + ] deps = [ "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_${buildos}", @@ -153,7 +160,10 @@ if (is_ohos) { "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb:native_rdb", ] - external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps = [ + "bounds_checking_function:libsec_static", + "kv_store:datamgr_common", + ] subsystem_name = "distributeddatamgr" part_name = "relational_store" @@ -163,7 +173,6 @@ if (is_ohos) { ohos_source_set("data_relationalstore") { include_dirs = [ "mock/include", - "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_js_common_path}/mock/include", "include", @@ -186,6 +195,7 @@ if (is_ohos) { ] sources += [ + "src/napi_rdb_store_observer.cpp", "${relational_store_js_common_path}/mock/src/js_ability.cpp", "//foundation/appframework/ability/ability_runtime/cross_platform/interfaces/inner_api/napi_base_context/src/napi_base_context.cpp", ] @@ -196,7 +206,10 @@ if (is_ohos) { "//foundation/arkui/ace_engine/adapter/android/build:libarkui_android", ] - external_deps = [ "bounds_checking_function:libsec_static" ] + external_deps = [ + "bounds_checking_function:libsec_static", + "kv_store:datamgr_common", + ] subsystem_name = "distributeddatamgr" part_name = "relational_store" @@ -205,7 +218,6 @@ if (is_ohos) { ohos_source_set("data_relationalstore") { include_dirs = [ "mock/include", - "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_js_common_path}/mock/include", "include", @@ -220,6 +232,7 @@ if (is_ohos) { cflags_cc = [ "-std=c++17", "-stdlib=libc++", + "-Dnapi_send_event=SendEventMock", ] defines = [ @@ -227,19 +240,19 @@ if (is_ohos) { "CROSS_PLATFORM", ] - sources += [ "${relational_store_js_common_path}/mock/src/js_ability.cpp" ] + sources += [ + "${relational_store_js_common_path}/mock/src/mock.cpp", + "src/napi_rdb_store_observer.cpp", + "${relational_store_js_common_path}/mock/src/js_ability.cpp", + ] deps = [ + "${kvstore_path}/common:datamgr_common", "${relational_store_innerapi_path}/rdb:native_rdb", "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_ios", "//plugins/libs/napi:napi_ios", ] - external_deps = [ - "bounds_checking_function:libsec_static", - "c_utils:utils", - ] - subsystem_name = "distributeddatamgr" part_name = "relational_store" } diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_context.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_context.h index 5ffd6585..437d24fe 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_context.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_context.h @@ -19,6 +19,7 @@ #include "napi_async_call.h" #include "napi_rdb_js_utils.h" #include "napi_rdb_predicates.h" +#include "rdb_store.h" #include "transaction.h" #include "values_buckets.h" @@ -27,12 +28,7 @@ namespace RelationalStoreJsKit { class ResultSetProxy; using namespace OHOS::NativeRdb; struct RdbStoreContextBase : public ContextBase { - std::shared_ptr StealRdbStore() - { - auto rdb = std::move(rdbStore); - rdbStore = nullptr; - return rdb; - } + std::shared_ptr StealRdbStore(); std::shared_ptr rdbStore = nullptr; }; @@ -72,6 +68,7 @@ struct RdbStoreContext : public RdbStoreContextBase { std::map modifyTime; bool isQuerySql = false; uint32_t expiredTime = 0; + NativeRdb::RdbStoreConfig::CryptoParam cryptoParam; RdbStoreContext() : predicatesProxy(nullptr), int64Output(0), intOutput(0), enumArg(-1), @@ -88,6 +85,58 @@ struct CreateTransactionContext : public RdbStoreContextBase { AppDataMgrJsKit::JSUtils::TransactionOptions transactionOptions; std::shared_ptr transaction; }; + +int ParseTransactionOptions( + const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context); +int ParseTableName(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseCursor(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseCryptoParam(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseColumnName(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParsePrimaryKey(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseDevice(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseTablesName(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseSyncModeArg(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseDistributedTypeArg( + const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context); + +int ParseDistributedConfigArg( + const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context); + +int ParseCloudSyncModeArg(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseCallback(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseCloudSyncCallback(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParsePredicates(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseSrcType(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseSrcName(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseColumns(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseBindArgs(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseSql(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseTxId(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseSendableValuesBucket(const napi_env env, const napi_value map, std::shared_ptr context); + +int ParseValuesBucket(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseValuesBuckets(const napi_env env, const napi_value arg, std::shared_ptr context); + +int ParseConflictResolution(const napi_env env, const napi_value arg, std::shared_ptr context); } // namespace RelationalStoreJsKit } // namespace OHOS #endif // NAPI_RDB_CONTEXT_H \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h index 115c0e27..21936679 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_error.h @@ -90,16 +90,16 @@ public: class InnerError : public Error { public: - InnerError(int code) + InnerError(int code, const std::string &msg = "") { auto errorMsg = GetJsErrorCode(code); if (errorMsg.has_value()) { auto napiError = errorMsg.value(); code_ = napiError.jsCode; - msg_ = napiError.message; + msg_ = napiError.message + msg; } else { code_ = E_INNER_ERROR; - msg_ = "Inner error. Inner code is " + std::to_string(code % E_INNER_ERROR); + msg_ = "Inner error."; } } @@ -186,7 +186,7 @@ public: PathError(){}; std::string GetMessage() override { - return "Invalid database path."; + return "Failed to open or delete the database by an invalid database path."; }; int GetCode() override { diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h index 52f7b5ab..ddb90223 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h @@ -28,6 +28,7 @@ #include "value_object.h" #include "values_bucket.h" #include "values_buckets.h" +#include "rdb_sql_utils.h" namespace OHOS::AppDataMgrJsKit { namespace JSUtils { @@ -39,10 +40,12 @@ using JSChangeInfo = OHOS::RelationalStoreJsKit::NapiRdbStoreObserver::JSChangeI using PRIKey = OHOS::DistributedRdb::RdbStoreObserver::PrimaryKey; using Error = RelationalStoreJsKit::Error; using SecurityLevel = NativeRdb::SecurityLevel; +using SqlInfo = NativeRdb::SqlInfo; using Tokenizer = NativeRdb::Tokenizer; using RdbStoreConfig = NativeRdb::RdbStoreConfig; using BigInt = OHOS::NativeRdb::BigInteger; using SqlExecInfo = DistributedRdb::SqlObserver::SqlExecutionInfo; +using ExceptionMessage = DistributedRdb::SqlErrorObserver::ExceptionMessage; using ValuesBucket = OHOS::NativeRdb::ValuesBucket; using ValuesBuckets = OHOS::NativeRdb::ValuesBuckets; using HAMode = NativeRdb::HAMode; @@ -58,6 +61,7 @@ struct RdbConfig { bool allowRebuild = false; bool isReadOnly = false; bool persist = true; + bool enableSemanticIndex = false; SecurityLevel securityLevel = SecurityLevel::LAST; Tokenizer tokenizer = Tokenizer::NONE_TOKENIZER; std::string dataGroupId; @@ -137,6 +141,10 @@ template<> std::string ToString(const PRIKey &key); template<> napi_value Convert2JSValue(napi_env env, const SqlExecInfo &value); +template<> +napi_value Convert2JSValue(napi_env env, const ExceptionMessage &value); +template<> +napi_value Convert2JSValue(napi_env env, const SqlInfo &sqlinfo); bool IsNapiString(napi_env env, napi_value value); std::tuple> GetRealPath( diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_uv_queue.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_log_observer.h similarity index 50% rename from relational_store/frameworks/js/napi/relationalstore/include/napi_uv_queue.h rename to relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_log_observer.h index 5f3d618b..75c68822 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_uv_queue.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_log_observer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 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 @@ -12,36 +12,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef RDB_JSKIT_NAPI_RDB_LOG_OBSERVER_H +#define RDB_JSKIT_NAPI_RDB_LOG_OBSERVER_H +#include -#ifndef NAPI_UV_QUEUE_H -#define NAPI_UV_QUEUE_H - -#include - +#include "js_uv_queue.h" #include "napi/native_api.h" #include "napi/native_common.h" #include "napi/native_node_api.h" +#include "rdb_types.h" -namespace OHOS::RelationalStoreJsKit { -class NapiUvQueue { - using NapiArgsGenerator = std::function; - +namespace OHOS { +namespace RelationalStoreJsKit { +class NapiLogObserver + : public DistributedRdb::SqlErrorObserver, public std::enable_shared_from_this { public: - NapiUvQueue(napi_env env, napi_value callback); - - virtual ~NapiUvQueue(); - + NapiLogObserver(napi_env env, napi_value callback, std::shared_ptr uvQueue); + virtual ~NapiLogObserver(); + void Clear(); bool operator==(napi_value value); - - void CallFunction(NapiArgsGenerator genArgs = NapiArgsGenerator()); + void OnErrorLog(const ExceptionMessage &exceptionMessage) override; private: napi_env env_ = nullptr; napi_ref callback_ = nullptr; - NapiArgsGenerator args; - uv_loop_s *loop_ = nullptr; - - static constexpr int MAX_CALLBACK_ARG_NUM = 6; + std::shared_ptr queue_ = nullptr; }; -} // namespace OHOS::RelationalStoreJsKit -#endif \ No newline at end of file + +} // namespace RelationalStoreJsKit +} // namespace OHOS +#endif //RDB_JSKIT_NAPI_RDB_LOG_OBSERVER_H diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_predicates.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_predicates.h index f9c24ecb..6aefd2cd 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_predicates.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_predicates.h @@ -105,6 +105,7 @@ private: static napi_value GetBindArgs(napi_env env, napi_callback_info info); static napi_value InDevices(napi_env env, napi_callback_info info); static napi_value InAllDevices(napi_env env, napi_callback_info info); + static napi_value Having(napi_env env, napi_callback_info info); }; } // namespace RelationalStoreJsKit } // namespace OHOS diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_statistics_observer.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_statistics_observer.h index 4b2adf7a..2707545f 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_statistics_observer.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_statistics_observer.h @@ -39,6 +39,20 @@ private: std::shared_ptr queue_ = nullptr; }; +class NapiPerfStatObserver + : public DistributedRdb::SqlObserver, public std::enable_shared_from_this { +public: + NapiPerfStatObserver(napi_env env, napi_value callback, std::shared_ptr uvQueue); + virtual ~NapiPerfStatObserver(); + void Clear(); + bool operator==(napi_value value); + void OnStatistic(const SqlExecutionInfo &sqlExeInfo) override; + +private: + napi_env env_ = nullptr; + napi_ref callback_ = nullptr; + std::shared_ptr queue_ = nullptr; +}; } // namespace RelationalStoreJsKit } // namespace OHOS #endif //RDB_JSKIT_NAPI_RDB_STATISTICS_OBSERVER_H diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h index 2d506fe5..dde6181f 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h @@ -35,17 +35,17 @@ namespace RelationalStoreJsKit { using Descriptor = std::function(void)>; class NapiRdbStoreObserver; class NapiStatisticsObserver; +class NapiPerfStatObserver; +class NapiLogObserver; class RdbStoreProxy : public JSProxy::JSProxy { public: static void Init(napi_env env, napi_value exports); - static napi_value NewInstance(napi_env env, std::shared_ptr value, bool isSystemAppCalled, - const std::string &bundleName); + static napi_value NewInstance(napi_env env, std::shared_ptr value, bool isSystemAppCalled); RdbStoreProxy(); ~RdbStoreProxy(); RdbStoreProxy(std::shared_ptr rdbStore); RdbStoreProxy &operator=(std::shared_ptr rdbStore); bool IsSystemAppCalled(); - std::string GetBundleName(); private: static napi_value Initialize(napi_env env, napi_callback_info info); @@ -81,8 +81,10 @@ private: static napi_value CloudSync(napi_env env, napi_callback_info info); static napi_value GetModifyTime(napi_env env, napi_callback_info info); static napi_value CleanDirtyData(napi_env env, napi_callback_info info); + static napi_value Rekey(napi_env env, napi_callback_info info); static napi_value OnEvent(napi_env env, napi_callback_info info); static napi_value OffEvent(napi_env env, napi_callback_info info); + static napi_value SetLocale(napi_env env, napi_callback_info info); static napi_value Notify(napi_env env, napi_callback_info info); static napi_value QuerySharingResource(napi_env env, napi_callback_info info); static napi_value Close(napi_env env, napi_callback_info info); @@ -100,7 +102,7 @@ private: static void SetBusinessError(napi_env env, std::shared_ptr error, napi_value *businessError); void UnregisterAll(); - static constexpr int EVENT_HANDLE_NUM = 3; + static constexpr int EVENT_HANDLE_NUM = 5; static constexpr int WAIT_TIME_DEFAULT = 2; static constexpr int WAIT_TIME_LIMIT = 300; @@ -129,6 +131,10 @@ private: napi_value UnregisterSyncCallback(napi_env env, size_t argc, napi_value *argv); napi_value OnStatistics(napi_env env, size_t argc, napi_value *argv); napi_value OffStatistics(napi_env env, size_t argc, napi_value *argv); + napi_value OnErrorLog(napi_env env, size_t argc, napi_value *argv); + napi_value OffErrorLog(napi_env env, size_t argc, napi_value *argv); + napi_value OnPerfStat(napi_env env, size_t argc, napi_value *argv); + napi_value OffPerfStat(napi_env env, size_t argc, napi_value *argv); using EventHandle = napi_value (RdbStoreProxy::*)(napi_env, size_t, napi_value *); struct HandleInfo { @@ -138,12 +144,16 @@ private: static constexpr HandleInfo onEventHandlers_[EVENT_HANDLE_NUM] = { { "dataChange", &RdbStoreProxy::OnRemote }, { "autoSyncProgress", &RdbStoreProxy::RegisterSyncCallback }, - { "statistics", &RdbStoreProxy::OnStatistics } + { "statistics", &RdbStoreProxy::OnStatistics }, + { "perfStat", &RdbStoreProxy::OnPerfStat }, + { "sqliteErrorOccurred", &RdbStoreProxy::OnErrorLog } }; static constexpr HandleInfo offEventHandlers_[EVENT_HANDLE_NUM] = { { "dataChange", &RdbStoreProxy::OffRemote }, { "autoSyncProgress", &RdbStoreProxy::UnregisterSyncCallback }, - { "statistics", &RdbStoreProxy::OffStatistics } + { "statistics", &RdbStoreProxy::OffStatistics }, + { "perfStat", &RdbStoreProxy::OffPerfStat }, + { "sqliteErrorOccurred", &RdbStoreProxy::OffErrorLog } }; bool isSystemAppCalled_ = false; @@ -154,7 +164,8 @@ private: std::map>> localSharedObservers_; std::list> syncObservers_; std::list> statisticses_; - std::string bundleName_; + std::list> perfStats_; + std::list> logObservers_; }; } // namespace RelationalStoreJsKit } // namespace OHOS diff --git a/relational_store/frameworks/js/napi/relationalstore/mock/include/napi_rdb_store.h b/relational_store/frameworks/js/napi/relationalstore/mock/include/napi_rdb_store.h index 1122a89f..93397c9a 100644 --- a/relational_store/frameworks/js/napi/relationalstore/mock/include/napi_rdb_store.h +++ b/relational_store/frameworks/js/napi/relationalstore/mock/include/napi_rdb_store.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-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 @@ -31,17 +31,19 @@ namespace OHOS { namespace RelationalStoreJsKit { using Descriptor = std::function(void)>; +class NapiRdbStoreObserver; +class NapiStatisticsObserver; +class NapiPerfStatObserver; +class NapiLogObserver; class RdbStoreProxy : public JSProxy::JSProxy { public: static void Init(napi_env env, napi_value exports); - static napi_value NewInstance(napi_env env, std::shared_ptr value, bool isSystemAppCalled, - const std::string &bundleName); + static napi_value NewInstance(napi_env env, std::shared_ptr value, bool isSystemAppCalled); RdbStoreProxy(); ~RdbStoreProxy(); RdbStoreProxy(std::shared_ptr rdbStore); RdbStoreProxy &operator=(std::shared_ptr rdbStore); bool IsSystemAppCalled(); - std::string GetBundleName(); private: static Descriptor GetDescriptors(); @@ -54,6 +56,7 @@ private: static napi_value BatchInsertWithConflictResolution(napi_env env, napi_callback_info info); static napi_value Query(napi_env env, napi_callback_info info); static napi_value QuerySql(napi_env env, napi_callback_info info); + static napi_value QuerySync(napi_env env, napi_callback_info info); static napi_value ExecuteSql(napi_env env, napi_callback_info info); static napi_value Execute(napi_env env, napi_callback_info info); static napi_value Backup(napi_env env, napi_callback_info info); @@ -75,13 +78,47 @@ private: static napi_value Restore(napi_env env, napi_callback_info info); static napi_value Close(napi_env env, napi_callback_info info); static napi_value CreateTransaction(napi_env env, napi_callback_info info); + static napi_value Rekey(napi_env env, napi_callback_info info); + static napi_value SetLocale(napi_env env, napi_callback_info info); + static napi_value OnEvent(napi_env env, napi_callback_info info); + static napi_value OffEvent(napi_env env, napi_callback_info info); + + static constexpr int EVENT_HANDLE_NUM = 3; + napi_value RegisteredObserver(napi_env env, const DistributedRdb::SubscribeOption &option, napi_value callback); + napi_value UnRegisteredObserver(napi_env env, const DistributedRdb::SubscribeOption &option, napi_value callback); + napi_value OnStatistics(napi_env env, size_t argc, napi_value *argv); + napi_value OffStatistics(napi_env env, size_t argc, napi_value *argv); + napi_value OnErrorLog(napi_env env, size_t argc, napi_value *argv); + napi_value OffErrorLog(napi_env env, size_t argc, napi_value *argv); + napi_value OnPerfStat(napi_env env, size_t argc, napi_value *argv); + napi_value OffPerfStat(napi_env env, size_t argc, napi_value *argv); + using EventHandle = napi_value (RdbStoreProxy::*)(napi_env, size_t, napi_value *); + struct HandleInfo { + std::string_view event; + EventHandle handle; + }; + static constexpr HandleInfo onEventHandlers_[EVENT_HANDLE_NUM] = { + { "statistics", &RdbStoreProxy::OnStatistics }, + { "perfStat", &RdbStoreProxy::OnPerfStat }, + { "sqliteErrorOccurred", &RdbStoreProxy::OnErrorLog }, + }; + static constexpr HandleInfo offEventHandlers_[EVENT_HANDLE_NUM] = { + { "statistics", &RdbStoreProxy::OffStatistics }, + { "perfStat", &RdbStoreProxy::OffPerfStat }, + { "sqliteErrorOccurred", &RdbStoreProxy::OffErrorLog }, + }; void UnregisterAll(); + int32_t dbType = NativeRdb::DB_SQLITE; std::mutex mutex_; bool isSystemAppCalled_ = false; + std::map>> localObservers_; + std::map>> localSharedObservers_; std::shared_ptr queue_; - std::string bundleName_; - + std::list> statisticses_; + std::list> perfStats_; + std::list> logObservers_; + static constexpr int WAIT_TIME_DEFAULT = 2; static constexpr int WAIT_TIME_LIMIT = 300; }; diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_async_call.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_async_call.cpp index 6e333315..4c8ca8f0 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_async_call.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_async_call.cpp @@ -180,6 +180,10 @@ void AsyncCall::OnExecute(napi_env env, void *data) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); ContextBase *context = reinterpret_cast(data); + if (context == nullptr) { + LOG_ERROR("context is nullptr."); + return; + } if (context->executed_ != nullptr) { context->executed_->times_++; context->executed_->lastTime_ = std::chrono::duration_cast( @@ -194,6 +198,10 @@ void AsyncCall::OnExecute(napi_env env, void *data) void AsyncCall::OnComplete(napi_env env, void *data) { ContextBase *context = reinterpret_cast(data); + if (context == nullptr) { + LOG_ERROR("context is nullptr."); + return; + } if (context->execCode_ != NativeRdb::E_OK) { context->SetError(std::make_shared(context->execCode_)); } @@ -217,6 +225,10 @@ void AsyncCall::OnComplete(napi_env env, napi_status status, void *data) void AsyncCall::OnReturn(napi_env env, napi_status status, void *data) { ContextBase *context = reinterpret_cast(data); + if (context == nullptr) { + LOG_ERROR("context is nullptr."); + return; + } napi_value result[ARG_BUTT] = { 0 }; // if out function status is ok then async renturn output data, else return error. if (context->error == nullptr) { diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_context.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_context.cpp new file mode 100644 index 00000000..32829649 --- /dev/null +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_context.cpp @@ -0,0 +1,358 @@ +/* + * 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_rdb_context.h" + +using namespace OHOS::RelationalStoreJsKit; + +namespace OHOS { +namespace RelationalStoreJsKit { +constexpr int32_t KEY_INDEX = 0; +constexpr int32_t VALUE_INDEX = 1; +std::shared_ptr RdbStoreContextBase::StealRdbStore() +{ + auto rdb = std::move(rdbStore); + rdbStore = nullptr; + return rdb; +} +int ParseTransactionOptions( + const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context) +{ + context->transactionOptions.transactionType = Transaction::DEFERRED; + if (argc > 0 && !JSUtils::IsNull(env, argv[0])) { + auto status = JSUtils::Convert2Value(env, argv[0], context->transactionOptions); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("options", "a transactionOptions")); + } + return OK; +} +int ParseTableName(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + context->tableName = JSUtils::Convert2String(env, arg); + CHECK_RETURN_SET(!context->tableName.empty(), std::make_shared("table", "not empty string.")); + return OK; +} + +int ParseCursor(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + double cursor = 0; + auto status = JSUtils::Convert2Value(env, arg, cursor); + CHECK_RETURN_SET(status == napi_ok && cursor > 0, std::make_shared("cursor", "valid cursor.")); + context->cursor = static_cast(cursor); + return OK; +} + +int ParseCryptoParam(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + auto status = JSUtils::Convert2Value(env, arg, context->cryptoParam); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("cryptoParam", "valid cryptoParam.")); + return OK; +} + +int ParseColumnName(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + context->columnName = JSUtils::Convert2String(env, arg); + CHECK_RETURN_SET(!context->columnName.empty(), std::make_shared("columnName", "not empty string.")); + return OK; +} + +int ParsePrimaryKey(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + JSUtils::Convert2Value(env, arg, context->keys); + CHECK_RETURN_SET(!context->keys.empty(), std::make_shared("PRIKey", "number or string.")); + return OK; +} + +int ParseDevice(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + context->device = JSUtils::Convert2String(env, arg); + CHECK_RETURN_SET(!context->device.empty(), std::make_shared("device", "not empty")); + return OK; +} + +int ParseSrcType(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + std::string value = ""; + int32_t status = JSUtils::Convert2Value(env, arg, value); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("srcName", "not null")); + context->srcName = value; + return OK; +} + +int ParseTablesName(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + int32_t ret = JSUtils::Convert2Value(env, arg, context->tablesNames); + CHECK_RETURN_SET(ret == napi_ok, std::make_shared("tablesNames", "not empty string.")); + return OK; +} + +int ParseSyncModeArg(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + napi_valuetype type = napi_undefined; + napi_typeof(env, arg, &type); + CHECK_RETURN_SET(type == napi_number, std::make_shared("mode", "a SyncMode Type.")); + napi_status status = napi_get_value_int32(env, arg, &context->enumArg); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("mode", "a SyncMode Type.")); + bool checked = context->enumArg == 0 || context->enumArg == 1; + CHECK_RETURN_SET(checked, std::make_shared("mode", "a SyncMode of device.")); + return OK; +} + +int ParseDistributedTypeArg( + const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context) +{ + context->distributedType = DistributedRdb::DISTRIBUTED_DEVICE; + if (argc > 1) { + auto status = JSUtils::Convert2ValueExt(env, argv[1], context->distributedType); + bool checked = status == napi_ok && context->distributedType >= DistributedRdb::DISTRIBUTED_DEVICE && + context->distributedType <= DistributedRdb::DISTRIBUTED_CLOUD; + CHECK_RETURN_SET(JSUtils::IsNull(env, argv[1]) || checked, + std::make_shared("distributedType", "a DistributedType")); + } + return OK; +} + +int ParseDistributedConfigArg( + const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context) +{ + context->distributedConfig = { false }; + // '2' Ensure that the incoming argv contains 3 parameter + if (argc > 2) { + auto status = JSUtils::Convert2Value(env, argv[2], context->distributedConfig); + bool checked = status == napi_ok || JSUtils::IsNull(env, argv[2]); + CHECK_RETURN_SET(checked, std::make_shared("distributedConfig", "a DistributedConfig type")); + } + return OK; +} + +int ParseCloudSyncModeArg(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + auto status = JSUtils::Convert2ValueExt(env, arg, context->syncMode); + bool checked = (status == napi_ok && context->syncMode >= DistributedRdb::TIME_FIRST && + context->syncMode <= DistributedRdb::CLOUD_FIRST); + CHECK_RETURN_SET(checked, std::make_shared("mode", "a SyncMode of cloud.")); + return OK; +} + +int ParseCallback(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + napi_valuetype valueType = napi_undefined; + napi_status status = napi_typeof(env, arg, &valueType); + CHECK_RETURN_SET( + (status == napi_ok && valueType == napi_function), std::make_shared("callback", "a function.")); + NAPI_CALL_BASE(env, napi_create_reference(env, arg, 1, &context->callback_), ERR); + return OK; +} + +int ParseCloudSyncCallback(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + napi_valuetype valueType = napi_undefined; + napi_typeof(env, arg, &valueType); + CHECK_RETURN_SET(valueType == napi_function, std::make_shared("progress", "a callback type")); + NAPI_CALL_BASE(env, napi_create_reference(env, arg, 1, &context->asyncHolder), ERR); + return OK; +} + +int ParsePredicates(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + auto status = napi_unwrap(env, arg, reinterpret_cast(&context->predicatesProxy)); + CHECK_RETURN_SET(status == napi_ok && context->predicatesProxy != nullptr, + std::make_shared("predicates", "an RdbPredicates.")); + context->tableName = context->predicatesProxy->GetPredicates()->GetTableName(); + context->rdbPredicates = context->predicatesProxy->GetPredicates(); + return OK; +} + +int ParseSrcName(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + context->srcName = JSUtils::Convert2String(env, arg); + CHECK_RETURN_SET(!context->srcName.empty(), std::make_shared("srcName", "not empty")); + return OK; +} + +int ParseColumns(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + napi_valuetype type = napi_undefined; + napi_typeof(env, arg, &type); + if (type == napi_undefined || type == napi_null) { + return OK; + } + int32_t ret = JSUtils::Convert2Value(env, arg, context->columns); + CHECK_RETURN_SET(ret == napi_ok, std::make_shared("columns", "a string array")); + return OK; +} + +int ParseBindArgs(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + context->bindArgs.clear(); + napi_valuetype type = napi_undefined; + napi_typeof(env, arg, &type); + if (type == napi_undefined || type == napi_null) { + return OK; + } + bool isArray = false; + napi_status status = napi_is_array(env, arg, &isArray); + CHECK_RETURN_SET(status == napi_ok && isArray, std::make_shared("values", "a BindArgs array.")); + + uint32_t arrLen = 0; + status = napi_get_array_length(env, arg, &arrLen); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("values", "not empty.")); + for (size_t i = 0; i < arrLen; ++i) { + napi_value element = nullptr; + napi_get_element(env, arg, i, &element); + ValueObject valueObject; + int32_t ret = JSUtils::Convert2Value(env, element, valueObject.value); + CHECK_RETURN_SET(ret == OK, std::make_shared(std::to_string(i), "ValueObject")); + // The blob is an empty vector. + // If the API version is less than 14, and insert null. Otherwise, insert an empty vector. + if (valueObject.GetType() == ValueObject::TYPE_BLOB && JSUtils::GetHapVersion() < 14) { + std::vector tmpValue; + valueObject.GetBlob(tmpValue); + if (tmpValue.empty()) { + valueObject = ValueObject(); + } + } + context->bindArgs.push_back(std::move(valueObject)); + } + return OK; +} + +int ParseSql(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + context->sql = JSUtils::Convert2String(env, arg); + CHECK_RETURN_SET(!context->sql.empty(), std::make_shared("sql", "not empty")); + return OK; +} + +int ParseTxId(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + int64_t txId = 0; + auto status = JSUtils::Convert2ValueExt(env, arg, txId); + CHECK_RETURN_SET(status == napi_ok && txId >= 0, std::make_shared("txId", "not invalid txId")); + context->txId = txId; + return OK; +} + +int ParseSendableValuesBucket(const napi_env env, const napi_value map, std::shared_ptr context) +{ + uint32_t length = 0; + napi_status status = napi_map_get_size(env, map, &length); + auto error = std::make_shared("ValuesBucket is invalid."); + CHECK_RETURN_SET(status == napi_ok && length > 0, error); + napi_value entries = nullptr; + status = napi_map_get_entries(env, map, &entries); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_map_get_entries failed.")); + for (uint32_t i = 0; i < length; ++i) { + napi_value iter = nullptr; + status = napi_map_iterator_get_next(env, entries, &iter); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_map_iterator_get_next failed.")); + napi_value values = nullptr; + status = napi_get_named_property(env, iter, "value", &values); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_named_property value failed.")); + napi_value key = nullptr; + status = napi_get_element(env, values, KEY_INDEX, &key); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_element key failed.")); + std::string keyStr = JSUtils::Convert2String(env, key); + napi_value value = nullptr; + status = napi_get_element(env, values, VALUE_INDEX, &value); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_element value failed.")); + ValueObject valueObject; + int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value); + if (ret == napi_ok) { + context->valuesBucket.Put(keyStr, valueObject); + } else if (ret != napi_generic_failure) { + CHECK_RETURN_SET(false, std::make_shared("The value type of " + keyStr, "invalid.")); + } + } + return OK; +} + +int ParseValuesBucket(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + bool isMap = false; + napi_status status = napi_is_map(env, arg, &isMap); + CHECK_RETURN_SET( + status == napi_ok, std::make_shared("call napi_is_map failed" + std::to_string(status))); + if (isMap) { + return ParseSendableValuesBucket(env, arg, context); + } + napi_value keys = nullptr; + napi_get_all_property_names(env, arg, napi_key_own_only, + static_cast(napi_key_enumerable | napi_key_skip_symbols), napi_key_numbers_to_strings, &keys); + uint32_t arrLen = 0; + status = napi_get_array_length(env, keys, &arrLen); + CHECK_RETURN_SET(status == napi_ok && arrLen > 0, std::make_shared("ValuesBucket is invalid")); + + for (size_t i = 0; i < arrLen; ++i) { + napi_value key = nullptr; + status = napi_get_element(env, keys, i, &key); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("ValuesBucket is invalid.")); + std::string keyStr = JSUtils::Convert2String(env, key); + napi_value value = nullptr; + napi_get_property(env, arg, key, &value); + ValueObject valueObject; + int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value); + // The blob is an empty vector. + // If the API version is less than 14, and insert null. Otherwise, insert an empty vector. + if (ret == napi_ok && valueObject.GetType() == ValueObject::TYPE_BLOB && JSUtils::GetHapVersion() < 14) { + std::vector tmpValue; + valueObject.GetBlob(tmpValue); + if (tmpValue.empty()) { + valueObject = ValueObject(); + } + } + if (ret == napi_ok) { + context->valuesBucket.Put(keyStr, valueObject); + } else if (ret != napi_generic_failure) { + CHECK_RETURN_SET(false, std::make_shared("The value type of " + keyStr, "invalid.")); + } + } + return OK; +} + +int ParseValuesBuckets(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + bool isArray = false; + napi_status status = napi_is_array(env, arg, &isArray); + CHECK_RETURN_SET(status == napi_ok && isArray, std::make_shared("ValuesBuckets is invalid.")); + + uint32_t arrLen = 0; + status = napi_get_array_length(env, arg, &arrLen); + CHECK_RETURN_SET(status == napi_ok && arrLen > 0, std::make_shared("ValuesBuckets is invalid.")); + + for (uint32_t i = 0; i < arrLen; ++i) { + napi_value obj = nullptr; + status = napi_get_element(env, arg, i, &obj); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_element failed.")); + + CHECK_RETURN_ERR(ParseValuesBucket(env, obj, context) == OK); + context->sharedValuesBuckets.Put(context->valuesBucket); + context->valuesBucket.Clear(); + } + return OK; +} + +int ParseConflictResolution(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + int32_t conflictResolution = 0; + napi_get_value_int32(env, arg, &conflictResolution); + int32_t min = static_cast(NativeRdb::ConflictResolution::ON_CONFLICT_NONE); + int32_t max = static_cast(NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE); + bool checked = (conflictResolution >= min) && (conflictResolution <= max); + CHECK_RETURN_SET(checked, std::make_shared("conflictResolution", "a ConflictResolution.")); + context->conflictResolution = static_cast(conflictResolution); + return OK; +} +} // namespace RelationalStoreJsKit +} // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_error.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_error.cpp index d6418cd4..9d41b1c2 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_error.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_error.cpp @@ -21,23 +21,25 @@ namespace OHOS { namespace RelationalStoreJsKit { using JsErrorCode = OHOS::RelationalStoreJsKit::JsErrorCode; static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = { + { E_PARAM_ERROR, 401, "Invalid args."}, { E_NOT_STAGE_MODE, 14801001, "The operation is supported in the stage model only." }, { E_DATA_GROUP_ID_INVALID, 14801002, "Invalid data ground ID." }, { NativeRdb::E_NOT_SELECT, 14800019, "The SQL must be a query statement." }, - { NativeRdb::E_COLUMN_OUT_RANGE, 14800013, "Column out of bounds." }, - { NativeRdb::E_INVALID_FILE_PATH, 14800010, "Invalid database path." }, - { NativeRdb::E_ROW_OUT_RANGE, 14800012, "Row out of bounds." }, + { NativeRdb::E_COLUMN_OUT_RANGE, 14800013, "Resultset is empty or column index is out of bounds." }, + { NativeRdb::E_INVALID_FILE_PATH, 14800010, "Failed to open or delete the database by an invalid database path." }, + { NativeRdb::E_ROW_OUT_RANGE, 14800012, "ResultSet is empty or pointer index is out of bounds." }, { NativeRdb::E_NO_ROW_IN_QUERY, 14800018, "No data meets the condition." }, - { NativeRdb::E_ALREADY_CLOSED, 14800014, "Already closed." }, + { NativeRdb::E_ALREADY_CLOSED, 14800014, "The RdbStore or ResultSet is already closed." }, { NativeRdb::E_DATABASE_BUSY, 14800015, "The database does not respond." }, { NativeRdb::E_WAL_SIZE_OVER_LIMIT, 14800047, "The WAL file size over default limit." }, { NativeRdb::E_GET_DATAOBSMGRCLIENT_FAIL, 14801050, "Failed to get DataObsMgrClient." }, { NativeRdb::E_TYPE_MISMATCH, 14800051, "The type of the distributed table does not match." }, { NativeRdb::E_SQLITE_FULL, 14800029, "SQLite: The database is full." }, - { NativeRdb::E_NOT_SUPPORT_THE_SQL, 14800021, "SQLite: Generic error." }, + { NativeRdb::E_NOT_SUPPORT_THE_SQL, 14800021, "SQLite: Generic error. Executed SQL statement is not supported." }, { NativeRdb::E_ATTACHED_DATABASE_EXIST, 14800016, "The database alias already exists." }, - { NativeRdb::E_SQLITE_ERROR, 14800021, "SQLite: Generic error." }, - { NativeRdb::E_SQLITE_CORRUPT, 14800011, "Database corrupted." }, + { NativeRdb::E_SQLITE_ERROR, 14800021, + "SQLite: Generic error. Possible causes: Insert failed or the updated data does not exist." }, + { NativeRdb::E_SQLITE_CORRUPT, 14800011, "Failed to open the database because it is corrupted." }, { NativeRdb::E_SQLITE_ABORT, 14800022, "SQLite: Callback routine requested an abort." }, { NativeRdb::E_SQLITE_PERM, 14800023, "SQLite: Access permission denied." }, { NativeRdb::E_SQLITE_BUSY, 14800024, "SQLite: The database file is locked." }, @@ -50,10 +52,10 @@ static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = { { NativeRdb::E_SQLITE_CONSTRAINT, 14800032, "SQLite: Abort due to constraint violation." }, { NativeRdb::E_SQLITE_MISMATCH, 14800033, "SQLite: Data type mismatch." }, { NativeRdb::E_SQLITE_MISUSE, 14800034, "SQLite: Library used incorrectly." }, - { NativeRdb::E_CONFIG_INVALID_CHANGE, 14800017, "Config changed." }, + { NativeRdb::E_CONFIG_INVALID_CHANGE, 14800017, "StoreConfig is changed." }, { NativeRdb::E_INVALID_SECRET_KEY, 14800020, "The secret key is corrupted or lost." }, { NativeRdb::E_SQLITE_IOERR_FULL, 14800028, "SQLite: Some kind of disk I/O error occurred." }, - { NativeRdb::E_INVALID_ARGS_NEW, 401, "Invalid args." }, + { NativeRdb::E_INVALID_ARGS_NEW, 14800001, "Invalid args." }, { NativeRdb::E_NOT_SUPPORT, 801, "Capability not support." }, }; diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp index bdbf1f38..85b8062a 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp @@ -217,6 +217,35 @@ napi_value Convert2JSValue(napi_env env, const DistributedRdb::SqlObserver::SqlE return object; } +template<> +napi_value Convert2JSValue(napi_env env, const ExceptionMessage &value) +{ + std::vector descriptors = { + DECLARE_JS_PROPERTY(env, "code", value.code), + DECLARE_JS_PROPERTY(env, "message", value.message), + DECLARE_JS_PROPERTY(env, "sql", value.sql), + }; + + napi_value object = nullptr; + NAPI_CALL_RETURN_ERR( + napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); + return object; +} + +template<> +napi_value Convert2JSValue(napi_env env, const SqlInfo &sqlInfo) +{ + std::vector descriptors = { + DECLARE_JS_PROPERTY(env, "sql", sqlInfo.sql), + DECLARE_JS_PROPERTY(env, "args", sqlInfo.args), + }; + + napi_value object = nullptr; + NAPI_CALL_RETURN_ERR( + napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); + return object; +} + template<> napi_value Convert2JSValue(napi_env env, const DistributedRdb::Details &details) { @@ -397,6 +426,9 @@ int32_t Convert2Value(napi_env env, napi_value jsValue, RdbConfig &rdbConfig) status = GetNamedProperty(env, jsValue, "persist", rdbConfig.persist, true); ASSERT(OK == status, "get persist failed.", napi_invalid_arg); + + status = GetNamedProperty(env, jsValue, "enableSemanticIndex", rdbConfig.enableSemanticIndex, true); + ASSERT(OK == status, "get enableSemanticIndex failed.", napi_invalid_arg); return napi_ok; } @@ -544,6 +576,8 @@ RdbStoreConfig GetRdbStoreConfig(const RdbConfig &rdbConfig, const ContextParam rdbStoreConfig.SetHaMode(rdbConfig.haMode); rdbStoreConfig.SetCryptoParam(rdbConfig.cryptoParam); + + rdbStoreConfig.SetEnableSemanticIndex(rdbConfig.enableSemanticIndex); return rdbStoreConfig; } diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_log_observer.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_log_observer.cpp new file mode 100644 index 00000000..c0e3e3c9 --- /dev/null +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_log_observer.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 "napi_rdb_log_observer.h" + +#include "napi_rdb_js_utils.h" + +namespace OHOS::RelationalStoreJsKit { +NapiLogObserver::NapiLogObserver( + napi_env env, napi_value callback, std::shared_ptr queue) + : env_(env), queue_(queue) +{ + napi_create_reference(env, callback, 1, &callback_); +} + +NapiLogObserver::~NapiLogObserver() +{ +} + +void NapiLogObserver::Clear() +{ + if (callback_ == nullptr) { + return; + } + napi_delete_reference(env_, callback_); + callback_ = nullptr; +} + +bool NapiLogObserver::operator==(napi_value value) +{ + return JSUtils::Equal(env_, callback_, value); +} + +void NapiLogObserver::OnErrorLog(const ExceptionMessage &exceptionMessage) +{ + auto queue = queue_; + if (queue == nullptr) { + return; + } + queue->AsyncCall({ [observer = shared_from_this()](napi_env env) -> napi_value { + if (observer->callback_ == nullptr) { + return nullptr; + } + napi_value callback = nullptr; + napi_get_reference_value(env, observer->callback_, &callback); + return callback; + } }, + [infos = std::move(exceptionMessage)](napi_env env, int &argc, napi_value *argv) { + argc = 1; + argv[0] = JSUtils::Convert2JSValue(env, infos); + }); +} +} // namespace OHOS::RelationalStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp index a3dd2d34..f20a08fd 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp @@ -12,10 +12,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #define LOG_TAG "NapiRdbPredicates" #include "napi_rdb_predicates.h" +#include + #include "js_df_manager.h" +#include "js_native_api.h" +#include "js_native_api_types.h" #include "js_utils.h" #include "logger.h" #include "napi_rdb_error.h" @@ -68,6 +73,7 @@ void RdbPredicatesProxy::Init(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("on", On), DECLARE_NAPI_FUNCTION("clear", Clear), DECLARE_NAPI_FUNCTION("crossJoin", CrossJoin), + DECLARE_NAPI_FUNCTION("having", Having), DECLARE_NAPI_GETTER_SETTER("joinCount", GetJoinCount, SetJoinCount), DECLARE_NAPI_GETTER_SETTER("joinConditions", GetJoinConditions, SetJoinConditions), DECLARE_NAPI_GETTER_SETTER("joinNames", GetJoinTableNames, SetJoinTableNames), @@ -164,7 +170,9 @@ void RdbPredicatesProxy::Destructor(napi_env env, void *nativeObject, void *) LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(nativeObject) & LOWER_24_BITS_MASK); } RdbPredicatesProxy *proxy = static_cast(nativeObject); - + if (proxy == nullptr) { + return; + } proxy->SetInstance(nullptr); delete proxy; } @@ -858,5 +866,35 @@ napi_value RdbPredicatesProxy::InAllDevices(napi_env env, napi_callback_info inf predicatesProxy->GetInstance()->InAllDevices(); return thiz; } + +napi_value RdbPredicatesProxy::Having(napi_env env, napi_callback_info info) +{ + napi_value thiz = nullptr; + // There may be 2 parameters. + size_t argc = 2; + napi_value args[2] = { 0 }; + napi_status status = napi_get_cb_info(env, info, &argc, args, &thiz, nullptr); + RDB_NAPI_ASSERT(env, status == napi_ok && thiz != nullptr, std::make_shared("predicates", "null")); + // Ensure that argc contains 1 or 2 parameters + RDB_NAPI_ASSERT(env, argc >= 1 && argc <= 2, std::make_shared("1 or 2")); + RdbPredicatesProxy *proxy = nullptr; + status = napi_unwrap(env, thiz, reinterpret_cast(&proxy)); + RDB_NAPI_ASSERT( + env, status == napi_ok && proxy && proxy->GetInstance(), std::make_shared("predicates", "null")); + std::string conditions; + int32_t res = JSUtils::Convert2Value(env, args[0], conditions); + RDB_NAPI_ASSERT(env, res == OK && !conditions.empty(), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "conditions cannot be empty")); + std::vector values; + // 2 represents the number of parameters. + if (argc == 2 && !JSUtils::IsNull(env, args[1])) { + int32_t ret = JSUtils::Convert2Value(env, args[1], values); + RDB_NAPI_ASSERT(env, ret == napi_ok, std::make_shared("ags", "a ValueType array.")); + } + RDB_NAPI_ASSERT(env, !proxy->GetInstance()->GetGroup().empty(), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Missing GROUP BY clause.")); + proxy->GetInstance()->Having(conditions, values); + return thiz; +} } // namespace RelationalStoreJsKit -} // namespace OHOS +} // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_statistics_observer.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_statistics_observer.cpp index e7ff2166..8acd9dfa 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_statistics_observer.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_statistics_observer.cpp @@ -62,4 +62,49 @@ void NapiStatisticsObserver::OnStatistic(const SqlExecutionInfo &sqlExeInfo) argv[0] = JSUtils::Convert2JSValue(env, infos); }); } + +NapiPerfStatObserver::NapiPerfStatObserver( + napi_env env, napi_value callback, std::shared_ptr queue) + : env_(env), queue_(queue) +{ + napi_create_reference(env, callback, 1, &callback_); +} + +NapiPerfStatObserver::~NapiPerfStatObserver() +{ +} + +void NapiPerfStatObserver::Clear() +{ + if (callback_ == nullptr) { + return; + } + napi_delete_reference(env_, callback_); + callback_ = nullptr; +} + +bool NapiPerfStatObserver::operator==(napi_value value) +{ + return JSUtils::Equal(env_, callback_, value); +} + +void NapiPerfStatObserver::OnStatistic(const SqlExecutionInfo &sqlExeInfo) +{ + auto queue = queue_; + if (queue == nullptr) { + return; + } + queue->AsyncCall({ [observer = shared_from_this()](napi_env env) -> napi_value { + if (observer->callback_ == nullptr) { + return nullptr; + } + napi_value callback = nullptr; + napi_get_reference_value(env, observer->callback_, &callback); + return callback; + } }, + [infos = std::move(sqlExeInfo)](napi_env env, int &argc, napi_value *argv) { + argc = 1; + argv[0] = JSUtils::Convert2JSValue(env, infos); + }); +} } // namespace OHOS::RelationalStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp index 167b9bad..2ade18f5 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-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 @@ -30,15 +30,18 @@ #include "napi_rdb_context.h" #include "napi_rdb_error.h" #include "napi_rdb_js_utils.h" +#include "napi_rdb_log_observer.h" #include "napi_rdb_statistics_observer.h" #include "napi_rdb_store_observer.h" #include "napi_rdb_trace.h" #include "napi_result_set.h" #include "napi_transaction.h" #include "rdb_errno.h" +#include "rdb_sql_log.h" #include "rdb_sql_statistic.h" -#include "rdb_fault_hiview_reporter.h" +#include "rdb_perfStat.h" #include "securec.h" +#include "rdb_types.h" #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) #include "rdb_utils.h" @@ -48,6 +51,7 @@ using namespace OHOS::DataShare; using namespace OHOS::Rdb; using namespace OHOS::AppDataMgrJsKit; using namespace OHOS::AppDataMgrJsKit::JSUtils; +using namespace OHOS::DistributedRdb; #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) using OHOS::DistributedRdb::SubscribeMode; @@ -66,9 +70,6 @@ struct PredicatesProxy { std::shared_ptr predicates_; }; #endif -using Reportor = RdbFaultHiViewReporter; -constexpr int32_t KEY_INDEX = 0; -constexpr int32_t VALUE_INDEX = 1; RdbStoreProxy::RdbStoreProxy() {} @@ -89,7 +90,7 @@ void RdbStoreProxy::UnregisterAll() if (obs == nullptr) { continue; } - rdbStore->UnSubscribe({ static_cast(mode) }, obs.get()); + rdbStore->UnSubscribe({ static_cast(mode) }, obs); } } rdbStore->UnsubscribeObserver({ SubscribeMode::LOCAL_DETAIL }, nullptr); @@ -105,6 +106,9 @@ void RdbStoreProxy::UnregisterAll() for (const auto &obs : statisticses_) { DistributedRdb::SqlStatistic::Unsubscribe(obs); } + for (const auto &obs : logObservers_) { + NativeRdb::SqlLog::Unsubscribe(GetInstance()->GetPath(), obs); + } #endif } @@ -130,11 +134,6 @@ bool RdbStoreProxy::IsSystemAppCalled() return isSystemAppCalled_; } -std::string RdbStoreProxy::GetBundleName() -{ - return bundleName_; -} - bool IsNapiTypeString(napi_env env, size_t argc, napi_value *argv, size_t arg) { if (arg >= argc) { @@ -174,6 +173,10 @@ Descriptor RdbStoreProxy::GetDescriptors() DECLARE_NAPI_FUNCTION("attach", Attach), DECLARE_NAPI_FUNCTION("detach", Detach), DECLARE_NAPI_FUNCTION("createTransaction", CreateTransaction), + DECLARE_NAPI_FUNCTION("setLocale", SetLocale), + DECLARE_NAPI_FUNCTION("rekey", Rekey), + DECLARE_NAPI_FUNCTION("on", OnEvent), + DECLARE_NAPI_FUNCTION("off", OffEvent), }; #if !defined(CROSS_PLATFORM) AddDistributedFunctions(properties); @@ -207,13 +210,17 @@ napi_value RdbStoreProxy::Initialize(napi_env env, napi_callback_info info) napi_value self = nullptr; NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &self, nullptr)); auto finalize = [](napi_env env, void *data, void *hint) { + if (data == nullptr) { + LOG_ERROR("data is nullptr."); + return; + } auto tid = JSDFManager::GetInstance().GetFreedTid(data); if (tid != 0) { LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); } if (data != hint) { - LOG_ERROR("RdbStoreProxy memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, uintptr_t(data), - uintptr_t(hint)); + LOG_ERROR("RdbStoreProxy memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, + uintptr_t(data) & LOWER_24_BITS_MASK, uintptr_t(hint) & LOWER_24_BITS_MASK); return; } RdbStoreProxy *proxy = reinterpret_cast(data); @@ -235,8 +242,7 @@ napi_value RdbStoreProxy::Initialize(napi_env env, napi_callback_info info) return self; } -napi_value RdbStoreProxy::NewInstance( - napi_env env, std::shared_ptr value, bool isSystemAppCalled, const std::string &bundleName) +napi_value RdbStoreProxy::NewInstance(napi_env env, std::shared_ptr value, bool isSystemAppCalled) { if (value == nullptr) { LOG_ERROR("Value is nullptr ? %{public}d", (value == nullptr)); @@ -265,7 +271,6 @@ napi_value RdbStoreProxy::NewInstance( proxy->dbType = value->GetDbType(); proxy->SetInstance(std::move(value)); proxy->isSystemAppCalled_ = isSystemAppCalled; - proxy->bundleName_ = bundleName; return instance; } @@ -290,329 +295,6 @@ int ParserThis(const napi_env &env, const napi_value &self, std::shared_ptr context) -{ - context->tableName = JSUtils::Convert2String(env, arg); - CHECK_RETURN_SET(!context->tableName.empty(), std::make_shared("table", "not empty string.")); - return OK; -} - -int ParseCursor(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - double cursor = 0; - auto status = JSUtils::Convert2Value(env, arg, cursor); - CHECK_RETURN_SET(status == napi_ok && cursor > 0, std::make_shared("cursor", "valid cursor.")); - context->cursor = static_cast(cursor); - return OK; -} - -int ParseColumnName(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - context->columnName = JSUtils::Convert2String(env, arg); - CHECK_RETURN_SET(!context->columnName.empty(), std::make_shared("columnName", "not empty string.")); - return OK; -} - -int ParsePrimaryKey(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - JSUtils::Convert2Value(env, arg, context->keys); - CHECK_RETURN_SET(!context->keys.empty(), std::make_shared("PRIKey", "number or string.")); - return OK; -} - -int ParseDevice(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - context->device = JSUtils::Convert2String(env, arg); - CHECK_RETURN_SET(!context->device.empty(), std::make_shared("device", "not empty")); - return OK; -} - -int ParseTablesName(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - int32_t ret = JSUtils::Convert2Value(env, arg, context->tablesNames); - CHECK_RETURN_SET(ret == napi_ok, std::make_shared("tablesNames", "not empty string.")); - return OK; -} - -int ParseSyncModeArg(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - napi_valuetype type = napi_undefined; - napi_typeof(env, arg, &type); - CHECK_RETURN_SET(type == napi_number, std::make_shared("mode", "a SyncMode Type.")); - napi_status status = napi_get_value_int32(env, arg, &context->enumArg); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("mode", "a SyncMode Type.")); - bool checked = context->enumArg == 0 || context->enumArg == 1; - CHECK_RETURN_SET(checked, std::make_shared("mode", "a SyncMode of device.")); - return OK; -} - -int ParseDistributedTypeArg( - const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context) -{ - context->distributedType = DistributedRdb::DISTRIBUTED_DEVICE; - if (argc > 1) { - auto status = JSUtils::Convert2ValueExt(env, argv[1], context->distributedType); - bool checked = status == napi_ok && context->distributedType >= DistributedRdb::DISTRIBUTED_DEVICE && - context->distributedType <= DistributedRdb::DISTRIBUTED_CLOUD; - CHECK_RETURN_SET(JSUtils::IsNull(env, argv[1]) || checked, - std::make_shared("distributedType", "a DistributedType")); - } - return OK; -} - -int ParseDistributedConfigArg( - const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context) -{ - context->distributedConfig = { false }; - // '2' Ensure that the incoming argv contains 3 parameter - if (argc > 2) { - auto status = JSUtils::Convert2Value(env, argv[2], context->distributedConfig); - bool checked = status == napi_ok || JSUtils::IsNull(env, argv[2]); - CHECK_RETURN_SET(checked, std::make_shared("distributedConfig", "a DistributedConfig type")); - } - return OK; -} - -int ParseCloudSyncModeArg(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - auto status = JSUtils::Convert2ValueExt(env, arg, context->syncMode); - bool checked = (status == napi_ok && context->syncMode >= DistributedRdb::TIME_FIRST && - context->syncMode <= DistributedRdb::CLOUD_FIRST); - CHECK_RETURN_SET(checked, std::make_shared("mode", "a SyncMode of cloud.")); - return OK; -} - -int ParseCallback(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - napi_valuetype valueType = napi_undefined; - napi_status status = napi_typeof(env, arg, &valueType); - CHECK_RETURN_SET( - (status == napi_ok && valueType == napi_function), std::make_shared("callback", "a function.")); - NAPI_CALL_BASE(env, napi_create_reference(env, arg, 1, &context->callback_), ERR); - return OK; -} - -int ParseCloudSyncCallback(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - napi_valuetype valueType = napi_undefined; - napi_typeof(env, arg, &valueType); - CHECK_RETURN_SET(valueType == napi_function, std::make_shared("progress", "a callback type")); - NAPI_CALL_BASE(env, napi_create_reference(env, arg, 1, &context->asyncHolder), ERR); - return OK; -} - -int ParsePredicates(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - auto status = napi_unwrap(env, arg, reinterpret_cast(&context->predicatesProxy)); - CHECK_RETURN_SET(status == napi_ok && context->predicatesProxy != nullptr, - std::make_shared("predicates", "an RdbPredicates.")); - context->tableName = context->predicatesProxy->GetPredicates()->GetTableName(); - context->rdbPredicates = context->predicatesProxy->GetPredicates(); - return OK; -} - -int ParseDataSharePredicates(const napi_env env, const napi_value arg, std::shared_ptr context) -{ -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) - RdbStoreProxy *obj = reinterpret_cast(context->boundObj); - CHECK_RETURN_SET(obj->IsSystemAppCalled(), std::make_shared()); - PredicatesProxy *proxy = nullptr; - napi_status status = napi_unwrap(env, arg, reinterpret_cast(&proxy)); - bool checked = (status == napi_ok) && (proxy != nullptr) && (proxy->predicates_ != nullptr); - CHECK_RETURN_SET(checked, std::make_shared("predicates", "an DataShare Predicates.")); - - std::shared_ptr dsPredicates = proxy->predicates_; - RdbPredicates rdbPredicates = RdbDataShareAdapter::RdbUtils::ToPredicates(*dsPredicates, context->tableName); - context->rdbPredicates = std::make_shared(rdbPredicates); -#endif - return OK; -} - -int ParseSrcName(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - context->srcName = JSUtils::Convert2String(env, arg); - CHECK_RETURN_SET(!context->srcName.empty(), std::make_shared("srcName", "not empty")); - return OK; -} - -int ParseColumns(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - napi_valuetype type = napi_undefined; - napi_typeof(env, arg, &type); - if (type == napi_undefined || type == napi_null) { - return OK; - } - int32_t ret = JSUtils::Convert2Value(env, arg, context->columns); - CHECK_RETURN_SET(ret == napi_ok, std::make_shared("columns", "a string array")); - return OK; -} - -int ParseBindArgs(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - context->bindArgs.clear(); - napi_valuetype type = napi_undefined; - napi_typeof(env, arg, &type); - if (type == napi_undefined || type == napi_null) { - return OK; - } - bool isArray = false; - napi_status status = napi_is_array(env, arg, &isArray); - CHECK_RETURN_SET(status == napi_ok && isArray, std::make_shared("values", "a BindArgs array.")); - - uint32_t arrLen = 0; - status = napi_get_array_length(env, arg, &arrLen); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("values", "not empty.")); - for (size_t i = 0; i < arrLen; ++i) { - napi_value element = nullptr; - napi_get_element(env, arg, i, &element); - ValueObject valueObject; - int32_t ret = JSUtils::Convert2Value(env, element, valueObject.value); - CHECK_RETURN_SET(ret == OK, std::make_shared(std::to_string(i), "ValueObject")); - // The blob is an empty vector. - // If the API version is less than 14, and insert null. Otherwise, insert an empty vector. - if (valueObject.GetType() == ValueObject::TYPE_BLOB && JSUtils::GetHapVersion() < 14) { - std::vector tmpValue; - valueObject.GetBlob(tmpValue); - if (tmpValue.empty()) { - valueObject = ValueObject(); - } - } - context->bindArgs.push_back(std::move(valueObject)); - } - return OK; -} - -int ParseSql(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - context->sql = JSUtils::Convert2String(env, arg); - CHECK_RETURN_SET(!context->sql.empty(), std::make_shared("sql", "not empty")); - return OK; -} - -int ParseTxId(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - int64_t txId = 0; - auto status = JSUtils::Convert2ValueExt(env, arg, txId); - CHECK_RETURN_SET(status == napi_ok && txId >= 0, std::make_shared("txId", "not invalid txId")); - context->txId = txId; - return OK; -} - -int ParseSendableValuesBucket(const napi_env env, const napi_value map, std::shared_ptr context) -{ - uint32_t length = 0; - napi_status status = napi_map_get_size(env, map, &length); - auto error = std::make_shared("ValuesBucket is invalid."); - CHECK_RETURN_SET(status == napi_ok && length > 0, error); - napi_value entries = nullptr; - status = napi_map_get_entries(env, map, &entries); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_map_get_entries failed.")); - for (uint32_t i = 0; i < length; ++i) { - napi_value iter = nullptr; - status = napi_map_iterator_get_next(env, entries, &iter); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_map_iterator_get_next failed.")); - napi_value values = nullptr; - status = napi_get_named_property(env, iter, "value", &values); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_named_property value failed.")); - napi_value key = nullptr; - status = napi_get_element(env, values, KEY_INDEX, &key); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_element key failed.")); - std::string keyStr = JSUtils::Convert2String(env, key); - napi_value value = nullptr; - status = napi_get_element(env, values, VALUE_INDEX, &value); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_element value failed.")); - ValueObject valueObject; - int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value); - if (ret == napi_ok) { - context->valuesBucket.Put(keyStr, valueObject); - } else if (ret != napi_generic_failure) { - CHECK_RETURN_SET(false, std::make_shared("The value type of " + keyStr, "invalid.")); - } - } - return OK; -} - -int ParseValuesBucket(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - bool isMap = false; - napi_status status = napi_is_map(env, arg, &isMap); - CHECK_RETURN_SET( - status == napi_ok, std::make_shared("call napi_is_map failed" + std::to_string(status))); - if (isMap) { - return ParseSendableValuesBucket(env, arg, context); - } - napi_value keys = nullptr; - napi_get_all_property_names(env, arg, napi_key_own_only, - static_cast(napi_key_enumerable | napi_key_skip_symbols), napi_key_numbers_to_strings, &keys); - uint32_t arrLen = 0; - status = napi_get_array_length(env, keys, &arrLen); - CHECK_RETURN_SET(status == napi_ok && arrLen > 0, std::make_shared("ValuesBucket is invalid")); - - for (size_t i = 0; i < arrLen; ++i) { - napi_value key = nullptr; - status = napi_get_element(env, keys, i, &key); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("ValuesBucket is invalid.")); - std::string keyStr = JSUtils::Convert2String(env, key); - napi_value value = nullptr; - napi_get_property(env, arg, key, &value); - ValueObject valueObject; - int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value); - // The blob is an empty vector. - // If the API version is less than 14, and insert null. Otherwise, insert an empty vector. - if (ret == napi_ok && valueObject.GetType() == ValueObject::TYPE_BLOB && JSUtils::GetHapVersion() < 14) { - std::vector tmpValue; - valueObject.GetBlob(tmpValue); - if (tmpValue.empty()) { - valueObject = ValueObject(); - } - auto proxy = reinterpret_cast(context->boundObj); - if (tmpValue.empty() && (proxy != nullptr)) { - Reportor::ReportFault(RdbEmptyBlobEvent(proxy->GetBundleName())); - } - } - if (ret == napi_ok) { - context->valuesBucket.Put(keyStr, valueObject); - } else if (ret != napi_generic_failure) { - CHECK_RETURN_SET(false, std::make_shared("The value type of " + keyStr, "invalid.")); - } - } - return OK; -} - -int ParseValuesBuckets(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - bool isArray = false; - napi_is_array(env, arg, &isArray); - CHECK_RETURN_SET(isArray, std::make_shared("ValuesBuckets is invalid.")); - - uint32_t arrLen = 0; - napi_status status = napi_get_array_length(env, arg, &arrLen); - CHECK_RETURN_SET(status == napi_ok && arrLen > 0, std::make_shared("ValuesBuckets is invalid.")); - - for (uint32_t i = 0; i < arrLen; ++i) { - napi_value obj = nullptr; - status = napi_get_element(env, arg, i, &obj); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_element failed.")); - - CHECK_RETURN_ERR(ParseValuesBucket(env, obj, context) == OK); - context->sharedValuesBuckets.Put(context->valuesBucket); - context->valuesBucket.Clear(); - } - return OK; -} - -int ParseConflictResolution(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - int32_t conflictResolution = 0; - napi_get_value_int32(env, arg, &conflictResolution); - int32_t min = static_cast(NativeRdb::ConflictResolution::ON_CONFLICT_NONE); - int32_t max = static_cast(NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE); - bool checked = (conflictResolution >= min) && (conflictResolution <= max); - CHECK_RETURN_SET(checked, std::make_shared("conflictResolution", "a ConflictResolution.")); - context->conflictResolution = static_cast(conflictResolution); - return OK; -} - napi_value RdbStoreProxy::Insert(napi_env env, napi_callback_info info) { auto context = std::make_shared(); @@ -643,17 +325,6 @@ napi_value RdbStoreProxy::Insert(napi_env env, napi_callback_info info) return ASYNC_CALL(env, context); } -int ParseTransactionOptions( - const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context) -{ - context->transactionOptions.transactionType = Transaction::DEFERRED; - if (argc > 0 && !JSUtils::IsNull(env, argv[0])) { - auto status = JSUtils::Convert2Value(env, argv[0], context->transactionOptions); - CHECK_RETURN_SET(status == napi_ok, std::make_shared("options", "a transactionOptions")); - } - return OK; -} - napi_value RdbStoreProxy::BatchInsert(napi_env env, napi_callback_info info) { auto context = std::make_shared(); @@ -701,8 +372,8 @@ napi_value RdbStoreProxy::BatchInsertWithConflictResolution(napi_env env, napi_c auto exec = [context]() -> int { CHECK_RETURN_ERR(context->rdbStore != nullptr); auto rdbStore = std::move(context->rdbStore); - auto [ret, output] = rdbStore->BatchInsertWithConflictResolution( - context->tableName, context->sharedValuesBuckets, context->conflictResolution); + auto [ret, output] = + rdbStore->BatchInsert(context->tableName, context->sharedValuesBuckets, context->conflictResolution); context->int64Output = output; return ret; }; @@ -715,6 +386,23 @@ napi_value RdbStoreProxy::BatchInsertWithConflictResolution(napi_env env, napi_c return ASYNC_CALL(env, context); } +int ParseDataSharePredicates(const napi_env env, const napi_value arg, std::shared_ptr context) +{ +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) + RdbStoreProxy *obj = reinterpret_cast(context->boundObj); + CHECK_RETURN_SET(obj->IsSystemAppCalled(), std::make_shared()); + PredicatesProxy *proxy = nullptr; + napi_status status = napi_unwrap(env, arg, reinterpret_cast(&proxy)); + bool checked = (status == napi_ok) && (proxy != nullptr) && (proxy->predicates_ != nullptr); + CHECK_RETURN_SET(checked, std::make_shared("predicates", "an DataShare Predicates.")); + + std::shared_ptr dsPredicates = proxy->predicates_; + RdbPredicates rdbPredicates = RdbDataShareAdapter::RdbUtils::ToPredicates(*dsPredicates, context->tableName); + context->rdbPredicates = std::make_shared(rdbPredicates); +#endif + return OK; +} + napi_value RdbStoreProxy::Delete(napi_env env, napi_callback_info info) { auto context = std::make_shared(); @@ -810,8 +498,7 @@ napi_value RdbStoreProxy::Query(napi_env env, napi_callback_info info) context->resultSet = context->rdbStore->Query(*(context->rdbPredicates), context->columns); #endif context->rdbStore = nullptr; - // If the API version is greater than or equal to 20, throw E_ALREADY_CLOSED. - return (context->resultSet != nullptr) ? E_OK : (JSUtils::GetHapVersion() >= 20) ? E_ALREADY_CLOSED : E_ERROR; + return (context->resultSet != nullptr) ? E_OK : E_ERROR; }; auto output = [context](napi_env env, napi_value &result) { result = ResultSetProxy::NewInstance(env, std::move(context->resultSet)); @@ -881,8 +568,7 @@ napi_value RdbStoreProxy::QuerySql(napi_env env, napi_callback_info info) context->resultSet = context->rdbStore->QuerySql(context->sql, context->bindArgs); #endif context->rdbStore = nullptr; - // If the API version is greater than or equal to 20, throw E_ALREADY_CLOSED. - return (context->resultSet != nullptr) ? E_OK : (JSUtils::GetHapVersion() >= 20) ? E_ALREADY_CLOSED : E_ERROR; + return (context->resultSet != nullptr) ? E_OK : E_ERROR; }; auto output = [context](napi_env env, napi_value &result) { result = ResultSetProxy::NewInstance(env, std::move(context->resultSet)); @@ -1272,8 +958,7 @@ napi_value RdbStoreProxy::QueryByStep(napi_env env, napi_callback_info info) auto rdbStore = std::move(context->rdbStore); context->resultSet = context->isQuerySql ? rdbStore->QueryByStep(context->sql, context->bindArgs) : rdbStore->QueryByStep(*(context->rdbPredicates), context->columns); - // If the API version is greater than or equal to 20, throw E_ALREADY_CLOSED. - return (context->resultSet != nullptr) ? E_OK : (JSUtils::GetHapVersion() >= 20) ? E_ALREADY_CLOSED : E_ERROR; + return (context->resultSet != nullptr) ? E_OK : E_ERROR; }; auto output = [context](napi_env env, napi_value &result) { result = ResultSetProxy::NewInstance(env, std::move(context->resultSet)); @@ -1358,43 +1043,25 @@ napi_value RdbStoreProxy::Restore(napi_env env, napi_callback_info info) return ASYNC_CALL(env, context); } -#if !defined(CROSS_PLATFORM) -void RdbStoreProxy::AddDistributedFunctions(std::vector &properties) -{ - properties.push_back(DECLARE_NAPI_FUNCTION("remoteQuery", RemoteQuery)); - properties.push_back(DECLARE_NAPI_FUNCTION("setDistributedTables", SetDistributedTables)); - properties.push_back(DECLARE_NAPI_FUNCTION("obtainDistributedTableName", ObtainDistributedTableName)); - properties.push_back(DECLARE_NAPI_FUNCTION("sync", Sync)); - properties.push_back(DECLARE_NAPI_FUNCTION("cloudSync", CloudSync)); - properties.push_back(DECLARE_NAPI_FUNCTION("getModifyTime", GetModifyTime)); - properties.push_back(DECLARE_NAPI_FUNCTION("cleanDirtyData", CleanDirtyData)); - properties.push_back(DECLARE_NAPI_FUNCTION("on", OnEvent)); - properties.push_back(DECLARE_NAPI_FUNCTION("off", OffEvent)); - properties.push_back(DECLARE_NAPI_FUNCTION("emit", Notify)); - properties.push_back(DECLARE_NAPI_FUNCTION("querySharingResource", QuerySharingResource)); - properties.push_back(DECLARE_NAPI_FUNCTION("lockRow", LockRow)); - properties.push_back(DECLARE_NAPI_FUNCTION("unlockRow", UnlockRow)); - properties.push_back(DECLARE_NAPI_FUNCTION("queryLockedRow", QueryLockedRow)); - properties.push_back(DECLARE_NAPI_FUNCTION("lockCloudContainer", LockCloudContainer)); - properties.push_back(DECLARE_NAPI_FUNCTION("unlockCloudContainer", UnlockCloudContainer)); -} - -napi_value RdbStoreProxy::SetDistributedTables(napi_env env, napi_callback_info info) +napi_value RdbStoreProxy::Rekey(napi_env env, napi_callback_info info) { + LOG_INFO("RdbStoreProxy::Rekey start."); auto context = std::make_shared(); auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(1 <= argc && argc <= 3, std::make_shared("1 - 4")); + CHECK_RETURN_SET_E(argc >= 0 && argc <= 1, std::make_shared("0 - 1")); CHECK_RETURN(OK == ParserThis(env, self, context)); - CHECK_RETURN(OK == ParseTablesName(env, argv[0], context)); - CHECK_RETURN(OK == ParseDistributedTypeArg(env, argc, argv, context)); - CHECK_RETURN(OK == ParseDistributedConfigArg(env, argc, argv, context)); + if (argc == 1 && !JSUtils::IsNull(env, argv[0])) { + CHECK_RETURN(OK == ParseCryptoParam(env, argv[0], context)); + } + CHECK_RETURN_SET_E(context->cryptoParam.IsValid(), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Illegal CryptoParam.")); }; auto exec = [context]() -> int { CHECK_RETURN_ERR(context->rdbStore != nullptr); auto rdbStore = std::move(context->rdbStore); - return rdbStore->SetDistributedTables( - context->tablesNames, context->distributedType, context->distributedConfig); + return rdbStore->Rekey(context->cryptoParam); }; + auto output = [context](napi_env env, napi_value &result) { napi_status status = napi_get_undefined(env, &result); CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); @@ -1405,29 +1072,26 @@ napi_value RdbStoreProxy::SetDistributedTables(napi_env env, napi_callback_info return ASYNC_CALL(env, context); } -napi_value RdbStoreProxy::ObtainDistributedTableName(napi_env env, napi_callback_info info) +napi_value RdbStoreProxy::SetLocale(napi_env env, napi_callback_info info) { auto context = std::make_shared(); auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(argc == 2, std::make_shared("2 or 3")); + CHECK_RETURN_SET_E(argc == 1, std::make_shared("1")); CHECK_RETURN(OK == ParserThis(env, self, context)); - CHECK_RETURN(OK == ParseDevice(env, argv[0], context)); - CHECK_RETURN(OK == ParseTableName(env, argv[1], context)); + CHECK_RETURN(OK == ParseSrcType(env, argv[0], context)); + CHECK_RETURN_SET_E(!context->srcName.empty(), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "locale cannot be empty")); }; auto exec = [context]() -> int { - LOG_DEBUG("RdbStoreProxy::ObtainDistributedTableName Async."); CHECK_RETURN_ERR(context->rdbStore != nullptr); - int errCode = E_ERROR; - context->tableName = - context->rdbStore->ObtainDistributedTableName(context->device, context->tableName, errCode); - context->rdbStore = nullptr; + auto rdbStore = std::move(context->rdbStore); + auto errCode = rdbStore->ConfigLocale(context->srcName); return errCode; }; + auto output = [context](napi_env env, napi_value &result) { - std::string table = context->tableName; - napi_status status = napi_create_string_utf8(env, table.c_str(), table.length(), &result); + napi_status status = napi_get_undefined(env, &result); CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); - LOG_DEBUG("RdbStoreProxy::ObtainDistributedTableName end."); }; context->SetAction(env, info, input, exec, output); @@ -1435,58 +1099,420 @@ napi_value RdbStoreProxy::ObtainDistributedTableName(napi_env env, napi_callback return ASYNC_CALL(env, context); } -napi_value RdbStoreProxy::Sync(napi_env env, napi_callback_info info) +napi_value RdbStoreProxy::OnEvent(napi_env env, napi_callback_info info) { - auto context = std::make_shared(); - auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - CHECK_RETURN_SET_E(argc == 2, std::make_shared("2 or 3")); - CHECK_RETURN(OK == ParserThis(env, self, context)); - CHECK_RETURN(OK == ParseSyncModeArg(env, argv[0], context)); - CHECK_RETURN(OK == ParsePredicates(env, argv[1], context)); - }; - context->SetAction(env, info, std::move(input), nullptr, nullptr); - CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); - RdbStoreProxy *obj = reinterpret_cast(context->boundObj); - auto queue = obj->queue_; - napi_value promise = nullptr; - auto defer = context->defer_; - auto callback = context->callback_; - context->callback_ = nullptr; - if (callback == nullptr) { - napi_status status = napi_create_promise(env, &defer, &promise); - RDB_NAPI_ASSERT_BASE(env, status == napi_ok, - std::make_shared("failed(" + std::to_string(status) + ") to create promise"), nullptr); - } else { - napi_get_undefined(env, &promise); - } - auto predicates = *context->predicatesProxy->GetPredicates(); - auto exec = [queue, defer, callback, predicates, rdbStore = std::move(context->rdbStore), - enumArg = context->enumArg]() mutable { - SyncOption option{ static_cast(enumArg), false }; - auto ret = rdbStore->Sync(option, predicates, [queue, defer, callback](const SyncResult &result) { - auto args = [result](napi_env env, int &argc, napi_value *argv) { - argv[1] = JSUtils::Convert2JSValue(env, result); - }; - callback ? queue->AsyncCall({ callback }, args) : queue->AsyncPromise({ defer }, args); - }); - if (ret != NativeRdb::E_OK) { - auto args = [ret](napi_env env, int &argc, napi_value *argv) mutable { - SetBusinessError(env, std::make_shared(ret), &argv[0]); - }; - callback ? queue->AsyncCall({ callback }, args) : queue->AsyncPromise({ defer }, args); - } - }; - queue->Execute(std::move(exec)); - context = nullptr; - return promise; -} + size_t argc = 3; + napi_value argv[3]{}; + napi_value self = nullptr; + int32_t status = napi_get_cb_info(env, info, &argc, argv, &self, nullptr); + // 'argc == 3 || argc == 2' represents the number of parameters is three or two + RDB_NAPI_ASSERT(env, status == napi_ok && (argc == 3 || argc == 2), std::make_shared("2 or 3")); -void RdbStoreProxy::SetBusinessError(napi_env env, std::shared_ptr error, napi_value *businessError) -{ - if (error != nullptr) { - napi_value code = nullptr; - napi_value msg = nullptr; - napi_create_int32(env, error->GetCode(), &code); + auto proxy = GetNativeInstance(env, self); + RDB_NAPI_ASSERT(env, proxy != nullptr, std::make_shared("RdbStore", "valid")); + RDB_NAPI_ASSERT(env, proxy->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); + + std::string event; + // 'argv[0]' represents a event + status = JSUtils::Convert2Value(env, argv[0], event); + RDB_NAPI_ASSERT( + env, status == napi_ok && !event.empty(), std::make_shared("event", "a not empty string.")); + for (auto &eventInfo : onEventHandlers_) { + if (eventInfo.event == event) { + return (proxy->*(eventInfo.handle))(env, argc - 1, argv + 1); + } + } + // 'argc == 3' represents the number of parameters is three + RDB_NAPI_ASSERT(env, status == napi_ok && argc == 3, std::make_shared("3")); + bool valueBool = false; + status = JSUtils::Convert2Value(env, argv[1], valueBool); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("interProcess", "a boolean.")); + napi_valuetype type = napi_undefined; + // 'argv[2]' is observer function + napi_typeof(env, argv[2], &type); + RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("observer", "function")); + DistributedRdb::SubscribeOption option; + option.event = event; + option.mode = valueBool ? DistributedRdb::SubscribeMode::LOCAL_SHARED : DistributedRdb::SubscribeMode::LOCAL; + // 'argv[2]' represents a callback function + return proxy->RegisteredObserver(env, option, argv[2]); +} + +napi_value RdbStoreProxy::OffEvent(napi_env env, napi_callback_info info) +{ + size_t argc = 3; + // 'argv[3]' represents an array containing three elements + napi_value argv[3] = { nullptr }; + napi_value self = nullptr; + int32_t status = napi_get_cb_info(env, info, &argc, argv, &self, nullptr); + // '1 <= argc && argc <= 3' represents the number of parameters is 1 - 3 + RDB_NAPI_ASSERT(env, status == napi_ok && 1 <= argc && argc <= 3, std::make_shared("1 - 3")); + + auto proxy = GetNativeInstance(env, self); + RDB_NAPI_ASSERT(env, proxy != nullptr, std::make_shared("RdbStore", "valid")); + RDB_NAPI_ASSERT(env, proxy->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); + + std::string event; + status = JSUtils::Convert2Value(env, argv[0], event); + RDB_NAPI_ASSERT( + env, status == napi_ok && !event.empty(), std::make_shared("event", "a not empty string.")); + for (auto &eventInfo : offEventHandlers_) { + if (eventInfo.event == event) { + return (proxy->*(eventInfo.handle))(env, argc - 1, argv + 1); + } + } + // 'argc >= 2' represents the number of parameters is two or three + RDB_NAPI_ASSERT(env, status == napi_ok && argc >= 2, std::make_shared("2 or 3")); + bool valueBool = false; + status = JSUtils::Convert2Value(env, argv[1], valueBool); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("interProcess", "a boolean.")); + + // 'argc == 3' represents determine whether the value of variable 'argc' is equal to '3' + if (argc == 3) { + napi_valuetype type = napi_undefined; + // 'argv[2]' represents a callback function + napi_typeof(env, argv[2], &type); + RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("observer", "function")); + } + SubscribeOption option; + option.event = event; + valueBool ? option.mode = SubscribeMode::LOCAL_SHARED : option.mode = SubscribeMode::LOCAL; + // 'argv[2]' represents a callback function, 'argc == 3' represents determine if 'argc' is equal to '3' + return proxy->UnRegisteredObserver(env, option, argc == 3 ? argv[2] : nullptr); +} + +napi_value RdbStoreProxy::OnStatistics(napi_env env, size_t argc, napi_value *argv) +{ + napi_valuetype type = napi_undefined; + napi_typeof(env, argv[0], &type); + RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("statistics", "function")); + bool result = std::any_of(statisticses_.begin(), statisticses_.end(), + [argv](std::shared_ptr obs) { return obs && *obs == argv[0]; }); + if (result) { + LOG_DEBUG("Duplicate subscribe."); + return nullptr; + } + auto observer = std::make_shared(env, argv[0], queue_); + int errCode = DistributedRdb::SqlStatistic::Subscribe(observer); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + statisticses_.push_back(std::move(observer)); + LOG_INFO("Statistics subscribe success."); + return nullptr; +} + +napi_value RdbStoreProxy::OffStatistics(napi_env env, size_t argc, napi_value *argv) +{ + napi_valuetype type; + napi_typeof(env, argv[0], &type); + RDB_NAPI_ASSERT(env, type == napi_function || type == napi_undefined || type == napi_null, + std::make_shared("statistics", "function")); + + auto it = statisticses_.begin(); + while (it != statisticses_.end()) { + if (*it == nullptr) { + it = statisticses_.erase(it); + LOG_WARN("statisticsObserver is nullptr."); + continue; + } + if (type == napi_function && !(**it == argv[0])) { + ++it; + continue; + } + int errCode = DistributedRdb::SqlStatistic::Unsubscribe(*it); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + (*it)->Clear(); + it = statisticses_.erase(it); + } + return nullptr; +} + +napi_value RdbStoreProxy::OnPerfStat(napi_env env, size_t argc, napi_value *argv) +{ + RDB_NAPI_ASSERT(env, this->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); + int32_t dbType = this->GetInstance()->GetDbType(); + RDB_NAPI_ASSERT(env, dbType == DB_SQLITE, std::make_shared(NativeRdb::E_NOT_SUPPORT)); + napi_valuetype type = napi_undefined; + napi_typeof(env, argv[0], &type); + RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("perfStat", "function")); + bool result = std::any_of(perfStats_.begin(), perfStats_.end(), + [argv](std::shared_ptr obs) { return obs && *obs == argv[0]; }); + if (result) { + LOG_DEBUG("Duplicate subscribe."); + return nullptr; + } + auto observer = std::make_shared(env, argv[0], queue_); + std::string path = this->GetInstance()->GetPath(); + int errCode = DistributedRdb::PerfStat::Subscribe(path, observer); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + perfStats_.push_back(std::move(observer)); + LOG_DEBUG("perfStats_ subscribe success."); + return nullptr; +} + +napi_value RdbStoreProxy::OffPerfStat(napi_env env, size_t argc, napi_value *argv) +{ + RDB_NAPI_ASSERT(env, this->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); + int32_t dbType = this->GetInstance()->GetDbType(); + RDB_NAPI_ASSERT(env, dbType == DB_SQLITE, std::make_shared(NativeRdb::E_NOT_SUPPORT)); + napi_valuetype type; + napi_typeof(env, argv[0], &type); + RDB_NAPI_ASSERT(env, type == napi_function || type == napi_undefined || type == napi_null, + std::make_shared("perfStat", "function")); + + auto it = perfStats_.begin(); + while (it != perfStats_.end()) { + if (*it == nullptr) { + it = perfStats_.erase(it); + LOG_WARN("perfStatsObserver is nullptr."); + continue; + } + if (type == napi_function && !(**it == argv[0])) { + ++it; + continue; + } + std::string path = this->GetInstance()->GetPath(); + int errCode = DistributedRdb::PerfStat::Unsubscribe(path, *it); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + (*it)->Clear(); + it = perfStats_.erase(it); + } + return nullptr; +} + +napi_value RdbStoreProxy::OnErrorLog(napi_env env, size_t argc, napi_value *argv) +{ + RDB_NAPI_ASSERT(env, this->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); + int32_t dbType = this->GetInstance()->GetDbType(); + RDB_NAPI_ASSERT(env, dbType == DB_SQLITE, std::make_shared(NativeRdb::E_NOT_SUPPORT)); + napi_valuetype type = napi_undefined; + napi_typeof(env, argv[0], &type); + RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("sqliteErrorOccurred", "function")); + bool result = std::any_of(logObservers_.begin(), logObservers_.end(), + [argv](std::shared_ptr obs) { return obs && *obs == argv[0]; }); + if (result) { + LOG_DEBUG("Duplicate subscribe."); + return nullptr; + } + auto observer = std::make_shared(env, argv[0], queue_); + std::string dbPath = this->GetInstance()->GetPath(); + int errCode = NativeRdb::SqlLog::Subscribe(dbPath, observer); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + logObservers_.push_back(std::move(observer)); + LOG_DEBUG("sqliteErrorOccurred subscribe success."); + return nullptr; +} + +napi_value RdbStoreProxy::OffErrorLog(napi_env env, size_t argc, napi_value *argv) +{ + RDB_NAPI_ASSERT(env, this->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); + int32_t dbType = this->GetInstance()->GetDbType(); + RDB_NAPI_ASSERT(env, dbType == DB_SQLITE, std::make_shared(NativeRdb::E_NOT_SUPPORT)); + napi_valuetype type; + napi_typeof(env, argv[0], &type); + RDB_NAPI_ASSERT(env, type == napi_function || type == napi_undefined || type == napi_null, + std::make_shared("sqliteErrorOccurred", "function")); + + auto it = logObservers_.begin(); + while (it != logObservers_.end()) { + if (*it == nullptr) { + it = logObservers_.erase(it); + LOG_WARN("logObserver is nullptr."); + continue; + } + if (type == napi_function && !(**it == argv[0])) { + ++it; + continue; + } + std::string dbPath = this->GetInstance()->GetPath(); + int errCode = NativeRdb::SqlLog::Unsubscribe(dbPath, *it); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + (*it)->Clear(); + it = logObservers_.erase(it); + } + return nullptr; +} + +napi_value RdbStoreProxy::RegisteredObserver( + napi_env env, const DistributedRdb::SubscribeOption &option, napi_value callback) +{ + auto &observers = option.mode == SubscribeMode::LOCAL ? localObservers_ : localSharedObservers_; + observers.try_emplace(option.event); + auto &list = observers.find(option.event)->second; + bool result = + std::any_of(list.begin(), list.end(), [callback](const auto &observer) { return *observer == callback; }); + if (result) { + LOG_INFO("Duplicate subscribe event: %{public}s", option.event.c_str()); + return nullptr; + } + + auto uvQueue = std::make_shared(env); + auto localObserver = std::make_shared(callback, uvQueue); + int errCode = GetInstance()->Subscribe(option, localObserver); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + observers[option.event].push_back(localObserver); + LOG_INFO("Subscribe success event: %{public}s", option.event.c_str()); + return nullptr; +} + +napi_value RdbStoreProxy::UnRegisteredObserver( + napi_env env, const DistributedRdb::SubscribeOption &option, napi_value callback) +{ + auto &observers = option.mode == SubscribeMode::LOCAL ? localObservers_ : localSharedObservers_; + auto obs = observers.find(option.event); + if (obs == observers.end()) { + LOG_INFO("Observer not found, event: %{public}s", option.event.c_str()); + return nullptr; + } + + if (callback) { + auto &list = obs->second; + for (auto it = list.begin(); it != list.end(); it++) { + if (**it == callback) { + int errCode = GetInstance()->UnSubscribe(option, *it); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + list.erase(it); + break; + } + } + if (list.empty()) { + observers.erase(option.event); + } + } else { + int errCode = GetInstance()->UnSubscribe(option, nullptr); + RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); + observers.erase(option.event); + } + LOG_INFO("Unsubscribe success, event: %{public}s", option.event.c_str()); + return nullptr; +} + +#if !defined(CROSS_PLATFORM) +void RdbStoreProxy::AddDistributedFunctions(std::vector &properties) +{ + properties.push_back(DECLARE_NAPI_FUNCTION("remoteQuery", RemoteQuery)); + properties.push_back(DECLARE_NAPI_FUNCTION("setDistributedTables", SetDistributedTables)); + properties.push_back(DECLARE_NAPI_FUNCTION("obtainDistributedTableName", ObtainDistributedTableName)); + properties.push_back(DECLARE_NAPI_FUNCTION("sync", Sync)); + properties.push_back(DECLARE_NAPI_FUNCTION("cloudSync", CloudSync)); + properties.push_back(DECLARE_NAPI_FUNCTION("getModifyTime", GetModifyTime)); + properties.push_back(DECLARE_NAPI_FUNCTION("cleanDirtyData", CleanDirtyData)); + properties.push_back(DECLARE_NAPI_FUNCTION("emit", Notify)); + properties.push_back(DECLARE_NAPI_FUNCTION("querySharingResource", QuerySharingResource)); + properties.push_back(DECLARE_NAPI_FUNCTION("lockRow", LockRow)); + properties.push_back(DECLARE_NAPI_FUNCTION("unlockRow", UnlockRow)); + properties.push_back(DECLARE_NAPI_FUNCTION("queryLockedRow", QueryLockedRow)); + properties.push_back(DECLARE_NAPI_FUNCTION("lockCloudContainer", LockCloudContainer)); + properties.push_back(DECLARE_NAPI_FUNCTION("unlockCloudContainer", UnlockCloudContainer)); +} + +napi_value RdbStoreProxy::SetDistributedTables(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + CHECK_RETURN_SET_E(1 <= argc && argc <= 3, std::make_shared("1 - 4")); + CHECK_RETURN(OK == ParserThis(env, self, context)); + CHECK_RETURN(OK == ParseTablesName(env, argv[0], context)); + CHECK_RETURN(OK == ParseDistributedTypeArg(env, argc, argv, context)); + CHECK_RETURN(OK == ParseDistributedConfigArg(env, argc, argv, context)); + }; + auto exec = [context]() -> int { + CHECK_RETURN_ERR(context->rdbStore != nullptr); + auto rdbStore = std::move(context->rdbStore); + return rdbStore->SetDistributedTables( + context->tablesNames, context->distributedType, context->distributedConfig); + }; + auto output = [context](napi_env env, napi_value &result) { + napi_status status = napi_get_undefined(env, &result); + CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); + }; + context->SetAction(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return ASYNC_CALL(env, context); +} + +napi_value RdbStoreProxy::ObtainDistributedTableName(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + CHECK_RETURN_SET_E(argc == 2, std::make_shared("2 or 3")); + CHECK_RETURN(OK == ParserThis(env, self, context)); + CHECK_RETURN(OK == ParseDevice(env, argv[0], context)); + CHECK_RETURN(OK == ParseTableName(env, argv[1], context)); + }; + auto exec = [context]() -> int { + LOG_DEBUG("RdbStoreProxy::ObtainDistributedTableName Async."); + CHECK_RETURN_ERR(context->rdbStore != nullptr); + int errCode = E_ERROR; + context->tableName = + context->rdbStore->ObtainDistributedTableName(context->device, context->tableName, errCode); + context->rdbStore = nullptr; + return errCode; + }; + auto output = [context](napi_env env, napi_value &result) { + std::string table = context->tableName; + napi_status status = napi_create_string_utf8(env, table.c_str(), table.length(), &result); + CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); + LOG_DEBUG("RdbStoreProxy::ObtainDistributedTableName end."); + }; + context->SetAction(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return ASYNC_CALL(env, context); +} + +napi_value RdbStoreProxy::Sync(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + CHECK_RETURN_SET_E(argc == 2, std::make_shared("2 or 3")); + CHECK_RETURN(OK == ParserThis(env, self, context)); + CHECK_RETURN(OK == ParseSyncModeArg(env, argv[0], context)); + CHECK_RETURN(OK == ParsePredicates(env, argv[1], context)); + }; + context->SetAction(env, info, std::move(input), nullptr, nullptr); + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + RdbStoreProxy *obj = reinterpret_cast(context->boundObj); + auto queue = obj->queue_; + napi_value promise = nullptr; + auto defer = context->defer_; + auto callback = context->callback_; + context->callback_ = nullptr; + if (callback == nullptr) { + napi_status status = napi_create_promise(env, &defer, &promise); + RDB_NAPI_ASSERT_BASE(env, status == napi_ok, + std::make_shared("failed(" + std::to_string(status) + ") to create promise"), nullptr); + } else { + napi_get_undefined(env, &promise); + } + auto predicates = *context->predicatesProxy->GetPredicates(); + auto exec = [queue, defer, callback, predicates, rdbStore = std::move(context->rdbStore), + enumArg = context->enumArg]() mutable { + SyncOption option{ static_cast(enumArg), false }; + auto ret = rdbStore->Sync(option, predicates, [queue, defer, callback](const SyncResult &result) { + auto args = [result](napi_env env, int &argc, napi_value *argv) { + argv[1] = JSUtils::Convert2JSValue(env, result); + }; + callback ? queue->AsyncCall({ callback }, args) : queue->AsyncPromise({ defer }, args); + }); + if (ret != NativeRdb::E_OK) { + auto args = [ret](napi_env env, int &argc, napi_value *argv) mutable { + SetBusinessError(env, std::make_shared(ret), &argv[0]); + }; + callback ? queue->AsyncCall({ callback }, args) : queue->AsyncPromise({ defer }, args); + } + }; + queue->Execute(std::move(exec)); + context = nullptr; + return promise; +} + +void RdbStoreProxy::SetBusinessError(napi_env env, std::shared_ptr error, napi_value *businessError) +{ + if (error != nullptr) { + napi_value code = nullptr; + napi_value msg = nullptr; + napi_create_int32(env, error->GetCode(), &code); napi_create_string_utf8(env, error->GetMessage().c_str(), NAPI_AUTO_LENGTH, &msg); napi_create_error(env, code, msg, businessError); } @@ -1624,6 +1650,9 @@ napi_value RdbStoreProxy::CleanDirtyData(napi_env env, napi_callback_info info) napi_value RdbStoreProxy::OnRemote(napi_env env, size_t argc, napi_value *argv) { + // argc must be greater than or equal to 2 to be valid + RDB_NAPI_ASSERT(env, argc >= 2 && argv != nullptr, + std::make_shared(" argc is less than 2 or argv is nullptr")); napi_valuetype type = napi_undefined; int32_t mode = SubscribeMode::SUBSCRIBE_MODE_MAX; napi_get_value_int32(env, argv[0], &mode); @@ -1648,7 +1677,7 @@ napi_value RdbStoreProxy::OnRemote(napi_env env, size_t argc, napi_value *argv) if (option.mode == SubscribeMode::LOCAL_DETAIL) { errCode = GetInstance()->SubscribeObserver(option, observer); } else { - errCode = GetInstance()->Subscribe(option, observer.get()); + errCode = GetInstance()->Subscribe(option, observer); } RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); observers_[mode].push_back(observer); @@ -1656,28 +1685,6 @@ napi_value RdbStoreProxy::OnRemote(napi_env env, size_t argc, napi_value *argv) return nullptr; } -napi_value RdbStoreProxy::RegisteredObserver( - napi_env env, const DistributedRdb::SubscribeOption &option, napi_value callback) -{ - auto &observers = option.mode == SubscribeMode::LOCAL ? localObservers_ : localSharedObservers_; - observers.try_emplace(option.event); - auto &list = observers.find(option.event)->second; - bool result = - std::any_of(list.begin(), list.end(), [callback](const auto &observer) { return *observer == callback; }); - if (result) { - LOG_INFO("Duplicate subscribe event: %{public}s", option.event.c_str()); - return nullptr; - } - - auto uvQueue = std::make_shared(env); - auto localObserver = std::make_shared(callback, uvQueue); - int errCode = GetInstance()->Subscribe(option, localObserver.get()); - RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); - observers[option.event].push_back(localObserver); - LOG_INFO("Subscribe success event: %{public}s", option.event.c_str()); - return nullptr; -} - napi_value RdbStoreProxy::OffRemote(napi_env env, size_t argc, napi_value *argv) { napi_valuetype type = napi_undefined; @@ -1711,7 +1718,7 @@ napi_value RdbStoreProxy::OffRemote(napi_env env, size_t argc, napi_value *argv) if (option.mode == SubscribeMode::LOCAL_DETAIL) { errCode = GetInstance()->UnsubscribeObserver(option, *it); } else { - errCode = GetInstance()->UnSubscribe(option, it->get()); + errCode = GetInstance()->UnSubscribe(option, *it); } RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); (*it)->Clear(); @@ -1721,118 +1728,6 @@ napi_value RdbStoreProxy::OffRemote(napi_env env, size_t argc, napi_value *argv) return nullptr; } -napi_value RdbStoreProxy::UnRegisteredObserver( - napi_env env, const DistributedRdb::SubscribeOption &option, napi_value callback) -{ - auto &observers = option.mode == SubscribeMode::LOCAL ? localObservers_ : localSharedObservers_; - auto obs = observers.find(option.event); - if (obs == observers.end()) { - LOG_INFO("Observer not found, event: %{public}s", option.event.c_str()); - return nullptr; - } - - if (callback) { - auto &list = obs->second; - for (auto it = list.begin(); it != list.end(); it++) { - if (**it == callback) { - int errCode = GetInstance()->UnSubscribe(option, it->get()); - RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); - list.erase(it); - break; - } - } - if (list.empty()) { - observers.erase(option.event); - } - } else { - int errCode = GetInstance()->UnSubscribe(option, nullptr); - RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); - observers.erase(option.event); - } - LOG_INFO("Unsubscribe success, event: %{public}s", option.event.c_str()); - return nullptr; -} - -napi_value RdbStoreProxy::OnEvent(napi_env env, napi_callback_info info) -{ - size_t argc = 3; - napi_value argv[3]{}; - napi_value self = nullptr; - int32_t status = napi_get_cb_info(env, info, &argc, argv, &self, nullptr); - // 'argc == 3 || argc == 2' represents the number of parameters is three or two - RDB_NAPI_ASSERT(env, status == napi_ok && (argc == 3 || argc == 2), std::make_shared("2 or 3")); - - auto proxy = GetNativeInstance(env, self); - RDB_NAPI_ASSERT(env, proxy != nullptr, std::make_shared("RdbStore", "valid")); - RDB_NAPI_ASSERT(env, proxy->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); - - std::string event; - // 'argv[0]' represents a event - status = JSUtils::Convert2Value(env, argv[0], event); - RDB_NAPI_ASSERT( - env, status == napi_ok && !event.empty(), std::make_shared("event", "a not empty string.")); - for (auto &eventInfo : onEventHandlers_) { - if (eventInfo.event == event) { - return (proxy->*(eventInfo.handle))(env, argc - 1, argv + 1); - } - } - - bool valueBool = false; - status = JSUtils::Convert2Value(env, argv[1], valueBool); - RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("interProcess", "a boolean.")); - napi_valuetype type = napi_undefined; - // 'argv[2]' is observer function - napi_typeof(env, argv[2], &type); - RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("observer", "function")); - SubscribeOption option; - option.event = event; - option.mode = valueBool ? SubscribeMode::LOCAL_SHARED : SubscribeMode::LOCAL; - // 'argv[2]' represents a callback function - return proxy->RegisteredObserver(env, option, argv[2]); -} - -napi_value RdbStoreProxy::OffEvent(napi_env env, napi_callback_info info) -{ - size_t argc = 3; - // 'argv[3]' represents an array containing three elements - napi_value argv[3] = { nullptr }; - napi_value self = nullptr; - int32_t status = napi_get_cb_info(env, info, &argc, argv, &self, nullptr); - // '1 <= argc && argc <= 3' represents the number of parameters is 1 - 3 - RDB_NAPI_ASSERT(env, status == napi_ok && 1 <= argc && argc <= 3, std::make_shared("1 - 3")); - - auto proxy = GetNativeInstance(env, self); - RDB_NAPI_ASSERT(env, proxy != nullptr, std::make_shared("RdbStore", "valid")); - RDB_NAPI_ASSERT(env, proxy->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); - - std::string event; - status = JSUtils::Convert2Value(env, argv[0], event); - RDB_NAPI_ASSERT( - env, status == napi_ok && !event.empty(), std::make_shared("event", "a not empty string.")); - for (auto &eventInfo : offEventHandlers_) { - if (eventInfo.event == event) { - return (proxy->*(eventInfo.handle))(env, argc - 1, argv + 1); - } - } - - bool valueBool = false; - status = JSUtils::Convert2Value(env, argv[1], valueBool); - RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("interProcess", "a boolean.")); - - // 'argc == 3' represents determine whether the value of variable 'argc' is equal to '3' - if (argc == 3) { - napi_valuetype type = napi_undefined; - // 'argv[2]' represents a callback function - napi_typeof(env, argv[2], &type); - RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("observer", "function")); - } - SubscribeOption option; - option.event = event; - valueBool ? option.mode = SubscribeMode::LOCAL_SHARED : option.mode = SubscribeMode::LOCAL; - // 'argv[2]' represents a callback function, 'argc == 3' represents determine if 'argc' is equal to '3' - return proxy->UnRegisteredObserver(env, option, argc == 3 ? argv[2] : nullptr); -} - napi_value RdbStoreProxy::Notify(napi_env env, napi_callback_info info) { size_t argc = 1; @@ -1929,51 +1824,6 @@ napi_value RdbStoreProxy::UnregisterSyncCallback(napi_env env, size_t argc, napi return nullptr; } -napi_value RdbStoreProxy::OnStatistics(napi_env env, size_t argc, napi_value *argv) -{ - napi_valuetype type = napi_undefined; - napi_typeof(env, argv[0], &type); - RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("statistics", "function")); - bool result = std::any_of(statisticses_.begin(), statisticses_.end(), - [argv](std::shared_ptr obs) { return obs && *obs == argv[0]; }); - if (result) { - LOG_DEBUG("Duplicate subscribe."); - return nullptr; - } - auto observer = std::make_shared(env, argv[0], queue_); - int errCode = DistributedRdb::SqlStatistic::Subscribe(observer); - RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); - statisticses_.push_back(std::move(observer)); - LOG_DEBUG("Statistics subscribe success."); - return nullptr; -} - -napi_value RdbStoreProxy::OffStatistics(napi_env env, size_t argc, napi_value *argv) -{ - napi_valuetype type; - napi_typeof(env, argv[0], &type); - RDB_NAPI_ASSERT(env, type == napi_function || type == napi_undefined || type == napi_null, - std::make_shared("statistics", "function")); - - auto it = statisticses_.begin(); - while (it != statisticses_.end()) { - if (*it == nullptr) { - it = statisticses_.erase(it); - LOG_WARN("statisticsObserver is nullptr."); - continue; - } - if (type == napi_function && !(**it == argv[0])) { - ++it; - continue; - } - int errCode = DistributedRdb::SqlStatistic::Unsubscribe(*it); - RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); - (*it)->Clear(); - it = statisticses_.erase(it); - } - return nullptr; -} - RdbStoreProxy::SyncObserver::SyncObserver( napi_env env, napi_value callback, std::shared_ptr queue) : env_(env), queue_(queue) @@ -2068,8 +1918,7 @@ napi_value RdbStoreProxy::QueryLockedRow(napi_env env, napi_callback_info info) context->rdbPredicates->EqualTo(AbsRdbPredicates::LOCK_STATUS, AbsRdbPredicates::LOCK_CHANGED)->EndWrap(); context->resultSet = context->rdbStore->QueryByStep(*(context->rdbPredicates), context->columns); context->rdbStore = nullptr; - // If the API version is greater than or equal to 20, throw E_ALREADY_CLOSED. - return (context->resultSet != nullptr) ? E_OK : (JSUtils::GetHapVersion() >= 20) ? E_ALREADY_CLOSED : E_ERROR; + return (context->resultSet != nullptr) ? E_OK : E_ERROR; }; auto output = [context](napi_env env, napi_value &result) { result = ResultSetProxy::NewInstance(env, std::move(context->resultSet)); diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp index 83c547ad..d3682a3a 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp @@ -16,12 +16,14 @@ #include "napi_rdb_store_helper.h" #include +#include #include #include #include #include "logger.h" #include "napi_async_call.h" +#include "napi_rdb_context.h" #include "napi_rdb_error.h" #include "napi_rdb_js_utils.h" #include "napi_rdb_store.h" @@ -29,6 +31,8 @@ #include "rdb_errno.h" #include "rdb_open_callback.h" #include "rdb_store_config.h" +#include "rdb_sql_utils.h" +#include "sqlite_sql_builder.h" #include "unistd.h" using namespace OHOS::Rdb; @@ -38,8 +42,17 @@ using namespace OHOS::AppDataMgrJsKit::JSUtils; namespace OHOS { namespace RelationalStoreJsKit { +constexpr int32_t PARAM_LENGTH_MAX = 256; +constexpr int32_t VALUESBUCKET_LENGTH_MAX = 1000; using ContextParam = AppDataMgrJsKit::JSUtils::ContextParam; +const std::map ERR_STRING_MAP = { + { E_EMPTY_TABLE_NAME, "The table must be not empty string." }, + { E_EMPTY_VALUES_BUCKET, "Bucket must not be empty." }, + { E_INVALID_CONFLICT_FLAG, "Conflict flag is not correct." }, + { E_INVALID_ARGS, "The ValueBucket contains Assets and conflictResolution is REPLACE." }, +}; + class DefaultOpenCallback : public RdbOpenCallback { public: int OnCreate(RdbStore &rdbStore) override @@ -96,7 +109,7 @@ napi_value GetRdbStore(napi_env env, napi_callback_info info) return errCode; }; auto output = [context](napi_env env, napi_value &result) { - result = RdbStoreProxy::NewInstance(env, context->proxy, context->param.isSystemApp, context->param.bundleName); + result = RdbStoreProxy::NewInstance(env, context->proxy, context->param.isSystemApp); CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_ERROR)); }; context->SetAction(env, info, input, exec, output); @@ -134,16 +147,15 @@ napi_value DeleteRdbStore(napi_env env, napi_callback_info info) CHECK_RETURN_SET_E(OK == code, err); }; auto exec = [context]() -> int { - // If the API version is greater than or equal to 20, close the connection. RdbStoreConfig storeConfig = GetRdbStoreConfig(context->config, context->param); if (context->onlyPath) { storeConfig.SetDBType(DB_SQLITE); - int errCodeSqlite = RdbHelper::DeleteRdbStore(storeConfig, JSUtils::GetHapVersion() >= 20); + int errCodeSqlite = RdbHelper::DeleteRdbStore(storeConfig, false); storeConfig.SetDBType(DB_VECTOR); - int errCodeVector = RdbHelper::DeleteRdbStore(storeConfig, JSUtils::GetHapVersion() >= 20); + int errCodeVector = RdbHelper::DeleteRdbStore(storeConfig, false); return (errCodeSqlite == E_OK && errCodeVector == E_OK) ? E_OK : E_REMOVE_FILE; } - return RdbHelper::DeleteRdbStore(storeConfig, JSUtils::GetHapVersion() >= 20); + return RdbHelper::DeleteRdbStore(storeConfig, false); }; auto output = [context](napi_env env, napi_value &result) { napi_status status = napi_create_int64(env, OK, &result); @@ -176,6 +188,211 @@ napi_value IsTokenizerSupported(napi_env env, napi_callback_info info) return JSUtils::Convert2JSValue(env, result); } +static std::string GetErrorString(int errcode) +{ + if (ERR_STRING_MAP.find(errcode) != ERR_STRING_MAP.end()) { + return ERR_STRING_MAP.at(errcode); + } + return std::string(); +} + +int CheckTableName(const std::string &tableName) +{ + if (tableName.size() > PARAM_LENGTH_MAX) { + return ERR; + } + return OK; +} + +int CheckPredicatesWhereClause(const std::string &whereClause) +{ + if (whereClause.size() > PARAM_LENGTH_MAX) { + return ERR; + } + return OK; +} + +int CheckValuesBucket(const ValuesBucket &valuesBucket) +{ + if (valuesBucket.values_.size() > VALUESBUCKET_LENGTH_MAX) { + return ERR; + } + for (const auto &[key, val] : valuesBucket.values_) { + if (key.size() > PARAM_LENGTH_MAX) { + return ERR; + } + } + return OK; +} + +int CheckColumns(const std::vector &columns) +{ + if (columns.size() > VALUESBUCKET_LENGTH_MAX) { + return ERR; + } + for (const auto &key : columns) { + if (key.size() > PARAM_LENGTH_MAX) { + return ERR; + } + } + return OK; +} + +napi_value GetInsertSqlInfo(napi_env env, napi_callback_info info) +{ + LOG_DEBUG("GetInsertSqlInfo begin"); + size_t argc = 3; + napi_value argv[3]{}; + napi_value self = nullptr; + napi_get_cb_info(env, info, &argc, argv, &self, nullptr); + //2 or 3 is number of input parameters. If no, an error is reported. + RDB_NAPI_ASSERT(env, (argc == 2 || argc == 3), std::make_shared("2 or 3")); + auto context = std::make_shared(); + RDB_NAPI_ASSERT(env, + (OK == ParseTableName(env, argv[0], context)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "The table must be not empty string.")); + RDB_NAPI_ASSERT(env, + (OK == ParseValuesBucket(env, argv[1], context)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Bucket must not be empty.")); + RDB_NAPI_ASSERT( + env, (OK == CheckTableName(context->tableName)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Table is too long.")); + RDB_NAPI_ASSERT(env, + (OK == CheckValuesBucket(context->valuesBucket)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "ValuesBucket is too long.")); + ConflictResolution conflict = ConflictResolution::ON_CONFLICT_NONE; + //3 is number of input parameters, Third parameter is ConflictResolution + if (argc == 3) { + //2 is indicates the third input parameter. + auto status = ParseConflictResolution(env, argv[2], context); + RDB_NAPI_ASSERT(env, + (OK == status), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "ConflictResolution is invalid.")); + conflict = context->conflictResolution; + } + + auto [errcode, sqlInfo] = RdbSqlUtils::GetInsertSqlInfo(context->tableName, context->valuesBucket, conflict); + RDB_NAPI_ASSERT( + env, errcode == E_OK, std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, GetErrorString(errcode))); + LOG_DEBUG("GetInsertSqlInfo end"); + return Convert2JSValue(env, sqlInfo); +} + +napi_value GetUpdateSqlInfo(napi_env env, napi_callback_info info) +{ + LOG_DEBUG("GetUpdateSqlInfo Begin."); + size_t argc = 3; + napi_value argv[3]{}; + napi_value self = nullptr; + napi_get_cb_info(env, info, &argc, argv, &self, nullptr); + //2 or 3 is number of input parameters. If no, an error is reported. + RDB_NAPI_ASSERT(env, (argc == 2 || argc == 3), std::make_shared("2 or 3")); + auto context = std::make_shared(); + RDB_NAPI_ASSERT(env, + (OK == ParsePredicates(env, argv[0], context)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Predicates is empty.")); + RDB_NAPI_ASSERT(env, + (OK == ParseValuesBucket(env, argv[1], context)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Bucket must not be empty.")); + ConflictResolution conflict = ConflictResolution::ON_CONFLICT_NONE; + //3 is number of input parameters, Third parameter is ConflictResolution + if (argc == 3) { + //2 is indicates the third input parameter. + auto status = ParseConflictResolution(env, argv[2], context); + RDB_NAPI_ASSERT(env, + (OK == status), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "ConflictResolution is invalid.")); + conflict = context->conflictResolution; + } + auto predicates = context->rdbPredicates; + RDB_NAPI_ASSERT(env, + (!predicates->GetTableName().empty()), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "The table must be not empty string.")); + RDB_NAPI_ASSERT(env, + (OK == CheckPredicatesWhereClause(predicates->GetWhereClause())), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Columns in predicates is too much.")); + RDB_NAPI_ASSERT( + env, (OK == CheckTableName(predicates->GetTableName())), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Table is too long.")); + RDB_NAPI_ASSERT(env, + (OK == CheckValuesBucket(context->valuesBucket)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "ValuesBucket is too long.")); + auto [errcode, sqlInfo] = RdbSqlUtils::GetUpdateSqlInfo(*predicates, context->valuesBucket, conflict); + RDB_NAPI_ASSERT( + env, errcode == E_OK, std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, GetErrorString(errcode))); + LOG_DEBUG("GetUpdateSqlInfo end."); + return Convert2JSValue(env, sqlInfo); +} + +napi_value GetDeleteSqlInfo(napi_env env, napi_callback_info info) +{ + LOG_DEBUG("GetDeleteSqlInfo start"); + auto context = std::make_shared(); + size_t argc = 1; + napi_value argv[1]{}; + napi_value self = nullptr; + napi_get_cb_info(env, info, &argc, argv, &self, nullptr); + RDB_NAPI_ASSERT(env, argc == 1, std::make_shared("1")); + RDB_NAPI_ASSERT(env, + (OK == ParsePredicates(env, argv[0], context)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "predicates is empty.")); + auto predicates = context->rdbPredicates; + RDB_NAPI_ASSERT(env, + (!predicates->GetTableName().empty()), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "The table must be not empty string.")); + RDB_NAPI_ASSERT( + env, (OK == CheckTableName(predicates->GetTableName())), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Table is too long.")); + RDB_NAPI_ASSERT(env, + (OK == CheckPredicatesWhereClause(predicates->GetWhereClause())), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Columns in predicates is too much.")); + auto [errcode, sqlInfo] = RdbSqlUtils::GetDeleteSqlInfo(*predicates); + RDB_NAPI_ASSERT( + env, errcode == E_OK, std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, GetErrorString(errcode))); + LOG_DEBUG("GetDeleteSqlInfo end"); + return Convert2JSValue(env, sqlInfo); +} + +napi_value GetQuerySqlInfo(napi_env env, napi_callback_info info) +{ + LOG_DEBUG("GetQuerySqlInfo start"); + auto context = std::make_shared(); + size_t argc = 2; + napi_value argv[2]{}; + napi_value self = nullptr; + napi_get_cb_info(env, info, &argc, argv, &self, nullptr); + //1 or 2 is number of input parameters. If no, an error is reported. + RDB_NAPI_ASSERT(env, (argc == 1 || argc == 2), std::make_shared("1 or 2")); + RDB_NAPI_ASSERT(env, + (OK == ParsePredicates(env, argv[0], context)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "predicates is empty.")); + //2 is number of input parameters + if (argc == 2) { + auto status = ParseColumns(env, argv[1], context); + RDB_NAPI_ASSERT(env, + (OK == status), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Columns is not a string array.")); + } + auto predicates = context->rdbPredicates; + auto columns = context->columns; + RDB_NAPI_ASSERT(env, + (!predicates->GetTableName().empty()), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "The table must be not empty string.")); + RDB_NAPI_ASSERT(env, + (OK == CheckPredicatesWhereClause(predicates->GetWhereClause())), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Columns in predicates is too much.")); + RDB_NAPI_ASSERT(env, + (OK == CheckTableName(predicates->GetTableName())), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Table is too long.")); + RDB_NAPI_ASSERT(env, (OK == CheckColumns(columns)), + std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, "Columns is too long.")); + auto [errcode, sqlInfo] = RdbSqlUtils::GetQuerySqlInfo(*predicates, columns); + RDB_NAPI_ASSERT( + env, errcode == E_OK, std::make_shared(NativeRdb::E_INVALID_ARGS_NEW, GetErrorString(errcode))); + LOG_DEBUG("GetQuerySqlInfo end"); + return Convert2JSValue(env, sqlInfo); +} + napi_value InitRdbHelper(napi_env env, napi_value exports) { napi_property_descriptor properties[] = { @@ -185,6 +402,10 @@ napi_value InitRdbHelper(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION_WITH_DATA("deleteRdbStoreSync", DeleteRdbStore, SYNC), DECLARE_NAPI_FUNCTION_WITH_DATA("isVectorSupported", IsVectorSupported, SYNC), DECLARE_NAPI_FUNCTION_WITH_DATA("isTokenizerSupported", IsTokenizerSupported, SYNC), + DECLARE_NAPI_FUNCTION_WITH_DATA("getInsertSqlInfo", GetInsertSqlInfo, SYNC), + DECLARE_NAPI_FUNCTION_WITH_DATA("getUpdateSqlInfo", GetUpdateSqlInfo, SYNC), + DECLARE_NAPI_FUNCTION_WITH_DATA("getDeleteSqlInfo", GetDeleteSqlInfo, SYNC), + DECLARE_NAPI_FUNCTION_WITH_DATA("getQuerySqlInfo", GetQuerySqlInfo, SYNC), }; NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(*properties), properties)); return exports; diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp index 2e464046..984f272a 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp @@ -13,16 +13,16 @@ * limitations under the License. */ -#include -#include "js_native_api.h" -#include "js_native_api_types.h" #define LOG_TAG "ResultSetProxy" #include "napi_result_set.h" #include #include +#include #include "js_df_manager.h" +#include "js_native_api.h" +#include "js_native_api_types.h" #include "js_utils.h" #include "logger.h" #include "napi_rdb_error.h" @@ -95,13 +95,17 @@ napi_value ResultSetProxy::Initialize(napi_env env, napi_callback_info info) return nullptr; } auto finalize = [](napi_env env, void *data, void *hint) { + if (data == nullptr) { + LOG_ERROR("data is nullptr."); + return; + } auto tid = JSDFManager::GetInstance().GetFreedTid(data); if (tid != 0) { LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); } if (data != hint) { - LOG_ERROR("RdbStoreProxy memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, uintptr_t(data), - uintptr_t(hint)); + LOG_ERROR("RdbStoreProxy memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, + uintptr_t(data) & LOWER_24_BITS_MASK, uintptr_t(hint) & LOWER_24_BITS_MASK); return; } ResultSetProxy *proxy = reinterpret_cast(data); @@ -256,7 +260,7 @@ napi_value ResultSetProxy::GetColumnType(napi_env env, napi_callback_info info) errCode = result->GetColumnType(context->columnIndex, context->columnType); } if (errCode == E_INVALID_ARGS) { - return E_INVALID_ARGS_NEW; + return E_PARAM_ERROR; } return errCode; }; @@ -368,9 +372,6 @@ napi_value ResultSetProxy::GoToRow(napi_env env, napi_callback_info info) if (resultSet != nullptr) { errCode = resultSet->GoToRow(position); } - // If the API version is less than 13, directly return. - RDB_NAPI_ASSERT(env, JSUtils::GetHapVersion() < 13 || (errCode == E_ROW_OUT_RANGE || errCode == E_OK), - std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } @@ -383,9 +384,6 @@ napi_value ResultSetProxy::GoTo(napi_env env, napi_callback_info info) if (resultSet != nullptr) { errCode = resultSet->GoTo(offset); } - // If the API version is less than 13, directly return. - RDB_NAPI_ASSERT(env, JSUtils::GetHapVersion() < 13 || (errCode == E_ROW_OUT_RANGE || errCode == E_OK), - std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } @@ -397,9 +395,6 @@ napi_value ResultSetProxy::GoToFirstRow(napi_env env, napi_callback_info info) if (resultSet != nullptr) { errCode = resultSet->GoToFirstRow(); } - // If the API version is less than 13, directly return. - RDB_NAPI_ASSERT(env, JSUtils::GetHapVersion() < 13 || (errCode == E_ROW_OUT_RANGE || errCode == E_OK), - std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } @@ -411,9 +406,6 @@ napi_value ResultSetProxy::GoToLastRow(napi_env env, napi_callback_info info) if (resultSet != nullptr) { errCode = resultSet->GoToLastRow(); } - // If the API version is less than 13, directly return. - RDB_NAPI_ASSERT(env, JSUtils::GetHapVersion() < 13 || (errCode == E_ROW_OUT_RANGE || errCode == E_OK), - std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } @@ -425,9 +417,6 @@ napi_value ResultSetProxy::GoToNextRow(napi_env env, napi_callback_info info) if (resultSet != nullptr) { errCode = resultSet->GoToNextRow(); } - // If the API version is less than 13, directly return. - RDB_NAPI_ASSERT(env, JSUtils::GetHapVersion() < 13 || (errCode == E_ROW_OUT_RANGE || errCode == E_OK), - std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } @@ -439,9 +428,6 @@ napi_value ResultSetProxy::GoToPreviousRow(napi_env env, napi_callback_info info if (resultSet != nullptr) { errCode = resultSet->GoToPreviousRow(); } - // If the API version is less than 13, directly return. - RDB_NAPI_ASSERT(env, JSUtils::GetHapVersion() < 13 || (errCode == E_ROW_OUT_RANGE || errCode == E_OK), - std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } @@ -586,9 +572,6 @@ napi_value ResultSetProxy::GetColumnIndex(napi_env env, napi_callback_info info) if (resultSet != nullptr) { errCode = resultSet->GetColumnIndex(input, result); } - // If the API version is less than 13, directly return. - RDB_NAPI_ASSERT(env, JSUtils::GetHapVersion() < 13 || (errCode == E_INVALID_ARGS || errCode == E_OK), - std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, result); } @@ -602,8 +585,6 @@ napi_value ResultSetProxy::GetColumnName(napi_env env, napi_callback_info info) if (resultSet != nullptr) { errCode = resultSet->GetColumnName(columnIndex, result); } - // If the API version is less than 13, directly return. - RDB_NAPI_ASSERT(env, JSUtils::GetHapVersion() < 13 || errCode == E_OK, std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, result); } diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_transaction.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_transaction.cpp index cdf20470..582af0bf 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_transaction.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_transaction.cpp @@ -282,12 +282,17 @@ napi_value TransactionProxy::Initialize(napi_env env, napi_callback_info info) return nullptr; } auto finalize = [](napi_env env, void *data, void *hint) { + if (data == nullptr) { + LOG_ERROR("data is nullptr."); + return; + } auto tid = JSDFManager::GetInstance().GetFreedTid(data); if (tid != 0) { LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); } if (data != hint) { - LOG_ERROR("Memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, uintptr_t(data), uintptr_t(hint)); + LOG_ERROR("Memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, + uintptr_t(data) & LOWER_24_BITS_MASK, uintptr_t(hint) & LOWER_24_BITS_MASK); return; } TransactionProxy *proxy = reinterpret_cast(data); @@ -596,7 +601,7 @@ napi_value TransactionProxy::BatchInsertWithConflictResolution(napi_env env, nap }; auto exec = [context]() -> int { CHECK_RETURN_ERR(context->transaction_ != nullptr); - auto [code, insertRows] = context->StealTransaction()->BatchInsertWithConflictResolution( + auto [code, insertRows] = context->StealTransaction()->BatchInsert( context->tableName, context->valuesBuckets, context->conflictResolution); context->insertRows = insertRows; return code; @@ -647,7 +652,7 @@ napi_value TransactionProxy::Query(napi_env env, napi_callback_info info) return (context->resultSet != nullptr) ? E_OK : E_ALREADY_CLOSED; }; auto output = [context](napi_env env, napi_value &result) { - result = ResultSetProxy::NewInstance(env, context->resultSet); + result = ResultSetProxy::NewInstance(env, std::move(context->resultSet)); CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_ERROR)); }; context->SetAction(env, info, input, exec, output); @@ -693,7 +698,7 @@ napi_value TransactionProxy::QuerySql(napi_env env, napi_callback_info info) return (context->resultSet != nullptr) ? E_OK : E_ALREADY_CLOSED; }; auto output = [context](napi_env env, napi_value &result) { - result = ResultSetProxy::NewInstance(env, context->resultSet); + result = ResultSetProxy::NewInstance(env, std::move(context->resultSet)); CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_ERROR)); }; context->SetAction(env, info, input, exec, output); diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_uv_queue.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_uv_queue.cpp deleted file mode 100644 index adc23eb4..00000000 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_uv_queue.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2022 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. - */ -#define LOG_TAG "NapiUvQueue" -#include "napi_uv_queue.h" - -#include "logger.h" -#include "uv.h" - -namespace OHOS::RelationalStoreJsKit { -using namespace OHOS::Rdb; - -NapiUvQueue::NapiUvQueue(napi_env env, napi_value callback) : env_(env) -{ - napi_create_reference(env, callback, 1, &callback_); - napi_get_uv_event_loop(env, &loop_); -} - -NapiUvQueue::~NapiUvQueue() -{ - napi_delete_reference(env_, callback_); -} - -bool NapiUvQueue::operator==(napi_value value) -{ - napi_value callback = nullptr; - napi_get_reference_value(env_, callback_, &callback); - - bool isEquals = false; - napi_strict_equals(env_, value, callback, &isEquals); - return isEquals; -} - -void NapiUvQueue::CallFunction(NapiArgsGenerator genArgs) -{ - uv_work_t *work = new (std::nothrow) uv_work_t; - if (work == nullptr) { - return; - } - work->data = this; - this->args = std::move(genArgs); - - int ret = uv_queue_work(loop_, work, [](uv_work_t* work) {}, [](uv_work_t* work, int st) { - auto queue = static_cast(work->data); - napi_handle_scope scope = nullptr; - if (queue == nullptr) { - return; - } - napi_open_handle_scope(queue->env_, &scope); - if (scope == nullptr) { - delete work; - return; - } - int argc = 0; - napi_value argv[MAX_CALLBACK_ARG_NUM] = { nullptr }; - if (queue->args) { - queue->args(queue->env_, argc, argv); - } - - napi_value callback = nullptr; - napi_get_reference_value(queue->env_, queue->callback_, &callback); - napi_value global = nullptr; - napi_get_global(queue->env_, &global); - napi_value result = nullptr; - napi_status status = napi_call_function(queue->env_, global, callback, argc, argv, &result); - if (status != napi_ok) { - LOG_ERROR("napi_call_function failed, status=%{public}d", status); - } - napi_close_handle_scope(queue->env_, scope); - delete work; - }); - if (ret < 0) { - LOG_ERROR("uv_queue_work failed, errCode:%{public}d", ret); - delete static_cast(work->data); - delete work; - } -} -} // namespace OHOS::RelationalStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/sendablerelationalstore/BUILD.gn b/relational_store/frameworks/js/napi/sendablerelationalstore/BUILD.gn index 9742fe00..2150a164 100644 --- a/relational_store/frameworks/js/napi/sendablerelationalstore/BUILD.gn +++ b/relational_store/frameworks/js/napi/sendablerelationalstore/BUILD.gn @@ -51,6 +51,7 @@ ohos_shared_library("sendablerelationalstore") { "bounds_checking_function:libsec_shared", "hilog:libhilog", "hitrace:hitrace_meter", + "ipc:ipc_single", "napi:ace_napi", ] diff --git a/relational_store/frameworks/js/napi/sendablerelationalstore/src/napi_rdb_store_convert_utils.cpp b/relational_store/frameworks/js/napi/sendablerelationalstore/src/napi_rdb_store_convert_utils.cpp index 8565f0ce..0c993721 100644 --- a/relational_store/frameworks/js/napi/sendablerelationalstore/src/napi_rdb_store_convert_utils.cpp +++ b/relational_store/frameworks/js/napi/sendablerelationalstore/src/napi_rdb_store_convert_utils.cpp @@ -142,6 +142,69 @@ napi_value ToSendableAsset(napi_env env, napi_callback_info info) return Convert2Sendable(env, args[0]); } +napi_value FromSendableValues(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = { nullptr }; + napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + RDB_NAPI_ASSERT(env, status == napi_ok && argc == 1, std::make_shared("1")); + + bool isArray = false; + status = napi_is_array(env, args[0], &isArray); + RDB_NAPI_ASSERT(env, status == napi_ok && isArray, + std::make_shared("values is invalid" + std::to_string(status))); + + uint32_t length = 0; + status = napi_get_array_length(env, args[0], &length); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("napi_get_array_length failed.")); + napi_value outArray; + status = napi_create_array(env, &outArray); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("napi_create_array failed.")); + for (uint32_t i = 0; i < length; ++i) { + napi_value item = nullptr; + status = napi_get_element(env, args[0], i, &item); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("napi_get_element failed.")); + napi_value jsvalue = Convert2JSValue(env, item); + status = napi_set_element(env, outArray, i, jsvalue); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("napi_set_element failed.")); + } + return outArray; +} + +napi_value ToSendableValues(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = { nullptr }; + napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + RDB_NAPI_ASSERT(env, status == napi_ok && argc == 1, std::make_shared("1")); + + bool isArray = false; + status = napi_is_array(env, args[0], &isArray); + RDB_NAPI_ASSERT(env, status == napi_ok && isArray, + std::make_shared("values is invalid" + std::to_string(status))); + + uint32_t length = 0; + status = napi_get_array_length(env, args[0], &length); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("napi_get_array_length failed.")); + + napi_value outArray; + status = napi_create_sendable_array(env, &outArray); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("napi_create_sendable_array failed.")); + for (uint32_t i = 0; i < length; ++i) { + napi_value item = nullptr; + status = napi_get_element(env, args[0], i, &item); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("napi_get_element failed.")); + ValueObject object; + status = (napi_status)Convert2Value(env, item, object); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("Convert2Value failed.")); + napi_value sendablevalue = Convert2Sendable(env, object); + + status = napi_set_element(env, outArray, i, sendablevalue); + RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("napi_set_element failed.")); + } + return outArray; +} + napi_value InitRdbStoreUtils(napi_env env, napi_value exports) { napi_property_descriptor properties[] = { @@ -149,6 +212,8 @@ napi_value InitRdbStoreUtils(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("toSendableValuesBucket", ToSendableValuesBucket), DECLARE_NAPI_FUNCTION("fromSendableAsset", FromSendableAsset), DECLARE_NAPI_FUNCTION("toSendableAsset", ToSendableAsset), + DECLARE_NAPI_FUNCTION("fromSendableValues", FromSendableValues), + DECLARE_NAPI_FUNCTION("toSendableValues", ToSendableValues), }; NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(*properties), properties)); return exports; diff --git a/relational_store/frameworks/native/appdatafwk/src/serializable.cpp b/relational_store/frameworks/native/appdatafwk/src/serializable.cpp index 2a90ec7d..af42f1d6 100644 --- a/relational_store/frameworks/native/appdatafwk/src/serializable.cpp +++ b/relational_store/frameworks/native/appdatafwk/src/serializable.cpp @@ -141,6 +141,16 @@ bool Serializable::GetValue(const json &node, const std::string &name, Serializa return value.Unmarshal(subNode); } +bool Serializable::GetValue(const json &node, const std::string &name, double &value) +{ + auto &subNode = GetSubNode(node, name); + if (subNode.is_null() || !subNode.is_number_float()) { + return false; + } + subNode.get_to(value); + return true; +} + bool Serializable::SetValue(json &node, const std::string &value) { node = value; @@ -188,6 +198,12 @@ bool Serializable::SetValue(json &node, const Serializable &value) return value.Marshal(node); } +bool Serializable::SetValue(json &node, const double &value) +{ + node = value; + return true; +} + const Serializable::json &Serializable::GetSubNode(const json &node, const std::string &name) { static const json jsonNull = json::value_t::null; diff --git a/relational_store/frameworks/native/appdatafwk/src/shared_block.cpp b/relational_store/frameworks/native/appdatafwk/src/shared_block.cpp index 18cdfc18..8e76b974 100644 --- a/relational_store/frameworks/native/appdatafwk/src/shared_block.cpp +++ b/relational_store/frameworks/native/appdatafwk/src/shared_block.cpp @@ -155,7 +155,10 @@ int SharedBlock::Clear() mHeader->startPos_ = 0; mHeader->lastPos_ = 0; mHeader->blockPos_ = 0; - memset_s(mHeader->groupOffset, sizeof(mHeader->groupOffset), 0, sizeof(mHeader->groupOffset)); + auto result = memset_s(mHeader->groupOffset, sizeof(mHeader->groupOffset), 0, sizeof(mHeader->groupOffset)); + if (result != EOK) { + LOG_ERROR("memset_s failed, error code is %{public}d", result); + } mHeader->groupOffset[0] = sizeof(SharedBlockHeader); return SHARED_BLOCK_OK; } @@ -303,7 +306,7 @@ int SharedBlock::PutBigInt(uint32_t row, uint32_t column, const void *value, siz int SharedBlock::PutBlobOrString(uint32_t row, uint32_t column, const void *value, size_t size, int32_t type) { - if (UNLIKELY(row >= mHeader->rowNums || column >= mHeader->columnNums)) { + if (UNLIKELY(row >= mHeader->rowNums || column >= mHeader->columnNums || value == nullptr)) { LOG_ERROR("Failed to read row %{public}" PRIu32 ", column %{public}" PRIu32 " from a SharedBlock" " which has %{public}" PRIu32 " rows, %{public}" PRIu32 " columns.", row, column, mHeader->rowNums, mHeader->columnNums); @@ -391,7 +394,7 @@ int SharedBlock::PutNull(uint32_t row, uint32_t column) size_t SharedBlock::SetRawData(const void *rawData, size_t size) { - if (UNLIKELY(size <= 0)) { + if (UNLIKELY(size <= 0 || rawData == nullptr)) { LOG_ERROR("SharedBlock rawData is less than or equal to 0M"); return SHARED_BLOCK_INVALID_OPERATION; } @@ -409,6 +412,9 @@ size_t SharedBlock::SetRawData(const void *rawData, size_t size) std::string SharedBlock::CellUnit::GetString(SharedBlock *block) const { + if (UNLIKELY(block == nullptr)) { + return ""; + } auto value = static_cast(block->OffsetToPtr(cell.stringOrBlobValue.offset, cell.stringOrBlobValue.size)); if (cell.stringOrBlobValue.size < 1 || value == nullptr) { return ""; @@ -418,6 +424,9 @@ std::string SharedBlock::CellUnit::GetString(SharedBlock *block) const std::vector SharedBlock::CellUnit::GetBlob(SharedBlock *block) const { + if (UNLIKELY(block == nullptr)) { + return {}; + } auto value = reinterpret_cast(block->OffsetToPtr(cell.stringOrBlobValue.offset, cell.stringOrBlobValue.size)); return std::vector(value, value + cell.stringOrBlobValue.size); @@ -425,6 +434,9 @@ std::vector SharedBlock::CellUnit::GetBlob(SharedBlock *block) const const uint8_t *SharedBlock::CellUnit::GetRawData(SharedBlock *block) const { + if (UNLIKELY(block == nullptr)) { + return nullptr; + } return static_cast(block->OffsetToPtr(cell.stringOrBlobValue.offset, cell.stringOrBlobValue.size)); } } // namespace AppDataFwk diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_notifier_stub.h b/relational_store/frameworks/native/cloud_data/include/cloud_notifier_stub.h new file mode 100644 index 00000000..fecfcf01 --- /dev/null +++ b/relational_store/frameworks/native/cloud_data/include/cloud_notifier_stub.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 OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_NOTIFIER_STUB_H +#define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_NOTIFIER_STUB_H + +#include "cloud_notifier.h" +#include "iremote_broker.h" +#include "iremote_stub.h" + +namespace OHOS::CloudData { +using namespace DistributedRdb; +using NotifierCode = DistributedRdb::RelationalStore::ICloudNotifierInterfaceCode; + +class CloudNotifierStubBroker : public ICloudNotifier, public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.CloudData.ICloudNotifier"); +}; + +class CloudNotifierStub : public IRemoteStub { +public: + using SyncCompleteHandler = std::function; + explicit CloudNotifierStub(const SyncCompleteHandler &syncComplete); + virtual ~CloudNotifierStub() noexcept; + + int OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) override; + int32_t OnComplete(uint32_t seqNum, Details &&result) override; + +private: + int32_t OnCompleteInner(MessageParcel& data, MessageParcel& reply); + bool CheckInterfaceToken(MessageParcel& data); + + using RequestHandle = int32_t (CloudNotifierStub::*)(MessageParcel&, MessageParcel&); + static constexpr RequestHandle HANDLES[static_cast(NotifierCode::CLOUD_NOTIFIER_CMD_MAX)] = { + [static_cast(NotifierCode::CLOUD_NOTIFIER_CMD_SYNC_COMPLETE)] = &CloudNotifierStub::OnCompleteInner, + }; + + SyncCompleteHandler completeNotifier_; +}; +} // namespace OHOS::CloudData +#endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_NOTIFIER_STUB_H diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h index 780c5dd2..9db4d1f9 100644 --- a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h +++ b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h @@ -16,11 +16,14 @@ #ifndef OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_PROXY_H #define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_PROXY_H +#include "concurrent_map.h" #include "icloud_service.h" #include "iremote_object.h" #include "iremote_proxy.h" +#include "cloud_notifier_stub.h" namespace OHOS::CloudData { +using namespace DistributedRdb; class CloudServiceProxy : public IRemoteProxy { public: explicit CloudServiceProxy(const sptr &object); @@ -52,9 +55,17 @@ public: int32_t SetCloudStrategy(Strategy strategy, const std::vector &values) override; std::pair QueryLastSyncInfo( const std::string &id, const std::string &bundleName, const std::string &storeId) override; + int32_t CloudSync(const std::string &bundleName, const std::string &storeId, const Option &option, + const AsyncDetail &async) override; + int32_t InitNotifier(sptr notifier) override; + int32_t InitNotifier(); private: + int32_t DoAsync(const std::string &bundleName, const std::string &storeId, Option option); + void OnSyncComplete(uint32_t seqNum, Details &&result); sptr remote_; + sptr notifier_; + ConcurrentMap syncCallbacks_; }; } // namespace OHOS::CloudData #endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_PROXY_H \ No newline at end of file diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h b/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h index e0ab11dd..b524724c 100644 --- a/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h +++ b/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h @@ -16,6 +16,7 @@ #ifndef OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_UTIL_H #define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_UTIL_H #include "cloud_types.h" +#include "cloud_service.h" #include "common_types.h" #include "itypes_util.h" #include "values_bucket.h" @@ -33,6 +34,7 @@ using StatisticInfo = OHOS::CloudData::StatisticInfo; using CommonAsset = CommonType::Asset; using Strategy = OHOS::CloudData::Strategy; using CloudSyncInfo = OHOS::CloudData::CloudSyncInfo; +using Option = OHOS::CloudData::CloudService::Option; template<> bool Marshalling(const Participant &input, MessageParcel &data); @@ -85,5 +87,10 @@ template<> bool Marshalling(const CloudSyncInfo &input, MessageParcel &data); template<> bool Unmarshalling(CloudSyncInfo &output, MessageParcel &data); + +template<> +bool Marshalling(const Option &input, MessageParcel &data); +template<> +bool Unmarshalling(Option &output, MessageParcel &data); } // namespace OHOS::ITypesUtil #endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_UTIL_H \ No newline at end of file diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp index 36ec5bc4..cd8c42ed 100644 --- a/relational_store/frameworks/native/cloud_data/src/cloud_manager.cpp +++ b/relational_store/frameworks/native/cloud_data/src/cloud_manager.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 @@ -32,7 +32,6 @@ public: ~DataMgrService() = default; sptr GetFeatureInterface(const std::string &name) override; }; - class CloudDeath : public IRemoteObject::DeathRecipient { public: explicit CloudDeath(std::function action) : action_(std::move(action)) {}; @@ -92,6 +91,10 @@ std::pair> CloudManager::GetCloudService( if (proxy == nullptr) { return std::make_pair(CloudService::Status::FEATURE_UNAVAILABLE, nullptr); } + if (proxy->InitNotifier() != CloudService::Status::SUCCESS) { + LOG_ERROR("Init notifier failed."); + return { CloudService::Status::ERROR, nullptr }; + } cloudService_ = std::shared_ptr(proxy.GetRefPtr(), [holder = proxy](const auto *) {}); if (cloudService_ == nullptr) { diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_notifier_stub.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_notifier_stub.cpp new file mode 100644 index 00000000..e897f5e4 --- /dev/null +++ b/relational_store/frameworks/native/cloud_data/src/cloud_notifier_stub.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. + */ +#define LOG_TAG "CloudNotifierStub" + +#include "cloud_notifier_stub.h" + +#include + +#include "cloud_service.h" +#include "itypes_util.h" +#include "logger.h" + +namespace OHOS::CloudData { +using namespace Rdb; +CloudNotifierStub::CloudNotifierStub(const SyncCompleteHandler &completeNotifier) + : IRemoteStub(), completeNotifier_(completeNotifier) +{ +} + +CloudNotifierStub::~CloudNotifierStub() noexcept +{ +} + +bool CloudNotifierStub::CheckInterfaceToken(MessageParcel &data) +{ + auto localDescriptor = GetDescriptor(); + auto remoteDescriptor = data.ReadInterfaceToken(); + if (remoteDescriptor != localDescriptor) { + LOG_ERROR("interface token is not equal."); + return false; + } + return true; +} + +int CloudNotifierStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) +{ + LOG_DEBUG("code:%{public}u, callingPid:%{public}d", code, IPCSkeleton::GetCallingPid()); + if (!CheckInterfaceToken(data)) { + return CloudService::ERROR; + } + + if (code < static_cast(NotifierCode::CLOUD_NOTIFIER_CMD_MAX)) { + return (this->*HANDLES[code])(data, reply); + } + + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); +} + +int32_t CloudNotifierStub::OnCompleteInner(MessageParcel &data, MessageParcel &reply) +{ + uint32_t seqNum = 0; + Details result; + if (!ITypesUtil::Unmarshal(data, seqNum, result)) { + LOG_ERROR("read sync result failed."); + return CloudService::ERROR; + } + return OnComplete(seqNum, std::move(result)); +} + +int32_t CloudNotifierStub::OnComplete(uint32_t seqNum, Details &&result) +{ + if (completeNotifier_) { + completeNotifier_(seqNum, std::move(result)); + } + return CloudService::SUCCESS; +} +} // namespace OHOS::CloudData diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp index 51d4c2e6..95985dce 100644 --- a/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp +++ b/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp @@ -271,4 +271,75 @@ std::pair CloudServiceProxy::QueryLastSyncInfo( ITypesUtil::Unmarshal(reply, results); return { status, results }; } + +int32_t CloudServiceProxy::DoAsync(const std::string &bundleName, const std::string &storeId, Option option) +{ + MessageParcel reply; + int32_t status = IPC_SEND(TRANS_CLOUD_SYNC, reply, bundleName, storeId, option); + if (status != SUCCESS) { + LOG_ERROR( + "Status:0x%{public}x bundleName:%{public}s storeId:%{public}.3s syncMode:%{public}d seqNum:%{public}u", + status, bundleName.c_str(), storeId.c_str(), option.syncMode, option.seqNum); + } + return status; +} + +int32_t CloudServiceProxy::InitNotifier(sptr notifier) +{ + MessageParcel reply; + int32_t status = IPC_SEND(TRANS_INIT_NOTIFIER, reply, notifier); + if (status != SUCCESS) { + LOG_ERROR("Status:0x%{public}x", status); + } + return status; +} + +int32_t CloudServiceProxy::InitNotifier() +{ + notifier_ = new (std::nothrow) CloudNotifierStub([this](uint32_t seqNum, Details &&result) { + OnSyncComplete(seqNum, std::move(result)); + }); + if (notifier_ == nullptr) { + LOG_ERROR("create notifier failed"); + return ERROR; + } + auto status = InitNotifier(notifier_->AsObject()); + if (status != SUCCESS) { + notifier_ = nullptr; + LOG_ERROR("init notifier failed."); + return status; + } + return SUCCESS; +} + +void CloudServiceProxy::OnSyncComplete(uint32_t seqNum, Details &&result) +{ + syncCallbacks_.ComputeIfPresent(seqNum, [&result](const auto &key, const AsyncDetail &callback) { + auto finished = result.empty() || (result.begin()->second.progress == SYNC_FINISH); + if (callback != nullptr) { + callback(std::move(result)); + } + return !finished; + }); +} + +int32_t CloudServiceProxy::CloudSync(const std::string &bundleName, const std::string &storeId, + const Option &option, const AsyncDetail &async) +{ + LOG_INFO("cloud sync start, bundleName = %{public}s, seqNum = %{public}u", bundleName.c_str(), option.seqNum); + if (bundleName.empty() || storeId.empty() || option.syncMode < DistributedRdb::TIME_FIRST || + option.syncMode > DistributedRdb::CLOUD_FIRST || async == nullptr) { + LOG_ERROR("invalid args, bundleName = %{public}s", bundleName.c_str()); + return INVALID_ARGUMENT; + } + if (!syncCallbacks_.Insert(option.seqNum, async)) { + LOG_ERROR("register progress failed, bundleName = %{public}s", bundleName.c_str()); + return ERROR; + } + auto status = DoAsync(bundleName, storeId, option); + if (status != SUCCESS) { + syncCallbacks_.Erase(option.seqNum); + } + return status; +} } // namespace OHOS::CloudData diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp index abf93c05..70859e24 100644 --- a/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp +++ b/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp @@ -152,4 +152,15 @@ bool Unmarshalling(CloudSyncInfo &output, MessageParcel &data) { return Unmarshal(data, output.startTime, output.finishTime, output.code, output.syncStatus); } + +template<> +bool Marshalling(const Option &input, MessageParcel &data) +{ + return Marshal(data, input.syncMode, input.seqNum); +} +template<> +bool Unmarshalling(Option &output, MessageParcel &data) +{ + return Unmarshal(data, output.syncMode, output.seqNum); +} } // namespace OHOS::ITypesUtil \ No newline at end of file diff --git a/relational_store/frameworks/native/dfx/include/rdb_dfx_errno.h b/relational_store/frameworks/native/dfx/include/rdb_dfx_errno.h index eec0d0ce..f8028dd4 100644 --- a/relational_store/frameworks/native/dfx/include/rdb_dfx_errno.h +++ b/relational_store/frameworks/native/dfx/include/rdb_dfx_errno.h @@ -68,6 +68,58 @@ static constexpr int E_DFX_SET_JOURNAL_FAIL = (E_DFX_BASE + 0x8); */ static constexpr int E_DFX_DUMP_INFO = (E_DFX_BASE + 0x9); +/** +* @brief The base code of the exception dfx huks error code, base value is 0x1A28100. +*/ +constexpr int E_DFX_HUKS_BASE = E_DFX_BASE + 0x100; + +/** + * @brief The root key of the encrypted database is faulty. + */ +static constexpr int E_ROOT_KEY_FAULT = (E_DFX_HUKS_BASE + 0x4e); + +/** + * @brief The root key of the encrypted database cannot be loaded. + */ +static constexpr int E_ROOT_KEY_NOT_LOAD = (E_DFX_HUKS_BASE + 0x4f); + +/** + * @brief The working key of the encrypted database is faulty. + */ +static constexpr int E_WORK_KEY_FAIL = (E_DFX_HUKS_BASE + 0x50); + +/** + * @brief Failed to encrypt the working key. + */ +static constexpr int E_WORK_KEY_ENCRYPT_FAIL = (E_DFX_HUKS_BASE + 0x51); + +/** + * @brief Failed to decrypt the working key. + */ +static constexpr int E_WORK_KEY_DECRYPT_FAIL = (E_DFX_HUKS_BASE + 0x52); + +/** + * @brief Failed to open the sqlite database using the working key. + */ +static constexpr int E_SET_ENCRYPT_FAIL = (E_DFX_HUKS_BASE + 0x53); + +/** + * @brief Failed to open the sqlite database using the working new key. + */ +static constexpr int E_SET_NEW_ENCRYPT_FAIL = (E_DFX_HUKS_BASE + 0x54); + +/** + * @brief Failed to open the sqlite database using the working service key. + */ +static constexpr int E_SET_SERVICE_ENCRYPT_FAIL = (E_DFX_HUKS_BASE + 0x55); + +/** + * @brief Only use for dfx, print dump info. + */ +static constexpr int E_DFX_HUKS_GEN_RANDOM_FAIL = (E_DFX_HUKS_BASE + 0x56); + +static constexpr int E_DFX_LENGTH_PARAM_CHECK_FAIL = (E_DFX_HUKS_BASE + 0x57); + } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/dfx/include/rdb_fault_hiview_reporter.h b/relational_store/frameworks/native/dfx/include/rdb_fault_hiview_reporter.h index 96eb7713..50a8d950 100644 --- a/relational_store/frameworks/native/dfx/include/rdb_fault_hiview_reporter.h +++ b/relational_store/frameworks/native/dfx/include/rdb_fault_hiview_reporter.h @@ -63,7 +63,7 @@ static constexpr const char *FT_SQLITE = "SQLITE"; static constexpr const char *BUNDLE_NAME_COMMON = "common"; -class API_EXPORT RdbFaultEvent { +class RdbFaultEvent { public: RdbFaultEvent(const std::string &faultType, int32_t errorCode, const std::string &bundleName, const std::string &custLog); @@ -73,6 +73,7 @@ public: int32_t GetErrCode() const { return errorCode_; } std::string GetLogInfo() const { return custLog_; }; virtual void Report() const; + virtual ~RdbFaultEvent() = default; protected: void SetBundleName(const std::string &name) { bundleName_ = name; }; @@ -99,13 +100,7 @@ private: bool printDbInfo_; }; -class API_EXPORT RdbEmptyBlobEvent : public RdbFaultEvent { -public: - RdbEmptyBlobEvent(const std::string &bundleName); - virtual void Report() const override; -}; - -class API_EXPORT RdbFaultHiViewReporter { +class RdbFaultHiViewReporter { public: using Collector = int32_t (*)(const RdbStoreConfig &config, std::map&, DistributedRdb::RdbDfxInfo&); @@ -118,6 +113,8 @@ public: static void ReportRestore(const RdbCorruptedEvent &eventInfo, bool repair = true); static bool IsReportCorruptedFault(const std::string &dbPath); static std::string GetBundleName(const std::string &bundleName, const std::string &storeName); + static void ReportRAGFault(const std::string &errMsg, const std::string &functionName, + const std::string &bundleName, const int faultType, const int errCode); private: static void Update(std::map &localInfos, const std::map &infos); diff --git a/relational_store/frameworks/native/dfx/src/rdb_fault_hiview_reporter.cpp b/relational_store/frameworks/native/dfx/src/rdb_fault_hiview_reporter.cpp index e561d799..1706ea09 100644 --- a/relational_store/frameworks/native/dfx/src/rdb_fault_hiview_reporter.cpp +++ b/relational_store/frameworks/native/dfx/src/rdb_fault_hiview_reporter.cpp @@ -21,29 +21,27 @@ #include #include +#include #include #include #include -#include -#include "accesstoken_kit.h" #include "connection.h" #include "hisysevent_c.h" -#include "ipc_skeleton.h" #include "logger.h" #include "rdb_errno.h" +#include "rdb_time_utils.h" #include "sqlite_global_config.h" #include "sqlite_utils.h" -#include "rdb_time_utils.h" namespace OHOS::NativeRdb { using namespace OHOS::Rdb; -using namespace Security::AccessToken; static constexpr const char *CORRUPTED_EVENT = "DATABASE_CORRUPTED"; static constexpr const char *FAULT_EVENT = "DISTRIBUTED_DATA_RDB_FAULT"; static constexpr const char *DISTRIBUTED_DATAMGR = "DISTDATAMGR"; static constexpr const char *DB_CORRUPTED_POSTFIX = ".corruptedflg"; static constexpr int MAX_FAULT_TIMES = 1; +static constexpr const char *RAG_FAULT_EVENT_NAME = "ARKDATA_RAG_FRAMEWORK_FAULT"; RdbFaultHiViewReporter::Collector RdbFaultHiViewReporter::collector_ = nullptr; RdbFaultCode RdbFaultHiViewReporter::faultCounters_[] = { @@ -52,19 +50,12 @@ RdbFaultCode RdbFaultHiViewReporter::faultCounters_[] = { { E_SQLITE_CORRUPT, 0 }, { E_SQLITE_PERM, 0 }, { E_SQLITE_BUSY, 0 }, + { E_SQLITE_LOCKED, 0 }, { E_SQLITE_NOMEM, 0 }, { E_SQLITE_IOERR, 0 }, { E_SQLITE_CANTOPEN, 0 }, { E_SQLITE_CONSTRAINT, 0 }, { E_SQLITE_NOT_DB, 0 }, - { E_ROOT_KEY_FAULT, 0 }, - { E_ROOT_KEY_NOT_LOAD, 0 }, - { E_WORK_KEY_FAIL, 0 }, - { E_WORK_KEY_ENCRYPT_FAIL, 0 }, - { E_WORK_KEY_DECRYPT_FAIL, 0 }, - { E_SET_ENCRYPT_FAIL, 0 }, - { E_SET_NEW_ENCRYPT_FAIL, 0 }, - { E_SET_SERVICE_ENCRYPT_FAIL, 0 }, { E_CHECK_POINT_FAIL, 0 }, { E_SQLITE_META_RECOVERED, 0 }, { E_DFX_IS_NOT_CREATE, 0 }, @@ -76,8 +67,29 @@ RdbFaultCode RdbFaultHiViewReporter::faultCounters_[] = { { E_DFX_GET_JOURNAL_FAIL, 0 }, { E_DFX_SET_JOURNAL_FAIL, 0 }, { E_DFX_DUMP_INFO, 0 }, + { E_ROOT_KEY_FAULT, 0 }, + { E_ROOT_KEY_NOT_LOAD, 0 }, + { E_WORK_KEY_FAIL, 0 }, + { E_WORK_KEY_ENCRYPT_FAIL, 0 }, + { E_WORK_KEY_DECRYPT_FAIL, 0 }, + { E_SET_ENCRYPT_FAIL, 0 }, + { E_SET_NEW_ENCRYPT_FAIL, 0 }, + { E_SET_SERVICE_ENCRYPT_FAIL, 0 }, + { E_DFX_HUKS_GEN_RANDOM_FAIL, 0 }, }; +//static constexpr bool IsIncreasing() +//{ +// for (size_t i = 1; i < sizeof(faultCounters_) / sizeof(RdbFaultCode); i++) { +// if (faultCounters_[i].nativeCode <= faultCounters_[i - 1].nativeCode) { +// return false; +// } +// } +// return true; +//} +//// JS_ERROR_CODE_MSGS must ensure increment +//static_assert(IsIncreasing()); + bool RdbFaultHiViewReporter::memCorruptReportedFlg_ = false; void RdbFaultHiViewReporter::ReportCorruptedOnce(const RdbCorruptedEvent &eventInfo) @@ -134,6 +146,32 @@ void RdbFaultHiViewReporter::ReportCorrupted(const RdbCorruptedEvent &eventInfo) OH_HiSysEvent_Write(DISTRIBUTED_DATAMGR, CORRUPTED_EVENT, HISYSEVENT_FAULT, params, size); } +void RdbFaultHiViewReporter::ReportRAGFault(const std::string &errMsg, const std::string &functionName, + const std::string &bundleName, const int faultType, const int errCode) +{ + std::string appendix = ""; + HiSysEventParam params[] = { + { .name = "FAULT_TYPE", .t = HISYSEVENT_INT32, .v = { .ui32 = static_cast(faultType) }, .arraySize = 0 }, + { .name = "ERROR_CODE", .t = HISYSEVENT_INT32, .v = { .ui32 = static_cast(errCode) }, .arraySize = 0 }, + { .name = "ERROR_MESSAGE", + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(errMsg.c_str()) }, + .arraySize = 0 }, + { .name = "BUNDLE_NAME", + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(bundleName.c_str()) }, + .arraySize = 0 }, + { .name = "FUNCTION_NAME", + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(functionName.c_str()) }, + .arraySize = 0 }, + { .name = "APPENDIX", .t = HISYSEVENT_STRING, .v = { .s = const_cast(appendix.c_str()) }, .arraySize = 0 }, + }; + + OH_HiSysEvent_Write( + DISTRIBUTED_DATAMGR, RAG_FAULT_EVENT_NAME, HISYSEVENT_FAULT, params, sizeof(params) / sizeof(params[0])); +} + bool RdbFaultHiViewReporter::IsReportCorruptedFault(const std::string &dbPath) { if (dbPath.empty() || memCorruptReportedFlg_) { @@ -154,7 +192,7 @@ void RdbFaultHiViewReporter::CreateCorruptedFlag(const std::string &dbPath) return; } std::string flagFilename = dbPath + DB_CORRUPTED_POSTFIX; - int fd = creat(flagFilename.c_str(), S_IRWXU | S_IRWXG); + int fd = creat(flagFilename.c_str(), S_IRUSR | S_IWUSR); if (fd == -1) { LOG_WARN("Creat corrupted flg fail, flgname=%{public}s, errno=%{public}d", SqliteUtils::Anonymous(flagFilename).c_str(), errno); @@ -240,14 +278,6 @@ std::string RdbFaultHiViewReporter::GetBundleName(const std::string &bundleName, if (!bundleName.empty()) { return bundleName; } - auto tokenId = IPCSkeleton::GetCallingTokenID(); - auto tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId); - if ((tokenType == TOKEN_NATIVE) || (tokenType == TOKEN_SHELL)) { - NativeTokenInfo tokenInfo; - if (AccessTokenKit::GetNativeTokenInfo(tokenId, tokenInfo) == 0) { - return tokenInfo.processName; - } - } return SqliteUtils::Anonymous(storeName); } @@ -319,29 +349,6 @@ RdbFaultDbFileEvent::RdbFaultDbFileEvent(const std::string &faultType, int32_t e { } -RdbEmptyBlobEvent::RdbEmptyBlobEvent(const std::string &bundleName) - : RdbFaultEvent(FT_CURD, E_SQLITE_FULL, "", "The input blob is empty") -{ - SetBundleName(bundleName); -} - -void RdbEmptyBlobEvent::Report() const -{ - std::string occurTime = RdbTimeUtils::GetCurSysTimeWithMs(); - std::string bundleName = GetBundleName(); - std::string faultType = GetFaultType(); - std::string appendInfo = GetLogInfo(); - HiSysEventParam params[] = { - { .name = "FAULT_TIME", .t = HISYSEVENT_STRING, .v = { .s = occurTime.data() }, .arraySize = 0 }, - { .name = "FAULT_TYPE", .t = HISYSEVENT_STRING, .v = { .s = faultType.data() }, .arraySize = 0 }, - { .name = "BUNDLE_NAME", .t = HISYSEVENT_STRING, .v = { .s = bundleName.data() }, .arraySize = 0 }, - { .name = "ERROR_CODE", .t = HISYSEVENT_INT32, .v = { .ui32 = E_SQLITE_FULL }, .arraySize = 0 }, - { .name = "APPENDIX", .t = HISYSEVENT_STRING, .v = { .s = appendInfo.data() }, .arraySize = 0 }, - }; - auto size = sizeof(params) / sizeof(params[0]); - OH_HiSysEvent_Write(DISTRIBUTED_DATAMGR, FAULT_EVENT, HISYSEVENT_FAULT, params, size); -} - void RdbFaultDbFileEvent::Report() const { std::string occurTime = RdbTimeUtils::GetCurSysTimeWithMs(); diff --git a/relational_store/frameworks/native/dfx/src/rdb_radar_reporter.cpp b/relational_store/frameworks/native/dfx/src/rdb_radar_reporter.cpp index 8e872841..acc8a5e0 100644 --- a/relational_store/frameworks/native/dfx/src/rdb_radar_reporter.cpp +++ b/relational_store/frameworks/native/dfx/src/rdb_radar_reporter.cpp @@ -15,15 +15,11 @@ #include "rdb_radar_reporter.h" -#include "accesstoken_kit.h" #include "hisysevent_c.h" -#include "ipc_skeleton.h" #include "rdb_errno.h" namespace OHOS::NativeRdb { -using namespace Security::AccessToken; - static constexpr const char *ORG_PKG_VALUE = "distributeddata"; static constexpr const char *EVENT_NAME = "DISTRIBUTED_RDB_BEHAVIOR"; static constexpr const char *UNKNOW = "unknow"; @@ -91,16 +87,7 @@ std::string RdbRadar::GetHostPkgInfo() if (!hostPkg_.empty()) { return hostPkg_; } - auto tokenId = IPCSkeleton::GetCallingTokenID(); - auto tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId); - if ((tokenType == TOKEN_NATIVE) || (tokenType == TOKEN_SHELL)) { - NativeTokenInfo tokenInfo; - if (AccessTokenKit::GetNativeTokenInfo(tokenId, tokenInfo) == 0) { - hostPkg_ = tokenInfo.processName; - } - } else { - hostPkg_ = bundleName_; - } + hostPkg_ = bundleName_; return hostPkg_; } } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/dfx/src/rdb_stat_reporter.cpp b/relational_store/frameworks/native/dfx/src/rdb_stat_reporter.cpp index c56e3757..9e7ab491 100644 --- a/relational_store/frameworks/native/dfx/src/rdb_stat_reporter.cpp +++ b/relational_store/frameworks/native/dfx/src/rdb_stat_reporter.cpp @@ -58,10 +58,12 @@ RdbStatReporter::~RdbStatReporter() auto loadedReportTime = reportTime_.load(); auto reportInterval = std::chrono::duration_cast(endTime - loadedReportTime).count(); statEvent_.costTime = GetTimeType(static_cast(duration)); - if (statEvent_.costTime > TIME_LEVEL_NONE && reportInterval >= WAIT_TIME) { + if (statEvent_.costTime > TIME_LEVEL_NONE && + (loadedReportTime == std::chrono::steady_clock::time_point() || reportInterval >= WAIT_TIME)) { auto pool = TaskExecutor::GetInstance().GetExecutor(); if (pool == nullptr) { LOG_WARN("task pool err when RdbStatReporter"); + return; } pool->Execute([report = std::move(reportFunc_), statEvent = std::move(statEvent_)]() { (*report)(statEvent); diff --git a/relational_store/frameworks/native/dlopen_rdb/BUILD.gn b/relational_store/frameworks/native/dlopen_rdb/BUILD.gn new file mode 100644 index 00000000..0497be36 --- /dev/null +++ b/relational_store/frameworks/native/dlopen_rdb/BUILD.gn @@ -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. +import("//build/ohos.gni") +import("//build/ohos/ace/ace.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +group("build_module") { + deps = [] + if (relational_store_rdb_support_icu) { + deps += [ ":dlopen_rdb_demo" ] + } +} + +ohos_shared_library("dlopen_rdb_demo") { + branch_protector_ret = "pac_ret" + sanitize = { + boundary_sanitize = true + ubsan = true + cfi = true + cfi_cross_dso = true + debug = false + } + + ldflags = [ "-Wl,--exclude-libs,ALL" ] + cflags_cc = [ "-fvisibility=hidden" ] + + include_dirs = [ + "${relational_store_common_path}/include", + "${relational_store_innerapi_path}/rdb/include", + ] + + sources = [ "${relational_store_native_path}/dlopen_rdb/dlopen_rdb.cpp" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "relational_store:native_rdb", + ] + subsystem_name = "distributeddatamgr" + part_name = "relational_store" +} diff --git a/relational_store/frameworks/native/dlopen_rdb/dlopen_rdb.cpp b/relational_store/frameworks/native/dlopen_rdb/dlopen_rdb.cpp new file mode 100644 index 00000000..714d090f --- /dev/null +++ b/relational_store/frameworks/native/dlopen_rdb/dlopen_rdb.cpp @@ -0,0 +1,177 @@ +/* +* 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. +*/ + +#define LOG_TAG "Dlopen_RDB" + +#include +#include + +#include "logger.h" +#include "rdb_helper.h" +#include "rdb_visibility.h" + +using namespace OHOS::DistributedRdb; +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; +API_EXPORT int32_t Demo(const std::string &dbPath) asm("Demo"); +class RdbHelperTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string CREATE_TABLE_TEST; +}; + +const std::string RdbHelperTestOpenCallback::CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, " + "blobType BLOB)"; + +int RdbHelperTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_TEST); +} + +int RdbHelperTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} +class DemoRdbStoreObserver : public RdbStoreObserver { +public: + virtual ~DemoRdbStoreObserver(){}; + void OnChange(const std::vector &devices) override + { + LOG_INFO("OnChange devices"); + } + void OnChange(const Origin &origin, const PrimaryFields &fields, ChangeInfo &&changeInfo) override + { + LOG_INFO("OnChange store:%{public}s", origin.store.c_str()); + } + void OnChange() override + { + LOG_INFO("OnChange null"); + } +}; + +class Subscriber { +public: + Subscriber(std::shared_ptr store) : rdbstore_(store) + { + if (rdbstore_ == nullptr) { + return; + } + SubscribeOption option; + option.mode = SubscribeMode::LOCAL; + rdbstore_->Subscribe(option, localObs_); + + option.mode = SubscribeMode::LOCAL_SHARED; + option.event = "demoTest"; + rdbstore_->Subscribe(option, localSharedObs_); + + option.mode = SubscribeMode::LOCAL_DETAIL; + rdbstore_->SubscribeObserver(option, localDetailObs_); + } + ~Subscriber() + { + if (rdbstore_ == nullptr) { + return; + } + SubscribeOption option; + option.mode = SubscribeMode::LOCAL; + rdbstore_->UnSubscribe(option, localObs_); + + option.mode = SubscribeMode::LOCAL_SHARED; + option.event = "demoTest"; + rdbstore_->UnSubscribe(option, localSharedObs_); + + option.mode = SubscribeMode::LOCAL_DETAIL; + rdbstore_->UnsubscribeObserver(option, localDetailObs_); + } + +private: + std::shared_ptr rdbstore_; + std::shared_ptr localObs_ = std::make_shared(); + std::shared_ptr localSharedObs_ = std::make_shared(); + std::shared_ptr localDetailObs_ = std::make_shared(); +}; + +int32_t Crud(std::shared_ptr rdbStore) +{ + int64_t id; + ValuesBucket values; + int deletedRows; + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = rdbStore->Insert(id, "test", values); + if (ret != E_OK) { + return ret; + } + values.PutString("name", "update"); + values.PutInt("age", 20); + int changedRows = -1; + AbsRdbPredicates predicates("test"); + ret = rdbStore->Update(changedRows, values, predicates); + if (ret != E_OK) { + return ret; + } + + auto result = rdbStore->Query(predicates); + + if (result == nullptr) { + return E_ERROR; + } + + int32_t rowCount = -1; + ret = result->GetRowCount(rowCount); + if (ret != E_OK) { + return ret; + } + + ret = rdbStore->Delete(deletedRows, "test", "id = 1", std::vector()); + if (ret != E_OK) { + return ret; + } +} + +int32_t Demo(const std::string &dbPath) +{ + RdbStoreConfig config(dbPath); + config.SetName("dlopenTest.db"); + config.SetEncryptStatus(true); + std::string bundleName = "com.ohos.dlopenTest"; + config.SetBundleName(bundleName); + int errCode = E_OK; + + RdbHelperTestOpenCallback helper; + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + + if (rdbStore == nullptr) { + return E_ERROR; + } + Subscriber subscriber(rdbStore); + + errCode = rdbStore->Notify("demoTest"); + if (errCode != E_OK) { + return errCode; + } + + errCode = Crud(rdbStore); + if (errCode != E_OK) { + return errCode; + } +} \ No newline at end of file diff --git a/kv_store/test/fuzztest/singlekvstorestub_fuzzer/singlekvstorestub_fuzzer.h b/relational_store/frameworks/native/dlopen_rdb/dlopen_rdb.h similarity index 74% rename from kv_store/test/fuzztest/singlekvstorestub_fuzzer/singlekvstorestub_fuzzer.h rename to relational_store/frameworks/native/dlopen_rdb/dlopen_rdb.h index b2652170..86b400ae 100644 --- a/kv_store/test/fuzztest/singlekvstorestub_fuzzer/singlekvstorestub_fuzzer.h +++ b/relational_store/frameworks/native/dlopen_rdb/dlopen_rdb.h @@ -12,11 +12,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef LDBPROJ_DLOPEN_RDB_H +#define LDBPROJ_DLOPEN_RDB_H -#ifndef SINGLEKVSTORESTUB_FUZZER_H -#define SINGLEKVSTORESTUB_FUZZER_H - -#define FUZZ_PROJECT_NAME "singlekvstorestub_fuzzer" - -#endif // SINGLEKVSTORESTUB_FUZZER_H +namespace OHOS { +namespace DistributedData { +class dlopen_rdb { +}; +} // namespace DistributedData +} // namespace OHOS +#endif //LDBPROJ_DLOPEN_RDB_H diff --git a/relational_store/frameworks/native/gdb/adapter/include/grd_adapter.h b/relational_store/frameworks/native/gdb/adapter/include/grd_adapter.h deleted file mode 100644 index a59ed59b..00000000 --- a/relational_store/frameworks/native/gdb/adapter/include/grd_adapter.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRD_ADAPTER_H -#define OHOS_DISTRIBUTED_DATA_OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRD_ADAPTER_H - -#include -#include -#include -#include - -#include "full_result.h" -#include "statement.h" -#include "grd_type_export.h" - -namespace OHOS::DistributedDataAip { - -class GrdAdapter { -public: - static ColumnType TransColType(int grdColType); - static int Open(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB **db); - static int Repair(const char *dbPath, const char *configStr); - static int Close(GRD_DB *db, uint32_t flags); - - /* graph */ - static int32_t Prepare(GRD_DB *db, const char *str, uint32_t strLen, GRD_StmtT **stmt, const char **unusedStr); - static int32_t Reset(GRD_StmtT *stmt); - static int32_t Finalize(GRD_StmtT *stmt); - - static int32_t Step(GRD_StmtT *stmt); - static uint32_t ColumnCount(GRD_StmtT *stmt); - static GRD_DbDataTypeE ColumnType(GRD_StmtT *stmt, uint32_t idx); - static uint32_t ColumnBytes(GRD_StmtT *stmt, uint32_t idx); - static char *ColumnName(GRD_StmtT *stmt, uint32_t idx); - static GRD_DbValueT ColumnValue(GRD_StmtT *stmt, uint32_t idx); - static int64_t ColumnInt64(GRD_StmtT *stmt, uint32_t idx); - static int32_t ColumnInt(GRD_StmtT *stmt, uint32_t idx); - static double ColumnDouble(GRD_StmtT *stmt, uint32_t idx); - static const char *ColumnText(GRD_StmtT *stmt, uint32_t idx); - - static int Backup(GRD_DB *db, const char *backupDbFile, const std::vector &encryptedKey); - static int Restore(const char *dbFile, const char *backupDbFile, const std::vector &encryptedKey); - static int Rekey(const char *dbFile, const char *configStr, const std::vector &encryptedKey); - -private: - static int TransErrno(int err); - - static std::map GRD_ERRNO_MAP; -}; - -} // namespace OHOS::DistributedDataAip -#endif \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/adapter/include/grd_adapter_manager.h b/relational_store/frameworks/native/gdb/adapter/include/grd_adapter_manager.h deleted file mode 100644 index 2f6eac3f..00000000 --- a/relational_store/frameworks/native/gdb/adapter/include/grd_adapter_manager.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -* 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 OHOS_DISTRIBUTED_DATA_OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRD_ADAPTER_MANAGER_H -#define OHOS_DISTRIBUTED_DATA_OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRD_ADAPTER_MANAGER_H - -#include "grd_type_export.h" - -namespace OHOS::DistributedDataAip { - -typedef int32_t (*Open)(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB **db); -typedef int32_t (*Close)(GRD_DB *db, uint32_t flags); -typedef int32_t (*Repair)(const char *dbPath, const char *configStr); - -typedef int32_t (*Prepare)(GRD_DB *db, const char *str, uint32_t strLen, GRD_StmtT **stmt, const char **unusedStr); -typedef int32_t (*Reset)(GRD_StmtT *stmt); -typedef int32_t (*Finalize)(GRD_StmtT *stmt); - -typedef int32_t (*Step)(GRD_StmtT *stmt); -typedef uint32_t (*ColumnCount)(GRD_StmtT *stmt); -typedef GRD_DbDataTypeE (*GetColumnType)(GRD_StmtT *stmt, uint32_t idx); -typedef uint32_t (*ColumnBytes)(GRD_StmtT *stmt, uint32_t idx); -typedef char *(*ColumnName)(GRD_StmtT *stmt, uint32_t idx); -typedef GRD_DbValueT (*ColumnValue)(GRD_StmtT *stmt, uint32_t idx); -typedef int64_t (*ColumnInt64)(GRD_StmtT *stmt, uint32_t idx); -typedef int32_t (*ColumnInt)(GRD_StmtT *stmt, uint32_t idx); -typedef double (*ColumnDouble)(GRD_StmtT *stmt, uint32_t idx); -typedef const char *(*ColumnText)(GRD_StmtT *stmt, uint32_t idx); - -typedef int32_t (*Backup)(GRD_DB *db, const char *backupDbFile, GRD_CipherInfoT *cipherInfo); -typedef int32_t (*Restore)(const char *dbFile, const char *backupDbFile, GRD_CipherInfoT *cipherInfo); -typedef int32_t (*Rekey)(const char *dbFile, const char *configStr, GRD_CipherInfoT *cipherInfo); - -struct GrdAdapterHolder { - Open Open = nullptr; - Close Close = nullptr; - Repair Repair = nullptr; - - Prepare Prepare = nullptr; - Reset Reset = nullptr; - Finalize Finalize = nullptr; - Step Step = nullptr; - ColumnCount ColumnCount = nullptr; - GetColumnType GetColumnType = nullptr; - ColumnBytes ColumnBytes = nullptr; - ColumnName ColumnName = nullptr; - ColumnValue ColumnValue = nullptr; - ColumnInt64 ColumnInt64 = nullptr; - ColumnInt ColumnInt = nullptr; - ColumnDouble ColumnDouble = nullptr; - ColumnText ColumnText = nullptr; - - Backup Backup = nullptr; - Restore Restore = nullptr; - Rekey Rekey = nullptr; -}; - -bool IsSupportArkDataDb(); -GrdAdapterHolder GetAdapterHolder(); - -static void *g_library = nullptr; - -} // namespace OHOS::DistributedDataAip - -#endif // OHOS_DISTRIBUTED_DATA_OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRD_ADAPTER_MANAGER_H diff --git a/relational_store/frameworks/native/gdb/adapter/src/grd_adapter.cpp b/relational_store/frameworks/native/gdb/adapter/src/grd_adapter.cpp deleted file mode 100644 index 1b2129ce..00000000 --- a/relational_store/frameworks/native/gdb/adapter/src/grd_adapter.cpp +++ /dev/null @@ -1,388 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "GrdAdapter" - -#include "grd_adapter.h" - -#include -#include - -#include "gdb_errors.h" -#include "gdb_utils.h" -#include "grd_adapter_manager.h" -#include "grd_error.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { - -static GrdAdapterHolder g_adapterHolder; - -std::map GrdAdapter::GRD_ERRNO_MAP = { - { GRD_OK, E_OK }, - { GRD_REBUILD_DATABASE, E_OK }, - { GRD_NO_DATA, E_GRD_NO_DATA }, - { GRD_DATA_CORRUPTED, E_GRD_DATA_CORRUPTED }, - { GRD_INVALID_FILE_FORMAT, E_GRD_INVALID_FILE_FORMAT }, - { GRD_PRIMARY_KEY_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_RESTRICT_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_CONSTRAINT_CHECK_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_NOT_SUPPORT, E_GRD_NOT_SUPPORT }, - { GRD_OVER_LIMIT, E_GRD_OVER_LIMIT }, - { GRD_INVALID_ARGS, E_GRD_INVALID_ARGS }, - { GRD_FAILED_FILE_OPERATION, E_GRD_FAILED_FILE_OPERATION }, - { GRD_INSUFFICIENT_SPACE, E_GRD_DISK_SPACE_FULL }, - { GRD_RESOURCE_BUSY, E_DATABASE_BUSY }, - { GRD_DB_BUSY, E_DATABASE_BUSY }, - { GRD_FAILED_MEMORY_ALLOCATE, E_GRD_FAILED_MEMORY_ALLOCATE }, - { GRD_CRC_CHECK_DISABLED, E_GRD_CRC_CHECK_DISABLED }, - { GRD_DISK_SPACE_FULL, E_GRD_DISK_SPACE_FULL }, - - { GRD_PERMISSION_DENIED, E_GRD_PERMISSION_DENIED }, - { GRD_PASSWORD_UNMATCHED, E_GRD_PASSWORD_UNMATCHED }, - { GRD_PASSWORD_NEED_REKEY, E_GRD_PASSWORD_NEED_REKEY }, - - { GRD_NAME_TOO_LONG, E_GRD_INVALID_NAME }, - { GRD_INVALID_TABLE_DEFINITION, E_GRD_SEMANTIC_ERROR }, - { GRD_SEMANTIC_ERROR, E_GRD_SEMANTIC_ERROR }, - { GRD_SYNTAX_ERROR, E_GRD_SYNTAX_ERROR }, - { GRD_WRONG_STMT_OBJECT, E_GRD_WRONG_STMT_OBJECT }, - { GRD_DATA_CONFLICT, E_GRD_DATA_CONFLICT }, - - { GRD_INNER_ERR, E_GRD_INNER_ERR }, - { GRD_FAILED_MEMORY_RELEASE, E_GRD_FAILED_MEMORY_RELEASE }, - { GRD_NOT_AVAILABLE, E_GRD_NOT_AVAILABLE }, - { GRD_INVALID_FORMAT, E_GRD_SEMANTIC_ERROR }, - { GRD_TIME_OUT, E_DATABASE_BUSY }, - { GRD_DB_INSTANCE_ABNORMAL, E_GRD_DB_INSTANCE_ABNORMAL }, - { GRD_CIPHER_ERROR, E_GRD_CIPHER_ERROR }, - { GRD_DUPLICATE_TABLE, E_GRD_DUPLICATE_PARAM }, - { GRD_DUPLICATE_OBJECT, E_GRD_DUPLICATE_PARAM }, - { GRD_DUPLICATE_COLUMN, E_GRD_DUPLICATE_PARAM }, - { GRD_UNDEFINE_COLUMN, E_GRD_UNDEFINED_PARAM }, - { GRD_UNDEFINED_OBJECT, E_GRD_UNDEFINED_PARAM }, - { GRD_UNDEFINED_TABLE, E_GRD_UNDEFINED_PARAM }, - { GRD_INVALID_CONFIG_VALUE, E_CONFIG_INVALID_CHANGE }, - { GRD_REQUEST_TIME_OUT, E_DATABASE_BUSY }, - { GRD_DATATYPE_MISMATCH, E_GRD_SEMANTIC_ERROR }, - { GRD_UNIQUE_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_INVALID_BIND_VALUE, E_GRD_INVALID_BIND_VALUE }, - { GRD_JSON_OPERATION_NOT_SUPPORT, E_GRD_SEMANTIC_ERROR }, - { GRD_MODEL_NOT_SUPPORT, E_GRD_SEMANTIC_ERROR }, - { GRD_FEATURE_NOT_SUPPORTED, E_GRD_SEMANTIC_ERROR }, - { GRD_JSON_LEN_LIMIT, E_GRD_DATA_CONFLICT }, - { GRD_SUBSCRIPTION_EXCEEDED_LIMIT, E_GRD_INNER_ERR }, - { GRD_SYNC_EXCEED_TASK_QUEUE_LIMIT, E_DATABASE_BUSY }, - { GRD_SHARED_OBJ_ENABLE_UNDO_EXCEED_LIMIT, E_GRD_INNER_ERR }, - { GRD_TABLE_LIMIT_EXCEEDED, E_GRD_OVER_LIMIT }, - { GRD_FIELD_TYPE_NOT_MATCH, E_GRD_SEMANTIC_ERROR }, - { GRD_LARGE_JSON_NEST, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_JSON_TYPE, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_OPERATOR, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_PROJECTION_FIELD, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_PROJECTION_VALUE, E_GRD_SEMANTIC_ERROR }, - { GRD_DB_NOT_EXIST, E_GRD_DB_NOT_EXIST }, - { GRD_INVALID_VALUE, E_GRD_INVALID_ARGS }, - { GRD_SHARED_OBJ_NOT_EXIST, E_GRD_DATA_NOT_FOUND }, - { GRD_SUBSCRIBE_NOT_EXIST, E_GRD_DATA_NOT_FOUND }, - { GRD_COLLECTION_NOT_EXIST, E_GRD_DATA_NOT_FOUND }, - { GRD_RESULTSET_BUSY, E_DATABASE_BUSY }, - { GRD_RECORD_NOT_FOUND, E_GRD_DATA_NOT_FOUND }, - { GRD_FIELD_NOT_FOUND, E_GRD_DATA_NOT_FOUND }, - { GRD_ARRAY_INDEX_NOT_FOUND, E_GRD_DATA_NOT_FOUND }, - { GRD_RESULT_SET_NOT_AVAILABLE, E_GRD_DATA_NOT_FOUND }, - { GRD_SHARED_OBJ_UNDO_NOT_AVAILABLE, E_GRD_DATA_NOT_FOUND }, - { GRD_SHARED_OBJ_REDO_NOT_AVAILABLE, E_GRD_DATA_NOT_FOUND }, - { GRD_INVALID_JSON_FORMAT, E_GRD_DATA_CONFLICT }, - { GRD_INVALID_KEY_FORMAT, E_GRD_INVALID_NAME }, - { GRD_INVALID_COLLECTION_NAME, E_GRD_INVALID_NAME }, - { GRD_INVALID_EQUIP_ID, E_GRD_SEMANTIC_ERROR }, - { GRD_KEY_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_FIELD_TYPE_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_SHARED_OBJ_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_SUBSCRIBE_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_EQUIP_ID_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_SHARED_OBJ_ENABLE_UNDO_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_SCHEMA_CHANGED, E_CONFIG_INVALID_CHANGE }, - { GRD_DATA_EXCEPTION, E_GRD_DATA_EXCEPTION }, - { GRD_FIELD_OVERFLOW, E_GRD_SEMANTIC_ERROR }, - { GRD_DIVISION_BY_ZERO, E_GRD_SYNTAX_ERROR }, - { GRD_TRANSACTION_ROLLBACK, E_GRD_TRANSACTION_ROLLBACK }, - { GRD_NO_ACTIVE_TRANSACTION, E_GRD_NO_ACTIVE_TRANSACTION }, - { GRD_ACTIVE_TRANSACTION, E_GRD_ACTIVE_TRANSACTION }, -}; - -int GrdAdapter::TransErrno(int err) -{ - if (err > 0) { - return err; - } - auto result = GRD_ERRNO_MAP.find(err); - if (result != GRD_ERRNO_MAP.end()) { - return result->second; - } - return E_GRD_INNER_ERR; -} - -ColumnType GrdAdapter::TransColType(int grdColType) -{ - switch (grdColType) { - case GRD_DB_DATATYPE_INTEGER: - return ColumnType::TYPE_INTEGER; - case GRD_DB_DATATYPE_FLOAT: - return ColumnType::TYPE_FLOAT; - case GRD_DB_DATATYPE_TEXT: - return ColumnType::TYPE_TEXT; - case GRD_DB_DATATYPE_BLOB: - return ColumnType::TYPE_BLOB; - case GRD_DB_DATATYPE_FLOATVECTOR: - return ColumnType::TYPE_FLOATVECTOR; - case GRD_DB_DATATYPE_JSONSTR: - return ColumnType::TYPE_JSONSTR; - case GRD_DB_DATATYPE_NULL: - return ColumnType::TYPE_NULL; - default: - LOG_ERROR("trans failed. GRD_DbDataTypeE=%{public}d.", grdColType); - return ColumnType::TYPE_NULL; - } -} - -int GrdAdapter::Open(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB **db) -{ - if (g_adapterHolder.Open == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Open == nullptr) { - return E_NOT_SUPPORT; - } - auto ret = g_adapterHolder.Open(dbPath, configStr, flags, db); - return TransErrno(ret); -} - -int GrdAdapter::Close(GRD_DB *db, uint32_t flags) -{ - if (g_adapterHolder.Close == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Close == nullptr) { - return E_NOT_SUPPORT; - } - auto ret = g_adapterHolder.Close(db, flags); - LOG_DEBUG("Close ret=%{public}d", ret); - return TransErrno(ret); -} - -int GrdAdapter::Repair(const char *dbPath, const char *configStr) -{ - if (g_adapterHolder.Repair == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Repair == nullptr) { - return E_NOT_SUPPORT; - } - return E_NOT_SUPPORT; -} - -int GrdAdapter::Backup(GRD_DB *db, const char *backupDbFile, const std::vector &encryptedKey) -{ - if (g_adapterHolder.Backup == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Backup == nullptr) { - return E_NOT_SUPPORT; - } - return E_NOT_SUPPORT; -} - -int GrdAdapter::Restore(const char *dbFile, const char *backupDbFile, const std::vector &encryptedKey) -{ - if (g_adapterHolder.Restore == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Restore == nullptr) { - return E_NOT_SUPPORT; - } - return E_NOT_SUPPORT; -} - -int GrdAdapter::Rekey(const char *dbFile, const char *configStr, const std::vector &encryptedKey) -{ - if (g_adapterHolder.Rekey == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Rekey == nullptr) { - return E_NOT_SUPPORT; - } - if (encryptedKey.empty()) { - return E_GRD_INVALID_ARGS; - } - int32_t ret = E_OK; - GRD_CipherInfoT info = { 0 }; - const size_t keySize = encryptedKey.size() * 2 + 1; // 2 hex number can represent a uint8_t, 1 is for '\0' - std::vector key(keySize); - info.hexPassword = GdbUtils::GetEncryptKey(encryptedKey, key.data(), keySize); - ret = g_adapterHolder.Rekey(dbFile, configStr, &info); - key.assign(keySize, 0); - return TransErrno(ret); -} - -int32_t GrdAdapter::Prepare(GRD_DB *db, const char *str, uint32_t strLen, GRD_StmtT **stmt, const char **unusedStr) -{ - if (g_adapterHolder.Prepare == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Prepare == nullptr) { - return E_NOT_SUPPORT; - } - int32_t ret = g_adapterHolder.Prepare(db, str, strLen, stmt, unusedStr); - return TransErrno(ret); -} - -int32_t GrdAdapter::Reset(GRD_StmtT *stmt) -{ - if (g_adapterHolder.Reset == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Reset == nullptr) { - return E_NOT_SUPPORT; - } - return TransErrno(g_adapterHolder.Reset(stmt)); -} - -int32_t GrdAdapter::Finalize(GRD_StmtT *stmt) -{ - if (g_adapterHolder.Finalize == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Finalize == nullptr) { - return E_NOT_SUPPORT; - } - int32_t ret = g_adapterHolder.Finalize(stmt); - LOG_DEBUG("Finalize ret=%{public}d", ret); - return TransErrno(ret); -} - -int32_t GrdAdapter::Step(GRD_StmtT *stmt) -{ - if (g_adapterHolder.Step == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Step == nullptr) { - return E_NOT_SUPPORT; - } - int32_t ret = g_adapterHolder.Step(stmt); - LOG_DEBUG("Step ret=%{public}d", ret); - return TransErrno(ret); -} - -uint32_t GrdAdapter::ColumnCount(GRD_StmtT *stmt) -{ - if (g_adapterHolder.ColumnCount == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnCount == nullptr) { - return E_NOT_SUPPORT; - } - return g_adapterHolder.ColumnCount(stmt); -} - -GRD_DbDataTypeE GrdAdapter::ColumnType(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.GetColumnType == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.GetColumnType == nullptr) { - return GRD_DB_DATATYPE_NULL; - } - return g_adapterHolder.GetColumnType(stmt, idx); -} - -uint32_t GrdAdapter::ColumnBytes(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnBytes == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnBytes == nullptr) { - return E_NOT_SUPPORT; - } - return g_adapterHolder.ColumnBytes(stmt, idx); -} - -char *GrdAdapter::ColumnName(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnName == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnName == nullptr) { - return nullptr; - } - return g_adapterHolder.ColumnName(stmt, idx); -} - -GRD_DbValueT GrdAdapter::ColumnValue(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnValue == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnValue == nullptr) { - return {}; - } - return g_adapterHolder.ColumnValue(stmt, idx); -} - -int64_t GrdAdapter::ColumnInt64(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnInt64 == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnInt64 == nullptr) { - return 0; - } - return g_adapterHolder.ColumnInt64(stmt, idx); -} - -int32_t GrdAdapter::ColumnInt(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnInt == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnInt == nullptr) { - return 0; - } - return g_adapterHolder.ColumnInt(stmt, idx); -} - -double GrdAdapter::ColumnDouble(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnDouble == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnDouble == nullptr) { - return 0; - } - return g_adapterHolder.ColumnDouble(stmt, idx); -} - -const char *GrdAdapter::ColumnText(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnText == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnText == nullptr) { - return nullptr; - } - return g_adapterHolder.ColumnText(stmt, idx); -} - -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/adapter/src/grd_adapter_manager.cpp b/relational_store/frameworks/native/gdb/adapter/src/grd_adapter_manager.cpp deleted file mode 100644 index a2859a2a..00000000 --- a/relational_store/frameworks/native/gdb/adapter/src/grd_adapter_manager.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* -* 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. -*/ -#define LOG_TAG "GrdAdapter" -#include - -#include "grd_adapter_manager.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { -void GrdAdapterHolderInit(GrdAdapterHolder &adapterHolder) -{ - adapterHolder.Open = (Open)dlsym(g_library, "GRD_DBOpen"); - adapterHolder.Close = (Close)dlsym(g_library, "GRD_DBClose"); - adapterHolder.Repair = (Repair)dlsym(g_library, "GRD_DBRepair"); - adapterHolder.Backup = (Backup)dlsym(g_library, "GRD_DBBackup"); - adapterHolder.Restore = (Restore)dlsym(g_library, "GRD_DBRestore"); - adapterHolder.Rekey = (Rekey)dlsym(g_library, "GRD_DBRekey"); - - adapterHolder.Prepare = (Prepare)dlsym(g_library, "GRD_GqlPrepare"); - adapterHolder.Reset = (Reset)dlsym(g_library, "GRD_GqlReset"); - adapterHolder.Finalize = (Finalize)dlsym(g_library, "GRD_GqlFinalize"); - adapterHolder.Step = (Step)dlsym(g_library, "GRD_GqlStep"); - adapterHolder.ColumnCount = (ColumnCount)dlsym(g_library, "GRD_GqlColumnCount"); - adapterHolder.GetColumnType = (GetColumnType)dlsym(g_library, "GRD_GqlColumnType"); - adapterHolder.ColumnBytes = (ColumnBytes)dlsym(g_library, "GRD_GqlColumnBytes"); - adapterHolder.ColumnName = (ColumnName)dlsym(g_library, "GRD_GqlColumnName"); - adapterHolder.ColumnValue = (ColumnValue)dlsym(g_library, "GRD_GqlColumnValue"); - adapterHolder.ColumnInt64 = (ColumnInt64)dlsym(g_library, "GRD_GqlColumnInt64"); - adapterHolder.ColumnInt = (ColumnInt)dlsym(g_library, "GRD_GqlColumnInt"); - adapterHolder.ColumnDouble = (ColumnDouble)dlsym(g_library, "GRD_GqlColumnDouble"); - adapterHolder.ColumnText = (ColumnText)dlsym(g_library, "GRD_GqlColumnText"); -} - -bool IsSupportArkDataDb() -{ -#ifdef ARKDATA_DB_CORE_IS_EXISTS - return true; -#else - return false; -#endif -} - -GrdAdapterHolder GetAdapterHolder() -{ - GrdAdapterHolder adapterHolder; - if (g_library == nullptr) { - g_library = dlopen("libarkdata_db_core.z.so", RTLD_LAZY); - } - if (g_library == nullptr) { - LOG_WARN("use default db kernel"); - return adapterHolder; - } - GrdAdapterHolderInit(adapterHolder); - return adapterHolder; -} - -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/include/connection.h b/relational_store/frameworks/native/gdb/include/connection.h deleted file mode 100644 index 52f5eaf1..00000000 --- a/relational_store/frameworks/native/gdb/include/connection.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_NATIVE_GDB_CONNECTION_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_CONNECTION_H - -#include "gdb_store_config.h" -#include "statement.h" - -namespace OHOS::DistributedDataAip { -class StoreConfig; -class Statement; -class Connection { -public: - using SConn = std::shared_ptr; - using Stmt = std::shared_ptr; - using Creator = std::pair (*)(const StoreConfig &config, bool isWriter); - static std::pair Create(const StoreConfig &config, bool isWriter); - static int32_t RegisterCreator(DBType dbType, Creator creator); - - int32_t SetId(int32_t id); - int32_t GetId() const; - virtual ~Connection() = default; - virtual std::pair CreateStatement(const std::string &gql, std::shared_ptr conn) = 0; - virtual DBType GetDBType() const = 0; - virtual bool IsWriter() const = 0; - -private: - int32_t id_ = 0; -}; -} // namespace OHOS::DistributedDataAip -#endif // OHOS_DISTRIBUTED_DATA_NATIVE_GDB_CONNECTION_H \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/include/connection_pool.h b/relational_store/frameworks/native/gdb/include/connection_pool.h deleted file mode 100644 index 2da03e16..00000000 --- a/relational_store/frameworks/native/gdb/include/connection_pool.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_NATIVE_GDB_CONNECTION_POOL_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_CONNECTION_POOL_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "connection.h" -#include "gdb_store_config.h" - -namespace OHOS::DistributedDataAip { -class ConnectionPool : public std::enable_shared_from_this { -public: - using SharedConn = std::shared_ptr; - static constexpr std::chrono::milliseconds INVALID_TIME = std::chrono::milliseconds(0); - static std::shared_ptr Create(const StoreConfig &config, int &errCode); - ~ConnectionPool(); - std::pair> CreateTransConn(); - SharedConn Acquire(bool isReadOnly, std::chrono::milliseconds ms = INVALID_TIME); - // this interface is only provided for resultSet - SharedConn AcquireRef(bool isReadOnly, std::chrono::milliseconds ms = INVALID_TIME); - int32_t Dump(bool isWriter, const char *header); - int RestartReaders(); - void CloseAllConnections(); - - explicit ConnectionPool(const StoreConfig &storeConfig); - -private: - struct ConnNode { - bool using_ = false; - int32_t tid_ = 0; - int32_t id_ = 0; - std::chrono::steady_clock::time_point time_ = std::chrono::steady_clock::now(); - std::shared_ptr connect_; - - explicit ConnNode(std::shared_ptr conn); - std::shared_ptr GetConnect(); - int64_t GetUsingTime() const; - bool IsWriter() const; - int32_t Unused(int32_t count, bool timeout); - }; - - struct Container { - using Creator = std::function>()>; - static constexpr int32_t MAX_RIGHT = 0x4FFFFFFF; - static constexpr int32_t MIN_TRANS_ID = 10000; - bool disable_ = true; - int max_ = 0; - int total_ = 0; - int count_ = 0; - int trans_ = 0; - int32_t left_ = 0; - int32_t right_ = 0; - std::chrono::seconds timeout_; - std::list> nodes_; - std::list> details_; - std::mutex mutex_; - std::condition_variable cond_; - Creator creator_ = nullptr; - std::pair> Initialize( - Creator creator, int32_t max, int32_t timeout, bool disable, bool acquire = false); - std::shared_ptr Acquire(std::chrono::milliseconds milliS); - std::pair> Create(); - - void Disable(); - void Enable(); - int32_t Release(std::shared_ptr node); - int32_t Drop(std::shared_ptr node); - int32_t Clear(); - bool IsFull(); - int32_t Dump(const char *header, int32_t count); - - private: - int32_t ExtendNode(); - int32_t RelDetails(std::shared_ptr node); - }; - - std::pair> Init(bool isAttach = false, bool needWriter = false); - int32_t GetMaxReaders(const StoreConfig &config); - std::shared_ptr Convert2AutoConn(std::shared_ptr node, bool isTrans = false); - void ReleaseNode(std::shared_ptr node, bool reuse = true); - - static constexpr uint32_t CHECK_POINT_INTERVAL = 5; // 5 min - static constexpr uint32_t ITER_V1 = 5000; - static constexpr uint32_t ITERS_COUNT = 2; - static constexpr uint32_t MAX_TRANS = 4; - const StoreConfig &config_; - Container writers_; - Container readers_; - int32_t maxReader_ = 0; - - std::condition_variable transCondition_; - std::atomic isInTransaction_ = false; - std::atomic transCount_ = 0; - std::atomic failedTime_; -}; - -} // namespace OHOS::DistributedDataAip -#endif diff --git a/relational_store/frameworks/native/gdb/include/db_store_impl.h b/relational_store/frameworks/native/gdb/include/db_store_impl.h deleted file mode 100644 index a50062fb..00000000 --- a/relational_store/frameworks/native/gdb/include/db_store_impl.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_NATIVE_GDB_DB_STORE_IMPL_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_DB_STORE_IMPL_H - -#include -#include - -#include "connection.h" -#include "connection_pool.h" -#include "gdb_store.h" -#include "gdb_store_config.h" -#include "gdb_transaction.h" - -namespace OHOS::DistributedDataAip { -class DBStoreImpl final : public DBStore { -public: - explicit DBStoreImpl(StoreConfig config); - ~DBStoreImpl(); - std::pair> QueryGql(const std::string &gql) override; - std::pair> ExecuteGql(const std::string &gql) override; - std::pair> CreateTransaction() override; - int32_t Close() override; - int32_t InitConn(); - -private: - std::shared_ptr GetConnectionPool(); - void SetConnectionPool(std::shared_ptr connectionPool); - - std::mutex mutex_; - std::mutex transMutex_; - StoreConfig config_; - std::shared_ptr connectionPool_ = nullptr; - std::list> transactions_; -}; -} // namespace OHOS::DistributedDataAip -#endif diff --git a/relational_store/frameworks/native/gdb/include/db_store_manager.h b/relational_store/frameworks/native/gdb/include/db_store_manager.h deleted file mode 100644 index e5cef31d..00000000 --- a/relational_store/frameworks/native/gdb/include/db_store_manager.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_NATIVE_GDB_DB_STORE_MANAGER_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_DB_STORE_MANAGER_H -#include -#include - -#include "db_store_impl.h" - -namespace OHOS::DistributedDataAip { -class StoreManager { -public: - static StoreManager &GetInstance(); - ~StoreManager(); - std::shared_ptr GetDBStore(const StoreConfig &config, int &errCode); - void Clear(); - bool Delete(const std::string &path); - -private: - StoreManager(); - bool DeleteFile(const std::string &path); - int SetSecurityLabel(const StoreConfig &config); - std::string GetSecurityLevelValue(SecurityLevel securityLevel); - std::string GetFileSecurityLevel(const std::string &filePath); - bool IsValidName(const std::string& name); - bool IsValidSecurityLevel(const int32_t securityLevel); - std::mutex mutex_; - std::string bundleName_; - std::map> storeCache_; - static constexpr const char *GRD_POST_FIXES[] = { - "", - ".redo", - ".undo", - ".ctrl", - ".ctrl.dwr", - ".safe", - ".map", - ".corruptedflg", - }; -}; -} // namespace OHOS::DistributedDataAip -#endif \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/include/full_result.h b/relational_store/frameworks/native/gdb/include/full_result.h deleted file mode 100644 index 648ebaf9..00000000 --- a/relational_store/frameworks/native/gdb/include/full_result.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_FULLRESULT_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_FULLRESULT_H - -#include -#include -#include -#include -#include -#include - -#include "edge.h" -#include "gdb_store_config.h" -#include "nlohmann/json.hpp" -#include "path.h" -#include "result.h" -#include "vertex.h" - -namespace OHOS::DistributedDataAip { -class Statement; -class FullResult final : public Result { -public: - FullResult() = default; - std::vector> GetAllData() const override; - int32_t InitData(std::shared_ptr stmt); - -private: - std::pair> GetRow(std::shared_ptr stmt); - std::vector> data_; -}; -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_FULLRESULT_H diff --git a/relational_store/frameworks/native/gdb/include/gdb_utils.h b/relational_store/frameworks/native/gdb/include/gdb_utils.h deleted file mode 100644 index 055e91c3..00000000 --- a/relational_store/frameworks/native/gdb/include/gdb_utils.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GDB_UTILS_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GDB_UTILS_H -#include - -#include "rdb_visibility.h" - -namespace OHOS::DistributedDataAip { -class API_EXPORT GdbUtils { -public: - static bool IsTransactionGql(const std::string &gql); - static int CreateDirectory(const std::string &databaseDir); - static std::string Anonymous(const std::string &srcFile); - static void ClearAndZeroString(std::string &str); - static std::string GetConfigStr(const std::vector &keys, bool isEncrypt); - static const char *GetEncryptKey(const std::vector &encryptedKey, char outBuff[], size_t outBufSize); -private: - static constexpr int DIR_RWXRWS__X = 0771; - static constexpr const char *GRD_OPEN_CONFIG_STR = - R"("pageSize": 8, "crcCheckEnable": 0, "defaultIsolationLevel": 3, "redoFlushByTrx": 1, )" - R"("metaInfoBak": 1, "maxConnNum": 500, "bufferPoolSize": 10240)"; - static std::string GetAnonymousName(const std::string& fileName); - static std::string AnonyDigits(const std::string& fileName); -}; -} - -#endif \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/include/graph_connection.h b/relational_store/frameworks/native/gdb/include/graph_connection.h deleted file mode 100644 index 670a5a1d..00000000 --- a/relational_store/frameworks/native/gdb/include/graph_connection.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_CONNECTION_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_CONNECTION_H - -#include -#include -#include - -#include "connection.h" -#include "gdb_store_config.h" -#include "grd_adapter.h" - -namespace OHOS::DistributedDataAip { -class GraphConnection : public Connection { -public: - static std::pair> Create(const StoreConfig &config, bool isWriter); - GraphConnection(const StoreConfig &config, bool isWriter); - ~GraphConnection() override; - std::pair CreateStatement(const std::string &gql, std::shared_ptr conn) override; - DBType GetDBType() const override; - bool IsWriter() const override; - -private: - static constexpr uint32_t NO_ITER = 0; - static constexpr uint32_t ITER_V1 = 5000; - static constexpr uint32_t ITERS[] = { NO_ITER, ITER_V1 }; - static constexpr uint32_t ITERS_COUNT = sizeof(ITERS) / sizeof(ITERS[0]); - - static const int32_t regCreator_; - - int InnerOpen(const StoreConfig &config); - int32_t ResetKey(const StoreConfig &config); - bool IsEncryptInvalidChanged(const StoreConfig &config); - GRD_DB *dbHandle_ = nullptr; - const StoreConfig config_; - bool isWriter_ = false; -}; - -} // namespace OHOS::DistributedDataAip - -#endif // OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_CONNECTION_H diff --git a/relational_store/frameworks/native/gdb/include/graph_statement.h b/relational_store/frameworks/native/gdb/include/graph_statement.h deleted file mode 100644 index 5f4d3c23..00000000 --- a/relational_store/frameworks/native/gdb/include/graph_statement.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_STATEMENT_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_STATEMENT_H - -#ifndef JSON_NOEXCEPTION -#define JSON_NOEXCEPTION -#endif -#include "connection.h" -#include "grd_adapter.h" -#include "nlohmann/json.hpp" -#include "statement.h" - -namespace OHOS::DistributedDataAip { -class GraphStatement final : public Statement { -public: - GraphStatement(GRD_DB *db, const std::string &gql, std::shared_ptr conn, int32_t &errCode); - ~GraphStatement(); - - int32_t Prepare() override; - int32_t Step() override; - int32_t Finalize() override; - - uint32_t GetColumnCount() const override; - std::pair GetColumnName(int32_t index) const override; - std::pair GetColumnType(int32_t index) const override; - std::pair GetColumnValue(int32_t index) const override; - - bool IsReady() const override; - -private: - std::shared_ptr conn_; - std::string gql_; - GRD_Stmt *stmtHandle_ = nullptr; - GRD_DB *dbHandle_ = nullptr; - static GraphValue ParseJsonStr(const std::string &jsonStr, int32_t &errCode) ; -}; -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_NATIVE_GDB_GRAPH_STATEMENT_H diff --git a/relational_store/frameworks/native/gdb/include/statement.h b/relational_store/frameworks/native/gdb/include/statement.h deleted file mode 100644 index 89d29ae4..00000000 --- a/relational_store/frameworks/native/gdb/include/statement.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_NATIVE_GDB_STATEMENT_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_GDB_STATEMENT_H -#include -#include -#include -#include -#include - -#include "full_result.h" - -namespace OHOS::DistributedDataAip { -/** - * @brief Indicates the column type. - * - * Value returned by getColumnType(int) - */ -enum class ColumnType : int { - TYPE_INTEGER = 0, - TYPE_FLOAT, - TYPE_TEXT, - TYPE_BLOB, - TYPE_FLOATVECTOR, - TYPE_JSONSTR, - TYPE_NULL, -}; -class Statement { -public: - virtual int32_t Prepare() = 0; - virtual int32_t Step() = 0; - virtual int32_t Finalize() = 0; - - virtual uint32_t GetColumnCount() const = 0; - virtual std::pair GetColumnName(int32_t index) const = 0; - virtual std::pair GetColumnType(int32_t index) const = 0; - virtual std::pair GetColumnValue(int32_t index) const = 0; - - virtual bool IsReady() const = 0; -}; -} // namespace OHOS::DistributedDataAip -#endif //ARKDATA_INTELLIGENCE_PLATFORM_STATEMENT_H \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/src/connection.cpp b/relational_store/frameworks/native/gdb/src/connection.cpp deleted file mode 100644 index 52e6d8a4..00000000 --- a/relational_store/frameworks/native/gdb/src/connection.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 "connection.h" - -#include "gdb_errors.h" - -namespace OHOS::DistributedDataAip { -static Connection::Creator g_creators[static_cast(DBType::DB_BUTT)] = { nullptr, nullptr }; - -std::pair> Connection::Create(const StoreConfig &config, const bool isWriter) -{ - auto dbType = config.GetDbType(); - if (dbType < DBType::DB_GRAPH || dbType >= DBType::DB_BUTT) { - return { E_NOT_SUPPORT, nullptr }; - } - - auto creator = g_creators[static_cast(dbType)]; - if (creator == nullptr) { - return { E_NOT_SUPPORT, nullptr }; - } - - return creator(config, isWriter); -} - -int32_t Connection::RegisterCreator(DBType dbType, Creator creator) -{ - if (dbType < DBType::DB_GRAPH || dbType >= DBType::DB_BUTT) { - return E_NOT_SUPPORT; - } - - if (g_creators[static_cast(dbType)] != nullptr) { - return E_OK; - } - - g_creators[static_cast(dbType)] = creator; - return E_OK; -} - -int Connection::SetId(int id) -{ - id_ = id; - return id_; -} - -int Connection::GetId() const -{ - return id_; -} - -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/src/connection_pool.cpp b/relational_store/frameworks/native/gdb/src/connection_pool.cpp deleted file mode 100644 index 24ea15cb..00000000 --- a/relational_store/frameworks/native/gdb/src/connection_pool.cpp +++ /dev/null @@ -1,475 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "GdbConnPool" -#include "connection_pool.h" - -#include -#include - -#include "gdb_errors.h" -#include "gdb_utils.h" -#include "logger.h" -#include "rdb_store_config.h" - -namespace OHOS::DistributedDataAip { -using namespace std::chrono; - -std::shared_ptr ConnectionPool::Create(const StoreConfig &config, int &errCode) -{ - std::shared_ptr pool = std::make_shared(config); - if (pool == nullptr) { - LOG_ERROR("ConnectionPool::Create new failed, pool is nullptr."); - errCode = E_INIT_CONN_POOL_FAILED; - return nullptr; - } - std::shared_ptr conn; - for (uint32_t retry = 0; retry < ITERS_COUNT; ++retry) { - std::tie(errCode, conn) = pool->Init(); - if (errCode != E_GRD_DATA_CORRUPTED) { - break; - } - config.SetIter(ITER_V1); - } - return errCode == E_OK ? pool : nullptr; -} - -ConnectionPool::ConnectionPool(const StoreConfig &storeConfig) : config_(storeConfig), writers_(), readers_() -{ -} - -std::pair> ConnectionPool::Init(bool isAttach, bool needWriter) -{ - std::pair> result; - auto &[errCode, conn] = result; - config_.GenerateEncryptedKey(); - // write connect count is 1 - std::shared_ptr node; - std::tie(errCode, node) = writers_.Initialize( - [this, isAttach]() { return Connection::Create(config_, true); }, 1, config_.GetWriteTime(), true, needWriter); - conn = Convert2AutoConn(node); - if (errCode != E_OK) { - return result; - } - - maxReader_ = GetMaxReaders(config_); - LOG_DEBUG("ConnectionPool::Init maxReader=%{public}d", maxReader_); - // max read connect count is 64 - if (maxReader_ > 64) { - LOG_ERROR("maxReader is too big. maxReader=%{public}d", maxReader_); - return { E_ARGS_READ_CON_OVERLOAD, nullptr }; - } - auto [ret, nodeRead] = readers_.Initialize([this, isAttach]() { return Connection::Create(config_, false); }, - maxReader_, config_.GetReadTime(), maxReader_ == 0); - errCode = ret; - return result; -} - -ConnectionPool::~ConnectionPool() -{ - LOG_DEBUG("enter"); - CloseAllConnections(); -} - -int32_t ConnectionPool::GetMaxReaders(const StoreConfig &config) -{ - return config.GetReadConSize(); -} - -std::shared_ptr ConnectionPool::Convert2AutoConn(std::shared_ptr node, bool isTrans) -{ - if (node == nullptr) { - return nullptr; - } - - auto conn = node->GetConnect(); - if (conn == nullptr) { - return nullptr; - } - if (isTrans) { - transCount_++; - } - - return std::shared_ptr(conn.get(), [pool = weak_from_this(), node, isTrans](auto *) mutable { - auto realPool = pool.lock(); - if (realPool == nullptr) { - return; - } - realPool->ReleaseNode(node, !isTrans); - if (isTrans) { - realPool->transCount_--; - } - node = nullptr; - }); -} - -void ConnectionPool::CloseAllConnections() -{ - writers_.Clear(); - readers_.Clear(); -} - -std::pair> ConnectionPool::CreateTransConn() -{ - if (transCount_ >= MAX_TRANS) { - writers_.Dump("NO TRANS", transCount_ + isInTransaction_); - return { E_DATABASE_BUSY, nullptr }; - } - auto [errCode, node] = writers_.Create(); - return { errCode, Convert2AutoConn(node, true) }; -} - -std::shared_ptr ConnectionPool::Acquire(bool isReadOnly, std::chrono::milliseconds ms) -{ - Container *container = (isReadOnly && maxReader_ != 0) ? &readers_ : &writers_; - auto node = container->Acquire(ms); - if (node == nullptr) { - const char *header = (isReadOnly && maxReader_ != 0) ? "readers_" : "writers_"; - container->Dump(header, transCount_ + isInTransaction_); - return nullptr; - } - return Convert2AutoConn(node); -} - -std::shared_ptr ConnectionPool::AcquireRef(bool isReadOnly, std::chrono::milliseconds ms) -{ - if (maxReader_ != 0) { - return Acquire(isReadOnly, ms); - } - auto node = writers_.Acquire(ms); - if (node == nullptr) { - writers_.Dump("writers_", transCount_ + isInTransaction_); - return nullptr; - } - auto conn = node->connect_; - writers_.Release(node); - return {conn.get(), [pool = weak_from_this(), conn](Connection *) { - auto realPool = pool.lock(); - if (realPool == nullptr) { - return; - } - realPool->writers_.cond_.notify_all(); - }}; -} - -void ConnectionPool::ReleaseNode(std::shared_ptr node, bool reuse) -{ - if (node == nullptr) { - return; - } - auto now = steady_clock::now(); - auto timeout = now > (failedTime_.load() + minutes(CHECK_POINT_INTERVAL)) || now < failedTime_.load() || - failedTime_.load() == steady_clock::time_point(); - auto transCount = transCount_ + isInTransaction_; - auto remainCount = reuse ? transCount : transCount - 1; - auto errCode = node->Unused(remainCount, timeout); - if (errCode == E_DATABASE_BUSY) { - writers_.Dump("WAL writers_", transCount); - readers_.Dump("WAL readers_", transCount); - } - LOG_DEBUG( - "ConnectionPool::ReleaseNode reuse=%{public}d,timeout=%{public}d,remainCount=%{public}d,isWriter=%{public}d", - reuse, timeout, remainCount, node->IsWriter()); - - if (node->IsWriter() && errCode != E_NOT_SUPPORT) { - failedTime_ = errCode != E_OK ? now : steady_clock::time_point(); - } - - auto &container = node->IsWriter() ? writers_ : readers_; - if (reuse) { - container.Release(node); - } else { - container.Drop(node); - } -} - -int ConnectionPool::RestartReaders() -{ - readers_.Clear(); - auto [errCode, node] = readers_.Initialize( - [this]() { return Connection::Create(config_, false); }, maxReader_, config_.GetReadTime(), maxReader_ == 0); - return errCode; -} - -int32_t ConnectionPool::Dump(bool isWriter, const char *header) -{ - Container *container = (isWriter || maxReader_ == 0) ? &writers_ : &readers_; - container->Dump(header, transCount_ + isInTransaction_); - return E_OK; -} - -ConnectionPool::ConnNode::ConnNode(std::shared_ptr conn) : connect_(std::move(conn)) -{ -} - -std::shared_ptr ConnectionPool::ConnNode::GetConnect() -{ - tid_ = gettid(); - time_ = steady_clock::now(); - return connect_; -} - -int64_t ConnectionPool::ConnNode::GetUsingTime() const -{ - auto time = steady_clock::now() - time_; - return duration_cast(time).count(); -} - -int32_t ConnectionPool::ConnNode::Unused(int32_t count, bool timeout) -{ - time_ = steady_clock::now(); - if (connect_ == nullptr) { - return E_OK; - } - time_ = steady_clock::now(); - if (!connect_->IsWriter()) { - tid_ = 0; - } - return E_OK; -} - -bool ConnectionPool::ConnNode::IsWriter() const -{ - if (connect_ != nullptr) { - return connect_->IsWriter(); - } - return false; -} - -std::pair> ConnectionPool::Container::Initialize( - Creator creator, int32_t max, int32_t timeout, bool disable, bool acquire) -{ - std::shared_ptr connNode = nullptr; - { - std::unique_lock lock(mutex_); - disable_ = disable; - max_ = max; - creator_ = std::move(creator); - timeout_ = std::chrono::seconds(timeout); - for (int i = 0; i < max; ++i) { - auto errCode = ExtendNode(); - if (errCode != E_OK) { - nodes_.clear(); - details_.clear(); - return { errCode, nullptr }; - } - } - - if (acquire && count_ > 0) { - connNode = nodes_.back(); - nodes_.pop_back(); - count_--; - } - } - cond_.notify_all(); - return { E_OK, connNode }; -} - -std::shared_ptr ConnectionPool::Container::Acquire(std::chrono::milliseconds milliS) -{ - auto interval = (milliS == INVALID_TIME) ? timeout_ : milliS; - std::unique_lock lock(mutex_); - LOG_DEBUG("count %{public}d max %{public}d total %{public}d left %{public}d right%{public}d", count_, max_, total_, - left_, right_); - if (max_ == 0) { - return nullptr; - } - auto waiter = [this]() -> bool { - if (count_ > 0) { - return true; - } - - if (disable_) { - return false; - } - return ExtendNode() == E_OK; - }; - if (cond_.wait_for(lock, interval, waiter)) { - if (nodes_.empty()) { - LOG_ERROR("nodes is empty.count %{public}d max %{public}d total %{public}d left %{public}d right%{public}d", - count_, max_, total_, left_, right_); - count_ = 0; - return nullptr; - } - auto node = nodes_.back(); - nodes_.pop_back(); - count_--; - return node; - } - return nullptr; -} - -std::pair> ConnectionPool::Container::Create() -{ - std::unique_lock lock(mutex_); - if (creator_ == nullptr) { - return { E_NOT_SUPPORT, nullptr }; - } - - auto [errCode, conn] = creator_(); - if (conn == nullptr) { - return { errCode, nullptr }; - } - - auto node = std::make_shared(conn); - if (node == nullptr) { - return { E_ERROR, nullptr }; - } - node->id_ = MIN_TRANS_ID + trans_; - conn->SetId(node->id_); - details_.push_back(node); - trans_++; - return { E_OK, node }; -} - -int32_t ConnectionPool::Container::ExtendNode() -{ - if (creator_ == nullptr) { - return E_ERROR; - } - auto [errCode, conn] = creator_(); - if (conn == nullptr) { - return errCode; - } - auto node = std::make_shared(conn); - node->id_ = right_++; - conn->SetId(node->id_); - nodes_.push_back(node); - details_.push_back(node); - count_++; - total_++; - return E_OK; -} - -void ConnectionPool::Container::Disable() -{ - disable_ = true; - cond_.notify_one(); -} - -void ConnectionPool::Container::Enable() -{ - disable_ = false; - cond_.notify_one(); -} - -int32_t ConnectionPool::Container::Release(std::shared_ptr node) -{ - { - std::unique_lock lock(mutex_); - if (node->id_ < left_ || node->id_ >= right_) { - return E_OK; - } - if (count_ == max_) { - total_ = total_ > count_ ? total_ - 1 : count_; - RelDetails(node); - } else { - nodes_.push_front(node); - count_++; - } - } - cond_.notify_one(); - return E_OK; -} - -int32_t ConnectionPool::Container::Drop(std::shared_ptr node) -{ - { - std::unique_lock lock(mutex_); - RelDetails(node); - } - cond_.notify_one(); - return E_OK; -} - -int32_t ConnectionPool::Container::RelDetails(std::shared_ptr node) -{ - for (auto it = details_.begin(); it != details_.end();) { - auto detailNode = it->lock(); - if (detailNode == nullptr || detailNode->id_ == node->id_) { - it = details_.erase(it); - } else { - it++; - } - } - return E_OK; -} - -int32_t ConnectionPool::Container::Clear() -{ - std::list> nodes; - std::list> details; - { - std::unique_lock lock(mutex_); - nodes = std::move(nodes_); - details = std::move(details_); - disable_ = true; - total_ = 0; - count_ = 0; - if (right_ > MAX_RIGHT) { - right_ = 0; - } - left_ = right_; - creator_ = nullptr; - } - nodes.clear(); - details.clear(); - LOG_DEBUG( - "Container::Clear success count=%{public}d, max=%{public}d, total=%{public}d, left=%{public}d, " - "right=%{public}d", count_, max_, total_, left_, right_); - return 0; -} - -bool ConnectionPool::Container::IsFull() -{ - std::unique_lock lock(mutex_); - return total_ == count_; -} - -int32_t ConnectionPool::Container::Dump(const char *header, int32_t count) -{ - std::string info; - std::vector> details; - std::string title = "B_M_T_C[" + std::to_string(count) + "," + std::to_string(max_) + "," + - std::to_string(total_) + "," + std::to_string(count_) + "]"; - { - std::unique_lock lock(mutex_); - details.reserve(details_.size()); - for (auto &detail : details_) { - auto node = detail.lock(); - if (node == nullptr) { - continue; - } - details.push_back(node); - } - } - - for (auto &node : details) { - info.append("<") - .append(std::to_string(node->id_)) - .append(",") - .append(std::to_string(node->tid_)) - .append(",") - .append(std::to_string(node->GetUsingTime())) - .append(">"); - // 256 represent that limit to info length - if (info.size() > 256) { - LOG_WARN("%{public}s %{public}s:%{public}s", header, title.c_str(), info.c_str()); - info.clear(); - } - } - LOG_WARN("%{public}s %{public}s:%{public}s", header, title.c_str(), info.c_str()); - return 0; -} -} // namespace OHOS::DistributedDataAip \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/src/db_store_impl.cpp b/relational_store/frameworks/native/gdb/src/db_store_impl.cpp deleted file mode 100644 index bb7808dc..00000000 --- a/relational_store/frameworks/native/gdb/src/db_store_impl.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "GdbStore" -#include "db_store_impl.h" - -#include - -#include "connection.h" -#include "db_trace.h" -#include "gdb_errors.h" -#include "gdb_transaction.h" -#include "gdb_utils.h" -#include "logger.h" -#include "transaction_impl.h" - -namespace OHOS::DistributedDataAip { - -constexpr int32_t MAX_GQL_LEN = 1024 * 1024; - -DBStoreImpl::DBStoreImpl(StoreConfig config) : config_(std::move(config)) -{ -} - -DBStoreImpl::~DBStoreImpl() -{ - LOG_DEBUG("DBStoreImpl enter"); - Close(); -} - -std::shared_ptr DBStoreImpl::GetConnectionPool() -{ - std::lock_guard lock(mutex_); - return connectionPool_; -} - -void DBStoreImpl::SetConnectionPool(std::shared_ptr connectionPool) -{ - std::lock_guard lock(mutex_); - connectionPool_ = connectionPool; -} - -int32_t DBStoreImpl::InitConn() -{ - if (GetConnectionPool() != nullptr) { - LOG_INFO("connectionPool_ is not nullptr"); - return E_OK; - } - int errCode; - auto connectionPool = ConnectionPool::Create(config_, errCode); - if (errCode != E_OK || connectionPool == nullptr) { - LOG_ERROR("Create conn failed, ret=%{public}d", errCode); - return errCode; - } - SetConnectionPool(connectionPool); - return E_OK; -} - -std::pair> DBStoreImpl::QueryGql(const std::string &gql) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - if (gql.empty() || gql.length() > MAX_GQL_LEN) { - LOG_ERROR("Gql is empty or length is too long."); - return { E_INVALID_ARGS, nullptr }; - } - if (GdbUtils::IsTransactionGql(gql)) { - LOG_ERROR("Transaction related statements are not supported."); - return { E_INVALID_ARGS, nullptr }; - } - auto connectionPool = GetConnectionPool(); - if (connectionPool == nullptr) { - LOG_ERROR("The connpool is nullptr."); - return { E_STORE_HAS_CLOSED, std::make_shared() }; - } - auto conn = connectionPool->AcquireRef(true); - if (conn == nullptr) { - LOG_ERROR("Get conn failed"); - return { E_ACQUIRE_CONN_FAILED, std::make_shared() }; - } - auto [ret, stmt] = conn->CreateStatement(gql, conn); - if (ret != E_OK || stmt == nullptr) { - LOG_ERROR("Create stmt failed, ret=%{public}d", ret); - return { ret, std::make_shared() }; - } - - auto result = std::make_shared(); - ret = result->InitData(stmt); - if (ret != E_OK) { - LOG_ERROR("Get FullResult failed, ret=%{public}d", ret); - return { ret, std::make_shared() }; - } - - return { E_OK, result }; -} - -std::pair> DBStoreImpl::ExecuteGql(const std::string &gql) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - if (gql.empty() || gql.length() > MAX_GQL_LEN) { - LOG_ERROR("Gql is empty or length is too long."); - return { E_INVALID_ARGS, std::make_shared() }; - } - if (GdbUtils::IsTransactionGql(gql)) { - LOG_ERROR("Transaction related statements are not supported."); - return { E_INVALID_ARGS, std::make_shared() }; - } - auto connectionPool = GetConnectionPool(); - if (connectionPool == nullptr) { - LOG_ERROR("The connpool is nullptr."); - return { E_STORE_HAS_CLOSED, std::make_shared() }; - } - auto conn = connectionPool->AcquireRef(false); - if (conn == nullptr) { - LOG_ERROR("Get conn failed"); - return { E_ACQUIRE_CONN_FAILED, std::make_shared() }; - } - auto [ret, stmt] = conn->CreateStatement(gql, conn); - if (ret != E_OK || stmt == nullptr) { - LOG_ERROR("Create stmt failed, ret=%{public}d", ret); - return { ret, std::make_shared() }; - } - ret = stmt->Step(); - if (ret != E_OK) { - LOG_ERROR("Step stmt failed, ret=%{public}d", ret); - } - return { ret, std::make_shared() }; -} - -std::pair> DBStoreImpl::CreateTransaction() -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - auto connectionPool = GetConnectionPool(); - if (connectionPool == nullptr) { - LOG_ERROR("The connpool is nullptr."); - return { E_STORE_HAS_CLOSED, nullptr }; - } - auto [ret, conn] = connectionPool->CreateTransConn(); - if (ret != E_OK || conn == nullptr) { - LOG_ERROR("Get conn failed"); - return { ret, nullptr }; - } - std::shared_ptr trans; - std::tie(ret, trans) = TransactionImpl::Create(conn); - if (ret != E_OK || trans == nullptr) { - LOG_ERROR("Create trans failed, ret=%{public}d", ret); - return { ret, nullptr }; - } - - std::lock_guard lock(transMutex_); - for (auto it = transactions_.begin(); it != transactions_.end();) { - if (it->expired()) { - it = transactions_.erase(it); - } else { - it++; - } - } - transactions_.push_back(trans); - return { ret, trans }; -} - -int32_t DBStoreImpl::Close() -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - SetConnectionPool(nullptr); - - std::lock_guard lock(transMutex_); - for (auto &trans : transactions_) { - auto realTrans = trans.lock(); - if (realTrans) { - (void)realTrans->Close(); - } - } - transactions_ = {}; - return E_OK; -} -} // namespace OHOS::DistributedDataAip \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/src/db_store_manager.cpp b/relational_store/frameworks/native/gdb/src/db_store_manager.cpp deleted file mode 100644 index aa232801..00000000 --- a/relational_store/frameworks/native/gdb/src/db_store_manager.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "GdbStoreManager" -#include "db_store_manager.h" - -#include - -#include - -#include "gdb_errors.h" -#include "db_store_impl.h" -#include "gdb_utils.h" -#include "logger.h" -#include "security_label.h" - -namespace OHOS::DistributedDataAip { -StoreManager &StoreManager::GetInstance() -{ - static StoreManager manager; - return manager; -} - -StoreManager::StoreManager() = default; - -StoreManager::~StoreManager() -{ - Clear(); -} - -bool StoreManager::IsValidName(const std::string &name) -{ - const std::regex pattern("^[a-zA-Z0-9_]+$"); - return std::regex_match(name, pattern); -} - -bool StoreManager::IsValidSecurityLevel(const int32_t securityLevel) -{ - return securityLevel >= SecurityLevel::S1 && securityLevel <= SecurityLevel::S4; -} - -std::shared_ptr StoreManager::GetDBStore(const StoreConfig &config, int &errCode) -{ - if (!IsValidName(config.GetName())) { - LOG_ERROR("GetDBStore failed. Invalid name"); - errCode = E_GRD_INVAILD_NAME_ERR; - return nullptr; - } - if (!IsValidSecurityLevel(config.GetSecurityLevel())) { - LOG_ERROR("GetDBStore failed. Invalid securityLevel: %{public}d", config.GetSecurityLevel()); - errCode = E_INVALID_ARGS; - return nullptr; - } - std::lock_guard lock(mutex_); - auto path = config.GetFullPath(); - if (storeCache_.find(path) != storeCache_.end()) { - std::shared_ptr dbStore = storeCache_[path].lock(); - if (dbStore != nullptr) { - LOG_ERROR("GetDBStore reuse success."); - return dbStore; - } - storeCache_.erase(path); - } - // open and store DBStore - std::shared_ptr dbStore = std::make_shared(config); - errCode = dbStore->InitConn(); - if (errCode != E_OK) { - LOG_ERROR("GetDBStore InitConn failed, name=%{public}s, errCode=%{public}d", - GdbUtils::Anonymous(config.GetName()).c_str(), errCode); - return nullptr; - } - errCode = SetSecurityLabel(config); - if (errCode != E_OK) { - LOG_ERROR("GetDBStore SetSecurityLabel failed, errCode=%{public}d", errCode); - return nullptr; - } - storeCache_[path] = dbStore; - return dbStore; -} - -void StoreManager::Clear() -{ - std::lock_guard lock(mutex_); - auto iter = storeCache_.begin(); - while (iter != storeCache_.end()) { - if (auto store = iter->second.lock()) { - store->Close(); - } - iter = storeCache_.erase(iter); - } - storeCache_.clear(); -} - -bool StoreManager::Delete(const std::string &path) -{ - LOG_DEBUG("Delete file, path=%{public}s", GdbUtils::Anonymous(path).c_str()); - { - std::lock_guard lock(mutex_); - auto item = storeCache_.find(path); - if (item != storeCache_.end()) { - if (auto store = item->second.lock()) { - store->Close(); - } - storeCache_.erase(path); // clean invalid store ptr - } - } - - bool deleteResult = true; - for (auto &suffix : GRD_POST_FIXES) { - deleteResult = DeleteFile(path + suffix) && deleteResult; - } - return deleteResult; -} - -bool StoreManager::DeleteFile(const std::string &path) -{ - if (access(path.c_str(), 0) != 0) { - LOG_WARN("access return, path=%{public}s", GdbUtils::Anonymous(path).c_str()); - return true; - } - auto ret = remove(path.c_str()); - if (ret != 0) { - LOG_ERROR("remove file failed errno %{public}d ret %{public}d %{public}s", errno, ret, - GdbUtils::Anonymous(path).c_str()); - return false; - } - return true; -} - -int StoreManager::SetSecurityLabel(const StoreConfig &config) -{ - if (config.GetSecurityLevel() >= SecurityLevel::S1 && config.GetSecurityLevel() <= SecurityLevel::S4) { - auto toSetLevel = GetSecurityLevelValue(static_cast(config.GetSecurityLevel())); - auto errCode = - FileManagement::ModuleSecurityLabel::SecurityLabel::SetSecurityLabel(config.GetFullPath(), toSetLevel) - ? E_OK - : E_CONFIG_INVALID_CHANGE; - if (errCode != E_OK) { - auto currentLevel = GetFileSecurityLevel(config.GetFullPath()); - LOG_ERROR( - "Set security level:%{public}s -> %{public}s, result=%{public}d, errno=%{public}d, name=%{public}s.", - currentLevel.c_str(), toSetLevel.c_str(), errCode, errno, - GdbUtils::Anonymous(config.GetName()).c_str()); - } - return errCode; - } - return E_OK; -} - -std::string StoreManager::GetSecurityLevelValue(SecurityLevel securityLevel) -{ - switch (securityLevel) { - case SecurityLevel::S1: - return "s1"; - case SecurityLevel::S2: - return "s2"; - case SecurityLevel::S3: - return "s3"; - case SecurityLevel::S4: - return "s4"; - default: - return ""; - } -} - -std::string StoreManager::GetFileSecurityLevel(const std::string &filePath) -{ - return FileManagement::ModuleSecurityLabel::SecurityLabel::GetSecurityLabel(filePath); -} - -} // namespace OHOS::DistributedDataAip \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/src/edge.cpp b/relational_store/frameworks/native/gdb/src/edge.cpp deleted file mode 100644 index 1b3fb582..00000000 --- a/relational_store/frameworks/native/gdb/src/edge.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "GdbEdge" -#include - -#include "gdb_errors.h" -#include "full_result.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { -Edge::Edge() : Vertex(), sourceId_("0"), targetId_("0") -{ -} - -Edge::Edge(std::string id, std::string label, std::string sourceId, std::string targetId) - : Vertex(std::move(id), std::move(label)), sourceId_(std::move(sourceId)), targetId_(std::move(targetId)) -{ -} - -Edge::Edge(const std::shared_ptr &element, std::string sourceId, std::string targetId) - : sourceId_(std::move(sourceId)), targetId_(std::move(targetId)) -{ - if (element != nullptr) { - id_ = element->GetId(); - label_ = element->GetLabel(); - properties_ = element->GetProperties(); - } -} - -std::string Edge::GetSourceId() const -{ - return sourceId_; -} - -void Edge::SetSourceId(std::string sourceId) -{ - sourceId_ = std::move(sourceId); -} - -std::string Edge::GetTargetId() const -{ - return targetId_; -} - -void Edge::SetTargetId(std::string targetId) -{ - targetId_ = std::move(targetId); -} - -std::string Edge::GetIdFromJson(const std::string &key, const nlohmann::json &json, int32_t &errCode) -{ - if (key.empty() || (!json.at(key).is_string() && !json.at(key).is_number())) { - LOG_ERROR("edge start or end id is not number or string. jsonStr=%{public}s", json.dump().c_str()); - errCode = E_PARSE_JSON_FAILED; - return ""; - } - errCode = E_OK; - if (json.at(key).is_number()) { - auto sourceId = json.at(key).get(); - return std::to_string(sourceId); - } - if (json.at(key).is_string()) { - return json.at(key).get(); - } - errCode = E_PARSE_JSON_FAILED; - return ""; -} - -std::shared_ptr Edge::Parse(const nlohmann::json &json, int32_t &errCode) -{ - if (!json.contains(Edge::SOURCEID) || !json.contains(Edge::TARGETID)) { - LOG_ERROR("edge format error. jsonStr=%{public}s", json.dump().c_str()); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - errCode = E_OK; - std::shared_ptr element = Vertex::Parse(json, errCode); - if (errCode != E_OK || element == nullptr) { - LOG_ERROR("parse edge element failed. jsonStr=%{public}s", json.dump().c_str()); - return nullptr; - } - auto sourceId = Edge::GetIdFromJson(Edge::SOURCEID, json, errCode); - if (errCode != E_OK) { - return nullptr; - } - auto targetId = Edge::GetIdFromJson(Edge::TARGETID, json, errCode); - if (errCode != E_OK) { - return nullptr; - } - return std::make_shared(element, sourceId, targetId); -} -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/src/full_result.cpp b/relational_store/frameworks/native/gdb/src/full_result.cpp deleted file mode 100644 index fdc8a026..00000000 --- a/relational_store/frameworks/native/gdb/src/full_result.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "GdbDataSet" -#include "full_result.h" - -#include "gdb_errors.h" -#include "statement.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { -int32_t FullResult::InitData(std::shared_ptr stmt) -{ - if (stmt == nullptr) { - return E_STATEMENT_EMPTY; - } - data_ = std::vector>(); - int32_t errCode = stmt->Step(); - while (errCode == E_OK) { - auto [ret, oneResult] = GetRow(stmt); - if (ret != E_OK) { - return ret; - } - data_.emplace_back(oneResult); - errCode = stmt->Step(); - } - return (errCode == E_GRD_NO_DATA) ? E_OK : errCode; -} - -std::vector> FullResult::GetAllData() const -{ - return data_; -} -std::pair> FullResult::GetRow(std::shared_ptr stmt) -{ - std::unordered_map res; - if (stmt == nullptr) { - return { E_STATEMENT_EMPTY, res }; - } - auto columnCount = stmt->GetColumnCount(); - if (columnCount == 0) { - LOG_ERROR("GetKeys failed ret=%{public}d.", E_NO_DATA); - return { E_NO_DATA, res }; - } - - for (uint32_t i = 0; i < columnCount; i++) { - auto [ret, key] = stmt->GetColumnName(i); - if (ret != E_OK) { - LOG_ERROR("GetKeys failed ret=%{public}d.", ret); - return { ret, res }; - } - auto [err, value] = stmt->GetColumnValue(i); - if (err != E_OK) { - LOG_ERROR("GetValue failed, key=%{public}s, ret=%{public}d.", key.c_str(), err); - return { err, res }; - } - res.emplace(key, value); - } - return { E_OK, res }; -} - -} // namespace OHOS::DistributedDataAip \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/src/gdb_utils.cpp b/relational_store/frameworks/native/gdb/src/gdb_utils.cpp deleted file mode 100644 index ee35ad14..00000000 --- a/relational_store/frameworks/native/gdb/src/gdb_utils.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * 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. - */ - -#define LOG_TAG "RdbGqlUtils" -#include "gdb_utils.h" - -#include -#include -#include -#include - -#include "gdb_errors.h" - -namespace OHOS::DistributedDataAip { -constexpr int32_t CONTINUOUS_DIGITS_MINI_SIZE = 5; -constexpr int32_t FILE_PATH_MINI_SIZE = 6; -constexpr int32_t AREA_MINI_SIZE = 4; -constexpr int32_t AREA_OFFSET_SIZE = 5; -constexpr int32_t PRE_OFFSET_SIZE = 1; -constexpr int32_t PREFIX_POS = 0; -constexpr int32_t PREFIX_LEN = 3; - -bool GdbUtils::IsTransactionGql(const std::string &gql) -{ - auto prefix = gql.substr(PREFIX_POS, PREFIX_LEN); - if (prefix == "STA" || prefix == "COM" || prefix == "ROL") { - return true; - } - return false; -} - -int GdbUtils::CreateDirectory(const std::string &databaseDir) -{ - std::string tempDirectory = databaseDir; - std::vector directories; - - size_t pos = tempDirectory.find('/'); - while (pos != std::string::npos) { - std::string directory = tempDirectory.substr(0, pos); - directories.push_back(directory); - tempDirectory = tempDirectory.substr(pos + 1); - pos = tempDirectory.find('/'); - } - directories.push_back(tempDirectory); - - std::string databaseDirectory; - for (const std::string &directory : directories) { - databaseDirectory += "/" + directory; - if (access(databaseDirectory.c_str(), F_OK) != 0) { - if (mkdir(databaseDirectory.c_str(), DIR_RWXRWS__X)) { - return E_CREATE_FOLDER_FAIT; - } - } - } - return E_OK; -} - -std::string GdbUtils::Anonymous(const std::string &srcFile) -{ - auto pre = srcFile.find("/"); - auto end = srcFile.rfind("/"); - if (pre == std::string::npos || end - pre < FILE_PATH_MINI_SIZE) { - return GetAnonymousName(srcFile); - } - auto path = srcFile.substr(pre, end - pre); - auto area = path.find("/el"); - if (area == std::string::npos || area + AREA_MINI_SIZE > path.size()) { - path = ""; - } else if (area + AREA_OFFSET_SIZE < path.size()) { - path = path.substr(area, AREA_MINI_SIZE) + "/***"; - } else { - path = path.substr(area, AREA_MINI_SIZE); - } - std::string fileName = srcFile.substr(end); // rdb file name - fileName = GetAnonymousName(fileName); - return srcFile.substr(0, pre + PRE_OFFSET_SIZE) + "***" + path + fileName; -} - -std::string GdbUtils::GetAnonymousName(const std::string &fileName) -{ - std::vector alnum; - std::vector noAlnum; - std::string alnumStr; - std::string noAlnumStr; - for (const auto &letter : fileName) { - if (isxdigit(letter)) { - if (!noAlnumStr.empty()) { - noAlnum.push_back(noAlnumStr); - noAlnumStr.clear(); - alnum.push_back(""); - } - alnumStr += letter; - } else { - if (!alnumStr.empty()) { - alnum.push_back(alnumStr); - alnumStr.clear(); - noAlnum.push_back(""); - } - noAlnumStr += letter; - } - } - if (!alnumStr.empty()) { - alnum.push_back(alnumStr); - noAlnum.push_back(""); - } - if (!noAlnumStr.empty()) { - noAlnum.push_back(alnumStr); - alnum.push_back(""); - } - std::string res = ""; - for (size_t i = 0; i < alnum.size(); ++i) { - res += (AnonyDigits(alnum[i]) + noAlnum[i]); - } - return res; -} - -std::string GdbUtils::AnonyDigits(const std::string &fileName) -{ - std::string::size_type digitsNum = fileName.size(); - if (digitsNum < CONTINUOUS_DIGITS_MINI_SIZE) { - return fileName; - } - constexpr std::string::size_type longDigits = 7; - std::string::size_type endDigitsNum = 4; - std::string::size_type shortEndDigitsNum = 3; - std::string name = fileName; - std::string last = ""; - if (digitsNum >= CONTINUOUS_DIGITS_MINI_SIZE && digitsNum < longDigits) { - last = name.substr(name.size() - shortEndDigitsNum); - } else { - last = name.substr(name.size() - endDigitsNum); - } - - return "***" + last; -} - -void GdbUtils::ClearAndZeroString(std::string &str) -{ - str.clear(); - std::fill(str.begin(), str.end(), char(0)); -} - -std::string GdbUtils::GetConfigStr(const std::vector &keys, bool isEncrypt) -{ - std::string config = "{"; - if (isEncrypt) { - const size_t keyBuffSize = keys.size() * 2 + 1; // 2 hex number can represent a uint8_t, 1 is for '\0' - std::vector keyBuff(keyBuffSize); - config += "\"isEncrypted\":1,"; - config += "\"hexPassword\":\""; - config += GetEncryptKey(keys, keyBuff.data(), keyBuffSize); - config += "\","; - keyBuff.assign(keyBuffSize, 0); - } - config += GRD_OPEN_CONFIG_STR; - config += "}"; - return config; -} - -const char *GdbUtils::GetEncryptKey(const std::vector &encryptedKey, char outBuff[], size_t outBufSize) -{ - char *buffer = nullptr; - auto keySize = encryptedKey.size(); - for (size_t i = 0; i < keySize; i++) { - buffer = (char *)(outBuff + i * 2); // each uint8_t will convert to 2 hex char - // each uint8_t will convert to 2 hex char - errno_t err = snprintf_s(buffer, outBufSize - i * 2, outBufSize - i * 2, "%02x", encryptedKey[i]); - if (err < 0) { - return nullptr; - } - } - return outBuff; -} -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/src/graph_connection.cpp b/relational_store/frameworks/native/gdb/src/graph_connection.cpp deleted file mode 100644 index a0a0fcf3..00000000 --- a/relational_store/frameworks/native/gdb/src/graph_connection.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "GdbConn" -#include "graph_connection.h" - -#include - -#include -#include - -#include "gdb_errors.h" -#include "gdb_utils.h" -#include "graph_statement.h" -#include "logger.h" -#include "rdb_security_manager.h" -#include "securec.h" - -namespace OHOS::DistributedDataAip { -__attribute__((used)) -const int32_t GraphConnection::regCreator_ = Connection::RegisterCreator(DBType::DB_GRAPH, GraphConnection::Create); - -std::pair> GraphConnection::Create(const StoreConfig &config, bool isWriter) -{ - LOG_DEBUG("GraphConnection::Create start, name=%{public}s, isWriter=%{public}d", - GdbUtils::Anonymous(config.GetName()).c_str(), isWriter); - std::pair> result = { E_INNER_ERROR, nullptr }; - auto &[errCode, conn] = result; - for (size_t i = 0; i < ITERS_COUNT; i++) { - std::shared_ptr connection = std::make_shared(config, isWriter); - if (connection == nullptr) { - LOG_ERROR("Open new failed, connection is nullptr. name=%{public}s", - GdbUtils::Anonymous(config.GetName()).c_str()); - return result; - } - errCode = connection->InnerOpen(config); - if (errCode == E_OK) { - conn = connection; - break; - } - if (errCode == E_GRD_INVALID_ARGS && connection->IsEncryptInvalidChanged(config)) { - errCode = E_CONFIG_INVALID_CHANGE; - break; - } - } - return result; -} - -GraphConnection::GraphConnection(const StoreConfig &config, bool isWriter) : config_(config), isWriter_(isWriter) -{ -} - -GraphConnection::~GraphConnection() -{ - LOG_DEBUG("enter"); - if (dbHandle_ != nullptr) { - int errCode = GrdAdapter::Close(dbHandle_, 0); - if (errCode != E_OK) { - LOG_ERROR("could not close database, err=%{public}d", errCode); - } - dbHandle_ = nullptr; - } -} - -int GraphConnection::InnerOpen(const StoreConfig &config) -{ - std::string dbPath = config.GetFullPath(); - std::vector newKey = config.GetNewEncryptKey(); - if (!newKey.empty()) { - // NewKey exists, oldKey has expired, ResetKey is required - newKey.assign(newKey.size(), 0); - auto errCode = ResetKey(config); - if (errCode != E_OK) { - LOG_ERROR("Can not reset key %{public}d.", errCode); - return errCode; - } - } - std::vector key = config.GetEncryptKey(); - std::string configJson = GdbUtils::GetConfigStr(key, config.IsEncrypt()); - LOG_DEBUG( - "GraphConnection::InnerOpen: dbPath=%{public}s, configJson=%{public}s", - GdbUtils::Anonymous(dbPath).c_str(), configJson.c_str()); - int32_t errCode = GrdAdapter::Open(dbPath.c_str(), configJson.c_str(), GRD_DB_OPEN_CREATE, &dbHandle_); - if (errCode == E_GRD_PASSWORD_NEED_REKEY) { - // Upgrading from non encrypted to encrypted, requires Rekey first and then Open - errCode = GrdAdapter::Rekey(dbPath.c_str(), GdbUtils::GetConfigStr({}, false).c_str(), key); - if (errCode != E_OK) { - key.assign(key.size(), 0); - GdbUtils::ClearAndZeroString(configJson); - LOG_ERROR("Can not rekey graph db %{public}d.", errCode); - return errCode; - } - errCode = GrdAdapter::Open(dbPath.c_str(), configJson.c_str(), GRD_DB_OPEN_CREATE, &dbHandle_); - } - key.assign(key.size(), 0); - GdbUtils::ClearAndZeroString(configJson); - if (errCode != E_OK) { - LOG_ERROR("Can not open graph db, name=%{public}s, errCode=%{public}d.", - GdbUtils::Anonymous(config.GetName()).c_str(), errCode); - return errCode; - } - return errCode; -} - -std::pair GraphConnection::CreateStatement( - const std::string &gql, std::shared_ptr connection) -{ - int32_t ret; - auto stmt = std::make_shared(dbHandle_, gql, connection, ret); - if (ret != E_OK) { - return { ret, nullptr }; - } - return { ret, stmt }; -} - -DBType GraphConnection::GetDBType() const -{ - return DBType::DB_GRAPH; -} - -bool GraphConnection::IsWriter() const -{ - return isWriter_; -} - -int32_t GraphConnection::ResetKey(const StoreConfig &config) -{ - if (!IsWriter()) { - return E_OK; - } - std::string dbPath = config.GetFullPath(); - std::vector key = config.GetEncryptKey(); - std::vector newKey = config.GetNewEncryptKey(); - std::string configStr = GdbUtils::GetConfigStr(key, config.IsEncrypt()); - auto errCode = GrdAdapter::Rekey(dbPath.c_str(), configStr.c_str(), newKey); - GdbUtils::ClearAndZeroString(configStr); - key.assign(key.size(), 0); - newKey.assign(newKey.size(), 0); - if (errCode != E_OK) { - LOG_ERROR("Rekey failed, err = %{public}d, errno = %{public}d", errCode, errno); - NativeRdb::RdbSecurityManager::GetInstance().DelKeyFile( - config.GetFullPath(), NativeRdb::RdbSecurityManager::KeyFileType::PUB_KEY_FILE_NEW_KEY); - return errCode; - } - config.ChangeEncryptKey(); - return E_OK; -} - -bool GraphConnection::IsEncryptInvalidChanged(const StoreConfig &config) -{ - if (config.GetFullPath().empty() || config.IsEncrypt()) { - LOG_WARN("Config has no path or config is encrypted, path: %{public}s, isEncrypt: %{public}d", - GdbUtils::Anonymous(config.GetFullPath()).c_str(), config.IsEncrypt()); - return false; - } - return NativeRdb::RdbSecurityManager::GetInstance().IsKeyFileExists(config.GetFullPath(), - NativeRdb::RdbSecurityManager::KeyFileType::PUB_KEY_FILE); -} -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/src/graph_statement.cpp b/relational_store/frameworks/native/gdb/src/graph_statement.cpp deleted file mode 100644 index d1d0b3ce..00000000 --- a/relational_store/frameworks/native/gdb/src/graph_statement.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "GdbStmt" -#include "graph_statement.h" - -#include - -#include "gdb_errors.h" -#include "connection.h" -#include "full_result.h" -#include "grd_error.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { -GraphStatement::GraphStatement(GRD_DB *db, const std::string &gql, std::shared_ptr conn, int32_t &errCode) - : conn_(conn), gql_(gql), dbHandle_(db) -{ - errCode = E_OK; - if (db == nullptr || gql.empty()) { - errCode = E_PREPARE_CHECK_FAILED; - return; - } - - errCode = GrdAdapter::Prepare(dbHandle_, gql_.c_str(), gql_.size(), &stmtHandle_, nullptr); - if (errCode != E_OK) { - LOG_ERROR("GRD_GqlPrepare failed. ret=%{public}d", errCode); - if (stmtHandle_ != nullptr) { - GrdAdapter::Finalize(stmtHandle_); - } - } -} - -GraphStatement::~GraphStatement() -{ - Finalize(); -} - -int32_t GraphStatement::Prepare() -{ - if (dbHandle_ == nullptr || gql_.empty()) { - return E_PREPARE_CHECK_FAILED; - } - - int32_t ret = GrdAdapter::Prepare(dbHandle_, gql_.c_str(), gql_.size(), &stmtHandle_, nullptr); - if (ret != E_OK) { - LOG_ERROR("GRD_GqlPrepare failed. ret=%{public}d", ret); - } - return ret; -} - -int32_t GraphStatement::Step() -{ - if (stmtHandle_ == nullptr) { - return E_STEP_CHECK_FAILED; - } - int32_t ret = GrdAdapter::Step(stmtHandle_); - if (ret != E_OK && ret != E_GRD_NO_DATA) { - LOG_ERROR("GRD_GqlStep failed. ret=%{public}d", ret); - } - return ret; -} - -int32_t GraphStatement::Finalize() -{ - if (stmtHandle_ == nullptr) { - return E_OK; - } - int32_t ret = GrdAdapter::Finalize(stmtHandle_); - if (ret != E_OK) { - LOG_ERROR("GRD_GqlFinalize failed. ret=%{public}d", ret); - return ret; - } - stmtHandle_ = nullptr; - gql_ = ""; - return E_OK; -} - -uint32_t GraphStatement::GetColumnCount() const -{ - if (stmtHandle_ == nullptr) { - return E_STATEMENT_EMPTY; - } - return GrdAdapter::ColumnCount(stmtHandle_); -} - -std::pair GraphStatement::GetColumnName(int32_t index) const -{ - if (stmtHandle_ == nullptr) { - return { E_STATEMENT_EMPTY, "" }; - } - const char *name = GrdAdapter::ColumnName(stmtHandle_, index); - if (name == nullptr) { - LOG_ERROR("column_name is null. index=%{public}d", index); - return { E_GETTED_COLNAME_EMPTY, "" }; - } - return { E_OK, name }; -} - -std::pair GraphStatement::GetColumnType(int32_t index) const -{ - if (stmtHandle_ == nullptr) { - return { E_STATEMENT_EMPTY, ColumnType::TYPE_NULL }; - } - GRD_DbDataTypeE type = GrdAdapter::ColumnType(stmtHandle_, index); - return { E_OK, GrdAdapter::TransColType(type) }; -} - -GraphValue GraphStatement::ParseJsonStr(const std::string &jsonStr, int32_t &errCode) -{ - if (jsonStr.empty()) { - LOG_WARN("parse json string. jsonStr is empty"); - errCode = E_OK; - return nullptr; - } - nlohmann::json json = nlohmann::json::parse(jsonStr, nullptr, false); - if (json.is_discarded()) { - LOG_ERROR("parse json string failed. jsonStr=%{public}s", jsonStr.c_str()); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - - errCode = E_OK; - if (json.is_null()) { - LOG_WARN("parse json string. jsonStr is empty"); - return nullptr; - } - if (!json.is_object()) { - LOG_ERROR("json format error. jsonStr=%{public}s", jsonStr.c_str()); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - - if (json.contains(Path::SEGMENTS)) { - return Path::Parse(json, errCode); - } - if (json.contains(Edge::SOURCEID) && json.contains(Edge::TARGETID)) { - return Edge::Parse(json, errCode); - } - return Vertex::Parse(json, errCode); -} - -std::pair GraphStatement::GetColumnValue(int32_t index) const -{ - if (stmtHandle_ == nullptr) { - return { E_STATEMENT_EMPTY, nullptr }; - } - ColumnType type = GetColumnType(index).second; - GraphValue value; - - auto ret = 0; - switch (type) { - case ColumnType::TYPE_INTEGER: - value = GrdAdapter::ColumnInt(stmtHandle_, index); - break; - case ColumnType::TYPE_FLOAT: - value = GrdAdapter::ColumnDouble(stmtHandle_, index); - break; - case ColumnType::TYPE_JSONSTR: { - auto text = ""; - text = GrdAdapter::ColumnText(stmtHandle_, index); - value = ParseJsonStr(text, ret); - if (ret != E_OK) { - LOG_ERROR("ParseJsonStr failed. index=%{public}d, ret=%{public}d", index, ret); - return { ret, nullptr }; - } - break; - } - case ColumnType::TYPE_TEXT: - value = GrdAdapter::ColumnText(stmtHandle_, index); - break; - case ColumnType::TYPE_BLOB: - LOG_ERROR("not support blob type. index=%{public}d", index); - return { E_NOT_SUPPORT, nullptr }; - case ColumnType::TYPE_FLOATVECTOR: - LOG_ERROR("not support float vector type. index=%{public}d", index); - return { E_NOT_SUPPORT, nullptr }; - case ColumnType::TYPE_NULL: - default: - value = nullptr; - } - return { E_OK, value }; -} - -bool GraphStatement::IsReady() const -{ - return !gql_.empty() && stmtHandle_ != nullptr && dbHandle_ != nullptr; -} -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/src/path.cpp b/relational_store/frameworks/native/gdb/src/path.cpp deleted file mode 100644 index d390b319..00000000 --- a/relational_store/frameworks/native/gdb/src/path.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "GdbPath" -#include "path.h" - -#include "gdb_errors.h" -#include "path_segment.h" -#include "grd_error.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { -Path::Path(std::shared_ptr start, std::shared_ptr end) : start_(start), end_(end) -{ - pathLen_ = 0; -} - -Path::Path(std::shared_ptr start, std::shared_ptr end, uint32_t pathLen, - std::vector> segments) - : pathLen_(pathLen), start_(start), end_(end), segments_(std::move(segments)) -{ -} - -Path::Path() : pathLen_(0), start_(nullptr), end_(nullptr), segments_() -{ -} - -uint32_t Path::GetPathLength() const -{ - return pathLen_; -} - -void Path::SetPathLength(uint32_t pathLen) -{ - this->pathLen_ = pathLen; -} - -std::shared_ptr Path::GetStart() const -{ - return start_; -} - -void Path::SetStart(std::shared_ptr start) -{ - this->start_ = start; -} - -std::shared_ptr Path::GetEnd() const -{ - return end_; -} - -void Path::SetEnd(std::shared_ptr end) -{ - this->end_ = end; -} - -const std::vector> &Path::GetSegments() const -{ - return segments_; -} - -std::shared_ptr Path::Parse(const nlohmann::json &json, int32_t &errCode) -{ - if (!json.contains(Path::PATHLEN) || !json.contains(Path::START) || !json.at(Path::START).is_object() || - !json.contains(Path::END) || !json.at(Path::END).is_object() || !json.contains(Path::SEGMENTS) || - !json.at(Path::SEGMENTS).is_array() || !json.at(Path::PATHLEN).is_number_unsigned()) { - LOG_ERROR("path format error. jsonStr=%{public}s", json.dump().c_str()); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - errCode = E_OK; - - auto pathLen = json.at(Path::PATHLEN).get(); - auto start = Vertex::Parse(json.at(Path::START), errCode); - if (errCode != E_OK) { - return nullptr; - } - - auto end = Vertex::Parse(json.at(Path::END), errCode); - if (errCode != E_OK) { - return nullptr; - } - auto pathSegments = std::vector>(); - for (const auto &item : json.at(Path::SEGMENTS)) { - if (!item.is_object()) { - LOG_ERROR("pathItem format error. jsonStr=%{public}s", json.dump().c_str()); - return nullptr; - } - auto pathSegment = PathSegment::Parse(item, errCode); - if (errCode != E_OK) { - return nullptr; - } - pathSegments.push_back(pathSegment); - } - errCode = E_OK; - return std::make_shared(start, end, pathLen, pathSegments); - ; -} -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/src/path_segment.cpp b/relational_store/frameworks/native/gdb/src/path_segment.cpp deleted file mode 100644 index a4c501eb..00000000 --- a/relational_store/frameworks/native/gdb/src/path_segment.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "GdbPath" -#include "path_segment.h" - -#include "gdb_errors.h" -#include "grd_error.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { -PathSegment::PathSegment() : sourceVertex_(nullptr), edge_(nullptr), targetVertex_(nullptr) -{ -} - -PathSegment::PathSegment( - std::shared_ptr sourceVertex, std::shared_ptr targetVertex, std::shared_ptr edge) - : sourceVertex_(sourceVertex), edge_(edge), targetVertex_(targetVertex) -{ -} - -std::shared_ptr PathSegment::GetSourceVertex() const -{ - return sourceVertex_; -} - -void PathSegment::SetSourceVertex(std::shared_ptr vertex) -{ - sourceVertex_ = vertex; -} - -std::shared_ptr PathSegment::GetEdge() const -{ - return edge_; -} - -void PathSegment::SetEdge(std::shared_ptr edge) -{ - this->edge_ = edge; -} - -std::shared_ptr PathSegment::GetTargetVertex() const -{ - return targetVertex_; -} - -void PathSegment::SetTargetVertex(std::shared_ptr vertex) -{ - targetVertex_ = vertex; -} - -std::shared_ptr PathSegment::Parse(const nlohmann::json &json, int32_t &errCode) -{ - if (!json.contains(PathSegment::SOURCE_VERTEX) || !json.at(PathSegment::SOURCE_VERTEX).is_object() || - !json.contains(PathSegment::EDGE) || !json.at(PathSegment::EDGE).is_object() || - !json.contains(PathSegment::TARGET_VERTEX) || !json.at(PathSegment::TARGET_VERTEX).is_object()) { - LOG_ERROR("pathSegment format error. jsonStr=%{public}s", json.dump().c_str()); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - errCode = E_OK; - std::shared_ptr segment = std::make_shared(); - auto sourceVertex = Vertex::Parse(json.at(PathSegment::SOURCE_VERTEX), errCode); - if (errCode != E_OK) { - return nullptr; - } - segment->SetSourceVertex(sourceVertex); - - auto edge = Edge::Parse(json.at(PathSegment::EDGE), errCode); - if (errCode != E_OK) { - return nullptr; - } - segment->SetEdge(edge); - - auto targetVertex = Vertex::Parse(json.at(PathSegment::TARGET_VERTEX), errCode); - if (errCode != E_OK) { - return nullptr; - } - segment->SetTargetVertex(targetVertex); - - return segment; -} -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/src/store_config.cpp b/relational_store/frameworks/native/gdb/src/store_config.cpp deleted file mode 100644 index cda3da4c..00000000 --- a/relational_store/frameworks/native/gdb/src/store_config.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "GdbStoreConfig" -#include - -#include "gdb_errors.h" -#include "gdb_store_config.h" -#include "gdb_utils.h" -#include "logger.h" -#include "rdb_security_manager.h" - -namespace OHOS::DistributedDataAip { -StoreConfig::StoreConfig( - std::string name, std::string path, DBType dbType, bool isEncrypt, const std::vector &encryptKey) - : name_(std::move(name)), path_(std::move(path)), dbType_(dbType), isEncrypt_(isEncrypt), encryptKey_(encryptKey) -{ -} - -StoreConfig::~StoreConfig() -{ - ClearEncryptKey(); -} - -void StoreConfig::SetName(std::string name) -{ - name_ = std::move(name); -} - -void StoreConfig::SetPath(std::string path) -{ - path_ = std::move(path); -} - -void StoreConfig::SetDbType(DBType dbType) -{ - dbType_ = dbType; -} - -void StoreConfig::SetEncryptStatus(const bool status) -{ - isEncrypt_ = status; -} - -bool StoreConfig::IsEncrypt() const -{ - return isEncrypt_; -} - -std::string StoreConfig::GetFullPath() const -{ - return path_ + "/" + name_ + ".db"; -} - -std::string StoreConfig::GetPath() const -{ - return path_; -} - -std::string StoreConfig::GetName() const -{ - return name_; -} - -DBType StoreConfig::GetDbType() const -{ - return dbType_; -} - -int32_t StoreConfig::GetIter() const -{ - return iter_; -} - -void StoreConfig::SetIter(int32_t iter) const -{ - iter_ = iter; -} - -int StoreConfig::GetWriteTime() const -{ - return writeTimeout_; -} - -void StoreConfig::SetWriteTime(int timeout) -{ - writeTimeout_ = std::max(MIN_TIMEOUT, std::min(MAX_TIMEOUT, timeout)); -} - -int StoreConfig::GetReadTime() const -{ - return readTimeout_; -} - -void StoreConfig::SetReadTime(int timeout) -{ - readTimeout_ = std::max(MIN_TIMEOUT, std::min(MAX_TIMEOUT, timeout)); -} - -int StoreConfig::GetReadConSize() const -{ - return readConSize_; -} - -void StoreConfig::SetReadConSize(int readConSize) -{ - readConSize_ = readConSize; -} - -void StoreConfig::SetSecurityLevel(int32_t securityLevel) -{ - securityLevel_ = securityLevel; -} - -int32_t StoreConfig::GetSecurityLevel() const -{ - return securityLevel_; -} - -int StoreConfig::SetBundleName(const std::string &bundleName) -{ - if (bundleName.empty()) { - return E_ERROR; - } - bundleName_ = bundleName; - return E_OK; -} - -std::string StoreConfig::GetBundleName() const -{ - return bundleName_; -} - -std::vector StoreConfig::GetEncryptKey() const -{ - return encryptKey_; -} - -std::vector StoreConfig::GetNewEncryptKey() const -{ - return newEncryptKey_; -} - -void StoreConfig::GenerateEncryptedKey() const -{ - if (!IsEncrypt()) { - return; - } - auto rdbConfig = std::make_shared(GetFullPath()); - if (rdbConfig == nullptr) { - LOG_ERROR("rdbConfig is nullptr. path:%{public}s", GdbUtils::Anonymous(GetFullPath()).c_str()); - return; - } - rdbConfig->SetBundleName(bundleName_); - rdbConfig->SetEncryptStatus(true); - auto errCode = rdbConfig->Initialize(); - if (errCode != E_OK) { - LOG_ERROR("rdbConfig init encrypt failed. errCode:%{public}d, path:%{public}s", - errCode, GdbUtils::Anonymous(GetFullPath()).c_str()); - return; - } - encryptKey_.assign(encryptKey_.size(), 0); - encryptKey_ = rdbConfig->GetEncryptKey(); - newEncryptKey_.assign(newEncryptKey_.size(), 0); - newEncryptKey_ = rdbConfig->GetNewEncryptKey(); -} - -void StoreConfig::ClearEncryptKey() -{ - encryptKey_.assign(encryptKey_.size(), 0); - newEncryptKey_.assign(newEncryptKey_.size(), 0); -} - -void StoreConfig::ChangeEncryptKey() const -{ - NativeRdb::RdbSecurityManager::GetInstance().ChangeKeyFile(GetFullPath()); - if (newEncryptKey_.empty()) { - return; - } - encryptKey_.assign(encryptKey_.size(), 0); - encryptKey_ = newEncryptKey_; - newEncryptKey_.assign(newEncryptKey_.size(), 0); - newEncryptKey_.resize(0); -} -} // namespace OHOS::DistributedDataAip \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/src/trans_db.cpp b/relational_store/frameworks/native/gdb/src/trans_db.cpp deleted file mode 100644 index 3c9a6804..00000000 --- a/relational_store/frameworks/native/gdb/src/trans_db.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "TransDB" -#include "trans_db.h" - -#include "gdb_errors.h" -#include "db_trace.h" -#include "gdb_utils.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { - -constexpr int32_t MAX_GQL_LEN = 1024 * 1024; - -TransDB::TransDB(std::shared_ptr connection) : conn_(connection) -{ -} - -std::pair> TransDB::QueryGql(const std::string &gql) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - if (gql.empty() || gql.length() > MAX_GQL_LEN) { - LOG_ERROR("Gql is empty or length is too long."); - return { E_INVALID_ARGS, std::make_shared() }; - } - if (GdbUtils::IsTransactionGql(gql)) { - LOG_ERROR("Transaction related statements are not supported."); - return { E_INVALID_ARGS, std::make_shared() }; - } - - auto [errCode, statement] = GetStatement(gql); - if (errCode != E_OK || statement == nullptr) { - return { errCode, std::make_shared() }; - } - - auto result = std::make_shared(); - errCode = result->InitData(statement); - if (errCode != E_OK) { - LOG_ERROR("Get FullResult failed, errCode=%{public}d", errCode); - return { errCode, std::make_shared() }; - } - - return { errCode, result }; -} - -std::pair> TransDB::ExecuteGql(const std::string &gql) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - if (gql.empty() || gql.length() > MAX_GQL_LEN) { - LOG_ERROR("Gql is empty or length is too long."); - return { E_INVALID_ARGS, std::make_shared() }; - } - if (GdbUtils::IsTransactionGql(gql)) { - LOG_ERROR("Transaction related statements are not supported."); - return { E_INVALID_ARGS, std::make_shared() }; - } - - auto [errCode, statement] = GetStatement(gql); - if (errCode != E_OK || statement == nullptr) { - return { errCode, std::make_shared() }; - } - - errCode = statement->Step(); - if (errCode != E_OK) { - LOG_ERROR("Step statement failed, errCode=%{public}d", errCode); - } - return { errCode, std::make_shared() }; -} - -std::pair> TransDB::GetStatement(const std::string &gql) const -{ - auto connection = conn_.lock(); - if (connection == nullptr) { - return { E_GRD_DB_INSTANCE_ABNORMAL, nullptr }; - } - return connection->CreateStatement(gql, connection); -} - -std::pair> TransDB::CreateTransaction() -{ - return { E_NOT_SUPPORT, nullptr }; -} - -int32_t TransDB::Close() -{ - return E_NOT_SUPPORT; -} -} // namespace OHOS::DistributedDataAip \ No newline at end of file diff --git a/relational_store/frameworks/native/gdb/src/transaction_impl.cpp b/relational_store/frameworks/native/gdb/src/transaction_impl.cpp deleted file mode 100644 index 22faf2b3..00000000 --- a/relational_store/frameworks/native/gdb/src/transaction_impl.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "GdbTrans" -#include "transaction_impl.h" - -#include - -#include "gdb_errors.h" -#include "db_trace.h" -#include "logger.h" -#include "trans_db.h" - -namespace OHOS::DistributedDataAip { - -constexpr const char *START_GQL = "START TRANSACTION;"; -constexpr const char *COMMIT_GQL = "COMMIT;"; -constexpr const char *ROLLBACK_GQL = "ROLLBACK;"; - -__attribute__((used)) -const int32_t TransactionImpl::regCreator_ = Transaction::RegisterCreator(TransactionImpl::Create); - -TransactionImpl::TransactionImpl(std::shared_ptr connection) - : connection_(std::move(connection)) -{ -} - -TransactionImpl::~TransactionImpl() -{ - CloseInner(); -} - -std::pair> TransactionImpl::Create(std::shared_ptr conn) -{ - if (conn == nullptr) { - LOG_ERROR("conn is nullptr"); - return { E_ERROR, nullptr }; - } - auto trans = std::make_shared(std::move(conn)); - if (trans == nullptr) { - LOG_ERROR("trans is nullptr"); - return { E_ERROR, nullptr }; - } - auto errorCode = trans->Start(); - if (errorCode != E_OK) { - LOG_ERROR("transaction start failed, errorCode=%{public}d", errorCode); - return { errorCode, nullptr }; - } - return { E_OK, trans }; -} - -int32_t TransactionImpl::Start() -{ - std::lock_guard lock(mutex_); - store_ = std::make_shared(connection_); - if (store_ == nullptr) { - LOG_ERROR("create trans db failed"); - return E_ERROR; - } - - if (connection_ == nullptr) { - LOG_ERROR("connection already closed"); - return E_GRD_DB_INSTANCE_ABNORMAL; - } - - auto [errorCode, statement] = connection_->CreateStatement(START_GQL, connection_); - if (errorCode != E_OK || statement == nullptr) { - LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode); - CloseInner(); - return errorCode; - } - errorCode = statement->Step(); - if (errorCode != E_OK) { - LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode); - CloseInner(); - return errorCode; - } - return E_OK; -} - -int32_t TransactionImpl::Commit() -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - std::lock_guard lock(mutex_); - if (connection_ == nullptr) { - LOG_ERROR("connection already closed"); - return E_GRD_DB_INSTANCE_ABNORMAL; - } - - auto [errorCode, statement] = connection_->CreateStatement(COMMIT_GQL, connection_); - if (errorCode != E_OK || statement == nullptr) { - LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode); - CloseInner(); - return errorCode; - } - - errorCode = statement->Step(); - CloseInner(); - if (errorCode != E_OK) { - LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode); - return errorCode; - } - return E_OK; -} - -int32_t TransactionImpl::Rollback() -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - std::lock_guard lock(mutex_); - if (connection_ == nullptr) { - LOG_ERROR("connection already closed"); - return E_GRD_DB_INSTANCE_ABNORMAL; - } - - auto [errorCode, statement] = connection_->CreateStatement(ROLLBACK_GQL, connection_); - if (errorCode != E_OK || statement == nullptr) { - LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode); - CloseInner(); - return errorCode; - } - - errorCode = statement->Step(); - CloseInner(); - if (errorCode != E_OK) { - LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode); - return errorCode; - } - return E_OK; -} - -int32_t TransactionImpl::CloseInner() -{ - std::lock_guard lock(mutex_); - store_ = nullptr; - connection_ = nullptr; - return E_OK; -} - -int32_t TransactionImpl::Close() -{ - return Rollback(); -} - -std::shared_ptr TransactionImpl::GetStore() -{ - std::lock_guard lock(mutex_); - return store_; -} - -std::pair> TransactionImpl::Query(const std::string &gql) -{ - auto store = GetStore(); - if (store == nullptr) { - LOG_ERROR("transaction already close"); - return { E_GRD_DB_INSTANCE_ABNORMAL, std::make_shared() }; - } - return store->QueryGql(gql); -} - -std::pair> TransactionImpl::Execute(const std::string &gql) -{ - auto store = GetStore(); - if (store == nullptr) { - LOG_ERROR("transaction already close"); - return { E_GRD_DB_INSTANCE_ABNORMAL, std::make_shared() }; - } - return store->ExecuteGql(gql); -} -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/gdb/src/vertex.cpp b/relational_store/frameworks/native/gdb/src/vertex.cpp deleted file mode 100644 index ffdb97d5..00000000 --- a/relational_store/frameworks/native/gdb/src/vertex.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "GdbElement" -#include - -#include "gdb_errors.h" -#include "full_result.h" -#include "logger.h" - -namespace OHOS::DistributedDataAip { -Vertex::Vertex() : id_("0"), properties_() -{ -} - -Vertex::Vertex(std::string id, std::string label) : id_(std::move(id)), label_(std::move(label)) -{ - labels_.emplace_back(label_); -} - -Vertex::Vertex(std::string id, std::string label, - const std::unordered_map &properties) - : id_(std::move(id)), label_(std::move(label)), properties_(properties) -{ - labels_.emplace_back(label_); -} - -std::string Vertex::GetId() const -{ - return id_; -} - -void Vertex::SetId(std::string id) -{ - id_ = std::move(id); -} - -const std::string &Vertex::GetLabel() const -{ - return label_; -} - -const std::vector &Vertex::GetLabels() const -{ - return labels_; -} - -void Vertex::SetLabel(const std::string &label) -{ - label_ = label; - labels_.emplace_back(label); -} - -const std::unordered_map &Vertex::GetProperties() const -{ - return properties_; -} - -void Vertex::SetProperty(const std::string &key, PropType value) -{ - properties_[key] = std::move(value); -} - -std::shared_ptr Vertex::Parse(const nlohmann::json &json, int32_t &errCode) -{ - std::shared_ptr element = std::make_shared(); - if (!json.contains(Vertex::LABEL) || !json.contains(Vertex::ID) || - !json.contains(Vertex::PROPERTIES) || !json.at(Vertex::PROPERTIES).is_object()) { - LOG_ERROR("element format error."); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - - if (json.at(Vertex::ID).is_number()) { - auto id = json.at(Vertex::ID).get(); - element->SetId(std::to_string(id)); - } else if (json.at(Vertex::ID).is_string()) { - auto id = json.at(Vertex::ID).get(); - element->SetId(id); - } else { - LOG_ERROR("element id is not number or string."); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - if (!json.at(Vertex::LABEL).is_string()) { - LOG_ERROR("element label is not string."); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - element->SetLabel(json.at(Vertex::LABEL).get()); - for (const auto &[key, value] : json.at(Vertex::PROPERTIES).items()) { - if (value.is_string()) { - element->SetProperty(key, value.get()); - } else if (value.is_number_integer()) { - element->SetProperty(key, value.get()); - } else if (value.is_number_float()) { - element->SetProperty(key, value.get()); - } else if (value.is_boolean()) { - element->SetProperty(key, value.get()); - } else if (value.is_null()) { - element->SetProperty(key, nullptr); - } else { - LOG_ERROR("element property value type is not supported."); - errCode = E_PARSE_JSON_FAILED; - return nullptr; - } - } - errCode = E_OK; - return element; -} -} // namespace OHOS::DistributedDataAip diff --git a/relational_store/frameworks/native/icu/BUILD.gn b/relational_store/frameworks/native/icu/BUILD.gn index ee35d546..f2f4587d 100644 --- a/relational_store/frameworks/native/icu/BUILD.gn +++ b/relational_store/frameworks/native/icu/BUILD.gn @@ -38,6 +38,7 @@ ohos_shared_library("relational_store_icu") { "${relational_store_common_path}/include", "${relational_store_native_path}/icu/include", "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/rdb/include", ] sources = [ "${relational_store_native_path}/icu/src/icu_collect.cpp" ] diff --git a/relational_store/frameworks/native/icu/include/icu_collect.h b/relational_store/frameworks/native/icu/include/icu_collect.h index b8f09767..b68aad60 100644 --- a/relational_store/frameworks/native/icu/include/icu_collect.h +++ b/relational_store/frameworks/native/icu/include/icu_collect.h @@ -23,7 +23,7 @@ namespace OHOS::NativeRdb { class ICUCollect { public: - static int32_t Local(sqlite3 *dbHandle, const std::string &str); + static int32_t Locale(sqlite3 *dbHandle, const std::string &str); private: static int Collate8Compare(void *p, int n1, const void *v1, int n2, const void *v2); diff --git a/relational_store/frameworks/native/icu/src/icu_collect.cpp b/relational_store/frameworks/native/icu/src/icu_collect.cpp index b948c921..d9d2d2fd 100644 --- a/relational_store/frameworks/native/icu/src/icu_collect.cpp +++ b/relational_store/frameworks/native/icu/src/icu_collect.cpp @@ -17,17 +17,26 @@ #include #include +#include #include "ohos/init_data.h" #include "logger.h" #include "rdb_errno.h" #include "rdb_visibility.h" #include "sqlite3.h" +#include "sqlite_errno.h" -API_EXPORT int32_t ConfigICULocal(sqlite3 *, const std::string &str) asm("ConfigICULocal"); -int32_t ConfigICULocal(sqlite3 *handle, const std::string &str) +API_EXPORT int32_t ConfigICULocale(sqlite3 *, const std::string &str) asm("ConfigICULocale"); +API_EXPORT int32_t CleanUp() asm("CleanUp"); +int32_t ConfigICULocale(sqlite3 *handle, const std::string &str) { - return OHOS::NativeRdb::ICUCollect::Local(handle, str); + return OHOS::NativeRdb::ICUCollect::Locale(handle, str); +} + +int32_t CleanUp() +{ + u_cleanup(); + return OHOS::NativeRdb::E_OK; } namespace OHOS::NativeRdb { @@ -62,26 +71,34 @@ void ICUCollect::LocalizedCollatorDestroy(void *collator) ucol_close(reinterpret_cast(collator)); } -int32_t ICUCollect::Local(sqlite3 *dbHandle, const std::string &str) +int32_t ICUCollect::Locale(sqlite3 *dbHandle, const std::string &str) { UErrorCode status = U_ZERO_ERROR; SetHwIcuDirectory(); UCollator *collator = ucol_open(str.c_str(), &status); + if (status == U_USING_DEFAULT_WARNING || status == U_ILLEGAL_ARGUMENT_ERROR) { + LOG_ERROR("A resource bundle lookup returned a result from the root locale, locale:%{public}s.", str.c_str()); + ucol_close(collator); + return E_INVALID_ARGS_NEW; + } if (U_FAILURE(status)) { LOG_ERROR("Can not open collator, status:%{public}d.", status); + ucol_close(collator); return E_ERROR; } ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_PRIMARY, &status); if (U_FAILURE(status)) { LOG_ERROR("Set attribute of collator failed, status:%{public}d.", status); + ucol_close(collator); return E_ERROR; } int err = sqlite3_create_collation_v2(dbHandle, "LOCALES", SQLITE_UTF8, collator, ICUCollect::Collate8Compare, (void (*)(void *))ICUCollect::LocalizedCollatorDestroy); if (err != SQLITE_OK) { LOG_ERROR("SCreate collator in sqlite3 failed err:%{public}d.", err); - return err; + ucol_close(collator); + return SQLiteError::ErrNo(err); } return E_OK; } diff --git a/relational_store/frameworks/native/obs_mgr_adapter/BUILD.gn b/relational_store/frameworks/native/obs_mgr_adapter/BUILD.gn new file mode 100644 index 00000000..8de7d7b0 --- /dev/null +++ b/relational_store/frameworks/native/obs_mgr_adapter/BUILD.gn @@ -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. +import("//build/ohos.gni") +import("//build/ohos/ace/ace.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +group("build_module") { + deps = [ ":rdb_obs_mgr_adapter" ] +} + +ohos_shared_library("rdb_obs_mgr_adapter") { + branch_protector_ret = "pac_ret" + sanitize = { + boundary_sanitize = true + ubsan = true + cfi = true + cfi_cross_dso = true + debug = false + } + + ldflags = [ "-Wl,--exclude-libs,ALL" ] + cflags_cc = [ "-fvisibility=hidden" ] + + include_dirs = [ + "${relational_store_common_path}/include", + "${relational_store_innerapi_path}/rdb/include", + ] + + sources = [ "${relational_store_native_path}/obs_mgr_adapter/obs_mgr_adapter.cpp" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + ] + subsystem_name = "distributeddatamgr" + part_name = "relational_store" +} diff --git a/relational_store/frameworks/native/obs_mgr_adapter/obs_mgr_adapter.cpp b/relational_store/frameworks/native/obs_mgr_adapter/obs_mgr_adapter.cpp new file mode 100644 index 00000000..4b016f24 --- /dev/null +++ b/relational_store/frameworks/native/obs_mgr_adapter/obs_mgr_adapter.cpp @@ -0,0 +1,299 @@ +/* + * 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. + */ + +#define LOG_TAG "ObsMgrAdapter" +#include "obs_mgr_adapter.h" + +#include +#include +#include + +#include "concurrent_map.h" +#include "data_ability_observer_stub.h" +#include "dataobs_mgr_client.h" +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_types.h" +#include "rdb_visibility.h" + +using namespace OHOS::DistributedRdb; +API_EXPORT int32_t Register(const std::string &uri, std::shared_ptr observer) asm("Register"); +API_EXPORT int32_t Unregister(const std::string &uri, std::shared_ptr observer) asm("Unregister"); +API_EXPORT int32_t NotifyChange(const std::string &uri) asm("NotifyChange"); +API_EXPORT bool CleanUp() asm("CleanUp"); +namespace OHOS::NativeRdb { +using namespace OHOS::Rdb; +constexpr int32_t MAX_RETRY = 100; +class RdbStoreLocalSharedObserver : public AAFwk::DataAbilityObserverStub { +public: + explicit RdbStoreLocalSharedObserver(std::shared_ptr observer) : observer_(observer){}; + virtual ~RdbStoreLocalSharedObserver(){}; + void OnChange() override + { + if (observer_ == nullptr) { + LOG_ERROR("observer_ is null."); + return; + } + observer_->OnChange(); + } + + bool operator==(std::shared_ptr observer) + { + if (observer == nullptr) { + return false; + } + return observer_ == observer; + } + +private: + std::shared_ptr observer_ = nullptr; +}; + +static std::string Anonymous(const std::string &uri) +{ + return std::string(uri).substr(uri.rfind("/") + 1, uri.size()); +} + +class ObsMgrAdapterImpl { +public: + ObsMgrAdapterImpl() = default; + static int32_t RegisterObserver(const std::string &uri, std::shared_ptr observer); + static int32_t UnregisterObserver(const std::string &uri, std::shared_ptr observer); + static int32_t NotifyChange(const std::string &uri); + static bool Clean(); + +private: + static void RemoveObserver(const std::string &uri, sptr observer); + static void AddObserver(const std::string &uri, const std::list> &observers); + static void PushReleaseObs(wptr obs); + static bool CleanReleaseObs(bool force = false); + static ConcurrentMap>> obs_; + static std::mutex mutex_; + static std::list> releaseObs_; +}; + +ConcurrentMap>> ObsMgrAdapterImpl::obs_; +std::mutex ObsMgrAdapterImpl::mutex_; +std::list> ObsMgrAdapterImpl::releaseObs_; +int32_t ObsMgrAdapterImpl::RegisterObserver(const std::string &uri, std::shared_ptr observer) +{ + sptr localSharedObserver; + int32_t code = E_OK; + obs_.Compute(uri, [&localSharedObserver, &observer, &uri, &code](const auto &key, auto &obs) { + for (auto it = obs.begin(); it != obs.end();) { + if (*it == nullptr) { + it = obs.erase(it); + continue; + } + if ((**it) == observer) { + LOG_WARN("Duplicate subscribe, uri:%{public}s", Anonymous(uri).c_str()); + code = RDB_OBS_DUPLICATE_SUB; + return !obs.empty(); + } + ++it; + } + localSharedObserver = new (std::nothrow) RdbStoreLocalSharedObserver(observer); + if (localSharedObserver == nullptr) { + LOG_ERROR("no memory! uri:%{public}s", Anonymous(uri).c_str()); + code = E_ERROR; + return !obs.empty(); + } + obs.push_back(localSharedObserver); + return !obs.empty(); + }); + if (localSharedObserver == nullptr) { + return code; + } + auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); + if (client == nullptr) { + RemoveObserver(uri, localSharedObserver); + LOG_ERROR("Failed to get DataObsMgrClient, uri:%{public}s", Anonymous(uri).c_str()); + return E_GET_DATAOBSMGRCLIENT_FAIL; + } + code = client->RegisterObserver(Uri(uri), localSharedObserver); + if (code != 0) { + RemoveObserver(uri, localSharedObserver); + LOG_ERROR("Subscribe failed. code:%{public}d, uri:%{public}s", code, Anonymous(uri).c_str()); + return E_ERROR; + } + return E_OK; +} + +int32_t ObsMgrAdapterImpl::UnregisterObserver(const std::string &uri, std::shared_ptr observer) +{ + std::list> localSharedObservers; + obs_.Compute(uri, [&localSharedObservers, &observer](const auto &key, auto &obs) { + for (auto it = obs.begin(); it != obs.end();) { + if (*it == nullptr) { + it = obs.erase(it); + continue; + } + if ((**it) == observer || observer == nullptr) { + localSharedObservers.push_back(std::move(*it)); + it = obs.erase(it); + continue; + } + ++it; + } + return !obs.empty(); + }); + if (localSharedObservers.empty()) { + return E_OK; + } + auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); + if (client == nullptr) { + AddObserver(uri, localSharedObservers); + LOG_ERROR("Failed to get DataObsMgrClient, uri:%{public}s", Anonymous(uri).c_str()); + return E_GET_DATAOBSMGRCLIENT_FAIL; + } + for (auto it = localSharedObservers.begin(); it != localSharedObservers.end();) { + if (*it == nullptr) { + it = localSharedObservers.erase(it); + continue; + } + int32_t err = client->UnregisterObserver(Uri(uri), *it); + if (err != 0) { + AddObserver(uri, localSharedObservers); + LOG_ERROR("UnregisterObserver failed. code:%{public}d, uri:%{public}s", err, Anonymous(uri).c_str()); + return err; + } + PushReleaseObs(*it); + it = localSharedObservers.erase(it); + } + CleanReleaseObs(); + return E_OK; +} + +int32_t ObsMgrAdapterImpl::NotifyChange(const std::string &uri) +{ + auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); + if (client == nullptr) { + LOG_ERROR("Failed to get DataObsMgrClient, uri:%{public}s", Anonymous(uri).c_str()); + return E_GET_DATAOBSMGRCLIENT_FAIL; + } + auto err = client->NotifyChange(Uri(uri)); + if (err != 0) { + LOG_ERROR("Notify failed, uri:%{public}s", Anonymous(uri).c_str()); + return E_ERROR; + } + return E_OK; +} + +bool ObsMgrAdapterImpl::Clean() +{ + auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); + if (client == nullptr) { + LOG_ERROR("Failed to get DataObsMgrClient"); + return obs_.Empty() && CleanReleaseObs(true); + } + obs_.EraseIf([client](const auto &key, auto &observer) { + for (auto it = observer.begin(); it != observer.end();) { + if (*it == nullptr) { + it = observer.erase(it); + continue; + } + int32_t err = client->UnregisterObserver(Uri(key), *it); + if (err != 0) { + LOG_ERROR("UnregisterObserver failed. code:%{public}d, uri:%{public}s", err, Anonymous(key).c_str()); + ++it; + continue; + } + PushReleaseObs(*it); + it = observer.erase(it); + } + return observer.empty(); + }); + return obs_.Empty() && CleanReleaseObs(true); +} + +void ObsMgrAdapterImpl::RemoveObserver(const std::string &uri, sptr observer) +{ + obs_.ComputeIfPresent(uri, [&observer](const auto &key, auto &obs) { + for (auto it = obs.begin(); it != obs.end();) { + if (*it == nullptr) { + it = obs.erase(it); + continue; + } + if (observer == nullptr || (*it) == observer) { + it = obs.erase(it); + continue; + } + ++it; + } + return !obs.empty(); + }); +} + +void ObsMgrAdapterImpl::AddObserver( + const std::string &uri, const std::list> &observers) +{ + obs_.Compute(uri, [&observers](const auto &key, auto &obs) { + obs.insert(obs.end(), observers.begin(), observers.end()); + return !obs.empty(); + }); +} + +void ObsMgrAdapterImpl::PushReleaseObs(wptr obs) +{ + std::lock_guard lock(mutex_); + releaseObs_.push_back(obs); +} + +bool ObsMgrAdapterImpl::CleanReleaseObs(bool force) +{ + std::lock_guard lock(mutex_); + int32_t retry = 0; + do { + auto it = releaseObs_.begin(); + while (it != releaseObs_.end()) { + if (it->promote()) { + ++it; + } else { + it = releaseObs_.erase(it); + } + } + if (!force) { + break; + } + retry++; + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } while (retry < MAX_RETRY && !releaseObs_.empty()); + if (force && !releaseObs_.empty()) { + LOG_ERROR("Failed to release obs, size:%{public}zu, retry:%{public}d", releaseObs_.size(), retry); + return false; + } + return true; +} +} // namespace OHOS::NativeRdb + +int32_t Register(const std::string &uri, std::shared_ptr observer) +{ + return OHOS::NativeRdb::ObsMgrAdapterImpl::RegisterObserver(uri, observer); +} + +int32_t Unregister(const std::string &uri, std::shared_ptr observer) +{ + return OHOS::NativeRdb::ObsMgrAdapterImpl::UnregisterObserver(uri, observer); +} + +int32_t NotifyChange(const std::string &uri) +{ + return OHOS::NativeRdb::ObsMgrAdapterImpl::NotifyChange(uri); +} + +bool CleanUp() +{ + return OHOS::NativeRdb::ObsMgrAdapterImpl::Clean(); +} \ No newline at end of file diff --git a/relational_store/frameworks/native/obs_mgr_adapter/obs_mgr_adapter.h b/relational_store/frameworks/native/obs_mgr_adapter/obs_mgr_adapter.h new file mode 100644 index 00000000..2623fdf1 --- /dev/null +++ b/relational_store/frameworks/native/obs_mgr_adapter/obs_mgr_adapter.h @@ -0,0 +1,21 @@ +/* + * 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 HOS_NATIVE_RDB_OBS_MGR_ADAPTER_H +#define HOS_NATIVE_RDB_OBS_MGR_ADAPTER_H +#include +namespace OHOS::NativeRdb { +constexpr int32_t RDB_OBS_DUPLICATE_SUB = -1; +} // namespace OHOS::NativeRdb +#endif //HOS_NATIVE_RDB_OBS_MGR_ADAPTER_H diff --git a/relational_store/frameworks/native/rdb/include/connection.h b/relational_store/frameworks/native/rdb/include/connection.h index dd8e291e..a218566b 100644 --- a/relational_store/frameworks/native/rdb/include/connection.h +++ b/relational_store/frameworks/native/rdb/include/connection.h @@ -22,7 +22,9 @@ #include #include +#include "knowledge_types.h" #include "rdb_common.h" +#include "rdb_store_config.h" #include "rdb_types.h" #include "statement.h" @@ -42,17 +44,17 @@ public: using Repairer = int32_t (*)(const RdbStoreConfig &config); using Deleter = int32_t (*)(const RdbStoreConfig &config); using Collector = std::map (*)(const RdbStoreConfig &config); - using Restorer = int32_t (*)(const RdbStoreConfig &config, const std::string &srcPath, const std::string &destPath); + using ReplicaChecker = int32_t (*)(const RdbStoreConfig &config); static std::pair Create(const RdbStoreConfig &config, bool isWriter); static int32_t Repair(const RdbStoreConfig &config); static int32_t Delete(const RdbStoreConfig &config); - static int32_t Restore(const RdbStoreConfig &config, const std::string &srcPath, const std::string &destPath); static std::map Collect(const RdbStoreConfig &config); + static int32_t CheckReplicaIntegrity(const RdbStoreConfig &config); static int32_t RegisterCreator(int32_t dbType, Creator creator); static int32_t RegisterRepairer(int32_t dbType, Repairer repairer); static int32_t RegisterDeleter(int32_t dbType, Deleter deleter); static int32_t RegisterCollector(int32_t dbType, Collector collector); - static int32_t RegisterRestorer(int32_t dbType, Restorer restorer); + static int32_t RegisterReplicaChecker(int32_t dbType, ReplicaChecker replicaChecker); int32_t SetId(int32_t id); int32_t GetId() const; @@ -61,24 +63,31 @@ public: virtual ~Connection() = default; virtual int32_t VerifyAndRegisterHook(const RdbStoreConfig &config) = 0; virtual std::pair CreateStatement(const std::string &sql, SConn conn) = 0; + virtual std::pair CreateReplicaStatement(const std::string &sql, SConn conn) = 0; + virtual int CheckReplicaForRestore() = 0; virtual int32_t GetDBType() const = 0; virtual bool IsWriter() const = 0; - virtual int32_t ReSetKey(const RdbStoreConfig &config) = 0; + virtual int32_t ResetKey(const RdbStoreConfig &config) = 0; virtual int32_t TryCheckPoint(bool timeout) = 0; + virtual int32_t Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) = 0; virtual int32_t LimitWalSize() = 0; virtual int32_t ConfigLocale(const std::string &localeStr) = 0; virtual int32_t CleanDirtyData(const std::string &table, uint64_t cursor) = 0; virtual int32_t SubscribeTableChanges(const Notifier ¬ifier) = 0; virtual int32_t GetMaxVariable() const = 0; virtual int32_t GetJournalMode() = 0; - virtual int32_t ClearCache() = 0; + virtual int32_t ClearCache(bool isForceClear = false) = 0; virtual int32_t Subscribe(const std::shared_ptr &observer) = 0; virtual int32_t Unsubscribe(const std::shared_ptr &observer) = 0; virtual int32_t Backup(const std::string &databasePath, const std::vector &destEncryptKey, bool isAsync, - SlaveStatus &slaveStatus) = 0; + std::shared_ptr slaveStatus, bool verifyDb = true) = 0; virtual int32_t Restore( - const std::string &databasePath, const std::vector &destEncryptKey, SlaveStatus &slaveStatus) = 0; - virtual ExchangeStrategy GenerateExchangeStrategy(const SlaveStatus &status) = 0; + const std::string &databasePath, const std::vector &destEncryptKey, + std::shared_ptr slaveStatus) = 0; + virtual ExchangeStrategy GenerateExchangeStrategy(std::shared_ptr status, bool isRelpay = true) = 0; + virtual int SetKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema &schema) = 0; + virtual int CleanDirtyLog(const std::string &table, uint64_t cursor) = 0; + virtual int RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) = 0; private: int32_t id_ = 0; diff --git a/relational_store/frameworks/native/rdb/include/connection_pool.h b/relational_store/frameworks/native/rdb/include/connection_pool.h index a85a7eb9..8121d12a 100644 --- a/relational_store/frameworks/native/rdb/include/connection_pool.h +++ b/relational_store/frameworks/native/rdb/include/connection_pool.h @@ -31,6 +31,7 @@ #include "connection.h" #include "rdb_common.h" #include "rdb_store_config.h" +#include "delay_actuator.h" namespace OHOS { class ExecutorPool; namespace NativeRdb { @@ -54,9 +55,11 @@ public: int32_t Dump(bool isWriter, const char *header); int RestartConns(); + int ReopenConns(); int ConfigLocale(const std::string &localeStr); int ChangeDbFileForRestore(const std::string &newPath, const std::string &backupPath, - const std::vector &newKey, SlaveStatus &slaveStatus); + const std::vector &newKey, std::shared_ptr slaveStatus); + int Rekey(const RdbStoreConfig::CryptoParam &cryptoParam); std::stack &GetTransactionStack(); std::mutex &GetTransactionStackMutex(); int AcquireTransaction(); @@ -71,7 +74,7 @@ private: int32_t tid_ = 0; int32_t id_ = 0; std::chrono::steady_clock::time_point time_ = std::chrono::steady_clock::now(); - std::shared_ptr connect_; + const std::shared_ptr connect_; explicit ConnNode(std::shared_ptr conn); std::shared_ptr GetConnect(); @@ -125,7 +128,9 @@ private: int32_t GetMaxReaders(const RdbStoreConfig &config); std::shared_ptr Convert2AutoConn(std::shared_ptr node, bool isTrans = false); void ReleaseNode(std::shared_ptr node, bool reuse = true); - int RestoreMasterDb(const std::string &newPath, const std::string &backupPath, SlaveStatus &slaveStatus); + int RestoreByDbSqliteType(const std::string &newPath, const std::string &backupPath, + std::shared_ptr slaveStatus); + int RestoreMasterDb(const std::string &newPath, const std::string &backupPath); bool CheckIntegrity(const std::string &dbPath); void DelayClearTrans(); @@ -135,6 +140,12 @@ private: static constexpr uint32_t ITERS_COUNT = 2; static constexpr uint32_t MAX_TRANS = 4; static constexpr std::chrono::steady_clock::duration TRANS_CLEAR_INTERVAL = std::chrono::seconds(150); + static constexpr uint32_t FIRST_DELAY_INTERVAL = ActuatorBase::INVALID_INTERVAL; + static constexpr uint32_t MIN_EXECUTE_INTERVAL = ActuatorBase::INVALID_INTERVAL; + static constexpr uint32_t MAX_EXECUTE_INTERVAL = 30000; // 30000ms + std::shared_ptr>, + std::function> &out, std::shared_ptr &&input)>>> + clearActuator_; const RdbStoreConfig &config_; RdbStoreConfig attachConfig_; Container writers_; diff --git a/relational_store/frameworks/native/rdb/include/delay_notify.h b/relational_store/frameworks/native/rdb/include/delay_notify.h index 3ac0f736..c2f1d685 100644 --- a/relational_store/frameworks/native/rdb/include/delay_notify.h +++ b/relational_store/frameworks/native/rdb/include/delay_notify.h @@ -28,7 +28,7 @@ namespace OHOS { class ExecutorPool; namespace NativeRdb { -class DelayNotify { +class DelayNotify : public std::enable_shared_from_this { public: using Task = std::function; using Time = std::chrono::steady_clock::time_point; diff --git a/relational_store/frameworks/native/rdb/include/global_resource.h b/relational_store/frameworks/native/rdb/include/global_resource.h new file mode 100644 index 00000000..8217b63a --- /dev/null +++ b/relational_store/frameworks/native/rdb/include/global_resource.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 NATIVE_RDB_GLOBAL_RESOURCE_H +#define NATIVE_RDB_GLOBAL_RESOURCE_H +#include +namespace OHOS { +namespace NativeRdb { +class GlobalResource { +public: + enum CleanType { + CLEAN_HEAD = 0, + DB_CLIENT = CLEAN_HEAD, + OPEN_SSL, + ICU, + OBS, + IPC, + CLEAN_BUTT + }; + using Cleaner = int32_t (*)(); + static int32_t RegisterClean(CleanType type, Cleaner clean); + static int32_t CleanUp(int32_t type); +}; + +} // namespace NativeRdb +} // namespace OHOS +#endif // NATIVE_RDB_GLOBAL_RESOURCE_H diff --git a/relational_store/frameworks/native/rdb/include/grd_api_manager.h b/relational_store/frameworks/native/rdb/include/grd_api_manager.h index 51a01de1..d9f2e10a 100644 --- a/relational_store/frameworks/native/rdb/include/grd_api_manager.h +++ b/relational_store/frameworks/native/rdb/include/grd_api_manager.h @@ -58,7 +58,8 @@ typedef int32_t (*DBRestore)(const char *dbFile, const char *backupDbFile, GRD_C typedef int32_t (*DBReKey)(const char *dbFile, const char *configStr, GRD_CipherInfoT *cipherInfo); typedef GRD_DbValueT (*DBGetConfig)(GRD_DB *db, GRD_ConfigTypeE type); typedef int32_t (*DBSetConfig)(GRD_DB *db, GRD_ConfigTypeE type, GRD_DbValueT value); -typedef int32_t (*DBSqlRegistryThreadPool)(GRD_DB *db, GRD_ThreadPool *threadPool); +typedef int32_t (*DBSqlRegistryThreadPool)(GRD_DB *db, GRD_DbThreadPoolT *threadPool); +typedef int32_t (*DBSqlRegistryClusterAlgo)(GRD_DB *db, const char *clstAlgoName, GRD_ClusterAlgoFunc func); struct GRD_APIInfo { DBOpen DBOpenApi = nullptr; @@ -92,6 +93,7 @@ struct GRD_APIInfo { DBGetConfig DBGetConfigApi = nullptr; DBSetConfig DBSetConfigApi = nullptr; DBSqlRegistryThreadPool DBSqlRegistryThreadPool = nullptr; + DBSqlRegistryClusterAlgo DBSqlRegistryClusterAlgo = nullptr; }; API_EXPORT bool IsUsingArkData(); diff --git a/relational_store/frameworks/native/rdb/include/grd_type_export.h b/relational_store/frameworks/native/rdb/include/grd_type_export.h index dedcdf52..42a086d2 100644 --- a/relational_store/frameworks/native/rdb/include/grd_type_export.h +++ b/relational_store/frameworks/native/rdb/include/grd_type_export.h @@ -30,10 +30,36 @@ typedef struct GRD_DB GRD_DB; typedef struct GRD_SqlStmt GRD_SqlStmt; typedef struct GRD_Stmt GRD_StmtT; -typedef void (*GRD_ScheduleFunc)(void *func, void *param); -typedef struct GRD_ThreadPool { - GRD_ScheduleFunc schedule; -} GRD_ThreadPoolT; +typedef uint64_t (*GRD_DbScheduleFunc)(void *func, void *param); +typedef bool (*GRD_DbRemoveFunc)(uint64_t taskId, bool wait); +typedef struct GRD_DbThreadPool { + GRD_DbScheduleFunc schedule; + GRD_DbRemoveFunc remove; +} GRD_DbThreadPoolT; + +typedef struct GRD_ClstAlgoPara { + /* Input Parameters */ + uint16_t featureDim; // Feature vector dimension, currently supports 256D only + uint32_t oldFeaturesNum; // Number of historical cluster center vectors + float *oldFeatures; // Array of historical cluster center vectors, + // stored in row-major order (length: oldFeaturesNum * dim) + const int32_t *oldClstGroupId; // Cluster ID for each historical vector (length: oldFeaturesNum) + const int32_t *oldClstVecNum; // Number of vectors in each historical cluster (length: oldFeaturesNum) + + uint32_t newFeaturesNum; // Number of newly collected vectors + float *newFeatures; // Array of new feature vectors + // stored in row-major order (length: newFeaturesNum * dim) + int32_t newClusterIdStart; // Starting cluster ID for new clusters, usually the maximum old cluster ID plus one + + /* Customization Parameters */ + void *customParams; // Developers need to communicate with the database development team before using it + + /* Output Parameters */ + int32_t *clusterResult; // Clustering result array, indicating the assigned cluster ID for each new vector + // (length: newFeaturesNum) +} GRD_ClstAlgoParaT; + +typedef int32_t (*GRD_ClusterAlgoFunc)(GRD_ClstAlgoParaT *para); /** * @brief Open database config diff --git a/relational_store/frameworks/native/rdb/include/irdb_service.h b/relational_store/frameworks/native/rdb/include/irdb_service.h index 88682d63..efce9f83 100644 --- a/relational_store/frameworks/native/rdb/include/irdb_service.h +++ b/relational_store/frameworks/native/rdb/include/irdb_service.h @@ -32,7 +32,9 @@ class IKvStoreDataService : public IRemoteBroker { public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedKv.IKvStoreDataService"); virtual sptr GetFeatureInterface(const std::string &name) = 0; - virtual int32_t RegisterDeathObserver(const std::string &bundleName, sptr observer) = 0; + virtual int32_t RegisterDeathObserver( + const std::string &bundleName, sptr observer, const std::string &featureName) = 0; + virtual int32_t Exit(const std::string &featureName) = 0; }; } // namespace OHOS::DistributedRdb #endif diff --git a/relational_store/frameworks/native/gdb/include/transaction_impl.h b/relational_store/frameworks/native/rdb/include/knowledge_schema_helper.h similarity index 38% rename from relational_store/frameworks/native/gdb/include/transaction_impl.h rename to relational_store/frameworks/native/rdb/include/knowledge_schema_helper.h index fdaaa64a..ef6a2501 100644 --- a/relational_store/frameworks/native/gdb/include/transaction_impl.h +++ b/relational_store/frameworks/native/rdb/include/knowledge_schema_helper.h @@ -12,44 +12,42 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef ARKDATA_INTELLIGENCE_PLATFORM_TRANSACTION_IMPL_H -#define ARKDATA_INTELLIGENCE_PLATFORM_TRANSACTION_IMPL_H + +#ifndef DISTRIBUTED_RDB_KNOWLEDGE_SCHEMA_HELPER_H +#define DISTRIBUTED_RDB_KNOWLEDGE_SCHEMA_HELPER_H #include -#include #include +#include +#include -#include "connection.h" -#include "gdb_store_config.h" -#include "gdb_transaction.h" -#include "result.h" +#include "knowledge_types.h" +#include "rdb_types.h" -namespace OHOS::DistributedDataAip { -class DBStore; -class TransactionImpl : public Transaction { +namespace OHOS::NativeRdb { +class KnowledgeSchemaHelper : public std::enable_shared_from_this { public: - TransactionImpl(std::shared_ptr connection); - ~TransactionImpl() override; - - int32_t Commit() override; - int32_t Rollback() override; - int32_t Close() override; - - std::pair> Query(const std::string &gql) override; - std::pair> Execute(const std::string &gql) override; - - static std::pair> Create(std::shared_ptr conn); + KnowledgeSchemaHelper() = default; + ~KnowledgeSchemaHelper(); + void Init(const RdbStoreConfig &config, const DistributedRdb::RdbKnowledgeSchema &schema); + std::pair GetRdbKnowledgeSchema(const std::string &dbName); + void DonateKnowledgeData(); + void Close(); private: - int32_t Start(); - int32_t CloseInner(); - std::shared_ptr GetStore(); - - std::recursive_mutex mutex_; - std::shared_ptr store_; - std::shared_ptr connection_; - - static const int32_t regCreator_; -}; -} // namespace OHOS::DistributedDataAip + void LoadKnowledgeLib(); + void LoadKnowledgeSchemaManager(void *handle); + bool IsLoadLib() const; + void StartTask(); + + mutable std::shared_mutex libMutex_; + DistributedRdb::IKnowledgeSchemaManager *schemaManager_ = nullptr; + bool inited_ = false; +#ifndef CROSS_PLATFORM + void *dlHandle_ = nullptr; #endif + std::string bundleName_ = ""; + std::string dbName_ = ""; +}; +} +#endif // DISTRIBUTED_RDB_KNOWLEDGE_SCHEMA_HELPER_H diff --git a/relational_store/frameworks/native/rdb/include/rd_connection.h b/relational_store/frameworks/native/rdb/include/rd_connection.h index 7d0da643..0f4315d9 100644 --- a/relational_store/frameworks/native/rdb/include/rd_connection.h +++ b/relational_store/frameworks/native/rdb/include/rd_connection.h @@ -39,38 +39,40 @@ public: ~RdConnection(); int32_t VerifyAndRegisterHook(const RdbStoreConfig &config) override; std::pair CreateStatement(const std::string &sql, SConn conn) override; + std::pair CreateReplicaStatement(const std::string &sql, SConn conn) override; + int CheckReplicaForRestore() override; int32_t GetDBType() const override; bool IsWriter() const override; - int32_t ReSetKey(const RdbStoreConfig &config) override; + int32_t ResetKey(const RdbStoreConfig &config) override; int32_t TryCheckPoint(bool timeout) override; int32_t LimitWalSize() override; + int32_t Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) override; int32_t ConfigLocale(const std::string &localeStr) override; int32_t CleanDirtyData(const std::string &table, uint64_t cursor) override; int32_t SubscribeTableChanges(const Notifier ¬ifier) override; int32_t GetMaxVariable() const override; int32_t GetJournalMode() override; - int32_t ClearCache() override; + int32_t ClearCache(bool isForceClear = false) override; int32_t Subscribe(const std::shared_ptr &observer) override; int32_t Unsubscribe(const std::shared_ptr &observer) override; int32_t Backup(const std::string &databasePath, const std::vector &destEncryptKey, bool isAsync, - SlaveStatus &slaveStatus) override; + std::shared_ptr slaveStatus, bool verifyDb = true) override; int32_t Restore(const std::string &databasePath, const std::vector &destEncryptKey, - SlaveStatus &slaveStatus) override; - ExchangeStrategy GenerateExchangeStrategy(const SlaveStatus &status) override; + std::shared_ptr slaveStatus) override; + ExchangeStrategy GenerateExchangeStrategy(std::shared_ptr status, bool isRelpay) override; + int SetKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema &schema) override; + int CleanDirtyLog(const std::string &table, uint64_t cursor) override; + int RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) override; private: - static void CheckConfig(std::shared_ptr conn, const RdbStoreConfig &config); - static void ExecuteSet(std::shared_ptr conn, const std::string ¶mName, int num); - - static constexpr int MAX_VARIABLE_NUM = 500; + static constexpr int MAX_VARIABLE_NUM = 32766; static constexpr const char *GRD_OPEN_CONFIG_STR = "\"pageSize\":8, \"crcCheckEnable\":0, \"redoFlushByTrx\":1, \"bufferPoolSize\":10240," - "\"sharedModeEnable\":1, \"metaInfoBak\":1, \"maxConnNum\":500"; + "\"sharedModeEnable\":1, \"metaInfoBak\":1, \"maxConnNum\":500, \"defaultIsolationLevel\":2"; static constexpr uint32_t NO_ITER = 0; static constexpr uint32_t ITER_V1 = 5000; static constexpr uint32_t ITERS[] = { NO_ITER, ITER_V1 }; static constexpr uint32_t ITERS_COUNT = sizeof(ITERS) / sizeof(ITERS[0]); - static constexpr int NCANDIDATES_DEFAULT_NUM = 128; static const int32_t regCreator_; static const int32_t regRepairer_; static const int32_t regDeleter_; diff --git a/relational_store/frameworks/native/rdb/include/rd_statement.h b/relational_store/frameworks/native/rdb/include/rd_statement.h index fcba0f5b..9e8a09f3 100644 --- a/relational_store/frameworks/native/rdb/include/rd_statement.h +++ b/relational_store/frameworks/native/rdb/include/rd_statement.h @@ -51,6 +51,7 @@ public: bool ReadOnly() const override; bool SupportBlockInfo() const override; int32_t FillBlockInfo(SharedBlockInfo *info) const override; + std::pair> GetRows(uint32_t maxCount) override; void GetProperties(); private: diff --git a/relational_store/frameworks/native/rdb/include/rd_utils.h b/relational_store/frameworks/native/rdb/include/rd_utils.h index 1e759ac4..16a62e79 100644 --- a/relational_store/frameworks/native/rdb/include/rd_utils.h +++ b/relational_store/frameworks/native/rdb/include/rd_utils.h @@ -40,6 +40,22 @@ public: static int RdSqlFinalize(GRD_SqlStmt *stmt); static int RdSqlBindBlob(GRD_SqlStmt *stmt, uint32_t idx, const void *val, int32_t len, void (*freeFunc)(void *)); + /** + * @brief Binds a text buffer to a parameter in a prepared SQL statement + * + * This function binds a text data buffer to a parameter placeholder in a SQL prepared statement. + * Typically used to replace "?" placeholders in SQL statements with actual values before execution. + * + * @param stmt Pointer to the prepared statement object. Must be properly initialized. + * @param idx 1-based parameter index (SQL parameter numbering starts at 1). + * @param val Pointer to the data buffer to bind. Can be text. + * @param len The actual length of the val cannot be greater than the actual length of the val. + * @param freeFunc Memory disposal callback + * @return int Operation status code: + * - 0: Success + * - Non-zero: Error code (see implementation-specific definitions) + * @note The prepared statement must be in a state that accepts parameter binding. + */ static int RdSqlBindText(GRD_SqlStmt *stmt, uint32_t idx, const void *val, int32_t len, void (*freeFunc)(void *)); static int RdSqlBindInt(GRD_SqlStmt *stmt, uint32_t idx, int32_t val); static int RdSqlBindInt64(GRD_SqlStmt *stmt, uint32_t idx, int64_t val); @@ -72,8 +88,9 @@ public: static int RdDbSetVersion(GRD_DB *db, GRD_ConfigTypeE type, int version); static int RdSqlRegistryThreadPool(GRD_DB *db); + static int RdSqlRegistryClusterAlgo(GRD_DB *db, const char *clstAlgoName, GRD_ClusterAlgoFunc func); private: - static GRD_ThreadPoolT threadPool_; + static GRD_DbThreadPoolT threadPool_; }; } // namespace NativeRdb diff --git a/relational_store/frameworks/native/rdb/include/rdb_icu_manager.h b/relational_store/frameworks/native/rdb/include/rdb_icu_manager.h new file mode 100644 index 00000000..d079da92 --- /dev/null +++ b/relational_store/frameworks/native/rdb/include/rdb_icu_manager.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 OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_ICU_MANAGER_H +#define OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_ICU_MANAGER_H +#include +#include +#include +struct sqlite3; +namespace OHOS { +namespace NativeRdb { +class RdbICUManager { +public: + static RdbICUManager &GetInstance(); + int32_t ConfigLocale(sqlite3 *, const std::string &); +private: + RdbICUManager(); + ~RdbICUManager(); + int32_t CleanUp(); + using ConfigICULocaleFunc = int32_t(*)(sqlite3 *, const std::string &); + using CleanUpFunc = int32_t(*)(); + struct ICUAPIInfo { + ConfigICULocaleFunc configIcuLocaleFunc = nullptr; + CleanUpFunc cleanUpFunc = nullptr; + }; + ICUAPIInfo GetApiInfo(); + std::mutex mutex_; + void *handle_ = nullptr; + ICUAPIInfo apiInfo_; +}; + +} // namespace NativeRdb +} // namespace OHOS +#endif //LDBPROJ_RDB_ICU_MANAGER_H diff --git a/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h b/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h index dd0ee95a..af71706d 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h +++ b/relational_store/frameworks/native/rdb/include/rdb_manager_impl.h @@ -63,6 +63,10 @@ private: void ResetServiceHandle(); + int32_t CleanUp(); + + static sptr LinkToDeath(const sptr &remote); + static std::shared_ptr GetDistributedDataManager(const std::string &bundleName); std::mutex mutex_; @@ -76,7 +80,12 @@ public: explicit RdbStoreDataServiceProxy(const sptr &impl); ~RdbStoreDataServiceProxy() = default; sptr GetFeatureInterface(const std::string &name) override; - int32_t RegisterDeathObserver(const std::string &bundleName, sptr observer) override; + int32_t RegisterDeathObserver(const std::string &bundleName, sptr observer, + const std::string &featureName = DistributedRdb::RdbService::SERVICE_NAME) override; + int32_t Exit(const std::string &featureName = DistributedRdb::RdbService::SERVICE_NAME) override; + +private: + sptr clientDeathObserver_; }; } // namespace OHOS::DistributedRdb #endif diff --git a/relational_store/frameworks/native/rdb/include/rdb_obs_manager.h b/relational_store/frameworks/native/rdb/include/rdb_obs_manager.h new file mode 100644 index 00000000..a4d8ec57 --- /dev/null +++ b/relational_store/frameworks/native/rdb/include/rdb_obs_manager.h @@ -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. + */ +#ifndef OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_OBS_MANAGER_H +#define OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_OBS_MANAGER_H +#include +#include +#include + +#include "concurrent_map.h" +#include "rdb_types.h" + +namespace OHOS::NativeRdb { +class RdbObsManager { +public: + RdbObsManager() = default; + virtual ~RdbObsManager(); + int32_t Register(const std::string &uri, std::shared_ptr rdbStoreObserver); + int32_t Unregister(const std::string &uri, std::shared_ptr rdbStoreObserver); + int32_t Notify(const std::string &uri); + +private: + using RegisterFunc = int32_t (*)(const std::string &, std::shared_ptr); + using UnregisterFunc = int32_t (*)(const std::string &, std::shared_ptr); + using NotifyFunc = int32_t (*)(const std::string &); + using CleanFunc = bool (*)(); + struct ObsAPIInfo { + RegisterFunc registerFunc = nullptr; + UnregisterFunc unregisterFunc = nullptr; + NotifyFunc notifyFunc = nullptr; + CleanFunc cleanFunc = nullptr; + }; + static ObsAPIInfo GetApiInfo(); + static int32_t CleanUp(); + static std::mutex mutex_; + static ObsAPIInfo apiInfo_; + static void *handle_; + ConcurrentMap>> obs_; +}; +} // namespace OHOS::NativeRdb +#endif //OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_OBS_MANAGER_H diff --git a/relational_store/frameworks/native/rdb/include/rdb_perfStat.h b/relational_store/frameworks/native/rdb/include/rdb_perfStat.h new file mode 100644 index 00000000..14a1afa2 --- /dev/null +++ b/relational_store/frameworks/native/rdb/include/rdb_perfStat.h @@ -0,0 +1,82 @@ +/* + * 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 OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_PERFSTAT_H +#define OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_PERFSTAT_H +#include +#include +#include +#include +#include + +#include "rdb_types.h" +#include "rdb_visibility.h" + +namespace OHOS { +template +class ConcurrentMap; +namespace DistributedRdb { +class PerfStat { +public: + struct ThreadParam { + int32_t suspenders_ = 0; + size_t size_ = 0; + }; + enum Step : int32_t { + STEP_TOTAL, + STEP_TOTAL_REF, + STEP_TOTAL_RES, + STEP_WAIT, + STEP_PREPARE, + STEP_EXECUTE, + STEP_TRANS_START, + STEP_TRANS, + STEP_TRANS_END, + STEP_BUTT, + }; + API_EXPORT static int Subscribe(const std::string &storeId, std::shared_ptr observer); + API_EXPORT static int Unsubscribe(const std::string &storeId, std::shared_ptr observer); + static uint32_t GenerateId(); + static void Pause(uint32_t seqId = 0); + static void Resume(uint32_t seqId = 0); + + ~PerfStat(); + PerfStat(const std::string &storeId, const std::string &sql, int32_t step, uint32_t seqId = 0, size_t size = 0); + +private: + using SqlExecInfo = SqlObserver::SqlExecutionInfo; + using Release = std::function; + void FormatSql(const std::string& sql); + static Release GetRelease(int32_t step, uint32_t seqId, const std::string &storeId); + static void Merge(uint32_t seqId, SqlExecInfo *execInfo); + static void Notify(SqlExecInfo *execInfo, const std::string &storeId); + static bool IsPaused(); + static size_t GetSize(); + static void SetSize(size_t size); + static ConcurrentMap>> observers_; + static ConcurrentMap> execInfos_; + static bool enabled_; + static std::atomic_uint32_t seqId_; + static std::shared_mutex mutex_; + static std::map threadParams_; + + int32_t step_ = 0; + uint64_t key_ = 0; + std::chrono::steady_clock::time_point time_; + std::shared_ptr execInfo_; +}; +} // namespace DistributedRdb +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_PERFSTAT_H \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/include/rdb_security_manager.h b/relational_store/frameworks/native/rdb/include/rdb_security_manager.h index af98a09f..d0efae2a 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_security_manager.h +++ b/relational_store/frameworks/native/rdb/include/rdb_security_manager.h @@ -26,20 +26,35 @@ #include #include -#include "hks_type.h" - namespace OHOS::NativeRdb { struct RdbSecretKeyData { - uint8_t distributed = 0; + static constexpr uint32_t CURRENT_VERSION = 1; + uint8_t distributed = CURRENT_VERSION; time_t timeValue{}; std::vector secretKey{}; RdbSecretKeyData() = default; ~RdbSecretKeyData() { + distributed = 0; + timeValue = time_t(); secretKey.assign(secretKey.size(), 0); } }; +struct RdbSecretContent { + static constexpr uint32_t MAGIC_NUMBER_V2 = 0x6B6B6B6B; + static constexpr uint32_t NONCE_VALUE_SIZE = 12; + uint32_t magicNum = MAGIC_NUMBER_V2; + std::vector nonceValue{}; + std::vector encryptValue{}; + RdbSecretContent() = default; + ~RdbSecretContent() + { + nonceValue.assign(nonceValue.size(), 0); + encryptValue.assign(encryptValue.size(), 0); + } +}; + class RdbPassword final { public: RdbPassword(); @@ -63,6 +78,12 @@ private: class RdbSecurityManager { public: + enum HksErrCode { + HKS_SUCCESS = 0, + HKS_FAILURE = -1, + HKS_ERROR_NOT_EXIST = -13, + }; + enum KeyFileType : int32_t { PUB_KEY_FILE = 0, PUB_KEY_FILE_NEW_KEY, @@ -75,7 +96,7 @@ public: const std::string &GetKeyFile(KeyFileType type); int32_t InitKeyPath(); int32_t DestroyLock(); - int32_t Lock(); + int32_t Lock(bool isBlock = true); int32_t Unlock(); private: @@ -98,36 +119,39 @@ private: ~RdbSecurityManager(); bool HasRootKey(); - int GenerateRootKey(const std::vector &rootKeyAlias); + void* GetHandle(); + int32_t GenerateRootKey(const std::vector &rootKeyAlias); int32_t CheckRootKeyExists(std::vector &rootKeyAlias); - std::vector EncryptWorkKey(std::vector &key); - bool DecryptWorkKey(std::vector &source, std::vector &key); + std::pair EncryptWorkKey(const std::vector &key); + std::vector DecryptWorkKey(const std::vector &key, const std::vector &nonce); + void ReportCryptFault(int32_t code, const std::string &message); std::vector GenerateRootKeyAlias(const std::string &bundleName); static bool InitPath(const std::string &fileDir); std::vector GenerateRandomNum(int32_t len); bool SaveSecretKeyToFile(const std::string &keyFile, const std::vector &workey = {}); - bool SaveSecretKeyToDisk(const std::string &keyPath, RdbSecretKeyData &keyData); + bool SaveSecretKeyToDisk(const std::string &keyPath, const RdbSecretContent &secretContent); RdbPassword LoadSecretKeyFromFile(const std::string &keyFile); bool LoadSecretKeyFromDisk(const std::string &keyPath, RdbSecretKeyData &keyData); + bool LoadSecretKeyFromDiskV1(const std::string &keyPath, RdbSecretKeyData &keyData); + std::pair UnpackV1(const std::vector &content); + std::pair UnpackV2(const std::vector &content); + std::pair DecryptV1(const RdbSecretContent &content); + std::pair DecryptV2(const RdbSecretContent &content); bool IsKeyFileEmpty(const std::string &keyFile); static bool IsKeyExpired(const time_t &createTime); std::vector GetRootKeyAlias(); std::string GetBundleNameByAlias(); std::string GetBundleNameByAlias(const std::vector &rootKeyAlias); void SetRootKeyAlias(std::vector rootKeyAlias); - int32_t HksLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, - const struct HksBlob *inData, struct HksBlob *outData); - int32_t HksEncryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, - const struct HksBlob *plainText, struct HksBlob *cipherText); - int32_t HksDecryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, - const struct HksBlob *cipherText, struct HksBlob *plainText); + std::string ReplaceSuffix(const std::string& str); static constexpr char const *SUFFIX_KEY_LOCK = ".key_lock"; - static constexpr char const *SUFFIX_PUB_KEY = ".pub_key"; + static constexpr char const *SUFFIX_PUB_KEY = ".pub_key_v1"; static constexpr char const *SUFFIX_PUB_KEY_NEW = ".pub_key.new"; + static constexpr const char *SUFFIX_PUB_KEY_OLD = ".pub_key"; + static constexpr const char *SUFFIX_PUB_TMP_NEW_KEY = ".pub_key.new.bk"; static constexpr const char *RDB_ROOT_KEY_ALIAS_PREFIX = "DistributedDataRdb"; static constexpr const char *RDB_HKS_BLOB_TYPE_NONCE = "Z5s0Bo571Koq"; - static constexpr const char *RDB_HKS_BLOB_TYPE_AAD = "RdbClientAAD"; static constexpr uint32_t TIMES = 4; static constexpr uint32_t MAX_UPDATE_SIZE = 64; static constexpr uint32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES; @@ -140,10 +164,10 @@ private: std::mutex rootKeyMutex_; std::vector rootKeyAlias_{}; - std::vector nonce_; - std::vector aad_; std::mutex mutex_; std::atomic hasRootKey_ = false; + void *handle_; + std::mutex handleMutex_; }; } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h index 244cf491..1c74a036 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h +++ b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h @@ -20,6 +20,7 @@ #include #include +#include #include "concurrent_map.h" #include "irdb_service.h" @@ -29,7 +30,7 @@ namespace OHOS::DistributedRdb { class RdbServiceProxy : public IRemoteProxy { public: struct ObserverParam { - RdbStoreObserver *observer = nullptr; + std::weak_ptr observer; std::string bundleName; SubscribeOption subscribeOption{ SubscribeMode::REMOTE }; }; @@ -40,8 +41,10 @@ public: }; using SyncObservers = ConcurrentMap>; explicit RdbServiceProxy(const sptr &object); + ~RdbServiceProxy(); - std::string ObtainDistributedTableName(const std::string &device, const std::string &table) override; + std::string ObtainDistributedTableName( + const RdbSyncerParam ¶m, const std::string &device, const std::string &table) override; int32_t InitNotifier(const RdbSyncerParam ¶m); @@ -53,10 +56,11 @@ public: int32_t Sync(const RdbSyncerParam ¶m, const Option &option, const PredicatesMemo &predicates, const AsyncDetail &async) override; - int32_t Subscribe(const RdbSyncerParam ¶m, const SubscribeOption &option, RdbStoreObserver *observer) override; + int32_t Subscribe(const RdbSyncerParam ¶m, const SubscribeOption &option, + std::shared_ptr observer) override; - int32_t UnSubscribe( - const RdbSyncerParam ¶m, const SubscribeOption &option, RdbStoreObserver *observer) override; + int32_t UnSubscribe(const RdbSyncerParam ¶m, const SubscribeOption &option, + std::shared_ptr observer) override; int32_t RegisterAutoSyncCallback( const RdbSyncerParam ¶m, std::shared_ptr observer) override; @@ -101,6 +105,7 @@ public: int32_t VerifyPromiseInfo(const RdbSyncerParam ¶m) override; SyncObservers ExportSyncObservers(); void ImportSyncObservers(SyncObservers &SyncObservers); + void OnRemoteDeadSyncComplete(); private: using ChangeInfo = RdbStoreObserver::ChangeInfo; diff --git a/relational_store/frameworks/native/rdb/include/rdb_sql_log.h b/relational_store/frameworks/native/rdb/include/rdb_sql_log.h new file mode 100644 index 00000000..9e09eb65 --- /dev/null +++ b/relational_store/frameworks/native/rdb/include/rdb_sql_log.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 OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_SQL_LOG_H +#define OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_SQL_LOG_H +#include +#include +#include +#include + +#include "rdb_types.h" +#include "rdb_visibility.h" + +namespace OHOS { +template +class ConcurrentMap; +namespace NativeRdb { +using ExceptionMessage = DistributedRdb::SqlErrorObserver::ExceptionMessage; +using SqlErrorObserver = DistributedRdb::SqlErrorObserver; +class SqlLog { +public: + SqlLog(); + ~SqlLog(); + API_EXPORT static int Subscribe(const std::string storeId, std::shared_ptr observer); + API_EXPORT static int Unsubscribe(const std::string storeId, std::shared_ptr observer); + static void Notify(const std::string &storeId, const ExceptionMessage &exceptionMessage); + static void Pause(); + static void Resume(); +private: + static bool IsPause(); + static ConcurrentMap>> observerSets_; + static std::atomic enabled_; + static std::shared_mutex mutex_; + static std::map suspenders_; +}; +} // namespace NativeRdb +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_SQL_LOG_H diff --git a/relational_store/frameworks/native/rdb/include/rdb_sql_statistic.h b/relational_store/frameworks/native/rdb/include/rdb_sql_statistic.h index c5926b7e..02c99daf 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_sql_statistic.h +++ b/relational_store/frameworks/native/rdb/include/rdb_sql_statistic.h @@ -39,7 +39,6 @@ public: }; API_EXPORT static int Subscribe(std::shared_ptr observer); API_EXPORT static int Unsubscribe(std::shared_ptr observer); - static uint32_t GenerateId(); SqlStatistic(const std::string &sql, int32_t step, uint32_t seqId = 0); ~SqlStatistic(); diff --git a/relational_store/frameworks/native/rdb/include/rdb_store_impl.h b/relational_store/frameworks/native/rdb/include/rdb_store_impl.h index 7088ea05..2313cb98 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_store_impl.h +++ b/relational_store/frameworks/native/rdb/include/rdb_store_impl.h @@ -25,9 +25,10 @@ #include "concurrent_map.h" #include "connection_pool.h" -#include "data_ability_observer_stub.h" -#include "dataobs_mgr_client.h" +#include "knowledge_schema_helper.h" #include "rdb_errno.h" +#include "rdb_obs_manager.h" +#include "rdb_open_callback.h" #include "rdb_service.h" #include "rdb_store.h" #include "rdb_store_config.h" @@ -43,52 +44,40 @@ class ExecutorPool; namespace OHOS::NativeRdb { class DelayNotify; class RdbStoreLocalDbObserver; +using RdbStoreObserver = DistributedRdb::RdbStoreObserver; class RdbStoreLocalObserver { public: - explicit RdbStoreLocalObserver(DistributedRdb::RdbStoreObserver *observer) : observer_(observer) {}; + explicit RdbStoreLocalObserver(std::shared_ptr observer) : observer_(observer) {}; virtual ~RdbStoreLocalObserver() {}; void OnChange() { - observer_->OnChange(); + auto obs = observer_.lock(); + if (obs != nullptr) { + obs->OnChange(); + } } - DistributedRdb::RdbStoreObserver *getObserver() + std::shared_ptr getObserver() { - return observer_; + return observer_.lock(); } private: - DistributedRdb::RdbStoreObserver *observer_ = nullptr; -}; - -class RdbStoreLocalSharedObserver : public AAFwk::DataAbilityObserverStub { -public: - explicit RdbStoreLocalSharedObserver(DistributedRdb::RdbStoreObserver *observer) : observer_(observer) {}; - virtual ~RdbStoreLocalSharedObserver() {}; - void OnChange() override - { - observer_->OnChange(); - } - DistributedRdb::RdbStoreObserver *getObserver() - { - return observer_; - } - -private: - DistributedRdb::RdbStoreObserver *observer_ = nullptr; + std::weak_ptr observer_; }; class RdbStoreImpl : public RdbStore { public: RdbStoreImpl(const RdbStoreConfig &config); - RdbStoreImpl(const RdbStoreConfig &config, int &errCode); ~RdbStoreImpl() override; + int32_t Init(int version, RdbOpenCallback &openCallback); std::pair Insert(const std::string &table, const Row &row, Resolution resolution) override; std::pair BatchInsert(const std::string &table, const ValuesBuckets &rows) override; - std::pair BatchInsertWithConflictResolution( - const std::string &table, const ValuesBuckets &rows, Resolution resolution) override; - std::pair Update(const std::string &table, const Row &row, const std::string &where, const Values &args, - Resolution resolution) override; - int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) override; + std::pair BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution) override; + std::pair Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) override; + std::pair Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) override; std::shared_ptr QuerySql(const std::string &sql, const Values &args) override; std::shared_ptr QueryByStep(const std::string &sql, const Values &args, bool preCount) override; std::shared_ptr RemoteQuery( @@ -97,6 +86,7 @@ public: const AbsRdbPredicates &predicates, const Fields &columns) override; int ExecuteSql(const std::string &sql, const Values &args) override; std::pair Execute(const std::string &sql, const Values &args, int64_t trxId) override; + std::pair ExecuteExt(const std::string &sql, const Values &args) override; int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const Values &args) override; int ExecuteAndGetString(std::string &outValue, const std::string &sql, const Values &args) override; int ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, const Values &args) override; @@ -116,17 +106,18 @@ public: bool IsMemoryRdb() const override; bool IsHoldingConnection() override; bool IsSlaveDiffFromMaster() const override; - int Backup(const std::string &databasePath, const std::vector &encryptKey) override; + int Backup(const std::string &databasePath, const std::vector &encryptKey, bool verifyDb) override; int Restore(const std::string &backupPath, const std::vector &newKey) override; int Count(int64_t &outValue, const AbsRdbPredicates &predicates) override; int SetDistributedTables(const std::vector &tables, int32_t type, const DistributedRdb::DistributedConfig &distributedConfig) override; + int32_t Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) override; std::string ObtainDistributedTableName(const std::string &device, const std::string &table, int &errCode) override; int Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncBrief &async) override; int Sync(const SyncOption &option, const std::vector &tables, const AsyncDetail &async) override; int Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncDetail &async) override; - int Subscribe(const SubscribeOption &option, RdbStoreObserver *observer) override; - int UnSubscribe(const SubscribeOption &option, RdbStoreObserver *observer) override; + int Subscribe(const SubscribeOption &option, std::shared_ptr observer) override; + int UnSubscribe(const SubscribeOption &option, std::shared_ptr observer) override; int SubscribeObserver(const SubscribeOption &option, const std::shared_ptr &observer) override; int UnsubscribeObserver(const SubscribeOption &option, const std::shared_ptr &observer) override; int RegisterAutoSyncCallback(std::shared_ptr observer) override; @@ -147,10 +138,13 @@ public: int InterruptBackup() override; int32_t GetBackupStatus() const override; std::pair> CreateTransaction(int32_t type) override; + int CleanDirtyLog(const std::string &table, uint64_t cursor) override; + int InitKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema &schema) override; + int RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) override; // not virtual functions / const RdbStoreConfig &GetConfig(); - int ConfigLocale(const std::string &localeStr); + int ConfigLocale(const std::string &localeStr) override; std::string GetName(); std::string GetFileType(); int32_t ExchangeSlaverToMaster(); @@ -179,15 +173,20 @@ private: }; static void AfterOpen(const RdbParam ¶m, int32_t retry = 0); + int32_t ProcessOpenCallback(int version, RdbOpenCallback &openCallback); + int32_t CreatePool(bool &created); static void RegisterDataChangeCallback( std::shared_ptr delayNotifier, std::weak_ptr connPool, int retry); int InnerOpen(); void InitReportFunc(const RdbParam ¶m); void InitSyncerParam(const RdbStoreConfig &config, bool created); + int32_t SetSecurityLabel(const RdbStoreConfig &config); int ExecuteByTrxId(const std::string &sql, int64_t trxId, bool closeConnAfterExecute = false, const std::vector &bindArgs = {}); + std::pair HandleResults( + std::shared_ptr &&statement, const std::string &sql, int32_t code, int sqlType); std::pair HandleDifferentSqlTypes( - std::shared_ptr statement, const std::string &sql, const ValueObject &object, int sqlType); + std::shared_ptr &&statement, const std::string &sql, int32_t code, int sqlType); int CheckAttach(const std::string &sql); std::pair BeginExecuteSql(const std::string &sql); int GetDataBasePath(const std::string &databasePath, std::string &backupFilePath); @@ -195,20 +194,21 @@ private: static int InnerSync(const RdbParam ¶m, const Options &option, const Memo &predicates, const AsyncDetail &async); int InnerBackup(const std::string &databasePath, - const std::vector &destEncryptKey = std::vector()); + const std::vector &destEncryptKey = std::vector(), bool verifyDb = true); ModifyTime GetModifyTimeByRowId(const std::string &logTable, std::vector &keys); - Uri GetUri(const std::string &event); - int SubscribeLocal(const SubscribeOption &option, RdbStoreObserver *observer); - int SubscribeLocalShared(const SubscribeOption &option, RdbStoreObserver *observer); + std::string GetUri(const std::string &event); + int SubscribeLocal(const SubscribeOption &option, std::shared_ptr observer); + int SubscribeLocalShared(const SubscribeOption &option, std::shared_ptr observer); int32_t SubscribeLocalDetail(const SubscribeOption &option, const std::shared_ptr &observer); - int SubscribeRemote(const SubscribeOption &option, RdbStoreObserver *observer); - int UnSubscribeLocal(const SubscribeOption &option, RdbStoreObserver *observer); - int UnSubscribeLocalShared(const SubscribeOption &option, RdbStoreObserver *observer); + int SubscribeRemote(const SubscribeOption &option, std::shared_ptr observer); + int UnSubscribeLocal(const SubscribeOption &option, std::shared_ptr observer); + int UnSubscribeLocalShared(const SubscribeOption &option, std::shared_ptr observer); int32_t UnsubscribeLocalDetail(const SubscribeOption &option, const std::shared_ptr &observer); - int UnSubscribeRemote(const SubscribeOption &option, RdbStoreObserver *observer); + int UnSubscribeRemote(const SubscribeOption &option, std::shared_ptr observer); int RegisterDataChangeCallback(); void InitDelayNotifier(); - std::pair> CreateWritableConn(); + void TryDump(int32_t code, const char *dumpHeader); + static std::pair> CreateWritableConn(const RdbStoreConfig &config); std::vector CreateBackupBindArgs( const std::string &databasePath, const std::vector &destEncryptKey); std::pair GetStatement(const std::string &sql, std::shared_ptr conn) const; @@ -227,23 +227,39 @@ private: int HandleCloudSyncAfterSetDistributedTables( const std::vector &tables, const DistributedRdb::DistributedConfig &distributedConfig); std::pair> GetConn(bool isRead); - void HandleSchemaDDL(std::shared_ptr statement, - std::shared_ptr pool, const std::string &sql, int32_t &errCode); + std::pair ExecuteForRow(const std::string &sql, const Values &args); + static Results GenerateResult(int32_t code, std::shared_ptr statement, bool isDML = true); + static std::shared_ptr GetValues(std::shared_ptr statement); + int32_t HandleSchemaDDL(std::shared_ptr &&statement, const std::string &sql); void BatchInsertArgsDfx(int argsSize); + void SetKnowledgeSchema(); + std::shared_ptr GetKnowledgeSchemaHelper(); + void SwitchOver(bool isUseReplicaDb); + bool TryAsyncRepair(); + bool IsUseAsyncRestore(const std::string &newPath, const std::string &backupPath); + int StartAsyncRestore(std::shared_ptr pool) const; + int StartAsyncBackupIfNeed(std::shared_ptr slaveStatus); + int RestoreInner(const std::string &destPath, const std::vector &newKey, + std::shared_ptr pool); + static int32_t RestoreWithPool(std::shared_ptr pool, const std::string &path); + static bool IsKnowledgeDataChange(const DistributedRdb::RdbChangedData &rdbChangedData); + static bool IsNotifyService(const DistributedRdb::RdbChangedData &rdbChangedData); static constexpr char SCHEME_RDB[] = "rdb://"; static constexpr uint32_t EXPANSION = 2; - static inline constexpr uint32_t INTERVAL = 10; + static inline constexpr uint32_t INTERVAL = 200; + static inline constexpr uint32_t MAX_RETURNING_ROWS = 1024; static inline constexpr uint32_t RETRY_INTERVAL = 5; // s static inline constexpr int32_t MAX_RETRY_TIMES = 5; static constexpr const char *ROW_ID = "ROWID"; bool isOpen_ = false; bool isReadOnly_ = false; - bool isMemoryRdb_; - std::atomic hasRegisterDataChange_ = false; + bool isMemoryRdb_ = false; + bool isUseReplicaDb_ = false; uint32_t rebuild_ = RebuiltType::NONE; - SlaveStatus slaveStatus_ = SlaveStatus::UNDEFINED; + int32_t initStatus_ = -1; + const std::shared_ptr slaveStatus_ = std::make_shared(SlaveStatus::UNDEFINED); int64_t vSchema_ = 0; std::atomic newTrxId_ = 1; const RdbStoreConfig config_; @@ -257,15 +273,19 @@ private: mutable std::shared_mutex rwMutex_; mutable std::shared_mutex poolMutex_; std::mutex mutex_; + std::mutex initMutex_; std::shared_ptr connectionPool_ = nullptr; std::shared_ptr delayNotifier_ = nullptr; std::shared_ptr cloudInfo_ = std::make_shared(); + RdbObsManager obsManger_; std::map>> localObservers_; - std::map>> localSharedObservers_; std::list> localDetailObservers_; ConcurrentMap attachedInfo_; ConcurrentMap> trxConnMap_ = {}; std::list> transactions_; + std::mutex helperMutex_; + std::shared_ptr knowledgeSchemaHelper_; + std::atomic isKnowledgeSchemaReady_{false}; }; } // namespace OHOS::NativeRdb #endif diff --git a/relational_store/frameworks/native/rdb/include/rdb_store_manager.h b/relational_store/frameworks/native/rdb/include/rdb_store_manager.h index 2fecfd58..58c3a68c 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_store_manager.h +++ b/relational_store/frameworks/native/rdb/include/rdb_store_manager.h @@ -37,30 +37,32 @@ public: std::shared_ptr GetRdbStore( const RdbStoreConfig &config, int &errCode, int version, RdbOpenCallback &openCallback); void Clear(); + void Init(); + bool Destroy(); bool Remove(const std::string &path, bool shouldClose); bool Delete(const RdbStoreConfig &config, bool shouldClose); - int SetSecurityLabel(const RdbStoreConfig &config); private: using Param = DistributedRdb::RdbSyncerParam; using Info = DistributedRdb::RdbDebugInfo; using DebugInfos = std::map; using DfxInfo = DistributedRdb::RdbDfxInfo; - int ProcessOpenCallback(RdbStore &rdbStore, int version, RdbOpenCallback &openCallback); bool IsConfigInvalidChanged(const std::string &path, RdbStoreConfig &config); int32_t GetParamFromService(DistributedRdb::RdbSyncerParam ¶m); - static bool IsPermitted(const DistributedRdb::RdbSyncerParam ¶m); - static int32_t CheckConfig(const RdbStoreConfig &config); + bool IsPermitted(const DistributedRdb::RdbSyncerParam ¶m, const std::string &path); + int32_t CheckConfig(const RdbStoreConfig &config, const std::string &path); static Param GetSyncParam(const RdbStoreConfig &config); static int32_t Collector(const RdbStoreConfig &config, DebugInfos &debugInfos, DfxInfo &dfxInfo); - std::shared_ptr GetStoreFromCache(const std::string &path); - std::pair> OpenStore(const RdbStoreConfig &config, const std::string &path); + std::shared_ptr GetStoreFromCache(const std::string &path, + const RdbStoreConfig &config, int &errCode); static constexpr uint32_t BUCKET_MAX_SIZE = 4; + static constexpr uint32_t PROMISEINFO_CACHE_SIZE = 32; static const bool regCollector_; std::mutex mutex_; std::map> storeCache_; LRUBucket configCache_; + LRUBucket promiseInfoCache_; }; } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/include/share_block.h b/relational_store/frameworks/native/rdb/include/share_block.h index 830344c9..2b7bbd98 100644 --- a/relational_store/frameworks/native/rdb/include/share_block.h +++ b/relational_store/frameworks/native/rdb/include/share_block.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -20,9 +20,10 @@ #include -#include "shared_block.h" - namespace OHOS { +namespace AppDataFwk { +class SharedBlock; +} namespace NativeRdb { #ifdef __cplusplus extern "C" { diff --git a/relational_store/frameworks/native/rdb/include/sqlite_connection.h b/relational_store/frameworks/native/rdb/include/sqlite_connection.h index b1ab71ef..07b808a0 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_connection.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_connection.h @@ -23,6 +23,7 @@ #include #include +#include "concurrent_map.h" #include "connection.h" #include "rdb_store_config.h" #include "sqlite3sym.h" @@ -43,35 +44,43 @@ public: static int32_t Delete(const RdbStoreConfig &config); static int32_t Delete(const std::string &path); static int32_t Repair(const RdbStoreConfig &config); - static int32_t Restore(const RdbStoreConfig &config, const std::string &srcPath, const std::string &destPath); static std::map Collect(const RdbStoreConfig &config); - SqliteConnection(const RdbStoreConfig &config, bool isWriteConnection); + static int32_t CheckReplicaIntegrity(const RdbStoreConfig &config); + static int32_t ClientCleanUp(); + static int32_t OpenSSLCleanUp(); + SqliteConnection(const RdbStoreConfig &config, bool isWriteConnection, bool isSlave = false); ~SqliteConnection(); int32_t VerifyAndRegisterHook(const RdbStoreConfig &config) override; int TryCheckPoint(bool timeout) override; int LimitWalSize() override; int ConfigLocale(const std::string &localeStr) override; int CleanDirtyData(const std::string &table, uint64_t cursor) override; - int ReSetKey(const RdbStoreConfig &config) override; + int ResetKey(const RdbStoreConfig &config) override; int32_t GetJournalMode() override; std::pair CreateStatement(const std::string &sql, SConn conn) override; + std::pair CreateReplicaStatement(const std::string &sql, SConn conn) override; + int CheckReplicaForRestore() override; + int32_t Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) override; bool IsWriter() const override; int SubscribeTableChanges(const Notifier ¬ifier) override; int GetMaxVariable() const override; int32_t GetDBType() const override; - int32_t ClearCache() override; + int32_t ClearCache(bool isForceClear = false) override; int32_t Subscribe(const std::shared_ptr &observer) override; int32_t Unsubscribe(const std::shared_ptr &observer) override; int32_t Backup(const std::string &databasePath, const std::vector &destEncryptKey, bool isAsync, - SlaveStatus &slaveStatus) override; + std::shared_ptr slaveStatus, bool verifyDb = true) override; int32_t Restore(const std::string &databasePath, const std::vector &destEncryptKey, - SlaveStatus &slaveStatus) override; - ExchangeStrategy GenerateExchangeStrategy(const SlaveStatus &status) override; - + std::shared_ptr slaveStatus) override; + ExchangeStrategy GenerateExchangeStrategy(std::shared_ptr status, bool isRelpay) override; + int SetKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema &schema) override; + int CleanDirtyLog(const std::string &table, uint64_t cursor) override; + static bool IsSupportBinlog(const RdbStoreConfig &config); protected: std::pair ExecuteForValue( const std::string &sql, const std::vector &bindArgs = std::vector()); int ExecuteSql(const std::string &sql, const std::vector &bindArgs = std::vector()); + int RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) override; private: struct Suffix { @@ -91,17 +100,19 @@ private: int SetEncryptKey(const std::vector &key, const RdbStoreConfig &config); int SetServiceKey(const RdbStoreConfig &config, int32_t errCode); int SetEncryptAgo(const RdbStoreConfig &config); + int SetEncryptAgo(const RdbStoreConfig::CryptoParam &cryptoParam); int SetJournalMode(const RdbStoreConfig &config); int SetAutoCheckpoint(const RdbStoreConfig &config); int SetWalFile(const RdbStoreConfig &config); int SetWalSyncMode(const std::string &syncMode); int SetTokenizer(const RdbStoreConfig &config); + int SetBinlog(); void LimitPermission(const RdbStoreConfig &config, const std::string &dbPath) const; int SetPersistWal(const RdbStoreConfig &config); int SetBusyTimeout(int timeout); - int SetCrcCheck(const RdbStoreConfig &config); void SetDwrEnable(const RdbStoreConfig &config); + void SetIsSupportBinlog(bool isSupport); int RegDefaultFunctions(sqlite3 *dbHandle); int SetCustomFunctions(const RdbStoreConfig &config); @@ -114,36 +125,55 @@ private: RdbStoreConfig GetSlaveRdbStoreConfig(const RdbStoreConfig &rdbConfig); std::pair> CreateSlaveConnection( const RdbStoreConfig &config, SlaveOpenPolicy slaveOpenPolicy); - int ExchangeSlaverToMaster(bool isRestore, bool verifyDb, SlaveStatus &status); + int ExchangeSlaverToMaster(bool isRestore, bool verifyDb, std::shared_ptr curStatus); int ExchangeVerify(bool isRestore); - int SqliteNativeBackup(bool isRestore, SlaveStatus &curStatus); + int SqliteBackupStep(bool isRestore, sqlite3_backup *pBackup, std::shared_ptr curStatus); + int SqliteNativeBackup(bool isRestore, std::shared_ptr curStatus); int VeritySlaveIntegrity(); bool IsDbVersionBelowSlave(); int RegisterStoreObs(); int RegisterClientObs(); int RegisterHookIfNecessary(); + std::pair CreateStatementInner(const std::string &sql, SConn conn, + sqlite3 *db, bool isFromReplica); + void ReplayBinlog(const RdbStoreConfig &config); + ExchangeStrategy CompareWithSlave(int64_t mCount, int64_t mIdxCount); static std::pair> InnerCreate( - const RdbStoreConfig &config, bool isWrite); - static int CopyDb(const RdbStoreConfig &config, const std::string &srcPath, const std::string &destPath); + const RdbStoreConfig &config, bool isWrite, bool isReusableReplica = false); + static void BinlogOnErrFunc(void *pCtx, int errNo, char *errMsg, const char *dbPath); + static void BinlogCloseHandle(sqlite3 *dbHandle); + static int CheckPathExist(const std::string &dbPath); + static int BinlogOpenHandle(const std::string &dbPath, sqlite3 *&dbHandle, bool isMemoryRdb); + static void BinlogSetConfig(sqlite3 *dbHandle); + static void BinlogOnFullFunc(void *pCtx, unsigned short currentCount, const char *dbPath); + static void ReplayBinlog(const std::string &dbPath, + std::shared_ptr slaveConn, bool isNeedClean); + static std::string GetBinlogFolderPath(const std::string &dbPath); + static constexpr const char *BINLOG_FOLDER_SUFFIX = "_binlog"; static constexpr SqliteConnection::Suffix FILE_SUFFIXES[] = { { "", "DB" }, { "-shm", "SHM" }, { "-wal", "WAL" }, { "-dwr", "DWR" }, { "-journal", "JOURNAL" }, { "-slaveFailure", nullptr }, { "-syncInterrupt", nullptr }, - { ".corruptedflg", nullptr }, { "-compare", nullptr } }; + { ".corruptedflg", nullptr }, { "-compare", nullptr }, { "-walcompress", nullptr }, + { "-journalcompress", nullptr }, { "-shmcompress", nullptr } }; static constexpr int CHECKPOINT_TIME = 500; static constexpr int DEFAULT_BUSY_TIMEOUT_MS = 2000; static constexpr int BACKUP_PAGES_PRE_STEP = 12800; // 1024 * 4 * 12800 == 50m static constexpr int BACKUP_PRE_WAIT_TIME = 10; + static constexpr int RESTORE_PRE_WAIT_TIME = 100; static constexpr ssize_t SLAVE_WAL_SIZE_LIMIT = 2147483647; // 2147483647 = 2g - 1 static constexpr ssize_t SLAVE_INTEGRITY_CHECK_LIMIT = 524288000; // 524288000 == 1024 * 1024 * 500 + static constexpr unsigned short BINLOG_FILE_NUMS_LIMIT = 2; + static constexpr uint32_t BINLOG_FILE_SIZE_LIMIT = 1024 * 1024 * 4; // 4194304 == 1024 * 1024 * 4 static constexpr uint32_t NO_ITER = 0; static constexpr uint32_t DB_INDEX = 0; static constexpr uint32_t WAL_INDEX = 2; - static constexpr uint32_t ITER_V1 = 5000; - static constexpr uint32_t SQLITE_CKSUMVFS_RESERVE_BYTES = 8; static const int32_t regCreator_; static const int32_t regRepairer_; static const int32_t regDeleter_; static const int32_t regCollector_; - static const int32_t regRestorer_; + static const int32_t regReplicaChecker_; + static const int32_t regDbClientCleaner_; + static const int32_t regOpenSSLCleaner_; + static ConcurrentMap> reusableReplicas_; using EventHandle = int (SqliteConnection::*)(); struct HandleInfo { RegisterType Type; @@ -159,6 +189,9 @@ private: bool isWriter_; bool isReadOnly_; bool isConfigured_ = false; + bool isSupportBinlog_ = false; + bool isSlave_ = false; + bool isReplay_ = false; JournalMode mode_ = JournalMode::MODE_WAL; int maxVariableNumber_; std::shared_ptr slaveConnection_; diff --git a/relational_store/frameworks/native/rdb/include/sqlite_errno.h b/relational_store/frameworks/native/rdb/include/sqlite_errno.h index 8e643e53..6ecde0d1 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_errno.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_errno.h @@ -27,10 +27,14 @@ #endif namespace OHOS { namespace NativeRdb { -const static std::map ERROR_CODE_MAPPINT_TABLE = { +struct SQLiteErrorCode { + int sqliteError; + int rdbError; +}; +static constexpr SQLiteErrorCode SQLiteErrorCodes[] = { { SQLITE_ERROR, E_SQLITE_ERROR }, - { SQLITE_ABORT, E_SQLITE_ABORT }, { SQLITE_PERM, E_SQLITE_PERM }, + { SQLITE_ABORT, E_SQLITE_ABORT }, { SQLITE_BUSY, E_SQLITE_BUSY }, { SQLITE_LOCKED, E_SQLITE_LOCKED }, { SQLITE_NOMEM, E_SQLITE_NOMEM }, @@ -38,26 +42,49 @@ const static std::map ERROR_CODE_MAPPINT_TABLE = { { SQLITE_IOERR, E_SQLITE_IOERR }, { SQLITE_CORRUPT, E_SQLITE_CORRUPT }, { SQLITE_FULL, E_SQLITE_FULL }, - { SQLITE_SCHEMA, E_SQLITE_SCHEMA }, { SQLITE_CANTOPEN, E_SQLITE_CANTOPEN }, + { SQLITE_SCHEMA, E_SQLITE_SCHEMA }, { SQLITE_TOOBIG, E_SQLITE_TOOBIG }, { SQLITE_CONSTRAINT, E_SQLITE_CONSTRAINT }, { SQLITE_MISMATCH, E_SQLITE_MISMATCH }, { SQLITE_MISUSE, E_SQLITE_MISUSE }, { SQLITE_NOTADB, E_SQLITE_CORRUPT }, - { SQLITE_DONE, E_NO_MORE_ROWS }, - { SQLITE_ROW, E_OK }, { SQLITE_META_RECOVERED, E_SQLITE_META_RECOVERED }, + { SQLITE_ROW, E_OK }, + { SQLITE_DONE, E_NO_MORE_ROWS }, }; + +static constexpr bool IsIncreasing() +{ + for (size_t i = 1; i < sizeof(SQLiteErrorCodes) / sizeof(SQLiteErrorCode); i++) { + if (SQLiteErrorCodes[i].sqliteError <= SQLiteErrorCodes[i - 1].sqliteError) { + return false; + } + } + return true; +} +// JS_ERROR_CODE_MSGS must ensure increment +static_assert(IsIncreasing()); + +static int GetRdbErrorCode(int32_t errorCode) +{ + auto jsErrorCode = SQLiteErrorCode{ errorCode, -errorCode }; + auto iter = std::lower_bound(SQLiteErrorCodes, + SQLiteErrorCodes + sizeof(SQLiteErrorCodes) / sizeof(SQLiteErrorCodes[0]), jsErrorCode, + [](const SQLiteErrorCode &jsErrorCode1, const SQLiteErrorCode &jsErrorCode2) { + return jsErrorCode1.sqliteError < jsErrorCode2.sqliteError; + }); + if (iter < SQLiteErrorCodes + sizeof(SQLiteErrorCodes) / sizeof(SQLiteErrorCodes[0]) && + iter->sqliteError == errorCode) { + return iter->rdbError; + } + return -errorCode; +} class SQLiteError { public: static int ErrNo(int sqliteErr) { - auto iter = ERROR_CODE_MAPPINT_TABLE.find(sqliteErr); - if (iter != ERROR_CODE_MAPPINT_TABLE.end()) { - return iter->second; - } - return -sqliteErr; + return GetRdbErrorCode(sqliteErr); } }; } // namespace NativeRdb diff --git a/relational_store/frameworks/native/rdb/include/sqlite_sql_builder.h b/relational_store/frameworks/native/rdb/include/sqlite_sql_builder.h index d4c636a0..2a2f92fb 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_sql_builder.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_sql_builder.h @@ -30,25 +30,21 @@ public: using BatchRefSqls = std::vector>>>; SqliteSqlBuilder(); ~SqliteSqlBuilder(); - static std::string BuildUpdateString(const ValuesBucket &values, const std::string &tableName, - const std::vector &whereArgs, const std::string &index, const std::string &whereClause, - const std::string &group, const std::string &order, int limit, int offset, std::vector &bindArgs, - ConflictResolution conflictResolution); static int BuildQueryString(bool distinct, const std::string &table, const std::string &joinClause, const std::vector &columns, const std::string &whereClause, const std::string &groupBy, const std::string &indexName, const std::string &orderBy, const int &limit, const int &offset, std::string &outSql); - static std::string BuildSqlStringFromPredicates(const std::string &index, const std::string &joinClause, - const std::string &whereClause, const std::string &group, const std::string &order, int limit, int offset); static std::string BuildQueryString(const AbsRdbPredicates &predicates, const std::vector &columns); static std::string BuildCountString(const AbsRdbPredicates &predicates); - static std::string BuildSqlStringFromPredicates(const AbsPredicates &predicates); + static std::string BuildClauseFromPredicates(const AbsRdbPredicates &predicates); static std::string BuildCursorQueryString(const AbsRdbPredicates &predicates, const std::vector &columns, const std::string &logTable, const std::pair &queryStatus); static std::string BuildLockRowQueryString( const AbsRdbPredicates &predicates, const std::vector &columns, const std::string &logTable); static std::string GetSqlArgs(size_t size); + static void AppendReturning(std::string &sql, const std::vector &fields); + static BatchRefSqls GenerateSqls(const std::string &table, const ValuesBuckets &buckets, int limit, ConflictResolution resolution = ConflictResolution::ON_CONFLICT_REPLACE); static void UpdateAssetStatus(const ValueObject &value, int32_t status); @@ -60,12 +56,13 @@ private: std::string &builder, const std::string &name, const std::string &clause, const std::string &table = ""); static void AppendColumns( std::string &builder, const std::vector &columns, const std::string &table = ""); - + static void AppendLimitAndOffset(std::string &builder, int limit, int offset); + static std::string GetSelectClause(const std::vector &columns, bool IsDistinct, + const std::string &ast, const std::string &table = ""); static constexpr const char *SHARING_RESOURCE = "sharing_resource"; static constexpr uint32_t EXPANSION = 2; static ValueObject nullObject_; static std::reference_wrapper nullRef_; - static std::string HandleTable(const std::string &tableName); }; } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/include/sqlite_statement.h b/relational_store/frameworks/native/rdb/include/sqlite_statement.h index e66eee14..d230ebf6 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_statement.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_statement.h @@ -36,7 +36,7 @@ public: static constexpr int COLUMN_TYPE_FLOATS = 1002; static constexpr int COLUMN_TYPE_BIGINT = 1003; - SqliteStatement(); + SqliteStatement(const RdbStoreConfig *config = nullptr); ~SqliteStatement(); int Prepare(const std::string &sql) override; int Bind(const std::vector &args) override; @@ -54,6 +54,7 @@ public: std::pair GetColumnType(int index) const override; std::pair GetSize(int index) const override; std::pair GetColumn(int index) const override; + std::pair> GetRows(uint32_t maxCount) override; bool ReadOnly() const override; bool SupportBlockInfo() const override; int32_t FillBlockInfo(SharedBlockInfo *info) const override; @@ -94,6 +95,7 @@ private: void TableReport(const std::string &errMsg, const std::string &bundleName, ErrMsgState state); void ColumnReport(const std::string &errMsg, const std::string &bundleName, ErrMsgState state); void HandleErrMsg(const std::string &errMsg, const std::string &dbPath, const std::string &bundleName); + void TryNotifyErrorLog(const int &errCode, sqlite3 *dbHandle, const std::string &sql); static constexpr uint32_t BUFFER_LEN = 16; diff --git a/relational_store/frameworks/native/rdb/include/sqlite_utils.h b/relational_store/frameworks/native/rdb/include/sqlite_utils.h index cb25c478..8467b59b 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_utils.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_utils.h @@ -51,9 +51,12 @@ public: static constexpr int DISABLE_LOAD_EXTENSION = 0; static constexpr int ENABLE_LOAD_EXTENSION = 1; static constexpr int MAX_LOAD_EXTENSION_COUNT = 16; + static constexpr int PATH_DEPTH = 3; static constexpr const char *REP = "#_"; static constexpr const char *SLAVE_FAILURE = "-slaveFailure"; static constexpr const char *SLAVE_INTERRUPT = "-syncInterrupt"; + static constexpr const char *SLAVE_RESTORE = "-restoring"; + static constexpr ssize_t SLAVE_ASYNC_REPAIR_CHECK_LIMIT = 1073741824; // 1073741824 = 1024 * 1024 * 1024 static int GetSqlStatementType(const std::string &sql); static bool IsSupportSqlForExecute(int sqlType); @@ -61,16 +64,23 @@ public: static bool IsSpecial(int sqlType); static const char *GetConflictClause(int conflictResolution); static std::string StrToUpper(const std::string &s); - static void Replace(std::string &src, const std::string &rep, const std::string &dst); + static std::string Replace(const std::string &src, const std::string &rep, const std::string &dst); static bool DeleteFile(const std::string &filePath); static bool RenameFile(const std::string &srcFile, const std::string &destFile); static bool CopyFile(const std::string &srcFile, const std::string &destFile); - static std::string Anonymous(const std::string &srcFile); + static size_t DeleteFolder(const std::string &folderPath); + API_EXPORT static std::string Anonymous(const std::string &srcFile); + static std::string SqlAnonymous(const std::string &sql); + static std::string GetArea(const std::string &srcFile); static ssize_t GetFileSize(const std::string &fileName); static bool IsSlaveDbName(const std::string &fileName); static std::string GetSlavePath(const std::string &name); static int SetSlaveInvalid(const std::string &dbPath); static int SetSlaveInterrupted(const std::string &dbPath); + static int SetSlaveRestoring(const std::string &dbPath, bool isRestore = true); + static bool IsSlaveRestoring(const std::string &dbPath); + static ssize_t GetDecompressedSize(const std::string &dbPath); + static bool IsSlaveLarge(const std::string &dbPath); static bool IsSlaveInvalid(const std::string &dbPath); static bool IsSlaveInterrupted(const std::string &dbPath); static void SetSlaveValid(const std::string &dbPath); @@ -90,6 +100,8 @@ public: static std::string FormatDebugInfo(const std::map &debugs, const std::string &header); static std::string FormatDebugInfoBrief(const std::map &debugs, const std::string &header); static std::string FormatDfxInfo(const DfxInfo &dfxInfo); + static std::string GetParentModes(const std::string &path, int pathDepth = PATH_DEPTH); + static std::string GetFileStatInfo(const DebugInfo &debugInfo); private: struct SqlType { @@ -118,9 +130,11 @@ private: static constexpr const char *ON_CONFLICT_CLAUSE[CONFLICT_CLAUSE_COUNT] = { "", " OR ROLLBACK", " OR ABORT", " OR FAIL", " OR IGNORE", " OR REPLACE" }; - static std::string GetAnonymousName(const std::string& fileName); - static std::string AnonyDigits(const std::string& fileName); - static std::string GetFileStatInfo(const DebugInfo &debugInfo); + static std::string GetAnonymousName(const std::string &fileName); + static std::string AnonymousDigits(const std::string &digits); + static bool IsKeyword(const std::string& word); + static std::string GetModeInfo(uint32_t st_mode); + static int GetPageCountCallback(void *data, int argc, char **argv, char **azColName); }; } // namespace NativeRdb diff --git a/relational_store/frameworks/native/rdb/include/statement.h b/relational_store/frameworks/native/rdb/include/statement.h index d766fb6f..199cb7a3 100644 --- a/relational_store/frameworks/native/rdb/include/statement.h +++ b/relational_store/frameworks/native/rdb/include/statement.h @@ -21,6 +21,7 @@ #include #include "value_object.h" +#include "values_bucket.h" namespace OHOS::NativeRdb { struct SharedBlockInfo; class Statement { @@ -50,6 +51,7 @@ public: virtual std::pair GetColumnType(int32_t index) const = 0; virtual std::pair GetSize(int32_t index) const = 0; virtual std::pair GetColumn(int32_t index) const = 0; + virtual std::pair> GetRows(uint32_t maxCount = 1024) = 0; virtual bool ReadOnly() const = 0; virtual bool SupportBlockInfo() const = 0; virtual int32_t FillBlockInfo(SharedBlockInfo *info) const = 0; diff --git a/relational_store/frameworks/native/rdb/include/string_utils.h b/relational_store/frameworks/native/rdb/include/string_utils.h index b231fed6..1322af55 100644 --- a/relational_store/frameworks/native/rdb/include/string_utils.h +++ b/relational_store/frameworks/native/rdb/include/string_utils.h @@ -31,6 +31,7 @@ public: static std::string ExtractFilePath(const std::string &fileFullName); static std::string ExtractFileName(const std::string &fileFullName); static std::string TruncateAfterFirstParen(const std::string& str); + static std::string GetParentPath(const std::string &path); static bool IsEmpty(std::string source) { return (source.empty()); diff --git a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_transaction.h b/relational_store/frameworks/native/rdb/include/suspender.h similarity index 33% rename from relational_store/frameworks/js/napi/graphstore/include/napi_gdb_transaction.h rename to relational_store/frameworks/native/rdb/include/suspender.h index 98565623..0db4df5c 100644 --- a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_transaction.h +++ b/relational_store/frameworks/native/rdb/include/suspender.h @@ -12,37 +12,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_TRANSACTION_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_GDB_TRANSACTION_H -#include -#include -#include -#include - -#include "gdb_transaction.h" -#include "js_proxy.h" -#include "js_uv_queue.h" -#include "napi/native_api.h" -#include "napi/native_common.h" -#include "napi/native_node_api.h" - -namespace OHOS::GraphStoreJsKit { -using Transaction = DistributedDataAip::Transaction; -class GdbTransactionProxy final : public GraphStoreJsKit::JSProxy { +#ifndef OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_SUSPENDER_H +#define OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_SUSPENDER_H +namespace OHOS { +namespace NativeRdb { +class Suspender { public: - GdbTransactionProxy() = default; - ~GdbTransactionProxy(); - explicit GdbTransactionProxy(std::shared_ptr gdbTransaction); - static void Init(napi_env env, napi_value exports); - static napi_value NewInstance(napi_env env, std::shared_ptr value); + enum Flag { + SQL_STATISTIC = 0x1, + SQL_LOG = 0x2, + }; + Suspender(Flag flag); + ~Suspender(); private: - static napi_value Initialize(napi_env env, napi_callback_info info); - static napi_value Read(napi_env env, napi_callback_info info); - static napi_value Write(napi_env env, napi_callback_info info); - static napi_value Commit(napi_env env, napi_callback_info info); - static napi_value Rollback(napi_env env, napi_callback_info info); + Flag flag_; }; -} // namespace OHOS::GraphStoreJsKit -#endif \ No newline at end of file +} // namespace DistributedRdb +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_SUSPENDER_H diff --git a/relational_store/frameworks/native/rdb/include/trans_db.h b/relational_store/frameworks/native/rdb/include/trans_db.h index de97806c..4c1da0b9 100644 --- a/relational_store/frameworks/native/rdb/include/trans_db.h +++ b/relational_store/frameworks/native/rdb/include/trans_db.h @@ -23,28 +23,34 @@ namespace OHOS::NativeRdb { class TransDB : public RdbStore { public: - TransDB(std::shared_ptr conn, const std::string &name); + TransDB(std::shared_ptr conn, const std::string &path); std::pair Insert(const std::string &table, const Row &row, Resolution resolution) override; std::pair BatchInsert(const std::string &table, const RefRows &rows) override; - std::pair BatchInsertWithConflictResolution( - const std::string &table, const ValuesBuckets &rows, Resolution resolution) override; - std::pair Update(const std::string &table, const Row &row, const std::string &where, const Values &args, - Resolution resolution) override; - int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) override; + std::pair BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution) override; + std::pair Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) override; + std::pair Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) override; std::shared_ptr QuerySql(const std::string &sql, const Values &args) override; std::shared_ptr QueryByStep(const std::string &sql, const Values &args, bool preCount) override; std::pair Execute(const std::string &sql, const Values &args, int64_t trxId) override; + std::pair ExecuteExt(const std::string &sql, const Values &args) override; int GetVersion(int &version) override; int SetVersion(int version) override; int Sync(const SyncOption &option, const std::vector &tables, const AsyncDetail &async) override; private: std::pair> GetStatement(const std::string &sql) const; + void HandleSchemaDDL(std::shared_ptr statement); + static inline constexpr uint32_t MAX_RETURNING_ROWS = 1024; + static Results GenerateResult(int32_t code, std::shared_ptr statement, bool isDML = true); + static std::shared_ptr GetValues(std::shared_ptr statement); int32_t maxArgs_ = 0; int64_t vSchema_ = 0; std::weak_ptr conn_; - std::string name_; + std::string path_; }; } // namespace OHOS::NativeRdb #endif // NATIVE_RDB_TRANS_DB_H \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/include/transaction_impl.h b/relational_store/frameworks/native/rdb/include/transaction_impl.h index 954e3e6a..330fd3d6 100644 --- a/relational_store/frameworks/native/rdb/include/transaction_impl.h +++ b/relational_store/frameworks/native/rdb/include/transaction_impl.h @@ -26,7 +26,7 @@ namespace OHOS::NativeRdb { class RdbStore; class TransactionImpl : public Transaction { public: - TransactionImpl(std::shared_ptr connection, const std::string &name); + TransactionImpl(std::shared_ptr connection, const std::string &path); ~TransactionImpl() override; int32_t Commit() override; @@ -36,22 +36,19 @@ public: std::pair Insert(const std::string &table, const Row &row, Resolution resolution) override; std::pair BatchInsert(const std::string &table, const Rows &rows) override; std::pair BatchInsert(const std::string &table, const RefRows &rows) override; - std::pair BatchInsertWithConflictResolution( - const std::string &table, const RefRows &rows, Resolution resolution) override; - std::pair Update(const std::string &table, const Row &row, const std::string &where, const Values &args, - Resolution resolution) override; - std::pair Update( - const Row &row, const AbsRdbPredicates &predicates, Resolution resolution) override; - std::pair Delete( - const std::string &table, const std::string &whereClause, const Values &args) override; - std::pair Delete(const AbsRdbPredicates &predicates) override; + std::pair BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution) override; + std::pair Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) override; + std::pair Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) override; std::shared_ptr QueryByStep(const std::string &sql, const Values &args, bool preCount) override; std::shared_ptr QueryByStep(const AbsRdbPredicates &predicates, const Fields &columns, bool preCount) override; std::pair Execute(const std::string &sql, const Values &args) override; - + std::pair ExecuteExt(const std::string &sql, const Values &args) override; static std::pair> Create( - int32_t type, std::shared_ptr connection, const std::string &name); + int32_t type, std::shared_ptr connection, const std::string &path); private: static std::string GetBeginSql(int32_t type); @@ -60,7 +57,8 @@ private: std::shared_ptr GetStore(); void AddResultSet(std::weak_ptr resultSet); - std::string name_; + std::string path_; + uint32_t seqId_ = 0; std::recursive_mutex mutex_; std::shared_ptr store_; std::shared_ptr connection_; diff --git a/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h b/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h index 6ed5797e..25856589 100644 --- a/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h +++ b/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h @@ -27,6 +27,8 @@ #include "abs_shared_result_set.h" #include "concurrent_map.h" #include "connection_pool.h" +#include "knowledge_schema_helper.h" +#include "rdb_open_callback.h" #include "rdb_store.h" #include "rdb_store_config.h" #include "sqlite_statement.h" @@ -36,19 +38,21 @@ class DelayNotify; class RdbStoreImpl : public RdbStore { public: RdbStoreImpl(const RdbStoreConfig &config); - RdbStoreImpl(const RdbStoreConfig &config, int &errCode); ~RdbStoreImpl() override; + int32_t Init(int version, RdbOpenCallback &openCallback); std::pair Insert(const std::string &table, const Row &row, Resolution resolution) override; std::pair BatchInsert(const std::string &table, const ValuesBuckets &rows) override; - std::pair BatchInsertWithConflictResolution( - const std::string &table, const ValuesBuckets &rows, Resolution resolution) override; - std::pair Update(const std::string &table, const Row &row, const std::string &where, const Values &args, - Resolution resolution) override; - int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) override; + std::pair BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution) override; + std::pair Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) override; + std::pair Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) override; std::shared_ptr QuerySql(const std::string &sql, const Values &args) override; std::shared_ptr QueryByStep(const std::string &sql, const Values &args, bool preCount) override; int ExecuteSql(const std::string &sql, const Values &args) override; std::pair Execute(const std::string &sql, const Values &args, int64_t trxId) override; + std::pair ExecuteExt(const std::string &sql, const Values &args) override; int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const Values &args) override; int ExecuteAndGetString(std::string &outValue, const std::string &sql, const Values &args) override; int ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, const Values &args) override; @@ -68,7 +72,7 @@ public: bool IsMemoryRdb() const override; bool IsHoldingConnection() override; bool IsSlaveDiffFromMaster() const override; - int Backup(const std::string &databasePath, const std::vector &encryptKey) override; + int Backup(const std::string &databasePath, const std::vector &encryptKey, bool verifyDb) override; int Restore(const std::string &backupPath, const std::vector &newKey) override; int Count(int64_t &outValue, const AbsRdbPredicates &predicates) override; int GetRebuilt(RebuiltType &rebuilt) override; @@ -79,8 +83,12 @@ public: int32_t GetBackupStatus() const override; int32_t GetDbType() const override; std::pair> CreateTransaction(int32_t type) override; + int CleanDirtyLog(const std::string &table, uint64_t cursor) override; + int InitKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema &schema) override; + int RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) override; + const RdbStoreConfig &GetConfig(); - int ConfigLocale(const std::string &localeStr); + int ConfigLocale(const std::string &localeStr) override; std::string GetName(); std::string GetFileType(); int32_t ExchangeSlaverToMaster(); @@ -104,19 +112,24 @@ private: }; int InnerOpen(); + int32_t ProcessOpenCallback(int version, RdbOpenCallback &openCallback); + int32_t CreatePool(bool &created); void InitReportFunc(const RdbParam ¶m); void InitSyncerParam(const RdbStoreConfig &config, bool created); + int32_t SetSecurityLabel(const RdbStoreConfig &config); int ExecuteByTrxId(const std::string &sql, int64_t trxId, bool closeConnAfterExecute = false, const std::vector &bindArgs = {}); + std::pair HandleResults( + std::shared_ptr &&statement, const std::string &sql, int32_t code, int sqlType); std::pair HandleDifferentSqlTypes( - std::shared_ptr statement, const std::string &sql, const ValueObject &object, int sqlType); + std::shared_ptr &&statement, const std::string &sql, int32_t code, int sqlType); int CheckAttach(const std::string &sql); std::pair BeginExecuteSql(const std::string &sql); int GetDataBasePath(const std::string &databasePath, std::string &backupFilePath); void DoCloudSync(const std::string &table); int InnerBackup(const std::string& databasePath, - const std::vector &destEncryptKey = std::vector()); - std::pair> CreateWritableConn(); + const std::vector &destEncryptKey = std::vector(), bool verifyDb = true); + static std::pair> CreateWritableConn(const RdbStoreConfig &config); std::vector CreateBackupBindArgs( const std::string &databasePath, const std::vector &destEncryptKey); std::pair GetStatement(const std::string &sql, std::shared_ptr conn) const; @@ -129,27 +142,45 @@ private: int GetSlaveName(const std::string &dbName, std::string &backupFilePath); bool TryGetMasterSlaveBackupPath(const std::string &srcPath, std::string &destPath, bool isRestore = false); void NotifyDataChange(); + void TryDump(int32_t code, const char *dumpHeader); int GetDestPath(const std::string &backupPath, std::string &destPath); std::shared_ptr GetPool() const; int HandleCloudSyncAfterSetDistributedTables( const std::vector &tables, const DistributedRdb::DistributedConfig &distributedConfig); std::pair> GetConn(bool isRead); - void HandleSchemaDDL(std::shared_ptr statement, - std::shared_ptr pool, const std::string &sql, int32_t &errCode); + std::pair ExecuteForRow(const std::string &sql, const Values &args); + static Results GenerateResult(int32_t code, std::shared_ptr statement, bool isDML = true); + static std::shared_ptr GetValues(std::shared_ptr statement); + int32_t HandleSchemaDDL(std::shared_ptr &&statement, const std::string &sql); void BatchInsertArgsDfx(int argsSize); + void SetKnowledgeSchema(); + std::shared_ptr GetKnowledgeSchemaHelper(); + void SwitchOver(bool isUseReplicaDb); + bool TryAsyncRepair(); + bool IsUseAsyncRestore(const std::string &newPath, const std::string &backupPath); + int StartAsyncRestore(std::shared_ptr pool) const; + int StartAsyncBackupIfNeed(std::shared_ptr slaveStatus); + int RestoreInner(const std::string &destPath, const std::vector &newKey, + std::shared_ptr pool); + static int32_t RestoreWithPool(std::shared_ptr pool, const std::string &path); + static bool IsKnowledgeDataChange(const DistributedRdb::RdbChangedData &rdbChangedData); + static bool IsNotifyService(const DistributedRdb::RdbChangedData &rdbChangedData); static constexpr char SCHEME_RDB[] = "rdb://"; static constexpr uint32_t EXPANSION = 2; static inline constexpr uint32_t INTERVAL = 10; + static inline constexpr uint32_t MAX_RETURNING_ROWS = 1024; static inline constexpr uint32_t RETRY_INTERVAL = 5; // s static inline constexpr int32_t MAX_RETRY_TIMES = 5; static constexpr const char *ROW_ID = "ROWID"; bool isOpen_ = false; bool isReadOnly_ = false; - bool isMemoryRdb_; + bool isMemoryRdb_ = false; + bool isUseReplicaDb_ = false; uint32_t rebuild_ = RebuiltType::NONE; - SlaveStatus slaveStatus_ = SlaveStatus::UNDEFINED; + int32_t initStatus_ = -1; + const std::shared_ptr slaveStatus_ = std::make_shared(SlaveStatus::UNDEFINED); int64_t vSchema_ = 0; std::atomic newTrxId_ = 1; const RdbStoreConfig config_; @@ -161,12 +192,18 @@ private: std::string fileType_; mutable std::shared_mutex poolMutex_; std::mutex mutex_; + std::mutex initMutex_; std::shared_ptr connectionPool_ = nullptr; std::shared_ptr delayNotifier_ = nullptr; std::shared_ptr cloudInfo_ = std::make_shared(); ConcurrentMap attachedInfo_; ConcurrentMap> trxConnMap_ = {}; std::list> transactions_; + mutable std::mutex schemaMutex_; + std::shared_ptr knowledgeSchema_; + std::mutex helperMutex_; + std::shared_ptr knowledgeSchemaHelper_; + std::atomic isKnowledgeSchemaReady_{false}; }; } // namespace OHOS::NativeRdb #endif diff --git a/relational_store/frameworks/native/rdb/mock/include/task_executor.h b/relational_store/frameworks/native/rdb/mock/include/task_executor.h deleted file mode 100644 index 5f6426aa..00000000 --- a/relational_store/frameworks/native/rdb/mock/include/task_executor.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -* Copyright (c) 2023 Huawei Device Co., Ltd. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#ifndef DISTRIBUTED_NATIVE_RDB_TASK_EXECUTOR_H -#define DISTRIBUTED_NATIVE_RDB_TASK_EXECUTOR_H -#include -#include -#include -namespace OHOS { -class ExecutorPool { -public: - using TaskId = uint64_t; - using Task = std::function; - using Duration = std::chrono::steady_clock::duration; - static constexpr Duration INVALID_DURATION = std::chrono::milliseconds(0); - static constexpr TaskId INVALID_TASK_ID = static_cast(0l); - static constexpr uint64_t UNLIMITED_TIMES = std::numeric_limits::max(); - ExecutorPool(size_t max, size_t min) - { - } - ~ExecutorPool() - { - } - - TaskId Execute(Task task) - { - return INVALID_TASK_ID; - } - - TaskId Schedule(Duration delay, Task task) - { - return INVALID_TASK_ID; - } - - TaskId Schedule(Task task, Duration interval) - { - return INVALID_TASK_ID; - } - - TaskId Schedule(Task task, Duration delay, Duration interval) - { - return INVALID_TASK_ID; - } - - TaskId Schedule(Task task, Duration delay, Duration interval, uint64_t times) - { - return INVALID_TASK_ID; - } - - bool Remove(TaskId taskId, bool wait = false) - { - return true; - } - - TaskId Reset(TaskId taskId, Duration interval) - { - return INVALID_TASK_ID; - } -}; -namespace NativeRdb { -class TaskExecutor { -public: - using TaskId = ExecutorPool::TaskId; - using Task = std::function; - using Duration = std::chrono::steady_clock::duration; - static constexpr TaskId INVALID_TASK_ID = ExecutorPool::INVALID_TASK_ID; - - static TaskExecutor &GetInstance(); - std::shared_ptr GetExecutor(); - void SetExecutor(std::shared_ptr executor); - -private: - TaskExecutor(); - ~TaskExecutor(); - std::shared_ptr pool_; -}; -} // namespace NativeRdb -} // namespace OHOS -#endif // DISTRIBUTED_DATA_TASK_EXECUTOR_H diff --git a/relational_store/frameworks/native/rdb/mock/src/rdb_fault_hiview_reporter.cpp b/relational_store/frameworks/native/rdb/mock/src/rdb_fault_hiview_reporter.cpp index 2dc6a2b7..feca8507 100644 --- a/relational_store/frameworks/native/rdb/mock/src/rdb_fault_hiview_reporter.cpp +++ b/relational_store/frameworks/native/rdb/mock/src/rdb_fault_hiview_reporter.cpp @@ -47,6 +47,14 @@ void RdbFaultHiViewReporter::DeleteCorruptedFlag(const std::string &dbPath) (void)dbPath; } +void RdbFaultHiViewReporter::ReportRAGFault(const std::string &errMsg, const std::string &functionName, + const std::string &bundleName, const int faultType, const int errCode) +{ + (void)errMsg; + (void)functionName; + (void)bundleName; +} + RdbCorruptedEvent RdbFaultHiViewReporter::Create( const RdbStoreConfig &config, int32_t errCode, const std::string &appendix, bool needSyncParaFromSrv) { @@ -95,15 +103,6 @@ void RdbFaultEvent::Report() const { } -RdbEmptyBlobEvent::RdbEmptyBlobEvent(const std::string &bundleName) - : RdbFaultEvent("", 0, "", "") -{ -} - -void RdbEmptyBlobEvent::Report() const -{ -} - RdbFaultDbFileEvent::RdbFaultDbFileEvent(const std::string &faultType, int32_t errorCode, const RdbStoreConfig &config, const std::string &custLog, bool printDbInfo) : RdbFaultEvent(faultType, errorCode, "", custLog), config_(config) { diff --git a/relational_store/frameworks/native/rdb/mock/src/task_executor.cpp b/relational_store/frameworks/native/rdb/mock/src/task_executor.cpp index a0139a30..f7ea6e49 100644 --- a/relational_store/frameworks/native/rdb/mock/src/task_executor.cpp +++ b/relational_store/frameworks/native/rdb/mock/src/task_executor.cpp @@ -16,7 +16,7 @@ #include "task_executor.h" namespace OHOS::NativeRdb { -TaskExecutor::TaskExecutor() : pool_(nullptr) +TaskExecutor::TaskExecutor() { } @@ -31,13 +31,34 @@ TaskExecutor &TaskExecutor::GetInstance() return instance; } +void TaskExecutor::Init() +{ + std::unique_lock lock(mutex_); + if (pool_ != nullptr) { + return; + } + pool_ = std::make_shared(MAX_THREADS, MIN_THREADS, "TaskExecutorRDB"); +}; + std::shared_ptr TaskExecutor::GetExecutor() { + std::unique_lock lock(mutex_); + if (pool_ == nullptr) { + pool_ = std::make_shared(MAX_THREADS, MIN_THREADS, "TaskExecutorRDB"); + } return pool_; } void TaskExecutor::SetExecutor(std::shared_ptr executor) { + std::unique_lock lock(mutex_); pool_ = executor; }; + +bool TaskExecutor::Stop() +{ + std::unique_lock lock(mutex_); + pool_ = nullptr; + return true; +} } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/abs_predicates.cpp b/relational_store/frameworks/native/rdb/src/abs_predicates.cpp index 08b297d1..9fa79ff1 100644 --- a/relational_store/frameworks/native/rdb/src/abs_predicates.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_predicates.cpp @@ -255,6 +255,20 @@ AbsPredicates *AbsPredicates::Glob(const std::string &field, const std::string & return this; } +/** + * Configures to match the specified field whose data type is String and the value not contains a wildcard. + */ +AbsPredicates *AbsPredicates::NotGlob(const std::string &field, const std::string &value) +{ + if (!CheckParameter("notGlob", field, { value })) { + return this; + } + CheckIsNeedAnd(); + whereClause += field + " NOT GLOB ? "; + bindArgs.push_back(ValueObject(value)); + return this; +} + /** * Restricts the value of the field to be unequal to the specified value. */ @@ -481,6 +495,16 @@ AbsPredicates *AbsPredicates::NotIn(const std::string &field, const std::vector< return NotIn(field, bindArgs); } +AbsPredicates *AbsPredicates::Having(const std::string &conditions, const std::vector &values) +{ + if (!CheckParameter("having", conditions, {})) { + return this; + } + havingClause = conditions; + bindArgs.insert(bindArgs.end(), values.begin(), values.end()); + return this; +} + /** * Configures to match the specified field whose data type is String array and values are out of a given range. */ @@ -561,7 +585,7 @@ void AbsPredicates::AppendWhereClauseWithInOrNotIn( std::string AbsPredicates::GetStatement() const { - return SqliteSqlBuilder::BuildSqlStringFromPredicates(*this); + return ""; } std::string AbsPredicates::GetWhereClause() const @@ -653,5 +677,10 @@ std::string AbsPredicates::GetIndex() const { return index; } + +std::string AbsPredicates::GetHaving() const +{ + return havingClause; +} } // namespace NativeRdb } // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/abs_rdb_predicates.cpp b/relational_store/frameworks/native/rdb/src/abs_rdb_predicates.cpp index 2ffa84da..e34e4284 100644 --- a/relational_store/frameworks/native/rdb/src/abs_rdb_predicates.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_rdb_predicates.cpp @@ -19,6 +19,7 @@ #include "logger.h" #include "rdb_trace.h" +#include "sqlite_sql_builder.h" namespace OHOS::NativeRdb { using namespace OHOS::Rdb; @@ -304,6 +305,11 @@ AbsRdbPredicates *AbsRdbPredicates::Glob(const std::string &field, const std::st predicates_.AddOperation(DistributedRdb::GLOB, field, value); return (AbsRdbPredicates *)AbsPredicates::Glob(field, value); } +AbsRdbPredicates *AbsRdbPredicates::NotGlob(const std::string &field, const std::string &value) +{ + predicates_.AddOperation(DistributedRdb::NOT_GLOB, field, value); + return (AbsRdbPredicates *)AbsPredicates::NotGlob(field, value); +} AbsRdbPredicates *AbsRdbPredicates::Distinct() { predicates_.AddOperation(DistributedRdb::DISTINCT, "", ""); @@ -333,4 +339,8 @@ AbsRdbPredicates *AbsRdbPredicates::NotIn(const std::string &field, const std::v predicates_.AddOperation(DistributedRdb::NOT_IN, field, vals); return (AbsRdbPredicates *)AbsPredicates::NotIn(field, values); } +std::string AbsRdbPredicates::GetStatement() const +{ + return SqliteSqlBuilder::BuildClauseFromPredicates(*this); +} } // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp index 467fdc71..d8dc46d4 100644 --- a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp @@ -118,7 +118,7 @@ int AbsResultSet::GetAllColumnNames(std::vector &columnNames) } columnNames.resize(columnCount_); for (auto &[name, index] : columnMap_) { - if (index > columnCount_) { + if (index >= columnCount_) { continue; } columnNames[index] = name; @@ -392,8 +392,7 @@ int AbsResultSet::GetColumnIndex(const std::string &columnName, int &columnIndex return E_OK; } - std::string lowerName = columnName; - SqliteUtils::Replace(lowerName, SqliteUtils::REP, ""); + std::string lowerName = SqliteUtils::Replace(columnName, SqliteUtils::REP, ""); auto periodIndex = lowerName.rfind('.'); if (periodIndex != std::string::npos) { lowerName = lowerName.substr(periodIndex + 1); diff --git a/relational_store/frameworks/native/rdb/src/cache_result_set.cpp b/relational_store/frameworks/native/rdb/src/cache_result_set.cpp index 50e8720a..a4f9b0a3 100644 --- a/relational_store/frameworks/native/rdb/src/cache_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/cache_result_set.cpp @@ -25,6 +25,9 @@ #include "rdb_trace.h" namespace OHOS { namespace NativeRdb { +CacheResultSet::CacheResultSet() : row_(0), maxRow_(0), maxCol_(0) +{ +} CacheResultSet::CacheResultSet(std::vector &&valueBuckets) : row_(0), maxCol_(0), valueBuckets_(std::move(valueBuckets)) { diff --git a/relational_store/frameworks/native/rdb/src/connection.cpp b/relational_store/frameworks/native/rdb/src/connection.cpp index 5588fa22..8f36eefb 100644 --- a/relational_store/frameworks/native/rdb/src/connection.cpp +++ b/relational_store/frameworks/native/rdb/src/connection.cpp @@ -22,7 +22,7 @@ static Connection::Creator g_creators[DB_BUTT] = { nullptr, nullptr }; static Connection::Repairer g_repairers[DB_BUTT] = { nullptr, nullptr }; static Connection::Deleter g_fileDeleter[DB_BUTT] = { nullptr, nullptr }; static Connection::Collector g_collectors[DB_BUTT] = { nullptr, nullptr }; -static Connection::Restorer g_restorer[DB_BUTT] = { nullptr, nullptr }; +static Connection::ReplicaChecker g_replicaCheckers[DB_BUTT] = { nullptr, nullptr }; std::pair> Connection::Create(const RdbStoreConfig &config, bool isWriter) { auto dbType = config.GetDBType(); @@ -82,19 +82,18 @@ std::map Connection::Collect(const RdbStoreConfig return collector(config); } -int32_t Connection::Restore(const RdbStoreConfig &config, const std::string &srcPath, const std::string &destPath) +int32_t Connection::CheckReplicaIntegrity(const RdbStoreConfig &config) { auto dbType = config.GetDBType(); if (dbType < static_cast(DB_SQLITE) || dbType >= static_cast(DB_BUTT)) { return E_INVALID_ARGS; } - - auto restorer = g_restorer[dbType]; - if (restorer == nullptr) { + auto replicaChecker = g_replicaCheckers[dbType]; + if (replicaChecker == nullptr) { return E_NOT_SUPPORT; } - return restorer(config, srcPath, destPath); + return replicaChecker(config); } int32_t Connection::RegisterCreator(int32_t dbType, Creator creator) @@ -153,17 +152,17 @@ int32_t Connection::RegisterCollector(int32_t dbType, Collector collector) return E_OK; } -int32_t Connection::RegisterRestorer(int32_t dbType, Restorer restorer) +int32_t Connection::RegisterReplicaChecker(int32_t dbType, ReplicaChecker replicaChecker) { if (dbType < static_cast(DB_SQLITE) || dbType >= static_cast(DB_BUTT)) { return E_INVALID_ARGS; } - if (g_restorer[dbType] != nullptr) { + if (g_replicaCheckers[dbType] != nullptr) { return E_OK; } - g_restorer[dbType] = restorer; + g_replicaCheckers[dbType] = replicaChecker; return E_OK; } diff --git a/relational_store/frameworks/native/rdb/src/connection_pool.cpp b/relational_store/frameworks/native/rdb/src/connection_pool.cpp index 8eff9a1c..c993f066 100644 --- a/relational_store/frameworks/native/rdb/src/connection_pool.cpp +++ b/relational_store/frameworks/native/rdb/src/connection_pool.cpp @@ -30,6 +30,7 @@ #include "rdb_errno.h" #include "rdb_fault_hiview_reporter.h" #include "rdb_sql_statistic.h" +#include "rdb_perfStat.h" #include "sqlite_global_config.h" #include "sqlite_utils.h" #include "task_executor.h" @@ -43,8 +44,10 @@ using ConnPool = ConnectionPool; using SharedConn = std::shared_ptr; using SharedConns = std::vector>; using SqlStatistic = DistributedRdb::SqlStatistic; +using PerfStat = DistributedRdb::PerfStat; using Reportor = RdbFaultHiViewReporter; constexpr int32_t TRANSACTION_TIMEOUT(2); +constexpr int64_t WAIT_TIME = 2; std::shared_ptr ConnPool::Create(const RdbStoreConfig &config, int &errCode) { @@ -64,11 +67,11 @@ std::shared_ptr ConnPool::Create(const RdbStoreConfig &config, int &er } std::string dbPath; (void)SqliteGlobalConfig::GetDbPath(config, dbPath); - LOG_INFO("code:%{public}d app[%{public}s:%{public}s] path[%{public}s] " + LOG_INFO("code:%{public}d app[%{public}s:%{public}s] area[%{public}s] " "cfg[%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d]" "%{public}s", errCode, config.GetBundleName().c_str(), config.GetModuleName().c_str(), - SqliteUtils::Anonymous(dbPath).c_str(), config.GetDBType(), config.GetHaMode(), config.IsEncrypt(), + SqliteUtils::GetArea(dbPath).c_str(), config.GetDBType(), config.GetHaMode(), config.IsEncrypt(), config.GetArea(), config.GetSecurityLevel(), config.GetRoleType(), config.IsReadOnly(), SqliteUtils::FormatDebugInfoBrief(Connection::Collect(config), SqliteUtils::Anonymous(config.GetName())).c_str()); @@ -112,6 +115,31 @@ ConnPool::ConnectionPool(const RdbStoreConfig &storeConfig) attachConfig_.SetJournalMode(JournalMode::MODE_TRUNCATE); trans_.right_ = Container::MIN_TRANS_ID; trans_.left_ = trans_.right_; + clearActuator_ = std::make_shared>, + std::function> & out, std::shared_ptr && input)>>>( + [](auto &out, std::shared_ptr &&input) { + for (auto &node : out) { + if (node.lock() == input) { + return; + } + } + out.push_back(std::move(input)); + }, + FIRST_DELAY_INTERVAL, + MIN_EXECUTE_INTERVAL, + MAX_EXECUTE_INTERVAL); + clearActuator_->SetExecutorPool(TaskExecutor::GetInstance().GetExecutor()); + clearActuator_->SetTask([](std::vector> &&nodes) { + for (auto &node : nodes) { + auto realNode = node.lock(); + if (realNode == nullptr || realNode->connect_ == nullptr) { + continue; + } + realNode->connect_->ClearCache(true); + } + return E_OK; + }); } std::pair> ConnPool::Init(bool isAttach, bool needWriter) @@ -156,6 +184,7 @@ std::pair> ConnPool::Init(bool isAttach, bo ConnPool::~ConnectionPool() { + clearActuator_ = nullptr; CloseAllConnections(); } @@ -231,6 +260,7 @@ void ConnPool::SetInTransaction(bool isInTransaction) std::pair> ConnPool::CreateTransConn(bool limited) { + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_WAIT); if (transCount_.load() >= MAX_TRANS && limited) { trans_.Dump("NO TRANS", transCount_ + isInTransaction_); writers_.Dump("NO TRANS WRITE", transCount_ + isInTransaction_); @@ -246,19 +276,21 @@ std::pair> ConnPool::CreateTransConn(bool l std::shared_ptr ConnPool::AcquireConnection(bool isReadOnly) { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_WAIT); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_WAIT); return Acquire(isReadOnly); } std::pair ConnPool::AcquireAll(int32_t time) { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_WAIT); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_WAIT); using namespace std::chrono; std::pair result; auto &[writer, readers] = result; auto interval = duration_cast(seconds(time)); auto start = steady_clock::now(); auto [res, writerNodes] = writers_.AcquireAll(interval); - if (!res) { + if (!res || writerNodes.empty()) { return {}; } writer = Convert2AutoConn(writerNodes.front()); @@ -316,6 +348,7 @@ std::shared_ptr ConnPool::Acquire(bool isReadOnly, std::chrono::millisecon SharedConn ConnPool::AcquireRef(bool isReadOnly, std::chrono::milliseconds ms) { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_WAIT); + PerfStat perfStat(config_.GetPath(), "", SqlStatistic::Step::STEP_WAIT); if (maxReader_ != 0) { return Acquire(isReadOnly, ms); } @@ -352,7 +385,6 @@ void ConnPool::ReleaseNode(std::shared_ptr node, bool isTrans) trans_.Dump("WAL trans_", transCount); readers_.Dump("WAL readers_", transCount); } - if (node->IsWriter() && (errCode != E_INNER_WARNING && errCode != E_NOT_SUPPORT)) { failedTime_ = errCode != E_OK ? now : steady_clock::time_point(); } @@ -363,6 +395,9 @@ void ConnPool::ReleaseNode(std::shared_ptr node, bool isTrans) auto &container = node->IsWriter() ? writers_ : readers_; container.Release(node); } + if (clearActuator_ != nullptr) { + clearActuator_->Execute>(std::move(node)); + } } int ConnPool::AcquireTransaction() @@ -407,6 +442,17 @@ int ConnPool::RestartConns() return errCode; } +int ConnPool::ReopenConns() +{ + CloseAllConnections(); + auto initRes = Init(); + if (initRes.first != E_OK) { + LOG_ERROR("Init fail, errCode:%{public}d", initRes.first); + return initRes.first; + } + return E_OK; +} + /** * The database locale. */ @@ -416,14 +462,18 @@ int ConnPool::ConfigLocale(const std::string &localeStr) if (errCode != E_OK) { return errCode; } - return writers_.ConfigLocale(localeStr); + errCode = writers_.ConfigLocale(localeStr); + if (errCode != E_OK) { + return errCode; + } + return trans_.ConfigLocale(localeStr); } /** * Rename the backed up database. */ int ConnPool::ChangeDbFileForRestore(const std::string &newPath, const std::string &backupPath, - const std::vector &newKey, SlaveStatus &slaveStatus) + const std::vector &newKey, std::shared_ptr slaveStatus) { if (!writers_.IsFull() || config_.GetPath() == backupPath || newPath == backupPath) { LOG_ERROR("Connection pool is busy now!"); @@ -451,12 +501,13 @@ int ConnPool::ChangeDbFileForRestore(const std::string &newPath, const std::stri } return retVal; } - return RestoreMasterDb(newPath, backupPath, slaveStatus); + return RestoreByDbSqliteType(newPath, backupPath, slaveStatus); } -int ConnPool::RestoreMasterDb(const std::string &newPath, const std::string &backupPath, SlaveStatus &slaveStatus) +int ConnPool::RestoreByDbSqliteType(const std::string &newPath, const std::string &backupPath, + std::shared_ptr slaveStatus) { - if (SqliteUtils::IsSlaveDbName(backupPath) && config_.GetHaMode() == HAMode::MAIN_REPLICA) { + if (SqliteUtils::IsSlaveDbName(backupPath) && config_.GetHaMode() != HAMode::SINGLE) { auto connection = AcquireConnection(false); if (connection == nullptr) { return E_DATABASE_BUSY; @@ -464,8 +515,34 @@ int ConnPool::RestoreMasterDb(const std::string &newPath, const std::string &bac return connection->Restore(backupPath, {}, slaveStatus); } + return RestoreMasterDb(newPath, backupPath); +} + +int ConnPool::RestoreMasterDb(const std::string &newPath, const std::string &backupPath) +{ + if (!CheckIntegrity(backupPath)) { + LOG_ERROR("backup file is corrupted, %{public}s", SqliteUtils::Anonymous(backupPath).c_str()); + return E_SQLITE_CORRUPT; + } + auto walFile = backupPath + "-wal"; + if (SqliteUtils::GetFileSize(walFile) != 0) { + LOG_ERROR("Wal file exist."); + return E_SQLITE_CORRUPT; + } + + SqliteUtils::DeleteFile(backupPath + "-shm"); + SqliteUtils::DeleteFile(backupPath + "-wal"); + CloseAllConnections(); - int ret = Connection::Restore(config_, backupPath, newPath); + Connection::Delete(config_); + + if (config_.GetPath() != newPath) { + RdbStoreConfig config(newPath); + config.SetPath(newPath); + Connection::Delete(config); + } + + bool copyRet = SqliteUtils::CopyFile(backupPath, newPath); int32_t errCode = E_OK; std::shared_ptr pool; for (uint32_t retry = 0; retry < ITERS_COUNT; ++retry) { @@ -485,7 +562,37 @@ int ConnPool::RestoreMasterDb(const std::string &newPath, const std::string &bac LOG_WARN("Restore failed! rebuild res:%{public}d, path:%{public}s.", errCode, SqliteUtils::Anonymous(backupPath).c_str()); } - return ret == E_OK ? errCode : ret; + return copyRet ? errCode : E_ERROR; +} + +int ConnPool::Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) +{ + int errCode = E_OK; + auto [connection, readers] = AcquireAll(WAIT_TIME); + if (connection == nullptr) { + return E_DATABASE_BUSY; + } + CloseAllConnections(); + auto key = config_.GetEncryptKey(); + readers.clear(); + + errCode = connection->Rekey(cryptoParam); + if (errCode != E_OK) { + LOG_ERROR("ReKey failed, err = %{public}d", errCode); + key.assign(key.size(), 0); + return errCode; + } + config_.ResetEncryptKey(cryptoParam.encryptKey_); + connection = nullptr; + auto initRes = Init(); + if (initRes.first != E_OK) { + LOG_ERROR("Init fail, errCode:%{public}d", initRes.first); + config_.ResetEncryptKey(key); + key.assign(key.size(), 0); + initRes = Init(); + return initRes.first; + } + return E_OK; } std::stack &ConnPool::GetTransactionStack() @@ -572,10 +679,13 @@ void ConnPool::Container::InitMembers(Creator creator, int32_t max, int32_t time std::pair> ConnPool::Container::Initialize( Creator creator, int32_t max, int32_t timeout, bool disable, bool acquire) { - InitMembers(creator, max, timeout, disable); std::shared_ptr connNode = nullptr; { std::unique_lock lock(mutex_); + disable_ = disable; + max_ = max; + creator_ = creator; + timeout_ = std::chrono::seconds(timeout); for (int i = 0; i < max_; ++i) { auto errCode = ExtendNode(); if (errCode != E_OK) { @@ -598,16 +708,18 @@ std::pair> ConnPool::Container::Ini int32_t ConnPool::Container::ConfigLocale(const std::string &locale) { std::unique_lock lock(mutex_); - if (total_ != count_) { - return E_DATABASE_BUSY; - } for (auto it = details_.begin(); it != details_.end();) { auto conn = it->lock(); if (conn == nullptr || conn->connect_ == nullptr) { it = details_.erase(it); continue; } - conn->connect_->ConfigLocale(locale); + int32_t errCode = conn->connect_->ConfigLocale(locale); + if (errCode != E_OK) { + LOG_ERROR("ConfigLocale failed %{public}d", errCode); + return errCode; + } + ++it; } return E_OK; } diff --git a/relational_store/frameworks/native/rdb/src/delay_notify.cpp b/relational_store/frameworks/native/rdb/src/delay_notify.cpp index 336af218..3fbb9b1f 100644 --- a/relational_store/frameworks/native/rdb/src/delay_notify.cpp +++ b/relational_store/frameworks/native/rdb/src/delay_notify.cpp @@ -29,7 +29,7 @@ DelayNotify::~DelayNotify() return; } if (delaySyncTaskId_ != TaskExecutor::INVALID_TASK_ID) { - pool_->Remove(delaySyncTaskId_); + pool_->Remove(delaySyncTaskId_, true); } if (task_ != nullptr && changedData_.tableData.size() > 0) { DistributedRdb::RdbNotifyConfig rdbNotifyConfig; @@ -48,7 +48,7 @@ void DelayNotify::UpdateNotify(const DistributedRdb::RdbChangedData &changedData { std::lock_guard lock(mutex_); for (auto &[k, v] : changedData.tableData) { - if (!v.isTrackedDataChange && !v.isP2pSyncDataChange) { + if (!v.isTrackedDataChange && !v.isP2pSyncDataChange && !v.isKnowledgeDataChange) { continue; } auto it = changedData_.tableData.find(k); @@ -88,8 +88,14 @@ void DelayNotify::StartTimer() } if (delaySyncTaskId_ == TaskExecutor::INVALID_TASK_ID) { + std::weak_ptr delayNotify = shared_from_this(); delaySyncTaskId_ = pool_->Schedule(std::chrono::milliseconds(autoSyncInterval_), - [this]() { ExecuteTask(); }); + [delayNotify]() { + auto lockedDelayNotify = delayNotify.lock(); + if (lockedDelayNotify != nullptr) { + lockedDelayNotify->ExecuteTask(); + } + }); } else { delaySyncTaskId_ = pool_->Reset(delaySyncTaskId_, std::chrono::milliseconds(autoSyncInterval_)); diff --git a/relational_store/frameworks/native/rdb/src/global_resource.cpp b/relational_store/frameworks/native/rdb/src/global_resource.cpp new file mode 100644 index 00000000..ab9b1553 --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/global_resource.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. + */ + +#define LOG_TAG "global_resource" +#include "global_resource.h" + +#include "rdb_errno.h" + +namespace OHOS::NativeRdb { +static GlobalResource::Cleaner g_cleaners[GlobalResource::CLEAN_BUTT]; +int32_t GlobalResource::RegisterClean(CleanType type, Cleaner clean) +{ + if (type < static_cast(GlobalResource::ICU) || type >= static_cast(GlobalResource::CLEAN_BUTT) || + clean == nullptr) { + return E_INVALID_ARGS; + } + + if (g_cleaners[type] != nullptr) { + return E_OK; + } + + g_cleaners[type] = clean; + return E_OK; +} + +int32_t GlobalResource::CleanUp(int32_t type) +{ + if (type < static_cast(GlobalResource::CLEAN_HEAD) || + type >= static_cast(GlobalResource::CLEAN_BUTT)) { + return E_INVALID_ARGS; + } + + int32_t ret = E_OK; + if (g_cleaners[type] != nullptr) { + ret = g_cleaners[type](); + } + + return ret; +} +} // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/grd_api_manager.cpp b/relational_store/frameworks/native/rdb/src/grd_api_manager.cpp index 5b401c3a..04d7ea2a 100644 --- a/relational_store/frameworks/native/rdb/src/grd_api_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/grd_api_manager.cpp @@ -62,7 +62,8 @@ void GRD_DBApiInitEnhance(GRD_APIInfo &GRD_DBApiInfo) GRD_DBApiInfo.DBReKeyApi = (DBReKey)dlsym(g_library, "GRD_DBRekey"); GRD_DBApiInfo.DBGetConfigApi = (DBGetConfig)dlsym(g_library, "GRD_GetConfig"); GRD_DBApiInfo.DBSetConfigApi = (DBSetConfig)dlsym(g_library, "GRD_SetConfig"); - GRD_DBApiInfo.DBSqlRegistryThreadPool = (DBSqlRegistryThreadPool)dlsym(g_library, "GRD_SqlRegistryThreadPool"); + GRD_DBApiInfo.DBSqlRegistryThreadPool = (DBSqlRegistryThreadPool)dlsym(g_library, "GRD_DbRegistryThreadPool"); + GRD_DBApiInfo.DBSqlRegistryClusterAlgo = (DBSqlRegistryClusterAlgo)dlsym(g_library, "GRD_SqlRegistryClusterAlgo"); #endif } diff --git a/relational_store/frameworks/native/rdb/src/knowledge_schema_helper.cpp b/relational_store/frameworks/native/rdb/src/knowledge_schema_helper.cpp new file mode 100644 index 00000000..f99fe863 --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/knowledge_schema_helper.cpp @@ -0,0 +1,200 @@ +/* + * 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. + */ +#define LOG_TAG "KnowledgeSchemaHelper" +#include "knowledge_schema_helper.h" + +#ifndef CROSS_PLATFORM +#include +#endif +#include +#include +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_fault_hiview_reporter.h" +#include "sqlite_utils.h" +#include "task_executor.h" + +namespace OHOS::NativeRdb { +using namespace OHOS::Rdb; + +static constexpr int AIP_MODULE_ID = 13; +constexpr ErrCode AIP_ERR_OFFSET = ErrCodeOffset(SUBSYS_DISTRIBUTEDDATAMNG, AIP_MODULE_ID); +constexpr int32_t KNOWLEDGE_BASE_ERROR_CODE_OFFSET{ 20000 }; +constexpr ErrCode KNOWLEDGE_BASE_FAIL = AIP_ERR_OFFSET + KNOWLEDGE_BASE_ERROR_CODE_OFFSET; +constexpr ErrCode KNOWLEDGE_SCHEMA_NOT_VALID = KNOWLEDGE_BASE_FAIL + 1; + +KnowledgeSchemaHelper::~KnowledgeSchemaHelper() +{ + std::unique_lock writeLock(libMutex_); + if (schemaManager_ != nullptr) { + schemaManager_->StopTask(dbName_); + delete schemaManager_; + schemaManager_ = nullptr; + } +#ifndef CROSS_PLATFORM + if (dlHandle_ != nullptr) { + dlclose(dlHandle_); + dlHandle_ = nullptr; + } +#endif +} + +void KnowledgeSchemaHelper::Init(const RdbStoreConfig &config, const DistributedRdb::RdbKnowledgeSchema &schema) +{ + LoadKnowledgeLib(); + if (!IsLoadLib()) { + LOG_WARN("skip init by miss lib"); + return; + } + std::unique_lock writeLock(libMutex_); + if (schemaManager_ == nullptr) { + LOG_WARN("skip init by miss manager"); + return; + } + schemaManager_->Init(config, schema); + bundleName_ = config.GetBundleName(); + dbName_ = config.GetName(); + inited_ = true; +} + +std::pair KnowledgeSchemaHelper::GetRdbKnowledgeSchema( + const std::string &dbName) +{ + std::pair res; + auto &[errCode, schema] = res; + LoadKnowledgeLib(); + if (!IsLoadLib()) { + LOG_WARN("skip get donate data by miss lib"); + errCode = E_ERROR; + return res; + } + std::shared_lock readLock(libMutex_); + if (schemaManager_ == nullptr) { + LOG_WARN("skip get donate data by miss manager"); + errCode = E_ERROR; + return res; + } + errCode = E_OK; + auto kSchema = schemaManager_->GetRdbKnowledgeSchema(dbName); + if (kSchema == nullptr) { + LOG_WARN("unable to get knowledge schema."); + RdbFaultHiViewReporter::ReportRAGFault("Parse knowledge schema failed", "ParseRdbKnowledgeSchema", bundleName_, + KNOWLEDGE_BASE_FAIL, KNOWLEDGE_SCHEMA_NOT_VALID); + errCode = E_ERROR; + return res; + } + schema = *kSchema; + return res; +} + +void KnowledgeSchemaHelper::DonateKnowledgeData() +{ + if (!inited_) { + LOG_WARN("knowledge schema helper not init."); + return; + } + LoadKnowledgeLib(); + if (!IsLoadLib()) { + LOG_WARN("skip donate data by miss lib"); + return; + } + auto executor = TaskExecutor::GetInstance().GetExecutor(); + if (executor == nullptr) { + LOG_WARN("skip donate data by miss pool"); + return; + } + std::shared_lock readLock(libMutex_); + if (schemaManager_ == nullptr) { + LOG_WARN("skip donate data by miss manager"); + return; + } + std::weak_ptr helper = shared_from_this(); + executor->Execute([helper]() { + auto realHelper = helper.lock(); + if (realHelper == nullptr) { + LOG_WARN("knowledge helper is null"); + return; + } + realHelper->StartTask(); + }); +} + +void KnowledgeSchemaHelper::LoadKnowledgeLib() +{ +#ifndef CROSS_PLATFORM + std::unique_lock writeLock(libMutex_); + if (dlHandle_ != nullptr) { + return; + } + auto handle = dlopen("libaip_knowledge_process.z.so", RTLD_LAZY); + if (handle != nullptr) { + LoadKnowledgeSchemaManager(handle); + dlHandle_ = handle; + } else { + LOG_WARN("unable to load lib, errno: %{public}d, %{public}s", errno, dlerror()); + } +#endif +} + +void KnowledgeSchemaHelper::LoadKnowledgeSchemaManager(void *handle) +{ +#ifndef CROSS_PLATFORM + typedef DistributedRdb::IKnowledgeSchemaManager* (*CreateKnowledgeSchemaManager)(); + auto creator = (CreateKnowledgeSchemaManager)(dlsym(handle, "CreateKnowledgeSchemaManager")); + if (creator == nullptr) { + LOG_WARN("unable to load creator, errno: %{public}d, %{public}s", errno, dlerror()); + return; + } + schemaManager_ = creator(); + if (schemaManager_ != nullptr) { + LOG_INFO("load creator success"); + } else { + LOG_WARN("load creator failed with oom"); + } +#endif +} + +bool KnowledgeSchemaHelper::IsLoadLib() const +{ +#ifndef CROSS_PLATFORM + std::shared_lock readLock(libMutex_); + return dlHandle_ != nullptr; +#else + return false; +#endif +} + +void KnowledgeSchemaHelper::StartTask() +{ + DistributedRdb::IKnowledgeSchemaManager *manager = nullptr; + { + std::shared_lock readLock(libMutex_); + if (schemaManager_ == nullptr) { + LOG_WARN("skip execute donate data by miss manager"); + return; + } + manager = schemaManager_; + } + manager->StartTask(dbName_); +} + +void KnowledgeSchemaHelper::Close() +{ + std::unique_lock writeLock(libMutex_); + if (schemaManager_ != nullptr) { + schemaManager_->StopTask(dbName_); + } +} +} \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rd_connection.cpp b/relational_store/frameworks/native/rdb/src/rd_connection.cpp index f84b475c..b7c6348f 100644 --- a/relational_store/frameworks/native/rdb/src/rd_connection.cpp +++ b/relational_store/frameworks/native/rdb/src/rd_connection.cpp @@ -35,6 +35,7 @@ __attribute__((used)) const int32_t RdConnection::regRepairer_ = Connection::RegisterRepairer(DB_VECTOR, RdConnection::Repair); __attribute__((used)) const int32_t RdConnection::regDeleter_ = Connection::RegisterDeleter(DB_VECTOR, RdConnection::Delete); +constexpr int CONFIG_SIZE_EXCEPT_ENCRYPT = 167; // When modifying config, this item needs to be modified std::pair> RdConnection::Create(const RdbStoreConfig &config, bool isWrite) { @@ -53,33 +54,12 @@ std::pair> RdConnection::Create(const RdbSt errCode = connection->InnerOpen(config); if (errCode == E_OK) { conn = connection; - CheckConfig(connection, config); break; } } return result; } -void RdConnection::CheckConfig(std::shared_ptr conn, const RdbStoreConfig &config) -{ - if (config.GetNcandidates() != NCANDIDATES_DEFAULT_NUM) { - ExecuteSet(conn, "diskann_probe_ncandidates", config.GetNcandidates()); - } -} - -void RdConnection::ExecuteSet(std::shared_ptr conn, const std::string ¶mName, int num) -{ - std::string sql = "SET " + paramName + " = " + std::to_string(num); - auto [errCode, stmt] = conn->CreateStatement(sql, conn); - if (errCode != E_OK || stmt == nullptr) { - LOG_ERROR("Create statement failed, paramName: %{public}s, errCode: %{public}d", - paramName.c_str(), errCode); - return; - } - stmt->Step(); - stmt->Finalize(); -} - int32_t RdConnection::Repair(const RdbStoreConfig &config) { std::string dbPath = ""; @@ -140,12 +120,13 @@ std::string RdConnection::GetConfigStr(const std::vector &keys, bool is std::string config = "{"; if (isEncrypt) { const size_t keyBuffSize = keys.size() * 2 + 1; // 2 hex number can represent a uint8_t, 1 is for '/0' + config.reserve(CONFIG_SIZE_EXCEPT_ENCRYPT + keyBuffSize); char keyBuff[keyBuffSize]; config += "\"isEncrypted\":1,"; config += "\"hexPassword\":\""; config += RdUtils::GetEncryptKey(keys, keyBuff, keyBuffSize); config += "\","; - (void)memset_s(keyBuff, keyBuffSize, 0, keyBuffSize); + std::fill(keyBuff, keyBuff + keyBuffSize, 0); } config += RdConnection::GRD_OPEN_CONFIG_STR; config += "}"; @@ -163,7 +144,7 @@ int RdConnection::InnerOpen(const RdbStoreConfig &config) std::vector newKey = config.GetNewEncryptKey(); if (!newKey.empty()) { newKey.assign(newKey.size(), 0); - errCode = ReSetKey(config); + errCode = ResetKey(config); if (errCode != E_OK) { LOG_ERROR("Can not reset key %{public}d.", errCode); return errCode; @@ -222,6 +203,17 @@ std::pair RdConnection::CreateStatement(const std:: return { ret, stmt }; } +std::pair RdConnection::CreateReplicaStatement([[gnu::unused]] const std::string &sql, + [[gnu::unused]] Connection::SConn conn) +{ + return { E_NOT_SUPPORT, nullptr }; +} + +int RdConnection::CheckReplicaForRestore() +{ + return E_NOT_SUPPORT; +} + int32_t RdConnection::GetDBType() const { return DB_VECTOR; @@ -232,7 +224,7 @@ bool RdConnection::IsWriter() const return isWriter_; } -int32_t RdConnection::ReSetKey(const RdbStoreConfig &config) +int32_t RdConnection::ResetKey(const RdbStoreConfig &config) { if (!IsWriter()) { return E_OK; @@ -280,6 +272,11 @@ int32_t RdConnection::CleanDirtyData(const std::string &table, uint64_t cursor) return E_NOT_SUPPORT; } +int32_t RdConnection::Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) +{ + return E_NOT_SUPPORT; +} + int32_t RdConnection::SubscribeTableChanges(const Connection::Notifier ¬ifier) { return E_NOT_SUPPORT; @@ -295,7 +292,7 @@ int32_t RdConnection::GetJournalMode() return E_NOT_SUPPORT; } -int32_t RdConnection::ClearCache() +int32_t RdConnection::ClearCache(bool isForceClear) { return E_NOT_SUPPORT; } @@ -311,7 +308,7 @@ int32_t RdConnection::Unsubscribe(const std::shared_ptr &destEncryptKey, bool isAsync, - SlaveStatus &slaveStatus) + std::shared_ptr slaveStatus, bool verifyDb) { if (!destEncryptKey.empty() && !config_.IsEncrypt()) { return RdUtils::RdDbBackup(dbHandle_, databasePath.c_str(), destEncryptKey); @@ -326,7 +323,8 @@ int32_t RdConnection::Backup(const std::string &databasePath, const std::vector< } int32_t RdConnection::Restore( - const std::string &databasePath, const std::vector &destEncryptKey, SlaveStatus &slaveStatus) + const std::string &databasePath, const std::vector &destEncryptKey, + std::shared_ptr slaveStatus) { auto ret = RdUtils::RdDbClose(dbHandle_, 0); if (ret != E_OK) { @@ -344,7 +342,8 @@ int32_t RdConnection::Restore( if (ret != E_OK) { LOG_ERROR("Restore failed, original datapath:%{public}s, restorepath:%{public}s, errcode:%{public}d", - config_.GetPath().c_str(), databasePath.c_str(), ret); + SqliteUtils::Anonymous(config_.GetPath()).c_str(), + SqliteUtils::Anonymous(databasePath).c_str(), ret); return ret; } @@ -356,9 +355,31 @@ int32_t RdConnection::Restore( return ret; } -ExchangeStrategy RdConnection::GenerateExchangeStrategy(const SlaveStatus &status) +ExchangeStrategy RdConnection::GenerateExchangeStrategy(std::shared_ptr status, bool isRelpay) { return ExchangeStrategy::NOT_HANDLE; } + +int RdConnection::SetKnowledgeSchema([[gnu::unused]] const DistributedRdb::RdbKnowledgeSchema &schema) +{ + return E_NOT_SUPPORT; +} + +int RdConnection::CleanDirtyLog([[gnu::unused]] const std::string &table, [[gnu::unused]] uint64_t cursor) +{ + return E_NOT_SUPPORT; +} + +int RdConnection::RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) +{ + int errCode = + RdUtils::RdSqlRegistryClusterAlgo(dbHandle_, clstAlgoName.c_str(), reinterpret_cast(func)); + if (errCode != E_OK) { + LOG_ERROR("Can not registry cluster func in rd db %{public}d.", errCode); + return errCode; + } + return E_OK; +} + } // namespace NativeRdb } // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rd_statement.cpp b/relational_store/frameworks/native/rdb/src/rd_statement.cpp index be0b5b0e..98ec4221 100644 --- a/relational_store/frameworks/native/rdb/src/rd_statement.cpp +++ b/relational_store/frameworks/native/rdb/src/rd_statement.cpp @@ -515,5 +515,10 @@ void RdStatement::GetProperties() { columnCount_ = RdUtils::RdSqlColCnt(stmtHandle_); } + +std::pair> RdStatement::GetRows(uint32_t maxCount) +{ + return { E_NOT_SUPPORT, {} }; +} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/rd_utils.cpp b/relational_store/frameworks/native/rdb/src/rd_utils.cpp index db615d28..0dd705a5 100644 --- a/relational_store/frameworks/native/rdb/src/rd_utils.cpp +++ b/relational_store/frameworks/native/rdb/src/rd_utils.cpp @@ -35,7 +35,7 @@ using namespace OHOS::Rdb; static GRD_APIInfo GRD_KVApiInfo; -GRD_ThreadPoolT RdUtils::threadPool_ = { 0 }; +GRD_DbThreadPoolT RdUtils::threadPool_ = { 0 }; struct GrdErrnoPair { int32_t grdCode; @@ -284,7 +284,12 @@ int RdUtils::RdSqlBindBlob(GRD_SqlStmt *stmt, uint32_t idx, const void *val, int if (freeFunc == nullptr) { freeFunc = RdSqlFreeBlob; } - return TransferGrdErrno(GRD_KVApiInfo.DBSqlBindBlob(stmt, idx, tmpVal, len, freeFunc)); + int result = TransferGrdErrno(GRD_KVApiInfo.DBSqlBindBlob(stmt, idx, tmpVal, len, freeFunc)); + if (result != E_OK) { + LOG_ERROR("DBSqlBindBlob failed, error code: %{public}d", result); + freeFunc(tmpVal); + } + return result; } void RdSqlFreeCharStr(void *charStr) @@ -300,7 +305,7 @@ int RdUtils::RdSqlBindText(GRD_SqlStmt *stmt, uint32_t idx, const void *val, int if (GRD_KVApiInfo.DBSqlBindText == nullptr) { return E_NOT_SUPPORT; } - if (len <= 0) { + if (len < 0) { LOG_ERROR("Invalid len %{public}d", len); return E_INVALID_ARGS; } @@ -317,7 +322,12 @@ int RdUtils::RdSqlBindText(GRD_SqlStmt *stmt, uint32_t idx, const void *val, int if (freeFunc == nullptr) { freeFunc = RdSqlFreeCharStr; } - return TransferGrdErrno(GRD_KVApiInfo.DBSqlBindText(stmt, idx, tmpVal, len, freeFunc)); + int result = TransferGrdErrno(GRD_KVApiInfo.DBSqlBindText(stmt, idx, tmpVal, len, freeFunc)); + if (result != E_OK) { + LOG_ERROR("DBSqlBindText failed, error code: %{public}d", result); + freeFunc(tmpVal); + } + return result; } int RdUtils::RdSqlBindInt(GRD_SqlStmt *stmt, uint32_t idx, int32_t val) @@ -394,7 +404,12 @@ int RdUtils::RdSqlBindFloatVector(GRD_SqlStmt *stmt, uint32_t idx, float *val, u if (freeFunc == nullptr) { freeFunc = RdSqlFreeFloatArr; } - return TransferGrdErrno(GRD_KVApiInfo.DBSqlBindFloatVector(stmt, idx, tmpVal, dim, freeFunc)); + int result = TransferGrdErrno(GRD_KVApiInfo.DBSqlBindFloatVector(stmt, idx, tmpVal, dim, freeFunc)); + if (result != E_OK) { + LOG_ERROR("DBSqlBindFloatVector failed, error code: %{public}d", result); + freeFunc(tmpVal); + } + return result; } int RdUtils::RdSqlStep(GRD_SqlStmt *stmt) @@ -639,17 +654,28 @@ int RdUtils::RdDbSetVersion(GRD_DB *db, GRD_ConfigTypeE type, int version) return TransferGrdErrno(GRD_KVApiInfo.DBSetConfigApi(db, type, value)); } -static void Schedule(void *func, void *param) +static uint64_t Schedule(void *func, void *param) { auto pool = TaskExecutor::GetInstance().GetExecutor(); if (pool == nullptr) { - LOG_ERROR("pool is nullptr"); - return; + LOG_ERROR("|Schedule| pool is nullptr"); + return static_cast(TaskExecutor::INVALID_TASK_ID); } - pool->Execute([func, param]() { + TaskExecutor::TaskId taskId = pool->Execute([func, param]() { void (*funcPtr)(void *) = reinterpret_cast(func); funcPtr(param); }); + return static_cast(taskId); +} + +static bool Remove(uint64_t taskId, bool wait) +{ + auto pool = TaskExecutor::GetInstance().GetExecutor(); + if (pool == nullptr) { + LOG_ERROR("|Remove| pool is nullptr"); + return false; + } + return pool->Remove(taskId, wait); } int RdUtils::RdSqlRegistryThreadPool(GRD_DB *db) @@ -661,9 +687,22 @@ int RdUtils::RdSqlRegistryThreadPool(GRD_DB *db) LOG_ERROR("registry threadPool ptr is nullptr"); return E_NOT_SUPPORT; } - RdUtils::threadPool_.schedule = reinterpret_cast(Schedule); + RdUtils::threadPool_.schedule = reinterpret_cast(Schedule); + RdUtils::threadPool_.remove = reinterpret_cast(Remove); return TransferGrdErrno(GRD_KVApiInfo.DBSqlRegistryThreadPool(db, &threadPool_)); } +int RdUtils::RdSqlRegistryClusterAlgo(GRD_DB *db, const char *clstAlgoName, GRD_ClusterAlgoFunc func) +{ + if (GRD_KVApiInfo.DBSqlRegistryClusterAlgo == nullptr) { + GRD_KVApiInfo = GetApiInfoInstance(); + } + if (GRD_KVApiInfo.DBSqlRegistryClusterAlgo == nullptr) { + LOG_ERROR("registry ClusterAlgo ptr is nullptr"); + return E_NOT_SUPPORT; + } + return TransferGrdErrno(GRD_KVApiInfo.DBSqlRegistryClusterAlgo(db, clstAlgoName, func)); +} + } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/rdb_helper.cpp b/relational_store/frameworks/native/rdb/src/rdb_helper.cpp index 67e4d1f9..6741e8b7 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_helper.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_helper.cpp @@ -15,6 +15,7 @@ #define LOG_TAG "RdbHelper" #include "rdb_helper.h" +#include "global_resource.h" #include "logger.h" #include "rdb_errno.h" #include "rdb_fault_hiview_reporter.h" @@ -28,12 +29,13 @@ #include "security_policy.h" #endif #include "rdb_fault_hiview_reporter.h" +#include namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; using Reportor = RdbFaultHiViewReporter; - +static_assert(ErrCodeOffset(SUBSYS_DISTRIBUTEDDATAMNG, 2) == DISTRIBUTEDDATAMGR_RDB_ERR_OFFSET); std::shared_ptr RdbHelper::GetRdbStore( const RdbStoreConfig &config, int version, RdbOpenCallback &openCallback, int &errCode) { @@ -41,7 +43,9 @@ std::shared_ptr RdbHelper::GetRdbStore( SqliteGlobalConfig::InitSqliteGlobalConfig(); auto rdb = RdbStoreManager::GetInstance().GetRdbStore(config, errCode, version, openCallback); if (errCode != E_OK) { - Reportor::ReportFault(RdbFaultDbFileEvent(FT_OPEN, errCode, config, "LOG:RdbHelper::GetRdbStore", true)); + Reportor::ReportFault(RdbFaultDbFileEvent(FT_OPEN, errCode, config, + SqliteUtils::FormatDebugInfoBrief(Connection::Collect(config), SqliteUtils::Anonymous(config.GetName())), + true)); } return rdb; @@ -53,6 +57,40 @@ void RdbHelper::ClearCache() RdbStoreManager::GetInstance().Clear(); } +bool RdbHelper::Init() +{ + LOG_INFO("Init start"); + RdbStoreManager::GetInstance().Init(); + return true; +} + +bool RdbHelper::Destroy(const DestroyOption &option) +{ + LOG_INFO("Destroy resource start"); + bool ret = RdbStoreManager::GetInstance().Destroy(); + if (option.cleanICU && GlobalResource::CleanUp(GlobalResource::ICU) != E_OK) { + LOG_WARN("CleanUp ICU failed"); + ret = false; + } + if (option.cleanOpenSSL && GlobalResource::CleanUp(GlobalResource::OPEN_SSL) != E_OK) { + LOG_WARN("CleanUp OPEN_SSL failed"); + ret = false; + } + if (GlobalResource::CleanUp(GlobalResource::DB_CLIENT) != E_OK) { + LOG_WARN("CleanUp DB_CLIENT failed"); + ret = false; + } + if (GlobalResource::CleanUp(GlobalResource::OBS) != E_OK) { + LOG_WARN("CleanUp OBS failed"); + ret = false; + } + if (GlobalResource::CleanUp(GlobalResource::IPC) != E_OK) { + LOG_WARN("CleanUp IPC failed"); + ret = false; + } + return ret; +} + int RdbHelper::DeleteRdbStore(const std::string &dbFileName, bool shouldClose) { RdbStoreConfig config(dbFileName); diff --git a/relational_store/frameworks/native/rdb/src/rdb_icu_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_icu_manager.cpp new file mode 100644 index 00000000..43e4e2e5 --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/rdb_icu_manager.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "RdbICUManager" +#include "rdb_icu_manager.h" + +#include + +#include "global_resource.h" +#include "logger.h" +#include "rdb_errno.h" +namespace OHOS::NativeRdb { +using namespace OHOS::Rdb; +RdbICUManager &RdbICUManager::GetInstance() +{ + static RdbICUManager instance; + return instance; +} + +int32_t RdbICUManager::ConfigLocale(sqlite3 *db, const std::string &localeStr) +{ + auto handle = GetApiInfo(); + if (handle.configIcuLocaleFunc == nullptr) { + LOG_ERROR("dlsym(ConfigLocal) failed!"); + return E_NOT_SUPPORT; + } + return handle.configIcuLocaleFunc(db, localeStr); +} + +RdbICUManager::RdbICUManager() +{ + handle_ = nullptr; +} + +RdbICUManager::~RdbICUManager() +{ + if (handle_ != nullptr) { + dlclose(handle_); + handle_ = nullptr; + } +} + +int32_t RdbICUManager::CleanUp() +{ + auto handle = GetApiInfo(); + if (handle.cleanUpFunc == nullptr) { + LOG_ERROR("dlsym(CleanUp) failed!"); + return E_NOT_SUPPORT; + } + auto code = handle.cleanUpFunc(); + if (code != E_OK) { + return code; + } + std::lock_guard lock(mutex_); + dlclose(handle_); + handle_ = nullptr; + apiInfo_.cleanUpFunc = nullptr; + apiInfo_.configIcuLocaleFunc = nullptr; + return E_OK; +} + +RdbICUManager::ICUAPIInfo RdbICUManager::GetApiInfo() +{ + std::lock_guard lock(mutex_); + if (handle_ != nullptr) { + return apiInfo_; + } + handle_ = dlopen("librelational_store_icu.z.so", RTLD_LAZY); + if (handle_ == nullptr) { + LOG_ERROR("dlopen(librelational_store_icu) failed!"); + return apiInfo_; + } + GlobalResource::RegisterClean(GlobalResource::ICU, []() { return RdbICUManager::GetInstance().CleanUp(); }); + apiInfo_.configIcuLocaleFunc = reinterpret_cast(dlsym(handle_, "ConfigICULocale")); + apiInfo_.cleanUpFunc = reinterpret_cast(dlsym(handle_, "CleanUp")); + return apiInfo_; +} +} // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp index ed6d1f80..55240013 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp @@ -17,6 +17,7 @@ #include +#include "global_resource.h" #include "ipc_skeleton.h" #include "irdb_service.h" #include "iservice_registry.h" @@ -31,7 +32,7 @@ using namespace OHOS::Rdb; using RdbServiceProxy = DistributedRdb::RdbServiceProxy; using namespace OHOS::NativeRdb; using namespace OHOS::DistributedRdb::RelationalStore; - +constexpr int32_t MAX_RETRY = 100; class DeathStub : public IRemoteBroker { public: DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedRdb.DeathStub"); @@ -57,21 +58,22 @@ std::shared_ptr RdbManagerImpl::GetDistributedDataMana sptr observer = new (std::nothrow) DeathStubImpl(); dataService->RegisterDeathObserver(bundleName, observer); - return std::shared_ptr(dataService.GetRefPtr(), [dataService, observer](const auto *) {}); + return std::shared_ptr(dataService.GetRefPtr(), [dataService](const auto *) {}); } -static void LinkToDeath(const sptr &remote) +sptr RdbManagerImpl::LinkToDeath(const sptr &remote) { auto &manager = RdbManagerImpl::GetInstance(); sptr deathRecipient = new (std::nothrow) RdbManagerImpl::ServiceDeathRecipient(&manager); if (deathRecipient == nullptr) { LOG_ERROR("New ServiceDeathRecipient failed."); - return; + return nullptr; } if (!remote->AddDeathRecipient(deathRecipient)) { LOG_ERROR("Add death recipient failed."); } + return deathRecipient; } RdbManagerImpl::RdbManagerImpl() @@ -129,10 +131,16 @@ std::pair> RdbManagerImpl::GetRdbService(co } sptr serviceBase = rdbService; - LinkToDeath(serviceBase->AsObject()); + auto deathRecipient = LinkToDeath(serviceBase->AsObject()); // the rdbService is not null, so rdbService.GetRefPtr() is not null; - rdbService_ = std::shared_ptr(rdbService.GetRefPtr(), [rdbService](const auto *) {}); + rdbService_ = std::shared_ptr(rdbService.GetRefPtr(), [rdbService, deathRecipient](const auto *) { + sptr serviceBase = rdbService; + serviceBase->AsObject()->RemoveDeathRecipient(deathRecipient); + }); param_ = param; + GlobalResource::RegisterClean(GlobalResource::IPC, []() { + return RdbManagerImpl::GetInstance().CleanUp(); + }); return { E_OK, rdbService_ }; } @@ -144,8 +152,12 @@ void RdbManagerImpl::OnRemoteDied() return; } auto proxy = std::static_pointer_cast(rdbService_); + if (proxy == nullptr) { + return; + } auto observers = proxy->ExportObservers(); auto syncObservers = proxy->ExportSyncObservers(); + proxy->OnRemoteDeadSyncComplete(); ResetServiceHandle(); std::this_thread::sleep_for(std::chrono::seconds(WAIT_TIME)); @@ -168,6 +180,25 @@ void RdbManagerImpl::ResetServiceHandle() rdbService_ = nullptr; } +int32_t RdbManagerImpl::CleanUp() +{ + std::lock_guard lock(mutex_); + if (distributedDataMgr_ != nullptr) { + auto code = distributedDataMgr_->Exit(); + if (code != E_OK) { + LOG_ERROR("Exit failed.code:%{public}d!", code); + return code; + } + } + distributedDataMgr_ = nullptr; + if (rdbService_.use_count() > 1) { + LOG_WARN("RdbService has other in use:%{public}ld!", rdbService_.use_count()); + return E_ERROR; + } + rdbService_ = nullptr; + return E_OK; +} + RdbStoreDataServiceProxy::RdbStoreDataServiceProxy(const sptr &impl) : IRemoteProxy(impl) { @@ -204,7 +235,8 @@ sptr RdbStoreDataServiceProxy::GetFeatureInterface(const std::str return remoteObject; } -int32_t RdbStoreDataServiceProxy::RegisterDeathObserver(const std::string &bundleName, sptr observer) +int32_t RdbStoreDataServiceProxy::RegisterDeathObserver( + const std::string &bundleName, sptr observer, const std::string &featureName) { MessageParcel data; if (!data.WriteInterfaceToken(RdbStoreDataServiceProxy::GetDescriptor())) { @@ -212,7 +244,7 @@ int32_t RdbStoreDataServiceProxy::RegisterDeathObserver(const std::string &bundl return E_ERROR; } - if (!ITypesUtil::Marshal(data, bundleName, observer)) { + if (!ITypesUtil::Marshal(data, bundleName, observer, featureName)) { LOG_ERROR("Write descriptor failed."); return E_ERROR; } @@ -228,6 +260,46 @@ int32_t RdbStoreDataServiceProxy::RegisterDeathObserver(const std::string &bundl int32_t status = E_ERROR; ITypesUtil::Unmarshal(reply, status); + if (status == E_OK) { + clientDeathObserver_ = observer; + } + return status; +} + +int32_t RdbStoreDataServiceProxy::Exit(const std::string &featureName) +{ + MessageParcel data; + if (!data.WriteInterfaceToken(RdbStoreDataServiceProxy::GetDescriptor())) { + LOG_ERROR("Write descriptor failed."); + return E_ERROR; + } + + if (!ITypesUtil::Marshal(data, featureName)) { + LOG_ERROR("Write descriptor failed."); + return E_ERROR; + } + + MessageParcel reply; + MessageOption mo{ MessageOption::TF_SYNC }; + int32_t error = Remote()->SendRequest(static_cast(KvStoreInterfaceCode::FEATURE_EXIT), data, reply, mo); + if (error != 0) { + LOG_ERROR("SendRequest returned %{public}d", error); + return E_ERROR; + } + + int32_t status = E_ERROR; + ITypesUtil::Unmarshal(reply, status); + if (status == E_OK) { + int32_t retry = 0; + while (clientDeathObserver_ != nullptr && clientDeathObserver_->GetSptrRefCount() > 1 && retry < MAX_RETRY) { + retry++; + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + if (clientDeathObserver_ != nullptr && clientDeathObserver_->GetSptrRefCount() > 1) { + LOG_WARN("observer still in use! count:%{public}d", clientDeathObserver_->GetSptrRefCount()); + return E_ERROR; + } + } return status; } } // namespace OHOS::DistributedRdb diff --git a/relational_store/frameworks/native/rdb/src/rdb_obs_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_obs_manager.cpp new file mode 100644 index 00000000..4cf9b09d --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/rdb_obs_manager.cpp @@ -0,0 +1,146 @@ +/* + * 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. + */ + +#define LOG_TAG "RdbObsManager" + +#include "rdb_obs_manager.h" + +#include + +#include "global_resource.h" +#include "logger.h" +#include "obs_mgr_adapter.h" +#include "rdb_errno.h" +#include "sqlite_utils.h" + +namespace OHOS::NativeRdb { +using RdbStoreObserver = DistributedRdb::RdbStoreObserver; +using namespace OHOS::Rdb; +std::mutex RdbObsManager::mutex_; +RdbObsManager::ObsAPIInfo RdbObsManager::apiInfo_; +void *RdbObsManager::handle_ = nullptr; +RdbObsManager::~RdbObsManager() +{ + if (obs_.Empty()) { + return; + } + auto handle = GetApiInfo(); + if (handle.unregisterFunc == nullptr) { + LOG_ERROR("dlsym(Unregister) failed"); + return; + } + obs_.ForEach([handle](const auto &key, auto &value) { + for (auto &obs : value) { + handle.unregisterFunc(key, obs); + } + return false; + }); +} + +RdbObsManager::ObsAPIInfo RdbObsManager::GetApiInfo() +{ + std::lock_guard lock(mutex_); + if (handle_ != nullptr) { + return apiInfo_; + } + handle_ = dlopen("librdb_obs_mgr_adapter.z.so", RTLD_LAZY); + if (handle_ == nullptr) { + LOG_ERROR("dlopen(librdb_obs_mgr_adapter) failed(%{public}d)!", errno); + return apiInfo_; + } + GlobalResource::RegisterClean(GlobalResource::OBS, CleanUp); + apiInfo_.registerFunc = reinterpret_cast(dlsym(handle_, "Register")); + apiInfo_.unregisterFunc = reinterpret_cast(dlsym(handle_, "Unregister")); + apiInfo_.notifyFunc = reinterpret_cast(dlsym(handle_, "NotifyChange")); + apiInfo_.cleanFunc = reinterpret_cast(dlsym(handle_, "CleanUp")); + return apiInfo_; +} + +int32_t RdbObsManager::CleanUp() +{ + auto handle = GetApiInfo(); + if (handle.cleanFunc == nullptr) { + LOG_ERROR("dlsym(CleanUp) fail!"); + return E_ERROR; + } + if (!handle.cleanFunc()) { + return E_ERROR; + } + std::lock_guard lock(mutex_); + dlclose(handle_); + handle_ = nullptr; + apiInfo_.registerFunc = nullptr; + apiInfo_.unregisterFunc = nullptr; + apiInfo_.notifyFunc = nullptr; + apiInfo_.cleanFunc = nullptr; + return E_OK; +} + +int32_t RdbObsManager::Register(const std::string &uri, std::shared_ptr obs) +{ + auto handle = GetApiInfo(); + if (handle.registerFunc == nullptr) { + LOG_ERROR("dlsym(Register) fail!, uri:%{public}s", SqliteUtils::Anonymous(uri).c_str()); + return E_ERROR; + } + auto code = handle.registerFunc(uri, obs); + if (code == E_OK) { + obs_.Compute(uri, [obs](const auto &key, auto &value) { + value.push_back(obs); + return !value.empty(); + }); + return E_OK; + } + return code == RDB_OBS_DUPLICATE_SUB ? E_OK : code; +} + +int32_t RdbObsManager::Unregister(const std::string &uri, std::shared_ptr obs) +{ + auto handle = GetApiInfo(); + if (handle.unregisterFunc == nullptr) { + LOG_ERROR("dlsym(Unregister) fail!, uri:%{public}s", SqliteUtils::Anonymous(uri).c_str()); + return E_ERROR; + } + auto code = handle.unregisterFunc(uri, obs); + if (code != E_OK) { + return code; + } + obs_.Compute(uri, [obs](const auto &key, auto &value) { + if (obs == nullptr) { + value.clear(); + } + for (auto it = value.begin(); it != value.end();) { + if (*it == obs) { + value.erase(it); + break; + } + ++it; + } + return !value.empty(); + }); + return code; +} + +int32_t RdbObsManager::Notify(const std::string &uri) +{ + auto handle = GetApiInfo(); + if (handle.notifyFunc == nullptr) { + LOG_ERROR("dlsym(NotifyChange) fail! uri:%{public}s", SqliteUtils::Anonymous(uri).c_str()); + return E_ERROR; + } + return handle.notifyFunc(uri); +} + +} // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_perfStat.cpp b/relational_store/frameworks/native/rdb/src/rdb_perfStat.cpp new file mode 100644 index 00000000..bf6c2ba8 --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/rdb_perfStat.cpp @@ -0,0 +1,267 @@ +/* + * 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. + */ + +#define LOG_TAG "RdbPerfStat" +#include "rdb_perfStat.h" + +#include + +#include "concurrent_map.h" +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_platform.h" +#include "sqlite_utils.h" +#include "task_executor.h" +namespace OHOS::DistributedRdb { +using namespace OHOS::Rdb; +using namespace OHOS::NativeRdb; +using SqlExecInfo = SqlObserver::SqlExecutionInfo; +std::shared_mutex PerfStat::mutex_; +std::map PerfStat::threadParams_; +ConcurrentMap>> PerfStat::observers_; +ConcurrentMap> PerfStat::execInfos_; +bool PerfStat::enabled_ = false; +std::atomic_uint32_t PerfStat::seqId_ = 0; +int PerfStat::Subscribe(const std::string &storeId, std::shared_ptr observer) +{ + observers_.Compute(storeId, [observer](const auto &, auto &observers) { + observers.insert(observer); + enabled_ = true; + return true; + }); + return E_OK; +} + +int PerfStat::Unsubscribe(const std::string &storeId, std::shared_ptr observer) +{ + observers_.ComputeIfPresent(storeId, [observer](const auto &key, auto &observers) { + observers.erase(observer); + return !observers.empty(); + }); + observers_.DoActionIfEmpty([]() { + enabled_ = false; + execInfos_.Clear(); + std::unique_lock lock(mutex_); + threadParams_.clear(); + }); + return E_OK; +} + +uint32_t PerfStat::GenerateId() +{ + return ++seqId_; +} + +PerfStat::PerfStat(const std::string &storeId, const std::string &sql, int32_t step, uint32_t seqId, size_t size) +{ + if (!enabled_ || IsPaused()) { + return; + } + auto storeObservers = observers_.Find(storeId); + if (!storeObservers.first) { + return; + } + + step_ = step; + key_ = (seqId == 0) ? GetThreadId() : uint64_t(seqId); + time_ = std::chrono::steady_clock::now(); + + if (step == STEP_TOTAL || step == STEP_TRANS || step == STEP_TRANS_END) { + execInfo_ = std::shared_ptr(new (std::nothrow) SqlExecInfo(), GetRelease(step, seqId, storeId)); + execInfos_.Insert(GetThreadId(), execInfo_); + } else { + auto it = execInfos_.Find(key_); + if (it.first) { + execInfo_ = it.second; + } + } + + if (execInfo_ == nullptr && seqId != 0) { + auto it = execInfos_.Find(GetThreadId()); + execInfo_ = it.second; + } + + if (step_ == STEP_TRANS_START && execInfo_ != nullptr) { + execInfos_.Insert(seqId, execInfo_); + } + + if ((step_ == STEP_TOTAL || step_ == STEP_TRANS) && size > 0) { + SetSize(size); + } + + if (step_ == STEP_PREPARE && !sql.empty() && execInfo_ != nullptr) { + FormatSql(sql); + } +} + +PerfStat::~PerfStat() +{ + if (!enabled_ || IsPaused()) { + return; + } + if (execInfo_ == nullptr) { + return; + } + + auto interval = std::chrono::duration_cast(std::chrono::steady_clock::now() - time_); + switch (step_) { + case STEP_WAIT: + execInfo_->waitTime_ += interval.count(); + break; + case STEP_PREPARE: + execInfo_->prepareTime_ += interval.count(); + break; + case STEP_EXECUTE: + execInfo_->executeTime_ += interval.count(); + break; + case STEP_TOTAL: + SetSize(0); + [[fallthrough]]; + case STEP_TOTAL_RES: + execInfo_->totalTime_ += interval.count(); + execInfos_.Erase(key_); + break; + case STEP_TRANS: + execInfo_->totalTime_ += interval.count(); + execInfos_.Erase(GetThreadId()); + SetSize(0); + break; + case STEP_TRANS_END: + execInfo_->totalTime_ += interval.count(); + execInfos_.Erase(GetThreadId()); + execInfo_ = nullptr; + execInfos_.Erase(key_); + break; + default: + execInfo_->totalTime_ += interval.count(); + break; + } +} + +PerfStat::Release PerfStat::GetRelease(int32_t step, uint32_t seqId, const std::string &storeId) +{ + switch (step) { + case STEP_TRANS: + [[fallthrough]]; + case STEP_TRANS_END: + return [seqId](SqlExecInfo *execInfo) { + Merge(seqId, execInfo); + }; + default: + return [seqId, storeId](SqlExecInfo *execInfo) { + Notify(execInfo, storeId); + }; + } +} + +void PerfStat::Merge(uint32_t seqId, SqlExecInfo *execInfo) +{ + if (execInfo == nullptr) { + return; + } + if (execInfo->sql_.empty()) { + delete execInfo; + return; + } + execInfos_.ComputeIfPresent(seqId, [execInfo](const auto &, std::shared_ptr info) { + info->totalTime_ += execInfo->totalTime_; + info->waitTime_ += execInfo->waitTime_; + info->prepareTime_ += execInfo->prepareTime_; + info->executeTime_ += execInfo->executeTime_; + info->sql_.insert(info->sql_.end(), execInfo->sql_.begin(), execInfo->sql_.end()); + return true; + }); + delete execInfo; +} + +void PerfStat::Notify(SqlExecInfo *execInfo, const std::string &storeId) +{ + if (execInfo == nullptr) { + return; + } + if (execInfo->sql_.empty()) { + delete execInfo; + return; + } + auto executor = TaskExecutor::GetInstance().GetExecutor(); + if (executor == nullptr) { + delete execInfo; + return; + } + executor->Execute([info = std::move(*execInfo), storeId]() { + std::set> sqlObservers; + observers_.ComputeIfPresent(storeId, [&sqlObservers](const auto &, auto &observers) { + sqlObservers = observers; + return true; + }); + for (auto &obs : sqlObservers) { + if (obs != nullptr) { + obs->OnStatistic(info); + } + } + }); + delete execInfo; +} +void PerfStat::Pause(uint32_t seqId) +{ + std::unique_lock lock(mutex_); + threadParams_[GetThreadId()].suspenders_ = std::max(1, threadParams_[GetThreadId()].suspenders_ + 1); +} +void PerfStat::Resume(uint32_t seqId) +{ + std::unique_lock lock(mutex_); + threadParams_[GetThreadId()].suspenders_ = std::max(0, threadParams_[GetThreadId()].suspenders_ - 1); +} + +void PerfStat::FormatSql(const std::string &sql) +{ + auto size = GetSize(); + if (size == 0) { + execInfo_->sql_.emplace_back(sql); + return; + } + if (size > 0 && execInfo_->sql_.size() > 0) { + return; + } + size_t firstPos = sql.find("),("); + if (firstPos != std::string::npos) { + std::string newSql = sql.substr(0, firstPos + 1); + newSql.append(",...,").append(std::to_string(size)); + execInfo_->sql_.emplace_back(std::move(newSql)); + return; + } + execInfo_->sql_.emplace_back(sql); +} + +bool PerfStat::IsPaused() +{ + std::shared_lock lock(mutex_); + auto it = threadParams_.find(GetThreadId()); + return it != threadParams_.end() && it->second.suspenders_ > 0; +} + +size_t PerfStat::GetSize() +{ + std::shared_lock lock(mutex_); + auto it = threadParams_.find(GetThreadId()); + return it != threadParams_.end() ? it->second.size_ : 0; +} + +void PerfStat::SetSize(size_t size) +{ + std::unique_lock lock(mutex_); + threadParams_[GetThreadId()].size_ = size; +} +} // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_security_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_security_manager.cpp index 68a0be70..4ef3ae6c 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_security_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_security_manager.cpp @@ -15,6 +15,8 @@ #define LOG_TAG "RdbSecurityManager" #include "rdb_security_manager.h" +#include +#include #include #include #include @@ -25,20 +27,25 @@ #include "directory_ex.h" #include "file_ex.h" -#include "hks_api.h" -#include "hks_param.h" #include "logger.h" #include "rdb_errno.h" #include "rdb_platform.h" #include "rdb_sql_utils.h" +#include "rdb_store_manager.h" #include "sqlite_utils.h" #include "string_utils.h" #include "rdb_fault_hiview_reporter.h" +#include "relational_store_crypt.h" namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; -using Reportor = RdbFaultHiViewReporter; +using Reporter = RdbFaultHiViewReporter; +using CheckRootKeyExistsFunc = int32_t (*)(std::vector &); +using GenerateRootKeyFunc = int32_t (*)(const std::vector &, RDBCryptoFault &); +using EncryptFunc = std::vector (*)(const RDBCryptoParam &, RDBCryptoFault &); +using DecryptFunc = std::vector (*)(const RDBCryptoParam &, RDBCryptoFault &); +using GenerateRandomNumFunc = std::vector (*)(uint32_t); RdbPassword::RdbPassword() = default; @@ -129,311 +136,114 @@ std::string RdbSecurityManager::GetBundleNameByAlias(const std::vector return ""; } -int32_t RdbSecurityManager::HksLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, - const struct HksBlob *inData, struct HksBlob *outData) +RdbSecurityManager::RdbSecurityManager() { - if (outData->size < inData->size * TIMES) { - HksAbort(handle, paramSet); - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_FAIL, GetBundleNameByAlias(), - "HksLoopUpdate out size not enough")); - return HKS_ERROR_INVALID_ARGUMENT; - } + handle_ = nullptr; +}; - struct HksBlob input = { MAX_UPDATE_SIZE, inData->data }; - uint8_t *end = inData->data + inData->size - 1; - outData->size = 0; - struct HksBlob output = { MAX_OUTDATA_SIZE, outData->data }; - while (input.data <= end) { - if (input.data + MAX_UPDATE_SIZE > end) { - input.size = end - input.data + 1; - break; - } - auto result = HksUpdate(handle, paramSet, &input, &output); - if (result != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_FAIL, GetBundleNameByAlias(), - "HksUpdate ret=" + std::to_string(result))); - LOG_ERROR("HksUpdate Failed."); - return HKS_FAILURE; - } - - output.data += output.size; - outData->size += output.size; - input.data += MAX_UPDATE_SIZE; - } - output.size = input.size * TIMES; - auto result = HksFinish(handle, paramSet, &input, &output); - if (result != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_FAIL, GetBundleNameByAlias(), - "HksFinish ret=" + std::to_string(result))); - LOG_ERROR("HksFinish Failed."); - return HKS_FAILURE; - } - outData->size += output.size; - return HKS_SUCCESS; -} - -int32_t RdbSecurityManager::HksEncryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, - const struct HksBlob *plainText, struct HksBlob *cipherText) +RdbSecurityManager::~RdbSecurityManager() { - uint8_t handle[sizeof(uint64_t)] = { 0 }; - struct HksBlob handleBlob = { sizeof(uint64_t), handle }; - int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr); - if (result != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_ENCRYPT_FAIL, - GetBundleNameByAlias(), "Encrypt HksInit ret=" + std::to_string(result))); - LOG_ERROR("HksEncrypt failed with error %{public}d", result); - return result; + if (handle_ != nullptr) { + dlclose(handle_); + handle_ = nullptr; } - return HksLoopUpdate(&handleBlob, paramSet, plainText, cipherText); } -int32_t RdbSecurityManager::HksDecryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, - const struct HksBlob *cipherText, struct HksBlob *plainText) -{ - uint8_t handle[sizeof(uint64_t)] = { 0 }; - struct HksBlob handleBlob = { sizeof(uint64_t), handle }; - int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr); - if (result != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(), - "Decrypt HksInit ret=" + std::to_string(result))); - LOG_ERROR("HksEncrypt failed with error %{public}d", result); - return result; - } - result = HksLoopUpdate(&handleBlob, paramSet, cipherText, plainText); - if (result != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(), - "Decrypt HksLoopUpdate ret=" + std::to_string(result))); - } - return result; -} - -RdbSecurityManager::RdbSecurityManager() - : nonce_(RDB_HKS_BLOB_TYPE_NONCE, RDB_HKS_BLOB_TYPE_NONCE + strlen(RDB_HKS_BLOB_TYPE_NONCE)), - aad_(RDB_HKS_BLOB_TYPE_AAD, RDB_HKS_BLOB_TYPE_AAD + strlen(RDB_HKS_BLOB_TYPE_AAD)) {}; - -RdbSecurityManager::~RdbSecurityManager() = default; - std::vector RdbSecurityManager::GenerateRandomNum(int32_t len) { - std::random_device randomDevice; - std::uniform_int_distribution distribution(0, std::numeric_limits::max()); - std::vector key(len); - for (int32_t i = 0; i < len; i++) { - key[i] = static_cast(distribution(randomDevice)); + auto handle = GetHandle(); + if (handle == nullptr) { + return {}; } - return key; + auto generateRandomNum = reinterpret_cast(dlsym(handle, "generateRandomNum")); + if (generateRandomNum == nullptr) { + LOG_ERROR("dlsym GenerateRandomNum failed(%{public}d)!", errno); + return {}; + } + auto rootKeyAlias = GetRootKeyAlias(); + auto ret = generateRandomNum(len); + return ret; } bool RdbSecurityManager::SaveSecretKeyToFile(const std::string &keyFile, const std::vector &workey) { LOG_INFO("begin keyFile%{public}s.", SqliteUtils::Anonymous(keyFile).c_str()); if (!HasRootKey()) { - Reportor::ReportFault(RdbFaultEvent(FT_OPEN, E_ROOT_KEY_NOT_LOAD, GetBundleNameByAlias(), "not root key")); + Reporter::ReportFault(RdbFaultEvent(FT_OPEN, E_ROOT_KEY_NOT_LOAD, GetBundleNameByAlias(), "not root key")); LOG_ERROR("Root key not exists!"); return false; } + std::vector key = workey.empty() ? GenerateRandomNum(RDB_KEY_SIZE) : workey; + if (key.empty()) { + return false; + } RdbSecretKeyData keyData; keyData.timeValue = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now()); - keyData.distributed = 0; - keyData.secretKey = EncryptWorkKey(key); - - if (keyData.secretKey.empty()) { - Reportor::ReportFault(RdbFaultEvent(FT_OPEN, E_WORK_KEY_FAIL, GetBundleNameByAlias(), "key is empty")); + std::vector keyContent; + keyContent.push_back(char(keyData.distributed)); + keyContent.insert(keyContent.end(), reinterpret_cast(&keyData.timeValue), + reinterpret_cast(&keyData.timeValue) + sizeof(keyData.timeValue)); + keyContent.insert(keyContent.end(), key.begin(), key.end()); + auto [res, secretContent] = EncryptWorkKey(keyContent); + if (!res) { + LOG_ERROR("EncryptWorkKey failed, keyFile%{public}s", SqliteUtils::Anonymous(keyFile).c_str()); + keyContent.assign(keyContent.size(), 0); + key.assign(key.size(), 0); + return false; + } + if (secretContent.encryptValue.empty()) { + Reporter::ReportFault(RdbFaultEvent(FT_OPEN, E_WORK_KEY_FAIL, GetBundleNameByAlias(), "key is empty")); LOG_ERROR("Key size is 0"); + keyContent.assign(keyContent.size(), 0); key.assign(key.size(), 0); return false; } + keyContent.assign(keyContent.size(), 0); key.assign(key.size(), 0); - return SaveSecretKeyToDisk(keyFile, keyData); + auto keyFileOld = ReplaceSuffix(keyFile); + auto ret = SaveSecretKeyToDisk(keyFile, secretContent); + if (!ret) { + LOG_ERROR("Save key to file fail, ret:%{public}d", ret); + return false; + } + return SqliteUtils::DeleteFile(keyFileOld); } -bool RdbSecurityManager::SaveSecretKeyToDisk(const std::string &keyPath, RdbSecretKeyData &keyData) +bool RdbSecurityManager::SaveSecretKeyToDisk(const std::string &keyPath, const RdbSecretContent &secretContent) { LOG_INFO("begin keyPath:%{public}s.", SqliteUtils::Anonymous(keyPath).c_str()); - std::vector distributedInByte = { &keyData.distributed, &keyData.distributed + sizeof(uint8_t) }; - std::vector timeInByte = { reinterpret_cast(&keyData.timeValue), - reinterpret_cast(&keyData.timeValue) + sizeof(time_t) }; - std::vector secretKeyInChar; - secretKeyInChar.insert(secretKeyInChar.end(), distributedInByte.begin(), distributedInByte.end()); - secretKeyInChar.insert(secretKeyInChar.end(), timeInByte.begin(), timeInByte.end()); - secretKeyInChar.insert(secretKeyInChar.end(), keyData.secretKey.begin(), keyData.secretKey.end()); + std::string secretKeyInString; + secretKeyInString.append(reinterpret_cast(&secretContent.magicNum), sizeof(uint32_t)); + secretKeyInString.append( + reinterpret_cast(secretContent.nonceValue.data()), secretContent.nonceValue.size()); + secretKeyInString.append( + reinterpret_cast(secretContent.encryptValue.data()), secretContent.encryptValue.size()); bool ret; { std::lock_guard lock(mutex_); - ret = SaveBufferToFile(keyPath, secretKeyInChar); + auto fd = open(keyPath.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + ret = SaveStringToFd(fd, secretKeyInString); + if (fd >= 0) { + close(fd); + } } if (!ret) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_FAIL, GetBundleNameByAlias(), - "save fail errno=" + std::to_string(errno))); + Reporter::ReportFault(RdbFaultEvent( + FT_EX_FILE, E_WORK_KEY_FAIL, GetBundleNameByAlias(), "save fail errno=" + std::to_string(errno))); } return ret; } -int RdbSecurityManager::GenerateRootKey(const std::vector &rootKeyAlias) -{ - LOG_INFO("RDB GenerateRootKey begin."); - std::vector tempRootKeyAlias = rootKeyAlias; - struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), tempRootKeyAlias.data() }; - struct HksParamSet *params = nullptr; - int32_t ret = HksInitParamSet(¶ms); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_ROOT_KEY_FAULT, GetBundleNameByAlias(rootKeyAlias), - "generator root key, HksInitParamSet ret=" + std::to_string(ret))); - LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret); - return ret; - } - - struct HksParam hksParam[] = { - { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, - { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, - { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, - { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, - { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, - { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, - { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, - }; - - ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_ROOT_KEY_FAULT, GetBundleNameByAlias(rootKeyAlias), - "HksAddParams ret=" + std::to_string(ret))); - LOG_ERROR("HksAddParams-client failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return ret; - } - - ret = HksBuildParamSet(¶ms); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_ROOT_KEY_FAULT, GetBundleNameByAlias(rootKeyAlias), - "HksBuildParamSet ret=" + std::to_string(ret))); - LOG_ERROR("HksBuildParamSet-client failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return ret; - } - - ret = HksGenerateKey(&rootKeyName, params, nullptr); - HksFreeParamSet(¶ms); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_ROOT_KEY_FAULT, GetBundleNameByAlias(rootKeyAlias), - "HksGenerateKey ret=" + std::to_string(ret))); - LOG_ERROR("HksGenerateKey-client failed with error %{public}d", ret); - } - return ret; -} - -std::vector RdbSecurityManager::EncryptWorkKey(std::vector &key) -{ - std::vector rootKeyAlias = GetRootKeyAlias(); - struct HksBlob blobAad = { uint32_t(aad_.size()), aad_.data() }; - struct HksBlob blobNonce = { uint32_t(nonce_.size()), nonce_.data() }; - struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), rootKeyAlias.data() }; - struct HksBlob plainKey = { uint32_t(key.size()), key.data() }; - struct HksParamSet *params = nullptr; - int32_t ret = HksInitParamSet(¶ms); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_ENCRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias), - "Encrypt HksInitParamSet ret=" + std::to_string(ret))); - LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret); - return {}; - } - struct HksParam hksParam[] = {{ .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, - { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT }, - { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, - { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, - { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, - { .tag = HKS_TAG_NONCE, .blob = blobNonce }, - { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, - { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }}; - - ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_ENCRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias), - "Encrypt HksAddParams ret=" + std::to_string(ret))); - LOG_ERROR("HksAddParams failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return {}; - } - - ret = HksBuildParamSet(¶ms); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_ENCRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias), - "Encrypt HksBuildParamSet ret=" + std::to_string(ret))); - LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return {}; - } - std::vector encryptedKey(plainKey.size * TIMES + 1); - struct HksBlob cipherText = { uint32_t(encryptedKey.size()), encryptedKey.data() }; - ret = HksEncryptThreeStage(&rootKeyName, params, &plainKey, &cipherText); - (void)HksFreeParamSet(¶ms); - if (ret != HKS_SUCCESS) { - encryptedKey.assign(encryptedKey.size(), 0); - LOG_ERROR("HksEncrypt failed with error %{public}d", ret); - return {}; - } - encryptedKey.resize(cipherText.size); - return encryptedKey; -} - -bool RdbSecurityManager::DecryptWorkKey(std::vector &source, std::vector &key) +void RdbSecurityManager::ReportCryptFault(int32_t code, const std::string &message) { - std::vector rootKeyAlias = GetRootKeyAlias(); - struct HksBlob blobAad = { uint32_t(aad_.size()), &(aad_[0]) }; - struct HksBlob blobNonce = { uint32_t(nonce_.size()), &(nonce_[0]) }; - struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), &(rootKeyAlias[0]) }; - struct HksBlob encryptedKeyBlob = { uint32_t(source.size() - AEAD_LEN), source.data() }; - struct HksBlob blobAead = { AEAD_LEN, source.data() + source.size() - AEAD_LEN }; - struct HksParamSet *params = nullptr; - int32_t ret = HksInitParamSet(¶ms); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias), - "HksInitParamSet ret=" + std::to_string(ret))); - LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret); - return false; - } - struct HksParam hksParam[] = { - { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, - { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }, - { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, - { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, - { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, - { .tag = HKS_TAG_NONCE, .blob = blobNonce }, - { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, - { .tag = HKS_TAG_AE_TAG, .blob = blobAead }, - { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, - }; - ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias), - "HksAddParams ret=" + std::to_string(ret))); - LOG_ERROR("HksAddParams failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return false; - } - - ret = HksBuildParamSet(¶ms); - if (ret != HKS_SUCCESS) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_HUKS, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(rootKeyAlias), - "HksBuildParamSet ret=" + std::to_string(ret))); - LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return false; - } - key.resize(encryptedKeyBlob.size * TIMES + 1); - struct HksBlob plainKeyBlob = { uint32_t(key.size()), key.data() }; - ret = HksDecryptThreeStage(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob); - (void)HksFreeParamSet(¶ms); - if (ret != HKS_SUCCESS) { - key.assign(key.size(), 0); - LOG_ERROR("HksDecrypt failed with error %{public}d", ret); - return false; + if (message.empty()) { + return; } - key.resize(plainKeyBlob.size); - return true; + Reporter::ReportFault(RdbFaultEvent(FT_EX_HUKS, code, GetBundleNameByAlias(), message)); } int32_t RdbSecurityManager::Init(const std::string &bundleName) @@ -465,44 +275,85 @@ int32_t RdbSecurityManager::Init(const std::string &bundleName) int32_t RdbSecurityManager::CheckRootKeyExists(std::vector &rootKeyAlias) { - LOG_DEBUG("RDB checkRootKeyExist begin."); - struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), rootKeyAlias.data() }; - struct HksParamSet *params = nullptr; - int32_t ret = HksInitParamSet(¶ms); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret); - return ret; - } - - struct HksParam hksParam[] = { - { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, - { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, - { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, - { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, - { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, - { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, - { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, - }; - - ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksAddParams failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return ret; - } - - ret = HksBuildParamSet(¶ms); - if (ret != HKS_SUCCESS) { - LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); - HksFreeParamSet(¶ms); - return ret; - } - - ret = HksKeyExist(&rootKeyName, params); - HksFreeParamSet(¶ms); + auto handle = GetHandle(); + if (handle == nullptr) { + return E_NOT_SUPPORT; + } + auto creatorCheck = reinterpret_cast(dlsym(handle, "checkRootKeyExists")); + if (creatorCheck == nullptr) { + LOG_ERROR("CheckRootKeyExists failed(%{public}d)!", errno); + return E_NOT_SUPPORT; + } + return creatorCheck(rootKeyAlias); +} + +int32_t RdbSecurityManager::GenerateRootKey(const std::vector &rootKeyAlias) +{ + auto handle = GetHandle(); + if (handle == nullptr) { + return E_NOT_SUPPORT; + } + RDBCryptoFault rdbFault; + auto generateRootKey = reinterpret_cast(dlsym(handle, "generateRootKey")); + if (generateRootKey == nullptr) { + LOG_ERROR("dlsym GenerateRootKey failed(%{public}d)!", errno); + return E_NOT_SUPPORT; + } + auto ret = generateRootKey(rootKeyAlias, rdbFault); + ReportCryptFault(rdbFault.code, rdbFault.message); return ret; } +std::pair RdbSecurityManager::EncryptWorkKey(const std::vector &key) +{ + RdbSecretContent rdbSecretContent; + auto handle = GetHandle(); + if (handle == nullptr) { + return { false, rdbSecretContent }; + } + RDBCryptoFault rdbFault; + auto encrypt = reinterpret_cast(dlsym(handle, "encrypt")); + if (encrypt == nullptr) { + LOG_ERROR("dlsym Encrypt failed(%{public}d)!", errno); + return { false, rdbSecretContent }; + } + auto rootKeyAlias = GetRootKeyAlias(); + RDBCryptoParam param; + param.KeyValue = key; + param.rootAlias = rootKeyAlias; + param.nonceValue = GenerateRandomNum(RdbSecretContent::NONCE_VALUE_SIZE); + if (param.nonceValue.empty()) { + return { false, rdbSecretContent }; + } + auto encryptKey = encrypt(param, rdbFault); + rdbSecretContent.nonceValue = param.nonceValue; + rdbSecretContent.encryptValue = encryptKey; + ReportCryptFault(rdbFault.code, rdbFault.message); + return { true, rdbSecretContent }; +} + +std::vector RdbSecurityManager::DecryptWorkKey( + const std::vector &key, const std::vector &nonce) +{ + auto handle = GetHandle(); + if (handle == nullptr) { + return {}; + } + RDBCryptoFault rdbFault; + auto decrypt = reinterpret_cast(dlsym(handle, "decrypt")); + if (decrypt == nullptr) { + LOG_ERROR("dlsym Decrypt failed(%{public}d)!", errno); + return {}; + } + RDBCryptoParam param; + param.KeyValue = key; + param.nonceValue = nonce; + param.rootAlias = GetRootKeyAlias(); + auto decryptKey = decrypt(param, rdbFault); + ReportCryptFault(rdbFault.code, rdbFault.message); + return decryptKey; +} + bool RdbSecurityManager::InitPath(const std::string &fileDir) { constexpr mode_t DEFAULT_UMASK = 0002; @@ -512,11 +363,11 @@ bool RdbSecurityManager::InitPath(const std::string &fileDir) umask(DEFAULT_UMASK); auto ret = MkDir(fileDir, (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); if (ret != 0 && errno != EEXIST) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_FAIL, + Reporter::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_FAIL, RdbSecurityManager::GetInstance().GetBundleNameByAlias(), "mkdir err, ret=" + std::to_string(ret) + ",errno=" + std::to_string(errno) + ",fileDir=" + SqliteUtils::Anonymous(fileDir))); - LOG_ERROR("mkdir error:%{public}d, dbDir:%{public}s", errno, SqliteUtils::Anonymous(fileDir).c_str()); + LOG_ERROR("mkdir error:%{public}d, area:%{public}s", errno, SqliteUtils::GetArea(fileDir).c_str()); return false; } return true; @@ -524,82 +375,78 @@ bool RdbSecurityManager::InitPath(const std::string &fileDir) RdbPassword RdbSecurityManager::LoadSecretKeyFromFile(const std::string &keyFile) { - auto ret = access(keyFile.c_str(), F_OK); - if (ret != 0) { - auto anonymousFile = SqliteUtils::Anonymous(keyFile); - Reportor::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(), - "access " + anonymousFile + " fail, ret=" + std::to_string(ret) + ",errno=" + std::to_string(errno))); - LOG_ERROR("Not exists. errno:%{public}d, file:%{public}s", errno, anonymousFile.c_str()); - return {}; - } - + auto keyFileOld = ReplaceSuffix(keyFile); + RdbPassword rdbPasswd; RdbSecretKeyData keyData; - if (!LoadSecretKeyFromDisk(keyFile, keyData)) { - Reportor::ReportFault(RdbFaultEvent(FT_OPEN, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(), - "LoadSecretKeyFromDisk fail,errno=" + std::to_string(errno))); - LOG_ERROR("Load key failed."); - return {}; + if (access(keyFile.c_str(), F_OK) == 0) { + if (LoadSecretKeyFromDiskV1(keyFile, keyData) && !keyData.secretKey.empty()) { + rdbPasswd.isKeyExpired = IsKeyExpired(keyData.timeValue); + rdbPasswd.SetValue(keyData.secretKey.data(), keyData.secretKey.size()); + return rdbPasswd; + } } - - std::vector key; - if (!DecryptWorkKey(keyData.secretKey, key)) { - Reportor::ReportFault(RdbFaultEvent(FT_OPEN, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(), - "DecryptWorkKey fail,errno=" + std::to_string(errno))); - LOG_ERROR("Decrypt key failed!"); - return {}; + if (LoadSecretKeyFromDisk(keyFileOld, keyData) && !keyData.secretKey.empty()) { + rdbPasswd.isKeyExpired = IsKeyExpired(keyData.timeValue); + rdbPasswd.SetValue(keyData.secretKey.data(), keyData.secretKey.size()); + return rdbPasswd; } - - RdbPassword rdbPasswd; - rdbPasswd.isKeyExpired = IsKeyExpired(keyData.timeValue); - rdbPasswd.SetValue(key.data(), key.size()); - key.assign(key.size(), 0); - return rdbPasswd; + return {}; } bool RdbSecurityManager::LoadSecretKeyFromDisk(const std::string &keyPath, RdbSecretKeyData &keyData) { - LOG_DEBUG("begin keyPath:%{public}s.", SqliteUtils::Anonymous(keyPath).c_str()); std::vector content; { std::lock_guard lock(mutex_); if (!LoadBufferFromFile(keyPath, content) || content.empty()) { - Reportor::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(), + Reporter::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(), "LoadBufferFromFile fail, errno=" + std::to_string(errno))); LOG_ERROR("LoadBufferFromFile failed!"); return false; } } - - auto size = content.size(); - std::size_t offset = 0; - auto iter = content.begin(); - if (offset + 1 >= static_cast(size)) { + auto [res, rdbSecretContent] = UnpackV1(content); + if (!res) { + LOG_ERROR("UnpackV1 failed:%{public}s.", SqliteUtils::Anonymous(keyPath).c_str()); return false; } - keyData.distributed = *iter; - iter++; - offset++; - - std::vector createTime; - if (offset + static_cast(sizeof(time_t) / sizeof(uint8_t)) >= size) { + std::tie(res, keyData) = DecryptV1(rdbSecretContent); + if (!res) { + LOG_ERROR("DecryptV1 failed:%{public}s.", SqliteUtils::Anonymous(keyPath).c_str()); return false; } - offset += sizeof(time_t) / sizeof(uint8_t); - for (std::size_t i = 0; i < sizeof(time_t) / sizeof(uint8_t); i++) { - createTime.push_back(*iter); - iter++; + std::string keyPathV1; + std::string oldSuffix = std::string(SUFFIX_PUB_KEY_OLD); + if (keyPath.length() >= oldSuffix.length() && + keyPath.compare(keyPath.length() - oldSuffix.length(), oldSuffix.length(), oldSuffix) == 0) { + keyPathV1 = keyPath.substr(0, keyPath.length() - oldSuffix.length()) + SUFFIX_PUB_KEY; } + SaveSecretKeyToFile(keyPathV1, keyData.secretKey); + return true; +} - if (createTime.size() == sizeof(time_t)) { - keyData.timeValue = *reinterpret_cast(&createTime[0]); +bool RdbSecurityManager::LoadSecretKeyFromDiskV1(const std::string &keyPath, RdbSecretKeyData &keyData) +{ + std::vector content; + { + std::lock_guard lock(mutex_); + if (!LoadBufferFromFile(keyPath, content) || content.empty()) { + Reporter::ReportFault(RdbFaultEvent(FT_EX_FILE, E_WORK_KEY_DECRYPT_FAIL, GetBundleNameByAlias(), + "LoadBufferFromFile fail, errno=" + std::to_string(errno))); + LOG_ERROR("LoadBufferFromFile failed!"); + return false; + } } - - if (offset + AEAD_LEN >= static_cast(size)) { + auto [res, rdbSecretContent] = UnpackV2(content); + if (!res) { + LOG_ERROR("UnpackV2 failed:%{public}s.", SqliteUtils::Anonymous(keyPath).c_str()); + return false; + } + std::tie(res, keyData) = DecryptV2(rdbSecretContent); + if (!res) { + LOG_ERROR("DecryptV2 failed:%{public}s.", SqliteUtils::Anonymous(keyPath).c_str()); return false; } - offset = size; - keyData.secretKey.insert(keyData.secretKey.end(), iter, content.end()); - return true; } @@ -607,8 +454,9 @@ RdbPassword RdbSecurityManager::GetRdbPassword(const std::string &dbPath, KeyFil { KeyFiles keyFiles(dbPath); keyFiles.Lock(); - auto &keyFile = keyFiles.GetKeyFile(keyFileType); - if (IsKeyFileEmpty(keyFile)) { + auto keyFile = keyFiles.GetKeyFile(keyFileType); + auto keyFileOld = ReplaceSuffix(keyFile); + if (IsKeyFileEmpty(keyFile) && IsKeyFileEmpty(keyFileOld)) { keyFiles.InitKeyPath(); if (!SaveSecretKeyToFile(keyFile)) { keyFiles.Unlock(); @@ -616,8 +464,9 @@ RdbPassword RdbSecurityManager::GetRdbPassword(const std::string &dbPath, KeyFil return {}; } } + auto rdbPassword = LoadSecretKeyFromFile(keyFile); keyFiles.Unlock(); - return LoadSecretKeyFromFile(keyFile); + return rdbPassword; } std::vector RdbSecurityManager::GenerateRootKeyAlias(const std::string &bundlename) @@ -641,6 +490,8 @@ void RdbSecurityManager::DelAllKeyFiles(const std::string &dbPath) std::lock_guard lock(mutex_); SqliteUtils::DeleteFile(keyFiles.GetKeyFile(PUB_KEY_FILE)); SqliteUtils::DeleteFile(keyFiles.GetKeyFile(PUB_KEY_FILE_NEW_KEY)); + SqliteUtils::DeleteFile(ReplaceSuffix(keyFiles.GetKeyFile(PUB_KEY_FILE))); + SqliteUtils::DeleteFile(ReplaceSuffix(keyFiles.GetKeyFile(PUB_KEY_FILE_NEW_KEY))); } keyFiles.Unlock(); keyFiles.DestroyLock(); @@ -700,6 +551,18 @@ bool RdbSecurityManager::HasRootKey() return hasRootKey_; } +void* RdbSecurityManager::GetHandle() +{ + std::lock_guard lock(handleMutex_); + if (handle_ == nullptr) { + handle_ = dlopen("librelational_store_crypt.z.so", RTLD_LAZY); + if (handle_ == nullptr) { + LOG_ERROR("crypto dlopen failed errno is %{public}d", errno); + } + } + return handle_; +} + bool RdbSecurityManager::IsKeyFileEmpty(const std::string &keyFile) { struct stat fileInfo; @@ -728,13 +591,116 @@ int32_t RdbSecurityManager::RestoreKeyFile(const std::string &dbPath, const std: return E_OK; } +std::pair RdbSecurityManager::UnpackV1(const std::vector &content) +{ + RdbSecretContent rdbSecretContent; + rdbSecretContent.magicNum = 0; + rdbSecretContent.nonceValue = { RDB_HKS_BLOB_TYPE_NONCE, + RDB_HKS_BLOB_TYPE_NONCE + strlen(RDB_HKS_BLOB_TYPE_NONCE) }; + rdbSecretContent.encryptValue = { content.begin(), content.end() }; + return { true, rdbSecretContent }; +} + +std::pair RdbSecurityManager::UnpackV2(const std::vector &content) +{ + std::pair result; + auto &[res, rdbSecretContent] = result; + rdbSecretContent.magicNum = RdbSecretContent::MAGIC_NUMBER_V2; + res = false; + auto size = content.size(); + std::size_t offset = sizeof(rdbSecretContent.magicNum); + if (offset >= static_cast(size)) { + return result; + } + if (offset + RdbSecretContent::NONCE_VALUE_SIZE >= static_cast(size)) { + return result; + } + rdbSecretContent.nonceValue = { content.begin() + offset, + content.begin() + offset + RdbSecretContent::NONCE_VALUE_SIZE }; + offset += RdbSecretContent::NONCE_VALUE_SIZE; + rdbSecretContent.encryptValue = { content.begin() + offset, content.end() }; + res = true; + return result; +} + +std::pair RdbSecurityManager::DecryptV1(const RdbSecretContent &content) +{ + RdbSecretKeyData keyData; + auto size = content.encryptValue.size(); + std::size_t offset = 0; + auto iter = content.encryptValue.begin(); + if (offset + 1 >= static_cast(size)) { + return { false, keyData }; + } + keyData.distributed = *iter; + iter++; + offset++; + + std::vector createTime; + if (offset + static_cast(sizeof(time_t) / sizeof(uint8_t)) >= size) { + return { false, keyData }; + } + offset += sizeof(time_t) / sizeof(uint8_t); + for (std::size_t i = 0; i < sizeof(time_t) / sizeof(uint8_t); i++) { + createTime.push_back(*iter); + iter++; + } + + if (createTime.size() == sizeof(time_t)) { + keyData.timeValue = *reinterpret_cast(&createTime[0]); + } + + if (offset + AEAD_LEN >= static_cast(size)) { + return { false, keyData }; + } + std::vector key = { iter, content.encryptValue.end() }; + keyData.secretKey = DecryptWorkKey(key, content.nonceValue); + key.assign(key.size(), 0); + return { true, keyData }; +} + +std::pair RdbSecurityManager::DecryptV2(const RdbSecretContent &content) +{ + RdbSecretKeyData keyData; + std::vector value = DecryptWorkKey(content.encryptValue, content.nonceValue); + std::shared_ptr autoClean = + std::shared_ptr("autoClean", [&value](const char *) mutable { value.assign(value.size(), 0); }); + auto size = value.size(); + std::size_t offset = 0; + auto iter = value.begin(); + if (offset + 1 >= static_cast(size)) { + return { false, keyData }; + } + keyData.distributed = *iter; + iter++; + offset++; + + std::vector createTime; + if (offset + static_cast(sizeof(time_t) / sizeof(uint8_t)) >= size) { + return { false, keyData }; + } + offset += sizeof(time_t) / sizeof(uint8_t); + for (std::size_t i = 0; i < sizeof(time_t) / sizeof(uint8_t); i++) { + createTime.push_back(*iter); + iter++; + } + + if (createTime.size() == sizeof(time_t)) { + keyData.timeValue = *reinterpret_cast(&createTime[0]); + } + + if (offset + AEAD_LEN >= static_cast(size)) { + return { false, keyData }; + } + keyData.secretKey = { iter, value.end() }; + return { true, keyData }; +} + RdbSecurityManager::KeyFiles::KeyFiles(const std::string &dbPath, bool openFile) { const std::string dbKeyDir = StringUtils::ExtractFilePath(dbPath) + "key/"; const std::string lockDir = StringUtils::ExtractFilePath(dbPath) + "lock/"; - if (!InitPath(lockDir)) { - LOG_ERROR("lockDir failed, errno:%{public}d, dir:%{public}s.", errno, SqliteUtils::Anonymous(lockDir).c_str()); - } + bool isDirCreate = InitPath(lockDir); const std::string dbName = RemoveSuffix(StringUtils::ExtractFileName(dbPath)); lock_ = lockDir + dbName + SUFFIX_KEY_LOCK; keys_[PUB_KEY_FILE] = dbKeyDir + dbName + SUFFIX_PUB_KEY; @@ -742,8 +708,8 @@ RdbSecurityManager::KeyFiles::KeyFiles(const std::string &dbPath, bool openFile) if (!openFile) { return; } - lockFd_ = open(lock_.c_str(), O_RDONLY | O_CREAT, S_IRWXU | S_IRWXG); - if (lockFd_ < 0) { + lockFd_ = open(lock_.c_str(), O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (lockFd_ < 0 && isDirCreate) { LOG_WARN("open failed, errno:%{public}d, file:%{public}s.", errno, SqliteUtils::Anonymous(lock_).c_str()); } } @@ -774,17 +740,19 @@ int32_t RdbSecurityManager::KeyFiles::InitKeyPath() return E_OK; } -int32_t RdbSecurityManager::KeyFiles::Lock() +int32_t RdbSecurityManager::KeyFiles::Lock(bool isBlock) { if (lockFd_ < 0) { return E_INVALID_FILE_PATH; } int32_t errCode; + int lockType = isBlock ? LOCK_EX : LOCK_EX | LOCK_NB; do { - errCode = flock(lockFd_, LOCK_EX); + errCode = flock(lockFd_, lockType); } while (errCode < 0 && errno == EINTR); if (errCode < 0) { - LOG_WARN("lock failed, errno:%{public}d, dir:%{public}s.", errno, SqliteUtils::Anonymous(lock_).c_str()); + LOG_WARN("lock failed, type:%{public}d, errno:%{public}d, dir:%{public}s.", lockType, errno, + SqliteUtils::Anonymous(lock_).c_str()); return E_ERROR; } return E_OK; @@ -815,5 +783,19 @@ int32_t RdbSecurityManager::KeyFiles::DestroyLock() SqliteUtils::DeleteFile(lock_); return E_OK; } + +std::string RdbSecurityManager::ReplaceSuffix(const std::string &str) +{ + std::string oldSuffix = std::string(SUFFIX_PUB_KEY); + std::string newSuffix = std::string(SUFFIX_PUB_KEY_NEW); + if (str.length() >= oldSuffix.length() && + str.compare(str.length() - oldSuffix.length(), oldSuffix.length(), oldSuffix) == 0) { + return str.substr(0, str.length() - oldSuffix.length()) + SUFFIX_PUB_KEY_OLD; + } else if (str.length() >= newSuffix.length() && + str.compare(str.length() - newSuffix.length(), newSuffix.length(), newSuffix) == 0) { + return str.substr(0, str.length() - newSuffix.length()) + SUFFIX_PUB_TMP_NEW_KEY; + } + return str; +} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp index dacd16bc..a8a3b9c3 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp @@ -15,6 +15,7 @@ #define LOG_TAG "RdbServiceProxy" #include "rdb_service_proxy.h" +#include #include "itypes_util.h" #include "logger.h" #include "result_set_proxy.h" @@ -24,7 +25,7 @@ namespace OHOS::DistributedRdb { using namespace OHOS::Rdb; using SqliteUtils = OHOS::NativeRdb::SqliteUtils; using RdbServiceCode = OHOS::DistributedRdb::RelationalStore::RdbServiceInterfaceCode; - +constexpr int32_t MAX_RETRY = 100; #define IPC_SEND(code, reply, ...) \ ({ \ int32_t __status = RDB_OK; \ @@ -56,9 +57,18 @@ RdbServiceProxy::RdbServiceProxy(const sptr &object) remote_ = Remote(); } -std::string RdbServiceProxy::ObtainDistributedTableName(const std::string &device, const std::string &table) +std::string RdbServiceProxy::ObtainDistributedTableName( + const RdbSyncerParam ¶m, const std::string &device, const std::string &table) { - return ""; + MessageParcel reply; + int32_t status = + IPC_SEND(static_cast(RdbServiceCode::RDB_SERVICE_CMD_OBTAIN_TABLE), reply, param, device, table); + std::string distributedTableName; + if (status != RDB_OK || !ITypesUtil::Unmarshal(reply, distributedTableName)) { + LOG_ERROR("status:%{public}d, device:%{public}s, table:%{public}s", status, + SqliteUtils::Anonymous(device).c_str(), SqliteUtils::Anonymous(table).c_str()); + } + return distributedTableName; } int32_t RdbServiceProxy::InitNotifier(const RdbSyncerParam ¶m) @@ -209,7 +219,7 @@ std::string RdbServiceProxy::RemoveSuffix(const std::string &name) } int32_t RdbServiceProxy::Subscribe( - const RdbSyncerParam ¶m, const SubscribeOption &option, RdbStoreObserver *observer) + const RdbSyncerParam ¶m, const SubscribeOption &option, std::shared_ptr observer) { if (observer == nullptr) { return RDB_ERROR; @@ -224,7 +234,7 @@ int32_t RdbServiceProxy::Subscribe( auto name = RemoveSuffix(param.storeName_); observers_.Compute(name, [observer, ¶m, &option](const auto &key, std::list &value) { for (const auto &element : value) { - if (element.observer == observer) { + if (element.observer.lock() == observer) { LOG_ERROR("duplicate observer, storeName:%{public}s", SqliteUtils::Anonymous(key).c_str()); return true; } @@ -247,7 +257,7 @@ int32_t RdbServiceProxy::DoSubscribe(const RdbSyncerParam ¶m, const Subscrib } int32_t RdbServiceProxy::UnSubscribe( - const RdbSyncerParam ¶m, const SubscribeOption &option, RdbStoreObserver *observer) + const RdbSyncerParam ¶m, const SubscribeOption &option, std::shared_ptr observer) { if (observer == nullptr) { LOG_ERROR("observer is null."); @@ -259,7 +269,7 @@ int32_t RdbServiceProxy::UnSubscribe( auto name = RemoveSuffix(param.storeName_); observers_.ComputeIfPresent(name, [observer](const auto &key, std::list &value) { LOG_INFO("before remove size=%{public}d", static_cast(value.size())); - value.remove_if([observer](const ObserverParam ¶m) { return param.observer == observer; }); + value.remove_if([observer](const ObserverParam ¶m) { return param.observer.lock() == observer; }); LOG_INFO("after remove size=%{public}d", static_cast(value.size())); return !(value.empty()); }); @@ -323,7 +333,7 @@ void RdbServiceProxy::ImportObservers(Observers &observers) for (const auto ¶m : value) { syncerParam.bundleName_ = param.bundleName; syncerParam.storeName_ = key; - Subscribe(syncerParam, param.subscribeOption, param.observer); + Subscribe(syncerParam, param.subscribeOption, param.observer.lock()); } return false; }); @@ -504,12 +514,31 @@ void RdbServiceProxy::OnDataChange( const auto &key, const std::list &value) mutable { auto size = value.size(); for (const auto ¶ms : value) { - params.observer->OnChange(origin, primaries, --size > 0 ? ChangeInfo(info) : std::move(info)); + auto obs = params.observer.lock(); + size--; + if (obs != nullptr) { + obs->OnChange(origin, primaries, size > 0 ? ChangeInfo(info) : std::move(info)); + } } return !value.empty(); }); } +void RdbServiceProxy::OnRemoteDeadSyncComplete() +{ + std::map result; + result.insert(std::pair("", {Progress::SYNC_FINISH, ProgressCode::UNKNOWN_ERROR})); + auto callbacks = std::move(syncCallbacks_); + callbacks.ForEach([&result](const auto &key, const AsyncDetail &callback) { + LOG_INFO("remote dead, compensate progress notification"); + std::map copyResult = result; + if (callback != nullptr) { + callback(std::move(result)); + } + return false; + }); +} + void RdbServiceProxy::OnSyncComplete(uint32_t seqNum, Details &&result) { syncCallbacks_.ComputeIfPresent(seqNum, [&result](const auto &key, const AsyncDetail &callback) { @@ -672,4 +701,16 @@ int32_t RdbServiceProxy::VerifyPromiseInfo(const RdbSyncerParam ¶m) } return status; } + +RdbServiceProxy::~RdbServiceProxy() +{ + int32_t retry = 0; + while (notifier_ != nullptr && notifier_->GetSptrRefCount() > 1 && retry < MAX_RETRY) { + retry++; + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + if (notifier_ != nullptr && notifier_->GetSptrRefCount() > 1) { + LOG_WARN("notifier_ has other in use:%{public}d!", notifier_->GetSptrRefCount()); + } +} } // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_sql_log.cpp b/relational_store/frameworks/native/rdb/src/rdb_sql_log.cpp new file mode 100644 index 00000000..05106a55 --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/rdb_sql_log.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. +*/ + +#define LOG_TAG "RdbSqlLog" + +#include "rdb_sql_log.h" + +#include "concurrent_map.h" +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_platform.h" +#include "task_executor.h" + +namespace OHOS::NativeRdb { +ConcurrentMap>> SqlLog::observerSets_; +std::atomic SqlLog::enabled_ = false; +std::shared_mutex SqlLog::mutex_; +std::map SqlLog::suspenders_; +int SqlLog::Subscribe(const std::string storeId, std::shared_ptr observer) +{ + observerSets_.Compute(storeId, [observer](const std::string& key, auto& observers) { + observers.insert(observer); + enabled_ = true; + return true; + }); + return E_OK; +} + +int SqlLog::Unsubscribe(const std::string storeId, std::shared_ptr observer) +{ + observerSets_.ComputeIfPresent(storeId, + [observer](const std::string& key, std::set>& observers) { + observers.erase(observer); + return observer !=nullptr && !observers.empty(); + }); + observerSets_.DoActionIfEmpty([]() { + enabled_ = false; + }); + return E_OK; +} + +void SqlLog::Notify(const std::string &storeId, const ExceptionMessage &exceptionMessage) +{ + if (!enabled_ || IsPause()) { + return; + } + if (!observerSets_.Contains(storeId)) { + return; + } + auto executor = TaskExecutor::GetInstance().GetExecutor(); + if (executor == nullptr) { + return; + } + executor->Execute([exceptionMessage, storeId]() { + auto it = observerSets_.Find(storeId); + if (!it.first) { + return; + } + for (const auto &observer: it.second) { + if (observer) { + observer->OnErrorLog(exceptionMessage); + } + } + }); +} + +void SqlLog::Pause() +{ + std::unique_lock lock(mutex_); + suspenders_[GetThreadId()] = std::max(1, ++suspenders_[GetThreadId()]); +} + +void SqlLog::Resume() +{ + std::unique_lock lock(mutex_); + suspenders_[GetThreadId()] = std::max(0, --suspenders_[GetThreadId()]); +} + +bool SqlLog::IsPause() +{ + std::shared_lock lock(mutex_); + auto it = suspenders_.find(GetThreadId()); + return it != suspenders_.end() && it->second > 0; +} + +SqlLog::SqlLog() +{ +} + +SqlLog::~SqlLog() +{ +} + +} \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_sql_statistic.cpp b/relational_store/frameworks/native/rdb/src/rdb_sql_statistic.cpp index 94dbe863..e7568fa5 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_sql_statistic.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_sql_statistic.cpp @@ -50,11 +50,6 @@ int SqlStatistic::Unsubscribe(std::shared_ptr observer) return E_OK; } -uint32_t SqlStatistic::GenerateId() -{ - return ++seqId_; -} - SqlStatistic::SqlStatistic(const std::string &sql, int32_t step, uint32_t seqId) { if (!enabled_) { diff --git a/relational_store/frameworks/native/rdb/src/rdb_sql_utils.cpp b/relational_store/frameworks/native/rdb/src/rdb_sql_utils.cpp index 798b23ce..dbf2dffb 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_sql_utils.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_sql_utils.cpp @@ -54,10 +54,12 @@ int RdbSqlUtils::CreateDirectory(const std::string &databaseDir) databaseDirectory = databaseDirectory + "/" + directory; if (access(databaseDirectory.c_str(), F_OK) != 0) { if (MkDir(databaseDirectory)) { - LOG_ERROR("failed to mkdir errno[%{public}d] %{public}s", errno, - SqliteUtils::Anonymous(databaseDirectory).c_str()); + LOG_ERROR("failed to mkdir errno[%{public}d] %{public}s, parent dir modes: %{public}s", errno, + SqliteUtils::Anonymous(databaseDirectory).c_str(), + SqliteUtils::GetParentModes(databaseDirectory).c_str()); RdbFaultHiViewReporter::ReportFault(RdbFaultEvent(FT_EX_FILE, E_CREATE_FOLDER_FAIL, BUNDLE_NAME_COMMON, - "failed to mkdir errno[ " + std::to_string(errno) + "]," + databaseDirectory)); + "failed to mkdir errno[ " + std::to_string(errno) + "]," + databaseDirectory + + "parent dir modes:" + SqliteUtils::GetParentModes(databaseDirectory))); return E_CREATE_FOLDER_FAIL; } // Set the default ACL attribute to the database root directory to ensure that files created by the server @@ -126,5 +128,128 @@ std::string RdbSqlUtils::BuildQueryString(const AbsRdbPredicates &predicates, co { return SqliteSqlBuilder::BuildQueryString(predicates, columns); } + +std::pair RdbSqlUtils::GetInsertSqlInfo(const std::string &table, const Row &row, Resolution resolution) +{ + SqlInfo sqlInfo; + if (table.empty()) { + return std::make_pair(E_EMPTY_TABLE_NAME, sqlInfo); + } + + if (row.IsEmpty()) { + return std::make_pair(E_EMPTY_VALUES_BUCKET, sqlInfo); + } + + auto conflictClause = SqliteUtils::GetConflictClause(static_cast(resolution)); + if (conflictClause == nullptr) { + return std::make_pair(E_INVALID_CONFLICT_FLAG, sqlInfo); + } + std::string sql; + sql.append("INSERT").append(conflictClause).append(" INTO ").append(table).append("("); + size_t bindArgsSize = row.values_.size(); + std::vector bindArgs; + bindArgs.reserve(bindArgsSize); + const char *split = ""; + for (const auto &[key, val] : row.values_) { + sql.append(split).append(key); + if (val.GetType() == ValueObject::TYPE_ASSETS && resolution == ConflictResolution::ON_CONFLICT_REPLACE) { + return std::make_pair(E_INVALID_ARGS, sqlInfo); + } + SqliteSqlBuilder::UpdateAssetStatus(val, AssetValue::STATUS_INSERT); + bindArgs.push_back(val); // columnValue + split = ","; + } + + sql.append(") VALUES ("); + if (bindArgsSize > 0) { + sql.append(SqliteSqlBuilder::GetSqlArgs(bindArgsSize)); + } + + sql.append(")"); + sqlInfo.sql = std::move(sql); + sqlInfo.args = std::move(bindArgs); + return std::make_pair(E_OK, sqlInfo); +} + +std::pair RdbSqlUtils::GetUpdateSqlInfo(const AbsRdbPredicates &predicates, const Row &row, + Resolution resolution, const std::vector &returningFields) +{ + SqlInfo sqlInfo; + auto table = predicates.GetTableName(); + auto args = predicates.GetBindArgs(); + auto where = predicates.GetWhereClause(); + if (table.empty()) { + return std::make_pair(E_EMPTY_TABLE_NAME, sqlInfo); + } + + if (row.IsEmpty()) { + return std::make_pair(E_EMPTY_VALUES_BUCKET, sqlInfo); + } + + auto clause = SqliteUtils::GetConflictClause(static_cast(resolution)); + if (clause == nullptr) { + return std::make_pair(E_INVALID_CONFLICT_FLAG, sqlInfo); + } + std::string sql; + sql.append("UPDATE").append(clause).append(" ").append(table).append(" SET "); + std::vector tmpBindArgs; + size_t tmpBindSize = row.values_.size() + args.size(); + tmpBindArgs.reserve(tmpBindSize); + const char *split = ""; + for (auto &[key, val] : row.values_) { + sql.append(split); + if (val.GetType() == ValueObject::TYPE_ASSETS) { + sql.append(key).append("=merge_assets(").append(key).append(", ?)"); // columnName + } else if (val.GetType() == ValueObject::TYPE_ASSET) { + sql.append(key).append("=merge_asset(").append(key).append(", ?)"); // columnName + } else { + sql.append(key).append("=?"); // columnName + } + tmpBindArgs.push_back(val); // columnValue + split = ","; + } + if (!where.empty()) { + sql.append(" WHERE ").append(where); + } + if (!returningFields.empty()) { + SqliteSqlBuilder::AppendReturning(sql, returningFields); + } + tmpBindArgs.insert(tmpBindArgs.end(), args.begin(), args.end()); + + sqlInfo.sql = std::move(sql); + sqlInfo.args = std::move(tmpBindArgs); + return std::make_pair(E_OK, sqlInfo); +} + +std::pair RdbSqlUtils::GetDeleteSqlInfo( + const AbsRdbPredicates &predicates, const std::vector &returningFields) +{ + SqlInfo sqlInfo; + auto table = predicates.GetTableName(); + auto where = predicates.GetWhereClause(); + if (table.empty()) { + return std::make_pair(E_EMPTY_TABLE_NAME, sqlInfo); + } + std::string sql; + sql.append("DELETE FROM ").append(table); + if (!where.empty()) { + sql.append(" WHERE ").append(where); + } + if (!returningFields.empty()) { + SqliteSqlBuilder::AppendReturning(sql, returningFields); + } + sqlInfo.sql = std::move(sql); + sqlInfo.args = predicates.GetBindArgs(); + return std::make_pair(E_OK, sqlInfo); +} + +std::pair RdbSqlUtils::GetQuerySqlInfo(const AbsRdbPredicates &predicates, const Fields &columns) +{ + SqlInfo sqlInfo; + std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); + sqlInfo.sql = std::move(sql); + sqlInfo.args = predicates.GetBindArgs(); + return std::make_pair(E_OK, sqlInfo); +} } // namespace NativeRdb } // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_store.cpp b/relational_store/frameworks/native/rdb/src/rdb_store.cpp index f97c56c4..f22e9786 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store.cpp @@ -14,10 +14,12 @@ */ #include "rdb_store.h" +#include "logger.h" #include "sqlite_sql_builder.h" #include "sqlite_utils.h" #include "traits.h" namespace OHOS::NativeRdb { +using namespace OHOS::Rdb; RdbStore::ModifyTime::ModifyTime( std::shared_ptr result, std::map, PRIKey> hashKeys, bool isFromRowId) : result_(std::move(result)), hash_(std::move(hashKeys)), isFromRowId_(isFromRowId) @@ -138,6 +140,12 @@ int RdbStore::Replace(int64_t &outRowId, const std::string &table, const Row &ro return errCode; } +// Old version implementation, cannot be modified +std::pair RdbStore::BatchInsert(const std::string &table, const RefRows &rows) +{ + return { E_NOT_SUPPORT, -1 }; +} + int RdbStore::BatchInsert(int64_t &outInsertNum, const std::string &table, const Rows &rows) { ValuesBuckets refRows; @@ -151,13 +159,14 @@ int RdbStore::BatchInsert(int64_t &outInsertNum, const std::string &table, const return errCode; } -std::pair RdbStore::BatchInsert(const std::string &table, const RefRows &rows) +std::pair RdbStore::BatchInsert(const std::string &table, const RefRows &rows, Resolution resolution) { - return { E_NOT_SUPPORT, -1 }; + auto [code, result] = BatchInsert(table, rows, {}, resolution); + return { code, result.changed }; } -std::pair RdbStore::BatchInsertWithConflictResolution( - const std::string &table, const RdbStore::RefRows &rows, RdbStore::Resolution resolution) +std::pair RdbStore::BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution) { return { E_NOT_SUPPORT, -1 }; } @@ -165,12 +174,11 @@ std::pair RdbStore::BatchInsertWithConflictResolution( std::pair RdbStore::Update( const std::string &table, const Row &row, const std::string &where, const Values &args, Resolution resolution) { - (void)table; - (void)row; - (void)where; - (void)args; - (void)resolution; - return { E_NOT_SUPPORT, 0 }; + AbsRdbPredicates predicates(table); + predicates.SetWhereClause(where); + predicates.SetBindArgs(args); + auto [code, result] = Update(row, predicates, {}, resolution); + return { code, result.changed }; } int RdbStore::Update( @@ -194,6 +202,12 @@ int RdbStore::Update( return Update(changedRows, table, row, whereClause, ToValues(args)); }; +std::pair RdbStore::Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) +{ + return { E_NOT_SUPPORT, -1 }; +} + int RdbStore::UpdateWithConflictResolution(int &changedRows, const std::string &table, const Row &row, const std::string &whereClause, const Olds &args, Resolution resolution) { @@ -224,6 +238,23 @@ int RdbStore::Delete(int &deletedRows, const AbsRdbPredicates &predicates) return Delete(deletedRows, predicates.GetTableName(), predicates.GetWhereClause(), predicates.GetBindArgs()); } +int RdbStore::Delete( + int &deletedRows, const std::string &table, const std::string &whereClause, const RdbStore::Values &args) +{ + AbsRdbPredicates predicates(table); + predicates.SetWhereClause(whereClause); + predicates.SetBindArgs(args); + auto [code, result] = Delete(predicates); + deletedRows = result.changed; + return code; +} + +std::pair RdbStore::Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) +{ + return { E_NOT_SUPPORT, -1 }; +} + std::shared_ptr RdbStore::Query(int &errCode, bool distinct, const std::string &table, const Fields &columns, const std::string &whereClause, const Values &args, const std::string &groupBy, const std::string &indexName, const std::string &orderBy, const int &limit, const int &offset) @@ -242,8 +273,7 @@ std::shared_ptr RdbStore::Query(const AbsRdbPredicates &pred std::string sql; std::pair queryStatus = { ColHasSpecificField(columns), predicates.HasSpecificField() }; if (queryStatus.first || queryStatus.second) { - std::string table = predicates.GetTableName(); - std::string logTable = GetLogTableName(table); + std::string logTable = GetLogTableName(predicates.GetTableName()); sql = SqliteSqlBuilder::BuildCursorQueryString(predicates, columns, logTable, queryStatus); } else { sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); @@ -265,7 +295,8 @@ std::shared_ptr RdbStore::QueryByStep(const AbsRdbPredicates &predica bool preCount) { std::string sql; - if (predicates.HasSpecificField()) { + std::pair queryStatus = { ColHasSpecificField(columns), predicates.HasSpecificField() }; + if (queryStatus.first || queryStatus.second) { std::string table = predicates.GetTableName(); std::string logTable = GetLogTableName(table); sql = SqliteSqlBuilder::BuildLockRowQueryString(predicates, columns, logTable); @@ -304,6 +335,11 @@ std::pair RdbStore::Execute(const std::string &sql, const return { E_NOT_SUPPORT, ValueObject() }; } +std::pair RdbStore::ExecuteExt(const std::string &sql, const Values &args) +{ + return { E_NOT_SUPPORT, -1 }; +} + int RdbStore::ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const Values &args) { auto [errCode, value] = Execute(sql, args); @@ -342,6 +378,12 @@ int RdbStore::ExecuteForChangedRowCount(int64_t &outValue, const std::string &sq int RdbStore::Backup(const std::string &databasePath, const std::vector &encryptKey) { + return Backup(databasePath, encryptKey, true); +} + +int RdbStore::Backup(const std::string &databasePath, const std::vector &encryptKey, bool verifyDb) +{ + (void)verifyDb; (void)databasePath; (void)encryptKey; return E_NOT_SUPPORT; @@ -446,6 +488,12 @@ int RdbStore::SetDistributedTables( return E_NOT_SUPPORT; } +int RdbStore::Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) +{ + (void)cryptoParam; + return E_NOT_SUPPORT; +} + std::string RdbStore::ObtainDistributedTableName(const std::string &device, const std::string &table, int &errCode) { errCode = E_NOT_SUPPORT; @@ -476,14 +524,14 @@ int RdbStore::Sync(const SyncOption &option, const AbsRdbPredicates &predicate, return E_NOT_SUPPORT; } -int RdbStore::Subscribe(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStore::Subscribe(const SubscribeOption &option, std::shared_ptr observer) { (void)option; (void)observer; return E_NOT_SUPPORT; } -int RdbStore::UnSubscribe(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStore::UnSubscribe(const SubscribeOption &option, std::shared_ptr observer) { (void)option; (void)observer; @@ -607,4 +655,27 @@ std::string RdbStore::GetLogTableName(const std::string &tableName) { return "naturalbase_rdb_aux_" + tableName + "_log"; } + +int RdbStore::CleanDirtyLog([[gnu::unused]] const std::string &table, [[gnu::unused]] uint64_t cursor) +{ + return E_NOT_SUPPORT; +} + +int RdbStore::ConfigLocale(const std::string &localeStr) +{ + (void)localeStr; + return E_NOT_SUPPORT; +} + +int RdbStore::InitKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema &schema) +{ + return E_NOT_SUPPORT; +} + +int RdbStore::RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) +{ + (void)func; + (void)clstAlgoName; + return E_NOT_SUPPORT; +} } // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp index a8cf560c..37188f9d 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp @@ -16,6 +16,7 @@ #include "rdb_store_config.h" #include +#include #include "logger.h" #include "rdb_errno.h" @@ -27,6 +28,8 @@ namespace OHOS::NativeRdb { using namespace OHOS::Rdb; +// this is modifications to be made in the future. +static std::mutex g_mutex; RdbStoreConfig::RdbStoreConfig(const std::string &name, StorageMode storageMode, bool isReadOnly, const std::vector &encryptKey, const std::string &journalMode, const std::string &syncMode, @@ -360,6 +363,12 @@ std::vector RdbStoreConfig::GetEncryptKey() const return cryptoParam_.encryptKey_; } +void RdbStoreConfig::ResetEncryptKey(const std::vector &encryptKey) const +{ + cryptoParam_.encryptKey_.assign(cryptoParam_.encryptKey_.size(), 0); + cryptoParam_.encryptKey_ = encryptKey; +} + void RdbStoreConfig::ChangeEncryptKey() const { RdbSecurityManager::GetInstance().ChangeKeyFile(GetPath()); @@ -393,6 +402,7 @@ int32_t RdbStoreConfig::GenerateEncryptedKey() const name = std::string(path_).substr(0, path_.rfind("/") + 1); } using KeyFileType = RdbSecurityManager::KeyFileType; + std::lock_guard lock(g_mutex); auto errCode = RdbSecurityManager::GetInstance().Init(name); if (errCode != E_OK) { RdbFaultHiViewReporter::ReportFault(RdbFaultDbFileEvent(FT_OPEN, E_ROOT_KEY_FAULT, *this, @@ -511,9 +521,9 @@ void RdbStoreConfig::SetWriteTime(int timeout) writeTimeout_ = std::max(MIN_TIMEOUT, std::min(MAX_TIMEOUT, timeout)); } -bool RdbStoreConfig::IsLocalOnly() const +bool RdbStoreConfig::IsCustomEncryptParam() const { - return localOnly_; + return customEncryptParam_; } int RdbStoreConfig::GetReadTime() const @@ -566,24 +576,24 @@ IntegrityCheck RdbStoreConfig::GetIntegrityCheck() const return checkType_; } -void RdbStoreConfig::SetPluginLibs(const std::vector &pluginLibs) +int32_t RdbStoreConfig::GetIter() const { - pluginLibs_ = pluginLibs; + return cryptoParam_.iterNum; } -std::vector RdbStoreConfig::GetPluginLibs() const +void RdbStoreConfig::SetIter(int32_t iter) const { - return pluginLibs_; + cryptoParam_.iterNum = iter; } -int32_t RdbStoreConfig::GetIter() const +void RdbStoreConfig::SetPluginLibs(const std::vector &pluginLibs) { - return cryptoParam_.iterNum; + pluginLibs_ = pluginLibs; } -void RdbStoreConfig::SetIter(int32_t iter) const +std::vector RdbStoreConfig::GetPluginLibs() const { - cryptoParam_.iterNum = iter; + return pluginLibs_; } int32_t RdbStoreConfig::GetHaMode() const @@ -606,7 +616,6 @@ void RdbStoreConfig::SetPromiseInfo(PromiseInfo promiseInfo) promiseInfo_ = promiseInfo; } - Tokenizer RdbStoreConfig::GetTokenizer() const { return tokenizer_; @@ -622,6 +631,16 @@ ssize_t RdbStoreConfig::GetWalLimitSize() const return walLimitSize_; } +void RdbStoreConfig::SetEnableSemanticIndex(bool enableSemanticIndex) +{ + enableSemanticIndex_ = enableSemanticIndex; +} + +bool RdbStoreConfig::GetEnableSemanticIndex() const +{ + return enableSemanticIndex_; +} + void RdbStoreConfig::SetWalLimitSize(ssize_t size) { if (size < GlobalExpr::DB_WAL_DEFAULT_SIZE) { @@ -653,12 +672,12 @@ void RdbStoreConfig::SetClearMemorySize(int32_t size) std::string RdbStoreConfig::GetCollatorLocales() const { - return loacles_; + return collatorLocales_.Get(); } -void RdbStoreConfig::SetCollatorLocales(const std::string &loacles) +void RdbStoreConfig::SetCollatorLocales(const std::string &locales) const { - loacles_ = loacles; + collatorLocales_.Set(locales); } ssize_t RdbStoreConfig::GetCheckpointSize() const @@ -690,7 +709,7 @@ void RdbStoreConfig::SetCryptoParam(RdbStoreConfig::CryptoParam cryptoParam) { cryptoParam_ = cryptoParam; if (!(cryptoParam_.encryptKey_.empty())) { - localOnly_ = true; + customEncryptParam_ = true; } } @@ -699,16 +718,6 @@ RdbStoreConfig::CryptoParam RdbStoreConfig::GetCryptoParam() const return cryptoParam_; } -int RdbStoreConfig::GetNcandidates() const -{ - return ncandidates_; -} - -void RdbStoreConfig::SetNcandidates(int ncandidates) -{ - ncandidates_ = ncandidates; -} - RdbStoreConfig::CryptoParam::CryptoParam() = default; RdbStoreConfig::CryptoParam::~CryptoParam() diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp index e6371c60..4dce2c8c 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp @@ -15,6 +15,8 @@ #define LOG_TAG "RdbStoreImpl" #include "rdb_store_impl.h" +#include +#include #include #include @@ -32,14 +34,18 @@ #include "connection_pool.h" #include "delay_notify.h" #include "directory_ex.h" +#include "knowledge_schema_helper.h" #include "logger.h" #include "rdb_common.h" #include "rdb_errno.h" #include "rdb_fault_hiview_reporter.h" #include "rdb_local_db_observer.h" +#include "rdb_perfStat.h" #include "rdb_radar_reporter.h" #include "rdb_stat_reporter.h" #include "rdb_security_manager.h" +#include "rdb_sql_log.h" +#include "rdb_sql_utils.h" #include "rdb_sql_statistic.h" #include "rdb_store.h" #include "rdb_trace.h" @@ -47,23 +53,24 @@ #include "relational_store_client.h" #include "sqlite_global_config.h" #include "sqlite_sql_builder.h" -#include "sqlite_statement.h" #include "sqlite_utils.h" #include "step_result_set.h" +#include "suspender.h" #include "task_executor.h" #include "traits.h" #include "transaction.h" #include "values_buckets.h" #if !defined(CROSS_PLATFORM) #include "raw_data_parser.h" -#include "rdb_device_manager_adapter.h" #include "rdb_manager_impl.h" #include "relational_store_manager.h" -#include "runtime_config.h" #include "security_policy.h" #include "sqlite_shared_result_set.h" #endif +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) +#include "security_policy.h" +#endif #ifdef WINDOWS_PLATFORM #define ISFILE(filePath) ((filePath.find("\\") == std::string::npos)) #else @@ -75,9 +82,11 @@ namespace OHOS::NativeRdb { using namespace OHOS::Rdb; using namespace std::chrono; using SqlStatistic = DistributedRdb::SqlStatistic; +using PerfStat = DistributedRdb::PerfStat; using RdbNotifyConfig = DistributedRdb::RdbNotifyConfig; using Reportor = RdbFaultHiViewReporter; -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) + +#if !defined(CROSS_PLATFORM) using RdbMgr = DistributedRdb::RdbManagerImpl; #endif @@ -85,6 +94,7 @@ static constexpr const char *BEGIN_TRANSACTION_SQL = "begin;"; static constexpr const char *COMMIT_TRANSACTION_SQL = "commit;"; static constexpr const char *ROLLBACK_TRANSACTION_SQL = "rollback;"; static constexpr const char *BACKUP_RESTORE = "backup.restore"; +static constexpr const char *ASYNC_RESTORE = "-async.restore"; constexpr int64_t TIME_OUT = 1500; void RdbStoreImpl::InitSyncerParam(const RdbStoreConfig &config, bool created) @@ -116,13 +126,16 @@ void RdbStoreImpl::InitSyncerParam(const RdbStoreConfig &config, bool created) int RdbStoreImpl::InnerOpen() { isOpen_ = true; -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) - if (isReadOnly_ || isMemoryRdb_ || config_.IsLocalOnly()) { +#if !defined(CROSS_PLATFORM) + // Only owner mode can store metadata information. + if (isReadOnly_ || isMemoryRdb_ || config_.IsCustomEncryptParam() || (config_.GetRoleType() != OWNER)) { return E_OK; } - + if (config_.GetEnableSemanticIndex()) { + SetKnowledgeSchema(); + } AfterOpen(syncerParam_); - if (config_.GetDBType() == DB_VECTOR || !config_.IsSearchable()) { + if (config_.GetDBType() == DB_VECTOR || (!config_.IsSearchable() && !config_.GetEnableSemanticIndex())) { return E_OK; } int errCode = RegisterDataChangeCallback(); @@ -172,6 +185,12 @@ void RdbStoreImpl::Close() } transactions_ = {}; } + { + std::lock_guard autoLock(helperMutex_); + if (knowledgeSchemaHelper_ != nullptr) { + knowledgeSchemaHelper_->Close(); + } + } } std::shared_ptr RdbStoreImpl::GetPool() const @@ -194,7 +213,7 @@ std::pair> RdbStoreImpl::GetConn(bool isRea return { E_OK, connection }; } -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) +#if !defined(CROSS_PLATFORM) void RdbStoreImpl::AfterOpen(const RdbParam ¶m, int32_t retry) { auto [err, service] = RdbMgr::GetInstance().GetRdbService(param); @@ -202,10 +221,13 @@ void RdbStoreImpl::AfterOpen(const RdbParam ¶m, int32_t retry) return; } if (err != E_OK || service == nullptr) { - LOG_ERROR("GetRdbService failed, err: %{public}d, storeName: %{public}s.", err, - SqliteUtils::Anonymous(param.storeName_).c_str()); + if (err != E_INVALID_ARGS) { + LOG_ERROR("GetRdbService failed, err: %{public}d, storeName: %{public}s.", err, + SqliteUtils::Anonymous(param.storeName_).c_str()); + } auto pool = TaskExecutor::GetInstance().GetExecutor(); - if (err == E_SERVICE_NOT_FOUND && pool != nullptr && retry++ < MAX_RETRY_TIMES) { + if (err == E_SERVICE_NOT_FOUND && pool != nullptr && retry < MAX_RETRY_TIMES) { + retry++; pool->Schedule(std::chrono::seconds(RETRY_INTERVAL), [param, retry]() { AfterOpen(param, retry); }); @@ -399,6 +421,55 @@ int RdbStoreImpl::SetDistributedTables( return HandleCloudSyncAfterSetDistributedTables(tables, distributedConfig); } +int32_t RdbStoreImpl::Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) +{ + if (config_.GetDBType() == DB_VECTOR || isReadOnly_ || isMemoryRdb_) { + return E_NOT_SUPPORT; + } + if (!cryptoParam.IsValid()) { + LOG_ERROR("Invalid crypto param, name:%{public}s", SqliteUtils::Anonymous(config_.GetName()).c_str()); + return E_INVALID_ARGS_NEW; + } + if (!config_.IsEncrypt() || !config_.GetCryptoParam().Equal(cryptoParam) || + (config_.IsCustomEncryptParam() == cryptoParam.encryptKey_.empty())) { + LOG_ERROR("Not supported! name:%{public}s, [%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}u]" + "->[%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}u]", + SqliteUtils::Anonymous(config_.GetName()).c_str(), config_.GetCryptoParam().encryptKey_.empty(), + config_.GetCryptoParam().iterNum, config_.GetCryptoParam().encryptAlgo, config_.GetCryptoParam().hmacAlgo, + config_.GetCryptoParam().kdfAlgo, config_.GetCryptoParam().cryptoPageSize, cryptoParam.encryptKey_.empty(), + cryptoParam.iterNum, cryptoParam.encryptAlgo, cryptoParam.hmacAlgo, + cryptoParam.kdfAlgo, cryptoParam.cryptoPageSize); + return E_NOT_SUPPORT; + } + + auto pool = GetPool(); + if (pool == nullptr) { + LOG_ERROR("Database already closed."); + return E_ALREADY_CLOSED; + } + +#if !defined(CROSS_PLATFORM) + auto [err, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); + if (service != nullptr) { + service->Disable(syncerParam_); + } +#endif + LOG_INFO("Start rekey, name:%{public}s, IsCustomEncrypt:%{public}d. ", + SqliteUtils::Anonymous(config_.GetName()).c_str(), config_.IsCustomEncryptParam()); + auto errCode = pool->Rekey(cryptoParam); +#if !defined(CROSS_PLATFORM) + if (service != nullptr) { + service->Enable(syncerParam_); + if (errCode == E_OK && !config_.IsCustomEncryptParam()) { + auto syncerParam = syncerParam_; + syncerParam.password_ = config_.GetEncryptKey(); + service->AfterOpen(syncerParam); + } + } +#endif + return errCode; +} + int RdbStoreImpl::HandleCloudSyncAfterSetDistributedTables( const std::vector &tables, const DistributedRdb::DistributedConfig &distributedConfig) { @@ -436,21 +507,14 @@ std::string RdbStoreImpl::ObtainDistributedTableName(const std::string &device, if (config_.GetDBType() == DB_VECTOR || isMemoryRdb_) { return ""; } - std::string uuid; - DeviceManagerAdaptor::RdbDeviceManagerAdaptor &deviceManager = - DeviceManagerAdaptor::RdbDeviceManagerAdaptor::GetInstance(syncerParam_.bundleName_); - errCode = deviceManager.GetEncryptedUuidByNetworkId(device, uuid); - if (errCode != E_OK) { - LOG_ERROR("GetUuid is failed."); + auto [err, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); + if (err != E_OK || service == nullptr) { + errCode = err; return ""; } - - auto translateCall = [uuid](const std::string &oriDevId, const DistributedDB::StoreInfo &info) { - return uuid; - }; - DistributedDB::RuntimeConfig::SetTranslateToDeviceIdCallback(translateCall); - - return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table); + auto tableName = service->ObtainDistributedTableName(syncerParam_, device, table); + errCode = tableName.empty() ? E_ERROR : E_OK; + return tableName; } int RdbStoreImpl::Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncBrief &callback) @@ -508,7 +572,7 @@ int RdbStoreImpl::InnerSync( return E_OK; } -Uri RdbStoreImpl::GetUri(const std::string &event) +std::string RdbStoreImpl::GetUri(const std::string &event) { std::string rdbUri; if (config_.GetDataGroupId().empty()) { @@ -516,10 +580,10 @@ Uri RdbStoreImpl::GetUri(const std::string &event) } else { rdbUri = SCHEME_RDB + config_.GetDataGroupId() + "/" + path_ + "/" + event; } - return Uri(rdbUri); + return rdbUri; } -int RdbStoreImpl::SubscribeLocal(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::SubscribeLocal(const SubscribeOption &option, std::shared_ptr observer) { std::lock_guard lock(mutex_); localObservers_.try_emplace(option.event); @@ -535,31 +599,9 @@ int RdbStoreImpl::SubscribeLocal(const SubscribeOption &option, RdbStoreObserver return E_OK; } -int RdbStoreImpl::SubscribeLocalShared(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::SubscribeLocalShared(const SubscribeOption &option, std::shared_ptr observer) { - std::lock_guard lock(mutex_); - localSharedObservers_.try_emplace(option.event); - auto &list = localSharedObservers_.find(option.event)->second; - for (auto it = list.begin(); it != list.end(); it++) { - if ((*it)->getObserver() == observer) { - LOG_ERROR("Duplicate subscribe."); - return E_OK; - } - } - - auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); - if (client == nullptr) { - LOG_ERROR("Failed to get DataObsMgrClient."); - return E_GET_DATAOBSMGRCLIENT_FAIL; - } - sptr localSharedObserver(new (std::nothrow) RdbStoreLocalSharedObserver(observer)); - int32_t err = client->RegisterObserver(GetUri(option.event), localSharedObserver); - if (err != 0) { - LOG_ERROR("Subscribe failed."); - return err; - } - localSharedObservers_[option.event].push_back(std::move(localSharedObserver)); - return E_OK; + return obsManger_.Register(GetUri(option.event), observer); } int32_t RdbStoreImpl::SubscribeLocalDetail( @@ -591,7 +633,7 @@ int32_t RdbStoreImpl::SubscribeLocalDetail( return E_OK; } -int RdbStoreImpl::SubscribeRemote(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::SubscribeRemote(const SubscribeOption &option, std::shared_ptr observer) { auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); if (errCode != E_OK) { @@ -600,7 +642,7 @@ int RdbStoreImpl::SubscribeRemote(const SubscribeOption &option, RdbStoreObserve return service->Subscribe(syncerParam_, option, observer); } -int RdbStoreImpl::Subscribe(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::Subscribe(const SubscribeOption &option, std::shared_ptr observer) { if (config_.GetDBType() == DB_VECTOR) { return E_NOT_SUPPORT; @@ -617,7 +659,7 @@ int RdbStoreImpl::Subscribe(const SubscribeOption &option, RdbStoreObserver *obs return SubscribeRemote(option, observer); } -int RdbStoreImpl::UnSubscribeLocal(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::UnSubscribeLocal(const SubscribeOption &option, std::shared_ptr observer) { std::lock_guard lock(mutex_); auto obs = localObservers_.find(option.event); @@ -643,40 +685,9 @@ int RdbStoreImpl::UnSubscribeLocal(const SubscribeOption &option, RdbStoreObserv return E_OK; } -int RdbStoreImpl::UnSubscribeLocalShared(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::UnSubscribeLocalShared(const SubscribeOption &option, std::shared_ptr observer) { - std::lock_guard lock(mutex_); - auto obs = localSharedObservers_.find(option.event); - if (obs == localSharedObservers_.end()) { - return E_OK; - } - - auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); - if (client == nullptr) { - LOG_ERROR("Failed to get DataObsMgrClient."); - return E_GET_DATAOBSMGRCLIENT_FAIL; - } - - auto &list = obs->second; - for (auto it = list.begin(); it != list.end();) { - if (observer == nullptr || (*it)->getObserver() == observer) { - int32_t err = client->UnregisterObserver(GetUri(option.event), *it); - if (err != 0) { - LOG_ERROR("UnSubscribeLocalShared failed."); - return err; - } - it = list.erase(it); - if (observer != nullptr) { - break; - } - } else { - it++; - } - } - if (list.empty()) { - localSharedObservers_.erase(option.event); - } - return E_OK; + return obsManger_.Unregister(GetUri(option.event), observer); } int32_t RdbStoreImpl::UnsubscribeLocalDetail( @@ -706,7 +717,7 @@ int32_t RdbStoreImpl::UnsubscribeLocalDetail( return E_OK; } -int RdbStoreImpl::UnSubscribeRemote(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::UnSubscribeRemote(const SubscribeOption &option, std::shared_ptr observer) { auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); if (errCode != E_OK) { @@ -715,7 +726,7 @@ int RdbStoreImpl::UnSubscribeRemote(const SubscribeOption &option, RdbStoreObser return service->UnSubscribe(syncerParam_, option, observer); } -int RdbStoreImpl::UnSubscribe(const SubscribeOption &option, RdbStoreObserver *observer) +int RdbStoreImpl::UnSubscribe(const SubscribeOption &option, std::shared_ptr observer) { if (config_.GetDBType() == DB_VECTOR) { return E_NOT_SUPPORT; @@ -767,12 +778,7 @@ int RdbStoreImpl::Notify(const std::string &event) if (isMemoryRdb_) { return E_OK; } - auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); - if (client == nullptr) { - LOG_ERROR("Failed to get DataObsMgrClient."); - return E_GET_DATAOBSMGRCLIENT_FAIL; - } - int32_t err = client->NotifyChange(GetUri(event)); + int32_t err = obsManger_.Notify(GetUri(event)); if (err != 0) { LOG_ERROR("Notify failed."); } @@ -826,9 +832,21 @@ void RdbStoreImpl::InitDelayNotifier() LOG_ERROR("Init delay notifier failed."); return; } + std::weak_ptr helper = GetKnowledgeSchemaHelper(); delayNotifier_->SetExecutorPool(TaskExecutor::GetInstance().GetExecutor()); - delayNotifier_->SetTask([param = syncerParam_](const DistributedRdb::RdbChangedData &rdbChangedData, - const RdbNotifyConfig &rdbNotifyConfig) -> int { + delayNotifier_->SetTask([param = syncerParam_, helper = helper]( + const DistributedRdb::RdbChangedData &rdbChangedData, const RdbNotifyConfig &rdbNotifyConfig) -> int { + if (IsKnowledgeDataChange(rdbChangedData)) { + auto realHelper = helper.lock(); + if (realHelper == nullptr) { + LOG_WARN("knowledge helper is nullptr"); + return E_OK; + } + realHelper->DonateKnowledgeData(); + } + if (!IsNotifyService(rdbChangedData)) { + return E_OK; + } auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(param); if (errCode == E_NOT_SUPPORT) { return errCode; @@ -865,7 +883,8 @@ void RdbStoreImpl::RegisterDataChangeCallback( if (conn == nullptr) { relConnPool->Dump(true, "DATACHANGE"); auto pool = TaskExecutor::GetInstance().GetExecutor(); - if (pool != nullptr && retry++ < MAX_RETRY_TIMES) { + if (pool != nullptr && retry < MAX_RETRY_TIMES) { + retry++; pool->Schedule(std::chrono::seconds(1), [delayNotifier, connPool, retry]() { RegisterDataChangeCallback(delayNotifier, connPool, retry); }); } @@ -895,13 +914,12 @@ int RdbStoreImpl::GetHashKeyForLockRow(const AbsRdbPredicates &predicates, std:: sql.append(table).append(".ROWID = ").append(logTable).append(".data_key"); auto whereClause = predicates.GetWhereClause(); if (!whereClause.empty()) { - SqliteUtils::Replace(whereClause, SqliteUtils::REP, logTable + "."); - sql.append(" WHERE ").append(whereClause); + sql.append(" WHERE ").append(SqliteUtils::Replace(whereClause, SqliteUtils::REP, logTable + ".")); } auto result = QuerySql(sql, predicates.GetBindArgs()); if (result == nullptr) { - return E_ALREADY_CLOSED ; + return E_ALREADY_CLOSED; } int count = 0; if (result->GetRowCount(count) != E_OK) { @@ -932,6 +950,7 @@ int RdbStoreImpl::ModifyLockStatus(const AbsRdbPredicates &predicates, bool isLo LOG_ERROR("GetHashKeyForLockRow failed, err is %{public}d.", ret); return ret; } + Suspender suspender(Suspender::SQL_LOG); auto [err, statement] = GetStatement(GlobalExpr::PRAGMA_VERSION); if (statement == nullptr || err != E_OK) { return err; @@ -1007,27 +1026,87 @@ RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config) isReadOnly_ = config.IsReadOnly() || config.GetRoleType() == VISITOR; } -RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config, int &errCode) - : isMemoryRdb_(config.IsMemoryRdb()), config_(config), name_(config.GetName()), - fileType_(config.GetDatabaseFileType()) +int32_t RdbStoreImpl::ProcessOpenCallback(int version, RdbOpenCallback &openCallback) { - isReadOnly_ = config.IsReadOnly() || config.GetRoleType() == VISITOR; - SqliteGlobalConfig::GetDbPath(config_, path_); - bool created = access(path_.c_str(), F_OK) != 0; + DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + int32_t errCode = E_OK; + if (version == -1) { + return errCode; + } + + int32_t currentVersion; + errCode = GetVersion(currentVersion); + if (errCode != E_OK) { + return errCode; + } + + if (version == currentVersion) { + return openCallback.OnOpen(*this); + } + + if (currentVersion == 0) { + errCode = openCallback.OnCreate(*this); + } else if (version > currentVersion) { + errCode = openCallback.OnUpgrade(*this, currentVersion, version); + } else { + errCode = openCallback.OnDowngrade(*this, currentVersion, version); + } + + if (errCode == E_OK) { + errCode = SetVersion(version); + } + + if (errCode != E_OK) { + LOG_ERROR("openCallback failed. version: %{public}d -> %{public}d, errCode:%{public}d", + currentVersion, version, errCode); + return errCode; + } + + return openCallback.OnOpen(*this); +} + +bool RdbStoreImpl::TryAsyncRepair() +{ + std::string slavePath = SqliteUtils::GetSlavePath(path_); + if (!IsUseAsyncRestore(path_, slavePath)) { + return false; + } + + int errCode = Connection::CheckReplicaIntegrity(config_); + if (errCode != E_OK) { + return false; + } + + SqliteUtils::DeleteDirtyFiles(path_); + auto pool = ConnectionPool::Create(config_, errCode); + if (errCode != E_OK) { + LOG_WARN("create new connection failed"); + return false; + } + connectionPool_ = pool; + errCode = StartAsyncRestore(pool); + if (errCode != E_OK) { + return false; + } + rebuild_ = RebuiltType::REPAIRED; + + Reportor::ReportRestore(Reportor::Create(config_, E_OK, "RestoreType:Rebuild", false), false); + return true; +} +int32_t RdbStoreImpl::CreatePool(bool &created) +{ + int32_t errCode = E_OK; connectionPool_ = ConnectionPool::Create(config_, errCode); if (connectionPool_ == nullptr && (errCode == E_SQLITE_CORRUPT || errCode == E_INVALID_SECRET_KEY) && !isReadOnly_) { LOG_ERROR("database corrupt, errCode:0x%{public}x, %{public}s, %{public}s", errCode, SqliteUtils::Anonymous(name_).c_str(), SqliteUtils::FormatDebugInfoBrief(Connection::Collect(config_), "master").c_str()); -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) - RdbParam param; - param.bundleName_ = config_.GetBundleName(); - param.storeName_ = config_.GetName(); - param.subUser_ = config_.GetSubUser(); - auto [err, service] = RdbMgr::GetInstance().GetRdbService(param); +#if !defined(CROSS_PLATFORM) + InitSyncerParam(config_, false); + auto [err, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); if (service != nullptr) { - service->Disable(param); + service->Disable(syncerParam_); } #endif config_.SetIter(0); @@ -1036,23 +1115,71 @@ RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config, int &errCode) RdbSecurityManager::GetInstance().RestoreKeyFile(path_, key); key.assign(key.size(), 0); } - std::tie(rebuild_, connectionPool_) = ConnectionPool::HandleDataCorruption(config_, errCode); + + if (TryAsyncRepair()) { + errCode = E_OK; + } else { + std::tie(rebuild_, connectionPool_) = ConnectionPool::HandleDataCorruption(config_, errCode); + } created = true; -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) +#if !defined(CROSS_PLATFORM) if (service != nullptr) { - service->Enable(param); + service->Enable(syncerParam_); } #endif } + return errCode; +} + +int32_t RdbStoreImpl::SetSecurityLabel(const RdbStoreConfig &config) +{ + if (config.IsMemoryRdb()) { + return E_OK; + } +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) + return SecurityPolicy::SetSecurityLabel(config); +#endif + return E_OK; +} + +int32_t RdbStoreImpl::Init(int version, RdbOpenCallback &openCallback) +{ + if (initStatus_ != -1) { + return initStatus_; + } + std::lock_guard lock(initMutex_); + if (initStatus_ != -1) { + return initStatus_; + } + int32_t errCode = E_OK; + bool created = access(path_.c_str(), F_OK) != 0; + errCode = CreatePool(created); if (connectionPool_ == nullptr || errCode != E_OK) { connectionPool_ = nullptr; LOG_ERROR("Create connPool failed, err is %{public}d, path:%{public}s", errCode, SqliteUtils::Anonymous(path_).c_str()); - return; + return errCode; } InitSyncerParam(config_, created); InitReportFunc(syncerParam_); InnerOpen(); + + if (config_.GetRoleType() == OWNER && !config_.IsReadOnly()) { + errCode = SetSecurityLabel(config_); + if (errCode != E_OK) { + return errCode; + } + (void) ExchangeSlaverToMaster(); + SwitchOver(true); + errCode = ProcessOpenCallback(version, openCallback); + SwitchOver(false); + if (errCode != E_OK) { + LOG_ERROR("Callback fail, path:%{public}s code:%{public}d", SqliteUtils::Anonymous(path_).c_str(), errCode); + return errCode; + } + } + initStatus_ = errCode; + return initStatus_; } RdbStoreImpl::~RdbStoreImpl() @@ -1066,6 +1193,10 @@ RdbStoreImpl::~RdbStoreImpl() } } transactions_ = {}; + if (knowledgeSchemaHelper_ != nullptr) { + knowledgeSchemaHelper_->Close(); + } + *slaveStatus_ = SlaveStatus::DB_CLOSING; } const RdbStoreConfig &RdbStoreImpl::GetConfig() @@ -1079,44 +1210,16 @@ std::pair RdbStoreImpl::Insert(const std::string &table, const Row if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { return { E_NOT_SUPPORT, -1 }; } - if (table.empty()) { - return { E_EMPTY_TABLE_NAME, -1 }; - } - - if (row.IsEmpty()) { - return { E_EMPTY_VALUES_BUCKET, -1 }; - } - - auto conflictClause = SqliteUtils::GetConflictClause(static_cast(resolution)); - if (conflictClause == nullptr) { - return { E_INVALID_CONFLICT_FLAG, -1 }; - } RdbStatReporter reportStat(RDB_PERF, INSERT, config_, reportFunc_); SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); - std::string sql; - sql.append("INSERT").append(conflictClause).append(" INTO ").append(table).append("("); - size_t bindArgsSize = row.values_.size(); - std::vector bindArgs; - bindArgs.reserve(bindArgsSize); - const char *split = ""; - for (const auto &[key, val] : row.values_) { - sql.append(split).append(key); - if (val.GetType() == ValueObject::TYPE_ASSETS && resolution == ConflictResolution::ON_CONFLICT_REPLACE) { - return { E_INVALID_ARGS, -1 }; - } - SqliteSqlBuilder::UpdateAssetStatus(val, AssetValue::STATUS_INSERT); - bindArgs.push_back(val); // columnValue - split = ","; - } - - sql.append(") VALUES ("); - if (bindArgsSize > 0) { - sql.append(SqliteSqlBuilder::GetSqlArgs(bindArgsSize)); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL); + auto [status, sqlInfo] = RdbSqlUtils::GetInsertSqlInfo(table, row, resolution); + if (status != E_OK) { + return { status, -1 }; } - sql.append(")"); int64_t rowid = -1; - auto errCode = ExecuteForLastInsertedRowId(rowid, sql, bindArgs); + auto errCode = ExecuteForLastInsertedRowId(rowid, sqlInfo.sql, sqlInfo.args); if (errCode == E_OK) { DoCloudSync(table); } @@ -1126,7 +1229,7 @@ std::pair RdbStoreImpl::Insert(const std::string &table, const Row std::pair RdbStoreImpl::BatchInsert(const std::string &table, const ValuesBuckets &rows) { - if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { + if (isReadOnly_) { return { E_NOT_SUPPORT, -1 }; } @@ -1136,6 +1239,7 @@ std::pair RdbStoreImpl::BatchInsert(const std::string &table, cons RdbStatReporter reportStat(RDB_PERF, BATCHINSERT, config_, reportFunc_); SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL, 0, rows.RowSize()); auto pool = GetPool(); if (pool == nullptr) { return { E_ALREADY_CLOSED, -1 }; @@ -1148,8 +1252,8 @@ std::pair RdbStoreImpl::BatchInsert(const std::string &table, cons auto executeSqlArgs = SqliteSqlBuilder::GenerateSqls(table, rows, conn->GetMaxVariable()); BatchInsertArgsDfx(static_cast(executeSqlArgs.size())); if (executeSqlArgs.empty()) { - LOG_ERROR("empty, table=%{public}s, values:%{public}zu, max number:%{public}d.", table.c_str(), rows.RowSize(), - conn->GetMaxVariable()); + LOG_ERROR("empty, table=%{public}s, values:%{public}zu, max number:%{public}d.", + SqliteUtils::Anonymous(table).c_str(), rows.RowSize(), conn->GetMaxVariable()); return { E_INVALID_ARGS, -1 }; } PauseDelayNotify pauseDelayNotify(delayNotifier_); @@ -1157,7 +1261,7 @@ std::pair RdbStoreImpl::BatchInsert(const std::string &table, cons auto [errCode, statement] = GetStatement(sql, conn); if (statement == nullptr) { LOG_ERROR("statement is nullptr, errCode:0x%{public}x, args:%{public}zu, table:%{public}s, " - "app self can check the SQL", errCode, bindArgs.size(), table.c_str()); + "app self can check the SQL", errCode, bindArgs.size(), SqliteUtils::Anonymous(table).c_str()); return { E_OK, -1 }; } for (const auto &args : bindArgs) { @@ -1168,7 +1272,7 @@ std::pair RdbStoreImpl::BatchInsert(const std::string &table, cons } if (errCode != E_OK) { LOG_ERROR("failed, errCode:%{public}d,args:%{public}zu,table:%{public}s,app self can check the SQL", - errCode, bindArgs.size(), table.c_str()); + errCode, bindArgs.size(), SqliteUtils::Anonymous(table).c_str()); return { E_OK, -1 }; } } @@ -1186,8 +1290,8 @@ void RdbStoreImpl::BatchInsertArgsDfx(int argsSize) } } -std::pair RdbStoreImpl::BatchInsertWithConflictResolution( - const std::string &table, const ValuesBuckets &rows, Resolution resolution) +std::pair RdbStoreImpl::BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution) { if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { return { E_NOT_SUPPORT, -1 }; @@ -1197,7 +1301,9 @@ std::pair RdbStoreImpl::BatchInsertWithConflictResolution( return { E_OK, 0 }; } + RdbStatReporter reportStat(RDB_PERF, BATCHINSERT, config_, reportFunc_); SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL, 0, rows.RowSize()); auto pool = GetPool(); if (pool == nullptr) { return { E_ALREADY_CLOSED, -1 }; @@ -1211,113 +1317,76 @@ std::pair RdbStoreImpl::BatchInsertWithConflictResolution( // To ensure atomicity, execute SQL only once if (sqlArgs.size() != 1 || sqlArgs.front().second.size() != 1) { auto [fields, values] = rows.GetFieldsAndValues(); - LOG_ERROR("invalid args, table=%{public}s, rows:%{public}zu, fields:%{public}zu, max:%{public}d.", - table.c_str(), rows.RowSize(), fields != nullptr ? fields->size() : 0, conn->GetMaxVariable()); + LOG_ERROR("invalid! rows:%{public}zu, table:%{public}s, fields:%{public}zu, max:%{public}d.", rows.RowSize(), + SqliteUtils::Anonymous(table).c_str(), fields != nullptr ? fields->size() : 0, conn->GetMaxVariable()); return { E_INVALID_ARGS, -1 }; } auto &[sql, bindArgs] = sqlArgs.front(); + SqliteSqlBuilder::AppendReturning(sql, returningFields); auto [errCode, statement] = GetStatement(sql, conn); if (statement == nullptr) { LOG_ERROR("statement is nullptr, errCode:0x%{public}x, args:%{public}zu, table:%{public}s, " - "app self can check the SQL", errCode, bindArgs.size(), table.c_str()); + "app self can check the SQL", errCode, bindArgs.size(), SqliteUtils::Anonymous(table).c_str()); return { errCode, -1 }; } PauseDelayNotify pauseDelayNotify(delayNotifier_); - auto args = std::ref(bindArgs.front()); - errCode = statement->Execute(args); + errCode = statement->Execute(std::ref(bindArgs.front())); if (errCode == E_SQLITE_LOCKED || errCode == E_SQLITE_BUSY) { pool->Dump(true, "BATCH"); return { errCode, -1 }; } if (errCode != E_OK) { LOG_ERROR("failed,errCode:%{public}d,table:%{public}s,args:%{public}zu,resolution:%{public}d.", errCode, - table.c_str(), args.get().size(), static_cast(resolution)); - return { errCode, errCode == E_SQLITE_CONSTRAINT ? int64_t(statement->Changes()) : -1 }; + SqliteUtils::Anonymous(table).c_str(), bindArgs.front().size(), static_cast(resolution)); } - conn = nullptr; - DoCloudSync(table); - return { E_OK, int64_t(statement->Changes()) }; + auto result = GenerateResult(errCode, statement); + if (result.changed > 0) { + DoCloudSync(table); + } + return { errCode, result }; } -std::pair RdbStoreImpl::Update( - const std::string &table, const Row &row, const std::string &where, const Values &args, Resolution resolution) +std::pair RdbStoreImpl::Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { return { E_NOT_SUPPORT, -1 }; } - if (table.empty()) { - return { E_EMPTY_TABLE_NAME, -1 }; - } - - if (row.IsEmpty()) { - return { E_EMPTY_VALUES_BUCKET, -1 }; - } - - auto clause = SqliteUtils::GetConflictClause(static_cast(resolution)); - if (clause == nullptr) { - return { E_INVALID_CONFLICT_FLAG, -1 }; - } RdbStatReporter reportStat(RDB_PERF, UPDATE, config_, reportFunc_); SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); - std::string sql; - sql.append("UPDATE").append(clause).append(" ").append(table).append(" SET "); - std::vector tmpBindArgs; - size_t tmpBindSize = row.values_.size() + args.size(); - tmpBindArgs.reserve(tmpBindSize); - const char *split = ""; - for (auto &[key, val] : row.values_) { - sql.append(split); - if (val.GetType() == ValueObject::TYPE_ASSETS) { - sql.append(key).append("=merge_assets(").append(key).append(", ?)"); // columnName - } else if (val.GetType() == ValueObject::TYPE_ASSET) { - sql.append(key).append("=merge_asset(").append(key).append(", ?)"); // columnName - } else { - sql.append(key).append("=?"); // columnName - } - tmpBindArgs.push_back(val); // columnValue - split = ","; + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL); + auto [status, sqlInfo] = RdbSqlUtils::GetUpdateSqlInfo(predicates, row, resolution, returningFields); + if (status != E_OK) { + return { status, -1 }; } - - if (!where.empty()) { - sql.append(" WHERE ").append(where); + auto [code, result] = ExecuteForRow(sqlInfo.sql, sqlInfo.args); + if (result.changed > 0) { + DoCloudSync(predicates.GetTableName()); } - - tmpBindArgs.insert(tmpBindArgs.end(), args.begin(), args.end()); - - int64_t changes = 0; - auto errCode = ExecuteForChangedRowCount(changes, sql, tmpBindArgs); - if (errCode == E_OK) { - DoCloudSync(table); - } - return { errCode, int32_t(changes) }; + return { code, result }; } -int RdbStoreImpl::Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) +std::pair RdbStoreImpl::Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { - return E_NOT_SUPPORT; - } - if (table.empty()) { - return E_EMPTY_TABLE_NAME; + return { E_NOT_SUPPORT, -1 }; } - RdbStatReporter reportStat(RDB_PERF, DELETE, config_, reportFunc_); SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); - std::string sql; - sql.append("DELETE FROM ").append(table); - if (!whereClause.empty()) { - sql.append(" WHERE ").append(whereClause); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL); + auto [status, sqlInfo] = RdbSqlUtils::GetDeleteSqlInfo(predicates, returningFields); + if (status != E_OK) { + return { status, -1 }; } - int64_t changes = 0; - auto errCode = ExecuteForChangedRowCount(changes, sql, args); - if (errCode != E_OK) { - return errCode; + + auto [code, result] = ExecuteForRow(sqlInfo.sql, predicates.GetBindArgs()); + if (result.changed > 0) { + DoCloudSync(predicates.GetTableName()); } - deletedRows = changes; - DoCloudSync(table); - return E_OK; + return { code, result }; } std::shared_ptr RdbStoreImpl::QuerySql(const std::string &sql, const Values &bindArgs) @@ -1327,7 +1396,8 @@ std::shared_ptr RdbStoreImpl::QuerySql(const std::string &sq return nullptr; } SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL); +#if !defined(CROSS_PLATFORM) auto start = std::chrono::steady_clock::now(); auto pool = GetPool(); if (pool == nullptr) { @@ -1345,13 +1415,14 @@ std::shared_ptr RdbStoreImpl::QuerySql(const std::string &sq std::shared_ptr RdbStoreImpl::QueryByStep(const std::string &sql, const Values &args, bool preCount) { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL); auto start = std::chrono::steady_clock::now(); auto pool = GetPool(); if (pool == nullptr) { LOG_ERROR("Database already closed."); return nullptr; } -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) +#if !defined(CROSS_PLATFORM) return std::make_shared(start, connectionPool_->AcquireRef(true), sql, args, preCount); #else return std::make_shared(start, connectionPool_->AcquireRef(true), sql, args, false); @@ -1382,25 +1453,33 @@ void WriteToCompareFile(const std::string &dbPath, const std::string &bundleName } } -void RdbStoreImpl::HandleSchemaDDL(std::shared_ptr statement, - std::shared_ptr pool, const std::string &sql, int32_t &errCode) +int32_t RdbStoreImpl::HandleSchemaDDL(std::shared_ptr &&statement, const std::string &sql) { statement->Reset(); + Suspender suspender(Suspender::SQL_STATISTIC); statement->Prepare("PRAGMA schema_version"); auto [err, version] = statement->ExecuteForValue(); statement = nullptr; if (vSchema_ < static_cast(version)) { - LOG_INFO("db:%{public}s exe DDL schema<%{public}" PRIi64 "->%{public}" PRIi64 - "> app self can check the SQL.", + LOG_INFO("db:%{public}s exe DDL schema<%{public}" PRIi64 "->%{public}" PRIi64 ">", SqliteUtils::Anonymous(name_).c_str(), vSchema_, static_cast(version)); vSchema_ = version; - errCode = pool->RestartConns(); if (!isMemoryRdb_) { std::string dbPath = config_.GetPath(); std::string bundleName = config_.GetBundleName(); WriteToCompareFile(dbPath, bundleName, sql); } + statement = nullptr; + if (config_.GetEnableSemanticIndex() && !isKnowledgeSchemaReady_) { + SetKnowledgeSchema(); + } + auto pool = GetPool(); + if (pool == nullptr) { + return E_ALREADY_CLOSED; + } + return pool->RestartConns(); } + return E_OK; } int RdbStoreImpl::ExecuteSql(const std::string &sql, const Values &args) @@ -1415,25 +1494,20 @@ int RdbStoreImpl::ExecuteSql(const std::string &sql, const Values &args) } RdbStatReporter reportStat(RDB_PERF, EXECUTESQL, config_, reportFunc_); SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL); auto [errCode, statement] = BeginExecuteSql(sql); if (statement == nullptr) { return errCode; } - auto pool = GetPool(); - if (pool == nullptr) { - return E_ALREADY_CLOSED; - } errCode = statement->Execute(args); if (errCode != E_OK) { LOG_ERROR("failed,error:0x%{public}x app self can check the SQL.", errCode); - if (errCode == E_SQLITE_LOCKED || errCode == E_SQLITE_BUSY) { - pool->Dump(true, "EXECUTE"); - } + TryDump(errCode, "EXECUTE"); return errCode; } int sqlType = SqliteUtils::GetSqlStatementType(sql); if (sqlType == SqliteUtils::STATEMENT_DDL) { - HandleSchemaDDL(statement, pool, sql, errCode); + HandleSchemaDDL(std::move(statement), sql); } statement = nullptr; if (errCode == E_OK && (sqlType == SqliteUtils::STATEMENT_UPDATE || sqlType == SqliteUtils::STATEMENT_INSERT)) { @@ -1451,6 +1525,7 @@ std::pair RdbStoreImpl::Execute(const std::string &sql, co RdbStatReporter reportStat(RDB_PERF, EXECUTE, config_, reportFunc_); SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL); int sqlType = SqliteUtils::GetSqlStatementType(sql); if (!SqliteUtils::IsSupportSqlForExecute(sqlType)) { LOG_ERROR("Not support the sqlType: %{public}d, app self can check the SQL", sqlType); @@ -1461,48 +1536,34 @@ std::pair RdbStoreImpl::Execute(const std::string &sql, co return { ExecuteByTrxId(sql, trxId, false, args), ValueObject() }; } - auto pool = GetPool(); - if (pool == nullptr) { - return { E_ALREADY_CLOSED, object }; - } - auto conn = pool->AcquireConnection(false); - if (pool == nullptr) { - return { E_DATABASE_BUSY, object }; - } - - auto [errCode, statement] = GetStatement(sql, conn); - if (errCode != E_OK) { - return { errCode, object }; + auto [errCode, statement] = GetStatement(sql, false); + if (errCode != E_OK || statement == nullptr) { + return { errCode != E_OK ? errCode : E_ERROR, object }; } errCode = statement->Execute(args); - if (errCode != E_OK) { - LOG_ERROR("failed,error:0x%{public}x app self can check the SQL.", errCode); - if (errCode == E_SQLITE_LOCKED || errCode == E_SQLITE_BUSY) { - pool->Dump(true, "EXECUTE"); - } - return { errCode, object }; - } - + TryDump(errCode, "EXECUTE"); if (config_.IsVector()) { return { errCode, object }; } - return HandleDifferentSqlTypes(statement, sql, object, sqlType); + return HandleDifferentSqlTypes(std::move(statement), sql, errCode, sqlType); } std::pair RdbStoreImpl::HandleDifferentSqlTypes( - std::shared_ptr statement, const std::string &sql, const ValueObject &object, int sqlType) + std::shared_ptr &&statement, const std::string &sql, int32_t code, int sqlType) { - int32_t errCode = E_OK; + if (code != E_OK) { + return { code, ValueObject() }; + } if (sqlType == SqliteUtils::STATEMENT_INSERT) { int64_t outValue = statement->Changes() > 0 ? statement->LastInsertRowId() : -1; - return { errCode, ValueObject(outValue) }; + return { code, ValueObject(outValue) }; } if (sqlType == SqliteUtils::STATEMENT_UPDATE) { int outValue = statement->Changes(); - return { errCode, ValueObject(outValue) }; + return { code, ValueObject(outValue) }; } if (sqlType == SqliteUtils::STATEMENT_PRAGMA) { @@ -1512,19 +1573,47 @@ std::pair RdbStoreImpl::HandleDifferentSqlTypes( if (statement->GetColumnCount() > 1) { LOG_ERROR("Not support the sql:app self can check the SQL, column count more than 1"); - return { E_NOT_SUPPORT_THE_SQL, object }; + return { E_NOT_SUPPORT_THE_SQL, ValueObject() }; } } - auto pool = GetPool(); - if (pool == nullptr) { - return { E_ALREADY_CLOSED, object }; + if (sqlType == SqliteUtils::STATEMENT_DDL) { + HandleSchemaDDL(std::move(statement), sql); + } + return { code, ValueObject() }; +} + +std::pair RdbStoreImpl::ExecuteExt(const std::string &sql, const Values &args) +{ + if (isReadOnly_ || config_.IsVector()) { + return { E_NOT_SUPPORT, -1 }; } + RdbStatReporter reportStat(RDB_PERF, EXECUTE, config_, reportFunc_); + SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + int sqlType = SqliteUtils::GetSqlStatementType(sql); + if (!SqliteUtils::IsSupportSqlForExecute(sqlType)) { + LOG_ERROR("Not support the sqlType: %{public}d, app self can check the SQL", sqlType); + return { E_NOT_SUPPORT_THE_SQL, -1 }; + } + auto [errCode, statement] = GetStatement(sql, false); + if (errCode != E_OK) { + return { errCode, -1 }; + } + errCode = statement->Execute(args); + TryDump(errCode, "ExecuteExt"); + return HandleResults(std::move(statement), sql, errCode, sqlType); +} + +std::pair RdbStoreImpl::HandleResults( + std::shared_ptr &&statement, const std::string &sql, int32_t code, int sqlType) +{ + Results result = GenerateResult( + code, statement, sqlType == SqliteUtils::STATEMENT_INSERT || sqlType == SqliteUtils::STATEMENT_UPDATE); if (sqlType == SqliteUtils::STATEMENT_DDL) { - HandleSchemaDDL(statement, pool, sql, errCode); + HandleSchemaDDL(std::move(statement), sql); } - return { errCode, object }; + return { code, result }; } int RdbStoreImpl::ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const Values &args) @@ -1594,32 +1683,35 @@ int RdbStoreImpl::ExecuteForLastInsertedRowId(int64_t &outValue, const std::stri LOG_WARN("total[%{public}" PRId64 "] stmt[%{public}" PRId64 "] exec[%{public}" PRId64 "] result[%{public}" PRId64 "] " "sql[%{public}s]", - totalCostTime, prepareCost, execCost, resultCost, SqliteUtils::Anonymous(sql).c_str()); + totalCostTime, prepareCost, execCost, resultCost, SqliteUtils::SqlAnonymous(sql).c_str()); } return E_OK; } -int RdbStoreImpl::ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, const Values &args) +std::pair RdbStoreImpl::ExecuteForRow(const std::string &sql, const Values &args) { if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { - return E_NOT_SUPPORT; + return { E_NOT_SUPPORT, -1 }; } auto [errCode, statement] = GetStatement(sql, false); if (statement == nullptr) { - return errCode; + return { errCode, -1 }; } errCode = statement->Execute(args); - if (errCode == E_OK) { - outValue = statement->Changes(); - return E_OK; - } if (errCode == E_SQLITE_LOCKED || errCode == E_SQLITE_BUSY) { auto pool = GetPool(); if (pool != nullptr) { pool->Dump(true, "UPG DEL"); } } - return errCode; + return { errCode, GenerateResult(errCode, statement) }; +} + +int RdbStoreImpl::ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, const Values &args) +{ + auto [code, result] = ExecuteForRow(sql, args); + outValue = result.changed; + return code; } int RdbStoreImpl::GetDataBasePath(const std::string &databasePath, std::string &backupFilePath) @@ -1664,16 +1756,17 @@ int RdbStoreImpl::GetSlaveName(const std::string &path, std::string &backupFileP /** * Backup a database from a specified encrypted or unencrypted database file. + * Support skipping verification. */ -int RdbStoreImpl::Backup(const std::string &databasePath, const std::vector &encryptKey) +int RdbStoreImpl::Backup(const std::string &databasePath, const std::vector &encryptKey, bool verifyDb) { - LOG_INFO("Backup db: %{public}s.", SqliteUtils::Anonymous(config_.GetName()).c_str()); + LOG_INFO("Backup db: %{public}s, verify: %{public}d.", SqliteUtils::Anonymous(config_.GetName()).c_str(), verifyDb); if (isReadOnly_ || isMemoryRdb_) { return E_NOT_SUPPORT; } std::string backupFilePath; if (TryGetMasterSlaveBackupPath(databasePath, backupFilePath)) { - return InnerBackup(backupFilePath, encryptKey); + return InnerBackup(backupFilePath, encryptKey, verifyDb); } int ret = GetDataBasePath(databasePath, backupFilePath); @@ -1737,7 +1830,8 @@ std::vector RdbStoreImpl::CreateBackupBindArgs( /** * Backup a database from a specified encrypted or unencrypted database file. */ -int RdbStoreImpl::InnerBackup(const std::string &databasePath, const std::vector &destEncryptKey) +int RdbStoreImpl::InnerBackup( + const std::string &databasePath, const std::vector &destEncryptKey, bool verifyDb) { if (isReadOnly_) { return E_NOT_SUPPORT; @@ -1750,10 +1844,13 @@ int RdbStoreImpl::InnerBackup(const std::string &databasePath, const std::vector if (config_.GetHaMode() != HAMode::SINGLE && SqliteUtils::IsSlaveDbName(databasePath)) { auto [errCode, conn] = GetConn(false); - return errCode != E_OK ? errCode : conn->Backup(databasePath, {}, false, slaveStatus_); + return errCode != E_OK ? errCode : conn->Backup(databasePath, {}, false, slaveStatus_, verifyDb); } - - auto [result, conn] = CreateWritableConn(); + Suspender suspender(Suspender::SQL_LOG); + auto config = config_; + config.SetHaMode(HAMode::SINGLE); + config.SetCreateNecessary(false); + auto [result, conn] = CreateWritableConn(config); if (result != E_OK) { return result; } @@ -1766,7 +1863,7 @@ int RdbStoreImpl::InnerBackup(const std::string &databasePath, const std::vector } std::vector bindArgs = CreateBackupBindArgs(databasePath, destEncryptKey); - auto [errCode, statement] = conn->CreateStatement(GlobalExpr::ATTACH_BACKUP_SQL, conn); + auto [errCode, statement] = GetStatement(GlobalExpr::ATTACH_BACKUP_SQL, conn); errCode = statement->Execute(bindArgs); if (errCode != E_OK) { return errCode; @@ -1800,7 +1897,7 @@ std::pair RdbStoreImpl::BeginExecuteSql(const std:: return { E_DATABASE_BUSY, nullptr }; } - auto [errCode, statement] = conn->CreateStatement(sql, conn); + auto [errCode, statement] = GetStatement(sql, conn); if (statement == nullptr) { return { errCode, nullptr }; } @@ -1855,7 +1952,8 @@ int RdbStoreImpl::SetDefaultEncryptAlgo(const ConnectionPool::SharedConn &conn, std::string sql = std::string(GlobalExpr::CIPHER_DEFAULT_ATTACH_CIPHER_PREFIX) + SqliteUtils::EncryptAlgoDescription(config.GetEncryptAlgo()) + std::string(GlobalExpr::ALGO_SUFFIX); - auto [errCode, statement] = conn->CreateStatement(sql, conn); + Suspender suspender(Suspender::SQL_LOG); + auto [errCode, statement] = GetStatement(sql, conn); errCode = SetDefaultEncryptSql(statement, sql, config); if (errCode != E_OK) { return errCode; @@ -1896,6 +1994,7 @@ int RdbStoreImpl::AttachInner(const RdbStoreConfig &config, const std::string &a if (pool == nullptr) { return E_ALREADY_CLOSED; } + Suspender suspender(Suspender::SQL_LOG); auto [conn, readers] = pool->AcquireAll(waitTime); if (conn == nullptr) { return E_DATABASE_BUSY; @@ -1921,7 +2020,7 @@ int RdbStoreImpl::AttachInner(const RdbStoreConfig &config, const std::string &a return ret; } bindArgs.emplace_back(ValueObject(key)); - auto [errCode, statement] = conn->CreateStatement(GlobalExpr::ATTACH_WITH_KEY_SQL, conn); + auto [errCode, statement] = GetStatement(GlobalExpr::ATTACH_WITH_KEY_SQL, conn); if (statement == nullptr || errCode != E_OK) { LOG_ERROR("Attach get statement failed, code is %{public}d", errCode); return E_ERROR; @@ -1929,7 +2028,7 @@ int RdbStoreImpl::AttachInner(const RdbStoreConfig &config, const std::string &a return statement->Execute(bindArgs); } - auto [errCode, statement] = conn->CreateStatement(GlobalExpr::ATTACH_SQL, conn); + auto [errCode, statement] = GetStatement(GlobalExpr::ATTACH_SQL, conn); if (statement == nullptr || errCode != E_OK) { LOG_ERROR("Attach get statement failed, code is %{public}d", errCode); return errCode; @@ -1975,7 +2074,7 @@ std::pair RdbStoreImpl::Attach( } else if (err != E_OK) { LOG_ERROR("failed, errCode[%{public}d] fileName[%{public}s] attachName[%{public}s] attach fileName" "[%{public}s]", - err, SqliteUtils::Anonymous(config_.GetName()).c_str(), attachName.c_str(), + err, SqliteUtils::Anonymous(config_.GetName()).c_str(), SqliteUtils::Anonymous(attachName).c_str(), SqliteUtils::Anonymous(config.GetName()).c_str()); return { err, 0 }; } @@ -1993,7 +2092,7 @@ std::pair RdbStoreImpl::Detach(const std::string &attachName, if (!attachedInfo_.Contains(attachName)) { return { E_OK, attachedInfo_.Size() }; } - + Suspender suspender(Suspender::SQL_LOG); auto pool = GetPool(); if (pool == nullptr) { return { E_ALREADY_CLOSED, 0 }; @@ -2005,7 +2104,7 @@ std::pair RdbStoreImpl::Detach(const std::string &attachName, std::vector bindArgs; bindArgs.push_back(ValueObject(attachName)); - auto [errCode, statement] = connection->CreateStatement(GlobalExpr::DETACH_SQL, connection); + auto [errCode, statement] = GetStatement(GlobalExpr::DETACH_SQL, connection); if (statement == nullptr || errCode != E_OK) { LOG_ERROR("Detach get statement failed, errCode %{public}d", errCode); return { errCode, 0 }; @@ -2013,7 +2112,7 @@ std::pair RdbStoreImpl::Detach(const std::string &attachName, errCode = statement->Execute(bindArgs); if (errCode != E_OK) { LOG_ERROR("failed, errCode[%{public}d] fileName[%{public}s] attachName[%{public}s] attach", errCode, - SqliteUtils::Anonymous(config_.GetName()).c_str(), attachName.c_str()); + SqliteUtils::Anonymous(config_.GetName()).c_str(), SqliteUtils::Anonymous(attachName).c_str()); return { errCode, 0 }; } @@ -2037,6 +2136,7 @@ std::pair RdbStoreImpl::Detach(const std::string &attachName, */ int RdbStoreImpl::GetVersion(int &version) { + Suspender suspender(Suspender::SQL_LOG); auto [errCode, statement] = GetStatement(GlobalExpr::PRAGMA_VERSION, isReadOnly_); if (statement == nullptr) { return errCode; @@ -2058,6 +2158,7 @@ int RdbStoreImpl::SetVersion(int version) if (isReadOnly_) { return E_NOT_SUPPORT; } + Suspender suspender(Suspender::SQL_LOG); std::string sql = std::string(GlobalExpr::PRAGMA_VERSION) + " = " + std::to_string(version); auto [errCode, statement] = GetStatement(sql); if (statement == nullptr) { @@ -2113,7 +2214,6 @@ std::pair RdbStoreImpl::BeginTrans() if (!config_.IsVector() || isReadOnly_) { return { E_NOT_SUPPORT, 0 }; } - int64_t tmpTrxId = 0; auto pool = GetPool(); if (pool == nullptr) { @@ -2222,7 +2322,6 @@ int RdbStoreImpl::ExecuteByTrxId( if (ret != E_OK) { LOG_ERROR("transaction id: %{public}" PRIu64 ", storeName: %{public}s, errCode: %{public}d" PRIu64, trxId, SqliteUtils::Anonymous(name_).c_str(), ret); - trxConnMap_.Erase(trxId); return ret; } if (closeConnAfterExecute) { @@ -2261,7 +2360,8 @@ int RdbStoreImpl::Commit() std::string sqlStr = transaction.GetCommitStr(); if (sqlStr.size() <= 1) { LOG_WARN("id: %{public}zu, storeName: %{public}s, sql: %{public}s", transactionId, - SqliteUtils::Anonymous(name_).c_str(), sqlStr.c_str()); + SqliteUtils::Anonymous(name_).c_str(), + SqliteUtils::SqlAnonymous(sqlStr).c_str()); pool->GetTransactionStack().pop(); return E_OK; } @@ -2324,7 +2424,7 @@ int RdbStoreImpl::CheckAttach(const std::string &sql) if (sqlType != "ATT") { return E_OK; } - + Suspender suspender(Suspender::SQL_LOG); auto [errCode, statement] = GetStatement(GlobalExpr::PRAGMA_JOUR_MODE_EXP); if (statement == nullptr) { return errCode; @@ -2377,7 +2477,7 @@ std::string RdbStoreImpl::GetName() void RdbStoreImpl::DoCloudSync(const std::string &table) { -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) +#if !defined(CROSS_PLATFORM) auto needSync = cloudInfo_->Change(table); if (!needSync) { return; @@ -2422,6 +2522,7 @@ int RdbStoreImpl::ConfigLocale(const std::string &localeStr) if (pool == nullptr) { return E_ALREADY_CLOSED; } + config_.SetCollatorLocales(localeStr); return pool->ConfigLocale(localeStr); } @@ -2443,6 +2544,128 @@ int RdbStoreImpl::GetDestPath(const std::string &backupPath, std::string &destPa return E_OK; } +void RdbStoreImpl::SwitchOver(bool isUseReplicaDb) +{ + isUseReplicaDb_ = isUseReplicaDb; +} + +bool RdbStoreImpl::IsUseAsyncRestore(const std::string &newPath, const std::string &backupPath) +{ + if (config_.GetPath() == backupPath || newPath == backupPath || + config_.GetDBType() == DB_VECTOR || config_.GetHaMode() == HAMode::SINGLE || + !SqliteUtils::IsSlaveDbName(backupPath) || !SqliteUtils::IsSlaveLarge(config_.GetPath())) { + return false; + } + return true; +} + +int32_t RdbStoreImpl::RestoreWithPool(std::shared_ptr pool, const std::string &path) +{ + if (pool == nullptr) { + return E_OK; + } + auto connection = pool->AcquireConnection(false); + if (connection == nullptr) { + return E_DATABASE_BUSY; + } + pool->ReopenConns(); + auto curStatus = std::make_shared(SlaveStatus::UNDEFINED); + return connection->Restore(path, {}, curStatus); +} + +int RdbStoreImpl::StartAsyncRestore(std::shared_ptr pool) const +{ + auto keyFilesPtr = std::make_shared(path_ + ASYNC_RESTORE); + SqliteUtils::SetSlaveRestoring(path_); + auto err = keyFilesPtr->Lock(false); + if (err == E_OK) { + auto taskPool = TaskExecutor::GetInstance().GetExecutor(); + if (taskPool == nullptr) { + LOG_ERROR("Get thread pool failed"); + keyFilesPtr->Unlock(); + return E_ERROR; + } + taskPool->Execute([keyFilesPtr, config = config_, pool] { + auto dbPath = config.GetPath(); + LOG_INFO("async restore started for %{public}s", SqliteUtils::Anonymous(dbPath).c_str()); + auto result = RdbStoreImpl::RestoreWithPool(pool, dbPath); + if (result != E_OK) { + LOG_WARN("async restore failed, retry once, %{public}d", result); + result = RdbStoreImpl::RestoreWithPool(pool, dbPath); + } + if (result != E_OK) { + LOG_WARN("async restore failed, %{public}d", result); + SqliteUtils::SetSlaveInvalid(dbPath); + } + SqliteUtils::SetSlaveRestoring(dbPath, false); + if (pool != nullptr) { + pool->ReopenConns(); + } + keyFilesPtr->Unlock(); + }); + + return E_OK; + } + LOG_WARN("Get process lock failed. Async restore is started in another process, %{public}s", + SqliteUtils::Anonymous(path_).c_str()); + return E_OK; +} + +int RdbStoreImpl::StartAsyncBackupIfNeed(std::shared_ptr slaveStatus) +{ + auto taskPool = TaskExecutor::GetInstance().GetExecutor(); + if (taskPool == nullptr) { + LOG_ERROR("Get thread pool failed"); + return E_ERROR; + } + auto config = config_; + config.SetCreateNecessary(false); + taskPool->Execute([config, slaveStatus] { + if (*slaveStatus == SlaveStatus::DB_CLOSING) { + return; + } + auto [result, conn] = CreateWritableConn(config); + if (result != E_OK || conn == nullptr) { + return; + } + auto strategy = conn->GenerateExchangeStrategy(slaveStatus); + if (*slaveStatus == SlaveStatus::DB_CLOSING) { + return; + } + LOG_INFO("async exchange st:%{public}d,", strategy); + if (strategy == ExchangeStrategy::BACKUP) { + (void)conn->Backup({}, {}, false, slaveStatus); + } + }); + return E_OK; +} + +int RdbStoreImpl::RestoreInner(const std::string &destPath, const std::vector &newKey, + std::shared_ptr pool) +{ + bool isUseAsync = IsUseAsyncRestore(path_, destPath); + LOG_INFO("restore start, using async=%{public}d", isUseAsync); + if (!isUseAsync) { + auto err = pool->ChangeDbFileForRestore(path_, destPath, newKey, slaveStatus_); + LOG_INFO("restore finished, sync mode rc=%{public}d", err); + return err; + } + + auto connection = pool->AcquireConnection(false); + if (connection == nullptr) { + LOG_WARN("Failed to obtain writer for async restore"); + return E_DATABASE_BUSY; + } + + int errCode = connection->CheckReplicaForRestore(); + if (errCode != E_OK) { + return errCode; + } + errCode = StartAsyncRestore(pool); + LOG_INFO("restore finished, async mode rc=%{public}d", errCode); + return errCode; +} + int RdbStoreImpl::Restore(const std::string &backupPath, const std::vector &newKey) { LOG_INFO("Restore db: %{public}s.", SqliteUtils::Anonymous(config_.GetName()).c_str()); @@ -2467,16 +2690,16 @@ int RdbStoreImpl::Restore(const std::string &backupPath, const std::vectorDisable(syncerParam_); } #endif bool corrupt = Reportor::IsReportCorruptedFault(path_); - int errCode = pool->ChangeDbFileForRestore(path_, destPath, newKey, slaveStatus_); + int errCode = RestoreInner(destPath, newKey, pool); keyFiles.Unlock(); -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) +#if !defined(CROSS_PLATFORM) SecurityPolicy::SetSecurityLabel(config_); if (service != nullptr) { service->Enable(syncerParam_); @@ -2497,11 +2720,8 @@ int RdbStoreImpl::Restore(const std::string &backupPath, const std::vector> RdbStoreImpl::CreateWritableConn() +std::pair> RdbStoreImpl::CreateWritableConn(const RdbStoreConfig &config) { - auto config = config_; - config.SetHaMode(HAMode::SINGLE); - config.SetCreateNecessary(false); auto [result, conn] = Connection::Create(config, true); if (result != E_OK || conn == nullptr) { LOG_ERROR("create connection failed, err:%{public}d", result); @@ -2516,6 +2736,32 @@ std::pair> RdbStoreImpl::GetStatement( if (conn == nullptr) { return { E_DATABASE_BUSY, nullptr }; } + + if (config_.GetHaMode() != HAMode::SINGLE && SqliteUtils::IsSlaveRestoring(config_.GetPath())) { + auto keyFiles = RdbSecurityManager::KeyFiles(config_.GetPath() + ASYNC_RESTORE); + int32_t ret = keyFiles.Lock(false); + if (ret != E_OK) { + if (isUseReplicaDb_) { + LOG_INFO("Use replica statement, %{public}s", SqliteUtils::Anonymous(config_.GetPath()).c_str()); + return conn->CreateReplicaStatement(sql, conn); + } + return { E_DATABASE_BUSY, nullptr }; + } + SqliteUtils::SetSlaveRestoring(config_.GetPath(), false); + (void)keyFiles.Unlock(); + auto strategy = conn->GenerateExchangeStrategy(slaveStatus_); + LOG_WARN("Got lock file but process is not in restore, mark removed, st:%{public}d, %{public}s", + strategy, SqliteUtils::Anonymous(config_.GetPath()).c_str()); + if (strategy != ExchangeStrategy::RESTORE) { + return conn->CreateStatement(sql, conn); + } + auto result = conn->CheckReplicaForRestore(); + if (result == E_OK) { + result = StartAsyncRestore(GetPool()); + return conn->CreateReplicaStatement(sql, conn); + } + } + return conn->CreateStatement(sql, conn); } @@ -2529,7 +2775,7 @@ std::pair> RdbStoreImpl::GetStatement(const if (conn == nullptr) { return { E_DATABASE_BUSY, nullptr }; } - return conn->CreateStatement(sql, conn); + return GetStatement(sql, conn); } int RdbStoreImpl::GetRebuilt(RebuiltType &rebuilt) @@ -2543,8 +2789,8 @@ int RdbStoreImpl::InterruptBackup() if (config_.GetHaMode() != HAMode::MANUAL_TRIGGER) { return E_NOT_SUPPORT; } - if (slaveStatus_ == SlaveStatus::BACKING_UP) { - slaveStatus_ = SlaveStatus::BACKUP_INTERRUPT; + if (*slaveStatus_ == SlaveStatus::BACKING_UP) { + *slaveStatus_ = SlaveStatus::BACKUP_INTERRUPT; return E_OK; } return E_CANCEL; @@ -2555,7 +2801,7 @@ int32_t RdbStoreImpl::GetBackupStatus() const if (config_.GetHaMode() != HAMode::MANUAL_TRIGGER && config_.GetHaMode() != HAMode::MAIN_REPLICA) { return SlaveStatus::UNDEFINED; } - return slaveStatus_; + return *slaveStatus_; } bool RdbStoreImpl::TryGetMasterSlaveBackupPath(const std::string &srcPath, std::string &destPath, bool isRestore) @@ -2590,18 +2836,20 @@ int32_t RdbStoreImpl::ExchangeSlaverToMaster() if (errCode != E_OK) { return errCode; } - auto strategy = conn->GenerateExchangeStrategy(slaveStatus_); + auto strategy = conn->GenerateExchangeStrategy(slaveStatus_, false); if (strategy != ExchangeStrategy::NOT_HANDLE) { LOG_WARN("exchange st:%{public}d, %{public}s,", strategy, SqliteUtils::Anonymous(config_.GetName()).c_str()); } int ret = E_OK; - if (strategy == ExchangeStrategy::RESTORE) { + if (strategy == ExchangeStrategy::RESTORE && !SqliteUtils::IsSlaveRestoring(config_.GetPath())) { conn = nullptr; // disable is required before restore ret = Restore({}, {}); } else if (strategy == ExchangeStrategy::BACKUP) { // async backup ret = conn->Backup({}, {}, true, slaveStatus_); + } else if (strategy == ExchangeStrategy::PENDING_BACKUP) { + ret = StartAsyncBackupIfNeed(slaveStatus_); } return ret; } @@ -2616,17 +2864,17 @@ std::pair> RdbStoreImpl::CreateTransaction if (isReadOnly_) { return { E_NOT_SUPPORT, nullptr }; } - auto pool = GetPool(); if (pool == nullptr) { return { E_ALREADY_CLOSED, nullptr }; } + PerfStat perfStat(config_.GetPath(), "", PerfStat::Step::STEP_TOTAL); auto [errCode, conn] = pool->CreateTransConn(); if (conn == nullptr) { return { errCode, nullptr }; } std::shared_ptr trans; - std::tie(errCode, trans) = Transaction::Create(type, conn, config_.GetName()); + std::tie(errCode, trans) = Transaction::Create(type, conn, config_.GetPath()); if (trans == nullptr) { if (errCode == E_SQLITE_LOCKED || errCode == E_SQLITE_BUSY) { pool->Dump(true, "TRANS"); @@ -2646,6 +2894,68 @@ std::pair> RdbStoreImpl::CreateTransaction return { errCode, trans }; } +int RdbStoreImpl::CleanDirtyLog(const std::string &table, uint64_t cursor) +{ + if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR) || isMemoryRdb_) { + LOG_ERROR("Not support. table:%{public}s, isRead:%{public}d, dbType:%{public}d, isMemoryRdb:%{public}d.", + SqliteUtils::Anonymous(table).c_str(), isReadOnly_, config_.GetDBType(), isMemoryRdb_); + return E_NOT_SUPPORT; + } + auto [errCode, conn] = GetConn(false); + if (errCode != E_OK || conn == nullptr) { + LOG_ERROR("The database is busy or closed errCode:%{public}d", errCode); + return errCode; + } + return conn->CleanDirtyLog(table, cursor); +} + +std::shared_ptr RdbStoreImpl::GetValues(std::shared_ptr statement) +{ + if (statement == nullptr) { + return nullptr; + } + auto [code, rows] = statement->GetRows(MAX_RETURNING_ROWS); + auto size = rows.size(); + std::shared_ptr result = std::make_shared(std::move(rows)); + // The correct number of changed rows can only be obtained after completing the step + while (code == E_OK && size == MAX_RETURNING_ROWS) { + std::tie(code, rows) = statement->GetRows(MAX_RETURNING_ROWS); + size = rows.size(); + } + return result; +} + +Results RdbStoreImpl::GenerateResult(int32_t code, std::shared_ptr statement, bool isDML) +{ + Results result{ -1 }; + if (statement == nullptr) { + return result; + } + // There are no data changes in other scenarios + if (code == E_OK) { + result.results = GetValues(statement); + result.changed = isDML ? statement->Changes() : 0; + } + if (code == E_SQLITE_CONSTRAINT) { + result.changed = statement->Changes(); + } + if (isDML && result.changed <= 0) { + result.results = std::make_shared(); + } + return result; +} + +void RdbStoreImpl::TryDump(int32_t code, const char *dumpHeader) +{ + if (code != E_SQLITE_LOCKED && code != E_SQLITE_BUSY) { + return; + } + auto pool = GetPool(); + if (pool != nullptr) { + pool->Dump(true, dumpHeader); + } +} + int32_t RdbStoreImpl::CloudTables::AddTables(const std::vector &tables) { std::lock_guard lock(mutex_); @@ -2692,4 +3002,87 @@ std::set RdbStoreImpl::CloudTables::Steal() } return result; } + +void RdbStoreImpl::SetKnowledgeSchema() +{ + auto [errCode, schema] = GetKnowledgeSchemaHelper()->GetRdbKnowledgeSchema(config_.GetName()); + if (errCode != E_OK) { + return; + } + auto [ret, conn] = GetConn(false); + if (ret != E_OK) { + LOG_ERROR("The database is busy or closed when set knowledge schema ret %{public}d.", ret); + return; + } + if (isKnowledgeSchemaReady_) { + return; + } + ret = conn->SetKnowledgeSchema(schema); + if (ret != E_OK) { + LOG_ERROR("Set knowledge schema failed %{public}d.", ret); + return; + } + isKnowledgeSchemaReady_ = true; + auto helper = GetKnowledgeSchemaHelper(); + helper->Init(config_, schema); + helper->DonateKnowledgeData(); +} + +int RdbStoreImpl::InitKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema &schema) +{ + auto [ret, conn] = GetConn(false); + if (ret != E_OK) { + LOG_ERROR("The database is busy or closed when set knowledge schema ret %{public}d.", ret); + return ret; + } + ret = conn->SetKnowledgeSchema(schema); + if (ret != E_OK) { + LOG_ERROR("Set knowledge schema failed %{public}d.", ret); + return ret; + } + return E_OK; +} + +std::shared_ptr RdbStoreImpl::GetKnowledgeSchemaHelper() +{ + std::lock_guard autoLock(helperMutex_); + if (knowledgeSchemaHelper_ == nullptr) { + knowledgeSchemaHelper_ = std::make_shared(); + } + return knowledgeSchemaHelper_; +} + +bool RdbStoreImpl::IsKnowledgeDataChange(const DistributedRdb::RdbChangedData &rdbChangedData) +{ + for (const auto &item : rdbChangedData.tableData) { + if (item.second.isKnowledgeDataChange) { + return true; + } + } + return false; +} + +bool RdbStoreImpl::IsNotifyService(const DistributedRdb::RdbChangedData &rdbChangedData) +{ + for (const auto &item : rdbChangedData.tableData) { + if (item.second.isP2pSyncDataChange || item.second.isTrackedDataChange) { + return true; + } + } + return false; +} + +int RdbStoreImpl::RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) +{ + if (!config_.IsVector() || isMemoryRdb_ || isReadOnly_) { + return E_NOT_SUPPORT; + } + + auto [ret, conn] = GetConn(false); + if (ret != E_OK) { + LOG_ERROR("The database is busy or closed when RegisterAlgo ret %{public}d.", ret); + return ret; + } + return conn->RegisterAlgo(clstAlgoName, func); +} } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp index 283e63ce..75211998 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp @@ -54,20 +54,42 @@ RdbStoreManager::~RdbStoreManager() Clear(); } -RdbStoreManager::RdbStoreManager() : configCache_(BUCKET_MAX_SIZE) +RdbStoreManager::RdbStoreManager() : configCache_(BUCKET_MAX_SIZE), promiseInfoCache_(PROMISEINFO_CACHE_SIZE) { } -std::shared_ptr RdbStoreManager::GetStoreFromCache(const std::string &path) +std::shared_ptr RdbStoreManager::GetStoreFromCache(const std::string &path, + const RdbStoreConfig &config, int &errCode) { + std::lock_guard lock(mutex_); + std::shared_ptr rdbStore = nullptr; auto it = storeCache_.find(path); if (it == storeCache_.end()) { - return nullptr; + rdbStore = std::make_shared(config); + storeCache_[path] = rdbStore; + return rdbStore; } - std::shared_ptr rdbStore = it->second.lock(); + + rdbStore = it->second.lock(); if (rdbStore == nullptr) { - storeCache_.erase(it); - return nullptr; + rdbStore = std::make_shared(config); + storeCache_[path] = rdbStore; + return rdbStore; + } + + if (!(rdbStore->GetConfig() == config)) { + auto log = RdbStoreConfig::FormatCfg(rdbStore->GetConfig(), config); + LOG_WARN("Diff config! app[%{public}s:%{public}s] path[%{public}s] cfg[%{public}s]", + config.GetBundleName().c_str(), config.GetModuleName().c_str(), SqliteUtils::Anonymous(path).c_str(), + log.c_str()); + Reportor::ReportFault(RdbFaultDbFileEvent(FT_OPEN, E_CONFIG_INVALID_CHANGE, config, log)); + if (rdbStore->GetConfig().IsMemoryRdb() || config.IsMemoryRdb()) { + errCode = E_CONFIG_INVALID_CHANGE; + rdbStore = nullptr; + return rdbStore; + } + rdbStore = std::make_shared(config); + storeCache_[path] = rdbStore; } return rdbStore; } @@ -75,54 +97,45 @@ std::shared_ptr RdbStoreManager::GetStoreFromCache(const std::stri std::shared_ptr RdbStoreManager::GetRdbStore( const RdbStoreConfig &config, int &errCode, int version, RdbOpenCallback &openCallback) { - errCode = CheckConfig(config); - if (errCode != E_OK) { - return nullptr; - } std::string path; errCode = SqliteGlobalConfig::GetDbPath(config, path); if (errCode != E_OK) { return nullptr; } - // TOD this lock should only work on storeCache_, add one more lock for connectionPool - std::lock_guard lock(mutex_); - std::shared_ptr rdbStore = GetStoreFromCache(path); - if (rdbStore != nullptr && rdbStore->GetConfig() == config) { - return rdbStore; + errCode = CheckConfig(config, path); + if (errCode != E_OK) { + return nullptr; } - if (rdbStore != nullptr) { - auto log = RdbStoreConfig::FormatCfg(rdbStore->GetConfig(), config); - LOG_WARN("Diff config! app[%{public}s:%{public}s] path[%{public}s] cfg[%{public}s]", - config.GetBundleName().c_str(), config.GetModuleName().c_str(), SqliteUtils::Anonymous(path).c_str(), - log.c_str()); - Reportor::ReportFault(RdbFaultDbFileEvent(FT_OPEN, E_CONFIG_INVALID_CHANGE, config, log)); - if (rdbStore->GetConfig().IsMemoryRdb() || config.IsMemoryRdb()) { - errCode = E_CONFIG_INVALID_CHANGE; - return nullptr; - } - storeCache_.erase(path); + std::shared_ptr rdbStore = nullptr; + RdbStoreConfig modifyConfig = config; + if (config.GetRoleType() == OWNER && IsConfigInvalidChanged(path, modifyConfig)) { + errCode = E_CONFIG_INVALID_CHANGE; rdbStore = nullptr; + return rdbStore; } - std::tie(errCode, rdbStore) = OpenStore(config, path); - if (errCode != E_OK || rdbStore == nullptr) { - return nullptr; + rdbStore = GetStoreFromCache(path, modifyConfig, errCode); + if (rdbStore == nullptr) { + return rdbStore; } - if (rdbStore->GetConfig().GetRoleType() == OWNER && !rdbStore->GetConfig().IsReadOnly()) { - errCode = SetSecurityLabel(rdbStore->GetConfig()); - if (errCode != E_OK) { - return nullptr; + errCode = rdbStore->Init(version, openCallback); + if (errCode != E_OK) { + if (modifyConfig.IsEncrypt() != config.IsEncrypt()) { + rdbStore = nullptr; + rdbStore = GetStoreFromCache(path, config, errCode); + if (rdbStore == nullptr) { + return rdbStore; + } + errCode = rdbStore->Init(version, openCallback); } - (void)rdbStore->ExchangeSlaverToMaster(); - errCode = ProcessOpenCallback(*rdbStore, version, openCallback); - if (errCode != E_OK) { - LOG_ERROR("Callback fail, path:%{public}s code:%{public}d", SqliteUtils::Anonymous(path).c_str(), errCode); - return nullptr; + if (errCode != E_OK || rdbStore == nullptr) { + rdbStore = nullptr; + return rdbStore; } } + if (!rdbStore->GetConfig().IsMemoryRdb()) { configCache_.Set(path, GetSyncParam(rdbStore->GetConfig())); } - storeCache_.insert_or_assign(std::move(path), rdbStore); return rdbStore; } @@ -132,7 +145,7 @@ bool RdbStoreManager::IsConfigInvalidChanged(const std::string &path, RdbStoreCo return false; } if (config.GetBundleName().empty()) { - LOG_WARN("Config has no bundleName, path: %{public}s", SqliteUtils::Anonymous(path).c_str()); + LOG_WARN("no bundleName"); return false; } Param lastParam = GetSyncParam(config); @@ -140,6 +153,7 @@ bool RdbStoreManager::IsConfigInvalidChanged(const std::string &path, RdbStoreCo LOG_WARN("Not found config cache, path: %{public}s", SqliteUtils::Anonymous(path).c_str()); return false; }; + configCache_.Set(path, lastParam); // The lastParam is possible that the same named db parameters of different paths when GetParamFromService if (lastParam.customDir_ != config.GetCustomDir() || lastParam.hapName_ != config.GetModuleName() || lastParam.area_ != config.GetArea()) { @@ -158,6 +172,7 @@ bool RdbStoreManager::IsConfigInvalidChanged(const std::string &path, RdbStoreCo LOG_WARN("Reset encrypt, storePath %{public}s, input:%{public}d original:%{public}d", SqliteUtils::Anonymous(path).c_str(), config.IsEncrypt(), lastParam.isEncrypt_); config.SetEncryptStatus(lastParam.isEncrypt_); + config.SetAllowRebuild(false); } return false; } @@ -201,9 +216,14 @@ int32_t RdbStoreManager::GetParamFromService(DistributedRdb::RdbSyncerParam &par return E_ERROR; } -bool RdbStoreManager::IsPermitted(const DistributedRdb::RdbSyncerParam ¶m) +bool RdbStoreManager::IsPermitted(const DistributedRdb::RdbSyncerParam ¶m, const std::string &path) { #if !defined(CROSS_PLATFORM) + bool result = false; + // ToDo: Scenario for handling cache refresh + if (promiseInfoCache_.Get(path, result)) { + return true; + }; auto [err, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(param); if (err == E_NOT_SUPPORT) { return false; @@ -214,6 +234,7 @@ bool RdbStoreManager::IsPermitted(const DistributedRdb::RdbSyncerParam ¶m) } err = service->VerifyPromiseInfo(param); if (err == DistributedRdb::RDB_OK) { + promiseInfoCache_.Set(path, true); return true; } LOG_ERROR("failed, bundleName:%{public}s, store:%{public}s, err:%{public}d.", param.bundleName_.c_str(), @@ -224,14 +245,34 @@ bool RdbStoreManager::IsPermitted(const DistributedRdb::RdbSyncerParam ¶m) void RdbStoreManager::Clear() { + configCache_.ResetCapacity(0); + configCache_.ResetCapacity(BUCKET_MAX_SIZE); + promiseInfoCache_.ResetCapacity(0); + promiseInfoCache_.ResetCapacity(PROMISEINFO_CACHE_SIZE); std::lock_guard lock(mutex_); auto iter = storeCache_.begin(); while (iter != storeCache_.end()) { + auto rdbStore = iter->second.lock(); + if (rdbStore.use_count() > 1) { + LOG_WARN("store[%{public}s] in use by %{public}ld holders", + SqliteUtils::Anonymous(rdbStore->GetPath()).c_str(), rdbStore.use_count()); + } iter = storeCache_.erase(iter); } storeCache_.clear(); } +void RdbStoreManager::Init() +{ + TaskExecutor::GetInstance().Init(); +} + +bool RdbStoreManager::Destroy() +{ + Clear(); + return TaskExecutor::GetInstance().Stop(); +} + bool RdbStoreManager::Remove(const std::string &path, bool shouldClose) { std::lock_guard lock(mutex_); @@ -239,7 +280,7 @@ bool RdbStoreManager::Remove(const std::string &path, bool shouldClose) auto it = storeCache_.find(path); if (it != storeCache_.end()) { auto rdbStore = it->second.lock(); - LOG_INFO("store in use by %{public}ld holders", storeCache_[path].lock().use_count()); + LOG_INFO("store in use by %{public}ld holders", rdbStore.use_count()); if (rdbStore && shouldClose) { rdbStore->Close(); } @@ -250,44 +291,6 @@ bool RdbStoreManager::Remove(const std::string &path, bool shouldClose) return false; } -int RdbStoreManager::ProcessOpenCallback(RdbStore &rdbStore, int version, RdbOpenCallback &openCallback) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - int errCode = E_OK; - if (version == -1) { - return errCode; - } - - int currentVersion; - errCode = rdbStore.GetVersion(currentVersion); - if (errCode != E_OK) { - return errCode; - } - - if (version == currentVersion) { - return openCallback.OnOpen(rdbStore); - } - - if (currentVersion == 0) { - errCode = openCallback.OnCreate(rdbStore); - } else if (version > currentVersion) { - errCode = openCallback.OnUpgrade(rdbStore, currentVersion, version); - } else { - errCode = openCallback.OnDowngrade(rdbStore, currentVersion, version); - } - - if (errCode == E_OK) { - errCode = rdbStore.SetVersion(version); - } - - if (errCode != E_OK) { - LOG_ERROR("RdbHelper ProcessOpenCallback set new version failed."); - return errCode; - } - - return openCallback.OnOpen(rdbStore); -} - bool RdbStoreManager::Delete(const RdbStoreConfig &config, bool shouldClose) { auto path = config.GetPath(); @@ -298,6 +301,9 @@ bool RdbStoreManager::Delete(const RdbStoreConfig &config, bool shouldClose) param.bundleName_ = config.GetBundleName(); param.storeName_ = *tokens.rbegin(); param.subUser_ = config.GetSubUser(); + param.area_ = config.GetArea(); + param.hapName_ = config.GetModuleName(); + param.customDir_ = config.GetCustomDir(); auto [err, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(param); if (err != E_OK || service == nullptr) { LOG_DEBUG("GetRdbService failed, err is %{public}d.", err); @@ -314,17 +320,6 @@ bool RdbStoreManager::Delete(const RdbStoreConfig &config, bool shouldClose) return Remove(path, shouldClose); } -int RdbStoreManager::SetSecurityLabel(const RdbStoreConfig &config) -{ - if (config.IsMemoryRdb()) { - return E_OK; - } -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) - return SecurityPolicy::SetSecurityLabel(config); -#endif - return E_OK; -} - int32_t RdbStoreManager::Collector(const RdbStoreConfig &config, DebugInfos &debugInfos, DfxInfo &dfxInfo) { #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) @@ -353,9 +348,9 @@ int32_t RdbStoreManager::Collector(const RdbStoreConfig &config, DebugInfos &deb return E_OK; } -int32_t RdbStoreManager::CheckConfig(const RdbStoreConfig &config) +int32_t RdbStoreManager::CheckConfig(const RdbStoreConfig &config, const std::string &path) { - if (config.GetRoleType() == VISITOR_WRITE && !IsPermitted(GetSyncParam(config))) { + if (config.GetRoleType() == VISITOR_WRITE && !IsPermitted(GetSyncParam(config), path)) { return E_NOT_SUPPORT; } if (config.IsMemoryRdb()) { @@ -369,23 +364,5 @@ int32_t RdbStoreManager::CheckConfig(const RdbStoreConfig &config) return E_OK; } -std::pair> RdbStoreManager::OpenStore( - const RdbStoreConfig &config, const std::string &path) -{ - RdbStoreConfig modifyConfig = config; - if (modifyConfig.GetRoleType() == OWNER && IsConfigInvalidChanged(path, modifyConfig)) { - return { E_CONFIG_INVALID_CHANGE, nullptr }; - } - - std::pair> result = { E_ERROR, nullptr }; - auto &[errCode, store] = result; - store = std::make_shared(modifyConfig, errCode); - if (errCode != E_OK && modifyConfig.IsEncrypt() != config.IsEncrypt()) { - LOG_WARN("Failed to OpenStore using modifyConfig. path:%{public}s, rc=%{public}d", - SqliteUtils::Anonymous(path).c_str(), errCode); - store = std::make_shared(config, errCode); // retry with input config - } - return result; -} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/share_block.cpp b/relational_store/frameworks/native/rdb/src/share_block.cpp index cfc30293..f2049745 100644 --- a/relational_store/frameworks/native/rdb/src/share_block.cpp +++ b/relational_store/frameworks/native/rdb/src/share_block.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -20,6 +20,7 @@ #include #include "logger.h" +#include "shared_block.h" #include "shared_block_serializer_info.h" #include "sqlite_errno.h" #include "sqlite_utils.h" diff --git a/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp b/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp index b8a3c732..88517787 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp @@ -26,12 +26,15 @@ #include #include +#include "global_resource.h" #include "logger.h" #include "raw_data_parser.h" #include "rdb_errno.h" #include "rdb_fault_hiview_reporter.h" +#include "rdb_icu_manager.h" #include "rdb_local_db_observer.h" #include "rdb_security_manager.h" +#include "rdb_sql_log.h" #include "rdb_sql_statistic.h" #include "rdb_store_config.h" #include "relational_store_client.h" @@ -40,6 +43,7 @@ #include "sqlite_errno.h" #include "sqlite_global_config.h" #include "sqlite_utils.h" +#include "suspender.h" #include "value_object.h" #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) #include "rdb_manager_impl.h" @@ -58,13 +62,15 @@ constexpr SqliteConnection::Suffix SqliteConnection::FILE_SUFFIXES[]; constexpr int SqliteConnection::DEFAULT_BUSY_TIMEOUT_MS; constexpr int SqliteConnection::BACKUP_PAGES_PRE_STEP; // 1024 * 4 * 12800 == 50m constexpr int SqliteConnection::BACKUP_PRE_WAIT_TIME; +constexpr int SqliteConnection::RESTORE_PRE_WAIT_TIME; constexpr ssize_t SqliteConnection::SLAVE_WAL_SIZE_LIMIT; constexpr ssize_t SqliteConnection::SLAVE_INTEGRITY_CHECK_LIMIT; constexpr uint32_t SqliteConnection::NO_ITER; +constexpr unsigned short SqliteConnection::BINLOG_FILE_NUMS_LIMIT; +constexpr uint32_t SqliteConnection::BINLOG_FILE_SIZE_LIMIT; constexpr uint32_t SqliteConnection::DB_INDEX; constexpr uint32_t SqliteConnection::WAL_INDEX; -constexpr uint32_t SqliteConnection::ITER_V1; -constexpr uint32_t SqliteConnection::SQLITE_CKSUMVFS_RESERVE_BYTES; +ConcurrentMap> SqliteConnection::reusableReplicas_ = {}; __attribute__((used)) const int32_t SqliteConnection::regCreator_ = Connection::RegisterCreator(DB_SQLITE, SqliteConnection::Create); __attribute__((used)) @@ -73,23 +79,32 @@ __attribute__((used)) const int32_t SqliteConnection::regDeleter_ = Connection::RegisterDeleter(DB_SQLITE, SqliteConnection::Delete); __attribute__((used)) const int32_t SqliteConnection::regCollector_ = Connection::RegisterCollector(DB_SQLITE, SqliteConnection::Collect); -__attribute__((used)) -const int32_t SqliteConnection::regRestorer_ = Connection::RegisterRestorer(DB_SQLITE, SqliteConnection::Restore); +__attribute__((used)) const int32_t SqliteConnection::regReplicaChecker_ = + Connection::RegisterReplicaChecker(DB_SQLITE, SqliteConnection::CheckReplicaIntegrity); +__attribute__((used)) const int32_t SqliteConnection::regDbClientCleaner_ = + GlobalResource::RegisterClean(GlobalResource::DB_CLIENT, SqliteConnection::ClientCleanUp); +__attribute__((used)) const int32_t SqliteConnection::regOpenSSLCleaner_ = + GlobalResource::RegisterClean(GlobalResource::OPEN_SSL, SqliteConnection::OpenSSLCleanUp); std::pair> SqliteConnection::Create(const RdbStoreConfig &config, bool isWrite) { std::pair> result = { E_ERROR, nullptr }; auto &[errCode, conn] = result; - std::tie(errCode, conn) = InnerCreate(config, isWrite); + std::tie(errCode, conn) = InnerCreate(config, isWrite, true); return result; } int32_t SqliteConnection::Delete(const RdbStoreConfig &config) { auto path = config.GetPath(); + auto binlogFolder = GetBinlogFolderPath(path); + size_t num = SqliteUtils::DeleteFolder(binlogFolder); + if (num > 0 && IsSupportBinlog(config)) { + LOG_INFO("removed %{public}zu binlog related items", num); + } auto slavePath = SqliteUtils::GetSlavePath(path); - Delete(path); Delete(slavePath); + Delete(path); return E_OK; } @@ -133,8 +148,8 @@ std::map SqliteConnection::Collect(const RdbStore return collection; } -SqliteConnection::SqliteConnection(const RdbStoreConfig &config, bool isWriteConnection) - : dbHandle_(nullptr), isWriter_(isWriteConnection), isReadOnly_(false), maxVariableNumber_(0), +SqliteConnection::SqliteConnection(const RdbStoreConfig &config, bool isWriteConnection, bool isSlave) + : dbHandle_(nullptr), isWriter_(isWriteConnection), isReadOnly_(false), isSlave_(isSlave), maxVariableNumber_(0), config_(config) { backupId_ = TaskExecutor::INVALID_TASK_ID; @@ -152,12 +167,12 @@ std::pair> SqliteConnection::CreateSl bool walOverLimit = bugInfo.find(FILE_SUFFIXES[WAL_INDEX].debug_) != bugInfo.end() && bugInfo[FILE_SUFFIXES[WAL_INDEX].debug_].size_ > SLAVE_WAL_SIZE_LIMIT; LOG_INFO("slave cfg:[%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d]%{public}s " - "%{public}s,[%{public}d,%{public}d,%{public}d,%{public}d]", + "%{public}s,[%{public}d,%{public}d,%{public}d,%{public}d,%{public}d]", config.GetDBType(), config.GetHaMode(), config.IsEncrypt(), config.GetArea(), config.GetSecurityLevel(), config.GetRoleType(), config.IsReadOnly(), SqliteUtils::FormatDebugInfoBrief(bugInfo, SqliteUtils::Anonymous(config.GetName())).c_str(), SqliteUtils::FormatDebugInfoBrief(Connection::Collect(config_), "master").c_str(), isSlaveExist, - isSlaveLockExist, hasFailure, walOverLimit); + isSlaveLockExist, hasFailure, walOverLimit, IsSupportBinlog(config_)); if (config.GetHaMode() == HAMode::MANUAL_TRIGGER && (slaveOpenPolicy == SlaveOpenPolicy::OPEN_IF_DB_VALID && (!isSlaveExist || isSlaveLockExist || hasFailure || walOverLimit))) { if (walOverLimit) { @@ -167,7 +182,8 @@ std::pair> SqliteConnection::CreateSl return result; } - std::shared_ptr connection = std::make_shared(config, true); + std::shared_ptr connection = std::make_shared(config, true, true); + connection->SetIsSupportBinlog(IsSupportBinlog(config_)); errCode = connection->InnerOpen(config); if (errCode != E_OK) { SqliteUtils::SetSlaveInvalid(config_.GetPath()); @@ -243,18 +259,19 @@ int SqliteConnection::InnerOpen(const RdbStoreConfig &config) } #endif isReadOnly_ = !isWriter_ || config.IsReadOnly(); - int openFileFlags = config.IsReadOnly() ? (SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) - : (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX); + uint32_t openFileFlags = config.IsReadOnly() ? (SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) + : (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX); if (config.IsMemoryRdb()) { openFileFlags |= SQLITE_OPEN_URI; } - errCode = OpenDatabase(dbPath, openFileFlags); + errCode = OpenDatabase(dbPath, static_cast(openFileFlags)); if (errCode != E_OK) { Reportor::ReportFault(RdbFaultDbFileEvent(FT_OPEN, errCode, config, "", true)); return errCode; } maxVariableNumber_ = sqlite3_limit(dbHandle_, SQLITE_LIMIT_VARIABLE_NUMBER, -1); + errCode = Configure(config, dbPath); isConfigured_ = true; if (errCode != E_OK) { @@ -273,7 +290,7 @@ int SqliteConnection::InnerOpen(const RdbStoreConfig &config) if (errCode == E_OK && static_cast(checkResult) != "ok") { LOG_ERROR("%{public}s integrity check result is %{public}s, sql:%{public}s", SqliteUtils::Anonymous(config.GetName()).c_str(), static_cast(checkResult).c_str(), - sql); + SqliteUtils::SqlAnonymous(sql).c_str()); Reportor::ReportCorruptedOnce(Reportor::Create(config, errCode, static_cast(checkResult))); } } @@ -283,10 +300,28 @@ int SqliteConnection::InnerOpen(const RdbStoreConfig &config) int32_t SqliteConnection::OpenDatabase(const std::string &dbPath, int openFileFlags) { - int errCode = sqlite3_open_v2(dbPath.c_str(), &dbHandle_, openFileFlags, nullptr); + const char *option = isSlave_ && isSupportBinlog_ ? "compressvfs" : nullptr; + int errCode = sqlite3_open_v2(dbPath.c_str(), &dbHandle_, openFileFlags, option); if (errCode != SQLITE_OK) { LOG_ERROR("fail to open database errCode=%{public}d, dbPath=%{public}s, flags=%{public}d, errno=%{public}d", errCode, SqliteUtils::Anonymous(dbPath).c_str(), openFileFlags, errno); + if (isSlave_ && errCode == SQLITE_WARNING && + sqlite3_extended_errcode(dbHandle_) == SQLITE_WARNING_NOTCOMPRESSDB) { + LOG_WARN("slave db is not using compress"); + return E_SQLITE_CORRUPT; + } + if (errCode == SQLITE_CANTOPEN) { + std::pair fileInfo = SqliteUtils::Stat(dbPath); + if (fileInfo.first != E_OK) { + LOG_ERROR("The stat error, errno=%{public}d, parent dir modes: %{public}s", errno, + SqliteUtils::GetParentModes(dbPath).c_str()); + } + Reportor::ReportFault(RdbFaultDbFileEvent(FT_OPEN, E_SQLITE_CANTOPEN, config_, + "failed to openDB errno[ " + std::to_string(errno) + "]," + + SqliteUtils::GetFileStatInfo(fileInfo.second) + + "parent dir modes:" + SqliteUtils::GetParentModes(dbPath), + true)); + } #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) auto const pos = dbPath.find_last_of("\\/"); if (pos != std::string::npos) { @@ -360,6 +395,7 @@ int SqliteConnection::SetCustomScalarFunction(const std::string &functionName, i int SqliteConnection::Configure(const RdbStoreConfig &config, std::string &dbPath) { + Suspender suspender(Suspender::SQL_STATISTIC); // there is a read-only dependency if (!config.GetCollatorLocales().empty()) { ConfigLocale(config.GetCollatorLocales()); @@ -369,12 +405,7 @@ int SqliteConnection::Configure(const RdbStoreConfig &config, std::string &dbPat return E_OK; } - auto errCode = SetCrcCheck(config); - if (errCode != E_OK) { - return errCode; - } - - errCode = RegDefaultFunctions(dbHandle_); + auto errCode = RegDefaultFunctions(dbHandle_); if (errCode != E_OK) { return errCode; } @@ -480,26 +511,75 @@ int SqliteConnection::RegisterClientObs() return E_OK; } -std::pair> SqliteConnection::CreateStatement( - const std::string &sql, std::shared_ptr conn) +int32_t SqliteConnection::CheckReplicaIntegrity(const RdbStoreConfig &config) { - std::shared_ptr statement = std::make_shared(); + std::shared_ptr connection = std::make_shared(config, true); + if (connection == nullptr) { + return E_ERROR; + } + RdbStoreConfig rdbSlaveStoreConfig = connection->GetSlaveRdbStoreConfig(config); + if (access(rdbSlaveStoreConfig.GetPath().c_str(), F_OK) != 0) { + return E_NOT_SUPPORT; + } + auto [ret, conn] = connection->CreateSlaveConnection(rdbSlaveStoreConfig, SlaveOpenPolicy::FORCE_OPEN); + if (ret != E_OK) { + return ret; + } + connection->slaveConnection_ = conn; + if (IsSupportBinlog(config)) { + SqliteConnection::ReplayBinlog(config.GetPath(), conn, false); + } + return connection->VeritySlaveIntegrity(); +} + +int SqliteConnection::CheckReplicaForRestore() +{ + return ExchangeVerify(true); +} + +std::pair> SqliteConnection::CreateStatement(const std::string &sql, + std::shared_ptr conn) +{ + return CreateStatementInner(sql, conn, dbHandle_, false); +} + +std::pair> SqliteConnection::CreateReplicaStatement(const std::string &sql, + std::shared_ptr conn) +{ + sqlite3 *db = dbHandle_; + RdbStoreConfig rdbSlaveStoreConfig = GetSlaveRdbStoreConfig(config_); + if (slaveConnection_ == nullptr && access(rdbSlaveStoreConfig.GetPath().c_str(), F_OK) == 0) { + auto [errCode, slaveConn] = CreateSlaveConnection(rdbSlaveStoreConfig, SlaveOpenPolicy::FORCE_OPEN); + if (errCode == E_OK) { + slaveConnection_ = slaveConn; + db = slaveConnection_->dbHandle_; + } + LOG_INFO("create slave conn ret=%{public}d, %{public}d", errCode, IsWriter()); + } + return CreateStatementInner(sql, conn, db, true); +} + +std::pair> SqliteConnection::CreateStatementInner(const std::string &sql, + std::shared_ptr conn, sqlite3 *db, bool isFromReplica) +{ + std::shared_ptr statement = std::make_shared(&config_); // When memory is not cleared, quick_check reads memory pages and detects damage but does not report it - if (sql == INTEGRITIES[1] && dbHandle_ != nullptr && mode_ == JournalMode::MODE_WAL) { - sqlite3_db_release_memory(dbHandle_); + if (sql == INTEGRITIES[1] && db != nullptr && mode_ == JournalMode::MODE_WAL) { + sqlite3_db_release_memory(db); } - statement->config_ = &config_; - int errCode = statement->Prepare(dbHandle_, sql); + int errCode = statement->Prepare(db, sql); if (errCode != E_OK) { return { errCode, nullptr }; } statement->conn_ = conn; - if (slaveConnection_ && IsWriter()) { + if (!isFromReplica && slaveConnection_ && IsWriter() && !IsSupportBinlog(config_) && + !SqliteUtils::IsSlaveRestoring(config_.GetPath())) { auto slaveStmt = std::make_shared(); if (sql == INTEGRITIES[1] && dbHandle_ != nullptr && mode_ == JournalMode::MODE_WAL) { sqlite3_db_release_memory(dbHandle_); } slaveStmt->config_ = &slaveConnection_->config_; + slaveStmt->conn_ = slaveConnection_; errCode = slaveStmt->Prepare(slaveConnection_->dbHandle_, sql); if (errCode != E_OK) { LOG_WARN("prepare slave stmt failed:%{public}d, app self can check the SQL", errCode); @@ -526,9 +606,10 @@ int SqliteConnection::SubscribeTableChanges(const Connection::Notifier ¬ifier int32_t status = RegisterClientObserver(dbHandle_, [notifier](const ClientChangedData &clientData) { DistributedRdb::RdbChangedData rdbChangedData; for (auto &[key, val] : clientData.tableData) { - if (val.isTrackedDataChange || val.isP2pSyncDataChange) { + if (val.isTrackedDataChange || val.isP2pSyncDataChange || val.isKnowledgeDataChange) { rdbChangedData.tableData[key].isTrackedDataChange = val.isTrackedDataChange; rdbChangedData.tableData[key].isP2pSyncDataChange = val.isP2pSyncDataChange; + rdbChangedData.tableData[key].isKnowledgeDataChange = val.isKnowledgeDataChange; } } notifier(rdbChangedData); @@ -565,6 +646,7 @@ int SqliteConnection::SetPageSize(const RdbStoreConfig &config) } int targetValue = config.GetPageSize(); + Suspender suspender(Suspender::SQL_LOG); auto [errCode, object] = ExecuteForValue("PRAGMA page_size"); if (errCode != E_OK) { LOG_ERROR("SetPageSize fail to get page size : %{public}d", errCode); @@ -584,24 +666,29 @@ int SqliteConnection::SetPageSize(const RdbStoreConfig &config) int SqliteConnection::SetEncryptAgo(const RdbStoreConfig &config) { - if (!config.GetCryptoParam().IsValid()) { - LOG_ERROR("Invalid crypto param: %{public}s, %{public}d, %{public}d, %{public}d, %{public}d, %{public}u", - SqliteUtils::Anonymous(config.GetName()).c_str(), config.GetCryptoParam().iterNum, - config.GetCryptoParam().encryptAlgo, config.GetCryptoParam().hmacAlgo, config.GetCryptoParam().kdfAlgo, - config.GetCryptoParam().cryptoPageSize); + return SetEncryptAgo(config.GetCryptoParam()); +} + +int SqliteConnection::SetEncryptAgo(const RdbStoreConfig::CryptoParam &cryptoParam) +{ + if (!cryptoParam.IsValid()) { + LOG_ERROR("Invalid crypto param: %{public}d, %{public}d, %{public}d, %{public}d, %{public}u", + cryptoParam.iterNum, cryptoParam.encryptAlgo, cryptoParam.hmacAlgo, cryptoParam.kdfAlgo, + cryptoParam.cryptoPageSize); return E_INVALID_ARGS; } - if (config.GetIter() != NO_ITER) { - auto errCode = ExecuteSql(std::string(GlobalExpr::CIPHER_ALGO_PREFIX) + - SqliteUtils::EncryptAlgoDescription(config.GetEncryptAlgo()) + - std::string(GlobalExpr::ALGO_SUFFIX)); + if (cryptoParam.iterNum != NO_ITER) { + auto errCode = + ExecuteSql(std::string(GlobalExpr::CIPHER_ALGO_PREFIX) + + SqliteUtils::EncryptAlgoDescription(static_cast(cryptoParam.encryptAlgo)) + + std::string(GlobalExpr::ALGO_SUFFIX)); if (errCode != E_OK) { LOG_ERROR("set cipher algo failed, err = %{public}d", errCode); return errCode; } - errCode = ExecuteSql(std::string(GlobalExpr::CIPHER_KDF_ITER) + std::to_string(config.GetIter())); + errCode = ExecuteSql(std::string(GlobalExpr::CIPHER_KDF_ITER) + std::to_string(cryptoParam.iterNum)); if (errCode != E_OK) { LOG_ERROR("set kdf iter number V1 failed, err = %{public}d", errCode); return errCode; @@ -609,7 +696,7 @@ int SqliteConnection::SetEncryptAgo(const RdbStoreConfig &config) } auto errCode = ExecuteSql(std::string(GlobalExpr::CODEC_HMAC_ALGO_PREFIX) + - SqliteUtils::HmacAlgoDescription(config.GetCryptoParam().hmacAlgo) + + SqliteUtils::HmacAlgoDescription(cryptoParam.hmacAlgo) + std::string(GlobalExpr::ALGO_SUFFIX)); if (errCode != E_OK) { LOG_ERROR("set codec hmac algo failed, err = %{public}d", errCode); @@ -617,7 +704,7 @@ int SqliteConnection::SetEncryptAgo(const RdbStoreConfig &config) } errCode = ExecuteSql(std::string(GlobalExpr::CODEC_KDF_ALGO_PREFIX) + - SqliteUtils::KdfAlgoDescription(config.GetCryptoParam().kdfAlgo) + + SqliteUtils::KdfAlgoDescription(cryptoParam.kdfAlgo) + std::string(GlobalExpr::ALGO_SUFFIX)); if (errCode != E_OK) { LOG_ERROR("set codec kdf algo failed, err = %{public}d", errCode); @@ -625,7 +712,7 @@ int SqliteConnection::SetEncryptAgo(const RdbStoreConfig &config) } errCode = ExecuteSql( - std::string(GlobalExpr::CODEC_PAGE_SIZE_PREFIX) + std::to_string(config.GetCryptoParam().cryptoPageSize)); + std::string(GlobalExpr::CODEC_PAGE_SIZE_PREFIX) + std::to_string(cryptoParam.cryptoPageSize)); if (errCode != E_OK) { LOG_ERROR("set codec page size failed, err = %{public}d", errCode); return errCode; @@ -639,7 +726,44 @@ int SqliteConnection::SetEncryptAgo(const RdbStoreConfig &config) return E_OK; } -int SqliteConnection::ReSetKey(const RdbStoreConfig &config) +int SqliteConnection::Rekey(const RdbStoreConfig::CryptoParam &cryptoParam) +{ + std::vector key; + RdbPassword rdbPwd; + int errCode = E_OK; + if (cryptoParam.encryptKey_.empty()) { + rdbPwd = RdbSecurityManager::GetInstance().GetRdbPassword( + config_.GetPath(), RdbSecurityManager::PUB_KEY_FILE_NEW_KEY); + key = std::vector(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize()); + } else { + key = cryptoParam.encryptKey_; + } + if (key.empty()) { + LOG_ERROR("key is empty"); + return E_ERROR; + } + errCode = sqlite3_rekey(dbHandle_, static_cast(key.data()), static_cast(key.size())); + if (errCode != SQLITE_OK) { + key.assign(key.size(), 0); + LOG_ERROR("ReKey failed, err = %{public}d, name = %{public}s", errCode, + SqliteUtils::Anonymous(config_.GetName()).c_str()); + return SQLiteError::ErrNo(errCode); + } + errCode = SetEncryptAgo(cryptoParam); + if (errCode != E_OK) { + key.assign(key.size(), 0); + LOG_ERROR("ReKey failed, err = %{public}d, name = %{public}s", errCode, + SqliteUtils::Anonymous(config_.GetName()).c_str()); + return errCode; + } + if (cryptoParam.encryptKey_.empty()) { + RdbSecurityManager::GetInstance().ChangeKeyFile(config_.GetPath()); + } + key.assign(key.size(), 0); + return E_OK; +} + +int SqliteConnection::ResetKey(const RdbStoreConfig &config) { if (!IsWriter()) { return E_OK; @@ -658,24 +782,6 @@ int SqliteConnection::ReSetKey(const RdbStoreConfig &config) return E_OK; } -int SqliteConnection::SetCrcCheck(const RdbStoreConfig &config) -{ - if (config.IsEncrypt() || config.IsMemoryRdb()) { - return E_OK; - } - int n = -1; - auto errCode = SQLiteError::ErrNo(sqlite3_file_control(dbHandle_, 0, SQLITE_FCNTL_RESERVE_BYTES, &n)); - if (errCode != E_OK) { - LOG_ERROR("failed to set sqlite reserved bytes(SQLITE_FCNTL_RESERVE_BYTES), errCode=%{public}d", errCode); - return errCode; - } - if (n == 0) { - n = SQLITE_CKSUMVFS_RESERVE_BYTES; - (void)sqlite3_file_control(dbHandle_, 0, SQLITE_FCNTL_RESERVE_BYTES, &n); - } - return E_OK; -} - void SqliteConnection::SetDwrEnable(const RdbStoreConfig &config) { if (config.IsEncrypt() || config.IsMemoryRdb()) { @@ -733,7 +839,7 @@ int SqliteConnection::SetEncrypt(const RdbStoreConfig &config) } if (!newKey.empty()) { - ReSetKey(config); + ResetKey(config); } newKey.assign(newKey.size(), 0); return E_OK; @@ -749,13 +855,13 @@ int SqliteConnection::SetEncryptKey(const std::vector &key, const RdbSt if (errCode != SQLITE_OK) { return SQLiteError::ErrNo(errCode); } - + Suspender suspender(Suspender::SQL_LOG); errCode = SetEncryptAgo(config); if (errCode != E_OK) { return errCode; } - if (IsWriter()) { + if (IsWriter() || config.IsReadOnly()) { ValueObject version; std::tie(errCode, version) = ExecuteForValue(GlobalExpr::PRAGMA_VERSION); if (errCode != E_OK || version.GetType() == ValueObject::TYPE_NULL) { @@ -821,7 +927,7 @@ int SqliteConnection::SetJournalMode(const RdbStoreConfig &config) if (errCode != E_OK) { LOG_ERROR("SetJournalMode fail to get journal mode : %{public}d, errno %{public}d", errCode, errno); Reportor::ReportFault(RdbFaultEvent(FT_OPEN, E_DFX_GET_JOURNAL_FAIL, config_.GetBundleName(), - "PRAGMA journal_mode get fail: " + std::to_string(errCode) + "," + std::to_string(errno))); + "PRAGMA journal_mode get fail: " + std::to_string(errCode) + "," + std::to_string(errno))); // errno: 28 No space left on device return (errCode == E_SQLITE_IOERR && sqlite3_system_errno(dbHandle_) == 28) ? E_SQLITE_IOERR_FULL : errCode; } @@ -899,6 +1005,7 @@ int SqliteConnection::SetWalFile(const RdbStoreConfig &config) if (!IsWriter()) { return E_OK; } + Suspender suspender(Suspender::SQL_LOG); auto [errCode, version] = ExecuteForValue(GlobalExpr::PRAGMA_VERSION); if (errCode != E_OK) { return errCode; @@ -912,7 +1019,7 @@ int SqliteConnection::SetWalSyncMode(const std::string &syncMode) if (syncMode.length() != 0) { targetValue = syncMode; } - + Suspender suspender(Suspender::SQL_LOG); auto [errCode, object] = ExecuteForValue("PRAGMA synchronous"); if (errCode != E_OK) { LOG_ERROR("get wal sync mode fail, errCode:%{public}d", errCode); @@ -957,18 +1064,21 @@ std::pair SqliteConnection::ExecuteForValue( return { errCode, object }; } -int SqliteConnection::ClearCache() +int SqliteConnection::ClearCache(bool isForceClear) { if (dbHandle_ != nullptr && mode_ == JournalMode::MODE_WAL) { - int usedBytes = 0; - int nEnyry = 0; - int errCode = sqlite3_db_status(dbHandle_, SQLITE_DBSTATUS_CACHE_USED, &usedBytes, &nEnyry, 0); - if (errCode == SQLITE_OK && usedBytes > config_.GetClearMemorySize()) { + auto getUsedBytes = [dbHandle = dbHandle_]() -> int { + int usedBytes = 0; + int nEntry = 0; + sqlite3_db_status(dbHandle, SQLITE_DBSTATUS_CACHE_USED, &usedBytes, &nEntry, 0); + return usedBytes; + }; + if (isForceClear || getUsedBytes() > config_.GetClearMemorySize()) { sqlite3_db_release_memory(dbHandle_); } } if (slaveConnection_) { - int errCode = slaveConnection_->ClearCache(); + int errCode = slaveConnection_->ClearCache(isForceClear); if (errCode != E_OK) { LOG_ERROR("slaveConnection clearCache failed:%{public}d", errCode); } @@ -996,18 +1106,7 @@ void SqliteConnection::LimitPermission(const RdbStoreConfig &config, const std:: int SqliteConnection::ConfigLocale(const std::string &localeStr) { - static void *handle = dlopen("librelational_store_icu.z.so", RTLD_LAZY); - if (handle == nullptr) { - LOG_ERROR("dlopen(librelational_store_icu) failed(%{public}d)!", errno); - return E_NOT_SUPPORT; - } - auto func = reinterpret_cast(dlsym(handle, "ConfigICULocal")); - if (func == nullptr) { - LOG_ERROR("dlsym(librelational_store_icu) failed(%{public}d)!", errno); - return E_ERROR; - } - func(dbHandle_, localeStr); - return E_OK; + return RdbICUManager::GetInstance().ConfigLocale(dbHandle_, localeStr); } int SqliteConnection::CleanDirtyData(const std::string &table, uint64_t cursor) @@ -1109,10 +1208,10 @@ int32_t SqliteConnection::Unsubscribe(const std::shared_ptr &destEncryptKey, - bool isAsync, SlaveStatus &slaveStatus) + bool isAsync, std::shared_ptr slaveStatus, bool verifyDb) { - if (slaveStatus == SlaveStatus::BACKING_UP) { - LOG_INFO("backing up, return:%{public}s", config_.GetName().c_str()); + if (*slaveStatus == SlaveStatus::BACKING_UP) { + LOG_INFO("backing up, return:%{public}s", SqliteUtils::Anonymous(config_.GetName()).c_str()); return E_OK; } LOG_INFO( @@ -1125,8 +1224,9 @@ int32_t SqliteConnection::Backup(const std::string &databasePath, const std::vec return errCode; } slaveConnection_ = conn; + reusableReplicas_.InsertOrAssign(rdbSlaveStoreConfig.GetPath(), conn); } - return ExchangeSlaverToMaster(false, true, slaveStatus); + return ExchangeSlaverToMaster(false, verifyDb, slaveStatus); } if (backupId_ == TaskExecutor::INVALID_TASK_ID) { @@ -1135,7 +1235,7 @@ int32_t SqliteConnection::Backup(const std::string &databasePath, const std::vec LOG_WARN("task pool err when restore"); return E_OK; } - backupId_ = pool->Execute([this, &slaveStatus]() { + backupId_ = pool->Execute([this, slaveStatus]() { auto [err, conn] = InnerCreate(config_, true); if (err != E_OK) { return; @@ -1151,7 +1251,8 @@ int32_t SqliteConnection::Backup(const std::string &databasePath, const std::vec } int32_t SqliteConnection::Restore( - const std::string &databasePath, const std::vector &destEncryptKey, SlaveStatus &slaveStatus) + const std::string &databasePath, const std::vector &destEncryptKey, + std::shared_ptr slaveStatus) { return ExchangeSlaverToMaster(true, true, slaveStatus); }; @@ -1239,42 +1340,69 @@ int SqliteConnection::SetServiceKey(const RdbStoreConfig &config, int32_t errCod return errCode; } -int SqliteConnection::ExchangeSlaverToMaster(bool isRestore, bool verifyDb, SlaveStatus &curStatus) +int SqliteConnection::ExchangeSlaverToMaster(bool isRestore, bool verifyDb, std::shared_ptr curStatus) { - curStatus = SlaveStatus::BACKING_UP; + *curStatus = SlaveStatus::BACKING_UP; int err = verifyDb ? ExchangeVerify(isRestore) : E_OK; if (err != E_OK) { - curStatus = SlaveStatus::UNDEFINED; + *curStatus = SlaveStatus::UNDEFINED; + return err; + } + + err = SqliteNativeBackup(isRestore, curStatus); + if (err != E_OK) { return err; } - return SqliteNativeBackup(isRestore, curStatus); + if (!isRestore && IsSupportBinlog(config_) && config_.GetHaMode() != HAMode::SINGLE) { + LOG_INFO("reset binlog start"); + sqlite3_db_config(dbHandle_, SQLITE_DBCONFIG_ENABLE_BINLOG, nullptr); + SetBinlog(); + err = sqlite3_clean_binlog(dbHandle_, BinlogFileCleanModeE::BINLOG_FILE_CLEAN_ALL_MODE); + if (err != SQLITE_OK) { + sqlite3_db_config(dbHandle_, SQLITE_DBCONFIG_ENABLE_BINLOG, nullptr); + SqliteUtils::SetSlaveInvalid(config_.GetPath()); + } + LOG_INFO("reset binlog finished, %{public}d", err); + } + return E_OK; } -int SqliteConnection::SqliteNativeBackup(bool isRestore, SlaveStatus &curStatus) + +int SqliteConnection::SqliteBackupStep(bool isRestore, sqlite3_backup *pBackup, std::shared_ptr curStatus) { - sqlite3 *dbFrom = isRestore ? dbHandle_ : slaveConnection_->dbHandle_; - sqlite3 *dbTo = isRestore ? slaveConnection_->dbHandle_ : dbHandle_; - sqlite3_backup *pBackup = sqlite3_backup_init(dbFrom, "main", dbTo, "main"); - if (pBackup == nullptr) { - LOG_WARN("slave backup init failed"); - curStatus = SlaveStatus::UNDEFINED; - return E_OK; + int sleepTime = BACKUP_PRE_WAIT_TIME; + if (isRestore) { + sleepTime = SqliteUtils::IsSlaveRestoring(config_.GetPath()) ? RESTORE_PRE_WAIT_TIME : 0; } int rc = SQLITE_OK; do { - if (!isRestore && curStatus == SlaveStatus::BACKUP_INTERRUPT) { + if (!isRestore && (*curStatus == SlaveStatus::BACKUP_INTERRUPT || *curStatus == SlaveStatus::DB_CLOSING)) { rc = E_CANCEL; break; } rc = sqlite3_backup_step(pBackup, BACKUP_PAGES_PRE_STEP); - LOG_INFO("backup slave process cur/total:%{public}d/%{public}d, rs:%{public}d, isRestore:%{public}d", + LOG_INFO("backup slave process cur/total:%{public}d/%{public}d, rs:%{public}d,isRestore:%{public}d,%{public}d", sqlite3_backup_pagecount(pBackup) - sqlite3_backup_remaining(pBackup), sqlite3_backup_pagecount(pBackup), - rc, isRestore); - if (!isRestore) { - sqlite3_sleep(BACKUP_PRE_WAIT_TIME); + rc, isRestore, sleepTime); + if (sleepTime > 0) { + sqlite3_sleep(sleepTime); } } while (sqlite3_backup_pagecount(pBackup) != 0 && (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED)); (void)sqlite3_backup_finish(pBackup); + return rc; +} + +int SqliteConnection::SqliteNativeBackup(bool isRestore, std::shared_ptr curStatus) +{ + sqlite3 *dbFrom = isRestore ? dbHandle_ : slaveConnection_->dbHandle_; + sqlite3 *dbTo = isRestore ? slaveConnection_->dbHandle_ : dbHandle_; + sqlite3_backup *pBackup = sqlite3_backup_init(dbFrom, "main", dbTo, "main"); + if (pBackup == nullptr) { + LOG_WARN("slave backup init failed"); + *curStatus = SlaveStatus::UNDEFINED; + return E_OK; + } + int rc = SqliteBackupStep(isRestore, pBackup, curStatus); if (rc != SQLITE_DONE) { LOG_ERROR("backup slave err:%{public}d, isRestore:%{public}d", rc, isRestore); if (!isRestore) { @@ -1283,7 +1411,7 @@ int SqliteConnection::SqliteNativeBackup(bool isRestore, SlaveStatus &curStatus) slaveConnection_ = nullptr; (void)SqliteConnection::Delete(slaveConfig.GetPath()); } - curStatus = SlaveStatus::BACKUP_INTERRUPT; + *curStatus = SlaveStatus::BACKUP_INTERRUPT; Reportor::ReportCorrupted(Reportor::Create(slaveConfig, SQLiteError::ErrNo(rc), "ErrorType: slaveBackup")); } return rc == E_CANCEL ? E_CANCEL : SQLiteError::ErrNo(rc); @@ -1291,60 +1419,87 @@ int SqliteConnection::SqliteNativeBackup(bool isRestore, SlaveStatus &curStatus) rc = isRestore ? TryCheckPoint(true) : slaveConnection_->TryCheckPoint(true); if (rc != E_OK && config_.GetHaMode() == HAMode::MANUAL_TRIGGER) { if (!isRestore) { - curStatus = SlaveStatus::BACKUP_INTERRUPT; + *curStatus = SlaveStatus::BACKUP_INTERRUPT; } LOG_WARN("CheckPoint failed err:%{public}d, isRestore:%{public}d", rc, isRestore); return E_OK; } - curStatus = SlaveStatus::BACKUP_FINISHED; + *curStatus = SlaveStatus::BACKUP_FINISHED; SqliteUtils::SetSlaveValid(config_.GetPath()); LOG_INFO("backup slave success, isRestore:%{public}d", isRestore); return E_OK; } -ExchangeStrategy SqliteConnection::GenerateExchangeStrategy(const SlaveStatus &status) +ExchangeStrategy SqliteConnection::GenerateExchangeStrategy(std::shared_ptr status, bool isRelpay) { if (dbHandle_ == nullptr || slaveConnection_ == nullptr || slaveConnection_->dbHandle_ == nullptr || - config_.GetHaMode() == HAMode::SINGLE || status == SlaveStatus::BACKING_UP) { + config_.GetHaMode() == HAMode::SINGLE || *status == SlaveStatus::BACKING_UP) { return ExchangeStrategy::NOT_HANDLE; } - static const std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';"; + const std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';"; + const std::string qIndexSql = "SELECT COUNT(*) FROM sqlite_master WHERE type='index';"; auto [mRet, mObj] = ExecuteForValue(querySql); - if (mRet == E_SQLITE_CORRUPT) { + auto [mIdxRet, mIdxObj] = ExecuteForValue(qIndexSql); + if (mRet == E_SQLITE_CORRUPT || mIdxRet == E_SQLITE_CORRUPT) { LOG_WARN("main abnormal, err:%{public}d", mRet); return ExchangeStrategy::RESTORE; } int64_t mCount = static_cast(mObj); + int64_t mIdxCount = static_cast(mIdxObj); // trigger mode only does restore, not backup if (config_.GetHaMode() == HAMode::MANUAL_TRIGGER) { return mCount == 0 ? ExchangeStrategy::RESTORE : ExchangeStrategy::NOT_HANDLE; } - auto [sRet, sObj] = slaveConnection_->ExecuteForValue(querySql); - if (sRet == E_SQLITE_CORRUPT) { - LOG_WARN("slave db abnormal, need backup, err:%{public}d", sRet); - return ExchangeStrategy::BACKUP; + if (*status == SlaveStatus::DB_CLOSING) { + return ExchangeStrategy::NOT_HANDLE; } - if (status == SlaveStatus::DB_NOT_EXITS || status == SlaveStatus::BACKUP_INTERRUPT) { + if (*status == SlaveStatus::BACKUP_INTERRUPT) { return ExchangeStrategy::BACKUP; } - int64_t sCount = static_cast(sObj); - if ((mCount == sCount) && !SqliteUtils::IsSlaveInvalid(config_.GetPath())) { - LOG_INFO("equal, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount); - return ExchangeStrategy::NOT_HANDLE; + if (IsSupportBinlog(config_)) { + if (isRelpay) { + SqliteConnection::ReplayBinlog(config_.GetPath(), slaveConnection_, false); + } else if (mCount == 0) { + LOG_INFO("main empty"); + return ExchangeStrategy::RESTORE; + } else { + return ExchangeStrategy::PENDING_BACKUP; + } } - if (mCount == 0) { - LOG_INFO("main empty, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount); - return ExchangeStrategy::RESTORE; + return CompareWithSlave(mCount, mIdxCount); +} + +int SqliteConnection::SetKnowledgeSchema(const DistributedRdb::RdbKnowledgeSchema &schema) +{ + DistributedDB::DBStatus status = DistributedDB::DBStatus::OK; + for (const auto &table : schema.tables) { + DistributedDB::KnowledgeSourceSchema sourceSchema; + sourceSchema.tableName = table.tableName; + for (const auto &item : table.knowledgeFields) { + sourceSchema.knowledgeColNames.insert(item.columnName); + } + sourceSchema.extendColNames = std::set(table.referenceFields.begin(), + table.referenceFields.end()); + status = SetKnowledgeSourceSchema(dbHandle_, sourceSchema); + if (status != DistributedDB::DBStatus::OK) { + return E_ERROR; + } } - LOG_INFO("backup, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount); - return ExchangeStrategy::BACKUP; + return E_OK; } -int32_t SqliteConnection::Repair(const RdbStoreConfig &config) +int SqliteConnection::CleanDirtyLog(const std::string &table, uint64_t cursor) { - if (config.GetHaMode() == HAMode::MANUAL_TRIGGER) { - return SqliteConnection::Restore(config, SqliteUtils::GetSlavePath(config.GetPath()), config.GetPath()); + if (table.empty()) { + LOG_ERROR("table is empty"); + return E_INVALID_ARGS; } + auto status = CleanDeletedData(dbHandle_, table, cursor); + return status == DistributedDB::DBStatus::OK ? E_OK : E_ERROR; +} + +int32_t SqliteConnection::Repair(const RdbStoreConfig &config) +{ std::shared_ptr connection = std::make_shared(config, true); if (connection == nullptr) { return E_ERROR; @@ -1358,6 +1513,9 @@ int32_t SqliteConnection::Repair(const RdbStoreConfig &config) return ret; } connection->slaveConnection_ = conn; + if (IsSupportBinlog(config)) { + SqliteConnection::ReplayBinlog(config.GetPath(), conn, false); + } ret = connection->VeritySlaveIntegrity(); if (ret != E_OK) { return ret; @@ -1369,11 +1527,12 @@ int32_t SqliteConnection::Repair(const RdbStoreConfig &config) return ret; } connection->TryCheckPoint(true); - SlaveStatus curStatus; + std::shared_ptr curStatus = std::make_shared(SlaveStatus::UNDEFINED); ret = connection->ExchangeSlaverToMaster(true, false, curStatus); if (ret != E_OK) { - LOG_ERROR("repair failed, [%{public}s]->[%{public}s], err:%{public}d", rdbSlaveStoreConfig.GetName().c_str(), - SqliteUtils::Anonymous(config.GetName()).c_str(), ret); + auto slavePath = SqliteUtils::GetSlavePath(config.GetPath()); + LOG_ERROR("repair failed, [%{public}s]->[%{public}s], err:%{public}d", + SqliteUtils::Anonymous(slavePath).c_str(), SqliteUtils::Anonymous(config.GetName()).c_str(), ret); } else { LOG_INFO("repair main success:%{public}s", SqliteUtils::Anonymous(config.GetPath()).c_str()); } @@ -1383,6 +1542,7 @@ int32_t SqliteConnection::Repair(const RdbStoreConfig &config) int SqliteConnection::ExchangeVerify(bool isRestore) { if (isRestore) { + SqliteConnection::ReplayBinlog(config_); int err = VeritySlaveIntegrity(); if (err != E_OK) { return err; @@ -1391,7 +1551,7 @@ int SqliteConnection::ExchangeVerify(bool isRestore) return E_OK; } if (SqliteUtils::IsSlaveInvalid(config_.GetPath())) { - LOG_ERROR("incomplete slave, %{public}s", config_.GetName().c_str()); + LOG_ERROR("incomplete slave, %{public}s", SqliteUtils::Anonymous(config_.GetName()).c_str()); return E_SQLITE_CORRUPT; } return E_OK; @@ -1400,7 +1560,8 @@ int SqliteConnection::ExchangeVerify(bool isRestore) return E_ALREADY_CLOSED; } if (access(config_.GetPath().c_str(), F_OK) != 0) { - LOG_WARN("main no exist, isR:%{public}d, %{public}s", isRestore, config_.GetName().c_str()); + LOG_WARN("main no exist, isR:%{public}d, %{public}s", isRestore, + SqliteUtils::Anonymous(config_.GetName()).c_str()); return E_DB_NOT_EXIST; } auto [cRet, cObj] = ExecuteForValue(INTEGRITIES[1]); // 1 is quick_check @@ -1414,7 +1575,7 @@ int SqliteConnection::ExchangeVerify(bool isRestore) } std::pair> SqliteConnection::InnerCreate( - const RdbStoreConfig &config, bool isWrite) + const RdbStoreConfig &config, bool isWrite, bool isReusableReplica) { std::pair> result = { E_ERROR, nullptr }; auto &[errCode, conn] = result; @@ -1432,8 +1593,13 @@ std::pair> SqliteConnection::InnerCre if (isWrite && config.GetHaMode() != HAMode::SINGLE) { RdbStoreConfig slaveCfg = connection->GetSlaveRdbStoreConfig(config); auto [err, slaveConn] = connection->CreateSlaveConnection(slaveCfg, SlaveOpenPolicy::OPEN_IF_DB_VALID); - if (err == E_OK) { - conn->slaveConnection_ = slaveConn; + if (err != E_OK) { + return result; + } + conn->slaveConnection_ = slaveConn; + conn->SetBinlog(); + if (isReusableReplica) { + reusableReplicas_.InsertOrAssign(slaveCfg.GetPath(), slaveConn); } } return result; @@ -1453,7 +1619,7 @@ int SqliteConnection::VeritySlaveIntegrity() if (SqliteUtils::IsSlaveInterrupted(config_.GetPath())) { return E_SQLITE_CORRUPT; } - + Suspender suspender(Suspender::SQL_LOG); std::string sql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';"; auto [err, obj] = slaveConnection_->ExecuteForValue(sql); auto val = std::get_if(&obj.value); @@ -1470,9 +1636,14 @@ int SqliteConnection::VeritySlaveIntegrity() mCount = static_cast(*val); } } - bool isSlaveDbOverLimit = bugInfo.find(FILE_SUFFIXES[DB_INDEX].debug_) != bugInfo.end() && - bugInfo[FILE_SUFFIXES[DB_INDEX].debug_].size_ > SLAVE_INTEGRITY_CHECK_LIMIT; - if (isSlaveDbOverLimit && mCount == 0L) { + ssize_t slaveSize = 0; + if (IsSupportBinlog(config_)) { + slaveSize = SqliteUtils::GetDecompressedSize(slaveCfg.GetPath()); + } + if (slaveSize == 0 && bugInfo.find(FILE_SUFFIXES[DB_INDEX].debug_) != bugInfo.end()) { + slaveSize = bugInfo[FILE_SUFFIXES[DB_INDEX].debug_].size_; + } + if ((slaveSize > SLAVE_INTEGRITY_CHECK_LIMIT && mCount == 0L) || IsSupportBinlog(config_)) { return SqliteUtils::IsSlaveInvalid(config_.GetPath()) ? E_SQLITE_CORRUPT : E_OK; } @@ -1491,11 +1662,11 @@ bool SqliteConnection::IsDbVersionBelowSlave() if (slaveConnection_ == nullptr) { return false; } - + Suspender suspender(Suspender::SQL_LOG); auto [cRet, cObj] = ExecuteForValue("SELECT COUNT(*) FROM sqlite_master WHERE type='table';"); auto cVal = std::get_if(&cObj.value); if (cRet == E_SQLITE_CORRUPT || (cVal != nullptr && (static_cast(*cVal) == 0L))) { - LOG_INFO("main empty, %{public}d, %{public}s", cRet, config_.GetName().c_str()); + LOG_INFO("main empty, %{public}d, %{public}s", cRet, SqliteUtils::Anonymous(config_.GetName()).c_str()); return true; } @@ -1511,90 +1682,237 @@ bool SqliteConnection::IsDbVersionBelowSlave() return false; } -int SqliteConnection::CopyDb(const RdbStoreConfig &config, const std::string &srcPath, const std::string &destPath) +void SqliteConnection::BinlogOnErrFunc(void *pCtx, int errNo, char *errMsg, const char *dbPath) { - RdbStoreConfig srcConfig(config); - srcConfig.SetPath(srcPath); - srcConfig.SetIntegrityCheck(IntegrityCheck::FULL); - srcConfig.SetHaMode(HAMode::SINGLE); - auto [ret, conn] = Connection::Create(srcConfig, true); - if (ret == E_SQLITE_CORRUPT && srcConfig.IsEncrypt() && srcConfig.GetIter() != ITER_V1) { - srcConfig.SetIter(ITER_V1); - std::tie(ret, conn) = Connection::Create(srcConfig, true); + if (dbPath == nullptr) { + LOG_WARN("path is null"); + return; } - if (ret != E_OK) { - LOG_ERROR("backup file is corrupted, %{public}s", SqliteUtils::Anonymous(srcPath).c_str()); - return E_SQLITE_CORRUPT; + std::string dbPathStr(dbPath); + LOG_WARN("binlog failed, mark invalid %{public}s", SqliteUtils::Anonymous(dbPathStr).c_str()); + SqliteUtils::SetSlaveInvalid(dbPathStr); +} + +int SqliteConnection::BinlogOpenHandle(const std::string &dbPath, sqlite3 *&dbHandle, bool isMemoryRdb) +{ + uint32_t openFileFlags = (SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX); + if (isMemoryRdb) { + openFileFlags |= SQLITE_OPEN_URI; } - conn = nullptr; + sqlite3 *db = nullptr; + int err = sqlite3_open_v2(dbPath.c_str(), &db, static_cast(openFileFlags), nullptr); + if (err != SQLITE_OK) { + LOG_ERROR("open binlog handle error. rc=%{public}d, errno=%{public}d, p=%{public}s", + err, errno, SqliteUtils::Anonymous(dbPath).c_str()); + sqlite3_close_v2(db); + return E_INVALID_FILE_PATH; + } + dbHandle = db; + return E_OK; +} - auto walFile = srcPath + "-wal"; - if (SqliteUtils::GetFileSize(walFile) != 0) { - LOG_ERROR("Wal file exist."); - return E_SQLITE_CORRUPT; +void SqliteConnection::BinlogCloseHandle(sqlite3 *dbHandle) +{ + if (dbHandle != nullptr) { + int errCode = sqlite3_close_v2(dbHandle); + if (errCode != SQLITE_OK) { + LOG_ERROR("could not close binlog handle err = %{public}d, errno = %{public}d", errCode, errno); + } } - SqliteUtils::DeleteFile(srcPath + "-shm"); - SqliteUtils::DeleteFile(srcPath + "-wal"); - Connection::Delete(config); +} - if (config.GetPath() != destPath) { - RdbStoreConfig dstConfig(destPath); - Connection::Delete(dstConfig); +int SqliteConnection::CheckPathExist(const std::string &dbPath) +{ + bool isDbFileExist = access(dbPath.c_str(), F_OK) == 0; + if (!isDbFileExist) { + LOG_ERROR("db %{public}s not exist errno is %{public}d", + SqliteUtils::Anonymous(dbPath).c_str(), errno); + return E_DB_NOT_EXIST; } + return E_OK; +} - if (!SqliteUtils::CopyFile(srcPath, destPath)) { - return E_ERROR; +void SqliteConnection::BinlogSetConfig(sqlite3 *dbHandle) +{ + Sqlite3BinlogConfig binLogConfig = { + .mode = Sqlite3BinlogMode::ROW, + .fullCallbackThreshold = BINLOG_FILE_NUMS_LIMIT, + .maxFileSize = BINLOG_FILE_SIZE_LIMIT, + .xErrorCallback = &BinlogOnErrFunc, + .xLogFullCallback = nullptr, + .callbackCtx = nullptr, + }; + + int err = sqlite3_db_config(dbHandle, SQLITE_DBCONFIG_ENABLE_BINLOG, &binLogConfig); + if (err != SQLITE_OK) { + LOG_ERROR("set binlog config error. err=%{public}d, errno=%{public}d", err, errno); + } +} + +void SqliteConnection::BinlogOnFullFunc(void *pCtx, unsigned short currentCount, const char *dbPath) +{ + if (dbPath == nullptr) { + LOG_WARN("path is null"); + return; + } + auto pool = TaskExecutor::GetInstance().GetExecutor(); + if (pool == nullptr) { + LOG_WARN("get pool failed"); + return; + } + std::string dbPathStr(dbPath); + auto [found, weakPtr] = reusableReplicas_.Find(SqliteUtils::GetSlavePath(dbPathStr)); + if (!found) { + LOG_WARN("no replica connection for %{public}s", SqliteUtils::Anonymous(dbPath).c_str()); + return; + } + auto slaveConn = weakPtr.lock(); + if (slaveConn == nullptr) { + LOG_WARN("replica connection expired for %{public}s", SqliteUtils::Anonymous(dbPath).c_str()); + return; + } + pool->Execute([dbPathStr, slaveConn] { + SqliteConnection::ReplayBinlog(dbPathStr, slaveConn, true); + }); +} + +int SqliteConnection::SetBinlog() +{ + if (!IsSupportBinlog(config_)) { + return E_OK; + } + Sqlite3BinlogConfig binLogConfig = { + .mode = Sqlite3BinlogMode::ROW, + .fullCallbackThreshold = BINLOG_FILE_NUMS_LIMIT, + .maxFileSize = BINLOG_FILE_SIZE_LIMIT, + .xErrorCallback = &BinlogOnErrFunc, + .xLogFullCallback = &BinlogOnFullFunc, + .callbackCtx = nullptr, + }; + + LOG_INFO("binlog: open %{public}s", SqliteUtils::Anonymous(config_.GetPath()).c_str()); + int err = sqlite3_db_config(dbHandle_, SQLITE_DBCONFIG_ENABLE_BINLOG, &binLogConfig); + if (err != SQLITE_OK) { + LOG_ERROR("set binlog error. err=%{public}d, errno=%{public}d", err, errno); + return err; } return E_OK; } -int32_t SqliteConnection::Restore(const RdbStoreConfig &config, const std::string &srcPath, const std::string &destPath) +void SqliteConnection::ReplayBinlog(const std::string &dbPath, + std::shared_ptr slaveConn, bool isNeedClean) { - if (config.GetHaMode() == HAMode::SINGLE || !SqliteUtils::IsSlaveDbName(srcPath)) { - return SqliteConnection::CopyDb(config, srcPath, destPath); + auto errCode = SqliteConnection::CheckPathExist(dbPath); + if (errCode != E_OK) { + LOG_WARN("main db does not exist, %{public}d", errCode); + return; } - std::shared_ptr connection = std::make_shared(config, true); - if (connection == nullptr) { - return E_ERROR; + if (slaveConn == nullptr || slaveConn->dbHandle_ == nullptr) { + LOG_WARN("backup db does not exist, %{public}d", slaveConn == nullptr); + return; } - RdbStoreConfig slaveConfig = connection->GetSlaveRdbStoreConfig(config); - if (access(slaveConfig.GetPath().c_str(), F_OK) != 0) { - return E_NOT_SUPPORT; + sqlite3 *dbFrom = nullptr; + errCode = SqliteConnection::BinlogOpenHandle(dbPath, dbFrom, false); + if (errCode != E_OK) { + return; } - auto [ret, conn] = connection->CreateSlaveConnection(slaveConfig, SlaveOpenPolicy::FORCE_OPEN); - if (ret != E_OK) { - return ret; + SqliteConnection::BinlogSetConfig(dbFrom); + errCode = SQLiteError::ErrNo(sqlite3_replay_binlog(dbFrom, slaveConn->dbHandle_)); + if (errCode != E_OK) { + LOG_WARN("async replay err:%{public}d", errCode); + } else if (isNeedClean) { + errCode = SQLiteError::ErrNo(sqlite3_clean_binlog(dbFrom, BinlogFileCleanModeE::BINLOG_FILE_CLEAN_READ_MODE)); + LOG_INFO("clean finished, %{public}d, %{public}s", errCode, SqliteUtils::Anonymous(dbPath).c_str()); } - connection->slaveConnection_ = conn; + SqliteConnection::BinlogCloseHandle(dbFrom); + return; +} - int openMainRes = connection->InnerOpen(config); - ret = connection->VeritySlaveIntegrity(); - if (ret != E_OK) { - return ret; +void SqliteConnection::ReplayBinlog(const RdbStoreConfig &config) +{ + if (!IsSupportBinlog(config)) { + return; } - if (openMainRes == E_OK && SqliteUtils::IsSlaveInvalid(config.GetPath()) && !connection->IsDbVersionBelowSlave()) { - return E_SQLITE_CORRUPT; + if (slaveConnection_ == nullptr) { + LOG_WARN("back up does not exist"); + return; + } + if (SqliteConnection::CheckPathExist(config.GetPath()) != E_OK) { + LOG_WARN("main db does not exist"); + return; + } + int err = SQLiteError::ErrNo(sqlite3_replay_binlog(dbHandle_, slaveConnection_->dbHandle_)); + if (err != E_OK) { + LOG_WARN("replay err:%{public}d", err); } + return; +} - ret = SQLiteError::ErrNo(sqlite3_wal_checkpoint_v2(connection->slaveConnection_->dbHandle_, nullptr, - SQLITE_CHECKPOINT_TRUNCATE, nullptr, nullptr)); - if (ret != E_OK) { - LOG_ERROR("chk %{public}d %{public}d %{public}s", ret, errno, SqliteUtils::Anonymous(config.GetName()).c_str()); - return ret; +void SqliteConnection::SetIsSupportBinlog(bool isSupport) +{ + isSupportBinlog_ = isSupport; +} + +bool SqliteConnection::IsSupportBinlog(const RdbStoreConfig &config) +{ +#if !defined(CROSS_PLATFORM) + if (sqlite3_is_support_binlog == nullptr) { + return false; + } + if (sqlite3_is_support_binlog(config.GetName().c_str()) != SQLITE_OK) { + return false; } - connection->slaveConnection_ = nullptr; - connection = nullptr; + return !config.IsEncrypt() && !config.IsMemoryRdb(); +#else + return false; +#endif +} - if (!SqliteUtils::RenameFile(slaveConfig.GetPath(), config.GetPath())) { - LOG_ERROR("rename %{public}d %{public}s", errno, SqliteUtils::Anonymous(config.GetName()).c_str()); - return E_ERROR; +std::string SqliteConnection::GetBinlogFolderPath(const std::string &dbPath) +{ + std::string suffix(BINLOG_FOLDER_SUFFIX); + return dbPath + suffix; +} + +ExchangeStrategy SqliteConnection::CompareWithSlave(int64_t mCount, int64_t mIdxCount) +{ + const std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';"; + const std::string qIndexSql = "SELECT COUNT(*) FROM sqlite_master WHERE type='index';"; + auto [sRet, sObj] = slaveConnection_->ExecuteForValue(querySql); + auto [sInxRet, sInxObj] = slaveConnection_->ExecuteForValue(qIndexSql); + if (sRet == E_SQLITE_CORRUPT || sInxRet == E_SQLITE_CORRUPT) { + LOG_WARN("slave db abnormal, need backup, err:%{public}d", sRet); + return ExchangeStrategy::BACKUP; } - for (auto &suffix : FILE_SUFFIXES) { - if (suffix.suffix_ != nullptr && !std::string(suffix.suffix_).empty()) { - SqliteUtils::DeleteFile(config.GetPath() + suffix.suffix_); - } + int64_t sCount = static_cast(sObj); + int64_t sIdxCount = static_cast(sInxObj); + if ((mCount == sCount && mIdxCount == sIdxCount) && !SqliteUtils::IsSlaveInvalid(config_.GetPath())) { + LOG_INFO("equal, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount); + return ExchangeStrategy::NOT_HANDLE; + } + if (mCount == 0) { + LOG_INFO("main empty, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount); + return ExchangeStrategy::RESTORE; } - Connection::Delete(slaveConfig.GetPath()); + LOG_INFO("backup, main:[%{public}" PRId64 ",%{public}" PRId64 "], slave:[%{public}" PRId64 ",%{public}" PRId64 "]", + mCount, mIdxCount, sCount, sIdxCount); + return ExchangeStrategy::BACKUP; +} + +int SqliteConnection::RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func) +{ + return E_NOT_SUPPORT; +} + +int32_t SqliteConnection::ClientCleanUp() +{ + Clean(false); + return E_OK; +} + +int32_t SqliteConnection::OpenSSLCleanUp() +{ + Clean(true); return E_OK; } } // namespace NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/sqlite_global_config.cpp b/relational_store/frameworks/native/rdb/src/sqlite_global_config.cpp index d75a1236..76064345 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_global_config.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_global_config.cpp @@ -63,6 +63,10 @@ SqliteGlobalConfig::SqliteGlobalConfig() SqliteGlobalConfig::~SqliteGlobalConfig() { + sqlite3_unregister_cksumvfs(); + sqlite3_config(SQLITE_CONFIG_CORRUPTION, nullptr, nullptr); + sqlite3_config(SQLITE_CONFIG_LOG, nullptr, nullptr); + LOG_INFO("Destruct."); } void SqliteGlobalConfig::Corruption(void *arg, const void *msg) @@ -82,21 +86,22 @@ void SqliteGlobalConfig::Log(const void *data, int err, const char *msg) if (errType == 0 || errType == SQLITE_CONSTRAINT || errType == SQLITE_SCHEMA || errType == SQLITE_NOTICE || err == SQLITE_WARNING_AUTOINDEX) { if (verboseLog) { - LOG_INFO("Error(%{public}d) %{public}s ", err, SqliteUtils::Anonymous(msg).c_str()); + LOG_INFO("Error(%{public}d) %{public}s ", err, SqliteUtils::SqlAnonymous(msg).c_str()); } } else if (errType == SQLITE_WARNING) { - LOG_WARN("WARNING(%{public}d) %{public}s ", err, SqliteUtils::Anonymous(msg).c_str()); + LOG_WARN("WARNING(%{public}d) %{public}s ", err, SqliteUtils::SqlAnonymous(msg).c_str()); } else { - LOG_ERROR("Error(%{public}d) errno is:%{public}d %{public}s.", err, errno, SqliteUtils::Anonymous(msg).c_str()); + LOG_ERROR("Error(%{public}d) errno is:%{public}d %{public}s.", err, errno, + SqliteUtils::SqlAnonymous(msg).c_str()); SqliteErrReport(err, msg); } } void SqliteGlobalConfig::SqliteErrReport(int err, const char *msg) { - int lowErr = (err & 0xFF); + auto lowErr = static_cast(err) & 0xFF; if (lowErr == SQLITE_NOMEM || lowErr == SQLITE_INTERRUPT || lowErr == SQLITE_FULL || lowErr == SQLITE_SCHEMA || - lowErr == SQLITE_NOLFS || lowErr == SQLITE_AUTH || lowErr == SQLITE_BUSY || lowErr == SQLITE_LOCKED || + lowErr == SQLITE_NOLFS || lowErr == SQLITE_AUTH || lowErr == SQLITE_BUSY || lowErr == SQLITE_LOCKED || lowErr == SQLITE_IOERR || lowErr == SQLITE_CANTOPEN) { std::string log(msg == nullptr ? "" : SqliteUtils::Anonymous(msg).c_str()); log.append(",errcode=").append(std::to_string(err)).append(",errno=").append(std::to_string(errno)); diff --git a/relational_store/frameworks/native/rdb/src/sqlite_shared_result_set.cpp b/relational_store/frameworks/native/rdb/src/sqlite_shared_result_set.cpp index 14a523fb..962b2214 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_shared_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_shared_result_set.cpp @@ -64,8 +64,8 @@ SqliteSharedResultSet::SqliteSharedResultSet( int64_t countCost = duration_cast(endTime - countBegin).count(); LOG_WARN("total[%{public}" PRId64 "]<%{public}" PRId64 ",%{public}" PRId64 ",%{public}" PRId64 "> rowCount[%{public}d] sql[%{public}s] path[%{public}s]", - totalCost, acquireCost, prepareCost, countCost, rowCount_, qrySql_.c_str(), - SqliteUtils::Anonymous(path).c_str()); + totalCost, acquireCost, prepareCost, countCost, rowCount_, + SqliteUtils::SqlAnonymous(qrySql_).c_str(), SqliteUtils::Anonymous(path).c_str()); } } @@ -84,7 +84,7 @@ std::pair, int> SqliteSharedResultSet::PrepareStep() auto type = SqliteUtils::GetSqlStatementType(qrySql_); if (type == SqliteUtils::STATEMENT_ERROR) { - LOG_ERROR("invalid sql_ %{public}s!", qrySql_.c_str()); + LOG_ERROR("invalid sql_ %{public}s, type: %{public}d", SqliteUtils::SqlAnonymous(qrySql_).c_str(), type); lastErr_ = E_INVALID_ARGS; return { nullptr, E_INVALID_ARGS }; } @@ -96,7 +96,7 @@ std::pair, int> SqliteSharedResultSet::PrepareStep() } if (!statement->ReadOnly()) { - LOG_ERROR("failed, %{public}s is not query sql!", SqliteUtils::Anonymous(qrySql_).c_str()); + LOG_ERROR("failed, %{public}s is not query sql!", SqliteUtils::SqlAnonymous(qrySql_).c_str()); lastErr_ = E_NOT_SELECT; return { nullptr, E_NOT_SELECT }; } @@ -117,8 +117,8 @@ SqliteSharedResultSet::~SqliteSharedResultSet() {} std::pair> SqliteSharedResultSet::GetColumnNames() { if (isClosed_) { - LOG_ERROR( - "fail, result set has been closed, ret %{public}d, sql %{public}s", E_ALREADY_CLOSED, qrySql_.c_str()); + LOG_ERROR("fail, result set has been closed, ret %{public}d, sql %{public}s", + E_ALREADY_CLOSED, SqliteUtils::SqlAnonymous(qrySql_).c_str()); return { E_ALREADY_CLOSED, {} }; } @@ -155,8 +155,8 @@ int SqliteSharedResultSet::Close() int SqliteSharedResultSet::OnGo(int oldPosition, int newPosition) { if (isClosed_) { - LOG_ERROR( - "fail, result set has been closed, ret %{public}d, sql %{public}s", E_ALREADY_CLOSED, qrySql_.c_str()); + LOG_ERROR("fail, result set has been closed, ret %{public}d, sql %{public}s", + E_ALREADY_CLOSED, SqliteUtils::SqlAnonymous(qrySql_).c_str()); return E_ALREADY_CLOSED; } auto sharedBlock = GetBlock(); diff --git a/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp b/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp index 2653f870..8cdc4457 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp @@ -36,38 +36,6 @@ std::reference_wrapper SqliteSqlBuilder::nullRef_ = SqliteSqlBuilde SqliteSqlBuilder::SqliteSqlBuilder() {} SqliteSqlBuilder::~SqliteSqlBuilder() {} -/** - * Build a count SQL string using the given condition for SQLite. - */ -std::string SqliteSqlBuilder::BuildUpdateString(const ValuesBucket &values, const std::string &tableName, - const std::vector &whereArgs, const std::string &index, const std::string &whereClause, - const std::string &group, const std::string &order, int limit, int offset, std::vector &bindArgs, - ConflictResolution conflictResolution) -{ - std::string sql; - - sql.append("UPDATE") - .append(g_onConflictClause[static_cast(conflictResolution)]) - .append(" ") - .append(HandleTable(tableName)) - .append(" SET "); - const char *split = ""; - for (auto &[key, val] : values.values_) { - sql.append(split); - sql.append(key).append("=?"); - bindArgs.push_back(val); - split = ","; - } - - if (!whereArgs.empty()) { - for (size_t i = 0; i < whereArgs.size(); i++) { - bindArgs.push_back(ValueObject(whereArgs[i])); - } - } - sql.append(BuildSqlStringFromPredicates(index, "", whereClause, group, order, limit, offset)); - return sql; -} - /** * Build a query SQL string using the given condition for SQLite. */ @@ -78,58 +46,27 @@ int SqliteSqlBuilder::BuildQueryString(bool distinct, const std::string &table, if (table.empty()) { return E_EMPTY_TABLE_NAME; } - - std::string sql; - sql.append("SELECT "); - if (distinct) { - sql.append("DISTINCT "); - } - if (columns.size() != 0) { - AppendColumns(sql, columns); - } else { - sql.append("* "); - } - sql.append("FROM ") - .append(HandleTable(table)) - .append(BuildSqlStringFromPredicates(indexName, joinClause, whereClause, groupBy, orderBy, limit, offset)); - outSql = sql; - + outSql = GetSelectClause(columns, distinct, "*"); + AppendClause(outSql, " FROM ", table); + AppendClause(outSql, " INDEXED BY ", indexName); + AppendClause(outSql, " ", joinClause); + AppendClause(outSql, " WHERE ", whereClause); + AppendClause(outSql, " GROUP BY ", groupBy); + AppendClause(outSql, " ORDER BY ", orderBy); + AppendLimitAndOffset(outSql, limit, offset); return E_OK; } -std::string SqliteSqlBuilder::BuildSqlStringFromPredicates(const std::string &index, const std::string &joinClause, - const std::string &whereClause, const std::string &group, const std::string &order, int limit, int offset) +std::string SqliteSqlBuilder::BuildClauseFromPredicates(const AbsRdbPredicates &predicates) { std::string sqlString; - - std::string limitStr = (limit == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(limit); - std::string offsetStr = (offset == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(offset); - - AppendClause(sqlString, " INDEXED BY ", index); - AppendClause(sqlString, " ", joinClause); - AppendClause(sqlString, " WHERE ", whereClause); - AppendClause(sqlString, " GROUP BY ", group); - AppendClause(sqlString, " ORDER BY ", order); - AppendClause(sqlString, " LIMIT ", limitStr); - AppendClause(sqlString, " OFFSET ", offsetStr); - - return sqlString; -} - -std::string SqliteSqlBuilder::BuildSqlStringFromPredicates(const AbsPredicates &predicates) -{ - std::string limitStr = - (predicates.GetLimit() == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(predicates.GetLimit()); - std::string offsetStr = - (predicates.GetOffset() == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(predicates.GetOffset()); - - std::string sqlString; AppendClause(sqlString, " INDEXED BY ", predicates.GetIndex()); + AppendClause(sqlString, " ", predicates.GetJoinClause()); AppendClause(sqlString, " WHERE ", predicates.GetWhereClause()); AppendClause(sqlString, " GROUP BY ", predicates.GetGroup()); + AppendClause(sqlString, " HAVING ", predicates.GetHaving()); AppendClause(sqlString, " ORDER BY ", predicates.GetOrder()); - AppendClause(sqlString, " LIMIT ", limitStr); - AppendClause(sqlString, " OFFSET ", offsetStr); + AppendLimitAndOffset(sqlString, predicates.GetLimit(), predicates.GetOffset()); return sqlString; } @@ -171,53 +108,63 @@ void SqliteSqlBuilder::AppendColumns( } } +void SqliteSqlBuilder::AppendLimitAndOffset(std::string &builder, int limit, int offset) +{ + std::string limitStr = (limit == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(limit); + std::string offsetStr = (offset == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(offset); + AppendClause(builder, " LIMIT ", limitStr); + AppendClause(builder, " OFFSET ", offsetStr); +} + +std::string SqliteSqlBuilder::GetSelectClause( + const std::vector &columns, bool IsDistinct, const std::string &ast, const std::string &table) +{ + std::string sql; + sql.append("SELECT "); + if (IsDistinct) { + sql.append("DISTINCT "); + } + if (!columns.empty()) { + AppendColumns(sql, columns, table); + } else { + sql.append(table + ast); + } + return sql; +} + std::string SqliteSqlBuilder::BuildQueryString( const AbsRdbPredicates &predicates, const std::vector &columns) { - bool distinct = predicates.IsDistinct(); - std::string tableName = predicates.GetTableName(); - std::string joinClauseStr = predicates.GetJoinClause(); - std::string whereClauseStr = predicates.GetWhereClause(); - std::string groupStr = predicates.GetGroup(); - std::string indexStr = predicates.GetIndex(); - std::string orderStr = predicates.GetOrder(); - int limit = predicates.GetLimit(); - int offset = predicates.GetOffset(); - std::string sqlStr; - BuildQueryString(distinct, tableName, joinClauseStr, columns, whereClauseStr, groupStr, indexStr, orderStr, limit, - offset, sqlStr); + if (predicates.GetTableName().empty()) { + return ""; + } + + std::string sqlStr = GetSelectClause(columns, predicates.IsDistinct(), "*"); + AppendClause(sqlStr, " FROM ", predicates.GetTableName()); + sqlStr.append(BuildClauseFromPredicates(predicates)); return sqlStr; } std::string SqliteSqlBuilder::BuildCountString(const AbsRdbPredicates &predicates) { std::string tableName = predicates.GetTableName(); - return "SELECT COUNT(*) FROM " + HandleTable(tableName) + BuildSqlStringFromPredicates(predicates); + return "SELECT COUNT(*) FROM " + tableName + BuildClauseFromPredicates(predicates); } std::string SqliteSqlBuilder::BuildCursorQueryString(const AbsRdbPredicates &predicates, const std::vector &columns, const std::string &logTable, const std::pair &queryStatus) { - std::string sql; - std::string table = HandleTable(predicates.GetTableName()); - auto logName = HandleTable(logTable); + std::string table = predicates.GetTableName(); + auto logName = logTable; if (table.empty() || logName.empty()) { - return sql; - } - sql.append("SELECT "); - if (predicates.IsDistinct()) { - sql.append("DISTINCT "); - } - if (!columns.empty()) { - AppendColumns(sql, columns, table); - } else { - sql.append(table + ".*"); + return ""; } + std::string sql = GetSelectClause(columns, predicates.IsDistinct(), ".*", table); + logName += "."; if (queryStatus.first) { - std::string field = DistributedRdb::Field::SHARING_RESOURCE_FIELD; - SqliteUtils::Replace(field, SqliteUtils::REP, ""); - SqliteUtils::Replace(sql, table + "." + DistributedRdb::Field::SHARING_RESOURCE_FIELD, - logName + "." + SHARING_RESOURCE + " AS " + field); + std::string field = SqliteUtils::Replace(DistributedRdb::Field::SHARING_RESOURCE_FIELD, SqliteUtils::REP, ""); + sql = SqliteUtils::Replace(sql, table + "." + DistributedRdb::Field::SHARING_RESOURCE_FIELD, + logName + SHARING_RESOURCE + " AS " + field); } if (queryStatus.second) { sql.append(", " + logTable + ".cursor"); @@ -231,61 +178,39 @@ std::string SqliteSqlBuilder::BuildCursorQueryString(const AbsRdbPredicates &pre AppendClause(sql, " INDEXED BY ", predicates.GetIndex()); sql.append(" INNER JOIN ").append(logTable).append(" ON ").append(table) .append(".ROWID = ").append(logTable).append(".data_key"); - auto whereClause = predicates.GetWhereClause(); - SqliteUtils::Replace(whereClause, SqliteUtils::REP, logName + "."); - AppendClause(sql, " WHERE ", whereClause); + + AppendClause(sql, " WHERE ", SqliteUtils::Replace(predicates.GetWhereClause(), SqliteUtils::REP, logName)); AppendClause(sql, " GROUP BY ", predicates.GetGroup(), table); - auto order = predicates.GetOrder(); - SqliteUtils::Replace(order, SqliteUtils::REP, logName + "."); - AppendClause(sql, " ORDER BY ", order); - int limit = predicates.GetLimit(); - auto limitClause = (limit == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(limit); - int offset = predicates.GetOffset(); - auto offsetClause = (offset == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(offset); - AppendClause(sql, " LIMIT ", limitClause); - AppendClause(sql, " OFFSET ", offsetClause); + AppendClause(sql, " HAVING ", SqliteUtils::Replace(predicates.GetHaving(), SqliteUtils::REP, logName)); + AppendClause(sql, " ORDER BY ", SqliteUtils::Replace(predicates.GetOrder(), SqliteUtils::REP, logName)); + AppendLimitAndOffset(sql, predicates.GetLimit(), predicates.GetOffset()); return sql; } std::string SqliteSqlBuilder::BuildLockRowQueryString( const AbsRdbPredicates &predicates, const std::vector &columns, const std::string &logTable) { - std::string sql; - std::string table = HandleTable(predicates.GetTableName()); - auto logName = HandleTable(logTable); + std::string table = predicates.GetTableName(); + auto logName = logTable; if (table.empty() || logName.empty()) { - return sql; - } - sql.append("SELECT "); - if (predicates.IsDistinct()) { - sql.append("DISTINCT "); - } - if (!columns.empty()) { - AppendColumns(sql, columns, table); - } else { - sql.append(table + ".*"); + return ""; } + std::string sql = GetSelectClause(columns, predicates.IsDistinct(), ".*", table); sql.append(" FROM ").append(table); AppendClause(sql, " INDEXED BY ", predicates.GetIndex()); sql.append(" INNER JOIN ").append(logName).append(" ON "); - sql.append(table).append(".ROWID = ").append(logName).append(".data_key"); + logName += "."; + sql.append(table).append(".ROWID = ").append(logName).append("data_key"); auto whereClause = predicates.GetWhereClause(); if (whereClause.empty()) { - sql.append(" WHERE ").append(logName).append(".status = 2 OR ").append(logName).append(".status = 3 "); + sql.append(" WHERE ").append(logName).append("status = 2 OR ").append(logName).append("status = 3 "); } else { - SqliteUtils::Replace(whereClause, SqliteUtils::REP, logName + "."); - AppendClause(sql, " WHERE ", whereClause); + AppendClause(sql, " WHERE ", SqliteUtils::Replace(whereClause, SqliteUtils::REP, logName)); } AppendClause(sql, " GROUP BY ", predicates.GetGroup(), table); - auto order = predicates.GetOrder(); - SqliteUtils::Replace(order, SqliteUtils::REP, logName + "."); - AppendClause(sql, " ORDER BY ", order); - int limit = predicates.GetLimit(); - auto limitClause = (limit == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(limit); - int offset = predicates.GetOffset(); - auto offsetClause = (offset == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(offset); - AppendClause(sql, " LIMIT ", limitClause); - AppendClause(sql, " OFFSET ", offsetClause); + AppendClause(sql, " HAVING ", SqliteUtils::Replace(predicates.GetHaving(), SqliteUtils::REP, logName)); + AppendClause(sql, " ORDER BY ", SqliteUtils::Replace(predicates.GetOrder(), SqliteUtils::REP, logName)); + AppendLimitAndOffset(sql, predicates.GetLimit(), predicates.GetOffset()); return sql; } @@ -369,18 +294,6 @@ SqliteSqlBuilder::BatchRefSqls SqliteSqlBuilder::MakeExecuteSqls( return executeSqls; } -std::string SqliteSqlBuilder::HandleTable(const std::string &tableName) -{ - if (tableName.empty()) { - return tableName; - } - std::regex validName("^([a-zA-Z_][a-zA-Z0-9_\\.\\ ]*)$"); - if (std::regex_match(tableName, validName)) { - return tableName; - } - return "'" + tableName + "'"; -} - void SqliteSqlBuilder::UpdateAssetStatus(const ValueObject &val, int32_t status) { if (val.GetType() == ValueObject::TYPE_ASSET) { @@ -398,5 +311,17 @@ void SqliteSqlBuilder::UpdateAssetStatus(const ValueObject &val, int32_t status) } } } + +void SqliteSqlBuilder::AppendReturning(std::string &sql, const std::vector &fields) +{ + if (fields.empty()) { + return; + } + sql.append(" returning "); + for (const auto &field : fields) { + sql.append(field).append(","); + } + sql.pop_back(); +} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp b/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp index 429ab25d..16c24715 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp @@ -26,7 +26,10 @@ #include "raw_data_parser.h" #include "rdb_errno.h" #include "rdb_fault_hiview_reporter.h" +#include "rdb_sql_log.h" #include "rdb_sql_statistic.h" +#include "rdb_perfStat.h" +#include "rdb_types.h" #include "relational_store_client.h" #include "remote_result_set.h" #include "share_block.h" @@ -43,6 +46,7 @@ namespace NativeRdb { using namespace OHOS::Rdb; using namespace std::chrono; using SqlStatistic = DistributedRdb::SqlStatistic; +using PerfStat = DistributedRdb::PerfStat; using Reportor = RdbFaultHiViewReporter; // Setting Data Precision constexpr SqliteStatement::Action SqliteStatement::ACTIONS[ValueObject::TYPE_MAX]; @@ -52,16 +56,21 @@ static constexpr const char *ERR_MSG[] = { "no such column:", "has no column named" }; -SqliteStatement::SqliteStatement() : readOnly_(false), columnCount_(0), numParameters_(0), stmt_(nullptr), sql_("") + +SqliteStatement::SqliteStatement(const RdbStoreConfig *config) + : readOnly_(false), columnCount_(0), numParameters_(0), stmt_(nullptr), sql_(""), config_(config) { - seqId_ = SqlStatistic::GenerateId(); + seqId_ = PerfStat::GenerateId(); SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL_REF, seqId_); + PerfStat perfStat((config_ != nullptr) ? config_->GetPath() : "", "", SqlStatistic::Step::STEP_TOTAL_REF, seqId_); } SqliteStatement::~SqliteStatement() { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL_RES, seqId_); + PerfStat perfStat((config_ != nullptr) ? config_->GetPath() : "", "", PerfStat::Step::STEP_TOTAL_RES, seqId_); Finalize(); + slave_ = nullptr; conn_ = nullptr; config_ = nullptr; } @@ -120,6 +129,18 @@ void SqliteStatement::HandleErrMsg(const std::string &errMsg, const std::string } } } +void SqliteStatement::TryNotifyErrorLog(const int &errCode, sqlite3 *dbHandle, const std::string &sql) +{ + if (errCode == SQLITE_ROW || errCode == SQLITE_DONE || errCode == SQLITE_OK) { + return ; + } + std::string errMsg(sqlite3_errmsg(dbHandle)); + DistributedRdb::SqlErrorObserver::ExceptionMessage exceMessage; + exceMessage.code = errCode; + exceMessage.message = std::move(errMsg); + exceMessage.sql = sql; + NativeRdb::SqlLog::Notify(config_->GetPath(), exceMessage); +} int SqliteStatement::Prepare(sqlite3 *dbHandle, const std::string &newSql) { @@ -129,9 +150,11 @@ int SqliteStatement::Prepare(sqlite3 *dbHandle, const std::string &newSql) // prepare the new sqlite3_stmt sqlite3_stmt *stmt = nullptr; SqlStatistic sqlStatistic(newSql, SqlStatistic::Step::STEP_PREPARE, seqId_); + PerfStat perfStat((config_ != nullptr) ? config_->GetPath() : "", newSql, PerfStat::Step::STEP_PREPARE, seqId_); int errCode = sqlite3_prepare_v2(dbHandle, newSql.c_str(), newSql.length(), &stmt, nullptr); if (errCode != SQLITE_OK) { std::string errMsg(sqlite3_errmsg(dbHandle)); + TryNotifyErrorLog(errCode, dbHandle, newSql); if (errMsg.size() != 0) { HandleErrMsg(errMsg, config_->GetPath(), config_->GetBundleName()); } @@ -223,6 +246,7 @@ int SqliteStatement::BindArgs(const std::vector &bindArgs) int SqliteStatement::BindArgs(const std::vector> &bindArgs) { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_PREPARE, seqId_); + PerfStat perfStat((config_ != nullptr) ? config_->GetPath() : "", "", PerfStat::Step::STEP_PREPARE, seqId_); if (bound_) { sqlite3_reset(stmt_); sqlite3_clear_bindings(stmt_); @@ -237,7 +261,8 @@ int SqliteStatement::BindArgs(const std::vector &args) if (count > numParameters_) { LOG_ERROR("bind args count(%{public}d) > numParameters(%{public}d), sql: %{public}s", count, numParameters_, - sql_.c_str()); + SqliteUtils::SqlAnonymous(sql_).c_str()); return E_INVALID_BIND_ARGS_COUNT; } @@ -353,8 +378,11 @@ int SqliteStatement::Step() int SqliteStatement::InnerStep() { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_EXECUTE, seqId_); + PerfStat perfStat((config_ != nullptr) ? config_->GetPath() : "", "", PerfStat::Step::STEP_EXECUTE, seqId_); auto errCode = sqlite3_step(stmt_); int ret = SQLiteError::ErrNo(errCode); + auto db = sqlite3_db_handle(stmt_); + TryNotifyErrorLog(errCode, db, sql_); if (config_ != nullptr && (errCode == SQLITE_CORRUPT || (errCode == SQLITE_NOTADB && config_->GetIter() != 0))) { Reportor::ReportCorruptedOnce(Reportor::Create(*config_, ret, (errCode == SQLITE_CORRUPT ? SqliteGlobalConfig::GetLastCorruptionMsg() : "SqliteStatement::InnerStep"))); @@ -416,7 +444,7 @@ int32_t SqliteStatement::Execute(const std::vector(args.size()); if (count != numParameters_) { LOG_ERROR("bind args count(%{public}d) > numParameters(%{public}d), sql is %{public}s", count, numParameters_, - sql_.c_str()); + SqliteUtils::SqlAnonymous(sql_).c_str()); return E_INVALID_BIND_ARGS_COUNT; } @@ -440,7 +468,8 @@ int32_t SqliteStatement::Execute(const std::vectorExecute(args); if (errCode != E_OK) { - LOG_ERROR( - "slave execute error:%{public}d, sql is %{public}s, errno %{public}d", errCode, sql_.c_str(), errno); + LOG_ERROR("slave execute error:%{public}d, sql is %{public}s, errno %{public}d", + errCode, SqliteUtils::SqlAnonymous(sql_).c_str(), errno); SqliteUtils::SetSlaveInvalid(config_->GetPath()); } } @@ -602,6 +631,43 @@ std::pair SqliteStatement::GetColumn(int index) const return { E_OK, GetValueFromBlob(index, type) }; } +std::pair> SqliteStatement::GetRows(uint32_t maxCount) +{ + auto colCount = GetColumnCount(); + if (colCount <= 0) { + return { E_OK, {} }; + } + std::vector valuesBuckets; + std::vector colNames; + colNames.reserve(colCount); + for (int i = 0; i < colCount; i++) { + auto [code, colName] = GetColumnName(i); + if (code != E_OK) { + LOG_ERROR("GetColumnName ret %{public}d", code); + return { code, {} }; + } + colNames.push_back(std::move(colName)); + } + int32_t status = 0; + do { + if (valuesBuckets.size() >= maxCount) { + break; + } + ValuesBucket value; + for (int32_t i = 0; i < colCount; i++) { + auto [code, val] = GetColumn(i); + if (code != E_OK) { + LOG_WARN("GetColumn failed, errCode:%{public}d", code); + continue; + } + value.Put(colNames[i], std::move(val)); + } + valuesBuckets.push_back(std::move(value)); + status = InnerStep(); + } while (status == E_OK); + return { status, valuesBuckets }; +} + ValueObject SqliteStatement::GetValueFromBlob(int32_t index, int32_t type) const { int size = sqlite3_column_bytes(stmt_, index); @@ -650,6 +716,7 @@ bool SqliteStatement::SupportBlockInfo() const int32_t SqliteStatement::FillBlockInfo(SharedBlockInfo *info) const { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_EXECUTE, seqId_); + PerfStat perfStat((config_ != nullptr) ? config_->GetPath() : "", "", PerfStat::Step::STEP_EXECUTE, seqId_); if (info == nullptr) { return E_INVALID_ARGS; } @@ -660,6 +727,15 @@ int32_t SqliteStatement::FillBlockInfo(SharedBlockInfo *info) const errCode = FillSharedBlock(info, stmt_); } if (errCode != E_OK) { + if (config_ != nullptr) { + Reportor::ReportFault(RdbFaultDbFileEvent(FT_CURD, errCode, *config_, + "FillBlockInfo", true)); + } + auto ret = (config_ != nullptr && errCode == E_SQLITE_CORRUPT); + if (ret) { + Reportor::ReportCorruptedOnce(Reportor::Create(*config_, errCode, + "FillBlockInfo: " + SqliteGlobalConfig::GetLastCorruptionMsg())); + } return errCode; } if (!ResetStatement(info, stmt_)) { @@ -795,7 +871,9 @@ int SqliteStatement::InnerFinalize() return E_OK; } + auto db = sqlite3_db_handle(stmt_); int errCode = sqlite3_finalize(stmt_); + TryNotifyErrorLog(errCode, db, sql_); stmt_ = nullptr; sql_ = ""; readOnly_ = false; diff --git a/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp b/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp index 9a5fb81f..0fed2908 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp @@ -16,6 +16,7 @@ #include "sqlite_utils.h" #include +#include #include #include #include @@ -27,6 +28,11 @@ #include #include #include +#if !defined(CROSS_PLATFORM) +#include +#include +#include "relational/relational_store_sqlite_ext.h" +#endif #include #include #include @@ -42,7 +48,6 @@ namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; - /* A continuous number must contain at least eight digits, because the employee ID has eight digits, and the mobile phone number has 11 digits. The UUID is longer */ constexpr int32_t CONTINUOUS_DIGITS_MINI_SIZE = 6; @@ -54,9 +59,75 @@ constexpr int32_t DISPLAY_BYTE = 2; constexpr int32_t PREFIX_LENGTH = 3; constexpr int32_t FILE_MAX_SIZE = 20 * 1024; +constexpr int32_t HEAD_SIZE = 3; +constexpr int32_t END_SIZE = 3; +constexpr int32_t MIN_SIZE = HEAD_SIZE + END_SIZE + 3; +constexpr const char *REPLACE_CHAIN = "***"; +constexpr const unsigned char MAX_PRINTABLE_BYTE = 0x7F; + constexpr SqliteUtils::SqlType SqliteUtils::SQL_TYPE_MAP[]; constexpr const char *SqliteUtils::ON_CONFLICT_CLAUSE[]; +constexpr const char *SQL_KEYWORD[] = { "ABORT", "ABS", "ACTION", "ADD", "AFTER", "ALIAS", "ALL", "ALTER", "ALWAYS", + "AMBIGUOUS", "ANALYZE", "AND", "AS", "ASC", "ATTACH", "AUTOINCREMENT", "AVG", "BEFORE", "BEGIN", "BETWEEN", "BIG", + "BIGINT", "BLOB", "BOOLEAN", "BY", "CASCADE", "CASE", "CAST", "CEIL", "CEILING", "CHARACTER", "CHECK", "CLOB", + "COALESCE", "COLLATE", "COLUMN", "COMMIT", "CONCAT", "CONFLICT", "CONSTRAINT", "COUNT", "CREATE", "CROSS", + "CURRENT", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DATE", "DATETIME", "DECIMAL", + "DEFAULT", "DEFERRABLE", "DEFERRED", "DELETE", "DESC", "DETACH", "DIGIT", "DISTINCT", "DO", "DOUBLE", "DROP", "E", + "EACH", "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUDE", "EXCLUSIVE", "EXISTS", "EXP", "EXPLAIN", "EXPR", "FAIL", + "FALSE", "FILENAME", "FILTER", "FIRST", "FLOAT", "FLOOR", "FOLLOWING", "FOR", "FOREIGN", "FROM", "FULL", + "GENERATED", "GLOB", "GROUP", "GROUPS", "GROUP_CONCAT", "HAVING", "HEXDIGIT", "IF", "IFNULL", "IGNORE", "IMMEDIATE", + "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", "INSERT", "INSTEAD", "INSTR", "INT", "INT2", "INT8", "INTEGER", + "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "JULIANDAY", "KEY", "LAST", "LEFT", "LENGTH", "LIKE", "LIMIT", "LN", + "LOG", "LOWER", "LTRIM", "MATCH", "MATERIALIZED", "MAX", "MEDIUMINT", "MIN", "NAME", "NATIVE", "NATURAL", "NCHAR", + "NEWLINE", "NO", "NOT", "NOTHING", "NOTNULL", "NULL", "NULLIF", "NULLS", "NUMERIC", "NVARCHAR", "OF", "OFFSET", + "ON", "OR", "ORDER", "OTHERS", "OUTER", "OVER", "PARTITION", "PLAN", "POWER", "PRAGMA", "PRECEDING", "PRECISION", + "PRIMARY", "QUERY", "RAISE", "RANDOM", "RANGE", "REAL", "RECURSIVE", "REFERENCES", "REGEXP", "REINDEX", "RELEASE", + "RENAME", "REPLACE", "RESTRICT", "RETURNING", "RIGHT", "ROLLBACK", "ROUND", "ROW", "ROWID", "ROWS", "RTRIM", + "SAVEPOINT", "SELECT", "SET", "SMALLINT", "SQRT", "STORED", "STRFTIME", "STRICT", "SUBSTR", "SUM", "TABLE", "TEMP", + "TEMPORARY", "TEXT", "THEN", "TIES", "TIME", "TINYINT", "TO", "TOTAL", "TRANSACTION", "TRIGGER", "TRIM", "TRUE", + "TYPEOF", "UNBOUNDED", "UNION", "UNIQUE", "UNSIGNED", "UPDATE", "UPPER", "USING", "VACUUM", "VALUES", "VARCHAR", + "VARYING", "VIEW", "VIRTUAL", "WHEN", "WHERE", "WINDOW", "WITH", "WITHOUT" }; + +constexpr const char *WHILE_KEYWORDS[] = { "ABORTS", "ACQLOCK", "ALREADY", "AT", "BUSYLINE", "CHANGED", "CURLOCK", + "DBREF", "DEL", "DUPLICATE", "ENABLE", "ERRNO", "ERROR", "FAILED", "FD", "FILE", "FILELOCK", "FRAMES", "F_RDLCK", + "F_WRLCK", "GO", "HANDLELOCKS", "HAS", "IDX", "LEN", "LINE", "LITERAL", "LOCKCNT", "LOCKS", "MISUSE", "MONITOR", + "NEAR", "NONE", "PID", "PROCESSLOCK", "QUOTED", "READ", "RECOVERED", "SCHEMA", "SHARED_FIRST", "SQLITE", + "STATEMENT", "STRING", "SUCH", "SYNTAX", "TID", "TRX", "TYPE", "WAL", "WAL_DMS", "WARNING", "WRITE", "WRONG" }; + +constexpr int32_t WordCompare(const char *a, const char *b) +{ + while (*a && *b && (*a == *b)) { + ++a; + ++b; + } + return static_cast(*a) - static_cast(*b); +} + +constexpr bool IsLexSorted(const char *const *keyword, size_t size) +{ + for (size_t i = 1; i < size; ++i) { + if (WordCompare(keyword[i - 1], keyword[i]) >= 0) { + return false; + } + } + return true; +} + +bool IsMatchKeyword(const char *const *keyword, size_t size, const char *str) +{ + auto it = std::lower_bound( + keyword, keyword + size, str, [](const char *a, const char *b) { return WordCompare(a, b) < 0; }); + if (it != keyword + size && WordCompare(*it, str) == 0) { + return true; + } + return false; +} + +// ensure lexicographical order +static_assert(IsLexSorted(SQL_KEYWORD, sizeof(SQL_KEYWORD) / sizeof(char*))); +static_assert(IsLexSorted(WHILE_KEYWORDS, sizeof(WHILE_KEYWORDS) / sizeof(char*))); + int SqliteUtils::GetSqlStatementType(const std::string &sql) { /* the sql string length less than 3 can not be any type sql */ @@ -89,16 +160,18 @@ std::string SqliteUtils::StrToUpper(const std::string &s) return str; } -void SqliteUtils::Replace(std::string &src, const std::string &rep, const std::string &dst) +std::string SqliteUtils::Replace(const std::string &src, const std::string &rep, const std::string &dst) { if (src.empty() || rep.empty()) { - return; + return ""; } + auto res = src; size_t pos = 0; - while ((pos = src.find(rep, pos)) != std::string::npos) { - src.replace(pos, rep.length(), dst); + while ((pos = res.find(rep, pos)) != std::string::npos) { + res.replace(pos, rep.length(), dst); pos += dst.length(); } + return res; } bool SqliteUtils::IsSupportSqlForExecute(int sqlType) @@ -172,53 +245,55 @@ bool SqliteUtils::CopyFile(const std::string &srcFile, const std::string &destFi return true; } +size_t SqliteUtils::DeleteFolder(const std::string &folderPath) +{ +#if !defined(CROSS_PLATFORM) + std::error_code ec; + size_t count = std::filesystem::remove_all(folderPath, ec); + auto errorCount = static_cast(-1); + if (count == errorCount) { + LOG_WARN("remove folder, %{public}d, %{public}s, %{public}s", ec.value(), + ec.message().c_str(), Anonymous(folderPath).c_str()); + count = 0; + } + return count; +#else + return 0; +#endif +} + +bool SqliteUtils::IsKeyword(const std::string &word) +{ + return IsMatchKeyword(SQL_KEYWORD, sizeof(SQL_KEYWORD) / sizeof(char *), StrToUpper(word).c_str()) || + IsMatchKeyword(WHILE_KEYWORDS, sizeof(WHILE_KEYWORDS) / sizeof(char *), StrToUpper(word).c_str()); +} + std::string SqliteUtils::GetAnonymousName(const std::string &fileName) { - std::vector alnum; - std::vector noAlnum; - std::string alnumStr; - std::string noAlnumStr; - for (const auto &letter : fileName) { - if (isxdigit(letter)) { - if (!noAlnumStr.empty()) { - noAlnum.push_back(noAlnumStr); - noAlnumStr.clear(); - alnum.push_back(""); - } - alnumStr += letter; - } else { - if (!alnumStr.empty()) { - alnum.push_back(alnumStr); - alnumStr.clear(); - noAlnum.push_back(""); - } - noAlnumStr += letter; - } - } - if (!alnumStr.empty()) { - alnum.push_back(alnumStr); - noAlnum.push_back(""); + if (fileName.empty()) { + return ""; } - if (!noAlnumStr.empty()) { - noAlnum.push_back(noAlnumStr); - alnum.push_back(""); + + if (fileName.length() <= HEAD_SIZE) { + return fileName.substr(0, 1) + "**"; } - std::string res = ""; - for (size_t i = 0; i < alnum.size(); ++i) { - res += (AnonyDigits(alnum[i]) + noAlnum[i]); + + if (fileName.length() < MIN_SIZE) { + return (fileName.substr(0, HEAD_SIZE) + REPLACE_CHAIN); } - return res; + + return (fileName.substr(0, HEAD_SIZE) + REPLACE_CHAIN + fileName.substr(fileName.length() - END_SIZE, END_SIZE)); } -std::string SqliteUtils::AnonyDigits(const std::string &fileName) +std::string SqliteUtils::AnonymousDigits(const std::string &digits) { - std::string::size_type digitsNum = fileName.size(); + std::string::size_type digitsNum = digits.size(); if (digitsNum < CONTINUOUS_DIGITS_MINI_SIZE) { - return fileName; + return digits; } std::string::size_type endDigitsNum = 4; std::string::size_type shortEndDigitsNum = 3; - std::string name = fileName; + std::string name = digits; std::string last = ""; if (digitsNum == CONTINUOUS_DIGITS_MINI_SIZE) { last = name.substr(name.size() - shortEndDigitsNum); @@ -228,6 +303,53 @@ std::string SqliteUtils::AnonyDigits(const std::string &fileName) return "***" + last; } +std::string ByteAnonymous(const std::string &input) +{ + std::string output; + bool maskCurrent = false; + for (unsigned char byte : input) { + if (byte > MAX_PRINTABLE_BYTE) { + if (!maskCurrent) { + output += "***"; + maskCurrent = true; + } + } else { + output.push_back(static_cast(byte)); + maskCurrent = false; + } + } + return output; +} + +std::string SqliteUtils::SqlAnonymous(const std::string &sql) +{ + std::ostringstream result; + std::regex idRegex(R"(\b[a-zA-Z0-9_]+\b)"); + auto begin = std::sregex_iterator(sql.begin(), sql.end(), idRegex); + auto end = std::sregex_iterator(); + + size_t lastPos = 0; + for (auto it = begin; it != end; ++it) { + std::smatch match = *it; + std::string word = match.str(); + size_t pos = static_cast(match.position()); + + result << ByteAnonymous(sql.substr(lastPos, pos - lastPos)); + + lastPos = pos + word.length(); + if (std::regex_match(word, std::regex(R"(\b[0-9a-fA-F]+\b)"))) { + result << AnonymousDigits(word); + } else if (IsKeyword(word)) { + result << std::move(word); + } else { + result << GetAnonymousName(word); + } + } + + result << ByteAnonymous(sql.substr(lastPos)); + return result.str(); +} + std::string SqliteUtils::Anonymous(const std::string &srcFile) { auto pre = srcFile.find("/"); @@ -244,9 +366,22 @@ std::string SqliteUtils::Anonymous(const std::string &srcFile) } else { path = path.substr(area, AREA_MINI_SIZE); } - std::string fileName = srcFile.substr(end); // rdb file name + std::string fileName = srcFile.substr(end + 1); // rdb file name fileName = GetAnonymousName(fileName); - return srcFile.substr(0, pre + PRE_OFFSET_SIZE) + "***" + path + fileName; + return srcFile.substr(0, pre + PRE_OFFSET_SIZE) + "***" + path + "/" + fileName; +} + +std::string SqliteUtils::GetArea(const std::string &srcFile) +{ + size_t start = srcFile.find("/el"); + if (start == std::string::npos) { + return ""; + } + size_t end = srcFile.find("/", start + 1); + if (end != std::string::npos) { + return srcFile.substr(start + 1, end - start - 1); + } + return ""; } ssize_t SqliteUtils::GetFileSize(const std::string &fileName) @@ -361,6 +496,77 @@ bool SqliteUtils::IsSlaveInterrupted(const std::string &dbPath) return access((dbPath + SLAVE_INTERRUPT).c_str(), F_OK) == 0; } +int SqliteUtils::GetPageCountCallback(void *data, int argc, char **argv, char **azColName) +{ + int64_t *count = (int64_t *)data; + if (argc > 0 && argv[0] != NULL) { + char *endptr = nullptr; + *count = static_cast(strtoll(argv[0], &endptr, 10)); // 10 means decimal + } + return 0; +} + +ssize_t SqliteUtils::GetDecompressedSize(const std::string &dbPath) +{ + sqlite3 *dbHandle = nullptr; + int errCode = sqlite3_open_v2(dbPath.c_str(), &dbHandle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_FULLMUTEX, nullptr); + if (errCode != SQLITE_OK) { + LOG_WARN("failed to open %{public}s to calculate size", Anonymous(dbPath).c_str()); + sqlite3_close_v2(dbHandle); + return 0; + } + int64_t pageCount = 0; + errCode = sqlite3_exec(dbHandle, "SELECT COUNT(1) FROM vfs_pages;", GetPageCountCallback, &pageCount, nullptr); + sqlite3_close_v2(dbHandle); + if (errCode != SQLITE_OK) { + LOG_WARN("failed to get page count, %{public}s", Anonymous(dbPath).c_str()); + return 0; + } + auto size = pageCount * 4096; + if (size > SSIZE_MAX) { + LOG_WARN("actual size overflow:%{public}" PRId64, size); + return SSIZE_MAX; + } + return (ssize_t)size; +} + +bool SqliteUtils::IsSlaveLarge(const std::string &dbPath) +{ + auto slavePath = GetSlavePath(dbPath); + if (sqlite3_is_support_binlog(StringUtils::ExtractFileName(dbPath).c_str()) == SQLITE_OK) { + auto size = GetDecompressedSize(slavePath); + if (size > 0) { + return size > SLAVE_ASYNC_REPAIR_CHECK_LIMIT; + } + } + std::pair fileInfo = Stat(slavePath); + if (fileInfo.first == E_OK) { + return fileInfo.second.size_ > SLAVE_ASYNC_REPAIR_CHECK_LIMIT; + } + return false; +} + +int SqliteUtils::SetSlaveRestoring(const std::string &dbPath, bool isRestore) +{ + if (IsSlaveRestoring(dbPath)) { + if (!isRestore) { + std::remove((dbPath + SLAVE_RESTORE).c_str()); + } + return E_OK; + } + std::ofstream src((dbPath + SLAVE_RESTORE).c_str(), std::ios::binary); + if (src.is_open()) { + src.close(); + return E_OK; + } + return E_ERROR; +} + +bool SqliteUtils::IsSlaveRestoring(const std::string &dbPath) +{ + return access((dbPath + SLAVE_RESTORE).c_str(), F_OK) == 0; +} + void SqliteUtils::SetSlaveValid(const std::string &dbPath) { std::remove((dbPath + SLAVE_INTERRUPT).c_str()); @@ -419,13 +625,12 @@ std::string SqliteUtils::ReadFileHeader(const std::string &filePath) std::string SqliteUtils::GetFileStatInfo(const DebugInfo &debugInfo) { std::stringstream oss; - const uint32_t permission = 0777; oss << " dev:0x" << std::hex << debugInfo.dev_ << " ino:0x" << std::hex << debugInfo.inode_; if (debugInfo.inode_ != debugInfo.oldInode_ && debugInfo.oldInode_ != 0) { oss << "<>0x" << std::hex << debugInfo.oldInode_; } - oss << " mode:0" << std::oct << (debugInfo.mode_ & permission) << " size:" << std::dec << debugInfo.size_ - << " uid:" << std::dec << debugInfo.uid_ << " gid:" << std::dec << debugInfo.gid_ + oss << " " << GetModeInfo(debugInfo.mode_) << " size:" << std::dec << debugInfo.size_ << " uid:" << std::dec + << debugInfo.uid_ << " gid:" << std::dec << debugInfo.gid_ << " atim:" << RdbTimeUtils::GetTimeWithMs(debugInfo.atime_.sec_, debugInfo.atime_.nsec_) << " mtim:" << RdbTimeUtils::GetTimeWithMs(debugInfo.mtime_.sec_, debugInfo.mtime_.nsec_) << " ctim:" << RdbTimeUtils::GetTimeWithMs(debugInfo.ctime_.sec_, debugInfo.ctime_.nsec_); @@ -573,7 +778,8 @@ std::string SqliteUtils::FormatDebugInfoBrief(const std::map"; + oss << "<" << name << ",0x" << std::hex << debugInfo.inode_ << "," << std::dec << debugInfo.size_ << "," + << std::oct << debugInfo.mode_ << ">"; } return oss.str(); } @@ -583,5 +789,46 @@ std::string SqliteUtils::FormatDfxInfo(const DfxInfo &dfxInfo) oss << "LastOpen:" << dfxInfo.lastOpenTime_ << "," << "CUR_USER:" << dfxInfo.curUserId_; return oss.str(); } + +std::string SqliteUtils::GetModeInfo(uint32_t st_mode) +{ + std::ostringstream oss; + const uint32_t permission = 0777; + oss << "mode:"; + if (S_ISDIR(st_mode)) + oss << 'd'; + else + oss << '-'; + + oss << std::setw(PREFIX_LENGTH) << std::setfill('0') << std::oct << (st_mode & permission); + + return oss.str(); +} + +std::string SqliteUtils::GetParentModes(const std::string &path, int pathDepth) +{ + std::vector> dirModes; + std::string currentPath = path; + + for (int i = 0; i < pathDepth; ++i) { + currentPath = StringUtils::GetParentPath(currentPath); + if (currentPath == "/" || currentPath.empty()) { + break; + } + + std::string dirName = StringUtils::ExtractFileName(currentPath); + struct stat st {}; + dirModes.emplace_back(dirName, (stat(currentPath.c_str(), &st) == 0) ? GetModeInfo(st.st_mode) : "access_fail"); + } + std::string result; + for (auto it = dirModes.rbegin(); it != dirModes.rend(); ++it) { + if (!result.empty()) { + result += " <- "; + } + result += (it->first.size() > PREFIX_LENGTH ? it->first.substr(0, PREFIX_LENGTH) + "***" : it->first) + ":" + + it->second; + } + return result.empty() ? "no_parent" : result; +} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/step_result_set.cpp b/relational_store/frameworks/native/rdb/src/step_result_set.cpp index 32161b43..520d6a20 100644 --- a/relational_store/frameworks/native/rdb/src/step_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/step_result_set.cpp @@ -67,7 +67,7 @@ StepResultSet::StepResultSet(Time start, Conn conn, const std::string &sql, cons int64_t countCost = std::chrono::duration_cast(queryEnd - prepareEnd).count(); LOG_WARN("total[%{public}" PRId64 "]<%{public}" PRId64 ",%{public}" PRId64 ",%{public}" PRId64 "> count[%{public}d] sql[%{public}s]", - totalCost, acquireCost, prepareCost, countCost, rowCount_, SqliteUtils::Anonymous(sql_).c_str()); + totalCost, acquireCost, prepareCost, countCost, rowCount_, SqliteUtils::SqlAnonymous(sql_).c_str()); } } @@ -93,7 +93,7 @@ int StepResultSet::PrepareStep() auto type = SqliteUtils::GetSqlStatementType(sql_); if (type == SqliteUtils::STATEMENT_ERROR) { - LOG_ERROR("invalid sql_ %{public}s!", SqliteUtils::Anonymous(sql_).c_str()); + LOG_ERROR("invalid sql_ %{public}s!", SqliteUtils::SqlAnonymous(sql_).c_str()); lastErr_ = E_INVALID_ARGS; return lastErr_; } @@ -101,11 +101,12 @@ int StepResultSet::PrepareStep() auto [errCode, statement] = conn_->CreateStatement(sql_, conn_); if (statement == nullptr || errCode != E_OK) { lastErr_ = errCode; + LOG_ERROR("CreateStatement failed. sql_ %{public}s!", SqliteUtils::SqlAnonymous(sql_).c_str()); return E_STATEMENT_NOT_PREPARED; } if (!statement->ReadOnly()) { - LOG_ERROR("failed, %{public}s is not query sql!", SqliteUtils::Anonymous(sql_).c_str()); + LOG_ERROR("failed, %{public}s is not query sql!", SqliteUtils::SqlAnonymous(sql_).c_str()); lastErr_ = E_NOT_SELECT; return lastErr_; } diff --git a/relational_store/frameworks/native/rdb/src/string_utils.cpp b/relational_store/frameworks/native/rdb/src/string_utils.cpp index 27ebb660..7e527910 100644 --- a/relational_store/frameworks/native/rdb/src/string_utils.cpp +++ b/relational_store/frameworks/native/rdb/src/string_utils.cpp @@ -70,13 +70,29 @@ std::string StringUtils::ExtractFileName(const std::string &fileFullName) return std::string(fileFullName).substr(fileFullName.rfind("/") + 1, fileFullName.size()); } -std::string StringUtils::TruncateAfterFirstParen(const std::string& str) +std::string StringUtils::TruncateAfterFirstParen(const std::string &str) { size_t pos = str.find('('); return (pos != std::string::npos) ? str.substr(0, pos) : str; } -StringUtils::StringUtils() {} -StringUtils::~StringUtils() {} +std::string StringUtils::GetParentPath(const std::string &path) +{ + size_t pos = path.find_last_of("/\\"); + if (pos == std::string::npos) { + return ""; + } + if (pos == 0) { + return "/"; + } + return path.substr(0, pos); +} + +StringUtils::StringUtils() +{ +} +StringUtils::~StringUtils() +{ +} } // namespace NativeRdb } // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/src/entry_point.cpp b/relational_store/frameworks/native/rdb/src/suspender.cpp similarity index 37% rename from relational_store/frameworks/js/napi/graphstore/src/entry_point.cpp rename to relational_store/frameworks/native/rdb/src/suspender.cpp index 18d4d98e..cfc9ae59 100644 --- a/relational_store/frameworks/js/napi/graphstore/src/entry_point.cpp +++ b/relational_store/frameworks/native/rdb/src/suspender.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2024 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 @@ -12,43 +12,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "napi/native_api.h" -#include "napi_gdb_const_properties.h" -#include "napi_gdb_store.h" -#include "napi_gdb_store_helper.h" -#include "napi_gdb_transaction.h" -using namespace OHOS::GraphStoreJsKit; +#define LOG_TAG "Suspender" +#include "suspender.h" +#include "rdb_sql_log.h" +#include "rdb_perfStat.h" -EXTERN_C_START -/* - * function for module exports - */ -static napi_value Init(napi_env env, napi_value exports) +namespace OHOS::NativeRdb { +Suspender::Suspender(Flag flag) : flag_(flag) { - InitGdbHelper(env, exports); - GdbStoreProxy::Init(env, exports); - GdbTransactionProxy::Init(env, exports); - InitConstProperties(env, exports); - return exports; + if ((flag_ & SQL_STATISTIC) != 0) { + DistributedRdb::PerfStat::Pause(); + } + if ((flag_ & SQL_LOG) != 0) { + SqlLog::Pause(); + } } -EXTERN_C_END - -/* - * Module define - */ -static napi_module _module = { .nm_version = 1, - .nm_flags = 0, - .nm_filename = nullptr, - .nm_register_func = Init, - .nm_modname = "data.graphStore", - .nm_priv = ((void *)0), - .reserved = { 0 } }; - -/* - * Module register function - */ -static __attribute__((constructor)) void RegisterModule(void) +Suspender::~Suspender() { - napi_module_register(&_module); -} \ No newline at end of file + if ((flag_ & SQL_STATISTIC) != 0) { + DistributedRdb::PerfStat::Resume(); + } + if ((flag_ & SQL_LOG) != 0) { + SqlLog::Resume(); + } +} +} // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/task_executor.cpp b/relational_store/frameworks/native/rdb/src/task_executor.cpp index 888169cf..102406ef 100644 --- a/relational_store/frameworks/native/rdb/src/task_executor.cpp +++ b/relational_store/frameworks/native/rdb/src/task_executor.cpp @@ -13,12 +13,15 @@ * limitations under the License. */ +#define LOG_TAG "TaskExecutor" #include "task_executor.h" +#include "logger.h" + namespace OHOS::NativeRdb { +using namespace OHOS::Rdb; TaskExecutor::TaskExecutor() { - pool_ = std::make_shared(MAX_THREADS, MIN_THREADS); } TaskExecutor::~TaskExecutor() @@ -32,16 +35,39 @@ TaskExecutor &TaskExecutor::GetInstance() return instance; } +void TaskExecutor::Init() +{ + std::unique_lock lock(mutex_); + if (pool_ != nullptr) { + return; + } + pool_ = std::make_shared(MAX_THREADS, MIN_THREADS, "TaskExecutorRDB"); +}; + std::shared_ptr TaskExecutor::GetExecutor() { - std::shared_lock lock(rwMutex_); + std::unique_lock lock(mutex_); + if (pool_ == nullptr) { + pool_ = std::make_shared(MAX_THREADS, MIN_THREADS, "TaskExecutorRDB"); + } return pool_; } void TaskExecutor::SetExecutor(std::shared_ptr executor) { - std::unique_lock lock(rwMutex_); + std::unique_lock lock(mutex_); pool_ = executor; -}; +} + +bool TaskExecutor::Stop() +{ + std::unique_lock lock(mutex_); + if (pool_ != nullptr && pool_.use_count() > 1) { + LOG_WARN("There are other threads using the thread pool. count:%{public}ld", pool_.use_count()); + return false; + } + pool_ = nullptr; + return true; +} } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/trans_db.cpp b/relational_store/frameworks/native/rdb/src/trans_db.cpp index b7cb37a8..7751d319 100644 --- a/relational_store/frameworks/native/rdb/src/trans_db.cpp +++ b/relational_store/frameworks/native/rdb/src/trans_db.cpp @@ -15,6 +15,7 @@ #define LOG_TAG "TransDB" #include "trans_db.h" +#include "cache_result_set.h" #include "logger.h" #include "rdb_sql_statistic.h" #include "rdb_trace.h" @@ -27,7 +28,7 @@ namespace OHOS::NativeRdb { using namespace OHOS::Rdb; using namespace DistributedRdb; -TransDB::TransDB(std::shared_ptr conn, const std::string &name) : conn_(conn), name_(name) +TransDB::TransDB(std::shared_ptr conn, const std::string &path) : conn_(conn), path_(path) { maxArgs_ = conn->GetMaxVariable(); } @@ -82,7 +83,8 @@ std::pair TransDB::BatchInsert(const std::string &table, const Ref auto batchInfo = SqliteSqlBuilder::GenerateSqls(table, rows, maxArgs_); if (table.empty() || batchInfo.empty()) { - LOG_ERROR("empty,table=%{public}s,rows:%{public}zu,max:%{public}d.", table.c_str(), rows.RowSize(), maxArgs_); + LOG_ERROR("empty,table=%{public}s,rows:%{public}zu,max:%{public}d.", SqliteUtils::Anonymous(table).c_str(), + rows.RowSize(), maxArgs_); return { E_INVALID_ARGS, -1 }; } @@ -97,15 +99,15 @@ std::pair TransDB::BatchInsert(const std::string &table, const Ref continue; } LOG_ERROR("failed(0x%{public}x) db:%{public}s table:%{public}s args:%{public}zu", errCode, - SqliteUtils::Anonymous(name_).c_str(), table.c_str(), args.size()); + SqliteUtils::Anonymous(path_).c_str(), SqliteUtils::Anonymous(table).c_str(), args.size()); return { errCode, -1 }; } } return { E_OK, int64_t(rows.RowSize()) }; } -std::pair TransDB::BatchInsertWithConflictResolution( - const std::string &table, const ValuesBuckets &rows, Resolution resolution) +std::pair TransDB::BatchInsert(const std::string &table, const ValuesBuckets &rows, + const std::vector &returningFields, Resolution resolution) { if (rows.RowSize() == 0) { return { E_OK, 0 }; @@ -115,31 +117,32 @@ std::pair TransDB::BatchInsertWithConflictResolution( if (sqlArgs.size() != 1 || sqlArgs.front().second.size() != 1) { auto [fields, values] = rows.GetFieldsAndValues(); LOG_ERROR("invalid args, table=%{public}s, rows:%{public}zu, fields:%{public}zu, max:%{public}d.", - table.c_str(), rows.RowSize(), fields != nullptr ? fields->size() : 0, maxArgs_); + SqliteUtils::Anonymous(table).c_str(), rows.RowSize(), fields != nullptr ? fields->size() : 0, maxArgs_); return { E_INVALID_ARGS, -1 }; } auto &[sql, bindArgs] = sqlArgs.front(); + SqliteSqlBuilder::AppendReturning(sql, returningFields); auto [errCode, statement] = GetStatement(sql); if (statement == nullptr) { LOG_ERROR("statement is nullptr, errCode:0x%{public}x, args:%{public}zu, table:%{public}s.", errCode, - bindArgs.size(), table.c_str()); + bindArgs.size(), SqliteUtils::Anonymous(table).c_str()); return { errCode, -1 }; } auto args = std::ref(bindArgs.front()); errCode = statement->Execute(args); if (errCode != E_OK) { LOG_ERROR("failed,errCode:%{public}d,table:%{public}s,args:%{public}zu,resolution:%{public}d.", errCode, - table.c_str(), args.get().size(), static_cast(resolution)); - return { errCode, errCode == E_SQLITE_CONSTRAINT ? int64_t(statement->Changes()) : -1 }; + SqliteUtils::Anonymous(table).c_str(), args.get().size(), static_cast(resolution)); } - return { E_OK, int64_t(statement->Changes()) }; + return { errCode, GenerateResult(errCode, statement) }; } -std::pair TransDB::Update( - const std::string &table, const Row &row, const std::string &where, const Values &args, Resolution resolution) +std::pair TransDB::Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); auto clause = SqliteUtils::GetConflictClause(static_cast(resolution)); + auto table = predicates.GetTableName(); if (table.empty() || row.IsEmpty() || clause == nullptr) { return { E_INVALID_ARGS, 0 }; } @@ -147,6 +150,7 @@ std::pair TransDB::Update( std::string sql("UPDATE"); sql.append(clause).append(" ").append(table).append(" SET "); std::vector totalArgs; + auto args = predicates.GetBindArgs(); totalArgs.reserve(row.values_.size() + args.size()); const char *split = ""; for (auto &[key, val] : row.values_) { @@ -161,53 +165,58 @@ std::pair TransDB::Update( totalArgs.push_back(val); split = ","; } - + auto where = predicates.GetWhereClause(); if (!where.empty()) { sql.append(" WHERE ").append(where); } - + SqliteSqlBuilder::AppendReturning(sql, returningFields); totalArgs.insert(totalArgs.end(), args.begin(), args.end()); auto [errCode, statement] = GetStatement(sql); - if (statement == nullptr) { - return { errCode, 0 }; + if (errCode != E_OK || statement == nullptr) { + return { errCode != E_OK ? errCode : E_ERROR, -1 }; } errCode = statement->Execute(totalArgs); if (errCode != E_OK) { - return { errCode, 0 }; + LOG_ERROR("failed,errCode:%{public}d,table:%{public}s,returningFields:%{public}zu,resolution:%{public}d.", + errCode, SqliteUtils::Anonymous(table).c_str(), returningFields.size(), static_cast(resolution)); } - return { errCode, int32_t(statement->Changes()) }; + return { errCode, GenerateResult(errCode, statement) }; } -int TransDB::Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) +std::pair TransDB::Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + auto table = predicates.GetTableName(); if (table.empty()) { - return E_INVALID_ARGS; + return { E_INVALID_ARGS, -1 }; } std::string sql; sql.append("DELETE FROM ").append(table); + auto whereClause = predicates.GetWhereClause(); if (!whereClause.empty()) { sql.append(" WHERE ").append(whereClause); } + SqliteSqlBuilder::AppendReturning(sql, returningFields); auto [errCode, statement] = GetStatement(sql); - if (statement == nullptr) { - return errCode; + if (errCode != E_OK || statement == nullptr) { + return { errCode != E_OK ? errCode : E_ERROR, -1 }; } - errCode = statement->Execute(args); + errCode = statement->Execute(predicates.GetBindArgs()); if (errCode != E_OK) { - return errCode; + LOG_ERROR("failed,errCode:%{public}d,table:%{public}s,returningFields:%{public}zu.", errCode, + SqliteUtils::Anonymous(table).c_str(), returningFields.size()); } - deletedRows = statement->Changes(); - return E_OK; + return { errCode, GenerateResult(errCode, statement) }; } std::shared_ptr TransDB::QuerySql(const std::string &sql, const Values &args) { #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) auto start = std::chrono::steady_clock::now(); - return std::make_shared(start, conn_.lock(), sql, args, name_); + return std::make_shared(start, conn_.lock(), sql, args, path_); #else (void)sql; (void)args; @@ -227,7 +236,7 @@ std::pair TransDB::Execute(const std::string &sql, const V ValueObject object; int sqlType = SqliteUtils::GetSqlStatementType(sql); if (!SqliteUtils::IsSupportSqlForExecute(sqlType) && !SqliteUtils::IsSpecial(sqlType)) { - LOG_ERROR("Not support the sql:app self can check the SQL"); + LOG_ERROR("Not support the sql:app self can check the SQL, sqlType:%{public}d", sqlType); return { E_INVALID_ARGS, object }; } @@ -259,19 +268,53 @@ std::pair TransDB::Execute(const std::string &sql, const V } if (sqlType == SqliteUtils::STATEMENT_DDL) { - statement->Reset(); - statement->Prepare("PRAGMA schema_version"); - auto [err, version] = statement->ExecuteForValue(); - if (vSchema_ < static_cast(version)) { - LOG_INFO("db:%{public}s exe DDL schema<%{public}" PRIi64 "->%{public}" PRIi64 - "> app self can check the SQL.", - SqliteUtils::Anonymous(name_).c_str(), vSchema_, static_cast(version)); - vSchema_ = version; - } + HandleSchemaDDL(statement); } return { errCode, object }; } +std::pair TransDB::ExecuteExt(const std::string &sql, const Values &args) +{ + ValueObject object; + int sqlType = SqliteUtils::GetSqlStatementType(sql); + if (!SqliteUtils::IsSupportSqlForExecute(sqlType) && !SqliteUtils::IsSpecial(sqlType)) { + LOG_ERROR("Not support the sql:app self can check the SQL"); + return { E_INVALID_ARGS, -1 }; + } + auto [errCode, statement] = GetStatement(sql); + if (errCode != E_OK || statement == nullptr) { + return { errCode != E_OK ? errCode : E_ERROR, -1 }; + } + + errCode = statement->Execute(args); + auto result = GenerateResult( + errCode, statement, sqlType == SqliteUtils::STATEMENT_INSERT || sqlType == SqliteUtils::STATEMENT_UPDATE); + if (errCode != E_OK) { + LOG_ERROR("failed,app self can check the SQL, error:0x%{public}x.", errCode); + return { errCode, result }; + } + + if (sqlType == SqliteUtils::STATEMENT_DDL) { + HandleSchemaDDL(statement); + } + return { errCode, result }; +} + +void TransDB::HandleSchemaDDL(std::shared_ptr statement) +{ + if (statement == nullptr) { + return; + } + statement->Reset(); + statement->Prepare("PRAGMA schema_version"); + auto [err, version] = statement->ExecuteForValue(); + if (vSchema_ < static_cast(version)) { + LOG_INFO("db:%{public}s exe DDL schema<%{public}" PRIi64 "->%{public}" PRIi64 ">", + SqliteUtils::Anonymous(path_).c_str(), vSchema_, static_cast(version)); + vSchema_ = version; + } +} + int TransDB::GetVersion(int &version) { return E_NOT_SUPPORT; @@ -298,4 +341,40 @@ std::pair> TransDB::GetStatement(const std:: } return connection->CreateStatement(sql, connection); } + +Results TransDB::GenerateResult(int32_t code, std::shared_ptr statement, bool isDML) +{ + Results result{ -1 }; + if (statement == nullptr) { + return result; + } + // There are no data changes in other scenarios + if (code == E_OK) { + result.results = GetValues(statement); + result.changed = isDML ? statement->Changes() : 0; + } + if (code == E_SQLITE_CONSTRAINT) { + result.changed = statement->Changes(); + } + if (isDML && result.changed <= 0) { + result.results = std::make_shared(); + } + return result; +} + +std::shared_ptr TransDB::GetValues(std::shared_ptr statement) +{ + if (statement == nullptr) { + return nullptr; + } + auto [code, rows] = statement->GetRows(MAX_RETURNING_ROWS); + auto size = rows.size(); + std::shared_ptr result = std::make_shared(std::move(rows)); + // The correct number of changed rows can only be obtained after completing the step + while (code == E_OK && size == MAX_RETURNING_ROWS) { + std::tie(code, rows) = statement->GetRows(MAX_RETURNING_ROWS); + size = rows.size(); + } + return result; +} } // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/transaction.cpp b/relational_store/frameworks/native/rdb/src/transaction.cpp index 420049c3..0b44cdc2 100644 --- a/relational_store/frameworks/native/rdb/src/transaction.cpp +++ b/relational_store/frameworks/native/rdb/src/transaction.cpp @@ -16,10 +16,10 @@ namespace OHOS::NativeRdb { std::pair> Transaction::Create( - int32_t type, std::shared_ptr connection, const std::string &name) + int32_t type, std::shared_ptr connection, const std::string &path) { if (creator_ != nullptr) { - return creator_(type, std::move(connection), name); + return creator_(type, std::move(connection), path); } return { E_ERROR, nullptr }; } @@ -29,4 +29,70 @@ int32_t Transaction::RegisterCreator(Creator creator) creator_ = std::move(creator); return E_OK; } + +std::pair Transaction::BatchInsert( + const std::string &table, const RefRows &rows, Resolution resolution) +{ + auto [code, result] = BatchInsert(table, rows, {}, resolution); + return { code, result.changed }; +} + +std::pair Transaction::BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution) +{ + return { E_NOT_SUPPORT, -1 }; +} + +std::pair Transaction::Update( + const std::string &table, const Row &row, const std::string &where, const Values &args, Resolution resolution) +{ + AbsRdbPredicates predicates(table); + predicates.SetWhereClause(where); + predicates.SetBindArgs(args); + return Update(row, predicates, resolution); +} + +std::pair Transaction::Update( + const Row &row, const AbsRdbPredicates &predicates, Resolution resolution) +{ + auto [code, result] = Update(row, predicates, {}, resolution); + return { code, result.changed }; +} + +std::pair Transaction::Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) +{ + return { E_NOT_SUPPORT, -1 }; +} + +std::pair Transaction::Delete( + const std::string &table, const std::string &whereClause, const Values &args) +{ + AbsRdbPredicates predicates(table); + predicates.SetWhereClause(whereClause); + predicates.SetBindArgs(args); + return Delete(predicates); +} + +std::pair Transaction::Delete(const AbsRdbPredicates &predicates) +{ + auto [code, result] = Delete(predicates, {}); + return { code, result.changed }; +} + +std::pair Transaction::Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) +{ + return { E_NOT_SUPPORT, -1 }; +} + +std::pair Transaction::Execute(const std::string &sql, const Values &args) +{ + return { E_NOT_SUPPORT, -1 }; +} + +std::pair Transaction::ExecuteExt(const std::string &sql, const Values &args) +{ + return { E_NOT_SUPPORT, -1 }; +} } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/transaction_impl.cpp b/relational_store/frameworks/native/rdb/src/transaction_impl.cpp index b9b7adc1..b2dfbde3 100644 --- a/relational_store/frameworks/native/rdb/src/transaction_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/transaction_impl.cpp @@ -21,16 +21,19 @@ #include "rdb_errno.h" #include "rdb_store.h" #include "trans_db.h" +#include "rdb_perfStat.h" using namespace OHOS::Rdb; namespace OHOS::NativeRdb { - +using PerfStat = DistributedRdb::PerfStat; __attribute__((used)) const int32_t TransactionImpl::regCreator_ = Transaction::RegisterCreator(TransactionImpl::Create); -TransactionImpl::TransactionImpl(std::shared_ptr connection, const std::string &name) - : name_(name), connection_(std::move(connection)) +TransactionImpl::TransactionImpl(std::shared_ptr connection, const std::string &path) + : path_(path), connection_(std::move(connection)) { + seqId_ = PerfStat::GenerateId(); + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS_START, seqId_); } TransactionImpl::~TransactionImpl() @@ -38,6 +41,7 @@ TransactionImpl::~TransactionImpl() // If the user does not commit the transaction, the next time using this connection to create the transaction will // fail. Here, we attempt to roll back during the transaction object decomposition to prevent this situation // from happening. + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS_END, seqId_); if (connection_ == nullptr) { return; } @@ -45,9 +49,9 @@ TransactionImpl::~TransactionImpl() } std::pair> TransactionImpl::Create( - int32_t type, std::shared_ptr connection, const std::string &name) + int32_t type, std::shared_ptr connection, const std::string &path) { - auto trans = std::make_shared(std::move(connection), name); + auto trans = std::make_shared(std::move(connection), path); if (trans == nullptr) { return { E_ERROR, nullptr }; } @@ -71,7 +75,7 @@ std::string TransactionImpl::GetBeginSql(int32_t type) int32_t TransactionImpl::Begin(int32_t type) { std::lock_guard lock(mutex_); - store_ = std::make_shared(connection_, name_); + store_ = std::make_shared(connection_, path_); if (store_ == nullptr) { return E_ERROR; } @@ -98,6 +102,7 @@ int32_t TransactionImpl::Begin(int32_t type) int32_t TransactionImpl::Commit() { std::lock_guard lock(mutex_); + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS_END, seqId_); if (connection_ == nullptr) { LOG_ERROR("connection already closed"); return E_ALREADY_CLOSED; @@ -112,8 +117,8 @@ int32_t TransactionImpl::Commit() errorCode = statement->Execute(); if (errorCode != E_OK) { - CloseInner(false); LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode); + CloseInner(false); return errorCode; } CloseInner(); @@ -123,6 +128,7 @@ int32_t TransactionImpl::Commit() int32_t TransactionImpl::Rollback() { std::lock_guard lock(mutex_); + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS_END, seqId_); if (connection_ == nullptr) { LOG_ERROR("connection already closed"); return E_ALREADY_CLOSED; @@ -137,8 +143,8 @@ int32_t TransactionImpl::Rollback() errorCode = statement->Execute(); if (errorCode != E_OK) { - CloseInner(false); LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode); + CloseInner(false); return errorCode; } CloseInner(); @@ -175,6 +181,7 @@ std::shared_ptr TransactionImpl::GetStore() std::pair TransactionImpl::Insert(const std::string &table, const Row &row, Resolution resolution) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); @@ -185,6 +192,7 @@ std::pair TransactionImpl::Insert(const std::string &table, const std::pair TransactionImpl::BatchInsert(const std::string &table, const Rows &rows) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_, rows.size()); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); @@ -197,6 +205,7 @@ std::pair TransactionImpl::BatchInsert(const std::string &tabl std::pair TransactionImpl::BatchInsert(const std::string &table, const RefRows &rows) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_, rows.RowSize()); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); @@ -205,63 +214,40 @@ std::pair TransactionImpl::BatchInsert(const std::string &table, c return store->BatchInsert(table, rows); } -std::pair TransactionImpl::BatchInsertWithConflictResolution( - const std::string &table, const RefRows &rows, Resolution resolution) +std::pair TransactionImpl::BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_, rows.RowSize()); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); return { E_ALREADY_CLOSED, -1 }; } - return store->BatchInsertWithConflictResolution(table, rows, resolution); + return store->BatchInsert(table, rows, returningFields, resolution); } -std::pair TransactionImpl::Update( - const std::string &table, const Row &row, const std::string &where, const Values &args, Resolution resolution) +std::pair TransactionImpl::Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); return { E_ALREADY_CLOSED, -1 }; } - return store->Update(table, row, where, args, resolution); + return store->Update(row, predicates, returningFields, resolution); } -std::pair TransactionImpl::Update( - const Row &row, const AbsRdbPredicates &predicates, Resolution resolution) +std::pair TransactionImpl::Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); return { E_ALREADY_CLOSED, -1 }; } - return store->Update( - predicates.GetTableName(), row, predicates.GetWhereClause(), predicates.GetBindArgs(), resolution); -} - -std::pair TransactionImpl::Delete( - const std::string &table, const std::string &whereClause, const Values &args) -{ - auto store = GetStore(); - if (store == nullptr) { - LOG_ERROR("transaction already close"); - return { E_ALREADY_CLOSED, -1 }; - } - int deletedRows{}; - auto errorCode = store->Delete(deletedRows, table, whereClause, args); - return { errorCode, deletedRows }; -} - -std::pair TransactionImpl::Delete(const AbsRdbPredicates &predicates) -{ - auto store = GetStore(); - if (store == nullptr) { - LOG_ERROR("transaction already close"); - return { E_ALREADY_CLOSED, -1 }; - } - int deletedRows{}; - auto errorCode = store->Delete(deletedRows, predicates); - return { errorCode, deletedRows }; + return store->Delete(predicates, returningFields); } void TransactionImpl::AddResultSet(std::weak_ptr resultSet) @@ -272,6 +258,7 @@ void TransactionImpl::AddResultSet(std::weak_ptr resultSet) std::shared_ptr TransactionImpl::QueryByStep(const std::string &sql, const Values &args, bool preCount) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); @@ -287,6 +274,7 @@ std::shared_ptr TransactionImpl::QueryByStep(const std::string &sql, std::shared_ptr TransactionImpl::QueryByStep( const AbsRdbPredicates &predicates, const Fields &columns, bool preCount) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); @@ -301,6 +289,7 @@ std::shared_ptr TransactionImpl::QueryByStep( std::pair TransactionImpl::Execute(const std::string &sql, const Values &args) { + PerfStat perfStat(path_, "", PerfStat::Step::STEP_TRANS, seqId_); auto store = GetStore(); if (store == nullptr) { LOG_ERROR("transaction already close"); @@ -308,4 +297,14 @@ std::pair TransactionImpl::Execute(const std::string &sql, } return store->Execute(sql, args); } + +std::pair TransactionImpl::ExecuteExt(const std::string &sql, const Values &args) +{ + auto store = GetStore(); + if (store == nullptr) { + LOG_ERROR("transaction already close"); + return { E_ALREADY_CLOSED, -1 }; + } + return store->ExecuteExt(sql, args); +} } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/values_bucket.cpp b/relational_store/frameworks/native/rdb/src/values_bucket.cpp index ae2f7d4b..41d68696 100644 --- a/relational_store/frameworks/native/rdb/src/values_bucket.cpp +++ b/relational_store/frameworks/native/rdb/src/values_bucket.cpp @@ -91,6 +91,11 @@ void ValuesBucket::Put(const std::string &columnName, const ValueObject &value) values_.insert_or_assign(columnName, value); } +void ValuesBucket::Put(const std::string &columnName, ValueObject &&value) +{ + values_.insert_or_assign(columnName, std::move(value)); +} + void ValuesBucket::Delete(const std::string &columnName) { values_.erase(columnName); diff --git a/relational_store/frameworks/native/rdb/src/values_buckets.cpp b/relational_store/frameworks/native/rdb/src/values_buckets.cpp index c04f5ae9..f226531f 100644 --- a/relational_store/frameworks/native/rdb/src/values_buckets.cpp +++ b/relational_store/frameworks/native/rdb/src/values_buckets.cpp @@ -24,6 +24,22 @@ ValuesBuckets::ValuesBuckets() values_ = std::make_shared>(); } +ValuesBuckets::ValuesBuckets(const std::vector &rows) : ValuesBuckets() +{ + buckets_.reserve(rows.size()); + for (const auto &bucket : rows) { + Put(bucket); + } +} + +ValuesBuckets::ValuesBuckets(std::vector &&rows) noexcept : ValuesBuckets() +{ + buckets_.reserve(rows.size()); + for (auto &bucket : rows) { + Put(std::move(bucket)); + } +} + size_t ValuesBuckets::RowSize() const { return buckets_.size(); @@ -34,6 +50,18 @@ std::pair ValuesBuckets::G return { fields_, values_ }; } +void ValuesBuckets::Reserve(int32_t size) +{ + buckets_.reserve(size); +} + +void ValuesBuckets::Clear() +{ + buckets_.clear(); + fields_->clear(); + values_->clear(); +} + void ValuesBuckets::Put(const ValuesBucket &bucket) { BucketType row; @@ -46,6 +74,18 @@ void ValuesBuckets::Put(const ValuesBucket &bucket) buckets_.push_back(std::move(row)); } +void ValuesBuckets::Put(ValuesBucket &&bucket) +{ + BucketType row; + for (auto &[field, value] : bucket.values_) { + auto fieldResult = fields_->insert(std::move(field)); + auto valueResult = values_->insert(std::move(value)); + row.insert(std::make_pair(std::ref(const_cast(*fieldResult.first)), + std::ref(const_cast(*valueResult.first)))); + } + buckets_.push_back(std::move(row)); +} + std::pair ValuesBuckets::Get(size_t row, const FieldType &field) const { ValueObject empty; diff --git a/relational_store/frameworks/native/rdb_crypt/BUILD.gn b/relational_store/frameworks/native/rdb_crypt/BUILD.gn new file mode 100644 index 00000000..543039d3 --- /dev/null +++ b/relational_store/frameworks/native/rdb_crypt/BUILD.gn @@ -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. +import("//build/ohos.gni") +import("//build/ohos/ace/ace.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +ohos_shared_library("relational_store_crypt") { +part_name = "relational_store" +sanitize = { + boundary_sanitize = true + ubsan = true + cfi = true + cfi_cross_dso = true + debug = false +} + +sources = [ + "${relational_store_native_path}/rdb_crypt/relational_store_crypt.cpp", +] +include_dirs = [ + "${relational_store_common_path}/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/rdb_crypt", + "${relational_store_native_path}/rdb/include", + "${relational_store_native_path}/dfx/include", +] +ldflags = [ "-Wl,--exclude-libs,ALL" ] +cflags_cc = [ "-fvisibility=hidden" ] + +external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "huks:libhukssdk", +] +subsystem_name = "distributeddatamgr" +} \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb_crypt/relational_store_crypt.cpp b/relational_store/frameworks/native/rdb_crypt/relational_store_crypt.cpp new file mode 100644 index 00000000..4aeabef4 --- /dev/null +++ b/relational_store/frameworks/native/rdb_crypt/relational_store_crypt.cpp @@ -0,0 +1,385 @@ +/* + * 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 "relational_store_crypt.h" +#define LOG_TAG "RDBCryptoFault" + +#include +#include +#include + +#include "rdb_dfx_errno.h" +#include "hks_api.h" +#include "hks_param.h" +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_visibility.h" + +using RDBCryptoFault = OHOS::NativeRdb::RDBCryptoFault; +using RdbSecretContent = OHOS::NativeRdb::RdbSecretContent; +namespace OHOS { +namespace NativeRdb { +class RDBCrypto { +public: + static int32_t CheckRootKeyExists(std::vector &rootKeyAlias); + static int32_t GenerateRootKey(const std::vector &rootKeyAlias, RDBCryptoFault &rdbFault); + static std::vector Encrypt(const RDBCryptoParam ¶m, RDBCryptoFault &rdbFault); + static std::vector Decrypt(const RDBCryptoParam ¶m, RDBCryptoFault &rdbFault); + static std::vector GenerateRandomNum(uint32_t len); +}; +} // namespace NativeRdb +} // namespace OHOS +API_EXPORT int32_t CheckRootKeyExists(std::vector &rootKeyAlias) asm("checkRootKeyExists"); +API_EXPORT int32_t GenerateRootKey(const std::vector &rootKeyAlias, RDBCryptoFault &rdbFault) asm( + "generateRootKey"); +API_EXPORT std::vector Encrypt(const OHOS::NativeRdb::RDBCryptoParam ¶m, RDBCryptoFault &rdbFault) asm( + "encrypt"); +API_EXPORT std::vector Decrypt(const OHOS::NativeRdb::RDBCryptoParam ¶m, RDBCryptoFault &rdbFault) asm( + "decrypt"); +API_EXPORT std::vector GenerateRandomNum(int32_t &len) asm("generateRandomNum"); +int32_t CheckRootKeyExists(std::vector &rootKeyAlias) +{ + return OHOS::NativeRdb::RDBCrypto::CheckRootKeyExists(rootKeyAlias); +} +int32_t GenerateRootKey(const std::vector &rootKeyAlias, RDBCryptoFault &rdbFault) +{ + return OHOS::NativeRdb::RDBCrypto::GenerateRootKey(rootKeyAlias, rdbFault); +} +std::vector Encrypt(const OHOS::NativeRdb::RDBCryptoParam ¶m, RDBCryptoFault &rdbFault) +{ + return OHOS::NativeRdb::RDBCrypto::Encrypt(param, rdbFault); +} +std::vector Decrypt(const OHOS::NativeRdb::RDBCryptoParam ¶m, RDBCryptoFault &rdbFault) +{ + return OHOS::NativeRdb::RDBCrypto::Decrypt(param, rdbFault); +} +std::vector GenerateRandomNum(uint32_t len) +{ + return OHOS::NativeRdb::RDBCrypto::GenerateRandomNum(len); +} +namespace OHOS { +namespace NativeRdb { +using namespace OHOS::Rdb; +constexpr const char *RDB_HKS_BLOB_TYPE_NONCE = "Z5s0Bo571Koq"; +constexpr const char *RDB_HKS_BLOB_TYPE_AAD = "RdbClientAAD"; +constexpr uint32_t TIMES = 4; +constexpr uint32_t MAX_UPDATE_SIZE = 64; +constexpr uint32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES; +constexpr uint8_t AEAD_LEN = 16; +static std::vector g_nonce(RDB_HKS_BLOB_TYPE_NONCE, RDB_HKS_BLOB_TYPE_NONCE + strlen(RDB_HKS_BLOB_TYPE_NONCE)); +static std::vector g_add(RDB_HKS_BLOB_TYPE_AAD, RDB_HKS_BLOB_TYPE_AAD + strlen(RDB_HKS_BLOB_TYPE_AAD)); + +RDBCryptoFault GetDfxFault(int32_t code, const std::string &message) +{ + RDBCryptoFault rdbDfxFault; + rdbDfxFault.code = code; + rdbDfxFault.message = message; + return rdbDfxFault; +} + +int32_t HksLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData, + struct HksBlob *outData, RDBCryptoFault &rdbFault) +{ + if (outData->size < inData->size * TIMES) { + HksAbort(handle, paramSet); + rdbFault = GetDfxFault(E_WORK_KEY_FAIL, "HksLoopUpdate out size not enough"); + return HKS_ERROR_INVALID_ARGUMENT; + } + + struct HksBlob input = { MAX_UPDATE_SIZE, inData->data }; + uint8_t *end = inData->data + inData->size - 1; + outData->size = 0; + struct HksBlob output = { MAX_OUTDATA_SIZE, outData->data }; + while (input.data <= end) { + if (input.data + MAX_UPDATE_SIZE > end) { + input.size = end - input.data + 1; + break; + } + auto result = HksUpdate(handle, paramSet, &input, &output); + if (result != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_FAIL, "HksUpdate ret=" + std::to_string(result)); + LOG_ERROR("HksUpdate Failed."); + return HKS_FAILURE; + } + + output.data += output.size; + outData->size += output.size; + input.data += MAX_UPDATE_SIZE; + } + output.size = input.size * TIMES; + auto result = HksFinish(handle, paramSet, &input, &output); + if (result != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_FAIL, "HksFinish ret=" + std::to_string(result)); + LOG_ERROR("HksFinish Failed."); + return HKS_FAILURE; + } + outData->size += output.size; + return HKS_SUCCESS; +} + +int32_t HksDecryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, + const struct HksBlob *cipherText, struct HksBlob *plainText, RDBCryptoFault &rdbFault) +{ + uint8_t handle[sizeof(uint64_t)] = { 0 }; + struct HksBlob handleBlob = { sizeof(uint64_t), handle }; + int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr); + if (result != HKS_SUCCESS) { + LOG_ERROR("HksEncrypt failed with error %{public}d", result); + rdbFault = GetDfxFault(E_WORK_KEY_DECRYPT_FAIL, "Decrypt HksInit ret=" + std::to_string(result)); + return result; + } + result = HksLoopUpdate(&handleBlob, paramSet, cipherText, plainText, rdbFault); + if (result != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_DECRYPT_FAIL, "Decrypt HksLoopUpdate ret=" + std::to_string(result)); + } + return result; +} + +int32_t HksEncryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, + const struct HksBlob *plainText, struct HksBlob *cipherText, RDBCryptoFault &rdbFault) +{ + uint8_t handle[sizeof(uint64_t)] = { 0 }; + struct HksBlob handleBlob = { sizeof(uint64_t), handle }; + int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr); + if (result != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_ENCRYPT_FAIL, "Decrypt HksInit ret=" + std::to_string(result)); + LOG_ERROR("HksEncrypt failed with error %{public}d", result); + return result; + } + return HksLoopUpdate(&handleBlob, paramSet, plainText, cipherText, rdbFault); +} + +std::vector CreateHksParams(const HksBlob &blobNonce, const HksBlob &blobAad, const HksBlob &blobAead) +{ + std::vector params; + params.push_back(HksParam{ .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }); + params.push_back(HksParam{ .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_DECRYPT }); + params.push_back(HksParam{ .tag = HKS_TAG_DIGEST, .uint32Param = 0 }); + params.push_back(HksParam{ .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }); + params.push_back(HksParam{ .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }); + params.push_back(HksParam{ .tag = HKS_TAG_NONCE, .blob = blobNonce }); + params.push_back(HksParam{ .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }); + params.push_back(HksParam{ .tag = HKS_TAG_AE_TAG, .blob = blobAead }); + params.push_back(HksParam{ .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }); + return params; +} + +int32_t RDBCrypto::CheckRootKeyExists(std::vector &rootKeyAlias) +{ + LOG_DEBUG("RDB checkRootKeyExist begin."); + struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), rootKeyAlias.data() }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret); + return ret; + } + + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, + }; + + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return ret; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return ret; + } + + ret = HksKeyExist(&rootKeyName, params); + HksFreeParamSet(¶ms); + return ret; +} + +int32_t RDBCrypto::GenerateRootKey(const std::vector &rootKeyAlias, RDBCryptoFault &rdbFault) +{ + LOG_INFO("RDB GenerateRootKey begin."); + std::vector tempRootKeyAlias = rootKeyAlias; + struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), tempRootKeyAlias.data() }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_ROOT_KEY_FAULT, "generator root key, HksInitParamSet ret=" + std::to_string(ret)); + LOG_ERROR("HksInitParamSet()-client failed with error %{public}d", ret); + return ret; + } + + struct HksParam hksParam[] = { + { .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_KEY_SIZE, .uint32Param = HKS_AES_KEY_SIZE_256 }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT | HKS_KEY_PURPOSE_DECRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }, + }; + + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_ROOT_KEY_FAULT, "HksAddParams ret=" + std::to_string(ret)); + LOG_ERROR("HksAddParams-client failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return ret; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_ROOT_KEY_FAULT, "HksBuildParamSet ret=" + std::to_string(ret)); + LOG_ERROR("HksBuildParamSet-client failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return ret; + } + + ret = HksGenerateKey(&rootKeyName, params, nullptr); + HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_ROOT_KEY_FAULT, "HksGenerateKey ret=" + std::to_string(ret)); + LOG_ERROR("HksGenerateKey-client failed with error %{public}d", ret); + } + return ret; +} + +std::vector CreateEncryptHksParams(const HksBlob &blobNonce, const HksBlob &blobAad) +{ + std::vector params; + params.push_back(HksParam{ .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }); + params.push_back(HksParam{ .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT }); + params.push_back(HksParam{ .tag = HKS_TAG_DIGEST, .uint32Param = 0 }); + params.push_back(HksParam{ .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }); + params.push_back(HksParam{ .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }); + params.push_back(HksParam{ .tag = HKS_TAG_NONCE, .blob = blobNonce }); + params.push_back(HksParam{ .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }); + params.push_back(HksParam{ .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }); + return params; +} + +std::vector RDBCrypto::Encrypt(const RDBCryptoParam ¶m, RDBCryptoFault &rdbFault) +{ + std::vector tempRootKeyAlias(param.rootAlias); + std::vector tempKey(param.KeyValue); + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_ENCRYPT_FAIL, "Encrypt HksInitParamSet ret=" + std::to_string(ret)); + LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret); + tempKey.assign(tempKey.size(), 0); + return {}; + } + struct HksBlob blobAad = { uint32_t(g_add.size()), g_add.data() }; + struct HksBlob rootKeyName = { uint32_t(tempRootKeyAlias.size()), tempRootKeyAlias.data() }; + struct HksBlob plainKey = { uint32_t(tempKey.size()), tempKey.data() }; + struct HksBlob blobNonce = { uint32_t(param.nonceValue.size()), const_cast(&(param.nonceValue[0])) }; + + auto hksParams = CreateEncryptHksParams(blobNonce, blobAad); + ret = HksAddParams(params, hksParams.data(), hksParams.size()); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_ENCRYPT_FAIL, "Encrypt HksAddParams ret=" + std::to_string(ret)); + LOG_ERROR("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + tempKey.assign(tempKey.size(), 0); + return {}; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_ENCRYPT_FAIL, "Encrypt HksBuildParamSet ret=" + std::to_string(ret)); + LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + tempKey.assign(tempKey.size(), 0); + return {}; + } + std::vector encryptedKey(plainKey.size * TIMES + 1); + struct HksBlob cipherText = { uint32_t(encryptedKey.size()), encryptedKey.data() }; + ret = HksEncryptThreeStage(&rootKeyName, params, &plainKey, &cipherText, rdbFault); + (void)HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + encryptedKey.assign(encryptedKey.size(), 0); + tempKey.assign(tempKey.size(), 0); + return {}; + } + encryptedKey.resize(cipherText.size); + tempKey.assign(tempKey.size(), 0); + return encryptedKey; +} + +std::vector RDBCrypto::Decrypt(const RDBCryptoParam ¶m, RDBCryptoFault &rdbFault) +{ + std::vector tempRootKeyAlias(param.rootAlias); + std::vector source(param.KeyValue); + struct HksBlob blobAad = { uint32_t(g_add.size()), &(g_add[0]) }; + struct HksBlob blobNonce = { uint32_t(param.nonceValue.size()), const_cast(&(param.nonceValue[0])) }; + struct HksBlob rootKeyName = { uint32_t(tempRootKeyAlias.size()), &(tempRootKeyAlias[0]) }; + struct HksBlob encryptedKeyBlob = { uint32_t(source.size() - AEAD_LEN), source.data() }; + struct HksBlob blobAead = { AEAD_LEN, source.data() + source.size() - AEAD_LEN }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_DECRYPT_FAIL, "HksInitParamSet ret=" + std::to_string(ret)); + LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret); + return {}; + } + auto hksParams = CreateHksParams(blobNonce, blobAad, blobAead); + ret = HksAddParams(params, hksParams.data(), hksParams.size()); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_DECRYPT_FAIL, "HksAddParams ret=" + std::to_string(ret)); + LOG_ERROR("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return {}; + } + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + rdbFault = GetDfxFault(E_WORK_KEY_DECRYPT_FAIL, "HksBuildParamSet ret=" + std::to_string(ret)); + LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return {}; + } + std::vector decryptKey(encryptedKeyBlob.size * TIMES + 1); + struct HksBlob plainKeyBlob = { uint32_t(decryptKey.size()), decryptKey.data() }; + ret = HksDecryptThreeStage(&rootKeyName, params, &encryptedKeyBlob, &plainKeyBlob, rdbFault); + (void)HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + decryptKey.assign(decryptKey.size(), 0); + LOG_ERROR("HksDecrypt failed with error %{public}d", ret); + return {}; + } + decryptKey.resize(plainKeyBlob.size); + return decryptKey; +} + +std::vector RDBCrypto::GenerateRandomNum(uint32_t len) +{ + std::vector value(len, 0); + struct HksBlob blobValue = { .size = len, .data = &(value[0]) }; + auto ret = HksGenerateRandom(nullptr, &blobValue); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksGenerateRandom failed, status: %{public}d", ret); + return {}; + } + return value; +} +} // namespace NativeRdb +} // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb_crypt/relational_store_crypt.h b/relational_store/frameworks/native/rdb_crypt/relational_store_crypt.h new file mode 100644 index 00000000..e0cc26d4 --- /dev/null +++ b/relational_store/frameworks/native/rdb_crypt/relational_store_crypt.h @@ -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. + */ +#ifndef RELATIONAL_STORE_CRYPT_H +#define RELATIONAL_STORE_CRYPT_H + +#include +#include +#include + +#include "rdb_security_manager.h" + +namespace OHOS { +namespace NativeRdb { +struct RDBCryptoFault { + int32_t code; + std::string message; +}; +struct RDBCryptoParam { + std::vector rootAlias; + std::vector nonceValue; + std::vector KeyValue; + RDBCryptoParam() = default; + ~RDBCryptoParam() + { + nonceValue.assign(nonceValue.size(), 0); + KeyValue.assign(KeyValue.size(), 0); + } +}; +} // namespace OHOS::NativeRdb +} // OHOS + +#endif // RELATIONAL_STORE_CRYPT_H \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/appdatafwk/BUILD.gn b/relational_store/interfaces/inner_api/appdatafwk/BUILD.gn index f327747e..62931059 100644 --- a/relational_store/interfaces/inner_api/appdatafwk/BUILD.gn +++ b/relational_store/interfaces/inner_api/appdatafwk/BUILD.gn @@ -39,7 +39,6 @@ config("common_public_config") { include_dirs = [ "include", "${relational_store_common_path}/include", - "//third_party/json/single_include", ] } @@ -63,6 +62,11 @@ if (is_android || is_ios) { ":appdatafwk_public_config", ] + deps = [ + "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_${target_os}", + "//third_party/json:nlohmann_json_static", + ] + subsystem_name = "distributeddatamgr" part_name = "relational_store" @@ -98,6 +102,10 @@ if (is_android || is_ios) { ":common_public_config", ":appdatafwk_public_config", ] + external_deps = [ + "json:nlohmann_json_static", + "hilog:libhilog", + ] subsystem_name = "distributeddatamgr" part_name = "relational_store" @@ -127,6 +135,7 @@ ohos_shared_library("native_appdatafwk") { external_deps = [ "c_utils:utils", + "json:nlohmann_json_static", "hilog:libhilog", "ipc:ipc_single", ] diff --git a/relational_store/interfaces/inner_api/appdatafwk/include/serializable.h b/relational_store/interfaces/inner_api/appdatafwk/include/serializable.h index b4fd7f8f..f8293bbb 100644 --- a/relational_store/interfaces/inner_api/appdatafwk/include/serializable.h +++ b/relational_store/interfaces/inner_api/appdatafwk/include/serializable.h @@ -59,6 +59,7 @@ public: API_EXPORT static bool GetValue(const json &node, const std::string &name, bool &value); API_EXPORT static bool GetValue(const json &node, const std::string &name, std::vector &value); API_EXPORT static bool GetValue(const json &node, const std::string &name, Serializable &value); + API_EXPORT static bool GetValue(const json &node, const std::string &name, double &value); API_EXPORT static bool SetValue(json &node, const std::string &value); API_EXPORT static bool SetValue(json &node, const uint32_t &value); API_EXPORT static bool SetValue(json &node, const int32_t &value); @@ -67,6 +68,7 @@ public: API_EXPORT static bool SetValue(json &node, const bool &value); API_EXPORT static bool SetValue(json &node, const std::vector &value); API_EXPORT static bool SetValue(json &node, const Serializable &value); + API_EXPORT static bool SetValue(json &node, const double &value); protected: API_EXPORT ~Serializable() = default; diff --git a/relational_store/interfaces/inner_api/appdatafwk/include/shared_block.h b/relational_store/interfaces/inner_api/appdatafwk/include/shared_block.h index edae9b81..6bfde2c1 100644 --- a/relational_store/interfaces/inner_api/appdatafwk/include/shared_block.h +++ b/relational_store/interfaces/inner_api/appdatafwk/include/shared_block.h @@ -36,7 +36,7 @@ static const uint32_t INVALID_ROW_RECORD = 0xFFFFFFFF; * This class stores a set of rows from a database in a buffer, * which is used as the set of query result. */ -class API_EXPORT SharedBlock { +class SharedBlock { public: /** * @brief Cell Unit types. @@ -98,21 +98,8 @@ public: API_EXPORT const uint8_t *GetRawData(SharedBlock *block) const; } __attribute((packed)); - /** - * @brief Constructor. - */ - API_EXPORT SharedBlock(const std::string &name, sptr ashmem, size_t size, bool readOnly); - - /** - * @brief Destructor. - */ API_EXPORT ~SharedBlock(); - /** - * @brief Init current shared block. - */ - API_EXPORT bool Init(); - /** * @brief Create a shared block. */ @@ -193,6 +180,9 @@ public: */ API_EXPORT const char *GetCellUnitValueString(CellUnit *cellUnit, size_t *outSizeIncludingNull) { + if (cellUnit == nullptr || outSizeIncludingNull == nullptr) { + return nullptr; + } *outSizeIncludingNull = cellUnit->cell.stringOrBlobValue.size; return static_cast( OffsetToPtr(cellUnit->cell.stringOrBlobValue.offset, cellUnit->cell.stringOrBlobValue.size)); @@ -203,6 +193,9 @@ public: */ API_EXPORT const void *GetCellUnitValueBlob(CellUnit *cellUnit, size_t *outSize) { + if (cellUnit == nullptr || outSize == nullptr) { + return nullptr; + } *outSize = cellUnit->cell.stringOrBlobValue.size; return OffsetToPtr(cellUnit->cell.stringOrBlobValue.offset, cellUnit->cell.stringOrBlobValue.size); } @@ -365,6 +358,10 @@ private: SharedBlockHeader *mHeader; + SharedBlock(const std::string &name, sptr ashmem, size_t size, bool readOnly); + + bool Init(); + /** * Allocate a portion of the block. Returns the offset of the allocation. * Returns 0 if there isn't enough space. diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_notifier.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_notifier.h new file mode 100644 index 00000000..1fdcbc67 --- /dev/null +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_notifier.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 OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_NOTIFIER_H +#define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_NOTIFIER_H + +#include "cloud_types.h" +#include "distributeddata_relational_store_ipc_interface_code.h" +#include "rdb_types.h" + +namespace OHOS::CloudData { +class ICloudNotifier { +public: + virtual int32_t OnComplete(uint32_t seqNum, DistributedRdb::Details &&result) = 0; +}; +} // namespace OHOS::CloudData +#endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_NOTIFIER_H diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h index 1351c795..2ecc08ab 100644 --- a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h @@ -24,6 +24,7 @@ #include "cloud_types.h" #include "common_types.h" +#include "iremote_broker.h" #include "rdb_types.h" #include "values_bucket.h" namespace OHOS { @@ -42,6 +43,7 @@ public: TRANS_QUERY_STATISTICS, TRANS_QUERY_LAST_SYNC_INFO, TRANS_SET_GLOBAL_CLOUD_STRATEGY, + TRANS_CLOUD_SYNC, TRANS_CONFIG_BUTT, TRANS_SHARE_HEAD = TRANS_CONFIG_BUTT, TRANS_ALLOC_RESOURCE_AND_SHARE = TRANS_SHARE_HEAD, @@ -56,6 +58,7 @@ public: TRANS_SHARE_BUTT, TRANS_CLIENT_HEAD = TRANS_SHARE_BUTT, TRANS_SET_CLOUD_STRATEGY = TRANS_CLIENT_HEAD, + TRANS_INIT_NOTIFIER, TRANS_CLIENT_BUTT, TRANS_BUTT = TRANS_CLIENT_BUTT, }; @@ -91,6 +94,12 @@ public: CLOUD_INFO_INVALID, SCHEMA_INVALID, STRATEGY_BLOCKING, + INVALID_ARGUMENT_V20, + }; + + struct Option { + int32_t syncMode; + uint32_t seqNum = 0; }; static const int INVALID_USER_ID = -1; @@ -124,6 +133,9 @@ public: virtual int32_t SetCloudStrategy(Strategy strategy, const std::vector &values) = 0; virtual std::pair QueryLastSyncInfo( const std::string &id, const std::string &bundleName, const std::string &storeId) = 0; + virtual int32_t CloudSync(const std::string &bundleName, const std::string &storeId, const Option &option, + const DistributedRdb::AsyncDetail &async) = 0; + virtual int32_t InitNotifier(sptr notifier) = 0; inline static constexpr const char *SERVICE_NAME = "cloud"; }; diff --git a/relational_store/interfaces/inner_api/dataability/BUILD.gn b/relational_store/interfaces/inner_api/dataability/BUILD.gn index 97d6ef4f..0c06a5e9 100644 --- a/relational_store/interfaces/inner_api/dataability/BUILD.gn +++ b/relational_store/interfaces/inner_api/dataability/BUILD.gn @@ -58,7 +58,10 @@ ohos_shared_library("native_dataability") { configs = [ ":native_dataability_config" ] if (!(host_os == "linux" && host_cpu == "arm64")) { - deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + deps = [ + "${relational_store_innerapi_path}/rdb:native_rdb", + "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", + ] } external_deps = [ diff --git a/relational_store/interfaces/inner_api/dataability/include/data_ability_predicates.h b/relational_store/interfaces/inner_api/dataability/include/data_ability_predicates.h index aeb0553b..0e2f4601 100644 --- a/relational_store/interfaces/inner_api/dataability/include/data_ability_predicates.h +++ b/relational_store/interfaces/inner_api/dataability/include/data_ability_predicates.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef NATIVE_RDB_DATD_ABILITY_PREDICATES_H -#define NATIVE_RDB_DATD_ABILITY_PREDICATES_H +#ifndef NATIVE_RDB_DATA_ABILITY_PREDICATES_H +#define NATIVE_RDB_DATA_ABILITY_PREDICATES_H #include diff --git a/relational_store/interfaces/inner_api/gdb/include/gdb_errors.h b/relational_store/interfaces/inner_api/gdb/include/gdb_errors.h deleted file mode 100644 index 7ad53617..00000000 --- a/relational_store/interfaces/inner_api/gdb/include/gdb_errors.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GDB_ERRORS_H -#define OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GDB_ERRORS_H - -#include "errors.h" - -namespace OHOS { -namespace DistributedDataAip { -enum { - AIP_MODULE_SERVICE_ID = 0x08, -}; - -constexpr ErrCode DISTRIBUTEDDATAMGR_GDB_ERR_OFFSET = ErrCodeOffset(SUBSYS_DISTRIBUTEDDATAMNG, AIP_MODULE_SERVICE_ID); - -/** -* @brief The error code in the correct case. -*/ -constexpr int E_OK = 0; - -/** -* @brief The base code of the exception error code. -*/ -constexpr int E_BASE = DISTRIBUTEDDATAMGR_GDB_ERR_OFFSET; - -/** -* @brief The error code for common exceptions. -*/ -constexpr int E_ERROR = E_BASE; - -constexpr int E_INVALID_ARGS = (E_BASE + 0x1); -constexpr int E_NOT_SUPPORT = (E_BASE + 0x2); - -/* GRD error */ - -constexpr int E_GRD_NO_DATA = (E_BASE + 0x3); -constexpr int E_GRD_DATA_CORRUPTED = (E_BASE + 0x4); -constexpr int E_GRD_DB_INSTANCE_ABNORMAL = (E_BASE + 0x5); -constexpr int E_DATABASE_BUSY = (E_BASE + 0x6); -constexpr int E_GRD_FAILED_MEMORY_ALLOCATE = (E_BASE + 0x7); -constexpr int E_GRD_DISK_SPACE_FULL = (E_BASE + 0x8); -constexpr int E_GRD_DUPLICATE_PARAM = (E_BASE + 0x9); -constexpr int E_GRD_UNDEFINED_PARAM = (E_BASE + 0xa); -constexpr int E_GRD_INVALID_NAME = (E_BASE + 0xb); -constexpr int E_GRD_SYNTAX_ERROR = (E_BASE + 0xc); -constexpr int E_GRD_SEMANTIC_ERROR = (E_BASE + 0xd); -constexpr int E_GRD_OVER_LIMIT = (E_BASE + 0xe); - -constexpr int E_GRD_INVALID_ARGS = (E_BASE + 0xf); -constexpr int E_GRD_FAILED_FILE_OPERATION = (E_BASE + 0x10); -constexpr int E_GRD_CRC_CHECK_DISABLED = (E_BASE + 0x11); -constexpr int E_GRD_PERMISSION_DENIED = (E_BASE + 0x12); -constexpr int E_GRD_PASSWORD_UNMATCHED = (E_BASE + 0x13); -constexpr int E_GRD_PASSWORD_NEED_REKEY = (E_BASE + 0x14); -constexpr int E_GRD_WRONG_STMT_OBJECT = (E_BASE + 0x15); -constexpr int E_GRD_DATA_CONFLICT = (E_BASE + 0x16); -constexpr int E_GRD_INNER_ERR = (E_BASE + 0x17); -constexpr int E_GRD_FAILED_MEMORY_RELEASE = (E_BASE + 0x18); -constexpr int E_GRD_NOT_AVAILABLE = (E_BASE + 0x19); -constexpr int E_GRD_CIPHER_ERROR = (E_BASE + 0x1a); -constexpr int E_ARGS_READ_CON_OVERLOAD = (E_BASE + 0x1b); -constexpr int E_GRD_INVALID_FILE_FORMAT = (E_BASE + 0x1c); -constexpr int E_GRD_INVALID_BIND_VALUE = (E_BASE + 0x1d); -constexpr int E_GRD_DB_NOT_EXIST = (E_BASE + 0x1e); -constexpr int E_GRD_DATA_NOT_FOUND = (E_BASE + 0x1f); -constexpr int E_GRD_DATA_EXCEPTION = (E_BASE + 0x20); -constexpr int E_GRD_TRANSACTION_ROLLBACK = (E_BASE + 0x21); -constexpr int E_GRD_NO_ACTIVE_TRANSACTION = (E_BASE + 0x22); -constexpr int E_GRD_ACTIVE_TRANSACTION = (E_BASE + 0x23); - -constexpr int E_ACQUIRE_CONN_FAILED = (E_BASE + 0x24); -constexpr int E_PREPARE_CHECK_FAILED = (E_BASE + 0x25); -constexpr int E_STEP_CHECK_FAILED = (E_BASE + 0x26); -constexpr int E_GETTED_COLNAME_EMPTY = (E_BASE + 0x27); -constexpr int E_PARSE_JSON_FAILED = (E_BASE + 0x28); -constexpr int E_INNER_ERROR = (E_BASE + 0x29); -constexpr int E_NO_DATA = (E_BASE + 0x2a); -constexpr int E_DBPATH_ACCESS_FAILED = (E_BASE + 0x2b); -constexpr int E_INIT_CONN_POOL_FAILED = (E_BASE + 0x2c); -constexpr int E_CONFIG_INVALID_CHANGE = (E_BASE + 0x2d); -constexpr int E_GRD_INVAILD_NAME_ERR = (E_BASE + 0x2e); -constexpr int E_CREATE_FOLDER_FAIT = (E_BASE + 0x3f); -constexpr int E_STATEMENT_EMPTY = (E_BASE + 0x30); -constexpr int E_STORE_HAS_CLOSED = (E_BASE + 0x31); -constexpr int E_GRD_NOT_SUPPORT = (E_BASE + 0x32); -} // namespace DistributedDataAip -} // namespace OHOS - -#endif // OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GDB_ERRORS_H \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/gdb/include/gdb_store.h b/relational_store/interfaces/inner_api/gdb/include/gdb_store.h deleted file mode 100644 index fc251b50..00000000 --- a/relational_store/interfaces/inner_api/gdb/include/gdb_store.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_DB_STORE_H -#define OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_DB_STORE_H -#include "gdb_transaction.h" -#include "rdb_visibility.h" -#include "result.h" - -namespace OHOS::DistributedDataAip { -class API_EXPORT DBStore { -public: - API_EXPORT virtual std::pair> QueryGql(const std::string &gql) = 0; - API_EXPORT virtual std::pair> ExecuteGql(const std::string &gql) = 0; - API_EXPORT virtual std::pair> CreateTransaction() = 0; - API_EXPORT virtual int32_t Close() = 0; - - virtual ~DBStore() = default; -}; -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_DB_STORE_H diff --git a/relational_store/interfaces/inner_api/gdb/include/gdb_store_config.h b/relational_store/interfaces/inner_api/gdb/include/gdb_store_config.h deleted file mode 100644 index 89962ccf..00000000 --- a/relational_store/interfaces/inner_api/gdb/include/gdb_store_config.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_STORE_CONFIG_H -#define OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_STORE_CONFIG_H - -#include -#include -#include - -#include "rdb_store_config.h" -#include "rdb_visibility.h" - -namespace OHOS::DistributedDataAip { -enum SecurityLevel : int32_t { - S1 = 1, - S2, - S3, - S4, - LAST, -}; - -enum class DBType : int { - /** - * The graph database. - */ - DB_GRAPH, - - /** - * The vector database. - */ - DB_VECTOR, - /** - * The BUTT of database. - */ - DB_BUTT -}; - -class StoreConfig { -public: - API_EXPORT StoreConfig() = default; - API_EXPORT ~StoreConfig(); - API_EXPORT StoreConfig(std::string name, std::string path, DBType dbType = DBType::DB_GRAPH, bool isEncrypt = false, - const std::vector &encryptKey = std::vector()); - API_EXPORT void SetName(std::string name); - API_EXPORT void SetPath(std::string path); - API_EXPORT void SetDbType(DBType dbType); - API_EXPORT void SetEncryptStatus(bool status); - API_EXPORT void SetSecurityLevel(int32_t securityLevel); - API_EXPORT bool IsEncrypt() const; - API_EXPORT std::string GetFullPath() const; - API_EXPORT std::string GetPath() const; - API_EXPORT std::string GetName() const; - API_EXPORT int32_t GetSecurityLevel() const; - API_EXPORT DBType GetDbType() const; - API_EXPORT void SetIter(int32_t iter) const; - API_EXPORT int32_t GetIter() const; - API_EXPORT int GetWriteTime() const; - API_EXPORT void SetWriteTime(int timeout); - API_EXPORT int GetReadTime() const; - API_EXPORT void SetReadTime(int timeout); - API_EXPORT int GetReadConSize() const; - API_EXPORT void SetReadConSize(int readConSize); - API_EXPORT std::vector GetEncryptKey() const; - API_EXPORT int SetBundleName(const std::string &bundleName); - API_EXPORT std::string GetBundleName() const; - void GenerateEncryptedKey() const; - std::vector GetNewEncryptKey() const; - void ChangeEncryptKey() const; - -private: - std::string name_; - std::string path_; - std::string bundleName_; - DBType dbType_ = DBType::DB_GRAPH; - bool isEncrypt_ = false; - mutable std::vector encryptKey_{}; - mutable std::vector newEncryptKey_{}; - mutable int32_t iter_ = 0; - int32_t writeTimeout_ = 2; // seconds - int32_t readTimeout_ = 1; // seconds - int32_t readConSize_ = 4; - int32_t securityLevel_ = SecurityLevel::S1; - - static constexpr int MAX_TIMEOUT = 300; // seconds - static constexpr int MIN_TIMEOUT = 1; // seconds - void ClearEncryptKey(); -}; -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_STORE_CONFIG_H \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/gdb/include/path.h b/relational_store/interfaces/inner_api/gdb/include/path.h deleted file mode 100644 index d7095e2d..00000000 --- a/relational_store/interfaces/inner_api/gdb/include/path.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -* 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 OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_PATH_H -#define OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_PATH_H -#include -#include -#include -#include -#include -#include - -#include "edge.h" -#include "nlohmann/json.hpp" -#include "path_segment.h" -#include "rdb_visibility.h" -#include "vertex.h" - -namespace OHOS::DistributedDataAip { -class Path { -public: - API_EXPORT Path(); - API_EXPORT Path(std::shared_ptr start, std::shared_ptr end); - API_EXPORT Path(std::shared_ptr start, std::shared_ptr end, uint32_t pathLen, - std::vector> segments); - - static std::shared_ptr Parse(const nlohmann::json &json, int32_t &errCode); - - API_EXPORT uint32_t GetPathLength() const; - API_EXPORT void SetPathLength(uint32_t pathLen); - API_EXPORT std::shared_ptr GetStart() const; - API_EXPORT void SetStart(std::shared_ptr start); - API_EXPORT std::shared_ptr GetEnd() const; - API_EXPORT void SetEnd(std::shared_ptr end); - API_EXPORT const std::vector> &GetSegments() const; - - static constexpr const char *PATHLEN = "length"; - static constexpr const char *START = "start"; - static constexpr const char *END = "end"; - static constexpr const char *SEGMENTS = "segments"; - -private: - uint32_t pathLen_; - std::shared_ptr start_; - std::shared_ptr end_; - std::vector> segments_; -}; - -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_PATH_H diff --git a/relational_store/interfaces/inner_api/gdb/include/path_segment.h b/relational_store/interfaces/inner_api/gdb/include/path_segment.h deleted file mode 100644 index 31e00a00..00000000 --- a/relational_store/interfaces/inner_api/gdb/include/path_segment.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -* 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 OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_PATH_SEGMENT_H -#define OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_PATH_SEGMENT_H -#include -#include -#include -#include -#include -#include - -#include "edge.h" -#include "rdb_visibility.h" -#include "vertex.h" - -namespace OHOS::DistributedDataAip { -class PathSegment { -public: - API_EXPORT PathSegment(); - API_EXPORT PathSegment(std::shared_ptr sourceVertex, std::shared_ptr targetVertex, - std::shared_ptr edge); - static std::shared_ptr Parse(const nlohmann::json &json, int32_t &errCode); - - API_EXPORT std::shared_ptr GetSourceVertex() const; - API_EXPORT void SetSourceVertex(std::shared_ptr vertex); - - API_EXPORT std::shared_ptr GetEdge() const; - API_EXPORT void SetEdge(std::shared_ptr edge); - - API_EXPORT std::shared_ptr GetTargetVertex() const; - API_EXPORT void SetTargetVertex(std::shared_ptr vertex); - - static constexpr const char *SOURCE_VERTEX = "start"; - static constexpr const char *TARGET_VERTEX = "end"; - static constexpr const char *EDGE = "relationship"; - -private: - std::shared_ptr sourceVertex_; - std::shared_ptr edge_; - std::shared_ptr targetVertex_; -}; -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_PATH_SEGMENT_H diff --git a/relational_store/interfaces/inner_api/gdb/include/vertex.h b/relational_store/interfaces/inner_api/gdb/include/vertex.h deleted file mode 100644 index f4f28882..00000000 --- a/relational_store/interfaces/inner_api/gdb/include/vertex.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -* 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 OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_VERTEX_H -#define OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_VERTEX_H -#include -#include -#include -#include -#include -#include - -#include "nlohmann/json.hpp" -#include "rdb_visibility.h" - -namespace OHOS::DistributedDataAip { -using PropType = std::variant; -class Vertex { -public: - API_EXPORT Vertex(); - API_EXPORT Vertex(std::string id, std::string label); - API_EXPORT Vertex(std::string id, std::string label, const std::unordered_map &properties); - static std::shared_ptr Parse(const nlohmann::json &json, int32_t &errCode); - - API_EXPORT std::string GetId() const; - API_EXPORT void SetId(std::string id); - - API_EXPORT const std::string &GetLabel() const; - API_EXPORT const std::vector &GetLabels() const; - API_EXPORT void SetLabel(const std::string &label); - - API_EXPORT const std::unordered_map &GetProperties() const; - API_EXPORT void SetProperty(const std::string &key, PropType value); - - static constexpr const char *ID = "identity"; - static constexpr const char *LABEL = "label"; - static constexpr const char *PROPERTIES = "properties"; - -protected: - std::string id_; - std::string label_; - std::vector labels_; - std::unordered_map properties_; -}; -} // namespace OHOS::DistributedDataAip -#endif //OHOS_DISTRIBUTED_DATA_INTERFACE_GDB_GRAPH_VERTEX_H diff --git a/relational_store/interfaces/inner_api/rdb/BUILD.gn b/relational_store/interfaces/inner_api/rdb/BUILD.gn index 3888a55d..c28fbde1 100644 --- a/relational_store/interfaces/inner_api/rdb/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# Copyright (c) 2021-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 @@ -24,11 +24,17 @@ base_sources = [ "${relational_store_native_path}/rdb/src/connection.cpp", "${relational_store_native_path}/rdb/src/connection_pool.cpp", "${relational_store_native_path}/rdb/src/delay_notify.cpp", + "${relational_store_native_path}/rdb/src/global_resource.cpp", + "${relational_store_native_path}/rdb/src/knowledge_schema_helper.cpp", "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", "${relational_store_native_path}/rdb/src/rdb_helper.cpp", + "${relational_store_native_path}/rdb/src/rdb_icu_manager.cpp", "${relational_store_native_path}/rdb/src/rdb_local_db_observer.cpp", + "${relational_store_native_path}/rdb/src/rdb_obs_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_perfStat.cpp", "${relational_store_native_path}/rdb/src/rdb_predicates.cpp", "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_log.cpp", "${relational_store_native_path}/rdb/src/rdb_sql_statistic.cpp", "${relational_store_native_path}/rdb/src/rdb_sql_utils.cpp", "${relational_store_native_path}/rdb/src/rdb_store.cpp", @@ -43,6 +49,7 @@ base_sources = [ "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", "${relational_store_native_path}/rdb/src/step_result_set.cpp", "${relational_store_native_path}/rdb/src/string_utils.cpp", + "${relational_store_native_path}/rdb/src/suspender.cpp", "${relational_store_native_path}/rdb/src/trans_db.cpp", "${relational_store_native_path}/rdb/src/transaction.cpp", "${relational_store_native_path}/rdb/src/transaction_impl.cpp", @@ -67,9 +74,10 @@ if (is_ohos && !build_ohos_sdk) { include_dirs = [ "include", "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb_crypt", "${relational_store_native_path}/rdb/include", "${relational_store_native_path}/dfx/include", - "${relational_store_native_path}/rdb_device_manager_adapter/include", + "${relational_store_native_path}/obs_mgr_adapter", ] defines = [ @@ -83,11 +91,6 @@ if (is_ohos && !build_ohos_sdk) { defined(global_parts_info.distributeddatamgr_arkdata_database_core)) { defines += [ "ARKDATA_DATABASE_CORE_ENABLE" ] } - include_dirs += [ - "${kvstore_path}/common", - "${kvstore_interface_path}", - "${distributedfile_path}/mod_securitylabel", - ] } config("native_rdb_public_config") { @@ -97,6 +100,8 @@ if (is_ohos && !build_ohos_sdk) { "include", "${relational_store_native_path}/rdb/include", "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", + "${relational_store_innerapi_path}/appdatafwk/include", "../cloud_data/include", "../common_type/include", ] @@ -138,27 +143,24 @@ if (is_ohos && !build_ohos_sdk) { "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", "${relational_store_native_path}/rdb/src/task_executor.cpp", - "${relational_store_native_path}/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp", ] - public_deps = [ + deps = [ "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", "${relational_store_innerapi_path}/appdatafwk:relational_common_base", ] external_deps = [ - "ability_base:zuri", - "ability_runtime:dataobs_manager", - "access_token:libaccesstoken_sdk", "c_utils:utils", - "device_manager:devicemanagersdk", + "file_api:securitylabel", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", - "huks:libhukssdk", "ipc:ipc_core", + "json:nlohmann_json_static", "kv_store:database_utils", - "kv_store:distributeddb", + "kv_store:datamgr_common", + "kv_store:distributeddb_client", "samgr:samgr_proxy", "sqlite:sqlite", "sqlite:sqliteicu", @@ -211,7 +213,6 @@ if (is_ohos && !build_ohos_sdk) { "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", "${relational_store_native_path}/rdb/src/task_executor.cpp", - "${relational_store_native_path}/rdb_device_manager_adapter/src/rdb_device_manager_adapter.cpp", ] public_deps = [ @@ -220,18 +221,16 @@ if (is_ohos && !build_ohos_sdk) { ] external_deps = [ - "ability_base:zuri", - "ability_runtime:dataobs_manager", - "access_token:libaccesstoken_sdk", "c_utils:utils", - "device_manager:devicemanagersdk", + "file_api:securitylabel", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", - "huks:libhukssdk", "ipc:ipc_core", + "json:nlohmann_json_static", "kv_store:database_utils", - "kv_store:distributeddb", + "kv_store:datamgr_common", + "kv_store:distributeddb_client", "samgr:samgr_proxy", "sqlite:sqlite", "sqlite:sqliteicu", @@ -248,6 +247,7 @@ if (is_ohos && !build_ohos_sdk) { include_dirs = [ "${relational_store_mock_path}/frameworks/native/rdb", + "${relational_store_mock_path}/frameworks/native/rdb/common", "${relational_store_mock_path}/frameworks/native/win32", "mock/include", "${relational_store_common_path}/include", @@ -255,8 +255,10 @@ if (is_ohos && !build_ohos_sdk) { "//commonlibrary/c_utils/base/include", "include", "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "${relational_store_native_path}/rdb_crypt", "${relational_store_native_path}/rdb/include", "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", "//third_party/libuv/src/win", ] @@ -273,6 +275,7 @@ if (is_ohos && !build_ohos_sdk) { include_dirs += [ "//foundation/distributeddatamgr/kv_store/frameworks/common", "//third_party/sqlite/include", + "//third_party/json/single_include", ] libs = [ "//prebuilts/mingw-w64/ohos/linux-x86_64/clang-mingw/x86_64-w64-mingw32/lib/libws2_32.a" ] } @@ -304,6 +307,7 @@ if (is_ohos && !build_ohos_sdk) { deps = [ "${relational_store_innerapi_path}/appdatafwk:relational_common_base", "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_windows", + "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner_executor", "//third_party/sqlite:sqlite_sdk", ] @@ -327,6 +331,7 @@ if (is_ohos && !build_ohos_sdk) { deps = [ "${relational_store_innerapi_path}/appdatafwk:relational_common_base", "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_windows", + "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner_executor", "//third_party/sqlite:sqlite_sdk", ] cflags_cc = [ "-std=c++17" ] @@ -342,14 +347,17 @@ if (is_ohos && !build_ohos_sdk) { include_dirs = [ "${relational_store_mock_path}/frameworks/native/rdb", + "${relational_store_mock_path}/frameworks/native/rdb/common", "mock/include", "${relational_store_common_path}/include", "${relational_store_native_path}/rdb/mock/include", "//commonlibrary/c_utils/base/include", "include", "//foundation/communication/ipc/interfaces/innerkits/ipc_core/include", + "${relational_store_native_path}/rdb_crypt", "${relational_store_native_path}/rdb/include", "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", ] cflags = [ "-includemock.h" ] @@ -365,6 +373,7 @@ if (is_ohos && !build_ohos_sdk) { include_dirs += [ "//foundation/distributeddatamgr/kv_store/frameworks/common", "//third_party/sqlite/include", + "//third_party/json/single_include", ] } @@ -393,6 +402,7 @@ if (is_ohos && !build_ohos_sdk) { deps = [ "${relational_store_innerapi_path}/appdatafwk:relational_common_base", "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_mac", + "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner_executor", "//third_party/sqlite:sqlite_sdk", ] cflags_cc = [ "-std=c++17" ] @@ -415,6 +425,7 @@ if (is_ohos && !build_ohos_sdk) { deps = [ "${relational_store_innerapi_path}/appdatafwk:relational_common_base", "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_mac", + "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner_executor", "//third_party/sqlite:sqlite_sdk", ] cflags_cc = [ "-std=c++17" ] @@ -430,13 +441,16 @@ if (is_ohos && !build_ohos_sdk) { include_dirs = [ "${relational_store_mock_path}/frameworks/native/rdb", + "${relational_store_mock_path}/frameworks/native/rdb/common", "${distributedfile_path}/mod_securitylabel", "${relational_store_common_path}/include", "${relational_store_innerapi_path}/rdb/mock/include", "${relational_store_native_path}/rdb/mock/include", "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/rdb_crypt", "${relational_store_native_path}/rdb/include", "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", ] cflags = [ "-includemock.h" ] @@ -455,9 +469,11 @@ if (is_ohos && !build_ohos_sdk) { "${relational_store_native_path}/mock/rdb/include", "${relational_store_native_path}/rdb/include", "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", "../cloud_data/include", "../common_type/include", "//commonlibrary/c_utils/base/include", + "//third_party/json/single_include", ] } @@ -481,6 +497,7 @@ if (is_ohos && !build_ohos_sdk) { deps = [ "${relational_store_innerapi_path}/appdatafwk:relational_common_base", "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_android", + "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner_executor", "//third_party/sqlite:sqlite_static", ] cflags_cc = [ "-std=c++17" ] @@ -494,13 +511,16 @@ if (is_ohos && !build_ohos_sdk) { include_dirs = [ "${relational_store_mock_path}/frameworks/native/rdb", + "${relational_store_mock_path}/frameworks/native/rdb/common", "${distributedfile_path}/mod_securitylabel", "${relational_store_common_path}/include", "${relational_store_innerapi_path}/rdb/mock/include", "${relational_store_native_path}/rdb/mock/include", "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/rdb_crypt", "${relational_store_native_path}/rdb/include", "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", ] cflags = [ "-includemock.h" ] @@ -518,9 +538,11 @@ if (is_ohos && !build_ohos_sdk) { "include", "${relational_store_native_path}/rdb/include", "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", "../cloud_data/include", "../common_type/include", "//commonlibrary/c_utils/base/include", + "//third_party/json/single_include", ] } @@ -543,6 +565,7 @@ if (is_ohos && !build_ohos_sdk) { deps = [ "${relational_store_innerapi_path}/appdatafwk:relational_common_base", "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_ios", + "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_inner_executor", "//third_party/sqlite:sqlite_static", ] diff --git a/relational_store/interfaces/inner_api/rdb/include/abs_predicates.h b/relational_store/interfaces/inner_api/rdb/include/abs_predicates.h index 104f3c07..47bfa0ef 100644 --- a/relational_store/interfaces/inner_api/rdb/include/abs_predicates.h +++ b/relational_store/interfaces/inner_api/rdb/include/abs_predicates.h @@ -45,7 +45,6 @@ public: BUTT }; - API_EXPORT std::string GetStatement() const; API_EXPORT std::string GetWhereClause() const; API_EXPORT void SetWhereClause(const std::string &whereClause); [[deprecated("Use GetBindArgs() instead.")]] @@ -64,6 +63,7 @@ public: API_EXPORT bool IsNeedAnd() const; API_EXPORT bool IsSorted() const; API_EXPORT bool HasSpecificField() const; + API_EXPORT std::string GetHaving() const; public: API_EXPORT virtual void Clear(); @@ -82,6 +82,7 @@ public: API_EXPORT virtual AbsPredicates *Like(const std::string &field, const std::string &value); API_EXPORT virtual AbsPredicates *NotLike(const std::string &field, const std::string &value); API_EXPORT virtual AbsPredicates *Glob(const std::string &field, const std::string &value); + API_EXPORT virtual AbsPredicates *NotGlob(const std::string &field, const std::string &value); API_EXPORT virtual AbsPredicates *Between( const std::string &field, const ValueObject &low, const ValueObject &high); API_EXPORT virtual AbsPredicates *NotBetween( @@ -104,6 +105,9 @@ public: [[deprecated("Use NotIn(const std::string &, const std::vector &) instead.")]] API_EXPORT virtual AbsPredicates *NotIn(const std::string &field, const std::vector &values); API_EXPORT virtual AbsPredicates *NotIn(const std::string &field, const std::vector &values); + API_EXPORT virtual AbsPredicates *Having( + const std::string &conditions, const std::vector &values = {}); + API_EXPORT virtual std::string GetStatement() const; private: static constexpr const char *LOG_ORIGIN_FIELD = "#_flag"; @@ -113,6 +117,7 @@ private: std::string order; std::string group; std::string index; + std::string havingClause; int limit; int offset; bool distinct; diff --git a/relational_store/interfaces/inner_api/rdb/include/abs_rdb_predicates.h b/relational_store/interfaces/inner_api/rdb/include/abs_rdb_predicates.h index b99b5c99..05694fb3 100644 --- a/relational_store/interfaces/inner_api/rdb/include/abs_rdb_predicates.h +++ b/relational_store/interfaces/inner_api/rdb/include/abs_rdb_predicates.h @@ -49,7 +49,7 @@ public: API_EXPORT ~AbsRdbPredicates() override {} /** - * @brief Initalzie AbsRdbPredicates object. + * @brief Clear AbsRdbPredicates object. */ API_EXPORT void Clear() override; @@ -213,6 +213,13 @@ public: */ API_EXPORT AbsRdbPredicates *Glob(const std::string &field, const std::string &value) override; + /** + * @brief Adds an Glob condition to the remote AbsRdbPredicates. + * + * This method is similar to glob of the SQL statement. + */ + API_EXPORT AbsRdbPredicates *NotGlob(const std::string &field, const std::string &value) override; + /** * @brief Adds an Distinct condition to the remote AbsRdbPredicates. * @@ -313,6 +320,8 @@ public: */ API_EXPORT virtual void SetJoinCount(int joinCount); + API_EXPORT std::string GetStatement() const override; + static constexpr const char *LOCK_STATUS = "#_status"; static constexpr int LOCKED = 2; static constexpr int LOCK_CHANGED = 3; diff --git a/relational_store/interfaces/inner_api/rdb/include/cache_result_set.h b/relational_store/interfaces/inner_api/rdb/include/cache_result_set.h index 219637c3..49298201 100644 --- a/relational_store/interfaces/inner_api/rdb/include/cache_result_set.h +++ b/relational_store/interfaces/inner_api/rdb/include/cache_result_set.h @@ -41,6 +41,10 @@ namespace NativeRdb { */ class API_EXPORT CacheResultSet : public ResultSet { public: + /** + * @brief Constructor. + */ + API_EXPORT CacheResultSet(); /** * @brief Constructor. */ diff --git a/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h b/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h index 7d313863..7238f001 100644 --- a/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h +++ b/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h @@ -60,12 +60,18 @@ enum class IResultSetInterfaceCode { enum class KvStoreInterfaceCode { GET_FEATURE_INTERFACE = 0, REGISTER_DEATH_OBSERVER, + FEATURE_EXIT = 3, }; enum class CloudKvStoreInterfaceCode { GET_FEATURE_INTERFACE = 0 }; +enum class ICloudNotifierInterfaceCode { + CLOUD_NOTIFIER_CMD_SYNC_COMPLETE = 0, + CLOUD_NOTIFIER_CMD_MAX +}; + enum class RdbServiceInterfaceCode { RDB_SERVICE_CMD_OBTAIN_TABLE, RDB_SERVICE_CMD_INIT_NOTIFIER, diff --git a/relational_store/interfaces/inner_api/rdb/include/knowledge_types.h b/relational_store/interfaces/inner_api/rdb/include/knowledge_types.h new file mode 100644 index 00000000..a4079f41 --- /dev/null +++ b/relational_store/interfaces/inner_api/rdb/include/knowledge_types.h @@ -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. + */ + +#ifndef DISTRIBUTED_RDB_KNOWLEDGE_TYPES_H +#define DISTRIBUTED_RDB_KNOWLEDGE_TYPES_H + +#include +#include +#include +#include "rdb_store_config.h" + +namespace OHOS::DistributedRdb { + +constexpr int DEFAULT_CHUNK_SIZE = 3072; +constexpr int DEFAULT_SEGMENT_SIZE = 300; +constexpr double DEFAULT_OVERLAP_RATIO = 0.1; +constexpr int DEFAULT_TEXT_EMBEDDING_MAX_CNT = 50; +constexpr int DEFAULT_IMAGE_EMBEDDING_MAX_CNT = 10; +constexpr int DEFAULT_PARSE_FILE_MAX_CNT = 10; + +struct RdbKnowledgeParser { + std::string type; + std::string path; +}; + +struct RdbKnowledgeField { + std::string columnName; + std::vector type; + std::vector parser; + std::string description; +}; + +struct RdbKnowledgeTable { + std::string tableName; + std::string tokenizer; + std::vector referenceFields; + std::vector knowledgeFields; + std::unordered_map> pipelineHandlers; +}; + +struct RdbKnowledgeProcess { + struct { + std::string modelVersion; + } embeddingModelCfgs; + struct { + int chunkSize{DEFAULT_CHUNK_SIZE}; + int segmentSize{DEFAULT_SEGMENT_SIZE}; + double overlapRatio{DEFAULT_OVERLAP_RATIO}; + } chunkSplitter; + struct { + int textEmbeddingMaxCnt{DEFAULT_TEXT_EMBEDDING_MAX_CNT}; + int imageEmbeddingMaxCnt{DEFAULT_IMAGE_EMBEDDING_MAX_CNT}; + int parseFileMaxCnt{DEFAULT_PARSE_FILE_MAX_CNT}; + } perRecordLimit; +}; + +struct RdbKnowledgeSchema { + int64_t version = 0; + std::string dbName; + std::vector tables; + RdbKnowledgeProcess knowledgeProcess; +}; + +class API_EXPORT IKnowledgeSchemaManager { +public: + API_EXPORT virtual ~IKnowledgeSchemaManager() = default; + + /** + * @brief Init with database config and schema. + */ + API_EXPORT virtual void Init(const NativeRdb::RdbStoreConfig &config, + const DistributedRdb::RdbKnowledgeSchema &schema) = 0; + + /** + * @brief Start build knowledge data task. + */ + API_EXPORT virtual void StartTask(const std::string &dbName) = 0; + + /** + * @brief Stop build knowledge data task. + */ + API_EXPORT virtual void StopTask(const std::string &dbName) = 0; + + /** + * @brief Get rdb knowledge schema. + */ + API_EXPORT virtual std::shared_ptr GetRdbKnowledgeSchema(const std::string &dbName) = 0; +}; +} +#endif // DISTRIBUTED_RDB_KNOWLEDGE_TYPES_H \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_common.h b/relational_store/interfaces/inner_api/rdb/include/rdb_common.h index f2897ee3..16383629 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_common.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_common.h @@ -42,16 +42,17 @@ enum RebuiltType : uint32_t { enum SlaveStatus : uint32_t { UNDEFINED, - DB_NOT_EXITS, BACKING_UP, BACKUP_INTERRUPT, BACKUP_FINISHED, + DB_CLOSING, }; enum ExchangeStrategy : uint32_t { NOT_HANDLE, BACKUP, RESTORE, + PENDING_BACKUP, }; } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h b/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h index 04beefee..c15e6b0a 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h @@ -406,7 +406,7 @@ static constexpr int E_SQLITE_SCHEMA = (E_BASE + 0x48); static constexpr int E_CANCEL = (E_BASE + 0x49); /** - * @brief The key parameter is invalid. + * @brief The secret key is corrupted or lost. */ static constexpr int E_INVALID_SECRET_KEY = (E_BASE + 0x4a); @@ -425,46 +425,6 @@ static constexpr int E_INNER_WARNING = (E_BASE + 0x4c); */ static constexpr int E_SQLITE_NOT_DB = (E_BASE + 0x4d); -/** - * @brief The root key of the encrypted database is faulty. - */ -static constexpr int E_ROOT_KEY_FAULT = (E_BASE + 0x4e); - -/** - * @brief The root key of the encrypted database cannot be loaded. - */ -static constexpr int E_ROOT_KEY_NOT_LOAD = (E_BASE + 0x4f); - -/** - * @brief The working key of the encrypted database is faulty. - */ -static constexpr int E_WORK_KEY_FAIL = (E_BASE + 0x50); - -/** - * @brief Failed to encrypt the working key. - */ -static constexpr int E_WORK_KEY_ENCRYPT_FAIL = (E_BASE + 0x51); - -/** - * @brief Failed to decrypt the working key. - */ -static constexpr int E_WORK_KEY_DECRYPT_FAIL = (E_BASE + 0x52); - -/** - * @brief Failed to open the sqlite database using the working key. - */ -static constexpr int E_SET_ENCRYPT_FAIL = (E_BASE + 0x53); - -/** - * @brief Failed to open the sqlite database using the working new key. - */ -static constexpr int E_SET_NEW_ENCRYPT_FAIL = (E_BASE + 0x54); - -/** - * @brief Failed to open the sqlite database using the working service key. - */ -static constexpr int E_SET_SERVICE_ENCRYPT_FAIL = (E_BASE + 0x55); - /** * @brief Database WAL file check point failed. */ diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_helper.h b/relational_store/interfaces/inner_api/rdb/include/rdb_helper.h index bf425e1d..27526166 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_helper.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_helper.h @@ -72,6 +72,26 @@ public: * @return Returns {@code true} if the custom tokenizer is supported; returns {@code false} otherwise. */ API_EXPORT static bool IsSupportedTokenizer(Tokenizer tokenizer); + + struct DestroyOption { + bool cleanOpenSSL = false; + bool cleanICU = false; + }; + /** + * @brief initialization resources. + * + * @note Create pool initialization resources. + */ + API_EXPORT static bool Init(); + + /** + * @brief Clean up resources before dlclose. + * + * @note This interface is only used to release resources before calling dlclose, and can only be called before + * actually uninstalling rdb. Please manually release all resources obtained from rdb (rdbStore, resultSet, + * transaction, etc.) before calling, and then dlopen again to use them normally + */ + API_EXPORT static bool Destroy(const DestroyOption &option = { false, false }); }; } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_open_callback.h b/relational_store/interfaces/inner_api/rdb/include/rdb_open_callback.h index 7d309835..87c55dfc 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_open_callback.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_open_callback.h @@ -75,6 +75,11 @@ public: { return 0; } + + /** + * @brief Virtual destructor to ensure proper cleanup of derived class objects. + */ + virtual ~RdbOpenCallback() = default; }; } // namespace NativeRdb diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h index 0ff79324..fac04667 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h @@ -20,6 +20,7 @@ #include #include "distributeddata_relational_store_ipc_interface_code.h" +#include "iremote_object.h" #include "rdb_notifier.h" #include "rdb_types.h" #include "result_set.h" @@ -38,7 +39,8 @@ public: using ResultSet = NativeRdb::ResultSet; inline static constexpr const char *SERVICE_NAME = "relational_store"; - virtual std::string ObtainDistributedTableName(const std::string &device, const std::string &table) = 0; + virtual std::string ObtainDistributedTableName( + const RdbSyncerParam ¶m, const std::string &device, const std::string &table) = 0; virtual int32_t SetDistributedTables(const RdbSyncerParam ¶m, const std::vector &tables, const std::vector &references, bool isRebuild, int32_t type = DISTRIBUTED_DEVICE) = 0; @@ -47,10 +49,10 @@ public: const AsyncDetail &async) = 0; virtual int32_t Subscribe( - const RdbSyncerParam ¶m, const SubscribeOption &option, RdbStoreObserver *observer) = 0; + const RdbSyncerParam ¶m, const SubscribeOption &option, std::shared_ptr observer) = 0; virtual int32_t UnSubscribe( - const RdbSyncerParam ¶m, const SubscribeOption &option, RdbStoreObserver *observer) = 0; + const RdbSyncerParam ¶m, const SubscribeOption &option, std::shared_ptr observer) = 0; virtual int32_t RegisterAutoSyncCallback( const RdbSyncerParam ¶m, std::shared_ptr observer) = 0; @@ -95,6 +97,8 @@ public: virtual int32_t VerifyPromiseInfo(const RdbSyncerParam ¶m) = 0; virtual int32_t ReportStatistic(const RdbSyncerParam ¶m, const RdbStatEvent &statEvent) = 0; + + virtual ~RdbService() = default; }; } // namespace DistributedRdb } // namespace OHOS diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_sql_utils.h b/relational_store/interfaces/inner_api/rdb/include/rdb_sql_utils.h index fb5475c9..038bd142 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_sql_utils.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_sql_utils.h @@ -15,10 +15,27 @@ #ifndef NATIVE_RDB_SQL_UTILS_H #define NATIVE_RDB_SQL_UTILS_H +#include +#include #include "abs_rdb_predicates.h" +#include "rdb_common.h" +#include "rdb_predicates.h" +#include "values_bucket.h" +#include "value_object.h" namespace OHOS { namespace NativeRdb { +struct SqlInfo { + std::string sql; + std::vector args; +}; + +using Values = std::vector; +using Row = ValuesBucket; +using Rows = std::vector; +using Fields = std::vector; +using Resolution = ConflictResolution; + class API_EXPORT RdbSqlUtils { public: /** @@ -47,6 +64,13 @@ public: * @brief build query sql string. */ static std::string BuildQueryString(const AbsRdbPredicates &predicates, const std::vector &columns); + + static std::pair GetInsertSqlInfo(const std::string &table, const Row &row, Resolution resolution); + static std::pair GetUpdateSqlInfo(const AbsRdbPredicates &predicates, const Row &row, + Resolution resolution, const std::vector &returningFields = {}); + static std::pair GetDeleteSqlInfo( + const AbsRdbPredicates &predicates, const std::vector &returningFields = {}); + static std::pair GetQuerySqlInfo(const AbsRdbPredicates &predicates, const Fields &columns); }; } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_store.h b/relational_store/interfaces/inner_api/rdb/include/rdb_store.h index 03f56597..6dc11821 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_store.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_store.h @@ -28,6 +28,7 @@ #include "rdb_errno.h" #include "rdb_store_config.h" #include "rdb_types.h" +#include "knowledge_types.h" #include "result_set.h" #include "transaction.h" #include "value_object.h" @@ -80,6 +81,11 @@ public: */ using DetailProgressObserver = DistributedRdb::DetailProgressObserver; + /** + * @brief Use RdbKnowledgeSchema replace DistributedRdb::RdbKnowledgeSchema namespace. + */ + using RdbKnowledgeSchema = DistributedRdb::RdbKnowledgeSchema; + /** * @brief Use Date replace DistributedRdb::Date namespace. */ @@ -204,8 +210,23 @@ public: * @param values Indicates the rows of data {@link ValuesBuckets} to be inserted into the table. * @param resolution Indicates the {@link ConflictResolution} to insert data into the table. */ - virtual std::pair BatchInsertWithConflictResolution( - const std::string &table, const RefRows &rows, Resolution resolution); + virtual std::pair BatchInsert(const std::string &table, const RefRows &rows, Resolution resolution); + + /** + * @brief Inserts a batch of data into the target table. + * + * @param table Indicates the target table. + * @param rows Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param returningFields Indicates the returning fields. + * @param resolution Indicates the {@link ConflictResolution} to insert data into the table. + * @return Return the inserted result. Contains error codes, affected rows, + * and returningField values for inserting data + * @warning 1. When using returningField, it is not recommended to use the ON_CONFLICT_FAIL strategy. This will + * result in returned results that do not match expectations. 2.When the number of affected rows exceeds 1024, + * only the first 1024 returningFields will be returned + */ + virtual std::pair BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution = NO_ACTION); /** * @brief Updates data in the database based on specified conditions. @@ -240,6 +261,23 @@ public: */ virtual int Update(int &changedRows, const Row &row, const AbsRdbPredicates &predicates); + /** + * @brief Updates data in the database based on a a specified instance object of AbsRdbPredicates. + * + * @param row Indicates the row of data to be updated in the database. + * The key-value pairs are associated with column names of the database table. + * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. + * @param returningFields Indicates the returning fields. + * @param resolution Indicates the {@link ConflictResolution} to insert data into the table. + * @return Return the updated result. Contains error code, number of affected rows, + * and value of returningField after update + * @warning 1. When using returningField, it is not recommended to use the ON_CONFLICT_FAIL strategy. This will + * result in returned results that do not match expectations. 2.When the number of affected rows exceeds 1024, + * only the first 1024 returningFields will be returned + */ + virtual std::pair Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution = NO_ACTION); + /** * @brief Updates data in the database based on specified conditions. * @@ -306,8 +344,19 @@ public: * @param args Indicates the where arguments. */ virtual int Delete( - int &deletedRows, const std::string &table, const std::string &whereClause = "", const Values &args = {}) = 0; + int &deletedRows, const std::string &table, const std::string &whereClause = "", const Values &args = {}); + /** + * @brief Deletes data from the database based on a specified instance object of AbsRdbPredicates. + * + * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. + * @param returningFields Indicates the returning fields. + * @return Return the deleted result. Contains error code, number of affected rows, + * and value of returningField before delete + * @warning When the number of affected rows exceeds 1024, only the first 1024 returningFields will be returned. + */ + virtual std::pair Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields = {}); /** * @brief Queries data in the database based on specified conditions. * @@ -366,7 +415,7 @@ public: * * @param sql Indicates the SQL statement to execute. * @param args Indicates the selection arguments. - * @param preCount IIndicates whether to calculate the count during query. + * @param preCount Indicates whether to calculate the count during query. */ virtual std::shared_ptr QueryByStep(const std::string &sql, const Values &args = {}, bool preCount = true) = 0; @@ -376,7 +425,7 @@ public: * * @param predicates Indicates the specified query condition by the instance object of {@link AbsRdbPredicates}. * @param columns Indicates the columns to query. If the value is empty array, the query applies to all columns. - * @param preCount IIndicates whether to calculate the count during query. + * @param preCount Indicates whether to calculate the count during query. */ virtual std::shared_ptr QueryByStep(const AbsRdbPredicates &predicates, const Fields &columns = {}, bool preCount = true); @@ -418,6 +467,17 @@ public: */ virtual std::pair Execute(const std::string &sql, const Values &args = {}, int64_t trxId = 0); + /** + * @brief Executes an SQL statement that contains specified parameters and + * get two values of type int and ValueObject. + * + * @param sql Indicates the SQL statement to execute. + * @param returningField Indicates the fieldName of result. + * @param args Indicates the {@link ValueObject} values of the parameters in the SQL statement. + * @return Return the result. Contains error code, number of affected rows, and value of returningField + */ + virtual std::pair ExecuteExt(const std::string &sql, const Values &args = {}); + /** * @brief Executes an SQL statement that contains specified parameters and get a long integer value. * @@ -460,6 +520,15 @@ public: */ virtual int Backup(const std::string &databasePath, const std::vector &encryptKey = {}); + /** + * @brief Restores a database from a specified encrypted or unencrypted database file. + * + * @param databasePath Indicates the database file path. + * @param encryptKey Indicates the database encrypt key. + * @param verifyDb Indicates whether to check the integrity of the database. + */ + virtual int Backup(const std::string &databasePath, const std::vector &encryptKey, bool verifyDb); + /** * @brief Attaches a database. * @@ -538,6 +607,13 @@ public: */ virtual bool IsReadOnly() const; + /** + * @brief Changes the key used to encrypt the database. + * + * @param Crypto parameters + */ + virtual int32_t Rekey(const RdbStoreConfig::CryptoParam &cryptoParam); + /** * @brief Check the current database is memory database. */ @@ -597,12 +673,12 @@ public: /** * @brief Subscribe to event changes. */ - virtual int Subscribe(const SubscribeOption &option, RdbStoreObserver *observer); + virtual int Subscribe(const SubscribeOption &option, std::shared_ptr observer); /** * @brief UnSubscribe to event changes. */ - virtual int UnSubscribe(const SubscribeOption &option, RdbStoreObserver *observer); + virtual int UnSubscribe(const SubscribeOption &option, std::shared_ptr observer); /** * @brief SubscribeObserver to event changes. @@ -702,6 +778,26 @@ public: */ virtual int SetSearchable(bool isSearchable); + virtual int CleanDirtyLog(const std::string &table, uint64_t cursor = 0); + + virtual int InitKnowledgeSchema(const RdbKnowledgeSchema &schema); + + /** + * @brief Support for collations in different languages. + * + * @param locale Represents Language related to the locale, for example, zh. + * The value complies with the ISO 639 standard. + */ + virtual int ConfigLocale(const std::string &localeStr); + + /** + * @brief Register a customized cluster algo to db + * + * @param clstAlgoName name of function + * @param func ptr of function + */ + virtual int RegisterAlgo(const std::string &clstAlgoName, ClusterAlgoFunc func); + protected: virtual std::string GetLogTableName(const std::string &tableName); }; diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h b/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h index 56416e4b..d3e4a677 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h @@ -218,20 +218,20 @@ public: bool Get(RegisterType type) { uint8_t bit = type % sizeof(uint8_t); - std::lock_guard LockGuard(mutex_); + std::lock_guard lockGuard(mutex_); return (1 << bit) & info_; } void Set(RegisterType type, bool state) { uint8_t bit = type % sizeof(uint8_t); - std::lock_guard LockGuard(mutex_); + std::lock_guard lockGuard(mutex_); info_ |= 1 << bit; } bool operator==(const RegisterInfo& info) { - std::lock_guard LockGuard(mutex_); + std::lock_guard lockGuard(mutex_); return info_ == info.info_; } private: @@ -239,6 +239,32 @@ private: std::mutex mutex_; }; +struct CollatorLocales { + CollatorLocales() + { + locales_ = ""; + } + explicit CollatorLocales(const CollatorLocales &collatorLocales) + { + locales_ = collatorLocales.Get(); + } + std::string Get() const + { + std::lock_guard lockGuard(localesMutex_); + return locales_; + } + + void Set(const std::string &locales) + { + std::lock_guard lockGuard(localesMutex_); + locales_ = locales; + } + +private: + std::string locales_; + mutable std::mutex localesMutex_; +}; + /** * @brief Use DistributedType replace OHOS::DistributedRdb::RdbDistributedType. */ @@ -262,6 +288,30 @@ struct PromiseInfo { std::vector permissionNames_ = {}; }; +struct ClstAlgoParaT { + /* Input Parameters */ + uint16_t featureDim; // Feature vector dimension, currently supports 256D only + uint32_t oldFeaturesNum; // Number of historical cluster center vectors + float *oldFeatures; // Array of historical cluster center vectors, + // stored in row-major order (length: oldFeaturesNum * dim) + const int32_t *oldClstGroupId; // Cluster ID for each historical vector (length: oldFeaturesNum) + const int32_t *oldClstVecNum; // Number of vectors in each historical cluster (length: oldFeaturesNum) + + uint32_t newFeaturesNum; // Number of newly collected vectors + float *newFeatures; // Array of new feature vectors + // stored in row-major order (length: newFeaturesNum * dim) + int32_t newClusterIdStart; // Starting cluster ID for new clusters, usually the maximum old cluster ID plus one + + /* Customization Parameters */ + void *customParams; // Developers need to communicate with the database development team before using it + + /* Output Parameters */ + int32_t *clusterResult; // Clustering result array, indicating the assigned cluster ID for each new vector + // (length: newFeaturesNum) +}; + +using ClusterAlgoFunc = int32_t (*)(ClstAlgoParaT *para); + /** * Manages relational database configurations. */ @@ -280,6 +330,12 @@ public: API_EXPORT CryptoParam(); API_EXPORT ~CryptoParam(); API_EXPORT bool IsValid() const; + bool Equal(const CryptoParam &other) const + { + bool baseEqual = encryptAlgo == other.encryptAlgo && hmacAlgo == other.hmacAlgo && + kdfAlgo == other.kdfAlgo && cryptoPageSize == other.cryptoPageSize; + return (other.iterNum == 0) ? baseEqual : (iterNum == other.iterNum && baseEqual); + } }; /** @@ -562,6 +618,8 @@ public: void RestoreEncryptKey(const std::vector &encryptKey) const; + void ResetEncryptKey(const std::vector &encryptKey) const; + /** * @brief Obtains the encrypt key in this {@code StoreConfig} object. */ @@ -615,7 +673,7 @@ public: /** * @brief Obtains the cryptoParam field in this {@code StoreConfig} object. */ - bool IsLocalOnly() const; + bool IsCustomEncryptParam() const; /** * @brief Set the isVector field in this {@code StoreConfig} object. @@ -748,7 +806,7 @@ public: std::string GetCollatorLocales() const; - void SetCollatorLocales(const std::string &loacles); + void SetCollatorLocales(const std::string &locales) const; int32_t GetHaMode() const; @@ -768,10 +826,6 @@ public: void EnableRekey(bool enable); - int GetNcandidates() const; - - void SetNcandidates(int ncandidates); - std::string ToString() const; static std::string FormatCfg(const RdbStoreConfig &first, const RdbStoreConfig &second); @@ -781,6 +835,10 @@ public: bool GetRegisterInfo(RegisterType type) const; bool IsEqualRegisterInfo(const RdbStoreConfig& config) const; + + void SetEnableSemanticIndex(bool enableSemanticIndex); + + bool GetEnableSemanticIndex() const; private: void ClearEncryptKey(); int32_t GenerateEncryptedKey() const; @@ -793,7 +851,8 @@ private: bool isAutoClean_ = true; bool isVector_ = false; bool autoRekey_ = false; - bool localOnly_ = false; + bool customEncryptParam_ = false; + bool enableSemanticIndex_ = false; int32_t journalSize_; int32_t pageSize_; int32_t readConSize_ = 4; @@ -819,7 +878,7 @@ private: ssize_t checkpointSize_; ssize_t startCheckpointSize_; int32_t clearMemorySize_; - std::string loacles_; + mutable CollatorLocales collatorLocales_; // distributed rdb std::string bundleName_; std::string moduleName_; @@ -829,7 +888,6 @@ private: mutable std::vector newEncryptKey_{}; std::map customScalarFunctions_; std::vector pluginLibs_{}; - int ncandidates_ = 128; static constexpr int MAX_TIMEOUT = 300; // seconds static constexpr int MIN_TIMEOUT = 1; // seconds diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h index 2f2d68f5..c3b0bc16 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h @@ -24,7 +24,10 @@ #include #include -namespace OHOS::DistributedRdb { +#include "values_buckets.h" + +namespace OHOS { +namespace DistributedRdb { enum RdbStatus { RDB_OK, RDB_ERROR, @@ -231,6 +234,7 @@ enum RdbPredicateOperator { NOT_CONTAINS, NOT_LIKE, ASSETS_ONLY, + NOT_GLOB, OPERATOR_MAX }; @@ -371,6 +375,7 @@ struct Field { struct RdbChangeProperties { bool isTrackedDataChange = false; bool isP2pSyncDataChange = false; + bool isKnowledgeDataChange = false; }; struct RdbChangedData { @@ -389,5 +394,27 @@ public: virtual ~SqlObserver() = default; virtual void OnStatistic(const SqlExecutionInfo &info) = 0; }; -} // namespace OHOS::DistributedRdb + +class SqlErrorObserver { +public: + struct ExceptionMessage { + int32_t code = 0; + std::string message; + std::string sql; + }; + virtual ~SqlErrorObserver() = default; + virtual void OnErrorLog(const ExceptionMessage &message) = 0; +}; +} // namespace DistributedRdb +namespace NativeRdb { +class ResultSet; +struct Results { + Results(int32_t count) : changed(count) + { + } + int32_t changed = -1; + std::shared_ptr results; +}; +} // namespace NativeRdb +} // namespace OHOS #endif \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/include/task_executor.h b/relational_store/interfaces/inner_api/rdb/include/task_executor.h similarity index 79% rename from relational_store/frameworks/native/rdb/include/task_executor.h rename to relational_store/interfaces/inner_api/rdb/include/task_executor.h index 4f3d8d27..ee89412b 100644 --- a/relational_store/frameworks/native/rdb/include/task_executor.h +++ b/relational_store/interfaces/inner_api/rdb/include/task_executor.h @@ -15,7 +15,10 @@ #ifndef DISTRIBUTED_NATIVE_RDB_TASK_EXECUTOR_H #define DISTRIBUTED_NATIVE_RDB_TASK_EXECUTOR_H #include "executor_pool.h" -namespace OHOS::NativeRdb { +#include "rdb_visibility.h" +namespace OHOS { +//class ExecutorPool; +namespace NativeRdb { class TaskExecutor { public: using TaskId = ExecutorPool::TaskId; @@ -23,17 +26,20 @@ public: using Duration = std::chrono::steady_clock::duration; static constexpr TaskId INVALID_TASK_ID = ExecutorPool::INVALID_TASK_ID; - static TaskExecutor &GetInstance(); + API_EXPORT static TaskExecutor &GetInstance(); std::shared_ptr GetExecutor(); - void SetExecutor(std::shared_ptr executor); + API_EXPORT void SetExecutor(std::shared_ptr executor); + void Init(); + bool Stop(); private: size_t MAX_THREADS = 2; size_t MIN_THREADS = 0; TaskExecutor(); ~TaskExecutor(); - mutable std::shared_mutex rwMutex_; + std::mutex mutex_; std::shared_ptr pool_; }; -} // namespace OHOS::NativeRdb +} // namespace NativeRdb +} // namespace OHOS #endif // DISTRIBUTED_DATA_TASK_EXECUTOR_H diff --git a/relational_store/interfaces/inner_api/rdb/include/transaction.h b/relational_store/interfaces/inner_api/rdb/include/transaction.h index 04563e9b..eb880447 100644 --- a/relational_store/interfaces/inner_api/rdb/include/transaction.h +++ b/relational_store/interfaces/inner_api/rdb/include/transaction.h @@ -77,7 +77,7 @@ public: int32_t type, std::shared_ptr connection, const std::string &)>; static std::pair> Create( - int32_t type, std::shared_ptr connection, const std::string &name); + int32_t type, std::shared_ptr connection, const std::string &path); static int32_t RegisterCreator(Creator creator); virtual ~Transaction() = default; @@ -119,9 +119,24 @@ public: * @param rows Indicates the rows of data {@link RefRows} to be inserted into the table. * @param resolution Indicates the {@link ConflictResolution} to insert data into the table. */ - virtual std::pair BatchInsertWithConflictResolution( - const std::string &table, const RefRows &rows, Resolution resolution) = 0; + virtual std::pair BatchInsert( + const std::string &table, const RefRows &rows, Resolution resolution); + /** + * @brief Inserts a batch of data into the target table. + * + * @param table Indicates the target table. + * @param rows Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param returningFields Indicates the returning fields. + * @param resolution Indicates the {@link ConflictResolution} to insert data into the table. + * @return Return the inserted result. Contains error codes, affected rows, + * and returningField values for inserting data + * @warning 1. When using returningField, it is not recommended to use the ON_CONFLICT_FAIL strategy. This will + * result in returned results that do not match expectations. 2.When the number of affected rows exceeds 1024, + * only the first 1024 returningFields will be returned + */ + virtual std::pair BatchInsert(const std::string &table, const RefRows &rows, + const std::vector &returningFields, Resolution resolution = NO_ACTION); /** * @brief Updates data in the database based on specified conditions. * @@ -132,7 +147,7 @@ public: * @param args Indicates the where arguments. */ virtual std::pair Update(const std::string &table, const Row &row, const std::string &where = "", - const Values &args = {}, Resolution resolution = NO_ACTION) = 0; + const Values &args = {}, Resolution resolution = NO_ACTION); /** * @brief Updates data in the database based on a a specified instance object of AbsRdbPredicates. @@ -142,7 +157,24 @@ public: * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. */ virtual std::pair Update( - const Row &row, const AbsRdbPredicates &predicates, Resolution resolution = NO_ACTION) = 0; + const Row &row, const AbsRdbPredicates &predicates, Resolution resolution = NO_ACTION); + + /** + * @brief Updates data in the database based on a a specified instance object of AbsRdbPredicates. + * + * @param row Indicates the row of data to be updated in the database. + * The key-value pairs are associated with column names of the database table. + * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. + * @param returningFields Indicates the returning fields. + * @param resolution Indicates the {@link ConflictResolution} to insert data into the table. + * @return Return the updated result. Contains error code, number of affected rows, + * and value of returningField after update + * @warning 1. When using returningField, it is not recommended to use the ON_CONFLICT_FAIL strategy. This will + * result in returned results that do not match expectations. 2.When the number of affected rows exceeds 1024, + * only the first 1024 returningFields will be returned + */ + virtual std::pair Update(const Row &row, const AbsRdbPredicates &predicates, + const std::vector &returningFields, Resolution resolution = NO_ACTION); /** * @brief Deletes data from the database based on specified conditions. @@ -152,21 +184,33 @@ public: * @param args Indicates the where arguments. */ virtual std::pair Delete( - const std::string &table, const std::string &whereClause = "", const Values &args = {}) = 0; + const std::string &table, const std::string &whereClause = "", const Values &args = {}); /** * @brief Deletes data from the database based on a specified instance object of AbsRdbPredicates. * * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. */ - virtual std::pair Delete(const AbsRdbPredicates &predicates) = 0; + virtual std::pair Delete(const AbsRdbPredicates &predicates); + + /** + * @brief Deletes data from the database based on a specified instance object of AbsRdbPredicates. + * + * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. + * @param returningFields Indicates the returning fields. + * @return Return the deleted result. Contains error code, number of affected rows, + * and value of returningField before delete + * @warning When the number of affected rows exceeds 1024, only the first 1024 returningFields will be returned. + */ + virtual std::pair Delete( + const AbsRdbPredicates &predicates, const std::vector &returningFields); /** * @brief Queries data in the database based on SQL statement. * * @param sql Indicates the SQL statement to execute. * @param args Indicates the selection arguments. - * @param preCount IIndicates whether to calculate the count during query. + * @param preCount Indicates whether to calculate the count during query. */ virtual std::shared_ptr QueryByStep(const std::string &sql, const Values &args = {}, bool preCount = true) = 0; @@ -176,7 +220,7 @@ public: * * @param predicates Indicates the specified query condition by the instance object of {@link AbsRdbPredicates}. * @param columns Indicates the columns to query. If the value is empty array, the query applies to all columns. - * @param preCount IIndicates whether to calculate the count during query. + * @param preCount Indicates whether to calculate the count during query. */ virtual std::shared_ptr QueryByStep(const AbsRdbPredicates &predicates, const Fields &columns = {}, bool preCount = true) = 0; @@ -188,7 +232,17 @@ public: * @param sql Indicates the SQL statement to execute. * @param args Indicates the {@link ValueObject} values of the parameters in the SQL statement. */ - virtual std::pair Execute(const std::string &sql, const Values &args = {}) = 0; + virtual std::pair Execute(const std::string &sql, const Values &args = {}); + + /** + * @brief Executes an SQL statement that contains specified parameters and + * get two values of type int and ValueObject. + * + * @param sql Indicates the SQL statement to execute. + * @param args Indicates the {@link ValueObject} values of the parameters in the SQL statement. + * @warning When the number of affected rows exceeds 1024, only the first 1024 returningFields will be returned. + */ + virtual std::pair ExecuteExt(const std::string &sql, const Values &args = {}); private: static inline Creator creator_; diff --git a/relational_store/interfaces/inner_api/rdb/include/values_bucket.h b/relational_store/interfaces/inner_api/rdb/include/values_bucket.h index f8250d76..0981de32 100644 --- a/relational_store/interfaces/inner_api/rdb/include/values_bucket.h +++ b/relational_store/interfaces/inner_api/rdb/include/values_bucket.h @@ -113,6 +113,14 @@ public: */ API_EXPORT void Put(const std::string &columnName, const ValueObject &value); + /** + * @brief Put the integer double bool string bytes asset asset and so on + * to this {@code ValuesBucket} object for the given column name. + * + * @param columnName Indicates the name of the column. + */ + API_EXPORT void Put(const std::string &columnName, ValueObject &&value); + /** * @brief Delete the ValueObject object for the given column name. * diff --git a/relational_store/interfaces/inner_api/rdb/include/values_buckets.h b/relational_store/interfaces/inner_api/rdb/include/values_buckets.h index e776b9fb..beb14605 100644 --- a/relational_store/interfaces/inner_api/rdb/include/values_buckets.h +++ b/relational_store/interfaces/inner_api/rdb/include/values_buckets.h @@ -34,13 +34,19 @@ public: using BucketType = std::map>; API_EXPORT ValuesBuckets(); + API_EXPORT ValuesBuckets(const std::vector &rows); + API_EXPORT ValuesBuckets(std::vector &&rows) noexcept; API_EXPORT size_t RowSize() const; API_EXPORT std::pair GetFieldsAndValues() const; + API_EXPORT void Reserve(int32_t size); API_EXPORT void Put(const ValuesBucket &bucket); + API_EXPORT void Put(ValuesBucket &&bucket); API_EXPORT std::pair Get(size_t row, const FieldType &field) const; + API_EXPORT void Clear(); + private: FieldsType fields_; ValuesType values_; diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h b/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h index a239f28f..8fd52182 100644 --- a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h +++ b/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h @@ -21,6 +21,10 @@ #include #include #include + +#include "rdb_types.h" +#include "rdb_visibility.h" + namespace OHOS::NativeRdb { enum class IntegrityCheck { NONE, @@ -128,20 +132,20 @@ public: bool Get(RegisterType type) { uint8_t bit = type % sizeof(uint8_t); - std::lock_guard LockGuard(mutex_); + std::lock_guard lockGuard(mutex_); return (1 << bit) & info_; } void Set(RegisterType type, bool state) { uint8_t bit = type % sizeof(uint8_t); - std::lock_guard LockGuard(mutex_); + std::lock_guard lockGuard(mutex_); info_ |= 1 << bit; } bool operator==(const RegisterInfo& info) { - std::lock_guard LockGuard(mutex_); + std::lock_guard lockGuard(mutex_); return info_ == info.info_; } private: @@ -149,6 +153,32 @@ private: std::mutex mutex_; }; +struct CollatorLocales { + CollatorLocales() + { + locales_ = ""; + } + explicit CollatorLocales(const CollatorLocales &collatorLocales) + { + locales_ = collatorLocales.Get(); + } + std::string Get() const + { + std::lock_guard lockGuard(localesMutex_); + return locales_; + } + + void Set(const std::string &locales) + { + std::lock_guard lockGuard(localesMutex_); + locales_ = locales; + } + +private: + std::string locales_; + mutable std::mutex localesMutex_; +}; + using ScalarFunction = std::function &)>; struct ScalarFunctionInfo { @@ -164,6 +194,30 @@ struct PromiseInfo { std::vector permissionNames_ = {}; }; +struct ClstAlgoParaT { + /* Input Parameters */ + uint16_t featureDim; // Feature vector dimension, currently supports 256D only + uint32_t oldFeaturesNum; // Number of historical cluster center vectors + float *oldFeatures; // Array of historical cluster center vectors, + // stored in row-major order (length: oldFeaturesNum * dim) + const int32_t *oldClstGroupId; // Cluster ID for each historical vector (length: oldFeaturesNum) + const int32_t *oldClstVecNum; // Number of vectors in each historical cluster (length: oldFeaturesNum) + + uint32_t newFeaturesNum; // Number of newly collected vectors + float *newFeatures; // Array of new feature vectors + // stored in row-major order (length: newFeaturesNum * dim) + int32_t newClusterIdStart; // Starting cluster ID for new clusters, usually the maximum old cluster ID plus one + + /* Customization Parameters */ + void *customParams; // Developers need to communicate with the database development team before using it + + /* Output Parameters */ + int32_t *clusterResult; // Clustering result array, indicating the assigned cluster ID for each new vector + // (length: newFeaturesNum) +}; + +using ClusterAlgoFunc = int32_t (*)(ClstAlgoParaT *para); + class RdbStoreConfig { public: struct CryptoParam { @@ -197,7 +251,7 @@ public: bool IsReadOnly() const; bool IsMemoryRdb() const; - bool IsLocalOnly() const; + bool IsCustomEncryptParam() const; std::string GetDatabaseFileType() const; SecurityLevel GetSecurityLevel() const; void SetEncryptStatus(const bool status); @@ -238,6 +292,7 @@ public: void SetReadConSize(int readConSize); void SetEncryptKey(const std::vector &encryptKey); void RestoreEncryptKey(const std::vector &encryptKey) const; + void ResetEncryptKey(const std::vector &encryptKey) const; std::vector GetEncryptKey() const; void ChangeEncryptKey() const; std::vector GetNewEncryptKey() const; @@ -313,7 +368,7 @@ public: int32_t GetClearMemorySize() const; void SetClearMemorySize(int32_t size); std::string GetCollatorLocales() const; - void SetCollatorLocales(const std::string &loacles); + void SetCollatorLocales(const std::string &locales) const; int32_t GetSubUser() const; void SetSubUser(int32_t subUser); void SetHaMode(int32_t haMode); @@ -322,13 +377,13 @@ public: CryptoParam GetCryptoParam() const; void SetJournalMode(const std::string &journalMode); void EnableRekey(bool enable); - int GetNcandidates() const; - void SetNcandidates(int ncandidates); std::string ToString() const; static std::string FormatCfg(const RdbStoreConfig &first, const RdbStoreConfig &second); void SetRegisterInfo(RegisterType type, bool state) const; bool GetRegisterInfo(RegisterType type) const; bool IsEqualRegisterInfo(const RdbStoreConfig& config) const; + void SetEnableSemanticIndex(bool enableSemanticIndex); + bool GetEnableSemanticIndex() const; private: void ClearEncryptKey(); @@ -342,7 +397,8 @@ private: bool isAutoClean_ = true; bool isVector_ = false; bool autoRekey_ = false; - bool localOnly_ = false; + bool customEncryptParam_ = false; + bool enableSemanticIndex_ = false; int32_t journalSize_; int32_t pageSize_; int32_t readConSize_ = 4; @@ -368,7 +424,7 @@ private: ssize_t checkpointSize_; ssize_t startCheckpointSize_; int32_t clearMemorySize_; - std::string loacles_; + mutable CollatorLocales collatorLocales_; // distributed rdb std::string bundleName_; std::string moduleName_; @@ -378,7 +434,6 @@ private: mutable std::vector newEncryptKey_{}; std::map customScalarFunctions_; std::vector pluginLibs_{}; - int ncandidates_ = 128; static constexpr int MAX_TIMEOUT = 300; // seconds static constexpr int MIN_TIMEOUT = 1; // seconds diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/values_bucket.h b/relational_store/interfaces/inner_api/rdb/mock/include/values_bucket.h index 5aea4009..904d632d 100644 --- a/relational_store/interfaces/inner_api/rdb/mock/include/values_bucket.h +++ b/relational_store/interfaces/inner_api/rdb/mock/include/values_bucket.h @@ -109,6 +109,14 @@ public: */ void Put(const std::string &columnName, const ValueObject &value); + /** + * @brief Put the integer double bool string bytes asset asset and so on + * to this {@code ValuesBucket} object for the given column name. + * + * @param columnName Indicates the name of the column. + */ + void Put(const std::string &columnName, ValueObject &&value); + /** * @brief Delete the ValueObject object for the given column name. * diff --git a/relational_store/interfaces/inner_api/rdb_data_ability_adapter/BUILD.gn b/relational_store/interfaces/inner_api/rdb_data_ability_adapter/BUILD.gn index 8fdebcc4..d55ed2d2 100644 --- a/relational_store/interfaces/inner_api/rdb_data_ability_adapter/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb_data_ability_adapter/BUILD.gn @@ -20,10 +20,8 @@ config("rdb_data_ability_adapter_config") { } include_dirs = [ "include", - "${datashare_path}/common/include/", "${relational_store_innerapi_path}/rdb/include", "${relational_store_native_path}/rdb/include", - "${common_tool_path}/", ] } @@ -57,7 +55,13 @@ ohos_shared_library("rdb_data_ability_adapter") { "${relational_store_innerapi_path}/rdb:native_rdb", ] - external_deps = [ "c_utils:utils" ] + external_deps = [ + "c_utils:utils", + "data_share:datashare_common_lite", + "ipc:ipc_single", + "json:nlohmann_json_static", + "kv_store:datamgr_common", + ] public_configs = [ ":rdb_data_ability_adapter_public_config" ] diff --git a/relational_store/interfaces/inner_api/rdb_data_share_adapter/BUILD.gn b/relational_store/interfaces/inner_api/rdb_data_share_adapter/BUILD.gn index 13a54411..71d2d856 100644 --- a/relational_store/interfaces/inner_api/rdb_data_share_adapter/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb_data_share_adapter/BUILD.gn @@ -22,12 +22,10 @@ config("rdb_data_share_adapter_config") { } include_dirs = [ "include", - "${datashare_path}/common/include/", "${relational_store_common_path}/include", "${relational_store_innerapi_path}/rdb/include", "${relational_store_native_path}/rdb_data_share_adapter/include", "${relational_store_native_path}/rdb/include", - "${common_tool_path}/", ] } @@ -35,7 +33,6 @@ config("rdb_data_share_adapter_public_config") { visibility = [ ":*" ] include_dirs = [ "include", - "${datashare_path}/provider/include", ] } @@ -63,7 +60,10 @@ ohos_shared_library("rdb_data_share_adapter") { external_deps = [ "c_utils:utils", + "data_share:datashare_common_lite", "hilog:libhilog", + "json:nlohmann_json_static", + "kv_store:datamgr_common", ] public_configs = [ ":rdb_data_share_adapter_public_config" ] diff --git a/relational_store/interfaces/inner_api/rdb_data_share_adapter/include/rdb_utils.h b/relational_store/interfaces/inner_api/rdb_data_share_adapter/include/rdb_utils.h index 00c37410..7d3986a9 100644 --- a/relational_store/interfaces/inner_api/rdb_data_share_adapter/include/rdb_utils.h +++ b/relational_store/interfaces/inner_api/rdb_data_share_adapter/include/rdb_utils.h @@ -155,7 +155,7 @@ RDB_UTILS_DISABLE_WARNING("-Wc99-designator") [DataShare::SQL_IN] = &RdbUtils::In, [DataShare::NOT_IN] = &RdbUtils::NotIn, [DataShare::LIKE] = &RdbUtils::Like, - [DataShare::UNLIKE] = &RdbUtils::NoSupport, + [DataShare::UNLIKE] = &RdbUtils::NotLike, [DataShare::ORDER_BY_ASC] = &RdbUtils::OrderByAsc, [DataShare::ORDER_BY_DESC] = &RdbUtils::OrderByDesc, [DataShare::LIMIT] = &RdbUtils::Limit, diff --git a/relational_store/frameworks/js/napi/graphstore/BUILD.gn b/relational_store/interfaces/ndk/BUILD.gn similarity index 38% rename from relational_store/frameworks/js/napi/graphstore/BUILD.gn rename to relational_store/interfaces/ndk/BUILD.gn index e970ce11..58c8261d 100644 --- a/relational_store/frameworks/js/napi/graphstore/BUILD.gn +++ b/relational_store/interfaces/ndk/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2024 Huawei Device Co., Ltd. +# Copyright (c) 2023 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -14,7 +14,8 @@ import("//build/ohos.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") -ohos_shared_library("graphstore") { +ohos_shared_library("native_rdb_ndk") { + branch_protector_ret = "pac_ret" sanitize = { boundary_sanitize = true ubsan = true @@ -22,42 +23,46 @@ ohos_shared_library("graphstore") { cfi_cross_dso = true debug = false } - cflags_cc = [ "-fvisibility=hidden" ] + include_dirs = [ + "include", + "${relational_store_base_path}/interfaces/ndk", "${relational_store_common_path}/include", - "${relational_store_frameworks_path}/js/napi/common/include", - "${relational_store_frameworks_path}/js/napi/graphstore/include", - "${relational_store_native_path}/gdb/include", "${relational_store_native_path}/rdb/include", + "${relational_store_native_path}/dfx/include", ] sources = [ - "${relational_store_frameworks_path}/js/napi/common/src/js_ability.cpp", - "${relational_store_frameworks_path}/js/napi/common/src/js_scope.cpp", - "${relational_store_frameworks_path}/js/napi/common/src/js_utils.cpp", - "${relational_store_frameworks_path}/js/napi/common/src/js_uv_queue.cpp", - "${relational_store_frameworks_path}/js/napi/graphstore/src/entry_point.cpp", - "${relational_store_frameworks_path}/js/napi/graphstore/src/napi_async_call.cpp", - "${relational_store_frameworks_path}/js/napi/graphstore/src/napi_gdb_const_properties.cpp", - "${relational_store_frameworks_path}/js/napi/graphstore/src/napi_gdb_error.cpp", - "${relational_store_frameworks_path}/js/napi/graphstore/src/napi_gdb_js_utils.cpp", - "${relational_store_frameworks_path}/js/napi/graphstore/src/napi_gdb_store.cpp", - "${relational_store_frameworks_path}/js/napi/graphstore/src/napi_gdb_store_helper.cpp", - "${relational_store_frameworks_path}/js/napi/graphstore/src/napi_gdb_transaction.cpp", + "src/convertor_error_code.cpp", + "src/modify_time_cursor.cpp", + "src/oh_data_utils.cpp", + "src/oh_data_value.cpp", + "src/oh_data_values.cpp", + "src/oh_data_values_buckets.cpp", + "src/oh_rdb_crypto_param.cpp", + "src/oh_rdb_transaction.cpp", + "src/relational_asset.cpp", + "src/relational_cursor.cpp", + "src/relational_predicates.cpp", + "src/relational_predicates_objects.cpp", + "src/relational_store.cpp", + "src/relational_values_bucket.cpp", + ] + + defines = [ "API_EXPORT=__attribute__((visibility (\"default\")))" ] + + deps = [ + "${relational_store_base_path}/interfaces/rdb_ndk_utils:native_rdb_ndk_utils", + "${relational_store_innerapi_path}/rdb:native_rdb" ] - deps = [ "${relational_store_innerapi_path}/gdb:native_graphstore" ] + external_deps = [ - "ability_runtime:abilitykit_native", - "ability_runtime:extensionkit_native", - "ability_runtime:napi_base_context", "c_utils:utils", - "eventhandler:libeventhandler", "hilog:libhilog", - "hisysevent:libhisysevent", - "hitrace:hitrace_meter", - "napi:ace_napi", + "json:nlohmann_json_static", + "kv_store:datamgr_common", ] - subsystem_name = "distributeddatamgr" + relative_install_dir = "ndk" part_name = "relational_store" - relative_install_dir = "module/data" + subsystem_name = "distributeddatamgr" } diff --git a/relational_store/interfaces/ndk/include/oh_data_value.h b/relational_store/interfaces/ndk/include/oh_data_value.h index 59d4de33..d3ab007c 100644 --- a/relational_store/interfaces/ndk/include/oh_data_value.h +++ b/relational_store/interfaces/ndk/include/oh_data_value.h @@ -125,7 +125,7 @@ typedef struct OH_Data_Value OH_Data_Value; * @see OH_Value_Destroy. * @since 16 */ -OH_Data_Value *OH_Value_Create(); +OH_Data_Value *OH_Value_Create(void); /** * @brief Destroys an OH_Data_Value instance object. @@ -266,7 +266,8 @@ int OH_Value_GetType(OH_Data_Value *value, OH_ColumnType *type); * @brief Check whether the data is empty from OH_Data_Value object. * * @param value Represents a pointer to an instance of OH_Data_Value. - * @param val Represents empty data flag. It is an output parameter. Ture is empty, false is not empty. + * @param val Represents empty data flag. It is an output parameter. + * The value true means that the data is empty, and false means the opposite. * @return Returns the error code. * Returns {@link RDB_OK} if the execution is successful. * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. diff --git a/relational_store/interfaces/ndk/include/oh_data_values.h b/relational_store/interfaces/ndk/include/oh_data_values.h index 6f16bd72..7075ea98 100644 --- a/relational_store/interfaces/ndk/include/oh_data_values.h +++ b/relational_store/interfaces/ndk/include/oh_data_values.h @@ -62,7 +62,7 @@ typedef struct OH_Data_Values OH_Data_Values; * @see OH_Values_Destroy. * @since 16 */ -OH_Data_Values *OH_Values_Create(); +OH_Data_Values *OH_Values_Create(void); /** * @brief Destroys an OH_Data_Values instance object. @@ -243,7 +243,8 @@ int OH_Values_Get(OH_Data_Values *values, int index, OH_Data_Value **val); * * @param values Represents a pointer to an instance of OH_Data_Values. * @param index Represents the zero-based index of target data in values. - * @param val Represents empty data flag. It is an output parameter. Ture is empty, false is not empty. + * @param val Represents empty data flag. It is an output parameter. + * The value true means that the data is empty, and false means the opposite. * @return Returns the error code. * Returns {@link RDB_OK} if the execution is successful. * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. diff --git a/relational_store/interfaces/ndk/include/oh_data_values_buckets.h b/relational_store/interfaces/ndk/include/oh_data_values_buckets.h index e3cb1bcd..b32d7614 100644 --- a/relational_store/interfaces/ndk/include/oh_data_values_buckets.h +++ b/relational_store/interfaces/ndk/include/oh_data_values_buckets.h @@ -61,7 +61,7 @@ typedef struct OH_Data_VBuckets OH_Data_VBuckets; * @see OH_VBuckets_Destroy. * @since 16 */ -OH_Data_VBuckets *OH_VBuckets_Create(); +OH_Data_VBuckets *OH_VBuckets_Create(void); /** * @brief Destroys an OH_Data_VBuckets instance object. @@ -99,7 +99,7 @@ int OH_VBuckets_PutRow(OH_Data_VBuckets *buckets, const OH_VBucket *row); int OH_VBuckets_PutRows(OH_Data_VBuckets *buckets, const OH_Data_VBuckets *rows); /** - * @brief Add an OH_Data_VBuckets to OH_Data_VBuckets object. + * @brief Gets the number of rows in OH_Data_VBuckets object. * * @param buckets Represents a pointer to an instance of OH_Data_VBuckets. * @param count Represents the count of OH_VBucket in OH_Data_VBuckets. It is an output parameter. diff --git a/relational_store/interfaces/ndk/include/oh_predicates.h b/relational_store/interfaces/ndk/include/oh_predicates.h index 28808e30..487f2967 100644 --- a/relational_store/interfaces/ndk/include/oh_predicates.h +++ b/relational_store/interfaces/ndk/include/oh_predicates.h @@ -37,10 +37,12 @@ * @since 10 */ -#include #include -#include "oh_value_object.h" +#include + +#include "oh_data_values.h" +#include "oh_value_object.h" #ifdef __cplusplus extern "C" { #endif @@ -396,6 +398,60 @@ typedef struct OH_Predicates { int (*destroy)(OH_Predicates *predicates); } OH_Predicates; +/** + * @brief Sets the OH_Predicates to specify conditions to filter grouped results that will appear in the final result. + * + * @param predicates Represents a pointer to an instance of OH_Predicates. + * @param conditions Indicates filter conditions in the having clause. + * @param values Indicates a pointer to an instance of OH_Data_Values. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 +*/ +int OH_Predicates_Having(OH_Predicates *predicates, const char *conditions, const OH_Data_Values *values); + +/** + * @brief Sets the OH_Predicates to match the field whose data type is string and value is not like the specified value. + * This method is similar to "Not like" of the SQL statement. + * + * @param predicates Represents a pointer to an instance of OH_Predicates. + * @param field Indicates the column name in the database table. + * @param pattern Indicates the value to compare against. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 +*/ +int OH_Predicates_NotLike(OH_Predicates *predicates, const char *field, const char *pattern); + +/** + * @brief Sets the OH_Predicates to match the specified field whose data type is string and the value contains + * a wildcard. Different from like, the input parameters of this method are case-sensitive. + * + * @param predicates Represents a pointer to an instance of OH_Predicates. + * @param field Indicates the column name in the database table. + * @param pattern Indicates the value to match with the predicate. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 +*/ +int OH_Predicates_Glob(OH_Predicates *predicates, const char *field, const char *pattern); + +/** + * @brief Sets the OH_Predicates to not match the specified field whose data type is string and the value contains + * a wildcard. Different from not like, the input parameters of this method are case-sensitive. + * + * @param predicates Represents a pointer to an instance of OH_Predicates. + * @param field Indicates the column name in the database table. + * @param pattern Indicates the value to compare against. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 +*/ +int OH_Predicates_NotGlob(OH_Predicates *predicates, const char *field, const char *pattern); #ifdef __cplusplus }; #endif diff --git a/relational_store/interfaces/ndk/include/oh_rdb_crypto_param.h b/relational_store/interfaces/ndk/include/oh_rdb_crypto_param.h new file mode 100644 index 00000000..3968b607 --- /dev/null +++ b/relational_store/interfaces/ndk/include/oh_rdb_crypto_param.h @@ -0,0 +1,227 @@ +/* + * 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. + */ + +/** + * @addtogroup RDB + * @{ + * + * @brief The relational database (RDB) store manages data based on relational models. + * With the underlying SQLite database, the RDB store provides a complete mechanism for managing local databases. + * To satisfy different needs in complicated scenarios, the RDB store offers a series of APIs for performing operations + * such as adding, deleting, modifying, and querying data, and supports direct execution of SQL statements. + * + * @since 10 + */ + +/** + * @file oh_rdb_crypto_param.h + * + * @brief Provides functions and enumerations related to cryptographic parameters of the relational database. + * + * @kit ArkData + * @library libnative_rdb_ndk.z.so + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * + * @since 20 + */ + +#ifndef OH_RDB_CRYPTO_PARAM_H +#define OH_RDB_CRYPTO_PARAM_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Enumerates the database encryption algorithms. + * + * @since 20 + */ +typedef enum Rdb_EncryptionAlgo { + /** + * @brief Indicates the database is encrypted using RDB_AES_256_GCM. + * + * @since 20 + */ + RDB_AES_256_GCM = 0, + /** + * @brief Indicates the database is encrypted using RDB_AES_256_CBC. + * + * @since 20 + */ + RDB_AES_256_CBC, +} Rdb_EncryptionAlgo; + +/** + * @brief Enumerates the supported HMAC algorithm when opening a database. + * + * @since 20 + */ +typedef enum Rdb_HmacAlgo { + /** + * @brief RDB_HMAC_SHA1 algorithm. + * + * @since 20 + */ + RDB_HMAC_SHA1 = 0, + /** + * @brief RDB_HMAC_SHA256 algorithm. + * + * @since 20 + */ + RDB_HMAC_SHA256, + /** + * @brief RDB_HMAC_SHA512 algorithm. + * + * @since 20 + */ + RDB_HMAC_SHA512, +} Rdb_HmacAlgo; + +/** + * @brief Enumerates the supported KDF algorithm when opening a database. + * + * @since 20 + */ +typedef enum Rdb_KdfAlgo { + /** + * @brief RDB_KDF_SHA1 algorithm. + * + * @since 20 + */ + RDB_KDF_SHA1 = 0, + /** + * @brief RDB_KDF_SHA256 algorithm. + * + * @since 20 + */ + RDB_KDF_SHA256, + /** + * @brief RDB_KDF_SHA512 algorithm. + * + * @since 20 + */ + RDB_KDF_SHA512, +} Rdb_KdfAlgo; + +/** + * @brief Specifies the cryptographic parameters used when opening an encrypted database. + * + * @since 20 + */ +typedef struct OH_Rdb_CryptoParam OH_Rdb_CryptoParam; + +/** + * @brief Creates an OH_Rdb_CryptoParam instance object. + * + * @return Returns a pointer to OH_Rdb_CryptoParam instance when the execution is successful. + * Otherwise, nullptr is returned. The memory must be released through the OH_Rdb_DestroyCryptoParam + * interface after the use is complete. + * @see OH_Rdb_DestroyCryptoParam. + * @since 20 + */ +OH_Rdb_CryptoParam *OH_Rdb_CreateCryptoParam(void); + +/** + * @brief Destroys an OH_Rdb_CryptoParam instance object. + * + * @param param Represents a pointer to an instance of OH_Rdb_CryptoParam. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Rdb_DestroyCryptoParam(OH_Rdb_CryptoParam *param); + +/** + * @brief Sets key data to the OH_Rdb_CryptoParam object. + * + * @param param Represents a pointer to an instance of OH_Rdb_CryptoParam. + * @param key Represents a pointer to array data. + * @param length Represents the size of key array. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Crypto_SetEncryptionKey(OH_Rdb_CryptoParam *param, const uint8_t *key, int32_t length); + +/** + * @brief Sets the number of KDF iterations used when opening an encrypted database. + * + * @param param Represents a pointer to an instance of OH_Rdb_CryptoParam. + * @param iteration Represents a pointer to array data. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Crypto_SetIteration(OH_Rdb_CryptoParam *param, int64_t iteration); + +/** + * @brief Sets the encryption algorithm when opening an encrypted database. + * + * @param param Represents a pointer to an instance of OH_Rdb_CryptoParam. + * @param algo Represents the encryption algorithm. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Crypto_SetEncryptionAlgo(OH_Rdb_CryptoParam *param, int32_t algo); + +/** + * @brief Sets the HMAC algorithm when opening an encrypted database. + * + * @param param Represents a pointer to an instance of OH_Rdb_CryptoParam. + * @param algo Represents the HMAC algorithm. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Crypto_SetHmacAlgo(OH_Rdb_CryptoParam *param, int32_t algo); + +/** + * @brief Sets the KDF algorithm when opening an encrypted database. + * + * @param param Represents a pointer to an instance of OH_Rdb_CryptoParam. + * @param algo Represents the KDF algorithm. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Crypto_SetKdfAlgo(OH_Rdb_CryptoParam *param, int32_t algo); + +/** + * @brief Sets the page size used when opening an encrypted database. + * + * @param param Represents a pointer to an instance of OH_Rdb_CryptoParam. + * @param size Represents the page size. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Crypto_SetCryptoPageSize(OH_Rdb_CryptoParam *param, int64_t size); + +#ifdef __cplusplus +}; +#endif +#endif +/** @} */ diff --git a/relational_store/interfaces/ndk/include/oh_rdb_transaction.h b/relational_store/interfaces/ndk/include/oh_rdb_transaction.h index d8960c52..2067da26 100644 --- a/relational_store/interfaces/ndk/include/oh_rdb_transaction.h +++ b/relational_store/interfaces/ndk/include/oh_rdb_transaction.h @@ -98,30 +98,30 @@ typedef struct OH_Rdb_Transaction OH_Rdb_Transaction; * @see OH_RdbTrans_DestroyOptions. * @since 16 */ -OH_RDB_TransOptions *OH_RdbTrans_CreateOptions(); +OH_RDB_TransOptions *OH_RdbTrans_CreateOptions(void); /** * @brief Destroys an OH_RDB_TransOptions instance object. * - * @param opitons Represents a pointer to an instance of OH_RDB_TransOptions. + * @param options Represents a pointer to an instance of OH_RDB_TransOptions. * @return Returns the error code. * Returns {@link RDB_OK} if the execution is successful. * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. * @since 16 */ -int OH_RdbTrans_DestroyOptions(OH_RDB_TransOptions *opitons); +int OH_RdbTrans_DestroyOptions(OH_RDB_TransOptions *options); /** - * @brief Sets integer data to the opitons object. + * @brief Sets integer data to the options object. * - * @param opitons Represents a pointer to an instance of OH_RDB_TransOptions. + * @param options Represents a pointer to an instance of OH_RDB_TransOptions. * @param type Represents relation database transaction type. * @return Returns the error code. * Returns {@link RDB_OK} if the execution is successful. * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. * @since 16 */ -int OH_RdbTransOption_SetType(OH_RDB_TransOptions *opitons, OH_RDB_TransType type); +int OH_RdbTransOption_SetType(OH_RDB_TransOptions *options, OH_RDB_TransType type); /** * @brief Commits a transaction of a relational database. @@ -191,6 +191,36 @@ int OH_RdbTrans_Rollback(OH_Rdb_Transaction *trans); */ int OH_RdbTrans_Insert(OH_Rdb_Transaction *trans, const char *table, const OH_VBucket *row, int64_t *rowId); +/** + * @brief Inserts a row of data into the target table and support conflict resolution. + * + * @param trans Represents a pointer to an instance of OH_Rdb_Transaction. + * @param table Represents the target table. + * @param row Represents the row data to be inserted into the table. + * @param resolution Represents the resolution when conflict occurs. + * @param rowId Represents row line number when insert successfully. + * @return Returns the status code of the execution. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_ERROR} database common error. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * Returns {@link RDB_E_ALREADY_CLOSED} database already closed. + * Returns {@link RDB_E_WAL_SIZE_OVER_LIMIT} the WAL file size over default limit. + * Returns {@link RDB_E_SQLITE_FULL} SQLite: The database is full. + * Returns {@link RDB_E_SQLITE_CORRUPT} database corrupted. + * Returns {@link RDB_E_SQLITE_PERM} SQLite: Access permission denied. + * Returns {@link RDB_E_SQLITE_BUSY} SQLite: The database file is locked. + * Returns {@link RDB_E_SQLITE_LOCKED} SQLite: A table in the database is locked. + * Returns {@link RDB_E_SQLITE_NOMEM} SQLite: The database is out of memory. + * Returns {@link RDB_E_SQLITE_READONLY} SQLite: Attempt to write a readonly database. + * Returns {@link RDB_E_SQLITE_IOERR} SQLite: Some kind of disk I/O error occurred. + * Returns {@link RDB_E_SQLITE_TOO_BIG} SQLite: TEXT or BLOB exceeds size limit. + * Returns {@link RDB_E_SQLITE_MISMATCH} SQLite: Data type mismatch. + * Returns {@link RDB_E_SQLITE_CONSTRAINT} SQLite: Abort due to constraint violation. + * @since 20 + */ +int OH_RdbTrans_InsertWithConflictResolution(OH_Rdb_Transaction *trans, const char *table, const OH_VBucket *row, + Rdb_ConflictResolution resolution, int64_t *rowId); + /** * @brief Inserts a batch of data into the target table. * @@ -248,6 +278,35 @@ int OH_RdbTrans_BatchInsert(OH_Rdb_Transaction *trans, const char *table, const */ int OH_RdbTrans_Update(OH_Rdb_Transaction *trans, const OH_VBucket *row, const OH_Predicates *predicates, int64_t *changes); +/** + * @brief Updates data in the database based on specified conditions and support conflict resolution. + * + * @param trans Represents a pointer to an instance of OH_Rdb_Transaction. + * @param row Represents the row data to be updated into the table. + * @param predicates Represents the specified update condition by the instance object of OH_Predicates. + * @param resolution Represents the resolution when conflict occurs. + * @param changes Represents the number of successful insertions. + * @return Returns the status code of the execution. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_ERROR} database common error. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * Returns {@link RDB_E_ALREADY_CLOSED} database already closed. + * Returns {@link RDB_E_WAL_SIZE_OVER_LIMIT} the WAL file size over default limit. + * Returns {@link RDB_E_SQLITE_FULL} SQLite: The database is full. + * Returns {@link RDB_E_SQLITE_CORRUPT} database corrupted. + * Returns {@link RDB_E_SQLITE_PERM} SQLite: Access permission denied. + * Returns {@link RDB_E_SQLITE_BUSY} SQLite: The database file is locked. + * Returns {@link RDB_E_SQLITE_LOCKED} SQLite: A table in the database is locked. + * Returns {@link RDB_E_SQLITE_NOMEM} SQLite: The database is out of memory. + * Returns {@link RDB_E_SQLITE_READONLY} SQLite: Attempt to write a readonly database. + * Returns {@link RDB_E_SQLITE_IOERR} SQLite: Some kind of disk I/O error occurred. + * Returns {@link RDB_E_SQLITE_TOO_BIG} SQLite: TEXT or BLOB exceeds size limit. + * Returns {@link RDB_E_SQLITE_MISMATCH} SQLite: Data type mismatch. + * Returns {@link RDB_E_SQLITE_CONSTRAINT} SQLite: Abort due to constraint violation. + * @since 20 + */ +int OH_RdbTrans_UpdateWithConflictResolution(OH_Rdb_Transaction *trans, const OH_VBucket *row, + const OH_Predicates *predicates, Rdb_ConflictResolution resolution, int64_t *changes); /** * @brief Deletes data from the database based on specified conditions diff --git a/relational_store/interfaces/ndk/include/relational_store.h b/relational_store/interfaces/ndk/include/relational_store.h index 54699112..d03f49b9 100644 --- a/relational_store/interfaces/ndk/include/relational_store.h +++ b/relational_store/interfaces/ndk/include/relational_store.h @@ -43,6 +43,7 @@ #include "oh_values_bucket.h" #include "oh_rdb_transaction.h" #include "oh_rdb_types.h" +#include "oh_rdb_crypto_param.h" #ifdef __cplusplus extern "C" { @@ -319,6 +320,19 @@ int OH_Rdb_SetSecurityLevel(OH_Rdb_ConfigV2 *config, int securityLevel); */ int OH_Rdb_SetArea(OH_Rdb_ConfigV2 *config, int area); +/** + * @brief Set whether the database enable the capabilities for semantic indexing processing. + * + * @param config Represents a pointer to {@link OH_Rdb_ConfigV2} instance. + * Indicates the configuration of the database related to this RDB store. + * @param enableSemanticIndex Indicates whether the database enable the capabilities for semantic indexing processing. + * @return Returns the status code of the execution. Successful execution returns RDB_OK, + * {@link RDB_OK} - success. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * @since 20 + */ +int OH_Rdb_SetSemanticIndex(OH_Rdb_ConfigV2 *config, bool enableSemanticIndex); + /** * @brief Set property dbType into config * @param config Represents a pointer to {@link OH_Rdb_ConfigV2} instance. @@ -330,6 +344,56 @@ int OH_Rdb_SetArea(OH_Rdb_ConfigV2 *config, int area); * @since 14 */ int OH_Rdb_SetDbType(OH_Rdb_ConfigV2 *config, int dbType); + +/** + * @brief Sets the customized directory relative to the database. + * + * @param config Represents a pointer to a configuration of the database related to this relation database store. + * @param customDir Represents the customized relative to the database directory, the value cannot exceed 128 bytes. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Rdb_SetCustomDir(OH_Rdb_ConfigV2 *config, const char *customDir); + +/** + * @brief Sets the relation database store is read-only mode. + * + * @param config Represents a pointer to a configuration of the database related to this relation database store. + * @param readOnly Represents whether the relation database store is read-only. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Rdb_SetReadOnly(OH_Rdb_ConfigV2 *config, bool readOnly); + +/** + * @brief Sets the dynamic libraries with capabilities such as Full-Text Search (FTS). + * + * @param config Represents a pointer to a configuration of the database related to this relation database store. + * @param plugins Represents the dynamic libraries. + * @param length the size of plugins that the maximum value is 16. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Rdb_SetPlugins(OH_Rdb_ConfigV2 *config, const char **plugins, int32_t length); + +/** + * @brief Sets the custom encryption parameters. + * + * @param config Represents a pointer to a configuration of the database related to this relation database store. + * @param cryptoParam Represents the custom encryption parameters. + * @return Returns the error code. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * @since 20 + */ +int OH_Rdb_SetCryptoParam(OH_Rdb_ConfigV2 *config, const OH_Rdb_CryptoParam *cryptoParam); + /** * @brief Check if a tokenizer is supported or not. * @@ -370,7 +434,7 @@ int OH_Rdb_SetPersistent(OH_Rdb_ConfigV2 *config, bool isPersistent); /** * @brief Get support db type list - * @param typeCount The output parameter, which is used to recieve the length of the support db type array. + * @param typeCount The output parameter, which is used to receive the length of the support db type array. * @return Return Rdb_DBType array contains supported db type, array length is number of support type * @since 14 */ @@ -499,6 +563,36 @@ int OH_Rdb_DeleteStoreV2(const OH_Rdb_ConfigV2 *config); */ int OH_Rdb_Insert(OH_Rdb_Store *store, const char *table, OH_VBucket *valuesBucket); +/** + * @brief Inserts a row of data into the target table and support conflict resolution. + * + * @param store Represents a pointer to an OH_Rdb_Store instance. + * @param table Represents the target table. + * @param row Represents the row data to be inserted into the table. + * @param resolution Represents the resolution when conflict occurs. + * @param rowId Represents the number of successful insertion. + * @return Returns the status code of the execution. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_ERROR} database common error. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * Returns {@link RDB_E_ALREADY_CLOSED} database already closed. + * Returns {@link RDB_E_WAL_SIZE_OVER_LIMIT} the WAL file size over default limit. + * Returns {@link RDB_E_SQLITE_FULL} SQLite: The database is full. + * Returns {@link RDB_E_SQLITE_CORRUPT} database corrupted. + * Returns {@link RDB_E_SQLITE_PERM} SQLite: Access permission denied. + * Returns {@link RDB_E_SQLITE_BUSY} SQLite: The database file is locked. + * Returns {@link RDB_E_SQLITE_LOCKED} SQLite: A table in the database is locked. + * Returns {@link RDB_E_SQLITE_NOMEM} SQLite: The database is out of memory. + * Returns {@link RDB_E_SQLITE_READONLY} SQLite: Attempt to write a readonly database. + * Returns {@link RDB_E_SQLITE_IOERR} SQLite: Some kind of disk I/O error occurred. + * Returns {@link RDB_E_SQLITE_TOO_BIG} SQLite: TEXT or BLOB exceeds size limit. + * Returns {@link RDB_E_SQLITE_MISMATCH} SQLite: Data type mismatch. + * Returns {@link RDB_E_SQLITE_CONSTRAINT} SQLite: Abort due to constraint violation. + * @since 20 + */ +int OH_Rdb_InsertWithConflictResolution(OH_Rdb_Store *store, const char *table, OH_VBucket *row, + Rdb_ConflictResolution resolution, int64_t *rowId); + /** * @brief Inserts a batch of data into the target table. * @@ -544,6 +638,35 @@ int OH_Rdb_BatchInsert(OH_Rdb_Store *store, const char *table, * @since 10 */ int OH_Rdb_Update(OH_Rdb_Store *store, OH_VBucket *valuesBucket, OH_Predicates *predicates); +/** + * @brief Updates data in the database based on specified conditions and support conflict resolution. + * + * @param store Represents a pointer to an OH_Rdb_Store instance. + * @param row Represents the row data to be inserted into the table. + * @param predicates Represents a pointer to an link OH_Predicates instance. + * @param resolution Represents the resolution when conflict occurs. + * @param changes Represents the number of successful update. + * @return Returns the status code of the execution. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_ERROR} database common error. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * Returns {@link RDB_E_ALREADY_CLOSED} database already closed. + * Returns {@link RDB_E_WAL_SIZE_OVER_LIMIT} the WAL file size over default limit. + * Returns {@link RDB_E_SQLITE_FULL} SQLite: The database is full. + * Returns {@link RDB_E_SQLITE_CORRUPT} database corrupted. + * Returns {@link RDB_E_SQLITE_PERM} SQLite: Access permission denied. + * Returns {@link RDB_E_SQLITE_BUSY} SQLite: The database file is locked. + * Returns {@link RDB_E_SQLITE_LOCKED} SQLite: A table in the database is locked. + * Returns {@link RDB_E_SQLITE_NOMEM} SQLite: The database is out of memory. + * Returns {@link RDB_E_SQLITE_READONLY} SQLite: Attempt to write a readonly database. + * Returns {@link RDB_E_SQLITE_IOERR} SQLite: Some kind of disk I/O error occurred. + * Returns {@link RDB_E_SQLITE_TOO_BIG} SQLite: TEXT or BLOB exceeds size limit. + * Returns {@link RDB_E_SQLITE_MISMATCH} SQLite: Data type mismatch. + * Returns {@link RDB_E_SQLITE_CONSTRAINT} SQLite: Abort due to constraint violation. + * @since 20 + */ +int OH_Rdb_UpdateWithConflictResolution(OH_Rdb_Store *store, OH_VBucket *row, OH_Predicates *predicates, + Rdb_ConflictResolution resolution, int64_t *changes); /** * @brief Deletes data from the database based on specified conditions. @@ -597,7 +720,7 @@ int OH_Rdb_Execute(OH_Rdb_Store *store, const char *sql); * @return Returns the status code of the execution. * {@link RDB_OK} - success. * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. - * {@link RDB_E_NOT_SUPPORTED} - The error code for not supprt. + * {@link RDB_E_NOT_SUPPORTED} - The error code for not support. * @see OH_Rdb_Store. * @since 14 */ @@ -659,7 +782,7 @@ int OH_Rdb_Commit(OH_Rdb_Store *store); * @return Returns the status code of the execution. * {@link RDB_OK} - success. * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. - * {@link RDB_E_NOT_SUPPORTED} - The error code for not supprt. + * {@link RDB_E_NOT_SUPPORTED} - The error code for not support. * @see OH_Rdb_Store. * @since 14 */ @@ -673,7 +796,7 @@ int OH_Rdb_BeginTransWithTrxId(OH_Rdb_Store *store, int64_t *trxId); * @return Returns the status code of the execution. * {@link RDB_OK} - success. * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. - * {@link RDB_E_NOT_SUPPORTED} - The error code for not supprt. + * {@link RDB_E_NOT_SUPPORTED} - The error code for not support. * @see OH_Rdb_Store. * @since 14 */ @@ -687,7 +810,7 @@ int OH_Rdb_RollBackByTrxId(OH_Rdb_Store *store, int64_t trxId); * @return Returns the status code of the execution. * {@link RDB_OK} - success. * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. - * {@link RDB_E_NOT_SUPPORTED} - The error code for not supprt. + * {@link RDB_E_NOT_SUPPORTED} - The error code for not support. * @see OH_Rdb_Store. * @since 14 */ @@ -1264,7 +1387,7 @@ int OH_Rdb_CloudSync(OH_Rdb_Store *store, Rdb_SyncMode mode, const char *tables[ * A callback will be invoked when there is a notification of the automatic synchronization progress. * * @param store Indicates the pointer to the target {@Link OH_Rdb_Store} instance. -* @param observer The {@link Rdb_SyncObserver} for the automatic synchornizaiton progress +* @param observer The {@link Rdb_SyncObserver} for the automatic synchronization progress * Indicates the callback invoked to return the automatic synchronization progress. * @return Returns the status code of the execution. See {@link OH_Rdb_ErrCode}. * {@link RDB_OK} - success. @@ -1402,6 +1525,85 @@ int OH_Rdb_ExecuteV2(OH_Rdb_Store *store, const char *sql, const OH_Data_Values */ OH_Cursor *OH_Rdb_ExecuteQueryV2(OH_Rdb_Store *store, const char *sql, const OH_Data_Values *args); +/** + * @brief Attaches a database file to the currently linked database. + * + * @param store Represents a pointer to an OH_Rdb_Store instance. + * @param config Represents a pointer to an OH_Rdb_ConfigV2 configuration of the database related to this RDB store. + * @param attachName Represents the alias of the database. + * @param waitTime Represents the maximum time allowed for attaching the database, valid range is 1 to 300. + * @param attachedNumber Represents the number of attached databases, It is an output parameter. + * @return Returns the status code of the execution. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_ERROR} database common error. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * Returns {@link RDB_E_ALREADY_CLOSED} database already closed. + * Returns {@link RDB_E_NOT_SUPPORTED} - The error code for not support. + * Returns {@link RDB_E_DATABASE_BUSY} database does not respond. + * Returns {@link RDB_E_SQLITE_FULL} SQLite: The database is full. + * Returns {@link RDB_E_SQLITE_CORRUPT} database corrupted. + * Returns {@link RDB_E_SQLITE_PERM} SQLite: Access permission denied. + * Returns {@link RDB_E_SQLITE_BUSY} SQLite: The database file is locked. + * Returns {@link RDB_E_SQLITE_LOCKED} SQLite: A table in the database is locked. + * Returns {@link RDB_E_SQLITE_NOMEM} SQLite: The database is out of memory. + * Returns {@link RDB_E_SQLITE_READONLY} SQLite: Attempt to write a readonly database. + * Returns {@link RDB_E_SQLITE_IOERR} SQLite: Some kind of disk I/O error occurred. + * Returns {@link RDB_E_SQLITE_TOO_BIG} SQLite: TEXT or BLOB exceeds size limit. + * Returns {@link RDB_E_SQLITE_MISMATCH} SQLite: Data type mismatch. + * Returns {@link RDB_E_SQLITE_CONSTRAINT} SQLite: Abort due to constraint violation. + * @since 20 + */ +int OH_Rdb_Attach(OH_Rdb_Store *store, const OH_Rdb_ConfigV2 *config, const char *attachName, int64_t waitTime, + size_t *attachedNumber); + +/** + * @brief Detaches a database from this database. + * + * @param store Represents a pointer to an OH_Rdb_Store instance. + * @param attachName Represents the alias of the database. + * @param waitTime Represents the maximum time allowed for detaching the database, valid range is 1 to 300. + * @param attachedNumber Represents the number of attached databases, It is an output parameter. + * @return Returns the status code of the execution. + * Returns {@link RDB_OK} if the execution is successful. + * Returns {@link RDB_E_ERROR} database common error. + * Returns {@link RDB_E_INVALID_ARGS} if invalid input parameter. + * Returns {@link RDB_E_ALREADY_CLOSED} database already closed. + * Returns {@link RDB_E_NOT_SUPPORTED} - The error code for not support. + * Returns {@link RDB_E_DATABASE_BUSY} database does not respond. + * Returns {@link RDB_E_SQLITE_FULL} SQLite: The database is full. + * Returns {@link RDB_E_SQLITE_CORRUPT} database corrupted. + * Returns {@link RDB_E_SQLITE_PERM} SQLite: Access permission denied. + * Returns {@link RDB_E_SQLITE_BUSY} SQLite: The database file is locked. + * Returns {@link RDB_E_SQLITE_LOCKED} SQLite: A table in the database is locked. + * Returns {@link RDB_E_SQLITE_NOMEM} SQLite: The database is out of memory. + * Returns {@link RDB_E_SQLITE_READONLY} SQLite: Attempt to write a readonly database. + * Returns {@link RDB_E_SQLITE_IOERR} SQLite: Some kind of disk I/O error occurred. + * Returns {@link RDB_E_SQLITE_TOO_BIG} SQLite: TEXT or BLOB exceeds size limit. + * Returns {@link RDB_E_SQLITE_MISMATCH} SQLite: Data type mismatch. + * Returns {@link RDB_E_SQLITE_CONSTRAINT} SQLite: Abort due to constraint violation. + * @see OH_Rdb_Store, OH_Rdb_ErrCode. + * @since 20 + */ +int OH_Rdb_Detach(OH_Rdb_Store *store, const char *attachName, int64_t waitTime, size_t *attachedNumber); + +/** + * @brief Support for collations in different languages. + * + * @param store Represents a pointer to an {@link OH_Rdb_Store} instance. + * @param locale Language related to the locale, for example, zh. The value complies with the ISO 639 standard. + * @return Returns a specific error code. + * {@link RDB_OK} if the execution is successful. + * {@link RDB_ERR} - Indicates that the function execution exception. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * {@link RDB_E_ALREADY_CLOSED} database already closed. + * {@link RDB_E_SQLITE_BUSY} SQLite: The database file is locked. + * {@link RDB_E_SQLITE_NOMEM} SQLite: The database is out of memory. + * Specific error codes can be referenced {@link OH_Rdb_ErrCode}. + * @see OH_Rdb_Store. + * @since 20 + */ +int OH_Rdb_SetLocale(OH_Rdb_Store *store, const char *locale); + #ifdef __cplusplus }; #endif diff --git a/relational_store/interfaces/ndk/relational_store_inner_types.h b/relational_store/interfaces/ndk/relational_store_inner_types.h new file mode 100644 index 00000000..1faf3c9a --- /dev/null +++ b/relational_store/interfaces/ndk/relational_store_inner_types.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 RELATIONAL_STORE_INNER_TYPES_H +#define RELATIONAL_STORE_INNER_TYPES_H +#include +#include + +#include "rdb_store_config.h" +#include "relational_store.h" +constexpr int RDB_CONFIG_V2_MAGIC_CODE = 0xDBCF2ADE; +struct OH_Rdb_ConfigV2 { + int magicNum = RDB_CONFIG_V2_MAGIC_CODE; + std::string dataBaseDir = ""; + std::string storeName = ""; + std::string bundleName = ""; + std::string moduleName = ""; + bool isEncrypt = false; + bool persist = true; + int securityLevel = 0; + int area = 0; + int dbType = RDB_SQLITE; + int token = RDB_NONE_TOKENIZER; + std::string customDir = ""; + bool readOnly = false; + std::vector pluginLibs{}; + OHOS::NativeRdb::RdbStoreConfig::CryptoParam cryptoParam; + bool enableSemanticIndex = false; +}; +#endif // RELATIONAL_STORE_INNER_TYPES_H diff --git a/relational_store/interfaces/ndk/src/oh_data_define.h b/relational_store/interfaces/ndk/src/oh_data_define.h index 425b9412..8cfc07c4 100644 --- a/relational_store/interfaces/ndk/src/oh_data_define.h +++ b/relational_store/interfaces/ndk/src/oh_data_define.h @@ -22,6 +22,7 @@ #include "transaction.h" #include "oh_predicates.h" #include "oh_rdb_transaction.h" +#include "rdb_store_config.h" struct OH_Rdb_Transaction { static constexpr int64_t OH_RDB_TRANS_ID = 0x10000000; @@ -62,4 +63,12 @@ struct OH_Data_VBuckets { std::vector rows_; bool IsValid() const; }; + +struct OH_Rdb_CryptoParam { + static constexpr int64_t OH_CRYPTO_PARAM_ID = 0x10005000; + int64_t id = OH_CRYPTO_PARAM_ID; + + OHOS::NativeRdb::RdbStoreConfig::CryptoParam cryptoParam; + bool IsValid() const; +}; #endif diff --git a/relational_store/interfaces/ndk/src/oh_data_value.cpp b/relational_store/interfaces/ndk/src/oh_data_value.cpp index 0c2993bb..ec98e42d 100644 --- a/relational_store/interfaces/ndk/src/oh_data_value.cpp +++ b/relational_store/interfaces/ndk/src/oh_data_value.cpp @@ -58,7 +58,7 @@ static int CheckValueType(const OH_Data_Value *value, int32_t type) return RDB_OK; } -OH_Data_Value *OH_Value_Create() +OH_Data_Value *OH_Value_Create(void) { OH_Data_Value *value = new (std::nothrow) OH_Data_Value; if (value == nullptr) { diff --git a/relational_store/interfaces/ndk/src/oh_data_values.cpp b/relational_store/interfaces/ndk/src/oh_data_values.cpp index e284bb4d..5675ea95 100644 --- a/relational_store/interfaces/ndk/src/oh_data_values.cpp +++ b/relational_store/interfaces/ndk/src/oh_data_values.cpp @@ -42,7 +42,7 @@ static bool IsValidValuesElement(OH_Data_Values *values, int index) return true; } -OH_Data_Values *OH_Values_Create() +OH_Data_Values *OH_Values_Create(void) { OH_Data_Values *values = new (std::nothrow) OH_Data_Values; return values; diff --git a/relational_store/interfaces/ndk/src/oh_data_values_buckets.cpp b/relational_store/interfaces/ndk/src/oh_data_values_buckets.cpp index d1bdf1fc..5be4eaf3 100644 --- a/relational_store/interfaces/ndk/src/oh_data_values_buckets.cpp +++ b/relational_store/interfaces/ndk/src/oh_data_values_buckets.cpp @@ -34,7 +34,7 @@ static bool IsValidVBuckets(const OH_Data_VBuckets *vbuckets) return ret; } -OH_Data_VBuckets *OH_VBuckets_Create() +OH_Data_VBuckets *OH_VBuckets_Create(void) { OH_Data_VBuckets *vbuckets = new (std::nothrow) OH_Data_VBuckets; if (vbuckets == nullptr) { diff --git a/relational_store/interfaces/ndk/src/oh_rdb_crypto_param.cpp b/relational_store/interfaces/ndk/src/oh_rdb_crypto_param.cpp new file mode 100644 index 00000000..657ab9fd --- /dev/null +++ b/relational_store/interfaces/ndk/src/oh_rdb_crypto_param.cpp @@ -0,0 +1,112 @@ +/* + * 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. + */ +#define LOG_TAG "OhRdbCryptoParam" +#include "oh_rdb_crypto_param.h" +#include +#include "oh_data_define.h" +#include "relational_store_error_code.h" + +using namespace OHOS::DistributedRdb; +using namespace OHOS::NativeRdb; + +bool OH_Rdb_CryptoParam::IsValid() const +{ + return id == OH_CRYPTO_PARAM_ID; +} + +OH_Rdb_CryptoParam *OH_Rdb_CreateCryptoParam(void) +{ + OH_Rdb_CryptoParam *value = new (std::nothrow) OH_Rdb_CryptoParam; + if (value == nullptr) { + return nullptr; + } + return value; +} + +int OH_Rdb_DestroyCryptoParam(OH_Rdb_CryptoParam *cryptoParam) +{ + if (cryptoParam == nullptr || !cryptoParam->IsValid()) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + delete cryptoParam; + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Crypto_SetEncryptionKey(OH_Rdb_CryptoParam *param, const uint8_t *key, int32_t length) +{ + if (param == nullptr || !param->IsValid()) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + if (key == nullptr || length == 0) { + param->cryptoParam.encryptKey_.assign(param->cryptoParam.encryptKey_.size(), 0); + } else { + param->cryptoParam.encryptKey_ = std::vector{ key, key + length }; + } + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Crypto_SetIteration(OH_Rdb_CryptoParam *param, int64_t iteration) +{ + if (param == nullptr || !param->IsValid() || iteration < 0) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + param->cryptoParam.iterNum = static_cast(iteration); + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Crypto_SetEncryptionAlgo(OH_Rdb_CryptoParam *param, int32_t algo) +{ + if (param == nullptr || !param->IsValid() || + (algo != static_cast(RDB_AES_256_GCM) && + algo != static_cast(RDB_AES_256_CBC))) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + param->cryptoParam.encryptAlgo = algo; + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Crypto_SetHmacAlgo(OH_Rdb_CryptoParam *param, int32_t algo) +{ + if (param == nullptr || !param->IsValid() || + algo < static_cast(RDB_HMAC_SHA1) || algo > static_cast(RDB_HMAC_SHA512)) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + param->cryptoParam.hmacAlgo = algo; + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Crypto_SetKdfAlgo(OH_Rdb_CryptoParam *param, int32_t algo) +{ + if (param == nullptr || !param->IsValid() || + algo < static_cast(RDB_KDF_SHA1) || algo > static_cast(RDB_KDF_SHA512)) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + param->cryptoParam.kdfAlgo = algo; + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Crypto_SetCryptoPageSize(OH_Rdb_CryptoParam *param, int64_t size) +{ + if (param == nullptr || !param->IsValid() || size < 0) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + uint32_t value = static_cast(size); + if (!((value != 0) && ((value & RdbStoreConfig::DB_INVALID_CRYPTO_PAGE_SIZE_MASK) == 0) && + (value & (value - 1)) == 0)) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + param->cryptoParam.cryptoPageSize = value; + return OH_Rdb_ErrCode::RDB_OK; +} \ No newline at end of file diff --git a/relational_store/interfaces/ndk/src/oh_rdb_transaction.cpp b/relational_store/interfaces/ndk/src/oh_rdb_transaction.cpp index 943967e4..f5c3ea87 100644 --- a/relational_store/interfaces/ndk/src/oh_rdb_transaction.cpp +++ b/relational_store/interfaces/ndk/src/oh_rdb_transaction.cpp @@ -41,7 +41,7 @@ static bool IsValidRdbTransOptions(const OH_RDB_TransOptions *options) return ret; } -OH_RDB_TransOptions *OH_RdbTrans_CreateOptions() +OH_RDB_TransOptions *OH_RdbTrans_CreateOptions(void) { OH_RDB_TransOptions *value = new (std::nothrow) OH_RDB_TransOptions; if (value == nullptr) { @@ -52,22 +52,22 @@ OH_RDB_TransOptions *OH_RdbTrans_CreateOptions() return value; } -int OH_RdbTrans_DestroyOptions(OH_RDB_TransOptions *opitons) +int OH_RdbTrans_DestroyOptions(OH_RDB_TransOptions *options) { - if (!IsValidRdbTransOptions(opitons)) { + if (!IsValidRdbTransOptions(options)) { return RDB_E_INVALID_ARGS; } - delete opitons; + delete options; return RDB_OK; } -int OH_RdbTransOption_SetType(OH_RDB_TransOptions *opitons, OH_RDB_TransType type) +int OH_RdbTransOption_SetType(OH_RDB_TransOptions *options, OH_RDB_TransType type) { - if (!IsValidRdbTransOptions(opitons) || type < RDB_TRANS_DEFERRED || type >= RDB_TRANS_BUTT) { + if (!IsValidRdbTransOptions(options) || type < RDB_TRANS_DEFERRED || type >= RDB_TRANS_BUTT) { LOG_ERROR("invalid options, type=%{public}d.", type); return RDB_E_INVALID_ARGS; } - opitons->type_ = type; + options->type_ = type; return RDB_OK; } @@ -138,8 +138,7 @@ int OH_RdbTrans_BatchInsert(OH_Rdb_Transaction *trans, const char *table, const } datas.Put(valuesBucket->Get()); } - auto [errCode, count] = - trans->trans_->BatchInsertWithConflictResolution(table, datas, Utils::ConvertConflictResolution(resolution)); + auto [errCode, count] = trans->trans_->BatchInsert(table, datas, Utils::ConvertConflictResolution(resolution)); *changes = count; if (errCode != E_OK) { LOG_ERROR("batch insert fail, errCode=%{public}d count=%{public}" PRId64, errCode, count); @@ -276,4 +275,41 @@ bool OH_RDB_TransOptions::IsValid() const return false; } return id == OH_TRANS_OPTION_ID; +} + +int OH_RdbTrans_InsertWithConflictResolution(OH_Rdb_Transaction *trans, const char *table, const OH_VBucket *row, + Rdb_ConflictResolution resolution, int64_t *rowId) +{ + auto valuesBucket = RelationalValuesBucket::GetSelf(const_cast(row)); + if (!IsValidRdbTrans(trans) || table == nullptr || valuesBucket == nullptr || rowId == nullptr || + resolution < RDB_CONFLICT_NONE || resolution > RDB_CONFLICT_REPLACE) { + return RDB_E_INVALID_ARGS; + } + + auto [err, id] = trans->trans_->Insert(table, valuesBucket->Get(), Utils::ConvertConflictResolution(resolution)); + *rowId = id; + if (err != E_OK) { + LOG_ERROR("insert with conflict resolution fail,errCode=%{public}x,resolution=%{public}d,id=%{public}" PRId64, + err, resolution, id); + } + return ConvertorErrorCode::GetInterfaceCode(err); +} + +int OH_RdbTrans_UpdateWithConflictResolution(OH_Rdb_Transaction *trans, const OH_VBucket *row, + const OH_Predicates *predicates, Rdb_ConflictResolution resolution, int64_t *changes) +{ + auto rdbPredicate = RelationalPredicate::GetSelf(const_cast(predicates)); + auto rdbValuesBucket = RelationalValuesBucket::GetSelf(const_cast(row)); + if (!IsValidRdbTrans(trans) || rdbValuesBucket == nullptr || rdbPredicate == nullptr || changes == nullptr || + resolution < RDB_CONFLICT_NONE || resolution > RDB_CONFLICT_REPLACE) { + return RDB_E_INVALID_ARGS; + } + auto [err, count] = trans->trans_->Update(rdbValuesBucket->Get(), rdbPredicate->Get(), + Utils::ConvertConflictResolution(resolution)); + *changes = count; + if (err != E_OK) { + LOG_ERROR("update with conflict resolution fail, errCode=%{public}x,resolution=%{public}d,count=%{public}d", + err, resolution, count); + } + return ConvertorErrorCode::GetInterfaceCode(err); } \ No newline at end of file diff --git a/relational_store/interfaces/ndk/src/relational_predicates.cpp b/relational_store/interfaces/ndk/src/relational_predicates.cpp index 5ae55665..a8d82c66 100644 --- a/relational_store/interfaces/ndk/src/relational_predicates.cpp +++ b/relational_store/interfaces/ndk/src/relational_predicates.cpp @@ -17,7 +17,9 @@ #include +#include "convertor_error_code.h" #include "logger.h" +#include "oh_data_define.h" #include "oh_predicates.h" #include "relational_predicates_objects.h" #include "relational_store_error_code.h" @@ -377,3 +379,59 @@ RelationalPredicate *RelationalPredicate::GetSelf(OH_Predicates *predicates) } } // namespace RdbNdk } // namespace OHOS + +using namespace OHOS::RdbNdk; +using namespace OHOS::NativeRdb; +int OH_Predicates_Having(OH_Predicates *predicates, const char *conditions, const OH_Data_Values *values) +{ + auto self = RelationalPredicate::GetSelf(predicates); + if (self == nullptr || conditions == nullptr || (values != nullptr && !values->IsValid())) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + if (self->Get().GetGroup().empty() || strlen(conditions) == 0) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + if (values == nullptr) { + self->Get().Having(conditions); + return OH_Rdb_ErrCode::RDB_OK; + } + std::vector datas; + for (auto &value : values->values_) { + if (!value.IsValid()) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + datas.push_back(value.value_); + } + self->Get().Having(conditions, datas); + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Predicates_NotLike(OH_Predicates *predicates, const char *field, const char *pattern) +{ + auto self = RelationalPredicate::GetSelf(predicates); + if (self == nullptr || field == nullptr || pattern == nullptr) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + self->Get().NotLike(field, pattern); + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Predicates_Glob(OH_Predicates *predicates, const char *field, const char *pattern) +{ + auto self = RelationalPredicate::GetSelf(predicates); + if (self == nullptr || field == nullptr || pattern == nullptr) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + self->Get().Glob(field, pattern); + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Predicates_NotGlob(OH_Predicates *predicates, const char *field, const char *pattern) +{ + auto self = RelationalPredicate::GetSelf(predicates); + if (self == nullptr || field == nullptr || pattern == nullptr) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + self->Get().NotGlob(field, pattern); + return OH_Rdb_ErrCode::RDB_OK; +} diff --git a/relational_store/interfaces/ndk/src/relational_predicates_objects.cpp b/relational_store/interfaces/ndk/src/relational_predicates_objects.cpp index 378c363b..3b6316a0 100644 --- a/relational_store/interfaces/ndk/src/relational_predicates_objects.cpp +++ b/relational_store/interfaces/ndk/src/relational_predicates_objects.cpp @@ -23,6 +23,7 @@ namespace OHOS { namespace RdbNdk { // The class id used to uniquely identify the OH_VObject class. constexpr int RDB_PREDICATES_OBJECTS_CID = 1234565; + int RelationalPredicatesObjects::PutInt64(OH_VObject *objects, int64_t *value, uint32_t count) { auto self = GetSelf(objects); diff --git a/relational_store/interfaces/ndk/src/relational_store.cpp b/relational_store/interfaces/ndk/src/relational_store.cpp index c66b7efa..5072916c 100644 --- a/relational_store/interfaces/ndk/src/relational_store.cpp +++ b/relational_store/interfaces/ndk/src/relational_store.cpp @@ -19,9 +19,12 @@ #include "grd_api_manager.h" #include "logger.h" #include "modify_time_cursor.h" +#include "oh_data_define.h" +#include "oh_data_utils.h" #include "raw_data_parser.h" #include "rdb_errno.h" #include "rdb_helper.h" +#include "rdb_ndk_utils.h" #include "rdb_predicates.h" #include "rdb_sql_utils.h" #include "rdb_store_config.h" @@ -30,37 +33,26 @@ #include "relational_predicates_objects.h" #include "relational_store_error_code.h" #include "relational_store_impl.h" +#include "relational_store_inner_types.h" #include "relational_types_v0.h" #include "relational_values_bucket.h" #include "securec.h" #include "sqlite_global_config.h" -#include "oh_data_define.h" -#include "oh_data_utils.h" #include "values_buckets.h" +#include "sqlite_utils.h" using namespace OHOS::RdbNdk; using namespace OHOS::DistributedRdb; -constexpr int RDB_STORE_CID = 1234560; // The class id used to uniquely identify the OH_Rdb_Store class. +constexpr int RDB_STORE_CID = 1234560; // The class id used to uniquely identify the OH_Rdb_Store class. constexpr int RDB_CONFIG_SIZE_V0 = 41; constexpr int RDB_CONFIG_SIZE_V1 = 45; -constexpr int RDB_CONFIG_V2_MAGIC_CODE = 0xDBCF2ADE; +constexpr int RDB_ATTACH_WAIT_TIME_MIN = 1; +constexpr int RDB_ATTACH_WAIT_TIME_MAX = 300; +constexpr int RDB_CONFIG_PLUGINS_MAX = 16; +constexpr int RDB_CONFIG_CUST_DIR_MAX_LEN = 128; static int g_supportDbTypes[] = { RDB_SQLITE, RDB_CAYLEY }; -struct OH_Rdb_ConfigV2 { - int magicNum = RDB_CONFIG_V2_MAGIC_CODE; - std::string dataBaseDir = ""; - std::string storeName = ""; - std::string bundleName = ""; - std::string moduleName = ""; - bool isEncrypt = false; - bool persist = true; - int securityLevel = 0; - int area = 0; - int dbType = RDB_SQLITE; - int token = RDB_NONE_TOKENIZER; -}; - OH_Rdb_ConfigV2 *OH_Rdb_CreateConfig() { return new (std::nothrow) OH_Rdb_ConfigV2(); @@ -165,6 +157,17 @@ int OH_Rdb_SetArea(OH_Rdb_ConfigV2 *config, int area) return OH_Rdb_ErrCode::RDB_OK; } +int OH_Rdb_SetSemanticIndex(OH_Rdb_ConfigV2 *config, bool isEnable) +{ + if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) { + LOG_ERROR("config is null %{public}d or magic num not valid %{public}x when set SemanticIndex.", + (config == nullptr), (config == nullptr ? 0 : config->magicNum)); + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + config->enableSemanticIndex = isEnable; + return OH_Rdb_ErrCode::RDB_OK; +} + int OH_Rdb_SetDbType(OH_Rdb_ConfigV2 *config, int dbType) { if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE) || @@ -180,6 +183,47 @@ int OH_Rdb_SetDbType(OH_Rdb_ConfigV2 *config, int dbType) return OH_Rdb_ErrCode::RDB_OK; } +int OH_Rdb_SetCustomDir(OH_Rdb_ConfigV2 *config, const char *customDir) +{ + if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE) || customDir == nullptr || + strlen(customDir) > RDB_CONFIG_CUST_DIR_MAX_LEN) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + config->customDir = customDir; + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Rdb_SetReadOnly(OH_Rdb_ConfigV2 *config, bool readOnly) +{ + if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + config->readOnly = readOnly; + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Rdb_SetPlugins(OH_Rdb_ConfigV2 *config, const char **plugins, int32_t length) +{ + if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE) || plugins == nullptr || + length > RDB_CONFIG_PLUGINS_MAX) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + for (int i = 0; i < length; i++) { + config->pluginLibs.push_back(plugins[i]); + } + return OH_Rdb_ErrCode::RDB_OK; +} + +int OH_Rdb_SetCryptoParam(OH_Rdb_ConfigV2 *config, const OH_Rdb_CryptoParam *cryptoParam) +{ + if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE) || + cryptoParam == nullptr || !cryptoParam->IsValid()) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + config->cryptoParam = cryptoParam->cryptoParam; + return OH_Rdb_ErrCode::RDB_OK; +} + int OH_Rdb_IsTokenizerSupported(Rdb_Tokenizer tokenizer, bool *isSupported) { if (tokenizer < RDB_NONE_TOKENIZER || tokenizer > RDB_CUSTOM_TOKENIZER) { @@ -263,6 +307,9 @@ int RelationalStore::SubscribeAutoSyncProgress(const Rdb_ProgressObserver *callb return OH_Rdb_ErrCode::RDB_OK; } auto obs = std::make_shared(callback); + if (store_ == nullptr) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } int errCode = store_->RegisterAutoSyncCallback(obs); if (errCode == NativeRdb::E_OK) { LOG_ERROR("subscribe failed."); @@ -275,6 +322,9 @@ int RelationalStore::SubscribeAutoSyncProgress(const Rdb_ProgressObserver *callb int RelationalStore::UnsubscribeAutoSyncProgress(const Rdb_ProgressObserver *callback) { std::lock_guard lock(mutex_); + if (store_ == nullptr) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } for (auto it = callbacks_.begin(); it != callbacks_.end();) { if (callback != nullptr && !(**it == callback)) { ++it; @@ -355,59 +405,6 @@ RelationalStore *GetRelationalStore(OH_Rdb_Store *store) return static_cast(store); } -// caller must ensure token is valid -static OHOS::NativeRdb::Tokenizer ConvertTokenizer2Native(Rdb_Tokenizer token) -{ - if (token == Rdb_Tokenizer::RDB_NONE_TOKENIZER) { - return OHOS::NativeRdb::Tokenizer::NONE_TOKENIZER; - } - if (token == Rdb_Tokenizer::RDB_ICU_TOKENIZER) { - return OHOS::NativeRdb::Tokenizer::ICU_TOKENIZER; - } - if (token == Rdb_Tokenizer::RDB_CUSTOM_TOKENIZER) { - return OHOS::NativeRdb::Tokenizer::CUSTOM_TOKENIZER; - } - return OHOS::NativeRdb::Tokenizer::TOKENIZER_END; -} - -static OHOS::NativeRdb::RdbStoreConfig GetRdbStoreConfig(const OH_Rdb_ConfigV2 *config, int *errCode) -{ - if (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE || (config->persist && - ((OHOS::NativeRdb::SecurityLevel(config->securityLevel) < OHOS::NativeRdb::SecurityLevel::S1 || - OHOS::NativeRdb::SecurityLevel(config->securityLevel) >= OHOS::NativeRdb::SecurityLevel::LAST))) || - (config->area < RDB_SECURITY_AREA_EL1 || config->area > RDB_SECURITY_AREA_EL5) || - (config->dbType < RDB_SQLITE || config->dbType > RDB_CAYLEY) || - (config->token < RDB_NONE_TOKENIZER || config->token > RDB_CUSTOM_TOKENIZER)) { - *errCode = OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; - LOG_ERROR("Config magic number is not valid %{public}x or securityLevel %{public}d area %{public}d" - "dbType %{public}d token %{public}d ret %{public}d persist %{public}d", - config->magicNum, config->securityLevel, config->area, config->dbType, config->token, *errCode, - config->persist); - return OHOS::NativeRdb::RdbStoreConfig(""); - } - std::string realPath = !config->persist ? config->dataBaseDir: - OHOS::NativeRdb::RdbSqlUtils::GetDefaultDatabasePath(config->dataBaseDir, config->storeName, *errCode); - if (*errCode != 0) { - *errCode = ConvertorErrorCode::NativeToNdk(*errCode); - LOG_ERROR("Get database path failed from new config, ret %{public}d ", *errCode); - return OHOS::NativeRdb::RdbStoreConfig(""); - } - OHOS::NativeRdb::RdbStoreConfig rdbStoreConfig(realPath); - if (!config->storeName.empty()) { - rdbStoreConfig.SetName(config->storeName); - } - rdbStoreConfig.SetSecurityLevel(OHOS::NativeRdb::SecurityLevel(config->securityLevel)); - rdbStoreConfig.SetEncryptStatus(config->isEncrypt); - rdbStoreConfig.SetArea(config->area - 1); - rdbStoreConfig.SetIsVector(config->dbType == RDB_CAYLEY); - rdbStoreConfig.SetBundleName(config->bundleName); - rdbStoreConfig.SetName(config->storeName); - rdbStoreConfig.SetTokenizer(ConvertTokenizer2Native(static_cast(config->token))); - rdbStoreConfig.SetStorageMode( - config->persist ? OHOS::NativeRdb::StorageMode::MODE_DISK : OHOS::NativeRdb::StorageMode::MODE_MEMORY); - return rdbStoreConfig; -} - OH_Rdb_Store *OH_Rdb_GetOrOpen(const OH_Rdb_Config *config, int *errCode) { if (config == nullptr || config->selfSize > RDB_CONFIG_SIZE_V1 || errCode == nullptr) { @@ -440,7 +437,7 @@ OH_Rdb_Store *OH_Rdb_GetOrOpen(const OH_Rdb_Config *config, int *errCode) OHOS::NativeRdb::RdbHelper::GetRdbStore(rdbStoreConfig, -1, callback, *errCode); *errCode = ConvertorErrorCode::NativeToNdk(*errCode); if (store == nullptr) { - LOG_ERROR("Get RDB Store fail %{public}s", realPath.c_str()); + LOG_ERROR("Get RDB Store fail %{public}s", OHOS::NativeRdb::SqliteUtils::Anonymous(realPath).c_str()); return nullptr; } return new (std::nothrow) RelationalStore(store); @@ -454,8 +451,10 @@ OH_Rdb_Store *OH_Rdb_CreateOrOpen(const OH_Rdb_ConfigV2 *config, int *errCode) (config == nullptr), (config == nullptr ? 0 : config->magicNum), (errCode == nullptr)); return nullptr; } - OHOS::NativeRdb::RdbStoreConfig rdbStoreConfig = GetRdbStoreConfig(config, errCode); - if (*errCode != OH_Rdb_ErrCode::RDB_OK) { + + auto [ret, rdbStoreConfig] = RdbNdkUtils::GetRdbStoreConfig(config); + if (ret != OHOS::NativeRdb::E_OK) { + *errCode = ret; return nullptr; } MainOpenCallback callback; @@ -463,7 +462,8 @@ OH_Rdb_Store *OH_Rdb_CreateOrOpen(const OH_Rdb_ConfigV2 *config, int *errCode) OHOS::NativeRdb::RdbHelper::GetRdbStore(rdbStoreConfig, -1, callback, *errCode); *errCode = ConvertorErrorCode::NativeToNdk(*errCode); if (store == nullptr) { - LOG_ERROR("Get RDB Store fail %{public}s", rdbStoreConfig.GetPath().c_str()); + LOG_ERROR("Get RDB Store fail %{public}s", + OHOS::NativeRdb::SqliteUtils::Anonymous(rdbStoreConfig.GetPath()).c_str()); return nullptr; } return new (std::nothrow) RelationalStore(store); @@ -538,7 +538,7 @@ int OH_Rdb_BatchInsert(OH_Rdb_Store *store, const char *table, } datas.Put(valuesBucket->Get()); } - auto [errCode, count] = rdbStore->GetStore()->BatchInsertWithConflictResolution(table, + auto [errCode, count] = rdbStore->GetStore()->BatchInsert(table, datas, Utils::ConvertConflictResolution(resolution)); *changes = count; if (errCode != OHOS::NativeRdb::E_OK) { @@ -821,7 +821,7 @@ int RelationalStore::DoSubScribe(Rdb_SubscribeType type, const Rdb_DataObserver auto ndkObserver = std::make_shared(observer, type); int subscribeResult = (type == RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS) ? store_->SubscribeObserver(subscribeOption, ndkObserver) - : store_->Subscribe(subscribeOption, ndkObserver.get()); + : store_->Subscribe(subscribeOption, ndkObserver); if (subscribeResult != OHOS::NativeRdb::E_OK) { LOG_ERROR("subscribe failed."); } else { @@ -843,7 +843,7 @@ int RelationalStore::DoUnsubScribe(Rdb_SubscribeType type, const Rdb_DataObserve } auto subscribeOption = SubscribeOption{ .mode = NDKUtils::GetSubscribeType(type), .event = "data_change" }; int errCode = (type == RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS) ? store_->UnsubscribeObserver(subscribeOption, *it) - : store_->UnSubscribe(subscribeOption, it->get()); + : store_->UnSubscribe(subscribeOption, *it); if (errCode != NativeRdb::E_OK) { LOG_ERROR("unsubscribe failed."); return ConvertorErrorCode::NativeToNdk(errCode); @@ -903,7 +903,10 @@ Rdb_TableDetails *RelationalProgressDetails::GetTableDetails(int paraVersion) if (detailsV0 == nullptr) { return nullptr; } - (void)memset_s(detailsV0, length, 0, length); + auto result = memset_s(detailsV0, length, 0, length); + if (result != EOK) { + LOG_ERROR("memset_s failed, error code is %{public}d", result); + } int index = 0; for (const auto &pair : tableDetails_) { detailsV0[index].table = pair.first.c_str(); @@ -1037,7 +1040,6 @@ OH_Cursor *OH_Rdb_QueryLockedRow( auto rdbStore = GetRelationalStore(store); auto predicate = RelationalPredicate::GetSelf(predicates); if (rdbStore == nullptr || predicate == nullptr) { - LOG_ERROR("rdbStore or predicate is nullptr."); return nullptr; } std::vector columns; @@ -1282,8 +1284,81 @@ void NDKStoreObserver::ConvertKeyInfoData( bool NDKStoreObserver::operator==(const Rdb_DataObserver *other) { - if (other == nullptr) { + if (other == nullptr || observer_ == nullptr) { return false; } return other->context == observer_->context && &(other->callback) == &(observer_->callback); +} + +int OH_Rdb_InsertWithConflictResolution(OH_Rdb_Store *store, const char *table, OH_VBucket *row, + Rdb_ConflictResolution resolution, int64_t *rowId) +{ + auto rdbStore = GetRelationalStore(store); + auto bucket = RelationalValuesBucket::GetSelf(row); + if (rdbStore == nullptr || table == nullptr || bucket == nullptr || rowId == nullptr || + resolution < RDB_CONFLICT_NONE || resolution > RDB_CONFLICT_REPLACE) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + auto [errCode, count] = rdbStore->GetStore()->Insert(table, bucket->Get(), + Utils::ConvertConflictResolution(resolution)); + *rowId = count; + return ConvertorErrorCode::GetInterfaceCode(errCode); +} + +int OH_Rdb_UpdateWithConflictResolution(OH_Rdb_Store *store, OH_VBucket *row, OH_Predicates *predicates, + Rdb_ConflictResolution resolution, int64_t *changes) +{ + auto rdbStore = GetRelationalStore(store); + auto bucket = RelationalValuesBucket::GetSelf(row); + auto predicate = RelationalPredicate::GetSelf(predicates); + if (rdbStore == nullptr || bucket == nullptr || predicate == nullptr || changes == nullptr || + resolution < RDB_CONFLICT_NONE || resolution > RDB_CONFLICT_REPLACE) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + int changedRows = 0; + auto errCode = rdbStore->GetStore()->UpdateWithConflictResolution(changedRows, + predicate->Get().GetTableName(), bucket->Get(), predicate->Get().GetWhereClause(), + predicate->Get().GetBindArgs(), Utils::ConvertConflictResolution(resolution)); + *changes = changedRows; + return ConvertorErrorCode::GetInterfaceCode(errCode); +} + +int OH_Rdb_Attach(OH_Rdb_Store *store, const OH_Rdb_ConfigV2 *config, const char *attachName, int64_t waitTime, + size_t *attachedNumber) +{ + auto rdbStore = GetRelationalStore(store); + if (rdbStore == nullptr || config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE) || + attachName == nullptr || waitTime < RDB_ATTACH_WAIT_TIME_MIN || waitTime > RDB_ATTACH_WAIT_TIME_MAX || + attachedNumber == nullptr) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + auto [ret, rdbStoreConfig] = RdbNdkUtils::GetRdbStoreConfig(config); + if (ret != OHOS::NativeRdb::E_OK) { + return ConvertorErrorCode::NativeToNdk(ret); + } + auto [errCode, size] = rdbStore->GetStore()->Attach(rdbStoreConfig, attachName, static_cast(waitTime)); + *attachedNumber = size; + return ConvertorErrorCode::GetInterfaceCode(errCode); +} + +int OH_Rdb_Detach(OH_Rdb_Store *store, const char *attachName, int64_t waitTime, size_t *attachedNumber) +{ + auto rdbStore = GetRelationalStore(store); + if (rdbStore == nullptr || attachName == nullptr || + waitTime < RDB_ATTACH_WAIT_TIME_MIN || waitTime > RDB_ATTACH_WAIT_TIME_MAX || attachedNumber == nullptr) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + auto [errCode, size] = rdbStore->GetStore()->Detach(attachName, static_cast(waitTime)); + *attachedNumber = size; + return ConvertorErrorCode::GetInterfaceCode(errCode); +} + +int OH_Rdb_SetLocale(OH_Rdb_Store *store, const char *locale) +{ + auto rdbStore = GetRelationalStore(store); + if (rdbStore == nullptr || locale == nullptr) { + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + auto errCode = rdbStore->GetStore()->ConfigLocale(locale); + return ConvertorErrorCode::GetInterfaceCode(errCode); } \ No newline at end of file diff --git a/relational_store/interfaces/ndk/src/BUILD.gn b/relational_store/interfaces/rdb_ndk_utils/BUILD.gn similarity index 65% rename from relational_store/interfaces/ndk/src/BUILD.gn rename to relational_store/interfaces/rdb_ndk_utils/BUILD.gn index 9ce64297..ba7ffff0 100644 --- a/relational_store/interfaces/ndk/src/BUILD.gn +++ b/relational_store/interfaces/rdb_ndk_utils/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. +# Copyright (c) 2025 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -14,7 +14,14 @@ import("//build/ohos.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") -ohos_shared_library("native_rdb_ndk") { +config("native_rdb_ndk_utils_public_config") { + visibility = [ ":*" ] + + include_dirs = [ + "include", + ] +} +ohos_shared_library("native_rdb_ndk_utils") { branch_protector_ret = "pac_ret" sanitize = { boundary_sanitize = true @@ -25,26 +32,11 @@ ohos_shared_library("native_rdb_ndk") { } include_dirs = [ - "../include", - "${kvstore_path}/common", + "${relational_store_base_path}/interfaces/ndk", + "${relational_store_base_path}/interfaces/ndk/include", "${relational_store_common_path}/include", - "${relational_store_native_path}/rdb/include", - ] - sources = [ - "convertor_error_code.cpp", - "modify_time_cursor.cpp", - "oh_data_utils.cpp", - "oh_data_value.cpp", - "oh_data_values.cpp", - "oh_data_values_buckets.cpp", - "oh_rdb_transaction.cpp", - "relational_asset.cpp", - "relational_cursor.cpp", - "relational_predicates.cpp", - "relational_predicates_objects.cpp", - "relational_store.cpp", - "relational_values_bucket.cpp", ] + sources = [ "src/rdb_ndk_utils.cpp" ] defines = [ "API_EXPORT=__attribute__((visibility (\"default\")))" ] @@ -53,9 +45,10 @@ ohos_shared_library("native_rdb_ndk") { external_deps = [ "c_utils:utils", "hilog:libhilog", + "kv_store:datamgr_common", ] + public_configs = [ ":native_rdb_ndk_utils_public_config" ] - relative_install_dir = "ndk" part_name = "relational_store" subsystem_name = "distributeddatamgr" } diff --git a/relational_store/interfaces/rdb_ndk_utils/include/rdb_ndk_utils.h b/relational_store/interfaces/rdb_ndk_utils/include/rdb_ndk_utils.h new file mode 100644 index 00000000..218aecd1 --- /dev/null +++ b/relational_store/interfaces/rdb_ndk_utils/include/rdb_ndk_utils.h @@ -0,0 +1,25 @@ +/* +* 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 RDB_NDK_UTILS_H +#define RDB_NDK_UTILS_H +#include "rdb_store_config.h" +typedef struct OH_Rdb_ConfigV2 OH_Rdb_ConfigV2; +namespace OHOS::RdbNdk { +class API_EXPORT RdbNdkUtils { +public: + static std::pair GetRdbStoreConfig(const OH_Rdb_ConfigV2 *config); +}; +} // namespace OHOS::RdbNdk +#endif // RDB_NDK_UTILS_H \ No newline at end of file diff --git a/relational_store/interfaces/rdb_ndk_utils/src/rdb_ndk_utils.cpp b/relational_store/interfaces/rdb_ndk_utils/src/rdb_ndk_utils.cpp new file mode 100644 index 00000000..aa238754 --- /dev/null +++ b/relational_store/interfaces/rdb_ndk_utils/src/rdb_ndk_utils.cpp @@ -0,0 +1,90 @@ +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#define LOG_TAG "RdbNdkUtils" +#include "rdb_ndk_utils.h" + +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_sql_utils.h" +#include "relational_store_inner_types.h" + +namespace OHOS::RdbNdk { +// caller must ensure token is valid +static OHOS::NativeRdb::Tokenizer ConvertTokenizer2Native(Rdb_Tokenizer token) +{ + if (token == Rdb_Tokenizer::RDB_NONE_TOKENIZER) { + return OHOS::NativeRdb::Tokenizer::NONE_TOKENIZER; + } + if (token == Rdb_Tokenizer::RDB_ICU_TOKENIZER) { + return OHOS::NativeRdb::Tokenizer::ICU_TOKENIZER; + } + if (token == Rdb_Tokenizer::RDB_CUSTOM_TOKENIZER) { + return OHOS::NativeRdb::Tokenizer::CUSTOM_TOKENIZER; + } + return OHOS::NativeRdb::Tokenizer::TOKENIZER_END; +} + +std::pair RdbNdkUtils::GetRdbStoreConfig(const OH_Rdb_ConfigV2 *config) +{ + if (config == nullptr || config->magicNum != RDB_CONFIG_V2_MAGIC_CODE || (config->persist && + ((OHOS::NativeRdb::SecurityLevel(config->securityLevel) < OHOS::NativeRdb::SecurityLevel::S1 || + OHOS::NativeRdb::SecurityLevel(config->securityLevel) >= OHOS::NativeRdb::SecurityLevel::LAST))) || + (config->area < RDB_SECURITY_AREA_EL1 || config->area > RDB_SECURITY_AREA_EL5) || + (config->dbType < RDB_SQLITE || config->dbType > RDB_CAYLEY) || + (config->token < RDB_NONE_TOKENIZER || config->token > RDB_CUSTOM_TOKENIZER)) { + if (config != nullptr) { + LOG_ERROR("Config magic number is not valid %{public}x or securityLevel %{public}d area %{public}d" + " dbType %{public}d token %{public}d persist %{public}d" + " readOnly %{public}d", + config->magicNum, config->securityLevel, config->area, config->dbType, config->token, + config->persist, config->readOnly); + } else { + LOG_ERROR("Config is null"); + } + return { OHOS::NativeRdb::E_INVALID_ARGS, OHOS::NativeRdb::RdbStoreConfig("") }; + } + + std::string realPath; + int32_t code = OHOS::NativeRdb::E_OK; + if (config->persist) { + std::tie(realPath, code) = OHOS::NativeRdb::RdbSqlUtils::GetDefaultDatabasePath( + config->dataBaseDir, config->storeName, config->customDir); + } else { + realPath = config->dataBaseDir; + } + + if (code != OHOS::NativeRdb::E_OK) { + LOG_ERROR("Get database path failed from new config, ret %{public}d ", code); + return { OHOS::NativeRdb::E_INVALID_ARGS, OHOS::NativeRdb::RdbStoreConfig("") }; + } + OHOS::NativeRdb::RdbStoreConfig rdbStoreConfig(realPath); + rdbStoreConfig.SetSecurityLevel(OHOS::NativeRdb::SecurityLevel(config->securityLevel)); + rdbStoreConfig.SetEncryptStatus(config->isEncrypt); + rdbStoreConfig.SetArea(config->area - 1); + rdbStoreConfig.SetIsVector(config->dbType == RDB_CAYLEY); + rdbStoreConfig.SetBundleName(config->bundleName); + rdbStoreConfig.SetName(config->storeName); + rdbStoreConfig.SetTokenizer(ConvertTokenizer2Native(static_cast(config->token))); + rdbStoreConfig.SetStorageMode( + config->persist ? OHOS::NativeRdb::StorageMode::MODE_DISK : OHOS::NativeRdb::StorageMode::MODE_MEMORY); + rdbStoreConfig.SetCustomDir(config->customDir); + rdbStoreConfig.SetReadOnly(config->readOnly); + rdbStoreConfig.SetPluginLibs(config->pluginLibs); + rdbStoreConfig.SetCryptoParam(config->cryptoParam); + rdbStoreConfig.SetEnableSemanticIndex(config->enableSemanticIndex); + return { OHOS::NativeRdb::E_OK, rdbStoreConfig }; +} +} // namespace OHOS::RdbNdk \ No newline at end of file diff --git a/relational_store/rdbmock/frameworks/native/rdb/concurrent_map.h b/relational_store/rdbmock/frameworks/native/rdb/common/concurrent_map.h similarity index 100% rename from relational_store/rdbmock/frameworks/native/rdb/concurrent_map.h rename to relational_store/rdbmock/frameworks/native/rdb/common/concurrent_map.h diff --git a/relational_store/rdbmock/frameworks/native/rdb/file_ex.h b/relational_store/rdbmock/frameworks/native/rdb/file_ex.h index d2102fcb..ab6de135 100644 --- a/relational_store/rdbmock/frameworks/native/rdb/file_ex.h +++ b/relational_store/rdbmock/frameworks/native/rdb/file_ex.h @@ -19,7 +19,7 @@ #include #include -static bool SaveBufferToFile(const std::string &filePath, const std::vector &content, bool truncated = true) +static bool SaveStringToFd(int fd, const std::string& content) { return true; } diff --git a/relational_store/rdbmock/frameworks/native/rdb/relational_store_client.h b/relational_store/rdbmock/frameworks/native/rdb/relational_store_client.h index cc94d325..2ba9fab4 100644 --- a/relational_store/rdbmock/frameworks/native/rdb/relational_store_client.h +++ b/relational_store/rdbmock/frameworks/native/rdb/relational_store_client.h @@ -17,6 +17,7 @@ #define RELATIONAL_STORE_RELATIONAL_STORE_CLIENT_H #include +#include #include "sqlite3sym.h" #include "store_observer.h" @@ -57,4 +58,18 @@ void UnregisterDbHook(sqlite3 *db); DistributedDB::DBStatus CreateDataChangeTempTrigger(sqlite3 *db); +namespace DistributedDB { +struct KnowledgeSourceSchema { + std::string tableName; + std::set extendColNames; + std::set knowledgeColNames; +}; +} + +DistributedDB::DBStatus SetKnowledgeSourceSchema(sqlite3 *db, const DistributedDB::KnowledgeSourceSchema &schema); + +DistributedDB::DBStatus CleanDeletedData(sqlite3 *db, const std::string &tableName, uint64_t cursor); + +void Clean(bool isOpenSslClean); + #endif //RELATIONAL_STORE_RELATIONAL_STORE_CLIENT_H diff --git a/relational_store/rdbmock/frameworks/native/rdb/sys/file.h b/relational_store/rdbmock/frameworks/native/rdb/sys/file.h index 525ff1e4..eee8a7da 100644 --- a/relational_store/rdbmock/frameworks/native/rdb/sys/file.h +++ b/relational_store/rdbmock/frameworks/native/rdb/sys/file.h @@ -23,6 +23,10 @@ #ifndef LOCK_UN #define LOCK_UN 1 #endif + +#ifndef LOCK_NB +#define LOCK_NB 4 +#endif #ifdef __cplusplus extern "C" { #endif diff --git a/relational_store/rdbmock/frameworks/native/win32/dlfcn.cpp b/relational_store/rdbmock/frameworks/native/win32/dlfcn.cpp index 62abb46b..12102614 100644 --- a/relational_store/rdbmock/frameworks/native/win32/dlfcn.cpp +++ b/relational_store/rdbmock/frameworks/native/win32/dlfcn.cpp @@ -21,6 +21,11 @@ void *dlopen(const char *pathName, int mode) }; void *dlsym(void *handle, const char *funcName) +{ + return nullptr; +}; + +void *dlclose(void *handle) { return nullptr; }; \ No newline at end of file diff --git a/relational_store/rdbmock/frameworks/native/win32/dlfcn.h b/relational_store/rdbmock/frameworks/native/win32/dlfcn.h index f0fc3b50..e29758f2 100644 --- a/relational_store/rdbmock/frameworks/native/win32/dlfcn.h +++ b/relational_store/rdbmock/frameworks/native/win32/dlfcn.h @@ -28,6 +28,7 @@ extern "C" { void *dlopen(const char *pathName, int mode); void *dlsym(void *handle, const char *funcName); +void *dlclose(void *handle); #ifdef __cplusplus } #endif diff --git a/relational_store/relational_store.gni b/relational_store/relational_store.gni index d5c7eb3e..55ba7439 100644 --- a/relational_store/relational_store.gni +++ b/relational_store/relational_store.gni @@ -28,6 +28,9 @@ relational_store_base_path = "//foundation/distributeddatamgr/relational_store" relational_store_mock_path = "${relational_store_base_path}/rdbmock" +relational_store_mock_test_path = + "${relational_store_base_path}/test/native/rdb/mock" + relational_store_js_common_path = "${relational_store_base_path}/frameworks/js/napi/common" @@ -60,10 +63,12 @@ sdk_c_path = "//interface/sdk_c/distributeddatamgr" plugins_path = "//plugins" -relational_store_frameworks_path = "${relational_store_base_path}/frameworks" - -plugins_path = "//plugins" - foundation_systemabilitymgr_path = "//foundation/systemabilitymgr/" base_security_dataclassification_path = "//base/security/dataclassification" + +datashare_base_path = "//foundation/distributeddatamgr/data_share" + +datashare_common_native_path = "${datashare_base_path}/frameworks/native/common" + +datashare_innerapi_path = "${datashare_base_path}/interfaces/inner_api" \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/AppScope/app.json b/relational_store/test/ets/cloud_data/AppScope/app.json new file mode 100644 index 00000000..8bbcec32 --- /dev/null +++ b/relational_store/test/ets/cloud_data/AppScope/app.json @@ -0,0 +1,21 @@ +{ + "app":{ + "bundleName":"com.clouddata.configtest", + "vendor":"example", + "versionCode":1000000, + "versionName":"1.0.0", + "debug":false, + "icon":"$media:icon", + "label":"$string:app_name", + "description":"$string:description_application", + "distributedNotificationEnabled":true, + "keepAlive":true, + "singleUser":true, + "minAPIVersion":8, + "targetAPIVersion":8, + "car":{ + "apiCompatibleVersion":8, + "singleUser":false + } + } +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/AppScope/resources/base/element/string.json b/relational_store/test/ets/cloud_data/AppScope/resources/base/element/string.json new file mode 100644 index 00000000..75824003 --- /dev/null +++ b/relational_store/test/ets/cloud_data/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string":[ + { + "name":"app_name", + "value":"ohosProject" + } + ] +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/BUILD.gn b/relational_store/test/ets/cloud_data/BUILD.gn new file mode 100644 index 00000000..d57ca3d5 --- /dev/null +++ b/relational_store/test/ets/cloud_data/BUILD.gn @@ -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. + +import("//build/test.gni") + +ohos_js_stage_unittest("CloudConfigEtsTest") { + hap_profile = "entry/src/main/module.json" + deps = [ + ":stageetstest_js_assets", + ":stageetstest_resources", + ] + ets2abc = true + certificate_profile = "signature/openharmony_sx.p7b" + hap_name = "CloudConfigEtsTest" + subsystem_name = "distributeddatamgr" + part_name = "relational_store" + module_out_path = "relational_store/relational_store/relational_store_ets" +} + +ohos_app_scope("stageetstest_app_profile") { + app_profile = "AppScope/app.json" + sources = [ "AppScope/resources" ] +} + +ohos_js_assets("stageetstest_js_assets") { + source_dir = "entry/src/main/ets" +} + +ohos_resources("stageetstest_resources") { + sources = [ "entry/src/main/resources" ] + deps = [ ":stageetstest_app_profile" ] + hap_profile = "entry/src/main/module.json" +} + +group("stage_unittest") { + testonly = true + deps = [ ":CloudConfigEtsTest" ] +} diff --git a/relational_store/test/ets/cloud_data/Test.json b/relational_store/test/ets/cloud_data/Test.json new file mode 100644 index 00000000..4d6ad28d --- /dev/null +++ b/relational_store/test/ets/cloud_data/Test.json @@ -0,0 +1,26 @@ +{ + "description": "Configuration for hjunit demo Tests", + "driver": { + "type": "OHJSUnitTest", + "test-timeout": "180000", + "bundle-name": "com.clouddata.configtest", + "module-name": "testModule", + "shell-timeout": "600000", + "testcase-timeout": 70000 + }, + "kits": [ + { + "test-file-name": [ + "CloudConfigEtsTest.hap" + ], + "type": "AppInstallKit", + "cleanup-apps": true + }, + { + "type": "ShellKit", + "teardown-command":[ + "bm uninstall -n com.clouddata.configtest" + ] + } + ] +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/ets/Application/AbilityStage.ts b/relational_store/test/ets/cloud_data/entry/src/main/ets/Application/AbilityStage.ts new file mode 100644 index 00000000..d7d5f024 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/ets/Application/AbilityStage.ts @@ -0,0 +1,22 @@ +// 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 AbilityStage from "@ohos.app.ability.AbilityStage" + +export default class MyAbilityStage extends AbilityStage { + onCreate() { + console.log('[Demo] MyAbilityStage onCreate'); + globalThis.stageOnCreateRun = 1; + globalThis.stageContext = this.context; + } +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/ets/MainAbility/MainAbility.ts b/relational_store/test/ets/cloud_data/entry/src/main/ets/MainAbility/MainAbility.ts new file mode 100644 index 00000000..586e4fff --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/ets/MainAbility/MainAbility.ts @@ -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. + +import Ability from '@ohos.app.ability.UIAbility' + +export default class MainAbility extends Ability { + onCreate(want, launchParam){ + // Ability is creating, initialize resources for this ability + console.log('[Demo] MainAbility onCreate'); + globalThis.abilityWant = want; + } + + onDestroy() { + // Ability is destroying, release resources for this ability + console.log('[Demo] MainAbility onDestroy'); + } + + onWindowStageCreate(windowStage) { + // Main window is created, set main page for this ability + console.log('[Demo] MainAbility onWindowStageCreate'); + globalThis.abilityContext = this.context; + globalThis.cacheDir = this.context.cacheDir; + windowStage.setUIContent(this.context, "MainAbility/pages/index/index", null); + } + + onWindowStageDestroy() { + //Main window is destroyed, release UI related resources + console.log('[Demo] MainAbility onWindowStageDestroy'); + } + + onForeground() { + // Ability has brought to foreground + console.log('[Demo] MainAbility onForeground'); + } + + onBackground() { + // Ability has back to background + console.log('[Demo] MainAbility onBackground'); + } +}; \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/ets/MainAbility/pages/index/index.ets b/relational_store/test/ets/cloud_data/entry/src/main/ets/MainAbility/pages/index/index.ets new file mode 100644 index 00000000..f42bd5a8 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/ets/MainAbility/pages/index/index.ets @@ -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. + */ +import router from '@ohos.router'; + +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' +import { Hypium } from '@ohos/hypium' +import testsuite from '../../../test/List.test' + + +@Entry +@Component +struct Index { + + aboutToAppear(){ + console.info("start run testcase!!!!") + var abilityDelegator: any + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var abilityDelegatorArguments: any + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + console.info('start run testcase!!!') + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) + } + + build() { + Flex({ direction:FlexDirection.Column, alignItems:ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('Hello World') + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(25) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(() => { + + }) + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/ets/TestAbility/TestAbility.ts b/relational_store/test/ets/cloud_data/entry/src/main/ets/TestAbility/TestAbility.ts new file mode 100644 index 00000000..65891485 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/ets/TestAbility/TestAbility.ts @@ -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. + +import Ability from '@ohos.app.ability.UIAbility' + +export default class TestAbility extends Ability { + onCreate(want, launchParam) { + console.log('TestAbility onCreate'); + } + + onDestroy() { + console.log('TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage) { + console.log('TestAbility onWindowStageCreate'); + windowStage.setUIContent(this.context, 'TestAbility/pages/index', null); + + globalThis.abilityContext = this.context; + } + + onWindowStageDestroy() { + console.log('TestAbility onWindowStageDestroy'); + } + + onForeground() { + console.log('TestAbility onForeground'); + } + + onBackground() { + console.log('TestAbility onBackground'); + } +}; \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/ets/TestAbility/pages/index.ets b/relational_store/test/ets/cloud_data/entry/src/main/ets/TestAbility/pages/index.ets new file mode 100644 index 00000000..fc1b5b89 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/ets/TestAbility/pages/index.ets @@ -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. + */ +import router from '@ohos.router'; + +@Entry +@Component +struct Index { + aboutToAppear() { + console.info('TestAbility index aboutToAppear') + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts b/relational_store/test/ets/cloud_data/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts new file mode 100644 index 00000000..25d9a6df --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts @@ -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. + +import TestRunner from '@ohos.application.testRunner' +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +function translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s it', + '-s level', '-s testType', '-s size', '-s timeout' + ]) + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams = `${targetParams} ${key} ${parameters[key]}` + } + } + return targetParams.trim() +} + +async function onAbilityCreateCallback() { + console.log('onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + console.info('addAbilityMonitorCallback : ' + JSON.stringify(err)); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + console.info("OpenHarmonyTestRunner OnPrepare "); + } + + async onRun() { + console.log('OpenHarmonyTestRunner onRun run') + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.MainAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a com.acts.request.MainAbility' + ' -b ' + abilityDelegatorArguments.bundleName + cmd += ' '+translateParamsToString(abilityDelegatorArguments.parameters) + console.info('cmd : '+ cmd) + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + console.info('executeShellCommand : err : ' + JSON.stringify(err)); + console.info('executeShellCommand : data : ' + d.stdResult); + console.info('executeShellCommand : data : ' + d.exitCode); + }) + console.info('OpenHarmonyTestRunner onRun end'); + } +}; \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/ets/test/CloudConfigEtsTest.test.ets b/relational_store/test/ets/cloud_data/entry/src/main/ets/test/CloudConfigEtsTest.test.ets new file mode 100644 index 00000000..31e6632f --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/ets/test/CloudConfigEtsTest.test.ets @@ -0,0 +1,510 @@ +/** + * 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 impligetProfileByAbilityEmptyAbilityCalled. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-nocheck +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from "@ohos/hypium" +import cloudData from '@ohos.data.cloudData'; +import relationalStore from '@ohos.data.relationalStore'; + +export default function CloudConfigEtsTest() { + describe('CloudConfigEtsTest', function () { + beforeAll(function () { + console.info('beforeAll called'); + }) + + afterAll(function () { + console.info('afterAll called'); + }) + + beforeEach(function () { + console.info('beforeEach called'); + }) + + afterEach(async function () { + console.info('afterEach called'); + }) + + /** + * @tc.name CloudSync001 + * @tc.desc Test Js Api cloudSync + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync001', 0, async function (done) { + console.info('CloudSync001'); + function Progress(detail) { + console.log('CloudSync001 Progress: ' + JSON.Stringify(detail)); + } + try { + // cloud config permission denied + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync001 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 202).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync002 + * @tc.desc Test Js Api cloudSync with diff syncMode + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync002', 0, async function (done) { + console.info('CloudSync002'); + function Progress(detail) { + console.log('CloudSync002 Progress: ' + JSON.Stringify(detail)); + } + try { + // cloud config permission denied + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_NATIVE_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync002 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 202).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync003 + * @tc.desc Test Js Api cloudSync with diff syncMode + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync003', 0, async function (done) { + console.info('CloudSync003'); + function Progress(detail) { + console.log('CloudSync003 Progress: ' + JSON.Stringify(detail)); + } + try { + // cloud config permission denied + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_CLOUD_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync003 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 202).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync004 + * @tc.desc Test Js Api cloudSync, invalid param, no progress + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync004', 0, async function (done) { + console.info('CloudSync004'); + try { + // Parameter error. The number of parameters is incorrect. + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync004 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync005 + * @tc.desc Test Js Api cloudSync, invalid param, empty storeId + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync005', 0, async function (done) { + console.info('CloudSync005'); + function Progress(detail) { + console.log('CloudSync005 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. storeId can not empty. + await cloudData.Config.cloudSync("bundleName", "", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync005 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 14800001).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync006 + * @tc.desc Test Js Api cloudSync, invalid param, storeId is null + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync006', 0, async function (done) { + console.info('CloudSync006'); + function Progress(detail) { + console.log('CloudSync006 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of storeId must be string and not empty. + await cloudData.Config.cloudSync("bundleName", null, relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync006 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync007 + * @tc.desc Test Js Api cloudSync, invalid param, storeId is undefined + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync007', 0, async function (done) { + console.info('CloudSync007'); + function Progress(detail) { + console.log('CloudSync007 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of storeId must be string and not empty. + await cloudData.Config.cloudSync("bundleName", undefined, relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync007 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync008 + * @tc.desc Test Js Api cloudSync, invalid param, storeId is invalid type + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync008', 0, async function (done) { + console.info('CloudSync008'); + function Progress(detail) { + console.log('CloudSync008 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of storeId must be string. + await cloudData.Config.cloudSync("bundleName", 10, relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync008 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync009 + * @tc.desc Test Js Api cloudSync, invalid param, wrong syncMode + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync009', 0, async function (done) { + console.info('CloudSync009'); + function Progress(detail) { + console.log('CloudSync009 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The syncMode is invalid. + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_PUSH, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync009 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 14800001).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync010 + * @tc.desc Test Js Api cloudSync, invalid param, wrong syncMode + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync010', 0, async function (done) { + console.info('CloudSync010'); + function Progress(detail) { + console.log('CloudSync010 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The syncMode is invalid. + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_PULL, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync010 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 14800001).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync011 + * @tc.desc Test Js Api cloudSync, invalid param, wrong syncMode + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync011', 0, async function (done) { + console.info('CloudSync011'); + function Progress(detail) { + console.log('CloudSync011 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The syncMode is invalid. + await cloudData.Config.cloudSync("bundleName", "storeId", 100, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync011 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 14800001).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync012 + * @tc.desc Test Js Api cloudSync, invalid param, wrong syncMode + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync012', 0, async function (done) { + console.info('CloudSync012'); + function Progress(detail) { + console.log('CloudSync012 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of syncMode must be number. + await cloudData.Config.cloudSync("bundleName", "storeId", "syncMode", Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync012 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync013 + * @tc.desc Test Js Api cloudSync, invalid param, syncMode is null. + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync013', 0, async function (done) { + console.info('CloudSync013'); + function Progress(detail) { + console.log('CloudSync013 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of syncMode must be number. + await cloudData.Config.cloudSync("bundleName", "storeId", null, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync013 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync014 + * @tc.desc Test Js Api cloudSync, invalid param, syncMode is undefined. + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync014', 0, async function (done) { + console.info('CloudSync014'); + function Progress(detail) { + console.log('CloudSync014 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of syncMode must be number. + await cloudData.Config.cloudSync("bundleName", "storeId", undefined, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync014 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync015 + * @tc.desc Test Js Api cloudSync, invalid param, empty bundleName + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync015', 0, async function (done) { + console.info('CloudSync015'); + function Progress(detail) { + console.log('CloudSync015 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. bundleName can not be empty. + await cloudData.Config.cloudSync("", "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync015 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 14800001).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync016 + * @tc.desc Test Js Api cloudSync, invalid param, bundleName is null + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync016', 0, async function (done) { + console.info('CloudSync016'); + function Progress(detail) { + console.log('CloudSync016 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of bundleName must be string and not empty. + await cloudData.Config.cloudSync(null, "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync016 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync017 + * @tc.desc Test Js Api cloudSync, invalid param, bundleName is undefined + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync017', 0, async function (done) { + console.info('CloudSync017'); + function Progress(detail) { + console.log('CloudSync017 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of bundleName must be string and not empty. + await cloudData.Config.cloudSync(undefined, "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync017 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync018 + * @tc.desc Test Js Api cloudSync, invalid param, bundleName is invalid type + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync018', 0, async function (done) { + console.info('CloudSync018'); + function Progress(detail) { + console.log('CloudSync018 Progress: ' + JSON.Stringify(detail)); + } + try { + // Parameter error. The type of bundleName must be string. + await cloudData.Config.cloudSync(5, "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, Progress); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync018 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync019 + * @tc.desc Test Js Api cloudSync, invalid param, progress is null + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync019', 0, async function (done) { + console.info('CloudSync019'); + try { + // Parameter error. The type progress should be function. + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, null); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync019 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync020 + * @tc.desc Test Js Api cloudSync, invalid param, progress is undefined + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync020', 0, async function (done) { + console.info('CloudSync020'); + try { + // Parameter error. The type progress should be function. + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, undefined); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync020 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name CloudSync021 + * @tc.desc Test Js Api cloudSync, invalid param, progress is undefined + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('CloudSync021', 0, async function (done) { + console.info('CloudSync021'); + try { + // Parameter error. The type progress should be function. + await cloudData.Config.cloudSync("bundleName", "storeId", relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, 123); + expect(false).assertTrue(); + done(); + } catch (e) { + console.error('CloudSync021 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/ets/test/List.test.ets b/relational_store/test/ets/cloud_data/entry/src/main/ets/test/List.test.ets new file mode 100644 index 00000000..c5070bd5 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * 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 CloudConfigEtsTest from './CloudConfigEtsTest.test.ets'; + +export default function testsuite() { + CloudConfigEtsTest(); +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/module.json b/relational_store/test/ets/cloud_data/entry/src/main/module.json new file mode 100644 index 00000000..cd018fac --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/module.json @@ -0,0 +1,62 @@ +{ + "module": { + "name": "testModule", + "type": "entry", + "srcEntrance": "./ets/Application/AbilityStage.ts", + "description": "$string:testModule_entry_dsc", + "mainElement": "com.acts.request.MainAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "uiSyntax": "ets", + "pages": "$profile:main_pages", + "metadata": [ + { + "name": "ArkTSPartialUpdate", + "value": "false" + } + ], + "abilities": [ + { + "name": "com.acts.request.MainAbility", + "srcEntrance": "./ets/MainAbility/MainAbility.ts", + "description": "$string:testModule_entry_main", + "icon": "$media:icon", + "label": "$string:entry_label", + "visible": true, + "launchType": "singleton", + "orientation": "portrait", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities":[ + "entity.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.CLOUDDATA_CONFIG", + "reason": "$string:permission_reason", + "usedScene": { + "abilities": ["MainAbility"], + "when": "always" + } + } + ], + "metadata": [ + { + "name": "MetaData1", + "value": "MetaDataValue", + "resource": "$profile:shortcuts_config" + } + ] + } +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/resources/base/element/string.json b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/element/string.json new file mode 100644 index 00000000..1f38082b --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/element/string.json @@ -0,0 +1,44 @@ +{ + "string": [ + { + "name": "testModule_entry_dsc", + "value": "i am an entry for testModule" + }, + { + "name": "testModule_entry_main", + "value": "the testModule entry ability" + }, + { + "name": "entry_label", + "value": "ActsContextTest" + }, + { + "name": "form_description", + "value": "my form" + }, + { + "name": "serviceability_description", + "value": "my whether" + }, + { + "name": "description_application", + "value": "demo for test" + }, + { + "name": "app_name", + "value": "Demo" + }, + { + "name": "form_FormAbility_desc", + "value": "form_description" + }, + { + "name": "form_FormAbility_label", + "value": "form_label" + }, + { + "name": "permission_reason", + "value": "Need permission" + } + ] +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/resources/base/media/icon.png b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..474a55588fd7216113dd42073aadf254d4dba023 GIT binary patch literal 15458 zcmV-oJe|XdP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXfJNHRMK~#8N)t$?W zZ`*d)f6uD@IOn2&LJ;lP6@!gHh#>Y1!r&0HL_gDqb&`3X(Z=GaQp8SP` z92In5!tr>lHv4nxKS1{J@p1P!+F4$_JksuYcRrnVr_*tFKEi|jF}%m8r`_Y_l6p^% z@+LnCznqL`mDBrry9$FzRWuxkQF=}GpwhbiR|yW zmfjQNx4tFelhpeM=s1qPZ}7VBtuHUqIh+_+IvN7$>(jXIa?55SEAd6rfw_FG^Ciq> zUAOb*d;6XH7UwzzrTnE1QtLJmPK4||=GS#JMbf8dX;2o^T+5qYx7QF%t86tY^M!6V zrngTY z1udv}ju^g5nNRXGgh*Bp3Mrd$sWa|p#az3e^Glh~4OYDwx?a*KW72*IFc`5a72{iM zp*N~%>#A7GyQ5CGc@5sreOI4Vr-jh46-ty$UgtlNS4u^>BKcJpW(i@*S9!$UCqmcd z(U6LQxPK-@LYcI@ROQlUqYfv9)@pP1D z^PGd_#Bn=j?h;(A2YP*^zO{q!-impmO*sshM)pxC{aRnxpLI$OVz(ElViw;?d~N$q$^VbIP>sa0q0)N~6iq!!fI>IcRGDdADCq?$^K61=g>C{IY# z;~=ksR37V9Yzp%@sRJ8ebxt7()agtNj zFX-#JY(~NHNecrS7DT}|J>yQfr$J*Ww>;PMMSj|?ifs>m;mOpS;hB2QJtAw(Aw2S_ zSHe`NtQeUBZN(O=rgRoV{J5F+Ft*YQkw zwtwkXsI}a&=y|SSZxEX3H8VG5pvDb*DypGrx7RHOJ0i^ra2-P!NRFO4D{+Ry>|JXL zGjQaB$9omq%IUE9OgQbqtQMtUxwo448OTeE6JEO(GROhuciWZ5BouJ*L~LTeo;4dtD1t#pnhtSi{UW~!N8lsnLV4AB&!P?*BYDt{H& z%&bDsz7IE15kl1~PvI`8P44N?xzRmdc}}725-w90Fdv0S!A0anyY|dSG}_^L&))LF zz4K+fI-yqH>N0 zgo)+iY3)b8AJt+2Z>KNwTQ-d?GjYyuI%!>DNlTFvDiBBa$CrlyNy#r_Sho8!34uL# zRbE+7I??*TrZGd;$+f!%8_B1Sc*Ia#=XozCRDucxF$H^&J+EfrLzkl0 z&Y3P^^vbm_^GJtcTe;>pe{n4!{EtOfLyv17pOHk&6d)QY28Om{l|N|LJYM(9dcX=m z(`(v2zJ^0${=gPYRc@u!raOd&0;{ZWR``si^fg~l4oL?SD>EgWzMqA-<`?rq(W^EZ zVWn$bq5GX_&GgJOY`!oa&@zRZ&4hiDHmw<(Mk_N)4(+wilna`8P6Sjw)OS?{y0(N(0*);t@8SAl~B`A^+@J zV1RVu>FKY$>KaP3uj?dg$oKga*<{6RD1b)fODgTiZOJR>{Kkeu4uk2y#e!oE4iAlB zYL*V8DT~1MLc{NwyHeClv|$!rLwWSf$b4NexAR)uTBgvUvCBJO=sfB6_1wOZtOXTj zc`5k{U1P}t$8tTmwm1Gq57=?FuXc|tkh+fj*LX~;FJx?f%NC4*45f)%IS75<;}ANX z;gHpyj8K*dUZi4hTt8$GpexJ4q}CPXVyW%DV;NflfVk+qu7f_9k z*}8EIodV}*+31PZmwxv(r&~BEn9C$YJ9U6zg!~5>d$_Pa8+ad7I91;c_0IOtEQZJv zWv~YzHgi=b!-mWfXtn|_JkoD5oK-0qxdz=bc;8A)h$8Ki7uj*~)FIoxTCmM)Lkx$^ zDAapMq>9(D*y56Y3)j_pPZhR{lBnF6$6?8nU&c%yomL(4$90sL@mADWR@cgG>br4< zm7f(4kA&8Grlx|Pqa>B}@VHOlNlK;+Bw%8XPl;5YrIxrI!FgaD+MM$T3TD9_g?p$n0Z^z z(ZK~3V;*H`@3>UjK<`U8)$c<0O1ic7Ev6ocyuLu$qCG4Y{bp{Y=5PB;{k{&5MvzIV zqrB@hYXOE@LmvV6T#B|X4dE6jY+>wEAHh2P=EcesGcpX)dv1+PVs{Q^sw4rG+6 zIMNJ)vc{%SR$PJ)BEf_u+O<&U!M5VQ%rC4^x?<;d{RR~!z6NtUq3;)^4s7W1#)j^v zagl`{s8YEpK6_jhO$@_^<2ryqkqSlOyMV|^!)TC@2*LI`^CDdG%EMG3N_}|VeMXsg zreLRr}}fkU0|;F z*7Y@d*Xq264ee>$vQAr(zQG}~k1UIKZbPoo zBq4|^xF`pLiPaELV00X>9O?5D3Lo=a4w3a>7DQFw_SB8SWLAZInMO&pQ4!LSj~YD6 z@OBztL*L8Ob`EK5=<7MJK_T?^rLFqqOeZgHg&A?6PjVts8H}BcoI;mGT&hNI$*O+_n?-TzQ=5&@FU+ z8%JCG;=yD5GrXl(p=k!g0{xS2uj3r!y6+pk&uJG6J=Xz^8H=fHEN`Geyfj0EZ=)FZ zy@n~1956HJK-yv(s;r3#B|r&&i8b$4=&<8A?%_Ig;+gcpy^8a?q58J3buP@kLYeB# zuvJF4c@1BKR_u&3Y};O=+1J~;*T6d6N2fErzRvXb@UVNhXB&bjsk}B6yjIvbbueQP zP_b352q{pB@qe)PPPC;?V+3uRSYKh6Wh-G{U!Yyu2MUFQ#d`*N-+5JeEfd?K^}L)s zf!p!b7#;VQb6lcB|I})~eU0;~5--2s&h1c7E$a&)Ds*<-L~vtY9Bo zkapu+;9@BYMXVY#B)(0sTH}^k>s8%(pgI{Xf(haf_V8hgi`#C?Ct4y|0|!+}!f3DH z+7lPAq<`@md>3KNVE+qD(Zi^+g|6Fue3yRaI^D*%0Okp7ODn37mjONA%=wvO%5xVQ zTLN#vEcl-WuJzOXZ*iUv#jn9!=WG1ER=&-j$2yn2*1lnGH$&%rZA`Dxw@t4VG%`~H zf9Y}|9;`TQTK9mS3;I0H&4~Yo49$KP^r%W)`Y{~?48zu$u*+BI`E4V#7j8e-FPMdy zlv}aA@EU9d+kG}};U%9{-@sDA#eUW{uhD8bEb>B1V&8Xp-q{fYW8z=#H*jr$*E;_$ z@M<5gC_cd5Lp9u}jyf=BwmQi6V+=lfOKvJ=X!Iyx9EQ#c)`b4 zKvDGyx4pWr^=v#+VuYs=Vk6@e7u4d1!Kpb%RZKw6E3Qj(?^v^!=Q7Om@wg(g?zN8j&sMIKz9iV4 zc4x~y!k!I8Fuzx!iz65Z7T|G~b`%6DdXCfb5(*ml-~nmlifY7JlTJMQPa*T6b2Jn|a6Da6sHJDjm$zW)COz7Nma z@m_;#<#XO^G&--#XB5;;-!C3HD{Omx?S7m8{~l__aQ@jdxtjJ|GzXroXKu&PLYf6O zL+8I%{xz6AQnDcGd_$FMLthRI;Udw+8<#Aotm2N-r zn4jnMT(+Iln*YY{3tt;|=YLVISAuh&+d6O2oXfmkV-9ew;oRt2c{B3U2;nXGKJ=PL z+kCBE*O}|i*TS`N3fp=@=WX+a*XUe>ZQUNzwfq_SemU6@Yx6j~5$H6 zu;u5q_CIgf^3gE!x&`ZZ`D@tq7DaaE&kp4gtA`ZK9SgCgo-bd)9K39^W)8b2Ztif?dvTxo*6ccMW}uCEo;sUVl;Jz`QTk8!jk$#usgAFpX;qo!2ti%EoIA zMVkHHp}Jn%HeC1V*ZXeR_Pxc17mAz<8oHy`I-B#ioy<6wZ?7A!-EZ?6s*Jud5+Ofi zIg%24U0|46NB&xI&1(x=cx_w_ua#fptNCrb2GV;C--2uPXMCZ^x#0Uk%@ZZm8Rh{s z-PZ;=LkmNth%>xspLc-rszbie_3ri@yg8q_KP}()(Q~#Qp0=~MZm{Ry`TmPM=t#Hu zU489s=>2TBdoiZ(0o@KhSeOi}UO~Y%z6~{qQjicKF%WU@&%XNl>2bmm0DGU|9UYQJ zIt}Xefv!Av8x{BN=Cu2Gd$W6gd)&P{lSi}qb$lsPMF`*5ShqX{&_quc4bAJjc<3)rwKDgfRl=YcS(%!j2KHR5(iWb-9aNb?G8LMhadSeDH|Knt=S;nP8H(1& zN0fWH?9K@C{rR-JHUE6v-J*beX^Zyjd}Ckm_f&JNh4UUTNPeCzQt$ckVfXZSzuQ0F z?M}PP?%nZu_k;K6-M6U5)#_s_`j&(uhmE4I^64=5C9bsBI*N}K zw?J1f&}WF>1^N|_l7A5nA3*ZB4$aOKR8BM8isEME=#g#m6;6TbY37x^mW zNFDJ8A-+5BP?n+ZxO@NZu=@ypxZMvV|NN9X@6h&p@CH}PH}L3Hpz z&-EizlqsKw{Ud!pVH_A1bZ*ZY%=kzmdCjL3TR;Ux|Laio?6+n1U0|;JU3!VK27hn$ zvH!)t`Y)fYsGw9{#|fW6=j6i_!N{-zRd9lBtmA9`2@{mm&%C&!9Tt*Q4>++32{U+v zB%SljvqQa3kjcDxE;SV7k9_>u-sgLNNQ77V%WB%@)e}ick3Qwuc`$P!%F}4{?pqXQ zG-%rWD=>c&7=`;wvE)M~E>v|}XfxQpvzf7nK;_d>mvJ|I*}mlUni3KXg*>TQ;Wa+C zP`sf(U*pK5AL`ijs3n63tQnb9xEsH3uNR(H3-O33t3(M!Ies$K*BOeD`ZQ?gt5E94 zLr~XIkGbqlq&LS-@gUL@DQbkt&*=VvP)WEX_2vC+H%P@33eYf`p9-<03Y$FjbI|iZ z4eSPtcQT%AS!knA)wFV5&_dJibO!Tg{66qj{jJhoGlZt$TP)ltSZ@3d)&T)4WbmLs zQ9@TnE!@|KAJPCZs6;;ndgeY$eg$iZ`BAPm9E(X=0-^nhC2|_z%``IH=}`&EdlkoA zy1zuh@0ssz4-dOr^Pf@f<@0X$@CiBedVLOFdCy#x#TG*7fZRPb3MQM-7R0^ zIAS!<`Ito5u8`=*;L(jC@)OF6Dv_#f_5S=Mn=#qfE%V|5Bd`w_4ld@@fc5>3!5`i| zjxS2qn8pZ7QSjG-;%;2qRt}9&UQg?Wt1#$YF^X!l%Cw;BH$B_UZMXe&YvfrLoi94# z4f!&pF?A@XeuG#9wA?J^VE%@7?{LhI?^wv(x=3+RgSCrzkQRTU&XKyu=L_u^u!DxF zClztw8qaw~F=9Q{M+x*HPbWQ)MURo;MCiSRt_z~~w~xDT-|u#R_lJ~bkhZr?L(h4vO)QenY#q;#a8k38h2fY2B{L6z2Ir%cc(bpF`eBC1}zo5tV zI+VvX%5*{vC<^%JS)?IE*KY)t_ zR*T>b!uY_F@jXg>cSgJ}He5gu3f-Tn+?(tf*)O`$_ZqxmrJAh)p7)M2Qw8ka?o1oE z3wn)VzC?=B481U_K;_AK^PaGrh=Cjwf;=5rpxvGf_0WQcY&(WmM)A0=3UW?#zR%Cw zAwUmR$55|!6K+c(j(Zk<(Rv#jS|M+>|E}=0Hr>y`c}T&l2sh9yYiP}im3G-yAXL%$ z&N>R~9oCI5m*w&{{bBdb$K&qXZ*F!UKim>3&zbu?r@TebClppzZ(6Iu ztTLhRH*)S>^|5L1&zRL-lWmH@?+SCtOMZole100m-HU|s&tN`5rWb;toyE#JDARZ) zs39p2w?5AC<=OJN3QDLpt%RWv(g<D^bECi1RPoG4Aau1p0ZiEPC`7 z7}Byu>xh?Z)Gt|(++}OvHD1Wv>}Szz-{0Ud%_n1^LzP142Bl@ai${5sdz6P(pU|?N z<^1b-GF>=l#=}-2Mi6jj{l0fxef|FeX2taNtoY8~qHuUbkXa2Pz&*kdJ?*(+nC=BV zRk?Mcf>)|^agT!AL=On86pJ@q?oi5S6mpM3?h!Z(C-SobrjNTQ>mi|2L?63Hl31ETM82B?t`DXxdR_il|rO35ANsgesKzBF}xG z)tSpwoQfL85d#^*dP1QIhj{YbPXsxwRem4omNA*`GjY}dcJkXN>rul z<$l#NG~r#y0mCE&SE`1}s8(a)+OE2e_e$n%!A$}#c3;4?wk?OouR+s)4b}sLqIY=4 zqQzxph@kWN=OgP>LK0ILgHuz2D^uqg!WF5jPnYh_hR#jy2eT)%je?gR0`__t0N2%C zZ*h+Y(}Z>kVh}#dJbJ{(>e-VT)-G9e-RS)&d{2KWhoq*CHkRFO`C3<0Z^zwynhlbLzWyESf&- z-oJm3m)45avsP0VNI5;imA#fvQS(@Yfuejel4C;VV)vG{FBK2jTDbpoK6fGG9~6Xv z@ZvY=+H+T-d%*9h2+Gp)90RCfx`VmEfL_Uv($2E2!djr6Hbho0vlf`!{j6}U-{x@z zl}g>e^0$9mwNlI7hyyF-sdNWyh%?;zSJOPk^MG8>v6gUy^z+9;voE9q@cHvkvUo9n zh6rE?Osu!12P5`H^V5;px#DUDl9j5x(QuhpDbA4~*M5;wWL@fUwfTru;$x|%6#c12u{xgy;ej~ zAnd5T(9k0>iZe7t-@Ung=esx_j*nwOSJAf~4<2%Qz!0+f_h8d=fTU~zpEFj3Q-{FDp=l%Bf%-+|742%r=bPa8yh&yDAbTV$4Ql$@p(dIdll&zTs(nREi}B!XgNaT+|Tzzd8TRFma?|cb^E%(>x0Ux zeH(KlxL7NLJs^eIt1EC?r1z)<2qX9qLK%XB@mfz6TVd^$Z3K%Ts+D!Fl=J znXrz+d{gg(NcjDLBBNMCZo=(YES-oFj3cXSJuLhv0qDb@s#{K;49(;SEiAz{jY8T7 zE&u7UJzIsiHEQg>XCAJBW!693-=jE|a(O}^G8oYc$ZX72&RZ%(_Dji)4$QeVtH;bw zWdLHAi|J4=1I-ttS0TGXZF{SWmAd!uh@jL6&v3X7%Egy|iarPMu5w*Dv%1Y&dU~!4 zvz%19Kw}&Swn=Vl=u-m}3_RXl7!|X52~ma0d&=!ssAw}om;5}T$0xSjgig26vJehg z)qy$BbXZ!h+XP(3aCSVgUnG=yJwsl$BFRNgyj)>ZS3y?D)e!31#a8n4)+sDHR=v)rE+1GJeN>@z|DFw} zZ!vfu&!mN3N!0@C#~YxZg^=Efnp_!+E~R^c;T(`>LJ#Cup2~IU3{e{n(GVqt8$C&Mbz4y%4(bPNIj; zKSOWyw}dw`>@R@Aw%}oa(7b#XyascA%c1ctnCW)?X+!AMnEJUZXv9eFE&|4@7AEOUf; zBei?;QpYscqQ<3$S79)cacx9#To@(;(n!mQpa(ieI0z3k8R&>BjnR$!gjvvBL67!Y zyp5|^e!(`cky2kG`tdGkTNIwUV%7EC=; zJ)e{|3)+W#P_O!fZY$C$g#Qeu?p-D9+k7gnIFb{+K;FE{i20|kg|$wy19THugnI=A z>xnU!k(Y9a=PvuyqTNaqayjZyJ7aqR(xlPx7yi^=_+i2e<>hq_%jG!t(2mek+4&QT zHUvZ65GRowvU5RGa>#(&c$4#^UaLUOla_)Ve3ai8dr^wz)FVisz~Utf5IvMOX-mEl zAWBkMv<{ysAE^ooP1=Vh=zUUprArm*7`kqZEdr{s)>ZSzzY5%fApcuo0IXEmE3mX3 z(4N`QLotVz>X5U;j}?Cv#R<37h8|=U6dg%9DtkV_MPBhJ^9ZIzT9) z*hcHlUZ;dF-41w}*_(SBDGj~YW;86FKueUjW+kZ_J z)fczpe(-4<>S=7BamfGm`Dyowh4<&IxKTKvcKLCTQZf%7Bqxp1I(-g)t=Ew933^OI zr{)RHi2*(F3JmtsuG`FDdk;5yD|h^bU;Nb{Qr#9{q(h=W3_0BDf&7<8ClLgQd1o$F znkWQzDU+P_@Su33ir}7(iVv<+Zs(wkAcQQ6L}^m)>5`tLH|Bf|7-u`=(I^KOws$VJ zjd=>mJnKo9lnVzLy70P$W}`#~Pn*n-C-UjTr#aG+R7!^;%}^$zKrtzqMKRp~*eX&m zZ$?2w47jC8mx&8O%*c^uRXxm!I^$8{-h&s+ko06qo=%lIfA(+uE_W}%0jNGfT|MVF zkT9U0{cT9{eG?8L42w`(SrszxcvvnIf_V-gYz^Vc`qC*@RTft{EsACEWa|+D7;9l9 zrO+P$Wsswv#{4!y=7IJMaoyxg&Xza3&v%#I|NeYO`ndBCu*EC=l6|M00ok^Y`Wwa75C&bU)X|^(4cbGA z{RgO9SZ>&937TK+t!J->lwQDCUccm86=`{ut$k+9%*_= zQd3ZMl0KCM(~*(OsVUm{mB0Qw7%7zuGlKg(nbq_F%VcI@WJue@A?o589SY;~ufB?DLtP)KdH!i1z3Ro2)J`AVh_tfA*Zs|>nLsuZU1f?T&Ziz@ND zH?FYMy#h^x|MMJHCsBF5KUUEiLOGAuYN0UmD`_OWf7l)WYXO*9(-^0n|J5k z4?f=RzWs2M^T@LvNu`s>@DzojTu`ZxP^)Le)4)8n2VQ*U_i;hbwd#YKo|E7n!4bS}`*<4ol?7`j7&-a+HVn7(mGavG}_} ze_-QJ1m55Hkp`a}obm+0$3YRVzYu=>%=JU|lL>sDiugtV9VX0?TUcHoMmPvBFE4Y= zW$LOR>vE~hk)j|`MUi&-OS*cYb+F#NxlnOquH$w0VQ5zIqSy68^C%;&YZnTxO6w4U zDqx4%#`1`UR)hk~b_nRahP7?wn_|mX!?4@2Qew%-F}nThXr=$nW6ShKD9I~1W7_yk z9yR>YDeio^k2rj~{>}Sa@TMNt-X8H%9|8HxsT1h|WOaqt=2uSwofhK?ri5A+RUNnB z%u`9#gz$@}8Fsm=fzmF35x{rqI-Pq>AKAF*@~0U_6r)^C z31y6~SY1PW@}1r%+V~EuA<>nWMB9Dc+qfLgYZE9>Wj5a8(xQyHniBdsVKZ!JdQT1v zWH3ywLW;uIagjIX9OqUI1g0ZYm=y&FFMr}9FzIVRqfh6$STL#ghE3BhH=HUA@6%4B zBNao7xwqy^1UL9=1<7}VO3;s4_pfs4#w)@hfmC2qyjR;O3Q55`KxOWk! zGBb~(%)GnHwJ&3TW=;ADEq}Uqn%M7td=Kk}KDAqJ?4a}l2Mx0$9?Resi}@N{Gimy= ze8t71ydKckb6&%?t}xdRs^m#fWenC?@2h^L=6{iDI3%qsafUL`rnlle#)i49vGY4^ z6jWx63O-_lbnSE9`lI8{=_;lccwxery@0I`m!31QgcixkNHD{SYF+LpkC;F5f99KR2C#Ur#LZZ;4FUXsdfp3$uk%R z!R#d`;m}~@AcMvb^*h|l!d<%&$sCE?2ba`#LSB>GN9ZG z86mGru+Z_%wlFtVdOeVZ;R&{RbKPt8g>9W{IM?H!<@y@F3E5UK-T~@sUa&F9%J-h@ z&cBAQMW#+??7F7ql`$E_KH9>AkX3CCEL^zNw#cni=2Koi6oHr(7@fy@DAJl17}mX}G77^A=8ACI@@vmHp@RzzX-Y#{Z?qq< z&7bRvgNv#&!>C^oXn58&S4vs+GegsV4Hw0itpr>=W~fBA?n=kXt1l`K%=*A>l*qM? z<$Jz|`dXuJZhP{M;v`lo0qdu8IS9ux@-PpmMNX%3vI>;kfdw?JGSUc)yc~B~CNAw7 zir#C`^|#nZX!aqraytDI5s0OxV?0W)%WbEyg>}5pp0LbSBhN*Z4`@1HgRWO-lq;-o zs?ciHEYu^fQJ10)-STP%FJt(tDBtR4&H8xnRy&Vdd~}kpcnB_z zT-q{_7f4t>9z2LA1do+vj+5++8vQq`uqEijq+vXvd>Dn-wi{?oae?6}Ma&)&A%n_b6hhS(ns%pxit^s9ykF#) zY150JzLy7k?Uv>j!ifT;jyNl(1wTXAQ+RVK3JXnPEcQCx?z0;@Z;Ju>9{iOu=@TbV zuKfcle{&N)7+n2o8P5Oa-~YGB#RU&HqmijD+yac7BeZ+=IBq>$_PV!mS?pKo+<)3e z%n43fQHG-YyB0Zlc^$xZ%^5Pj@3vh72I3bb$oFZ-lW zS!Y}jt*k+_@0wrzWCpwHviu8AaFFh>F?z=!7-Lmg+uC12kAbTqRyPB@Yx)7MjcCzL zIIelrsOFtqesb|l5TepR zqNz_?SGhv0oIEFLA@$a=BxJWD`w&{NwRIgtXsSr_#-Qq&aG$j57Fb^6QOR9bC=;7H zhi}Vmzp<|vm_UutDUJ%H9d8)ktsil&s?jx zW-+X0e3ysa0loN}m;K-QC;u*8SUHM>PPwlNEg`lrvX?=ipD(@^amfk8kMHWiu0M$N zs~vtnN14kaeWcAkkD@fA@|GxErlIXiM#)1c-Ukd#T&C~J2}I}!!hC~f>c?P8IH{j` zrJxibR3BQj|1SLiDqY#Ff^L`v4(M(J=JxrnI;u=LW6)FVuOmy#ZZ(v(|1vbL!Ik1P zO;FG2%iC6@KP~k4Ev{9bk@so;xO;zlv)li@fBx^8vPy|!QD6?l(rS@Xie&;!`1O#$ z(|WfUK0ADPERXc9IX}Jf8BeV`dN1=JiZ%55WvuLnkfm=N2=Ve&)VgN9S4h^fB2*S zm{t*1^Y6!SwE#Vo?o^~5((Txwj*9y;0<{|l?CB5+L~%Y*$@k?@n2PXq3Kg7lLE^ef z5OUh{aEah$K2HorD2>NLTZ2%roF9IYg=FQt*B!E9RaGJq%G7jHFU(t7?VNY$r*gjAb-%-l+KXx zeI9oc39;N8JwJXt@BBdH{0T;dvjY~_sCbRsQCH5l&CVK?{QQ5jdV&W^~B#Xm(fIV9wIXr`^sVtk(r}0v9yWt z?dsdE0?kSZj&Tsd5cg1>k5mU*P^s(Sg$64UMtm$H7u`kl$@#e+c`FT49{HE zIQQ!agbOXZ6;8b9KAcGrMH-{Fb=4ByYS`R3jJpZ(r{roEjFMfNqGmlGZor^PSt ztmp|4($o66U@Ir9RO+1Qq(2CuvhN=5cXxPXg*;FA^&;DVdh(!?&;_#^hV4|QiqY${ zu=-SwZJejAqY(7JwBssglPFq`wY`RNII~&OU@$zIq~E1)$JwE8)kgBe4?P&#k_R_> zRoWy1R6S2t>|1438~Z3T>U-%d;kuy}X#|4To*}|OBtAlH31KLbaT#Wp0f2gv&_6pDLJROKAzruA zrF9|CA$v$1ATP8LZ@g6j5mF7+KAFkMKP#)BxX{8dKHuN(PB*u522I1S{TYId4$weI zF2bZ4<eWjRP5I!zpm_2VZSqUnHo%~8_AkN zw`yec z-0dDE`am`B-K3t6bwI*zy(2{3bVc9tspU6K^2(?~l5LRoL?7qAcwLV-!Y{ zQ9ry#uk8ykl+F zH2dHB(SM+i@;ZM*XvYejUgD8jn(dA-ZJLuA$|4-=NRU)8q&Q#?+w%un08i%y72=$! zcU=gr$zwozmoE|BUG7S0iy#Y5^sC@y*pf&1QGoR>P#sbvjH0z{jqX6^W4%|g9B*8Z z=~=9vt(QK^8zX#$5O0Hi#;75UF{&;U--_u}$gv^@AiYwSWrpHf{d->#Yi$#C8LDZk z0n~wqio}SimeVrBCL;44DL>uz0~a%7I7j;N#b*rOMUK>@?T0c#>o@+DiiC&)$^q@< z>MACRbgr~4PFw^arE6Qy19b-z64db>pS+lrc4UrD_0%4u;DYBTK0tLr#Ga_<%0|J^ zgT!)`k4?aAA_8gZ&`&-_L8gkj__hNVhCJky@M<0F#{2PP2b@C>`RVb{RykN-#T%0I zeAX!;yp)1grEyK8=g0fJmugx5P8h~2UB}|upp|Bm@T^!EQ}~K%H7p&*#f&ew)n``y zA}5hFUYR!+@kTvNnOk2k*NC1FqS0pm8$bF39X||aB{*WX;HotW(&eM5QbKu1mD!?x zuMTH_w`*L-hZ^}VA4_q0C{nr+u zX!;X)j}2>|dd^VcqUK5Rtm7CRxb&p!t0#`fgAX4QMJS3%<-tt8{Dm^xgRLvyLS#U` zio8Vu9|(J%Gxz6b>`x=mXbwyZ@}*(ql}B#m#fJ`2DssqQ3POqgjgt2$k#$V|V2$V6 z{<#fz4bLuqY?smTFMUNmdIKf<-~8SGlI=%ec;mREm@HjRX*f(66cBMz?@ylE&?bsh z@s#R?ew0BbZQ+kp`U46IM6|5~Ez2ZdkB^+RYy~d!Wyw(lOy$cVp#7IeiW&lCzEKw8 zGhArebA>XW(l}@Ks0#88AM#=p=?4tAHNMUh>^}zRVgblcD*zuJeB%NHxA8~7&3F3K zAYd$S$x+vP6FXyZt}- z{r}3!ysV$w#X1$JZl72G@wkTCr@<`VBT++f{`d+4%SsK_oWS!)h$X)7Iw5YwMUI%|DP($<}KZ+-u>XG?b9I5f47B0;%?P3__l;YH& z`92CVO`RCVP#y-H@nJZgr1<2a{xBQ-lIK~pAH?^`km{I01IzdD7@r|t*_4y`9@NA5 zq$<1;c6}R8!%NJeZ{_C?c;3;(Bhvgl9`1TUrhJs+)3eHTVN^Wtf9v1;w`bk-!U80# zPb4Nai`;Q4VyWJmBm(HGVb%x!$o9g(m z@BNm8)L5LW41ks^%nDsO9dc#n{!ihj%?OK8jS5s)q|ox6AsyuMaEws?(61<4>Dl&% z(AowWE}sZbd2$Fpd3X!W{44-|eRU%5z)~*gA?R**Vyu2$E5~BWM~PgBBq$=kqGE67 z`@|=dDkKs@MXyRk(q=Sb__5!7i&kaqd|~>q`yW64akf!;YC=W70<8l5tW13-+~|Y; zkOj7m+O z!5pPf&u5hW8I_=fD zD*;20N{)BIOQ{tj;NRl5w-|ch2}M5c{wK!f>CfqKoBq&WEM66PqkaN5`Y)t8TRI`--F?$f7FyF2*vpx(dgmuRWV_Q&1- Y0jIQKqpXab7ytkO07*qoM6N<$f;yQ2zW@LL literal 0 HcmV?d00001 diff --git a/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/form_config.json b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/form_config.json new file mode 100644 index 00000000..5990f171 --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/form_config.json @@ -0,0 +1,6 @@ +{ + "src": [ + "MainAbility/pages/index/index", + "MainAbility/pages/second/second" + ] +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/form_config1.txt b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/form_config1.txt new file mode 100644 index 00000000..32f9ff7d --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/form_config1.txt @@ -0,0 +1 @@ +{"src": ["MainAbility/pages/index/index","MainAbility/pages/second/second"]} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/invalid.txt b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/invalid.txt new file mode 100644 index 00000000..5e41923e --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/invalid.txt @@ -0,0 +1,3 @@ +{ + "src": ["MainAbility/pages/index/index"] +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/main_pages.json b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 00000000..ceb075cd --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "MainAbility/pages/index/index" + ] +} \ No newline at end of file diff --git a/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/shortcuts_config.json b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/shortcuts_config.json new file mode 100644 index 00000000..ceb075cd --- /dev/null +++ b/relational_store/test/ets/cloud_data/entry/src/main/resources/base/profile/shortcuts_config.json @@ -0,0 +1,5 @@ +{ + "src": [ + "MainAbility/pages/index/index" + ] +} \ No newline at end of file diff --git a/relational_store/test/js/gdb/performance/openharmony_sx.p7b b/relational_store/test/ets/cloud_data/signature/openharmony_sx.p7b similarity index 50% rename from relational_store/test/js/gdb/performance/openharmony_sx.p7b rename to relational_store/test/ets/cloud_data/signature/openharmony_sx.p7b index 9be1e98fa4c0c28ca997ed660112fa16b194f0f5..5417cc6844ca22af15cd65131d02657d64a3219e 100644 GIT binary patch delta 1086 zcmZ9LO>EnA7{*EJ6uPxsU`TXG3{R6_tcmT$UD9f7e}BXutK+zJK9^}Yj$+CQDXOBV{C7f z*hEH&!4|qrhgKNLHn&Z0Y$t(~YE#6dh_E%8?X5q?IaDQWTC2MMmwgMTrtPfEQWXl2+?bU8L+r z*Ru2;zR`f)h*Lp@GV>)0_$te0!&;dXsueM45F{z&*6eB-i!L%?yLVuc)H>v`|Jm4F zsB@89C32Wn&JKi}Xg9c$r4z-ltOAuX^}f~Z$OT29DAVlM;lUSf1Xl!|_W~neAL5h`fPi*P*^fDZbbY^;&;*kahCK zlBr1`CjtxM@F1tf-20HXmA))XNEVxVCKg>ci1Fi5$69j;2vRhlssvdH5$Mx_g! zMcI>QS1U_l5#pq7JA-CZ3$&!}z*gG~3_qCUP;>1` zDxu@`G<*Cxa*RJ1uV}7|UY(qE+eeqTP|dcT&}c3k?3Yl-a{Q!gc)hm2pY9~RDi;|B zsNf1M=W_ywULOC7JR3*R@qA+b{Qetv!S&i3ZQC%71zmHsM%!)&ZDT^ego1rKaNVMB z6#g->QDDG*HhTHpbmIPW0$`)qxp8u~Kl|U_jc?8-w@GXX$FQ@+5|OQ8slyu1AUKMg zcPvGJ!K zxOvNX_|#qT&R;{e_YVE@?yWCQy?so+ntA5++b=x*$+wyKiRo{yzn>c`Ek$JbU0=4tlRzX9H?ZNC5j delta 994 zcmY+DONbkF9LJmNB)Ym$P})O1Y>fxO>}F^3+N4nHe;zwC*_}xy$>cFc+?mNFlVl#r zJTea}fgBb=5tdw}2d#&Sr&_QVPf~A!C`wUpA}9)?1x1Pn!E~i79)F+j_Y1$n_xsCJ zzn-7Ni^MR#{@f9DbT1KkD0*#?5LT!ejYN>g;Y57>@Q8{iYfv;2I|DCb@&BxmYYXTe zw1ED2B{@?pduSTlhNvsai%BF6r{Uz*DVELN3L{%daWdKN4Q^q9J@)z>?Oab0Sj{nLgOx3h|%1qJBiDE5xBbU!ra0~-dW&k`I z1p}IB)T#m>F5if}H)lr#(lr>I4%r5uZK*QLgoL-E;VB!TF2mU##&z%}$B~3r#v3D| z&Y*w<2v1-rQ|=lbZ!Bf<22&$E+&ghogr|lg*>n|M)ua)@F(CJEN@b`zUz_js z$W^dGaH}UCNdAfRK;apbK8XOIIgqlbCh4jw>&Q$p#$Kxd8t6cts^d|mYg9QJMF)eE ztI9Db>aiFAHLxElZUZ3*j+hlZQqA;T$)m!c)OH2O8#mlGJ)+vMn)kbg!YTtv<}kF! zTfGjB_#Lb*U}#8K1ShtOe~c#nup|k`wyoPD+|Ez#}niO4gZN2?Y#}asU@R;0b{C8c6D3 zj27vxp{su1GlD|SZ)P1WaCzQV_r;nu_C-+ScSy}OteHJ2wF0GDuhPLx7a89y*TD$I zV8>#~uHjZFz~)SC2)F8DXNp!SYOuqreHkyN#x)raSYF$ADow-6QsaZLT`ZS+dE1gp zp?zt21 { + + }) + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/TestAbility/TestAbility.ts b/relational_store/test/ets/relational_store/entry/src/main/ets/TestAbility/TestAbility.ts new file mode 100644 index 00000000..65891485 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/TestAbility/TestAbility.ts @@ -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. + +import Ability from '@ohos.app.ability.UIAbility' + +export default class TestAbility extends Ability { + onCreate(want, launchParam) { + console.log('TestAbility onCreate'); + } + + onDestroy() { + console.log('TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage) { + console.log('TestAbility onWindowStageCreate'); + windowStage.setUIContent(this.context, 'TestAbility/pages/index', null); + + globalThis.abilityContext = this.context; + } + + onWindowStageDestroy() { + console.log('TestAbility onWindowStageDestroy'); + } + + onForeground() { + console.log('TestAbility onForeground'); + } + + onBackground() { + console.log('TestAbility onBackground'); + } +}; \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/TestAbility/pages/index.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/TestAbility/pages/index.ets new file mode 100644 index 00000000..fc1b5b89 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/TestAbility/pages/index.ets @@ -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. + */ +import router from '@ohos.router'; + +@Entry +@Component +struct Index { + aboutToAppear() { + console.info('TestAbility index aboutToAppear') + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ + }) + } + .width('100%') + } + .height('100%') + } + } \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts b/relational_store/test/ets/relational_store/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts new file mode 100644 index 00000000..a1f107a9 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts @@ -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. + +import TestRunner from '@ohos.application.testRunner' +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +function translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s it', + '-s level', '-s testType', '-s size', '-s timeout' + ]) + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams = `${targetParams} ${key} ${parameters[key]}` + } + } + return targetParams.trim() +} + +async function onAbilityCreateCallback() { + console.log('onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + console.info('addAbilityMonitorCallback : ' + JSON.stringify(err)); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + console.info("OpenHarmonyTestRunner OnPrepare "); + } + + async onRun() { + console.log('OpenHarmonyTestRunner onRun run') + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.MainAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a com.example.myapplication.MainAbility' + ' -b ' + abilityDelegatorArguments.bundleName + cmd += ' '+translateParamsToString(abilityDelegatorArguments.parameters) + console.info('cmd : '+ cmd) + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + console.info('executeShellCommand : err : ' + JSON.stringify(err)); + console.info('executeShellCommand : data : ' + d.stdResult); + console.info('executeShellCommand : data : ' + d.exitCode); + }) + console.info('OpenHarmonyTestRunner onRun end'); + } +}; \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/List.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/List.test.ets new file mode 100644 index 00000000..41df574f --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/List.test.ets @@ -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. + */ +import RdbPredicatesEtsTest from './RdbstorePredicatesEts.test.ets'; +import RdbPredicatesPrefEtsTest from './RdbPredicatesPerfEts.test.ets'; +import RelationalStoreDataGroupId from './RdbGroupIdEts.test.ets'; +import PerfStatEtsTest from './RdbstorePerfStatEts.test.ets'; +import RdbRekeyEtsTest from './RdbstoreRekeyEts.test.ets'; +import RdbStoreErrorlogTest from './RdbOnErrorLog.test.ets'; +import RDBstoreGetSqlInfoTest from './RdbstoreGetSqlInfoEts.test.ets'; +import RdbStoreTransactionTest from './RdbStoreTransaction.test.ets'; +import RdbstoreTransactionJsunit from './RdbstoreTransactionJsunit.test.ets'; +import RdbStoreTransInsertJsunit from './RdbStoreTransInsertJsunit.test.ets'; +import RdbStoreTransJsunit from './RdbStoreTransJsunit.test.ets'; +import ExecuteSqlTest from './RdbStoreExecuteSql.test.ets'; +import RdbstoreCustomTokenizerTest from './RdbstoreCustomTokenizerEts.ets'; +import SetLocaleEtsTest from './RdbstoreSetLocaleEts.test.ets'; +import RelationalStoreEtsTest from './RelationalStoreEtsTest.test.ets' +export default function testsuite() { + RdbPredicatesEtsTest(); + RdbPredicatesPrefEtsTest(); + RelationalStoreDataGroupId(); + PerfStatEtsTest(); + RdbRekeyEtsTest(); + RdbStoreErrorlogTest(); + RDBstoreGetSqlInfoTest(); + RdbStoreTransactionTest(); + RdbstoreTransactionJsunit(); + RdbStoreTransInsertJsunit(); + RdbStoreTransJsunit(); + ExecuteSqlTest(); + RdbstoreCustomTokenizerTest(); + SetLocaleEtsTest(); + RelationalStoreEtsTest(); +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbGroupIdEts.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbGroupIdEts.test.ets new file mode 100644 index 00000000..46aeec4d --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbGroupIdEts.test.ets @@ -0,0 +1,267 @@ +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level, Size, TestType } from "@ohos/hypium"; +import relationalStore from '@ohos.data.relationalStore'; +import common from "@ohos.app.ability.common" +import contextConstant from '@ohos.app.ability.contextConstant'; +let context: common.UIAbilityContext + +const TAG = "[RDB_GROUPID_TEST]"; +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT NOT NULL, " + + "age INTEGER, " + + "salary REAL, " + + "blobType BLOB)"; + +async function crudTest(store:relationalStore.RdbStore):Promise +{ + await store?.executeSql(CREATE_TABLE_TEST); + let values:relationalStore.ValuesBucket = { + name:"zhangsan", + age:20, + salary:1.5 + } + let insertNum:number = await store?.insert("test", values) as number; + expect(insertNum).assertEqual(1); + let pre:relationalStore.RdbPredicates = new relationalStore.RdbPredicates("test"); + let resultSet:relationalStore.ResultSet = await store?.query(pre) as relationalStore.ResultSet; + expect(resultSet.rowCount).assertEqual(1); + expect(resultSet.goToFirstRow()).assertEqual(true); + let row:relationalStore.ValuesBucket = resultSet.getRow(); + expect(row.name).assertEqual("zhangsan"); + resultSet.close(); + + values.name = "lisi"; + pre.equalTo("name", "zhangsan"); + let updateNum:number = await store?.update(values, pre) as number; + expect(updateNum).assertEqual(1); + let pre1:relationalStore.RdbPredicates = new relationalStore.RdbPredicates("test"); + resultSet = await store?.query(pre1) as relationalStore.ResultSet; + expect(resultSet.goToFirstRow()).assertEqual(true); + row = resultSet.getRow(); + expect(row.name).assertEqual("lisi"); + resultSet.close(); + + pre1.equalTo("name", "lisi"); + let deleteNum:number = await store?.delete(pre1) as number; + expect(deleteNum).assertEqual(1); + resultSet = await store?.query(pre) as relationalStore.ResultSet; + expect(resultSet.rowCount).assertEqual(0); + resultSet.close(); +} + +export default function RelationalStoreDataGroupId() { + describe('relationalStoreDataGroupId', () => { + beforeAll(() => { + console.info(TAG + 'beforeAll') + context = globalThis.abilityContext; + }) + + beforeEach(() => { + console.info(TAG + 'beforeEach') + }) + + afterEach(() => { + console.info(TAG + 'afterEach') + }) + + afterAll(async () => { + console.info(TAG + 'afterAll') + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.number SUB_DistributedData_RelationalStore_SDK_GetRdbStoreJsAPITest_0100 + * @tc.name relationalStore dataGroupId null test + * @tc.desc relationalStore getRdbStore dataGroupId null test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 0 + */ + it('SUB_DDM_RelationalStore_DataGroupId_0100', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL0, async () => { + const STORE_CONFIG: relationalStore.StoreConfig = { + name: "RdbTest.db", + securityLevel: relationalStore.SecurityLevel.S1, + dataGroupId: null, + }; + try { + let rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + console.info(TAG, `Get RdbStore successfully.`); + expect(rdbStore != undefined).assertTrue(); + await relationalStore.deleteRdbStore(context, STORE_CONFIG); + } catch (errInfo) { + console.error(TAG, `failed, code is ${errInfo.code},message is ${errInfo.message}`); + expect().assertFail(); + } + }) + + /** + * @tc.number SUB_DistributedData_RelationalStore_SDK_GetRdbStoreJsAPITest_0200 + * @tc.name relationalStore dataGroupId undefined callback test + * @tc.desc relationalStore getRdbStore dataGroupId undefined test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 0 + */ + it('SUB_DDM_RelationalStore_DataGroupId_0200', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL0, async () => { + const STORE_CONFIG: relationalStore.StoreConfig = { + name: "RdbTest.db", + securityLevel: relationalStore.SecurityLevel.S1, + dataGroupId: undefined, + }; + try { + let rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + console.info(TAG, `Get RdbStore successfully.`); + expect(rdbStore != undefined).assertTrue(); + await relationalStore.deleteRdbStore(context, STORE_CONFIG); + } catch (errInfo) { + expect().assertFail(); + } + }) + + + /** + * @tc.number SUB_DistributedData_RelationalStore_SDK_GetRdbStoreJsAPITest_0300 + * @tc.name relationalStore dataGroupId callback test + * @tc.desc relationalStore getRdbStore dataGroupId test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 0 + */ + it('SUB_DDM_RelationalStore_DataGroupId_0300', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL0, async () => { + const STORE_CONFIG: relationalStore.StoreConfig = { + name: "RdbTest.db", + securityLevel: relationalStore.SecurityLevel.S1, + dataGroupId: '112233', + }; + try { + await relationalStore.getRdbStore(context, STORE_CONFIG); + console.info(TAG, `Get RdbStore successfully.`); + expect().assertFail(); + } catch (errInfo) { + console.error(TAG, `failed, code is ${errInfo.code},message is ${errInfo.message}`); + expect(errInfo.code == 14801002).assertTrue(); + } + }) + + /** + * @tc.number SUB_DistributedData_RelationalStore_SDK_GetRdbStoreJsAPITest_0400 + * @tc.name relationalStore dataGroupId callback test + * @tc.desc relationalStore deleteRdbStore dataGroupId test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 0 + */ + it('SUB_DDM_RelationalStore_DataGroupId_0400', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL0, async () => { + const STORE_CONFIG: relationalStore.StoreConfig = { + name: "RdbTest.db", + securityLevel: relationalStore.SecurityLevel.S1, + dataGroupId: '123456', + }; + try { + let rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + console.info(TAG, `Get RdbStore successfully.`); + expect(rdbStore != undefined).assertTrue(); + await relationalStore.deleteRdbStore(context, STORE_CONFIG); + } catch (errInfo) { + console.error(TAG, `failed, code is ${errInfo.code},message is ${errInfo.message}`); + expect().assertFail(); + } + }) + + /** + * @tc.number SUB_DistributedData_RelationalStore_SDK_GetRdbStoreJsAPITest_0400 + * @tc.name relationalStore dataGroupId callback test + * @tc.desc relationalStore deleteRdbStore dataGroupId test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 0 + */ + it('SUB_DDM_RelationalStore_DataGroupId_0400', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL0, async () => { + const STORE_CONFIG: relationalStore.StoreConfig = { + name: "RdbTest.db", + securityLevel: relationalStore.SecurityLevel.S1, + dataGroupId: '123456', + }; + try { + let rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + console.info(TAG, `Get RdbStore successfully.`); + expect(rdbStore != undefined).assertTrue(); + await relationalStore.deleteRdbStore(context, STORE_CONFIG); + } catch (errInfo) { + console.error(TAG, `failed, code is ${errInfo.code},message is ${errInfo.message}`); + expect().assertFail(); + } + }) + + /** + * @tc.number SUB_DistributedData_RelationalStore_SDK_GetRdbStoreJsAPITest_0500 + * @tc.name relationalStore dataGroupId el3 test + * @tc.desc relationalStore deleteRdbStore dataGroupId test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 0 + */ + it('SUB_DDM_RelationalStore_DataGroupId_0500', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL0, async () => { + const STORE_CONFIG: relationalStore.StoreConfig = { + name: "RdbTest.db", + securityLevel: relationalStore.SecurityLevel.S1, + dataGroupId: '123456', + }; + let contextEl3:Context = context.createAreaModeContext(contextConstant.AreaMode.EL3); + let groupDir:string = await contextEl3.getGroupDir("123456"); + console.info(TAG, "DataGroupId groupDir:" + groupDir); + try { + let store:relationalStore.RdbStore = await relationalStore.getRdbStore(contextEl3, STORE_CONFIG); + await crudTest(store); + await relationalStore.deleteRdbStore(contextEl3, STORE_CONFIG); + } catch (errInfo) { + console.error(TAG, `failed, code is ${errInfo.code},message is ${errInfo.message}`); + expect().assertFail(); + } + }) + + /** + * @tc.number SUB_DistributedData_RelationalStore_SDK_GetRdbStoreJsAPITest_0600 + * @tc.name relationalStore dataGroupId el4 test + * @tc.desc relationalStore deleteRdbStore dataGroupId test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 0 + */ + it('SUB_DDM_RelationalStore_DataGroupId_0600', TestType.FUNCTION | Size.MEDIUMTEST | Level.LEVEL0, async () => { + const STORE_CONFIG: relationalStore.StoreConfig = { + name: "RdbTest.db", + securityLevel: relationalStore.SecurityLevel.S1, + dataGroupId: '123456', + }; + let contextEl4:Context = context.createAreaModeContext(contextConstant.AreaMode.EL4); + let groupDir:string = await contextEl4.getGroupDir("123456"); + console.info(TAG, "DataGroupId groupDir:" + groupDir); + try { + let store:relationalStore.RdbStore = await relationalStore.getRdbStore(contextEl4, STORE_CONFIG); + await crudTest(store); + await relationalStore.deleteRdbStore(contextEl4, STORE_CONFIG); + } catch (errInfo) { + console.error(TAG, `failed, code is ${errInfo.code},message is ${errInfo.message}`); + expect().assertFail(); + } + }) + console.info(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbOnErrorLog.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbOnErrorLog.test.ets new file mode 100644 index 00000000..72d3b3ba --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbOnErrorLog.test.ets @@ -0,0 +1,309 @@ +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level, Size, TestType } from "@ohos/hypium"; +import data_relationalStore from '@ohos.data.relationalStore'; +import abilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; + +let context = abilityDelegatorRegistry.getAbilityDelegator().getAppContext().getApplicationContext(); +const TAG = "[RELATIONAL_STORE_ON_ERROR]" +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; +const CREATE_TABLE_TEST4 = "CREATE TABLE IF NOT EXISTS users (" + "id INTEGER PRIMARY KEY," + "username TEXT UNIQUE," + + "email TEXT NOT NULL)"; +const STORE_CONFIG: data_relationalStore.StoreConfig = { + name: "sqliteErrorOccurred.db", + securityLevel: data_relationalStore.SecurityLevel.S1, +} + +let rdbStore: data_relationalStore.RdbStore; + +export default function rdbStoreSqliteErrorOccurredTest() { + describe('rdbStoreSqliteErrorOccurredTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll') + }) + beforeEach(async (done: Function) => { + console.info(TAG + 'beforeEach') + rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); + await rdbStore.executeSql(CREATE_TABLE_TEST); + await rdbStore.executeSql(CREATE_TABLE_TEST4); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucketUser: data_relationalStore.ValuesBucket = { + "username": 'user1', + "email": 'user1@example.com', + }; + await rdbStore.insert("users", valueBucketUser); + const valueBucket: data_relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket); + done(); + }) + + afterEach(async (done: Function) => { + console.info(TAG + 'afterEach') + try { + rdbStore.off('sqliteErrorOccurred'); + await rdbStore.close(); + } catch (err) { + console.log(`afterEach error, failed code:${err.code},message:${err.message}`); + } + await data_relationalStore.deleteRdbStore(context, "sqliteErrorOccurred.db"); + done(); + }) + afterAll(async () => { + console.info(TAG + 'afterAll') + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.number SUB_DDM_AppDataFWK_JSRDB_OnsqliteErrorOccurred_0001 + * @tc.name Normal test case of OnsqliteErrorOccurred Already closed + * @tc.desc 1.create db 2.close db 3.OnsqliteErrorOccurred + */ + it('testRdbStoreOnsqliteErrorOccurred0001', 0, async (done: Function) => { + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0001 start *************"); + try { + rdbStore.close(); + let exceptionMessage: data_relationalStore.ExceptionMessage; + rdbStore.on('sqliteErrorOccurred', exceptionMessage => { + console.log(`error log is ${exceptionMessage.code}`) + }); + } catch (err) { + expect(err.code == 14800014).assertTrue(); + console.error(`error is failed code:${err.code},message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0001 end *************"); + }) + + /** + * @tc.number SUB_DDM_AppDataFWK_JSRDB_OnsqliteErrorOccurred_0002 + * @tc.name Normal test case of OnsqliteErrorOccurred SQLITE_ERROR + * @tc.desc 1.OnsqliteErrorOccurred 2.execute sql with SQLITE_ERROR + */ + it('testRdbStoreOnsqliteErrorOccurred0002', 0, async (done: Function) => { + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0002 start *************"); + try { + let exceptionMessage: data_relationalStore.ExceptionMessage; + rdbStore.on('sqliteErrorOccurred', exceptionMessage => { + let sqliteCode = exceptionMessage.code; + let sqliteMessage = exceptionMessage.message; + let errSQL = exceptionMessage.sql; + console.info(`error log is ${sqliteCode}, errMessage is ${sqliteMessage}, errSQL is ${errSQL}`); + expect(sqliteCode == 1).assertTrue(); + expect(sqliteMessage == "table test has no column named exsc").assertTrue(); + expect(errSQL == "INSERT INTO test(age,blobType,exsc,name,salary) VALUES (?,?,?,?,?)").assertTrue(); + done(); + }); + console.log(`sqliteErrorOccurred on is success`); + } catch (err) { + console.error(`sqliteErrorOccurred on is failed ${err.code}`); + } + try { + let u8: Uint8Array = new Uint8Array([1, 2, 3]); + const valueBucket: data_relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + "exsc": 100, + } + await rdbStore.insert("test", valueBucket); + expect(true).assertFail(); + } catch (err) { + console.error(`sqliteErrorOccurred on is failed code:${err.code},message:${err.message}`); + expect(err.code == 14800021).assertTrue(); + } + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0002 end *************"); + }) + + /** + * @tc.number SUB_DDM_AppDataFWK_JSRDB_OnsqliteErrorOccurred_0003 + * @tc.name Normal test case of OnsqliteErrorOccurred SQLITE_MISMATCH + * @tc.desc 1.Insert data + */ + it('testRdbStoreOnsqliteErrorOccurred0003', 0, async (done: Function) => { + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0003 start *************"); + try { + let exceptionMessage: data_relationalStore.ExceptionMessage; + rdbStore.on('sqliteErrorOccurred', exceptionMessage => { + let sqliteCode = exceptionMessage.code; + let sqliteMessage = exceptionMessage.message; + let errSQL = exceptionMessage.sql; + expect(sqliteCode == 20).assertTrue(); + expect(sqliteMessage == "datatype mismatch").assertTrue(); + expect(errSQL == "INSERT INTO test(age,blobType,id,name,salary) VALUES (?,?,?,?,?)").assertTrue(); + console.info(`errCode is ${sqliteCode}, errMessage is ${sqliteMessage}, errSQL is ${errSQL}`); + done(); + }); + } catch (err) { + console.error(`err log failed, code is ${err.code},message is ${err.message}`); + expect(true).assertFail(); + } + let u8 = new Uint8Array([1, 2, 3]); + let transaction = await rdbStore?.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + try { + const valueBucket: data_relationalStore.ValuesBucket = { + "id": "test", + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + let row = transaction?.insertSync("test", valueBucket); + console.log(TAG + "testRdbStoreOnsqliteErrorOccurred0003 insert row:" + row); + expect(true).assertFail(); + await transaction?.commit(); + } catch (e) { + await transaction?.rollback(); + console.log(TAG + e + " code: " + e.code); + expect(e.code == 14800033).assertTrue(); + console.log(TAG + "testRdbStoreOnsqliteErrorOccurred0003 failed"); + } + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0003 end *************"); + }) + + /** + * @tc.number SUB_DDM_AppDataFWK_JSRDB_OnsqliteErrorOccurred_0004 + * @tc.name Normal test case of OnsqliteErrorOccurred performance + * @tc.desc 1.Insert data + */ + it('testRdbStoreOnsqliteErrorOccurred0004', 0, async (done: Function) => { + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0004 start *************"); + try { + let averageTime = 0; + let startTime = new Date().getTime(); + for (let i = 0; i < 2000; ++i) { + let exceptionMessage: data_relationalStore.ExceptionMessage | undefined = undefined; + rdbStore.on('sqliteErrorOccurred', exceptionMessage => { + }); + } + let endTime = new Date().getTime(); + averageTime = ((endTime - startTime) * 1000) / 2000; + expect(averageTime < 1000).assertTrue(); + console.info(TAG + " testRdbStoreOnsqliteErrorOccurred0004 average time is: " + averageTime + " μs"); + } catch (err) { + console.error(`on err log failed, code is ${err.code},message is ${err.message}`); + expect(true).assertFail(); + } + rdbStore.off('sqliteErrorOccurred'); + done(); + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0004 end *************"); + }) + + /** + * @tc.number SUB_DDM_AppDataFWK_JSRDB_OnsqliteErrorOccurred_0005 + * @tc.name Normal test case of OnsqliteErrorOccurred and offsqliteErrorOccurred + * @tc.desc 1.Insert data + */ + it('testRdbStoreOnsqliteErrorOccurred0005', 0, async (done: Function) => { + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0005 start *************"); + try { + let exceptionMessage: data_relationalStore.ExceptionMessage; + rdbStore.on('sqliteErrorOccurred', exceptionMessage => { + expect(exceptionMessage.code === 0).assertTrue(); + }); + rdbStore.off('sqliteErrorOccurred'); + } catch (err) { + console.error(`sqliteErrorOccurred on is failed ${err.code}`); + } + try { + let u8: Uint8Array = new Uint8Array([1, 2, 3]); + const valueBucket: data_relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + "exsc": 100, + } + await rdbStore.insert("test", valueBucket); + expect().assertFail(); + } catch (err) { + console.error(`sqliteErrorOccurred on is failed code:${err.code},message:${err.message}`); + expect(true).assertTrue(); + } + done(); + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0005 end *************"); + }) + + /** + * @tc.number SUB_DDM_AppDataFWK_JSRDB_OnsqliteErrorOccurred_0006 + * @tc.name Abormal test case of OnErrorlog + * @tc.desc 1.Insert data + */ + it('testRdbStoreOnsqliteErrorOccurred0006', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0006 start *************"); + if (!data_relationalStore.isVectorSupported()) { + done() + return + } + let STORE_CONFIG1: data_relationalStore.StoreConfig = { + name: 'rdbStore2.db', + securityLevel: data_relationalStore.SecurityLevel.S1, + vector: true, + }; + let rdbStore1 = await data_relationalStore.getRdbStore(context, STORE_CONFIG1) + try{ + rdbStore1.on('sqliteErrorOccurred', exceptionMessage => { + expect().assertFail(); + }); + expect().assertFail(); + done(); + } catch (err){ + expect(err.code).assertEqual("801"); + done() + } + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0006 end *************"); + }) + + /** + * @tc.number SUB_DDM_AppDataFWK_JSRDB_OnsqliteErrorOccurred_0007 + * @tc.name Abnormal test case of offErrorlog + * @tc.desc 1.Insert data + */ + it('testRdbStoreOnsqliteErrorOccurred0007', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0007 start *************"); + if (!data_relationalStore.isVectorSupported()) { + done() + return + } + let STORE_CONFIG1: data_relationalStore.StoreConfig = { + name: 'rdbStore2.db', + securityLevel: data_relationalStore.SecurityLevel.S1, + vector: true, + }; + let rdbStore1 = await data_relationalStore.getRdbStore(context, STORE_CONFIG1) + try{ + rdbStore1.off('sqliteErrorOccurred'); + expect().assertFail(); + done(); + } catch (err){ + expect(err.code).assertEqual("801"); + done() + } + console.log(TAG + "************* testRdbStoreOnsqliteErrorOccurred0007 end *************"); + }) + + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/js/gdb/performance/src/GdbHelperPromisePerf.js b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbPredicatesPerfEts.test.ets similarity index 30% rename from relational_store/test/js/gdb/performance/src/GdbHelperPromisePerf.js rename to relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbPredicatesPerfEts.test.ets index 7bba8fc6..e65e75d6 100644 --- a/relational_store/test/js/gdb/performance/src/GdbHelperPromisePerf.js +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbPredicatesPerfEts.test.ets @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 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 @@ -12,65 +12,48 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Assert } from 'deccjsunit/index'; -import graphStore from '@ohos.data.graphStore'; -import featureAbility from '@ohos.ability.featureAbility'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; +import relationalStore from '@ohos.data.relationalStore' import deviceInfo from '@ohos.deviceInfo'; -const TAG = "[GDBHELPER_PROMISE]"; -const DB_NAME = "gdbPromise"; -const STORE_CONFIG = { - name: DB_NAME, - securityLevel: graphStore.SecurityLevel.S1 -} -let context = featureAbility.getContext(); -let store; +const TAG = "[RDB_PREDICATES_PERF]"; const BASE_COUNT = 2000; // loop times -const BASE_LINE_TABLE = 2500; // callback tablet base line -const BASE_LINE_PHONE = 3000; // callback phone base line -const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; +const HAVING_BASE_LINE_TABLE = 50; // callback tablet base line +const HAVING_BASE_LINE_PHONE = 100; // callback phone base line +const HAVING_BASE_LINE = (deviceInfo.deviceType == "tablet") ? HAVING_BASE_LINE_TABLE : HAVING_BASE_LINE_PHONE; -describe('gdbHelperPromisePerf', () => { +export default function RdbPredicatesPrefEtsTest() { + describe('rdbPredicatesPrefEtsTest', () => { beforeAll(async () => { - console.info(TAG + 'beforeAll'); - }) + console.info(TAG + 'beforeAll'); + }); beforeEach(async () => { - console.info(TAG + 'beforeEach'); - }) + console.info(TAG + 'beforeEach'); + }); afterEach(async () => { - console.info(TAG + 'afterEach'); - }) + console.info(TAG + 'afterEach'); + }); afterAll(async () => { - console.info(TAG + 'afterAll'); - await store.close(); - await graphStore.deleteStore(context, STORE_CONFIG); - }) + console.info(TAG + 'afterAll'); + }); console.log(TAG + "*************Unit Test Begin*************"); - it('Perf_Gdb_GetStore_Promise_001', 0, async () => { - let averageTime = 0; - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - await graphStore.getStore(context, STORE_CONFIG); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the getStore_Promise average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); + it('SUB_DDM_PERF_RDB_Predicates_having', 0, async (done:Function) => { + let conditions: string = "data"; + let predicates:relationalStore.RdbPredicates = new relationalStore.RdbPredicates("tableName"); + predicates.groupBy(["data1"]); + let startTime = new Date().getTime(); + for (let i = 0; i < BASE_COUNT; i++) { + predicates.having(conditions); + } + let endTime = new Date().getTime(); + let averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; + console.info(TAG + " the Predicates_having average time is: " + averageTime + " μs"); + expect(averageTime < HAVING_BASE_LINE).assertTrue(); + done(); }) - it('Perf_Gdb_DeleteStore_Promise_001', 0, async () => { - let averageTime = 0; - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - await graphStore.deleteStore(context, STORE_CONFIG); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the deleteStore_Promise average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - console.info(TAG + "*************Unit Test End*************") - }) -}) \ No newline at end of file + console.log(TAG + "*************Unit Test End*************"); + }) +} diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreExecuteSql.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreExecuteSql.test.ets new file mode 100644 index 00000000..0ff88650 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreExecuteSql.test.ets @@ -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. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' +import relationalStore from '@ohos.data.relationalStore' + +let context = globalThis.abilityContext; + +const TAG = "[RELATIONAL_STORE_TRANSACTION_JSKITS_TEST]" + +const STORE_CONFIG = { + name: "executeSqlTest.db", + securityLevel: relationalStore.SecurityLevel.S1, +} + +let rdbStore: relationalStore.RdbStore | undefined; + +export default function ExecuteSqlTest() { + describe('executeSqlTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll') + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + }) + + beforeEach(async () => { + console.info(TAG + 'beforeEach') + }) + + afterEach(async () => { + console.info(TAG + 'afterEach') + }) + + afterAll(async () => { + console.info(TAG + 'afterAll') + rdbStore = undefined; + await relationalStore.deleteRdbStore(context, "executeSqlTest.db"); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.number concurrentExecuteDDLSQLTest0001 + * @tc.name Normal test case of executeSql, create table in multi-threaded environment + * @tc.desc execute DDL by executeSql + */ + it('concurrentExecuteDDLSQLTest0001', 0, async () => { + console.log(TAG + "************* concurrentExecuteDDLSQLTest0001 start *************"); + const CREATE_TABLE = "CREATE TABLE IF NOT EXISTS test"; + const CREATE_TABLE_COLUMN = "(id INTEGER PRIMARY KEY, name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"; + const CREATE_INDEX = "CREATE INDEX IF NOT EXISTS indexTest"; + const CREATE_INDEX_TABLE = "ON test"; + const CREATE_INDEX_COLUMN = "(age)"; + + try { + await Promise.all(new Array(50).fill(0).map(async (value, index) => { + if (rdbStore == undefined) { + expect(null).assertFail(); + return; + } + await rdbStore.executeSql(CREATE_TABLE + index + " " + CREATE_TABLE_COLUMN); + await rdbStore.executeSql(CREATE_INDEX + index + " " + CREATE_INDEX_TABLE + index + " " + CREATE_INDEX_COLUMN); + })) + expect(true).assertTrue(); + } catch (error) { + console.error(`${TAG} error in concurrentExecuteDDLSQLTest0001, code: ${error?.code} message: ${error?.message}`); + expect(null).assertFail(); + } + console.log(TAG + "************* concurrentExecuteDDLSQLTest0001 end *************"); + }) + console.log(TAG + "*************Unit Test End*************"); + }) +} diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransInsertJsunit.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransInsertJsunit.test.ets new file mode 100644 index 00000000..fd8302e4 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransInsertJsunit.test.ets @@ -0,0 +1,947 @@ +/* + * 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. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' +import data_relationalStore from '@ohos.data.relationalStore' +import ability_featureAbility from '@ohos.ability.featureAbility' + +var context = globalThis.abilityContext; + +const TAG = "[RELATIONAL_STORE_TRANSACTION_JSKITS_TEST]" +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; + +const STORE_CONFIG = { + name: "TransactionTest.db", + securityLevel: data_relationalStore.SecurityLevel.S3, +} + +var rdbStore = undefined; + +export default function () { + describe('rdbStoreTransactionJsunitTest', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll') + rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + }) + + beforeEach(async function () { + console.info(TAG + 'beforeEach') + + }) + + afterEach(async function () { + console.info(TAG + 'afterEach') + await rdbStore.executeSql("DELETE FROM test"); + }) + + afterAll(async function () { + console.info(TAG + 'afterAll') + rdbStore = null + await data_relationalStore.deleteRdbStore(context, "TransactionTest.db"); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + + it('testRdbTransInsert0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsert0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsert0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsert0001 failed"); + } + + console.log(TAG + "************* testRdbTransInsert0001 end *************"); + done(); + }) + + it('testRdbTransInsert0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsert0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsert0002 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsert0002 failed"); + } + + console.log(TAG + "************* testRdbTransInsert0002 end *************"); + done(); + }) + + it('testRdbTransInsert0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsert0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsert0003 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsert0003 failed"); + } + + console.log(TAG + "************* testRdbTransInsert0003 end *************"); + done(); + }) + + it('testRdbTransInsert0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsert0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsert0011 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsert0011 failed"); + } + + console.log(TAG + "************* testRdbTransInsert0011 end *************"); + done(); + }) + + it('testRdbTransInsert0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsert0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsert0012 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsert0012 failed"); + } + + console.log(TAG + "************* testRdbTransInsert0012 end *************"); + done(); + }) + + it('testRdbTransInsert0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsert0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsert0013 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsert0013 failed"); + } + + console.log(TAG + "************* testRdbTransInsert0013 end *************"); + done(); + }) + + it('testRdbTransInsertSync0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsertSync0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = rdbTrans.insertSync("test", valueBucket); + expect(1).assertEqual(rowId); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsertSync0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsertSync0001 failed"); + } + + console.log(TAG + "************* testRdbTransInsertSync0001 end *************"); + done(); + }) + + it('testRdbTransInsertSync0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsertSync0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = rdbTrans.insertSync("test", valueBucket); + expect(1).assertEqual(rowId); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsertSync0002 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsertSync0002 failed"); + } + + console.log(TAG + "************* testRdbTransInsertSync0002 end *************"); + done(); + }) + + it('testRdbTransInsertSync0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsertSync0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = rdbTrans.insertSync("test", valueBucket); + expect(1).assertEqual(rowId); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsertSync0003 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsertSync0003 failed"); + } + + console.log(TAG + "************* testRdbTransInsertSync0003 end *************"); + done(); + }) + + it('testRdbTransInsertSync0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsertSync0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = rdbTrans.insertSync("test", valueBucket); + expect(1).assertEqual(rowId); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsertSync0011 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsertSync0011 failed"); + } + + console.log(TAG + "************* testRdbTransInsertSync0011 end *************"); + done(); + }) + + it('testRdbTransInsertSync0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsertSync0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = rdbTrans.insertSync("test", valueBucket); + expect(1).assertEqual(rowId); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsertSync0012 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsertSync0012 failed"); + } + + console.log(TAG + "************* testRdbTransInsertSync0012 end *************"); + done(); + }) + + it('testRdbTransInsertSync0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransInsertSync0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = rdbTrans.insertSync("test", valueBucket); + expect(1).assertEqual(rowId); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransInsertSync0013 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransInsertSync0013 failed"); + } + + console.log(TAG + "************* testRdbTransInsertSync0013 end *************"); + done(); + }) + + it('testRdbTransBatchInsert0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsert0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = await rdbTrans.batchInsert("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsert0001 result count " + resultSet.rowCount); + expect(100).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsert0001 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsert0001 end *************"); + done(); + }) + + it('testRdbTransBatchInsert0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsert0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = await rdbTrans.batchInsert("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsert0002 result count " + resultSet.rowCount); + expect(100).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsert0002 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsert0002 end *************"); + done(); + }) + + it('testRdbTransBatchInsert0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsert0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = await rdbTrans.batchInsert("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsert0003 result count " + resultSet.rowCount); + expect(100).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsert0003 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsert0003 end *************"); + done(); + }) + + it('testRdbTransBatchInsert0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsert0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = await rdbTrans.batchInsert("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsert0011 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsert0011 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsert0011 end *************"); + done(); + }) + + it('testRdbTransBatchInsert0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsert0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = await rdbTrans.batchInsert("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsert0012 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsert0012 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsert0012 end *************"); + done(); + }) + + it('testRdbTransBatchInsert0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsert0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = await rdbTrans.batchInsert("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsert0013 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsert0013 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsert0013 end *************"); + done(); + }) + + it('testRdbTransBatchInsertSync0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsertSync0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsertSync0001 result count " + resultSet.rowCount); + expect(100).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsertSync0001 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsertSync0001 end *************"); + done(); + }) + + it('testRdbTransBatchInsertSync0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsertSync0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsertSync0002 result count " + resultSet.rowCount); + expect(100).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsertSync0002 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsertSync0002 end *************"); + done(); + }) + + it('testRdbTransBatchInsertSync0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsertSync0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsertSync0003 result count " + resultSet.rowCount); + expect(100).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsertSync0003 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsertSync0003 end *************"); + done(); + }) + + it('testRdbTransBatchInsertSync0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsertSync0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsertSync0011 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsertSync0011 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsertSync0011 end *************"); + done(); + }) + + it('testRdbTransBatchInsertSync0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsertSync0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsertSync0012 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsertSync0012 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsertSync0012 end *************"); + done(); + }) + + it('testRdbTransBatchInsertSync0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransBatchInsertSync0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBuckets = new Array(100).fill(0).map(() => { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + return valueBucket; + }) + const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); + expect(rowCount).assertEqual(100); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransBatchInsertSync0013 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransBatchInsertSync0013 failed"); + } + + console.log(TAG + "************* testRdbTransBatchInsertSync0013 end *************"); + done(); + }) + + it('testRdbTransUpdate0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdate0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbTrans.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.update({ age: 20 }, updatePredicates); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdate0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(20); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdate0001 failed"); + } + + console.log(TAG + "************* testRdbTransUpdate0001 end *************"); + done(); + }) + + it('testRdbTransUpdate0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdate0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbTrans.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.update({ age: 20 }, updatePredicates); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdate0002 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(20); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdate0002 failed"); + } + + console.log(TAG + "************* testRdbTransUpdate0002 end *************"); + done(); + }) + + it('testRdbTransUpdate0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdate0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbTrans.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.update({ age: 20 }, updatePredicates); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdate0003 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(20); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdate0003 failed"); + } + + console.log(TAG + "************* testRdbTransUpdate0003 end *************"); + done(); + }) + + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransJsunit.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransJsunit.test.ets new file mode 100644 index 00000000..4f88f7f1 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransJsunit.test.ets @@ -0,0 +1,1988 @@ +/* + * 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. + */ + +// @ts-nocheck +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' +import data_relationalStore from '@ohos.data.relationalStore' + +var context = globalThis.abilityContext; + +const TAG = "[RELATIONAL_STORE_TRANSACTION_JSKITS_TEST]" +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; + +const STORE_CONFIG = { + name: "TransactionTest.db", + securityLevel: data_relationalStore.SecurityLevel.S3, +} + +var rdbStore = undefined; + +async function insertInThread(context, transType, insertCount = 1) { + const TAG = "[RELATIONAL_STORE_JS_KITS_TEST]" + let rdbTrans; + try { + rdbTrans = await rdbStore.createTransaction({ + transactionType: transType + }); + console.log(TAG + 'insertInThread after createTrans'); + + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(insertCount).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }); + const resultCount = await rdbTrans.batchInsert("test", valueBuckets); + await rdbTrans.commit(); + console.log(TAG + 'insertInThread after commit'); + return resultCount; + } catch (err) { + if (rdbTrans) { + rdbTrans.rollback(); + } + console.error(TAG + "************* testRdbTransInsert error thread insert *************"); + console.error(TAG + JSON.stringify(err)); + return err.code; + } +} + +async function queryInThread(context, transType, querySql) { + const TAG = "[RELATIONAL_STORE_JS_KITS_TEST]" + let rdbTrans; + try { + rdbTrans = await rdbStore.createTransaction({ + transactionType: transType + }); + + const resultSet = await rdbTrans.querySql(querySql); + const rowCount = resultSet.rowCount; + + await rdbTrans.commit(); + return rowCount; + } catch (err) { + if (rdbTrans) { + rdbTrans.rollback(); + } + console.error(TAG + "************* testRdbTransInsert error thread insert *************"); + console.error(TAG + JSON.stringify(err)); + return err.code; + } +} + +export default function () { + describe('rdbStoreTransactionJsunitTest', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll') + rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + }) + + beforeEach(async function () { + console.info(TAG + 'beforeEach') + + }) + + afterEach(async function () { + console.info(TAG + 'afterEach') + await rdbStore.executeSql("DELETE FROM test"); + }) + + afterAll(async function () { + console.info(TAG + 'afterAll') + rdbStore = null + await data_relationalStore.deleteRdbStore(context, "TransactionTest.db"); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + it('testRdbTransUpdate0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdate0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbStore.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.update({ age: 20 }, updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdate0011 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(18); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdate0011 failed"); + } + + console.log(TAG + "************* testRdbTransUpdate0011 end *************"); + done(); + }) + + it('testRdbTransUpdate0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdate0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbStore.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.update({ age: 20 }, updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdate0012 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(18); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdate0012 failed"); + } + + console.log(TAG + "************* testRdbTransUpdate0012 end *************"); + done(); + }) + + it('testRdbTransUpdate0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdate0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbStore.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.update({ age: 20 }, updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdate0013 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(18); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdate0013 failed"); + } + + console.log(TAG + "************* testRdbTransUpdate0013 end *************"); + done(); + }) + + it('testRdbTransUpdateSync0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdateSync0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbTrans.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + rdbTrans.updateSync({ age: 20 }, updatePredicates); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdateSync0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(20); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdateSync0001 failed"); + } + + console.log(TAG + "************* testRdbTransUpdateSync0001 end *************"); + done(); + }) + + it('testRdbTransUpdateSync0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdateSync0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbTrans.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + rdbTrans.updateSync({ age: 20 }, updatePredicates); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdateSync0002 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(20); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdateSync0002 failed"); + } + + console.log(TAG + "************* testRdbTransUpdateSync0002 end *************"); + done(); + }) + + it('testRdbTransUpdateSync0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdateSync0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbTrans.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + rdbTrans.updateSync({ age: 20 }, updatePredicates); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdateSync0003 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(20); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdateSync0003 failed"); + } + + console.log(TAG + "************* testRdbTransUpdateSync0003 end *************"); + done(); + }) + + it('testRdbTransUpdateSync0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdateSync0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbStore.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + rdbTrans.updateSync({ age: 20 }, updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdateSync0011 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(18); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdateSync0011 failed"); + } + + console.log(TAG + "************* testRdbTransUpdateSync0011 end *************"); + done(); + }) + + it('testRdbTransUpdateSync0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdateSync0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbStore.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + rdbTrans.updateSync({ age: 20 }, updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdateSync0012 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(18); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdateSync0012 failed"); + } + + console.log(TAG + "************* testRdbTransUpdateSync0012 end *************"); + done(); + }) + + it('testRdbTransUpdateSync0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransUpdateSync0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + const rowId = await rdbStore.insert("test", valueBucket); + expect(rowId).assertEqual(1); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + rdbTrans.updateSync({ age: 20 }, updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransUpdateSync0013 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + const rowData = resultSet.getRow(); + expect(rowData['age']).assertEqual(18); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransUpdateSync0013 failed"); + } + + console.log(TAG + "************* testRdbTransUpdateSync0013 end *************"); + done(); + }) + + it('testRdbTransDelete0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransDelete0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = await rdbTrans.delete(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDelete0001 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDelete0001 failed"); + } + + console.log(TAG + "************* testRdbTransDelete0001 end *************"); + done(); + }) + + it('testRdbTransDelete0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransDelete0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = await rdbTrans.delete(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDelete0002 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDelete0002 failed"); + } + + console.log(TAG + "************* testRdbTransDelete0002 end *************"); + done(); + }) + + it('testRdbTransDelete0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransDelete0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = await rdbTrans.delete(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDelete0003 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDelete0003 failed"); + } + + console.log(TAG + "************* testRdbTransDelete0003 end *************"); + done(); + }) + + it('testRdbTransDelete0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransDelete0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.delete(updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDelete0011 result count " + resultSet.rowCount); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDelete0011 failed"); + } + + console.log(TAG + "************* testRdbTransDelete0011 end *************"); + done(); + }) + + it('testRdbTransDelete0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransDelete0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.delete(updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDelete0012 result count " + resultSet.rowCount); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDelete0012 failed"); + } + + console.log(TAG + "************* testRdbTransDelete0012 end *************"); + done(); + }) + + it('testRdbTransDelete0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransDelete0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + await rdbTrans.delete(updatePredicates); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDelete0013 result count " + resultSet.rowCount); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDelete0013 failed"); + } + + console.log(TAG + "************* testRdbTransDelete0013 end *************"); + done(); + }) + + it('testRdbTransDeleteSync0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransDeleteSync0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = rdbTrans.deleteSync(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDeleteSync0001 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDeleteSync0001 failed"); + } + + console.log(TAG + "************* testRdbTransDeleteSync0001 end *************"); + done(); + }) + + it('testRdbTransDeleteSync0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransDeleteSync0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = rdbTrans.deleteSync(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDeleteSync0002 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDeleteSync0002 failed"); + } + + console.log(TAG + "************* testRdbTransDeleteSync0002 end *************"); + done(); + }) + + it('testRdbTransDeleteSync0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransDeleteSync0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = rdbTrans.deleteSync(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDeleteSync0003 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.goToFirstRow(); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDeleteSync0003 failed"); + } + + console.log(TAG + "************* testRdbTransDeleteSync0003 end *************"); + done(); + }) + + it('testRdbTransDeleteSync0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransDeleteSync0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = rdbTrans.deleteSync(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDeleteSync0011 result count " + resultSet.rowCount); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDeleteSync0011 failed"); + } + + console.log(TAG + "************* testRdbTransDeleteSync0011 end *************"); + done(); + }) + + it('testRdbTransDeleteSync0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransDeleteSync0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = rdbTrans.deleteSync(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDeleteSync0012 result count " + resultSet.rowCount); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDeleteSync0012 failed"); + } + + console.log(TAG + "************* testRdbTransDeleteSync0012 end *************"); + done(); + }) + + it('testRdbTransDeleteSync0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransDeleteSync0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(3).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rowId = await rdbStore.batchInsert("test", valueBuckets); + expect(rowId).assertEqual(3); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const updatePredicates = new data_relationalStore.RdbPredicates("test"); + updatePredicates.equalTo('name', 'lisi'); + const deleteRows = rdbTrans.deleteSync(updatePredicates); + expect(deleteRows).assertEqual(3); + await rdbTrans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransDeleteSync0013 result count " + resultSet.rowCount); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransDeleteSync0013 failed"); + } + + console.log(TAG + "************* testRdbTransDeleteSync0013 end *************"); + done(); + }) + + it('testRdbTransQuery0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransQuery0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbTrans.query(predicates); + console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + await rdbTrans.commit(); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransQuery0001 failed"); + } + + console.log(TAG + "************* testRdbTransQuery0001 end *************"); + done(); + }) + + it('testRdbTransQuery0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransQuery0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbTrans.query(predicates); + console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + await rdbTrans.commit(); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransQuery0002 failed"); + } + + console.log(TAG + "************* testRdbTransQuery0002 end *************"); + done(); + }) + + it('testRdbTransQuery0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransQuery0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbTrans.query(predicates); + console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + await rdbTrans.commit(); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransQuery0003 failed"); + } + + console.log(TAG + "************* testRdbTransQuery0003 end *************"); + done(); + }) + + it('testRdbTransQuery0011', 0, async (done) => { + console.log(TAG + "************* testRdbTransQuery0011 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbTrans.querySync(predicates); + console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + await rdbTrans.commit(); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransQuery0011 failed"); + } + + console.log(TAG + "************* testRdbTransQuery0011 end *************"); + done(); + }) + + it('testRdbTransQuery0012', 0, async (done) => { + console.log(TAG + "************* testRdbTransQuery0012 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbTrans.querySync(predicates); + console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + await rdbTrans.commit(); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransQuery0012 failed"); + } + + console.log(TAG + "************* testRdbTransQuery0012 end *************"); + done(); + }) + + it('testRdbTransQuery0013', 0, async (done) => { + console.log(TAG + "************* testRdbTransQuery0013 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbTrans.querySync(predicates); + console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + await rdbTrans.commit(); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransQuery0013 failed"); + } + + console.log(TAG + "************* testRdbTransQuery0013 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0001 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0001 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0001 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0002 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0002 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0002 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0003 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0003 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0003 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0004', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0004 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + console.log(TAG + "before second trans create"); + const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); + console.log(TAG + "after second trans create"); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + console.log(TAG + "before query predicates create"); + let predicates = new data_relationalStore.RdbPredicates("test"); + console.log(TAG + "after query predicates create"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0004 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0004 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0004 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0005', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0005 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0005 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0005 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0005 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0006', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0006 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0006 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0006 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0006 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0007', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0007 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0007 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0007 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0007 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0008', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0008 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await insertInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 10); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0008 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0008 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0008 end *************"); + done(); + }) + + it('testRdbTransSameThreadInsert0009', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadInsert0009 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await insertInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 10); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadInsert0009 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadInsert0009 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadInsert0009 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0001 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const rowCount = await queryInThread(context, data_relationalStore.TransactionType.DEFERRED, 'select * from test'); + expect(rowCount).assertEqual(0); + + await rdbTrans.commit(); + + { + const rowCount = await queryInThread(context, data_relationalStore.TransactionType.DEFERRED, 'select * from test'); + expect(rowCount).assertEqual(10); + } + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0001 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0001 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0001 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0002', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0002 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const rowCount = await queryInThread(context, data_relationalStore.TransactionType.DEFERRED, 'select * from test'); + expect(rowCount).assertEqual(0); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0002 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0002 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0002 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0003 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + + await rdbStore.batchInsert('test', valueBuckets); + + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const rowCount = await queryInThread(context, data_relationalStore.TransactionType.DEFERRED, 'select * from test'); + expect(rowCount).assertEqual(10); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0003 result count " + resultSet.rowCount); + expect(20).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0003 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0003 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0004', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0004 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await queryInThread(context, data_relationalStore.TransactionType.IMMEDIATE, 'select * from test'); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0004 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0004 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0004 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0005', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0005 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await queryInThread(context, data_relationalStore.TransactionType.IMMEDIATE, 'select * from test'); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0005 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0005 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0005 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0006', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0006 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await queryInThread(context, data_relationalStore.TransactionType.IMMEDIATE, 'select * from test'); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0006 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0006 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0006 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0007', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0007 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await queryInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 'select * from test'); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0007 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0007 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0007 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0008', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0008 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await queryInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 'select * from test'); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0008 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0008 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0008 end *************"); + done(); + }) + + it('testRdbTransSameThreadQuery0009', 0, async (done) => { + console.log(TAG + "************* testRdbTransSameThreadQuery0009 start *************"); + try { + const u8 = new Uint8Array([1, 2, 3]); + const valueBuckets = new Array(10).fill(0).map(() => { + return { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + }) + const rdbTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + + const insertCount = await rdbTrans.batchInsert('test', valueBuckets); + expect(insertCount).assertEqual(10); + + const errCode = await queryInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 'select * from test'); + expect(errCode).assertEqual(14800024); + + await rdbTrans.commit(); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = rdbStore.querySync(predicates); + console.log(TAG + "testRdbTransSameThreadQuery0009 result count " + resultSet.rowCount); + expect(10).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransSameThreadQuery0009 failed"); + } + + console.log(TAG + "************* testRdbTransSameThreadQuery0009 end *************"); + done(); + }) + + /** + * @tc.name rdb transaction insert test + * @tc.number testRdbTransactionInsert0001 + * @tc.desc rdb transaction insert & commit, the result comes out is 3 items; + */ + it('testRdbTransactionInsert0001', 0, async (done) => { + console.log(TAG + "************* testRdbStoreInsert0001 start *************"); + const u8 = new Uint8Array([1, 2, 3]); + try { + const rdbTrans = await rdbStore.createTransaction(); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await rdbTrans.insert("test", valueBucket); + await rdbTrans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransactionInsert0001 result count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail(); + console.log(TAG + "testRdbTransactionInsert0001 failed"); + } + done(); + console.log(TAG + "************* testRdbTransactionInsert0001 end *************"); + }) + + /** + * @tc.name rdb transaction insert test + * @tc.number testRdbTransactionInsert0001 + * @tc.desc rdb transaction insert & commit, the result comes out is 3 items; + */ + it('testRdbTransactionInsert0002', 0, async (done) => { + console.log(TAG + "************* testRdbStoreInsert0002 start *************"); + const u8 = new Uint8Array([1, 2, 3]); + try { + const trans = await rdbStore.createTransaction(); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await trans.insert("test", valueBucket); + const valueBucket1 = { + "name": "zhangsan", + "age": 20, + "salary": 9.5, + "blobType": u8, + }; + await trans.insert("test", valueBucket1); + const valueBucket2 = { + "name": "wangwu", + "age": 16, + "salary": 99, + "blobType": u8, + }; + await trans.insert("test", valueBucket2); + await trans.commit(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "testRdbTransactionInsert0002 failed"); + } + done(); + console.log(TAG + "************* testRdbTransactionInsert0002 end *************"); + }) + + /** + * @tc.name rdb transaction insert test + * @tc.number testRdbTransactionInsert0002 + * @tc.desc while using transaction to insert values, querying the db, + * the result comes out is 0; + */ + it('testRdbTransactionInsert0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransactionInsert0003 start *************"); + const u8 = new Uint8Array([1, 2, 3]); + try { + const trans = await rdbStore.createTransaction(); + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await trans.insert("test", valueBucket); + const valueBucket1 = { + "name": "zhangsan", + "age": 20, + "salary": 9.5, + "blobType": u8, + }; + await trans.insert("test", valueBucket1); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await trans.query(predicates); + expect(2).assertEqual(resultSet.rowCount); + resultSet.close(); + const valueBucket2 = { + "name": "wangwu", + "age": 16, + "salary": 99, + "blobType": u8, + }; + await trans.insert("test", valueBucket2); + await trans.commit(); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "testRdbTransactionInsert0003 failed"); + } + done(); + console.log(TAG + "************* testRdbTransactionInsert0003 end *************"); + }) + + /** + * @tc.number testRdbTransactionInsert0004 + * @tc.name Abnormal test case of transaction insert, if catch exception then rollback + * @tc.desc 1.Execute beginTransaction + * 2.Insert data (primary key conflict) + * 3.Execute rollBack + * 4.Query data + */ + it('testRdbTransactionRollBack0001', 0, async (done) => { + console.log(TAG + "************* testRdbTransactionRollBack0001 start *************"); + const u8 = new Uint8Array([1, 2, 3]); + const trans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + try { + const valueBucket = { + "id": 1, + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await trans.insert("test", valueBucket); + await trans.insert("test", valueBucket); + trans.commit(); + } catch (e) { + trans.rollback(); + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + console.log(TAG + "testRdbTransactionRollBack0001 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } + done(); + console.log(TAG + "************* testRdbTransactionRollBack0001 end *************"); + }) + + /** + * @tc.number testRdbTransactionInsert0005 + * @tc.name Normal test case of transaction, begin transactions within a transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute beginTransaction + * 4.Insert data + * 5.Execute rollBack + * 6.Insert data + * 7.Execute commit + * 8.Query data + */ + it('testRdbTransactionMulti0003', 0, async (done) => { + console.log(TAG + "************* testRdbTransactionMulti0003 start *************"); + const u8 = new Uint8Array([1, 2, 3]); + let trans = await rdbStore.createTransaction(); + const trans2 = await rdbStore.createTransaction(); + try { + const valueBucket = { + "id": 1, + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + await trans.insert("test", valueBucket); + console.log(TAG + "before second create trans"); + console.log(TAG + "after second create trans"); + const valueBucket1 = { + "name": "zhangsan", + "age": 20, + "salary": 220.5, + "blobType": u8, + }; + await trans2.insert("test", valueBucket1); + } catch (e) { + expect(e.code).assertEqual(14800024) + await trans.rollback(); + await trans2.rollback(); + console.log(TAG + "testRdbTransactionMulti0003 rollback ***** "); + } + done(); + console.log(TAG + "************* testRdbTransactionMulti0003 end *************"); + }) + + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransaction.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransaction.test.ets new file mode 100644 index 00000000..0170d9e8 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbStoreTransaction.test.ets @@ -0,0 +1,2729 @@ +/* + * 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. + */ + +// @ts-nocheck +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' +import data_relationalStore from '@ohos.data.relationalStore' + +var context = globalThis.abilityContext; + +const TAG = "[RELATIONAL_STORE_TRANSACTION_JSKITS_TEST]" +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; +const CREATE_TABLE_TEST1 = "CREATE TABLE IF NOT EXISTS test1 (" + "id INTEGER PRIMARY KEY, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; + +const STORE_CONFIG = { + name: "TransactionTest.db", + securityLevel: data_relationalStore.SecurityLevel.S1, +} + +var rdbStore = undefined; + +export default function () { + describe('rdbStoreTransactionTest', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll') + rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + }) + + beforeEach(async function () { + await rdbStore.executeSql(CREATE_TABLE_TEST); + console.info(TAG + 'beforeEach') + }) + + afterEach(async function () { + try { + await rdbStore.executeSql("DELETE FROM test"); + } catch (error) { + console.error(`${TAG} error in afterEach, code: ${error?.code} message: ${error?.message}`); + } + console.info(TAG + 'afterEach') + }) + + afterAll(async function () { + console.info(TAG + 'afterAll') + rdbStore = null + await data_relationalStore.deleteRdbStore(context, "TransactionTest.db"); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.number testTransactionInsert0001 + * @tc.name Normal test case of transactions, insert a row of data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute commit + * 4.Query data + */ + it('testTransactionInsert0001', 0, async function (done) { + console.log(TAG + "************* testTransactionInsert0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var num = await transaction.insert("test", valueBucket) + expect(1).assertEqual(num); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await transaction.query(predicates) + console.log(TAG + "testTransactionInsert0001 result count " + resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) + resultSet.close() + await transaction.commit() + } catch (e) { + await transaction.commit() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionInsert0001 failed"); + } + done() + console.log(TAG + "************* testTransactionInsert0001 end *************"); + }) + + /** + * @tc.number testTransactionInsert0002 + * @tc.name Abnormal test case of transaction, insert a type mismatch data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute commit + */ + it('testTransactionInsert0002', 0, async function (done) { + console.log(TAG + "************* testTransactionInsert0002 start *************"); + let u8 = new Uint8Array([1, 2, 3]); + let transaction = await rdbStore?.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }); + try { + const valueBucket = { + "id": "test", + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + let row = transaction?.insertSync("test", valueBucket); + console.log(TAG + "testTransactionInsert0002 insert row:" + row); + expect(null).assertFail(); + await transaction?.commit(); + } catch (e) { + await transaction?.rollback(); + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800033) + console.log(TAG + "testTransactionInsert0002 failed"); + } + done(); + console.log(TAG + "************* testTransactionInsert0002 end *************"); + }) + + /** + * @tc.number testTransactionInsert0003 + * @tc.name Abnormal test case of transaction, insert with an abnormal table + * @tc.desc 1.Execute beginTransaction + * 2.Insert data to a no exist table + * 3.Execute commit + */ + it('testTransactionInsert0003', 0, async function (done) { + console.log(TAG + "************* testTransactionInsert0003 start *************"); + let u8 = new Uint8Array([1, 2, 3]); + let transaction = await rdbStore?.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + try { + const valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + }; + let row = await transaction?.insert("testNotExist", valueBucket); + console.log(TAG + "testTransactionInsert0003 insert row:" + row); + expect(null).assertFail(); + await transaction?.commit(); + } catch (e) { + await transaction?.rollback(); + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800021) + console.log(TAG + "testTransactionInsert0003 failed"); + } + done(); + console.log(TAG + "************* testTransactionInsert0003 end *************"); + }) + + /** + * @tc.number testTransactionInsert0004 + * @tc.name Abnormal test case of transaction, insert an more attribute data + * @tc.desc 1.Execute beginTransaction + * 2.Insert insert an more attribute data + * 3.Execute commit + */ + it('testTransactionInsert0004', 0, async function (done) { + console.log(TAG + "************* testTransactionInsert0004 start *************"); + let u8 = new Uint8Array([1, 2, 3]); + let transaction = await rdbStore?.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + try { + const valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + "notExist": "test" + }; + let row = transaction?.insertSync("test", valueBucket); + console.log(TAG + "testTransactionInsert0004 insert row:" + row); + expect(null).assertFail(); + await transaction?.commit(); + } catch (e) { + await transaction?.rollback(); + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800021) + console.log(TAG + "testTransactionInsert0004 failed"); + } + done(); + console.log(TAG + "************* testTransactionInsert0004 end *************"); + }) + + /** + * @tc.number testTransactionBatchInsert0001 + * @tc.name Normal test case of transactions, insert a row of data + * @tc.desc 1.Execute beginTransaction + * 2.BatchInsert data + * 3.Execute commit + * 4.Query data + */ + it('testTransactionBatchInsert0001', 0, async function (done) { + console.log(TAG + "************* testTransactionBatchInsert0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + for (let i = 0; i < 2; i++) { + valueBucketArray.push(valueBucket); + } + var num = await transaction.batchInsert("test", valueBucketArray) + expect(2).assertEqual(num); + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testTransactionBatchInsert0001 result count " + resultSet.rowCount) + expect(2).assertEqual(resultSet.rowCount) + resultSet.close() + + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionBatchInsert0001 failed"); + } + done() + console.log(TAG + "************* testTransactionBatchInsert0001 end *************"); + }) + + /** + * @tc.number testTransactionUpdate0001 + * @tc.name Normal test case of transactions, insert and update a row of data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 2.Update data + * 3.Execute commit + * 4.Query data + */ + it('testTransactionUpdate0001', 0, async function (done) { + console.log(TAG + "************* testTransactionUpdate0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket) + + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi"); + const updateValueBucket = { + "name": "update", + "age": 28, + "salary": 25, + "blobType": u8, + } + var num = await transaction.update(updateValueBucket, predicates) + expect(1).assertEqual(num); + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testTransactionUpdate0001 result count " + resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) + expect(true).assertEqual(resultSet.goToFirstRow()) + const name = resultSet.getString(resultSet.getColumnIndex("name")) + expect("update").assertEqual(name); + const age = resultSet.getLong(resultSet.getColumnIndex("age")) + expect(28).assertEqual(age); + const salary = resultSet.getLong(resultSet.getColumnIndex("salary")) + expect(25).assertEqual(salary); + resultSet.close() + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionUpdate0001 failed"); + } + done() + console.log(TAG + "************* testTransactionUpdate0001 end *************"); + }) + + /** + * @tc.number testTransactionDelete0001 + * @tc.name Normal test case of transactions, insert and update a row of data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 2.Delete data + * 3.Execute commit + * 4.Query data + */ + it('testTransactionDelete0001', 0, async function (done) { + console.log(TAG + "************* testTransactionDelete0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket) + + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi"); + var num = await transaction.delete(predicates) + expect(1).assertEqual(num); + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testTransactionDelete0001 result count " + resultSet.rowCount) + expect(0).assertEqual(resultSet.rowCount) + resultSet.close() + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionDelete0001 failed"); + } + done() + console.log(TAG + "************* testTransactionDelete0001 end *************"); + }) + + /** + * @tc.number testExecute0001 + * @tc.name Normal test case of Execute, check integrity for store + * @tc.desc 1. Execute sql: PRAGMA integrity_check + * 2. Check returned value + */ + it('testExecute0001', 0, async function (done) { + console.info(TAG + "************* testExecute0001 start *************"); + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + try { + let ret = await transaction.execute("PRAGMA integrity_check"); + expect("ok").assertEqual(ret); + await transaction.commit(); + } catch (err) { + await transaction.rollback(); + expect(null).assertFail(); + console.error(`integrity_check failed, code:${err.code}, message: ${err.message}`); + } + done(); + console.info(TAG + "************* testExecute0001 end *************"); + }) + + + /** + * @tc.number testExecute0002 + * @tc.name Normal test case of ExecuteSql + * @tc.desc 1.Insert data + * 2.ExecuteSql(delete age = "18" OR "20") + * 3.QuerySql + */ + it('testExecute0002', 0, async function (done) { + console.log(TAG + "************* testExecute0002 start *************"); + var transaction = await rdbStore.createTransaction() + var u8 = new Uint8Array([1, 2, 3]) + try { + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + for (let i = 0; i < 3; i++) { + valueBucket.age = valueBucket.age + 1; + var row = await transaction.insert("test", valueBucket) + console.log(TAG + "testExecute0002 insert row " + row) + } + await transaction.execute("DELETE FROM test WHERE age = ? OR age = ?", [21, 20]) + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testExecute0002 transaction.querySql result count " + resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) + expect(true).assertEqual(resultSet.goToFirstRow()) + const age = resultSet.getLong(resultSet.getColumnIndex("age")) + expect(19).assertEqual(age); + await resultSet.close() + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testExecute0002 failed"); + } + done(); + console.log(TAG + "************* testExecute0002 end *************"); + } + ) + + /** + * @tc.number testExecute0003 + * @tc.name Normal test case of ExecuteSql + * @tc.desc 1.Insert data (param is long string) + * 2.Query data + * 3.ExecuteSql (delete age = 19 AND name = nameStr) + * 4.Query data + */ + it('ExecuteSqlTest0003', 0, async function (done) { + console.log(TAG + "************* testExecute0003 start *************"); + var u8 = new Uint8Array([3, 4, 5]) + var transaction = await rdbStore.createTransaction() + var nameStr = "lisi" + "e".repeat(2000) + "zhangsan" + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var row = await transaction.insert("test", valueBucket) + console.log(TAG + "testExecute0003 insert row " + row) + valueBucket.name = nameStr + for (let i = 0; i < 2; i++) { + row = await transaction.insert("test", valueBucket) + valueBucket.age = valueBucket.age + 1; + console.log(TAG + "testExecute0003 insert row " + row) + } + { + let predicates = await new data_relationalStore.RdbPredicates("test") + predicates.equalTo("name", nameStr) + let querySqlPromise = transaction.query(predicates) + querySqlPromise.then(async (resultSet) => { + expect(2).assertEqual(resultSet.rowCount) + resultSet.close() + }).catch((err) => { + expect(null).assertFail(); + }) + await querySqlPromise + } + { + let executeSqlPromise = transaction.execute("DELETE FROM test WHERE age = 19 AND name ='" + nameStr + "'") + executeSqlPromise.then(async () => { + console.log(TAG + "executeSql done."); + }).catch((err) => { + console.log(TAG + "executeSql failed. " + err); + expect(null).assertFail(); + }) + await executeSqlPromise + } + await transaction.commit(); + { + let predicates = await new data_relationalStore.RdbPredicates("test") + predicates.equalTo("name", nameStr) + let querySqlPromise = rdbStore.query(predicates) + querySqlPromise.then(async (resultSet) => { + console.log(TAG + "testExecute0003 rdbStore.querySql result count " + resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) + expect(true).assertEqual(resultSet.goToFirstRow()) + const name = resultSet.getString(resultSet.getColumnIndex("name")) + expect(nameStr).assertEqual(name) + expect(2012).assertEqual(name.length) + expect(18).assertEqual(resultSet.getLong(resultSet.getColumnIndex("age"))) + expect(100.5).assertEqual(resultSet.getDouble(resultSet.getColumnIndex("salary"))) + const blobType = resultSet.getBlob(resultSet.getColumnIndex("blobType")) + expect(3).assertEqual(blobType[0]) + resultSet.close(); + done(); + }).catch((err) => { + console.log(TAG + err); + expect(null).assertFail(); + }) + await querySqlPromise + } + done(); + console.log(TAG + "************* testExecute0003 end *************"); + }) + + /** + * @tc.number testExecute0004 + * @tc.name Normal test case of ExecuteSql, drop table + * @tc.desc 1.Insert data + * 2.ExecuteSql (drop table) + */ + it('testExecute0004', 0, async function (done) { + console.log(TAG + "************* testExecute0004 start *************"); + var u8 = new Uint8Array([3, 4, 5]) + var transaction = await rdbStore.createTransaction() + try { + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + for (let i = 0; i < 3; i++) { + valueBucket.age = valueBucket.age + 1; + valueBucketArray.push(valueBucket); + } + var num = await transaction.batchInsert("test", valueBucketArray) + expect(3).assertEqual(num); + await transaction.execute("DROP TABLE IF EXISTS test") + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testExecute0004 transaction.querySql result count " + resultSet.rowCount) + expect(resultSet.rowCount < 1).assertTrue() + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testExecute0004 failed"); + } + done(); + console.log(TAG + "************* testExecute0004 end *************"); + }) + + /** + * @tc.number testExecute0005 + * @tc.name Normal test case of executeSql and querySql, PRAGMA user_version + * @tc.desc 1.Set user_version + * 2.Get user_version + */ + it('testExecute0005', 0, async function (done) { + console.log(TAG + "************* testExecute0005 start *************"); + // 2 is used to set the store version + var transaction = await rdbStore.createTransaction() + try { + await transaction.execute("PRAGMA user_version = 2") + let resultSet = await transaction.querySql("PRAGMA user_version"); + console.log(TAG + "testExecute0005 transaction.querySql result count " + resultSet.rowCount) + resultSet.goToFirstRow(); + expect(2).assertEqual(resultSet.getLong(0)) + resultSet.close(); + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testExecute0005 failed"); + } + done(); + console.log(TAG + "************* testExecute0005 end *************"); + }) + + /** + * @tc.number testExecute0006 + * @tc.name Normal test case of executeSql and querySql, PRAGMA table_info + * @tc.desc 1.Get table_info + * 2.Check table_info + */ + it('testExecute0006', 0, async function (done) { + console.log(TAG + "************* testExecute0006 start *************"); + var transaction = await rdbStore.createTransaction() + try { + let resultSet = await transaction.querySql("PRAGMA table_info(test)"); + console.log(TAG + "testExecute0006 transaction.querySql result count " + resultSet.rowCount) + resultSet.goToFirstRow(); + expect(0).assertEqual(resultSet.getLong(0)) + expect("id").assertEqual(resultSet.getString(1)) + expect("INTEGER").assertEqual(resultSet.getString(2)) + resultSet.goToNextRow(); + expect(1).assertEqual(resultSet.getLong(0)) + expect("name").assertEqual(resultSet.getString(1)) + expect("TEXT").assertEqual(resultSet.getString(2)) + expect(1).assertEqual(resultSet.getLong(3)) + resultSet.goToNextRow(); + expect(2).assertEqual(resultSet.getLong(0)) + expect("age").assertEqual(resultSet.getString(1)) + expect("INTEGER").assertEqual(resultSet.getString(2)) + resultSet.goToNextRow(); + expect(3).assertEqual(resultSet.getLong(0)) + expect("salary").assertEqual(resultSet.getString(1)) + expect("REAL").assertEqual(resultSet.getString(2)) + resultSet.goToNextRow(); + expect(4).assertEqual(resultSet.getLong(0)) + expect("blobType").assertEqual(resultSet.getString(1)) + expect("BLOB").assertEqual(resultSet.getString(2)) + resultSet.close(); + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testExecute0006 failed"); + } + done(); + console.log(TAG + "************* testExecute0006 end *************"); + }) + + /** + * @tc.number testExecute0007 + * @tc.name Normal test case of executeSql, if spaces before the sql + * @tc.desc 1.Set user_version + * 2.Get user_version + */ + it('testExecute0007', 0, async function (done) { + console.log(TAG + "************* testExecute0007 start *************"); + var transaction = await rdbStore.createTransaction() + try { + // 2 is used to set the store version + await transaction.execute(" PRAGMA user_version = 2") + let resultSet = await transaction.querySql("PRAGMA user_version"); + console.log(TAG + "testExecute0007 transaction.querySql1 result count " + resultSet.rowCount) + resultSet.goToFirstRow(); + expect(2).assertEqual(resultSet.getLong(0)) + + await transaction.execute("\r\nPRAGMA user_version = 3") + resultSet = await transaction.querySql("PRAGMA user_version"); + console.log(TAG + "testExecute0007 transaction.querySql2 result count " + resultSet.rowCount) + resultSet.goToFirstRow(); + expect(3).assertEqual(resultSet.getLong(0)) + resultSet.close(); + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testExecute0007 failed"); + } + done(); + console.log(TAG + "************* testExecute0007 end *************"); + }) + + /** + * @tc.number testTransactionSyncInterface0001 + * @tc.name Normal test case of transactions, insert a row of data + * @tc.desc 1.Execute beginTransaction + * 2.BatchInsertSync data + * 3.InsertSync data + * 4.UpdateSync data + * 5.DeleteSync data + * 6.Execute commit + * 7.querySqlSync + * 7.ExecuteSync + */ + it('testTransactionSyncInterface0001', 0, async function (done) { + console.log(TAG + "************* testTransactionSyncInterface0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var num = await transaction.insertSync("test", valueBucket, data_relationalStore.ConflictResolution.ON_CONFLICT_REPLACE); + expect(1).assertEqual(num); + const updateValueBucket = { + "name": "update", + "age": 28, + "salary": 25, + "blobType": u8, + } + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi") + num = await transaction.updateSync(updateValueBucket, predicates) + expect(1).assertEqual(num); + + let deletePredicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "update") + num = await transaction.deleteSync(deletePredicates); + expect(1).assertEqual(num); + + let resultSet = await transaction.querySqlSync("select * from test") + console.log(TAG + "testTransactionSyncInterface0001 result count " + resultSet.rowCount) + expect(0).assertEqual(resultSet.rowCount) + resultSet.close() + + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionSyncInterface0001 failed"); + } + done() + console.log(TAG + "************* testTransactionSyncInterface0001 end *************"); + }) + + /** + * @tc.number testTransactionRollback0001 + * @tc.name Normal test case of transactions, insert and update a row of data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.rollback data + * 4.Query data + */ + it('testTransactionRollback0001', 0, async function (done) { + console.log(TAG + "************* testTransactionRollback0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket) + + await transaction.rollback() + + let resultSet = rdbStore.querySqlSync("select * from test") + console.log(TAG + "testTransactionRollback0001 result count " + resultSet.rowCount) + expect(0).assertEqual(resultSet.rowCount) + resultSet.close() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionRollback0001 failed"); + } + done() + console.log(TAG + "************* testTransactionRollback0001 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0001 + * @tc.name testTransactionIsolation. EXCLUSIVE and EXCLUSIVE + * @tc.desc 1.begin EXCLUSIVE Transaction + * 2.begin EXCLUSIVE Transaction again + * 3.throw 14800024 + */ + it('testTransactionIsolation0001', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0001 start *************"); + var exclusiveTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + try { + var trans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + trans.commit(); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0001 failed"); + } catch (e) { + await exclusiveTrans.rollback(); + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + console.log(TAG + "testTransactionIsolation0001 success"); + } + done() + console.log(TAG + "************* testTransactionIsolation0001 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0002 + * @tc.name testTransactionIsolation. DEFERRED and EXCLUSIVE + * @tc.desc 1.begin DEFERRED Transaction + * 2.begin EXCLUSIVE Transaction again + * 3.insert data with EXCLUSIVE Transaction + * 4.query data with DEFERRED Transaction -> no data + * 5.execute commit with EXCLUSIVE Transaction + * 6.query data with DEFERRED Transaction -> no data -> why? step 4 start isolation + * 7.query data with Rdb -> has data + */ + it('testTransactionIsolation0002', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0002 start *************"); + var deferredTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + var exclusiveTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + var insertRow = await exclusiveTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0002 exclusiveTrans.insert row " + insertRow) + expect(1).assertEqual(insertRow) + + var resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0002 deferredTrans querySqlSync before exclusiveTrans commit count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close() + + await exclusiveTrans.commit(); + + resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0002 deferredTrans querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + + resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0002 rdbStore querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close() + + } catch (e) { + exclusiveTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "insert failed"); + } + await deferredTrans.commit(); + } catch (e) { + await deferredTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0002 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0002 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0003 + * @tc.name testTransactionIsolation. IMMEDIATE and rdbStore + * @tc.desc 1.begin IMMEDIATE Transaction + * 2.insert data with rdbStore -> busy + * 3.insert data with IMMEDIATE Transaction + * 4.execute commit with IMMEDIATE Transaction + * 5.query data with rdbStore -> has data + */ + it('testTransactionIsolation0003', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0003 start *************"); + var immediateTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + try { + await rdbStore.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0003 rdbStore.insert success "); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + console.log(TAG + "insert failed"); + } + var insertRow = await immediateTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0003 immediateTrans.insert row " + insertRow); + expect(insertRow).assertEqual(1); + + await immediateTrans.commit(); + + var resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0003 querySqlSync count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + await immediateTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0003 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0003 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0004 + * @tc.name testTransactionIsolation. DEFERRED and rdbStore + * @tc.desc 1.begin DEFERRED Transaction + * 2.insert data with rdbStore + * 3.insert data with DEFERRED Transaction + * 4.query data with rdbStore -> has 2 row + * 5.insert data with rdbStore again -> busy + * 6.query data with DEFERRED Transaction -> has 2 row + * 7.execute commit with DEFERRED Transaction + * 8.insert data with rdbStore again + * 9.query data with rdbStore -> has 3 row + */ + it('testTransactionIsolation0004', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0004 start *************"); + var deferredTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + await rdbStore.insert("test", valueBucket); + + await deferredTrans.insert("test", valueBucket); + + var resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0004 rdbStore.querySqlSync count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + + try { + await rdbStore.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0004 insert success "); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + console.log(TAG + "insert failed"); + } + resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0004 deferredTrans.querySqlSync count " + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + + await deferredTrans.commit(); + + await rdbStore.insert("test", valueBucket); + + resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0004 rdbStore.querySqlSync after deferredTrans commit count " + resultSet.rowCount); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + await deferredTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0004 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0004 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0005 + * @tc.name testTransactionIsolation. DEFERRED and IMMEDIATE + * @tc.desc 1.begin DEFERRED Transaction + * 2.begin IMMEDIATE Transaction + * 3.insert data with DEFERRED Transaction -> busy + * 4.insert data with IMMEDIATE Transaction + * 5.execute commit with IMMEDIATE Transaction + * 6.insert data with DEFERRED Transaction + * 7.execute commit with DEFERRED Transaction + * 8.query data with rdbStore -> has 4 row + */ + it('testTransactionIsolation0005', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0005 start *************"); + var deferredTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + var immediateTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + try { + await deferredTrans.insert("test", valueBucket); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + console.log(TAG + "insert failed"); + } + var insertRow = await immediateTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0005 immediateTrans.insert row " + insertRow); + expect(1).assertEqual(insertRow); + + await immediateTrans.commit(); + + insertRow = await deferredTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0005 deferredTrans.insert after immediateTrans.commit row " + insertRow); + expect(2).assertEqual(insertRow); + + await deferredTrans.commit(); + + var resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0005 querySqlSync count " + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + await immediateTrans.rollback(); + await deferredTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0005 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0005 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0006 + * @tc.name testTransactionIsolation. DEFERRED and DEFERRED + * @tc.desc 1.insert data with rdbStore + * 2.begin DEFERRED Transaction1 + * 3.begin DEFERRED Transaction2 + * 4.update data with DEFERRED Transaction1 + * 5.delete data with DEFERRED Transaction2 -> busy + * 6.execute commit with DEFERRED Transaction1 + * 7.query data with DEFERRED Transaction2 -> has updated data + * 8.delete data with DEFERRED Transaction2 + * 9.execute commit with DEFERRED Transaction2 + * 10.query data with rdbStore -> has 0 row + */ + it('testTransactionIsolation0006', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0006 start *************"); + var deferredTrans1 = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + var deferredTrans2 = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + var rowId = await rdbStore.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0006 insert row " + rowId); + expect(1).assertEqual(rowId); + + const updateValueBucket = { + "name": "deferredTrans1", + "age": 18, + "salary": 100.5, + } + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi") + rowId = await deferredTrans1.updateSync(updateValueBucket, predicates) + console.log(TAG + "testTransactionIsolation0006 insert row " + rowId); + expect(1).assertEqual(rowId); + + let deletePredicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("age", "18"); + try { + await deferredTrans2.delete(deletePredicates) + console.log(TAG + "testTransactionIsolation0006 deferredTrans2.delete success "); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + console.log(TAG + "insert failed"); + } + + await deferredTrans1.commit(); + + var resultSet = deferredTrans2.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0006 deferredTrans2.querySqlSync count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToFirstRow()) + const name = resultSet.getString(resultSet.getColumnIndex("name")) + expect("deferredTrans1").assertEqual(name); + resultSet.close() + + var num = await deferredTrans2.deleteSync(deletePredicates) + console.log(TAG + "testTransactionIsolation0006 delete num " + num); + expect(1).assertEqual(num); + + await deferredTrans2.commit(); + + resultSet = rdbStore.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0006 rdbStore.querySqlSync count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + await deferredTrans2.rollback(); + await deferredTrans1.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0006 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0006 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0007 + * @tc.name testTransactionIsolation. DEFERRED and EXCLUSIVE + * @tc.desc 1.begin DEFERRED Transaction1 + * 2.begin EXCLUSIVE Transaction + * 3.insert data with EXCLUSIVE Transaction + * 4.execute commit with EXCLUSIVE Transaction + * 5.query data with DEFERRED1 Transaction -> has data + * 6.begin DEFERRED Transaction2 + * 7.query data with DEFERRED2 Transaction -> has data + */ + it('testTransactionIsolation0007', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0007 start *************"); + var deferredTrans1 = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + var exclusiveTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + var insertRow = await exclusiveTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0007 exclusiveTrans.insert row " + insertRow) + expect(1).assertEqual(insertRow) + await exclusiveTrans.commit(); + + var resultSet = deferredTrans1.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0007 deferredTrans1 querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + + var deferredTrans2 = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + resultSet = deferredTrans2.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0007 deferredTrans2 querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + deferredTrans2.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "querySqlSync failed"); + } + + } catch (e) { + exclusiveTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "insert failed"); + } + await deferredTrans1.commit(); + } catch (e) { + await deferredTrans1.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0007 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0007 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0008 + * @tc.name testTransactionIsolation. DEFERRED and rdbStore + * @tc.desc 1.begin DEFERRED Transaction + * 2.insert data with rdbStore + * 3.query data with DEFERRED Transaction -> has 1 data + * 4.begin EXCLUSIVE Transaction -> busy + * 5.insert data with DEFERRED Transaction + * 6.execute commit with DEFERRED Transaction + * 7.begin EXCLUSIVE Transaction + * 8.query data with EXCLUSIVE Transaction -> has 2 data + */ + it('testTransactionIsolation0008', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0008 start *************"); + var deferredTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + await rdbStore.insert("test", valueBucket); + + var resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0008 querySqlSync1 count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close() + try { + var exclusiveTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + console.log(TAG + "begin EXCLUSIVE success abnormal"); + await exclusiveTrans.rollback(); + } catch (e) { + console.log(TAG + e); + console.log(TAG + "begin EXCLUSIVE failed"); + expect(true).assertFail(); + } + var rowId = await deferredTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0008 deferredTrans.insert row " + rowId) + expect(2).assertEqual(rowId); + + await deferredTrans.commit(); + + try { + var exclusiveTrans = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + console.log(TAG + "begin EXCLUSIVE success"); + try { + resultSet = exclusiveTrans.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0008 exclusiveTrans.querySqlSync count " + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "exclusiveTrans.querySqlSync failed"); + } + exclusiveTrans.rollback(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "begin EXCLUSIVE failed"); + } + } catch (e) { + await deferredTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0008 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0008 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0009 + * @tc.name testTransactionIsolation. DEFERRED and DEFERRED + * @tc.desc 1.insert data with rdbStore + * 2.begin DEFERRED Transaction1 + * 3.begin DEFERRED Transaction2 + * 4.update data to update1 with DEFERRED Transaction1 + * 5.query data with DEFERRED Transaction2 -> has before update data + * 6.update update1 to update2 with DEFERRED Transaction1 + * 7.execute commit with DEFERRED Transaction1 + * 8.query data with DEFERRED Transaction2 -> has before update data + * 9.delete data with DEFERRED Transaction2 -> busy + * 10.execute commit with DEFERRED Transaction2 + * 11.query data with rdbStore -> has 1 row + */ + it('testTransactionIsolation0009', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0009 start *************"); + var deferredTrans1 = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + var deferredTrans2 = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + var rowId = await rdbStore.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0009 insert row " + rowId); + expect(1).assertEqual(rowId); + + const updateValueBucket1 = { + "name": "update1", + "age": 18, + "salary": 100.5, + } + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi") + var num = await deferredTrans1.updateSync(updateValueBucket1, predicates) + console.log(TAG + "testTransactionIsolation0009 updateSync 1 num " + num); + expect(1).assertEqual(num); + + var resultSet = deferredTrans2.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0009 deferredTrans2.querySqlSync1 count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToFirstRow()) + var name = resultSet.getString(resultSet.getColumnIndex("name")) + expect("lisi").assertEqual(name); + resultSet.close() + + const updateValueBucket2 = { + "name": "update2", + "age": 18, + "salary": 100.5, + } + predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "update1") + var num = await deferredTrans1.updateSync(updateValueBucket2, predicates) + console.log(TAG + "testTransactionIsolation0009 updateSync 2 num " + num); + expect(1).assertEqual(num); + + await deferredTrans1.commit(); + + resultSet = deferredTrans2.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0009 deferredTrans2.querySqlSync2 count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToFirstRow()) + name = resultSet.getString(resultSet.getColumnIndex("name")) + expect("lisi").assertEqual(name); + resultSet.close() + + let deletePredicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("age", "18"); + try { + num = await deferredTrans2.delete(deletePredicates) + console.log(TAG + "testTransactionIsolation0009 delete num " + num); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + } + await deferredTrans2.commit(); + + resultSet = rdbStore.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0009 rdbStore.querySqlSync count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + await deferredTrans2.rollback(); + await deferredTrans1.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0009 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0009 end *************"); + }) + + /** + * @tc.number testTransactionEnd0001 + * @tc.name Query data with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute commit + * 4.Query data with transaction -> throw 14800014 + */ + it('testTransactionEnd0001', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var num = await transaction.insert("test", valueBucket) + expect(1).assertEqual(num); + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await transaction.query(predicates) + console.log(TAG + "testTransactionEnd0001 result count " + resultSet.rowCount) + expect(null).assertFail() + resultSet.close() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0001 end *************"); + }) + + /** + * @tc.number testTransactionEnd0002 + * @tc.name Query data with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Query data with transaction -> get resultSet + * 4.Execute commit + * 5.resultSet go to first row -> throw 14800014 + */ + it('testTransactionEnd0002', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0002 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + let resultSet; + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var num = await transaction.insert("test", valueBucket) + expect(1).assertEqual(num); + + let predicates = new data_relationalStore.RdbPredicates("test"); + resultSet = await transaction.query(predicates) + console.log(TAG + "testTransactionEnd0002 result count " + resultSet.rowCount) + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + expect(false).assertEqual(resultSet.goToFirstRow()) + done() + console.log(TAG + "************* testTransactionEnd0002 end *************"); + }) + + /** + * @tc.number testTransactionEnd0003 + * @tc.name Insert data with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute commit + * 4.Insert data with closed transaction -> throw 14800014 + */ + it('testTransactionEnd0003', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0003 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + try { + var rowId = await transaction.insert("test", valueBucket) + expect(1).assertEqual(rowId); + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + rowId = await transaction.insert("test", valueBucket) + console.log(TAG + "testTransactionEnd0003 insert rowId " + rowId) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0003 end *************"); + }) + + /** + * @tc.number testTransactionEnd0004 + * @tc.name Update data with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute rollback + * 4.Update data with closed transaction -> throw 14800014 + */ + it('testTransactionEnd0004', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0004 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.IMMEDIATE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var rowId = await transaction.insert("test", valueBucket) + expect(1).assertEqual(rowId); + await transaction.rollback() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi"); + const updateValueBucket = { + "name": "update", + "age": 28, + "salary": 25, + "blobType": u8, + } + rowId = await transaction.update(updateValueBucket, predicates) + console.log(TAG + "testTransactionEnd0004 update rowId " + rowId) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0004 end *************"); + }) + + /** + * @tc.number testTransactionEnd0005 + * @tc.name Delete data with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute rollback + * 4.Delete data with closed transaction -> throw 14800014 + */ + it('testTransactionEnd0005', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0005 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var rowId = await transaction.insert("test", valueBucket) + expect(1).assertEqual(rowId); + await transaction.rollback() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi"); + var num = transaction.deleteSync(predicates) + console.log(TAG + "testTransactionEnd0005 delete num " + num) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0005 end *************"); + }) + + /** + * @tc.number testTransactionEnd0006 + * @tc.name Execute Sql with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute rollback + * 4.Execute Sql with closed transaction -> throw 14800014 + */ + it('testTransactionEnd0006', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0006 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var rowId = await transaction.insert("test", valueBucket) + expect(1).assertEqual(rowId); + await transaction.rollback() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + let ret = transaction.executeSync("PRAGMA integrity_check"); + console.log(TAG + "testTransactionEnd0006 executeSync PRAGMA integrity_check: " + ret) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0006 end *************"); + }) + + /** + * @tc.number testTransactionEnd0007 + * @tc.name Execute Sql with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute rollback + * 4.Commit with closed transaction -> throw 14800014 + */ + it('testTransactionEnd0007', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0007 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var rowId = await transaction.insert("test", valueBucket) + expect(1).assertEqual(rowId); + await transaction.rollback() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + await transaction.commit(); + console.log(TAG + "testTransactionEnd0007 commit success") + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0007 end *************"); + }) + + /** + * @tc.number testTransactionBusy0001 + * @tc.name Abnormal test case of createTransaction + * @tc.desc 1.Execute beginTransaction 5 times + */ + it('testTransactionBusy0001', 0, async function (done) { + console.log(TAG + "************* testTransactionBusy0001 start *************"); + let transactions = []; + try { + for (let i = 0; i < 5; i++) { + transactions.push(await rdbStore?.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + })); + console.log(TAG + "testTransactionBusy0001 createTransaction success. i " + i); + } + } catch (e) { + console.log(TAG + e + " code: " + e.code); + // expect(e.code).assertEqual(14800000) + expect(e.code).assertEqual(14800015) + console.log(TAG + "testTransactionBusy0001 failed"); + } + done(); + transactions.forEach(element => { + element?.rollback(); + console.log(TAG + "testTransactionBusy0001 rollback"); + }); + console.log(TAG + "************* testTransactionBusy0001 end *************"); + }) + + /** + * @tc.number testTransactionWithReadOnlyStore0001 + * @tc.name createTransactionWithReadOnlyStore + * @tc.desc 1.Get a readOnly store + * 2.createTransaction with readOnly store + */ + it('testTransactionWithReadOnlyStore0001', 0, async function (done) { + console.log(TAG + "************* testTransactionWithReadOnlyStore0001 start *************"); + let storeConfig = { + name: "ReadOnlyTransactionTest.db", + securityLevel: data_relationalStore.SecurityLevel.S1, + } + let store = await data_relationalStore.getRdbStore(context, storeConfig); + await store.close() + storeConfig.isReadOnly = true; + let readOnlyStore = await data_relationalStore.getRdbStore(context, storeConfig); + expect(readOnlyStore === null).assertFalse(); + try { + let transaction = await readOnlyStore?.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + console.log(TAG + "testTransactionWithReadOnlyStore0001 createTransaction success"); + const valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + }; + let row = transaction?.insertSync("test", valueBucket); + console.log(TAG + "testTransactionWithReadOnlyStore0001 insert row:" + row); + await transaction?.rollback(); + expect(null).assertFail(); + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(801) + console.log(TAG + "testTransactionWithReadOnlyStore0001 success"); + } + await data_relationalStore.deleteRdbStore(context, storeConfig); + done(); + console.log(TAG + "************* testTransactionWithReadOnlyStore0001 end *************"); + }) + + /** + * @tc.number testbatchInsertWithConflictResolutionInTransaction0001 + * @tc.name batchInsertWithConflictResolutionInTransaction + * @tc.desc normal batch insert with ON_CONFLICT_NONE + */ + it('testbatchInsertWithConflictResolutionInTransaction0001', 0, async function (done) { + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + for (let i = 0; i < 2; i++) { + valueBucketArray.push(valueBucket); + } + var num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_NONE) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num1 " + num) + expect(2).assertEqual(num); + + num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num2 " + num) + expect(2).assertEqual(num); + + num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_ABORT) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num3 " + num) + expect(2).assertEqual(num); + + num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_FAIL) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num4 " + num) + expect(2).assertEqual(num); + + num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_IGNORE) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num5 " + num) + expect(2).assertEqual(num); + + num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_REPLACE) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num6 " + num) + expect(2).assertEqual(num); + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 result count " + resultSet.rowCount) + expect(12).assertEqual(resultSet.rowCount) + resultSet.close() + + await transaction.commit() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + await transaction.rollback() + expect(null).assertFail() + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 failed"); + } + done() + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0001 end *************"); + }) + + /** + * @tc.number testbatchInsertWithConflictResolutionInTransaction0011 + * @tc.name batchInsertWithConflictResolutionInTransaction + * @tc.desc conflict batch insert with ON_CONFLICT_NONE + */ + it('testbatchInsertWithConflictResolutionInTransaction0011', 0, async function (done) { + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0011 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "id": 2, + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket); + let valueBucketArray = new Array(); + for (let i = 0; i < 5; i++) { + var vb = { ...valueBucket }; + vb.id = i; + valueBucketArray.push(vb); + } + let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_NONE) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0011 failed num " + num); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(14800032).assertEqual(e.code) + await transaction.rollback() + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0011 success"); + } + done() + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0011 end *************"); + }) + + /** + * @tc.number testbatchInsertWithConflictResolutionInTransaction0012 + * @tc.name batchInsertWithConflictResolutionInTransaction + * @tc.desc conflict batch insert with ON_CONFLICT_ABORT + */ + it('testbatchInsertWithConflictResolutionInTransaction0012', 0, async function (done) { + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0012 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "id": 2, + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket); + let valueBucketArray = new Array(); + for (let i = 0; i < 5; i++) { + var vb = { ...valueBucket }; + vb.id = i; + valueBucketArray.push(vb); + } + let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_ABORT) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0012 failed num " + num); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(14800032).assertEqual(e.code) + await transaction.rollback() + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0012 success"); + } + done() + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0012 end *************"); + }) + + /** + * @tc.number testbatchInsertWithConflictResolutionInTransaction0013 + * @tc.name batchInsertWithConflictResolutionInTransaction + * @tc.desc conflict batch insert with ON_CONFLICT_FAIL + */ + it('testbatchInsertWithConflictResolutionInTransaction0013', 0, async function (done) { + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0013 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "id": 2, + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket); + let valueBucketArray = new Array(); + for (let i = 0; i < 5; i++) { + var vb = { ...valueBucket }; + vb.id = i; + valueBucketArray.push(vb); + } + let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_FAIL) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0013 failed num " + num); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(14800032).assertEqual(e.code) + await transaction.rollback() + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0013 success"); + } + done() + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0013 end *************"); + }) + + /** + * @tc.number testbatchInsertWithConflictResolutionInTransaction0014 + * @tc.name batchInsertWithConflictResolutionInTransaction + * @tc.desc conflict batch insert with ON_CONFLICT_IGNORE + */ + it('testbatchInsertWithConflictResolutionInTransaction0014', 0, async function (done) { + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0014 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "id": 2, + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket); + let valueBucketArray = new Array(); + for (let i = 0; i < 5; i++) { + var vb = { ...valueBucket }; + vb.id = i; + valueBucketArray.push(vb); + } + let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_IGNORE) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0014 success num " + num); + expect(4).assertEqual(num) + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0014 result count " + resultSet.rowCount) + expect(5).assertEqual(resultSet.rowCount) + resultSet.close() + + await transaction.commit() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + await transaction.rollback() + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0014 failed"); + expect(null).assertFail() + } + done() + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0014 end *************"); + }) + + /** + * @tc.number testbatchInsertWithConflictResolutionInTransaction0015 + * @tc.name batchInsertWithConflictResolutionInTransaction + * @tc.desc conflict batch insert with ON_CONFLICT_REPLACE + */ + it('testbatchInsertWithConflictResolutionInTransaction0015', 0, async function (done) { + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0015 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "id": 2, + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket); + let valueBucketArray = new Array(); + for (let i = 0; i < 5; i++) { + var vb = { ...valueBucket }; + vb.id = i; + valueBucketArray.push(vb); + } + let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_REPLACE) + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0015 success num " + num); + expect(5).assertEqual(num) + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0015 result count " + resultSet.rowCount) + expect(5).assertEqual(resultSet.rowCount) + resultSet.close() + + await transaction.commit() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + await transaction.rollback() + console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0015 failed"); + expect(null).assertFail() + } + done() + console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0015 end *************"); + }) + + /** + * @tc.number testON_CONFLICT_ROLLBACKInTransaction0021 + * @tc.name InsertWithON_CONFLICT_ROLLBACKInTransaction + * @tc.desc conflict insert with ON_CONFLICT_ROLLBACK + */ + it('testON_CONFLICT_ROLLBACKInTransaction0021', 0, async function (done) { + console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0021 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": null, + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var num = await transaction.insert("test", valueBucket, + data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK); + console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0021 fail num " + num); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800032) + try { + await transaction.rollback() + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800021); + } + console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0021 success"); + } + done() + console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0021 end *************"); + }) + + /** + * @tc.number testON_CONFLICT_ROLLBACKInTransaction0022 + * @tc.name InsertWithON_CONFLICT_ROLLBACKInTransaction + * @tc.desc conflict insert with ON_CONFLICT_ROLLBACK + */ + it('testON_CONFLICT_ROLLBACKInTransaction0022', 0, async function (done) { + console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0022 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var num = await transaction.insert("test", valueBucket); + console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0022 insert num " + num) + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "zhangsan"); + const updateValueBucket = { + "name": null, + "age": 28, + "salary": 25, + "blobType": u8, + } + await transaction.update(updateValueBucket, predicates, data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800032) + try { + await transaction.rollback() + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800021); + } + console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0022 success"); + } + done() + console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0022 end *************"); + }) + + /** + * @tc.number testON_CONFLICT_ROLLBACKInTransaction0023 + * @tc.name BatchInsertWithON_CONFLICT_ROLLBACKInTransaction + * @tc.desc conflict insert with ON_CONFLICT_ROLLBACK + */ + it('testON_CONFLICT_ROLLBACKInTransaction0023', 0, async function (done) { + console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0023 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": null, + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + valueBucketArray.push(valueBucket); + var num = transaction.batchInsertWithConflictResolutionSync("test", valueBucketArray, + data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK); + console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0023 insert num " + num) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800032) + try { + await transaction.rollback() + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800021); + } + console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0023 success"); + + } + done() + console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0023 end *************"); + }) + + /** + * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 + * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs + * @tc.desc batch Insert With ConflictResolution with Invalid Args + */ + it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031', 0, async function (done) { + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction(); + try { + const valueBucket = { + "name": "bbb", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + valueBucketArray.push(valueBucket); + var num = await transaction.batchInsertWithConflictResolution(123, valueBucket, + data_relationalStore.ConflictResolution.ON_CONFLICT_ABORT); + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 insert num " + num) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(String(e.code)).assertEqual(String(401)) + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 success"); + } + await transaction.rollback(); + done() + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 end *************"); + }) + + /** + * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 + * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs + * @tc.desc batch Insert With ConflictResolution with Invalid Args + */ + it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032', 0, async function (done) { + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 start *************"); + var transaction = await rdbStore.createTransaction(); + try { + var num = transaction.batchInsertWithConflictResolutionSync("table", undefined, + data_relationalStore.ConflictResolution.ON_CONFLICT_FAIL); + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 insert num " + num) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(String(e.code)).assertEqual(String(401)) + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 success"); + } + await transaction.rollback(); + done() + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 end *************"); + }) + + /** + * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 + * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs + * @tc.desc batch Insert With ConflictResolution with Invalid Args + */ + it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033', 0, async function (done) { + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + valueBucketArray.push(valueBucket); + var num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, "abc"); + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 insert num " + num) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(String(e.code)).assertEqual(String(401)) + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 success"); + } + await transaction.rollback(); + done() + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 end *************"); + }) + + /** + * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 + * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs + * @tc.desc batch Insert With ConflictResolution with Invalid Args + */ + it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034', 0, async function (done) { + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + valueBucketArray.push(valueBucket); + var num = transaction.batchInsertWithConflictResolutionSync("test", valueBucketArray); + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 insert num " + num) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(String(e.code)).assertEqual(String(401)) + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 success"); + } + await transaction.rollback(); + done() + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 end *************"); + }) + + /** + * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 + * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs + * @tc.desc batch Insert With ConflictResolution with Invalid Args + */ + it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035', 0, async function (done) { + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + let rows = 32768 / 4 + 1; + for (let i = 0; i < rows; i++) { + valueBucketArray.push(valueBucket); + } + var num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, data_relationalStore.ConflictResolution.ON_CONFLICT_NONE); + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 insert num " + num) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(String(e.code)).assertEqual(String(14800000)) + console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 success"); + } + await transaction.rollback(); + done() + console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 end *************"); + }) + + /** + * @tc.number testSqliteLocked0001 + * @tc.name testSqliteLocked + * @tc.desc Drop the table before closing the resultSet after querying the data + */ + it('testSqliteLocked0001', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0001 start *************"); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + await transaction.execute('DROP TABLE test'); + console.error(TAG + 'drop table success but testSqliteLocked0001 failed'); + await transaction.commit(); + expect(null).assertFail() + } catch (err) { + console.info(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(String(err.code)).assertEqual(String(14800025)) + console.info(TAG + "testSqliteLocked0001 success"); + } + resultSet.close(); + done() + console.log(TAG + "************* testSqliteLocked0001 end *************"); + }) + + /** + * @tc.number testSqliteLocked0002 + * @tc.name testSqliteLocked + * @tc.desc Drop the table before closing the resultSet after querying the data + */ + it('testSqliteLocked0002', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0002 start *************"); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount - 1; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + await transaction.execute('DROP TABLE test'); + console.error(TAG + 'drop table success but testSqliteLocked0002 failed'); + await transaction.commit(); + expect(null).assertFail() + } catch (err) { + console.info(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(String(err.code)).assertEqual(String(14800025)) + console.info(TAG + "testSqliteLocked0002 success"); + } + resultSet.close(); + done() + console.log(TAG + "************* testSqliteLocked0002 end *************"); + }) + + /** + * @tc.number testSqliteLocked0003 + * @tc.name testSqliteLocked + * @tc.desc Drop the table after querying the data and closing the resultSet + */ + it('testSqliteLocked0003', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0003 start *************"); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + resultSet.close(); + + await transaction.execute('DROP TABLE test'); + console.info(TAG + 'testSqliteLocked0003 success'); + await transaction.commit(); + } catch (err) { + console.error(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(null).assertFail() + console.error(TAG + "testSqliteLocked0003 failed"); + } + done() + console.log(TAG + "************* testSqliteLocked0003 end *************"); + }) + + /** + * @tc.number testSqliteLocked0004 + * @tc.name testSqliteLocked + * @tc.desc Drop the index before closing the resultSet after querying the data + */ + it('testSqliteLocked0004', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0004 start *************"); + + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + await rdbStore.execute('CREATE INDEX test_index ON test(age)'); + + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + await transaction.execute('DROP INDEX test_index'); + console.error(TAG + 'drop table success but testSqliteLocked0004 failed'); + await transaction.commit(); + expect(null).assertFail() + } catch (err) { + console.info(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(String(err.code)).assertEqual(String(14800025)) + console.info(TAG + "testSqliteLocked0004 success"); + } + resultSet.close(); + await rdbStore.execute('DROP INDEX test_index'); + done() + console.log(TAG + "************* testSqliteLocked0004 end *************"); + }) + + /** + * @tc.number testSqliteLocked0005 + * @tc.name testSqliteLocked + * @tc.desc Drop the index before closing the resultSet after querying the data + */ + it('testSqliteLocked0005', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0005 start *************"); + + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + await rdbStore.execute('CREATE INDEX test_index ON test(age)'); + + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount - 1; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + await transaction.execute('DROP INDEX test_index'); + console.error(TAG + 'drop table success but testSqliteLocked0005 failed'); + await transaction.commit(); + expect(null).assertFail() + } catch (err) { + console.info(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(String(err.code)).assertEqual(String(14800025)) + console.info(TAG + "testSqliteLocked0005 success"); + } + resultSet.close(); + await rdbStore.execute('DROP INDEX test_index'); + done() + console.log(TAG + "************* testSqliteLocked0005 end *************"); + }) + + /** + * @tc.number testSqliteLocked0006 + * @tc.name testSqliteLocked + * @tc.desc Drop the index after querying the data and closing the resultSet + */ + it('testSqliteLocked0006', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0006 start *************"); + + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + await rdbStore.execute('CREATE INDEX test_index ON test(age)'); + + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + resultSet.close(); + + await transaction.execute('DROP INDEX test_index'); + console.info(TAG + 'testSqliteLocked0006 success'); + await transaction.commit(); + } catch (err) { + console.info(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(null).assertFail() + console.error(TAG + "testSqliteLocked0006 failed"); + } + done() + console.log(TAG + "************* testSqliteLocked0006 end *************"); + }) + + /** + * @tc.number testSqliteLocked0007 + * @tc.name testSqliteLocked + * @tc.desc Drop the table before closing the resultSet after querying the data + */ + it('testSqliteLocked0007', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0007 start *************"); + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + resultSet.close(); + + await transaction.execute('DROP TABLE test'); + console.info(TAG + 'testSqliteLocked0007 success'); + await transaction.commit(); + } catch (err) { + console.error(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(null).assertFail(); + console.error(TAG + "testSqliteLocked0007 failed"); + } + done() + console.log(TAG + "************* testSqliteLocked0007 end *************"); + }) + + /** + * @tc.number testSqliteLocked0008 + * @tc.name testSqliteLocked + * @tc.desc Drop the index before closing the resultSet after querying the data + */ + it('testSqliteLocked0008', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0008 start *************"); + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + await rdbStore.execute('CREATE INDEX test_index ON test(age)'); + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + resultSet.close(); + + await transaction.execute('DROP INDEX test_index'); + console.info(TAG + 'testSqliteLocked0008 success'); + await transaction.commit(); + } catch (err) { + console.error(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(null).assertFail(); + console.error(TAG + "testSqliteLocked0008 failed"); + } + done() + console.log(TAG + "************* testSqliteLocked0008 end *************"); + }) + + /** + * @tc.number testSqliteLocked0009 + * @tc.name testSqliteLocked + * @tc.desc Drop the table before closing the resultSet after querying the data + */ + it('testSqliteLocked0009', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0009 start *************"); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + await rdbStore.execute(CREATE_TABLE_TEST1); + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + await transaction.execute('DROP TABLE test1'); + console.error(TAG + 'drop table success but testSqliteLocked0009 failed'); + await transaction.commit(); + expect(null).assertFail() + } catch (err) { + console.info(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(String(err.code)).assertEqual(String(14800025)) + console.info(TAG + "testSqliteLocked0009 success"); + } + resultSet.close(); + done() + console.log(TAG + "************* testSqliteLocked0009 end *************"); + }) + + /** + * @tc.number testSqliteLocked0010 + * @tc.name testSqliteLocked + * @tc.desc Drop the table before closing the resultSet after querying the data + */ + it('testSqliteLocked0010', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0010 start *************"); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + await rdbStore.execute(CREATE_TABLE_TEST1); + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + + await transaction.execute('DROP TABLE test1'); + console.info(TAG + 'testSqliteLocked0010 success'); + await transaction.commit(); + } catch (err) { + console.error(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(null).assertFail() + console.error(TAG + "testSqliteLocked0010 failed"); + } + resultSet.close(); + done() + console.log(TAG + "************* testSqliteLocked0010 end *************"); + }) + + /** + * @tc.number testSqliteLocked0011 + * @tc.name testSqliteLocked + * @tc.desc Drop the table before closing the resultSet after querying the data + */ + it('testSqliteLocked0011', 0, async function (done) { + console.log(TAG + "************* testSqliteLocked0011 start *************"); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: relationalStore.ValueBucket = { + "name": "aaa", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + + let transaction: relationalStore.Transaction; + let resultSet: relationalStore.ResultSet; + try { + let rowId = await rdbStore.insert('test', valueBucket); + expect(1).assertEqual(rowId); + rowId = await rdbStore.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + transaction = await rdbStore.createTransaction(); + resultSet = await transaction.querySql('SELECT * FROM test'); + for (let i = 0; i < resultSet.rowCount; i++) { + let ret = resultSet.goToNextRow(); + expect(true).assertEqual(ret); + } + + let ret = resultSet.goToNextRow(); + expect(false).assertEqual(ret); + + await transaction.execute('DROP TABLE test'); + console.error(TAG + 'testSqliteLocked0011 success'); + await transaction.commit(); + } catch (err) { + console.info(TAG + 'err code: ' + err.code + 'err message: ' + err.message); + await transaction.rollback(); + expect(null).assertFail() + console.info(TAG + "testSqliteLocked0011 failed"); + } + resultSet.close(); + done() + console.log(TAG + "************* testSqliteLocked0011 end *************"); + }) + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreCustomTokenizerEts.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreCustomTokenizerEts.ets new file mode 100644 index 00000000..8de1abb8 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreCustomTokenizerEts.ets @@ -0,0 +1,350 @@ +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; +import relationalStore from '@ohos.data.relationalStore' +import common from "@ohos.app.ability.common" +let context: common.UIAbilityContext + +const TAG = "[RDB_CUSTOM_TOKENIZER_TEST]"; + +export default function RdbStoreCustomTokenizerTest() { + describe('rdbStoreCustomTokenizerEtsTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll'); + context = globalThis.abilityContext; + }); + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + }); + afterEach(async () => { + console.info(TAG + 'afterEach'); + }); + afterAll(async () => { + console.info(TAG + 'afterAll'); + }); + + console.log(TAG + "*************Unit Test Begin*************"); + /** + * @tc.number rdbStoreCustomTokenizerEtsTest + * @tc.name CustomTokenizerTest001 + * @tc.desc Test a single long word + */ + it('CustomTokenizerTest001', 0, async () => { + console.log(TAG + "************* CustomTokenizerTest001 start *************"); + try { + let store: relationalStore.RdbStore | undefined = undefined; + const storeConfig: relationalStore.StoreConfig = { + name: "MyStore.db", + securityLevel: relationalStore.SecurityLevel.S3 + }; + let customType = relationalStore.Tokenizer.CUSTOM_TOKENIZER; + let customTypeSupported = relationalStore.isTokenizerSupported(customType); + if (customTypeSupported) { + storeConfig.tokenizer = customType; + } else { + console.info('not support custom tokenizer.'); + return true; + } + store = await relationalStore.getRdbStore(context, storeConfig); + if (store == undefined) { + expect().assertFail(); + return false; + } + + let createTableSql = "CREATE VIRTUAL TABLE example USING fts5(content, " + + "tokenize = 'customtokenizer cut_mode short_words')"; + await store.executeSql(createTableSql); + + let insertValueSql = "INSERT INTO example VALUES('电子邮件')"; + await store.executeSql(insertValueSql); + + let words: string[] = ["电子", "邮件", "电子邮件"]; + for (const word of words) { + let resultSet = await store.querySql("SELECT * FROM example WHERE content MATCH ?;", [word]); + expect(1).assertEqual(resultSet.rowCount); + } + + let dropTableSql = "DROP TABLE IF EXISTS example"; + await store.executeSql(dropTableSql); + await store.close(); + } catch (err) { + console.log("errcode: " + err.code); + expect().assertFail(); + } + console.log(TAG + "************* CustomTokenizerTest001 end *************"); + return true; + }); + + /** + * @tc.number rdbStoreCustomTokenizerEtsTest + * @tc.name CustomTokenizerTest002 + * @tc.desc Test if there is a long word in a sentence + */ + it('CustomTokenizerTest002', 0, async () => { + console.log(TAG + "************* CustomTokenizerTest002 start *************"); + try { + let store: relationalStore.RdbStore | undefined = undefined; + const storeConfig: relationalStore.StoreConfig = { + name: "MyStore.db", + securityLevel: relationalStore.SecurityLevel.S3 + }; + let customType = relationalStore.Tokenizer.CUSTOM_TOKENIZER; + let customTypeSupported = relationalStore.isTokenizerSupported(customType); + if (customTypeSupported) { + storeConfig.tokenizer = customType; + } else { + console.info('not support custom tokenizer.'); + return true; + } + store = await relationalStore.getRdbStore(context, storeConfig); + if (store == undefined) { + expect().assertFail(); + return false; + } + + let createTableSql = "CREATE VIRTUAL TABLE example USING fts5(content, " + + "tokenize = 'customtokenizer cut_mode short_words')"; + await store.executeSql(createTableSql); + + let insertValueSql = "INSERT INTO example VALUES('这是一封电子邮件')"; + await store.executeSql(insertValueSql); + + let words: string[] = ["电子", "邮件", "电子邮件"]; + for (const word of words) { + let resultSet = await store.querySql("SELECT * FROM example WHERE content MATCH ?;", [word]); + expect(1).assertEqual(resultSet.rowCount); + } + + let dropTableSql = "DROP TABLE IF EXISTS example"; + await store.executeSql(dropTableSql); + await store.close(); + } catch (err) { + console.log("errcode: " + err.code); + expect().assertFail(); + } + console.log(TAG + "************* CustomTokenizerTest002 end *************"); + return true; + }); + + /** + * @tc.number rdbStoreCustomTokenizerEtsTest + * @tc.name CustomTokenizerTest003 + * @tc.desc Test multiple long words + */ + it('CustomTokenizerTest003', 0, async () => { + console.log(TAG + "************* CustomTokenizerTest003 start *************"); + try { + let store: relationalStore.RdbStore | undefined = undefined; + const storeConfig: relationalStore.StoreConfig = { + name: "MyStore.db", + securityLevel: relationalStore.SecurityLevel.S3 + }; + let customType = relationalStore.Tokenizer.CUSTOM_TOKENIZER; + let customTypeSupported = relationalStore.isTokenizerSupported(customType); + if (customTypeSupported) { + storeConfig.tokenizer = customType; + } else { + console.info('not support custom tokenizer.'); + return true; + } + store = await relationalStore.getRdbStore(context, storeConfig); + if (store == undefined) { + expect().assertFail(); + return false; + } + + let createTableSql = "CREATE VIRTUAL TABLE example USING fts5(content, " + + "tokenize = 'customtokenizer cut_mode short_words')"; + await store.executeSql(createTableSql); + + let insertValueSql = "INSERT INTO example VALUES('这是一封关于少数民族的电子邮件')"; + await store.executeSql(insertValueSql); + + let words: string[] = ["电子", "邮件", "电子邮件", "少数", "民族", "少数民族"]; + for (const word of words) { + let resultSet = await store.querySql("SELECT * FROM example WHERE content MATCH ?;", [word]); + expect(1).assertEqual(resultSet.rowCount); + } + + let dropTableSql = "DROP TABLE IF EXISTS example"; + await store.executeSql(dropTableSql); + await store.close(); + } catch (err) { + console.log("errcode: " + err.code); + expect().assertFail(); + } + console.log(TAG + "************* CustomTokenizerTest003 end *************"); + return true; + }); + + /** + * @tc.number rdbStoreCustomTokenizerEtsTest + * @tc.name CustomTokenizerTest004 + * @tc.desc Test repeated long words + */ + it('CustomTokenizerTest004', 0, async () => { + console.log(TAG + "************* CustomTokenizerTest004 start *************"); + try { + let store: relationalStore.RdbStore | undefined = undefined; + const storeConfig: relationalStore.StoreConfig = { + name: "MyStore.db", + securityLevel: relationalStore.SecurityLevel.S3 + }; + let customType = relationalStore.Tokenizer.CUSTOM_TOKENIZER; + let customTypeSupported = relationalStore.isTokenizerSupported(customType); + if (customTypeSupported) { + storeConfig.tokenizer = customType; + } else { + console.info('not support custom tokenizer.'); + return true; + } + store = await relationalStore.getRdbStore(context, storeConfig); + if (store == undefined) { + expect().assertFail(); + return false; + } + + let createTableSql = "CREATE VIRTUAL TABLE example USING fts5(content, " + + "tokenize = 'customtokenizer cut_mode short_words')"; + await store.executeSql(createTableSql); + + let insertValueSql = "INSERT INTO example VALUES('华中师范大学是一所位于武汉市的全日制综合性师范大学')"; + await store.executeSql(insertValueSql); + + let words: string[] = ["华中", "中师", "师范", "武汉", "武汉市", "师范大学"]; + for (const word of words) { + let resultSet = await store.querySql("SELECT * FROM example WHERE content MATCH ?;", [word]); + expect(1).assertEqual(resultSet.rowCount); + } + + let dropTableSql = "DROP TABLE IF EXISTS example"; + await store.executeSql(dropTableSql); + await store.close(); + } catch (err) { + console.log("errcode: " + err.code); + expect().assertFail(); + } + console.log(TAG + "************* CustomTokenizerTest004 end *************"); + return true; + }); + + /** + * @tc.number rdbStoreCustomTokenizerEtsTest + * @tc.name CustomTokenizerTest005 + * @tc.desc Test intermediate words + */ + it('CustomTokenizerTest005', 0, async () => { + console.log(TAG + "************* CustomTokenizerTest005 start *************"); + try { + let store: relationalStore.RdbStore | undefined = undefined; + const storeConfig: relationalStore.StoreConfig = { + name: "MyStore.db", + securityLevel: relationalStore.SecurityLevel.S3 + }; + let customType = relationalStore.Tokenizer.CUSTOM_TOKENIZER; + let customTypeSupported = relationalStore.isTokenizerSupported(customType); + if (customTypeSupported) { + storeConfig.tokenizer = customType; + } else { + console.info('not support custom tokenizer.'); + return true; + } + store = await relationalStore.getRdbStore(context, storeConfig); + if (store == undefined) { + expect().assertFail(); + return false; + } + + let createTableSql = "CREATE VIRTUAL TABLE example USING fts5(content, " + + "tokenize = 'customtokenizer cut_mode short_words')"; + await store.executeSql(createTableSql); + + let insertValueSql = "INSERT INTO example VALUES('中华人民共和国')"; + await store.executeSql(insertValueSql); + + let words: string[] = ["中华", "华人", "人民", "共和", "共和国", "中华人民共和国"]; + for (const word of words) { + let resultSet = await store.querySql("SELECT * FROM example WHERE content MATCH ?;", [word]); + expect(1).assertEqual(resultSet.rowCount); + } + let noMatchWord = "人民共和国"; + let noMatchResultSet = await store.querySql("SELECT * FROM example WHERE content MATCH ?;", [noMatchWord]); + expect(0).assertEqual(noMatchResultSet.rowCount); + + let dropTableSql = "DROP TABLE IF EXISTS example"; + await store.executeSql(dropTableSql); + await store.close(); + } catch (err) { + console.log("errcode: " + err.code); + expect().assertFail(); + } + console.log(TAG + "************* CustomTokenizerTest005 end *************"); + return true; + }); + + /** + * @tc.number rdbStoreCustomTokenizerEtsTest + * @tc.name CustomTokenizerTest006 + * @tc.desc Test in both Chinese and English + */ + it('CustomTokenizerTest006', 0, async () => { + console.log(TAG + "************* CustomTokenizerTest006 start *************"); + try { + let store: relationalStore.RdbStore | undefined = undefined; + const storeConfig: relationalStore.StoreConfig = { + name: "MyStore.db", + securityLevel: relationalStore.SecurityLevel.S3 + }; + let customType = relationalStore.Tokenizer.CUSTOM_TOKENIZER; + let customTypeSupported = relationalStore.isTokenizerSupported(customType); + if (customTypeSupported) { + storeConfig.tokenizer = customType; + } else { + console.info('not support custom tokenizer.'); + return true; + } + store = await relationalStore.getRdbStore(context, storeConfig); + if (store == undefined) { + expect().assertFail(); + return false; + } + + let createTableSql = "CREATE VIRTUAL TABLE example USING fts5(content, " + + "tokenize = 'customtokenizer cut_mode short_words')"; + await store.executeSql(createTableSql); + + let insertValueSql = "INSERT INTO example VALUES('武汉市长江大桥Wuhan Yangtze River Bridge是武汉市最长的桥')"; + await store.executeSql(insertValueSql); + + let words: string[] = ["长江", "大桥", "Wuhan", "Yangtze", "武汉市"]; + for (const word of words) { + let resultSet = await store.querySql("SELECT * FROM example WHERE content MATCH ?;", [word]); + expect(1).assertEqual(resultSet.rowCount); + } + + let dropTableSql = "DROP TABLE IF EXISTS example"; + await store.executeSql(dropTableSql); + await store.close(); + } catch (err) { + console.log("errcode: " + err.code); + expect().assertFail(); + } + console.log(TAG + "************* CustomTokenizerTest006 end *************"); + return true; + }); + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetRowForFlutterEts.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetRowForFlutterEts.test.ets new file mode 100644 index 00000000..f8d67d68 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetRowForFlutterEts.test.ets @@ -0,0 +1,306 @@ + +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level, Size, TestType, + Assert } from "@ohos/hypium"; +import relationalStore from '@ohos.data.relationalStore'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { ValuesBucket } from "@ohos.data.ValuesBucket"; + + +const TAG = "[STAGE_RELATIONAL_STORE_JSKITS_TEST]"; +let rdbStore:relationalStore.RdbStore | undefined = undefined; + +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + + "id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, salary REAL, blobType BLOB, data1 asset)"; + +const STORE_CONFIG: relationalStore.StoreConfig = { + name: "rdbStore.db", + securityLevel: relationalStore.SecurityLevel.S1, +} + +const delegator = AbilityDelegatorRegistry.getAbilityDelegator(); +const context = delegator.getAppContext().getApplicationContext(); + + +export default function getRowForFlutterEtsTest() { + describe('getRowForFlutterEtsTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll') + }) + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore?.executeSql(CREATE_TABLE_TEST); + }) + afterEach(async () => { + console.info(TAG + 'afterEach'); + await relationalStore.deleteRdbStore(context, "rdbStore.db"); + }) + afterAll(async () => { + console.info(TAG + 'afterAll'); + }) + + + /** + * @tc.name testRdbStoreGetRowForFlutter + * @tc.number testRdbStoreGetRowForFlutter_0001 + * @tc.desc integer greater than Number.MAX_SAFE_INTEGER test + */ + it('testRdbStoreGetRowForFlutter_0001', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0001 start *************"); + let valueNum = Number.MAX_SAFE_INTEGER.toString() + 0; + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket: ValuesBucket = { + 'age': valueNum, + } + try { + let rowId = await rdbStore.insert("test", valueBucket); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + let res = resultSet.getRowForFlutter(); + expect(valueNum).assertEqual(res.age); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0001 end *************"); + }) + + /** + * @tc.name testRdbStoreGetRowForFlutter + * @tc.number testRdbStoreGetRowForFlutter_0002 + * @tc.desc integer is Number.MAX_SAFE_INTEGER test + */ + it('testRdbStoreGetRowForFlutter_0002', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0002 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': Number.MAX_SAFE_INTEGER, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + let res = resultSet.getRowForFlutter(); + expect(Number.MAX_SAFE_INTEGER).assertEqual(res.age); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0002 end *************"); + }) + + /** + * @tc.name testRdbStoreGetRowForFlutter + * @tc.number testRdbStoreGetRowForFlutter_0003 + * @tc.desc integer less than Number.MAX_SAFE_INTEGER test + */ + it('testRdbStoreGetrowForFlutter_0003', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0003 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': 500, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + let res = resultSet.getRowForFlutter(); + expect(500).assertEqual(res.age); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0003 end *************"); + }) + + /** + * @tc.name testRdbStoreGetRowForFlutter + * @tc.number testRdbStoreGetRowForFlutter_0004 + * @tc.desc integer greater than Number.MIN_SAFE_INTEGER test + */ + it('testRdbStoreGetRowForFlutter_0004', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0004 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': -500, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + let res = resultSet.getRowForFlutter(); + expect(-500).assertEqual(res.age); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0004 end *************"); + }) + + /** + * @tc.name testRdbStoreGetRowForFlutter + * @tc.number testRdbStoreGetRowForFlutter_0005 + * @tc.desc integer is Number.MIN_SAFE_INTEGER test + */ + it('testRdbStoreGetRowForFlutter_0005', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0005 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': Number.MIN_SAFE_INTEGER, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + let res = resultSet.getRowForFlutter(); + expect(Number.MIN_SAFE_INTEGER).assertEqual(res.age); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0005 end *************"); + }) + + /** + * @tc.name testRdbStoreGetRowForFlutter + * @tc.number testRdbStoreGetRowForFlutter_0006 + * @tc.desc integer less than Number.MIN_SAFE_INTEGER test + */ + it('testRdbStoreGetRowForFlutter_0006', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0006 start *************"); + let valueNum = Number.MIN_SAFE_INTEGER.toString() + 0; + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': valueNum, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + let res = resultSet.getRowForFlutter(); + expect(valueNum).assertEqual(res.age); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0006 end *************"); + }) + + /** + * @tc.name testRdbStoreGetRowForFlutter + * @tc.number testRdbStoreGetRowForFlutter_0007 + * @tc.desc other types test + */ + it('testRdbStoreGetRowForFlutter_0007', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0007 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const asset1: relationalStore.Asset = { + name: "name1", + uri: "uri1", + createTime: "createTime1", + modifyTime: "modifyTime1", + size: "size1", + path: "path1", + } + const valueBucket1: relationalStore.ValuesBucket = { + 'name': 'test', + 'age': 18, + 'salary': 100.5, + 'blobType': true, + 'data1': asset1, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + let res = resultSet.getRowForFlutter(); + expect('test').assertEqual(res.name); + expect(18).assertEqual(res.age); + expect(100.5).assertEqual(res.salary); + const assets2 = res["data1"] as relationalStore.Asset; + expect(asset1.name).assertEqual(assets2.name); + expect(asset1.uri).assertEqual(assets2.uri); + expect(asset1.createTime).assertEqual(assets2.createTime); + expect(asset1.modifyTime).assertEqual(assets2.modifyTime); + expect(asset1.size).assertEqual(assets2.size); + expect(asset1.path).assertEqual(assets2.path); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetRowForFlutter_0007 end *************"); + }) + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetSqlInfoEts.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetSqlInfoEts.test.ets new file mode 100644 index 00000000..6894e7c7 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetSqlInfoEts.test.ets @@ -0,0 +1,727 @@ +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; +import relationalStore from '@ohos.data.relationalStore'; +import sendableRelationalStore from '@ohos.data.sendableRelationalStore'; + +const TAG = "[RDB_GETSQL_TEST]"; +const bucket1000: relationalStore.ValuesBucket = {}; +for(let i = 0; i < 1001; i++) { + bucket1000["test" + i] = i; +} +export default function RDBstoreGetSqlInfoTest() { + describe('rdbstoreGetSqlInfoTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll'); + }); + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + }); + afterEach(async () => { + console.info(TAG + 'afterEach'); + }); + afterAll(async () => { + console.info(TAG + 'afterAll'); + }); + + console.log(TAG + "*************Unit Test Begin*************"); + /** + * @tc.number testGetInsertSqlInfo + * @tc.name Get Insert SQL Info + * @tc.desc Tests the functionality of generating an INSERT SQL statement and its arguments. + */ + it('testGetInsertSqlInfo', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfo start *************"); + try { + const bucket: relationalStore.ValuesBucket = { + name: "Logitech", + age: "18", + sex: "man", + desc: "asserter" + }; + const info: relationalStore.SqlInfo = relationalStore.getInsertSqlInfo( + "USER", + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(info.sql).assertEqual("INSERT INTO USER(age,desc,name,sex) VALUES (?,?,?,?)"); + expect(info.args[0]).assertEqual("18"); + expect(info.args[1]).assertEqual("asserter"); + expect(info.args[2]).assertEqual("Logitech"); + expect(info.args[3]).assertEqual("man"); + console.log(TAG + "************* testGetInsertSqlInfo end *************"); + } catch (e){ + expect(null).assertFail(); + console.log(TAG + "************* testGetInsertSqlInfo end *************"); + } + }); + + /** + * @tc.number testGetInsertSqlInfoTabkleNameTooLong + * @tc.name Get Insert SQL Info tablename length must less then 256 + * @tc.desc Verifies that an error is thrown when the tablename is too long. + */ + it('testGetInsertSqlInfoTabkleNameTooLong', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfoTabkleNameTooLong start *************"); + const bucket: relationalStore.ValuesBucket = { + name: "Logitech", + age: "18", + sex: "man", + desc: "asserter" + }; + let tableName: string = "x".repeat(257); + try { + relationalStore.getInsertSqlInfo( + tableName, + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetInsertSqlInfoTabkleNameTooLong end *************"); + } + }); + + /** + * @tc.number testGetInsertSqlInfoBucketTooLong + * @tc.name Get Insert SQL Info Bucket length must less then 1000 + * @tc.desc Verifies that an error is thrown when the bucket is too long. + */ + it('testGetInsertSqlInfoBucketTooLong', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfoBucketTooLong start *************"); + try { + relationalStore.getInsertSqlInfo( + "user", + bucket1000, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetInsertSqlInfoBucketTooLong end *************"); + } + }); + + /** + * @tc.number testGetInsertSqlInfoBucketColumnTooLong + * @tc.name Get Insert SQL Info bucket key length must less then 256 + * @tc.desc Verifies that an error is thrown when the bucket Column is too long. + */ + it('testGetInsertSqlInfoBucketColumnTooLong', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfoBucketColumnTooLong start *************"); + let tableName: string = "a".repeat(257); + const bucket: relationalStore.ValuesBucket = { + name: tableName, + age: "18", + sex: "man", + desc: "asserter" + }; + bucket[tableName] = "tableName" + try { + relationalStore.getInsertSqlInfo( + "user", + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetInsertSqlInfoBucketColumnTooLong end *************"); + } + }); + + /** + * @tc.number testGetInsertSqlInfoTableNameIsEmpty + * @tc.name Get Insert SQL Info table Is empty + * @tc.desc Verifies that an error is thrown when the table is empty or null. + */ + it('testGetInsertSqlInfoTableNameIsEmpty', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfoTableNameIsEmpty start *************"); + const bucket: relationalStore.ValuesBucket = { + name: "tableName", + age: "18", + sex: "man", + desc: "asserter" + }; + try { + relationalStore.getInsertSqlInfo( + "", + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetInsertSqlInfoTableNameIsEmpty end *************"); + } + }); + + /** + * @tc.number testGetInsertSqlInfoConflictResolutionIsNotEmpty + * @tc.name Get Insert SQL Info + * @tc.desc Verifies that an error is thrown when the ConflictResolution is not empty. + */ + it('testGetInsertSqlInfoConflictResolutionIsNotEmpty', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfoConflictResolutionIsNotEmpty start *************"); + try { + const bucket: relationalStore.ValuesBucket = { + name: "tableName", + age: "18", + sex: "man", + desc: "asserter" + }; + const info: relationalStore.SqlInfo = relationalStore.getInsertSqlInfo( + "tableName", + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(info.sql).assertEqual("INSERT INTO tableName(age,desc,name,sex) VALUES (?,?,?,?)"); + console.log(TAG + "************* testGetInsertSqlInfoConflictResolutionIsNotEmpty end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetInsertSqlInfoConflictResolutionIsNotEmpty end *************"); + } + }); + + /** + * @tc.number testGetInsertSqlInfoBucketIsNull + * @tc.name Get Insert SQL Info Bucket Is Null + * @tc.desc Verifies that an error is thrown when the bucket is empty or null. + */ + it('testGetInsertSqlInfoBucketIsNull', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfoBucketIsNull start *************"); + const bucket: relationalStore.ValuesBucket = {}; + try { + relationalStore.getInsertSqlInfo( + "USER", + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetInsertSqlInfoBucketIsNull end *************"); + } + }); + + /** + * @tc.number testGetInsertSqlInfoBucketIsAssets + * @tc.name Get Insert SQL Info Bucket contains Assets + * @tc.desc Verifies that an error is thrown when the bucket contains Assets & ON_CONFLICT_REPLACE. + */ + it('testGetInsertSqlInfoBucketIsAssets', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfoBucketIsAssets start *************"); + const values: relationalStore.Assets = [ + { + name: "a", + uri: "b", + path: "c", + createTime: "d", + modifyTime: "e", + size: "f", + status: relationalStore.AssetStatus.ASSET_INSERT + } + ]; + const bucket: relationalStore.ValuesBucket = { + value: values + }; + try { + relationalStore.getInsertSqlInfo( + "ASSETS", + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_REPLACE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetInsertSqlInfoBucketIsAssets end *************"); + } + }); + + /** + * @tc.number testGetInsertSqlInfoBucketIsAssets2 + * @tc.name Get Insert SQL Info Bucket contains Assets + * @tc.desc Verifies that an error is thrown when the bucket contains Assets & ON_CONFLICT_IGNORE. + */ + it('testGetInsertSqlInfoBucketIsAssets2', 0, async () => { + console.log(TAG + "************* testGetInsertSqlInfoBucketIsAssets start *************"); + try { + const values: relationalStore.Assets = [ + { + name: "a", + uri: "b", + path: "c", + createTime: "d", + modifyTime: "e", + size: "f", + status: relationalStore.AssetStatus.ASSET_INSERT + } + ]; + const bucket: relationalStore.ValuesBucket = { + value: values + }; + const info: relationalStore.SqlInfo = relationalStore.getInsertSqlInfo( + "USER", + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_IGNORE + ); + const assets = info.args[0] as relationalStore.Assets; + expect(info.sql).assertEqual("INSERT OR IGNORE INTO USER(value) VALUES (?)"); + expect(assets.length).assertEqual(values.length); + expect(assets[0].name).assertEqual(values[0].name); + expect(assets[0].uri).assertEqual(values[0].uri); + expect(assets[0].path).assertEqual(values[0].path); + expect(assets[0].createTime).assertEqual(values[0].createTime); + expect(assets[0].modifyTime).assertEqual(values[0].modifyTime); + expect(assets[0].size).assertEqual(values[0].size); + expect(assets[0].status).assertEqual(values[0].status); + console.log(TAG + "************* testGetInsertSqlInfo end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetInsertSqlInfo end *************"); + } + }); + + /** + * @tc.number testGetUpdateSqlInfo + * @tc.name Get Update SQL Info + * @tc.desc Verifies `getUpdateSqlInfo` function correctly generates an UPDATE SQL statement and its arguments. + */ + it('testGetUpdateSqlInfo', 0, async () => { + console.log(TAG + "************* testGetUpdateSqlInfo start *************"); + try { + const bucket: relationalStore.ValuesBucket = { + name: "Logitech", + age: "18", + sex: "man", + desc: "asserter" + }; + const predicates = new relationalStore.RdbPredicates("users"); + const info: relationalStore.SqlInfo = relationalStore.getUpdateSqlInfo( + predicates, + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(info.sql).assertEqual("UPDATE users SET age=?,desc=?,name=?,sex=?"); + expect(info.args[0]).assertEqual("18"); + expect(info.args[1]).assertEqual("asserter"); + expect(info.args[2]).assertEqual("Logitech"); + expect(info.args[3]).assertEqual("man"); + console.log(TAG + "************* testGetUpdateSqlInfo end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetUpdateSqlInfo end *************"); + } + }); + + /** + * @tc.number testGetUpdateSqlInfoBucketIsNull + * @tc.name Get Update SQL Info Bucket Is Null + * @tc.desc Verifies that an error is thrown when the bucket is empty. + */ + it('testGetUpdateSqlInfoBucketIsNull', 0, async () => { + console.log(TAG + "************* testGetUpdateSqlInfoBucketIsNull start *************"); + const predicates = new relationalStore.RdbPredicates("users"); + const bucket: relationalStore.ValuesBucket = {}; + try { + relationalStore.getUpdateSqlInfo( + predicates, + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetUpdateSqlInfoBucketIsNull end *************"); + } + }); + + /** + * @tc.number testGetUpdateSqlInfoBucketTooLong + * @tc.name Get Update SQL Info Bucket length must less then 1000 + * @tc.desc Verifies that an error is thrown when the bucket is too long. + */ + it('testGetUpdateSqlInfoBucketTooLong', 0, async () => { + console.log(TAG + "************* testGetUpdateSqlInfoBucketTooLong start *************"); + const predicates = new relationalStore.RdbPredicates("users"); + try { + relationalStore.getUpdateSqlInfo( + predicates, + bucket1000, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetUpdateSqlInfoBucketTooLong end *************"); + } + }); + + /** + * @tc.number testGetUpdateSqlInfoBucketCloumnTooLong + * @tc.name Get Update SQL Info the column in bucket length must less then 256 + * @tc.desc Verifies that an error is thrown when the column in bucket is too long. + */ + it('testGetUpdateSqlInfoBucketCloumnTooLong', 0, async () => { + console.log(TAG + "************* testGetUpdateSqlInfoBucketCloumnTooLong start *************"); + const predicates = new relationalStore.RdbPredicates("users"); + let tableName: string = "a".repeat(257); + const bucket: relationalStore.ValuesBucket = { + age: "18", + sex: "man", + desc: "asserter" + }; + bucket[tableName] = "tableName"; + try { + relationalStore.getUpdateSqlInfo( + predicates, + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetUpdateSqlInfoBucketCloumnTooLong end *************"); + } + }); + + /** + * @tc.number testGetUpdateSqlInfoTableTooLong + * @tc.name Get Update SQL Info Bucket Is Null + * @tc.desc Verifies that an error is thrown when the tablename is too long. + */ + it('testGetUpdateSqlInfoTableTooLong', 0, async () => { + console.log(TAG + "************* testGetUpdateSqlInfoTableTooLong start *************"); + let tableName: string = "a".repeat(257); + for(let i = 0; i < 256; i++) { + tableName = tableName + "a"; + } + const predicates = new relationalStore.RdbPredicates(tableName); + const bucket: relationalStore.ValuesBucket = { + name: "tableName", + age: "18", + sex: "man", + desc: "asserter" + }; + try { + relationalStore.getUpdateSqlInfo( + predicates, + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetUpdateSqlInfoTableTooLong end *************"); + } + }); + + /** + * @tc.number testGetUpdateSqlInfoWhereClauseTooLong + * @tc.name Get Update SQL Info Bucket Is Null + * @tc.desc Verifies that an error is thrown when the WhereClause is too long. + */ + it('testGetUpdateSqlInfoWhereClauseTooLong', 0, async () => { + console.log(TAG + "************* testGetUpdateSqlInfoWhereClauseTooLong start *************"); + let tableName: string = ""; + for(let i = 0; i < 256; i++) { + tableName = tableName + "a"; + } + const predicates = new relationalStore.RdbPredicates("tableName"); + predicates.equalTo(tableName, "user"); + const bucket: relationalStore.ValuesBucket = { + name: "tableName", + age: "18", + sex: "man", + desc: "asserter" + }; + try { + relationalStore.getUpdateSqlInfo( + predicates, + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetUpdateSqlInfoWhereClauseTooLong end *************"); + } + }); + + /** + * @tc.number testGetUpdateSqlInfoConflictResolutionIsNotEmpty + * @tc.name Get Update SQL Info Bucket Is Null + * @tc.desc Verifies that an error is thrown when the Conflict is not empty. + */ + it('testGetUpdateSqlInfoConflictResolutionIsNotEmpty', 0, async () => { + console.log(TAG + "************* testGetUpdateSqlInfoConflictResolutionIsNotEmpty start *************"); + try { + const predicates = new relationalStore.RdbPredicates("tableName"); + predicates.equalTo("tableName", "user"); + const bucket: relationalStore.ValuesBucket = { + name: "tableName", + age: "18", + sex: "man", + desc: "asserter" + }; + const info: relationalStore.SqlInfo = relationalStore.getUpdateSqlInfo( + predicates, + bucket, + relationalStore.ConflictResolution.ON_CONFLICT_NONE + ); + expect(info.sql).assertEqual("UPDATE tableName SET age=?,desc=?,name=?,sex=? WHERE tableName = ? "); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetUpdateSqlInfoConflictResolutionIsEmpty end *************"); + } + }); + + /** + * @tc.number testGetDeleteSqlInfo + * @tc.name Get Delete SQL Info + * @tc.desc Verifies that the generated delete SQL statement is correct when the table name is provided. + */ + it('testGetDeleteSqlInfo', 0, async () => { + console.log(TAG + "************* testGetDeleteSqlInfo start *************"); + try { + const predicates = new relationalStore.RdbPredicates("users"); + const info: relationalStore.SqlInfo = relationalStore.getDeleteSqlInfo(predicates); + expect(info.sql).assertEqual("DELETE FROM users"); + console.log(TAG + "************* testGetDeleteSqlInfo end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetDeleteSqlInfo end *************"); + } + }); + + /** + * @tc.number testGetDeleteSqlInfo2 + * @tc.name Get Delete SQL Info Table Name Must Be Not Empty + * @tc.desc Verifies that the generated delete SQL statement is correct when the table name is provided. + */ + it('testGetDeleteSqlInfo2', 0, async () => { + console.log(TAG + "************* testGetDeleteSqlInfo2 start *************"); + try { + const predicates = new relationalStore.RdbPredicates("users"); + predicates.equalTo("tableName", "a"); + predicates.notEqualTo("age", 18) + const info: relationalStore.SqlInfo = relationalStore.getDeleteSqlInfo(predicates); + expect(info.sql).assertEqual("DELETE FROM users WHERE tableName = ? AND age <> ? "); + expect(info.args[0]).assertEqual("a"); + expect(info.args[1]).assertEqual(18); + console.log(TAG + "************* testGetDeleteSqlInfo2 end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetQuerySqlInfo end *************"); + } + }); + + /** + * @tc.number testGetDeleteSqlInfoTableNameTooLong + * @tc.name Get Delete SQL Info Table Name length Must less then 256 + * @tc.desc Verifies that an error is thrown when the table name is too long. + */ + it('testGetDeleteSqlInfoTableNameTooLong', 0, async () => { + console.log(TAG + "************* testGetDeleteSqlInfoTableNameTooLong start *************"); + try { + let tableName: string = "a".repeat(257); + const predicates = new relationalStore.RdbPredicates(tableName); + relationalStore.getDeleteSqlInfo(predicates); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetDeleteSqlInfoTableNameTooLong end *************"); + } + }); + + /** + * @tc.number testGetDeleteSqlInfoValueTooLong + * @tc.name Get Delete SQL Info value Must less then 256 + * @tc.desc Verifies that an error is thrown when the value is too long. + */ + it('testGetDeleteSqlInfoValueTooLong', 0, async () => { + console.log(TAG + "************* testGetDeleteSqlInfoValueTooLong start *************"); + try { + let tableName: string = "a".repeat(257); + const predicates = new relationalStore.RdbPredicates("tableName"); + predicates.equalTo(tableName, "a"); + relationalStore.getDeleteSqlInfo(predicates); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetDeleteSqlInfoValueTooLong end *************"); + } + }); + + /** + * @tc.number testGetQuerySqlInfo + * @tc.name Get Query SQL Info + * @tc.desc Verifies that the generated query SQL statement is correct with default columns. + */ + it('testGetQuerySqlInfo', 0, async () => { + console.log(TAG + "************* testGetQuerySqlInfo start *************"); + try { + const predicates = new relationalStore.RdbPredicates("users"); + const info: relationalStore.SqlInfo = relationalStore.getQuerySqlInfo(predicates); + expect(info.sql).assertEqual("SELECT * FROM users"); + console.log(TAG + "************* testGetQuerySqlInfo end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetQuerySqlInfo end *************"); + } + }); + + /** + * @tc.number testGetQuerySqlInfoColumnsIsNullList + * @tc.name Get Query SQL Info Columns Is Null List + * @tc.desc Verifies that the generated query SQL statement is correct when an empty column list is provided. + */ + it('testGetQuerySqlInfoColumnsIsNullList', 0, async () => { + console.log(TAG + "************* testGetQuerySqlInfoColumnsIsNullList start *************"); + try { + const predicates = new relationalStore.RdbPredicates("users"); + const info: relationalStore.SqlInfo = relationalStore.getQuerySqlInfo(predicates, []); + expect(info.sql).assertEqual("SELECT * FROM users"); + console.log(TAG + "************* testGetQuerySqlInfoColumnsIsNullList end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetQuerySqlInfoColumnsIsNullList end *************"); + } + }); + + /** + * @tc.number testGetQuerySqlInfoByColumns + * @tc.name Get Query SQL Info By Columns + * @tc.desc Verifies that the generated query SQL statement is correct when specific columns are provided. + */ + it('testGetQuerySqlInfoByColumns', 0, async () => { + console.log(TAG + "************* testGetQuerySqlInfoByColumns start *************"); + try { + const predicates = new relationalStore.RdbPredicates("users"); + const info: relationalStore.SqlInfo = relationalStore.getQuerySqlInfo(predicates, ["name", "age"]); + expect(info.sql).assertEqual("SELECT name, age FROM users"); + console.log(TAG + "************* testGetQuerySqlInfoByColumns end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetQuerySqlInfoByColumns end *************"); + } + }); + + /** + * @tc.number testGetQuerySqlInfoTableNameTooLong + * @tc.name Get Query SQL Info Table Name length must less then 256 + * @tc.desc Verifies that an error is thrown when the Table is too Long. + */ + it('testGetQuerySqlInfoTableNameTooLong', 0, async () => { + console.log(TAG + "************* testGetQuerySqlInfoTableNameTooLong start *************"); + try { + let tableName: string = "a".repeat(257); + const predicates = new relationalStore.RdbPredicates(tableName); + relationalStore.getQuerySqlInfo(predicates); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetQuerySqlInfoTableNameTooLong end *************"); + } + }); + + /** + * @tc.number testGetQuerySqlInfoWhereClauseTooLong + * @tc.name Get Query SQL Info WhereClause length is less then 256 + * @tc.desc Verifies that an error is thrown when the WhereClause is too long. + */ + it('testGetQuerySqlInfoWhereClauseTooLong', 0, async () => { + console.log(TAG + "************* testGetQuerySqlInfoWhereClauseTooLong start *************"); + try { + let tableName: string = "a".repeat(257); + const predicates = new relationalStore.RdbPredicates("tableName"); + predicates.equalTo(tableName, "a"); + relationalStore.getQuerySqlInfo(predicates); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetQuerySqlInfoWhereClauseTooLong end *************"); + } + }); + + /** + * @tc.number testGetQuerySqlInfoColumnsNotstringarray + * @tc.name Get Query SQL Info Columns must be a string array + * @tc.desc Verifies that an error is thrown when the Columns is not a string array. + */ + it('testGetQuerySqlInfoColumnsNotstringarray', 0, async () => { + console.log(TAG + "************* testGetQuerySqlInfoColumnsNotstringarray start *************"); + try { + const predicates = new relationalStore.RdbPredicates("tableName"); + predicates.equalTo("tableName", "a"); + const info: relationalStore.SqlInfo = relationalStore.getQuerySqlInfo(predicates, ["3", "4"]); + expect(info.sql).assertEqual("SELECT 3, 4 FROM tableName WHERE tableName = ? "); + expect(info.args[0]).assertEqual('a'); + console.log(TAG + "************* testGetQuerySqlInfoColumnsNotstringarray end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testGetQuerySqlInfoColumnsNotstringarray end *************"); + } + }); + + /** + * @tc.number testGetQuerySqlInfoColumnsTooLong + * @tc.name Get Query SQL Info Columns length Must less then 1000 + * @tc.desc Verifies that an error is thrown when the Columns is too length. + */ + it('testGetQuerySqlInfoColumnsTooLong', 0, async () => { + console.log(TAG + "************* testGetQuerySqlInfoColumnsTooLong start *************"); + try { + const colums:string[] = new Array(1003); + for(let i = 0; i < colums.length; i++) { + colums[i] = "a"; + } + const predicates = new relationalStore.RdbPredicates("tableName"); + predicates.equalTo("tableName", "a"); + relationalStore.getQuerySqlInfo(predicates, colums); + expect(null).assertFail(); + } catch (e) { + expect(e.code).assertEqual("14800001"); + console.log(TAG + "************* testGetQuerySqlInfoColumnsTooLong end *************"); + } + }); + + /** + * @tc.number testToSendableValues + * @tc.name Test To Sendable Values + * @tc.desc Verifies that converting an array of values to sendable values works correctly. + */ + it('testToSendableValues', 0, async () => { + console.log(TAG + "************* testToSendableValues start *************"); + try { + const array: relationalStore.ValueType[] = []; + array.push(1); + array.push(2); + array.push("aaaaaaa"); + const values = sendableRelationalStore.toSendableValues(array); + expect(values.length).assertEqual(3); + expect(values[0]).assertEqual(1); + expect(values[1]).assertEqual(2); + expect(values[2]).assertEqual("aaaaaaa"); + console.log(TAG + "************* testToSendableValues end *************"); + } catch (e) { + expect(null).assertFail(); + console.log(TAG + "************* testToSendableValues end *************"); + } + }); + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetValueForFlutterEts.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetValueForFlutterEts.test.ets new file mode 100644 index 00000000..b8d84618 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreGetValueForFlutterEts.test.ets @@ -0,0 +1,299 @@ + +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level, Size, TestType, + Assert } from "@ohos/hypium"; +import relationalStore from '@ohos.data.relationalStore'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import { ValuesBucket } from "@ohos.data.ValuesBucket"; + + +const TAG = "[STAGE_RELATIONAL_STORE_JSKITS_TEST]"; +let rdbStore:relationalStore.RdbStore | undefined = undefined; + +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + + "id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, salary REAL, blobType BLOB, data1 asset)"; + +const STORE_CONFIG: relationalStore.StoreConfig = { + name: "rdbStore.db", + securityLevel: relationalStore.SecurityLevel.S1, +} + +const delegator = AbilityDelegatorRegistry.getAbilityDelegator(); +const context = delegator.getAppContext().getApplicationContext(); + + +export default function getValueForFlutterEtsTest() { + describe('getValueForFlutterEtsTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll') + }) + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore?.executeSql(CREATE_TABLE_TEST); + }) + afterEach(async () => { + console.info(TAG + 'afterEach'); + await relationalStore.deleteRdbStore(context, "rdbStore.db"); + }) + afterAll(async () => { + console.info(TAG + 'afterAll'); + }) + + + /** + * @tc.name testRdbStoreGetValueForFlutter + * @tc.number testRdbStoreGetValueForFlutter_0001 + * @tc.desc integer greater than Number.MAX_SAFE_INTEGER test + */ + it('testRdbStoreGetValueForFlutter_0001', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0001 start *************"); + let valueNum = Number.MAX_SAFE_INTEGER.toString() + 0; + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': valueNum, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + expect(valueNum).assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('age'))); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0001 end *************"); + }) + + /** + * @tc.name testRdbStoreGetValueForFlutter + * @tc.number testRdbStoreGetValueForFlutter_0002 + * @tc.desc integer is Number.MAX_SAFE_INTEGER test + */ + it('testRdbStoreGetValueForFlutter_0002', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0002 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': Number.MAX_SAFE_INTEGER, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + expect(Number.MAX_SAFE_INTEGER).assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('age'))); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0002 end *************"); + }) + + /** + * @tc.name testRdbStoreGetValueForFlutter + * @tc.number testRdbStoreGetValueForFlutter_0003 + * @tc.desc integer less than Number.MAX_SAFE_INTEGER test + */ + it('testRdbStoreGetValueForFlutter_0003', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0003 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': 100, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + expect(100).assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('age'))); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0003 end *************"); + }) + + /** + * @tc.name testRdbStoreGetValueForFlutter + * @tc.number testRdbStoreGetValueForFlutter_0004 + * @tc.desc integer greater than Number.MIN_SAFE_INTEGER test + */ + it('testRdbStoreGetValueForFlutter_0004', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0004 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': -100, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + expect(-100).assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('age'))); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0004 end *************"); + }) + + /** + * @tc.name testRdbStoreGetValueForFlutter + * @tc.number testRdbStoreGetValueForFlutter_0005 + * @tc.desc integer is Number.MIN_SAFE_INTEGER test + */ + it('testRdbStoreGetValueForFlutter_0005', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0005 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': Number.MIN_SAFE_INTEGER, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + expect(Number.MIN_SAFE_INTEGER).assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('age'))); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0005 end *************"); + }) + + /** + * @tc.name testRdbStoreGetValueForFlutter + * @tc.number testRdbStoreGetValueForFlutter_0006 + * @tc.desc integer less than Number.MIN_SAFE_INTEGER test + */ + it('testRdbStoreGetValueForFlutter_0006', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0006 start *************"); + let valueNum = Number.MIN_SAFE_INTEGER.toString() + 0; + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const valueBucket1: ValuesBucket = { + 'age': valueNum, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + expect(valueNum).assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('age'))); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0006 end *************"); + }) + + /** + * @tc.name testRdbStoreGetValueForFlutter + * @tc.number testRdbStoreGetValueForFlutter_0007 + * @tc.desc other types test + */ + it('testRdbStoreGetValueForFlutter_0007', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0007 start *************"); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore.executeSql(CREATE_TABLE_TEST); + const asset1: relationalStore.Asset = { + name: "name1", + uri: "uri1", + createTime: "createTime1", + modifyTime: "modifyTime1", + size: "size1", + path: "path1", + } + const valueBucket1: relationalStore.ValuesBucket = { + 'name': 'test', + 'age': 18, + 'salary': 100, + 'blobType': true, + 'data1': asset1, + } + try { + let rowId = await rdbStore.insert("test", valueBucket1); + expect(1).assertEqual(rowId); + } catch (err) { + console.error(`### insert failed, code:${err.code}, message:${err.message}`); + } + try { + let resultSet = await rdbStore.querySql('SELECT * FROM test'); + expect(true).assertEqual(resultSet.goToFirstRow()); + expect('test').assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('name'))); + expect(18).assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('age'))); + expect(1).assertEqual(resultSet.getValueForFlutter(resultSet.getColumnIndex('blobType'))); + const assets2 = resultSet.getValueForFlutter(resultSet.getColumnIndex('data1')) as relationalStore.Asset; + expect(asset1.name).assertEqual(assets2.name); + expect(asset1.uri).assertEqual(assets2.uri); + expect(asset1.createTime).assertEqual(assets2.createTime); + expect(asset1.modifyTime).assertEqual(assets2.modifyTime); + expect(asset1.size).assertEqual(assets2.size); + expect(asset1.path).assertEqual(assets2.path); + resultSet.close(); + } catch (err) { + console.error(`### query failed, code:${err.code}, message:${err.message}`); + } + done(); + console.log(TAG + "************* testRdbStoreGetValueForFlutter_0007 end *************"); + }) + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstorePerfStatEts.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstorePerfStatEts.test.ets new file mode 100644 index 00000000..02fbd83d --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstorePerfStatEts.test.ets @@ -0,0 +1,671 @@ + +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level, Size, TestType } from "@ohos/hypium"; +import relationalStore from '@ohos.data.relationalStore'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; + +const TAG = "[STAGE_RELATIONAL_STORE_JSKITS_TEST]"; +let rdbStore:relationalStore.RdbStore | undefined = undefined; + +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL)"; + +const STORE_CONFIG: relationalStore.StoreConfig = { + name: "rdbStore.db", + securityLevel: relationalStore.SecurityLevel.S1, +} + +const delegator = AbilityDelegatorRegistry.getAbilityDelegator(); +const context = delegator.getAppContext().getApplicationContext(); + + +export default function PerfStatEtsTest() { + describe('perfStatEtsTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll') + }) + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore?.executeSql(CREATE_TABLE_TEST); + const valueBucket: relationalStore.ValuesBucket = { + 'name': 'zhangsan', + 'age': 18, + 'salary': 25000, + }; + await rdbStore?.insert('test', valueBucket); + await new Promise(resolve => setTimeout(resolve, 1000)); + }) + afterEach(async () => { + console.info(TAG + 'afterEach'); + try { + rdbStore?.off('perfStat'); + } catch (err) { + expect(err.code).assertEqual("14800014"); + } + await relationalStore.deleteRdbStore(context, "rdbStore.db"); + }) + afterAll(async () => { + console.info(TAG + 'afterAll'); + }) + + + /** + * @tc.name Normal case for perfStat insert data execution time + * @tc.number testRdbStorePerfStat_0001 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0001', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0001 start *************"); + rdbStore?.on('perfStat', async (SqlExeInfo) => { + expect('INSERT INTO test(age,name,salary) VALUES (?,?,?)').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }) + const valueBucket: relationalStore.ValuesBucket = { + 'name': 'zhangsan', + 'age': 18, + 'salary': 25000, + }; + let rowId = await rdbStore?.insert('test', valueBucket); + expect(2).assertEqual(rowId); + + console.log(TAG + "************* testRdbStorePerfStat_0001 end *************"); + }) + + /** + * @tc.name Normal case for perfStat update data execution time + * @tc.number testRdbStorePerfStat_0002 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0002', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0002 start *************"); + rdbStore?.on('perfStat', async (SqlExeInfo) => { + expect('UPDATE test SET age=?,name=?,salary=? WHERE id = ? ').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }) + + const valueBucket: relationalStore.ValuesBucket = { + 'name': 'lisi', + 'age': 18, + 'salary': 25000, + }; + let predicates = new relationalStore.RdbPredicates('test'); + predicates.equalTo('id', 1); + let rowId = await rdbStore?.update(valueBucket, predicates); + expect(1).assertEqual(rowId); + console.log(TAG + "************* testRdbStorePerfStat_0002 end *************"); + }) + + /** + * @tc.name Normal case for perfStat delete data execution time + * @tc.number testRdbStorePerfStat_0003 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0003', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0003 start *************"); + rdbStore?.on('perfStat', async (SqlExeInfo) => { + expect('DELETE FROM test WHERE id = ? ').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }) + + + let predicates = new relationalStore.RdbPredicates('test'); + predicates.equalTo('id', 1); + let rowId = await rdbStore?.delete(predicates); + expect(1).assertEqual(rowId); + console.log(TAG + "************* testRdbStorePerfStat_0003 end *************"); + }) + + /** + * @tc.name Normal case for perfStat executeSql data execution time + * @tc.number testRdbStorePerfStat_0004 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0004', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0004 start *************"); + rdbStore?.on('perfStat', async (SqlExeInfo) => { + expect('CREATE TABLE IF NOT EXISTS EMPLOYEE (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }) + + const SQL_CREATE_TABLE1 = "CREATE TABLE IF NOT EXISTS EMPLOYEE (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT NOT NULL)"; // 建表Sql语句 + await rdbStore?.executeSql(SQL_CREATE_TABLE1) + console.log(TAG + "************* testRdbStorePerfStat_0004 end *************"); + }) + + /** + * @tc.name Normal case for perfStat execute data execution time + * @tc.number testRdbStorePerfStat_0005 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0005', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0005 start *************"); + rdbStore?.on('perfStat', async (SqlExeInfo) => { + expect('PRAGMA quick_check').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }) + await rdbStore?.execute("PRAGMA quick_check") + console.log(TAG + "************* testRdbStorePerfStat_0005 end *************"); + }) + + /** + * @tc.name Normal case for perfStat update data execution time + * @tc.number testRdbStorePerfStat_0006 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0006', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0006 start *************"); + rdbStore?.on('perfStat', async (SqlExeInfo) => { + expect('SELECT * FROM test').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }) + let predicates = new relationalStore.RdbPredicates('test'); + await rdbStore?.query(predicates); + console.log(TAG + "************* testRdbStorePerfStat_0006 end *************"); + }) + + /** + * @tc.name Normal case for perfStat querySql data execution time + * @tc.number testRdbStorePerfStat_0007 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0007', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0007 start *************"); + rdbStore?.on('perfStat', async (SqlExeInfo) => { + expect('SELECT * FROM test').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }) + await rdbStore?.querySql("SELECT * FROM test"); + console.log(TAG + "************* testRdbStorePerfStat_0007 end *************"); + }) + + /** + * @tc.name Normal case for perfStat update querySql execution time + * @tc.number testRdbStorePerfStat_0008 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0008', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0008 start *************"); + rdbStore?.on('perfStat', async (SqlExeInfo) => { + expect('with test1 as (select * from test) select * from test').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }) + await rdbStore?.querySql("with test1 as (select * from test) select * from test"); + console.log(TAG + "************* testRdbStorePerfStat_0008 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0009 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0009', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0009 start *************"); + let observer1 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect('SELECT * FROM test').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }; + + let observer2 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + + rdbStore?.on('perfStat', observer1) + await rdbStore?.querySql("SELECT * FROM test"); + // done() + console.log(TAG + "************* testRdbStorePerfStat_0009 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0010 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0010', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0010 start *************"); + let observer1 = async (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect('SELECT * FROM test').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + await new Promise(resolve => setTimeout(resolve, 2000)); + done() + }; + + let observer2 = async (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect('SELECT * FROM test').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + await new Promise(resolve => setTimeout(resolve, 2000)); + done() + }; + + rdbStore?.on('perfStat', observer1) + rdbStore?.on('perfStat', observer2) + await rdbStore?.querySql("SELECT * FROM test"); + console.log(TAG + "************* testRdbStorePerfStat_0010 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0011 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0011', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0011 start *************"); + let observer = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect('INSERT INTO test(age,name,salary) VALUES (?,?,?)').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }; + let observer1 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect('INSERT INTO test(age,name,salary) VALUES (?,?,?)').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }; + rdbStore?.on('perfStat', observer) + rdbStore?.on('statistics', observer1) + const valueBucket1: relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + } + await rdbStore?.insert("test", valueBucket1) + rdbStore?.off('statistics') + console.log(TAG + "************* testRdbStorePerfStat_0011 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0012 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0012', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0012 start *************"); + let observer = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect('INSERT INTO test(age,name,salary) VALUES (?,?,?)').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }; + let observer1 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + rdbStore?.on('statistics', observer1) + rdbStore?.off('statistics') + await new Promise(resolve => setTimeout(resolve, 1000)); + rdbStore?.on('perfStat', observer) + const valueBucket1: relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + } + await rdbStore?.insert("test", valueBucket1) + console.log(TAG + "************* testRdbStorePerfStat_0012 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0013 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0013', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0013 start *************"); + let observer = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect(SqlExeInfo.sql.length > 0).assertTrue(); + done() + }; + let observer1 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + rdbStore?.on('perfStat', observer1) + rdbStore?.off('perfStat') + rdbStore?.on('statistics', observer) + const valueBucket1: relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + } + await rdbStore?.insert("test", valueBucket1) + await new Promise(resolve => setTimeout(resolve, 1000)); + rdbStore?.off('statistics') + console.log(TAG + "************* testRdbStorePerfStat_0013 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0014 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0014', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0014 start *************"); + let observer1 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + let observer2 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + + rdbStore?.on('perfStat', observer1) + rdbStore?.off('perfStat') + rdbStore?.on('perfStat', observer2) + rdbStore?.off('perfStat') + await new Promise(resolve => setTimeout(resolve, 1000)); + await rdbStore?.querySql("SELECT * FROM test"); + done() + console.log(TAG + "************* testRdbStorePerfStat_0014 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0015 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0015', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0015 start *************"); + let observer1 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + let observer2 = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect('SELECT * FROM test').assertEqual(SqlExeInfo.sql[0]); + expect(1).assertEqual(SqlExeInfo.sql.length); + done() + }; + + rdbStore?.on('perfStat', observer1) + rdbStore?.off('perfStat', observer1) + rdbStore?.on('perfStat', observer2) + await new Promise(resolve => setTimeout(resolve, 1000)); + await rdbStore?.querySql("SELECT * FROM test"); + console.log(TAG + "************* testRdbStorePerfStat_0015 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0016 + * @tc.desc 1. Register callback for perfStat + + */ + it('testRdbStorePerfStat_0016', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0016 start *************"); + let store2: relationalStore.RdbStore | undefined = undefined; + let STORE_CONFIG2: relationalStore.StoreConfig = { + name: 'test2.db', + securityLevel: relationalStore.SecurityLevel.S1 + }; + store2 = await relationalStore.getRdbStore(context, STORE_CONFIG2) + await store2?.executeSql(CREATE_TABLE_TEST); + let timerId = -1; + let observer1 = async (sqlExecutionInfo : relationalStore.SqlExecutionInfo) => { + expect('INSERT INTO test(age,name,salary) VALUES (?,?,?)').assertEqual(sqlExecutionInfo.sql[0]); + expect(1).assertEqual(sqlExecutionInfo.sql.length); + if (timerId > 0) { + clearTimeout(timerId); + expect().assertFail(); + } + timerId = setTimeout(done, 2000); + }; + rdbStore?.on('perfStat',observer1) + + const valueBucket: relationalStore.ValuesBucket = { + 'name': 'zhangsan', + 'age': 18, + 'salary': 25000, + }; + let rowId = await rdbStore?.insert('test', valueBucket); + expect(2).assertEqual(rowId); + let rowId2 = await store2?.insert('test', valueBucket); + expect(1).assertEqual(rowId2); + console.log(TAG + "************* testRdbStorePerfStat_0016 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0001 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0017', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0017 start *************"); + let store2: relationalStore.RdbStore | undefined = undefined; + let STORE_CONFIG2: relationalStore.StoreConfig = { + name: 'test2.db', + securityLevel: relationalStore.SecurityLevel.S1 + }; + let timerId = -1; + let observer1 = async (sqlExecutionInfo : relationalStore.SqlExecutionInfo) => { + if (timerId = -1) { + clearTimeout(timerId); + expect().assertFail(); + } + }; + rdbStore?.on('perfStat',observer1) + store2 = await relationalStore.getRdbStore(context, STORE_CONFIG2) + timerId = setTimeout(done, 2000); + console.log(TAG + "************* testRdbStorePerfStat_0017 end *************"); + }) + + /** + * @tc.name Normal case for perfStat + * @tc.number testRdbStorePerfStat_0001 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0018', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0018 start *************"); + let observer1 = async (sqlExecutionInfo : relationalStore.SqlExecutionInfo) => { + expect(4).assertEqual(sqlExecutionInfo.sql.length); + done() + }; + rdbStore?.on('perfStat',observer1) + + const rdbTrans = await rdbStore?.createTransaction(); + const valueBucket1: relationalStore.ValuesBucket = { + 'name': 'zhangsan', + 'age': 18, + 'salary': 25000, + }; + await rdbTrans?.insert('test', valueBucket1) + await rdbTrans?.insert("test", valueBucket1) + await rdbTrans?.commit(); + console.log(TAG + "************* testRdbStorePerfStat_0018 end *************"); + }) + + /** + * @tc.name Normal case for perfStat update data execution time + * @tc.number testRdbStorePerfStat_0019 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0019', 0, async () => { + console.log(TAG + "************* testRdbStorePerfStat_0019 start *************"); + let observer = (SqlExeInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + + rdbStore?.close(); + try { + rdbStore?.on('perfStat', observer); + } catch (err) { + expect(err.code).assertEqual("14800014"); + } + console.log(TAG + "************* testRdbStorePerfStat_0019 end *************"); + }) + + /** + * @tc.name Normal case for perfStat batchInsert data execution time + * @tc.number testRdbStorePerfStat_0020 + * @tc.desc 1. Register callback for perfStat + * 2. Update data + */ + it('testRdbStorePerfStat_0020', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0020 start *************"); + let observer = (sqlExecutionInfo : relationalStore.SqlExecutionInfo) => { + expect(1).assertEqual(sqlExecutionInfo.sql.length); + done() + }; + rdbStore?.on('perfStat', observer); + const valueBucket1: relationalStore.ValuesBucket = { + 'id': 1, + 'name': 'zhangsan', + 'age': 13, + }; + const valueBucket2: relationalStore.ValuesBucket = { + 'id': 2, + 'name': 'zhangsan', + 'age': 13, + }; + const valueBucket3: relationalStore.ValuesBucket = { + 'id': 5, + 'name': 'zhangsan', + 'age': 13, + }; + let valueBuckets = new Array(valueBucket1, valueBucket2, valueBucket3); + await rdbStore?.batchInsert("test", valueBuckets); + console.log(TAG + "************* testRdbStorePerfStat_0020 end *************"); + }) + + /** + * @tc.name Normal case for perfStat batchInsert data execution time + * @tc.number testRdbStorePerfStat_0021 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0021', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0021 start *************"); + let observer = (sqlExecutionInfo : relationalStore.SqlExecutionInfo) => { + expect('INSERT OR REPLACE INTO test (age,id,name) VALUES (?,?,?),...,3').assertEqual(sqlExecutionInfo.sql[1]); + expect(3).assertEqual(sqlExecutionInfo.sql.length); + done() + }; + rdbStore?.on('perfStat', observer); + const rdbTrans = await rdbStore?.createTransaction(); + const valueBucket1: relationalStore.ValuesBucket = { + 'id': 1, + 'name': 'zhangsan', + 'age': 13, + }; + const valueBucket2: relationalStore.ValuesBucket = { + 'id': 2, + 'name': 'zhangsan', + 'age': 13, + }; + const valueBucket3: relationalStore.ValuesBucket = { + 'id': 5, + 'name': 'zhangsan', + 'age': 13, + }; + let valueBuckets = new Array(valueBucket1, valueBucket2, valueBucket3); + await rdbTrans?.batchInsert("test", valueBuckets); + await rdbTrans?.commit(); + console.log(TAG + "************* testRdbStorePerfStat_0021 end *************"); + }) + + /** + * @tc.name Normal case for perfStat batchInsert data execution time + * @tc.number testRdbStorePerfStat_0022 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0022', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0022 start *************"); + let observer = (sqlExecutionInfo : relationalStore.SqlExecutionInfo) => { + expect('INSERT OR REPLACE INTO test (age,name) VALUES (?,?),...,30000').assertEqual(sqlExecutionInfo.sql[1]); + expect(3).assertEqual(sqlExecutionInfo.sql.length); + done() + }; + rdbStore?.on('perfStat', observer); + const rdbTrans = await rdbStore?.createTransaction(); + + let valueBuckets : relationalStore.ValuesBucket[] = new Array(); + const valueBucket1: relationalStore.ValuesBucket = { + 'name': 'zhangsan', + 'age': 13, + }; + for (let i = 0; i < 30000; i++) { + valueBuckets.push(valueBucket1) + } + await rdbTrans?.batchInsert("test", valueBuckets); + await rdbTrans?.commit(); + console.log(TAG + "************* testRdbStorePerfStat_0022 end *************"); + }) + + /** + * @tc.name Abnormal case for perfStat + * @tc.number testRdbStorePerfStat_0023 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0023', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0023 start *************"); + if (!relationalStore.isVectorSupported()) { + done() + return + } + let observer = (sqlExecutionInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + let STORE_CONFIG1: relationalStore.StoreConfig = { + name: 'rdbStore2.db', + securityLevel: relationalStore.SecurityLevel.S1, + vector: true, + }; + let rdbStore1 = await relationalStore.getRdbStore(context, STORE_CONFIG1) + try{ + rdbStore1.on('perfStat', observer); + expect().assertFail(); + done(); + } catch (err){ + expect(err.code).assertEqual("801"); + done() + } + console.log(TAG + "************* testRdbStorePerfStat_0023 end *************"); + }) + + /** + * @tc.name Abnormal case for perfStat + * @tc.number testRdbStorePerfStat_0024 + * @tc.desc 1. Register callback for perfStat + */ + it('testRdbStorePerfStat_0024', 0, async (done:Function) => { + console.log(TAG + "************* testRdbStorePerfStat_0024 start *************"); + if (!relationalStore.isVectorSupported()) { + done() + return + } + let observer = (sqlExecutionInfo : relationalStore.SqlExecutionInfo) => { + expect().assertFail(); + }; + let STORE_CONFIG1: relationalStore.StoreConfig = { + name: 'rdbStore2.db', + securityLevel: relationalStore.SecurityLevel.S1, + vector: true, + }; + let rdbStore1 = await relationalStore.getRdbStore(context, STORE_CONFIG1) + try{ + rdbStore1.off('perfStat', observer); + expect().assertFail(); + done(); + } catch (err){ + expect(err.code).assertEqual("801"); + done() + } + console.log(TAG + "************* testRdbStorePerfStat_0024 end *************"); + }) + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstorePredicatesEts.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstorePredicatesEts.test.ets new file mode 100644 index 00000000..dab7011c --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstorePredicatesEts.test.ets @@ -0,0 +1,369 @@ +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; +import relationalStore from '@ohos.data.relationalStore' +const TAG = "[STAGE_RELATIONAL_STORE_JSKITS_TEST]"; +const STORE_CONFIG: relationalStore.StoreConfig = { + name: "Predicates.db", + securityLevel: relationalStore.SecurityLevel.S1, +}; +const SQL_CREATE_TABLE = + 'CREATE TABLE IF NOT EXISTS orders (id INTEGER PRIMARY KEY AUTOINCREMENT, customer_id INTEGER, amount INTEGER)'; +let rdbStore: relationalStore.RdbStore | undefined = undefined; + +async function preData():Promise +{ + const INSERT_SQL = + 'INSERT INTO orders (customer_id, amount) VALUES' + + '(1, 1500), (1, 2000), (1, 3000), (2, 800), (2, 1200), (3, 1500), (3, 2000), (3, 2500), (3, 1000)'; + await rdbStore?.executeSql(INSERT_SQL); +} + +export default function RdbPredicatesEtsTest() { + describe('rdbPredicatesEtsTest', () => { + beforeAll(async () => { + rdbStore = await relationalStore.getRdbStore(globalThis.abilityContext, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + console.info(TAG + 'beforeAll'); + }); + beforeEach(async () => { + await rdbStore?.executeSql(SQL_CREATE_TABLE); + await preData(); + console.info(TAG + 'beforeEach'); + }); + afterEach(async () => { + await rdbStore?.executeSql('DROP TABLE IF EXISTS orders'); + console.info(TAG + 'afterEach'); + }); + afterAll(async () => { + rdbStore = undefined; + await relationalStore.deleteRdbStore(globalThis.abilityContext, "Predicates.db"); + console.info(TAG + 'afterAll'); + }); + + console.log(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_001 + * @tc.name Verify no placeholders and pass in empty args in the scenario + * @tc.desc 1.Execute having("total > 5000 AND count >= 3", []) + * 2.Query data + */ + it('testHaving001', 0, async () => { + console.log(TAG + "************* testHaving001 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having("total > 5000 AND count >= 3", []); + let resultSet:relationalStore.ResultSet = + rdbStore?.querySync(predicates, ["customer_id", "COUNT(*) AS count", "SUM(amount) AS total"]) as relationalStore.ResultSet; + console.info(TAG + 'testHaving001 rowCount ' + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToNextRow()); + let row:relationalStore.ValuesBucket = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving001 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(1); + expect(row.total).assertEqual(6500); + expect(true).assertEqual(resultSet.goToNextRow()); + row = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving001 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(3); + expect(row.total).assertEqual(7000); + resultSet.close(); + console.log(TAG + " testHaving001 having success"); + } catch (e) { + console.error(TAG + " testHaving001 having failed" + e); + expect(true).assertFail(); + } + console.log(TAG + "************* testHaving001 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_002 + * @tc.name Verify scenarios without placeholders and without passing args + * @tc.desc 1.Execute having("total > 5000 AND count >= 3") + * 2.Query data + */ + it('testHaving002', 0, async () => { + console.log(TAG + "************* testHaving002 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having("total > 5000 AND count >= 3"); + let resultSet:relationalStore.ResultSet = + rdbStore?.querySync(predicates, ["customer_id", "COUNT(*) AS count", "SUM(amount) AS total"]) as relationalStore.ResultSet; + console.info(TAG + 'testHaving002 rowCount ' + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToNextRow()); + let row:relationalStore.ValuesBucket = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving002 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(1); + expect(row.total).assertEqual(6500); + expect(true).assertEqual(resultSet.goToNextRow()); + row = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving002 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(3); + expect(row.total).assertEqual(7000); + resultSet.close(); + console.log(TAG + " testHaving002 having success"); + } catch (e) { + console.error(TAG + " testHaving002 having failed" + e); + expect(true).assertFail(); + } + console.log(TAG + "************* testHaving002 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_003 + * @tc.name Verify the absence of placeholders and null passing scenarios for args + * @tc.desc 1.Execute having("SALARY = 1.2", null) + * 2.Query data + */ + it('testHaving003', 0, async () => { + console.log(TAG + "************* testHaving003 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having("total > 5000 AND count >= 3", null); + let resultSet:relationalStore.ResultSet = + rdbStore?.querySync(predicates, ["customer_id", "COUNT(*) AS count", "SUM(amount) AS total"]) as relationalStore.ResultSet; + console.info(TAG + 'testHaving003 rowCount ' + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToNextRow()); + let row:relationalStore.ValuesBucket = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving003 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(1); + expect(row.total).assertEqual(6500); + expect(true).assertEqual(resultSet.goToNextRow()); + row = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving003 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(3); + expect(row.total).assertEqual(7000); + resultSet.close(); + console.log(TAG + " testHaving003 having success"); + } catch (e) { + console.error(TAG + " testHaving003 having failed" + e); + expect(true).assertFail(); + } + console.log(TAG + "************* testHaving001 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_004 + * @tc.name Verify the absence of placeholders and undefined passing scenarios for args + * @tc.desc 1.Execute having("SALARY = 1.2", undefined) + * 2.Query data + */ + it('testHaving004', 0, async () => { + console.log(TAG + "************* testHaving001 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having("total > 5000 AND count >= 3", undefined); + let resultSet:relationalStore.ResultSet = + rdbStore?.querySync(predicates, ["customer_id", "COUNT(*) AS count", "SUM(amount) AS total"]) as relationalStore.ResultSet; + console.info(TAG + 'testHaving004 rowCount ' + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToNextRow()); + let row:relationalStore.ValuesBucket = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving004 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(1); + expect(row.total).assertEqual(6500); + expect(true).assertEqual(resultSet.goToNextRow()); + row = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving004 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(3); + expect(row.total).assertEqual(7000); + resultSet.close(); + console.log(TAG + " testHaving004 having success"); + } catch (e) { + console.error(TAG + " testHaving004 having failed" + e); + expect(true).assertFail(); + } + console.log(TAG + "************* testHaving004 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_005 + * @tc.name Normal test case for predicate, testing 'having' passing in null condition + * @tc.desc 1.Execute having("") + * 2.Query data + */ + it('testHaving005', 0, async () => { + console.log(TAG + "************* testHaving005 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having(""); + console.log(TAG + " testHaving005 having success"); + expect(true).assertFail(); + } catch (e) { + console.error(TAG + " testHaving005 having failed" + e); + expect(e.code == 14800001).assertTrue(); + } + console.log(TAG + "************* testHaving005 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_006 + * @tc.name Test conditions for passing in illegal SQL + * @tc.desc 1.Execute having("SALARY == 1.2") + * 2.Query data + */ + it('testHaving006', 0, async () => { + console.log(TAG + "************* testHaving006 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having("SALARY == 1.2"); + let resultSet:relationalStore.ResultSet = rdbStore?.querySync(predicates) as relationalStore.ResultSet; + expect(false).assertEqual(resultSet.goToFirstRow()); + resultSet.getRow(); + console.log(TAG + " testHaving006 having success"); + resultSet.close(); + expect(true).assertFail(); + } catch (e) { + console.error(TAG + " testHaving006 having failed. " + e.msg + e.code); + expect(e.code == 14800021).assertTrue(); + } + console.log(TAG + "************* testHaving006 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_007 + * @tc.name When there are placeholders in the test condition statement, passing in an ARG that does not match the + * number of placeholders. + * @tc.desc 1.Execute having(total > ? AND count >= ?", [5000]) + * 2.Query data + */ + it('testHaving007', 0, async () => { + console.log(TAG + "************* testHaving007 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having("total > ? AND count >= ?"); + let resultSet:relationalStore.ResultSet = + await rdbStore?.querySync(predicates, ["customer_id", "COUNT(*) AS count", "SUM(amount) AS total"]) as relationalStore.ResultSet; + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + console.log(TAG + " testHaving007 having success"); + } catch (e) { + console.error(TAG + " testHaving007 having failed " + e); + expect(true).assertFail(); + } + console.log(TAG + "************* testHaving007 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_008 + * @tc.name Call 'having' when 'group by' is missing. + * @tc.desc Execute having(total > ? AND count >= ?", [5000, 3]) + */ + it('testHaving008', 0, async () => { + console.log(TAG + "************* testHaving008 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.having("total > ? AND count >= ?", [5000, 3]); + console.log(TAG + " testHaving008 having success"); + expect(true).assertFail(); + } catch (e) { + console.error(TAG + " testHaving008 having failed" + e); + expect(e.code == 14800001).assertTrue(); + } + console.log(TAG + "************* testHaving008 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_009 + * @tc.name Test using placeholder scenarios. + * @tc.desc 1.Execute having(total > ? AND count >= ?", [5000, 3]) + * 2.Query data + */ + it('testHaving009', 0, async () => { + console.log(TAG + "************* testHaving009 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having("total > ? AND count >= ?", [5000, 3]); + let resultSet:relationalStore.ResultSet = + rdbStore?.querySync(predicates, ["customer_id", "COUNT(*) AS count", "SUM(amount) AS total"]) as relationalStore.ResultSet; + console.info(TAG + 'testHaving009 rowCount ' + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToNextRow()); + let row:relationalStore.ValuesBucket = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving009 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(1); + expect(row.total).assertEqual(6500); + expect(true).assertEqual(resultSet.goToNextRow()); + row = resultSet.getRow() as relationalStore.ValuesBucket; + console.info(TAG + 'testHaving009 customer_id ' + row.customer_id + ' total ' + row.total); + expect(row.customer_id).assertEqual(3); + expect(row.total).assertEqual(7000); + resultSet.close(); + console.log(TAG + " testHaving009 having success"); + } catch (e) { + console.error(TAG + " testHaving009 having failed" + e); + expect(true).assertFail(); + } + console.log(TAG + "************* testHaving009 end *************"); + }); + + /** + * @tc.number SUB_DDM_AppDataFWK_ETSRDB_Predicates_010 + * @tc.name Test using placeholder scenarios. + * @tc.desc Multi threaded testing + */ + it('testHaving010', 0, async (done:Function) => { + console.log(TAG + "************* testHaving010 start *************"); + try { + let predicates = new relationalStore.RdbPredicates("orders"); + predicates.groupBy(["customer_id"]); + predicates.having("total > ? AND count >= ?", [5000, 3]); + let count:number = 200; + for (let i = 0; i <= count; ++i) { + rdbStore?.query(predicates, ["customer_id", "COUNT(*) AS count", "SUM(amount) AS total"]) + .then((resultSet:relationalStore.ResultSet)=>{ + expect(2).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToNextRow()); + let row:relationalStore.ValuesBucket = resultSet.getRow() as relationalStore.ValuesBucket; + expect(row.customer_id).assertEqual(1); + expect(row.total).assertEqual(6500); + expect(true).assertEqual(resultSet.goToNextRow()); + row = resultSet.getRow() as relationalStore.ValuesBucket; + expect(row.customer_id).assertEqual(3); + expect(row.total).assertEqual(7000); + resultSet.close(); + count--; + if (count == 0) { + done(); + } + }).catch((e:BusinessError)=>{ + console.error(TAG + " testHaving010 having failed query: " + e); + done(); + expect(true).assertFail(); + }); + } + console.log(TAG + " testHaving010 having success"); + } catch (e) { + console.error(TAG + " testHaving010 having failed: " + e); + done(); + expect(true).assertFail(); + } + console.log(TAG + "************* testHaving010 end *************"); + }); + + console.log(TAG + "*************Unit Test End*************"); + }) +} diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreRekeyEts.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreRekeyEts.test.ets new file mode 100644 index 00000000..d67650b3 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreRekeyEts.test.ets @@ -0,0 +1,862 @@ +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; +import data_relationalStore from '@ohos.data.relationalStore' + +const TAG = "[RDB_REKEY_TEST]"; +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; + +export default function RdbstoreRekeysEtsTest() { + describe('rdbstoreRekeyEtsTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll'); + }); + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + }); + afterEach(async () => { + console.info(TAG + 'afterEach'); + }); + afterAll(async () => { + console.info(TAG + 'afterAll'); + }); + + console.log(TAG + "*************Unit Test Begin*************"); + /** + * @tc.number testRekey + * @tc.name testRekey0001 + * @tc.desc invalid parameters test + */ + it('testRekey0001', 0, async () => { + console.log(TAG + "************* testRekey0001 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testCrypt0001.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + iterationCount: -1, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect("14800001").assertEqual(e.code); + console.log(TAG + "************* testRekey0001 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0002 + * @tc.desc invalid parameters test + */ + it('testRekey0002', 0, async () => { + console.log(TAG + "************* testRekey0002 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0002.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + encryptionAlgo: -1, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect("14800001").assertEqual(e.code); + console.log(TAG + "************* testRekey0002 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0003 + * @tc.desc invalid parameters test + */ + it('testRekey0003', 0, async () => { + console.log(TAG + "************* testRekey0003 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0003.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + hmacAlgo: -1, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect("14800001").assertEqual(e.code); + console.log(TAG + "************* testRekey0003 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0004 + * @tc.desc invalid parameters test + */ + it('testRekey0004', 0, async () => { + console.log(TAG + "************* testRekey0004 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0004.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + kdfAlgo: -1, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect("14800001").assertEqual(e.code); + console.log(TAG + "************* testRekey0004 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0005 + * @tc.desc invalid parameters test + */ + it('testRekey0005', 0, async () => { + console.log(TAG + "************* testRekey0005 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0005.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + cryptoPageSize: -1, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect("14800001").assertEqual(e.code); + console.log(TAG + "************* testRekey0005 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0006 + * @tc.desc non-encrypted database rekey test + */ + it('testRekey0006', 0, async () => { + console.log(TAG + "************* testRekey0006 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0006.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0006 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0007 + * @tc.desc exception iterationCount test + */ + it('testRekey0007', 0, async () => { + console.log(TAG + "************* testRekey0007 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0007.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + iterationCount: 500, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0007 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0008 + * @tc.desc exception encryptionAlgo test + */ + it('testRekey0008', 0, async () => { + console.log(TAG + "************* testRekey0008 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0008.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + encryptionAlgo: 1, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0008 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0009 + * @tc.desc exception hmacAlgo test + */ + it('testRekey0009', 0, async () => { + console.log(TAG + "************* testRekey0009 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0009.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + hmacAlgo: 2, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0009 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0010 + * @tc.desc exception kdfAlgo test + */ + it('testRekey0010', 0, async () => { + console.log(TAG + "************* testRekey0010 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0010.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + kdfAlgo: 2, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0010 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0011 + * @tc.desc exception cryptoPageSize test + */ + it('testRekey0011', 0, async () => { + console.log(TAG + "************* testRekey0011 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0011.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + cryptoPageSize: 2048, + }; + + try { + await rdbStore.rekey(cryptoParam); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0011 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0012 + * @tc.desc custom encrypt rekey test + */ + it('testRekey0012', 0, async () => { + console.log(TAG + "************* testRekey0012 start *************"); + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([1, 2, 3, 4, 5, 6]), + }; + + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0012.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + cryptoParam: cryptoParam, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + await rdbStore.executeSql(CREATE_TABLE_TEST); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([6, 5, 4, 3, 2, 1]), + }; + + try { + await rdbStore.rekey(cryptoParam1); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: data_relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket); + const valueBucket1: data_relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 19, + "salary": 200.5, + "blobType": u8, + } + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("NAME", "zhangsan"); + await rdbStore.update(valueBucket1, predicates) + await rdbStore.delete(predicates); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(false).assertTrue(); + console.log(TAG + "************* testRekey0012 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0013 + * @tc.desc custom encrypt rekey test + */ + it('testRekey0013', 0, async () => { + console.log(TAG + "************* testRekey0013 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0013.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([6, 5, 4, 3, 2, 1]), + }; + + try { + await rdbStore.rekey(cryptoParam1); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0013 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0014 + * @tc.desc rekey test + */ + it('testRekey0014', 0, async () => { + console.log(TAG + "************* testRekey0014 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0014.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + await rdbStore.executeSql(CREATE_TABLE_TEST); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + }; + + try { + await rdbStore.rekey(cryptoParam1); + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: data_relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket); + const valueBucket1: data_relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 19, + "salary": 200.5, + "blobType": u8, + } + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("NAME", "zhangsan"); + await rdbStore.update(valueBucket1, predicates) + await rdbStore.delete(predicates); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(false).assertTrue(); + console.log(TAG + "************* testRekey0014 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0015 + * @tc.desc rekey test + */ + it('testRekey0015', 0, async () => { + console.log(TAG + "************* testRekey0015 start *************"); + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([6, 5, 4, 3, 2, 1]), + }; + + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0015.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + cryptoParam: cryptoParam, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + }; + + try { + await rdbStore.rekey(cryptoParam1); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0015 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0016 + * @tc.desc transaction rekey test + */ + it('testRekey0016', 0, async () => { + console.log(TAG + "************* testRekey0016 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0016.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let SQL_CREATE_TABLE = + 'CREATE TABLE IF NOT EXISTS employee (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER)'; + await rdbStore.executeSql(SQL_CREATE_TABLE); + + let transaction = await rdbStore?.createTransaction({ + transactionType: data_relationalStore.TransactionType.DEFERRED + }); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + }; + + try { + const valueBucket: data_relationalStore.ValuesBucket = { + "id": 1, + "name": "lisi", + "age": 18, + } + await transaction.insert("employee", valueBucket) + await rdbStore.rekey(cryptoParam1); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(14800015)); + console.log(TAG + "************* testRekey0016 end *************"); + } + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0017 + * @tc.desc transaction rekey test + */ + it('testRekey0017', 0, async () => { + console.log(TAG + "************* testRekey0017 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0017.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let SQL_CREATE_TABLE = + 'CREATE TABLE IF NOT EXISTS employee (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER)'; + await rdbStore.executeSql(SQL_CREATE_TABLE); + + let transaction = await rdbStore?.createTransaction({ + transactionType: data_relationalStore.TransactionType.EXCLUSIVE + }); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + }; + + try { + const valueBucket: data_relationalStore.ValuesBucket = { + "id": 1, + "name": "lisi", + "age": 18, + } + await transaction.insert("employee", valueBucket) + await rdbStore.rekey(cryptoParam1); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(14800015)); + console.log(TAG + "************* testRekey0017 end *************"); + } + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0018 + * @tc.desc other parameters rekey test + */ + it('testRekey0018', 0, async () => { + console.log(TAG + "************* testRekey0018 start *************"); + let storeConfig : data_relationalStore.StoreConfig= { + name: "testRekey0018.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + try { + await rdbStore.rekey(undefined); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(false).assertTrue(); + console.log(TAG + "************* testRekey0018 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0019 + * @tc.desc other parameters rekey test + */ + it('testRekey0019', 0, async () => { + console.log(TAG + "************* testRekey0019 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0019.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + try { + await rdbStore.rekey(null); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(false).assertTrue(); + console.log(TAG + "************* testRekey0019 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0020 + * @tc.desc other parameters rekey test + */ + it('testRekey0020', 0, async () => { + console.log(TAG + "************* testRekey0020 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0020.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + try { + await rdbStore.rekey(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(false).assertTrue(); + console.log(TAG + "************* testRekey0020 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0021 + * @tc.desc other parameters rekey test + */ + it('testRekey0021', 0, async () => { + console.log(TAG + "************* testRekey0021 start *************"); + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0021.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + await rdbStore.executeSql(CREATE_TABLE_TEST); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array(), + }; + + try { + let u8 = new Uint8Array([1, 2, 3]) + const valueBucket: data_relationalStore.ValuesBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket); + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "zhangsan"); + const resultSet = await rdbStore.query(predicates); + resultSet.goToNextRow(); + await rdbStore.rekey(cryptoParam1); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(14800015)); + console.log(TAG + "************* testRekey0021 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0022 + * @tc.desc exception iterationCount test + */ + it('testRekey0022', 0, async () => { + console.log(TAG + "************* testRekey0022 start *************"); + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([6, 5, 4, 3, 2, 1]), + }; + + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0022.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + cryptoParam: cryptoParam + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([1, 2, 3, 4, 5, 6]), + iterationCount: 500, + }; + + try { + await rdbStore.rekey(cryptoParam1); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0022 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0023 + * @tc.desc exception encryptionAlgo test + */ + it('testRekey0023', 0, async () => { + console.log(TAG + "************* testRekey0023 start *************"); + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([6, 5, 4, 3, 2, 1]), + }; + + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0023.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + cryptoParam: cryptoParam + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([1, 2, 3, 4, 5, 6]), + encryptionAlgo: 1, + }; + + try { + await rdbStore.rekey(cryptoParam1); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0023 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0024 + * @tc.desc exception hmacAlgo test + */ + it('testRekey0024', 0, async () => { + console.log(TAG + "************* testRekey0024 start *************"); + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([6, 5, 4, 3, 2, 1]), + }; + + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0024.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + cryptoParam: cryptoParam + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([1, 2, 3, 4, 5, 6]), + hmacAlgo: 2, + }; + + try { + await rdbStore.rekey(cryptoParam1); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0024 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + + /** + * @tc.number testRekey + * @tc.name testRekey0025 + * @tc.desc exception kdfAlgo test + */ + it('testRekey0025', 0, async () => { + console.log(TAG + "************* testRekey0025 start *************"); + let cryptoParam: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([6, 5, 4, 3, 2, 1]), + }; + + let storeConfig: data_relationalStore.StoreConfig = { + name: "testRekey0025.db", + securityLevel: data_relationalStore.SecurityLevel.S2, + encrypt: true, + cryptoParam: cryptoParam + } + let rdbStore = await data_relationalStore.getRdbStore(globalThis.abilityContext, storeConfig); + + let cryptoParam1: data_relationalStore.CryptoParam = { + encryptionKey: new Uint8Array([1, 2, 3, 4, 5, 6]), + kdfAlgo: 2, + }; + + try { + await rdbStore.rekey(cryptoParam1); + expect().assertFail(); + } catch (e) { + console.log("catch err: failed, err: code=" + e.code + " message=" + e.message); + expect(String(e.code)).assertEqual(String(801)); + console.log(TAG + "************* testRekey0025 end *************"); + } + console.info(TAG + " ************* End*************"); + }); + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreSetLocaleEts.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreSetLocaleEts.test.ets new file mode 100644 index 00000000..ef90ae6d --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreSetLocaleEts.test.ets @@ -0,0 +1,226 @@ + +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level, Size, TestType } from "@ohos/hypium"; +import relationalStore from '@ohos.data.relationalStore'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; + + +const TAG = "[STAGE_RELATIONAL_STORE_JSKITS_TEST]"; +let rdbStore:relationalStore.RdbStore | undefined = undefined; + +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL)"; + +const STORE_CONFIG: relationalStore.StoreConfig = { + name: "rdbStore.db", + securityLevel: relationalStore.SecurityLevel.S1, +} + +const delegator = AbilityDelegatorRegistry.getAbilityDelegator(); +const context = delegator.getAppContext().getApplicationContext(); + + +export default function SetLocaleEtsTest() { + describe('SetLocaleEtsTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll') + }) + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore != undefined).assertTrue(); + await rdbStore?.executeSql(CREATE_TABLE_TEST); + const valueBucket: relationalStore.ValuesBucket = { + 'name': '张三', + 'age': 18, + 'salary': 25000, + }; + const valueBucket1: relationalStore.ValuesBucket = { + 'name': '李四', + 'age': 18, + 'salary': 25000, + }; + const valueBucket2: relationalStore.ValuesBucket = { + 'name': '王五', + 'age': 18, + 'salary': 25000, + }; + await rdbStore?.insert('test', valueBucket); + await rdbStore?.insert('test', valueBucket1); + await rdbStore?.insert('test', valueBucket2); + + }) + afterEach(async () => { + console.info(TAG + 'afterEach'); + await relationalStore.deleteRdbStore(context, "rdbStore.db"); + }) + afterAll(async () => { + console.info(TAG + 'afterAll'); + }) + + + /** + * @tc.name Normal case + * @tc.number testRdbStoreSetLocale_0001 + */ + it('testRdbStoreSetLocale_0001', 0, async () => { + console.log(TAG + "************* testRdbStoreSetLocale_0001 start *************"); + try { + await rdbStore?.setLocale("zh"); + let resultSet = await rdbStore?.querySql("select * from test order by name collate LOCALES") + resultSet?.goToNextRow() + + expect('李四').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + resultSet?.goToNextRow() + expect('王五').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + resultSet?.goToNextRow() + expect('张三').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + } catch (e) { + console.error(`message is ${e.message} code ${e.code}`); + expect().assertFail(); + } + console.log(TAG + "************* testRdbStoreSetLocale_0001 end *************"); + }) + + /** + * @tc.name Abnormal case + * @tc.number testRdbStoreSetLocale_0002 + */ + it('testRdbStoreSetLocale_0002', 0, async () => { + console.log(TAG + "************* testRdbStoreSetLocale_0002 start *************"); + try { + await rdbStore?.close(); + await rdbStore?.setLocale("zh"); + } catch (e) { + console.error(`message is ${e.message} code ${e.code}`); + expect(e.code).assertEqual("14800014");; + } + console.log(TAG + "************* testRdbStoreSetLocale_0002 end *************"); + }) + + /** + * @tc.name Abnormal case + * @tc.number testRdbStoreSetLocale_0003 + */ + it('testRdbStoreSetLocale_0003', 0, async () => { + console.log(TAG + "************* testRdbStoreSetLocale_0003 start *************"); + try { + await rdbStore?.setLocale("111"); + } catch (e) { + console.error(`message is ${e.message} code ${e.code}`); + expect(e.code).assertEqual(14800001); + } + console.log(TAG + "************* testRdbStoreSetLocale_0003 end *************"); + }) + + /** + * @tc.name Normal case + * @tc.number testRdbStoreSetLocale_0004 + */ + it('testRdbStoreSetLocale_0004', 0, async () => { + console.log(TAG + "************* testRdbStoreSetLocale_0004 start *************"); + try { + for (let i = 0; i < 10; i++) { + await rdbStore?.querySql("select * from test") + } + await rdbStore?.setLocale("zh"); + let resultSet = await rdbStore?.querySql("select * from test order by name collate LOCALES") + resultSet?.goToNextRow() + + expect('李四').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + resultSet?.goToNextRow() + expect('王五').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + resultSet?.goToNextRow() + expect('张三').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + } catch (e) { + console.error(`message is ${e.message} code ${e.code}`); + expect().assertFail(); + } + console.log(TAG + "************* testRdbStoreSetLocale_0004 end *************"); + }) + + /** + * @tc.name Normal case + * @tc.number testRdbStoreSetLocale_0005 + */ + it('testRdbStoreSetLocale_0005', 0, async () => { + console.log(TAG + "************* testRdbStoreSetLocale_0005 start *************"); + try { + await rdbStore?.setLocale("zh"); + const rdbTrans = await rdbStore?.createTransaction(); + let resultSet = await rdbTrans?.querySql("select * from test order by name collate LOCALES") + console.log(`mmy rowCount ${resultSet?.rowCount}`) + resultSet?.goToNextRow() + expect('李四').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + resultSet?.goToNextRow() + expect('王五').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + resultSet?.goToNextRow() + expect('张三').assertEqual(resultSet?.getString(resultSet.getColumnIndex("name"))); + await rdbTrans?.commit(); + } catch (e) { + console.error(`message is ${e.message} code ${e.code}`); + expect().assertFail(); + } + console.log(TAG + "************* testRdbStoreSetLocale_0005 end *************"); + }) + + /** + * @tc.name Abnormal case + * @tc.number testRdbStoreSetLocale_0006 + */ + it('testRdbStoreSetLocale_0006', 0, async () => { + console.log(TAG + "************* testRdbStoreSetLocale_0006 start *************"); + try { + await rdbStore?.setLocale(""); + } catch (e) { + console.error(`message is ${e.message} code ${e.code}`); + expect(e.code).assertEqual("14800001"); + } + console.log(TAG + "************* testRdbStoreSetLocale_0006 end *************"); + }) + + /** + * @tc.name Abnormal case + * @tc.number testRdbStoreSetLocale_0007 + */ + it('testRdbStoreSetLocale_0007', 0, async () => { + console.log(TAG + "************* testRdbStoreSetLocale_0007 start *************"); + try { + await rdbStore?.setLocale(null); + } catch (e) { + console.error(`message is ${e.message} code ${e.code}`); + expect(e.code).assertEqual("401"); + } + console.log(TAG + "************* testRdbStoreSetLocale_0007 end *************"); + }) + + /** + * @tc.name Abnormal case + * @tc.number testRdbStoreSetLocale_0008 + */ + it('testRdbStoreSetLocale_0008', 0, async () => { + console.log(TAG + "************* testRdbStoreSetLocale_0008 start *************"); + try { + await rdbStore?.setLocale(undefined); + } catch (e) { + console.error(`message is ${e.message} code ${e.code}`); + expect(e.code).assertEqual("401"); + } + console.log(TAG + "************* testRdbStoreSetLocale_0008 end *************"); + }) + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreTransactionJsunit.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreTransactionJsunit.test.ets new file mode 100644 index 00000000..b395ccb6 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RdbstoreTransactionJsunit.test.ets @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2021 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. + */ + +// @ts-nocheck +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' +import data_relationalStore from '@ohos.data.relationalStore' +var context = globalThis.abilityContext; + +const TAG = "[RELATIONAL_STORE_JSKITS_TEST]" +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; + +const STORE_CONFIG = { + name: "TransactionInsertTest.db", + securityLevel: data_relationalStore.SecurityLevel.S1, +} + +var rdbStore = undefined; + +export default function () { + describe('rdbStoreTransactionTest', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll') + rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + }) + + beforeEach(async function () { + console.info(TAG + 'beforeEach') + + }) + + afterEach(async function () { + console.info(TAG + 'afterEach') + await rdbStore.executeSql("DELETE FROM test"); + }) + + afterAll(async function () { + console.info(TAG + 'afterAll') + rdbStore = null + await data_relationalStore.deleteRdbStore(context, "TransactionInsertTest.db"); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.number testRdbTransactionInsert0001 + * @tc.name Normal test case of transactions, insert a row of data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute commit + * 4.Query data + */ + it('testRdbTransactionInsert0001', 0, async function (done) { + console.log(TAG + "************* testRdbStoreInsert0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + try { + rdbStore.beginTransaction() + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket) + + rdbStore.commit() + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates) + console.log(TAG + "testRdbTransactionInsert0001 result count " + resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) + resultSet.close() + } catch (e) { + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testRdbTransactionInsert0001 failed"); + } + done() + console.log(TAG + "************* testRdbTransactionInsert0001 end *************"); + }) + + /** + * @tc.number testRdbTransactionInsert0002 + * @tc.name Normal test case of transaction, insert three rows of data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute commit + * 4.Query data + */ + it('testRdbTransactionInsert0002', 0, async function (done) { + console.log(TAG + "************* testRdbStoreInsert0002 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + try { + rdbStore.beginTransaction() + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket) + + const valueBucket1 = { + "name": "zhangsan", + "age": 20, + "salary": 9.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket1) + + + const valueBucket2 = { + "name": "wangwu", + "age": 16, + "salary": 99, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket2) + + rdbStore.commit() + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates) + expect(3).assertEqual(resultSet.rowCount) + resultSet.close() + } catch (e) { + expect(null).assertFail() + console.log(TAG + "testRdbTransactionInsert0002 failed"); + } + done() + console.log(TAG + "************* testRdbTransactionInsert0002 end *************"); + }) + + + /** + * @tc.number testRdbTransactionInsert0003 + * @tc.name Normal test case of transaction, query data before commit + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Query data (expect 0 row) + * 4.Insert data + * 5.Execute commit + */ + it('testRdbTransactionInsert0003', 0, async function (done) { + console.log(TAG + "************* testRdbTransactionInsert0003 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + try { + rdbStore.beginTransaction() + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket) + + const valueBucket1 = { + "name": "zhangsan", + "age": 20, + "salary": 9.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket1) + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates) + expect(0).assertEqual(resultSet.rowCount) + resultSet.close() + const valueBucket2 = { + "name": "wangwu", + "age": 16, + "salary": 99, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket2) + + rdbStore.commit() + } catch (e) { + expect(null).assertFail() + console.log(TAG + "testRdbTransactionInsert0003 failed"); + } + done() + console.log(TAG + "************* testRdbTransactionInsert0003 end *************"); + }) + + /** + * @tc.number testRdbTransactionInsert0004 + * @tc.name Abnormal test case of transaction insert, if catch exception then rollback + * @tc.desc 1.Execute beginTransaction + * 2.Insert data (primary key conflict) + * 3.Execute rollBack + * 4.Query data + */ + it('testRdbTransactionRollBack0001', 0, async function (done) { + console.log(TAG + "************* testRdbTransactionRollBack0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + try { + rdbStore.beginTransaction() + const valueBucket = { + "id": 1, + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket) + await rdbStore.insert("test", valueBucket) + + rdbStore.commit() + } catch (e) { + rdbStore.rollBack() + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates) + console.log(TAG + "testRdbTransactionRollBack0001 result count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount) + resultSet.close() + } + done() + console.log(TAG + "************* testRdbTransactionRollBack0001 end *************"); + }) + + /** + * @tc.number testRdbTransactionInsert0005 + * @tc.name Normal test case of transaction, begin transactions within a transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute beginTransaction + * 4.Insert data + * 5.Execute rollBack + * 6.Insert data + * 7.Execute commit + * 8.Query data + */ + it('testRdbTransactionMulti0003', 0, async function (done) { + console.log(TAG + "************* testRdbTransactionMulti0003 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + try { + rdbStore.beginTransaction() + const valueBucket = { + "id": 1, + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket); + + rdbStore.beginTransaction() + const valueBucket1 = { + "name": "zhangsan", + "age": 20, + "salary": 220.5, + "blobType": u8, + } + await rdbStore.insert("test", valueBucket1) + + rdbStore.rollBack() + + await rdbStore.insert("test", valueBucket) + rdbStore.commit() + + let predicates = new data_relationalStore.RdbPredicates("test"); + let ret = await rdbStore.query(predicates) + expect(1).assertEqual(ret.rowCount) + ret.close() + } catch (e) { + rdbStore.rollBack() + console.log(TAG + "testRdbTransactionMulti0003 rollback ***** "); + } + done() + console.log(TAG + "************* testRdbTransactionMulti0003 end *************"); + }) + + /** + * @tc.number testRdbTransactionSetVersion001 + * @tc.name Normal test case of transaction, GetVersion before transaction submission + * @tc.desc 1.Execute beginTransaction + * 2.setVersion + * 3.GetVersion + * 4.commit + */ + it('testRdbTransactionSetVersion001', 0, async function (done) { + console.log(TAG + "************* testRdbTransactionSetVersion001 start *************"); + try { + rdbStore.beginTransaction() + let version:number = rdbStore.version; + rdbStore.version = version + 1; + expect(rdbStore.version).assertEqual(version + 1); + rdbStore.commit() + } catch (e) { + rdbStore.rollBack(); + expect().assertFail(); + console.log(TAG + "testRdbTransactionSetVersion001 rollback ***** " + e); + } + done() + console.log(TAG + "************* testRdbTransactionSetVersion001 end *************"); + }) + + /** + * @tc.number testRdbTransactionSetVersion002 + * @tc.name Normal test case of transaction, query version after transaction submission + * @tc.desc 1.Execute beginTransaction + * 2.setVersion + * 3.commit + * 4.GetVersion + */ + it('testRdbTransactionSetVersion002', 0, async function (done) { + console.log(TAG + "************* testRdbTransactionSetVersion002 start *************"); + try { + rdbStore.beginTransaction(); + let version:number = rdbStore.version; + rdbStore.version = version + 1; + rdbStore.commit(); + expect(rdbStore.version).assertEqual(version + 1); + } catch (e) { + rdbStore.rollBack() + expect().assertFail(); + console.log(TAG + "testRdbTransactionSetVersion002 rollback ***** " + e); + } + done() + console.log(TAG + "************* testRdbTransactionSetVersion002 end *************"); + }) + + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/ets/test/RelationalStoreEtsTest.test.ets b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RelationalStoreEtsTest.test.ets new file mode 100644 index 00000000..68a9a2a3 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/ets/test/RelationalStoreEtsTest.test.ets @@ -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. + */ + +// @ts-nocheck +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' +import relationalStore from '@ohos.data.relationalStore' +var context = globalThis.abilityContext; +const TAG = "[ttt]" +const STORE_CONFIG: relationalStore.StoreConfig = { + name: "RdbTest.db", + securityLevel: relationalStore.SecurityLevel.S3 +}; +const CREATE_TABLE_TEST = + "CREATE TABLE IF NOT EXISTS EMPLOYEE (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB, float32 floatvector(128))"; + +let store: relationalStore.RdbStore | undefined = undefined; + +export default function RelationalStoreEtsTest() { + describe('relationalStoreEtsTest', () => { + beforeAll(async () => { + console.info(TAG + 'beforeAll'); + }); + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + try { + store = await relationalStore.getRdbStore(context, STORE_CONFIG) + console.info(TAG + 'Get RdbStore successfully.'); + (store as relationalStore.RdbStore).executeSql(CREATE_TABLE_TEST); + } catch (err) { + console.error(TAG + `Get RdbStore failed, code is ${err.code},message is ${err.message}`); + } + + }); + afterEach(async () => { + console.info(TAG + 'afterEach'); + store = undefined; + await relationalStore.deleteRdbStore(context, "RdbTest.db"); + }); + afterAll(async () => { + console.info(TAG + 'afterAll'); + }); + console.info(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.name testRdbStoreGetvalueEtstest0100 + * @tc.number SUB_DistributedData_RelationalStore_SDK_getValueEtsAPI16Test_0200 + * @tc.desc RelationalStore getValue test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 2 + */ + it('testRdbStoreGetvalueEtstest0100', 0, async (done: Function) => { + console.info(TAG + "************* testRdbStoreGetvalueEtstest0100 start *************"); + let float32Array = new Float32Array(); + const valueBucket: relationalStore.ValuesBucket = { + "name": "zhangsan", + "float32":float32Array, + }; + try { + let rowId = await (store as relationalStore.RdbStore).insert("EMPLOYEE", valueBucket) + console.info(TAG + `Insert is successful, val = ${rowId}`); + let resultSet: relationalStore.ResultSet | undefined = undefined; + let predicates = new relationalStore.RdbPredicates("EMPLOYEE"); + let result = await (store as relationalStore.RdbStore).query(predicates) + resultSet = result; + console.info(TAG + `rowCount = ${resultSet.rowCount}`); + expect((resultSet as relationalStore.ResultSet).goToFirstRow()).assertTrue(); + console.info(TAG + `Index = ${(resultSet as relationalStore.ResultSet).getColumnIndex("float32")}`); + const codes = (resultSet as relationalStore.ResultSet).getValue((resultSet as relationalStore.ResultSet).getColumnIndex("float32")); + console.info(TAG + "codes:" + codes) + expect(codes).assertInstanceOf("Float32Array"); + const row = (resultSet as relationalStore.ResultSet).getRow(); + console.info(TAG + "row.float32:" + JSON.stringify(row.float32)); + expect(row.float32).assertInstanceOf("Float32Array"); + resultSet = undefined; + done() + } catch (err) { + console.error(TAG + `Insert is failed, code is ${err.code},message is ${err.message}`); + expect().assertFail() + } + console.info(TAG + "************* testRdbStoreGetvalueEtstest0100 end *************"); + }); + console.info(TAG + " *************Unit Test End*************"); + }) +} diff --git a/relational_store/test/ets/relational_store/entry/src/main/module.json b/relational_store/test/ets/relational_store/entry/src/main/module.json new file mode 100644 index 00000000..ddcf38c5 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/module.json @@ -0,0 +1,74 @@ +{ + "module": { + "name": "testModule", + "type": "entry", + "srcEntrance": "./ets/Application/AbilityStage.ts", + "description": "$string:testModule_entry_dsc", + "mainElement": "com.example.myapplication.MainAbility", + "deviceTypes": [ + "default", + "tablet", + "2in1", + "phone" + ], + "deliveryWithInstall": true, + "installationFree": false, + "uiSyntax": "ets", + "pages": "$profile:main_pages", + "metadata": [ + { + "name": "ArkTSPartialUpdate", + "value": "false" + }, + { + "name": "MetaData1", + "value": "MetaDataValue", + "resource": "$profile:shortcuts_config" + } + ], + "abilities": [ + { + "name": "com.example.myapplication.MainAbility", + "srcEntrance": "./ets/MainAbility/MainAbility.ts", + "description": "$string:testModule_entry_main", + "icon": "$media:icon", + "label": "$string:entry_label", + "visible": true, + "launchType": "singleton", + "orientation": "portrait", + "skills": [ + { + "actions": [ + "action.system.home" + ], + "entities": [ + "entity.system.home" + ] + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.GET_BUNDLE_INFO", + "reason": "$string:permission_reason", + "usedScene": { + "abilities": [ + "MainAbility" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.READ_CALENDAR", + "reason": "$string:permission_reason", + "usedScene": { + "abilities": [ + "MainAbility" + ], + "when": "inuse" + } + } + ] + } +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/resources/base/element/string.json b/relational_store/test/ets/relational_store/entry/src/main/resources/base/element/string.json new file mode 100644 index 00000000..a4e9ba5b --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/resources/base/element/string.json @@ -0,0 +1,44 @@ +{ + "string": [ + { + "name": "testModule_entry_dsc", + "value": "i am an entry for testModule" + }, + { + "name": "testModule_entry_main", + "value": "the testModule entry ability" + }, + { + "name": "entry_label", + "value": "ActsContextTest" + }, + { + "name": "form_description", + "value": "my form" + }, + { + "name": "serviceability_description", + "value": "my whether" + }, + { + "name": "description_application", + "value": "demo for test" + }, + { + "name": "app_name", + "value": "Demo" + }, + { + "name": "form_FormAbility_desc", + "value": "form_description" + }, + { + "name": "form_FormAbility_label", + "value": "form_label" + }, + { + "name": "permission_reason", + "value": "Need permission" + } + ] +} diff --git a/relational_store/test/ets/relational_store/entry/src/main/resources/base/media/icon.png b/relational_store/test/ets/relational_store/entry/src/main/resources/base/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..474a55588fd7216113dd42073aadf254d4dba023 GIT binary patch literal 15458 zcmV-oJe|XdP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXfJNHRMK~#8N)t$?W zZ`*d)f6uD@IOn2&LJ;lP6@!gHh#>Y1!r&0HL_gDqb&`3X(Z=GaQp8SP` z92In5!tr>lHv4nxKS1{J@p1P!+F4$_JksuYcRrnVr_*tFKEi|jF}%m8r`_Y_l6p^% z@+LnCznqL`mDBrry9$FzRWuxkQF=}GpwhbiR|yW zmfjQNx4tFelhpeM=s1qPZ}7VBtuHUqIh+_+IvN7$>(jXIa?55SEAd6rfw_FG^Ciq> zUAOb*d;6XH7UwzzrTnE1QtLJmPK4||=GS#JMbf8dX;2o^T+5qYx7QF%t86tY^M!6V zrngTY z1udv}ju^g5nNRXGgh*Bp3Mrd$sWa|p#az3e^Glh~4OYDwx?a*KW72*IFc`5a72{iM zp*N~%>#A7GyQ5CGc@5sreOI4Vr-jh46-ty$UgtlNS4u^>BKcJpW(i@*S9!$UCqmcd z(U6LQxPK-@LYcI@ROQlUqYfv9)@pP1D z^PGd_#Bn=j?h;(A2YP*^zO{q!-impmO*sshM)pxC{aRnxpLI$OVz(ElViw;?d~N$q$^VbIP>sa0q0)N~6iq!!fI>IcRGDdADCq?$^K61=g>C{IY# z;~=ksR37V9Yzp%@sRJ8ebxt7()agtNj zFX-#JY(~NHNecrS7DT}|J>yQfr$J*Ww>;PMMSj|?ifs>m;mOpS;hB2QJtAw(Aw2S_ zSHe`NtQeUBZN(O=rgRoV{J5F+Ft*YQkw zwtwkXsI}a&=y|SSZxEX3H8VG5pvDb*DypGrx7RHOJ0i^ra2-P!NRFO4D{+Ry>|JXL zGjQaB$9omq%IUE9OgQbqtQMtUxwo448OTeE6JEO(GROhuciWZ5BouJ*L~LTeo;4dtD1t#pnhtSi{UW~!N8lsnLV4AB&!P?*BYDt{H& z%&bDsz7IE15kl1~PvI`8P44N?xzRmdc}}725-w90Fdv0S!A0anyY|dSG}_^L&))LF zz4K+fI-yqH>N0 zgo)+iY3)b8AJt+2Z>KNwTQ-d?GjYyuI%!>DNlTFvDiBBa$CrlyNy#r_Sho8!34uL# zRbE+7I??*TrZGd;$+f!%8_B1Sc*Ia#=XozCRDucxF$H^&J+EfrLzkl0 z&Y3P^^vbm_^GJtcTe;>pe{n4!{EtOfLyv17pOHk&6d)QY28Om{l|N|LJYM(9dcX=m z(`(v2zJ^0${=gPYRc@u!raOd&0;{ZWR``si^fg~l4oL?SD>EgWzMqA-<`?rq(W^EZ zVWn$bq5GX_&GgJOY`!oa&@zRZ&4hiDHmw<(Mk_N)4(+wilna`8P6Sjw)OS?{y0(N(0*);t@8SAl~B`A^+@J zV1RVu>FKY$>KaP3uj?dg$oKga*<{6RD1b)fODgTiZOJR>{Kkeu4uk2y#e!oE4iAlB zYL*V8DT~1MLc{NwyHeClv|$!rLwWSf$b4NexAR)uTBgvUvCBJO=sfB6_1wOZtOXTj zc`5k{U1P}t$8tTmwm1Gq57=?FuXc|tkh+fj*LX~;FJx?f%NC4*45f)%IS75<;}ANX z;gHpyj8K*dUZi4hTt8$GpexJ4q}CPXVyW%DV;NflfVk+qu7f_9k z*}8EIodV}*+31PZmwxv(r&~BEn9C$YJ9U6zg!~5>d$_Pa8+ad7I91;c_0IOtEQZJv zWv~YzHgi=b!-mWfXtn|_JkoD5oK-0qxdz=bc;8A)h$8Ki7uj*~)FIoxTCmM)Lkx$^ zDAapMq>9(D*y56Y3)j_pPZhR{lBnF6$6?8nU&c%yomL(4$90sL@mADWR@cgG>br4< zm7f(4kA&8Grlx|Pqa>B}@VHOlNlK;+Bw%8XPl;5YrIxrI!FgaD+MM$T3TD9_g?p$n0Z^z z(ZK~3V;*H`@3>UjK<`U8)$c<0O1ic7Ev6ocyuLu$qCG4Y{bp{Y=5PB;{k{&5MvzIV zqrB@hYXOE@LmvV6T#B|X4dE6jY+>wEAHh2P=EcesGcpX)dv1+PVs{Q^sw4rG+6 zIMNJ)vc{%SR$PJ)BEf_u+O<&U!M5VQ%rC4^x?<;d{RR~!z6NtUq3;)^4s7W1#)j^v zagl`{s8YEpK6_jhO$@_^<2ryqkqSlOyMV|^!)TC@2*LI`^CDdG%EMG3N_}|VeMXsg zreLRr}}fkU0|;F z*7Y@d*Xq264ee>$vQAr(zQG}~k1UIKZbPoo zBq4|^xF`pLiPaELV00X>9O?5D3Lo=a4w3a>7DQFw_SB8SWLAZInMO&pQ4!LSj~YD6 z@OBztL*L8Ob`EK5=<7MJK_T?^rLFqqOeZgHg&A?6PjVts8H}BcoI;mGT&hNI$*O+_n?-TzQ=5&@FU+ z8%JCG;=yD5GrXl(p=k!g0{xS2uj3r!y6+pk&uJG6J=Xz^8H=fHEN`Geyfj0EZ=)FZ zy@n~1956HJK-yv(s;r3#B|r&&i8b$4=&<8A?%_Ig;+gcpy^8a?q58J3buP@kLYeB# zuvJF4c@1BKR_u&3Y};O=+1J~;*T6d6N2fErzRvXb@UVNhXB&bjsk}B6yjIvbbueQP zP_b352q{pB@qe)PPPC;?V+3uRSYKh6Wh-G{U!Yyu2MUFQ#d`*N-+5JeEfd?K^}L)s zf!p!b7#;VQb6lcB|I})~eU0;~5--2s&h1c7E$a&)Ds*<-L~vtY9Bo zkapu+;9@BYMXVY#B)(0sTH}^k>s8%(pgI{Xf(haf_V8hgi`#C?Ct4y|0|!+}!f3DH z+7lPAq<`@md>3KNVE+qD(Zi^+g|6Fue3yRaI^D*%0Okp7ODn37mjONA%=wvO%5xVQ zTLN#vEcl-WuJzOXZ*iUv#jn9!=WG1ER=&-j$2yn2*1lnGH$&%rZA`Dxw@t4VG%`~H zf9Y}|9;`TQTK9mS3;I0H&4~Yo49$KP^r%W)`Y{~?48zu$u*+BI`E4V#7j8e-FPMdy zlv}aA@EU9d+kG}};U%9{-@sDA#eUW{uhD8bEb>B1V&8Xp-q{fYW8z=#H*jr$*E;_$ z@M<5gC_cd5Lp9u}jyf=BwmQi6V+=lfOKvJ=X!Iyx9EQ#c)`b4 zKvDGyx4pWr^=v#+VuYs=Vk6@e7u4d1!Kpb%RZKw6E3Qj(?^v^!=Q7Om@wg(g?zN8j&sMIKz9iV4 zc4x~y!k!I8Fuzx!iz65Z7T|G~b`%6DdXCfb5(*ml-~nmlifY7JlTJMQPa*T6b2Jn|a6Da6sHJDjm$zW)COz7Nma z@m_;#<#XO^G&--#XB5;;-!C3HD{Omx?S7m8{~l__aQ@jdxtjJ|GzXroXKu&PLYf6O zL+8I%{xz6AQnDcGd_$FMLthRI;Udw+8<#Aotm2N-r zn4jnMT(+Iln*YY{3tt;|=YLVISAuh&+d6O2oXfmkV-9ew;oRt2c{B3U2;nXGKJ=PL z+kCBE*O}|i*TS`N3fp=@=WX+a*XUe>ZQUNzwfq_SemU6@Yx6j~5$H6 zu;u5q_CIgf^3gE!x&`ZZ`D@tq7DaaE&kp4gtA`ZK9SgCgo-bd)9K39^W)8b2Ztif?dvTxo*6ccMW}uCEo;sUVl;Jz`QTk8!jk$#usgAFpX;qo!2ti%EoIA zMVkHHp}Jn%HeC1V*ZXeR_Pxc17mAz<8oHy`I-B#ioy<6wZ?7A!-EZ?6s*Jud5+Ofi zIg%24U0|46NB&xI&1(x=cx_w_ua#fptNCrb2GV;C--2uPXMCZ^x#0Uk%@ZZm8Rh{s z-PZ;=LkmNth%>xspLc-rszbie_3ri@yg8q_KP}()(Q~#Qp0=~MZm{Ry`TmPM=t#Hu zU489s=>2TBdoiZ(0o@KhSeOi}UO~Y%z6~{qQjicKF%WU@&%XNl>2bmm0DGU|9UYQJ zIt}Xefv!Av8x{BN=Cu2Gd$W6gd)&P{lSi}qb$lsPMF`*5ShqX{&_quc4bAJjc<3)rwKDgfRl=YcS(%!j2KHR5(iWb-9aNb?G8LMhadSeDH|Knt=S;nP8H(1& zN0fWH?9K@C{rR-JHUE6v-J*beX^Zyjd}Ckm_f&JNh4UUTNPeCzQt$ckVfXZSzuQ0F z?M}PP?%nZu_k;K6-M6U5)#_s_`j&(uhmE4I^64=5C9bsBI*N}K zw?J1f&}WF>1^N|_l7A5nA3*ZB4$aOKR8BM8isEME=#g#m6;6TbY37x^mW zNFDJ8A-+5BP?n+ZxO@NZu=@ypxZMvV|NN9X@6h&p@CH}PH}L3Hpz z&-EizlqsKw{Ud!pVH_A1bZ*ZY%=kzmdCjL3TR;Ux|Laio?6+n1U0|;JU3!VK27hn$ zvH!)t`Y)fYsGw9{#|fW6=j6i_!N{-zRd9lBtmA9`2@{mm&%C&!9Tt*Q4>++32{U+v zB%SljvqQa3kjcDxE;SV7k9_>u-sgLNNQ77V%WB%@)e}ick3Qwuc`$P!%F}4{?pqXQ zG-%rWD=>c&7=`;wvE)M~E>v|}XfxQpvzf7nK;_d>mvJ|I*}mlUni3KXg*>TQ;Wa+C zP`sf(U*pK5AL`ijs3n63tQnb9xEsH3uNR(H3-O33t3(M!Ies$K*BOeD`ZQ?gt5E94 zLr~XIkGbqlq&LS-@gUL@DQbkt&*=VvP)WEX_2vC+H%P@33eYf`p9-<03Y$FjbI|iZ z4eSPtcQT%AS!knA)wFV5&_dJibO!Tg{66qj{jJhoGlZt$TP)ltSZ@3d)&T)4WbmLs zQ9@TnE!@|KAJPCZs6;;ndgeY$eg$iZ`BAPm9E(X=0-^nhC2|_z%``IH=}`&EdlkoA zy1zuh@0ssz4-dOr^Pf@f<@0X$@CiBedVLOFdCy#x#TG*7fZRPb3MQM-7R0^ zIAS!<`Ito5u8`=*;L(jC@)OF6Dv_#f_5S=Mn=#qfE%V|5Bd`w_4ld@@fc5>3!5`i| zjxS2qn8pZ7QSjG-;%;2qRt}9&UQg?Wt1#$YF^X!l%Cw;BH$B_UZMXe&YvfrLoi94# z4f!&pF?A@XeuG#9wA?J^VE%@7?{LhI?^wv(x=3+RgSCrzkQRTU&XKyu=L_u^u!DxF zClztw8qaw~F=9Q{M+x*HPbWQ)MURo;MCiSRt_z~~w~xDT-|u#R_lJ~bkhZr?L(h4vO)QenY#q;#a8k38h2fY2B{L6z2Ir%cc(bpF`eBC1}zo5tV zI+VvX%5*{vC<^%JS)?IE*KY)t_ zR*T>b!uY_F@jXg>cSgJ}He5gu3f-Tn+?(tf*)O`$_ZqxmrJAh)p7)M2Qw8ka?o1oE z3wn)VzC?=B481U_K;_AK^PaGrh=Cjwf;=5rpxvGf_0WQcY&(WmM)A0=3UW?#zR%Cw zAwUmR$55|!6K+c(j(Zk<(Rv#jS|M+>|E}=0Hr>y`c}T&l2sh9yYiP}im3G-yAXL%$ z&N>R~9oCI5m*w&{{bBdb$K&qXZ*F!UKim>3&zbu?r@TebClppzZ(6Iu ztTLhRH*)S>^|5L1&zRL-lWmH@?+SCtOMZole100m-HU|s&tN`5rWb;toyE#JDARZ) zs39p2w?5AC<=OJN3QDLpt%RWv(g<D^bECi1RPoG4Aau1p0ZiEPC`7 z7}Byu>xh?Z)Gt|(++}OvHD1Wv>}Szz-{0Ud%_n1^LzP142Bl@ai${5sdz6P(pU|?N z<^1b-GF>=l#=}-2Mi6jj{l0fxef|FeX2taNtoY8~qHuUbkXa2Pz&*kdJ?*(+nC=BV zRk?Mcf>)|^agT!AL=On86pJ@q?oi5S6mpM3?h!Z(C-SobrjNTQ>mi|2L?63Hl31ETM82B?t`DXxdR_il|rO35ANsgesKzBF}xG z)tSpwoQfL85d#^*dP1QIhj{YbPXsxwRem4omNA*`GjY}dcJkXN>rul z<$l#NG~r#y0mCE&SE`1}s8(a)+OE2e_e$n%!A$}#c3;4?wk?OouR+s)4b}sLqIY=4 zqQzxph@kWN=OgP>LK0ILgHuz2D^uqg!WF5jPnYh_hR#jy2eT)%je?gR0`__t0N2%C zZ*h+Y(}Z>kVh}#dJbJ{(>e-VT)-G9e-RS)&d{2KWhoq*CHkRFO`C3<0Z^zwynhlbLzWyESf&- z-oJm3m)45avsP0VNI5;imA#fvQS(@Yfuejel4C;VV)vG{FBK2jTDbpoK6fGG9~6Xv z@ZvY=+H+T-d%*9h2+Gp)90RCfx`VmEfL_Uv($2E2!djr6Hbho0vlf`!{j6}U-{x@z zl}g>e^0$9mwNlI7hyyF-sdNWyh%?;zSJOPk^MG8>v6gUy^z+9;voE9q@cHvkvUo9n zh6rE?Osu!12P5`H^V5;px#DUDl9j5x(QuhpDbA4~*M5;wWL@fUwfTru;$x|%6#c12u{xgy;ej~ zAnd5T(9k0>iZe7t-@Ung=esx_j*nwOSJAf~4<2%Qz!0+f_h8d=fTU~zpEFj3Q-{FDp=l%Bf%-+|742%r=bPa8yh&yDAbTV$4Ql$@p(dIdll&zTs(nREi}B!XgNaT+|Tzzd8TRFma?|cb^E%(>x0Ux zeH(KlxL7NLJs^eIt1EC?r1z)<2qX9qLK%XB@mfz6TVd^$Z3K%Ts+D!Fl=J znXrz+d{gg(NcjDLBBNMCZo=(YES-oFj3cXSJuLhv0qDb@s#{K;49(;SEiAz{jY8T7 zE&u7UJzIsiHEQg>XCAJBW!693-=jE|a(O}^G8oYc$ZX72&RZ%(_Dji)4$QeVtH;bw zWdLHAi|J4=1I-ttS0TGXZF{SWmAd!uh@jL6&v3X7%Egy|iarPMu5w*Dv%1Y&dU~!4 zvz%19Kw}&Swn=Vl=u-m}3_RXl7!|X52~ma0d&=!ssAw}om;5}T$0xSjgig26vJehg z)qy$BbXZ!h+XP(3aCSVgUnG=yJwsl$BFRNgyj)>ZS3y?D)e!31#a8n4)+sDHR=v)rE+1GJeN>@z|DFw} zZ!vfu&!mN3N!0@C#~YxZg^=Efnp_!+E~R^c;T(`>LJ#Cup2~IU3{e{n(GVqt8$C&Mbz4y%4(bPNIj; zKSOWyw}dw`>@R@Aw%}oa(7b#XyascA%c1ctnCW)?X+!AMnEJUZXv9eFE&|4@7AEOUf; zBei?;QpYscqQ<3$S79)cacx9#To@(;(n!mQpa(ieI0z3k8R&>BjnR$!gjvvBL67!Y zyp5|^e!(`cky2kG`tdGkTNIwUV%7EC=; zJ)e{|3)+W#P_O!fZY$C$g#Qeu?p-D9+k7gnIFb{+K;FE{i20|kg|$wy19THugnI=A z>xnU!k(Y9a=PvuyqTNaqayjZyJ7aqR(xlPx7yi^=_+i2e<>hq_%jG!t(2mek+4&QT zHUvZ65GRowvU5RGa>#(&c$4#^UaLUOla_)Ve3ai8dr^wz)FVisz~Utf5IvMOX-mEl zAWBkMv<{ysAE^ooP1=Vh=zUUprArm*7`kqZEdr{s)>ZSzzY5%fApcuo0IXEmE3mX3 z(4N`QLotVz>X5U;j}?Cv#R<37h8|=U6dg%9DtkV_MPBhJ^9ZIzT9) z*hcHlUZ;dF-41w}*_(SBDGj~YW;86FKueUjW+kZ_J z)fczpe(-4<>S=7BamfGm`Dyowh4<&IxKTKvcKLCTQZf%7Bqxp1I(-g)t=Ew933^OI zr{)RHi2*(F3JmtsuG`FDdk;5yD|h^bU;Nb{Qr#9{q(h=W3_0BDf&7<8ClLgQd1o$F znkWQzDU+P_@Su33ir}7(iVv<+Zs(wkAcQQ6L}^m)>5`tLH|Bf|7-u`=(I^KOws$VJ zjd=>mJnKo9lnVzLy70P$W}`#~Pn*n-C-UjTr#aG+R7!^;%}^$zKrtzqMKRp~*eX&m zZ$?2w47jC8mx&8O%*c^uRXxm!I^$8{-h&s+ko06qo=%lIfA(+uE_W}%0jNGfT|MVF zkT9U0{cT9{eG?8L42w`(SrszxcvvnIf_V-gYz^Vc`qC*@RTft{EsACEWa|+D7;9l9 zrO+P$Wsswv#{4!y=7IJMaoyxg&Xza3&v%#I|NeYO`ndBCu*EC=l6|M00ok^Y`Wwa75C&bU)X|^(4cbGA z{RgO9SZ>&937TK+t!J->lwQDCUccm86=`{ut$k+9%*_= zQd3ZMl0KCM(~*(OsVUm{mB0Qw7%7zuGlKg(nbq_F%VcI@WJue@A?o589SY;~ufB?DLtP)KdH!i1z3Ro2)J`AVh_tfA*Zs|>nLsuZU1f?T&Ziz@ND zH?FYMy#h^x|MMJHCsBF5KUUEiLOGAuYN0UmD`_OWf7l)WYXO*9(-^0n|J5k z4?f=RzWs2M^T@LvNu`s>@DzojTu`ZxP^)Le)4)8n2VQ*U_i;hbwd#YKo|E7n!4bS}`*<4ol?7`j7&-a+HVn7(mGavG}_} ze_-QJ1m55Hkp`a}obm+0$3YRVzYu=>%=JU|lL>sDiugtV9VX0?TUcHoMmPvBFE4Y= zW$LOR>vE~hk)j|`MUi&-OS*cYb+F#NxlnOquH$w0VQ5zIqSy68^C%;&YZnTxO6w4U zDqx4%#`1`UR)hk~b_nRahP7?wn_|mX!?4@2Qew%-F}nThXr=$nW6ShKD9I~1W7_yk z9yR>YDeio^k2rj~{>}Sa@TMNt-X8H%9|8HxsT1h|WOaqt=2uSwofhK?ri5A+RUNnB z%u`9#gz$@}8Fsm=fzmF35x{rqI-Pq>AKAF*@~0U_6r)^C z31y6~SY1PW@}1r%+V~EuA<>nWMB9Dc+qfLgYZE9>Wj5a8(xQyHniBdsVKZ!JdQT1v zWH3ywLW;uIagjIX9OqUI1g0ZYm=y&FFMr}9FzIVRqfh6$STL#ghE3BhH=HUA@6%4B zBNao7xwqy^1UL9=1<7}VO3;s4_pfs4#w)@hfmC2qyjR;O3Q55`KxOWk! zGBb~(%)GnHwJ&3TW=;ADEq}Uqn%M7td=Kk}KDAqJ?4a}l2Mx0$9?Resi}@N{Gimy= ze8t71ydKckb6&%?t}xdRs^m#fWenC?@2h^L=6{iDI3%qsafUL`rnlle#)i49vGY4^ z6jWx63O-_lbnSE9`lI8{=_;lccwxery@0I`m!31QgcixkNHD{SYF+LpkC;F5f99KR2C#Ur#LZZ;4FUXsdfp3$uk%R z!R#d`;m}~@AcMvb^*h|l!d<%&$sCE?2ba`#LSB>GN9ZG z86mGru+Z_%wlFtVdOeVZ;R&{RbKPt8g>9W{IM?H!<@y@F3E5UK-T~@sUa&F9%J-h@ z&cBAQMW#+??7F7ql`$E_KH9>AkX3CCEL^zNw#cni=2Koi6oHr(7@fy@DAJl17}mX}G77^A=8ACI@@vmHp@RzzX-Y#{Z?qq< z&7bRvgNv#&!>C^oXn58&S4vs+GegsV4Hw0itpr>=W~fBA?n=kXt1l`K%=*A>l*qM? z<$Jz|`dXuJZhP{M;v`lo0qdu8IS9ux@-PpmMNX%3vI>;kfdw?JGSUc)yc~B~CNAw7 zir#C`^|#nZX!aqraytDI5s0OxV?0W)%WbEyg>}5pp0LbSBhN*Z4`@1HgRWO-lq;-o zs?ciHEYu^fQJ10)-STP%FJt(tDBtR4&H8xnRy&Vdd~}kpcnB_z zT-q{_7f4t>9z2LA1do+vj+5++8vQq`uqEijq+vXvd>Dn-wi{?oae?6}Ma&)&A%n_b6hhS(ns%pxit^s9ykF#) zY150JzLy7k?Uv>j!ifT;jyNl(1wTXAQ+RVK3JXnPEcQCx?z0;@Z;Ju>9{iOu=@TbV zuKfcle{&N)7+n2o8P5Oa-~YGB#RU&HqmijD+yac7BeZ+=IBq>$_PV!mS?pKo+<)3e z%n43fQHG-YyB0Zlc^$xZ%^5Pj@3vh72I3bb$oFZ-lW zS!Y}jt*k+_@0wrzWCpwHviu8AaFFh>F?z=!7-Lmg+uC12kAbTqRyPB@Yx)7MjcCzL zIIelrsOFtqesb|l5TepR zqNz_?SGhv0oIEFLA@$a=BxJWD`w&{NwRIgtXsSr_#-Qq&aG$j57Fb^6QOR9bC=;7H zhi}Vmzp<|vm_UutDUJ%H9d8)ktsil&s?jx zW-+X0e3ysa0loN}m;K-QC;u*8SUHM>PPwlNEg`lrvX?=ipD(@^amfk8kMHWiu0M$N zs~vtnN14kaeWcAkkD@fA@|GxErlIXiM#)1c-Ukd#T&C~J2}I}!!hC~f>c?P8IH{j` zrJxibR3BQj|1SLiDqY#Ff^L`v4(M(J=JxrnI;u=LW6)FVuOmy#ZZ(v(|1vbL!Ik1P zO;FG2%iC6@KP~k4Ev{9bk@so;xO;zlv)li@fBx^8vPy|!QD6?l(rS@Xie&;!`1O#$ z(|WfUK0ADPERXc9IX}Jf8BeV`dN1=JiZ%55WvuLnkfm=N2=Ve&)VgN9S4h^fB2*S zm{t*1^Y6!SwE#Vo?o^~5((Txwj*9y;0<{|l?CB5+L~%Y*$@k?@n2PXq3Kg7lLE^ef z5OUh{aEah$K2HorD2>NLTZ2%roF9IYg=FQt*B!E9RaGJq%G7jHFU(t7?VNY$r*gjAb-%-l+KXx zeI9oc39;N8JwJXt@BBdH{0T;dvjY~_sCbRsQCH5l&CVK?{QQ5jdV&W^~B#Xm(fIV9wIXr`^sVtk(r}0v9yWt z?dsdE0?kSZj&Tsd5cg1>k5mU*P^s(Sg$64UMtm$H7u`kl$@#e+c`FT49{HE zIQQ!agbOXZ6;8b9KAcGrMH-{Fb=4ByYS`R3jJpZ(r{roEjFMfNqGmlGZor^PSt ztmp|4($o66U@Ir9RO+1Qq(2CuvhN=5cXxPXg*;FA^&;DVdh(!?&;_#^hV4|QiqY${ zu=-SwZJejAqY(7JwBssglPFq`wY`RNII~&OU@$zIq~E1)$JwE8)kgBe4?P&#k_R_> zRoWy1R6S2t>|1438~Z3T>U-%d;kuy}X#|4To*}|OBtAlH31KLbaT#Wp0f2gv&_6pDLJROKAzruA zrF9|CA$v$1ATP8LZ@g6j5mF7+KAFkMKP#)BxX{8dKHuN(PB*u522I1S{TYId4$weI zF2bZ4<eWjRP5I!zpm_2VZSqUnHo%~8_AkN zw`yec z-0dDE`am`B-K3t6bwI*zy(2{3bVc9tspU6K^2(?~l5LRoL?7qAcwLV-!Y{ zQ9ry#uk8ykl+F zH2dHB(SM+i@;ZM*XvYejUgD8jn(dA-ZJLuA$|4-=NRU)8q&Q#?+w%un08i%y72=$! zcU=gr$zwozmoE|BUG7S0iy#Y5^sC@y*pf&1QGoR>P#sbvjH0z{jqX6^W4%|g9B*8Z z=~=9vt(QK^8zX#$5O0Hi#;75UF{&;U--_u}$gv^@AiYwSWrpHf{d->#Yi$#C8LDZk z0n~wqio}SimeVrBCL;44DL>uz0~a%7I7j;N#b*rOMUK>@?T0c#>o@+DiiC&)$^q@< z>MACRbgr~4PFw^arE6Qy19b-z64db>pS+lrc4UrD_0%4u;DYBTK0tLr#Ga_<%0|J^ zgT!)`k4?aAA_8gZ&`&-_L8gkj__hNVhCJky@M<0F#{2PP2b@C>`RVb{RykN-#T%0I zeAX!;yp)1grEyK8=g0fJmugx5P8h~2UB}|upp|Bm@T^!EQ}~K%H7p&*#f&ew)n``y zA}5hFUYR!+@kTvNnOk2k*NC1FqS0pm8$bF39X||aB{*WX;HotW(&eM5QbKu1mD!?x zuMTH_w`*L-hZ^}VA4_q0C{nr+u zX!;X)j}2>|dd^VcqUK5Rtm7CRxb&p!t0#`fgAX4QMJS3%<-tt8{Dm^xgRLvyLS#U` zio8Vu9|(J%Gxz6b>`x=mXbwyZ@}*(ql}B#m#fJ`2DssqQ3POqgjgt2$k#$V|V2$V6 z{<#fz4bLuqY?smTFMUNmdIKf<-~8SGlI=%ec;mREm@HjRX*f(66cBMz?@ylE&?bsh z@s#R?ew0BbZQ+kp`U46IM6|5~Ez2ZdkB^+RYy~d!Wyw(lOy$cVp#7IeiW&lCzEKw8 zGhArebA>XW(l}@Ks0#88AM#=p=?4tAHNMUh>^}zRVgblcD*zuJeB%NHxA8~7&3F3K zAYd$S$x+vP6FXyZt}- z{r}3!ysV$w#X1$JZl72G@wkTCr@<`VBT++f{`d+4%SsK_oWS!)h$X)7Iw5YwMUI%|DP($<}KZ+-u>XG?b9I5f47B0;%?P3__l;YH& z`92CVO`RCVP#y-H@nJZgr1<2a{xBQ-lIK~pAH?^`km{I01IzdD7@r|t*_4y`9@NA5 zq$<1;c6}R8!%NJeZ{_C?c;3;(Bhvgl9`1TUrhJs+)3eHTVN^Wtf9v1;w`bk-!U80# zPb4Nai`;Q4VyWJmBm(HGVb%x!$o9g(m z@BNm8)L5LW41ks^%nDsO9dc#n{!ihj%?OK8jS5s)q|ox6AsyuMaEws?(61<4>Dl&% z(AowWE}sZbd2$Fpd3X!W{44-|eRU%5z)~*gA?R**Vyu2$E5~BWM~PgBBq$=kqGE67 z`@|=dDkKs@MXyRk(q=Sb__5!7i&kaqd|~>q`yW64akf!;YC=W70<8l5tW13-+~|Y; zkOj7m+O z!5pPf&u5hW8I_=fD zD*;20N{)BIOQ{tj;NRl5w-|ch2}M5c{wK!f>CfqKoBq&WEM66PqkaN5`Y)t8TRI`--F?$f7FyF2*vpx(dgmuRWV_Q&1- Y0jIQKqpXab7ytkO07*qoM6N<$f;yQ2zW@LL literal 0 HcmV?d00001 diff --git a/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/form_config.json b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/form_config.json new file mode 100644 index 00000000..1441277b --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/form_config.json @@ -0,0 +1,5 @@ +{ + "src": [ + "MainAbility/pages/index/index" + ] +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/form_config1.txt b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/form_config1.txt new file mode 100644 index 00000000..2e4f770a --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/form_config1.txt @@ -0,0 +1 @@ +{"src": ["MainAbility/pages/index/index"]} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/invalid.txt b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/invalid.txt new file mode 100644 index 00000000..09c15700 --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/invalid.txt @@ -0,0 +1,3 @@ +{ + "src": [MainAbility/pages/index/index"] +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/main_pages.json b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 00000000..ceb075cd --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "MainAbility/pages/index/index" + ] +} \ No newline at end of file diff --git a/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/shortcuts_config.json b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/shortcuts_config.json new file mode 100644 index 00000000..ceb075cd --- /dev/null +++ b/relational_store/test/ets/relational_store/entry/src/main/resources/base/profile/shortcuts_config.json @@ -0,0 +1,5 @@ +{ + "src": [ + "MainAbility/pages/index/index" + ] +} \ No newline at end of file diff --git a/relational_store/test/js/gdb/unittest/openharmony_sx.p7b b/relational_store/test/ets/relational_store/signature/openharmony_sx.p7b similarity index 50% rename from relational_store/test/js/gdb/unittest/openharmony_sx.p7b rename to relational_store/test/ets/relational_store/signature/openharmony_sx.p7b index 9be1e98fa4c0c28ca997ed660112fa16b194f0f5..2fac054162b97eb332cb3074f30f216db6701d27 100644 GIT binary patch delta 987 zcmZ9LO^6$19L7yHyWOvVMXTZ-Z08_UHk)@QGiwrEtr&SNiun7 zl9}vGQ%WGhQc#O+=)r?fP{czEe)go|N%5kdil=&5ka`d=7QuoVSXjl||M~Ibe|nx@ zpT4zWf@$=FrIqInvIl=eLnp#Fr_s0P=tejc!lPhqY30>}Y)D^-ghODuDEupiZcZ1| zk?G?0C2U_Gx*Z$EklNR=G)8QJEr4wvW6f^OF>$Rse1=Mq$!&_DlA9Q^y_nke^dXkU zx05OI`2;~-dze_0935rVVc$jH=Da3BQ9@?ds#QSnG7BgDBS};mC=33laT#CZ z1E)r0fLck7giOwA@?}#aN`6Iw3T@F=(KpB+|5BU?5bQHHndBr$V(` zy;`(zcB)y8{#1Lb_N?PkqVDFwKsB><&btD{2S z5OLSuA2oG(0F{}u@c61hD@}8#bsA`Pbs;&)6un?LGOY&Ec4^towS28U$d6KXp;R_h z5&AsC4EQ~fOwmweX&JIAgnnHX0+{nuP?QOWWQ9@OaT_Qvw(<;X$W$qdTYx5uyh&T4 z(drQ6b`tecuA`1QS%`yb!FSqTQicNKXZJ>ssOVO?6So^^46O`EvZ$FGN|Glbc|iGD zsc5k^nv}fKSgPgbe>B@0awr$%#=L9BXICQmRcl^8WDonQHTyntN;o<%sE#u)V@vha zm@%|RPOQ^%vGh3%ClVyJjcuZlWu3pgiK&`3=a(?mvTR>(#g6hh3_JhHZ;|wgMF^&$ zo!Qpwv!I5>-#2|B%LO0+N9Hl%1)D}O}~;h zAAOs+Qs`k26k+H^_Mq!w#e?X=dhsOdZ9x=dQEwtBdQcbiuy_#cj_ioX|L=Jo_#d9< z!%M$CJH=-4&dTbG$K3J5c;tNa<}9u*P$e3P;7?=mmDQtTE@CXjqLJlu*lc;_KWpUX zEcP%qi~ad(Vr)2W$F{bt#=uDICGc%*8%u1SVcl*nFus{+42N6Ij_Wxc&G#M!yx`=u zSJpF0VmF!E#mUWtWqVtVmS;E%e>fe+paAl=5 z-EXpspv*{%Cmu_aQ|Ymy2#`OGfQgXT2-w#Krl}9`v1awqp$uf$)<G<+Fn7>OBY5Njq|zJ|Ck$X0#TLp|BA@?EZqndwR0GDM@T=@JE- ziqovo_@qWvRSJfT)2kg=q%HBhB{uzJJ_z@1oJR@`TCgovxU#^oG&rnVZ76G|qj%=B zC30G~_Ng#CX>nl{>j%{yCzf!dkWyRr&W1J=0AeX>#Fm9r76O5W5};KCkP3Jt;~V)N zB>B2EFefc!1)0>OLU{eaR}|MgXq24Zqyb1}hwb~8Gj@mB!@ww(i+nI1G=zzrD}yei zFwYU$y5$!*Ag1ho2Rke`Y9mwse}@=#_Lj5S9LcSEyJH!S(WCmCR+EY1h%S zp?hV1J(j;T+-eyO&vzbGc2TcuZs2;x;M$_3i96Wx-uYz;n?xUe^LJczgv3{{p8lh(cXIX#&zX~kM3)KoP7TAx8&<@ zU{9_*v6$SKS7J-i7>hB{%T9rQer^5tdmb?uzx=KvQsb}GzjN (person)};"; -const DB_NAME = "gdbStorePromise"; -const STORE_CONFIG = { - name: DB_NAME, - securityLevel: graphStore.SecurityLevel.S1 -} -let context = featureAbility.getContext(); -let store; -const BASE_COUNT = 1000; // loop times -const BASE_LINE_TABLE = 2500; // callback tablet base line -const BASE_LINE_PHONE = 3000; // callback phone base line -const BASE_LINE = (deviceInfo.deviceType == "tablet") ? BASE_LINE_TABLE : BASE_LINE_PHONE; - -describe('gdbStorePromisePerf', () => { - beforeAll(async () => { - console.info(TAG + 'beforeAll'); - await graphStore.deleteStore(context, STORE_CONFIG); - store = await graphStore.getStore(context, STORE_CONFIG); - }) - beforeEach(async () => { - console.info(TAG + 'beforeEach'); - await store.write(CREATE_GRAPH_TEST); - }) - afterEach(async () => { - console.info(TAG + 'afterEach'); - await store.write("DROP GRAPH test"); - }) - afterAll(async () => { - console.info(TAG + 'afterAll'); - await store.close(); - await graphStore.deleteStore(context, STORE_CONFIG); - }) - - console.log(TAG + "*************Unit Test Begin*************"); - - it('Perf_Gdb_Write_Promise_001', 0, async () => { - console.info(TAG + "************* testPerfGdbWritePromise001 start *************"); - let averageTime = 0; - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - let INSERT = "INSERT (:Person {name: 'name_" + (i + 1) + "', age:" + (i + 1) + "});"; - await store.write(INSERT); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the write_INSERT_Promise average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - console.info(TAG + "************* testPerfGdbWritePromise001 end *************"); - }) - - it('Perf_Gdb_Write_Promise_002', 0, async () => { - console.info(TAG + "************* testPerfGdbWritePromise002 start *************"); - for (let i = 0; i < BASE_COUNT; i++) { - let INSERT = "INSERT (:Person {name: 'name_" + (i + 1) + "', age:" + (i + 1) + "});"; - await store.write(INSERT); - } - let averageTime = 0; - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - let UPDATE = "MATCH (n:Person {name: 'name_" + (i + 1) + "' }) SET n.age = " + (i + 2) + ";"; - await store.write(UPDATE); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the write_UPDATE_Promise average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - console.info(TAG + "************* testPerfGdbWritePromise002 end *************"); - }) - - it('Perf_Gdb_Write_Promise_003', 0, async () => { - console.info(TAG + "************* testPerfGdbWritePromise003 start *************"); - for (let i = 0; i < BASE_COUNT; i++) { - let INSERT = "INSERT (:Person {name: 'name_" + (i + 1) + "', age:" + (i + 1) + "});"; - await store.write(INSERT); - } - let averageTime = 0; - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - let DELETE = "MATCH (n:Person {name: 'name_" + (i + 1) + "' }) DETACH DELETE n;"; - await store.write(DELETE); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the write_DELETE_Promise average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - console.info(TAG + "************* testPerfGdbWritePromise003 end *************"); - }) - - it('Perf_Gdb_Read_Promise_001', 0, async () => { - console.info(TAG + "************* testPerfGdbReadPromise001 start *************"); - for (let i = 0; i < BASE_COUNT; i++) { - let INSERT = "INSERT (:Person {name: 'name_" + (i + 1) + "', age:" + (i + 1) + "});"; - await store.write(INSERT); - } - let averageTime = 0; - let startTime = new Date().getTime(); - for (let i = 0; i < BASE_COUNT; i++) { - let QUERY = "MATCH (n:Person {name: 'name_" + (i + 1) + "' }) RETURN n;"; - await store.read(QUERY); - } - let endTime = new Date().getTime(); - averageTime = ((endTime - startTime) * 1000) / BASE_COUNT; - console.info(TAG + " the read_Query_Vertex_Promise average time is: " + averageTime + " μs"); - expect(averageTime < BASE_LINE).assertTrue(); - console.info(TAG + "************* testPerfGdbReadPromise001 end *************"); - }) - console.info(TAG + "*************Unit Test End*************") -}) \ No newline at end of file diff --git a/relational_store/test/js/gdb/unittest/config.json b/relational_store/test/js/gdb/unittest/config.json deleted file mode 100644 index ea584027..00000000 --- a/relational_store/test/js/gdb/unittest/config.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "app": { - "bundleName": "com.example.myapplication", - "vendor": "example", - "version": { - "code": 1, - "name": "1.0" - }, - "apiVersion": { - "compatible": 4, - "target": 5 - } - }, - "deviceConfig": {}, - "module": { - "package": "com.example.myapplication", - "name": ".MyApplication", - "deviceType": [ - "tablet", - "2in1", - "default", - "phone" - ], - "distro": { - "deliveryWithInstall": true, - "moduleName": "entry", - "moduleType": "entry" - }, - "abilities": [ - { - "visible": true, - "skills": [ - { - "entities": [ - "entity.system.home" - ], - "actions": [ - "action.system.home" - ] - } - ], - "name": "com.example.myapplication.MainAbility", - "icon": "$media:icon", - "description": "$string:mainability_description", - "label": "MyApplication", - "type": "page", - "launchType": "standard" - } - ], - "js": [ - { - "pages": [ - "pages/index/index" - ], - "name": "default", - "window": { - "designWidth": 720, - "autoDesignWidth": false - } - } - ] - } - } - \ No newline at end of file diff --git a/relational_store/test/js/gdb/unittest/src/GdbStoreGdbStoreJsunit.test.js b/relational_store/test/js/gdb/unittest/src/GdbStoreGdbStoreJsunit.test.js deleted file mode 100644 index f6ea11ba..00000000 --- a/relational_store/test/js/gdb/unittest/src/GdbStoreGdbStoreJsunit.test.js +++ /dev/null @@ -1,422 +0,0 @@ -/* - * 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. - */ - -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' -import graphStore from '@ohos.data.graphStore' -import ability_featureAbility from '@ohos.ability.featureAbility' - -const TAG = "[GRAPH_STORE_JSKITS_TEST]"; -const context = ability_featureAbility.getContext(); -const CREATE_GRAPH_TEST = "CREATE GRAPH test {(person:Person {name STRING, age INT}), (person) -[:Friend]-> (person)};" -const STORE_CONFIG = { - name: "graphstore", - securityLevel: graphStore.SecurityLevel.S1, -}; - -describe('graphStoreTest', () => { - beforeAll(async () => { - console.info(TAG + 'beforeAll'); - }) - - beforeEach(async () => { - console.info(TAG + 'beforeEach'); - }) - - afterEach(async () => { - console.info(TAG + 'afterEach'); - await graphStore.deleteStore(context, STORE_CONFIG); - }) - - afterAll(async () => { - console.info(TAG + 'afterAll'); - }) - - console.info(TAG + "*************Unit Test Begin*************"); - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0001 - * @tc.desc graph store getStore test - */ - it('testGraphStore0001', 0, async () => { - console.info(TAG + "************* testGraphStore0001 start *************"); - try { - let store = await graphStore.getStore(context, STORE_CONFIG); - await store.close(); - await graphStore.deleteStore(context, STORE_CONFIG); - } catch (e) { - console.error(TAG + "graphStore test_1 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStore0001 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0002 - * @tc.desc graph store getStore and write - */ - it('testGraphStore0002', 0, async () => { - console.info(TAG + "************* testGraphStore0002 start *************"); - try { - let store = await graphStore.getStore(context, STORE_CONFIG); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - await graphStore.deleteStore(context, STORE_CONFIG); - } catch (e) { - console.error(TAG + "graphStore test_2 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStore0002 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0003 - * @tc.desc graph store getStore with wrong storeConfig name - */ - it('testGraphStore0003', 0, async () => { - console.info(TAG + "************* testGraphStore0003 start *************"); - let storeConfig = { - name: "/wrong/graphstore", - securityLevel: graphStore.SecurityLevel.S1, - }; - try { - let store = await graphStore.getStore(context, storeConfig); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - await graphStore.deleteStore(context, storeConfig); - expect().assertFail(); - } catch (e) { - expect('401').assertEqual(e.code); - } - console.info(TAG + "************* testGraphStore0003 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0004 - * @tc.desc graph store getStore with securityLevel - */ - it('testGraphStore0004', 0, async () => { - console.info(TAG + "************* testGraphStore0004 start *************"); - let storeConfig = { - name: "secure", - securityLevel: graphStore.SecurityLevel.S3, - }; - try { - let store = await graphStore.getStore(context, storeConfig); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - await graphStore.deleteStore(context, storeConfig); - } catch (e) { - console.error(TAG + "graphStore test_4 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStore0004 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0005 - * @tc.desc graph store getStore with invalid securityLevel - */ - it('testGraphStore0005', 0, async () => { - console.info(TAG + "************* testGraphStore0005 start *************"); - let storeConfig = { - name: "secure", - securityLevel: 0, - }; - try { - //expect getStore failed - let store = await graphStore.getStore(context, storeConfig); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - await graphStore.deleteStore(context, storeConfig); - expect().assertFail(); - } catch (e) { - expect(401).assertEqual(e.code); - } - console.info(TAG + "************* testGraphStore0005 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0006 - * @tc.desc graph store getStore with 1 param - */ - it('testGraphStore0006', 0, async () => { - console.info(TAG + "************* testGraphStore0006 start *************"); - try { - //expect getStore failed - let store = await graphStore.getStore(STORE_CONFIG); - expect().assertFail(); - } catch (e) { - expect('401').assertEqual(e.code); - } - console.info(TAG + "************* testGraphStore0006 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0007 - * @tc.desc graph store getStore name has db Suffix - */ - it('testGraphStore0007', 0, async () => { - console.info(TAG + "************* testGraphStore0007 start *************"); - let storeConfig = { - name: "suffix.db", - securityLevel: graphStore.SecurityLevel.S1, - } - try { - // expect get store failed - let store = await graphStore.getStore(context, storeConfig); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - await graphStore.deleteStore(context, storeConfig); - expect().assertFail(); - } catch (e) { - expect(31300000).assertEqual(e.code); - } - console.info(TAG + "************* testGraphStore0007 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0008 - * @tc.desc graph store getStore with null storeConfig name - */ - it('testGraphStore0008', 0, async () => { - console.info(TAG + "************* testGraphStore0008 start *************"); - let storeConfig = { - securityLevel: graphStore.SecurityLevel.S1, - } - try { - // expect get store failed - let store = await graphStore.getStore(context, storeConfig); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - await graphStore.deleteStore(context, storeConfig); - expect().assertFail(); - } catch (e) { - expect('401').assertEqual(e.code); - } - console.info(TAG + "************* testGraphStore0008 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0009 - * @tc.desc graph store getStore name has special characters - */ - it('testGraphStore0009', 0, async () => { - console.info(TAG + "************* testGraphStore0009 start *************"); - let storeConfig = { - name: "char*@#!(.&", - securityLevel: graphStore.SecurityLevel.S1, - } - try { - // expect get store failed - let store = await graphStore.getStore(context, storeConfig); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - await graphStore.deleteStore(context, storeConfig); - expect().assertFail(); - } catch (e) { - expect(31300000).assertEqual(e.code); - } - console.info(TAG + "************* testGraphStore0009 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0010 - * @tc.desc graph store getStore SecurityLevel S2->S1 - */ - it('testGraphStore0010', 0, async () => { - console.info(TAG + "************* testGraphStore0010 start *************"); - let storeConfig = { - name: "graphstore", - securityLevel: graphStore.SecurityLevel.S2, - } - try { - let store = await graphStore.getStore(context, storeConfig); - await store.close(); - store = await graphStore.getStore(context, STORE_CONFIG); - expect().assertFail(); - } catch (e) { - expect(401).assertEqual(e.code); - } - await graphStore.deleteStore(context, storeConfig); - console.info(TAG + "************* testGraphStore0010 end *************"); - }) - - /** - * @tc.name graph store getStore test - * @tc.number GdbStoreGdbStoreJsunitTest0011 - * @tc.desc graph store getStore SecurityLevel S1->S2 - */ - it('testGraphStore0011', 0, async () => { - console.info(TAG + "************* testGraphStore0011 start *************"); - let storeConfig = { - name: "graphstore", - securityLevel: graphStore.SecurityLevel.S2, - } - try { - let store = await graphStore.getStore(context, STORE_CONFIG); - await store.close(); - store = await graphStore.getStore(context, storeConfig); - await store.close(); - await graphStore.deleteStore(context, storeConfig); - } catch (e) { - console.error(TAG + "graphStore test_11 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStore0011 end *************"); - }) - - /** - * @tc.name graph store deleteStore test - * @tc.number GdbStoreGdbStoreJsunitTest0012 - * @tc.desc graph store deleteStore test - */ - it('testGraphStore0012', 0, async () => { - console.info(TAG + "************* testGraphStore0012 start *************"); - let store = await graphStore.getStore(context, STORE_CONFIG); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - try { - await graphStore.deleteStore(context, STORE_CONFIG); - } catch (e) { - console.error(TAG + "graphStore test_12 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStore0012 end *************"); - }) - - /** - * @tc.name graph store deleteStore test - * @tc.number GdbStoreGdbStoreJsunitTest0013 - * @tc.desc graph store deleteStore with wrong store name - */ - it('testGraphStore0013', 0, async () => { - console.info(TAG + "************* testGraphStore0013 start *************"); - let storeConfig = { - name: "/wrong/graphstore", - securityLevel: graphStore.SecurityLevel.S1, - } - let store = await graphStore.getStore(context, STORE_CONFIG); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - try { - await graphStore.deleteStore(context, storeConfig); - expect().assertFail(); - } catch (e) { - expect('401').assertEqual(e.code); - } - console.info(TAG + "************* testGraphStore0013 end *************"); - }) - - /** - * @tc.name graph store deleteStore test - * @tc.number GdbStoreGdbStoreJsunitTest0014 - * @tc.desc graph store deleteStore with different store name - */ - it('testGraphStore0014', 0, async () => { - console.info(TAG + "************* testGraphStore0014 start *************"); - let storeConfig = { - name: "teststore", - securityLevel: graphStore.SecurityLevel.S1, - } - let store = await graphStore.getStore(context, STORE_CONFIG); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - try { - // delete success - await graphStore.deleteStore(context, storeConfig); - } catch (e) { - expect().assertFail(); - } - console.info(TAG + "************* testGraphStore0014 end *************"); - }) - - /** - * @tc.name graph store deleteStore test - * @tc.number GdbStoreGdbStoreJsunitTest0015 - * @tc.desc graph store deleteStore with different securityLevel - */ - it('testGraphStore0015', 0, async () => { - console.info(TAG + "************* testGraphStore0015 start *************"); - let storeConfig = { - name: "graphstore", - securityLevel: graphStore.SecurityLevel.S4, - } - let store = await graphStore.getStore(context, STORE_CONFIG); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - try { - // delete success - await graphStore.deleteStore(context, storeConfig); - } catch (e) { - expect().assertFail(); - } - console.info(TAG + "************* testGraphStore0015 end *************"); - }) - - /** - * @tc.name graph store deleteStore test - * @tc.number GdbStoreGdbStoreJsunitTest0016 - * @tc.desc graph store deleteStore with 1 param - */ - it('testGraphStore0016', 0, async () => { - console.info(TAG + "************* testGraphStore0016 start *************"); - let store = await graphStore.getStore(context, STORE_CONFIG); - await store.write(CREATE_GRAPH_TEST); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("DROP GRAPH test"); - await store.close(); - try { - await graphStore.deleteStore(context); - expect().assertFail(); - } catch (e) { - expect('401').assertEqual(e.code); - } - console.info(TAG + "************* testGraphStore0016 end *************"); - }) - - console.info(TAG + "*************Unit Test End*************"); -}) diff --git a/relational_store/test/js/gdb/unittest/src/GdbStoreReadWriteJsunit.test.js b/relational_store/test/js/gdb/unittest/src/GdbStoreReadWriteJsunit.test.js deleted file mode 100644 index 17cb922e..00000000 --- a/relational_store/test/js/gdb/unittest/src/GdbStoreReadWriteJsunit.test.js +++ /dev/null @@ -1,936 +0,0 @@ -/* - * 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. - */ - -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' -import graphStore from '@ohos.data.graphStore' -import ability_featureAbility from '@ohos.ability.featureAbility' - -const TAG = "[GRAPH_STORE_JSKITS_TEST]"; -const context = ability_featureAbility.getContext(); -const CREATE_GRAPH_TEST = "CREATE GRAPH test {(person:Person {name STRING, age INT}), (person) -[:Friend]-> (person)};" -const STORE_CONFIG = { - name: "readwritegraph", - securityLevel: graphStore.SecurityLevel.S1, -}; - -describe('graphStoreReadWriteTest', () => { - let store; - beforeAll(async () => { - console.info(TAG + 'beforeAll'); - await graphStore.deleteStore(context, STORE_CONFIG); - store = await graphStore.getStore(context, STORE_CONFIG); - }) - - beforeEach(async () => { - console.info(TAG + 'beforeEach'); - await store.write(CREATE_GRAPH_TEST); - }) - - afterEach(async () => { - console.info(TAG + 'afterEach'); - await store.write("DROP GRAPH test"); - }) - - afterAll(async () => { - console.info(TAG + 'afterAll'); - await store.close(); - await graphStore.deleteStore(context, STORE_CONFIG); - }) - - console.info(TAG + "*************Unit Test Begin*************"); - - /** - * @tc.name graph store close test - * @tc.number GdbStoreCloseTest0001 - * @tc.desc graph store close test - */ - it('testGraphStoreClose0001', 0, async () => { - console.info(TAG + "************* testGraphStoreClose0001 start *************"); - let storeConfig = { - name: "closeStore", - securityLevel: graphStore.SecurityLevel.S1, - }; - let closestore = await graphStore.getStore(context, storeConfig); - await closestore.write(CREATE_GRAPH_TEST); - await closestore.write("INSERT (:Person {name: 'name_1', age: 11});"); - await closestore.write("DROP GRAPH test"); - try { - await closestore.close(); - } catch (e) { - console.error(TAG + "close test failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - await graphStore.deleteStore(context, storeConfig); - console.info(TAG + "************* testGraphStoreClose0001 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0001 - * @tc.desc graph store write insert - */ - it('testGraphStoreWrite0001', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0001 start *************"); - try { - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1) -[:Friend]-> (p2);" - ); - let result = await store.read("MATCH (p:Person) where p.age < 30 RETURN p") - if (result.records) { - expect(2).assertEqual(result.records.length); - } else { - console.error(TAG + "write test1 INSERT vertex failed."); - expect().assertFail(); - } - let path = await store.read( - "MATCH path = (p1:Person {name: 'name_1'})-[]-(p2:Person {name: 'name_2'}) RETURN path;" - ); - if (path.records) { - expect(1).assertEqual(path.records.length); - } else { - console.error(TAG + "write test1 INSERT edge failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "write test1 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreWrite0001 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0002 - * @tc.desc graph store write update - */ - it('testGraphStoreWrite0002', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0002 start *************"); - try { - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1) -[:Friend]-> (p2);" - ); - await store.write("MATCH (p1:Person {name: 'name_1'}) SET p1.age = 21;"); - await store.write("MATCH (p2:Person {name: 'name_2'}) SET p2.name = 'Aname';"); - await store.write("MATCH (n:Person {name: 'name_1'})-[r:Friend]->(m:Person) SET m.age = 32"); - - let p1 = await store.read("MATCH (p1:Person) where p1.name = 'name_1' RETURN p1;"); - if (p1.records) { - expect(1).assertEqual(p1.records.length); - let temp = p1.records[0]; - let vertex = temp["p1"]; - expect('1').assertEqual(vertex.vid); - let proper = vertex.properties; - expect(21).assertEqual(proper["AGE"]); - expect('name_1').assertEqual(proper["NAME"]); - } else { - console.error(TAG + "write test2 read data1 failed."); - expect().assertFail(); - } - - let p2 = await store.read("MATCH (p2:Person) where p2.name = 'name_2' RETURN p2;"); - if (p2.records) { - expect(0).assertEqual(p2.records.length); - } else { - console.error(TAG + "write test2 read data2 failed."); - expect().assertFail(); - } - - let p3 = await store.read("MATCH (p3:Person) where p3.name = 'Aname' RETURN p3;"); - if (p3.records) { - expect(1).assertEqual(p3.records.length); - let temp = p3.records[0]; - let vertex = temp["p3"]; - expect('2').assertEqual(vertex.vid); - let proper = vertex.properties; - expect(32).assertEqual(proper["AGE"]); - expect('Aname').assertEqual(proper["NAME"]); - } else { - console.error(TAG + "write test2 read data3 failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "write test2 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreWrite0002 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0003 - * @tc.desc graph store write delete - */ - it('testGraphStoreWrite0003', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0003 start *************"); - try { - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1) -[:Friend]-> (p2);" - ); - await store.write("MATCH (p:Person {name: 'name_1'}) DETACH DELETE p;"); - // read - let p = await store.read("MATCH (p:Person) where p.age < 30 RETURN p"); - if (p.records) { - expect(1).assertEqual(p.records.length); - } else { - console.error(TAG + "write test3 read data1 failed."); - expect().assertFail(); - } - - let path = await store.read( - "MATCH path = (p1:Person {name: 'name_1'})-[]-(p2:Person {name: 'name_2'}) RETURN path;" - ) - if (path.records) { - expect(0).assertEqual(path.records.length); - } else { - console.error(TAG + "write test3 read data2 failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "write test3 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreWrite0003 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0004 - * @tc.desc graph store write with 2 params - */ - it('testGraphStoreWrite0004', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0004 start *************"); - try { - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - let INSERT1 = "INSERT (:Person {name: 'name_3', age: 33});" - let INSERT2 = "INSERT (:Person {name: 'name_4', age: 44});" - await store.write(INSERT1, INSERT2); - expect().assertFail(); - } catch (e) { - expect('401').assertEqual(e.code); - // read - let p = await store.read("MATCH (p:Person) where p.age < 50 RETURN p"); - if (p.records) { - expect(2).assertEqual(p.records.length); - } else { - console.error(TAG + "write test4 read data failed."); - expect().assertFail(); - } - } - console.info(TAG + "************* testGraphStoreWrite0004 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0005 - * @tc.desc graph store close before write - */ - it('testGraphStoreWrite0005', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0005 start *************"); - let storeConfig = { - name: "closeStore", - securityLevel: graphStore.SecurityLevel.S1, - }; - let closestore = await graphStore.getStore(context, storeConfig); - await closestore.write(CREATE_GRAPH_TEST); - try { - await closestore.write("INSERT (:Person {name: 'name_1', age: 11});"); - let p = await closestore.read("MATCH (p:Person) where p.age < 30 RETURN p"); - if (p.records) { - expect(1).assertEqual(p.records.length); - } else { - console.error(TAG + "write test5 read data failed."); - expect().assertFail(); - } - await closestore.close(); - await closestore.write("INSERT (:Person {name: 'name_2', age: 22});"); - expect().assertFail(); - } catch (e) { - expect('31300002').assertEqual(e.code); - } - await graphStore.deleteStore(context, storeConfig); - console.info(TAG + "************* testGraphStoreWrite0005 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0006 - * @tc.desc graph store write with duplicate type - */ - it('testGraphStoreWrite0006', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0006 start *************") - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - let INSERT = "INSERT (:Person {name: 'name_3', name: 'name_4', age: 33});" - try { - //insert failed but no error - await store.write(INSERT); - let result = await store.write("MATCH (p:Person) where p.age = 33 RETURN p;"); - if (result.records) { - expect(0).assertEqual(result.records.length); - } - } catch (e) { - console.error(TAG + "write test6 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreWrite0006 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0007 - * @tc.desc graph store write with undefined type - */ - it('testGraphStoreWrite0007', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0007 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - let UPDATE = "MATCH (p:Person {name: 'name_1'}) DETACH DELETE p_error" - try { - await store.write(UPDATE); - expect().assertFail(); - } catch (e) { - expect(31300007).assertEqual(e.code); - // read - let p = await store.read("MATCH (p:Person) where p.age < 50 RETURN p"); - if (p.records) { - expect(2).assertEqual(p.records.length); - } else { - console.error(TAG + "write test7 read data failed."); - expect().assertFail(); - } - } - console.info(TAG + "************* testGraphStoreWrite0007 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0008 - * @tc.desc graph store write with GQL statement syntax error - */ - it('testGraphStoreWrite0008', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0008 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - let INSERT = "INSERT (:ZOO {name: 'name_3', age: 33);" - try { - await store.write(INSERT); - expect().assertFail(); - } catch (e) { - expect(31300009).assertEqual(e.code); - // read - let p = await store.read("MATCH (p:Person) where p.age < 50 RETURN p"); - if (p.records) { - expect(2).assertEqual(p.records.length); - } else { - console.error(TAG + "write test8 read data failed."); - expect().assertFail(); - } - } - console.info(TAG + "************* testGraphStoreWrite0008 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0009 - * @tc.desc graph store write with GQL statement semantic error - */ - it('testGraphStoreWrite0009', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0009 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - let UPDATE = "MATCH (p1:Person {name: 'name_1'}) SET p1.age = 'six';" - try { - await store.write(UPDATE); - expect().assertFail(); - } catch (e) { - expect(31300010).assertEqual(e.code); - // read - let p = await store.read("MATCH (p:Person) where p.age < 50 RETURN p"); - if (p.records) { - expect(2).assertEqual(p.records.length); - let temp = p.records[0]; - let vertex = temp["p"]; - expect('1').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_1').assertEqual(proper["NAME"]); - expect(11).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "write test9 read data failed."); - expect().assertFail(); - } - } - console.info(TAG + "************* testGraphStoreWrite0009 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0010 - * @tc.desc graph store write and update null data - */ - it('testGraphStoreWrite0010', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0010 start *************"); - await store.write("INSERT (:Person {name: 'name_1'});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - let data = await store.read("MATCH (p:Person) where p.age < 50 RETURN p"); - if (data.records) { - expect(1).assertEqual(data.records.length); - let temp = data.records[0]; - let vertex = temp["p"]; - expect('2').assertEqual(vertex.vid); - let proper = vertex.properties; - expect(22).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "write test10 INSERT data failed."); - expect().assertFail(); - } - let UPDATE1 = "MATCH (p1:Person {name: 'name_1'}) SET p1.age = 16;" - let UPDATE2 = "MATCH (p2:Person {name: 'name_2'}) SET p2.age = 16, p2.name = null;" - try { - await store.write(UPDATE1); - await store.write(UPDATE2); - data = await store.read("MATCH (p:Person) where p.age < 50 RETURN p"); - if (data.records) { - expect(2).assertEqual(data.records.length); - let temp = data.records[0]; - let vertex = temp["p"]; - expect('1').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_1').assertEqual(proper["NAME"]); - expect(16).assertEqual(proper["AGE"]); - - temp = data.records[1]; - vertex = temp["p"]; - expect('2').assertEqual(vertex.vid); - proper = vertex.properties; - // name undefined - expect(16).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "write test10 read data failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "write test10 update null data failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreWrite0010 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0011 - * @tc.desc graph store write create too many graphs - */ - it('testGraphStoreWrite0011', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0011 start *************"); - try { - await store.write("CREATE GRAPH test1 {(company:Company {rowid INT, name STRING}) };"); - expect().assertFail(); - } catch (e) { - expect(31300012).assertEqual(e.code); - } - console.info(TAG + "************* testGraphStoreWrite0011 end *************"); - }) - - /** - * @tc.name graph store write test - * @tc.number GdbStoreWriteTest0012 - * @tc.desc graph store write delete the vertexs of a relation - */ - it('testGraphStoreWrite0012', 0, async () => { - console.info(TAG + "************* testGraphStoreWrite0012 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 33});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p3:Person {name: 'name_3'}) INSERT (p1) -[:Friend]-> (p3);" - ); - let data = await store.read("MATCH (p:Person) where p.age < 50 RETURN p"); - if (data.records) { - expect(3).assertEqual(data.records.length); - } else { - console.error(TAG + "write test12 INSERT data failed."); - expect().assertFail(); - } - let DELETE = "MATCH (p:Person)-[:Friend]->(relatedP:Person) DETACH DELETE p, relatedP;" - try { - await store.write(DELETE); - data = await store.read("MATCH (p:Person) where p.age < 50 RETURN p"); - // read data - if (data.records) { - expect(1).assertEqual(data.records.length); - let temp = data.records[0]; - let vertex = temp["p"]; - expect('2').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_2').assertEqual(proper["NAME"]); - expect(22).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "write test12 read data failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "write test12 delete failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreWrite0012 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0001 - * @tc.desc graph store read query vertex test - */ - it('testGraphStoreRead0001', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0001 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 22});"); - try { - let p = await store.read("MATCH (p:Person {age: 22}) RETURN p;"); - if (p.records) { - expect(2).assertEqual(p.records.length); - let temp = p.records[0]; - let vertex = temp["p"]; - expect('2').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_2').assertEqual(proper["NAME"]); - expect(22).assertEqual(proper["AGE"]); - - temp = p.records[1]; - vertex = temp["p"]; - expect('3').assertEqual(vertex.vid); - proper = vertex.properties; - expect('name_3').assertEqual(proper["NAME"]); - expect(22).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "read test1 query failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "read test1 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreRead0001 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0002 - * @tc.desc graph store read query null data test - */ - it('testGraphStoreRead0002', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0002 start *************"); - await store.write("INSERT (:Person {age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 22});"); - try { - let p = await store.read("MATCH (p:Person {age: 11}) RETURN p;"); - if (p.records) { - expect(1).assertEqual(p.records.length); - let temp = p.records[0]; - let vertex = temp["p"]; - expect('1').assertEqual(vertex.vid); - let proper = vertex.properties; - // name undefined - expect(11).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "read test2 query null data failed."); - expect().assertFail(); - } - - p = await store.read("MATCH (p:Person {age: 22}) RETURN p;"); - if (p.records) { - expect(2).assertEqual(p.records.length); - let temp = p.records[0]; - let vertex = temp["p"]; - expect('2').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_2').assertEqual(proper["NAME"]); - expect(22).assertEqual(proper["AGE"]); - - temp = p.records[1]; - vertex = temp["p"]; - proper = vertex.properties; - expect('name_3').assertEqual(proper["NAME"]); - } else { - console.error(TAG + "read test2 query null data failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "read test2 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreRead0002 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0003 - * @tc.desc graph store read by relation - */ - it('testGraphStoreRead0003', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0003 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 22});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1)-[:Friend]->(p2);" - ) - try { - let data = await store.read( - "MATCH (p1:Person {age: 11})-[r:Friend]->(p2:Person {name :'name_2'}) RETURN p1, r, p2;" - ); - if (data.records) { - expect(1).assertEqual(data.records.length); - let temp = data.records[0]; - let vertex = temp["p1"]; - expect('1').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_1').assertEqual(proper["NAME"]); - expect(11).assertEqual(proper["AGE"]); - - let edge = temp["r"]; - expect('4').assertEqual(edge.eid); - expect('1').assertEqual(edge.startVid); - expect('2').assertEqual(edge.endVid); - - vertex = temp["p2"]; - expect('2').assertEqual(vertex.vid); - proper = vertex.properties; - expect(22).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "read test3 query relation failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "read test3 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreRead0003 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0004 - * @tc.desc graph store read by where statement - */ - it('testGraphStoreRead0004', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0004 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 22});"); - try { - let data = await store.read("MATCH (p:Person) where p.age >= 22 RETURN p;"); - if (data.records) { - expect(2).assertEqual(data.records.length); - let temp = data.records[0]; - let vertex = temp["p"]; - expect('2').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_2').assertEqual(proper["NAME"]); - expect(22).assertEqual(proper["AGE"]); - - temp = data.records[1]; - vertex = temp["p"]; - expect('3').assertEqual(vertex.vid); - proper = vertex.properties; - expect('name_3').assertEqual(proper["NAME"]); - } else { - console.error(TAG + "read test4 query by where failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "read test4 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreRead0004 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0005 - * @tc.desc graph store read by where statement - */ - it('testGraphStoreRead0005', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0005 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 22});"); - try { - let data = await store.read("MATCH (p:Person) where p.age < 22 RETURN p;"); - if (data.records) { - expect(1).assertEqual(data.records.length); - let temp = data.records[0]; - let vertex = temp["p"]; - expect('1').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_1').assertEqual(proper["NAME"]); - expect(11).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "read test5 query by where failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "read test5 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreRead0005 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0006 - * @tc.desc graph store read by where statement - */ - it('testGraphStoreRead0006', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0006 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 33});"); - try { - let data = await store.read("MATCH (p:Person) where p.age <> 22 RETURN p;"); - if (data.records) { - expect(2).assertEqual(data.records.length); - let temp = data.records[0]; - let vertex = temp["p"]; - expect('1').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_1').assertEqual(proper["NAME"]); - expect(11).assertEqual(proper["AGE"]); - - temp = data.records[1]; - vertex = temp["p"]; - expect('3').assertEqual(vertex.vid); - proper = vertex.properties; - expect('name_3').assertEqual(proper["NAME"]); - expect(33).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "read test6 query by where failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "read test6 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreRead0006 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0007 - * @tc.desc graph store read by like statement - */ - it('testGraphStoreRead0007', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0007 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 33});"); - try { - let data = await store.read("MATCH (p:Person) where p.name like 'name_%' RETURN p;"); - if (data.records) { - expect(3).assertEqual(data.records.length); - let temp = data.records[0]; - let vertex = temp["p"]; - expect('1').assertEqual(vertex.vid); - let proper = vertex.properties; - expect('name_1').assertEqual(proper["NAME"]); - expect(11).assertEqual(proper["AGE"]); - - temp = data.records[1]; - vertex = temp["p"]; - expect('2').assertEqual(vertex.vid); - proper = vertex.properties; - expect('name_2').assertEqual(proper["NAME"]); - expect(22).assertEqual(proper["AGE"]); - - temp = data.records[2]; - vertex = temp["p"]; - expect('3').assertEqual(vertex.vid); - proper = vertex.properties; - expect('name_3').assertEqual(proper["NAME"]); - expect(33).assertEqual(proper["AGE"]); - } else { - console.error(TAG + "read test7 query by like failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "read test7 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreRead0007 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0008 - * @tc.desc graph store read path - */ - it('testGraphStoreRead0008', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0008 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write("INSERT (:Person {name: 'name_3', age: 33});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1) -[:Friend]-> (p2);" - ); - await store.write( - "MATCH (p2:Person {name: 'name_2'}), (p3:Person {name: 'name_3'}) INSERT (p2) -[:Friend]-> (p3);" - ); - try { - let data = await store.read( - "MATCH path = (a:Person {name: 'name_1'})-[]->{2,2}(b:Person {name: 'name_3'}) RETURN a, b, path;" - ); - if (data.records) { - expect(1).assertEqual(data.records.length); - let temp = data.records[0]; - - let vertex1 = temp["a"]; - expect('1').assertEqual(vertex1.vid); - let proper = vertex1.properties; - expect('name_1').assertEqual(proper["NAME"]); - expect(11).assertEqual(proper["AGE"]); - - let vertex2 = temp["b"]; - expect('3').assertEqual(vertex2.vid); - proper = vertex2.properties; - expect('name_3').assertEqual(proper["NAME"]); - expect(33).assertEqual(proper["AGE"]); - - let path = temp["path"]; - expect(2).assertEqual(path.length); - let segments = path.segments; - expect(JSON.stringify(vertex1)).assertEqual(JSON.stringify(segments[0].start)); - expect(JSON.stringify(vertex2)).assertEqual(JSON.stringify(segments[1].end)); - - let edge = segments[1].edge; - expect('5').assertEqual(edge.eid); - expect('2').assertEqual(edge.startVid); - expect('3').assertEqual(edge.endVid); - } else { - console.error(TAG + "read test8 query path failed."); - expect().assertFail(); - } - } catch (e) { - console.error(TAG + "read test8 failed, error:" + JSON.stringify(e)); - expect().assertFail(); - } - console.info(TAG + "************* testGraphStoreRead0008 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0009 - * @tc.desc graph store read with 2 params - */ - it('testGraphStoreRead0009', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0009 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1) -[:Friend]-> (p2);" - ); - - let MATCH1 = "MATCH (p1:Person {name: 'name_1'}) RETURN p1;" - let MATCH2 = "MATCH (p2:Person {name: 'name_2'}) RETURN p2;" - try { - let result = await store.read(MATCH1, MATCH2); - expect().assertFail(); - } catch (e) { - expect('401').assertEqual(e.code); - } - console.info(TAG + "************* testGraphStoreRead0009 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0010 - * @tc.desc graph store close before read - */ - it('testGraphStoreRead0010', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0010 start *************"); - let storeConfig = { - name: "closeStore", - securityLevel: graphStore.SecurityLevel.S1, - }; - let closestore = await graphStore.getStore(context, storeConfig); - await closestore.write(CREATE_GRAPH_TEST); - await closestore.write("INSERT (:Person {name: 'name_1', age: 11});"); - await closestore.write("INSERT (:Person {name: 'name_2', age: 22});"); - await closestore.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1) -[:Friend]-> (p2);" - ); - await closestore.close(); - let MATCH = "MATCH (p1:Person {name: 'name_1'}) RETURN p1;" - try { - let result = await closestore.read(MATCH); - expect().assertFail(); - } catch (e) { - expect('31300002').assertEqual(e.code); - } - await graphStore.deleteStore(context, storeConfig); - console.info(TAG + "************* testGraphStoreRead0010 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0011 - * @tc.desc graph store read with undefined type - */ - it('testGraphStoreRead0011', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0011 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1) -[:Friend]-> (p2);" - ); - let MATCH = "MATCH path = (p1:ZOO {name: 'name_1'})-[]-(p2:Person {name: 'name_2'}) RETURN path;" - try { - let result = await store.read(MATCH); - expect().assertFail(); - } catch (e) { - expect(31300007).assertEqual(e.code); - } - console.info(TAG + "************* testGraphStoreRead0011 end *************"); - }) - - /** - * @tc.name graph store read test - * @tc.number GdbStoreReadTest0012 - * @tc.desc graph store read with GQL statement syntax error - */ - it('testGraphStoreRead0012', 0, async () => { - console.info(TAG + "************* testGraphStoreRead0012 start *************"); - await store.write("INSERT (:Person {name: 'name_1', age: 11});"); - await store.write("INSERT (:Person {name: 'name_2', age: 22});"); - await store.write( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1) -[:Friend]-> (p2);" - ); - try { - let result = await store.read("MATCH (p:Person {name: 'name_1}) RETURN p"); - expect().assertFail(); - } catch (e) { - expect(31300009).assertEqual(e.code); - } - console.info(TAG + "************* testGraphStoreRead0012 end *************"); - }) - console.info(TAG + "*************Unit Test End*************"); -}) \ No newline at end of file diff --git a/relational_store/test/js/rdb/unittest/src/RdbStoreDistributedJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbStoreDistributedJsunit.test.js index bf46e3ed..893febf9 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbStoreDistributedJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbStoreDistributedJsunit.test.js @@ -208,9 +208,9 @@ describe('rdbStoreDistributedTest', function () { const name = await resultSet.getString(resultSet.getColumnIndex("name")) const age = await resultSet.getLong(resultSet.getColumnIndex("age")) - await expect(1).assertEqual(id); - await expect("Jim").assertEqual(name); - await expect(30).assertEqual(age); + expect(1).assertEqual(id); + expect("Jim").assertEqual(name); + expect(30).assertEqual(age); resultSet.close(); expect(true).assertEqual(resultSet.isClosed) } catch (e) { diff --git a/relational_store/test/js/rdb/unittest/src/RdbstoreCreateDeleteWithFAContextJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstoreCreateDeleteWithFAContextJsunit.test.js index 3e2f4ec3..8cbc09df 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbstoreCreateDeleteWithFAContextJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbstoreCreateDeleteWithFAContextJsunit.test.js @@ -100,14 +100,8 @@ describe('rdbStoreCreateDeleteWithFAContextTest', function () { { let predicates = await new dataRdb.RdbPredicates("test") predicates.equalTo("name", "zhangsan") - let deletePromise = rdbStore.delete(predicates) - deletePromise.then(async (ret) => { - await expect(1).assertEqual(ret) - await console.log(TAG + "Delete done: " + ret) - }).catch((err) => { - expect(null).assertFail() - }) - await deletePromise + let ret = await rdbStore.delete(predicates) + expect(1).assertEqual(ret) } await rdbStore.executeSql("DELETE FROM test"); rdbStore = null diff --git a/relational_store/test/js/rdb/unittest/src/RdbstoreDeleteJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstoreDeleteJsunit.test.js index ec3de69e..05292f9c 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbstoreDeleteJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbstoreDeleteJsunit.test.js @@ -134,14 +134,8 @@ describe('rdbStoreDeleteTest', function () { { let predicates = await new dataRdb.RdbPredicates("test") predicates.equalTo("name", "zhangsan") - let deletePromise = rdbStore.delete(predicates) - deletePromise.then(async (ret) => { - await expect(1).assertEqual(ret) - await console.log(TAG + "Delete done: " + ret) - }).catch((err) => { - expect(null).assertFail() - }) - await deletePromise + let ret = await rdbStore.delete(predicates) + expect(1).assertEqual(ret) } done() console.log(TAG + "************* testRdbStoreDelete0002 end *************"); diff --git a/relational_store/test/js/rdb/unittest/src/RdbstoreEncryptionJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstoreEncryptionJsunit.test.js index b054febf..21c35988 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbstoreEncryptionJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbstoreEncryptionJsunit.test.js @@ -101,7 +101,7 @@ describe('rdbEncryptTest', function () { * @tc.desc RDB create encrypt db test */ it('RdbEncryptTest_0010', 0, async function () { - await console.log(TAG + "************* RdbEncryptTest_0010 start *************") + console.log(TAG + "************* RdbEncryptTest_0010 start *************") try { context = ability_featureAbility.getContext() await data_rdb.getRdbStore(context, STORE_CONFIG_ENCRYPT, 1); @@ -109,7 +109,7 @@ describe('rdbEncryptTest', function () { console.log(TAG + `failed, errcode:${JSON.stringify(err)}.`); expect(null).assertFail(); } - await console.log(TAG + "************* RdbEncryptTest_0010 end *************") + console.log(TAG + "************* RdbEncryptTest_0010 end *************") }) /** @@ -118,7 +118,7 @@ describe('rdbEncryptTest', function () { * @tc.desc RDB create unencrypted db test */ it('RdbEncryptTest_0020', 0, async function () { - await console.log(TAG + "************* RdbEncryptTest_0020 start *************") + console.log(TAG + "************* RdbEncryptTest_0020 start *************") context = ability_featureAbility.getContext() try { await data_rdb.getRdbStore(context, STORE_CONFIG_UNENCRYPT, 1); @@ -126,7 +126,7 @@ describe('rdbEncryptTest', function () { console.log(TAG + `failed, errcode:${JSON.stringify(err)}.`); expect(null).assertFail(); } - await console.log(TAG + "************* RdbEncryptTest_0020 end *************") + console.log(TAG + "************* RdbEncryptTest_0020 end *************") }) @@ -136,7 +136,7 @@ describe('rdbEncryptTest', function () { * @tc.desc RDB encrypt function test */ it('RdbEncryptTest_0030', 0, async function () { - await console.log(TAG + "************* RdbEncryptTest_0030 start *************") + console.log(TAG + "************* RdbEncryptTest_0030 start *************") context = ability_featureAbility.getContext() let rdbStore = await CreateRdbStore(context, STORE_CONFIG_ENCRYPT) let predicates = new data_rdb.RdbPredicates("test") @@ -159,7 +159,7 @@ describe('rdbEncryptTest', function () { resultSet = null rdbStore = null } - await console.log(TAG + "************* RdbEncryptTest_0030 end *************") + console.log(TAG + "************* RdbEncryptTest_0030 end *************") }) /** @@ -213,7 +213,7 @@ describe('rdbEncryptTest', function () { * 4. query db1 and db2 */ it('RdbEncryptTest_0050', 0, async function () { - await console.info(TAG + "************* RdbEncryptTest_0050 start *************") + console.info(TAG + "************* RdbEncryptTest_0050 start *************") context = ability_featureAbility.getContext() let rdbStore1; let rdbStore2; diff --git a/relational_store/test/js/rdb/unittest/src/RdbstorePredicatesComplexFiledJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstorePredicatesComplexFiledJsunit.test.js index 80ffc254..3396fce7 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbstorePredicatesComplexFiledJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbstorePredicatesComplexFiledJsunit.test.js @@ -75,12 +75,12 @@ describe('rdbStorePredicatesComplexFiledTest', function () { let count = await resultSet.getLong(resultSet.getColumnIndex("num count")) let birthday = await resultSet.getString(resultSet.getColumnIndex("birthday")) expect(2).assertEqual(count); - await expect("2022-09-01").assertEqual(birthday) + expect("2022-09-01").assertEqual(birthday) expect(true).assertEqual(resultSet.goToNextRow()) count = await resultSet.getLong(resultSet.getColumnIndex("num count")) birthday = await resultSet.getString(resultSet.getColumnIndex("birthday")) expect(3).assertEqual(count); - await expect("2022-09-02").assertEqual(birthday) + expect("2022-09-02").assertEqual(birthday) expect(false).assertEqual(resultSet.goToNextRow()) resultSet.close(); done(); @@ -102,12 +102,12 @@ describe('rdbStorePredicatesComplexFiledTest', function () { let count = await resultSet.getLong(resultSet.getColumnIndex("numcount")) let birthday = await resultSet.getString(resultSet.getColumnIndex("birthday")) expect(3).assertEqual(count); - await expect("2022-09-02").assertEqual(birthday) + expect("2022-09-02").assertEqual(birthday) expect(true).assertEqual(resultSet.goToNextRow()) count = await resultSet.getLong(resultSet.getColumnIndex("numcount")) birthday = await resultSet.getString(resultSet.getColumnIndex("birthday")) expect(2).assertEqual(count); - await expect("2022-09-01").assertEqual(birthday) + expect("2022-09-01").assertEqual(birthday) expect(false).assertEqual(resultSet.goToNextRow()) resultSet.close(); done(); diff --git a/relational_store/test/js/rdb/unittest/src/RdbstoreStoreExcuteSqlJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstoreStoreExcuteSqlJsunit.test.js index 60c72b01..26d15cd5 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbstoreStoreExcuteSqlJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbstoreStoreExcuteSqlJsunit.test.js @@ -88,7 +88,7 @@ describe('rdbStoreExcuteSqlTest', function () { let querySqlPromise = rdbStore.querySql("SELECT * FROM test") querySqlPromise.then(async (resultSet) => { - await expect(0).assertEqual(resultSet.rowCount) + expect(0).assertEqual(resultSet.rowCount) resultSet.close() done(); }).catch((err) => { @@ -139,7 +139,7 @@ describe('rdbStoreExcuteSqlTest', function () { await rdbStore.executeSql("DELETE FROM test WHERE name = 'lisi'") let querySqlPromise = rdbStore.querySql("SELECT * FROM test") querySqlPromise.then(async (resultSet) => { - await expect(1).assertEqual(resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) resultSet.close() done(); }).catch((err) => { @@ -193,7 +193,7 @@ describe('rdbStoreExcuteSqlTest', function () { predicates.equalTo("name", nameStr) let querySqlPromise = rdbStore.query(predicates) querySqlPromise.then(async (resultSet) => { - await expect(2).assertEqual(resultSet.rowCount) + expect(2).assertEqual(resultSet.rowCount) resultSet.close() }).catch((err) => { expect(null).assertFail(); @@ -203,7 +203,7 @@ describe('rdbStoreExcuteSqlTest', function () { { let executeSqlPromise = rdbStore.executeSql("DELETE FROM test WHERE age = 19 AND name ='" + nameStr + "'") executeSqlPromise.then(async () => { - await console.log(TAG + "executeSql done."); + console.log(TAG + "executeSql done."); }).catch((err) => { expect(null).assertFail(); }) @@ -212,7 +212,7 @@ describe('rdbStoreExcuteSqlTest', function () { { let querySqlPromise = rdbStore.querySql("SELECT * FROM test WHERE name ='" + nameStr + "'") querySqlPromise.then(async (resultSet) => { - await expect(1).assertEqual(resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) expect(true).assertEqual(resultSet.goToFirstRow()) const name = resultSet.getString(resultSet.getColumnIndex("name")) const age = resultSet.getLong(resultSet.getColumnIndex("age")) diff --git a/relational_store/test/js/rdb/unittest/src/RdbstoreUpdateJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstoreUpdateJsunit.test.js index 63339ec7..9834848e 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbstoreUpdateJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbstoreUpdateJsunit.test.js @@ -75,8 +75,8 @@ describe('rdbStoreUpdateTest', function () { let predicates = await new dataRdb.RdbPredicates("test") await predicates.equalTo("id", "1") let ret = await rdbStore.update(valueBucket, predicates) - await expect(1).assertEqual(ret); - await console.log(TAG + "update done: " + ret); + expect(1).assertEqual(ret); + console.log(TAG + "update done: " + ret); predicates = await new dataRdb.RdbPredicates("test") let resultSet = await rdbStore.query(predicates) @@ -88,14 +88,14 @@ describe('rdbStoreUpdateTest', function () { const salary = await resultSet.getDouble(resultSet.getColumnIndex("salary")) const blobType = await resultSet.getBlob(resultSet.getColumnIndex("blobType")) - await expect(1).assertEqual(id); - await expect("lisi").assertEqual(name); - await expect(20).assertEqual(age); - await expect(200.5).assertEqual(salary); - await expect(4).assertEqual(blobType[0]); - await expect(5).assertEqual(blobType[1]); - await expect(6).assertEqual(blobType[2]); - await expect(false).assertEqual(resultSet.goToNextRow()) + expect(1).assertEqual(id); + expect("lisi").assertEqual(name); + expect(20).assertEqual(age); + expect(200.5).assertEqual(salary); + expect(4).assertEqual(blobType[0]); + expect(5).assertEqual(blobType[1]); + expect(6).assertEqual(blobType[2]); + expect(false).assertEqual(resultSet.goToNextRow()) } finally { resultSet.close() resultSet = null @@ -246,8 +246,8 @@ describe('rdbStoreUpdateTest', function () { let predicates = await new dataRdb.RdbPredicates("test") await predicates.equalTo("name", "xiaoming") let ret = await rdbStore.update(valueBucket, predicates) - await expect(1).assertEqual(ret); - await console.log(TAG + "update done: " + ret); + expect(1).assertEqual(ret); + console.log(TAG + "update done: " + ret); predicates = await new dataRdb.RdbPredicates("test") predicates.equalTo("age", 20) @@ -255,7 +255,7 @@ describe('rdbStoreUpdateTest', function () { try { expect(true).assertEqual(resultSet.goToFirstRow()) const name = await resultSet.getString(resultSet.getColumnIndex("name")) - await expect(nameStr).assertEqual(name); + expect(nameStr).assertEqual(name); } finally { resultSet.close() resultSet = null @@ -296,8 +296,8 @@ describe('rdbStoreUpdateTest', function () { let predicates = await new dataRdb.RdbPredicates("test") await predicates.equalTo("name", "xiaohua") let ret = await rdbStore.update(valueBucket, predicates) - await expect(1).assertEqual(ret); - await console.log(TAG + "update done: " + ret); + expect(1).assertEqual(ret); + console.log(TAG + "update done: " + ret); predicates = await new dataRdb.RdbPredicates("test") predicates.equalTo("age", 19) @@ -305,7 +305,7 @@ describe('rdbStoreUpdateTest', function () { try { expect(true).assertEqual(resultSet.goToFirstRow()) const name = await resultSet.getString(resultSet.getColumnIndex("name")) - await expect(nameStr).assertEqual(name); + expect(nameStr).assertEqual(name); } finally { resultSet.close() resultSet = null @@ -346,8 +346,8 @@ describe('rdbStoreUpdateTest', function () { let predicates = await new dataRdb.RdbPredicates("test") await predicates.equalTo("name", "xiaocan") let ret = await rdbStore.update(valueBucket, predicates); - await expect(1).assertEqual(ret); - await console.log(TAG + "update done: " + ret); + expect(1).assertEqual(ret); + console.log(TAG + "update done: " + ret); predicates = await new dataRdb.RdbPredicates("test") predicates.equalTo("age", 21) @@ -355,7 +355,7 @@ describe('rdbStoreUpdateTest', function () { try { expect(true).assertEqual(resultSet.goToFirstRow()) const name = await resultSet.getString(resultSet.getColumnIndex("name")) - await expect(nameStr).assertEqual(name); + expect(nameStr).assertEqual(name); } finally { resultSet.close() resultSet = null diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreDataChange.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreDataChange.test.js index 912f4ce8..448be972 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreDataChange.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreDataChange.test.js @@ -546,5 +546,69 @@ describe('RdbStoreDataChangeTest', function () { console.info(TAG + "************* testRdbStoreDataChange0011 end *************"); }) + /** + * @tc.name Normal case for multi observer + * @tc.number testRdbStoreOn0001 + * @tc.desc 1. Register and cancel registration concurrent testing + * + */ + it('testRdbStoreDataChange0011', 0, async function (done) { + console.info(TAG + "************* testRdbStoreOn0001 start *************"); + function observer() { + console.info(TAG + "observer1"); + }; + for (let i = 0; i < 500; ++i) { + rdbStore.on("concurrencyTest", true, observer) + rdbStore.emit("concurrencyTest"); + rdbStore.off("concurrencyTest", true, observer); + } + done(); + console.info(TAG + "************* testRdbStoreOn0001 end *************"); + }) + + /** + * @tc.name off parameters number error + * @tc.number testRdbStoreDataChange0012 + * @tc.desc UnRegister error parameters number test + * + */ + it('testRdbStoreDataChange0012', 0, async function (done) { + console.info(TAG + "************* testRdbStoreDataChange0012 start *************"); + function observer() { + console.info(TAG + "observer1"); + }; + try { + rdbStore.off("errorParametersNumberTest"); + expect(false).assertTrue() + } catch (err) { + console.error("off parameters error, err: code=" + err.code + " message=" + err.message) + expect(true).assertTrue() + } + done(); + console.info(TAG + "************* testRdbStoreDataChange0012 end *************"); + }) + + /** + * @tc.name on parameters number error + * @tc.number testRdbStoreDataChange0013 + * @tc.desc Register error parameters number test + * + */ + it('testRdbStoreDataChange0013', 0, async function (done) { + console.info(TAG + "************* testRdbStoreDataChange0013 start *************"); + function observer() { + console.info(TAG + "observer1"); + }; + try { + rdbStore.on("errorParametersNumberTest", true); + expect(false).assertTrue() + } catch (err) { + console.error("on parameters error, err: code=" + err.code + " message=" + err.message) + expect(true).assertTrue() + } + done(); + console.info(TAG + "************* testRdbStoreDataChange0013 end *************"); + }) + console.info(TAG + "*************Unit Test End*************"); }) diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreRdExecuteJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreRdExecuteJsunit.test.js index c303f9b3..4682a6aa 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreRdExecuteJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreRdExecuteJsunit.test.js @@ -87,6 +87,72 @@ const vec10 = '[10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,3 '78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,' + '110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137]'; +const clstVec0 = '[0.12,-0.05,0.23,-0.17,0.08,0.31,-0.02,0.14,-0.11,0.25,0.03,-0.19,0.07,0.29,-0.08,0.16,0.21,-0.03,' + + '0.09,-0.14,0.27,0.05,-0.22,0.11,0.18,-0.07,0.13,-0.09,0.24,0.01,-0.16,0.04,0.12,-0.05,0.23,-0.17,0.08,0.31,-0.02,' + + '0.14,-0.11,0.25,0.03,-0.19,0.07,0.29,-0.08,0.16,0.21,-0.03,0.09,-0.14,0.27,0.05,-0.22,0.11,0.18,-0.07,0.13,-0.09,' + + '0.24,0.01,-0.16,0.04,0.12,-0.05,0.23,-0.17,0.08,0.31,-0.02,0.14,-0.11,0.25,0.03,-0.19,0.07,0.29,-0.08,0.16,0.21,' + + '-0.03,0.09,-0.14,0.27,0.05,-0.22,0.11,0.18,-0.07,0.13,-0.09,0.24,0.01,-0.16,0.04,0.12,-0.05,0.23,-0.17,0.08,0.31,' + + '-0.02,0.14,-0.11,0.25,0.03,-0.19,0.07,0.29,-0.08,0.16,0.21,-0.03,0.09,-0.14,0.27,0.05,-0.22,0.11,0.18,-0.07,0.13,' + + '-0.09,0.24,0.01,-0.16,0.04,0.12,-0.05,0.23,-0.17,0.08,0.31,-0.02,0.14,-0.11,0.25,0.03,-0.19,0.07,0.29,-0.08,0.16,' + + '0.21,-0.03,0.09,-0.14,0.27,0.05,-0.22,0.11,0.18,-0.07,0.13,-0.09,0.24,0.01,-0.16,0.04,0.12,-0.05,0.23,-0.17,0.08,' + + '0.31,-0.02,0.14,-0.11,0.25,0.03,-0.19,0.07,0.29,-0.08,0.16,0.21,-0.03,0.09,-0.14,0.27,0.05,-0.22,0.11,0.18,-0.07,' + + '0.13,-0.09,0.24,0.01,-0.16,0.04,0.12,-0.05,0.23,-0.17,0.08,0.31,-0.02,0.14,-0.11,0.25,0.03,-0.19,0.07,0.29,-0.08,' + + '0.16,0.21,-0.03,0.09,-0.14,0.27,0.05,-0.22,0.11,0.18,-0.07,0.13,-0.09,0.24,0.01,-0.16,0.04,0.12,-0.05,0.23,-0.17,' + + '0.08,0.31,-0.02,0.14,-0.11,0.25,0.03,-0.19,0.07,0.29,-0.08,0.16,0.21,-0.03,0.09,-0.14,0.27,0.05,-0.22,0.11,0.18,' + + '-0.07,0.13,-0.09,0.24,0.01,-0.16,0.04]'; +const clstVec1 = '[-0.08,0.15,-0.22,0.07,0.19,-0.03,0.11,-0.14,0.26,0.02,-0.18,0.09,0.13,-0.06,0.21,-0.11,0.04,0.17,' + + '-0.09,0.23,-0.15,0.08,0.12,-0.07,0.24,0.01,-0.19,0.05,0.16,-0.04,0.14,-0.12,-0.08,0.15,-0.22,0.07,0.19,-0.03,' + + '0.11,-0.14,0.26,0.02,-0.18,0.09,0.13,-0.06,0.21,-0.11,0.04,0.17,-0.09,0.23,-0.15,0.08,0.12,-0.07,0.24,0.01,-0.19,' + + '0.05,0.16,-0.04,0.14,-0.12,-0.08,0.15,-0.22,0.07,0.19,-0.03,0.11,-0.14,0.26,0.02,-0.18,0.09,0.13,-0.06,0.21,-0.11,' + + '0.04,0.17,-0.09,0.23,-0.15,0.08,0.12,-0.07,0.24,0.01,-0.19,0.05,0.16,-0.04,0.14,-0.12,-0.08,0.15,-0.22,0.07,0.19,' + + '-0.03,0.11,-0.14,0.26,0.02,-0.18,0.09,0.13,-0.06,0.21,-0.11,0.04,0.17,-0.09,0.23,-0.15,0.08,0.12,-0.07,0.24,0.01,' + + '-0.19,0.05,0.16,-0.04,0.14,-0.12,-0.08,0.15,-0.22,0.07,0.19,-0.03,0.11,-0.14,0.26,0.02,-0.18,0.09,0.13,-0.06,0.21,' + + '-0.11,0.04,0.17,-0.09,0.23,-0.15,0.08,0.12,-0.07,0.24,0.01,-0.19,0.05,0.16,-0.04,0.14,-0.12,-0.08,0.15,-0.22,0.07,' + + '0.19,-0.03,0.11,-0.14,0.26,0.02,-0.18,0.09,0.13,-0.06,0.21,-0.11,0.04,0.17,-0.09,0.23,-0.15,0.08,0.12,-0.07,0.24,' + + '0.01,-0.19,0.05,0.16,-0.04,0.14,-0.12,-0.08,0.15,-0.22,0.07,0.19,-0.03,0.11,-0.14,0.26,0.02,-0.18,0.09,0.13,-0.06,' + + '0.21,-0.11,0.04,0.17,-0.09,0.23,-0.15,0.08,0.12,-0.07,0.24,0.01,-0.19,0.05,0.16,-0.04,0.14,-0.12,-0.08,0.15,-0.22,' + + '0.07,0.19,-0.03,0.11,-0.14,0.26,0.02,-0.18,0.09,0.13,-0.06,0.21,-0.11,0.04,0.17,-0.09,0.23,-0.15,0.08,0.12,-0.07,' + + '0.24,0.01,-0.19,0.05,0.16,-0.04,0.14,-0.12]'; +const clstVec2 = '[0.15,-0.12,0.18,-0.09,0.22,0.04,-0.17,0.11,0.07,-0.14,0.23,-0.06,0.19,0.02,-0.21,0.08,0.13,-0.11,' + + '0.16,-0.07,0.24,0.03,-0.18,0.09,0.12,-0.13,0.17,-0.05,0.25,0.01,-0.19,0.07,0.15,-0.12,0.18,-0.09,0.22,0.04,-0.17,' + + '0.11,0.07,-0.14,0.23,-0.06,0.19,0.02,-0.21,0.08,0.13,-0.11,0.16,-0.07,0.24,0.03,-0.18,0.09,0.12,-0.13,0.17,-0.05,' + + '0.25,0.01,-0.19,0.07,0.15,-0.12,0.18,-0.09,0.22,0.04,-0.17,0.11,0.07,-0.14,0.23,-0.06,0.19,0.02,-0.21,0.08,0.13,' + + '-0.11,0.16,-0.07,0.24,0.03,-0.18,0.09,0.12,-0.13,0.17,-0.05,0.25,0.01,-0.19,0.07,0.15,-0.12,0.18,-0.09,0.22,0.04,' + + '-0.17,0.11,0.07,-0.14,0.23,-0.06,0.19,0.02,-0.21,0.08,0.13,-0.11,0.16,-0.07,0.24,0.03,-0.18,0.09,0.12,-0.13,0.17,' + + '-0.05,0.25,0.01,-0.19,0.07,0.15,-0.12,0.18,-0.09,0.22,0.04,-0.17,0.11,0.07,-0.14,0.23,-0.06,0.19,0.02,-0.21,0.08,' + + '0.13,-0.11,0.16,-0.07,0.24,0.03,-0.18,0.09,0.12,-0.13,0.17,-0.05,0.25,0.01,-0.19,0.07,0.15,-0.12,0.18,-0.09,0.22,' + + '0.04,-0.17,0.11,0.07,-0.14,0.23,-0.06,0.19,0.02,-0.21,0.08,0.13,-0.11,0.16,-0.07,0.24,0.03,-0.18,0.09,0.12,-0.13,' + + '0.17,-0.05,0.25,0.01,-0.19,0.07,0.15,-0.12,0.18,-0.09,0.22,0.04,-0.17,0.11,0.07,-0.14,0.23,-0.06,0.19,0.02,-0.21,' + + '0.08,0.13,-0.11,0.16,-0.07,0.24,0.03,-0.18,0.09,0.12,-0.13,0.17,-0.05,0.25,0.01,-0.19,0.07,0.15,-0.12,0.18,-0.09,' + + '0.22,0.04,-0.17,0.11,0.07,-0.14,0.23,-0.06,0.19,0.02,-0.21,0.08,0.13,-0.11,0.16,-0.07,0.24,0.03,-0.18,0.09,0.12,' + + '-0.13,0.17,-0.05,0.25,0.01,-0.19,0.07]'; +const clstVec3 = '[-0.21,0.08,0.14,-0.19,0.05,0.17,-0.12,0.23,-0.07,0.11,0.16,-0.14,0.09,0.22,-0.04,0.18,-0.11,0.13,' + + '0.15,-0.16,0.07,0.24,-0.02,0.19,-0.09,0.12,0.17,-0.13,0.08,0.21,-0.05,0.15,-0.21,0.08,0.14,-0.19,0.05,0.17,-0.12,' + + '0.23,-0.07,0.11,0.16,-0.14,0.09,0.22,-0.04,0.18,-0.11,0.13,0.15,-0.16,0.07,0.24,-0.02,0.19,-0.09,0.12,0.17,-0.13,' + + '0.08,0.21,-0.05,0.15,-0.21,0.08,0.14,-0.19,0.05,0.17,-0.12,0.23,-0.07,0.11,0.16,-0.14,0.09,0.22,-0.04,0.18,-0.11,' + + '0.13,0.15,-0.16,0.07,0.24,-0.02,0.19,-0.09,0.12,0.17,-0.13,0.08,0.21,-0.05,0.15,-0.21,0.08,0.14,-0.19,0.05,0.17,' + + '-0.12,0.23,-0.07,0.11,0.16,-0.14,0.09,0.22,-0.04,0.18,-0.11,0.13,0.15,-0.16,0.07,0.24,-0.02,0.19,-0.09,0.12,0.17,' + + '-0.13,0.08,0.21,-0.05,0.15,-0.21,0.08,0.14,-0.19,0.05,0.17,-0.12,0.23,-0.07,0.11,0.16,-0.14,0.09,0.22,-0.04,0.18,' + + '-0.11,0.13,0.15,-0.16,0.07,0.24,-0.02,0.19,-0.09,0.12,0.17,-0.13,0.08,0.21,-0.05,0.15,-0.21,0.08,0.14,-0.19,0.05,' + + '0.17,-0.12,0.23,-0.07,0.11,0.16,-0.14,0.09,0.22,-0.04,0.18,-0.11,0.13,0.15,-0.16,0.07,0.24,-0.02,0.19,-0.09,0.12,' + + '0.17,-0.13,0.08,0.21,-0.05,0.15,-0.21,0.08,0.14,-0.19,0.05,0.17,-0.12,0.23,-0.07,0.11,0.16,-0.14,0.09,0.22,-0.04,' + + '0.18,-0.11,0.13,0.15,-0.16,0.07,0.24,-0.02,0.19,-0.09,0.12,0.17,-0.13,0.08,0.21,-0.05,0.15,-0.21,0.08,0.14,-0.19,' + + '0.05,0.17,-0.12,0.23,-0.07,0.11,0.16,-0.14,0.09,0.22,-0.04,0.18,-0.11,0.13,0.15,-0.16,0.07,0.24,-0.02,0.19,-0.09,' + + '0.12,0.17,-0.13,0.08,0.21,-0.05,0.15]'; +const clstVec4 = '[0.07,-0.18,0.12,0.15,-0.09,0.21,-0.14,0.06,0.17,-0.11,0.19,-0.07,0.13,0.16,-0.12,0.08,0.22,' + + '-0.05,0.14,-0.17,0.09,0.18,-0.13,0.11,0.15,-0.08,0.2,-0.04,0.16,-0.14,0.1,0.19,0.07,-0.18,0.12,0.15,-0.09,' + + '0.21,-0.14,0.06,0.17,-0.11,0.19,-0.07,0.13,0.16,-0.12,0.08,0.22,-0.05,0.14,-0.17,0.09,0.18,-0.13,0.11,0.15,' + + '-0.08,0.2,-0.04,0.16,-0.14,0.1,0.19,0.07,-0.18,0.12,0.15,-0.09,0.21,-0.14,0.06,0.17,-0.11,0.19,-0.07,0.13,' + + '0.16,-0.12,0.08,0.22,-0.05,0.14,-0.17,0.09,0.18,-0.13,0.11,0.15,-0.08,0.2,-0.04,0.16,-0.14,0.1,0.19,0.07,' + + '-0.18,0.12,0.15,-0.09,0.21,-0.14,0.06,0.17,-0.11,0.19,-0.07,0.13,0.16,-0.12,0.08,0.22,-0.05,0.14,-0.17,0.09,' + + '0.18,-0.13,0.11,0.15,-0.08,0.2,-0.04,0.16,-0.14,0.1,0.19,0.07,-0.18,0.12,0.15,-0.09,0.21,-0.14,0.06,0.17,' + + '-0.11,0.19,-0.07,0.13,0.16,-0.12,0.08,0.22,-0.05,0.14,-0.17,0.09,0.18,-0.13,0.11,0.15,-0.08,0.2,-0.04,0.16,' + + '-0.14,0.1,0.19,0.07,-0.18,0.12,0.15,-0.09,0.21,-0.14,0.06,0.17,-0.11,0.19,-0.07,0.13,0.16,-0.12,0.08,0.22,' + + '-0.05,0.14,-0.17,0.09,0.18,-0.13,0.11,0.15,-0.08,0.2,-0.04,0.16,-0.14,0.1,0.19,0.07,-0.18,0.12,0.15,-0.09,' + + '0.21,-0.14,0.06,0.17,-0.11,0.19,-0.07,0.13,0.16,-0.12,0.08,0.22,-0.05,0.14,-0.17,0.09,0.18,-0.13,0.11,0.15,' + + '-0.08,0.2,-0.04,0.16,-0.14,0.1,0.19,0.07,-0.18,0.12,0.15,-0.09,0.21,-0.14,0.06,0.17,-0.11,0.19,-0.07,0.13,' + + '0.16,-0.12,0.08,0.22,-0.05,0.14,-0.17,0.09,0.18,-0.13,0.11,0.15,-0.08,0.2,-0.04,0.16,-0.14,0.1,0.19]'; + let isSupportVector = false; let store; let context = ability_featureAbility.getContext() @@ -813,5 +879,211 @@ describe('rdbStoreRdExecuteTest', function () { console.log(TAG + "************* testVectorSubSelectFailed0009 end *************"); }); + /** + * @tc.name testVectorClusterIndexSuccess0001 + * @tc.number SUB_DISTRIBUTEDDATAMGR_RDB_JSVectorStore_ClusterIndex_success_0001 + * @tc.desc create cluster index and insert 10 vec, then query from table and check. + */ + it('testVectorClusterInsertSuccess0001', 0, async function () { + console.log(TAG + "************* testVectorClusterInsertSuccess0001 start *************"); + if (!isSupportVector) { + expect(isSupportVector).assertFalse(); + return; + } + + try { + await store?.execute("create table cluster_vec_10 (id int PRIMARY KEY, repr floatvector(256));"); + } catch (e) { + console.error(TAG + `create table cluster_vec_10 failed. errcode: ${e.code}`); + } + + try { + await store?.execute("create index cluster_index on cluster_vec_10 using IVFCLUSTER(repr COSINE);"); + } catch (e) { + console.error(TAG + `create cluster index failed. errcode: ${e.code}`); + } + + try { + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (0, '${clstVec0}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (1, '${clstVec1}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (2, '${clstVec2}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (3, '${clstVec3}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (4, '${clstVec4}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (5, '${clstVec0}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (6, '${clstVec1}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (7, '${clstVec2}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (8, '${clstVec3}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (9, '${clstVec4}');`); + } catch (e) { + console.error(TAG + `insert face vector in table failed. errcode: ${e.code}`); + } + + const selectSql = `select id, repr, CLUSTER_ID(repr) from cluster_vec_10;`; + const result = await store?.querySql(selectSql); + expect(result?.rowCount).assertEqual(10); + try { + while (result?.goToNextRow()) { + let id = result.getValue(0); + let tmpVec = result.getValue(1); + let clstId = result.getValue(2); + console.log(TAG + "id: " + id?.toString() + "clstId: " + clstId?.toString()); + } + result?.getValue(10); + expect().assertFail(); + result?.close(); + } catch (e) { + console.error(TAG + `testVectorClusterInsertSuccess0001 failed. err: ${JSON.stringify(e)}`); + result?.close(); + expect(14800012 == e.code).assertTrue(); + } + console.log(TAG + "************* testVectorClusterInsertSuccess0001 end *************"); + }); + + /** + * @tc.name testVectorClusterIndexSuccess0002 + * @tc.number SUB_DISTRIBUTEDDATAMGR_RDB_JSVectorStore_ClusterIndex_success_0002 + * @tc.desc insert 10 vec, run cluster, then query from table and check. + */ + it('testVectorClusterIndexSuccess0002', 0, async function () { + console.log(TAG + "************* testVectorClusterIndexSuccess0002 start *************"); + if (!isSupportVector) { + expect(isSupportVector).assertFalse(); + return; + } + + try { + await store?.execute("create table cluster_vec_10 (id int PRIMARY KEY, repr floatvector(256));"); + } catch (e) { + console.error(TAG + `create table cluster_vec_10 failed. errcode: ${e.code}`); + } + + try { + await store?.execute("create index cluster_index on cluster_vec_10 using IVFCLUSTER(repr COSINE);"); + } catch (e) { + console.error(TAG + `create cluster index failed. errcode: ${e.code}`); + } + + try { + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (0, '${clstVec0}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (1, '${clstVec1}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (2, '${clstVec2}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (3, '${clstVec3}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (4, '${clstVec4}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (5, '${clstVec0}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (6, '${clstVec1}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (7, '${clstVec2}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (8, '${clstVec3}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (9, '${clstVec4}');`); + } catch (e) { + console.error(TAG + `insert face vector in table failed. errcode: ${e.code}`); + } + + try { + await store?.execute("PRAGMA CLUSTER_RUN cluster_vec_10.cluster_index;"); + await new Promise(resolve => setTimeout(resolve, 50)); // wait 50ms for cluster build exec + } catch (e) { + console.error(TAG + `run cluster build failed. errcode: ${e.code}`); + } + + const selectSql = `select id, repr, CLUSTER_ID(repr) from cluster_vec_10;`; + const result = await store?.querySql(selectSql); + expect(result?.rowCount).assertEqual(10); + try { + while (result?.goToNextRow()) { + let id = result.getValue(0); + let tmpVec = result.getValue(1); + let clstId = result.getValue(2); + console.log(TAG + "id: " + id?.toString() + "clstId: " + clstId?.toString()); + } + result?.getValue(10); + expect().assertFail(); + result?.close(); + } catch (e) { + console.error(TAG + `testVectorClusterIndexSuccess0002 failed. err: ${JSON.stringify(e)}`); + result?.close(); + expect(14800012 == e.code).assertTrue(); + } + console.log(TAG + "************* testVectorClusterIndexSuccess0002 end *************"); + }); + + /** + * @tc.name testVectorClusterIndexSuccess0003 + * @tc.number SUB_DISTRIBUTEDDATAMGR_RDB_JSVectorStore_ClusterIndex_success_0003 + * @tc.desc insert 5 vec, run cluster, then insert 5 vec, run cluster again. + */ + it('testVectorClusterIndexSuccess0003', 0, async function () { + console.log(TAG + "************* testVectorClusterIndexSuccess0003 start *************"); + if (!isSupportVector) { + expect(isSupportVector).assertFalse(); + return; + } + + try { + await store?.execute("create table cluster_vec_10 (id int PRIMARY KEY, repr floatvector(256));"); + } catch (e) { + console.error(TAG + `create table cluster_vec_10 failed. errcode: ${e.code}`); + } + + try { + await store?.execute("create index cluster_index on using IVFCLUSTER(repr COSINE);"); + } catch (e) { + console.error(TAG + `create cluster index failed. errcode: ${e.code}`); + } + + try { + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (0, '${clstVec0}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (1, '${clstVec1}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (2, '${clstVec2}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (3, '${clstVec3}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (4, '${clstVec4}');`); + } catch (e) { + console.error(TAG + `insert face vector in table failed. errcode: ${e.code}`); + } + + try { + await store?.execute("PRAGMA CLUSTER_RUN cluster_vec_10.cluster_index;"); + await new Promise(resolve => setTimeout(resolve, 50)); // wait 50ms for cluster build exec + } catch (e) { + console.error(TAG + `run cluster build failed. errcode: ${e.code}`); + } + + try { + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (5, '${clstVec0}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (6, '${clstVec1}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (7, '${clstVec2}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (8, '${clstVec3}');`); + await store?.execute(`INSERT INTO cluster_vec_10 VALUES (9, '${clstVec4}');`); + } catch (e) { + console.error(TAG + `insert face vector in table failed. errcode: ${e.code}`); + } + + try { + await store?.execute("PRAGMA CLUSTER_RUN cluster_vec_10.cluster_index;"); + await new Promise(resolve => setTimeout(resolve, 50)); // wait 50ms for cluster build exec + } catch (e) { + console.error(TAG + `run cluster build failed. errcode: ${e.code}`); + } + + const selectSql = `select id, repr, CLUSTER_ID(repr) from cluster_vec_10;`; + const result = await store?.querySql(selectSql); + expect(result?.rowCount).assertEqual(10); + try { + while (result?.goToNextRow()) { + let id = result.getValue(0); + let tmpVec = result.getValue(1); + let clstId = result.getValue(2); + console.log(TAG + "id: " + id?.toString() + "clstId: " + clstId?.toString()); + } + result?.getValue(10); + expect().assertFail(); + result?.close(); + } catch (e) { + console.error(TAG + `testVectorClusterIndexSuccess0003 failed. err: ${JSON.stringify(e)}`); + result?.close(); + expect(14800012 == e.code).assertTrue(); + } + console.log(TAG + "************* testVectorClusterIndexSuccess0003 end *************"); + }); + console.log(TAG + "*************Unit Test End*************"); }) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreReadOnlyJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreReadOnlyJsunit.test.js index ede3df40..b904e98a 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreReadOnlyJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreReadOnlyJsunit.test.js @@ -51,6 +51,7 @@ describe('rdbStoreReadOnlyTest', function () { try { await relationalStore.deleteRdbStore(context, STORE_CONFIG); let rdbStore = await relationalStore.getRdbStore(context, STORE_CONFIG); + expect(rdbStore === null).assertFalse(); const CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT, age INTEGER, salary REAL, blobType BLOB)"; @@ -69,6 +70,7 @@ describe('rdbStoreReadOnlyTest', function () { beforeEach(async function () { store = await relationalStore.getRdbStore(context, STORE_CONFIG2); + expect(rdbStore === null).assertFalse(); console.info(TAG + 'beforeEach'); }) diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetJsunit.test.js index 9607f421..abc73477 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetJsunit.test.js @@ -812,28 +812,6 @@ describe('rdbResultSetTest', function () { console.log(TAG + "************* testGoToFirstRow0003 end *************"); }) - /** - * @tc.name resultSet goToFirstRow with no result test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0103 - * @tc.desc resultSet goToFirstRow with no result test - */ - it('testGoToFirstRow0004', 0, async function (done) { - console.log(TAG + "************* testGoToFirstRow0004 start *************"); - - let predicates = await new data_relationalStore.RdbPredicates("test") - let resultSet = await rdbStore.query(predicates) - resultSet.close() - try { - resultSet.goToFirstRow() - } catch (e) { - expect(e.code).assertFail("14800014"); - } - - resultSet = null - done(); - console.log(TAG + "************* testGoToFirstRow0004 end *************"); - }) - /** * @tc.name resultSet goToLastRow test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0110 @@ -891,27 +869,6 @@ describe('rdbResultSetTest', function () { }) - /** - * @tc.name resultSet goToLastRow with no result test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0113 - * @tc.desc resultSet goToLastRow with no result test - */ - it('testGoToLastRow0004', 0, async function (done) { - console.log(TAG + "************* testGoToLastRow0004 start *************"); - let predicates = await new data_relationalStore.RdbPredicates("test") - predicates.equalTo("name", "wangwu"); - let resultSet = await rdbStore.query(predicates) - resultSet.close() - try { - resultSet.goToLastRow() - } catch (error) { - expect(error.code).assertEqual("14800014") - } - resultSet = null; - done(); - console.log(TAG + "************* testGoToLastRow0004 end *************"); - }) - /** * @tc.name resultSet goToNextRow test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0120 @@ -997,29 +954,6 @@ describe('rdbResultSetTest', function () { }) - /** - * @tc.name resultSet goToNextRow with no result test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0124 - * @tc.desc resultSet goToNextRow with no result test - */ - it('testGoToNextRow0005', 0, async function (done) { - console.log(TAG + "************* testGoToNextRow0005 start *************"); - - let predicates = await new data_relationalStore.RdbPredicates("test") - let resultSet = await rdbStore.query(predicates) - resultSet.close() - try { - resultSet.goToNextRow() - } catch (error) { - expect(error.code).assertEqual("14800014") - } - - resultSet = null; - done(); - console.log(TAG + "************* testGoToNextRow0005 end *************"); - - }) - /** * @tc.name resultSet goToPreviousRow test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0130 @@ -1104,28 +1038,6 @@ describe('rdbResultSetTest', function () { }) - /** - * @tc.name resultSet goToPreviousRow with no result test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0134 - * @tc.desc resultSet goToPreviousRow with no result test - */ - it('testGoToPreviousRow0005', 0, async function (done) { - console.log(TAG + "************* testGoToPreviousRow0005 start *************"); - - let predicates = await new data_relationalStore.RdbPredicates("test") - let resultSet = await rdbStore.query(predicates) - resultSet.close() - try { - resultSet.goToPreviousRow() - } catch (error) { - expect(error).assertEqual("14800014") - } - resultSet = null; - done(); - console.log(TAG + "************* testGoToPreviousRow0005 end *************"); - - }) - /** * @tc.name resultSet goTo test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0140 @@ -1215,31 +1127,6 @@ describe('rdbResultSetTest', function () { }) - /** - * @tc.name resultSet goTo after last row test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0144 - * @tc.desc resultSet goTo after last row test - */ - it('testGoTo0005', 0, async function (done) { - console.log(TAG + "************* testGoTo0005 start *************"); - - let predicates = await new data_relationalStore.RdbPredicates("test") - predicates.equalTo("name", "wangwu"); - let resultSet = await rdbStore.query(predicates) - resultSet.close() - - try { - resultSet.goTo(1) - } catch (error) { - expect(error.code).assertEqual("14800014") - } - - resultSet = null; - done(); - console.log(TAG + "************* testGoTo0005 end *************"); - - }) - /** * @tc.name resultSet goToRow test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0150 @@ -1308,31 +1195,6 @@ describe('rdbResultSetTest', function () { }) - /** - * @tc.name resultSet goToRow with no result test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0154 - * @tc.desc resultSet goToRow with no result test - */ - it('testGoToRow0005', 0, async function (done) { - console.log(TAG + "************* testGoToRow0005 start *************"); - - let predicates = await new data_relationalStore.RdbPredicates("test") - predicates.equalTo("name", "wangwu"); - let resultSet = await rdbStore.query(predicates) - - resultSet.close() - try { - resultSet.goToRow(1) - } catch (error) { - expect(error.code).assertEqual("14800014") - } - - resultSet = null; - done(); - console.log(TAG + "************* testGoToRow0005 end *************"); - - }) - /** * @tc.name resultSet goToRow after last row test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0153 @@ -1853,28 +1715,6 @@ describe('rdbResultSetTest', function () { }) - /** - * @tc.name resultSet getColumnIndex test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0204 - * @tc.desc resultSet getColumnIndex test - */ - it('testGetColumnIndex0005', 0, async function (done) { - console.log(TAG + "************* testGetColumnIndex0005 start *************"); - - let predicates = await new data_relationalStore.RdbPredicates("test") - let resultSet = await rdbStore.query(predicates) - resultSet.close() - try { - resultSet.getColumnIndex("dataX") - } catch (error) { - expect(error.code).assertEqual("14800014") - } - resultSet = null; - done(); - console.log(TAG + "************* testGetColumnIndex0005 end *************"); - - }) - /** * @tc.name resultSet getColumnName test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0210 @@ -1959,28 +1799,6 @@ describe('rdbResultSetTest', function () { }) - /** - * @tc.name resultSet getColumnName test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0214 - * @tc.desc resultSet getColumnName test - */ - it('testGetColumnName0005', 0, async function (done) { - console.log(TAG + "************* testGetColumnName0005 start *************"); - - let predicates = await new data_relationalStore.RdbPredicates("test") - let resultSet = await rdbStore.query(predicates) - resultSet.close() - try { - resultSet.getColumnName(10) - } catch (error) { - expect(error.code).assertEqual("14800014") - } - resultSet = null; - done(); - console.log(TAG + "************* testGetColumnName0005 end *************"); - - }) - /** * @tc.name resultSet close test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0220 diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreStatisticsJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreStatisticsJsunit.test.js index 79318b0a..1e87c3a3 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreStatisticsJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreStatisticsJsunit.test.js @@ -280,7 +280,7 @@ describe('RdbStoreStatisticsTest', function () { console.info(TAG + "************* testRdbStoreStatistics0006 start *************"); try { rdbStore.on('statistics', (SqlExeInfo) => { - expect().assertFail(); + expect('INSERT INTO test(age,blobType,salary) VALUES (?,?,?)').assertEqual(SqlExeInfo.sql[0]); done(); }) } catch (err) { @@ -300,7 +300,6 @@ describe('RdbStoreStatisticsTest', function () { } catch (error) { expect(14800032).assertEqual(error.code); console.error(TAG + `insert fail, code:${error.code}, message: ${error.message}`); - done(); } console.info(TAG + "************* testRdbStoreStatistics0006 end *************"); }) diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransInsertJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransInsertJsunit.test.js deleted file mode 100644 index 4326a934..00000000 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransInsertJsunit.test.js +++ /dev/null @@ -1,945 +0,0 @@ -/* - * 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. - */ - -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' -import data_relationalStore from '@ohos.data.relationalStore' -import ability_featureAbility from '@ohos.ability.featureAbility' - -var context = ability_featureAbility.getContext() - -const TAG = "[RELATIONAL_STORE_TRANSACTION_JSKITS_TEST]" -const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + - "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; - -const STORE_CONFIG = { - name: "TransactionTest.db", - securityLevel: data_relationalStore.SecurityLevel.S3, -} - -var rdbStore = undefined; - -describe('rdbStoreTransactionJsunitTest', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll') - rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); - await rdbStore.executeSql(CREATE_TABLE_TEST, null); - }) - - beforeEach(async function () { - console.info(TAG + 'beforeEach') - - }) - - afterEach(async function () { - console.info(TAG + 'afterEach') - await rdbStore.executeSql("DELETE FROM test"); - }) - - afterAll(async function () { - console.info(TAG + 'afterAll') - rdbStore = null - await data_relationalStore.deleteRdbStore(context, "TransactionTest.db"); - }) - - console.log(TAG + "*************Unit Test Begin*************"); - - - it('testRdbTransInsert0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsert0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsert0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsert0001 failed"); - } - - console.log(TAG + "************* testRdbTransInsert0001 end *************"); - done(); - }) - - it('testRdbTransInsert0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsert0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsert0002 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsert0002 failed"); - } - - console.log(TAG + "************* testRdbTransInsert0002 end *************"); - done(); - }) - - it('testRdbTransInsert0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsert0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsert0003 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsert0003 failed"); - } - - console.log(TAG + "************* testRdbTransInsert0003 end *************"); - done(); - }) - - it('testRdbTransInsert0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsert0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsert0011 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsert0011 failed"); - } - - console.log(TAG + "************* testRdbTransInsert0011 end *************"); - done(); - }) - - it('testRdbTransInsert0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsert0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsert0012 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsert0012 failed"); - } - - console.log(TAG + "************* testRdbTransInsert0012 end *************"); - done(); - }) - - it('testRdbTransInsert0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsert0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsert0013 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsert0013 failed"); - } - - console.log(TAG + "************* testRdbTransInsert0013 end *************"); - done(); - }) - - it('testRdbTransInsertSync0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsertSync0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = rdbTrans.insertSync("test", valueBucket); - expect(1).assertEqual(rowId); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsertSync0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsertSync0001 failed"); - } - - console.log(TAG + "************* testRdbTransInsertSync0001 end *************"); - done(); - }) - - it('testRdbTransInsertSync0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsertSync0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = rdbTrans.insertSync("test", valueBucket); - expect(1).assertEqual(rowId); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsertSync0002 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsertSync0002 failed"); - } - - console.log(TAG + "************* testRdbTransInsertSync0002 end *************"); - done(); - }) - - it('testRdbTransInsertSync0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsertSync0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = rdbTrans.insertSync("test", valueBucket); - expect(1).assertEqual(rowId); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsertSync0003 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsertSync0003 failed"); - } - - console.log(TAG + "************* testRdbTransInsertSync0003 end *************"); - done(); - }) - - it('testRdbTransInsertSync0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsertSync0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = rdbTrans.insertSync("test", valueBucket); - expect(1).assertEqual(rowId); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsertSync0011 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsertSync0011 failed"); - } - - console.log(TAG + "************* testRdbTransInsertSync0011 end *************"); - done(); - }) - - it('testRdbTransInsertSync0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsertSync0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = rdbTrans.insertSync("test", valueBucket); - expect(1).assertEqual(rowId); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsertSync0012 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsertSync0012 failed"); - } - - console.log(TAG + "************* testRdbTransInsertSync0012 end *************"); - done(); - }) - - it('testRdbTransInsertSync0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransInsertSync0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = rdbTrans.insertSync("test", valueBucket); - expect(1).assertEqual(rowId); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransInsertSync0013 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransInsertSync0013 failed"); - } - - console.log(TAG + "************* testRdbTransInsertSync0013 end *************"); - done(); - }) - - it('testRdbTransBatchInsert0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsert0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = await rdbTrans.batchInsert("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsert0001 result count " + resultSet.rowCount); - expect(100).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsert0001 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsert0001 end *************"); - done(); - }) - - it('testRdbTransBatchInsert0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsert0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = await rdbTrans.batchInsert("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsert0002 result count " + resultSet.rowCount); - expect(100).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsert0002 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsert0002 end *************"); - done(); - }) - - it('testRdbTransBatchInsert0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsert0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = await rdbTrans.batchInsert("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsert0003 result count " + resultSet.rowCount); - expect(100).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsert0003 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsert0003 end *************"); - done(); - }) - - it('testRdbTransBatchInsert0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsert0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = await rdbTrans.batchInsert("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsert0011 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsert0011 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsert0011 end *************"); - done(); - }) - - it('testRdbTransBatchInsert0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsert0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = await rdbTrans.batchInsert("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsert0012 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsert0012 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsert0012 end *************"); - done(); - }) - - it('testRdbTransBatchInsert0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsert0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = await rdbTrans.batchInsert("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsert0013 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsert0013 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsert0013 end *************"); - done(); - }) - - it('testRdbTransBatchInsertSync0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsertSync0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsertSync0001 result count " + resultSet.rowCount); - expect(100).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsertSync0001 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsertSync0001 end *************"); - done(); - }) - - it('testRdbTransBatchInsertSync0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsertSync0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsertSync0002 result count " + resultSet.rowCount); - expect(100).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsertSync0002 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsertSync0002 end *************"); - done(); - }) - - it('testRdbTransBatchInsertSync0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsertSync0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsertSync0003 result count " + resultSet.rowCount); - expect(100).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsertSync0003 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsertSync0003 end *************"); - done(); - }) - - it('testRdbTransBatchInsertSync0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsertSync0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsertSync0011 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsertSync0011 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsertSync0011 end *************"); - done(); - }) - - it('testRdbTransBatchInsertSync0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsertSync0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsertSync0012 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsertSync0012 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsertSync0012 end *************"); - done(); - }) - - it('testRdbTransBatchInsertSync0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransBatchInsertSync0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBuckets = new Array(100).fill(0).map(() => { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - return valueBucket; - }) - const rowCount = rdbTrans.batchInsertSync("test", valueBuckets); - expect(rowCount).assertEqual(100); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransBatchInsertSync0013 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransBatchInsertSync0013 failed"); - } - - console.log(TAG + "************* testRdbTransBatchInsertSync0013 end *************"); - done(); - }) - - it('testRdbTransUpdate0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdate0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbTrans.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.update({ age: 20 }, updatePredicates); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdate0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(20); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdate0001 failed"); - } - - console.log(TAG + "************* testRdbTransUpdate0001 end *************"); - done(); - }) - - it('testRdbTransUpdate0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdate0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbTrans.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.update({ age: 20 }, updatePredicates); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdate0002 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(20); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdate0002 failed"); - } - - console.log(TAG + "************* testRdbTransUpdate0002 end *************"); - done(); - }) - - it('testRdbTransUpdate0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdate0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbTrans.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.update({ age: 20 }, updatePredicates); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdate0003 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(20); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdate0003 failed"); - } - - console.log(TAG + "************* testRdbTransUpdate0003 end *************"); - done(); - }) - - console.log(TAG + "*************Unit Test End*************"); -}) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransJsunit.test.js deleted file mode 100644 index 4d150faa..00000000 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransJsunit.test.js +++ /dev/null @@ -1,1986 +0,0 @@ -/* - * 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. - */ - -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' -import data_relationalStore from '@ohos.data.relationalStore' -import ability_featureAbility from '@ohos.ability.featureAbility' - -var context = ability_featureAbility.getContext() - -const TAG = "[RELATIONAL_STORE_TRANSACTION_JSKITS_TEST]" -const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + - "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; - -const STORE_CONFIG = { - name: "TransactionTest.db", - securityLevel: data_relationalStore.SecurityLevel.S3, -} - -var rdbStore = undefined; - -async function insertInThread(context, transType, insertCount = 1) { - const TAG = "[RELATIONAL_STORE_JS_KITS_TEST]" - let rdbTrans; - try { - rdbTrans = await rdbStore.createTransaction({ - transactionType: transType - }); - console.log(TAG + 'insertInThread after createTrans'); - - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(insertCount).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }); - const resultCount = await rdbTrans.batchInsert("test", valueBuckets); - await rdbTrans.commit(); - console.log(TAG + 'insertInThread after commit'); - return resultCount; - } catch (err) { - if (rdbTrans) { - rdbTrans.rollback(); - } - console.error(TAG + "************* testRdbTransInsert error thread insert *************"); - console.error(TAG + JSON.stringify(err)); - return err.code; - } -} - -async function queryInThread(context, transType, querySql) { - const TAG = "[RELATIONAL_STORE_JS_KITS_TEST]" - let rdbTrans; - try { - rdbTrans = await rdbStore.createTransaction({ - transactionType: transType - }); - - const resultSet = await rdbTrans.querySql(querySql); - const rowCount = resultSet.rowCount; - - await rdbTrans.commit(); - return rowCount; - } catch (err) { - if (rdbTrans) { - rdbTrans.rollback(); - } - console.error(TAG + "************* testRdbTransInsert error thread insert *************"); - console.error(TAG + JSON.stringify(err)); - return err.code; - } -} - -describe('rdbStoreTransactionJsunitTest', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll') - rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); - await rdbStore.executeSql(CREATE_TABLE_TEST, null); - }) - - beforeEach(async function () { - console.info(TAG + 'beforeEach') - - }) - - afterEach(async function () { - console.info(TAG + 'afterEach') - await rdbStore.executeSql("DELETE FROM test"); - }) - - afterAll(async function () { - console.info(TAG + 'afterAll') - rdbStore = null - await data_relationalStore.deleteRdbStore(context, "TransactionTest.db"); - }) - - console.log(TAG + "*************Unit Test Begin*************"); - - it('testRdbTransUpdate0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdate0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbStore.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.update({ age: 20 }, updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdate0011 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(18); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdate0011 failed"); - } - - console.log(TAG + "************* testRdbTransUpdate0011 end *************"); - done(); - }) - - it('testRdbTransUpdate0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdate0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbStore.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.update({ age: 20 }, updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdate0012 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(18); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdate0012 failed"); - } - - console.log(TAG + "************* testRdbTransUpdate0012 end *************"); - done(); - }) - - it('testRdbTransUpdate0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdate0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbStore.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.update({ age: 20 }, updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdate0013 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(18); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdate0013 failed"); - } - - console.log(TAG + "************* testRdbTransUpdate0013 end *************"); - done(); - }) - - it('testRdbTransUpdateSync0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdateSync0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbTrans.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - rdbTrans.updateSync({ age: 20 }, updatePredicates); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdateSync0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(20); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdateSync0001 failed"); - } - - console.log(TAG + "************* testRdbTransUpdateSync0001 end *************"); - done(); - }) - - it('testRdbTransUpdateSync0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdateSync0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbTrans.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - rdbTrans.updateSync({ age: 20 }, updatePredicates); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdateSync0002 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(20); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdateSync0002 failed"); - } - - console.log(TAG + "************* testRdbTransUpdateSync0002 end *************"); - done(); - }) - - it('testRdbTransUpdateSync0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdateSync0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbTrans.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - rdbTrans.updateSync({ age: 20 }, updatePredicates); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdateSync0003 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(20); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdateSync0003 failed"); - } - - console.log(TAG + "************* testRdbTransUpdateSync0003 end *************"); - done(); - }) - - it('testRdbTransUpdateSync0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdateSync0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbStore.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - rdbTrans.updateSync({ age: 20 }, updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdateSync0011 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(18); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdateSync0011 failed"); - } - - console.log(TAG + "************* testRdbTransUpdateSync0011 end *************"); - done(); - }) - - it('testRdbTransUpdateSync0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdateSync0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbStore.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - rdbTrans.updateSync({ age: 20 }, updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdateSync0012 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(18); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdateSync0012 failed"); - } - - console.log(TAG + "************* testRdbTransUpdateSync0012 end *************"); - done(); - }) - - it('testRdbTransUpdateSync0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransUpdateSync0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - const rowId = await rdbStore.insert("test", valueBucket); - expect(rowId).assertEqual(1); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - rdbTrans.updateSync({ age: 20 }, updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransUpdateSync0013 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - const rowData = resultSet.getRow(); - expect(rowData['age']).assertEqual(18); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransUpdateSync0013 failed"); - } - - console.log(TAG + "************* testRdbTransUpdateSync0013 end *************"); - done(); - }) - - it('testRdbTransDelete0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransDelete0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = await rdbTrans.delete(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDelete0001 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDelete0001 failed"); - } - - console.log(TAG + "************* testRdbTransDelete0001 end *************"); - done(); - }) - - it('testRdbTransDelete0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransDelete0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = await rdbTrans.delete(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDelete0002 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDelete0002 failed"); - } - - console.log(TAG + "************* testRdbTransDelete0002 end *************"); - done(); - }) - - it('testRdbTransDelete0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransDelete0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = await rdbTrans.delete(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDelete0003 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDelete0003 failed"); - } - - console.log(TAG + "************* testRdbTransDelete0003 end *************"); - done(); - }) - - it('testRdbTransDelete0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransDelete0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.delete(updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDelete0011 result count " + resultSet.rowCount); - expect(3).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDelete0011 failed"); - } - - console.log(TAG + "************* testRdbTransDelete0011 end *************"); - done(); - }) - - it('testRdbTransDelete0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransDelete0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.delete(updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDelete0012 result count " + resultSet.rowCount); - expect(3).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDelete0012 failed"); - } - - console.log(TAG + "************* testRdbTransDelete0012 end *************"); - done(); - }) - - it('testRdbTransDelete0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransDelete0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - await rdbTrans.delete(updatePredicates); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDelete0013 result count " + resultSet.rowCount); - expect(3).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDelete0013 failed"); - } - - console.log(TAG + "************* testRdbTransDelete0013 end *************"); - done(); - }) - - it('testRdbTransDeleteSync0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransDeleteSync0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = rdbTrans.deleteSync(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDeleteSync0001 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDeleteSync0001 failed"); - } - - console.log(TAG + "************* testRdbTransDeleteSync0001 end *************"); - done(); - }) - - it('testRdbTransDeleteSync0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransDeleteSync0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = rdbTrans.deleteSync(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDeleteSync0002 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDeleteSync0002 failed"); - } - - console.log(TAG + "************* testRdbTransDeleteSync0002 end *************"); - done(); - }) - - it('testRdbTransDeleteSync0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransDeleteSync0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = rdbTrans.deleteSync(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDeleteSync0003 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.goToFirstRow(); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDeleteSync0003 failed"); - } - - console.log(TAG + "************* testRdbTransDeleteSync0003 end *************"); - done(); - }) - - it('testRdbTransDeleteSync0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransDeleteSync0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = rdbTrans.deleteSync(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDeleteSync0011 result count " + resultSet.rowCount); - expect(3).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDeleteSync0011 failed"); - } - - console.log(TAG + "************* testRdbTransDeleteSync0011 end *************"); - done(); - }) - - it('testRdbTransDeleteSync0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransDeleteSync0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = rdbTrans.deleteSync(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDeleteSync0012 result count " + resultSet.rowCount); - expect(3).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDeleteSync0012 failed"); - } - - console.log(TAG + "************* testRdbTransDeleteSync0012 end *************"); - done(); - }) - - it('testRdbTransDeleteSync0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransDeleteSync0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(3).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rowId = await rdbStore.batchInsert("test", valueBuckets); - expect(rowId).assertEqual(3); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const updatePredicates = new data_relationalStore.RdbPredicates("test"); - updatePredicates.equalTo('name', 'lisi'); - const deleteRows = rdbTrans.deleteSync(updatePredicates); - expect(deleteRows).assertEqual(3); - await rdbTrans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransDeleteSync0013 result count " + resultSet.rowCount); - expect(3).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransDeleteSync0013 failed"); - } - - console.log(TAG + "************* testRdbTransDeleteSync0013 end *************"); - done(); - }) - - it('testRdbTransQuery0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransQuery0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbTrans.query(predicates); - console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - await rdbTrans.commit(); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransQuery0001 failed"); - } - - console.log(TAG + "************* testRdbTransQuery0001 end *************"); - done(); - }) - - it('testRdbTransQuery0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransQuery0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbTrans.query(predicates); - console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - await rdbTrans.commit(); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransQuery0002 failed"); - } - - console.log(TAG + "************* testRdbTransQuery0002 end *************"); - done(); - }) - - it('testRdbTransQuery0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransQuery0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbTrans.query(predicates); - console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - await rdbTrans.commit(); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransQuery0003 failed"); - } - - console.log(TAG + "************* testRdbTransQuery0003 end *************"); - done(); - }) - - it('testRdbTransQuery0011', 0, async (done) => { - console.log(TAG + "************* testRdbTransQuery0011 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbTrans.querySync(predicates); - console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - await rdbTrans.commit(); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransQuery0011 failed"); - } - - console.log(TAG + "************* testRdbTransQuery0011 end *************"); - done(); - }) - - it('testRdbTransQuery0012', 0, async (done) => { - console.log(TAG + "************* testRdbTransQuery0012 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbTrans.querySync(predicates); - console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - await rdbTrans.commit(); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransQuery0012 failed"); - } - - console.log(TAG + "************* testRdbTransQuery0012 end *************"); - done(); - }) - - it('testRdbTransQuery0013', 0, async (done) => { - console.log(TAG + "************* testRdbTransQuery0013 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbTrans.querySync(predicates); - console.log(TAG + "testRdbTransQuery0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - await rdbTrans.commit(); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransQuery0013 failed"); - } - - console.log(TAG + "************* testRdbTransQuery0013 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0001 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0001 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0001 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0002 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0002 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0002 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0003 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0003 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0003 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0004', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0004 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - console.log(TAG + "before second trans create"); - const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); - console.log(TAG + "after second trans create"); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - console.log(TAG + "before query predicates create"); - let predicates = new data_relationalStore.RdbPredicates("test"); - console.log(TAG + "after query predicates create"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0004 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0004 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0004 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0005', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0005 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0005 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0005 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0005 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0006', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0006 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0006 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0006 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0006 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0007', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0007 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await insertInThread(context, data_relationalStore.TransactionType.DEFERRED, 10); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0007 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0007 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0007 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0008', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0008 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await insertInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 10); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0008 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0008 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0008 end *************"); - done(); - }) - - it('testRdbTransSameThreadInsert0009', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadInsert0009 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await insertInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 10); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadInsert0009 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadInsert0009 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadInsert0009 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0001 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const rowCount = await queryInThread(context, data_relationalStore.TransactionType.DEFERRED, 'select * from test'); - expect(rowCount).assertEqual(0); - - await rdbTrans.commit(); - - { - const rowCount = await queryInThread(context, data_relationalStore.TransactionType.DEFERRED, 'select * from test'); - expect(rowCount).assertEqual(10); - } - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0001 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0001 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0001 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0002', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0002 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const rowCount = await queryInThread(context, data_relationalStore.TransactionType.DEFERRED, 'select * from test'); - expect(rowCount).assertEqual(0); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0002 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0002 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0002 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0003 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - - await rdbStore.batchInsert('test', valueBuckets); - - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const rowCount = await queryInThread(context, data_relationalStore.TransactionType.DEFERRED, 'select * from test'); - expect(rowCount).assertEqual(10); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0003 result count " + resultSet.rowCount); - expect(20).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0003 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0003 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0004', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0004 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await queryInThread(context, data_relationalStore.TransactionType.IMMEDIATE, 'select * from test'); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0004 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0004 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0004 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0005', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0005 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await queryInThread(context, data_relationalStore.TransactionType.IMMEDIATE, 'select * from test'); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0005 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0005 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0005 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0006', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0006 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await queryInThread(context, data_relationalStore.TransactionType.IMMEDIATE, 'select * from test'); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0006 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0006 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0006 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0007', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0007 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await queryInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 'select * from test'); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0007 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0007 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0007 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0008', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0008 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await queryInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 'select * from test'); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0008 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0008 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0008 end *************"); - done(); - }) - - it('testRdbTransSameThreadQuery0009', 0, async (done) => { - console.log(TAG + "************* testRdbTransSameThreadQuery0009 start *************"); - try { - const u8 = new Uint8Array([1, 2, 3]); - const valueBuckets = new Array(10).fill(0).map(() => { - return { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - }) - const rdbTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - - const insertCount = await rdbTrans.batchInsert('test', valueBuckets); - expect(insertCount).assertEqual(10); - - const errCode = await queryInThread(context, data_relationalStore.TransactionType.EXCLUSIVE, 'select * from test'); - expect(errCode).assertEqual(14800024); - - await rdbTrans.commit(); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = rdbStore.querySync(predicates); - console.log(TAG + "testRdbTransSameThreadQuery0009 result count " + resultSet.rowCount); - expect(10).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransSameThreadQuery0009 failed"); - } - - console.log(TAG + "************* testRdbTransSameThreadQuery0009 end *************"); - done(); - }) - - /** - * @tc.name rdb transaction insert test - * @tc.number testRdbTransactionInsert0001 - * @tc.desc rdb transaction insert & commit, the result comes out is 3 items; - */ - it('testRdbTransactionInsert0001', 0, async (done) => { - console.log(TAG + "************* testRdbStoreInsert0001 start *************"); - const u8 = new Uint8Array([1, 2, 3]); - try { - const rdbTrans = await rdbStore.createTransaction(); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await rdbTrans.insert("test", valueBucket); - await rdbTrans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransactionInsert0001 result count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail(); - console.log(TAG + "testRdbTransactionInsert0001 failed"); - } - done(); - console.log(TAG + "************* testRdbTransactionInsert0001 end *************"); - }) - - /** - * @tc.name rdb transaction insert test - * @tc.number testRdbTransactionInsert0001 - * @tc.desc rdb transaction insert & commit, the result comes out is 3 items; - */ - it('testRdbTransactionInsert0002', 0, async (done) => { - console.log(TAG + "************* testRdbStoreInsert0002 start *************"); - const u8 = new Uint8Array([1, 2, 3]); - try { - const trans = await rdbStore.createTransaction(); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await trans.insert("test", valueBucket); - const valueBucket1 = { - "name": "zhangsan", - "age": 20, - "salary": 9.5, - "blobType": u8, - }; - await trans.insert("test", valueBucket1); - const valueBucket2 = { - "name": "wangwu", - "age": 16, - "salary": 99, - "blobType": u8, - }; - await trans.insert("test", valueBucket2); - await trans.commit(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - expect(3).assertEqual(resultSet.rowCount); - resultSet.close(); - } catch (e) { - expect(null).assertFail(); - console.log(TAG + "testRdbTransactionInsert0002 failed"); - } - done(); - console.log(TAG + "************* testRdbTransactionInsert0002 end *************"); - }) - - /** - * @tc.name rdb transaction insert test - * @tc.number testRdbTransactionInsert0002 - * @tc.desc while using transaction to insert values, querying the db, - * the result comes out is 0; - */ - it('testRdbTransactionInsert0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransactionInsert0003 start *************"); - const u8 = new Uint8Array([1, 2, 3]); - try { - const trans = await rdbStore.createTransaction(); - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await trans.insert("test", valueBucket); - const valueBucket1 = { - "name": "zhangsan", - "age": 20, - "salary": 9.5, - "blobType": u8, - }; - await trans.insert("test", valueBucket1); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await trans.query(predicates); - expect(2).assertEqual(resultSet.rowCount); - resultSet.close(); - const valueBucket2 = { - "name": "wangwu", - "age": 16, - "salary": 99, - "blobType": u8, - }; - await trans.insert("test", valueBucket2); - await trans.commit(); - } catch (e) { - expect(null).assertFail(); - console.log(TAG + "testRdbTransactionInsert0003 failed"); - } - done(); - console.log(TAG + "************* testRdbTransactionInsert0003 end *************"); - }) - - /** - * @tc.number testRdbTransactionInsert0004 - * @tc.name Abnormal test case of transaction insert, if catch exception then rollback - * @tc.desc 1.Execute beginTransaction - * 2.Insert data (primary key conflict) - * 3.Execute rollBack - * 4.Query data - */ - it('testRdbTransactionRollBack0001', 0, async (done) => { - console.log(TAG + "************* testRdbTransactionRollBack0001 start *************"); - const u8 = new Uint8Array([1, 2, 3]); - const trans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - try { - const valueBucket = { - "id": 1, - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await trans.insert("test", valueBucket); - await trans.insert("test", valueBucket); - trans.commit(); - } catch (e) { - trans.rollback(); - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates); - console.log(TAG + "testRdbTransactionRollBack0001 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close(); - } - done(); - console.log(TAG + "************* testRdbTransactionRollBack0001 end *************"); - }) - - /** - * @tc.number testRdbTransactionInsert0005 - * @tc.name Normal test case of transaction, begin transactions within a transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute beginTransaction - * 4.Insert data - * 5.Execute rollBack - * 6.Insert data - * 7.Execute commit - * 8.Query data - */ - it('testRdbTransactionMulti0003', 0, async (done) => { - console.log(TAG + "************* testRdbTransactionMulti0003 start *************"); - const u8 = new Uint8Array([1, 2, 3]); - let trans = await rdbStore.createTransaction(); - const trans2 = await rdbStore.createTransaction(); - try { - const valueBucket = { - "id": 1, - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - await trans.insert("test", valueBucket); - console.log(TAG + "before second create trans"); - console.log(TAG + "after second create trans"); - const valueBucket1 = { - "name": "zhangsan", - "age": 20, - "salary": 220.5, - "blobType": u8, - }; - await trans2.insert("test", valueBucket1); - } catch (e) { - expect(e.code).assertEqual(14800024) - await trans.rollback(); - await trans2.rollback(); - console.log(TAG + "testRdbTransactionMulti0003 rollback ***** "); - } - done(); - console.log(TAG + "************* testRdbTransactionMulti0003 end *************"); - }) - - console.log(TAG + "*************Unit Test End*************"); -}) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransaction.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransaction.test.js deleted file mode 100644 index 0f07730e..00000000 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransaction.test.js +++ /dev/null @@ -1,2239 +0,0 @@ -/* - * 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. - */ - -import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' -import data_relationalStore from '@ohos.data.relationalStore' -import ability_featureAbility from '@ohos.ability.featureAbility' - -var context = ability_featureAbility.getContext() - -const TAG = "[RELATIONAL_STORE_TRANSACTION_JSKITS_TEST]" -const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + - "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; - -const STORE_CONFIG = { - name: "TransactionTest.db", - securityLevel: data_relationalStore.SecurityLevel.S1, -} - -var rdbStore = undefined; - -describe('rdbStoreTransactionTest', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll') - rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); - await rdbStore.executeSql(CREATE_TABLE_TEST, null); - }) - - beforeEach(async function () { - await rdbStore.executeSql(CREATE_TABLE_TEST); - console.info(TAG + 'beforeEach') - }) - - afterEach(async function () { - await rdbStore.executeSql("DELETE FROM test"); - console.info(TAG + 'afterEach') - }) - - afterAll(async function () { - console.info(TAG + 'afterAll') - rdbStore = null - await data_relationalStore.deleteRdbStore(context, "TransactionTest.db"); - }) - - console.log(TAG + "*************Unit Test Begin*************"); - - /** - * @tc.number testTransactionInsert0001 - * @tc.name Normal test case of transactions, insert a row of data - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute commit - * 4.Query data - */ - it('testTransactionInsert0001', 0, async function (done) { - console.log(TAG + "************* testTransactionInsert0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var num = await transaction.insert("test", valueBucket) - expect(1).assertEqual(num); - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await transaction.query(predicates) - console.log(TAG + "testTransactionInsert0001 result count " + resultSet.rowCount) - expect(1).assertEqual(resultSet.rowCount) - resultSet.close() - await transaction.commit() - } catch (e) { - await transaction.commit() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionInsert0001 failed"); - } - done() - console.log(TAG + "************* testTransactionInsert0001 end *************"); - }) - - /** - * @tc.number testTransactionInsert0002 - * @tc.name Abnormal test case of transaction, insert a type mismatch data - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute commit - */ - it('testTransactionInsert0002', 0, async function (done) { - console.log(TAG + "************* testTransactionInsert0002 start *************"); - let u8 = new Uint8Array([1, 2, 3]); - let transaction = await rdbStore?.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }); - try { - const valueBucket = { - "id": "test", - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - let row = transaction?.insertSync("test", valueBucket); - console.log(TAG + "testTransactionInsert0002 insert row:" + row); - expect(null).assertFail(); - await transaction?.commit(); - } catch (e) { - await transaction?.rollback(); - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800033) - console.log(TAG + "testTransactionInsert0002 failed"); - } - done(); - console.log(TAG + "************* testTransactionInsert0002 end *************"); - }) - - /** - * @tc.number testTransactionInsert0003 - * @tc.name Abnormal test case of transaction, insert with an abnormal table - * @tc.desc 1.Execute beginTransaction - * 2.Insert data to a no exist table - * 3.Execute commit - */ - it('testTransactionInsert0003', 0, async function (done) { - console.log(TAG + "************* testTransactionInsert0003 start *************"); - let u8 = new Uint8Array([1, 2, 3]); - let transaction = await rdbStore?.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - try { - const valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - }; - let row = await transaction?.insert("testNotExist", valueBucket); - console.log(TAG + "testTransactionInsert0003 insert row:" + row); - expect(null).assertFail(); - await transaction?.commit(); - } catch (e) { - await transaction?.rollback(); - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800021) - console.log(TAG + "testTransactionInsert0003 failed"); - } - done(); - console.log(TAG + "************* testTransactionInsert0003 end *************"); - }) - - /** - * @tc.number testTransactionInsert0004 - * @tc.name Abnormal test case of transaction, insert an more attribute data - * @tc.desc 1.Execute beginTransaction - * 2.Insert insert an more attribute data - * 3.Execute commit - */ - it('testTransactionInsert0004', 0, async function (done) { - console.log(TAG + "************* testTransactionInsert0004 start *************"); - let u8 = new Uint8Array([1, 2, 3]); - let transaction = await rdbStore?.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }); - try { - const valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - "notExist": "test" - }; - let row = transaction?.insertSync("test", valueBucket); - console.log(TAG + "testTransactionInsert0004 insert row:" + row); - expect(null).assertFail(); - await transaction?.commit(); - } catch (e) { - await transaction?.rollback(); - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800021) - console.log(TAG + "testTransactionInsert0004 failed"); - } - done(); - console.log(TAG + "************* testTransactionInsert0004 end *************"); - }) - - /** - * @tc.number testTransactionBatchInsert0001 - * @tc.name Normal test case of transactions, insert a row of data - * @tc.desc 1.Execute beginTransaction - * 2.BatchInsert data - * 3.Execute commit - * 4.Query data - */ - it('testTransactionBatchInsert0001', 0, async function (done) { - console.log(TAG + "************* testTransactionBatchInsert0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - let valueBucketArray = new Array(); - for (let i = 0; i < 2; i++) { - valueBucketArray.push(valueBucket); - } - var num = await transaction.batchInsert("test", valueBucketArray) - expect(2).assertEqual(num); - - let resultSet = await transaction.querySql("select * from test") - console.log(TAG + "testTransactionBatchInsert0001 result count " + resultSet.rowCount) - expect(2).assertEqual(resultSet.rowCount) - resultSet.close() - - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionBatchInsert0001 failed"); - } - done() - console.log(TAG + "************* testTransactionBatchInsert0001 end *************"); - }) - - /** - * @tc.number testTransactionUpdate0001 - * @tc.name Normal test case of transactions, insert and update a row of data - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 2.Update data - * 3.Execute commit - * 4.Query data - */ - it('testTransactionUpdate0001', 0, async function (done) { - console.log(TAG + "************* testTransactionUpdate0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await transaction.insert("test", valueBucket) - - let predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "lisi"); - const updateValueBucket = { - "name": "update", - "age": 28, - "salary": 25, - "blobType": u8, - } - var num = await transaction.update(updateValueBucket, predicates) - expect(1).assertEqual(num); - - let resultSet = await transaction.querySql("select * from test") - console.log(TAG + "testTransactionUpdate0001 result count " + resultSet.rowCount) - expect(1).assertEqual(resultSet.rowCount) - expect(true).assertEqual(resultSet.goToFirstRow()) - const name = resultSet.getString(resultSet.getColumnIndex("name")) - expect("update").assertEqual(name); - const age = resultSet.getLong(resultSet.getColumnIndex("age")) - expect(28).assertEqual(age); - const salary = resultSet.getLong(resultSet.getColumnIndex("salary")) - expect(25).assertEqual(salary); - resultSet.close() - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionUpdate0001 failed"); - } - done() - console.log(TAG + "************* testTransactionUpdate0001 end *************"); - }) - - /** - * @tc.number testTransactionDelete0001 - * @tc.name Normal test case of transactions, insert and update a row of data - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 2.Delete data - * 3.Execute commit - * 4.Query data - */ - it('testTransactionDelete0001', 0, async function (done) { - console.log(TAG + "************* testTransactionDelete0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await transaction.insert("test", valueBucket) - - let predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "lisi"); - var num = await transaction.delete(predicates) - expect(1).assertEqual(num); - - let resultSet = await transaction.querySql("select * from test") - console.log(TAG + "testTransactionDelete0001 result count " + resultSet.rowCount) - expect(0).assertEqual(resultSet.rowCount) - resultSet.close() - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionDelete0001 failed"); - } - done() - console.log(TAG + "************* testTransactionDelete0001 end *************"); - }) - - /** - * @tc.number testExecute0001 - * @tc.name Normal test case of Execute, check integrity for store - * @tc.desc 1. Execute sql: PRAGMA integrity_check - * 2. Check returned value - */ - it('testExecute0001', 0, async function (done) { - console.info(TAG + "************* testExecute0001 start *************"); - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - try { - let ret = await transaction.execute("PRAGMA integrity_check"); - expect("ok").assertEqual(ret); - await transaction.commit(); - } catch (err) { - await transaction.rollback(); - expect(null).assertFail(); - console.error(`integrity_check failed, code:${err.code}, message: ${err.message}`); - } - done(); - console.info(TAG + "************* testExecute0001 end *************"); - }) - - - /** - * @tc.number testExecute0002 - * @tc.name Normal test case of ExecuteSql - * @tc.desc 1.Insert data - * 2.ExecuteSql(delete age = "18" OR "20") - * 3.QuerySql - */ - it('testExecute0002', 0, async function (done) { - console.log(TAG + "************* testExecute0002 start *************"); - var transaction = await rdbStore.createTransaction() - var u8 = new Uint8Array([1, 2, 3]) - try { - var valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - for (let i = 0; i < 3; i++) { - valueBucket.age = valueBucket.age + 1; - var row = await transaction.insert("test", valueBucket) - console.log(TAG + "testExecute0002 insert row " + row) - } - await transaction.execute("DELETE FROM test WHERE age = ? OR age = ?", [21, 20]) - - let resultSet = await transaction.querySql("select * from test") - console.log(TAG + "testExecute0002 transaction.querySql result count " + resultSet.rowCount) - expect(1).assertEqual(resultSet.rowCount) - expect(true).assertEqual(resultSet.goToFirstRow()) - const age = resultSet.getLong(resultSet.getColumnIndex("age")) - expect(19).assertEqual(age); - await resultSet.close() - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testExecute0002 failed"); - } - done(); - console.log(TAG + "************* testExecute0002 end *************"); - } - ) - - /** - * @tc.number testExecute0003 - * @tc.name Normal test case of ExecuteSql - * @tc.desc 1.Insert data (param is long string) - * 2.Query data - * 3.ExecuteSql (delete age = 19 AND name = nameStr) - * 4.Query data - */ - it('ExecuteSqlTest0003', 0, async function (done) { - console.log(TAG + "************* testExecute0003 start *************"); - var u8 = new Uint8Array([3, 4, 5]) - var transaction = await rdbStore.createTransaction() - var nameStr = "lisi" + "e".repeat(2000) + "zhangsan" - var valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var row = await transaction.insert("test", valueBucket) - console.log(TAG + "testExecute0003 insert row " + row) - valueBucket.name = nameStr - for (let i = 0; i < 2; i++) { - row = await transaction.insert("test", valueBucket) - valueBucket.age = valueBucket.age + 1; - console.log(TAG + "testExecute0003 insert row " + row) - } - { - let predicates = await new data_relationalStore.RdbPredicates("test") - predicates.equalTo("name", nameStr) - let querySqlPromise = transaction.query(predicates) - querySqlPromise.then(async (resultSet) => { - expect(2).assertEqual(resultSet.rowCount) - resultSet.close() - }).catch((err) => { - expect(null).assertFail(); - }) - await querySqlPromise - } - { - let executeSqlPromise = transaction.execute("DELETE FROM test WHERE age = 19 AND name ='" + nameStr + "'") - executeSqlPromise.then(async () => { - console.log(TAG + "executeSql done."); - }).catch((err) => { - console.log(TAG + "executeSql failed. " + err); - expect(null).assertFail(); - }) - await executeSqlPromise - } - await transaction.commit(); - { - let predicates = await new data_relationalStore.RdbPredicates("test") - predicates.equalTo("name", nameStr) - let querySqlPromise = rdbStore.query(predicates) - querySqlPromise.then(async (resultSet) => { - console.log(TAG + "testExecute0003 rdbStore.querySql result count " + resultSet.rowCount) - expect(1).assertEqual(resultSet.rowCount) - expect(true).assertEqual(resultSet.goToFirstRow()) - const name = resultSet.getString(resultSet.getColumnIndex("name")) - expect(nameStr).assertEqual(name) - expect(2012).assertEqual(name.length) - expect(18).assertEqual(resultSet.getLong(resultSet.getColumnIndex("age"))) - expect(100.5).assertEqual(resultSet.getDouble(resultSet.getColumnIndex("salary"))) - const blobType = resultSet.getBlob(resultSet.getColumnIndex("blobType")) - expect(3).assertEqual(blobType[0]) - resultSet.close(); - done(); - }).catch((err) => { - console.log(TAG + err); - expect(null).assertFail(); - }) - await querySqlPromise - } - done(); - console.log(TAG + "************* testExecute0003 end *************"); - }) - - /** - * @tc.number testExecute0004 - * @tc.name Normal test case of ExecuteSql, drop table - * @tc.desc 1.Insert data - * 2.ExecuteSql (drop table) - */ - it('testExecute0004', 0, async function (done) { - console.log(TAG + "************* testExecute0004 start *************"); - var u8 = new Uint8Array([3, 4, 5]) - var transaction = await rdbStore.createTransaction() - try { - var valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - let valueBucketArray = new Array(); - for (let i = 0; i < 3; i++) { - valueBucket.age = valueBucket.age + 1; - valueBucketArray.push(valueBucket); - } - var num = await transaction.batchInsert("test", valueBucketArray) - expect(3).assertEqual(num); - await transaction.execute("DROP TABLE IF EXISTS test") - - let resultSet = await transaction.querySql("select * from test") - console.log(TAG + "testExecute0004 transaction.querySql result count " + resultSet.rowCount) - expect(resultSet.rowCount < 1).assertTrue() - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testExecute0004 failed"); - } - done(); - console.log(TAG + "************* testExecute0004 end *************"); - }) - - /** - * @tc.number testExecute0005 - * @tc.name Normal test case of executeSql and querySql, PRAGMA user_version - * @tc.desc 1.Set user_version - * 2.Get user_version - */ - it('testExecute0005', 0, async function (done) { - console.log(TAG + "************* testExecute0005 start *************"); - // 2 is used to set the store version - var transaction = await rdbStore.createTransaction() - try { - await transaction.execute("PRAGMA user_version = 2") - let resultSet = await transaction.querySql("PRAGMA user_version"); - console.log(TAG + "testExecute0005 transaction.querySql result count " + resultSet.rowCount) - resultSet.goToFirstRow(); - expect(2).assertEqual(resultSet.getLong(0)) - resultSet.close(); - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testExecute0005 failed"); - } - done(); - console.log(TAG + "************* testExecute0005 end *************"); - }) - - /** - * @tc.number testExecute0006 - * @tc.name Normal test case of executeSql and querySql, PRAGMA table_info - * @tc.desc 1.Get table_info - * 2.Check table_info - */ - it('testExecute0006', 0, async function (done) { - console.log(TAG + "************* testExecute0006 start *************"); - var transaction = await rdbStore.createTransaction() - try { - let resultSet = await transaction.querySql("PRAGMA table_info(test)"); - console.log(TAG + "testExecute0006 transaction.querySql result count " + resultSet.rowCount) - resultSet.goToFirstRow(); - expect(0).assertEqual(resultSet.getLong(0)) - expect("id").assertEqual(resultSet.getString(1)) - expect("INTEGER").assertEqual(resultSet.getString(2)) - resultSet.goToNextRow(); - expect(1).assertEqual(resultSet.getLong(0)) - expect("name").assertEqual(resultSet.getString(1)) - expect("TEXT").assertEqual(resultSet.getString(2)) - expect(1).assertEqual(resultSet.getLong(3)) - resultSet.goToNextRow(); - expect(2).assertEqual(resultSet.getLong(0)) - expect("age").assertEqual(resultSet.getString(1)) - expect("INTEGER").assertEqual(resultSet.getString(2)) - resultSet.goToNextRow(); - expect(3).assertEqual(resultSet.getLong(0)) - expect("salary").assertEqual(resultSet.getString(1)) - expect("REAL").assertEqual(resultSet.getString(2)) - resultSet.goToNextRow(); - expect(4).assertEqual(resultSet.getLong(0)) - expect("blobType").assertEqual(resultSet.getString(1)) - expect("BLOB").assertEqual(resultSet.getString(2)) - resultSet.close(); - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testExecute0006 failed"); - } - done(); - console.log(TAG + "************* testExecute0006 end *************"); - }) - - /** - * @tc.number testExecute0007 - * @tc.name Normal test case of executeSql, if spaces before the sql - * @tc.desc 1.Set user_version - * 2.Get user_version - */ - it('testExecute0007', 0, async function (done) { - console.log(TAG + "************* testExecute0007 start *************"); - var transaction = await rdbStore.createTransaction() - try { - // 2 is used to set the store version - await transaction.execute(" PRAGMA user_version = 2") - let resultSet = await transaction.querySql("PRAGMA user_version"); - console.log(TAG + "testExecute0007 transaction.querySql1 result count " + resultSet.rowCount) - resultSet.goToFirstRow(); - expect(2).assertEqual(resultSet.getLong(0)) - - await transaction.execute("\r\nPRAGMA user_version = 3") - resultSet = await transaction.querySql("PRAGMA user_version"); - console.log(TAG + "testExecute0007 transaction.querySql2 result count " + resultSet.rowCount) - resultSet.goToFirstRow(); - expect(3).assertEqual(resultSet.getLong(0)) - resultSet.close(); - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testExecute0007 failed"); - } - done(); - console.log(TAG + "************* testExecute0007 end *************"); - }) - - /** - * @tc.number testTransactionSyncInterface0001 - * @tc.name Normal test case of transactions, insert a row of data - * @tc.desc 1.Execute beginTransaction - * 2.BatchInsertSync data - * 3.InsertSync data - * 4.UpdateSync data - * 5.DeleteSync data - * 6.Execute commit - * 7.querySqlSync - * 7.ExecuteSync - */ - it('testTransactionSyncInterface0001', 0, async function (done) { - console.log(TAG + "************* testTransactionSyncInterface0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var num = await transaction.insertSync("test", valueBucket, data_relationalStore.ConflictResolution.ON_CONFLICT_REPLACE); - expect(1).assertEqual(num); - const updateValueBucket = { - "name": "update", - "age": 28, - "salary": 25, - "blobType": u8, - } - let predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "lisi") - num = await transaction.updateSync(updateValueBucket, predicates) - expect(1).assertEqual(num); - - let deletePredicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "update") - num = await transaction.deleteSync(deletePredicates); - expect(1).assertEqual(num); - - let resultSet = await transaction.querySqlSync("select * from test") - console.log(TAG + "testTransactionSyncInterface0001 result count " + resultSet.rowCount) - expect(0).assertEqual(resultSet.rowCount) - resultSet.close() - - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionSyncInterface0001 failed"); - } - done() - console.log(TAG + "************* testTransactionSyncInterface0001 end *************"); - }) - - /** - * @tc.number testTransactionRollback0001 - * @tc.name Normal test case of transactions, insert and update a row of data - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.rollback data - * 4.Query data - */ - it('testTransactionRollback0001', 0, async function (done) { - console.log(TAG + "************* testTransactionRollback0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await transaction.insert("test", valueBucket) - - await transaction.rollback() - - let resultSet = rdbStore.querySqlSync("select * from test") - console.log(TAG + "testTransactionRollback0001 result count " + resultSet.rowCount) - expect(0).assertEqual(resultSet.rowCount) - resultSet.close() - } catch (e) { - await transaction.rollback() - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionRollback0001 failed"); - } - done() - console.log(TAG + "************* testTransactionRollback0001 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0001 - * @tc.name testTransactionIsolation. EXCLUSIVE and EXCLUSIVE - * @tc.desc 1.begin EXCLUSIVE Transaction - * 2.begin EXCLUSIVE Transaction again - * 3.throw 14800024 - */ - it('testTransactionIsolation0001', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0001 start *************"); - var exclusiveTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - try { - var trans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - trans.commit(); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0001 failed"); - } catch (e) { - await exclusiveTrans.rollback(); - console.log(TAG + e); - expect(e.code).assertEqual(14800024) - console.log(TAG + "testTransactionIsolation0001 success"); - } - done() - console.log(TAG + "************* testTransactionIsolation0001 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0002 - * @tc.name testTransactionIsolation. DEFERRED and EXCLUSIVE - * @tc.desc 1.begin DEFERRED Transaction - * 2.begin EXCLUSIVE Transaction again - * 3.insert data with EXCLUSIVE Transaction - * 4.query data with DEFERRED Transaction -> no data - * 5.execute commit with EXCLUSIVE Transaction - * 6.query data with DEFERRED Transaction -> no data -> why? step 4 start isolation - * 7.query data with Rdb -> has data - */ - it('testTransactionIsolation0002', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0002 start *************"); - var deferredTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - var exclusiveTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - } - var insertRow = await exclusiveTrans.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0002 exclusiveTrans.insert row " + insertRow) - expect(1).assertEqual(insertRow) - - var resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0002 deferredTrans querySqlSync before exclusiveTrans commit count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close() - - await exclusiveTrans.commit(); - - resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0002 deferredTrans querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - - resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0002 rdbStore querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close() - - } catch (e) { - exclusiveTrans.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "insert failed"); - } - await deferredTrans.commit(); - } catch (e) { - await deferredTrans.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0002 failed"); - } - done() - console.log(TAG + "************* testTransactionIsolation0002 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0003 - * @tc.name testTransactionIsolation. IMMEDIATE and rdbStore - * @tc.desc 1.begin IMMEDIATE Transaction - * 2.insert data with rdbStore -> busy - * 3.insert data with IMMEDIATE Transaction - * 4.execute commit with IMMEDIATE Transaction - * 5.query data with rdbStore -> has data - */ - it('testTransactionIsolation0003', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0003 start *************"); - var immediateTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - } - try { - await rdbStore.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0003 rdbStore.insert success "); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e); - expect(e.code).assertEqual(14800024) - console.log(TAG + "insert failed"); - } - var insertRow = await immediateTrans.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0003 immediateTrans.insert row " + insertRow); - expect(insertRow).assertEqual(1); - - await immediateTrans.commit(); - - var resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0003 querySqlSync count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close() - } catch (e) { - await immediateTrans.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0003 failed"); - } - done() - console.log(TAG + "************* testTransactionIsolation0003 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0004 - * @tc.name testTransactionIsolation. DEFERRED and rdbStore - * @tc.desc 1.begin DEFERRED Transaction - * 2.insert data with rdbStore - * 3.insert data with DEFERRED Transaction - * 4.query data with rdbStore -> has 2 row - * 5.insert data with rdbStore again -> busy - * 6.query data with DEFERRED Transaction -> has 2 row - * 7.execute commit with DEFERRED Transaction - * 8.insert data with rdbStore again - * 9.query data with rdbStore -> has 3 row - */ - it('testTransactionIsolation0004', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0004 start *************"); - var deferredTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - } - await rdbStore.insert("test", valueBucket); - - await deferredTrans.insert("test", valueBucket); - - var resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0004 rdbStore.querySqlSync count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - - try { - await rdbStore.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0004 insert success "); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e); - expect(e.code).assertEqual(14800024) - console.log(TAG + "insert failed"); - } - resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0004 deferredTrans.querySqlSync count " + resultSet.rowCount); - expect(2).assertEqual(resultSet.rowCount); - - await deferredTrans.commit(); - - await rdbStore.insert("test", valueBucket); - - resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0004 rdbStore.querySqlSync after deferredTrans commit count " + resultSet.rowCount); - expect(3).assertEqual(resultSet.rowCount); - resultSet.close() - } catch (e) { - await deferredTrans.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0004 failed"); - } - done() - console.log(TAG + "************* testTransactionIsolation0004 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0005 - * @tc.name testTransactionIsolation. DEFERRED and IMMEDIATE - * @tc.desc 1.begin DEFERRED Transaction - * 2.begin IMMEDIATE Transaction - * 3.insert data with DEFERRED Transaction -> busy - * 4.insert data with IMMEDIATE Transaction - * 5.execute commit with IMMEDIATE Transaction - * 6.insert data with DEFERRED Transaction - * 7.execute commit with DEFERRED Transaction - * 8.query data with rdbStore -> has 4 row - */ - it('testTransactionIsolation0005', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0005 start *************"); - var deferredTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - var immediateTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - } - try { - await deferredTrans.insert("test", valueBucket); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e); - expect(e.code).assertEqual(14800024) - console.log(TAG + "insert failed"); - } - var insertRow = await immediateTrans.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0005 immediateTrans.insert row " + insertRow); - expect(1).assertEqual(insertRow); - - await immediateTrans.commit(); - - insertRow = await deferredTrans.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0005 deferredTrans.insert after immediateTrans.commit row " + insertRow); - expect(2).assertEqual(insertRow); - - await deferredTrans.commit(); - - var resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0005 querySqlSync count " + resultSet.rowCount); - expect(2).assertEqual(resultSet.rowCount); - resultSet.close() - } catch (e) { - await immediateTrans.rollback(); - await deferredTrans.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0005 failed"); - } - done() - console.log(TAG + "************* testTransactionIsolation0005 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0006 - * @tc.name testTransactionIsolation. DEFERRED and DEFERRED - * @tc.desc 1.insert data with rdbStore - * 2.begin DEFERRED Transaction1 - * 3.begin DEFERRED Transaction2 - * 4.update data with DEFERRED Transaction1 - * 5.delete data with DEFERRED Transaction2 -> busy - * 6.execute commit with DEFERRED Transaction1 - * 7.query data with DEFERRED Transaction2 -> has updated data - * 8.delete data with DEFERRED Transaction2 - * 9.execute commit with DEFERRED Transaction2 - * 10.query data with rdbStore -> has 0 row - */ - it('testTransactionIsolation0006', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0006 start *************"); - var deferredTrans1 = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - var deferredTrans2 = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - } - var rowId = await rdbStore.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0006 insert row " + rowId); - expect(1).assertEqual(rowId); - - const updateValueBucket = { - "name": "deferredTrans1", - "age": 18, - "salary": 100.5, - } - let predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "lisi") - rowId = await deferredTrans1.updateSync(updateValueBucket, predicates) - console.log(TAG + "testTransactionIsolation0006 insert row " + rowId); - expect(1).assertEqual(rowId); - - let deletePredicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("age", "18"); - try { - await deferredTrans2.delete(deletePredicates) - console.log(TAG + "testTransactionIsolation0006 deferredTrans2.delete success "); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e); - expect(e.code).assertEqual(14800024) - console.log(TAG + "insert failed"); - } - - await deferredTrans1.commit(); - - var resultSet = deferredTrans2.querySqlSync("select * from test"); - console.log(TAG + "testTransactionIsolation0006 deferredTrans2.querySqlSync count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - expect(true).assertEqual(resultSet.goToFirstRow()) - const name = resultSet.getString(resultSet.getColumnIndex("name")) - expect("deferredTrans1").assertEqual(name); - resultSet.close() - - var num = await deferredTrans2.deleteSync(deletePredicates) - console.log(TAG + "testTransactionIsolation0006 delete num " + num); - expect(1).assertEqual(num); - - await deferredTrans2.commit(); - - resultSet = rdbStore.querySqlSync("select * from test"); - console.log(TAG + "testTransactionIsolation0006 rdbStore.querySqlSync count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount); - resultSet.close() - } catch (e) { - await deferredTrans2.rollback(); - await deferredTrans1.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0006 failed"); - } - done() - console.log(TAG + "************* testTransactionIsolation0006 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0007 - * @tc.name testTransactionIsolation. DEFERRED and EXCLUSIVE - * @tc.desc 1.begin DEFERRED Transaction1 - * 2.begin EXCLUSIVE Transaction - * 3.insert data with EXCLUSIVE Transaction - * 4.execute commit with EXCLUSIVE Transaction - * 5.query data with DEFERRED1 Transaction -> has data - * 6.begin DEFERRED Transaction2 - * 7.query data with DEFERRED2 Transaction -> has data - */ - it('testTransactionIsolation0007', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0007 start *************"); - var deferredTrans1 = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - var exclusiveTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - } - var insertRow = await exclusiveTrans.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0007 exclusiveTrans.insert row " + insertRow) - expect(1).assertEqual(insertRow) - await exclusiveTrans.commit(); - - var resultSet = deferredTrans1.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0007 deferredTrans1 querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - - var deferredTrans2 = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - resultSet = deferredTrans2.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0007 deferredTrans2 querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close() - } catch (e) { - deferredTrans2.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "querySqlSync failed"); - } - - } catch (e) { - exclusiveTrans.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "insert failed"); - } - await deferredTrans1.commit(); - } catch (e) { - await deferredTrans1.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0007 failed"); - } - done() - console.log(TAG + "************* testTransactionIsolation0007 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0008 - * @tc.name testTransactionIsolation. DEFERRED and rdbStore - * @tc.desc 1.begin DEFERRED Transaction - * 2.insert data with rdbStore - * 3.query data with DEFERRED Transaction -> has 1 data - * 4.begin EXCLUSIVE Transaction -> busy - * 5.insert data with DEFERRED Transaction - * 6.execute commit with DEFERRED Transaction - * 7.begin EXCLUSIVE Transaction - * 8.query data with EXCLUSIVE Transaction -> has 2 data - */ - it('testTransactionIsolation0008', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0008 start *************"); - var deferredTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - } - await rdbStore.insert("test", valueBucket); - - var resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); - console.log(TAG + "testTransactionIsolation0008 querySqlSync1 count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close() - try { - var exclusiveTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - console.log(TAG + "begin EXCLUSIVE success abnormal"); - await exclusiveTrans.rollback(); - } catch (e) { - console.log(TAG + e); - console.log(TAG + "begin EXCLUSIVE failed"); - expect(true).assertFail(); - } - var rowId = await deferredTrans.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0008 deferredTrans.insert row " + rowId) - expect(2).assertEqual(rowId); - - await deferredTrans.commit(); - - try { - var exclusiveTrans = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - console.log(TAG + "begin EXCLUSIVE success"); - try { - resultSet = exclusiveTrans.querySqlSync("select * from test"); - console.log(TAG + "testTransactionIsolation0008 exclusiveTrans.querySqlSync count " + resultSet.rowCount); - expect(2).assertEqual(resultSet.rowCount); - resultSet.close() - } catch (e) { - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "exclusiveTrans.querySqlSync failed"); - } - exclusiveTrans.rollback(); - } catch (e) { - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "begin EXCLUSIVE failed"); - } - } catch (e) { - await deferredTrans.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0008 failed"); - } - done() - console.log(TAG + "************* testTransactionIsolation0008 end *************"); - }) - - /** - * @tc.number testTransactionIsolation0009 - * @tc.name testTransactionIsolation. DEFERRED and DEFERRED - * @tc.desc 1.insert data with rdbStore - * 2.begin DEFERRED Transaction1 - * 3.begin DEFERRED Transaction2 - * 4.update data to update1 with DEFERRED Transaction1 - * 5.query data with DEFERRED Transaction2 -> has before update data - * 6.update update1 to update2 with DEFERRED Transaction1 - * 7.execute commit with DEFERRED Transaction1 - * 8.query data with DEFERRED Transaction2 -> has before update data - * 9.delete data with DEFERRED Transaction2 -> busy - * 10.execute commit with DEFERRED Transaction2 - * 11.query data with rdbStore -> has 1 row - */ - it('testTransactionIsolation0009', 0, async function (done) { - console.log(TAG + "************* testTransactionIsolation0009 start *************"); - var deferredTrans1 = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - var deferredTrans2 = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - } - var rowId = await rdbStore.insert("test", valueBucket); - console.log(TAG + "testTransactionIsolation0009 insert row " + rowId); - expect(1).assertEqual(rowId); - - const updateValueBucket1 = { - "name": "update1", - "age": 18, - "salary": 100.5, - } - let predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "lisi") - var num = await deferredTrans1.updateSync(updateValueBucket1, predicates) - console.log(TAG + "testTransactionIsolation0009 updateSync 1 num " + num); - expect(1).assertEqual(num); - - var resultSet = deferredTrans2.querySqlSync("select * from test"); - console.log(TAG + "testTransactionIsolation0009 deferredTrans2.querySqlSync1 count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - expect(true).assertEqual(resultSet.goToFirstRow()) - var name = resultSet.getString(resultSet.getColumnIndex("name")) - expect("lisi").assertEqual(name); - resultSet.close() - - const updateValueBucket2 = { - "name": "update2", - "age": 18, - "salary": 100.5, - } - predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "update1") - var num = await deferredTrans1.updateSync(updateValueBucket2, predicates) - console.log(TAG + "testTransactionIsolation0009 updateSync 2 num " + num); - expect(1).assertEqual(num); - - await deferredTrans1.commit(); - - resultSet = deferredTrans2.querySqlSync("select * from test"); - console.log(TAG + "testTransactionIsolation0009 deferredTrans2.querySqlSync2 count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - expect(true).assertEqual(resultSet.goToFirstRow()) - name = resultSet.getString(resultSet.getColumnIndex("name")) - expect("lisi").assertEqual(name); - resultSet.close() - - let deletePredicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("age", "18"); - try { - num = await deferredTrans2.delete(deletePredicates) - console.log(TAG + "testTransactionIsolation0009 delete num " + num); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e); - expect(e.code).assertEqual(14800024) - } - await deferredTrans2.commit(); - - resultSet = rdbStore.querySqlSync("select * from test"); - console.log(TAG + "testTransactionIsolation0009 rdbStore.querySqlSync count " + resultSet.rowCount); - expect(1).assertEqual(resultSet.rowCount); - resultSet.close() - } catch (e) { - await deferredTrans2.rollback(); - await deferredTrans1.rollback(); - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testTransactionIsolation0009 failed"); - } - done() - console.log(TAG + "************* testTransactionIsolation0009 end *************"); - }) - - /** - * @tc.number testTransactionEnd0001 - * @tc.name Query data with closed transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute commit - * 4.Query data with transaction -> throw 14800014 - */ - it('testTransactionEnd0001', 0, async function (done) { - console.log(TAG + "************* testTransactionEnd0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var num = await transaction.insert("test", valueBucket) - expect(1).assertEqual(num); - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e + " code: " + e.code); - expect(null).assertFail() - } - try { - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await transaction.query(predicates) - console.log(TAG + "testTransactionEnd0001 result count " + resultSet.rowCount) - expect(null).assertFail() - resultSet.close() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800014) - } - done() - console.log(TAG + "************* testTransactionEnd0001 end *************"); - }) - - /** - * @tc.number testTransactionEnd0002 - * @tc.name Query data with closed transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Query data with transaction -> get resultSet - * 4.Execute commit - * 5.resultSet go to first row -> throw 14800014 - */ - it('testTransactionEnd0002', 0, async function (done) { - console.log(TAG + "************* testTransactionEnd0002 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - let resultSet; - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var num = await transaction.insert("test", valueBucket) - expect(1).assertEqual(num); - - let predicates = new data_relationalStore.RdbPredicates("test"); - resultSet = await transaction.query(predicates) - console.log(TAG + "testTransactionEnd0002 result count " + resultSet.rowCount) - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e + " code: " + e.code); - expect(null).assertFail() - } - expect(false).assertEqual(resultSet.goToFirstRow()) - done() - console.log(TAG + "************* testTransactionEnd0002 end *************"); - }) - - /** - * @tc.number testTransactionEnd0003 - * @tc.name Insert data with closed transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute commit - * 4.Insert data with closed transaction -> throw 14800014 - */ - it('testTransactionEnd0003', 0, async function (done) { - console.log(TAG + "************* testTransactionEnd0003 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - try { - var rowId = await transaction.insert("test", valueBucket) - expect(1).assertEqual(rowId); - await transaction.commit() - } catch (e) { - await transaction.rollback() - console.log(TAG + e + " code: " + e.code); - expect(null).assertFail() - } - try { - rowId = await transaction.insert("test", valueBucket) - console.log(TAG + "testTransactionEnd0003 insert rowId " + rowId) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800014) - } - done() - console.log(TAG + "************* testTransactionEnd0003 end *************"); - }) - - /** - * @tc.number testTransactionEnd0004 - * @tc.name Update data with closed transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute rollback - * 4.Update data with closed transaction -> throw 14800014 - */ - it('testTransactionEnd0004', 0, async function (done) { - console.log(TAG + "************* testTransactionEnd0004 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.IMMEDIATE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var rowId = await transaction.insert("test", valueBucket) - expect(1).assertEqual(rowId); - await transaction.rollback() - } catch (e) { - await transaction.rollback() - console.log(TAG + e + " code: " + e.code); - expect(null).assertFail() - } - try { - let predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "lisi"); - const updateValueBucket = { - "name": "update", - "age": 28, - "salary": 25, - "blobType": u8, - } - rowId = await transaction.update(updateValueBucket, predicates) - console.log(TAG + "testTransactionEnd0004 update rowId " + rowId) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800014) - } - done() - console.log(TAG + "************* testTransactionEnd0004 end *************"); - }) - - /** - * @tc.number testTransactionEnd0005 - * @tc.name Delete data with closed transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute rollback - * 4.Delete data with closed transaction -> throw 14800014 - */ - it('testTransactionEnd0005', 0, async function (done) { - console.log(TAG + "************* testTransactionEnd0005 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.EXCLUSIVE - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var rowId = await transaction.insert("test", valueBucket) - expect(1).assertEqual(rowId); - await transaction.rollback() - } catch (e) { - await transaction.rollback() - console.log(TAG + e + " code: " + e.code); - expect(null).assertFail() - } - try { - let predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "lisi"); - var num = transaction.deleteSync(predicates) - console.log(TAG + "testTransactionEnd0005 delete num " + num) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800014) - } - done() - console.log(TAG + "************* testTransactionEnd0005 end *************"); - }) - - /** - * @tc.number testTransactionEnd0006 - * @tc.name Execute Sql with closed transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute rollback - * 4.Execute Sql with closed transaction -> throw 14800014 - */ - it('testTransactionEnd0006', 0, async function (done) { - console.log(TAG + "************* testTransactionEnd0006 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var rowId = await transaction.insert("test", valueBucket) - expect(1).assertEqual(rowId); - await transaction.rollback() - } catch (e) { - await transaction.rollback() - console.log(TAG + e + " code: " + e.code); - expect(null).assertFail() - } - try { - let ret = transaction.executeSync("PRAGMA integrity_check"); - console.log(TAG + "testTransactionEnd0006 executeSync PRAGMA integrity_check: " + ret) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800014) - } - done() - console.log(TAG + "************* testTransactionEnd0006 end *************"); - }) - - /** - * @tc.number testTransactionEnd0007 - * @tc.name Execute Sql with closed transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute rollback - * 4.Commit with closed transaction -> throw 14800014 - */ - it('testTransactionEnd0007', 0, async function (done) { - console.log(TAG + "************* testTransactionEnd0007 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }) - try { - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var rowId = await transaction.insert("test", valueBucket) - expect(1).assertEqual(rowId); - await transaction.rollback() - } catch (e) { - await transaction.rollback() - console.log(TAG + e + " code: " + e.code); - expect(null).assertFail() - } - try { - await transaction.commit(); - console.log(TAG + "testTransactionEnd0007 commit success") - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800014) - } - done() - console.log(TAG + "************* testTransactionEnd0007 end *************"); - }) - - /** - * @tc.number testTransactionBusy0001 - * @tc.name Abnormal test case of createTransaction - * @tc.desc 1.Execute beginTransaction 5 times - */ - it('testTransactionBusy0001', 0, async function (done) { - console.log(TAG + "************* testTransactionBusy0001 start *************"); - let transactions = []; - try { - for (let i = 0; i < 5; i++) { - transactions.push(await rdbStore?.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - })); - console.log(TAG + "testTransactionBusy0001 createTransaction success. i " + i); - } - } catch (e) { - console.log(TAG + e + " code: " + e.code); - // expect(e.code).assertEqual(14800000) - expect(e.code).assertEqual(14800015) - console.log(TAG + "testTransactionBusy0001 failed"); - } - done(); - transactions.forEach(element => { - element?.rollback(); - console.log(TAG + "testTransactionBusy0001 rollback"); - }); - console.log(TAG + "************* testTransactionBusy0001 end *************"); - }) - - /** - * @tc.number testTransactionWithReadOnlyStore0001 - * @tc.name createTransactionWithReadOnlyStore - * @tc.desc 1.Get a readOnly store - * 2.createTransaction with readOnly store - */ - it('testTransactionWithReadOnlyStore0001', 0, async function (done) { - console.log(TAG + "************* testTransactionWithReadOnlyStore0001 start *************"); - let storeConfig = { - name: "ReadOnlyTransactionTest.db", - securityLevel: data_relationalStore.SecurityLevel.S1, - } - let store = await data_relationalStore.getRdbStore(context, storeConfig); - await store.close() - storeConfig.isReadOnly = true; - let readOnlyStore = await data_relationalStore.getRdbStore(context, storeConfig); - expect(readOnlyStore === null).assertFalse(); - try { - let transaction = await readOnlyStore?.createTransaction({ - transactionType: data_relationalStore.TransactionType.DEFERRED - }); - console.log(TAG + "testTransactionWithReadOnlyStore0001 createTransaction success"); - const valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - }; - let row = transaction?.insertSync("test", valueBucket); - console.log(TAG + "testTransactionWithReadOnlyStore0001 insert row:" + row); - await transaction?.rollback(); - expect(null).assertFail(); - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(801) - console.log(TAG + "testTransactionWithReadOnlyStore0001 success"); - } - await data_relationalStore.deleteRdbStore(context, storeConfig); - done(); - console.log(TAG + "************* testTransactionWithReadOnlyStore0001 end *************"); - }) - - /** - * @tc.number testbatchInsertWithConflictResolutionInTransaction0001 - * @tc.name batchInsertWithConflictResolutionInTransaction - * @tc.desc normal batch insert with ON_CONFLICT_NONE - */ - it('testbatchInsertWithConflictResolutionInTransaction0001', 0, async function (done) { - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - let valueBucketArray = new Array(); - for (let i = 0; i < 2; i++) { - valueBucketArray.push(valueBucket); - } - var num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_NONE) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num1 " + num) - expect(2).assertEqual(num); - - num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num2 " + num) - expect(2).assertEqual(num); - - num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_ABORT) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num3 " + num) - expect(2).assertEqual(num); - - num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_FAIL) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num4 " + num) - expect(2).assertEqual(num); - - num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_IGNORE) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num5 " + num) - expect(2).assertEqual(num); - - num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_REPLACE) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 batch num6 " + num) - expect(2).assertEqual(num); - - let resultSet = await transaction.querySql("select * from test") - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 result count " + resultSet.rowCount) - expect(12).assertEqual(resultSet.rowCount) - resultSet.close() - - await transaction.commit() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - await transaction.rollback() - expect(null).assertFail() - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0001 failed"); - } - done() - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0001 end *************"); - }) - - /** - * @tc.number testbatchInsertWithConflictResolutionInTransaction0011 - * @tc.name batchInsertWithConflictResolutionInTransaction - * @tc.desc conflict batch insert with ON_CONFLICT_NONE - */ - it('testbatchInsertWithConflictResolutionInTransaction0011', 0, async function (done) { - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0011 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "id" : 2, - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await transaction.insert("test", valueBucket); - let valueBucketArray = new Array(); - for (let i = 0; i < 5; i++) { - var vb = {...valueBucket}; - vb.id = i; - valueBucketArray.push(vb); - } - let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_NONE) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0011 failed num " + num); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(14800032).assertEqual(e.code) - await transaction.rollback() - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0011 success"); - } - done() - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0011 end *************"); - }) - - /** - * @tc.number testbatchInsertWithConflictResolutionInTransaction0012 - * @tc.name batchInsertWithConflictResolutionInTransaction - * @tc.desc conflict batch insert with ON_CONFLICT_ABORT - */ - it('testbatchInsertWithConflictResolutionInTransaction0012', 0, async function (done) { - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0012 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "id" : 2, - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await transaction.insert("test", valueBucket); - let valueBucketArray = new Array(); - for (let i = 0; i < 5; i++) { - var vb = {...valueBucket}; - vb.id = i; - valueBucketArray.push(vb); - } - let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_ABORT) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0012 failed num " + num); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(14800032).assertEqual(e.code) - await transaction.rollback() - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0012 success"); - } - done() - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0012 end *************"); - }) - - /** - * @tc.number testbatchInsertWithConflictResolutionInTransaction0013 - * @tc.name batchInsertWithConflictResolutionInTransaction - * @tc.desc conflict batch insert with ON_CONFLICT_FAIL - */ - it('testbatchInsertWithConflictResolutionInTransaction0013', 0, async function (done) { - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0013 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "id" : 2, - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await transaction.insert("test", valueBucket); - let valueBucketArray = new Array(); - for (let i = 0; i < 5; i++) { - var vb = {...valueBucket}; - vb.id = i; - valueBucketArray.push(vb); - } - let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_FAIL) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0013 failed num " + num); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(14800032).assertEqual(e.code) - await transaction.rollback() - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0013 success"); - } - done() - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0013 end *************"); - }) - - /** - * @tc.number testbatchInsertWithConflictResolutionInTransaction0014 - * @tc.name batchInsertWithConflictResolutionInTransaction - * @tc.desc conflict batch insert with ON_CONFLICT_IGNORE - */ - it('testbatchInsertWithConflictResolutionInTransaction0014', 0, async function (done) { - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0014 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "id" : 2, - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await transaction.insert("test", valueBucket); - let valueBucketArray = new Array(); - for (let i = 0; i < 5; i++) { - var vb = {...valueBucket}; - vb.id = i; - valueBucketArray.push(vb); - } - let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_IGNORE) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0014 success num " + num); - expect(4).assertEqual(num) - - let resultSet = await transaction.querySql("select * from test") - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0014 result count " + resultSet.rowCount) - expect(5).assertEqual(resultSet.rowCount) - resultSet.close() - - await transaction.commit() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - await transaction.rollback() - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0014 failed"); - expect(null).assertFail() - } - done() - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0014 end *************"); - }) - - /** - * @tc.number testbatchInsertWithConflictResolutionInTransaction0015 - * @tc.name batchInsertWithConflictResolutionInTransaction - * @tc.desc conflict batch insert with ON_CONFLICT_REPLACE - */ - it('testbatchInsertWithConflictResolutionInTransaction0015', 0, async function (done) { - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0015 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "id" : 2, - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await transaction.insert("test", valueBucket); - let valueBucketArray = new Array(); - for (let i = 0; i < 5; i++) { - var vb = {...valueBucket}; - vb.id = i; - valueBucketArray.push(vb); - } - let num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_REPLACE) - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0015 success num " + num); - expect(5).assertEqual(num) - - let resultSet = await transaction.querySql("select * from test") - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0015 result count " + resultSet.rowCount) - expect(5).assertEqual(resultSet.rowCount) - resultSet.close() - - await transaction.commit() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - await transaction.rollback() - console.log(TAG + "testbatchInsertWithConflictResolutionInTransaction0015 failed"); - expect(null).assertFail() - } - done() - console.log(TAG + "************* testbatchInsertWithConflictResolutionInTransaction0015 end *************"); - }) - - /** - * @tc.number testON_CONFLICT_ROLLBACKInTransaction0021 - * @tc.name InsertWithON_CONFLICT_ROLLBACKInTransaction - * @tc.desc conflict insert with ON_CONFLICT_ROLLBACK - */ - it('testON_CONFLICT_ROLLBACKInTransaction0021', 0, async function (done) { - console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0021 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "name": null, - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var num = await transaction.insert("test", valueBucket, - data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK); - console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0021 fail num " + num); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800032) - try { - await transaction.rollback() - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800021); - } - console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0021 success"); - } - done() - console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0021 end *************"); - }) - - /** - * @tc.number testON_CONFLICT_ROLLBACKInTransaction0022 - * @tc.name InsertWithON_CONFLICT_ROLLBACKInTransaction - * @tc.desc conflict insert with ON_CONFLICT_ROLLBACK - */ - it('testON_CONFLICT_ROLLBACKInTransaction0022', 0, async function (done) { - console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0022 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "name": "zhangsan", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - var num = await transaction.insert("test", valueBucket); - console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0022 insert num " + num) - let predicates = new data_relationalStore.RdbPredicates("test"); - predicates.equalTo("name", "zhangsan"); - const updateValueBucket = { - "name": null, - "age": 28, - "salary": 25, - "blobType": u8, - } - await transaction.update(updateValueBucket, predicates, data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK); - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800032) - try { - await transaction.rollback() - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800014); - } - console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0022 success"); - } - done() - console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0022 end *************"); - }) - - /** - * @tc.number testON_CONFLICT_ROLLBACKInTransaction0023 - * @tc.name BatchInsertWithON_CONFLICT_ROLLBACKInTransaction - * @tc.desc conflict insert with ON_CONFLICT_ROLLBACK - */ - it('testON_CONFLICT_ROLLBACKInTransaction0023', 0, async function (done) { - console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0023 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "name": null, - "age": 18, - "salary": 100.5, - "blobType": u8, - } - let valueBucketArray = new Array(); - valueBucketArray.push(valueBucket); - var num = transaction.batchInsertWithConflictResolutionSync("test", valueBucketArray, - data_relationalStore.ConflictResolution.ON_CONFLICT_ROLLBACK); - console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0023 insert num " + num) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800032) - try { - await transaction.rollback() - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(e.code).assertEqual(14800021); - } - console.log(TAG + "testON_CONFLICT_ROLLBACKInTransaction0023 success"); - } - done() - console.log(TAG + "************* testON_CONFLICT_ROLLBACKInTransaction0023 end *************"); - }) - - /** - * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 - * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs - * @tc.desc batch Insert With ConflictResolution with Invalid Args - */ - it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031', 0, async function (done) { - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction(); - try { - const valueBucket = { - "name": "bbb", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - let valueBucketArray = new Array(); - valueBucketArray.push(valueBucket); - var num = await transaction.batchInsertWithConflictResolution(123, valueBucket, - data_relationalStore.ConflictResolution.ON_CONFLICT_ABORT); - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 insert num " + num) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(String(e.code)).assertEqual(String(401)) - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 success"); - } - await transaction.rollback(); - done() - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0031 end *************"); - }) - - /** - * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 - * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs - * @tc.desc batch Insert With ConflictResolution with Invalid Args - */ - it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032', 0, async function (done) { - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 start *************"); - var transaction = await rdbStore.createTransaction(); - try { - var num = transaction.batchInsertWithConflictResolutionSync("table", undefined, - data_relationalStore.ConflictResolution.ON_CONFLICT_FAIL); - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 insert num " + num) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(String(e.code)).assertEqual(String(401)) - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 success"); - } - await transaction.rollback(); - done() - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0032 end *************"); - }) - - /** - * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 - * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs - * @tc.desc batch Insert With ConflictResolution with Invalid Args - */ - it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033', 0, async function (done) { - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "name": "aaa", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - let valueBucketArray = new Array(); - valueBucketArray.push(valueBucket); - var num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, "abc"); - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 insert num " + num) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(String(e.code)).assertEqual(String(401)) - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 success"); - } - await transaction.rollback(); - done() - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0033 end *************"); - }) - - /** - * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 - * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs - * @tc.desc batch Insert With ConflictResolution with Invalid Args - */ - it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034', 0, async function (done) { - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "name": "aaa", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - let valueBucketArray = new Array(); - valueBucketArray.push(valueBucket); - var num = transaction.batchInsertWithConflictResolutionSync("test", valueBucketArray); - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 insert num " + num) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(String(e.code)).assertEqual(String(401)) - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 success"); - } - await transaction.rollback(); - done() - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0034 end *************"); - }) - - /** - * @tc.number testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 - * @tc.name testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs - * @tc.desc batch Insert With ConflictResolution with Invalid Args - */ - it('testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035', 0, async function (done) { - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - var transaction = await rdbStore.createTransaction() - try { - const valueBucket = { - "name": "aaa", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - let valueBucketArray = new Array(); - let rows = 32768 / 4 + 1; - for (let i = 0; i < rows; i++) { - valueBucketArray.push(valueBucket); - } - var num = await transaction.batchInsertWithConflictResolution("test", valueBucketArray, data_relationalStore.ConflictResolution.ON_CONFLICT_NONE); - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 insert num " + num) - expect(null).assertFail() - } catch (e) { - console.log(TAG + e + " code: " + e.code); - expect(String(e.code)).assertEqual(String(14800000)) - console.log(TAG + "testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 success"); - } - await transaction.rollback(); - done() - console.log(TAG + "************* testBatchInsertWithConflictResolutionInTransactionWithInvalidArgs0035 end *************"); - }) - - console.log(TAG + "*************Unit Test End*************"); -}) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstoreConcurrentQueryWithCrud.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstoreConcurrentQueryWithCrud.test.js index cf01c404..42b60537 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstoreConcurrentQueryWithCrud.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbstoreConcurrentQueryWithCrud.test.js @@ -78,8 +78,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(7); done(); @@ -115,8 +115,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(7); done(); @@ -150,6 +150,7 @@ describe('QueryWithCrudTest', function () { const age = resultSet.getString(resultSet.getColumnIndex("age")); console.log(TAG + "age:" + age); expect().assertFail(); + done(); } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); @@ -190,8 +191,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(0); done(); @@ -234,6 +235,7 @@ describe('QueryWithCrudTest', function () { const age = resultSet.getString(resultSet.getColumnIndex("age")); console.log(TAG + "age:" + age); expect().assertFail(); + done(); } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); @@ -282,14 +284,52 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(9); done(); console.log(TAG + "************* QueryWithDelete006 end *************"); }) + /** + * @tc.name Concurrent query and delet test + * @tc.number QueryWithDelete007 + * @tc.desc 10 records with a total of less than 2M data, + * delete 10 records, rowCount equals 0 records. + */ + it('QueryWithDelete007', 0, async function (done) { + console.log(TAG + "************* QueryWithDelete007 start *************"); + let u8 = new Uint8Array(Array(1).fill(1)); + for (let i = 0; i < 10; i++) { + const valueBucket = { + "name": "zhangsan" + String(i), + "age": i, + "salary": 100.5, + "blobType": u8, + }; + await rdbStore.insert("test", valueBucket); + } + let predicates = new relationalStore.RdbPredicates("test"); + let resultSet = await rdbStore.query(predicates); + predicates.between('age', 0, 9); + let deleteRows = await rdbStore.delete(predicates); + expect(deleteRows).assertEqual(10); + try { + while (resultSet.goToNextRow()) { + const age = resultSet.getString(resultSet.getColumnIndex("age")); + console.log(TAG + "age:" + age); + } + } catch (err) { + console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); + expect().assertFail(); + done(); + } + expect(resultSet.rowCount).assertEqual(0); + done(); + console.log(TAG + "************* QueryWithDelete007 end *************"); + }) + /** * @tc.name Concurrent query and insert test * @tc.number QueryWithInsert001 @@ -328,8 +368,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(7); done(); @@ -376,8 +416,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(9); done(); @@ -421,6 +461,7 @@ describe('QueryWithCrudTest', function () { const age = resultSet.getString(resultSet.getColumnIndex("age")); console.log(TAG + "age:" + age); expect().assertFail(); + done(); } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); @@ -470,8 +511,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(1); done(); @@ -560,8 +601,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(10); done(); @@ -603,8 +644,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(10); done(); @@ -648,8 +689,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } expect(resultSet.rowCount).assertEqual(2); done(); @@ -693,8 +734,8 @@ describe('QueryWithCrudTest', function () { } } catch (err) { console.log(TAG + "catch err: failed, err: code=" + err.code + " message=" + err.message); - done(); expect().assertFail(); + done(); } console.log(TAG + "rowCount:" + resultSet.rowCount); done(); diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstoreEncryptionJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstoreEncryptionJsunit.test.js index a62a80d5..5ca13c1a 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstoreEncryptionJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbstoreEncryptionJsunit.test.js @@ -115,7 +115,7 @@ async function CreateRdbStoreAndInsertData(context, store_config) { "y": 1 } let insertPromise = rdbStore.insert("t", valueBucket) - insertPromise.then(async (ret) => { + await insertPromise.then(async (ret) => { expect(1).assertEqual(ret) }) return rdbStore diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstoreRdbstoreJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstoreRdbstoreJsunit.test.js index 72b830c5..adf60174 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstoreRdbstoreJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbstoreRdbstoreJsunit.test.js @@ -239,9 +239,9 @@ describe('rdbStoreTest', function () { } await data_relationalStore.getRdbStore(context, config1); - try { await data_relationalStore.getRdbStore(context, config2); + done(); } catch (err) { console.log(TAG + "************* testRdbStore0009 end *************"); } @@ -1387,7 +1387,7 @@ describe('rdbStoreTest', function () { done(); } }) - + /** * @tc.name tokenizer supported test * @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_0051 diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstoreTransactionJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstoreTransactionJsunit.test.js deleted file mode 100644 index c5c595ad..00000000 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstoreTransactionJsunit.test.js +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (C) 2021 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' -import data_relationalStore from '@ohos.data.relationalStore' -import ability_featureAbility from '@ohos.ability.featureAbility' -var context = ability_featureAbility.getContext() - -const TAG = "[RELATIONAL_STORE_JSKITS_TEST]" -const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + - "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; - -const STORE_CONFIG = { - name: "TransactionInsertTest.db", - securityLevel: data_relationalStore.SecurityLevel.S1, -} - -var rdbStore = undefined; - -describe('rdbStoreTransactionTest', function () { - beforeAll(async function () { - console.info(TAG + 'beforeAll') - rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); - await rdbStore.executeSql(CREATE_TABLE_TEST, null); - }) - - beforeEach(async function () { - console.info(TAG + 'beforeEach') - - }) - - afterEach(async function () { - console.info(TAG + 'afterEach') - await rdbStore.executeSql("DELETE FROM test"); - }) - - afterAll(async function () { - console.info(TAG + 'afterAll') - rdbStore = null - await data_relationalStore.deleteRdbStore(context, "TransactionInsertTest.db"); - }) - - console.log(TAG + "*************Unit Test Begin*************"); - - /** - * @tc.number testRdbTransactionInsert0001 - * @tc.name Normal test case of transactions, insert a row of data - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute commit - * 4.Query data - */ - it('testRdbTransactionInsert0001', 0, async function (done) { - console.log(TAG + "************* testRdbStoreInsert0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - try { - rdbStore.beginTransaction() - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket) - - rdbStore.commit() - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates) - console.log(TAG + "testRdbTransactionInsert0001 result count " + resultSet.rowCount) - expect(1).assertEqual(resultSet.rowCount) - resultSet.close() - } catch (e) { - console.log(TAG + e); - expect(null).assertFail() - console.log(TAG + "testRdbTransactionInsert0001 failed"); - } - done() - console.log(TAG + "************* testRdbTransactionInsert0001 end *************"); - }) - - /** - * @tc.number testRdbTransactionInsert0002 - * @tc.name Normal test case of transaction, insert three rows of data - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute commit - * 4.Query data - */ - it('testRdbTransactionInsert0002', 0, async function (done) { - console.log(TAG + "************* testRdbStoreInsert0002 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - try { - rdbStore.beginTransaction() - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket) - - const valueBucket1 = { - "name": "zhangsan", - "age": 20, - "salary": 9.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket1) - - - const valueBucket2 = { - "name": "wangwu", - "age": 16, - "salary": 99, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket2) - - rdbStore.commit() - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates) - expect(3).assertEqual(resultSet.rowCount) - resultSet.close() - } catch (e) { - expect(null).assertFail() - console.log(TAG + "testRdbTransactionInsert0002 failed"); - } - done() - console.log(TAG + "************* testRdbTransactionInsert0002 end *************"); - }) - - - /** - * @tc.number testRdbTransactionInsert0003 - * @tc.name Normal test case of transaction, query data before commit - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Query data (expect 0 row) - * 4.Insert data - * 5.Execute commit - */ - it('testRdbTransactionInsert0003', 0, async function (done) { - console.log(TAG + "************* testRdbTransactionInsert0003 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - try { - rdbStore.beginTransaction() - const valueBucket = { - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket) - - const valueBucket1 = { - "name": "zhangsan", - "age": 20, - "salary": 9.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket1) - - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates) - expect(0).assertEqual(resultSet.rowCount) - resultSet.close() - const valueBucket2 = { - "name": "wangwu", - "age": 16, - "salary": 99, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket2) - - rdbStore.commit() - } catch (e) { - expect(null).assertFail() - console.log(TAG + "testRdbTransactionInsert0003 failed"); - } - done() - console.log(TAG + "************* testRdbTransactionInsert0003 end *************"); - }) - - /** - * @tc.number testRdbTransactionInsert0004 - * @tc.name Abnormal test case of transaction insert, if catch exception then rollback - * @tc.desc 1.Execute beginTransaction - * 2.Insert data (primary key conflict) - * 3.Execute rollBack - * 4.Query data - */ - it('testRdbTransactionRollBack0001', 0, async function (done) { - console.log(TAG + "************* testRdbTransactionRollBack0001 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - try { - rdbStore.beginTransaction() - const valueBucket = { - "id": 1, - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket) - await rdbStore.insert("test", valueBucket) - - rdbStore.commit() - } catch (e) { - rdbStore.rollBack() - let predicates = new data_relationalStore.RdbPredicates("test"); - let resultSet = await rdbStore.query(predicates) - console.log(TAG + "testRdbTransactionRollBack0001 result count " + resultSet.rowCount); - expect(0).assertEqual(resultSet.rowCount) - resultSet.close() - } - done() - console.log(TAG + "************* testRdbTransactionRollBack0001 end *************"); - }) - - /** - * @tc.number testRdbTransactionInsert0005 - * @tc.name Normal test case of transaction, begin transactions within a transaction - * @tc.desc 1.Execute beginTransaction - * 2.Insert data - * 3.Execute beginTransaction - * 4.Insert data - * 5.Execute rollBack - * 6.Insert data - * 7.Execute commit - * 8.Query data - */ - it('testRdbTransactionMulti0003', 0, async function (done) { - console.log(TAG + "************* testRdbTransactionMulti0003 start *************"); - var u8 = new Uint8Array([1, 2, 3]) - try { - rdbStore.beginTransaction() - const valueBucket = { - "id": 1, - "name": "lisi", - "age": 18, - "salary": 100.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket); - - rdbStore.beginTransaction() - const valueBucket1 = { - "name": "zhangsan", - "age": 20, - "salary": 220.5, - "blobType": u8, - } - await rdbStore.insert("test", valueBucket1) - - rdbStore.rollBack() - - await rdbStore.insert("test", valueBucket) - rdbStore.commit() - - let predicates = new data_relationalStore.RdbPredicates("test"); - let ret = await rdbStore.query(predicates) - expect(1).assertEqual(ret.rowCount) - ret.close() - } catch (e) { - rdbStore.rollBack() - console.log(TAG + "testRdbTransactionMulti0003 rollback ***** "); - } - done() - console.log(TAG + "************* testRdbTransactionMulti0003 end *************"); - }) - - console.log(TAG + "*************Unit Test End*************"); - -}) \ No newline at end of file diff --git a/relational_store/test/native/appdatafwk/BUILD.gn b/relational_store/test/native/appdatafwk/BUILD.gn index 3d7893bf..a59a48a1 100644 --- a/relational_store/test/native/appdatafwk/BUILD.gn +++ b/relational_store/test/native/appdatafwk/BUILD.gn @@ -30,11 +30,16 @@ config("module_private_config") { ohos_unittest("NativeAppDataFwkTest") { module_out_path = module_output_path - sources = [ "unittest/serializable_test.cpp" ] + sources = [ + "${relational_store_native_path}/appdatafwk/src/serializable.cpp", + "unittest/serializable_test.cpp", + ] configs = [ ":module_private_config" ] external_deps = [ + "json:nlohmann_json_static", + "googletest:gtest_main", "hilog:libhilog", "relational_store:native_appdatafwk", ] @@ -43,7 +48,6 @@ ohos_unittest("NativeAppDataFwkTest") { "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", "${relational_store_innerapi_path}/appdatafwk:relational_common_base", "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", ] } diff --git a/relational_store/test/native/appdatafwk/unittest/serializable_test.cpp b/relational_store/test/native/appdatafwk/unittest/serializable_test.cpp index 4744e929..4eea9094 100644 --- a/relational_store/test/native/appdatafwk/unittest/serializable_test.cpp +++ b/relational_store/test/native/appdatafwk/unittest/serializable_test.cpp @@ -222,4 +222,141 @@ HWTEST_F(SerializableTest, ToJson_04, TestSize.Level1) Serializable::json result = Serializable::ToJson(jsonStr); ASSERT_FALSE(result.is_discarded()); } + +/** +* @tc.name: ToJson_05 +* @tc.desc: test string to json of value with numeric type. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, ToJson_05, TestSize.Level1) +{ + std::string jsonStr = "{\"key\": 10}"; + Serializable::json result = Serializable::ToJson(jsonStr); + uint64_t uint64Value; + bool ret = Serializable::GetValue(result, "key", uint64Value); + ASSERT_TRUE(ret); + + std::string jsonStr2 = "{\"key\": 10.0}"; + Serializable::json result2 = Serializable::ToJson(jsonStr2); + double doubleValue; + ret = Serializable::GetValue(result2, "key", doubleValue); + ASSERT_TRUE(ret); +} + +/** +* @tc.name: GetValueTest001 +* @tc.desc: Test to json when type not match. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, GetValueTest001, TestSize.Level1) +{ + std::string jsonStr = "{\"key\": 10}"; + Serializable::json result = Serializable::ToJson(jsonStr); + + std::string value; + bool ret = Serializable::GetValue(result, "key", value); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(result, "notExist", value); + ASSERT_FALSE(ret); + + std::string jsonStr2 = "{\"key\": \"str\"}"; + Serializable::json strResult = Serializable::ToJson(jsonStr2); + int32_t intValue; + ret = Serializable::GetValue(strResult, "key", intValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", intValue); + ASSERT_FALSE(ret); + + uint32_t uintValue; + ret = Serializable::GetValue(strResult, "key", uintValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", uintValue); + ASSERT_FALSE(ret); + + uint64_t uint64Value; + ret = Serializable::GetValue(strResult, "key", uint64Value); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", uint64Value); + ASSERT_FALSE(ret); + + int64_t int64Value; + ret = Serializable::GetValue(strResult, "key", int64Value); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", int64Value); + ASSERT_FALSE(ret); + + bool boolValue; + ret = Serializable::GetValue(strResult, "key", boolValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", boolValue); + ASSERT_FALSE(ret); + + double doubleValue; + ret = Serializable::GetValue(strResult, "key", doubleValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", doubleValue); + ASSERT_FALSE(ret); + + std::vector arrayValue; + ret = Serializable::GetValue(strResult, "key", arrayValue); + ASSERT_FALSE(ret); + ret = Serializable::GetValue(strResult, "notExist", arrayValue); + ASSERT_FALSE(ret); +} + +/** +* @tc.name: BoundaryTest +* @tc.desc: test boundary. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, BoundaryTest, TestSize.Level1) +{ + struct TestBoundary : public Serializable { + int32_t int32Val; + uint32_t uint32Val; + int64_t int64Val; + uint64_t uint64Val; + bool Marshal(json &node) const override + { + SetValue(node[GET_NAME(int32Val)], int32Val); + SetValue(node[GET_NAME(uint32Val)], uint32Val); + SetValue(node[GET_NAME(int64Val)], int64Val); + SetValue(node[GET_NAME(uint64Val)], uint64Val); + return true; + } + bool Unmarshal(const json &node) override + { + bool success = true; + success = GetValue(node, GET_NAME(int32Val), int32Val) && success; + success = GetValue(node, GET_NAME(uint32Val), uint32Val) && success; + success = GetValue(node, GET_NAME(int64Val), int64Val) && success; + success = GetValue(node, GET_NAME(uint64Val), uint64Val) && success; + return success; + } + }; + TestBoundary in, out; + in.int32Val = INT32_MIN; + in.uint32Val = 0; + in.int64Val = INT64_MIN; + in.uint64Val = 0; + + auto json = to_string(in.Marshall()); + out.Unmarshall(json); + EXPECT_EQ(out.int32Val, in.int32Val); + EXPECT_EQ(out.uint32Val, in.uint32Val); + EXPECT_EQ(out.int64Val, in.int64Val); + EXPECT_EQ(out.uint64Val, in.uint64Val); + + in.int32Val = INT32_MAX; + in.uint32Val = UINT32_MAX; + in.int64Val = INT64_MAX; + in.uint64Val = UINT64_MAX; + + json = to_string(in.Marshall()); + out.Unmarshall(json); + EXPECT_EQ(out.int32Val, in.int32Val); + EXPECT_EQ(out.uint32Val, in.uint32Val); + EXPECT_EQ(out.int64Val, in.int64Val); + EXPECT_EQ(out.uint64Val, in.uint64Val); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/relational_store/test/native/clouddata/BUILD.gn b/relational_store/test/native/clouddata/BUILD.gn index 357e7582..e390161b 100644 --- a/relational_store/test/native/clouddata/BUILD.gn +++ b/relational_store/test/native/clouddata/BUILD.gn @@ -25,6 +25,7 @@ config("module_private_config") { "${relational_store_innerapi_path}/cloud_data/include", "${relational_store_innerapi_path}/common_type/include", "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/rdb_crypt", ] } @@ -33,6 +34,7 @@ ohos_unittest("NativeCloudDataTest") { sources = [ "${cloud_data_native_path}/src/cloud_manager.cpp", + "${cloud_data_native_path}/src/cloud_notifier_stub.cpp", "${cloud_data_native_path}/src/cloud_service_proxy.cpp", "${cloud_data_native_path}/src/cloud_types_util.cpp", "unittest/cloud_data_test.cpp", @@ -54,16 +56,14 @@ ohos_unittest("NativeCloudDataTest") { "access_token:libtoken_setproc", "access_token:libtokenid_sdk", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddata_mgr", "samgr:samgr_proxy", ] - deps = [ - "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", - ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] } ############################################################################### @@ -73,3 +73,13 @@ group("unittest") { deps = [ ":NativeCloudDataTest" ] } ############################################################################### + +group("fuzztest") { + testonly = true + deps = [] + deps += [ + "fuzztest/cloudnotifierstub_fuzzer:fuzztest", + ] +} + +############################################################################### diff --git a/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/BUILD.gn b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/BUILD.gn new file mode 100644 index 00000000..6111e8da --- /dev/null +++ b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("CloudNotifierStubFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/cloud_data/include", + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer" + + sources = [ + "${cloud_data_native_path}/src/cloud_notifier_stub.cpp", + "${relational_store_native_path}/rdb/src/rdb_types_util.cpp", + "cloudnotifierstub_fuzzer.cpp" + ] + + deps = [ "${relational_store_innerapi_path}/cloud_data:cloud_data_inner" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [ ":CloudNotifierStubFuzzTest" ] +} +############################################################################### diff --git a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/gdbstore_fuzzer.cpp b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/cloudnotifierstub_fuzzer.cpp similarity index 40% rename from relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/gdbstore_fuzzer.cpp rename to relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/cloudnotifierstub_fuzzer.cpp index 880eca29..096187c4 100644 --- a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/gdbstore_fuzzer.cpp +++ b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/cloudnotifierstub_fuzzer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 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 @@ -12,57 +12,38 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include -#include "gdbstore_fuzzer.h" - -#include "gdb_helper.h" +#include "cloud_notifier_stub.h" using namespace OHOS; -using namespace OHOS::DistributedDataAip; - +using namespace OHOS::CloudData; namespace OHOS { -const std::string DATABASE_NAME = "gdbStoreFuzz"; -const std::string DATABASE_PATH = "/data/test"; -StoreConfig config_(DATABASE_NAME, DATABASE_PATH); - -std::shared_ptr GetStore() -{ - int errCode = 0; - auto store = GDBHelper::GetDBStore(config_, errCode); - return store; -} - -void GdbQueryFuzz(const uint8_t *data, size_t size) -{ - std::string gql(data, data + size); - auto store = GetStore(); - if (store == nullptr) { - return; - } - store->QueryGql(gql); - GDBHelper::DeleteDBStore(config_); -} +const std::u16string INTERFACE_TOKEN = u"OHOS.CloudData.ICloudNotifier"; +constexpr uint32_t CODE_MIN = 0; +constexpr uint32_t CODE_MAX = 2; -void GdbExecuteFuzz(const uint8_t *data, size_t size) +bool OnRemoteRequestFuzz(FuzzedDataProvider &provider) { - std::string gql(data, data + size); - auto store = GetStore(); - if (store == nullptr) { - return; - } - store->ExecuteGql(gql); - GDBHelper::DeleteDBStore(config_); + auto syncCompleteHandler = [](uint32_t, Details &&) {}; + std::shared_ptr notifierStub = std::make_shared(syncCompleteHandler); + uint32_t code = provider.ConsumeIntegralInRange(CODE_MIN, CODE_MAX); + std::vector remainingData = provider.ConsumeRemainingBytes(); + MessageParcel request; + request.WriteInterfaceToken(INTERFACE_TOKEN); + request.WriteBuffer(static_cast(remainingData.data()), remainingData.size()); + request.RewindRead(0); + MessageParcel reply; + MessageOption option; + notifierStub->OnRemoteRequest(code, request, reply, option); + return true; } } // namespace OHOS /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - /* Run your code on data */ - if (data == nullptr) { - return 0; - } - OHOS::GdbQueryFuzz(data, size); - OHOS::GdbExecuteFuzz(data, size); + FuzzedDataProvider provider(data, size); + OHOS::OnRemoteRequestFuzz(provider); return 0; } \ No newline at end of file diff --git a/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/cloudnotifierstub_fuzzer.h b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/cloudnotifierstub_fuzzer.h new file mode 100644 index 00000000..49d25c3a --- /dev/null +++ b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/cloudnotifierstub_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 CLOUD_NOTIFIER_STUB_FUZZER_H +#define CLOUD_NOTIFIER_STUB_FUZZER_H + +#define FUZZ_PROJECT_NAME "cloudnotifierstub_fuzzer" + +#endif // CLOUD_NOTIFIER_STUB_FUZZER_H diff --git a/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/corpus/init b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/corpus/init new file mode 100644 index 00000000..2aea1356 --- /dev/null +++ b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ diff --git a/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/project.xml b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/clouddata/fuzztest/cloudnotifierstub_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/clouddata/unittest/cloud_data_test.cpp b/relational_store/test/native/clouddata/unittest/cloud_data_test.cpp index 0db6e691..8b583154 100644 --- a/relational_store/test/native/clouddata/unittest/cloud_data_test.cpp +++ b/relational_store/test/native/clouddata/unittest/cloud_data_test.cpp @@ -13,20 +13,27 @@ * limitations under the License. */ +#define LOG_TAG "CloudDataTest" + +#include #include #include #include "accesstoken_kit.h" #include "cloud_manager.h" +#include "cloud_notifier_stub.h" +#include "cloud_service_proxy.h" #include "cloud_types.h" #include "cloud_types_util.h" #include "logger.h" +#include "rdb_types.h" #include "token_setproc.h" namespace OHOS::CloudData { using namespace testing::ext; using namespace OHOS::Security::AccessToken; using namespace OHOS::Rdb; +using namespace DistributedRdb; uint64_t g_selfTokenID = 0; static constexpr const char *TEST_BUNDLE_NAME = "bundleName"; static constexpr const char *TEST_ACCOUNT_ID = "testId"; @@ -146,18 +153,68 @@ public: { SetSelfTokenID(g_selfTokenID); } + + static std::mutex syncCompleteLock_; + static std::condition_variable syncCompleteCv_; + static int32_t progressStatus_; + static int32_t code_; + static constexpr uint32_t delayTime = 2000; }; +std::mutex CloudDataTest::syncCompleteLock_; +std::condition_variable CloudDataTest::syncCompleteCv_; +int32_t CloudDataTest::progressStatus_ = Progress::SYNC_BEGIN; +int32_t CloudDataTest::code_ = ProgressCode::SUCCESS; + void CloudDataTest::SetUpTestCase(void) { + LOG_INFO("SetUpTestCase in."); g_selfTokenID = GetSelfTokenID(); } void CloudDataTest::TearDownTestCase(void) { + LOG_INFO("TearDownTestCase in."); SetSelfTokenID(g_selfTokenID); } +/* * + * @tc.name: CloudSync_SyncComplete_001 + * @tc.desc: Test the CloudSync API with syncComplete callback + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync_SyncComplete_001, TestSize.Level1) +{ + AllocSystemHapToken(g_systemPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&details) { + ASSERT_NE(details.size(), 0); + progressStatus_ = details.begin()->second.progress; + code_ = details.begin()->second.code; + LOG_INFO("CloudSync_SyncComplete_001, progressStatus_:%{public}d, code_:%{public}d", progressStatus_, code_); + if (progressStatus_ == Progress::SYNC_FINISH) { + LOG_INFO("CloudSync_SyncComplete_001, start to notify, progressStatus_:%{public}d, code_:%{public}d", + progressStatus_, code_); + std::unique_lock lock(syncCompleteLock_); + syncCompleteCv_.notify_one(); + } + }; + int32_t syncMode = 4; // 4 is native_first + uint32_t seqNum = 101; + auto status = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, { syncMode, seqNum }, progress); + EXPECT_EQ(status, CloudService::SUCCESS); + std::unique_lock lock(syncCompleteLock_); + auto result = syncCompleteCv_.wait_for(lock, std::chrono::milliseconds(CloudDataTest::delayTime), [] { + LOG_INFO("CloudSync_SyncComplete_001, wait_for in, progressStatus_:%{public}d, code_:%{public}d", + progressStatus_, code_); + return progressStatus_ == Progress::SYNC_FINISH && code_ == ProgressCode::CLOUD_DISABLED; + }); + EXPECT_TRUE(result); + LOG_INFO("CloudSync_SyncComplete_001 test end."); +} + /* * * @tc.name: CloudDataTest_001 * @tc.desc: Test the system application permissions of the QueryStatistics API @@ -180,7 +237,7 @@ HWTEST_F(CloudDataTest, CloudDataTest_001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, CloudDataTest_002, TestSize.Level0) +HWTEST_F(CloudDataTest, CloudDataTest_002, TestSize.Level1) { AllocSystemHapToken(g_notPermissonPolicy); auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -196,7 +253,7 @@ HWTEST_F(CloudDataTest, CloudDataTest_002, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, CloudDataTest_003, TestSize.Level0) +HWTEST_F(CloudDataTest, CloudDataTest_003, TestSize.Level1) { AllocSystemHapToken(g_systemPolicy); auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -259,7 +316,7 @@ HWTEST_F(CloudDataTest, ChangeAppSwitch001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, Clean001, TestSize.Level0) +HWTEST_F(CloudDataTest, Clean001, TestSize.Level1) { AllocSystemHapToken(g_systemPolicy); auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -276,7 +333,7 @@ HWTEST_F(CloudDataTest, Clean001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, NotifyDataChange001, TestSize.Level0) +HWTEST_F(CloudDataTest, NotifyDataChange001, TestSize.Level1) { AllocSystemHapToken(g_systemPolicy); auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -291,7 +348,7 @@ HWTEST_F(CloudDataTest, NotifyDataChange001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, NotifyDataChange002, TestSize.Level0) +HWTEST_F(CloudDataTest, NotifyDataChange002, TestSize.Level1) { AllocSystemHapToken(g_systemPolicy); auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -306,7 +363,7 @@ HWTEST_F(CloudDataTest, NotifyDataChange002, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, SetGlobalCloudStrategy001, TestSize.Level0) +HWTEST_F(CloudDataTest, SetGlobalCloudStrategy001, TestSize.Level1) { AllocSystemHapToken(g_systemPolicy); auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -338,7 +395,7 @@ HWTEST_F(CloudDataTest, QueryLastSyncInfo001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, QueryLastSyncInfo002, TestSize.Level0) +HWTEST_F(CloudDataTest, QueryLastSyncInfo002, TestSize.Level1) { AllocSystemHapToken(g_notPermissonPolicy); auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -514,7 +571,7 @@ HWTEST_F(CloudDataTest, ChangeConfirmation001, TestSize.Level0) * @tc.type: FUNC * @tc.require: */ -HWTEST_F(CloudDataTest, SetCloudStrategy001, TestSize.Level0) +HWTEST_F(CloudDataTest, SetCloudStrategy001, TestSize.Level1) { AllocNormalHapToken(g_normalPolicy); auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -528,4 +585,230 @@ HWTEST_F(CloudDataTest, SetCloudStrategy001, TestSize.Level0) ret = proxy->SetCloudStrategy(strategy, values); EXPECT_EQ(ret, CloudService::SUCCESS); } + +/* * + * @tc.name: CloudSync001 + * @tc.desc: Test the invalid param of the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync001, TestSize.Level1) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto ret = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, {}, nullptr); // no progress + EXPECT_EQ(ret, CloudService::INVALID_ARGUMENT); + LOG_INFO("CloudSync001 test end."); +} + +/* * + * @tc.name: CloudSync002 + * @tc.desc: Test the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync002, TestSize.Level1) +{ + AllocSystemHapToken(g_systemPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&) {}; + auto status = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, {}, progress); + EXPECT_EQ(status, CloudService::INVALID_ARGUMENT); // invalid syncMode + LOG_INFO("CloudSync002 test end."); +} + +/* * + * @tc.name: CloudSync003 + * @tc.desc: Test the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync003, TestSize.Level1) +{ + AllocSystemHapToken(g_systemPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&) {}; + int32_t syncMode = 4; // 4 is native_first + uint32_t seqNum = 10; + auto status = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, { syncMode, seqNum }, progress); + EXPECT_EQ(status, CloudService::SUCCESS); + LOG_INFO("CloudSync003 test end."); +} + +/* * + * @tc.name: CloudSync004 + * @tc.desc: Test the hap permission of the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync004, TestSize.Level1) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&) {}; + int32_t syncMode = 4; // 4 is native_first + uint32_t seqNum = 100; + auto status = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, { syncMode, seqNum }, progress); + EXPECT_EQ(status, CloudService::PERMISSION_DENIED); + LOG_INFO("CloudSync004 test end."); +} + +/* * + * @tc.name: CloudSync005 + * @tc.desc: Test the permissions of the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync005, TestSize.Level1) +{ + AllocSystemHapToken(g_notPermissonPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&) {}; + int32_t syncMode = 4; // 4 is native_first + uint32_t seqNum = 1000; + auto status = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, { syncMode, seqNum }, progress); + EXPECT_EQ(status, CloudService::CLOUD_CONFIG_PERMISSION_DENIED); + LOG_INFO("CloudSync005 test end."); +} + +/* * + * @tc.name: CloudSync006 + * @tc.desc: Test the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync006, TestSize.Level1) +{ + AllocSystemHapToken(g_systemPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&) {}; + int32_t syncMode = 4; // 4 is native_first + uint32_t seqNum = 20; + auto status = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, { syncMode, seqNum }, progress); + EXPECT_EQ(status, CloudService::SUCCESS); + + // same seqNum, register progress failed. + status = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, { syncMode, seqNum }, progress); + EXPECT_EQ(status, CloudService::ERROR); + LOG_INFO("CloudSync006 test end."); +} + +/* * + * @tc.name: CloudSync007 + * @tc.desc: Test the invalid param of the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync007, TestSize.Level1) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&) {}; + int32_t syncMode = 4; // 4 is native_first + uint32_t seqNum = 21; + auto ret = proxy->CloudSync("", TEST_STORE_ID, { syncMode, seqNum }, progress); // bundleName is empty + EXPECT_EQ(ret, CloudService::INVALID_ARGUMENT); + LOG_INFO("CloudSync007 test end."); +} + +/* * + * @tc.name: CloudSync008 + * @tc.desc: Test the invalid param of the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync008, TestSize.Level1) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&) {}; + int32_t syncMode = 4; // 4 is native_first + uint32_t seqNum = 22; + auto ret = proxy->CloudSync(TEST_BUNDLE_NAME, "", { syncMode, seqNum }, progress); // storeId is empty + EXPECT_EQ(ret, CloudService::INVALID_ARGUMENT); + LOG_INFO("CloudSync008 test end."); +} + +/* * + * @tc.name: CloudSync009 + * @tc.desc: Test the invalid param of the CloudSync API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, CloudSync009, TestSize.Level1) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + auto progress = [](DistributedRdb::Details &&) {}; + int32_t syncMode = 10; + uint32_t seqNum = 22; + auto ret = proxy->CloudSync(TEST_BUNDLE_NAME, TEST_STORE_ID, { syncMode, seqNum }, progress); // invalid syncMode + EXPECT_EQ(ret, CloudService::INVALID_ARGUMENT); + LOG_INFO("CloudSync009 test end."); +} + +/* * + * @tc.name: InitNotifier001 + * @tc.desc: Test the InitNotifier API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, InitNotifier001, TestSize.Level1) +{ + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + sptr notifier = nullptr; + auto status = proxy->InitNotifier(notifier); // can not Marshalling a 'nullptr' + EXPECT_EQ(status, CloudService::IPC_PARCEL_ERROR); + LOG_INFO("InitNotifier001 test end."); +} + +/* * + * @tc.name: InitNotifier002 + * @tc.desc: Test the InitNotifier API + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, InitNotifier002, TestSize.Level1) +{ + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + ASSERT_EQ(state == CloudService::SUCCESS && proxy != nullptr, true); + sptr notifier = new (std::nothrow) CloudNotifierStub(nullptr); + auto status = proxy->InitNotifier(notifier); + EXPECT_EQ(status, CloudService::SUCCESS); + LOG_INFO("InitNotifier002 test end."); +} + +/* * + * @tc.name: MarshallingOptionTest + * @tc.desc: Test the Marshalling interface + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(CloudDataTest, MarshallingOptionTest, TestSize.Level1) +{ + LOG_INFO("MarshallingOptionTest test in."); + CloudData::CloudService::Option input; + input.syncMode = 4; + input.seqNum = 10; + MessageParcel parcel; + bool ret = ITypesUtil::Marshalling(input, parcel); + EXPECT_TRUE(ret); + + CloudData::CloudService::Option output; + ret = ITypesUtil::Unmarshalling(output, parcel); + EXPECT_TRUE(ret); + EXPECT_EQ(output.syncMode, input.syncMode); + EXPECT_EQ(output.seqNum, input.seqNum); + LOG_INFO("MarshallingOptionTest test end."); +} } // namespace OHOS::CloudData \ No newline at end of file diff --git a/relational_store/test/native/dataability/BUILD.gn b/relational_store/test/native/dataability/BUILD.gn index 375dcf41..a34491e4 100644 --- a/relational_store/test/native/dataability/BUILD.gn +++ b/relational_store/test/native/dataability/BUILD.gn @@ -22,7 +22,6 @@ config("module_private_config") { include_dirs = [ "${relational_store_native_path}/dataability/include", "${relational_store_innerapi_path}/dataability/include", - "//commonlibrary/c_utils/base/include", ] } @@ -35,15 +34,13 @@ ohos_unittest("NativeDataAbilityTest") { external_deps = [ "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "relational_store:native_dataability", "relational_store:native_rdb", ] - deps = [ - "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", - ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] } ############################################################################### diff --git a/relational_store/test/native/gdb/BUILD.gn b/relational_store/test/native/gdb/BUILD.gn deleted file mode 100644 index 4b1f8e90..00000000 --- a/relational_store/test/native/gdb/BUILD.gn +++ /dev/null @@ -1,221 +0,0 @@ -# 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/distributeddatamgr/relational_store/relational_store.gni") - -module_output_path = "relational_store/relational_store/native_gdb" - -base_sources = [ - "${relational_store_native_path}/gdb/adapter/src/grd_adapter.cpp", - "${relational_store_native_path}/gdb/adapter/src/grd_adapter_manager.cpp", - "${relational_store_native_path}/gdb/src/connection.cpp", - "${relational_store_native_path}/gdb/src/connection_pool.cpp", - "${relational_store_native_path}/gdb/src/db_helper.cpp", - "${relational_store_native_path}/gdb/src/db_store_impl.cpp", - "${relational_store_native_path}/gdb/src/db_store_manager.cpp", - "${relational_store_native_path}/gdb/src/edge.cpp", - "${relational_store_native_path}/gdb/src/full_result.cpp", - "${relational_store_native_path}/gdb/src/gdb_utils.cpp", - "${relational_store_native_path}/gdb/src/graph_connection.cpp", - "${relational_store_native_path}/gdb/src/graph_statement.cpp", - "${relational_store_native_path}/gdb/src/path.cpp", - "${relational_store_native_path}/gdb/src/path_segment.cpp", - "${relational_store_native_path}/gdb/src/store_config.cpp", - "${relational_store_native_path}/gdb/src/trans_db.cpp", - "${relational_store_native_path}/gdb/src/transaction.cpp", - "${relational_store_native_path}/gdb/src/transaction_impl.cpp", - "${relational_store_native_path}/gdb/src/vertex.cpp", - "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", - "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", - "${relational_store_native_path}/rdb/src/rdb_time_utils.cpp", - "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", - "${relational_store_native_path}/rdb/src/string_utils.cpp", -] - -############################################################################### - -ohos_unittest("NativeGdbTest") { - module_out_path = module_output_path - - include_dirs = [ - "${relational_store_common_path}/include", - "${relational_store_innerapi_path}/gdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${relational_store_native_path}/gdb/include", - "${relational_store_native_path}/gdb/adapter/include", - "${relational_store_native_path}/rdb/include", - ] - - sources = base_sources - sources += [ - "unittest/gdb_encrypt_test.cpp", - "unittest/gdb_execute_test.cpp", - "unittest/gdb_function_test.cpp", - "unittest/gdb_grdapi_test.cpp", - "unittest/gdb_multi_thread_test.cpp", - "unittest/gdb_query_test.cpp", - "unittest/gdb_transaction_test.cpp", - ] - - external_deps = [ - "c_utils:utils", - "file_api:securitylabel", - "googletest:gtest_main", - "hilog:libhilog", - "hisysevent:libhisysevent", - "hitrace:hitrace_meter", - "huks:libhukssdk", - "json:nlohmann_json_static", - "kv_store:distributeddata_inner", - ] - if (arkdata_db_core_is_exists) { - defines = [ "ARKDATA_DB_CORE_IS_EXISTS" ] - } -} - -ohos_unittest("NativeGdbAdaptTest") { - module_out_path = module_output_path - - include_dirs = [ - "${relational_store_common_path}/include", - "${relational_store_innerapi_path}/gdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${relational_store_native_path}/gdb/include", - "${relational_store_native_path}/gdb/adapter/include", - "${relational_store_native_path}/rdb/include", - ] - - sources = base_sources - sources += [ "unittest/gdb_adapt_test.cpp" ] - - external_deps = [ - "c_utils:utils", - "file_api:securitylabel", - "googletest:gmock", - "googletest:gtest_main", - "hilog:libhilog", - "hisysevent:libhisysevent", - "hitrace:hitrace_meter", - "huks:libhukssdk", - "json:nlohmann_json_static", - "kv_store:distributeddata_inner", - ] - if (arkdata_db_core_is_exists) { - defines = [ "ARKDATA_DB_CORE_IS_EXISTS" ] - } -} - -ohos_unittest("NativeGdbGrdAdapterTest") { - module_out_path = module_output_path - - include_dirs = [ - "${relational_store_common_path}/include", - "${relational_store_innerapi_path}/gdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${relational_store_native_path}/gdb/include", - "${relational_store_native_path}/gdb/adapter/include", - "${relational_store_native_path}/rdb/include", - ] - - sources = [ - "${relational_store_native_path}/gdb/adapter/src/grd_adapter_manager.cpp", - "${relational_store_native_path}/gdb/src/connection.cpp", - "${relational_store_native_path}/gdb/src/connection_pool.cpp", - "${relational_store_native_path}/gdb/src/db_helper.cpp", - "${relational_store_native_path}/gdb/src/db_store_impl.cpp", - "${relational_store_native_path}/gdb/src/db_store_manager.cpp", - "${relational_store_native_path}/gdb/src/edge.cpp", - "${relational_store_native_path}/gdb/src/full_result.cpp", - "${relational_store_native_path}/gdb/src/gdb_utils.cpp", - "${relational_store_native_path}/gdb/src/graph_connection.cpp", - "${relational_store_native_path}/gdb/src/graph_statement.cpp", - "${relational_store_native_path}/gdb/src/path.cpp", - "${relational_store_native_path}/gdb/src/path_segment.cpp", - "${relational_store_native_path}/gdb/src/store_config.cpp", - "${relational_store_native_path}/gdb/src/trans_db.cpp", - "${relational_store_native_path}/gdb/src/transaction.cpp", - "${relational_store_native_path}/gdb/src/transaction_impl.cpp", - "${relational_store_native_path}/gdb/src/vertex.cpp", - "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", - "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", - "${relational_store_native_path}/rdb/src/rdb_time_utils.cpp", - "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", - "${relational_store_native_path}/rdb/src/string_utils.cpp", - "mock/grd_adapter.cpp", - "unittest/gdb_grd_adapter_test.cpp", - ] - - external_deps = [ - "c_utils:utils", - "file_api:securitylabel", - "googletest:gmock", - "googletest:gtest_main", - "hilog:libhilog", - "hisysevent:libhisysevent", - "hitrace:hitrace_meter", - "huks:libhukssdk", - "json:nlohmann_json_static", - ] - - if (arkdata_db_core_is_exists) { - defines = [ "ARKDATA_DB_CORE_IS_EXISTS" ] - } -} - -ohos_unittest("NativeGdbStoreConfigTest") { - module_out_path = module_output_path - - include_dirs = [ - "${relational_store_common_path}/include", - "${relational_store_innerapi_path}/gdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${relational_store_native_path}/gdb/include", - "${relational_store_native_path}/rdb/include", - ] - - sources = [ - "${relational_store_native_path}/gdb/src/store_config.cpp", - "unittest/gdb_store_config_test.cpp", - ] - - external_deps = [ - "c_utils:utils", - "googletest:gtest_main", - "hilog:libhilog", - "huks:libhukssdk", - ] - if (arkdata_db_core_is_exists) { - defines = [ "ARKDATA_DB_CORE_IS_EXISTS" ] - } -} - -############################################################################### -group("unittest") { - testonly = true - - deps = [ - ":NativeGdbAdaptTest", - ":NativeGdbGrdAdapterTest", - ":NativeGdbStoreConfigTest", - ":NativeGdbTest", - ] -} - -############################################################################### - -group("fuzztest") { - testonly = true - deps = [] - deps += [ "fuzztest/gdbstore_fuzzer:fuzztest" ] -} -############################################################################### diff --git a/relational_store/test/native/gdb/mock/grd_adapter.cpp b/relational_store/test/native/gdb/mock/grd_adapter.cpp deleted file mode 100644 index 35d4e81f..00000000 --- a/relational_store/test/native/gdb/mock/grd_adapter.cpp +++ /dev/null @@ -1,407 +0,0 @@ -/* - * 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 "grd_adapter.h" - -#include -#include - -#include "gdb_errors.h" -#include "gdb_utils.h" -#include "grd_adapter_manager.h" -#include "grd_error.h" - -namespace OHOS::DistributedDataAip { - -static GrdAdapterHolder g_adapterHolder; - -int32_t GrdAdapter::errorCode_[FuncName::ALL] = { GRD_OK }; - -std::map GrdAdapter::GRD_ERRNO_MAP = { - { GRD_OK, E_OK }, - { GRD_REBUILD_DATABASE, E_OK }, - { GRD_NO_DATA, E_GRD_NO_DATA }, - { GRD_DATA_CORRUPTED, E_GRD_DATA_CORRUPTED }, - { GRD_INVALID_FILE_FORMAT, E_GRD_INVALID_FILE_FORMAT }, - { GRD_PRIMARY_KEY_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_RESTRICT_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_CONSTRAINT_CHECK_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_NOT_SUPPORT, E_GRD_NOT_SUPPORT }, - { GRD_OVER_LIMIT, E_GRD_OVER_LIMIT }, - { GRD_INVALID_ARGS, E_GRD_INVALID_ARGS }, - { GRD_FAILED_FILE_OPERATION, E_GRD_FAILED_FILE_OPERATION }, - { GRD_INSUFFICIENT_SPACE, E_GRD_DISK_SPACE_FULL }, - { GRD_RESOURCE_BUSY, E_DATABASE_BUSY }, - { GRD_DB_BUSY, E_DATABASE_BUSY }, - { GRD_FAILED_MEMORY_ALLOCATE, E_GRD_FAILED_MEMORY_ALLOCATE }, - { GRD_CRC_CHECK_DISABLED, E_GRD_CRC_CHECK_DISABLED }, - { GRD_DISK_SPACE_FULL, E_GRD_DISK_SPACE_FULL }, - - { GRD_PERMISSION_DENIED, E_GRD_PERMISSION_DENIED }, - { GRD_PASSWORD_UNMATCHED, E_GRD_PASSWORD_UNMATCHED }, - { GRD_PASSWORD_NEED_REKEY, E_GRD_PASSWORD_NEED_REKEY }, - - { GRD_NAME_TOO_LONG, E_GRD_INVALID_NAME }, - { GRD_INVALID_TABLE_DEFINITION, E_GRD_SEMANTIC_ERROR }, - { GRD_SEMANTIC_ERROR, E_GRD_SEMANTIC_ERROR }, - { GRD_SYNTAX_ERROR, E_GRD_SYNTAX_ERROR }, - { GRD_WRONG_STMT_OBJECT, E_GRD_WRONG_STMT_OBJECT }, - { GRD_DATA_CONFLICT, E_GRD_DATA_CONFLICT }, - - { GRD_INNER_ERR, E_GRD_INNER_ERR }, - { GRD_FAILED_MEMORY_RELEASE, E_GRD_FAILED_MEMORY_RELEASE }, - { GRD_NOT_AVAILABLE, E_GRD_NOT_AVAILABLE }, - { GRD_INVALID_FORMAT, E_GRD_SEMANTIC_ERROR }, - { GRD_TIME_OUT, E_DATABASE_BUSY }, - { GRD_DB_INSTANCE_ABNORMAL, E_GRD_DB_INSTANCE_ABNORMAL }, - { GRD_CIPHER_ERROR, E_GRD_CIPHER_ERROR }, - { GRD_DUPLICATE_TABLE, E_GRD_DUPLICATE_PARAM }, - { GRD_DUPLICATE_OBJECT, E_GRD_DUPLICATE_PARAM }, - { GRD_DUPLICATE_COLUMN, E_GRD_DUPLICATE_PARAM }, - { GRD_UNDEFINE_COLUMN, E_GRD_UNDEFINED_PARAM }, - { GRD_UNDEFINED_OBJECT, E_GRD_UNDEFINED_PARAM }, - { GRD_UNDEFINED_TABLE, E_GRD_UNDEFINED_PARAM }, - { GRD_INVALID_CONFIG_VALUE, E_CONFIG_INVALID_CHANGE }, - { GRD_REQUEST_TIME_OUT, E_DATABASE_BUSY }, - { GRD_DATATYPE_MISMATCH, E_GRD_SEMANTIC_ERROR }, - { GRD_UNIQUE_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_INVALID_BIND_VALUE, E_GRD_INVALID_BIND_VALUE }, - { GRD_JSON_OPERATION_NOT_SUPPORT, E_GRD_SEMANTIC_ERROR }, - { GRD_MODEL_NOT_SUPPORT, E_GRD_SEMANTIC_ERROR }, - { GRD_FEATURE_NOT_SUPPORTED, E_GRD_SEMANTIC_ERROR }, - { GRD_JSON_LEN_LIMIT, E_GRD_DATA_CONFLICT }, - { GRD_SUBSCRIPTION_EXCEEDED_LIMIT, E_GRD_INNER_ERR }, - { GRD_SYNC_EXCEED_TASK_QUEUE_LIMIT, E_DATABASE_BUSY }, - { GRD_SHARED_OBJ_ENABLE_UNDO_EXCEED_LIMIT, E_GRD_INNER_ERR }, - { GRD_TABLE_LIMIT_EXCEEDED, E_GRD_OVER_LIMIT }, - { GRD_FIELD_TYPE_NOT_MATCH, E_GRD_SEMANTIC_ERROR }, - { GRD_LARGE_JSON_NEST, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_JSON_TYPE, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_OPERATOR, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_PROJECTION_FIELD, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_PROJECTION_VALUE, E_GRD_SEMANTIC_ERROR }, - { GRD_DB_NOT_EXIST, E_GRD_DB_NOT_EXIST }, - { GRD_INVALID_VALUE, E_GRD_INVALID_ARGS }, - { GRD_SHARED_OBJ_NOT_EXIST, E_GRD_DATA_NOT_FOUND }, - { GRD_SUBSCRIBE_NOT_EXIST, E_GRD_DATA_NOT_FOUND }, - { GRD_COLLECTION_NOT_EXIST, E_GRD_DATA_NOT_FOUND }, - { GRD_RESULTSET_BUSY, E_DATABASE_BUSY }, - { GRD_RECORD_NOT_FOUND, E_GRD_DATA_NOT_FOUND }, - { GRD_FIELD_NOT_FOUND, E_GRD_DATA_NOT_FOUND }, - { GRD_ARRAY_INDEX_NOT_FOUND, E_GRD_DATA_NOT_FOUND }, - { GRD_RESULT_SET_NOT_AVAILABLE, E_GRD_DATA_NOT_FOUND }, - { GRD_SHARED_OBJ_UNDO_NOT_AVAILABLE, E_GRD_DATA_NOT_FOUND }, - { GRD_SHARED_OBJ_REDO_NOT_AVAILABLE, E_GRD_DATA_NOT_FOUND }, - { GRD_INVALID_JSON_FORMAT, E_GRD_DATA_CONFLICT }, - { GRD_INVALID_KEY_FORMAT, E_GRD_INVALID_NAME }, - { GRD_INVALID_COLLECTION_NAME, E_GRD_INVALID_NAME }, - { GRD_INVALID_EQUIP_ID, E_GRD_SEMANTIC_ERROR }, - { GRD_KEY_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_FIELD_TYPE_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_SHARED_OBJ_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_SUBSCRIBE_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_EQUIP_ID_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_SHARED_OBJ_ENABLE_UNDO_CONFLICT, E_GRD_DATA_CONFLICT }, - { GRD_SCHEMA_CHANGED, E_CONFIG_INVALID_CHANGE }, - { GRD_DATA_EXCEPTION, E_GRD_DATA_EXCEPTION }, - { GRD_FIELD_OVERFLOW, E_GRD_SEMANTIC_ERROR }, - { GRD_DIVISION_BY_ZERO, E_GRD_SYNTAX_ERROR }, - { GRD_TRANSACTION_ROLLBACK, E_GRD_TRANSACTION_ROLLBACK }, - { GRD_NO_ACTIVE_TRANSACTION, E_GRD_NO_ACTIVE_TRANSACTION }, - { GRD_ACTIVE_TRANSACTION, E_GRD_ACTIVE_TRANSACTION }, -}; - -int GrdAdapter::TransErrno(int err) -{ - if (err > 0) { - return err; - } - auto result = GRD_ERRNO_MAP.find(err); - if (result != GRD_ERRNO_MAP.end()) { - return result->second; - } - return E_GRD_INNER_ERR; -} - -void GrdAdapter::SetErrorCode(FuncName func, int32_t err) -{ - if (func == FuncName::ALL) { - for (int i = FuncName::PREPARE; i < FuncName::ALL; i++) { - errorCode_[i] = err; - } - } else { - errorCode_[func] = err; - } -} - -int32_t GrdAdapter::Prepare(GRD_DB *db, const char *str, uint32_t strLen, GRD_StmtT **stmt, const char **unusedStr) -{ - if (errorCode_[FuncName::PREPARE] == GRD_OK) { - if (g_adapterHolder.Prepare == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Prepare == nullptr) { - return E_NOT_SUPPORT; - } - int32_t ret = g_adapterHolder.Prepare(db, str, strLen, stmt, unusedStr); - return TransErrno(ret); - } - return TransErrno(errorCode_[FuncName::PREPARE]); -} - -int32_t GrdAdapter::Step(GRD_StmtT *stmt) -{ - if (errorCode_[FuncName::STEP] == GRD_OK) { - if (g_adapterHolder.Step == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Step == nullptr) { - return E_NOT_SUPPORT; - } - int32_t ret = g_adapterHolder.Step(stmt); - return TransErrno(ret); - } - return TransErrno(errorCode_[FuncName::STEP]); -} - -int32_t GrdAdapter::Finalize(GRD_StmtT *stmt) -{ - if (errorCode_[FuncName::FINALIZE] == GRD_OK) { - if (g_adapterHolder.Finalize == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Finalize == nullptr) { - return E_NOT_SUPPORT; - } - int32_t ret = g_adapterHolder.Finalize(stmt); - return TransErrno(ret); - } - return TransErrno(errorCode_[FuncName::FINALIZE]); -} - -int32_t GrdAdapter::Rekey(const char *dbFile, const char *configStr, const std::vector &encryptedKey) -{ - if (errorCode_[FuncName::REKEY] == GRD_OK) { - if (g_adapterHolder.Rekey == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Rekey == nullptr) { - return E_NOT_SUPPORT; - } - if (encryptedKey.empty()) { - return E_GRD_INVALID_ARGS; - } - int32_t ret = E_OK; - GRD_CipherInfoT info = { 0 }; - const size_t keySize = encryptedKey.size() * 2 + 1; - std::vector key(keySize); - info.hexPassword = GdbUtils::GetEncryptKey(encryptedKey, key.data(), keySize); - ret = g_adapterHolder.Rekey(dbFile, configStr, &info); - key.assign(keySize, 0); - return TransErrno(ret); - } - return TransErrno(errorCode_[FuncName::REKEY]); -} - -ColumnType GrdAdapter::TransColType(int grdColType) -{ - switch (grdColType) { - case GRD_DB_DATATYPE_INTEGER: - return ColumnType::TYPE_INTEGER; - case GRD_DB_DATATYPE_FLOAT: - return ColumnType::TYPE_FLOAT; - case GRD_DB_DATATYPE_TEXT: - return ColumnType::TYPE_TEXT; - case GRD_DB_DATATYPE_BLOB: - return ColumnType::TYPE_BLOB; - case GRD_DB_DATATYPE_FLOATVECTOR: - return ColumnType::TYPE_FLOATVECTOR; - case GRD_DB_DATATYPE_JSONSTR: - return ColumnType::TYPE_JSONSTR; - case GRD_DB_DATATYPE_NULL: - return ColumnType::TYPE_NULL; - default: - return ColumnType::TYPE_NULL; - } -} - -int GrdAdapter::Open(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB **db) -{ - if (g_adapterHolder.Open == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Open == nullptr) { - return E_NOT_SUPPORT; - } - auto ret = g_adapterHolder.Open(dbPath, configStr, flags, db); - return TransErrno(ret); -} - -int GrdAdapter::Close(GRD_DB *db, uint32_t flags) -{ - if (g_adapterHolder.Close == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Close == nullptr) { - return E_NOT_SUPPORT; - } - auto ret = g_adapterHolder.Close(db, flags); - return TransErrno(ret); -} - -int GrdAdapter::Repair(const char *dbPath, const char *configStr) -{ - if (g_adapterHolder.Repair == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Repair == nullptr) { - return E_NOT_SUPPORT; - } - return E_NOT_SUPPORT; -} - -int GrdAdapter::Backup(GRD_DB *db, const char *backupDbFile, const std::vector &encryptedKey) -{ - if (g_adapterHolder.Backup == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Backup == nullptr) { - return E_NOT_SUPPORT; - } - return E_NOT_SUPPORT; -} - -int GrdAdapter::Restore(const char *dbFile, const char *backupDbFile, const std::vector &encryptedKey) -{ - if (g_adapterHolder.Restore == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Restore == nullptr) { - return E_NOT_SUPPORT; - } - return E_NOT_SUPPORT; -} - -int32_t GrdAdapter::Reset(GRD_StmtT *stmt) -{ - if (g_adapterHolder.Reset == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.Reset == nullptr) { - return E_NOT_SUPPORT; - } - return TransErrno(g_adapterHolder.Reset(stmt)); -} - -uint32_t GrdAdapter::ColumnCount(GRD_StmtT *stmt) -{ - if (g_adapterHolder.ColumnCount == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnCount == nullptr) { - return E_NOT_SUPPORT; - } - return g_adapterHolder.ColumnCount(stmt); -} - -GRD_DbDataTypeE GrdAdapter::ColumnType(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.GetColumnType == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.GetColumnType == nullptr) { - return GRD_DB_DATATYPE_NULL; - } - return g_adapterHolder.GetColumnType(stmt, idx); -} - -uint32_t GrdAdapter::ColumnBytes(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnBytes == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnBytes == nullptr) { - return E_NOT_SUPPORT; - } - return g_adapterHolder.ColumnBytes(stmt, idx); -} - -char *GrdAdapter::ColumnName(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnName == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnName == nullptr) { - return nullptr; - } - return g_adapterHolder.ColumnName(stmt, idx); -} - -GRD_DbValueT GrdAdapter::ColumnValue(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnValue == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnValue == nullptr) { - return {}; - } - return g_adapterHolder.ColumnValue(stmt, idx); -} - -int64_t GrdAdapter::ColumnInt64(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnInt64 == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnInt64 == nullptr) { - return 0; - } - return g_adapterHolder.ColumnInt64(stmt, idx); -} - -int32_t GrdAdapter::ColumnInt(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnInt == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnInt == nullptr) { - return 0; - } - return g_adapterHolder.ColumnInt(stmt, idx); -} - -double GrdAdapter::ColumnDouble(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnDouble == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnDouble == nullptr) { - return 0; - } - return g_adapterHolder.ColumnDouble(stmt, idx); -} - -const char *GrdAdapter::ColumnText(GRD_StmtT *stmt, uint32_t idx) -{ - if (g_adapterHolder.ColumnText == nullptr) { - g_adapterHolder = GetAdapterHolder(); - } - if (g_adapterHolder.ColumnText == nullptr) { - return nullptr; - } - return g_adapterHolder.ColumnText(stmt, idx); -} -} - diff --git a/relational_store/test/native/gdb/mock/grd_adapter.h b/relational_store/test/native/gdb/mock/grd_adapter.h deleted file mode 100644 index c1b10547..00000000 --- a/relational_store/test/native/gdb/mock/grd_adapter.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 OHOS_DISTRIBUTED_DATA_NATIVE_MOCK_GRD_ADAPTER_H -#define OHOS_DISTRIBUTED_DATA_NATIVE_MOCK_GRD_ADAPTER_H - -#include -#include -#include -#include - -#include "full_result.h" -#include "grd_error.h" -#include "grd_type_export.h" -#include "statement.h" - -namespace OHOS::DistributedDataAip { -class GrdAdapter { -public: - enum FuncName : int32_t { - PREPARE = 0, - STEP, - FINALIZE, - REKEY, - ALL - }; - - static void SetErrorCode(FuncName func, int32_t err); - - static int32_t Prepare(GRD_DB *db, const char *str, uint32_t strLen, GRD_StmtT **stmt, const char **unusedStr); - static int32_t Step(GRD_StmtT *stmt); - static int32_t Finalize(GRD_StmtT *stmt); - static int32_t Rekey(const char *dbFile, const char *configStr, const std::vector &encryptedKey); - - static ColumnType TransColType(int grdColType); - static int Open(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB **db); - static int Repair(const char *dbPath, const char *configStr); - static int Close(GRD_DB *db, uint32_t flags); - static int32_t Reset(GRD_StmtT *stmt); - static uint32_t ColumnCount(GRD_StmtT *stmt); - static GRD_DbDataTypeE ColumnType(GRD_StmtT *stmt, uint32_t idx); - static uint32_t ColumnBytes(GRD_StmtT *stmt, uint32_t idx); - static char *ColumnName(GRD_StmtT *stmt, uint32_t idx); - static GRD_DbValueT ColumnValue(GRD_StmtT *stmt, uint32_t idx); - static int64_t ColumnInt64(GRD_StmtT *stmt, uint32_t idx); - static int32_t ColumnInt(GRD_StmtT *stmt, uint32_t idx); - static double ColumnDouble(GRD_StmtT *stmt, uint32_t idx); - static const char *ColumnText(GRD_StmtT *stmt, uint32_t idx); - - static int Backup(GRD_DB *db, const char *backupDbFile, const std::vector &encryptedKey); - static int Restore(const char *dbFile, const char *backupDbFile, const std::vector &encryptedKey); - -private: - static int TransErrno(int err); - - static int32_t errorCode_[FuncName::ALL]; - static std::map GRD_ERRNO_MAP; -}; -} -#endif // OHOS_DISTRIBUTED_DATA_NATIVE_MOCK_GRD_ADAPTER_H - diff --git a/relational_store/test/native/gdb/unittest/gdb_adapt_test.cpp b/relational_store/test/native/gdb/unittest/gdb_adapt_test.cpp deleted file mode 100644 index d480ad83..00000000 --- a/relational_store/test/native/gdb/unittest/gdb_adapt_test.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/* - * 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 "gmock/gmock.h" -#include "grd_adapter_manager.h" -#include "grd_adapter.h" -#include "gdb_store.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; -using ::testing::Return; -using ::testing::NiceMock; -class MockDlsym { -public: - MOCK_METHOD(void *, dlopen, (const char *fileName, int flag)); - MOCK_METHOD(void *, dlsym, (void *handle, const char *symbol)); -}; - -NiceMock *mockDlsym; - -extern "C" { - // mock dlopen - void *dlopen(const char *fileName, int flag) - { - if (mockDlsym == nullptr) { - mockDlsym = new NiceMock(); - } - return mockDlsym->dlopen(fileName, flag); - } - - // mock dlsym - void *dlsym(void *handle, const char *symbol) - { - if (mockDlsym == nullptr) { - mockDlsym = new NiceMock(); - } - return mockDlsym->dlsym(handle, symbol); - } -} - -class GdbAdaptTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - void MockAllSymbols(); - static const std::string databaseName; - static const std::string databasePath; - const std::vector> mockSymbols = { - {"GRD_DBOpen", reinterpret_cast(0x1111)}, - {"GRD_DBClose", reinterpret_cast(0x2222)}, - {"GRD_DBRepair", reinterpret_cast(0x3333)}, - {"GRD_GqlPrepare", reinterpret_cast(0x4444)}, - {"GRD_GqlReset", reinterpret_cast(0x5555)}, - {"GRD_GqlFinalize", reinterpret_cast(0x6666)}, - {"GRD_GqlStep", reinterpret_cast(0x7777)}, - {"GRD_GqlColumnCount", reinterpret_cast(0x8888)}, - {"GRD_GqlColumnType", reinterpret_cast(0x9999)}, - {"GRD_GqlColumnBytes", reinterpret_cast(0xaaaa)}, - {"GRD_GqlColumnName", reinterpret_cast(0xbbbb)}, - {"GRD_GqlColumnValue", reinterpret_cast(0xcccc)}, - {"GRD_GqlColumnInt64", reinterpret_cast(0xdddd)}, - {"GRD_GqlColumnInt", reinterpret_cast(0xeeee)}, - {"GRD_GqlColumnDouble", reinterpret_cast(0xffff)}, - {"GRD_GqlColumnText", reinterpret_cast(0x1112)}, - {"GRD_DBBackup", reinterpret_cast(0x1222)}, - {"GRD_DBRestore", reinterpret_cast(0x1333)}, - {"GRD_DBRekey", reinterpret_cast(0x1444)}, - }; -}; - -const std::string GdbAdaptTest::databaseName = "execute_test"; -const std::string GdbAdaptTest::databasePath = "/data"; - -void GdbAdaptTest::SetUpTestCase(void) -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } - mockDlsym = new NiceMock(); -} - -void GdbAdaptTest::TearDownTestCase(void) -{ - delete mockDlsym; - mockDlsym = nullptr; -} - -void GdbAdaptTest::SetUp() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } -} - -void GdbAdaptTest::TearDown() -{ -} - -void GdbAdaptTest::MockAllSymbols() -{ - EXPECT_CALL(*mockDlsym, dlopen(::testing::_, RTLD_LAZY)) - .WillRepeatedly(Return(reinterpret_cast(0x1234))); - - for (const auto &symbol : mockSymbols) { - EXPECT_CALL(*mockDlsym, dlsym(::testing::_, ::testing::StrEq(symbol.first.c_str()))) - .WillRepeatedly(Return(symbol.second)); - } -} - -/** - * @tc.name: GdbAdaptTest_Dlopen01 - * @tc.desc: No Mock All Symbols - * @tc.type: FUNC - */ -HWTEST_F(GdbAdaptTest, GdbAdaptTest_Dlopen01, TestSize.Level2) -{ - GetAdapterHolder(); - EXPECT_CALL(*mockDlsym, dlopen(::testing::_, RTLD_LAZY)) - .WillRepeatedly(Return(reinterpret_cast(0x1234))); - GrdAdapterHolder holder = GetAdapterHolder(); - EXPECT_EQ(holder.Open, nullptr); - EXPECT_EQ(holder.Close, nullptr); - EXPECT_EQ(holder.Repair, nullptr); - EXPECT_EQ(holder.Prepare, nullptr); - EXPECT_EQ(holder.Reset, nullptr); - EXPECT_EQ(holder.Finalize, nullptr); - EXPECT_EQ(holder.Step, nullptr); - EXPECT_EQ(holder.ColumnCount, nullptr); - EXPECT_EQ(holder.GetColumnType, nullptr); - EXPECT_EQ(holder.ColumnBytes, nullptr); - EXPECT_EQ(holder.ColumnName, nullptr); - EXPECT_EQ(holder.ColumnValue, nullptr); - EXPECT_EQ(holder.ColumnInt64, nullptr); - EXPECT_EQ(holder.ColumnInt, nullptr); - EXPECT_EQ(holder.ColumnDouble, nullptr); - EXPECT_EQ(holder.ColumnText, nullptr); - EXPECT_EQ(holder.Backup, nullptr); - EXPECT_EQ(holder.Restore, nullptr); - EXPECT_EQ(holder.Rekey, nullptr); - GrdAdapter::Open(databaseName.c_str(), databasePath.c_str(), 1, nullptr); - GrdAdapter::Close(nullptr, 1); - GrdAdapter::Repair(databasePath.c_str(), {}); - GrdAdapter::Prepare(nullptr, databaseName.c_str(), 1, nullptr, nullptr); - GrdAdapter::Reset(nullptr); - GrdAdapter::Finalize(nullptr); - GrdAdapter::Step(nullptr); - GrdAdapter::ColumnCount(nullptr); - GrdAdapter::ColumnType(nullptr, 1); - GrdAdapter::ColumnBytes(nullptr, 1); - GrdAdapter::ColumnName(nullptr, 1); - GrdAdapter::ColumnValue(nullptr, 1); - GrdAdapter::ColumnInt64(nullptr, 1); - GrdAdapter::ColumnInt(nullptr, 1); - GrdAdapter::ColumnDouble(nullptr, 1); - GrdAdapter::ColumnText(nullptr, 1); - GrdAdapter::Backup(nullptr, databaseName.c_str(), {}); - GrdAdapter::Restore(nullptr, databaseName.c_str(), {}); - GrdAdapter::Rekey(nullptr, databaseName.c_str(), {}); -} - -/** - * @tc.name: GdbAdaptTest_Dlopen02 - * @tc.desc: Mock All Symbols test. - * @tc.type: FUNC - */ -HWTEST_F(GdbAdaptTest, GdbAdaptTest_Dlopen02, TestSize.Level2) -{ - EXPECT_CALL(*mockDlsym, dlopen(::testing::_, RTLD_LAZY)) - .WillRepeatedly(Return(reinterpret_cast(0x1234))); - MockAllSymbols(); - GrdAdapterHolder holder = GetAdapterHolder(); - EXPECT_NE(holder.Open, nullptr); - EXPECT_NE(holder.Close, nullptr); - EXPECT_NE(holder.Repair, nullptr); - EXPECT_NE(holder.Prepare, nullptr); - EXPECT_NE(holder.Reset, nullptr); - EXPECT_NE(holder.Finalize, nullptr); - EXPECT_NE(holder.Step, nullptr); - EXPECT_NE(holder.ColumnCount, nullptr); - EXPECT_NE(holder.GetColumnType, nullptr); - EXPECT_NE(holder.ColumnBytes, nullptr); - EXPECT_NE(holder.ColumnName, nullptr); - EXPECT_NE(holder.ColumnValue, nullptr); - EXPECT_NE(holder.ColumnInt64, nullptr); - EXPECT_NE(holder.ColumnInt, nullptr); - EXPECT_NE(holder.ColumnDouble, nullptr); - EXPECT_NE(holder.ColumnText, nullptr); - EXPECT_NE(holder.Backup, nullptr); - EXPECT_NE(holder.Restore, nullptr); - EXPECT_NE(holder.Rekey, nullptr); -} \ No newline at end of file diff --git a/relational_store/test/native/gdb/unittest/gdb_encrypt_test.cpp b/relational_store/test/native/gdb/unittest/gdb_encrypt_test.cpp deleted file mode 100644 index 14551571..00000000 --- a/relational_store/test/native/gdb/unittest/gdb_encrypt_test.cpp +++ /dev/null @@ -1,460 +0,0 @@ -/* - * 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 "gdb_errors.h" -#include "db_store_impl.h" -#include "db_store_manager.h" -#include "edge.h" -#include "grd_adapter.h" -#include "grd_adapter_manager.h" -#include "gdb_helper.h" -#include "gdb_store.h" -#include "gdb_utils.h" -#include "graph_statement.h" -#include "graph_connection.h" -#include "path.h" -#include "result.h" -#include "vertex.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; -class GdbEncryptTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase(); - void SetUp(); - void TearDown(); - void VerifyPersonInfo(const GraphValue &person, const std::string &name, const int32_t &age); - static const std::string createGraphGql; - static const std::string databasePath; -}; -const std::string GdbEncryptTest::databasePath = "/data"; -const std::string GdbEncryptTest::createGraphGql = "CREATE GRAPH test { " - "(person:Person {name STRING, age INT, sex BOOL DEFAULT false})," - "(dog:Dog {name STRING, age INT}), " - "(person) -[:Friend]-> (person) " - "};"; - -void GdbEncryptTest::SetUpTestCase() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } -} - -void GdbEncryptTest::TearDownTestCase() -{ -} - -void GdbEncryptTest::SetUp() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } -} - -void GdbEncryptTest::TearDown() -{ -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_DeaultIsUnencrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "DeaultIsUnencrypt"; - std::string dbPath = databasePath; - // DeaultIsUnencrypt - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - store->Close(); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_Unencrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "Unencrypt"; - std::string dbPath = databasePath; - // Unencryptdb - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, false); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - store->Close(); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_Encrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "Encrypt"; - std::string dbPath = databasePath; - // Unencryptdb - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, true); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - store->Close(); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_UnencryptToEncrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "UnencryptToEncrypt"; - std::string dbPath = databasePath; - // Unencryptdb - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, false); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - result.second = nullptr; - store->Close(); - StoreManager::GetInstance().Clear(); - // Unencryptdb to encryptdb - config.SetEncryptStatus(true); - store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - if (store != nullptr) { - result = store->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 22}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_2", 22); - store->Close(); - } - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_EncryptToUnencrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "EncryptToUnencrypt"; - std::string dbPath = databasePath; - // encryptdb - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, true); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - store->Close(); - StoreManager::GetInstance().Clear(); - // encryptdb to Unencryptdb - config.SetEncryptStatus(false); - store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_CONFIG_INVALID_CHANGE); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_DefaultToEncrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "DefaultToEncrypt"; - std::string dbPath = databasePath; - // Unencryptdb - auto config = StoreConfig(dbName, dbPath); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - result.second = nullptr; - store->Close(); - StoreManager::GetInstance().Clear(); - // Unencryptdb to encryptdb - config.SetEncryptStatus(true); - store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - if (store != nullptr) { - result = store->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 22}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_2", 22); - store->Close(); - } - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_EncryptToEncrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "EncryptToUnencrypt"; - std::string dbPath = databasePath; - // encryptdb - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, true); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - store->Close(); - StoreManager::GetInstance().Clear(); - // encryptdb to encryptdb - config.SetEncryptStatus(true); - store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 22}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_2", 22); - store->Close(); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_UnencryptToUnencrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "UnencryptToEncrypt"; - std::string dbPath = databasePath; - // Unencryptdb - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, false); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - store->Close(); - StoreManager::GetInstance().Clear(); - // Unencryptdb to Unencryptdb - config.SetEncryptStatus(false); - store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 22}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_2", 22); - store->Close(); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_DefaultToUnencrypt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "UnencryptToEncrypt"; - std::string dbPath = databasePath; - // Unencryptdb - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - store->Close(); - StoreManager::GetInstance().Clear(); - // Unencryptdb to Unencryptdb - config.SetEncryptStatus(false); - store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - result = store->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(result.first, E_OK); - result = store->QueryGql("MATCH (person:Person {age: 22}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_2", 22); - store->Close(); - GDBHelper::DeleteDBStore(config); -} - -void GdbEncryptTest::VerifyPersonInfo(const GraphValue &person, const std::string &name, const int32_t &age) -{ - auto expectSize = 3; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), expectSize); - - auto nameDb = personVertex->GetProperties().find("name"); - ASSERT_NE(nameDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(nameDb->second)); - EXPECT_EQ(std::get(nameDb->second), name); - - auto ageDb = personVertex->GetProperties().find("age"); - ASSERT_NE(ageDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(ageDb->second)); - EXPECT_EQ(std::get(ageDb->second), age); - - auto sex = personVertex->GetProperties().find("sex"); - ASSERT_NE(sex, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(sex->second)); - EXPECT_EQ(std::get(sex->second), 0); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_Config, TestSize.Level1) -{ - std::string dbName = "UnencryptToEncrypt"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH); - EXPECT_EQ(config.IsEncrypt(), false); - config.GenerateEncryptedKey(); - EXPECT_EQ(config.GetEncryptKey().size(), 0); - EXPECT_EQ(config.GetNewEncryptKey().size(), 0); - - config.SetBundleName(""); - EXPECT_EQ(config.GetBundleName(), ""); - config.SetEncryptStatus(true); - EXPECT_EQ(config.IsEncrypt(), true); - config.SetBundleName("test_name"); - EXPECT_EQ(config.GetBundleName(), "test_name"); - // empty return E_ERROR - EXPECT_EQ(config.SetBundleName(""), E_ERROR); - EXPECT_EQ(config.GetBundleName(), "test_name"); - - config.GenerateEncryptedKey(); - // not exists bundleName, failed - EXPECT_EQ(config.GetEncryptKey().size(), 0); - EXPECT_EQ(config.GetNewEncryptKey().size(), 0); - config.ChangeEncryptKey(); - config.GenerateEncryptedKey(); - config.ChangeEncryptKey(); -} - -HWTEST_F(GdbEncryptTest, GdbEncrypt_Config_Test, TestSize.Level1) -{ - std::string dbName = "ConfigTest"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, true); - EXPECT_EQ(config.IsEncrypt(), true); - config.GenerateEncryptedKey(); - ASSERT_TRUE(config.GetEncryptKey().size() > 0); - EXPECT_EQ(config.GetNewEncryptKey().size(), 0); - // newkey is empty, not change key - config.ChangeEncryptKey(); - ASSERT_TRUE(config.GetEncryptKey().size() > 0); - EXPECT_EQ(config.GetNewEncryptKey().size(), 0); -} \ No newline at end of file diff --git a/relational_store/test/native/gdb/unittest/gdb_execute_test.cpp b/relational_store/test/native/gdb/unittest/gdb_execute_test.cpp deleted file mode 100644 index 8db22068..00000000 --- a/relational_store/test/native/gdb/unittest/gdb_execute_test.cpp +++ /dev/null @@ -1,2043 +0,0 @@ -/* - * 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 - -#include -#include -#include -#include -#include - -#include "gdb_errors.h" -#include "db_store_impl.h" -#include "edge.h" -#include "grd_adapter.h" -#include "grd_adapter_manager.h" -#include "gdb_helper.h" -#include "gdb_store.h" -#include "gdb_utils.h" -#include "graph_statement.h" -#include "graph_connection.h" -#include "path.h" -#include "result.h" -#include "vertex.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; -class GdbExecuteTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase(); - void SetUp(); - void TearDown(); - void VerifyPersonInfo(const GraphValue &person, const std::string &name, const int32_t &age); - void MatchAndVerifyPerson(const std::string &name, const int32_t &age); - - static const std::string databaseName; - static const std::string databasePath; - static std::shared_ptr store_; - static const std::string createGraphGql; - static const std::shared_ptr databaseConfig; - static const std::string pathJsonString; -}; -std::shared_ptr GdbExecuteTest::store_; -const std::string GdbExecuteTest::databaseName = "execute_test"; -const std::string GdbExecuteTest::databasePath = "/data"; -const std::string GdbExecuteTest::createGraphGql = "CREATE GRAPH test { " - "(person:Person {name STRING, age INT, sex BOOL DEFAULT false})," - "(dog:Dog {name STRING, age INT}), " - "(person) -[:Friend]-> (person) " - "};"; -const std::string GdbExecuteTest::pathJsonString = R"({ - "start": { - "label": "PERSON", - "identity": 1, - "properties": { - "AGE": 32, - "SALARY": 75.35, - "NAME": "Alice", - "GENDER": "Female", - "PHONENUMBERS": false, - "EMAILS": null - } - }, - "end": { - "label": "PERSON", - "identity": 2, - "properties": { - "AGE": 28, - "SALARY": 65000, - "NAME": "Bob", - "GENDER": "Male", - "PHONENUMBERS": "123456789", - "EMAILS": "bob@example.com" - } - }, - "relationship": { - "label": "鐩寸郴浜插睘", - "identity": 3, - "start": 1, - "end": 2, - "properties": { - "NUM": 4, - "PINYIN": "zhixiqinshu" - } - } - })"; - -void GdbExecuteTest::SetUpTestCase() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } - int errCode = E_OK; - auto config = StoreConfig(databaseName, databasePath); - GDBHelper::DeleteDBStore(config); - - GdbExecuteTest::store_ = GDBHelper::GetDBStore(config, errCode); -} - -void GdbExecuteTest::TearDownTestCase() -{ - GDBHelper::DeleteDBStore(StoreConfig(databaseName, databasePath)); - store_ = nullptr; -} - -void GdbExecuteTest::SetUp() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } - auto result = store_->ExecuteGql(createGraphGql); -} - -void GdbExecuteTest::TearDown() -{ - if (store_ != nullptr) { - auto result = store_->ExecuteGql("DROP GRAPH test"); - } -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStoreVector, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath, DBType::DB_VECTOR); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_NOT_SUPPORT); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStoreButt, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath, DBType::DB_BUTT); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_NOT_SUPPORT); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStoreReadConSize, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - config.SetReadConSize(0); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStoreReadConSizeMax, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - config.SetReadConSize(500); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_ARGS_READ_CON_OVERLOAD); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_NameHasdbSuffix, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success.db"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_NE(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_NameHasDBSuffix, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success.DB"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_NE(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_NameHasSpecialChar, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "suc@!#$*(cess."; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_NE(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_PathOkEmptyName, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = ""; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_NE(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_NotFoundPath, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success"; - std::string dbPath = "/test/path1/"; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_GRD_FAILED_FILE_OPERATION); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_PathErrorEmptyName, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = ""; - std::string dbPath = "/test/path2"; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_GRD_INVAILD_NAME_ERR); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_Empty_Path, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = databaseName; - std::string dbPath = ""; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_GRD_FAILED_FILE_OPERATION); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_Empty_NameAndPath, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = ""; - std::string dbPath = ""; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_GRD_INVAILD_NAME_ERR); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_OK, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "execute_test_ok"; - std::string dbPath = "/data"; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_OK_PathRepeat, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "execute_test_ok_2"; - std::string dbPath = "/data"; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_LongName, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = ""; - for (int32_t i = 0; i < 1000000; i++) { - dbName += "A"; - } - std::string dbPath = "/test/path2"; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_GRD_FAILED_FILE_OPERATION); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_LongNamePathOk, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = ""; - for (int32_t i = 0; i < 1000000; i++) { - dbName += "A"; - } - std::string dbPath = "/data"; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_GRD_SEMANTIC_ERROR); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_LongPath, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = ""; - for (int32_t i = 0; i < 30; i++) { - dbName += "A"; - } - std::string dbPath = "/test/path2"; - for (int32_t i = 0; i < 3000000; i++) { - dbPath += "A"; - } - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_GRD_SEMANTIC_ERROR); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_InVaildSecurityLevel, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "tttt"; - std::string dbPath = "/data"; - - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(-3); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_INVALID_ARGS); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_InVaildSecurityLevel02, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "tttt"; - std::string dbPath = "/data"; - - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(0); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_INVALID_ARGS); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_InVaildSecurityLevel03, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "tttt"; - std::string dbPath = "/data"; - - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(500); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_INVALID_ARGS); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_SecurityLevel, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "tttt"; - std::string dbPath = "/data"; - - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(3); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_SecurityLevelLast, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "tttt"; - std::string dbPath = "/data"; - - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(SecurityLevel::LAST); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(store, nullptr); - EXPECT_EQ(errCode, E_INVALID_ARGS); - store = nullptr; - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_GetSecurityLeve, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "tttt03"; - std::string dbPath = "/data"; - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(SecurityLevel::S2); - auto level = config.GetSecurityLevel(); - EXPECT_EQ(level, SecurityLevel::S2); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - - store = nullptr; - GDBHelper::DeleteDBStore(config); - - config.SetSecurityLevel(SecurityLevel::LAST); - level = config.GetSecurityLevel(); - EXPECT_EQ(level, SecurityLevel::LAST); - store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(errCode, E_INVALID_ARGS); - EXPECT_EQ(store, nullptr); - store = nullptr; - GDBHelper::DeleteDBStore(config); -} - -/** - * @tc.name: GdbStore_GetDBStore_SecurityLevel03 - * @tc.desc: test StoreConfig SetSecurityLevel S2->S1 - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_SecurityLevel02, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "tttt02"; - std::string dbPath = "/data"; - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(SecurityLevel::S2); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - store = nullptr; - - auto invalidConfig = config; - invalidConfig.SetSecurityLevel(SecurityLevel::S1); - store = GDBHelper::GetDBStore(invalidConfig, errCode); - EXPECT_EQ(errCode, E_CONFIG_INVALID_CHANGE); - EXPECT_EQ(store, nullptr); - store = nullptr; - GDBHelper::DeleteDBStore(config); -} - -/** - * @tc.name: GdbStore_GetDBStore_SecurityLevel03 - * @tc.desc: test StoreConfig SetSecurityLevel S2->S3 - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_SecurityLevel03, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "tttt02"; - std::string dbPath = "/data"; - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(SecurityLevel::S2); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - store = nullptr; - - auto invalidConfig = config; - invalidConfig.SetSecurityLevel(SecurityLevel::S3); - store = GDBHelper::GetDBStore(invalidConfig, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - store = nullptr; - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_NoInsertQuery, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 0); -} - -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_AfterClose, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_OK; - std::string dbName = "ttttclose"; - std::string dbPath = "/data"; - - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(SecurityLevel::S3); - - auto store = GDBHelper::GetDBStore(config, errCode); - ASSERT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - auto ret = store->Close(); - EXPECT_EQ(E_OK, ret); - EXPECT_NE(store, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store_->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GDBHelper::DeleteDBStore(config); -} - -/** - * @tc.name: GdbStore_GetDBStore_AfterDrop - * @tc.desc: test GdbStore AfterDrop Insert - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_GetDBStore_AfterDrop, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_OK; - std::string dbName = "ttttdrop"; - std::string dbPath = "/data"; - - auto config = StoreConfig(dbName, dbPath); - config.SetSecurityLevel(SecurityLevel::S3); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - - auto result = store_->ExecuteGql("DROP GRAPH test;"); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - - result = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_GRD_UNDEFINED_PARAM); - result = store_->ExecuteGql(createGraphGql); - EXPECT_NE(result.second, nullptr); - EXPECT_EQ(result.first, E_OK); - GDBHelper::DeleteDBStore(config); -} - -/** - * @tc.name: GdbStore_Execute_001 - * @tc.desc: test GdbStore Execute - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_Execute_LongName, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store_->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - std::string name = "name2"; - for (int32_t i = 0; i < 300; i++) { - name += "A"; - } - result = store_->ExecuteGql("INSERT (:Person {name: '" + name + "', age: 11});"); - ASSERT_EQ(result.first, E_OK); - result = store_->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 2); - - std::string name2 = "name2"; - for (int32_t i = 0; i < 3000000; i++) { - name2 += "A"; - } - result = store_->ExecuteGql("INSERT (:Person {name: '" + name2 + "', age: 11});"); - ASSERT_EQ(result.first, E_INVALID_ARGS); - result = store_->QueryGql("MATCH (person:Person {age: 11}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 2); -} - -/** - * @tc.name: GdbStore_Execute_001 - * @tc.desc: test GdbStore Execute - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_Execute_001, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_1", 11); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_2", 22); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_3', age: 33});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_3", 33); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_2'}), (p2:Person {name: 'name_3'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - - result = store_->QueryGql("MATCH (person:Person)-[relation:Friend]->() RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - auto data = result.second->GetAllData(); - GraphValue person = data[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - - auto result2 = - store_->QueryGql("MATCH path=(a:Person {name: 'name_1'})-[]->{2, 2}(b:Person {name: 'name_3'}) RETURN path;"); - ASSERT_EQ(result2.first, E_OK); - EXPECT_EQ(result2.second->GetAllData().size(), 1); - - GraphValue path = result2.second->GetAllData()[0]["path"]; - ASSERT_TRUE(std::holds_alternative>(path)); - - auto pathPath = std::get>(path); - EXPECT_EQ(pathPath->GetPathLength(), 2); -} - -/** - * @tc.name: GdbStore_Execute_001 - * @tc.desc: test GdbStore Execute - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_Execute_002, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_3', age: 33});"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_2'}), (p2:Person {name: 'name_3'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_3'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - - result = store_->QueryGql( - "MATCH (person:Person {name: 'name_1'})-[relation:Friend]->(d) where d.age > 25 RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, "name_1", 11); - - GraphValue relation = result.second->GetAllData()[0]["relation"]; - ASSERT_TRUE(std::holds_alternative>(relation)); - auto relationGraphEdge = std::get>(relation); - EXPECT_EQ(relationGraphEdge->GetLabel(), "Friend"); -} - -void GdbExecuteTest::MatchAndVerifyPerson(const std::string &name, const int32_t &age) -{ - ASSERT_NE(store_, nullptr); - auto gql = "MATCH (person:Person {name: '" + name + "'}) RETURN person;"; - auto result = store_->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, name, age); -} - -void GdbExecuteTest::VerifyPersonInfo(const GraphValue &person, const std::string &name, const int32_t &age) -{ - auto expectSize = 3; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), expectSize); - - auto nameDb = personVertex->GetProperties().find("name"); - ASSERT_NE(nameDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(nameDb->second)); - EXPECT_EQ(std::get(nameDb->second), name); - - auto ageDb = personVertex->GetProperties().find("age"); - ASSERT_NE(ageDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(ageDb->second)); - EXPECT_EQ(std::get(ageDb->second), age); - - auto sex = personVertex->GetProperties().find("sex"); - ASSERT_NE(sex, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(sex->second)); - EXPECT_EQ(std::get(sex->second), 0); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Updata, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_1", 11); - - result = store_->ExecuteGql("MATCH (p1:Person {name: 'name_1'}) SET p1.name = 'name_1_modify';"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_1_modify", 11); - - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_1_modify'}) SET p1.name = 'name_1_modify2', p1.age=100 + 11;"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_1_modify2", 111); - - result = store_->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_2", 22); - result = store_->ExecuteGql("MATCH (p2:Person {name: 'name_2'}) SET p2 = {name: 'name_2_modify_all', age: 99};"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_2_modify_all", 99); - - result = store_->ExecuteGql("MATCH (p1:Person {name: 'name_1_modify2'}), (p2:Person {name: 'name_2_modify_all'}) " - "INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = - store_->ExecuteGql("MATCH (n:Person {name: 'name_1_modify2'})-[r:Friend]->(m:Person ) SET m.name = 'name_3';"); - MatchAndVerifyPerson("name_3", 99); - EXPECT_EQ(result.first, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_UpdataNull, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'hahaha', age: 987});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("hahaha", 987); - // update name = null - result = store_->ExecuteGql("MATCH (p1:Person {name: 'hahaha'}) SET p1 = {age: 666};"); - EXPECT_EQ(result.first, E_OK); - result = store_->QueryGql("MATCH (person:Person {age: 666}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), 2); - - auto nameDb = personVertex->GetProperties().find("name"); - ASSERT_EQ(nameDb, personVertex->GetProperties().end()); - - auto ageDb = personVertex->GetProperties().find("age"); - ASSERT_NE(ageDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(ageDb->second)); - EXPECT_EQ(std::get(ageDb->second), 666); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_UpdataNull02, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'hahaha', age: 987});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("hahaha", 987); - // update name = null - result = store_->ExecuteGql("MATCH (p1:Person {name: 'hahaha'}) SET p1.age = 666, p1.name = null;"); - EXPECT_EQ(result.first, E_OK); - result = store_->QueryGql("MATCH (person:Person {age: 666}) RETURN person;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), 2); - - auto nameDb = personVertex->GetProperties().find("name"); - ASSERT_EQ(nameDb, personVertex->GetProperties().end()); - - auto ageDb = personVertex->GetProperties().find("age"); - ASSERT_NE(ageDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(ageDb->second)); - EXPECT_EQ(std::get(ageDb->second), 666); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Updata_MatchFail, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'zhangsan001', age: 10});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("zhangsan001", 10); - - result = store_->ExecuteGql("MATCH (p1:Person {name: 'notFound'}) SET p1.name = 'name_1_modify';"); - EXPECT_EQ(result.first, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Updata_AgeError, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_4', age: 44});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("name_4", 44); - - result = store_->ExecuteGql("MATCH (p1:Person {name: 'name_4'}) SET p1.age = 'string_age';"); - EXPECT_EQ(result.first, E_GRD_SEMANTIC_ERROR); - // update failed, no change - MatchAndVerifyPerson("name_4", 44); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Updata_ColumnError, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto result = store_->ExecuteGql("INSERT (:PersonErr {name: true, age: 44});"); - EXPECT_EQ(result.first, E_GRD_UNDEFINED_PARAM); - - auto gql = "MATCH (person:Person) RETURN person;"; - result = store_->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 0); - - result = store_->ExecuteGql("INSERT (:Person {name: true, age: 44});"); - EXPECT_EQ(result.first, E_GRD_SEMANTIC_ERROR); - gql = "MATCH (person:Person) RETURN person;"; - result = store_->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 0); - - result = store_->ExecuteGql("INSERT (:Person {name: 'zhangsan', age: 'error'});"); - EXPECT_EQ(result.first, E_GRD_SEMANTIC_ERROR); - gql = "MATCH (person:Person) RETURN person;"; - result = store_->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 0); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Delete, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto result = store_->ExecuteGql("INSERT (:Person {name: 'zhangsan_delete', age: 10});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("zhangsan_delete", 10); - - result = store_->ExecuteGql("MATCH (p:Person {name: 'zhangsan_delete'}) DETACH DELETE p;"); - EXPECT_EQ(result.first, E_OK); - auto gql = "MATCH (person:Person {name: 'zhangsan_delete'}) RETURN person;"; - result = store_->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 0); - // Double Delete - result = store_->ExecuteGql("MATCH (p:Person {name: 'zhangsan_delete'}) DETACH DELETE p;"); - EXPECT_EQ(result.first, E_OK); - gql = "MATCH (person:Person {name: 'zhangsan_delete'}) RETURN person;"; - result = store_->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 0); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Delete_NotFound, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'zhangsan_delete', age: 10});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("zhangsan_delete", 10); - - result = store_->ExecuteGql("MATCH (p:Person {name: 'notFound'}) DETACH DELETE p;"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("zhangsan_delete", 10); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Delete_PError, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'delete_error', age: 11});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("delete_error", 11); - - result = store_->ExecuteGql("MATCH (p:Person {name: 'delete_error'}) DETACH DELETE p_error;"); - EXPECT_EQ(result.first, E_GRD_UNDEFINED_PARAM); - MatchAndVerifyPerson("delete_error", 11); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Delete_Related, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto result = store_->ExecuteGql("INSERT (:Person {name: 'delete_1', age: 11});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("delete_1", 11); - result = store_->ExecuteGql("INSERT (:Person {name: 'delete_2', age: 22});"); - MatchAndVerifyPerson("delete_2", 22); - EXPECT_EQ(result.first, E_OK); - - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'delete_1'}), (p2:Person {name: 'delete_2'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = - store_->QueryGql("MATCH (person:Person {name: 'delete_1'})-[relation:Friend]->() RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), 3); - auto name = personVertex->GetProperties().find("name"); - ASSERT_NE(name, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(name->second)); - EXPECT_EQ(std::get(name->second), "delete_1"); - - auto age = personVertex->GetProperties().find("age"); - ASSERT_NE(age, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(age->second)); - EXPECT_EQ(std::get(age->second), 11); - - result = store_->ExecuteGql("MATCH (p:Person)-[:Friend]->(relatedPerson:Person) DETACH DELETE p, relatedPerson;"); - EXPECT_EQ(result.first, E_OK); - result = - store_->QueryGql("MATCH (person:Person {name: 'delete_1'})-[relation:Friend]->() RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 0); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Delete_Related_Error, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto result = store_->ExecuteGql("INSERT (:Person {name: 'delete_3', age: 11});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("delete_3", 11); - result = store_->ExecuteGql("INSERT (:Person {name: 'delete_4', age: 22});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyPerson("delete_4", 22); - - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'delete_3'}), (p2:Person {name: 'delete_4'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = - store_->QueryGql("MATCH (person:Person {name: 'delete_3'})-[relation:Friend]->() RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), 3); - auto name = personVertex->GetProperties().find("name"); - ASSERT_NE(name, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(name->second)); - EXPECT_EQ(std::get(name->second), "delete_3"); - - // No Friend_Error, delete Eror - result = - store_->ExecuteGql("MATCH (p:Person)-[:Friend_Error]->(relatedPerson:Person) DETACH DELETE p, relatedPerson;"); - EXPECT_EQ(result.first, E_GRD_UNDEFINED_PARAM); - // p:Person, but delete p_error - result = - store_->ExecuteGql("MATCH (p:Person)-[:Friend]->(relatedPerson:Person) DETACH DELETE p_error, relatedPerson;"); - EXPECT_EQ(result.first, E_GRD_UNDEFINED_PARAM); - //relatedPerson:Person, but delete relatedPerson_error - result = - store_->ExecuteGql("MATCH (p:Person)-[:Friend]->(relatedPerson:Person) DETACH DELETE p, relatedPerson_error;"); - EXPECT_EQ(result.first, E_GRD_UNDEFINED_PARAM); - - result = store_->ExecuteGql("MATCH (p:Person)-[:Friend]->(relatedPerson:Person) DETACH DELETE relatedPerson, p;"); - EXPECT_EQ(result.first, E_OK); - // delete success, data.size == 0 - result = - store_->QueryGql("MATCH (person:Person {name: 'delete_3'})-[relation:Friend]->() RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 0); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_QueryGql, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'zhangsan_111', age: 11, sex: true});"); - EXPECT_EQ(result.first, E_OK); - - result = store_->QueryGql("MATCH (person:Person {name: 'zhangsan_111'}) RETURN person;"); - EXPECT_EQ(result.first, E_OK); - - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue personErr = result.second->GetAllData()[0]["personErr"]; - // No personErr - ASSERT_TRUE(std::holds_alternative(personErr)); - - GraphValue person = result.second->GetAllData()[0]["person"]; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - ASSERT_NE(personVertex->GetLabel(), "error_label"); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - // size = 4 {name, age, sex, identity} - ASSERT_EQ(personVertex->GetProperties().size(), 3); - - auto name = personVertex->GetProperties().find("name"); - ASSERT_NE(name, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(name->second)); - EXPECT_EQ(std::get(name->second), "zhangsan_111"); - - auto age = personVertex->GetProperties().find("age"); - ASSERT_NE(age, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(age->second)); - EXPECT_EQ(std::get(age->second), 11); - - auto sex = personVertex->GetProperties().find("sex"); - ASSERT_NE(sex, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(sex->second)); - EXPECT_EQ(std::get(sex->second), 1); - // No Propertie is OTHER, equal End - auto other = personVertex->GetProperties().find("OTHER"); - EXPECT_EQ(other, personVertex->GetProperties().end()); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_QueryGql_2, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto result = store_->ExecuteGql("INSERT (:Person {name: 'lisi_1', age: 66});"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql("INSERT (:Person {name: 'lisi_2', age: 66, sex: true});"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql("INSERT (:Dog {name: 'xiaohuang1', age: 66});"); - EXPECT_EQ(result.first, E_OK); - result = store_->QueryGql("MATCH (person:Person{age: 66}) RETURN person;"); - EXPECT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - - GraphValue person = result.second->GetAllData()[0]["person"]; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), 3); - auto name = personVertex->GetProperties().find("name"); - ASSERT_NE(name, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(name->second)); - EXPECT_EQ(std::get(name->second), "lisi_1"); - auto age = personVertex->GetProperties().find("age"); - ASSERT_NE(age, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(age->second)); - EXPECT_EQ(std::get(age->second), 66); - auto sex = personVertex->GetProperties().find("sex"); - ASSERT_NE(sex, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(age->second)); - EXPECT_EQ(std::get(sex->second), 0); - - person = result.second->GetAllData()[1]["person"]; - ASSERT_TRUE(std::holds_alternative>(person)); - personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), 3); - name = personVertex->GetProperties().find("name"); - ASSERT_NE(name, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(name->second)); - EXPECT_EQ(std::get(name->second), "lisi_2"); - age = personVertex->GetProperties().find("age"); - ASSERT_NE(age, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(age->second)); - EXPECT_EQ(std::get(age->second), 66); - sex = personVertex->GetProperties().find("sex"); - ASSERT_NE(sex, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(age->second)); - EXPECT_EQ(std::get(sex->second), 1); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_ParseEdge, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_ERROR; - // no start, no end - nlohmann::json json = nlohmann::json::parse("{\"name\" : \"zhangsan\"}", nullptr, false); - ASSERT_FALSE(json.is_discarded()); - ASSERT_FALSE(json.is_null()); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - // no identity - std::string jsonStr = "{\"start\" : 1, \"end\" : 2}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - // ok - jsonStr = "{\"start\" : 1, \"end\" : 2, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // start is AA - jsonStr = "{\"start\" : \"AA\", \"end\" : 2, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // end is B - jsonStr = "{\"start\" : 1, \"end\" : \"B\", \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // identity is C - jsonStr = "{\"start\" : 1, \"end\" : 2, \"label\":\"COMPANY\",\"identity\":\"C\"," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // label is 222 - jsonStr = "{\"start\" : 1, \"end\" : 2, \"label\":222,'identity':3,\"properties\":{\"NAME\":\"myCompany3\"," - "\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - // key4 is null - jsonStr = - "{\"start\" : 1, \"end\" : 2, \"label\":\"COMPANY\",\"identity\":2," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":4.5,\"SEX\":true,\"key1\":true,\"key2\":[], \"key3\":{}, " - "\"key4\": null}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_PathSegment, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_ERROR; - // NO start and end - nlohmann::json json = nlohmann::json::parse("{\"name\" : \"zhangsan\"}", nullptr, false); - ASSERT_FALSE(json.is_discarded()); - ASSERT_FALSE(json.is_null()); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - // no relationship - std::string jsonStr = "{\"start\" : {}, \"end\" : {}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"end\" : {}, \"relationship\":{}, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"end\" : {}, \"relationship\":{}, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"end\" : {}, \"relationship\":{}, \"label\":\"COMPANY\",\"identity\":\"C\"," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"end\" : {}, \"relationship\":{}, \"label\":222,\"identity\":2," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"end\" : {}, \"relationship\":{}, \"label\":\"COMPANY\",\"identity\":2," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":4.5,\"SEX\":true,\"key1\":true,\"key2\":[], " - "\"key3\":{}, \"key4\": null}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - json = nlohmann::json::parse(pathJsonString, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_PathSegment02, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_ERROR; - nlohmann::json json = nlohmann::json::parse(pathJsonString, nullptr, false); - PathSegment::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // identity:A, E_OK - std::string jsonStr = - "{\"start\":{\"label\":\"PERSON\",\"identity\":\"A\",\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":2,\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - - // label:2, E_PARSE_JSON_FAILED - jsonStr = - "{\"start\":{\"label\":2,\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":2,\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - - // relationship->start:B, E_OK - jsonStr = - "{\"start\":{\"label\":\"PERSON\",\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":\"B\",\"end\":2,\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - - // relationship->end:C, E_OK - jsonStr = - "{\"start\":{\"label\":\"PERSON\",\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":\"C\",\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_PathSegment03, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_ERROR; - nlohmann::json json = nlohmann::json::parse(pathJsonString, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_OK); - // end no label:PERSON and identity: A - std::string jsonStr = - "{\"start\":{\"label\":\"PERSON\",\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"identity\":\"A\",\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":2,\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : 1, \"end\" : {}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"relationship\" : 1}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"relationship\" : {}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"relationship\" : {}, \"end\" : 1}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : {}, \"relationship\" : {}, \"end\" : {}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_PathSegment04, TestSize.Level1) -{ - int errCode = E_ERROR; - nlohmann::json json = nlohmann::json::parse(pathJsonString, nullptr, false); - PathSegment::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // identity:A, E_OK - std::string jsonStr = - "{\"start\":{\"label\":\"PERSON\",\"identity\":{},\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":2,\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - std::shared_ptr sourceVertex; - std::shared_ptr targetVertex; - std::shared_ptr edge; - auto paths = std::make_shared(sourceVertex, targetVertex, edge); - EXPECT_NE(paths, nullptr); - EXPECT_EQ(sourceVertex, paths->GetSourceVertex()); - EXPECT_EQ(edge, paths->GetEdge()); - EXPECT_EQ(targetVertex, paths->GetTargetVertex()); - jsonStr = - "{\"start\":{\"label\":\"PERSON\",\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - PathSegment::Parse(json, errCode); - ASSERT_EQ(errCode, E_PARSE_JSON_FAILED); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Path01, TestSize.Level1) -{ - std::shared_ptr start = std::make_shared(); - std::shared_ptr end = std::make_shared(); - auto path = std::make_shared(); - path = std::make_shared(start, end); - EXPECT_NE(path, nullptr); - path->SetPathLength(1); - EXPECT_EQ(1, path->GetPathLength()); - path->SetStart(std::make_shared("1", "HAHA")); - EXPECT_EQ("1", path->GetStart()->GetId()); - EXPECT_EQ("HAHA", path->GetStart()->GetLabel()); - auto labels = path->GetStart()->GetLabels(); - EXPECT_EQ(1, labels.size()); - - path->SetEnd(std::make_shared("2", "HAHA2")); - EXPECT_EQ("2", path->GetEnd()->GetId()); - EXPECT_EQ("HAHA2", path->GetEnd()->GetLabel()); - auto segment = path->GetSegments(); - EXPECT_EQ(segment.size(), 0); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Path02, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_ERROR; - nlohmann::json json = nlohmann::json::parse(pathJsonString, nullptr, false); - Path::Parse(json, errCode); - // no length - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - // identity:A, E_OK - std::string jsonStr = - "{\"length\": 1,\"start\":{\"label\":\"PERSON\",\"identity\":3,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\"}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":2,\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}},\"segments\":[{\"start\":{\"label\":\"PERSON\"," - "\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":\"C\",\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}}}]}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Path::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - - // label:2, E_PARSE_JSON_FAILED - jsonStr = - "{\"length\": 1,\"start\":{\"label\":2,\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":2,\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}},\"segments\":[{}]}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Path::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Path03, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_ERROR; - nlohmann::json json = nlohmann::json::parse(pathJsonString, nullptr, false); - Path::Parse(json, errCode); - // no length - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - // relationship->start:B, E_OK - auto jsonStr = - "{\"length\": 1,\"start\":{\"label\":\"PERSON\",\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":\"B\",\"end\":2,\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}},\"segments\":[{}]}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Path::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - - // relationship->end:C, E_OK - jsonStr = - "{\"length\": 1,\"start\":{\"label\":\"PERSON\",\"identity\":1,\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":\"C\",\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}},\"segments\":[{\"start\":{\"label\":\"PERSON\",\"identity\":1," - "\"properties\":{\"AGE\":32,\"SALARY\":75.35," - "\"NAME\":\"Alice\",\"GENDER\":\"Female\",\"PHONENUMBERS\":false,\"EMAILS\":null}}," - "\"end\":{\"label\":\"PERSON\",\"identity\":2,\"properties\":{\"AGE\":28,\"SALARY\":65000," - "\"NAME\":\"Bob\",\"GENDER\":\"Male\",\"PHONENUMBERS\":\"123456789\",\"EMAILS\":\" bob@example.com\"}}," - "\"relationship\":{\"label\":\"tttt\",\"identity\":3,\"start\":1,\"end\":\"C\",\"properties\":{\"NUM\":4," - "\"PINYIN\":\"zhixiqinshu\"}}}]}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Path::Parse(json, errCode); - ASSERT_EQ(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Vertex, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - int errCode = E_ERROR; - // no start, no end - nlohmann::json json = nlohmann::json::parse("{\"name\" : \"zhangsan\"}", nullptr, false); - ASSERT_FALSE(json.is_discarded()); - ASSERT_FALSE(json.is_null()); - Vertex::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - // no identity - std::string jsonStr = "{\"start\" : 1, \"end\" : 2}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Vertex::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - // ok - jsonStr = "{\"start\" : 1, \"end\" : 2, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Vertex::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // start is AA - jsonStr = "{\"start\" : \"AA\", \"end\" : 2, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Vertex::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // end is B - jsonStr = "{\"start\" : 1, \"end\" : \"B\", \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Vertex::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // identity is C - jsonStr = "{\"start\" : 1, \"end\" : 2, \"label\":\"COMPANY\",\"identity\":\"C\"," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Vertex::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - // label is 222 - jsonStr = "{\"start\" : 1, \"end\" : 2, \"label\":222,'identity':3,\"properties\":{\"NAME\":\"myCompany3\"," - "\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Vertex::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - // key4 is null - jsonStr = - "{\"start\" : 1, \"end\" : 2, \"label\":\"COMPANY\",\"identity\":2," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":4.5,\"SEX\":true,\"key1\":true,\"key2\":[], \"key3\":{}, " - "\"key4\": null}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Vertex::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Vertex02, TestSize.Level1) -{ - Vertex vertex; - Vertex vertex2("1", "PERSON"); - ASSERT_EQ(vertex2.GetLabel(), "PERSON"); - vertex2.SetLabel("PERSON1"); - ASSERT_EQ(vertex2.GetLabel(), "PERSON1"); - std::unordered_map properties; - Vertex vertex3("1", "PERSON2", properties); - ASSERT_EQ(vertex3.GetLabel(), "PERSON2"); - vertex3.SetLabel("PERSON3"); - ASSERT_EQ(vertex3.GetLabel(), "PERSON3"); -} - -/** - * @tc.name: GdbStore_Execute_PathChange - * @tc.desc: test Path Change - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_Execute_PathChange, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - MatchAndVerifyPerson("name_1", 11); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - MatchAndVerifyPerson("name_2", 22); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_3', age: 33});"); - MatchAndVerifyPerson("name_3", 33); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_4', age: 44});"); - MatchAndVerifyPerson("name_4", 44); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_3'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_4'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_2'}), (p2:Person {name: 'name_3'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_2'}), (p2:Person {name: 'name_4'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_3'}), (p2:Person {name: 'name_4'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - - result = - store_->QueryGql("MATCH path=(a:Person {name: 'name_1'})-[]->{0, 3}(b:Person) RETURN path;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 8); - - GraphValue path = result.second->GetAllData()[0]["path"]; - ASSERT_TRUE(std::holds_alternative>(path)); -} - -/** - * @tc.name: GdbStore_Execute_PathChangeRing - * @tc.desc: Querying a Trail with a Ring - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_Execute_PathChangeRing, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - MatchAndVerifyPerson("name_1", 11); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_2', age: 22});"); - MatchAndVerifyPerson("name_2", 22); - result = store_->ExecuteGql("INSERT (:Person {name: 'name_3', age: 33});"); - MatchAndVerifyPerson("name_3", 33); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_1'}), (p2:Person {name: 'name_2'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_2'}), (p2:Person {name: 'name_3'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_3'}), (p2:Person {name: 'name_1'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - - result = - store_->QueryGql("MATCH path=(a:Person {name: 'name_1'})-[]->{0, 3}(b:Person) RETURN path;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 4); - - GraphValue path = result.second->GetAllData()[0]["path"]; - ASSERT_TRUE(std::holds_alternative>(path)); -} - -/** - * @tc.name: GdbStore_Execute_AllGraph - * @tc.desc: test All Graph - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_Execute_AllGraph, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - std::string name = "zhangsanfeng"; - for (int32_t i = 0; i < 50; i++) { - auto nameInner = name + "_" + std::to_string(i); - auto result = store_->ExecuteGql("INSERT (:Person {name: '" + nameInner + "', age: 11});"); - MatchAndVerifyPerson(nameInner, 11); - for (int32_t j = 0; j < 100; j++) { - auto nameOut = nameInner + "_" + std::to_string(j); - result = store_->ExecuteGql("INSERT (:Person {name: '" + nameOut + "', age: 22});"); - MatchAndVerifyPerson(nameOut, 22); - result = store_->ExecuteGql( - "MATCH (p1:Person {name: '" + nameInner + "'}), (p2:Person {name: '" + nameOut + "'}) " - "INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - } - } - auto result = - store_->QueryGql("MATCH path=(a:Person)-[]->{0, 3}(b:Person) RETURN path;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 10050); - GraphValue path = result.second->GetAllData()[0]["path"]; - ASSERT_TRUE(std::holds_alternative>(path)); - - auto gql = "MATCH (person:Person) RETURN person;"; - result = store_->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 5050); -} - -/** - * @tc.name: GdbStore_Execute_SelfPath - * @tc.desc: test Self Path - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_Execute_SelfPath, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_111', age: 11});"); - MatchAndVerifyPerson("name_111", 11); - - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_111'}), (p2:Person {name: 'name_111'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - - result = store_->QueryGql("MATCH path=(a:Person {name: 'name_111'})-[]->{0, 3}(b:Person) RETURN path;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - - GraphValue path = result.second->GetAllData()[0]["path"]; - ASSERT_TRUE(std::holds_alternative>(path)); -} - -/** - * @tc.name: GdbStore_Execute_SelfPath - * @tc.desc: test Self Path - * @tc.type: FUNC - */ -HWTEST_F(GdbExecuteTest, GdbStore_Execute_SelfPath02, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("INSERT (:Person {name: 'name_test_001', age: 11});"); - MatchAndVerifyPerson("name_test_001", 11); - - result = store_->ExecuteGql("INSERT (:Person {name: 'name_test_001', age: 11});"); - - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_test_001'}), (p2:Person {name: 'name_test_001'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - - result = store_->ExecuteGql( - "MATCH (p1:Person {name: 'name_test_001'}), (p2:Person {name: 'name_test_001'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - - result = - store_->QueryGql("MATCH path=(a:Person {name: 'name_test_001'})-[]->{0, 3}(b:Person) RETURN path;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 126); - - GraphValue path = result.second->GetAllData()[0]["path"]; - ASSERT_TRUE(std::holds_alternative>(path)); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_StoreConfigSetName, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success01"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - config.SetName("success01_update"); - EXPECT_EQ("success01_update", config.GetName()); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(StoreConfig("success01_update", databasePath)); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_StoreConfigSetPath, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success01"; - std::string dbPath = "/test/test"; - auto config = StoreConfig(dbName, dbPath); - config.SetPath(databasePath); - EXPECT_EQ(databasePath, config.GetPath()); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(StoreConfig(dbName, databasePath)); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_StoreConfigSetDbType, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success01"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - config.SetDbType(DBType::DB_GRAPH); - EXPECT_EQ(config.GetDbType(), DBType::DB_GRAPH); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(StoreConfig(dbName, databasePath)); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_StoreConfigSetEncryptStatus, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success01"; - std::string dbPath = databasePath; - auto config = StoreConfig(dbName, dbPath); - config.SetEncryptStatus(true); - ASSERT_TRUE(config.IsEncrypt()); - config.SetEncryptStatus(false); - ASSERT_TRUE(!config.IsEncrypt()); - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(StoreConfig(dbName, databasePath)); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_StoreConfigSetReadTime, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "success01"; - std::string dbPath = databasePath; - std::vector encryptKey = std::vector(); - auto config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, true, encryptKey); - config = StoreConfig(dbName, dbPath, DBType::DB_GRAPH, false, encryptKey); - config.SetReadTime(3); - EXPECT_EQ(config.GetReadTime(), 3); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - GDBHelper::DeleteDBStore(StoreConfig(dbName, databasePath)); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_UtilsTest, TestSize.Level1) -{ - int errCode = E_OK; - errCode = GdbUtils::CreateDirectory(""); - EXPECT_EQ(errCode, E_OK); - errCode = GdbUtils::CreateDirectory("dir1"); - EXPECT_EQ(errCode, E_CREATE_FOLDER_FAIT); - GdbUtils::CreateDirectory("dir1/dir2"); - EXPECT_EQ(errCode, E_CREATE_FOLDER_FAIT); - GdbUtils::CreateDirectory("dir1/dir2/dir3"); - EXPECT_EQ(errCode, E_CREATE_FOLDER_FAIT); - GdbUtils::CreateDirectory("/dir1/dir2/dir3"); - EXPECT_EQ(errCode, E_CREATE_FOLDER_FAIT); - GdbUtils::CreateDirectory("/data/"); - EXPECT_EQ(errCode, E_CREATE_FOLDER_FAIT); - GdbUtils::CreateDirectory("/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2" - "/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2" - "/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2" - "/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2" - "/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2" - "/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2" - "/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2/data/dir1/dir2"); - EXPECT_EQ(errCode, E_CREATE_FOLDER_FAIT); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_UtilsAnonymousTest, TestSize.Level1) -{ - auto ret = GdbUtils::Anonymous("fileName"); - EXPECT_EQ(ret, "fileName"); - ret = GdbUtils::Anonymous("dir1/shortPath"); - EXPECT_EQ(ret, "dir1/shortPa"); - ret = GdbUtils::Anonymous("dir1/el1/longPath"); - EXPECT_EQ(ret, "dir1/el1/longPa"); - ret = GdbUtils::Anonymous("el1/l"); - EXPECT_EQ(ret, "el1"); - ret = GdbUtils::Anonymous( - "dir1/el1/longPath/longPath/longPath/longPath/longPath/longPath/longPath/longPath/longPath/longPath/longPath"); - EXPECT_EQ(ret, "dir1/***/el1/***/longPa"); - ret = GdbUtils::Anonymous("/data/dir1/dir2/dir3"); - EXPECT_EQ(ret, "/***/dir3"); - ret = GdbUtils::Anonymous("/data/el1/dir2"); - EXPECT_EQ(ret, "/***/el1/dir2"); - ret = GdbUtils::Anonymous("/data/app/el1/0/base/com.my.hmos.arkwebcore"); - EXPECT_EQ(ret, "/***/el1/***/com.my.hmos.arkwebcore"); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_StatementTest, TestSize.Level1) -{ - auto errCode = E_OK; - std::string gql = "INSERT (:Person {name: 'name_test_001', age: 11});"; - GraphStatement statement(nullptr, "", nullptr, errCode); - EXPECT_EQ(errCode, E_PREPARE_CHECK_FAILED); - - GRD_DB *dbHandle; - auto ret = std::make_shared(dbHandle, gql, nullptr, errCode); - EXPECT_NE(ret, nullptr); - errCode = ret->Prepare(); - EXPECT_EQ(errCode, E_PREPARE_CHECK_FAILED); - - errCode = ret->Step(); - EXPECT_EQ(errCode, E_STEP_CHECK_FAILED); - - errCode = ret->Finalize(); - EXPECT_EQ(errCode, E_OK); - - errCode = ret->GetColumnCount(); - EXPECT_EQ(errCode, E_STATEMENT_EMPTY); - - auto pair = ret->GetColumnName(0); - EXPECT_EQ(pair.first, E_STATEMENT_EMPTY); - pair = ret->GetColumnName(0); - EXPECT_EQ(pair.first, E_STATEMENT_EMPTY); - pair = ret->GetColumnName(3); - EXPECT_EQ(pair.first, E_STATEMENT_EMPTY); - pair = ret->GetColumnName(9); - EXPECT_EQ(pair.first, E_STATEMENT_EMPTY); - - auto pair1 = ret->GetColumnValue(0); - EXPECT_EQ(pair1.first, E_STATEMENT_EMPTY); - pair1 = ret->GetColumnValue(3); - EXPECT_EQ(pair1.first, E_STATEMENT_EMPTY); - pair1 = ret->GetColumnValue(100); - EXPECT_EQ(pair1.first, E_STATEMENT_EMPTY); - - errCode = ret->IsReady(); - EXPECT_EQ(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_StatementTest02, TestSize.Level1) -{ - auto errCode = E_OK; - std::string gql = "INSERT (:Person {name: 'name_test_001', age: 11});"; - - auto ret = std::make_shared(nullptr, gql, nullptr, errCode); - EXPECT_NE(ret, nullptr); - errCode = ret->Prepare(); - EXPECT_EQ(errCode, E_PREPARE_CHECK_FAILED); - - errCode = ret->Step(); - EXPECT_EQ(errCode, E_STEP_CHECK_FAILED); - - errCode = ret->Finalize(); - EXPECT_EQ(errCode, E_OK); - - errCode = ret->GetColumnCount(); - EXPECT_EQ(errCode, E_STATEMENT_EMPTY); - - auto pair = ret->GetColumnName(0); - EXPECT_EQ(pair.first, E_STATEMENT_EMPTY); - - auto pair1 = ret->GetColumnValue(0); - EXPECT_EQ(pair1.first, E_STATEMENT_EMPTY); - - errCode = ret->IsReady(); - EXPECT_EQ(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_FullResult, TestSize.Level1) -{ - auto fullResult = std::make_shared(); - EXPECT_NE(fullResult, nullptr); - auto errCode = fullResult->InitData(nullptr); - EXPECT_EQ(errCode, E_STATEMENT_EMPTY); - fullResult = std::make_shared(); - EXPECT_NE(fullResult, nullptr); - auto statement = std::make_shared(nullptr, "", nullptr, errCode); - errCode = fullResult->InitData(statement); - EXPECT_EQ(errCode, E_STEP_CHECK_FAILED); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_EdgeTest, TestSize.Level1) -{ - auto errCode = E_ERROR; - auto edge = std::make_shared(); - EXPECT_NE(edge, nullptr); - edge = std::make_shared(std::make_shared(), "2", "3"); - EXPECT_NE(edge, nullptr); - edge = std::make_shared(nullptr, "2", "3"); - EXPECT_NE(edge, nullptr); - edge = std::make_shared("1", "PERSON", "2", "3"); - EXPECT_NE(edge, nullptr); - edge->SetSourceId("22"); - EXPECT_EQ("22", edge->GetSourceId()); - edge->SetTargetId("33"); - EXPECT_EQ("33", edge->GetTargetId()); - - auto jsonStr = "{\"start\" : 1, \"end\" : 2, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - nlohmann::json json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_OK); - - jsonStr = "{\"start\" : {}, \"end\" : 2, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); - - jsonStr = "{\"start\" : 1, \"end\" : {}, \"label\":\"COMPANY\",\"identity\":3," - "\"properties\":{\"NAME\":\"myCompany3\",\"FOUNDED\":2011}}"; - json = nlohmann::json::parse(jsonStr, nullptr, false); - Edge::Parse(json, errCode); - EXPECT_EQ(errCode, E_PARSE_JSON_FAILED); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_Connect, TestSize.Level1) -{ - auto errCode = E_ERROR; - errCode = Connection::RegisterCreator(DBType::DB_BUTT, nullptr); - EXPECT_EQ(errCode, E_NOT_SUPPORT); - errCode = Connection::RegisterCreator(static_cast(-1), nullptr); - EXPECT_EQ(errCode, E_NOT_SUPPORT); - auto func = [](const StoreConfig& config, bool isWriter) { - std::pair> ret = std::make_pair( - static_cast(DBType::DB_GRAPH), nullptr); - return ret; - }; - errCode = Connection::RegisterCreator(DBType::DB_GRAPH, func); - EXPECT_EQ(errCode, E_OK); -} - -HWTEST_F(GdbExecuteTest, GdbStore_DBStore01, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "execute_test_ok_2"; - std::string dbPath = "/data"; - auto config = StoreConfig(dbName, dbPath); - - auto store = std::make_shared(config); - EXPECT_NE(store, nullptr); - errCode = store->InitConn(); - EXPECT_EQ(errCode, E_OK); - errCode = store->InitConn(); - EXPECT_EQ(errCode, E_OK); - const std::string gql = "INSERT (:Person {name: 'name_1', age: 11});"; - auto [err, result] = store->QueryGql(gql); - EXPECT_EQ(err, E_GRD_UNDEFINED_PARAM); - auto [err1, result1] = store->ExecuteGql(gql); - EXPECT_EQ(err1, E_GRD_UNDEFINED_PARAM); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbExecuteTest, GdbStore_NameErre01, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("DROP GRAPH test"); - EXPECT_EQ(result.first, E_OK); - - std::string createGql = "CREATE GRAPH test {(person:"; - for (int i = 0; i < 129; ++i) { - createGql += "i"; - } - createGql += " {name STRING, age INT}), (person) -[:FRIEND]-> (person)};"; - result = store_->ExecuteGql(createGql); - EXPECT_EQ(result.first, E_GRD_INVALID_NAME); -} - -HWTEST_F(GdbExecuteTest, GdbStore_NameErre02, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("DROP GRAPH test"); - EXPECT_EQ(result.first, E_OK); - - std::string createGql = - "CREATE GRAPH test {(anon_person: Person {name STRING, age INT}), (person) -[:Friend]-> (person)};"; - result = store_->ExecuteGql(createGql); - EXPECT_EQ(result.first, E_GRD_SEMANTIC_ERROR); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Conflict01, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto result = store_->ExecuteGql("DROP GRAPH test"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql( - "CREATE GRAPH test {(person: Person {id INT, name STRING}),(person) -[:Friend]-> (person)};"); - EXPECT_EQ(result.first, E_OK); - - result = store_->ExecuteGql("CREATE UNIQUE INDEX index_person_id ON person(id);"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql("INSERT (:Person {id: 1, name: 'name_1'});"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql("INSERT (:Person {id: 1, name: 'name_2'});"); - EXPECT_EQ(result.first, E_GRD_DATA_CONFLICT); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_UtilsStringTest, TestSize.Level1) -{ - std::string str = "abcd"; - GdbUtils::ClearAndZeroString(str); - EXPECT_EQ(str, ""); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_UtilsConfigTest, TestSize.Level1) -{ - std::vector keys = {1, 2, 3, 4, 5, 6, 7, 8}; - auto ret = GdbUtils::GetConfigStr(keys, false); - EXPECT_EQ(ret, R"({"pageSize": 8, "crcCheckEnable": 0, "defaultIsolationLevel": 3, )" - R"("redoFlushByTrx": 1, "metaInfoBak": 1, "maxConnNum": 500, "bufferPoolSize": 10240})"); - - ret = GdbUtils::GetConfigStr(keys, true); - EXPECT_EQ(ret, R"({"isEncrypted":1,"hexPassword":"0102030405060708",)" - R"("pageSize": 8, "crcCheckEnable": 0, "defaultIsolationLevel": 3, )" - R"("redoFlushByTrx": 1, "metaInfoBak": 1, "maxConnNum": 500, "bufferPoolSize": 10240})"); -} - -HWTEST_F(GdbExecuteTest, GdbStore_Execute_UtilsKeyTest, TestSize.Level1) -{ - std::vector keys = {1, 2, 3, 4, 5, 6, 7, 8}; - const size_t keyBuffSize = keys.size() * 2 + 1; // 2 hex number can represent a uint8_t, 1 is for '\0' - std::vector keyBuff(keyBuffSize); - auto ret = GdbUtils::GetEncryptKey(keys, keyBuff.data(), keyBuffSize); - std::string hexString(ret, ret + keyBuffSize - 1); - EXPECT_EQ(hexString, "0102030405060708"); -} \ No newline at end of file diff --git a/relational_store/test/native/gdb/unittest/gdb_function_test.cpp b/relational_store/test/native/gdb/unittest/gdb_function_test.cpp deleted file mode 100644 index 228bdad4..00000000 --- a/relational_store/test/native/gdb/unittest/gdb_function_test.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* -* 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. -*/ - -#define LOG_TAG "GdbFuncTest" -#include - -#include - -#include "gdb_errors.h" -#include "connection_pool.h" -#include "gdb_helper.h" -#include "grd_adapter_manager.h" -#include "logger.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; -class GdbFuncTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase(); - void SetUp(); - void TearDown(); -}; - -void GdbFuncTest::SetUpTestCase() -{ - LOG_INFO("SetUpTestCase"); -} - -void GdbFuncTest::TearDownTestCase() -{ - LOG_INFO("TearDownTestCase"); -} - -void GdbFuncTest::SetUp() -{ - LOG_INFO("SetUp"); - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - } -} - -void GdbFuncTest::TearDown() -{ - LOG_INFO("TearDown"); -} - -HWTEST_F(GdbFuncTest, GdbStore_Func_OpenClose01, TestSize.Level1) -{ - int errCode = E_OK; - std::string dbName = "testReopendb"; - std::string dbPath = "/data"; - auto config = StoreConfig(dbName, dbPath); - - auto store = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - - auto result = store->QueryGql(""); - EXPECT_NE(result.first, E_OK); - - store->Close(); - result = store->QueryGql("abc"); - EXPECT_NE(result.first, E_OK); - - store = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(errCode, E_OK); - - GDBHelper::DeleteDBStore(config); - - auto store1 = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(store, nullptr); - EXPECT_EQ(errCode, E_OK); - result = store1->ExecuteGql( - "CREATE GRAPH test {(person: Person {name STRING, age INT, sex BOOL DEFAULT false})}"); - EXPECT_EQ(result.first, E_OK); - GDBHelper::DeleteDBStore(config); -} - -HWTEST_F(GdbFuncTest, GdbStore_Func_CreateConnPool01, TestSize.Level1) -{ - int32_t errCode = E_OK; - auto config = StoreConfig("test", "/data", DBType::DB_VECTOR); - auto connectionPool = ConnectionPool::Create(config, errCode); - EXPECT_EQ(errCode, E_NOT_SUPPORT); -} - -HWTEST_F(GdbFuncTest, GdbStore_Func_CreateConnPool02, TestSize.Level1) -{ - int32_t errCode = E_OK; - auto config = StoreConfig("test", "/data", DBType::DB_GRAPH); - config.SetIter(0); - EXPECT_EQ(config.GetIter(), 0); - auto connectionPool = ConnectionPool::Create(config, errCode); - EXPECT_EQ(errCode, E_OK); -} - -HWTEST_F(GdbFuncTest, GdbStore_Func_CreateConnPool03, TestSize.Level1) -{ - int32_t errCode = E_OK; - auto config = StoreConfig("test", "/data", DBType::DB_GRAPH); - config.SetReadConSize(0); - auto connectionPool = ConnectionPool::Create(config, errCode); - EXPECT_EQ(errCode, E_OK); - - auto connRead1 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead1, nullptr); - EXPECT_EQ(connRead1->GetDBType(), DBType::DB_GRAPH); - auto connRead2 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead2, nullptr); - auto connRead3 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead3, nullptr); - - auto connWrite1 = connectionPool->AcquireRef(false); - EXPECT_NE(connWrite1, nullptr); - auto connWrite2 = connectionPool->AcquireRef(false); - EXPECT_NE(connWrite2, nullptr); - auto connWrite3 = connectionPool->AcquireRef(false); - EXPECT_NE(connWrite3, nullptr); - - connWrite1 = nullptr; - connWrite2 = nullptr; - connWrite3 = nullptr; - auto connWrite4 = connectionPool->AcquireRef(false); - EXPECT_NE(connWrite4, nullptr); - - connectionPool->CloseAllConnections(); - - connRead1 = connectionPool->AcquireRef(true); - EXPECT_EQ(connRead1, nullptr); - - connWrite1 = connectionPool->AcquireRef(false); - EXPECT_EQ(connWrite1, nullptr); -} - -HWTEST_F(GdbFuncTest, GdbStore_Func_CreateConnPool04, TestSize.Level1) -{ - int32_t errCode = E_OK; - auto config = StoreConfig("test", "/data", DBType::DB_GRAPH); - config.SetReadConSize(65); - auto connectionPool = ConnectionPool::Create(config, errCode); - EXPECT_EQ(errCode, E_ARGS_READ_CON_OVERLOAD); -} - -HWTEST_F(GdbFuncTest, GdbStore_Func_CreateConnPool05, TestSize.Level1) -{ - int32_t errCode = E_OK; - auto config = StoreConfig("test", "/data", DBType::DB_GRAPH); - auto connectionPool = ConnectionPool::Create(config, errCode); - EXPECT_EQ(errCode, E_OK); - - errCode = connectionPool->Dump(true, "header"); - EXPECT_EQ(errCode, E_OK); - - errCode = connectionPool->RestartReaders(); - EXPECT_EQ(errCode, E_OK); - - auto connRead1 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead1, nullptr); - EXPECT_NE(connRead1->GetId(), -1); - auto connRead2 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead2, nullptr); - auto connRead3 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead3, nullptr); - auto connRead4 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead4, nullptr); - auto connRead5 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead5, nullptr); - auto connRead6 = connectionPool->AcquireRef(true); - EXPECT_NE(connRead6, nullptr); - - auto connWrite1 = connectionPool->AcquireRef(false); - EXPECT_NE(connWrite1, nullptr); - auto connWrite2 = connectionPool->AcquireRef(false); - EXPECT_EQ(connWrite2, nullptr); - auto connWrite3 = connectionPool->AcquireRef(false); - EXPECT_EQ(connWrite3, nullptr); - - connWrite1 = nullptr; - connWrite2 = nullptr; - connWrite3 = nullptr; - auto connWrite4 = connectionPool->AcquireRef(false); - EXPECT_NE(connWrite4, nullptr); - - connectionPool->CloseAllConnections(); - - connRead1 = connectionPool->AcquireRef(true); - EXPECT_EQ(connRead1, nullptr); - - connWrite1 = connectionPool->AcquireRef(false); - EXPECT_EQ(connWrite1, nullptr); -} \ No newline at end of file diff --git a/relational_store/test/native/gdb/unittest/gdb_grd_adapter_test.cpp b/relational_store/test/native/gdb/unittest/gdb_grd_adapter_test.cpp deleted file mode 100644 index 3a60a496..00000000 --- a/relational_store/test/native/gdb/unittest/gdb_grd_adapter_test.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/* - * 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 "gdb_errors.h" -#include "db_store_manager.h" -#include "edge.h" -#include "full_result.h" -#include "gdb_helper.h" -#include "gdb_store.h" -#include "gdb_transaction.h" -#include "grd_adapter_manager.h" -#include "path.h" -#include "result.h" -#include "vertex.h" -#include "../mock/grd_adapter.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; - -using FuncName = GrdAdapter::FuncName; - -class GdbGrdAdapterTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase() {} - void SetUp(); - void TearDown() {} - - void CheckPrepareStepErrCode(int32_t grdErr, int32_t gdbErr, FuncName func); - void CheckRekeyErrCode(int32_t grdErr, int32_t gdbErr); - - void GetStore(const std::string &name); - void DeleteStore(const std::string &name); - - static const std::string path; - static const std::string createGraphGql; - static const std::string executeGql; - static const std::string queryGql; - - static std::shared_ptr store_; -}; - -const std::string GdbGrdAdapterTest::path = "/data"; - -const std::string GdbGrdAdapterTest::createGraphGql = "CREATE GRAPH test { " - "(person:Person {name STRING, age INT, sex BOOL DEFAULT false})," - "(dog:Dog {name STRING, age INT}), " - "(person) -[:Friend]-> (person) " - "};"; - -const std::string GdbGrdAdapterTest::executeGql = "INSERT (:Person {name: 'name_1', age: 11});"; -const std::string GdbGrdAdapterTest::queryGql = "MATCH (person:Person {name: 'name_1'}) RETURN person;"; - -std::shared_ptr GdbGrdAdapterTest::store_; - -static constexpr int32_t MAX_LEN = 128; -static constexpr int32_t MAX_PROP_CNT = 1024; - -void GdbGrdAdapterTest::SetUpTestCase() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } -} - -void GdbGrdAdapterTest::SetUp() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } -} - -void GdbGrdAdapterTest::GetStore(const std::string &name) -{ - auto config = StoreConfig(name, path); - GDBHelper::DeleteDBStore(config); - - int32_t errorCode = E_OK; - store_ = GDBHelper::GetDBStore(config, errorCode); - ASSERT_NE(store_, nullptr); - ASSERT_EQ(errorCode, E_OK); - - auto [errCode, result] = store_->ExecuteGql(createGraphGql); - ASSERT_EQ(errCode, E_OK); - - GrdAdapter::SetErrorCode(FuncName::ALL, GRD_OK); -} - -void GdbGrdAdapterTest::DeleteStore(const std::string &name) -{ - auto config = StoreConfig(name, path); - GDBHelper::DeleteDBStore(config); - - store_ = nullptr; -} - -void GdbGrdAdapterTest::CheckPrepareStepErrCode(int32_t grdErr, int32_t gdbErr, FuncName func) -{ - std::string name = "prepare_step_test"; - GetStore(name); - ASSERT_NE(store_, nullptr); - - GrdAdapter::SetErrorCode(func, grdErr); - - auto [errCode, result] = store_->ExecuteGql(executeGql); - EXPECT_EQ(errCode, gdbErr); - - std::tie(errCode, result) = store_->QueryGql(queryGql); - if (func == FuncName::STEP && grdErr == GRD_NO_DATA) { - EXPECT_EQ(errCode, E_OK); - } else { - EXPECT_EQ(errCode, gdbErr); - } - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, gdbErr); - EXPECT_EQ(trans, nullptr); - - GrdAdapter::SetErrorCode(func, GRD_OK); - - std::tie(err, trans) = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - - GrdAdapter::SetErrorCode(func, grdErr); - - std::tie(errCode, result) = trans->Execute(executeGql); - EXPECT_EQ(errCode, gdbErr); - - std::tie(errCode, result) = trans->Query(queryGql); - if (func == FuncName::STEP && grdErr == GRD_NO_DATA) { - EXPECT_EQ(errCode, E_OK); - } else { - EXPECT_EQ(errCode, gdbErr); - } - - errCode = trans->Commit(); - EXPECT_EQ(errCode, gdbErr); - - GrdAdapter::SetErrorCode(func, GRD_OK); - - std::tie(err, trans) = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - - GrdAdapter::SetErrorCode(func, grdErr); - - errCode = trans->Rollback(); - EXPECT_EQ(errCode, gdbErr); - - GrdAdapter::SetErrorCode(func, GRD_OK); - - DeleteStore(name); -} - -void GdbGrdAdapterTest::CheckRekeyErrCode(int32_t grdErr, int32_t gdbErr) -{ - std::string name = "rekey_test"; - GetStore(name); - ASSERT_NE(store_, nullptr); - - auto errCode = store_->Close(); - EXPECT_EQ(errCode, E_OK); - StoreManager::GetInstance().Clear(); - - GrdAdapter::SetErrorCode(FuncName::REKEY, grdErr); - - auto config = StoreConfig(name, path, DBType::DB_GRAPH, true); - store_ = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(errCode, gdbErr); - EXPECT_EQ(store_, nullptr); - - GrdAdapter::SetErrorCode(FuncName::REKEY, GRD_OK); - - DeleteStore(name); -} - -/** - * @tc.name: GdbGrdAdapterTest001 - * @tc.desc: test Prepare returned the following error code - * @tc.type: FUNC - */ -HWTEST_F(GdbGrdAdapterTest, GdbGrdAdapterTest001, TestSize.Level1) -{ - std::map errCodeMap = { - { GRD_INVALID_ARGS, E_GRD_INVALID_ARGS }, - { GRD_SYNTAX_ERROR, E_GRD_SYNTAX_ERROR }, - { GRD_SEMANTIC_ERROR, E_GRD_SEMANTIC_ERROR }, - { GRD_OVER_LIMIT, E_GRD_OVER_LIMIT }, - { GRD_FAILED_MEMORY_ALLOCATE, E_GRD_FAILED_MEMORY_ALLOCATE }, - { GRD_MODEL_NOT_SUPPORT, E_GRD_SEMANTIC_ERROR }, - { GRD_FEATURE_NOT_SUPPORTED, E_GRD_SEMANTIC_ERROR }, - { GRD_DATATYPE_MISMATCH, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_VALUE, E_GRD_INVALID_ARGS }, - { GRD_NAME_TOO_LONG, E_GRD_INVALID_NAME }, - { GRD_DUPLICATE_TABLE, E_GRD_DUPLICATE_PARAM }, - { GRD_DUPLICATE_OBJECT, E_GRD_DUPLICATE_PARAM }, - { GRD_INVALID_CONFIG_VALUE, E_CONFIG_INVALID_CHANGE }, - { GRD_DUPLICATE_COLUMN, E_GRD_DUPLICATE_PARAM }, - { GRD_UNDEFINE_COLUMN, E_GRD_UNDEFINED_PARAM }, - { GRD_UNDEFINED_OBJECT, E_GRD_UNDEFINED_PARAM }, - { GRD_UNDEFINED_TABLE, E_GRD_UNDEFINED_PARAM }, - }; - - for (auto [grdErr, gdbErr] : errCodeMap) { - CheckPrepareStepErrCode(grdErr, gdbErr, FuncName::PREPARE); - } -} - -/** - * @tc.name: GdbGrdAdapterTest002 - * @tc.desc: test Step returned the following error code - * @tc.type: FUNC - */ -HWTEST_F(GdbGrdAdapterTest, GdbGrdAdapterTest002, TestSize.Level1) -{ - std::map errCodeMap = { - { GRD_NO_DATA, E_GRD_NO_DATA }, - { GRD_INVALID_TABLE_DEFINITION, E_GRD_SEMANTIC_ERROR }, - { GRD_INVALID_ARGS, E_GRD_INVALID_ARGS }, - { GRD_INVALID_CONFIG_VALUE, E_CONFIG_INVALID_CHANGE }, - { GRD_DATATYPE_MISMATCH, E_GRD_SEMANTIC_ERROR }, - { GRD_DIVISION_BY_ZERO, E_GRD_SYNTAX_ERROR }, - { GRD_MODEL_NOT_SUPPORT, E_GRD_SEMANTIC_ERROR }, - { GRD_FEATURE_NOT_SUPPORTED, E_GRD_SEMANTIC_ERROR }, - { GRD_FIELD_OVERFLOW, E_GRD_SEMANTIC_ERROR }, - { GRD_FILE_OPERATE_FAILED, E_GRD_INNER_ERR }, - { GRD_INSUFFICIENT_RESOURCES, E_GRD_INNER_ERR }, - { GRD_RESOURCE_BUSY, E_DATABASE_BUSY }, - { GRD_OVER_LIMIT, E_GRD_OVER_LIMIT }, - { GRD_REQUEST_TIME_OUT, E_DATABASE_BUSY }, - { GRD_RESTRICT_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_NO_ACTIVE_TRANSACTION, E_GRD_NO_ACTIVE_TRANSACTION }, - { GRD_TRANSACTION_ROLLBACK, E_GRD_TRANSACTION_ROLLBACK }, - { GRD_ACTIVE_TRANSACTION, E_GRD_ACTIVE_TRANSACTION }, - { GRD_UNIQUE_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_PRIMARY_KEY_VIOLATION, E_GRD_DATA_CONFLICT }, - { GRD_UNDEFINED_TABLE, E_GRD_UNDEFINED_PARAM }, - { GRD_UNDEFINED_OBJECT, E_GRD_UNDEFINED_PARAM }, - { GRD_DUPLICATE_TABLE, E_GRD_DUPLICATE_PARAM }, - { GRD_DUPLICATE_OBJECT, E_GRD_DUPLICATE_PARAM }, - { GRD_DATA_CORRUPTED, E_GRD_DATA_CORRUPTED }, - { GRD_THIRD_PARTY_FUNCTION_EXECUTE_FAILED, E_GRD_INNER_ERR }, - { GRD_SCHEMA_CHANGED, E_CONFIG_INVALID_CHANGE }, - }; - - for (auto [grdErr, gdbErr] : errCodeMap) { - CheckPrepareStepErrCode(grdErr, gdbErr, FuncName::STEP); - } -} - -/** - * @tc.name: GdbGrdAdapterTest003 - * @tc.desc: test ReKey returned the following error code - * @tc.type: FUNC - */ -HWTEST_F(GdbGrdAdapterTest, GdbGrdAdapterTest003, TestSize.Level1) -{ - std::map errCodeMap = { - { GRD_INVALID_ARGS, E_GRD_INVALID_ARGS }, - { GRD_INNER_ERR, E_GRD_INNER_ERR }, - { GRD_NO_DATA, E_GRD_NO_DATA }, - { GRD_RESOURCE_BUSY, E_DATABASE_BUSY }, - { GRD_SYSTEM_ERR, E_GRD_INNER_ERR }, - { GRD_INVALID_FORMAT, E_GRD_SEMANTIC_ERROR }, - { GRD_INSUFFICIENT_SPACE, E_GRD_DISK_SPACE_FULL }, - { GRD_DB_INSTANCE_ABNORMAL, E_GRD_DB_INSTANCE_ABNORMAL }, - { GRD_DB_BUSY, E_DATABASE_BUSY }, - { GRD_DATA_CORRUPTED, E_GRD_DATA_CORRUPTED }, - }; - - for (auto [grdErr, gdbErr] : errCodeMap) { - CheckRekeyErrCode(grdErr, gdbErr); - } -} - -/** - * @tc.name: GdbGrdAdapterTest004 - * @tc.desc: test whether the error code returned by Prepare when using the following gql is correct - * @tc.type: FUNC - */ -HWTEST_F(GdbGrdAdapterTest, GdbGrdAdapterTest004, TestSize.Level1) -{ - std::string duplicateObjectGql = "CREATE GRAPH test { " - "(person:Person {name STRING, age INT, age DOUBLE})," - "(person) -[:Friend]-> (person) " - "};"; - std::map errCodeMap = { - { "INSERT (:Person {});", E_GRD_SYNTAX_ERROR }, // GRD_SYNTAX_ERROR - { "INSERT ();", E_GRD_SEMANTIC_ERROR }, // GRD_SEMANTIC_ERROR - { "INSERT (:Person {name: 11, age: 'age_11'});", E_GRD_SEMANTIC_ERROR }, // GRD_DATATYPE_MISMATCH - { "DROP GRAPH nonexistent_graph;", E_GRD_UNDEFINED_PARAM }, // GRD_UNDEFINE_COLUMN - { "MATCH (a: Person {name: 'Alf'}) SET a.nationality='EN'", E_GRD_UNDEFINED_PARAM }, // GRD_UNDEFINED_OBJECT - { "INSERT (:Student {name: 'name_1', age: 11});", E_GRD_UNDEFINED_PARAM }, // GRD_UNDEFINED_TABLE - { duplicateObjectGql, E_GRD_DUPLICATE_PARAM }, // GRD_DUPLICATE_OBJECT - }; - - for (auto [gql, gdbErr] : errCodeMap) { - std::string name = "prepare_test"; - GetStore(name); - ASSERT_NE(store_, nullptr); - - auto [errCode, result] = store_->ExecuteGql(gql); - EXPECT_EQ(errCode, gdbErr); - - DeleteStore(name); - } -} - -/** - * @tc.name: GdbGrdAdapterTest005 - * @tc.desc: test whether the error code returned by Prepare when using the following gql is correct - * @tc.type: FUNC - */ -HWTEST_F(GdbGrdAdapterTest, GdbGrdAdapterTest005, TestSize.Level1) -{ - std::string graphName = "test_"; - for (int i = 0; i < MAX_LEN; i++) { - graphName += "a"; - } - std::string nameTooLongGql = "CREATE GRAPH " + graphName + " { " - "(person:Person {name STRING, age INT, sex BOOL DEFAULT false})," - "(person) -[:Friend]-> (person) " - "};"; - std::string duplicateTableGql = "CREATE GRAPH test { " - "(person:Person {name STRING, age INT, sex BOOL DEFAULT false})," - "(student:Person {name STRING, age INT}), " - "(person) -[:Friend]-> (person) " - "};"; - std::string duplicateColumnGql = "CREATE GRAPH test { " - "(person:Person {name STRING, age INT, age DOUBLE})," - "(person) -[:Friend]-> (person) " - "};"; - std::map errCodeMap = { - { nameTooLongGql, E_GRD_INVALID_NAME }, // GRD_NAME_TOO_LONG - { duplicateTableGql, E_GRD_DUPLICATE_PARAM }, // GRD_DUPLICATE_TABLE - { duplicateColumnGql, E_GRD_DUPLICATE_PARAM }, // GRD_DUPLICATE_COLUMN - }; - - for (auto [gql, gdbErr] : errCodeMap) { - std::string name = "prepare_test"; - auto config = StoreConfig(name, path); - GDBHelper::DeleteDBStore(config); - - int32_t errorCode = E_OK; - store_ = GDBHelper::GetDBStore(config, errorCode); - ASSERT_NE(store_, nullptr); - ASSERT_EQ(errorCode, E_OK); - - auto [errCode, result] = store_->ExecuteGql(gql); - EXPECT_EQ(errCode, gdbErr); - - DeleteStore(name); - } -} - -/** - * @tc.name: GdbGrdAdapterTest006 - * @tc.desc: test whether the error code returned by Step when using the following gql is correct - * @tc.type: FUNC - */ -HWTEST_F(GdbGrdAdapterTest, GdbGrdAdapterTest006, TestSize.Level1) -{ - std::map errCodeMap = { - { "MATCH (p:Person {age: 11}) RETURN p.age / 0;", E_GRD_SYNTAX_ERROR }, // GRD_DIVISION_BY_ZERO - { "MATCH (p:Person {age: 11}) SET p.age=9223372036854775808;", E_GRD_SEMANTIC_ERROR }, // GRD_FIELD_OVERFLOW - }; - - for (auto [gql, gdbErr] : errCodeMap) { - std::string name = "step_test"; - GetStore(name); - ASSERT_NE(store_, nullptr); - - auto [errCode, result] = store_->ExecuteGql(executeGql); - EXPECT_EQ(errCode, E_OK); - - std::tie(errCode, result) = store_->ExecuteGql(gql); - EXPECT_EQ(errCode, gdbErr); - - DeleteStore(name); - } -} - -/** - * @tc.name: GdbGrdAdapterTest007 - * @tc.desc: test whether the error code returned by Step when using the following gql is correct - * @tc.type: FUNC - */ -HWTEST_F(GdbGrdAdapterTest, GdbGrdAdapterTest007, TestSize.Level1) -{ - std::string name = "step_test"; - auto config = StoreConfig(name, path); - GDBHelper::DeleteDBStore(config); - - int32_t errorCode = E_OK; - store_ = GDBHelper::GetDBStore(config, errorCode); - ASSERT_NE(store_, nullptr); - ASSERT_EQ(errorCode, E_OK); - - std::string overLimitGql = "CREATE GRAPH test { (person:Person {"; - for (int i = 0; i < MAX_PROP_CNT; i++) { - overLimitGql += "name" + std::to_string(i) + " STRING, "; - } - overLimitGql += "age INT, sex BOOL DEFAULT false}) };"; - - auto [errCode, result] = store_->ExecuteGql(overLimitGql); - EXPECT_EQ(errCode, E_GRD_OVER_LIMIT); // GRD_OVER_LIMIT - - DeleteStore(name); -} - -/** - * @tc.name: GdbGrdAdapterTest008 - * @tc.desc: test whether the error code returned by Step when using the following gql is correct - * @tc.type: FUNC - */ -HWTEST_F(GdbGrdAdapterTest, GdbGrdAdapterTest008, TestSize.Level1) -{ - std::string name = "step_test"; - GetStore(name); - ASSERT_NE(store_, nullptr); - - auto [errCode, result] = store_->ExecuteGql("CREATE UNIQUE INDEX nameIndex ON Person(name);"); - EXPECT_EQ(errCode, E_OK); - - std::tie(errCode, result) = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 11});"); - EXPECT_EQ(errCode, E_OK); - - std::tie(errCode, result) = store_->ExecuteGql("INSERT (:Person {name: 'name_1', age: 22});"); - EXPECT_EQ(errCode, E_GRD_DATA_CONFLICT); // GRD_UNIQUE_VIOLATION - - DeleteStore(name); -} diff --git a/relational_store/test/native/gdb/unittest/gdb_grdapi_test.cpp b/relational_store/test/native/gdb/unittest/gdb_grdapi_test.cpp deleted file mode 100644 index f9088256..00000000 --- a/relational_store/test/native/gdb/unittest/gdb_grdapi_test.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* -* 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. -*/ - -#define LOG_TAG "GdbGrdApiTest" -#include -#include - -#include -#include -#include - -#include "gdb_errors.h" -#include "db_store_manager.h" -#include "gdb_helper.h" -#include "grd_adapter.h" -#include "grd_adapter_manager.h" -#include "grd_error.h" -#include "logger.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; -class GdbGrdApiTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase(); - void SetUp(); - void TearDown(); -}; - -void GdbGrdApiTest::SetUpTestCase() -{ - LOG_INFO("SetUpTestCase"); -} - -void GdbGrdApiTest::TearDownTestCase() -{ - LOG_INFO("TearDownTestCase"); -} - -void GdbGrdApiTest::SetUp() -{ - LOG_INFO("SetUp"); - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - } -} - -void GdbGrdApiTest::TearDown() -{ - LOG_INFO("TearDown"); -} - -HWTEST_F(GdbGrdApiTest, GdbStore_GrdApi_TransType01, TestSize.Level1) -{ - auto type = GrdAdapter::TransColType(GRD_DB_DATATYPE_INTEGER); - EXPECT_EQ(type, ColumnType::TYPE_INTEGER); - type = GrdAdapter::TransColType(GRD_DB_DATATYPE_FLOAT); - EXPECT_EQ(type, ColumnType::TYPE_FLOAT); - type = GrdAdapter::TransColType(GRD_DB_DATATYPE_TEXT); - EXPECT_EQ(type, ColumnType::TYPE_TEXT); - type = GrdAdapter::TransColType(GRD_DB_DATATYPE_BLOB); - EXPECT_EQ(type, ColumnType::TYPE_BLOB); - type = GrdAdapter::TransColType(GRD_DB_DATATYPE_FLOATVECTOR); - EXPECT_EQ(type, ColumnType::TYPE_FLOATVECTOR); - type = GrdAdapter::TransColType(GRD_DB_DATATYPE_JSONSTR); - EXPECT_EQ(type, ColumnType::TYPE_JSONSTR); - type = GrdAdapter::TransColType(GRD_DB_DATATYPE_NULL); - EXPECT_EQ(type, ColumnType::TYPE_NULL); - type = GrdAdapter::TransColType(-1); - EXPECT_EQ(type, ColumnType::TYPE_NULL); - type = GrdAdapter::TransColType(7); - EXPECT_EQ(type, ColumnType::TYPE_NULL); -} - -HWTEST_F(GdbGrdApiTest, GdbStore_GrdApi_NotUsed01, TestSize.Level1) -{ - std::string createGql = "CREATE GRAPH test {(person:Person {name STRING} )};"; - std::string dbPath = "/data/test.db"; - std::string backupPath = "/data/testBackup.db"; - GDBHelper::DeleteDBStore({"test", "/data"}); - if (g_library != nullptr) { - dlclose(g_library); - } - GRD_DB *db = nullptr; - auto ret = GrdAdapter::Open(dbPath.c_str(), "", GRD_DB_OPEN_CREATE, &db); - EXPECT_EQ(ret, E_OK); - - if (g_library != nullptr) { - dlclose(g_library); - } - std::vector entryKey = { 't', 'e', 's', 't' }; - ret = GrdAdapter::Backup(db, backupPath.c_str(), entryKey); - EXPECT_EQ(ret, E_NOT_SUPPORT); - - if (g_library != nullptr) { - dlclose(g_library); - } - ret = GrdAdapter::Close(db, 0); - EXPECT_EQ(ret, E_OK); - - if (g_library != nullptr) { - dlclose(g_library); - } - ret = GrdAdapter::Restore(dbPath.c_str(), backupPath.c_str(), entryKey); - EXPECT_EQ(ret, E_NOT_SUPPORT); - - if (g_library != nullptr) { - dlclose(g_library); - } - ret = GrdAdapter::Repair(dbPath.c_str(), ""); - EXPECT_EQ(ret, E_NOT_SUPPORT); - - if (g_library != nullptr) { - dlclose(g_library); - } - ret = GrdAdapter::Rekey(dbPath.c_str(), "", std::vector()); - EXPECT_EQ(ret, E_GRD_INVALID_ARGS); - GDBHelper::DeleteDBStore({"test", "/data"}); -} - -HWTEST_F(GdbGrdApiTest, GdbStore_GrdApi_NotUsed02, TestSize.Level1) -{ - std::string createGql = "CREATE GRAPH test {(person:Person {name STRING} )};"; - std::string dbPath = "/data/test.db"; - std::string backupPath = "/data/testBackup.db"; - GDBHelper::DeleteDBStore({"test", "/data"}); - GRD_DB *db = nullptr; - if (g_library != nullptr) { - dlclose(g_library); - } - auto ret = GrdAdapter::Open(dbPath.c_str(), "", GRD_DB_OPEN_CREATE, &db); - EXPECT_EQ(ret, E_OK); - - if (g_library != nullptr) { - dlclose(g_library); - } - GRD_Stmt *stmt = nullptr; - ret = GrdAdapter::Prepare(db, createGql.c_str(), createGql.size(), &stmt, nullptr); - EXPECT_EQ(ret, E_OK); - - if (g_library != nullptr) { - dlclose(g_library); - } - ret = GrdAdapter::Reset(stmt); - EXPECT_EQ(ret, E_OK); - - if (g_library != nullptr) { - dlclose(g_library); - } - auto result = GrdAdapter::ColumnBytes(stmt, 0); - EXPECT_EQ(result, 0); - - if (g_library != nullptr) { - dlclose(g_library); - } - auto result2 = GrdAdapter::ColumnInt64(stmt, 0); - EXPECT_EQ(result2, 0); - - result2 = GrdAdapter::ColumnInt(stmt, 0); - EXPECT_EQ(result2, 0); - - auto result3 = GrdAdapter::ColumnDouble(stmt, 0); - EXPECT_EQ(result3, 0.0); - - if (g_library != nullptr) { - dlclose(g_library); - } - auto value = GrdAdapter::ColumnValue(stmt, 0); - EXPECT_EQ(value.type, GRD_DB_DATATYPE_NULL); - ret = StoreManager::GetInstance().Delete(dbPath); - EXPECT_EQ(ret, 1); - ret = StoreManager::GetInstance().Delete(backupPath); - EXPECT_EQ(ret, 1); - GDBHelper::DeleteDBStore({"test", "/data"}); -} \ No newline at end of file diff --git a/relational_store/test/native/gdb/unittest/gdb_multi_thread_test.cpp b/relational_store/test/native/gdb/unittest/gdb_multi_thread_test.cpp deleted file mode 100644 index 6eded774..00000000 --- a/relational_store/test/native/gdb/unittest/gdb_multi_thread_test.cpp +++ /dev/null @@ -1,342 +0,0 @@ -/* - * 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 "gdb_errors.h" -#include "executor_pool.h" -#include "grd_adapter_manager.h" -#include "gdb_helper.h" -#include "gdb_store.h" -#include "path.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; -class GdbMultiThreadTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - void VerifyPersonInfo(const GraphValue &person, const std::string &name, const int32_t &age); - void MatchAndVerifyPerson(const std::string &name, const int32_t &age, std::shared_ptr store); - void MultiThreadExecuteInsert(std::shared_ptr store); - void MultiThreadExecuteDBStore(); - void MultiThreadInsertRelation(std::shared_ptr store); - void MultiThreadQueryRelation(std::shared_ptr store); - std::string RandomString(size_t length); - -protected: - std::atomic counter; - static const std::string databaseName; - static const std::string databasePath; - static const std::string createGraphGql; - std::shared_ptr executors_; -}; -const std::string GdbMultiThreadTest::databaseName = "execute_test"; -const std::string GdbMultiThreadTest::databasePath = "/data"; -const std::string GdbMultiThreadTest::createGraphGql = "CREATE GRAPH test { " - "(person:Person {name STRING, age INT, sex BOOL DEFAULT false})," - "(dog:Dog {name STRING, age INT}), " - "(person) -[:Friend]-> (person) " - "};"; - -void GdbMultiThreadTest::SetUpTestCase(void) -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } -} - -void GdbMultiThreadTest::TearDownTestCase(void) -{ -} - -void GdbMultiThreadTest::SetUp() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } - int32_t maxThread = 5; - int32_t minThread = 0; - executors_ = std::make_shared(maxThread, minThread); -} - -void GdbMultiThreadTest::TearDown() -{ - executors_ = nullptr; -} - -/** - * @tc.name: MultiThread_GetDBStore_0001 - * @tc.desc: Start two threads to open the database. - * @tc.type: FUNC - */ -HWTEST_F(GdbMultiThreadTest, MultiThread_GetDBStore_0001, TestSize.Level2) -{ - counter.store(0); - MultiThreadExecuteDBStore(); - MultiThreadExecuteDBStore(); - while (true) { - if (counter.load() == 100) { - break; - } - } -} - -/** - * @tc.name: MultiThreadExecuteDBStore - * @tc.desc: Start the database in the current thread for 50 times. - * @tc.type: FUNC - */ -void GdbMultiThreadTest::MultiThreadExecuteDBStore() -{ - executors_->Execute([this]() { - int errCode = E_OK; - std::string dbName = RandomString(10) + RandomString(10); - constexpr int32_t COUNT = 50; - for (uint32_t j = 0; j < COUNT; j++) { - auto config = StoreConfig(dbName + std::to_string(j), databasePath); - GDBHelper::DeleteDBStore(config); - auto store = GDBHelper::GetDBStore(config, errCode); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(store, nullptr); - EXPECT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - - result = store->ExecuteGql("DROP GRAPH test"); - EXPECT_NE(store, nullptr); - EXPECT_EQ(result.first, E_OK); - GDBHelper::DeleteDBStore(config); - counter.fetch_add(1, std::memory_order_relaxed); - } - }); -} - -/** - * @tc.name: MultiThread_GetDBStore_0002 - * @tc.desc: Start two threads to test the insertion Vertex and Edge. - * @tc.type: FUNC - */ -HWTEST_F(GdbMultiThreadTest, MultiThread_GetDBStore_0002, TestSize.Level2) -{ - int errCode = E_OK; - auto config = StoreConfig(databaseName + "test22", databasePath); - auto store = GDBHelper::GetDBStore(config, errCode); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(store, nullptr); - EXPECT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - counter.store(0); - MultiThreadExecuteInsert(store); - sleep(1); - MultiThreadExecuteInsert(store); - while (true) { - // counter ++ 200 - if (counter.load() == 200) { - break; - } - } - sleep(1); - result = store->ExecuteGql("DROP GRAPH test"); - EXPECT_NE(store, nullptr); - EXPECT_EQ(result.first, E_OK); - GDBHelper::DeleteDBStore(config); -} - -/** - * @tc.name: MultiThreadExecuteInsert - * @tc.desc: Start threads to test the insertion Vertex and Edge. - * @tc.type: FUNC - */ -void GdbMultiThreadTest::MultiThreadExecuteInsert(std::shared_ptr store) -{ - executors_->Execute([this, &store]() { - std::string nameStr = RandomString(10) + RandomString(10); - constexpr int32_t MAX_COUNT = 100; - for (uint32_t j = 0; j < MAX_COUNT; j++) { - std::string name = nameStr + std::to_string(j); - auto result = store->ExecuteGql("INSERT (:Person {name: '" + name + "', age: 11});"); - EXPECT_EQ(result.first, E_OK); - constexpr int32_t AGE_11 = 11; - MatchAndVerifyPerson(name, AGE_11, store); - - std::string name2 = name + std::to_string(j); - result = store->ExecuteGql("INSERT (:Person {name: '" + name2 + "', age: 22});"); - EXPECT_EQ(result.first, E_OK); - constexpr int32_t AGE = 22; - MatchAndVerifyPerson(name2, AGE, store); - - std::string name3 = name2 + std::to_string(j); - result = store->ExecuteGql("INSERT (:Person {name: '" + name3 + "', age: 33});"); - EXPECT_EQ(result.first, E_OK); - constexpr int32_t AGE_33 = 33; - MatchAndVerifyPerson(name3, AGE_33, store); - - result = store->ExecuteGql("MATCH (p1:Person {name: '" + name + "'}), (p2:Person {name: '" + name2 + - "'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - result = store->ExecuteGql("MATCH (p1:Person {name: '" + name2 + "'}), (p2:Person {name: '" + name3 + - "'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - - result = store->QueryGql( - "MATCH (person:Person {name: '" + name + "'})-[relation:Friend]->() RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - - auto result2 = store->QueryGql("MATCH path=(a:Person {name: '" + name + - "'})-[]->{2, 2}(b:Person {name: '" + name3 + "'}) RETURN path;"); - ASSERT_EQ(result2.first, E_OK); - counter.fetch_add(1, std::memory_order_relaxed); - } - }); -} - -/** - * @tc.name: MultiThread_GetDBStore_0003 - * @tc.desc: Start two threads to insert edges of the same Vertex, and start another thread to query edges. - * @tc.type: FUNC - */ -HWTEST_F(GdbMultiThreadTest, MultiThread_GetDBStore_0003, TestSize.Level2) -{ - int errCode = E_OK; - auto config = StoreConfig(databaseName + "test33", databasePath); - auto store = GDBHelper::GetDBStore(config, errCode); - auto result = store->ExecuteGql(createGraphGql); - EXPECT_NE(store, nullptr); - EXPECT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - counter.store(0); - - std::string name = "zhangsan"; - result = store->ExecuteGql("INSERT (:Person {name: '" + name + "', age: 11});"); - EXPECT_EQ(result.first, E_OK); - constexpr int32_t AGE_11 = 11; - MatchAndVerifyPerson(name, AGE_11, store); - //insert Vertex and edge - MultiThreadInsertRelation(store); - MultiThreadInsertRelation(store); - sleep(1); - //query Vertex and edge - MultiThreadExecuteInsert(store); - while (true) { - if (counter.load() == 300) { - break; - } - } - // query match count is 200 - result = - store->QueryGql("MATCH (person:Person {name: '" + name + "'})-[relation:Friend]->() RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 200); - - result = store->ExecuteGql("DROP GRAPH test"); - EXPECT_NE(store, nullptr); - EXPECT_EQ(result.first, E_OK); - GDBHelper::DeleteDBStore(config); -} - -void GdbMultiThreadTest::MultiThreadInsertRelation(std::shared_ptr store) -{ - executors_->Execute([this, &store]() { - std::string nameStr = RandomString(10) + RandomString(10); - std::string name = "zhangsan"; - constexpr int32_t MAX_COUNT = 100; - for (uint32_t j = 0; j < MAX_COUNT; j++) { - std::string name2 = nameStr + std::to_string(j); - auto result = store->ExecuteGql("INSERT (:Person {name: '" + name2 + "', age: 22});"); - EXPECT_EQ(result.first, E_OK); - constexpr int32_t AGE = 22; - MatchAndVerifyPerson(name2, AGE, store); - - result = store->ExecuteGql("MATCH (p1:Person {name: '" + name + "'}), (p2:Person {name: '" + name2 + - "'}) INSERT (p1)-[:Friend]->(p2);"); - EXPECT_EQ(result.first, E_OK); - counter.fetch_add(1, std::memory_order_relaxed); - } - }); -} - -void GdbMultiThreadTest::MultiThreadQueryRelation(std::shared_ptr store) -{ - executors_->Execute([this, &store]() { - std::string name = "zhangsan"; - constexpr int32_t MAX_COUNT = 100; - for (uint32_t j = 0; j < MAX_COUNT; j++) { - auto result = store->QueryGql( - "MATCH (person:Person {name: '" + name + "'})-[relation:Friend]->() RETURN person, relation;"); - ASSERT_EQ(result.first, E_OK); - counter.fetch_add(1, std::memory_order_relaxed); - } - }); -} - -std::string GdbMultiThreadTest::RandomString(size_t length) -{ - const std::string letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(0, letters.size() - 1); - - std::string randomStr; - for (size_t i = 0; i < length; ++i) { - randomStr.push_back(letters[dis(gen)]); - } - return randomStr; -} - -void GdbMultiThreadTest::MatchAndVerifyPerson( - const std::string &name, const int32_t &age, std::shared_ptr store) -{ - EXPECT_NE(store, nullptr); - auto gql = "MATCH (person:Person {name: '" + name + "', age: " + std::to_string(age) + "}) RETURN person;"; - auto result = store->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - ASSERT_EQ(result.second->GetAllData().size(), 1); - GraphValue person = result.second->GetAllData()[0]["person"]; - VerifyPersonInfo(person, name, age); -} - -void GdbMultiThreadTest::VerifyPersonInfo(const GraphValue &person, const std::string &name, const int32_t &age) -{ - auto expectSize = 3; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), expectSize); - - auto nameDb = personVertex->GetProperties().find("name"); - ASSERT_NE(nameDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(nameDb->second)); - EXPECT_EQ(std::get(nameDb->second), name); - - auto ageDb = personVertex->GetProperties().find("age"); - ASSERT_NE(ageDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(ageDb->second)); - EXPECT_EQ(std::get(ageDb->second), age); - - auto sex = personVertex->GetProperties().find("sex"); - ASSERT_NE(sex, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(sex->second)); - EXPECT_EQ(std::get(sex->second), 0); -} \ No newline at end of file diff --git a/relational_store/test/native/gdb/unittest/gdb_query_test.cpp b/relational_store/test/native/gdb/unittest/gdb_query_test.cpp deleted file mode 100644 index eac39961..00000000 --- a/relational_store/test/native/gdb/unittest/gdb_query_test.cpp +++ /dev/null @@ -1,646 +0,0 @@ -/* -* 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 - -#include -#include -#include -#include -#include - -#include "gdb_errors.h" -#include "gdb_helper.h" -#include "gdb_store.h" -#include "grd_adapter_manager.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; -class GdbQueryTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase(); - void SetUp(); - void TearDown(); - void InsertCompany(const std::string &name, const int32_t &founded); - void MatchAndVerifyCompany(const std::string &name, const int32_t &founded); - void VerifyCompanyInfo(const GraphValue &company, const std::string &name, const int32_t &founded); - - static const std::string databaseName; - static const std::string databasePath; - static std::shared_ptr store_; - static const std::string createGraphGql; - static const std::string createGraphGql2; - static const std::shared_ptr databaseConfig; -}; -std::shared_ptr GdbQueryTest::store_; -const std::string GdbQueryTest::databaseName = "test_gdb"; -const std::string GdbQueryTest::databasePath = "/data"; -const std::string GdbQueryTest::createGraphGql = "CREATE GRAPH companyGraph { " - "(company:Company {name STRING, founded INT}), " - "(department:Department {name STRING}), " - "(employee:Employee {name STRING, position STRING}), " - "(project:Project {name STRING, budget INT}), " - "(company) -[:HAS_DEPARTMENT]-> (department), " - "(department) -[:HAS_EMPLOYEE]-> (employee), " - "(employee) -[:WORKS_ON]-> (project), " - "(department) -[:HAS_PROJECT]-> (project) " - "};"; -const std::string GdbQueryTest::createGraphGql2 = "CREATE GRAPH companyGraph2 {" - "(company:Company {name STRING, founded INT}) };"; -void GdbQueryTest::SetUpTestCase() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - } - int errCode = E_OK; - auto config = StoreConfig(databaseName, databasePath); - GDBHelper::DeleteDBStore(config); - - GdbQueryTest::store_ = GDBHelper::GetDBStore(config, errCode); - EXPECT_NE(GdbQueryTest::store_, nullptr); - EXPECT_EQ(errCode, E_OK); -} - -void GdbQueryTest::TearDownTestCase() -{ - GDBHelper::DeleteDBStore(StoreConfig(databaseName, databasePath)); - store_ = nullptr; -} - -void GdbQueryTest::SetUp() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - } - auto result = store_->ExecuteGql(createGraphGql); - EXPECT_EQ(result.first, E_OK); -} - -void GdbQueryTest::TearDown() -{ - if (store_ != nullptr) { - auto result = store_->ExecuteGql("DROP GRAPH companyGraph"); - } -} - -HWTEST_F(GdbQueryTest, GdbStore_Test_CreateHaveRowId, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - auto createGql = "CREATE GRAPH companyGraph3 {" - "(company:Company {rowid INT, name STRING, founded INT}) };"; - auto result = store_->ExecuteGql(createGql); - EXPECT_EQ(result.first, E_GRD_OVER_LIMIT); -} - -/** - * @tc.name: GdbStore_Test_CreateLimitDb - * @tc.desc: Too many graphs can be created for only one graph in a library. Failed to create too many graphs. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_Test_CreateLimitDb, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - // Too many graphs can be created for only one graph in a library. Failed to create too many graphs. - auto result = store_->ExecuteGql(createGraphGql2); - EXPECT_EQ(result.first, E_GRD_OVER_LIMIT); -} - -/** - * @tc.name: GdbStore_QuertTest_001 - * @tc.desc: To test the function of querying an employee. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_001, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - // Insert Employee - const std::string insertEmployeeQuery = "INSERT (:Employee {name: 'John Doe11', position: 'Software Engineer'});"; - auto result = store_->ExecuteGql(insertEmployeeQuery); - EXPECT_EQ(result.first, E_OK); - - // Verifying the Employee Vertex - result = store_->QueryGql("MATCH (e:Employee {name: 'John Doe11'}) RETURN e;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - - GraphValue employee = result.second->GetAllData()[0]["e"]; - ASSERT_TRUE(std::holds_alternative>(employee)); - auto employeeVertex = std::get>(employee); - EXPECT_EQ(employeeVertex->GetLabel(), "Employee"); - - auto name = employeeVertex->GetProperties().find("name"); - ASSERT_NE(name, employeeVertex->GetProperties().end()); - EXPECT_EQ(std::get(name->second), "John Doe11"); - - auto position = employeeVertex->GetProperties().find("position"); - ASSERT_NE(position, employeeVertex->GetProperties().end()); - EXPECT_EQ(std::get(position->second), "Software Engineer"); -} - -/** - * @tc.name: GdbStore_QuertTest_002 - * @tc.desc: To test the function of querying an Employee and Project and Relation. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_002, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - // insert Employee - auto result = store_->ExecuteGql("INSERT (:Employee {name: 'John Doe', position: 'Software Engineer'});"); - EXPECT_EQ(result.first, E_OK); - // insert Project - result = store_->ExecuteGql("INSERT (:Project {name: 'Project Alpha'});"); - EXPECT_EQ(result.first, E_OK); - - // Associating an Employee with a Project, WORKS_ON - const std::string insertRelationQuery = - "MATCH (e:Employee {name: 'John Doe'}), (p:Project {name: 'Project Alpha'}) " - "INSERT (e)-[:WORKS_ON]->(p);"; - result = store_->ExecuteGql(insertRelationQuery); - EXPECT_EQ(result.first, E_OK); - - // Querying and Verifying the Relationship Existence - result = store_->QueryGql("MATCH (e:Employee {name: 'John Doe'})-[r:WORKS_ON]->" - "(p:Project {name: 'Project Alpha'}) RETURN e, r, p;"); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - - // Verifying the Employee Vertex - GraphValue employee = result.second->GetAllData()[0]["e"]; - ASSERT_TRUE(std::holds_alternative>(employee)); - auto employeeVertex = std::get>(employee); - EXPECT_EQ(employeeVertex->GetLabel(), "Employee"); - - // Verifying Project Vertex - GraphValue project = result.second->GetAllData()[0]["p"]; - ASSERT_TRUE(std::holds_alternative>(project)); - auto projectVertex = std::get>(project); - EXPECT_EQ(projectVertex->GetLabel(), "Project"); - - // Validate Relationships - GraphValue relation = result.second->GetAllData()[0]["r"]; - ASSERT_TRUE(std::holds_alternative>(relation)); - auto relationship = std::get>(relation); - EXPECT_EQ(relationship->GetSourceId(), "1"); - EXPECT_EQ(relationship->GetTargetId(), "2"); -} - -/** - * @tc.name: MatchAndVerifyCompany - * @tc.desc: Match And Verify that company information meets expectations - * @tc.type: FUNC - */ -void GdbQueryTest::MatchAndVerifyCompany(const std::string &name, const int32_t &founded) -{ - ASSERT_NE(store_, nullptr); - auto gql = "MATCH (company:Company {name: '" + name + "'}) RETURN company;"; - auto result = store_->QueryGql(gql); - ASSERT_EQ(result.first, E_OK); - ASSERT_NE(result.second, nullptr); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, name, founded); -} - -/** - * @tc.name: VerifyCompanyInfo - * @tc.desc: Verify that company information meets expectations - * @tc.type: FUNC - */ -void GdbQueryTest::VerifyCompanyInfo(const GraphValue &company, const std::string &name, const int32_t &founded) -{ - auto expectSize = 2; - ASSERT_TRUE(std::holds_alternative>(company)); - auto companyVertex = std::get>(company); - EXPECT_EQ(companyVertex->GetLabel(), "Company"); - ASSERT_EQ(companyVertex->GetProperties().size(), expectSize); - - auto nameDb = companyVertex->GetProperties().find("name"); - ASSERT_NE(nameDb, companyVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(nameDb->second)); - EXPECT_EQ(std::get(nameDb->second), name); - - auto foundedDb = companyVertex->GetProperties().find("founded"); - ASSERT_NE(foundedDb, companyVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(foundedDb->second)); - EXPECT_EQ(std::get(foundedDb->second), founded); -} - -/** - * @tc.name: InsertCompany - * @tc.desc: Insert Company Information - * @tc.type: FUNC - */ -void GdbQueryTest::InsertCompany(const std::string &name, const int32_t &founded) -{ - ASSERT_NE(store_, nullptr); - auto result = - store_->ExecuteGql("INSERT (:Company {name: '" + name + "', founded: " + std::to_string(founded) + "});"); - EXPECT_EQ(result.first, E_OK); - MatchAndVerifyCompany(name, founded); -} - -/** - * @tc.name: GdbStore_QuertTest_WhereInMatch - * @tc.desc: Verify the where condition in match. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_WhereInMatch, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("myCompany3", 2011); - // where condition in match. - auto result = store_->QueryGql("MATCH (company:Company where company.founded > 2000) RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany2", 2001); - - GraphValue company1 = result.second->GetAllData()[1]["company"]; - VerifyCompanyInfo(company1, "myCompany3", 2011); -} - -/** - * @tc.name: GdbStore_QuertTest_WhereOutsideMatch - * @tc.desc: Validate where condition outside match - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_WhereOutsideMatch, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("myCompany3", 2011); - // where condition outside match - auto result = store_->QueryGql("MATCH (company:Company) where company.founded != 2001 RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany", 1991); - - GraphValue company1 = result.second->GetAllData()[1]["company"]; - VerifyCompanyInfo(company1, "myCompany3", 2011); -} - -/** - * @tc.name: GdbStore_QuertTest_WhereAppendAnd - * @tc.desc: Verify that the where condition is appended to the AND statement outside the match condition. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_WhereAppendAnd, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("myCompany3", 2011); - // Verify that the where condition is appended to the AND statement outside the match condition. - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.founded != 2001 and company.name <> 'myCompany3' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany", 1991); -} - -/** - * @tc.name: GdbStore_QuertTest_WhereOutsideAndInsideMatch - * @tc.desc: Validate where conditions outside and inside match - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_WhereOutsideAndInsideMatch, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("myCompany3", 2011); - // Validate where conditions outside and inside match - auto result = store_->QueryGql("MATCH (company:Company where company.founded != 2001 ) " - " where company.name <> 'myCompany3' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany", 1991); -} - -/** - * @tc.name: GdbStore_QuertTest_WhereStartAnd - * @tc.desc: The validation condition is outside and inside match, but outside it starts with and, not where. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_WhereStartAnd, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("myCompany3", 2011); - // The validation condition is outside and inside match, but outside it starts with and, not where. - auto result = store_->QueryGql("MATCH (company:Company where company.founded != 2001 ) " - " AND company.name <> 'myCompany3' RETURN company;"); - ASSERT_EQ(result.first, E_GRD_SYNTAX_ERROR); - EXPECT_EQ(result.second->GetAllData().size(), 0); -} - -/** - * @tc.name: GdbStore_QuertTest_WhereByMatch - * @tc.desc: Use {} to transfer query conditions in match. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_WhereByMatch, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("myCompany3", 2011); - // The validation condition is outside and inside match, but outside it starts with and, not where. - auto result = store_->QueryGql("MATCH (company:Company {founded: 2001} ) " - " where company.name = 'myCompany2' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany2", 2001); -} - -/** - * @tc.name: GdbStore_QuertTest_WhereOperators - * @tc.desc: Verify that operators are supported in the where condition. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_WhereOperators, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("myCompany3", 2011); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.founded >= 2000+1 and company.founded < 2012 -1 RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany2", 2001); - - result = store_->QueryGql("MATCH (company:Company) " - "where company.founded > 2 * 1000 +1 and company.founded < 2 * 1000 +12 RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany3", 2011); -} - -/** - * @tc.name: GdbStore_QuertTest_PostLike - * @tc.desc: Verify that the matching starts with a fixed character and ends with any number of other characters. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_PostLike, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("aimyCompany", 2011); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.name like 'myCompany%' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany", 1991); - - company = result.second->GetAllData()[1]["company"]; - VerifyCompanyInfo(company, "myCompany2", 2001); -} - -/** - * @tc.name: GdbStore_QuertTest_WhereLike - * @tc.desc: Matches contain specific characters. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_Like, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("aimyCompany", 2011); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.name like '%myCompany%' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 3); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany", 1991); - - company = result.second->GetAllData()[1]["company"]; - VerifyCompanyInfo(company, "myCompany2", 2001); - - company = result.second->GetAllData()[2]["company"]; - VerifyCompanyInfo(company, "aimyCompany", 2011); -} - -/** - * @tc.name: GdbStore_QuertTest_BeferLike - * @tc.desc: Matches any number of other characters before the end of a fixed character. - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_BeferLike, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - InsertCompany("myCompany", 1991); - InsertCompany("myCompany2", 2001); - InsertCompany("aimyCompany", 2011); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.name like '%myCompany' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany", 1991); - - company = result.second->GetAllData()[1]["company"]; - VerifyCompanyInfo(company, "aimyCompany", 2011); -} - -/** - * @tc.name: GdbStore_QuertTest_MatchesCharacter - * @tc.desc: Matches a character - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_MatchesCharacter, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("amyCompany", 2001); - InsertCompany("amyCompanya", 2002); - InsertCompany("abmyCompanyab", 2003); - InsertCompany("abmyCompany", 2004); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.name like '_myCompany' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "amyCompany", 2001); -} - -/** - * @tc.name: GdbStore_QuertTest_MatchesCharacter02 - * @tc.desc: Matches a character - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_MatchesCharacter02, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - InsertCompany("myCompany", 1991); - InsertCompany("amyCompany", 2001); - InsertCompany("amyCompanya", 2002); - InsertCompany("abmyCompanyab", 2003); - InsertCompany("abmyCompany", 2004); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.name like '_myCompany_' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "amyCompanya", 2002); -} - -/** - * @tc.name: GdbStore_QuertTest_MatchesCharacter03 - * @tc.desc: Matches a character - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_MatchesCharacter03, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - InsertCompany("myCompany", 1991); - InsertCompany("myCompanya", 2001); - InsertCompany("myCompanyab", 2002); - InsertCompany("amyCompanya", 2003); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.name like 'myCompany_' RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompanya", 2001); -} - -/** - * @tc.name: GdbStore_QuertTest_In - * @tc.desc: Match conditions in - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_In, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - InsertCompany("myCompany", 1991); - InsertCompany("myCompany1", 2001); - InsertCompany("myCompany2", 2002); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.founded in (2001, 2002, 9999) RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany1", 2001); - - company = result.second->GetAllData()[1]["company"]; - VerifyCompanyInfo(company, "myCompany2", 2002); -} - -/** - * @tc.name: GdbStore_QuertTest_In01 - * @tc.desc: Match conditions in - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_NotIn, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - InsertCompany("myCompany", 1991); - InsertCompany("myCompany1", 2001); - InsertCompany("myCompany2", 2002); - auto result = store_->QueryGql("MATCH (company:Company) " - "where company.founded not in (2001, 9999) RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany", 1991); - - company = result.second->GetAllData()[1]["company"]; - VerifyCompanyInfo(company, "myCompany2", 2002); -} - -/** - * @tc.name: GdbStore_QuertTest_IsNull - * @tc.desc: Match conditions in - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_IsNull, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto result = store_->ExecuteGql("INSERT (:Employee {name: 'zhangsan', position: 'Software'});"); - EXPECT_EQ(result.first, E_OK); - result = store_->ExecuteGql("INSERT (:Employee {name: 'zhangsan1', position: 'Software1'});"); - EXPECT_EQ(result.first, E_OK); - // 寮簊chema涓嬪叾浠栨湭濉瓧娈典负null - result = store_->ExecuteGql("MATCH (e:Employee {name: 'zhangsan'}) SET e = {position: 'SoftwareNew'};"); - EXPECT_EQ(result.first, E_OK); - result = store_->QueryGql("MATCH (e:Employee) " - "where e.name IS NULL RETURN e;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 1); - GraphValue company = result.second->GetAllData()[0]["e"]; - ASSERT_TRUE(std::holds_alternative>(company)); - auto companyVertex = std::get>(company); - EXPECT_EQ(companyVertex->GetLabel(), "Employee"); - ASSERT_EQ(companyVertex->GetProperties().size(), 1); - - auto nameDb = companyVertex->GetProperties().find("name"); - EXPECT_EQ(nameDb, companyVertex->GetProperties().end()); - - auto foundedDb = companyVertex->GetProperties().find("position"); - ASSERT_NE(foundedDb, companyVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(foundedDb->second)); - EXPECT_EQ(std::get(foundedDb->second), "SoftwareNew"); -} - -/** - * @tc.name: GdbStore_QuertTest_IsNotNull - * @tc.desc: Match conditions in - * @tc.type: FUNC - */ -HWTEST_F(GdbQueryTest, GdbStore_QuertTest_IsNotNull, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto result = store_->ExecuteGql("INSERT (:Company {founded: 1991});"); - EXPECT_EQ(result.first, E_OK); - InsertCompany("myCompany1", 2001); - InsertCompany("myCompany2", 2002); - result = store_->QueryGql("MATCH (company:Company) " - "where company.name IS NOT NULL RETURN company;"); - ASSERT_EQ(result.first, E_OK); - EXPECT_EQ(result.second->GetAllData().size(), 2); - GraphValue company = result.second->GetAllData()[0]["company"]; - VerifyCompanyInfo(company, "myCompany1", 2001); - - company = result.second->GetAllData()[1]["company"]; - VerifyCompanyInfo(company, "myCompany2", 2002); -} \ No newline at end of file diff --git a/relational_store/test/native/gdb/unittest/gdb_transaction_test.cpp b/relational_store/test/native/gdb/unittest/gdb_transaction_test.cpp deleted file mode 100644 index 71626cbe..00000000 --- a/relational_store/test/native/gdb/unittest/gdb_transaction_test.cpp +++ /dev/null @@ -1,802 +0,0 @@ -/* - * 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 "gdb_transaction.h" - -#include - -#include -#include -#include -#include -#include - -#include "edge.h" -#include "full_result.h" -#include "gdb_errors.h" -#include "gdb_helper.h" -#include "gdb_store.h" -#include "grd_adapter_manager.h" -#include "path.h" -#include "result.h" -#include "vertex.h" - -using namespace testing::ext; -using namespace OHOS::DistributedDataAip; - -using Transaction = OHOS::DistributedDataAip::Transaction; - -class GdbTransactionTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase(); - void SetUp(); - void TearDown(); - void InsertPerson(const std::string &name, const int32_t &age, std::shared_ptr trans = nullptr); - void MatchAndVerifyPerson(const std::string &name, const int32_t &age, - std::shared_ptr trans = nullptr, bool hasData = true); - void VerifyPersonInfo(const GraphValue &person, const std::string &name, const int32_t &age); - - static const std::string databaseName; - static const std::string databasePath; - - static const std::string createGraphGql; - - static std::shared_ptr store_; -}; - -const std::string GdbTransactionTest::databaseName = "transaction_test"; -const std::string GdbTransactionTest::databasePath = "/data"; - -const std::string GdbTransactionTest::createGraphGql = "CREATE GRAPH test { " - "(person:Person {name STRING, age INT, sex BOOL DEFAULT false})," - "(dog:Dog {name STRING, age INT}), " - "(person) -[:Friend]-> (person) " - "};"; - -std::shared_ptr GdbTransactionTest::store_; - -static constexpr int32_t MAX_GQL_LEN = 1024 * 1024; - -static constexpr int32_t MAX_CNT = 4; -static constexpr int32_t MAX_DATA_CNT = 200; - -static constexpr int32_t BUSY_TIMEOUT = 2; -static constexpr int32_t EXECUTE_INTERVAL = 3; -static constexpr int32_t READ_INTERVAL = 100; - -void GdbTransactionTest::SetUpTestCase() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } - int errCode = E_OK; - auto config = StoreConfig(databaseName, databasePath); - GDBHelper::DeleteDBStore(config); - - GdbTransactionTest::store_ = GDBHelper::GetDBStore(config, errCode); -} - -void GdbTransactionTest::TearDownTestCase() -{ - GDBHelper::DeleteDBStore(StoreConfig(databaseName, databasePath)); - GdbTransactionTest::store_ = nullptr; -} - -void GdbTransactionTest::SetUp() -{ - if (!IsSupportArkDataDb()) { - GTEST_SKIP() << "Current testcase is not compatible from current gdb"; - return; - } - auto result = store_->ExecuteGql(createGraphGql); -} - -void GdbTransactionTest::TearDown() -{ - if (store_ != nullptr) { - auto result = store_->ExecuteGql("DROP GRAPH test"); - } -} - -void GdbTransactionTest::InsertPerson(const std::string &name, const int32_t &age, std::shared_ptr trans) -{ - ASSERT_NE(store_, nullptr); - int32_t errCode = E_OK; - std::shared_ptr result = std::make_shared(); - std::string gql = "INSERT (:Person {name: '" + name + "', age: " + std::to_string(age) + "});"; - if (trans == nullptr) { - std::tie(errCode, result) = store_->ExecuteGql(gql); - } else { - ASSERT_NE(trans, nullptr); - std::tie(errCode, result) = trans->Execute(gql); - } - EXPECT_EQ(errCode, E_OK); -} - -void GdbTransactionTest::MatchAndVerifyPerson(const std::string &name, const int32_t &age, - std::shared_ptr trans, bool hasData) -{ - ASSERT_NE(store_, nullptr); - int32_t errCode = E_OK; - std::shared_ptr result = std::make_shared(); - std::string gql = "MATCH (person:Person {name: '" + name + "'}) RETURN person;"; - if (trans == nullptr) { - std::tie(errCode, result) = store_->QueryGql(gql); - } else { - ASSERT_NE(trans, nullptr); - std::tie(errCode, result) = trans->Query(gql); - } - ASSERT_EQ(errCode, E_OK); - ASSERT_NE(result, nullptr); - if (!hasData) { - EXPECT_EQ(result->GetAllData().size(), 0); - return; - } - EXPECT_EQ(result->GetAllData().size(), 1); - GraphValue person = result->GetAllData()[0]["person"]; - VerifyPersonInfo(person, name, age); -} - -void GdbTransactionTest::VerifyPersonInfo(const GraphValue &person, const std::string &name, const int32_t &age) -{ - auto expectSize = 3; - ASSERT_TRUE(std::holds_alternative>(person)); - auto personVertex = std::get>(person); - EXPECT_EQ(personVertex->GetLabel(), "Person"); - ASSERT_EQ(personVertex->GetProperties().size(), expectSize); - - auto nameDb = personVertex->GetProperties().find("name"); - ASSERT_NE(nameDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(nameDb->second)); - EXPECT_EQ(std::get(nameDb->second), name); - - auto ageDb = personVertex->GetProperties().find("age"); - ASSERT_NE(ageDb, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(ageDb->second)); - EXPECT_EQ(std::get(ageDb->second), age); - - auto sex = personVertex->GetProperties().find("sex"); - ASSERT_NE(sex, personVertex->GetProperties().end()); - ASSERT_TRUE(std::holds_alternative(sex->second)); - EXPECT_EQ(std::get(sex->second), 0); -} - -/** - * @tc.name: GdbTransactionTest001_CreateTransaction_Normal - * @tc.desc: test CreateTransaction - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest001_CreateTransaction_Normal, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err1, trans1] = store_->CreateTransaction(); - EXPECT_EQ(err1, E_OK); - EXPECT_NE(trans1, nullptr); - - auto [err2, trans2] = store_->CreateTransaction(); - EXPECT_EQ(err2, E_OK); - EXPECT_NE(trans2, nullptr); - - auto [err3, trans3] = store_->CreateTransaction(); - EXPECT_EQ(err3, E_OK); - EXPECT_NE(trans3, nullptr); - - auto [err4, trans4] = store_->CreateTransaction(); - EXPECT_EQ(err4, E_OK); - EXPECT_NE(trans4, nullptr); - - err4 = trans4->Commit(); - EXPECT_EQ(err4, E_OK); - - auto [err5, trans5] = store_->CreateTransaction(); - EXPECT_EQ(err5, E_OK); - EXPECT_NE(trans5, nullptr); -} - -/** - * @tc.name: GdbTransactionTest002_CreateTransaction_Abnormal - * @tc.desc: test CreateTransaction upper bound - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest002_CreateTransaction_Abnormal, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err1, trans1] = store_->CreateTransaction(); - EXPECT_EQ(err1, E_OK); - EXPECT_NE(trans1, nullptr); - - auto [err2, trans2] = store_->CreateTransaction(); - EXPECT_EQ(err2, E_OK); - EXPECT_NE(trans2, nullptr); - - auto [err3, trans3] = store_->CreateTransaction(); - EXPECT_EQ(err3, E_OK); - EXPECT_NE(trans3, nullptr); - - auto [err4, trans4] = store_->CreateTransaction(); - EXPECT_EQ(err4, E_OK); - EXPECT_NE(trans4, nullptr); - - auto [err5, trans5] = store_->CreateTransaction(); - EXPECT_EQ(err5, E_DATABASE_BUSY); - EXPECT_EQ(trans5, nullptr); -} - -/** - * @tc.name: GdbTransactionTest003_Query_Execute_Normal - * @tc.desc: test Transaction::Query and Transaction::Execute - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest003_Query_Execute_Normal, TestSize.Level1) -{ - InsertPerson("name_1", 11); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - - MatchAndVerifyPerson("name_1", 11, trans); - - InsertPerson("name_2", 22, trans); - - MatchAndVerifyPerson("name_2", 22, trans); -} - -/** - * @tc.name: GdbTransactionTest004_Query_Execute_Abnormal - * @tc.desc: test Transaction::Query and Transaction::Execute with invalid gql - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest004_Query_Execute_Abnormal, TestSize.Level1) -{ - InsertPerson("name_1", 11); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - - int32_t errCode = E_OK; - std::shared_ptr result = std::make_shared(); - std::string gql = ""; - std::tie(errCode, result) = trans->Query(gql); - EXPECT_EQ(errCode, E_INVALID_ARGS); - - std::tie(errCode, result) = trans->Execute(gql); - EXPECT_EQ(errCode, E_INVALID_ARGS); - - for (int i = 0; i <= MAX_GQL_LEN; i++) { - gql += "I"; - } - std::tie(errCode, result) = trans->Query(gql); - EXPECT_EQ(errCode, E_INVALID_ARGS); - - std::tie(errCode, result) = trans->Execute(gql); - EXPECT_EQ(errCode, E_INVALID_ARGS); - - gql = "MATCH (person:Person {name: 11}) RETURN person;"; - std::tie(errCode, result) = trans->Query(gql); - EXPECT_EQ(errCode, E_GRD_SEMANTIC_ERROR); - - std::tie(err, trans) = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - gql = "INSERT (:Person {name: 11, age: 'name_1'});"; - std::tie(errCode, result) = trans->Execute(gql); - EXPECT_EQ(errCode, E_GRD_SEMANTIC_ERROR); - - std::tie(err, trans) = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - gql = "MATCH;"; - std::tie(errCode, result) = trans->Query(gql); - EXPECT_EQ(errCode, E_GRD_SYNTAX_ERROR); - - std::tie(err, trans) = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - gql = "INSERT;"; - std::tie(errCode, result) = trans->Execute(gql); - EXPECT_EQ(errCode, E_GRD_SYNTAX_ERROR); -} - -/** - * @tc.name: GdbTransactionTest005_Commit_Normal - * @tc.desc: test Transaction::Commit - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest005_Commit_Normal, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - - InsertPerson("name_1", 11, trans); - - auto gql = "MATCH (person:Person {name: 'name_1'}) RETURN person;"; - auto result = store_->QueryGql(gql); - EXPECT_EQ(result.first, E_DATABASE_BUSY); - - auto errCode = trans->Commit(); - EXPECT_EQ(errCode, E_OK); - - MatchAndVerifyPerson("name_1", 11); -} - -/** - * @tc.name: GdbTransactionTest006_Commit_Abnormal - * @tc.desc: test Transaction::Commit - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest006_Commit_Abnormal, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - - auto errCode = trans->Commit(); - EXPECT_EQ(errCode, E_OK); - - errCode = trans->Commit(); - EXPECT_EQ(errCode, E_GRD_DB_INSTANCE_ABNORMAL); -} - -/** - * @tc.name: GdbTransactionTest007_Rollback_Normal - * @tc.desc: test Transaction::Rollback - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest007_Rollback_Normal, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - - InsertPerson("name_1", 11, trans); - - auto gql = "MATCH (person:Person {name: 'name_1'}) RETURN person;"; - auto result = store_->QueryGql(gql); - EXPECT_EQ(result.first, E_DATABASE_BUSY); - - auto errCode = trans->Rollback(); - EXPECT_EQ(errCode, E_OK); - - MatchAndVerifyPerson("name_1", 11, nullptr, false); -} - -/** - * @tc.name: GdbTransactionTest008_Rollback_Abnormal - * @tc.desc: test Transaction::Rollback - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest008_Rollback_Abnormal, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - - auto errCode = trans->Rollback(); - EXPECT_EQ(errCode, E_OK); - - errCode = trans->Rollback(); - EXPECT_EQ(errCode, E_GRD_DB_INSTANCE_ABNORMAL); -} - -/** - * @tc.name: GdbTransactionTest009_Isolation001 - * @tc.desc: test Transaction - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest009_Isolation001, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err1, trans1] = store_->CreateTransaction(); - EXPECT_EQ(err1, E_OK); - EXPECT_NE(trans1, nullptr); - - auto [err2, trans2] = store_->CreateTransaction(); - EXPECT_EQ(err2, E_OK); - EXPECT_NE(trans2, nullptr); - - InsertPerson("name_1", 11, trans1); - - auto gql = "MATCH (person:Person {name: 'name_1'}) RETURN person;"; - auto [errCode, result] = trans2->Query(gql); - EXPECT_EQ(errCode, E_DATABASE_BUSY); -} - -/** - * @tc.name: GdbTransactionTest010_Isolation002 - * @tc.desc: test Transaction - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest010_Isolation002, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err1, trans1] = store_->CreateTransaction(); - EXPECT_EQ(err1, E_OK); - EXPECT_NE(trans1, nullptr); - - auto [err2, trans2] = store_->CreateTransaction(); - EXPECT_EQ(err2, E_OK); - EXPECT_NE(trans2, nullptr); - - InsertPerson("name_1", 11, trans1); - - ASSERT_NE(trans1, nullptr); - auto errCode = trans1->Commit(); - EXPECT_EQ(errCode, E_OK); - - MatchAndVerifyPerson("name_1", 11, trans2); -} - -/** - * @tc.name: GdbTransactionTest011_Isolation003 - * @tc.desc: test Transaction - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest011_Isolation003, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err1, trans1] = store_->CreateTransaction(); - EXPECT_EQ(err1, E_OK); - EXPECT_NE(trans1, nullptr); - - auto [err2, trans2] = store_->CreateTransaction(); - EXPECT_EQ(err2, E_OK); - EXPECT_NE(trans2, nullptr); - - InsertPerson("name_1", 11, trans1); - - ASSERT_NE(trans1, nullptr); - auto errCode = trans1->Rollback(); - EXPECT_EQ(errCode, E_OK); - - MatchAndVerifyPerson("name_1", 11, trans2, false); -} - -/** - * @tc.name: GdbTransactionTest012_Isolation004 - * @tc.desc: test Transaction - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest012_Isolation004, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err1, trans1] = store_->CreateTransaction(); - EXPECT_EQ(err1, E_OK); - EXPECT_NE(trans1, nullptr); - - auto [err2, trans2] = store_->CreateTransaction(); - EXPECT_EQ(err2, E_OK); - EXPECT_NE(trans2, nullptr); - - InsertPerson("name_1", 11, trans1); - - ASSERT_NE(trans2, nullptr); - int32_t errCode = E_OK; - std::shared_ptr result = std::make_shared(); - std::tie(errCode, result) = trans2->Execute("INSERT (:Person {name: 'name_2', age: 22});"); - EXPECT_EQ(errCode, E_DATABASE_BUSY); - - errCode = trans1->Commit(); - EXPECT_EQ(errCode, E_OK); - - InsertPerson("name_2", 22, trans2); -} - -/** - * @tc.name: GdbTransactionTest013_Close - * @tc.desc: test Close - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest013_Close, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - EXPECT_NE(trans, nullptr); - - InsertPerson("name_1", 11, trans); - - ASSERT_NE(store_, nullptr); - int32_t errCode = store_->Close(); - EXPECT_EQ(errCode, E_OK); - store_ = nullptr; - - auto config = StoreConfig(databaseName, databasePath); - store_ = GDBHelper::GetDBStore(config, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store_, nullptr); - - MatchAndVerifyPerson("name_1", 11, nullptr, false); -} - -/** - * @tc.name: GdbTransactionTest014_StartTransByExecute - * @tc.desc: test Execute("START TRANSACTION;"), Execute("COMMIT") and Execute("ROLLBACK") - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest014_StartTransByExecute001, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err, result] = store_->ExecuteGql("START TRANSACTION;"); - EXPECT_EQ(err, E_INVALID_ARGS); - - std::tie(err, result) = store_->ExecuteGql("COMMIT;"); - EXPECT_EQ(err, E_INVALID_ARGS); - - std::tie(err, result) = store_->ExecuteGql("ROLLBACK;"); - EXPECT_EQ(err, E_INVALID_ARGS); -} - -/** - * @tc.name: GdbTransactionTest015_TransactionNestification - * @tc.desc: test Transaction Nestification - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest015_TransactionNestification, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - auto [err1, trans1] = store_->CreateTransaction(); - EXPECT_EQ(err1, E_OK); - EXPECT_NE(trans1, nullptr); - - auto result = trans1->Execute("START TRANSACTION;"); - EXPECT_EQ(result.first, E_INVALID_ARGS); -} - -/** - * @tc.name: GdbTransactionTest016_TransactionMultiThread - * @tc.desc: test Transaction MultiThread - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest016_TransactionMultiThread, TestSize.Level1) -{ - std::thread th[MAX_CNT]; - for (int32_t i = 0; i < MAX_CNT; i++) { - th[i] = std::thread([this, i] () { - ASSERT_NE(store_, nullptr); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - - InsertPerson("name_" + std::to_string(i), i, trans); - - err = trans->Commit(); - EXPECT_EQ(err, E_OK); - }); - } - - for (int32_t i = 0; i < MAX_CNT; i++) { - th[i].join(); - } - - for (int32_t i = 0; i < MAX_CNT; i++) { - MatchAndVerifyPerson("name_" + std::to_string(i), i); - } -} - -/** - * @tc.name: GdbTransactionTest017_TransactionMultiThread - * @tc.desc: test Transaction MultiThread write busy(Unable to obtain lock in 2 seconds) - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest017_TransactionMultiThread, TestSize.Level1) -{ - std::thread th[MAX_CNT]; - std::atomic_int insertCnt = 0; - std::atomic_int insertIndex = -1; - for (int32_t i = 0; i < MAX_CNT; i++) { - th[i] = std::thread([this, i, &insertCnt, &insertIndex] () { - ASSERT_NE(store_, nullptr); - - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - - std::shared_ptr result = std::make_shared(); - std::string age = std::to_string(i); - std::string name = "name_" + age; - std::string gql = "INSERT (:Person {name: '" + name + "', age: " + age + "});"; - std::tie(err, result) = trans->Execute(gql); - if (err == E_OK && insertCnt.load() == 0) { - insertCnt++; - insertIndex.store(i); - } else { - EXPECT_EQ(err, E_DATABASE_BUSY); - } - - std::this_thread::sleep_for(std::chrono::seconds(BUSY_TIMEOUT)); - - err = trans->Commit(); - EXPECT_EQ(err, E_OK); - }); - } - - for (int32_t i = 0; i < MAX_CNT; i++) { - th[i].join(); - } - - for (int32_t i = 0; i < MAX_CNT; i++) { - if (i == insertIndex.load()) { - MatchAndVerifyPerson("name_" + std::to_string(i), i); - } else { - MatchAndVerifyPerson("name_" + std::to_string(i), i, nullptr, false); - } - } - - EXPECT_EQ(insertCnt, 1); -} - -/** - * @tc.name: GdbTransactionTest018_TransactionMultiThread - * @tc.desc: test Transaction MultiThread Trasaction.write and Transaction.read - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest018_TransactionMultiThread, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - std::thread writeThread([this] () { - for (int i = 0; i < MAX_DATA_CNT; i++) { - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - InsertPerson("name_" + std::to_string(i), i, trans); - err = trans->Commit(); - EXPECT_EQ(err, E_OK); - std::this_thread::sleep_for(std::chrono::milliseconds(EXECUTE_INTERVAL)); - } - }); - - std::thread readThread([this] () { - std::this_thread::sleep_for(std::chrono::milliseconds(READ_INTERVAL)); - for (int i = 0; i < MAX_DATA_CNT; i++) { - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - MatchAndVerifyPerson("name_" + std::to_string(i), i, trans); - err = trans->Rollback(); - EXPECT_EQ(err, E_OK); - std::this_thread::sleep_for(std::chrono::milliseconds(EXECUTE_INTERVAL)); - } - }); - - writeThread.join(); - readThread.join(); -} - -/** - * @tc.name: GdbTransactionTest019_TransactionMultiThread - * @tc.desc: test Transaction MultiThread GraphStore.write and Transaction.read - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest019_TransactionMultiThread, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - std::thread writeThread([this] () { - for (int i = 0; i < MAX_DATA_CNT; i++) { - InsertPerson("name_" + std::to_string(i), i); - std::this_thread::sleep_for(std::chrono::milliseconds(EXECUTE_INTERVAL)); - } - }); - - std::thread readThread([this] () { - std::this_thread::sleep_for(std::chrono::milliseconds(READ_INTERVAL)); - for (int i = 0; i < MAX_DATA_CNT; i++) { - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - MatchAndVerifyPerson("name_" + std::to_string(i), i, trans); - err = trans->Rollback(); - EXPECT_EQ(err, E_OK); - std::this_thread::sleep_for(std::chrono::milliseconds(EXECUTE_INTERVAL)); - } - }); - - writeThread.join(); - readThread.join(); -} - -/** - * @tc.name: GdbTransactionTest020_TransactionMultiThread - * @tc.desc: test Transaction MultiThread Trasaction.write and GraphStore.read - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest020_TransactionMultiThread, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - std::thread writeThread([this] () { - for (int i = 0; i < MAX_DATA_CNT; i++) { - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - InsertPerson("name_" + std::to_string(i), i, trans); - err = trans->Commit(); - EXPECT_EQ(err, E_OK); - std::this_thread::sleep_for(std::chrono::milliseconds(EXECUTE_INTERVAL)); - } - }); - - std::thread readThread([this] () { - std::this_thread::sleep_for(std::chrono::milliseconds(READ_INTERVAL)); - for (int i = 0; i < MAX_DATA_CNT; i++) { - MatchAndVerifyPerson("name_" + std::to_string(i), i); - std::this_thread::sleep_for(std::chrono::milliseconds(EXECUTE_INTERVAL)); - } - }); - - writeThread.join(); - readThread.join(); -} - -/** - * @tc.name: GdbTransactionTest021_TransactionMultiThread - * @tc.desc: test Transaction MultiThread Trasaction.write and GraphStore.write - * @tc.type: FUNC - */ -HWTEST_F(GdbTransactionTest, GdbTransactionTest021_TransactionMultiThread, TestSize.Level1) -{ - ASSERT_NE(store_, nullptr); - - std::thread transWriteThread([this] () { - for (int i = 0; i < MAX_DATA_CNT; i++) { - auto [err, trans] = store_->CreateTransaction(); - EXPECT_EQ(err, E_OK); - ASSERT_NE(trans, nullptr); - InsertPerson("name_trans_" + std::to_string(i), i, trans); - err = trans->Commit(); - EXPECT_EQ(err, E_OK); - std::this_thread::sleep_for(std::chrono::milliseconds(EXECUTE_INTERVAL)); - } - }); - - std::thread writeThread([this] () { - for (int i = 0; i < MAX_DATA_CNT; i++) { - InsertPerson("name_" + std::to_string(i), i); - std::this_thread::sleep_for(std::chrono::milliseconds(EXECUTE_INTERVAL)); - } - }); - - transWriteThread.join(); - writeThread.join(); - - for (int i = 0; i < MAX_DATA_CNT; i++) { - MatchAndVerifyPerson("name_trans_" + std::to_string(i), i); - MatchAndVerifyPerson("name_" + std::to_string(i), i); - } -} diff --git a/relational_store/test/native/rdb/BUILD.gn b/relational_store/test/native/rdb/BUILD.gn index 5a785407..5b78a542 100644 --- a/relational_store/test/native/rdb/BUILD.gn +++ b/relational_store/test/native/rdb/BUILD.gn @@ -21,14 +21,13 @@ config("module_private_config") { include_dirs = [ "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb_crypt", "${relational_store_native_path}/rdb/include", "${relational_store_innerapi_path}/rdb/include", "${relational_store_native_path}/dfx/include", "${relational_store_native_path}/rdb/src", "${relational_store_innerapi_path}/appdatafwk/include", - "//commonlibrary/c_utils/base/include", - "${common_tool_path}/", - "${kvstore_interface_path}", + "${relational_store_base_path}/test/native/rdb/unittest", ] defines = [ "RELATIONAL_STORE" ] @@ -48,17 +47,18 @@ ohos_unittest("NativeRdbMultiThreadTest") { "ability_base:zuri", "ability_runtime:dataobs_manager", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", "huks:libhukssdk", "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddata_inner", "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", ] - deps = [ - "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", - "//third_party/sqlite:sqlite", - ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] } ohos_unittest("NativeRdbMultiProcessTest") { @@ -75,6 +75,7 @@ ohos_unittest("NativeRdbMultiProcessTest") { "${relational_store_native_path}/dfx/include", "${relational_store_native_path}/rdb/src", "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/test/native/rdb/unittest", ] defines = [ "RELATIONAL_STORE" ] @@ -87,7 +88,49 @@ ohos_unittest("NativeRdbMultiProcessTest") { "hilog:libhilog", "huks:libhukssdk", "ipc:ipc_core", + "kv_store:datamgr_common", "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] +} + +ohos_unittest("NativeRdbLogTest") { + module_out_path = module_output_path + + sources = [ + "unittest/common.cpp", + "unittest/rdb_error_log_test/get_rdb_store_test.cpp", + "unittest/rdb_error_log_test/rdb_error_log_test.cpp", + "unittest/rdb_error_log_test/rdb_perfStat_test.cpp", + ] + sources += [ + "../../../frameworks/native/rdb/src/suspender.cpp", + "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", + ] + include_dirs = [ + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_base_path}/test/native/rdb/unittest", + ] + + defines = [ "RELATIONAL_STORE" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "googletest:gtest", + "googletest:gtest_main", + "hilog:libhilog", + "huks:libhukssdk", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "kv_store:distributeddb_client", "sqlite:sqlite", ] @@ -110,6 +153,8 @@ ohos_unittest("NativeRdbTest") { "unittest/rd_utils_test.cpp", "unittest/rdb_attach_test.cpp", "unittest/rdb_bigint_test.cpp", + "unittest/rdb_callback_icu_test.cpp", + "unittest/rdb_concurrent_querywithcurd_test.cpp", "unittest/rdb_corrupt_test.cpp", "unittest/rdb_delete_test.cpp", "unittest/rdb_distributed_test.cpp", @@ -128,6 +173,7 @@ ohos_unittest("NativeRdbTest") { "unittest/rdb_rd_data_aging_test.cpp", "unittest/rdb_read_only_test.cpp", "unittest/rdb_security_manager_test.cpp", + "unittest/rdb_service_proxy_test.cpp", "unittest/rdb_sql_utils_test.cpp", "unittest/rdb_sqlite_shared_result_set_test.cpp", "unittest/rdb_step_result_get_row_test.cpp", @@ -149,38 +195,61 @@ ohos_unittest("NativeRdbTest") { "unittest/sqlite_utils_test.cpp", "unittest/transaction_test.cpp", "unittest/value_object_test.cpp", + "unittest/delay_notify_test.cpp", ] + if (is_ohos) { + sources += [ + "unittest/rdb_double_write_binlog_test.cpp", + ] + } + sources += [ - "../../../frameworks/native/rdb/mock/src/rdb_fault_hiview_reporter.cpp", - "../../../frameworks/native/rdb/src/base_transaction.cpp", - "../../../frameworks/native/rdb/src/connection.cpp", - "../../../frameworks/native/rdb/src/connection_pool.cpp", - "../../../frameworks/native/rdb/src/grd_api_manager.cpp", - "../../../frameworks/native/rdb/src/raw_data_parser.cpp", - "../../../frameworks/native/rdb/src/rd_connection.cpp", - "../../../frameworks/native/rdb/src/rd_statement.cpp", - "../../../frameworks/native/rdb/src/rd_utils.cpp", - "../../../frameworks/native/rdb/src/rdb_local_db_observer.cpp", - "../../../frameworks/native/rdb/src/rdb_manager_impl.cpp", - "../../../frameworks/native/rdb/src/rdb_notifier_stub.cpp", - "../../../frameworks/native/rdb/src/rdb_security_manager.cpp", - "../../../frameworks/native/rdb/src/rdb_service_proxy.cpp", - "../../../frameworks/native/rdb/src/rdb_sql_statistic.cpp", - "../../../frameworks/native/rdb/src/result_set_proxy.cpp", - "../../../frameworks/native/rdb/src/share_block.cpp", - "../../../frameworks/native/rdb/src/shared_block_serializer_info.cpp", - "../../../frameworks/native/rdb/src/sqlite_connection.cpp", - "../../../frameworks/native/rdb/src/sqlite_default_function.cpp", - "../../../frameworks/native/rdb/src/sqlite_global_config.cpp", - "../../../frameworks/native/rdb/src/sqlite_shared_result_set.cpp", - "../../../frameworks/native/rdb/src/sqlite_sql_builder.cpp", - "../../../frameworks/native/rdb/src/sqlite_statement.cpp", - "../../../frameworks/native/rdb/src/sqlite_utils.cpp", - "../../../frameworks/native/rdb/src/step_result_set.cpp", - "../../../frameworks/native/rdb/src/string_utils.cpp", - "../../../frameworks/native/rdb/src/task_executor.cpp", - "../../../frameworks/native/rdb/src/trans_db.cpp", + "${relational_store_native_path}/appdatafwk/src/serializable.cpp", + "${relational_store_native_path}/appdatafwk/src/general_endian.cpp", + "${relational_store_native_path}/appdatafwk/src/shared_block.cpp", + "${relational_store_native_path}/dfx/src/rdb_radar_reporter.cpp", + "${relational_store_native_path}/dfx/src/rdb_stat_reporter.cpp", + "${relational_store_native_path}/rdb/src/delay_notify.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_impl.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_fault_hiview_reporter.cpp", + "${relational_store_native_path}/rdb/src/base_transaction.cpp", + "${relational_store_native_path}/rdb/src/connection.cpp", + "${relational_store_native_path}/rdb/src/connection_pool.cpp", + "${relational_store_native_path}/rdb/src/grd_api_manager.cpp", + "${relational_store_native_path}/rdb/src/global_resource.cpp", + "${relational_store_native_path}/rdb/src/knowledge_schema_helper.cpp", + "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", + "${relational_store_native_path}/rdb/src/rd_connection.cpp", + "${relational_store_native_path}/rdb/src/rd_statement.cpp", + "${relational_store_native_path}/rdb/src/rd_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_icu_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_local_db_observer.cpp", + "${relational_store_native_path}/rdb/src/rdb_manager_impl.cpp", + "${relational_store_native_path}/rdb/src/rdb_notifier_stub.cpp", + "${relational_store_native_path}/rdb/src/rdb_obs_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_perfStat.cpp", + "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_service_proxy.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_log.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_statistic.cpp", + "${relational_store_native_path}/rdb/src/rdb_time_utils.cpp", + "${relational_store_native_path}/rdb/src/result_set_proxy.cpp", + "${relational_store_native_path}/rdb/src/security_policy.cpp", + "${relational_store_native_path}/rdb/src/share_block.cpp", + "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", + "${relational_store_native_path}/rdb/src/sqlite_connection.cpp", + "${relational_store_native_path}/rdb/src/sqlite_default_function.cpp", + "${relational_store_native_path}/rdb/src/sqlite_global_config.cpp", + "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/sqlite_sql_builder.cpp", + "${relational_store_native_path}/rdb/src/sqlite_statement.cpp", + "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", + "${relational_store_native_path}/rdb/src/step_result_set.cpp", + "${relational_store_native_path}/rdb/src/string_utils.cpp", + "${relational_store_native_path}/rdb/src/suspender.cpp", + "${relational_store_native_path}/rdb/src/task_executor.cpp", + "${relational_store_native_path}/rdb/src/trans_db.cpp", ] configs = [ ":module_private_config" ] @@ -188,20 +257,160 @@ ohos_unittest("NativeRdbTest") { external_deps = [ "ability_base:zuri", "ability_runtime:dataobs_manager", + "json:nlohmann_json_static", "c_utils:utils", + "file_api:securitylabel", + "googletest:gtest_main", "hilog:libhilog", - "huks:libhukssdk", + "hisysevent:libhisysevent", "ipc:ipc_core", + "kv_store:datamgr_common", "kv_store:distributeddata_inner", "kv_store:distributeddb", + "kv_store:distributeddb_client", "samgr:samgr_proxy", + "sqlite:sqlite", ] - deps = [ - "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", - "//third_party/sqlite:sqlite", + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] +} + +ohos_unittest("NativeRdbSecurityManagerTest") { + module_out_path = module_output_path + + cflags = [ + "-fno-access-control", # Ignore Private Member Access Control ] + + include_dirs = [ + "${relational_store_native_path}/obs_mgr_adapter", + "${relational_store_native_path}/icu/include", + ] + + sources = [ + "unittest/rdb_encrypt_upgrade_test.cpp", + ] + + sources += [ + "${relational_store_native_path}/appdatafwk/src/serializable.cpp", + "${relational_store_native_path}/appdatafwk/src/general_endian.cpp", + "${relational_store_native_path}/appdatafwk/src/shared_block.cpp", + "${relational_store_native_path}/dfx/src/rdb_radar_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_fault_hiview_reporter.cpp", + "${relational_store_native_path}/dfx/src/rdb_stat_reporter.cpp", + "${relational_store_native_path}/obs_mgr_adapter/obs_mgr_adapter.cpp", + "${relational_store_native_path}/rdb/src/abs_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_result_set.cpp", + "${relational_store_native_path}/rdb/src/abs_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/base_transaction.cpp", + "${relational_store_native_path}/rdb/src/big_integer.cpp", + "${relational_store_native_path}/rdb/src/cache_result_set.cpp", + "${relational_store_native_path}/rdb/src/connection.cpp", + "${relational_store_native_path}/rdb/src/connection_pool.cpp", + "${relational_store_native_path}/rdb/src/delay_notify.cpp", + "${relational_store_native_path}/rdb/src/grd_api_manager.cpp", + "${relational_store_native_path}/rdb/src/global_resource.cpp", + "${relational_store_native_path}/rdb/src/knowledge_schema_helper.cpp", + "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", + "${relational_store_native_path}/rdb/src/rd_connection.cpp", + "${relational_store_native_path}/rdb/src/rd_statement.cpp", + "${relational_store_native_path}/rdb/src/rd_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_icu_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_helper.cpp", + "${relational_store_native_path}/rdb/src/rdb_local_db_observer.cpp", + "${relational_store_native_path}/rdb/src/rdb_manager_impl.cpp", + "${relational_store_native_path}/rdb/src/rdb_notifier_stub.cpp", + "${relational_store_native_path}/rdb/src/rdb_obs_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_perfStat.cpp", + "${relational_store_native_path}/rdb/src/rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_service_proxy.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_log.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_statistic.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_store.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_impl.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_time_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_types_util.cpp", + "${relational_store_native_path}/rdb/src/result_set_proxy.cpp", + "${relational_store_native_path}/rdb/src/security_policy.cpp", + "${relational_store_native_path}/rdb/src/share_block.cpp", + "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", + "${relational_store_native_path}/rdb/src/sqlite_connection.cpp", + "${relational_store_native_path}/rdb/src/sqlite_default_function.cpp", + "${relational_store_native_path}/rdb/src/sqlite_global_config.cpp", + "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/sqlite_sql_builder.cpp", + "${relational_store_native_path}/rdb/src/sqlite_statement.cpp", + "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", + "${relational_store_native_path}/rdb/src/step_result_set.cpp", + "${relational_store_native_path}/rdb/src/string_utils.cpp", + "${relational_store_native_path}/rdb/src/suspender.cpp", + "${relational_store_native_path}/rdb/src/task_executor.cpp", + "${relational_store_native_path}/rdb/src/trans_db.cpp", + "${relational_store_native_path}/rdb/src/transaction.cpp", + "${relational_store_native_path}/rdb/src/transaction_impl.cpp", + "${relational_store_native_path}/rdb/src/value_object.cpp", + "${relational_store_native_path}/rdb/src/values_bucket.cpp", + "${relational_store_native_path}/rdb/src/values_buckets.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "json:nlohmann_json_static", + "c_utils:utils", + "file_api:securitylabel", + "googletest:gtest_main", + "hilog:libhilog", + "hisysevent:libhisysevent", + "huks:libhukssdk", + "ipc:ipc_core", + "kv_store:database_utils", + "kv_store:datamgr_common", + "kv_store:distributeddata_inner", + "kv_store:distributeddb_client", + "samgr:samgr_proxy", + "sqlite:sqlite", + ] +} + +ohos_unittest("DelayActuatorTest") { + module_out_path = module_output_path + + sources = [ + "unittest/delay_actuator_test.cpp", + ] + include_dirs = [ + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_base_path}/test/native/rdb/unittest", + ] + + defines = [ "RELATIONAL_STORE" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "googletest:gtest", + "googletest:gtest_main", + "hilog:libhilog", + "huks:libhukssdk", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] } ############################################################################### @@ -209,9 +418,12 @@ group("unittest") { testonly = true deps = [ + ":DelayActuatorTest", + ":NativeRdbLogTest", ":NativeRdbMultiProcessTest", ":NativeRdbMultiThreadTest", ":NativeRdbTest", + ":NativeRdbSecurityManagerTest", ] } @@ -221,10 +433,36 @@ group("fuzztest") { testonly = true deps = [] deps += [ + "fuzztest/rdbhelper_fuzzer:fuzztest", "fuzztest/rdbimpl_fuzzer:fuzztest", "fuzztest/rdbrdutils_fuzzer:fuzztest", "fuzztest/rdbstore_fuzzer:fuzztest", "fuzztest/rdstatement_fuzzer:fuzztest", + "fuzztest/returning_fuzzer:fuzztest", + "fuzztest/sharedblock_fuzzer:fuzztest", + "fuzztest/transdb_fuzzer:fuzztest", + "fuzztest/transaction_fuzzer:fuzztest", + "fuzztest/big_integer_test_ut2fuzz:fuzztest", + "fuzztest/cache_result_set_test_ut2fuzz:fuzztest", + "fuzztest/cloud_data_test_ut2fuzz:fuzztest", + "fuzztest/connection_test_ut2fuzz:fuzztest", + "fuzztest/rdb_attach_test_ut2fuzz:fuzztest", + "fuzztest/rdb_bigint_test_ut2fuzz:fuzztest", + "fuzztest/rdb_callback_icu_test_ut2fuzz:fuzztest", + "fuzztest/rdb_corrupt_test_ut2fuzz:fuzztest", + "fuzztest/rdb_delete_test_ut2fuzz:fuzztest", + "fuzztest/rdb_distributed_test_ut2fuzz:fuzztest", + "fuzztest/rdb_double_write_test_ut2fuzz:fuzztest", + "fuzztest/rdbsqlutils_fuzzer:fuzztest", + "fuzztest/storeconfig_fuzzer:fuzztest", + "fuzztest/absrdbpredicates_fuzzer:fuzztest", + "fuzztest/abssharedresultset_fuzzer:fuzztest", + "fuzztest/abspredicates_fuzzer:fuzztest", + "fuzztest/absresultset_fuzzer:fuzztest", + "fuzztest/rdbpredicates_fuzzer:fuzztest", + "fuzztest/valueobject_fuzzer:fuzztest", + "fuzztest/valuesbucket_fuzzer:fuzztest", + "fuzztest/valuesbuckets_fuzzer:fuzztest", ] } diff --git a/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/BUILD.gn b/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/BUILD.gn index 39778e1a..307ff2d6 100644 --- a/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/BUILD.gn +++ b/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/BUILD.gn @@ -20,20 +20,12 @@ config("module_private_config") { visibility = [ ":*" ] include_dirs = [ + "${relational_store_common_path}/include", "${relational_store_native_path}/rdb/include", "${relational_store_innerapi_path}/rdb/include", "${relational_store_native_path}/rdb/src", "${relational_store_innerapi_path}/appdatafwk/include", - "//commonlibrary/c_utils/base/include", - "${common_tool_path}/", ] - - if (relational_store_rdb_support_icu) { - include_dirs += [ - "//third_party/icu/icu4c/source/i18n", - "//third_party/icu/icu4c/source/common", - ] - } } ohos_distributedtest("DistributedTest") { @@ -48,18 +40,23 @@ ohos_distributedtest("DistributedTest") { "ability_runtime:dataobs_manager", "c_utils:utils", "device_manager:devicemanagersdk", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:datamgr_common", "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", ] - deps = [ - "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", - "//third_party/icu/icu4c:shared_icui18n", - "//third_party/icu/icu4c:shared_icuuc", - "//third_party/sqlite:sqlite", - ] + if (relational_store_rdb_support_icu) { + external_deps += [ + "icu:shared_icui18n", + "icu:shared_icuuc", + ] + } + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] } ohos_distributedtest("DistributedTestAgent") { @@ -72,18 +69,23 @@ ohos_distributedtest("DistributedTestAgent") { "ability_runtime:dataobs_manager", "c_utils:utils", "device_manager:devicemanagersdk", + "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", + "kv_store:datamgr_common", "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", ] - deps = [ - "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", - "//third_party/icu/icu4c:shared_icui18n", - "//third_party/icu/icu4c:shared_icuuc", - "//third_party/sqlite:sqlite", - ] + if (relational_store_rdb_support_icu) { + external_deps += [ + "icu:shared_icui18n", + "icu:shared_icuuc", + ] + } + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] } ############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/BUILD.gn new file mode 100644 index 00000000..13ca9421 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("abspredicates_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/abspredicates_fuzzer" + + sources = [ "abspredicates_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":abspredicates_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/abspredicates_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/abspredicates_fuzzer.cpp new file mode 100644 index 00000000..50a95e4c --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/abspredicates_fuzzer.cpp @@ -0,0 +1,322 @@ +/* + * 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 "abspredicates_fuzzer.h" + +#include + +#include +#include + +#include "abs_shared_result_set.h" +#include "ashmem.h" +#include "rd_statement.h" +#include "rdb_errno.h" +#include "rdb_store_config.h" +#include "rdb_store_impl.h" +#include "rdb_types.h" +#include "refbase.h" +#include "shared_block.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +// Define constants +#define MAX_STRING_LENGTH 50 +#define MAX_VECTOR_SIZE 10 + +namespace OHOS { + +std::vector ConsumeRandomLengthValueObjectVector(FuzzedDataProvider &provider) +{ + const int loopsMin = 0; + const int loopsMax = 100; + size_t loops = provider.ConsumeIntegralInRange(loopsMin, loopsMax); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t value = provider.ConsumeIntegral(); + ValueObject obj(value); + columns.emplace_back(obj); + } + return columns; +} + +std::vector ConsumeRandomLengthStringVector(FuzzedDataProvider &provider) +{ + const int loopsMin = 0; + const int loopsMax = 100; + size_t loops = provider.ConsumeIntegralInRange(loopsMin, loopsMax); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t length = provider.ConsumeIntegral(); + auto bytes = provider.ConsumeBytes(length); + columns.emplace_back(bytes.begin(), bytes.end()); + } + return columns; +} + +void TestSetWhereClause(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string whereClause = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.SetWhereClause(whereClause); +} + +void TestSetBindArgs(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::vector valueObjects = ConsumeRandomLengthValueObjectVector(provider); + predicates.SetBindArgs(valueObjects); +} + +void TestSetOrder(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string order = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.SetOrder(order); +} + +void TestLimit(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + int limit = provider.ConsumeIntegral(); + predicates.Limit(limit); +} + +void TestLimitWithOffset(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + int offset = provider.ConsumeIntegral(); + int limit = provider.ConsumeIntegral(); + predicates.Limit(offset, limit); +} + +void TestOffset(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + int offset = provider.ConsumeIntegral(); + predicates.Offset(offset); +} + +void TestGroupBy(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::vector fields = ConsumeRandomLengthStringVector(provider); + predicates.GroupBy(fields); +} + +void TestIndexedBy(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string indexName = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.IndexedBy(indexName); +} + +void TestHaving(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string conditions = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::vector valueObjects = ConsumeRandomLengthValueObjectVector(provider); + predicates.Having(conditions, valueObjects); +} + +void TestIn(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::vector valueObjects = ConsumeRandomLengthValueObjectVector(provider); + predicates.In(field, valueObjects); +} + +void TestNotIn(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::vector valueObjects = ConsumeRandomLengthValueObjectVector(provider); + predicates.NotIn(field, valueObjects); +} + +void TestBetween(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + int32_t value1 = provider.ConsumeIntegral(); + ValueObject obj1(value1); + int32_t value2 = provider.ConsumeIntegral(); + ValueObject obj2(value2); + predicates.Between(field, obj1, obj2); +} + +void TestNotBetween(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + int32_t value1 = provider.ConsumeIntegral(); + ValueObject obj1(value1); + int32_t value2 = provider.ConsumeIntegral(); + ValueObject obj2(value2); + predicates.NotBetween(field, obj1, obj2); +} + +void TestGreaterThan(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + ValueObject valueObject = provider.ConsumeIntegral(); + predicates.GreaterThan(field, valueObject); +} + +void TestLessThan(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + ValueObject valueObject = provider.ConsumeIntegral(); + predicates.LessThan(field, valueObject); +} + +void TestGreaterThanOrEqualTo(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + ValueObject valueObject = provider.ConsumeIntegral(); + predicates.GreaterThanOrEqualTo(field, valueObject); +} + +void TestLessThanOrEqualTo(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + ValueObject valueObject = provider.ConsumeIntegral(); + predicates.LessThanOrEqualTo(field, valueObject); +} + +void TestOrderByAsc(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.OrderByAsc(field); +} + +void TestOrderByDesc(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.OrderByDesc(field); +} + +void TestEqualTo(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + ValueObject valueObject = provider.ConsumeIntegral(); + predicates.EqualTo(field, valueObject); +} + +void TestNotEqualTo(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + ValueObject valueObject = provider.ConsumeIntegral(); + predicates.NotEqualTo(field, valueObject); +} + +void TestContains(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.Contains(field, value); +} + +void TestNotContains(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.NotContains(field, value); +} + +void TestBeginsWith(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.BeginsWith(field, value); +} + +void TestEndsWith(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.EndsWith(field, value); +} + +void TestIsNull(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.IsNull(field); +} + +void TestIsNotNull(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.IsNotNull(field); +} + +void TestLike(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.Like(field, value); +} + +void TestNotLike(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.NotLike(field, value); +} + +void TestGlob(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.Glob(field, value); +} + +void TestNotGlob(FuzzedDataProvider &provider, AbsPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + predicates.NotGlob(field, value); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::NativeRdb::AbsPredicates predicates; + + // Call test functions + OHOS::TestSetWhereClause(provider, predicates); + OHOS::TestSetBindArgs(provider, predicates); + OHOS::TestSetOrder(provider, predicates); + OHOS::TestLimit(provider, predicates); + OHOS::TestLimitWithOffset(provider, predicates); + OHOS::TestOffset(provider, predicates); + OHOS::TestGroupBy(provider, predicates); + OHOS::TestIndexedBy(provider, predicates); + OHOS::TestHaving(provider, predicates); + OHOS::TestIn(provider, predicates); + OHOS::TestNotIn(provider, predicates); + OHOS::TestBetween(provider, predicates); + OHOS::TestNotBetween(provider, predicates); + OHOS::TestGreaterThan(provider, predicates); + OHOS::TestLessThan(provider, predicates); + OHOS::TestGreaterThanOrEqualTo(provider, predicates); + OHOS::TestLessThanOrEqualTo(provider, predicates); + OHOS::TestOrderByAsc(provider, predicates); + OHOS::TestOrderByDesc(provider, predicates); + OHOS::TestEqualTo(provider, predicates); + OHOS::TestNotEqualTo(provider, predicates); + OHOS::TestContains(provider, predicates); + OHOS::TestNotContains(provider, predicates); + OHOS::TestBeginsWith(provider, predicates); + OHOS::TestEndsWith(provider, predicates); + OHOS::TestIsNull(provider, predicates); + OHOS::TestIsNotNull(provider, predicates); + OHOS::TestLike(provider, predicates); + OHOS::TestNotLike(provider, predicates); + OHOS::TestGlob(provider, predicates); + OHOS::TestNotGlob(provider, predicates); + + return 0; +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/abspredicates_fuzzer.h b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/abspredicates_fuzzer.h new file mode 100644 index 00000000..6f52f567 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/abspredicates_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 ABSPREDICATES_FUZZER_H +#define ABSPREDICATES_FUZZER_H + +#define FUZZ_PROJECT_NAME "abspredicates_fuzzer" + +#endif // ABSPREDICATES_FUZZER_H diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/corpus/init similarity index 92% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/corpus/init rename to relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/corpus/init index bc977bd9..65af8ee8 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/corpus/init +++ b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/corpus/init @@ -1,4 +1,4 @@ -# Copyright (c) 2022 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 diff --git a/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/abspredicates_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/BUILD.gn new file mode 100644 index 00000000..7dece9a5 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("absrdbpredicates_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/absrdbpredicates_fuzzer" + + sources = [ "absrdbpredicates_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":absrdbpredicates_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/absrdbpredicates_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/absrdbpredicates_fuzzer.cpp new file mode 100644 index 00000000..989633b1 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/absrdbpredicates_fuzzer.cpp @@ -0,0 +1,232 @@ +/* + * 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 "abs_rdb_predicates.h" +#include "rdb_types.h" + + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +static const int FOR_LOOP_MIN = 0; +static const int FOR_LOOP_MAX = 10; +static const int RANDOM_STRING_LENGTH = 30; + +namespace OHOS { +void FuzzInDevices(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::vector devices; + size_t numDevices = provider.ConsumeIntegralInRange(FOR_LOOP_MIN, FOR_LOOP_MAX); + for (size_t i = 0; i < numDevices; ++i) { + devices.push_back(provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH)); + } + predicates.InDevices(devices); +} + +void FuzzEqualTo(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + ValueObject value(provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH)); + predicates.EqualTo(field, value); +} + +void FuzzNotEqualTo(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + ValueObject value(provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH)); + predicates.NotEqualTo(field, value); +} + +void FuzzInStringVector(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::vector values; + size_t numValues = provider.ConsumeIntegralInRange(FOR_LOOP_MIN, FOR_LOOP_MAX); + for (size_t i = 0; i < numValues; ++i) { + values.push_back(provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH)); + } + predicates.In(field, values); +} + +void FuzzInValueObjectVector(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::vector values; + size_t numValues = provider.ConsumeIntegralInRange(FOR_LOOP_MIN, FOR_LOOP_MAX); + for (size_t i = 0; i < numValues; ++i) { + ValueObject value(provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH)); + values.push_back(value); + } + predicates.In(field, values); +} + +void FuzzContains(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.Contains(field, value); +} + +void FuzzNotContains(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.NotContains(field, value); +} + +void FuzzBeginsWith(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.BeginsWith(field, value); +} + +void FuzzEndsWith(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.EndsWith(field, value); +} + +void FuzzLike(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.Like(field, value); +} + +void FuzzNotLike(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.NotLike(field, value); +} + +void FuzzGlob(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.Glob(field, value); +} + +void FuzzNotGlob(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::string value = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.NotGlob(field, value); +} + +void FuzzNotInStringVector(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::vector values; + size_t numValues = provider.ConsumeIntegralInRange(FOR_LOOP_MIN, FOR_LOOP_MAX); + for (size_t i = 0; i < numValues; ++i) { + values.push_back(provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH)); + } + predicates.NotIn(field, values); +} + +void FuzzNotInValueObjectVector(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + std::vector values; + size_t numValues = provider.ConsumeIntegralInRange(FOR_LOOP_MIN, FOR_LOOP_MAX); + for (size_t i = 0; i < numValues; ++i) { + ValueObject value(provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH)); + values.push_back(value); + } + predicates.NotIn(field, values); +} + +void FuzzOrderByAsc(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.OrderByAsc(field); +} + +void FuzzOrderByDesc(FuzzedDataProvider &provider, AbsRdbPredicates &predicates) +{ + std::string field = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + predicates.OrderByDesc(field); +} + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + + // Create an instance of AbsRdbPredicates + std::string tableName = provider.ConsumeRandomLengthString(RANDOM_STRING_LENGTH); + AbsRdbPredicates predicates(tableName); + + // Fuzzing for InDevices + OHOS::FuzzInDevices(provider, predicates); + + // Fuzzing for EqualTo + OHOS::FuzzEqualTo(provider, predicates); + + // Fuzzing for NotEqualTo + OHOS::FuzzNotEqualTo(provider, predicates); + + // Fuzzing for In (string vector) + OHOS::FuzzInStringVector(provider, predicates); + + // Fuzzing for In (ValueObject vector) + OHOS::FuzzInValueObjectVector(provider, predicates); + + // Fuzzing for Contains + OHOS::FuzzContains(provider, predicates); + + // Fuzzing for NotContains + OHOS::FuzzNotContains(provider, predicates); + + // Fuzzing for BeginsWith + OHOS::FuzzBeginsWith(provider, predicates); + + // Fuzzing for EndsWith + OHOS::FuzzEndsWith(provider, predicates); + + // Fuzzing for Like + OHOS::FuzzLike(provider, predicates); + + // Fuzzing for NotLike + OHOS::FuzzNotLike(provider, predicates); + + // Fuzzing for Glob + OHOS::FuzzGlob(provider, predicates); + + // Fuzzing for NotGlob + OHOS::FuzzNotGlob(provider, predicates); + + // Fuzzing for NotIn (string vector) + OHOS::FuzzNotInStringVector(provider, predicates); + + // Fuzzing for NotIn (ValueObject vector) + OHOS::FuzzNotInValueObjectVector(provider, predicates); + + // Fuzzing for OrderByAsc + OHOS::FuzzOrderByAsc(provider, predicates); + + // Fuzzing for OrderByDesc + OHOS::FuzzOrderByDesc(provider, predicates); + + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/absrdbpredicates_fuzzer.h b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/absrdbpredicates_fuzzer.h new file mode 100644 index 00000000..51c074ec --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/absrdbpredicates_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 ABSRDBPREDICATES_FUZZER_H +#define ABSRDBPREDICATES_FUZZER_H + +#define FUZZ_PROJECT_NAME "absrdbpredicates_fuzzer" + +#endif // ABSRDBPREDICATES_FUZZER_H diff --git a/kv_store/test/fuzztest/jsonservice_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/corpus/init similarity index 92% rename from kv_store/test/fuzztest/jsonservice_fuzzer/corpus/init rename to relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/corpus/init index e7c3fecd..65af8ee8 100644 --- a/kv_store/test/fuzztest/jsonservice_fuzzer/corpus/init +++ b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/corpus/init @@ -1,4 +1,4 @@ -# Copyright (c) 2024 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 diff --git a/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/absrdbpredicates_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/BUILD.gn new file mode 100644 index 00000000..b3101f01 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("absresultset_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/absresultset_fuzzer" + + sources = [ "absresultset_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":absresultset_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/absresultset_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/absresultset_fuzzer.cpp new file mode 100644 index 00000000..d3d48248 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/absresultset_fuzzer.cpp @@ -0,0 +1,293 @@ +/* + * 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 "absresultset_fuzzer.h" + +#include + +#include +#include +#include +#include "abs_result_set.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + +// Define constants +#define MAX_STRING_LENGTH 50 +#define MAX_VECTOR_SIZE 10 + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +namespace OHOS { + +static const std::string RDB_PATH = "/data/test/absresultsetFuzzerTest.db"; +static const std::string CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, " + "blobType BLOB)"; + +class AbsresultsetFuzzerTestCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +int AbsresultsetFuzzerTestCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_TEST); +} + +int AbsresultsetFuzzerTestCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +std::vector ConsumeRandomLengthValueObjectVector(FuzzedDataProvider &provider) +{ + const int loopsMin = 0; + const int loopsMax = 100; + size_t loops = provider.ConsumeIntegralInRange(loopsMin, loopsMax); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t value = provider.ConsumeIntegral(); + ValueObject obj(value); + columns.emplace_back(obj); + } + return columns; +} + +std::vector ConsumeRandomLengthStringVector(FuzzedDataProvider &provider) +{ + const int loopsMin = 0; + const int loopsMax = 100; + size_t loops = provider.ConsumeIntegralInRange(loopsMin, loopsMax); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t length = provider.ConsumeIntegral(); + auto bytes = provider.ConsumeBytes(length); + columns.emplace_back(bytes.begin(), bytes.end()); + } + return columns; +} + +void TestGetBlob(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + std::vector blob; + resultSet->GetBlob(columnIndex, blob); +} + +void TestGetString(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + std::string value; + resultSet->GetString(columnIndex, value); +} + +void TestGetInt(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + int value; + resultSet->GetInt(columnIndex, value); +} + +void TestGetLong(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + int64_t value; + resultSet->GetLong(columnIndex, value); +} + +void TestGetDouble(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + double value; + resultSet->GetDouble(columnIndex, value); +} + +void TestGetAsset(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int32_t columnIndex = provider.ConsumeIntegral(); + ValueObject::Asset value; + resultSet->GetAsset(columnIndex, value); +} + +void TestGetAssets(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int32_t columnIndex = provider.ConsumeIntegral(); + ValueObject::Assets value; + resultSet->GetAssets(columnIndex, value); +} + +void TestGetFloat32Array(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int32_t columnIndex = provider.ConsumeIntegral(); + ValueObject::FloatVector value; + resultSet->GetFloat32Array(columnIndex, value); +} + +void TestIsColumnNull(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + bool isNull; + resultSet->IsColumnNull(columnIndex, isNull); +} + +void TestGetRow(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + RowEntity rowEntity; + resultSet->GetRow(rowEntity); +} + +void TestGoToRow(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int position = provider.ConsumeIntegral(); + resultSet->GoToRow(position); +} + +void TestGetColumnType(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + ColumnType columnType; + resultSet->GetColumnType(columnIndex, columnType); +} + +void TestGetRowIndex(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int position; + resultSet->GetRowIndex(position); +} + +void TestGoTo(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int offset = provider.ConsumeIntegral(); + resultSet->GoTo(offset); +} + +void TestGoToFirstRow(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + resultSet->GoToFirstRow(); +} + +void TestGoToLastRow(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + resultSet->GoToLastRow(); +} + +void TestGoToNextRow(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + resultSet->GoToNextRow(); +} + +void TestGoToPreviousRow(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + resultSet->GoToPreviousRow(); +} + +void TestIsAtFirstRow(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + bool result; + resultSet->IsAtFirstRow(result); +} + +void TestIsAtLastRow(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + bool result; + resultSet->IsAtLastRow(result); +} + +void TestIsStarted(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + bool result; + resultSet->IsStarted(result); +} + +void TestIsEnded(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + bool result; + resultSet->IsEnded(result); +} + +void TestGetColumnCount(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int count; + resultSet->GetColumnCount(count); +} + +void TestGetColumnIndex(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + std::string columnName = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + int columnIndex; + resultSet->GetColumnIndex(columnName, columnIndex); +} + +void TestGetColumnName(FuzzedDataProvider &provider, std::shared_ptr &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + std::string columnName; + resultSet->GetColumnName(columnIndex, columnName); +} + +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + RdbHelper::DeleteRdbStore(RDB_PATH); + RdbStoreConfig config(RDB_PATH); + config.SetHaMode(HAMode::MAIN_REPLICA); + config.SetReadOnly(false); + AbsresultsetFuzzerTestCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + if (store == nullptr || errCode != E_OK) { + return 0; + } + std::vector selectionArgs; + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test", selectionArgs); + if (resultSet == nullptr) { + return 0; + } + + // Call test functions + OHOS::TestGetBlob(provider, resultSet); + OHOS::TestGetString(provider, resultSet); + OHOS::TestGetInt(provider, resultSet); + OHOS::TestGetLong(provider, resultSet); + OHOS::TestGetDouble(provider, resultSet); + OHOS::TestGetAsset(provider, resultSet); + OHOS::TestGetAssets(provider, resultSet); + OHOS::TestGetFloat32Array(provider, resultSet); + OHOS::TestIsColumnNull(provider, resultSet); + OHOS::TestGetRow(provider, resultSet); + OHOS::TestGoToRow(provider, resultSet); + OHOS::TestGetColumnType(provider, resultSet); + OHOS::TestGetRowIndex(provider, resultSet); + OHOS::TestGoTo(provider, resultSet); + OHOS::TestGoToFirstRow(provider, resultSet); + OHOS::TestGoToLastRow(provider, resultSet); + OHOS::TestGoToNextRow(provider, resultSet); + OHOS::TestGoToPreviousRow(provider, resultSet); + OHOS::TestIsAtFirstRow(provider, resultSet); + OHOS::TestIsAtLastRow(provider, resultSet); + OHOS::TestIsStarted(provider, resultSet); + OHOS::TestIsEnded(provider, resultSet); + OHOS::TestGetColumnCount(provider, resultSet); + OHOS::TestGetColumnIndex(provider, resultSet); + OHOS::TestGetColumnName(provider, resultSet); + return 0; +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/absresultset_fuzzer.h b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/absresultset_fuzzer.h new file mode 100644 index 00000000..36cea0ee --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/absresultset_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 ABSRESULTSET_FUZZER_H +#define ABSRESULTSET_FUZZER_H + +#define FUZZ_PROJECT_NAME "absresultset_fuzzer" + +#endif // ABSRESULTSET_FUZZER_H diff --git a/kv_store/test/fuzztest/kvsync_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/corpus/init similarity index 92% rename from kv_store/test/fuzztest/kvsync_fuzzer/corpus/init rename to relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/corpus/init index e4ceac1b..65af8ee8 100644 --- a/kv_store/test/fuzztest/kvsync_fuzzer/corpus/init +++ b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/corpus/init @@ -1,4 +1,4 @@ -# Copyright (c) 2023 Huawei Device Co., Ltd. +# Copyright (c) 2025 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/absresultset_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/BUILD.gn new file mode 100644 index 00000000..1ee817ae --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/BUILD.gn @@ -0,0 +1,67 @@ +# 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("abssharedresultset_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/abssharedresultset_fuzzer" + + sources = [ "abssharedresultset_fuzzer.cpp" ] + + deps = [ + "${relational_store_innerapi_path}/rdb:native_rdb", + "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":abssharedresultset_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/abssharedresultset_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/abssharedresultset_fuzzer.cpp new file mode 100644 index 00000000..fd89cf56 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/abssharedresultset_fuzzer.cpp @@ -0,0 +1,156 @@ +/* + * 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 "abssharedresultset_fuzzer.h" + +#include + +#include +#include + +#include "abs_shared_result_set.h" +#include "rdb_types.h" +#include "ashmem.h" +#include "rd_statement.h" +#include "rdb_errno.h" +#include "rdb_store_config.h" +#include "rdb_store_impl.h" +#include "refbase.h" +#include "shared_block.h" + + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +static const size_t DEFAULT_BLOCK_SIZE = 1 * 1024 * 1024; + +namespace OHOS { +void FuzzGetString(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + std::string value; + resultSet.GetString(columnIndex, value); +} + +void FuzzGet(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + int32_t columnIndex = provider.ConsumeIntegral(); + ValueObject value; + resultSet.Get(columnIndex, value); +} + +void FuzzGetSize(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + size_t size; + resultSet.GetSize(columnIndex, size); +} + +void FuzzGetColumnType(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + int columnIndex = provider.ConsumeIntegral(); + ColumnType columnType; + resultSet.GetColumnType(columnIndex, columnType); +} + +void FuzzGoToRow(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + int position = provider.ConsumeIntegral(); + resultSet.GoToRow(position); +} + +void FuzzGetRowCount(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + int count; + resultSet.GetRowCount(count); +} + +void FuzzGetBlock(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + resultSet.GetBlock(); +} + +void FuzzOnGo(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + int oldRowIndex = provider.ConsumeIntegral(); + int newRowIndex = provider.ConsumeIntegral(); + resultSet.OnGo(oldRowIndex, newRowIndex); +} + +void FuzzSetBlock(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + AppDataFwk::SharedBlock *block = nullptr; + std::string sharedBlockName = "SharedBlockFuzzTestBlock"; + auto errcode = AppDataFwk::SharedBlock::Create(sharedBlockName, DEFAULT_BLOCK_SIZE, block); + if (errcode != AppDataFwk::SharedBlock::SHARED_BLOCK_OK) { + return; + } + resultSet.SetBlock(block); +} + +void FuzzClose(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + resultSet.Close(); +} + +void FuzzHasBlock(FuzzedDataProvider &provider, AbsSharedResultSet &resultSet) +{ + resultSet.HasBlock(); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + + // Create an instance of AbsSharedResultSet + const int randomStringLength = 30; + std::string tableName = provider.ConsumeRandomLengthString(randomStringLength); + AbsSharedResultSet resultSet(tableName); + + // Fuzzing for GetString + OHOS::FuzzGetString(provider, resultSet); + + // Fuzzing for Get + OHOS::FuzzGet(provider, resultSet); + + // Fuzzing for GetSize + OHOS::FuzzGetSize(provider, resultSet); + + // Fuzzing for GetColumnType + OHOS::FuzzGetColumnType(provider, resultSet); + + // Fuzzing for GoToRow + OHOS::FuzzGoToRow(provider, resultSet); + + // Fuzzing for GetRowCount + OHOS::FuzzGetRowCount(provider, resultSet); + + // Fuzzing for GetBlock + OHOS::FuzzGetBlock(provider, resultSet); + + // Fuzzing for OnGo + OHOS::FuzzOnGo(provider, resultSet); + + // Fuzzing for SetBlock + OHOS::FuzzSetBlock(provider, resultSet); + + // Fuzzing for Close + OHOS::FuzzClose(provider, resultSet); + + // Fuzzing for HasBlock + OHOS::FuzzHasBlock(provider, resultSet); + + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/abssharedresultset_fuzzer.h b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/abssharedresultset_fuzzer.h new file mode 100644 index 00000000..1d434c88 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/abssharedresultset_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 ABSSHAREDRESULTSET_FUZZER_H +#define ABSSHAREDRESULTSET_FUZZER_H + +#define FUZZ_PROJECT_NAME "abssharedresultset_fuzzer" + +#endif // ABSSHAREDRESULTSET_FUZZER_H diff --git a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/corpus/init similarity index 92% rename from relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/corpus/init rename to relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/corpus/init index e7c3fecd..65af8ee8 100644 --- a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/corpus/init +++ b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/corpus/init @@ -1,4 +1,4 @@ -# Copyright (c) 2024 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 diff --git a/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/abssharedresultset_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/BUILD.gn b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/BUILD.gn new file mode 100644 index 00000000..3520d866 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("big_integer_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/big_integer_test_ut2fuzz" + + sources = [ "big_integer_test_ut2fuzz.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":big_integer_test_ut2fuzz", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/big_integer_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/big_integer_test_ut2fuzz.cpp new file mode 100644 index 00000000..3f0bb82e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/big_integer_test_ut2fuzz.cpp @@ -0,0 +1,76 @@ +/* + * 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 "big_integer_test_ut2fuzz.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "big_integer.h" +#include "connection_pool.h" +#include "trans_db.h" + + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +void BigIntegerFuzzTest(FuzzedDataProvider &fdp) +{ + // Test primary constructor with int64_t + auto bi1 = OHOS::NativeRdb::BigInteger(fdp.ConsumeIntegral()); + + // Test (sign, vector) constructor + std::vector vec; + while (fdp.remaining_bytes() >= sizeof(uint64_t)) { + vec.push_back(fdp.ConsumeIntegral()); + } + auto bi2 = OHOS::NativeRdb::BigInteger( + fdp.ConsumeIntegralInRange(-1, 1), + std::move(vec) + ); + + // Validate copy semantics + auto bi3 = OHOS::NativeRdb::BigInteger(bi1); + bi3 = bi2; // Test assignment operator + + // Stress test move semantics + auto bi4 = OHOS::NativeRdb::BigInteger(std::move(bi2)); + bi1 = std::move(bi3); + + // Verify core operations + (void)(bi1 == bi4); // Compare equality + (void)(bi1 < bi4); // Compare ordering + + // Exercise all public methods + (void)bi1.Sign(); // Validate sign retrieval + (void)bi1.Size(); // Check array size + (void)bi1.TrueForm(); // Access raw data + (void)bi1.Value(); // Test value copy +} + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::BigIntegerFuzzTest(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/big_integer_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/big_integer_test_ut2fuzz.h new file mode 100644 index 00000000..c424c456 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/big_integer_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * 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 BIG_INTEGER_TEST_UT2FUZZ_H +#define BIG_INTEGER_TEST_UT2FUZZ_H + +#define FUZZ_PROJECT_NAME "big_integer_test_ut2fuzz" + +#endif // BIG_INTEGER_TEST_UT2FUZZ_H diff --git a/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/corpus/init new file mode 100644 index 00000000..2aea1356 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/big_integer_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/BUILD.gn b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/BUILD.gn new file mode 100644 index 00000000..82236975 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("cache_result_set_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz" + + sources = [ "cache_result_set_test_ut2fuzz.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":cache_result_set_test_ut2fuzz", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/cache_result_set_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/cache_result_set_test_ut2fuzz.cpp new file mode 100644 index 00000000..47f8792d --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/cache_result_set_test_ut2fuzz.cpp @@ -0,0 +1,393 @@ +/* + * 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 "cache_result_set_test_ut2fuzz.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "big_integer.h" +#include "cache_result_set.h" +#include "connection_pool.h" +#include "rdb_errno.h" +#include "trans_db.h" +#include "value_object.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +void CreateValuesBuckets(FuzzedDataProvider &fdp, std::vector &valuesBuckets) +{ + ValuesBucket valuesBucket; + { + std::string columnName = fdp.ConsumeRandomLengthString(); + std::string columnValue = fdp.ConsumeRandomLengthString(); + valuesBucket.PutString(columnName, columnValue); + } + { + std::string columnName = fdp.ConsumeRandomLengthString(); + valuesBucket.PutInt(columnName, fdp.ConsumeIntegral()); + } + { + std::string columnName = fdp.ConsumeRandomLengthString(); + valuesBucket.PutLong(columnName, fdp.ConsumeIntegral()); + } + { + std::string columnName = fdp.ConsumeRandomLengthString(); + double value = fdp.ConsumeFloatingPoint(); + valuesBucket.PutDouble(columnName, value); + } + { + uint32_t status = fdp.ConsumeIntegralInRange( + AssetValue::Status::STATUS_UNKNOWN, AssetValue::Status::STATUS_BUTT); + AssetValue asset{ + .version = fdp.ConsumeIntegral(), + .status = status, + .expiresTime = fdp.ConsumeIntegral(), + .id = fdp.ConsumeRandomLengthString(), + .name = fdp.ConsumeRandomLengthString(), + .uri = fdp.ConsumeRandomLengthString(), + .createTime = fdp.ConsumeRandomLengthString(), + .modifyTime = fdp.ConsumeRandomLengthString(), + .size = fdp.ConsumeRandomLengthString(), + .hash = fdp.ConsumeRandomLengthString(), + .path = fdp.ConsumeRandomLengthString(), + }; + ValueObject valueObject = ValueObject(asset); + ValueObject::Asset value = ValueObject::Asset(valueObject); + std::string columnName = fdp.ConsumeRandomLengthString(); + valuesBucket.Put(columnName, value); + } + valuesBuckets.push_back(std::move(valuesBucket)); +} + +void CacheResultSetTestGetRowCountTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + int count = fdp.ConsumeIntegral(); + cacheResultSet.GetRowCount(count); +} + +void CacheResultSetTestGetAllColumnNamesTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + std::vector columnNamesTmp = {}; + cacheResultSet.GetAllColumnNames(columnNamesTmp); +} + +void CacheResultSetTestGetStringTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + int columnIndex = fdp.ConsumeIntegral(); + std::string value; + cacheResultSet.GetString(columnIndex, value); +} + +void CacheResultSetTestGetIntTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + int columnIndex = fdp.ConsumeIntegral(); + int value = 0; + cacheResultSet.GetInt(columnIndex, value); +} + +void CacheResultSetTestGetLongTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + int columnIndex = fdp.ConsumeIntegral(); + int64_t value = 0; + cacheResultSet.GetLong(columnIndex, value); +} + +void CacheResultSetTestGetDoubleTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + int columnIndex = fdp.ConsumeIntegral(); + double value = 0; + cacheResultSet.GetDouble(columnIndex, value); +} + +void CacheResultSetTestGetAssetTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + int32_t columnIndex = fdp.ConsumeIntegral(); + ValueObject::Asset valueOut = {}; + cacheResultSet.GetAsset(columnIndex, valueOut); +} + +void CacheResultSetTestGetTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + int32_t columnIndex = fdp.ConsumeIntegral(); + ValueObject value; + cacheResultSet.Get(columnIndex, value); + int res = 0; + value.GetInt(res); +} + +void CacheResultSetTestIsColumnNullTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + int32_t columnIndex = fdp.ConsumeIntegral(); + bool isNull = fdp.ConsumeBool(); + cacheResultSet.IsColumnNull(columnIndex, isNull); +} + +void CacheResultSetTestGetRowTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + RowEntity rowEntity; + cacheResultSet.GetRow(rowEntity); +} + +void CacheResultSetTestGoToRowTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + int32_t columnIndex = fdp.ConsumeIntegral(); + cacheResultSet.GoToRow(columnIndex); +} + +void CacheResultSetTestGetColumnTypeTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + int32_t columnIndex = fdp.ConsumeIntegral(); + ColumnType columnType = ColumnType::TYPE_INTEGER; + cacheResultSet.GetColumnType(columnIndex, columnType); +} + +void CacheResultSetTestGetRowIndexTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + int32_t columnIndex = fdp.ConsumeIntegral(); + cacheResultSet.GetRowIndex(columnIndex); +} + +void CacheResultSetTestGoToTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + int32_t offset = fdp.ConsumeIntegral(); + cacheResultSet.GoTo(offset); + std::string value; + cacheResultSet.GetString(fdp.ConsumeIntegral(), value); + cacheResultSet.GoToRow(fdp.ConsumeIntegral()); + cacheResultSet.GetString(fdp.ConsumeIntegral(), value); + cacheResultSet.GoTo(fdp.ConsumeIntegral()); +} + +void CacheResultSetTestGoToFirstRowTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + cacheResultSet.GoToFirstRow(); + int position = fdp.ConsumeIntegral(); + cacheResultSet.GetRowIndex(position); +} + +void CacheResultSetTestGoToLastRowTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + cacheResultSet.GoToLastRow(); + int position = fdp.ConsumeIntegral(); + cacheResultSet.GetRowIndex(position); +} + +void CacheResultSetTestGoToNextRowTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + cacheResultSet.GoToNextRow(); + int position = fdp.ConsumeIntegral(); + cacheResultSet.GetRowIndex(position); +} + +void CacheResultSetTestGoToPreviousRowTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + int offset = fdp.ConsumeIntegral(); + int position = fdp.ConsumeIntegral(); + cacheResultSet.GoToRow(position); + cacheResultSet.GoTo(offset); + cacheResultSet.GoToPreviousRow(); +} + +void CacheResultSetTestIsAtFirstRowTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + bool result = fdp.ConsumeBool(); + cacheResultSet.IsAtFirstRow(result); + cacheResultSet.GoToNextRow(); + cacheResultSet.IsAtLastRow(result); +} + +void CacheResultSetTestIsAtLastRowTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + bool result = fdp.ConsumeBool(); + cacheResultSet.IsAtLastRow(result); + cacheResultSet.GoToNextRow(); + cacheResultSet.IsAtLastRow(result); +} + +void CacheResultSetTestIsStartedTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + bool result = fdp.ConsumeBool(); + cacheResultSet.IsStarted(result); +} + +void CacheResultSetTestIsEndedTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + bool result = fdp.ConsumeBool(); + cacheResultSet.IsEnded(result); +} + +void CacheResultSetTestGetColumnCountTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + int count = fdp.ConsumeIntegral(); + cacheResultSet.GetColumnCount(count); +} + +void CacheResultSetTestGetColumnIndexTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + std::string columnName = fdp.ConsumeRandomLengthString(); + int columnIndex = 0; + cacheResultSet.GetColumnIndex(columnName, columnIndex); +} + +void CacheResultSetTestGetColumnNameTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + std::string columnName; + const int index = 0; + cacheResultSet.GetColumnName(index, columnName); +} + +void CacheResultSetTestGetSizeTest001(FuzzedDataProvider &fdp) +{ + std::vector valuesBuckets; + CreateValuesBuckets(fdp, valuesBuckets); + CacheResultSet cacheResultSet(std::move(valuesBuckets)); + + int32_t columnIndex = fdp.ConsumeIntegral(); + size_t size = 0; + cacheResultSet.GetSize(columnIndex, size); +} + + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::CacheResultSetTestGetRowCountTest001(fdp); + OHOS::CacheResultSetTestGetAllColumnNamesTest001(fdp); + OHOS::CacheResultSetTestGetStringTest001(fdp); + OHOS::CacheResultSetTestGetIntTest001(fdp); + OHOS::CacheResultSetTestGetLongTest001(fdp); + OHOS::CacheResultSetTestGetDoubleTest001(fdp); + OHOS::CacheResultSetTestGetAssetTest001(fdp); + OHOS::CacheResultSetTestGetTest001(fdp); + OHOS::CacheResultSetTestIsColumnNullTest001(fdp); + OHOS::CacheResultSetTestGetRowTest001(fdp); + OHOS::CacheResultSetTestGetColumnTypeTest001(fdp); + OHOS::CacheResultSetTestGetRowIndexTest001(fdp); + OHOS::CacheResultSetTestGoToTest001(fdp); + OHOS::CacheResultSetTestGoToFirstRowTest001(fdp); + OHOS::CacheResultSetTestGoToLastRowTest001(fdp); + OHOS::CacheResultSetTestGoToNextRowTest001(fdp); + OHOS::CacheResultSetTestGoToPreviousRowTest001(fdp); + OHOS::CacheResultSetTestIsAtFirstRowTest001(fdp); + OHOS::CacheResultSetTestIsAtLastRowTest001(fdp); + OHOS::CacheResultSetTestIsStartedTest001(fdp); + OHOS::CacheResultSetTestIsEndedTest001(fdp); + OHOS::CacheResultSetTestGetColumnCountTest001(fdp); + OHOS::CacheResultSetTestGetColumnIndexTest001(fdp); + OHOS::CacheResultSetTestGetColumnNameTest001(fdp); + OHOS::CacheResultSetTestGetSizeTest001(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/cache_result_set_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/cache_result_set_test_ut2fuzz.h new file mode 100644 index 00000000..c07d7e7c --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/cache_result_set_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * 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 CACHE_RESULT_SET_TEST_UT2FUZZ_H +#define CACHE_RESULT_SET_TEST_UT2FUZZ_H + +#define FUZZ_PROJECT_NAME "cache_result_set_test_ut2fuzz" + +#endif // CACHE_RESULT_SET_TEST_UT2FUZZ_H diff --git a/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/corpus/init new file mode 100644 index 00000000..2aea1356 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cache_result_set_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/BUILD.gn similarity index 49% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/BUILD.gn rename to relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/BUILD.gn index 718d50ae..aad6b951 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer/BUILD.gn +++ b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2025 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -17,27 +17,19 @@ import("//build/test.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") ##############################fuzztest########################################## -ohos_fuzztest("RddbrepairFuzzerTest") { +ohos_fuzztest("cloud_data_test_ut2fuzz") { module_out_path = "relational_store/relational_store" - include_dirs = [ + include_dirs = [ "${relational_store_native_path}/rdb/include", + "${relational_store_base_path}/interfaces/ndk/include", "${relational_store_innerapi_path}/rdb/include", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb/include", - "${common_tool_path}/", - "//third_party/sqlite/include", - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", - "${foundation_systemabilitymgr_path}/safwk/services/safwk/include", - "${foundation_systemabilitymgr_path}/samgr/interfaces/innerkits/samgr_proxy/include", - "${base_security_dataclassification_path}/interfaces/innerkits/datatransmitmgr/include", - "//third_party/json/single_include", - "//third_party/googletest/googletest/include/gtest", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${cloud_data_native_path}/include", + "${relational_store_innerapi_path}/cloud_data/include", + "${relational_store_innerapi_path}/common_type/include", ] cflags = [ @@ -47,22 +39,32 @@ ohos_fuzztest("RddbrepairFuzzerTest") { "-fno-omit-frame-pointer", ] - fuzz_config_file = "${relational_store_base_path}/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbrepair_fuzzer" + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz" - sources = [ "rddbrepair_fuzzer.cpp" ] - - deps = [ - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb:distributeddb", - "${distributeddata_base_path}/relational_store/interfaces/inner_api/rdb:native_rdb_static", - "//third_party/jsoncpp:jsoncpp", + sources = [ + "${cloud_data_native_path}/src/cloud_types_util.cpp", + "${cloud_data_native_path}/src/cloud_manager.cpp", + "${cloud_data_native_path}/src/cloud_notifier_stub.cpp", + "${cloud_data_native_path}/src/cloud_service_proxy.cpp", + "cloud_data_test_ut2fuzz.cpp", ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + external_deps = [ "ability_base:zuri", "ability_runtime:dataobs_manager", "c_utils:utils", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:datamgr_common", + "sqlite:sqlite", + "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", + "access_token:libtokenid_sdk", + "samgr:samgr_proxy", ] } @@ -72,7 +74,7 @@ group("fuzztest") { deps = [] deps += [ # deps file - ":RddbrepairFuzzerTest", + ":cloud_data_test_ut2fuzz", ] } ############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/cloud_data_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/cloud_data_test_ut2fuzz.cpp new file mode 100644 index 00000000..c02bde62 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/cloud_data_test_ut2fuzz.cpp @@ -0,0 +1,300 @@ +/* + * 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 "cloud_data_test_ut2fuzz.h" + +#include +#include + +#include +#include +#include + +#include "accesstoken_kit.h" +#include "cloud_manager.h" +#include "cloud_types.h" +#include "cloud_types_util.h" +#include "logger.h" +#include "token_setproc.h" + + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::Rdb; +using namespace OHOS::CloudData; +namespace OHOS { + +static constexpr const char *TEST_BUNDLE_NAME = "bundleName"; +static constexpr const char *TEST_ACCOUNT_ID = "testId"; + +void AllocSystemHapToken(const HapPolicyParams &policy) +{ + HapInfoParams info = { .userID = 100, + .bundleName = "ohos.clouddatatest.demo", + .instIndex = 0, + .appIDDesc = "ohos.clouddatatest.demo", + .isSystemApp = true }; + auto token = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(token.tokenIDEx); +} + +void AllocNormalHapToken(const HapPolicyParams &policy) +{ + HapInfoParams info = { .userID = 100, + .bundleName = "ohos.clouddatatest.demo", + .instIndex = 0, + .appIDDesc = "ohos.clouddatatest.demo", + .isSystemApp = false }; + auto token = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(token.tokenIDEx); +} + +HapPolicyParams g_normalPolicy = { .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { { .permissionName = "ohos.permission.CLOUDDATA_CONFIG", + .bundleName = "ohos.clouddatatest.demo", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "ohos.clouddatatest.demo", + .descriptionId = 1 } }, + .permStateList = { { .permissionName = "ohos.permission.CLOUDDATA_CONFIG", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } } } }; + +HapPolicyParams g_systemPolicy = { .apl = APL_SYSTEM_BASIC, + .domain = "test.domain", + .permList = { { .permissionName = "ohos.permission.CLOUDDATA_CONFIG", + .bundleName = "ohos.clouddatatest.demo", + .grantMode = 1, + .availableLevel = APL_SYSTEM_BASIC, + .label = "label", + .labelId = 1, + .description = "ohos.clouddatatest.demo", + .descriptionId = 1 } }, + .permStateList = { { .permissionName = "ohos.permission.CLOUDDATA_CONFIG", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } } } }; + +HapPolicyParams g_notPermissonPolicy = { .apl = APL_SYSTEM_BASIC, + .domain = "test.domain", + .permList = { { .permissionName = "ohos.permission.TEST", + .bundleName = "ohos.clouddatatest.demo", + .grantMode = 1, + .availableLevel = APL_SYSTEM_BASIC, + .label = "label", + .labelId = 1, + .description = "ohos.clouddatatest.demo", + .descriptionId = 1 } }, + .permStateList = { { .permissionName = "ohos.permission.TEST", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } } } }; + +CloudData::Participants CreateParticipants(FuzzedDataProvider &fdp) +{ + Privilege privilege; + privilege.writable = fdp.ConsumeBool(); + privilege.readable = fdp.ConsumeBool(); + privilege.creatable = fdp.ConsumeBool(); + privilege.deletable = fdp.ConsumeBool(); + privilege.shareable = fdp.ConsumeBool(); + + Participant participant; + participant.identity = fdp.ConsumeRandomLengthString(); + participant.role = fdp.ConsumeIntegralInRange(Role::ROLE_NIL, Role::ROLE_BUTT); + participant.state = fdp.ConsumeIntegralInRange(Confirmation::CFM_NIL, Confirmation::CFM_BUTT); + participant.privilege = privilege; + participant.attachInfo = fdp.ConsumeRandomLengthString(); + + CloudData::Participants participants; + participants.push_back(participant); + return participants; +} + +void CloudDataTestCloudDataTest001(FuzzedDataProvider &fdp) +{ + AllocSystemHapToken(g_systemPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + std::map switches; + switches.emplace(TEST_BUNDLE_NAME, fdp.ConsumeIntegral()); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + proxy->EnableCloud(TEST_ACCOUNT_ID, switches); +} + +void CloudDataTestChangeAppSwitch001(FuzzedDataProvider &fdp) +{ + AllocSystemHapToken(g_systemPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + proxy->ChangeAppSwitch(TEST_ACCOUNT_ID, TEST_BUNDLE_NAME, fdp.ConsumeIntegral()); +} + +void CloudDataTestClean001(FuzzedDataProvider &fdp) +{ + AllocSystemHapToken(g_systemPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::map actions; + actions.emplace(TEST_BUNDLE_NAME, fdp.ConsumeIntegral()); + proxy->Clean(TEST_ACCOUNT_ID, actions); +} + +void CloudDataTestNotifyDataChange001(FuzzedDataProvider &fdp) +{ + AllocSystemHapToken(g_systemPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string eventId = fdp.ConsumeRandomLengthString(); + std::string extraData = fdp.ConsumeRandomLengthString(); + int32_t userId = fdp.ConsumeIntegral(); + proxy->NotifyDataChange(eventId, extraData, userId); +} + +void CloudDataTestShare001(FuzzedDataProvider &fdp) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string sharingRes = fdp.ConsumeRandomLengthString(); + + CloudData::Participants participants = CreateParticipants(fdp); + CloudData::Results results; + proxy->Share(sharingRes, participants, results); +} + +void CloudDataTestUnshare001(FuzzedDataProvider &fdp) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string sharingRes = fdp.ConsumeRandomLengthString(); + + CloudData::Participants participants = CreateParticipants(fdp); + CloudData::Results results; + proxy->Unshare(sharingRes, participants, results); +} + +void CloudDataTestExit001(FuzzedDataProvider &fdp) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string sharingRes = fdp.ConsumeRandomLengthString(); + std::pair result; + proxy->Exit(sharingRes, result); +} + +void CloudDataTestChangePrivilege001(FuzzedDataProvider &fdp) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string sharingRes = fdp.ConsumeRandomLengthString(); + CloudData::Participants participants = CreateParticipants(fdp); + CloudData::Results results; + proxy->ChangePrivilege(sharingRes, participants, results); +} + +void CloudDataTestQuery001(FuzzedDataProvider &fdp) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string sharingRes = fdp.ConsumeRandomLengthString(); + CloudData::QueryResults result; + proxy->Query(sharingRes, result); +} + +void CloudDataTestQueryByInvitation001(FuzzedDataProvider &fdp) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string invitation = fdp.ConsumeRandomLengthString(); + CloudData::QueryResults result; + proxy->QueryByInvitation(invitation, result); +} + +void CloudDataTestConfirmInvitation001(FuzzedDataProvider &fdp) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string sharingRes = fdp.ConsumeRandomLengthString(); + int32_t confirmation = fdp.ConsumeIntegral(); + std::tuple result; + proxy->ConfirmInvitation(sharingRes, confirmation, result); +} + +void CloudDataTestChangeConfirmation001(FuzzedDataProvider &fdp) +{ + AllocNormalHapToken(g_normalPolicy); + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (state != CloudService::SUCCESS || proxy == nullptr) { + return; + } + std::string sharingRes = fdp.ConsumeRandomLengthString(); + int32_t confirmation = fdp.ConsumeIntegral(); + std::pair result; + proxy->ChangeConfirmation(sharingRes, confirmation, result); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::CloudDataTestCloudDataTest001(fdp); + OHOS::CloudDataTestChangeAppSwitch001(fdp); + OHOS::CloudDataTestClean001(fdp); + OHOS::CloudDataTestNotifyDataChange001(fdp); + OHOS::CloudDataTestShare001(fdp); + OHOS::CloudDataTestUnshare001(fdp); + OHOS::CloudDataTestExit001(fdp); + OHOS::CloudDataTestChangePrivilege001(fdp); + OHOS::CloudDataTestQuery001(fdp); + OHOS::CloudDataTestQueryByInvitation001(fdp); + OHOS::CloudDataTestConfirmInvitation001(fdp); + OHOS::CloudDataTestChangeConfirmation001(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/cloud_data_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/cloud_data_test_ut2fuzz.h new file mode 100644 index 00000000..fe3ee731 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/cloud_data_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * 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 CLOUD_DATA_TEST_UT2FUZZ_H +#define CLOUD_DATA_TEST_UT2FUZZ_H + +#define FUZZ_PROJECT_NAME "cloud_data_test_ut2fuzz" + +#endif // CLOUD_DATA_TEST_UT2FUZZ_H diff --git a/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/corpus/init new file mode 100644 index 00000000..2aea1356 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/cloud_data_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/BUILD.gn b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/BUILD.gn new file mode 100644 index 00000000..75023b65 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("connection_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ "${relational_store_native_path}/rdb/include" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/connection_test_ut2fuzz" + + sources = [ + "${relational_store_native_path}/rdb/src/connection.cpp", + "connection_test_ut2fuzz.cpp", + ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":connection_test_ut2fuzz", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/transfergrderrno_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/connection_test_ut2fuzz.cpp similarity index 50% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/transfergrderrno_fuzzer.cpp rename to relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/connection_test_ut2fuzz.cpp index b7d963fb..ac15d09e 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/transfergrderrno_fuzzer.cpp +++ b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/connection_test_ut2fuzz.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 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 @@ -12,34 +12,42 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "connection_test_ut2fuzz.h" -#include "rd_utils.h" +#include +#include "connection.h" + +#include +#include + +#include "grd_type_export.h" #include "rdb_errno.h" #include "rdb_store_config.h" -#include "rdb_store_impl.h" + + using namespace OHOS; using namespace OHOS::NativeRdb; namespace OHOS { -uint32_t ConvertToUint32(const uint8_t *ptr, size_t size) +void ConnectionTestConnectionTest001(FuzzedDataProvider &fdp) { - if (ptr == nullptr || (size < sizeof(uint32_t))) { - return 0; - } - return *(reinterpret_cast(ptr)); + RdbStoreConfig config(fdp.ConsumeRandomLengthString()); + config.SetDBType(OHOS::NativeRdb::DBType::DB_BUTT); + Connection::Create(config, fdp.ConsumeBool()); } -void RdUtilsTransferGrdErrnoFuzz(const uint8_t *data, size_t size) +void ConnectionTestConnectionTest002(FuzzedDataProvider &fdp) { - int err = ConvertToUint32(data, size); - RdUtils::TransferGrdErrno(err); + RdbStoreConfig config(fdp.ConsumeRandomLengthString()); + config.SetDBType(OHOS::NativeRdb::DBType::DB_BUTT); + Connection::Repair(config); } } // namespace OHOS -/* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - /* Run your code on data */ - OHOS::RdUtilsTransferGrdErrnoFuzz(data, size); + FuzzedDataProvider fdp(data, size); + OHOS::ConnectionTestConnectionTest001(fdp); + OHOS::ConnectionTestConnectionTest002(fdp); return 0; } diff --git a/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/connection_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/connection_test_ut2fuzz.h new file mode 100644 index 00000000..7a36efcc --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/connection_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * 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 CONNECTION_TEST_UT2FUZZ_H +#define CONNECTION_TEST_UT2FUZZ_H + +#define FUZZ_PROJECT_NAME "connection_test_ut2fuzz" + +#endif // CONNECTION_TEST_UT2FUZZ_H diff --git a/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/corpus/init new file mode 100644 index 00000000..2aea1356 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/connection_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/BUILD.gn similarity index 69% rename from relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/BUILD.gn rename to relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/BUILD.gn index cc3e3cb8..682eece9 100644 --- a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/BUILD.gn +++ b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2025 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -17,15 +17,10 @@ import("//build/test.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") ##############################fuzztest########################################## -ohos_fuzztest("GdbStoreFuzzTest") { +ohos_fuzztest("rdb_attach_test_ut2fuzz") { module_out_path = "relational_store/relational_store" - include_dirs = [ - "${relational_store_innerapi_path}/gdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${relational_store_native_path}/gdb/adapter/include", - "${relational_store_native_path}/gdb/include", - ] + include_dirs = [ "${relational_store_native_path}/rdb/include" ] cflags = [ "-g", @@ -35,15 +30,20 @@ ohos_fuzztest("GdbStoreFuzzTest") { ] fuzz_config_file = - "${relational_store_base_path}/test/native/gdb/fuzztest/gdbstore_fuzzer" + "${relational_store_base_path}/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz" - sources = [ "gdbstore_fuzzer.cpp" ] + sources = [ "rdb_attach_test_ut2fuzz.cpp" ] - deps = [ "${relational_store_innerapi_path}/gdb:native_graphstore" ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", "hilog:libhilog", - "json:nlohmann_json_static", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", ] } @@ -53,7 +53,7 @@ group("fuzztest") { deps = [] deps += [ # deps file - ":GdbStoreFuzzTest", + ":rdb_attach_test_ut2fuzz", ] } ############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/corpus/init new file mode 100644 index 00000000..2aea1356 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/rdb_attach_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/rdb_attach_test_ut2fuzz.cpp new file mode 100644 index 00000000..3a4fe5a8 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/rdb_attach_test_ut2fuzz.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 "rdb_attach_test_ut2fuzz.h" + +#include + +#include +#include + +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +static const std::string MAIN_DATABASE_NAME = "/data/test/main.db"; +static const std::string ATTACHED_DATABASE_NAME = "/data/test/attached.db"; +static const std::string ENCRYPT_ATTACHED_DATABASE_NAME = "/data/test/encrypt_attached.db"; +static const int BUSY_TIMEOUT = 2; + +class MainOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string createTableSql; +}; + +std::string const MainOpenCallback::createTableSql = "CREATE TABLE IF NOT EXISTS test1(id INTEGER PRIMARY KEY " + "AUTOINCREMENT, name TEXT NOT NULL)"; + +int MainOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(createTableSql); +} + +int MainOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +class AttachedOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string createTableSql; +}; + +std::string const AttachedOpenCallback::createTableSql = "CREATE TABLE IF NOT EXISTS test2(id INTEGER PRIMARY KEY " + "AUTOINCREMENT, name TEXT NOT NULL)"; + +int AttachedOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(createTableSql); +} + +int AttachedOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void SetUpTestCase(void) +{ + RdbStoreConfig attachedConfig(ATTACHED_DATABASE_NAME); + AttachedOpenCallback attachedHelper; + int errCode = E_OK; + std::shared_ptr attachedStore = RdbHelper::GetRdbStore(attachedConfig, 1, attachedHelper, errCode); +} + +void TearDownTestCase(void) +{ + RdbHelper::DeleteRdbStore(MAIN_DATABASE_NAME); + RdbHelper::DeleteRdbStore(ATTACHED_DATABASE_NAME); +} + +void QueryCheck1(std::shared_ptr &store) +{ + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test1"); + if (resultSet == nullptr) { + return; + } + int ret = resultSet->GoToNextRow(); + int columnIndex; + int intVal; + ret = resultSet->GetColumnIndex("id", columnIndex); + ret = resultSet->GetInt(columnIndex, intVal); + std::string strVal; + ret = resultSet->GetColumnIndex("name", columnIndex); + ret = resultSet->GetString(columnIndex, strVal); + resultSet = store->QuerySql("SELECT * FROM test2"); + ret = resultSet->GoToNextRow(); + ret = resultSet->GetColumnIndex("id", columnIndex); + ret = resultSet->GetInt(columnIndex, intVal); + ret = resultSet->GetColumnIndex("name", columnIndex); + ret = resultSet->GetString(columnIndex, strVal); +} + +void QueryCheck2(std::shared_ptr &store) +{ + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test1"); + if (resultSet == nullptr) { + return; + } + int ret = resultSet->GoToNextRow(); + int columnIndex; + int intVal; + ret = resultSet->GetColumnIndex("id", columnIndex); + ret = resultSet->GetInt(columnIndex, intVal); + std::string strVal; + ret = resultSet->GetColumnIndex("name", columnIndex); + ret = resultSet->GetString(columnIndex, strVal); + resultSet = store->QuerySql("SELECT * FROM test2"); +} + +void RdbAttachTestRdbStoreAttach001(FuzzedDataProvider &fdp) +{ + int errCode = E_OK; + AttachedOpenCallback attachedHelper; + RdbStoreConfig encryptAttachedConfig(ENCRYPT_ATTACHED_DATABASE_NAME); + encryptAttachedConfig.SetEncryptStatus(fdp.ConsumeBool()); + std::shared_ptr encryptAttachedStore = + RdbHelper::GetRdbStore(encryptAttachedConfig, 1, attachedHelper, errCode); + if (encryptAttachedStore == nullptr) { + return; + } + encryptAttachedStore = nullptr; + const std::string attachedName = "attached"; + RdbStoreConfig config(MAIN_DATABASE_NAME); + MainOpenCallback helper; + + std::shared_ptr store1 = RdbHelper::GetRdbStore(config, 1, helper, errCode); + if (store1 == nullptr) { + return; + } + + store1->Attach(encryptAttachedConfig, attachedName, BUSY_TIMEOUT); + + int64_t id; + ValuesBucket values; + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutString(fdp.ConsumeRandomLengthString(), fdp.ConsumeRandomLengthString()); + store1->Insert(id, fdp.ConsumeRandomLengthString(), values); + + QueryCheck1(store1); + + store1->Detach(attachedName); + + QueryCheck2(store1); + RdbHelper::DeleteRdbStore(ENCRYPT_ATTACHED_DATABASE_NAME); +} + +void RdbAttachTestRdbStoreAttach002(FuzzedDataProvider &fdp) +{ + const std::string attachedName = "attached"; + RdbStoreConfig config(fdp.ConsumeRandomLengthString()); + config.SetStorageMode(StorageMode::MODE_MEMORY); + MainOpenCallback helper; + int errCode = E_OK; + std::shared_ptr mainMemDb = RdbHelper::GetRdbStore(config, 1, helper, errCode); + if (mainMemDb == nullptr) { + return; + } + + RdbStoreConfig attachedConfig(fdp.ConsumeRandomLengthString()); + std::shared_ptr walDb = RdbHelper::GetRdbStore(attachedConfig, 1, helper, errCode); + if (walDb == nullptr) { + return; + } + + std::string sql = fdp.ConsumeRandomLengthString(); + auto code = walDb->ExecuteSql(sql); + + mainMemDb->Attach(attachedConfig, attachedName, BUSY_TIMEOUT); + + ValueObject val; + std::tie(code, val) = + mainMemDb->Execute(fdp.ConsumeRandomLengthString(), { fdp.ConsumeIntegral(), "memDbName" }); + auto result = mainMemDb->QuerySql(fdp.ConsumeRandomLengthString()); + + int index = fdp.ConsumeIntegral(); + result->GetColumnIndex(fdp.ConsumeRandomLengthString(), index); + std::string name; + result->GetString(index, name); + result->Close(); + mainMemDb->Detach(attachedName); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::RdbAttachTestRdbStoreAttach001(fdp); + OHOS::RdbAttachTestRdbStoreAttach002(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/rdb_attach_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/rdb_attach_test_ut2fuzz.h new file mode 100644 index 00000000..b5d77fef --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_attach_test_ut2fuzz/rdb_attach_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * 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 RDB_ATTACH_TEST_UT2FUZZ +#define RDB_ATTACH_TEST_UT2FUZZ + +#define FUZZ_PROJECT_NAME "rdb_attach_test_ut2fuzz" + +#endif // RDB_ATTACH_TEST_UT2FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/BUILD.gn new file mode 100644 index 00000000..9a0d5876 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("rdb_bigint_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz" + + sources = [ "rdb_bigint_test_ut2fuzz.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":rdb_bigint_test_ut2fuzz", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/corpus/init new file mode 100644 index 00000000..2aea1356 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/rdb_bigint_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/rdb_bigint_test_ut2fuzz.cpp new file mode 100644 index 00000000..48a4f895 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/rdb_bigint_test_ut2fuzz.cpp @@ -0,0 +1,76 @@ +/* + * 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 "rdb_bigint_test_ut2fuzz.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "big_integer.h" +#include "connection_pool.h" +#include "trans_db.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +namespace OHOS { + +void BigIntegerFuzzTest(FuzzedDataProvider &fdp) +{ + // Test primary constructor with int64_t + auto bi1 = NativeRdb::BigInteger(fdp.ConsumeIntegral()); + + // Test (sign, vector) constructor + std::vector vec; + while (fdp.remaining_bytes() >= sizeof(uint64_t)) { + vec.push_back(fdp.ConsumeIntegral()); + } + auto bi2 = NativeRdb::BigInteger( + fdp.ConsumeIntegralInRange(-1, 1), + std::move(vec) + ); + + // Validate copy semantics + auto bi3 = NativeRdb::BigInteger(bi1); + bi3 = bi2; // Test assignment operator + + // Stress test move semantics + auto bi4 = NativeRdb::BigInteger(std::move(bi2)); + bi1 = std::move(bi3); + + // Verify core operations + (void)(bi1 == bi4); // Compare equality + (void)(bi1 < bi4); // Compare ordering + + // Exercise all public methods + (void)bi1.Sign(); // Validate sign retrieval + (void)bi1.Size(); // Check array size + (void)bi1.TrueForm(); // Access raw data + (void)bi1.Value(); // Test value copy +} + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::BigIntegerFuzzTest(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/rdb_bigint_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/rdb_bigint_test_ut2fuzz.h new file mode 100644 index 00000000..8282ff37 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_bigint_test_ut2fuzz/rdb_bigint_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * 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 RDB_BIGINT_TEST_UT2FUZZ +#define RDB_BIGINT_TEST_UT2FUZZ + +#define FUZZ_PROJECT_NAME "rdb_bigint_test_ut2fuzz" + +#endif // RDB_BIGINT_TEST_UT2FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/BUILD.gn new file mode 100644 index 00000000..d7a2ef6f --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("rdb_callback_icu_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ "${relational_store_native_path}/rdb/include" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz" + + sources = [ "rdb_callback_icu_test_ut2fuzz.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":rdb_callback_icu_test_ut2fuzz", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/corpus/init new file mode 100644 index 00000000..2aea1356 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/rdb_callback_icu_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/rdb_callback_icu_test_ut2fuzz.cpp new file mode 100644 index 00000000..f2a5c001 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/rdb_callback_icu_test_ut2fuzz.cpp @@ -0,0 +1,134 @@ +/* + * 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 "rdb_callback_icu_test_ut2fuzz.h" + +#include + +#include +#include + +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +static const std::string PATH_NAME = "/data/test/rdb_callback_icu_test.db"; + +class OpenCallbackIcu : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + int OnDowngrade(RdbStore &store, int oldVersion, int newVersion) override; + int OnOpen(RdbStore &store) override; + + static std::string CreateTableSQL(const std::string &tableName); + static std::string DropTableSQL(const std::string &tableName); +}; + +std::string OpenCallbackIcu::CreateTableSQL(const std::string &tableName) +{ + return "CREATE VIRTUAL TABLE IF NOT EXISTS " + tableName + " USING fts4(name, content, tokenize=icu zh_CN);"; +} + +std::string OpenCallbackIcu::DropTableSQL(const std::string &tableName) +{ + return "DROP TABLE IF EXISTS " + tableName + ";"; +} + +int OpenCallbackIcu::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CreateTableSQL("test1")); +} + +int OpenCallbackIcu::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +int OpenCallbackIcu::OnDowngrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +int OpenCallbackIcu::OnOpen(RdbStore &store) +{ + return E_OK; +} + +void RdbCallbackIcuTestRdbCallbackIcu01(FuzzedDataProvider &fdp) +{ + RdbStoreConfig config(PATH_NAME); + config.SetTokenizer(ICU_TOKENIZER); + OpenCallbackIcu helper; + + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + if (store == nullptr) { + return; + } + + const char *sqlCreateTable = "CREATE VIRTUAL TABLE example USING fts4(name, content, tokenize=icu zh_CN);"; + int ret = store->ExecuteSql(sqlCreateTable); + + const char *sqlInsert1 = + "INSERT INTO example(name, content) VALUES('文档1', '这是一个测试文档,用于测试中文文本的分词和索引。');"; + ret = store->ExecuteSql(sqlInsert1); + + const char *sqlInsert2 = + "INSERT INTO example(name, content) VALUES('文档2', '我们将使用这个示例来演示如何在SQLite中进行全文搜索。');"; + ret = store->ExecuteSql(sqlInsert2); + + const char *sqlInsert3 = + "INSERT INTO example(name, content) VALUES('文档3', 'ICU分词器能够很好地处理中文文本的分词和分析。');"; + ret = store->ExecuteSql(sqlInsert3); + + const char *sqlQuery = "SELECT * FROM example WHERE example MATCH '测试';"; + ret = store->ExecuteSql(sqlQuery); + + std::shared_ptr resultSet = store->QuerySql(sqlQuery); + if (resultSet == nullptr) { + return; + } + + ret = resultSet->GoToNextRow(); + + int columnIndex; + std::string strVal; + + ret = resultSet->GetColumnIndex(fdp.ConsumeRandomLengthString(), columnIndex); + + ret = resultSet->GetString(columnIndex, strVal); + + ret = resultSet->GetColumnIndex(fdp.ConsumeRandomLengthString(), columnIndex); + + ret = resultSet->GetString(columnIndex, strVal); + + ret = resultSet->GoToNextRow(); + + ret = resultSet->Close(); +} + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::RdbCallbackIcuTestRdbCallbackIcu01(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/rdb_callback_icu_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/rdb_callback_icu_test_ut2fuzz.h new file mode 100644 index 00000000..d15c46ba --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_callback_icu_test_ut2fuzz/rdb_callback_icu_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * 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 RDB_CALLBACK_ICU_TEST_UT2FUZZ +#define RDB_CALLBACK_ICU_TEST_UT2FUZZ + +#define FUZZ_PROJECT_NAME "rdb_callback_icu_test_ut2fuzz" + +#endif // RDB_CALLBACK_ICU_TEST_UT2FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/BUILD.gn new file mode 100644 index 00000000..64d3f5be --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("rdb_corrupt_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ "${relational_store_native_path}/rdb/include" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz" + + sources = [ "rdb_corrupt_test_ut2fuzz.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":rdb_corrupt_test_ut2fuzz", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/corpus/init new file mode 100644 index 00000000..2aea1356 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/rdb_corrupt_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/rdb_corrupt_test_ut2fuzz.cpp new file mode 100644 index 00000000..b09a0ed7 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/rdb_corrupt_test_ut2fuzz.cpp @@ -0,0 +1,129 @@ +/* + * 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 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 "rdb_corrupt_test_ut2fuzz.h" + +#include +#include + +#include +#include +#include +#include + +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +namespace OHOS { + +static const std::string PATH_NAME = "/data/test/corrupt_test.db"; + +class CorruptTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary " + "REAL, blobType BLOB)"; +}; + +int CorruptTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(createTableTest); +} + +int CorruptTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void SetUp(std::shared_ptr &store) +{ + RdbHelper::ClearCache(); + RdbHelper::DeleteRdbStore(PATH_NAME); + RdbStoreConfig sqliteSharedRstConfig(PATH_NAME); + CorruptTestOpenCallback openCallback; + int errCode = E_OK; + store = RdbHelper::GetRdbStore(sqliteSharedRstConfig, 1, openCallback, errCode); + if (store == nullptr) { + return; + } + RdbHelper::ClearCache(); +} + +void TearDown(void) +{ + RdbHelper::ClearCache(); + RdbHelper::DeleteRdbStore(PATH_NAME); +} + +void DestroyDbFile(const std::string &filePath, size_t offset, size_t len, unsigned char ch) +{ + constexpr size_t MAX_CORRUPT_SIZE = 2048; + len = std::min(len, MAX_CORRUPT_SIZE); + + std::vector buf; + buf.reserve(len); + buf.assign(len, static_cast(ch)); + + std::ofstream f(filePath, std::ios::binary | std::ios::in | std::ios::out); + if (!f) + return; + + f.seekp(offset); + f.write(buf.data(), len); +} + +void RdbCorruptTestRdbCorruptTest001(FuzzedDataProvider &fdp) +{ + std::shared_ptr store; + SetUp(store); + if (store == nullptr) { + return; + } + + constexpr size_t MAX_FILE_SIZE = 4096; + size_t offset = fdp.ConsumeIntegralInRange(0, MAX_FILE_SIZE / 2); + size_t len = fdp.ConsumeIntegralInRange(1, MAX_FILE_SIZE - offset); + DestroyDbFile(PATH_NAME, offset, len, fdp.ConsumeIntegral()); + + CorruptTestOpenCallback sqliteCallback; + RdbStoreConfig sqliteConfig(PATH_NAME); + int errCode = E_OK; + store = RdbHelper::GetRdbStore(sqliteConfig, 1, sqliteCallback, errCode); + if (store == nullptr) { + return; + } + + std::shared_ptr resultSet = store->QueryByStep("SELECT * FROM test"); + if (resultSet == nullptr) { + return; + } + + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + if (errCode != E_OK) { + break; + } + } + resultSet->Close(); + TearDown(); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::RdbCorruptTestRdbCorruptTest001(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/rdb_corrupt_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/rdb_corrupt_test_ut2fuzz.h new file mode 100644 index 00000000..5eb7c1e5 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_corrupt_test_ut2fuzz/rdb_corrupt_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * 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 RDB_CORRUPT_TEST_UT2FUZZ +#define RDB_CORRUPT_TEST_UT2FUZZ + +#define FUZZ_PROJECT_NAME "rdb_corrupt_test_ut2fuzz" + +#endif // RDB_CORRUPT_TEST_UT2FUZZ diff --git a/kv_store/test/fuzztest/distributedkvdataservice_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/BUILD.gn similarity index 63% rename from kv_store/test/fuzztest/distributedkvdataservice_fuzzer/BUILD.gn rename to relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/BUILD.gn index 45dd0620..cc9d6272 100644 --- a/kv_store/test/fuzztest/distributedkvdataservice_fuzzer/BUILD.gn +++ b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2024 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 @@ -14,35 +14,36 @@ #####################hydra-fuzz################### import("//build/config/features.gni") import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") ##############################fuzztest########################################## -ohos_fuzztest("DistributedKvDataServiceFuzzTest") { - module_out_path = "kv_store/kv_store" - - include_dirs = [ - "../../../frameworks/common", - "../../../frameworks/innerkitsimpl/distributeddatafwk/include", - "../../../frameworks/innerkitsimpl/distributeddatafwk/src", - "../../../interfaces/innerkits/distributeddata/include", - ] +ohos_fuzztest("rdb_delete_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" - fuzz_config_file = "../../../test/fuzztest/distributedkvdataservice_fuzzer" + include_dirs = [ "${relational_store_native_path}/rdb/include" ] cflags = [ "-g", "-O0", "-Wno-unused-variable", "-fno-omit-frame-pointer", - "-Wno-c99-designator", ] - sources = [ "distributedkvdataservice_fuzzer.cpp" ] - deps = [] + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz" + + sources = [ "rdb_delete_test_ut2fuzz.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", "c_utils:utils", "hilog:libhilog", - "kv_store:distributeddata_inner", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", ] } @@ -52,7 +53,7 @@ group("fuzztest") { deps = [] deps += [ # deps file - ":DistributedKvDataServiceFuzzTest", + ":rdb_delete_test_ut2fuzz", ] } ############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/corpus/init new file mode 100644 index 00000000..2aea1356 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/rdb_delete_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/rdb_delete_test_ut2fuzz.cpp new file mode 100644 index 00000000..685582c2 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/rdb_delete_test_ut2fuzz.cpp @@ -0,0 +1,233 @@ +/* + * 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 "rdb_delete_test_ut2fuzz.h" + +#include +#include + +#include +#include +#include +#include + +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +static const std::string DATABASE_NAME = "/data/test/delete_test.db"; +std::shared_ptr store_; +std::shared_ptr memDBStore_; + +struct RowData { + int id; + std::string name; + int age; + double salary; + std::vector blobType; + AssetValue asset; + std::vector assets; +}; + +class DeleteTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; +constexpr const char *CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test" + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary " + "REAL, blobType BLOB)"; +int DeleteTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_TEST); +} + +int DeleteTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +ValuesBucket SetRowData(const RowData &rowData) +{ + ValuesBucket value; + value.PutInt("id", rowData.id); + value.PutString("name", rowData.name); + value.PutInt("age", rowData.age); + value.PutDouble("salary", rowData.salary); + value.PutBlob("blobType", rowData.blobType); + return value; +} + +void SetUpTestCase(void) +{ + int errCode = E_OK; + RdbHelper::DeleteRdbStore(DATABASE_NAME); + RdbStoreConfig config(DATABASE_NAME); + DeleteTestOpenCallback helper; + store_ = RdbHelper::GetRdbStore(config, 1, helper, errCode); + store_->ExecuteSql("DELETE FROM test"); + + config.SetStorageMode(StorageMode::MODE_MEMORY); + memDBStore_ = RdbHelper::GetRdbStore(config, 1, helper, errCode); +} + +void TearDownTestCase(void) +{ + RdbStoreConfig config(DATABASE_NAME); + RdbHelper::DeleteRdbStore(config); + config.SetStorageMode(StorageMode::MODE_MEMORY); + RdbHelper::DeleteRdbStore(config); +} + +void RdbDeleteTestRdbStoreDelete001(FuzzedDataProvider &fdp) +{ + SetUpTestCase(); + std::shared_ptr store = store_; + if (store == NULL) { + return; + } + + int64_t id; + int deletedRows; + + const RowData rowData[3] = { { 1, "zhangsan", 18, 100.5, std::vector{ 1, 2, 3 } }, + { 2, "lisi", 19, 200.5, std::vector{ 4, 5, 6 } }, + { 3, "wangyjing", 20, 300.5, std::vector{ 7, 8, 9 } } }; + + const int indexZero = 0; + store->Insert(id, fdp.ConsumeRandomLengthString(), SetRowData(rowData[indexZero])); + + const int indexOne = 1; + store->Insert(id, fdp.ConsumeRandomLengthString(), SetRowData(rowData[indexOne])); + + const int indexTwo = 2; + store->Insert(id, fdp.ConsumeRandomLengthString(), SetRowData(rowData[indexTwo])); + + store->Delete(deletedRows, fdp.ConsumeRandomLengthString(), fdp.ConsumeRandomLengthString()); + + std::shared_ptr resultSet = + store->QuerySql("SELECT * FROM test WHERE id = ?", std::vector{ "1" }); + + resultSet->GoToNextRow(); + + resultSet->Close(); + + resultSet = store->QuerySql("SELECT * FROM test WHERE id = ?", std::vector{ "2" }); + + resultSet->GoToFirstRow(); + + resultSet->GoToNextRow(); + + resultSet->Close(); + + resultSet = store->QuerySql("SELECT * FROM test WHERE id = 3", std::vector()); + + resultSet->GoToFirstRow(); + + resultSet->GoToNextRow(); + + resultSet->Close(); + TearDownTestCase(); +} + +void RdbDeleteTestRdbStoreDelete002(FuzzedDataProvider &fdp) +{ + SetUpTestCase(); + std::shared_ptr store = store_; + if (store == NULL) { + return; + } + + int64_t id; + ValuesBucket values; + int deletedRows; + + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutString(fdp.ConsumeRandomLengthString(), std::string(fdp.ConsumeRandomLengthString())); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutDouble(fdp.ConsumeRandomLengthString(), fdp.ConsumeFloatingPoint()); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + store->Insert(id, fdp.ConsumeRandomLengthString(), values); + + values.Clear(); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutString(fdp.ConsumeRandomLengthString(), std::string(fdp.ConsumeRandomLengthString())); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutDouble(fdp.ConsumeRandomLengthString(), fdp.ConsumeFloatingPoint()); + values.PutBlob("blobType", std::vector{ 4, 5, 6 }); + store->Insert(id, fdp.ConsumeRandomLengthString(), values); + + values.Clear(); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutString(fdp.ConsumeRandomLengthString(), std::string(fdp.ConsumeRandomLengthString())); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutDouble(fdp.ConsumeRandomLengthString(), fdp.ConsumeFloatingPoint()); + values.PutBlob("blobType", std::vector{ 7, 8, 9 }); + store->Insert(id, fdp.ConsumeRandomLengthString(), values); + + store->Delete(deletedRows, fdp.ConsumeRandomLengthString()); + + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + if (resultSet == NULL) { + return; + } + resultSet->GoToNextRow(); + resultSet->Close(); + TearDownTestCase(); +} + +void RdbDeleteTestRdbStoreDelete003(FuzzedDataProvider &fdp) +{ + SetUpTestCase(); + std::shared_ptr store = store_; + if (store == NULL) { + return; + } + + int64_t id; + ValuesBucket values; + int deletedRows; + + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutString(fdp.ConsumeRandomLengthString(), std::string(fdp.ConsumeRandomLengthString())); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutDouble(fdp.ConsumeRandomLengthString(), fdp.ConsumeFloatingPoint()); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + store->Insert(id, fdp.ConsumeRandomLengthString(), values); + + store->Delete(deletedRows, "", "id = ?", std::vector{ "1" }); + + store->Delete(deletedRows, "wrongTable", "id = ?", std::vector{ "1" }); + + store->Delete(deletedRows, "test", "wrong sql id = ?", std::vector{ "1" }); + + store->Delete(deletedRows, "test", "id = 1", std::vector()); + TearDownTestCase(); +} + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::RdbDeleteTestRdbStoreDelete001(fdp); + OHOS::RdbDeleteTestRdbStoreDelete002(fdp); + OHOS::RdbDeleteTestRdbStoreDelete003(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/rdb_delete_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/rdb_delete_test_ut2fuzz.h new file mode 100644 index 00000000..2c4a4075 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_delete_test_ut2fuzz/rdb_delete_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * 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 RDB_DELETE_TEST_UT2FUZZ +#define RDB_DELETE_TEST_UT2FUZZ + +#define FUZZ_PROJECT_NAME "rdb_delete_test_ut2fuzz" + +#endif // RDB_DELETE_TEST_UT2FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/BUILD.gn new file mode 100644 index 00000000..a5790bbc --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("rdb_distributed_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ "${relational_store_native_path}/rdb/include" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz" + + sources = [ "rdb_distributed_test_ut2fuzz.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":rdb_distributed_test_ut2fuzz", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/corpus/init new file mode 100644 index 00000000..2aea1356 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/rdb_distributed_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/rdb_distributed_test_ut2fuzz.cpp new file mode 100644 index 00000000..2b735ea4 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/rdb_distributed_test_ut2fuzz.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 "rdb_distributed_test_ut2fuzz.h" + +#include +#include +#include +#include + +#include +#include + +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +static const std::string DATABASE_NAME = "/data/test/distributed_rdb.db"; +static std::shared_ptr rdbStore; + +class TestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override + { + std::string sql = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY AUTOINCREMENT," + "name TEXT NOT NULL," + "age INTEGER," + "salary REAL," + "data BLOB)"; + store.ExecuteSql(sql); + return 0; + } + + int OnOpen(RdbStore &store) override + { + return 0; + } + + int OnUpgrade(RdbStore &store, int currentVersion, int targetVersion) override + { + return 0; + } +}; + +void SetUpTestCase(void) +{ + int errCode = 0; + std::string path = DATABASE_NAME; + RdbHelper::DeleteRdbStore(path); + int fd = open(path.c_str(), O_CREAT, S_IRWXU | S_IRWXG); + if (fd < 0) { + return; + } + if (fd > 0) { + close(fd); + } + const int ddmsGroupId = 1000; + chown(path.c_str(), 0, ddmsGroupId); + + RdbStoreConfig config(path); + config.SetBundleName("com.example.distributed.rdb"); + config.SetName(DATABASE_NAME); + TestOpenCallback callback; + rdbStore = RdbHelper::GetRdbStore(config, 1, callback, errCode); + rdbStore->ExecuteSql("DELETE FROM test"); +} + +void TearDownTestCase(void) +{ + rdbStore->ExecuteSql("DELETE FROM test"); + RdbHelper::DeleteRdbStore(DATABASE_NAME); +} + +void RdbStoreDistributedTestRdbStoreDistributedTest001(FuzzedDataProvider &fdp) +{ + SetUpTestCase(); + int errCode; + std::vector tables; + OHOS::DistributedRdb::DistributedConfig distributedConfig; + + rdbStore->SetDistributedTables(tables, fdp.ConsumeIntegral(), distributedConfig); + tables.push_back(fdp.ConsumeRandomLengthString()); + rdbStore->SetDistributedTables(tables, fdp.ConsumeIntegral(), distributedConfig); + + std::string path = DATABASE_NAME; + RdbHelper::DeleteRdbStore(path); + RdbStoreConfig config(path); + TestOpenCallback callback; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, callback, errCode); + if (store == NULL) { + return; + } + + store->SetDistributedTables(tables, fdp.ConsumeIntegral(), distributedConfig); + + RdbHelper::DeleteRdbStore(path); + + TearDownTestCase(); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::RdbStoreDistributedTestRdbStoreDistributedTest001(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/rdb_distributed_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/rdb_distributed_test_ut2fuzz.h new file mode 100644 index 00000000..87961856 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_distributed_test_ut2fuzz/rdb_distributed_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * 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 RDB_DISTRIBUTED_TEST_UT2FUZZ +#define RDB_DISTRIBUTED_TEST_UT2FUZZ + +#define FUZZ_PROJECT_NAME "rdb_distributed_test_ut2fuzz" + +#endif // RDB_DISTRIBUTED_TEST_UT2FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/BUILD.gn new file mode 100644 index 00000000..5214a0af --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("rdb_double_write_test_ut2fuzz") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ "${relational_store_native_path}/rdb/include" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz" + + sources = [ "rdb_double_write_test_ut2fuzz.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":rdb_double_write_test_ut2fuzz", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/corpus/init b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/corpus/init new file mode 100644 index 00000000..2aea1356 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/project.xml b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/rdb_double_write_test_ut2fuzz.cpp b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/rdb_double_write_test_ut2fuzz.cpp new file mode 100644 index 00000000..779652a7 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/rdb_double_write_test_ut2fuzz.cpp @@ -0,0 +1,210 @@ +/* + * 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 "rdb_double_write_test_ut2fuzz.h" + +#include +#include +#include + +#include +#include + +#include "file_ex.h" +#include "rdb_common.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "sqlite_utils.h" +#include "sys/types.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +static const std::string DATABASE_NAME = "/data/test/dual_write_test.db"; +static const std::string SLAVE_DATABASE_NAME = "/data/test/dual_write_test_slave.db"; +std::shared_ptr store = nullptr; +std::shared_ptr slaveStore = nullptr; +std::shared_ptr store3 = nullptr; + +class DoubleWriteTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string createTableTest; +}; + +const std::string DoubleWriteTestOpenCallback::createTableTest = + std::string("CREATE TABLE IF NOT EXISTS test ") + std::string("(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary " + "REAL, blobType BLOB)"); + +int DoubleWriteTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(createTableTest); +} + +int DoubleWriteTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void SetUpTestCase(void) +{ +} + +void TearDownTestCase(void) +{ + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(DATABASE_NAME); +} + +void InitDb() +{ + int errCode = E_OK; + RdbStoreConfig config(DATABASE_NAME); + config.SetHaMode(HAMode::MAIN_REPLICA); + DoubleWriteTestOpenCallback helper; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + + RdbStoreConfig slaveConfig(SLAVE_DATABASE_NAME); + DoubleWriteTestOpenCallback slaveHelper; + slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); + store->ExecuteSql("DELETE FROM test"); + slaveStore->ExecuteSql("DELETE FROM test"); +} + +void CheckAge(std::shared_ptr &resultSet) +{ + int columnIndex; + int intVal; + ColumnType columnType; + int ret = resultSet->GetColumnIndex("age", columnIndex); + ret = resultSet->GetColumnType(columnIndex, columnType); + + ret = resultSet->GetInt(columnIndex, intVal); +} + +void CheckSalary(std::shared_ptr &resultSet) +{ + int columnIndex; + double dVal; + ColumnType columnType; + int ret = resultSet->GetColumnIndex("salary", columnIndex); + + ret = resultSet->GetColumnType(columnIndex, columnType); + + ret = resultSet->GetDouble(columnIndex, dVal); +} + +void CheckBlob(std::shared_ptr &resultSet) +{ + int columnIndex; + std::vector blob; + ColumnType columnType; + int ret = resultSet->GetColumnIndex("blobType", columnIndex); + + ret = resultSet->GetColumnType(columnIndex, columnType); + + ret = resultSet->GetBlob(columnIndex, blob); +} + +void CheckNumber( + std::shared_ptr &store, int num, int errCode, const std::string &tableName) +{ + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM " + tableName); + int countNum; + resultSet->GetRowCount(countNum); +} + +void CheckResultSet(std::shared_ptr &store) +{ + std::shared_ptr resultSet = + store->QuerySql("SELECT * FROM test WHERE name = ?", std::vector{ "zhangsan" }); + + int columnIndex; + int intVal; + std::string strVal; + ColumnType columnType; + int position; + int ret = resultSet->GetRowIndex(position); + + ret = resultSet->GetColumnType(0, columnType); + + ret = resultSet->GoToFirstRow(); + + ret = resultSet->GetColumnIndex("id", columnIndex); + + ret = resultSet->GetColumnType(columnIndex, columnType); + + ret = resultSet->GetInt(columnIndex, intVal); + + ret = resultSet->GetColumnIndex("name", columnIndex); + + ret = resultSet->GetColumnType(columnIndex, columnType); + + ret = resultSet->GetString(columnIndex, strVal); + + CheckAge(resultSet); + CheckSalary(resultSet); + CheckBlob(resultSet); + + ret = resultSet->GoToNextRow(); + + ret = resultSet->GetColumnType(columnIndex, columnType); + + ret = resultSet->Close(); +} + +void RdbDoubleWriteTestRdbStoreDoubleWrite001(FuzzedDataProvider &fdp) +{ + InitDb(); + int64_t id; + ValuesBucket values; + + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutString(fdp.ConsumeRandomLengthString(), std::string(fdp.ConsumeRandomLengthString())); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutDouble(fdp.ConsumeRandomLengthString(), fdp.ConsumeFloatingPoint()); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store->Insert(id, "test", values); + + values.Clear(); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutString(fdp.ConsumeRandomLengthString(), std::string(fdp.ConsumeRandomLengthString())); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutDouble(fdp.ConsumeRandomLengthString(), fdp.ConsumeFloatingPoint()); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + ret = store->Insert(id, "test", values); + + values.Clear(); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutString(fdp.ConsumeRandomLengthString(), std::string(fdp.ConsumeRandomLengthString())); + values.PutInt(fdp.ConsumeRandomLengthString(), fdp.ConsumeIntegral()); + values.PutDouble(fdp.ConsumeRandomLengthString(), fdp.ConsumeFloatingPoint()); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + ret = store->Insert(id, "test", values); + + CheckResultSet(slaveStore); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider fdp(data, size); + OHOS::RdbDoubleWriteTestRdbStoreDoubleWrite001(fdp); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/rdb_double_write_test_ut2fuzz.h b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/rdb_double_write_test_ut2fuzz.h new file mode 100644 index 00000000..97861890 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdb_double_write_test_ut2fuzz/rdb_double_write_test_ut2fuzz.h @@ -0,0 +1,21 @@ +/* + * 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 RDB_DOUBLE_WRITE_TEST_UT2FUZZ +#define RDB_DOUBLE_WRITE_TEST_UT2FUZZ + +#define FUZZ_PROJECT_NAME "rdb_double_write_test_ut2fuzz" + +#endif // RDB_DOUBLE_WRITE_TEST_UT2FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/BUILD.gn new file mode 100644 index 00000000..97054c66 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("RdbHelperFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ "${relational_store_native_path}/rdb/include" ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdbhelper_fuzzer" + + sources = [ "rdbhelper_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":RdbHelperFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/corpus/init new file mode 100644 index 00000000..14cddafc --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/corpus/init @@ -0,0 +1,16 @@ +/* + * 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. + */ + +FUZZ diff --git a/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/project.xml new file mode 100644 index 00000000..880527c3 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/project.xml @@ -0,0 +1,26 @@ + + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/rdbhelper_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/rdbhelper_fuzzer.cpp new file mode 100644 index 00000000..cfdb230f --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/rdbhelper_fuzzer.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 +#include +#include +#include +#include +#include + +#include + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +class FuzzRdbOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &rdbStore) override + { + return 0; + } + int OnUpgrade(RdbStore &rdbStore, int currentVersion, int targetVersion) override + { + return 0; + } + int OnOpen(RdbStore &rdbStore) override + { + return 0; + } + int OnDowngrade(RdbStore &rdbStore, int currentVersion, int targetVersion) override + { + return 0; + } +}; + +void ExecuteSqlFuzzTest(FuzzedDataProvider &provider) +{ + std::string path = provider.ConsumeRandomLengthString(); + RdbStoreConfig config(path); + config.SetReadOnly(provider.ConsumeBool()); + config.SetPageSize(provider.ConsumeIntegral()); + config.SetBundleName(provider.ConsumeRandomLengthString()); + config.SetSearchable(provider.ConsumeBool()); + config.SetStorageMode(provider.ConsumeBool() ? StorageMode::MODE_MEMORY : StorageMode::MODE_DISK); + + FuzzRdbOpenCallback openCallback; + int errCode = 0; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, openCallback, errCode); + if (!store) { + return; + } + + { + std::string sql = provider.ConsumeRandomLengthString(); + store->ExecuteSql(sql); + } + + ValuesBucket valuesBucket; + { + std::string columnName = provider.ConsumeRandomLengthString(); + valuesBucket.PutInt(columnName, provider.ConsumeIntegral()); + } + + { + std::string columnName = provider.ConsumeRandomLengthString(); + valuesBucket.PutInt(columnName, provider.ConsumeIntegral()); + } + + int64_t outRowId = 0; + std::string tableName = provider.ConsumeRandomLengthString(); + store->Insert(outRowId, tableName, valuesBucket); +} + +void OnDowngradeFuzzTest(FuzzedDataProvider &provider) +{ + // Construct RdbStoreConfig + std::string path = provider.ConsumeRandomLengthString(); + RdbStoreConfig config(path); + config.SetHaMode(provider.ConsumeIntegral()); + + // Construct RdbOpenCallback + FuzzRdbOpenCallback openCallback; + + // Construct RdbStore + int errCode = 0; + std::shared_ptr rdbStore = + RdbHelper::GetRdbStore(config, provider.ConsumeIntegral(), openCallback, errCode); + if (!rdbStore) { + return; + } + + // Test GetBackupStatus + rdbStore->GetBackupStatus(); + + // Test InterruptBackup + rdbStore->InterruptBackup(); + + // Test OnOpen + openCallback.OnOpen(*rdbStore); + + // Test OnDowngrade + openCallback.OnDowngrade(*rdbStore, provider.ConsumeIntegral(), provider.ConsumeIntegral()); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::ExecuteSqlFuzzTest(provider); + OHOS::OnDowngradeFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/rdbhelper_fuzzer.h b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/rdbhelper_fuzzer.h new file mode 100644 index 00000000..b86cb138 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbhelper_fuzzer/rdbhelper_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 RDBHELPER_FUZZER_H +#define RDBHELPER_FUZZER_H + +#define FUZZ_PROJECT_NAME "rdbhelper_fuzzer" + +#endif // RDBHELPER_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/BUILD.gn index 7b03f3c3..67355c3f 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/BUILD.gn +++ b/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 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 @@ -22,22 +22,7 @@ ohos_fuzztest("RdbImplFuzzTest") { include_dirs = [ "${relational_store_native_path}/rdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb/include", - "${common_tool_path}/", - "//third_party/sqlite/include", - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", - "${foundation_systemabilitymgr_path}/safwk/services/safwk/include", - "${foundation_systemabilitymgr_path}/samgr/interfaces/innerkits/samgr_proxy/include", - "${base_security_dataclassification_path}/interfaces/innerkits/datatransmitmgr/include", - "//third_party/json/single_include", - "//third_party/googletest/googletest/include/gtest", + "${relational_store_common_path}/include", ] cflags = [ @@ -52,11 +37,7 @@ ohos_fuzztest("RdbImplFuzzTest") { sources = [ "rdbimpl_fuzzer.cpp" ] - deps = [ - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb:distributeddb", - "${distributeddata_base_path}/relational_store/interfaces/inner_api/rdb:native_rdb_static", - "//third_party/jsoncpp:jsoncpp", - ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] external_deps = [ "ability_base:zuri", @@ -64,6 +45,10 @@ ohos_fuzztest("RdbImplFuzzTest") { "c_utils:utils", "hilog:libhilog", "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", ] } diff --git a/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/corpus/init index bc977bd9..65af8ee8 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/corpus/init +++ b/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/corpus/init @@ -1,4 +1,4 @@ -# Copyright (c) 2022 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 diff --git a/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/project.xml index 6e8ad2cf..66e1dcac 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/project.xml +++ b/relational_store/test/native/rdb/fuzztest/rdbimpl_fuzzer/project.xml @@ -1,5 +1,5 @@ - + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/rdbpredicates_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/rdbpredicates_fuzzer.cpp new file mode 100644 index 00000000..91011636 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/rdbpredicates_fuzzer.cpp @@ -0,0 +1,91 @@ +/* + * 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 "rdb_predicates.h" + + +#define LOOPS_MIN 0 +#define LOOPS_MAX 100 + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +namespace OHOS { +std::vector ConsumeRandomLengthStringVector(FuzzedDataProvider &provider) +{ + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t length = provider.ConsumeIntegral(); + auto bytes = provider.ConsumeBytes(length); + columns.emplace_back(bytes.begin(), bytes.end()); + } + return columns; +} + +void RdbPredicatesCrossJoinFuzz(FuzzedDataProvider &provider) +{ + std::string tableName = provider.ConsumeRandomLengthString(); + RdbPredicates predicates(tableName); + std::string joinTableName = provider.ConsumeRandomLengthString(); + predicates.CrossJoin(joinTableName); +} + +void RdbPredicatesInnerJoinFuzz(FuzzedDataProvider &provider) +{ + std::string tableName = provider.ConsumeRandomLengthString(); + RdbPredicates predicates(tableName); + std::string joinTableName = provider.ConsumeRandomLengthString(); + predicates.InnerJoin(joinTableName); +} + +void RdbPredicatesLeftOuterJoinFuzz(FuzzedDataProvider &provider) +{ + std::string tableName = provider.ConsumeRandomLengthString(); + RdbPredicates predicates(tableName); + std::string joinTableName = provider.ConsumeRandomLengthString(); + predicates.LeftOuterJoin(joinTableName); +} + +void RdbPredicatesUsingFuzz(FuzzedDataProvider &provider) +{ + std::string tableName = provider.ConsumeRandomLengthString(); + RdbPredicates predicates(tableName); + std::vector fields = ConsumeRandomLengthStringVector(provider); + predicates.Using(fields); +} + +void RdbPredicatesOnFuzz(FuzzedDataProvider &provider) +{ + std::string tableName = provider.ConsumeRandomLengthString(); + RdbPredicates predicates(tableName); + std::vector clauses = ConsumeRandomLengthStringVector(provider); + predicates.On(clauses); +} + +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::RdbPredicatesCrossJoinFuzz(provider); + OHOS::RdbPredicatesInnerJoinFuzz(provider); + OHOS::RdbPredicatesLeftOuterJoinFuzz(provider); + OHOS::RdbPredicatesUsingFuzz(provider); + OHOS::RdbPredicatesOnFuzz(provider); + return 0; +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/rdbpredicates_fuzzer.h b/relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/rdbpredicates_fuzzer.h new file mode 100644 index 00000000..43733bba --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbpredicates_fuzzer/rdbpredicates_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 RDBPREDICATES_FUZZER_H +#define RDBPREDICATES_FUZZER_H + +#define FUZZ_PROJECT_NAME "rdbpredicates_fuzzer" + +#endif // RDBPREDICATES_FUZZER_H diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/BUILD.gn index 64301965..58bb5070 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/BUILD.gn +++ b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 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 @@ -15,13 +15,62 @@ import("//build/config/features.gni") import("//build/test.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("RdbRdUtilsFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdbrdutils_fuzzer" + + sources = [ + "${relational_store_native_path}/rdb/mock/src/rdb_fault_hiview_reporter.cpp", + "${relational_store_native_path}/rdb/src/grd_api_manager.cpp", + "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", + "${relational_store_native_path}/rdb/src/rd_statement.cpp", + "${relational_store_native_path}/rdb/src/rd_utils.cpp", + "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", + "rdbrdutils_fuzzer.cpp", + ] + + deps = [ + "${relational_store_innerapi_path}/appdatafwk:relational_common_base", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "json:nlohmann_json_static", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### group("fuzztest") { testonly = true - deps = [ - "rddbopen_fuzzer:fuzztest", - "rddbrepair_fuzzer:fuzztest", - "transfergrderrno_fuzzer:fuzztest", - "transfergrdtypetocoltype_fuzzer:fuzztest", + deps = [] + deps += [ + # deps file + ":RdbRdUtilsFuzzTest", ] } ############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/corpus/init new file mode 100644 index 00000000..65af8ee8 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rdbrdutils_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rdbrdutils_fuzzer.cpp new file mode 100644 index 00000000..c9341bfa --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rdbrdutils_fuzzer.cpp @@ -0,0 +1,132 @@ +/* + * 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 "rdbrdutils_fuzzer.h" + +#include + +#include "rd_utils.h" +#include "rdb_errno.h" +#include "rdb_store_config.h" +#include "rdb_store_impl.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +static const int MIN_BLOB_SIZE = 1; +static const int MAX_BLOB_SIZE = 200; + +GRD_DB *CreateDBHandle(FuzzedDataProvider &provider) +{ + GRD_DB *dbHandle = nullptr; + std::string dbPath = provider.ConsumeRandomLengthString(); + std::string configStr = provider.ConsumeRandomLengthString(); + uint32_t flags = provider.ConsumeIntegral(); + RdUtils::RdDbOpen(dbPath.c_str(), configStr.c_str(), flags, &dbHandle); + return dbHandle; +} + +GRD_SqlStmt *CreateSqlStmt(GRD_DB *dbHandle, FuzzedDataProvider &provider) +{ + GRD_SqlStmt *stmtHandle = nullptr; + std::string str = provider.ConsumeRandomLengthString(); + RdUtils::RdSqlPrepare(dbHandle, str.c_str(), str.size(), &stmtHandle, nullptr); + RdUtils::RdSqlReset(stmtHandle); + RdUtils::RdSqlFinalize(stmtHandle); + return stmtHandle; +} + +void RdSqlBindBlobFuzzTest(GRD_SqlStmt *stmtHandle, FuzzedDataProvider &provider) +{ + size_t blobSize = provider.ConsumeIntegralInRange(MIN_BLOB_SIZE, MAX_BLOB_SIZE); + void *val = static_cast(new uint8_t[blobSize]); + provider.ConsumeData(val, blobSize); + + uint32_t idx = provider.ConsumeIntegral(); + RdUtils::RdSqlBindBlob(stmtHandle, idx, val, blobSize, nullptr); + delete[] static_cast(val); + val = nullptr; +} + +void RdbRdUtilsFuzzer(FuzzedDataProvider &provider) +{ + GRD_DB *dbHandle = CreateDBHandle(provider); + + std::string dbPath = provider.ConsumeRandomLengthString(); + std::string configStr = provider.ConsumeRandomLengthString(); + RdUtils::RdDbRepair(dbPath.c_str(), configStr.c_str()); + + { + int err = provider.ConsumeIntegral(); + RdUtils::TransferGrdErrno(err); + } + + { + int err = provider.ConsumeIntegral(); + RdUtils::TransferGrdTypeToColType(err); + } + + GRD_SqlStmt *stmtHandle = CreateSqlStmt(dbHandle, provider); + RdSqlBindBlobFuzzTest(stmtHandle, provider); + + { + uint32_t idx = provider.ConsumeIntegral(); + std::string str = provider.ConsumeRandomLengthString(); + RdUtils::RdSqlBindText(stmtHandle, idx, str.c_str(), str.length(), nullptr); + } + + { + uint32_t idx = provider.ConsumeIntegral(); + int32_t val = provider.ConsumeIntegral(); + RdUtils::RdSqlBindInt(stmtHandle, idx, val); + } + + { + uint32_t idx = provider.ConsumeIntegral(); + int64_t val = provider.ConsumeIntegral(); + RdUtils::RdSqlBindInt64(stmtHandle, idx, val); + } + + { + uint32_t idx = provider.ConsumeIntegral(); + double val = provider.ConsumeFloatingPoint(); + RdUtils::RdSqlBindDouble(stmtHandle, idx, val); + } + + { + uint32_t idx = provider.ConsumeIntegral(); + RdUtils::RdSqlBindNull(stmtHandle, idx); + } + + { + float ftVec[1]; + ftVec[0] = provider.ConsumeFloatingPoint(); + uint32_t idx = provider.ConsumeIntegral(); + RdUtils::RdSqlBindFloatVector(stmtHandle, idx, ftVec, 1, nullptr); + } + + uint32_t flags = provider.ConsumeIntegral(); + RdUtils::RdDbClose(dbHandle, flags); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + /* Run your code on data */ + FuzzedDataProvider provider(data, size); + OHOS::RdbRdUtilsFuzzer(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rdbrdutils_fuzzer.h b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rdbrdutils_fuzzer.h new file mode 100644 index 00000000..1e4b22b2 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rdbrdutils_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 RDBRDUTILS_FUZZER_H +#define RDBRDUTILS_FUZZER_H + +#define FUZZ_PROJECT_NAME "rdutils_fuzzer" + +#endif // RDBRDUTILS_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/rddbopen_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/rddbopen_fuzzer.cpp deleted file mode 100644 index a4842364..00000000 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/rddbopen_fuzzer.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2022 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 "rd_utils.h" -#include "rdb_errno.h" -#include "rdb_store_config.h" -#include "rdb_store_impl.h" - -#define DOUBLE_SIZE 8 -#define INT_SIZE 4 - -using namespace OHOS; -using namespace OHOS::NativeRdb; -namespace OHOS { - -uint32_t ConvertToUint32(const uint8_t *ptr, size_t size) -{ - if (ptr == nullptr || (size < sizeof(uint32_t))) { - return 0; - } - return *(reinterpret_cast(ptr)); -} - -int32_t ConvertToInt32(const uint8_t *ptr, size_t size) -{ - if (ptr == nullptr || (size < sizeof(int32_t))) { - return 0; - } - return *(reinterpret_cast(ptr)); -} - -int64_t ConvertToInt64(const uint8_t *ptr, size_t size) -{ - if (ptr == nullptr || (size < sizeof(int64_t))) { - return 0; - } - return *(reinterpret_cast(ptr)); -} - -double ConvertToDouble(const uint8_t *ptr, size_t size) -{ - if (ptr == nullptr || size < DOUBLE_SIZE) { - return 0; - } - double fa = 0; - uint8_t uc[DOUBLE_SIZE]; - for (int i = 0; i < DOUBLE_SIZE; i++) { - uc[i] = ptr[i]; - } - errno_t err = memcpy_s(&fa, DOUBLE_SIZE, uc, DOUBLE_SIZE); - if (err < 0) { - return 0; - } - return fa; -} - -float ConvertToFloat(const uint8_t *ptr, size_t size) -{ - if (ptr == nullptr || size < INT_SIZE) { - return 0; - } - float fa = 0; - uint8_t uc[INT_SIZE]; - for (int i = 0; i < INT_SIZE; i++) { - uc[i] = ptr[i]; - } - errno_t err = memcpy_s(&fa, INT_SIZE, uc, INT_SIZE); - if (err < 0) { - return 0; - } - return fa; -} - -void RdDbOpenFuzzer(const uint8_t *data, size_t size) -{ - uint32_t unit32t = ConvertToUint32(data, size); - int32_t nit32t = ConvertToInt32(data, size); - int32_t nit64t = ConvertToInt64(data, size); - double doubleValue = ConvertToDouble(data, size); - GRD_DB *dbHandle_ = nullptr; - RdUtils::RdDbOpen(reinterpret_cast(data), reinterpret_cast(data), unit32t, &dbHandle_); - GRD_SqlStmt *stmtHandle = nullptr; - RdUtils::RdSqlPrepare(dbHandle_, reinterpret_cast(data), size, &stmtHandle, nullptr); - RdUtils::RdSqlReset(stmtHandle); - RdUtils::RdSqlFinalize(stmtHandle); - RdUtils::RdSqlBindBlob(stmtHandle, unit32t, static_cast(data), size, nullptr); - RdUtils::RdSqlBindText(stmtHandle, unit32t, static_cast(data), size, nullptr); - RdUtils::RdSqlBindInt(stmtHandle, unit32t, nit32t); - RdUtils::RdSqlBindInt64(stmtHandle, unit32t, nit64t); - RdUtils::RdSqlBindDouble(stmtHandle, unit32t, doubleValue); - RdUtils::RdSqlBindNull(stmtHandle, unit32t); - float ft = ConvertToFloat(data, size); - float ftVec[1]; - ftVec[0] = ft; - RdUtils::RdSqlBindFloatVector(stmtHandle, unit32t, ftVec, 1, nullptr); - RdUtils::RdDbClose(dbHandle_, unit32t); -} -} // namespace OHOS - -/* Fuzzer entry point */ -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - /* Run your code on data */ - OHOS::RdDbOpenFuzzer(data, size); - return 0; -} diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/BUILD.gn deleted file mode 100644 index 9ebe4ea4..00000000 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/BUILD.gn +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (c) 2022 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. - -#####################hydra-fuzz################### -import("//build/config/features.gni") -import("//build/test.gni") -import("//foundation/distributeddatamgr/relational_store/relational_store.gni") - -##############################fuzztest########################################## -ohos_fuzztest("RdbRdUtilsTransferGrdErrnoFuzzTest") { - module_out_path = "relational_store/relational_store" - - include_dirs = [ - "${relational_store_native_path}/rdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb/include", - "${common_tool_path}/", - "//third_party/sqlite/include", - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", - "${foundation_systemabilitymgr_path}/safwk/services/safwk/include", - "${foundation_systemabilitymgr_path}/samgr/interfaces/innerkits/samgr_proxy/include", - "${base_security_dataclassification_path}/interfaces/innerkits/datatransmitmgr/include", - "//third_party/json/single_include", - "//third_party/googletest/googletest/include/gtest", - ] - - cflags = [ - "-g", - "-O0", - "-Wno-unused-variable", - "-fno-omit-frame-pointer", - ] - - fuzz_config_file = "${relational_store_base_path}/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer" - - sources = [ "transfergrderrno_fuzzer.cpp" ] - - deps = [ - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb:distributeddb", - "${distributeddata_base_path}/relational_store/interfaces/inner_api/rdb:native_rdb_static", - "//third_party/jsoncpp:jsoncpp", - ] - - external_deps = [ - "ability_base:zuri", - "ability_runtime:dataobs_manager", - "c_utils:utils", - "hilog:libhilog", - "ipc:ipc_core", - ] -} - -############################################################################### -group("fuzztest") { - testonly = true - deps = [] - deps += [ - # deps file - ":RdbRdUtilsTransferGrdErrnoFuzzTest", - ] -} -############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/corpus/init deleted file mode 100644 index bc977bd9..00000000 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2022 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. - -FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/project.xml deleted file mode 100644 index 6e8ad2cf..00000000 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/transfergrderrno_fuzzer.h b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/transfergrderrno_fuzzer.h deleted file mode 100644 index 6f11ac7c..00000000 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrderrno_fuzzer/transfergrderrno_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2022 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 TRANSFER_GRD_FUZZER_H -#define TRANSFER_GRD_FUZZER_H - -#define FUZZ_PROJECT_NAME "transfergrderrno_fuzzer" - -#endif // TRANSFER_GRD_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/BUILD.gn deleted file mode 100644 index a897d983..00000000 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/BUILD.gn +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (c) 2022 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. - -#####################hydra-fuzz################### -import("//build/config/features.gni") -import("//build/test.gni") -import("//foundation/distributeddatamgr/relational_store/relational_store.gni") - -##############################fuzztest########################################## -ohos_fuzztest("TransferGrdTypeToColTypeFuzzTest") { - module_out_path = "relational_store/relational_store" - - include_dirs = [ - "${relational_store_native_path}/rdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb/include", - "${common_tool_path}/", - "//third_party/sqlite/include", - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", - "${foundation_systemabilitymgr_path}/safwk/services/safwk/include", - "${foundation_systemabilitymgr_path}/samgr/interfaces/innerkits/samgr_proxy/include", - "${base_security_dataclassification_path}/interfaces/innerkits/datatransmitmgr/include", - "//third_party/json/single_include", - "//third_party/googletest/googletest/include/gtest", - ] - - cflags = [ - "-g", - "-O0", - "-Wno-unused-variable", - "-fno-omit-frame-pointer", - ] - - fuzz_config_file = "${relational_store_base_path}/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer" - - sources = [ "transfergrdtypetocoltype_fuzzer.cpp" ] - - deps = [ - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb:distributeddb", - "${distributeddata_base_path}/relational_store/interfaces/inner_api/rdb:native_rdb_static", - "//third_party/jsoncpp:jsoncpp", - ] - - external_deps = [ - "ability_base:zuri", - "ability_runtime:dataobs_manager", - "c_utils:utils", - "hilog:libhilog", - "ipc:ipc_core", - ] -} - -############################################################################### -group("fuzztest") { - testonly = true - deps = [] - deps += [ - # deps file - ":TransferGrdTypeToColTypeFuzzTest", - ] -} -############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/project.xml deleted file mode 100644 index 6e8ad2cf..00000000 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/transfergrdtypetocoltype_fuzzer.h b/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/transfergrdtypetocoltype_fuzzer.h deleted file mode 100644 index 6ec5dc5d..00000000 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/transfergrdtypetocoltype_fuzzer/transfergrdtypetocoltype_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2022 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 TRANSFERGRDTYPETOCOLTYPE_FUZZER_H -#define TRANSFERGRDTYPETOCOLTYPE_FUZZER_H - -#define FUZZ_PROJECT_NAME "transfergrdtypetocoltype_fuzzer" - -#endif // TRANSFERGRDTYPETOCOLTYPE_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/BUILD.gn new file mode 100644 index 00000000..6856e786 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("rdbsqlutils_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/rdbsqlutils_fuzzer" + + sources = [ "rdbsqlutils_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":rdbsqlutils_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/corpus/init new file mode 100644 index 00000000..65af8ee8 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/rdbsqlutils_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/rdbsqlutils_fuzzer.cpp new file mode 100644 index 00000000..7d1e1cd2 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/rdbsqlutils_fuzzer.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 "rdbsqlutils_fuzzer.h" + +#include +#include +#include +#include + +#include +#include +#include + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +ConflictResolution GetConflictResolution(FuzzedDataProvider &provider) +{ + int min = static_cast(ConflictResolution::ON_CONFLICT_NONE); + int max = static_cast(ConflictResolution::ON_CONFLICT_REPLACE); + int enumInt = provider.ConsumeIntegralInRange(min, max); + ConflictResolution resolution = static_cast(enumInt); + return resolution; +} + +std::vector ConsumeRandomLengthValueObjectVector(FuzzedDataProvider &provider) +{ + const int loopsMin = 0; + const int loopsMax = 100; + size_t loops = provider.ConsumeIntegralInRange(loopsMin, loopsMax); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t value = provider.ConsumeIntegral(); + ValueObject obj(value); + columns.emplace_back(obj); + } + return columns; +} + +std::vector ConsumeRandomLengthStringVector(FuzzedDataProvider &provider) +{ + const int loopsMin = 0; + const int loopsMax = 100; + size_t loops = provider.ConsumeIntegralInRange(loopsMin, loopsMax); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t length = provider.ConsumeIntegral(); + auto bytes = provider.ConsumeBytes(length); + columns.emplace_back(bytes.begin(), bytes.end()); + } + return columns; +} + +// Fuzz CreateDirectory +void FuzzCreateDirectory(FuzzedDataProvider &provider) +{ + std::string databaseDir = provider.ConsumeRandomLengthString(); + RdbSqlUtils::CreateDirectory(databaseDir); +} + +// Fuzz GetDefaultDatabasePath +void FuzzGetDefaultDatabasePath(FuzzedDataProvider &provider) +{ + std::string baseDir = provider.ConsumeRandomLengthString(); + std::string name = provider.ConsumeRandomLengthString(); + std::string customDir = provider.ConsumeRandomLengthString(); + RdbSqlUtils::GetDefaultDatabasePath(baseDir, name, customDir); +} + +// Fuzz GetCustomDatabasePath +void FuzzGetCustomDatabasePath(FuzzedDataProvider &provider) +{ + std::string rootDir = provider.ConsumeRandomLengthString(); + std::string name = provider.ConsumeRandomLengthString(); + std::string customDir = provider.ConsumeRandomLengthString(); + RdbSqlUtils::GetCustomDatabasePath(rootDir, name, customDir); +} + +// Fuzz GetDefaultDatabasePath with errorCode +void FuzzGetDefaultDatabasePathWithErrorCode(FuzzedDataProvider &provider) +{ + std::string baseDir = provider.ConsumeRandomLengthString(); + std::string name = provider.ConsumeRandomLengthString(); + int errorCode = 0; + RdbSqlUtils::GetDefaultDatabasePath(baseDir, name, errorCode); +} + +// Fuzz BuildQueryString +void FuzzBuildQueryString(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(); + AbsRdbPredicates predicates(table); + std::vector columns = ConsumeRandomLengthStringVector(provider); + RdbSqlUtils::BuildQueryString(predicates, columns); +} + +// Fuzz GetInsertSqlInfo +void FuzzGetInsertSqlInfo(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(); + Row row; + ConflictResolution resolution = GetConflictResolution(provider); + RdbSqlUtils::GetInsertSqlInfo(table, row, resolution); +} + +// Fuzz GetUpdateSqlInfo +void FuzzGetUpdateSqlInfo(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(); + AbsRdbPredicates predicates(table); + Row row; + ConflictResolution resolution = GetConflictResolution(provider); + std::vector returningFields; + RdbSqlUtils::GetUpdateSqlInfo(predicates, row, resolution, returningFields); +} + +// Fuzz GetDeleteSqlInfo +void FuzzGetDeleteSqlInfo(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(); + AbsRdbPredicates predicates(table); + std::vector returningFields; + RdbSqlUtils::GetDeleteSqlInfo(predicates, returningFields); +} + +// Fuzz GetQuerySqlInfo +void FuzzGetQuerySqlInfo(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(); + AbsRdbPredicates predicates(table); + Fields columns = ConsumeRandomLengthStringVector(provider); + RdbSqlUtils::GetQuerySqlInfo(predicates, columns); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::FuzzCreateDirectory(provider); + OHOS::FuzzGetDefaultDatabasePath(provider); + OHOS::FuzzGetCustomDatabasePath(provider); + OHOS::FuzzGetDefaultDatabasePathWithErrorCode(provider); + OHOS::FuzzBuildQueryString(provider); + OHOS::FuzzGetInsertSqlInfo(provider); + OHOS::FuzzGetUpdateSqlInfo(provider); + OHOS::FuzzGetDeleteSqlInfo(provider); + OHOS::FuzzGetQuerySqlInfo(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/rdbsqlutils_fuzzer.h b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/rdbsqlutils_fuzzer.h new file mode 100644 index 00000000..6d46e084 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/rdbsqlutils_fuzzer/rdbsqlutils_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 RDBSQLUTILS_FUZZER_H +#define RDBSQLUTILS_FUZZER_H + +#define FUZZ_PROJECT_NAME "rdbsqlutils_fuzzer" + +#endif // RDBSQLUTILS_FUZZER_H diff --git a/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/BUILD.gn index a30acba3..10a36912 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/BUILD.gn +++ b/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 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 @@ -34,9 +34,17 @@ ohos_fuzztest("RdbStoreFuzzTest") { sources = [ "rdbstore_fuzzer.cpp" ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", "hilog:libhilog", - "relational_store:native_rdb", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", ] } diff --git a/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/corpus/init index bc977bd9..65af8ee8 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/corpus/init +++ b/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/corpus/init @@ -1,4 +1,4 @@ -# Copyright (c) 2022 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 diff --git a/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/project.xml index 6e8ad2cf..66e1dcac 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/project.xml +++ b/relational_store/test/native/rdb/fuzztest/rdbstore_fuzzer/project.xml @@ -1,5 +1,5 @@ - + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/returning_fuzzer/returning_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/returning_fuzzer/returning_fuzzer.cpp new file mode 100644 index 00000000..66b4c39c --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/returning_fuzzer/returning_fuzzer.cpp @@ -0,0 +1,317 @@ +/* + * 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 "rdb_errno.h" +#define LOG_TAG "RETURNING_FUZZER" +#include "returning_fuzzer.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "abs_predicates.h" +#include "abs_rdb_predicates.h" +#include "connection_pool.h" +#include "logger.h" +#include "trans_db.h" +#include "value_object.h" +#include "values_buckets.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; + +namespace OHOS { + +static const int MIN_BLOB_SIZE = 1; +static const int MAX_BLOB_SIZE = 200; +static const std::string TABLE_NAME = "test"; +static const std::string DATABASE_NAME = "/data/test/returningFuzz.db"; +static const std::string CREATE_TABLE_SQL = + "CREATE TABLE IF NOT EXISTS test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"; + +class ReturningFuzzTest { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + + static std::shared_ptr store_; +}; + +class RdbTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +std::shared_ptr ReturningFuzzTest::store_ = nullptr; + +int RdbTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_SQL); +} + +int RdbTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void ReturningFuzzTest::SetUpTestCase(void) +{ + int errCode = E_OK; + RdbStoreConfig config(DATABASE_NAME); + config.SetSecurityLevel(SecurityLevel::S3); + config.SetBundleName("com.example.returningfuzz"); + RdbTestOpenCallback helper; + ReturningFuzzTest::store_ = RdbHelper::GetRdbStore(config, 1, helper, errCode); + + if (store_ == nullptr || errCode != E_OK) { + return; + } +} + +void ReturningFuzzTest::TearDownTestCase(void) +{ + if (RdbHelper::DeleteRdbStore(DATABASE_NAME) != E_OK) { + return; + } +} + +std::vector GetColumns(FuzzedDataProvider &provider, int max = 10, int min = 1) +{ + std::vector columns; + int colCount = provider.ConsumeIntegralInRange(min, max); + for (int i = 0; i < colCount; i++) { + columns.push_back(provider.ConsumeRandomLengthString()); + } + return columns; +} + +ValuesBucket MakeRandomBucket(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + size_t strLength = provider.ConsumeIntegralInRange(1, 16); + int fieldCount = provider.ConsumeIntegralInRange(1, 5); + for (int i = 0; i < fieldCount; ++i) { + std::string key = provider.ConsumeRandomLengthString(strLength); + int type = provider.ConsumeIntegralInRange(0, 2); + if (type == 0) { + bucket.Put(key, provider.ConsumeIntegral()); + } else if (type == 1) { + bucket.Put(key, provider.ConsumeRandomLengthString(strLength)); + } else { + int blobSize = provider.ConsumeIntegralInRange(MIN_BLOB_SIZE, MAX_BLOB_SIZE); + std::vector blob = + provider.ConsumeBytes(provider.ConsumeIntegralInRange(0, blobSize)); + bucket.PutBlob(key, blob); + } + } + return bucket; +} + +Transaction::TransactionType GetRandomTransactionType(FuzzedDataProvider &provider) +{ + return provider.PickValueInArray({ + Transaction::DEFERRED, + Transaction::IMMEDIATE, + Transaction::EXCLUSIVE + }); +} + +ConflictResolution GetRandomConflictResolution(FuzzedDataProvider &provider) +{ + return provider.PickValueInArray({ + ConflictResolution::ON_CONFLICT_NONE, + ConflictResolution::ON_CONFLICT_ROLLBACK, + ConflictResolution::ON_CONFLICT_ABORT, + ConflictResolution::ON_CONFLICT_REPLACE, + ConflictResolution::ON_CONFLICT_IGNORE, + ConflictResolution::ON_CONFLICT_FAIL + }); +} + +void BatchInsertReturningFuzz(FuzzedDataProvider &provider, std::shared_ptr store) +{ + std::string valName = provider.ConsumeRandomLengthString(); + int valAge = provider.ConsumeIntegral(); + double valSalary = provider.ConsumeFloatingPoint(); + + ValuesBuckets rows; + ValuesBucket value; + value.PutString("name", valName); + value.PutInt("age", valAge); + value.PutDouble("salary", valSalary); + rows.Put(value); + + size_t blobSize = provider.ConsumeIntegralInRange(MIN_BLOB_SIZE, MAX_BLOB_SIZE); + std::vector blobData = provider.ConsumeBytes(blobSize); + value.PutBlob("blobType", blobData); + + auto resolution = GetRandomConflictResolution(provider); + + auto columns = GetColumns(provider); + auto [codeReturning, result] = store->BatchInsert(TABLE_NAME, rows, columns, resolution); + + auto [ret, trans] = store->CreateTransaction(GetRandomTransactionType(provider)); + + if (ret != E_OK || trans == nullptr) { + LOG_ERROR("Failed to create transaction, error code: %{public}d", ret); + return; + } + + trans->BatchInsert(TABLE_NAME, rows, columns, resolution); + + trans->Commit(); +} + +void UpdateReturningFuzz(FuzzedDataProvider &provider, std::shared_ptr store) +{ + std::string valName = provider.ConsumeRandomLengthString(); + int valAge = provider.ConsumeIntegral(); + double valSalary = provider.ConsumeFloatingPoint(); + + ValuesBucket values; + values.PutString("name", valName); + values.PutInt("age", valAge); + values.PutDouble("salary", valSalary); + + size_t blobSize = provider.ConsumeIntegralInRange(MIN_BLOB_SIZE, MAX_BLOB_SIZE); + std::vector blobData = provider.ConsumeBytes(blobSize); + values.PutBlob("blobType", blobData); + + AbsRdbPredicates predicates(TABLE_NAME); + predicates.EqualTo("name", ValueObject(provider.ConsumeRandomLengthString())); + auto returningFields = GetColumns(provider); + + store->Update(values, predicates, returningFields); + + auto [ret, trans] = store->CreateTransaction(GetRandomTransactionType(provider)); + + if (ret != E_OK || trans == nullptr) { + LOG_ERROR("Failed to create transaction, error code: %{public}d", ret); + return; + } + + AbsRdbPredicates predicates2(TABLE_NAME); + predicates2.EqualTo("name", ValueObject(provider.ConsumeRandomLengthString())); + auto returningFields2 = GetColumns(provider); + + trans->Update(values, predicates2, returningFields2); + trans->Commit(); +} + +void DeleteReturningFuzz(FuzzedDataProvider &provider, std::shared_ptr store) +{ + AbsRdbPredicates predicates(TABLE_NAME); + predicates.EqualTo("name", ValueObject(provider.ConsumeRandomLengthString())); + auto returningFields = GetColumns(provider); + + store->Delete(predicates, returningFields); + + auto [ret, trans] = store->CreateTransaction(GetRandomTransactionType(provider)); + + if (ret != E_OK || trans == nullptr) { + LOG_ERROR("Failed to create transaction, error code: %{public}d", ret); + return; + } + AbsRdbPredicates predicates2(TABLE_NAME); + predicates2.EqualTo("name", ValueObject(provider.ConsumeRandomLengthString())); + auto returningFields2 = GetColumns(provider); + trans->Delete(predicates2, returningFields2); + trans->Rollback(); +} + +void ExecuteExtReturningFuzz(FuzzedDataProvider &provider, std::shared_ptr store) +{ + std::string sql = provider.ConsumeRandomLengthString(); + + std::vector bindArgs; + bindArgs.push_back(ValueObject(provider.ConsumeIntegral())); + bindArgs.push_back(ValueObject(provider.ConsumeRandomLengthString())); + bindArgs.push_back(ValueObject(provider.ConsumeIntegral())); + bindArgs.push_back(ValueObject(provider.ConsumeFloatingPoint())); + + size_t blobSize = provider.ConsumeIntegralInRange(MIN_BLOB_SIZE, MAX_BLOB_SIZE); + std::vector blobData = provider.ConsumeBytes(blobSize); + bindArgs.push_back(ValueObject(blobData)); + + auto returning = provider.PickValueInArray({ + "id", + "name", + "age", + "salary", + }); + + store->ExecuteExt("INSERT INTO test(id, name, age, salary) VALUES (?, ?, ?, ?) returning " + returning, bindArgs); + store->ExecuteExt("UPDATE test set name = ? where name = ? RETURNING " + returning, bindArgs); + store->ExecuteExt("DELETE FROM test where name = ? RETURNING " + returning, bindArgs); + + auto [ret, trans] = store->CreateTransaction(GetRandomTransactionType(provider)); + + if (ret != E_OK || trans == nullptr) { + LOG_ERROR("Failed to create transaction, error code: %{public}d", ret); + return; + } + + trans->ExecuteExt("INSERT INTO test(id, name, age, salary) VALUES (?, ?, ?, ?) returning " + returning, bindArgs); + trans->ExecuteExt("UPDATE test set name = ? where name = ? RETURNING " + returning, bindArgs); + trans->ExecuteExt("DELETE FROM test where name = ? RETURNING " + returning, bindArgs); + trans->Rollback(); +} + +void ValuesBucketFuzz(FuzzedDataProvider &provider) +{ + int rowCount = provider.ConsumeIntegralInRange(0, 10); + std::vector buckets; + for (int i = 0; i < rowCount; ++i) { + buckets.push_back(MakeRandomBucket(provider)); + } + + ValuesBuckets vb1; + ValuesBuckets vb2(buckets); + ValuesBuckets vb3(std::move(buckets)); + + for (int i = 0; i < rowCount; ++i) { + vb1.Put(MakeRandomBucket(provider)); + } + + vb1.RowSize(); + std::string field = provider.ConsumeRandomLengthString(); + vb1.GetFieldsAndValues(); + int32_t size = static_cast(provider.ConsumeIntegral()); + vb1.Reserve(size); + vb1.Clear(); +} + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::ReturningFuzzTest::SetUpTestCase(); + OHOS::BatchInsertReturningFuzz(provider, ReturningFuzzTest::store_); + OHOS::UpdateReturningFuzz(provider, ReturningFuzzTest::store_); + OHOS::DeleteReturningFuzz(provider, ReturningFuzzTest::store_); + OHOS::ExecuteExtReturningFuzz(provider, ReturningFuzzTest::store_); + OHOS::ValuesBucketFuzz(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/returning_fuzzer/returning_fuzzer.h b/relational_store/test/native/rdb/fuzztest/returning_fuzzer/returning_fuzzer.h new file mode 100644 index 00000000..c6881a3c --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/returning_fuzzer/returning_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 RETURNING_FUZZER_H +#define RETURNING_FUZZER_H + +#define FUZZ_PROJECT_NAME "returning_fuzzer" + +#endif // RETURNING_FUZZER_H diff --git a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/BUILD.gn similarity index 50% rename from relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/BUILD.gn rename to relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/BUILD.gn index 772d2847..1664e10f 100644 --- a/relational_store/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer/BUILD.gn +++ b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2025 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -17,27 +17,12 @@ import("//build/test.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") ##############################fuzztest########################################## -ohos_fuzztest("RddbopenFuzzTest") { +ohos_fuzztest("SharedBlockFuzzTest") { module_out_path = "relational_store/relational_store" include_dirs = [ "${relational_store_native_path}/rdb/include", - "${relational_store_innerapi_path}/rdb/include", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb", - "${distributeddata_base_path}/kv_store/frameworks/innerkitsimpl/rdb/include", - "${common_tool_path}/", - "//third_party/sqlite/include", - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", - "${foundation_systemabilitymgr_path}/safwk/services/safwk/include", - "${foundation_systemabilitymgr_path}/samgr/interfaces/innerkits/samgr_proxy/include", - "${base_security_dataclassification_path}/interfaces/innerkits/datatransmitmgr/include", - "//third_party/json/single_include", - "//third_party/googletest/googletest/include/gtest", + "${relational_store_common_path}/include", ] cflags = [ @@ -47,14 +32,13 @@ ohos_fuzztest("RddbopenFuzzTest") { "-fno-omit-frame-pointer", ] - fuzz_config_file = "${relational_store_base_path}/test/native/rdb/fuzztest/rdbrdutils_fuzzer/rddbopen_fuzzer" + fuzz_config_file = "${relational_store_base_path}/test/native/rdb/fuzztest/sharedblock_fuzzer" - sources = [ "rddbopen_fuzzer.cpp" ] + sources = [ "sharedblock_fuzzer.cpp" ] deps = [ - "${distributeddata_base_path}/kv_store/frameworks/libs/distributeddb:distributeddb", - "${distributeddata_base_path}/relational_store/interfaces/inner_api/rdb:native_rdb_static", - "//third_party/jsoncpp:jsoncpp", + "${relational_store_innerapi_path}/rdb:native_rdb", + "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", ] external_deps = [ @@ -63,6 +47,10 @@ ohos_fuzztest("RddbopenFuzzTest") { "c_utils:utils", "hilog:libhilog", "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", ] } @@ -72,7 +60,7 @@ group("fuzztest") { deps = [] deps += [ # deps file - ":RddbopenFuzzTest", + ":SharedBlockFuzzTest", ] } ############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/corpus/init new file mode 100644 index 00000000..65af8ee8 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/sharedblock_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/sharedblock_fuzzer.cpp new file mode 100644 index 00000000..0d29ad97 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/sharedblock_fuzzer.cpp @@ -0,0 +1,159 @@ +/* + * 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 "sharedblock_fuzzer.h" + +#include + +#include "ashmem.h" +#include "rd_statement.h" +#include "rdb_errno.h" +#include "rdb_store_config.h" +#include "rdb_store_impl.h" +#include "refbase.h" +#include "shared_block.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +static const size_t DEFAULT_BLOCK_SIZE = 1 * 1024 * 1024; +static const int MIN_BLOB_SIZE = 1; +static const int MAX_BLOB_SIZE = 200; +namespace OHOS { + +void SharedBlockPutFuzz(std::shared_ptr sharedBlock, FuzzedDataProvider &provider) +{ + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + int64_t value = provider.ConsumeIntegral(); + sharedBlock->PutLong(row, column, value); + } + + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + double value = provider.ConsumeFloatingPoint(); + sharedBlock->PutDouble(row, column, value); + } + + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + size_t size = provider.ConsumeIntegralInRange(MIN_BLOB_SIZE, MAX_BLOB_SIZE); + std::vector value = provider.ConsumeBytes(size); + sharedBlock->PutAsset(row, column, value.data(), value.size()); + } + + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + size_t size = provider.ConsumeIntegralInRange(MIN_BLOB_SIZE, MAX_BLOB_SIZE); + std::vector value = provider.ConsumeBytes(size); + sharedBlock->PutAssets(row, column, value.data(), value.size()); + } + + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + float item = provider.ConsumeFloatingPoint(); + std::vector value; + value.push_back(item); + sharedBlock->PutFloats(row, column, value.data(), value.size()); + } + + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + int value = provider.ConsumeIntegral(); + ValueObject bigIntItem(value); + std::vector bigIntList; + bigIntList.push_back(bigIntItem); + sharedBlock->PutBigInt(row, column, bigIntList.data(), bigIntList.size()); + } +} + +void SharedBlockFuzz(FuzzedDataProvider &provider) +{ + AppDataFwk::SharedBlock *block = nullptr; + std::string sharedBlockName = "SharedBlockFuzzTestBlock"; + auto errcode = AppDataFwk::SharedBlock::Create(sharedBlockName, DEFAULT_BLOCK_SIZE, block); + if (errcode != AppDataFwk::SharedBlock::SHARED_BLOCK_OK) { + return; + } + std::shared_ptr sharedBlock = std::shared_ptr(block); + + // Prepare a dummy CellUnit + AppDataFwk::SharedBlock::CellUnit cellUnit; + cellUnit.type = provider.ConsumeIntegral(); // Arbitrary type + cellUnit.cell.stringOrBlobValue.offset = provider.ConsumeIntegral(); + cellUnit.cell.stringOrBlobValue.size = provider.ConsumeIntegral(); + + uint32_t numColumns = provider.ConsumeIntegral(); + sharedBlock->SetColumnNum(numColumns); + sharedBlock->AllocRow(); + sharedBlock->FreeLastRow(); + + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + size_t blobSize = provider.ConsumeIntegralInRange(MIN_BLOB_SIZE, MAX_BLOB_SIZE); + std::vector blobData = provider.ConsumeBytes(blobSize); + sharedBlock->PutBlob(row, column, blobData.data(), blobData.size()); + } + + { + size_t outSizeIncludingNull = 0; + sharedBlock->GetCellUnitValueString(&cellUnit, &outSizeIncludingNull); + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + std::string value = provider.ConsumeRandomLengthString(); + size_t sizeIncludingNull = provider.ConsumeIntegral(); + sharedBlock->PutString(row, column, value.c_str(), sizeIncludingNull); + } + SharedBlockPutFuzz(sharedBlock, provider); + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + sharedBlock->PutNull(row, column); + } + + { + uint32_t row = provider.ConsumeIntegral(); + uint32_t column = provider.ConsumeIntegral(); + sharedBlock->GetCellUnit(row, column); + } + // Fuzz GetUsedBytes + sharedBlock->GetUsedBytes(); + + // Fuzz GetCellUnitValueBlob + size_t blobSize = 0; + sharedBlock->GetCellUnitValueBlob(&cellUnit, &blobSize); + + // Fuzz Size + sharedBlock->Size(); + + // Fuzz SetRawData + std::vector remaining_data = provider.ConsumeRemainingBytes(); + sharedBlock->SetRawData(remaining_data.data(), remaining_data.size()); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + /* Run your code on data */ + FuzzedDataProvider provider(data, size); + OHOS::SharedBlockFuzz(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/sharedblock_fuzzer.h b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/sharedblock_fuzzer.h new file mode 100644 index 00000000..91a29763 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/sharedblock_fuzzer/sharedblock_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 SHAREDBLOCK_FUZZER_H +#define SHAREDBLOCK_FUZZER_H + +#define FUZZ_PROJECT_NAME "sharedblock_fuzzer" + +#endif // RDSTATEMENT_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/BUILD.gn new file mode 100644 index 00000000..c423d891 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("storeconfig_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/storeconfig_fuzzer" + + sources = [ "storeconfig_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":storeconfig_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/corpus/init new file mode 100644 index 00000000..65af8ee8 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/storeconfig_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/storeconfig_fuzzer.cpp new file mode 100644 index 00000000..aff9ab1e --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/storeconfig_fuzzer.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 "storeconfig_fuzzer.h" + +#include + +#include + +#include "rdb_store_config.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +void FuzzSetPath(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + std::string path = provider.ConsumeRandomLengthString(); + config.SetPath(path); +} + +void FuzzSetJournalMode(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + JournalMode min = JournalMode::MODE_DELETE; + int intValueMin = static_cast(min); + + JournalMode max = JournalMode::MODE_OFF; + int intValueMax = static_cast(max); + + JournalMode journalMode = static_cast(provider.ConsumeIntegralInRange(intValueMin, intValueMax)); + config.SetJournalMode(journalMode); +} + +void FuzzSetReadOnly(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + bool readOnly = provider.ConsumeBool(); + config.SetReadOnly(readOnly); +} + +void FuzzSetStorageMode(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + StorageMode min = StorageMode::MODE_MEMORY; + int intValueMin = static_cast(min); + + StorageMode max = StorageMode::MODE_DISK; + int intValueMax = static_cast(max); + + StorageMode storageMode = static_cast(provider.ConsumeIntegralInRange(intValueMin, intValueMax)); + config.SetStorageMode(storageMode); +} + +void FuzzSetDatabaseFileType(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + DatabaseFileType min = DatabaseFileType::NORMAL; + int intValueMin = static_cast(min); + + DatabaseFileType max = DatabaseFileType::CORRUPT; + int intValueMax = static_cast(max); + + DatabaseFileType databaseFileType = + static_cast(provider.ConsumeIntegralInRange(intValueMin, intValueMax)); + config.SetDatabaseFileType(databaseFileType); +} + +void FuzzSetSecurityLevel(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + SecurityLevel min = SecurityLevel::S1; + int intValueMin = static_cast(min); + + SecurityLevel max = SecurityLevel::S4; + int intValueMax = static_cast(max); + + SecurityLevel securityLevel = + static_cast(provider.ConsumeIntegralInRange(intValueMin, intValueMax)); + config.SetSecurityLevel(securityLevel); +} + +void FuzzSetCreateNecessary(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + bool isCreateNecessary = provider.ConsumeBool(); + config.SetCreateNecessary(isCreateNecessary); +} + +void FuzzSetTokenizer(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + Tokenizer min = Tokenizer::NONE_TOKENIZER; + int intValueMin = static_cast(min); + + Tokenizer max = Tokenizer::TOKENIZER_END; + int intValueMax = static_cast(max); + + Tokenizer tokenizer = static_cast(provider.ConsumeIntegralInRange(intValueMin, intValueMax)); + config.SetTokenizer(tokenizer); +} + +void FuzzSetEncryptKey(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + const int min = 0; + const int max = 100; + std::vector encryptKey(provider.ConsumeIntegralInRange(min, max)); + config.SetEncryptKey(encryptKey); +} + +void FuzzSetEncryptAlgo(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + EncryptAlgo min = EncryptAlgo::AES_256_GCM; + int intValueMin = static_cast(min); + + EncryptAlgo max = EncryptAlgo::AES_256_CBC; + int intValueMax = static_cast(max); + + EncryptAlgo encryptAlgo = static_cast(provider.ConsumeIntegralInRange(intValueMin, intValueMax)); + config.SetEncryptAlgo(encryptAlgo); +} + +void FuzzSetJournalSize(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + const int min = 1; + const int max = 1024 * 1024; + int journalSize = provider.ConsumeIntegralInRange(min, max); + config.SetJournalSize(journalSize); +} + +void FuzzSetPageSize(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + const int min = 1; + const int max = 4096; + int pageSize = provider.ConsumeIntegralInRange(min, max); + config.SetPageSize(pageSize); +} + +void FuzzSetScalarFunction(FuzzedDataProvider &provider, RdbStoreConfig &config) +{ + std::string functionName = provider.ConsumeRandomLengthString(); + const int min = 1; + const int max = 5; + int argc = provider.ConsumeIntegralInRange(min, max); + ScalarFunction function = [](const std::vector &args) -> std::string { + return args.empty() ? "" : args[0]; + }; + config.SetScalarFunction(functionName, argc, function); +} + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + + // Generate random inputs + std::string path = provider.ConsumeRandomLengthString(); + int intValueMin = static_cast(StorageMode::MODE_MEMORY); + int intValueMax = static_cast(StorageMode::MODE_DISK); + StorageMode storageMode = static_cast(provider.ConsumeIntegralInRange(intValueMin, intValueMax)); + bool readOnly = provider.ConsumeBool(); + const int min = 0; + const int max = 100; + std::vector encryptKey(provider.ConsumeIntegralInRange(min, max)); + std::string journalMode = provider.ConsumeRandomLengthString(); + std::string syncMode = provider.ConsumeRandomLengthString(); + std::string databaseFileType = provider.ConsumeRandomLengthString(); + SecurityLevel securityLevel = static_cast( + provider.ConsumeIntegralInRange(static_cast(SecurityLevel::S1), static_cast(SecurityLevel::S4))); + bool isCreateNecessary = provider.ConsumeBool(); + bool autoCheck = provider.ConsumeBool(); + const int journalSizeMin = 1; + const int journalSizeMax = 1024 * 1024; + int journalSize = provider.ConsumeIntegralInRange(journalSizeMin, journalSizeMax); + const int pageSizeMin = 1; + const int pageSizeMax = 1024 * 1024; + int pageSize = provider.ConsumeIntegralInRange(pageSizeMin, pageSizeMax); + + RdbStoreConfig config(path, storageMode, readOnly, encryptKey, journalMode, syncMode, databaseFileType, + securityLevel, isCreateNecessary, autoCheck, journalSize, pageSize); + + // Fuzzing individual methods + OHOS::FuzzSetPath(provider, config); + OHOS::FuzzSetJournalMode(provider, config); + OHOS::FuzzSetReadOnly(provider, config); + OHOS::FuzzSetStorageMode(provider, config); + OHOS::FuzzSetDatabaseFileType(provider, config); + OHOS::FuzzSetSecurityLevel(provider, config); + OHOS::FuzzSetCreateNecessary(provider, config); + OHOS::FuzzSetTokenizer(provider, config); + OHOS::FuzzSetEncryptKey(provider, config); + OHOS::FuzzSetEncryptAlgo(provider, config); + OHOS::FuzzSetJournalSize(provider, config); + OHOS::FuzzSetPageSize(provider, config); + OHOS::FuzzSetScalarFunction(provider, config); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/storeconfig_fuzzer.h b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/storeconfig_fuzzer.h new file mode 100644 index 00000000..c8925a74 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/storeconfig_fuzzer/storeconfig_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 STORECONFIG_FUZZER_H +#define STORECONFIG_FUZZER_H + +#define FUZZ_PROJECT_NAME "storeconfig_fuzzer" + +#endif // STORECONFIG_FUZZER_H diff --git a/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/BUILD.gn new file mode 100644 index 00000000..8b447b8d --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("TransactionFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/transaction_fuzzer" + + sources = [ "transaction_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":TransactionFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/corpus/init new file mode 100644 index 00000000..65af8ee8 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/transaction_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/transaction_fuzzer.cpp new file mode 100644 index 00000000..bbc2797f --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/transaction_fuzzer.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 "transaction_fuzzer.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "connection_pool.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "trans_db.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +static const std::string RDB_PATH = "/data/test/transactionFuzzTest.db"; +static const std::string CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, " + "blobType BLOB)"; + +class TransactionTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +int TransactionTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_TEST); +} + +int TransactionTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void TransactionCommitFailFuzzTest(FuzzedDataProvider &provider) +{ + RdbHelper::DeleteRdbStore(RDB_PATH); + RdbStoreConfig config(RDB_PATH); + config.SetHaMode(HAMode::MAIN_REPLICA); + config.SetReadOnly(false); + TransactionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + if (store == nullptr || errCode != E_OK) { + return; + } + + store->Execute("DROP TABLE IF EXISTS test1"); + auto res = store->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)"); + if (res.first != E_OK) { + return; + } + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + if (transaction == nullptr || ret != E_OK) { + return; + } + + Transaction::Row row; + row.Put("id", provider.ConsumeIntegral()); + row.Put("name", provider.ConsumeRandomLengthString()); + auto result = transaction->Insert("test1", row); + const int count = 1; + if (result.first != E_OK || result.second != count) { + return; + } + + // Constructing a Commit Failure Scenario + std::string walFile = RDB_PATH + "-wal"; + + // Disabling wal File Operations + std::string chattrAddiCmd = "chattr +i " + walFile; + system(chattrAddiCmd.c_str()); + + ret = transaction->Commit(); + if (ret == E_OK) { + return; + } + + // Enable the wal file operation. + std::string chattrSubiCmd = "chattr -i " + walFile; + system(chattrSubiCmd.c_str()); + + RdbHelper::DeleteRdbStore(RDB_PATH); +} +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::TransactionCommitFailFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/transaction_fuzzer.h b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/transaction_fuzzer.h new file mode 100644 index 00000000..b6a1ea64 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transaction_fuzzer/transaction_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 TRANSACTION_FUZZER_H +#define TRANSACTION_FUZZER_H + +#define FUZZ_PROJECT_NAME "transaction_fuzzer" + +#endif // TRANSACTION_FUZZER_H diff --git a/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/BUILD.gn new file mode 100644 index 00000000..79a8c13a --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/BUILD.gn @@ -0,0 +1,67 @@ +# 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("TransDBFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/transdb_fuzzer" + + sources = [ "transdb_fuzzer.cpp" ] + + deps = [ + "${relational_store_innerapi_path}/rdb:native_rdb", + "${relational_store_innerapi_path}/rdb:native_rdb_static", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:datamgr_common", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":TransDBFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/corpus/init new file mode 100644 index 00000000..44d06ec6 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/corpus/init @@ -0,0 +1 @@ +# 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. FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/transdb_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/transdb_fuzzer.cpp new file mode 100644 index 00000000..0ea460f9 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/transdb_fuzzer.cpp @@ -0,0 +1,134 @@ +/* + * 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 "transdb_fuzzer.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include "connection_pool.h" +#include "trans_db.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +namespace OHOS { + +static constexpr const char *CREATE_TABLE = "CREATE TABLE IF NOT EXISTS TEST (id INT PRIMARY KEY, name TEXT, " + "extend BLOB, code REAL, years UNLIMITED INT, attachment ASSET, " + "attachments ASSETS)"; +static constexpr const char *DROP_TABLE = "DROP TABLE IF EXISTS TEST"; +static constexpr const char *TABLE_NAME = "TEST"; +static const int MIN_ROWS_SIZE = 1; +static const int MAX_ROWS_SIZE = 50; + +void FillDataToValuesBucket(FuzzedDataProvider &provider, ValuesBucket &value) +{ + std::string valName = provider.ConsumeRandomLengthString(); + int valAge = provider.ConsumeIntegral(); + double valSalary = provider.ConsumeFloatingPoint(); + + value.PutString("name", valName); + value.PutInt("age", valAge); + value.PutDouble("salary", valSalary); +} + +void FillDataToValuesBuckets(FuzzedDataProvider &provider, ValuesBuckets &values) +{ + uint32_t loopTimes = provider.ConsumeIntegralInRange(MIN_ROWS_SIZE, MAX_ROWS_SIZE); + for (uint32_t i = 0; i < loopTimes; i++) { + ValuesBucket value; + FillDataToValuesBucket(provider, value); + values.Put(value); + } +} + +void TransDbExecuteFuzzTest(std::shared_ptr transDB, FuzzedDataProvider &provider) +{ + if (transDB == nullptr) { + return; + } + transDB->Execute(DROP_TABLE); + transDB->Execute(CREATE_TABLE); + std::string sql = provider.ConsumeRandomLengthString(); + transDB->Execute(sql); +} + +ConflictResolution GetConflictResolution(FuzzedDataProvider &provider) +{ + int min = static_cast(ConflictResolution::ON_CONFLICT_NONE); + int max = static_cast(ConflictResolution::ON_CONFLICT_REPLACE); + int enumInt = provider.ConsumeIntegralInRange(min, max); + ConflictResolution resolution = static_cast(enumInt); + return resolution; +} + +void TransDbInsertFuzzTest(std::shared_ptr transDB, FuzzedDataProvider &provider) +{ + if (transDB == nullptr) { + return; + } + ValuesBucket value; + FillDataToValuesBucket(provider, value); + + { + ConflictResolution resolution = GetConflictResolution(provider); + transDB->Insert(TABLE_NAME, value, resolution); + } + + ValuesBuckets rows; + FillDataToValuesBuckets(provider, rows); + transDB->BatchInsert(TABLE_NAME, rows); + + { + ConflictResolution resolution = GetConflictResolution(provider); + transDB->BatchInsert(TABLE_NAME, rows, resolution); + } +} + +void TransDbFuzzTest(FuzzedDataProvider &provider) +{ + std::string path = provider.ConsumeRandomLengthString(); + RdbStoreConfig config(path); + config.SetHaMode(provider.ConsumeIntegral()); + int errCode = 0; + std::shared_ptr connPool = ConnectionPool::Create(config, errCode); + if (connPool == nullptr) { + return; + } + auto [err, conn] = connPool->CreateTransConn(); + if (err != E_OK || conn == nullptr) { + return; + } + std::shared_ptr transDB = std::make_shared(conn, config.GetName()); + if (transDB == nullptr) { + return; + } + TransDbExecuteFuzzTest(transDB, provider); + TransDbInsertFuzzTest(transDB, provider); +} + +} // namespace OHOS + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::TransDbFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/transdb_fuzzer.h b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/transdb_fuzzer.h new file mode 100644 index 00000000..1305c5bd --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/transdb_fuzzer/transdb_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 TRANSDB_FUZZER_H +#define TRANSDB_FUZZER_H + +#define FUZZ_PROJECT_NAME "transdb_fuzzer" + +#endif // TRANSDB_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/BUILD.gn new file mode 100644 index 00000000..3900a099 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("valueobject_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/valueobject_fuzzer" + + sources = [ "valueobject_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":valueobject_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/corpus/init new file mode 100644 index 00000000..65af8ee8 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/valueobject_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/valueobject_fuzzer.cpp new file mode 100644 index 00000000..f7f52424 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/valueobject_fuzzer.cpp @@ -0,0 +1,168 @@ +/* + * 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 "valueobject_fuzzer.h" + +#include + +#include "value_object.h" + +#define LOOPS_MIN 0 +#define LOOPS_MAX 100 + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +namespace OHOS { +std::vector ConsumeRandomLengthAssetValueVector(FuzzedDataProvider &provider) +{ + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + uint32_t status = provider.ConsumeIntegralInRange( + AssetValue::Status::STATUS_UNKNOWN, AssetValue::Status::STATUS_BUTT); + AssetValue asset{ + .version = provider.ConsumeIntegral(), + .status = status, + .expiresTime = provider.ConsumeIntegral(), + .id = provider.ConsumeRandomLengthString(), + .name = provider.ConsumeRandomLengthString(), + .uri = provider.ConsumeRandomLengthString(), + .createTime = provider.ConsumeRandomLengthString(), + .modifyTime = provider.ConsumeRandomLengthString(), + .size = provider.ConsumeRandomLengthString(), + .hash = provider.ConsumeRandomLengthString(), + .path = provider.ConsumeRandomLengthString(), + }; + columns.emplace_back(asset); + } + return columns; +} + +std::vector ConsumeFloatingPointVector(FuzzedDataProvider &provider) +{ + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + float value = provider.ConsumeFloatingPoint(); + columns.push_back(value); + } + return columns; +} + +void ValueObjectGetIntFuzz(FuzzedDataProvider &provider) +{ + int32_t value = provider.ConsumeIntegral(); + ValueObject obj(value); + int val; + obj.GetInt(val); +} + +void ValueObjectGetLongFuzz(FuzzedDataProvider &provider) +{ + int64_t value = provider.ConsumeIntegral(); + ValueObject obj(value); + int64_t val; + obj.GetLong(val); +} + +void ValueObjectGetDoubleFuzz(FuzzedDataProvider &provider) +{ + double value = provider.ConsumeFloatingPoint(); + ValueObject obj(value); + double val; + obj.GetDouble(val); +} + +void ValueObjectGetBoolFuzz(FuzzedDataProvider &provider) +{ + bool value = provider.ConsumeBool(); + ValueObject obj(value); + bool val; + obj.GetBool(val); +} + +void ValueObjectGetStringFuzz(FuzzedDataProvider &provider) +{ + std::string value = provider.ConsumeRandomLengthString(); + ValueObject obj(value); + std::string val; + obj.GetString(val); +} + +void ValueObjectGetBlobFuzz(FuzzedDataProvider &provider) +{ + size_t length = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector blob = provider.ConsumeBytes(length); + ValueObject obj(blob); + std::vector val; + obj.GetBlob(val); +} + +void ValueObjectGetAssetFuzz(FuzzedDataProvider &provider) +{ + uint32_t status = + provider.ConsumeIntegralInRange(AssetValue::Status::STATUS_UNKNOWN, AssetValue::Status::STATUS_BUTT); + AssetValue asset{ + .version = provider.ConsumeIntegral(), + .status = status, + .expiresTime = provider.ConsumeIntegral(), + .id = provider.ConsumeRandomLengthString(), + .name = provider.ConsumeRandomLengthString(), + .uri = provider.ConsumeRandomLengthString(), + .createTime = provider.ConsumeRandomLengthString(), + .modifyTime = provider.ConsumeRandomLengthString(), + .size = provider.ConsumeRandomLengthString(), + .hash = provider.ConsumeRandomLengthString(), + .path = provider.ConsumeRandomLengthString(), + }; + + ValueObject obj(asset); + AssetValue val; + obj.GetAsset(val); +} + +void ValueObjectGetAssetsFuzz(FuzzedDataProvider &provider) +{ + std::vector assets = ConsumeRandomLengthAssetValueVector(provider); + ValueObject obj(assets); + std::vector val; + obj.GetAssets(val); +} + +void ValueObjectGetVecsFuzz(FuzzedDataProvider &provider) +{ + std::vector vecs = ConsumeFloatingPointVector(provider); + ValueObject obj(vecs); + std::vector val; + obj.GetVecs(val); +} + +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::ValueObjectGetIntFuzz(provider); + OHOS::ValueObjectGetLongFuzz(provider); + OHOS::ValueObjectGetDoubleFuzz(provider); + OHOS::ValueObjectGetBoolFuzz(provider); + OHOS::ValueObjectGetStringFuzz(provider); + OHOS::ValueObjectGetBlobFuzz(provider); + OHOS::ValueObjectGetAssetFuzz(provider); + OHOS::ValueObjectGetAssetsFuzz(provider); + OHOS::ValueObjectGetVecsFuzz(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/valueobject_fuzzer.h b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/valueobject_fuzzer.h new file mode 100644 index 00000000..7e51b02b --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valueobject_fuzzer/valueobject_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 VALUEOBJECT_FUZZER_H +#define VALUEOBJECT_FUZZER_H + +#define FUZZ_PROJECT_NAME "valueobject_fuzzer" + +#endif // VALUEOBJECT_FUZZER_H diff --git a/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/BUILD.gn new file mode 100644 index 00000000..f2636071 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("valuesbucket_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/valuesbucket_fuzzer" + + sources = [ "valuesbucket_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":valuesbucket_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/corpus/init new file mode 100644 index 00000000..65af8ee8 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/valuesbucket_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/valuesbucket_fuzzer.cpp new file mode 100644 index 00000000..d86ef735 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/valuesbucket_fuzzer.cpp @@ -0,0 +1,157 @@ +/* + * 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 "valuesbucket_fuzzer.h" + +#include + +#include "value_object.h" +#include "values_bucket.h" + + +#define LOOPS_MIN 0 +#define LOOPS_MAX 100 + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +namespace OHOS { + +void ValuesBucketPutStringFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + std::string value = provider.ConsumeRandomLengthString(); + bucket.PutString(columnName, value); +} + +void ValuesBucketPutIntFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + int value = provider.ConsumeIntegral(); + bucket.PutInt(columnName, value); +} + +void ValuesBucketPutLongFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + int64_t value = provider.ConsumeIntegral(); + bucket.PutLong(columnName, value); +} + +void ValuesBucketPutDoubleFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + double value = provider.ConsumeFloatingPoint(); + bucket.PutDouble(columnName, value); +} + +void ValuesBucketPutBoolFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + bool value = provider.ConsumeBool(); + bucket.PutBool(columnName, value); +} + +void ValuesBucketPutBlobFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + size_t length = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector value = provider.ConsumeBytes(length); + bucket.PutBlob(columnName, value); +} + +void ValuesBucketPutNullFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + bucket.PutNull(columnName); +} + +void ValuesBucketPutValueObjectFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + ValueObject value(provider.ConsumeIntegral()); + bucket.Put(columnName, value); +} + +void ValuesBucketPutValueObjectMoveFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + ValueObject value(provider.ConsumeIntegral()); + bucket.Put(columnName, std::move(value)); +} + +void ValuesBucketDeleteFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + bucket.Delete(columnName); +} + +void ValuesBucketGetObjectFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + ValueObject value(provider.ConsumeIntegral()); + bucket.Put(columnName, value); + ValueObject output; + bucket.GetObject(columnName, output); +} + +void ValuesBucketHasColumnFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + bucket.HasColumn(columnName); +} + +void ValuesBucketGetAllFuzz(FuzzedDataProvider &provider) +{ + ValuesBucket bucket; + std::string columnName = provider.ConsumeRandomLengthString(); + ValueObject value(provider.ConsumeIntegral()); + bucket.Put(columnName, value); + std::map output; + bucket.GetAll(output); +} + +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::ValuesBucketPutStringFuzz(provider); + OHOS::ValuesBucketPutIntFuzz(provider); + OHOS::ValuesBucketPutLongFuzz(provider); + OHOS::ValuesBucketPutDoubleFuzz(provider); + OHOS::ValuesBucketPutBoolFuzz(provider); + OHOS::ValuesBucketPutBlobFuzz(provider); + OHOS::ValuesBucketPutNullFuzz(provider); + OHOS::ValuesBucketPutValueObjectFuzz(provider); + OHOS::ValuesBucketPutValueObjectMoveFuzz(provider); + OHOS::ValuesBucketDeleteFuzz(provider); + OHOS::ValuesBucketGetObjectFuzz(provider); + OHOS::ValuesBucketHasColumnFuzz(provider); + OHOS::ValuesBucketGetAllFuzz(provider); + return 0; +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/valuesbucket_fuzzer.h b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/valuesbucket_fuzzer.h new file mode 100644 index 00000000..4c598ba9 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbucket_fuzzer/valuesbucket_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 VALUESBUCKET_FUZZER_H +#define VALUESBUCKET_FUZZER_H + +#define FUZZ_PROJECT_NAME "valuesbucket_fuzzer" + +#endif // VALUESBUCKET_FUZZER_H diff --git a/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/BUILD.gn b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/BUILD.gn new file mode 100644 index 00000000..eb74a7ac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("valuesbuckets_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_native_path}/rdb/include", + "${relational_store_common_path}/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "-fno-access-control", # Ignore Private Member Access Control + ] + + fuzz_config_file = + "${relational_store_base_path}/test/native/rdb/fuzztest/valuesbuckets_fuzzer" + + sources = [ "valuesbuckets_fuzzer.cpp" ] + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":valuesbuckets_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/corpus/init b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/corpus/init new file mode 100644 index 00000000..65af8ee8 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/project.xml b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/valuesbuckets_fuzzer.cpp b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/valuesbuckets_fuzzer.cpp new file mode 100644 index 00000000..b85c1c35 --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/valuesbuckets_fuzzer.cpp @@ -0,0 +1,107 @@ +/* + * 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 "valuesbuckets_fuzzer.h" + +#include + +#include "value_object.h" +#include "values_bucket.h" +#include "values_buckets.h" + +#define LOOPS_MIN 0 +#define LOOPS_MAX 10 + +using namespace OHOS; +using namespace OHOS::NativeRdb; + +namespace OHOS { + +std::vector ConsumeRandomLengthValueObjectVector(FuzzedDataProvider &provider) +{ + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t value = provider.ConsumeIntegral(); + ValueObject obj(value); + columns.emplace_back(obj); + } + return columns; +} + +std::vector ConsumeRandomLengthStringVector(FuzzedDataProvider &provider) +{ + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + int32_t length = provider.ConsumeIntegral(); + auto bytes = provider.ConsumeBytes(length); + columns.emplace_back(bytes.begin(), bytes.end()); + } + return columns; +} + +void ValuesBucketsReserveFuzz(FuzzedDataProvider &provider) +{ + ValuesBuckets buckets; + int32_t size = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + buckets.Reserve(size); +} + +void ValuesBucketsPutFuzz(FuzzedDataProvider &provider) +{ + ValuesBuckets buckets; + std::vector fields = ConsumeRandomLengthStringVector(provider); + std::vector values = ConsumeRandomLengthValueObjectVector(provider); + size_t loopsNum = fields.size(); + if (loopsNum > values.size()) { + loopsNum = values.size(); + } + ValuesBucket bucket; + for (size_t i = 0; i < loopsNum; i++) { + bucket.Put(fields[i], values[i]); + } + buckets.Put(bucket); +} + +void ValuesBucketsGetFuzz(FuzzedDataProvider &provider) +{ + ValuesBuckets buckets; + std::vector fields = ConsumeRandomLengthStringVector(provider); + std::vector values = ConsumeRandomLengthValueObjectVector(provider); + size_t loopsNum = fields.size(); + if (loopsNum > values.size()) { + loopsNum = values.size(); + } + ValuesBucket bucket; + for (size_t i = 0; i < loopsNum; ++i) { + bucket.Put(fields[i], values[i]); + } + buckets.Put(bucket); + size_t row = provider.ConsumeIntegral(); + std::string field = provider.ConsumeRandomLengthString(); + buckets.Get(row, field); +} + +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::ValuesBucketsReserveFuzz(provider); + OHOS::ValuesBucketsPutFuzz(provider); + OHOS::ValuesBucketsGetFuzz(provider); + return 0; +} diff --git a/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/valuesbuckets_fuzzer.h b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/valuesbuckets_fuzzer.h new file mode 100644 index 00000000..724fa86b --- /dev/null +++ b/relational_store/test/native/rdb/fuzztest/valuesbuckets_fuzzer/valuesbuckets_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 VALUESBUCKETS_FUZZER_H +#define VALUESBUCKETS_FUZZER_H + +#define FUZZ_PROJECT_NAME "valuesbuckets_fuzzer" + +#endif // VALUESBUCKETS_FUZZER_H diff --git a/relational_store/test/native/rdb/mock/connection_mock.h b/relational_store/test/native/rdb/mock/connection_mock.h new file mode 100644 index 00000000..57511a6e --- /dev/null +++ b/relational_store/test/native/rdb/mock/connection_mock.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 OHOS_CONNECTION_MOCK_H +#define OHOS_CONNECTION_MOCK_H + +#include "connection.h" + +namespace DistributedDB { +class StoreObserver; +} +namespace OHOS::NativeRdb { +class RdbStoreConfig; +class Statement; +class MockConnection : public Connection { +public: + using Info = DistributedRdb::RdbDebugInfo; + using SConn = std::shared_ptr; + using Stmt = std::shared_ptr; + using Notifier = std::function; + using Creator = std::pair (*)(const RdbStoreConfig &config, bool isWriter); + using Repairer = int32_t (*)(const RdbStoreConfig &config); + using Deleter = int32_t (*)(const RdbStoreConfig &config); + using Collector = std::map (*)(const RdbStoreConfig &config); + using Restorer = int32_t (*)(const RdbStoreConfig &config, const std::string &srcPath, const std::string &destPath); + using ReplicaChecker = int32_t (*)(const RdbStoreConfig &config); + + MOCK_METHOD(int32_t, VerifyAndRegisterHook, (const RdbStoreConfig &config), (override)); + MOCK_METHOD((std::pair), CreateStatement, (const std::string &sql, SConn conn), (override)); + MOCK_METHOD((std::pair), CreateReplicaStatement, + (const std::string &sql, SConn conn), (override)); + MOCK_METHOD(int, CheckReplicaForRestore, (), (override)); + MOCK_METHOD(int32_t, Rekey, (const RdbStoreConfig::CryptoParam &cryptoParam), (override)); + MOCK_METHOD(int32_t, GetDBType, (), (const, override)); + MOCK_METHOD(bool, IsWriter, (), (const, override)); + MOCK_METHOD(int32_t, ResetKey, (const RdbStoreConfig &config), (override)); + MOCK_METHOD(int32_t, TryCheckPoint, (bool timeout), (override)); + MOCK_METHOD(int32_t, LimitWalSize, (), (override)); + MOCK_METHOD(int32_t, ConfigLocale, (const std::string &localeStr), (override)); + MOCK_METHOD(int32_t, CleanDirtyData, (const std::string &table, uint64_t cursor), (override)); + MOCK_METHOD(int32_t, SubscribeTableChanges, (const Notifier ¬ifier), (override)); + MOCK_METHOD(int32_t, GetMaxVariable, (), (const, override)); + MOCK_METHOD(int32_t, GetJournalMode, (), (override)); + MOCK_METHOD(int32_t, ClearCache, (bool isForceClear), (override)); + MOCK_METHOD(int32_t, Subscribe, (const std::shared_ptr &observer), (override)); + MOCK_METHOD(int32_t, Unsubscribe, (const std::shared_ptr &observer), (override)); + MOCK_METHOD(int32_t, Backup, + (const std::string &databasePath, const std::vector &destEncryptKey, bool isAsync, + std::shared_ptr slaveStatus, bool verifyDb), + (override)); + MOCK_METHOD(int32_t, Restore, + (const std::string &databasePath, const std::vector &destEncryptKey, + std::shared_ptr slaveStatus), + (override)); + MOCK_METHOD(ExchangeStrategy, GenerateExchangeStrategy, (std::shared_ptr status, + bool isReplay), (override)); + MOCK_METHOD(int, SetKnowledgeSchema, (const DistributedRdb::RdbKnowledgeSchema &schema), (override)); + MOCK_METHOD(int, CleanDirtyLog, (const std::string &table, uint64_t cursor), (override)); + MOCK_METHOD(int, RegisterAlgo, (const std::string &clstAlgoName, ClusterAlgoFunc func), (override)); +}; +} // namespace OHOS::NativeRdb +#endif // OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_INCLUDE_CONNECTION_H diff --git a/relational_store/test/native/rdb/mock/dataobs_mgr_client_mock.cpp b/relational_store/test/native/rdb/mock/dataobs_mgr_client_mock.cpp new file mode 100644 index 00000000..9b89dd62 --- /dev/null +++ b/relational_store/test/native/rdb/mock/dataobs_mgr_client_mock.cpp @@ -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. + */ +#include "dataobs_mgr_client_mock.h" + +namespace OHOS { +namespace AAFwk { +std::shared_ptr DataObsMgrClient::GetInstance() +{ + if (IDataObsMgrClient::dataObsMgrClient == nullptr) { + return nullptr; + } + return IDataObsMgrClient::dataObsMgrClient->GetInstance(); +} + +ErrCode DataObsMgrClient::NotifyChange(const Uri &uri, int userId, DataObsOption opt) +{ + if (IDataObsMgrClient::dataObsMgrClient == nullptr) { + return DATAOBS_SERVICE_NOT_CONNECTED; + } + return IDataObsMgrClient::dataObsMgrClient->NotifyChange(uri, userId, opt); +} +} // namespace AAFwk +} // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb_device_manager_adapter/include/rdb_device_manager_adapter.h b/relational_store/test/native/rdb/mock/dataobs_mgr_client_mock.h similarity index 42% rename from relational_store/frameworks/native/rdb_device_manager_adapter/include/rdb_device_manager_adapter.h rename to relational_store/test/native/rdb/mock/dataobs_mgr_client_mock.h index 7d0929e4..d5835c17 100644 --- a/relational_store/frameworks/native/rdb_device_manager_adapter/include/rdb_device_manager_adapter.h +++ b/relational_store/test/native/rdb/mock/dataobs_mgr_client_mock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2021 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,35 +13,29 @@ * limitations under the License. */ -#ifndef RDB_DEVICE_MANAGER_ADAPTER_H -#define RDB_DEVICE_MANAGER_ADAPTER_H +#ifndef OHOS_ABILITY_RUNTIME_DATAOBS_MGR_CLIENT_MOCK_H +#define OHOS_ABILITY_RUNTIME_DATAOBS_MGR_CLIENT_MOCK_H -#include "device_manager.h" -#include "device_manager_callback.h" +#include + +#include "dataobs_mgr_client.h" namespace OHOS { -namespace DeviceManagerAdaptor { -class RdbDeviceManagerAdaptor { +namespace AAFwk { +class IDataObsMgrClient { public: - static RdbDeviceManagerAdaptor &GetInstance(const std::string &packageName); - int GetEncryptedUuidByNetworkId(const std::string &networkId, std::string &uuid); - -private: - RdbDeviceManagerAdaptor(const std::string &packageName); - ~RdbDeviceManagerAdaptor(); + IDataObsMgrClient(){}; + virtual ~IDataObsMgrClient(){}; + virtual ErrCode NotifyChange(const Uri &uri, int32_t userId = -1, DataObsOption opt = DataObsOption()) = 0; + virtual std::shared_ptr GetInstance() = 0; - void Init(); - void UnInit(); - - std::string packageName_; + static inline std::shared_ptr dataObsMgrClient = nullptr; }; - -class InitDeviceManagerCallback final : public DistributedHardware::DmInitCallback { +class MockDataObsMgrClient : public IDataObsMgrClient { public: - InitDeviceManagerCallback() {}; - ~InitDeviceManagerCallback() {}; - void OnRemoteDied() override {}; + MOCK_METHOD((std::shared_ptr), GetInstance, (), (override)); + MOCK_METHOD(ErrCode, NotifyChange, (const Uri &uri, int32_t userId, DataObsOption opt), (override)); }; -} // namespace DeviceManagerAdaptor +} // namespace AAFwk } // namespace OHOS -#endif // RDB_DEVICE_MANAGER_ADAPTER_H +#endif \ No newline at end of file diff --git a/relational_store/test/native/rdb/mock/rdb_manager_impl_mock.cpp b/relational_store/test/native/rdb/mock/rdb_manager_impl_mock.cpp new file mode 100644 index 00000000..70812462 --- /dev/null +++ b/relational_store/test/native/rdb/mock/rdb_manager_impl_mock.cpp @@ -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. + */ + +#include "rdb_manager_impl_mock.h" +namespace OHOS::DistributedRdb { + +RdbManagerImpl::RdbManagerImpl() +{ +} + +RdbManagerImpl::~RdbManagerImpl() +{ +} + +RdbManagerImpl &RdbManagerImpl::GetInstance() +{ + static RdbManagerImpl manager; + return manager; +} +std::pair> RdbManagerImpl::GetRdbService(const RdbSyncerParam ¶m) +{ + if (BRdbManagerImpl::rdbManagerImpl == nullptr) { + return { NativeRdb::E_ERROR, nullptr }; + } + return BRdbManagerImpl::rdbManagerImpl->GetRdbService(param); +} +} // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/relational_store/test/native/rdb/mock/rdb_manager_impl_mock.h b/relational_store/test/native/rdb/mock/rdb_manager_impl_mock.h new file mode 100644 index 00000000..ec047185 --- /dev/null +++ b/relational_store/test/native/rdb/mock/rdb_manager_impl_mock.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 DISTRIBUTED_RDB_RDB_MANAGER_MOCK_H +#define DISTRIBUTED_RDB_RDB_MANAGER_MOCK_H + +#include + +#include "rdb_manager_impl.h" +namespace OHOS::DistributedRdb { +class BRdbManagerImpl { +public: + BRdbManagerImpl() = default; + virtual ~BRdbManagerImpl() = default; + virtual std::pair> GetRdbService(const RdbSyncerParam ¶m) = 0; + +public: + static inline std::shared_ptr rdbManagerImpl = nullptr; +}; +class MockRdbManagerImpl : public BRdbManagerImpl { +public: + MOCK_METHOD( + (std::pair>), GetRdbService, (const RdbSyncerParam ¶m), (override)); +}; +} // namespace OHOS::DistributedRdb +#endif \ No newline at end of file diff --git a/relational_store/test/native/rdb/mock/rdb_service_mock.h b/relational_store/test/native/rdb/mock/rdb_service_mock.h new file mode 100644 index 00000000..13952d09 --- /dev/null +++ b/relational_store/test/native/rdb/mock/rdb_service_mock.h @@ -0,0 +1,91 @@ +/* + * 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 DISTRIBUTED_RDB_RDB_SERVICE_MOCK_H +#define DISTRIBUTED_RDB_RDB_SERVICE_MOCK_H + +#include + +#include "iremote_object.h" +#include "rdb_service.h" + +namespace OHOS { +namespace DistributedRdb { +class MockRdbService : public RdbService { +public: + MOCK_METHOD(std::string, ObtainDistributedTableName, + (const RdbSyncerParam ¶m, const std::string &device, const std::string &table), (override)); + MOCK_METHOD(int32_t, SetDistributedTables, + (const RdbSyncerParam ¶m, const std::vector &tables, const std::vector &references, + bool isRebuild, int32_t type), + (override)); + MOCK_METHOD(int32_t, Sync, + (const RdbSyncerParam ¶m, const Option &option, const PredicatesMemo &predicates, const AsyncDetail &async), + (override)); + MOCK_METHOD(int32_t, Subscribe, + (const RdbSyncerParam ¶m, const SubscribeOption &option, std::shared_ptr observer), + (override)); + MOCK_METHOD(int32_t, UnSubscribe, + (const RdbSyncerParam ¶m, const SubscribeOption &option, std::shared_ptr observer), + (override)); + MOCK_METHOD(int32_t, RegisterAutoSyncCallback, + (const RdbSyncerParam ¶m, std::shared_ptr observer), (override)); + MOCK_METHOD(int32_t, UnregisterAutoSyncCallback, + (const RdbSyncerParam ¶m, std::shared_ptr observer), (override)); + MOCK_METHOD((std::pair>), RemoteQuery, + (const RdbSyncerParam ¶m, const std::string &device, const std::string &sql, + const std::vector &selectionArgs), + (override)); + MOCK_METHOD(int32_t, InitNotifier, (const RdbSyncerParam ¶m, sptr notifier), (override)); + + MOCK_METHOD(int32_t, BeforeOpen, (RdbSyncerParam & param), (override)); + + MOCK_METHOD(int32_t, AfterOpen, (const RdbSyncerParam ¶m), (override)); + + MOCK_METHOD(int32_t, Delete, (const RdbSyncerParam ¶m), (override)); + + MOCK_METHOD((std::pair>), QuerySharingResource, + (const RdbSyncerParam ¶m, const PredicatesMemo &predicates, const std::vector &columns), + (override)); + + MOCK_METHOD(int32_t, NotifyDataChange, + (const RdbSyncerParam ¶m, const RdbChangedData &rdbChangedData, const RdbNotifyConfig &rdbNotifyConfig), + (override)); + + MOCK_METHOD(int32_t, SetSearchable, (const RdbSyncerParam ¶m, bool isSearchable), (override)); + + MOCK_METHOD(int32_t, Disable, (const RdbSyncerParam ¶m), (override)); + + MOCK_METHOD(int32_t, Enable, (const RdbSyncerParam ¶m), (override)); + + MOCK_METHOD( + int32_t, GetPassword, (const RdbSyncerParam ¶m, std::vector> &password), (override)); + + MOCK_METHOD((std::pair), LockCloudContainer, (const RdbSyncerParam ¶m), (override)); + + MOCK_METHOD(int32_t, UnlockCloudContainer, (const RdbSyncerParam ¶m), (override)); + + MOCK_METHOD(int32_t, GetDebugInfo, + (const RdbSyncerParam ¶m, (std::map & debugInfo)), (override)); + + MOCK_METHOD(int32_t, GetDfxInfo, (const RdbSyncerParam ¶m, RdbDfxInfo &dfxInfo), (override)); + + MOCK_METHOD(int32_t, VerifyPromiseInfo, (const RdbSyncerParam ¶m), (override)); + + MOCK_METHOD(int32_t, ReportStatistic, (const RdbSyncerParam ¶m, const RdbStatEvent &statEvent), (override)); +}; +} // namespace DistributedRdb +} // namespace OHOS +#endif \ No newline at end of file diff --git a/relational_store/test/native/rdb/mock/statement_mock.h b/relational_store/test/native/rdb/mock/statement_mock.h new file mode 100644 index 00000000..966bb9b6 --- /dev/null +++ b/relational_store/test/native/rdb/mock/statement_mock.h @@ -0,0 +1,51 @@ +/* + * 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 OHOS_STATEMENT_MOCK_H +#define OHOS_STATEMENT_MOCK_H + +#include + +#include "statement.h" + +namespace OHOS::NativeRdb { +struct SharedBlockInfo; +class MockStatement : public Statement { +public: + MOCK_METHOD(int32_t, Prepare, (const std::string &sql), (override)); + MOCK_METHOD(int32_t, Bind, (const std::vector &args), (override)); + MOCK_METHOD((std::pair), Count, (), (override)); + MOCK_METHOD(int32_t, Step, (), (override)); + MOCK_METHOD(int32_t, Reset, (), (override)); + MOCK_METHOD(int32_t, Finalize, (), (override)); + MOCK_METHOD(int32_t, Execute, (const std::vector &args), (override)); + MOCK_METHOD(int32_t, Execute, (const std::vector> &args), (override)); + MOCK_METHOD((std::pair), ExecuteForValue, (const std::vector &args), (override)); + MOCK_METHOD(int32_t, Changes, (), (const, override)); + MOCK_METHOD(int64_t, LastInsertRowId, (), (const, override)); + MOCK_METHOD(int32_t, GetColumnCount, (), (const, override)); + MOCK_METHOD((std::pair), GetColumnName, (int32_t index), (const, override)); + MOCK_METHOD((std::pair), GetColumnType, (int32_t index), (const, override)); + MOCK_METHOD((std::pair), GetSize, (int32_t index), (const, override)); + MOCK_METHOD((std::pair), GetColumn, (int32_t index), (const, override)); + MOCK_METHOD((std::pair>), GetRows, (uint32_t maxCount), (override)); + MOCK_METHOD(bool, ReadOnly, (), (const, override)); + MOCK_METHOD(bool, SupportBlockInfo, (), (const, override)); + MOCK_METHOD(int32_t, FillBlockInfo, (SharedBlockInfo * info), (const, override)); + MOCK_METHOD(int, ModifyLockStatus, + (const std::string &table, const std::vector> &hashKeys, bool isLock), (override)); +}; +} // namespace OHOS::NativeRdb +#endif // OHOS_STATEMENT_MOCK_H diff --git a/relational_store/test/native/rdb/unittest/connection_test.cpp b/relational_store/test/native/rdb/unittest/connection_test.cpp index dbe45772..cd33a26e 100644 --- a/relational_store/test/native/rdb/unittest/connection_test.cpp +++ b/relational_store/test/native/rdb/unittest/connection_test.cpp @@ -20,9 +20,15 @@ #include #include +#include "common.h" #include "grd_type_export.h" #include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "rdb_store.h" #include "rdb_store_config.h" +#include "sqlite_connection.h" +#include "sqlite_global_config.h" using namespace testing::ext; using namespace OHOS::NativeRdb; @@ -32,10 +38,29 @@ class ConnectionTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); - void SetUp(void) {}; - void TearDown(void) {}; + void SetUp(void){}; + void TearDown(void){}; + static const std::string rdbStorePath; }; +const std::string ConnectionTest::rdbStorePath = RDB_TEST_PATH + "connection_ut_test.db"; + +class ConnectionTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +int ConnectionTestOpenCallback::OnCreate(RdbStore &store) +{ + return E_OK; +} + +int ConnectionTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + void ConnectionTest::SetUpTestCase(void) { } @@ -51,7 +76,8 @@ void ConnectionTest::TearDownTestCase(void) */ HWTEST_F(ConnectionTest, Connection_Test_001, TestSize.Level1) { - RdbStoreConfig config("/data/test/connection_ut_test.db"); + SqliteGlobalConfig::InitSqliteGlobalConfig(); + RdbStoreConfig config(rdbStorePath); config.SetDBType(OHOS::NativeRdb::DBType::DB_BUTT); auto [errCode, connection] = Connection::Create(config, true); EXPECT_EQ(errCode, E_INVALID_ARGS); @@ -70,7 +96,7 @@ HWTEST_F(ConnectionTest, Connection_Test_001, TestSize.Level1) */ HWTEST_F(ConnectionTest, Connection_Test_002, TestSize.Level1) { - RdbStoreConfig config("/data/test/connection_ut_test.db"); + RdbStoreConfig config(rdbStorePath); config.SetDBType(OHOS::NativeRdb::DBType::DB_BUTT); int ret = Connection::Repair(config); EXPECT_EQ(ret, E_INVALID_ARGS); @@ -79,4 +105,184 @@ HWTEST_F(ConnectionTest, Connection_Test_002, TestSize.Level1) ret = Connection::Repair(config); EXPECT_EQ(ret, E_NOT_SUPPORT); } + +/** + * @tc.name: SetEncryptAgo_Test_001 + * @tc.desc: The test case is to test whether the param is available. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, SetEncryptAgo_Test_001, TestSize.Level2) +{ + int errCode; + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, true); + config.SetIter(-1); + errCode = conn->SetEncryptAgo(config); + EXPECT_EQ(errCode, E_INVALID_ARGS); +} + +/** + * @tc.name: ResetKey_Test_001 + * @tc.desc: The test case is to test whether ResetKey is a write connection. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, ReSetKey_Test_001, TestSize.Level2) +{ + int errCode; + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, false); + errCode = conn->ResetKey(config); + EXPECT_EQ(errCode, E_OK); +} + +/** + * @tc.name: SetEncrypt_Test_001 + * @tc.desc: The test case is to test whether SetEncrypt is a memory RDB. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, SetEncrypt_Test_001, TestSize.Level2) +{ + int errCode; + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, true); + config.SetEncryptStatus(true); + config.SetStorageMode(StorageMode::MODE_MEMORY); + errCode = conn->SetEncrypt(config); + EXPECT_EQ(errCode, E_NOT_SUPPORT); +} + +/** + * @tc.name: RegDefaultFunctions_Test_001 + * @tc.desc: The testCase of RegDefaultFunctions. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, RegDefaultFunctions_Test_001, TestSize.Level2) +{ + int errCode; + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, true); + errCode = conn->RegDefaultFunctions(nullptr); + EXPECT_EQ(errCode, SQLITE_OK); +} + +/** + * @tc.name: SetTokenizer_Test_001 + * @tc.desc: The testCase of SetTokenizer. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, SetTokenizer_Test_001, TestSize.Level2) +{ + int errCode; + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, true); + config.SetTokenizer(TOKENIZER_END); + errCode = conn->SetTokenizer(config); + EXPECT_EQ(errCode, E_INVALID_ARGS); +} + +/** + * @tc.name: Backup_Test_001 + * @tc.desc: The testCase of Backup. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, Backup_Test_001, TestSize.Level2) +{ + int errCode; + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, true); + std::shared_ptr slaveStatus = std::make_shared(SlaveStatus::BACKING_UP); + errCode = conn->Backup("test", { 1, 2, 3 }, true, slaveStatus); + EXPECT_EQ(errCode, E_OK); + EXPECT_EQ(*slaveStatus, BACKING_UP); +} + +/** + * @tc.name: ExchangeVerify_Test_001 + * @tc.desc: The testCase of ExchangeVerify. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, ExchangeVerify_Test_001, TestSize.Level2) +{ + int errCode; + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, true); + errCode = conn->ExchangeVerify(false); + EXPECT_EQ(errCode, E_ALREADY_CLOSED); +} + +/** + * @tc.name: VeritySlaveIntegrity_Test_001 + * @tc.desc: The testCase of VeritySlaveIntegrity. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, VeritySlaveIntegrity_Test_001, TestSize.Level2) +{ + int errCode; + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, true); + errCode = conn->VeritySlaveIntegrity(); + EXPECT_EQ(errCode, E_ALREADY_CLOSED); +} + +/** + * @tc.name: IsDbVersionBelowSlave_Test_001 + * @tc.desc: The testCase of IsDbVersionBelowSlave. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, IsDbVersionBelowSlave_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(rdbStorePath); + auto conn = std::make_shared(config, true); + bool res = conn->IsDbVersionBelowSlave(); + EXPECT_EQ(res, false); +} + +/** + * @tc.name: CheckReplicaIntegrity_Test_001 + * @tc.desc: The testCase of CheckReplicaIntegrity. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, CheckReplicaIntegrity_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(rdbStorePath); + config.SetDBType(OHOS::NativeRdb::DBType::DB_BUTT); + EXPECT_EQ(Connection::CheckReplicaIntegrity(config), E_INVALID_ARGS); + + config.SetDBType(OHOS::NativeRdb::DBType::DB_VECTOR); + EXPECT_EQ(Connection::CheckReplicaIntegrity(config), E_NOT_SUPPORT); +} + +/** + * @tc.name: CheckReplicaIntegrity_Test_002 + * @tc.desc: The testCase of CheckReplicaIntegrity. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, CheckReplicaIntegrity_Test_002, TestSize.Level2) +{ + RdbHelper::DeleteRdbStore(rdbStorePath); + RdbStoreConfig config(rdbStorePath); + config.SetDBType(OHOS::NativeRdb::DBType::DB_SQLITE); + config.SetHaMode(HAMode::SINGLE); + EXPECT_EQ(Connection::CheckReplicaIntegrity(config), E_NOT_SUPPORT); + RdbHelper::DeleteRdbStore(rdbStorePath); +} + +static int32_t MockReplicaChecker(const RdbStoreConfig &config) +{ + return E_OK; +} + +/** + * @tc.name: RegisterReplicaChecker_Test_001 + * @tc.desc: The testCase of RegisterReplicaChecker. + * @tc.type: FUNC + */ +HWTEST_F(ConnectionTest, RegisterReplicaChecker_Test_001, TestSize.Level2) +{ + EXPECT_EQ(Connection::RegisterReplicaChecker(OHOS::NativeRdb::DBType::DB_BUTT, nullptr), E_INVALID_ARGS); + EXPECT_EQ(Connection::RegisterReplicaChecker(OHOS::NativeRdb::DBType::DB_VECTOR, MockReplicaChecker), E_OK); + EXPECT_EQ(Connection::RegisterReplicaChecker(OHOS::NativeRdb::DBType::DB_VECTOR, MockReplicaChecker), E_OK); + EXPECT_EQ(Connection::RegisterReplicaChecker(OHOS::NativeRdb::DBType::DB_SQLITE, MockReplicaChecker), E_OK); + EXPECT_EQ(Connection::RegisterReplicaChecker(OHOS::NativeRdb::DBType::DB_SQLITE, MockReplicaChecker), E_OK); +} } // namespace Test \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/delay_actuator_test.cpp b/relational_store/test/native/rdb/unittest/delay_actuator_test.cpp new file mode 100644 index 00000000..4f8049a0 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/delay_actuator_test.cpp @@ -0,0 +1,220 @@ +/* + * 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 "delay_actuator.h" +#include "block_data.h" + +#include +using namespace testing::ext; +namespace OHOS::Test { +class DelayActuatorTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; +}; + +/** +* @tc.name: Execute_001 +* @tc.desc: Execute normally +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(DelayActuatorTest, Execute_001, TestSize.Level0) +{ + auto delayActuator = std::make_shared>(nullptr, ActuatorBase::DEFAULT_MIN_EXECUTE_INTERVAL); + delayActuator->SetExecutorPool(std::make_shared(1, 1)); + auto blockData = std::make_shared>(2, 0); + delayActuator->SetTask([blockData](int data) { + blockData->SetValue(data); + return 0; + }); + delayActuator->Execute(1); + EXPECT_EQ(blockData->GetValue(), 1); +} + +/** +* @tc.name: Execute_002 +* @tc.desc: When triggered once, the Task is executed normally with delayInterval_ delay +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(DelayActuatorTest, Execute_002, TestSize.Level0) +{ + uint32_t firstDelay = 1500; + uint32_t minInterval = 2000; + uint32_t maxInterval = 3000; + auto delayActuator = std::make_shared>(nullptr, firstDelay, minInterval, maxInterval); + delayActuator->SetExecutorPool(std::make_shared(1, 1)); + auto blockData = std::make_shared>(1, 0); + delayActuator->SetTask([blockData](int data) { + blockData->SetValue(data); + return 0; + }); + delayActuator->Execute(1); + EXPECT_EQ(blockData->GetValue(), 0); + EXPECT_EQ(blockData->GetValue(), 1); +} + +/** +* @tc.name: Execute_003 +* @tc.desc: When triggered multiple times, the Task is executed normally with forceInterval_ delay +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(DelayActuatorTest, Execute_003, TestSize.Level0) +{ + uint32_t firstDelay = 200; + uint32_t minInterval = 200; + uint32_t maxInterval = 600; + auto delayActuator = std::make_shared>(nullptr, firstDelay, minInterval, maxInterval); + delayActuator->SetExecutorPool(std::make_shared(1, 1)); + auto blockData = std::make_shared>(0, 0); + delayActuator->SetTask([blockData](int data) { + blockData->SetValue(data); + return 0; + }); + for (int i = 0; i < 5; i++) { + delayActuator->Execute(std::move(i)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + EXPECT_EQ(blockData->GetValue(), 0); + } + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + EXPECT_EQ(blockData->GetValue(), 4); +} + +/** +* @tc.name: Execute_004 +* @tc.desc: Execute task after Defer deconstruction +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(DelayActuatorTest, Execute_004, TestSize.Level0) +{ + auto delayActuator = std::make_shared>(nullptr, ActuatorBase::DEFAULT_MIN_EXECUTE_INTERVAL); + delayActuator->SetExecutorPool(std::make_shared(1, 1)); + auto blockData = std::make_shared>(1, 0); + delayActuator->SetTask([blockData](int data) { + blockData->SetValue(data); + return 0; + }); + { + ActuatorBase::Defer defer(delayActuator); + for (int i = 0; i < 3; i++) { + delayActuator->Execute(std::move(i)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + EXPECT_EQ(blockData->GetValue(), 0); + } + } + EXPECT_EQ(blockData->GetValue(), 2); +} + +/** +* @tc.name: Execute_005 +* @tc.desc: When triggered multiple times, use mergeFunc to merge parameters +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(DelayActuatorTest, Execute_005, TestSize.Level0) +{ + auto delayActuator = std::make_shared>( + [](int& out, int&& input) { + out += input; + }, + 100, 100, 300); + delayActuator->SetExecutorPool(std::make_shared(1, 1)); + auto blockData = std::make_shared>(0, 0); + delayActuator->SetTask([blockData](int data) { + blockData->SetValue(data); + return 0; + }); + for (int i = 0; i < 5; i++) { + delayActuator->Execute(std::move(i)); + EXPECT_EQ(blockData->GetValue(), 0); + } + std::this_thread::sleep_for(std::chrono::milliseconds(300)); + EXPECT_EQ(blockData->GetValue(), 10); +} + +/** +* @tc.name: Execute_006 +* @tc.desc: Testing MergeFunc for complex types +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(DelayActuatorTest, Execute_006, TestSize.Level0) +{ + using DelayActuatorT = DelayActuator>; + auto delayActuator = std::make_shared( + [](auto& out, std::map&& input) { + for (auto& [k, v] : input) { + out[k] += std::move(v); + } + }, + 100); + delayActuator->SetExecutorPool(std::make_shared(1, 1)); + auto blockData = std::make_shared>>(3); + delayActuator->SetTask([blockData](const std::map& data) { + blockData->SetValue(data); + return 0; + }); + std::map data; + int len = 10; + for (int i = 0; i < len; i++) { + data.insert_or_assign(std::to_string(i), "t"); + delayActuator->Execute(std::move(data)); + } + auto val = blockData->GetValue(); + EXPECT_EQ(val.size(), len); + for (auto& [k, v] : val) { + EXPECT_EQ(v, std::string(len--, 't')); + } +} + +/** +* @tc.name: Execute_007 +* @tc.desc: Testing delay of first execution and minimum interval +* @tc.type: FUNC +* @tc.require: +* @tc.author: ht +*/ +HWTEST_F(DelayActuatorTest, Execute_007, TestSize.Level0) +{ + uint32_t firstDelay = 50; + uint32_t minInterval = 1500; + uint32_t maxInterval = 5000; + auto delayActuator = std::make_shared>(nullptr, firstDelay, minInterval, maxInterval); + delayActuator->SetExecutorPool(std::make_shared(1, 1)); + auto blockData = std::make_shared>(1, 0); + delayActuator->SetTask([blockData](int data) { + blockData->SetValue(data); + return 0; + }); + delayActuator->Execute(1); + EXPECT_EQ(blockData->GetValue(), 1); + blockData->Clear(0); + delayActuator->Execute(2); + EXPECT_EQ(blockData->GetValue(), 0); + blockData->Clear(0); + EXPECT_EQ(blockData->GetValue(), 2); +} +} // namespace OHOS::Test diff --git a/relational_store/test/native/rdb/unittest/delay_notify_test.cpp b/relational_store/test/native/rdb/unittest/delay_notify_test.cpp new file mode 100644 index 00000000..23198da3 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/delay_notify_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. + */ + +#define LOG_TAG "DelayNotifyTest" +#include + +#include "logger.h" +#include "common.h" +#include "executor_pool.h" +#include "rdb_helper.h" +#include "rdb_store_impl.h" +#include "delay_notify.h" +#include "block_data.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; +using namespace OHOS::DistributedRdb; +class DelayNotifyTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DelayNotifyTest::SetUpTestCase(void) +{ +} + +void DelayNotifyTest::TearDownTestCase(void) +{ +} + +void DelayNotifyTest::SetUp() +{ +} + +void DelayNotifyTest::TearDown() +{ +} + +/** +* @tc.name: StartTimer_Test_001 +* @tc.desc: Check the normal process of starting the timer. +* @tc.type: FUNC +*/ +HWTEST_F(DelayNotifyTest, StartTimer_Test_001, TestSize.Level1) +{ + auto delayNotifier = std::make_shared(); + delayNotifier->SetExecutorPool(std::make_shared(5, 0)); + auto block = std::make_shared>(1, false); + delayNotifier->SetTask([block](const RdbChangedData &, const RdbNotifyConfig &){ + block->SetValue(true); + return 0; + }); + delayNotifier->isFull_ = true; + delayNotifier->UpdateNotify(RdbChangedData()); + EXPECT_TRUE(block->GetValue()); +} + +/** +* @tc.name: StartTimer_Test_002 +* @tc.desc: Check if the function ExecuteTask() can avoid crashing when the delayNotify is destructed prematurely +* in the main process of starting the timer. +* @tc.type: FUNC +*/ +HWTEST_F(DelayNotifyTest, StartTimer_Test_002, TestSize.Level1) +{ + auto delayNotifier = std::make_shared(); + auto pool = std::make_shared(5, 0); + delayNotifier->SetExecutorPool(pool); + auto block = std::make_shared>(1, false); + delayNotifier->SetTask([block](const RdbChangedData &, const RdbNotifyConfig &){ + block->SetValue(true); + return 0; + }); + delayNotifier->UpdateNotify(RdbChangedData()); + delayNotifier->delaySyncTaskId_ = OHOS::ExecutorPool::INVALID_TASK_ID; + delayNotifier.reset(); + ASSERT_NO_FATAL_FAILURE(EXPECT_FALSE(block->GetValue())); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/dynamic_load_test/BUILD.gn b/relational_store/test/native/rdb/unittest/dynamic_load_test/BUILD.gn new file mode 100644 index 00000000..f08d43e0 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/dynamic_load_test/BUILD.gn @@ -0,0 +1,151 @@ +# 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/distributeddatamgr/relational_store/relational_store.gni") + +module_output_path = "relational_store/relational_store/native_rdb" + +############################################################################### +config("module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${relational_store_mock_path}/frameworks/native/rdb/common", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", + "${relational_store_native_path}/rdb/src", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_native_path}/rdb_crypt", + "${relational_store_native_path}/rdb_device_manager_adapter/include", + "${relational_store_base_path}/test/native/rdb/unittest", + ] + + defines = [ + "RELATIONAL_STORE", + ] +} + +ohos_unittest("DynamicLoadTest") { + module_out_path = module_output_path + + cflags = [ + "-fno-access-control", # Ignore Private Member Access Control + ] + + sources = [ "dynamic_load_test.cpp" ] + + sources += [ + "${relational_store_native_path}/rdb/src/rdb_manager_impl.cpp", + "${relational_store_native_path}/dfx/src/rdb_radar_reporter.cpp", + "${relational_store_native_path}/dfx/src/rdb_stat_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_fault_hiview_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_time_utils.cpp", + "${relational_store_native_path}/rdb/src/abs_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_result_set.cpp", + "${relational_store_native_path}/rdb/src/abs_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/base_transaction.cpp", + "${relational_store_native_path}/rdb/src/big_integer.cpp", + "${relational_store_native_path}/rdb/src/cache_result_set.cpp", + "${relational_store_native_path}/rdb/src/connection.cpp", + "${relational_store_native_path}/rdb/src/connection_pool.cpp", + "${relational_store_native_path}/rdb/src/delay_notify.cpp", + "${relational_store_native_path}/rdb/src/grd_api_manager.cpp", + "${relational_store_native_path}/rdb/src/global_resource.cpp", + "${relational_store_native_path}/rdb/src/knowledge_schema_helper.cpp", + "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", + "${relational_store_native_path}/rdb/src/rd_connection.cpp", + "${relational_store_native_path}/rdb/src/rd_statement.cpp", + "${relational_store_native_path}/rdb/src/rd_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_helper.cpp", + "${relational_store_native_path}/rdb/src/rdb_icu_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_local_db_observer.cpp", + "${relational_store_native_path}/rdb/src/rdb_notifier_stub.cpp", + "${relational_store_native_path}/rdb/src/rdb_obs_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_perfStat.cpp", + "${relational_store_native_path}/rdb/src/rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_service_proxy.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_log.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_statistic.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_store.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_impl.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_types_util.cpp", + "${relational_store_native_path}/rdb/src/result_set_proxy.cpp", + "${relational_store_native_path}/rdb/src/security_policy.cpp", + "${relational_store_native_path}/rdb/src/share_block.cpp", + "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", + "${relational_store_native_path}/rdb/src/sqlite_connection.cpp", + "${relational_store_native_path}/rdb/src/sqlite_default_function.cpp", + "${relational_store_native_path}/rdb/src/sqlite_global_config.cpp", + "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/sqlite_sql_builder.cpp", + "${relational_store_native_path}/rdb/src/sqlite_statement.cpp", + "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", + "${relational_store_native_path}/rdb/src/step_result_set.cpp", + "${relational_store_native_path}/rdb/src/string_utils.cpp", + "${relational_store_native_path}/rdb/src/suspender.cpp", + "${relational_store_native_path}/rdb/src/task_executor.cpp", + "${relational_store_native_path}/rdb/src/trans_db.cpp", + "${relational_store_native_path}/rdb/src/transaction.cpp", + "${relational_store_native_path}/rdb/src/transaction_impl.cpp", + "${relational_store_native_path}/rdb/src/value_object.cpp", + "${relational_store_native_path}/rdb/src/values_bucket.cpp", + "${relational_store_native_path}/rdb/src/values_buckets.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "c_utils:utils", + "file_api:securitylabel", + "googletest:gmock", + "googletest:gtest", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "huks:libhukssdk", + "ipc:ipc_core", + "ipc:ipc_single", + "json:nlohmann_json_static", + "kv_store:database_utils", + "kv_store:datamgr_common", + "kv_store:distributeddata_inner", + "kv_store:distributeddb_client", + "samgr:samgr_proxy", + "sqlite:sqlite", + "sqlite:sqliteicu", + ] + + deps = [ + "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", + "${relational_store_innerapi_path}/appdatafwk:relational_common_base", + ] +} + +############################################################################### +group("unittest") { + testonly = true + + deps = [ ":DynamicLoadTest" ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/unittest/dynamic_load_test/dynamic_load_test.cpp b/relational_store/test/native/rdb/unittest/dynamic_load_test/dynamic_load_test.cpp new file mode 100644 index 00000000..ce1e527c --- /dev/null +++ b/relational_store/test/native/rdb/unittest/dynamic_load_test/dynamic_load_test.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 + +#include + +#include "block_data.h" +#include "global_resource.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_manager_impl.h" +#include "rdb_open_callback.h" +#include "rdb_store_impl.h" +#include "rdb_store_manager.h" +#include "sqlite_connection.h" +#include "task_executor.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::DistributedRdb; +const std::string RDB_TEST_PATH = "/data/test/"; +class OpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override + { + return E_OK; + } + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override + { + return E_OK; + } +}; + +class RdbDynamicLoadTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void RdbDynamicLoadTest::SetUpTestCase(void) +{ +} + +void RdbDynamicLoadTest::TearDownTestCase(void) +{ +} + +void RdbDynamicLoadTest::SetUp(void) +{ +} + +void RdbDynamicLoadTest::TearDown(void) +{ +} + +class RdbDynamicLoadTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string CREATE_TABLE_TEST; +}; +const std::string RdbDynamicLoadTestOpenCallback::CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, " + "blobType BLOB)"; + +int RdbDynamicLoadTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_TEST); +} + +int RdbDynamicLoadTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +/** + * @tc.name: DynamicLoading001 + * @tc.desc: Dynamic loading test + * @tc.type: FUNC + */ +HWTEST_F(RdbDynamicLoadTest, DynamicLoading001, TestSize.Level1) +{ + EXPECT_TRUE(RdbHelper::Init()); + + const std::string dbPath = RDB_TEST_PATH + "DynamicLoading.db"; + RdbStoreConfig config(dbPath); + config.SetBundleName("com.ohos.config.DynamicLoading"); + int errCode = E_ERROR; + RdbDynamicLoadTestOpenCallback helper; + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(rdbStore, nullptr); + + EXPECT_FALSE(RdbStoreManager::GetInstance().storeCache_.empty()); + EXPECT_NE(RdbManagerImpl::GetInstance().distributedDataMgr_, nullptr); + EXPECT_NE(RdbManagerImpl::GetInstance().rdbService_, nullptr); + EXPECT_NE(TaskExecutor::GetInstance().pool_, nullptr); + rdbStore = nullptr; + EXPECT_TRUE(RdbHelper::Destroy()); + + EXPECT_TRUE(RdbStoreManager::GetInstance().storeCache_.empty()); + EXPECT_EQ(RdbManagerImpl::GetInstance().distributedDataMgr_, nullptr); + EXPECT_EQ(RdbManagerImpl::GetInstance().rdbService_, nullptr); + EXPECT_EQ(TaskExecutor::GetInstance().pool_, nullptr); + EXPECT_TRUE(RdbHelper::Init()); + EXPECT_NE(TaskExecutor::GetInstance().pool_, nullptr); +} + +/** + * @tc.name: DynamicLoading002 + * @tc.desc: Dynamic loading test + * @tc.type: FUNC + */ +HWTEST_F(RdbDynamicLoadTest, DynamicLoading002, TestSize.Level1) +{ + EXPECT_TRUE(RdbHelper::Init()); + + const std::string dbPath = RDB_TEST_PATH + "DynamicLoading.db"; + RdbStoreConfig config(dbPath); + config.SetBundleName("com.ohos.config.DynamicLoading"); + int errCode = E_ERROR; + RdbDynamicLoadTestOpenCallback helper; + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(rdbStore, nullptr); + + EXPECT_FALSE(RdbStoreManager::GetInstance().storeCache_.empty()); + EXPECT_NE(RdbManagerImpl::GetInstance().distributedDataMgr_, nullptr); + EXPECT_NE(RdbManagerImpl::GetInstance().rdbService_, nullptr); + EXPECT_NE(TaskExecutor::GetInstance().pool_, nullptr); + OHOS::NativeRdb::RdbHelper::DestroyOption destroyOption; + destroyOption.cleanICU = true; + rdbStore = nullptr; + EXPECT_TRUE(RdbHelper::Destroy(destroyOption)); + + EXPECT_TRUE(RdbStoreManager::GetInstance().storeCache_.empty()); + EXPECT_EQ(RdbManagerImpl::GetInstance().distributedDataMgr_, nullptr); + EXPECT_EQ(RdbManagerImpl::GetInstance().rdbService_, nullptr); + EXPECT_EQ(TaskExecutor::GetInstance().pool_, nullptr); +} + +/** + * @tc.name: ObsManger001 + * @tc.desc: Destroy when the subscription is not cancelled + * @tc.type: FUNC + */ +HWTEST_F(RdbDynamicLoadTest, ObsManger001, TestSize.Level1) +{ + const std::string dbPath = RDB_TEST_PATH + "ObsManger001.db"; + RdbStoreConfig config(dbPath); + config.SetBundleName("com.ohos.config.DynamicLoading"); + int errCode = E_ERROR; + RdbDynamicLoadTestOpenCallback helper; + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(rdbStore, nullptr); + std::shared_ptr autoRelease = + std::shared_ptr("ObsManger001", [config](const char *) { RdbHelper::DeleteRdbStore(config); }); + std::shared_ptr observer; + auto status = rdbStore->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer" }, observer); + EXPECT_EQ(status, E_OK); + ASSERT_NO_FATAL_FAILURE(EXPECT_FALSE(RdbHelper::Destroy())); + ASSERT_NO_FATAL_FAILURE(EXPECT_FALSE(RdbHelper::Destroy())); + rdbStore = nullptr; + ASSERT_NO_FATAL_FAILURE(EXPECT_TRUE(RdbHelper::Destroy())); + auto rdbStoreNew = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(rdbStore, rdbStoreNew); +} + +/** + * @tc.name: ObsManger002 + * @tc.desc: Destroy after the database is closed + * @tc.type: FUNC + */ +HWTEST_F(RdbDynamicLoadTest, ObsManger002, TestSize.Level1) +{ + const std::string dbPath = RDB_TEST_PATH + "ObsManger002.db"; + RdbStoreConfig config(dbPath); + config.SetBundleName("com.ohos.config.DynamicLoading"); + int errCode = E_ERROR; + RdbDynamicLoadTestOpenCallback helper; + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(rdbStore, nullptr); + std::shared_ptr autoRelease = + std::shared_ptr("ObsManger002", [config](const char *) { RdbHelper::DeleteRdbStore(config); }); + std::shared_ptr observer; + auto status = rdbStore->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer" }, observer); + EXPECT_EQ(status, E_OK); + rdbStore = nullptr; + ASSERT_NO_FATAL_FAILURE(EXPECT_TRUE(RdbHelper::Destroy())); +} + +/** + * @tc.name: ICUManager001 + * @tc.desc: Destroy ICU + * @tc.type: FUNC + */ +HWTEST_F(RdbDynamicLoadTest, ICUManager001, TestSize.Level1) +{ + const std::string dbPath = RDB_TEST_PATH + "ICUManager001.db"; + RdbStoreConfig config(dbPath); + config.SetBundleName("com.ohos.config.DynamicLoading"); + int errCode = E_ERROR; + RdbDynamicLoadTestOpenCallback helper; + config.SetCollatorLocales("zh_CN"); + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(rdbStore, nullptr); + std::shared_ptr autoRelease = + std::shared_ptr("ICUManager001", [config](const char *) { RdbHelper::DeleteRdbStore(config); }); + rdbStore->ExecuteSql("CREATE TABLE ICUManager (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, " + "data2 INTEGER);"); + int64_t id; + ValuesBucket valuesBucket; + valuesBucket.PutString("data1", "张三"); + valuesBucket.PutInt("data2", 20); + errCode = rdbStore->Insert(id, "ICUManager", valuesBucket); + EXPECT_EQ(errCode, E_OK); + rdbStore = nullptr; + RdbHelper::DestroyOption option; + option.cleanICU = true; + ASSERT_NO_FATAL_FAILURE(EXPECT_TRUE(RdbHelper::Destroy(option))); +} + +using CheckOnChangeFunc = std::function; +class SubObserver : public RdbStoreObserver { +public: + virtual ~SubObserver() + { + } + void OnChange(const std::vector &devices) override + { + } + void OnChange(const Origin &origin, const PrimaryFields &fields, RdbStoreObserver::ChangeInfo &&info) override; + void OnChange() override + { + } + void RegisterCallback(const CheckOnChangeFunc &callback); + +private: + CheckOnChangeFunc checkOnChangeFunc_; +}; + +void SubObserver::OnChange(const Origin &origin, const PrimaryFields &fields, RdbStoreObserver::ChangeInfo &&info) +{ + if (checkOnChangeFunc_) { + checkOnChangeFunc_(info); + } +} + +void SubObserver::RegisterCallback(const CheckOnChangeFunc &callback) +{ + checkOnChangeFunc_ = callback; +} + +/** + * @tc.name: DbClient001 + * @tc.desc: Destroy DbClient + * @tc.type: FUNC + */ +HWTEST_F(RdbDynamicLoadTest, DbClient001, TestSize.Level1) +{ + const std::string dbPath = RDB_TEST_PATH + "DbClient001.db"; + RdbStoreConfig config(dbPath); + config.SetBundleName("com.ohos.config.DynamicLoading"); + int errCode = E_ERROR; + RdbDynamicLoadTestOpenCallback helper; + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(rdbStore, nullptr); + std::shared_ptr autoRelease = + std::shared_ptr("DbClient001", [config](const char *) { RdbHelper::DeleteRdbStore(config); }); + auto obs = std::make_shared(); + auto flag = std::make_shared>(false, 3); + obs->RegisterCallback([flag](RdbStoreObserver::ChangeInfo &changeInfo) { + flag->SetValue(true); + return; + }); + errCode = rdbStore->Subscribe({ SubscribeMode::LOCAL_DETAIL }, obs); + EXPECT_EQ(errCode, E_OK); + int64_t id; + ValuesBucket valuesBucket; + valuesBucket.PutString("name", "bob"); + valuesBucket.PutInt("age", 20); + errCode = rdbStore->Insert(id, "test", valuesBucket); + EXPECT_EQ(errCode, E_OK); + EXPECT_EQ(flag->GetValue(), true); + rdbStore = nullptr; + ASSERT_NO_FATAL_FAILURE(EXPECT_TRUE(RdbHelper::Destroy())); +} + +/** + * @tc.name: OpenSSL001 + * @tc.desc: Destroy OpenSSL + * @tc.type: FUNC + */ +HWTEST_F(RdbDynamicLoadTest, OpenSSL001, TestSize.Level1) +{ + const std::string dbPath = RDB_TEST_PATH + "OpenSSL001.db"; + RdbStoreConfig config(dbPath); + config.SetBundleName("com.ohos.config.DynamicLoading"); + config.SetEncryptStatus(true); + int errCode = E_ERROR; + RdbDynamicLoadTestOpenCallback helper; + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(rdbStore, nullptr); + std::shared_ptr autoRelease = + std::shared_ptr("OpenSSL001", [config](const char *) { RdbHelper::DeleteRdbStore(config); }); + int64_t id; + ValuesBucket valuesBucket; + valuesBucket.PutString("name", "bob"); + valuesBucket.PutInt("age", 20); + errCode = rdbStore->Insert(id, "test", valuesBucket); + EXPECT_EQ(errCode, E_OK); + rdbStore = nullptr; + RdbHelper::DestroyOption option; + option.cleanOpenSSL = true; + ASSERT_NO_FATAL_FAILURE(EXPECT_TRUE(RdbHelper::Destroy(option))); +} + +/** + * @tc.name: GlobalResource001 + * @tc.desc: GlobalResource CleanUp invalid args + * @tc.type: FUNC + */ +HWTEST_F(RdbDynamicLoadTest, GlobalResource001, TestSize.Level1) +{ + EXPECT_EQ(GlobalResource::CleanUp(-1), E_INVALID_ARGS); + EXPECT_EQ(GlobalResource::CleanUp(GlobalResource::CLEAN_BUTT), E_INVALID_ARGS); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/mock_obs_manage_test/BUILD.gn b/relational_store/test/native/rdb/unittest/mock_obs_manage_test/BUILD.gn new file mode 100644 index 00000000..630cc753 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/mock_obs_manage_test/BUILD.gn @@ -0,0 +1,156 @@ +# 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/distributeddatamgr/relational_store/relational_store.gni") + +module_output_path = "relational_store/relational_store/native_rdb" + +############################################################################### +config("module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${relational_store_mock_path}/frameworks/native/rdb/common", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", + "${relational_store_native_path}/rdb_crypt", + "${relational_store_native_path}/rdb/src", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_native_path}/rdb_device_manager_adapter/include", + "${relational_store_base_path}/test/native/rdb/unittest", + ] + + defines = [ + "RELATIONAL_STORE", + ] +} + +base_sources = [ + "${relational_store_native_path}/rdb/src/rdb_manager_impl.cpp", + "${relational_store_native_path}/dfx/src/rdb_radar_reporter.cpp", + "${relational_store_native_path}/dfx/src/rdb_stat_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_fault_hiview_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_time_utils.cpp", + "${relational_store_native_path}/rdb/src/abs_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_result_set.cpp", + "${relational_store_native_path}/rdb/src/abs_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/base_transaction.cpp", + "${relational_store_native_path}/rdb/src/big_integer.cpp", + "${relational_store_native_path}/rdb/src/cache_result_set.cpp", + "${relational_store_native_path}/rdb/src/connection.cpp", + "${relational_store_native_path}/rdb/src/connection_pool.cpp", + "${relational_store_native_path}/rdb/src/delay_notify.cpp", + "${relational_store_native_path}/rdb/src/grd_api_manager.cpp", + "${relational_store_native_path}/rdb/src/knowledge_schema_helper.cpp", + "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", + "${relational_store_native_path}/rdb/src/rd_connection.cpp", + "${relational_store_native_path}/rdb/src/rd_statement.cpp", + "${relational_store_native_path}/rdb/src/rd_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_helper.cpp", + "${relational_store_native_path}/rdb/src/rdb_icu_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_local_db_observer.cpp", + "${relational_store_native_path}/rdb/src/rdb_notifier_stub.cpp", + "${relational_store_native_path}/rdb/src/rdb_obs_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_perfStat.cpp", + "${relational_store_native_path}/rdb/src/rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_service_proxy.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_log.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_statistic.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_store.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_impl.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_types_util.cpp", + "${relational_store_native_path}/rdb/src/result_set_proxy.cpp", + "${relational_store_native_path}/rdb/src/security_policy.cpp", + "${relational_store_native_path}/rdb/src/share_block.cpp", + "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", + "${relational_store_native_path}/rdb/src/sqlite_connection.cpp", + "${relational_store_native_path}/rdb/src/sqlite_default_function.cpp", + "${relational_store_native_path}/rdb/src/sqlite_global_config.cpp", + "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/sqlite_sql_builder.cpp", + "${relational_store_native_path}/rdb/src/sqlite_statement.cpp", + "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", + "${relational_store_native_path}/rdb/src/step_result_set.cpp", + "${relational_store_native_path}/rdb/src/string_utils.cpp", + "${relational_store_native_path}/rdb/src/suspender.cpp", + "${relational_store_native_path}/rdb/src/task_executor.cpp", + "${relational_store_native_path}/rdb/src/trans_db.cpp", + "${relational_store_native_path}/rdb/src/transaction.cpp", + "${relational_store_native_path}/rdb/src/transaction_impl.cpp", + "${relational_store_native_path}/rdb/src/value_object.cpp", + "${relational_store_native_path}/rdb/src/values_bucket.cpp", + "${relational_store_native_path}/rdb/src/values_buckets.cpp", +] + +ohos_unittest("GlobalResourceTest") { + module_out_path = module_output_path + + cflags = [ + "-fno-access-control", # Ignore Private Member Access Control + ] + + sources = base_sources + + sources += [ + "global_resource_test.cpp", + "mock_global_resource.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "c_utils:utils", + "file_api:securitylabel", + "googletest:gmock", + "googletest:gtest", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "huks:libhukssdk", + "ipc:ipc_core", + "ipc:ipc_single", + "json:nlohmann_json_static", + "kv_store:database_utils", + "kv_store:datamgr_common", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "samgr:samgr_proxy", + "sqlite:sqlite", + "sqlite:sqliteicu", + ] + + deps = [ + "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", + "${relational_store_innerapi_path}/appdatafwk:relational_common_base", + ] +} + +############################################################################### +group("unittest") { + testonly = true + + deps = [ ":GlobalResourceTest" ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/unittest/mock_obs_manage_test/global_resource_test.cpp b/relational_store/test/native/rdb/unittest/mock_obs_manage_test/global_resource_test.cpp new file mode 100644 index 00000000..e09b364b --- /dev/null +++ b/relational_store/test/native/rdb/unittest/mock_obs_manage_test/global_resource_test.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 +#include + +#include "rdb_helper.h" + +#include "mock_global_resource.h" + +using namespace testing::ext; +using namespace testing; +using namespace OHOS::NativeRdb; + +class GlobalResourceTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static inline std::shared_ptr mockGlobalResource; +}; + +void GlobalResourceTest::SetUpTestCase(void) +{ + mockGlobalResource = std::make_shared(); +} + +void GlobalResourceTest::TearDownTestCase(void) +{ + mockGlobalResource = nullptr; +} + +void GlobalResourceTest::SetUp() +{ +} + +void GlobalResourceTest::TearDown() +{ +} + +/** +* @tc.name: GlobalResourceTest_CleanUp01 +* @tc.desc: No Mock All Symbols +* @tc.type: FUNC +*/ +HWTEST_F(GlobalResourceTest, GlobalResourceTest_CleanUp01, TestSize.Level2) +{ + EXPECT_CALL(*mockGlobalResource, CleanUp(_)).WillRepeatedly(Return(E_ERROR)); + OHOS::NativeRdb::RdbHelper::DestroyOption destroyOption; + destroyOption.cleanICU = true; + destroyOption.cleanOpenSSL = true; + EXPECT_FALSE(RdbHelper::Destroy(destroyOption)); +} diff --git a/relational_store/test/native/rdb/unittest/mock_obs_manage_test/mock_global_resource.cpp b/relational_store/test/native/rdb/unittest/mock_obs_manage_test/mock_global_resource.cpp new file mode 100644 index 00000000..31891508 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/mock_obs_manage_test/mock_global_resource.cpp @@ -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. + */ + +#include "mock_global_resource.h" +#include "rdb_errno.h" +namespace OHOS::NativeRdb { + +int32_t GlobalResource::CleanUp(int32_t type) +{ + if (BGlobalResource::globalResource_ == nullptr) { + return NativeRdb::E_ERROR; + } + return BGlobalResource::globalResource_->CleanUp(type); +} + +int32_t GlobalResource::RegisterClean(GlobalResource::CleanType type, GlobalResource::Cleaner clean) +{ + if (BGlobalResource::globalResource_ == nullptr) { + return NativeRdb::E_ERROR; + } + return BGlobalResource::globalResource_->RegisterClean(type, clean); +} +} // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/mock_obs_manage_test/mock_global_resource.h b/relational_store/test/native/rdb/unittest/mock_obs_manage_test/mock_global_resource.h new file mode 100644 index 00000000..aa739184 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/mock_obs_manage_test/mock_global_resource.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 DISTRIBUTED_GLOBAL_RESOURCE_MOCK_H +#define DISTRIBUTED_GLOBAL_RESOURCE_MOCK_H + +#include + +#include "global_resource.h" +namespace OHOS::NativeRdb { +class BGlobalResource { +public: + BGlobalResource() = default; + virtual ~BGlobalResource() = default; + virtual int32_t CleanUp(int32_t type) = 0; + virtual int32_t RegisterClean(GlobalResource::CleanType type, GlobalResource::Cleaner clean) = 0; + +public: + static inline std::shared_ptr globalResource_ = nullptr; +}; + +class MockGlobalResource : public BGlobalResource { +public: + MOCK_METHOD(int32_t, CleanUp, (int32_t type), (override)); + MOCK_METHOD(int32_t, RegisterClean, + (GlobalResource::CleanType type, GlobalResource::Cleaner clean), (override)); +}; +} // namespace OHOS::NativeRdb +#endif \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/mockservice/BUILD.gn b/relational_store/test/native/rdb/unittest/mockservice/BUILD.gn new file mode 100644 index 00000000..fb0732b5 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/mockservice/BUILD.gn @@ -0,0 +1,154 @@ +# 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/distributeddatamgr/relational_store/relational_store.gni") + +module_output_path = "relational_store/relational_store/native_rdb" + +############################################################################### +config("module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", + "${relational_store_native_path}/rdb/src", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_native_path}/rdb_crypt", + "${relational_store_native_path}/rdb_device_manager_adapter/include", + "${relational_store_base_path}/test/native/rdb/unittest", + "${relational_store_mock_test_path}/", + "${relational_store_mock_path}/frameworks/native/rdb/common", + ] + + defines = [ + "RELATIONAL_STORE", + "private=public", + ] +} + +ohos_unittest("NativeRdbConditionTest") { + module_out_path = module_output_path + + cflags = [ + "-fno-access-control", # Ignore Private Member Access Control + ] + + sources = [ "rdb_store_impl_test.cpp" ] + + sources += [ + "${relational_store_mock_test_path}/dataobs_mgr_client_mock.cpp", + "${relational_store_mock_test_path}/rdb_manager_impl_mock.cpp", + "${relational_store_native_path}/dfx/src/rdb_radar_reporter.cpp", + "${relational_store_native_path}/dfx/src/rdb_stat_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_fault_hiview_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_time_utils.cpp", + "${relational_store_native_path}/rdb/src/abs_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_result_set.cpp", + "${relational_store_native_path}/rdb/src/abs_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/base_transaction.cpp", + "${relational_store_native_path}/rdb/src/big_integer.cpp", + "${relational_store_native_path}/rdb/src/cache_result_set.cpp", + "${relational_store_native_path}/rdb/src/connection.cpp", + "${relational_store_native_path}/rdb/src/connection_pool.cpp", + "${relational_store_native_path}/rdb/src/delay_notify.cpp", + "${relational_store_native_path}/rdb/src/grd_api_manager.cpp", + "${relational_store_native_path}/rdb/src/global_resource.cpp", + "${relational_store_native_path}/rdb/src/knowledge_schema_helper.cpp", + "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", + "${relational_store_native_path}/rdb/src/rd_connection.cpp", + "${relational_store_native_path}/rdb/src/rd_statement.cpp", + "${relational_store_native_path}/rdb/src/rd_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_helper.cpp", + "${relational_store_native_path}/rdb/src/rdb_icu_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_local_db_observer.cpp", + "${relational_store_native_path}/rdb/src/rdb_obs_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_notifier_stub.cpp", + "${relational_store_native_path}/rdb/src/rdb_perfStat.cpp", + "${relational_store_native_path}/rdb/src/rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_service_proxy.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_log.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_statistic.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_store.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_impl.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_types_util.cpp", + "${relational_store_native_path}/rdb/src/result_set_proxy.cpp", + "${relational_store_native_path}/rdb/src/security_policy.cpp", + "${relational_store_native_path}/rdb/src/share_block.cpp", + "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", + "${relational_store_native_path}/rdb/src/sqlite_connection.cpp", + "${relational_store_native_path}/rdb/src/sqlite_default_function.cpp", + "${relational_store_native_path}/rdb/src/sqlite_global_config.cpp", + "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/sqlite_sql_builder.cpp", + "${relational_store_native_path}/rdb/src/sqlite_statement.cpp", + "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", + "${relational_store_native_path}/rdb/src/step_result_set.cpp", + "${relational_store_native_path}/rdb/src/string_utils.cpp", + "${relational_store_native_path}/rdb/src/suspender.cpp", + "${relational_store_native_path}/rdb/src/task_executor.cpp", + "${relational_store_native_path}/rdb/src/trans_db.cpp", + "${relational_store_native_path}/rdb/src/transaction.cpp", + "${relational_store_native_path}/rdb/src/transaction_impl.cpp", + "${relational_store_native_path}/rdb/src/value_object.cpp", + "${relational_store_native_path}/rdb/src/values_bucket.cpp", + "${relational_store_native_path}/rdb/src/values_buckets.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "c_utils:utils", + "file_api:securitylabel", + "googletest:gmock", + "googletest:gtest", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "huks:libhukssdk", + "ipc:ipc_core", + "ipc:ipc_single", + "json:nlohmann_json_static", + "kv_store:database_utils", + "kv_store:distributeddata_inner", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "samgr:samgr_proxy", + "sqlite:sqlite", + "sqlite:sqliteicu", + ] + + deps = [ + "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", + "${relational_store_innerapi_path}/appdatafwk:relational_common_base", + ] +} + +############################################################################### +group("unittest") { + testonly = true + + deps = [ ":NativeRdbConditionTest" ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/unittest/mockservice/rdb_store_impl_test.cpp b/relational_store/test/native/rdb/unittest/mockservice/rdb_store_impl_test.cpp new file mode 100644 index 00000000..70d3dae6 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/mockservice/rdb_store_impl_test.cpp @@ -0,0 +1,1853 @@ +/* + * 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 "rdb_store_impl.h" + +#include +#include + +#include "common.h" +#include "connection_mock.h" +#include "dataobs_mgr_client_mock.h" +#include "delay_notify.h" +#include "grd_api_manager.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_manager_impl_mock.h" +#include "rdb_open_callback.h" +#include "rdb_service_mock.h" +#include "rdb_sql_statistic.h" +#include "rdb_store_config.h" +#include "rdb_types.h" +#include "statement_mock.h" +#include "task_executor.h" + +using namespace testing::ext; +using namespace testing; +using namespace OHOS::NativeRdb; +using namespace OHOS::DistributedRdb; +using namespace OHOS::AAFwk; +using CheckOnChangeFunc = std::function; +using ValueObjects = std::vector; +class SubObserver : public RdbStoreObserver { +public: + virtual ~SubObserver() + { + } + void OnChange(const std::vector &devices){}; + void OnChange(const Origin &origin, const PrimaryFields &fields, RdbStoreObserver::ChangeInfo &&changeInfo){}; + void OnChange(){}; + void RegisterCallback(const CheckOnChangeFunc &callback); + uint32_t count = 0; + +private: + CheckOnChangeFunc checkOnChangeFunc_; +}; +class RdbStoreImplConditionTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static std::shared_ptr observer_; + static const std::string DATABASE_NAME; + static const std::string DATABASE_BACKUP_NAME; + static const std::string DEFAULT_DATABASE_NAME; + static inline std::shared_ptr mockRdbManagerImpl = nullptr; + static inline std::shared_ptr mockDataObsMgrClient = nullptr; + static inline std::shared_ptr mockStatement = nullptr; + static inline std::shared_ptr mockConnection = nullptr; + +protected: + std::shared_ptr store_; +}; + +const std::string RdbStoreImplConditionTest::DATABASE_NAME = RDB_TEST_PATH + "rdb_store_impl_condition_test.db"; +const std::string RdbStoreImplConditionTest::DATABASE_BACKUP_NAME = + RDB_TEST_PATH + "rdb_store_impl_condition_test_backup.db"; +const std::string RdbStoreImplConditionTest::DEFAULT_DATABASE_NAME = RDB_TEST_PATH + "default_condition_test.db"; + +std::shared_ptr RdbStoreImplConditionTest::observer_ = nullptr; + +class RdbStoreImplConditionTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string CREATE_TABLE_TEST; +}; + +const std::string RdbStoreImplConditionTestOpenCallback::CREATE_TABLE_TEST = + std::string("CREATE TABLE IF NOT EXISTS employee ") + std::string("(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary " + "REAL, blobType BLOB)"); + +int RdbStoreImplConditionTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_TEST); +} + +int RdbStoreImplConditionTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void RdbStoreImplConditionTest::SetUpTestCase(void) +{ + if (observer_ == nullptr) { + observer_ = std::make_shared(); + } + mockRdbManagerImpl = std::make_shared(); + BRdbManagerImpl::rdbManagerImpl = mockRdbManagerImpl; + mockDataObsMgrClient = std::make_shared(); + IDataObsMgrClient::dataObsMgrClient = mockDataObsMgrClient; + mockStatement = std::make_shared(); + mockConnection = std::make_shared(); +} + +void RdbStoreImplConditionTest::TearDownTestCase(void) +{ + mockRdbManagerImpl = nullptr; + BRdbManagerImpl::rdbManagerImpl = nullptr; + mockDataObsMgrClient = nullptr; + IDataObsMgrClient::dataObsMgrClient = nullptr; + mockStatement = nullptr; + mockConnection = nullptr; +} + +void RdbStoreImplConditionTest::SetUp(void) +{ + int errCode; + RdbStoreConfig config(RdbStoreImplConditionTest::DEFAULT_DATABASE_NAME); + RdbStoreImplConditionTestOpenCallback helper; + store_ = RdbHelper::GetRdbStore(config, 0, helper, errCode); + EXPECT_NE(store_, nullptr); + EXPECT_EQ(errCode, E_OK); +} + +void RdbStoreImplConditionTest::TearDown(void) +{ + store_ = nullptr; + RdbHelper::ClearCache(); + int errCode = RdbHelper::DeleteRdbStore(DEFAULT_DATABASE_NAME); + EXPECT_EQ(E_OK, errCode); + errCode = RdbHelper::DeleteRdbStore(DATABASE_NAME); + EXPECT_EQ(E_OK, errCode); +} + +/* * + * @tc.name: Rdb_RemoteQueryTest_003 + * @tc.desc: Abnormal testCase for RemoteQuery + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Rdb_RemoteQueryTest_003, TestSize.Level2) +{ + int errCode = E_OK; + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 1); + + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetName("RdbStore_impl_test.db"); + config.SetBundleName("com.example.distributed.rdb"); + config.SetDBType(DB_SQLITE); + config.SetStorageMode(StorageMode::MODE_MEMORY); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + EXPECT_EQ(E_OK, errCode); + + // GetRdbService succeeded if configuration file has already been configured + auto ret = store->RemoteQuery("", predicates, {}, errCode); + ASSERT_EQ(nullptr, ret); + + store = nullptr; + RdbHelper::DeleteRdbStore(RdbStoreImplConditionTest::DATABASE_NAME); +} + +/* * + * @tc.name: Rdb_RemoteQueryTest_005 + * @tc.desc: Abnormal testCase for RemoteQuery + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Rdb_RemoteQueryTest_005, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)) + .WillRepeatedly(Return(std::make_pair(E_NOT_SUPPORT, mockRdbService))); + int errCode = E_OK; + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 1); + + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetName("RdbStore_impl_test.db"); + config.SetBundleName("com.example.distributed.rdb"); + config.SetDBType(DB_SQLITE); + config.SetStorageMode(StorageMode::MODE_DISK); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(nullptr, store); + EXPECT_EQ(E_OK, errCode); + // GetRdbService succeeded if configuration file has already been configured + auto ret = store->RemoteQuery("", predicates, {}, errCode); + ASSERT_EQ(nullptr, ret); + + store = nullptr; + RdbHelper::DeleteRdbStore(RdbStoreImplConditionTest::DATABASE_NAME); +} + +/* * + * @tc.name: NotifyDataChangeTest_005 + * @tc.desc: Abnormal testCase for NotifyDataChange + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, NotifyDataChangeTest_005, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::CLIENT_OBSERVER, true); + auto storeImpl = std::make_shared(config); + storeImpl->NotifyDataChange(); + EXPECT_EQ(storeImpl->config_.GetRegisterInfo(RegisterType::CLIENT_OBSERVER), true); +} + +/* * + * @tc.name: NotifyDataChangeTest_006 + * @tc.desc: Abnormal testCase for NotifyDataChange + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, NotifyDataChangeTest_006, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(true); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::CLIENT_OBSERVER, true); + auto storeImpl = std::make_shared(config); + storeImpl->NotifyDataChange(); + EXPECT_EQ(storeImpl->config_.GetRegisterInfo(RegisterType::CLIENT_OBSERVER), true); +} + +/* * + * @tc.name: NotifyDataChangeTest_007 + * @tc.desc: Abnormal testCase for NotifyDataChange + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, NotifyDataChangeTest_007, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(true); + config.SetDBType(DB_VECTOR); + config.SetRegisterInfo(RegisterType::CLIENT_OBSERVER, true); + auto storeImpl = std::make_shared(config); + storeImpl->NotifyDataChange(); + EXPECT_EQ(storeImpl->config_.GetRegisterInfo(RegisterType::CLIENT_OBSERVER), true); +} + +/* * + * @tc.name: NotifyDataChangeTest_009 + * @tc.desc: Abnormal testCase for NotifyDataChange + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, NotifyDataChangeTest_009, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(true); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::OBSERVER_END, true); + auto storeImpl = std::make_shared(config); + storeImpl->NotifyDataChange(); + EXPECT_EQ(storeImpl->config_.GetRegisterInfo(RegisterType::CLIENT_OBSERVER), true); +} + +/* * + * @tc.name: ObtainDistributedTableNameTest_003 + * @tc.desc: Abnormal testCase for ObtainDistributedTableName + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ObtainDistributedTableNameTest_003, TestSize.Level2) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetDBType(DB_SQLITE); + config.SetStorageMode(StorageMode::MODE_MEMORY); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr); + EXPECT_EQ(errCode, E_OK); + auto tableName = store->ObtainDistributedTableName("123", "test", errCode); + EXPECT_EQ(tableName, ""); +} + +/* * + * @tc.name: GetUriTest_001 + * @tc.desc: Abnormal testCase for GetUri + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, GetUriTest_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetDataGroupId("123"); + auto storeImlp = std::make_shared(config); + auto uri = storeImlp->GetUri("test"); + EXPECT_EQ(uri, "rdb://123//data/test/rdb_store_impl_condition_test.db/test"); +} + +/* * + * @tc.name: Rdb_QuerySharingResourceTest_004 + * @tc.desc: QuerySharingResource testCase + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Rdb_QuerySharingResourceTest_004, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, QuerySharingResource(_, _, _)).WillOnce(Return(std::make_pair(E_ERROR, nullptr))); + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetName("RdbStore_impl_test.db"); + config.SetBundleName("com.example.distributed.rdb"); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr); + EXPECT_EQ(errCode, E_OK); + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 1); + + auto ret = store->QuerySharingResource(predicates, {}); + EXPECT_EQ(E_ERROR, ret.first); + EXPECT_EQ(nullptr, ret.second); +} + +/* * + * @tc.name: Rdb_QuerySharingResourceTest_005 + * @tc.desc: QuerySharingResource testCase + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Rdb_QuerySharingResourceTest_005, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, QuerySharingResource(_, _, _)).WillOnce(Return(std::make_pair(E_OK, nullptr))); + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetName("RdbStore_impl_test.db"); + config.SetBundleName("com.example.distributed.rdb"); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr); + EXPECT_EQ(errCode, E_OK); + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 1); + + auto ret = store->QuerySharingResource(predicates, {}); + EXPECT_EQ(E_OK, ret.first); + EXPECT_EQ(nullptr, ret.second); +} + +/* * + * @tc.name: CleanDirtyDataTest_002 + * @tc.desc: Abnormal testCase for CleanDirtyData + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Abnormal_CleanDirtyDataTest_002, TestSize.Level2) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetDBType(DB_SQLITE); + config.SetStorageMode(StorageMode::MODE_DISK); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(nullptr, store); + EXPECT_EQ(E_OK, errCode); + std::string table = ""; + uint64_t cursor = UINT64_MAX; + errCode = store->CleanDirtyData(table, cursor); + EXPECT_EQ(E_INVALID_ARGS, errCode); +} + +/* * + * @tc.name: CleanDirtyDataTest_003 + * @tc.desc: Abnormal testCase for CleanDirtyData + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Abnormal_CleanDirtyDataTest_003, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(true); + config.SetDBType(DB_VECTOR); + config.SetStorageMode(StorageMode::MODE_DISK); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(nullptr, store); + EXPECT_EQ(E_OK, errCode); + std::string table = ""; + uint64_t cursor = UINT64_MAX; + errCode = store->CleanDirtyData(table, cursor); + EXPECT_EQ(E_NOT_SUPPORT, errCode); +} + +/* * + * @tc.name: CleanDirtyDataTest_006 + * @tc.desc: Abnormal testCase for CleanDirtyData + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Abnormal_CleanDirtyDataTest_006, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetDBType(DB_VECTOR); + config.SetStorageMode(StorageMode::MODE_DISK); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(nullptr, store); + EXPECT_EQ(E_OK, errCode); + std::string table = ""; + uint64_t cursor = UINT64_MAX; + errCode = store->CleanDirtyData(table, cursor); + EXPECT_EQ(E_NOT_SUPPORT, errCode); +} + +/* * + * @tc.name: CleanDirtyDataTest_007 + * @tc.desc: Abnormal testCase for CleanDirtyData + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Abnormal_CleanDirtyDataTest_007, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(true); + config.SetDBType(DB_VECTOR); + config.SetStorageMode(StorageMode::MODE_DISK); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(nullptr, store); + EXPECT_EQ(E_OK, errCode); + std::string table = ""; + uint64_t cursor = UINT64_MAX; + errCode = store->CleanDirtyData(table, cursor); + EXPECT_EQ(E_NOT_SUPPORT, errCode); +} + +/* * + * @tc.name: CleanDirtyDataTest_009 + * @tc.desc: Abnormal testCase for CleanDirtyData + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Abnormal_CleanDirtyDataTest_009, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetDBType(DB_VECTOR); + config.SetStorageMode(StorageMode::MODE_DISK); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(nullptr, store); + EXPECT_EQ(E_OK, errCode); + std::string table = ""; + uint64_t cursor = UINT64_MAX; + errCode = store->CleanDirtyData(table, cursor); + EXPECT_EQ(E_NOT_SUPPORT, errCode); +} + +/* * + * @tc.name: CleanDirtyDataTest_010 + * @tc.desc: Abnormal testCase for CleanDirtyData + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Abnormal_CleanDirtyDataTest_010, TestSize.Level2) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetDBType(DB_SQLITE); + config.SetStorageMode(StorageMode::MODE_MEMORY); + RdbStoreImplConditionTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(nullptr, store); + EXPECT_EQ(E_OK, errCode); + std::string table = ""; + uint64_t cursor = UINT64_MAX; + errCode = store->CleanDirtyData(table, cursor); + EXPECT_EQ(E_NOT_SUPPORT, errCode); +} + +/** + * @tc.name: RdbStoreSubscribeRemote_001 + * @tc.desc: RdbStoreSubscribe + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, RdbStoreSubscribeRemote_001, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetDBType(DB_VECTOR); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(observer_, nullptr) << "observer is null"; + auto status = store->Subscribe({ SubscribeMode::REMOTE, "observer" }, observer_); + EXPECT_EQ(status, E_NOT_SUPPORT); + status = store->UnSubscribe({ SubscribeMode::REMOTE, "observer" }, observer_); + EXPECT_EQ(status, E_NOT_SUPPORT); +} + +/** + * @tc.name: RdbStoreSubscribeRemote_002 + * @tc.desc: RdbStoreSubscribe + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, RdbStoreSubscribeRemote_002, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetDBType(DB_SQLITE); + config.SetStorageMode(StorageMode::MODE_MEMORY); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(observer_, nullptr) << "observer is null"; + auto status = store->Subscribe({ SubscribeMode::REMOTE, "observer" }, observer_); + EXPECT_EQ(status, E_NOT_SUPPORT); + status = store->UnSubscribe({ SubscribeMode::REMOTE, "observer" }, observer_); + EXPECT_EQ(status, E_NOT_SUPPORT); +} + +/** + * @tc.name: SetDistributedTables_Test_001 + * @tc.desc: Abnormal testCase of SetDistributedTables + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDistributedTables_Test_001, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, SetDistributedTables(_, _, _, _, _)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::STORE_OBSERVER, true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector tables; + OHOS::DistributedRdb::DistributedConfig distributedConfig; + + tables.push_back("employee"); + errCode = store->SetDistributedTables(tables, DISTRIBUTED_DEVICE, distributedConfig); + EXPECT_EQ(E_OK, errCode); +} + +/** + * @tc.name: RdbStore_Distributed_Test_002 + * @tc.desc: Abnormal testCase of SetDistributedTables + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDistributedTables_Test_002, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, SetDistributedTables(_, _, _, _, _)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::CLIENT_OBSERVER, true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector tables; + OHOS::DistributedRdb::DistributedConfig distributedConfig; + + tables.push_back("employee"); + errCode = store->SetDistributedTables(tables, DISTRIBUTED_DEVICE, distributedConfig); + EXPECT_EQ(E_OK, errCode); +} + +/** + * @tc.name: SetDistributedTables_Test_003 + * @tc.desc: Abnormal testCase of SetDistributedTables + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDistributedTables_Test_003, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, SetDistributedTables(_, _, _, _, _)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::CLIENT_OBSERVER, true); + config.SetAllowRebuild(true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector tables; + OHOS::DistributedRdb::DistributedConfig distributedConfig; + distributedConfig.enableCloud = true; + distributedConfig.autoSync = true; + tables.push_back("employee"); + errCode = store->SetDistributedTables(tables, DISTRIBUTED_CLOUD, distributedConfig); + EXPECT_EQ(E_OK, errCode); +} + +/** + * @tc.name: SetDistributedTables_Test_004 + * @tc.desc: Abnormal testCase of SetDistributedTables + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDistributedTables_Test_004, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, SetDistributedTables(_, _, _, _, _)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::CLIENT_OBSERVER, true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector tables; + OHOS::DistributedRdb::DistributedConfig distributedConfig; + distributedConfig.enableCloud = true; + distributedConfig.autoSync = true; + tables.push_back("employee"); + errCode = store->SetDistributedTables(tables, DISTRIBUTED_CLOUD, distributedConfig); + EXPECT_EQ(E_OK, errCode); +} + +/** + * @tc.name: SetDistributedTables_Test_005 + * @tc.desc: Abnormal testCase of SetDistributedTables + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDistributedTables_Test_005, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, SetDistributedTables(_, _, _, _, _)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::STORE_OBSERVER, true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector tables; + OHOS::DistributedRdb::DistributedConfig distributedConfig; + distributedConfig.enableCloud = true; + distributedConfig.autoSync = false; + tables.push_back("employee"); + errCode = store->SetDistributedTables(tables, DISTRIBUTED_CLOUD, distributedConfig); + EXPECT_EQ(E_OK, errCode); +} + +/** + * @tc.name: SetDistributedTables_Test_006 + * @tc.desc: Abnormal testCase of SetDistributedTables + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDistributedTables_Test_006, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, SetDistributedTables(_, _, _, _, _)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::STORE_OBSERVER, true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector tables; + OHOS::DistributedRdb::DistributedConfig distributedConfig; + distributedConfig.enableCloud = false; + distributedConfig.autoSync = false; + tables.push_back("employee"); + errCode = store->SetDistributedTables(tables, DISTRIBUTED_CLOUD, distributedConfig); + EXPECT_EQ(E_OK, errCode); +} + +/** + * @tc.name: SetDistributedTables_Test_007 + * @tc.desc: Abnormal testCase of SetDistributedTables + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDistributedTables_Test_007, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + EXPECT_CALL(*mockRdbService, SetDistributedTables(_, _, _, _, _)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetRegisterInfo(RegisterType::STORE_OBSERVER, true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector tables; + OHOS::DistributedRdb::DistributedConfig distributedConfig; + distributedConfig.enableCloud = false; + distributedConfig.autoSync = true; + tables.push_back("employee"); + errCode = store->SetDistributedTables(tables, DISTRIBUTED_CLOUD, distributedConfig); + EXPECT_EQ(E_OK, errCode); +} + +/** + * @tc.name: Notify_Test_001 + * @tc.desc: Abnormal testCase of Notify + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Notify_Test_001, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + RdbStoreImplConditionTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::string event = "test"; + auto res = store->Notify(event); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: Notify_Test_002 + * @tc.desc: Abnormal testCase of Notify + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Notify_Test_002, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_MEMORY); + config.SetDBType(DB_SQLITE); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::string event = "test"; + auto res = store->Notify(event); + EXPECT_EQ(E_OK, res); +} + +/** + * @tc.name: Notify_Test_004 + * @tc.desc: Abnormal testCase of Notify + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Notify_Test_004, TestSize.Level2) +{ + //mock client->NotifyChange(GetUri(event)) + auto dataObsMgrClient = std::make_shared(); + EXPECT_CALL(*mockDataObsMgrClient, GetInstance()).WillOnce(Return(dataObsMgrClient)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::string event = "test"; + auto res = store->Notify(event); + EXPECT_EQ(E_OK, res); +} + +/** + * @tc.name: SetSearchable_Test_001 + * @tc.desc: Abnormal testCase of SetSearchable + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetSearchable_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_MEMORY); + config.SetDBType(DB_SQLITE); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + auto res = store->SetSearchable(true); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: SetSearchable_Test_002 + * @tc.desc: Abnormal testCase of SetSearchable + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetSearchable_Test_002, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + auto res = store->SetSearchable(true); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: RegisterAutoSyncCallback_Test_001 + * @tc.desc: Abnormal testCase of RegisterAutoSyncCallback + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, RegisterAutoSyncCallback_Test_001, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::shared_ptr observer; + auto res = store->RegisterAutoSyncCallback(observer); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: RegisterAutoSyncCallback_Test_002 + * @tc.desc: Abnormal testCase of RegisterAutoSyncCallback + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, RegisterAutoSyncCallback_Test_002, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_MEMORY); + config.SetDBType(DB_SQLITE); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::shared_ptr observer; + auto res = store->RegisterAutoSyncCallback(observer); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: RegisterAutoSyncCallback_Test_003 + * @tc.desc: Abnormal testCase of RegisterAutoSyncCallback + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, RegisterAutoSyncCallback_Test_003, TestSize.Level2) +{ + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_ERROR, nullptr))); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::shared_ptr observer; + auto res = store->RegisterAutoSyncCallback(observer); + EXPECT_EQ(E_ERROR, res); +} + +/** + * @tc.name: UnregisterAutoSyncCallback_Test_001 + * @tc.desc: Abnormal testCase of UnregisterAutoSyncCallback + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, UnregisterAutoSyncCallback_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_MEMORY); + config.SetDBType(DB_SQLITE); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::shared_ptr observer; + auto res = store->UnregisterAutoSyncCallback(observer); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: UnregisterAutoSyncCallback_Test_002 + * @tc.desc: Abnormal testCase of UnregisterAutoSyncCallback + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, UnregisterAutoSyncCallback_Test_002, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::shared_ptr observer; + auto res = store->UnregisterAutoSyncCallback(observer); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: UnregisterAutoSyncCallback_Test_003 + * @tc.desc: Abnormal testCase of UnregisterAutoSyncCallback + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, UnregisterAutoSyncCallback_Test_003, TestSize.Level2) +{ + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_ERROR, nullptr))); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::shared_ptr observer; + auto res = store->UnregisterAutoSyncCallback(observer); + EXPECT_EQ(E_ERROR, res); +} + +/** + * @tc.name: RegisterDataChangeCallback_Test_001 + * @tc.desc: Abnormal testCase of RegisterDataChangeCallback + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, RegisterDataChangeCallback_Test_001, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + auto storeImpl = std::make_shared(config); + storeImpl->connectionPool_ = nullptr; + auto res = storeImpl->RegisterDataChangeCallback(); + EXPECT_EQ(E_ALREADY_CLOSED, res); +} + +/** + * @tc.name: ModifyLockStatus_Test_001 + * @tc.desc: Abnormal testCase of ModifyLockStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ModifyLockStatusk_Test_001, TestSize.Level2) +{ + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + store = nullptr; + store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(true); + AbsRdbPredicates predicates(""); + auto res = store->ModifyLockStatus(predicates, false); + EXPECT_EQ(E_EMPTY_TABLE_NAME, res); +} + +/** + * @tc.name: ModifyLockStatus_Test_002 + * @tc.desc: Abnormal testCase of ModifyLockStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ModifyLockStatusk_Test_002, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + config.SetReadOnly(true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + AbsRdbPredicates predicates(""); + auto res = store->ModifyLockStatus(predicates, false); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: ModifyLockStatus_Test_003 + * @tc.desc: Abnormal testCase of ModifyLockStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ModifyLockStatusk_Test_003, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + config.SetReadOnly(false); + config.SetIsVector(true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + AbsRdbPredicates predicates(""); + auto res = store->ModifyLockStatus(predicates, false); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: ModifyLockStatus_Test_004 + * @tc.desc: Abnormal testCase of ModifyLockStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ModifyLockStatusk_Test_004, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_MEMORY); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + AbsRdbPredicates predicates(""); + auto res = store->ModifyLockStatus(predicates, false); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: ModifyLockStatus_Test_005 + * @tc.desc: Abnormal testCase of ModifyLockStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ModifyLockStatusk_Test_005, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + AbsRdbPredicates predicates(""); + auto res = store->ModifyLockStatus(predicates, false); + EXPECT_EQ(E_EMPTY_TABLE_NAME, res); +} + +/** + * @tc.name: ModifyLockStatus_Test_006 + * @tc.desc: Abnormal testCase of ModifyLockStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ModifyLockStatusk_Test_006, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + AbsRdbPredicates predicates("test"); + auto res = store->ModifyLockStatus(predicates, false); + EXPECT_EQ(E_NO_ROW_IN_QUERY, res); +} + +/** + * @tc.name: ModifyLockStatus_Test_007 + * @tc.desc: Abnormal testCase of ModifyLockStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ModifyLockStatusk_Test_007, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + AbsRdbPredicates predicates("test"); + auto res = store->ModifyLockStatus(predicates, false); + EXPECT_EQ(E_NO_ROW_IN_QUERY, res); +} + +/** + * @tc.name: LockCloudContainer_Test_001 + * @tc.desc: Abnormal testCase of LockCloudContainer + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, LockCloudContainer_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_MEMORY); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + auto res1 = store->LockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res1.first); + auto res2 = store->UnlockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res2); +} + +/** + * @tc.name: LockCloudContainer_Test_002 + * @tc.desc: Abnormal testCase of LockCloudContainer + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, LockCloudContainer_Test_002, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + config.SetReadOnly(false); + config.SetIsVector(true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + auto res1 = store->LockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res1.first); + auto res2 = store->UnlockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res2); +} + +/** + * @tc.name: LockCloudContainer_Test_003 + * @tc.desc: Abnormal testCase of LockCloudContainer + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, LockCloudContainer_Test_003, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + config.SetReadOnly(true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + auto res1 = store->LockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res1.first); + auto res2 = store->UnlockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res2); +} + +/** + * @tc.name: LockCloudContainer_Test_004 + * @tc.desc: Abnormal testCase of LockCloudContainer + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, LockCloudContainer_Test_004, TestSize.Level2) +{ + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + store = nullptr; + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(true); + store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + auto res1 = store->LockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res1.first); + auto res2 = store->UnlockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res2); +} + +/** + * @tc.name: LockCloudContainer_Test_005 + * @tc.desc: Abnormal testCase of LockCloudContainer + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, LockCloudContainer_Test_005, TestSize.Level2) +{ + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_NOT_SUPPORT, nullptr))); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + auto res1 = store->LockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res1.first); + auto res2 = store->UnlockCloudContainer(); + EXPECT_EQ(E_NOT_SUPPORT, res2); +} + +/** + * @tc.name: Vector_Test_001 + * @tc.desc: Abnormal testCase of VectorDB + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Vector_Test_001, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetDBType(DB_VECTOR); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + const std::string sql; + const ValueObjects bindArgs; + auto res1 = store->QuerySql(sql, bindArgs); + ASSERT_EQ(nullptr, res1); + const AbsRdbPredicates predicates("test"); + int64_t outValue; + std::string valueString; + auto res2 = store->Count(outValue, predicates); + EXPECT_EQ(E_NOT_SUPPORT, res2); + auto res3 = store->ExecuteAndGetString(valueString, sql, bindArgs); + EXPECT_EQ(E_NOT_SUPPORT, res3); +} + +/** + * @tc.name: ExecuteForChangedRowCount_Test_001 + * @tc.desc: Abnormal testCase of ExecuteForChangedRowCount + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ExecuteForChangedRowCount_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + store = nullptr; + config.SetDBType(DB_SQLITE); + config.SetReadOnly(true); + store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + int64_t outValue; + const std::string sql; + const ValueObjects bindArgs; + auto res = store->ExecuteForChangedRowCount(outValue, sql, bindArgs); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: ExecuteForChangedRowCount_Test_002 + * @tc.desc: Abnormal testCase of ExecuteForChangedRowCount + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ExecuteForChangedRowCount_Test_002, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetDBType(DB_VECTOR); + config.SetReadOnly(true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + int64_t outValue; + const std::string sql; + const ValueObjects bindArgs; + auto res = store->ExecuteForChangedRowCount(outValue, sql, bindArgs); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: ExecuteForChangedRowCount_Test_003 + * @tc.desc: Abnormal testCase of ExecuteForChangedRowCount + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ExecuteForChangedRowCount_Test_003, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetDBType(DB_VECTOR); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + int64_t outValue; + const std::string sql; + const ValueObjects bindArgs; + auto res = store->ExecuteForChangedRowCount(outValue, sql, bindArgs); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: SetDefaultEncryptSql_Test_001 + * @tc.desc: Abnormal testCase of SetDefaultEncryptSql + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDefaultEncryptSql_Test_001, TestSize.Level2) +{ + EXPECT_CALL(*mockStatement, Prepare(_)).WillOnce(Return(E_ERROR)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + auto storeImpl = std::make_shared(config); + const std::string sql = "SELECT * FROM employee"; + auto res = storeImpl->SetDefaultEncryptSql(mockStatement, sql, config); + EXPECT_EQ(E_ERROR, res); +} + +/** + * @tc.name: SetDefaultEncryptSql_Test_002 + * @tc.desc: Abnormal testCase of SetDefaultEncryptSql + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDefaultEncryptSql_Test_002, TestSize.Level2) +{ + std::vector args; + EXPECT_CALL(*mockStatement, Prepare(_)).WillOnce(Return(E_OK)); + EXPECT_CALL(*mockStatement, Execute(args)).WillOnce(Return(E_SQLITE_BUSY)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + auto storeImpl = std::make_shared(config); + const std::string sql = "SELECT * FROM employee"; + auto res = storeImpl->SetDefaultEncryptSql(mockStatement, sql, config); + EXPECT_EQ(E_SQLITE_BUSY, res); +} + +/** + * @tc.name: SetDefaultEncryptAlgo_Test_001 + * @tc.desc: Abnormal testCase of SetDefaultEncryptAlgo + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDefaultEncryptAlgo_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->SetDefaultEncryptAlgo(nullptr, config); + EXPECT_EQ(E_DATABASE_BUSY, res); +} + +/** + * @tc.name: SetDefaultEncryptAlgo_Test_002 + * @tc.desc: Abnormal testCase of SetDefaultEncryptAlgo + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDefaultEncryptAlgo_Test_002, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + RdbStoreConfig::CryptoParam cryptoParam; + config.SetCryptoParam(cryptoParam); + config.SetIter(-1); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->SetDefaultEncryptAlgo(mockConnection, config); + EXPECT_EQ(E_INVALID_ARGS, res); +} + +/** + * @tc.name: SetDefaultEncryptAlgo_Test_003 + * @tc.desc: Abnormal testCase of SetDefaultEncryptAlgo + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDefaultEncryptAlgo_Test_003, TestSize.Level2) +{ + EXPECT_CALL(*mockConnection, CreateStatement(_, _)).WillOnce(Return(std::make_pair(E_OK, mockStatement))); + EXPECT_CALL(*mockStatement, Prepare(_)).WillOnce(Return(E_ERROR)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + RdbStoreConfig::CryptoParam cryptoParam; + config.SetCryptoParam(cryptoParam); + config.SetIter(1); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->SetDefaultEncryptAlgo(mockConnection, config); + EXPECT_EQ(E_ERROR, res); +} + +/** + * @tc.name: SetDefaultEncryptAlgo_Test_004 + * @tc.desc: Abnormal testCase of SetDefaultEncryptAlgo + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDefaultEncryptAlgo_Test_004, TestSize.Level2) +{ + EXPECT_CALL(*mockConnection, CreateStatement(_, _)).WillOnce(Return(std::make_pair(E_OK, mockStatement))); + std::vector args; + EXPECT_CALL(*mockStatement, Prepare(_)).WillOnce(Return(E_OK)).WillOnce(Return(E_ERROR)); + EXPECT_CALL(*mockStatement, Execute(args)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + RdbStoreConfig::CryptoParam cryptoParam; + config.SetCryptoParam(cryptoParam); + config.SetIter(1); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->SetDefaultEncryptAlgo(mockConnection, config); + EXPECT_EQ(E_ERROR, res); +} + +/** + * @tc.name: SetDefaultEncryptAlgo_Test_005 + * @tc.desc: Abnormal testCase of SetDefaultEncryptAlgo + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDefaultEncryptAlgo_Test_005, TestSize.Level2) +{ + EXPECT_CALL(*mockConnection, CreateStatement(_, _)).WillOnce(Return(std::make_pair(E_OK, mockStatement))); + std::vector args; + EXPECT_CALL(*mockStatement, Prepare(_)).WillOnce(Return(E_OK)).WillOnce(Return(E_OK)).WillOnce(Return(E_ERROR)); + EXPECT_CALL(*mockStatement, Execute(args)).WillOnce(Return(E_OK)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + RdbStoreConfig::CryptoParam cryptoParam; + config.SetCryptoParam(cryptoParam); + config.SetIter(1); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->SetDefaultEncryptAlgo(mockConnection, config); + EXPECT_EQ(E_ERROR, res); +} + +/** + * @tc.name: SetDefaultEncryptAlgo_Test_006 + * @tc.desc: Abnormal testCase of SetDefaultEncryptAlgo + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, SetDefaultEncryptAlgo_Test_006, TestSize.Level2) +{ + EXPECT_CALL(*mockConnection, CreateStatement(_, _)).WillOnce(Return(std::make_pair(E_OK, mockStatement))); + std::vector args; + EXPECT_CALL(*mockStatement, Prepare(_)) + .WillOnce(Return(E_OK)) + .WillOnce(Return(E_OK)) + .WillOnce(Return(E_OK)) + .WillOnce(Return(E_ERROR)); + EXPECT_CALL(*mockStatement, Execute(args)).WillOnce(Return(E_OK)).WillOnce(Return(E_OK)).WillOnce(Return(E_OK)); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + RdbStoreConfig::CryptoParam cryptoParam; + config.SetCryptoParam(cryptoParam); + config.SetIter(1); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->SetDefaultEncryptAlgo(mockConnection, config); + EXPECT_EQ(E_ERROR, res); +} + +/** + * @tc.name: Backup_Test_001 + * @tc.desc: Abnormal testCase of Backup + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Backup_Test_001, TestSize.Level2) +{ + auto mockRdbService = std::make_shared(); + EXPECT_CALL(*mockRdbManagerImpl, GetRdbService(_)).WillRepeatedly(Return(std::make_pair(E_OK, mockRdbService))); + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetReadOnly(false); + config.SetHaMode(HAMode::SINGLE); + config.SetIter(1); + config.SetEncryptStatus(true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector encryptKey; + auto res = store->Backup(RdbStoreImplConditionTest::DATABASE_BACKUP_NAME, encryptKey); + EXPECT_EQ(E_OK, res); +} + +/** + * @tc.name: Backup_Test_002 + * @tc.desc: Abnormal testCase of Backup + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Backup_Test_002, TestSize.Level2) +{ + std::vector args; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetReadOnly(false); + config.SetHaMode(HAMode::SINGLE); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + std::vector encryptKey; + auto res = store->Backup(RdbStoreImplConditionTest::DATABASE_BACKUP_NAME, encryptKey); + EXPECT_EQ(E_OK, res); +} + +/** + * @tc.name: Attach_Test_001 + * @tc.desc: Abnormal testCase of Attach + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Attach_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetEncryptStatus(true); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + RdbStoreConfig config1(RdbStoreImplConditionTest::DATABASE_NAME); + config1.SetReadOnly(false); + config1.SetDBType(DB_SQLITE); + config1.SetHaMode(HAMode::SINGLE); + config1.SetStorageMode(StorageMode::MODE_DISK); + config1.SetEncryptStatus(false); + auto res = store->Attach(config1, "test", 0); + EXPECT_EQ(E_NOT_SUPPORT, res.first); +} + +/** + * @tc.name: ExecuteByTrxId_Test_001 + * @tc.desc: Abnormal testCase of ExecuteByTrxId + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ExecuteByTrxId_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetIsVector(true); + auto storeImpl = std::make_shared(config); + std::vector bindArgs; + auto res = storeImpl->ExecuteByTrxId("sql", 0, false); + EXPECT_EQ(E_INVALID_ARGS, res); +} + +/** + * @tc.name: ExecuteByTrxId_Test_002 + * @tc.desc: Abnormal testCase of ExecuteByTrxId + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, ExecuteByTrxId_Test_002, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetIsVector(true); + auto storeImpl = std::make_shared(config); + std::vector bindArgs; + auto res = storeImpl->ExecuteByTrxId("sql", 1, false); + EXPECT_EQ(E_INVALID_ARGS, res); +} + +/** + * @tc.name: Restore_Test_001 + * @tc.desc: Abnormal testCase of Restore + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Restore_Test_001, TestSize.Level2) +{ + std::vector newKey; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(true); + config.SetStorageMode(StorageMode::MODE_MEMORY); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->Restore("test.db", newKey); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: Restore_Test_002 + * @tc.desc: Abnormal testCase of Restore + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Restore_Test_002, TestSize.Level2) +{ + std::vector newKey; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetStorageMode(StorageMode::MODE_MEMORY); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->Restore("test.db", newKey); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: Restore_Test_003 + * @tc.desc: Abnormal testCase of Restore + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, Restore_Test_003, TestSize.Level2) +{ + std::vector newKey; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetReadOnly(true); + config.SetStorageMode(StorageMode::MODE_DISK); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->Restore("test.db", newKey); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: GetStatement_Test_001 + * @tc.desc: Abnormal testCase of GetStatement + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, GetStatement_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + auto storeImpl = std::make_shared(config); + const std::string sql = "ATTACH DATABASE 'database.db';"; + auto res = storeImpl->GetStatement(sql, nullptr); + EXPECT_EQ(E_DATABASE_BUSY, res.first); +} + +/** + * @tc.name: InterruptBackup_Test_001 + * @tc.desc: Abnormal testCase of InterruptBackup + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, InterruptBackup_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetHaMode(HAMode::SINGLE); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->InterruptBackup(); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: InterruptBackup_Test_003 + * @tc.desc: Abnormal testCase of InterruptBackup + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, InterruptBackup_Test_003, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetHaMode(HAMode::MANUAL_TRIGGER); + auto storeImpl = std::make_shared(config); + *(storeImpl->slaveStatus_) = BACKING_UP; + auto res = storeImpl->InterruptBackup(); + EXPECT_EQ(E_OK, res); +} + +/** + * @tc.name: GetBackupStatus_Test_001 + * @tc.desc: Abnormal testCase of GetBackupStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, GetBackupStatus_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetHaMode(HAMode::SINGLE); + auto storeImpl = std::make_shared(config); + auto res = storeImpl->GetBackupStatus(); + EXPECT_EQ(UNDEFINED, res); +} + +/** + * @tc.name: GetBackupStatus_Test_002 + * @tc.desc: Abnormal testCase of GetBackupStatus + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, GetBackupStatus_Test_002, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetHaMode(HAMode::MANUAL_TRIGGER); + auto storeImpl = std::make_shared(config); + *(storeImpl->slaveStatus_) = BACKING_UP; + auto res = storeImpl->GetBackupStatus(); + EXPECT_EQ(BACKING_UP, res); +} + +/** + * @tc.name: CleanDirtyLog_Test_001 + * @tc.desc: Abnormal testCase of CleanDirtyLog + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, CleanDirtyLog_Test_001, TestSize.Level2) +{ + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_MEMORY); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + uint64_t cursor = 0; + auto res = store->CleanDirtyLog("test", cursor); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: CleanDirtyLog_Test_002 + * @tc.desc: Abnormal testCase of CleanDirtyLog + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, CleanDirtyLog_Test_002, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_VECTOR); + config.SetReadOnly(false); + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + uint64_t cursor = 0; + auto res = store->CleanDirtyLog("test", cursor); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: CleanDirtyLog_Test_004 + * @tc.desc: Abnormal testCase of CleanDirtyLog + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, CleanDirtyLog_Test_004, TestSize.Level2) +{ + RdbStoreImplConditionTestOpenCallback helper; + int errCode; + RdbStoreConfig config(RdbStoreImplConditionTest::DATABASE_NAME); + std::shared_ptr store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + store = nullptr; + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetDBType(DB_SQLITE); + config.SetReadOnly(true); + store = RdbHelper::GetRdbStore(config, 0, helper, errCode); + ASSERT_NE(store, nullptr) << "store is null"; + uint64_t cursor = 0; + auto res = store->CleanDirtyLog("test", cursor); + EXPECT_EQ(E_NOT_SUPPORT, res); +} + +/** + * @tc.name: CloudTables::Change_Test_001 + * @tc.desc: Abnormal testCase of CloudTables::Change + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, CloudTables_Change_Test_001, TestSize.Level2) +{ + auto cloudTables = std::make_shared(); + std::string table = ""; + auto res = cloudTables->Change(table); + EXPECT_EQ(false, res); + cloudTables->AddTables({ "test1" }); + std::string table1 = "test"; + res = cloudTables->Change(table1); + EXPECT_EQ(false, res); + cloudTables->AddTables({ "test" }); + std::string table2 = "test"; + res = cloudTables->Change(table2); + EXPECT_EQ(true, res); + res = cloudTables->Change(table); + EXPECT_EQ(false, res); +} + +/** + * @tc.name: RdbStore_GetValues_002 + * @tc.desc: test RdbStore GetValues + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, RdbStore_GetValues_002, TestSize.Level1) +{ + EXPECT_EQ(OHOS::NativeRdb::RdbStoreImpl::GetValues(nullptr), nullptr); + uint32_t maxReturningRows = 1024; + std::vector valuesBuckets; + EXPECT_CALL(*mockStatement, GetRows(maxReturningRows)) + .WillOnce(Return(std::make_pair(E_ERROR, valuesBuckets))); + auto resultSet = RdbStoreImpl::GetValues(mockStatement); + ASSERT_NE(nullptr, resultSet); + int rowCount = -1; + ASSERT_EQ(resultSet->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); +} + +/** + * @tc.name: RdbStore_GetValues_003 + * @tc.desc: test RdbStore GetValues + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplConditionTest, RdbStore_GetValues_003, TestSize.Level1) +{ + uint32_t maxReturningRows = 1024; + auto [code, statement] = + static_cast(store_.get())->GetStatement("PRAGMA user_version = 1;", true); + ASSERT_EQ(E_OK, code); + ASSERT_NE(nullptr, statement); + auto [ret, valuesBucket] = statement->GetRows(maxReturningRows); + ASSERT_EQ(E_OK, ret); + + std::vector valuesBuckets; + for (int i = 0; i < maxReturningRows; i++) { + ValuesBucket valuesBucket; + valuesBucket.Put("name", "test"); + valuesBuckets.push_back(std::move(valuesBucket)); + } + + EXPECT_CALL(*mockStatement, GetRows(maxReturningRows)) + .WillOnce(Return(std::make_pair(E_OK, valuesBuckets))) + .WillOnce(Return(std::make_pair(E_NO_MORE_ROWS, valuesBuckets))); + auto resultSet = RdbStoreImpl::GetValues(mockStatement); + ASSERT_NE(nullptr, resultSet); + int rowCount = -1; + ASSERT_EQ(resultSet->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1024); +} diff --git a/relational_store/test/native/rdb/unittest/multiThread/rdb_connection_rd_test.cpp b/relational_store/test/native/rdb/unittest/multiThread/rdb_connection_rd_test.cpp index d9a99944..49fe3814 100644 --- a/relational_store/test/native/rdb/unittest/multiThread/rdb_connection_rd_test.cpp +++ b/relational_store/test/native/rdb/unittest/multiThread/rdb_connection_rd_test.cpp @@ -19,7 +19,7 @@ #include #include -#include "../common.h" +#include "common.h" #include "block_data.h" #include "executor_pool.h" #include "rd_utils.h" diff --git a/relational_store/test/native/rdb/unittest/multiThread/rdb_connection_test.cpp b/relational_store/test/native/rdb/unittest/multiThread/rdb_connection_test.cpp index e42b3214..e9f7a6a9 100644 --- a/relational_store/test/native/rdb/unittest/multiThread/rdb_connection_test.cpp +++ b/relational_store/test/native/rdb/unittest/multiThread/rdb_connection_test.cpp @@ -19,7 +19,7 @@ #include #include -#include "../common.h" +#include "common.h" #include "block_data.h" #include "executor_pool.h" #include "rdb_errno.h" diff --git a/relational_store/test/native/rdb/unittest/multiThread/rdb_store_multiprocess_createDB_test.cpp b/relational_store/test/native/rdb/unittest/multiThread/rdb_store_multiprocess_createDB_test.cpp index 6758a23e..2b58b803 100644 --- a/relational_store/test/native/rdb/unittest/multiThread/rdb_store_multiprocess_createDB_test.cpp +++ b/relational_store/test/native/rdb/unittest/multiThread/rdb_store_multiprocess_createDB_test.cpp @@ -25,7 +25,7 @@ #include #include -#include "../common.h" +#include "common.h" #include "rdb_errno.h" #include "rdb_helper.h" #include "rdb_open_callback.h" diff --git a/relational_store/test/native/rdb/unittest/rd_utils_test.cpp b/relational_store/test/native/rdb/unittest/rd_utils_test.cpp index a7f3c32b..e9c32ce6 100644 --- a/relational_store/test/native/rdb/unittest/rd_utils_test.cpp +++ b/relational_store/test/native/rdb/unittest/rd_utils_test.cpp @@ -19,14 +19,43 @@ #include #include +#include #include +#include #include +#include +#include "grd_api_manager.h" #include "grd_type_export.h" +#include "rdb_helper.h" +#include "task_executor.h" using namespace testing::ext; using namespace OHOS::NativeRdb; +static std::mutex g_mutex; +static std::unordered_set allocatedAddresses; +static bool g_isRecord = false; + +void *operator new[](size_t size, const std::nothrow_t &tag) noexcept +{ + void *ptr = std::malloc(size); + if (g_isRecord && ptr != nullptr) { + std::lock_guard lock(g_mutex); + allocatedAddresses.insert(ptr); + } + return ptr; +} + +void operator delete[](void *ptr) noexcept +{ + if (g_isRecord && ptr != nullptr) { + std::lock_guard lock(g_mutex); + allocatedAddresses.erase(ptr); + } + std::free(ptr); +} + namespace Test { class RdUtilsTest : public testing::Test { public: @@ -38,10 +67,21 @@ public: void RdUtilsTest::SetUpTestCase(void) { + std::lock_guard lock(g_mutex); + g_isRecord = true; } void RdUtilsTest::TearDownTestCase(void) { + std::lock_guard lock(g_mutex); + g_isRecord = false; +} + +static void ScheduleMock(void *param) +{ + (void)param; + int sleepTime = 20; + std::this_thread::sleep_for(std::chrono::seconds(sleepTime)); } /** @@ -65,4 +105,109 @@ HWTEST_F(RdUtilsTest, RdUtils_Test_002, TestSize.Level1) EXPECT_EQ(RdUtils::TransferGrdTypeToColType(GRD_DB_DATATYPE_FLOATVECTOR), ColumnType::TYPE_FLOAT32_ARRAY); EXPECT_EQ(RdUtils::TransferGrdTypeToColType(GRD_DB_DATATYPE_NULL), ColumnType::TYPE_NULL); } + +/** + * @tc.name: RdUtils_Test_003 + * @tc.desc: Test RdSqlRegistryThreadPool + * @tc.type: FUNC + */ +HWTEST_F(RdUtilsTest, RdUtils_Test_003, TestSize.Level1) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + std::string dbPath = "/data/test/execute_test.db"; + std::string configStr = "{}"; + RdbHelper::DeleteRdbStore(dbPath); + + GRD_DB *db = nullptr; + EXPECT_EQ(RdUtils::RdDbOpen(dbPath.c_str(), configStr.c_str(), GRD_DB_OPEN_CREATE, &db), E_OK); + ASSERT_EQ(RdUtils::RdSqlRegistryThreadPool(db), E_OK); + + ASSERT_NE(RdUtils::threadPool_.schedule, nullptr); + ASSERT_NE(RdUtils::threadPool_.remove, nullptr); + +// TaskExecutor::TaskId taskId = RdUtils::threadPool_.schedule(reinterpret_cast(ScheduleMock), nullptr); +// ASSERT_NE(static_cast(taskId), TaskExecutor::INVALID_TASK_ID); + + int sleepTime = 2; + std::this_thread::sleep_for(std::chrono::seconds(sleepTime)); + +// bool ret = RdUtils::threadPool_.remove(static_cast(taskId), false); + // expect false because this task is running, will remove from exec list +// ASSERT_FALSE(ret); + + EXPECT_EQ(RdUtils::RdDbClose(db, 0), E_OK); + RdbHelper::DeleteRdbStore(dbPath); +} + +/** + * @tc.name: RdUtils_Test_004 + * @tc.desc: Test bind empty string + * @tc.type: FUNC + */ +HWTEST_F(RdUtilsTest, RdUtils_Test_004, TestSize.Level1) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + GRD_SqlStmt *stmt = nullptr; + uint32_t idx = 0; + const char *str = ""; + EXPECT_EQ(RdUtils::RdSqlBindText(stmt, idx, str, -1, nullptr), E_INVALID_ARGS); + EXPECT_EQ(RdUtils::RdSqlBindText(stmt, idx, str, 0, nullptr), E_INVALID_ARGS); +} + +/** + * @tc.name: RdUtils_Test_005 + * @tc.desc: Test RdSqlBindBlob + * @tc.type: FUNC + */ +HWTEST_F(RdUtilsTest, RdUtils_Test_005, TestSize.Level0) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + GRD_SqlStmt *stmtHandle = nullptr; + const uint8_t testData[] = { 0x05, 0x06 }; + const int32_t dataLen = sizeof(testData); + auto ret = RdUtils::RdSqlBindBlob(stmtHandle, 1, testData, dataLen, nullptr); + EXPECT_EQ(ret, E_INVALID_ARGS); + EXPECT_TRUE(allocatedAddresses.empty()); +} + +/** + * @tc.name: RdUtils_Test_006 + * @tc.desc: Test RdSqlBindBlob + * @tc.type: FUNC + */ +HWTEST_F(RdUtilsTest, RdUtils_Test_006, TestSize.Level0) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + GRD_SqlStmt *stmtHandle = nullptr; + const char *testStr = "Test"; + auto ret = RdUtils::RdSqlBindText(stmtHandle, 1, testStr, strlen(testStr), nullptr); + EXPECT_EQ(ret, E_INVALID_ARGS); + EXPECT_TRUE(allocatedAddresses.empty()); +} + +/** + * @tc.name: RdUtils_Test_007 + * @tc.desc: Test RdSqlBindFloatVector + * @tc.type: FUNC + */ +HWTEST_F(RdUtilsTest, RdUtils_Test_007, TestSize.Level0) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + GRD_SqlStmt *stmtHandle = nullptr; + float testData[] = { 1.1f, 2.2f, 3.3f }; + uint32_t dim = sizeof(testData) / sizeof(float); + auto ret = RdUtils::RdSqlBindFloatVector(stmtHandle, 2, testData, dim, nullptr); + EXPECT_EQ(ret, E_INVALID_ARGS); + EXPECT_TRUE(allocatedAddresses.empty()); +} } // namespace Test diff --git a/relational_store/test/native/rdb/unittest/rdb_callback_icu_test.cpp b/relational_store/test/native/rdb/unittest/rdb_callback_icu_test.cpp new file mode 100644 index 00000000..50cc488c --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_callback_icu_test.cpp @@ -0,0 +1,166 @@ +/* + * 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. + */ +#define LOG_TAG "RdbCallbackIcuTest" +#include + +#include + +#include "common.h" +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + +using namespace testing::ext; +using namespace OHOS::Rdb; +using namespace OHOS::NativeRdb; + +class RdbCallbackIcuTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static const std::string databaseName; +}; + +const std::string RdbCallbackIcuTest::databaseName = RDB_TEST_PATH + "open_helper.db"; + +void RdbCallbackIcuTest::SetUpTestCase(void) +{ +} + +void RdbCallbackIcuTest::TearDownTestCase(void) +{ + RdbHelper::DeleteRdbStore(RdbCallbackIcuTest::databaseName); +} + +void RdbCallbackIcuTest::SetUp(void) +{ +} + +void RdbCallbackIcuTest::TearDown(void) +{ + RdbHelper::ClearCache(); +} + +class OpenCallbackIcu : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + int OnDowngrade(RdbStore &store, int oldVersion, int newVersion) override; + int OnOpen(RdbStore &store) override; + + static std::string CreateTableSQL(const std::string &tableName); + static std::string DropTableSQL(const std::string &tableName); +}; + +std::string OpenCallbackIcu::CreateTableSQL(const std::string &tableName) +{ + return "CREATE VIRTUAL TABLE IF NOT EXISTS " + tableName + " USING fts4(name, content, tokenize=icu zh_CN);"; +} + +std::string OpenCallbackIcu::DropTableSQL(const std::string &tableName) +{ + return "DROP TABLE IF EXISTS " + tableName + ";"; +} + +int OpenCallbackIcu::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CreateTableSQL("test1")); +} + +int OpenCallbackIcu::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +int OpenCallbackIcu::OnDowngrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +int OpenCallbackIcu::OnOpen(RdbStore &store) +{ + return E_OK; +} + +/** + * @tc.name: RdbCallbackIcu_01 + * @tc.desc: test RdbCallbackIcu + * @tc.type: FUNC + */ +HWTEST_F(RdbCallbackIcuTest, RdbCallbackIcu_01, TestSize.Level1) +{ + RdbStoreConfig config(RdbCallbackIcuTest::databaseName); + config.SetTokenizer(ICU_TOKENIZER); + OpenCallbackIcu helper; + + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + const char *sqlCreateTable = "CREATE VIRTUAL TABLE example USING fts4(name, content, tokenize=icu zh_CN);"; + int ret = store->ExecuteSql(sqlCreateTable); + EXPECT_EQ(ret, E_OK); + + const char *sqlInsert1 = + "INSERT INTO example(name, content) VALUES('文档1', '这是一个测试文档,用于测试中文文本的分词和索引。');"; + ret = store->ExecuteSql(sqlInsert1); + EXPECT_EQ(ret, E_OK); + + const char *sqlInsert2 = + "INSERT INTO example(name, content) VALUES('文档2', '我们将使用这个示例来演示如何在SQLite中进行全文搜索。');"; + ret = store->ExecuteSql(sqlInsert2); + EXPECT_EQ(ret, E_OK); + + const char *sqlInsert3 = + "INSERT INTO example(name, content) VALUES('文档3', 'ICU分词器能够很好地处理中文文本的分词和分析。');"; + ret = store->ExecuteSql(sqlInsert3); + EXPECT_EQ(ret, E_OK); + + const char *sqlQuery = "SELECT * FROM example WHERE example MATCH '测试';"; + ret = store->ExecuteSql(sqlQuery); + EXPECT_EQ(ret, E_OK); + + std::shared_ptr resultSet = store->QuerySql(sqlQuery); + ASSERT_NE(resultSet, nullptr); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + + int columnIndex; + std::string strVal; + + ret = resultSet->GetColumnIndex("name", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ("文档1", strVal); + + ret = resultSet->GetColumnIndex("content", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ("这是一个测试文档,用于测试中文文本的分词和索引。", strVal); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ROW_OUT_RANGE); + + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_concurrent_querywithcurd_test.cpp b/relational_store/test/native/rdb/unittest/rdb_concurrent_querywithcurd_test.cpp new file mode 100644 index 00000000..7e6817c3 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_concurrent_querywithcurd_test.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 + +#include "common.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "values_bucket.h" +using namespace testing::ext; +using namespace OHOS::NativeRdb; +namespace Test { +class QueryWithCrudTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(void); + void TearDown(void); + void InsertData(int rowCount, int size); + static std::shared_ptr rdbStore_; + static constexpr const char *DATABASE_PATH = "/data/test/queryWithCrud_test.db"; + static constexpr const char *CREATE_TABLE = "CREATE TABLE IF NOT EXISTS test(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"; + static constexpr const char *DROP_TABLE = "DROP TABLE IF EXISTS test"; + const double SALARY = 100.5; + + class RdbCallback : public RdbOpenCallback { + public: + int OnCreate(RdbStore &store) override + { + return E_OK; + } + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override + { + return E_OK; + } + }; +}; +std::shared_ptr QueryWithCrudTest::rdbStore_; +void QueryWithCrudTest::SetUpTestCase(void) +{ + int errCode = E_OK; + RdbCallback callback; + RdbStoreConfig config(DATABASE_PATH); + RdbHelper::DeleteRdbStore(DATABASE_PATH); + rdbStore_ = RdbHelper::GetRdbStore(config, 1, callback, errCode); + ASSERT_NE(rdbStore_, nullptr); +} + +void QueryWithCrudTest::TearDownTestCase(void) +{ + rdbStore_ = nullptr; + RdbHelper::DeleteRdbStore(DATABASE_PATH); +} +void QueryWithCrudTest::SetUp(void) +{ + rdbStore_->ExecuteSql(DROP_TABLE); + rdbStore_->ExecuteSql(CREATE_TABLE); +} + +void QueryWithCrudTest::TearDown(void) +{ + rdbStore_->ExecuteSql(DROP_TABLE); +} +void QueryWithCrudTest::InsertData(int rowCount, int size) +{ + EXPECT_GT(rowCount, 0); + EXPECT_GT(size, 0); + int64_t id; + ValuesBucket values; + std::vector u8(size, 1); + std::vector valuesBuckets; + for (int i = 0; i < rowCount; i++) { + values.Put("name", "zhangsan" + std::to_string(i)); + values.Put("age", i); + values.Put("salary", SALARY); + values.Put("blobType", u8); + valuesBuckets.push_back(values); + } + auto ret = rdbStore_->BatchInsert(id, "test", valuesBuckets); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(id, rowCount); +} +/** + * @tc.name: QueryWithDelete_001 + * @tc.desc: 10 records with a total of less than 2M data, + * delete 3 records, rowCount equals 7 records. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithDelete_001, TestSize.Level1) +{ + InsertData(10, 1); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.Between("age", 5, 7); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 3); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 7); +} + +/** + * @tc.name: QueryWithDelete_002 + * @tc.desc: 10 pieces of 1M data, delete 3 pieces, rowCount equals 7 pieces. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithDelete_002, TestSize.Level1) +{ + InsertData(10, 1024 * 1024); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.Between("age", 5, 7); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 3); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 7); +} + +/** + * @tc.name: QueryWithDelete_003 + * @tc.desc: Single data exceeding 2M can return an error normally + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithDelete_003, TestSize.Level1) +{ + InsertData(2, 1024 * 1024 * 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.EqualTo("age", 1); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 1); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ERROR); +} + +/** + * @tc.name: QueryWithDelete_004 + * @tc.desc: 2 pieces of single 2M data, delete 2 pieces, rowCount equals 0. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithDelete_004, TestSize.Level1) +{ + InsertData(2, 1024 * 1024 * 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.Between("age", 0, 1); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 2); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 0); +} + +/** + * @tc.name: QueryWithDelete_005 + * @tc.desc: 10 pieces of data, one of which is greater than 2M, the other 1M, + * delete 9 pieces of data less than 1M, expect an error. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithDelete_005, TestSize.Level1) +{ + InsertData(9, 2); + InsertData(1, 1024 * 1024 * 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.Between("id", 1, 9); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 9); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ERROR); +} + +/** + * @tc.name: QueryWithDelete_006 + * @tc.desc: 10 pieces of data, one of which is greater than 2M, the other 1M, + * delete data greater than 2M, rowCount is 9. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithDelete_006, TestSize.Level1) +{ + InsertData(9, 2); + InsertData(1, 1024 * 1024 * 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.EqualTo("id", 10); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 1); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 9); +} + +/** + * @tc.name: QueryWithDelete_007 + * @tc.desc: 10 records with a total of less than 2M data, + * delete 10 records, rowCount equals 0 records. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithDelete_007, TestSize.Level1) +{ + InsertData(10, 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 10); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 0); +} + +/** + * @tc.name: QueryWithInsert_001 + * @tc.desc: 10 pieces of data with a total size less than 2M, delete 3 pieces, + * insert 1 piece of data with a single size less than 1M, rowCount is equal to 8. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithInsert_001, TestSize.Level1) +{ + InsertData(10, 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.Between("age", 5, 7); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 3); + EXPECT_EQ(res, E_OK); + InsertData(1, 2); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 8); +} + +/** + * @tc.name: QueryWithInsert_002 + * @tc.desc: 10 pieces of data with a total size less than 2M, delete 4 pieces, + * insert 3 pieces of data with a single size less than 2M, rowCount is equal to 9. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithInsert_002, TestSize.Level1) +{ + InsertData(10, 1024 * 1024); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.Between("age", 1, 4); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 4); + EXPECT_EQ(res, E_OK); + InsertData(3, 2); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 9); +} + +/** + * @tc.name: QueryWithInsert_003 + * @tc.desc: 3 pieces of data larger than 2M, delete 2 pieces, + * insert 1 piece of data smaller than 1M, expect an error. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithInsert_003, TestSize.Level1) +{ + InsertData(3, 1024 * 1024 * 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.Between("age", 0, 1); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 2); + EXPECT_EQ(res, E_OK); + InsertData(1, 2); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ERROR); +} + +/** + * @tc.name: QueryWithInsert_004 + * @tc.desc: 2 pieces of data larger than 2M, delete 2 pieces, + * insert 1 piece of data smaller than 1M, rowCount is equal to 1. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithInsert_004, TestSize.Level1) +{ + InsertData(2, 1024 * 1024 * 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 2); + EXPECT_EQ(res, E_OK); + InsertData(1, 2); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 1); +} + +/** + * @tc.name: QueryWithInsert_005 + * @tc.desc: 10 pieces of data with a total of less than 2M, delete 6 pieces, + * insert 1 pieces of data with a single value greater than 2M, expect an error. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithInsert_005, TestSize.Level1) +{ + InsertData(10, 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + predicates.Between("age", 0, 5); + int deletedRows; + auto res = rdbStore_->Delete(deletedRows, predicates); + EXPECT_EQ(deletedRows, 6); + EXPECT_EQ(res, E_OK); + InsertData(1, 1024 * 1024 * 2); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ERROR); +} + +/** + * @tc.name: QueryWithUpdate_001 + * @tc.desc: 10 records with a total of less than 2M data, updated 3 records, rowCount is 10. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithUpdate_001, TestSize.Level1) +{ + InsertData(10, 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + int updatedRows; + ValuesBucket values; + std::vector u8(2, 1); + predicates.Between("age", 0, 2); + values.Put("name", "zhangsan30"); + values.Put("age", 30); + values.Put("salary", SALARY); + values.Put("blobType", u8); + auto res = rdbStore_->Update(updatedRows, values, predicates); + EXPECT_EQ(updatedRows, 3); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 10); +} + +/** + * @tc.name: QueryWithUpdate_002 + * @tc.desc: 10 pieces of single data less than 1M, update 3 pieces, rowCount is 10. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithUpdate_002, TestSize.Level1) +{ + InsertData(10, 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + int updatedRows; + ValuesBucket values; + std::vector bigU8(1024 * 1024 * 2, 1); + predicates.Between("age", 0, 2); + values.Put("name", "zhangsan30"); + values.Put("age", 30); + values.Put("salary", SALARY); + values.Put("blobType", bigU8); + auto res = rdbStore_->Update(updatedRows, values, predicates); + EXPECT_EQ(updatedRows, 3); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ERROR); +} + +/** + * @tc.name: QueryWithUpdate_003 + * @tc.desc: 2 pieces of data larger than 2M, update 2 pieces of data smaller than 1M, + * rowCount is 2. + * @tc.type: FUNC + */ +HWTEST_F(QueryWithCrudTest, QueryWithUpdate_003, TestSize.Level1) +{ + InsertData(2, 1024 * 1024 * 2); + AbsRdbPredicates predicates("test"); + auto resultSet = rdbStore_->Query(predicates); + ASSERT_NE(resultSet, nullptr); + int updatedRows; + ValuesBucket values; + std::vector u8(2, 1); + predicates.Between("age", 0, 1); + values.Put("name", "zhangsan30"); + values.Put("age", 30); + values.Put("salary", SALARY); + values.Put("blobType", u8); + auto res = rdbStore_->Update(updatedRows, values, predicates); + EXPECT_EQ(updatedRows, 2); + EXPECT_EQ(res, E_OK); + int errCode = E_OK; + while ((errCode = resultSet->GoToNextRow()) == E_OK) { + } + EXPECT_EQ(errCode, E_ROW_OUT_RANGE); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 2); +} +} // namespace Test diff --git a/relational_store/test/native/rdb/unittest/rdb_corrupt_test.cpp b/relational_store/test/native/rdb/unittest/rdb_corrupt_test.cpp index 944af040..f2958a38 100644 --- a/relational_store/test/native/rdb/unittest/rdb_corrupt_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_corrupt_test.cpp @@ -41,6 +41,7 @@ public: void GenerateData(int count); static void DestroyDbFile(const std::string &filePath, size_t offset, size_t len, unsigned char ch); static constexpr const char *DATABASE_NAME = "corrupt_test.db"; + static constexpr int DB_FILE_HEADER_LENGTH = 100; std::shared_ptr store_; }; @@ -137,4 +138,21 @@ HWTEST_F(RdbCorruptTest, RdbCorruptTest001, TestSize.Level2) } EXPECT_EQ(errCode, E_SQLITE_CORRUPT); } + +/** + * @tc.name: RdbCorruptTest002 + * @tc.desc: test Rdb verify db file header's reserved bytes + * @tc.type: FUNC + */ +HWTEST_F(RdbCorruptTest, RdbCorruptTest002, TestSize.Level2) +{ + std::fstream f; + f.open(RDB_TEST_PATH + DATABASE_NAME); + f.seekp(0, std::ios::beg); + char buf[DB_FILE_HEADER_LENGTH] = {0}; + f.read(buf, sizeof(buf)); + f.close(); + // 20 is the offset of reserved bytes field + EXPECT_EQ((unsigned int)buf[20], 0); +} } // namespace Test \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_delete_test.cpp b/relational_store/test/native/rdb/unittest/rdb_delete_test.cpp index b60c4a9b..b217af1b 100644 --- a/relational_store/test/native/rdb/unittest/rdb_delete_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_delete_test.cpp @@ -15,8 +15,10 @@ #include +#include #include +#include "abs_rdb_predicates.h" #include "common.h" #include "rdb_errno.h" #include "rdb_helper.h" @@ -92,6 +94,7 @@ void RdbDeleteTest::TearDownTestCase(void) void RdbDeleteTest::SetUp(void) { store_ = *GetParam(); + ASSERT_NE(store_, nullptr); store_->ExecuteSql("DELETE FROM test"); } @@ -106,36 +109,34 @@ void RdbDeleteTest::TearDown(void) */ HWTEST_P(RdbDeleteTest, RdbStore_Delete_001, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int64_t id; int deletedRows; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[2])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[2])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); - ret = store->Delete(deletedRows, "test", "id = 1"); + ret = store_->Delete(deletedRows, "test", "id = 1"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, deletedRows); std::shared_ptr resultSet = - store->QuerySql("SELECT * FROM test WHERE id = ?", std::vector{ "1" }); + store_->QuerySql("SELECT * FROM test WHERE id = ?", std::vector{ "1" }); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_ROW_OUT_RANGE); ret = resultSet->Close(); EXPECT_EQ(ret, E_OK); - resultSet = store->QuerySql("SELECT * FROM test WHERE id = ?", std::vector{ "2" }); + resultSet = store_->QuerySql("SELECT * FROM test WHERE id = ?", std::vector{ "2" }); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToFirstRow(); EXPECT_EQ(ret, E_OK); @@ -144,7 +145,7 @@ HWTEST_P(RdbDeleteTest, RdbStore_Delete_001, TestSize.Level1) ret = resultSet->Close(); EXPECT_EQ(ret, E_OK); - resultSet = store->QuerySql("SELECT * FROM test WHERE id = 3", std::vector()); + resultSet = store_->QuerySql("SELECT * FROM test WHERE id = 3", std::vector()); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToFirstRow(); EXPECT_EQ(ret, E_OK); @@ -161,8 +162,6 @@ HWTEST_P(RdbDeleteTest, RdbStore_Delete_001, TestSize.Level1) */ HWTEST_P(RdbDeleteTest, RdbStore_Delete_002, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; int deletedRows; @@ -172,7 +171,7 @@ HWTEST_P(RdbDeleteTest, RdbStore_Delete_002, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); + int ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -182,7 +181,7 @@ HWTEST_P(RdbDeleteTest, RdbStore_Delete_002, TestSize.Level1) values.PutInt("age", 19); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->Insert(id, "test", values); + ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -192,15 +191,15 @@ HWTEST_P(RdbDeleteTest, RdbStore_Delete_002, TestSize.Level1) values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->Insert(id, "test", values); + ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); - ret = store->Delete(deletedRows, "test"); + ret = store_->Delete(deletedRows, "test"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, deletedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_ROW_OUT_RANGE); @@ -215,8 +214,6 @@ HWTEST_P(RdbDeleteTest, RdbStore_Delete_002, TestSize.Level1) */ HWTEST_P(RdbDeleteTest, RdbStore_Delete_003, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; int deletedRows; @@ -226,23 +223,306 @@ HWTEST_P(RdbDeleteTest, RdbStore_Delete_003, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); + int ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Delete(deletedRows, "", "id = ?", std::vector{ "1" }); + ret = store_->Delete(deletedRows, "", "id = ?", std::vector{ "1" }); EXPECT_EQ(ret, E_EMPTY_TABLE_NAME); - ret = store->Delete(deletedRows, "wrongTable", "id = ?", std::vector{ "1" }); + ret = store_->Delete(deletedRows, "wrongTable", "id = ?", std::vector{ "1" }); EXPECT_EQ(ret, E_SQLITE_ERROR); - ret = store->Delete(deletedRows, "test", "wrong sql id = ?", std::vector{ "1" }); + ret = store_->Delete(deletedRows, "test", "wrong sql id = ?", std::vector{ "1" }); EXPECT_EQ(ret, E_SQLITE_ERROR); - ret = store->Delete(deletedRows, "test", "id = 1", std::vector()); + ret = store_->Delete(deletedRows, "test", "id = 1", std::vector()); EXPECT_EQ(ret, E_OK); EXPECT_EQ(deletedRows, 1); } +/** + * @tc.name: RdbStore_Delete_With_Returning_001 + * @tc.desc: normal test + * @tc.type: FUNC + */ +HWTEST_P(RdbDeleteTest, RdbStore_Delete_With_Returning_001, TestSize.Level1) +{ + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store_->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + AbsRdbPredicates predicates("test"); + auto [status, res] = store_->Delete(predicates, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(res.changed, 1); + + int rowCount = -1; + ASSERT_EQ(res.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(res.results->GetColumnIndex("id", columnIndex), E_OK); + int64_t value; + ASSERT_EQ(res.results->GetLong(columnIndex, value), E_OK); + EXPECT_EQ(value, 1); +} + +/** + * @tc.name: RdbStore_Delete_With_Returning_002 + * @tc.desc: abnormal test, delete over returning limit + * @tc.type: FUNC + */ +HWTEST_P(RdbDeleteTest, RdbStore_Delete_With_Returning_002, TestSize.Level1) +{ + ValuesBuckets rows; + for (int i = 0; i < 1124; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto ret = store_->BatchInsert("test", rows); + EXPECT_EQ(ret.first, E_OK); + EXPECT_EQ(ret.second, 1124); + + AbsRdbPredicates predicates("test"); + auto [code, res] = store_->Delete(predicates, { "id" }); + EXPECT_EQ(code, E_OK); + EXPECT_EQ(res.changed, 1124); + int rowCount = -1; + ASSERT_EQ(res.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1024); +} + +/** + * @tc.name: RdbStore_Delete_With_Returning_003 + * @tc.desc: abnormal test, delete with returning field is string + * @tc.type: FUNC + */ +HWTEST_P(RdbDeleteTest, RdbStore_Delete_With_Returning_003, TestSize.Level1) +{ + ValuesBuckets rows; + for (int i = 0; i < 15; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim" + std::to_string(i)); + rows.Put(row); + } + auto ret = store_->BatchInsert("test", rows); + EXPECT_EQ(ret.first, E_OK); + EXPECT_EQ(ret.second, 15); + + AbsRdbPredicates predicates("test"); + auto [status, res] = store_->Delete(predicates, { "name" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(res.changed, 15); + + int rowCount = -1; + ASSERT_EQ(res.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 15); + int columnIndex = -1; + ASSERT_EQ(res.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + int i = 0; + while (i < 15) { + ASSERT_EQ(res.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "Jim" + std::to_string(i++)); + if (i < 15) { + ASSERT_EQ(res.results->GoToNextRow(), E_OK); + } + } +} + +/** + * @tc.name: RdbStore_Delete_With_Returning_004 + * @tc.desc: abnormal test, delete with returning field is blob + * @tc.type: FUNC + */ +HWTEST_P(RdbDeleteTest, RdbStore_Delete_With_Returning_004, TestSize.Level1) +{ + ValuesBuckets rows; + for (int i = 0; i < 15; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim" + std::to_string(i)); + std::vector blob(i + 1); + std::iota(blob.begin(), blob.end(), 1); + row.PutBlob("blobType", blob); + rows.Put(row); + } + auto ret = store_->BatchInsert("test", rows); + EXPECT_EQ(ret.first, E_OK); + EXPECT_EQ(ret.second, 15); + + AbsRdbPredicates predicates("test"); + auto [status, res] = store_->Delete(predicates, { "blobType" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(res.changed, 15); + + int rowCount = -1; + ASSERT_EQ(res.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 15); + int columnIndex = -1; + ASSERT_EQ(res.results->GetColumnIndex("blobType", columnIndex), E_OK); + int i = 0; + while (i < 15) { + std::vector blob; + ASSERT_EQ(res.results->GetBlob(columnIndex, blob), E_OK); + std::vector expectedBlob(++i); + std::iota(expectedBlob.begin(), expectedBlob.end(), 1); + EXPECT_EQ(blob, expectedBlob); + if (i < 15) { + ASSERT_EQ(res.results->GoToNextRow(), E_OK); + } + } +} + +/** + * @tc.name: RdbStore_Delete_With_Returning_005 + * @tc.desc: abnormal test, delete with returning field is not exist + * @tc.type: FUNC + */ +HWTEST_P(RdbDeleteTest, RdbStore_Delete_With_Returning_005, TestSize.Level1) +{ + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store_->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + AbsRdbPredicates predicates("test"); + auto [status, res] = store_->Delete(predicates, { "notExist" }); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(res.changed, -1); + ASSERT_EQ(res.results, nullptr); +} + +/** + * @tc.name: RdbStore_Delete_With_Returning_006 + * @tc.desc: abnormal test, delete with returning field is not exist + * @tc.type: FUNC + */ +HWTEST_P(RdbDeleteTest, RdbStore_Delete_With_Returning_006, TestSize.Level1) +{ + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store_->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 100); + auto [status, res] = store_->Delete(predicates, { "notExist" }); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(res.changed, -1); + ASSERT_EQ(res.results, nullptr); +} + +/** + * @tc.name: RdbStore_Delete_With_Returning_007 + * @tc.desc: normal test. delete from virtual table with returning + * @tc.type: FUNC + */ +HWTEST_P(RdbDeleteTest, RdbStore_Delete_With_Returning_007, TestSize.Level1) +{ + auto [execRet, execResult] = + store_->Execute("CREATE VIRTUAL TABLE IF NOT EXISTS articles USING fts5(title, content);"); + ASSERT_EQ(execRet, E_OK); + ValuesBuckets rows; + ValuesBucket row; + row.Put("title", "fts5"); + row.Put("content", "test virtual tables"); + rows.Put(std::move(row)); + auto [insertStatus, result] = + store_->BatchInsert("articles", rows, NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(insertStatus, E_OK); + + AbsRdbPredicates predicates("articles"); + predicates.EqualTo("title", "fts5"); + auto [status, res] = store_->Delete(predicates, { "title" }); + // DELETE RETURNING is not available on virtual tables + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(res.changed, -1); + + store_->Execute("Drop TABLE articles"); +} + +/** + * @tc.name: RdbStore_Delete_With_Returning_008 + * @tc.desc: normal test. delete with returning and trigger + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbDeleteTest, RdbStore_Delete_With_Returning_008, TestSize.Level1) +{ + auto [code, result1] = store_->Execute( + "CREATE TRIGGER before_delete BEFORE DELETE ON test" + " BEGIN UPDATE test SET name = 'li' WHERE name = 'wang'; END"); + + EXPECT_EQ(code, E_OK); + + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 200); + row.Put("name", "wang"); + rows.Put(std::move(row)); + row.Put("id", 201); + row.Put("name", "zhang"); + rows.Put(std::move(row)); + + auto [insertStatus, result] = + store_->BatchInsert("test", rows, { "name" }, NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(insertStatus, E_OK); + EXPECT_EQ(result.changed, 2); + + AbsRdbPredicates predicates("test"); + predicates.EqualTo("name", "zhang"); + auto [status, res] = store_->Delete(predicates, { "name" }); + + EXPECT_EQ(status, E_OK); + EXPECT_EQ(res.changed, 1); + int rowCount = -1; + ASSERT_EQ(res.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(res.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + ASSERT_EQ(res.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "zhang"); + + // Check the trigger effect + auto resultSet = store_->QuerySql("select name from test where id = 200"); + + rowCount = -1; + resultSet->GetRowCount(rowCount); + ASSERT_EQ(rowCount, 1); + ASSERT_EQ(resultSet->GoToNextRow(), E_OK); + columnIndex = -1; + resultSet->GetColumnIndex("name", columnIndex); + + value.clear(); + EXPECT_EQ(E_OK, resultSet->GetString(columnIndex, value)); + EXPECT_EQ(value, "li"); + + store_->Execute("DROP TRIGGER IF EXISTS before_delete"); +} INSTANTIATE_TEST_SUITE_P(DeleteTest, RdbDeleteTest, testing::Values(&g_store, &g_memDb)); } // namespace OHOS::RdbDeleteTest diff --git a/relational_store/test/native/rdb/unittest/rdb_distributed_test.cpp b/relational_store/test/native/rdb/unittest/rdb_distributed_test.cpp index aeaa88e3..34fc5c78 100644 --- a/relational_store/test/native/rdb/unittest/rdb_distributed_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_distributed_test.cpp @@ -185,7 +185,7 @@ HWTEST_F(RdbStoreDistributedTest, RdbStore_Distributed_002, TestSize.Level2) EXPECT_NE(nullptr, rdbStore); int errCode; EXPECT_EQ("", rdbStore->ObtainDistributedTableName("", "employee", errCode)); - EXPECT_EQ(-1, errCode); + EXPECT_EQ(E_ERROR, errCode); } /** @@ -198,7 +198,7 @@ HWTEST_F(RdbStoreDistributedTest, RdbStore_Distributed_003, TestSize.Level2) EXPECT_NE(nullptr, rdbStore); int errCode; EXPECT_EQ("", rdbStore->ObtainDistributedTableName("123456", "employee", errCode)); - EXPECT_EQ(-1, errCode); + EXPECT_EQ(E_ERROR, errCode); } /** diff --git a/relational_store/test/native/rdb/unittest/rdb_double_write_binlog_test.cpp b/relational_store/test/native/rdb/unittest/rdb_double_write_binlog_test.cpp new file mode 100644 index 00000000..680a7b1b --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_double_write_binlog_test.cpp @@ -0,0 +1,1460 @@ +/* + * 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. + */ + +#define LOG_TAG "RdbDoubleWriteBinlogTest" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "file_ex.h" +#include "logger.h" +#include "rdb_common.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "relational/relational_store_sqlite_ext.h" +#include "sqlite3.h" +#include "sqlite_connection.h" +#include "sqlite_utils.h" +#include "sqlite_global_config.h" +#include "sys/types.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; + +class RdbDoubleWriteBinlogTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static void CheckNumber( + std::shared_ptr &store, int num, int errCode = E_OK, const std::string &tableName = "test"); + static bool CheckFolderExist(const std::string &path); + void RemoveFolder(const std::string &path); + static void Insert(int64_t start, int count, bool isSlave = false, int dataSize = 0); + static void InsertNativeConn(sqlite3 *db, int64_t start, int count, int dataSize = 0); + void Update(int64_t start, int count, bool isSlave = false, int dataSize = 0); + void CheckProcess(std::shared_ptr &store); + void DeleteDbFile(const RdbStoreConfig &config); + void PutValue(std::shared_ptr &store, const std::string &data, int64_t id, int age); + static void WaitForBackupFinish(int32_t expectStatus, int maxTimes = 4000); + static void WaitForBinlogDelete(int maxTimes = 1000); + static void WaitForBinlogReplayFinish(); + void InitDb(HAMode mode = HAMode::MAIN_REPLICA, bool isOpenSlave = true); + int64_t GetRestoreTime(HAMode haMode, bool isOpenSlave = true); + + static const std::string databaseName; + static const std::string slaveDatabaseName; + static const std::string binlogDatabaseName; + static std::shared_ptr store; + static std::shared_ptr slaveStore; + static const std::string insertSql; + + enum SlaveStatus : uint32_t { + UNDEFINED, + BACKING_UP, + BACKUP_INTERRUPT, + BACKUP_FINISHED, + DB_CLOSING, + }; +}; + +const std::string RdbDoubleWriteBinlogTest::databaseName = RDB_TEST_PATH + "dual_write_binlog_test.db"; +const std::string RdbDoubleWriteBinlogTest::slaveDatabaseName = RDB_TEST_PATH + "dual_write_binlog_test_slave.db"; +const std::string RdbDoubleWriteBinlogTest::binlogDatabaseName = RDB_TEST_PATH + "dual_write_binlog_test.db_binlog"; +std::shared_ptr RdbDoubleWriteBinlogTest::store = nullptr; +std::shared_ptr RdbDoubleWriteBinlogTest::slaveStore = nullptr; +const std::string RdbDoubleWriteBinlogTest::insertSql = "INSERT INTO test(id, name, age, salary, blobType) VALUES" + "(?,?,?,?,?)"; + +const int CHECKAGE = 18; +const double CHECKCOLUMN = 100.5; +const int CHANGENUM = 12; +const int BINLOG_DELETE_PER_WAIT_TIME = 100000; // 100000us = 100ms +const int BINLOG_REPLAY_WAIT_TIME = 2; // 2s + +class DoubleWriteBinlogTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string createTableTest; +}; + +const std::string DoubleWriteBinlogTestOpenCallback::createTableTest = + std::string("CREATE TABLE IF NOT EXISTS test ") + std::string("(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary " + "REAL, blobType BLOB)"); + +int DoubleWriteBinlogTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(DoubleWriteBinlogTestOpenCallback::createTableTest); +} + +int DoubleWriteBinlogTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void RdbDoubleWriteBinlogTest::SetUpTestCase(void) +{ +} + +void RdbDoubleWriteBinlogTest::TearDownTestCase(void) +{ +} + +void RdbDoubleWriteBinlogTest::SetUp(void) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (!SqliteConnection::IsSupportBinlog(config)) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + testing::UnitTest *test = testing::UnitTest::GetInstance(); + ASSERT_NE(test, nullptr); + const testing::TestInfo *testInfo = test->current_test_info(); + ASSERT_NE(testInfo, nullptr); + LOG_INFO("---- double writebinlog test: %{public}s.%{public}s run start.", + testInfo->test_case_name(), testInfo->name()); +} + +void RdbDoubleWriteBinlogTest::TearDown(void) +{ + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName); + WaitForBinlogDelete(); + testing::UnitTest *test = testing::UnitTest::GetInstance(); + ASSERT_NE(test, nullptr); + const testing::TestInfo *testInfo = test->current_test_info(); + ASSERT_NE(testInfo, nullptr); + LOG_INFO("---- double writebinlog test: %{public}s.%{public}s run end.", + testInfo->test_case_name(), testInfo->name()); +} + +void RdbDoubleWriteBinlogTest::InitDb(HAMode mode, bool isOpenSlave) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + config.SetHaMode(mode); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(RdbDoubleWriteBinlogTest::store, nullptr); + store->ExecuteSql("DELETE FROM test"); + + if (isOpenSlave) { + RdbStoreConfig slaveConfig(RdbDoubleWriteBinlogTest::slaveDatabaseName); + DoubleWriteBinlogTestOpenCallback slaveHelper; + RdbDoubleWriteBinlogTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); + ASSERT_NE(RdbDoubleWriteBinlogTest::slaveStore, nullptr); + slaveStore->ExecuteSql("DELETE FROM test"); + } +} + +void RdbDoubleWriteBinlogTest::Insert(int64_t start, int count, bool isSlave, int dataSize) +{ + ValuesBucket values; + int64_t id = start; + int ret = E_OK; + for (int i = 0; i < count; i++) { + values.Clear(); + values.PutInt("id", id); + if (dataSize > 0) { + values.PutString("name", std::string(dataSize, 'a')); + } else { + values.PutString("name", std::string("zhangsan")); + } + values.PutInt("age", CHECKAGE); + values.PutDouble("salary", CHECKCOLUMN); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + if (isSlave) { + ret = slaveStore->Insert(id, "test", values); + } else { + ret = store->Insert(id, "test", values); + } + EXPECT_EQ(ret, E_OK); + id++; + } +} + +void RdbDoubleWriteBinlogTest::InsertNativeConn(sqlite3 *db, int64_t start, int count, int dataSize) +{ + int64_t id = start; + sqlite3_stmt *stat = nullptr; + EXPECT_EQ(sqlite3_prepare_v2(db, RdbDoubleWriteBinlogTest::insertSql.c_str(), -1, &stat, nullptr), SQLITE_OK); + for (int i = 0; i < count; i++) { + // bind parameters, 1 is the sequence number of field + sqlite3_bind_int(stat, 1, id); + std::string nameStr; + if (dataSize > 0) { + nameStr = std::string(dataSize, 'a'); + } else { + nameStr = std::string("zhangsan"); + } + // bind parameters, 2 is the sequence number of field + sqlite3_bind_text(stat, 2, nameStr.c_str(), -1, SQLITE_STATIC); + // bind parameters, 3 is the sequence number of field + sqlite3_bind_int(stat, 3, CHECKAGE); + // bind parameters, 4 is the sequence number of field + sqlite3_bind_double(stat, 4, CHECKCOLUMN); + uint8_t blob[] = { 1, 2, 3 }; + // bind parameters, 5 is the sequence number of field + sqlite3_bind_blob(stat, 5, blob, sizeof(blob), nullptr); + EXPECT_EQ(sqlite3_step(stat), SQLITE_DONE); + sqlite3_reset(stat); + id++; + } + sqlite3_finalize(stat); +} + +void RdbDoubleWriteBinlogTest::Update(int64_t start, int count, bool isSlave, int dataSize) +{ + ValuesBucket values; + int64_t id = start; + int age = 20; + int ret = E_OK; + for (int i = 0; i < count; i++) { + values.Clear(); + values.PutInt("id", id); + if (dataSize > 0) { + values.PutString("name", std::string(dataSize, 'a')); + } else { + values.PutString("name", std::string("zhangsan")); + } + values.PutInt("age", age); + values.PutDouble("salary", CHECKCOLUMN); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + if (isSlave) { + ret = slaveStore->Replace(id, "test", values); + } else { + ret = store->Replace(id, "test", values); + } + EXPECT_EQ(ret, E_OK); + id++; + } +} + +void RdbDoubleWriteBinlogTest::WaitForBackupFinish(int32_t expectStatus, int maxTimes) +{ + int32_t curStatus = store->GetBackupStatus(); + int tryTimes = 0; + while (curStatus != expectStatus && (++tryTimes <= maxTimes)) { + usleep(50000); // 50000 delay + curStatus = store->GetBackupStatus(); + } + LOG_INFO("----------cur backup Status:%{public}d---------", curStatus); + ASSERT_EQ(curStatus, expectStatus); +} + +void RdbDoubleWriteBinlogTest::WaitForBinlogDelete(int maxTimes) +{ + int waitTimes = 0; + while (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName) && waitTimes < maxTimes) { + usleep(BINLOG_DELETE_PER_WAIT_TIME); + waitTimes++; + LOG_INFO("---- Binlog replay in progress, waiting for finish"); + RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName); + } + EXPECT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); +} + +void RdbDoubleWriteBinlogTest::WaitForBinlogReplayFinish() +{ + sleep(BINLOG_REPLAY_WAIT_TIME); +} + +void RdbDoubleWriteBinlogTest::CheckNumber( + std::shared_ptr &store, int num, int errCode, const std::string &tableName) +{ + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM " + tableName); + ASSERT_NE(resultSet, nullptr); + int countNum; + int ret = resultSet->GetRowCount(countNum); + EXPECT_EQ(ret, errCode); + EXPECT_EQ(num, countNum); +} + +bool RdbDoubleWriteBinlogTest::CheckFolderExist(const std::string &path) +{ + if (access(path.c_str(), F_OK) != 0) { + return false; + } + return true; +} + +void RdbDoubleWriteBinlogTest::RemoveFolder(const std::string &path) +{ + std::filesystem::path folder(path); + for (const auto &entry : std::filesystem::directory_iterator(folder)) { + if (entry.is_directory()) { + RemoveFolder(entry.path()); + } else { + std::filesystem::remove(entry.path()); + } + } + std::filesystem::remove(folder); +} + +typedef int (*GtForkCallbackT)(const char *arg); +static pid_t GtFork(GtForkCallbackT callback, const char *arg) +{ + pid_t pid = fork(); + if (pid == 0) { + int ret = callback(arg); + _exit(ret); + } + return pid; +} + +static int InsertProcess(const char *arg) +{ + std::string test = std::string(arg); + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + int errCode = E_OK; + config.SetHaMode(HAMode::MAIN_REPLICA); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(RdbDoubleWriteBinlogTest::store, nullptr); + int64_t id = 11; + int count = 1000; + RdbDoubleWriteBinlogTest::Insert(id, count); + int32_t num = 1010; + RdbDoubleWriteBinlogTest::CheckNumber(RdbDoubleWriteBinlogTest::store, num); + return 0; +} + +static int InsertTwoProcess(const char *arg) +{ + std::string test = std::string(arg); + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + int errCode = E_OK; + config.SetHaMode(HAMode::MAIN_REPLICA); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(RdbDoubleWriteBinlogTest::store, nullptr); + bool isBinlogExist = RdbDoubleWriteBinlogTest::CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + EXPECT_TRUE(isBinlogExist); + int count = 10; + for (int i = 0; i < count; i++) { + errCode = RdbDoubleWriteBinlogTest::store->Backup(std::string(""), {}); + } + return 0; +} + +static int InsertManualProcess(const char *arg) +{ + std::string test = std::string(arg); + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + int errCode = E_OK; + config.SetHaMode(HAMode::MANUAL_TRIGGER); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(RdbDoubleWriteBinlogTest::store, nullptr); + int64_t id = 11; + int count = 1000; + RdbDoubleWriteBinlogTest::Insert(id, count); + int32_t num = 1010; + RdbDoubleWriteBinlogTest::CheckNumber(RdbDoubleWriteBinlogTest::store, num); + return 0; +} + +static int InsertManualTwoProcess(const char *arg) +{ + std::string test = std::string(arg); + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + int errCode = E_OK; + config.SetHaMode(HAMode::MANUAL_TRIGGER); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(RdbDoubleWriteBinlogTest::store, nullptr); + bool isBinlogExist = RdbDoubleWriteBinlogTest::CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + EXPECT_TRUE(isBinlogExist); + int count = 10; + for (int i = 0; i < count; i++) { + errCode = RdbDoubleWriteBinlogTest::store->Backup(std::string(""), {}); + } + return 0; +} + +void RdbDoubleWriteBinlogTest::CheckProcess(std::shared_ptr &store) +{ + int64_t changeId = 2; + int changeCount = 4; + Update(changeId, changeCount); + int deletedRows; + store->Delete(deletedRows, "test", "id == 8"); + store->Delete(deletedRows, "test", "id == 9"); + int ret = store->BeginTransaction(); + EXPECT_EQ(ret, E_OK); + std::string sqlCreateIndex = "CREATE INDEX id_index ON test (id);"; + store->ExecuteSql(sqlCreateIndex.c_str()); + ret = store->Commit(); + EXPECT_EQ(ret, E_OK); + ret = store->BeginTransaction(); + EXPECT_EQ(ret, E_OK); + changeId = CHANGENUM; + Update(changeId, changeCount); + store->Delete(deletedRows, "test", "id == 18"); + store->Delete(deletedRows, "test", "id == 19"); + ret = store->RollBack(); + EXPECT_EQ(ret, E_OK); +} + +void RdbDoubleWriteBinlogTest::DeleteDbFile(const RdbStoreConfig &config) +{ + std::string dbFile; + auto errCode = SqliteGlobalConfig::GetDbPath(config, dbFile); + if (errCode != E_OK || dbFile.empty()) { + return; + } + std::ifstream binFile(dbFile); + if (binFile.is_open()) { + std::string content((std::istreambuf_iterator(binFile)), (std::istreambuf_iterator())); + std::remove(dbFile.c_str()); + } +} + +void RdbDoubleWriteBinlogTest::PutValue(std::shared_ptr &store, const std::string &data, int64_t id, int age) +{ + ValuesBucket values; + values.PutInt("id", id); + values.PutString("name", data); + values.PutInt("age", age); + values.PutDouble("salary", CHECKCOLUMN); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_001, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + config.SetHaMode(HAMode::MAIN_REPLICA); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + ASSERT_TRUE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + store = nullptr; + RdbHelper::DeleteRdbStore(config); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_002, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + config.SetHaMode(HAMode::MANUAL_TRIGGER); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_FALSE(isBinlogExist); + errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_003, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + config.SetHaMode(HAMode::MAIN_REPLICA); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + int64_t id = 1; + int count = 10; + Insert(id, count); + store = nullptr; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isSlaveDbFileExist = OHOS::FileExists(RdbDoubleWriteBinlogTest::slaveDatabaseName); + ASSERT_TRUE(isSlaveDbFileExist); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_004, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + config.SetHaMode(HAMode::MANUAL_TRIGGER); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + int64_t id = 1; + int count = 10; + Insert(id, count); + store = nullptr; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isSlaveDbFileExist = OHOS::FileExists(RdbDoubleWriteBinlogTest::slaveDatabaseName); + ASSERT_FALSE(isSlaveDbFileExist); + errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + isSlaveDbFileExist = OHOS::FileExists(RdbDoubleWriteBinlogTest::slaveDatabaseName); + ASSERT_TRUE(isSlaveDbFileExist); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_005, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(); + int64_t id = 1; + int count = 10; + Insert(id, count); + Insert(id, count, true); + store = nullptr; + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_006, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + int errCode = E_OK; + config.SetHaMode(HAMode::MANUAL_TRIGGER); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + store->ExecuteSql("DELETE FROM test"); + + // open slave for conflict by compress + sqlite3 *db = nullptr; + int rc = sqlite3_open_v2(RdbDoubleWriteBinlogTest::slaveDatabaseName.c_str(), + &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); + EXPECT_EQ(rc, SQLITE_OK); + EXPECT_NE(db, nullptr); + sqlite3_close_v2(db); + + int64_t id = 1; + int count = 10; + Insert(id, count); + store = nullptr; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_007, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(); + int64_t id = 1; + int count = 10; + Insert(id, count); + Insert(id, count, true); + + SqliteUtils::SetSlaveInvalid(RdbDoubleWriteBinlogTest::databaseName); + std::string failureFlagPath = RdbDoubleWriteBinlogTest::databaseName + +"-slaveFailure"; + bool isFlagFileExists = OHOS::FileExists(failureFlagPath); + ASSERT_TRUE(isFlagFileExists); + store = nullptr; + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_008, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + int errCode = E_OK; + config.SetHaMode(HAMode::MANUAL_TRIGGER); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + store->ExecuteSql("DELETE FROM test"); + + // open slave for conflict by compress + sqlite3 *db = nullptr; + int rc = sqlite3_open_v2(RdbDoubleWriteBinlogTest::slaveDatabaseName.c_str(), + &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); + EXPECT_EQ(rc, SQLITE_OK); + EXPECT_NE(db, nullptr); + sqlite3_close_v2(db); + + int64_t id = 1; + int count = 10; + Insert(id, count); + + SqliteUtils::SetSlaveInvalid(RdbDoubleWriteBinlogTest::databaseName); + std::string failureFlagPath = RdbDoubleWriteBinlogTest::databaseName + +"-slaveFailure"; + bool isFlagFileExists = OHOS::FileExists(failureFlagPath); + ASSERT_TRUE(isFlagFileExists); + store = nullptr; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_FALSE(isBinlogExist); + errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_009, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(HAMode::MAIN_REPLICA, false); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + int64_t id = 1; + int count = 10; + Insert(id, count); + + store = nullptr; + config.SetHaMode(HAMode::MAIN_REPLICA); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); + id = 11; + Insert(id, count); + WaitForBinlogReplayFinish(); + store = nullptr; + DeleteDbFile(config); + + config.SetHaMode(HAMode::MAIN_REPLICA); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + WaitForBackupFinish(BACKUP_FINISHED); + WaitForBinlogReplayFinish(); + int32_t num = 20; + RdbDoubleWriteBinlogTest::CheckNumber(store, num); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_010, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + int errCode = E_OK; + config.SetHaMode(HAMode::MANUAL_TRIGGER); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + store->ExecuteSql("DELETE FROM test"); + + int64_t id = 1; + int count = 10; + Insert(id, count); + + // open slave for conflict by compress + sqlite3 *db = nullptr; + int rc = sqlite3_open_v2(RdbDoubleWriteBinlogTest::slaveDatabaseName.c_str(), + &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "compressvfs"); + EXPECT_EQ(rc, SQLITE_OK); + EXPECT_NE(db, nullptr); + const char *ddl = DoubleWriteBinlogTestOpenCallback::createTableTest.c_str(); + EXPECT_EQ(sqlite3_exec(db, ddl, nullptr, nullptr, nullptr), SQLITE_OK); + InsertNativeConn(db, id, count); + sqlite3_close_v2(db); + + store = nullptr; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + WaitForBinlogReplayFinish(); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); + id = 11; + Insert(id, count); + store = nullptr; + DeleteDbFile(config); + + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + WaitForBackupFinish(BACKUP_FINISHED); + int32_t num = 20; + RdbDoubleWriteBinlogTest::CheckNumber(store, num); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_011, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(HAMode::MAIN_REPLICA, false); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + int64_t id = 1; + int count = 10; + Insert(id, count); + + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); + id = 11; + Insert(id, count); + int32_t num = 20; + RdbDoubleWriteBinlogTest::CheckNumber(store, num); + CheckProcess(store); + + store = nullptr; + DeleteDbFile(config); + + config.SetHaMode(HAMode::MAIN_REPLICA); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + WaitForBackupFinish(BACKUP_FINISHED); + WaitForBinlogReplayFinish(); + num = 18; + RdbDoubleWriteBinlogTest::CheckNumber(store, num); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_012, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + + InitDb(HAMode::MAIN_REPLICA, false); + int64_t id = 1; + int count = 10; + Insert(id, count); + + config.SetHaMode(HAMode::MANUAL_TRIGGER); + DoubleWriteBinlogTestOpenCallback helper; + int errCode = E_OK; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); + id = 11; + Insert(id, count); + int32_t num = 20; + RdbDoubleWriteBinlogTest::CheckNumber(store, num); + CheckProcess(store); + + store = nullptr; + DeleteDbFile(config); + + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + WaitForBackupFinish(BACKUP_FINISHED); + num = 18; + RdbDoubleWriteBinlogTest::CheckNumber(store, num); +} + +static int Callback(void *data, int argc, char **argv, char **azColName) +{ + int64_t *count = (int64_t *)data; + if (argc > 0 && argv[0] != NULL) { + *count = atoi(argv[0]); + } + return 0; +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_013, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + int errCode = E_OK; + config.SetHaMode(HAMode::MAIN_REPLICA); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + + bool isSlaveDbFileExists = OHOS::FileExists(RdbDoubleWriteBinlogTest::slaveDatabaseName); + ASSERT_TRUE(isSlaveDbFileExists); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); + + int64_t id = 1; + int count = 20; + Insert(id, count); + CheckProcess(store); + + int64_t num = 18; + RdbDoubleWriteBinlogTest::CheckNumber(store, num); + errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + + // open slave for conflict by compress + sqlite3 *db = nullptr; + int rc = sqlite3_open_v2(RdbDoubleWriteBinlogTest::slaveDatabaseName.c_str(), + &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "compressvfs"); + EXPECT_EQ(rc, SQLITE_OK); + EXPECT_NE(db, nullptr); + + count = 0; + rc = sqlite3_exec(db, "SELECT COUNT(1) FROM test;", Callback, &count, nullptr); + EXPECT_EQ(rc, SQLITE_OK); + EXPECT_EQ(count, num); + sqlite3_close_v2(db); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_014, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + int errCode = E_OK; + config.SetHaMode(HAMode::MANUAL_TRIGGER); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + + bool isSlaveDbFileExists = OHOS::FileExists(RdbDoubleWriteBinlogTest::slaveDatabaseName); + ASSERT_FALSE(isSlaveDbFileExists); + errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + WaitForBackupFinish(BACKUP_FINISHED); + isSlaveDbFileExists = OHOS::FileExists(RdbDoubleWriteBinlogTest::slaveDatabaseName); + ASSERT_TRUE(isSlaveDbFileExists); + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); + + int64_t id = 1; + int count = 20; + Insert(id, count); + CheckProcess(store); + + int64_t num = 18; + RdbDoubleWriteBinlogTest::CheckNumber(store, num); + errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + + // open slave for conflict by compress + sqlite3 *db = nullptr; + int rc = sqlite3_open_v2(RdbDoubleWriteBinlogTest::slaveDatabaseName.c_str(), + &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "compressvfs"); + EXPECT_EQ(rc, SQLITE_OK); + EXPECT_NE(db, nullptr); + count = 0; + rc = sqlite3_exec(db, "SELECT COUNT(1) FROM test;", Callback, &count, nullptr); + EXPECT_EQ(rc, SQLITE_OK); + EXPECT_EQ(count, num); + sqlite3_close_v2(db); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_015, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(); + int64_t id = 1; + int count = 10; + Insert(id, count); + store = nullptr; + std::string test = "lisi"; + pid_t pid1 = GtFork(InsertProcess, test.c_str()); + ASSERT_GT(pid1, 0); + InsertTwoProcess(test.c_str()); + int status; +// waitpid(pid1, &status, 0); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_016, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + int errCode = E_OK; + config.SetHaMode(HAMode::MANUAL_TRIGGER); + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + store->ExecuteSql("DELETE FROM test"); + int64_t id = 1; + int count = 10; + Insert(id, count); + EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); + ASSERT_TRUE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + + RdbStoreConfig slaveConfig(RdbDoubleWriteBinlogTest::slaveDatabaseName); + DoubleWriteBinlogTestOpenCallback slaveHelper; + RdbDoubleWriteBinlogTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); + EXPECT_NE(slaveStore, nullptr); + + store = nullptr; + std::string test = "lisi"; + pid_t pid1 = GtFork(InsertManualProcess, test.c_str()); + ASSERT_GT(pid1, 0); + InsertManualTwoProcess(test.c_str()); + int status; +// waitpid(pid1, &status, 0); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_017, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(); + int64_t id = 1; + int count = 10; + Insert(id, count); + store = nullptr; + + config.SetHaMode(HAMode::MAIN_REPLICA); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); + + size_t bigSize = 1024 * 1024 * 128; + std::string data(bigSize, 'a'); + PutValue(store, data, 11, 18); + PutValue(store, data, 12, 19); + + store = nullptr; + id = 13; + for (int i = 0; i < count; i++) { + config.SetHaMode(HAMode::MAIN_REPLICA); + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + PutValue(store, data, id, CHECKAGE); + store = nullptr; + id++; + } + WaitForBinlogReplayFinish(); +} + +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_018, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(); + int64_t id = 1; + int count = 10; + Insert(id, count); + store = nullptr; + + config.SetHaMode(HAMode::MAIN_REPLICA); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + + bool isBinlogExist = CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName); + ASSERT_TRUE(isBinlogExist); + + size_t bigSize = 1024 * 1024 * 13; + std::string data(bigSize, 'a'); + + store = nullptr; + id = 11; + for (int i = 0; i < count; i++) { + config.SetHaMode(HAMode::MAIN_REPLICA); + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + PutValue(store, data, id, CHECKAGE); + store = nullptr; + id++; + } + WaitForBinlogReplayFinish(); +} + +/** + * @tc.name: RdbStore_Binlog_019 + * @tc.desc: open MAIN_REPLICA db when replica is invalid, + * then batch insert new data and test main and replica are the same + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_019, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + InitDb(); + int64_t id = 1; + int count = 10; + Insert(id, count); + store = nullptr; + slaveStore = nullptr; + SqliteUtils::SetSlaveInvalid(RdbDoubleWriteBinlogTest::databaseName); + + LOG_INFO("---- open db when slave is invalid to trigger backup"); + config.SetHaMode(HAMode::MAIN_REPLICA); + int errCode = E_OK; + DoubleWriteBinlogTestOpenCallback helper; + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + WaitForBinlogReplayFinish(); + LOG_INFO("---- insert after backup after wait"); + int totalCount = count; + id += totalCount; + count = 1000; // 1000 is one batch + Insert(id, count); + totalCount += count; + EXPECT_TRUE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + EXPECT_FALSE(SqliteUtils::IsSlaveInvalid(RdbDoubleWriteBinlogTest::databaseName)); + RdbDoubleWriteBinlogTest::CheckNumber(store, totalCount); + store = nullptr; + SqliteUtils::DeleteFile(databaseName); + LOG_INFO("---- check for data count after restore"); + RdbDoubleWriteBinlogTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + RdbDoubleWriteBinlogTest::CheckNumber(store, totalCount); +} + +static int MockCleanBinlog(sqlite3* db, BinlogFileCleanModeE mode) +{ + return SQLITE_ERROR; +} + +static int MockSupportBinlogOff(const char *name) +{ + return SQLITE_ERROR; +} +/** + * @tc.name: RdbStore_Binlog_020 + * @tc.desc: test backup when binlog clean failed will mark slave invalid + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_020, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + InitDb(); + int64_t id = 1; + int count = 10; + Insert(id, count); + +// LOG_INFO("---- let binlog clean return ERROR"); +// auto originalApi = sqlite3_export_extra_symbols; +// struct sqlite3_api_routines_extra mockApi = *sqlite3_export_extra_symbols; +// mockApi.clean_binlog = MockCleanBinlog; +// sqlite3_export_extra_symbols = &mockApi; +// +// LOG_INFO("---- binlog clean failed should mark invalid"); +// EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); +// EXPECT_TRUE(SqliteUtils::IsSlaveInvalid(RdbDoubleWriteBinlogTest::databaseName)); +// sqlite3_export_extra_symbols = originalApi; +} + +/** + * @tc.name: RdbStore_Binlog_021 + * @tc.desc: test delete rdb store will work if binlog is not supported + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_021, TestSize.Level0) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + InitDb(); + int64_t id = 1; + int count = 10; + Insert(id, count); + store = nullptr; + slaveStore = nullptr; + + LOG_INFO("---- let support binlog becomes off"); + struct sqlite3_api_routines_relational mockApi = *sqlite3_export_relational_symbols; + mockApi.is_support_binlog = MockSupportBinlogOff; + auto originalApi = sqlite3_export_relational_symbols; + sqlite3_export_relational_symbols = &mockApi; + + LOG_INFO("---- rdb delete store should return ok"); + EXPECT_EQ(RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName), E_OK); + sqlite3_export_relational_symbols = originalApi; +} + +static int64_t GetInsertTime(std::shared_ptr &rdbStore, int repeat, size_t dataSize) +{ + size_t bigSize = dataSize; + std::string data(bigSize, 'a'); + + LOG_INFO("---- start insert ----"); + int64_t totalCost = 0; + for (int64_t id = 0; id < repeat; id++) { + ValuesBucket values; + values.PutInt("id", id); + values.PutString("name", data); + values.PutInt("age", id); + values.PutDouble("salary", CHECKCOLUMN); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + auto begin = std::chrono::high_resolution_clock::now(); + int ret = rdbStore->Insert(id, "test", values); + auto stop = std::chrono::high_resolution_clock::now(); + EXPECT_EQ(ret, E_OK); + totalCost += std::chrono::duration_cast(stop - begin).count(); + } + return totalCost; +} + +static int64_t GetUpdateTime(std::shared_ptr &rdbStore, int batchSize, int repeat, size_t dataSize) +{ + size_t bigSize = dataSize; + std::string data(bigSize, 'b'); + LOG_INFO("---- start update ----"); + int64_t totalCost = 0; + for (int i = 0; i < repeat; i++) { + int start = i * batchSize; + int end = (i + 1) * batchSize; + std::string sql = "update test set name = '" + data + "' where id >= " + std::to_string(start) + + " and id < " + std::to_string(end) + ";"; + auto begin = std::chrono::high_resolution_clock::now(); + int ret = rdbStore->ExecuteSql(sql); + auto stop = std::chrono::high_resolution_clock::now(); + EXPECT_EQ(ret, E_OK); + totalCost += std::chrono::duration_cast(stop - begin).count(); + } + return totalCost; +} + +static int64_t GetDeleteTime(std::shared_ptr &rdbStore, int batchSize, int repeat) +{ + LOG_INFO("---- start delete ----"); + int64_t totalCost = 0; + for (int i = 0; i < repeat; i++) { + int start = i * batchSize; + int end = (i + 1) * batchSize; + std::string sql = + "delete from test where id >= " + std::to_string(start) + " and id < " + std::to_string(end) + ";"; + auto begin = std::chrono::high_resolution_clock::now(); + int ret = rdbStore->ExecuteSql(sql); + auto stop = std::chrono::high_resolution_clock::now(); + EXPECT_EQ(ret, E_OK); + totalCost += std::chrono::duration_cast(stop - begin).count(); + } + return totalCost; +} + +int64_t RdbDoubleWriteBinlogTest::GetRestoreTime(HAMode haMode, bool isOpenSlave) +{ + InitDb(haMode, isOpenSlave); + EXPECT_NE(store, nullptr); + if (haMode == HAMode::MANUAL_TRIGGER) { + int errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + } + int id = 1; + int totalCount = 20000; + int size = 1024; + Insert(id, totalCount, false, size); + store = nullptr; + + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + DoubleWriteBinlogTestOpenCallback helper; + config.SetHaMode(haMode); + DeleteDbFile(config); + + int errCode = E_OK; + auto begin = std::chrono::high_resolution_clock::now(); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + auto stop = std::chrono::high_resolution_clock::now(); + EXPECT_NE(store, nullptr); + return std::chrono::duration_cast(stop - begin).count(); +} + +/** + * @tc.name: RdbStore_Binlog_Performance_001 + * @tc.desc: test performance of insert, update, query and delete in main_replica + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_Performance_001, TestSize.Level2) +{ + LOG_INFO("----RdbStore_Binlog_Performance_001 start----"); + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(HAMode::SINGLE); + EXPECT_NE(store, nullptr); + if (!CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + return; + } + + int totalCount = 20000; + int dataSize = 1024; + int batchSize = 10; + auto T1_2 = GetInsertTime(store, totalCount, dataSize); + auto T2_2 = GetUpdateTime(store, batchSize, totalCount / batchSize, dataSize); + auto T3_2 = GetDeleteTime(store, batchSize, totalCount / batchSize); + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName); + WaitForBinlogDelete(); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + + InitDb(HAMode::MAIN_REPLICA); + EXPECT_NE(store, nullptr); + + auto T1 = GetInsertTime(store, totalCount, dataSize); + auto T2 = GetUpdateTime(store, batchSize, totalCount / batchSize, dataSize); + auto T3 = GetDeleteTime(store, batchSize, totalCount / batchSize); + + EXPECT_LT(T1, T1_2 * 1.8); + EXPECT_LT(T2, T2_2 * 1.8); + EXPECT_LT(T3, T3_2 * 1.8); + LOG_INFO("----RdbStore_Binlog_Performance_001----, %{public}" PRId64 ", %{public}" PRId64 ", %{public}" PRId64 ",", + T1, T2, T3); + LOG_INFO("----RdbStore_Binlog_Performance_001----, %{public}" PRId64 ", %{public}" PRId64 ", %{public}" PRId64 ",", + T1_2, T2_2, T3_2); +} + +/** + * @tc.name: RdbStore_Binlog_Performance_002 + * @tc.desc: test performance of insert, update, query and delete in mannual_trigger + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_Performance_002, TestSize.Level2) +{ + LOG_INFO("----RdbStore_Binlog_Performance_002 start----"); + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(HAMode::SINGLE); + ASSERT_NE(store, nullptr); + + int totalCount = 20000; + int dataSize = 200; + int batchSize = 1; + auto T1_2 = GetInsertTime(store, totalCount, dataSize); + auto T2_2 = GetUpdateTime(store, batchSize, totalCount / batchSize, dataSize); + auto T3_2 = GetDeleteTime(store, batchSize, totalCount / batchSize); + + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName); + WaitForBinlogDelete(); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + + InitDb(HAMode::MANUAL_TRIGGER); + EXPECT_NE(store, nullptr); + int errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + if (!CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + return; + } + + auto T1 = GetInsertTime(store, totalCount, dataSize); + auto T2 = GetUpdateTime(store, batchSize, totalCount / batchSize, dataSize); + auto T3 = GetDeleteTime(store, batchSize, totalCount / batchSize); + + EXPECT_LT(T1, T1_2 * 1.8); + EXPECT_LT(T2, T2_2 * 1.8); + EXPECT_LT(T3, T3_2 * 1.8); + LOG_INFO("----RdbStore_Binlog_Performance_002----, %{public}" PRId64 ", %{public}" PRId64 ", %{public}" PRId64 ",", + T1, T2, T3); + LOG_INFO("----RdbStore_Binlog_Performance_002----, %{public}" PRId64 ", %{public}" PRId64 ", %{public}" PRId64 ",", + T1_2, T2_2, T3_2); +} + +/** + * @tc.name: RdbStore_Binlog_Performance_003 + * @tc.desc: test performance of insert, update, query and delete in main_replica with large data + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_Performance_003, TestSize.Level2) +{ + LOG_INFO("----RdbStore_Binlog_Performance_003 start----"); + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(HAMode::SINGLE); + EXPECT_NE(store, nullptr); + + int totalCount = 200; + int dataSize = 1024 * 1024; + int batchSize = 10; + auto T1_2 = GetInsertTime(store, totalCount, dataSize); + auto T2_2 = GetUpdateTime(store, batchSize, totalCount / batchSize, dataSize); + auto T3_2 = GetDeleteTime(store, batchSize, totalCount / batchSize); + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName); + WaitForBinlogDelete(); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + + InitDb(HAMode::MAIN_REPLICA); + EXPECT_NE(store, nullptr); + if (!CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + return; + } + + auto T1 = GetInsertTime(store, totalCount, dataSize); + auto T2 = GetUpdateTime(store, batchSize, totalCount / batchSize, dataSize); + auto T3 = GetDeleteTime(store, batchSize, totalCount / batchSize); + + EXPECT_LT(T1, T1_2 * 1.8); + EXPECT_LT(T2, T2_2 * 1.8); + EXPECT_LT(T3, T3_2 * 1.8); + LOG_INFO("----RdbStore_Binlog_Performance_003----, %{public}" PRId64 ", %{public}" PRId64 ", %{public}" PRId64 ",", + T1, T2, T3); + LOG_INFO("----RdbStore_Binlog_Performance_003----, %{public}" PRId64 ", %{public}" PRId64 ", %{public}" PRId64 ",", + T1_2, T2_2, T3_2); +} + +/** + * @tc.name: RdbStore_Binlog_Performance_004 + * @tc.desc: test performance of insert, update, query and delete in mannual_trigger with large data + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_Performance_004, TestSize.Level2) +{ + LOG_INFO("----RdbStore_Binlog_Performance_004 start----"); + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + if (CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + RemoveFolder(RdbDoubleWriteBinlogTest::binlogDatabaseName); + } + InitDb(HAMode::SINGLE); + EXPECT_NE(store, nullptr); + + int totalCount = 200; + int dataSize = 1024 * 1024; + int batchSize = 10; + auto T1_2 = GetInsertTime(store, totalCount, dataSize); + auto T2_2 = GetUpdateTime(store, batchSize, totalCount / batchSize, dataSize); + auto T3_2 = GetDeleteTime(store, batchSize, totalCount / batchSize); + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName); + WaitForBinlogDelete(); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + + InitDb(HAMode::MANUAL_TRIGGER); + ASSERT_NE(store, nullptr); + int errCode = store->Backup(std::string(""), {}); + EXPECT_EQ(errCode, E_OK); + if (!CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)) { + return; + } + + auto T1 = GetInsertTime(store, totalCount, dataSize); + auto T2 = GetUpdateTime(store, batchSize, totalCount / batchSize, dataSize); + auto T3 = GetDeleteTime(store, batchSize, totalCount / batchSize); + + EXPECT_LT(T1, T1_2 * 1.8); + EXPECT_LT(T2, T2_2 * 1.8); + EXPECT_LT(T3, T3_2 * 1.8); + LOG_INFO("----RdbStore_Binlog_Performance_004----, %{public}" PRId64 ", %{public}" PRId64 ", %{public}" PRId64 ",", + T1, T2, T3); + LOG_INFO("----RdbStore_Binlog_Performance_004----, %{public}" PRId64 ", %{public}" PRId64 ", %{public}" PRId64 ",", + T1_2, T2_2, T3_2); +} + +/** + * @tc.name: RdbStore_Binlog_Performance_005 + * @tc.desc: test performance of restore in main_replica + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_Performance_005, TestSize.Level3) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + struct sqlite3_api_routines_relational mockApi = *sqlite3_export_relational_symbols; + mockApi.is_support_binlog = MockSupportBinlogOff; + auto originalApi = sqlite3_export_relational_symbols; + sqlite3_export_relational_symbols = &mockApi; + EXPECT_EQ(SqliteConnection::IsSupportBinlog(config), false); + LOG_INFO("----RdbStore_Binlog_Performance_005 binlog off----"); + auto T1 = GetRestoreTime(HAMode::MAIN_REPLICA); + + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName); + WaitForBinlogDelete(); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + sqlite3_export_relational_symbols = originalApi; + EXPECT_EQ(SqliteConnection::IsSupportBinlog(config), true); + LOG_INFO("----RdbStore_Binlog_Performance_005 binlog on----"); + auto T1_2 = GetRestoreTime(HAMode::MAIN_REPLICA); + EXPECT_GT(T1 * 1.8, T1_2); + LOG_INFO("----RdbStore_Binlog_Performance_005----, %{public}" PRId64 ", %{public}" PRId64 ",", T1, T1_2); +} + +/** + * @tc.name: RdbStore_Binlog_Performance_006 + * @tc.desc: test performance of restore in mannual_trigger + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteBinlogTest, RdbStore_Binlog_Performance_006, TestSize.Level3) +{ + RdbStoreConfig config(RdbDoubleWriteBinlogTest::databaseName); + struct sqlite3_api_routines_relational mockApi = *sqlite3_export_relational_symbols; + mockApi.is_support_binlog = MockSupportBinlogOff; + auto originalApi = sqlite3_export_relational_symbols; + sqlite3_export_relational_symbols = &mockApi; + EXPECT_EQ(SqliteConnection::IsSupportBinlog(config), false); + LOG_INFO("----RdbStore_Binlog_Performance_006 binlog off----"); + auto T1 = GetRestoreTime(HAMode::MANUAL_TRIGGER, false); + + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(RdbDoubleWriteBinlogTest::databaseName); + WaitForBinlogDelete(); + ASSERT_FALSE(CheckFolderExist(RdbDoubleWriteBinlogTest::binlogDatabaseName)); + sqlite3_export_relational_symbols = originalApi; + EXPECT_EQ(SqliteConnection::IsSupportBinlog(config), true); + LOG_INFO("----RdbStore_Binlog_Performance_006 binlog on----"); + auto T1_2 = GetRestoreTime(HAMode::MANUAL_TRIGGER, false); + EXPECT_GT(T1 * 1.8, T1_2); + LOG_INFO("----RdbStore_Binlog_Performance_006----, %{public}" PRId64 ", %{public}" PRId64 ",", T1, T1_2); +} diff --git a/relational_store/test/native/rdb/unittest/rdb_double_write_concurrent_test.cpp b/relational_store/test/native/rdb/unittest/rdb_double_write_concurrent_test.cpp index 4ab065f3..394a1969 100644 --- a/relational_store/test/native/rdb/unittest/rdb_double_write_concurrent_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_double_write_concurrent_test.cpp @@ -66,10 +66,10 @@ protected: enum SlaveStatus : uint32_t { UNDEFINED, - DB_NOT_EXITS, BACKING_UP, BACKUP_INTERRUPT, BACKUP_FINISHED, + DB_CLOSING, }; }; diff --git a/relational_store/test/native/rdb/unittest/rdb_double_write_test.cpp b/relational_store/test/native/rdb/unittest/rdb_double_write_test.cpp index 4438c316..8cb38c9f 100644 --- a/relational_store/test/native/rdb/unittest/rdb_double_write_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_double_write_test.cpp @@ -1,1172 +1,1787 @@ -/* - * Copyright (c) 2021 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. - */ -#define LOG_TAG "RdbDoubleWriteTest" -#include -#include -#include - -#include -#include - -#include "common.h" -#include "file_ex.h" -#include "logger.h" -#include "rdb_common.h" -#include "rdb_errno.h" -#include "rdb_helper.h" -#include "rdb_open_callback.h" -#include "sqlite_utils.h" -#include "sys/types.h" - -using namespace testing::ext; -using namespace OHOS::NativeRdb; -using namespace OHOS::Rdb; - -class RdbDoubleWriteTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - void CheckResultSet(std::shared_ptr &store); - void CheckAge(std::shared_ptr &resultSet); - void CheckSalary(std::shared_ptr &resultSet); - void CheckBlob(std::shared_ptr &resultSet); - void CheckNumber( - std::shared_ptr &store, int num, int errCode = E_OK, const std::string &tableName = "test"); - void Insert(int64_t start, int count, bool isSlave = false, int dataSize = 0); - void WaitForBackupFinish(int32_t expectStatus, int maxTimes = 400); - void TryInterruptBackup(); - void InitDb(); - - static const std::string DATABASE_NAME; - static const std::string SLAVE_DATABASE_NAME; - static std::shared_ptr store; - static std::shared_ptr slaveStore; - static std::shared_ptr store3; - - enum SlaveStatus : uint32_t { - UNDEFINED, - DB_NOT_EXITS, - BACKING_UP, - BACKUP_INTERRUPT, - BACKUP_FINISHED, - }; -}; - -const std::string RdbDoubleWriteTest::DATABASE_NAME = RDB_TEST_PATH + "dual_write_test.db"; -const std::string RdbDoubleWriteTest::SLAVE_DATABASE_NAME = RDB_TEST_PATH + "dual_write_test_slave.db"; -std::shared_ptr RdbDoubleWriteTest::store = nullptr; -std::shared_ptr RdbDoubleWriteTest::slaveStore = nullptr; -std::shared_ptr RdbDoubleWriteTest::store3 = nullptr; -const int BLOB_SIZE = 3; -const uint8_t EXPECTED_BLOB_DATA[]{ 1, 2, 3 }; -const int CHECKAGE = 18; -const double CHECKCOLUMN = 100.5; - -class DoubleWriteTestOpenCallback : public RdbOpenCallback { -public: - int OnCreate(RdbStore &store) override; - int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; - static const std::string CREATE_TABLE_TEST; -}; - -const std::string DoubleWriteTestOpenCallback::CREATE_TABLE_TEST = - std::string("CREATE TABLE IF NOT EXISTS test ") + std::string("(id INTEGER PRIMARY KEY AUTOINCREMENT, " - "name TEXT NOT NULL, age INTEGER, salary " - "REAL, blobType BLOB)"); - -int DoubleWriteTestOpenCallback::OnCreate(RdbStore &store) -{ - return store.ExecuteSql(CREATE_TABLE_TEST); -} - -int DoubleWriteTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) -{ - return E_OK; -} - -void RdbDoubleWriteTest::SetUpTestCase(void) -{ -} - -void RdbDoubleWriteTest::TearDownTestCase(void) -{ -} - -void RdbDoubleWriteTest::SetUp(void) -{ -} - -void RdbDoubleWriteTest::TearDown(void) -{ - store = nullptr; - slaveStore = nullptr; - RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME); -} - -void RdbDoubleWriteTest::InitDb() -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MAIN_REPLICA); - DoubleWriteTestOpenCallback helper; - RdbDoubleWriteTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(RdbDoubleWriteTest::store, nullptr); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - store->ExecuteSql("DELETE FROM test"); - slaveStore->ExecuteSql("DELETE FROM test"); -} - -/** - * @tc.name: RdbStore_DoubleWrite_001 - * @tc.desc: test RdbStore doubleWrite - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_001, TestSize.Level1) -{ - InitDb(); - int64_t id; - ValuesBucket values; - - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(1, id); - - values.Clear(); - values.PutInt("id", 2); - values.PutString("name", std::string("lisi")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(2, id); - - values.Clear(); - values.PutInt("id", 3); - values.PutString("name", std::string("lisi")); - values.PutInt("age", 20L); - values.PutDouble("salary", 100.5f); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, id); - - RdbDoubleWriteTest::CheckResultSet(slaveStore); -} - -void RdbDoubleWriteTest::Insert(int64_t start, int count, bool isSlave, int dataSize) -{ - ValuesBucket values; - int64_t id = start; - int ret = E_OK; - for (int i = 0; i < count; i++) { - values.Clear(); - values.PutInt("id", id); - if (dataSize > 0) { - values.PutString("name", std::string(dataSize, 'a')); - } else { - values.PutString("name", std::string("zhangsan")); - } - values.PutInt("age", CHECKAGE); - values.PutDouble("salary", CHECKCOLUMN); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - if (isSlave) { - ret = slaveStore->Insert(id, "test", values); - } else { - ret = store->Insert(id, "test", values); - } - EXPECT_EQ(ret, E_OK); - id++; - } -} - -void RdbDoubleWriteTest::WaitForBackupFinish(int32_t expectStatus, int maxTimes) -{ - int32_t curStatus = store->GetBackupStatus(); - int tryTimes = 0; - while (curStatus != expectStatus && (++tryTimes <= maxTimes)) { - usleep(50000); // 50000 delay - curStatus = store->GetBackupStatus(); - } - LOG_INFO("----------cur backup Status:%{public}d---------", curStatus); - ASSERT_EQ(curStatus, expectStatus); -} - -void RdbDoubleWriteTest::TryInterruptBackup() -{ - int err = store->InterruptBackup(); - int tryTimes = 0; - while (err != E_OK && (++tryTimes <= 1000)) { // 1000 is try time - usleep(10000); // 10000 delay - err = store->InterruptBackup(); - } - EXPECT_EQ(err, E_OK); - LOG_INFO("----------interrupt backup---------"); -} - -void RdbDoubleWriteTest::CheckResultSet(std::shared_ptr &store) -{ - std::shared_ptr resultSet = - store->QuerySql("SELECT * FROM test WHERE name = ?", std::vector{ "zhangsan" }); - EXPECT_NE(resultSet, nullptr); - - int columnIndex; - int intVal; - std::string strVal; - ColumnType columnType; - int position; - int ret = resultSet->GetRowIndex(position); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(position, -1); - - ret = resultSet->GetColumnType(0, columnType); - EXPECT_EQ(ret, E_ROW_OUT_RANGE); - - ret = resultSet->GoToFirstRow(); - EXPECT_EQ(ret, E_OK); - - ret = resultSet->GetColumnIndex("id", columnIndex); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(columnIndex, 0); - ret = resultSet->GetColumnType(columnIndex, columnType); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(1, intVal); - - ret = resultSet->GetColumnIndex("name", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnType(columnIndex, columnType); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(columnType, ColumnType::TYPE_STRING); - ret = resultSet->GetString(columnIndex, strVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ("zhangsan", strVal); - - RdbDoubleWriteTest::CheckAge(resultSet); - RdbDoubleWriteTest::CheckSalary(resultSet); - RdbDoubleWriteTest::CheckBlob(resultSet); - - ret = resultSet->GoToNextRow(); - EXPECT_EQ(ret, E_ROW_OUT_RANGE); - - ret = resultSet->GetColumnType(columnIndex, columnType); - EXPECT_EQ(ret, E_ROW_OUT_RANGE); - - ret = resultSet->Close(); - EXPECT_EQ(ret, E_OK); -} - -void RdbDoubleWriteTest::CheckAge(std::shared_ptr &resultSet) -{ - int columnIndex; - int intVal; - ColumnType columnType; - int ret = resultSet->GetColumnIndex("age", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnType(columnIndex, columnType); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(CHECKAGE, intVal); -} - -void RdbDoubleWriteTest::CheckSalary(std::shared_ptr &resultSet) -{ - int columnIndex; - double dVal; - ColumnType columnType; - int ret = resultSet->GetColumnIndex("salary", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnType(columnIndex, columnType); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(columnType, ColumnType::TYPE_FLOAT); - ret = resultSet->GetDouble(columnIndex, dVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(CHECKCOLUMN, dVal); -} - -void RdbDoubleWriteTest::CheckBlob(std::shared_ptr &resultSet) -{ - int columnIndex; - std::vector blob; - ColumnType columnType; - int ret = resultSet->GetColumnIndex("blobType", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnType(columnIndex, columnType); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(columnType, ColumnType::TYPE_BLOB); - ret = resultSet->GetBlob(columnIndex, blob); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(BLOB_SIZE, static_cast(blob.size())); - for (int i = 0; i < BLOB_SIZE; i++) { - EXPECT_EQ(EXPECTED_BLOB_DATA[i], blob[i]); - } -} - -void RdbDoubleWriteTest::CheckNumber( - std::shared_ptr &store, int num, int errCode, const std::string &tableName) -{ - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM " + tableName); - ASSERT_NE(resultSet, nullptr); - int countNum; - int ret = resultSet->GetRowCount(countNum); - EXPECT_EQ(ret, errCode); - EXPECT_EQ(num, countNum); -} - -/** - * @tc.name: RdbStore_DoubleWrite_003 - * @tc.desc: test RdbStore execute - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_003, TestSize.Level1) -{ - InitDb(); - - int64_t id; - ValuesBucket values; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 25); - values.PutDouble("salary", CHECKCOLUMN); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - auto [ret2, outValue2] = store->Execute("UPDATE test SET age= 18 WHERE id = 1"); - EXPECT_EQ(E_OK, ret2); - - RdbDoubleWriteTest::CheckResultSet(slaveStore); -} - -/** - * @tc.name: RdbStore_DoubleWrite_004 - * @tc.desc: test RdbStore updata - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_004, TestSize.Level1) -{ - InitDb(); - - int64_t id; - - ValuesBucket values; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 25); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); - - int changedRows; - values.Clear(); - values.PutInt("age", 18); - ret = store->Update(changedRows, "test", values); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(1, changedRows); - - RdbDoubleWriteTest::CheckResultSet(slaveStore); -} - -/** - * @tc.name: RdbStore_DoubleWrite_005 - * @tc.desc: test RdbStore delete - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_005, TestSize.Level1) -{ - InitDb(); - - ValuesBucket values; - int64_t id; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(1, id); - - values.Clear(); - values.PutInt("id", 2); - values.PutString("name", std::string("lisi")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(2, id); - - values.Clear(); - values.PutInt("id", 3); - values.PutString("name", std::string("lisi")); - values.PutInt("age", 20L); - values.PutDouble("salary", 100.5f); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, id); - - int deletedRows; - ret = store->Delete(deletedRows, "test", "id = 2"); - ret = store->Delete(deletedRows, "test", "id = 3"); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(1, deletedRows); - - RdbDoubleWriteTest::CheckNumber(slaveStore, 1); -} - -/** - * @tc.name: RdbStore_DoubleWrite_007 - * @tc.desc: open SINGLE db, write, close, open MAIN_REPLICA db, check slave - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_007, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::SINGLE); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(store, nullptr); - - int64_t id = 10; - int count = 100; - Insert(id, count); - - store = nullptr; - config.SetHaMode(HAMode::MAIN_REPLICA); - RdbDoubleWriteTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(RdbDoubleWriteTest::store, nullptr); - - WaitForBackupFinish(BACKUP_FINISHED); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - - RdbDoubleWriteTest::CheckNumber(RdbDoubleWriteTest::slaveStore, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_008 - * @tc.desc: open MAIN_REPLICA db, write, close, corrupt, reopen db allow rebuild, db returns to normal - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_008, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_008 insert finish"); - - store = nullptr; - - std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); - ASSERT_TRUE(file.is_open() == true); - file.seekp(30, std::ios::beg); - ASSERT_TRUE(file.good() == true); - char bytes[2] = { 0x6, 0x6 }; - file.write(bytes, 2); - ASSERT_TRUE(file.good() == true); - file.close(); - LOG_INFO("RdbStore_DoubleWrite_008 corrupt db finish"); - - SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); - SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MAIN_REPLICA); - config.SetAllowRebuild(true); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - RebuiltType rebuiltType; - store->GetRebuilt(rebuiltType); - EXPECT_EQ(rebuiltType, RebuiltType::REPAIRED); - LOG_INFO("RdbStore_DoubleWrite_008 reopen db finish"); - - RdbDoubleWriteTest::CheckNumber(store, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_009 - * @tc.desc: open MAIN_REPLICA db, write, slave db has 100 more data than main db, restore, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_009, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - Insert(id, 100); - id = 200; - Insert(id, 100, true); - RdbDoubleWriteTest::CheckNumber(store, 100); - RdbDoubleWriteTest::CheckNumber(slaveStore, 200); - EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); - RdbDoubleWriteTest::CheckNumber(store, 200); -} - -/** - * @tc.name: RdbStore_DoubleWrite_010 - * @tc.desc: open MAIN_REPLICA db, write, close all, corrupt slave, open MAIN_REPLICA db, slave returns to normal - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_010, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_010 insert finish"); - - slaveStore = nullptr; - store = nullptr; - - std::fstream file(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); - ASSERT_TRUE(file.is_open() == true); - file.seekp(30, std::ios::beg); - ASSERT_TRUE(file.good() == true); - char bytes[2] = { 0x6, 0x6 }; - file.write(bytes, 2); - ASSERT_TRUE(file.good() == true); - file.close(); - LOG_INFO("RdbStore_DoubleWrite_010 corrupt db finish"); - SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); - SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); - - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MAIN_REPLICA); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - LOG_INFO("RdbStore_DoubleWrite_010 reopen main db finish"); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - LOG_INFO("RdbStore_DoubleWrite_010 reopen slave db finish"); - WaitForBackupFinish(BACKUP_FINISHED); - RdbDoubleWriteTest::CheckNumber(slaveStore, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_011 - * @tc.desc: open MAIN_REPLICA db, write, close slave, corrupt slave, backup, check slave - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_011, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_011 insert finish"); - - slaveStore = nullptr; - - std::fstream file(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); - ASSERT_TRUE(file.is_open() == true); - file.seekp(30, std::ios::beg); - ASSERT_TRUE(file.good() == true); - char bytes[2] = { 0x6, 0x6 }; - file.write(bytes, 2); - ASSERT_TRUE(file.good() == true); - file.close(); - LOG_INFO("RdbStore_DoubleWrite_011 corrupt db finish"); - - EXPECT_NE(store->Backup(std::string(""), {}), E_OK); - LOG_INFO("RdbStore_DoubleWrite_011 backup db finish"); - EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - int errCode; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - LOG_INFO("RdbStore_DoubleWrite_011 reopen slave db finish"); - - RdbDoubleWriteTest::CheckNumber(slaveStore, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_012 - * @tc.desc: test RdbStore transaction - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_012, TestSize.Level1) -{ - InitDb(); - - int err = store->BeginTransaction(); - EXPECT_EQ(err, E_OK); - int64_t id; - ValuesBucket values; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 25); - values.PutDouble("salary", CHECKCOLUMN); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - auto [ret2, outValue2] = store->Execute("UPDATE test SET age= 18 WHERE id = 1"); - EXPECT_EQ(E_OK, ret2); - err = store->Commit(); - EXPECT_EQ(err, E_OK); - - RdbDoubleWriteTest::CheckResultSet(slaveStore); -} - -/** - * @tc.name: RdbStore_DoubleWrite_013 - * @tc.desc: open MANUAL_TRIGGER db, open slave, write, slave is empty, backup, check slave, write, check slave - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_013, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MANUAL_TRIGGER); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - LOG_INFO("RdbStore_DoubleWrite_013 reopen main db finish"); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - LOG_INFO("RdbStore_DoubleWrite_013 reopen slave db finish"); - - int64_t id = 10; - int count = 100; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_013 insert finish"); - - RdbDoubleWriteTest::CheckNumber(slaveStore, 0); - - errCode = store->Backup(std::string(""), {}); - EXPECT_EQ(errCode, E_OK); - LOG_INFO("RdbStore_DoubleWrite_013 backup finish"); - - RdbDoubleWriteTest::CheckNumber(slaveStore, count); - - id = 1000; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_013 insert finish"); - RdbDoubleWriteTest::CheckNumber(slaveStore, 200); // 200 is all count -} - -/** - * @tc.name: RdbStore_DoubleWrite_014 - * @tc.desc: open MANUAL_TRIGGER db, write, backup, open slave, check slave, write, check slave - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_014, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MANUAL_TRIGGER); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - LOG_INFO("RdbStore_DoubleWrite_014 reopen main db finish"); - - int64_t id = 10; - int count = 100; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_014 insert finish"); - - errCode = store->Backup(std::string(""), {}); - EXPECT_EQ(errCode, E_OK); - LOG_INFO("RdbStore_DoubleWrite_014 backup finish"); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - LOG_INFO("RdbStore_DoubleWrite_014 reopen slave db finish"); - - RdbDoubleWriteTest::CheckNumber(slaveStore, count); - - id = 1000; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_014 insert finish"); - RdbDoubleWriteTest::CheckNumber(slaveStore, 200); // 200 is all count -} - -/** - * @tc.name: RdbStore_DoubleWrite_015 - * @tc.desc: open MAIN_REPLICA db, write, close, corrupt, slave create table, open MAIN_REPLICA db. check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_015, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - ValuesBucket values; - for (int i = 0; i < count; i++) { - id++; - values.Clear(); - values.PutInt("id", id); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - } - LOG_INFO("RdbStore_DoubleWrite_015 insert finish"); - - store = nullptr; - - std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); - ASSERT_TRUE(file.is_open() == true); - file.seekp(30, std::ios::beg); - ASSERT_TRUE(file.good() == true); - char bytes[2] = { 0x6, 0x6 }; - file.write(bytes, 2); - ASSERT_TRUE(file.good() == true); - file.close(); - LOG_INFO("RdbStore_DoubleWrite_015 corrupt db finish"); - SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); - SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); - - int errCode = slaveStore->ExecuteSql("CREATE TABLE IF NOT EXISTS xx (id INTEGER PRIMARY KEY AUTOINCREMENT," - "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"); - EXPECT_EQ(errCode, E_OK); - EXPECT_EQ(slaveStore->Insert(id, "xx", values), E_OK); - - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MAIN_REPLICA); - config.SetAllowRebuild(true); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - LOG_INFO("RdbStore_DoubleWrite_015 reopen db finish"); - - RdbDoubleWriteTest::CheckNumber(store, 1, E_OK, std::string("xx")); - RdbDoubleWriteTest::CheckNumber(store, count); - RdbDoubleWriteTest::CheckNumber(slaveStore, 1, E_OK, std::string("xx")); - RdbDoubleWriteTest::CheckNumber(slaveStore, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_016 - * @tc.desc: open MAIN_REPLICA db, write, close, delete db file, reopen, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_016, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_016 insert finish"); - - store = nullptr; - LOG_INFO("RdbStore_DoubleWrite_016 close finish"); - - SqliteUtils::DeleteFile(DATABASE_NAME); - SqliteUtils::DeleteFile(DATABASE_NAME + "-shm"); - SqliteUtils::DeleteFile(DATABASE_NAME + "-wal"); - LOG_INFO("RdbStore_DoubleWrite_016 delete db file finish"); - - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MAIN_REPLICA); - DoubleWriteTestOpenCallback helper; - int errCode; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - LOG_INFO("RdbStore_DoubleWrite_016 reopen db finish"); - - WaitForBackupFinish(BACKUP_FINISHED); - - RdbDoubleWriteTest::CheckNumber(store, count); - RdbDoubleWriteTest::CheckNumber(slaveStore, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_018 - * @tc.desc: open MAIN_REPLICA db, update slave, insert, M succ && S failed, - * check failureFlag, backup, check failureFlag - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_018, TestSize.Level1) -{ - InitDb(); - - int64_t id; - ValuesBucket values; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 25); - values.PutDouble("salary", CHECKCOLUMN); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - - auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 3 WHERE id = 1"); - EXPECT_EQ(E_OK, ret2); - - int64_t id2; - ValuesBucket values2; - values2.PutInt("id", 3); - values2.PutString("name", std::string("zhangsan")); - values2.PutInt("age", 25); - values2.PutDouble("salary", CHECKCOLUMN); - values2.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret3 = store->Insert(id2, "test", values2); - EXPECT_EQ(E_OK, ret3); - std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + +"-slaveFailure"; - bool isFlagFileExists = OHOS::FileExists(failureFlagPath); - ASSERT_TRUE(isFlagFileExists); - ASSERT_TRUE(store->IsSlaveDiffFromMaster()); - - int errCode; - errCode = store->Backup(std::string(""), {}); - EXPECT_EQ(errCode, E_OK); - isFlagFileExists = OHOS::FileExists(failureFlagPath); - ASSERT_FALSE(isFlagFileExists); -} - -/** - * @tc.name: RdbStore_DoubleWrite_019 - * @tc.desc: open MAIN_REPLICA db, update slave, insert, M succ && S failed, - * check failureFlag, reopen, check failureFlag - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_019, TestSize.Level1) -{ - InitDb(); - - int64_t id; - ValuesBucket values; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 25); - values.PutDouble("salary", CHECKCOLUMN); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); - EXPECT_EQ(ret, E_OK); - - auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 3 WHERE id = 1"); - EXPECT_EQ(E_OK, ret2); - - int64_t id2; - ValuesBucket values2; - values2.PutInt("id", 3); - values2.PutString("name", std::string("zhangsan")); - values2.PutInt("age", 25); - values2.PutDouble("salary", CHECKCOLUMN); - values2.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret3 = store->Insert(id2, "test", values2); - EXPECT_EQ(E_OK, ret3); - std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + +"-slaveFailure"; - bool isFlagFileExists = OHOS::FileExists(failureFlagPath); - ASSERT_TRUE(isFlagFileExists); - ASSERT_TRUE(store->IsSlaveDiffFromMaster()); - - store = nullptr; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MAIN_REPLICA); - config.SetAllowRebuild(true); - DoubleWriteTestOpenCallback helper; - int errCode; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - WaitForBackupFinish(BACKUP_FINISHED); - store = nullptr; - isFlagFileExists = OHOS::FileExists(failureFlagPath); - ASSERT_FALSE(isFlagFileExists); -} - -/** - * @tc.name: RdbStore_DoubleWrite_026 - * @tc.desc: open MANUAL_TRIGGER db, write, restore, insert, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_026, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MANUAL_TRIGGER); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - - int64_t id = 10; - int count = 100; - Insert(id, count); - - EXPECT_EQ(store->Restore(std::string(""), {}), E_INVALID_FILE_PATH); - - id = 2000; - Insert(id, count); - RdbDoubleWriteTest::CheckNumber(store, count + count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_027 - * @tc.desc: open MANUAL_TRIGGER db, write, close, corrupt db, reopen, insert, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_027, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MANUAL_TRIGGER); - config.SetAllowRebuild(true); - DoubleWriteTestOpenCallback helper; - - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - - EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); - - int64_t id = 10; - int count = 100; - Insert(id, count); - RdbDoubleWriteTest::CheckNumber(slaveStore, count); - - store = nullptr; - - std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); - ASSERT_TRUE(file.is_open() == true); - file.seekp(30, std::ios::beg); - ASSERT_TRUE(file.good() == true); - char bytes[2] = { 0x6, 0x6 }; - file.write(bytes, 2); - ASSERT_TRUE(file.good() == true); - file.close(); - - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - - id = 1000; - Insert(id, count); - RdbDoubleWriteTest::CheckNumber(store, count + count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_029 - * @tc.desc: open db, write, corrupt slave db, backup, backup, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_029, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - Insert(id, count); - - std::fstream slaveFile(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::trunc); - ASSERT_TRUE(slaveFile.is_open() == true); - slaveFile << "0000"; - slaveFile.flush(); - slaveFile.close(); - - std::fstream slaveWalFile(SLAVE_DATABASE_NAME + "-wal", std::ios::in | std::ios::out | std::ios::trunc); - ASSERT_TRUE(slaveWalFile.is_open() == true); - slaveWalFile << "0000"; - slaveWalFile.flush(); - slaveWalFile.close(); - - EXPECT_NE(store->Backup(std::string(""), {}), E_OK); - LOG_INFO("RdbStore_DoubleWrite_029 backup again"); - EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); - - RdbDoubleWriteTest::CheckNumber(store, count); - RdbDoubleWriteTest::CheckNumber(slaveStore, -1, E_SQLITE_CORRUPT); - - int errCode = E_OK; - slaveStore = nullptr; - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - - RdbDoubleWriteTest::CheckNumber(slaveStore, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_030 - * @tc.desc: open db, write, update slave, insert, check failure, restore, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_030, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - Insert(id, count); - - auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 666 WHERE id = 22"); - EXPECT_EQ(E_OK, ret2); - - id = 666; - Insert(id, 1); - - std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + +"-slaveFailure"; - bool isFlagFileExists = OHOS::FileExists(failureFlagPath); - ASSERT_TRUE(isFlagFileExists); - - EXPECT_NE(store->Restore(std::string(""), {}), E_OK); - - RdbDoubleWriteTest::CheckNumber(store, count + 1); - RdbDoubleWriteTest::CheckNumber(slaveStore, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_031 - * @tc.desc: open db, delete main.db, deleteRdbStore, check slave db - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_031, TestSize.Level1) -{ - InitDb(); - remove(RdbDoubleWriteTest::DATABASE_NAME.c_str()); - RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME); - EXPECT_NE(access(RdbDoubleWriteTest::SLAVE_DATABASE_NAME.c_str(), F_OK), 0); -} - -/** - * @tc.name: RdbStore_DoubleWrite_032 - * @tc.desc: open db, delete main.db, deleteRdbStore, check slave db - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_032, TestSize.Level1) -{ - InitDb(); - remove(RdbDoubleWriteTest::DATABASE_NAME.c_str()); - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - RdbHelper::DeleteRdbStore(config); - EXPECT_NE(access(RdbDoubleWriteTest::SLAVE_DATABASE_NAME.c_str(), F_OK), 0); -} - -/** - * @tc.name: RdbStore_DoubleWrite_033 - * @tc.desc: open db, write, close, corrupt, open SINGLE db, check - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_033, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - Insert(id, count); - - store = nullptr; - slaveStore = nullptr; - - std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); - ASSERT_TRUE(file.is_open() == true); - file.seekp(30, std::ios::beg); - ASSERT_TRUE(file.good() == true); - char bytes[2] = { 0x6, 0x6 }; - file.write(bytes, 2); - ASSERT_TRUE(file.good() == true); - file.close(); - - SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); - SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::SINGLE); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - - RebuiltType rebuiltType; - store->GetRebuilt(rebuiltType); - EXPECT_EQ(rebuiltType, RebuiltType::REPAIRED); - - RdbDoubleWriteTest::CheckNumber(store, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_034 - * @tc.desc: open MANUAL_TRIGGER db, write, backup, insert, check count, restore, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_034, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MANUAL_TRIGGER); - config.SetAllowRebuild(true); - DoubleWriteTestOpenCallback helper; - - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - - int64_t id = 10; - int count = 100; - Insert(id, count); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); - RdbDoubleWriteTest::CheckNumber(slaveStore, count); - - id = 1000; - Insert(id, count, true); - RdbDoubleWriteTest::CheckNumber(store, count); - RdbDoubleWriteTest::CheckNumber(slaveStore, count + count); - slaveStore = nullptr; - - EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); - RdbDoubleWriteTest::CheckNumber(store, count + count); - - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - RdbDoubleWriteTest::CheckNumber(slaveStore, 0L); -} \ No newline at end of file +///* +// * Copyright (c) 2021 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. +// */ +// +//#define LOG_TAG "RdbDoubleWriteTest" +//#include +//#include +//#include +//#include +// +//#include +//#include +// +//#include "common.h" +//#include "file_ex.h" +//#include "grd_api_manager.h" +//#include "logger.h" +//#include "rdb_common.h" +//#include "rdb_errno.h" +//#include "rdb_helper.h" +//#include "rdb_open_callback.h" +//#include "rdb_security_manager.h" +//#ifndef CROSS_PLATFORM +//#include "relational/relational_store_sqlite_ext.h" +//#endif +//#include "sqlite_connection.h" +//#include "sqlite_utils.h" +//#include "sys/types.h" +// +//using namespace testing::ext; +//using namespace OHOS::NativeRdb; +//using namespace OHOS::Rdb; +// +//class RdbDoubleWriteTest : public testing::Test { +//public: +// static void SetUpTestCase(void); +// static void TearDownTestCase(void); +// void SetUp(); +// void TearDown(); +// void CheckResultSet(std::shared_ptr &store); +// void CheckAge(std::shared_ptr &resultSet); +// void CheckSalary(std::shared_ptr &resultSet); +// void CheckBlob(std::shared_ptr &resultSet); +// void CheckNumber( +// std::shared_ptr &store, int num, int errCode = E_OK, const std::string &tableName = "test"); +// void Insert(int64_t start, int count, bool isSlave = false, int dataSize = 0); +// void WaitForBackupFinish(int32_t expectStatus, int maxTimes = 400); +// void WaitForAsyncRepairFinish(int maxTimes = 400); +// void TryInterruptBackup(); +// void InitDb(HAMode mode = HAMode::MAIN_REPLICA, bool isOpenSlave = true); +// +// static const std::string DATABASE_NAME; +// static const std::string SLAVE_DATABASE_NAME; +// static std::shared_ptr store; +// static std::shared_ptr slaveStore; +// static std::shared_ptr store3; +// static const struct sqlite3_api_routines_extra *originalExtraApi; +// static struct sqlite3_api_routines_extra mockExtraApi; +//#ifndef CROSS_PLATFORM +// static const struct sqlite3_api_routines_relational *originalKvApi; +// static struct sqlite3_api_routines_relational mockKvApi; +//#endif +// +// enum SlaveStatus : uint32_t { +// UNDEFINED, +// BACKING_UP, +// BACKUP_INTERRUPT, +// BACKUP_FINISHED, +// DB_CLOSING, +// }; +//}; +// +//const std::string RdbDoubleWriteTest::DATABASE_NAME = RDB_TEST_PATH + "dual_write_test.db"; +//const std::string RdbDoubleWriteTest::SLAVE_DATABASE_NAME = RDB_TEST_PATH + "dual_write_test_slave.db"; +//std::shared_ptr RdbDoubleWriteTest::store = nullptr; +//std::shared_ptr RdbDoubleWriteTest::slaveStore = nullptr; +//std::shared_ptr RdbDoubleWriteTest::store3 = nullptr; +//const struct sqlite3_api_routines_extra *RdbDoubleWriteTest::originalExtraApi = sqlite3_export_extra_symbols; +//struct sqlite3_api_routines_extra RdbDoubleWriteTest::mockExtraApi = *sqlite3_export_extra_symbols; +//#ifndef CROSS_PLATFORM +//const struct sqlite3_api_routines_relational *RdbDoubleWriteTest::originalKvApi = sqlite3_export_relational_symbols; +//struct sqlite3_api_routines_relational RdbDoubleWriteTest::mockKvApi = *sqlite3_export_relational_symbols; +//#endif +//const int BLOB_SIZE = 3; +//const uint8_t EXPECTED_BLOB_DATA[]{ 1, 2, 3 }; +//const int CHECKAGE = 18; +//const double CHECKCOLUMN = 100.5; +//const int HUGE_DATA_SIZE = 6 * 1024 * 1024; // 1MB +// +//class DoubleWriteTestOpenCallback : public RdbOpenCallback { +//public: +// int OnCreate(RdbStore &store) override; +// int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +// int OnOpen(RdbStore &rdbStore) override; +// static const std::string CREATE_TABLE_TEST; +//}; +// +//const std::string DoubleWriteTestOpenCallback::CREATE_TABLE_TEST = +// std::string("CREATE TABLE IF NOT EXISTS test ") + std::string("(id INTEGER PRIMARY KEY AUTOINCREMENT, " +// "name TEXT NOT NULL, age INTEGER, salary " +// "REAL, blobType BLOB)"); +// +//int DoubleWriteTestOpenCallback::OnCreate(RdbStore &store) +//{ +// return store.ExecuteSql(CREATE_TABLE_TEST); +//} +// +//int DoubleWriteTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +//{ +// return E_OK; +//} +// +//int DoubleWriteTestOpenCallback::OnOpen(RdbStore &rdbStore) +//{ +// int version = 0; +// rdbStore.GetVersion(version); +// EXPECT_TRUE(version > -1); +// return E_OK; +//} +// +//static int MockNotSupportBinlog(const char *notUsed) +//{ +// return SQLITE_ERROR; +//} +// +//static int MockSupportBinlog(const char *notUsed) +//{ +// return SQLITE_OK; +//} +// +//#ifndef CROSS_PLATFORM +//static int MockNotSupportBinlogWithParam(const char *name) +//{ +// return SQLITE_ERROR; +//} +// +//static int MockSupportBinlogWithParam(const char *name) +//{ +// return SQLITE_OK; +//} +//#endif +//static int MockReplayBinlog(sqlite3 *srcDb, sqlite3 *destDb) +//{ +// return SQLITE_OK; +//} +// +//static int MockCleanBinlog(sqlite3 *db, BinlogFileCleanModeE mode) +//{ +// return SQLITE_OK; +//} +// +//void RdbDoubleWriteTest::SetUpTestCase(void) +//{ +//} +// +//void RdbDoubleWriteTest::TearDownTestCase(void) +//{ +//} +// +//void RdbDoubleWriteTest::SetUp(void) +//{ +// mockExtraApi.is_support_binlog = MockNotSupportBinlog; +// mockExtraApi.replay_binlog = MockReplayBinlog; +// mockExtraApi.clean_binlog = MockCleanBinlog; +// sqlite3_export_extra_symbols = &mockExtraApi; +//#ifndef CROSS_PLATFORM +// mockKvApi.is_support_binlog = MockNotSupportBinlogWithParam; +// sqlite3_export_relational_symbols = &mockKvApi; +//#endif +// store = nullptr; +// slaveStore = nullptr; +// RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME); +//} +// +//void RdbDoubleWriteTest::TearDown(void) +//{ +// RdbDoubleWriteTest::WaitForAsyncRepairFinish(); +// store = nullptr; +// slaveStore = nullptr; +// RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME); +// sqlite3_export_extra_symbols = originalExtraApi; +//#ifndef CROSS_PLATFORM +// sqlite3_export_relational_symbols = originalKvApi; +//#endif +//} +// +//void RdbDoubleWriteTest::InitDb(HAMode mode, bool isOpenSlave) +//{ +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(mode); +// DoubleWriteTestOpenCallback helper; +// RdbDoubleWriteTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// ASSERT_NE(RdbDoubleWriteTest::store, nullptr); +// store->ExecuteSql("DELETE FROM test"); +// +// if (isOpenSlave) { +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// ASSERT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// slaveStore->ExecuteSql("DELETE FROM test"); +// } +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_001 +// * @tc.desc: test RdbStore doubleWrite +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_001, TestSize.Level1) +//{ +// InitDb(); +// int64_t id; +// ValuesBucket values; +// +// values.PutInt("id", 1); +// values.PutString("name", std::string("zhangsan")); +// values.PutInt("age", 18); +// values.PutDouble("salary", 100.5); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(1, id); +// +// values.Clear(); +// values.PutInt("id", 2); +// values.PutString("name", std::string("lisi")); +// values.PutInt("age", 18); +// values.PutDouble("salary", 100.5); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(2, id); +// +// values.Clear(); +// values.PutInt("id", 3); +// values.PutString("name", std::string("lisi")); +// values.PutInt("age", 20L); +// values.PutDouble("salary", 100.5f); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(3, id); +// +// RdbDoubleWriteTest::CheckResultSet(slaveStore); +//} +// +//void RdbDoubleWriteTest::Insert(int64_t start, int count, bool isSlave, int dataSize) +//{ +// ValuesBucket values; +// int64_t id = start; +// int ret = E_OK; +// for (int i = 0; i < count; i++) { +// values.Clear(); +// values.PutInt("id", id); +// if (dataSize > 0) { +// values.PutString("name", std::string(dataSize, 'a')); +// } else { +// values.PutString("name", std::string("zhangsan")); +// } +// values.PutInt("age", CHECKAGE); +// values.PutDouble("salary", CHECKCOLUMN); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// if (isSlave) { +// ret = slaveStore->Insert(id, "test", values); +// } else { +// ret = store->Insert(id, "test", values); +// } +// EXPECT_EQ(ret, E_OK); +// id++; +// } +//} +// +//void RdbDoubleWriteTest::WaitForBackupFinish(int32_t expectStatus, int maxTimes) +//{ +// int32_t curStatus = store->GetBackupStatus(); +// int tryTimes = 0; +// while (curStatus != expectStatus && (++tryTimes <= maxTimes)) { +// usleep(50000); // 50000 delay +// curStatus = store->GetBackupStatus(); +// } +// LOG_INFO("----------cur backup Status:%{public}d---------", curStatus); +// ASSERT_EQ(curStatus, expectStatus); +//} +// +//void RdbDoubleWriteTest::WaitForAsyncRepairFinish(int maxTimes) +//{ +// LOG_INFO("---- start wait for async finish----"); +// sleep(1); +// int tryTimes = 0; +// auto keyFiles = RdbSecurityManager::KeyFiles(DATABASE_NAME + "-async.restore"); +// while (keyFiles.Lock(false) != E_OK && (++tryTimes <= maxTimes)) { +// sleep(1); +// } +// LOG_INFO("---- end wait for async finish ----, %{public}d", tryTimes); +//} +// +//void RdbDoubleWriteTest::TryInterruptBackup() +//{ +// int err = store->InterruptBackup(); +// int tryTimes = 0; +// while (err != E_OK && (++tryTimes <= 1000)) { // 1000 is try time +// usleep(10000); // 10000 delay +// err = store->InterruptBackup(); +// } +// EXPECT_EQ(err, E_OK); +// LOG_INFO("----------interrupt backup---------"); +//} +// +//void RdbDoubleWriteTest::CheckResultSet(std::shared_ptr &store) +//{ +// std::shared_ptr resultSet = +// store->QuerySql("SELECT * FROM test WHERE name = ?", std::vector{ "zhangsan" }); +// EXPECT_NE(resultSet, nullptr); +// +// int columnIndex; +// int intVal; +// std::string strVal; +// ColumnType columnType; +// int position; +// int ret = resultSet->GetRowIndex(position); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(position, -1); +// +// ret = resultSet->GetColumnType(0, columnType); +// EXPECT_EQ(ret, E_ROW_OUT_RANGE); +// +// ret = resultSet->GoToFirstRow(); +// EXPECT_EQ(ret, E_OK); +// +// ret = resultSet->GetColumnIndex("id", columnIndex); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(columnIndex, 0); +// ret = resultSet->GetColumnType(columnIndex, columnType); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER); +// ret = resultSet->GetInt(columnIndex, intVal); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(1, intVal); +// +// ret = resultSet->GetColumnIndex("name", columnIndex); +// EXPECT_EQ(ret, E_OK); +// ret = resultSet->GetColumnType(columnIndex, columnType); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(columnType, ColumnType::TYPE_STRING); +// ret = resultSet->GetString(columnIndex, strVal); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ("zhangsan", strVal); +// +// RdbDoubleWriteTest::CheckAge(resultSet); +// RdbDoubleWriteTest::CheckSalary(resultSet); +// RdbDoubleWriteTest::CheckBlob(resultSet); +// +// ret = resultSet->GoToNextRow(); +// EXPECT_EQ(ret, E_ROW_OUT_RANGE); +// +// ret = resultSet->GetColumnType(columnIndex, columnType); +// EXPECT_EQ(ret, E_ROW_OUT_RANGE); +// +// ret = resultSet->Close(); +// EXPECT_EQ(ret, E_OK); +//} +// +//void RdbDoubleWriteTest::CheckAge(std::shared_ptr &resultSet) +//{ +// int columnIndex; +// int intVal; +// ColumnType columnType; +// int ret = resultSet->GetColumnIndex("age", columnIndex); +// EXPECT_EQ(ret, E_OK); +// ret = resultSet->GetColumnType(columnIndex, columnType); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER); +// ret = resultSet->GetInt(columnIndex, intVal); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(CHECKAGE, intVal); +//} +// +//void RdbDoubleWriteTest::CheckSalary(std::shared_ptr &resultSet) +//{ +// int columnIndex; +// double dVal; +// ColumnType columnType; +// int ret = resultSet->GetColumnIndex("salary", columnIndex); +// EXPECT_EQ(ret, E_OK); +// ret = resultSet->GetColumnType(columnIndex, columnType); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(columnType, ColumnType::TYPE_FLOAT); +// ret = resultSet->GetDouble(columnIndex, dVal); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(CHECKCOLUMN, dVal); +//} +// +//void RdbDoubleWriteTest::CheckBlob(std::shared_ptr &resultSet) +//{ +// int columnIndex; +// std::vector blob; +// ColumnType columnType; +// int ret = resultSet->GetColumnIndex("blobType", columnIndex); +// EXPECT_EQ(ret, E_OK); +// ret = resultSet->GetColumnType(columnIndex, columnType); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(columnType, ColumnType::TYPE_BLOB); +// ret = resultSet->GetBlob(columnIndex, blob); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(BLOB_SIZE, static_cast(blob.size())); +// for (int i = 0; i < BLOB_SIZE; i++) { +// EXPECT_EQ(EXPECTED_BLOB_DATA[i], blob[i]); +// } +//} +// +//void RdbDoubleWriteTest::CheckNumber( +// std::shared_ptr &store, int num, int errCode, const std::string &tableName) +//{ +// std::shared_ptr resultSet = store->QuerySql("SELECT * FROM " + tableName); +// ASSERT_NE(resultSet, nullptr); +// int countNum; +// int ret = resultSet->GetRowCount(countNum); +// EXPECT_EQ(ret, errCode); +// EXPECT_EQ(num, countNum); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_003 +// * @tc.desc: test RdbStore execute +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_003, TestSize.Level1) +//{ +// InitDb(); +// +// int64_t id; +// ValuesBucket values; +// values.PutInt("id", 1); +// values.PutString("name", std::string("zhangsan")); +// values.PutInt("age", 25); +// values.PutDouble("salary", CHECKCOLUMN); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// auto [ret2, outValue2] = store->Execute("UPDATE test SET age= 18 WHERE id = 1"); +// EXPECT_EQ(E_OK, ret2); +// +// RdbDoubleWriteTest::CheckResultSet(slaveStore); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_004 +// * @tc.desc: test RdbStore updata +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_004, TestSize.Level1) +//{ +// InitDb(); +// +// int64_t id; +// +// ValuesBucket values; +// values.PutInt("id", 1); +// values.PutString("name", std::string("zhangsan")); +// values.PutInt("age", 25); +// values.PutDouble("salary", 100.5); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret = store->Insert(id, "test", values); +// +// int changedRows; +// values.Clear(); +// values.PutInt("age", 18); +// ret = store->Update(changedRows, "test", values); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(1, changedRows); +// +// RdbDoubleWriteTest::CheckResultSet(slaveStore); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_005 +// * @tc.desc: test RdbStore delete +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_005, TestSize.Level1) +//{ +// InitDb(); +// +// ValuesBucket values; +// int64_t id; +// values.PutInt("id", 1); +// values.PutString("name", std::string("zhangsan")); +// values.PutInt("age", 18); +// values.PutDouble("salary", 100.5); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(1, id); +// +// values.Clear(); +// values.PutInt("id", 2); +// values.PutString("name", std::string("lisi")); +// values.PutInt("age", 18); +// values.PutDouble("salary", 100.5); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(2, id); +// +// values.Clear(); +// values.PutInt("id", 3); +// values.PutString("name", std::string("lisi")); +// values.PutInt("age", 20L); +// values.PutDouble("salary", 100.5f); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(3, id); +// +// int deletedRows; +// ret = store->Delete(deletedRows, "test", "id = 2"); +// ret = store->Delete(deletedRows, "test", "id = 3"); +// EXPECT_EQ(ret, E_OK); +// EXPECT_EQ(1, deletedRows); +// +// RdbDoubleWriteTest::CheckNumber(slaveStore, 1); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_007 +// * @tc.desc: open SINGLE db, write, close, open MAIN_REPLICA db, check slave +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_007, TestSize.Level1) +//{ +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::SINGLE); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_NE(store, nullptr); +// +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// +// store = nullptr; +// config.SetHaMode(HAMode::MAIN_REPLICA); +// RdbDoubleWriteTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_NE(RdbDoubleWriteTest::store, nullptr); +// +// WaitForBackupFinish(BACKUP_FINISHED); +// +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// +// RdbDoubleWriteTest::CheckNumber(RdbDoubleWriteTest::slaveStore, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_008 +// * @tc.desc: open MAIN_REPLICA db, write, close, corrupt, reopen db allow rebuild, db returns to normal +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_008, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_008 insert finish"); +// +// store = nullptr; +// +// std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// LOG_INFO("RdbStore_DoubleWrite_008 corrupt db finish"); +// +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// config.SetAllowRebuild(true); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// RebuiltType rebuiltType; +// store->GetRebuilt(rebuiltType); +// EXPECT_EQ(rebuiltType, RebuiltType::REPAIRED); +// LOG_INFO("RdbStore_DoubleWrite_008 reopen db finish"); +// +// RdbDoubleWriteTest::CheckNumber(store, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_009 +// * @tc.desc: open MAIN_REPLICA db, write, slave db has 100 more data than main db, restore, check count +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_009, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// Insert(id, 100); +// id = 200; +// Insert(id, 100, true); +// RdbDoubleWriteTest::CheckNumber(store, 100); +// RdbDoubleWriteTest::CheckNumber(slaveStore, 200); +// EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); +// RdbDoubleWriteTest::CheckNumber(store, 200); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_010 +// * @tc.desc: open MAIN_REPLICA db, write, close all, corrupt slave, open MAIN_REPLICA db, slave returns to normal +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_010, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_010 insert finish"); +// +// slaveStore = nullptr; +// store = nullptr; +// +// std::fstream file(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// LOG_INFO("RdbStore_DoubleWrite_010 corrupt db finish"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); +// +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_010 reopen main db finish"); +// +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_010 reopen slave db finish"); +// WaitForBackupFinish(BACKUP_FINISHED); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_011 +// * @tc.desc: open MAIN_REPLICA db, write, close slave, corrupt slave, backup, check slave +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_011, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_011 insert finish"); +// +// slaveStore = nullptr; +// +// std::fstream file(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// LOG_INFO("RdbStore_DoubleWrite_011 corrupt db finish"); +// +// EXPECT_NE(store->Backup(std::string(""), {}), E_OK); +// LOG_INFO("RdbStore_DoubleWrite_011 backup db finish"); +// EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); +// +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// int errCode; +// RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_011 reopen slave db finish"); +// +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_012 +// * @tc.desc: test RdbStore transaction +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_012, TestSize.Level1) +//{ +// InitDb(); +// +// int err = store->BeginTransaction(); +// EXPECT_EQ(err, E_OK); +// int64_t id; +// ValuesBucket values; +// values.PutInt("id", 1); +// values.PutString("name", std::string("zhangsan")); +// values.PutInt("age", 25); +// values.PutDouble("salary", CHECKCOLUMN); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// auto [ret2, outValue2] = store->Execute("UPDATE test SET age= 18 WHERE id = 1"); +// EXPECT_EQ(E_OK, ret2); +// err = store->Commit(); +// EXPECT_EQ(err, E_OK); +// +// RdbDoubleWriteTest::CheckResultSet(slaveStore); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_013 +// * @tc.desc: open MANUAL_TRIGGER db, open slave, write, slave is empty, backup, check slave, write, check slave +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_013, TestSize.Level1) +//{ +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_013 reopen main db finish"); +// +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_013 reopen slave db finish"); +// +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_013 insert finish"); +// +// RdbDoubleWriteTest::CheckNumber(slaveStore, 0); +// +// errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// LOG_INFO("RdbStore_DoubleWrite_013 backup finish"); +// +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// +// id = 1000; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_013 insert finish"); +// RdbDoubleWriteTest::CheckNumber(slaveStore, 200); // 200 is all count +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_014 +// * @tc.desc: open MANUAL_TRIGGER db, write, backup, open slave, check slave, write, check slave +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_014, TestSize.Level1) +//{ +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_014 reopen main db finish"); +// +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_014 insert finish"); +// +// errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// LOG_INFO("RdbStore_DoubleWrite_014 backup finish"); +// +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_014 reopen slave db finish"); +// +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// +// id = 1000; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_014 insert finish"); +// RdbDoubleWriteTest::CheckNumber(slaveStore, 200); // 200 is all count +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_015 +// * @tc.desc: open MAIN_REPLICA db, write, close, corrupt, slave create table, open MAIN_REPLICA db. check count +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_015, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// int count = 100; +// ValuesBucket values; +// for (int i = 0; i < count; i++) { +// id++; +// values.Clear(); +// values.PutInt("id", id); +// values.PutString("name", std::string("zhangsan")); +// values.PutInt("age", 18); +// values.PutDouble("salary", CHECKCOLUMN); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// } +// LOG_INFO("RdbStore_DoubleWrite_015 insert finish"); +// +// store = nullptr; +// +// std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// LOG_INFO("RdbStore_DoubleWrite_015 corrupt db finish"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); +// +// int errCode = slaveStore->ExecuteSql("CREATE TABLE IF NOT EXISTS xx (id INTEGER PRIMARY KEY AUTOINCREMENT," +// "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"); +// EXPECT_EQ(errCode, E_OK); +// EXPECT_EQ(slaveStore->Insert(id, "xx", values), E_OK); +// +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// config.SetAllowRebuild(true); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_015 reopen db finish"); +// +// RdbDoubleWriteTest::CheckNumber(store, 1, E_OK, std::string("xx")); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, 1, E_OK, std::string("xx")); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_016 +// * @tc.desc: open MAIN_REPLICA db, write, close, delete db file, reopen, check count +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_016, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_016 insert finish"); +// +// store = nullptr; +// LOG_INFO("RdbStore_DoubleWrite_016 close finish"); +// +// SqliteUtils::DeleteFile(DATABASE_NAME); +// SqliteUtils::DeleteFile(DATABASE_NAME + "-shm"); +// SqliteUtils::DeleteFile(DATABASE_NAME + "-wal"); +// LOG_INFO("RdbStore_DoubleWrite_016 delete db file finish"); +// +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// DoubleWriteTestOpenCallback helper; +// int errCode; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_016 reopen db finish"); +// +// WaitForBackupFinish(BACKUP_FINISHED); +// +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_018 +// * @tc.desc: open MAIN_REPLICA db, update slave, insert, M succ && S failed, +// * check failureFlag, backup, check failureFlag +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_018, TestSize.Level1) +//{ +// InitDb(); +// +// int64_t id; +// ValuesBucket values; +// values.PutInt("id", 1); +// values.PutString("name", std::string("zhangsan")); +// values.PutInt("age", 25); +// values.PutDouble("salary", CHECKCOLUMN); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// +// auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 3 WHERE id = 1"); +// EXPECT_EQ(E_OK, ret2); +// +// int64_t id2; +// ValuesBucket values2; +// values2.PutInt("id", 3); +// values2.PutString("name", std::string("zhangsan")); +// values2.PutInt("age", 25); +// values2.PutDouble("salary", CHECKCOLUMN); +// values2.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret3 = store->Insert(id2, "test", values2); +// EXPECT_EQ(E_OK, ret3); +// std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + +"-slaveFailure"; +// bool isFlagFileExists = OHOS::FileExists(failureFlagPath); +// ASSERT_TRUE(isFlagFileExists); +// ASSERT_TRUE(store->IsSlaveDiffFromMaster()); +// +// int errCode; +// errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// isFlagFileExists = OHOS::FileExists(failureFlagPath); +// ASSERT_FALSE(isFlagFileExists); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_019 +// * @tc.desc: open MAIN_REPLICA db, update slave, insert, M succ && S failed, +// * check failureFlag, reopen, check failureFlag +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_019, TestSize.Level1) +//{ +// InitDb(); +// +// int64_t id; +// ValuesBucket values; +// values.PutInt("id", 1); +// values.PutString("name", std::string("zhangsan")); +// values.PutInt("age", 25); +// values.PutDouble("salary", CHECKCOLUMN); +// values.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret = store->Insert(id, "test", values); +// EXPECT_EQ(ret, E_OK); +// +// auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 3 WHERE id = 1"); +// EXPECT_EQ(E_OK, ret2); +// +// int64_t id2; +// ValuesBucket values2; +// values2.PutInt("id", 3); +// values2.PutString("name", std::string("zhangsan")); +// values2.PutInt("age", 25); +// values2.PutDouble("salary", CHECKCOLUMN); +// values2.PutBlob("blobType", std::vector{ 1, 2, 3 }); +// int ret3 = store->Insert(id2, "test", values2); +// EXPECT_EQ(E_OK, ret3); +// std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + +"-slaveFailure"; +// bool isFlagFileExists = OHOS::FileExists(failureFlagPath); +// ASSERT_TRUE(isFlagFileExists); +// ASSERT_TRUE(store->IsSlaveDiffFromMaster()); +// +// store = nullptr; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// config.SetAllowRebuild(true); +// DoubleWriteTestOpenCallback helper; +// int errCode; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// WaitForBackupFinish(BACKUP_FINISHED); +// store = nullptr; +// isFlagFileExists = OHOS::FileExists(failureFlagPath); +// ASSERT_FALSE(isFlagFileExists); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_026 +// * @tc.desc: open MANUAL_TRIGGER db, write, restore, insert, check count +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_026, TestSize.Level1) +//{ +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// +// EXPECT_EQ(store->Restore(std::string(""), {}), E_INVALID_FILE_PATH); +// +// id = 2000; +// Insert(id, count); +// RdbDoubleWriteTest::CheckNumber(store, count + count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_027 +// * @tc.desc: open MANUAL_TRIGGER db, write, close, corrupt db, reopen, insert, check count +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_027, TestSize.Level1) +//{ +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// config.SetAllowRebuild(true); +// DoubleWriteTestOpenCallback helper; +// +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// +// store = nullptr; +// +// std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// +// id = 1000; +// Insert(id, count); +// RdbDoubleWriteTest::CheckNumber(store, count + count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_029 +// * @tc.desc: open db, write, corrupt slave db, backup, backup, check count +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_029, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// +// std::fstream slaveFile(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::trunc); +// ASSERT_TRUE(slaveFile.is_open() == true); +// slaveFile << "0000"; +// slaveFile.flush(); +// slaveFile.close(); +// +// std::fstream slaveWalFile(SLAVE_DATABASE_NAME + "-wal", std::ios::in | std::ios::out | std::ios::trunc); +// ASSERT_TRUE(slaveWalFile.is_open() == true); +// slaveWalFile << "0000"; +// slaveWalFile.flush(); +// slaveWalFile.close(); +// +// EXPECT_NE(store->Backup(std::string(""), {}), E_OK); +// LOG_INFO("RdbStore_DoubleWrite_029 backup again"); +// EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); +// +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, -1, E_SQLITE_CORRUPT); +// +// int errCode = E_OK; +// slaveStore = nullptr; +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_030 +// * @tc.desc: open db, write, update slave, insert, check failure, restore, check count +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_030, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// +// auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 666 WHERE id = 22"); +// EXPECT_EQ(E_OK, ret2); +// +// id = 666; +// Insert(id, 1); +// +// std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + +"-slaveFailure"; +// bool isFlagFileExists = OHOS::FileExists(failureFlagPath); +// ASSERT_TRUE(isFlagFileExists); +// +// EXPECT_NE(store->Restore(std::string(""), {}), E_OK); +// +// RdbDoubleWriteTest::CheckNumber(store, count + 1); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_031 +// * @tc.desc: open db, delete main.db, deleteRdbStore, check slave db +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_031, TestSize.Level1) +//{ +// InitDb(); +// remove(RdbDoubleWriteTest::DATABASE_NAME.c_str()); +// RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME); +// EXPECT_NE(access(RdbDoubleWriteTest::SLAVE_DATABASE_NAME.c_str(), F_OK), 0); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_032 +// * @tc.desc: open db, delete main.db, deleteRdbStore, check slave db +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_032, TestSize.Level1) +//{ +// InitDb(); +// remove(RdbDoubleWriteTest::DATABASE_NAME.c_str()); +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// RdbHelper::DeleteRdbStore(config); +// EXPECT_NE(access(RdbDoubleWriteTest::SLAVE_DATABASE_NAME.c_str(), F_OK), 0); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_033 +// * @tc.desc: open db, write, close, corrupt, open SINGLE db, check +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_033, TestSize.Level1) +//{ +// InitDb(); +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// +// store = nullptr; +// slaveStore = nullptr; +// +// std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::SINGLE); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// +// RebuiltType rebuiltType; +// store->GetRebuilt(rebuiltType); +// EXPECT_EQ(rebuiltType, RebuiltType::REPAIRED); +// +// RdbDoubleWriteTest::CheckNumber(store, count); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_034 +// * @tc.desc: open db, close, open SINGLE db, create index, write, reopen, check slave db +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_034, TestSize.Level1) +//{ +// InitDb(); +// store = nullptr; +// slaveStore = nullptr; +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::SINGLE); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// EXPECT_EQ(store->ExecuteSql("CREATE index age_index ON test(age);"), E_OK); +// int64_t id = 10; +// int count = 10; +// Insert(id, count); +// store = nullptr; +// +// config.SetHaMode(HAMode::MAIN_REPLICA); +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// ASSERT_NE(store, nullptr); +// RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// DoubleWriteTestOpenCallback slaveHelper; +// slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); +// ASSERT_NE(RdbDoubleWriteTest::slaveStore, nullptr); +// WaitForBackupFinish(BACKUP_FINISHED); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// store = nullptr; +// slaveStore = nullptr; +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Manual_Trigger_Not_Verify_Db +// * @tc.desc: open MANUAL_TRIGGER db, write, corrupt db, check backup with verify and no verify +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Manual_Trigger_Not_Verify_Db, TestSize.Level0) +//{ +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("RdbStore_DoubleWrite_Manual_Trigger_Not_Verify_Db reopen main db finish"); +// +// int64_t id = 10; +// int count = 100; +// Insert(id, count); +// LOG_INFO("RdbStore_DoubleWrite_Manual_Trigger_Not_Verify_Db insert finish"); +// +// RdbDoubleWriteTest::CheckNumber(store, count); +// store = nullptr; +// +// std::fstream file(RdbDoubleWriteTest::DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open()); +// +// file.seekp(0x2000, std::ios::beg); +// ASSERT_TRUE(file.good()); +// +// char bytes[128]; +// std::fill_n(bytes, 128, 0xff); +// file.write(bytes, 128); +// file.flush(); +// file.close(); +// LOG_INFO("RdbStore_DoubleWrite_Manual_Trigger_Not_Verify_Db corrupt db finish"); +// +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// +// errCode = store->Backup(std::string("")); +// EXPECT_EQ(errCode, E_SQLITE_CORRUPT); +// +// errCode = store->Backup(std::string(""), {}, false); +// EXPECT_EQ(errCode, E_OK); +// store = nullptr; +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_001 +// * @tc.desc: test db is deleted while open huge database, in MANUAL_TRIGGER +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_001, TestSize.Level3) +//{ +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_001 ----"); +// InitDb(HAMode::MANUAL_TRIGGER); +// int errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: close store ----"); +// store = nullptr; +// slaveStore = nullptr; +// LOG_INFO("---- step 3: remove db file ----"); +// remove(RdbDoubleWriteTest::DATABASE_NAME.c_str()); +// LOG_INFO("---- step 4: reopen and trigger restore ----"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// if (errCode != E_SQLITE_BUSY) { +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("---- step 5: execute sql while restore ----"); +// EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY); +// LOG_INFO("---- step 6: check db count ----"); +// RdbDoubleWriteTest::WaitForAsyncRepairFinish(); +// RdbDoubleWriteTest::CheckNumber(store, count); +// } +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_001 ----"); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_002 +// * @tc.desc: test db is deleted while open huge database, in MAIN_REPLICA +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_002, TestSize.Level3) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_002 ----"); +// InitDb(); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: close store ----"); +// store = nullptr; +// slaveStore = nullptr; +// LOG_INFO("---- step 3: remove db file ----"); +// remove(RdbDoubleWriteTest::DATABASE_NAME.c_str()); +// LOG_INFO("---- step 4: reopen and trigger restore ----"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); +// int errCode = E_OK; +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// if (errCode != E_SQLITE_BUSY) { +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("---- step 5: execute sql while restore ----"); +// EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY); +// LOG_INFO("---- step 6: check db count ----"); +// RdbDoubleWriteTest::WaitForAsyncRepairFinish(); +// RdbDoubleWriteTest::CheckNumber(store, count); +// } +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_002 ----"); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_003 +// * @tc.desc: test async restore for huge db in MAIN_REPLICA +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_003, TestSize.Level3) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_003 ----"); +// InitDb(); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: corrupt store ----"); +// std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// LOG_INFO("---- step 3: manually trigger repair ----"); +// EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); +// EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY); +// LOG_INFO("---- step 4: check db count ----"); +// RdbDoubleWriteTest::WaitForAsyncRepairFinish(); +// RdbDoubleWriteTest::CheckNumber(store, count); +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_003 ----"); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_004 +// * @tc.desc: test async restore for huge db in MANUAL_TRIGGER +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_004, TestSize.Level3) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_004 ----"); +// InitDb(HAMode::MANUAL_TRIGGER); +// int errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: corrupt store ----"); +// std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// LOG_INFO("---- step 3: manually trigger repair ----"); +// EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); +// EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY); +// LOG_INFO("---- step 4: check db count ----"); +// RdbDoubleWriteTest::WaitForAsyncRepairFinish(); +// RdbDoubleWriteTest::CheckNumber(store, count); +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_004 ----"); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_005 +// * @tc.desc: test restore is called while doing async restore +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_005, TestSize.Level3) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_005 ----"); +// InitDb(HAMode::MANUAL_TRIGGER); +// int errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: corrupt store ----"); +// std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// LOG_INFO("---- step 3: manually trigger repair ----"); +// EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); +// EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY); +// LOG_INFO("---- step 4: trigger repair again ----"); +// EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); +// LOG_INFO("---- step 5: check db count ----"); +// RdbDoubleWriteTest::WaitForAsyncRepairFinish(); +// RdbDoubleWriteTest::CheckNumber(store, count); +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_005 ----"); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_006 +// * @tc.desc: test call restore for huge db when slave db is corrupted +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_006, TestSize.Level3) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_006 ----"); +// InitDb(HAMode::MANUAL_TRIGGER); +// int errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: corrupt store ----"); +// std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// ASSERT_TRUE(file.is_open() == true); +// file.seekp(30, std::ios::beg); +// ASSERT_TRUE(file.good() == true); +// char bytes[2] = { 0x6, 0x6 }; +// file.write(bytes, 2); +// ASSERT_TRUE(file.good() == true); +// file.close(); +// LOG_INFO("---- step 3: mark backup db corrupted ----"); +// SqliteUtils::SetSlaveInvalid(DATABASE_NAME); +// EXPECT_TRUE(SqliteUtils::IsSlaveInvalid(DATABASE_NAME)); +// LOG_INFO("---- step 4: manually trigger repair ----"); +// EXPECT_EQ(store->Restore(std::string(""), {}), E_SQLITE_CORRUPT); +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_006 ----"); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_007 +// * @tc.desc: test execsql when restore mark is abnormal +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_007, TestSize.Level3) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_007 ----"); +// InitDb(HAMode::MANUAL_TRIGGER); +// int errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: mark backup db as restoring ----"); +// SqliteUtils::SetSlaveRestoring(DATABASE_NAME); +// EXPECT_TRUE(SqliteUtils::IsSlaveRestoring(DATABASE_NAME)); +// LOG_INFO("---- step 3: manually trigger create statement should remove the mark ----"); +// EXPECT_EQ(store->ExecuteSql("select * from test;"), E_OK); +// EXPECT_FALSE(SqliteUtils::IsSlaveRestoring(DATABASE_NAME)); +// LOG_INFO("---- step 4: lock database for restoring and trigger create statement should not remove the mark ----"); +// SqliteUtils::SetSlaveRestoring(DATABASE_NAME); +// EXPECT_TRUE(SqliteUtils::IsSlaveRestoring(DATABASE_NAME)); +// auto keyFiles = RdbSecurityManager::KeyFiles(DATABASE_NAME + "-async.restore"); +// EXPECT_EQ(keyFiles.Lock(false), E_OK); +// LOG_INFO("---- step 5: manually trigger create statement should not remove the mark ----"); +// EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY); +// EXPECT_TRUE(SqliteUtils::IsSlaveRestoring(DATABASE_NAME)); +// SqliteUtils::SetSlaveRestoring(DATABASE_NAME, false); +// keyFiles.Unlock(); +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_007 ----"); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_008 +// * @tc.desc: test trigger async repair +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_008, TestSize.Level3) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_008 ----"); +// InitDb(HAMode::MANUAL_TRIGGER); +// int errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: corrupt both slave and master db ----"); +// store = nullptr; +// slaveStore = nullptr; +// EXPECT_TRUE(SqliteUtils::CopyFile(DATABASE_NAME + "-dwr", DATABASE_NAME)); +// std::fstream file(SLAVE_DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); +// file.seekp(1, std::ios::beg); +// std::vector null_buffer(count, '\0'); +// file.write(null_buffer.data(), count); +// file.close(); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); +// SqliteUtils::SetSlaveInvalid(DATABASE_NAME); +// EXPECT_TRUE(SqliteUtils::IsSlaveInvalid(DATABASE_NAME)); +// +// LOG_INFO("---- step 3: reopen should give E_SQLITE_CORRUPT ----"); +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_EQ(errCode, E_SQLITE_CORRUPT); +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_008 ----"); +//} +// +///** +// * @tc.name: RdbStore_DoubleWrite_Huge_DB_009 +// * @tc.desc: test trigger async repair +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_Huge_DB_009, TestSize.Level3) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// LOG_INFO("---- start RdbStore_DoubleWrite_Huge_DB_009 ----"); +// InitDb(HAMode::MANUAL_TRIGGER); +// int errCode = store->Backup(std::string(""), {}); +// EXPECT_EQ(errCode, E_OK); +// int64_t id = 10; +// int count = 200; +// LOG_INFO("---- step 1: insert huge data ----"); +// Insert(id, count, false, HUGE_DATA_SIZE); +// RdbDoubleWriteTest::CheckNumber(store, count); +// RdbDoubleWriteTest::CheckNumber(slaveStore, count); +// LOG_INFO("---- step 2: corrupt master db ----"); +// store = nullptr; +// slaveStore = nullptr; +// EXPECT_TRUE(SqliteUtils::CopyFile(DATABASE_NAME + "-dwr", DATABASE_NAME)); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::DATABASE_NAME + "-dwr"); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME + "-dwr"); +// LOG_INFO("---- step 3: reopen should give ok ----"); +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// DoubleWriteTestOpenCallback helper; +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// if (errCode != E_SQLITE_BUSY) { +// EXPECT_EQ(errCode, E_OK); +// ASSERT_NE(store, nullptr); +// LOG_INFO("---- step 4: trigger statement should busy ----"); +// EXPECT_EQ(store->ExecuteSql("select * from test;"), E_DATABASE_BUSY); +// store = nullptr; +// } +// LOG_INFO("---- step 5: check db count ----"); +// RdbDoubleWriteTest::WaitForAsyncRepairFinish(); +// store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// ASSERT_NE(store, nullptr); +// RdbDoubleWriteTest::CheckNumber(store, count); +// LOG_INFO("---- end RdbStore_DoubleWrite_Huge_DB_009 ----"); +//} +// +///* +// * @tc.name: RdbStore_Mock_Binlog_001 +// * @tc.desc: test call backup and restore when binlog is supported +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_Mock_Binlog_001, TestSize.Level0) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// mockExtraApi.is_support_binlog = MockSupportBinlog; +// sqlite3_export_extra_symbols = &mockExtraApi; +//#ifndef CROSS_PLATFORM +// mockKvApi.is_support_binlog = MockSupportBinlogWithParam; +// sqlite3_export_relational_symbols = &mockKvApi; +//#endif +// +// InitDb(HAMode::MANUAL_TRIGGER, false); +// EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); +// EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); +//} +// +///* +// * @tc.name: RdbStore_Mock_Binlog_002 +// * @tc.desc: test call CheckReplicaIntegrity when binlog is supported +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, RdbStore_Mock_Binlog_002, TestSize.Level0) +//{ +// if (!IsUsingArkData()) { +// GTEST_SKIP() << "Current testcase is not compatible from current rdb"; +// } +// mockExtraApi.is_support_binlog = MockSupportBinlog; +// sqlite3_export_extra_symbols = &mockExtraApi; +//#ifndef CROSS_PLATFORM +// mockKvApi.is_support_binlog = MockSupportBinlogWithParam; +// sqlite3_export_relational_symbols = &mockKvApi; +//#endif +// InitDb(HAMode::MAIN_REPLICA, false); +// store = nullptr; +// +// // open slave for conflict by compress +// sqlite3 *db = nullptr; +// int rc = sqlite3_open_v2(RdbDoubleWriteTest::SLAVE_DATABASE_NAME.c_str(), +// &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "compressvfs"); +// EXPECT_EQ(rc, SQLITE_OK); +// EXPECT_NE(db, nullptr); +// const char *ddl = DoubleWriteTestOpenCallback::CREATE_TABLE_TEST.c_str(); +// EXPECT_EQ(sqlite3_exec(db, ddl, nullptr, nullptr, nullptr), SQLITE_OK); +// sqlite3_close_v2(db); +// +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// EXPECT_EQ(Connection::CheckReplicaIntegrity(config), E_OK); +//} +// +///** +// * @tc.name: CreateReplicaStatement_Test_001 +// * @tc.desc: Normal testCase of CreateReplicaStatement. +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, CreateReplicaStatement_Test_001, TestSize.Level2) +//{ +// InitDb(); +// +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// auto [errCode, readConn] = SqliteConnection::Create(config, false); +// EXPECT_EQ(errCode, SQLITE_OK); +// ASSERT_NE(readConn, nullptr); +// auto [err, statement] = readConn->CreateReplicaStatement("select * from test;", readConn); +// EXPECT_EQ(err, SQLITE_OK); +// EXPECT_NE(statement, nullptr); +// statement = nullptr; +// readConn = nullptr; +//} +// +///** +// * @tc.name: CreateReplicaStatement_Test_002 +// * @tc.desc: Abnormal testCase of CreateReplicaStatement. +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, CreateReplicaStatement_Test_002, TestSize.Level2) +//{ +// InitDb(); +// SqliteUtils::DeleteFile(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); +// +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MAIN_REPLICA); +// auto [errCode, readConn] = SqliteConnection::Create(config, false); +// EXPECT_EQ(errCode, SQLITE_OK); +// ASSERT_NE(readConn, nullptr); +// auto [err, statement] = readConn->CreateReplicaStatement("select * from test;", readConn); +// EXPECT_EQ(err, SQLITE_OK); +// EXPECT_NE(statement, nullptr); +// statement = nullptr; +// readConn = nullptr; +//} +// +///** +// * @tc.name: CreateReplicaStatement_Test_003 +// * @tc.desc: Abnormal testCase of CreateReplicaStatement. +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDoubleWriteTest, CreateReplicaStatement_Test_003, TestSize.Level2) +//{ +// InitDb(); +// EXPECT_TRUE(SqliteUtils::CopyFile(SLAVE_DATABASE_NAME + "-dwr", SLAVE_DATABASE_NAME)); +// +// RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); +// config.SetHaMode(HAMode::MANUAL_TRIGGER); +// auto [errCode, readConn] = SqliteConnection::Create(config, false); +// EXPECT_EQ(errCode, SQLITE_OK); +// ASSERT_NE(readConn, nullptr); +// auto [err, statement] = readConn->CreateReplicaStatement("select * from test;", readConn); +// EXPECT_EQ(err, SQLITE_OK); +// EXPECT_NE(statement, nullptr); +//} diff --git a/relational_store/test/native/rdb/unittest/rdb_encrypt_decrypt_test.cpp b/relational_store/test/native/rdb/unittest/rdb_encrypt_decrypt_test.cpp index 530c711c..c0655302 100644 --- a/relational_store/test/native/rdb/unittest/rdb_encrypt_decrypt_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_encrypt_decrypt_test.cpp @@ -193,7 +193,7 @@ HWTEST_F(RdbEncryptTest, RdbStore_Encrypt_04, TestSize.Level1) int errCode; std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); EXPECT_NE(store, nullptr); - std::string keyPath = RDB_TEST_PATH + "key/encrypted.pub_key"; + std::string keyPath = RDB_TEST_PATH + "key/encrypted.pub_key_v1"; int ret = access(keyPath.c_str(), F_OK); EXPECT_EQ(ret, 0); @@ -356,7 +356,7 @@ HWTEST_F(RdbEncryptTest, RdbStore_Encrypt_010, TestSize.Level1) EXPECT_NE(store, nullptr); EXPECT_EQ(errCode, E_OK); - std::string keyPath = RDB_TEST_PATH + "key/encrypted.pub_key"; + std::string keyPath = RDB_TEST_PATH + "key/encrypted.pub_key_v1"; int ret = access(keyPath.c_str(), F_OK); EXPECT_EQ(ret, 0); @@ -529,4 +529,151 @@ HWTEST_F(RdbEncryptTest, KeyFilePath_test_001, TestSize.Level2) EXPECT_EQ(E_OK, store2->Backup(RdbEncryptTest::ENCRYPTED_DATABASE_BACKUP_NAME2)); EXPECT_EQ(E_OK, store2->Restore(RdbEncryptTest::ENCRYPTED_DATABASE_BACKUP_NAME2)); +} + +/** + * @tc.name: KeyCorruptTest + * @tc.desc: test key file corrupt readonly + * @tc.type: FUNC + */ +HWTEST_F(RdbEncryptTest, KeyCorruptTest_01, TestSize.Level1) +{ + RdbStoreConfig config1(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + config1.SetEncryptStatus(true); + config1.SetBundleName("com.example.TestEncrypt1"); + EncryptTestOpenCallback helper1; + int errCode = E_ERROR; + std::shared_ptr store1 = RdbHelper::GetRdbStore(config1, 1, helper1, errCode); + ASSERT_NE(nullptr, store1); + ASSERT_EQ(E_OK, errCode); + int64_t id; + int ret = store1->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + store1 = nullptr; + + RdbSecurityManager::KeyFiles keyFile(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + std::string file = keyFile.GetKeyFile(RdbSecurityManager::KeyFileType::PUB_KEY_FILE); + ASSERT_TRUE(OHOS::FileExists(file)); + std::vector keyfileData; + ASSERT_TRUE(OHOS::LoadBufferFromFile(file, keyfileData)); + + std::vector keyCorrupted = keyfileData; + // fill bytes of keyfile index 10 to 19 with 0 + for (size_t i = 10; i < 20 && i < keyCorrupted.size(); ++i) { + keyCorrupted[i] = 0; + } + ASSERT_TRUE(OHOS::SaveBufferToFile(file, keyCorrupted)); + + RdbStoreConfig config2(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + config2.SetEncryptStatus(true); + config2.SetBundleName("com.example.TestEncrypt1"); + config2.SetReadOnly(true); + EncryptTestOpenCallback helper2; + std::shared_ptr store2 = RdbHelper::GetRdbStore(config2, 1, helper2, errCode); + ASSERT_NE(nullptr, store2); + ASSERT_EQ(E_OK, errCode); + + std::shared_ptr resultSet = store2->QuerySql("SELECT * FROM test"); + ASSERT_NE(nullptr, resultSet); + ret = resultSet->GoToFirstRow(); + EXPECT_EQ(ret, E_OK); + RowEntity rowEntity; + ASSERT_EQ(E_OK, resultSet->GetRow(rowEntity)); + ASSERT_EQ(1, int(rowEntity.Get("id"))); + resultSet->Close(); + store2 = nullptr; +} + +/** + * @tc.name: KeyCorruptTest + * @tc.desc: test key file not exist when readonly + * @tc.type: FUNC + */ +HWTEST_F(RdbEncryptTest, KeyCorruptTest_02, TestSize.Level1) +{ + RdbStoreConfig config1(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + config1.SetEncryptStatus(true); + config1.SetBundleName("com.example.TestEncrypt1"); + EncryptTestOpenCallback helper1; + int errCode = E_ERROR; + std::shared_ptr store1 = RdbHelper::GetRdbStore(config1, 1, helper1, errCode); + ASSERT_NE(nullptr, store1); + ASSERT_EQ(E_OK, errCode); + int64_t id; + int ret = store1->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + store1 = nullptr; + + RdbSecurityManager::KeyFiles keyFile(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + std::string file = keyFile.GetKeyFile(RdbSecurityManager::KeyFileType::PUB_KEY_FILE); + ASSERT_TRUE(OHOS::FileExists(file)); + std::remove(file.c_str()); + ASSERT_FALSE(OHOS::FileExists(file)); + + RdbStoreConfig config2(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + config2.SetEncryptStatus(true); + config2.SetBundleName("com.example.TestEncrypt1"); + config2.SetReadOnly(true); + EncryptTestOpenCallback helper2; + std::shared_ptr store2 = RdbHelper::GetRdbStore(config2, 1, helper2, errCode); + ASSERT_NE(nullptr, store2); + ASSERT_EQ(E_OK, errCode); + + std::shared_ptr resultSet = store2->QuerySql("SELECT * FROM test"); + ASSERT_NE(nullptr, resultSet); + ret = resultSet->GoToFirstRow(); + EXPECT_EQ(ret, E_OK); + RowEntity rowEntity; + ASSERT_EQ(E_OK, resultSet->GetRow(rowEntity)); + ASSERT_EQ(1, int(rowEntity.Get("id"))); + resultSet->Close(); + store2 = nullptr; +} + +/** + * @tc.name: KeyCorruptTest + * @tc.desc: test save key data to file failed + * @tc.type: FUNC + */ +HWTEST_F(RdbEncryptTest, KeyCorruptTest_03, TestSize.Level0) +{ + RdbStoreConfig config1(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + config1.SetEncryptStatus(true); + config1.SetBundleName("com.example.TestEncrypt1"); + EncryptTestOpenCallback helper1; + int errCode = E_ERROR; + std::shared_ptr store1 = RdbHelper::GetRdbStore(config1, 1, helper1, errCode); + ASSERT_NE(nullptr, store1); + ASSERT_EQ(E_OK, errCode); + store1 = nullptr; + + RdbSecurityManager::KeyFiles keyFile(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + std::string file = keyFile.GetKeyFile(RdbSecurityManager::KeyFileType::PUB_KEY_FILE); + ASSERT_TRUE(OHOS::FileExists(file)); + std::vector keyfileData; + ASSERT_TRUE(OHOS::LoadBufferFromFile(file, keyfileData)); + + std::vector keyCorrupted = keyfileData; + // fill bytes of keyfile index 10 to 19 with 0 + for (size_t i = 10; i < 20 && i < keyCorrupted.size(); ++i) { + keyCorrupted[i] = 0; + } + ASSERT_TRUE(OHOS::SaveBufferToFile(file, keyCorrupted)); + + std::string chattrAddiCmd = "chattr +i " + file; + ASSERT_EQ(E_OK, system(chattrAddiCmd.c_str())); + + RdbStoreConfig config2(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + config2.SetEncryptStatus(true); + config2.SetBundleName("com.example.TestEncrypt1"); + EncryptTestOpenCallback helper2; + std::shared_ptr store2 = RdbHelper::GetRdbStore(config2, 1, helper2, errCode); + ASSERT_NE(nullptr, store2); + ASSERT_EQ(E_OK, errCode); + + // Enable the wal file operation. + std::string chattrSubiCmd = "chattr -i " + file; + ASSERT_EQ(E_OK, system(chattrSubiCmd.c_str())); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_encrypt_upgrade_test.cpp b/relational_store/test/native/rdb/unittest/rdb_encrypt_upgrade_test.cpp new file mode 100644 index 00000000..030cf26a --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_encrypt_upgrade_test.cpp @@ -0,0 +1,460 @@ +/* +* 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. +*/ + +#define LOG_TAG "RdbEncryptUpgradeTest" +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "block_data.h" +#include "common.h" +#include "file_ex.h" +#include "hks_api.h" +#include "hks_param.h" +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "rdb_security_manager.h" +#include "sqlite_utils.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; +class RdbEncryptUpgradeTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + static std::string RemoveSuffix(const std::string &name); + std::vector EncryptV0(std::vector &key, std::vector rootKeyAlias); + bool SaveSecretKeyToV0(const std::string &keyPath, RdbSecretKeyData &keyData); + int32_t HksLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, + const struct HksBlob *inData, struct HksBlob *outData); + int32_t HksEncryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, + const struct HksBlob *plainText, struct HksBlob *cipherText); + + static const std::string encryptedDatabaseName; + static const std::string encryptedDatabasePath; + static const std::string encryptedDatabaseKeyDir; + std::mutex mutex_; +}; + +const std::string RdbEncryptUpgradeTest::encryptedDatabaseName = "encrypted.db"; +const std::string RdbEncryptUpgradeTest::encryptedDatabasePath = RDB_TEST_PATH + encryptedDatabaseName; +const std::string RdbEncryptUpgradeTest::encryptedDatabaseKeyDir = RDB_TEST_PATH + "key/"; +static constexpr uint32_t TIMES = 4; +static constexpr uint32_t MAX_UPDATE_SIZE = 64; +static constexpr uint32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES; +static constexpr const char *RDB_HKS_BLOB_TYPE_NONCE = "Z5s0Bo571Koq"; +static constexpr const char *RDB_HKS_BLOB_TYPE_AAD = "RdbClientAAD"; + +class RdbEncryptUpgradeTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string createTableTest; +}; + +std::string const RdbEncryptUpgradeTestOpenCallback::createTableTest = "CREATE TABLE IF NOT EXISTS test " + "(id INTEGER PRIMARY KEY " + "AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, " + "salary " + "REAL, blobType BLOB)"; + +int RdbEncryptUpgradeTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(createTableTest); +} + +int RdbEncryptUpgradeTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void RdbEncryptUpgradeTest::SetUpTestCase() +{ +} + +void RdbEncryptUpgradeTest::TearDownTestCase() +{ +} + +void RdbEncryptUpgradeTest::SetUp() +{ + RdbHelper::ClearCache(); + RdbHelper::DeleteRdbStore(RdbEncryptUpgradeTest::encryptedDatabasePath); +} + +void RdbEncryptUpgradeTest::TearDown() +{ + RdbHelper::ClearCache(); + RdbHelper::DeleteRdbStore(RdbEncryptUpgradeTest::encryptedDatabasePath); +} + +std::string RdbEncryptUpgradeTest::RemoveSuffix(const std::string &name) +{ + std::string suffix(".db"); + auto pos = name.rfind(suffix); + if (pos == std::string::npos || pos < name.length() - suffix.length()) { + return name; + } + return { name, 0, pos }; +} + +int32_t RdbEncryptUpgradeTest::HksLoopUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, + const struct HksBlob *inData, struct HksBlob *outData) +{ + if (outData->size < inData->size * TIMES) { + return HKS_ERROR_INVALID_ARGUMENT; + } + + struct HksBlob input = { MAX_UPDATE_SIZE, inData->data }; + uint8_t *end = inData->data + inData->size - 1; + outData->size = 0; + struct HksBlob output = { MAX_OUTDATA_SIZE, outData->data }; + while (input.data <= end) { + if (input.data + MAX_UPDATE_SIZE > end) { + input.size = end - input.data + 1; + break; + } + auto result = HksUpdate(handle, paramSet, &input, &output); + if (result != HKS_SUCCESS) { + LOG_ERROR("HksUpdate Failed."); + return HKS_FAILURE; + } + + output.data += output.size; + outData->size += output.size; + input.data += MAX_UPDATE_SIZE; + } + output.size = input.size * TIMES; + auto result = HksFinish(handle, paramSet, &input, &output); + if (result != HKS_SUCCESS) { + LOG_ERROR("HksFinish Failed."); + return HKS_FAILURE; + } + outData->size += output.size; + return HKS_SUCCESS; +} + +int32_t RdbEncryptUpgradeTest::HksEncryptThreeStage(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, + const struct HksBlob *plainText, struct HksBlob *cipherText) +{ + uint8_t handle[sizeof(uint64_t)] = { 0 }; + struct HksBlob handleBlob = { sizeof(uint64_t), handle }; + int32_t result = HksInit(keyAlias, paramSet, &handleBlob, nullptr); + if (result != HKS_SUCCESS) { + LOG_ERROR("bai: HksEncrypt failed with error %{public}d", result); + return result; + } + return HksLoopUpdate(&handleBlob, paramSet, plainText, cipherText); +} + +std::vector RdbEncryptUpgradeTest::EncryptV0(std::vector &key, std::vector rootKeyAlias) +{ + std::vector nonce_(RDB_HKS_BLOB_TYPE_NONCE, RDB_HKS_BLOB_TYPE_NONCE + strlen(RDB_HKS_BLOB_TYPE_NONCE)); + std::vector aad_(RDB_HKS_BLOB_TYPE_AAD, RDB_HKS_BLOB_TYPE_AAD + strlen(RDB_HKS_BLOB_TYPE_AAD)); + struct HksBlob blobAad = { uint32_t(aad_.size()), aad_.data() }; + struct HksBlob blobNonce = { uint32_t(nonce_.size()), nonce_.data() }; + struct HksBlob rootKeyName = { uint32_t(rootKeyAlias.size()), rootKeyAlias.data() }; + struct HksBlob plainKey = { uint32_t(key.size()), key.data() }; + struct HksParamSet *params = nullptr; + int32_t ret = HksInitParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksInitParamSet() failed with error %{public}d", ret); + return {}; + } + struct HksParam hksParam[] = {{ .tag = HKS_TAG_ALGORITHM, .uint32Param = HKS_ALG_AES }, + { .tag = HKS_TAG_PURPOSE, .uint32Param = HKS_KEY_PURPOSE_ENCRYPT }, + { .tag = HKS_TAG_DIGEST, .uint32Param = 0 }, + { .tag = HKS_TAG_BLOCK_MODE, .uint32Param = HKS_MODE_GCM }, + { .tag = HKS_TAG_PADDING, .uint32Param = HKS_PADDING_NONE }, + { .tag = HKS_TAG_NONCE, .blob = blobNonce }, + { .tag = HKS_TAG_ASSOCIATED_DATA, .blob = blobAad }, + { .tag = HKS_TAG_AUTH_STORAGE_LEVEL, .uint32Param = HKS_AUTH_STORAGE_LEVEL_DE }}; + + ret = HksAddParams(params, hksParam, sizeof(hksParam) / sizeof(hksParam[0])); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksAddParams failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return {}; + } + + ret = HksBuildParamSet(¶ms); + if (ret != HKS_SUCCESS) { + LOG_ERROR("HksBuildParamSet failed with error %{public}d", ret); + HksFreeParamSet(¶ms); + return {}; + } + std::vector encryptedKey(plainKey.size * TIMES + 1); + struct HksBlob cipherText = { uint32_t(encryptedKey.size()), encryptedKey.data() }; + ret = HksEncryptThreeStage(&rootKeyName, params, &plainKey, &cipherText); + (void)HksFreeParamSet(¶ms); + if (ret != HKS_SUCCESS) { + encryptedKey.assign(encryptedKey.size(), 0); + LOG_ERROR("bai: HksEncrypt failed with error %{public}d", ret); + return {}; + } + encryptedKey.resize(cipherText.size); + LOG_ERROR("bai: EncryptOld success "); + return encryptedKey; +} + +bool RdbEncryptUpgradeTest::SaveSecretKeyToV0(const std::string &keyPath, RdbSecretKeyData &keyData) +{ + LOG_INFO("begin keyPath:%{public}s.", SqliteUtils::Anonymous(keyPath).c_str()); + + std::string secretKeyInString; + secretKeyInString.append(reinterpret_cast(&keyData.distributed), sizeof(uint8_t)); + secretKeyInString.append(reinterpret_cast(&keyData.timeValue), sizeof(time_t)); + secretKeyInString.append(reinterpret_cast(keyData.secretKey.data()), keyData.secretKey.size()); + bool ret; + { + std::lock_guard lock(mutex_); + auto fd = open(keyPath.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + if (fd >= 0) { + ret = OHOS::SaveStringToFd(fd, secretKeyInString); + close(fd); + } else { + ret = false; + } + } + return ret; +} + + +/** +* @tc.name: OTATest_001 +* @tc.desc: getRdbStore ota test +* @tc.type: FUNC +*/ +HWTEST_F(RdbEncryptUpgradeTest, OTATest_001, TestSize.Level1) +{ + RdbStoreConfig config(RdbEncryptUpgradeTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetEncryptStatus(true); + RdbEncryptUpgradeTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + std::string keyPathV1 = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; + bool isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_TRUE(isFileExists); + store = nullptr; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + store = nullptr; + + RdbSecretKeyData keyDataV1; + auto res = RdbSecurityManager::GetInstance().LoadSecretKeyFromDiskV1(keyPathV1, keyDataV1); + ASSERT_EQ(res, true); + std::string keyPathV0 = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + RdbSecretKeyData keyDataV0; + keyDataV0.timeValue = keyDataV1.timeValue; + keyDataV0.distributed = 0; + auto rootKeyAlias = RdbSecurityManager::GetInstance().GetRootKeyAlias(); + auto ret = RdbSecurityManager::GetInstance().CheckRootKeyExists(rootKeyAlias); + ASSERT_NE(ret, HKS_ERROR_NOT_EXIST); + keyDataV0.secretKey = EncryptV0(keyDataV1.secretKey, rootKeyAlias); + res = SaveSecretKeyToV0(keyPathV0, keyDataV0); + ASSERT_EQ(res, true); + isFileExists = OHOS::FileExists(keyPathV0); + ASSERT_TRUE(isFileExists); + + SqliteUtils::DeleteFile(keyPathV1); + isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_FALSE(isFileExists); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_TRUE(isFileExists); + isFileExists = OHOS::FileExists(keyPathV0); + ASSERT_FALSE(isFileExists); +} + + +/** +* @tc.name: OTATest_002 +* @tc.desc: keyFileV1 corrupted ota test +* @tc.type: FUNC +*/ +HWTEST_F(RdbEncryptUpgradeTest, OTATest_002, TestSize.Level1) +{ + RdbStoreConfig config(RdbEncryptUpgradeTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetEncryptStatus(true); + RdbEncryptUpgradeTestOpenCallback helper; + int errCode = E_OK; + RdbHelper::DeleteRdbStore(config); + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + std::string keyPathV1 = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; + bool isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_TRUE(isFileExists); + store = nullptr; + + RdbSecretKeyData keyDataV1; + auto res = RdbSecurityManager::GetInstance().LoadSecretKeyFromDiskV1(keyPathV1, keyDataV1); + ASSERT_EQ(res, true); + std::string keyPathV0 = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + RdbSecretKeyData keyDataV0; + keyDataV0.timeValue = keyDataV1.timeValue; + keyDataV0.distributed = 0; + auto rootKeyAlias = RdbSecurityManager::GetInstance().GetRootKeyAlias(); + auto ret = RdbSecurityManager::GetInstance().CheckRootKeyExists(rootKeyAlias); + ASSERT_NE(ret, HKS_ERROR_NOT_EXIST); + keyDataV0.secretKey = EncryptV0(keyDataV1.secretKey, rootKeyAlias); + res = SaveSecretKeyToV0(keyPathV0, keyDataV0); + ASSERT_EQ(res, true); + isFileExists = OHOS::FileExists(keyPathV0); + ASSERT_TRUE(isFileExists); + + std::vector keyfileData; + ASSERT_TRUE(OHOS::LoadBufferFromFile(keyPathV1, keyfileData)); + std::vector keyCorrupted = keyfileData; + for (size_t i = 10; i < 20 && i < keyCorrupted.size(); ++i) { + keyCorrupted[i] = 0; + } + ASSERT_TRUE(OHOS::SaveBufferToFile(keyPathV1, keyCorrupted)); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_TRUE(isFileExists); + isFileExists = OHOS::FileExists(keyPathV0); + ASSERT_FALSE(isFileExists); +} + +/** +* @tc.name: OTATest_003 +* @tc.desc: keyFileV1 and keyFile exit ota test +* @tc.type: FUNC +*/ +HWTEST_F(RdbEncryptUpgradeTest, OTATest_003, TestSize.Level1) +{ + RdbStoreConfig config(RdbEncryptUpgradeTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetEncryptStatus(true); + RdbEncryptUpgradeTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + std::string keyPathV1 = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; + bool isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_TRUE(isFileExists); + store = nullptr; + + RdbSecretKeyData keyDataV1; + auto res = RdbSecurityManager::GetInstance().LoadSecretKeyFromDiskV1(keyPathV1, keyDataV1); + ASSERT_EQ(res, true); + std::string keyPathV0 = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + RdbSecretKeyData keyDataV0; + keyDataV0.timeValue = keyDataV1.timeValue; + keyDataV0.distributed = 0; + auto rootKeyAlias = RdbSecurityManager::GetInstance().GetRootKeyAlias(); + auto ret = RdbSecurityManager::GetInstance().CheckRootKeyExists(rootKeyAlias); + ASSERT_NE(ret, HKS_ERROR_NOT_EXIST); + keyDataV0.secretKey = EncryptV0(keyDataV1.secretKey, rootKeyAlias); + res = SaveSecretKeyToV0(keyPathV0, keyDataV0); + ASSERT_EQ(res, true); + isFileExists = OHOS::FileExists(keyPathV0); + ASSERT_TRUE(isFileExists); + + SqliteUtils::DeleteFile(keyPathV1); + isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_FALSE(isFileExists); + auto fd = open(keyPathV1.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + ASSERT_GT(fd, 0); + isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_TRUE(isFileExists); + + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + isFileExists = OHOS::FileExists(keyPathV1); + ASSERT_TRUE(isFileExists); + isFileExists = OHOS::FileExists(keyPathV0); + ASSERT_FALSE(isFileExists); +} + +/** +* @tc.name: OTATest_004 +* @tc.desc: query after getRdbStore ota test +* @tc.type: FUNC +*/ +HWTEST_F(RdbEncryptUpgradeTest, OTATest_004, TestSize.Level1) +{ + RdbStoreConfig config(RdbEncryptUpgradeTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetEncryptStatus(true); + RdbEncryptUpgradeTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"); + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + std::string keyPathV1 = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; + store = nullptr; + + RdbSecretKeyData keyDataV1; + auto res = RdbSecurityManager::GetInstance().LoadSecretKeyFromDiskV1(keyPathV1, keyDataV1); + ASSERT_EQ(res, true); + std::string keyPathV0 = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + RdbSecretKeyData keyDataV0; + keyDataV0.timeValue = keyDataV1.timeValue; + keyDataV0.distributed = 0; + auto rootKeyAlias = RdbSecurityManager::GetInstance().GetRootKeyAlias(); + ret = RdbSecurityManager::GetInstance().CheckRootKeyExists(rootKeyAlias); + ASSERT_NE(ret, HKS_ERROR_NOT_EXIST); + keyDataV0.secretKey = EncryptV0(keyDataV1.secretKey, rootKeyAlias); + res = SaveSecretKeyToV0(keyPathV0, keyDataV0); + ASSERT_EQ(res, true); + + SqliteUtils::DeleteFile(keyPathV1); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + auto resultSet = store->QueryByStep("SELECT * FROM test1"); + ASSERT_NE(resultSet, nullptr); + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + ASSERT_EQ(rowCount, 1); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_error_log_test/get_rdb_store_test.cpp b/relational_store/test/native/rdb/unittest/rdb_error_log_test/get_rdb_store_test.cpp new file mode 100644 index 00000000..609d473f --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_error_log_test/get_rdb_store_test.cpp @@ -0,0 +1,594 @@ +/* + * 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 "common.h" +#include "block_data.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "rdb_sql_log.h" +#include "rdb_store.h" +#include "rdb_store_manager.h" +#include "rdb_types.h" +#include "executor_pool.h" +#include "shared_block.h" +#include "sqlite_utils.h" +#include "values_bucket.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::DistributedRdb; + +static constexpr int32_t MAX_THREAD = 8; +static constexpr int32_t MID_THREAD = 4; +static constexpr int32_t SLEEP_TIME = 500; +static constexpr int32_t MAX_SLEEP_TIME = 2000; +static constexpr int32_t JOURNAL_MAX_SIZE = 4096; +static constexpr int32_t JOURNAL_MIN_SIZE = 1024; +static constexpr double DEFAULT_SALARY = 100.5; +static constexpr int32_t AGE_NUM = 18; + +class RdbStoreStoreMultiTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static std::shared_ptr CreateRDB(const std::string &path, + bool encrypt = false, const std::string &bundleName = ""); + static std::shared_ptr CreateRDBSleep(const std::string &path, + bool encrypt = false, const std::string &bundleName = ""); + static void InsertData(std::shared_ptr rdbStore); + static void QueryData(std::shared_ptr rdbStore); +}; + + +void RdbStoreStoreMultiTest::SetUpTestCase(void) +{ +} + +void RdbStoreStoreMultiTest::TearDownTestCase(void) +{ +} + +void RdbStoreStoreMultiTest::SetUp() +{ +} + +void RdbStoreStoreMultiTest::TearDown() +{ +} + +class RDBCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +int RDBCallback::OnCreate(RdbStore &store) +{ + return E_OK; +} + +int RDBCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +class CallbackSleep : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +int CallbackSleep::OnCreate(RdbStore &store) +{ + std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME)); + return E_OK; +} + +int CallbackSleep::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME)); + return E_OK; +} + +std::shared_ptr RdbStoreStoreMultiTest::CreateRDB(const std::string &path, + bool encrypt, const std::string &bundleName) +{ + int version = 1; + RdbStoreConfig config(path); + config.SetEncryptStatus(encrypt); + config.SetBundleName(bundleName); + RDBCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, version, helper, errCode); + EXPECT_NE(store, nullptr); + return store; +} + +std::shared_ptr RdbStoreStoreMultiTest::CreateRDBSleep(const std::string &path, + bool encrypt, const std::string &bundleName) +{ + int version = 1; + RdbStoreConfig config(path); + config.SetEncryptStatus(encrypt); + config.SetBundleName(bundleName); + CallbackSleep helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, version, helper, errCode); + EXPECT_NE(store, nullptr); + return store; +} + +void RdbStoreStoreMultiTest::InsertData(std::shared_ptr rdbStore) +{ + const std::string createTable = + std::string("CREATE TABLE IF NOT EXISTS test ") + std::string("(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary " + "REAL, blobType BLOB)"); + rdbStore->Execute(createTable); + int64_t id; + ValuesBucket values; + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", AGE_NUM); + values.PutDouble("salary", DEFAULT_SALARY); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = rdbStore->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); +} + +void RdbStoreStoreMultiTest::QueryData(std::shared_ptr rdbStore) +{ + std::shared_ptr resultSet = rdbStore->QuerySql("select * from test"); + int ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + int columnIndex; + std::string strVal; + + ret = resultSet->GetColumnIndex("name", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ("zhangsan", strVal); +} + +std::string g_dbPaths[MAX_THREAD] = { "/data/test/store1.db", "/data/test/store2.db", + "/data/test/store3.db", "/data/test/store4.db", "/data/test/store5.db", + "/data/test/store6.db", "/data/test/store7.db", "/data/test/store8.db" }; + +std::string g_dbBundlenames[MAX_THREAD] = { "com.ohos.test1", "com.ohos.test2", + "com.ohos.test3", "com.ohos.test4", "com.ohos.test5", + "com.ohos.test6", "com.ohos.test7", "com.ohos.test8" }; + +/** + * @tc.name: GetRdbStoreTest_001 + * @tc.desc: test Multithreading calls GetRdbStore with same store + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_001, TestSize.Level1) +{ + std::string path = "/data/test/store.db"; + std::shared_ptr stores[MAX_THREAD]; + std::thread threads[MAX_THREAD]; + for (int i = 0; i < MAX_THREAD; ++i) { + threads[i] = std::thread([i, &stores, &path]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDB(path); + }); + } + for (auto& t : threads) { + if (t.joinable()) { + t.join(); + } + } + EXPECT_EQ(stores[0], stores[1]); + EXPECT_EQ(stores[1], stores[2]); + EXPECT_EQ(stores[2], stores[3]); + EXPECT_EQ(stores[3], stores[4]); + EXPECT_EQ(stores[4], stores[5]); + EXPECT_EQ(stores[5], stores[6]); + EXPECT_EQ(stores[6], stores[7]); + RdbHelper::DeleteRdbStore(path); +} + +/** + * @tc.name: GetRdbStoreTest_002 + * @tc.desc: test Multithreading calls GetRdbStore with same encrypt store + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_002, TestSize.Level1) +{ + std::string path = "/data/test/encryptStore.db"; + std::string bundleName = "com.ohos.test"; + std::shared_ptr stores[MAX_THREAD]; + std::thread threads[MAX_THREAD]; + for (int i = 0; i < MAX_THREAD; ++i) { + threads[i] = std::thread([i, &stores, &path, &bundleName]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDB(path, true, bundleName); + }); + } + for (auto& t : threads) { + if (t.joinable()) { + t.join(); + } + } + + EXPECT_EQ(stores[0], stores[1]); + EXPECT_EQ(stores[1], stores[2]); + EXPECT_EQ(stores[2], stores[3]); + EXPECT_EQ(stores[3], stores[4]); + EXPECT_EQ(stores[4], stores[5]); + EXPECT_EQ(stores[5], stores[6]); + EXPECT_EQ(stores[6], stores[7]); + RdbHelper::DeleteRdbStore(path); +} + +/** + * @tc.name: GetRdbStoreTest_003 + * @tc.desc: test Multithreading calls GetRdbStore with diff store + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_003, TestSize.Level1) +{ + std::shared_ptr stores[MAX_THREAD]; + std::thread threads[MAX_THREAD]; + for (int i = 0; i < MID_THREAD; ++i) { + threads[i] = std::thread([i, &stores]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDB(g_dbPaths[i]); + }); + } + for (int i = MID_THREAD; i < MAX_THREAD; ++i) { + threads[i] = std::thread([i, &stores]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDBSleep(g_dbPaths[i]); + }); + } + for (int i = 0; i < MAX_THREAD; ++i) { + if (threads[i].joinable()) { + threads[i].join(); + } + EXPECT_NE(stores[i], nullptr); + } + std::this_thread::sleep_for(std::chrono::milliseconds(MAX_SLEEP_TIME)); + for (int i = 0; i < MAX_THREAD; ++i) { + RdbHelper::DeleteRdbStore(g_dbPaths[i]); + } +} + +/** + * @tc.name: GetRdbStoreTest_004 + * @tc.desc: test Multithreading calls GetRdbStore with diff encrypt store + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_004, TestSize.Level1) +{ + std::string bundleName = "com.ohos.test"; + std::shared_ptr stores[MAX_THREAD]; + std::thread threads[MAX_THREAD]; + for (int i = 0; i < MID_THREAD; ++i) { + threads[i] = std::thread([i, &stores, &bundleName]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDB(g_dbPaths[i], true, bundleName); + }); + } + for (int i = MID_THREAD; i < MAX_THREAD; ++i) { + threads[i] = std::thread([i, &stores, &bundleName]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDBSleep(g_dbPaths[i], true, bundleName); + }); + } + for (int i = 0; i < MAX_THREAD; ++i) { + if (threads[i].joinable()) { + threads[i].join(); + } + EXPECT_NE(stores[i], nullptr); + } + std::this_thread::sleep_for(std::chrono::milliseconds(MAX_SLEEP_TIME)); + for (int i = 0; i < MAX_THREAD; ++i) { + RdbHelper::DeleteRdbStore(g_dbPaths[i]); + } +} + +/** + * @tc.name: GetRdbStoreTest_005 + * @tc.desc: test Multithreading calls GetRdbStore with diff encrypt store and store + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_005, TestSize.Level1) +{ + std::string bundleName = "com.ohos.test"; + std::shared_ptr stores[MAX_THREAD]; + std::thread threads[MAX_THREAD]; + for (int i = 0; i < MID_THREAD; ++i) { + threads[i] = std::thread([i, &stores, &bundleName]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDB(g_dbPaths[i]); + }); + } + for (int i = MID_THREAD; i < MAX_THREAD; ++i) { + threads[i] = std::thread([i, &stores, &bundleName]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDBSleep(g_dbPaths[i], true, bundleName); + }); + } + for (int i = 0; i < MAX_THREAD; ++i) { + if (threads[i].joinable()) { + threads[i].join(); + } + EXPECT_NE(stores[i], nullptr); + } + std::this_thread::sleep_for(std::chrono::milliseconds(MAX_SLEEP_TIME)); + for (int i = 0; i < MAX_THREAD; ++i) { + RdbHelper::DeleteRdbStore(g_dbPaths[i]); + } +} + +/** + * @tc.name: GetRdbStoreTest_006 + * @tc.desc: test Multithreading calls GetRdbStore with diff encrypt store with diff bundlename + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_006, TestSize.Level1) +{ + std::shared_ptr stores[MAX_THREAD]; + std::thread threads[MAX_THREAD]; + for (int i = 0; i < MAX_THREAD; ++i) { + threads[i] = std::thread([i, &stores]() { + stores[i] = RdbStoreStoreMultiTest::CreateRDB(g_dbPaths[i], true, g_dbBundlenames[i]); + }); + } + for (int i = 0; i < MAX_THREAD; ++i) { + if (threads[i].joinable()) { + threads[i].join(); + } + EXPECT_NE(stores[i], nullptr); + } + std::this_thread::sleep_for(std::chrono::milliseconds(MAX_SLEEP_TIME)); + for (int i = 0; i < MAX_THREAD; ++i) { + RdbHelper::DeleteRdbStore(g_dbPaths[i]); + } +} + +/** + * @tc.name: GetRdbStoreTest_007 + * @tc.desc: test Multithreading calls GetRdbStore with diff config + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_007, TestSize.Level1) +{ + std::string path = "/data/test/encrypt07store.db"; + int version = 1; + RdbStoreConfig configA(path); + configA.SetEncryptStatus(true); + configA.SetBundleName("com.ohos.test"); + RDBCallback helper; + int errCode = E_OK; + std::shared_ptr storeA = RdbHelper::GetRdbStore(configA, version, helper, errCode); + EXPECT_NE(storeA, nullptr); + RdbStoreStoreMultiTest::InsertData(storeA); + storeA = nullptr; + + RdbStoreConfig configB(path); + configB.SetEncryptStatus(false); + configB.SetBundleName("com.ohos.test"); + std::shared_ptr storeB = RdbHelper::GetRdbStore(configB, version, helper, errCode); + EXPECT_NE(storeB, nullptr); + RdbStoreStoreMultiTest::QueryData(storeB); + + RdbHelper::DeleteRdbStore(path); +} + +/** + * @tc.name: GetRdbStoreTest_008 + * @tc.desc: test Multithreading calls GetRdbStore with diff config + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_008, TestSize.Level1) +{ + std::string path = "/data/test/store.db"; + int version = 1; + RdbStoreConfig configA(path); + configA.SetJournalSize(JOURNAL_MAX_SIZE); + configA.SetBundleName("com.ohos.test"); + RDBCallback helper; + int errCode = E_OK; + std::shared_ptr storeA = RdbHelper::GetRdbStore(configA, version, helper, errCode); + EXPECT_NE(storeA, nullptr); + + RdbStoreConfig configB(path); + configB.SetBundleName("com.ohos.test"); + configB.SetJournalSize(JOURNAL_MIN_SIZE); + std::shared_ptr storeB = RdbHelper::GetRdbStore(configB, version, helper, errCode); + EXPECT_NE(storeB, nullptr); + EXPECT_NE(storeA, storeB); + + std::shared_ptr storeC = RdbHelper::GetRdbStore(configB, version, helper, errCode); + EXPECT_EQ(storeB, storeC); + RdbHelper::DeleteRdbStore(path); +} + +/** + * @tc.name: GetRdbStoreTest_009 + * @tc.desc: test Multithreading calls GetRdbStore with diff config and allowRebuild + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_009, TestSize.Level1) +{ + std::string path = "/data/test/encrypt09store.db"; + int version = 1; + RdbStoreConfig configA(path); + configA.SetEncryptStatus(false); + configA.SetAllowRebuild(true); + configA.SetBundleName("com.ohos.test"); + RDBCallback helper; + int errCode = E_OK; + std::shared_ptr storeA = RdbHelper::GetRdbStore(configA, version, helper, errCode); + ASSERT_NE(storeA, nullptr); + RdbStoreStoreMultiTest::InsertData(storeA); + storeA = nullptr; + + RdbStoreConfig configB(path); + configB.SetEncryptStatus(true); + configB.SetAllowRebuild(true); + configB.SetBundleName("com.ohos.test"); + std::shared_ptr storeB = RdbHelper::GetRdbStore(configB, version, helper, errCode); + ASSERT_NE(storeB, nullptr); + auto rebuilt = RebuiltType::NONE; + storeB->GetRebuilt(rebuilt); + EXPECT_EQ(rebuilt, RebuiltType::NONE); + RdbStoreStoreMultiTest::QueryData(storeB); + + RdbHelper::DeleteRdbStore(path); +} + +/** + * @tc.name: GetRdbStoreTest_010 + * @tc.desc: 1. Create encrypted and non-encrypted databases + * 2. Insert a piece of data into a non-encrypted database + * 3. Delete encrypted database + * 4. Rename the non-encrypted database as an encrypted database + * 5. Open with non-encrypted parameters to query data + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_010, TestSize.Level1) +{ + std::string path1 = "/data/test/encrypt10store.db"; + std::string path1Wal = "/data/test/encrypt10store.db-wal"; + std::string path1Shm = "/data/test/encrypt10store.db-shm"; + std::string path2 = "/data/test/10store.db"; + std::string path2Wal = "/data/test/10store.db-wal"; + std::string path2Shm = "/data/test/10store.db-shm"; + int version = 1; + RdbStoreConfig configA(path1); + configA.SetEncryptStatus(true); + configA.SetAllowRebuild(true); + configA.SetBundleName("com.ohos.test"); + RDBCallback helper; + int errCode = E_OK; + std::shared_ptr storeA = RdbHelper::GetRdbStore(configA, version, helper, errCode); + ASSERT_NE(storeA, nullptr); + storeA = nullptr; + + RdbStoreConfig configB(path2); + configB.SetEncryptStatus(false); + configB.SetAllowRebuild(true); + configB.SetBundleName("com.ohos.test"); + std::shared_ptr storeB = RdbHelper::GetRdbStore(configB, version, helper, errCode); + ASSERT_NE(storeB, nullptr); + RdbStoreStoreMultiTest::InsertData(storeB); + storeB = nullptr; + // Delete the encrypted database path1, rename the database path2 to path1. + SqliteUtils::DeleteFile(path1); + SqliteUtils::DeleteFile(path1Wal); + SqliteUtils::DeleteFile(path1Shm); + SqliteUtils::RenameFile(path2, path1); + SqliteUtils::RenameFile(path2Wal, path1Wal); + SqliteUtils::RenameFile(path2Shm, path1Shm); + // The current database of path1 is actually a non-encrypted database, + // and the data content is the original data content of path2. + configA.SetEncryptStatus(false); + storeA = RdbHelper::GetRdbStore(configA, version, helper, errCode); + ASSERT_NE(storeA, nullptr); + RdbStoreStoreMultiTest::QueryData(storeA); + storeA = nullptr; + + RdbHelper::DeleteRdbStore(path1); +} + + +/** + * @tc.name: GetRdbStoreTest_011 + * @tc.desc: 1. Create encrypted and non-encrypted databases + * 2. Insert a piece of data into a non-encrypted database + * 3. Delete encrypted database + * 4. Rename the non-encrypted database as an encrypted database + * 5. Open with encrypted parameters to query data + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreStoreMultiTest, GetRdbStoreTest_011, TestSize.Level1) +{ + std::string path1 = "/data/test/encrypt11store.db"; + std::string path1Wal = "/data/test/encrypt11store.db-wal"; + std::string path1Shm = "/data/test/encrypt11store.db-shm"; + std::string path2 = "/data/test/11store.db"; + std::string path2Wal = "/data/test/11store.db-wal"; + std::string path2Shm = "/data/test/11store.db-shm"; + int version = 1; + RdbStoreConfig configA(path1); + configA.SetEncryptStatus(true); + configA.SetAllowRebuild(true); + configA.SetBundleName("com.ohos.test"); + RDBCallback helper; + int errCode = E_OK; + std::shared_ptr storeA = RdbHelper::GetRdbStore(configA, version, helper, errCode); + ASSERT_NE(storeA, nullptr); + storeA = nullptr; + + RdbStoreConfig configB(path2); + configB.SetEncryptStatus(false); + configB.SetAllowRebuild(true); + configB.SetBundleName("com.ohos.test"); + std::shared_ptr storeB = RdbHelper::GetRdbStore(configB, version, helper, errCode); + ASSERT_NE(storeB, nullptr); + RdbStoreStoreMultiTest::InsertData(storeB); + storeB = nullptr; + // Delete the encrypted database path1, rename the database path2 to path1, and open path1. + SqliteUtils::DeleteFile(path1); + SqliteUtils::DeleteFile(path1Wal); + SqliteUtils::DeleteFile(path1Shm); + SqliteUtils::RenameFile(path2, path1); + SqliteUtils::RenameFile(path2Wal, path1Wal); + SqliteUtils::RenameFile(path2Shm, path1Shm); + // The current database of path1 is actually a non-encrypted database, and it cannot be opened + // using encryption parameters. The reconstruction was successful, but there is no data in the table. + storeA = RdbHelper::GetRdbStore(configA, version, helper, errCode); + ASSERT_NE(storeA, nullptr); + RebuiltType rebuiltType; + storeA->GetRebuilt(rebuiltType); + EXPECT_EQ(rebuiltType, RebuiltType::REBUILT); + std::shared_ptr resultSet = storeA->QuerySql("select * from test"); + int ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_SQLITE_ERROR); + storeA = nullptr; + + RdbHelper::DeleteRdbStore(path1); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_error_log_test/rdb_error_log_test.cpp b/relational_store/test/native/rdb/unittest/rdb_error_log_test/rdb_error_log_test.cpp new file mode 100644 index 00000000..48800db5 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_error_log_test/rdb_error_log_test.cpp @@ -0,0 +1,387 @@ +/* + * 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 "common.h" +#include "block_data.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "rdb_sql_log.h" +#include "rdb_store_manager.h" +#include "rdb_types.h" +#include "executor_pool.h" +#include "shared_block.h" +#include "sqlite_shared_result_set.h" +#include "step_result_set.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::DistributedRdb; +static constexpr int32_t MAX_THREAD = 5; +static constexpr int32_t MIN_THREAD = 0; +static std::string g_createTable = "CREATE TABLE IF NOT EXISTS test " +"(id INTEGER PRIMARY KEY AUTOINCREMENT, " +"name TEXT NOT NULL, age INTEGER, salary " +"REAL, blobType BLOB)"; +static std::string g_databaseName = "/data/test/subscribe.db"; + +class RdbStoreLogSubTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static std::shared_ptr CreateRDB(int version); + static std::shared_ptr store; +}; + +std::shared_ptr RdbStoreLogSubTest::store = nullptr; + +void RdbStoreLogSubTest::SetUpTestCase(void) +{ + RdbHelper::DeleteRdbStore(g_databaseName); + store = CreateRDB(1); +} + +void RdbStoreLogSubTest::TearDownTestCase(void) +{ + store = nullptr; + RdbHelper::DeleteRdbStore(g_databaseName); +} + +void RdbStoreLogSubTest::SetUp() +{ +} + +void RdbStoreLogSubTest::TearDown() +{ +} + +class Callback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +int Callback::OnCreate(RdbStore &store) +{ + return E_OK; +} + +int Callback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +std::shared_ptr RdbStoreLogSubTest::CreateRDB(int version) +{ + RdbStoreConfig config(g_databaseName); + config.SetBundleName("subscribe_test"); + config.SetArea(0); + config.SetCreateNecessary(true); + config.SetDistributedType(RDB_DEVICE_COLLABORATION); + config.SetSecurityLevel(OHOS::NativeRdb::SecurityLevel::S1); + Callback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, version, helper, errCode); + EXPECT_NE(store, nullptr); + return store; +} + +class OnErrorObserver : public SqlErrorObserver { +public: + void OnErrorLog(const ExceptionMessage &message) override; + ExceptionMessage GetLastMessage(); + void SetBlockData(std::shared_ptr> block); + +private: + std::shared_ptr> block_; + ExceptionMessage lastMessage; +}; + + +void OnErrorObserver::OnErrorLog(const ExceptionMessage &message) +{ + lastMessage = message; + if (block_) { + block_->SetValue(true); + } +} + +ExceptionMessage OnErrorObserver::GetLastMessage() +{ + return lastMessage; +} + +void OnErrorObserver::SetBlockData(std::shared_ptr> block) +{ + block_ = block; +} + + +/** + * @tc.name: RdbStoreSubscribeLog001 + * @tc.desc: test sqliteErrorOccurred observer when SQLITE_ERROR + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreLogSubTest, RdbStoreSubscribeLog001, TestSize.Level1) +{ + auto observer = std::make_shared(); + SqlLog::Subscribe(g_databaseName, observer); + std::shared_ptr> block = std::make_shared>(3, false); + observer->SetBlockData(block); + ValuesBucket values; + int64_t id; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + auto ret = store->Insert(id, "sqliteLog", values); + EXPECT_NE(ret, E_OK); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(observer->GetLastMessage().code, 1); + EXPECT_EQ(observer->GetLastMessage().message, "no such table: sqliteLog"); + EXPECT_EQ(observer->GetLastMessage().sql, "INSERT INTO sqliteLog(age,id,name) VALUES (?,?,?)"); +} + +/** + * @tc.name: RdbStoreSubscribeLog002 + * @tc.desc: test sqliteErrorOccurred observer when SQLITE_CONSTRAINT + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreLogSubTest, RdbStoreSubscribeLog002, TestSize.Level1) +{ + auto observer = std::make_shared(); + constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS errorlog_test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"; + auto ret = store->ExecuteSql(createTableTest); + EXPECT_EQ(ret, E_OK); + ValuesBucket values; + int64_t id; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + ret = store->Insert(id, "errorlog_test", values); + EXPECT_EQ(ret, E_OK); + std::shared_ptr> block = std::make_shared>(3, false); + SqlLog::Subscribe(g_databaseName, observer); + observer->SetBlockData(block); + ret = store->Insert(id, "errorlog_test", values); + EXPECT_NE(ret, E_OK); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(observer->GetLastMessage().code, 19); + EXPECT_EQ(observer->GetLastMessage().message, "UNIQUE constraint failed: errorlog_test.id"); + EXPECT_EQ(observer->GetLastMessage().sql, "INSERT INTO errorlog_test(age,id,name) VALUES (?,?,?)"); +} + +/** + * @tc.name: RdbStoreSubscribeLog003 + * @tc.desc: test sqliteErrorOccurred observer when SQLITE_BUSY + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreLogSubTest, RdbStoreSubscribeLog003, TestSize.Level1) +{ + auto observer = std::make_shared(); + std::string tableName = "OnErrorLogTable"; + auto res = store->Execute( + "CREATE TABLE " + tableName + " (id INTEGER PRIMARY KEY CHECK (id >= 3 OR id <= 1), name TEXT NOT NULL)"); + ASSERT_EQ(res.first, E_OK); + + auto [code, transaction] = store->CreateTransaction(Transaction::IMMEDIATE); + ASSERT_EQ(code, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + SqlLog::Subscribe(g_databaseName, observer); + std::shared_ptr> block = std::make_shared>(3, false); + observer->SetBlockData(block); + auto result = store->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); + ASSERT_EQ(result.first, E_SQLITE_BUSY); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(observer->GetLastMessage().code, 5); + EXPECT_EQ(observer->GetLastMessage().message, "database is locked"); + EXPECT_EQ( + observer->GetLastMessage().sql, "INSERT INTO OnErrorLogTable (id,name) VALUES (?,?),(?,?),(?,?),(?,?),(?,?)"); +} + +/** + * @tc.name: RdbStoreSubscribeLog004 + * @tc.desc: test sqliteErrorOccurred observer when SQLITE_LOCKED + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ + HWTEST_F(RdbStoreLogSubTest, RdbStoreSubscribeLog004, TestSize.Level1) + { + auto observer = std::make_shared(); + std::string dbPath = RDB_TEST_PATH + "errorlog.db"; + int errCode = E_OK; + RdbStoreConfig memoryConfig(dbPath); + Callback helper; + memoryConfig.SetStorageMode(StorageMode::MODE_MEMORY); + std::shared_ptr memoryStore = RdbHelper::GetRdbStore(memoryConfig, 1, helper, errCode); + auto res = memoryStore->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)"); + ASSERT_EQ(res.first, E_OK); + auto [ret1, transaction1] = memoryStore->CreateTransaction(Transaction::IMMEDIATE); + ASSERT_EQ(ret1, E_OK); + ASSERT_NE(transaction1, nullptr); + + auto [ret, transaction] = memoryStore->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + Transaction::Row row; + row.Put("id", i); + row.Put("name", "Jim_batchInsert"); + rows.Put(row); + } + SqlLog::Subscribe(dbPath, observer); + std::shared_ptr> block = std::make_shared>(3, false); + observer->SetBlockData(block); + auto result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_NONE); + ASSERT_EQ(result.first, E_SQLITE_LOCKED); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(observer->GetLastMessage().code, 6); + EXPECT_EQ(observer->GetLastMessage().message, "database table is locked"); + EXPECT_EQ(observer->GetLastMessage().sql, "INSERT INTO test1 (id,name) VALUES (?,?),(?,?),(?,?),(?,?),(?,?)"); +} + +/** + * @tc.name: RdbStoreSubscribeLog005 + * @tc.desc: test sqliteErrorOccurred observer when SQLITE_SCHEMA + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreLogSubTest, RdbStoreSubscribeLog005, TestSize.Level1) +{ + auto observer = std::make_shared(); + store->ExecuteSql(g_createTable); + std::shared_ptr executors; + std::shared_ptr> block1 = std::make_shared>(3, false); + executors = std::make_shared(MAX_THREAD, MIN_THREAD); + auto taskId1 = executors->Execute([storeCopy = store, block1]() { + constexpr const char *createTable = "CREATE TABLE test"; + constexpr const char *createTableColumn = " (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, " + "blobType BLOB)"; + int32_t errCode = E_ERROR; + for (uint32_t i = 0; i < 2000; i++) { + errCode = storeCopy->ExecuteSql(createTable + std::to_string(i) + createTableColumn); + if (errCode != E_OK) { + break; + } + } + block1->SetValue(errCode); + }); + std::shared_ptr> block = std::make_shared>(3, false); + SqlLog::Subscribe(g_databaseName, observer); + observer->SetBlockData(block); + std::shared_ptr> block2 = std::make_shared>(3, false); + auto taskId2 = executors->Execute([storeCopy = store, block2]() { + int32_t errCode = E_ERROR; + for (uint32_t i = 0; i < 2000; i++) { + auto resultSet = storeCopy->QueryByStep("SELECT * FROM test"); + int rowCount = -1; + errCode = resultSet->GetRowCount(rowCount); + resultSet->Close(); + if (errCode != E_OK && errCode != E_SQLITE_SCHEMA) { + break; + } + } + auto code = (errCode == E_OK || errCode == E_SQLITE_SCHEMA) ? E_OK : errCode; + block2->SetValue(code); + }); + EXPECT_EQ(block1->GetValue(), E_OK); + EXPECT_EQ(block2->GetValue(), E_OK); + EXPECT_NE(taskId1, taskId2); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(observer->GetLastMessage().code, 17); + EXPECT_EQ(observer->GetLastMessage().message, "database schema has changed"); + EXPECT_EQ(observer->GetLastMessage().sql, "SELECT * FROM test"); +} + +/** + * @tc.name: RdbStoreSubscribeLog006 + * @tc.desc: test sqliteErrorOccurred observer when SQLITE_FULL + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreLogSubTest, RdbStoreSubscribeLog006, TestSize.Level1) +{ + auto observer = std::make_shared(); + store->ExecuteSql(g_createTable); + auto [code, maxPageCount] = store->Execute("PRAGMA max_page_count;"); + auto recover = std::shared_ptr("recover", [defPageCount = maxPageCount, + storeCopy = store](const char *) { + storeCopy->Execute("PRAGMA max_page_count = " + static_cast(defPageCount) + ";"); + }); + std::tie(code, maxPageCount) = store->Execute("PRAGMA max_page_count = 256;"); + ValuesBucket row; + row.Put("name", std::string(1024 * 1024, 'e')); + std::shared_ptr> block = std::make_shared>(3, false); + SqlLog::Subscribe(g_databaseName, observer); + observer->SetBlockData(block); + auto result = store->Insert("test", row, ConflictResolution::ON_CONFLICT_NONE); + ASSERT_EQ(result.first, E_SQLITE_FULL); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(observer->GetLastMessage().code, 13); + EXPECT_EQ(observer->GetLastMessage().message, "database or disk is full"); + EXPECT_EQ(observer->GetLastMessage().sql, "INSERT INTO test(name) VALUES (?)"); +} + +/** + * @tc.name: RdbStoreSubscribeLog007 + * @tc.desc: test sqliteErrorOccurred observer when off observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreLogSubTest, RdbStoreSubscribeLog007, TestSize.Level1) +{ + auto observer = std::make_shared(); + SqlLog::Subscribe(g_databaseName, observer); + std::shared_ptr> block = std::make_shared>(3, false); + observer->SetBlockData(block); + SqlLog::Unsubscribe(g_databaseName, observer); + ValuesBucket values; + int64_t id; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + auto ret = store->Insert(id, "sqliteLog", values); + EXPECT_NE(ret, E_OK); + EXPECT_EQ(block->GetValue(), false); + EXPECT_EQ(observer->GetLastMessage().code, 0); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_error_log_test/rdb_perfStat_test.cpp b/relational_store/test/native/rdb/unittest/rdb_error_log_test/rdb_perfStat_test.cpp new file mode 100644 index 00000000..c2fa3db1 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_error_log_test/rdb_perfStat_test.cpp @@ -0,0 +1,436 @@ +/* + * 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. + */ + +#define LOG_TAG "RdbPerfStatTest" +#include + +#include +#include +#include + +#include "block_data.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "rdb_store_manager.h" +#include "rdb_types.h" +#include "logger.h" +#include "rdb_platform.h" +#include "rdb_perfStat.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::DistributedRdb; +using namespace OHOS::Rdb; + +class PerfStatObserver : public SqlObserver { +public: + virtual ~PerfStatObserver() + { + } + void OnStatistic(const SqlExecutionInfo &info); + void SetBlockData(std::shared_ptr> block); + SqlExecutionInfo perfInfo_; +private: + std::shared_ptr> block_; +}; + +class RdbPerfStatTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static const std::string databasePath; + static std::shared_ptr CreateRDB(int version); + static std::shared_ptr store; + static std::shared_ptr sqlObserver_; +}; + +const std::string RdbPerfStatTest::databasePath = "/data/test/perfStat.db"; +std::shared_ptr RdbPerfStatTest::store = nullptr; +std::shared_ptr RdbPerfStatTest::sqlObserver_ = nullptr; +void RdbPerfStatTest::SetUpTestCase(void) +{ + RdbHelper::DeleteRdbStore(databasePath); + store = CreateRDB(1); + if (sqlObserver_ == nullptr) { + sqlObserver_ = std::make_shared(); + } +} + +void RdbPerfStatTest::TearDownTestCase(void) +{ + store = nullptr; + RdbHelper::DeleteRdbStore(databasePath); +} + +void RdbPerfStatTest::SetUp() +{ +} + +void RdbPerfStatTest::TearDown() +{ +} + +class PerfStatCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +int PerfStatCallback::OnCreate(RdbStore &store) +{ + return E_OK; +} + +int PerfStatCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void PerfStatObserver::OnStatistic(const PerfStatObserver::SqlExecutionInfo &info) +{ + perfInfo_ = info; + if (block_) { + block_->SetValue(true); + } +} + +void PerfStatObserver::SetBlockData(std::shared_ptr> block) +{ + block_ = block; +} + +std::shared_ptr RdbPerfStatTest::CreateRDB(int version) +{ + RdbStoreConfig config(RdbPerfStatTest::databasePath); + config.SetBundleName("subscribe_test"); + config.SetArea(0); + config.SetCreateNecessary(true); + config.SetDistributedType(RDB_DEVICE_COLLABORATION); + config.SetSecurityLevel(OHOS::NativeRdb::SecurityLevel::S1); + PerfStatCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, version, helper, errCode); + EXPECT_NE(store, nullptr); + constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS perfStat_test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"; + store->ExecuteSql(createTableTest); + return store; +} + +/** + * @tc.name: RdbPerfStat001 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat001, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + ValuesBucket values; + int64_t id; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); // 18 is random age + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + status = store->Insert(id, "perfStat_test", values); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(id, 1); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat002 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat002, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + int id; + ValuesBucket values; + values.PutString("name", std::string("zhangsan_update2")); + values.PutInt("age", 20); // 20 is random age + AbsRdbPredicates predicates("perfStat_test"); + predicates.EqualTo("id", 1); + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + status = store->Update(id, values, predicates); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(id, 1); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat003 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat003, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + int id; + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + status = store->Delete(id, "perfStat_test", "id = ?", std::vector{ "1" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(id, 1); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat004 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat004, TestSize.Level1) +{ + int num = 3; + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + int64_t id; + std::vector values; + for (int i = 0; i < num; i++) { + ValuesBucket value; + value.PutInt("id", i); + value.PutString("name", std::string("zhangsan")); + value.PutInt("age", 18); // 18 is random age + values.push_back(value); + } + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + status = store->BatchInsert(id, "perfStat_test", values); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(id, num); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat005 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat005, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS perfStat_test2 " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"; + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + status = store->ExecuteSql(createTableTest); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_[0], createTableTest); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat006 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat006, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + constexpr const char *pargmaTest = "PRAGMA quick_check"; + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + store->Execute(pargmaTest); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_[0], pargmaTest); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat007 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat007, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + std::shared_ptr resultSet = store->QueryByStep("SELECT * FROM perfStat_test"); + ASSERT_NE(resultSet, nullptr); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat008 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat008, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM perfStat_test"); + ASSERT_NE(resultSet, nullptr); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat009 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat009, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + AbsRdbPredicates predicates("perfStat_test"); + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + std::shared_ptr resultSet = store->Query(predicates); + ASSERT_NE(resultSet, nullptr); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 1); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat010 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat010, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + EXPECT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBucket value; + value.PutString("name", std::string("zhangsan")); + value.PutInt("age", 18); // 18 is random age + + auto result = transaction->Insert("perfStat_test", value); + EXPECT_EQ(result.first, E_OK); + ret = transaction->Commit(); + EXPECT_EQ(ret, E_OK); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 3); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbPerfStat011 + * @tc.desc: test perfStat observer + * @tc.type: FUNC + */ +HWTEST_F(RdbPerfStatTest, RdbPerfStat011, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + ASSERT_NE(sqlObserver_, nullptr) << "observer is null"; + + auto status = PerfStat::Subscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); + + std::shared_ptr> block = std::make_shared>(3, false); + sqlObserver_->SetBlockData(block); + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + EXPECT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + int num = 3; + std::vector values; + for (int i = 0; i < num; i++) { + ValuesBucket value; + value.PutInt("id", i); + value.PutString("name", std::string("zhangsan")); + value.PutInt("age", 18); // 18 is random age + values.push_back(value); + } + auto result = transaction->BatchInsert("perfStat_test", values); + EXPECT_EQ(result.first, E_OK); + ret = transaction->Commit(); + EXPECT_EQ(ret, E_OK); + EXPECT_TRUE(block->GetValue()); + EXPECT_EQ(sqlObserver_->perfInfo_.sql_.size(), 3); + status = PerfStat::Unsubscribe(databasePath, sqlObserver_); + EXPECT_EQ(status, E_OK); +} + \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_execute_rd_test.cpp b/relational_store/test/native/rdb/unittest/rdb_execute_rd_test.cpp index 58b218b0..7c478c7b 100644 --- a/relational_store/test/native/rdb/unittest/rdb_execute_rd_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_execute_rd_test.cpp @@ -13,7 +13,6 @@ limitations under the License. */ #include -#include #include #include "common.h" @@ -45,6 +44,10 @@ const std::string RdbExecuteRdTest::databaseName = RDB_TEST_PATH + "execute_test const std::string RdbExecuteRdTest::restoreDatabaseName = RDB_TEST_PATH + "execute_test_restore.db"; const std::string RdbExecuteRdTest::backupDatabaseName = RDB_TEST_PATH + "execute_test_backup.db"; std::shared_ptr RdbExecuteRdTest::store = nullptr; +const bool IS_TESTING_PERFORMANCE = false; +const int BATCH_TOTAL_SIZE = IS_TESTING_PERFORMANCE ? 12000 : 120; +const int BATCH_SIZE = IS_TESTING_PERFORMANCE ? 100 : 10; +const int MAX_VARIABLE_NUM = 32766; class ExecuteTestOpenRdCallback : public RdbOpenCallback { public: @@ -80,8 +83,6 @@ void RdbExecuteRdTest::SetUp(void) RdbStoreConfig config(RdbExecuteRdTest::databaseName); config.SetIsVector(true); config.SetEncryptStatus(GetParam()); - int num = 300; - config.SetNcandidates(num); ExecuteTestOpenRdCallback helper; RdbExecuteRdTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); EXPECT_NE(RdbExecuteRdTest::store, nullptr); @@ -94,11 +95,6 @@ void RdbExecuteRdTest::TearDown(void) RdbHelper::DeleteRdbStore(RdbExecuteRdTest::databaseName); } -// 随机数生成器 -std::random_device g_rd; // 用于获取随机种子 -std::mt19937 g_gen(g_rd()); // 以随机设备作为种子的Mersenne Twister生成器 -std::uniform_real_distribution<> dis(-1.0, 1.0); // 定义一个均匀分布的实数范围 - /** @tc.name: RdbStore_Execute_001 @tc.desc: test RdbStore Execute in vector mode @@ -262,7 +258,7 @@ HWTEST_P(RdbExecuteRdTest, RdbStore_Execute_006, TestSize.Level1) std::string dbPath = "/data/test/execute_test1.db"; std::string configStr = "{\"pageSize\":8, \"crcCheckEnable\":0, \"redoFlushByTrx\":1, \"bufferPoolSize\":10240," - "\"sharedModeEnable\":1, \"metaInfoBak\":1, \"maxConnNum\":500 }"; + "\"sharedModeEnable\":1, \"metaInfoBak\":1, \"maxConnNum\":500, \"defaultIsolationLevel\":2 }"; GRD_DB *db2 = nullptr; GRD_DB *db4 = nullptr; @@ -935,43 +931,65 @@ HWTEST_P(RdbExecuteRdTest, RdbStore_Execute_018, TestSize.Level1) } /** - * @tc.name: RdbStore_Execute_019 - * @tc.desc: test RdbStore Execute in vector mode - * @tc.type: FUNC - */ +@tc.name: RdbStore_Execute_019 +@tc.desc: test RdbStore Execute in vector mode, empty string bind case. +@tc.type: FUNC +*/ HWTEST_P(RdbExecuteRdTest, RdbStore_Execute_019, TestSize.Level1) { + std::string sqlCreateTable + = "CREATE TABLE IF NOT EXISTS testEmptyString (id INTEGER PRIMARY KEY, name text, repr floatvector(8));"; + std::string sqlInsert = "INSERT INTO testEmptyString VALUES(?, ?, ?);"; + std::string sqlQuery = "SELECT id FROM testEmptyString"; std::shared_ptr &store = RdbExecuteRdTest::store; - const char *sqlCreateTable = "CREATE TABLE vecTable(inode int primary key, embedding floatvector(4));"; - auto res = store->Execute(sqlCreateTable); - EXPECT_EQ(E_OK, res.first); + std::vector floatVector = { 1.2, 0.3, 3.2, 1.6, 2.5, 3.1, 0.8, 0.4 }; + std::vector bindArgs = std::vector{ ValueObject(1), ValueObject(""), ValueObject(floatVector)}; - const char *sqlCreateIndex = "CREATE INDEX diskann_cos_idx ON vecTable USING GSDISKANN(embedding COSINE);"; - res = store->Execute(sqlCreateIndex); - EXPECT_EQ(E_OK, res.first); + EXPECT_EQ(store->Execute(sqlCreateTable).first, E_OK); + EXPECT_EQ(store->Execute(sqlInsert, bindArgs).first, E_OK); - std::string sqlInsert = "INSERT INTO vecTable VALUES(1, '[1,2,-3,4]'), (2, '[2,2,-3,4]'), (3, '[3,2,3,4]'), (4, " - "'[4,2,3,4]'), (5, '[5,2,-3,4]')"; - for (int i = 6; i <= 1000; i++) { - std::string tmpStr = ", (" + std::to_string(i) + ", '[" + std::to_string(dis(g_gen)) + "," + - std::to_string(dis(g_gen)) + "," + std::to_string(dis(g_gen)) + "," + - std::to_string(dis(g_gen)) + "]')"; - sqlInsert.append(tmpStr); - } - sqlInsert.append(";"); - res = store->Execute(sqlInsert); - EXPECT_EQ(E_OK, res.first); + std::shared_ptr resultSet = store->QueryByStep(sqlQuery); + ASSERT_NE(resultSet, nullptr); + int32_t rowCount = 0; + EXPECT_EQ(resultSet->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1); +} - const char *sqlSelect = "SELECT inode, embedding, embedding<=>'[1,1,1,1]' AS score FROM vecTable ORDER BY " - "embedding<=>'[1,1,1,1]' LIMIT 501;"; - std::shared_ptr resultSet = store->QueryByStep(sqlSelect, std::vector()); - EXPECT_NE(resultSet, nullptr); - int count = 0; - resultSet->GetRowCount(count); - EXPECT_EQ(count, 299); - const char *sqlDelete = "DELETE FROM vecTable"; - res = store->Execute(sqlDelete); - EXPECT_EQ(E_OK, res.first); +/** + * @tc.name: RdbStore_Execute_020 + * @tc.desc: Vector database transaction testing. If the SQL execution fails, the transaction is not closed. + * @tc.type: FUNC +*/ +HWTEST_P(RdbExecuteRdTest, RdbStore_Execute_020, TestSize.Level0) +{ + std::shared_ptr &store = RdbExecuteRdTest::store; + std::string sqlCreateTable = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, repr floatvector(8));"; + std::string sqlInsert1 = "INSERT INTO test VALUES(1, '[1.2, 0.3, 3.2, 1.6, 2.5, 3.1, 0.8, 0.4]');"; + std::string sqlInsert2 = "INSERT INTO test VALUES(2, '[1.2, 0.3, 3.2, 1.6, 2.5, 3.1, 0.8, 0.4]');"; + std::string sqlQuery = "SELECT id FROM test order by repr <-> '[1.1, 0.3, 2.2, 6.6, 1.5, 3.1, 0.6, 0.2]' limit 3;"; + + std::pair res = {}; + res = store->Execute(sqlCreateTable, {}, 0); + EXPECT_EQ(res.first, E_OK); + + auto [ret1, transId1] = store->BeginTrans(); + EXPECT_EQ(ret1, E_OK); + EXPECT_GE(transId1, 0); + + res = store->Execute(sqlInsert1, {}, transId1); + EXPECT_EQ(res.first, E_OK); + + auto [ret2, transId2] = store->BeginTrans(); + EXPECT_EQ(ret2, E_OK); + EXPECT_GE(transId2, 0); + + res = store->Execute(sqlInsert2, {}, transId2); + EXPECT_EQ(res.first, E_DATABASE_BUSY); + + EXPECT_EQ(store->Commit(transId2), E_OK); + EXPECT_EQ(store->Commit(transId1), E_OK); + res = store->Execute("DROP TABLE test;", {}, 0); + EXPECT_EQ(res.first, E_OK); } /* * @@ -1050,4 +1068,349 @@ HWTEST_P(RdbExecuteRdTest, Rdb_BackupRestoreTest_001, TestSize.Level2) HWTEST_P(RdbExecuteRdTest, Rdb_IsUsingArkDataTest_001, TestSize.Level2) { EXPECT_EQ(OHOS::NativeRdb::RdbHelper::IsSupportArkDataDb(), true); -} \ No newline at end of file +} + +/** + * @tc.name: RdbStore_BatchInsert_001 + * @tc.desc: test RdbStore BatchInsert in vector mode + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, RdbStore_BatchInsert_001, TestSize.Level1) +{ + std::shared_ptr &store = RdbExecuteRdTest::store; + std::string sqlCreateTable = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, repr floatvector(8));"; + std::string sqlQuery = "SELECT * FROM test order by repr <-> '[1.1, 0.3, 2.2, 6.6, 1.5, 3.1, 0.6, 0.2]' limit 3;"; + + std::pair res = {}; + std::pair resBatch = {}; + res = store->Execute(sqlCreateTable.c_str(), {}, 0); + EXPECT_EQ(res.first, E_OK); + std::vector vec = {1.2, 0.3, 3.2, 1.6, 2.5, 3.1, 0.8, 0.4}; + + int id = 0; + std::cout << "Start BatchInsert" << std::endl; + auto start = std::chrono::high_resolution_clock::now(); + + for (int32_t batch = 0; batch < BATCH_TOTAL_SIZE / BATCH_SIZE; batch++) { + ValuesBuckets rows; + for (int32_t i = 0; i < BATCH_SIZE; i++) { + ValuesBucket row; + row.PutInt("id", id++); + row.Put("repr", vec); + rows.Put(row); + } + resBatch = store->BatchInsert("test", rows); + EXPECT_EQ(resBatch.first, E_OK); + EXPECT_EQ(resBatch.second, BATCH_SIZE); + } + + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration duration = end - start; + std::cout << "Insert Cost Time: " << duration.count() << " seconds" << std::endl; + std::cout << "Ops: " << BATCH_TOTAL_SIZE / (duration.count() * 1000) << " Kops/s" << std::endl; + + std::shared_ptr resultSet = store->QueryByStep(sqlQuery.c_str(), std::vector()); + + int32_t resCnt = 0; + int32_t resId = -1; + while (resultSet->GoToNextRow() == E_OK) { + ValueObject::FloatVector floatVector = {}; + resultSet->GetInt(0, resId); // 0 is the index of primary INTEGER column in select projection + resultSet->GetFloat32Array(1, floatVector); // 1 is the index of vector column in select projection + EXPECT_EQ(resCnt, resId); + EXPECT_EQ(vec.size(), floatVector.size()); + for (size_t i = 0; i < floatVector.size(); i++) { + EXPECT_FLOAT_EQ(vec[i], floatVector[i]); + } + resCnt++; + } + EXPECT_EQ(3, resCnt); // Expect 3 result due to limit 3 + + res = store->Execute("DROP TABLE test;", {}, 0); + EXPECT_EQ(res.first, E_OK); +} + +/** + * @tc.name: RdbStore_BatchInsert_002 + * @tc.desc: test RdbStore BatchInsert performance in vector mode + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, RdbStore_BatchInsert_002, TestSize.Level1) +{ + std::string testStr2k = R"( +{"$type":"root", "width":"1260.000000", "height":"2720.000000", "$resolution":"3.250000", "pageUrl":"pages/AppIndex", +"$attrs":{"enabled":"1", "focusable":"1"}, "$children":[{"$type":"__Common__", "$rect":"[0.00, 0.00], +[1260.00, 2720.00]", "$attrs":{}, "$children":[{"$type":"Navigation", "$rect":"[0.00, 0.00], [1260.00, 2720.00]", +"$attrs":{"id":"mixnavigator", "enabled":"1", "focusable":"1"}, "$children":[{"$type":"NavigationContent", "$rect":" +[0.00, 0.00], [1260.00, 2720.00]", "$attrs":{}, "$children":[{"$type":"NavDestination", "$rect":"[0.00, 0.00], +[1260.00, 2720.00]", "$attrs":{"enabled":"1", "focusable":"1"}, "$children":[{"$type":"NavDestinationContent", +"$rect":"[0.00, 0.00], [1260.00, 2720.00]", "$attrs":{"enabled":"1", "focusable":"1"}, "$children":[{"$type":"Stack", +"$rect":"[0.00, 0.00], [1260.00, 2720.00]", "$attrs":{"enabled":"1", "focusable":"1"}, "$children":[{"$type": +"__Common__", "$rect":"[0.00, 0.00], [1260.00, 2629.00]", "$attrs":{}, "$children":[{"$type":"Stack", "$rect":" +[0.00, 0.00], [1260.00, 2629.00]", "$attrs":{"enabled":"1", "focusable":"1"}, "$children":[{"$type":"Stack", "$rect":" +[0.00, 0.00], [1260.00, 2629.00]", "$attrs":{"id":"0", "enabled":"1", "focusable":"1"}, "$children":[{"$type":"Column", +"$rect":"[0.00, 0.00], [1260.00, 2629.00]", "$attrs":{"id":"1", "enabled":"1", "focusable":"1"}, "$children":[{"$type": +"Tabs", "$rect":"[0.00, 0.00], [1260.00, 2629.00]", "$attrs":{"enabled":"1", "focusable":"1"}, "$children":[{"$type": +"Swiper", "$rect":"[0.00, 0.00], [1260.00, 2460.00]", "$attrs":{"enabled":"1", "focusable":"1"}, "$children":[{"$type": +"TabContent", "$rect":"[0.00, 0.00], [1260.00, 2460.00]", "$attrs":{}, "$children":[{"$type":"Column", "$rect":" +[0.00, 0.00], [1260.00, 2460.00]", "$attrs":{"id":"14", "enabled":"1", "focusable":"1"}, "$children":[{"$type": +"Column", "$rect":"[0.00, 0.00], [1260.00, 2460.00]", "$attrs":{""}, "$children":[{"$attrs":{"id":"540", "enabled":"1", +"focusable":"1"}, "$children":[{"$type":"GridCol", "$children":[{"$type":"Column", "$rect":"[0.00, 2460.00], +[315.00, 2629.00]", "$attrs":{"enabled":"1", "focusable":"0"}, "$children":[{")"; + + std::shared_ptr &store = RdbExecuteRdTest::store; + std::string sqlCreateTable = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, name TEXT);"; + + std::pair res = {}; + std::pair resBatch = {}; + res = store->Execute(sqlCreateTable.c_str(), {}, 0); + EXPECT_EQ(res.first, E_OK); + + int id = 0; + std::cout << "Start BatchInsert" << std::endl; + auto start = std::chrono::high_resolution_clock::now(); + + for (int32_t batch = 0; batch < BATCH_TOTAL_SIZE / BATCH_SIZE; batch++) { + ValuesBuckets rows; + for (int32_t i = 0; i < BATCH_SIZE; i++) { + ValuesBucket row; + row.PutInt("id", id++); + row.PutString("name", testStr2k); + rows.Put(row); + } + resBatch = store->BatchInsert("test", rows); + EXPECT_EQ(resBatch.first, E_OK); + EXPECT_EQ(resBatch.second, BATCH_SIZE); + } + + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration duration = end - start; + std::cout << "Insert Cost Time: " << duration.count() << " seconds" << std::endl; + std::cout << "Ops: " << BATCH_TOTAL_SIZE / (duration.count() * 1000) << " Kops/s" << std::endl; + + res = store->Execute("DROP TABLE test;", {}, 0); + EXPECT_EQ(res.first, E_OK); +} + +/** + * @tc.name: RdbStore_BatchInsert_003 + * @tc.desc: test RdbStore BatchInsert performance in vector mode + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, RdbStore_BatchInsert_003, TestSize.Level1) +{ + std::string testStr2k = R"({"$type":"root"})"; + + std::shared_ptr &store = RdbExecuteRdTest::store; + std::string sqlCreateTable = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, name TEXT);"; + + std::pair res = {}; + std::pair resBatch = {}; + res = store->Execute(sqlCreateTable.c_str(), {}, 0); + EXPECT_EQ(res.first, E_OK); + + int id = 0; + std::cout << "Start BatchInsert" << std::endl; + auto start = std::chrono::high_resolution_clock::now(); + int maxVariableNum = MAX_VARIABLE_NUM / 2; + + for (int32_t batch = 0; batch < 1; batch++) { + ValuesBuckets rows; + for (int32_t i = 0; i < maxVariableNum; i++) { + ValuesBucket row; + row.PutInt("id", id++); + row.PutString("name", testStr2k); + rows.Put(row); + } + resBatch = store->BatchInsert("test", rows); + EXPECT_EQ(resBatch.first, E_OK); + EXPECT_EQ(resBatch.second, maxVariableNum); + } + + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration duration = end - start; + std::cout << "Insert Cost Time: " << duration.count() << " seconds" << std::endl; + std::cout << "Ops: " << maxVariableNum / (duration.count() * 1000) << " Kops/s" << std::endl; + + res = store->Execute("DROP TABLE test;", {}, 0); + EXPECT_EQ(res.first, E_OK); +} + +constexpr uint16_t CLUSTER_INDEX_DIM = 256; + +int32_t ClusterAlgoByEvenNumber(ClstAlgoParaT *para) +{ + int *result = para->clusterResult; + const int specialId = 985; + for (uint32_t i = 0; i < para->newFeaturesNum; i++) { + result[i] = specialId; + } + std::cout << "ClusterAlgoByEvenNumber exec!" << std::endl; + return 0; +} + +/** + * @tc.name: RdbStore_RegisterAlgo_001 + * @tc.desc: test RdbStore RegisterAlgo in vector mode + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, RdbStore_RegisterAlgo_001, TestSize.Level1) +{ + std::shared_ptr &store = RdbExecuteRdTest::store; + std::string algoName = "clst_algo_v0"; + int ret = store->RegisterAlgo(algoName, nullptr); + EXPECT_EQ(ret, E_NO_MORE_ROWS); + ret = store->RegisterAlgo(algoName, ClusterAlgoByEvenNumber); + EXPECT_EQ(ret, E_OK); + + std::string sqlCreateTable = + "CREATE TABLE test(id int primary key, repr floatvector(" + std::to_string(CLUSTER_INDEX_DIM) + "));"; + std::string sqlCreateIndex = + "CREATE INDEX ivfcluster_l2_idx ON test USING IVFCLUSTER(repr L2) with (CLUSTER_ALGO='clst_algo_v0');"; + std::string sqlSelect = "SELECT id, repr, CLUSTER_ID(repr) from test;"; + + std::pair res = {}; + res = store->Execute(sqlCreateTable.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + + res = store->Execute(sqlCreateIndex.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + + for (uint16_t i = 0; i < EXPEC_INSERT_CNT_FOR; i++) { + std::string sqlInsert = "INSERT INTO test VALUES(1000000" + std::to_string(i) + ", '" + + GetRandVector(MAX_INT_PART, CLUSTER_INDEX_DIM) + "');"; + res = store->Execute(sqlInsert.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + } + + ret = store->RegisterAlgo(algoName, nullptr); + EXPECT_EQ(ret, E_OK); + + res = store->Execute("DROP TABLE test;", {}, 0); + EXPECT_EQ(res.first, E_OK); +} + +/** + * @tc.name: RdbStore_RegisterAlgo_002 + * @tc.desc: test RdbStore RegisterAlgo in vector mode + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, RdbStore_RegisterAlgo_002, TestSize.Level1) +{ + std::shared_ptr &store = RdbExecuteRdTest::store; + std::string algoName = "clst_algo_v0"; + int ret = store->RegisterAlgo(algoName, ClusterAlgoByEvenNumber); + EXPECT_EQ(ret, E_OK); + + std::string sqlCreateTable = + "CREATE TABLE test(id int primary key, repr floatvector(" + std::to_string(CLUSTER_INDEX_DIM) + "));"; + std::string sqlCreateIndex = + "CREATE INDEX ivfcluster_l2_idx ON test USING IVFCLUSTER(repr L2) with (CLUSTER_ALGO='clst_algo_v0');"; + std::string sqlSelect = "SELECT id, repr, CLUSTER_ID(repr) from test;"; + + std::pair res = {}; + res = store->Execute(sqlCreateTable.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + + res = store->Execute(sqlCreateIndex.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + + for (uint16_t i = 0; i < EXPEC_INSERT_CNT_FOR; i++) { + std::string sqlInsert = "INSERT INTO test VALUES(1000000" + std::to_string(i) + ", '" + + GetRandVector(MAX_INT_PART, CLUSTER_INDEX_DIM) + "');"; + res = store->Execute(sqlInsert.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + } + + std::string sqlRunCluster = "PRAGMA CLUSTER_RUN test.ivfcluster_l2_idx;"; + res = store->Execute(sqlRunCluster.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + + std::shared_ptr resultSet = store->QueryByStep(sqlSelect.c_str(), std::vector()); + EXPECT_NE(resultSet, nullptr); + + int32_t resCnt = 0; + while (resultSet->GoToNextRow() == E_OK) { + resCnt++; + } + EXPECT_EQ(EXPEC_INSERT_CNT_FOR, resCnt); + + res = store->Execute("DROP TABLE test;", {}, 0); + EXPECT_EQ(res.first, E_OK); +} + +/** + * @tc.name: RdbStore_RegisterAlgo_003 + * @tc.desc: test sqlite don't support RegisterAlgo + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, RdbStore_RegisterAlgo_003, TestSize.Level1) +{ + RdbExecuteRdTest::store = nullptr; + RdbHelper::DeleteRdbStore(RdbExecuteRdTest::databaseName); + + int errCode = E_OK; + RdbHelper::DeleteRdbStore(RdbExecuteRdTest::databaseName); + RdbStoreConfig config(RdbExecuteRdTest::databaseName); + config.SetIsVector(false); + config.SetEncryptStatus(GetParam()); + ExecuteTestOpenRdCallback helper; + RdbExecuteRdTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(RdbExecuteRdTest::store, nullptr); + EXPECT_EQ(errCode, E_OK); + + std::shared_ptr &store = RdbExecuteRdTest::store; + + std::string sqlCreateTable = + "CREATE TABLE test(id int primary key, repr int);"; + + std::pair res = {}; + res = store->Execute(sqlCreateTable.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + + std::string algoName = "clst_algo_v0"; + int ret = store->RegisterAlgo(algoName, ClusterAlgoByEvenNumber); + EXPECT_EQ(ret, E_NOT_SUPPORT); + + res = store->Execute("DROP TABLE test;", {}, 0); + EXPECT_EQ(res.first, E_OK); +} + +/** + * @tc.name: RdbStore_RegisterAlgo_004 + * @tc.desc: test don't support RegisterAlgo + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, RdbStore_RegisterAlgo_004, TestSize.Level1) +{ + RdbExecuteRdTest::store = nullptr; + RdbHelper::DeleteRdbStore(RdbExecuteRdTest::databaseName); + + int errCode = E_OK; + RdbStoreConfig config(RdbExecuteRdTest::databaseName); + config.SetIsVector(true); + config.SetReadOnly(true); + config.SetEncryptStatus(GetParam()); + ExecuteTestOpenRdCallback helper; + RdbExecuteRdTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(RdbExecuteRdTest::store, nullptr); + EXPECT_EQ(errCode, E_OK); + + std::string algoName = "clst_algo_v0"; + int ret = RdbExecuteRdTest::store->RegisterAlgo(algoName, ClusterAlgoByEvenNumber); + EXPECT_EQ(ret, E_NOT_SUPPORT); +} + +/** + * @tc.name: RdbStore_RegisterAlgo_005 + * @tc.desc: test RegisterAlgo after deleteRdbStore + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, RdbStore_RegisterAlgo_005, TestSize.Level1) +{ + RdbHelper::DeleteRdbStore(RdbExecuteRdTest::databaseName); + std::shared_ptr &store = RdbExecuteRdTest::store; + std::string algoName = "clst_algo_v0"; + int ret = store->RegisterAlgo(algoName, ClusterAlgoByEvenNumber); + EXPECT_EQ(ret, E_ALREADY_CLOSED); +} diff --git a/relational_store/test/native/rdb/unittest/rdb_execute_test.cpp b/relational_store/test/native/rdb/unittest/rdb_execute_test.cpp index bf769385..3ec06694 100644 --- a/relational_store/test/native/rdb/unittest/rdb_execute_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_execute_test.cpp @@ -21,6 +21,7 @@ #include "rdb_errno.h" #include "rdb_helper.h" #include "rdb_open_callback.h" +#include "value_object.h" using namespace testing::ext; using namespace OHOS::NativeRdb; @@ -95,12 +96,14 @@ void RdbExecuteTest::TearDownTestCase(void) void RdbExecuteTest::SetUp(void) { store_ = *GetParam(); + ASSERT_NE(store_, nullptr); store_->ExecuteSql(CREATE_TABLE_TEST); } void RdbExecuteTest::TearDown(void) { store_ = *GetParam(); + ASSERT_NE(store_, nullptr); store_->ExecuteSql("DROP TABLE test"); } @@ -111,8 +114,6 @@ void RdbExecuteTest::TearDown(void) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_001, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; @@ -121,7 +122,7 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_001, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); + int ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -131,7 +132,7 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_001, TestSize.Level1) values.PutInt("age", 19); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->Insert(id, "test", values); + ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -141,27 +142,27 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_001, TestSize.Level1) values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->Insert(id, "test", values); + ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); int64_t count; - ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); + ret = store_->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(count, 3); - ret = store->ExecuteSql("DELETE FROM test WHERE age = ? OR age = ?", + ret = store_->ExecuteSql("DELETE FROM test WHERE age = ? OR age = ?", std::vector{ ValueObject(std::string("18")), ValueObject(std ::string("20")) }); EXPECT_EQ(ret, E_OK); - ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test where age = 19"); + ret = store_->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test where age = 19"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(count, 1); - ret = store->ExecuteSql("DELETE FROM test WHERE age = 19"); + ret = store_->ExecuteSql("DELETE FROM test WHERE age = 19"); EXPECT_EQ(ret, E_OK); - ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); + ret = store_->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(count, 0); } @@ -173,48 +174,46 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_001, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_002, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[2])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[2])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); int64_t count; - ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test", std::vector()); + ret = store_->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test", std::vector()); EXPECT_EQ(ret, E_OK); EXPECT_EQ(count, 3); - ret = store->ExecuteSql("DELETE FROM test WHERE age = ? OR age = ?", + ret = store_->ExecuteSql("DELETE FROM test WHERE age = ? OR age = ?", std::vector{ ValueObject(std::string("18")), ValueObject(std ::string("20")) }); EXPECT_EQ(ret, E_OK); - ret = store->ExecuteAndGetLong( + ret = store_->ExecuteAndGetLong( count, "SELECT COUNT(*) FROM test where age = ?", std::vector{ ValueObject(std::string("19")) }); EXPECT_EQ(ret, E_OK); EXPECT_EQ(count, 1); - ret = store->ExecuteSql("DELETE FROM test WHERE age = 19"); + ret = store_->ExecuteSql("DELETE FROM test WHERE age = 19"); EXPECT_EQ(ret, E_OK); - ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test", std::vector()); + ret = store_->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test", std::vector()); EXPECT_EQ(ret, E_OK); EXPECT_EQ(count, 0); - ret = store->ExecuteSql("DROP TABLE IF EXISTS test"); + ret = store_->ExecuteSql("DROP TABLE IF EXISTS test"); EXPECT_EQ(ret, E_OK); - ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); + ret = store_->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); EXPECT_EQ(ret, E_SQLITE_ERROR); } @@ -225,20 +224,18 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_002, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_003, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int64_t pageSize; - int ret = store->ExecuteAndGetLong(pageSize, "PRAGMA page_size"); + int ret = store_->ExecuteAndGetLong(pageSize, "PRAGMA page_size"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(pageSize, 4096); int64_t journalSize; - ret = store->ExecuteAndGetLong(journalSize, "PRAGMA journal_size_limit"); + ret = store_->ExecuteAndGetLong(journalSize, "PRAGMA journal_size_limit"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(journalSize, 1048576); std::string journalMode; - ret = store->ExecuteAndGetString(journalMode, "PRAGMA journal_mode"); + ret = store_->ExecuteAndGetString(journalMode, "PRAGMA journal_mode"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(journalMode, GetParam()->mode); } @@ -253,7 +250,7 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_004, TestSize.Level4) std::shared_ptr store = *GetParam(); std::string outValue; - int ret = store->ExecuteAndGetString(outValue, "BEGIN;"); + int ret = store_->ExecuteAndGetString(outValue, "BEGIN;"); EXPECT_NE(E_OK, ret); } @@ -265,9 +262,8 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_004, TestSize.Level4) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_005, TestSize.Level4) { - std::shared_ptr store = *GetParam(); int64_t outValue; - int ret = store->ExecuteForLastInsertedRowId(outValue, "", {}); + int ret = store_->ExecuteForLastInsertedRowId(outValue, "", {}); EXPECT_NE(E_OK, ret); } @@ -278,9 +274,8 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_005, TestSize.Level4) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_006, TestSize.Level4) { - std::shared_ptr store = *GetParam(); int64_t outValue; - int ret = store->ExecuteForChangedRowCount(outValue, "", {}); + int ret = store_->ExecuteForChangedRowCount(outValue, "", {}); EXPECT_NE(E_OK, ret); } @@ -291,9 +286,7 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_006, TestSize.Level4) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_007, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - - auto [ret, outValue] = store->Execute("PRAGMA integrity_check"); + auto [ret, outValue] = store_->Execute("PRAGMA integrity_check"); EXPECT_EQ(E_OK, ret); EXPECT_EQ(ValueObjectType::TYPE_STRING, outValue.GetType()); @@ -309,9 +302,7 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_007, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_008, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - - auto [ret, outValue] = store->Execute("PRAGMA quick_check"); + auto [ret, outValue] = store_->Execute("PRAGMA quick_check"); EXPECT_EQ(E_OK, ret); EXPECT_EQ(ValueObjectType::TYPE_STRING, outValue.GetType()); @@ -327,11 +318,9 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_008, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_009, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - // set user_version as 5 - store->SetVersion(5); - auto [ret, outValue] = store->Execute("PRAGMA user_version"); + store_->SetVersion(5); + auto [ret, outValue] = store_->Execute("PRAGMA user_version"); EXPECT_EQ(E_OK, ret); EXPECT_EQ(ValueObjectType::TYPE_INT, outValue.GetType()); @@ -340,7 +329,7 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_009, TestSize.Level1) EXPECT_EQ(5, outputResult); // set user_version as 0 - store->SetVersion(0); + store_->SetVersion(0); } /** @@ -350,10 +339,11 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_009, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0010, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - - auto [ret, outValue] = store->Execute("SELECT * FROM test"); + auto [ret, outValue] = store_->Execute("SELECT * FROM test"); EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, ret); + + auto [code, result] = store_->ExecuteExt("SELECT * FROM test"); + EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, code); } /** @@ -363,11 +353,9 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0010, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0011, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - std::vector args = { ValueObject(std::string("tt")), ValueObject(int(28)), ValueObject(double(50000.0)) }; - auto [ret, outValue] = store->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?);", args); + auto [ret, outValue] = store_->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?);", args); EXPECT_EQ(E_OK, ret); EXPECT_EQ(ValueObjectType::TYPE_INT, outValue.GetType()); @@ -384,12 +372,10 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0011, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0012, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - std::vector args = { ValueObject(std::string("tt")), ValueObject(int(28)), ValueObject(double(50000.0)), ValueObject(std::string("ttt")), ValueObject(int(58)), ValueObject(double(500080.0)) }; - auto [ret, outValue] = store->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?)", args); + auto [ret, outValue] = store_->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?)", args); EXPECT_EQ(E_OK, ret); EXPECT_EQ(ValueObjectType::TYPE_INT, outValue.GetType()); @@ -407,12 +393,10 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0012, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0013, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - std::vector args = { ValueObject(std::string("tt")), ValueObject(int(28)), ValueObject(double(50000.0)), ValueObject(std::string("ttt")), ValueObject(int(58)), ValueObject(double(500080.0)) }; - auto [ret1, outValue1] = store->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?)", args); + auto [ret1, outValue1] = store_->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?)", args); EXPECT_EQ(E_OK, ret1); EXPECT_EQ(ValueObjectType::TYPE_INT, outValue1.GetType()); @@ -421,7 +405,7 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0013, TestSize.Level1) // 2 represent that the last data is inserted in the second row EXPECT_EQ(2, outputResult); - auto [ret2, outValue2] = store->Execute("UPDATE test SET name='dd' WHERE id = 2"); + auto [ret2, outValue2] = store_->Execute("UPDATE test SET name='dd' WHERE id = 2"); EXPECT_EQ(E_OK, ret2); EXPECT_EQ(ValueObjectType::TYPE_INT, outValue2.GetType()); @@ -437,12 +421,10 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0013, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0014, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - std::vector args = { ValueObject(std::string("tt")), ValueObject(int(28)), ValueObject(double(50000.0)), ValueObject(std::string("ttt")), ValueObject(int(82)), ValueObject(double(500080.0)) }; - auto [ret1, outValue1] = store->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?)", args); + auto [ret1, outValue1] = store_->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?)", args); EXPECT_EQ(E_OK, ret1); EXPECT_EQ(ValueObjectType::TYPE_INT, outValue1.GetType()); @@ -451,7 +433,7 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0014, TestSize.Level1) // 2 represent that the last data is inserted in the second row EXPECT_EQ(2, outputResult); - auto [ret2, outValue2] = store->Execute("DELETE FROM test"); + auto [ret2, outValue2] = store_->Execute("DELETE FROM test"); EXPECT_EQ(E_OK, ret2); EXPECT_EQ(ValueObjectType::TYPE_INT, outValue2.GetType()); @@ -467,22 +449,23 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0014, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0015, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - - auto [ret1, outValue1] = store->Execute("ATTACH DATABASE 'execute_attach_test.db' AS 'attach.db'"); + auto [ret1, outValue1] = store_->Execute("ATTACH DATABASE 'execute_attach_test.db' AS 'attach.db'"); EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, ret1); - auto [ret2, outValue2] = store->Execute("DETACH DATABASE 'attach.db'"); + auto [ret2, outValue2] = store_->Execute("DETACH DATABASE 'attach.db'"); EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, ret2); - auto [ret3, outValue3] = store->Execute("BEGIN TRANSACTION"); + auto [ret3, outValue3] = store_->Execute("BEGIN TRANSACTION"); EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, ret3); - auto [ret4, outValue4] = store->Execute("COMMIT"); + auto [ret4, outValue4] = store_->Execute("COMMIT"); EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, ret4); - auto [ret5, outValue5] = store->Execute("ROLLBACK"); + auto [ret5, outValue5] = store_->Execute("ROLLBACK"); EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, ret5); + + auto [ret6, outValue6] = store_->ExecuteExt("ROLLBACK"); + EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, ret6); } /** @@ -492,7 +475,6 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0015, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0016, TestSize.Level1) { - std::shared_ptr store = *GetParam(); int64_t intOutValue; constexpr const char *CREATE_TABLE_TEST2 = "CREATE TABLE IF NOT EXISTS test2 " @@ -503,11 +485,11 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0016, TestSize.Level1) constexpr const char *TEST_TABLE_IS_EXIST = "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='test2'"; - auto [ret1, outValue1] = store->Execute(CREATE_TABLE_TEST2); + auto [ret1, outValue1] = store_->Execute(CREATE_TABLE_TEST2); EXPECT_EQ(E_OK, ret1); EXPECT_EQ(ValueObjectType::TYPE_NULL, outValue1.GetType()); - std::shared_ptr resultSet = store->QuerySql(TEST_TABLE_IS_EXIST); + std::shared_ptr resultSet = store_->QuerySql(TEST_TABLE_IS_EXIST); EXPECT_NE(nullptr, resultSet); resultSet->GoToFirstRow(); // 0 represent that get count of table test in the first row @@ -516,11 +498,14 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0016, TestSize.Level1) EXPECT_EQ(1, intOutValue); resultSet->Close(); - auto [ret2, outValue2] = store->Execute(DROP_TABLE_TEST2); + auto [ret2, outValue2] = store_->ExecuteExt(DROP_TABLE_TEST2); EXPECT_EQ(E_OK, ret2); - EXPECT_EQ(ValueObjectType::TYPE_NULL, outValue2.GetType()); + EXPECT_EQ(0, outValue2.changed); + int rowCount = -1; + outValue2.results->GetRowCount(rowCount); + EXPECT_EQ(0, rowCount); - resultSet = store->QuerySql(TEST_TABLE_IS_EXIST); + resultSet = store_->QuerySql(TEST_TABLE_IS_EXIST); EXPECT_NE(nullptr, resultSet); resultSet->GoToFirstRow(); // 0 represent that get count of table test in the first column @@ -537,7 +522,6 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0016, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0017, TestSize.Level1) { - std::shared_ptr store = *GetParam(); int64_t intOutValue; int intOutResultSet; @@ -547,24 +531,24 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0017, TestSize.Level1) "blobType BLOB)"; constexpr const char *DROP_TABLE_TEST2 = "DROP TABLE test2"; - auto [ret1, outValue1] = store->Execute(CREATE_TABLE_TEST2); + auto [ret1, outValue1] = store_->Execute(CREATE_TABLE_TEST2); EXPECT_EQ(E_OK, ret1); std::vector args = { ValueObject("tt"), ValueObject(28), ValueObject(50000) }; - auto [ret2, outValue2] = store->Execute("INSERT INTO test2(name, age, salary) VALUES (?, ?, ?)", args); + auto [ret2, outValue2] = store_->Execute("INSERT INTO test2(name, age, salary) VALUES (?, ?, ?)", args); EXPECT_EQ(E_OK, ret2); outValue2.GetLong(intOutValue); // 1 represent that the last data is inserted in the first row EXPECT_EQ(1, intOutValue); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test2"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test2"); EXPECT_NE(nullptr, resultSet); EXPECT_EQ(E_OK, resultSet->GetRowCount(intOutResultSet)); // 1 represent that the row number of resultSet EXPECT_EQ(1, intOutResultSet); resultSet->Close(); - auto [ret3, outValue3] = store->Execute(DROP_TABLE_TEST2); + auto [ret3, outValue3] = store_->Execute(DROP_TABLE_TEST2); EXPECT_EQ(E_OK, ret3); } @@ -575,10 +559,9 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0017, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0018, TestSize.Level1) { - std::shared_ptr store = *GetParam(); ValueObject outValue; - auto [ret1, outValue1] = store->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?)"); + auto [ret1, outValue1] = store_->Execute("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?)"); EXPECT_NE(E_OK, ret1); } @@ -589,15 +572,13 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0018, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0019, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - // set user_version as 5 - auto [ret, outValue] = store->Execute("PRAGMA user_version=5"); + auto [ret, outValue] = store_->Execute("PRAGMA user_version=5"); EXPECT_EQ(E_OK, ret); EXPECT_EQ(ValueObjectType::TYPE_NULL, outValue.GetType()); // set user_version as 0 - std::tie(ret, outValue) = store->Execute("PRAGMA user_version=0"); + std::tie(ret, outValue) = store_->Execute("PRAGMA user_version=0"); EXPECT_EQ(E_OK, ret); EXPECT_EQ(ValueObjectType::TYPE_NULL, outValue.GetType()); } @@ -609,12 +590,275 @@ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0019, TestSize.Level1) */ HWTEST_P(RdbExecuteTest, RdbStore_Execute_0020, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - - auto [ret, outValue] = store->Execute("PRAGMA table_info(test)"); + auto [ret, outValue] = store_->Execute("PRAGMA table_info(test)"); EXPECT_EQ(E_NOT_SUPPORT_THE_SQL, ret); } +/** + * @tc.name: RdbStore_Execute_0021 + * @tc.desc: Normal testCase for Execute insert, update and delete 2 rows with returning + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteTest, RdbStore_Execute_0021, TestSize.Level1) +{ + std::vector args = { "tt", 28, 50000.0, "ttt", 58, 500080.0 }; + auto [status, result] = + store_->ExecuteExt("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?) returning name", args); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 2); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 2); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "tt"); + ASSERT_EQ(result.results->GoToNextRow(), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "ttt"); + + std::tie(status, result) = + store_->ExecuteExt("update test set name = ? where name = ? returning name", {"update", "tt"}); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "update"); + + std::tie(status, result) = store_->ExecuteExt("delete from test returning name"); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 2); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 2); + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "update"); + ASSERT_EQ(result.results->GoToNextRow(), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "ttt"); +} + +/** + * @tc.name: RdbStore_Execute_0022 + * @tc.desc: Normal testCase for Execute insert, update and delete over limit with returning + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteTest, RdbStore_Execute_0022, TestSize.Level1) +{ + std::vector args = { "0", 0 }; + std::string sql = "INSERT INTO test(name, age) VALUES (?, ?)"; + for (int32_t i = 1; i < 1025; i++) { + sql.append(", (?, ?)"); + args.push_back(std::to_string(i)); + args.push_back(i); + } + auto [status, result] = store_->ExecuteExt(sql + " returning name", args); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1024); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "0"); + ASSERT_EQ(result.results->GoToRow(1000), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "1000"); + + std::tie(status, result) = store_->ExecuteExt("update test set name = ? returning name", { "update" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1024); + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "update"); + + + std::tie(status, result) = store_->ExecuteExt("delete from test returning name"); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1024); + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "update"); +} + +/** + * @tc.name: RdbStore_Execute_0023 + * @tc.desc: normal testCase for Execute insert, update and delete 0 rows with returning + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteTest, RdbStore_Execute_0023, TestSize.Level1) +{ + std::vector args = { 1, "tt", 28, 50000.0 }; + auto [status, result] = + store_->ExecuteExt("INSERT INTO test(id, name, age, salary) VALUES (?, ?, ?, ?) returning id", args); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("id", columnIndex), E_OK); + int64_t value; + ASSERT_EQ(result.results->GetLong(columnIndex, value), E_OK); + EXPECT_EQ(value, 1); + + std::tie(status, result) = + store_->ExecuteExt("INSERT INTO test(id, name, age, salary) VALUES (?, ?, ?, ?) returning id", args); + EXPECT_EQ(status, E_SQLITE_CONSTRAINT); + EXPECT_EQ(result.changed, 0); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); + + std::tie(status, result) = + store_->ExecuteExt("update test set name = ? where name = ? returning name", { "update", "noExist" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); + + std::tie(status, result) = store_->ExecuteExt("delete from test where name = ? returning name", { "noExist" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); +} + +/** + * @tc.name: RdbStore_Execute_0024 + * @tc.desc: abnormal testCase for Execute insert, update and delete with returning field not exist + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteTest, RdbStore_Execute_0024, TestSize.Level1) +{ + std::vector args = { 1, "tt", 28, 50000.0 }; + auto [status, result] = + store_->ExecuteExt("INSERT INTO test(id, name, age, salary) VALUES (?, ?, ?, ?) returning noExist", args); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + ASSERT_EQ(result.results, nullptr); + + std::tie(status, result) = + store_->ExecuteExt("update test set name = ? where name = ? returning noExist", { "update", "noExist" }); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + ASSERT_EQ(result.results, nullptr); + + std::tie(status, result) = store_->ExecuteExt("delete from test where name = ? returning noExist", { "noExist" }); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + ASSERT_EQ(result.results, nullptr); +} + +/** + * @tc.name: RdbStore_Execute_0025 + * @tc.desc: normal test. batch insert into virtual table with returning + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbExecuteTest, RdbStore_Execute_0025, TestSize.Level1) +{ + store_->Execute("CREATE VIRTUAL TABLE IF NOT EXISTS articles USING fts5(title, content);"); + + std::vector args = { "title", "content" }; + auto [status, result] = + store_->ExecuteExt("INSERT INTO articles(title, content) VALUES (?, ?) returning title", args); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("title", columnIndex), E_OK); + std::string value; + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "title"); + + std::vector args2 = { "title2", "title" }; + std::tie(status, result) = + store_->ExecuteExt("UPDATE articles set title = ? where title = ? returning title", args2); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + ASSERT_EQ(result.results, nullptr); + + // DELETE RETURNING is not available on virtual tables + std::tie(status, result) = store_->ExecuteExt("DELETE FROM articles where title = ? returning title", { "title" }); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + ASSERT_EQ(result.results, nullptr); + store_->Execute("Drop TABLE articles"); +} + +/** + * @tc.name: RdbStore_Execute_0026 + * @tc.desc: normal test. create trigger before update, delete data in trigger, then update data + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbExecuteTest, RdbStore_Execute_0026, TestSize.Level1) +{ + auto [code, result1] = store_->Execute( + "CREATE TRIGGER before_update BEFORE UPDATE ON test" + " BEGIN DELETE FROM test WHERE name = 'wang'; END"); + + EXPECT_EQ(code, E_OK); + + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 200); + row.Put("name", "wang"); + rows.Put(std::move(row)); + row.Put("id", 201); + row.Put("name", "zhang"); + rows.Put(std::move(row)); + + auto [insertStatus, insertResult] = + store_->BatchInsert("test", rows, { "name" }, NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(insertStatus, E_OK); + EXPECT_EQ(insertResult.changed, 2); + + std::vector args2 = { "liu", "zhang" }; + auto [status, res] = + store_->ExecuteExt("UPDATE test set name = ? where name = ? returning name", args2); + + EXPECT_EQ(status, E_OK); + EXPECT_EQ(res.changed, 1); + int rowCount = -1; + ASSERT_EQ(res.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(res.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + ASSERT_EQ(res.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "liu"); + + // Check the trigger effect + auto resultSet = store_->QuerySql("select name from test where id = 200"); + + rowCount = -1; + resultSet->GetRowCount(rowCount); + ASSERT_EQ(rowCount, 0); + store_->Execute("DROP TRIGGER IF EXISTS before_update"); +} + INSTANTIATE_TEST_SUITE_P(ExecuteTest, RdbExecuteTest, testing::Values(&g_store, &g_memDb)); } // namespace OHOS::RdbExecuteTest \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_helper_test.cpp b/relational_store/test/native/rdb/unittest/rdb_helper_test.cpp index 663d8b33..988c376b 100644 --- a/relational_store/test/native/rdb/unittest/rdb_helper_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_helper_test.cpp @@ -428,6 +428,9 @@ HWTEST_F(RdbHelperTest, DeleteDatabase_014, TestSize.Level0) auto [ret2, outValue] = store->Execute(RdbHelperTestOpenCallback::CREATE_TABLE_TEST); EXPECT_EQ(ret2, E_ALREADY_CLOSED); + + auto [code, result] = store->ExecuteExt(RdbHelperTestOpenCallback::CREATE_TABLE_TEST); + EXPECT_EQ(code, E_ALREADY_CLOSED); } /** @@ -614,6 +617,29 @@ HWTEST_F(RdbHelperTest, DeleteDatabase_023, TestSize.Level0) ASSERT_EQ(result.first, E_ALREADY_CLOSED); } +/** + * @tc.name: DeleteDatabase_024 + * @tc.desc: BatchInsert after deleteRdbStore + * @tc.type: FUNC + */ +HWTEST_F(RdbHelperTest, DeleteDatabase_024, TestSize.Level0) +{ + InitDb(); + ValuesBuckets rows; + + int ret = RdbHelper::DeleteRdbStore(RdbHelperTest::rdbStorePath); + EXPECT_EQ(ret, E_OK); + + for (int32_t i = 0; i < 10; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto result = store->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_NONE); + EXPECT_EQ(result.first, E_ALREADY_CLOSED); +} + /** * @tc.name: getrdbstore_001 * @tc.desc: get db file with a invalid path @@ -804,4 +830,4 @@ HWTEST_F(RdbHelperTest, GetDatabase_007, TestSize.Level0) // Ensure that two databases not equal EXPECT_NE(rdbStore1, rdbStore2); -} \ No newline at end of file +} diff --git a/relational_store/test/native/rdb/unittest/rdb_insert_test.cpp b/relational_store/test/native/rdb/unittest/rdb_insert_test.cpp index 52b9eb3e..4ea6ed3b 100644 --- a/relational_store/test/native/rdb/unittest/rdb_insert_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_insert_test.cpp @@ -22,6 +22,8 @@ #include "rdb_errno.h" #include "rdb_helper.h" #include "rdb_open_callback.h" +#include "result_set.h" +#include "values_buckets.h" using namespace testing::ext; using namespace OHOS::NativeRdb; @@ -75,6 +77,24 @@ int InsertTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVe return E_OK; } +std::vector GetColumnValues(std::shared_ptr resultSet, const std::string &filed) +{ + std::vector res; + if (resultSet->GoToFirstRow() != E_OK) { + return res; + } + int32_t colIndex = -1; + if (resultSet->GetColumnIndex(filed, colIndex) != E_OK) { + return res; + } + do { + ValueObject value; + EXPECT_EQ(resultSet->Get(colIndex, value), E_OK); + res.push_back(value); + } while (resultSet->GoToNextRow() == E_OK); + return res; +} + void RdbStoreInsertTest::SetUpTestCase(void) { int errCode = E_OK; @@ -100,6 +120,7 @@ void RdbStoreInsertTest::TearDownTestCase(void) void RdbStoreInsertTest::SetUp(void) { store_ = *GetParam(); + ASSERT_NE(store_, nullptr); store_->ExecuteSql("DELETE FROM test"); } @@ -112,10 +133,8 @@ void RdbStoreInsertTest::TearDown(void) * @tc.desc: test RdbStore insert * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_001, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_001, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; @@ -124,7 +143,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_001, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); + int ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -134,7 +153,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_001, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Insert(id, "test", values); + ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -144,18 +163,18 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_001, TestSize.Level1) values.PutInt("age", 20L); values.PutDouble("salary", 100.5f); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Insert(id, "test", values); + ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); - RdbStoreInsertTest::CheckResultSet(store); + RdbStoreInsertTest::CheckResultSet(store_); } void RdbStoreInsertTest::CheckResultSet(std::shared_ptr &store) { std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test WHERE name = ?", std::vector{ "zhangsan" }); - EXPECT_NE(resultSet, nullptr); + ASSERT_NE(resultSet, nullptr); int columnIndex; int intVal; @@ -258,10 +277,8 @@ void RdbStoreInsertTest::CheckBlob(std::shared_ptr &resultSet) * @tc.desc: test RdbStore insert * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_002, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_002, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; values.PutInt("id", 1); @@ -269,10 +286,10 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_002, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "", values); // empty table name + int ret = store_->Insert(id, "", values); // empty table name EXPECT_EQ(ret, E_EMPTY_TABLE_NAME); - ret = store->Insert(id, "wrongTable", values); // no such table + ret = store_->Insert(id, "wrongTable", values); // no such table EXPECT_EQ(ret, E_SQLITE_ERROR); } @@ -281,13 +298,11 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_002, TestSize.Level1) * @tc.desc: test RdbStore insert * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_003, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_003, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket emptyBucket; - int ret = store->Insert(id, "test", emptyBucket); + int ret = store_->Insert(id, "test", emptyBucket); EXPECT_EQ(ret, E_EMPTY_VALUES_BUCKET); ValuesBucket values; @@ -296,7 +311,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_003, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("wrongColumn", 100.5); // no such column values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Insert(id, "test", values); + ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_SQLITE_ERROR); } @@ -305,18 +320,16 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Insert_003, TestSize.Level1) * @tc.desc: test RdbStore replace * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_001, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_001, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; - int ret = store->Replace(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Replace(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -356,14 +369,12 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_001, TestSize.Level1) * @tc.desc: test RdbStore replace * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_002, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_002, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -373,11 +384,11 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_002, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Replace(id, "test", values); + ret = store_->Replace(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -417,10 +428,8 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_002, TestSize.Level1) * @tc.desc: test RdbStore Replace * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_003, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_003, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; values.PutInt("id", 1); @@ -428,10 +437,10 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_003, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Replace(id, "", values); // empty table name + int ret = store_->Replace(id, "", values); // empty table name EXPECT_EQ(ret, E_EMPTY_TABLE_NAME); - ret = store->Replace(id, "wrongTable", values); // no such table + ret = store_->Replace(id, "wrongTable", values); // no such table EXPECT_EQ(ret, E_SQLITE_ERROR); } @@ -440,13 +449,11 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_003, TestSize.Level1) * @tc.desc: test RdbStore Replace * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_004, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_004, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket emptyBucket; - int ret = store->Replace(id, "test", emptyBucket); + int ret = store_->Replace(id, "test", emptyBucket); EXPECT_EQ(ret, E_EMPTY_VALUES_BUCKET); ValuesBucket values; @@ -455,7 +462,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_004, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("wrongColumn", 100.5); // no such column values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Replace(id, "test", values); + ret = store_->Replace(id, "test", values); EXPECT_EQ(ret, E_SQLITE_ERROR); } @@ -464,17 +471,15 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_004, TestSize.Level1) * @tc.desc: test RdbStore replace * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_005, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_005, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; - int ret = store->Replace(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Replace(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -511,14 +516,12 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_005, TestSize.Level1) * @tc.desc: test RdbStore replace * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_006, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_006, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -528,11 +531,11 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_006, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Replace(id, "test", values); + ret = store_->Replace(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -569,10 +572,8 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_Replace_006, TestSize.Level1) * @tc.desc: test RdbStore InsertWithConflictResolution * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_001_002, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_001_002, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; @@ -583,7 +584,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_001_002, Test values.PutBlob("blobType", std::vector{ 1, 2, 3 }); // default is ConflictResolution::ON_CONFLICT_NONE - int ret = store->InsertWithConflictResolution(id, "test", values); + int ret = store_->InsertWithConflictResolution(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -593,7 +594,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_001_002, Test values.PutInt("age", 18); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->InsertWithConflictResolution(id, "test", values); + ret = store_->InsertWithConflictResolution(id, "test", values); EXPECT_EQ(ret, E_SQLITE_CONSTRAINT); } @@ -602,10 +603,8 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_001_002, Test * @tc.desc: test RdbStore InsertWithConflictResolution * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_003_004, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_003_004, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; @@ -614,7 +613,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_003_004, Test values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_ROLLBACK); + int ret = store_->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_ROLLBACK); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -624,7 +623,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_003_004, Test values.PutInt("age", 18); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_ROLLBACK); + ret = store_->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_ROLLBACK); EXPECT_EQ(ret, E_SQLITE_CONSTRAINT); } @@ -633,10 +632,8 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_003_004, Test * @tc.desc: test RdbStore InsertWithConflictResolution * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_005, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_005, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; @@ -645,7 +642,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_005, TestSize values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_IGNORE); + int ret = store_->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_IGNORE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -655,7 +652,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_005, TestSize values.PutInt("age", 18); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_IGNORE); + ret = store_->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_IGNORE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(id, -1); } @@ -665,14 +662,12 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_005, TestSize * @tc.desc: test RdbStore InsertWithConflictResolution * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_006, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_006, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; - int ret = store->InsertWithConflictResolution( + int ret = store_->InsertWithConflictResolution( id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0]), ConflictResolution::ON_CONFLICT_REPLACE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -683,11 +678,11 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_006, TestSize values.PutInt("age", 18); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_REPLACE); + ret = store_->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_REPLACE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(id, 1); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -727,14 +722,12 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_006, TestSize * @tc.desc: test RdbStore InsertWithConflictResolution * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_007, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_007, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; - int ret = store->InsertWithConflictResolution( + int ret = store_->InsertWithConflictResolution( id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0]), ConflictResolution::ON_CONFLICT_REPLACE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -745,11 +738,11 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_007, TestSize values.PutInt("age", 18); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_REPLACE); + ret = store_->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_REPLACE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(id, 1); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -786,23 +779,21 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_007, TestSize * @tc.desc: Abnormal testCase of InsertWithConflictResolution, if conflictResolution is invalid * @tc.type: FUNC */ -HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_008, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_008, TestSize.Level0) { - std::shared_ptr store = *GetParam(); - int64_t id = 0; ValuesBucket values; values.PutInt("id", 1); values.PutInt("age", 18); - int ret = store->InsertWithConflictResolution(id, "test", values, static_cast(6)); + int ret = store_->InsertWithConflictResolution(id, "test", values, static_cast(6)); EXPECT_EQ(E_INVALID_CONFLICT_FLAG, ret); EXPECT_EQ(0, id); values.Clear(); values.PutInt("id", 1); values.PutInt("age", 18); - ret = store->InsertWithConflictResolution(id, "test", values, static_cast(-1)); + ret = store_->InsertWithConflictResolution(id, "test", values, static_cast(-1)); EXPECT_EQ(E_INVALID_CONFLICT_FLAG, ret); EXPECT_EQ(0, id); } @@ -814,7 +805,7 @@ HWTEST_P(RdbStoreInsertTest, RdbStore_InsertWithConflictResolution_008, TestSize * @tc.require: * @tc.author: */ -HWTEST_P(RdbStoreInsertTest, OverLimitWithInsert_001, TestSize.Level1) +HWTEST_P(RdbStoreInsertTest, OverLimitWithInsert_001, TestSize.Level0) { std::shared_ptr store = *GetParam(); auto [code, maxPageCount] = store->Execute("PRAGMA max_page_count;"); @@ -829,5 +820,654 @@ HWTEST_P(RdbStoreInsertTest, OverLimitWithInsert_001, TestSize.Level1) ASSERT_EQ(result.first, E_SQLITE_FULL); } +/** + * @tc.name: BatchInsert_001 + * @tc.desc: normal test + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_001, TestSize.Level0) +{ + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto [status, result] = store_->BatchInsert("test", rows, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 5); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 5); + auto values = GetColumnValues(result.results, "id"); + ASSERT_EQ(values.size(), 5); + for (int i = 0; i < 5; i++) { + int val = -1; + EXPECT_EQ(values[i].GetInt(val), E_OK); + EXPECT_EQ(val, i); + } +} + +/** + * @tc.name: BatchInsert_002 + * @tc.desc: abnormal test. batch insert with returning and conflict IGNORE + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_002, TestSize.Level0) +{ + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + ValuesBucket row; + row.Put("id", 2); + row.Put("name", "Jim"); + auto res = store_->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 2); + std::string returningField = "id"; + auto [status, result] = + store_->BatchInsert("test", rows, { returningField }, ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 4); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 4); + auto values = GetColumnValues(result.results, returningField); + ASSERT_EQ(values.size(), 4); + for (size_t i = 0; i < values.size(); i++) { + int val = -1; + EXPECT_EQ(values[i].GetInt(val), E_OK); + EXPECT_EQ(val, i + (i >= 2)); + } +} + +/** + * @tc.name: BatchInsert_003 + * @tc.desc: abnormal test. batch insert with returning and conflict fail. + * When using the fail strategy, if the constraint is violated, the correct result cannot be obtained + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_003, TestSize.Level0) +{ + std::vector rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.push_back(std::move(row)); + } + ValuesBucket row; + row.Put("id", 2); + row.Put("name", "Jim"); + auto res = store_->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 2); + auto [status, result] = store_->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_FAIL); + EXPECT_EQ(status, E_SQLITE_CONSTRAINT); + EXPECT_EQ(result.changed, 2); + EXPECT_EQ(result.results, nullptr); +} + +/** + * @tc.name: BatchInsert_004 + * @tc.desc: abnormal test. batch insert with returning and conflict replace + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_004, TestSize.Level0) +{ + std::vector rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.push_back(std::move(row)); + } + ValuesBucket row; + row.Put("id", 2); + row.Put("name", "Jim"); + auto res = store_->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 2); + std::string returningField = "id"; + auto [status, result] = store_->BatchInsert( + "test", ValuesBuckets(std::move(rows)), { returningField }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 5); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 5); + auto values = GetColumnValues(result.results, returningField); + ASSERT_EQ(values.size(), 5); + for (size_t i = 0; i < 5; i++) { + int val = -1; + EXPECT_EQ(values[i].GetInt(val), E_OK); + EXPECT_EQ(val, i); + } +} + +/** + * @tc.name: BatchInsert_005 + * @tc.desc: abnormal test. batch insert with over returning limit + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_005, TestSize.Level0) +{ + ValuesBuckets rows; + rows.Reserve(1025); + for (int i = 0; i < 1025; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(std::move(row)); + } + auto [status, result] = store_->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1024); + auto values = GetColumnValues(result.results, "id"); + ASSERT_EQ(values.size(), 1024); + for (size_t i = 0; i < 1024; i++) { + EXPECT_EQ(int(values[i]), i); + } +} + +/** + * @tc.name: BatchInsert_006 + * @tc.desc: abnormal test. batch insert with returning non-existent fields + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_006, TestSize.Level0) +{ + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(std::move(row)); + } + std::string returningField = "notExist"; + auto [status, result] = + store_->BatchInsert("test", rows, { returningField }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + ASSERT_EQ(result.results, nullptr); +} + +/** + * @tc.name: BatchInsert_007 + * @tc.desc: abnormal test. batch insert with returning and no changed rows + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_007, TestSize.Level0) +{ + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 2); + row.Put("name", "Jim"); + auto res = store_->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 2); + rows.Put(std::move(row)); + auto [status, result] = store_->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 0); +} + +/** + * @tc.name: BatchInsert_008 + * @tc.desc: normal test. batch insert with returning rowId + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_008, TestSize.Level0) +{ + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 2); + row.Put("name", "Jim"); + rows.Put(std::move(row)); + // rowId can use in retuning, but get column not include rowId + auto [status, result] = store_->BatchInsert("test", rows, { "rowId", "rowid", "RowId", "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("id")), 2); +} + +/** + * @tc.name: BatchInsert_009 + * @tc.desc: normal test. batch insert with returning * + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_009, TestSize.Level0) +{ + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 2); + row.Put("name", "Jim"); + row.Put("age", 18); + row.PutDouble("salary", 100.5); + std::vector blob{ 1, 2, 3 }; + row.PutBlob("blobType", blob); + rows.Put(std::move(row)); + auto [status, result] = + store_->BatchInsert("test", rows, { "*" }, NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("id")), 2); + EXPECT_EQ(std::string(rowEntity.Get("name")), "Jim"); + EXPECT_EQ(int(rowEntity.Get("age")), 18); + EXPECT_NEAR(double(rowEntity.Get("salary")), 100.5, std::numeric_limits::epsilon()); + EXPECT_EQ(std::vector(rowEntity.Get("blobType")), blob); +} + +/** + * @tc.name: BatchInsert_010 + * @tc.desc: normal test. batch insert with returning complex field + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_010, TestSize.Level0) +{ + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 2); + row.Put("name", "Jim"); + row.PutDouble("salary", 100.5); + rows.Put(std::move(row)); + auto [status, result] = store_->BatchInsert("test", rows, { "id", "name", "salary * 1.1 AS bonusSalary" }, + NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("id")), 2); + EXPECT_EQ(std::string(rowEntity.Get("name")), "Jim"); + EXPECT_NEAR(double(rowEntity.Get("bonusSalary")), 100.5 * 1.1, std::numeric_limits::epsilon()); +} + +/** + * @tc.name: BatchInsert_011 + * @tc.desc: normal test. batch insert with returning complex field + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_011, TestSize.Level1) +{ + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 1); + row.Put("name", "Jim"); + row.Put("age", 18); + row.PutDouble("salary", 110.5); + rows.Put(std::move(row)); + row.Clear(); + row.Put("id", 2); + row.Put("name", "Bob"); + row.Put("age", 22); + row.PutDouble("salary", 90); + rows.Put(std::move(row)); + auto [status, result] = store_->BatchInsert("test", rows, + { "id", "name", "(salary < 100) AS lowSalary", "age > 18 as adult" }, + NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 2); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 2); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("id")), 1); + EXPECT_EQ(std::string(rowEntity.Get("name")), "Jim"); + EXPECT_EQ(bool(rowEntity.Get("lowSalary")), false); + EXPECT_EQ(bool(rowEntity.Get("adult")), false); + + EXPECT_EQ(result.results->GoToNextRow(), E_OK); + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("id")), 2); + EXPECT_EQ(std::string(rowEntity.Get("name")), "Bob"); + EXPECT_EQ(bool(rowEntity.Get("lowSalary")), true); + EXPECT_EQ(bool(rowEntity.Get("adult")), true); +} + +/** + * @tc.name: BatchInsert_012 + * @tc.desc: normal test. batch insert with returning function + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_012, TestSize.Level1) +{ + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 20); + row.Put("name", "Jim"); + row.PutDouble("salary", 100.5); + rows.Put(std::move(row)); + auto [status, result] = store_->BatchInsert("test", rows, { "id", "name", "datetime('now') AS createdTime" }, + NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("id")), 20); + EXPECT_EQ(std::string(rowEntity.Get("name")), "Jim"); + EXPECT_EQ(rowEntity.Get("createdTime").GetType(), ValueObject::TYPE_STRING); + EXPECT_FALSE(std::string(rowEntity.Get("createdTime")).empty()); +} + +/** + * @tc.name: BatchInsert_013 + * @tc.desc: normal test. batch insert into virtual table with returning + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_013, TestSize.Level1) +{ + store_->Execute("CREATE VIRTUAL TABLE IF NOT EXISTS articles USING fts5(title, content);"); + ValuesBuckets rows; + ValuesBucket row; + row.Put("title", "fts5"); + row.Put("content", "test virtual tables"); + rows.Put(std::move(row)); + auto [status, result] = + store_->BatchInsert("articles", rows, { "title" }, NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(std::string(rowEntity.Get("title")), "fts5"); + store_->Execute("Drop TABLE articles"); +} + +/** + * @tc.name: BatchInsert_014 + * @tc.desc: normal test. batch insert with returning and trigger + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_014, TestSize.Level1) +{ + auto [code, result1] = store_->Execute("CREATE TRIGGER after_name_insert AFTER INSERT ON test" + " BEGIN UPDATE test SET name = 'after trigger' WHERE name = 'BatchInsert_014'; END"); + + EXPECT_EQ(code, E_OK); + + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 200); + row.Put("name", "BatchInsert_014"); + rows.Put(std::move(row)); + auto [status, result] = + store_->BatchInsert("test", rows, { "name" }, NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(std::string(rowEntity.Get("name")), "BatchInsert_014"); + + auto resultSet = store_->QuerySql("select name from test where id = 200"); + int rowCount = -1; + resultSet->GetRowCount(rowCount); + resultSet->GoToFirstRow(); + EXPECT_EQ(resultSet->GetRow(rowEntity), E_OK); + EXPECT_EQ(std::string(rowEntity.Get("name")), "after trigger"); + store_->Execute("DROP TRIGGER IF EXISTS after_name_insert"); +} + +/** + * @tc.name: BatchInsert_015 + * @tc.desc: normal test. batch insert with returning and sub query + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_015, TestSize.Level1) +{ + store_->Execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT);"); + store_->Execute("CREATE TABLE IF NOT EXISTS logs (id INTEGER PRIMARY KEY, action TEXT);"); + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 200); + row.Put("action", "BatchInsert_015"); + rows.Put(std::move(row)); + auto [status, changed] = store_->BatchInsert("logs", rows); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(changed, 1); + Results result{ -1 }; + row.Clear(); + rows.Clear(); + row.Put("id", 1); + row.Put("name", "BatchInsert_015"); + rows.Put(std::move(row)); + std::tie(status, result) = store_->BatchInsert("users", rows, + { "(SELECT COUNT(*) FROM logs WHERE action = name) AS count" }, + NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("count")), 1); + store_->Execute("DROP TABLE users"); + store_->Execute("DROP TABLE logs"); +} + +/** + * @tc.name: BatchInsert_016 + * @tc.desc: abnormal test. batch insert with max returning limit + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_016, TestSize.Level0) +{ + int maxRowCount = 1024; + ValuesBuckets rows; + rows.Reserve(maxRowCount); + for (int i = 0; i < maxRowCount; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(std::move(row)); + } + auto [status, result] = + store_->BatchInsert("test", ValuesBuckets(rows), {"id", "name"}, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, maxRowCount); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, maxRowCount); + for (size_t i = 0; i < maxRowCount; i++) { + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("id")), i); + EXPECT_EQ(std::string(rowEntity.Get("name")), "Jim"); + if (i != maxRowCount - 1) { + ASSERT_EQ(result.results->GoToNextRow(), E_OK); + } + } +} + +/** + * @tc.name: BatchInsert_017 + * @tc.desc: abnormal test. batch insert with max returning limit + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_017, TestSize.Level0) +{ + int maxRowCount = 1024; + ValuesBuckets rows; + rows.Reserve(maxRowCount); + for (int i = 0; i < maxRowCount; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(std::move(row)); + } + auto [status, result] = + store_->BatchInsert("test", ValuesBuckets(rows), {"id", "name"}, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, maxRowCount); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, maxRowCount); + + std::tie(status, result) = + store_->ExecuteExt("UPDATE test SET name = 'Tim' WHERE name = 'Jim' RETURNING id, name"); + + EXPECT_EQ(result.changed, maxRowCount); + count = 0; + EXPECT_EQ(result.results->GetRowCount(count), E_OK); + EXPECT_EQ(count, maxRowCount); + for (size_t i = 0; i < maxRowCount; i++) { + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(int(rowEntity.Get("id")), i); + EXPECT_EQ(std::string(rowEntity.Get("name")), "Tim"); + if (i != maxRowCount - 1) { + ASSERT_EQ(result.results->GoToNextRow(), E_OK); + } + } +} + +/** + * @tc.name: BatchInsert_018 + * @tc.desc: abnormal test. batch insert with max returning limit + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_018, TestSize.Level0) +{ + int maxRowCount = 1024; + ValuesBuckets rows; + rows.Reserve(maxRowCount); + for (int i = 0; i < maxRowCount; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(std::move(row)); + } + auto [status, result] = + store_->BatchInsert("test", ValuesBuckets(rows), {"id", "name"}, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, maxRowCount); + + std::tie(status, result) = + store_->ExecuteExt("update test set name = ? where name = ?", { "Tim", "Jim" }); + + EXPECT_NE(result.results, nullptr); + EXPECT_EQ(result.changed, maxRowCount); + int32_t count = 0; + EXPECT_EQ(result.results->GetRowCount(count), E_OK); + EXPECT_EQ(count, 0); +} +/** + * @tc.name: BatchInsert_019 + * @tc.desc: normal test. batch insert with returning and trigger + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreInsertTest, BatchInsert_019, TestSize.Level1) +{ + auto [code, result1] = store_->Execute("CREATE TRIGGER after_name_insert AFTER INSERT ON test" + " BEGIN UPDATE test SET name = 'after trigger' WHERE name = 'BatchInsert_014'; END"); + + EXPECT_EQ(code, E_OK); + + auto [status, result] = + store_->ExecuteExt("INSERT INTO test (id, name) VALUES (200, 'BatchInsert_014') RETURNING name;"); + + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int32_t count = 0; + ASSERT_EQ(result.results->GetRowCount(count), E_OK); + ASSERT_EQ(count, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(std::string(rowEntity.Get("name")), "BatchInsert_014"); + + auto resultSet = store_->QuerySql("select name from test where id = 200"); + int rowCount = -1; + resultSet->GetRowCount(rowCount); + resultSet->GoToFirstRow(); + EXPECT_EQ(resultSet->GetRow(rowEntity), E_OK); + EXPECT_EQ(std::string(rowEntity.Get("name")), "after trigger"); + store_->Execute("DROP TRIGGER IF EXISTS after_name_insert"); +} INSTANTIATE_TEST_SUITE_P(InsertTest, RdbStoreInsertTest, testing::Values(&g_store, &g_memDb)); } // namespace OHOS::RdbStoreInsertTest \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_memory_db_test.cpp b/relational_store/test/native/rdb/unittest/rdb_memory_db_test.cpp index db452113..62835c61 100644 --- a/relational_store/test/native/rdb/unittest/rdb_memory_db_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_memory_db_test.cpp @@ -400,27 +400,27 @@ HWTEST_F(RdbMemoryDbTest, CRUDWithMemoryDb_003, TestSize.Level1) row.Put("name", "Jim_batchInsert"); rows.Put(row); } - auto result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_SQLITE_LOCKED); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_SQLITE_LOCKED); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_SQLITE_LOCKED); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_SQLITE_LOCKED); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_SQLITE_LOCKED); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_SQLITE_LOCKED); ASSERT_EQ(result.second, -1); } diff --git a/relational_store/test/native/rdb/unittest/rdb_predicates_test.cpp b/relational_store/test/native/rdb/unittest/rdb_predicates_test.cpp index 0b4b2506..017be1f0 100644 --- a/relational_store/test/native/rdb/unittest/rdb_predicates_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_predicates_test.cpp @@ -353,7 +353,12 @@ const std::string ALL_DATA_TYPE_INSERT_SQL = "primShortValue, primFloatValue, primDoubleValue, " "primBooleanValue, primByteValue, primCharValue, `orderr`) " "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);"; - +const std::string HAVING_CREATE_SQL = + "CREATE TABLE IF NOT EXISTS orders (id INTEGER PRIMARY KEY AUTOINCREMENT, customer_id INTEGER, amount INTEGER)"; +const std::string HAVING_INSERT_SQL = + "INSERT INTO orders (customer_id, amount) VALUES (1, 1500), (1, 2000), (1, 3000), (2, 800), (2, 1200), (3, 1500)," + " (3, 2000), (3, 2500), (3, 1000)"; +const std::string HAVING_DROP_SQL = "DROP TABLE IF EXISTS orders"; class PredicateTestOpenCallback : public RdbOpenCallback { public: int OnCreate(RdbStore &store) override; @@ -2483,7 +2488,7 @@ HWTEST_F(RdbStorePredicateTest, RdbStore_GetString_001, TestSize.Level1) store->ExecuteSql("DELETE FROM person"); } -/* * +/** * @tc.name: RdbStore_GetString_002 * @tc.desc: Normal testCase of RdbPredicates for GetString * @tc.type: FUNC @@ -2518,4 +2523,125 @@ HWTEST_F(RdbStorePredicateTest, RdbStore_GetString_002, TestSize.Level1) resultSet->Close(); store->ExecuteSql("DELETE FROM person"); +} + +/** + * @tc.name: RdbStore_Having_001 + * @tc.desc: Verify scenarios without placeholders and without passing values + * 1.Execute Having("total > 5000 AND count >= 3") + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbStorePredicateTest, RdbStore_Having_001, TestSize.Level1) +{ + store->Execute(HAVING_CREATE_SQL); + store->Execute(HAVING_INSERT_SQL); + RdbPredicates predicates("orders"); + predicates.GroupBy({ "customer_id" }); + predicates.Having("total > 5000 AND count >= 3"); + auto resultSet = store->Query(predicates, { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total" }); + EXPECT_EQ(resultSet->GoToNextRow(), E_OK); + RowEntity rowEntity; + EXPECT_EQ(resultSet->GetRow(rowEntity), E_OK); + EXPECT_TRUE(rowEntity.Get("customer_id") == ValueObject(1)); + EXPECT_TRUE(rowEntity.Get("total") == ValueObject(6500)); // 6500 means total price. + + EXPECT_EQ(resultSet->GoToNextRow(), E_OK); + RowEntity rowEntity1; + EXPECT_EQ(resultSet->GetRow(rowEntity1), E_OK); + EXPECT_TRUE(rowEntity1.Get("customer_id") == ValueObject(3)); // 3 means customer id. + EXPECT_TRUE(rowEntity1.Get("total") == ValueObject(7000)); // 7000 means total price. + store->ExecuteSql(HAVING_DROP_SQL); +} + +/** + * @tc.name: RdbStore_Having_002 + * @tc.desc: Verify scenarios without placeholders and without passing args. + * 1.Execute having("") + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbStorePredicateTest, RdbStore_Having_002, TestSize.Level1) +{ + store->Execute(HAVING_CREATE_SQL); + store->Execute(HAVING_INSERT_SQL); + RdbPredicates predicates("orders"); + predicates.GroupBy({ "customer_id" }); + // When conditions are passed empty, 'having' does not take effect. + predicates.Having(""); + auto resultSet = store->Query(predicates, { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total" }); + int count; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 3); // 3 means row count. + store->ExecuteSql(HAVING_DROP_SQL); +} + + /** + * @tc.name: RdbStore_Having_003 + * @tc.desc: Test conditions for passing in illegal SQL + * 1.Execute Having("SALARY == 1.2") + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbStorePredicateTest, RdbStore_Having_003, TestSize.Level1) +{ + store->Execute(HAVING_CREATE_SQL); + store->Execute(HAVING_INSERT_SQL); + RdbPredicates predicates("orders"); + predicates.GroupBy({ "customer_id" }); + predicates.Having("SALARY == 1.2"); + auto resultSet = store->Query(predicates, { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total" }); + int count; + EXPECT_EQ(resultSet->GetRowCount(count), E_SQLITE_ERROR); + store->ExecuteSql(HAVING_DROP_SQL); +} + +/** + * @tc.name: RdbStore_Having_004 + * @tc.desc: Verify scenarios without placeholders and without passing values + * 1.Execute Having(total > ? AND count >= ?", {5000}) + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbStorePredicateTest, RdbStore_Having_004, TestSize.Level1) +{ + store->Execute(HAVING_CREATE_SQL); + store->Execute(HAVING_INSERT_SQL); + RdbPredicates predicates("orders"); + predicates.GroupBy({ "customer_id" }); + predicates.Having("total > ? AND count >= ?", { 5000 }); + auto resultSet = store->Query(predicates, { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total" }); + int count = -1; + resultSet->GetRowCount(count); + EXPECT_EQ(count, 0); + store->ExecuteSql(HAVING_DROP_SQL); +} + +/** + * @tc.name: RdbStore_Having_005 + * @tc.desc: Test using placeholder scenarios. + * 1.Execute Having(total > ? AND count >= ?", {5000, 3}) + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbStorePredicateTest, RdbStore_Having_005, TestSize.Level1) +{ + store->Execute(HAVING_CREATE_SQL); + store->Execute(HAVING_INSERT_SQL); + RdbPredicates predicates("orders"); + predicates.GroupBy({ "customer_id" }); + predicates.Having("total > ? AND count >= ?", {5000, 3}); // 5000 means lower limit of total price. + auto resultSet = store->Query(predicates, { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total" }); + EXPECT_EQ(resultSet->GoToNextRow(), E_OK); + RowEntity rowEntity; + EXPECT_EQ(resultSet->GetRow(rowEntity), E_OK); + EXPECT_TRUE(rowEntity.Get("customer_id") == ValueObject(1)); + EXPECT_TRUE(rowEntity.Get("total") == ValueObject(6500)); // 6500 means total price. + + EXPECT_EQ(resultSet->GoToNextRow(), E_OK); + RowEntity rowEntity1; + EXPECT_EQ(resultSet->GetRow(rowEntity1), E_OK); + EXPECT_TRUE(rowEntity1.Get("customer_id") == ValueObject(3)); // 3 means customer id. + EXPECT_TRUE(rowEntity1.Get("total") == ValueObject(7000)); // 7000 means total price. + store->ExecuteSql(HAVING_DROP_SQL); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_read_only_test.cpp b/relational_store/test/native/rdb/unittest/rdb_read_only_test.cpp index 1552f2f9..99c20f94 100644 --- a/relational_store/test/native/rdb/unittest/rdb_read_only_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_read_only_test.cpp @@ -252,6 +252,9 @@ HWTEST_F(RdbReadOnlyTest, RdbStore_ReadOnly_0008, TestSize.Level1) std::tie(ret, object) = store->Execute("PRAGMA user_version=2"); EXPECT_EQ(E_NOT_SUPPORT, ret); + + auto [code, result] = store->ExecuteExt("PRAGMA user_version=2"); + EXPECT_EQ(E_NOT_SUPPORT, code); } /** @@ -512,7 +515,7 @@ HWTEST_F(RdbReadOnlyTest, RdbStore_ReadOnly_0022, TestSize.Level1) /** * @tc.name: RdbStore_ReadOnly_0023 - * @tc.desc: test BatchInsertWithConflictResolution + * @tc.desc: test BatchInsert * @tc.type: FUNC */ HWTEST_F(RdbReadOnlyTest, RdbStore_ReadOnly_0023, TestSize.Level1) @@ -525,17 +528,17 @@ HWTEST_F(RdbReadOnlyTest, RdbStore_ReadOnly_0023, TestSize.Level1) row.Put("name", "Jim"); rows.Put(row); } - auto ret = store->BatchInsertWithConflictResolution("test", rows, ConflictResolution::ON_CONFLICT_NONE); + auto ret = store->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_NONE); EXPECT_EQ(E_NOT_SUPPORT, ret.first); - ret = store->BatchInsertWithConflictResolution("test", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + ret = store->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); EXPECT_EQ(E_NOT_SUPPORT, ret.first); - ret = store->BatchInsertWithConflictResolution("test", rows, ConflictResolution::ON_CONFLICT_ABORT); + ret = store->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_ABORT); EXPECT_EQ(E_NOT_SUPPORT, ret.first); - ret = store->BatchInsertWithConflictResolution("test", rows, ConflictResolution::ON_CONFLICT_FAIL); + ret = store->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_FAIL); EXPECT_EQ(E_NOT_SUPPORT, ret.first); - ret = store->BatchInsertWithConflictResolution("test", rows, ConflictResolution::ON_CONFLICT_IGNORE); + ret = store->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_IGNORE); EXPECT_EQ(E_NOT_SUPPORT, ret.first); - ret = store->BatchInsertWithConflictResolution("test", rows, ConflictResolution::ON_CONFLICT_REPLACE); + ret = store->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_REPLACE); EXPECT_EQ(E_NOT_SUPPORT, ret.first); } diff --git a/relational_store/test/native/rdb/unittest/rdb_security_manager_test.cpp b/relational_store/test/native/rdb/unittest/rdb_security_manager_test.cpp index cf8b1f7a..d6b028a9 100644 --- a/relational_store/test/native/rdb/unittest/rdb_security_manager_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_security_manager_test.cpp @@ -157,4 +157,48 @@ HWTEST_F(RdbSecurityManagerTest, LoadSecretKeyFromDiskTest, TestSize.Level1) RdbHelper::DeleteRdbStore(config); } + +/** + * @tc.name: LockNoBlockTest001 + * @tc.desc: Abnormal test for LockNB + * @tc.type: FUNC + */ +HWTEST_F(RdbSecurityManagerTest, LockNBTest001, TestSize.Level1) +{ + std::string lockPath = dbFile_ + "-LockNBTest001"; + RdbSecurityManager::KeyFiles keyFiles(lockPath); + EXPECT_EQ(keyFiles.DestroyLock(), E_OK); + EXPECT_NE(keyFiles.Lock(false), E_OK); +} + +/** + * @tc.name: LockNBTest002 + * @tc.desc: test LockNB return E_ERROR when called from another fd + * @tc.type: FUNC + */ +HWTEST_F(RdbSecurityManagerTest, LockNBTest002, TestSize.Level1) +{ + RdbSecurityManager::KeyFiles keyFiles(dbFile_); + EXPECT_EQ(keyFiles.Lock(false), E_OK); + std::thread thread([dbFile = dbFile_]() { + RdbSecurityManager::KeyFiles keyFiles(dbFile); + EXPECT_EQ(keyFiles.Lock(false), E_ERROR); + keyFiles.Unlock(); + }); + sleep(1); + thread.join(); + keyFiles.Unlock(); +} + +/** + * @tc.name: InitPathTest + * @tc.desc: test init path test + * @tc.type: FUNC + */ +HWTEST_F(RdbSecurityManagerTest, InitPathTest, TestSize.Level1) +{ + std::string filePath("system/test"); + bool ret = RdbSecurityManager::InitPath(filePath); + EXPECT_FALSE(ret); +} } // namespace Test \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_service_proxy_test.cpp b/relational_store/test/native/rdb/unittest/rdb_service_proxy_test.cpp new file mode 100644 index 00000000..597c2436 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_service_proxy_test.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 "rdb_service_proxy.h" + +#include + +#include "rdb_manager_impl.h" +#include "rdb_service.h" +#include "rdb_types.h" + +using namespace testing::ext; +using namespace OHOS::DistributedRdb; +namespace Test { +class RdbServiceProxyTest : public testing::Test { +public: + static void SetUpTestCase(void){}; + static void TearDownTestCase(void){}; + void SetUp(void){}; + void TearDown(void){}; +}; + +/** + * @tc.name: OnRemoteDeadSyncComplete + * @tc.desc: OnRemoteDeadSyncComplete callback is executed + * @tc.type: FUNC + */ +HWTEST_F(RdbServiceProxyTest, OnRemoteDeadSyncComplete, TestSize.Level1) +{ + RdbSyncerParam param; + param.bundleName_ = "com.example.test"; + param.storeName_ = "test.db"; + auto [status, service] = RdbManagerImpl::GetInstance().GetRdbService(param); + ASSERT_NE(service, nullptr); + + auto callback = [](const Details &details) { + ASSERT_NE(details.size(), 0); + EXPECT_TRUE(details.begin()->first.empty()); + EXPECT_EQ(details.begin()->second.progress, Progress::SYNC_FINISH); + EXPECT_EQ(details.begin()->second.code, ProgressCode::UNKNOWN_ERROR); + }; + + RdbService::Option option; + option.seqNum = 1; + auto proxy = std::static_pointer_cast(service); + ASSERT_NE(proxy, nullptr); + proxy->syncCallbacks_.Insert(option.seqNum, callback); + proxy->OnRemoteDeadSyncComplete(); +} +} // namespace Test \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_sql_utils_test.cpp b/relational_store/test/native/rdb/unittest/rdb_sql_utils_test.cpp index b6578623..6ef1d5f6 100644 --- a/relational_store/test/native/rdb/unittest/rdb_sql_utils_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_sql_utils_test.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#define LOG_TAG "RdbSqlUtilsTest" #include "rdb_sql_utils.h" #include @@ -22,11 +23,14 @@ #include "grd_type_export.h" #include "rd_utils.h" +#include "logger.h" #include "sqlite_sql_builder.h" #include "values_buckets.h" +#include "rdb_predicates.h" using namespace testing::ext; using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; class RdbSqlUtilsTest : public testing::Test { public: @@ -61,23 +65,172 @@ HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_Test_001, TestSize.Level1) } /** - * @tc.name: RdbStore_UpdateSqlBuilder_001 - * @tc.desc: test RdbStore UpdateSqlBuilder + * @tc.name: RdbStore_GetInsertSqlInfo_001 + * @tc.desc: test RdbStore GetInsertSqlInfo * @tc.type: FUNC */ -HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_UpdateSqlBuilder_001, TestSize.Level1) +HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_GetInsertSqlInfo_001, TestSize.Level1) { ValuesBucket values; values.PutString("name", std::string("zhangsan")); values.PutInt("age", 20); values.PutDouble("salary", 300.5); + std::pair result = RdbSqlUtils::GetInsertSqlInfo("", values, ConflictResolution::ON_CONFLICT_NONE); + EXPECT_EQ(result.first, E_EMPTY_TABLE_NAME); +} + +/** + * @tc.name: RdbStore_GetInsertSqlInfo_002 + * @tc.desc: test RdbStore GetInsertSqlInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_GetInsertSqlInfo_002, TestSize.Level1) +{ + ValuesBucket values; + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + ValuesBucket emptyValues; + + std::pair result = + RdbSqlUtils::GetInsertSqlInfo("temp", emptyValues, ConflictResolution::ON_CONFLICT_NONE); + EXPECT_EQ(result.first, E_EMPTY_VALUES_BUCKET); +} + +/** + * @tc.name: RdbStore_GetInsertSqlInfo_003 + * @tc.desc: test RdbStore GetInsertSqlInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_GetInsertSqlInfo_003, TestSize.Level1) +{ + ValuesBucket values; + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + + std::pair result = + RdbSqlUtils::GetInsertSqlInfo("temp", values, ConflictResolution::ON_CONFLICT_NONE); + LOG_INFO("INSERT SQL is %{public}s", result.second.sql.c_str()); + EXPECT_EQ(result.first, E_OK); +} + +/** + * @tc.name: RdbStore_GetInsertSqlInfo_004 + * @tc.desc: test RdbStore GetInsertSqlInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_GetInsertSqlInfo_004, TestSize.Level1) +{ + ValuesBucket values; + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + + AssetValue assetVal; + assetVal.id = "123"; + assetVal.name = "kkk"; + std::vector assets; + assets.emplace_back(assetVal); + + ValueObject vo(assets); + values.Put("kkk", vo); + std::pair result = + RdbSqlUtils::GetInsertSqlInfo("temp", values, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(result.first, E_INVALID_ARGS); +} + +/** + * @tc.name: RdbStore_GetUpdateSqlInfo_001 + * @tc.desc: test RdbStore GetUpdateSqlInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_GetUpdateSqlInfo_001, TestSize.Level1) +{ + std::vector returningFields; + RdbPredicates predicates(""); + ValuesBucket bucketValues; + bucketValues.PutString("name", std::string("zhangsan")); + bucketValues.PutInt("age", 20); + bucketValues.PutDouble("salary", 300.5); + std::vector emptyValues; + std::pair result = RdbSqlUtils::GetUpdateSqlInfo( + predicates, bucketValues, ConflictResolution::ON_CONFLICT_NONE, returningFields); + EXPECT_EQ(result.first, E_EMPTY_TABLE_NAME); +} - std::vector bindArgs; - std::string updateSql = SqliteSqlBuilder::BuildUpdateString(values, "test", std::vector{ "19" }, "", - "age = ?", "", "", INT_MIN, INT_MIN, bindArgs, ConflictResolution::ON_CONFLICT_NONE); - EXPECT_EQ(updateSql, "UPDATE test SET age=?,name=?,salary=? WHERE age = ?"); +/** + * @tc.name: RdbStore_GetUpdateSqlInfo_002 + * @tc.desc: test RdbStore GetUpdateSqlInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_GetUpdateSqlInfo_002, TestSize.Level1) +{ + std::vector returningFields; + RdbPredicates predicates("temp"); + ValuesBucket bucketValues; + bucketValues.PutString("name", std::string("zhangsan")); + bucketValues.PutInt("age", 20); + bucketValues.PutDouble("salary", 300.5); + ValuesBucket emptyBucketValues; + std::vector emptyValues; - updateSql = SqliteSqlBuilder::BuildUpdateString(values, "test", std::vector{}, "", "", "", "", - INT_MIN, INT_MIN, bindArgs, ConflictResolution::ON_CONFLICT_NONE); - EXPECT_EQ(updateSql, "UPDATE test SET age=?,name=?,salary=?"); + std::pair result = RdbSqlUtils::GetUpdateSqlInfo( + predicates, emptyBucketValues, ConflictResolution::ON_CONFLICT_NONE, returningFields); + EXPECT_EQ(result.first, E_EMPTY_VALUES_BUCKET); } + +/** + * @tc.name: RdbStore_GetUpdateSqlInfo_003 + * @tc.desc: test RdbStore GetUpdateSqlInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_GetUpdateSqlInfo_003, TestSize.Level1) +{ + std::vector returningFields; + RdbPredicates predicates("temp"); + ValuesBucket bucketValues; + bucketValues.PutString("name", std::string("zhangsan")); + bucketValues.PutInt("age", 20); + bucketValues.PutDouble("salary", 300.5); + std::vector values; + ValueObject object; + values.push_back(object); + predicates.EqualTo("name", "wangwu"); + predicates.SetBindArgs(values); + std::pair result = RdbSqlUtils::GetUpdateSqlInfo( + predicates, bucketValues, ConflictResolution::ON_CONFLICT_NONE, returningFields); + LOG_INFO("UPDATE SQL is %{public}s", result.second.sql.c_str()); + EXPECT_EQ(result.first, E_OK); +} + +/** + * @tc.name: RdbStore_GetDeleteSqlInfo_001 + * @tc.desc: test RdbStore GetDeleteSqlInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqlUtilsTest, RdbSqlUtils_GetDeleteSqlInfo_001, TestSize.Level1) +{ + std::vector returningFields; + RdbPredicates predicates(""); + std::pair result = RdbSqlUtils::GetDeleteSqlInfo(predicates, returningFields); + EXPECT_EQ(result.first, E_EMPTY_TABLE_NAME); +} + +/** + * @tc.name: RdbStore_GetDeleteSqlInfo_002 + * @tc.desc: test RdbStore GetDeleteSqlInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqlUtilsTest, GetDeleteSqlInfo_002, TestSize.Level1) +{ + std::vector returningFields; + std::vector emptyValues; + RdbPredicates predicates("temp"); + predicates.EqualTo("name", "wangwu"); + predicates.SetBindArgs(emptyValues); + std::pair result = + RdbSqlUtils::GetDeleteSqlInfo(predicates, returningFields); + LOG_INFO("DELETE SQL is %{public}s", result.second.sql.c_str()); + EXPECT_EQ(result.first, E_OK); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_sqlite_shared_result_set_test.cpp b/relational_store/test/native/rdb/unittest/rdb_sqlite_shared_result_set_test.cpp index 5ac955a2..e1d387a4 100644 --- a/relational_store/test/native/rdb/unittest/rdb_sqlite_shared_result_set_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_sqlite_shared_result_set_test.cpp @@ -15,7 +15,9 @@ #include +#include #include +#include #include "common.h" #include "rdb_errno.h" @@ -29,6 +31,8 @@ using namespace testing::ext; using namespace OHOS::NativeRdb; using Asset = ValueObject::Asset; using Assets = ValueObject::Assets; +using ValueObjects = std::vector; +using Time = std::chrono::steady_clock::time_point; class RdbSqliteSharedResultSetTest : public testing::Test { public: static void SetUpTestCase(void); @@ -117,14 +121,14 @@ void RdbSqliteSharedResultSetTest::GenerateDefaultTable() values.PutBlob("data4", std::vector{ 66 }); // set uint8_t value 66 values.Put("data5", asset); values.Put("data6", assets); - values.Put("data7", std::vector(1, 0.5)); // set float value 0.5 + values.Put("data7", std::vector(1, 0.5)); // set float value 0.5 values.Put("data8", BigInteger(0)); store->Insert(id, "test", values); values.Clear(); values.PutInt("id", 2); // set int value 2 values.PutString("data1", std::string("2")); - values.PutInt("data2", -5); // set int value -5 + values.PutInt("data2", -5); // set int value -5 values.PutDouble("data3", 2.5); // set float value 2.5 values.PutBlob("data4", std::vector{}); store->Insert(id, "test", values); @@ -132,7 +136,7 @@ void RdbSqliteSharedResultSetTest::GenerateDefaultTable() values.Clear(); values.PutInt("id", 3); // set int value 3 values.PutString("data1", std::string("hello world")); - values.PutInt("data2", 3); // set int value 3 + values.PutInt("data2", 3); // set int value 3 values.PutDouble("data3", 1.8); // set float value 1.8 values.PutBlob("data4", std::vector{}); store->Insert(id, "test", values); @@ -1643,4 +1647,51 @@ HWTEST_F(RdbSqliteSharedResultSetTest, Sqlite_Shared_Result_Set_039, TestSize.Le rstSet->GetColumnType(8, colType); EXPECT_EQ(colType, ColumnType::TYPE_NULL); rstSet->Close(); +} + +/** + * @tc.name: Sqlite_Shared_Result_Set_003 + * @tc.desc: Abnormal testCase of PrepareStep + * @tc.type: FUNC + */ +HWTEST_F(RdbSqliteSharedResultSetTest, SqliteSharedResultSet_003, TestSize.Level2) +{ + ValueObjects values = {}; + Time start = std::chrono::steady_clock::now(); + auto sqliteSharedRst = std::make_shared( + start, nullptr, SqliteSharedOpenCallback::CREATE_TABLE_TEST, values, DATABASE_NAME); + auto res = sqliteSharedRst->PrepareStep(); + ASSERT_EQ(res.first, nullptr); + EXPECT_EQ(res.second, E_ALREADY_CLOSED); +} + +/** + * @tc.name: Sqlite_Shared_Result_Set_004 + * @tc.desc: Abnormal testCase of GetColumnNames + * @tc.type: FUNC + */ +HWTEST_F(RdbSqliteSharedResultSetTest, SqliteSharedResultSet_004, TestSize.Level2) +{ + ValueObjects values = {}; + Time start = std::chrono::steady_clock::now(); + auto sqliteSharedRst = std::make_shared( + start, nullptr, SqliteSharedOpenCallback::CREATE_TABLE_TEST, values, DATABASE_NAME); + auto res = sqliteSharedRst->GetColumnNames(); + EXPECT_EQ(res.first, E_ALREADY_CLOSED); + EXPECT_TRUE(res.second.empty()); +} + +/** + * @tc.name: Sqlite_Shared_Result_Set_005 + * @tc.desc: Abnormal testCase of OnGo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqliteSharedResultSetTest, SqliteSharedResultSet_005, TestSize.Level2) +{ + ValueObjects values = {}; + Time start = std::chrono::steady_clock::now(); + auto sqliteSharedRst = std::make_shared( + start, nullptr, SqliteSharedOpenCallback::CREATE_TABLE_TEST, values, DATABASE_NAME); + auto res = sqliteSharedRst->OnGo(0, 0); + EXPECT_EQ(res, E_ALREADY_CLOSED); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp b/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp index f6b63608..863bfd4d 100644 --- a/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp @@ -2150,22 +2150,22 @@ HWTEST_F(RdbStepResultSetTest, Abnormal_CacheResultSet004, TestSize.Level1) } /** - * @tc.name: Abnormal_CacheResultSet004 + * @tc.name: Invalid_TableName * @tc.desc: Abnormal testcase of CacheResultSet, if CacheResultSet is Empty * @tc.type: FUNC */ HWTEST_F(RdbStepResultSetTest, Invalid_TableName, TestSize.Level1) { - auto sql = "create table if not exists 'table_-1' (id INTEGER PRIMARY KEY AUTOINCREMENT)"; + auto sql = "create table if not exists 'test_name' (id INTEGER PRIMARY KEY AUTOINCREMENT)"; auto ret = store->ExecuteSql(sql); EXPECT_EQ(E_OK, ret); int64_t rowId = 0; ValuesBucket bucket{}; bucket.Put("id", 1); - ret = store->Insert(rowId, "'table_-1'", bucket); + ret = store->Insert(rowId, "test_name", bucket); EXPECT_EQ(E_OK, ret); EXPECT_EQ(rowId, 1); - AbsRdbPredicates predicates("table_-1"); + AbsRdbPredicates predicates("test_name where id = 1"); auto resultSet = store->Query(predicates, {}); EXPECT_NE(resultSet, nullptr); auto rowCount = 0; diff --git a/relational_store/test/native/rdb/unittest/rdb_store_backup_restore_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_backup_restore_test.cpp index 67efdc0a..f41531b7 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_backup_restore_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_backup_restore_test.cpp @@ -320,7 +320,7 @@ HWTEST_F(RdbStoreBackupRestoreTest, Rdb_BackupRestoreTest_005, TestSize.Level2) store = nullptr; CorruptDoubleWriteStore(); store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); + ASSERT_EQ(errCode, E_OK); int deletedRows = 0; ret = store->Delete(deletedRows, "test", "id = 1"); diff --git a/relational_store/test/native/rdb/unittest/rdb_store_config_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_config_test.cpp index ecdbac62..3f9b3250 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_config_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_config_test.cpp @@ -1276,4 +1276,37 @@ HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_038, TestSize.Level2) resultSet1->GoToNextRow(); resultSet1->GetString(1, strValue1); EXPECT_EQ(strValue1, "张三"); +} + +/* * + * @tc.name: RdbStoreConfigGetEnableSemanticIndex_001 + * @tc.desc: test RdbStoreConfigGetEnableSemanticIndex + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_039, TestSize.Level2) +{ + const std::string dbPath = RDB_TEST_PATH + "config_test.db"; + RdbStoreConfig config(dbPath); + + bool ret = config.GetEnableSemanticIndex(); + EXPECT_EQ(ret, false); +} + +/* * + * @tc.name: RdbStoreConfigSetEnableSemanticIndex_001 + * @tc.desc: test RdbStoreConfigSetEnableSemanticIndex + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_040, TestSize.Level2) +{ + const std::string dbPath = RDB_TEST_PATH + "config_test.db"; + RdbStoreConfig config(dbPath); + + bool enableSemanticIndex = true; + config.SetEnableSemanticIndex(enableSemanticIndex); + EXPECT_EQ(enableSemanticIndex, config.GetEnableSemanticIndex()); + + enableSemanticIndex = false; + config.SetEnableSemanticIndex(enableSemanticIndex); + EXPECT_EQ(enableSemanticIndex, config.GetEnableSemanticIndex()); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_store_impl_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_impl_test.cpp index 1ee2e704..fa47f70e 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_impl_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_impl_test.cpp @@ -20,16 +20,17 @@ #include #include -#include "types.h" -#include "single_kvstore.h" -#include "distributed_kv_data_manager.h" #include "common.h" +#include "distributed_kv_data_manager.h" +#include "grd_api_manager.h" #include "rdb_errno.h" #include "rdb_helper.h" #include "rdb_open_callback.h" #include "relational_store_delegate.h" #include "relational_store_manager.h" +#include "single_kvstore.h" #include "sqlite_connection.h" +#include "types.h" using namespace testing::ext; using namespace OHOS::NativeRdb; @@ -491,6 +492,34 @@ HWTEST_F(RdbStoreImplTest, Rdb_SqlitConnectionTest_001, TestSize.Level2) EXPECT_NE(nullptr, connection); } +/** + * @tc.name: Rdb_RdConnectionTest_001 + * @tc.desc: The testCase of vector database for replica. + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, Rdb_RdConnectionTest_001, TestSize.Level2) +{ + if (!IsUsingArkData()) { + GTEST_SKIP() << "Current testcase is not compatible from current rdb"; + } + const std::string databaseName = RDB_TEST_PATH + "RdConnectionOpenTest.db"; + RdbStoreConfig config(databaseName); + config.SetDBType(OHOS::NativeRdb::DBType::DB_VECTOR); + RdbStoreImplTestOpenCallback helper; + int openErr = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, openErr); + EXPECT_EQ(E_OK, openErr); + + auto [errCode, connection] = Connection::Create(config, true); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(connection, nullptr); + auto [err, statement] = connection->CreateReplicaStatement("test", connection); + EXPECT_EQ(err, E_NOT_SUPPORT); + EXPECT_EQ(statement, nullptr); + EXPECT_EQ(connection->CheckReplicaForRestore(), E_NOT_SUPPORT); + RdbHelper::DeleteRdbStore(databaseName); +} + /* * * @tc.name: Rdb_ConnectionPoolTest_001 * @tc.desc: Abnormal testCase for ConfigLocale @@ -516,7 +545,7 @@ HWTEST_F(RdbStoreImplTest, Rdb_ConnectionPoolTest_001, TestSize.Level2) auto connection = connectionPool->AcquireConnection(true); EXPECT_NE(nullptr, connection); errCode = connectionPool->ConfigLocale("AbnormalTest"); - EXPECT_EQ(OHOS::NativeRdb::E_DATABASE_BUSY, errCode); + EXPECT_EQ(OHOS::NativeRdb::E_INVALID_ARGS_NEW, errCode); store = nullptr; RdbHelper::DeleteRdbStore(DATABASE_NAME); @@ -584,7 +613,7 @@ HWTEST_F(RdbStoreImplTest, Rdb_ConnectionPoolTest_0023, TestSize.Level2) // newPath == currentPath, writeConnectionUsed == true auto connection = connectionPool->AcquireConnection(false); - SlaveStatus curStatus; + std::shared_ptr curStatus = std::make_shared(SlaveStatus::UNDEFINED); errCode = connectionPool->ChangeDbFileForRestore(newPath, backupPath, newKey, curStatus); EXPECT_EQ(E_ERROR, errCode); connection = nullptr; @@ -597,6 +626,58 @@ HWTEST_F(RdbStoreImplTest, Rdb_ConnectionPoolTest_0023, TestSize.Level2) EXPECT_EQ(E_ERROR, errCode); } +/* * + * @tc.name: Rdb_ConnectionPoolTest_004 + * @tc.desc: Abnormal testCase for ReopenConns + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, Rdb_ConnectionPoolTest_004, TestSize.Level2) +{ + const std::string databaseName = RDB_TEST_PATH + "ConnectionTest004.db"; + int errCode = E_OK; + RdbStoreConfig config(databaseName); + config.SetReadConSize(1); + config.SetStorageMode(StorageMode::MODE_DISK); + auto connectionPool = ConnectionPool::Create(config, errCode); + ASSERT_NE(nullptr, connectionPool); + EXPECT_EQ(E_OK, errCode); + + config.SetReadConSize(65); + EXPECT_NE(E_OK, connectionPool->ReopenConns()); +} + +/* * + * @tc.name: Rdb_ConnectionPoolTest_005 + * @tc.desc: Abnormal repair when pool create fails + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, Rdb_ConnectionPoolTest_005, TestSize.Level2) +{ + const std::string databaseName = RDB_TEST_PATH + "ConnectionTest005.db"; + RdbHelper::DeleteRdbStore(databaseName); + int errCode = E_OK; + RdbStoreConfig config(databaseName); + config.SetReadConSize(1); + config.SetStorageMode(StorageMode::MODE_DISK); + config.SetHaMode(HAMode::MAIN_REPLICA); + + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + store->ExecuteSql(CREATE_TABLE_TEST); + store = nullptr; + + auto connectionPool = ConnectionPool::Create(config, errCode); + ASSERT_NE(nullptr, connectionPool); + EXPECT_EQ(E_OK, errCode); + auto connection = connectionPool->AcquireConnection(false); + ASSERT_NE(nullptr, connection); + + config.SetReadConSize(128); + EXPECT_EQ(E_OK, connection->Repair(config)); + RdbHelper::DeleteRdbStore(databaseName); +} + HWTEST_F(RdbStoreImplTest, NotifyDataChangeTest_001, TestSize.Level2) { const std::string DATABASE_NAME = RDB_TEST_PATH + "SqlitConnectionOpenTest.db"; @@ -1079,13 +1160,13 @@ HWTEST_F(RdbStoreImplTest, CreateTransaction_004, TestSize.Level1) } /* * - * @tc.name: BatchInsertWithConflictResolution_001 - * @tc.desc: BatchInsertWithConflictResolution when violation the unique constraint. + * @tc.name: BatchInsert_001 + * @tc.desc: BatchInsert when violation the unique constraint. * @tc.type: FUNC */ -HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_001, TestSize.Level1) +HWTEST_F(RdbStoreImplTest, BatchInsert_001, TestSize.Level1) { - std::string tableName = "BatchInsertWithConflictResolutionTest"; + std::string tableName = "BatchInsertTest"; store_->Execute("DROP TABLE IF EXISTS " + tableName); auto res = store_->Execute("CREATE TABLE " + tableName + " (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)"); @@ -1104,27 +1185,27 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_001, TestSize.Level auto result = store_->Insert(tableName, row); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 5); @@ -1136,13 +1217,13 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_001, TestSize.Level } /* * - * @tc.name: BatchInsertWithConflictResolution_002 - * @tc.desc: BatchInsertWithConflictResolution when violation the not null constraint. + * @tc.name: BatchInsert_002 + * @tc.desc: BatchInsert when violation the not null constraint. * @tc.type: FUNC */ -HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_002, TestSize.Level1) +HWTEST_F(RdbStoreImplTest, BatchInsert_002, TestSize.Level1) { - std::string tableName = "BatchInsertWithConflictResolutionTest"; + std::string tableName = "BatchInsertTest"; store_->Execute("DROP TABLE IF EXISTS " + tableName); auto res = store_->Execute("CREATE TABLE " + tableName + " (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)"); @@ -1155,27 +1236,27 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_002, TestSize.Level row.Put("name", i == 2 ? ValueObject() : "Jim"); rows.Put(row); } - auto result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); @@ -1187,13 +1268,13 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_002, TestSize.Level } /* * - * @tc.name: BatchInsertWithConflictResolution_003 - * @tc.desc: BatchInsertWithConflictResolution when violation the PRIMARY constraint. + * @tc.name: BatchInsert_003 + * @tc.desc: BatchInsert when violation the PRIMARY constraint. * @tc.type: FUNC */ -HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_003, TestSize.Level1) +HWTEST_F(RdbStoreImplTest, BatchInsert_003, TestSize.Level1) { - std::string tableName = "BatchInsertWithConflictResolutionTest"; + std::string tableName = "BatchInsertTest"; store_->Execute("DROP TABLE IF EXISTS " + tableName); auto res = store_->Execute("CREATE TABLE " + tableName + " (id TEXT PRIMARY KEY, name TEXT NOT NULL)"); @@ -1212,27 +1293,27 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_003, TestSize.Level auto result = store_->Insert(tableName, row); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 5); @@ -1244,13 +1325,13 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_003, TestSize.Level } /* * - * @tc.name: BatchInsertWithConflictResolution_004 - * @tc.desc: BatchInsertWithConflictResolution when violation the check constraint. + * @tc.name: BatchInsert_004 + * @tc.desc: BatchInsert when violation the check constraint. * @tc.type: FUNC */ -HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_004, TestSize.Level1) +HWTEST_F(RdbStoreImplTest, BatchInsert_004, TestSize.Level1) { - std::string tableName = "BatchInsertWithConflictResolutionTest"; + std::string tableName = "BatchInsertTest"; store_->Execute("DROP TABLE IF EXISTS " + tableName); auto res = store_->Execute( "CREATE TABLE " + tableName + " (id INTEGER PRIMARY KEY CHECK (id >= 3 OR id <= 1), name TEXT NOT NULL)"); @@ -1263,27 +1344,27 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_004, TestSize.Level row.Put("name", "Jim"); rows.Put(row); } - auto result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); @@ -1295,13 +1376,13 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_004, TestSize.Level } /* * - * @tc.name: BatchInsertWithConflictResolution_005 - * @tc.desc: BatchInsertWithConflictResolution when busy. + * @tc.name: BatchInsert_005 + * @tc.desc: BatchInsert when busy. * @tc.type: FUNC */ -HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_005, TestSize.Level1) +HWTEST_F(RdbStoreImplTest, BatchInsert_005, TestSize.Level1) { - std::string tableName = "BatchInsertWithConflictResolutionTest"; + std::string tableName = "BatchInsertTest"; store_->Execute("DROP TABLE IF EXISTS " + tableName); auto res = store_->Execute( "CREATE TABLE " + tableName + " (id INTEGER PRIMARY KEY CHECK (id >= 3 OR id <= 1), name TEXT NOT NULL)"); @@ -1318,27 +1399,27 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_005, TestSize.Level row.Put("name", "Jim"); rows.Put(row); } - auto result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); @@ -1350,13 +1431,13 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_005, TestSize.Level } /* * - * @tc.name: BatchInsertWithConflictResolution_006 - * @tc.desc: Normal BatchInsertWithConflictResolution. + * @tc.name: BatchInsert_006 + * @tc.desc: Normal BatchInsert. * @tc.type: FUNC */ -HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_006, TestSize.Level1) +HWTEST_F(RdbStoreImplTest, BatchInsert_006, TestSize.Level1) { - std::string tableName = "BatchInsertWithConflictResolutionTest"; + std::string tableName = "BatchInsertTest"; store_->Execute("DROP TABLE IF EXISTS " + tableName); auto res = store_->Execute("CREATE TABLE " + tableName + " (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)"); @@ -1364,15 +1445,15 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_006, TestSize.Level ValuesBuckets rows; - auto result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 0); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 0); for (int i = 0; i < 5; i++) { @@ -1381,15 +1462,15 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_006, TestSize.Level rows.Put(row); } - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 5); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 5); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 5); @@ -1401,13 +1482,13 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_006, TestSize.Level } /* * - * @tc.name: BatchInsertWithConflictResolution_007 - * @tc.desc: over limit params BatchInsertWithConflictResolution. + * @tc.name: BatchInsert_007 + * @tc.desc: over limit params BatchInsert. * @tc.type: FUNC */ -HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_007, TestSize.Level1) +HWTEST_F(RdbStoreImplTest, BatchInsert_007, TestSize.Level1) { - std::string tableName = "BatchInsertWithConflictResolutionTest"; + std::string tableName = "BatchInsertTest"; store_->Execute("DROP TABLE IF EXISTS " + tableName); auto res = store_->Execute("CREATE TABLE " + tableName + " (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)"); @@ -1422,27 +1503,27 @@ HWTEST_F(RdbStoreImplTest, BatchInsertWithConflictResolution_007, TestSize.Level row.Put("name", "Jim"); rows.Put(row); } - auto result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = store_->BatchInsertWithConflictResolution(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = store_->BatchInsert(tableName, rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); @@ -1545,4 +1626,214 @@ HWTEST_F(RdbStoreImplTest, RdbStore_Crypt_001, TestSize.Level1) rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); EXPECT_EQ(errCode, E_SQLITE_CORRUPT); -} \ No newline at end of file +} + +/** + * @tc.name: RdbStore_ClearDirtyLog_001 + * @tc.desc: test RdbStore ClearDirtyLog + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, RdbStore_ClearDirtyLog_001, TestSize.Level1) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME); + config.SetBundleName(""); + config.SetEnableSemanticIndex(true); + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + ASSERT_NE(store, nullptr); + errCode = store->ExecuteSql(CREATE_TABLE_TEST); + EXPECT_EQ(errCode, E_OK); + errCode = store->CleanDirtyLog("test", 0); + EXPECT_EQ(errCode, E_OK); + errCode = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(errCode, E_OK); +} + +/** + * @tc.name: RdbStore_ConfigLocale_001 + * @tc.desc: test RdbStore ConfigLocale + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, RdbStore_ConfigLocale_001, TestSize.Level1) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME); + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + ASSERT_NE(store, nullptr); + errCode = store->ExecuteSql("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, " + "data2 INTEGER);"); + EXPECT_EQ(errCode, E_OK); + errCode = store->ConfigLocale("111"); + EXPECT_EQ(errCode, E_INVALID_ARGS_NEW); + int64_t id; + ValuesBucket valuesBucket; + valuesBucket.PutString("data1", "张三"); + valuesBucket.PutInt("data2", 20); + errCode = store->Insert(id, "test1", valuesBucket); + EXPECT_EQ(errCode, E_OK); + + ValuesBucket valuesBucket1; + valuesBucket1.PutString("data1", "李四"); + valuesBucket1.PutInt("data2", 20); + errCode = store->Insert(id, "test1", valuesBucket1); + EXPECT_EQ(errCode, E_OK); + + std::vector columns; + AbsRdbPredicates predicates("test1"); + predicates.OrderByAsc("data1 COLLATE LOCALES"); + std::shared_ptr resultSet = store->Query(predicates, columns); + ASSERT_NE(resultSet, nullptr); + std::string strValue; + errCode = resultSet->GoToNextRow(); + EXPECT_EQ(errCode, E_SQLITE_ERROR); + errCode = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(errCode, E_OK); +} + +/** + * @tc.name: RdbStore_ConfigLocale_002 + * @tc.desc: test RdbStore ConfigLocale + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, RdbStore_ConfigLocale_002, TestSize.Level1) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME); + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + ASSERT_NE(store, nullptr); + errCode = store->ExecuteSql("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, " + "data2 INTEGER);"); + EXPECT_EQ(errCode, E_OK); + errCode = store->ConfigLocale("zh"); + EXPECT_EQ(errCode, E_OK); + + int64_t id; + ValuesBucket valuesBucket; + valuesBucket.PutString("data1", "张三"); + valuesBucket.PutInt("data2", 20); + errCode = store->Insert(id, "test1", valuesBucket); + + ValuesBucket valuesBucket1; + valuesBucket1.PutString("data1", "李四"); + valuesBucket1.PutInt("data2", 20); + errCode = store->Insert(id, "test1", valuesBucket1); + EXPECT_EQ(errCode, E_OK); + + std::vector columns; + AbsRdbPredicates predicates("test1"); + predicates.OrderByAsc("data1 COLLATE LOCALES"); + std::shared_ptr resultSet = store->Query(predicates, columns); + ASSERT_NE(nullptr, resultSet); + std::string strValue; + resultSet->GoToNextRow(); + resultSet->GetString(1, strValue); + EXPECT_EQ(strValue, "李四"); + + resultSet->GoToNextRow(); + resultSet->GetString(1, strValue); + EXPECT_EQ(strValue, "张三"); + errCode = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(errCode, E_OK); +} + +/** + * @tc.name: RdbStore_ConfigLocale_003 + * @tc.desc: test RdbStore ConfigLocale + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, RdbStore_ConfigLocale_003, TestSize.Level1) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME); + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + ASSERT_NE(store, nullptr); + errCode = store->ExecuteSql("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, " + "data2 INTEGER);"); + EXPECT_EQ(errCode, E_OK); + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + EXPECT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + errCode = store->ConfigLocale("zh"); + EXPECT_EQ(errCode, E_OK); + + ValuesBucket valuesBucket; + valuesBucket.PutString("data1", "张三"); + valuesBucket.PutInt("data2", 20); + auto result = transaction->Insert("test1", valuesBucket); + EXPECT_EQ(result.first, E_OK); + ValuesBucket valuesBucket1; + valuesBucket1.PutString("data1", "李四"); + valuesBucket1.PutInt("data2", 20); + result = transaction->Insert("test1", valuesBucket1); + EXPECT_EQ(result.first, E_OK); + std::vector columns; + AbsRdbPredicates predicates("test1"); + predicates.OrderByAsc("data1 COLLATE LOCALES"); + auto resultSet = transaction->QueryByStep("SELECT * FROM test1 order by data1 COLLATE LOCALES");; + ASSERT_NE(nullptr, resultSet); + std::string strValue; + resultSet->GoToNextRow(); + resultSet->GetString(1, strValue); + EXPECT_EQ(strValue, "李四"); + + resultSet->GoToNextRow(); + resultSet->GetString(1, strValue); + EXPECT_EQ(strValue, "张三"); + errCode = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(errCode, E_OK); +} +/** + * @tc.name: RdbStore_InitKnowledgeSchema_001 + * @tc.desc: test RdbStore InitKnowledgeSchema + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, RdbStore_InitKnowledgeSchema_001, TestSize.Level1) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME); + config.SetBundleName(""); + config.SetEnableSemanticIndex(true); + OHOS::DistributedRdb::RdbKnowledgeSchema schema; + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + ASSERT_NE(store, nullptr); + + errCode = store->InitKnowledgeSchema(schema); + EXPECT_EQ(errCode, E_OK); +} + +/** + * @tc.name: RdbStore_InitKnowledgeSchema_002 + * @tc.desc: test RdbStore SetKnowledgeSchema when create table + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, RdbStore_InitKnowledgeSchema_002, TestSize.Level1) +{ + store_ = nullptr; + int errCode = RdbHelper::DeleteRdbStore(DATABASE_NAME); + EXPECT_EQ(E_OK, errCode); + + RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME); + config.SetBundleName(""); + config.SetEnableSemanticIndex(true); + OHOS::DistributedRdb::RdbKnowledgeSchema schema; + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + ASSERT_NE(store, nullptr); + + std::pair ret = store->Execute(std::string(CREATE_TABLE_TEST)); + ASSERT_EQ(ret.first, E_OK); + + ret = store->Execute(std::string(CREATE_TABLE_TEST)); + ASSERT_EQ(ret.first, E_OK); +} diff --git a/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp index 71f4495c..8c28ac40 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp @@ -12,18 +12,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#define LOG_TAG "RdbRekeyTest" #include #include #include #include +#include #include #include #include +#include +#include "block_data.h" #include "common.h" #include "file_ex.h" +#include "logger.h" #include "rdb_errno.h" #include "rdb_helper.h" #include "rdb_open_callback.h" @@ -32,6 +36,7 @@ using namespace testing::ext; using namespace OHOS::NativeRdb; +using namespace OHOS::Rdb; class RdbRekeyTest : public testing::Test { public: static void SetUpTestCase(); @@ -130,7 +135,7 @@ std::chrono::system_clock::time_point RdbRekeyTest::GetKeyFileDate(const std::st { std::chrono::system_clock::time_point timePoint; std::string name = RemoveSuffix(dbName); - auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key"; + auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key_v1"; if (!OHOS::FileExists(keyPath)) { return timePoint; } @@ -151,7 +156,7 @@ std::chrono::system_clock::time_point RdbRekeyTest::GetKeyFileDate(const std::st bool RdbRekeyTest::ChangeKeyFileDate(const std::string &dbName, int rep) { std::string name = RemoveSuffix(dbName); - auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key"; + auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key_v1"; if (!OHOS::FileExists(keyPath)) { return false; } @@ -172,7 +177,7 @@ bool RdbRekeyTest::ChangeKeyFileDate(const std::string &dbName, int rep) bool RdbRekeyTest::SaveNewKey(const string &dbName) { std::string name = RemoveSuffix(dbName); - auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key"; + auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key_v1"; auto newKeyPath = RDB_TEST_PATH + "key/" + name + ".pub_key.new"; if (!OHOS::FileExists(keyPath)) { return false; @@ -251,7 +256,7 @@ void RdbRekeyTest::CheckQueryData(std::shared_ptr &store) */ HWTEST_F(RdbRekeyTest, Rdb_Rekey_01, TestSize.Level1) { - std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key.new"; bool isFileExists = OHOS::FileExists(keyPath); @@ -260,9 +265,6 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_01, TestSize.Level1) bool isFileDateChanged = ChangeKeyFileDate(encryptedDatabaseName, RdbRekeyTest::HOURS_EXPIRED); ASSERT_TRUE(isFileDateChanged); - auto changedDate = GetKeyFileDate(encryptedDatabaseName); - ASSERT_TRUE(std::chrono::system_clock::now() - changedDate > std::chrono::hours(RdbRekeyTest::HOURS_EXPIRED)); - RdbStoreConfig config = GetRdbConfig(RdbRekeyTest::encryptedDatabasePath); RekeyTestOpenCallback helper; int errCode = E_OK; @@ -275,8 +277,6 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_01, TestSize.Level1) isFileExists = OHOS::FileExists(newKeyPath); ASSERT_FALSE(isFileExists); - auto newDate = GetKeyFileDate(encryptedDatabaseName); - ASSERT_TRUE(std::chrono::system_clock::now() - newDate < std::chrono::seconds(2)); CheckQueryData(store); } @@ -287,7 +287,7 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_01, TestSize.Level1) */ HWTEST_F(RdbRekeyTest, Rdb_Rekey_02, TestSize.Level1) { - std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; bool isFileExists = OHOS::FileExists(keyPath); ASSERT_TRUE(isFileExists); @@ -313,7 +313,7 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_02, TestSize.Level1) */ HWTEST_F(RdbRekeyTest, Rdb_Rekey_03, TestSize.Level1) { - std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key.new"; bool isFileExists = OHOS::FileExists(keyPath); @@ -344,20 +344,15 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_03, TestSize.Level1) */ HWTEST_F(RdbRekeyTest, Rdb_Rekey_04, TestSize.Level1) { - std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key.new"; bool isFileExists = OHOS::FileExists(keyPath); ASSERT_TRUE(isFileExists); - auto keyFileDate = GetKeyFileDate(encryptedDatabaseName); - bool isFileDateChanged = ChangeKeyFileDate(encryptedDatabaseName, -RdbRekeyTest::HOURS_EXPIRED); ASSERT_TRUE(isFileDateChanged); - auto changedDate = GetKeyFileDate(encryptedDatabaseName); - ASSERT_GT(changedDate, keyFileDate); - RdbStoreConfig config = GetRdbConfig(RdbRekeyTest::encryptedDatabasePath); RekeyTestOpenCallback helper; int errCode; @@ -369,9 +364,6 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_04, TestSize.Level1) isFileExists = OHOS::FileExists(newKeyPath); ASSERT_FALSE(isFileExists); - keyFileDate = GetKeyFileDate(encryptedDatabaseName); - ASSERT_EQ(changedDate, keyFileDate); - CheckQueryData(store); } @@ -382,20 +374,15 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_04, TestSize.Level1) */ HWTEST_F(RdbRekeyTest, Rdb_Rekey_RenameFailed_05, TestSize.Level1) { - std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key.new"; bool isFileExists = OHOS::FileExists(keyPath); ASSERT_TRUE(isFileExists); - auto keyFileDate = GetKeyFileDate(encryptedDatabaseName); - bool isFileDateChanged = ChangeKeyFileDate(encryptedDatabaseName, RdbRekeyTest::HOURS_LONG_LONG_AGO); ASSERT_TRUE(isFileDateChanged); - auto changedDate = GetKeyFileDate(encryptedDatabaseName); - ASSERT_GT(keyFileDate, changedDate); - RdbStoreConfig config = GetRdbConfig(RdbRekeyTest::encryptedDatabasePath); RekeyTestOpenCallback helper; int errCode = E_OK; @@ -418,7 +405,7 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_RenameFailed_05, TestSize.Level1) */ HWTEST_F(RdbRekeyTest, Rdb_Rekey_06, TestSize.Level1) { - std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; std::string newKeyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key.new"; bool isFileExists = OHOS::FileExists(keyPath); @@ -464,7 +451,7 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_07, TestSize.Level1) ASSERT_NE(store, nullptr); ASSERT_EQ(errCode, E_OK); - std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; bool isFileExists = OHOS::FileExists(keyPath); ASSERT_TRUE(isFileExists); struct stat fileStat; @@ -510,7 +497,7 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_08, TestSize.Level1) ASSERT_NE(store, nullptr); ASSERT_EQ(errCode, E_OK); - std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; bool isFileExists = OHOS::FileExists(keyPath); ASSERT_TRUE(isFileExists); struct stat fileStat; @@ -536,4 +523,677 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_08, TestSize.Level1) } ASSERT_EQ(inodeNumber1, inodeNumber2); +} + +/** +** +* @tc.name: Rdb_Delete_Rekey_Test_009 +* @tc.desc: test rekey the encrypted database +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_009, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetAllowRebuild(false); + config.SetEncryptStatus(true); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"); + + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + RdbStoreConfig::CryptoParam cryptoParam1; + cryptoParam1.iterNum = -1; + errCode = store->Rekey(cryptoParam1); + ASSERT_EQ(errCode, E_INVALID_ARGS_NEW); + + RdbStoreConfig::CryptoParam cryptoParam2; + cryptoParam2.encryptAlgo = -1; + errCode = store->Rekey(cryptoParam2); + ASSERT_EQ(errCode, E_INVALID_ARGS_NEW); + + RdbStoreConfig::CryptoParam cryptoParam3; + cryptoParam3.hmacAlgo = -1; + errCode = store->Rekey(cryptoParam3); + ASSERT_EQ(errCode, E_INVALID_ARGS_NEW); + + RdbStoreConfig::CryptoParam cryptoParam4; + cryptoParam4.kdfAlgo = -1; + errCode = store->Rekey(cryptoParam4); + ASSERT_EQ(errCode, E_INVALID_ARGS_NEW); + + RdbStoreConfig::CryptoParam cryptoParam5; + cryptoParam5.cryptoPageSize = -1; + errCode = store->Rekey(cryptoParam5); + ASSERT_EQ(errCode, E_INVALID_ARGS_NEW); + + values.Clear(); + values.PutInt("id", 2); + values.PutString("name", std::string("lisi")); + values.PutInt("age", 19); + ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_010 +* @tc.desc: test rekey the encrypted database +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_010, TestSize.Level1) +{ + const std::string encryptedDatabaseName1 = "encrypted1.db"; + const std::string encryptedDatabasePath1 = RDB_TEST_PATH + encryptedDatabaseName1; + RdbStoreConfig config(encryptedDatabasePath1); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"); + + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan1")); + values.PutInt("age", 50); + values.PutDouble("salary", 263); + values.PutBlob("blobType", std::vector{ 1, 2, 3, 4, 5}); + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + RdbStoreConfig::CryptoParam cryptoParam; + auto isEncrypt = config.IsEncrypt(); + ASSERT_EQ(isEncrypt, false); + errCode = store->Rekey(cryptoParam); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + cryptoParam.encryptKey_ = std::vector{ 1, 2, 3, 4, 5, 6 }; + errCode = store->Rekey(cryptoParam); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + values.Clear(); + values.PutInt("id", 2); + values.PutString("name", std::string("lisi1")); + values.PutInt("age", 191); + values.PutDouble("salary", 2001.5); + values.PutBlob("blobType", std::vector{ 4, 5, 6, 7 }); + ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + + auto resultSet = store->QueryByStep("SELECT * FROM test1"); + ASSERT_NE(resultSet, nullptr); + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + ASSERT_EQ(rowCount, 2); + + ret = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_011 +* @tc.desc: test rekey other parameters +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_011, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetBundleName("com.example.test_rekey"); + config.SetEncryptStatus(true); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"); + + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("1zhangsan")); + values.PutInt("age", 118); + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + RdbStoreConfig::CryptoParam cryptoParam1; + cryptoParam1.iterNum = 500; + errCode = store->Rekey(cryptoParam1); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + RdbStoreConfig::CryptoParam cryptoParam2; + cryptoParam2.encryptAlgo = EncryptAlgo::AES_256_CBC; + errCode = store->Rekey(cryptoParam2); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + RdbStoreConfig::CryptoParam cryptoParam3; + cryptoParam3.hmacAlgo = HmacAlgo::SHA512; + errCode = store->Rekey(cryptoParam3); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + RdbStoreConfig::CryptoParam cryptoParam4; + cryptoParam4.kdfAlgo = KdfAlgo::KDF_SHA512; + errCode = store->Rekey(cryptoParam4); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + RdbStoreConfig::CryptoParam cryptoParam5; + cryptoParam5.cryptoPageSize = 2048; + errCode = store->Rekey(cryptoParam5); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + ret = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_12 +* @tc.desc: test custom encrypt rekey +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_012, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetEncryptStatus(true); + RdbStoreConfig::CryptoParam cryptoParam; + cryptoParam.encryptKey_ = std::vector{ 1, 2, 3, 4, 5, 6 }; + config.SetCryptoParam(cryptoParam); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"); + + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + RdbStoreConfig::CryptoParam newCryptoParam; + newCryptoParam.encryptKey_ = std::vector{ 6, 2, 3, 4, 5, 1 }; + errCode = store->Rekey(newCryptoParam); + ASSERT_EQ(errCode, E_OK); + + values.Clear(); + values.PutInt("id", 2); + values.PutString("name", std::string("lisi")); + values.PutInt("age", 19); + ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + + store = nullptr; + config.SetCryptoParam(newCryptoParam); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + auto resultSet = store->QueryByStep("SELECT * FROM test1"); + ASSERT_NE(resultSet, nullptr); + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + ASSERT_EQ(rowCount, 2); + + RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); +} + + +/** +* @tc.name: Rdb_Delete_Rekey_Test_013 +* @tc.desc: test rekey +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_013, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetEncryptStatus(true); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"); + + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + int changedRows; + values.Clear(); + values.PutInt("age", 30); + ret = store->Update(changedRows, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, changedRows); + + RdbStoreConfig::CryptoParam cryptoParam; + cryptoParam.encryptKey_ = std::vector{ 1, 2, 3, 4, 5, 6 }; + errCode = store->Rekey(cryptoParam); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + values.Clear(); + values.PutInt("id", 2); + values.PutString("name", std::string("lisi")); + values.PutInt("age", 19); + ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + + values.Clear(); + values.PutInt("age", 60); + ret = store->Update(changedRows, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, changedRows); + + ret = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_014 +* @tc.desc: test rekey +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_014, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetEncryptStatus(true); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"); + + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + RdbStoreConfig::CryptoParam cryptoParam; + errCode = store->Rekey(cryptoParam); + ASSERT_EQ(errCode, E_OK); + + values.Clear(); + values.PutInt("id", 2); + values.PutString("name", std::string("lisi")); + values.PutInt("age", 19); + ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + + int changedRows = 0; + AbsRdbPredicates predicates("test1"); + predicates.EqualTo("id", 1); + ret = store->Delete(changedRows, predicates); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(changedRows, 1); + + store = nullptr; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + auto resultSet = store->QueryByStep("SELECT * FROM test1"); + ASSERT_NE(resultSet, nullptr); + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + ASSERT_EQ(rowCount, 1); +} + + +/** +* @tc.name: Rdb_Delete_Rekey_Test_015 +* @tc.desc: test rekey +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_015, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetEncryptStatus(true); + RdbStoreConfig::CryptoParam cryptoParam; + cryptoParam.encryptKey_ = std::vector{ 1, 2, 3, 4, 5, 6 }; + config.SetCryptoParam(cryptoParam); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + RdbHelper::DeleteRdbStore(config); + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER)"); + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + RdbStoreConfig::CryptoParam newCryptoParam; + errCode = store->Rekey(newCryptoParam); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + values.Clear(); + values.PutInt("id", 2); + values.PutString("name", std::string("lisi")); + values.PutInt("age", 19); + ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + + store = nullptr; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + auto resultSet = store->QueryByStep("SELECT * FROM test1"); + ASSERT_NE(resultSet, nullptr); + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + ASSERT_EQ(rowCount, 2); + + RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_016 +* @tc.desc: test transaction rekey +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_016, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetAllowRebuild(false); + config.SetEncryptStatus(true); + RdbStoreConfig::CryptoParam cryptoParam; + cryptoParam.encryptKey_ = std::vector{ 1, 2, 3, 4, 5, 6 }; + config.SetCryptoParam(cryptoParam); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + RdbHelper::DeleteRdbStore(config); + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"); + + auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + ASSERT_EQ(result.first, E_OK); + ASSERT_EQ(1, result.second); + + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; + bool isFileExists = OHOS::FileExists(keyPath); + ASSERT_FALSE(isFileExists); + + RdbStoreConfig::CryptoParam newCryptoParam; + newCryptoParam.encryptKey_ = std::vector{ 6, 5, 4, 3, 2, 1 }; + errCode = store->Rekey(newCryptoParam); + ASSERT_EQ(errCode, E_DATABASE_BUSY); + + result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ASSERT_EQ(result.first, E_OK); + ASSERT_EQ(2, result.second); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + ASSERT_NE(resultSet, nullptr); + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + ASSERT_EQ(rowCount, 2); + + ret = transaction->Commit(); + ASSERT_EQ(ret, E_OK); + + resultSet = store->QueryByStep("SELECT * FROM test"); + ASSERT_NE(resultSet, nullptr); + resultSet->GetRowCount(rowCount); + EXPECT_EQ(rowCount, 2); + + RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_017 +* @tc.desc: test transaction rekey +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_017, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetAllowRebuild(false); + config.SetEncryptStatus(true); + RdbStoreConfig::CryptoParam cryptoParam; + config.SetCryptoParam(cryptoParam); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + RdbHelper::DeleteRdbStore(config); + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + ASSERT_EQ(result.first, E_OK); + ASSERT_EQ(1, result.second); + + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key_v1"; + bool isFileExists = OHOS::FileExists(keyPath); + ASSERT_TRUE(isFileExists); + + RdbStoreConfig::CryptoParam newCryptoParam; + errCode = store->Rekey(newCryptoParam); + ASSERT_EQ(errCode, E_DATABASE_BUSY); + + result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ASSERT_EQ(result.first, E_OK); + ASSERT_EQ(2, result.second); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + ASSERT_NE(resultSet, nullptr); + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + ASSERT_EQ(rowCount, 2); + + ret = transaction->Commit(); + ASSERT_EQ(ret, E_OK); + + resultSet = store->QueryByStep("SELECT * FROM test"); + ASSERT_NE(resultSet, nullptr); + resultSet->GetRowCount(rowCount); + EXPECT_EQ(rowCount, 2); + + RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_018 +* @tc.desc: rekey test +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_018, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetEncryptStatus(true); + config.SetReadOnly(true); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + RdbStoreConfig::CryptoParam cryptoParam1; + + errCode = store->Rekey(cryptoParam1); + ASSERT_EQ(errCode, E_NOT_SUPPORT); + + int ret = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_019 +* @tc.desc: mutltiThread rekey test +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_019, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + RdbStoreConfig::CryptoParam cryptoParam; + cryptoParam.encryptKey_ = std::vector{ 1, 2, 3, 4, 5, 6 }; + config.SetCryptoParam(cryptoParam); + config.SetBundleName("com.example.test_rekey"); + config.SetEncryptStatus(true); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + auto blockResult = std::make_shared>(3, false); + std::thread thread([store, blockResult]() { + RdbStoreConfig::CryptoParam cryptoParam; + cryptoParam.encryptKey_ = std::vector{ 6, 2, 3, 4, 5, 1 }; + int ret1 = store->Rekey(cryptoParam); + LOG_INFO("Rdb_Rekey_020 thread Rekey finish, code:%{public}d", ret1); + blockResult->SetValue(true); + }); + thread.detach(); + RdbStoreConfig::CryptoParam cryptoParam2; + cryptoParam2.encryptKey_ = std::vector{ 6, 5, 3, 4, 2, 1 }; + int ret2 = store->Rekey(cryptoParam2); + LOG_INFO("Rdb_Rekey_020 main Rekey finish, code:%{public}d", ret2); + EXPECT_TRUE(blockResult->GetValue()); + + store->ExecuteSql("CREATE TABLE IF NOT EXISTS test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"); + + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan1")); + values.PutInt("age", 50); + values.PutDouble("salary", 263); + values.PutBlob("blobType", std::vector{ 1, 2, 3, 4, 5 }); + int ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + int changedRows; + values.Clear(); + values.PutInt("age", 30); + ret = store->Update(changedRows, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, changedRows); + + auto resultSet = store->QueryByStep("SELECT * FROM test1"); + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + ASSERT_EQ(rowCount, 1); +} + +/** +* @tc.name: Rdb_UnpackV2_Test_001 +* @tc.desc: unpackV2 test +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, UnpackV2Test, TestSize.Level1) +{ + RdbSecurityManager manager; + std::vector content; + auto result = manager.UnpackV2(content); + EXPECT_FALSE(result.first); + EXPECT_EQ(result.second.nonceValue.size(), 0); + EXPECT_EQ(result.second.encryptValue.size(), 0); + + uint32_t magicNum = RdbSecretContent::MAGIC_NUMBER_V2; + char* magicPtr = reinterpret_cast(&magicNum); + content.insert(content.end(), magicPtr, magicPtr + sizeof(magicNum)); + + const size_t nonceSize = RdbSecretContent::NONCE_VALUE_SIZE - 1; + std::vector nonce(nonceSize, 'N'); + content.insert(content.end(), nonce.begin(), nonce.end()); + + result = manager.UnpackV2(content); + + EXPECT_FALSE(result.first); + EXPECT_EQ(result.second.nonceValue.size(), 0); + EXPECT_EQ(result.second.encryptValue.size(), 0); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_store_subscribe_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_subscribe_test.cpp index debd883b..9f7c8097 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_subscribe_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_subscribe_test.cpp @@ -17,6 +17,7 @@ #include #include +#include "block_data.h" #include "common.h" #include "rdb_errno.h" #include "rdb_helper.h" @@ -45,6 +46,22 @@ public: private: CheckOnChangeFunc checkOnChangeFunc_; }; +class LocalShareObserver : public RdbStoreObserver { +public: + explicit LocalShareObserver(std::function func) : callback_(func) + { + } + void OnChange(const std::vector &devices){}; + void OnChange() + { + if (callback_ != nullptr) { + callback_(); + } + }; + +private: + std::function callback_; +}; class StatisticsObserver : public SqlObserver { public: @@ -186,7 +203,6 @@ std::shared_ptr RdbStoreSubTest::CreateRDB(int version) Callback helper; int errCode = E_OK; std::shared_ptr store = RdbHelper::GetRdbStore(config, version, helper, errCode); - EXPECT_NE(store, nullptr); return store; } @@ -223,11 +239,11 @@ void RdbStoreSubTest::RegisterCheckUpdateCallback(const std::vectorSubscribe({ SubscribeMode::REMOTE, "observer" }, observer_.get()); + auto status = store->Subscribe({ SubscribeMode::REMOTE, "observer" }, observer_); EXPECT_EQ(status, E_OK); - status = store->UnSubscribe({ SubscribeMode::REMOTE, "observer" }, observer_.get()); + status = store->UnSubscribe({ SubscribeMode::REMOTE, "observer" }, observer_); EXPECT_EQ(status, E_OK); } @@ -240,11 +256,11 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeRemote, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeCloud, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; - auto status = store->Subscribe({ SubscribeMode::CLOUD, "observer" }, observer_.get()); + auto status = store->Subscribe({ SubscribeMode::CLOUD, "observer" }, observer_); EXPECT_EQ(status, E_OK); - status = store->UnSubscribe({ SubscribeMode::CLOUD, "observer" }, observer_.get()); + status = store->UnSubscribe({ SubscribeMode::CLOUD, "observer" }, observer_); EXPECT_EQ(status, E_OK); } @@ -257,11 +273,11 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeCloud, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeCloudDetail, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; - auto status = store->Subscribe({ SubscribeMode::CLOUD_DETAIL, "observer" }, observer_.get()); + auto status = store->Subscribe({ SubscribeMode::CLOUD_DETAIL, "observer" }, observer_); EXPECT_EQ(status, E_OK); - status = store->UnSubscribe({ SubscribeMode::CLOUD_DETAIL, "observer" }, observer_.get()); + status = store->UnSubscribe({ SubscribeMode::CLOUD_DETAIL, "observer" }, observer_); EXPECT_EQ(status, E_OK); } @@ -274,12 +290,12 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeCloudDetail, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocal, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; - auto status = store->Subscribe({ SubscribeMode::LOCAL, "observer1" }, observer_.get()); - store->Subscribe({ SubscribeMode::LOCAL, "observer1" }, observer_.get()); + auto status = store->Subscribe({ SubscribeMode::LOCAL, "observer1" }, observer_); + store->Subscribe({ SubscribeMode::LOCAL, "observer1" }, observer_); EXPECT_EQ(status, E_OK); - store->Subscribe({ SubscribeMode::LOCAL, "observer2" }, observer_.get()); + store->Subscribe({ SubscribeMode::LOCAL, "observer2" }, observer_); EXPECT_EQ(status, E_OK); status = store->Notify("observer1"); @@ -292,9 +308,9 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocal, TestSize.Level1) int count; resultSet->GetRowCount(count); EXPECT_EQ(observer_->count, count); - status = store->UnSubscribe({ SubscribeMode::LOCAL, "nonexistent" }, observer_.get()); + status = store->UnSubscribe({ SubscribeMode::LOCAL, "nonexistent" }, observer_); EXPECT_EQ(status, E_OK); - status = store->UnSubscribe({ SubscribeMode::LOCAL, "observer1" }, observer_.get()); + status = store->UnSubscribe({ SubscribeMode::LOCAL, "observer1" }, observer_); EXPECT_EQ(status, E_OK); status = store->UnSubscribe({ SubscribeMode::LOCAL, "nonexistent" }, nullptr); EXPECT_EQ(status, E_OK); @@ -305,25 +321,26 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocal, TestSize.Level1) } /** - * @tc.name: RdbStoreSubscribeLocalShared + * @tc.name: RdbStoreSubscribeLocalShared001 * @tc.desc: RdbStoreSubscribe * @tc.type: FUNC * @tc.require: * @tc.author: */ -HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared, TestSize.Level1) +HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared001, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; - auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer1" }, observer_.get()); - store->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer1" }, observer_.get()); + auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer1" }, observer_); + EXPECT_EQ(status, E_OK); + status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer1" }, observer_); EXPECT_EQ(status, E_OK); - store->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer2" }, observer_.get()); + status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "observer2" }, observer_); EXPECT_EQ(status, E_OK); - status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "nonexistent" }, observer_.get()); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "nonexistent" }, observer_); EXPECT_EQ(status, E_OK); - status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "observer1" }, observer_.get()); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "observer1" }, observer_); EXPECT_EQ(status, E_OK); status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "nonexistent" }, nullptr); EXPECT_EQ(status, E_OK); @@ -331,6 +348,181 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared, TestSize.Level1) EXPECT_EQ(status, E_OK); } +/** + * @tc.name: RdbStoreSubscribeLocalShared002 + * @tc.desc: RdbStoreSubscribe + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared002, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + auto block = std::make_shared>(5, false); + auto callback = [block]() { block->SetValue(true); }; + auto observer = std::make_shared(callback); + auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared002" }, observer); + EXPECT_EQ(status, E_OK); + status = store->Notify("RdbStoreSubscribeLocalShared002"); + EXPECT_EQ(status, E_OK); + EXPECT_TRUE(block->GetValue()); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared002" }, observer); +} + +/** + * @tc.name: RdbStoreSubscribeLocalShared003 + * @tc.desc: RdbStoreSubscribe + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared003, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + auto count = std::make_shared>(0); + auto callback = [count]() { count->fetch_add(1); }; + auto observer = std::make_shared(callback); + auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared003" }, observer); + EXPECT_EQ(status, E_OK); + status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared003" }, observer); + EXPECT_EQ(status, E_OK); + status = store->Notify("RdbStoreSubscribeLocalShared003"); + EXPECT_EQ(status, E_OK); + std::this_thread::sleep_for(std::chrono::seconds(3)); + EXPECT_EQ(count->load(), 1); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared003" }, observer); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbStoreSubscribeLocalShared004 + * @tc.desc: UnSubscribe all + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared004, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + auto count = std::make_shared>(0); + auto callback = [count]() { count->fetch_add(1); }; + auto observer1 = std::make_shared(callback); + auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared004" }, observer1); + EXPECT_EQ(status, E_OK); + auto observer2 = std::make_shared(callback); + status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared004" }, observer2); + EXPECT_EQ(status, E_OK); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared004" }, nullptr); + EXPECT_EQ(status, E_OK); + status = store->Notify("RdbStoreSubscribeLocalShared004"); + EXPECT_EQ(status, E_OK); + std::this_thread::sleep_for(std::chrono::seconds(3)); + EXPECT_EQ(count->load(), 0); +} + +/** + * @tc.name: RdbStoreSubscribeLocalShared005 + * @tc.desc: Subscribe after UnSubscribe + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared005, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + auto block = std::make_shared>(3, false); + auto callback = [block]() { block->SetValue(true); }; + auto observer = std::make_shared(callback); + auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared005" }, observer); + EXPECT_EQ(status, E_OK); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared005" }, observer); + EXPECT_EQ(status, E_OK); + status = store->Notify("RdbStoreSubscribeLocalShared005"); + EXPECT_EQ(status, E_OK); + EXPECT_FALSE(block->GetValue()); + + status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared005" }, observer); + EXPECT_EQ(status, E_OK); + block->Clear(false); + status = store->Notify("RdbStoreSubscribeLocalShared005"); + EXPECT_EQ(status, E_OK); + EXPECT_TRUE(block->GetValue()); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared005" }, nullptr); + EXPECT_EQ(status, E_OK); +} + +/** + * @tc.name: RdbStoreSubscribeLocalShared006 + * @tc.desc: Different db Subscribe same uri + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared006, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + RdbStoreConfig config(RDB_TEST_PATH + "RdbStoreSubscribeLocalShared006.db"); + config.SetBundleName("subscribe_test"); + Callback helper; + int errCode = E_ERROR; + std::shared_ptr localStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(localStore, nullptr); + ASSERT_EQ(errCode, E_OK); + + auto count = std::make_shared>(0); + auto callback = [count]() { count->fetch_add(1); }; + auto observer = std::make_shared(callback); + auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared006" }, observer); + EXPECT_EQ(status, E_OK); + status = localStore->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared006" }, observer); + EXPECT_EQ(status, E_OK); + + status = store->Notify("RdbStoreSubscribeLocalShared006"); + EXPECT_EQ(status, E_OK); + std::this_thread::sleep_for(std::chrono::seconds(3)); + EXPECT_EQ(count->load(), 1); + status = localStore->Notify("RdbStoreSubscribeLocalShared006"); + EXPECT_EQ(status, E_OK); + std::this_thread::sleep_for(std::chrono::seconds(3)); + EXPECT_EQ(count->load(), 2); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared006" }, nullptr); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(RdbHelper::DeleteRdbStore(config), E_OK); +} + +/** + * @tc.name: RdbStoreSubscribeLocalShared007 + * @tc.desc: Subscribe to the same URI with different obs, then cancel all at once + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared007, TestSize.Level1) +{ + ASSERT_NE(store, nullptr) << "store is null"; + auto count = std::make_shared>(0); + auto callback = [count]() { count->fetch_add(1); }; + auto observer1 = std::make_shared(callback); + auto status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared007" }, observer1); + EXPECT_EQ(status, E_OK); + + auto observer2 = std::make_shared(callback); + status = store->Subscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared007" }, observer2); + EXPECT_EQ(status, E_OK); + + status = store->Notify("RdbStoreSubscribeLocalShared007"); + EXPECT_EQ(status, E_OK); + std::this_thread::sleep_for(std::chrono::seconds(3)); + EXPECT_EQ(count->load(), 2); + status = store->UnSubscribe({ SubscribeMode::LOCAL_SHARED, "RdbStoreSubscribeLocalShared007" }, nullptr); + EXPECT_EQ(status, E_OK); + + status = store->Notify("RdbStoreSubscribeLocalShared007"); + EXPECT_EQ(status, E_OK); + std::this_thread::sleep_for(std::chrono::seconds(3)); + EXPECT_EQ(count->load(), 2); +} + /** * @tc.name: RdbStoreSubscribeLocalDetail001 * @tc.desc: test local observer onchange when insert data @@ -340,7 +532,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalShared, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail001, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS local_test " "(id INTEGER PRIMARY KEY AUTOINCREMENT, " @@ -392,7 +584,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail001, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail002, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_); EXPECT_EQ(status, E_OK); @@ -440,7 +632,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail002, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail003, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_); EXPECT_EQ(status, E_OK); @@ -474,7 +666,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail003, TestSize.Level1) HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail004, TestSize.Level1) { int num = 10; - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_); EXPECT_EQ(status, E_OK); @@ -517,7 +709,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail004, TestSize.Level1) HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail005, TestSize.Level1) { int num = 1; - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, observer_); EXPECT_EQ(status, E_OK); @@ -568,7 +760,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail005, TestSize.Level1) HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail006, TestSize.Level1) { int num = 20; - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS local_test2" "(id INTEGER PRIMARY KEY AUTOINCREMENT, " @@ -621,7 +813,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail006, TestSize.Level1) HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail007, TestSize.Level1) { int num = 20; - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS local_test3" "(id INTEGER PRIMARY KEY AUTOINCREMENT, " @@ -678,7 +870,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail007, TestSize.Level1) HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail008, TestSize.Level1) { int num = 20; - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS local_test4" "(id INTEGER PRIMARY KEY AUTOINCREMENT, " @@ -723,7 +915,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail008, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail009, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(observer_, nullptr) << "observer is null"; auto status = store->SubscribeObserver({ SubscribeMode::LOCAL_DETAIL, "dataChange" }, nullptr); EXPECT_EQ(status, E_OK); @@ -749,7 +941,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeLocalDetail009, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics001, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; constexpr const char *createTableTest = "CREATE TABLE IF NOT EXISTS statistics_test " "(id INTEGER PRIMARY KEY AUTOINCREMENT, " @@ -784,7 +976,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics001, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics002, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; auto status = SqlStatistic::Subscribe(sqlObserver_); EXPECT_EQ(status, E_OK); @@ -811,7 +1003,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics002, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics003, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; auto status = SqlStatistic::Subscribe(sqlObserver_); EXPECT_EQ(status, E_OK); @@ -836,7 +1028,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics003, TestSize.Level1) HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics004, TestSize.Level1) { int num = 10; - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; auto status = SqlStatistic::Subscribe(sqlObserver_); EXPECT_EQ(status, E_OK); @@ -866,7 +1058,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics004, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics005, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; auto status = SqlStatistic::Subscribe(sqlObserver_); EXPECT_EQ(status, E_OK); @@ -897,7 +1089,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics005, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics006, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; auto status = SqlStatistic::Subscribe(sqlObserver_); EXPECT_EQ(status, E_OK); @@ -917,7 +1109,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics006, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics007, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; auto status = SqlStatistic::Subscribe(sqlObserver_); EXPECT_EQ(status, E_OK); @@ -937,7 +1129,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics007, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics008, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; auto status = SqlStatistic::Subscribe(sqlObserver_); EXPECT_EQ(status, E_OK); @@ -956,7 +1148,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics008, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics009, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; std::string value = "with test as (select * from statistics_test) select * from test1"; auto status = SqlStatistic::Subscribe(sqlObserver_); @@ -976,7 +1168,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics009, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics010, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; EXPECT_NE(sqlObserver_, nullptr) << "observer is null"; auto status = SqlStatistic::Subscribe(nullptr); EXPECT_EQ(status, E_OK); @@ -989,7 +1181,7 @@ HWTEST_F(RdbStoreSubTest, RdbStoreSubscribeStatistics010, TestSize.Level1) */ HWTEST_F(RdbStoreSubTest, RdbStore_RegisterAutoSyncCallbackAndRdbStore_UnregisterAutoSyncCallback_001, TestSize.Level1) { - EXPECT_NE(store, nullptr) << "store is null"; + ASSERT_NE(store, nullptr) << "store is null"; auto obs = std::make_shared(); auto status = store->RegisterAutoSyncCallback(obs); EXPECT_EQ(status, E_OK); diff --git a/relational_store/test/native/rdb/unittest/rdb_update_test.cpp b/relational_store/test/native/rdb/unittest/rdb_update_test.cpp index 585eb590..dcc37793 100644 --- a/relational_store/test/native/rdb/unittest/rdb_update_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_update_test.cpp @@ -99,6 +99,7 @@ void RdbStoreUpdateTest::TearDownTestCase(void) void RdbStoreUpdateTest::SetUp(void) { store_ = *GetParam(); + ASSERT_NE(store_, nullptr); store_->ExecuteSql("DELETE FROM test"); } @@ -114,13 +115,11 @@ void RdbStoreUpdateTest::TearDown(void) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_001, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -130,11 +129,11 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_001, TestSize.Level1) values.PutInt("age", 20); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->Update(changedRows, "test", values, "id = ?", std::vector{ "1" }); + ret = store_->Update(changedRows, "test", values, "id = ?", std::vector{ "1" }); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToFirstRow(); @@ -155,28 +154,26 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_001, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_002, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int64_t id; ValuesBucket values; int changedRows; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); values.Clear(); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->Update(changedRows, "test", values); + ret = store_->Update(changedRows, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -201,8 +198,6 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_002, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_003, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int changedRows; ValuesBucket values; values.PutInt("id", 1); @@ -210,10 +205,10 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_003, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Update(changedRows, "", values, "", std::vector()); // empty table name + int ret = store_->Update(changedRows, "", values, "", std::vector()); // empty table name EXPECT_EQ(ret, E_EMPTY_TABLE_NAME); - ret = store->Update(changedRows, "wrongTable", values, "", std::vector()); // no such table + ret = store_->Update(changedRows, "wrongTable", values, "", std::vector()); // no such table EXPECT_EQ(ret, E_SQLITE_ERROR); } @@ -224,11 +219,9 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_003, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_004, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int changedRows; ValuesBucket emptyBucket; - int ret = store->Update(changedRows, "test", emptyBucket); + int ret = store_->Update(changedRows, "test", emptyBucket); EXPECT_EQ(ret, E_EMPTY_VALUES_BUCKET); ValuesBucket values; @@ -237,7 +230,7 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_004, TestSize.Level1) values.PutInt("age", 18); values.PutDouble("wrongColumn", 100.5); // no such column values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Update(changedRows, "test", values, "", std::vector()); + ret = store_->Update(changedRows, "test", values, "", std::vector()); EXPECT_EQ(ret, E_SQLITE_ERROR); } @@ -248,17 +241,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_004, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_005, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Update(changedRows, "test", values, "id = ?", std::vector{ "1" }); + ret = store_->Update(changedRows, "test", values, "id = ?", std::vector{ "1" }); EXPECT_EQ(ret, E_EMPTY_VALUES_BUCKET); } @@ -269,8 +260,6 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_005, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_006, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; @@ -281,15 +270,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_006, TestSize.Level1) values.PutInt("age", 20); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Update(changedRows, "test", values, "id = ?", std::vector{ "1" }); + ret = store_->Update(changedRows, "test", values, "id = ?", std::vector{ "1" }); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToFirstRow(); @@ -310,21 +299,20 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_006, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_007, TestSize.Level1) { - std::shared_ptr store = *GetParam(); ValuesBucket values; AssetValue value{ .version = 1, .name = "123", .uri = "your test path", .createTime = "13", .modifyTime = "13" }; int changedRows; int64_t id; values.PutNull("assetType"); - int ret = store->Insert(id, "test", values); + int ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); values.Clear(); values.Put("assetType", value); - ret = store->Update(changedRows, "test", values); + ret = store_->Update(changedRows, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToFirstRow(); @@ -348,7 +336,6 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_007, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_008, TestSize.Level1) { - std::shared_ptr store = *GetParam(); ValuesBucket values; AssetValue valueDef{ .version = 0, @@ -361,15 +348,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_008, TestSize.Level1) int changedRows; int64_t id; values.Put("assetType", valueDef); - int ret = store->Insert(id, "test", values); + int ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(4, id); values.Clear(); values.Put("assetType", value); - ret = store->Update(changedRows, "test", values); + ret = store_->Update(changedRows, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToFirstRow(); @@ -388,7 +375,6 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_008, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_009, TestSize.Level1) { - std::shared_ptr store = *GetParam(); ValuesBucket values; AssetValue valueDef{ .version = 0, .status = AssetValue::STATUS_NORMAL, @@ -403,15 +389,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_009, TestSize.Level1) int changedRows; int64_t id; values.Put("assetType", valueDef); - int ret = store->Insert(id, "test", values); + int ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(5, id); values.Clear(); values.Put("assetType", value); - ret = store->Update(changedRows, "test", values); + ret = store_->Update(changedRows, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToFirstRow(); EXPECT_EQ(ret, E_OK); @@ -435,7 +421,6 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_009, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_010, TestSize.Level1) { - std::shared_ptr store = *GetParam(); ValuesBucket values; std::vector assetsDef{ { .version = 0, .name = "123", .uri = "my test path", .createTime = "12", .modifyTime = "12" } @@ -447,13 +432,13 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_010, TestSize.Level1) int changedRows; int64_t id; values.Put("assetsType", assetsDef); - int ret = store->Insert(id, "test", values); + int ret = store_->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(6, id); values.Clear(); values.Put("assetsType", assets); - ret = store->Update(changedRows, "test", values); + ret = store_->Update(changedRows, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); } @@ -465,17 +450,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_Update_010, TestSize.Level1) */ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_001, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -485,11 +468,11 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_001, TestSize values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = 19"); + ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = 19"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -514,17 +497,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_001, TestSize */ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_002, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -534,11 +515,11 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_002, TestSize values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, + ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, ConflictResolution::ON_CONFLICT_NONE); EXPECT_EQ(ret, E_SQLITE_CONSTRAINT); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -563,17 +544,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_002, TestSize */ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_003, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -583,12 +562,12 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_003, TestSize values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, + ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, ConflictResolution::ON_CONFLICT_ROLLBACK); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -613,17 +592,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_003, TestSize */ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_004, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -633,11 +610,11 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_004, TestSize values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, + ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, ConflictResolution::ON_CONFLICT_ROLLBACK); EXPECT_EQ(ret, E_SQLITE_CONSTRAINT); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -662,17 +639,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_004, TestSize */ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_005, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -682,12 +657,12 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_005, TestSize values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, + ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, ConflictResolution::ON_CONFLICT_REPLACE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -712,17 +687,15 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_005, TestSize */ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_006, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - ValuesBucket values; int changedRows; int64_t id; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -730,12 +703,12 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_006, TestSize values.PutString("name", std::string("zhangsan")); values.PutInt("age", 20); values.PutDouble("salary", 300.5); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, + ret = store_->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, ConflictResolution::ON_CONFLICT_REPLACE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(changedRows, 1); - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = store_->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); ret = resultSet->GoToNextRow(); @@ -757,19 +730,17 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_006, TestSize */ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_007, TestSize.Level1) { - std::shared_ptr store = *GetParam(); - int changedRows = 0; int64_t id = -1; ValuesBucket values; - int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); values.PutInt("id", 2); values.PutInt("age", 19); - ret = store->UpdateWithConflictResolution( + ret = store_->UpdateWithConflictResolution( changedRows, "test", values, "age = ?", std::vector{ "18" }, static_cast(6)); EXPECT_EQ(E_INVALID_CONFLICT_FLAG, ret); EXPECT_EQ(0, changedRows); @@ -777,7 +748,7 @@ HWTEST_P(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_007, TestSize values.Clear(); values.PutInt("id", 2); values.PutInt("age", 19); - ret = store->UpdateWithConflictResolution( + ret = store_->UpdateWithConflictResolution( changedRows, "test", values, "age = ?", std::vector{ "18" }, static_cast(-1)); EXPECT_EQ(E_INVALID_CONFLICT_FLAG, ret); EXPECT_EQ(0, changedRows); @@ -865,5 +836,300 @@ HWTEST_P(RdbStoreUpdateTest, OverLimitWithUpdate_001, TestSize.Level1) ASSERT_EQ(result, E_SQLITE_FULL); } +/** + * @tc.name: UpdateWithReturning_001 + * @tc.desc: normal test + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_001, TestSize.Level1) +{ + int64_t id; + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + ValuesBucket values; + values.PutInt("id", 2); + values.PutString("name", std::string("lisi")); + values.PutInt("age", 20); + values.PutDouble("salary", 200.5); + values.PutBlob("blobType", std::vector{ 4, 5, 6 }); + AbsRdbPredicates predicates("test"); + auto [status, result] = store_->Update(values, predicates, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("id", columnIndex), E_OK); + int val = -1; + ASSERT_EQ(result.results->GetInt(columnIndex, val), E_OK); +} + +/** + * @tc.name: UpdateWithReturning_002 + * @tc.desc: abnormal test, update with conflict ignore and partial Success + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_002, TestSize.Level1) +{ + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim_" + std::to_string(i)); + rows.Put(row); + } + auto [status, result] = store_->BatchInsert("test", rows, {}, ConflictResolution::ON_CONFLICT_REPLACE); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(result.changed, 5); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(0, rowCount); + + ValuesBucket row; + row.PutString("name", "Jim_3"); + row.PutInt("age", 20); + row.PutDouble("salary", 200.5); + row.PutBlob("blobType", std::vector{ 4, 5, 6 }); + AbsRdbPredicates predicates("test"); + predicates.In("id", { 1, 2, 3 }); + std::tie(status, result) = store_->Update(row, predicates, { "name" }, ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(1, rowCount); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + std::string val; + ASSERT_EQ(result.results->GetString(columnIndex, val), E_OK); + ASSERT_EQ(val, "Jim_3"); +} + +/** + * @tc.name: UpdateWithReturning_003 + * @tc.desc: abnormal test, update with conflict abort and failed + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_003, TestSize.Level1) +{ + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim_" + std::to_string(i)); + rows.Put(row); + } + auto [status, result] = store_->BatchInsert("test", rows, {}, ConflictResolution::ON_CONFLICT_REPLACE); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(result.changed, 5); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(0, rowCount); + + ValuesBucket row; + row.PutString("name", "Jim_3"); + row.PutInt("age", 20); + row.PutDouble("salary", 200.5); + row.PutBlob("blobType", std::vector{ 4, 5, 6 }); + AbsRdbPredicates predicates("test"); + predicates.In("id", { 1, 2, 3 }); + std::tie(status, result) = store_->Update(row, predicates, { "blobType" }, ConflictResolution::ON_CONFLICT_ABORT); + EXPECT_EQ(status, E_SQLITE_CONSTRAINT); + EXPECT_EQ(result.changed, 0); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(0, rowCount); +} + +/** + * @tc.name: UpdateWithReturning_004 + * @tc.desc: abnormal test, update over returning limit + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_004, TestSize.Level1) +{ + ValuesBuckets rows; + for (int i = 0; i < 1124; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim_" + std::to_string(i)); + rows.Put(row); + } + auto [status, result] = store_->BatchInsert("test", rows, {}, ConflictResolution::ON_CONFLICT_REPLACE); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(result.changed, 1124); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(0, rowCount); + + ValuesBucket row; + row.PutInt("age", 20); + row.PutDouble("salary", 200.5); + row.PutBlob("blobType", std::vector{ 4, 5, 6 }); + AbsRdbPredicates predicates("test"); + std::tie(status, result) = store_->Update(row, predicates, { "age" }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1124); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1024); +} + +/** + * @tc.name: UpdateWithReturning_005 + * @tc.desc: abnormal test, update with returning no exist field + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_005, TestSize.Level1) +{ + int64_t id; + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + ValuesBucket values; + values.PutString("name", std::string("lisi")); + values.PutInt("age", 20); + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 10000); + auto [status, result] = store_->Update(values, predicates, { "noExist" }); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + EXPECT_EQ(result.results, nullptr); +} + +/** + * @tc.name: UpdateWithReturning_006 + * @tc.desc: abnormal test, update 0 rows + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_006, TestSize.Level1) +{ + int64_t id; + int ret = store_->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + ValuesBucket values; + values.PutString("name", std::string("lisi")); + values.PutInt("age", 20); + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 10000); + auto [status, result] = store_->Update(values, predicates, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(0, rowCount); +} + + +/** + * @tc.name: UpdateWithReturning_007 + * @tc.desc: abnormal test, update 0 rows + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_007, TestSize.Level1) +{ + store_->Execute("CREATE VIRTUAL TABLE IF NOT EXISTS articles USING fts5(title, content);"); + ValuesBuckets rows; + ValuesBucket row; + row.Put("title", "fts5"); + row.Put("content", "test virtual tables"); + rows.Put(std::move(row)); + auto [status, result] = + store_->BatchInsert("articles", rows, { "title" }, NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + + AbsRdbPredicates predicates("test"); + predicates.EqualTo("title", "fts5"); + ValuesBucket values; + values.PutString("title", "fts5 updated"); + + std::tie(status, result) = store_->Update(values, predicates, { "title" }); + // UPDATE RETURNING is not available on virtual tables + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + EXPECT_EQ(result.results, nullptr); + + store_->Execute("Drop TABLE articles"); +} + +/** + * @tc.name: UpdateWithReturning_008 + * @tc.desc: normal test. create trigger before update, delete data in trigger, then update data + * @tc.type: FUNC + * @tc.require: + * @tc.author: +*/ +HWTEST_P(RdbStoreUpdateTest, UpdateWithReturning_008, TestSize.Level1) +{ + auto [code, result1] = store_->Execute( + "CREATE TRIGGER before_update BEFORE UPDATE ON test" + " BEGIN DELETE FROM test WHERE name = 'wang'; END"); + + EXPECT_EQ(code, E_OK); + + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 200); + row.Put("name", "wang"); + rows.Put(std::move(row)); + row.Put("id", 201); + row.Put("name", "zhang"); + rows.Put(std::move(row)); + + auto [insertStatus, insertResult] = + store_->BatchInsert("test", rows, { "name" }, NativeRdb::ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(insertStatus, E_OK); + EXPECT_EQ(insertResult.changed, 2); + + auto predicates = AbsRdbPredicates("test"); + predicates.EqualTo("name", "zhang"); + ValuesBucket values; + values.PutString("name", "liu"); + + auto [status, res] = + store_->Update(values, predicates, { "name" }); + + EXPECT_EQ(status, E_OK); + EXPECT_EQ(res.changed, 1); + int rowCount = -1; + ASSERT_EQ(res.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(res.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + ASSERT_EQ(res.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "liu"); + + // Check the trigger effect + auto resultSet = store_->QuerySql("select name from test where id = 200"); + + rowCount = -1; + resultSet->GetRowCount(rowCount); + ASSERT_EQ(rowCount, 0); + store_->Execute("DROP TRIGGER IF EXISTS before_update"); +} + INSTANTIATE_TEST_SUITE_P(UpdateTest, RdbStoreUpdateTest, testing::Values(&g_store, &g_memDb)); } // namespace OHOS::RdbStoreUpdateTest \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_utils_test.cpp b/relational_store/test/native/rdb/unittest/rdb_utils_test.cpp index bee28ab3..3dbcd423 100644 --- a/relational_store/test/native/rdb/unittest/rdb_utils_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_utils_test.cpp @@ -136,4 +136,22 @@ HWTEST_F(RdbUtilsTest, GetSqlStatementType_002, TestSize.Level1) EXPECT_EQ(SqliteUtils::STATEMENT_SELECT, SqliteUtils::GetSqlStatementType(" select * from text")); EXPECT_EQ(SqliteUtils::STATEMENT_UPDATE, SqliteUtils::GetSqlStatementType("\r\nupdate test set id = ?")); EXPECT_EQ(SqliteUtils::STATEMENT_OTHER, SqliteUtils::GetSqlStatementType("~!@# attach database ? as ?")); +} + +/** + * @tc.name: GetAreaTest + * @tc.desc: Test get area + * @tc.type: FUNC + */ +HWTEST_F(RdbUtilsTest, GetAreaTest, TestSize.Level1) +{ + std::string srcFile("data/app/el2/database"); + auto area = SqliteUtils::GetArea(srcFile); + EXPECT_EQ(area, "el2"); + std::string dirFile("data/app/database"); + area = SqliteUtils::GetArea(dirFile); + EXPECT_EQ(area, ""); + std::string dirSrcFile("data/app/el2database"); + area = SqliteUtils::GetArea(dirSrcFile); + EXPECT_EQ(area, ""); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/sqlite_statement_test/BUILD.gn b/relational_store/test/native/rdb/unittest/sqlite_statement_test/BUILD.gn new file mode 100644 index 00000000..04118e0f --- /dev/null +++ b/relational_store/test/native/rdb/unittest/sqlite_statement_test/BUILD.gn @@ -0,0 +1,153 @@ +# 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/distributeddatamgr/relational_store/relational_store.gni") + +module_output_path = "relational_store/relational_store/native_rdb" + +############################################################################### +config("module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "${relational_store_mock_path}/frameworks/native/rdb/common", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_native_path}/dfx/include", + "${relational_store_native_path}/obs_mgr_adapter", + "${relational_store_native_path}/rdb/src", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_native_path}/rdb_crypt", + "${relational_store_native_path}/rdb_device_manager_adapter/include", + "${relational_store_base_path}/test/native/rdb/unittest", + ] + + defines = [ + "RELATIONAL_STORE", + ] +} + +ohos_unittest("SqliteStatementTest") { + module_out_path = module_output_path + + cflags = [ + "-fno-access-control", # Ignore Private Member Access Control + ] + + sources = [ + "sqlite_statement_test.cpp", + "mock_shared_block_test.cpp", + ] + + sources += [ + "${relational_store_native_path}/rdb/src/rdb_manager_impl.cpp", + "${relational_store_native_path}/dfx/src/rdb_radar_reporter.cpp", + "${relational_store_native_path}/dfx/src/rdb_stat_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_fault_hiview_reporter.cpp", + "${relational_store_native_path}/rdb/mock/src/rdb_time_utils.cpp", + "${relational_store_native_path}/rdb/src/abs_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/abs_result_set.cpp", + "${relational_store_native_path}/rdb/src/abs_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/base_transaction.cpp", + "${relational_store_native_path}/rdb/src/big_integer.cpp", + "${relational_store_native_path}/rdb/src/cache_result_set.cpp", + "${relational_store_native_path}/rdb/src/connection.cpp", + "${relational_store_native_path}/rdb/src/connection_pool.cpp", + "${relational_store_native_path}/rdb/src/delay_notify.cpp", + "${relational_store_native_path}/rdb/src/grd_api_manager.cpp", + "${relational_store_native_path}/rdb/src/global_resource.cpp", + "${relational_store_native_path}/rdb/src/knowledge_schema_helper.cpp", + "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", + "${relational_store_native_path}/rdb/src/rd_connection.cpp", + "${relational_store_native_path}/rdb/src/rd_statement.cpp", + "${relational_store_native_path}/rdb/src/rd_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_helper.cpp", + "${relational_store_native_path}/rdb/src/rdb_icu_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_local_db_observer.cpp", + "${relational_store_native_path}/rdb/src/rdb_notifier_stub.cpp", + "${relational_store_native_path}/rdb/src/rdb_obs_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_perfStat.cpp", + "${relational_store_native_path}/rdb/src/rdb_predicates.cpp", + "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_service_proxy.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_log.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_statistic.cpp", + "${relational_store_native_path}/rdb/src/rdb_sql_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_store.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_impl.cpp", + "${relational_store_native_path}/rdb/src/rdb_store_manager.cpp", + "${relational_store_native_path}/rdb/src/rdb_types_util.cpp", + "${relational_store_native_path}/rdb/src/result_set_proxy.cpp", + "${relational_store_native_path}/rdb/src/security_policy.cpp", + "${relational_store_native_path}/rdb/src/shared_block_serializer_info.cpp", + "${relational_store_native_path}/rdb/src/sqlite_connection.cpp", + "${relational_store_native_path}/rdb/src/sqlite_default_function.cpp", + "${relational_store_native_path}/rdb/src/sqlite_global_config.cpp", + "${relational_store_native_path}/rdb/src/sqlite_shared_result_set.cpp", + "${relational_store_native_path}/rdb/src/sqlite_sql_builder.cpp", + "${relational_store_native_path}/rdb/src/sqlite_statement.cpp", + "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", + "${relational_store_native_path}/rdb/src/step_result_set.cpp", + "${relational_store_native_path}/rdb/src/string_utils.cpp", + "${relational_store_native_path}/rdb/src/suspender.cpp", + "${relational_store_native_path}/rdb/src/task_executor.cpp", + "${relational_store_native_path}/rdb/src/trans_db.cpp", + "${relational_store_native_path}/rdb/src/transaction.cpp", + "${relational_store_native_path}/rdb/src/transaction_impl.cpp", + "${relational_store_native_path}/rdb/src/value_object.cpp", + "${relational_store_native_path}/rdb/src/values_bucket.cpp", + "${relational_store_native_path}/rdb/src/values_buckets.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "c_utils:utils", + "file_api:securitylabel", + "googletest:gmock", + "googletest:gtest", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "huks:libhukssdk", + "ipc:ipc_core", + "ipc:ipc_single", + "json:nlohmann_json_static", + "kv_store:database_utils", + "kv_store:datamgr_common", + "kv_store:distributeddata_inner", + "kv_store:distributeddb_client", + "samgr:samgr_proxy", + "sqlite:sqlite", + "sqlite:sqliteicu", + ] + + deps = [ + "${relational_store_innerapi_path}/appdatafwk:native_appdatafwk", + "${relational_store_innerapi_path}/appdatafwk:relational_common_base", + ] +} + +############################################################################### +group("unittest") { + testonly = true + + deps = [ ":SqliteStatementTest" ] +} +############################################################################### diff --git a/relational_store/test/native/rdb/unittest/sqlite_statement_test/mock_shared_block_test.cpp b/relational_store/test/native/rdb/unittest/sqlite_statement_test/mock_shared_block_test.cpp new file mode 100644 index 00000000..b7b26f17 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/sqlite_statement_test/mock_shared_block_test.cpp @@ -0,0 +1,265 @@ +/* + * 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 "share_block.h" +#include "logger.h" +#include "sqlite_errno.h" +namespace OHOS { +namespace NativeRdb { +using namespace OHOS::Rdb; + +int SeriAddRow(void *pCtx, int addedRows) +{ + (void)pCtx; + (void)addedRows; + return E_ERROR; +} + +int SeriReset(void *pCtx, int startPos) +{ + (void)pCtx; + (void)startPos; + return E_ERROR; +} + +int SeriFinish(void *pCtx, int addedRows, int totalRows) +{ + (void)pCtx; + (void)addedRows; + (void)totalRows; + return E_ERROR; +} + +int SeriPutString(void *pCtx, int addedRows, int column, const char *text, int size) +{ + (void)pCtx; + (void)addedRows; + (void)column; + (void)text; + (void)size; + return E_ERROR; +} + +int SeriPutLong(void *pCtx, int addedRows, int column, sqlite3_int64 value) +{ + (void)pCtx; + (void)addedRows; + (void)column; + (void)value; + return E_ERROR; +} + +int SeriPutDouble(void *pCtx, int addedRows, int column, double value) +{ + (void)pCtx; + (void)addedRows; + (void)column; + (void)value; + return E_ERROR; +} + +int SeriPutBlob(void *pCtx, int addedRows, int column, const void *blob, int len) +{ + (void)pCtx; + (void)addedRows; + (void)column; + (void)blob; + (void)len; + return E_ERROR; +} + +int SeriPutNull(void *pCtx, int addedRows, int column) +{ + (void)pCtx; + (void)addedRows; + (void)column; + return E_ERROR; +} + +int SeriPutOther(void *pCtx, int addedRows, int column) +{ + (void)pCtx; + (void)addedRows; + (void)column; + return E_ERROR; +} + +int ClearSharedBlock(AppDataFwk::SharedBlock *sharedBlock) +{ + (void)sharedBlock; + return E_ERROR; +} + +int SharedBlockSetColumnNum(AppDataFwk::SharedBlock *sharedBlock, int columnNum) +{ + (void)sharedBlock; + (void)columnNum; + return E_ERROR; +} + +int FillSharedBlockOpt(SharedBlockInfo *info, sqlite3_stmt *stmt) +{ + (void)info; + (void)stmt; + return E_ERROR; +} + +int FillSharedBlock(SharedBlockInfo *info, sqlite3_stmt *stmt) +{ + (void)info; + (void)stmt; + return E_ERROR; +} + +void FillRow(SharedBlockInfo *info, sqlite3_stmt *stmt) +{ + (void)info; + (void)stmt; +} + +FillOneRowResult FillOneRow( + AppDataFwk::SharedBlock *sharedBlock, sqlite3_stmt *statement, int numColumns, int startPos, int addedRows) +{ + (void)sharedBlock; + (void)statement; + (void)numColumns; + (void)startPos; + (void)addedRows; + FillOneRowResult result = FILL_ONE_ROW_SUCESS; + return result; +} + +FillOneRowResult FillOneRowOfString( + AppDataFwk::SharedBlock *sharedBlock, sqlite3_stmt *statement, int startPos, int addedRows, int pos) +{ + (void)sharedBlock; + (void)statement; + (void)startPos; + (void)addedRows; + (void)pos; + FillOneRowResult result = FILL_ONE_ROW_SUCESS; + return result; +} + +FillOneRowResult FillOneRowOfLong( + AppDataFwk::SharedBlock *sharedBlock, sqlite3_stmt *statement, int startPos, int addedRows, int pos) +{ + (void)sharedBlock; + (void)statement; + (void)startPos; + (void)addedRows; + (void)pos; + FillOneRowResult result = FILL_ONE_ROW_SUCESS; + return result; +} + +FillOneRowResult FillOneRowOfFloat( + AppDataFwk::SharedBlock *sharedBlock, sqlite3_stmt *statement, int startPos, int addedRows, int pos) +{ + (void)sharedBlock; + (void)statement; + (void)startPos; + (void)addedRows; + (void)pos; + FillOneRowResult result = FILL_ONE_ROW_SUCESS; + return result; +} + +FillOneRowResult FillOneRowOfBlob( + AppDataFwk::SharedBlock *sharedBlock, sqlite3_stmt *statement, int startPos, int addedRows, int pos) +{ + (void)sharedBlock; + (void)statement; + (void)startPos; + (void)addedRows; + (void)pos; + FillOneRowResult result = FILL_ONE_ROW_SUCESS; + return result; +} + +FillOneRowResult FillOneRowOfNull( + AppDataFwk::SharedBlock *sharedBlock, sqlite3_stmt *statement, int startPos, int addedRows, int pos) +{ + (void)sharedBlock; + (void)statement; + (void)startPos; + (void)addedRows; + (void)pos; + FillOneRowResult result = FILL_ONE_ROW_SUCESS; + return result; +} + +bool ResetStatement(SharedBlockInfo *info, sqlite3_stmt *stmt) +{ + (void)info; + (void)stmt; + return true; +} + +int DefAddRow(void *pCtx, int addedRows) +{ + return SQLITE_FULL; +} + +int DefReset(void *pCtx, int startPos) +{ + return SQLITE_OK; +} + +int DefFinish(void *pCtx, int addedRows, int totalRows) +{ + return SQLITE_OK; +} + +int DefPutString(void *pCtx, int addedRows, int column, const char *text, int size) +{ + return SQLITE_FULL; +} + +int DefPutLong(void *pCtx, int addedRows, int column, sqlite3_int64 value) +{ + return SQLITE_FULL; +} + +int DefPutDouble(void *pCtx, int addedRows, int column, double value) +{ + return SQLITE_FULL; +} + +int DefPutBlob(void *pCtx, int addedRows, int column, const void *blob, int len) +{ + return SQLITE_FULL; +} + +int DefPutNull(void *pCtx, int addedRows, int column) +{ + return SQLITE_FULL; +} + +int DefPutOther(void *pCtx, int addedRows, int column) +{ + return SQLITE_FULL; +} + +void DefFillRow(SharedBlockInfo *info, sqlite3_stmt *stmt) +{ + (void)info; + (void)stmt; +} +} // namespace NativeRdb +} // namespace OHOS \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/sqlite_statement_test/sqlite_statement_test.cpp b/relational_store/test/native/rdb/unittest/sqlite_statement_test/sqlite_statement_test.cpp new file mode 100644 index 00000000..3cd045da --- /dev/null +++ b/relational_store/test/native/rdb/unittest/sqlite_statement_test/sqlite_statement_test.cpp @@ -0,0 +1,128 @@ +/* + * 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 "sqlite_statement.h" + +#include +#include + +#include +#include +#include + +#include "block_data.h" +#include "common.h" +#include "executor_pool.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "rdb_sql_log.h" +#include "rdb_store.h" +#include "rdb_store_manager.h" +#include "rdb_types.h" +#include "sqlite_utils.h" +#include "values_bucket.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::DistributedRdb; + +class RdbSqliteStatementTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void RdbSqliteStatementTest::SetUpTestCase(void) +{ +} + +void RdbSqliteStatementTest::TearDownTestCase(void) +{ +} + +void RdbSqliteStatementTest::SetUp(void) +{ +} + +void RdbSqliteStatementTest::TearDown(void) +{ +} +/** + * @tc.name: SqliteStatement001 + * @tc.desc: RdbSqliteStatementTest FillBlockInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqliteStatementTest, SqliteStatement001, TestSize.Level0) +{ + sqlite3 *db = nullptr; + int rc = sqlite3_open("/data/test/SqliteStatement001.db", &db); + ASSERT_NE(db, nullptr); + EXPECT_EQ(rc, SQLITE_OK); + const char *sqlCreate = "CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY)"; + char *errMsg = nullptr; + rc = sqlite3_exec(db, sqlCreate, NULL, NULL, &errMsg); + sqlite3_stmt *stmt; + const char *sql = "select id from users;"; + rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); + + SharedBlockInfo info(nullptr); + info.isCountAllRows = true; + info.isFull = true; + info.totalRows = -1; + SqliteStatement statem; + statem.stmt_ = stmt; + int errCode = statem.FillBlockInfo(&info); + EXPECT_EQ(errCode, E_ERROR); + statem.stmt_ = nullptr; + sqlite3_finalize(stmt); + rc = sqlite3_close(db); + EXPECT_EQ(rc, SQLITE_OK); +} + +/** + * @tc.name: SqliteStatement002 + * @tc.desc: RdbSqliteStatementTest FillBlockInfo + * @tc.type: FUNC + */ +HWTEST_F(RdbSqliteStatementTest, SqliteStatement002, TestSize.Level0) +{ + const char *dbPath = "/data/test/SqliteStatement002.db"; + RdbStoreConfig rdbConfig(dbPath); + sqlite3 *db = nullptr; + int rc = sqlite3_open(dbPath, &db); + ASSERT_NE(db, nullptr); + EXPECT_EQ(rc, SQLITE_OK); + const char *sqlCreate = "CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY)"; + char *errMsg = nullptr; + rc = sqlite3_exec(db, sqlCreate, NULL, NULL, &errMsg); + sqlite3_stmt *stmt; + const char *sql = "select id from users;"; + rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); + + SharedBlockInfo info(nullptr); + info.isCountAllRows = true; + info.isFull = true; + info.totalRows = -1; + SqliteStatement statem(&rdbConfig); + statem.stmt_ = stmt; + int errCode = statem.FillBlockInfo(&info); + EXPECT_EQ(errCode, E_ERROR); + statem.stmt_ = nullptr; + sqlite3_finalize(stmt); + rc = sqlite3_close(db); + EXPECT_EQ(rc, SQLITE_OK); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/sqlite_utils_test.cpp b/relational_store/test/native/rdb/unittest/sqlite_utils_test.cpp index ba5bf657..134c7b39 100644 --- a/relational_store/test/native/rdb/unittest/sqlite_utils_test.cpp +++ b/relational_store/test/native/rdb/unittest/sqlite_utils_test.cpp @@ -41,122 +41,181 @@ void SqliteUtilsTest::TearDownTestCase(void) HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_001, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("30005245854585524412855412_rdb_test.db"), "***5412_rdb_test.db"); -} - -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_002, TestSize.Level1) -{ - EXPECT_EQ(SqliteUtils::Anonymous("rdb_test_30005245854585524412855412.db"), "rdb_test_***5412.db"); -} - -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_003, TestSize.Level1) -{ - EXPECT_EQ(SqliteUtils::Anonymous("rdb_30005245854585524412855412_test.db"), "rdb_***5412_test.db"); -} - -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_004, TestSize.Level1) -{ - EXPECT_EQ(SqliteUtils::Anonymous("rdb_300052_test.db"), "rdb_***052_test.db"); -} - -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_005, TestSize.Level1) -{ - EXPECT_EQ(SqliteUtils::Anonymous("rdb_30005_test.db"), "rdb_30005_test.db"); -} - -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_006, TestSize.Level1) -{ - EXPECT_EQ(SqliteUtils::Anonymous("rdb_3000523_test.db"), "rdb_***0523_test.db"); + EXPECT_EQ(SqliteUtils::Anonymous("30005245854585524412855412_rdb_test.db"), "300***.db"); } HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_007, TestSize.Level1) { EXPECT_EQ( SqliteUtils::Anonymous("file /data/stage/el2/database/rdb/ddddddd/30005245854585524412855412_rdb_test.db"), - "file /***/el2/***/***5412_rdb_test.db"); -} - -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_008, TestSize.Level1) -{ - EXPECT_EQ(SqliteUtils::Anonymous("file /data/stage/database/rdb/ddddddd/30005245854585524412855412_rdb_test.db"), - "file /***/***5412_rdb_test.db"); + "file /***/el2/***/300***.db"); } HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_009, TestSize.Level1) { EXPECT_EQ( SqliteUtils::Anonymous("file /data/stage/el2/database/rdb/ddddddd/3E00mnj5H54efg5G4K1ABC5412_rdb_test.db"), - "file /***/el2/***/3E00mnj5H54efg5G4K***5412_rdb_test.db"); + "file /***/el2/***/3E0***.db"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_010, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0011, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("/data/stage/el2/database/rdb/ddddddd/3E00mnj5H54efg5G4K1ABC5412_rdb_test.db"), - "/***/el2/***/3E00mnj5H54efg5G4K***5412_rdb_test.db"); + EXPECT_EQ(SqliteUtils::Anonymous("30005245854585524412855412.db"), "300***.db"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0011, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0013, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("30005245854585524412855412.db"), "***5412.db"); + EXPECT_EQ(SqliteUtils::Anonymous("123edf4.db"), "123***.db"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0012, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0016, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("thequickbrownfoxjumpoverthelazydog.db"), "thequickbrownfoxjumpoverthelazydog.db"); + EXPECT_EQ(SqliteUtils::Anonymous("__23edf__.db"), "__2***.db"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0013, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0021, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("123edf4.db"), "***edf4.db"); + EXPECT_EQ(SqliteUtils::Anonymous("linker_reborn.db-wal"), "lin***wal"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0014, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0022, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("K123edfK.db"), "K***edfK.db"); + EXPECT_EQ(SqliteUtils::Anonymous("linker_grow.db-wal"), "lin***wal"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0015, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0023, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("K23edfK.db"), "K23edfK.db"); + EXPECT_EQ(SqliteUtils::Anonymous("file /data/stage/el2/database/rdb/ddddddd/linker_reborn.db-wal"), + "file /***/el2/***/lin***wal"); +} + +HWTEST_F(SqliteUtilsTest, Anonymous_001, TestSize.Level0) +{ + EXPECT_EQ(SqliteUtils::Anonymous(""), ""); + EXPECT_EQ(SqliteUtils::Anonymous("x"), "x**"); + EXPECT_EQ(SqliteUtils::Anonymous("xx"), "x**"); + EXPECT_EQ(SqliteUtils::Anonymous("xxx"), "x**"); + EXPECT_EQ(SqliteUtils::Anonymous("xxxx"), "xxx***"); + EXPECT_EQ(SqliteUtils::Anonymous("xxxxx"), "xxx***"); + EXPECT_EQ(SqliteUtils::Anonymous("xxxxxx"), "xxx***"); + EXPECT_EQ(SqliteUtils::Anonymous("xxxxxxx"), "xxx***"); + EXPECT_EQ(SqliteUtils::Anonymous("xxxxxxxx"), "xxx***"); + EXPECT_EQ(SqliteUtils::Anonymous("xxxxxxxxx"), "xxx***xxx"); + EXPECT_EQ(SqliteUtils::Anonymous("xxxxxxxxxx"), "xxx***xxx"); +} + +HWTEST_F(SqliteUtilsTest, SqlAnonymous_001, TestSize.Level0) +{ + EXPECT_EQ(SqliteUtils::SqlAnonymous("SELECT * FROM users WHERE id = 1"), "SELECT * FROM use*** WHERE i** = 1"); + EXPECT_EQ(SqliteUtils::SqlAnonymous( + "statement abort at 11: [ SELECT COUNT(1) AS count FROM Photos WHERE type = 'screenshot'"), + "statement abort at 11: [ SELECT COUNT(1) AS count FROM Pho*** WHERE type = 'scr***hot'"); + EXPECT_EQ(SqliteUtils::SqlAnonymous("errno is:25 ambiguous column name:" + " name in \"SELECT name FROM tableA JOIN tableB ON tableA.id = tableB.a_id;\""), + "errno is:25 ambiguous column name:" + " name in \"SELECT name FROM tab*** JOIN tab*** ON tab***.i** = tab***.a_i***;\""); + EXPECT_EQ( + SqliteUtils::SqlAnonymous("errno is:25 ambiguous column name:" + " story in \"SELECT story FROM tableA JOIN tableB ON tableA.id = tableB.a_id;\""), + "errno is:25 ambiguous column name:" + " sto*** in \"SELECT sto*** FROM tab*** JOIN tab*** ON tab***.i** = tab***.a_i***;\""); + EXPECT_EQ(SqliteUtils::SqlAnonymous( + "errno is:25 2 values for 1 columns in \"INSERT INTO tableA(story) Values(1, '你好中文字符')\"."), + "errno is:25 2 values for 1 col*** in \"INSERT INTO tab***(sto***) Values(1, '***')\"."); + EXPECT_EQ( + SqliteUtils::SqlAnonymous("errno is:0 no such table: CommonAddressModel in" + " \"SELECT * FROM CommonAddressModel WHERE addressType IN (? , ?)AND uid = ? \""), + "errno is:0 no such table: Com***del in \"SELECT * FROM Com***del WHERE add***ype IN (? , ?)AND u** = ? \""); + EXPECT_EQ(SqliteUtils::SqlAnonymous("abort at 14 in [INSERT INTO SETTINGSDATA(KEYWORD,VALUE) VALUES (?,?)]: " + "UNIQUE constraint failed: SETTINGSDATA.KEYWORD"), + "abort at 14 in [INSERT INTO SET***ATA(KEY***,VAL***) VALUES (?,?)]: " + "UNIQUE constraint failed: SET***ATA.KEY***"); + EXPECT_EQ(SqliteUtils::SqlAnonymous("error is:2 misuse at line 57f4b3 if [6cd587f]"), + "error is:2 misuse at line ***4b3 if [***587f]"); + + EXPECT_EQ(SqliteUtils::SqlAnonymous("[SQLite]BusyLine:63706, idx:0, type:4, fileLock:0, len:1, handleLocks:none"), + "[SQLite]BusyLine:63706, idx:0, type:4, fileLock:0, len:1, handleLocks:none"); + EXPECT_EQ(SqliteUtils::SqlAnonymous("[SQLite]acqLock:1, dbRef:2, lockCnt:2, curLock:1, processLock:0"), + "[SQLite]acqLock:1, dbRef:2, lockCnt:2, curLock:1, processLock:0"); + EXPECT_EQ(SqliteUtils::SqlAnonymous("[SQLite]Trx locks: "), + "[SQLite]Trx locks: "); + EXPECT_EQ(SqliteUtils::SqlAnonymous("hello 简体中文 world"), "hel*** *** wor***"); + EXPECT_EQ(SqliteUtils::SqlAnonymous("hello简体cplus中文world"), "hel******cpl******wor***"); +} + +HWTEST_F(SqliteUtilsTest, SqlAnonymous_002, TestSize.Level0) +{ + EXPECT_EQ(SqliteUtils::SqlAnonymous( + "[SQLite]Wal locks: " + ""), + "[SQLite]Wal locks: " + ""); + EXPECT_EQ(SqliteUtils::SqlAnonymous( + "statement aborts at 32: [UPDATE SETTINGSDATA SET KEYWORD=?,VALUE=? WHERE KEYWORD = ? ]" + " database schema has changed"), + "statement aborts at 32: [UPDATE SET***ATA SET KEY***=?,VAL***=? WHERE KEY*** = ? ]" + " database schema has changed"); + EXPECT_EQ( + SqliteUtils::SqlAnonymous("abort at 14 in [INSERT INTO USER_SETTINGSDATA_100(KEYWORD,VALUE) VALUES (?,?)]: " + "UNIQUE constraint failed: USER_SETTINGSDATA_100.KEYWORD"), + "abort at 14 in [INSERT INTO USE***100(KEY***,VAL***) VALUES (?,?)]: " + "UNIQUE constraint failed: USE***100.KEY***"); + EXPECT_EQ(SqliteUtils::SqlAnonymous( + "errno is:2 near \"IF\": syntax error in \"CREATE TRIGGER IF NOT EXISTS [update_contact_data_version]" + " AFTER UPDATE ON [contact_data] BEGIN IF UPDATE [version] RETURN; UPDATE [contact_data] " + "SET [version] = [OLD].[version] + 1 WHERE [id] = [OLD].[id]; END\"."), + "errno is:2 near \"IF\": syntax error in \"CREATE TRIGGER IF NOT EXISTS [upd***ion]" + " AFTER UPDATE ON [con***ata] BEGIN IF UPDATE [ver***] RET***; UPDATE [con***ata] " + "SET [ver***] = [O**].[ver***] + 1 WHERE [i**] = [O**].[i**]; END\"."); + EXPECT_EQ(SqliteUtils::SqlAnonymous("Fd 7 enable del monitor go wrong, errno = 13"), + "Fd 7 enable del monitor go wrong, errno = 13"); + EXPECT_EQ(SqliteUtils::SqlAnonymous( + "errno is:95 duplicate column name: Timestamp in \"ALTER TABLE BSD ADD COLUMN Timestamp TE."), + "errno is:95 duplicate column name: Tim***amp in \"ALTER TABLE B** ADD COLUMN Tim***amp T**."); + EXPECT_EQ( + SqliteUtils::SqlAnonymous("recovered 9 frames from WAL file /data/storage/el1/database/entry/hello.db-wal"), + "recovered 9 frames from WAL file /dat***/sto***/e**/database/ent***/hel***.db-wal"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0016, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqlAnonymous_003, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("__23edf__.db"), "__23edf__.db"); + EXPECT_EQ(SqliteUtils::SqlAnonymous("30005245854585524412855412 123edf4 30005 300052"), + "***5412 ***edf4 30005 ***052"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0017, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0024, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("K3edfK.db"), "K3edfK.db"); + EXPECT_EQ(0, SqliteUtils::DeleteFolder("non_exist_folder/random123")); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0018, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0025, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("K23564edfK.db"), "K***4edfK.db"); + EXPECT_NE(0, SqliteUtils::SetSlaveRestoring("non_exist_folder/non_exist_file")); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0019, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, HandleNormalPath, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("K235648edfK.db"), "K***8edfK.db"); + EXPECT_EQ(SqliteUtils::GetParentModes("/data/service/el1/public/database/distributeddata/meta", 3), + "pub***:mode:d711 <- dat***:mode:d711 <- dis***:mode:d770"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0020, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, ExceedPathDepth, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("K2356489edfK.db"), "K***9edfK.db"); + EXPECT_EQ(SqliteUtils::GetParentModes("a/backup/c", 5), "a:access_fail <- bac***:access_fail"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0021, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, UnixRootPath, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("linker_reborn.db-wal"), "linker_reborn.db-wal"); + EXPECT_EQ(SqliteUtils::GetParentModes("/", 1), "no_parent"); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0022, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, AccessFailureCase, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("linker_grow.db-wal"), "linker_grow.db-wal"); + EXPECT_NE(SqliteUtils::GetParentModes("a/non_existing_path", 1).find("access_fail"), std::string::npos); } -HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0023, TestSize.Level1) +HWTEST_F(SqliteUtilsTest, LongDirectoryName, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("file /data/stage/el2/database/rdb/ddddddd/linker_reborn.db-wal"), - "file /***/el2/***/linker_reborn.db-wal"); -} \ No newline at end of file + std::string longName(20, 'a'); + EXPECT_NE(SqliteUtils::GetParentModes(longName + "/b", 1).find("aaa***"), std::string::npos); +} diff --git a/relational_store/test/native/rdb/unittest/transaction_test.cpp b/relational_store/test/native/rdb/unittest/transaction_test.cpp index 657f2272..e2c1fd5c 100644 --- a/relational_store/test/native/rdb/unittest/transaction_test.cpp +++ b/relational_store/test/native/rdb/unittest/transaction_test.cpp @@ -16,7 +16,9 @@ #include #include +#include +#include "abs_rdb_predicates.h" #include "common.h" #include "rdb_errno.h" #include "rdb_helper.h" @@ -29,6 +31,9 @@ static const std::string DATABASE_NAME = RDB_TEST_PATH + "transaction_test.db"; static const char CREATE_TABLE_SQL[] = "CREATE TABLE IF NOT EXISTS test " "(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"; +static const char CREATE_TABLE1_SQL[] = + "CREATE TABLE IF NOT EXISTS test1 " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"; class TransactionTest : public testing::Test { public: @@ -64,8 +69,8 @@ void TransactionTest::SetUpTestCase() RdbStoreConfig config(DATABASE_NAME); TransactionTestOpenCallback helper; TransactionTest::store_ = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(TransactionTest::store_, nullptr); - EXPECT_EQ(errCode, E_OK); + ASSERT_NE(TransactionTest::store_, nullptr); + ASSERT_EQ(errCode, E_OK); } void TransactionTest::TearDownTestCase() @@ -76,6 +81,7 @@ void TransactionTest::TearDownTestCase() void TransactionTest::SetUp() { + ASSERT_NE(store_, nullptr); store_->Execute("DELETE FROM test"); } @@ -527,7 +533,7 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_011, TestSize.Level1) auto result = transaction->Insert("test1", row); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); ASSERT_EQ(transaction->Commit(), E_SQLITE_ERROR); @@ -568,7 +574,7 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_012, TestSize.Level1) auto result = transaction->Insert("test1", row); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); ASSERT_EQ(transaction->Commit(), E_OK); @@ -609,7 +615,7 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_013, TestSize.Level1) auto result = transaction->Insert("test1", row); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 2); ASSERT_EQ(transaction->Commit(), E_OK); @@ -650,7 +656,7 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_014, TestSize.Level1) auto result = transaction->Insert("test1", row); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 4); ASSERT_EQ(transaction->Commit(), E_OK); @@ -699,7 +705,7 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_015, TestSize.Level1) auto result = transaction->Insert("test1", row); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 5); ASSERT_EQ(transaction->Commit(), E_OK); @@ -748,7 +754,7 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_016, TestSize.Level1) auto result = transaction->Insert("test1", row); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); // ON_CONFLICT_REPLACE is equivalent to ON_CONFLICT_ABORT after failure ASSERT_EQ(result.first, E_SQLITE_CONSTRAINT); ASSERT_EQ(result.second, 0); @@ -790,27 +796,27 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_017, TestSize.Level1) row.Put("name", "Jim_batchInsert"); rows.Put(row); } - auto result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_SQLITE_BUSY); ASSERT_EQ(result.second, -1); } @@ -841,34 +847,34 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_018, TestSize.Level1) row.Put("name", "Jim_batchInsert"); rows.Put(row); } - auto result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_INVALID_ARGS); ASSERT_EQ(result.second, -1); } /** * @tc.name: RdbStore_Transaction_019 - * @tc.desc: Normal BatchInsertWithConflictResolution + * @tc.desc: Normal BatchInsert * @tc.type: FUNC */ HWTEST_F(TransactionTest, RdbStore_Transaction_019, TestSize.Level1) @@ -882,13 +888,13 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_019, TestSize.Level1) ASSERT_NE(transaction, nullptr); ValuesBuckets rows; - auto result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_NONE); + auto result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_NONE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 0); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 0); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_ABORT); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 0); for (int i = 0; i < 2; i++) { @@ -896,13 +902,13 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_019, TestSize.Level1) row.Put("name", "Jim_batchInsert"); rows.Put(row); } - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_FAIL); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_IGNORE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); - result = transaction->BatchInsertWithConflictResolution("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); + result = transaction->BatchInsert("test1", rows, ConflictResolution::ON_CONFLICT_REPLACE); ASSERT_EQ(result.first, E_OK); ASSERT_EQ(result.second, 2); @@ -974,8 +980,7 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_021, TestSize.Level1) ret = transaction->Commit(); EXPECT_EQ(ret, E_OK); - auto [err, rows] = transaction->Insert( - "test", UTUtils::SetRowData(UTUtils::g_rowData[0]), Transaction::NO_ACTION); + auto [err, rows] = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0]), Transaction::NO_ACTION); EXPECT_EQ(err, E_ALREADY_CLOSED); } @@ -1032,7 +1037,7 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_023, TestSize.Level1) /** * @tc.name: RdbStore_Transaction_024 - * @tc.desc: Abnormal testcase of BatchInsertWithConflictResolution after commit. + * @tc.desc: Abnormal testcase of BatchInsert after commit. * @tc.type: FUNC */ HWTEST_F(TransactionTest, RdbStore_Transaction_024, TestSize.Level1) @@ -1053,9 +1058,11 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_024, TestSize.Level1) row.Put("name", "Jim"); rows.Put(row); } - auto result = transaction->BatchInsertWithConflictResolution( - "test", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); + auto result = transaction->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_ROLLBACK); ASSERT_EQ(result.first, E_ALREADY_CLOSED); + + auto res = transaction->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_ROLLBACK); + ASSERT_EQ(res.first, E_ALREADY_CLOSED); } /** @@ -1170,6 +1177,9 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_029, TestSize.Level1) auto result = transaction->Execute(CREATE_TABLE_SQL); ASSERT_EQ(result.first, E_ALREADY_CLOSED); + + auto res = transaction->ExecuteExt(CREATE_TABLE_SQL); + ASSERT_EQ(res.first, E_ALREADY_CLOSED); } /** @@ -1193,4 +1203,1404 @@ HWTEST_F(TransactionTest, RdbStore_Transaction_030, TestSize.Level1) ret = transaction->Rollback(); EXPECT_EQ(ret, E_ALREADY_CLOSED); -} \ No newline at end of file +} + +/** + * @tc.name: RdbStore_Transaction_031 + * @tc.desc: normal testcase of batch insert with returning 1. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_031, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + ValuesBuckets rows; + for (int i = 0; i < 1; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + std::string returningField = "id"; + auto [status, result] = transaction->BatchInsert("test", rows, { returningField }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1); + + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex(returningField, columnIndex), E_OK); + int value = -1; + result.results->GetInt(columnIndex, value); + EXPECT_EQ(value, 0); + ret = transaction->Commit(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_032 + * @tc.desc: normal testcase of batch insert with returning 0. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_032, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 2); + row.Put("name", "Jim"); + auto res = transaction->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 2); + rows.Put(row); + auto [status, result] = transaction->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 0); + ret = transaction->Commit(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_033 + * @tc.desc: normal testcase of batch insert with returning overlimit. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_033, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 1025; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto [status, result] = transaction->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + int rowCount = -1; + int maxRowCount = 1024; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, maxRowCount); + int colIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("id", colIndex), E_OK); + for (size_t i = 0; i < maxRowCount; i++) { + int value = -1; + ASSERT_EQ(result.results->GetInt(colIndex, value), E_OK); + EXPECT_EQ(value, i); + if (i != maxRowCount - 1) { + ASSERT_EQ(result.results->GoToNextRow(), E_OK); + } + } + + ret = transaction->Commit(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_034 + * @tc.desc: normal testcase of batch insert with not exist returning field. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_034, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::IMMEDIATE); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto [status, result] = + transaction->BatchInsert("test", rows, { "notExist" }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + ASSERT_EQ(result.results, nullptr); + + ret = transaction->Commit(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_035 + * @tc.desc: normal testcase of batch insert with Busy. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_035, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [res, transactionImme] = store->CreateTransaction(Transaction::IMMEDIATE); + ASSERT_EQ(res, E_OK); + ASSERT_NE(transactionImme, nullptr); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto [status, result] = transaction->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_SQLITE_BUSY); + EXPECT_EQ(result.changed, -1); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 0); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_036 + * @tc.desc: normal testcase of update with returning 1. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_036, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + Transaction::Row row; + row.Put("id", 1); + row.Put("name", "Jim"); + auto res = transaction->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 1); + + row.Put("name", "Bob"); + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 1); + auto [status, result] = transaction->Update(row, predicates, { "id" }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("id", columnIndex), E_OK); + int value = -1; + ASSERT_EQ(result.results->GetInt(columnIndex, value), E_OK); + EXPECT_EQ(value, 1); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_037 + * @tc.desc: abnormal testcase of update with returning 0. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_037, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + Transaction::Row row; + row.Put("id", 1); + row.Put("name", "Jim"); + auto res = transaction->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 1); + + row.Put("name", "Bob"); + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 2); + auto [status, result] = transaction->Update(row, predicates, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 0); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_038 + * @tc.desc: abnormal testcase of update with returning overlimit. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_038, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 1025; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto res = transaction->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(res.first, E_OK); + EXPECT_EQ(res.second, 1025); + + ValuesBucket row; + row.Put("name", "Tom"); + + AbsRdbPredicates predicates("test"); + auto [status, result] = transaction->Update(row, predicates, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1024); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_039 + * @tc.desc: abnormal testcase of update with returning not exist field. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_039, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 2; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto res = transaction->BatchInsert("test", rows, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(res.first, E_OK); + EXPECT_EQ(res.second, 2); + + ValuesBucket row; + row.Put("name", "Tom"); + + AbsRdbPredicates predicates("test"); + auto [status, result] = transaction->Update(row, predicates, { "notExist" }); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + ASSERT_EQ(result.results, nullptr); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_040 + * @tc.desc: abnormal testcase of update with Busy. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_040, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [res, transactionImme] = store->CreateTransaction(Transaction::IMMEDIATE); + ASSERT_EQ(res, E_OK); + ASSERT_NE(transactionImme, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 5; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto [status, result] = + transactionImme->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 5); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 5); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBucket row; + row.Put("name", "Tom"); + AbsRdbPredicates predicates("test"); + std::tie(status, result) = transaction->Update(row, predicates, { "id" }); + EXPECT_EQ(status, E_SQLITE_BUSY); + EXPECT_EQ(result.changed, -1); + + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 0); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_041 + * @tc.desc: normal testcase of delete with returning 1. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_041, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + Transaction::Row row; + row.Put("id", 1); + row.Put("name", "Jim"); + auto res = transaction->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 1); + + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 1); + auto [status, result] = transaction->Delete(predicates, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("id", columnIndex), E_OK); + int value = -1; + ASSERT_EQ(result.results->GetInt(columnIndex, value), E_OK); + EXPECT_EQ(value, 1); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_042 + * @tc.desc: normal testcase of delete with returning 0. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_042, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + Transaction::Row row; + row.Put("id", 1); + row.Put("name", "Jim"); + auto res = transaction->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + ASSERT_EQ(res.second, 1); + + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 2); + auto [status, result] = transaction->Delete(predicates, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 0); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_043 + * @tc.desc: abnormal testcase of delete with returning over limit. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_043, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 1025; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto [status, result] = transaction->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1024); + + AbsRdbPredicates predicates("test"); + std::tie(status, result) = transaction->Delete(predicates, { "id" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1024); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_044 + * @tc.desc: abnormal testcase of delete with returning no exist field. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_044, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + for (int i = 0; i < 2; i++) { + ValuesBucket row; + row.Put("id", i); + row.Put("name", "Jim"); + rows.Put(row); + } + auto [status, result] = transaction->BatchInsert("test", rows, { "id" }, ConflictResolution::ON_CONFLICT_ROLLBACK); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 2); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 2); + + AbsRdbPredicates predicates("test"); + std::tie(status, result) = transaction->Delete(predicates, { "noExist" }); + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + + ASSERT_EQ(result.results, nullptr); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_045 + * @tc.desc: normal testcase of execute with returning over limit. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_045, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + std::vector args = { "tt", 28, 50000.0, "ttt", 58, 500080.0 }; + auto [status, result] = + transaction->ExecuteExt("INSERT INTO test(name, age, salary) VALUES (?, ?, ?), (?, ?, ?) returning name", args); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 2); + + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 2); + + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "tt"); + ASSERT_EQ(result.results->GoToNextRow(), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "ttt"); + + std::tie(status, result) = + transaction->ExecuteExt("update test set name = ? where name = ? returning name", { "update", "tt" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1); + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + result.results->GetString(columnIndex, value); + EXPECT_EQ(value, "update"); + + std::tie(status, result) = transaction->ExecuteExt("delete from test returning name"); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 2); + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 2); + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "update"); + ASSERT_EQ(result.results->GoToNextRow(), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "ttt"); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_046 + * @tc.desc: abnormal testcase of execute with returning. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_046, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::IMMEDIATE); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + std::vector args = { "0", 0 }; + std::string sql = "INSERT INTO test(name, age) VALUES (?, ?)"; + for (int32_t i = 1; i < 1025; i++) { + sql.append(", (?, ?)"); + args.push_back(std::to_string(i)); + args.push_back(i); + } + auto [status, result] = transaction->ExecuteExt(sql + " returning name", args); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1024); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "0"); + ASSERT_EQ(result.results->GoToRow(1000), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "1000"); + + std::tie(status, result) = transaction->ExecuteExt("update test set name = ? returning name", { "update" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1024); + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "update"); + + std::tie(status, result) = transaction->ExecuteExt("delete from test returning name", {}); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1025); + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1024); + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "update"); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_047 + * @tc.desc: normal testcase of execute with returning 0 rows. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_047, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + std::vector args = { 1, "tt", 28, 50000.0 }; + auto [status, result] = + transaction->ExecuteExt("INSERT INTO test(id, name, age, salary) VALUES (?, ?, ?, ?) returning id", args); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("id", columnIndex), E_OK); + int64_t value; + ASSERT_EQ(result.results->GetLong(columnIndex, value), E_OK); + EXPECT_EQ(value, 1); + std::tie(status, result) = + transaction->ExecuteExt("INSERT INTO test(id, name, age, salary) VALUES (?, ?, ?, ?) returning id", args); + EXPECT_EQ(status, E_SQLITE_CONSTRAINT); + EXPECT_EQ(result.changed, 0); + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); + + std::tie(status, result) = + transaction->ExecuteExt("update test set name = ? where name = ? returning name", { "update", "noExist" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); + + std::tie(status, result) = transaction->ExecuteExt("delete from test where name = ? returning name", { "noExist" }); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 0); + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_048 + * @tc.desc: abnormal testcase of execute busy with returning. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_048, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [res, immeTrans] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(res, E_OK); + ASSERT_NE(immeTrans, nullptr); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + std::vector args = { 1, "tt", 28, 50000.0 }; + auto [status, result] = + transaction->ExecuteExt("INSERT INTO test(id, name, age, salary) VALUES (?, ?, ?, ?) returning id", args); + EXPECT_EQ(status, E_SQLITE_BUSY); + EXPECT_EQ(result.changed, -1); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); + + std::tie(status, result) = + transaction->ExecuteExt("update test set name = ? where name = ? returning name", { "update", "noExist" }); + EXPECT_EQ(status, E_SQLITE_BUSY); + EXPECT_EQ(result.changed, -1); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); + + + std::tie(status, result) = transaction->ExecuteExt("delete from test where name = ? returning name", { "noExist" }); + EXPECT_EQ(status, E_SQLITE_BUSY); + EXPECT_EQ(result.changed, -1); + rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 0); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_049 + * @tc.desc: Crash Occurs When Test Commit Fails + * This test case constructs a transaction commit failure scenario. + * A special command is used to operate the database file. + * To avoid affecting other test cases, this test case uses an independent database file. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_049, TestSize.Level1) +{ + const std::string dbPath = RDB_TEST_PATH + "transaction049_test.db"; + RdbHelper::DeleteRdbStore(dbPath); + RdbStoreConfig config(dbPath); + config.SetHaMode(HAMode::MAIN_REPLICA); // Dual-write must be enabled. + config.SetReadOnly(false); + TransactionTestOpenCallback helper; + int errCode = E_OK; + const int version = 1; + std::shared_ptr storePtr = RdbHelper::GetRdbStore(config, version, helper, errCode); + EXPECT_NE(storePtr, nullptr); + EXPECT_EQ(errCode, E_OK); + + storePtr->Execute("DROP TABLE IF EXISTS test1"); + auto res = storePtr->Execute("CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)"); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = storePtr->CreateTransaction(Transaction::IMMEDIATE); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + const int idValue = 1; + Transaction::Row row; + row.Put("id", idValue); + row.Put("name", "Jim"); + auto result = transaction->Insert("test1", row); + ASSERT_EQ(result.first, E_OK); + const int count = 1; + ASSERT_EQ(result.second, count); + + // Constructing a Commit Failure Scenario + std::string walFile = dbPath + "-wal"; + + // Disabling wal File Operations + std::string chattrAddiCmd = "chattr +i " + walFile; + system(chattrAddiCmd.c_str()); + + ret = transaction->Commit(); + EXPECT_NE(ret, E_OK); + + // Enable the wal file operation. + std::string chattrSubiCmd = "chattr -i " + walFile; + system(chattrSubiCmd.c_str()); + + RdbHelper::DeleteRdbStore(dbPath); +} + +/** + * @tc.name: RdbStore_Transaction_050 + * @tc.desc: abnormal testcase of trigger delete with returning in trans. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_050, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [res, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(res, E_OK); + ASSERT_NE(transaction, nullptr); + + auto [code, result1] = transaction->Execute( + "CREATE TRIGGER before_update BEFORE UPDATE ON test" + " BEGIN DELETE FROM test WHERE name = 'wang'; END"); + EXPECT_EQ(code, E_OK); + + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 200); + row.Put("name", "wang"); + rows.Put(std::move(row)); + row.Put("id", 201); + row.Put("name", "zhang"); + rows.Put(std::move(row)); + + auto [status, result] = + transaction->BatchInsert("test", rows, { "name" }, ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 2); + ASSERT_NE(result.results, nullptr); + + auto predicates = AbsRdbPredicates("test"); + predicates.EqualTo("name", "zhang"); + ValuesBucket values; + values.PutString("name", "liu"); + + std::tie(status, result) = transaction->Update(values, predicates, { "name" }); + + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + int columnIndex = -1; + ASSERT_EQ(result.results->GetColumnIndex("name", columnIndex), E_OK); + std::string value; + ASSERT_EQ(result.results->GetString(columnIndex, value), E_OK); + EXPECT_EQ(value, "liu"); + + // Check the trigger effect + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + + rowCount = -1; + resultSet->GetRowCount(rowCount); + ASSERT_EQ(rowCount, 1); + + transaction->Execute("DROP TRIGGER IF EXISTS before_update"); + + int ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_051 + * @tc.desc: abnormal testcase of trigger update with returning in trans. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_051, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [res, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(res, E_OK); + ASSERT_NE(transaction, nullptr); + + auto [code, result1] = transaction->Execute( + "CREATE TRIGGER before_delete BEFORE DELETE ON test" + " BEGIN UPDATE test SET name = 'li' WHERE name = 'zhao'; END"); + EXPECT_EQ(code, E_OK); + + ValuesBuckets rows; + ValuesBucket row; + row.Put("id", 201); + row.Put("name", "zhang"); + rows.Put(std::move(row)); + row.Put("id", 202); + row.Put("name", "zhao"); + rows.Put(std::move(row)); + + auto [status, result] = + transaction->BatchInsert("test", rows, { "name" }, ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 2); + ASSERT_NE(result.results, nullptr); + + AbsRdbPredicates predicates("test"); + predicates.EqualTo("name", "zhang"); + std::tie(status, result) = transaction->Delete(predicates, { "name" }); + + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + ASSERT_EQ(rowCount, 1); + std::string value; + ASSERT_EQ(result.results->GetString(0, value), E_OK); + EXPECT_EQ(value, "zhang"); + + // Check the trigger effect + AbsRdbPredicates predicates1("test"); + predicates1.EqualTo("id", 202); + auto queryResult = transaction->QueryByStep(predicates1, { "name" }); + + rowCount = -1; + queryResult->GetRowCount(rowCount); + ASSERT_EQ(rowCount, 1); + ASSERT_EQ(queryResult->GoToNextRow(), E_OK); + + value.clear(); + EXPECT_EQ(E_OK, queryResult->GetString(0, value)); + EXPECT_EQ(value, "li"); + + transaction->Execute("DROP TRIGGER IF EXISTS before_update"); + + int ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_052 + * @tc.desc: abnormal testcase of virtual table with returning in transaction. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_052, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + auto [createTableStatus, createTableresult] = + store->Execute("CREATE VIRTUAL TABLE IF NOT EXISTS articles USING fts5(title, content);"); + + auto [res, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(res, E_OK); + ASSERT_NE(transaction, nullptr); + + ValuesBuckets rows; + ValuesBucket row; + row.Put("title", "fts5"); + row.Put("content", "test virtual tables"); + rows.Put(std::move(row)); + auto [status, result] = + transaction->BatchInsert("articles", rows, {"title"}, ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(result.changed, 1); + ASSERT_NE(result.results, nullptr); + int rowCount = -1; + ASSERT_EQ(result.results->GetRowCount(rowCount), E_OK); + EXPECT_EQ(rowCount, 1); + RowEntity rowEntity; + EXPECT_EQ(result.results->GetRow(rowEntity), E_OK); + EXPECT_EQ(std::string(rowEntity.Get("title")), "fts5"); + + AbsRdbPredicates predicates("test"); + predicates.EqualTo("title", "fts5"); + ValuesBucket values; + values.PutString("title", "fts5 updated"); + + std::tie(status, result) = transaction->Update(values, predicates, { "title" }); + // UPDATE RETURNING is not available on virtual tables + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + EXPECT_EQ(result.results, nullptr); + + std::tie(status, result) = store_->Delete(predicates, { "title" }); + // DELETE RETURNING is not available on virtual tables + EXPECT_EQ(status, E_SQLITE_ERROR); + EXPECT_EQ(result.changed, -1); + + transaction->Execute("Drop TABLE articles"); + EXPECT_EQ(transaction->Rollback(), E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_053 + * @tc.desc: abnormal testcase of drop the table before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_053, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + int rowCount = 0; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + auto [rs, obj] = transaction->Execute("DROP TABLE test"); + ASSERT_EQ(rs, E_SQLITE_LOCKED); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + rs = transaction->Rollback(); + ASSERT_EQ(rs, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_054 + * @tc.desc: abnormal testcase of drop the table before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_054, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + int rowCount = 0; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount - 1; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + auto [rs, obj] = transaction->Execute("DROP TABLE test"); + ASSERT_EQ(rs, E_SQLITE_LOCKED); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + rs = transaction->Rollback(); + ASSERT_EQ(rs, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_055 + * @tc.desc: normal testcase of drop the table after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_055, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [rt, object] = store->Execute(CREATE_TABLE1_SQL); + ASSERT_EQ(rt, E_OK); + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test1", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test1", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test1"); + int rowCount = 0; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + ret = resultSet->Close(); + ASSERT_EQ(ret, E_OK); + + auto [rs, obj] = transaction->Execute("DROP TABLE test1"); + ASSERT_EQ(rs, E_OK); + + rs = transaction->Commit(); + ASSERT_EQ(rs, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_056 + * @tc.desc: abnormal testcase of drop the index before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_056, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [rt, object] = store->Execute("CREATE INDEX test_index ON test(age)"); + ASSERT_EQ(rt, E_OK); + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + int rowCount = 0; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + auto [rs, obj] = transaction->Execute("DROP INDEX test_index"); + ASSERT_EQ(rs, E_SQLITE_LOCKED); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + rs = transaction->Rollback(); + ASSERT_EQ(rs, E_OK); + + std::tie(rt, object) = store->Execute("DROP INDEX test_index"); + ASSERT_EQ(rt, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_057 + * @tc.desc: abnormal testcase of drop the index before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_057, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [rt, object] = store->Execute("CREATE INDEX test_index ON test(age)"); + ASSERT_EQ(rt, E_OK); + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + int rowCount = 0; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount - 1; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + auto [rs, obj] = transaction->Execute("DROP INDEX test_index"); + ASSERT_EQ(rs, E_SQLITE_LOCKED); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + rs = transaction->Rollback(); + ASSERT_EQ(rs, E_OK); + + std::tie(rt, object) = store->Execute("DROP INDEX test_index"); + ASSERT_EQ(rt, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_058 + * @tc.desc: normal testcase of drop the index after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_058, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [rt, object] = store->Execute("CREATE INDEX test_index ON test(age)"); + ASSERT_EQ(rt, E_OK); + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + int rowCount = 0; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + ret = resultSet->Close(); + ASSERT_EQ(ret, E_OK); + + auto [rs, obj] = transaction->Execute("DROP INDEX test_index"); + ASSERT_EQ(rs, E_OK); + + rs = transaction->Commit(); + ASSERT_EQ(rs, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_059 + * @tc.desc: normal testcase of drop the table after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_059, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [rt, object] = store->Execute(CREATE_TABLE1_SQL); + ASSERT_EQ(rt, E_OK); + + auto [res, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(res, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test1"); + int rowCount = 0; + auto ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + auto [rs, obj] = transaction->Execute("DROP TABLE test1"); + ASSERT_EQ(rs, E_OK); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + + rs = transaction->Commit(); + ASSERT_EQ(rs, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_060 + * @tc.desc: normal testcase of drop the index after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_060, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [rt, object] = store->Execute("CREATE INDEX test_index ON test(age)"); + ASSERT_EQ(rt, E_OK); + + auto [res, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(res, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + int rowCount = 0; + auto ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + auto [rs, obj] = transaction->Execute("DROP INDEX test_index"); + ASSERT_EQ(rs, E_OK); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + + rs = transaction->Commit(); + ASSERT_EQ(rs, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_061 + * @tc.desc: abnormal testcase of drop the table before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_061, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [rt, object] = store->Execute(CREATE_TABLE1_SQL); + ASSERT_EQ(rt, E_OK); + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + int rowCount = 0; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + auto [rs, obj] = transaction->Execute("DROP TABLE test1"); + ASSERT_EQ(rs, E_SQLITE_LOCKED); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + rs = transaction->Rollback(); + ASSERT_EQ(rs, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_062 + * @tc.desc: abnormal testcase of drop the table before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_062, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + + auto [rs, obj] = transaction->Execute("DROP TABLE test"); + ASSERT_EQ(rs, E_OK); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + rs = transaction->Rollback(); + ASSERT_EQ(rs, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_063 + * @tc.desc: normal testcase of drop the table before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_063, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + ValuesBucket row; + row.Put("name", "Jim"); + auto res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + res = store->Insert("test", row); + ASSERT_EQ(res.first, E_OK); + + auto [ret, transaction] = store->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(ret, E_OK); + ASSERT_NE(transaction, nullptr); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + int rowCount = 0; + ret = resultSet->GetRowCount(rowCount); + ASSERT_EQ(ret, E_OK); + for (int i = 0; i < rowCount; i++) { + ret = resultSet->GoToNextRow(); + ASSERT_EQ(ret, E_OK); + } + + ret = resultSet->GoToNextRow(); + ASSERT_NE(ret, E_OK); + + auto [rs, obj] = transaction->Execute("DROP TABLE test"); + ASSERT_EQ(rs, E_OK); + + rs = resultSet->Close(); + ASSERT_EQ(rs, E_OK); + rs = transaction->Rollback(); + ASSERT_EQ(rs, E_OK); +} diff --git a/relational_store/test/native/rdb_data_ability_adapter/BUILD.gn b/relational_store/test/native/rdb_data_ability_adapter/BUILD.gn index 2f8e645b..51c3ad6c 100644 --- a/relational_store/test/native/rdb_data_ability_adapter/BUILD.gn +++ b/relational_store/test/native/rdb_data_ability_adapter/BUILD.gn @@ -11,7 +11,6 @@ # See the License for the specific language governing permissions and # limitations under the License. import("//build/test.gni") -import("//foundation/distributeddatamgr/data_share/datashare.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") module_output_path = @@ -22,10 +21,8 @@ config("module_private_config") { visibility = [ ":*" ] include_dirs = [ - "${datashare_innerapi_path}/common/include", "${relational_store_innerapi_path}/dataability/include", "${relational_store_innerapi_path}/rdb_data_ability_adapter/include", - "//commonlibrary/c_utils/base/include", ] } @@ -38,15 +35,15 @@ ohos_unittest("NativeDataAbilityAdapterTest") { external_deps = [ "c_utils:utils", + "data_share:datashare_common_lite", + "googletest:gtest_main", "hilog:libhilog", + "ipc:ipc_single", "relational_store:native_dataability", "relational_store:rdb_data_ability_adapter", ] - deps = [ - "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", - ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] } ############################################################################### diff --git a/relational_store/test/native/rdb_data_share_adapter/BUILD.gn b/relational_store/test/native/rdb_data_share_adapter/BUILD.gn index 70a8a93b..e00a6209 100644 --- a/relational_store/test/native/rdb_data_share_adapter/BUILD.gn +++ b/relational_store/test/native/rdb_data_share_adapter/BUILD.gn @@ -11,7 +11,6 @@ # See the License for the specific language governing permissions and # limitations under the License. import("//build/test.gni") -import("//foundation/distributeddatamgr/data_share/datashare.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") module_output_path = "relational_store/relational_store/rdb_data_share_adapter" @@ -23,27 +22,16 @@ config("module_private_config") { include_dirs = [ "${relational_store_common_path}/include", "${relational_store_native_path}/rdb_data_share_adapter/include", - "${datashare_common_native_path}/include", "${relational_store_innerapi_path}/rdb/src", "${relational_store_innerapi_path}/rdb_data_share_adapter/src", - "${datashare_base_path}/interfaces/inner_api/common/include", - "${datashare_base_path}/interfaces/inner_api/consumer/include", - "${datashare_base_path}/interfaces/inner_api/provider/include", "${relational_store_innerapi_path}/rdb/include", "${relational_store_innerapi_path}/rdb_data_share_adapter/include", - "//commonlibrary/c_utils/base/include", ] cflags = [ "-fno-access-control", #Ignore Private Member Access Control ] - if (relational_store_rdb_support_icu) { - include_dirs += [ - "//third_party/icu/icu4c/source/i18n", - "//third_party/icu/icu4c/source/common", - ] - } } ohos_unittest("RdbDataShareAdapterTest") { @@ -55,16 +43,22 @@ ohos_unittest("RdbDataShareAdapterTest") { external_deps = [ "c_utils:utils", + "data_share:datashare_common_lite", + "googletest:gmock", + "googletest:gtest_main", "hilog:libhilog", + "ipc:ipc_single", "relational_store:rdb_data_share_adapter", ] - deps = [ - "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", - "//third_party/icu/icu4c:shared_icui18n", - "//third_party/icu/icu4c:shared_icuuc", - ] + if (relational_store_rdb_support_icu) { + external_deps += [ + "icu:shared_icui18n", + "icu:shared_icuuc", + ] + } + + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] } ############################################################################### diff --git a/relational_store/test/native/rdb_data_share_adapter/unittest/rdb_data_share_adapter_test.cpp b/relational_store/test/native/rdb_data_share_adapter/unittest/rdb_data_share_adapter_test.cpp index 2c4ee8c1..210881ee 100644 --- a/relational_store/test/native/rdb_data_share_adapter/unittest/rdb_data_share_adapter_test.cpp +++ b/relational_store/test/native/rdb_data_share_adapter/unittest/rdb_data_share_adapter_test.cpp @@ -1,524 +1,788 @@ -/* - * Copyright (c) 2022 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. - */ -#define LOG_TAG "RdbDataShareAdapterTest" -#include - -#include - -#include "datashare_predicates.h" -#include "logger.h" -#include "rdb_errno.h" -#include "rdb_helper.h" -#include "rdb_open_callback.h" -#include "rdb_utils.h" - -using namespace testing::ext; -using namespace OHOS::Rdb; -using namespace OHOS::NativeRdb; -using namespace OHOS::DataShare; -using namespace OHOS::RdbDataShareAdapter; - -class RdbDataShareAdapterTest : public testing::Test { -public: - static void SetUpTestCase(void); - - static void TearDownTestCase(void); - - void SetUp(); - - void TearDown(); - - void GenerateDefaultTable(); - - void GenerateDefaultEmptyTable(); - - int ResultSize(std::shared_ptr resultSet); - - static const std::string DATABASE_NAME; - static std::shared_ptr store; - static const std::string RDB_ADAPTER_TEST_PATH; -}; - -const std::string RdbDataShareAdapterTest::RDB_ADAPTER_TEST_PATH = "/data/test/"; -const std::string RdbDataShareAdapterTest::DATABASE_NAME = RDB_ADAPTER_TEST_PATH + "rdbDataShareAdapter_test.db"; -std::shared_ptr RdbDataShareAdapterTest::store = nullptr; - -class RdbStepSharedResultSetOpenCallback : public RdbOpenCallback { -public: - int OnCreate(RdbStore &store) override; - - int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; - - static const std::string CREATE_TABLE_TEST; -}; - -int RdbStepSharedResultSetOpenCallback::OnCreate(RdbStore &store) -{ - return OHOS::NativeRdb::E_OK; -} - -int RdbStepSharedResultSetOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) -{ - return OHOS::NativeRdb::E_OK; -} - -void RdbDataShareAdapterTest::SetUpTestCase(void) -{ - int errCode = OHOS::NativeRdb::E_OK; - RdbStoreConfig config(RdbDataShareAdapterTest::DATABASE_NAME); - RdbStepSharedResultSetOpenCallback helper; - RdbDataShareAdapterTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(RdbDataShareAdapterTest::store, nullptr); - EXPECT_EQ(errCode, OHOS::NativeRdb::E_OK); -} - -void RdbDataShareAdapterTest::TearDownTestCase(void) -{ - RdbHelper::DeleteRdbStore(RdbDataShareAdapterTest::DATABASE_NAME); -} - -void RdbDataShareAdapterTest::SetUp(void) -{ - store->ExecuteSql("DROP TABLE IF EXISTS test"); -} - -void RdbDataShareAdapterTest::TearDown(void) -{ - RdbHelper::ClearCache(); -} - -void RdbDataShareAdapterTest::GenerateDefaultTable() -{ - std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, ") + - std::string("data2 INTEGER, data3 FLOAT, data4 BLOB);"); - store->ExecuteSql(createTableSql); - - std::string insertSql = "INSERT INTO test (data1, data2, data3, data4) VALUES (?, ?, ?, ?);"; - - /* insert first entry data */ - uint8_t uValue = 66; - std::vector typeBlob; - typeBlob.push_back(uValue); - store->ExecuteSql(insertSql, std::vector{ ValueObject(std::string("hello")), ValueObject((int)10), - ValueObject((double)1.0), ValueObject((std::vector)typeBlob) }); - - /* insert second entry data */ - typeBlob.clear(); - store->ExecuteSql(insertSql, std::vector{ - ValueObject(std::string("2")), ValueObject((int)-5), ValueObject((double)2.5), - ValueObject() // set double value 2.5 - }); - - /* insert third entry data */ - store->ExecuteSql(insertSql, std::vector{ - ValueObject(std::string("hello world")), ValueObject((int)3), ValueObject((double)1.8), - ValueObject(std::vector{ 4, 5, 6 }) // set int value 3, double 1.8 - }); - - /* insert four entry data */ - store->ExecuteSql(insertSql, std::vector{ - ValueObject(std::string("new world")), ValueObject((int)5), - ValueObject((double)5.8), ValueObject() // set int value 5, double 5.8 - }); -} - -void RdbDataShareAdapterTest::GenerateDefaultEmptyTable() -{ - std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, ") + - std::string("data2 INTEGER, data3 FLOAT, data4 BLOB);"); - store->ExecuteSql(createTableSql); -} - -int RdbDataShareAdapterTest::ResultSize(std::shared_ptr resultSet) -{ - if (resultSet->GoToFirstRow() != OHOS::NativeRdb::E_OK) { - return 0; - } - int count = 1; - while (resultSet->GoToNextRow() == OHOS::NativeRdb::E_OK) { - count++; - } - return count; -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_001 - * @tc.desc: test RdbDataShareAdapter - * @tc.type: FUNC - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_001, TestSize.Level1) -{ - GenerateDefaultTable(); - - std::shared_ptr resultSet = store->QueryByStep("SELECT * FROM test"); - EXPECT_NE(resultSet, nullptr); - int rowCount; - resultSet.get()->GetRowCount(rowCount); - LOG_INFO("result row count: %{public}d", rowCount); - EXPECT_NE(rowCount, 0); - auto bridge = OHOS::RdbDataShareAdapter::RdbUtils::ToResultSetBridge(resultSet); - EXPECT_NE(bridge, nullptr); -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_002 - * @tc.desc: normal testcase of RdbDataShareAdapter - * @tc.type: FUNC - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_002, TestSize.Level1) -{ - GenerateDefaultTable(); - - std::string table = "test"; - std::string column = "data1"; - std::string value = "hello"; - DataSharePredicates predicates; - predicates.EqualTo(column, value); - std::vector columns; - auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); - int rowCount; - allDataTypes.get()->GetRowCount(rowCount); - EXPECT_EQ(rowCount, 1); -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_003 - * @tc.desc: normal testcase of RdbDataShareAdapter - * @tc.type: FUNC - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_003, TestSize.Level1) -{ - GenerateDefaultTable(); - - std::string table = "test"; - OHOS::DataShare::DataSharePredicates predicates; - predicates.GreaterThan("data2", -5); - std::vector columns; - auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); - int rdbRowCount; - allDataTypes.get()->GetRowCount(rdbRowCount); - EXPECT_EQ(rdbRowCount, 3); - - allDataTypes->GoToFirstRow(); - - std::string strValue; - allDataTypes->GetString(1, strValue); - EXPECT_EQ("hello", strValue); - - int intValue; - allDataTypes->GetInt(2, intValue); - EXPECT_EQ(intValue, 10); - - std::vector blobValue; - uint8_t blobData = 66; - allDataTypes->GetBlob(4, blobValue); - EXPECT_EQ(blobData, blobValue[0]); - - allDataTypes->GoToNextRow(); - allDataTypes->GetBlob(4, blobValue); - EXPECT_EQ(3, static_cast(blobValue.size())); - blobData = 5; - EXPECT_EQ(blobData, blobValue[1]); -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_004 - * @tc.desc: normal testcase of RdbDataShareAdapter - * @tc.type: FUNC - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_004, TestSize.Level1) -{ - GenerateDefaultTable(); - - std::string table = "test"; - OHOS::DataShare::DataSharePredicates predicates; - predicates.SetWhereClause("`data2` > ?"); - predicates.SetWhereArgs(std::vector{ "-5" }); - predicates.SetOrder("data3"); - std::vector columns; - auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); - int rowCount; - allDataTypes.get()->GetRowCount(rowCount); - EXPECT_EQ(rowCount, 3); - - allDataTypes->GoToFirstRow(); - - std::string strValue; - allDataTypes->GetString(1, strValue); - EXPECT_EQ("hello", strValue); - - int intValue; - allDataTypes->GetInt(2, intValue); - EXPECT_EQ(intValue, 10); - - std::vector blobValue; - allDataTypes->GetBlob(4, blobValue); - EXPECT_EQ(1, static_cast(blobValue.size())); - - allDataTypes->GoToNextRow(); - - allDataTypes->GetString(1, strValue); - EXPECT_EQ("hello world", strValue); - - allDataTypes->GetInt(2, intValue); - EXPECT_EQ(intValue, 3); - - allDataTypes->GetBlob(4, blobValue); - EXPECT_EQ(3, static_cast(blobValue.size())); - uint8_t blobData = 5; - EXPECT_EQ(blobData, blobValue[1]); -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_005 - * @tc.desc: normal testcase of RdbDataShareAdapter - * @tc.type: FUNC - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_005, TestSize.Level1) -{ - GenerateDefaultTable(); - DataShareValuesBucket values; - int64_t id; - int changedRows; - values.Put("data1", std::string("tulip")); - values.Put("data2", 100); - values.Put("data3", 50.5); - values.Put("data4", std::vector{ 20, 21, 22 }); - - int ret = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); - EXPECT_EQ(ret, OHOS::NativeRdb::E_OK); - EXPECT_EQ(5, id); - - std::string table = "test"; - OHOS::DataShare::DataSharePredicates predicates; - std::string value = "tulip"; - predicates.EqualTo("data1", value); - std::vector columns; - auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); - int rowCount; - allDataTypes.get()->GetRowCount(rowCount); - EXPECT_EQ(rowCount, 1); - - allDataTypes.get()->Close(); - - values.Clear(); - values.Put("data3", 300.5); - values.Put("data4", std::vector{ 17, 18, 19 }); - ret = store->Update( - changedRows, "test", RdbUtils::ToValuesBucket(values), "data1 = ?", std::vector{ "tulip" }); - EXPECT_EQ(ret, OHOS::NativeRdb::E_OK); - EXPECT_EQ(1, changedRows); - - allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); - allDataTypes->GoToFirstRow(); - - double doubleVal; - allDataTypes->GetDouble(3, doubleVal); - EXPECT_EQ(300.5, doubleVal); - - int deletedRows; - ret = store->Delete(deletedRows, RdbUtils::ToPredicates(predicates, table)); - EXPECT_EQ(ret, OHOS::NativeRdb::E_OK); - EXPECT_EQ(1, deletedRows); -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_006 - * @tc.desc: normal testcase of RdbDataShareAdapter - * @tc.type: FUNC - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_006, TestSize.Level1) -{ - GenerateDefaultTable(); - - std::string table = "test"; - OHOS::DataShare::DataSharePredicates predicates; - predicates.Limit(1, 2); - std::vector columns; - auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); - int rdbRowCount; - allDataTypes.get()->GetRowCount(rdbRowCount); - EXPECT_EQ(rdbRowCount, 1); - - allDataTypes->GoToFirstRow(); - - std::string strValue; - allDataTypes->GetString(1, strValue); - EXPECT_EQ("hello world", strValue); - - int intValue; - allDataTypes->GetInt(2, intValue); - EXPECT_EQ(intValue, 3); - - double doubleValue; - allDataTypes->GetDouble(3, doubleValue); - EXPECT_EQ(doubleValue, 1.8); - - std::vector blobValue; - uint8_t blobData1 = 4; - uint8_t blobData2 = 5; - uint8_t blobData3 = 6; - allDataTypes->GetBlob(4, blobValue); - EXPECT_EQ(3, static_cast(blobValue.size())); - EXPECT_EQ(blobData1, blobValue[0]); - EXPECT_EQ(blobData2, blobValue[1]); - EXPECT_EQ(blobData3, blobValue[2]); -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_007 - * @tc.desc: normal testcase of RdbDataShareAdapter - * @tc.type: FUNC - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_007, TestSize.Level1) -{ - std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT,") + - std::string("age INTEGER, salary REAL);"); - store->ExecuteSql(createTableSql); - - DataShareValuesBucket values; - int64_t id; - values.Put("name", std::string("zhangsan")); - values.Put("age", INT64_MIN); - values.Put("salary", DBL_MIN); - int ret1 = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); - EXPECT_EQ(ret1, OHOS::NativeRdb::E_OK); - EXPECT_EQ(1, id); - - values.Clear(); - values.Put("name", std::string("lisi")); - values.Put("age", INT64_MAX); - values.Put("salary", DBL_MAX); - int ret2 = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); - EXPECT_EQ(ret2, OHOS::NativeRdb::E_OK); - EXPECT_EQ(2, id); - - std::string table = "test"; - OHOS::DataShare::DataSharePredicates predicates; - std::vector columns; - auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); - - allDataTypes->GoToFirstRow(); - int64_t int64Value; - allDataTypes->GetLong(2, int64Value); - EXPECT_EQ(int64Value, INT64_MIN); - - double doubleVal; - allDataTypes->GetDouble(3, doubleVal); - EXPECT_EQ(doubleVal, DBL_MIN); - - allDataTypes->GoToNextRow(); - - allDataTypes->GetLong(2, int64Value); - EXPECT_EQ(int64Value, INT64_MAX); - - allDataTypes->GetDouble(3, doubleVal); - EXPECT_EQ(doubleVal, DBL_MAX); -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_008 - * @tc.desc: normal testcase of query double - * @tc.type: test double for high accuracy - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_008, TestSize.Level1) -{ - std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 double,") + - std::string("data2 double, data3 TEXT);"); - store->ExecuteSql(createTableSql); - - ValuesBucket values; - int64_t id; - double data1 = 1.777777777777; - double data2 = 1.888888888888; - std::string data3 = "zh-has"; - std::string tableName = "test"; - - values.PutDouble("data1", data1); - values.PutDouble("data2", data2); - values.PutString("data3", data3); - int ret = store->Insert(id, tableName, values); - EXPECT_EQ(ret, OHOS::NativeRdb::E_OK); - EXPECT_EQ(1, id); - - OHOS::DataShare::DataSharePredicates predicates; - predicates.BeginWrap() - ->EqualTo("data1", data1) - ->And() - ->EqualTo("data2", data2) - ->And() - ->EqualTo("data3", data3) - ->EndWrap(); - std::vector columns; - auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, tableName), columns); - int rowCount; - int ok = allDataTypes->GetRowCount(rowCount); - EXPECT_EQ(ok, OHOS::NativeRdb::E_OK); - EXPECT_EQ(1, rowCount); -} - -/* * - * @tc.name: Rdb_DataShare_Adapter_009 - * @tc.desc: normal testcase of RdbDataShareAdapter - * @tc.type: FUNC - */ -HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_009, TestSize.Level1) -{ - std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT,") + - std::string("age INTEGER, salary REAL);"); - store->ExecuteSql(createTableSql); - - DataShareValuesBucket values; - int64_t id; - values.Put("name", std::string("zhangsan")); - values.Put("age", INT64_MIN); - values.Put("salary", DBL_MIN); - int ret1 = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); - EXPECT_EQ(ret1, OHOS::NativeRdb::E_OK); - EXPECT_EQ(1, id); - - values.Clear(); - values.Put("name", std::string("lisi")); - values.Put("age", INT64_MAX); - values.Put("salary", DBL_MAX); - int ret2 = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); - EXPECT_EQ(ret2, OHOS::NativeRdb::E_OK); - EXPECT_EQ(2, id); - - std::string table = "test"; - OHOS::DataShare::OperationItem item; - item.singleParams = {}; - RdbPredicates predicates("test"); - RdbUtils::EqualTo(item, predicates); - std::vector columns; - std::shared_ptr allPerson = store->Query(predicates, columns); - EXPECT_EQ(2, ResultSize(allPerson)); - - RdbUtils::GreaterThan(item, predicates); - allPerson = store->Query(predicates, columns); - EXPECT_EQ(2, ResultSize(allPerson)); - - RdbUtils::Limit(item, predicates); - allPerson = store->Query(predicates, columns); - EXPECT_EQ(2, ResultSize(allPerson)); - - RdbUtils::NotEqualTo(item, predicates); - allPerson = store->Query(predicates, columns); - EXPECT_EQ(2, ResultSize(allPerson)); - - RdbUtils::LessThan(item, predicates); - allPerson = store->Query(predicates, columns); - EXPECT_EQ(2, ResultSize(allPerson)); -} +///* +// * Copyright (c) 2022 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. +// */ +//#define LOG_TAG "RdbDataShareAdapterTest" +//#include +//#include +// +//#include +// +//#include "datashare_predicates.h" +//#include "logger.h" +//#include "rdb_errno.h" +//#include "rdb_helper.h" +//#include "rdb_open_callback.h" +//#include "rdb_utils.h" +// +//using namespace testing::ext; +//using namespace OHOS::Rdb; +//using namespace OHOS::NativeRdb; +//using namespace OHOS::DataShare; +//using namespace OHOS::RdbDataShareAdapter; +// +//class RdbDataShareAdapterTest : public testing::Test { +//public: +// static void SetUpTestCase(void); +// +// static void TearDownTestCase(void); +// +// void SetUp(); +// +// void TearDown(); +// +// void GenerateDefaultTable(); +// +// void GenerateDefaultEmptyTable(); +// +// int ResultSize(std::shared_ptr resultSet); +// +// static const std::string DATABASE_NAME; +// static std::shared_ptr store; +// static const std::string RDB_ADAPTER_TEST_PATH; +//}; +// +//const std::string RdbDataShareAdapterTest::RDB_ADAPTER_TEST_PATH = "/data/test/"; +//const std::string RdbDataShareAdapterTest::DATABASE_NAME = RDB_ADAPTER_TEST_PATH + "rdbDataShareAdapter_test.db"; +//std::shared_ptr RdbDataShareAdapterTest::store = nullptr; +// +//class RdbStepSharedResultSetOpenCallback : public RdbOpenCallback { +//public: +// int OnCreate(RdbStore &store) override; +// +// int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +// +// static const std::string CREATE_TABLE_TEST; +//}; +// +//int RdbStepSharedResultSetOpenCallback::OnCreate(RdbStore &store) +//{ +// return OHOS::NativeRdb::E_OK; +//} +// +//int RdbStepSharedResultSetOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +//{ +// return OHOS::NativeRdb::E_OK; +//} +// +//void RdbDataShareAdapterTest::SetUpTestCase(void) +//{ +// int errCode = OHOS::NativeRdb::E_OK; +// RdbStoreConfig config(RdbDataShareAdapterTest::DATABASE_NAME); +// RdbStepSharedResultSetOpenCallback helper; +// RdbDataShareAdapterTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); +// EXPECT_NE(RdbDataShareAdapterTest::store, nullptr); +// EXPECT_EQ(errCode, OHOS::NativeRdb::E_OK); +//} +// +//void RdbDataShareAdapterTest::TearDownTestCase(void) +//{ +// RdbHelper::DeleteRdbStore(RdbDataShareAdapterTest::DATABASE_NAME); +//} +// +//void RdbDataShareAdapterTest::SetUp(void) +//{ +// store->ExecuteSql("DROP TABLE IF EXISTS test"); +//} +// +//void RdbDataShareAdapterTest::TearDown(void) +//{ +// RdbHelper::ClearCache(); +//} +// +//void RdbDataShareAdapterTest::GenerateDefaultTable() +//{ +// std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, ") + +// std::string("data2 INTEGER, data3 FLOAT, data4 BLOB);"); +// store->ExecuteSql(createTableSql); +// +// std::string insertSql = "INSERT INTO test (data1, data2, data3, data4) VALUES (?, ?, ?, ?);"; +// +// /* insert first entry data */ +// uint8_t uValue = 66; +// std::vector typeBlob; +// typeBlob.push_back(uValue); +// store->ExecuteSql(insertSql, std::vector{ ValueObject(std::string("hello")), ValueObject((int)10), +// ValueObject((double)1.0), ValueObject((std::vector)typeBlob) }); +// +// /* insert second entry data */ +// typeBlob.clear(); +// store->ExecuteSql(insertSql, std::vector{ +// ValueObject(std::string("2")), ValueObject((int)-5), ValueObject((double)2.5), +// ValueObject() // set double value 2.5 +// }); +// +// /* insert third entry data */ +// store->ExecuteSql( +// insertSql, std::vector{ +// ValueObject(std::string("hello world")), ValueObject((int)3), ValueObject((double)1.8), +// ValueObject(std::vector{ 4, 5, 6 }) // set int value 3, double 1.8 +// }); +// +// /* insert four entry data */ +// store->ExecuteSql(insertSql, std::vector{ +// ValueObject(std::string("new world")), ValueObject((int)5), +// ValueObject((double)5.8), ValueObject() // set int value 5, double 5.8 +// }); +//} +// +//void RdbDataShareAdapterTest::GenerateDefaultEmptyTable() +//{ +// std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, ") + +// std::string("data2 INTEGER, data3 FLOAT, data4 BLOB);"); +// store->ExecuteSql(createTableSql); +//} +// +//int RdbDataShareAdapterTest::ResultSize(std::shared_ptr resultSet) +//{ +// if (resultSet->GoToFirstRow() != OHOS::NativeRdb::E_OK) { +// return 0; +// } +// int count = 1; +// while (resultSet->GoToNextRow() == OHOS::NativeRdb::E_OK) { +// count++; +// } +// return count; +//} +// +//OperationItem RdbDataShareAdapterTest::CreateOperationItem(int operation, +// const std::vector &singleParams = {}, const std::vector &multiParams = {}) +//{ +// OperationItem item; +// item.operation = operation; +// item.singleParams = singleParams; +// item.multiParams = multiParams; +// return item; +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_001 +// * @tc.desc: test RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_001, TestSize.Level1) +//{ +// GenerateDefaultTable(); +// +// std::shared_ptr resultSet = store->QueryByStep("SELECT * FROM test"); +// EXPECT_NE(resultSet, nullptr); +// int rowCount; +// resultSet.get()->GetRowCount(rowCount); +// LOG_INFO("result row count: %{public}d", rowCount); +// EXPECT_NE(rowCount, 0); +// auto bridge = OHOS::RdbDataShareAdapter::RdbUtils::ToResultSetBridge(resultSet); +// EXPECT_NE(bridge, nullptr); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_002 +// * @tc.desc: normal testcase of RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_002, TestSize.Level1) +//{ +// GenerateDefaultTable(); +// +// std::string table = "test"; +// std::string column = "data1"; +// std::string value = "hello"; +// DataSharePredicates predicates; +// predicates.EqualTo(column, value); +// std::vector columns; +// auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); +// int rowCount; +// allDataTypes.get()->GetRowCount(rowCount); +// EXPECT_EQ(rowCount, 1); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_003 +// * @tc.desc: normal testcase of RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_003, TestSize.Level1) +//{ +// GenerateDefaultTable(); +// +// std::string table = "test"; +// OHOS::DataShare::DataSharePredicates predicates; +// predicates.GreaterThan("data2", -5); +// std::vector columns; +// auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); +// int rdbRowCount; +// allDataTypes.get()->GetRowCount(rdbRowCount); +// EXPECT_EQ(rdbRowCount, 3); +// +// allDataTypes->GoToFirstRow(); +// +// std::string strValue; +// allDataTypes->GetString(1, strValue); +// EXPECT_EQ("hello", strValue); +// +// int intValue; +// allDataTypes->GetInt(2, intValue); +// EXPECT_EQ(intValue, 10); +// +// std::vector blobValue; +// uint8_t blobData = 66; +// allDataTypes->GetBlob(4, blobValue); +// EXPECT_EQ(blobData, blobValue[0]); +// +// allDataTypes->GoToNextRow(); +// allDataTypes->GetBlob(4, blobValue); +// EXPECT_EQ(3, static_cast(blobValue.size())); +// blobData = 5; +// EXPECT_EQ(blobData, blobValue[1]); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_004 +// * @tc.desc: normal testcase of RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_004, TestSize.Level1) +//{ +// GenerateDefaultTable(); +// +// std::string table = "test"; +// OHOS::DataShare::DataSharePredicates predicates; +// predicates.SetWhereClause("`data2` > ?"); +// predicates.SetWhereArgs(std::vector{ "-5" }); +// predicates.SetOrder("data3"); +// std::vector columns; +// auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); +// int rowCount; +// allDataTypes.get()->GetRowCount(rowCount); +// EXPECT_EQ(rowCount, 3); +// +// allDataTypes->GoToFirstRow(); +// +// std::string strValue; +// allDataTypes->GetString(1, strValue); +// EXPECT_EQ("hello", strValue); +// +// int intValue; +// allDataTypes->GetInt(2, intValue); +// EXPECT_EQ(intValue, 10); +// +// std::vector blobValue; +// allDataTypes->GetBlob(4, blobValue); +// EXPECT_EQ(1, static_cast(blobValue.size())); +// +// allDataTypes->GoToNextRow(); +// +// allDataTypes->GetString(1, strValue); +// EXPECT_EQ("hello world", strValue); +// +// allDataTypes->GetInt(2, intValue); +// EXPECT_EQ(intValue, 3); +// +// allDataTypes->GetBlob(4, blobValue); +// EXPECT_EQ(3, static_cast(blobValue.size())); +// uint8_t blobData = 5; +// EXPECT_EQ(blobData, blobValue[1]); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_005 +// * @tc.desc: normal testcase of RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_005, TestSize.Level1) +//{ +// GenerateDefaultTable(); +// DataShareValuesBucket values; +// int64_t id; +// int changedRows; +// values.Put("data1", std::string("tulip")); +// values.Put("data2", 100); +// values.Put("data3", 50.5); +// values.Put("data4", std::vector{ 20, 21, 22 }); +// +// int ret = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); +// EXPECT_EQ(ret, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(5, id); +// +// std::string table = "test"; +// OHOS::DataShare::DataSharePredicates predicates; +// std::string value = "tulip"; +// predicates.EqualTo("data1", value); +// std::vector columns; +// auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); +// int rowCount; +// allDataTypes.get()->GetRowCount(rowCount); +// EXPECT_EQ(rowCount, 1); +// +// allDataTypes.get()->Close(); +// +// values.Clear(); +// values.Put("data3", 300.5); +// values.Put("data4", std::vector{ 17, 18, 19 }); +// ret = store->Update( +// changedRows, "test", RdbUtils::ToValuesBucket(values), "data1 = ?", std::vector{ "tulip" }); +// EXPECT_EQ(ret, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(1, changedRows); +// +// allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); +// allDataTypes->GoToFirstRow(); +// +// double doubleVal; +// allDataTypes->GetDouble(3, doubleVal); +// EXPECT_EQ(300.5, doubleVal); +// +// int deletedRows; +// ret = store->Delete(deletedRows, RdbUtils::ToPredicates(predicates, table)); +// EXPECT_EQ(ret, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(1, deletedRows); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_006 +// * @tc.desc: normal testcase of RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_006, TestSize.Level1) +//{ +// GenerateDefaultTable(); +// +// std::string table = "test"; +// OHOS::DataShare::DataSharePredicates predicates; +// predicates.Limit(1, 2); +// std::vector columns; +// auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); +// int rdbRowCount; +// allDataTypes.get()->GetRowCount(rdbRowCount); +// EXPECT_EQ(rdbRowCount, 1); +// +// allDataTypes->GoToFirstRow(); +// +// std::string strValue; +// allDataTypes->GetString(1, strValue); +// EXPECT_EQ("hello world", strValue); +// +// int intValue; +// allDataTypes->GetInt(2, intValue); +// EXPECT_EQ(intValue, 3); +// +// double doubleValue; +// allDataTypes->GetDouble(3, doubleValue); +// EXPECT_EQ(doubleValue, 1.8); +// +// std::vector blobValue; +// uint8_t blobData1 = 4; +// uint8_t blobData2 = 5; +// uint8_t blobData3 = 6; +// allDataTypes->GetBlob(4, blobValue); +// EXPECT_EQ(3, static_cast(blobValue.size())); +// EXPECT_EQ(blobData1, blobValue[0]); +// EXPECT_EQ(blobData2, blobValue[1]); +// EXPECT_EQ(blobData3, blobValue[2]); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_007 +// * @tc.desc: normal testcase of RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_007, TestSize.Level1) +//{ +// std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT,") + +// std::string("age INTEGER, salary REAL);"); +// store->ExecuteSql(createTableSql); +// +// DataShareValuesBucket values; +// int64_t id; +// values.Put("name", std::string("zhangsan")); +// values.Put("age", INT64_MIN); +// values.Put("salary", DBL_MIN); +// int ret1 = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); +// EXPECT_EQ(ret1, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(1, id); +// +// values.Clear(); +// values.Put("name", std::string("lisi")); +// values.Put("age", INT64_MAX); +// values.Put("salary", DBL_MAX); +// int ret2 = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); +// EXPECT_EQ(ret2, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(2, id); +// +// std::string table = "test"; +// OHOS::DataShare::DataSharePredicates predicates; +// std::vector columns; +// auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, table), columns); +// +// allDataTypes->GoToFirstRow(); +// int64_t int64Value; +// allDataTypes->GetLong(2, int64Value); +// EXPECT_EQ(int64Value, INT64_MIN); +// +// double doubleVal; +// allDataTypes->GetDouble(3, doubleVal); +// EXPECT_EQ(doubleVal, DBL_MIN); +// +// allDataTypes->GoToNextRow(); +// +// allDataTypes->GetLong(2, int64Value); +// EXPECT_EQ(int64Value, INT64_MAX); +// +// allDataTypes->GetDouble(3, doubleVal); +// EXPECT_EQ(doubleVal, DBL_MAX); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_008 +// * @tc.desc: normal testcase of query double +// * @tc.type: test double for high accuracy +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_008, TestSize.Level1) +//{ +// std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 double,") + +// std::string("data2 double, data3 TEXT);"); +// store->ExecuteSql(createTableSql); +// +// ValuesBucket values; +// int64_t id; +// double data1 = 1.777777777777; +// double data2 = 1.888888888888; +// std::string data3 = "zh-has"; +// std::string tableName = "test"; +// +// values.PutDouble("data1", data1); +// values.PutDouble("data2", data2); +// values.PutString("data3", data3); +// int ret = store->Insert(id, tableName, values); +// EXPECT_EQ(ret, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(1, id); +// +// OHOS::DataShare::DataSharePredicates predicates; +// predicates.BeginWrap() +// ->EqualTo("data1", data1) +// ->And() +// ->EqualTo("data2", data2) +// ->And() +// ->EqualTo("data3", data3) +// ->EndWrap(); +// std::vector columns; +// auto allDataTypes = store->Query(RdbUtils::ToPredicates(predicates, tableName), columns); +// int rowCount; +// int ok = allDataTypes->GetRowCount(rowCount); +// EXPECT_EQ(ok, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(1, rowCount); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_009 +// * @tc.desc: normal testcase of RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_009, TestSize.Level1) +//{ +// std::string createTableSql = std::string("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT,") + +// std::string("age INTEGER, salary REAL);"); +// store->ExecuteSql(createTableSql); +// +// DataShareValuesBucket values; +// int64_t id; +// values.Put("name", std::string("zhangsan")); +// values.Put("age", INT64_MIN); +// values.Put("salary", DBL_MIN); +// int ret1 = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); +// EXPECT_EQ(ret1, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(1, id); +// +// values.Clear(); +// values.Put("name", std::string("lisi")); +// values.Put("age", INT64_MAX); +// values.Put("salary", DBL_MAX); +// int ret2 = store->Insert(id, "test", RdbUtils::ToValuesBucket(values)); +// EXPECT_EQ(ret2, OHOS::NativeRdb::E_OK); +// EXPECT_EQ(2, id); +// +// std::string table = "test"; +// OHOS::DataShare::OperationItem item; +// item.singleParams = {}; +// RdbPredicates predicates("test"); +// RdbUtils::EqualTo(item, predicates); +// std::vector columns; +// std::shared_ptr allPerson = store->Query(predicates, columns); +// EXPECT_EQ(2, ResultSize(allPerson)); +// +// RdbUtils::GreaterThan(item, predicates); +// allPerson = store->Query(predicates, columns); +// EXPECT_EQ(2, ResultSize(allPerson)); +// +// RdbUtils::Limit(item, predicates); +// allPerson = store->Query(predicates, columns); +// EXPECT_EQ(2, ResultSize(allPerson)); +// +// RdbUtils::NotEqualTo(item, predicates); +// allPerson = store->Query(predicates, columns); +// EXPECT_EQ(2, ResultSize(allPerson)); +// +// RdbUtils::LessThan(item, predicates); +// allPerson = store->Query(predicates, columns); +// EXPECT_EQ(2, ResultSize(allPerson)); +//} +// +///* * +// * @tc.name: Rdb_DataShare_Adapter_010 +// * @tc.desc: normal testcase of RdbDataShareAdapter +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, Rdb_DataShare_Adapter_010, TestSize.Level1) +//{ +// GenerateDefaultTable(); +// +// std::string table = "test"; +// std::string column = "data1"; +// std::string value = "%hello%"; +// DataSharePredicates predicates; +// predicates.Unlike(column, value); +// std::vector columns; +// auto result = store->Query(RdbUtils::ToPredicates(predicates, table), columns); +// int rowCount = 0; +// if (result.get() != nullptr) { +// result.get()->GetRowCount(rowCount); +// } +// EXPECT_EQ(rowCount, 2); +//} +// +//void RdbDataShareAdapterTest::LessThanTest(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, LessThan(testing::_, testing::_)).Times(1); +// auto item = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::LessThan(item, predicates); +//} +// +//void RdbDataShareAdapterTest::GreaterThanOrEqualTo(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, GreaterThanOrEqualTo(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, { "John" }); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::GreaterThanOrEqualTo(item1, predicates); +// RdbUtils::GreaterThanOrEqualTo(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::LessThanOrEqualTo(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, LessThanOrEqualTo(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, { "John" }); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::LessThanOrEqualTo(item1, predicates); +// RdbUtils::LessThanOrEqualTo(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::IsNull(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, IsNull(testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::IsNull(item1, predicates); +// RdbUtils::IsNull(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::IsNotNull(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, IsNotNull(testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::IsNotNull(item1, predicates); +// RdbUtils::IsNotNull(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::In(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, In(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0); +// auto item2 = CreateOperationItem(0, { "test_table", "John" }); +// auto item3 = CreateOperationItem(0, {}, { std::vector{ "zhangSan" }, std::vector{ 1, 2, 3 } }); +// auto item4 = CreateOperationItem( +// 0, { "test_table", 2 }, { std::vector{ "zhangSan" }, std::vector{ 1, 2, 3 } }); +// RdbUtils::In(item1, predicates); +// RdbUtils::In(item2, predicates); +// RdbUtils::In(item3, predicates); +// RdbUtils::In(item4, predicates); +//} +// +//void RdbDataShareAdapterTest::NotIn(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, NotIn(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0); +// auto item2 = CreateOperationItem(0, { "test_table", "John" }); +// auto item3 = CreateOperationItem(0, {}, { std::vector{ "zhangSan" }, std::vector{ 1, 2, 3 } }); +// auto item4 = CreateOperationItem( +// 0, { "test_table", 2 }, { std::vector{ "zhangSan" }, std::vector{ 1, 2, 3 } }); +// RdbUtils::NotIn(item1, predicates); +// RdbUtils::NotIn(item2, predicates); +// RdbUtils::NotIn(item3, predicates); +// RdbUtils::NotIn(item4, predicates); +//} +// +//void RdbDataShareAdapterTest::Like(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, Like(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::Like(item1, predicates); +// RdbUtils::Like(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::NotLike(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, NotLike(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::NotLike(item1, predicates); +// RdbUtils::NotLike(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::OrderByAsc(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, OrderByAsc(testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::OrderByAsc(item1, predicates); +// RdbUtils::OrderByAsc(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::OrderByDesc(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, OrderByDesc(testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::OrderByDesc(item1, predicates); +// RdbUtils::OrderByDesc(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::Offset(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, Offset(testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::Offset(item1, predicates); +// RdbUtils::Offset(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::BeginsWith(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, BeginsWith(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::BeginsWith(item1, predicates); +// RdbUtils::BeginsWith(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::EndsWith(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, EndsWith(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::EndsWith(item1, predicates); +// RdbUtils::EndsWith(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::GroupBy(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, GroupBy(testing::_)).Times(1); +// auto item1 = CreateOperationItem(0); +// auto item2 = CreateOperationItem(0, {}, { std::vector{ "zhangSan" }, std::vector{ 1, 2, 3 } }); +// RdbUtils::GroupBy(item1, predicates); +// RdbUtils::GroupBy(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::IndexedBy(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, IndexedBy(testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::IndexedBy(item1, predicates); +// RdbUtils::IndexedBy(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::Contains(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, Contains(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::Contains(item1, predicates); +// RdbUtils::Contains(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::NotContains(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, NotContains(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::NotContains(item1, predicates); +// RdbUtils::NotContains(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::Glob(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, Glob(testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", "John" }); +// RdbUtils::Glob(item1, predicates); +// RdbUtils::Glob(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::Between(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, Between(testing::_, testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", 1, true }); +// RdbUtils::Between(item1, predicates); +// RdbUtils::Between(item2, predicates); +//} +// +//void RdbDataShareAdapterTest::NotBetween(MockRdbPredicates &predicates) +//{ +// EXPECT_CALL(predicates, NotBetween(testing::_, testing::_, testing::_)).Times(1); +// auto item1 = CreateOperationItem(0, {}); +// auto item2 = CreateOperationItem(0, { "name", 1, true }); +// RdbUtils::NotBetween(item1, predicates); +// RdbUtils::NotBetween(item2, predicates); +//} +// +///** +// * @tc.name: RdbUtils_Operation_Test +// * @tc.desc: Test all operation handlers in RdbUtils +// * @tc.type: FUNC +// */ +//HWTEST_F(RdbDataShareAdapterTest, RdbUtils_Operation_Test, TestSize.Level1) +//{ +// LOG_INFO("RdbUtils_Operation_Test start"); +// MockRdbPredicates predicates("test_table"); +// LessThanTest(predicates); +// GreaterThanOrEqualTo(predicates); +// LessThanOrEqualTo(predicates); +// IsNull(predicates); +// IsNotNull(predicates); +// In(predicates); +// NotIn(predicates); +// Like(predicates); +// NotLike(predicates); +// OrderByAsc(predicates); +// OrderByDesc(predicates); +// Offset(predicates); +// BeginsWith(predicates); +// EndsWith(predicates); +// GroupBy(predicates); +// IndexedBy(predicates); +// Contains(predicates); +// NotContains(predicates); +// Glob(predicates); +// Between(predicates); +// NotBetween(predicates); +//} diff --git a/relational_store/test/ndk/BUILD.gn b/relational_store/test/ndk/BUILD.gn index dfd58ab1..d93ce60b 100644 --- a/relational_store/test/ndk/BUILD.gn +++ b/relational_store/test/ndk/BUILD.gn @@ -20,7 +20,7 @@ config("module_private_config") { visibility = [ ":*" ] include_dirs = [ - "${kvstore_path}/common", + "${relational_store_base_path}/interfaces/ndk", "${relational_store_base_path}/interfaces/ndk/include", "${relational_store_innerapi_path}/rdb/include", "${relational_store_innerapi_path}/appdatafwk/include", @@ -35,7 +35,10 @@ ohos_unittest("NativeRdbNdkTest") { sources = [ "unittest/rdb_asset_test.cpp", + "unittest/rdb_crypto_param_test.cpp", "unittest/rdb_cursor_test.cpp", + "unittest/rdb_performance_test.cpp", + "unittest/rdb_predicates_pref_test.cpp", "unittest/rdb_predicates_test.cpp", "unittest/rdb_store_configv2_test.cpp", "unittest/rdb_store_test.cpp", @@ -49,13 +52,15 @@ ohos_unittest("NativeRdbNdkTest") { "access_token:libaccesstoken_sdk", "access_token:libtoken_setproc", "c_utils:utils", + "googletest:gtest_main", "hilog:libhilog", + "kv_store:datamgr_common", ] deps = [ - "${relational_store_base_path}/interfaces/ndk/src:native_rdb_ndk", + "${relational_store_base_path}/interfaces/rdb_ndk_utils:native_rdb_ndk_utils", + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", "${relational_store_innerapi_path}/rdb:native_rdb", - "//third_party/googletest:gtest_main", ] } @@ -65,3 +70,24 @@ group("unittest") { deps = [ ":NativeRdbNdkTest" ] } + +group("fuzztest") { + testonly = true + deps = [] + deps += [ + "fuzztest/datavalue_fuzzer:fuzztest", + "fuzztest/ohrdbtransaction_fuzzer:fuzztest", + "fuzztest/relationalstore_fuzzer:fuzztest", + "fuzztest/relationalstorecapi_fuzzer:fuzztest", + "fuzztest/valuebucket_fuzzer:fuzztest", + "fuzztest/valueobject_fuzzer:fuzztest", + "fuzztest/ohpredicates_fuzzer:fuzztest", + "fuzztest/dataasset_fuzzer:fuzztest", + "fuzztest/oh_cursor_fuzzer:fuzztest", + "fuzztest/oh_data_value_fuzzer:fuzztest", + "fuzztest/oh_data_values_buckets_fuzzer:fuzztest", + "fuzztest/oh_data_values_fuzzer:fuzztest", + "fuzztest/oh_predicates_fuzzer:fuzztest", + "fuzztest/oh_rdb_crypto_param_fuzzer:fuzztest", + ] +} diff --git a/relational_store/test/ndk/fuzztest/dataasset_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/BUILD.gn new file mode 100644 index 00000000..18084f80 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("dataasset_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = "${relational_store_base_path}/test/ndk/fuzztest/dataasset_fuzzer" + + sources = [ "dataasset_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":dataasset_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/dataasset_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/corpus/init new file mode 100644 index 00000000..64d7767e --- /dev/null +++ b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/dataasset_fuzzer/dataasset_fuzzer.cpp b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/dataasset_fuzzer.cpp new file mode 100644 index 00000000..38ccdfbf --- /dev/null +++ b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/dataasset_fuzzer.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 "dataasset_fuzzer.h" + +#include + +#include "data_asset.h" +#include "grd_api_manager.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + +#define MAX_STRING_LENGTH 20 + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +namespace OHOS { +void OH_Data_Asset_SetNameFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + std::string name = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + OH_Data_Asset_SetName(asset, name.c_str()); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_SetName(nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_SetUriFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + std::string uri = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + OH_Data_Asset_SetUri(asset, uri.c_str()); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_SetUri(nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_SetPathFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + std::string path = provider.ConsumeRandomLengthString(MAX_STRING_LENGTH); + OH_Data_Asset_SetPath(asset, path.c_str()); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_SetPath(nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_SetCreateTimeFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + int64_t createTime = provider.ConsumeIntegral(); + OH_Data_Asset_SetCreateTime(asset, createTime); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_SetCreateTime(nullptr, 0); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_SetModifyTimeFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + int64_t modifyTime = provider.ConsumeIntegral(); + OH_Data_Asset_SetModifyTime(asset, modifyTime); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_SetModifyTime(nullptr, 0); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_SetSizeFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + size_t size = provider.ConsumeIntegral(); + OH_Data_Asset_SetSize(asset, size); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_SetSize(nullptr, 0); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_SetStatusFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + const int min = 0; + const int max = 6; + Data_AssetStatus status = static_cast(provider.ConsumeIntegralInRange(min, max)); + OH_Data_Asset_SetStatus(asset, status); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_SetStatus(nullptr, Data_AssetStatus::ASSET_NULL); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_GetNameFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + char name[MAX_STRING_LENGTH]; + size_t length = MAX_STRING_LENGTH; + OH_Data_Asset_GetName(asset, name, &length); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_GetName(nullptr, nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_GetUriFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + char uri[MAX_STRING_LENGTH]; + size_t length = MAX_STRING_LENGTH; + OH_Data_Asset_GetUri(asset, uri, &length); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_GetUri(nullptr, nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_GetPathFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + char path[MAX_STRING_LENGTH]; + size_t length = MAX_STRING_LENGTH; + OH_Data_Asset_GetPath(asset, path, &length); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_GetPath(nullptr, nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_GetCreateTimeFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + int64_t createTime; + OH_Data_Asset_GetCreateTime(asset, &createTime); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_GetCreateTime(nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_GetModifyTimeFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + int64_t modifyTime; + OH_Data_Asset_GetModifyTime(asset, &modifyTime); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_GetModifyTime(nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_GetSizeFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + size_t size; + OH_Data_Asset_GetSize(asset, &size); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_GetSize(nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} + +void OH_Data_Asset_GetStatusFuzz(FuzzedDataProvider &provider) +{ + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + Data_AssetStatus status; + OH_Data_Asset_GetStatus(asset, &status); + OH_Data_Asset_DestroyOne(asset); + + OH_Data_Asset_GetStatus(nullptr, nullptr); + OH_Data_Asset_DestroyOne(nullptr); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + OHOS::OH_Data_Asset_SetNameFuzz(provider); + OHOS::OH_Data_Asset_SetUriFuzz(provider); + OHOS::OH_Data_Asset_SetPathFuzz(provider); + OHOS::OH_Data_Asset_SetCreateTimeFuzz(provider); + OHOS::OH_Data_Asset_SetModifyTimeFuzz(provider); + OHOS::OH_Data_Asset_SetSizeFuzz(provider); + OHOS::OH_Data_Asset_SetStatusFuzz(provider); + OHOS::OH_Data_Asset_GetNameFuzz(provider); + OHOS::OH_Data_Asset_GetUriFuzz(provider); + OHOS::OH_Data_Asset_GetPathFuzz(provider); + OHOS::OH_Data_Asset_GetCreateTimeFuzz(provider); + OHOS::OH_Data_Asset_GetModifyTimeFuzz(provider); + OHOS::OH_Data_Asset_GetSizeFuzz(provider); + OHOS::OH_Data_Asset_GetStatusFuzz(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/dataasset_fuzzer/dataasset_fuzzer.h b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/dataasset_fuzzer.h new file mode 100644 index 00000000..a51abea6 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/dataasset_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 DATAASSET_FUZZER_H +#define DATAASSET_FUZZER_H + +#define FUZZ_PROJECT_NAME "dataasset_fuzzer" + +#endif // DATAASSET_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/dataasset_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/ndk/fuzztest/dataasset_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/datavalue_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/BUILD.gn new file mode 100644 index 00000000..ea8a320b --- /dev/null +++ b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("DataValueFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/ndk/fuzztest/datavalue_fuzzer" + + sources = [ "datavalue_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":DataValueFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/datavalue_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/corpus/init new file mode 100644 index 00000000..65af8ee8 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/datavalue_fuzzer/datavalue_fuzzer.cpp b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/datavalue_fuzzer.cpp new file mode 100644 index 00000000..8fcf2278 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/datavalue_fuzzer.cpp @@ -0,0 +1,282 @@ +/* + * 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 "datavalue_fuzzer.h" + +#include + +#include "grd_api_manager.h" +#include "oh_data_value.h" +#include "oh_value_object.h" +#include "oh_values_bucket.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +void OHValuePutAssetsFuzzTest(FuzzedDataProvider &provider, OH_Data_Value *value) +{ + const int minCount = 1; + const int maxCount = 50; + size_t count = provider.ConsumeIntegralInRange(minCount, maxCount); + Data_Asset **assets = OH_Data_Asset_CreateMultiple(count); + if (assets == nullptr) { + return; + } + for (size_t i = 0; i < count; i++) { + int64_t value = provider.ConsumeIntegral(); + OH_Data_Asset_SetCreateTime(assets[i], value); + } + OH_Value_PutAssets(value, assets, count); + OH_Data_Asset_DestroyMultiple(assets, count); +} + +void OHValuePutFloatVectorFuzzTest(FuzzedDataProvider &provider, OH_Data_Value *value) +{ + const int minFloatVectorSize = 1; + const int maxFloatVectorSize = 100; + size_t floatVectorSize = provider.ConsumeIntegralInRange(minFloatVectorSize, maxFloatVectorSize); + std::vector floatVector(floatVectorSize); + for (size_t i = 0; i < floatVectorSize; i++) { + floatVector[i] = provider.ConsumeFloatingPoint(); + } + OH_Value_PutFloatVector(value, floatVector.data(), floatVectorSize); +} + +void OHValuePutUnlimitedIntFuzzTest(FuzzedDataProvider &provider, OH_Data_Value *value) +{ + const int minSign = 0; + const int maxSign = 1; + int sign = provider.ConsumeIntegralInRange(minSign, maxSign); + const int minUnlimitedIntSize = 1; + const int maxUnlimitedIntSize = 10; + size_t unlimitedIntSize = provider.ConsumeIntegralInRange(minUnlimitedIntSize, maxUnlimitedIntSize); + std::vector trueForm(unlimitedIntSize); + for (size_t i = 0; i < unlimitedIntSize; i++) { + trueForm[i] = provider.ConsumeIntegral(); + } + OH_Value_PutUnlimitedInt(value, sign, trueForm.data(), unlimitedIntSize); +} + +void DataValuePutFuzzTest(FuzzedDataProvider &provider, OH_Data_Value *value) +{ + if (value == nullptr) { + return; + } + // Test OH_Value_PutNull + { + OH_Value_PutNull(value); + } + + // Test OH_Value_PutInt + { + int64_t intValue = provider.ConsumeIntegral(); + OH_Value_PutInt(value, intValue); + } + + // Test OH_Value_PutReal + { + double realValue = provider.ConsumeFloatingPoint(); + OH_Value_PutReal(value, realValue); + } + + // Test OH_Value_PutText + { + std::string textValue = provider.ConsumeRandomLengthString(); + OH_Value_PutText(value, textValue.c_str()); + } + + // Test OH_Value_PutBlob + { + const int minBlobSize = 1; + const int maxBlobSize = 50; + size_t blobSize = provider.ConsumeIntegralInRange(minBlobSize, maxBlobSize); + std::vector blobData = provider.ConsumeBytes(blobSize); + OH_Value_PutBlob(value, blobData.data(), blobData.size()); + } + + // Test OH_Value_PutAsset + { + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + OH_Value_PutAsset(value, asset); + OH_Data_Asset_DestroyOne(asset); + } + + // Test OH_Value_PutAssets + OHValuePutAssetsFuzzTest(provider, value); + + // Test OH_Value_PutFloatVector + OHValuePutFloatVectorFuzzTest(provider, value); + + // Test OH_Value_PutUnlimitedInt + OHValuePutUnlimitedIntFuzzTest(provider, value); +} + +void OHValueGetAssetsFuzzTest(OH_Data_Value *value) +{ + size_t assetsSize; + OH_Value_GetAssetsCount(value, &assetsSize); + + Data_Asset **assets = OH_Data_Asset_CreateMultiple(assetsSize); + if (assets == nullptr) { + return; + } + size_t assetsOutLen; + OH_Value_GetAssets(value, assets, assetsSize, &assetsOutLen); + OH_Data_Asset_DestroyMultiple(assets, assetsSize); +} + +void DataValueGetFuzzTestPartOne(OH_Data_Value *value) +{ + if (value == nullptr) { + return; + } + // Test OH_Value_GetType + { + OH_ColumnType type; + OH_Value_GetType(value, &type); + } + + // Test OH_Value_IsNull + { + bool isNull; + OH_Value_IsNull(value, &isNull); + } + + // Test OH_Value_GetInt + { + int64_t intValue; + OH_Value_GetInt(value, &intValue); + } + + // Test OH_Value_GetReal + { + double realValue; + OH_Value_GetReal(value, &realValue); + } + + // Test OH_Value_GetText + { + const char *textValue; + OH_Value_GetText(value, &textValue); + } + + // Test OH_Value_GetBlob + { + const uint8_t *blobValue; + size_t blobLength; + OH_Value_GetBlob(value, &blobValue, &blobLength); + } + + // Test OH_Value_GetAsset + { + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + OH_Value_GetAsset(value, asset); + OH_Data_Asset_DestroyOne(asset); + } + + // Test OH_Value_GetAssetsCount + { + size_t assetsCount; + OH_Value_GetAssetsCount(value, &assetsCount); + } + + // Test OH_Value_GetAssets + OHValueGetAssetsFuzzTest(value); + + // Test OH_Value_GetFloatVectorCount + { + size_t floatVectorCount; + OH_Value_GetFloatVectorCount(value, &floatVectorCount); + } +} + +void DataValueGetFuzzTestPartTwo(OH_Data_Value *value) +{ + if (value == nullptr) { + return; + } + // Test OH_Value_GetFloatVector + { + size_t floatVectorSize; + OH_Value_GetFloatVectorCount(value, &floatVectorSize); + const size_t maxMallocSize = 100; + if (floatVectorSize > maxMallocSize) { + floatVectorSize = maxMallocSize; + } + float *floatVector = (float *)malloc(floatVectorSize * sizeof(float)); + if (floatVector == nullptr) { + return; + } + size_t floatVectorOutLen; + OH_Value_GetFloatVector(value, floatVector, floatVectorSize, &floatVectorOutLen); + free(floatVector); + } + + // Test OH_Value_GetUnlimitedIntBand + { + size_t unlimitedIntBand; + OH_Value_GetUnlimitedIntBand(value, &unlimitedIntBand); + } + + // Test OH_Value_GetUnlimitedInt + { + size_t unlimitedIntSize; + OH_Value_GetUnlimitedIntBand(value, &unlimitedIntSize); + const size_t maxMallocSize = 100; + if (unlimitedIntSize > maxMallocSize) { + unlimitedIntSize = maxMallocSize; + } + uint64_t *trueForm = (uint64_t *)malloc(unlimitedIntSize * sizeof(uint64_t)); + if (trueForm == nullptr) { + return; + } + size_t unlimitedIntOutLen; + int sign; + OH_Value_GetUnlimitedInt(value, &sign, trueForm, unlimitedIntSize, &unlimitedIntOutLen); + free(trueForm); + } +} + +void DataValueFuzzTest(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + DataValuePutFuzzTest(provider, value); + DataValueGetFuzzTestPartOne(value); + DataValueGetFuzzTestPartTwo(value); + // Destroy the OH_Data_Value instance + OH_Value_Destroy(value); +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + DataValueFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/datavalue_fuzzer/datavalue_fuzzer.h b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/datavalue_fuzzer.h new file mode 100644 index 00000000..7e3addd8 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/datavalue_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 DATAVALUE_FUZZER_H +#define DATAVALUE_FUZZER_H + +#define FUZZ_PROJECT_NAME "datavalue_fuzzer" + +#endif // DATAVALUE_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/datavalue_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/ndk/fuzztest/datavalue_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/BUILD.gn new file mode 100644 index 00000000..d88cd510 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("oh_cursor_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = "${relational_store_base_path}/test/ndk/fuzztest/oh_cursor_fuzzer" + + sources = [ "oh_cursor_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":oh_cursor_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/corpus/init new file mode 100644 index 00000000..64d7767e --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/oh_cursor_fuzzer.cpp b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/oh_cursor_fuzzer.cpp new file mode 100644 index 00000000..e4d9eecb --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/oh_cursor_fuzzer.cpp @@ -0,0 +1,261 @@ +/* + * 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 "oh_cursor_fuzzer.h" + +#include +#include +#include +#include + +#include "grd_api_manager.h" +#include "oh_cursor.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + + +#define COLUMN_INDEX_MIN 0 +#define COLUMN_INDEX_MAX 10 +static constexpr const char *RDB_TEST_PATH = "/data/storage/el2/database/com.ohos.example.distributedndk/entry/"; + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +namespace OHOS { + +OH_Cursor *GetOH_Cursor() +{ + OH_Rdb_Config config; + config.dataBaseDir = RDB_TEST_PATH; + config.storeName = "rdb_store_oh_cursor_fuzzer_test.db"; + config.bundleName = "com.ohos.example.distributedndk"; + config.moduleName = ""; + config.securityLevel = OH_Rdb_SecurityLevel::S1; + config.isEncrypt = false; + config.selfSize = sizeof(OH_Rdb_Config); + config.area = RDB_SECURITY_AREA_EL1; + int chmodValue = 0770; + mkdir(config.dataBaseDir, chmodValue); + + int errCode = 0; + char table[] = "test"; + static OH_Rdb_Store *ndkStore = OH_Rdb_GetOrOpen(&config, &errCode); + + char createTableSql[] = "CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, data2 INTEGER, " + "data3 FLOAT, data4 BLOB, data5 TEXT);"; + OH_Rdb_Execute(ndkStore, createTableSql); + + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putInt64(valueBucket, "id", 1); + valueBucket->putText(valueBucket, "data1", "zhangSan"); + // init row one data2 value 12800 + valueBucket->putInt64(valueBucket, "data2", 12800); + // init row one data3 value 100.1 + valueBucket->putReal(valueBucket, "data3", 100.1); + uint8_t arr[] = { 1, 2, 3, 4, 5 }; + int len = sizeof(arr) / sizeof(arr[0]); + valueBucket->putBlob(valueBucket, "data4", arr, len); + valueBucket->putText(valueBucket, "data5", "ABCDEFG"); + OH_Rdb_Insert(ndkStore, table, valueBucket); + + char querySql[] = "SELECT * FROM test"; + static OH_Cursor *cursor = OH_Rdb_ExecuteQuery(ndkStore, querySql); + return cursor; +} + +OH_ColumnType GetOH_ColumnType(FuzzedDataProvider &provider) +{ + int min = static_cast(OH_ColumnType::TYPE_NULL); + int max = static_cast(OH_ColumnType::TYPE_UNLIMITED_INT); + int enumInt = provider.ConsumeIntegralInRange(min, max); + OH_ColumnType type = static_cast(enumInt); + return type; +} + +void OH_Cursor_GetColumnCountFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int count = provider.ConsumeIntegral(); + cursor->getColumnCount(cursor, &count); +} + +void OH_Cursor_GetColumnTypeFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + OH_ColumnType columnType = GetOH_ColumnType(provider); + cursor->getColumnType(cursor, columnIndex, &columnType); +} + +void OH_Cursor_GetColumnIndexFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + std::string name = provider.ConsumeRandomLengthString(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + cursor->getColumnIndex(cursor, name.c_str(), &columnIndex); +} + +void OH_Cursor_GetColumnNameFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + char name[10]; + const int length = 10; + cursor->getColumnName(cursor, columnIndex, name, length); +} + +void OH_Cursor_GetRowCountFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int count = provider.ConsumeIntegral(); + cursor->getRowCount(cursor, &count); +} + +void OH_Cursor_GoToNextRowFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + cursor->goToNextRow(cursor); +} + +void OH_Cursor_GetSizeFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + size_t size = provider.ConsumeIntegral(); + cursor->getSize(cursor, columnIndex, &size); +} + +void OH_Cursor_GetTextFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + char value = provider.ConsumeIntegral(); + int length = provider.ConsumeIntegral(); + cursor->getText(cursor, columnIndex, &value, length); +} + +void OH_Cursor_GetInt64Fuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + int64_t value = provider.ConsumeIntegral(); + cursor->getInt64(cursor, columnIndex, &value); +} + +void OH_Cursor_GetRealFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + double value = provider.ConsumeFloatingPoint(); + cursor->getReal(cursor, columnIndex, &value); +} + +void OH_Cursor_GetBlobFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + unsigned char value = provider.ConsumeIntegral(); + int length = provider.ConsumeIntegral(); + cursor->getBlob(cursor, columnIndex, &value, length); +} + +void OH_Cursor_IsNullFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + bool isNull = provider.ConsumeBool(); + cursor->isNull(cursor, columnIndex, &isNull); +} + +void OH_Cursor_GetAssetFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + cursor->getAsset(cursor, columnIndex, asset); + OH_Data_Asset_DestroyOne(asset); +} + +void OH_Cursor_GetAssetsFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + uint32_t length = provider.ConsumeIntegral(); + cursor->getAssets(cursor, columnIndex, &asset, &length); + OH_Data_Asset_DestroyOne(asset); +} + +void OH_Cursor_GetAssetsCountFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + uint32_t count = provider.ConsumeIntegral(); + cursor->getAssetsCount(cursor, columnIndex, &count); +} + +void OH_Cursor_GetFloatVectorCountFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + size_t length = provider.ConsumeIntegral(); + OH_Cursor_GetFloatVectorCount(cursor, columnIndex, &length); +} + +void OH_Cursor_GetFloatVectorFuzz(FuzzedDataProvider &provider) +{ + OH_Cursor *cursor = GetOH_Cursor(); + int32_t columnIndex = provider.ConsumeIntegralInRange(COLUMN_INDEX_MIN, COLUMN_INDEX_MAX); + float val = provider.ConsumeFloatingPoint(); + size_t inLen = provider.ConsumeIntegral(); + size_t outLen = provider.ConsumeIntegral(); + OH_Cursor_GetFloatVector(cursor, columnIndex, &val, inLen, &outLen); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + OHOS::OH_Cursor_GetColumnCountFuzz(provider); + OHOS::OH_Cursor_GetColumnTypeFuzz(provider); + OHOS::OH_Cursor_GetColumnIndexFuzz(provider); + OHOS::OH_Cursor_GetColumnNameFuzz(provider); + OHOS::OH_Cursor_GetRowCountFuzz(provider); + OHOS::OH_Cursor_GoToNextRowFuzz(provider); + OHOS::OH_Cursor_GetSizeFuzz(provider); + OHOS::OH_Cursor_GetTextFuzz(provider); + OHOS::OH_Cursor_GetInt64Fuzz(provider); + OHOS::OH_Cursor_GetRealFuzz(provider); + OHOS::OH_Cursor_GetBlobFuzz(provider); + OHOS::OH_Cursor_IsNullFuzz(provider); + OHOS::OH_Cursor_GetAssetFuzz(provider); + OHOS::OH_Cursor_GetAssetsFuzz(provider); + OHOS::OH_Cursor_GetAssetsCountFuzz(provider); + OHOS::OH_Cursor_GetFloatVectorCountFuzz(provider); + OHOS::OH_Cursor_GetFloatVectorFuzz(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/oh_cursor_fuzzer.h b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/oh_cursor_fuzzer.h new file mode 100644 index 00000000..50368086 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/oh_cursor_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 OH_CURSOR_FUZZER_H +#define OH_CURSOR_FUZZER_H + +#define FUZZ_PROJECT_NAME "oh_cursor_fuzzer" + +#endif // OH_CURSOR_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_cursor_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/BUILD.gn new file mode 100644 index 00000000..994ba471 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("oh_data_value_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = "${relational_store_base_path}/test/ndk/fuzztest/oh_data_value_fuzzer" + + sources = [ "oh_data_value_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":oh_data_value_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/corpus/init new file mode 100644 index 00000000..64d7767e --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/oh_data_value_fuzzer.cpp b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/oh_data_value_fuzzer.cpp new file mode 100644 index 00000000..2ad43473 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/oh_data_value_fuzzer.cpp @@ -0,0 +1,422 @@ +/* + * 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 "oh_data_value_fuzzer.h" + +#include + +#include "grd_api_manager.h" +#include "oh_data_value.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + + +#define BLOBSIZE_MIN 1 +#define BLOBSIZE_MAX 10 + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +namespace OHOS { +void OH_Value_DestroyFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = provider.ConsumeBool() ? OH_Value_Create() : nullptr; + OH_Value_Destroy(value); +} + +void OH_Value_PutNullFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + OH_Value_PutNull(value); + OH_Value_Destroy(value); + + OH_Value_PutNull(nullptr); + OH_Value_Destroy(nullptr); +} + +void OH_Value_PutIntFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + int64_t val = provider.ConsumeIntegral(); + OH_Value_PutInt(value, val); + OH_Value_Destroy(value); + + OH_Value_PutInt(nullptr, 0); + OH_Value_Destroy(nullptr); +} + +void OH_Value_PutRealFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + double val = provider.ConsumeFloatingPoint(); + OH_Value_PutReal(value, val); + OH_Value_Destroy(value); + + OH_Value_PutReal(nullptr, 0); + OH_Value_Destroy(nullptr); +} + +void OH_Value_PutTextFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + std::string val = provider.ConsumeRandomLengthString(); + OH_Value_PutText(value, val.c_str()); + OH_Value_Destroy(value); + + OH_Value_PutText(nullptr, nullptr); + OH_Value_Destroy(nullptr); +} + +void OH_Value_PutBlobFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + size_t blobSize = provider.ConsumeIntegralInRange(BLOBSIZE_MIN, BLOBSIZE_MAX); + std::vector blobData = provider.ConsumeBytes(blobSize); + blobData.resize(blobSize); + OH_Value_PutBlob(value, blobData.data(), blobSize); + OH_Value_Destroy(value); + + OH_Value_PutBlob(nullptr, nullptr, 0); + OH_Value_Destroy(nullptr); +} + +void OH_Value_PutAssetFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + OH_Value_Destroy(value); + return; + } + OH_Value_PutAsset(value, asset); + OH_Value_Destroy(value); + + OH_Value_PutAsset(nullptr, nullptr); + OH_Value_Destroy(nullptr); +} + +void OH_Value_PutAssetsFuzz(FuzzedDataProvider &provider) +{ + size_t count = provider.ConsumeIntegralInRange(BLOBSIZE_MIN, BLOBSIZE_MAX); + Data_Asset **assets = OH_Data_Asset_CreateMultiple(count); + if (assets == nullptr) { + return; + } + for (size_t i = 0; i < count; i++) { + int64_t value = provider.ConsumeIntegral(); + OH_Data_Asset_SetCreateTime(assets[i], value); + } + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + OH_Data_Asset_DestroyMultiple(assets, count); + return; + } + OH_Value_PutAssets(value, assets, count); + OH_Value_Destroy(value); + OH_Data_Asset_DestroyMultiple(assets, count); + + OH_Value_PutAssets(nullptr, nullptr, 0); + OH_Value_Destroy(nullptr); + OH_Data_Asset_DestroyMultiple(nullptr, 0); +} + +void OH_Value_PutFloatVectorFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + size_t length = provider.ConsumeIntegralInRange(BLOBSIZE_MIN, BLOBSIZE_MAX); + float floatArr[length]; + for (int i = 0; i < length; i++) { + float val = provider.ConsumeFloatingPoint(); + floatArr[i] = val; + } + OH_Value_PutFloatVector(value, floatArr, length); + OH_Value_Destroy(value); + + OH_Value_PutFloatVector(nullptr, nullptr, 0); + OH_Value_Destroy(nullptr); +} + +void OH_Value_PutUnlimitedIntFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + int sign = provider.ConsumeBool() ? 0 : 1; + size_t length = provider.ConsumeIntegralInRange(BLOBSIZE_MIN, BLOBSIZE_MAX); + uint64_t trueForm[length]; + for (int i = 0; i < length; i++) { + uint64_t trueFormValue = provider.ConsumeIntegral(); + trueForm[i] = trueFormValue; + } + OH_Value_PutUnlimitedInt(value, sign, trueForm, length); + OH_Value_Destroy(value); + + OH_Value_PutUnlimitedInt(nullptr, 0, nullptr, 0); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetTypeFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + OH_ColumnType type; + OH_Value_GetType(value, &type); + OH_Value_Destroy(value); + + OH_Value_GetType(nullptr, &type); + OH_Value_Destroy(nullptr); +} + +void OH_Value_IsNullFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + bool val; + OH_Value_IsNull(value, &val); + OH_Value_Destroy(value); + + OH_Value_IsNull(nullptr, &val); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetIntFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + int64_t val; + OH_Value_GetInt(value, &val); + OH_Value_Destroy(value); + + OH_Value_GetInt(nullptr, &val); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetRealFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + double val; + OH_Value_GetReal(value, &val); + OH_Value_Destroy(value); + + OH_Value_GetReal(nullptr, &val); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetTextFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + const char *textValue; + OH_Value_GetText(value, &textValue); + OH_Value_Destroy(value); + + OH_Value_GetText(nullptr, &textValue); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetBlobFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + const uint8_t *val; + size_t length; + OH_Value_GetBlob(value, &val, &length); + OH_Value_Destroy(value); + + OH_Value_GetBlob(nullptr, &val, &length); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetAssetFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + OH_Value_Destroy(value); + return; + } + OH_Value_GetAsset(value, asset); + OH_Value_Destroy(value); + OH_Data_Asset_DestroyOne(asset); + + OH_Value_GetAsset(nullptr, nullptr); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetAssetsCountFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + size_t length = provider.ConsumeIntegral(); + OH_Value_GetAssetsCount(value, &length); + OH_Value_Destroy(value); + + OH_Value_GetAssetsCount(nullptr, &length); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetAssetsFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + size_t inLen = provider.ConsumeIntegralInRange(BLOBSIZE_MIN, BLOBSIZE_MAX); + Data_Asset *val = OH_Data_Asset_CreateOne(); + if (val == nullptr) { + OH_Value_Destroy(value); + return; + } + size_t outLen = provider.ConsumeIntegral(); + OH_Value_GetAssets(value, &val, inLen, &outLen); + OH_Value_Destroy(value); + OH_Data_Asset_DestroyOne(val); + + OH_Value_GetAssets(nullptr, nullptr, 0, nullptr); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetFloatVectorCountFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + size_t length = provider.ConsumeIntegral(); + OH_Value_GetFloatVectorCount(value, &length); + OH_Value_Destroy(value); + + OH_Value_GetFloatVectorCount(nullptr, nullptr); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetFloatVectorFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + size_t inLen = provider.ConsumeIntegralInRange(BLOBSIZE_MIN, BLOBSIZE_MAX); + float *val = new float[inLen]; + size_t outLen = provider.ConsumeIntegral(); + OH_Value_GetFloatVector(value, val, inLen, &outLen); + delete[] val; + OH_Value_Destroy(value); + + OH_Value_GetFloatVector(nullptr, nullptr, 0, nullptr); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetUnlimitedIntBandFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + size_t length = provider.ConsumeIntegral(); + OH_Value_GetUnlimitedIntBand(value, &length); + OH_Value_Destroy(value); + + OH_Value_GetUnlimitedIntBand(nullptr, nullptr); + OH_Value_Destroy(nullptr); +} + +void OH_Value_GetUnlimitedIntFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Value *value = OH_Value_Create(); + if (value == nullptr) { + return; + } + int sign = provider.ConsumeIntegral(); + size_t inLen = provider.ConsumeIntegralInRange(BLOBSIZE_MIN, BLOBSIZE_MAX); + uint64_t *trueForm = new uint64_t[inLen]; + size_t outLen = provider.ConsumeIntegral(); + OH_Value_GetUnlimitedInt(value, &sign, trueForm, inLen, &outLen); + delete[] trueForm; + OH_Value_Destroy(value); + + OH_Value_GetUnlimitedInt(nullptr, nullptr, nullptr, 0, nullptr); + OH_Value_Destroy(nullptr); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + OHOS::OH_Value_DestroyFuzz(provider); + OHOS::OH_Value_PutNullFuzz(provider); + OHOS::OH_Value_PutIntFuzz(provider); + OHOS::OH_Value_PutRealFuzz(provider); + OHOS::OH_Value_PutTextFuzz(provider); + OHOS::OH_Value_PutBlobFuzz(provider); + OHOS::OH_Value_PutAssetFuzz(provider); + OHOS::OH_Value_PutAssetsFuzz(provider); + OHOS::OH_Value_PutFloatVectorFuzz(provider); + OHOS::OH_Value_PutUnlimitedIntFuzz(provider); + OHOS::OH_Value_GetTypeFuzz(provider); + OHOS::OH_Value_IsNullFuzz(provider); + OHOS::OH_Value_GetIntFuzz(provider); + OHOS::OH_Value_GetRealFuzz(provider); + OHOS::OH_Value_GetTextFuzz(provider); + OHOS::OH_Value_GetBlobFuzz(provider); + OHOS::OH_Value_GetAssetFuzz(provider); + OHOS::OH_Value_GetAssetsCountFuzz(provider); + OHOS::OH_Value_GetAssetsFuzz(provider); + OHOS::OH_Value_GetFloatVectorCountFuzz(provider); + OHOS::OH_Value_GetFloatVectorFuzz(provider); + OHOS::OH_Value_GetUnlimitedIntBandFuzz(provider); + OHOS::OH_Value_GetUnlimitedIntFuzz(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/oh_data_value_fuzzer.h b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/oh_data_value_fuzzer.h new file mode 100644 index 00000000..01b63c5e --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/oh_data_value_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 OH_DATA_VALUE_FUZZER_H +#define OH_DATA_VALUE_FUZZER_H + +#define FUZZ_PROJECT_NAME "oh_data_value_fuzzer" + +#endif // OH_DATA_VALUE_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_value_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/BUILD.gn new file mode 100644 index 00000000..af3c6c0f --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("oh_data_values_buckets_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = "${relational_store_base_path}/test/ndk/fuzztest/oh_data_values_buckets_fuzzer" + + sources = [ "oh_data_values_buckets_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":oh_data_values_buckets_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/corpus/init new file mode 100644 index 00000000..64d7767e --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/oh_data_values_buckets_fuzzer.cpp b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/oh_data_values_buckets_fuzzer.cpp new file mode 100644 index 00000000..53e2e2be --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/oh_data_values_buckets_fuzzer.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 "oh_data_values_buckets_fuzzer.h" + +#include + +#include "grd_api_manager.h" +#include "oh_data_value.h" +#include "oh_data_values_buckets.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + + +#define LENGTH_MIN 1 +#define LENGTH_MAX 10 + +#define STRING_MAX 10 + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +namespace OHOS { + +OH_VBucket *CreateRandomVBucket(FuzzedDataProvider &provider) +{ + OH_VBucket *vBucket = OH_Rdb_CreateValuesBucket(); + if (vBucket == nullptr) { + return nullptr; + } + std::string column = provider.ConsumeRandomLengthString(STRING_MAX); + int64_t value = provider.ConsumeIntegral(); + if (column.empty()) { + vBucket->destroy(vBucket); + return nullptr; + } + vBucket->putInt64(vBucket, column.c_str(), value); + return vBucket; +} + +OH_Data_VBuckets *CreateRandomVBuckets(FuzzedDataProvider &provider) +{ + OH_Data_VBuckets *vBuckets = OH_VBuckets_Create(); + if (vBuckets == nullptr) { + return nullptr; + } + OH_VBucket *vBucket = CreateRandomVBucket(provider); + if (vBucket != nullptr) { + OH_VBuckets_PutRow(vBuckets, vBucket); + } + return vBuckets; +} + +void OH_VBuckets_PutRowFuzz(FuzzedDataProvider &provider) +{ + OH_Data_VBuckets *vBuckets = OH_VBuckets_Create(); + if (vBuckets == nullptr) { + return; + } + + OH_VBucket *vBucket = CreateRandomVBucket(provider); + if (vBucket != nullptr) { + OH_VBuckets_PutRow(vBuckets, vBucket); + vBucket->destroy(vBucket); + } + OH_VBuckets_Destroy(vBuckets); + + OH_VBuckets_Destroy(nullptr); +} + +void OH_VBuckets_PutRowsFuzz(FuzzedDataProvider &provider) +{ + OH_Data_VBuckets *vBuckets = OH_VBuckets_Create(); + if (vBuckets == nullptr) { + return; + } + + OH_Data_VBuckets *rows = CreateRandomVBuckets(provider); + if (rows != nullptr) { + OH_VBuckets_PutRows(vBuckets, rows); + OH_VBuckets_Destroy(rows); + } + + OH_VBuckets_Destroy(vBuckets); +} + +void OH_VBuckets_RowCountFuzz(FuzzedDataProvider &provider) +{ + OH_Data_VBuckets *vBuckets = CreateRandomVBuckets(provider); + if (vBuckets == nullptr) { + return; + } + size_t count; + OH_VBuckets_RowCount(vBuckets, &count); + OH_VBuckets_Destroy(vBuckets); +} + +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + OHOS::OH_VBuckets_PutRowFuzz(provider); + OHOS::OH_VBuckets_PutRowsFuzz(provider); + OHOS::OH_VBuckets_RowCountFuzz(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/oh_data_values_buckets_fuzzer.h b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/oh_data_values_buckets_fuzzer.h new file mode 100644 index 00000000..7e1294c0 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/oh_data_values_buckets_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 OH_DATA_VALUES_BUCKETS_FUZZER_H +#define OH_DATA_VALUES_BUCKETS_FUZZER_H + +#define FUZZ_PROJECT_NAME "oh_data_values_buckets_fuzzer" + +#endif // OH_DATA_VALUES_BUCKETS_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_buckets_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/BUILD.gn new file mode 100644 index 00000000..0bd598f1 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("oh_data_values_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = "${relational_store_base_path}/test/ndk/fuzztest/oh_data_values_fuzzer" + + sources = [ "oh_data_values_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":oh_data_values_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/corpus/init new file mode 100644 index 00000000..64d7767e --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/oh_data_values_fuzzer.cpp b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/oh_data_values_fuzzer.cpp new file mode 100644 index 00000000..805ffe83 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/oh_data_values_fuzzer.cpp @@ -0,0 +1,550 @@ +/* + * 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 "oh_data_values_fuzzer.h" + +#include + +#include "grd_api_manager.h" +#include "oh_data_value.h" +#include "oh_data_values.h" +#include "oh_data_values_buckets.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + + +#define LOOPS_MIN 1 +#define LOOPS_MAX 10 + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +namespace OHOS { + +OH_Data_Values *CreateRandomDataValues(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return nullptr; + } + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + for (size_t i = 0; i < loops; ++i) { + int64_t intValue = provider.ConsumeIntegral(); + double realValue = provider.ConsumeFloatingPoint(); + std::string textValue = provider.ConsumeRandomLengthString(); + size_t blobLength = provider.ConsumeIntegral(); + std::vector blobValue = provider.ConsumeBytes(blobLength); + + OH_Values_PutInt(values, intValue); + OH_Values_PutReal(values, realValue); + OH_Values_PutText(values, textValue.c_str()); + OH_Values_PutBlob(values, blobValue.data(), blobValue.size()); + } + return values; +} + +void OH_Values_PutFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + OH_Data_Value *dataValue = OH_Value_Create(); + if (dataValue != nullptr) { + OH_Values_Put(values, dataValue); + OH_Values_Put(values, nullptr); + OH_Values_Put(nullptr, dataValue); + } + + OH_Values_Destroy(values); + OH_Value_Destroy(dataValue); + + OH_Values_Put(nullptr, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutNullFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + + OH_Values_PutNull(values); + OH_Values_Destroy(values); + + OH_Values_PutNull(nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutIntFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + + int64_t intValue = provider.ConsumeIntegral(); + OH_Values_PutInt(values, intValue); + OH_Values_Destroy(values); + + OH_Values_PutInt(nullptr, 0); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutRealFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + + double realValue = provider.ConsumeFloatingPoint(); + OH_Values_PutReal(values, realValue); + OH_Values_Destroy(values); + + OH_Values_PutReal(nullptr, 0); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutTextFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + + std::string textValue = provider.ConsumeRandomLengthString(); + OH_Values_PutText(values, textValue.c_str()); + OH_Values_PutText(values, nullptr); + OH_Values_PutText(nullptr, textValue.c_str()); + OH_Values_Destroy(values); + + OH_Values_PutText(nullptr, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutBlobFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + size_t blobLength = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector blobValue = provider.ConsumeBytes(blobLength); + OH_Values_PutBlob(values, blobValue.data(), blobValue.size()); + OH_Values_Destroy(values); + + OH_Values_PutBlob(nullptr, nullptr, 0); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutAssetFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + OH_Values_Destroy(values); + return; + } + OH_Values_PutAsset(values, asset); + OH_Values_Destroy(values); + OH_Data_Asset_DestroyOne(asset); + + OH_Values_PutAsset(nullptr, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutAssetsFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector assets; + for (size_t i = 0; i < loops; i++) { + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + continue; + } + assets.push_back(asset); + } + + if (!assets.empty()) { + OH_Values_PutAssets(values, assets.data(), assets.size()); + } + + OH_Values_Destroy(values); + for (size_t i = 0; i < assets.size(); i++) { + Data_Asset *asset = assets[i]; + OH_Data_Asset_DestroyOne(asset); + } + + OH_Values_PutAssets(nullptr, nullptr, 0); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutFloatVectorFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector floatVector(loops); + for (size_t i = 0; i < loops; ++i) { + floatVector[i] = provider.ConsumeFloatingPoint(); + } + + OH_Values_PutFloatVector(values, floatVector.data(), floatVector.size()); + OH_Values_Destroy(values); + + OH_Values_PutFloatVector(nullptr, nullptr, 0); + OH_Values_Destroy(nullptr); +} + +void OH_Values_PutUnlimitedIntFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = OH_Values_Create(); + if (values == nullptr) { + return; + } + + int sign = provider.ConsumeIntegral(); + size_t loops = provider.ConsumeIntegralInRange(LOOPS_MIN, LOOPS_MAX); + std::vector trueForm(loops); + for (size_t i = 0; i < loops; ++i) { + trueForm[i] = provider.ConsumeIntegral(); + } + + OH_Values_PutUnlimitedInt(values, sign, trueForm.data(), trueForm.size()); + OH_Values_Destroy(values); + + OH_Values_PutUnlimitedInt(nullptr, 0, nullptr, 0); + OH_Values_Destroy(nullptr); +} + +void OH_Values_CountFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + size_t count; + OH_Values_Count(values, &count); + OH_Values_Destroy(values); + + OH_Values_Count(nullptr, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetTypeFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + OH_ColumnType type; + OH_Values_GetType(values, index, &type); + OH_Values_Destroy(values); + + OH_Values_GetType(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + OH_Data_Value *dataValue; + OH_Values_Get(values, index, &dataValue); + OH_Values_Destroy(values); + + OH_Values_Get(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_IsNullFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + bool isNull; + OH_Values_IsNull(values, index, &isNull); + OH_Values_Destroy(values); + + OH_Values_IsNull(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetIntFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + int64_t intValue; + OH_Values_GetInt(values, index, &intValue); + OH_Values_Destroy(values); + + OH_Values_GetInt(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetRealFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + double realValue; + OH_Values_GetReal(values, index, &realValue); + OH_Values_Destroy(values); + + OH_Values_GetReal(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetTextFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + const char *textValue; + OH_Values_GetText(values, index, &textValue); + OH_Values_Destroy(values); + + OH_Values_GetText(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetBlobFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + const uint8_t *blobValue; + size_t blobLength; + OH_Values_GetBlob(values, index, &blobValue, &blobLength); + OH_Values_Destroy(values); + + OH_Values_GetBlob(nullptr, 0, nullptr, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetAssetFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset != nullptr) { + OH_Values_GetAsset(values, index, asset); + } + OH_Values_Destroy(values); + OH_Data_Asset_DestroyOne(asset); + + OH_Values_GetAsset(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetAssetsCountFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + size_t count; + OH_Values_GetAssetsCount(values, index, &count); + OH_Values_Destroy(values); + + OH_Values_GetAssetsCount(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetAssetsFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + size_t inLen; + OH_Values_GetAssetsCount(values, index, &inLen); + if (inLen > 0) { + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + OH_Values_Destroy(values); + return; + } + size_t outLen; + OH_Values_GetAssets(values, index, &asset, inLen, &outLen); + OH_Data_Asset_DestroyOne(asset); + } + + OH_Values_Destroy(values); + + OH_Values_GetAssets(nullptr, 0, nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetFloatVectorCountFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + size_t count; + OH_Values_GetFloatVectorCount(values, index, &count); + OH_Values_Destroy(values); + + OH_Values_GetFloatVectorCount(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetFloatVectorFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + size_t inLen; + OH_Values_GetFloatVectorCount(values, index, &inLen); + if (inLen > 0) { + float *floatVector = new float[inLen]; + size_t outLen; + OH_Values_GetFloatVector(values, index, floatVector, inLen, &outLen); + delete[] floatVector; + } + + OH_Values_Destroy(values); + + OH_Values_GetFloatVector(nullptr, 0, nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetUnlimitedIntBandFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + size_t count; + OH_Values_GetUnlimitedIntBand(values, index, &count); + OH_Values_Destroy(values); + + OH_Values_GetUnlimitedIntBand(nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +void OH_Values_GetUnlimitedIntFuzz(FuzzedDataProvider &provider) +{ + OH_Data_Values *values = CreateRandomDataValues(provider); + if (values == nullptr) { + return; + } + + int index = provider.ConsumeIntegral(); + size_t inLen; + OH_Values_GetUnlimitedIntBand(values, index, &inLen); + if (inLen > 0) { + int sign; + uint64_t *trueForm = new uint64_t[inLen]; + size_t outLen; + OH_Values_GetUnlimitedInt(values, index, &sign, trueForm, inLen, &outLen); + delete[] trueForm; + } + + OH_Values_Destroy(values); + + OH_Values_GetUnlimitedInt(nullptr, 0, nullptr, nullptr, 0, nullptr); + OH_Values_Destroy(nullptr); +} + +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + OHOS::OH_Values_PutFuzz(provider); + OHOS::OH_Values_PutNullFuzz(provider); + OHOS::OH_Values_PutIntFuzz(provider); + OHOS::OH_Values_PutRealFuzz(provider); + OHOS::OH_Values_PutTextFuzz(provider); + OHOS::OH_Values_PutBlobFuzz(provider); + OHOS::OH_Values_PutAssetFuzz(provider); + OHOS::OH_Values_PutAssetsFuzz(provider); + OHOS::OH_Values_PutFloatVectorFuzz(provider); + OHOS::OH_Values_PutUnlimitedIntFuzz(provider); + OHOS::OH_Values_CountFuzz(provider); + OHOS::OH_Values_GetTypeFuzz(provider); + OHOS::OH_Values_GetFuzz(provider); + OHOS::OH_Values_IsNullFuzz(provider); + OHOS::OH_Values_GetIntFuzz(provider); + OHOS::OH_Values_GetRealFuzz(provider); + OHOS::OH_Values_GetTextFuzz(provider); + OHOS::OH_Values_GetBlobFuzz(provider); + OHOS::OH_Values_GetAssetFuzz(provider); + OHOS::OH_Values_GetAssetsCountFuzz(provider); + OHOS::OH_Values_GetAssetsFuzz(provider); + OHOS::OH_Values_GetFloatVectorCountFuzz(provider); + OHOS::OH_Values_GetFloatVectorFuzz(provider); + OHOS::OH_Values_GetUnlimitedIntBandFuzz(provider); + OHOS::OH_Values_GetUnlimitedIntFuzz(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/oh_data_values_fuzzer.h b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/oh_data_values_fuzzer.h new file mode 100644 index 00000000..1fb1e57e --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/oh_data_values_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 OH_DATA_VALUES_FUZZER_H +#define OH_DATA_VALUES_FUZZER_H + +#define FUZZ_PROJECT_NAME "oh_data_values_fuzzer" + +#endif // OH_DATA_VALUES_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_data_values_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/BUILD.gn new file mode 100644 index 00000000..d39cf556 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("oh_predicates_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = "${relational_store_base_path}/test/ndk/fuzztest/oh_predicates_fuzzer" + + sources = [ "oh_predicates_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":oh_predicates_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/corpus/init new file mode 100644 index 00000000..64d7767e --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/oh_predicates_fuzzer.cpp b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/oh_predicates_fuzzer.cpp new file mode 100644 index 00000000..5969a0a1 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/oh_predicates_fuzzer.cpp @@ -0,0 +1,489 @@ +/* + * 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 "oh_predicates_fuzzer.h" + +#include + +#include "grd_api_manager.h" +#include "oh_data_value.h" +#include "oh_data_values.h" +#include "oh_data_values_buckets.h" +#include "oh_predicates.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +#define LENGTH_MIN 1 +#define LENGTH_MAX 10 + +#define STRING_LENGTH_MAX 20 + +namespace OHOS { + +std::vector ConsumeRandomLengthValueObjectVector(FuzzedDataProvider &provider) +{ + size_t loops = provider.ConsumeIntegralInRange(LENGTH_MIN, LENGTH_MAX); + std::vector columns; + for (size_t i = 0; i < loops; ++i) { + OH_VObject *obj = OH_Rdb_CreateValueObject(); + columns.emplace_back(obj); + } + return columns; +} + +void TestOH_Predicates_equalTo(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->equalTo(predicates, field.c_str(), obj); + predicates->destroy(predicates); +} + +void TestOH_Predicates_notEqualTo(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->notEqualTo(predicates, field.c_str(), obj); + predicates->destroy(predicates); +} + +void TestOH_Predicates_beginWrap(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + predicates->beginWrap(predicates); + predicates->destroy(predicates); +} + +void TestOH_Predicates_endWrap(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + predicates->endWrap(predicates); + predicates->destroy(predicates); +} + +void TestOH_Predicates_orOperate(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + predicates->orOperate(predicates); + predicates->destroy(predicates); +} + +void TestOH_Predicates_andOperate(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + predicates->andOperate(predicates); + predicates->destroy(predicates); +} + +void TestOH_Predicates_isNull(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->isNull(predicates, field.c_str()); + predicates->destroy(predicates); +} + +void TestOH_Predicates_isNotNull(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->isNotNull(predicates, field.c_str()); + predicates->destroy(predicates); +} + +void TestOH_Predicates_like(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->like(predicates, field.c_str(), obj); + predicates->destroy(predicates); + obj->destroy(obj); +} + +void TestOH_Predicates_between(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->between(predicates, field.c_str(), obj); + predicates->destroy(predicates); + obj->destroy(obj); +} + +void TestOH_Predicates_notBetween(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->notBetween(predicates, field.c_str(), obj); + predicates->destroy(predicates); + obj->destroy(obj); +} + +void TestOH_Predicates_greaterThan(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->greaterThan(predicates, field.c_str(), obj); + predicates->destroy(predicates); + obj->destroy(obj); +} + +void TestOH_Predicates_lessThan(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->lessThan(predicates, field.c_str(), obj); + predicates->destroy(predicates); + obj->destroy(obj); +} + +void TestOH_Predicates_greaterThanOrEqualTo(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->greaterThanOrEqualTo(predicates, field.c_str(), obj); + predicates->destroy(predicates); + obj->destroy(obj); +} + +void TestOH_Predicates_lessThanOrEqualTo(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + predicates->lessThanOrEqualTo(predicates, field.c_str(), obj); + predicates->destroy(predicates); + obj->destroy(obj); +} + +void TestOH_Predicates_orderBy(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + OH_VObject *obj = OH_Rdb_CreateValueObject(); + if (obj == nullptr) { + predicates->destroy(predicates); + return; + } + std::string value = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + obj->putText(obj, value.c_str()); + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_OrderType type = static_cast(provider.ConsumeIntegral()); + predicates->orderBy(predicates, field.c_str(), type); + predicates->destroy(predicates); + obj->destroy(obj); +} + +void TestOH_Predicates_distinct(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + predicates->distinct(predicates); + predicates->destroy(predicates); +} + +void TestOH_Predicates_limit(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + unsigned int value = provider.ConsumeIntegral(); + predicates->limit(predicates, value); + predicates->destroy(predicates); +} + +void TestOH_Predicates_offset(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + unsigned int rowOffset = provider.ConsumeIntegral(); + predicates->offset(predicates, rowOffset); + predicates->destroy(predicates); +} + +void TestOH_Predicates_groupBy(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + size_t loops = provider.ConsumeIntegralInRange(LENGTH_MIN, LENGTH_MAX); + const char *fields[loops]; + for (size_t i = 0; i < loops; ++i) { + static std::string fieldsString = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX).c_str(); + fields[i] = fieldsString.c_str(); + } + predicates->groupBy(predicates, fields, loops); + predicates->destroy(predicates); +} + +void TestOH_Predicates_in(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + std::vector values = ConsumeRandomLengthValueObjectVector(provider); + for (auto value : values) { + predicates->in(predicates, field.c_str(), value); + value->destroy(value); + } + predicates->destroy(predicates); +} + +void TestOH_Predicates_notIn(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + std::vector values = ConsumeRandomLengthValueObjectVector(provider); + for (auto value : values) { + predicates->notIn(predicates, field.c_str(), value); + value->destroy(value); + } + predicates->destroy(predicates); +} + +void TestOH_Predicates_Having(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + std::string conditions = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Data_Values *values = OH_Values_Create(); + OH_Predicates_Having(predicates, conditions.c_str(), values); + predicates->destroy(predicates); +} + +void TestOH_Predicates_NotLike(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + std::string pattern = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates_NotLike(predicates, field.c_str(), pattern.c_str()); + predicates->destroy(predicates); +} + +void TestOH_Predicates_Glob(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + std::string pattern = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates_Glob(predicates, field.c_str(), pattern.c_str()); + predicates->destroy(predicates); +} + +void TestOH_Predicates_NotGlob(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + std::string field = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + std::string pattern = provider.ConsumeRandomLengthString(STRING_LENGTH_MAX); + OH_Predicates_NotGlob(predicates, field.c_str(), pattern.c_str()); + predicates->destroy(predicates); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + OHOS::TestOH_Predicates_equalTo(provider); + OHOS::TestOH_Predicates_notEqualTo(provider); + OHOS::TestOH_Predicates_beginWrap(provider); + OHOS::TestOH_Predicates_endWrap(provider); + OHOS::TestOH_Predicates_orOperate(provider); + OHOS::TestOH_Predicates_andOperate(provider); + OHOS::TestOH_Predicates_isNull(provider); + OHOS::TestOH_Predicates_isNotNull(provider); + OHOS::TestOH_Predicates_like(provider); + OHOS::TestOH_Predicates_between(provider); + OHOS::TestOH_Predicates_notBetween(provider); + OHOS::TestOH_Predicates_greaterThan(provider); + OHOS::TestOH_Predicates_lessThan(provider); + OHOS::TestOH_Predicates_greaterThanOrEqualTo(provider); + OHOS::TestOH_Predicates_lessThanOrEqualTo(provider); + OHOS::TestOH_Predicates_orderBy(provider); + OHOS::TestOH_Predicates_distinct(provider); + OHOS::TestOH_Predicates_limit(provider); + OHOS::TestOH_Predicates_offset(provider); + OHOS::TestOH_Predicates_groupBy(provider); + OHOS::TestOH_Predicates_in(provider); + OHOS::TestOH_Predicates_notIn(provider); + OHOS::TestOH_Predicates_Having(provider); + OHOS::TestOH_Predicates_NotLike(provider); + OHOS::TestOH_Predicates_Glob(provider); + OHOS::TestOH_Predicates_NotGlob(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/oh_predicates_fuzzer.h b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/oh_predicates_fuzzer.h new file mode 100644 index 00000000..a229e340 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/oh_predicates_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 OH_PREDICATES_FUZZER_H +#define OH_PREDICATES_FUZZER_H + +#define FUZZ_PROJECT_NAME "oh_predicates_fuzzer" + +#endif // OH_PREDICATES_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_predicates_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/BUILD.gn new file mode 100644 index 00000000..3cb64052 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("oh_rdb_crypto_param_fuzzer") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = "${relational_store_base_path}/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer" + + sources = [ "oh_rdb_crypto_param_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":oh_rdb_crypto_param_fuzzer", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/corpus/init new file mode 100644 index 00000000..64d7767e --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/oh_rdb_crypto_param_fuzzer.cpp b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/oh_rdb_crypto_param_fuzzer.cpp new file mode 100644 index 00000000..f8d69fe7 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/oh_rdb_crypto_param_fuzzer.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 "oh_rdb_crypto_param_fuzzer.h" + +#include + +#include "grd_api_manager.h" +#include "oh_data_value.h" +#include "oh_data_values.h" +#include "oh_data_values_buckets.h" +#include "oh_predicates.h" +#include "oh_rdb_crypto_param.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + +#define LENGTH_MIN 1 +#define LENGTH_MAX 10 + +using namespace OHOS; +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; +using namespace std; + +namespace OHOS { + +void OH_Rdb_DestroyCryptoParamFuzz(FuzzedDataProvider &provider) +{ + OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam(); + if (param != nullptr) { + OH_Rdb_DestroyCryptoParam(param); + } + OH_Rdb_DestroyCryptoParam(nullptr); +} + +void OH_Crypto_SetEncryptionKeyFuzz(FuzzedDataProvider &provider) +{ + OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam(); + if (param != nullptr) { + size_t bytesSize = provider.ConsumeIntegralInRange(LENGTH_MIN, LENGTH_MAX); + std::vector blobData = provider.ConsumeBytes(bytesSize); + OH_Crypto_SetEncryptionKey(param, blobData.data(), blobData.size()); + } + OH_Rdb_DestroyCryptoParam(param); +} + +void OH_Crypto_SetIterationFuzz(FuzzedDataProvider &provider) +{ + OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam(); + if (param != nullptr) { + const int64_t iteration = provider.ConsumeIntegral(); + OH_Crypto_SetIteration(param, iteration); + } + OH_Rdb_DestroyCryptoParam(param); +} + +void OH_Crypto_SetEncryptionAlgoFuzz(FuzzedDataProvider &provider) +{ + OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam(); + if (param != nullptr) { + const int32_t algo = provider.ConsumeIntegral(); + OH_Crypto_SetEncryptionAlgo(param, algo); + } + OH_Rdb_DestroyCryptoParam(param); +} + +void OH_Crypto_SetHmacAlgoFuzz(FuzzedDataProvider &provider) +{ + OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam(); + if (param != nullptr) { + const int32_t algo = provider.ConsumeIntegral(); + OH_Crypto_SetHmacAlgo(param, algo); + } + OH_Rdb_DestroyCryptoParam(param); +} + +void OH_Crypto_SetKdfAlgoFuzz(FuzzedDataProvider &provider) +{ + OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam(); + if (param != nullptr) { + const int32_t algo = provider.ConsumeIntegral(); + OH_Crypto_SetKdfAlgo(param, algo); + } + OH_Rdb_DestroyCryptoParam(param); +} + +void OH_Crypto_SetCryptoPageSizeFuzz(FuzzedDataProvider &provider) +{ + OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam(); + if (param != nullptr) { + const int64_t size = provider.ConsumeIntegral(); + OH_Crypto_SetCryptoPageSize(param, size); + } + OH_Rdb_DestroyCryptoParam(param); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + OHOS::OH_Rdb_DestroyCryptoParamFuzz(provider); + OHOS::OH_Crypto_SetEncryptionKeyFuzz(provider); + OHOS::OH_Crypto_SetIterationFuzz(provider); + OHOS::OH_Crypto_SetEncryptionAlgoFuzz(provider); + OHOS::OH_Crypto_SetHmacAlgoFuzz(provider); + OHOS::OH_Crypto_SetKdfAlgoFuzz(provider); + OHOS::OH_Crypto_SetCryptoPageSizeFuzz(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/oh_rdb_crypto_param_fuzzer.h b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/oh_rdb_crypto_param_fuzzer.h new file mode 100644 index 00000000..824febac --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/oh_rdb_crypto_param_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 OH_RDB_CRYPTO_PARAM_FUZZER_H +#define OH_RDB_CRYPTO_PARAM_FUZZER_H + +#define FUZZ_PROJECT_NAME "oh_rdb_crypto_param_fuzzer" + +#endif // OH_RDB_CRYPTO_PARAM_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/ndk/fuzztest/oh_rdb_crypto_param_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/BUILD.gn new file mode 100644 index 00000000..9df548a6 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("OHPredicatesFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/ndk/fuzztest/ohpredicates_fuzzer" + + sources = [ "ohpredicates_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":OHPredicatesFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/corpus/init new file mode 100644 index 00000000..65af8ee8 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/ohpredicates_fuzzer.cpp b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/ohpredicates_fuzzer.cpp new file mode 100644 index 00000000..5c3cdb86 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/ohpredicates_fuzzer.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 "ohpredicates_fuzzer.h" +#include +#include "oh_predicates.h" +#include "relational_store.h" +#include + +void OhPredicatesFuzzTest(FuzzedDataProvider &provider) +{ + static bool runEndFlag = false; + std::string tableName = provider.ConsumeRandomLengthString(); + std::string field = provider.ConsumeRandomLengthString(); + std::string pattern = provider.ConsumeRandomLengthString(); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates(tableName.c_str()); + OH_Predicates_NotLike(predicates, field.c_str(), pattern.c_str()); + OH_Predicates_Glob(predicates, field.c_str(), pattern.c_str()); + OH_Predicates_NotGlob(predicates, field.c_str(), pattern.c_str()); + + if (!runEndFlag) { + runEndFlag = true; + std::cout << "OhPredicatesFuzzTest end" << std::endl; + } + if (predicates != nullptr) { + predicates->destroy(predicates); + } +} + + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + /* Run your code on data */ + FuzzedDataProvider provider(data, size); + + // Test OH_Predicates_NotLike, OH_Predicates_Glob, OH_Predicates_NotGlob + OhPredicatesFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/ohpredicates_fuzzer.h b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/ohpredicates_fuzzer.h new file mode 100644 index 00000000..f4f89da1 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/ohpredicates_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 OHPREDICATES_FUZZER_H +#define OHPREDICATES_FUZZER_H + +#define FUZZ_PROJECT_NAME "ohpredicates_fuzzer" + +#endif // OHPREDICATES_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohpredicates_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/BUILD.gn new file mode 100644 index 00000000..9abc24ca --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("OHRdbTransactionFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/ndk/fuzztest/ohrdbtransaction_fuzzer" + + sources = [ "ohrdbtransaction_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":OHRdbTransactionFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/corpus/init new file mode 100644 index 00000000..2aea1356 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ diff --git a/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/ohrdbtransaction_fuzzer.cpp b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/ohrdbtransaction_fuzzer.cpp new file mode 100644 index 00000000..fa1e2cad --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/ohrdbtransaction_fuzzer.cpp @@ -0,0 +1,205 @@ +/* + * 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 "grd_api_manager.h" +#include "oh_rdb_transaction.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" +#include "ohrdbtransaction_fuzzer.h" +#include + +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +// Helper function to create an OH_Rdb_Config structure with random data +OH_Rdb_Config *CreateRandomConfig(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = new OH_Rdb_Config(); + config->selfSize = sizeof(OH_Rdb_Config); + config->dataBaseDir = strdup(provider.ConsumeRandomLengthString().c_str()); + config->storeName = strdup(provider.ConsumeRandomLengthString().c_str()); + config->bundleName = strdup(provider.ConsumeRandomLengthString().c_str()); + config->moduleName = strdup(provider.ConsumeRandomLengthString().c_str()); + config->isEncrypt = provider.ConsumeBool(); + config->securityLevel = provider.ConsumeIntegralInRange(S1, S4); + config->area = provider.ConsumeIntegralInRange(RDB_SECURITY_AREA_EL1, RDB_SECURITY_AREA_EL5); + return config; +} + +void ReleaseConfig(OH_Rdb_Config *config) +{ + if (config == nullptr) { + return; + } + if (config->dataBaseDir != nullptr) { + free(static_cast(const_cast(config->dataBaseDir))); + } + if (config->storeName != nullptr) { + free(static_cast(const_cast(config->storeName))); + } + if (config->bundleName != nullptr) { + free(static_cast(const_cast(config->bundleName))); + } + if (config->moduleName != nullptr) { + free(static_cast(const_cast(config->moduleName))); + } + delete config; + config = nullptr; +} + +OH_RDB_TransOptions *CreateRandomTransOptions(FuzzedDataProvider &provider) +{ + OH_RDB_TransOptions *options = OH_RdbTrans_CreateOptions(); + if (options == nullptr) { + return nullptr; + } + OH_RDB_TransType type = + static_cast(provider.ConsumeIntegralInRange(RDB_TRANS_DEFERRED, RDB_TRANS_BUTT)); + OH_RdbTransOption_SetType(options, type); + return options; +} + +OH_VBucket *CreateRandomVBucket(FuzzedDataProvider &provider) +{ + OH_VBucket *vBucket = OH_Rdb_CreateValuesBucket(); + if (vBucket == nullptr) { + return nullptr; + } + const int minLen = 1; + const int maxLen = 50; + size_t len = provider.ConsumeIntegralInRange(minLen, maxLen); + for (size_t i = 0; i < len; i++) { + std::string column = provider.ConsumeRandomLengthString(); + int64_t value = provider.ConsumeIntegral(); + vBucket->putInt64(vBucket, column.c_str(), value); + } + return vBucket; +} + +std::vector g_randomVBuckets; +OH_Data_VBuckets *CreateRandomVBuckets(FuzzedDataProvider &provider) +{ + const int minRowCount = 1; + const int maxRowCount = 5; + g_randomVBuckets.clear(); + size_t rowCount = provider.ConsumeIntegralInRange(minRowCount, maxRowCount); + OH_Data_VBuckets *list = OH_VBuckets_Create(); + for (size_t i = 0; i < rowCount; i++) { + OH_VBucket *valueBucket = CreateRandomVBucket(provider); + g_randomVBuckets.push_back(valueBucket); + OH_VBuckets_PutRow(list, valueBucket); + } + return list; +} + +void DeleteCapiValueBuckets(OH_Data_VBuckets *rows) +{ + OH_VBuckets_Destroy(rows); + for (auto row : g_randomVBuckets) { + if (row != nullptr) { + row->destroy(row); + } + } + g_randomVBuckets.clear(); +} + +OH_VObject *CreateTransVObject(FuzzedDataProvider &provider) +{ + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + if (valueObject == nullptr) { + return nullptr; + } + std::string value = provider.ConsumeRandomLengthString(); + valueObject->putText(valueObject, value.c_str()); + return valueObject; +} + +OH_Predicates* GetCapiTransPredicates(FuzzedDataProvider &provider, std::string table) +{ + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return nullptr; + } + std::string value = provider.ConsumeRandomLengthString(); + OH_VObject *valueObject = CreateTransVObject(provider); + if (valueObject == nullptr) { + predicates->destroy(predicates); + return nullptr; + } + predicates->equalTo(predicates, value.c_str(), valueObject); + valueObject->destroy(valueObject); + return predicates; +} + +void DeleteCapiTransPredicates(OH_Predicates *predicates) +{ + if (predicates == nullptr) { + return; + } + predicates->destroy(predicates); +} + +void TransactionFuzzTest(FuzzedDataProvider &provider) +{ + static bool runEndFlag = false; + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + OH_RDB_TransOptions *options = CreateRandomTransOptions(provider); + OH_Rdb_Transaction *trans = nullptr; + OH_Rdb_CreateTransaction(store, options, &trans); + OH_RdbTrans_Commit(trans); + OH_RdbTrans_Rollback(trans); + std::string table = provider.ConsumeRandomLengthString(); + int64_t rowId = 0; + OH_VBucket *valueBucket = CreateRandomVBucket(provider); + OH_RdbTrans_Insert(trans, table.c_str(), valueBucket, &rowId); + OH_Data_VBuckets *list = CreateRandomVBuckets(provider); + std::string batchTable = provider.ConsumeRandomLengthString(); + int64_t changes; + Rdb_ConflictResolution resolution = static_cast( + provider.ConsumeIntegralInRange(RDB_CONFLICT_NONE, RDB_CONFLICT_REPLACE)); + OH_RdbTrans_BatchInsert(trans, batchTable.c_str(), list, resolution, &changes); + OH_RdbTrans_InsertWithConflictResolution(trans, table.c_str(), valueBucket, resolution, &rowId); + OH_Predicates *predicate = GetCapiTransPredicates(provider, table); + OH_RdbTrans_UpdateWithConflictResolution(trans, valueBucket, predicate, resolution, &rowId); + DeleteCapiTransPredicates(predicate); + DeleteCapiValueBuckets(list); + OH_Rdb_CloseStore(store); + ReleaseConfig(config); + OH_RdbTrans_DestroyOptions(options); + if (valueBucket != nullptr) { + valueBucket->destroy(valueBucket); + } + OH_RdbTrans_Destroy(trans); + if (!runEndFlag) { + runEndFlag = true; + std::cout << "TransactionFuzzTest end" << std::endl; + } +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + TransactionFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/ohrdbtransaction_fuzzer.h b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/ohrdbtransaction_fuzzer.h new file mode 100644 index 00000000..b5d77e84 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/ohrdbtransaction_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 OH_RDB_TRANSACTION_FUZZER_H +#define OH_RDB_TRANSACTION_FUZZER_H + +#define FUZZ_PROJECT_NAME "ohrdbtransaction_fuzzer" + +#endif // OH_RDB_TRANSACTION_FUZZER_H diff --git a/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/ndk/fuzztest/ohrdbtransaction_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/BUILD.gn new file mode 100644 index 00000000..8fd3218b --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/BUILD.gn @@ -0,0 +1,72 @@ +# 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("RelationalStoreFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/ndk/fuzztest/relationalstore_fuzzer" + + sources = [ "relationalstore_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "access_token:libaccesstoken_sdk", + "access_token:libtoken_setproc", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":RelationalStoreFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/corpus/init new file mode 100644 index 00000000..65af8ee8 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/relationalstore_fuzzer.cpp b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/relationalstore_fuzzer.cpp new file mode 100644 index 00000000..d50f1c54 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/relationalstore_fuzzer.cpp @@ -0,0 +1,428 @@ +/* + * 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 "relationalstore_fuzzer.h" + +#include +#include +#include + +#include "grd_api_manager.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" +#include "accesstoken_kit.h" + +static constexpr const char *RDB_TEST_PATH = "/data/storage/el2/database/com.ohos.example.distributedndk/entry/"; + +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; +using namespace OHOS::Security::AccessToken; + +void CreateAndSetCryptoParam(FuzzedDataProvider &provider, OH_Rdb_ConfigV2 *config) +{ + if (config == nullptr) { + return; + } + OH_Rdb_CryptoParam *param = OH_Rdb_CreateCryptoParam(); + int32_t length = provider.ConsumeIntegral(); + std::vector key = provider.ConsumeBytes(length); + int64_t iterator = provider.ConsumeIntegral(); + int32_t algo = provider.ConsumeIntegral(); + int64_t size = provider.ConsumeIntegral(); + + OH_Crypto_SetEncryptionKey(param, key.data(), key.size()); + OH_Crypto_SetIteration(param, iterator); + OH_Crypto_SetEncryptionAlgo(param, algo); + OH_Crypto_SetHmacAlgo(param, algo); + OH_Crypto_SetKdfAlgo(param, algo); + OH_Crypto_SetCryptoPageSize(param, size); + OH_Rdb_SetCryptoParam(config, param); + if (param != nullptr) { + OH_Rdb_DestroyCryptoParam(param); + } +} + +constexpr int RDB_CONFIG_PLUGINS_MAX = 16; +void CreateAndSetPlugins(FuzzedDataProvider &provider, OH_Rdb_ConfigV2 *config) +{ + uint32_t count = provider.ConsumeIntegralInRange(0, RDB_CONFIG_PLUGINS_MAX); + std::vector plugins; + for (uint32_t i = 0; i < count; i++) { + plugins.push_back(provider.ConsumeRandomLengthString()); + } + const char *arr[RDB_CONFIG_PLUGINS_MAX] = {nullptr}; + for (size_t i = 0; i < count; ++i) { + arr[i] = plugins[i].c_str(); + } + OH_Rdb_SetPlugins(config, arr, count); +} + +void AppendApi20ConfigV2(FuzzedDataProvider &provider, struct OH_Rdb_ConfigV2 *configV2) +{ + if (configV2 == nullptr) { + return; + } + bool readOnly = provider.ConsumeBool(); + OH_Rdb_SetReadOnly(configV2, readOnly); + std::string customDir = provider.ConsumeRandomLengthString(); + OH_Rdb_SetCustomDir(configV2, customDir.c_str()); + CreateAndSetPlugins(provider, configV2); + CreateAndSetCryptoParam(provider, configV2); +} + +struct OH_Rdb_ConfigV2 *CreateOHRdbConfigV2(FuzzedDataProvider &provider) +{ + struct OH_Rdb_ConfigV2 *configV2 = OH_Rdb_CreateConfig(); + if (configV2 == nullptr) { + return nullptr; + } + std::string databaseDir = provider.ConsumeRandomLengthString(); + OH_Rdb_SetDatabaseDir(configV2, databaseDir.c_str()); + std::string storeName = provider.ConsumeRandomLengthString(); + OH_Rdb_SetStoreName(configV2, storeName.c_str()); + std::string bundleName = provider.ConsumeRandomLengthString(); + OH_Rdb_SetBundleName(configV2, bundleName.c_str()); + std::string bmoduleName = provider.ConsumeRandomLengthString(); + OH_Rdb_SetModuleName(configV2, bmoduleName.c_str()); + bool isEncrypted = provider.ConsumeBool(); + OH_Rdb_SetEncrypted(configV2, isEncrypted); + int securityLevel = provider.ConsumeIntegral(); + OH_Rdb_SetSecurityLevel(configV2, securityLevel); + int area = provider.ConsumeIntegral(); + OH_Rdb_SetArea(configV2, area); + int dbType = provider.ConsumeIntegral(); + OH_Rdb_SetDbType(configV2, dbType); + + Rdb_Tokenizer tokenizer = + static_cast(provider.ConsumeIntegralInRange(RDB_NONE_TOKENIZER, RDB_CUSTOM_TOKENIZER)); + bool isSupported = false; + OH_Rdb_IsTokenizerSupported(tokenizer, &isSupported); + { + Rdb_Tokenizer tokenizer = + static_cast(provider.ConsumeIntegralInRange(RDB_NONE_TOKENIZER, RDB_CUSTOM_TOKENIZER)); + OH_Rdb_SetTokenizer(configV2, tokenizer); + } + bool isPersistent = provider.ConsumeBool(); + OH_Rdb_SetPersistent(configV2, isPersistent); + int typeCount = 0; + OH_Rdb_GetSupportedDbType(&typeCount); + return configV2; +} + +OH_VObject *CreateOHVObject(FuzzedDataProvider &provider) +{ + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + if (valueObject == nullptr) { + return nullptr; + } + std::string value = provider.ConsumeRandomLengthString(); + valueObject->putText(valueObject, value.c_str()); + return valueObject; +} + +OH_VBucket *CreateOHVBucket(FuzzedDataProvider &provider) +{ + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + if (valueBucket == nullptr) { + return nullptr; + } + { + std::string key = provider.ConsumeRandomLengthString(); + int64_t value = provider.ConsumeIntegral(); + valueBucket->putInt64(valueBucket, key.c_str(), value); + } + { + std::string key = provider.ConsumeRandomLengthString(); + std::string value = provider.ConsumeRandomLengthString(); + valueBucket->putText(valueBucket, key.c_str(), value.c_str()); + } + { + std::string key = provider.ConsumeRandomLengthString(); + float value = provider.ConsumeFloatingPoint(); + valueBucket->putReal(valueBucket, key.c_str(), value); + } + { + std::string key = provider.ConsumeRandomLengthString(); + const int minBlobSize = 1; + const int maxBlobSize = 50; + size_t blobSize = provider.ConsumeIntegralInRange(minBlobSize, maxBlobSize); + std::vector blobData = provider.ConsumeBytes(blobSize); + valueBucket->putBlob(valueBucket, key.c_str(), blobData.data(), blobData.size()); + } + return valueBucket; +} + +void RelationalStoreCAPIFuzzTest(FuzzedDataProvider &provider) +{ + struct OH_Rdb_ConfigV2 *configV2 = CreateOHRdbConfigV2(provider); + if (configV2 == nullptr) { + return; + } + OH_VObject *valueObject = CreateOHVObject(provider); + if (valueObject == nullptr) { + return; + } + std::string table = provider.ConsumeRandomLengthString(); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return; + } + { + std::string value = provider.ConsumeRandomLengthString(); + predicates->equalTo(predicates, value.c_str(), valueObject); + } + + OH_VBucket *valueBucket = CreateOHVBucket(provider); + if (valueBucket == nullptr) { + return; + } + + int errCode = 0; + static OH_Rdb_Store *OHRdbStore = OH_Rdb_CreateOrOpen(configV2, &errCode); + { + table = provider.ConsumeRandomLengthString(); + OH_Rdb_Insert(OHRdbStore, table.c_str(), valueBucket); + } + OH_Data_VBuckets *list = OH_VBuckets_Create(); + OH_VBuckets_PutRow(list, valueBucket); + { + table = provider.ConsumeRandomLengthString(); + Rdb_ConflictResolution resolution = static_cast( + provider.ConsumeIntegralInRange(RDB_CONFLICT_NONE, RDB_CONFLICT_REPLACE)); + int64_t changes = 0; + OH_Rdb_BatchInsert(OHRdbStore, table.c_str(), list, resolution, &changes); + } + OH_Rdb_Update(OHRdbStore, valueBucket, predicates); + valueBucket->destroy(valueBucket); + predicates->destroy(predicates); + valueObject->destroy(valueObject); + OH_VBuckets_Destroy(list); + OH_Rdb_CloseStore(OHRdbStore); + OH_Rdb_DeleteStoreV2(configV2); + OH_Rdb_DestroyConfig(configV2); +} + +void RelationalConfigV2Capi20FuzzTest(FuzzedDataProvider &provider) +{ + static bool runEndFlag = false; + struct OH_Rdb_ConfigV2 *configV2 = CreateOHRdbConfigV2(provider); + if (configV2 == nullptr) { + return; + } + AppendApi20ConfigV2(provider, configV2); + OH_Rdb_DestroyConfig(configV2); + if (!runEndFlag) { + runEndFlag = true; + std::cout << "RelationalConfigV2Capi20FuzzTest end" << std::endl; + } +} + +OH_Rdb_ConfigV2* g_normalConfig = nullptr; +void MockHap(void) +{ + HapInfoParams info = { + .userID = 100, + .bundleName = "com.example.distributed", + .instIndex = 0, + .appIDDesc = "com.example.distributed" + }; + PermissionDef infoManagerTestPermDef = { + .permissionName = "ohos.permission.test", + .bundleName = "com.example.distributed", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "open the door", + .descriptionId = 1 + }; + PermissionStateFull infoManagerTestState = { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + }; + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { infoManagerTestPermDef }, + .permStateList = { infoManagerTestState } + }; + AccessTokenKit::AllocHapToken(info, policy); +} + +OH_Rdb_Store *GetFuzzerNormalStore() +{ + MockHap(); + // 0770 is permission + mkdir(RDB_TEST_PATH, 0770); + g_normalConfig = OH_Rdb_CreateConfig(); + OH_Rdb_SetDatabaseDir(g_normalConfig, RDB_TEST_PATH); + OH_Rdb_SetStoreName(g_normalConfig, "rdb_store_test.db"); + OH_Rdb_SetBundleName(g_normalConfig, "com.ohos.example.distributedndk"); + OH_Rdb_SetEncrypted(g_normalConfig, false); + OH_Rdb_SetSecurityLevel(g_normalConfig, OH_Rdb_SecurityLevel::S1); + OH_Rdb_SetArea(g_normalConfig, RDB_SECURITY_AREA_EL1); + int errCode = 0; + OH_Rdb_Store *store = OH_Rdb_CreateOrOpen(g_normalConfig, &errCode); + return store; +} + +void DeleteFuzzerNormalStroe(OH_Rdb_Store *store) +{ + if (store != nullptr) { + delete store; + } + OH_Rdb_DeleteStoreV2(g_normalConfig); + OH_Rdb_DestroyConfig(g_normalConfig); + g_normalConfig = nullptr; +} + + +void InitFuzzerNormalStore(OH_Rdb_Store *store) +{ + if (store == nullptr) { + return; + } + char createTableSql[] = "CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, data2 INTEGER, " + "data3 FLOAT, data4 BLOB, data5 TEXT);"; + OH_Rdb_Execute(store, createTableSql); +} + +OH_VBucket* GetFuzzerNormalValuesBucket() +{ + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putInt64(valueBucket, "id", 1); + valueBucket->putText(valueBucket, "data1", "zhangSan"); + // 12800 stub number + valueBucket->putInt64(valueBucket, "data2", 12800); + // 100.1 stub number + valueBucket->putReal(valueBucket, "data3", 100.1); + valueBucket->putText(valueBucket, "data5", "ABCDEFG"); + return valueBucket; +} + +void DeleteFuzzerNormalValuesBucket(OH_VBucket *valueBucket) +{ + if (valueBucket == nullptr) { + return; + } + valueBucket->destroy(valueBucket); +} + +OH_Predicates* GetCapi20Predicates(FuzzedDataProvider &provider, std::string table) +{ + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return nullptr; + } + std::string value = provider.ConsumeRandomLengthString(); + OH_VObject *valueObject = CreateOHVObject(provider); + if (valueObject == nullptr) { + predicates->destroy(predicates); + return nullptr; + } + predicates->equalTo(predicates, value.c_str(), valueObject); + valueObject->destroy(valueObject); + return predicates; +} + +void DeleteCapi20Predicates(OH_Predicates *predicates) +{ + if (predicates != nullptr) { + return; + } + predicates->destroy(predicates); +} + + +void RelationalStoreCapi20FuzzTest(FuzzedDataProvider &provider) +{ + static bool runEndFlag = false; + int64_t rowId; + std::string table = "test"; + Rdb_ConflictResolution resolution = static_cast( + provider.ConsumeIntegralInRange(RDB_CONFLICT_NONE, RDB_CONFLICT_REPLACE)); + + OH_Rdb_Store *store = GetFuzzerNormalStore(); + OH_VBucket *valueBucket = GetFuzzerNormalValuesBucket(); + OH_Predicates *predicates = GetCapi20Predicates(provider, table); + do { + if (store == nullptr || valueBucket == nullptr || predicates == nullptr) { + break; + } + OH_Rdb_InsertWithConflictResolution(store, table.c_str(), valueBucket, resolution, &rowId); + OH_Rdb_UpdateWithConflictResolution(store, valueBucket, predicates, resolution, &rowId); + if (!runEndFlag) { + runEndFlag = true; + std::cout << "RelationalStoreCapi20FuzzTest end" << std::endl; + } + } while (0); + + DeleteCapi20Predicates(predicates); + DeleteFuzzerNormalValuesBucket(valueBucket); + DeleteFuzzerNormalStroe(store); +} + +void RelationalStoreAttatchFuzzTest(FuzzedDataProvider &provider) +{ + static bool runEndFlag = false; + OH_Rdb_Store *store = GetFuzzerNormalStore(); + OH_Rdb_ConfigV2 *attachConfig = OH_Rdb_CreateConfig(); + int64_t waitTime = provider.ConsumeIntegral(); + do { + if (store == nullptr || attachConfig == nullptr) { + break; + } + OH_Rdb_SetDatabaseDir(attachConfig, RDB_TEST_PATH); + OH_Rdb_SetStoreName(attachConfig, "rdb_attach_store_test.db"); + OH_Rdb_SetBundleName(attachConfig, "com.ohos.example.distributedndk"); + OH_Rdb_SetEncrypted(attachConfig, false); + OH_Rdb_SetSecurityLevel(attachConfig, OH_Rdb_SecurityLevel::S1); + OH_Rdb_SetArea(attachConfig, RDB_SECURITY_AREA_EL1); + + size_t attachedNumber = 0; + OH_Rdb_Attach(store, attachConfig, "attach_test", waitTime, &attachedNumber); + OH_Rdb_Detach(store, "attach_test", waitTime, &attachedNumber); + if (!runEndFlag) { + runEndFlag = true; + std::cout << "RelationalStoreAttatchFuzzTest end" << std::endl; + } + } while (0); + + OH_Rdb_DestroyConfig(attachConfig); + DeleteFuzzerNormalStroe(store); +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + /* Run your code on data */ + FuzzedDataProvider provider(data, size); + + RelationalStoreCAPIFuzzTest(provider); + + // Test OH_Rdb_SetCryptoParam + RelationalConfigV2Capi20FuzzTest(provider); + + // Test OH_Rdb_InsertWithConflictResolution and OH_Rdb_UpdateWithConflictResolution + RelationalStoreCapi20FuzzTest(provider); + + // Test OH_Rdb_Attach and OH_Rdb_Detach + RelationalStoreAttatchFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/relationalstore_fuzzer.h b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/relationalstore_fuzzer.h new file mode 100644 index 00000000..b947b8d1 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstore_fuzzer/relationalstore_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 RELATIONALSTORE_FUZZER_H +#define RELATIONALSTORE_FUZZER_H + +#define FUZZ_PROJECT_NAME "relationalstore_fuzzer" + +#endif // RELATIONALSTORE_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/BUILD.gn new file mode 100644 index 00000000..da459f3c --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/BUILD.gn @@ -0,0 +1,69 @@ +# 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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("RelationalStoreCAPIFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = "${relational_store_base_path}/test/ndk/fuzztest/relationalstorecapi_fuzzer" + + sources = [ "relationalstorecapi_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":RelationalStoreCAPIFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/corpus/init new file mode 100644 index 00000000..65af8ee8 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/relationalstorecapi_fuzzer.cpp b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/relationalstorecapi_fuzzer.cpp new file mode 100644 index 00000000..a2917e02 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/relationalstorecapi_fuzzer.cpp @@ -0,0 +1,526 @@ +/* + * 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 "relationalstorecapi_fuzzer.h" + +#include + +#include + +#include "grd_api_manager.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +// Helper function to create an OH_Rdb_Config structure with random data +OH_Rdb_Config *CreateRandomConfig(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = new OH_Rdb_Config(); + config->selfSize = sizeof(OH_Rdb_Config); + config->dataBaseDir = strdup(provider.ConsumeRandomLengthString().c_str()); + config->storeName = strdup(provider.ConsumeRandomLengthString().c_str()); + config->bundleName = strdup(provider.ConsumeRandomLengthString().c_str()); + config->moduleName = strdup(provider.ConsumeRandomLengthString().c_str()); + config->isEncrypt = provider.ConsumeBool(); + config->securityLevel = provider.ConsumeIntegralInRange(S1, S4); + config->area = provider.ConsumeIntegralInRange(RDB_SECURITY_AREA_EL1, RDB_SECURITY_AREA_EL5); + return config; +} + +void ReleaseConfig(OH_Rdb_Config *config) +{ + if (config == nullptr) { + return; + } + if (config->dataBaseDir != nullptr) { + free(static_cast(const_cast(config->dataBaseDir))); + } + if (config->storeName != nullptr) { + free(static_cast(const_cast(config->storeName))); + } + if (config->bundleName != nullptr) { + free(static_cast(const_cast(config->bundleName))); + } + if (config->moduleName != nullptr) { + free(static_cast(const_cast(config->moduleName))); + } + delete config; + config = nullptr; +} + +// Helper function to create an OH_Rdb_ConfigV2 structure with random data +OH_Rdb_ConfigV2 *CreateRandomConfigV2(FuzzedDataProvider &provider) +{ + OH_Rdb_ConfigV2 *configV2 = OH_Rdb_CreateConfig(); + std::string databaseDir = provider.ConsumeRandomLengthString(); + OH_Rdb_SetDatabaseDir(configV2, databaseDir.c_str()); + std::string storeName = provider.ConsumeRandomLengthString(); + OH_Rdb_SetStoreName(configV2, storeName.c_str()); + std::string bundleName = provider.ConsumeRandomLengthString(); + OH_Rdb_SetBundleName(configV2, bundleName.c_str()); + std::string bmoduleName = provider.ConsumeRandomLengthString(); + OH_Rdb_SetModuleName(configV2, bmoduleName.c_str()); + bool isEncrypted = provider.ConsumeBool(); + OH_Rdb_SetEncrypted(configV2, isEncrypted); + int securityLevel = provider.ConsumeIntegral(); + OH_Rdb_SetSecurityLevel(configV2, securityLevel); + int area = provider.ConsumeIntegral(); + OH_Rdb_SetArea(configV2, area); + int dbType = provider.ConsumeIntegral(); + OH_Rdb_SetDbType(configV2, dbType); + + Rdb_Tokenizer tokenizer = + static_cast(provider.ConsumeIntegralInRange(RDB_NONE_TOKENIZER, RDB_CUSTOM_TOKENIZER)); + bool isSupported = false; + OH_Rdb_IsTokenizerSupported(tokenizer, &isSupported); + { + Rdb_Tokenizer tokenizer = + static_cast(provider.ConsumeIntegralInRange(RDB_NONE_TOKENIZER, RDB_CUSTOM_TOKENIZER)); + OH_Rdb_SetTokenizer(configV2, tokenizer); + } + bool isPersistent = provider.ConsumeBool(); + OH_Rdb_SetPersistent(configV2, isPersistent); + return configV2; +} + +// Helper function to create an OH_Predicates structure with random data +OH_Predicates *CreateRandomPredicates(FuzzedDataProvider &provider) +{ + std::string table = provider.ConsumeRandomLengthString(); + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table.c_str()); + if (predicates == nullptr) { + return nullptr; + } + + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + { + std::string value = provider.ConsumeRandomLengthString(); + valueObject->putText(valueObject, value.c_str()); + } + + { + std::string value = provider.ConsumeRandomLengthString(); + predicates->equalTo(predicates, value.c_str(), valueObject); + } + + return predicates; +} + +// Helper function to create an OH_VBucket structure with random data +OH_VBucket *CreateRandomVBucket(FuzzedDataProvider &provider) +{ + OH_VBucket *vBucket = OH_Rdb_CreateValuesBucket(); + if (vBucket == nullptr) { + return nullptr; + } + const int minLen = 1; + const int maxLen = 50; + size_t len = provider.ConsumeIntegralInRange(minLen, maxLen); + for (size_t i = 0; i < len; i++) { + std::string column = provider.ConsumeRandomLengthString(); + int64_t value = provider.ConsumeIntegral(); + vBucket->putInt64(vBucket, column.c_str(), value); + } + return vBucket; +} + +// Helper function to create an OH_Rdb_TransOptions structure with random data +OH_RDB_TransOptions *CreateRandomTransOptions(FuzzedDataProvider &provider) +{ + OH_RDB_TransOptions *options = OH_RdbTrans_CreateOptions(); + OH_RDB_TransType type = + static_cast(provider.ConsumeIntegralInRange(RDB_TRANS_DEFERRED, RDB_TRANS_BUTT)); + OH_RdbTransOption_SetType(options, type); + return options; +} + +void OHRdbCreateOrOpenFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + // Test OH_Rdb_CloseStore + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbCreateOrOpenV2FuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_ConfigV2 *config = CreateRandomConfigV2(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_CreateOrOpen(config, &errCode); + if (store != nullptr) { + // Test OH_Rdb_CloseStore + OH_Rdb_CloseStore(store); + } +} + +void OHRdbSetVersionFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + int version = provider.ConsumeIntegral(); + OH_Rdb_SetVersion(store, version); + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbQueryLockedRowFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + OH_Predicates *predicates = CreateRandomPredicates(provider); + if (predicates != nullptr) { + const int minColumnCount = 1; + const int maxColumnCount = 50; + size_t columnCount = provider.ConsumeIntegralInRange(minColumnCount, maxColumnCount); + const char **columnNames = new const char *[columnCount]; + std::vector> columnStorage(columnCount); + + for (size_t i = 0; i < columnCount; ++i) { + std::string columnName = provider.ConsumeRandomLengthString(); + columnStorage[i] = std::make_unique(columnName.size() + 1); + std::copy(columnName.begin(), columnName.end(), columnStorage[i].get()); + columnStorage[i][columnName.size()] = '\0'; + columnNames[i] = columnStorage[i].get(); + } + OH_Cursor *cursor = OH_Rdb_QueryLockedRow(store, predicates, columnNames, columnCount); + if (cursor != nullptr) { + cursor->destroy(cursor); + } + predicates->destroy(predicates); + delete[] columnNames; + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbUnlockRowFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + OH_Predicates *predicates = CreateRandomPredicates(provider); + if (predicates != nullptr) { + OH_Rdb_UnlockRow(store, predicates); + predicates->destroy(predicates); + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbExecuteQueryV2FuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + std::string sql = provider.ConsumeRandomLengthString(); + OH_Data_Values *args = nullptr; // Simplified for fuzzing + OH_Cursor *cursor = OH_Rdb_ExecuteQueryV2(store, sql.c_str(), args); + if (cursor != nullptr) { + cursor->destroy(cursor); + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbBatchInsertFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + std::string table = provider.ConsumeRandomLengthString(); + const int minRowCount = 1; + const int maxRowCount = 5; + size_t rowCount = provider.ConsumeIntegralInRange(minRowCount, maxRowCount); + OH_Data_VBuckets *list = OH_VBuckets_Create(); + for (size_t i = 0; i < rowCount; i++) { + OH_VBuckets_PutRow(list, CreateRandomVBucket(provider)); + } + int64_t changes; + Rdb_ConflictResolution resolution = static_cast( + provider.ConsumeIntegralInRange(RDB_CONFLICT_NONE, RDB_CONFLICT_REPLACE)); + OH_Rdb_BatchInsert(store, table.c_str(), list, resolution, &changes); + OH_VBuckets_Destroy(list); + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbUpdateFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + OH_VBucket *valuesBucket = CreateRandomVBucket(provider); + OH_Predicates *predicates = CreateRandomPredicates(provider); + if (valuesBucket != nullptr && predicates != nullptr) { + OH_Rdb_Update(store, valuesBucket, predicates); + predicates->destroy(predicates); + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbLockRowFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + OH_Predicates *predicates = CreateRandomPredicates(provider); + if (predicates != nullptr) { + OH_Rdb_LockRow(store, predicates); + predicates->destroy(predicates); + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbCreateTransactionFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + OH_RDB_TransOptions *options = CreateRandomTransOptions(provider); + OH_Rdb_Transaction *trans = nullptr; + OH_Rdb_CreateTransaction(store, options, &trans); + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbCommitByTrxIdFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + int64_t trxId = provider.ConsumeIntegral(); + OH_Rdb_CommitByTrxId(store, trxId); + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbBackupFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + std::string databasePath = provider.ConsumeRandomLengthString(); + OH_Rdb_Backup(store, databasePath.c_str()); + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbUnsubscribeAutoSyncProgressFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + Rdb_ProgressObserver *observer = nullptr; // Simplified for fuzzing + OH_Rdb_UnsubscribeAutoSyncProgress(store, observer); + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbUnsubscribeFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + Rdb_SubscribeType type = static_cast( + provider.ConsumeIntegralInRange(RDB_SUBSCRIBE_TYPE_CLOUD, RDB_SUBSCRIBE_TYPE_LOCAL_DETAILS)); + Rdb_DataObserver *observer = nullptr; // Simplified for fuzzing + OH_Rdb_Unsubscribe(store, type, observer); + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbExecuteV2FuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + std::string sql = provider.ConsumeRandomLengthString(100); + OH_Data_Values *values = OH_Values_Create(); + int value = provider.ConsumeIntegral(); + OH_Values_PutInt(values, value); + OH_Data_Value *result = nullptr; + OH_Rdb_ExecuteV2(store, sql.c_str(), values, &result); + if (values != nullptr) { + OH_Values_Destroy(values); + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbFindModifyTimeFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + std::string tableName = provider.ConsumeRandomLengthString(50); + std::string columnName = provider.ConsumeRandomLengthString(50); + OH_VObject *values = OH_Rdb_CreateValueObject(); + if (values != nullptr) { + OH_Cursor *cursor = OH_Rdb_FindModifyTime(store, tableName.c_str(), columnName.c_str(), values); + if (cursor != nullptr) { + cursor->destroy(cursor); + } + values->destroy(values); + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbGetFloatVectorCountFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + std::string sql = provider.ConsumeRandomLengthString(); + OH_Data_Values *args = nullptr; // Simplified for fuzzing + OH_Cursor *cursor = OH_Rdb_ExecuteQueryV2(store, sql.c_str(), args); + if (cursor != nullptr) { + int columnIndex = provider.ConsumeIntegral(); + size_t length = provider.ConsumeIntegral(); + OH_Cursor_GetFloatVectorCount(cursor, columnIndex, &length); + cursor->destroy(cursor); + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void OHRdbGetFloatVectorFuzzTest(FuzzedDataProvider &provider) +{ + OH_Rdb_Config *config = CreateRandomConfig(provider); + int errCode; + OH_Rdb_Store *store = OH_Rdb_GetOrOpen(config, &errCode); + if (store != nullptr) { + std::string sql = provider.ConsumeRandomLengthString(); + OH_Data_Values *args = nullptr; // Simplified for fuzzing + OH_Cursor *cursor = OH_Rdb_ExecuteQueryV2(store, sql.c_str(), args); + if (cursor != nullptr) { + int columnIndex = provider.ConsumeIntegral(); + float *val = new float(); + size_t inLen = provider.ConsumeIntegral(); + size_t outLen = provider.ConsumeIntegral(); + OH_Cursor_GetFloatVector(cursor, columnIndex, val, inLen, &outLen); + delete val; + cursor->destroy(cursor); + } + OH_Rdb_CloseStore(store); + } + ReleaseConfig(config); +} + +void RelationalStoreFuzzTest(FuzzedDataProvider &provider) +{ + // Test OH_Rdb_CreateOrOpen + OHRdbCreateOrOpenFuzzTest(provider); + + // Test OH_Rdb_CreateOrOpenV2 + OHRdbCreateOrOpenV2FuzzTest(provider); + + // Test OH_Rdb_SetVersion + OHRdbSetVersionFuzzTest(provider); + + // Test OH_Rdb_QueryLockedRow + OHRdbQueryLockedRowFuzzTest(provider); + + // Test OH_Rdb_UnlockRow + OHRdbUnlockRowFuzzTest(provider); + + // Test OH_Rdb_ExecuteQueryV2 + OHRdbExecuteQueryV2FuzzTest(provider); + + // Test OH_Rdb_BatchInsert + OHRdbBatchInsertFuzzTest(provider); + + // Test OH_Rdb_Update + OHRdbUpdateFuzzTest(provider); + + // Test OH_Rdb_LockRow + OHRdbLockRowFuzzTest(provider); + + // Test OH_Rdb_CreateTransaction + OHRdbCreateTransactionFuzzTest(provider); + + // Test OH_Rdb_CommitByTrxId + OHRdbCommitByTrxIdFuzzTest(provider); + + // Test OH_Rdb_Backup + OHRdbBackupFuzzTest(provider); + + // Test OH_Rdb_UnsubscribeAutoSyncProgress + OHRdbUnsubscribeAutoSyncProgressFuzzTest(provider); + + // Test OH_Rdb_Unsubscribe + OHRdbUnsubscribeFuzzTest(provider); + + // Test OH_Rdb_ExecuteV2 + OHRdbExecuteV2FuzzTest(provider); + + // Test OH_Rdb_FindModifyTime + OHRdbFindModifyTimeFuzzTest(provider); + + // Test OH_Cursor_GetFloatVectorCount + OHRdbGetFloatVectorCountFuzzTest(provider); + + // Test OH_Cursor_GetFloatVector + OHRdbGetFloatVectorFuzzTest(provider); +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + FuzzedDataProvider provider(data, size); + RelationalStoreFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/relationalstorecapi_fuzzer.h b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/relationalstorecapi_fuzzer.h new file mode 100644 index 00000000..2703e181 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/relationalstorecapi_fuzzer/relationalstorecapi_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 RELATIONALSTORECAPI_FUZZER_H +#define RELATIONALSTORECAPI_FUZZER_H + +#define FUZZ_PROJECT_NAME "relationalstorecapi_fuzzer" + +#endif // RELATIONALSTORECAPI_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/BUILD.gn new file mode 100644 index 00000000..fb8046cc --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("ValueBucketFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/ndk/fuzztest/valuebucket_fuzzer" + + sources = [ "valuebucket_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":ValueBucketFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/corpus/init new file mode 100644 index 00000000..65af8ee8 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/valuebucket_fuzzer.cpp b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/valuebucket_fuzzer.cpp new file mode 100644 index 00000000..742a9c43 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/valuebucket_fuzzer.cpp @@ -0,0 +1,177 @@ +/* + * 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 "valuebucket_fuzzer.h" + +#include + +#include "grd_api_manager.h" +#include "oh_value_object.h" +#include "oh_values_bucket.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + + +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +void putTextFuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + std::string value = provider.ConsumeRandomLengthString(); + valueBucket->putText(valueBucket, field.c_str(), value.c_str()); +} + +void putInt64FuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + int64_t value = provider.ConsumeIntegral(); + valueBucket->putInt64(valueBucket, field.c_str(), value); +} + +void putRealFuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + double value = static_cast(provider.ConsumeFloatingPoint()); + valueBucket->putReal(valueBucket, field.c_str(), value); +} + +void putBlobFuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + const int minBlobSize = 1; + const int maxBlobSize = 50; + size_t blobSize = provider.ConsumeIntegralInRange(minBlobSize, maxBlobSize); + std::vector value = provider.ConsumeBytes(blobSize); + valueBucket->putBlob(valueBucket, field.c_str(), value.data(), value.size()); +} + +void putNullFuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + valueBucket->putNull(valueBucket, field.c_str()); +} + +void putAssetFuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + Data_Asset *asset = OH_Data_Asset_CreateOne(); + if (asset == nullptr) { + return; + } + int64_t value = provider.ConsumeIntegral(); + OH_Data_Asset_SetCreateTime(asset, value); + OH_VBucket_PutAsset(valueBucket, field.c_str(), asset); + OH_Data_Asset_DestroyOne(asset); // Destroy the asset +} + +void putAssetsFuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + const int minCount = 1; + const int maxCount = 50; + size_t count = provider.ConsumeIntegralInRange(minCount, maxCount); + Data_Asset **assets = OH_Data_Asset_CreateMultiple(count); + if (assets == nullptr) { + return; + } + for (size_t i = 0; i < count; i++) { + int64_t value = provider.ConsumeIntegral(); + OH_Data_Asset_SetCreateTime(assets[i], value); + } + OH_VBucket_PutAssets(valueBucket, field.c_str(), assets, count); + OH_Data_Asset_DestroyMultiple(assets, count); // Free the array of pointers +} + +void putFloatVectorFuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + const int minLen = 1; + const int maxLen = 50; + size_t len = provider.ConsumeIntegralInRange(minLen, maxLen); + std::vector vec(len); + for (size_t i = 0; i < len; i++) { + vec[i] = provider.ConsumeFloatingPoint(); + } + OH_VBucket_PutFloatVector(valueBucket, field.c_str(), vec.data(), len); +} + +void putUnlimitedIntFuzzTest(FuzzedDataProvider &provider, OH_VBucket *valueBucket) +{ + std::string field = provider.ConsumeRandomLengthString(); + const int minSign = 0; + const int maxSign = 1; + int sign = provider.ConsumeIntegralInRange(minSign, maxSign); + const int minLen = 1; + const int maxLen = 50; + size_t len = provider.ConsumeIntegralInRange(minLen, maxLen); + std::vector trueForm(len); + for (size_t i = 0; i < len; i++) { + trueForm[i] = provider.ConsumeIntegral(); + } + OH_VBucket_PutUnlimitedInt(valueBucket, field.c_str(), sign, trueForm.data(), len); +} + +void ValueBucketFuzzTest(FuzzedDataProvider &provider) +{ + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + if (valueBucket == nullptr) { + return; + } + + // Test putText + putTextFuzzTest(provider, valueBucket); + + // Test putInt64 + putInt64FuzzTest(provider, valueBucket); + + // Test putReal + putRealFuzzTest(provider, valueBucket); + + // Test putBlob + putBlobFuzzTest(provider, valueBucket); + + // Test putNull + putNullFuzzTest(provider, valueBucket); + + // Test putAsset + putAssetFuzzTest(provider, valueBucket); + + // Test putAssets + putAssetsFuzzTest(provider, valueBucket); + + // Test putFloatVector + putFloatVectorFuzzTest(provider, valueBucket); + + // Test putUnlimitedInt + putUnlimitedIntFuzzTest(provider, valueBucket); + + // Test clear + valueBucket->clear(valueBucket); + + // Destroy valueBucket + valueBucket->destroy(valueBucket); +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + ValueBucketFuzzTest(provider); + return 0; +} \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/valuebucket_fuzzer.h b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/valuebucket_fuzzer.h new file mode 100644 index 00000000..6e6b24df --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valuebucket_fuzzer/valuebucket_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 VALUEBUCKET_FUZZER_H +#define VALUEBUCKET_FUZZER_H + +#define FUZZ_PROJECT_NAME "valuebucket_fuzzer" + +#endif // VALUEBUCKET_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/valueobject_fuzzer/BUILD.gn b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/BUILD.gn new file mode 100644 index 00000000..3cae1a5f --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/BUILD.gn @@ -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. + +#####################hydra-fuzz################### +import("//build/config/features.gni") +import("//build/test.gni") +import("//foundation/distributeddatamgr/relational_store/relational_store.gni") + +##############################fuzztest########################################## +ohos_fuzztest("ValueObjectFuzzTest") { + module_out_path = "relational_store/relational_store" + + include_dirs = [ + "${relational_store_base_path}/interfaces/ndk/include", + "${relational_store_innerapi_path}/rdb/include", + "${relational_store_innerapi_path}/appdatafwk/include", + "${relational_store_base_path}/interfaces/ndk/src", + "${relational_store_common_path}/include", + "${relational_store_native_path}/rdb/include", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + fuzz_config_file = + "${relational_store_base_path}/test/ndk/fuzztest/valueobject_fuzzer" + + sources = [ "valueobject_fuzzer.cpp" ] + + deps = [ + "${relational_store_base_path}/interfaces/ndk:native_rdb_ndk", + "${relational_store_innerapi_path}/rdb:native_rdb", + ] + + external_deps = [ + "ability_base:zuri", + "ability_runtime:dataobs_manager", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddb", + "kv_store:distributeddb_client", + "sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":ValueObjectFuzzTest", + ] +} +############################################################################### diff --git a/relational_store/test/ndk/fuzztest/valueobject_fuzzer/corpus/init b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/corpus/init new file mode 100644 index 00000000..65af8ee8 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# 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. + +FUZZ \ No newline at end of file diff --git a/relational_store/test/ndk/fuzztest/valueobject_fuzzer/project.xml b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/project.xml new file mode 100644 index 00000000..66e1dcac --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/relational_store/test/ndk/fuzztest/valueobject_fuzzer/valueobject_fuzzer.cpp b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/valueobject_fuzzer.cpp new file mode 100644 index 00000000..1a66d8e2 --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/valueobject_fuzzer.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 "valueobject_fuzzer.h" + +#include + +#include "grd_api_manager.h" +#include "oh_value_object.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" + + +using namespace OHOS::NativeRdb; +using namespace OHOS::RdbNdk; + +void ValueObjectFuzzTest(FuzzedDataProvider &provider) +{ + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + if (valueObject == nullptr) { + return; + } + + // Test putText + { + std::string value = provider.ConsumeRandomLengthString(); + valueObject->putText(valueObject, value.c_str()); + } + + // Test putInt64 + { + const int minArraySize = 1; + const int maxArraySize = 50; + size_t arraySize = provider.ConsumeIntegralInRange(minArraySize, maxArraySize); + std::vector array(arraySize); + for (size_t i = 0; i < arraySize; i++) { + array[i] = provider.ConsumeIntegral(); + } + valueObject->putInt64(valueObject, array.data(), array.size()); + } + + // Test putDouble + { + const int minArraySize = 1; + const int maxArraySize = 50; + size_t arraySize = provider.ConsumeIntegralInRange(minArraySize, maxArraySize); + std::vector array(arraySize); + for (size_t i = 0; i < arraySize; i++) { + array[i] = static_cast(provider.ConsumeFloatingPoint()); + } + valueObject->putDouble(valueObject, array.data(), array.size()); + } + + // Test putTexts + { + const int minArraySize = 1; + const int maxArraySize = 50; + size_t arraySize = provider.ConsumeIntegralInRange(minArraySize, maxArraySize); + + // Use std::vector to manage memory + std::vector> stringStorage(arraySize); + const char **array = new const char *[arraySize]; + + for (size_t i = 0; i < arraySize; i++) { + std::string value = provider.ConsumeRandomLengthString(); + + // Allocate memory for each string + stringStorage[i] = std::make_unique(value.size() + 1); + std::copy(value.begin(), value.end(), stringStorage[i].get()); + stringStorage[i][value.size()] = '\0'; // Ensure the string is null-terminated + + // Assign the pointer to array + array[i] = stringStorage[i].get(); + } + + // Use array + valueObject->putTexts(valueObject, array, arraySize); + + // Free the array pointer + delete[] array; + } + + // Destroy valueObject + valueObject->destroy(valueObject); +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + // Run your code on data + FuzzedDataProvider provider(data, size); + ValueObjectFuzzTest(provider); + return 0; +} diff --git a/relational_store/test/ndk/fuzztest/valueobject_fuzzer/valueobject_fuzzer.h b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/valueobject_fuzzer.h new file mode 100644 index 00000000..554cdecb --- /dev/null +++ b/relational_store/test/ndk/fuzztest/valueobject_fuzzer/valueobject_fuzzer.h @@ -0,0 +1,21 @@ +/* + * 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 VALUEOBJECT_FUZZER_H +#define VALUEOBJECT_FUZZER_H + +#define FUZZ_PROJECT_NAME "valueobject_fuzzer" + +#endif // VALUEOBJECT_FUZZER_H \ No newline at end of file diff --git a/relational_store/test/ndk/unittest/rdb_crypto_param_test.cpp b/relational_store/test/ndk/unittest/rdb_crypto_param_test.cpp new file mode 100644 index 00000000..a2501fe2 --- /dev/null +++ b/relational_store/test/ndk/unittest/rdb_crypto_param_test.cpp @@ -0,0 +1,216 @@ +/* + * 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 "relational_store_error_code.h" +#include "common.h" +#include "oh_rdb_crypto_param.h" +#include "oh_data_define.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; + +class RdbCryptoParamTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static void InitRdbConfig() + { + } +}; + +void RdbCryptoParamTest::SetUpTestCase(void) +{ +} + +void RdbCryptoParamTest::TearDownTestCase(void) +{ +} + +void RdbCryptoParamTest::SetUp(void) +{ +} + +void RdbCryptoParamTest::TearDown(void) +{ +} + +/** + * @tc.name: RDB_Crypto_Param_test_001 + * @tc.desc: Normal testCase of OH_Rdb_CreateCryptoParam and OH_Rdb_DestroyCryptoParam. + * @tc.type: FUNC + */ +HWTEST_F(RdbCryptoParamTest, RDB_Crypto_Param_test_001, TestSize.Level1) +{ + auto obj = OH_Rdb_CreateCryptoParam(); + EXPECT_NE(obj, NULL); + + auto ret = OH_Rdb_DestroyCryptoParam(nullptr); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Rdb_CryptoParam wrong; + wrong.id = 1; + ret = OH_Rdb_DestroyCryptoParam(&wrong); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_DestroyCryptoParam(obj); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Crypto_Param_test_002 + * @tc.desc: Normal testCase of OH_Crypto_SetEncryptionKey. + * @tc.type: FUNC + */ +HWTEST_F(RdbCryptoParamTest, RDB_Crypto_Param_test_002, TestSize.Level1) +{ + OH_Rdb_CryptoParam *obj = OH_Rdb_CreateCryptoParam(); + EXPECT_NE(obj, NULL); + + const uint8_t key[] = "12345678"; + auto ret = OH_Crypto_SetEncryptionKey(nullptr, key, sizeof(key) - 1); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Crypto_SetEncryptionKey(obj, key, sizeof(key) - 1); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(obj->cryptoParam.encryptKey_.size(), sizeof(key) - 1); + ret = OH_Rdb_DestroyCryptoParam(obj); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Crypto_Param_test_003 + * @tc.desc: Normal testCase of OH_Crypto_SetIteration. + * @tc.type: FUNC + */ +HWTEST_F(RdbCryptoParamTest, RDB_Crypto_Param_test_003, TestSize.Level1) +{ + OH_Rdb_CryptoParam *obj = OH_Rdb_CreateCryptoParam(); + EXPECT_NE(obj, NULL); + + // -1 is iteration times + auto ret = OH_Crypto_SetIteration(obj, -1); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + // 1000 is iteration times + ret = OH_Crypto_SetIteration(obj, 1000); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(obj->cryptoParam.iterNum, 1000); + ret = OH_Rdb_DestroyCryptoParam(obj); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Crypto_Param_test_004 + * @tc.desc: Normal testCase of OH_Crypto_SetEncryptionAlgo. + * @tc.type: FUNC + */ +HWTEST_F(RdbCryptoParamTest, RDB_Crypto_Param_test_004, TestSize.Level1) +{ + OH_Rdb_CryptoParam *obj = OH_Rdb_CreateCryptoParam(); + EXPECT_NE(obj, NULL); + + // 2 is invalid encryption + auto ret = OH_Crypto_SetEncryptionAlgo(obj, 2); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Crypto_SetEncryptionAlgo(obj, RDB_AES_256_CBC); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(obj->cryptoParam.encryptAlgo, RDB_AES_256_CBC); + ret = OH_Rdb_DestroyCryptoParam(obj); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Crypto_Param_test_005 + * @tc.desc: Normal testCase of OH_Crypto_SetHmacAlgo. + * @tc.type: FUNC + */ +HWTEST_F(RdbCryptoParamTest, RDB_Crypto_Param_test_005, TestSize.Level1) +{ + OH_Rdb_CryptoParam *obj = OH_Rdb_CreateCryptoParam(); + EXPECT_NE(obj, NULL); + + // 3 is invalid hdc + auto ret = OH_Crypto_SetHmacAlgo(obj, 3); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Crypto_SetHmacAlgo(obj, RDB_HMAC_SHA512); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(obj->cryptoParam.hmacAlgo, RDB_HMAC_SHA512); + + ret = OH_Rdb_DestroyCryptoParam(obj); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Crypto_Param_test_006 + * @tc.desc: Normal testCase of OH_Crypto_SetKdfAlgo. + * @tc.type: FUNC + */ +HWTEST_F(RdbCryptoParamTest, RDB_Crypto_Param_test_006, TestSize.Level1) +{ + OH_Rdb_CryptoParam *obj = OH_Rdb_CreateCryptoParam(); + EXPECT_NE(obj, NULL); + + // 3 is invalid kdf + auto ret = OH_Crypto_SetKdfAlgo(obj, 3); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Crypto_SetKdfAlgo(obj, RDB_KDF_SHA512); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(obj->cryptoParam.kdfAlgo, RDB_KDF_SHA512); + ret = OH_Rdb_DestroyCryptoParam(obj); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Crypto_Param_test_007 + * @tc.desc: Normal testCase of OH_Crypto_SetCryptoPageSize. + * @tc.type: FUNC + */ +HWTEST_F(RdbCryptoParamTest, RDB_Crypto_Param_test_007, TestSize.Level1) +{ + OH_Rdb_CryptoParam *obj = OH_Rdb_CreateCryptoParam(); + EXPECT_NE(obj, NULL); + + int64_t pageSize = -1; + auto ret = OH_Crypto_SetCryptoPageSize(obj, pageSize); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + pageSize = 1023; + ret = OH_Crypto_SetCryptoPageSize(obj, pageSize); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + pageSize = 0; + ret = OH_Crypto_SetCryptoPageSize(obj, pageSize); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + pageSize = 1024; + ret = OH_Crypto_SetCryptoPageSize(obj, pageSize); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(obj->cryptoParam.cryptoPageSize, pageSize); + + pageSize = 4096; + ret = OH_Crypto_SetCryptoPageSize(obj, pageSize); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(obj->cryptoParam.cryptoPageSize, pageSize); + ret = OH_Rdb_DestroyCryptoParam(obj); + EXPECT_EQ(ret, RDB_OK); +} \ No newline at end of file diff --git a/relational_store/test/ndk/unittest/rdb_cursor_test.cpp b/relational_store/test/ndk/unittest/rdb_cursor_test.cpp index 1840d11a..b68a4e12 100644 --- a/relational_store/test/ndk/unittest/rdb_cursor_test.cpp +++ b/relational_store/test/ndk/unittest/rdb_cursor_test.cpp @@ -328,8 +328,8 @@ HWTEST_F(RdbNativeCursorTest, RDB_Native_cursor_test_004, TestSize.Level1) size_t size = 0; cursor->getSize(cursor, 0, &size); - char data1Value[size + 1]; - cursor->getText(cursor, 0, data1Value, size + 1); + char data1Value[size]; + cursor->getText(cursor, 0, data1Value, size); EXPECT_EQ(strcmp(data1Value, "zhangSan"), 0); int64_t data2Value; @@ -349,9 +349,9 @@ HWTEST_F(RdbNativeCursorTest, RDB_Native_cursor_test_004, TestSize.Level1) cursor->goToNextRow(cursor); cursor->getSize(cursor, 0, &size); - char data1Value_1[size + 1]; - cursor->getText(cursor, 0, data1Value_1, size + 1); - EXPECT_EQ(strcmp(data1Value_1, "liSi"), 0); + char data1Value1[size]; + cursor->getText(cursor, 0, data1Value1, size); + EXPECT_EQ(strcmp(data1Value1, "liSi"), 0); cursor->getInt64(cursor, 1, &data2Value); EXPECT_EQ(data2Value, 13800); diff --git a/relational_store/test/ndk/unittest/rdb_performance_test.cpp b/relational_store/test/ndk/unittest/rdb_performance_test.cpp new file mode 100644 index 00000000..3fecf3bc --- /dev/null +++ b/relational_store/test/ndk/unittest/rdb_performance_test.cpp @@ -0,0 +1,376 @@ +/* + * 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 "accesstoken_kit.h" +#include "common.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" +#include "token_setproc.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::RdbNdk; + +static constexpr int64_t BASE_COUNT = 1000; // loop times +static constexpr int64_t RDB_INSERT_BASELINE = 3000; +static constexpr int64_t RDB_UPDATE_BASELINE = 3000; +static constexpr int64_t TRANS_INSERT_BASELINE = 3000; +static constexpr int64_t TRANS_UPDATE_BASELINE = 3000; +static constexpr int64_t RDB_ATTACH_BASELINE = 6000; // attach and detach two interfaces together. + +class RdbPerformanceTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static void InitRdbConfig() + { + config_.dataBaseDir = RDB_TEST_PATH; + config_.storeName = "rdb_store_test.db"; + config_.bundleName = "com.ohos.example.distributedndk"; + config_.moduleName = ""; + config_.securityLevel = OH_Rdb_SecurityLevel::S1; + config_.isEncrypt = false; + config_.selfSize = sizeof(OH_Rdb_Config); + config_.area = RDB_SECURITY_AREA_EL1; + } + static OH_Rdb_Config config_; + static void MockHap(void); +}; + +static OH_Rdb_Store *g_performanStore = nullptr; +static OH_RDB_TransOptions *g_options = nullptr; +OH_Rdb_Config RdbPerformanceTest::config_ = { 0 }; + +void RdbPerformanceTest::MockHap(void) +{ + HapInfoParams info = { + .userID = 100, + .bundleName = "com.example.distributed", + .instIndex = 0, + .appIDDesc = "com.example.distributed" + }; + PermissionDef infoManagerTestPermDef = { + .permissionName = "ohos.permission.test", + .bundleName = "com.example.distributed", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "open the door", + .descriptionId = 1 + }; + PermissionStateFull infoManagerTestState = { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + }; + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { infoManagerTestPermDef }, + .permStateList = { infoManagerTestState } + }; + AccessTokenKit::AllocHapToken(info, policy); +} + +void RdbPerformanceTest::SetUpTestCase(void) +{ + MockHap(); + InitRdbConfig(); + // 0770 is permission + mkdir(config_.dataBaseDir, 0770); + int errCode = 0; + g_performanStore = OH_Rdb_GetOrOpen(&config_, &errCode); + EXPECT_NE(g_performanStore, NULL); + + g_options = OH_RdbTrans_CreateOptions(); + EXPECT_NE(g_options, nullptr); + int ret = OH_RdbTransOption_SetType(g_options, RDB_TRANS_BUTT); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_RdbTransOption_SetType(g_options, RDB_TRANS_DEFERRED); + EXPECT_EQ(ret, RDB_OK); +} + +void RdbPerformanceTest::TearDownTestCase(void) +{ + int errCode = OH_Rdb_CloseStore(g_performanStore); + EXPECT_EQ(errCode, 0); + errCode = OH_Rdb_DeleteStore(&config_); + EXPECT_EQ(errCode, 0); + + OH_RdbTrans_DestroyOptions(g_options); + g_options = nullptr; +} + +void RdbPerformanceTest::SetUp(void) +{ + char createTableSql[] = "CREATE TABLE store_test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, data2 INTEGER, " + "data3 FLOAT, data4 BLOB, data5 TEXT);"; + int errCode = OH_Rdb_Execute(g_performanStore, createTableSql); + EXPECT_EQ(errCode, 0); + + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putInt64(valueBucket, "id", 1); + valueBucket->putText(valueBucket, "data1", "zhangSan"); + // 12800 test value. + valueBucket->putInt64(valueBucket, "data2", 12800); + // 100.1 test value. + valueBucket->putReal(valueBucket, "data3", 100.1); + uint8_t arr[] = { 1, 2, 3, 4, 5 }; + int len = sizeof(arr) / sizeof(arr[0]); + valueBucket->putBlob(valueBucket, "data4", arr, len); + valueBucket->putText(valueBucket, "data5", "ABCDEFG"); + errCode = OH_Rdb_Insert(g_performanStore, "store_test", valueBucket); + EXPECT_EQ(errCode, 1); + + char querySql[] = "SELECT * FROM store_test"; + OH_Cursor *cursor = OH_Rdb_ExecuteQuery(g_performanStore, querySql); + + int rowCount = 0; + cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(rowCount, 1); + cursor->destroy(cursor); + valueBucket->destroy(valueBucket); +} + +void RdbPerformanceTest::TearDown(void) +{ + char dropTableSql[] = "DROP TABLE IF EXISTS store_test"; + int errCode = OH_Rdb_Execute(g_performanStore, dropTableSql); + EXPECT_EQ(errCode, 0); +} + +/* * + * @tc.name: Trans_InsertWithConflictResolution_test_001 + * @tc.desc: test OH_RdbTrans_InsertWithConflictResolution interface performance. + * @tc.type: FUNC + */ +HWTEST_F(RdbPerformanceTest, Trans_InsertWithConflictResolution_test_001, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + const char *table = "store_test"; + int ret = OH_Rdb_CreateTransaction(g_performanStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putText(valueBucket, "data1", "test_name4"); + // init is data2 is 14800 + valueBucket->putInt64(valueBucket, "data2", 14800); + // init is data2 is 300.1 + valueBucket->putReal(valueBucket, "data3", 300.1); + valueBucket->putText(valueBucket, "data5", "ABCDEFGHI"); + int64_t rowId = -1; + + auto now = std::chrono::system_clock::now().time_since_epoch(); + int64_t start = std::chrono::duration_cast(now).count(); + + for (int i = 0; i < BASE_COUNT; i++) { + ret = OH_RdbTrans_InsertWithConflictResolution(trans, table, valueBucket, RDB_CONFLICT_ROLLBACK, &rowId); + EXPECT_EQ(ret, RDB_OK); + } + + now = std::chrono::system_clock::now().time_since_epoch(); + int64_t summaryTime = (std::chrono::duration_cast(now).count() - start); + int64_t averageTime = summaryTime / BASE_COUNT; + + EXPECT_LE(averageTime, RDB_INSERT_BASELINE); + + valueBucket->destroy(valueBucket); + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/* * + * @tc.name: Trans_UpdateWithConflictResolution_test_002 + * @tc.desc: test OH_RdbTrans_UpdateWithConflictResolution interface performance. + * @tc.type: FUNC + */ +HWTEST_F(RdbPerformanceTest, Trans_UpdateWithConflictResolution_test_002, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + const char *table = "store_test"; + int ret = OH_Rdb_CreateTransaction(g_performanStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + // new row + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putText(valueBucket, "data1", "liSi"); + // init data2 value is 13800 + valueBucket->putInt64(valueBucket, "data2", 13800); + // init data3 value is 200.1 + valueBucket->putReal(valueBucket, "data3", 200.1); + valueBucket->putNull(valueBucket, "data5"); + + // create predicates + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table); + // create match data + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + const char *data1Value = "zhangSan"; + valueObject->putText(valueObject, data1Value); + predicates->equalTo(predicates, "data1", valueObject); + + // update + int64_t changes = -1; + auto now = std::chrono::system_clock::now().time_since_epoch(); + int64_t start = std::chrono::duration_cast(now).count(); + + for (int i = 0; i < BASE_COUNT; i++) { + ret = OH_RdbTrans_UpdateWithConflictResolution(trans, valueBucket, predicates, RDB_CONFLICT_REPLACE, &changes); + EXPECT_EQ(ret, RDB_OK); + } + + now = std::chrono::system_clock::now().time_since_epoch(); + int64_t summaryTime = (std::chrono::duration_cast(now).count() - start); + int64_t averageTime = summaryTime / BASE_COUNT; + + EXPECT_LE(averageTime, RDB_UPDATE_BASELINE); + + // destroy + valueObject->destroy(valueObject); + valueBucket->destroy(valueBucket); + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/* * + * @tc.name: RDB_InsertWithConflictResolution_test_003 + * @tc.desc: test OH_Rdb_InsertWithConflictResolution interface performance. + * @tc.type: FUNC + */ +HWTEST_F(RdbPerformanceTest, RDB_InsertWithConflictResolution_test_003, TestSize.Level1) +{ + int ret = 0; + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putText(valueBucket, "data1", "liSi"); + valueBucket->putInt64(valueBucket, "data2", 13800); + valueBucket->putReal(valueBucket, "data3", 200.1); + valueBucket->putText(valueBucket, "data5", "ABCDEFGH"); + int64_t rowId = 0; + + auto now = std::chrono::system_clock::now().time_since_epoch(); + int64_t start = std::chrono::duration_cast(now).count(); + + for (int i = 0; i < BASE_COUNT; i++) { + ret = OH_Rdb_InsertWithConflictResolution(g_performanStore, "store_test", valueBucket, RDB_CONFLICT_ROLLBACK, + &rowId); + EXPECT_EQ(ret, RDB_OK); + } + + now = std::chrono::system_clock::now().time_since_epoch(); + int64_t summaryTime = (std::chrono::duration_cast(now).count() - start); + int64_t averageTime = summaryTime / BASE_COUNT; + + EXPECT_LE(averageTime, TRANS_INSERT_BASELINE); + + valueBucket->destroy(valueBucket); +} + +/* * + * @tc.name: RDB_UpdateWithConflictResolution_test_004 + * @tc.desc: test OH_Rdb_UpdateWithConflictResolution interface performance. + * @tc.type: FUNC + */ +HWTEST_F(RdbPerformanceTest, RDB_UpdateWithConflictResolution_test_004, TestSize.Level1) +{ + int ret = 0; + OH_Predicates *predicates = OH_Rdb_CreatePredicates("store_test"); + EXPECT_NE(predicates, NULL); + + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + EXPECT_NE(valueObject, NULL); + const char *data1Value = "zhangSan"; + valueObject->putText(valueObject, data1Value); + + predicates->equalTo(predicates, "data1", valueObject); + + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + EXPECT_NE(valueBucket, NULL); + valueBucket->putText(valueBucket, "data1", "liSi"); + valueBucket->putInt64(valueBucket, "data2", 13800); + valueBucket->putReal(valueBucket, "data3", 200.1); + valueBucket->putNull(valueBucket, "data5"); + + int64_t chgs = 0; + auto now = std::chrono::system_clock::now().time_since_epoch(); + int64_t start = std::chrono::duration_cast(now).count(); + + for (int i = 0; i < BASE_COUNT; i++) { + ret = OH_Rdb_UpdateWithConflictResolution(g_performanStore, valueBucket, predicates, RDB_CONFLICT_ROLLBACK, + &chgs); + EXPECT_EQ(ret, RDB_OK); + } + + now = std::chrono::system_clock::now().time_since_epoch(); + int64_t summaryTime = (std::chrono::duration_cast(now).count() - start); + int64_t averageTime = summaryTime / BASE_COUNT; + + EXPECT_LE(averageTime, TRANS_UPDATE_BASELINE); + + valueObject->destroy(valueObject); + valueBucket->destroy(valueBucket); + predicates->destroy(predicates); +} + +/* * + * @tc.name: RDB_AttachAndDetach_test_005 + * @tc.desc: Normal testCase of OH_Rdb_InsertWithConflictResolution errcode. + * @tc.type: FUNC + */ +HWTEST_F(RdbPerformanceTest, RDB_AttachAndDetach_test_005, TestSize.Level1) +{ + auto attachConfig = OH_Rdb_CreateConfig(); + ASSERT_NE(attachConfig, nullptr); + OH_Rdb_SetDatabaseDir(attachConfig, RDB_TEST_PATH); + OH_Rdb_SetStoreName(attachConfig, "rdb_attach_store_test.db"); + OH_Rdb_SetBundleName(attachConfig, "com.ohos.example.distributedndk"); + OH_Rdb_SetEncrypted(attachConfig, false); + OH_Rdb_SetSecurityLevel(attachConfig, OH_Rdb_SecurityLevel::S1); + OH_Rdb_SetArea(attachConfig, RDB_SECURITY_AREA_EL1); + + int errCode = 0; + auto tmpStore = OH_Rdb_CreateOrOpen(attachConfig, &errCode); + EXPECT_NE(tmpStore, NULL); + OH_Rdb_CloseStore(tmpStore); + + size_t attachedNumber = 0; + auto now = std::chrono::system_clock::now().time_since_epoch(); + int64_t start = std::chrono::duration_cast(now).count(); + for (int i = 0; i < BASE_COUNT; i++) { + auto ret = OH_Rdb_Attach(g_performanStore, attachConfig, "rdb_attach_test", 3, &attachedNumber); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_Detach(g_performanStore, "rdb_attach_test", 3, &attachedNumber); + EXPECT_EQ(ret, RDB_OK); + } + + now = std::chrono::system_clock::now().time_since_epoch(); + int64_t summaryTime = (std::chrono::duration_cast(now).count() - start); + int64_t averageTime = summaryTime / BASE_COUNT; + + EXPECT_LE(averageTime, RDB_ATTACH_BASELINE); +} \ No newline at end of file diff --git a/relational_store/test/ndk/unittest/rdb_predicates_pref_test.cpp b/relational_store/test/ndk/unittest/rdb_predicates_pref_test.cpp new file mode 100644 index 00000000..b6508083 --- /dev/null +++ b/relational_store/test/ndk/unittest/rdb_predicates_pref_test.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. + */ +#define LOG_TAG "RdbNdkPredicatesPrefTest" +#include +#include +#include + +#include +#include + +#include "logger.h" +#include "relational_store.h" +using namespace testing::ext; +using namespace OHOS::Rdb; +class RdbNdkPredicatesPrefTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; +const int BASE_COUNT = 2000; +const int HAVING_BASE_LINE = 10; +void RdbNdkPredicatesPrefTest::SetUpTestCase(void) +{ +} + +void RdbNdkPredicatesPrefTest::TearDownTestCase(void) +{ +} + +void RdbNdkPredicatesPrefTest::SetUp(void) +{ +} + +void RdbNdkPredicatesPrefTest::TearDown(void) +{ +} + +/** + * @tc.name: RDB_predicates_pref_test_having + * @tc.desc: Performance testing of basic scenarios for the Having interface + * @tc.type: FUNC + */ +HWTEST_F(RdbNdkPredicatesPrefTest, RDB_predicates_pref_test_having, TestSize.Level1) +{ + OH_Predicates *predicates = OH_Rdb_CreatePredicates("test"); + const char *columnNames[] = { "data" }; + predicates->groupBy(predicates, columnNames, 1); + auto start = std::chrono::high_resolution_clock::now(); + for (int i = 0; i < BASE_COUNT; i++) { + OH_Predicates_Having(predicates, "data", nullptr); + } + auto end = std::chrono::high_resolution_clock::now(); + auto total = std::chrono::duration_cast(end - start).count(); + double averageTime = static_cast(total) / BASE_COUNT; + LOG_INFO("the predicates_pref_test_having average time is %{public}f", averageTime); + ASSERT_TRUE(averageTime < HAVING_BASE_LINE); +} \ No newline at end of file diff --git a/relational_store/test/ndk/unittest/rdb_predicates_test.cpp b/relational_store/test/ndk/unittest/rdb_predicates_test.cpp index 41b88b36..4bb1f506 100644 --- a/relational_store/test/ndk/unittest/rdb_predicates_test.cpp +++ b/relational_store/test/ndk/unittest/rdb_predicates_test.cpp @@ -20,10 +20,10 @@ #include #include "common.h" +#include "oh_data_define.h" #include "oh_value_object.h" #include "relational_store.h" #include "relational_store_error_code.h" - using namespace testing::ext; using namespace OHOS::NativeRdb; @@ -48,6 +48,12 @@ public: OH_Rdb_Store *predicatesTestRdbStore_; OH_Rdb_Config RdbNativePredicatesTest::config_ = { 0 }; +const char HAVING_CREATE_SQL[] = + "CREATE TABLE IF NOT EXISTS orders (id INTEGER PRIMARY KEY AUTOINCREMENT, customer_id INTEGER, amount INTEGER)"; +const char HAVING_INSERT_SQL[] = + "INSERT INTO orders (customer_id, amount) VALUES (1, 1500), (1, 2000), (1, 3000), (2, 800), (2, 1200), (3, 1500)," + " (3, 2000), (3, 2500), (3, 1000)"; +const char HAVING_DROP_SQL[] = "DROP TABLE IF EXISTS orders"; void RdbNativePredicatesTest::SetUpTestCase(void) { InitRdbConfig(); @@ -154,12 +160,12 @@ HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_002, TestSize.Level const char *data1Value = "zhangSan"; valueObject->putText(valueObject, data1Value); predicates->notEqualTo(predicates, "data1", valueObject); - EXPECT_EQ(errCode, 0); OH_Cursor *cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, NULL, 0); EXPECT_NE(cursor, NULL); int rowCount = 0; errCode = cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(errCode, 0); EXPECT_EQ(rowCount, 2); valueObject->destroy(valueObject); @@ -198,8 +204,8 @@ HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_003, TestSize.Level size_t size = 0; cursor->getSize(cursor, 1, &size); - char data1Value[size + 1]; - cursor->getText(cursor, 1, data1Value, size + 1); + char data1Value[size]; + cursor->getText(cursor, 1, data1Value, size); EXPECT_EQ(strcmp(data1Value, "liSi"), 0); int64_t data2Value; @@ -215,9 +221,9 @@ HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_003, TestSize.Level EXPECT_EQ(isNull, true); cursor->getSize(cursor, 5, &size); - char data5Value_1[size + 1]; - cursor->getText(cursor, 5, data5Value_1, size + 1); - EXPECT_EQ(strcmp(data5Value_1, "ABCDEFGH"), 0); + char data5Value1[size]; + cursor->getText(cursor, 5, data5Value1, size); + EXPECT_EQ(strcmp(data5Value1, "ABCDEFGH"), 0); cursor->goToNextRow(cursor); cursor->getInt64(cursor, 0, &id); @@ -769,4 +775,353 @@ HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_021, TestSize.Level errCode = valueObject->destroy(nullptr); EXPECT_EQ(errCode, OH_Rdb_ErrCode::RDB_E_INVALID_ARGS); valueObject->destroy(valueObject); -} \ No newline at end of file +} + +/** + * @tc.name: RDB_Native_predicates_test_025 + * @tc.desc: Normal testCase of Predicates for having check params. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_025, TestSize.Level1) +{ + OH_Data_Values wrongValues; + OH_Predicates wrongPredicates; + wrongPredicates.id = 1; + + auto ret = OH_Predicates_Having(nullptr, "data5", &wrongValues); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_Having(&wrongPredicates, "data5", &wrongValues); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates("test"); + EXPECT_NE(predicates, nullptr); + + // test missing group by clause. + ret = OH_Predicates_Having(predicates, "data5", &wrongValues); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + const char *columnNames[] = { "data1"}; + predicates->groupBy(predicates, columnNames, 1); + + ret = OH_Predicates_Having(predicates, nullptr, &wrongValues); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_Having(predicates, "", &wrongValues); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_Having(predicates, "data5", nullptr); + EXPECT_EQ(ret, RDB_OK); + + OH_Data_Value value; + value.id = 1; + wrongValues.values_.push_back(value); + ret = OH_Predicates_Having(predicates, "data5", &wrongValues); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + wrongValues.id = 1; + ret = OH_Predicates_Having(predicates, "data5", &wrongValues); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + predicates->destroy(predicates); +} + +/** + * @tc.name: RDB_Native_predicates_test_026 + * @tc.desc: Verify scenarios without placeholders and without passing values + * 1.Execute OH_Predicates_Having(predicates, "total > 5000 AND count >= 3") + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_026, TestSize.Level1) +{ + auto errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_CREATE_SQL); + EXPECT_EQ(errCode, RDB_OK); + errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_INSERT_SQL); + EXPECT_EQ(errCode, RDB_OK); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates("orders"); + EXPECT_NE(predicates, nullptr); + const char *columnNames[] = { "customer_id"}; + predicates->groupBy(predicates, columnNames, 1); + errCode = OH_Predicates_Having(predicates, "total > 5000 AND count >= 3", nullptr); + EXPECT_EQ(errCode, RDB_OK); + + const char *columnNames1[] = { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total"}; + // 3 represents the number of columns. + OH_Cursor *cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, columnNames1, 3); + + EXPECT_EQ(cursor->goToNextRow(cursor), RDB_OK); + int64_t value; + EXPECT_EQ(cursor->getInt64(cursor, 0, &value), E_OK); + EXPECT_EQ(value, 1); + EXPECT_EQ(cursor->getInt64(cursor, 2, &value), E_OK); // 2 represents the total in the third column. + EXPECT_EQ(value, 6500); // 6500 means total price. + + EXPECT_EQ(cursor->goToNextRow(cursor), RDB_OK); + EXPECT_EQ(cursor->getInt64(cursor, 0, &value), E_OK); + EXPECT_EQ(value, 3); + EXPECT_EQ(cursor->getInt64(cursor, 2, &value), E_OK); // 2 represents the total in the third column. + EXPECT_EQ(value, 7000); // 7000 means total price. + + predicates->destroy(predicates); + cursor->destroy(cursor); + errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_DROP_SQL); + EXPECT_EQ(errCode, RDB_OK); +} + + /** + * @tc.name: RDB_Native_predicates_test_028 + * @tc.desc: Test conditions for passing in illegal SQL + * 1.Execute OH_Predicates_Having(predicates, "SALARY == 1.2") + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_028, TestSize.Level1) +{ + auto errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_CREATE_SQL); + EXPECT_EQ(errCode, RDB_OK); + errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_INSERT_SQL); + EXPECT_EQ(errCode, RDB_OK); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates("orders"); + EXPECT_NE(predicates, nullptr); + const char *columnNames[] = { "customer_id"}; + predicates->groupBy(predicates, columnNames, 1); + errCode = OH_Predicates_Having(predicates, "SALARY == 1.2", nullptr); + EXPECT_EQ(errCode, RDB_OK); + + const char *columnNames1[] = { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total"}; + // 3 represents the number of columns. + OH_Cursor *cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, columnNames1, 3); + int count; + EXPECT_EQ(cursor->getRowCount(cursor, &count), RDB_E_ERROR); + + predicates->destroy(predicates); + cursor->destroy(cursor); + errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_DROP_SQL); + EXPECT_EQ(errCode, RDB_OK); +} + +/** + * @tc.name: RDB_Native_predicates_test_029 + * @tc.desc: Verify scenarios without placeholders and without passing values + * 1.Execute OH_Predicates_Having(predicates, total > ? AND count >= ?", {5000}) + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_029, TestSize.Level1) +{ + auto errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_CREATE_SQL); + EXPECT_EQ(errCode, RDB_OK); + errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_INSERT_SQL); + EXPECT_EQ(errCode, RDB_OK); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates("orders"); + EXPECT_NE(predicates, nullptr); + const char *columnNames[] = { "customer_id"}; + predicates->groupBy(predicates, columnNames, 1); + + auto values = OH_Values_Create(); + OH_Values_PutInt(values, 5000); + + errCode = OH_Predicates_Having(predicates, "total > ? AND count >= ?", values); + EXPECT_EQ(errCode, RDB_OK); + + const char *columnNames1[] = { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total"}; + // 3 represents the number of columns. + OH_Cursor *cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, columnNames1, 3); + int count = -1; + EXPECT_EQ(cursor->getRowCount(cursor, &count), RDB_OK); + EXPECT_EQ(count, 0); + + predicates->destroy(predicates); + cursor->destroy(cursor); + errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_DROP_SQL); + EXPECT_EQ(errCode, RDB_OK); +} + +/** + * @tc.name: RDB_Native_predicates_test_030 + * @tc.desc: Test using placeholder scenarios. + * 1.Execute OH_Predicates_Having(predicates, total > ? AND count >= ?", {5000, 3}) + * 2.Query data + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_030, TestSize.Level1) +{ + auto errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_CREATE_SQL); + EXPECT_EQ(errCode, RDB_OK); + errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_INSERT_SQL); + EXPECT_EQ(errCode, RDB_OK); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates("orders"); + EXPECT_NE(predicates, nullptr); + const char *columnNames[] = { "customer_id"}; + predicates->groupBy(predicates, columnNames, 1); + auto values = OH_Values_Create(); + OH_Values_PutInt(values, 5000); + OH_Values_PutInt(values, 3); + errCode = OH_Predicates_Having(predicates, "total > ? AND count >= ?", values); + EXPECT_EQ(errCode, RDB_OK); + + const char *columnNames1[] = { "customer_id", "COUNT(*) AS count", "SUM(amount) AS total"}; + // 3 represents the number of columns. + OH_Cursor *cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, columnNames1, 3); + + EXPECT_EQ(cursor->goToNextRow(cursor), RDB_OK); + int64_t value; + EXPECT_EQ(cursor->getInt64(cursor, 0, &value), E_OK); + EXPECT_EQ(value, 1); + EXPECT_EQ(cursor->getInt64(cursor, 2, &value), E_OK); // 2 represents the total in the third column. + EXPECT_EQ(value, 6500); // 6500 means total price. + + EXPECT_EQ(cursor->goToNextRow(cursor), RDB_OK); + EXPECT_EQ(cursor->getInt64(cursor, 0, &value), E_OK); + EXPECT_EQ(value, 3); + EXPECT_EQ(cursor->getInt64(cursor, 2, &value), E_OK); // 2 represents the total in the third column. + EXPECT_EQ(value, 7000); // 7000 means total price. + + predicates->destroy(predicates); + cursor->destroy(cursor); + errCode = OH_Rdb_Execute(predicatesTestRdbStore_, HAVING_DROP_SQL); + EXPECT_EQ(errCode, RDB_OK); +} + +/** + * @tc.name: RDB_Native_predicates_test_031 + * @tc.desc: Normal testCase of Predicates for notLike. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_031, TestSize.Level1) +{ + int errCode = 0; + const char *data5Value = "BBCD%"; + const char *data2Value = "12%"; + + auto ret = OH_Predicates_NotLike(nullptr, "data5", data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Predicates wrong; + wrong.id = 1; + ret = OH_Predicates_NotLike(&wrong, "data5", data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates("test"); + EXPECT_NE(predicates, nullptr); + + ret = OH_Predicates_NotLike(predicates, nullptr, data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_NotLike(predicates, "data5", nullptr); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_NotLike(predicates, "data5", data5Value); + ret = OH_Predicates_NotLike(predicates, "data2", data2Value); + + OH_Cursor *cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, NULL, 0); + EXPECT_NE(cursor, NULL); + int rowCount = 0; + errCode = cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(rowCount, 2); + + predicates->destroy(predicates); + cursor->destroy(cursor); +} + +/** + * @tc.name: RDB_Native_predicates_test_032 + * @tc.desc: Normal testCase of Predicates for glob. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_032, TestSize.Level1) +{ + int errCode = 0; + const char *data5Value = "aBCD*"; + const char *data5Value2 = "ABCD*"; + + auto ret = OH_Predicates_Glob(nullptr, "data5", data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Predicates wrong; + wrong.id = 1; + ret = OH_Predicates_Glob(&wrong, "data5", data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates("test"); + EXPECT_NE(predicates, nullptr); + + ret = OH_Predicates_Glob(predicates, nullptr, data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_Glob(predicates, "data5", nullptr); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_Glob(predicates, "data5", data5Value); + OH_Cursor *cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, NULL, 0); + EXPECT_NE(cursor, NULL); + int rowCount = 0; + errCode = cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(rowCount, 0); + cursor->destroy(cursor); + predicates->destroy(predicates); + + predicates = OH_Rdb_CreatePredicates("test"); + EXPECT_NE(predicates, nullptr); + ret = OH_Predicates_Glob(predicates, "data5", data5Value2); + cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, NULL, 0); + EXPECT_NE(cursor, NULL); + rowCount = 0; + errCode = cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(rowCount, 3); + cursor->destroy(cursor); + predicates->destroy(predicates); +} + +/** + * @tc.name: RDB_Native_predicates_test_033 + * @tc.desc: Normal testCase of Predicates for glob. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_033, TestSize.Level1) +{ + int errCode = 0; + const char *data5Value = "aBCD*"; + const char *data5Value2 = "ABCD*"; + + auto ret = OH_Predicates_NotGlob(nullptr, "data5", data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Predicates wrong; + wrong.id = 1; + ret = OH_Predicates_NotGlob(&wrong, "data5", data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Predicates *predicates = OH_Rdb_CreatePredicates("test"); + EXPECT_NE(predicates, nullptr); + + ret = OH_Predicates_NotGlob(predicates, nullptr, data5Value); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_NotGlob(predicates, "data5", nullptr); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Predicates_NotGlob(predicates, "data5", data5Value); + OH_Cursor *cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, NULL, 0); + EXPECT_NE(cursor, NULL); + int rowCount = 0; + errCode = cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(rowCount, 3); + cursor->destroy(cursor); + predicates->destroy(predicates); + + predicates = OH_Rdb_CreatePredicates("test"); + EXPECT_NE(predicates, nullptr); + ret = OH_Predicates_NotGlob(predicates, "data5", data5Value2); + cursor = OH_Rdb_Query(predicatesTestRdbStore_, predicates, NULL, 0); + EXPECT_NE(cursor, NULL); + rowCount = 0; + errCode = cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(rowCount, 0); + cursor->destroy(cursor); + predicates->destroy(predicates); +} diff --git a/relational_store/test/ndk/unittest/rdb_store_configv2_test.cpp b/relational_store/test/ndk/unittest/rdb_store_configv2_test.cpp index 9775bd32..b99f6651 100644 --- a/relational_store/test/ndk/unittest/rdb_store_configv2_test.cpp +++ b/relational_store/test/ndk/unittest/rdb_store_configv2_test.cpp @@ -21,10 +21,14 @@ #include "accesstoken_kit.h" #include "common.h" #include "grd_api_manager.h" +#include "oh_data_utils.h" #include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_ndk_utils.h" #include "relational_store.h" #include "relational_store_error_code.h" #include "relational_store_impl.h" +#include "relational_store_inner_types.h" #include "token_setproc.h" using namespace testing::ext; @@ -144,7 +148,7 @@ HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_003, TestSize.Level1) const int *supportTypeList = OH_Rdb_GetSupportedDbType(&numType); EXPECT_NE(supportTypeList, nullptr); EXPECT_TRUE(((!OHOS::NativeRdb::IsUsingArkData()) && numType == 1) || // 1 means only contain RDB_SQLITE - ((OHOS::NativeRdb::IsUsingArkData()) && numType == 2)); // 2 means both contain RDB_SQLITE and RDB_CAYLEY + ((OHOS::NativeRdb::IsUsingArkData()) && numType == 2)); // 2 means both contain RDB_SQLITE and RDB_CAYLEY EXPECT_EQ(RDB_SQLITE, supportTypeList[0]); if (OHOS::NativeRdb::IsUsingArkData()) { EXPECT_EQ(RDB_CAYLEY, supportTypeList[1]); // 1st element must be RDB_CAYLEY @@ -189,6 +193,8 @@ HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_004, TestSize.Level1) EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetDbType(config, 0)); // 0 is invalid db type level EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetDbType(config, 6)); // 6 is invalid db type level EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetDbType(config, -1)); // -1 is invalid db type level + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetSemanticIndex(config, true)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetSemanticIndex(config, false)); const int *supportList = OH_Rdb_GetSupportedDbType(nullptr); EXPECT_EQ(nullptr, supportList); @@ -314,3 +320,319 @@ HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_007, TestSize.Level1) EXPECT_EQ(errCode, OH_Rdb_ErrCode::RDB_OK); OH_Rdb_DestroyConfig(config); } + +/** + * @tc.name: RDB_ICU_TEST001 + * @tc.desc: test apis of icu + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_ICU_TEST001, TestSize.Level1) +{ + mkdir(RDB_TEST_PATH, 0770); + auto config = InitRdbConfig(); + + // invalid param test + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, + OH_Rdb_SetTokenizer(config, static_cast(Rdb_Tokenizer::RDB_NONE_TOKENIZER - 1))); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, + OH_Rdb_SetTokenizer(config, static_cast(Rdb_Tokenizer::RDB_CUSTOM_TOKENIZER + 1))); + + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetTokenizer(config, Rdb_Tokenizer::RDB_NONE_TOKENIZER)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetTokenizer(config, Rdb_Tokenizer::RDB_CUSTOM_TOKENIZER)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetTokenizer(config, Rdb_Tokenizer::RDB_ICU_TOKENIZER)); + + int numType = 0; + const int *supportTypeList = OH_Rdb_GetSupportedDbType(&numType); + EXPECT_NE(supportTypeList, nullptr); + if (numType == 2) { + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetDbType(config, RDB_CAYLEY)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_NOT_SUPPORTED, + + OH_Rdb_SetTokenizer(config, Rdb_Tokenizer::RDB_ICU_TOKENIZER)); + } + + OH_Rdb_DestroyConfig(config); +} + +/** + * @tc.name: RDB_ICU_TEST002 + * @tc.desc: test apis of icu + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_ICU_TEST002, TestSize.Level1) +{ + mkdir(RDB_TEST_PATH, 0770); + int errCode = 0; + auto config = InitRdbConfig(); + + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetTokenizer(config, Rdb_Tokenizer::RDB_ICU_TOKENIZER)); + auto storeConfigV2TestRdbStore = OH_Rdb_CreateOrOpen(config, &errCode); + EXPECT_NE(storeConfigV2TestRdbStore, NULL); + + char createTableSql[] = "CREATE VIRTUAL TABLE example USING fts4(name, content, tokenize=icu zh_CN);"; + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_Execute(storeConfigV2TestRdbStore, createTableSql)); + + char insertSql1[] = + "INSERT INTO example(name, content) VALUES('文档1', '这是一个测试文档,用于测试中文文本的分词和索引。');"; + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_Execute(storeConfigV2TestRdbStore, insertSql1)); + + char insertSql2[] = + "INSERT INTO example(name, content) VALUES('文档2', '我们将使用这个示例来演示如何在SQLite中进行全文搜索。');"; + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_Execute(storeConfigV2TestRdbStore, insertSql2)); + + char insertSql3[] = + "INSERT INTO example(name, content) VALUES('文档3', 'ICU分词器能够很好地处理中文文本的分词和分析。');"; + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_Execute(storeConfigV2TestRdbStore, insertSql3)); + + char querySql[] = "SELECT * FROM example WHERE example MATCH '测试';"; + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_Execute(storeConfigV2TestRdbStore, querySql)); + + OH_Cursor *cursor = OH_Rdb_ExecuteQuery(storeConfigV2TestRdbStore, querySql); + EXPECT_NE(cursor, nullptr); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, cursor->goToNextRow(cursor)); + + int columnIndex = -1; + errCode = cursor->getColumnIndex(cursor, "name", &columnIndex); + EXPECT_EQ(columnIndex, 0); + char name[10]; + errCode = cursor->getColumnName(cursor, columnIndex, name, 10); + EXPECT_EQ(strcmp(name, "name"), 0); + + size_t size = 0; + cursor->getSize(cursor, columnIndex, &size); + char data1Value[size + 1]; + cursor->getText(cursor, columnIndex, data1Value, size + 1); + EXPECT_EQ(strcmp(data1Value, "文档1"), 0); + + errCode = cursor->getColumnIndex(cursor, "content", &columnIndex); + char name2[10]; + errCode = cursor->getColumnName(cursor, columnIndex, name2, 10); + EXPECT_EQ(strcmp(name2, "content"), 0); + + cursor->getSize(cursor, columnIndex, &size); + char data2Value[size + 1]; + cursor->getText(cursor, columnIndex, data2Value, size + 1); + EXPECT_EQ(strcmp(data2Value, "这是一个测试文档,用于测试中文文本的分词和索引。"), 0); + + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_CloseStore(storeConfigV2TestRdbStore)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_DeleteStoreV2(config)); + OH_Rdb_DestroyConfig(config); +} + +/** + * @tc.name: RDB_Native_store_test_009 + * @tc.desc: test apis of config interface OH_Rdb_SetCustomDir. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_009, TestSize.Level1) +{ + const char *customDir = "test"; + auto ret = OH_Rdb_SetCustomDir(nullptr, customDir); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_SetCustomDir(nullptr, "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + OH_Rdb_ConfigV2 *confg = OH_Rdb_CreateConfig(); + EXPECT_NE(confg, nullptr); + ret = OH_Rdb_SetCustomDir(confg, nullptr); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_SetCustomDir(confg, customDir); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_DestroyConfig(confg); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Native_store_test_010 + * @tc.desc: test apis of config interface OH_Rdb_SetReadOnly. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_010, TestSize.Level1) +{ + OH_Rdb_ConfigV2 *confg = OH_Rdb_CreateConfig(); + EXPECT_NE(confg, nullptr); + + auto ret = OH_Rdb_SetReadOnly(nullptr, true); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_SetReadOnly(confg, true); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_SetReadOnly(confg, false); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_DestroyConfig(confg); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Native_store_test_011 + * @tc.desc: test apis of config interface OH_Rdb_SetPlugins. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_011, TestSize.Level1) +{ + OH_Rdb_ConfigV2 *confg = OH_Rdb_CreateConfig(); + EXPECT_NE(confg, nullptr); + + const char *plugins[] = { "1" }; + auto ret = OH_Rdb_SetPlugins(nullptr, plugins, 1); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_SetPlugins(confg, nullptr, 1); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_SetPlugins(confg, plugins, 0); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_SetPlugins(confg, plugins, 1); + EXPECT_EQ(ret, RDB_OK); + + const char *pluginsNew[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "0", "x" }; + ret = OH_Rdb_SetPlugins(confg, pluginsNew, sizeof(pluginsNew) / sizeof(pluginsNew[0]) - 1); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_SetPlugins(confg, pluginsNew, sizeof(pluginsNew) / sizeof(pluginsNew[0])); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_DestroyConfig(confg); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Native_store_test_012 + * @tc.desc: test apis of config interface OH_Rdb_SetCryptoParam. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_012, TestSize.Level1) +{ + OH_Rdb_ConfigV2 *confg = OH_Rdb_CreateConfig(); + EXPECT_NE(confg, nullptr); + + OH_Rdb_CryptoParam *crypto = OH_Rdb_CreateCryptoParam(); + EXPECT_NE(crypto, NULL); + + auto ret = OH_Rdb_SetCryptoParam(nullptr, crypto); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_SetCryptoParam(confg, nullptr); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_Rdb_SetCryptoParam(confg, crypto); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_DestroyCryptoParam(crypto); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_DestroyConfig(confg); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Native_store_test_013 + * @tc.desc: abnormal test of RdbNdkUtils::GetRdbStoreConfig, when config is null. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_013, TestSize.Level1) +{ + auto [errCode, rdbConfig] = RdbNdkUtils::GetRdbStoreConfig(nullptr); + EXPECT_EQ(errCode, OHOS::NativeRdb::E_INVALID_ARGS); +} + +/** + * @tc.name: RDB_Native_store_test_014 + * @tc.desc: abnormal test of RdbNdkUtils::GetRdbStoreConfig, when securityLevel overlimit. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_014, TestSize.Level1) +{ + OH_Rdb_ConfigV2 *config = OH_Rdb_CreateConfig(); + EXPECT_NE(config, nullptr); + std::shared_ptr autoRelease = std::shared_ptr("RDB_Native_store_test_014", + [config](const char *) { + OH_Rdb_DestroyConfig(config); + }); + EXPECT_EQ(OH_Rdb_SetPersistent(config, true), RDB_OK); + config->securityLevel = -1; + auto [errCode1, _] = RdbNdkUtils::GetRdbStoreConfig(config); + EXPECT_EQ(errCode1, OHOS::NativeRdb::E_INVALID_ARGS); + + config->securityLevel = 10; + auto [errCode2, __] = RdbNdkUtils::GetRdbStoreConfig(config); + EXPECT_EQ(errCode2, OHOS::NativeRdb::E_INVALID_ARGS); +} + +/** + * @tc.name: RDB_Native_store_test_015 + * @tc.desc: abnormal test of RdbNdkUtils::GetRdbStoreConfig, when securityLevel overlimit. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_015, TestSize.Level1) +{ + OH_Rdb_ConfigV2 *config = OH_Rdb_CreateConfig(); + EXPECT_NE(config, nullptr); + std::shared_ptr autoRelease = std::shared_ptr("RDB_Native_store_test_015", + [config](const char *) { + OH_Rdb_DestroyConfig(config); + }); + EXPECT_EQ(OH_Rdb_SetPersistent(config, false), RDB_OK); + config->area = -1; + auto [errCode1, _] = RdbNdkUtils::GetRdbStoreConfig(config); + EXPECT_EQ(errCode1, OHOS::NativeRdb::E_INVALID_ARGS); + + config->area = 10; + auto [errCode2, __] = RdbNdkUtils::GetRdbStoreConfig(config); + EXPECT_EQ(errCode2, OHOS::NativeRdb::E_INVALID_ARGS); +} + +/** + * @tc.name: RDB_Native_store_test_016 + * @tc.desc: abnormal test of RdbNdkUtils::GetRdbStoreConfig, when dbType overlimit. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_016, TestSize.Level1) +{ + OH_Rdb_ConfigV2 *config = OH_Rdb_CreateConfig(); + EXPECT_NE(config, nullptr); + std::shared_ptr autoRelease = std::shared_ptr("RDB_Native_store_test_016", + [config](const char *) { + OH_Rdb_DestroyConfig(config); + }); + EXPECT_EQ(OH_Rdb_SetPersistent(config, true), RDB_OK); + EXPECT_EQ(OH_Rdb_SetSecurityLevel(config, S1), RDB_OK); + config->dbType = -1; + auto [errCode1, _] = RdbNdkUtils::GetRdbStoreConfig(config); + EXPECT_EQ(errCode1, OHOS::NativeRdb::E_INVALID_ARGS); + + config->dbType = 10; + auto [errCode2, __] = RdbNdkUtils::GetRdbStoreConfig(config); + EXPECT_EQ(errCode2, OHOS::NativeRdb::E_INVALID_ARGS); +} + +/** + * @tc.name: RDB_Native_store_test_017 + * @tc.desc: abnormal test of RdbNdkUtils::GetRdbStoreConfig, when token overlimit. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_017, TestSize.Level1) +{ + OH_Rdb_ConfigV2 *config = OH_Rdb_CreateConfig(); + EXPECT_NE(config, nullptr); + std::shared_ptr autoRelease = std::shared_ptr("RDB_Native_store_test_017", + [config](const char *) { + OH_Rdb_DestroyConfig(config); + }); + EXPECT_EQ(OH_Rdb_SetPersistent(config, true), RDB_OK); + EXPECT_EQ(OH_Rdb_SetSecurityLevel(config, S1), RDB_OK); + config->token = -1; + auto [errCode1, _] = RdbNdkUtils::GetRdbStoreConfig(config); + EXPECT_EQ(errCode1, OHOS::NativeRdb::E_INVALID_ARGS); + + config->token = 10; + auto [errCode2, __] = RdbNdkUtils::GetRdbStoreConfig(config); + EXPECT_EQ(errCode2, OHOS::NativeRdb::E_INVALID_ARGS); +} diff --git a/relational_store/test/ndk/unittest/rdb_store_test.cpp b/relational_store/test/ndk/unittest/rdb_store_test.cpp index 274db390..208bf1d9 100644 --- a/relational_store/test/ndk/unittest/rdb_store_test.cpp +++ b/relational_store/test/ndk/unittest/rdb_store_test.cpp @@ -188,9 +188,10 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_001, TestSize.Level1) size_t size = 0; cursor->getSize(cursor, 1, &size); - char data1Value_1[size + 1]; - cursor->getText(cursor, 1, data1Value_1, size + 1); - EXPECT_EQ(strcmp(data1Value_1, "liSi"), 0); + EXPECT_EQ(size, 5); + char data1Value1[size]; + cursor->getText(cursor, 1, data1Value1, size); + EXPECT_EQ(strcmp(data1Value1, "liSi"), 0); int64_t data2Value; cursor->getInt64(cursor, 2, &data2Value); @@ -253,9 +254,10 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_002, TestSize.Level1) size_t size = 0; cursor->getSize(cursor, 1, &size); - char data1Value_1[size + 1]; - cursor->getText(cursor, 1, data1Value_1, size + 1); - EXPECT_EQ(strcmp(data1Value_1, "liSi"), 0); + EXPECT_EQ(size, 5); + char data1Value1[size]; + cursor->getText(cursor, 1, data1Value1, size); + EXPECT_EQ(strcmp(data1Value1, "liSi"), 0); int64_t data2Value; cursor->getInt64(cursor, 2, &data2Value); @@ -270,8 +272,8 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_002, TestSize.Level1) EXPECT_EQ(isNull, true); cursor->getSize(cursor, 5, &size); - char data5Value[size + 1]; - cursor->getText(cursor, 5, data5Value, size + 1); + char data5Value[size]; + cursor->getText(cursor, 5, data5Value, size); EXPECT_EQ(strcmp(data5Value, "ABCDEFGH"), 0); valueObject->destroy(valueObject); @@ -598,9 +600,9 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_0010, TestSize.Level1) size_t size = 0; cursor->getSize(cursor, 1, &size); - char data1Value_1[size + 1]; - cursor->getText(cursor, 1, data1Value_1, size + 1); - EXPECT_EQ(strcmp(data1Value_1, "zhangSan"), 0); + char data1Value1[size]; + cursor->getText(cursor, 1, data1Value1, size); + EXPECT_EQ(strcmp(data1Value1, "zhangSan"), 0); int64_t data2Value; cursor->getInt64(cursor, 2, &data2Value); @@ -679,7 +681,6 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_013, TestSize.Level1) constexpr int TABLE_COUNT = 1; const char *table[TABLE_COUNT]; table[0] = "store_test"; - EXPECT_EQ(table[0], "store_test"); Rdb_ProgressObserver observer; void *context = nullptr; observer.context = &context; @@ -1054,6 +1055,7 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_023, TestSize.Level1) predicates->clear(predicates); errCode = OH_Rdb_UnlockRow(storeTestRdbStore_, predicates); EXPECT_EQ(errCode, OH_Rdb_ErrCode::RDB_E_NO_ROW_IN_QUERY); + cursor->destroy(cursor); predicates->clear(predicates); cursor = OH_Rdb_QueryLockedRow(storeTestRdbStore_, predicates, NULL, 0); @@ -1685,4 +1687,189 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_037, TestSize.Level1) EXPECT_EQ(rowCount, 1); cursor->destroy(cursor); valueBucket->destroy(valueBucket); -} \ No newline at end of file +} + +/** + * @tc.name: RDB_Native_store_test_039 + * @tc.desc: normal testCase for OH_Rdb_InsertWithConflictResolution. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_039, TestSize.Level1) +{ + int errCode = 0; + OH_Rdb_Store *store = storeTestRdbStore_; + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putInt64(valueBucket, "id", 2); + valueBucket->putText(valueBucket, "data1", "liSi"); + valueBucket->putInt64(valueBucket, "data2", 13800); + valueBucket->putReal(valueBucket, "data3", 200.1); + valueBucket->putText(valueBucket, "data5", "ABCDEFGH"); + int64_t rowId = 0; + errCode = OH_Rdb_InsertWithConflictResolution(nullptr, "store_test", valueBucket, RDB_CONFLICT_ROLLBACK, &rowId); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + + errCode = OH_Rdb_InsertWithConflictResolution(store, nullptr, valueBucket, RDB_CONFLICT_ROLLBACK, &rowId); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + + errCode = OH_Rdb_InsertWithConflictResolution(store, "store_test", nullptr, RDB_CONFLICT_ROLLBACK, &rowId); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + + errCode = OH_Rdb_InsertWithConflictResolution(store, "store_test", valueBucket, + static_cast(0), &rowId); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + + errCode = OH_Rdb_InsertWithConflictResolution(store, "store_test", valueBucket, + static_cast(RDB_CONFLICT_REPLACE + 1), &rowId); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + + errCode = OH_Rdb_InsertWithConflictResolution(store, "store_test", valueBucket, RDB_CONFLICT_ROLLBACK, nullptr); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + + errCode = OH_Rdb_InsertWithConflictResolution(store, "store_test", valueBucket, RDB_CONFLICT_ROLLBACK, &rowId); + EXPECT_EQ(errCode, RDB_OK); + EXPECT_EQ(rowId, 2); + + valueBucket->destroy(valueBucket); +} + +/** + * @tc.name: RDB_Native_store_test_040 + * @tc.desc: normal testCase for OH_Rdb_UpdateWithConflictResolution. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_040, TestSize.Level1) +{ + int errCode = 0; + OH_Rdb_Store *store = storeTestRdbStore_; + OH_Predicates *predicates = OH_Rdb_CreatePredicates("store_test"); + EXPECT_NE(predicates, NULL); + + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + EXPECT_NE(valueObject, NULL); + const char *data1Value = "zhangSan"; + valueObject->putText(valueObject, data1Value); + + predicates->equalTo(predicates, "data1", valueObject); + + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + EXPECT_NE(valueBucket, NULL); + valueBucket->putText(valueBucket, "data1", "liSi"); + valueBucket->putInt64(valueBucket, "data2", 13800); + valueBucket->putReal(valueBucket, "data3", 200.1); + valueBucket->putNull(valueBucket, "data5"); + + int64_t chgs = 0; + errCode = OH_Rdb_UpdateWithConflictResolution(nullptr, valueBucket, predicates, RDB_CONFLICT_ROLLBACK, &chgs); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + errCode = OH_Rdb_UpdateWithConflictResolution(store, nullptr, predicates, RDB_CONFLICT_ROLLBACK, &chgs); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + errCode = OH_Rdb_UpdateWithConflictResolution(store, valueBucket, nullptr, RDB_CONFLICT_ROLLBACK, nullptr); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + errCode = OH_Rdb_UpdateWithConflictResolution(store, valueBucket, predicates, RDB_CONFLICT_ROLLBACK, &chgs); + EXPECT_EQ(errCode, RDB_OK); + EXPECT_EQ(chgs, 1); + + predicates->clear(predicates); + OH_Cursor *cursor = OH_Rdb_Query(storeTestRdbStore_, predicates, NULL, 0); + EXPECT_NE(cursor, NULL); + + int rowCount = 0; + cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(rowCount, 1); + + errCode = cursor->goToNextRow(cursor); + EXPECT_EQ(errCode, 0); + + size_t size = 0; + cursor->getSize(cursor, 1, &size); + EXPECT_EQ(size, 5); + char data1Value1[size]; + cursor->getText(cursor, 1, data1Value1, size); + EXPECT_STREQ(data1Value1, "liSi"); + + valueObject->destroy(valueObject); + valueBucket->destroy(valueBucket); + predicates->destroy(predicates); + cursor->destroy(cursor); +} + +static OH_Rdb_ConfigV2 *g_attachConfig = nullptr; +static void CreateAttachDatabase() +{ + g_attachConfig = OH_Rdb_CreateConfig(); + ASSERT_NE(g_attachConfig, nullptr); + OH_Rdb_SetDatabaseDir(g_attachConfig, RDB_TEST_PATH); + OH_Rdb_SetStoreName(g_attachConfig, "rdb_attach_store_test.db"); + OH_Rdb_SetBundleName(g_attachConfig, "com.ohos.example.distributedndk"); + OH_Rdb_SetEncrypted(g_attachConfig, false); + OH_Rdb_SetSecurityLevel(g_attachConfig, OH_Rdb_SecurityLevel::S1); + OH_Rdb_SetArea(g_attachConfig, RDB_SECURITY_AREA_EL1); + + int errCode = 0; + auto tmpStore = OH_Rdb_CreateOrOpen(g_attachConfig, &errCode); + EXPECT_NE(tmpStore, NULL); + OH_Rdb_CloseStore(tmpStore); +} + +static void DeleteAttachDatabase() +{ + EXPECT_EQ(OH_Rdb_DeleteStoreV2(g_attachConfig), 0); + OH_Rdb_DestroyConfig(g_attachConfig); + g_attachConfig = nullptr; +} + +/** + * @tc.name: RDB_Native_store_test_041 + * @tc.desc: normal testCase for OH_Rdb_Attach、OH_Rdb_Detach. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_041, TestSize.Level1) +{ + CreateAttachDatabase(); + + size_t attachedNumber = 0; + auto ret = OH_Rdb_Attach(nullptr, g_attachConfig, "rdb_attach_test", 3, &attachedNumber); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Attach(storeTestRdbStore_, nullptr, "rdb_attach_test", 3, &attachedNumber); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Attach(storeTestRdbStore_, g_attachConfig, nullptr, 3, &attachedNumber); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Attach(storeTestRdbStore_, g_attachConfig, "rdb_attach_test", 0, &attachedNumber); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Attach(storeTestRdbStore_, g_attachConfig, "rdb_attach_test", 3, nullptr); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Attach(storeTestRdbStore_, g_attachConfig, "rdb_attach_test", 3, &attachedNumber); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(attachedNumber, 1); + + ret = OH_Rdb_Detach(nullptr, "rdb_attach_test", 3, &attachedNumber); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Detach(storeTestRdbStore_, nullptr, 3, &attachedNumber); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Detach(storeTestRdbStore_, "rdb_attach_test", 0, &attachedNumber); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Detach(storeTestRdbStore_, "rdb_attach_test", 3, nullptr); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + ret = OH_Rdb_Detach(storeTestRdbStore_, "rdb_attach_test", 3, &attachedNumber); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(attachedNumber, 0); + + DeleteAttachDatabase(); +} + +/** + * @tc.name: RDB_Native_store_test_042 + * @tc.desc: normal testCase for OH_Rdb_SetLocale. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_042, TestSize.Level1) +{ + int errCode = 0; + OH_Rdb_Store *store = storeTestRdbStore_; + errCode = OH_Rdb_SetLocale(nullptr, "zh"); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + errCode = OH_Rdb_SetLocale(store, nullptr); + EXPECT_EQ(errCode, RDB_E_INVALID_ARGS); + errCode = OH_Rdb_SetLocale(store, "zh"); + EXPECT_EQ(errCode, RDB_OK); +} diff --git a/relational_store/test/ndk/unittest/rdb_transaction_capi_test.cpp b/relational_store/test/ndk/unittest/rdb_transaction_capi_test.cpp index bac6a33a..227df913 100644 --- a/relational_store/test/ndk/unittest/rdb_transaction_capi_test.cpp +++ b/relational_store/test/ndk/unittest/rdb_transaction_capi_test.cpp @@ -840,4 +840,551 @@ HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_014, TestSize.Level1) ret = OH_VBucket_PutUnlimitedInt(valueBucket, "data2", 1, trueForm, 3); EXPECT_EQ(ret, RDB_OK); valueBucket->destroy(valueBucket); +} + +/** + * @tc.name: RDB_Transaction_capi_test_016 + * @tc.desc: Normal testCase of store transaction for OH_RdbTrans_InsertWithConflictResolution + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_016, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + const char *table = "test"; + int ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + // new row + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putText(valueBucket, "data1", "liSi"); + // init data2 value is 13800 + valueBucket->putInt64(valueBucket, "data2", 13800); + // init data3 value is 200.1 + valueBucket->putReal(valueBucket, "data3", 200.1); + valueBucket->putNull(valueBucket, "data5"); + + // create predicates + OH_Predicates *predicates = OH_Rdb_CreatePredicates(table); + // create match data + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + const char *data1Value = "zhangSan"; + valueObject->putText(valueObject, data1Value); + predicates->equalTo(predicates, "data1", valueObject); + + // update + int64_t changes = -1; + ret = OH_RdbTrans_InsertWithConflictResolution(trans, table, valueBucket, + static_cast(0), &changes); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_RdbTrans_UpdateWithConflictResolution(trans, valueBucket, predicates, RDB_CONFLICT_REPLACE, &changes); + EXPECT_EQ(ret, RDB_OK); + EXPECT_EQ(changes, 1); + + // destroy + valueObject->destroy(valueObject); + valueBucket->destroy(valueBucket); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + + +/** + * @tc.name: RDB_Transaction_capi_test_017 + * @tc.desc: Normal testCase of store transaction for OH_RdbTrans_InsertWithConflictResolution and OH_RdbTrans_Rollback + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_017, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + const char *table = "test"; + int ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putText(valueBucket, "data1", "test_name4"); + // init is data2 is 14800 + valueBucket->putInt64(valueBucket, "data2", 14800); + // init is data2 is 300.1 + valueBucket->putReal(valueBucket, "data3", 300.1); + valueBucket->putText(valueBucket, "data5", "ABCDEFGHI"); + int64_t rowId = -1; + ret = OH_RdbTrans_InsertWithConflictResolution(trans, table, valueBucket, + static_cast(0), &rowId); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_RdbTrans_InsertWithConflictResolution(trans, table, valueBucket, RDB_CONFLICT_ROLLBACK, &rowId); + EXPECT_EQ(ret, RDB_OK); + // expect value is 4 + EXPECT_EQ(rowId, 4); + + ret = OH_RdbTrans_Rollback(trans); + EXPECT_EQ(ret, RDB_OK); + + valueBucket->destroy(valueBucket); + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_024 + * @tc.desc: Normal testCase of store transaction for OH_RdbTrans_InsertWithConflictResolution and OH_RdbTrans_Commit + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_024, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + const char *table = "test"; + int ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + EXPECT_NE(valueBucket, nullptr); + valueBucket->putText(valueBucket, "data1", "test_name4"); + // init is data2 is 14800 + valueBucket->putInt64(valueBucket, "data2", 14800); + // init is data2 is 300.1 + valueBucket->putReal(valueBucket, "data3", 300.1); + valueBucket->putText(valueBucket, "data5", "ABCDEFGHI"); + int64_t rowId = -1; + ret = OH_RdbTrans_InsertWithConflictResolution(trans, table, valueBucket, + static_cast(0), &rowId); + EXPECT_EQ(ret, RDB_E_INVALID_ARGS); + + ret = OH_RdbTrans_InsertWithConflictResolution(trans, table, valueBucket, RDB_CONFLICT_ROLLBACK, &rowId); + EXPECT_EQ(ret, RDB_OK); + // expect value is 4 + EXPECT_EQ(rowId, 4); + + ret = OH_RdbTrans_Commit(trans); + EXPECT_EQ(ret, RDB_OK); + + valueBucket->destroy(valueBucket); + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_025 + * @tc.desc: Abnormal testCase of drop the table before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_025, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + int ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + + const char *sql = "DROP TABLE test"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_E_SQLITE_LOCKED); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Rollback(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_026 + * @tc.desc: Abnormal testCase of drop the table before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_026, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + int ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + + const char *sql = "DROP TABLE test"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_E_SQLITE_LOCKED); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Rollback(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_027 + * @tc.desc: Normal testCase of drop the table after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_027, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + + char createTableSql[] = "CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, data2 INTEGER, " + "data3 FLOAT, data4 BLOB, data5 TEXT);"; + int ret = OH_Rdb_Execute(g_transStore, createTableSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + + cursor->destroy(cursor); + + const char *sql = "DROP TABLE test1"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Commit(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_028 + * @tc.desc: Abnormal testCase of drop the index before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_028, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + + char createIndexSql[] = "CREATE INDEX test_index ON test(data2);"; + int ret = OH_Rdb_Execute(g_transStore, createIndexSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + + const char *sql = "DROP INDEX test_index"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_E_SQLITE_LOCKED); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Rollback(trans); + EXPECT_EQ(ret, RDB_OK); + + char dropIndexSql[] = "DROP INDEX test_index;"; + ret = OH_Rdb_Execute(g_transStore, dropIndexSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_029 + * @tc.desc: Abnormal testCase of drop the index before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_029, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + + char createIndexSql[] = "CREATE INDEX test_index ON test(data2);"; + int ret = OH_Rdb_Execute(g_transStore, createIndexSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + + const char *sql = "DROP INDEX test_index"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_E_SQLITE_LOCKED); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Rollback(trans); + EXPECT_EQ(ret, RDB_OK); + + char dropIndexSql[] = "DROP INDEX test_index;"; + ret = OH_Rdb_Execute(g_transStore, dropIndexSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_030 + * @tc.desc: Abnormal testCase of drop the index after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_030, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + + char createIndexSql[] = "CREATE index test_index ON test(data2);"; + int ret = OH_Rdb_Execute(g_transStore, createIndexSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + + cursor->destroy(cursor); + + const char *sql = "DROP INDEX test_index"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Commit(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_031 + * @tc.desc: Normal testCase of drop the table after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_031, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + + char createTableSql[] = "CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, data2 INTEGER, " + "data3 FLOAT, data4 BLOB, data5 TEXT);"; + int ret = OH_Rdb_Execute(g_transStore, createTableSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test1"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_NE(ret, RDB_OK); + + const char *sql = "DROP TABLE test1"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_OK); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Commit(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_032 + * @tc.desc: Normal testCase of drop the index after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_032, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + + char createIndexSql[] = "CREATE index test_index ON test(data2);"; + int ret = OH_Rdb_Execute(g_transStore, createIndexSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test1"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_NE(ret, RDB_OK); + + const char *sql = "DROP INDEX test_index"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_OK); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Commit(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_033 + * @tc.desc: Abnormal testCase of drop the table after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_033, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + + char createTableSql[] = "CREATE TABLE test1 (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, data2 INTEGER, " + "data3 FLOAT, data4 BLOB, data5 TEXT);"; + int ret = OH_Rdb_Execute(g_transStore, createTableSql); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test1"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + ret = cursor->goToNextRow(cursor); + EXPECT_NE(ret, RDB_OK); + + const char *sql = "DROP TABLE test"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_OK); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Rollback(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_034 + * @tc.desc: Abnormal testCase of drop the table after querying the data and closing the resultSet. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_034, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + + int ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + const char *sql = "DROP TABLE test1"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_OK); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Rollback(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); +} + +/** + * @tc.name: RDB_Transaction_capi_test_035 + * @tc.desc: Normal testCase of drop the table before closing the resultSet after querying the data. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransactionCapiTest, RDB_Transaction_capi_test_035, TestSize.Level1) +{ + OH_Rdb_Transaction *trans = nullptr; + int ret = OH_Rdb_CreateTransaction(g_transStore, g_options, &trans); + EXPECT_EQ(ret, RDB_OK); + EXPECT_NE(trans, nullptr); + + const char *querySql = "SELECT * FROM test"; + OH_Cursor *cursor = OH_RdbTrans_QuerySql(trans, querySql, nullptr); + EXPECT_NE(cursor, nullptr); + + int rowCount = 0; + ret = cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(ret, RDB_OK); + + for (int i = 0; i < rowCount; i++) { + ret = cursor->goToNextRow(cursor); + EXPECT_EQ(ret, RDB_OK); + } + + ret = cursor->goToNextRow(cursor); + EXPECT_NE(ret, RDB_OK); + + const char *sql = "DROP TABLE test"; + ret = OH_RdbTrans_Execute(trans, sql, nullptr, nullptr); + EXPECT_EQ(ret, RDB_OK); + + cursor->destroy(cursor); + + ret = OH_RdbTrans_Commit(trans); + EXPECT_EQ(ret, RDB_OK); + + ret = OH_RdbTrans_Destroy(trans); + EXPECT_EQ(ret, RDB_OK); } \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 600b26e0..7b18ae65 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,12 +4,13 @@ project(LDBTest) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_FLAGS "-std=c++1y -fvisibility=default -D_GNU_SOURCE") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -fPIC -fpic -ffunction-sections -D_GLIBC_MOCK") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-access-control") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-access-control -D__CJSON_USE_INT64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--no-as-needed -ldl") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=0 -fpermissive -Wa,-mbig-obj") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=deprecated-declarations -Wno-deprecated-declarations -Wattributes") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") +add_definitions(-D__CJSON_USE_INT64) include_directories(${CMAKE_SOURCE_DIR}/utils_native/base/include) include_directories(${CMAKE_SOURCE_DIR}/utils_native/safwk/native/include) @@ -31,8 +32,18 @@ set(links secure mock app adapter svcFwk service) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) enable_testing() +#************************************************CommonTest start************************************************# +#aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/common/test KvStoreTestSrc) +# +#aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest KvStoreTestSrc) +add_executable(CommonTest ${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/common/test/executor_pool_test.cpp) +target_link_libraries(CommonTest gtest_main gmock_main gcov) +target_include_directories(CommonTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/common) +target_include_directories(CommonTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/interfaces/innerkits/distributeddata/include) +#************************************************CommonTest end************************************************# + #************************************************KVDBTest start************************************************# -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/innerkitsimpl/kvdb/test KvStoreTestSrc) +#aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/innerkitsimpl/kvdb/test KvStoreTestSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/innerkitsimpl/kvdb/test/mock/src KvStoreTestSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/common/test KvStoreTestSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest KvStoreTestSrc) @@ -56,11 +67,13 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/dis aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/adapter/communicator/test/unittest DataMgrTestSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/test/mock DataMgrTestSrc) #list(REMOVE_ITEM DataMgrTestSrc "../datamgr_service/services/distributeddataservice/service/test/unittest/cloud/device_manger_adapter_mock.cpp") -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/test DataMgrTestSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/framework/test DataMgrTestSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/adapter/test DataMgrTestSrc) +#aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/test DataMgrTestSrc) +#aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/adapter/test DataMgrTestSrc) add_executable(DataMgrServiceTest ${DataMgrTestSrc} ${mainSrc} ${serviceSrc}) target_link_libraries(DataMgrServiceTest ${links} gtest gtest_main gmock_main gcov relational_store data_share preferences distributeddb data_object kvdb udmf) +#add_executable(DataMgrServiceTest ${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/framework/test/serializable_test.cpp) +#target_link_libraries(DataMgrServiceTest svcFwk gtest gtest_main) +target_compile_definitions(DataMgrServiceTest PUBLIC -D__CJSON_USE_INT64) target_include_directories(DataMgrServiceTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/adapter/account/src) target_include_directories(DataMgrServiceTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/adapter/communicator/src) target_include_directories(DataMgrServiceTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/backup/include) @@ -128,18 +141,18 @@ target_include_directories(PerferencesTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/. #************************************************PerferencesTest end************************************************# #************************************************DataShareTest start************************************************# -file(GLOB_RECURSE dataShareTestSrc ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/test/native/unittest/*.cpp) -add_executable(DataShareTest ${dataShareTestSrc} ${mainSrc} ${serviceSrc}) -target_link_libraries(DataShareTest ${links} gtest_main gcov data_share service) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/common/include) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/test/native/unittest/mediadatashare_test/include) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/consumer/controller/common) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/consumer/controller/provider/include) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/consumer/controller/service/include) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/consumer/include) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/permission/include) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/provider/include) -target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/proxy/include) +#file(GLOB_RECURSE dataShareTestSrc ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/test/native/unittest/*.cpp) +#add_executable(DataShareTest ${dataShareTestSrc} ${mainSrc} ${serviceSrc}) +#target_link_libraries(DataShareTest ${links} gtest_main gcov data_share service) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/common/include) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/test/native/unittest/mediadatashare_test/include) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/consumer/controller/common) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/consumer/controller/provider/include) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/consumer/controller/service/include) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/consumer/include) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/permission/include) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/provider/include) +#target_include_directories(DataShareTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../data_share/frameworks/native/proxy/include) #************************************************DataShareTest end************************************************# #************************************************DataObjectTest start************************************************# @@ -170,7 +183,7 @@ target_include_directories(UdmfTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../kv_st aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/test/mock CloudTestSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/test/unittest/cloud CloudTestSrc) add_executable(CloudTest ${CloudTestSrc} ${mainSrc} ${serviceSrc}) -target_link_libraries(CloudTest gtest_main gmock_main gcov svcFwk distributeddb kvdb service app) +target_link_libraries(CloudTest gtest_main gmock gcov svcFwk distributeddb kvdb service app) target_include_directories(CloudTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/test) target_include_directories(CloudTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/backup/include) target_include_directories(CloudTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/bootstrap/include) diff --git a/udmf/BUILD.gn b/udmf/BUILD.gn index 5c7a57c8..28eefe11 100644 --- a/udmf/BUILD.gn +++ b/udmf/BUILD.gn @@ -17,9 +17,12 @@ group("udmf_packages") { if (is_standard_system) { deps = [ "interfaces/components:udmfcomponents", + "interfaces/innerkits:pixelmap_wrapper", "interfaces/innerkits:udmf_client", "interfaces/innerkits:utd_client", + "interfaces/innerkits/aipcore:aip_core_mgr_static", "interfaces/jskits:intelligence_napi", + "interfaces/jskits:rag_napi", "interfaces/jskits:udmf_data_napi", "interfaces/jskits:unifieddatachannel_napi", "interfaces/jskits:uniformtypedescriptor_napi", @@ -34,6 +37,7 @@ group("unittest") { deps = [ "framework/common/unittest:unittest", "framework/innerkitsimpl/test/unittest:unittest", + "framework/jskitsimpl/test:stage_unittest", "framework/jskitsimpl/unittest:unittest", "framework/ndkimpl/unittest:unittest", ] @@ -42,5 +46,8 @@ group("unittest") { group("fuzztest") { testonly = true - deps = [ "framework/innerkitsimpl/test/fuzztest:fuzztest" ] + deps = [ + "framework/innerkitsimpl/test/fuzztest:fuzztest", + "framework/ndkimpl/udmf_fuzzer:fuzztest", + ] } diff --git a/udmf/CMakeLists.txt b/udmf/CMakeLists.txt index b2e32d46..0c18d121 100644 --- a/udmf/CMakeLists.txt +++ b/udmf/CMakeLists.txt @@ -18,6 +18,7 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/convert list(REMOVE_ITEM udmf_src "${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/convert/data_params_conversion.cpp") aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/data udmf_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/dynamic udmf_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/service udmf_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/jskitsimpl/common udmf_channel_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/jskitsimpl/data udmf_channel_src) @@ -46,6 +47,7 @@ target_include_directories(udmf PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/in target_include_directories(udmf PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/innerkits/common) target_include_directories(udmf PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/innerkits/convert) target_include_directories(udmf PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/innerkits/data) +target_include_directories(udmf PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/innerkits/dynamic) target_include_directories(udmf PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/client) target_include_directories(udmf PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/framework/ndkimpl/data) diff --git a/udmf/CODEOWNERS b/udmf/CODEOWNERS index df88964e..23f246b1 100644 --- a/udmf/CODEOWNERS +++ b/udmf/CODEOWNERS @@ -11,5 +11,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -# any change to framework/service/distributeddata_udmf_ipc_interface_code.h needs to be reviewed by @leonchan5 -framework/service/distributeddata_udmf_ipc_interface_code.h @leonchan5 \ No newline at end of file +# any change to framework/service/distributeddata_udmf_ipc_interface_code.h needs to be reviewed by @leonchan5 liubao6@huawei.com +framework/service/distributeddata_udmf_ipc_interface_code.h @leonchan5 liubao6@huawei.com \ No newline at end of file diff --git a/udmf/adapter/BUILD.gn b/udmf/adapter/BUILD.gn index 8208f369..9813e3b2 100644 --- a/udmf/adapter/BUILD.gn +++ b/udmf/adapter/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2024 Huawei Device Co., Ltd. +# Copyright (c) 2024-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 @@ -14,6 +14,10 @@ import("//build/ohos.gni") import("//foundation/distributeddatamgr/udmf/adapter/arkui_x_udmf.gni") import("//foundation/distributeddatamgr/udmf/udmf.gni") +third_party_skia_path = "${third_party_path}/skia" +if (udmf_feature_upgrade_skia) { + third_party_skia_path = "${third_party_path}/skia/m133" +} config("udmf_client_config") { include_dirs = [ "${udmf_interfaces_path}/innerkits/client", @@ -69,14 +73,18 @@ config("arkui_x_udmf_config") { "${arkui_x_graphic_surface_path}/interfaces/inner_api/common", "${arkui_x_graphic_surface_path}/interfaces/inner_api/surface", "${arkui_x_graphic_surface_path}/interfaces/inner_api/utils", - "${third_party_path}/skia", + "${third_party_skia_path}", + "${udmf_interfaces_path}/innerkits/dynamic", ] - defines = [ "CROSS_PLATFORM" ] + if (udmf_feature_upgrade_skia) { + defines += [ "USE_M133_SKIA" ] + } } arkui_x_public_source = [ "${udmf_framework_path}/innerkitsimpl/client/getter_system.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", "${udmf_framework_path}/innerkitsimpl/common/unified_key.cpp", "${udmf_framework_path}/innerkitsimpl/data/application_defined_record.cpp", "${udmf_framework_path}/innerkitsimpl/data/audio.cpp", @@ -87,7 +95,6 @@ arkui_x_public_source = [ "${udmf_framework_path}/innerkitsimpl/data/image.cpp", "${udmf_framework_path}/innerkitsimpl/data/link.cpp", "${udmf_framework_path}/innerkitsimpl/data/plain_text.cpp", - "${udmf_framework_path}/innerkitsimpl/data/preset_type_descriptors.cpp", "${udmf_framework_path}/innerkitsimpl/data/system_defined_appitem.cpp", "${udmf_framework_path}/innerkitsimpl/data/system_defined_form.cpp", "${udmf_framework_path}/innerkitsimpl/data/system_defined_pixelmap.cpp", @@ -101,13 +108,14 @@ arkui_x_public_source = [ "${udmf_framework_path}/common/graph.cpp", "${udmf_root_path}/adapter/framework/innerkitsimpl/common/unified_meta.cpp", "${udmf_root_path}/adapter/framework/innerkitsimpl/client/utd_client.cpp", + "${udmf_framework_path}/common/base32_utils.cpp", + "${udmf_framework_path}/common/custom_utd_json_parser.cpp", + "${udmf_framework_path}/common/custom_utd_store.cpp", + "${udmf_root_path}/adapter/framework/innerkitsimpl/client/preset_type_descriptors.cpp", ] ohos_source_set("arkui_x_udmf_data") { sources = [ - "${udmf_framework_path}/common/base32_utils.cpp", - "${udmf_framework_path}/common/custom_utd_json_parser.cpp", - "${udmf_framework_path}/common/custom_utd_store.cpp", "${udmf_framework_path}/common/utd_cfgs_checker.cpp", "${udmf_root_path}/adapter/framework/common/udmf_utils.cpp", ] @@ -140,6 +148,7 @@ ohos_source_set("arkui_x_udmf_data_inner") { "${arkui_path}/napi/:ace_napi", "${arkui_x_c_utils_path}/base:utilsbase", "${arkui_x_hilog_path}/interfaces/native/innerkits:libhilog_${target_os}", + "${third_party_path}/cJSON:cjson_static", ] configs = [ @@ -166,10 +175,11 @@ config("arkui_x_udmf_napi_config") { "${arkui_x_graphic_surface_path}/interfaces/inner_api/utils", "${arkui_x_graphic_2d_path}/utils/color_manager/export", "${arkui_x_graphic_2d_path}/rosen/modules/platform/ipc_core", - "${third_party_path}/skia", + "${third_party_skia_path}", ] + defines = [ "CROSS_PLATFORM" ] if (current_os == "ios") { - defines = [ "IOS_PLATFORM" ] + defines += [ "IOS_PLATFORM" ] } } @@ -180,6 +190,9 @@ ohos_source_set("arkui_x_uniformtypedescriptor") { "${udmf_root_path}/adapter/framework/innerkitsimpl/client", ] + if (udmf_feature_upgrade_skia) { + defines = [ "USE_M133_SKIA" ] + } sources = [ "${udmf_framework_path}/jskitsimpl/common/napi_data_utils.cpp", "${udmf_framework_path}/jskitsimpl/common/napi_error_utils.cpp", @@ -253,6 +266,9 @@ ohos_source_set("arkui_x_unifieddatachannel") { "${ability_runtime_cross_platform_path}/interfaces/inner_api/want:want_params_config", ] + if (udmf_feature_upgrade_skia) { + defines = [ "USE_M133_SKIA" ] + } deps = [ ":arkui_x_udmf_data", "${ability_runtime_cross_platform_path}/interfaces/inner_api/want:cross_platform_want_params", @@ -301,7 +317,9 @@ ohos_source_set("arkui_x_udmf_data_napi") { ":arkui_x_udmf_napi_config", "${ability_runtime_cross_platform_path}/interfaces/inner_api/want:want_params_config", ] - + if (udmf_feature_upgrade_skia) { + defines = [ "USE_M133_SKIA" ] + } deps = [ ":arkui_x_udmf_data_inner", "${ability_runtime_cross_platform_path}/frameworks/js/napi/napi_common:napi_common", diff --git a/udmf/adapter/arkui_x_udmf.gni b/udmf/adapter/arkui_x_udmf.gni index e629b3a1..7d5f715a 100644 --- a/udmf/adapter/arkui_x_udmf.gni +++ b/udmf/adapter/arkui_x_udmf.gni @@ -11,6 +11,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +declare_args() { + udmf_feature_upgrade_skia = false +} ability_runtime_cross_platform_path = "//foundation/appframework/ability/ability_runtime/cross_platform" diff --git a/udmf/adapter/framework/innerkitsimpl/client/preset_type_descriptors.cpp b/udmf/adapter/framework/innerkitsimpl/client/preset_type_descriptors.cpp new file mode 100644 index 00000000..d7007c43 --- /dev/null +++ b/udmf/adapter/framework/innerkitsimpl/client/preset_type_descriptors.cpp @@ -0,0 +1,3346 @@ +/* + * 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 "preset_type_descriptors.h" + +namespace OHOS { +namespace UDMF { +constexpr const char *REFERENCE_URL = ""; + +PresetTypeDescriptors::PresetTypeDescriptors() +{ + InitDescriptors(); +} + +PresetTypeDescriptors::~PresetTypeDescriptors() +{ +} + +PresetTypeDescriptors &PresetTypeDescriptors::GetInstance() +{ + static PresetTypeDescriptors instance; + return instance; +} + +std::vector &PresetTypeDescriptors::GetPresetTypes() +{ + return typeDescriptors_; +} + +void PresetTypeDescriptors::InitDescriptors() +{ + std::lock_guard lock(mutex_); + typeDescriptors_ = { + {"general.entity", + {}, + {}, + {}, + "Base type for physical hierarchy.", + REFERENCE_URL, + ""}, + {"general.object", + {}, + {}, + {"*/*"}, + "Base type for logical hierarchy.", + REFERENCE_URL, + ""}, + {"general.composite-object", + {"general.object"}, + {}, + {}, + "Base type for mixed object. For example, a PDF file contains both text and special formatting data.", + REFERENCE_URL, + ""}, + {"general.text", + {"general.object"}, + {}, + {"text/*"}, + "Base type for all text.", + REFERENCE_URL, + ""}, + {"general.plain-text", + {"general.text"}, + {".txt", ".text"}, + {"text/plain"}, + "Text of unspecified encoding, with no markup.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_txt"}, + {"general.html", + {"general.text"}, + {".html", ".htm"}, + {"text/html"}, + "HTML text.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_html"}, + {"general.hyperlink", + {"general.text"}, + {}, + {}, + "Hyperlink.", + REFERENCE_URL, + ""}, + {"general.xml", + {"general.text"}, + {".xml"}, + {"text/xml"}, + "XML text.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_xml"}, + {"com.real.smil", + {"general.xml"}, + {".smil"}, + {"application/smil"}, + "Real synchronized multimedia integration language.", + REFERENCE_URL, + ""}, + {"general.source-code", + {"general.text"}, + {}, + {}, + "Generic source code.", + REFERENCE_URL, + ""}, + {"general.script", + {"general.source-code"}, + {}, + {}, + "Base type for scripting language source code.", + REFERENCE_URL, + ""}, + {"general.shell-script", + {"general.script"}, + {".sh", ".command"}, + {"text/x-shellscript"}, + "Shell script.", + REFERENCE_URL, + ""}, + {"general.csh-script", + {"general.shell-script"}, + {".csh"}, + {"text/x-csh"}, + "C-shell script.", + REFERENCE_URL, + ""}, + {"general.perl-script", + {"general.shell-script"}, + {".pl", ".pm"}, + {"text/x-perl-script"}, + "Perl script.", + REFERENCE_URL, + ""}, + {"general.php-script", + {"general.shell-script"}, + {".php", ".php3", ".php4", ".ph3", ".ph4", ".phtml"}, + {"text/x-php-script", "text/php", "application/php"}, + "PHP script.", + REFERENCE_URL, + ""}, + {"general.python-script", + {"general.shell-script"}, + {".py"}, + {"text/x-python-script"}, + "Python script.", + REFERENCE_URL, + ""}, + {"general.ruby-script", + {"general.shell-script"}, + {".rb", ".rbw"}, + {"text/ruby-script"}, + "Ruby script.", + REFERENCE_URL, + ""}, + {"general.type-script", + {"general.source-code"}, + {".ts"}, + {}, + "TypeScript source code.", + REFERENCE_URL, + ""}, + {"general.java-script", + {"general.source-code"}, + {".js", ".jscript", ".javascript"}, + {"text/javascript"}, + "JavaScript source code.", + REFERENCE_URL, + ""}, + {"general.c-header", + {"general.source-code"}, + {".h"}, + {"text/x-chdr"}, + "C header file.", + REFERENCE_URL, + ""}, + {"general.c-source", + {"general.source-code"}, + {".c"}, + {"text/x-csrc"}, + "C source code.", + REFERENCE_URL, + ""}, + {"general.c-plus-plus-header", + {"general.source-code"}, + {".hpp", ".h++", ".hxx", ".hh"}, + {"text/x-c++hdr"}, + "C++ header file.", + REFERENCE_URL, + ""}, + {"general.c-plus-plus-source", + {"general.source-code"}, + {".cp", ".cpp", ".c++", ".cc", ".cxx"}, + {"text/x-c++src"}, + "C++ source code.", + REFERENCE_URL, + ""}, + {"general.java-source", + {"general.source-code"}, + {".java", ".jav"}, + {"text/x-java"}, + "Java source code.", + REFERENCE_URL, + ""}, + {"general.markdown", + {"general.text"}, + {".md", ".markdown", ".markdn", ".mdown"}, + {"text/markdown"}, + "Markdown format.", + REFERENCE_URL, + ""}, + {"general.ebook", + {"general.composite-object"}, + {}, + {}, + "Base type for ebook.", + REFERENCE_URL, + ""}, + {"general.epub", + {"general.ebook"}, + {".epub"}, + {"application/epub+zip"}, + "Electronic publication (EPUB) format.", + REFERENCE_URL, + ""}, + {"com.amazon.azw", + {"general.ebook"}, + {".azw"}, + {"application/vnd.amazon.ebook"}, + "AZW ebook.", + REFERENCE_URL, + ""}, + {"com.amazon.azw3", + {"general.ebook"}, + {".azw3"}, + {"application/vnd.amazon.mobi8-ebook", "application/x-mobi8-ebook"}, + "AZW3 ebook.", + REFERENCE_URL, + ""}, + {"com.amazon.kfx", + {"general.ebook"}, + {".kfx"}, + {}, + "KFX ebook.", + REFERENCE_URL, + ""}, + {"com.amazon.mobi", + {"general.ebook"}, + {".mobi"}, + {"application/x-mobipocket-ebook"}, + "MOBI ebook.", + REFERENCE_URL, + ""}, + {"general.media", + {"general.object"}, + {}, + {}, + "Base type for media.", + REFERENCE_URL, + ""}, + {"general.image", + {"general.media"}, + {}, + {"image/*"}, + "Base type for images.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"general.jpeg", + {"general.image"}, + {".jpg", ".jpeg", ".jpe"}, + {"image/jpeg"}, + "JPEG image.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"general.png", + {"general.image"}, + {".png"}, + {"image/png"}, + "PNG image.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"general.raw-image", + {"general.image"}, + {}, + {}, + "Base type for digital camera raw image formats.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"general.tiff", + {"general.image"}, + {".tif", ".tiff"}, + {"image/tiff"}, + "TIFF image.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"com.microsoft.bmp", + {"general.image"}, + {".bmp", ".bm"}, + {"image/bmp", "image/x-ms-bmp"}, + "Windows bitmap image.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"com.microsoft.ico", + {"general.image"}, + {".ico"}, + {"image/ico", "image/x-icon"}, + "Windows icon image.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"com.adobe.photoshop-image", + {"general.image"}, + {".psd"}, + {"image/x-photoshop", "image/photoshop", "image/psd", "application/photoshop"}, + "Adobe Photoshop document.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"com.adobe.illustrator.ai-image", + {"general.image"}, + {".ai"}, + {}, + "Adobe Illustrator document.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"general.fax", + {"general.image"}, + {}, + {}, + "Base type for fax images.", + REFERENCE_URL, + ""}, + {"com.j2.jfx-fax", + {"general.fax"}, + {".jfx"}, + {}, + "J2 fax.", + REFERENCE_URL, + ""}, + {"com.js.efx-fax", + {"general.fax"}, + {".efx"}, + {"image/efax"}, + "eFax fax.", + REFERENCE_URL, + ""}, + {"general.xbitmap-image", + {"general.image"}, + {".xbm"}, + {"image/x-xbitmap", "image/x-xbm"}, + "X bitmap image.", + REFERENCE_URL, + ""}, + {"com.truevision.tga-image", + {"general.image"}, + {".tga"}, + {"image/targa", "image/tga", "application/tga"}, + "TGA image.", + REFERENCE_URL, + ""}, + {"com.sgi.sgi-image", + {"general.image"}, + {".sgi"}, + {"image/sgi"}, + "Silicon Graphics image.", + REFERENCE_URL, + ""}, + {"com.ilm.openexr-image", + {"general.image"}, + {".exr"}, + {}, + "OpenEXR image.", + REFERENCE_URL, + ""}, + {"com.kodak.flashpix.image", + {"general.image"}, + {".fpx"}, + {"image/fpx", "application/vnd.fpx"}, + "FlashPix image.", + REFERENCE_URL, + ""}, + {"com.microsoft.word.doc", + {"general.composite-object"}, + {".doc"}, + {"application/msword"}, + "Microsoft Word data.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_doc"}, + {"com.microsoft.excel.xls", + {"general.composite-object"}, + {".xls"}, + {"application/vnd.ms-excel"}, + "Microsoft Excel data.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_xls"}, + {"com.microsoft.powerpoint.ppt", + {"general.composite-object"}, + {".ppt"}, + {"application/vnd.ms-powerpoint"}, + "Microsoft PowerPoint presentation.", + REFERENCE_URL, + ""}, + {"com.adobe.pdf", + {"general.composite-object"}, + {".pdf"}, + {"application/pdf"}, + "PDF data.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_pdf"}, + {"com.adobe.postscript", + {"general.composite-object"}, + {".ps"}, + {"application/postscript"}, + "PostScript data.", + REFERENCE_URL, + ""}, + {"com.adobe.encapsulated-postscript", + {"com.adobe.postscript"}, + {".eps"}, + {}, + "Encapsulated PostScript.", + REFERENCE_URL, + ""}, + {"general.video", + {"general.media"}, + {}, + {"video/*"}, + "Base type for video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"general.avi", + {"general.video"}, + {".avi", ".vfw"}, + {"video/avi", "video/msvideo", "video/x-msvideo"}, + "AVI video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"general.mpeg", + {"general.video"}, + {".mpg", ".mpeg", ".m75", ".m15", ".mpe"}, + {"video/mpg", "video/mpeg", "video/x-mpg", "video/x-mpeg"}, + "MPEG-1 or MPEG-2 video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"general.mpeg-4", + {"general.video"}, + {".mp4", ".mp4v", ".mpeg4"}, + {"video/mp4", "video/mp4v"}, + "MPEG-4 video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"general.3gpp", + {"general.video"}, + {".3gp", ".3gpp"}, + {"video/3gpp"}, + "3GPP video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"general.3gpp2", + {"general.video"}, + {".3g2", ".3gp2", ".3gpp2"}, + {"video/3gpp2"}, + "3GPP2 video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.microsoft.windows-media-wm", + {"general.video", "com.microsoft.advanced-systems-format"}, + {".wm"}, + {"video/x-ms-wm"}, + "Windows WM video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.microsoft.windows-media-wmv", + {"general.video", "com.microsoft.advanced-systems-format"}, + {".wmv"}, + {"video/x-ms-wmv"}, + "Windows WMV video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.microsoft.windows-media-wmp", + {"general.video", "com.microsoft.advanced-systems-format"}, + {".wmp"}, + {"video/x-ms-wmp"}, + "Windows WMP video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.microsoft.windows-media-wvx", + {"general.video", "com.microsoft.advanced-systems-format"}, + {".wvx"}, + {"video/x-ms-wvx"}, + "Windows WVX video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.microsoft.windows-media-wmx", + {"general.video", "com.microsoft.advanced-systems-format"}, + {".wmx"}, + {"video/x-ms-wmx"}, + "Windows WMX video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.real.realmedia", + {"general.video"}, + {".rm"}, + {"application/vnd.rn-realmedia"}, + "RealMedia.", + REFERENCE_URL, + ""}, + {"general.audio", + {"general.media"}, + {}, + {"audio/*"}, + "Base type for audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.aac", + {"general.audio"}, + {".aac"}, + {"audio/aac"}, + "AAC audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.aiff", + {"general.audio"}, + {".aiff"}, + {"audio/aiff"}, + "AIFF audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.alac", + {"general.audio"}, + {".alac"}, + {"audio/alac"}, + "ALAC audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.flac", + {"general.audio"}, + {".flac"}, + {"audio/flac"}, + "FLAC audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_flac"}, + {"general.mp3", + {"general.audio"}, + {".mp3"}, + {"audio/mp3"}, + "MPEG-3 audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_mp3"}, + {"general.ogg", + {"general.audio"}, + {".ogg"}, + {"audio/ogg"}, + "OGG audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.pcm", + {"general.audio"}, + {".pcm"}, + {"audio/pcm"}, + "PCM audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"com.microsoft.advanced-systems-format", + {"general.media"}, + {".asf"}, + {"video/x-ms-asf", "application/vnd.ms-asf"}, + "Advanced Systems format", + REFERENCE_URL, + ""}, + {"com.microsoft.advanced-stream-redirector", + {"general.video"}, + {".asx"}, + {"video/x-ms-asf"}, + "Advanced stream redirector", + REFERENCE_URL, + ""}, + {"com.microsoft.windows-media-wma", + {"general.audio", "com.microsoft.advanced-systems-format"}, + {".wma"}, + {"audio/x-ms-wma"}, + "Windows WMA audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_wma"}, + {"com.microsoft.waveform-audio", + {"general.audio", "com.microsoft.advanced-systems-format"}, + {".wav", ".wave"}, + {"audio/wav", "audio/wave", "audio/x-wav"}, + "Waveform audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_wav"}, + {"com.microsoft.windows-media-wax", + {"general.audio", "com.microsoft.advanced-systems-format"}, + {".wax"}, + {"audio/x-ms-wax"}, + "Windows WAX audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.au-audio", + {"general.audio"}, + {".au", ".snd"}, + {"audio/basic", "audio/au", "audio/snd"}, + "Au file format.", + REFERENCE_URL, + ""}, + {"general.aifc-audio", + {"general.audio"}, + {".aifc", ".aif", ".aiff"}, + {"audio/x-aiff"}, + "Audio Interchange File Format.", + REFERENCE_URL, + ""}, + {"com.digidesign.sd2-audio", + {"general.audio"}, + {".sd2"}, + {"audio/x-sd2"}, + "Digidesign Sound Designer II audio.", + REFERENCE_URL, + ""}, + {"com.real.realaudio", + {"general.audio"}, + {".ram", ".ra"}, + {"audio/vnd.rn-realaudio", "audio/x-pn-realaudio"}, + "RealMedia audio.", + REFERENCE_URL, + ""}, + {"general.file", + {"general.entity"}, + {}, + {}, + "Base type for file.", + REFERENCE_URL, + ""}, + {"general.directory", + {"general.entity"}, + {}, + {}, + "Base type for directory.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_folder"}, + {"general.folder", + {"general.directory"}, + {}, + {}, + "Base type for folder.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_folder"}, + {"general.symlink", + {"general.entity"}, + {}, + {}, + "Base type for symlink.", + REFERENCE_URL, + ""}, + {"general.archive", + {"general.object"}, + {}, + {}, + "Base type for an archive of files and directories.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"general.bz2-archive", + {"general.archive"}, + {".bz2", ".bzip2"}, + {"application/x-bzip2"}, + "BZip2 archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"general.disk-image", + {"general.archive"}, + {}, + {}, + "Base type for items mountable as a volume.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"general.tar-archive", + {"general.archive"}, + {".tar"}, + {"application/x-tar", "application/tar"}, + "Tar archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"general.zip-archive", + {"general.archive"}, + {".zip"}, + {"application/zip"}, + "Zip archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_zip"}, + {"com.sun.java-archive", + {"general.archive", "general.executable"}, + {".jar"}, + {"application/java-archive"}, + "Java archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"org.gnu.gnu-tar-archive", + {"general.archive"}, + {".gtar"}, + {"application/x-gtar"}, + "GNU archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"org.gnu.gnu-zip-archive", + {"general.archive"}, + {".gz", ".gzip"}, + {"application/x-gzip", "application/gzip"}, + "Gzip archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"org.gnu.gnu-zip-tar-archive", + {"general.archive"}, + {".tgz"}, + {"application/x-gtar"}, + "Gzip tar archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"org.openxmlformats.openxml", + {"general.archive"}, + {}, + {}, + "Office Open XML.", + REFERENCE_URL, + ""}, + {"org.openxmlformats.wordprocessingml.document", + {"general.composite-object", "org.openxmlformats.openxml"}, + {".docx"}, + {"application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, + "Office Open XML Document.", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.sheet", + {"general.composite-object", "org.openxmlformats.openxml"}, + {".xlsx"}, + {"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, + "Office Open XML Workbook.", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.presentation", + {"general.composite-object", "org.openxmlformats.openxml"}, + {".pptx"}, + {"application/vnd.openxmlformats-officedocument.presentationml.presentation"}, + "Office Open XML Presentation.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument", + {"general.archive"}, + {}, + {}, + "Open Document Format for Office Applications.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument.text", + {"general.composite-object", "org.oasis.opendocument"}, + {".odt", ".fodt"}, + {"application/vnd.oasis.opendocument.text"}, + "OpenDocument Text.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument.spreadsheet", + {"general.composite-object", "org.oasis.opendocument"}, + {".ods", ".fods"}, + {"application/vnd.oasis.opendocument.spreadsheet"}, + "OpenDocument Spreadsheet.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument.presentation", + {"general.composite-object", "org.oasis.opendocument"}, + {".odp", ".fodp"}, + {"application/vnd.oasis.opendocument.presentation"}, + "OpenDocument Presentation.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument.graphics", + {"general.composite-object", "org.oasis.opendocument"}, + {".odg", ".fodg"}, + {"application/vnd.oasis.opendocument.graphics"}, + "OpenDocument Graphics.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument.formula", + {"org.oasis.opendocument"}, + {".odf"}, + {"application/vnd.oasis.opendocument.formula"}, + "OpenDocument Formulat.", + REFERENCE_URL, + ""}, + {"com.allume.stuffit-archive", + {"general.archive"}, + {".sit", ".sitx"}, + {"application/x-stuffit", "application/x-sit", "application/stuffit"}, + "Stuffit archive.", + REFERENCE_URL, + ""}, + {"general.calendar", + {"general.text"}, + {}, + {"text/calendar"}, + "Base type for scheduled events.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_calendar"}, + {"general.vcs", + {"general.calendar"}, + {".vcs"}, + {"text/calendar"}, + "vCalendar type.", + REFERENCE_URL, + ""}, + {"general.ics", + {"general.calendar"}, + {".ics"}, + {"text/calendar"}, + "iCalendar type.", + REFERENCE_URL, + ""}, + {"general.contact", + {"general.object"}, + {}, + {}, + "Base type for contact information.", + REFERENCE_URL, + ""}, + {"general.database", + {"general.object"}, + {}, + {}, + "Base type for databases.", + REFERENCE_URL, + ""}, + {"general.message", + {"general.object"}, + {}, + {}, + "Base type for messages.", + REFERENCE_URL, + ""}, + {"general.executable", + {"general.object"}, + {}, + {}, + "Base type for executable data.", + REFERENCE_URL, + ""}, + {"com.microsoft.portable-executable", + {"general.executable"}, + {".exe", ".dll"}, + {"application/vnd.microsoft.portable-executable"}, + "Microsoft Windows application.", + REFERENCE_URL, + ""}, + {"com.sun.java-class", + {"general.executable"}, + {".class"}, + {}, + "Java class.", + REFERENCE_URL, + ""}, + {"general.vcard", + {"general.object"}, + {".vcf", ".vcard"}, + {"text/vcard", "text/x-vcard"}, + "Base type for electronic business card.", + REFERENCE_URL, + ""}, + {"general.navigation", + {"general.object"}, + {}, + {}, + "Base type for navigation.", + REFERENCE_URL, + ""}, + {"general.location", + {"general.navigation"}, + {}, + {}, + "Navigation location.", + REFERENCE_URL, + ""}, + {"general.font", + {"general.object"}, + {}, + {}, + "Base type for fonts.", + REFERENCE_URL, + ""}, + {"general.truetype-font", + {"general.font"}, + {".ttf"}, + {"font/ttf"}, + "TrueType font.", + REFERENCE_URL, + ""}, + {"general.truetype-collection-font", + {"general.font"}, + {".ttc"}, + {"font/collection"}, + "TrueType collection font.", + REFERENCE_URL, + ""}, + {"general.opentype-font", + {"general.font"}, + {".otf"}, + {"font/otf"}, + "OpenType font.", + REFERENCE_URL, + ""}, + {"com.adobe.postscript-font", + {"general.font"}, + {}, + {}, + "PostScript font.", + REFERENCE_URL, + ""}, + {"openharmony.form", + {"general.object"}, + {}, + {}, + "OpenHarmony system defined form.", + REFERENCE_URL, + ""}, + {"openharmony.app-item", + {"general.object"}, + {}, + {}, + "OpenHarmony system defined app item.", + REFERENCE_URL, + ""}, + {"openharmony.pixel-map", + {"general.image"}, + {}, + {}, + "OpenHarmony system defined pixel map.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"openharmony.atomic-service", + {"general.object"}, + {}, + {}, + "OpenHarmony system defined atomic service.", + REFERENCE_URL, + ""}, + {"openharmony.package", + {"general.directory"}, + {}, + {}, + "OpenHarmony system defined package (that is, a directory presented to the user as a file).", + REFERENCE_URL, + ""}, + {"openharmony.hap", + {"openharmony.package"}, + {".hap"}, + {}, + "OpenHarmony system defined ability package.", + REFERENCE_URL, + ""}, + {"openharmony.hdoc", + {"general.composite-object"}, + {".hdoc"}, + {}, + "OpenHarmony system AppNotepad data format.", + REFERENCE_URL, + ""}, + {"openharmony.hinote", + {"general.composite-object"}, + {".hinote"}, + {}, + "OpenHarmony system Notes data format.", + REFERENCE_URL, + ""}, + {"openharmony.styled-string", + {"general.composite-object"}, + {}, + {}, + "OpenHarmony system defined styled string.", + REFERENCE_URL, + ""}, + {"openharmony.want", + {"general.object"}, + {}, + {}, + "OpenHarmony system defined Want.", + REFERENCE_URL, + ""}, + {"openharmony.moving-photo", + {"general.media"}, + {}, + {}, + "OpenHarmony system defined moving photo.", + REFERENCE_URL, + ""}, + {"macos.dmg", + {"general.disk-image"}, + {".dmg"}, + {"application/x-apple-diskimage"}, + "Apple Disk Image", + REFERENCE_URL, + ""}, + {"debian.deb", + {"general.archive"}, + {".deb", ".udeb"}, + {"application/x-debian-package", "application/vnd.debian.binary-package"}, + "OpenHarmony system defined Want.", + REFERENCE_URL, + ""}, + {"general.ofd", + {"general.composite-object"}, + {".ofd"}, + {}, + "Open fixed-layout document, a national standard for format documents", + REFERENCE_URL, + ""}, + {"general.opg", + {"general.archive"}, + {".opg"}, + {}, + "OPG archive", + REFERENCE_URL, + ""}, + {"general.tex", + {"general.source-code"}, + {}, + {}, + "Base type for TeX source code", + REFERENCE_URL, + ""}, + {"general.css", + {"general.script"}, + {".css"}, + {"text/css"}, + "Cascading style sheets", + REFERENCE_URL, + ""}, + {"general.vob", + {"general.video"}, + {".vob"}, + {"video/mpeg", "video/x-ms-vob"}, + "", + REFERENCE_URL, + ""}, + {"general.dif-video", + {"general.video"}, + {".dif"}, + {"video/dv"}, + "Digital interface format", + REFERENCE_URL, + ""}, + {"general.dv-video", + {"general.video"}, + {".dv"}, + {"video/dv"}, + "DV video", + REFERENCE_URL, + ""}, + {"general.flc-animation", + {"general.video"}, + {".fli", ".flc"}, + {"video/fli", "video/flc"}, + "FLIC file format", + REFERENCE_URL, + ""}, + {"general.mng", + {"general.video"}, + {".mng"}, + {"video/x-mng"}, + "Multiple-image network graphics", + REFERENCE_URL, + ""}, + {"general.mpegurl-video", + {"general.video"}, + {".mxu", ".m4u"}, + {"video/vnd.mpegurl"}, + "Video playlist", + REFERENCE_URL, + ""}, + {"general.ts", + {"general.video"}, + {".ts"}, + {"video/mp2ts", "video/mp2t"}, + "MPEG transport stream", + REFERENCE_URL, + ""}, + {"general.amr", + {"general.audio"}, + {".amr"}, + {"audio/amr"}, + "The adaptive multi-rate audio codecs", + REFERENCE_URL, + ""}, + {"general.amr-wb", + {"general.audio"}, + {".awb"}, + {"audio/amr-wb"}, + "Adaptive multi-rate wideband", + REFERENCE_URL, + ""}, + {"general.gsm", + {"general.audio"}, + {".gsm"}, + {"audio/x-gsm", "audio/gsm"}, + "Global system form mobile audio format", + REFERENCE_URL, + ""}, + {"general.imy", + {"general.audio"}, + {".imy"}, + {"audio/imelody"}, + "Non-polyphonic ringtone exchange object format", + REFERENCE_URL, + ""}, + {"general.kar", + {"general.audio"}, + {".kar"}, + {"audio/midi"}, + "Karaoke MIDI file format", + REFERENCE_URL, + ""}, + {"general.mpegurl-audio", + {"general.audio"}, + {".m3u"}, + {"audio/mpegurl", "audio/x-mpegurl"}, + "Audio playlist", + REFERENCE_URL, + ""}, + {"general.mpeg-4-audio", + {"general.audio"}, + {".m4a", ".m4b"}, + {"audio/mpeg"}, + "Audio-only MPEG-4 file", + REFERENCE_URL, + ""}, + {"general.midi-audio", + {"general.audio"}, + {".mid", ".midi"}, + {"audio/midi"}, + "MIDI audio", + REFERENCE_URL, + ""}, + {"general.mp2", + {"general.audio"}, + {".mp2"}, + {"audio/mpeg"}, + "MPEG-1 audio layer II or MPEG-2 audio layer II", + REFERENCE_URL, + ""}, + {"general.mpeg-audio", + {"general.audio"}, + {".mpga"}, + {"audio/mpeg"}, + "MPEG audio format", + REFERENCE_URL, + ""}, + {"general.mxmf", + {"general.audio"}, + {".mxmf"}, + {"audio/mobile-xmf"}, + "Mobile XMF audio format", + REFERENCE_URL, + ""}, + {"general.ota", + {"general.audio"}, + {".ota"}, + {"audio/midi"}, + "OTA ringtone file", + REFERENCE_URL, + ""}, + {"general.pls", + {"general.audio"}, + {".pls"}, + {"audio/x-scpls"}, + "Multimedia playlist format", + REFERENCE_URL, + ""}, + {"general.rtttl", + {"general.audio"}, + {".rtttl"}, + {"audio/midi"}, + "Ring tone transfer language file", + REFERENCE_URL, + ""}, + {"general.psid", + {"general.audio"}, + {".sid", ".psid"}, + {"audio/prs.sid"}, + "SID audio", + REFERENCE_URL, + ""}, + {"general.ulaw-audio", + {"general.audio"}, + {".au", ".ulw", ".snd"}, + {"audio/basic", "audio/au", "audio/snd"}, + "uLaw audio", + REFERENCE_URL, + ""}, + {"general.xmf", + {"general.audio"}, + {".xmf"}, + {"audio/midi"}, + "Extensible music file", + REFERENCE_URL, + ""}, + {"general.gif", + {"general.image"}, + {".gif"}, + {"image/gif"}, + "GIF image", + REFERENCE_URL, + ""}, + {"general.djvu-image", + {"general.image"}, + {".djv", ".djvu"}, + {"image/vnd.djvu"}, + "Djvu image", + REFERENCE_URL, + ""}, + {"general.jng-image", + {"general.image"}, + {".jng"}, + {"image/x-jng"}, + "JPEG network graphic", + REFERENCE_URL, + ""}, + {"general.pcx-image", + {"general.image"}, + {".pcx"}, + {"image/vnd.zbrush.pcx"}, + "Paintbrush bitmap image", + REFERENCE_URL, + ""}, + {"general.pbm-image", + {"general.image"}, + {".pbm"}, + {"image/x-portable-bitmap"}, + "Portable bitmap image", + REFERENCE_URL, + ""}, + {"general.pgm-image", + {"general.image"}, + {".pgm"}, + {"image/x-portable-graymap"}, + "Portable gray map image", + REFERENCE_URL, + ""}, + {"general.pnm-image", + {"general.image"}, + {".pnm"}, + {"image/x-portable-anymap"}, + "Portable any map image file", + REFERENCE_URL, + ""}, + {"general.ppm-image", + {"general.image"}, + {".ppm"}, + {"image/x-portable-pixmap"}, + "Portable pixmap image", + REFERENCE_URL, + ""}, + {"general.rgb-image", + {"general.image"}, + {".rgb"}, + {"image/x-rgb"}, + "RGB bitmap", + REFERENCE_URL, + ""}, + {"general.svg-image", + {"general.image"}, + {".svg", ".svgz"}, + {"image/svg+xml"}, + "Scalable vector graphic", + REFERENCE_URL, + ""}, + {"general.wbmp-image", + {"general.image"}, + {".wbmp"}, + {"image/vnd.wap.wbmp"}, + "Wireless bitmap image", + REFERENCE_URL, + ""}, + {"general.xpixmap-image", + {"general.image"}, + {".xpm"}, + {"image/x-xpixmap"}, + "X11 pixmap graphic", + REFERENCE_URL, + ""}, + {"general.xwindowdump-image", + {"general.image"}, + {".xwd"}, + {"image/x-xwindowdump"}, + "X windows dump image", + REFERENCE_URL, + ""}, + {"general.heif", + {"general.image"}, + {".heif", ".heifs", ".hif"}, + {"image/heif"}, + "High efficiency image format", + REFERENCE_URL, + ""}, + {"general.heic", + {"general.image"}, + {".heic", ".heics"}, + {"image/heic"}, + "High efficiency image format", + REFERENCE_URL, + ""}, + {"general.virtual-cd", + {"general.disk-image"}, + {".vcd"}, + {"application/x-cdlink"}, + "Virtual CD", + REFERENCE_URL, + ""}, + {"general.boo-source", + {"general.source-code"}, + {".boo"}, + {"text/x-boo"}, + "Boo source code", + REFERENCE_URL, + ""}, + {"general.d-source", + {"general.source-code"}, + {".d"}, + {"text/x-dsrc"}, + "D source code file", + REFERENCE_URL, + ""}, + {"general.html-component", + {"general.source-code"}, + {".htc"}, + {"text/x-component"}, + "HTML component", + REFERENCE_URL, + ""}, + {"general.pascal-source", + {"general.source-code"}, + {".p", ".pas"}, + {"text/x-pascal"}, + "Pascal source code", + REFERENCE_URL, + ""}, + {"general.haskell-script", + {"general.script"}, + {".hs"}, + {"text/x-haskell"}, + "Haskell script", + REFERENCE_URL, + ""}, + {"general.literate-haskell-script", + {"general.script"}, + {".lhs"}, + {"text/x-literate-haskell"}, + "Literate haskell script", + REFERENCE_URL, + ""}, + {"general.tcl-script", + {"general.script"}, + {".tcl"}, + {"text/x-tcl"}, + "Tcl script", + REFERENCE_URL, + ""}, + {"general.asc-text", + {"general.text"}, + {".asc"}, + {"text/plain"}, + "ASCII text file", + REFERENCE_URL, + ""}, + {"general.portable-object", + {"general.text"}, + {".po"}, + {"text/plain"}, + "Portable object", + REFERENCE_URL, + ""}, + {"general.rich-text", + {"general.text"}, + {".rtf", ".rtx"}, + {"text/rtf", "text/richtext"}, + "Rich text format file", + REFERENCE_URL, + ""}, + {"general.delimited-values-text", + {"general.text"}, + {}, + {}, + "Base type for delimited-values text", + REFERENCE_URL, + ""}, + {"general.comma-separated-values-text", + {"general.delimited-values-text"}, + {".csv"}, + {"text/csv"}, + "Comma-separated values file", + REFERENCE_URL, + ""}, + {"general.diff", + {"general.text"}, + {".diff"}, + {"text/plain"}, + "Patch file", + REFERENCE_URL, + ""}, + {"general.setext", + {"general.text"}, + {".etx"}, + {"text/x-setext"}, + "Structure enhanced Text", + REFERENCE_URL, + ""}, + {"general.gcd", + {"general.text"}, + {".gcd"}, + {"text/x-pcs-gcd"}, + "General content descriptor", + REFERENCE_URL, + ""}, + {"general.tab-separated-values-text", + {"general.delimited-values-text"}, + {".tsv"}, + {"text/tab-separated-values"}, + "Tab-Separated values file", + REFERENCE_URL, + ""}, + {"general.p7r", + {"general.text"}, + {".p7r"}, + {"application/x-pkcs7-certreqresp"}, + "Certificate request response file", + REFERENCE_URL, + ""}, + {"general.pem", + {"general.text"}, + {".pem"}, + {"application/x-pem-file"}, + "Privacy enhanced mail certificate", + REFERENCE_URL, + ""}, + {"general.chess-pgn", + {"general.plain-text"}, + {".pgn"}, + {"application/x-chess-pgn", "application/vnd.chess-pgn"}, + "Portable game notation file", + REFERENCE_URL, + ""}, + {"general.lha-archive", + {"general.archive"}, + {".lha"}, + {"application/x-lha"}, + "LHARC compressed archive", + REFERENCE_URL, + ""}, + {"general.lzh-archive", + {"general.archive"}, + {".lzh"}, + {"application/x-lzh"}, + "LZH compressed file", + REFERENCE_URL, + ""}, + {"general.lzx-archive", + {"general.archive"}, + {".lzx"}, + {"application/x-lzx"}, + "LZX compressed archive", + REFERENCE_URL, + ""}, + {"general.taz-archive", + {"general.tar-archive"}, + {".taz", ".tar.z", ".tz"}, + {"application/x-gtar"}, + "Tar zipped file", + REFERENCE_URL, + ""}, + {"general.shar-archive", + {"general.archive"}, + {".shar"}, + {"application/x-shar"}, + "Unix Shar archive", + REFERENCE_URL, + ""}, + {"general.cpio-archive", + {"general.archive"}, + {".cpio"}, + {"application/x-cpio"}, + "Unix CPIO archive", + REFERENCE_URL, + ""}, + {"general.web-archive", + {"general.archive"}, + {".mht", ".mhtml"}, + {"application/x-mimearchive"}, + "MHTML web archive", + REFERENCE_URL, + ""}, + {"general.ustar", + {"general.archive"}, + {".ustar"}, + {"application/x-ustar"}, + "Uniform standard tape archive format", + REFERENCE_URL, + ""}, + {"general.mathml", + {"general.xml"}, + {".mml"}, + {"text/mathml", "application/mathml+xml"}, + "Mathematical markup language file", + REFERENCE_URL, + ""}, + {"general.xhtml", + {"general.xml"}, + {".xhtml"}, + {"application/xhtml+xml"}, + "XHTML", + REFERENCE_URL, + ""}, + {"general.rss", + {"general.xml"}, + {".rss"}, + {"application/rss+xml"}, + "Rich site summary", + REFERENCE_URL, + ""}, + {"general.rdf", + {"general.xml"}, + {".rdf"}, + {"application/rdf+xml"}, + "Resource description framework file", + REFERENCE_URL, + ""}, + {"general.cad", + {"general.object"}, + {}, + {}, + "Base type for computer-aided design", + REFERENCE_URL, + ""}, + {"general.iges", + {"general.cad"}, + {".iges", ".igs"}, + {"model/iges"}, + "IGES drawing", + REFERENCE_URL, + ""}, + {"general.octet-stream", + {"general.object"}, + {}, + {"application/octet-stream"}, + "Arbitrary binary data", + REFERENCE_URL, + ""}, + {"general.iso", + {"general.disk-image"}, + {".iso"}, + {"application/x-iso9660-image"}, + "Disc image file", + REFERENCE_URL, + ""}, + {"general.mesh-model", + {"general.object"}, + {".msh", ".mesh", ".silo"}, + {"model/mesh"}, + "3D mesh model", + REFERENCE_URL, + ""}, + {"general.certificate", + {"general.object"}, + {}, + {}, + "Base type for security certificate", + REFERENCE_URL, + ""}, + {"general.c-object", + {"general.executable"}, + {".o"}, + {"application/x-object"}, + "Compiled C object file", + REFERENCE_URL, + ""}, + {"general.dvi", + {"general.tex"}, + {".dvi"}, + {"application/x-dvi"}, + "Device independent format file", + REFERENCE_URL, + ""}, + {"general.cer-certificate", + {"general.certificate"}, + {".cer"}, + {"application/pkix-cert"}, + "Internet security certificate", + REFERENCE_URL, + ""}, + {"general.crt-certificate", + {"general.certificate"}, + {".crt"}, + {"application/x-x509-ca-cert", "application/x-x509-server-cert", "application/x-x509-user-cert"}, + "Security Certificate", + REFERENCE_URL, + ""}, + {"general.crl-certificate", + {"general.certificate"}, + {".crl"}, + {"application/x-pkix-crl"}, + "Certificate revocation list file", + REFERENCE_URL, + ""}, + {"general.prn", + {"general.composite-object"}, + {".prn"}, + {}, + "Print to file", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.chart", + {"org.oasis.opendocument", "general.composite-object"}, + {".odc"}, + {"application/vnd.oasis.opendocument.chart"}, + "Open Document chart", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.text-master", + {"org.oasis.opendocument", "general.composite-object"}, + {".odm"}, + {"application/vnd.oasis.opendocument.text-master"}, + "Open Document text master", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.text-web", + {"org.oasis.opendocument", "general.composite-object"}, + {".oth"}, + {"application/vnd.oasis.opendocument.text-web"}, + "Open Document HTML template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.database", + {"org.oasis.opendocument", "general.database"}, + {".odb"}, + {"application/vnd.oasis.opendocument.database"}, + "Open Document database", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.image", + {"org.oasis.opendocument", "general.image"}, + {".odi"}, + {"application/vnd.oasis.opendocument.image"}, + "Open Document image", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.formula-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".otf"}, + {"application/vnd.oasis.opendocument.formula-template"}, + "Open Document formula template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.chart-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".otc"}, + {"application/vnd.oasis.opendocument.chart-template"}, + "Open Document chart template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.presentation-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".otp"}, + {"application/vnd.oasis.opendocument.presentation-template"}, + "Open Document presentation template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.image-template", + {"org.oasis.opendocument", "general.image"}, + {".oti"}, + {"application/vnd.oasis.opendocument.image-template"}, + "Open Document image template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.graphics-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".otg"}, + {"application/vnd.oasis.opendocument.graphics-template"}, + "Open Document graphics template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.spreadsheet-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".ots"}, + {"application/vnd.oasis.opendocument.spreadsheet-template"}, + "Open Document spreadsheet template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.text-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".ott"}, + {"application/vnd.oasis.opendocument.text-template"}, + "Open Document text template", + REFERENCE_URL, + ""}, + {"com.microsoft.word.dot", + {"general.composite-object"}, + {".dot"}, + {"application/msword"}, + "Microsoft Word document template", + REFERENCE_URL, + ""}, + {"com.microsoft.powerpoint.pps", + {"general.composite-object"}, + {".pps"}, + {"application/vnd.ms-powerpoint"}, + "Microsoft PowerPoint slide show", + REFERENCE_URL, + ""}, + {"com.microsoft.powerpoint.pot", + {"general.composite-object"}, + {".pot"}, + {"application/vnd.ms-powerpoint"}, + "Microsoft PowerPoint Template", + REFERENCE_URL, + ""}, + {"com.microsoft.excel.xlt", + {"general.composite-object"}, + {".xlt"}, + {"application/vnd.ms-excel"}, + "Microsoft Excel spreadsheet template", + REFERENCE_URL, + ""}, + {"com.microsoft.visio.vsd", + {"general.composite-object"}, + {".vsd"}, + {"application/vnd.visio"}, + "Microsoft Office Visio 2003-2010 drawing", + REFERENCE_URL, + ""}, + {"org.openxmlformats.drawingml.visio", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".vsdx"}, + {"application/vnd.openxmlformats-officedocument.drawingml.drawing"}, + "Microsoft Visio drawing", + REFERENCE_URL, + ""}, + {"org.openxmlformats.drawingml.template", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".vstx"}, + {}, + "Microsoft Visio drawing template", + REFERENCE_URL, + ""}, + {"org.openxmlformats.drawingml.visio.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".vsdm"}, + {}, + "Visio macro-enabled drawing", + REFERENCE_URL, + ""}, + {"org.openxmlformats.drawingml.template.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".vstm"}, + {}, + "Visio macro-enabled drawing template", + REFERENCE_URL, + ""}, + {"org.openxmlformats.wordprocessingml.template", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".dotx"}, + {"application/vnd.openxmlformats-officedocument.wordprocessingml.template"}, + "Office Open XML document template.", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.template", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".potx"}, + {"application/vnd.openxmlformats-officedocument.presentationml.template"}, + "Office Open XML presentation template", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.slideshow", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".ppsx"}, + {"application/vnd.openxmlformats-officedocument.presentationml.slideshow"}, + "Office Open XML slide show", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.template", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".xltx"}, + {"application/vnd.openxmlformats-officedocument.spreadsheetml.template"}, + "Office Open XML spreadsheet template", + REFERENCE_URL, + ""}, + {"org.openxmlformats.wordprocessingml.document.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".docm"}, + {"application/vnd.ms-word.document.macroEnabled.12"}, + "Office Open XML word processing document (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.wordprocessingml.template.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".dotm"}, + {"application/vnd.ms-word.template.macroEnabled.12"}, + "Office Open XML word processing template (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.template.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".xltm"}, + {"application/vnd.ms-excel.template.macroEnabled.12"}, + "Office Open XML spreadsheet template (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.addin.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".xlam"}, + {"application/vnd.ms-excel.addin.macroEnabled.12"}, + "Office Open XML spreadsheet addin (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.binary.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".xlsb"}, + {"application/vnd.ms-excel.sheet.binary.macroEnabled.12"}, + "Office Open XML spreadsheet binary (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.sheet.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".xlsm"}, + {"application/vnd.ms-excel.sheet.macroEnabled.12"}, + "Office Open XML spreadsheet (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.addin.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".ppam"}, + {"application/vnd.ms-powerpoint.addin.macroEnabled.12"}, + "Office Open XML presentation addin (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.presentation.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".pptm"}, + {"application/vnd.ms-powerpoint.presentation.macroEnabled.12"}, + "Office Open XML presentation (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.slideshow.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".ppsm"}, + {"application/vnd.ms-powerpoint.slideshow.macroEnabled.12"}, + "Office Open XML slide show (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.template.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".potm"}, + {"application/vnd.ms-powerpoint.template.macroEnabled.12"}, + "Office Open XML presentation template (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openoffice", + {"general.archive"}, + {}, + {}, + "OpenOffice document format for open-source office software suite", + REFERENCE_URL, + ""}, + {"org.openoffice.calc", + {"org.openoffice", "general.composite-object"}, + {".sxc"}, + {"application/vnd.sun.xml.calc"}, + "StarOffice Calc spreadsheet", + REFERENCE_URL, + ""}, + {"org.openoffice.draw", + {"org.openoffice", "general.composite-object"}, + {".sxd"}, + {"application/vnd.sun.xml.draw"}, + "StarOffice Drawing", + REFERENCE_URL, + ""}, + {"org.openoffice.writer-global", + {"org.openoffice", "general.composite-object"}, + {".sxg"}, + {"application/vnd.sun.xml.writer.global"}, + "Apache OpenOffice master document", + REFERENCE_URL, + ""}, + {"org.openoffice.impress", + {"org.openoffice", "general.composite-object"}, + {".sxi"}, + {"application/vnd.sun.xml.impress"}, + "StarOffice Impress presentation", + REFERENCE_URL, + ""}, + {"org.openoffice.math", + {"org.openoffice", "general.composite-object"}, + {".sxm"}, + {"application/vnd.sun.xml.math"}, + "StarMath Formula", + REFERENCE_URL, + ""}, + {"org.openoffice.writer", + {"org.openoffice", "general.composite-object"}, + {".sxw"}, + {"application/vnd.sun.xml.writer"}, + "StarOffice Writer document", + REFERENCE_URL, + ""}, + {"org.openoffice.calc.template", + {"org.openoffice", "general.composite-object"}, + {".stc"}, + {"application/vnd.sun.xml.calc.template"}, + "StarOffice Calc spreadsheet template", + REFERENCE_URL, + ""}, + {"org.openoffice.draw.template", + {"org.openoffice", "general.composite-object"}, + {".std"}, + {"application/vnd.sun.xml.draw.template"}, + "Apache OpenOffice Drawing template", + REFERENCE_URL, + ""}, + {"org.openoffice.impress.template", + {"org.openoffice", "general.composite-object"}, + {".sti"}, + {"application/vnd.sun.xml.impress.template"}, + "StarOffice Presentation template", + REFERENCE_URL, + ""}, + {"org.openoffice.writer.template", + {"org.openoffice", "general.composite-object"}, + {".stw"}, + {"application/vnd.sun.xml.writer.template"}, + "StarOffice Document template", + REFERENCE_URL, + ""}, + {"com.staroffice", + {"general.archive"}, + {}, + {}, + "StarOffice document format", + REFERENCE_URL, + ""}, + {"com.staroffice.draw", + {"com.staroffice", "general.composite-object"}, + {".sda"}, + {"application/vnd.stardivision.draw"}, + "StarOffice Drawing", + REFERENCE_URL, + ""}, + {"com.staroffice.calc", + {"com.staroffice", "general.composite-object"}, + {".sdc"}, + {"application/vnd.stardivision.calc"}, + "StarOffice Calc spreadsheet", + REFERENCE_URL, + ""}, + {"com.staroffice.impress", + {"com.staroffice", "general.composite-object"}, + {".sdd", ".sdp"}, + {"application/vnd.stardivision.impress"}, + "StarOffice Presentation", + REFERENCE_URL, + ""}, + {"com.staroffice.writer", + {"com.staroffice", "general.composite-object"}, + {".sdw"}, + {"application/vnd.stardivision.writer"}, + "StarOffice Writer text document", + REFERENCE_URL, + ""}, + {"com.staroffice.chart", + {"com.staroffice", "general.composite-object"}, + {".sds"}, + {"application/vnd.stardivision.chart"}, + "StarOffice Chart", + REFERENCE_URL, + ""}, + {"com.staroffice.mail", + {"com.staroffice", "general.composite-object"}, + {".sdm"}, + {"application/vnd.stardivision.mail"}, + "StarOffice Mail message", + REFERENCE_URL, + ""}, + {"com.staroffice.writer-global", + {"com.staroffice", "general.composite-object"}, + {".sgl"}, + {"application/vnd.stardivision.writer-global"}, + "StarOffice Master document", + REFERENCE_URL, + ""}, + {"com.staroffice.math", + {"com.staroffice", "general.composite-object"}, + {".smf"}, + {"application/vnd.stardivision.math"}, + "StarMath Formula file", + REFERENCE_URL, + ""}, + {"com.staroffice.template", + {"com.staroffice", "general.composite-object"}, + {".vor"}, + {"application/vnd.stardivision.template"}, + "StarOffice Template", + REFERENCE_URL, + ""}, + {"org.tug.bib", + {"general.tex"}, + {".bib"}, + {"text/x-bibtex"}, + "TeX Bibliography file", + REFERENCE_URL, + ""}, + {"org.tug.cls", + {"general.tex"}, + {".cls"}, + {"text/x-tex"}, + "TeX Class file", + REFERENCE_URL, + ""}, + {"org.tug.sty", + {"general.tex"}, + {".sty"}, + {"text/x-tex"}, + "TeX Style file", + REFERENCE_URL, + ""}, + {"org.tug.tex", + {"general.tex"}, + {".tex"}, + {"text/x-tex"}, + "TeX source document file", + REFERENCE_URL, + ""}, + {"org.latex-project.latex", + {"general.tex"}, + {".ltx", ".latex"}, + {"application/x-latex"}, + "LaTeX source document file", + REFERENCE_URL, + ""}, + {"org.matroska.mkv", + {"general.video"}, + {".mkv"}, + {"video/x-matroska"}, + "Matroska video", + REFERENCE_URL, + ""}, + {"org.matroska.mka", + {"general.audio"}, + {".mka"}, + {"audio/x-matroska"}, + "Matroska audio", + REFERENCE_URL, + ""}, + {"com.sgi.movie", + {"general.video"}, + {".movie"}, + {"video/x-sgi-movie"}, + "SGI movie", + REFERENCE_URL, + ""}, + {"com.apple.m4v", + {"general.video"}, + {".m4v"}, + {"video/m4v"}, + "M4V video", + REFERENCE_URL, + ""}, + {"org.webmproject.webm", + {"general.video"}, + {".webm"}, + {"video/webm"}, + "WebM is an audiovisual media file format", + REFERENCE_URL, + ""}, + {"com.apple.quicktime-movie", + {"general.video"}, + {".mov", ".qt", ".movie"}, + {"video/quicktime"}, + "QuickTime File Format", + REFERENCE_URL, + ""}, + {"com.coreldraw.cdr", + {"general.image"}, + {".cdr"}, + {"image/x-coreldraw"}, + "CorelDRAW file", + REFERENCE_URL, + ""}, + {"com.coreldraw.cdt", + {"general.image"}, + {".cdt"}, + {"image/x-coreldrawtemplate"}, + "CorelDRAW template", + REFERENCE_URL, + ""}, + {"com.coreldraw.cpt", + {"general.image"}, + {".cpt"}, + {"image/x-corelphotopaint"}, + "Corel PHOTO-PAINT image", + REFERENCE_URL, + ""}, + {"com.coreldraw.pat", + {"general.image"}, + {".pat"}, + {"image/x-coreldrawpattern"}, + "CorelDRAW pattern file", + REFERENCE_URL, + ""}, + {"com.microsoft.cur", + {"general.image"}, + {".cur"}, + {"image/ico"}, + "Microsoft Windows cursor image", + REFERENCE_URL, + ""}, + {"com.sun.raster", + {"general.image"}, + {".ras"}, + {"image/x-cmu-raster"}, + "Sun Raster Graphic", + REFERENCE_URL, + ""}, + {"com.google.webp", + {"general.image"}, + {".webp"}, + {"image/webp"}, + "WebP image", + REFERENCE_URL, + ""}, + {"com.sseyo.koan-audio", + {"general.audio"}, + {".skd", ".skm", ".skp", ".skt"}, + {"application/x-koan"}, + "Koan music files over the internet", + REFERENCE_URL, + ""}, + {"io.qt.moc", + {"general.source-code"}, + {".moc"}, + {"text/x-moc"}, + "Qt Meta-Object compiler file", + REFERENCE_URL, + ""}, + {"com.ghostscript.font", + {"general.font"}, + {".gsf"}, + {"application/x-font"}, + "Ghostscript font", + REFERENCE_URL, + ""}, + {"org.x.pcf-font", + {"general.font"}, + {".pcf"}, + {"application/x-font", "application/x-font-pcf"}, + "Portable compiled format", + REFERENCE_URL, + ""}, + {"com.microsoft.windows-media-wmd", + {"com.microsoft.advanced-systems-format", "general.zip-archive"}, + {".wmd"}, + {"application/x-ms-wmd"}, + "Windows media download package", + REFERENCE_URL, + ""}, + {"com.microsoft.windows-media-wmz", + {"com.microsoft.advanced-systems-format", "general.zip-archive"}, + {".wmz"}, + {"application/x-ms-wmz"}, + "Windows media player skin package", + REFERENCE_URL, + ""}, + {"com.microsoft.windows-installer", + {"general.executable"}, + {".msi"}, + {"application/x-msi"}, + "Windows installer package", + REFERENCE_URL, + ""}, + {"com.microsoft.publisher.pub", + {"general.composite-object"}, + {".pub"}, + {"application/x-mspublisher"}, + "Publisher document", + REFERENCE_URL, + ""}, + {"com.microsoft.windows-media-playlist", + {"general.xml", "general.media"}, + {".wpl"}, + {"application/vnd.ms-wpl"}, + "Windows media player playlist", + REFERENCE_URL, + ""}, + {"com.microsoft.access.mdb", + {"general.database"}, + {".mdb"}, + {"application/msaccess"}, + "Microsoft Access database", + REFERENCE_URL, + ""}, + {"com.3dsystems.stereolithography", + {"general.composite-object"}, + {".stl"}, + {"application/vnd.ms-pki.stl"}, + "Stereolithography file", + REFERENCE_URL, + ""}, + {"com.apple.media.playlist", + {"general.media"}, + {".m3u8"}, + {"application/vnd.apple.mpegurl"}, + "UTF-8 M3U playlist", + REFERENCE_URL, + ""}, + {"com.abisource.word", + {"general.composite-object"}, + {".abw"}, + {"application/x-abiword"}, + "AbiWord document", + REFERENCE_URL, + ""}, + {"com.adobe.framemaker", + {"general.composite-object"}, + {".book", ".fm", ".frame", ".maker"}, + {"application/x-maker"}, + "FrameMaker book file", + REFERENCE_URL, + ""}, + {"com.wolfram.cdf", + {"general.composite-object"}, + {".cdf"}, + {"application/x-cdf"}, + "Computable document format file", + REFERENCE_URL, + ""}, + {"de.cinderella.cdy", + {"general.composite-object"}, + {".cdy"}, + {"application/vnd.cinderella"}, + "Cinderella construction file", + REFERENCE_URL, + ""}, + {"com.adobe.dcr", + {"general.video"}, + {".dcr"}, + {"application/x-director"}, + "Shockwave media file", + REFERENCE_URL, + ""}, + {"com.adobe.dir", + {"general.video"}, + {".dir"}, + {"application/x-director"}, + "Adobe Director movie", + REFERENCE_URL, + ""}, + {"com.adobe.dxr", + {"general.video"}, + {".dxr"}, + {"application/x-director"}, + "Protected macromedia director movie", + REFERENCE_URL, + ""}, + {"org.gnumeric.spreadsheet", + {"general.xml"}, + {".gnumeric"}, + {"application/x-gnumeric"}, + "Gnumeric spreadsheet", + REFERENCE_URL, + ""}, + {"org.hdfgroup.hdf", + {"general.composite-object"}, + {".hdf"}, + {"application/x-hdf"}, + "Hierarchical data format", + REFERENCE_URL, + ""}, + {"com.apple.binhex-archive", + {"general.archive"}, + {".hqx"}, + {"application/mac-binhex40"}, + "BinHex 4.0 encoded file", + REFERENCE_URL, + ""}, + {"com.microsoft.hta", + {"general.archive", "general.executable"}, + {".hta"}, + {"application/hta"}, + "HTML application", + REFERENCE_URL, + ""}, + {"com.microsoft.internet.ins", + {"general.text"}, + {".ins"}, + {"application/x-internet-signup"}, + "Internet settings file", + REFERENCE_URL, + ""}, + {"com.microsoft.internet.isp", + {"general.text"}, + {".isp"}, + {"application/x-internet-signup"}, + "IIS internet service provider settings", + REFERENCE_URL, + ""}, + {"org.troff", + {"general.text"}, + {".man", ".t", ".roff"}, + {"text/troff"}, + "Unix troff format", + REFERENCE_URL, + ""}, + {"com.adobe.framemaker.mif", + {"general.composite-object"}, + {".mif"}, + {"application/vnd.mif"}, + "FrameMaker interchange format file", + REFERENCE_URL, + ""}, + {"io.sourceforge.freemind", + {"general.composite-object"}, + {".mm"}, + {"application/x-freemind"}, + "Mind Map file", + REFERENCE_URL, + ""}, + {"com.yamaha.smaf", + {"general.audio"}, + {".mmf"}, + {"application/vnd.smaf"}, + "Synthetic music mobile application file", + REFERENCE_URL, + ""}, + {"com.wolfram.mathematica.notebook", + {"general.text"}, + {".nb"}, + {"application/mathematica"}, + "Mathematica notebook", + REFERENCE_URL, + ""}, + {"org.xiph.ogg", + {"general.audio"}, + {".oga", ".ogg"}, + {"application/ogg"}, + "Ogg vorbis audio", + REFERENCE_URL, + ""}, + {"com.netscape.proxy-autoconfig", + {"general.plain-text"}, + {".pac"}, + {"application/x-ns-proxy-autoconfig"}, + "Proxy auto-config file", + REFERENCE_URL, + ""}, + {"com.rsa.pkcs-12", + {"general.archive"}, + {".pfx", ".p12"}, + {"application/x-pkcs12"}, + "PKCS #12 certificate file", + REFERENCE_URL, + ""}, + {"org.openpgp.signature", + {"general.object"}, + {".pgp"}, + {"application/pgp-signature"}, + "PGP security key", + REFERENCE_URL, + ""}, + {"com.apple.quicktime-link", + {"general.text"}, + {".qtl"}, + {"application/x-quicktimeplayer"}, + "QuickTime link file", + REFERENCE_URL, + ""}, + {"com.rarlab.rar-archive", + {"general.archive"}, + {".rar"}, + {"application/rar", "application/vnd.rar"}, + "WinRAR compressed archive", + REFERENCE_URL, + ""}, + {"org.7-zip.7-zip-archive", + {"general.archive"}, + {".7z"}, + {"application/x-7z-compressed"}, + "7-zip compressed archive", + REFERENCE_URL, + ""}, + {"com.red-bean.sgf", + {"general.text"}, + {".sgf"}, + {"application/x-go-sgf"}, + "Smart game format file", + REFERENCE_URL, + ""}, + {"com.stuffit.sit-archive", + {"general.archive"}, + {".sit"}, + {"application/x-stuffit"}, + "Stuffit archive", + REFERENCE_URL, + ""}, + {"com.adobe.futuresplash", + {"general.video"}, + {".spl"}, + {"application/futuresplash", "application/x-futuresplash"}, + "FutureSplash animation", + REFERENCE_URL, + ""}, + {"com.adobe.flash", + {"general.video"}, + {".swf", ".flv"}, + {"application/x-shockwave-flash", "video/x-flv"}, + "Shockwave flash movie", + REFERENCE_URL, + ""}, + {"org.gnu.texinfo", + {"general.source-code"}, + {".texinfo", ".texi"}, + {"application/x-texinfo"}, + "GNU Texinfo", + REFERENCE_URL, + ""}, + {"org.bittorrent.torrent", + {"general.text"}, + {".torrent"}, + {"application/x-bittorrent"}, + "BitTorrent file", + REFERENCE_URL, + ""}, + {"com.idsoftware.doom", + {"general.archive"}, + {".wad"}, + {"application/x-doom"}, + "Doom WAD file", + REFERENCE_URL, + ""}, + {"com.apple.webarchive", + {"general.archive"}, + {".webarchive"}, + {"application/x-webarchive"}, + "Safari web archive", + REFERENCE_URL, + ""}, + {"com.android.webarchive", + {"general.archive"}, + {".webarchivexml"}, + {"application/x-webarchive-xml"}, + "Android web browser archive", + REFERENCE_URL, + ""}, + {"org.gimp.xcf", + {"general.image"}, + {".xcf"}, + {"application/x-xcf", "image/x-xcf"}, + "eXperimental computing facility, GIMP image file", + REFERENCE_URL, + ""}, + {"com.edrawsoft.edrawmax", + {"general.composite-object"}, + {".eddx"}, + {"application/x-eddx"}, + "Edraw Max XML file", + REFERENCE_URL, + ""}, + {"com.edrawsoft.edrawmind", + {"general.composite-object"}, + {".emmx"}, + {"application/x-emmx"}, + "Edraw MindMaster XML file", + REFERENCE_URL, + ""}, + {"net.cnki.caj", + {"general.composite-object"}, + {".caj"}, + {"application/caj"}, + "Chinese academic journal file", + REFERENCE_URL, + ""}, + {"com.dbase.dbf", + {"general.database"}, + {".dbf"}, + {"application/dbf", "application/dbase"}, + "Database file", + REFERENCE_URL, + ""}, + {"com.autodesk.dwg", + {"general.composite-object"}, + {".dwg"}, + {"image/vnd.dwg"}, + "AutoCAD drawing", + REFERENCE_URL, + ""}, + {"com.autodesk.dxf", + {"general.composite-object"}, + {".dxf"}, + {"image/vnd.dxf"}, + "Drawing exchange format file", + REFERENCE_URL, + ""}, + {"com.autodesk.dws", + {"general.composite-object"}, + {".dws"}, + {}, + "AutoCAD drawing standards file", + REFERENCE_URL, + ""}, + {"com.autodesk.dwt", + {"general.composite-object"}, + {".dwt"}, + {}, + "AutoCAD drawing template", + REFERENCE_URL, + ""}, + {"com.autodesk.dwf", + {"general.composite-object"}, + {".dwf"}, + {"model/vnd.dwf"}, + "Design web format file", + REFERENCE_URL, + ""}, + {"com.autodesk.dwfx", + {"general.composite-object"}, + {".dwfx"}, + {}, + "Design web format XPS file", + REFERENCE_URL, + ""}, + {"com.autodesk.shp", + {"general.composite-object"}, + {".shp"}, + {}, + "3D studio shape", + REFERENCE_URL, + ""}, + {"com.autodesk.shx", + {"general.composite-object"}, + {".shx"}, + {}, + "AutoCAD compiled shape file", + REFERENCE_URL, + ""}, + {"com.autodesk.slide-library", + {"general.composite-object"}, + {".slb"}, + {}, + "AutoCAD slide library", + REFERENCE_URL, + ""}, + {"com.autodesk.line", + {"general.text"}, + {".lin"}, + {}, + "AutoCAD linetype file", + REFERENCE_URL, + ""}, + {"com.autodesk.plotter", + {"general.composite-object"}, + {".plt"}, + {}, + "AutoCAD plotter document", + REFERENCE_URL, + ""}, + {"com.hp.graphics-language", + {"general.composite-object"}, + {".hpgl"}, + {"application/vnd.hp-hpgl"}, + "HP graphics language plotter file", + REFERENCE_URL, + ""}, + {"com.microsoft.metafile", + {"general.composite-object"}, + {".wmf"}, + {}, + "Windows metafile", + REFERENCE_URL, + ""}, + {"com.spatial.acis.sat", + {"general.text"}, + {".sat"}, + {}, + "ACIS SAT 3D model", + REFERENCE_URL, + ""}, + {"org.aomedia.avif-image", + {"general.image"}, + {".avif"}, + {"image/avif"}, + "AVIF image", + REFERENCE_URL, + ""}, + {"com.microsoft.dds", + {"general.image"}, + {".dds"}, + {"image/vnd-ms.dds"}, + "DirectDraw surface image", + REFERENCE_URL, + ""}, + {"com.ea.iff-ilbm", + {"general.image"}, + {".ilbm"}, + {"image/x-ilbm"}, + "Interleaved bitmap image", + REFERENCE_URL, + ""}, + {"com.canon.cr2-raw-image", + {"general.raw-image"}, + {".cr2"}, + {"image/x-canon-cr2"}, + "Canon raw 2 image", + REFERENCE_URL, + ""}, + {"com.canon.cr3-raw-image", + {"general.raw-image"}, + {".cr3"}, + {"image/x-canon-cr3"}, + "Canon raw 3 image", + REFERENCE_URL, + ""}, + {"com.canon.crw-raw-image", + {"general.raw-image"}, + {".crw"}, + {"image/x-canon-crw"}, + "Canon raw CIFF image file", + REFERENCE_URL, + ""}, + {"com.adobe.dng-raw-image", + {"general.raw-image"}, + {".dng"}, + {"image/x-adobe-dng"}, + "Digital negative image", + REFERENCE_URL, + ""}, + {"com.sony.arw-raw-image", + {"general.raw-image"}, + {".arw"}, + {"image/x-sony-arw"}, + "Sony alpha raw digital camera image", + REFERENCE_URL, + ""}, + {"com.nikon.nef-raw-image", + {"general.raw-image"}, + {".nef"}, + {"image/x-nikon-nef"}, + "Nikon electronic format RAW image", + REFERENCE_URL, + ""}, + {"com.mindjet.mindmanager.mmap", + {"general.composite-object"}, + {".mmap"}, + {}, + "MindManager Map", + REFERENCE_URL, + ""}, + {"com.microsoft.email", + {"general.message"}, + {".eml"}, + {"message/rfc822"}, + "E-Mail message", + REFERENCE_URL, + ""}, + {"com.microsoft.message", + {"general.message"}, + {".msg"}, + {}, + "Outlook message item file", + REFERENCE_URL, + ""}, + {"com.microsoft.pst", + {"general.archive"}, + {".pst"}, + {}, + "Outlook personal information store", + REFERENCE_URL, + ""}, + {"com.kingsoft.office", + {"general.archive"}, + {}, + {}, + "Kingsoft office suite", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.writer.wps", + {"com.kingsoft.office", "general.composite-object"}, + {".wps"}, + {}, + "Kingsoft Writer document", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.writer.wpt", + {"com.kingsoft.office", "general.composite-object"}, + {".wpt"}, + {}, + "Kingsoft Writer template", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.presentation.dps", + {"com.kingsoft.office", "general.composite-object"}, + {".dps"}, + {}, + "Kingsoft Presentation file", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.presentation.template", + {"com.kingsoft.office", "general.composite-object"}, + {".dpt"}, + {}, + "Kingsoft Presentation template", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.spreadsheets.et", + {"com.kingsoft.office", "general.composite-object"}, + {".et"}, + {}, + "Kingsoft Spreadsheets tile", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.spreadsheets.template", + {"com.kingsoft.office", "general.composite-object"}, + {".ett"}, + {}, + "Kingsoft Spreadsheets template", + REFERENCE_URL, + ""}, + {"com.microsoft.ini", + {"general.text"}, + {".ini"}, + {}, + "Windows Initialization File", + REFERENCE_URL, + ""}, + {"general.json", + {"general.script"}, + {".json"}, + {"application/json"}, + "JavaScript Object Notation File", + REFERENCE_URL, + ""}, + {"general.yaml", + {"general.script"}, + {".yaml", ".yml"}, + {"application/yaml"}, + "YAML Document", + REFERENCE_URL, + ""}, + {"general.log", + {"general.text"}, + {".log"}, + {"text/plain"}, + "Log File", + REFERENCE_URL, + ""}, + {"general.uri", + {"general.object"}, + {}, + {}, + "Universal Resource Identifier", + REFERENCE_URL, + ""}, + {"general.file-uri", + {"general.uri"}, + {}, + {}, + "File URI", + REFERENCE_URL, + ""}, + {"general.text-lst", + {"general.plain-text"}, + {".lst"}, + {}, + "Data List", + REFERENCE_URL, + ""}, + {"com.android.apk", + {"general.archive"}, + {".apk", ".apks", ".aab", ".xapk", ".apkm", ".akp"}, + {"application/vnd.android.package-archive"}, + "Android Package File", + REFERENCE_URL, + ""}, + {"com.adobe.postscript-pfb-font", + {"com.adobe.postscript-font"}, + {".pfb"}, + {"application/x-font"}, + "Printer Font Binary, PostScript Type 1 outline font.", + REFERENCE_URL, + ""}, + {"com.adobe.postscript-pfa-font", + {"com.adobe.postscript-font"}, + {".pfa"}, + {"application/x-font"}, + "Printer Pont ASCII file, PostScript Type 1 outline font.", + REFERENCE_URL, + ""}, + {"general.bz-archive", + {"general.archive"}, + {".bz"}, + {"application/x-bzip"}, + "Bzip Compressed File", + REFERENCE_URL, + ""}, + {"general.tar-bzip-archive", + {"general.bz-archive"}, + {".tbz"}, + {"application/x-bzip-compressed-tar"}, + "Bzip Compressed Tar Archive", + REFERENCE_URL, + ""}, + {"general.tar-bzip2-archive", + {"general.bz2-archive"}, + {".tbz2"}, + {"application/x-bzip2-compressed-tar"}, + "Bzip2-Compressed TAR File", + REFERENCE_URL, + ""}, + {"org.tukaani.xz-archive", + {"general.archive"}, + {".xz"}, + {"application/x-xz"}, + "XZ Compressed Archive", + REFERENCE_URL, + ""}, + {"org.tukaani.tar-xz-archive", + {"org.tukaani.xz-archive"}, + {".txz"}, + {"application/x-xz-compressed-tar"}, + "XZ Compressed Tar Archive", + REFERENCE_URL, + ""}, + {"general.xar-archive", + {"general.archive"}, + {".xar"}, + {"application/x-xar"}, + "Extensible Archive Fromat", + REFERENCE_URL, + ""}, + {"com.microsoft.cab-archive", + {"general.archive"}, + {".cab"}, + {"application/vnd.ms-cab-compressed"}, + "Windows Cabinet File", + REFERENCE_URL, + ""}, + {"redhat.rpm-archive", + {"general.archive"}, + {".rpm"}, + {"application/x-rpm"}, + "RedHat Package Manager File", + REFERENCE_URL, + ""}, + {"org.godotengine.tpz-archive", + {"general.archive"}, + {".tpz"}, + {}, + "Godot Engine Export Template Archive", + REFERENCE_URL, + ""}, + {"general.lza-archive", + {"general.archive"}, + {".lza"}, + {"application/x-lzh-compressed"}, + "LZA Compressed Archive", + REFERENCE_URL, + ""}, + {"general.arj-archive", + {"general.archive"}, + {".arj"}, + {"application/x-arj"}, + "ARJ Compressed File Archive", + REFERENCE_URL, + ""}, + {"com.winzip.zipx", + {"general.archive"}, + {".zipx"}, + {}, + "Extended Zip Archive", + REFERENCE_URL, + ""}, + {"general.lzma-archive", + {"general.archive"}, + {".lzma"}, + {"application/x-lzma"}, + "LZMA Compressed File", + REFERENCE_URL, + ""}, + {"general.lzma86-archive", + {"general.archive"}, + {".lzma86"}, + {}, + "LZMA86 Compressed File", + REFERENCE_URL, + ""}, + {"org.mozilla.xpinstall", + {"general.archive"}, + {".xpi"}, + {"application/x-xpinstall"}, + "Cross-platform Installer Package", + REFERENCE_URL, + ""}, + {"general.hfs-disk-image", + {"general.disk-image"}, + {".hfs"}, + {}, + "HFS Disk Image File", + REFERENCE_URL, + ""}, + {"general.img-disk-image", + {"general.disk-image"}, + {".img"}, + {"application/x-raw-disk-image"}, + "Disc Image Data File", + REFERENCE_URL, + ""}, + {"com.ezbsystems.zipped-iso", + {"general.disk-image"}, + {".isz"}, + {}, + "Zipped ISO Disk Image", + REFERENCE_URL, + ""}, + {"com.microsoft.wim", + {"general.disk-image"}, + {".wim"}, + {"application/x-ms-wim"}, + "Windows Imaging Format File", + REFERENCE_URL, + ""}, + {"com.microsoft.swm", + {"general.disk-image"}, + {".swm"}, + {"application/x-ms-wim"}, + "Split Windows Imaging Format", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.spreadsheets.etx", + {"com.kingsoft.office", "general.composite-object"}, + {".etx"}, + {}, + "Kingsoft Spreadsheets File", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.spreadsheets.ettx", + {"com.kingsoft.office", "general.composite-object"}, + {".ettx"}, + {}, + "Kingsoft Spreadsheets Template", + REFERENCE_URL, + ""}, + {"com.microsoft.excel.dif", + {"general.composite-object"}, + {".dif"}, + {}, + "Data interchange format", + REFERENCE_URL, + ""}, + {"openharmony.app", + {"openharmony.package"}, + {".app"}, + {}, + "OpenHarmony system defined application package", + REFERENCE_URL, + ""}, + {"com.huawei.hmos.settings.wifi", + {"general.text"}, + {".hmoswifi"}, + {}, + "HarmonyOS WIFI sharing setting", + REFERENCE_URL, + ""}, + {"general.tel", + {"general.text"}, + {".tel"}, + {}, + "TEL schematic diagram file format", + REFERENCE_URL, + ""}, + {"general.ets", + {"general.script"}, + {".ets"}, + {}, + "Extended TypeScript source code", + REFERENCE_URL, + ""}, + {"general.json5", + {"general.script"}, + {".json5"}, + {}, + "JSON5 data interchange format", + REFERENCE_URL, + ""}, + {"com.monkeysaudio.ape-audio", + {"general.audio"}, + {".ape"}, + {"audio/x-monkeys-audio"}, + "Monkey's Audio", + REFERENCE_URL, + ""}, + {"org.xiph.opus-audio", + {"general.audio"}, + {".opus"}, + {"audio/opus"}, + "Opus Audio", + REFERENCE_URL, + ""}, + {"general.conf", + {"general.text"}, + {".conf"}, + {}, + "Generic Configuration File", + REFERENCE_URL, + ""}, + {"com.microsoft.dos-batch", + {"general.script"}, + {".bat"}, + {"application/x-bat"}, + "DOS Batch File", + REFERENCE_URL, + ""}, + {"com.microsoft.vbscript", + {"general.script"}, + {".vbs"}, + {"application/x-vbs"}, + "VBScript File", + REFERENCE_URL, + ""}, + {"general.ion", + {"general.text"}, + {".ion"}, + {}, + "File Description File", + REFERENCE_URL, + ""}, + {"com.microsoft.registry", + {"general.database"}, + {".reg"}, + {}, + "Registry File", + REFERENCE_URL, + ""}, + {"com.microsoft.catalog", + {"general.object"}, + {".cat"}, + {}, + "Windows Catalog File", + REFERENCE_URL, + ""}, + {"com.microsoft.powershell-script", + {"general.script"}, + {".ps1"}, + {}, + "Windows PowerShell Cmdlet File", + REFERENCE_URL, + ""}, + {"org.w3.woff", + {"general.font"}, + {".woff"}, + {"font/woff"}, + "Web Open Font Format File", + REFERENCE_URL, + ""}, + {"org.sqlite.database", + {"general.database"}, + {".sqlite", ".sqlite3", ".db", ".db3", ".s3db", ".sl3"}, + {"application/vnd.sqlite3"}, + "SQLite Database", + REFERENCE_URL, + ""}, + {"com.microsoft.sys", + {"general.object"}, + {".sys"}, + {}, + "Windows System File", + REFERENCE_URL, + ""}, + {"com.microsoft.inf", + {"general.text"}, + {".inf"}, + {"text/plain"}, + "Setup Information File", + REFERENCE_URL, + ""}, + {"com.microsoft.pdb", + {"general.database"}, + {".pdb"}, + {"application/x-ms-pdb"}, + "Program Database", + REFERENCE_URL, + ""}, + {"com.microsoft.tlb", + {"general.object"}, + {".tlb"}, + {}, + "OLE Type Library", + REFERENCE_URL, + ""}, + {"com.microsoft.sccd", + {"general.xml"}, + {".sccd"}, + {}, + "Signed Custom Capability Descriptor", + REFERENCE_URL, + ""}, + {"com.adobe.f4v", + {"general.video"}, + {".f4v"}, + {"video/mp4"}, + "Flash MP4 Video File", + REFERENCE_URL, + ""}, + {"general.mp2t", + {"general.video"}, + {".m2ts", ".mts", ".m2t"}, + {"video/mp2t"}, + "Blu-ray BDAV Video File Format", + REFERENCE_URL, + ""}, + {"com.youtube.video", + {"general.video"}, + {".yt", ".vt"}, + {"video/vnd.youtube.yt"}, + "Youtube Video format", + REFERENCE_URL, + ""}, + {"com.cisco.webex-video", + {"general.video"}, + {".wrf"}, + {"video/x-webex"}, + "WebEx Recording", + REFERENCE_URL, + ""}, + {"general.mpeg-2", + {"general.video"}, + {".mpeg2", ".mpv2", ".mp2v", ".m2v", ".mpv"}, + {"video/mpeg"}, + "MPEG-2 Video format", + REFERENCE_URL, + ""}, + {"general.mpeg-1", + {"general.video"}, + {".mpeg1", ".mpv1", ".mp1v", ".m1v"}, + {"video/mpeg"}, + "MPEG-1 Video format", + REFERENCE_URL, + ""}, + {"com.real.realmedia-vbr", + {"general.video"}, + {".rmvb"}, + {"application/vnd.rn-realmedia-vbr"}, + "RealMedia Variable Bit Rate Format", + REFERENCE_URL, + ""}, + {"com.real.realvideo", + {"general.video"}, + {".rv"}, + {"video/x-pn-realvideo"}, + "RealVideo Format", + REFERENCE_URL, + ""}, + {"general.divx-video", + {"general.video"}, + {".divx"}, + {"video/divx"}, + "DivX-Encoded Movie", + REFERENCE_URL, + ""}, + {"org.csiro.annodex", + {"general.video"}, + {".axv"}, + {"video/annodex"}, + "Annodex Video Format", + REFERENCE_URL, + ""}, + {"general.ogv", + {"general.video"}, + {".ogv"}, + {"video/ogg"}, + "Ogg Video Format", + REFERENCE_URL, + ""}, + {"com.microsoft.lsf-video", + {"general.video"}, + {".lsf", ".lsx"}, + {"video/x-la-asf"}, + "Streaming Media Format", + REFERENCE_URL, + ""}, + {"general.h264-video", + {"general.video"}, + {".h264"}, + {"video/H264"}, + "H.264 Encoded Video Format", + REFERENCE_URL, + ""}, + {"general.jpeg-2000", + {"general.image"}, + {".jp2", ".jpg2", ".jpx", ".jpf", ".jpm"}, + {"image/jp2", "image/jpx", "image/jpm"}, + "JPEG 2000 Image", + REFERENCE_URL, + ""}, + {"com.fujifilm.raf-raw-image", + {"general.raw-image"}, + {".raf"}, + {"image/x-fuji-raf"}, + "Fujifilm RAW Image", + REFERENCE_URL, + ""}, + {"com.nikon.nrw-raw-image", + {"general.raw-image"}, + {".nrw"}, + {"image/x-nikon-nrw"}, + "Nikon Raw Image", + REFERENCE_URL, + ""}, + {"com.panasonic.rw2-raw-image", + {"general.raw-image"}, + {".rw2", ".raw"}, + {"image/x-panasonic-raw"}, + "Panasonic RAW Image", + REFERENCE_URL, + ""}, + {"com.pentax.pef-raw-image", + {"general.raw-image"}, + {".pef"}, + {"image/x-pentax-pef"}, + "Pentax Electronic RAW Image", + REFERENCE_URL, + ""}, + {"com.sumsung.srw-raw-image", + {"general.raw-image"}, + {".srw"}, + {"image/x-samsung-srw"}, + "Samsung RAW Image", + REFERENCE_URL, + ""}, + {"com.epson.erf-raw-image", + {"general.raw-image"}, + {".erf"}, + {"image/x-epson-erf"}, + "Epson RAW Imager", + REFERENCE_URL, + ""}, + {"com.olympus.orf-raw-image", + {"general.raw-image"}, + {".orf"}, + {"image/x-olympus-orf"}, + "Olympus RAW Image", + REFERENCE_URL, + ""}, + {"general.ief-image", + {"general.image"}, + {".ief"}, + {"image/ief"}, + "Image Exchange Format", + REFERENCE_URL, + ""}, + {"com.aol.art-image", + {"general.image"}, + {".art"}, + {"image/x-jg"}, + "ART image format", + REFERENCE_URL, + ""}, + {"general.content-form", + {"general.object"}, + {}, + {}, + "Content form format", + REFERENCE_URL, + ""}, + {"com.apple.m4p-audio", + {"general.audio"}, + {".m4p"}, + {"audio/mp4"}, + "iTunes Music Store Audio File Format", + REFERENCE_URL, + ""}, + {"general.ac3-audio", + {"general.audio"}, + {".ac3"}, + {"audio/ac3"}, + "Audio Codec 3 File Format", + REFERENCE_URL, + ""}, + {"openharmony.hsp", + {"openharmony.package"}, + {".hsp"}, + {}, + "Harmony Shared Package", + REFERENCE_URL, + ""}, + {"openharmony.har", + {"openharmony.package"}, + {".har"}, + {}, + "Harmony Archive", + REFERENCE_URL, + ""}, + {"openharmony.gopaint", + {"general.archive"}, + {".gopaint"}, + {}, + "Gopaint file format defined for Openharmony", + REFERENCE_URL, + ""}, + {"openharmony.gobrush", + {"general.archive"}, + {".gobrush"}, + {}, + "Gobrush file format defined for Openharmony", + REFERENCE_URL, + ""}, + {"openharmony.gobrushes", + {"general.archive"}, + {".gobrushes"}, + {}, + "Gobrushes file format defined for Openharmony", + REFERENCE_URL, + ""}, + {"openharmony.gocolor", + {"general.archive"}, + {".gocolor"}, + {}, + "Gocolor file format defined for Openharmony", + REFERENCE_URL, + ""}, + {"openharmony.dlp", + {"general.composite-object"}, + {".dlp"}, + {}, + "Account identify encryption file format defined by OpenHarmony", + REFERENCE_URL, + ""} + }; +}; +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/adapter/framework/innerkitsimpl/client/utd_client.cpp b/udmf/adapter/framework/innerkitsimpl/client/utd_client.cpp index 5f402265..25cca592 100644 --- a/udmf/adapter/framework/innerkitsimpl/client/utd_client.cpp +++ b/udmf/adapter/framework/innerkitsimpl/client/utd_client.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -12,9 +12,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#define LOG_TAG "UtdClient" +#include +#include +#include #include "utd_client.h" +#include "logger.h" +#include "utd_graph.h" +#include "custom_utd_store.h" + namespace OHOS { namespace UDMF { +constexpr const int MAX_UTD_LENGTH = 256; +constexpr const char *CUSTOM_UTD_HAP_DIR = "/data/utd/utd-adt.json"; + UtdClient::UtdClient() { Init(); @@ -30,61 +42,282 @@ UtdClient &UtdClient::GetInstance() return *instance; } +std::vector GetHapTypeCfgs() +{ + LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg, Path:%{public}s.", CUSTOM_UTD_HAP_DIR); + std::string jsonStr; + std::ifstream fin(CUSTOM_UTD_HAP_DIR); + while (fin.good()) { + std::string line; + std::getline(fin, line); + jsonStr += line; + } + std::vector customUtdTypes; + CustomUtdJsonParser utdJsonParser; + utdJsonParser.ParseStoredCustomUtdJson(jsonStr, customUtdTypes); + LOG_DEBUG(UDMF_CLIENT, "GetTypeCfgs, customUtdTypes total:%{public}zu.", customUtdTypes.size()); + return customUtdTypes; +} + void UtdClient::Init() { + std::unique_lock lock(utdMutex_); + descriptorCfgs_ = PresetTypeDescriptors::GetInstance().GetPresetTypes(); + std::vector customTypes; + customTypes = GetHapTypeCfgs(); + LOG_INFO(UDMF_CLIENT, "get customUtd, size:%{public}zu", customTypes.size()); + if (!customTypes.empty()) { + descriptorCfgs_.insert(descriptorCfgs_.end(), customTypes.begin(), customTypes.end()); + } + UtdGraph::GetInstance().InitUtdGraph(descriptorCfgs_); +} + +bool UtdClient::IsHapTokenType() +{ + return true; +} + +Status UtdClient::GetCurrentActiveUserId(int32_t &userId) +{ + return Status::E_OK; } Status UtdClient::GetTypeDescriptor(const std::string &typeId, std::shared_ptr &descriptor) { + { + std::shared_lock guard(utdMutex_); + for (const auto &utdTypeCfg : descriptorCfgs_) { + if (utdTypeCfg.typeId == typeId) { + descriptor = std::make_shared(utdTypeCfg); + return Status::E_OK; + } + } + } + if (typeId.find(FLEXIBLE_TYPE_FLAG) != typeId.npos) { + return GetFlexibleTypeDescriptor(typeId, descriptor); + } return Status::E_OK; } bool UtdClient::IsValidFileExtension(const std::string &fileExtension) { + if (fileExtension.empty()) { + return false; + } + if (fileExtension[0] != '.' || fileExtension.find("?") != fileExtension.npos || + fileExtension.find(":") != fileExtension.npos || fileExtension.find("=") != fileExtension.npos || + fileExtension.find("\\") != fileExtension.npos) { + return false; + } + return true; } bool UtdClient::IsValidMimeType(const std::string &mimeType) { + if (mimeType.empty()) { + return false; + } + if (mimeType.find("?") != mimeType.npos || mimeType.find(":") != mimeType.npos || + mimeType.find("=") != mimeType.npos || mimeType.find("\\") != mimeType.npos) { + return false; + } return true; } Status UtdClient::GetFlexibleTypeDescriptor(const std::string &typeId, std::shared_ptr &descriptor) { + TypeDescriptorCfg flexibleTypeDescriptorCfg; + if (!FlexibleType::ParseFlexibleUtd(typeId, flexibleTypeDescriptorCfg)) { + LOG_ERROR(UDMF_CLIENT, "ParseFlexibleUtd failed, invalid typeId"); + return Status::E_ERROR; + } + descriptor = std::make_shared(flexibleTypeDescriptorCfg); return Status::E_OK; } Status UtdClient::GetUniformDataTypeByFilenameExtension(const std::string &fileExtension, std::string &typeId, std::string belongsTo) { + std::string lowerFileExtension = fileExtension; + std::transform(lowerFileExtension.begin(), lowerFileExtension.end(), lowerFileExtension.begin(), ::tolower); + if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo."); + return Status::E_INVALID_PARAMETERS; + } + { + std::shared_lock guard(utdMutex_); + bool found = false; + for (const auto &utdTypeCfg : descriptorCfgs_) { + for (auto fileEx : utdTypeCfg.filenameExtensions) { + std::transform(fileEx.begin(), fileEx.end(), fileEx.begin(), ::tolower); + if (fileEx == lowerFileExtension) { + typeId = utdTypeCfg.typeId; + found = true; + break; + } + } + if (found) { + break; + } + } + } + // the find typeId is not belongsTo to the belongsTo. + if (!typeId.empty() && belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && + !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { + typeId = ""; + } + + if (typeId.empty()) { + if (!IsValidFileExtension(lowerFileExtension)) { + LOG_ERROR(UDMF_CLIENT, "invalid fileExtension."); + return Status::E_INVALID_PARAMETERS; + } + typeId = FlexibleType::GenFlexibleUtd("", lowerFileExtension, belongsTo); + } return Status::E_OK; } Status UtdClient::GetUniformDataTypeByMIMEType(const std::string &mimeType, std::string &typeId, std::string belongsTo) { + std::string lowerMimeType = mimeType; + std::transform(lowerMimeType.begin(), lowerMimeType.end(), lowerMimeType.begin(), ::tolower); + if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo."); + return Status::E_INVALID_PARAMETERS; + } + typeId = GetTypeIdFromCfg(lowerMimeType); + // the find typeId is not belongsTo to the belongsTo. + if (!typeId.empty() && belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && + !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { + typeId = ""; + } + if (typeId.empty()) { + if (!IsValidMimeType(mimeType)) { + LOG_ERROR(UDMF_CLIENT, "invalid mimeType."); + return Status::E_INVALID_PARAMETERS; + } + typeId = FlexibleType::GenFlexibleUtd(lowerMimeType, "", belongsTo); + } return Status::E_OK; } Status UtdClient::IsUtd(std::string typeId, bool &result) { + if (typeId.empty() || typeId.size() > MAX_UTD_LENGTH) { + result = false; + return Status::E_INVALID_PARAMETERS; + } + if (typeId[0] == '.' || find(typeId.begin(), typeId.end(), '/') != typeId.end()) { + result = false; + return Status::E_OK; + } + constexpr const char *preSetTypeIdRegexRule = + R"(^(general\.|openharmony\.|org\.|com\.|macos\.|debian\.|redhat\.|io\.|de\.|net\.)[a-z0-9-\.]+(\-[a-z0-9-]+)*$)"; + if (std::regex_match(typeId, std::regex(preSetTypeIdRegexRule))) { + result = true; + return Status::E_OK; + } + constexpr const char *customUtdRegexRule = + R"(^([A-Za-z]\w*)(\.\w+)+(\.[A-Za-z\d-]+)+)"; + if (std::regex_match(typeId, std::regex(customUtdRegexRule))) { + result = true; + return Status::E_OK; + } + result = false; + LOG_ERROR(UDMF_CLIENT, "is not utd"); return Status::E_OK; } Status UtdClient::GetUniformDataTypesByFilenameExtension(const std::string &fileExtension, std::vector &typeIds, const std::string &belongsTo) { + if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo."); + return Status::E_INVALID_PARAMETERS; + } + if (!IsValidFileExtension(fileExtension)) { + LOG_ERROR(UDMF_CLIENT, "invalid fileExtension."); + return Status::E_INVALID_PARAMETERS; + } + + std::string lowerFileExtension = fileExtension; + std::transform(lowerFileExtension.begin(), lowerFileExtension.end(), lowerFileExtension.begin(), ::tolower); + std::vector typeIdsInCfg; + { + std::shared_lock guard(utdMutex_); + for (const auto &utdTypeCfg : descriptorCfgs_) { + for (auto fileEx : utdTypeCfg.filenameExtensions) { + std::transform(fileEx.begin(), fileEx.end(), fileEx.begin(), ::tolower); + if (fileEx == lowerFileExtension) { + typeIdsInCfg.push_back(utdTypeCfg.typeId); + break; + } + } + } + } + typeIds.clear(); + for (const auto &typeId : typeIdsInCfg) { + // the find typeId is not belongsTo to the belongsTo. + if (belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && + !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { + continue; + } + typeIds.emplace_back(typeId); + } + if (typeIds.empty()) { + typeIds.emplace_back(FlexibleType::GenFlexibleUtd("", lowerFileExtension, belongsTo)); + } return Status::E_OK; } std::string UtdClient::GetTypeIdFromCfg(const std::string &mimeType) { + std::shared_lock guard(utdMutex_); + for (const auto &utdTypeCfg : descriptorCfgs_) { + for (auto mime : utdTypeCfg.mimeTypes) { + std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); + if (mime == mimeType) { + return utdTypeCfg.typeId; + } + } + } + if (mimeType.empty() || mimeType.back() != '*') { + return ""; + } + std::string prefixType = mimeType.substr(0, mimeType.length() - 1); + for (const auto &utdTypeCfg : descriptorCfgs_) { + for (auto mime : utdTypeCfg.mimeTypes) { + std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); + if (mime.rfind(prefixType, 0) == 0 && utdTypeCfg.belongingToTypes.size() > 0) { + return utdTypeCfg.belongingToTypes[0]; + } + } + } return ""; } std::vector UtdClient::GetTypeIdsFromCfg(const std::string &mimeType) { + bool prefixMatch = false; + std::string prefixType; + if (!mimeType.empty() && mimeType.back() == '*') { + prefixType = mimeType.substr(0, mimeType.length() - 1); + prefixMatch = true; + } std::vector typeIdsInCfg; + + std::shared_lock guard(utdMutex_); + for (const auto &utdTypeCfg : descriptorCfgs_) { + for (auto mime : utdTypeCfg.mimeTypes) { + std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); + if ((mime == mimeType) || (prefixMatch && mime.rfind(prefixType, 0) == 0)) { + typeIdsInCfg.push_back(utdTypeCfg.typeId); + break; + } + } + } return typeIdsInCfg; } @@ -95,6 +328,30 @@ void UtdClient::SubscribeUtdChange() Status UtdClient::GetUniformDataTypesByMIMEType(const std::string &mimeType, std::vector &typeIds, const std::string &belongsTo) { + if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo."); + return Status::E_INVALID_PARAMETERS; + } + if (!IsValidMimeType(mimeType)) { + LOG_ERROR(UDMF_CLIENT, "invalid mimeType."); + return Status::E_INVALID_PARAMETERS; + } + + std::string lowerMimeType = mimeType; + std::transform(lowerMimeType.begin(), lowerMimeType.end(), lowerMimeType.begin(), ::tolower); + std::vector typeIdsInCfg = GetTypeIdsFromCfg(lowerMimeType); + typeIds.clear(); + for (const auto &typeId : typeIdsInCfg) { + // the find typeId is not belongsTo to the belongsTo. + if (belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && + !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { + continue; + } + typeIds.emplace_back(typeId); + } + if (typeIds.empty()) { + typeIds.emplace_back(FlexibleType::GenFlexibleUtd(lowerMimeType, "", belongsTo)); + } return Status::E_OK; } } // namespace UDMF diff --git a/udmf/adapter/framework/innerkitsimpl/client/utd_client.h b/udmf/adapter/framework/innerkitsimpl/client/utd_client.h index 2da4ec4b..5f31a7d8 100644 --- a/udmf/adapter/framework/innerkitsimpl/client/utd_client.h +++ b/udmf/adapter/framework/innerkitsimpl/client/utd_client.h @@ -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 diff --git a/udmf/adapter/framework/innerkitsimpl/common/unified_meta.cpp b/udmf/adapter/framework/innerkitsimpl/common/unified_meta.cpp index 417432d1..578f3d67 100644 --- a/udmf/adapter/framework/innerkitsimpl/common/unified_meta.cpp +++ b/udmf/adapter/framework/innerkitsimpl/common/unified_meta.cpp @@ -648,6 +648,28 @@ bool UnifiedDataUtils::IsPersist(const std::string &intention) return IsPersist(GetIntentionByString(intention)); } +bool UnifiedDataUtils::IsPersist(const int32_t &visibility) +{ + return visibility >= static_cast(VISIBILITY_ALL) && visibility < static_cast(VISIBILITY_BUTT); +} + +bool UnifiedDataUtils::IsFileMangerIntention(const std::string &intention) +{ + Intention optionIntention = GetIntentionByString(intention); + if (optionIntention == UD_INTENTION_SYSTEM_SHARE || + optionIntention == UD_INTENTION_MENU || + optionIntention == UD_INTENTION_PICKER) { + return true; + } + return false; +} + +std::string UnifiedDataUtils::FindIntentionMap(const Intention &queryIntention) +{ + auto find = UD_INTENTION_MAP.find(queryIntention); + return find == UD_INTENTION_MAP.end() ? "" : find->second; +} + Intention UnifiedDataUtils::GetIntentionByString(const std::string &intention) { for (const auto &it : UD_INTENTION_MAP) { @@ -658,23 +680,85 @@ Intention UnifiedDataUtils::GetIntentionByString(const std::string &intention) return UD_INTENTION_BUTT; } -bool UnifiedDataUtils::IsValidOptions(const std::string &key, std::string &intention) +bool UnifiedDataUtils::IsValidOptions(UnifiedKey &key, const std::string &intention, + const std::string &validIntention) { - UnifiedKey unifiedKey(key); - auto isValidKey = unifiedKey.IsValid(); - if (key.empty() && IsPersist(intention)) { - return true; + if (key.key.empty() && intention.empty()) { + return false; } - if (intention.empty() && isValidKey && IsPersist(unifiedKey.intention)) { - return true; + bool isIntentionValid = intention.empty() || intention == validIntention; + if (!isIntentionValid) { + return false; } - if (isValidKey && unifiedKey.intention == intention && IsPersist(intention)) { - intention = ""; - return true; + bool isValidKey = key.key.empty() || (key.IsValid() && key.intention == validIntention); + if (!isValidKey) { + return false; + } + return true; +} + +bool UnifiedDataUtils::IsValidOptions(UnifiedKey &key, const std::string &intention) +{ + if (key.key.empty() && intention.empty()) { + return false; + } + + bool isIntentionValid = intention.empty() || IsPersist(intention); + if (!isIntentionValid) { + return false; + } + + bool isValidKey = key.key.empty() || (key.IsValid() && IsPersist(key.intention)); + if (!isValidKey) { + return false; + } + + if (!key.key.empty() && !intention.empty()) { + return key.intention == intention; + } + return true; +} + +bool UnifiedDataUtils::IsValidOptionsNonDrag(UnifiedKey &key, const std::string &intention) +{ + if (IsValidOptions(key, intention)) { + return !key.key.empty() || intention == UD_INTENTION_MAP.at(Intention::UD_INTENTION_DATA_HUB); } return false; } +std::string UnifiedDataUtils::GetBelongsToFileType(const std::string &utdId) +{ + if (utdId.empty() || utdId == "general.html" || utdId == "general.plain-text") { + LOG_ERROR(UDMF_FRAMEWORK, "The utdId is empty or the utdId is general.html or general.plain-text"); + return ""; + } + std::shared_ptr descriptor; + UtdClient::GetInstance().GetTypeDescriptor(utdId, descriptor); + if (descriptor == nullptr) { + LOG_INFO(UDMF_FRAMEWORK, "The descriptor is null"); + return ""; + } + for (const auto &type : FILE_SUB_TYPES) { + bool isSpecificType = false; + descriptor->BelongsTo(type, isSpecificType); + if (isSpecificType) { + return type; + } + } + if (!descriptor->GetFilenameExtensions().empty()) { + LOG_INFO(UDMF_FRAMEWORK, "The type descriptor has file extensions"); + return "general.file"; + } + LOG_INFO(UDMF_FRAMEWORK, "Return empty"); + return ""; +} + +bool UnifiedDataUtils::IsFilterFileType(const std::string &type) +{ + return std::find(FILE_SUB_TYPES.begin(), FILE_SUB_TYPES.end(), type) != FILE_SUB_TYPES.end(); +} + std::shared_ptr ObjectUtils::ConvertToObject(UDDetails &details) { Object object; diff --git a/udmf/bundle.json b/udmf/bundle.json index 742654f2..531e200b 100644 --- a/udmf/bundle.json +++ b/udmf/bundle.json @@ -16,6 +16,7 @@ "SystemCapability.DistributedDataManager.UDMF.Core" ], "features": [ + "udmf_feature_upgrade_skia" ], "adapted_system_type": [ "standard" @@ -41,16 +42,17 @@ "samgr", "app_file_service", "os_account", - "selinux_adapter" - ], - "third_party": [ - "bounds_checking_function" + "selinux_adapter", + "libuv", + "runtime_core" ] }, "build": { "sub_component": [ "//foundation/distributeddatamgr/udmf:udmf_packages", - "//foundation/distributeddatamgr/udmf/interfaces/components:udmfcomponents" + "//foundation/distributeddatamgr/udmf/interfaces/components:udmfcomponents", + "//foundation/distributeddatamgr/udmf/conf:utd_conf", + "//foundation/distributeddatamgr/udmf/interfaces/ani:udmf_data_ani" ], "inner_kits": [ { @@ -165,11 +167,18 @@ }, { "name": "//foundation/distributeddatamgr/udmf/interfaces/jskits:intelligence_napi", + "header": { + "header_files": [], + "header_base":"//foundation/distributeddatamgr/udmf/interfaces/jskits/intelligence" + } + }, + { + "name": "//foundation/distributeddatamgr/udmf/interfaces/innerkits/aipcore:aip_core_mgr_static", "header": { "header_files": [ "i_aip_core_manager.h" ], - "header_base":"//foundation/distributeddatamgr/udmf/interfaces/jskits/intelligence" + "header_base":"//foundation/distributeddatamgr/udmf/interfaces/innerkits/aipcore" } }, { @@ -185,6 +194,24 @@ "header_files": [], "header_base":"//foundation/distributeddatamgr/udmf/interfaces/cj/include" } + }, + { + "name": "//foundation/distributeddatamgr/udmf/interfaces/ani:unifieddatachannel_ani", + "header": { + "header_files": [ + "unifieddatachannel_ani.h" + ], + "header_base":"//foundation/distributeddatamgr/udmf/interfaces/ani/native/include" + } + }, + { + "name": "//foundation/distributeddatamgr/udmf/interfaces/innerkits:pixelmap_wrapper", + "header": { + "header_files": [ + "pixelmap_wrapper.h" + ], + "header_base":"//foundation/distributeddatamgr/udmf/interfaces/innerkits/dynamic" + } } ], "test": [ diff --git a/udmf/conf/BUILD.gn b/udmf/conf/BUILD.gn new file mode 100644 index 00000000..c1eda704 --- /dev/null +++ b/udmf/conf/BUILD.gn @@ -0,0 +1,22 @@ +# 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/ohos.gni") +import("//build/ohos_var.gni") +import("//foundation/distributeddatamgr/udmf/udmf.gni") + +ohos_prebuilt_etc("utd_conf") { + source = "uniform_data_types.json" + relative_install_dir = "utd/conf" + subsystem_name = "distributeddatamgr" + part_name = "udmf" +} diff --git a/udmf/conf/uniform_data_types.json b/udmf/conf/uniform_data_types.json new file mode 100644 index 00000000..519c1d01 --- /dev/null +++ b/udmf/conf/uniform_data_types.json @@ -0,0 +1,6580 @@ +{ + "UniformDataTypeDeclarations": [ + { + "typeId": "general.entity", + "belongingToTypes": [], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for physical hierarchy.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.object", + "belongingToTypes": [], + "filenameExtensions": [], + "mimeTypes": [ + "*/*" + ], + "description": "Base type for logical hierarchy.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.composite-object", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for mixed object. For example, a PDF file contains both text and special formatting data.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.text", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [ + "text/*" + ], + "description": "Base type for all text.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.plain-text", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".txt", + ".text" + ], + "mimeTypes": [ + "text/plain" + ], + "description": "Text of unspecified encoding, with no markup.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_txt" + }, + { + "typeId": "general.html", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".html", + ".htm" + ], + "mimeTypes": [ + "text/html" + ], + "description": "HTML text.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_html" + }, + { + "typeId": "general.hyperlink", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Hyperlink.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.xml", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".xml" + ], + "mimeTypes": [ + "text/xml" + ], + "description": "XML text.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_xml" + }, + { + "typeId": "com.real.smil", + "belongingToTypes": [ + "general.xml" + ], + "filenameExtensions": [ + ".smil" + ], + "mimeTypes": [ + "application/smil" + ], + "description": "Real synchronized multimedia integration language.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.source-code", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Generic source code.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.script", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for scripting language source code.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.shell-script", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".sh", + ".command" + ], + "mimeTypes": [ + "text/x-shellscript" + ], + "description": "Shell script.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.csh-script", + "belongingToTypes": [ + "general.shell-script" + ], + "filenameExtensions": [ + ".csh" + ], + "mimeTypes": [ + "text/x-csh" + ], + "description": "C-shell script.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.perl-script", + "belongingToTypes": [ + "general.shell-script" + ], + "filenameExtensions": [ + ".pl", + ".pm" + ], + "mimeTypes": [ + "text/x-perl-script" + ], + "description": "Perl script.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.php-script", + "belongingToTypes": [ + "general.shell-script" + ], + "filenameExtensions": [ + ".php", + ".php3", + ".php4", + ".ph3", + ".ph4", + ".phtml" + ], + "mimeTypes": [ + "text/x-php-script", + "text/php", + "application/php" + ], + "description": "PHP script.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.python-script", + "belongingToTypes": [ + "general.shell-script" + ], + "filenameExtensions": [ + ".py" + ], + "mimeTypes": [ + "text/x-python-script" + ], + "description": "Python script.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ruby-script", + "belongingToTypes": [ + "general.shell-script" + ], + "filenameExtensions": [ + ".rb", + ".rbw" + ], + "mimeTypes": [ + "text/ruby-script" + ], + "description": "Ruby script.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.type-script", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".ts" + ], + "mimeTypes": [], + "description": "TypeScript source code.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.java-script", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".js", + ".jscript", + ".javascript" + ], + "mimeTypes": [ + "text/javascript" + ], + "description": "JavaScript source code.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.c-header", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".h" + ], + "mimeTypes": [ + "text/x-chdr" + ], + "description": "C header file.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.c-source", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".c" + ], + "mimeTypes": [ + "text/x-csrc" + ], + "description": "C source code.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.c-plus-plus-header", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".hpp", + ".h++", + ".hxx", + ".hh" + ], + "mimeTypes": [ + "text/x-c++hdr" + ], + "description": "C++ header file.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.c-plus-plus-source", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".cp", + ".cpp", + ".c++", + ".cc", + ".cxx" + ], + "mimeTypes": [ + "text/x-c++src" + ], + "description": "C++ source code.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.java-source", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".java", + ".jav" + ], + "mimeTypes": [ + "text/x-java" + ], + "description": "Java source code.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.markdown", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".md", + ".markdown", + ".markdn", + ".mdown" + ], + "mimeTypes": [ + "text/markdown" + ], + "description": "Markdown format.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ebook", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for ebook.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.epub", + "belongingToTypes": [ + "general.ebook" + ], + "filenameExtensions": [ + ".epub" + ], + "mimeTypes": [ + "application/epub+zip" + ], + "description": "Electronic publication (EPUB) format.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.amazon.azw", + "belongingToTypes": [ + "general.ebook" + ], + "filenameExtensions": [ + ".azw" + ], + "mimeTypes": [ + "application/vnd.amazon.ebook" + ], + "description": "AZW ebook.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.amazon.azw3", + "belongingToTypes": [ + "general.ebook" + ], + "filenameExtensions": [ + ".azw3" + ], + "mimeTypes": [ + "application/vnd.amazon.mobi8-ebook", + "application/x-mobi8-ebook" + ], + "description": "AZW3 ebook.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.amazon.kfx", + "belongingToTypes": [ + "general.ebook" + ], + "filenameExtensions": [ + ".kfx" + ], + "mimeTypes": [], + "description": "KFX ebook.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.amazon.mobi", + "belongingToTypes": [ + "general.ebook" + ], + "filenameExtensions": [ + ".mobi" + ], + "mimeTypes": [ + "application/x-mobipocket-ebook" + ], + "description": "MOBI ebook.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.media", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for media.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.image", + "belongingToTypes": [ + "general.media" + ], + "filenameExtensions": [], + "mimeTypes": [ + "image/*" + ], + "description": "Base type for images.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "general.jpeg", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".jpg", + ".jpeg", + ".jpe" + ], + "mimeTypes": [ + "image/jpeg" + ], + "description": "JPEG image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "general.png", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".png" + ], + "mimeTypes": [ + "image/png" + ], + "description": "PNG image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "general.raw-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for digital camera raw image formats.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "general.tiff", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".tif", + ".tiff" + ], + "mimeTypes": [ + "image/tiff" + ], + "description": "TIFF image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "com.microsoft.bmp", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".bmp", + ".bm" + ], + "mimeTypes": [ + "image/bmp", + "image/x-ms-bmp" + ], + "description": "Windows bitmap image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "com.microsoft.ico", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".ico" + ], + "mimeTypes": [ + "image/ico", + "image/x-icon" + ], + "description": "Windows icon image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "com.adobe.photoshop-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".psd" + ], + "mimeTypes": [ + "image/x-photoshop", + "image/photoshop", + "image/psd", + "application/photoshop" + ], + "description": "Adobe Photoshop document.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "com.adobe.illustrator.ai-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".ai" + ], + "mimeTypes": [], + "description": "Adobe Illustrator document.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "general.fax", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for fax images.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.j2.jfx-fax", + "belongingToTypes": [ + "general.fax" + ], + "filenameExtensions": [ + ".jfx" + ], + "mimeTypes": [], + "description": "J2 fax.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.js.efx-fax", + "belongingToTypes": [ + "general.fax" + ], + "filenameExtensions": [ + ".efx" + ], + "mimeTypes": [ + "image/efax" + ], + "description": "eFax fax.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.xbitmap-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".xbm" + ], + "mimeTypes": [ + "image/x-xbitmap", + "image/x-xbm" + ], + "description": "X bitmap image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.truevision.tga-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".tga" + ], + "mimeTypes": [ + "image/targa", + "image/tga", + "application/tga" + ], + "description": "TGA image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.sgi.sgi-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".sgi" + ], + "mimeTypes": [ + "image/sgi" + ], + "description": "Silicon Graphics image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.ilm.openexr-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".exr" + ], + "mimeTypes": [], + "description": "OpenEXR image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kodak.flashpix.image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".fpx" + ], + "mimeTypes": [ + "image/fpx", + "application/vnd.fpx" + ], + "description": "FlashPix image.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.word.doc", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".doc" + ], + "mimeTypes": [ + "application/msword" + ], + "description": "Microsoft Word data.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_doc" + }, + { + "typeId": "com.microsoft.excel.xls", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".xls" + ], + "mimeTypes": [ + "application/vnd.ms-excel" + ], + "description": "Microsoft Excel data.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_xls" + }, + { + "typeId": "com.microsoft.powerpoint.ppt", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".ppt" + ], + "mimeTypes": [ + "application/vnd.ms-powerpoint" + ], + "description": "Microsoft PowerPoint presentation.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.pdf", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".pdf" + ], + "mimeTypes": [ + "application/pdf" + ], + "description": "PDF data.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_pdf" + }, + { + "typeId": "com.adobe.postscript", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".ps" + ], + "mimeTypes": [ + "application/postscript" + ], + "description": "PostScript data.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.encapsulated-postscript", + "belongingToTypes": [ + "com.adobe.postscript" + ], + "filenameExtensions": [ + ".eps" + ], + "mimeTypes": [], + "description": "Encapsulated PostScript.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.video", + "belongingToTypes": [ + "general.media" + ], + "filenameExtensions": [], + "mimeTypes": [ + "video/*" + ], + "description": "Base type for video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "general.avi", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".avi", + ".vfw" + ], + "mimeTypes": [ + "video/avi", + "video/msvideo", + "video/x-msvideo" + ], + "description": "AVI video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "general.mpeg", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".mpg", + ".mpeg", + ".m75", + ".m15", + ".mpe" + ], + "mimeTypes": [ + "video/mpg", + "video/mpeg", + "video/x-mpg", + "video/x-mpeg" + ], + "description": "MPEG-1 or MPEG-2 video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "general.mpeg-4", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".mp4", + ".mp4v", + ".mpeg4" + ], + "mimeTypes": [ + "video/mp4", + "video/mp4v" + ], + "description": "MPEG-4 video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "general.3gpp", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".3gp", + ".3gpp" + ], + "mimeTypes": [ + "video/3gpp" + ], + "description": "3GPP video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "general.3gpp2", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".3g2", + ".3gp2", + ".3gpp2" + ], + "mimeTypes": [ + "video/3gpp2" + ], + "description": "3GPP2 video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "com.microsoft.windows-media-wm", + "belongingToTypes": [ + "general.video", + "com.microsoft.advanced-systems-format" + ], + "filenameExtensions": [ + ".wm" + ], + "mimeTypes": [ + "video/x-ms-wm" + ], + "description": "Windows WM video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "com.microsoft.windows-media-wmv", + "belongingToTypes": [ + "general.video", + "com.microsoft.advanced-systems-format" + ], + "filenameExtensions": [ + ".wmv" + ], + "mimeTypes": [ + "video/x-ms-wmv" + ], + "description": "Windows WMV video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "com.microsoft.windows-media-wmp", + "belongingToTypes": [ + "general.video", + "com.microsoft.advanced-systems-format" + ], + "filenameExtensions": [ + ".wmp" + ], + "mimeTypes": [ + "video/x-ms-wmp" + ], + "description": "Windows WMP video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "com.microsoft.windows-media-wvx", + "belongingToTypes": [ + "general.video", + "com.microsoft.advanced-systems-format" + ], + "filenameExtensions": [ + ".wvx" + ], + "mimeTypes": [ + "video/x-ms-wvx" + ], + "description": "Windows WVX video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "com.microsoft.windows-media-wmx", + "belongingToTypes": [ + "general.video", + "com.microsoft.advanced-systems-format" + ], + "filenameExtensions": [ + ".wmx" + ], + "mimeTypes": [ + "video/x-ms-wmx" + ], + "description": "Windows WMX video.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_video" + }, + { + "typeId": "com.real.realmedia", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".rm" + ], + "mimeTypes": [ + "application/vnd.rn-realmedia" + ], + "description": "RealMedia.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.audio", + "belongingToTypes": [ + "general.media" + ], + "filenameExtensions": [], + "mimeTypes": [ + "audio/*" + ], + "description": "Base type for audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_audio" + }, + { + "typeId": "general.aac", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".aac" + ], + "mimeTypes": [ + "audio/aac" + ], + "description": "AAC audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_audio" + }, + { + "typeId": "general.aiff", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".aiff" + ], + "mimeTypes": [ + "audio/aiff" + ], + "description": "AIFF audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_audio" + }, + { + "typeId": "general.alac", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".alac" + ], + "mimeTypes": [ + "audio/alac" + ], + "description": "ALAC audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_audio" + }, + { + "typeId": "general.flac", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".flac" + ], + "mimeTypes": [ + "audio/flac" + ], + "description": "FLAC audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_flac" + }, + { + "typeId": "general.mp3", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".mp3" + ], + "mimeTypes": [ + "audio/mp3" + ], + "description": "MPEG-3 audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_mp3" + }, + { + "typeId": "general.ogg", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".ogg" + ], + "mimeTypes": [ + "audio/ogg" + ], + "description": "OGG audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_audio" + }, + { + "typeId": "general.pcm", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".pcm" + ], + "mimeTypes": [ + "audio/pcm" + ], + "description": "PCM audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_audio" + }, + { + "typeId": "com.microsoft.advanced-systems-format", + "belongingToTypes": [ + "general.media" + ], + "filenameExtensions": [ + ".asf" + ], + "mimeTypes": [ + "video/x-ms-asf", + "application/vnd.ms-asf" + ], + "description": "Advanced Systems format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.advanced-stream-redirector", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".asx" + ], + "mimeTypes": [ + "video/x-ms-asf" + ], + "description": "Advanced stream redirector", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.windows-media-wma", + "belongingToTypes": [ + "general.audio", + "com.microsoft.advanced-systems-format" + ], + "filenameExtensions": [ + ".wma" + ], + "mimeTypes": [ + "audio/x-ms-wma" + ], + "description": "Windows WMA audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_wma" + }, + { + "typeId": "com.microsoft.waveform-audio", + "belongingToTypes": [ + "general.audio", + "com.microsoft.advanced-systems-format" + ], + "filenameExtensions": [ + ".wav", + ".wave" + ], + "mimeTypes": [ + "audio/wav", + "audio/wave", + "audio/x-wav" + ], + "description": "Waveform audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_wav" + }, + { + "typeId": "com.microsoft.windows-media-wax", + "belongingToTypes": [ + "general.audio", + "com.microsoft.advanced-systems-format" + ], + "filenameExtensions": [ + ".wax" + ], + "mimeTypes": [ + "audio/x-ms-wax" + ], + "description": "Windows WAX audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_audio" + }, + { + "typeId": "general.au-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".au", + ".snd" + ], + "mimeTypes": [ + "audio/basic", + "audio/au", + "audio/snd" + ], + "description": "Au file format.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.aifc-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".aifc", + ".aif", + ".aiff" + ], + "mimeTypes": [ + "audio/x-aiff" + ], + "description": "Audio Interchange File Format.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.digidesign.sd2-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".sd2" + ], + "mimeTypes": [ + "audio/x-sd2" + ], + "description": "Digidesign Sound Designer II audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.real.realaudio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".ram", + ".ra" + ], + "mimeTypes": [ + "audio/vnd.rn-realaudio", + "audio/x-pn-realaudio" + ], + "description": "RealMedia audio.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.file", + "belongingToTypes": [ + "general.entity" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for file.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.directory", + "belongingToTypes": [ + "general.entity" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for directory.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_folder" + }, + { + "typeId": "general.folder", + "belongingToTypes": [ + "general.directory" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for folder.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_folder" + }, + { + "typeId": "general.symlink", + "belongingToTypes": [ + "general.entity" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for symlink.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.archive", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for an archive of files and directories.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_compress" + }, + { + "typeId": "general.bz2-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".bz2", + ".bzip2" + ], + "mimeTypes": [ + "application/x-bzip2" + ], + "description": "BZip2 archive.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_compress" + }, + { + "typeId": "general.disk-image", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for items mountable as a volume.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_compress" + }, + { + "typeId": "general.tar-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".tar" + ], + "mimeTypes": [ + "application/x-tar", + "application/tar" + ], + "description": "Tar archive.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_compress" + }, + { + "typeId": "general.zip-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".zip" + ], + "mimeTypes": [ + "application/zip" + ], + "description": "Zip archive.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_zip" + }, + { + "typeId": "com.sun.java-archive", + "belongingToTypes": [ + "general.archive", + "general.executable" + ], + "filenameExtensions": [ + ".jar" + ], + "mimeTypes": [ + "application/java-archive" + ], + "description": "Java archive.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_compress" + }, + { + "typeId": "org.gnu.gnu-tar-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".gtar" + ], + "mimeTypes": [ + "application/x-gtar" + ], + "description": "GNU archive.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_compress" + }, + { + "typeId": "org.gnu.gnu-zip-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".gz", + ".gzip" + ], + "mimeTypes": [ + "application/x-gzip", + "application/gzip" + ], + "description": "Gzip archive.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_compress" + }, + { + "typeId": "org.gnu.gnu-zip-tar-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".tgz" + ], + "mimeTypes": [ + "application/x-gtar" + ], + "description": "Gzip tar archive.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_compress" + }, + { + "typeId": "org.openxmlformats.openxml", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Office Open XML.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.wordprocessingml.document", + "belongingToTypes": [ + "general.composite-object", + "org.openxmlformats.openxml" + ], + "filenameExtensions": [ + ".docx" + ], + "mimeTypes": [ + "application/vnd.openxmlformats-officedocument.wordprocessingml.document" + ], + "description": "Office Open XML Document.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.spreadsheetml.sheet", + "belongingToTypes": [ + "general.composite-object", + "org.openxmlformats.openxml" + ], + "filenameExtensions": [ + ".xlsx" + ], + "mimeTypes": [ + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ], + "description": "Office Open XML Workbook.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.presentationml.presentation", + "belongingToTypes": [ + "general.composite-object", + "org.openxmlformats.openxml" + ], + "filenameExtensions": [ + ".pptx" + ], + "mimeTypes": [ + "application/vnd.openxmlformats-officedocument.presentationml.presentation" + ], + "description": "Office Open XML Presentation.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis.opendocument", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Open Document Format for Office Applications.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis.opendocument.text", + "belongingToTypes": [ + "general.composite-object", + "org.oasis.opendocument" + ], + "filenameExtensions": [ + ".odt", + ".fodt" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.text" + ], + "description": "OpenDocument Text.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis.opendocument.spreadsheet", + "belongingToTypes": [ + "general.composite-object", + "org.oasis.opendocument" + ], + "filenameExtensions": [ + ".ods", + ".fods" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.spreadsheet" + ], + "description": "OpenDocument Spreadsheet.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis.opendocument.presentation", + "belongingToTypes": [ + "general.composite-object", + "org.oasis.opendocument" + ], + "filenameExtensions": [ + ".odp", + ".fodp" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.presentation" + ], + "description": "OpenDocument Presentation.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis.opendocument.graphics", + "belongingToTypes": [ + "general.composite-object", + "org.oasis.opendocument" + ], + "filenameExtensions": [ + ".odg", + ".fodg" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.graphics" + ], + "description": "OpenDocument Graphics.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis.opendocument.formula", + "belongingToTypes": [ + "org.oasis.opendocument" + ], + "filenameExtensions": [ + ".odf" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.formula" + ], + "description": "OpenDocument Formulat.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.allume.stuffit-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".sit", + ".sitx" + ], + "mimeTypes": [ + "application/x-stuffit", + "application/x-sit", + "application/stuffit" + ], + "description": "Stuffit archive.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.calendar", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [], + "mimeTypes": [ + "text/calendar" + ], + "description": "Base type for scheduled events.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_calendar" + }, + { + "typeId": "general.vcs", + "belongingToTypes": [ + "general.calendar" + ], + "filenameExtensions": [ + ".vcs" + ], + "mimeTypes": [ + "text/calendar" + ], + "description": "vCalendar type.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ics", + "belongingToTypes": [ + "general.calendar" + ], + "filenameExtensions": [ + ".ics" + ], + "mimeTypes": [ + "text/calendar" + ], + "description": "iCalendar type.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.contact", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for contact information.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.database", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for databases.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.message", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for messages.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.executable", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for executable data.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.portable-executable", + "belongingToTypes": [ + "general.executable" + ], + "filenameExtensions": [ + ".exe", + ".dll" + ], + "mimeTypes": [ + "application/vnd.microsoft.portable-executable" + ], + "description": "Microsoft Windows application.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.sun.java-class", + "belongingToTypes": [ + "general.executable" + ], + "filenameExtensions": [ + ".class" + ], + "mimeTypes": [], + "description": "Java class.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.vcard", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [ + ".vcf", + ".vcard" + ], + "mimeTypes": [ + "text/vcard", + "text/x-vcard" + ], + "description": "Base type for electronic business card.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.navigation", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for navigation.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.location", + "belongingToTypes": [ + "general.navigation" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Navigation location.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.font", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for fonts.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.truetype-font", + "belongingToTypes": [ + "general.font" + ], + "filenameExtensions": [ + ".ttf" + ], + "mimeTypes": [ + "font/ttf" + ], + "description": "TrueType font.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.truetype-collection-font", + "belongingToTypes": [ + "general.font" + ], + "filenameExtensions": [ + ".ttc" + ], + "mimeTypes": [ + "font/collection" + ], + "description": "TrueType collection font.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.opentype-font", + "belongingToTypes": [ + "general.font" + ], + "filenameExtensions": [ + ".otf" + ], + "mimeTypes": [ + "font/otf" + ], + "description": "OpenType font.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.postscript-font", + "belongingToTypes": [ + "general.font" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "PostScript font.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.form", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenHarmony system defined form.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.app-item", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenHarmony system defined app item.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.pixel-map", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenHarmony system defined pixel map.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype", + "iconFile": "sys.media.ohos_ic_normal_white_grid_image" + }, + { + "typeId": "openharmony.atomic-service", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenHarmony system defined atomic service.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.package", + "belongingToTypes": [ + "general.directory" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenHarmony system defined package (that is, a directory presented to the user as a file).", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.hap", + "belongingToTypes": [ + "openharmony.package" + ], + "filenameExtensions": [ + ".hap" + ], + "mimeTypes": [], + "description": "OpenHarmony system defined ability package.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.hdoc", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".hdoc" + ], + "mimeTypes": [], + "description": "OpenHarmony system AppNotepad data format.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.hinote", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".hinote" + ], + "mimeTypes": [], + "description": "OpenHarmony system Notes data format.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.styled-string", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenHarmony system defined styled string.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.want", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenHarmony system defined Want.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.moving-photo", + "belongingToTypes": [ + "general.media" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenHarmony system defined moving photo.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "macos.dmg", + "belongingToTypes": [ + "general.disk-image" + ], + "filenameExtensions": [ + ".dmg" + ], + "mimeTypes": [ + "application/x-apple-diskimage" + ], + "description": "Apple Disk Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "debian.deb", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".deb", + ".udeb" + ], + "mimeTypes": [ + "application/x-debian-package", + "application/vnd.debian.binary-package" + ], + "description": "OpenHarmony system defined Want.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ofd", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".ofd" + ], + "mimeTypes": [], + "description": "Open fixed-layout document, a national standard for format documents", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.opg", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".opg" + ], + "mimeTypes": [], + "description": "OPG archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.tex", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for TeX source code", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.css", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".css" + ], + "mimeTypes": [ + "text/css" + ], + "description": "Cascading style sheets", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.vob", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".vob" + ], + "mimeTypes": [ + "video/mpeg", + "video/x-ms-vob" + ], + "description": "", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.dif-video", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".dif" + ], + "mimeTypes": [ + "video/dv" + ], + "description": "Digital interface format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.dv-video", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".dv" + ], + "mimeTypes": [ + "video/dv" + ], + "description": "DV video", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.flc-animation", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".fli", + ".flc" + ], + "mimeTypes": [ + "video/fli", + "video/flc" + ], + "description": "FLIC file format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mng", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".mng" + ], + "mimeTypes": [ + "video/x-mng" + ], + "description": "Multiple-image network graphics", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mpegurl-video", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".mxu", + ".m4u" + ], + "mimeTypes": [ + "video/vnd.mpegurl" + ], + "description": "Video playlist", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ts", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".ts" + ], + "mimeTypes": [ + "video/mp2ts", + "video/mp2t" + ], + "description": "MPEG transport stream", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.amr", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".amr" + ], + "mimeTypes": [ + "audio/amr" + ], + "description": "The adaptive multi-rate audio codecs", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.amr-wb", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".awb" + ], + "mimeTypes": [ + "audio/amr-wb" + ], + "description": "Adaptive multi-rate wideband", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.gsm", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".gsm" + ], + "mimeTypes": [ + "audio/x-gsm", + "audio/gsm" + ], + "description": "Global system form mobile audio format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.imy", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".imy" + ], + "mimeTypes": [ + "audio/imelody" + ], + "description": "Non-polyphonic ringtone exchange object format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.kar", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".kar" + ], + "mimeTypes": [ + "audio/midi" + ], + "description": "Karaoke MIDI file format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mpegurl-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".m3u" + ], + "mimeTypes": [ + "audio/mpegurl", + "audio/x-mpegurl" + ], + "description": "Audio playlist", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mpeg-4-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".m4a", + ".m4b" + ], + "mimeTypes": [ + "audio/mpeg" + ], + "description": "Audio-only MPEG-4 file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.midi-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".mid", + ".midi" + ], + "mimeTypes": [ + "audio/midi" + ], + "description": "MIDI audio", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mp2", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".mp2" + ], + "mimeTypes": [ + "audio/mpeg" + ], + "description": "MPEG-1 audio layer II or MPEG-2 audio layer II", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mpeg-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".mpga" + ], + "mimeTypes": [ + "audio/mpeg" + ], + "description": "MPEG audio format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mxmf", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".mxmf" + ], + "mimeTypes": [ + "audio/mobile-xmf" + ], + "description": "Mobile XMF audio format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ota", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".ota" + ], + "mimeTypes": [ + "audio/midi" + ], + "description": "OTA ringtone file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.pls", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".pls" + ], + "mimeTypes": [ + "audio/x-scpls" + ], + "description": "Multimedia playlist format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.rtttl", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".rtttl" + ], + "mimeTypes": [ + "audio/midi" + ], + "description": "Ring tone transfer language file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.psid", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".sid", + ".psid" + ], + "mimeTypes": [ + "audio/prs.sid" + ], + "description": "SID audio", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ulaw-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".au", + ".ulw", + ".snd" + ], + "mimeTypes": [ + "audio/basic", + "audio/au", + "audio/snd" + ], + "description": "uLaw audio", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.xmf", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".xmf" + ], + "mimeTypes": [ + "audio/midi" + ], + "description": "Extensible music file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.gif", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".gif" + ], + "mimeTypes": [ + "image/gif" + ], + "description": "GIF image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.djvu-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".djv", + ".djvu" + ], + "mimeTypes": [ + "image/vnd.djvu" + ], + "description": "Djvu image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.jng-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".jng" + ], + "mimeTypes": [ + "image/x-jng" + ], + "description": "JPEG network graphic", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.pcx-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".pcx" + ], + "mimeTypes": [ + "image/vnd.zbrush.pcx" + ], + "description": "Paintbrush bitmap image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.pbm-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".pbm" + ], + "mimeTypes": [ + "image/x-portable-bitmap" + ], + "description": "Portable bitmap image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.pgm-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".pgm" + ], + "mimeTypes": [ + "image/x-portable-graymap" + ], + "description": "Portable gray map image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.pnm-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".pnm" + ], + "mimeTypes": [ + "image/x-portable-anymap" + ], + "description": "Portable any map image file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ppm-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".ppm" + ], + "mimeTypes": [ + "image/x-portable-pixmap" + ], + "description": "Portable pixmap image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.rgb-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".rgb" + ], + "mimeTypes": [ + "image/x-rgb" + ], + "description": "RGB bitmap", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.svg-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".svg", + ".svgz" + ], + "mimeTypes": [ + "image/svg+xml" + ], + "description": "Scalable vector graphic", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.wbmp-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".wbmp" + ], + "mimeTypes": [ + "image/vnd.wap.wbmp" + ], + "description": "Wireless bitmap image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.xpixmap-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".xpm" + ], + "mimeTypes": [ + "image/x-xpixmap" + ], + "description": "X11 pixmap graphic", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.xwindowdump-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".xwd" + ], + "mimeTypes": [ + "image/x-xwindowdump" + ], + "description": "X windows dump image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.heif", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".heif", + ".heifs", + ".hif" + ], + "mimeTypes": [ + "image/heif" + ], + "description": "High efficiency image format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.heic", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".heic", + ".heics" + ], + "mimeTypes": [ + "image/heic" + ], + "description": "High efficiency image format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.virtual-cd", + "belongingToTypes": [ + "general.disk-image" + ], + "filenameExtensions": [ + ".vcd" + ], + "mimeTypes": [ + "application/x-cdlink" + ], + "description": "Virtual CD", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.boo-source", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".boo" + ], + "mimeTypes": [ + "text/x-boo" + ], + "description": "Boo source code", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.d-source", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".d" + ], + "mimeTypes": [ + "text/x-dsrc" + ], + "description": "D source code file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.html-component", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".htc" + ], + "mimeTypes": [ + "text/x-component" + ], + "description": "HTML component", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.pascal-source", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".p", + ".pas" + ], + "mimeTypes": [ + "text/x-pascal" + ], + "description": "Pascal source code", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.haskell-script", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".hs" + ], + "mimeTypes": [ + "text/x-haskell" + ], + "description": "Haskell script", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.literate-haskell-script", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".lhs" + ], + "mimeTypes": [ + "text/x-literate-haskell" + ], + "description": "Literate haskell script", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.tcl-script", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".tcl" + ], + "mimeTypes": [ + "text/x-tcl" + ], + "description": "Tcl script", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.asc-text", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".asc" + ], + "mimeTypes": [ + "text/plain" + ], + "description": "ASCII text file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.portable-object", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".po" + ], + "mimeTypes": [ + "text/plain" + ], + "description": "Portable object", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.rich-text", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".rtf", + ".rtx" + ], + "mimeTypes": [ + "text/rtf", + "text/richtext" + ], + "description": "Rich text format file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.delimited-values-text", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for delimited-values text", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.comma-separated-values-text", + "belongingToTypes": [ + "general.delimited-values-text" + ], + "filenameExtensions": [ + ".csv" + ], + "mimeTypes": [ + "text/csv" + ], + "description": "Comma-separated values file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.diff", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".diff" + ], + "mimeTypes": [ + "text/plain" + ], + "description": "Patch file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.setext", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".etx" + ], + "mimeTypes": [ + "text/x-setext" + ], + "description": "Structure enhanced Text", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.gcd", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".gcd" + ], + "mimeTypes": [ + "text/x-pcs-gcd" + ], + "description": "General content descriptor", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.tab-separated-values-text", + "belongingToTypes": [ + "general.delimited-values-text" + ], + "filenameExtensions": [ + ".tsv" + ], + "mimeTypes": [ + "text/tab-separated-values" + ], + "description": "Tab-Separated values file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.p7r", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".p7r" + ], + "mimeTypes": [ + "application/x-pkcs7-certreqresp" + ], + "description": "Certificate request response file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.pem", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".pem" + ], + "mimeTypes": [ + "application/x-pem-file" + ], + "description": "Privacy enhanced mail certificate", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.chess-pgn", + "belongingToTypes": [ + "general.plain-text" + ], + "filenameExtensions": [ + ".pgn" + ], + "mimeTypes": [ + "application/x-chess-pgn", + "application/vnd.chess-pgn" + ], + "description": "Portable game notation file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.lha-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".lha" + ], + "mimeTypes": [ + "application/x-lha" + ], + "description": "LHARC compressed archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.lzh-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".lzh" + ], + "mimeTypes": [ + "application/x-lzh" + ], + "description": "LZH compressed file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.lzx-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".lzx" + ], + "mimeTypes": [ + "application/x-lzx" + ], + "description": "LZX compressed archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.taz-archive", + "belongingToTypes": [ + "general.tar-archive" + ], + "filenameExtensions": [ + ".taz", + ".tar.z", + ".tz" + ], + "mimeTypes": [ + "application/x-gtar" + ], + "description": "Tar zipped file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.shar-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".shar" + ], + "mimeTypes": [ + "application/x-shar" + ], + "description": "Unix Shar archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.cpio-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".cpio" + ], + "mimeTypes": [ + "application/x-cpio" + ], + "description": "Unix CPIO archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.web-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".mht", + ".mhtml" + ], + "mimeTypes": [ + "application/x-mimearchive" + ], + "description": "MHTML web archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ustar", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".ustar" + ], + "mimeTypes": [ + "application/x-ustar" + ], + "description": "Uniform standard tape archive format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mathml", + "belongingToTypes": [ + "general.xml" + ], + "filenameExtensions": [ + ".mml" + ], + "mimeTypes": [ + "text/mathml", + "application/mathml+xml" + ], + "description": "Mathematical markup language file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.xhtml", + "belongingToTypes": [ + "general.xml" + ], + "filenameExtensions": [ + ".xhtml" + ], + "mimeTypes": [ + "application/xhtml+xml" + ], + "description": "XHTML", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.rss", + "belongingToTypes": [ + "general.xml" + ], + "filenameExtensions": [ + ".rss" + ], + "mimeTypes": [ + "application/rss+xml" + ], + "description": "Rich site summary", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.rdf", + "belongingToTypes": [ + "general.xml" + ], + "filenameExtensions": [ + ".rdf" + ], + "mimeTypes": [ + "application/rdf+xml" + ], + "description": "Resource description framework file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.cad", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for computer-aided design", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.iges", + "belongingToTypes": [ + "general.cad" + ], + "filenameExtensions": [ + ".iges", + ".igs" + ], + "mimeTypes": [ + "model/iges" + ], + "description": "IGES drawing", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.octet-stream", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [ + "application/octet-stream" + ], + "description": "Arbitrary binary data", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.iso", + "belongingToTypes": [ + "general.disk-image" + ], + "filenameExtensions": [ + ".iso" + ], + "mimeTypes": [ + "application/x-iso9660-image" + ], + "description": "Disc image file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mesh-model", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [ + ".msh", + ".mesh", + ".silo" + ], + "mimeTypes": [ + "model/mesh" + ], + "description": "3D mesh model", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.certificate", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Base type for security certificate", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.c-object", + "belongingToTypes": [ + "general.executable" + ], + "filenameExtensions": [ + ".o" + ], + "mimeTypes": [ + "application/x-object" + ], + "description": "Compiled C object file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.dvi", + "belongingToTypes": [ + "general.tex" + ], + "filenameExtensions": [ + ".dvi" + ], + "mimeTypes": [ + "application/x-dvi" + ], + "description": "Device independent format file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.cer-certificate", + "belongingToTypes": [ + "general.certificate" + ], + "filenameExtensions": [ + ".cer" + ], + "mimeTypes": [ + "application/pkix-cert" + ], + "description": "Internet security certificate", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.crt-certificate", + "belongingToTypes": [ + "general.certificate" + ], + "filenameExtensions": [ + ".crt" + ], + "mimeTypes": [ + "application/x-x509-ca-cert", + "application/x-x509-server-cert", + "application/x-x509-user-cert" + ], + "description": "Security Certificate", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.crl-certificate", + "belongingToTypes": [ + "general.certificate" + ], + "filenameExtensions": [ + ".crl" + ], + "mimeTypes": [ + "application/x-pkix-crl" + ], + "description": "Certificate revocation list file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.prn", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".prn" + ], + "mimeTypes": [], + "description": "Print to file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.chart", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".odc" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.chart" + ], + "description": "Open Document chart", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.text-master", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".odm" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.text-master" + ], + "description": "Open Document text master", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.text-web", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".oth" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.text-web" + ], + "description": "Open Document HTML template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.database", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.database" + ], + "filenameExtensions": [ + ".odb" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.database" + ], + "description": "Open Document database", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.image", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.image" + ], + "filenameExtensions": [ + ".odi" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.image" + ], + "description": "Open Document image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.formula-template", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".otf" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.formula-template" + ], + "description": "Open Document formula template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.chart-template", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".otc" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.chart-template" + ], + "description": "Open Document chart template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.presentation-template", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".otp" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.presentation-template" + ], + "description": "Open Document presentation template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.image-template", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.image" + ], + "filenameExtensions": [ + ".oti" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.image-template" + ], + "description": "Open Document image template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.graphics-template", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".otg" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.graphics-template" + ], + "description": "Open Document graphics template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.spreadsheet-template", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".ots" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.spreadsheet-template" + ], + "description": "Open Document spreadsheet template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.oasis-open.opendocument.text-template", + "belongingToTypes": [ + "org.oasis.opendocument", + "general.composite-object" + ], + "filenameExtensions": [ + ".ott" + ], + "mimeTypes": [ + "application/vnd.oasis.opendocument.text-template" + ], + "description": "Open Document text template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.word.dot", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dot" + ], + "mimeTypes": [ + "application/msword" + ], + "description": "Microsoft Word document template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.powerpoint.pps", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".pps" + ], + "mimeTypes": [ + "application/vnd.ms-powerpoint" + ], + "description": "Microsoft PowerPoint slide show", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.powerpoint.pot", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".pot" + ], + "mimeTypes": [ + "application/vnd.ms-powerpoint" + ], + "description": "Microsoft PowerPoint Template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.excel.xlt", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".xlt" + ], + "mimeTypes": [ + "application/vnd.ms-excel" + ], + "description": "Microsoft Excel spreadsheet template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.visio.vsd", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".vsd" + ], + "mimeTypes": [ + "application/vnd.visio" + ], + "description": "Microsoft Office Visio 2003-2010 drawing", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.drawingml.visio", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object" + ], + "filenameExtensions": [ + ".vsdx" + ], + "mimeTypes": [ + "application/vnd.openxmlformats-officedocument.drawingml.drawing" + ], + "description": "Microsoft Visio drawing", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.drawingml.template", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object" + ], + "filenameExtensions": [ + ".vstx" + ], + "mimeTypes": [], + "description": "Microsoft Visio drawing template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.drawingml.visio.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object" + ], + "filenameExtensions": [ + ".vsdm" + ], + "mimeTypes": [], + "description": "Visio macro-enabled drawing", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.drawingml.template.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object" + ], + "filenameExtensions": [ + ".vstm" + ], + "mimeTypes": [], + "description": "Visio macro-enabled drawing template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.wordprocessingml.template", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object" + ], + "filenameExtensions": [ + ".dotx" + ], + "mimeTypes": [ + "application/vnd.openxmlformats-officedocument.wordprocessingml.template" + ], + "description": "Office Open XML document template.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.presentationml.template", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object" + ], + "filenameExtensions": [ + ".potx" + ], + "mimeTypes": [ + "application/vnd.openxmlformats-officedocument.presentationml.template" + ], + "description": "Office Open XML presentation template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.presentationml.slideshow", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object" + ], + "filenameExtensions": [ + ".ppsx" + ], + "mimeTypes": [ + "application/vnd.openxmlformats-officedocument.presentationml.slideshow" + ], + "description": "Office Open XML slide show", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.spreadsheetml.template", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object" + ], + "filenameExtensions": [ + ".xltx" + ], + "mimeTypes": [ + "application/vnd.openxmlformats-officedocument.spreadsheetml.template" + ], + "description": "Office Open XML spreadsheet template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.wordprocessingml.document.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".docm" + ], + "mimeTypes": [ + "application/vnd.ms-word.document.macroEnabled.12" + ], + "description": "Office Open XML word processing document (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.wordprocessingml.template.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".dotm" + ], + "mimeTypes": [ + "application/vnd.ms-word.template.macroEnabled.12" + ], + "description": "Office Open XML word processing template (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.spreadsheetml.template.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".xltm" + ], + "mimeTypes": [ + "application/vnd.ms-excel.template.macroEnabled.12" + ], + "description": "Office Open XML spreadsheet template (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.spreadsheetml.addin.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".xlam" + ], + "mimeTypes": [ + "application/vnd.ms-excel.addin.macroEnabled.12" + ], + "description": "Office Open XML spreadsheet addin (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.spreadsheetml.binary.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".xlsb" + ], + "mimeTypes": [ + "application/vnd.ms-excel.sheet.binary.macroEnabled.12" + ], + "description": "Office Open XML spreadsheet binary (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.spreadsheetml.sheet.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".xlsm" + ], + "mimeTypes": [ + "application/vnd.ms-excel.sheet.macroEnabled.12" + ], + "description": "Office Open XML spreadsheet (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.presentationml.addin.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".ppam" + ], + "mimeTypes": [ + "application/vnd.ms-powerpoint.addin.macroEnabled.12" + ], + "description": "Office Open XML presentation addin (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.presentationml.presentation.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".pptm" + ], + "mimeTypes": [ + "application/vnd.ms-powerpoint.presentation.macroEnabled.12" + ], + "description": "Office Open XML presentation (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.presentationml.slideshow.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".ppsm" + ], + "mimeTypes": [ + "application/vnd.ms-powerpoint.slideshow.macroEnabled.12" + ], + "description": "Office Open XML slide show (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openxmlformats.presentationml.template.macroenabled", + "belongingToTypes": [ + "org.openxmlformats.openxml", + "general.composite-object", + "general.executable" + ], + "filenameExtensions": [ + ".potm" + ], + "mimeTypes": [ + "application/vnd.ms-powerpoint.template.macroEnabled.12" + ], + "description": "Office Open XML presentation template (macros enabled)", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "OpenOffice document format for open-source office software suite", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.calc", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sxc" + ], + "mimeTypes": [ + "application/vnd.sun.xml.calc" + ], + "description": "StarOffice Calc spreadsheet", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.draw", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sxd" + ], + "mimeTypes": [ + "application/vnd.sun.xml.draw" + ], + "description": "StarOffice Drawing", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.writer-global", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sxg" + ], + "mimeTypes": [ + "application/vnd.sun.xml.writer.global" + ], + "description": "Apache OpenOffice master document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.impress", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sxi" + ], + "mimeTypes": [ + "application/vnd.sun.xml.impress" + ], + "description": "StarOffice Impress presentation", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.math", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sxm" + ], + "mimeTypes": [ + "application/vnd.sun.xml.math" + ], + "description": "StarMath Formula", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.writer", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sxw" + ], + "mimeTypes": [ + "application/vnd.sun.xml.writer" + ], + "description": "StarOffice Writer document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.calc.template", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".stc" + ], + "mimeTypes": [ + "application/vnd.sun.xml.calc.template" + ], + "description": "StarOffice Calc spreadsheet template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.draw.template", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".std" + ], + "mimeTypes": [ + "application/vnd.sun.xml.draw.template" + ], + "description": "Apache OpenOffice Drawing template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.impress.template", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sti" + ], + "mimeTypes": [ + "application/vnd.sun.xml.impress.template" + ], + "description": "StarOffice Presentation template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openoffice.writer.template", + "belongingToTypes": [ + "org.openoffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".stw" + ], + "mimeTypes": [ + "application/vnd.sun.xml.writer.template" + ], + "description": "StarOffice Document template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "StarOffice document format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.draw", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sda" + ], + "mimeTypes": [ + "application/vnd.stardivision.draw" + ], + "description": "StarOffice Drawing", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.calc", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sdc" + ], + "mimeTypes": [ + "application/vnd.stardivision.calc" + ], + "description": "StarOffice Calc spreadsheet", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.impress", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sdd", + ".sdp" + ], + "mimeTypes": [ + "application/vnd.stardivision.impress" + ], + "description": "StarOffice Presentation", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.writer", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sdw" + ], + "mimeTypes": [ + "application/vnd.stardivision.writer" + ], + "description": "StarOffice Writer text document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.chart", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sds" + ], + "mimeTypes": [ + "application/vnd.stardivision.chart" + ], + "description": "StarOffice Chart", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.mail", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sdm" + ], + "mimeTypes": [ + "application/vnd.stardivision.mail" + ], + "description": "StarOffice Mail message", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.writer-global", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".sgl" + ], + "mimeTypes": [ + "application/vnd.stardivision.writer-global" + ], + "description": "StarOffice Master document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.math", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".smf" + ], + "mimeTypes": [ + "application/vnd.stardivision.math" + ], + "description": "StarMath Formula file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.staroffice.template", + "belongingToTypes": [ + "com.staroffice", + "general.composite-object" + ], + "filenameExtensions": [ + ".vor" + ], + "mimeTypes": [ + "application/vnd.stardivision.template" + ], + "description": "StarOffice Template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.tug.bib", + "belongingToTypes": [ + "general.tex" + ], + "filenameExtensions": [ + ".bib" + ], + "mimeTypes": [ + "text/x-bibtex" + ], + "description": "TeX Bibliography file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.tug.cls", + "belongingToTypes": [ + "general.tex" + ], + "filenameExtensions": [ + ".cls" + ], + "mimeTypes": [ + "text/x-tex" + ], + "description": "TeX Class file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.tug.sty", + "belongingToTypes": [ + "general.tex" + ], + "filenameExtensions": [ + ".sty" + ], + "mimeTypes": [ + "text/x-tex" + ], + "description": "TeX Style file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.tug.tex", + "belongingToTypes": [ + "general.tex" + ], + "filenameExtensions": [ + ".tex" + ], + "mimeTypes": [ + "text/x-tex" + ], + "description": "TeX source document file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.latex-project.latex", + "belongingToTypes": [ + "general.tex" + ], + "filenameExtensions": [ + ".ltx", + ".latex" + ], + "mimeTypes": [ + "application/x-latex" + ], + "description": "LaTeX source document file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.matroska.mkv", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".mkv" + ], + "mimeTypes": [ + "video/x-matroska" + ], + "description": "Matroska video", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.matroska.mka", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".mka" + ], + "mimeTypes": [ + "audio/x-matroska" + ], + "description": "Matroska audio", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.sgi.movie", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".movie" + ], + "mimeTypes": [ + "video/x-sgi-movie" + ], + "description": "SGI movie", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.apple.m4v", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".m4v" + ], + "mimeTypes": [ + "video/m4v" + ], + "description": "M4V video", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.webmproject.webm", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".webm" + ], + "mimeTypes": [ + "video/webm" + ], + "description": "WebM is an audiovisual media file format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.apple.quicktime-movie", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".mov", + ".qt", + ".movie" + ], + "mimeTypes": [ + "video/quicktime" + ], + "description": "QuickTime File Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.coreldraw.cdr", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".cdr" + ], + "mimeTypes": [ + "image/x-coreldraw" + ], + "description": "CorelDRAW file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.coreldraw.cdt", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".cdt" + ], + "mimeTypes": [ + "image/x-coreldrawtemplate" + ], + "description": "CorelDRAW template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.coreldraw.cpt", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".cpt" + ], + "mimeTypes": [ + "image/x-corelphotopaint" + ], + "description": "Corel PHOTO-PAINT image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.coreldraw.pat", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".pat" + ], + "mimeTypes": [ + "image/x-coreldrawpattern" + ], + "description": "CorelDRAW pattern file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.cur", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".cur" + ], + "mimeTypes": [ + "image/ico" + ], + "description": "Microsoft Windows cursor image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.sun.raster", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".ras" + ], + "mimeTypes": [ + "image/x-cmu-raster" + ], + "description": "Sun Raster Graphic", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.google.webp", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".webp" + ], + "mimeTypes": [ + "image/webp" + ], + "description": "WebP image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.sseyo.koan-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".skd", + ".skm", + ".skp", + ".skt" + ], + "mimeTypes": [ + "application/x-koan" + ], + "description": "Koan music files over the internet", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "io.qt.moc", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".moc" + ], + "mimeTypes": [ + "text/x-moc" + ], + "description": "Qt Meta-Object compiler file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.ghostscript.font", + "belongingToTypes": [ + "general.font" + ], + "filenameExtensions": [ + ".gsf" + ], + "mimeTypes": [ + "application/x-font" + ], + "description": "Ghostscript font", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.x.pcf-font", + "belongingToTypes": [ + "general.font" + ], + "filenameExtensions": [ + ".pcf" + ], + "mimeTypes": [ + "application/x-font", + "application/x-font-pcf" + ], + "description": "Portable compiled format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.windows-media-wmd", + "belongingToTypes": [ + "com.microsoft.advanced-systems-format", + "general.zip-archive" + ], + "filenameExtensions": [ + ".wmd" + ], + "mimeTypes": [ + "application/x-ms-wmd" + ], + "description": "Windows media download package", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.windows-media-wmz", + "belongingToTypes": [ + "com.microsoft.advanced-systems-format", + "general.zip-archive" + ], + "filenameExtensions": [ + ".wmz" + ], + "mimeTypes": [ + "application/x-ms-wmz" + ], + "description": "Windows media player skin package", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.windows-installer", + "belongingToTypes": [ + "general.executable" + ], + "filenameExtensions": [ + ".msi" + ], + "mimeTypes": [ + "application/x-msi" + ], + "description": "Windows installer package", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.publisher.pub", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".pub" + ], + "mimeTypes": [ + "application/x-mspublisher" + ], + "description": "Publisher document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.windows-media-playlist", + "belongingToTypes": [ + "general.xml", + "general.media" + ], + "filenameExtensions": [ + ".wpl" + ], + "mimeTypes": [ + "application/vnd.ms-wpl" + ], + "description": "Windows media player playlist", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.access.mdb", + "belongingToTypes": [ + "general.database" + ], + "filenameExtensions": [ + ".mdb" + ], + "mimeTypes": [ + "application/msaccess" + ], + "description": "Microsoft Access database", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.3dsystems.stereolithography", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".stl" + ], + "mimeTypes": [ + "application/vnd.ms-pki.stl" + ], + "description": "Stereolithography file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.apple.media.playlist", + "belongingToTypes": [ + "general.media" + ], + "filenameExtensions": [ + ".m3u8" + ], + "mimeTypes": [ + "application/vnd.apple.mpegurl" + ], + "description": "UTF-8 M3U playlist", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.abisource.word", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".abw" + ], + "mimeTypes": [ + "application/x-abiword" + ], + "description": "AbiWord document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.framemaker", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".book", + ".fm", + ".frame", + ".maker" + ], + "mimeTypes": [ + "application/x-maker" + ], + "description": "FrameMaker book file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.wolfram.cdf", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".cdf" + ], + "mimeTypes": [ + "application/x-cdf" + ], + "description": "Computable document format file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "de.cinderella.cdy", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".cdy" + ], + "mimeTypes": [ + "application/vnd.cinderella" + ], + "description": "Cinderella construction file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.dcr", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".dcr" + ], + "mimeTypes": [ + "application/x-director" + ], + "description": "Shockwave media file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.dir", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".dir" + ], + "mimeTypes": [ + "application/x-director" + ], + "description": "Adobe Director movie", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.dxr", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".dxr" + ], + "mimeTypes": [ + "application/x-director" + ], + "description": "Protected macromedia director movie", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.gnumeric.spreadsheet", + "belongingToTypes": [ + "general.xml" + ], + "filenameExtensions": [ + ".gnumeric" + ], + "mimeTypes": [ + "application/x-gnumeric" + ], + "description": "Gnumeric spreadsheet", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.hdfgroup.hdf", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".hdf" + ], + "mimeTypes": [ + "application/x-hdf" + ], + "description": "Hierarchical data format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.apple.binhex-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".hqx" + ], + "mimeTypes": [ + "application/mac-binhex40" + ], + "description": "BinHex 4.0 encoded file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.hta", + "belongingToTypes": [ + "general.archive", + "general.executable" + ], + "filenameExtensions": [ + ".hta" + ], + "mimeTypes": [ + "application/hta" + ], + "description": "HTML application", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.internet.ins", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".ins" + ], + "mimeTypes": [ + "application/x-internet-signup" + ], + "description": "Internet settings file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.internet.isp", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".isp" + ], + "mimeTypes": [ + "application/x-internet-signup" + ], + "description": "IIS internet service provider settings", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.troff", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".man", + ".t", + ".roff" + ], + "mimeTypes": [ + "text/troff" + ], + "description": "Unix troff format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.framemaker.mif", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".mif" + ], + "mimeTypes": [ + "application/vnd.mif" + ], + "description": "FrameMaker interchange format file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "io.sourceforge.freemind", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".mm" + ], + "mimeTypes": [ + "application/x-freemind" + ], + "description": "Mind Map file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.yamaha.smaf", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".mmf" + ], + "mimeTypes": [ + "application/vnd.smaf" + ], + "description": "Synthetic music mobile application file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.wolfram.mathematica.notebook", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".nb" + ], + "mimeTypes": [ + "application/mathematica" + ], + "description": "Mathematica notebook", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.xiph.ogg", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".oga", + ".ogg" + ], + "mimeTypes": [ + "application/ogg" + ], + "description": "Ogg vorbis audio", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.netscape.proxy-autoconfig", + "belongingToTypes": [ + "general.plain-text" + ], + "filenameExtensions": [ + ".pac" + ], + "mimeTypes": [ + "application/x-ns-proxy-autoconfig" + ], + "description": "Proxy auto-config file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.rsa.pkcs-12", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".pfx", + ".p12" + ], + "mimeTypes": [ + "application/x-pkcs12" + ], + "description": "PKCS #12 certificate file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.openpgp.signature", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [ + ".pgp" + ], + "mimeTypes": [ + "application/pgp-signature" + ], + "description": "PGP security key", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.apple.quicktime-link", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".qtl" + ], + "mimeTypes": [ + "application/x-quicktimeplayer" + ], + "description": "QuickTime link file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.rarlab.rar-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".rar" + ], + "mimeTypes": [ + "application/rar", + "application/vnd.rar" + ], + "description": "WinRAR compressed archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.7-zip.7-zip-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".7z" + ], + "mimeTypes": [ + "application/x-7z-compressed" + ], + "description": "7-zip compressed archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.red-bean.sgf", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".sgf" + ], + "mimeTypes": [ + "application/x-go-sgf" + ], + "description": "Smart game format file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.stuffit.sit-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".sit" + ], + "mimeTypes": [ + "application/x-stuffit" + ], + "description": "Stuffit archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.futuresplash", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".spl" + ], + "mimeTypes": [ + "application/futuresplash", + "application/x-futuresplash" + ], + "description": "FutureSplash animation", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.flash", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".swf", + ".flv" + ], + "mimeTypes": [ + "application/x-shockwave-flash", + "video/x-flv" + ], + "description": "Shockwave flash movie", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.gnu.texinfo", + "belongingToTypes": [ + "general.source-code" + ], + "filenameExtensions": [ + ".texinfo", + ".texi" + ], + "mimeTypes": [ + "application/x-texinfo" + ], + "description": "GNU Texinfo", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.bittorrent.torrent", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".torrent" + ], + "mimeTypes": [ + "application/x-bittorrent" + ], + "description": "BitTorrent file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.idsoftware.doom", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".wad" + ], + "mimeTypes": [ + "application/x-doom" + ], + "description": "Doom WAD file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.apple.webarchive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".webarchive" + ], + "mimeTypes": [ + "application/x-webarchive" + ], + "description": "Safari web archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.android.webarchive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".webarchivexml" + ], + "mimeTypes": [ + "application/x-webarchive-xml" + ], + "description": "Android web browser archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.gimp.xcf", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".xcf" + ], + "mimeTypes": [ + "application/x-xcf", + "image/x-xcf" + ], + "description": "eXperimental computing facility, GIMP image file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.edrawsoft.edrawmax", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".eddx" + ], + "mimeTypes": [ + "application/x-eddx" + ], + "description": "Edraw Max XML file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.edrawsoft.edrawmind", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".emmx" + ], + "mimeTypes": [ + "application/x-emmx" + ], + "description": "Edraw MindMaster XML file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "net.cnki.caj", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".caj" + ], + "mimeTypes": [ + "application/caj" + ], + "description": "Chinese academic journal file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.dbase.dbf", + "belongingToTypes": [ + "general.database" + ], + "filenameExtensions": [ + ".dbf" + ], + "mimeTypes": [ + "application/dbf", + "application/dbase" + ], + "description": "Database file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.dwg", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dwg" + ], + "mimeTypes": [ + "image/vnd.dwg" + ], + "description": "AutoCAD drawing", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.dxf", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dxf" + ], + "mimeTypes": [ + "image/vnd.dxf" + ], + "description": "Drawing exchange format file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.dws", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dws" + ], + "mimeTypes": [], + "description": "AutoCAD drawing standards file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.dwt", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dwt" + ], + "mimeTypes": [], + "description": "AutoCAD drawing template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.dwf", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dwf" + ], + "mimeTypes": [ + "model/vnd.dwf" + ], + "description": "Design web format file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.dwfx", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dwfx" + ], + "mimeTypes": [], + "description": "Design web format XPS file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.shp", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".shp" + ], + "mimeTypes": [], + "description": "3D studio shape", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.shx", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".shx" + ], + "mimeTypes": [], + "description": "AutoCAD compiled shape file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.slide-library", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".slb" + ], + "mimeTypes": [], + "description": "AutoCAD slide library", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.line", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".lin" + ], + "mimeTypes": [], + "description": "AutoCAD linetype file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.autodesk.plotter", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".plt" + ], + "mimeTypes": [], + "description": "AutoCAD plotter document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.hp.graphics-language", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".hpgl" + ], + "mimeTypes": [ + "application/vnd.hp-hpgl" + ], + "description": "HP graphics language plotter file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.metafile", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".wmf" + ], + "mimeTypes": [], + "description": "Windows metafile", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.spatial.acis.sat", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".sat" + ], + "mimeTypes": [], + "description": "ACIS SAT 3D model", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.aomedia.avif-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".avif" + ], + "mimeTypes": [ + "image/avif" + ], + "description": "AVIF image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.dds", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".dds" + ], + "mimeTypes": [ + "image/vnd-ms.dds" + ], + "description": "DirectDraw surface image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.ea.iff-ilbm", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".ilbm" + ], + "mimeTypes": [ + "image/x-ilbm" + ], + "description": "Interleaved bitmap image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.canon.cr2-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".cr2" + ], + "mimeTypes": [ + "image/x-canon-cr2" + ], + "description": "Canon raw 2 image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.canon.cr3-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".cr3" + ], + "mimeTypes": [ + "image/x-canon-cr3" + ], + "description": "Canon raw 3 image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.canon.crw-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".crw" + ], + "mimeTypes": [ + "image/x-canon-crw" + ], + "description": "Canon raw CIFF image file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.dng-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".dng" + ], + "mimeTypes": [ + "image/x-adobe-dng" + ], + "description": "Digital negative image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.sony.arw-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".arw" + ], + "mimeTypes": [ + "image/x-sony-arw" + ], + "description": "Sony alpha raw digital camera image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.nikon.nef-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".nef" + ], + "mimeTypes": [ + "image/x-nikon-nef" + ], + "description": "Nikon electronic format RAW image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.mindjet.mindmanager.mmap", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".mmap" + ], + "mimeTypes": [], + "description": "MindManager Map", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.email", + "belongingToTypes": [ + "general.message" + ], + "filenameExtensions": [ + ".eml" + ], + "mimeTypes": [ + "message/rfc822" + ], + "description": "E-Mail message", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.message", + "belongingToTypes": [ + "general.message" + ], + "filenameExtensions": [ + ".msg" + ], + "mimeTypes": [], + "description": "Outlook message item file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.pst", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".pst" + ], + "mimeTypes": [], + "description": "Outlook personal information store", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Kingsoft office suite", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office.writer.wps", + "belongingToTypes": [ + "com.kingsoft.office", + "general.composite-object" + ], + "filenameExtensions": [ + ".wps" + ], + "mimeTypes": [], + "description": "Kingsoft Writer document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office.writer.wpt", + "belongingToTypes": [ + "com.kingsoft.office", + "general.composite-object" + ], + "filenameExtensions": [ + ".wpt" + ], + "mimeTypes": [], + "description": "Kingsoft Writer template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office.presentation.dps", + "belongingToTypes": [ + "com.kingsoft.office", + "general.composite-object" + ], + "filenameExtensions": [ + ".dps" + ], + "mimeTypes": [], + "description": "Kingsoft Presentation file", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office.presentation.template", + "belongingToTypes": [ + "com.kingsoft.office", + "general.composite-object" + ], + "filenameExtensions": [ + ".dpt" + ], + "mimeTypes": [], + "description": "Kingsoft Presentation template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office.spreadsheets.et", + "belongingToTypes": [ + "com.kingsoft.office", + "general.composite-object" + ], + "filenameExtensions": [ + ".et" + ], + "mimeTypes": [], + "description": "Kingsoft Spreadsheets tile", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office.spreadsheets.template", + "belongingToTypes": [ + "com.kingsoft.office", + "general.composite-object" + ], + "filenameExtensions": [ + ".ett" + ], + "mimeTypes": [], + "description": "Kingsoft Spreadsheets template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.ini", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".ini" + ], + "mimeTypes": [], + "description": "Windows Initialization File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.json", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".json" + ], + "mimeTypes": [ + "application/json" + ], + "description": "JavaScript Object Notation File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.yaml", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".yaml", + ".yml" + ], + "mimeTypes": [ + "application/yaml" + ], + "description": "YAML Document", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.log", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".log" + ], + "mimeTypes": [ + "text/plain" + ], + "description": "Log File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.uri", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Universal Resource Identifier", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.file-uri", + "belongingToTypes": [ + "general.uri" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "File URI", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.text-lst", + "belongingToTypes": [ + "general.plain-text" + ], + "filenameExtensions": [ + ".lst" + ], + "mimeTypes": [], + "description": "Data List", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.android.apk", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".apk", + ".apks", + ".aab", + ".xapk", + ".apkm", + ".akp" + ], + "mimeTypes": [ + "application/vnd.android.package-archive" + ], + "description": "Android Package File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.postscript-pfb-font", + "belongingToTypes": [ + "com.adobe.postscript-font" + ], + "filenameExtensions": [ + ".pfb" + ], + "mimeTypes": [ + "application/x-font" + ], + "description": "Printer Font Binary, PostScript Type 1 outline font.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.postscript-pfa-font", + "belongingToTypes": [ + "com.adobe.postscript-font" + ], + "filenameExtensions": [ + ".pfa" + ], + "mimeTypes": [ + "application/x-font" + ], + "description": "Printer Pont ASCII file, PostScript Type 1 outline font.", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.bz-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".bz" + ], + "mimeTypes": [ + "application/x-bzip" + ], + "description": "Bzip Compressed File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.tar-bzip-archive", + "belongingToTypes": [ + "general.bz-archive" + ], + "filenameExtensions": [ + ".tbz" + ], + "mimeTypes": [ + "application/x-bzip-compressed-tar" + ], + "description": "Bzip Compressed Tar Archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.tar-bzip2-archive", + "belongingToTypes": [ + "general.bz2-archive" + ], + "filenameExtensions": [ + ".tbz2" + ], + "mimeTypes": [ + "application/x-bzip2-compressed-tar" + ], + "description": "Bzip2-Compressed TAR File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.tukaani.xz-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".xz" + ], + "mimeTypes": [ + "application/x-xz" + ], + "description": "XZ Compressed Archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.tukaani.tar-xz-archive", + "belongingToTypes": [ + "org.tukaani.xz-archive" + ], + "filenameExtensions": [ + ".txz" + ], + "mimeTypes": [ + "application/x-xz-compressed-tar" + ], + "description": "XZ Compressed Tar Archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.xar-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".xar" + ], + "mimeTypes": [ + "application/x-xar" + ], + "description": "Extensible Archive Fromat", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.cab-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".cab" + ], + "mimeTypes": [ + "application/vnd.ms-cab-compressed" + ], + "description": "Windows Cabinet File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "redhat.rpm-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".rpm" + ], + "mimeTypes": [ + "application/x-rpm" + ], + "description": "RedHat Package Manager File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.godotengine.tpz-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".tpz" + ], + "mimeTypes": [], + "description": "Godot Engine Export Template Archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.lza-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".lza" + ], + "mimeTypes": [ + "application/x-lzh-compressed" + ], + "description": "LZA Compressed Archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.arj-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".arj" + ], + "mimeTypes": [ + "application/x-arj" + ], + "description": "ARJ Compressed File Archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.winzip.zipx", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".zipx" + ], + "mimeTypes": [], + "description": "Extended Zip Archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.lzma-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".lzma" + ], + "mimeTypes": [ + "application/x-lzma" + ], + "description": "LZMA Compressed File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.lzma86-archive", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".lzma86" + ], + "mimeTypes": [], + "description": "LZMA86 Compressed File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.mozilla.xpinstall", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".xpi" + ], + "mimeTypes": [ + "application/x-xpinstall" + ], + "description": "Cross-platform Installer Package", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.hfs-disk-image", + "belongingToTypes": [ + "general.disk-image" + ], + "filenameExtensions": [ + ".hfs" + ], + "mimeTypes": [], + "description": "HFS Disk Image File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.img-disk-image", + "belongingToTypes": [ + "general.disk-image" + ], + "filenameExtensions": [ + ".img" + ], + "mimeTypes": [ + "application/x-raw-disk-image" + ], + "description": "Disc Image Data File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.ezbsystems.zipped-iso", + "belongingToTypes": [ + "general.disk-image" + ], + "filenameExtensions": [ + ".isz" + ], + "mimeTypes": [], + "description": "Zipped ISO Disk Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.wim", + "belongingToTypes": [ + "general.disk-image" + ], + "filenameExtensions": [ + ".wim" + ], + "mimeTypes": [ + "application/x-ms-wim" + ], + "description": "Windows Imaging Format File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.swm", + "belongingToTypes": [ + "general.disk-image" + ], + "filenameExtensions": [ + ".swm" + ], + "mimeTypes": [ + "application/x-ms-wim" + ], + "description": "Split Windows Imaging Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office.spreadsheets.etx", + "belongingToTypes": [ + "com.kingsoft.office", + "general.composite-object" + ], + "filenameExtensions": [ + ".etx" + ], + "mimeTypes": [], + "description": "Kingsoft Spreadsheets File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.kingsoft.office.spreadsheets.ettx", + "belongingToTypes": [ + "com.kingsoft.office", + "general.composite-object" + ], + "filenameExtensions": [ + ".ettx" + ], + "mimeTypes": [], + "description": "Kingsoft Spreadsheets Template", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.excel.dif", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dif" + ], + "mimeTypes": [], + "description": "Data interchange format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.app", + "belongingToTypes": [ + "openharmony.package" + ], + "filenameExtensions": [ + ".app" + ], + "mimeTypes": [], + "description": "OpenHarmony system defined application package", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.huawei.hmos.settings.wifi", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".hmoswifi" + ], + "mimeTypes": [], + "description": "HarmonyOS WIFI sharing setting", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.tel", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".tel" + ], + "mimeTypes": [], + "description": "TEL schematic diagram file format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ets", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".ets" + ], + "mimeTypes": [], + "description": "Extended TypeScript source code", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.json5", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".json5" + ], + "mimeTypes": [], + "description": "JSON5 data interchange format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.monkeysaudio.ape-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".ape" + ], + "mimeTypes": [ + "audio/x-monkeys-audio" + ], + "description": "Monkey's Audio", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.xiph.opus-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".opus" + ], + "mimeTypes": [ + "audio/opus" + ], + "description": "Opus Audio", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.conf", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".conf" + ], + "mimeTypes": [], + "description": "Generic Configuration File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.dos-batch", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".bat" + ], + "mimeTypes": [ + "application/x-bat" + ], + "description": "DOS Batch File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.vbscript", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".vbs" + ], + "mimeTypes": [ + "application/x-vbs" + ], + "description": "VBScript File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ion", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".ion" + ], + "mimeTypes": [], + "description": "File Description File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.registry", + "belongingToTypes": [ + "general.database" + ], + "filenameExtensions": [ + ".reg" + ], + "mimeTypes": [], + "description": "Registry File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.catalog", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [ + ".cat" + ], + "mimeTypes": [], + "description": "Windows Catalog File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.powershell-script", + "belongingToTypes": [ + "general.script" + ], + "filenameExtensions": [ + ".ps1" + ], + "mimeTypes": [], + "description": "Windows PowerShell Cmdlet File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.w3.woff", + "belongingToTypes": [ + "general.font" + ], + "filenameExtensions": [ + ".woff" + ], + "mimeTypes": [ + "font/woff" + ], + "description": "Web Open Font Format File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.sqlite.database", + "belongingToTypes": [ + "general.database" + ], + "filenameExtensions": [ + ".sqlite", + ".sqlite3", + ".db", + ".db3", + ".s3db", + ".sl3" + ], + "mimeTypes": [ + "application/vnd.sqlite3" + ], + "description": "SQLite Database", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.sys", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [ + ".sys" + ], + "mimeTypes": [], + "description": "Windows System File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.inf", + "belongingToTypes": [ + "general.text" + ], + "filenameExtensions": [ + ".inf" + ], + "mimeTypes": [ + "text/plain" + ], + "description": "Setup Information File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.pdb", + "belongingToTypes": [ + "general.database" + ], + "filenameExtensions": [ + ".pdb" + ], + "mimeTypes": [ + "application/x-ms-pdb" + ], + "description": "Program Database", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.tlb", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [ + ".tlb" + ], + "mimeTypes": [], + "description": "OLE Type Library", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.sccd", + "belongingToTypes": [ + "general.xml" + ], + "filenameExtensions": [ + ".sccd" + ], + "mimeTypes": [], + "description": "Signed Custom Capability Descriptor", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.adobe.f4v", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".f4v" + ], + "mimeTypes": [ + "video/mp4" + ], + "description": "Flash MP4 Video File", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mp2t", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".m2ts", + ".mts", + ".m2t" + ], + "mimeTypes": [ + "video/mp2t" + ], + "description": "Blu-ray BDAV Video File Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.youtube.video", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".yt", + ".vt" + ], + "mimeTypes": [ + "video/vnd.youtube.yt" + ], + "description": "Youtube Video format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.cisco.webex-video", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".wrf" + ], + "mimeTypes": [ + "video/x-webex" + ], + "description": "WebEx Recording", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mpeg-2", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".mpeg2", + ".mpv2", + ".mp2v", + ".m2v", + ".mpv" + ], + "mimeTypes": [ + "video/mpeg" + ], + "description": "MPEG-2 Video format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.mpeg-1", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".mpeg1", + ".mpv1", + ".mp1v", + ".m1v" + ], + "mimeTypes": [ + "video/mpeg" + ], + "description": "MPEG-1 Video format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.real.realmedia-vbr", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".rmvb" + ], + "mimeTypes": [ + "application/vnd.rn-realmedia-vbr" + ], + "description": "RealMedia Variable Bit Rate Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.real.realvideo", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".rv" + ], + "mimeTypes": [ + "video/x-pn-realvideo" + ], + "description": "RealVideo Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.divx-video", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".divx" + ], + "mimeTypes": [ + "video/divx" + ], + "description": "DivX-Encoded Movie", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "org.csiro.annodex", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".axv" + ], + "mimeTypes": [ + "video/annodex" + ], + "description": "Annodex Video Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ogv", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".ogv" + ], + "mimeTypes": [ + "video/ogg" + ], + "description": "Ogg Video Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.microsoft.lsf-video", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".lsf", + ".lsx" + ], + "mimeTypes": [ + "video/x-la-asf" + ], + "description": "Streaming Media Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.h264-video", + "belongingToTypes": [ + "general.video" + ], + "filenameExtensions": [ + ".h264" + ], + "mimeTypes": [ + "video/H264" + ], + "description": "H.264 Encoded Video Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.jpeg-2000", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".jp2", + ".jpg2", + ".jpx", + ".jpf", + ".jpm" + ], + "mimeTypes": [ + "image/jp2", + "image/jpx", + "image/jpm" + ], + "description": "JPEG 2000 Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.fujifilm.raf-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".raf" + ], + "mimeTypes": [ + "image/x-fuji-raf" + ], + "description": "Fujifilm RAW Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.nikon.nrw-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".nrw" + ], + "mimeTypes": [ + "image/x-nikon-nrw" + ], + "description": "Nikon Raw Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.panasonic.rw2-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".rw2", + ".raw" + ], + "mimeTypes": [ + "image/x-panasonic-raw" + ], + "description": "Panasonic RAW Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.pentax.pef-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".pef" + ], + "mimeTypes": [ + "image/x-pentax-pef" + ], + "description": "Pentax Electronic RAW Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.sumsung.srw-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".srw" + ], + "mimeTypes": [ + "image/x-samsung-srw" + ], + "description": "Samsung RAW Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.epson.erf-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".erf" + ], + "mimeTypes": [ + "image/x-epson-erf" + ], + "description": "Epson RAW Imager", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.olympus.orf-raw-image", + "belongingToTypes": [ + "general.raw-image" + ], + "filenameExtensions": [ + ".orf" + ], + "mimeTypes": [ + "image/x-olympus-orf" + ], + "description": "Olympus RAW Image", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ief-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".ief" + ], + "mimeTypes": [ + "image/ief" + ], + "description": "Image Exchange Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.aol.art-image", + "belongingToTypes": [ + "general.image" + ], + "filenameExtensions": [ + ".art" + ], + "mimeTypes": [ + "image/x-jg" + ], + "description": "ART image format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.content-form", + "belongingToTypes": [ + "general.object" + ], + "filenameExtensions": [], + "mimeTypes": [], + "description": "Content form format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "com.apple.m4p-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".m4p" + ], + "mimeTypes": [ + "audio/mp4" + ], + "description": "iTunes Music Store Audio File Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "general.ac3-audio", + "belongingToTypes": [ + "general.audio" + ], + "filenameExtensions": [ + ".ac3" + ], + "mimeTypes": [ + "audio/ac3" + ], + "description": "Audio Codec 3 File Format", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.hsp", + "belongingToTypes": [ + "openharmony.package" + ], + "filenameExtensions": [ + ".hsp" + ], + "mimeTypes": [], + "description": "Harmony Shared Package", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.har", + "belongingToTypes": [ + "openharmony.package" + ], + "filenameExtensions": [ + ".har" + ], + "mimeTypes": [], + "description": "Harmony Archive", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.gopaint", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".gopaint" + ], + "mimeTypes": [], + "description": "Gopaint file format defined for Openharmony", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.gobrush", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".gobrush" + ], + "mimeTypes": [], + "description": "Gobrush file format defined for Openharmony", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.gobrushes", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".gobrushes" + ], + "mimeTypes": [], + "description": "Gobrushes file format defined for Openharmony", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.gocolor", + "belongingToTypes": [ + "general.archive" + ], + "filenameExtensions": [ + ".gocolor" + ], + "mimeTypes": [], + "description": "Gocolor file format defined for Openharmony", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + }, + { + "typeId": "openharmony.dlp", + "belongingToTypes": [ + "general.composite-object" + ], + "filenameExtensions": [ + ".dlp" + ], + "mimeTypes": [], + "description": "Account identify encryption file format defined by OpenHarmony", + "referenceURL": "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype" + } + ] +} \ No newline at end of file diff --git a/udmf/framework/common/concurrent_map.h b/udmf/framework/common/concurrent_map.h new file mode 100644 index 00000000..d0b2dbe8 --- /dev/null +++ b/udmf/framework/common/concurrent_map.h @@ -0,0 +1,305 @@ +/* + * 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 OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_CONCURRENT_MAP_H +#define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_CONCURRENT_MAP_H +#include +#include +#include +namespace OHOS { +template +class ConcurrentMap { + template + static _First First(); + +public: + using map_type = typename std::map<_Key, _Tp>; + using filter_type = typename std::function; + using key_type = typename std::map<_Key, _Tp>::key_type; + using mapped_type = typename std::map<_Key, _Tp>::mapped_type; + using value_type = typename std::map<_Key, _Tp>::value_type; + using size_type = typename std::map<_Key, _Tp>::size_type; + using reference = typename std::map<_Key, _Tp>::reference; + using const_reference = typename std::map<_Key, _Tp>::const_reference; + + ConcurrentMap() = default; + ~ConcurrentMap() + { + Clear(); + } + + ConcurrentMap(const ConcurrentMap &other) + { + operator=(std::move(other)); + } + + ConcurrentMap &operator=(const ConcurrentMap &other) noexcept + { + if (this == &other) { + return *this; + } + auto tmp = other.Clone(); + std::lock_guard lock(mutex_); + entries_ = std::move(tmp); + return *this; + } + + ConcurrentMap(ConcurrentMap &&other) noexcept + { + operator=(std::move(other)); + } + + ConcurrentMap &operator=(ConcurrentMap &&other) noexcept + { + if (this == &other) { + return *this; + } + auto tmp = other.Steal(); + std::lock_guard lock(mutex_); + entries_ = std::move(tmp); + return *this; + } + + bool Emplace() noexcept + { + std::lock_guard lock(mutex_); + auto it = entries_.emplace(); + return it.second; + } + + template + typename std::enable_if()), filter_type>, bool>::type + Emplace(_Args &&...args) noexcept + { + std::lock_guard lock(mutex_); + auto it = entries_.emplace(std::forward<_Args>(args)...); + return it.second; + } + + template + typename std::enable_if, bool>::type + Emplace(const _Filter &filter, _Args &&...args) noexcept + { + std::lock_guard lock(mutex_); + if (!filter(entries_)) { + return false; + } + auto it = entries_.emplace(std::forward<_Args>(args)...); + return it.second; + } + + std::pair Find(const key_type &key) const noexcept + { + std::lock_guard lock(mutex_); + auto it = entries_.find(key); + if (it == entries_.end()) { + return std::pair { false, mapped_type() }; + } + + return std::pair { true, it->second }; + } + + bool ContainIf(const key_type &key, const std::function &action) const noexcept + { + std::lock_guard lock(mutex_); + auto it = entries_.find(key); + if (it == entries_.end()) { + return false; + } + if (action) { + return action(it->second); + } + return true; + } + + bool Contains(const key_type &key) const noexcept + { + std::lock_guard lock(mutex_); + return (entries_.find(key) != entries_.end()); + } + + template + bool InsertOrAssign(const key_type &key, _Obj &&obj) noexcept + { + std::lock_guard lock(mutex_); + auto it = entries_.insert_or_assign(key, std::forward<_Obj>(obj)); + return it.second; + } + + bool Insert(const key_type &key, const mapped_type &value) noexcept + { + std::lock_guard lock(mutex_); + auto it = entries_.insert(value_type { key, value }); + return it.second; + } + + size_type Erase(const key_type &key) noexcept + { + std::lock_guard lock(mutex_); + return entries_.erase(key); + } + + void Clear() noexcept + { + std::lock_guard lock(mutex_); + return entries_.clear(); + } + + bool Empty() const noexcept + { + std::lock_guard lock(mutex_); + return entries_.empty(); + } + + size_type Size() const noexcept + { + std::lock_guard lock(mutex_); + return entries_.size(); + } + + // The action`s return true means meeting the erase condition + // The action`s return false means not meeting the erase condition + size_type EraseIf(const std::function &action) noexcept + { + if (action == nullptr) { + return 0; + } + std::lock_guard lock(mutex_); +#if __cplusplus > 201703L + auto count = std::erase_if(entries_, + [&action](value_type &value) -> bool { return action(value.first, value.second); }); +#else + auto count = entries_.size(); + for (auto it = entries_.begin(); it != entries_.end();) { + if (action((*it).first, (*it).second)) { + it = entries_.erase(it); + } else { + ++it; + } + } + count -= entries_.size(); +#endif + return count; + } + + void ForEach(const std::function &action) + { + if (action == nullptr) { + return; + } + std::lock_guard lock(mutex_); + for (auto &[key, value] : entries_) { + if (action(key, value)) { + break; + } + } + } + + void ForEachCopies(const std::function &action) + { + if (action == nullptr) { + return; + } + auto entries = Clone(); + for (auto &[key, value] : entries) { + if (action(key, value)) { + break; + } + } + } + + // The action's return value means that the element is keep in map or not; true means keeping, false means removing. + bool Compute(const key_type &key, const std::function &action) + { + if (action == nullptr) { + return false; + } + std::lock_guard lock(mutex_); + auto it = entries_.find(key); + if (it == entries_.end()) { + auto result = entries_.emplace(key, mapped_type()); + it = result.second ? result.first : entries_.end(); + } + if (it == entries_.end()) { + return false; + } + if (!action(it->first, it->second)) { + entries_.erase(key); + } + return true; + } + + // The action's return value means that the element is keep in map or not; true means keeping, false means removing. + bool ComputeIfPresent(const key_type &key, const std::function &action) + { + if (action == nullptr) { + return false; + } + std::lock_guard lock(mutex_); + auto it = entries_.find(key); + if (it == entries_.end()) { + return false; + } + if (!action(key, it->second)) { + entries_.erase(key); + } + return true; + } + + bool ComputeIfAbsent(const key_type &key, const std::function &action) + { + if (action == nullptr) { + return false; + } + std::lock_guard lock(mutex_); + auto it = entries_.find(key); + if (it != entries_.end()) { + return false; + } + entries_.emplace(key, action(key)); + return true; + } + + void DoActionIfEmpty(const std::function &action) + { + if (action == nullptr) { + return; + } + std::lock_guard lock(mutex_); + if (entries_.empty()) { + action(); + } + return; + } + +private: + std::map<_Key, _Tp> Steal() noexcept + { + std::lock_guard lock(mutex_); + return std::move(entries_); + } + + std::map<_Key, _Tp> Clone() const noexcept + { + std::lock_guard lock(mutex_); + return entries_; + } + +private: + mutable std::recursive_mutex mutex_; + std::map<_Key, _Tp> entries_; +}; +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_CONCURRENT_MAP_H diff --git a/udmf/framework/common/custom_utd_json_parser.cpp b/udmf/framework/common/custom_utd_json_parser.cpp index 4de2c31e..cc43d21e 100644 --- a/udmf/framework/common/custom_utd_json_parser.cpp +++ b/udmf/framework/common/custom_utd_json_parser.cpp @@ -26,6 +26,7 @@ constexpr const char* REFERENCE_URL = "referenceURL"; constexpr const char* ICON_FILE = "iconFile"; constexpr const char* OWNER = "ownerBundle"; constexpr const char* INSTALLERS = "installerBundles"; +constexpr const int32_t MAX_UTD_CUSTOM_SIZE = 1024 * 1024; CustomUtdJsonParser::CustomUtdJsonParser() { @@ -43,8 +44,19 @@ bool CustomUtdJsonParser::ParseStoredCustomUtdJson(const std::string &jsonData, } cJSON* jsonRoot = cJSON_Parse(jsonData.c_str()); - if (jsonRoot != NULL && cJSON_IsObject(jsonRoot)) { - GetTypeDescriptors(*jsonRoot, UTD_CUSTOM, typesCfg); + if (jsonRoot == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Failed to parse JSON: invalid format"); + return false; + } + if (!cJSON_IsObject(jsonRoot)) { + LOG_ERROR(UDMF_CLIENT, "Parsed JSON root is not an object"); + cJSON_Delete(jsonRoot); + return false; + } + if (!GetTypeDescriptors(*jsonRoot, UTD_CUSTOM, typesCfg)) { + LOG_ERROR(UDMF_CLIENT, "Failed to get type descriptors"); + cJSON_Delete(jsonRoot); + return false; } cJSON_Delete(jsonRoot); return true; @@ -59,12 +71,23 @@ bool CustomUtdJsonParser::ParseUserCustomUtdJson(const std::string &jsonData, } // parse utd-adt.json to TypeDescriptorCfg obj cJSON* jsonRoot = cJSON_Parse(jsonData.c_str()); - if (jsonRoot != NULL && cJSON_IsObject(jsonRoot)) { - GetTypeDescriptors(*jsonRoot, UTD_CUSTOM_DECLAEEARION, typesDeclarations); - GetTypeDescriptors(*jsonRoot, UTD_CUSTOM_REFERENCE, typesReference); + if (jsonRoot == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Parse failed: invalid JSON format."); + return false; + } + if (!cJSON_IsObject(jsonRoot)) { + LOG_ERROR(UDMF_CLIENT, "Parsed JSON root is not an object"); + cJSON_Delete(jsonRoot); + return false; + } + if (!GetTypeDescriptors(*jsonRoot, UTD_CUSTOM_DECLARATION, typesDeclarations) || + !GetTypeDescriptors(*jsonRoot, UTD_CUSTOM_REFERENCE, typesReference)) { + LOG_ERROR(UDMF_CLIENT, "Failed to get type descriptors"); + cJSON_Delete(jsonRoot); + return false; } cJSON_Delete(jsonRoot); - LOG_DEBUG(UDMF_CLIENT, "DeclarationsSize:%{public}zu, ReferenceSize:%{public}zu", + LOG_INFO(UDMF_CLIENT, "DeclarationsSize:%{public}zu, ReferenceSize:%{public}zu", typesDeclarations.size(), typesReference.size()); return true; } @@ -122,18 +145,22 @@ bool CustomUtdJsonParser::GetTypeDescriptors(const json &jsonRoot, const std::st if (cJSON_HasObjectItem(&jsonRoot, nodeName.c_str())) { cJSON *subNode = cJSON_GetObjectItem(&jsonRoot, nodeName.c_str()); int itemNum = cJSON_GetArraySize(subNode); + if (itemNum > MAX_UTD_CUSTOM_SIZE) { + LOG_ERROR(UDMF_CLIENT, "itemNum is too large, itemNum:%{public}d", itemNum); + return false; + } for (int i = 0; i < itemNum; i++) { - cJSON *node = cJSON_GetArrayItem(subNode, i); + const cJSON *node = cJSON_GetArrayItem(subNode, i); TypeDescriptorCfg typeCfg; - typeCfg.typeId = GetStringValue(*node, TYPEID); - typeCfg.belongingToTypes = GetStringArrayValue(*node, BELONGINGTOTYPES); - typeCfg.filenameExtensions = GetStringArrayValue(*node, FILE_NAME_EXTENSTENSIONS); - typeCfg.mimeTypes = GetStringArrayValue(*node, MIME_TYPES); - typeCfg.description = GetStringValue(*node, DESCRIPTION); - typeCfg.referenceURL = GetStringValue(*node, REFERENCE_URL); - typeCfg.iconFile = GetStringValue(*node, ICON_FILE); - typeCfg.ownerBundle = GetStringValue(*node, OWNER); - std::vector installerBundles = GetStringArrayValue(*node, INSTALLERS); + typeCfg.typeId = GetStringValue(node, TYPEID); + typeCfg.belongingToTypes = GetStringArrayValue(node, BELONGINGTOTYPES); + typeCfg.filenameExtensions = GetStringArrayValue(node, FILE_NAME_EXTENSTENSIONS); + typeCfg.mimeTypes = GetStringArrayValue(node, MIME_TYPES); + typeCfg.description = GetStringValue(node, DESCRIPTION); + typeCfg.referenceURL = GetStringValue(node, REFERENCE_URL); + typeCfg.iconFile = GetStringValue(node, ICON_FILE); + typeCfg.ownerBundle = GetStringValue(node, OWNER); + std::vector installerBundles = GetStringArrayValue(node, INSTALLERS); typeCfg.installerBundles.insert(installerBundles.begin(), installerBundles.end()); typesCfg.push_back(typeCfg); } @@ -141,11 +168,11 @@ bool CustomUtdJsonParser::GetTypeDescriptors(const json &jsonRoot, const std::st return true; } -std::string CustomUtdJsonParser::GetStringValue(const json &node, const std::string &nodeName) +std::string CustomUtdJsonParser::GetStringValue(const json *node, const std::string &nodeName) { std::string value; - if (!cJSON_IsNull(&node) && cJSON_IsObject(&node) && cJSON_HasObjectItem(&node, nodeName.c_str())) { - cJSON *subNode = cJSON_GetObjectItem(&node, nodeName.c_str()); + if (!cJSON_IsNull(node) && cJSON_IsObject(node) && cJSON_HasObjectItem(node, nodeName.c_str())) { + cJSON *subNode = cJSON_GetObjectItem(node, nodeName.c_str()); if (cJSON_IsString(subNode)) { value = cJSON_GetStringValue(subNode); } @@ -153,11 +180,11 @@ std::string CustomUtdJsonParser::GetStringValue(const json &node, const std::str return value; } -std::vector CustomUtdJsonParser::GetStringArrayValue(const json &node, const std::string &nodeName) +std::vector CustomUtdJsonParser::GetStringArrayValue(const json *node, const std::string &nodeName) { std::vector values; - if (!cJSON_IsNull(&node) && cJSON_IsObject(&node) && cJSON_HasObjectItem(&node, nodeName.c_str())) { - cJSON *subNode = cJSON_GetObjectItem(&node, nodeName.c_str()); + if (!cJSON_IsNull(node) && cJSON_IsObject(node) && cJSON_HasObjectItem(node, nodeName.c_str())) { + cJSON *subNode = cJSON_GetObjectItem(node, nodeName.c_str()); if (cJSON_IsNull(subNode) || !cJSON_IsArray(subNode)) { return values; } diff --git a/udmf/framework/common/custom_utd_json_parser.h b/udmf/framework/common/custom_utd_json_parser.h index c7bd6264..71d41081 100644 --- a/udmf/framework/common/custom_utd_json_parser.h +++ b/udmf/framework/common/custom_utd_json_parser.h @@ -33,13 +33,13 @@ public: bool ParseUserCustomUtdJson(const std::string &jsonData, std::vector &typesDeclarations, std::vector &typesReference); bool ConvertUtdCfgsToJson(const std::vector &typesCfg, std::string &jsonData); + bool GetTypeDescriptors(const json &jsonRoot, const std::string &nodeName, + std::vector &typesCfg); private: bool AddJsonStringArray(const std::vector &datas, const std::string &nodeName, json &node); - bool GetTypeDescriptors(const json &jsonRoot, const std::string &nodeName, - std::vector &typesCfg); - std::string GetStringValue(const json &node, const std::string &nodeName); - std::vector GetStringArrayValue(const json &node, const std::string &nodeName); + std::string GetStringValue(const json *node, const std::string &nodeName); + std::vector GetStringArrayValue(const json *node, const std::string &nodeName); }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/common/custom_utd_store.cpp b/udmf/framework/common/custom_utd_store.cpp index e7e11dbb..af187ae6 100644 --- a/udmf/framework/common/custom_utd_store.cpp +++ b/udmf/framework/common/custom_utd_store.cpp @@ -15,6 +15,7 @@ #define LOG_TAG "CustomUtdStore" #include "custom_utd_store.h" #include +#include #include #include "logger.h" #include "preset_type_descriptors.h" @@ -46,73 +47,83 @@ CustomUtdStore &CustomUtdStore::GetInstance() return utdCustomPersistence; } -std::vector CustomUtdStore::GetHapTypeCfgs() +std::vector CustomUtdStore::GetCustomUtd(bool isHap, int32_t userId) { - LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg, Path:%{public}s.", CUSTOM_UTD_HAP_DIR); - std::string jsonStr; - std::ifstream fin(CUSTOM_UTD_HAP_DIR); - while (fin.good()) { - std::string line; - std::getline(fin, line); - jsonStr += line; - } - std::vector customUtdTypes; - utdJsonParser_.ParseStoredCustomUtdJson(jsonStr, customUtdTypes); - LOG_DEBUG(UDMF_CLIENT, "GetTypeCfgs, customUtdTypes total:%{public}zu.", customUtdTypes.size()); - return customUtdTypes; + std::string path = GetCustomUtdPath(isHap, userId); + LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg"); + + std::vector customUtd; + std::ifstream fin(path); + if (!fin.is_open()) { + LOG_ERROR(UDMF_CLIENT, "Failed to open custom utd file, errno=%{public}d", errno); + return customUtd; + } + + std::ostringstream buffer; + buffer << fin.rdbuf(); + if (fin.fail() && !fin.eof()) { + LOG_ERROR(UDMF_CLIENT, "Error reading file, errno=%{public}d", errno); + return customUtd; + } + + std::string jsonStr = buffer.str(); + if (!utdJsonParser_.ParseStoredCustomUtdJson(jsonStr, customUtd)) { + LOG_ERROR(UDMF_CLIENT, "Failed to parse custom utd json"); + customUtd.clear(); + } + LOG_DEBUG(UDMF_CLIENT, "CustomUtd total:%{public}zu.", customUtd.size()); + return customUtd; } -std::vector CustomUtdStore::GetTypeCfgs(int32_t userId) +std::string CustomUtdStore::GetCustomUtdPath(bool isHap, int32_t userId) { - std::string path = CUSTOM_UTD_SA_DIR + std::to_string(userId) + CUSTOM_UTD_SA_SUB_DIR; - std::string old_path = CUSTOM_UTD_SA_DIR + std::to_string(userId) + OLD_CUSTOM_UTD_SA_SUB_DIR; - std::string cfgFilePath = path; - if (access(path.c_str(), F_OK) != 0 && access(old_path.c_str(), F_OK) == 0) { - cfgFilePath = old_path; - } - cfgFilePath.append(UTD_CFG_FILE); - LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg, Path:%{public}s.", cfgFilePath.c_str()); - std::string jsonStr; - std::ifstream fin(cfgFilePath); - while (fin.good()) { - std::string line; - std::getline(fin, line); - jsonStr += line; - } - std::vector customUtdTypes; - utdJsonParser_.ParseStoredCustomUtdJson(jsonStr, customUtdTypes); - LOG_DEBUG(UDMF_CLIENT, "GetTypeCfgs, customUtdTypes total:%{public}zu.", customUtdTypes.size()); - return customUtdTypes; + if (isHap) { + return CUSTOM_UTD_HAP_DIR; + } + std::string userIdStr = std::to_string(userId); + std::string path = std::string(CUSTOM_UTD_SA_DIR).append(userIdStr).append(CUSTOM_UTD_SA_SUB_DIR); + std::string oldPath = std::string(CUSTOM_UTD_SA_DIR).append(userIdStr).append(OLD_CUSTOM_UTD_SA_SUB_DIR); + path = (access(path.c_str(), F_OK) != 0 && access(oldPath.c_str(), F_OK) == 0) ? oldPath : path; + path.append(UTD_CFG_FILE); + return path; } int32_t CustomUtdStore::SaveTypeCfgs(const std::vector &customUtdTypes, int32_t user) { LOG_DEBUG(UDMF_CLIENT, "customUtdTypes total:%{public}zu.", customUtdTypes.size()); std::string jsonData; + if (!utdJsonParser_.ConvertUtdCfgsToJson(customUtdTypes, jsonData)) { + LOG_ERROR(UDMF_CLIENT, "ConvertUtdCfgsToJson failed"); + return E_JSON_CONVERT_FAILED; + } std::string cfgFileDir = CUSTOM_UTD_SA_DIR + std::to_string(user) + CUSTOM_UTD_SA_SUB_DIR; - if (utdJsonParser_.ConvertUtdCfgsToJson(customUtdTypes, jsonData) && CreateDirectory(cfgFileDir)) { - SavaCfgFile(jsonData, cfgFileDir.append(UTD_CFG_FILE)); + if (!CreateDirectory(cfgFileDir)) { + LOG_ERROR(UDMF_CLIENT, "CreateDirectory failed"); + return E_FS_ERROR; } - return 0; + return SaveCfgFile(jsonData, cfgFileDir + UTD_CFG_FILE); } -int32_t CustomUtdStore::SavaCfgFile(const std::string &jsonData, const std::string &cfgFilePath) +int32_t CustomUtdStore::SaveCfgFile(const std::string &jsonData, const std::string &cfgFilePath) { std::ofstream ofs; - LOG_DEBUG(UDMF_CLIENT, "set cfg start, path:%{public}s ", cfgFilePath.c_str()); ofs.open(cfgFilePath, std::ios_base::ate); if (!ofs.is_open()) { - LOG_ERROR(UDMF_CLIENT, "open cfg failed, path:%{public}s", cfgFilePath.c_str()); + LOG_ERROR(UDMF_CLIENT, "open cfg failed"); + return E_FS_ERROR; } ofs << jsonData << std::endl; + if (!ofs.good()) { + LOG_ERROR(UDMF_CLIENT, "write cfg failed"); + return E_FS_ERROR; + } ofs.close(); LOG_DEBUG(UDMF_CLIENT, "set cfg end."); - return 0; + return E_OK; } bool CustomUtdStore::CreateDirectory(const std::string &path) const { - LOG_DEBUG(UDMF_CLIENT, "CreateDirectory start, path:%{public}s ", path.c_str()); if (access(path.c_str(), F_OK) == 0) { return true; } @@ -129,8 +140,7 @@ bool CustomUtdStore::CreateDirectory(const std::string &path) const if (access(subPath.c_str(), F_OK) != 0) { if (mkdir(subPath.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0) { - LOG_WARN(UDMF_CLIENT, "CreateDirectory, fail. path:%{public}s, subPath:%{public}s.", - path.c_str(), subPath.c_str()); + LOG_WARN(UDMF_CLIENT, "CreateDirectory, fail."); return false; } } @@ -142,7 +152,7 @@ bool CustomUtdStore::CreateDirectory(const std::string &path) const #endif return true; } - + LOG_ERROR(UDMF_CLIENT, "CreateDirectory fail."); return false; } @@ -227,5 +237,20 @@ void CustomUtdStore::ProcessUtdForSave(const CustomUtdCfgs &utdTypes, std::vecto } } } + +UtdFileInfo CustomUtdStore::GetCustomUtdInfo(bool isHap, int32_t userId) +{ + UtdFileInfo info = {0}; + std::string path = GetCustomUtdPath(isHap, userId); + struct stat fileStat; + if (stat(path.c_str(), &fileStat) != 0) { + LOG_WARN(UDMF_CLIENT, "custom utd file not exist"); + return info; + } + + info.lastTime = fileStat.st_mtime; + info.size = static_cast(fileStat.st_size); + return info; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/common/custom_utd_store.h b/udmf/framework/common/custom_utd_store.h index 4c20c40f..57ca448f 100644 --- a/udmf/framework/common/custom_utd_store.h +++ b/udmf/framework/common/custom_utd_store.h @@ -27,20 +27,23 @@ namespace UDMF { class CustomUtdStore { public: static CustomUtdStore &GetInstance(); - std::vector GetTypeCfgs(int32_t userId); - std::vector GetHapTypeCfgs(); + std::vector GetCustomUtd(bool isHap, int32_t userId); int32_t SaveTypeCfgs(const std::vector &customUtdTypes, int32_t user); bool InstallCustomUtds(const std::string &bundleName, const std::string &jsonStr, int32_t user, std::vector &customTyepCfgs); bool UninstallCustomUtds(const std::string &bundleName, int32_t user, std::vector &customTyepCfgs); + UtdFileInfo GetCustomUtdInfo(bool isHap, int32_t userId); + private: CustomUtdStore(); ~CustomUtdStore(); - int32_t SavaCfgFile(const std::string &jsonData, const std::string &cfgFilePath); + int32_t SaveCfgFile(const std::string &jsonData, const std::string &cfgFilePath); bool CreateDirectory(const std::string &path) const; static void ProcessUtdForSave(const CustomUtdCfgs &utdTypes, std::vector &customTyepCfgs, const std::string &bundleName); + std::string GetCustomUtdPath(bool isHap, int32_t userId); + CustomUtdJsonParser utdJsonParser_; }; } // namespace UDMF diff --git a/udmf/framework/common/graph.cpp b/udmf/framework/common/graph.cpp index ccc44b70..077b8912 100644 --- a/udmf/framework/common/graph.cpp +++ b/udmf/framework/common/graph.cpp @@ -53,7 +53,11 @@ void Graph::AddEdge(const std::string &startNode, const std::string &endNode) void Graph::AddEdge(uint32_t start, uint32_t end) { - EdgeNode *edge = new EdgeNode; // add new edge + EdgeNode *edge = new (std::nothrow) EdgeNode; // add new edge + if (edge == nullptr) { + LOG_ERROR(UDMF_CLIENT, "edge is nullptr"); + return; + } edge->adjIndex = end; edge->next = adjList_[start].firstEdge; adjList_[start].firstEdge = edge; @@ -111,7 +115,7 @@ bool Graph::DfsUnconnectedGraph(Action action) bool Graph::IsValidType(const std::string &node) { if (typeIdIndex_.find(node) == typeIdIndex_.end()) { - LOG_ERROR(UDMF_CLIENT, "invalid typeId. typeId:%{public}s ", node.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid typeId"); return false; } return true; diff --git a/udmf/framework/common/graph.h b/udmf/framework/common/graph.h index 4786bf08..4f086941 100644 --- a/udmf/framework/common/graph.h +++ b/udmf/framework/common/graph.h @@ -16,23 +16,23 @@ #ifndef UDMF_GRAPH_H #define UDMF_GRAPH_H -#include -#include #include +#include +#include #include #include -#include +#include namespace OHOS { namespace UDMF { struct EdgeNode { - uint32_t adjIndex; - EdgeNode *next; + uint32_t adjIndex {0}; + EdgeNode *next {nullptr}; }; struct VertexNode { - uint32_t value; - EdgeNode *firstEdge; + uint32_t value {0}; + EdgeNode *firstEdge {nullptr}; }; class Graph { public: @@ -46,12 +46,11 @@ public: bool IsValidType(const std::string &node); int32_t GetIndex(const std::string &node); bool IsDAG(); - private: - uint32_t vertexNum_; - std::vector adjList_; // Adjacency List - std::vector visited_; // Determine whether the vertex has been accessed, index=vertex value - std::map typeIdIndex_; + uint32_t vertexNum_ {0}; + std::vector adjList_ {}; // Adjacency List + std::vector visited_ {}; // Determine whether the vertex has been accessed, index=vertex value + std::map typeIdIndex_ {}; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/common/itypes_util.h b/udmf/framework/common/itypes_util.h new file mode 100644 index 00000000..48fefb2a --- /dev/null +++ b/udmf/framework/common/itypes_util.h @@ -0,0 +1,603 @@ +/* + * 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 DISTRIBUTED_DATA_FRAMEWORKS_COMMON_ITYPES_UTIL_H +#define DISTRIBUTED_DATA_FRAMEWORKS_COMMON_ITYPES_UTIL_H +#include +#include +#include +#include +#include +#include +#include + +#include "iremote_object.h" +#include "message_parcel.h" +namespace OHOS { +template +struct is_container : std::false_type { +}; +template +struct is_container> : std::true_type { +}; +template +struct is_container> : std::true_type { +}; +namespace ITypesUtil { +inline constexpr size_t MAX_COUNT = 100000; +inline constexpr size_t MAX_SIZE = 1 * 1024 * 1024 * 1024; //1G +static inline bool Marshal(MessageParcel &data) +{ + return true; +} + +static inline bool Unmarshal(MessageParcel &data) +{ + return true; +} + +static inline bool Marshalling(int16_t input, MessageParcel &data) +{ + return data.WriteInt16(input); +} + +static inline bool Unmarshalling(int16_t &output, MessageParcel &data) +{ + return data.ReadInt16(output); +} + +static inline bool Marshalling(uint16_t input, MessageParcel &data) +{ + return data.WriteUint16(input); +} + +static inline bool Unmarshalling(uint16_t &output, MessageParcel &data) +{ + return data.ReadUint16(output); +} + +static inline bool Marshalling(uint32_t input, MessageParcel &data) +{ + return data.WriteUint32(input); +} + +static inline bool Unmarshalling(uint32_t &output, MessageParcel &data) +{ + return data.ReadUint32(output); +} + +static inline bool Marshalling(int32_t input, MessageParcel &data) +{ + return data.WriteInt32(input); +} + +static inline bool Unmarshalling(int32_t &output, MessageParcel &data) +{ + return data.ReadInt32(output); +} + +static inline bool Marshalling(uint64_t input, MessageParcel &data) +{ + return data.WriteUint64(input); +} + +static inline bool Unmarshalling(uint64_t &output, MessageParcel &data) +{ + return data.ReadUint64(output); +} + +static inline bool Marshalling(int64_t input, MessageParcel &data) +{ + return data.WriteInt64(input); +} + +static inline bool Unmarshalling(int64_t &output, MessageParcel &data) +{ + return data.ReadInt64(output); +} + +static inline bool Marshalling(double input, MessageParcel &data) +{ + return data.WriteDouble(input); +} + +static inline bool Unmarshalling(double &output, MessageParcel &data) +{ + return data.ReadDouble(output); +} + +static inline bool Marshalling(bool input, MessageParcel &data) +{ + return data.WriteBool(input); +} + +static inline bool Unmarshalling(bool &output, MessageParcel &data) +{ + return data.ReadBool(output); +} + +static inline bool Marshalling(const std::monostate &input, MessageParcel &data) +{ + return true; +} + +static inline bool Unmarshalling(std::monostate &output, MessageParcel &data) +{ + return true; +} + +static inline bool Marshalling(const std::vector &input, MessageParcel &data) +{ + return data.WriteFloatVector(input); +} + +static inline bool Unmarshalling(std::vector &output, MessageParcel &data) +{ + return data.ReadFloatVector(&output); +} + +static inline bool Marshalling(const std::string &input, MessageParcel &data) +{ + return data.WriteString(input); +} + +static inline bool Unmarshalling(std::string &output, MessageParcel &data) +{ + return data.ReadString(output); +} + +static inline bool Marshalling(const std::u16string &input, MessageParcel &data) +{ + return data.WriteString16(input); +} + +static inline bool Unmarshalling(std::u16string &output, MessageParcel &data) +{ + return data.ReadString16(output); +} + +static inline bool Marshalling(const std::vector &input, MessageParcel &data) +{ + return data.WriteUInt8Vector(input); +} + +static inline bool Unmarshalling(std::vector &output, MessageParcel &data) +{ + return data.ReadUInt8Vector(&output); +} + +static inline bool Marshalling(const sptr &input, MessageParcel &data) +{ + return data.WriteRemoteObject(input); +} + +static inline bool Unmarshalling(sptr &output, MessageParcel &data) +{ + output = data.ReadRemoteObject(); + return true; +} + +static inline bool Marshalling(IRemoteObject *input, MessageParcel &data) +{ + return data.WriteRemoteObject(input); +} + +template +bool ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data); +template +bool ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data); + +template +bool WriteVariant(uint32_t step, const _InTp &input, MessageParcel &data); +template +bool WriteVariant(uint32_t step, const _InTp &input, MessageParcel &data); + +template +bool Marshalling(const std::variant<_Types...> &input, MessageParcel &data); +template +bool Unmarshalling(std::variant<_Types...> &output, MessageParcel &data); + +template +bool Marshalling(const std::map &result, MessageParcel &parcel); +template +bool Unmarshalling(std::map &val, MessageParcel &parcel); + +template +bool Marshalling(const std::tuple &result, MessageParcel &parcel); +template +bool Unmarshalling(std::tuple &val, MessageParcel &parcel); + +template +bool Marshalling(const std::pair &result, MessageParcel &parcel); +template +bool Unmarshalling(std::pair &val, MessageParcel &parcel); + +template +bool Marshalling(const std::vector &val, MessageParcel &parcel); +template +bool Unmarshalling(std::vector &val, MessageParcel &parcel); + +template +bool Marshalling(const std::list &val, MessageParcel &parcel); +template +bool Unmarshalling(std::list &val, MessageParcel &parcel); + +template{}, int>::type = 0> +bool Marshalling(const T &input, MessageParcel &data) = delete; +template{}, int>::type = 0> +bool Unmarshalling(T &output, MessageParcel &data) = delete; + +template +bool Marshalling(const T &input, MessageParcel &data); +template +bool Unmarshalling(T &output, MessageParcel &data); + +template{}, int>::type = 0> +bool MarshalToContainer(const T &val, MessageParcel &parcel); +template{}, int>::type = 0> +bool UnmarshalFromContainer(T &val, MessageParcel &parcel); + +template +bool MarshalToBuffer(const T &input, int size, MessageParcel &data); +template +bool MarshalToBuffer(const std::vector &input, int size, MessageParcel &data); + +template +bool UnmarshalFromBuffer(MessageParcel &data, T &output); +template +bool UnmarshalFromBuffer(MessageParcel &data, std::vector &output); + +template +bool Marshal(MessageParcel &parcel, const T &first, const Types &...others); + +template +bool Unmarshal(MessageParcel &parcel, T &first, Types &...others); +} // namespace ITypesUtil + +template +bool ITypesUtil::ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data) +{ + return false; +} + +template +bool ITypesUtil::ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data) +{ + if (step == index) { + _First value{}; + auto success = ITypesUtil::Unmarshalling(value, data); + output = value; + return success; + } + return ITypesUtil::ReadVariant<_OutTp, _Rest...>(step + 1, index, output, data); +} + +template +bool ITypesUtil::WriteVariant(uint32_t step, const _InTp &input, MessageParcel &data) +{ + return false; +} + +template +bool ITypesUtil::WriteVariant(uint32_t step, const _InTp &input, MessageParcel &data) +{ + if (step == input.index()) { + return ITypesUtil::Marshalling(std::get<_First>(input), data); + } + return ITypesUtil::WriteVariant<_InTp, _Rest...>(step + 1, input, data); +} + +template +bool ITypesUtil::Marshalling(const std::variant<_Types...> &input, MessageParcel &data) +{ + uint32_t index = static_cast(input.index()); + if (!data.WriteUint32(index)) { + return false; + } + + return ITypesUtil::WriteVariant(0, input, data); +} + +template +bool ITypesUtil::Unmarshalling(std::variant<_Types...> &output, MessageParcel &data) +{ + uint32_t index = data.ReadUint32(); + if (index >= sizeof...(_Types)) { + return false; + } + + return ITypesUtil::ReadVariant(0, index, output, data); +} + +template +bool ITypesUtil::Marshalling(const std::map &result, MessageParcel &parcel) +{ + if (!parcel.WriteInt32(static_cast(result.size()))) { + return false; + } + for (const auto &entry : result) { + if ((!ITypesUtil::Marshalling(entry.first, parcel)) || (!ITypesUtil::Marshalling(entry.second, parcel))) { + return false; + } + } + return true; +} + +template +bool ITypesUtil::Unmarshalling(std::map &val, MessageParcel &parcel) +{ + int32_t size = 0; + if (!parcel.ReadInt32(size)) { + return false; + } + if (size < 0) { + return false; + } + + size_t readAbleSize = parcel.GetReadableBytes(); + if ((static_cast(size) > readAbleSize) || static_cast(size) > val.max_size()) { + return false; + } + + for (int32_t i = 0; i < size; i++) { + K key; + if ((!ITypesUtil::Unmarshalling(key, parcel)) || (!ITypesUtil::Unmarshalling(val[key], parcel))) { + return false; + } + } + return true; +} + +template +bool ITypesUtil::Marshalling(const std::tuple &result, MessageParcel &parcel) +{ + if (!ITypesUtil::Marshalling(std::get<0>(result), parcel)) { + return false; + } + if (!ITypesUtil::Marshalling(std::get<1>(result), parcel)) { + return false; + } + if (!ITypesUtil::Marshalling(std::get<2>(result), parcel)) { // 2 is the last element in tuple + return false; + } + return true; +} + +template +bool ITypesUtil::Unmarshalling(std::tuple &val, MessageParcel &parcel) +{ + F first; + if (!ITypesUtil::Unmarshalling(first, parcel)) { + return false; + } + S second; + if (!ITypesUtil::Unmarshalling(second, parcel)) { + return false; + } + T third; + if (!ITypesUtil::Unmarshalling(third, parcel)) { + return false; + } + val = { first, second, third }; + return true; +} + +template +bool ITypesUtil::Marshalling(const std::pair &result, MessageParcel &parcel) +{ + if (!ITypesUtil::Marshalling(result.first, parcel)) { + return false; + } + if (!ITypesUtil::Marshalling(result.second, parcel)) { + return false; + } + return true; +} + +template +bool ITypesUtil::Unmarshalling(std::pair &val, MessageParcel &parcel) +{ + F first; + if (!ITypesUtil::Unmarshalling(first, parcel)) { + return false; + } + S second; + if (!ITypesUtil::Unmarshalling(second, parcel)) { + return false; + } + val = { first, second }; + return true; +} + +template +bool ITypesUtil::Marshalling(const std::vector &val, MessageParcel &parcel) +{ + return ITypesUtil::MarshalToContainer(val, parcel); +} + +template +bool ITypesUtil::Unmarshalling(std::vector &val, MessageParcel &parcel) +{ + return ITypesUtil::UnmarshalFromContainer(val, parcel); +} + +template +bool ITypesUtil::Marshalling(const std::list &val, MessageParcel &parcel) +{ + return ITypesUtil::MarshalToContainer(val, parcel); +} + +template +bool ITypesUtil::Unmarshalling(std::list &val, MessageParcel &parcel) +{ + return ITypesUtil::UnmarshalFromContainer(val, parcel); +} + +template{}, int>::type> +bool ITypesUtil::MarshalToContainer(const T &val, MessageParcel &parcel) +{ + if (val.size() > INT_MAX) { + return false; + } + + if (!parcel.WriteInt32(static_cast(val.size()))) { + return false; + } + + for (auto &v : val) { + if (!ITypesUtil::Marshalling(v, parcel)) { + return false; + } + } + return true; +} + +template{}, int>::type> +bool ITypesUtil::UnmarshalFromContainer(T &val, MessageParcel &parcel) +{ + int32_t len = parcel.ReadInt32(); + if (len < 0) { + return false; + } + + size_t readAbleSize = parcel.GetReadableBytes(); + size_t size = static_cast(len); + if ((size > readAbleSize) || (size > val.max_size())) { + return false; + } + + val.clear(); + for (size_t i = 0; i < size; i++) { + typename T::value_type value; + if (!ITypesUtil::Unmarshalling(value, parcel)) { + return false; + } + val.emplace_back(std::move(value)); + } + return true; +} + +template +bool ITypesUtil::MarshalToBuffer(const T &input, int size, MessageParcel &data) +{ + if (size < 0 || static_cast(size) > MAX_SIZE || !data.WriteInt32(size)) { + return false; + } + if (size == 0) { + return true; + } + std::unique_ptr buffer = std::make_unique(size); + if (buffer == nullptr) { + return false; + } + + int leftSize = size; + uint8_t *cursor = buffer.get(); + if (!input.WriteToBuffer(cursor, leftSize)) { + return false; + } + return data.WriteRawData(buffer.get(), size); +} + +template +bool ITypesUtil::MarshalToBuffer(const std::vector &input, int size, MessageParcel &data) +{ + if (size < 0 || static_cast(size) > MAX_SIZE || input.size() > MAX_COUNT || !data.WriteInt32(size)) { + return false; + } + if (size == 0) { + return true; + } + if (!data.WriteInt32(input.size())) { + return false; + } + + std::unique_ptr buffer = std::make_unique(size); + if (buffer == nullptr) { + return false; + } + + uint8_t *cursor = buffer.get(); + int32_t left = size; + for (const auto &entry : input) { + if (!entry.WriteToBuffer(cursor, left)) { + return false; + } + } + return data.WriteRawData(buffer.get(), size); +} + +template +bool ITypesUtil::UnmarshalFromBuffer(MessageParcel &data, T &output) +{ + int32_t size = data.ReadInt32(); + if (size == 0) { + return true; + } + if (size < 0 || static_cast(size) > MAX_SIZE) { + return false; + } + const uint8_t *buffer = reinterpret_cast(data.ReadRawData(size)); + if (buffer == nullptr) { + return false; + } + return output.ReadFromBuffer(buffer, size); +} + +template +bool ITypesUtil::UnmarshalFromBuffer(MessageParcel &data, std::vector &output) +{ + int size = data.ReadInt32(); + if (size == 0) { + return true; + } + if (size < 0 || static_cast(size) > MAX_SIZE) { + return false; + } + int count = data.ReadInt32(); + const uint8_t *buffer = reinterpret_cast(data.ReadRawData(size)); + if (count < 0 || static_cast(count) > MAX_COUNT || buffer == nullptr) { + return false; + } + + output.resize(count); + for (auto &entry : output) { + if (!entry.ReadFromBuffer(buffer, size)) { + output.clear(); + return false; + } + } + return true; +} + +template +bool ITypesUtil::Marshal(MessageParcel &parcel, const T &first, const Types &...others) +{ + if (!ITypesUtil::Marshalling(first, parcel)) { + return false; + } + return ITypesUtil::Marshal(parcel, others...); +} + +template +bool ITypesUtil::Unmarshal(MessageParcel &parcel, T &first, Types &...others) +{ + if (!ITypesUtil::Unmarshalling(first, parcel)) { + return false; + } + return ITypesUtil::Unmarshal(parcel, others...); +} +} // namespace OHOS +#endif \ No newline at end of file diff --git a/udmf/framework/common/tlv_object.cpp b/udmf/framework/common/tlv_object.cpp index f68df376..cbab4006 100644 --- a/udmf/framework/common/tlv_object.cpp +++ b/udmf/framework/common/tlv_object.cpp @@ -131,8 +131,8 @@ size_t TLVObject::Count(const void *value) bool TLVObject::Write(TAG tag, const std::string &value) { if (!HasExpectBuffer(sizeof(TLVHead) + value.size())) { - LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv write. tag=%{public}hu, value=%{public}s", tag, - value.c_str()); + LOG_ERROR(UDMF_FRAMEWORK, "Has no enough buffer in tlv write. tag=%{public}hu, value's size=%{public}zu", tag, + value.size()); return false; } auto tlvHead = reinterpret_cast(GetStartCursor()); @@ -141,8 +141,8 @@ bool TLVObject::Write(TAG tag, const std::string &value) if (!value.empty()) { auto err = memcpy_s(tlvHead->value, value.size(), value.c_str(), value.size()); if (err != EOK) { - LOG_ERROR(UDMF_FRAMEWORK, "memcpy error in tlv write. tag=%{public}hu, value=%{public}s", tag, - value.c_str()); + LOG_ERROR(UDMF_FRAMEWORK, "memcpy error in tlv write. tag=%{public}hu, value's size=%{public}zu", tag, + value.size()); return false; } } @@ -259,6 +259,7 @@ bool TLVObject::Read(OHOS::AAFwk::Want &value, const TLVHead &head) return false; } value = *want; + delete want; return true; } diff --git a/udmf/framework/common/tlv_object.h b/udmf/framework/common/tlv_object.h index 8a0f6f9b..cb39dbc3 100644 --- a/udmf/framework/common/tlv_object.h +++ b/udmf/framework/common/tlv_object.h @@ -26,8 +26,8 @@ namespace OHOS { namespace UDMF { #pragma pack(1) struct TLVHead { - uint16_t tag; - uint32_t len; + uint16_t tag {0}; + uint32_t len {0}; std::uint8_t value[0]; }; #pragma pack() @@ -83,10 +83,10 @@ private: void PrepareBufferForFile(size_t size); std::uint8_t *GetStartCursor(); - std::size_t total_ = 0; - std::size_t cursor_ = 0; - std::vector *buffer_; - std::FILE *file_ = nullptr; + std::size_t total_ {0}; + std::size_t cursor_ {0}; + std::vector *buffer_ {nullptr}; + std::FILE *file_ {nullptr}; }; template size_t TLVObject::CountBasic(const T &value) diff --git a/udmf/framework/common/tlv_tag.h b/udmf/framework/common/tlv_tag.h index 4511daa0..79bc09c2 100644 --- a/udmf/framework/common/tlv_tag.h +++ b/udmf/framework/common/tlv_tag.h @@ -90,6 +90,19 @@ enum class TAG : uint16_t { TAG_PROPERTIES_TIMESTAMP, TAG_PROPERTIES_SHARE_OPTIONS, TAG_PROPERTIES_EXTRAS, + TAG_RECORD_UTD_ID2, + TAG_SUMMARY_FILE_TYPES, + TAG_DATA_LOAD_INFO, + TAG_DATA_LOAD_KEY, + TAG_SET_TYPES, + TAG_RECORD_COUNT, + TAG_SET_ITEM, + TAG_SET_SIZE, + TAG_VISIBILITY, + TAG_APP_ID, + TAG_SUMMARY_SPECIFIC_SUMMARY, + TAG_SUMMARY_SUMMARY_FORMAT, + TAG_SUMMARY_VERSION, }; } #endif //UDMF_TLV_TAG_H diff --git a/udmf/framework/common/tlv_util.cpp b/udmf/framework/common/tlv_util.cpp index e67b7251..7dc72ebb 100644 --- a/udmf/framework/common/tlv_util.cpp +++ b/udmf/framework/common/tlv_util.cpp @@ -18,6 +18,7 @@ #include "tlv_util.h" #include "udmf_utils.h" #include "logger.h" +#include "pixelmap_loader.h" #include "tlv_object.h" namespace OHOS { @@ -195,6 +196,10 @@ template <> bool Writing(const UnifiedKey &input, TLVObject &data, TAG tag) template <> bool Reading(UnifiedKey &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; @@ -254,6 +259,10 @@ template <> bool Writing(const UnifiedData &input, TLVObject &data, TAG tag) template <> bool Reading(UnifiedData &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; @@ -317,6 +326,10 @@ template <> bool Writing(const UnifiedDataProperties &input, TLVObject &data, TA template <> bool Reading(UnifiedDataProperties &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; @@ -418,12 +431,14 @@ template <> bool Reading(OHOS::AAFwk::WantParams &output, TLVObject &data, const free(buffer); return false; } + // The pointer returned by Unmarshalling needs to be manually deleted. auto wantParams = AAFwk::WantParams::Unmarshalling(*parcel); if (wantParams == nullptr) { LOG_ERROR(UDMF_FRAMEWORK, "Unmarshalling wantParams error in tlv read. tag=%{public}hu", head.tag); return false; } output = *wantParams; + delete wantParams; return true; } @@ -431,7 +446,8 @@ template <> size_t CountBufferSize(const UnifiedRecord &input, TLVObject &data) { return data.CountHead() + data.CountBasic(static_cast(input.GetType())) + data.Count(input.GetUid()) + CountBufferSize(input.GetOriginValue(), data) + data.Count(input.GetUtdId()) + - CountBufferSize(input.GetInnerEntries(), data) + CountBufferSize(input.GetUris(), data); + data.Count(input.GetUtdId2()) + CountBufferSize(input.GetInnerEntries(), data) + + CountBufferSize(input.GetUris(), data); } template <> bool Writing(const UnifiedRecord &input, TLVObject &data, TAG tag) @@ -451,6 +467,9 @@ template <> bool Writing(const UnifiedRecord &input, TLVObject &data, TAG tag) if (!data.Write(TAG::TAG_RECORD_UTD_ID, input.GetUtdId())) { return false; } + if (!data.Write(TAG::TAG_RECORD_UTD_ID2, input.GetUtdId2())) { + return false; + } if (!TLVUtil::Writing(input.GetInnerEntries(), data, TAG::TAG_RECORD_ENTRIES)) { return false; } @@ -462,6 +481,10 @@ template <> bool Writing(const UnifiedRecord &input, TLVObject &data, TAG tag) template <> bool Reading(UnifiedRecord &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } auto endCursor = data.GetCursor() + head.len; UDType dataType; std::string uid; @@ -472,6 +495,7 @@ template <> bool Reading(UnifiedRecord &output, TLVObject &data, const TLVHead & return false; } std::string utdId; + std::string utdId2; std::shared_ptr> entries; std::vector uriInfos; switch (headItem.tag) { @@ -499,6 +523,12 @@ template <> bool Reading(UnifiedRecord &output, TLVObject &data, const TLVHead & } output.SetUtdId(std::move(utdId)); break; + case static_cast(TAG::TAG_RECORD_UTD_ID2): + if (!data.Read(utdId2, headItem)) { + return false; + } + output.SetUtdId2(std::move(utdId2)); + break; case static_cast(TAG::TAG_RECORD_ENTRIES): if (!TLVUtil::Reading(entries, data, headItem)) { return false; @@ -526,7 +556,8 @@ template <> size_t CountBufferSize(const Runtime &input, TLVObject &data) data.CountBasic(static_cast(input.lastModifiedTime)) + data.CountBasic(static_cast(input.dataStatus)) + data.Count(input.sourcePackage) + data.Count(input.createPackage) + data.Count(input.deviceId) + TLVUtil::CountBufferSize(input.key, data) + - data.Count(input.sdkVersion) + TLVUtil::CountBufferSize(input.privileges, data); + data.Count(input.sdkVersion) + TLVUtil::CountBufferSize(input.privileges, data) + + data.CountBasic(static_cast(input.visibility)) + data.Count(input.appId); } template <> bool Writing(const Runtime &input, TLVObject &data, TAG tag) @@ -573,11 +604,21 @@ template <> bool Writing(const Runtime &input, TLVObject &data, TAG tag) if (!TLVUtil::Writing(input.sdkVersion, data, TAG::TAG_VERSION)) { return false; } + if (!data.WriteBasic(TAG::TAG_VISIBILITY, static_cast(input.visibility))) { + return false; + } + if (!TLVUtil::Writing(input.appId, data, TAG::TAG_APP_ID)) { + return false; + } return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); } template <> bool Reading(Runtime &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; @@ -587,6 +628,7 @@ template <> bool Reading(Runtime &output, TLVObject &data, const TLVHead &head) bool result = true; int64_t createTime = 0; int64_t lastModifiedTime = 0; + int32_t visibility = 0; switch (headItem.tag) { case static_cast(TAG::TAG_KEY): result = TLVUtil::Reading(output.key, data, headItem); @@ -629,6 +671,13 @@ template <> bool Reading(Runtime &output, TLVObject &data, const TLVHead &head) case static_cast(TAG::TAG_VERSION): result = data.Read(output.sdkVersion, headItem); break; + case static_cast(TAG::TAG_VISIBILITY): + result = data.ReadBasic(visibility, headItem); + output.visibility = static_cast(visibility); + break; + case static_cast(TAG::TAG_APP_ID): + result = data.Read(output.appId, headItem); + break; default: result = data.Skip(headItem); } @@ -664,6 +713,10 @@ template <> bool Writing(const Privilege &input, TLVObject &data, TAG tag) template <> bool Reading(Privilege &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; @@ -721,6 +774,10 @@ template <> bool Writing(const UriInfo &input, TLVObject &data, TAG tag) template <> bool Reading(UriInfo &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; @@ -754,7 +811,8 @@ template <> bool Reading(UriInfo &output, TLVObject &data, const TLVHead &head) template <> size_t CountBufferSize(const std::shared_ptr &input, TLVObject &data) { std::vector val; - if (!input->EncodeTlv(val)) { + PixelMapLoader loader; + if (!loader.EncodeTlv(input, val)) { LOG_ERROR(UDMF_FRAMEWORK, "Encode pixelMap error when CountBufferSize"); return 0; } @@ -765,7 +823,8 @@ template <> bool Writing(const std::shared_ptr &input, TL { InitWhenFirst(input, data); std::vector val; - if (!input->EncodeTlv(val)) { + PixelMapLoader loader; + if (!loader.EncodeTlv(input, val)) { LOG_ERROR(UDMF_FRAMEWORK, "Encode pixelMap error when Writing"); return false; } @@ -779,7 +838,8 @@ template <> bool Reading(std::shared_ptr &output, TLVObje LOG_ERROR(UDMF_FRAMEWORK, "Reading u8 vector error."); return false; } - output = std::shared_ptr(OHOS::Media::PixelMap::DecodeTlv(val)); + PixelMapLoader loader; + output = loader.DecodeTlv(val); if (output == nullptr) { LOG_ERROR(UDMF_FRAMEWORK, "DecodeTlv pixelMap error when Reading."); return false; @@ -882,7 +942,9 @@ template <> bool Reading(std::shared_ptr &output, TLVObject & template <> size_t CountBufferSize(const Summary &input, TLVObject &data) { - return data.CountHead() + CountBufferSize(input.summary, data) + data.CountBasic(input.totalSize); + return data.CountHead() + CountBufferSize(input.summary, data) + data.CountBasic(input.totalSize) + + CountBufferSize(input.specificSummary, data) + CountBufferSize(input.summaryFormat, data) + + data.CountBasic(input.version); } template <> bool Writing(const Summary &input, TLVObject &data, TAG tag) @@ -896,11 +958,24 @@ template <> bool Writing(const Summary &input, TLVObject &data, TAG tag) if (!data.WriteBasic(TAG::TAG_SUMMARY_SIZE, input.totalSize)) { return false; } + if (!TLVUtil::Writing(input.specificSummary, data, TAG::TAG_SUMMARY_SPECIFIC_SUMMARY)) { + return false; + } + if (!TLVUtil::Writing(input.summaryFormat, data, TAG::TAG_SUMMARY_SUMMARY_FORMAT)) { + return false; + } + if (!data.WriteBasic(TAG::TAG_SUMMARY_VERSION, input.version)) { + return false; + } return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); } template <> bool Reading(Summary &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headItem{}; @@ -918,6 +993,79 @@ template <> bool Reading(Summary &output, TLVObject &data, const TLVHead &head) return false; } break; + case static_cast(TAG::TAG_SUMMARY_SPECIFIC_SUMMARY): + if (!TLVUtil::Reading(output.specificSummary, data, headItem)) { + return false; + } + break; + case static_cast(TAG::TAG_SUMMARY_SUMMARY_FORMAT): + if (!TLVUtil::Reading(output.summaryFormat, data, headItem)) { + return false; + } + break; + case static_cast(TAG::TAG_SUMMARY_VERSION): + if (!data.ReadBasic(output.version, headItem)) { + return false; + } + break; + default: + data.Skip(headItem); + } + } + return true; +} + +template <> size_t API_EXPORT CountBufferSize(const DataLoadInfo &input, TLVObject &data) +{ + return data.CountHead() + data.Count(input.sequenceKey) + CountBufferSize(input.types, data) + + data.CountBasic(input.recordCount); +} + +template <> bool API_EXPORT Writing(const DataLoadInfo &input, TLVObject &data, TAG tag) +{ + InitWhenFirst(input, data); + auto tagCursor = data.GetCursor(); + data.OffsetHead(); + if (!TLVUtil::Writing(input.sequenceKey, data, TAG::TAG_DATA_LOAD_KEY)) { + return false; + } + if (!TLVUtil::Writing(input.types, data, TAG::TAG_SET_TYPES)) { + return false; + } + if (!data.WriteBasic(TAG::TAG_RECORD_COUNT, input.recordCount)) { + return false; + } + return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); +} + +template <> bool API_EXPORT Reading(DataLoadInfo &output, TLVObject &data, const TLVHead &head) +{ + if (head.len > data.GetTotal() - data.GetCursor()) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid length, would read out of bounds."); + return false; + } + auto endCursor = data.GetCursor() + head.len; + while (data.GetCursor() < endCursor) { + TLVHead headItem{}; + if (!data.ReadHead(headItem)) { + return false; + } + switch (headItem.tag) { + case static_cast(TAG::TAG_DATA_LOAD_KEY): + if (!TLVUtil::Reading(output.sequenceKey, data, headItem)) { + return false; + } + break; + case static_cast(TAG::TAG_SET_TYPES): + if (!TLVUtil::Reading(output.types, data, headItem)) { + return false; + } + break; + case static_cast(TAG::TAG_RECORD_COUNT): + if (!data.ReadBasic(output.recordCount, headItem)) { + return false; + } + break; default: data.Skip(headItem); } diff --git a/udmf/framework/common/tlv_util.h b/udmf/framework/common/tlv_util.h index 605ad4fe..3bd9c85b 100644 --- a/udmf/framework/common/tlv_util.h +++ b/udmf/framework/common/tlv_util.h @@ -52,6 +52,10 @@ template size_t API_EXPORT CountBufferSize(const std::m template bool API_EXPORT Writing(const std::map &input, TLVObject &data, TAG tag); template bool API_EXPORT Reading(std::map &output, TLVObject &data, const TLVHead &head); +template size_t API_EXPORT CountBufferSize(const std::set &input, TLVObject &data); +template bool API_EXPORT Writing(const std::set &input, TLVObject &data, TAG tag); +template bool API_EXPORT Reading(std::set &output, TLVObject &data, const TLVHead &head); + template <> size_t API_EXPORT CountBufferSize(const std::nullptr_t &input, TLVObject &data); template <> bool API_EXPORT Writing(const std::nullptr_t &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(std::nullptr_t &output, TLVObject &data, const TLVHead &head); @@ -135,6 +139,10 @@ template <> size_t API_EXPORT CountBufferSize(const Summary &input, TLVObject &d template <> bool API_EXPORT Writing(const Summary &input, TLVObject &data, TAG tag); template <> bool API_EXPORT Reading(Summary &output, TLVObject &data, const TLVHead &head); +template <> size_t API_EXPORT CountBufferSize(const DataLoadInfo &input, TLVObject &data); +template <> bool API_EXPORT Writing(const DataLoadInfo &input, TLVObject &data, TAG tag); +template <> bool API_EXPORT Reading(DataLoadInfo &output, TLVObject &data, const TLVHead &head); + template bool ReadTlv(T &output, TLVObject &data, TAG tag) { while (data.GetCursor() < data.GetTotal()) { @@ -231,6 +239,9 @@ template bool Writing(const std::vector &input, TLVObject &data, template bool Reading(std::vector &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead itemHead{}; @@ -287,6 +298,9 @@ template bool Writing(const std::map &input, TLVO template bool Reading(std::map &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + return false; + } auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { TLVHead headPair{}; @@ -389,6 +403,9 @@ bool ReadVariant(TLVObject &data, uint32_t step, uint32_t index, _OutTp &value, template bool Reading(std::variant<_Types...> &output, TLVObject &data, const TLVHead &head) { + if (head.len > data.GetTotal() - data.GetCursor()) { + return false; + } uint32_t index = 0; auto endCursor = data.GetCursor() + head.len; while (data.GetCursor() < endCursor) { @@ -406,6 +423,57 @@ template bool Reading(std::variant<_Types...> &output, TLVO } return true; } + +template size_t CountBufferSize(const std::set &input, TLVObject &data) +{ + auto size = data.CountHead() + data.CountBasic(input.size()); + for (const auto &item : input) { + size += CountBufferSize(item, data); + } + return size; +} + +template bool Writing(const std::set &input, TLVObject &data, TAG tag) +{ + InitWhenFirst(input, data); + auto tagCursor = data.GetCursor(); + data.OffsetHead(); + if (!data.WriteBasic(TAG::TAG_SET_SIZE, input.size())) { + return false; + } + for (const auto &item : input) { + if (!Writing(item, data, TAG::TAG_SET_ITEM)) { + return false; + } + } + return data.WriteBackHead(static_cast(tag), tagCursor, data.GetCursor() - tagCursor - sizeof(TLVHead)); +} + +template bool Reading(std::set &output, TLVObject &data, const TLVHead &head) +{ + if (head.len > data.GetTotal() - data.GetCursor()) { + return false; + } + auto endCursor = data.GetCursor() + head.len; + while (data.GetCursor() < endCursor) { + TLVHead itemHead{}; + if (!data.ReadHead(itemHead)) { + return false; + } + if (itemHead.tag == static_cast(TAG::TAG_SET_ITEM)) { + T item{}; + if (!Reading(item, data, itemHead)) { + return false; + } + output.insert(std::move(item)); + continue; + } + if (!data.Skip(itemHead)) { + return false; + } + } + return true; +} } // namespace TLVUtil } // namespace OHOS #endif // UDMF_TLV_UTIL_H diff --git a/udmf/framework/common/udmf_copy_file.cpp b/udmf/framework/common/udmf_copy_file.cpp index 827baebf..b8d23290 100644 --- a/udmf/framework/common/udmf_copy_file.cpp +++ b/udmf/framework/common/udmf_copy_file.cpp @@ -221,7 +221,7 @@ std::string UdmfCopyFile::GetFileName(const std::string &path) { std::string realSrc = path; if (IsRemote(path)) { - size_t index = path.rfind("?", 0); + size_t index = path.rfind("?"); realSrc = path.substr(0, index); } std::filesystem::path filePath(realSrc); diff --git a/udmf/framework/common/udmf_executor.cpp b/udmf/framework/common/udmf_executor.cpp new file mode 100644 index 00000000..3a039ec4 --- /dev/null +++ b/udmf/framework/common/udmf_executor.cpp @@ -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. + */ + +#include "udmf_executor.h" + +namespace OHOS::UDMF { +static constexpr const char *EXECUTOR_MASK = "TaskExecutor_UDMF"; + +UdmfExecutor::UdmfExecutor(size_t max, size_t min): executor_(max, min, EXECUTOR_MASK) {}; + +UdmfTaskId UdmfExecutor::Schedule(UdmfDuration delay, UdmfTask task) +{ + return executor_.Schedule(delay, task); +} + +bool UdmfExecutor::Remove(UdmfTaskId taskId, bool wait) +{ + return executor_.Remove(taskId, wait); +} + +UdmfTaskId UdmfExecutor::Execute(UdmfTask task) +{ + return executor_.Execute(std::move(task)); +} + +} // namespace OHOS::UDMF \ No newline at end of file diff --git a/udmf/framework/common/udmf_executor.h b/udmf/framework/common/udmf_executor.h new file mode 100644 index 00000000..0f292fe9 --- /dev/null +++ b/udmf/framework/common/udmf_executor.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 UDMF_EXECUTOR_H +#define UDMF_EXECUTOR_H + +#include "executor.h" +#include "executor_pool.h" + +namespace OHOS::UDMF { +using UdmfTaskId = Executor::TaskId; +using UdmfTask = std::function; +using UdmfDuration = std::chrono::steady_clock::duration; + +class UdmfExecutor { +public: + UdmfExecutor(size_t max, size_t min); + ~UdmfExecutor() = default; + UdmfTaskId Schedule(UdmfDuration delay, UdmfTask task); + bool Remove(UdmfTaskId taskId, bool wait = false); + UdmfTaskId Execute(UdmfTask task); +private: + ExecutorPool executor_; +}; + +} // namespace OHOS::UDMF +#endif // UDMF_EXECUTOR_H \ No newline at end of file diff --git a/udmf/framework/common/udmf_radar_reporter.cpp b/udmf/framework/common/udmf_radar_reporter.cpp index e90101f7..6a55a4c4 100644 --- a/udmf/framework/common/udmf_radar_reporter.cpp +++ b/udmf/framework/common/udmf_radar_reporter.cpp @@ -90,6 +90,44 @@ void RadarReporterAdapter::ReportNormal(std::string func, int32_t scene, int32_t ); } +void RadarReporterAdapter::ReportNormal(std::string func, int32_t scene, int32_t stage, + int32_t stageRes, std::string &bundleName) +{ + struct HiSysEventParam params[] = { + { .name = { "ORG_PKG" }, + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(ORG_PKG) }, + .arraySize = 0 }, + { .name = { "FUNC" }, + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(func.c_str()) }, + .arraySize = 0 }, + { .name = { "BIZ_SCENE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = scene }, + .arraySize = 0 }, + { .name = { "BIZ_STAGE" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = stage }, + .arraySize = 0 }, + { .name = { "STAGE_RES" }, + .t = HISYSEVENT_INT32, + .v = { .i32 = stageRes }, + .arraySize = 0 }, + { .name = { "APP_CALLER" }, + .t = HISYSEVENT_STRING, + .v = { .s = const_cast(bundleName.c_str()) }, + .arraySize = 0 } + }; + OH_HiSysEvent_Write( + DOMAIN, + EVENT_NAME, + HISYSEVENT_BEHAVIOR, + params, + sizeof(params) / sizeof(params[0]) + ); +} + void RadarReporterAdapter::ReportFail( std::string func, int32_t scene, int32_t stage, int32_t stageRes, int32_t errorCode, int32_t state) { diff --git a/udmf/framework/common/udmf_radar_reporter.h b/udmf/framework/common/udmf_radar_reporter.h index 7591c0fd..93baec22 100644 --- a/udmf/framework/common/udmf_radar_reporter.h +++ b/udmf/framework/common/udmf_radar_reporter.h @@ -32,9 +32,10 @@ enum BizScene : int32_t { enum SetDataStage : int32_t { SET_DATA_BEGIN = 1, - VERIFY_SHARE_PERMISSIONS = 2, - GERERATE_DFS_URI = 3, - SET_DATA_END = 4 + SET_DATA_SERVICE_BEGIN = 2, + VERIFY_SHARE_PERMISSIONS = 3, + GERERATE_DFS_URI = 4, + SET_DATA_END = 5 }; enum SyncDataStage : int32_t { @@ -74,6 +75,7 @@ class API_EXPORT RadarReporterAdapter { public: static void ReportNormal(std::string func, int32_t scene, int32_t stage, int32_t stageRes, int32_t state); static void ReportNormal(std::string func, int32_t scene, int32_t stage, int32_t stageRes); + static void ReportNormal(std::string func, int32_t scene, int32_t stage, int32_t stageRes, std::string &bundleName); static void ReportFail( std::string func, int32_t scene, int32_t stage, int32_t stageRes, int32_t errorCode, int32_t state); static void ReportFail(std::string func, int32_t scene, int32_t stage, int32_t stageRes, int32_t errorCode); diff --git a/udmf/framework/common/udmf_types_util.cpp b/udmf/framework/common/udmf_types_util.cpp index 921f783b..fc9eedaf 100644 --- a/udmf/framework/common/udmf_types_util.cpp +++ b/udmf/framework/common/udmf_types_util.cpp @@ -22,6 +22,7 @@ namespace OHOS { namespace ITypesUtil { using namespace UDMF; +static constexpr int32_t NORMAL_MAX_PARCEL_SIZE = 128 * 1024 * 1024; template<> bool Marshalling(const UnifiedData &input, MessageParcel &parcel) { @@ -42,9 +43,11 @@ bool Marshalling(const UnifiedData &input, MessageParcel &parcel) template<> bool Unmarshalling(UnifiedData &output, MessageParcel &parcel) { + auto dataSize = parcel.GetDataSize(); auto size = parcel.ReadInt32(); - if (size <= 0 || size > UnifiedData::MAX_DATA_SIZE) { - LOG_ERROR(UDMF_SERVICE, "UnifiedData is empty or too large!"); + if (size <= 0 || size > UnifiedData::MAX_DATA_SIZE || dataSize > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_SERVICE, + "UnifiedData is empty or too large, dataSize is %{public}zu, size is %{public}d", dataSize, size); return false; } auto rawData = parcel.ReadRawData(size); @@ -82,9 +85,11 @@ bool Marshalling(const std::vector &input, MessageParcel &parcel) template<> bool Unmarshalling(std::vector &output, MessageParcel &parcel) { + auto dataSize = parcel.GetDataSize(); auto size = parcel.ReadInt32(); - if (size <= 0 || size > UnifiedData::MAX_DATA_SIZE) { - LOG_ERROR(UDMF_SERVICE, "UnifiedDataSet is empty or too large!"); + if (size <= 0 || size > UnifiedData::MAX_DATA_SIZE || dataSize > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_SERVICE, + "UnifiedDataList is empty or too large, dataSize is %{public}zu, size is %{public}d", dataSize, size); return false; } const uint8_t *rawData = reinterpret_cast(parcel.ReadRawData(size)); @@ -104,13 +109,20 @@ bool Unmarshalling(std::vector &output, MessageParcel &parcel) template<> bool Marshalling(const Summary &input, MessageParcel &parcel) { - return ITypesUtil::Marshal(parcel, input.summary, input.totalSize); + return ITypesUtil::Marshal(parcel, input.summary, input.totalSize, input.specificSummary, + input.summaryFormat, input.version); } template<> bool Unmarshalling(Summary &output, MessageParcel &parcel) { - return ITypesUtil::Unmarshal(parcel, output.summary, output.totalSize); + auto dataSize = parcel.GetDataSize(); + if (dataSize <= 0 || dataSize > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_SERVICE, "UnifiedData is empty or too large, dataSize is %{public}zu", dataSize); + return false; + } + return ITypesUtil::Unmarshal(parcel, output.summary, output.totalSize, output.specificSummary, + output.summaryFormat, output.version); } template<> @@ -122,19 +134,29 @@ bool Marshalling(const Privilege &input, MessageParcel &parcel) template<> bool Unmarshalling(Privilege &output, MessageParcel &parcel) { + auto size = parcel.GetDataSize(); + if (size <= 0 || size > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_SERVICE, "Privilege is empty or too large, dataSize is %{public}zu", size); + return false; + } return ITypesUtil::Unmarshal(parcel, output.tokenId, output.readPermission, output.writePermission); } template<> bool Marshalling(const CustomOption &input, MessageParcel &parcel) { - return ITypesUtil::Marshal(parcel, input.intention); + return ITypesUtil::Marshal(parcel, input.intention, input.visibility); } template<> bool Unmarshalling(CustomOption &output, MessageParcel &parcel) { - return ITypesUtil::Unmarshal(parcel, output.intention); + auto size = parcel.GetDataSize(); + if (size <= 0 || size > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_SERVICE, "CustomOption is empty or too large, dataSize is %{public}zu", size); + return false; + } + return ITypesUtil::Unmarshal(parcel, output.intention, output.visibility); } template<> @@ -146,6 +168,11 @@ bool Marshalling(const QueryOption &input, MessageParcel &parcel) template<> bool Unmarshalling(QueryOption &output, MessageParcel &parcel) { + auto size = parcel.GetDataSize(); + if (size <= 0 || size > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_SERVICE, "QueryOption is empty or too large, dataSize is %{public}zu", size); + return false; + } return ITypesUtil::Unmarshal(parcel, output.key, output.intention); } @@ -159,6 +186,11 @@ bool Marshalling(const UDType &input, MessageParcel &parcel) template<> bool Unmarshalling(UDType &output, MessageParcel &parcel) { + auto size = parcel.GetDataSize(); + if (size <= 0 || size > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_FRAMEWORK, "UDType is empty or too large, dataSize is %{public}zu", size); + return false; + } int32_t type; if (!ITypesUtil::Unmarshal(parcel, type)) { LOG_ERROR(UDMF_FRAMEWORK, "Unmarshal UDType failed!"); @@ -182,6 +214,11 @@ bool Marshalling(const Intention &input, MessageParcel &parcel) template<> bool Unmarshalling(Intention &output, MessageParcel &parcel) { + auto size = parcel.GetDataSize(); + if (size <= 0 || size > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_FRAMEWORK, "Intention is empty or too large, dataSize is %{public}zu", size); + return false; + } int32_t intention; if (!ITypesUtil::Unmarshal(parcel, intention)) { LOG_ERROR(UDMF_FRAMEWORK, "Unmarshal Intention failed!"); @@ -195,6 +232,34 @@ bool Unmarshalling(Intention &output, MessageParcel &parcel) return true; } +template<> +bool Marshalling(const Visibility &input, MessageParcel &parcel) +{ + int32_t visibility = input; + return ITypesUtil::Marshal(parcel, visibility); +} + +template<> +bool Unmarshalling(Visibility &output, MessageParcel &parcel) +{ + auto size = parcel.GetDataSize(); + if (size <= 0 || size > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_FRAMEWORK, "Visibility is empty or too large, dataSize is %{public}zu", size); + return false; + } + int32_t visibility; + if (!ITypesUtil::Unmarshal(parcel, visibility)) { + LOG_ERROR(UDMF_FRAMEWORK, "Unmarshal Visibility failed!"); + return false; + } + if (visibility < VISIBILITY_ALL || visibility >= VISIBILITY_BUTT) { + LOG_ERROR(UDMF_FRAMEWORK, "invalid visibility : %{public}d", visibility); + return false; + } + output = static_cast(visibility); + return true; +} + template<> bool Marshalling(const AsyncProcessInfo &input, MessageParcel &parcel) { @@ -207,6 +272,11 @@ bool Marshalling(const AsyncProcessInfo &input, MessageParcel &parcel) template<> bool Unmarshalling(AsyncProcessInfo &output, MessageParcel &parcel) { + auto size = parcel.GetDataSize(); + if (size <= 0 || size > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_FRAMEWORK, "AsyncProcessInfo is empty or too large, dataSize is %{public}zu", size); + return false; + } uint32_t syncStatus; uint32_t permStatus; if (!ITypesUtil::Unmarshal(parcel, syncStatus, permStatus, output.srcDevName, output.syncFinished, output.syncTotal, @@ -223,5 +293,46 @@ bool Unmarshalling(AsyncProcessInfo &output, MessageParcel &parcel) output.permStatus = static_cast(permStatus); return true; } + +template<> +bool Marshalling(const DataLoadInfo &input, MessageParcel &parcel) +{ + std::vector dataSetBytes; + auto recordTlv = TLVObject(dataSetBytes); + if (!TLVUtil::Writing(input, recordTlv, TAG::TAG_DATA_LOAD_INFO)) { + LOG_ERROR(UDMF_SERVICE, "TLV writing failed!"); + return false; + } + if (!parcel.WriteInt32(static_cast(dataSetBytes.size())) + || !parcel.WriteRawData(dataSetBytes.data(), dataSetBytes.size())) { + LOG_ERROR(UDMF_SERVICE, "Marshall dataLoadInfo failed!"); + return false; + } + return true; +} + +template<> +bool Unmarshalling(DataLoadInfo &output, MessageParcel &parcel) +{ + auto size = parcel.ReadInt32(); + auto dataSize = parcel.GetDataSize(); + if (size <= 0 || size > NORMAL_MAX_PARCEL_SIZE || dataSize > NORMAL_MAX_PARCEL_SIZE) { + LOG_ERROR(UDMF_SERVICE, + "DataLoadInfo is empty or too large, dataSize is %{public}zu, size is %{public}d", dataSize, size); + return false; + } + const uint8_t *rawData = reinterpret_cast(parcel.ReadRawData(size)); + if (rawData == nullptr) { + LOG_ERROR(UDMF_SERVICE, "RawData is null!"); + return false; + } + std::vector dataSetBytes(rawData, rawData + size); + auto dataTlv = TLVObject(dataSetBytes); + if (!TLVUtil::ReadTlv(output, dataTlv, TAG::TAG_DATA_LOAD_INFO)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshall dataLoadInfo failed!"); + return false; + } + return true; +} } // namespace ITypesUtil } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/common/udmf_types_util.h b/udmf/framework/common/udmf_types_util.h index f6293c98..02d68190 100644 --- a/udmf/framework/common/udmf_types_util.h +++ b/udmf/framework/common/udmf_types_util.h @@ -21,6 +21,7 @@ #include "unified_data.h" #include "unified_meta.h" #include "unified_types.h" +#include "async_task_params.h" namespace OHOS { namespace ITypesUtil { @@ -31,7 +32,9 @@ using CustomOption = UDMF::CustomOption; using QueryOption = UDMF::QueryOption; using UDType = UDMF::UDType; using Intention = UDMF::Intention; +using Visibility = UDMF::Visibility; using AsyncProcessInfo = UDMF::AsyncProcessInfo; +using DataLoadInfo = UDMF::DataLoadInfo; template<> bool API_EXPORT Marshalling(const UnifiedData &input, MessageParcel &parcel); @@ -73,10 +76,20 @@ bool API_EXPORT Marshalling(const Intention &input, MessageParcel &parcel); template<> bool API_EXPORT Unmarshalling(Intention &output, MessageParcel &parcel); +template<> +bool API_EXPORT Marshalling(const Visibility &input, MessageParcel &parcel); +template<> +bool API_EXPORT Unmarshalling(Visibility &output, MessageParcel &parcel); + template<> bool API_EXPORT Marshalling(const AsyncProcessInfo &input, MessageParcel &parcel); template<> bool API_EXPORT Unmarshalling(AsyncProcessInfo &output, MessageParcel &parcel); + +template<> +bool API_EXPORT Marshalling(const DataLoadInfo &input, MessageParcel &parcel); +template<> +bool API_EXPORT Unmarshalling(DataLoadInfo &output, MessageParcel &parcel); } // namespace ITypesUtil } // namespace OHOS #endif // UDMF_TYPES_UTIL_H \ No newline at end of file diff --git a/udmf/framework/common/udmf_utils.cpp b/udmf/framework/common/udmf_utils.cpp index ac1f66f1..5ab66ec7 100644 --- a/udmf/framework/common/udmf_utils.cpp +++ b/udmf/framework/common/udmf_utils.cpp @@ -29,20 +29,6 @@ static constexpr int MINIMUM = 48; static constexpr int MAXIMUM = 121; constexpr char SPECIAL = '^'; -std::vector StrSplit(const std::string &str, const std::string &delimiter) -{ - std::vector result; - size_t start = 0; - size_t end = str.find(delimiter); - while (end != std::string::npos) { - result.push_back(str.substr(start, end - start)); - start = end + delimiter.length(); - end = str.find(delimiter, start); - } - result.push_back(str.substr(start)); - return result; -} - std::vector Random(int32_t len, int32_t minimum, int32_t maximum) { std::random_device randomDevice; @@ -66,37 +52,36 @@ std::string GenerateId() return idStr.str(); } -std::string GetSdkVersionByToken(uint32_t tokenId) +bool IsTokenNative() { - if (Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId) != - Security::AccessToken::ATokenTypeEnum::TOKEN_HAP) { - return ""; - } - Security::AccessToken::HapTokenInfo hapTokenInfo; - auto ret = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(tokenId, hapTokenInfo); - if (ret != 0) { - return ""; + uint32_t tokenId = IPCSkeleton::GetSelfTokenID(); + if (tokenId == 0) { + return false; } - return std::to_string(hapTokenInfo.apiVersion); -} - -std::string GetCurrentSdkVersion() -{ - static const std::string sdkVersion = GetSdkVersionByToken(IPCSkeleton::GetSelfTokenID()); - return sdkVersion; + auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId); + return tokenType == Security::AccessToken::TypeATokenTypeEnum::TOKEN_NATIVE; } -bool IsTokenNative() +bool IsNativeCallingToken() { - uint32_t tokenId = IPCSkeleton::GetSelfTokenID(); + uint32_t tokenId = IPCSkeleton::GetCallingTokenID(); if (tokenId == 0) { return false; } auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(tokenId); - LOG_DEBUG(UDMF_FRAMEWORK, "tokenId=%{public}u, tokenType=%{public}d", tokenId, tokenType); return tokenType == Security::AccessToken::TypeATokenTypeEnum::TOKEN_NATIVE; } +std::string GetSequenceKey(const std::string &udKey) +{ + auto pos = udKey.rfind('/'); + if (pos == std::string::npos || pos + 1 >= udKey.length()) { + LOG_ERROR(UDMF_FRAMEWORK, "Error udKey:%{public}s", udKey.c_str()); + return ""; + } + return udKey.substr(pos + 1); +} + } // namespace UTILS } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/common/udmf_utils.h b/udmf/framework/common/udmf_utils.h index 3d4fde6d..9cc3f7c7 100644 --- a/udmf/framework/common/udmf_utils.h +++ b/udmf/framework/common/udmf_utils.h @@ -16,21 +16,21 @@ #ifndef UDMF_UTILS_H #define UDMF_UTILS_H +#include #include #include -#include #include "visibility.h" namespace OHOS { namespace UDMF { namespace UTILS { -std::vector StrSplit(const std::string &str, const std::string &delimiter); std::vector Random(int32_t len, int32_t minimum = 0, int32_t maximum = std::numeric_limits::max()); -std::string GenerateId(); +std::string API_EXPORT GenerateId(); std::string GetSdkVersionByToken(uint32_t tokenId); std::string GetCurrentSdkVersion(); - bool API_EXPORT IsTokenNative(); +bool API_EXPORT IsNativeCallingToken(); +std::string API_EXPORT GetSequenceKey(const std::string &udKey); } // namespace UTILS } // namespace UDMF diff --git a/udmf/framework/common/unittest/BUILD.gn b/udmf/framework/common/unittest/BUILD.gn index 8009d2c2..c9f84221 100644 --- a/udmf/framework/common/unittest/BUILD.gn +++ b/udmf/framework/common/unittest/BUILD.gn @@ -13,7 +13,7 @@ import("//build/test.gni") import("//foundation/distributeddatamgr/udmf/udmf.gni") -module_output_path = "udmf/common" +module_output_path = "udmf/udmf/common" ############################################################################### config("module_private_config") { @@ -25,6 +25,7 @@ config("module_private_config") { "${udmf_interfaces_path}/innerkits/data", "${udmf_framework_path}/common/unittest/mock/include", "${udmf_framework_path}/innerkitsimpl/client/", + "mock/", ] } @@ -36,12 +37,13 @@ common_deps = [ common_external_deps = [ "ability_base:want", "ability_base:zuri", + "ability_runtime:dataobs_manager", "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "access_token:libtoken_setproc", "bundle_framework:appexecfwk_core", "c_utils:utils", - "ffmpeg:libohosffmpeg", + "dfs_service:distributed_file_daemon_kit_inner", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", @@ -52,7 +54,6 @@ common_external_deps = [ "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", - "libexif:libexif", "samgr:samgr_proxy", ] @@ -69,7 +70,7 @@ ohos_unittest("UtdCfgsCheckerTest") { configs = [ ":module_private_config" ] deps = common_deps - + use_exceptions = true external_deps = common_external_deps } @@ -90,6 +91,31 @@ ohos_unittest("UdmfTypesUtilTest") { ] } +ohos_unittest("UdmfTypesUtilMockTest") { + module_out_path = module_output_path + + sources = [ + "mock/message_parcel_mock.cpp", + "udmf_types_util_mock_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = common_deps + + external_deps = common_external_deps + + external_deps += [ + "googletest:gmock_main", + "googletest:gtest_main", + ] + + defines = [ + "private=public", + "protected=public", + ] +} + ohos_unittest("UdmfTypesUtilAbnormalTest") { module_out_path = module_output_path @@ -118,12 +144,15 @@ ohos_unittest("UdmfTypesUtilAbnormalTest") { deps = [ "${udmf_interfaces_path}/innerkits:udmf_client", "${udmf_interfaces_path}/innerkits:utd_client", - "//third_party/googletest:gmock_main", - "//third_party/googletest:gtest_main", ] external_deps = common_external_deps + external_deps += [ + "googletest:gmock_main", + "googletest:gtest_main", + ] + defines = [ "private=public", "protected=public", @@ -152,6 +181,8 @@ ohos_unittest("TlvUtilTest") { "image_framework:image", "image_framework:image_native", "image_framework:pixelmap", + "ipc:ipc_single", + "kv_store:distributeddata_inner", ] defines = [ @@ -180,14 +211,54 @@ ohos_unittest("EndianConverterTest") { ] } +ohos_unittest("CopyFileTest") { + module_out_path = module_output_path + + sources = [ + "${udmf_framework_path}/common/udmf_copy_file.cpp", + "${udmf_framework_path}/common/udmf_executor.cpp", + "${udmf_framework_path}/common/udmf_utils.cpp", + "${udmf_framework_path}/common/unittest/mock/file_copy_manager_mock.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_async_client.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_client.cpp", + "${udmf_framework_path}/innerkitsimpl/common/progress_queue.cpp", + "${udmf_framework_path}/innerkitsimpl/common/unified_meta.cpp", + "${udmf_framework_path}/innerkitsimpl/convert/udmf_conversion.cpp", + "${udmf_framework_path}/innerkitsimpl/data/unified_data.cpp", + "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + "${udmf_framework_path}/innerkitsimpl/service/progress_callback.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_notifier_stub.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_service_client.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_service_proxy.cpp", + "udmf_copy_file_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = common_deps + + external_deps = common_external_deps + + external_deps += [ "app_file_service:fileuri_native" ] + + defines = [ + "private=public", + "protected=public", + ] + + use_exceptions = true +} + ############################################################################### group("unittest") { testonly = true deps = [ + ":CopyFileTest", ":EndianConverterTest", ":TlvUtilTest", ":UdmfTypesUtilAbnormalTest", + ":UdmfTypesUtilMockTest", ":UdmfTypesUtilTest", ":UtdCfgsCheckerTest", ] diff --git a/udmf/framework/common/unittest/mock/file_copy_manager_mock.cpp b/udmf/framework/common/unittest/mock/file_copy_manager_mock.cpp new file mode 100644 index 00000000..542c7eb8 --- /dev/null +++ b/udmf/framework/common/unittest/mock/file_copy_manager_mock.cpp @@ -0,0 +1,148 @@ +/* + * 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. + */ + +#define LOG_TAG "UdmfCopyFileMock" +#include "copy/file_copy_manager.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "logger.h" + +namespace OHOS { +namespace Storage { +namespace DistributedFile { +std::shared_ptr FileCopyManager::instance_ = nullptr; + +std::shared_ptr FileCopyManager::GetInstance() +{ + static auto instance = std::make_shared(); + return instance; +} + +int32_t FileCopyManager::Copy(const std::string &srcUri, const std::string &destUri, ProcessCallback &processCallback) +{ + return 0; +} + +int32_t FileCopyManager::ExecRemote(std::shared_ptr infos, ProcessCallback &processCallback) +{ + return 0; +} + +int32_t FileCopyManager::Cancel(const bool isKeepFiles) +{ + return 0; +} + +int32_t FileCopyManager::Cancel(const std::string &srcUri, const std::string &destUri, const bool isKeepFiles) +{ + return 0; +} + +void FileCopyManager::DeleteResFile(std::shared_ptr infos) +{ +} + +int32_t FileCopyManager::ExecLocal(std::shared_ptr infos) +{ + return 0; +} + +int32_t FileCopyManager::CopyFile(const std::string &src, const std::string &dest, std::shared_ptr infos) +{ + return 0; +} + +void fs_req_cleanup(uv_fs_t* req) +{ +} + +int32_t FileCopyManager::SendFileCore(std::shared_ptr srcFdg, + std::shared_ptr destFdg, std::shared_ptr infos) +{ + return 0; +} + +int32_t FileCopyManager::CopyDirFunc(const std::string &src, const std::string &dest, std::shared_ptr infos) +{ + return 0; +} + +int32_t FileCopyManager::CopySubDir(const std::string &srcPath, + const std::string &destPath, std::shared_ptr infos) +{ + return 0; +} + +int32_t FileCopyManager::RecurCopyDir(const std::string &srcPath, + const std::string &destPath, std::shared_ptr infos) +{ + return 0; +} + +void FileCopyManager::AddFileInfos(std::shared_ptr infos) +{ +} + +void FileCopyManager::RemoveFileInfos(std::shared_ptr infos) +{ +} + +int32_t FileCopyManager::CreateFileInfos(const std::string &srcUri, + const std::string &destUri, std::shared_ptr &infos) +{ + return 0; +} + +std::string GetModeFromFlags(unsigned int flags) +{ + return 0; +} + +int32_t FileCopyManager::OpenSrcFile(const std::string &srcPth, std::shared_ptr infos, int32_t &srcFd) +{ + return 0; +} + +int FileCopyManager::MakeDir(const std::string &path) +{ + return 0; +} + +bool FileCopyManager::IsRemoteUri(const std::string &uri) +{ + return true; +} + +bool FileCopyManager::IsMediaUri(const std::string &uriPath) +{ + return true; +} + +int32_t FileCopyManager::CheckOrCreatePath(const std::string &destPath) +{ + return 0; +} +} // namespace DistributedFile +} // namespace Storage +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/common/unittest/mock/message_parcel_mock.cpp b/udmf/framework/common/unittest/mock/message_parcel_mock.cpp new file mode 100644 index 00000000..ebf0ac6b --- /dev/null +++ b/udmf/framework/common/unittest/mock/message_parcel_mock.cpp @@ -0,0 +1,253 @@ +/* + * 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 "iremote_broker.h" +#include "message_parcel_mock.h" + +namespace OHOS { +using namespace OHOS::UDMF; + +Parcelable::Parcelable() : Parcelable(false) +{} + +Parcelable::Parcelable(bool asRemote) +{ + asRemote_ = asRemote; + behavior_ = 0; +} + +bool MessageParcel::WriteInterfaceToken(std::u16string name) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteInterfaceToken(name); +} + +std::u16string MessageParcel::ReadInterfaceToken() +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return std::u16string(); + } + return UdmfMessageParcel::messageParcel->ReadInterfaceToken(); +} + +bool Parcel::WriteParcelable(const Parcelable *object) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteParcelable(object); +} + +bool Parcel::WriteInt32(int32_t value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteInt32(value); +} + +int32_t Parcel::ReadInt32() +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return -1; // -1: default err + } + return UdmfMessageParcel::messageParcel->ReadInt32(); +} + +bool Parcel::ReadInt32(int32_t &value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->ReadInt32(value); +} + +bool Parcel::WriteRemoteObject(const Parcelable *object) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteRemoteObject(object); +} + +bool MessageParcel::WriteRemoteObject(const sptr &object) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteRemoteObject(object); +} + +sptr MessageParcel::ReadRemoteObject() +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return nullptr; + } + return UdmfMessageParcel::messageParcel->ReadRemoteObject(); +} + +bool Parcel::ReadBool() +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->ReadBool(); +} + +bool Parcel::ReadBool(bool &value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->ReadBool(value); +} + +bool Parcel::WriteBool(bool value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteBool(value); +} + +bool Parcel::WriteString(const std::string &value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteString(value); +} + +bool Parcel::WriteCString(const char *value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteCString(value); +} + +bool Parcel::ReadString(std::string &value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->ReadString(value); +} + +bool Parcel::ReadStringVector(std::vector *value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->ReadStringVector(value); +} + +bool MessageParcel::WriteFileDescriptor(int fd) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteFileDescriptor(fd); +} + +int MessageParcel::ReadFileDescriptor() +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return -1; // -1: default err + } + return UdmfMessageParcel::messageParcel->ReadFileDescriptor(); +} + +bool Parcel::ReadUint32(uint32_t &value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->ReadUint32(value); +} + +bool Parcel::WriteUint64(uint64_t value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteUint64(value); +} + +bool Parcel::WriteUint16(uint16_t value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteUint16(value); +} + +bool Parcel::ReadUint64(uint64_t &value) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->ReadUint64(value); +} + +bool Parcel::WriteStringVector(const std::vector &val) +{ + if (UdmfMessageParcel::messageParcel == nullptr) { + return false; + } + return UdmfMessageParcel::messageParcel->WriteStringVector(val); +} + +bool Parcel::WriteUint32(uint32_t value) +{ + if (UdmfMessageParcel::messageParcel) { + return UdmfMessageParcel::messageParcel->WriteUint32(value); + } + return false; +} + +bool MessageParcel::WriteRawData(const void *data, size_t size) +{ + if (UdmfMessageParcel::messageParcel) { + return UdmfMessageParcel::messageParcel->WriteRawData(data, size); + } + return false; +} + +const void *MessageParcel::ReadRawData(size_t size) +{ + if (UdmfMessageParcel::messageParcel) { + return UdmfMessageParcel::messageParcel->ReadRawData(size); + } + return nullptr; +} + +uint32_t Parcel::ReadUint32() +{ + if (UdmfMessageParcel::messageParcel) { + return UdmfMessageParcel::messageParcel->ReadUint32(); + } + return 1; // : default value +} + +size_t Parcel::GetDataSize() const +{ + if (UdmfMessageParcel::messageParcel) { + return UdmfMessageParcel::messageParcel->GetDataSize(); + } + return 1; // : default value +} +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/common/unittest/mock/message_parcel_mock.h b/udmf/framework/common/unittest/mock/message_parcel_mock.h new file mode 100644 index 00000000..22bf9a6e --- /dev/null +++ b/udmf/framework/common/unittest/mock/message_parcel_mock.h @@ -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. + */ +#ifndef UDMF_MESSAGE_PARCEL_MOCK_H +#define UDMF_MESSAGE_PARCEL_MOCK_H + +#include +#include +#include + +#include "message_parcel.h" +#include "iremote_broker.h" + +namespace OHOS::UDMF { +class UdmfMessageParcel { +public: + virtual ~UdmfMessageParcel() = default; +public: + virtual bool WriteInterfaceToken(std::u16string name) = 0; + virtual std::u16string ReadInterfaceToken() = 0; + virtual bool WriteParcelable(const Parcelable *object) = 0; + virtual bool WriteInt32(int32_t value) = 0; + virtual int32_t ReadInt32() = 0; + virtual bool ReadInt32(int32_t &value) = 0; + virtual bool WriteRemoteObject(const Parcelable *object) = 0; + virtual bool WriteRemoteObject(const sptr &object) = 0; + virtual sptr ReadRemoteObject() = 0; + virtual bool ReadBool(); + virtual bool ReadBool(bool &value) = 0; + virtual bool WriteBool(bool value) = 0; + virtual bool WriteString(const std::string &value) = 0; + virtual bool WriteCString(const char *value) = 0; + virtual bool WriteFileDescriptor(int fd) = 0; + virtual bool ReadString(std::string &value) = 0; + virtual int ReadFileDescriptor() = 0; + virtual bool ReadStringVector(std::vector *value) = 0; + virtual bool ReadUint32(uint32_t &value) = 0; + virtual bool WriteUint64(uint64_t value) = 0; + virtual bool WriteUint16(uint16_t value) = 0; + virtual bool ReadUint64(uint64_t &value) = 0; + virtual bool WriteStringVector(const std::vector &val) = 0; + virtual bool WriteUint32(uint32_t value) = 0; + virtual bool WriteRawData(const void *data, size_t size) = 0; + virtual const void *ReadRawData(size_t size) = 0; + virtual uint32_t ReadUint32() = 0; + virtual size_t GetDataSize() = 0; +public: + static inline std::shared_ptr messageParcel = nullptr; +}; + +class MessageParcelMock : public UdmfMessageParcel { +public: + MOCK_METHOD1(WriteInterfaceToken, bool(std::u16string name)); + MOCK_METHOD0(ReadInterfaceToken, std::u16string()); + MOCK_METHOD1(WriteParcelable, bool(const Parcelable *object)); + MOCK_METHOD1(WriteInt32, bool(int32_t value)); + MOCK_METHOD0(ReadInt32, int32_t()); + MOCK_METHOD1(ReadInt32, bool(int32_t &value)); + MOCK_METHOD1(WriteRemoteObject, bool(const Parcelable *object)); + MOCK_METHOD1(WriteRemoteObject, bool(const sptr &object)); + MOCK_METHOD0(ReadRemoteObject, sptr()); + MOCK_METHOD0(ReadBool, bool()); + MOCK_METHOD1(ReadBool, bool(bool &value)); + MOCK_METHOD1(WriteBool, bool(bool value)); + MOCK_METHOD1(WriteString, bool(const std::string &value)); + MOCK_METHOD1(WriteCString, bool(const char *value)); + MOCK_METHOD1(WriteFileDescriptor, bool(int fd)); + MOCK_METHOD1(ReadString, bool(std::string &value)); + MOCK_METHOD0(ReadFileDescriptor, int()); + MOCK_METHOD1(ReadStringVector, bool(std::vector *value)); + MOCK_METHOD1(ReadUint32, bool(uint32_t &value)); + MOCK_METHOD1(WriteUint64, bool(uint64_t value)); + MOCK_METHOD1(WriteUint16, bool(uint16_t value)); + MOCK_METHOD1(ReadUint64, bool(uint64_t &value)); + MOCK_METHOD1(WriteStringVector, bool(const std::vector &val)); + MOCK_METHOD1(WriteUint32, bool(uint32_t value)); + MOCK_METHOD2(WriteRawData, bool(const void *data, size_t size)); + MOCK_METHOD1(ReadRawData, const void*(size_t size)); + MOCK_METHOD0(ReadUint32, uint32_t()); + MOCK_METHOD0(GetDataSize, size_t()); +}; +} +#endif // UDMF_MESSAGE_PARCEL_MOCK_H diff --git a/udmf/framework/common/unittest/mock/tlv_util_mock.cpp b/udmf/framework/common/unittest/mock/tlv_util_mock.cpp index 801a1016..adff8a6e 100644 --- a/udmf/framework/common/unittest/mock/tlv_util_mock.cpp +++ b/udmf/framework/common/unittest/mock/tlv_util_mock.cpp @@ -143,7 +143,10 @@ template <> size_t CountBufferSize(const UnifiedData &input, TLVObject &data) template <> bool Writing(const UnifiedData &input, TLVObject &data, TAG tag) { - return false; + if (input.dataId_ == 0) { + return false; + } + return true; } template <> bool Reading(UnifiedData &output, TLVObject &data, const TLVHead &head) @@ -227,6 +230,19 @@ template <> bool Reading(std::shared_ptr &output, TLVObject & return true; } +template <> size_t API_EXPORT CountBufferSize(const DataLoadInfo &input, TLVObject &data) +{ + return sizeof(TLVHead); +} + +template <> bool API_EXPORT Writing(const DataLoadInfo &input, TLVObject &data, TAG tag) +{ + return true; +} +template <> bool API_EXPORT Reading(DataLoadInfo &output, TLVObject &data, const TLVHead &head) +{ + return true; +} } // namespace TLVUtil } // namespace OHOS diff --git a/udmf/framework/common/unittest/tlv_util_test.cpp b/udmf/framework/common/unittest/tlv_util_test.cpp index 2079cda3..9d657dcd 100644 --- a/udmf/framework/common/unittest/tlv_util_test.cpp +++ b/udmf/framework/common/unittest/tlv_util_test.cpp @@ -179,7 +179,7 @@ HWTEST_F(TlvUtilTest, CountBufferSize_004, TestSize.Level1) EXPECT_EQ(4 * sizeof(TLVHead) + sizeof(int32_t), TLVUtil::CountBufferSize(privilege, tlvObject)); Runtime runtime; - EXPECT_EQ(19 * sizeof(TLVHead) + sizeof(bool) + sizeof(size_t) + 2 * sizeof(int64_t) + 2 * sizeof(int32_t) + + EXPECT_EQ(21 * sizeof(TLVHead) + sizeof(bool) + sizeof(size_t) + 2 * sizeof(int64_t) + 3 * sizeof(int32_t) + 2 * sizeof(uint32_t), TLVUtil::CountBufferSize(runtime, tlvObject)); LOG_INFO(UDMF_TEST, "CountBufferSize_004 end."); @@ -301,6 +301,7 @@ HWTEST_F(TlvUtilTest, WritingAndReading_002, TestSize.Level1) runtime.dataVersion = 3; runtime.createPackage = "package"; runtime.isPrivate = true; + runtime.appId = "appId"; std::vector dataBytes; auto tlvObject = TLVObject(dataBytes); @@ -320,6 +321,7 @@ HWTEST_F(TlvUtilTest, WritingAndReading_002, TestSize.Level1) EXPECT_EQ(runtime.privileges[0].tokenId, runtimeResult.privileges[0].tokenId); EXPECT_EQ(runtime.privileges[1].writePermission, runtimeResult.privileges[1].writePermission); EXPECT_EQ(runtime.privileges[1].tokenId, runtimeResult.privileges[1].tokenId); + EXPECT_EQ(runtime.appId, runtimeResult.appId); LOG_INFO(UDMF_TEST, "WritingAndReading_002 end."); } @@ -546,6 +548,56 @@ HWTEST_F(TlvUtilTest, WritingAndReading_005, TestSize.Level1) LOG_INFO(UDMF_TEST, "WritingAndReading_005 end."); } +/* * + * @tc.name: WritingAndReading_008 + * @tc.desc: test Runtime for Writing And Reading + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, WritingAndReading_008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "WritingAndReading_002 begin."); + UnifiedKey key; + key.key = "123456"; + Privilege privilege; + privilege.readPermission = "read"; + privilege.tokenId = 333; + Privilege privilege2; + privilege2.writePermission = "read"; + privilege2.tokenId = 444; + Runtime runtime; + runtime.dataStatus = DELETED; + runtime.key = key; + runtime.privileges.push_back(privilege); + runtime.privileges.push_back(privilege2); + runtime.createTime = 1; + runtime.dataVersion = 3; + runtime.createPackage = "package"; + runtime.isPrivate = true; + runtime.appId = "appId"; + + std::vector dataBytes; + auto tlvObject = TLVObject(dataBytes); + EXPECT_TRUE(TLVUtil::Writing(runtime, tlvObject, TAG::TAG_APP_ID)); + + tlvObject.ResetCursor(); + Runtime runtimeResult; + EXPECT_TRUE(TLVUtil::ReadTlv(runtimeResult, tlvObject, TAG::TAG_APP_ID)); + EXPECT_EQ(runtime.key.key, runtimeResult.key.key); + EXPECT_EQ(runtime.key.key, runtimeResult.key.key); + EXPECT_EQ(runtime.dataStatus, runtimeResult.dataStatus); + EXPECT_EQ(runtime.createTime, runtimeResult.createTime); + EXPECT_EQ(runtime.dataVersion, runtimeResult.dataVersion); + EXPECT_EQ(runtime.createPackage, runtimeResult.createPackage); + EXPECT_EQ(runtime.isPrivate, runtimeResult.isPrivate); + EXPECT_EQ(runtime.appId, runtimeResult.appId); + EXPECT_EQ(runtime.privileges[0].readPermission, runtimeResult.privileges[0].readPermission); + EXPECT_EQ(runtime.privileges[0].tokenId, runtimeResult.privileges[0].tokenId); + EXPECT_EQ(runtime.privileges[1].writePermission, runtimeResult.privileges[1].writePermission); + EXPECT_EQ(runtime.privileges[1].tokenId, runtimeResult.privileges[1].tokenId); + + LOG_INFO(UDMF_TEST, "WritingAndReading_008 end."); +} + /* * * @tc.name: WritingAndReadingFile_001 * @tc.desc: test Unified Data for Writing And Reading @@ -803,4 +855,398 @@ HWTEST_F(TlvUtilTest, WritingAndReading_007, TestSize.Level1) EXPECT_EQ(idValue, wantParamsResult.GetIntParam(idKey, 0)); LOG_INFO(UDMF_TEST, "WritingAndReading_007 end."); } + +/* * + * @tc.name: Reading_001 + * @tc.desc: Normal test of Reading + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_001, TestSize.Level1) +{ + std::nullptr_t output; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + TLVHead head; + bool ret = TLVUtil::Reading(output, data, head); + EXPECT_EQ(ret, data.Read(output, head)); +} + +/* * + * @tc.name: Reading_002 + * @tc.desc: Abnormal test of Reading, data is invalid + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_002, TestSize.Level1) +{ + DataStatus output; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + TLVHead head; + bool ret = TLVUtil::Reading(output, data, head); + EXPECT_FALSE(ret); +} + +/* * + * @tc.name: Reading_003 + * @tc.desc: Abnormal test of Reading, buffer_ is nullptr + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_003, TestSize.Level1) +{ + Object output; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + TLVHead head; + bool ret = TLVUtil::Reading(output, data, head); + EXPECT_FALSE(ret); +} + +/* * + * @tc.name: Reading_004 + * @tc.desc: Abnormal test of Reading, data is invalid + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_004, TestSize.Level1) +{ + OHOS::AAFwk::WantParams output; + TLVObject data; + TLVHead head; + bool ret = TLVUtil::Reading(output, data, head); + EXPECT_FALSE(ret); +} + +/* * + * @tc.name: Reading_005 + * @tc.desc: Test reading DataStatus with value below WORKING + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Reading_005 begin."); + int32_t invalidStatus = -1; + TLVHead head; + head.tag = static_cast(TAG::TAG_DATA_STATUS); + head.len = sizeof(invalidStatus); + + std::vector buffer; + buffer.resize(sizeof(head) + head.len); + + errno_t err = memcpy_s(buffer.data(), buffer.size(), &head, sizeof(head)); + ASSERT_EQ(err, EOK); + err = memcpy_s(buffer.data() + sizeof(head), buffer.size() - sizeof(head), + &invalidStatus, sizeof(invalidStatus)); + ASSERT_EQ(err, EOK); + TLVObject data(buffer); + TLVHead readHead; + ASSERT_TRUE(data.ReadHead(readHead)); + + DataStatus output; + EXPECT_FALSE(TLVUtil::Reading(output, data, readHead)); + LOG_INFO(UDMF_TEST, "Reading_005 end."); +} + +/* * + * @tc.name: Reading_006 + * @tc.desc: Test reading DataStatus with value at or above FADE + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Reading_006 begin."); + int32_t invalidStatus = 3; + TLVHead head; + head.tag = static_cast(TAG::TAG_DATA_STATUS); + head.len = sizeof(invalidStatus); + + std::vector buffer; + buffer.resize(sizeof(head) + head.len); + errno_t err = memcpy_s(buffer.data(), buffer.size(), &head, sizeof(head)); + ASSERT_EQ(err, EOK); + err = memcpy_s(buffer.data() + sizeof(head), buffer.size() - sizeof(head), + &invalidStatus, sizeof(invalidStatus)); + ASSERT_EQ(err, EOK); + TLVObject data(buffer); + TLVHead readHead; + ASSERT_TRUE(data.ReadHead(readHead)); + + DataStatus output; + EXPECT_FALSE(TLVUtil::Reading(output, data, readHead)); + LOG_INFO(UDMF_TEST, "Reading_006 end."); +} + +/* * + * @tc.name: Reading_007 + * @tc.desc: Test reading Object with incorrect inner tag + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_007, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Reading_007 begin."); + TLVHead outerHead; + outerHead.tag = static_cast(TAG::TAG_OBJECT_VALUE); + outerHead.len = sizeof(TLVHead) + 4; + + TLVHead innerHead; + innerHead.tag = static_cast(TAG::TAG_STRING); + innerHead.len = 4; + + const char* testData = "test"; + std::vector buffer; + buffer.resize(sizeof(outerHead) + sizeof(innerHead) + innerHead.len); + + errno_t err = memcpy_s(buffer.data(), buffer.size(), &outerHead, sizeof(outerHead)); + ASSERT_EQ(err, EOK); + err = memcpy_s(buffer.data() + sizeof(outerHead), buffer.size() - sizeof(outerHead), + &innerHead, sizeof(innerHead)); + ASSERT_EQ(err, EOK); + err = memcpy_s(buffer.data() + sizeof(outerHead) + sizeof(innerHead), + buffer.size() - sizeof(outerHead) - sizeof(innerHead), + testData, innerHead.len); + ASSERT_EQ(err, EOK); + + TLVObject data(buffer); + TLVHead readOuterHead; + ASSERT_TRUE(data.ReadHead(readOuterHead)); + + Object output; + bool result = TLVUtil::Reading(output, data, readOuterHead); + EXPECT_FALSE(result); + LOG_INFO(UDMF_TEST, "Reading_007 end."); +} + +/* * + * @tc.name: Writing_001 + * @tc.desc: Abnormal test of Writing, input.tag is invalid + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Writing_001, TestSize.Level1) +{ + UnifiedDataProperties input; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + TAG tag = TAG::TAG_NULL; + input.tag = "test"; + bool ret = TLVUtil::Writing(input, data, tag); + EXPECT_FALSE(ret); +} + +/* * + * @tc.name: Writing_002 + * @tc.desc: Abnormal test of Writing, input.timestamp is invalid + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Writing_002, TestSize.Level1) +{ + UnifiedDataProperties input; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + std::string dataFile = "demo1"; + std::vector dataBytes; + auto tlvObject = TLVObject(dataBytes); + std::FILE *file = fopen(dataFile.c_str(), "w+"); + tlvObject.SetFile(file); + TAG tag = TAG::TAG_NULL; + input.tag = "test"; + input.timestamp = 0; + bool ret = TLVUtil::Writing(input, data, tag); + EXPECT_FALSE(ret); + fclose(file); +} + +/* * + * @tc.name: Writing_003 + * @tc.desc: Abnormal test of Writing input is invalid + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Writing_003, TestSize.Level1) +{ + Privilege input; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + TAG tag = TAG::TAG_NULL; + bool ret = TLVUtil::Writing(input, data, tag); + EXPECT_FALSE(ret); +} + +/* * + * @tc.name: CountBufferSize_006 + * @tc.desc: Abnormal test of CountBufferSize, input is nullptr + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, CountBufferSize_006, TestSize.Level1) +{ + std::shared_ptr> input = nullptr; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + size_t ret = TLVUtil::CountBufferSize(input, data); + EXPECT_EQ(ret, data.CountHead()); +} + +/* * + * @tc.name: WritingSet001 + * @tc.desc: Normal test of Writing Set + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, WritingSet001, TestSize.Level1) { + LOG_INFO(UDMF_TEST, "WritingSet001 begin."); + std::set data = {"typeA", "typeB", "typeC"}; + + std::vector dataBytes; + auto tlvObject = TLVObject(dataBytes); + auto result = TLVUtil::Writing(data, tlvObject, TAG::TAG_SET_TYPES); + EXPECT_TRUE(result); + + tlvObject.ResetCursor(); + std::set dataResult; + result = TLVUtil::ReadTlv(dataResult, tlvObject, TAG::TAG_SET_TYPES); + EXPECT_TRUE(result); + ASSERT_EQ(data.size(), dataResult.size()); + for (auto &item : data) { + EXPECT_TRUE(dataResult.find(item) != dataResult.end()); + } + LOG_INFO(UDMF_TEST, "WritingSet001 end."); +} + +/* * + * @tc.name: WritingDataLoadInfo001 + * @tc.desc: Normal test of Writing DataLoadInfo + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, WritingDataLoadInfo001, TestSize.Level1) { + LOG_INFO(UDMF_TEST, "WritingDataLoadInfo001 begin."); + DataLoadInfo normalData; + normalData.sequenceKey = "seq_2023"; + normalData.types = {"typeA", "typeB", "typeC"}; + normalData.recordCount = 1000; + + std::vector dataBytes; + auto tlvObject = TLVObject(dataBytes); + auto result = TLVUtil::Writing(normalData, tlvObject, TAG::TAG_DATA_LOAD_INFO); + EXPECT_TRUE(result); + + tlvObject.ResetCursor(); + DataLoadInfo normalDataResult; + result = TLVUtil::ReadTlv(normalDataResult, tlvObject, TAG::TAG_DATA_LOAD_INFO); + EXPECT_TRUE(result); + EXPECT_EQ(normalData.sequenceKey, normalDataResult.sequenceKey); + EXPECT_EQ(normalData.recordCount, normalDataResult.recordCount); + ASSERT_EQ(normalData.types.size(), normalDataResult.types.size()); + for (auto &item : normalData.types) { + EXPECT_TRUE(normalDataResult.types.find(item) != normalDataResult.types.end()); + } + LOG_INFO(UDMF_TEST, "WritingDataLoadInfo001 end."); +} + +/* * + * @tc.name: WritingDataLoadInfo002 + * @tc.desc: Normal test of Writing boundary DataLoadInfo + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, WritingDataLoadInfo002, TestSize.Level1) { + DataLoadInfo boundaryData; + boundaryData.sequenceKey = ""; + boundaryData.types = {}; + boundaryData.recordCount = 0; + + std::vector dataBytes; + auto tlvObject = TLVObject(dataBytes); + auto result = TLVUtil::Writing(boundaryData, tlvObject, TAG::TAG_DATA_LOAD_INFO); + EXPECT_TRUE(result); + + tlvObject.ResetCursor(); + DataLoadInfo boundaryDataResult; + result = TLVUtil::ReadTlv(boundaryDataResult, tlvObject, TAG::TAG_DATA_LOAD_INFO); + EXPECT_TRUE(result); + EXPECT_EQ(boundaryData.sequenceKey, boundaryDataResult.sequenceKey); + EXPECT_EQ(boundaryData.recordCount, boundaryDataResult.recordCount); + ASSERT_EQ(boundaryData.types.size(), boundaryDataResult.types.size()); + for (auto &item : boundaryData.types) { + EXPECT_TRUE(boundaryDataResult.types.find(item) != boundaryDataResult.types.end()); + } + LOG_INFO(UDMF_TEST, "WritingDataLoadInfo002 end."); +} + +/* * + * @tc.name: Reading_008 + * @tc.desc: test Reading fun + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Reading_008 begin."); + UnifiedKey uKey; + UnifiedData uData; + UnifiedDataProperties uProperties; + UnifiedRecord uRecord; + Runtime rTime; + Privilege privilege; + UriInfo uInfo; + Summary summary; + DataLoadInfo loadInfo; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + TLVHead head; + head.len = data.GetTotal() - data.GetCursor() + 1; + auto result = TLVUtil::Reading(uKey, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(uData, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(uProperties, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(uRecord, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(rTime, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(privilege, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(uInfo, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(summary, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(loadInfo, data, head); + EXPECT_FALSE(result); + LOG_INFO(UDMF_TEST, "Reading_008 end."); +} + +/* * + * @tc.name: Reading_009 + * @tc.desc: test Reading fun + * @tc.type: FUNC + */ +HWTEST_F(TlvUtilTest, Reading_009, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Reading_009 begin."); + UnifiedKey uKey; + UnifiedData uData; + UnifiedDataProperties uProperties; + UnifiedRecord uRecord; + Runtime rTime; + Privilege privilege; + UriInfo uInfo; + Summary summary; + DataLoadInfo loadInfo; + std::vector buffer = { 1, 2 }; + TLVObject data(buffer); + TLVHead head; + head.len = data.GetTotal() - data.GetCursor() - 1; + auto result = TLVUtil::Reading(uKey, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(uData, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(uProperties, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(uRecord, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(rTime, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(privilege, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(uInfo, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(summary, data, head); + EXPECT_FALSE(result); + result = TLVUtil::Reading(loadInfo, data, head); + EXPECT_FALSE(result); + LOG_INFO(UDMF_TEST, "Reading_009 end."); +} } diff --git a/udmf/framework/common/unittest/udmf_copy_file_test.cpp b/udmf/framework/common/unittest/udmf_copy_file_test.cpp new file mode 100644 index 00000000..a9245403 --- /dev/null +++ b/udmf/framework/common/unittest/udmf_copy_file_test.cpp @@ -0,0 +1,150 @@ +/* + * 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. + */ +#define LOG_TAG "CopyFileTest" + +#include +#include +#include + +#include "logger.h" +#include "udmf_copy_file.h" + +using namespace testing::ext; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { + +class CopyFileTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void CopyFileTest::SetUpTestCase() +{ +} + +void CopyFileTest::TearDownTestCase() +{ +} + +void CopyFileTest::SetUp() +{ +} + +void CopyFileTest::TearDown() +{ +} + +/** +* @tc.name: GetInstance +* @tc.desc: GetInstance Should Return Same Instance +* @tc.type: FUNC +*/ +HWTEST_F(CopyFileTest, GetInstance, TestSize.Level1) +{ + auto& instance1 = UdmfCopyFile::GetInstance(); + auto& instance2 = UdmfCopyFile::GetInstance(); + ASSERT_EQ(&instance1, &instance2); +} + +/** +* @tc.name: Copy001 +* @tc.desc: Copy Should Return Canceled When ProgressQueue Is Cancel +* @tc.type: FUNC +*/ +HWTEST_F(CopyFileTest, Copy001, TestSize.Level1) +{ + auto asyncHelper = std::make_unique(); + asyncHelper->progressQueue.Cancel(); + ASSERT_TRUE(asyncHelper->progressQueue.IsCancel()); + + auto result = UdmfCopyFile::GetInstance().Copy(asyncHelper); + ASSERT_EQ(result, E_COPY_CANCELED); +} + +/** +* @tc.name: Copy002 +* @tc.desc: normal copy test +* @tc.type: FUNC +*/ +HWTEST_F(CopyFileTest, Copy002, TestSize.Level1) +{ + std::string srcUri = "test_src.txt"; + std::string destUri = "test_dest.txt"; + auto record = std::make_shared(); + auto asyncHelper = std::make_unique(); + UdmfCopyFile::CopyContext context(asyncHelper); + + bool result = UdmfCopyFile::GetInstance().CopyFile(srcUri, destUri, record, context); + EXPECT_TRUE(result); + EXPECT_EQ(context.status, E_OK); +} + +/** +* @tc.name: ConstructDestUri +* @tc.desc: Construct DestUri Should Correctly Construct Destination Path +* @tc.type: FUNC +*/ +HWTEST_F(CopyFileTest, ConstructDestUri, TestSize.Level1) +{ + std::string destUri = "/destination"; + std::string srcUri = "/source/file.txt"; + auto result = UdmfCopyFile::GetInstance().ConstructDestUri(destUri, srcUri); + ASSERT_EQ(result, "/destination/file.txt"); +} + +/** +* @tc.name: GetFileName001 +* @tc.desc: GetFileName Should Handle Remote Files Correctly +* @tc.type: FUNC +*/ +HWTEST_F(CopyFileTest, GetFileName001, TestSize.Level1) +{ + std::string remoteFile = "file://data/storage/el2/distributedfiles/103.png"; + auto result = UdmfCopyFile::GetInstance().GetFileName(remoteFile); + ASSERT_EQ(result, "103.png"); +} + +/** +* @tc.name: GetFileName002 +* @tc.desc: GetFileName Should Handle Remote Files Correctly +* @tc.type: FUNC +*/ +HWTEST_F(CopyFileTest, GetFileName002, TestSize.Level1) +{ + std::string remoteFile = "file://data/storage/el2/distributedfiles/103.png?networkid=xxx"; + auto result = UdmfCopyFile::GetInstance().GetFileName(remoteFile); + ASSERT_EQ(result, "103.png"); +} + +/** +* @tc.name: HandleRecord +* @tc.desc: HandleRecord Should Add To Processed Data For Non FileType +* @tc.type: FUNC +*/ +HWTEST_F(CopyFileTest, HandleRecord, TestSize.Level1) +{ + auto record = std::make_shared(); + auto helper = std::make_unique(); + UdmfCopyFile::CopyContext context(helper); + bool result = UdmfCopyFile::GetInstance().HandleRecord(record, context); + ASSERT_TRUE(result); + ASSERT_EQ(context.processedData->GetRecords().size(), 1); +} + +} // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/common/unittest/udmf_types_util_abnormal_test.cpp b/udmf/framework/common/unittest/udmf_types_util_abnormal_test.cpp index 78b7b4de..e8908130 100644 --- a/udmf/framework/common/unittest/udmf_types_util_abnormal_test.cpp +++ b/udmf/framework/common/unittest/udmf_types_util_abnormal_test.cpp @@ -66,7 +66,7 @@ void UdmfTypesUtilAbnormalTest::TearDown() /** * @tc.name: Marshalling001 -* @tc.desc: Abnrmal testcase of Marshalling, the return value of Writing() is nullptr +* @tc.desc: Abnrmal testcase of Marshalling, the return value of Writing() is false * @tc.type: FUNC */ HWTEST_F(UdmfTypesUtilAbnormalTest, Marshalling001, TestSize.Level1) @@ -91,7 +91,7 @@ HWTEST_F(UdmfTypesUtilAbnormalTest, Marshalling001, TestSize.Level1) /** * @tc.name: Marshalling002 -* @tc.desc: Abnrmal testcase of Marshalling, the return value of Writing() is nullptr +* @tc.desc: Abnrmal testcase of Marshalling, the return value of Writing() is false * @tc.type: FUNC */ HWTEST_F(UdmfTypesUtilAbnormalTest, Marshalling002, TestSize.Level1) @@ -107,23 +107,23 @@ HWTEST_F(UdmfTypesUtilAbnormalTest, Marshalling002, TestSize.Level1) /** * @tc.name: Marshalling003 -* @tc.desc: Abnrmal testcase of Marshalling, the return value of Reading() is nullptr +* @tc.desc: Abnrmal testcase of Marshalling, the return value of ReadTlv() is false * @tc.type: FUNC */ HWTEST_F(UdmfTypesUtilAbnormalTest, Marshalling003, TestSize.Level1) { LOG_INFO(UDMF_TEST, "Marshalling003 begin."); UnifiedData unifiedData; - std::vector input = {unifiedData}; + unifiedData.dataId_ = 1; MessageParcel parcel; - bool ret = ITypesUtil::Marshalling(input, parcel); + bool ret = ITypesUtil::Marshalling(unifiedData, parcel); EXPECT_FALSE(ret); LOG_INFO(UDMF_TEST, "Marshalling003 end."); } /** * @tc.name: Unmarshalling001 -* @tc.desc: Abnrmal testcase of Unmarshalling, the return value of Reading() is nullptr +* @tc.desc: Abnrmal testcase of Unmarshalling, the return value of ReadInt32() is 0 * @tc.type: FUNC */ HWTEST_F(UdmfTypesUtilAbnormalTest, Unmarshalling001, TestSize.Level1) @@ -136,4 +136,19 @@ HWTEST_F(UdmfTypesUtilAbnormalTest, Unmarshalling001, TestSize.Level1) EXPECT_FALSE(ret); LOG_INFO(UDMF_TEST, "Unmarshalling001 end."); } + +/** +* @tc.name: Unmarshalling002 +* @tc.desc: Abnrmal testcase of Unmarshalling, the return value of ReadInt32() is 0 +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilAbnormalTest, Unmarshalling002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Unmarshalling002 begin."); + UnifiedData output; + MessageParcel parcel; + bool ret = ITypesUtil::Unmarshalling(output, parcel); + EXPECT_FALSE(ret); + LOG_INFO(UDMF_TEST, "Unmarshalling002 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/common/unittest/udmf_types_util_mock_test.cpp b/udmf/framework/common/unittest/udmf_types_util_mock_test.cpp new file mode 100644 index 00000000..b3ee3bcf --- /dev/null +++ b/udmf/framework/common/unittest/udmf_types_util_mock_test.cpp @@ -0,0 +1,275 @@ +/* + * 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. + */ + +#define LOG_TAG "UdmfTypesUtilMockTest" + +#include +#include +#include + +#include "logger.h" +#include "udmf_types_util.h" +#include "unified_meta.h" +#include "text.h" +#include "plain_text.h" +#include "file.h" +#include "image.h" +#include "system_defined_record.h" +#include "system_defined_form.h" +#include "application_defined_record.h" +#include "unified_types.h" +#include "udmf_client.h" +#include "message_parcel_mock.h" + +using namespace testing; +using namespace testing::ext; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { +using namespace std; +static constexpr int32_t NORMAL_MAX_PARCEL_SIZE = 128 * 1024 * 1024; +class UdmfTypesUtilMockTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + static inline shared_ptr messageParcelMock_ = nullptr; +}; + +void UdmfTypesUtilMockTest::SetUpTestCase() +{ + messageParcelMock_ = make_shared(); + MessageParcelMock::messageParcel = messageParcelMock_; +} + +void UdmfTypesUtilMockTest::TearDownTestCase() +{ +} + +void UdmfTypesUtilMockTest::SetUp() +{ +} + +void UdmfTypesUtilMockTest::TearDown() +{ +} + +/** +* @tc.name: Unmarshalling001 +* @tc.desc: Unmarshalling UnifiedData +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling001, TestSize.Level1) +{ + std::vector unifiedDataList; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(10)) + .WillOnce(Return(10)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + EXPECT_CALL(*messageParcelMock_, ReadInt32()).WillOnce(Return(-1)) + .WillOnce(Return(UnifiedData::MAX_DATA_SIZE + 1)) + .WillOnce(Return(10)); + bool ret = ITypesUtil::Unmarshalling(unifiedDataList, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(unifiedDataList, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(unifiedDataList, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling002 +* @tc.desc: Unmarshalling UnifiedData +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling002, TestSize.Level1) +{ + UnifiedData unifiedData; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(10)) + .WillOnce(Return(10)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + EXPECT_CALL(*messageParcelMock_, ReadInt32()).WillOnce(Return(-1)) + .WillOnce(Return(UnifiedData::MAX_DATA_SIZE + 1)) + .WillOnce(Return(10)); + bool ret = ITypesUtil::Unmarshalling(unifiedData, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(unifiedData, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(unifiedData, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling003 +* @tc.desc: Unmarshalling summary +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling003, TestSize.Level1) +{ + Summary summary; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + bool ret = ITypesUtil::Unmarshalling(summary, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(summary, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling004 +* @tc.desc: Unmarshalling privilege +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling004, TestSize.Level1) +{ + Privilege privileges; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + bool ret = ITypesUtil::Unmarshalling(privileges, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(privileges, parcel); + EXPECT_FALSE(ret); +} + + +/** +* @tc.name: Unmarshalling005 +* @tc.desc: Unmarshalling CustomOption +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling005, TestSize.Level1) +{ + CustomOption option; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + bool ret = ITypesUtil::Unmarshalling(option, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(option, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling006 +* @tc.desc: Unmarshalling QueryOption +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling006, TestSize.Level1) +{ + QueryOption queryOption; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + bool ret = ITypesUtil::Unmarshalling(queryOption, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(queryOption, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling007 +* @tc.desc: Unmarshalling UDType +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling007, TestSize.Level1) +{ + UDType type; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + bool ret = ITypesUtil::Unmarshalling(type, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(type, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling008 +* @tc.desc: Unmarshalling Intention +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling008, TestSize.Level1) +{ + Intention intention; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + bool ret = ITypesUtil::Unmarshalling(intention, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(intention, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling009 +* @tc.desc: Unmarshalling Visibility +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling009, TestSize.Level1) +{ + Visibility visibility; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + bool ret = ITypesUtil::Unmarshalling(visibility, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(visibility, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling010 +* @tc.desc: Unmarshalling AsyncProcessInfo +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling010, TestSize.Level1) +{ + AsyncProcessInfo asyncProcessInfo; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + bool ret = ITypesUtil::Unmarshalling(asyncProcessInfo, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(asyncProcessInfo, parcel); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: Unmarshalling011 +* @tc.desc: Unmarshalling DataLoadInfo +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilMockTest, Unmarshalling011, TestSize.Level1) +{ + DataLoadInfo dataLoadInfo; + MessageParcel parcel; + EXPECT_CALL(*messageParcelMock_, GetDataSize()).WillOnce(Return(10)) + .WillOnce(Return(10)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)); + EXPECT_CALL(*messageParcelMock_, ReadInt32()).WillOnce(Return(-1)) + .WillOnce(Return(NORMAL_MAX_PARCEL_SIZE + 1)) + .WillOnce(Return(10)); + bool ret = ITypesUtil::Unmarshalling(dataLoadInfo, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(dataLoadInfo, parcel); + EXPECT_FALSE(ret); + ret = ITypesUtil::Unmarshalling(dataLoadInfo, parcel); + EXPECT_FALSE(ret); +} +} \ No newline at end of file diff --git a/udmf/framework/common/unittest/udmf_types_util_test.cpp b/udmf/framework/common/unittest/udmf_types_util_test.cpp index 86e94996..8d18ba05 100644 --- a/udmf/framework/common/unittest/udmf_types_util_test.cpp +++ b/udmf/framework/common/unittest/udmf_types_util_test.cpp @@ -299,4 +299,31 @@ HWTEST_F(UdmfTypesUtilTest, Unmarshalling009, TestSize.Level1) EXPECT_TRUE(ret); LOG_INFO(UDMF_TEST, "Unmarshalling009 end."); } + +/** +* @tc.name: Unmarshalling010 +* @tc.desc: Normal testcase of Unmarshalling +* @tc.type: FUNC +*/ +HWTEST_F(UdmfTypesUtilTest, Unmarshalling010, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Unmarshalling010 begin."); + DataLoadInfo input; + input.sequenceKey = "seq_2023"; + input.types = {"typeA", "typeB", "typeC"}; + input.recordCount = 1000; + + MessageParcel parcel; + ITypesUtil::Marshalling(input, parcel); + DataLoadInfo output; + bool ret = ITypesUtil::Unmarshalling(output, parcel); + EXPECT_TRUE(ret); + EXPECT_EQ(input.sequenceKey, output.sequenceKey); + EXPECT_EQ(input.recordCount, output.recordCount); + ASSERT_EQ(input.types.size(), output.types.size()); + for (auto &item : input.types) { + EXPECT_TRUE(output.types.find(item) != output.types.end()); + } + LOG_INFO(UDMF_TEST, "Unmarshalling010 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/common/unittest/utd_cfgs_checker_test.cpp b/udmf/framework/common/unittest/utd_cfgs_checker_test.cpp index 2a727441..e9fa7b93 100644 --- a/udmf/framework/common/unittest/utd_cfgs_checker_test.cpp +++ b/udmf/framework/common/unittest/utd_cfgs_checker_test.cpp @@ -269,7 +269,7 @@ HWTEST_F(UtdCfgsCheckerTest, CheckTypeDescriptors_005, TestSize.Level1) presetCfg2.belongingToTypes = {"com.demo.test.parent6"}; presetCfg2.mimeTypes = {"parent3/abc"}; std::vector presetCfgs = {presetCfg1, presetCfg2}; - + std::vector customCfgs = {tdc1, tdc3}; std::string bundleName("com.demo.test"); diff --git a/udmf/framework/common/utd_cfgs_checker.cpp b/udmf/framework/common/utd_cfgs_checker.cpp index 187b505f..b7eaa290 100644 --- a/udmf/framework/common/utd_cfgs_checker.cpp +++ b/udmf/framework/common/utd_cfgs_checker.cpp @@ -55,20 +55,32 @@ bool UtdCfgsChecker::CheckTypeDescriptors(CustomUtdCfgs &typeCfgs, const std::ve bool UtdCfgsChecker::CheckTypesFormat(CustomUtdCfgs &typeCfgs, const std::string &bundleName) { - for (auto declarationType: typeCfgs.first) { - if (!std::regex_match(declarationType.typeId, std::regex(bundleName + TYPE_ID_REGEX))) { - LOG_ERROR(UDMF_CLIENT, "Declaration typeId check failed, id: %{public}s, bundleName: %{public}s.", - declarationType.typeId.c_str(), bundleName.c_str()); - return false; +#ifndef CROSS_PLATFORM + try { +#endif + for (auto declarationType: typeCfgs.first) { + if (!std::regex_match(declarationType.typeId, std::regex(bundleName + TYPE_ID_REGEX))) { + LOG_ERROR(UDMF_CLIENT, "Declaration typeId check failed, bundleName: %{public}s", bundleName.c_str()); + return false; + } } - } - for (auto referenceTypes: typeCfgs.second) { - if (!std::regex_match(referenceTypes.typeId, std::regex(TYPE_ID_REGEX))) { - LOG_ERROR(UDMF_CLIENT, "Reference typeId check failed, id: %{public}s, bundleName: %{public}s.", - referenceTypes.typeId.c_str(), bundleName.c_str()); - return false; + for (auto referenceTypes: typeCfgs.second) { + if (!std::regex_match(referenceTypes.typeId, std::regex(TYPE_ID_REGEX))) { + LOG_ERROR(UDMF_CLIENT, "Reference typeId check failed, bundleName: %{public}s", bundleName.c_str()); + return false; + } } +#ifndef CROSS_PLATFORM + } catch (const std::regex_error& e) { + LOG_ERROR(UDMF_CLIENT, "catch regex_error, bundleName: %{public}s.", bundleName.c_str()); + return false; } +#endif + return CheckTypesOptions(typeCfgs, bundleName); +} + +bool UtdCfgsChecker::CheckTypesOptions(CustomUtdCfgs &typeCfgs, const std::string &bundleName) +{ std::vector inputTypeCfgs; if (!typeCfgs.first.empty()) { inputTypeCfgs.insert(inputTypeCfgs.end(), typeCfgs.first.begin(), typeCfgs.first.end()); @@ -79,8 +91,7 @@ bool UtdCfgsChecker::CheckTypesFormat(CustomUtdCfgs &typeCfgs, const std::string for (TypeDescriptorCfg &typeCfg : inputTypeCfgs) { for (std::string filenames : typeCfg.filenameExtensions) { if (filenames.size() <= 1 || filenames[0] != FILE_EXTENSION_PREFIX) { - LOG_ERROR(UDMF_CLIENT, "Extension not valid, extension: %{public}s, bundleName: %{public}s.", - filenames.c_str(), bundleName.c_str()); + LOG_ERROR(UDMF_CLIENT, "Extension not valid, bundleName: %{public}s.", bundleName.c_str()); return false; } } @@ -90,8 +101,7 @@ bool UtdCfgsChecker::CheckTypesFormat(CustomUtdCfgs &typeCfgs, const std::string } for (std::string mimeType : typeCfg.mimeTypes) { if (mimeType.empty()) { - LOG_ERROR(UDMF_CLIENT, "mimeType can not be an empty string, typeId: %{public}s.", - typeCfg.typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "mimeType can not be an empty string"); return false; } } @@ -148,13 +158,11 @@ bool UtdCfgsChecker::CheckBelongingToTypes(const std::vector for (auto &inputCfg : typeCfgs) { for (std::string belongingToType : inputCfg.belongingToTypes) { if (belongingToType.empty()) { - LOG_ERROR(UDMF_CLIENT, "BelongingToType can not be an empty string, typeId: %{public}s.", - inputCfg.typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "BelongingToType can not be an empty string"); return false; } if (inputCfg.typeId == belongingToType) { - LOG_ERROR(UDMF_CLIENT, "TypeId cannot equals belongingToType, typeId: %{public}s.", - inputCfg.typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "TypeId cannot equals belongingToType"); return false; } if (find(typeIds.begin(), typeIds.end(), belongingToType) == typeIds.end()) { diff --git a/udmf/framework/common/utd_cfgs_checker.h b/udmf/framework/common/utd_cfgs_checker.h index 13eab867..de81b62e 100644 --- a/udmf/framework/common/utd_cfgs_checker.h +++ b/udmf/framework/common/utd_cfgs_checker.h @@ -33,6 +33,7 @@ private: UtdCfgsChecker(const UtdCfgsChecker &obj) = delete; UtdCfgsChecker &operator=(const UtdCfgsChecker &obj) = delete; bool CheckTypesFormat(CustomUtdCfgs &typeCfgs, const std::string &bundleName); + bool CheckTypesOptions(CustomUtdCfgs &typeCfgs, const std::string &bundleName); bool CheckTypesRelation(CustomUtdCfgs &typeCfgs, const std::vector &presetCfgs, const std::vector &customCfgs); bool CanConstructDAG(CustomUtdCfgs &typeCfgs, const std::vector &presetCfgs, diff --git a/udmf/framework/common/utd_common.h b/udmf/framework/common/utd_common.h index ac39da62..6322bd44 100644 --- a/udmf/framework/common/utd_common.h +++ b/udmf/framework/common/utd_common.h @@ -17,6 +17,7 @@ #include #include #include +#include #include "error_code.h" namespace OHOS { @@ -25,14 +26,14 @@ struct TypeDescriptorCfg; using CustomUtdCfgs = std::pair, std::vector>; struct TypeDescriptorCfg { std::string typeId; - std::vector belongingToTypes; - std::vector filenameExtensions; - std::vector mimeTypes; + std::vector belongingToTypes {}; + std::vector filenameExtensions {}; + std::vector mimeTypes {}; std::string description; std::string referenceURL; std::string iconFile; std::string ownerBundle; - std::set installerBundles; + std::set installerBundles {}; bool operator==(const TypeDescriptorCfg &typeDescriptor) const { @@ -40,8 +41,13 @@ struct TypeDescriptorCfg { } }; +struct UtdFileInfo { + uint64_t size = 0; + int64_t lastTime = 0; +}; + // UTD data category -constexpr const char* UTD_CUSTOM_DECLAEEARION = "UniformDataTypeDeclarations"; +constexpr const char* UTD_CUSTOM_DECLARATION = "UniformDataTypeDeclarations"; constexpr const char* UTD_CUSTOM_REFERENCE = "ReferenceUniformDataTypeDeclarations"; constexpr const char* UTD_CUSTOM = "CustomUTDs"; diff --git a/udmf/framework/common/utd_graph.cpp b/udmf/framework/common/utd_graph.cpp index 4203d9dc..3382c524 100644 --- a/udmf/framework/common/utd_graph.cpp +++ b/udmf/framework/common/utd_graph.cpp @@ -14,8 +14,6 @@ */ #define LOG_TAG "UtdGraph" #include "utd_graph.h" - -#include #include "logger.h" namespace OHOS { namespace UDMF { @@ -60,11 +58,11 @@ void UtdGraph::InitUtdGraph(const std::vector &descriptorCfgs bool UtdGraph::IsLowerLevelType(const std::string &lowerLevelType, const std::string &heigitLevelType) { + std::unique_lock lock(graphMutex_); if (graph_ == nullptr) { LOG_ERROR(UDMF_CLIENT, "graph_ is nullptr."); return false; } - std::unique_lock lock(graphMutex_); bool isFind = false; int32_t start = graph_->GetIndex(lowerLevelType); int32_t end = graph_->GetIndex(heigitLevelType); @@ -91,7 +89,7 @@ std::unique_ptr UtdGraph::ConstructNewGraph(const std::vector(descriptorsNum, typeIdIndex); - + for (const auto &descriptorCfg : descriptorCfgs) { std::vector belongsTo = descriptorCfg.belongingToTypes; for (auto belongsToType : belongsTo) { diff --git a/udmf/framework/common/utd_graph.h b/udmf/framework/common/utd_graph.h index 0c185849..7178f47d 100644 --- a/udmf/framework/common/utd_graph.h +++ b/udmf/framework/common/utd_graph.h @@ -18,7 +18,6 @@ #include #include -#include #include #include #include diff --git a/udmf/framework/innerkitsimpl/client/udmf_async_client.cpp b/udmf/framework/innerkitsimpl/client/udmf_async_client.cpp index d7c1e65e..c6de1b6f 100644 --- a/udmf/framework/innerkitsimpl/client/udmf_async_client.cpp +++ b/udmf/framework/innerkitsimpl/client/udmf_async_client.cpp @@ -16,12 +16,17 @@ #include "udmf_async_client.h" +#include #include "dataobs_mgr_client.h" #include "logger.h" #include "plain_text.h" #include "progress_callback.h" #include "udmf_client.h" #include "udmf_copy_file.h" +#ifndef IOS_PLATFORM +#include "udmf_executor.h" +#endif +#include "udmf_notifier_stub.h" #include "udmf_service_client.h" namespace OHOS::UDMF { @@ -30,8 +35,11 @@ static constexpr size_t MIN_THREADS = 0; static constexpr int32_t START_ABILITY_INTERVAL = 500; static constexpr int32_t READ_PROGRESS_INTERVAL = 100; +static constexpr int32_t UPDATA_TIMESTAMP_INTERVAL = 1000; static constexpr int32_t SYNC_INTERVAL = 200; static constexpr int32_t MAX_SYNC_TIMES = 14; +static constexpr uint64_t SEC_TO_MILLISEC = 1000; +static constexpr uint64_t MICROSEC_TO_MILLISEC = 1000; static std::unordered_map STATUS_MAP = { { E_INVALID_PARAMETERS, ListenerStatus::INVALID_PARAMETERS }, @@ -47,10 +55,10 @@ static constexpr int32_t PROGRESS_SYNC_FINSHED = 10; static constexpr int32_t PROGRESS_GET_DATA_FINISHED = 20; static constexpr int32_t PROGRESS_ALL_FINISHED = 100; -#ifdef IOS_PLATFORM -UdmfAsyncClient::UdmfAsyncClient() {} -#else -UdmfAsyncClient::UdmfAsyncClient() : executor_(MAX_THREADS, MIN_THREADS) {} +UdmfAsyncClient::UdmfAsyncClient() = default; + +#ifndef IOS_PLATFORM +static UdmfExecutor udmfExecutor(MAX_THREADS, MIN_THREADS); #endif UdmfAsyncClient &UdmfAsyncClient::GetInstance() @@ -69,14 +77,18 @@ Status UdmfAsyncClient::StartAsyncDataRetrieval(const GetDataParams ¶ms) if (status != E_OK) { return status; } + if (asyncHelperMap_.find(params.query.key) == asyncHelperMap_.end()) { + LOG_ERROR(UDMF_CLIENT, "RegisterAsyncHelper failed, key=%{public}s", params.query.key.c_str()); + return E_ERROR; + } auto &asyncHelper = asyncHelperMap_.at(params.query.key); if (params.progressIndicator == ProgressIndicator::DEFAULT) { asyncHelper->progressQueue.SetClearable(false); - asyncHelper->invokeHapTask = executor_.Schedule(std::chrono::milliseconds(START_ABILITY_INTERVAL), + asyncHelper->invokeHapTask = udmfExecutor.Schedule(std::chrono::milliseconds(START_ABILITY_INTERVAL), (std::bind(&UdmfAsyncClient::InvokeHapTask, this, params.query.key))); } - asyncHelper->getDataTask = executor_.Execute(std::bind(&UdmfAsyncClient::GetDataTask, this, params.query)); - asyncHelper->progressTask = executor_.Execute(std::bind(&UdmfAsyncClient::ProgressTask, this, params.query.key)); + asyncHelper->getDataTask = udmfExecutor.Execute(std::bind(&UdmfAsyncClient::GetDataTask, this, params.query)); + asyncHelper->progressTask = udmfExecutor.Execute(std::bind(&UdmfAsyncClient::ProgressTask, this, params.query.key)); #endif return E_OK; } @@ -119,6 +131,7 @@ Status UdmfAsyncClient::ProgressTask(const std::string &businessUdKey) return status; } } + auto lastUpdateTime = std::chrono::steady_clock::now(); while (asyncHelper->lastProgress >= PROGRESS_INIT && asyncHelper->lastProgress < PROGRESS_ALL_FINISHED) { auto pair = asyncHelper->progressQueue.Poll(); if (!pair.first) { @@ -126,13 +139,18 @@ Status UdmfAsyncClient::ProgressTask(const std::string &businessUdKey) continue; } auto progressInfo = pair.second; - if (progressInfo->progress >= PROGRESS_INIT && progressInfo->progress <= asyncHelper->lastProgress) { + if (progressInfo->progress >= PROGRESS_INIT && progressInfo->progress < asyncHelper->lastProgress) { continue; } - asyncHelper->lastProgress = progressInfo->progress; if (asyncHelper->progressIndicator == ProgressIndicator::DEFAULT) { - UpdateProgressData(asyncHelper->processKey, *progressInfo); + auto now = std::chrono::steady_clock::now(); + auto elapsedMs = std::chrono::duration_cast(now - lastUpdateTime).count(); + if (progressInfo->progress != asyncHelper->lastProgress || elapsedMs > UPDATA_TIMESTAMP_INTERVAL) { + UpdateProgressData(asyncHelper->processKey, *progressInfo); + lastUpdateTime = now; + } } + asyncHelper->lastProgress = progressInfo->progress; } Clear(businessUdKey); return E_OK; @@ -162,7 +180,12 @@ Status UdmfAsyncClient::InvokeHapTask(const std::string &businessUdKey) Clear(businessUdKey); return E_ERROR; } - sptr callback = new ProgressSignalCallback(); + sptr callback = new (std::nothrow) ProgressSignalCallback(); + if (callback == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Create ProgressSignalCallback failed"); + Clear(businessUdKey); + return E_ERROR; + } auto obsMgrClient = AAFwk::DataObsMgrClient::GetInstance(); if (obsMgrClient == nullptr) { LOG_ERROR(UDMF_CLIENT, "Get DataObsMgrClient failed"); @@ -193,6 +216,7 @@ Status UdmfAsyncClient::RegisterAsyncHelper(const GetDataParams ¶ms) asyncHelper->progressIndicator = params.progressIndicator; asyncHelper->fileConflictOptions = params.fileConflictOptions; asyncHelper->destUri = params.destUri; + asyncHelper->acceptableInfo = params.acceptableInfo; asyncHelperMap_.insert_or_assign(params.query.key, std::move(asyncHelper)); return E_OK; } @@ -233,7 +257,7 @@ Status UdmfAsyncClient::CheckSync(std::unique_ptr &asyncHelper, con return E_SYNC_FAILED; } (asyncHelper->sycnRetryTime)++; - asyncHelper->getDataTask = executor_.Schedule(std::chrono::milliseconds(SYNC_INTERVAL), + asyncHelper->getDataTask = udmfExecutor.Schedule(std::chrono::milliseconds(SYNC_INTERVAL), std::bind(&UdmfAsyncClient::GetDataTask, this, query)); #endif return E_OK; @@ -242,7 +266,23 @@ Status UdmfAsyncClient::CheckSync(std::unique_ptr &asyncHelper, con Status UdmfAsyncClient::GetDataFromDB(std::unique_ptr &asyncHelper, const QueryOption &query) { auto &data = *(asyncHelper->data); - auto status = static_cast(UdmfServiceClient::GetInstance()->GetData(query, data)); + auto delayDataCallback = [this](const std::string &key, const UnifiedData &unifiedData) { + if (asyncHelperMap_.find(key) == asyncHelperMap_.end()) { + LOG_ERROR(UDMF_CLIENT, "No task exist, key=%{public}s", key.c_str()); + return; + } + auto &asyncHelper = asyncHelperMap_.at(key); + *(asyncHelper->data) = unifiedData; + UdmfAsyncClient::GetInstance().ProcessUnifiedData(asyncHelper); + }; + sptr iUdmfNotifier = new (std::nothrow) DelayDataCallbackClient(delayDataCallback); + if (iUdmfNotifier == nullptr) { + LOG_ERROR(UDMF_CLIENT, "IUdmfNotifier unavailable"); + return E_ERROR; + } + std::shared_ptr dataPtr = std::make_shared(); + auto status = static_cast(UdmfClient::GetInstance().GetDataIfAvailable(query.key, + asyncHelper->acceptableInfo, iUdmfNotifier, dataPtr)); if (status != E_OK) { LOG_ERROR(UDMF_CLIENT, "GetData error, status = %{public}d", status); ProgressInfo progressInfo = { @@ -252,6 +292,11 @@ Status UdmfAsyncClient::GetDataFromDB(std::unique_ptr &asyncHelper, CallProgress(asyncHelper, progressInfo, nullptr); return status; } + if (dataPtr->IsEmpty()) { + LOG_INFO(UDMF_CLIENT, "Wait delay data"); + return E_OK; + } + data = *dataPtr; return ProcessUnifiedData(asyncHelper); } @@ -274,6 +319,7 @@ Status UdmfAsyncClient::SetProgressData(const std::string &businessUdKey) auto obj = std::make_shared(); auto progressRecord = std::make_shared(UDType::PLAIN_TEXT, obj); progressRecord->SetContent(std::to_string(PROGRESS_INIT)); + progressRecord->SetAbstract(std::to_string(GetCurrentTimeMillis())); UnifiedData progressData; progressData.AddRecord(progressRecord); auto status = serviceClient->SetData(cusomOption, progressData, progressKey); @@ -304,6 +350,7 @@ Status UdmfAsyncClient::UpdateProgressData(const std::string &progressUdKey, con } else { progressRecord->SetContent(std::to_string(progressInfo.progress)); } + progressRecord->SetAbstract(std::to_string(GetCurrentTimeMillis())); UnifiedData progressData; progressData.AddRecord(progressRecord); auto status = serviceClient->UpdateData(queryOption, progressData); @@ -365,10 +412,10 @@ Status UdmfAsyncClient::Clear(const std::string &businessUdKey) return E_OK; } if (asyncHelper->invokeHapTask != ExecutorPool::INVALID_TASK_ID) { - executor_.Remove(asyncHelper->invokeHapTask); + udmfExecutor.Remove(asyncHelper->invokeHapTask); } - executor_.Remove(asyncHelper->getDataTask); - executor_.Remove(asyncHelper->progressTask); + udmfExecutor.Remove(asyncHelper->getDataTask); + udmfExecutor.Remove(asyncHelper->progressTask); asyncHelperMap_.erase(businessUdKey); UdmfServiceClient::GetInstance()->ClearAsynProcessByKey(businessUdKey); LOG_INFO(UDMF_CLIENT, "Clear task success, key = %{public}s", businessUdKey.c_str()); @@ -408,4 +455,17 @@ bool UdmfAsyncClient::IsParamValid(const GetDataParams &params) } return true; } + +void UdmfAsyncClient::PushTaskToExecutor(UdmfTask task) +{ + udmfExecutor.Execute(std::move(task)); +} + +uint64_t UdmfAsyncClient::GetCurrentTimeMillis() +{ + struct timeval tv = { 0, 0 }; + gettimeofday(&tv, nullptr); + return (static_cast<uint64_t>(tv.tv_sec) * SEC_TO_MILLISEC + + static_cast<uint64_t>(tv.tv_usec) / MICROSEC_TO_MILLISEC); +} } // namespace OHOS::UDMF diff --git a/udmf/framework/innerkitsimpl/client/udmf_client.cpp b/udmf/framework/innerkitsimpl/client/udmf_client.cpp index dbaa7d3e..a0644471 100644 --- a/udmf/framework/innerkitsimpl/client/udmf_client.cpp +++ b/udmf/framework/innerkitsimpl/client/udmf_client.cpp @@ -24,12 +24,19 @@ #include "udmf_utils.h" #include "accesstoken_kit.h" #include "ipc_skeleton.h" +#include "udmf_notifier_stub.h" #include "unified_data_helper.h" #include "unified_html_record_process.h" +#include "utd_client.h" namespace OHOS { namespace UDMF { constexpr const char *TAG = "UdmfClient::"; +constexpr const char *BUNDLE_IN_APP = "udmf.inapp.data"; +static constexpr int KEY_LEN = 32; +static constexpr int FILE_TYPES_MAX_SIZE = 1024; +static const std::initializer_list<std::string_view> FILE_TOP_TYPES = { "general.file-uri", "general.file" }; +static constexpr int WITH_SUMMARY_FORMAT_VER = 1; using namespace OHOS::DistributedDataDfx; using namespace RadarReporter; UdmfClient &UdmfClient::GetInstance() @@ -38,12 +45,28 @@ UdmfClient &UdmfClient::GetInstance() return instance; } +void UdmfClient::ProcessDragIfInApp(UnifiedData &unifiedData, std::string &intentionDrag, std::string &key) +{ + std::string bundleName = BUNDLE_IN_APP; + UnifiedKey udKey = UnifiedKey(intentionDrag, bundleName, UTILS::GenerateId()); + key = udKey.GetUnifiedKey(); + dataCache_.Clear(); + dataCache_.Insert(key, unifiedData); + LOG_INFO(UDMF_CLIENT, "SetData in app success, bundleName:%{public}s.", bundleName.c_str()); + RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), + BizScene::SET_DATA, SetDataStage::SET_DATA_END, StageRes::SUCCESS, BizState::DFX_END); +} + Status UdmfClient::SetData(CustomOption &option, UnifiedData &unifiedData, std::string &key) { DdsTrace trace( std::string(TAG) + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), BizScene::SET_DATA, SetDataStage::SET_DATA_BEGIN, StageRes::IDLE, BizState::DFX_BEGIN); + if (!UnifiedDataUtils::IsValidIntention(option.intention)) { + LOG_ERROR(UDMF_SERVICE, "Invalid intention"); + return E_INVALID_PARAMETERS; + } auto service = UdmfServiceClient::GetInstance(); if (service == nullptr) { LOG_ERROR(UDMF_CLIENT, "Service unavailable"); @@ -55,23 +78,16 @@ Status UdmfClient::SetData(CustomOption &option, UnifiedData &unifiedData, std:: BizScene::SET_DATA, SetDataStage::SET_DATA_BEGIN, StageRes::SUCCESS); if (option.intention == UD_INTENTION_DRAG) { ShareOptions shareOption = SHARE_OPTIONS_BUTT; - auto status = GetAppShareOption(UD_INTENTION_MAP.at(option.intention), shareOption); + auto intentionDrag = UD_INTENTION_MAP.at(option.intention); + auto status = GetAppShareOption(intentionDrag, shareOption); if (status != E_NOT_FOUND && status != E_OK) { RadarReporterAdapter::ReportFail(std::string(__FUNCTION__), BizScene::SET_DATA, SetDataStage::SET_DATA_END, StageRes::FAILED, status, BizState::DFX_END); - LOG_ERROR(UDMF_CLIENT, "get appShareOption fail, intention:%{public}s", - UD_INTENTION_MAP.at(option.intention).c_str()); + LOG_ERROR(UDMF_CLIENT, "get appShareOption fail, intention:%{public}s", intentionDrag.c_str()); return static_cast<Status>(status); } if (shareOption == ShareOptions::IN_APP) { - std::string bundleName = "udmf.inapp.data"; - UnifiedKey udKey = UnifiedKey(UD_INTENTION_MAP.at(option.intention), bundleName, UTILS::GenerateId()); - key = udKey.GetUnifiedKey(); - dataCache_.Clear(); - dataCache_.Insert(key, unifiedData); - LOG_INFO(UDMF_CLIENT, "SetData in app success, bundleName:%{public}s.", bundleName.c_str()); - RadarReporterAdapter::ReportNormal(std::string(__FUNCTION__), - BizScene::SET_DATA, SetDataStage::SET_DATA_END, StageRes::SUCCESS, BizState::DFX_END); + ProcessDragIfInApp(unifiedData, intentionDrag, key); return E_OK; } if (unifiedData.HasType(UtdUtils::GetUtdIdFromUtdEnum(UDType::HTML))) { @@ -324,5 +340,150 @@ Status UdmfClient::GetDataFromCache(const QueryOption &query, UnifiedData &unifi return E_NOT_FOUND; } +Status UdmfClient::GetParentType(Summary &oldSummary, Summary &newSummary) +{ + std::map<std::string, int64_t> tmpSummary; + for (const auto &[type, size] : oldSummary.summary) { + std::string fileType = UnifiedDataUtils::GetBelongsToFileType(type); + if (fileType.empty()) { + tmpSummary[type] = size; + continue; + } + if (tmpSummary.find(fileType) != tmpSummary.end()) { + tmpSummary[fileType] += size; + } else { + tmpSummary[fileType] = size; + } + } + newSummary.summary = std::move(tmpSummary); + newSummary.totalSize = oldSummary.totalSize; + return E_OK; +} + +Status UdmfClient::SetDelayInfo(const DataLoadParams &dataLoadParams, std::string &key) +{ + if (dataLoadParams.dataLoadInfo.sequenceKey.length() != KEY_LEN) { + LOG_ERROR(UDMF_CLIENT, "Invalid key=%{public}s", dataLoadParams.dataLoadInfo.sequenceKey.c_str()); + return E_INVALID_PARAMETERS; + } + auto service = UdmfServiceClient::GetInstance(); + if (service == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Service unavailable"); + return E_IPC; + } + sptr<IRemoteObject> iUdmfNotifier = new (std::nothrow) UdmfNotifierClient(dataLoadParams.loadHandler); + if (iUdmfNotifier == nullptr) { + LOG_ERROR(UDMF_CLIENT, "IUdmfNotifier unavailable"); + return E_IPC; + } + auto ret = service->SetDelayInfo(dataLoadParams.dataLoadInfo, iUdmfNotifier, key); + if (ret != E_OK) { + LOG_ERROR(UDMF_CLIENT, "Failed, ret = %{public}d, udkey = %{public}s.", ret, key.c_str()); + } + return static_cast<Status>(ret); +} + +Status UdmfClient::PushDelayData(const std::string &key, UnifiedData &unifiedData) +{ + if (key.empty()) { + LOG_ERROR(UDMF_CLIENT, "Empty key"); + return E_INVALID_PARAMETERS; + } + auto service = UdmfServiceClient::GetInstance(); + if (service == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Service unavailable"); + return E_IPC; + } + auto status = service->PushDelayData(key, unifiedData); + if (status != E_OK) { + LOG_ERROR(UDMF_CLIENT, "Failed, ret = %{public}d", status); + } + return static_cast<Status>(status); +} + +Status UdmfClient::GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr<IRemoteObject> iUdmfNotifier, std::shared_ptr<UnifiedData> unifiedData) +{ + if (key.empty() || iUdmfNotifier == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Empty key or notifier"); + return E_INVALID_PARAMETERS; + } + auto service = UdmfServiceClient::GetInstance(); + if (service == nullptr) { + LOG_ERROR(UDMF_CLIENT, "Service unavailable"); + return E_IPC; + } + int32_t ret = service->GetDataIfAvailable(key, dataLoadInfo, iUdmfNotifier, unifiedData); + if (ret != E_OK) { + LOG_ERROR(UDMF_CLIENT, "Failed! ret = %{public}d", ret); + return static_cast<Status>(ret); + } + return E_OK; +} + +std::string UdmfClient::GetBundleNameByUdKey(const std::string &key) +{ + UnifiedKey udkey(key); + if (!udkey.IsValid()) { + LOG_ERROR(UDMF_CLIENT, "IsValid udkey:%{public}s", key.c_str()); + return ""; + } + return udkey.bundleName; +} + +bool UdmfClient::IsAppropriateType(const Summary &summary, const std::vector<std::string> &allowTypes) +{ + for (const auto &allowType : allowTypes) { + if (summary.summary.find(allowType) != summary.summary.end() + || summary.specificSummary.find(allowType) != summary.specificSummary.end()) { + return true; + } + } + if (summary.version < WITH_SUMMARY_FORMAT_VER) { + return false; + } + // when the summary format version is greater than 0, we need to check the file type + return CheckFileUtdType(summary, allowTypes); +} + +bool UdmfClient::CheckFileUtdType(const Summary &summary, const std::vector<std::string> &allowTypes) +{ + std::set<std::string> fileUtdTypes; + for (const auto &[type, formats] : summary.summaryFormat) { + if (!type.empty() && std::find(formats.begin(), formats.end(), Uds_Type::UDS_FILE_URI) != formats.end()) { + fileUtdTypes.emplace(type); + } + if (fileUtdTypes.size() > FILE_TYPES_MAX_SIZE) { + LOG_WARN(UDMF_CLIENT, "Exceeding the maximum size"); + break; + } + } + for (const auto &type : allowTypes) { + if (std::find(FILE_TOP_TYPES.begin(), FILE_TOP_TYPES.end(), type) != FILE_TOP_TYPES.end()) { + // If the supported file type falls into, return true when the file is included + if (!fileUtdTypes.empty()) { + return true; + } + continue; + } + if (!UnifiedDataUtils::IsFilterFileType(type)) { + continue; + } + for (const auto &fileUtdType : fileUtdTypes) { + std::shared_ptr<TypeDescriptor> descriptor; + UtdClient::GetInstance().GetTypeDescriptor(fileUtdType, descriptor); + if (descriptor == nullptr) { + continue; + } + bool isSpecificType = false; + descriptor->BelongsTo(type, isSpecificType); + if (isSpecificType) { + return true; + } + } + } + LOG_INFO(UDMF_CLIENT, "Not appropriate type"); + return false; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/client/utd_client.cpp b/udmf/framework/innerkitsimpl/client/utd_client.cpp index f4006efe..234b545a 100644 --- a/udmf/framework/innerkitsimpl/client/utd_client.cpp +++ b/udmf/framework/innerkitsimpl/client/utd_client.cpp @@ -15,6 +15,8 @@ #define LOG_TAG "UtdClient" #include <regex> #include <thread> +#include <chrono> +#include <cinttypes> #include "utd_client.h" #include "logger.h" #include "utd_graph.h" @@ -25,16 +27,8 @@ namespace OHOS { namespace UDMF { constexpr const int MAX_UTD_LENGTH = 256; -constexpr const int MAX_FILE_EXTENSION_LENGTH = 14; -constexpr const char *DEFAULT_ANONYMOUS = "******"; -std::string UtdClient::Anonymous(const std::string &fileExtension) -{ - if (fileExtension.length() <= MAX_FILE_EXTENSION_LENGTH) { - return fileExtension; - } - - return (fileExtension.substr(0, MAX_FILE_EXTENSION_LENGTH) + DEFAULT_ANONYMOUS); -} +constexpr const int64_t RELOAD_INTERVAL = 10; +using namespace std::chrono; UtdClient::UtdClient() { @@ -62,21 +56,27 @@ UtdClient &UtdClient::GetInstance() bool UtdClient::Init() { bool result = true; + int32_t userId = DEFAULT_USER_ID; + bool isHap = IsHapTokenType(); + if (!isHap && GetCurrentActiveUserId(userId) != Status::E_OK) { + result = false; + } + + std::vector<TypeDescriptorCfg> customUtd; + { + std::lock_guard<std::mutex> lock(customUtdMutex_); + utdFileInfo_ = CustomUtdStore::GetInstance().GetCustomUtdInfo(isHap, userId); + customUtd = CustomUtdStore::GetInstance().GetCustomUtd(isHap, userId); + lastLoadTime_ = duration_cast<seconds>(system_clock::now().time_since_epoch()).count(); + } + std::unique_lock<std::shared_mutex> lock(utdMutex_); descriptorCfgs_ = PresetTypeDescriptors::GetInstance().GetPresetTypes(); - std::vector<TypeDescriptorCfg> customTypes; - if (IsHapTokenType()) { - customTypes = CustomUtdStore::GetInstance().GetHapTypeCfgs(); - } else { - int32_t userId = DEFAULT_USER_ID; - if (GetCurrentActiveUserId(userId) != Status::E_OK) { - result = false; - } - customTypes = CustomUtdStore::GetInstance().GetTypeCfgs(userId); - } - LOG_INFO(UDMF_CLIENT, "get customUtd, size:%{public}zu", customTypes.size()); - if (!customTypes.empty()) { - descriptorCfgs_.insert(descriptorCfgs_.end(), customTypes.begin(), customTypes.end()); + + LOG_INFO(UDMF_CLIENT, "get customUtd size:%{public}zu, file size:%{public}" PRIu64, + customUtd.size(), utdFileInfo_.size); + if (!customUtd.empty()) { + descriptorCfgs_.insert(descriptorCfgs_.end(), customUtd.begin(), customUtd.end()); } UtdGraph::GetInstance().InitUtdGraph(descriptorCfgs_); return result; @@ -89,15 +89,16 @@ Status UtdClient::GetTypeDescriptor(const std::string &typeId, std::shared_ptr<T for (const auto &utdTypeCfg : descriptorCfgs_) { if (utdTypeCfg.typeId == typeId) { descriptor = std::make_shared<TypeDescriptor>(utdTypeCfg); - LOG_DEBUG(UDMF_CLIENT, "get descriptor success. %{public}s ", typeId.c_str()); return Status::E_OK; } } } if (typeId.find(FLEXIBLE_TYPE_FLAG) != typeId.npos) { - LOG_DEBUG(UDMF_CLIENT, "get flexible descriptor. %{public}s ", typeId.c_str()); return GetFlexibleTypeDescriptor(typeId, descriptor); } + if (TryReloadCustomUtd()) { + return GetTypeDescriptor(typeId, descriptor); + } return Status::E_OK; } @@ -131,7 +132,7 @@ Status UtdClient::GetFlexibleTypeDescriptor(const std::string &typeId, std::shar { TypeDescriptorCfg flexibleTypeDescriptorCfg; if (!FlexibleType::ParseFlexibleUtd(typeId, flexibleTypeDescriptorCfg)) { - LOG_ERROR(UDMF_CLIENT, "ParseFlexibleUtd failed, invalid typeId: %{public}s", typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "ParseFlexibleUtd failed, invalid typeId"); return Status::E_ERROR; } descriptor = std::make_shared<TypeDescriptor>(flexibleTypeDescriptorCfg); @@ -144,8 +145,10 @@ Status UtdClient::GetUniformDataTypeByFilenameExtension(const std::string &fileE std::string lowerFileExtension = fileExtension; std::transform(lowerFileExtension.begin(), lowerFileExtension.end(), lowerFileExtension.begin(), ::tolower); if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { - LOG_ERROR(UDMF_CLIENT, "invalid belongsTo. fileExtension:%{public}s, belongsTo:%{public}s ", - fileExtension.c_str(), belongsTo.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo."); + if (TryReloadCustomUtd()) { + return GetUniformDataTypeByFilenameExtension(fileExtension, typeId, belongsTo); + } return Status::E_INVALID_PARAMETERS; } { @@ -154,7 +157,7 @@ Status UtdClient::GetUniformDataTypeByFilenameExtension(const std::string &fileE for (const auto &utdTypeCfg : descriptorCfgs_) { for (auto fileEx : utdTypeCfg.filenameExtensions) { std::transform(fileEx.begin(), fileEx.end(), fileEx.begin(), ::tolower); - if (fileEx == lowerFileExtension) { + if (fileEx == lowerFileExtension && IsBelongingType(belongsTo, utdTypeCfg.typeId)) { typeId = utdTypeCfg.typeId; found = true; break; @@ -165,16 +168,12 @@ Status UtdClient::GetUniformDataTypeByFilenameExtension(const std::string &fileE } } } - // the find typeId is not belongsTo to the belongsTo. - if (!typeId.empty() && belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && - !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { - typeId = ""; + if (typeId.empty() && TryReloadCustomUtd()) { + return GetUniformDataTypeByFilenameExtension(fileExtension, typeId, belongsTo); } - if (typeId.empty()) { if (!IsValidFileExtension(lowerFileExtension)) { - LOG_ERROR(UDMF_CLIENT, "invalid fileExtension. fileExtension:%{public}s, belongsTo:%{public}s ", - fileExtension.c_str(), belongsTo.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid fileExtension."); return Status::E_INVALID_PARAMETERS; } typeId = FlexibleType::GenFlexibleUtd("", lowerFileExtension, belongsTo); @@ -186,13 +185,14 @@ Status UtdClient::GetUniformDataTypesByFilenameExtension(const std::string &file std::vector<std::string> &typeIds, const std::string &belongsTo) { if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { - LOG_ERROR(UDMF_CLIENT, "invalid belongsTo. fileExtension:%{public}s, belongsTo:%{public}s ", - fileExtension.c_str(), belongsTo.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo."); + if (TryReloadCustomUtd()) { + return GetUniformDataTypesByFilenameExtension(fileExtension, typeIds, belongsTo); + } return Status::E_INVALID_PARAMETERS; } if (!IsValidFileExtension(fileExtension)) { - LOG_ERROR(UDMF_CLIENT, "invalid fileExtension. fileExtension:%{public}s, belongsTo:%{public}s ", - Anonymous(fileExtension).c_str(), belongsTo.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid fileExtension."); return Status::E_INVALID_PARAMETERS; } @@ -211,11 +211,13 @@ Status UtdClient::GetUniformDataTypesByFilenameExtension(const std::string &file } } } + if (typeIdsInCfg.empty() && TryReloadCustomUtd()) { + return GetUniformDataTypesByFilenameExtension(fileExtension, typeIds, belongsTo); + } typeIds.clear(); for (const auto &typeId : typeIdsInCfg) { // the find typeId is not belongsTo to the belongsTo. - if (belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && - !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { + if (!IsBelongingType(belongsTo, typeId)) { continue; } typeIds.emplace_back(typeId); @@ -232,20 +234,16 @@ Status UtdClient::GetUniformDataTypeByMIMEType(const std::string &mimeType, std: std::string lowerMimeType = mimeType; std::transform(lowerMimeType.begin(), lowerMimeType.end(), lowerMimeType.begin(), ::tolower); if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { - LOG_ERROR(UDMF_CLIENT, "invalid belongsTo. mimeType:%{public}s, belongsTo:%{public}s ", - mimeType.c_str(), belongsTo.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo."); + if (TryReloadCustomUtd()) { + return GetUniformDataTypeByMIMEType(mimeType, typeId, belongsTo); + } return Status::E_INVALID_PARAMETERS; } - typeId = GetTypeIdFromCfg(lowerMimeType); - // the find typeId is not belongsTo to the belongsTo. - if (!typeId.empty() && belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && - !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { - typeId = ""; - } + typeId = GetTypeIdFromCfg(lowerMimeType, belongsTo); if (typeId.empty()) { if (!IsValidMimeType(mimeType)) { - LOG_ERROR(UDMF_CLIENT, "invalid mimeType. mimeType:%{public}s, belongsTo:%{public}s ", - mimeType.c_str(), belongsTo.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid mimeType."); return Status::E_INVALID_PARAMETERS; } typeId = FlexibleType::GenFlexibleUtd(lowerMimeType, "", belongsTo); @@ -253,29 +251,44 @@ Status UtdClient::GetUniformDataTypeByMIMEType(const std::string &mimeType, std: return Status::E_OK; } -std::string UtdClient::GetTypeIdFromCfg(const std::string &mimeType) +std::string UtdClient::GetTypeIdFromCfg(const std::string &mimeType, const std::string &belongsTo) { - std::shared_lock<std::shared_mutex> guard(utdMutex_); - for (const auto &utdTypeCfg : descriptorCfgs_) { - for (auto mime : utdTypeCfg.mimeTypes) { - std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); - if (mime == mimeType) { - return utdTypeCfg.typeId; + if (mimeType.empty()) { + return ""; + } + { + std::shared_lock<std::shared_mutex> guard(utdMutex_); + for (const auto &utdTypeCfg : descriptorCfgs_) { + for (auto mime : utdTypeCfg.mimeTypes) { + std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); + if (mime == mimeType && IsBelongingType(belongsTo, utdTypeCfg.typeId)) { + return utdTypeCfg.typeId; + } } } } - if (mimeType.empty() || mimeType.back() != '*') { + if (mimeType.back() != '*') { + if (TryReloadCustomUtd()) { + return GetTypeIdFromCfg(mimeType, belongsTo); + } return ""; } - std::string prefixType = mimeType.substr(0, mimeType.length() - 1); - for (const auto &utdTypeCfg : descriptorCfgs_) { - for (auto mime : utdTypeCfg.mimeTypes) { - std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); - if (mime.rfind(prefixType, 0) == 0 && utdTypeCfg.belongingToTypes.size() > 0) { - return utdTypeCfg.belongingToTypes[0]; + { + std::shared_lock<std::shared_mutex> guard(utdMutex_); + std::string prefixType = mimeType.substr(0, mimeType.length() - 1); + for (const auto &utdTypeCfg : descriptorCfgs_) { + for (auto mime : utdTypeCfg.mimeTypes) { + std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); + if (mime.rfind(prefixType, 0) == 0 && utdTypeCfg.belongingToTypes.size() > 0 + && IsBelongingType(belongsTo, utdTypeCfg.typeId)) { + return utdTypeCfg.belongingToTypes[0]; + } } } } + if (TryReloadCustomUtd()) { + return GetTypeIdFromCfg(mimeType); + } return ""; } @@ -283,13 +296,14 @@ Status UtdClient::GetUniformDataTypesByMIMEType(const std::string &mimeType, std const std::string &belongsTo) { if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { - LOG_ERROR(UDMF_CLIENT, "invalid belongsTo. mimeType:%{public}s, belongsTo:%{public}s ", - mimeType.c_str(), belongsTo.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo."); + if (TryReloadCustomUtd()) { + return GetUniformDataTypesByMIMEType(mimeType, typeIds, belongsTo); + } return Status::E_INVALID_PARAMETERS; } if (!IsValidMimeType(mimeType)) { - LOG_ERROR(UDMF_CLIENT, "invalid mimeType. mimeType:%{public}s, belongsTo:%{public}s ", - mimeType.c_str(), belongsTo.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid mimeType."); return Status::E_INVALID_PARAMETERS; } @@ -299,8 +313,7 @@ Status UtdClient::GetUniformDataTypesByMIMEType(const std::string &mimeType, std typeIds.clear(); for (const auto &typeId : typeIdsInCfg) { // the find typeId is not belongsTo to the belongsTo. - if (belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && - !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { + if (!IsBelongingType(belongsTo, typeId)) { continue; } typeIds.emplace_back(typeId); @@ -321,16 +334,21 @@ std::vector<std::string> UtdClient::GetTypeIdsFromCfg(const std::string &mimeTyp } std::vector<std::string> typeIdsInCfg; - std::shared_lock<std::shared_mutex> guard(utdMutex_); - for (const auto &utdTypeCfg : descriptorCfgs_) { - for (auto mime : utdTypeCfg.mimeTypes) { - std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); - if ((mime == mimeType) || (prefixMatch && mime.rfind(prefixType, 0) == 0)) { - typeIdsInCfg.push_back(utdTypeCfg.typeId); - break; + { + std::shared_lock<std::shared_mutex> guard(utdMutex_); + for (const auto &utdTypeCfg : descriptorCfgs_) { + for (auto mime : utdTypeCfg.mimeTypes) { + std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower); + if ((mime == mimeType) || (prefixMatch && mime.rfind(prefixType, 0) == 0)) { + typeIdsInCfg.push_back(utdTypeCfg.typeId); + break; + } } } } + if (typeIdsInCfg.empty() && TryReloadCustomUtd()) { + return GetTypeIdsFromCfg(mimeType); + } return typeIdsInCfg; } @@ -358,11 +376,11 @@ Status UtdClient::IsUtd(std::string typeId, bool &result) } result = false; } catch (...) { - LOG_ERROR(UDMF_CLIENT, "exception, typeId:%{public}s", typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "throw error"); result = false; return Status::E_ERROR; } - LOG_ERROR(UDMF_CLIENT, "is not utd, typeId:%{public}s", typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "is not utd"); return Status::E_OK; } @@ -395,7 +413,8 @@ void UtdClient::InstallCustomUtds(const std::string &bundleName, const std::stri return; } LOG_INFO(UDMF_CLIENT, "start, bundleName:%{public}s, user:%{public}d", bundleName.c_str(), user); - std::vector<TypeDescriptorCfg> customTyepCfgs = CustomUtdStore::GetInstance().GetTypeCfgs(user); + std::lock_guard<std::mutex> lock(updateUtdMutex_); + std::vector<TypeDescriptorCfg> customTyepCfgs = CustomUtdStore::GetInstance().GetCustomUtd(false, user); if (!CustomUtdStore::GetInstance().UninstallCustomUtds(bundleName, user, customTyepCfgs)) { LOG_ERROR(UDMF_CLIENT, "custom utd installed failed. bundleName:%{public}s, user:%{public}d", bundleName.c_str(), user); @@ -418,7 +437,8 @@ void UtdClient::UninstallCustomUtds(const std::string &bundleName, int32_t user) return; } LOG_INFO(UDMF_CLIENT, "start, bundleName:%{public}s, user:%{public}d", bundleName.c_str(), user); - std::vector<TypeDescriptorCfg> customTyepCfgs = CustomUtdStore::GetInstance().GetTypeCfgs(user); + std::lock_guard<std::mutex> lock(updateUtdMutex_); + std::vector<TypeDescriptorCfg> customTyepCfgs = CustomUtdStore::GetInstance().GetCustomUtd(false, user); if (!CustomUtdStore::GetInstance().UninstallCustomUtds(bundleName, user, customTyepCfgs)) { LOG_ERROR(UDMF_CLIENT, "custom utd installed failed. bundleName:%{public}s, user:%{public}d", bundleName.c_str(), user); @@ -438,5 +458,48 @@ void UtdClient::UpdateGraph(const std::vector<TypeDescriptorCfg> &customTyepCfgs UtdGraph::GetInstance().Update(std::move(graph)); descriptorCfgs_ = allTypeCfgs; } + +bool UtdClient::TryReloadCustomUtd() +{ + { + std::lock_guard<std::mutex> lock(customUtdMutex_); + auto now = duration_cast<seconds>(system_clock::now().time_since_epoch()).count(); + auto delay = now - lastLoadTime_; + if (delay <= RELOAD_INTERVAL) { + LOG_DEBUG(UDMF_CLIENT, "interval time too short"); + return false; + } + lastLoadTime_ = now; + } + + bool isHap = IsHapTokenType(); + int32_t userId = DEFAULT_USER_ID; + if (!isHap) { + int32_t status = GetCurrentActiveUserId(userId); + LOG_DEBUG(UDMF_CLIENT, "get user id status=%{public}d", status); + if (status != Status::E_OK) { + return false; + } + } + UtdFileInfo info = CustomUtdStore::GetInstance().GetCustomUtdInfo(isHap, userId); + if (info.size == utdFileInfo_.size && info.lastTime == utdFileInfo_.lastTime) { + LOG_DEBUG(UDMF_CLIENT, "utd file not change"); + return false; + } + LOG_INFO(UDMF_CLIENT, "utd file has change, try reload custom utd info"); + if (Init()) { + std::lock_guard<std::mutex> lock(customUtdMutex_); + utdFileInfo_ = info; + return true; + } + return false; +} + +bool UtdClient::IsBelongingType(const std::string &belongsTo, const std::string &typeId) const +{ + return belongsTo == DEFAULT_TYPE_ID || + belongsTo == typeId || + UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId); +} } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/common/unified_key.cpp b/udmf/framework/innerkitsimpl/common/unified_key.cpp index 1aaf4cb6..7b6ee6d2 100644 --- a/udmf/framework/innerkitsimpl/common/unified_key.cpp +++ b/udmf/framework/innerkitsimpl/common/unified_key.cpp @@ -24,10 +24,14 @@ static std::bitset<MAX_BIT_SIZE> g_ruleIntention; static std::bitset<MAX_BIT_SIZE> g_ruleBundleName; static std::bitset<MAX_BIT_SIZE> g_ruleGroupId; static constexpr const char *UNIFIED_KEY_SCHEMA = "udmf://"; -static constexpr const char *ALPHA_AGGREGATE = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; -static constexpr const char *DIGIT_AGGREGATE = "0123456789"; -static constexpr const char *SYMBOL_AGGREGATE = ":;<=>?@[\\]_`"; static constexpr const char SEPARATOR = '/'; +static constexpr std::string_view SCHEME_SEPARATOR = "://"; +#define ALPHA_AGGREGATE "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define DIGIT_AGGREGATE "0123456789" +#define SYMBOL_AGGREGATE ":;<=>?@[\\]_`" +static constexpr std::string_view INTENTION_AGGREGATE_VIEW = ALPHA_AGGREGATE "_"; +static constexpr std::string_view BUNDLE_AGGREGATE_VIEW = ALPHA_AGGREGATE DIGIT_AGGREGATE "._+-"; +static constexpr std::string_view GROUPID_AGGREGATE_VIEW = ALPHA_AGGREGATE DIGIT_AGGREGATE SYMBOL_AGGREGATE; static constexpr uint32_t PREFIX_LEN = 24; static constexpr uint32_t SUFIX_LEN = 8; static constexpr uint32_t INDEX_LEN = 32; @@ -59,7 +63,7 @@ std::string UnifiedKey::GetUnifiedKey() return this->key; } -std::string UnifiedKey::GetPropertyKey() const +std::string UnifiedKey::GetKeyCommonPrefix() const { if (this->key.size() > INDEX_LEN) { return this->key.substr(0, key.size() - SUFIX_LEN); @@ -77,60 +81,60 @@ std::string UnifiedKey::GetPropertyKey() const bool UnifiedKey::IsValid() { - if (this->key.empty()) { - LOG_DEBUG(UDMF_FRAMEWORK, "empty key"); + if (key.empty()) { + LOG_ERROR(UDMF_FRAMEWORK, "Empty key"); return false; } PreliminaryWork(); - - std::string data = this->key; // schema/intention/groupId - std::string separator = "://"; - size_t pos = data.find(separator); + std::string_view data = key; + size_t pos = data.find(SCHEME_SEPARATOR); if (pos == std::string::npos) { + LOG_ERROR(UDMF_FRAMEWORK, "Missing scheme separator. Key=%{public}s", this->key.c_str()); return false; } - std::string schema = data.substr(0, pos + separator.size()); // schema - if (UNIFIED_KEY_SCHEMA != schema) { - LOG_DEBUG(UDMF_FRAMEWORK, "wrong schema"); + auto schema = data.substr(0, pos + SCHEME_SEPARATOR.length()); + if (schema != UNIFIED_KEY_SCHEMA) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid key schema. Key=%{public}s", this->key.c_str()); return false; } - - data = data.substr(pos + separator.size()); // intention/bundleName/groupId - pos = data.find('/'); // intention - if (pos == std::string::npos) { + data = data.substr(pos + SCHEME_SEPARATOR.length()); // intention/bundle/group + if (!ExtractAndValidateSegment(data, this->intention, g_ruleIntention, "intention")) { return false; } - std::string intentionTmp = data.substr(0, pos); - if (!CheckCharacter(intentionTmp, g_ruleIntention)) { + if (!ExtractAndValidateSegment(data, this->bundleName, g_ruleBundleName, "bundleName")) { return false; } - this->intention = intentionTmp; - - data = data.substr(pos + 1); - pos = data.find('/'); // bundleName - if (pos == std::string::npos) { + if (data.empty()) { + LOG_ERROR(UDMF_FRAMEWORK, "Find groupId error. Key=%{public}s", this->key.c_str()); return false; } - std::string bundle = data.substr(0, pos); - if (!CheckCharacter(bundle, g_ruleBundleName)) { - LOG_DEBUG(UDMF_FRAMEWORK, "wrong bundle"); + if (!CheckCharacter(data, g_ruleGroupId)) { + LOG_ERROR(UDMF_FRAMEWORK, "Check groupId character error. Key=%{public}s", this->key.c_str()); return false; } - this->bundleName = bundle; + this->groupId = data; + return true; +} - data = data.substr(pos + 1); // groupId - if (data.empty()) { +bool UnifiedKey::ExtractAndValidateSegment(std::string_view& data, std::string& field, + const std::bitset<MAX_BIT_SIZE>& rule, const std::string& name) +{ + size_t pos = data.find(SEPARATOR); + if (pos == std::string_view::npos) { + LOG_ERROR(UDMF_FRAMEWORK, "Missing '/' for %{public}s", name.c_str()); return false; } - if (!CheckCharacter(data, g_ruleGroupId)) { - LOG_DEBUG(UDMF_FRAMEWORK, "wrong groupId"); + field = std::string(data.substr(0, pos)); + if (!CheckCharacter(field, rule)) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid character in %{public}s", name.c_str()); return false; } - this->groupId = data; + // Remove the prefix '/' + data = data.substr(pos + 1); return true; } -bool UnifiedKey::CheckCharacter(std::string data, std::bitset<MAX_BIT_SIZE> rule) +bool UnifiedKey::CheckCharacter(const std::string_view& data, const std::bitset<MAX_BIT_SIZE> &rule) { if (data.empty()) { LOG_DEBUG(UDMF_FRAMEWORK, "empty key"); @@ -152,22 +156,19 @@ void UnifiedKey::PreliminaryWork() { // All intentions are composed of uppercase and lowercase letters and underscores. if (g_ruleIntention.none()) { - std::string intentionTmp = std::string(ALPHA_AGGREGATE) + "_"; - for (char i : intentionTmp) { + for (char i : INTENTION_AGGREGATE_VIEW) { g_ruleIntention.set(i); } } // All bundle name are composed of uppercase and lowercase letters and dots. if (g_ruleBundleName.none()) { - std::string bundleAggregate = std::string(ALPHA_AGGREGATE) + DIGIT_AGGREGATE + "._"; - for (char i : bundleAggregate) { + for (char i : BUNDLE_AGGREGATE_VIEW) { g_ruleBundleName.set(i); } } // Characters of groupId are taken from Ascii codes 48 to 122. if (g_ruleGroupId.none()) { - std::string idAggregate = std::string(DIGIT_AGGREGATE) + ALPHA_AGGREGATE + SYMBOL_AGGREGATE; - for (char i : idAggregate) { + for (char i : GROUPID_AGGREGATE_VIEW) { g_ruleGroupId.set(i); } } diff --git a/udmf/framework/innerkitsimpl/common/unified_meta.cpp b/udmf/framework/innerkitsimpl/common/unified_meta.cpp index 04989624..cd4e4ff5 100644 --- a/udmf/framework/innerkitsimpl/common/unified_meta.cpp +++ b/udmf/framework/innerkitsimpl/common/unified_meta.cpp @@ -507,16 +507,17 @@ static constexpr UtdType UTD_TYPES[] = { { OPENHARMONY_GOPAINT, "OPENHARMONY_GOPAINT", "openharmony.gopaint" }, { OPENHARMONY_GOBRUSH, "OPENHARMONY_GOBRUSH", "openharmony.gobrush" }, { OPENHARMONY_GOBRUSHES, "OPENHARMONY_GOBRUSHES", "openharmony.gobrushes" }, - { OPENHARMONY_GOCOLOR, "OPENHARMONY_GOCOLOR", "openharmony.gocolor" } + { OPENHARMONY_GOCOLOR, "OPENHARMONY_GOCOLOR", "openharmony.gocolor" }, + { OPENHARMONY_DLP, "OPENHARMONY_DLP", "openharmony.dlp"} }; -static const std::vector<std::string_view> NOT_NEED_COUNT_VALUE_LIST = { +static const std::initializer_list<std::string_view> NOT_NEED_COUNT_VALUE_LIST = { UNIFORM_DATA_TYPE, ARRAY_BUFFER_LENGTH, THUMB_DATA_LENGTH, APP_ICON_LENGTH, APPLICATION_DEFINED_RECORD_MARK, FILE_TYPE }; -static const std::set<std::string> FILE_SUB_TYPES = { - "general.image", "general.video", "general.audio", "general.folder" }; +static const std::initializer_list<std::string> FILE_SUB_TYPES = { + "general.image", "general.video", "general.audio", "general.folder", "general.file" }; namespace UtdUtils { bool IsValidUtdId(const std::string &utdId) @@ -648,6 +649,22 @@ bool UnifiedDataUtils::IsPersist(const std::string &intention) return IsPersist(GetIntentionByString(intention)); } +bool UnifiedDataUtils::IsPersist(const int32_t &visibility) +{ + return visibility >= static_cast<int32_t>(VISIBILITY_ALL) && visibility < static_cast<int32_t>(VISIBILITY_BUTT); +} + +bool UnifiedDataUtils::IsFileMangerIntention(const std::string &intention) +{ + Intention optionIntention = GetIntentionByString(intention); + if (optionIntention == UD_INTENTION_SYSTEM_SHARE || + optionIntention == UD_INTENTION_MENU || + optionIntention == UD_INTENTION_PICKER) { + return true; + } + return false; +} + Intention UnifiedDataUtils::GetIntentionByString(const std::string &intention) { for (const auto &it : UD_INTENTION_MAP) { @@ -658,23 +675,91 @@ Intention UnifiedDataUtils::GetIntentionByString(const std::string &intention) return UD_INTENTION_BUTT; } -bool UnifiedDataUtils::IsValidOptions(const std::string &key, std::string &intention) +std::string UnifiedDataUtils::FindIntentionMap(const Intention &queryIntention) { - UnifiedKey unifiedKey(key); - auto isValidKey = unifiedKey.IsValid(); - if (key.empty() && IsPersist(intention)) { - return true; + auto find = UD_INTENTION_MAP.find(queryIntention); + return find == UD_INTENTION_MAP.end() ? "" : find->second; +} + +bool UnifiedDataUtils::IsValidOptions(UnifiedKey &key, const std::string &intention, + const std::string &validIntention) +{ + if (key.key.empty() && intention.empty()) { + return false; } - if (intention.empty() && isValidKey && IsPersist(unifiedKey.intention)) { - return true; + bool isIntentionValid = intention.empty() || intention == validIntention; + if (!isIntentionValid) { + return false; } - if (isValidKey && unifiedKey.intention == intention && IsPersist(intention)) { - intention = ""; - return true; + bool isValidKey = key.key.empty() || (key.IsValid() && key.intention == validIntention); + if (!isValidKey) { + return false; + } + return true; +} + +bool UnifiedDataUtils::IsValidOptions(UnifiedKey &key, const std::string &intention) +{ + if (key.key.empty() && intention.empty()) { + return false; + } + + bool isIntentionValid = intention.empty() || IsPersist(intention); + if (!isIntentionValid) { + return false; + } + + bool isValidKey = key.key.empty() || (key.IsValid() && IsPersist(key.intention)); + if (!isValidKey) { + return false; + } + + if (!key.key.empty() && !intention.empty()) { + return key.intention == intention; + } + return true; +} + +bool UnifiedDataUtils::IsValidOptionsNonDrag(UnifiedKey &key, const std::string &intention) +{ + if (IsValidOptions(key, intention)) { + return !key.key.empty() || intention == UD_INTENTION_MAP.at(Intention::UD_INTENTION_DATA_HUB); } return false; } +std::string UnifiedDataUtils::GetBelongsToFileType(const std::string &utdId) +{ + if (utdId.empty() || utdId == "general.html" || utdId == "general.plain-text") { + LOG_ERROR(UDMF_FRAMEWORK, "The utdId is empty or the utdId is general.html or general.plain-text"); + return ""; + } + std::shared_ptr<TypeDescriptor> descriptor; + UtdClient::GetInstance().GetTypeDescriptor(utdId, descriptor); + if (descriptor == nullptr) { + LOG_INFO(UDMF_FRAMEWORK, "The descriptor is null"); + return ""; + } + for (const auto &type : FILE_SUB_TYPES) { + bool isSpecificType = false; + descriptor->BelongsTo(type, isSpecificType); + if (isSpecificType) { + return type; + } + } + if (!descriptor->GetFilenameExtensions().empty()) { + LOG_INFO(UDMF_FRAMEWORK, "The type descriptor has file extensions"); + return "general.file"; + } + LOG_INFO(UDMF_FRAMEWORK, "Return empty"); + return ""; +} + +bool UnifiedDataUtils::IsFilterFileType(const std::string &type) +{ + return std::find(FILE_SUB_TYPES.begin(), FILE_SUB_TYPES.end(), type) != FILE_SUB_TYPES.end(); +} + std::shared_ptr<Object> ObjectUtils::ConvertToObject(UDDetails &details) { Object object; @@ -781,20 +866,13 @@ void ObjectUtils::ProcessFileUriType(UDType &utdType, ValueType &value) utdType = FILE; std::string fileType; if (fileUri->GetValue(FILE_TYPE, fileType)) { - std::shared_ptr<TypeDescriptor> descriptor; - UtdClient::GetInstance().GetTypeDescriptor(fileType, descriptor); - if (descriptor == nullptr) { + std::string fileTypeStr = UnifiedDataUtils::GetBelongsToFileType(fileType); + if (fileTypeStr.empty()) { return; } - bool isFileType = false; - for (const auto &fileSub : FILE_SUB_TYPES) { - descriptor->BelongsTo(fileSub, isFileType); - if (isFileType) { - utdType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(fileSub)); - LOG_INFO(UDMF_FRAMEWORK, "Change type to %{public}s", fileSub.c_str()); - return; - } - } + utdType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(fileTypeStr)); + LOG_INFO(UDMF_FRAMEWORK, "Change type to %{public}s", fileTypeStr.c_str()); + return; } } } // namespace UDMF diff --git a/udmf/framework/innerkitsimpl/convert/data_params_conversion.cpp b/udmf/framework/innerkitsimpl/convert/data_params_conversion.cpp index 755b5281..bb9003ab 100644 --- a/udmf/framework/innerkitsimpl/convert/data_params_conversion.cpp +++ b/udmf/framework/innerkitsimpl/convert/data_params_conversion.cpp @@ -12,9 +12,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#define LOG_TAG "DataParamsConversion" #include "data_params_conversion.h" +#include "logger.h" #include "ndk_data_conversion.h" +#include "udmf_client.h" +#include "udmf_utils.h" namespace OHOS::UDMF { Status DataParamsConversion::GetInnerDataParams(OH_UdmfGetDataParams &ndkDataParams, QueryOption &query, @@ -42,6 +45,50 @@ Status DataParamsConversion::GetInnerDataParams(OH_UdmfGetDataParams &ndkDataPar ndkDataParams.dataProgressListener(&ndkProgrssInfo, ndkData); OH_UdmfData_Destroy(ndkData); }; + std::set<std::string> types; + for (size_t i = 0; i < ndkDataParams.acceptableInfo.typesCount; i++) { + types.insert(ndkDataParams.acceptableInfo.typesArray[i]); + } + dataParams.acceptableInfo = { + .types = std::move(types), + .recordCount = ndkDataParams.acceptableInfo.recordsCount, + }; + return Status::E_OK; +} + +Status DataParamsConversion::GetDataLoaderParams(const OH_UdmfDataLoadParams &ndkDataParams, + DataLoadParams &dataLoadParams) +{ + if (ndkDataParams.dataLoadHandler == nullptr) { + LOG_ERROR(UDMF_CAPI, "DataLoadHandler is null"); + return Status::E_INVALID_PARAMETERS; + } + std::set<std::string> types; + for (size_t i = 0; i < ndkDataParams.dataLoadInfo.typesCount; i++) { + types.insert(ndkDataParams.dataLoadInfo.typesArray[i]); + } + dataLoadParams.dataLoadInfo = { + .sequenceKey = UTILS::GenerateId(), + .types = std::move(types), + .recordCount = ndkDataParams.dataLoadInfo.recordsCount, + }; + dataLoadParams.loadHandler = [ndkDataParams](const std::string &udKey, const DataLoadInfo &dataLoadInfo) { + std::vector<std::string> types(dataLoadInfo.types.begin(), dataLoadInfo.types.end()); + OH_UdmfDataLoadInfo ndkDataLoadInfo { + .typesArray = NdkDataConversion::StrVectorToTypesArray(types), + .typesCount = types.size(), + .recordsCount = dataLoadInfo.recordCount, + }; + OH_UdmfData *data = ndkDataParams.dataLoadHandler(&ndkDataLoadInfo); + if (data == nullptr || data->unifiedData_ == nullptr) { + LOG_ERROR(UDMF_CAPI, "Data is null"); + return; + } + auto status = UdmfClient::GetInstance().PushDelayData(udKey, *data->unifiedData_); + if (status != Status::E_OK) { + LOG_ERROR(UDMF_CAPI, "Set delay data failed, status = %{public}d", status); + } + }; return Status::E_OK; } } diff --git a/udmf/framework/innerkitsimpl/convert/ndk_data_conversion.cpp b/udmf/framework/innerkitsimpl/convert/ndk_data_conversion.cpp index 00a105de..73b2fa9b 100644 --- a/udmf/framework/innerkitsimpl/convert/ndk_data_conversion.cpp +++ b/udmf/framework/innerkitsimpl/convert/ndk_data_conversion.cpp @@ -12,25 +12,76 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#define LOG_TAG "NdkDataConversion" #include "ndk_data_conversion.h" +#include "logger.h" +#include "securec.h" namespace OHOS::UDMF { - Status NdkDataConversion::GetNativeUnifiedData(OH_UdmfData* ndkData, std::shared_ptr<UnifiedData>& data) - { - if (ndkData == nullptr || data == nullptr || ndkData->cid != NdkStructId::UDMF_UNIFIED_DATA_STRUCT_ID) { - return Status::E_INVALID_PARAMETERS; +static constexpr uint64_t MAX_RECORDS_COUNT = 4 * 1024 * 1024; +static constexpr uint64_t MAX_KEY_STRING_LEN = 1 * 1024 * 1024; + +Status NdkDataConversion::GetNativeUnifiedData(OH_UdmfData* ndkData, std::shared_ptr<UnifiedData>& data) +{ + if (ndkData == nullptr || data == nullptr || ndkData->cid != NdkStructId::UDMF_UNIFIED_DATA_STRUCT_ID) { + return Status::E_INVALID_PARAMETERS; + } + data = ndkData->unifiedData_; + return Status::E_OK; +} + +Status NdkDataConversion::GetNdkUnifiedData(std::shared_ptr<UnifiedData> data, OH_UdmfData* ndkData) +{ + if (data == nullptr || ndkData == nullptr || ndkData->cid != NdkStructId::UDMF_UNIFIED_DATA_STRUCT_ID) { + return Status::E_INVALID_PARAMETERS; + } + ndkData->unifiedData_ = data; + return Status::E_OK; +} + +char** NdkDataConversion::StrVectorToTypesArray(const std::vector<std::string>& strVector) +{ + unsigned int vectorSize = strVector.size(); + if (vectorSize == 0 || vectorSize > MAX_RECORDS_COUNT) { + return nullptr; + } + char** typesArray = new (std::nothrow) char* [vectorSize]; + if (typesArray == nullptr) { + LOG_ERROR(UDMF_CAPI, "create types array failed!, vectorSize: %{public}d, MAX_RECORDS_COUNT: %{public}" PRIu64, + vectorSize, MAX_RECORDS_COUNT); + return nullptr; + } + for (unsigned int i = 0; i < vectorSize; ++i) { + unsigned int strLen = strVector[i].length() + 1; + if (strLen > MAX_KEY_STRING_LEN) { + LOG_INFO(UDMF_CAPI, "string exceeds maximum length, length is %{public}d", strLen); + DestroyStringArray(typesArray, vectorSize); + return nullptr; + } + typesArray[i] = new (std::nothrow) char[strLen]; + if (typesArray[i] == nullptr || + (strcpy_s(typesArray[i], strLen, strVector[i].c_str())) != EOK) { + LOG_ERROR(UDMF_CAPI, "string copy failed"); + DestroyStringArray(typesArray, vectorSize); + return nullptr; } - data = ndkData->unifiedData_; - return Status::E_OK; } + return typesArray; +} - Status NdkDataConversion::GetNdkUnifiedData(std::shared_ptr<UnifiedData> data, OH_UdmfData* ndkData) - { - if (data == nullptr || ndkData == nullptr || ndkData->cid != NdkStructId::UDMF_UNIFIED_DATA_STRUCT_ID) { - return Status::E_INVALID_PARAMETERS; +void NdkDataConversion::DestroyStringArray(char**& bufArray, unsigned int& count) +{ + if (bufArray == nullptr) { + return; + } + for (unsigned int i = 0; i < count; i++) { + if (bufArray[i] != nullptr) { + delete[] bufArray[i]; + bufArray[i] = nullptr; } - ndkData->unifiedData_ = data; - return Status::E_OK; } + delete[] bufArray; + bufArray = nullptr; + count = 0; +} } \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/convert/udmf_conversion.cpp b/udmf/framework/innerkitsimpl/convert/udmf_conversion.cpp index f4d0ae62..94f68c13 100644 --- a/udmf/framework/innerkitsimpl/convert/udmf_conversion.cpp +++ b/udmf/framework/innerkitsimpl/convert/udmf_conversion.cpp @@ -58,6 +58,7 @@ void UdmfConversion::ConvertRecordToSubclass(std::shared_ptr<UnifiedRecord> &rec auto uid = record->GetUid(); auto entries = record->GetInnerEntries(); auto utdId = record->GetUtdId(); + auto utdId2 = record->GetUtdId2(); auto uris = record->GetUris(); switch (type) { case UDType::TEXT: { @@ -122,6 +123,7 @@ void UdmfConversion::ConvertRecordToSubclass(std::shared_ptr<UnifiedRecord> &rec } record->SetUid(uid); record->SetUtdId(utdId); + record->SetUtdId2(utdId2); record->SetInnerEntries(entries); record->SetUris(uris); SetValueWhenNotUds(record); diff --git a/udmf/framework/innerkitsimpl/data/application_defined_record.cpp b/udmf/framework/innerkitsimpl/data/application_defined_record.cpp index 219c1a1c..15557072 100644 --- a/udmf/framework/innerkitsimpl/data/application_defined_record.cpp +++ b/udmf/framework/innerkitsimpl/data/application_defined_record.cpp @@ -45,7 +45,6 @@ ApplicationDefinedRecord::ApplicationDefinedRecord(UDType type, ValueType value) auto object = std::get<std::shared_ptr<Object>>(value); object->GetValue(UNIFORM_DATA_TYPE, applicationDefinedType); object->GetValue(ARRAY_BUFFER, rawData_); - hasObject_ = true; } if (applicationDefinedType.empty()) { applicationDefinedType = UtdUtils::GetUtdIdFromUtdEnum(type); diff --git a/udmf/framework/innerkitsimpl/data/audio.cpp b/udmf/framework/innerkitsimpl/data/audio.cpp index 41dafb68..c308f0cd 100644 --- a/udmf/framework/innerkitsimpl/data/audio.cpp +++ b/udmf/framework/innerkitsimpl/data/audio.cpp @@ -20,18 +20,30 @@ namespace UDMF { Audio::Audio() : Audio("") { SetType(AUDIO); - utdId_ = UtdUtils::GetUtdIdFromUtdEnum(AUDIO); + utdId2_ = GENERAL_FILE_URI; } Audio::Audio(const std::string &uri) : File(uri) { SetType(AUDIO); - utdId_ = UtdUtils::GetUtdIdFromUtdEnum(AUDIO); + utdId2_ = GENERAL_FILE_URI; } Audio::Audio(UDType type, ValueType value) : File(type, value) { SetType(AUDIO); + utdId2_ = GENERAL_FILE_URI; +} + +void Audio::InitObject() +{ + File::InitObject(); + auto object = std::get<std::shared_ptr<Object>>(value_); + if (!fileType_.empty()) { + object->value_[FILE_TYPE] = fileType_; + } else { + object->value_[FILE_TYPE] = "general.audio"; + } } } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/file.cpp b/udmf/framework/innerkitsimpl/data/file.cpp index cccc8487..c0cd19e1 100644 --- a/udmf/framework/innerkitsimpl/data/file.cpp +++ b/udmf/framework/innerkitsimpl/data/file.cpp @@ -18,16 +18,21 @@ namespace OHOS { namespace UDMF { File::File() : UnifiedRecord(FILE) { + SetType(FILE); + utdId2_ = GENERAL_FILE_URI; } File::File(const std::string &uri) : UnifiedRecord(FILE) { + SetType(FILE); this->oriUri_ = uri; + utdId2_ = GENERAL_FILE_URI; } File::File(UDType type, ValueType value) : UnifiedRecord(type, value) { - this->dataType_ = FILE; + SetType(FILE); + utdId2_ = GENERAL_FILE_URI; if (std::holds_alternative<std::string>(value)) { oriUri_ = std::get<std::string>(value); } else if (std::holds_alternative<std::shared_ptr<Object>>(value)) { @@ -35,23 +40,13 @@ File::File(UDType type, ValueType value) : UnifiedRecord(type, value) object->GetValue(ORI_URI, oriUri_); object->GetValue(REMOTE_URI, remoteUri_); object->GetValue(FILE_TYPE, fileType_); - std::string uniformDataType; - if (object->GetValue(UNIFORM_DATA_TYPE, uniformDataType) && uniformDataType == GENERAL_FILE_URI) { - utdId_ = std::move(uniformDataType); - } std::shared_ptr<Object> detailObj = nullptr; if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); } - hasObject_ = true; } } -void File::SetType(const UDType &type) -{ - this->dataType_ = type; -} - int64_t File::GetSize() { return static_cast<int64_t>(this->oriUri_.size() + this->remoteUri_.size() + @@ -109,7 +104,11 @@ void File::InitObject() object->value_[UNIFORM_DATA_TYPE] = GENERAL_FILE_URI; object->value_[ORI_URI] = oriUri_; object->value_[REMOTE_URI] = remoteUri_; - object->value_[FILE_TYPE] = fileType_; + if (!fileType_.empty()) { + object->value_[FILE_TYPE] = fileType_; + } else { + object->value_[FILE_TYPE] = "general.file"; + } object->value_[DETAILS] = ObjectUtils::ConvertToObject(details_); object->value_.insert_or_assign(VALUE_TYPE, std::move(value)); } diff --git a/udmf/framework/innerkitsimpl/data/flexible_type.cpp b/udmf/framework/innerkitsimpl/data/flexible_type.cpp index df907952..d99153fe 100644 --- a/udmf/framework/innerkitsimpl/data/flexible_type.cpp +++ b/udmf/framework/innerkitsimpl/data/flexible_type.cpp @@ -15,7 +15,6 @@ #define LOG_TAG "FlexibleType" #include "flexible_type.h" #include "logger.h" -#include "udmf_utils.h" #include "base32_utils.h" namespace OHOS { @@ -39,21 +38,19 @@ bool FlexibleType::ParseFlexibleUtd(const std::string &typeId, TypeDescriptorCfg std::string flexibleFlag = FLEXIBLE_TYPE_FLAG; flexibleUtd.erase(0, flexibleFlag.size()); std::string flexibleUtdDecode = Base32::Decode(flexibleUtd); - - LOG_DEBUG(UDMF_CLIENT, "The typeId be parsed, flexibleUtdDecode: %{public}s", flexibleUtdDecode.c_str()); if (flexibleUtdDecode.empty() || flexibleUtdDecode[0] != '?' || flexibleUtdDecode.find("=") == flexibleUtdDecode.npos) { - LOG_WARN(UDMF_CLIENT, "The typeId cannot be parsed, %{public}s ", typeId.c_str()); + LOG_WARN(UDMF_CLIENT, "The typeId cannot be parsed"); return false; } - std::vector<std::string> flexibleTypeAttrs = UTILS::StrSplit(flexibleUtdDecode, ":"); + std::vector<std::string> flexibleTypeAttrs = StrSplit(flexibleUtdDecode, ":"); for (auto attr : flexibleTypeAttrs) { - std::vector<std::string> attrkv = UTILS::StrSplit(attr, "="); + std::vector<std::string> attrkv = StrSplit(attr, "="); if (attrkv.size() != ATTRIBUTE_PAIR_SIZE) { continue; } if (attrkv[1].length() > MAX_TYPE_SIZE) { - LOG_ERROR(UDMF_CLIENT, "Attribute too long, attribute: %{public}s", attr.c_str()); + LOG_ERROR(UDMF_CLIENT, "Attribute too long"); return false; } std::string attrName = attrkv[0]; @@ -82,11 +79,23 @@ std::string FlexibleType::GenFlexibleUtd(const std::string &mimeType, const std: flexibleUtd += ":" + std::to_string(FILE_EXTENTSION) + "=" + fileExtension; } std::string encodeUtd = Base32::Encode(flexibleUtd); - LOG_DEBUG(UDMF_CLIENT, "FlexibleUtd typeId is: %{public}s, encodeUtd is: %{public}s", - flexibleUtd.c_str(), encodeUtd.c_str()); return FLEXIBLE_TYPE_FLAG + encodeUtd; } +std::vector<std::string> FlexibleType::StrSplit(const std::string &str, const std::string &delimiter) +{ + std::vector<std::string> result; + size_t start = 0; + size_t end = str.find(delimiter); + while (end != std::string::npos) { + result.push_back(str.substr(start, end - start)); + start = end + delimiter.length(); + end = str.find(delimiter, start); + } + result.push_back(str.substr(start)); + return result; +} + } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/folder.cpp b/udmf/framework/innerkitsimpl/data/folder.cpp index 2164cec3..52160d85 100644 --- a/udmf/framework/innerkitsimpl/data/folder.cpp +++ b/udmf/framework/innerkitsimpl/data/folder.cpp @@ -20,18 +20,30 @@ namespace UDMF { Folder::Folder() : Folder("") { SetType(FOLDER); - utdId_ = UtdUtils::GetUtdIdFromUtdEnum(FOLDER); + utdId2_ = GENERAL_FILE_URI; } Folder::Folder(const std::string &uri) : File(uri) { SetType(FOLDER); - utdId_ = UtdUtils::GetUtdIdFromUtdEnum(FOLDER); + utdId2_ = GENERAL_FILE_URI; } Folder::Folder(UDType type, ValueType value) : File(type, value) { SetType(FOLDER); + utdId2_ = GENERAL_FILE_URI; +} + +void Folder::InitObject() +{ + File::InitObject(); + auto object = std::get<std::shared_ptr<Object>>(value_); + if (!fileType_.empty()) { + object->value_[FILE_TYPE] = fileType_; + } else { + object->value_[FILE_TYPE] = "general.folder"; + } } } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/html.cpp b/udmf/framework/innerkitsimpl/data/html.cpp index 924634d2..a2f6d849 100644 --- a/udmf/framework/innerkitsimpl/data/html.cpp +++ b/udmf/framework/innerkitsimpl/data/html.cpp @@ -50,7 +50,6 @@ Html::Html(UDType type, ValueType value) : Text(type, value) if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); } - hasObject_ = true; } } diff --git a/udmf/framework/innerkitsimpl/data/image.cpp b/udmf/framework/innerkitsimpl/data/image.cpp index cf9067d6..a9de01f1 100644 --- a/udmf/framework/innerkitsimpl/data/image.cpp +++ b/udmf/framework/innerkitsimpl/data/image.cpp @@ -20,18 +20,30 @@ namespace UDMF { Image::Image() : Image("") { SetType(IMAGE); - utdId_ = UtdUtils::GetUtdIdFromUtdEnum(IMAGE); + utdId2_ = GENERAL_FILE_URI; } Image::Image(const std::string &uri) : File(uri) { SetType(IMAGE); - utdId_ = UtdUtils::GetUtdIdFromUtdEnum(IMAGE); + utdId2_ = GENERAL_FILE_URI; } Image::Image(UDType type, ValueType value) : File(type, value) { SetType(IMAGE); + utdId2_ = GENERAL_FILE_URI; +} + +void Image::InitObject() +{ + File::InitObject(); + auto object = std::get<std::shared_ptr<Object>>(value_); + if (!fileType_.empty()) { + object->value_[FILE_TYPE] = fileType_; + } else { + object->value_[FILE_TYPE] = "general.image"; + } } } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/link.cpp b/udmf/framework/innerkitsimpl/data/link.cpp index 695730c6..2a218730 100644 --- a/udmf/framework/innerkitsimpl/data/link.cpp +++ b/udmf/framework/innerkitsimpl/data/link.cpp @@ -38,7 +38,6 @@ Link::Link(UDType type, ValueType value) : Text(type, value) if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); } - hasObject_ = true; } } diff --git a/udmf/framework/innerkitsimpl/data/plain_text.cpp b/udmf/framework/innerkitsimpl/data/plain_text.cpp index 7928a6da..1ac1cc64 100644 --- a/udmf/framework/innerkitsimpl/data/plain_text.cpp +++ b/udmf/framework/innerkitsimpl/data/plain_text.cpp @@ -48,7 +48,6 @@ PlainText::PlainText(UDType type, ValueType value) : Text(type, value) if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); } - hasObject_ = true; } } diff --git a/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp index adbd21fe..b26bfba5 100644 --- a/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp +++ b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp @@ -12,11 +12,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define LOG_TAG "PresetTypeDescriptors" + #include "preset_type_descriptors.h" +#include <sstream> +#include <fstream> +#include "cJSON.h" +#include "custom_utd_json_parser.h" +#include "logger.h" + namespace OHOS { namespace UDMF { -constexpr const char *REFERENCE_URL = "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/"\ - "apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype"; +static constexpr const char *UTD_CONF_PATH = "/system/etc/utd/conf/"; +static constexpr const char *UNIFORM_DATA_TYPES_JSON_PATH = "uniform_data_types.json"; PresetTypeDescriptors::PresetTypeDescriptors() { @@ -37,3300 +45,39 @@ std::vector<TypeDescriptorCfg> &PresetTypeDescriptors::GetPresetTypes() { return typeDescriptors_; } + void PresetTypeDescriptors::InitDescriptors() { - typeDescriptors_ = { - {"general.entity", - {}, - {}, - {}, - "Base type for physical hierarchy.", - REFERENCE_URL, - ""}, - {"general.object", - {}, - {}, - {"*/*"}, - "Base type for logical hierarchy.", - REFERENCE_URL, - ""}, - {"general.composite-object", - {"general.object"}, - {}, - {}, - "Base type for mixed object. For example, a PDF file contains both text and special formatting data.", - REFERENCE_URL, - ""}, - {"general.text", - {"general.object"}, - {}, - {"text/*"}, - "Base type for all text.", - REFERENCE_URL, - ""}, - {"general.plain-text", - {"general.text"}, - {".txt", ".text"}, - {"text/plain"}, - "Text of unspecified encoding, with no markup.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_txt"}, - {"general.html", - {"general.text"}, - {".html", ".htm"}, - {"text/html"}, - "HTML text.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_html"}, - {"general.hyperlink", - {"general.text"}, - {}, - {}, - "Hyperlink.", - REFERENCE_URL, - ""}, - {"general.xml", - {"general.text"}, - {".xml"}, - {"text/xml"}, - "XML text.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_xml"}, - {"com.real.smil", - {"general.xml"}, - {".smil"}, - {"application/smil"}, - "Real synchronized multimedia integration language.", - REFERENCE_URL, - ""}, - {"general.source-code", - {"general.text"}, - {}, - {}, - "Generic source code.", - REFERENCE_URL, - ""}, - {"general.script", - {"general.source-code"}, - {}, - {}, - "Base type for scripting language source code.", - REFERENCE_URL, - ""}, - {"general.shell-script", - {"general.script"}, - {".sh", ".command"}, - {"text/x-shellscript"}, - "Shell script.", - REFERENCE_URL, - ""}, - {"general.csh-script", - {"general.shell-script"}, - {".csh"}, - {"text/x-csh"}, - "C-shell script.", - REFERENCE_URL, - ""}, - {"general.perl-script", - {"general.shell-script"}, - {".pl", ".pm"}, - {"text/x-perl-script"}, - "Perl script.", - REFERENCE_URL, - ""}, - {"general.php-script", - {"general.shell-script"}, - {".php", ".php3", ".php4", ".ph3", ".ph4", ".phtml"}, - {"text/x-php-script", "text/php", "application/php"}, - "PHP script.", - REFERENCE_URL, - ""}, - {"general.python-script", - {"general.shell-script"}, - {".py"}, - {"text/x-python-script"}, - "Python script.", - REFERENCE_URL, - ""}, - {"general.ruby-script", - {"general.shell-script"}, - {".rb", ".rbw"}, - {"text/ruby-script"}, - "Ruby script.", - REFERENCE_URL, - ""}, - {"general.type-script", - {"general.source-code"}, - {".ts"}, - {}, - "TypeScript source code.", - REFERENCE_URL, - ""}, - {"general.java-script", - {"general.source-code"}, - {".js", ".jscript", ".javascript"}, - {"text/javascript"}, - "JavaScript source code.", - REFERENCE_URL, - ""}, - {"general.c-header", - {"general.source-code"}, - {".h"}, - {"text/x-chdr"}, - "C header file.", - REFERENCE_URL, - ""}, - {"general.c-source", - {"general.source-code"}, - {".c"}, - {"text/x-csrc"}, - "C source code.", - REFERENCE_URL, - ""}, - {"general.c-plus-plus-header", - {"general.source-code"}, - {".hpp", ".h++", ".hxx", ".hh"}, - {"text/x-c++hdr"}, - "C++ header file.", - REFERENCE_URL, - ""}, - {"general.c-plus-plus-source", - {"general.source-code"}, - {".cp", ".cpp", ".c++", ".cc", ".cxx"}, - {"text/x-c++src"}, - "C++ source code.", - REFERENCE_URL, - ""}, - {"general.java-source", - {"general.source-code"}, - {".java", ".jav"}, - {"text/x-java"}, - "Java source code.", - REFERENCE_URL, - ""}, - {"general.markdown", - {"general.text"}, - {".md", ".markdown", ".markdn", ".mdown"}, - {"text/markdown"}, - "Markdown format.", - REFERENCE_URL, - ""}, - {"general.ebook", - {"general.composite-object"}, - {}, - {}, - "Base type for ebook.", - REFERENCE_URL, - ""}, - {"general.epub", - {"general.ebook"}, - {".epub"}, - {"application/epub+zip"}, - "Electronic publication (EPUB) format.", - REFERENCE_URL, - ""}, - {"com.amazon.azw", - {"general.ebook"}, - {".azw"}, - {"application/vnd.amazon.ebook"}, - "AZW ebook.", - REFERENCE_URL, - ""}, - {"com.amazon.azw3", - {"general.ebook"}, - {".azw3"}, - {"application/vnd.amazon.mobi8-ebook", "application/x-mobi8-ebook"}, - "AZW3 ebook.", - REFERENCE_URL, - ""}, - {"com.amazon.kfx", - {"general.ebook"}, - {".kfx"}, - {}, - "KFX ebook.", - REFERENCE_URL, - ""}, - {"com.amazon.mobi", - {"general.ebook"}, - {".mobi"}, - {"application/x-mobipocket-ebook"}, - "MOBI ebook.", - REFERENCE_URL, - ""}, - {"general.media", - {"general.object"}, - {}, - {}, - "Base type for media.", - REFERENCE_URL, - ""}, - {"general.image", - {"general.media"}, - {}, - {"image/*"}, - "Base type for images.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"general.jpeg", - {"general.image"}, - {".jpg", ".jpeg", ".jpe"}, - {"image/jpeg"}, - "JPEG image.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"general.png", - {"general.image"}, - {".png"}, - {"image/png"}, - "PNG image.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"general.raw-image", - {"general.image"}, - {}, - {}, - "Base type for digital camera raw image formats.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"general.tiff", - {"general.image"}, - {".tif", ".tiff"}, - {"image/tiff"}, - "TIFF image.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"com.microsoft.bmp", - {"general.image"}, - {".bmp", ".bm"}, - {"image/bmp", "image/x-ms-bmp"}, - "Windows bitmap image.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"com.microsoft.ico", - {"general.image"}, - {".ico"}, - {"image/ico", "image/x-icon"}, - "Windows icon image.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"com.adobe.photoshop-image", - {"general.image"}, - {".psd"}, - {"image/x-photoshop", "image/photoshop", "image/psd", "application/photoshop"}, - "Adobe Photoshop document.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"com.adobe.illustrator.ai-image", - {"general.image"}, - {".ai"}, - {}, - "Adobe Illustrator document.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"general.fax", - {"general.image"}, - {}, - {}, - "Base type for fax images.", - REFERENCE_URL, - ""}, - {"com.j2.jfx-fax", - {"general.fax"}, - {".jfx"}, - {}, - "J2 fax.", - REFERENCE_URL, - ""}, - {"com.js.efx-fax", - {"general.fax"}, - {".efx"}, - {"image/efax"}, - "eFax fax.", - REFERENCE_URL, - ""}, - {"general.xbitmap-image", - {"general.image"}, - {".xbm"}, - {"image/x-xbitmap", "image/x-xbm"}, - "X bitmap image.", - REFERENCE_URL, - ""}, - {"com.truevision.tga-image", - {"general.image"}, - {".tga"}, - {"image/targa", "image/tga", "application/tga"}, - "TGA image.", - REFERENCE_URL, - ""}, - {"com.sgi.sgi-image", - {"general.image"}, - {".sgi"}, - {"image/sgi"}, - "Silicon Graphics image.", - REFERENCE_URL, - ""}, - {"com.ilm.openexr-image", - {"general.image"}, - {".exr"}, - {}, - "OpenEXR image.", - REFERENCE_URL, - ""}, - {"com.kodak.flashpix.image", - {"general.image"}, - {".fpx"}, - {"image/fpx", "application/vnd.fpx"}, - "FlashPix image.", - REFERENCE_URL, - ""}, - {"com.microsoft.word.doc", - {"general.composite-object"}, - {".doc"}, - {"application/msword"}, - "Microsoft Word data.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_doc"}, - {"com.microsoft.excel.xls", - {"general.composite-object"}, - {".xls"}, - {"application/vnd.ms-excel"}, - "Microsoft Excel data.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_xls"}, - {"com.microsoft.powerpoint.ppt", - {"general.composite-object"}, - {".ppt"}, - {"application/vnd.ms-powerpoint"}, - "Microsoft PowerPoint presentation.", - REFERENCE_URL, - ""}, - {"com.adobe.pdf", - {"general.composite-object"}, - {".pdf"}, - {"application/pdf"}, - "PDF data.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_pdf"}, - {"com.adobe.postscript", - {"general.composite-object"}, - {".ps"}, - {"application/postscript"}, - "PostScript data.", - REFERENCE_URL, - ""}, - {"com.adobe.encapsulated-postscript", - {"com.adobe.postscript"}, - {".eps"}, - {}, - "Encapsulated PostScript.", - REFERENCE_URL, - ""}, - {"general.video", - {"general.media"}, - {}, - {"video/*"}, - "Base type for video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"general.avi", - {"general.video"}, - {".avi", ".vfw"}, - {"video/avi", "video/msvideo", "video/x-msvideo"}, - "AVI video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"general.mpeg", - {"general.video"}, - {".mpg", ".mpeg", ".m75", ".m15", ".mpe"}, - {"video/mpg", "video/mpeg", "video/x-mpg", "video/x-mpeg"}, - "MPEG-1 or MPEG-2 video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"general.mpeg-4", - {"general.video"}, - {".mp4", ".mp4v", ".mpeg4"}, - {"video/mp4", "video/mp4v"}, - "MPEG-4 video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"general.3gpp", - {"general.video"}, - {".3gp", ".3gpp"}, - {"video/3gpp"}, - "3GPP video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"general.3gpp2", - {"general.video"}, - {".3g2", ".3gp2", ".3gpp2"}, - {"video/3gpp2"}, - "3GPP2 video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.microsoft.windows-media-wm", - {"general.video", "com.microsoft.advanced-systems-format"}, - {".wm"}, - {"video/x-ms-wm"}, - "Windows WM video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.microsoft.windows-media-wmv", - {"general.video", "com.microsoft.advanced-systems-format"}, - {".wmv"}, - {"video/x-ms-wmv"}, - "Windows WMV video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.microsoft.windows-media-wmp", - {"general.video", "com.microsoft.advanced-systems-format"}, - {".wmp"}, - {"video/x-ms-wmp"}, - "Windows WMP video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.microsoft.windows-media-wvx", - {"general.video", "com.microsoft.advanced-systems-format"}, - {".wvx"}, - {"video/x-ms-wvx"}, - "Windows WVX video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.microsoft.windows-media-wmx", - {"general.video", "com.microsoft.advanced-systems-format"}, - {".wmx"}, - {"video/x-ms-wmx"}, - "Windows WMX video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.real.realmedia", - {"general.video"}, - {".rm"}, - {"application/vnd.rn-realmedia"}, - "RealMedia.", - REFERENCE_URL, - ""}, - {"general.audio", - {"general.media"}, - {}, - {"audio/*"}, - "Base type for audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.aac", - {"general.audio"}, - {".aac"}, - {"audio/aac"}, - "AAC audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.aiff", - {"general.audio"}, - {".aiff"}, - {"audio/aiff"}, - "AIFF audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.alac", - {"general.audio"}, - {".alac"}, - {"audio/alac"}, - "ALAC audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.flac", - {"general.audio"}, - {".flac"}, - {"audio/flac"}, - "FLAC audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_flac"}, - {"general.mp3", - {"general.audio"}, - {".mp3"}, - {"audio/mp3"}, - "MPEG-3 audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_mp3"}, - {"general.ogg", - {"general.audio"}, - {".ogg"}, - {"audio/ogg"}, - "OGG audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.pcm", - {"general.audio"}, - {".pcm"}, - {"audio/pcm"}, - "PCM audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"com.microsoft.advanced-systems-format", - {"general.media"}, - {".asf"}, - {"video/x-ms-asf", "application/vnd.ms-asf"}, - "Advanced Systems format", - REFERENCE_URL, - ""}, - {"com.microsoft.advanced-stream-redirector", - {"general.video"}, - {".asx"}, - {"video/x-ms-asf"}, - "Advanced stream redirector", - REFERENCE_URL, - ""}, - {"com.microsoft.windows-media-wma", - {"general.audio", "com.microsoft.advanced-systems-format"}, - {".wma"}, - {"audio/x-ms-wma"}, - "Windows WMA audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_wma"}, - {"com.microsoft.waveform-audio", - {"general.audio", "com.microsoft.advanced-systems-format"}, - {".wav", ".wave"}, - {"audio/wav", "audio/wave", "audio/x-wav"}, - "Waveform audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_wav"}, - {"com.microsoft.windows-media-wax", - {"general.audio", "com.microsoft.advanced-systems-format"}, - {".wax"}, - {"audio/x-ms-wax"}, - "Windows WAX audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.au-audio", - {"general.audio"}, - {".au", ".snd"}, - {"audio/basic", "audio/au", "audio/snd"}, - "Au file format.", - REFERENCE_URL, - ""}, - {"general.aifc-audio", - {"general.audio"}, - {".aifc", ".aif", ".aiff"}, - {"audio/x-aiff"}, - "Audio Interchange File Format.", - REFERENCE_URL, - ""}, - {"com.digidesign.sd2-audio", - {"general.audio"}, - {".sd2"}, - {"audio/x-sd2"}, - "Digidesign Sound Designer II audio.", - REFERENCE_URL, - ""}, - {"com.real.realaudio", - {"general.audio"}, - {".ram", ".ra"}, - {"audio/vnd.rn-realaudio", "audio/x-pn-realaudio"}, - "RealMedia audio.", - REFERENCE_URL, - ""}, - {"general.file", - {"general.entity"}, - {}, - {}, - "Base type for file.", - REFERENCE_URL, - ""}, - {"general.directory", - {"general.entity"}, - {}, - {}, - "Base type for directory.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_folder"}, - {"general.folder", - {"general.directory"}, - {}, - {}, - "Base type for folder.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_folder"}, - {"general.symlink", - {"general.entity"}, - {}, - {}, - "Base type for symlink.", - REFERENCE_URL, - ""}, - {"general.archive", - {"general.object"}, - {}, - {}, - "Base type for an archive of files and directories.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"general.bz2-archive", - {"general.archive"}, - {".bz2", ".bzip2"}, - {"application/x-bzip2"}, - "BZip2 archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"general.disk-image", - {"general.archive"}, - {}, - {}, - "Base type for items mountable as a volume.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"general.tar-archive", - {"general.archive"}, - {".tar"}, - {"application/x-tar", "application/tar"}, - "Tar archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"general.zip-archive", - {"general.archive"}, - {".zip"}, - {"application/zip"}, - "Zip archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_zip"}, - {"com.sun.java-archive", - {"general.archive", "general.executable"}, - {".jar"}, - {"application/java-archive"}, - "Java archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"org.gnu.gnu-tar-archive", - {"general.archive"}, - {".gtar"}, - {"application/x-gtar"}, - "GNU archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"org.gnu.gnu-zip-archive", - {"general.archive"}, - {".gz", ".gzip"}, - {"application/x-gzip", "application/gzip"}, - "Gzip archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"org.gnu.gnu-zip-tar-archive", - {"general.archive"}, - {".tgz"}, - {"application/x-gtar"}, - "Gzip tar archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"org.openxmlformats.openxml", - {"general.archive"}, - {}, - {}, - "Office Open XML.", - REFERENCE_URL, - ""}, - {"org.openxmlformats.wordprocessingml.document", - {"general.composite-object", "org.openxmlformats.openxml"}, - {".docx"}, - {"application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, - "Office Open XML Document.", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.sheet", - {"general.composite-object", "org.openxmlformats.openxml"}, - {".xlsx"}, - {"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, - "Office Open XML Workbook.", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.presentation", - {"general.composite-object", "org.openxmlformats.openxml"}, - {".pptx"}, - {"application/vnd.openxmlformats-officedocument.presentationml.presentation"}, - "Office Open XML Presentation.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument", - {"general.archive"}, - {}, - {}, - "Open Document Format for Office Applications.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument.text", - {"general.composite-object", "org.oasis.opendocument"}, - {".odt", ".fodt"}, - {"application/vnd.oasis.opendocument.text"}, - "OpenDocument Text.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument.spreadsheet", - {"general.composite-object", "org.oasis.opendocument"}, - {".ods", ".fods"}, - {"application/vnd.oasis.opendocument.spreadsheet"}, - "OpenDocument Spreadsheet.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument.presentation", - {"general.composite-object", "org.oasis.opendocument"}, - {".odp", ".fodp"}, - {"application/vnd.oasis.opendocument.presentation"}, - "OpenDocument Presentation.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument.graphics", - {"general.composite-object", "org.oasis.opendocument"}, - {".odg", ".fodg"}, - {"application/vnd.oasis.opendocument.graphics"}, - "OpenDocument Graphics.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument.formula", - {"org.oasis.opendocument"}, - {".odf"}, - {"application/vnd.oasis.opendocument.formula"}, - "OpenDocument Formulat.", - REFERENCE_URL, - ""}, - {"com.allume.stuffit-archive", - {"general.archive"}, - {".sit", ".sitx"}, - {"application/x-stuffit", "application/x-sit", "application/stuffit"}, - "Stuffit archive.", - REFERENCE_URL, - ""}, - {"general.calendar", - {"general.text"}, - {}, - {"text/calendar"}, - "Base type for scheduled events.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_calendar"}, - {"general.vcs", - {"general.calendar"}, - {".vcs"}, - {"text/calendar"}, - "vCalendar type.", - REFERENCE_URL, - ""}, - {"general.ics", - {"general.calendar"}, - {".ics"}, - {"text/calendar"}, - "iCalendar type.", - REFERENCE_URL, - ""}, - {"general.contact", - {"general.object"}, - {}, - {}, - "Base type for contact information.", - REFERENCE_URL, - ""}, - {"general.database", - {"general.object"}, - {}, - {}, - "Base type for databases.", - REFERENCE_URL, - ""}, - {"general.message", - {"general.object"}, - {}, - {}, - "Base type for messages.", - REFERENCE_URL, - ""}, - {"general.executable", - {"general.object"}, - {}, - {}, - "Base type for executable data.", - REFERENCE_URL, - ""}, - {"com.microsoft.portable-executable", - {"general.executable"}, - {".exe", ".dll"}, - {"application/vnd.microsoft.portable-executable"}, - "Microsoft Windows application.", - REFERENCE_URL, - ""}, - {"com.sun.java-class", - {"general.executable"}, - {".class"}, - {}, - "Java class.", - REFERENCE_URL, - ""}, - {"general.vcard", - {"general.object"}, - {".vcf", ".vcard"}, - {"text/vcard", "text/x-vcard"}, - "Base type for electronic business card.", - REFERENCE_URL, - ""}, - {"general.navigation", - {"general.object"}, - {}, - {}, - "Base type for navigation.", - REFERENCE_URL, - ""}, - {"general.location", - {"general.navigation"}, - {}, - {}, - "Navigation location.", - REFERENCE_URL, - ""}, - {"general.font", - {"general.object"}, - {}, - {}, - "Base type for fonts.", - REFERENCE_URL, - ""}, - {"general.truetype-font", - {"general.font"}, - {".ttf"}, - {"font/ttf"}, - "TrueType font.", - REFERENCE_URL, - ""}, - {"general.truetype-collection-font", - {"general.font"}, - {".ttc"}, - {"font/collection"}, - "TrueType collection font.", - REFERENCE_URL, - ""}, - {"general.opentype-font", - {"general.font"}, - {".otf"}, - {"font/otf"}, - "OpenType font.", - REFERENCE_URL, - ""}, - {"com.adobe.postscript-font", - {"general.font"}, - {}, - {}, - "PostScript font.", - REFERENCE_URL, - ""}, - {"openharmony.form", - {"general.object"}, - {}, - {}, - "OpenHarmony system defined form.", - REFERENCE_URL, - ""}, - {"openharmony.app-item", - {"general.object"}, - {}, - {}, - "OpenHarmony system defined app item.", - REFERENCE_URL, - ""}, - {"openharmony.pixel-map", - {"general.image"}, - {}, - {}, - "OpenHarmony system defined pixel map.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"openharmony.atomic-service", - {"general.object"}, - {}, - {}, - "OpenHarmony system defined atomic service.", - REFERENCE_URL, - ""}, - {"openharmony.package", - {"general.directory"}, - {}, - {}, - "OpenHarmony system defined package (that is, a directory presented to the user as a file).", - REFERENCE_URL, - ""}, - {"openharmony.hap", - {"openharmony.package"}, - {".hap"}, - {}, - "OpenHarmony system defined ability package.", - REFERENCE_URL, - ""}, - {"openharmony.hdoc", - {"general.composite-object"}, - {".hdoc"}, - {}, - "OpenHarmony system AppNotepad data format.", - REFERENCE_URL, - ""}, - {"openharmony.hinote", - {"general.composite-object"}, - {".hinote"}, - {}, - "OpenHarmony system Notes data format.", - REFERENCE_URL, - ""}, - {"openharmony.styled-string", - {"general.composite-object"}, - {}, - {}, - "OpenHarmony system defined styled string.", - REFERENCE_URL, - ""}, - {"openharmony.want", - {"general.object"}, - {}, - {}, - "OpenHarmony system defined Want.", - REFERENCE_URL, - ""}, - {"openharmony.moving-photo", - {"general.media"}, - {}, - {}, - "OpenHarmony system defined moving photo.", - REFERENCE_URL, - ""}, - {"macos.dmg", - {"general.disk-image"}, - {".dmg"}, - {"application/x-apple-diskimage"}, - "Apple Disk Image", - REFERENCE_URL, - ""}, - {"debian.deb", - {"general.archive"}, - {".deb", ".udeb"}, - {"application/x-debian-package", "application/vnd.debian.binary-package"}, - "OpenHarmony system defined Want.", - REFERENCE_URL, - ""}, - {"general.ofd", - {"general.composite-object"}, - {".ofd"}, - {}, - "Open fixed-layout document, a national standard for format documents", - REFERENCE_URL, - ""}, - {"general.opg", - {"general.archive"}, - {".opg"}, - {}, - "OPG archive", - REFERENCE_URL, - ""}, - {"general.tex", - {"general.source-code"}, - {}, - {}, - "Base type for TeX source code", - REFERENCE_URL, - ""}, - {"general.css", - {"general.script"}, - {".css"}, - {"text/css"}, - "Cascading style sheets", - REFERENCE_URL, - ""}, - {"general.vob", - {"general.video"}, - {".vob"}, - {"video/mpeg", "video/x-ms-vob"}, - "", - REFERENCE_URL, - ""}, - {"general.dif-video", - {"general.video"}, - {".dif"}, - {"video/dv"}, - "Digital interface format", - REFERENCE_URL, - ""}, - {"general.dv-video", - {"general.video"}, - {".dv"}, - {"video/dv"}, - "DV video", - REFERENCE_URL, - ""}, - {"general.flc-animation", - {"general.video"}, - {".fli", ".flc"}, - {"video/fli", "video/flc"}, - "FLIC file format", - REFERENCE_URL, - ""}, - {"general.mng", - {"general.video"}, - {".mng"}, - {"video/x-mng"}, - "Multiple-image network graphics", - REFERENCE_URL, - ""}, - {"general.mpegurl-video", - {"general.video"}, - {".mxu", ".m4u"}, - {"video/vnd.mpegurl"}, - "Video playlist", - REFERENCE_URL, - ""}, - {"general.ts", - {"general.video"}, - {".ts"}, - {"video/mp2ts", "video/mp2t"}, - "MPEG transport stream", - REFERENCE_URL, - ""}, - {"general.amr", - {"general.audio"}, - {".amr"}, - {"audio/amr"}, - "The adaptive multi-rate audio codecs", - REFERENCE_URL, - ""}, - {"general.amr-wb", - {"general.audio"}, - {".awb"}, - {"audio/amr-wb"}, - "Adaptive multi-rate wideband", - REFERENCE_URL, - ""}, - {"general.gsm", - {"general.audio"}, - {".gsm"}, - {"audio/x-gsm", "audio/gsm"}, - "Global system form mobile audio format", - REFERENCE_URL, - ""}, - {"general.imy", - {"general.audio"}, - {".imy"}, - {"audio/imelody"}, - "Non-polyphonic ringtone exchange object format", - REFERENCE_URL, - ""}, - {"general.kar", - {"general.audio"}, - {".kar"}, - {"audio/midi"}, - "Karaoke MIDI file format", - REFERENCE_URL, - ""}, - {"general.mpegurl-audio", - {"general.audio"}, - {".m3u"}, - {"audio/mpegurl", "audio/x-mpegurl"}, - "Audio playlist", - REFERENCE_URL, - ""}, - {"general.mpeg-4-audio", - {"general.audio"}, - {".m4a", ".m4b"}, - {"audio/mpeg"}, - "Audio-only MPEG-4 file", - REFERENCE_URL, - ""}, - {"general.midi-audio", - {"general.audio"}, - {".mid", ".midi"}, - {"audio/midi"}, - "MIDI audio", - REFERENCE_URL, - ""}, - {"general.mp2", - {"general.audio"}, - {".mp2"}, - {"audio/mpeg"}, - "MPEG-1 audio layer II or MPEG-2 audio layer II", - REFERENCE_URL, - ""}, - {"general.mpeg-audio", - {"general.audio"}, - {".mpga"}, - {"audio/mpeg"}, - "MPEG audio format", - REFERENCE_URL, - ""}, - {"general.mxmf", - {"general.audio"}, - {".mxmf"}, - {"audio/mobile-xmf"}, - "Mobile XMF audio format", - REFERENCE_URL, - ""}, - {"general.ota", - {"general.audio"}, - {".ota"}, - {"audio/midi"}, - "OTA ringtone file", - REFERENCE_URL, - ""}, - {"general.pls", - {"general.audio"}, - {".pls"}, - {"audio/x-scpls"}, - "Multimedia playlist format", - REFERENCE_URL, - ""}, - {"general.rtttl", - {"general.audio"}, - {".rtttl"}, - {"audio/midi"}, - "Ring tone transfer language file", - REFERENCE_URL, - ""}, - {"general.psid", - {"general.audio"}, - {".sid", ".psid"}, - {"audio/prs.sid"}, - "SID audio", - REFERENCE_URL, - ""}, - {"general.ulaw-audio", - {"general.audio"}, - {".au", ".ulw", ".snd"}, - {"audio/basic", "audio/au", "audio/snd"}, - "uLaw audio", - REFERENCE_URL, - ""}, - {"general.xmf", - {"general.audio"}, - {".xmf"}, - {"audio/midi"}, - "Extensible music file", - REFERENCE_URL, - ""}, - {"general.gif", - {"general.image"}, - {".gif"}, - {"image/gif"}, - "GIF image", - REFERENCE_URL, - ""}, - {"general.djvu-image", - {"general.image"}, - {".djv", ".djvu"}, - {"image/vnd.djvu"}, - "Djvu image", - REFERENCE_URL, - ""}, - {"general.jng-image", - {"general.image"}, - {".jng"}, - {"image/x-jng"}, - "JPEG network graphic", - REFERENCE_URL, - ""}, - {"general.pcx-image", - {"general.image"}, - {".pcx"}, - {"image/vnd.zbrush.pcx"}, - "Paintbrush bitmap image", - REFERENCE_URL, - ""}, - {"general.pbm-image", - {"general.image"}, - {".pbm"}, - {"image/x-portable-bitmap"}, - "Portable bitmap image", - REFERENCE_URL, - ""}, - {"general.pgm-image", - {"general.image"}, - {".pgm"}, - {"image/x-portable-graymap"}, - "Portable gray map image", - REFERENCE_URL, - ""}, - {"general.pnm-image", - {"general.image"}, - {".pnm"}, - {"image/x-portable-anymap"}, - "Portable any map image file", - REFERENCE_URL, - ""}, - {"general.ppm-image", - {"general.image"}, - {".ppm"}, - {"image/x-portable-pixmap"}, - "Portable pixmap image", - REFERENCE_URL, - ""}, - {"general.rgb-image", - {"general.image"}, - {".rgb"}, - {"image/x-rgb"}, - "RGB bitmap", - REFERENCE_URL, - ""}, - {"general.svg-image", - {"general.image"}, - {".svg", ".svgz"}, - {"image/svg+xml"}, - "Scalable vector graphic", - REFERENCE_URL, - ""}, - {"general.wbmp-image", - {"general.image"}, - {".wbmp"}, - {"image/vnd.wap.wbmp"}, - "Wireless bitmap image", - REFERENCE_URL, - ""}, - {"general.xpixmap-image", - {"general.image"}, - {".xpm"}, - {"image/x-xpixmap"}, - "X11 pixmap graphic", - REFERENCE_URL, - ""}, - {"general.xwindowdump-image", - {"general.image"}, - {".xwd"}, - {"image/x-xwindowdump"}, - "X windows dump image", - REFERENCE_URL, - ""}, - {"general.heif", - {"general.image"}, - {".heif", ".heifs", ".hif"}, - {"image/heif"}, - "High efficiency image format", - REFERENCE_URL, - ""}, - {"general.heic", - {"general.image"}, - {".heic", ".heics"}, - {"image/heic"}, - "High efficiency image format", - REFERENCE_URL, - ""}, - {"general.virtual-cd", - {"general.disk-image"}, - {".vcd"}, - {"application/x-cdlink"}, - "Virtual CD", - REFERENCE_URL, - ""}, - {"general.boo-source", - {"general.source-code"}, - {".boo"}, - {"text/x-boo"}, - "Boo source code", - REFERENCE_URL, - ""}, - {"general.d-source", - {"general.source-code"}, - {".d"}, - {"text/x-dsrc"}, - "D source code file", - REFERENCE_URL, - ""}, - {"general.html-component", - {"general.source-code"}, - {".htc"}, - {"text/x-component"}, - "HTML component", - REFERENCE_URL, - ""}, - {"general.pascal-source", - {"general.source-code"}, - {".p", ".pas"}, - {"text/x-pascal"}, - "Pascal source code", - REFERENCE_URL, - ""}, - {"general.haskell-script", - {"general.script"}, - {".hs"}, - {"text/x-haskell"}, - "Haskell script", - REFERENCE_URL, - ""}, - {"general.literate-haskell-script", - {"general.script"}, - {".lhs"}, - {"text/x-literate-haskell"}, - "Literate haskell script", - REFERENCE_URL, - ""}, - {"general.tcl-script", - {"general.script"}, - {".tcl"}, - {"text/x-tcl"}, - "Tcl script", - REFERENCE_URL, - ""}, - {"general.asc-text", - {"general.text"}, - {".asc"}, - {"text/plain"}, - "ASCII text file", - REFERENCE_URL, - ""}, - {"general.portable-object", - {"general.text"}, - {".po"}, - {"text/plain"}, - "Portable object", - REFERENCE_URL, - ""}, - {"general.rich-text", - {"general.text"}, - {".rtf", ".rtx"}, - {"text/rtf", "text/richtext"}, - "Rich text format file", - REFERENCE_URL, - ""}, - {"general.delimited-values-text", - {"general.text"}, - {}, - {}, - "Base type for delimited-values text", - REFERENCE_URL, - ""}, - {"general.comma-separated-values-text", - {"general.delimited-values-text"}, - {".csv"}, - {"text/csv"}, - "Comma-separated values file", - REFERENCE_URL, - ""}, - {"general.diff", - {"general.text"}, - {".diff"}, - {"text/plain"}, - "Patch file", - REFERENCE_URL, - ""}, - {"general.setext", - {"general.text"}, - {".etx"}, - {"text/x-setext"}, - "Structure enhanced Text", - REFERENCE_URL, - ""}, - {"general.gcd", - {"general.text"}, - {".gcd"}, - {"text/x-pcs-gcd"}, - "General content descriptor", - REFERENCE_URL, - ""}, - {"general.tab-separated-values-text", - {"general.delimited-values-text"}, - {".tsv"}, - {"text/tab-separated-values"}, - "Tab-Separated values file", - REFERENCE_URL, - ""}, - {"general.p7r", - {"general.text"}, - {".p7r"}, - {"application/x-pkcs7-certreqresp"}, - "Certificate request response file", - REFERENCE_URL, - ""}, - {"general.pem", - {"general.text"}, - {".pem"}, - {"application/x-pem-file"}, - "Privacy enhanced mail certificate", - REFERENCE_URL, - ""}, - {"general.chess-pgn", - {"general.plain-text"}, - {".pgn"}, - {"application/x-chess-pgn", "application/vnd.chess-pgn"}, - "Portable game notation file", - REFERENCE_URL, - ""}, - {"general.lha-archive", - {"general.archive"}, - {".lha"}, - {"application/x-lha"}, - "LHARC compressed archive", - REFERENCE_URL, - ""}, - {"general.lzh-archive", - {"general.archive"}, - {".lzh"}, - {"application/x-lzh"}, - "LZH compressed file", - REFERENCE_URL, - ""}, - {"general.lzx-archive", - {"general.archive"}, - {".lzx"}, - {"application/x-lzx"}, - "LZX compressed archive", - REFERENCE_URL, - ""}, - {"general.taz-archive", - {"general.tar-archive"}, - {".taz", ".tar.z", ".tz"}, - {"application/x-gtar"}, - "Tar zipped file", - REFERENCE_URL, - ""}, - {"general.shar-archive", - {"general.archive"}, - {".shar"}, - {"application/x-shar"}, - "Unix Shar archive", - REFERENCE_URL, - ""}, - {"general.cpio-archive", - {"general.archive"}, - {".cpio"}, - {"application/x-cpio"}, - "Unix CPIO archive", - REFERENCE_URL, - ""}, - {"general.web-archive", - {"general.archive"}, - {".mht", ".mhtml"}, - {"application/x-mimearchive"}, - "MHTML web archive", - REFERENCE_URL, - ""}, - {"general.ustar", - {"general.archive"}, - {".ustar"}, - {"application/x-ustar"}, - "Uniform standard tape archive format", - REFERENCE_URL, - ""}, - {"general.mathml", - {"general.xml"}, - {".mml"}, - {"text/mathml", "application/mathml+xml"}, - "Mathematical markup language file", - REFERENCE_URL, - ""}, - {"general.xhtml", - {"general.xml"}, - {".xhtml"}, - {"application/xhtml+xml"}, - "XHTML", - REFERENCE_URL, - ""}, - {"general.rss", - {"general.xml"}, - {".rss"}, - {"application/rss+xml"}, - "Rich site summary", - REFERENCE_URL, - ""}, - {"general.rdf", - {"general.xml"}, - {".rdf"}, - {"application/rdf+xml"}, - "Resource description framework file", - REFERENCE_URL, - ""}, - {"general.cad", - {"general.object"}, - {}, - {}, - "Base type for computer-aided design", - REFERENCE_URL, - ""}, - {"general.iges", - {"general.cad"}, - {".iges", ".igs"}, - {"model/iges"}, - "IGES drawing", - REFERENCE_URL, - ""}, - {"general.octet-stream", - {"general.object"}, - {}, - {"application/octet-stream"}, - "Arbitrary binary data", - REFERENCE_URL, - ""}, - {"general.iso", - {"general.disk-image"}, - {".iso"}, - {"application/x-iso9660-image"}, - "Disc image file", - REFERENCE_URL, - ""}, - {"general.mesh-model", - {"general.object"}, - {".msh", ".mesh", ".silo"}, - {"model/mesh"}, - "3D mesh model", - REFERENCE_URL, - ""}, - {"general.certificate", - {"general.object"}, - {}, - {}, - "Base type for security certificate", - REFERENCE_URL, - ""}, - {"general.c-object", - {"general.executable"}, - {".o"}, - {"application/x-object"}, - "Compiled C object file", - REFERENCE_URL, - ""}, - {"general.dvi", - {"general.tex"}, - {".dvi"}, - {"application/x-dvi"}, - "Device independent format file", - REFERENCE_URL, - ""}, - {"general.cer-certificate", - {"general.certificate"}, - {".cer"}, - {"application/pkix-cert"}, - "Internet security certificate", - REFERENCE_URL, - ""}, - {"general.crt-certificate", - {"general.certificate"}, - {".crt"}, - {"application/x-x509-ca-cert", "application/x-x509-server-cert", "application/x-x509-user-cert"}, - "Security Certificate", - REFERENCE_URL, - ""}, - {"general.crl-certificate", - {"general.certificate"}, - {".crl"}, - {"application/x-pkix-crl"}, - "Certificate revocation list file", - REFERENCE_URL, - ""}, - {"general.prn", - {"general.composite-object"}, - {".prn"}, - {}, - "Print to file", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.chart", - {"org.oasis.opendocument", "general.composite-object"}, - {".odc"}, - {"application/vnd.oasis.opendocument.chart"}, - "Open Document chart", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.text-master", - {"org.oasis.opendocument", "general.composite-object"}, - {".odm"}, - {"application/vnd.oasis.opendocument.text-master"}, - "Open Document text master", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.text-web", - {"org.oasis.opendocument", "general.composite-object"}, - {".oth"}, - {"application/vnd.oasis.opendocument.text-web"}, - "Open Document HTML template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.database", - {"org.oasis.opendocument", "general.database"}, - {".odb"}, - {"application/vnd.oasis.opendocument.database"}, - "Open Document database", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.image", - {"org.oasis.opendocument", "general.image"}, - {".odi"}, - {"application/vnd.oasis.opendocument.image"}, - "Open Document image", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.formula-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".otf"}, - {"application/vnd.oasis.opendocument.formula-template"}, - "Open Document formula template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.chart-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".otc"}, - {"application/vnd.oasis.opendocument.chart-template"}, - "Open Document chart template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.presentation-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".otp"}, - {"application/vnd.oasis.opendocument.presentation-template"}, - "Open Document presentation template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.image-template", - {"org.oasis.opendocument", "general.image"}, - {".oti"}, - {"application/vnd.oasis.opendocument.image-template"}, - "Open Document image template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.graphics-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".otg"}, - {"application/vnd.oasis.opendocument.graphics-template"}, - "Open Document graphics template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.spreadsheet-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".ots"}, - {"application/vnd.oasis.opendocument.spreadsheet-template"}, - "Open Document spreadsheet template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.text-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".ott"}, - {"application/vnd.oasis.opendocument.text-template"}, - "Open Document text template", - REFERENCE_URL, - ""}, - {"com.microsoft.word.dot", - {"general.composite-object"}, - {".dot"}, - {"application/msword"}, - "Microsoft Word document template", - REFERENCE_URL, - ""}, - {"com.microsoft.powerpoint.pps", - {"general.composite-object"}, - {".pps"}, - {"application/vnd.ms-powerpoint"}, - "Microsoft PowerPoint slide show", - REFERENCE_URL, - ""}, - {"com.microsoft.powerpoint.pot", - {"general.composite-object"}, - {".pot"}, - {"application/vnd.ms-powerpoint"}, - "Microsoft PowerPoint Template", - REFERENCE_URL, - ""}, - {"com.microsoft.excel.xlt", - {"general.composite-object"}, - {".xlt"}, - {"application/vnd.ms-excel"}, - "Microsoft Excel spreadsheet template", - REFERENCE_URL, - ""}, - {"com.microsoft.visio.vsd", - {"general.composite-object"}, - {".vsd"}, - {"application/vnd.visio"}, - "Microsoft Office Visio 2003-2010 drawing", - REFERENCE_URL, - ""}, - {"org.openxmlformats.drawingml.visio", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".vsdx"}, - {"application/vnd.openxmlformats-officedocument.drawingml.drawing"}, - "Microsoft Visio drawing", - REFERENCE_URL, - ""}, - {"org.openxmlformats.drawingml.template", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".vstx"}, - {}, - "Microsoft Visio drawing template", - REFERENCE_URL, - ""}, - {"org.openxmlformats.drawingml.visio.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".vsdm"}, - {}, - "Visio macro-enabled drawing", - REFERENCE_URL, - ""}, - {"org.openxmlformats.drawingml.template.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".vstm"}, - {}, - "Visio macro-enabled drawing template", - REFERENCE_URL, - ""}, - {"org.openxmlformats.wordprocessingml.template", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".dotx"}, - {"application/vnd.openxmlformats-officedocument.wordprocessingml.template"}, - "Office Open XML document template.", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.template", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".potx"}, - {"application/vnd.openxmlformats-officedocument.presentationml.template"}, - "Office Open XML presentation template", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.slideshow", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".ppsx"}, - {"application/vnd.openxmlformats-officedocument.presentationml.slideshow"}, - "Office Open XML slide show", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.template", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".xltx"}, - {"application/vnd.openxmlformats-officedocument.spreadsheetml.template"}, - "Office Open XML spreadsheet template", - REFERENCE_URL, - ""}, - {"org.openxmlformats.wordprocessingml.document.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".docm"}, - {"application/vnd.ms-word.document.macroEnabled.12"}, - "Office Open XML word processing document (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.wordprocessingml.template.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".dotm"}, - {"application/vnd.ms-word.template.macroEnabled.12"}, - "Office Open XML word processing template (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.template.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".xltm"}, - {"application/vnd.ms-excel.template.macroEnabled.12"}, - "Office Open XML spreadsheet template (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.addin.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".xlam"}, - {"application/vnd.ms-excel.addin.macroEnabled.12"}, - "Office Open XML spreadsheet addin (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.binary.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".xlsb"}, - {"application/vnd.ms-excel.sheet.binary.macroEnabled.12"}, - "Office Open XML spreadsheet binary (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.sheet.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".xlsm"}, - {"application/vnd.ms-excel.sheet.macroEnabled.12"}, - "Office Open XML spreadsheet (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.addin.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".ppam"}, - {"application/vnd.ms-powerpoint.addin.macroEnabled.12"}, - "Office Open XML presentation addin (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.presentation.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".pptm"}, - {"application/vnd.ms-powerpoint.presentation.macroEnabled.12"}, - "Office Open XML presentation (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.slideshow.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".ppsm"}, - {"application/vnd.ms-powerpoint.slideshow.macroEnabled.12"}, - "Office Open XML slide show (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.template.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".potm"}, - {"application/vnd.ms-powerpoint.template.macroEnabled.12"}, - "Office Open XML presentation template (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openoffice", - {"general.archive"}, - {}, - {}, - "OpenOffice document format for open-source office software suite", - REFERENCE_URL, - ""}, - {"org.openoffice.calc", - {"org.openoffice", "general.composite-object"}, - {".sxc"}, - {"application/vnd.sun.xml.calc"}, - "StarOffice Calc spreadsheet", - REFERENCE_URL, - ""}, - {"org.openoffice.draw", - {"org.openoffice", "general.composite-object"}, - {".sxd"}, - {"application/vnd.sun.xml.draw"}, - "StarOffice Drawing", - REFERENCE_URL, - ""}, - {"org.openoffice.writer-global", - {"org.openoffice", "general.composite-object"}, - {".sxg"}, - {"application/vnd.sun.xml.writer.global"}, - "Apache OpenOffice master document", - REFERENCE_URL, - ""}, - {"org.openoffice.impress", - {"org.openoffice", "general.composite-object"}, - {".sxi"}, - {"application/vnd.sun.xml.impress"}, - "StarOffice Impress presentation", - REFERENCE_URL, - ""}, - {"org.openoffice.math", - {"org.openoffice", "general.composite-object"}, - {".sxm"}, - {"application/vnd.sun.xml.math"}, - "StarMath Formula", - REFERENCE_URL, - ""}, - {"org.openoffice.writer", - {"org.openoffice", "general.composite-object"}, - {".sxw"}, - {"application/vnd.sun.xml.writer"}, - "StarOffice Writer document", - REFERENCE_URL, - ""}, - {"org.openoffice.calc.template", - {"org.openoffice", "general.composite-object"}, - {".stc"}, - {"application/vnd.sun.xml.calc.template"}, - "StarOffice Calc spreadsheet template", - REFERENCE_URL, - ""}, - {"org.openoffice.draw.template", - {"org.openoffice", "general.composite-object"}, - {".std"}, - {"application/vnd.sun.xml.draw.template"}, - "Apache OpenOffice Drawing template", - REFERENCE_URL, - ""}, - {"org.openoffice.impress.template", - {"org.openoffice", "general.composite-object"}, - {".sti"}, - {"application/vnd.sun.xml.impress.template"}, - "StarOffice Presentation template", - REFERENCE_URL, - ""}, - {"org.openoffice.writer.template", - {"org.openoffice", "general.composite-object"}, - {".stw"}, - {"application/vnd.sun.xml.writer.template"}, - "StarOffice Document template", - REFERENCE_URL, - ""}, - {"com.staroffice", - {"general.archive"}, - {}, - {}, - "StarOffice document format", - REFERENCE_URL, - ""}, - {"com.staroffice.draw", - {"com.staroffice", "general.composite-object"}, - {".sda"}, - {"application/vnd.stardivision.draw"}, - "StarOffice Drawing", - REFERENCE_URL, - ""}, - {"com.staroffice.calc", - {"com.staroffice", "general.composite-object"}, - {".sdc"}, - {"application/vnd.stardivision.calc"}, - "StarOffice Calc spreadsheet", - REFERENCE_URL, - ""}, - {"com.staroffice.impress", - {"com.staroffice", "general.composite-object"}, - {".sdd", ".sdp"}, - {"application/vnd.stardivision.impress"}, - "StarOffice Presentation", - REFERENCE_URL, - ""}, - {"com.staroffice.writer", - {"com.staroffice", "general.composite-object"}, - {".sdw"}, - {"application/vnd.stardivision.writer"}, - "StarOffice Writer text document", - REFERENCE_URL, - ""}, - {"com.staroffice.chart", - {"com.staroffice", "general.composite-object"}, - {".sds"}, - {"application/vnd.stardivision.chart"}, - "StarOffice Chart", - REFERENCE_URL, - ""}, - {"com.staroffice.mail", - {"com.staroffice", "general.composite-object"}, - {".sdm"}, - {"application/vnd.stardivision.mail"}, - "StarOffice Mail message", - REFERENCE_URL, - ""}, - {"com.staroffice.writer-global", - {"com.staroffice", "general.composite-object"}, - {".sgl"}, - {"application/vnd.stardivision.writer-global"}, - "StarOffice Master document", - REFERENCE_URL, - ""}, - {"com.staroffice.math", - {"com.staroffice", "general.composite-object"}, - {".smf"}, - {"application/vnd.stardivision.math"}, - "StarMath Formula file", - REFERENCE_URL, - ""}, - {"com.staroffice.template", - {"com.staroffice", "general.composite-object"}, - {".vor"}, - {"application/vnd.stardivision.template"}, - "StarOffice Template", - REFERENCE_URL, - ""}, - {"org.tug.bib", - {"general.tex"}, - {".bib"}, - {"text/x-bibtex"}, - "TeX Bibliography file", - REFERENCE_URL, - ""}, - {"org.tug.cls", - {"general.tex"}, - {".cls"}, - {"text/x-tex"}, - "TeX Class file", - REFERENCE_URL, - ""}, - {"org.tug.sty", - {"general.tex"}, - {".sty"}, - {"text/x-tex"}, - "TeX Style file", - REFERENCE_URL, - ""}, - {"org.tug.tex", - {"general.tex"}, - {".tex"}, - {"text/x-tex"}, - "TeX source document file", - REFERENCE_URL, - ""}, - {"org.latex-project.latex", - {"general.tex"}, - {".ltx", ".latex"}, - {"application/x-latex"}, - "LaTeX source document file", - REFERENCE_URL, - ""}, - {"org.matroska.mkv", - {"general.video"}, - {".mkv"}, - {"video/x-matroska"}, - "Matroska video", - REFERENCE_URL, - ""}, - {"org.matroska.mka", - {"general.audio"}, - {".mka"}, - {"audio/x-matroska"}, - "Matroska audio", - REFERENCE_URL, - ""}, - {"com.sgi.movie", - {"general.video"}, - {".movie"}, - {"video/x-sgi-movie"}, - "SGI movie", - REFERENCE_URL, - ""}, - {"com.apple.m4v", - {"general.video"}, - {".m4v"}, - {"video/m4v"}, - "M4V video", - REFERENCE_URL, - ""}, - {"org.webmproject.webm", - {"general.video"}, - {".webm"}, - {"video/webm"}, - "WebM is an audiovisual media file format", - REFERENCE_URL, - ""}, - {"com.apple.quicktime-movie", - {"general.video"}, - {".mov", ".qt", ".movie"}, - {"video/quicktime"}, - "QuickTime File Format", - REFERENCE_URL, - ""}, - {"com.coreldraw.cdr", - {"general.image"}, - {".cdr"}, - {"image/x-coreldraw"}, - "CorelDRAW file", - REFERENCE_URL, - ""}, - {"com.coreldraw.cdt", - {"general.image"}, - {".cdt"}, - {"image/x-coreldrawtemplate"}, - "CorelDRAW template", - REFERENCE_URL, - ""}, - {"com.coreldraw.cpt", - {"general.image"}, - {".cpt"}, - {"image/x-corelphotopaint"}, - "Corel PHOTO-PAINT image", - REFERENCE_URL, - ""}, - {"com.coreldraw.pat", - {"general.image"}, - {".pat"}, - {"image/x-coreldrawpattern"}, - "CorelDRAW pattern file", - REFERENCE_URL, - ""}, - {"com.microsoft.cur", - {"general.image"}, - {".cur"}, - {"image/ico"}, - "Microsoft Windows cursor image", - REFERENCE_URL, - ""}, - {"com.sun.raster", - {"general.image"}, - {".ras"}, - {"image/x-cmu-raster"}, - "Sun Raster Graphic", - REFERENCE_URL, - ""}, - {"com.google.webp", - {"general.image"}, - {".webp"}, - {"image/webp"}, - "WebP image", - REFERENCE_URL, - ""}, - {"com.sseyo.koan-audio", - {"general.audio"}, - {".skd", ".skm", ".skp", ".skt"}, - {"application/x-koan"}, - "Koan music files over the internet", - REFERENCE_URL, - ""}, - {"io.qt.moc", - {"general.source-code"}, - {".moc"}, - {"text/x-moc"}, - "Qt Meta-Object compiler file", - REFERENCE_URL, - ""}, - {"com.ghostscript.font", - {"general.font"}, - {".gsf"}, - {"application/x-font"}, - "Ghostscript font", - REFERENCE_URL, - ""}, - {"org.x.pcf-font", - {"general.font"}, - {".pcf"}, - {"application/x-font", "application/x-font-pcf"}, - "Portable compiled format", - REFERENCE_URL, - ""}, - {"com.microsoft.windows-media-wmd", - {"com.microsoft.advanced-systems-format", "general.zip-archive"}, - {".wmd"}, - {"application/x-ms-wmd"}, - "Windows media download package", - REFERENCE_URL, - ""}, - {"com.microsoft.windows-media-wmz", - {"com.microsoft.advanced-systems-format", "general.zip-archive"}, - {".wmz"}, - {"application/x-ms-wmz"}, - "Windows media player skin package", - REFERENCE_URL, - ""}, - {"com.microsoft.windows-installer", - {"general.executable"}, - {".msi"}, - {"application/x-msi"}, - "Windows installer package", - REFERENCE_URL, - ""}, - {"com.microsoft.publisher.pub", - {"general.composite-object"}, - {".pub"}, - {"application/x-mspublisher"}, - "Publisher document", - REFERENCE_URL, - ""}, - {"com.microsoft.windows-media-playlist", - {"general.xml", "general.media"}, - {".wpl"}, - {"application/vnd.ms-wpl"}, - "Windows media player playlist", - REFERENCE_URL, - ""}, - {"com.microsoft.access.mdb", - {"general.database"}, - {".mdb"}, - {"application/msaccess"}, - "Microsoft Access database", - REFERENCE_URL, - ""}, - {"com.3dsystems.stereolithography", - {"general.composite-object"}, - {".stl"}, - {"application/vnd.ms-pki.stl"}, - "Stereolithography file", - REFERENCE_URL, - ""}, - {"com.apple.media.playlist", - {"general.media"}, - {".m3u8"}, - {"application/vnd.apple.mpegurl"}, - "UTF-8 M3U playlist", - REFERENCE_URL, - ""}, - {"com.abisource.word", - {"general.composite-object"}, - {".abw"}, - {"application/x-abiword"}, - "AbiWord document", - REFERENCE_URL, - ""}, - {"com.adobe.framemaker", - {"general.composite-object"}, - {".book", ".fm", ".frame", ".maker"}, - {"application/x-maker"}, - "FrameMaker book file", - REFERENCE_URL, - ""}, - {"com.wolfram.cdf", - {"general.composite-object"}, - {".cdf"}, - {"application/x-cdf"}, - "Computable document format file", - REFERENCE_URL, - ""}, - {"de.cinderella.cdy", - {"general.composite-object"}, - {".cdy"}, - {"application/vnd.cinderella"}, - "Cinderella construction file", - REFERENCE_URL, - ""}, - {"com.adobe.dcr", - {"general.video"}, - {".dcr"}, - {"application/x-director"}, - "Shockwave media file", - REFERENCE_URL, - ""}, - {"com.adobe.dir", - {"general.video"}, - {".dir"}, - {"application/x-director"}, - "Adobe Director movie", - REFERENCE_URL, - ""}, - {"com.adobe.dxr", - {"general.video"}, - {".dxr"}, - {"application/x-director"}, - "Protected macromedia director movie", - REFERENCE_URL, - ""}, - {"org.gnumeric.spreadsheet", - {"general.xml"}, - {".gnumeric"}, - {"application/x-gnumeric"}, - "Gnumeric spreadsheet", - REFERENCE_URL, - ""}, - {"org.hdfgroup.hdf", - {"general.composite-object"}, - {".hdf"}, - {"application/x-hdf"}, - "Hierarchical data format", - REFERENCE_URL, - ""}, - {"com.apple.binhex-archive", - {"general.archive"}, - {".hqx"}, - {"application/mac-binhex40"}, - "BinHex 4.0 encoded file", - REFERENCE_URL, - ""}, - {"com.microsoft.hta", - {"general.archive", "general.executable"}, - {".hta"}, - {"application/hta"}, - "HTML application", - REFERENCE_URL, - ""}, - {"com.microsoft.internet.ins", - {"general.text"}, - {".ins"}, - {"application/x-internet-signup"}, - "Internet settings file", - REFERENCE_URL, - ""}, - {"com.microsoft.internet.isp", - {"general.text"}, - {".isp"}, - {"application/x-internet-signup"}, - "IIS internet service provider settings", - REFERENCE_URL, - ""}, - {"org.troff", - {"general.text"}, - {".man", ".t", ".roff"}, - {"text/troff"}, - "Unix troff format", - REFERENCE_URL, - ""}, - {"com.adobe.framemaker.mif", - {"general.composite-object"}, - {".mif"}, - {"application/vnd.mif"}, - "FrameMaker interchange format file", - REFERENCE_URL, - ""}, - {"io.sourceforge.freemind", - {"general.composite-object"}, - {".mm"}, - {"application/x-freemind"}, - "Mind Map file", - REFERENCE_URL, - ""}, - {"com.yamaha.smaf", - {"general.audio"}, - {".mmf"}, - {"application/vnd.smaf"}, - "Synthetic music mobile application file", - REFERENCE_URL, - ""}, - {"com.wolfram.mathematica.notebook", - {"general.text"}, - {".nb"}, - {"application/mathematica"}, - "Mathematica notebook", - REFERENCE_URL, - ""}, - {"org.xiph.ogg", - {"general.audio"}, - {".oga", ".ogg"}, - {"application/ogg"}, - "Ogg vorbis audio", - REFERENCE_URL, - ""}, - {"com.netscape.proxy-autoconfig", - {"general.plain-text"}, - {".pac"}, - {"application/x-ns-proxy-autoconfig"}, - "Proxy auto-config file", - REFERENCE_URL, - ""}, - {"com.rsa.pkcs-12", - {"general.archive"}, - {".pfx", ".p12"}, - {"application/x-pkcs12"}, - "PKCS #12 certificate file", - REFERENCE_URL, - ""}, - {"org.openpgp.signature", - {"general.object"}, - {".pgp"}, - {"application/pgp-signature"}, - "PGP security key", - REFERENCE_URL, - ""}, - {"com.apple.quicktime-link", - {"general.text"}, - {".qtl"}, - {"application/x-quicktimeplayer"}, - "QuickTime link file", - REFERENCE_URL, - ""}, - {"com.rarlab.rar-archive", - {"general.archive"}, - {".rar"}, - {"application/rar", "application/vnd.rar"}, - "WinRAR compressed archive", - REFERENCE_URL, - ""}, - {"org.7-zip.7-zip-archive", - {"general.archive"}, - {".7z"}, - {"application/x-7z-compressed"}, - "7-zip compressed archive", - REFERENCE_URL, - ""}, - {"com.red-bean.sgf", - {"general.text"}, - {".sgf"}, - {"application/x-go-sgf"}, - "Smart game format file", - REFERENCE_URL, - ""}, - {"com.stuffit.sit-archive", - {"general.archive"}, - {".sit"}, - {"application/x-stuffit"}, - "Stuffit archive", - REFERENCE_URL, - ""}, - {"com.adobe.futuresplash", - {"general.video"}, - {".spl"}, - {"application/futuresplash", "application/x-futuresplash"}, - "FutureSplash animation", - REFERENCE_URL, - ""}, - {"com.adobe.flash", - {"general.video"}, - {".swf", ".flv"}, - {"application/x-shockwave-flash", "video/x-flv"}, - "Shockwave flash movie", - REFERENCE_URL, - ""}, - {"org.gnu.texinfo", - {"general.source-code"}, - {".texinfo", ".texi"}, - {"application/x-texinfo"}, - "GNU Texinfo", - REFERENCE_URL, - ""}, - {"org.bittorrent.torrent", - {"general.text"}, - {".torrent"}, - {"application/x-bittorrent"}, - "BitTorrent file", - REFERENCE_URL, - ""}, - {"com.idsoftware.doom", - {"general.archive"}, - {".wad"}, - {"application/x-doom"}, - "Doom WAD file", - REFERENCE_URL, - ""}, - {"com.apple.webarchive", - {"general.archive"}, - {".webarchive"}, - {"application/x-webarchive"}, - "Safari web archive", - REFERENCE_URL, - ""}, - {"com.android.webarchive", - {"general.archive"}, - {".webarchivexml"}, - {"application/x-webarchive-xml"}, - "Android web browser archive", - REFERENCE_URL, - ""}, - {"org.gimp.xcf", - {"general.image"}, - {".xcf"}, - {"application/x-xcf", "image/x-xcf"}, - "eXperimental computing facility, GIMP image file", - REFERENCE_URL, - ""}, - {"com.edrawsoft.edrawmax", - {"general.composite-object"}, - {".eddx"}, - {"application/x-eddx"}, - "Edraw Max XML file", - REFERENCE_URL, - ""}, - {"com.edrawsoft.edrawmind", - {"general.composite-object"}, - {".emmx"}, - {"application/x-emmx"}, - "Edraw MindMaster XML file", - REFERENCE_URL, - ""}, - {"net.cnki.caj", - {"general.composite-object"}, - {".caj"}, - {"application/caj"}, - "Chinese academic journal file", - REFERENCE_URL, - ""}, - {"com.dbase.dbf", - {"general.database"}, - {".dbf"}, - {"application/dbf", "application/dbase"}, - "Database file", - REFERENCE_URL, - ""}, - {"com.autodesk.dwg", - {"general.composite-object"}, - {".dwg"}, - {"image/vnd.dwg"}, - "AutoCAD drawing", - REFERENCE_URL, - ""}, - {"com.autodesk.dxf", - {"general.composite-object"}, - {".dxf"}, - {"image/vnd.dxf"}, - "Drawing exchange format file", - REFERENCE_URL, - ""}, - {"com.autodesk.dws", - {"general.composite-object"}, - {".dws"}, - {}, - "AutoCAD drawing standards file", - REFERENCE_URL, - ""}, - {"com.autodesk.dwt", - {"general.composite-object"}, - {".dwt"}, - {}, - "AutoCAD drawing template", - REFERENCE_URL, - ""}, - {"com.autodesk.dwf", - {"general.composite-object"}, - {".dwf"}, - {"model/vnd.dwf"}, - "Design web format file", - REFERENCE_URL, - ""}, - {"com.autodesk.dwfx", - {"general.composite-object"}, - {".dwfx"}, - {}, - "Design web format XPS file", - REFERENCE_URL, - ""}, - {"com.autodesk.shp", - {"general.composite-object"}, - {".shp"}, - {}, - "3D studio shape", - REFERENCE_URL, - ""}, - {"com.autodesk.shx", - {"general.composite-object"}, - {".shx"}, - {}, - "AutoCAD compiled shape file", - REFERENCE_URL, - ""}, - {"com.autodesk.slide-library", - {"general.composite-object"}, - {".slb"}, - {}, - "AutoCAD slide library", - REFERENCE_URL, - ""}, - {"com.autodesk.line", - {"general.text"}, - {".lin"}, - {}, - "AutoCAD linetype file", - REFERENCE_URL, - ""}, - {"com.autodesk.plotter", - {"general.composite-object"}, - {".plt"}, - {}, - "AutoCAD plotter document", - REFERENCE_URL, - ""}, - {"com.hp.graphics-language", - {"general.composite-object"}, - {".hpgl"}, - {"application/vnd.hp-hpgl"}, - "HP graphics language plotter file", - REFERENCE_URL, - ""}, - {"com.microsoft.metafile", - {"general.composite-object"}, - {".wmf"}, - {}, - "Windows metafile", - REFERENCE_URL, - ""}, - {"com.spatial.acis.sat", - {"general.text"}, - {".sat"}, - {}, - "ACIS SAT 3D model", - REFERENCE_URL, - ""}, - {"org.aomedia.avif-image", - {"general.image"}, - {".avif"}, - {"image/avif"}, - "AVIF image", - REFERENCE_URL, - ""}, - {"com.microsoft.dds", - {"general.image"}, - {".dds"}, - {"image/vnd-ms.dds"}, - "DirectDraw surface image", - REFERENCE_URL, - ""}, - {"com.ea.iff-ilbm", - {"general.image"}, - {".ilbm"}, - {"image/x-ilbm"}, - "Interleaved bitmap image", - REFERENCE_URL, - ""}, - {"com.canon.cr2-raw-image", - {"general.raw-image"}, - {".cr2"}, - {"image/x-canon-cr2"}, - "Canon raw 2 image", - REFERENCE_URL, - ""}, - {"com.canon.cr3-raw-image", - {"general.raw-image"}, - {".cr3"}, - {"image/x-canon-cr3"}, - "Canon raw 3 image", - REFERENCE_URL, - ""}, - {"com.canon.crw-raw-image", - {"general.raw-image"}, - {".crw"}, - {"image/x-canon-crw"}, - "Canon raw CIFF image file", - REFERENCE_URL, - ""}, - {"com.adobe.dng-raw-image", - {"general.raw-image"}, - {".dng"}, - {"image/x-adobe-dng"}, - "Digital negative image", - REFERENCE_URL, - ""}, - {"com.sony.arw-raw-image", - {"general.raw-image"}, - {".arw"}, - {"image/x-sony-arw"}, - "Sony alpha raw digital camera image", - REFERENCE_URL, - ""}, - {"com.nikon.nef-raw-image", - {"general.raw-image"}, - {".nef"}, - {"image/x-nikon-nef"}, - "Nikon electronic format RAW image", - REFERENCE_URL, - ""}, - {"com.mindjet.mindmanager.mmap", - {"general.composite-object"}, - {".mmap"}, - {}, - "MindManager Map", - REFERENCE_URL, - ""}, - {"com.microsoft.email", - {"general.message"}, - {".eml"}, - {"message/rfc822"}, - "E-Mail message", - REFERENCE_URL, - ""}, - {"com.microsoft.message", - {"general.message"}, - {".msg"}, - {}, - "Outlook message item file", - REFERENCE_URL, - ""}, - {"com.microsoft.pst", - {"general.archive"}, - {".pst"}, - {}, - "Outlook personal information store", - REFERENCE_URL, - ""}, - {"com.kingsoft.office", - {"general.archive"}, - {}, - {}, - "Kingsoft office suite", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.writer.wps", - {"com.kingsoft.office", "general.composite-object"}, - {".wps"}, - {}, - "Kingsoft Writer document", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.writer.wpt", - {"com.kingsoft.office", "general.composite-object"}, - {".wpt"}, - {}, - "Kingsoft Writer template", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.presentation.dps", - {"com.kingsoft.office", "general.composite-object"}, - {".dps"}, - {}, - "Kingsoft Presentation file", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.presentation.template", - {"com.kingsoft.office", "general.composite-object"}, - {".dpt"}, - {}, - "Kingsoft Presentation template", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.spreadsheets.et", - {"com.kingsoft.office", "general.composite-object"}, - {".et"}, - {}, - "Kingsoft Spreadsheets tile", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.spreadsheets.template", - {"com.kingsoft.office", "general.composite-object"}, - {".ett"}, - {}, - "Kingsoft Spreadsheets template", - REFERENCE_URL, - ""}, - {"com.microsoft.ini", - {"general.text"}, - {".ini"}, - {}, - "Windows Initialization File", - REFERENCE_URL, - ""}, - {"general.json", - {"general.script"}, - {".json"}, - {"application/json"}, - "JavaScript Object Notation File", - REFERENCE_URL, - ""}, - {"general.yaml", - {"general.script"}, - {".yaml", ".yml"}, - {"application/yaml"}, - "YAML Document", - REFERENCE_URL, - ""}, - {"general.log", - {"general.text"}, - {".log"}, - {"text/plain"}, - "Log File", - REFERENCE_URL, - ""}, - {"general.uri", - {"general.object"}, - {}, - {}, - "Universal Resource Identifier", - REFERENCE_URL, - ""}, - {"general.file-uri", - {"general.uri"}, - {}, - {}, - "File URI", - REFERENCE_URL, - ""}, - {"general.text-lst", - {"general.plain-text"}, - {".lst"}, - {}, - "Data List", - REFERENCE_URL, - ""}, - {"com.android.apk", - {"general.archive"}, - {".apk", ".apks", ".aab", ".xapk", ".apkm", ".akp"}, - {"application/vnd.android.package-archive"}, - "Android Package File", - REFERENCE_URL, - ""}, - {"com.adobe.postscript-pfb-font", - {"com.adobe.postscript-font"}, - {".pfb"}, - {"application/x-font"}, - "Printer Font Binary, PostScript Type 1 outline font.", - REFERENCE_URL, - ""}, - {"com.adobe.postscript-pfa-font", - {"com.adobe.postscript-font"}, - {".pfa"}, - {"application/x-font"}, - "Printer Pont ASCII file, PostScript Type 1 outline font.", - REFERENCE_URL, - ""}, - {"general.bz-archive", - {"general.archive"}, - {".bz"}, - {"application/x-bzip"}, - "Bzip Compressed File", - REFERENCE_URL, - ""}, - {"general.tar-bzip-archive", - {"general.bz-archive"}, - {".tbz"}, - {"application/x-bzip-compressed-tar"}, - "Bzip Compressed Tar Archive", - REFERENCE_URL, - ""}, - {"general.tar-bzip2-archive", - {"general.bz2-archive"}, - {".tbz2"}, - {"application/x-bzip2-compressed-tar"}, - "Bzip2-Compressed TAR File", - REFERENCE_URL, - ""}, - {"org.tukaani.xz-archive", - {"general.archive"}, - {".xz"}, - {"application/x-xz"}, - "XZ Compressed Archive", - REFERENCE_URL, - ""}, - {"org.tukaani.tar-xz-archive", - {"org.tukaani.xz-archive"}, - {".txz"}, - {"application/x-xz-compressed-tar"}, - "XZ Compressed Tar Archive", - REFERENCE_URL, - ""}, - {"general.xar-archive", - {"general.archive"}, - {".xar"}, - {"application/x-xar"}, - "Extensible Archive Fromat", - REFERENCE_URL, - ""}, - {"com.microsoft.cab-archive", - {"general.archive"}, - {".cab"}, - {"application/vnd.ms-cab-compressed"}, - "Windows Cabinet File", - REFERENCE_URL, - ""}, - {"redhat.rpm-archive", - {"general.archive"}, - {".rpm"}, - {"application/x-rpm"}, - "RedHat Package Manager File", - REFERENCE_URL, - ""}, - {"org.godotengine.tpz-archive", - {"general.archive"}, - {".tpz"}, - {}, - "Godot Engine Export Template Archive", - REFERENCE_URL, - ""}, - {"general.lza-archive", - {"general.archive"}, - {".lza"}, - {"application/x-lzh-compressed"}, - "LZA Compressed Archive", - REFERENCE_URL, - ""}, - {"general.arj-archive", - {"general.archive"}, - {".arj"}, - {"application/x-arj"}, - "ARJ Compressed File Archive", - REFERENCE_URL, - ""}, - {"com.winzip.zipx", - {"general.archive"}, - {".zipx"}, - {}, - "Extended Zip Archive", - REFERENCE_URL, - ""}, - {"general.lzma-archive", - {"general.archive"}, - {".lzma"}, - {"application/x-lzma"}, - "LZMA Compressed File", - REFERENCE_URL, - ""}, - {"general.lzma86-archive", - {"general.archive"}, - {".lzma86"}, - {}, - "LZMA86 Compressed File", - REFERENCE_URL, - ""}, - {"org.mozilla.xpinstall", - {"general.archive"}, - {".xpi"}, - {"application/x-xpinstall"}, - "Cross-platform Installer Package", - REFERENCE_URL, - ""}, - {"general.hfs-disk-image", - {"general.disk-image"}, - {".hfs"}, - {}, - "HFS Disk Image File", - REFERENCE_URL, - ""}, - {"general.img-disk-image", - {"general.disk-image"}, - {".img"}, - {"application/x-raw-disk-image"}, - "Disc Image Data File", - REFERENCE_URL, - ""}, - {"com.ezbsystems.zipped-iso", - {"general.disk-image"}, - {".isz"}, - {}, - "Zipped ISO Disk Image", - REFERENCE_URL, - ""}, - {"com.microsoft.wim", - {"general.disk-image"}, - {".wim"}, - {"application/x-ms-wim"}, - "Windows Imaging Format File", - REFERENCE_URL, - ""}, - {"com.microsoft.swm", - {"general.disk-image"}, - {".swm"}, - {"application/x-ms-wim"}, - "Split Windows Imaging Format", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.spreadsheets.etx", - {"com.kingsoft.office", "general.composite-object"}, - {".etx"}, - {}, - "Kingsoft Spreadsheets File", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.spreadsheets.ettx", - {"com.kingsoft.office", "general.composite-object"}, - {".ettx"}, - {}, - "Kingsoft Spreadsheets Template", - REFERENCE_URL, - ""}, - {"com.microsoft.excel.dif", - {"general.composite-object"}, - {".dif"}, - {}, - "Data interchange format", - REFERENCE_URL, - ""}, - {"openharmony.app", - {"openharmony.package"}, - {".app"}, - {}, - "OpenHarmony system defined application package", - REFERENCE_URL, - ""}, - {"com.huawei.hmos.settings.wifi", - {"general.text"}, - {".hmoswifi"}, - {}, - "HarmonyOS WIFI sharing setting", - REFERENCE_URL, - ""}, - {"general.tel", - {"general.text"}, - {".tel"}, - {}, - "TEL schematic diagram file format", - REFERENCE_URL, - ""}, - {"general.ets", - {"general.script"}, - {".ets"}, - {}, - "Extended TypeScript source code", - REFERENCE_URL, - ""}, - {"general.json5", - {"general.script"}, - {".json5"}, - {}, - "JSON5 data interchange format", - REFERENCE_URL, - ""}, - {"com.monkeysaudio.ape-audio", - {"general.audio"}, - {".ape"}, - {"audio/x-monkeys-audio"}, - "Monkey's Audio", - REFERENCE_URL, - ""}, - {"org.xiph.opus-audio", - {"general.audio"}, - {".opus"}, - {"audio/opus"}, - "Opus Audio", - REFERENCE_URL, - ""}, - {"general.conf", - {"general.text"}, - {".conf"}, - {}, - "Generic Configuration File", - REFERENCE_URL, - ""}, - {"com.microsoft.dos-batch", - {"general.script"}, - {".bat"}, - {"application/x-bat"}, - "DOS Batch File", - REFERENCE_URL, - ""}, - {"com.microsoft.vbscript", - {"general.script"}, - {".vbs"}, - {"application/x-vbs"}, - "VBScript File", - REFERENCE_URL, - ""}, - {"general.ion", - {"general.text"}, - {".ion"}, - {}, - "File Description File", - REFERENCE_URL, - ""}, - {"com.microsoft.registry", - {"general.database"}, - {".reg"}, - {}, - "Registry File", - REFERENCE_URL, - ""}, - {"com.microsoft.catalog", - {"general.object"}, - {".cat"}, - {}, - "Windows Catalog File", - REFERENCE_URL, - ""}, - {"com.microsoft.powershell-script", - {"general.script"}, - {".ps1"}, - {}, - "Windows PowerShell Cmdlet File", - REFERENCE_URL, - ""}, - {"org.w3.woff", - {"general.font"}, - {".woff"}, - {"font/woff"}, - "Web Open Font Format File", - REFERENCE_URL, - ""}, - {"org.sqlite.database", - {"general.database"}, - {".sqlite", ".sqlite3", ".db", ".db3", ".s3db", ".sl3"}, - {"application/vnd.sqlite3"}, - "SQLite Database", - REFERENCE_URL, - ""}, - {"com.microsoft.sys", - {"general.object"}, - {".sys"}, - {}, - "Windows System File", - REFERENCE_URL, - ""}, - {"com.microsoft.inf", - {"general.text"}, - {".inf"}, - {"text/plain"}, - "Setup Information File", - REFERENCE_URL, - ""}, - {"com.microsoft.pdb", - {"general.database"}, - {".pdb"}, - {"application/x-ms-pdb"}, - "Program Database", - REFERENCE_URL, - ""}, - {"com.microsoft.tlb", - {"general.object"}, - {".tlb"}, - {}, - "OLE Type Library", - REFERENCE_URL, - ""}, - {"com.microsoft.sccd", - {"general.xml"}, - {".sccd"}, - {}, - "Signed Custom Capability Descriptor", - REFERENCE_URL, - ""}, - {"com.adobe.f4v", - {"general.video"}, - {".f4v"}, - {"video/mp4"}, - "Flash MP4 Video File", - REFERENCE_URL, - ""}, - {"general.mp2t", - {"general.video"}, - {".m2ts", ".mts", ".m2t"}, - {"video/mp2t"}, - "Blu-ray BDAV Video File Format", - REFERENCE_URL, - ""}, - {"com.youtube.video", - {"general.video"}, - {".yt", ".vt"}, - {"video/vnd.youtube.yt"}, - "Youtube Video format", - REFERENCE_URL, - ""}, - {"com.cisco.webex-video", - {"general.video"}, - {".wrf"}, - {"video/x-webex"}, - "WebEx Recording", - REFERENCE_URL, - ""}, - {"general.mpeg-2", - {"general.video"}, - {".mpeg2", ".mpv2", ".mp2v", ".m2v", ".mpv"}, - {"video/mpeg"}, - "MPEG-2 Video format", - REFERENCE_URL, - ""}, - {"general.mpeg-1", - {"general.video"}, - {".mpeg1", ".mpv1", ".mp1v", ".m1v"}, - {"video/mpeg"}, - "MPEG-1 Video format", - REFERENCE_URL, - ""}, - {"com.real.realmedia-vbr", - {"general.video"}, - {".rmvb"}, - {"application/vnd.rn-realmedia-vbr"}, - "RealMedia Variable Bit Rate Format", - REFERENCE_URL, - ""}, - {"com.real.realvideo", - {"general.video"}, - {".rv"}, - {"video/x-pn-realvideo"}, - "RealVideo Format", - REFERENCE_URL, - ""}, - {"general.divx-video", - {"general.video"}, - {".divx"}, - {"video/divx"}, - "DivX-Encoded Movie", - REFERENCE_URL, - ""}, - {"org.csiro.annodex", - {"general.video"}, - {".axv"}, - {"video/annodex"}, - "Annodex Video Format", - REFERENCE_URL, - ""}, - {"general.ogv", - {"general.video"}, - {".ogv"}, - {"video/ogg"}, - "Ogg Video Format", - REFERENCE_URL, - ""}, - {"com.microsoft.lsf-video", - {"general.video"}, - {".lsf", ".lsx"}, - {"video/x-la-asf"}, - "Streaming Media Format", - REFERENCE_URL, - ""}, - {"general.h264-video", - {"general.video"}, - {".h264"}, - {"video/H264"}, - "H.264 Encoded Video Format", - REFERENCE_URL, - ""}, - {"general.jpeg-2000", - {"general.image"}, - {".jp2", ".jpg2", ".jpx", ".jpf", ".jpm"}, - {"image/jp2", "image/jpx", "image/jpm"}, - "JPEG 2000 Image", - REFERENCE_URL, - ""}, - {"com.fujifilm.raf-raw-image", - {"general.raw-image"}, - {".raf"}, - {"image/x-fuji-raf"}, - "Fujifilm RAW Image", - REFERENCE_URL, - ""}, - {"com.nikon.nrw-raw-image", - {"general.raw-image"}, - {".nrw"}, - {"image/x-nikon-nrw"}, - "Nikon Raw Image", - REFERENCE_URL, - ""}, - {"com.panasonic.rw2-raw-image", - {"general.raw-image"}, - {".rw2", ".raw"}, - {"image/x-panasonic-raw"}, - "Panasonic RAW Image", - REFERENCE_URL, - ""}, - {"com.pentax.pef-raw-image", - {"general.raw-image"}, - {".pef"}, - {"image/x-pentax-pef"}, - "Pentax Electronic RAW Image", - REFERENCE_URL, - ""}, - {"com.sumsung.srw-raw-image", - {"general.raw-image"}, - {".srw"}, - {"image/x-samsung-srw"}, - "Samsung RAW Image", - REFERENCE_URL, - ""}, - {"com.epson.erf-raw-image", - {"general.raw-image"}, - {".erf"}, - {"image/x-epson-erf"}, - "Epson RAW Imager", - REFERENCE_URL, - ""}, - {"com.olympus.orf-raw-image", - {"general.raw-image"}, - {".orf"}, - {"image/x-olympus-orf"}, - "Olympus RAW Image", - REFERENCE_URL, - ""}, - {"general.ief-image", - {"general.image"}, - {".ief"}, - {"image/ief"}, - "Image Exchange Format", - REFERENCE_URL, - ""}, - {"com.aol.art-image", - {"general.image"}, - {".art"}, - {"image/x-jg"}, - "ART image format", - REFERENCE_URL, - ""}, - {"general.content-form", - {"general.object"}, - {}, - {}, - "Content form format", - REFERENCE_URL, - ""}, - {"com.apple.m4p-audio", - {"general.audio"}, - {".m4p"}, - {"audio/mp4"}, - "iTunes Music Store Audio File Format", - REFERENCE_URL, - ""}, - {"general.ac3-audio", - {"general.audio"}, - {".ac3"}, - {"audio/ac3"}, - "Audio Codec 3 File Format", - REFERENCE_URL, - ""}, - {"openharmony.hsp", - {"openharmony.package"}, - {".hsp"}, - {}, - "Harmony Shared Package", - REFERENCE_URL, - ""}, - {"openharmony.har", - {"openharmony.package"}, - {".har"}, - {}, - "Harmony Archive", - REFERENCE_URL, - ""}, - {"openharmony.gopaint", - {"general.archive"}, - {".gopaint"}, - {}, - "Gopaint file format defined for Openharmony", - REFERENCE_URL, - ""}, - {"openharmony.gobrush", - {"general.archive"}, - {".gobrush"}, - {}, - "Gobrush file format defined for Openharmony", - REFERENCE_URL, - ""}, - {"openharmony.gobrushes", - {"general.archive"}, - {".gobrushes"}, - {}, - "Gobrushes file format defined for Openharmony", - REFERENCE_URL, - ""}, - {"openharmony.gocolor", - {"general.archive"}, - {".gocolor"}, - {}, - "Gocolor file format defined for Openharmony", - REFERENCE_URL, - ""} - }; + if (!typeDescriptors_.empty()) { + LOG_INFO(UDMF_CLIENT, "Preset type descriptors already init, utd size is %{public}zu", + typeDescriptors_.size()); + return; + } + std::ifstream fin(std::string(UTD_CONF_PATH) + std::string(UNIFORM_DATA_TYPES_JSON_PATH)); + if (!fin.good()) { + LOG_ERROR(UDMF_CLIENT, "Failed to open uniform data types json file"); + return; + } + std::ostringstream oss; + std::string line; + while (std::getline(fin, line)) { + oss << line; + } + fin.close(); + CustomUtdJsonParser utdJsonParser; + cJSON* jsonRoot = cJSON_Parse(oss.str().c_str()); + if (jsonRoot != NULL && cJSON_IsObject(jsonRoot)) { + std::lock_guard<std::recursive_mutex> lock(mutex_); + if (!typeDescriptors_.empty()) { + LOG_INFO(UDMF_CLIENT, "Preset type descriptors already init, utd size is %{public}zu", + typeDescriptors_.size()); + cJSON_Delete(jsonRoot); + return; + } + utdJsonParser.GetTypeDescriptors(*jsonRoot, UTD_CUSTOM_DECLARATION, typeDescriptors_); + } + cJSON_Delete(jsonRoot); + LOG_INFO(UDMF_CLIENT, "Preset type descriptors init success, utd size is %{public}zu", typeDescriptors_.size()); }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/preset_type_descriptors.h b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.h index 6a57164c..546d03c4 100644 --- a/udmf/framework/innerkitsimpl/data/preset_type_descriptors.h +++ b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.h @@ -15,6 +15,7 @@ #ifndef UDMF_PRESET_TYPE_DESCRIPTORS #define UDMF_PRESET_TYPE_DESCRIPTORS #include <string> +#include <mutex> #include "error_code.h" #include "utd_common.h" #include "visibility.h" @@ -30,7 +31,8 @@ private: PresetTypeDescriptors(const PresetTypeDescriptors &obj) = delete; PresetTypeDescriptors &operator=(const PresetTypeDescriptors &obj) = delete; void InitDescriptors(); - std::vector<TypeDescriptorCfg> typeDescriptors_; + std::vector<TypeDescriptorCfg> typeDescriptors_ {}; + mutable std::recursive_mutex mutex_; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/system_defined_appitem.cpp b/udmf/framework/innerkitsimpl/data/system_defined_appitem.cpp index 2aea430c..9bda1294 100644 --- a/udmf/framework/innerkitsimpl/data/system_defined_appitem.cpp +++ b/udmf/framework/innerkitsimpl/data/system_defined_appitem.cpp @@ -37,7 +37,6 @@ SystemDefinedAppItem::SystemDefinedAppItem(UDType type, ValueType value) : Syste if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); } - hasObject_ = true; } } diff --git a/udmf/framework/innerkitsimpl/data/system_defined_form.cpp b/udmf/framework/innerkitsimpl/data/system_defined_form.cpp index d7d3c382..0c7f5c69 100644 --- a/udmf/framework/innerkitsimpl/data/system_defined_form.cpp +++ b/udmf/framework/innerkitsimpl/data/system_defined_form.cpp @@ -36,7 +36,6 @@ SystemDefinedForm::SystemDefinedForm(UDType type, ValueType value) : SystemDefin if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); } - hasObject_ = true; } } diff --git a/udmf/framework/innerkitsimpl/data/system_defined_pixelmap.cpp b/udmf/framework/innerkitsimpl/data/system_defined_pixelmap.cpp index e98789df..7f8cb419 100644 --- a/udmf/framework/innerkitsimpl/data/system_defined_pixelmap.cpp +++ b/udmf/framework/innerkitsimpl/data/system_defined_pixelmap.cpp @@ -16,9 +16,15 @@ #include "system_defined_pixelmap.h" #include "logger.h" +#include "pixelmap_loader.h" namespace OHOS { namespace UDMF { +static constexpr size_t BYTES_PER_COLOR = sizeof(uint32_t); +static constexpr const char* PIXEL_MAP_WIDTH = "width"; +static constexpr const char* PIXEL_MAP_HEIGHT = "height"; +static constexpr const char* PIXEL_MAP_FORMAT = "pixel-format"; +static constexpr const char* PIXEL_MAP_ALPHA_TYPE = "alpha-type"; SystemDefinedPixelMap::SystemDefinedPixelMap() { SetType(SYSTEM_DEFINED_PIXEL_MAP); @@ -38,21 +44,16 @@ SystemDefinedPixelMap::SystemDefinedPixelMap(UDType type, ValueType value) : Sys return; } else if (std::holds_alternative<std::shared_ptr<OHOS::Media::PixelMap>>(value)) { auto pixelMap = std::get<std::shared_ptr<OHOS::Media::PixelMap>>(value); - if (!pixelMap->EncodeTlv(rawData_)) { - LOG_ERROR(UDMF_KITS_INNER, "pixelMap encode fail!"); - } + ParseInfoFromPixelMap(pixelMap); } else if (std::holds_alternative<std::shared_ptr<Object>>(value)) { auto object = std::get<std::shared_ptr<Object>>(value); auto it = object->value_.find(PIXEL_MAP); - hasObject_ = true; if (it == object->value_.end()) { return; } if (std::holds_alternative<std::shared_ptr<OHOS::Media::PixelMap>>(it->second)) { auto pixelMap = std::get<std::shared_ptr<OHOS::Media::PixelMap>>(it->second); - if (!pixelMap->EncodeTlv(rawData_)) { - LOG_ERROR(UDMF_KITS_INNER, "pixelMap encode fail!"); - } + ParseInfoFromPixelMap(pixelMap); } else if (std::holds_alternative<std::vector<uint8_t>>(it->second)) { rawData_ = std::get<std::vector<uint8_t>>(it->second); } @@ -75,9 +76,9 @@ void SystemDefinedPixelMap::SetRawData(const std::vector<uint8_t> &rawData) this->rawData_ = rawData; if (std::holds_alternative<std::shared_ptr<Object>>(value_)) { auto object = std::get<std::shared_ptr<Object>>(value_); - auto pixelMap = std::shared_ptr<OHOS::Media::PixelMap>(OHOS::Media::PixelMap::DecodeTlv(rawData_)); + auto pixelMap = GetPixelMapFromRawData(); if (pixelMap == nullptr) { - LOG_ERROR(UDMF_KITS_INNER, "pixelMap decode fail!"); + LOG_ERROR(UDMF_KITS_INNER, "Get pixelMap from rawData fail!"); object->value_[PIXEL_MAP] = rawData; return; } @@ -91,9 +92,9 @@ void SystemDefinedPixelMap::InitObject() auto value = value_; value_ = std::make_shared<Object>(); auto object = std::get<std::shared_ptr<Object>>(value_); - auto pixelMap = std::shared_ptr<OHOS::Media::PixelMap>(OHOS::Media::PixelMap::DecodeTlv(rawData_)); + auto pixelMap = GetPixelMapFromRawData(); if (pixelMap == nullptr) { - LOG_ERROR(UDMF_KITS_INNER, "pixelMap decode fail!"); + LOG_WARN(UDMF_KITS_INNER, "Get pixelMap from rawData fail!"); object->value_[PIXEL_MAP] = rawData_; } else { object->value_[PIXEL_MAP] = pixelMap; @@ -103,5 +104,53 @@ void SystemDefinedPixelMap::InitObject() object->value_.insert_or_assign(VALUE_TYPE, std::move(value)); } } + +std::shared_ptr<OHOS::Media::PixelMap> SystemDefinedPixelMap::GetPixelMapFromRawData() +{ + if (rawData_.empty()) { + LOG_WARN(UDMF_KITS_INNER, "No RawData"); + return nullptr; + } + if (rawData_.size() % BYTES_PER_COLOR != 0) { + LOG_ERROR(UDMF_KITS_INNER, "RawData size error, size = %{public}zu", rawData_.size()); + return nullptr; + } + auto details = ObjectUtils::ConvertToObject(details_); + if (details == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "No details"); + return nullptr; + } + PixelMapDetails pixelMapDetails; + pixelMapDetails.rawData = std::ref(rawData_); + pixelMapDetails.width = details->GetValue(PIXEL_MAP_WIDTH, pixelMapDetails.width) ? pixelMapDetails.width : -1; + pixelMapDetails.height = details->GetValue(PIXEL_MAP_HEIGHT, pixelMapDetails.height) ? pixelMapDetails.height : -1; + pixelMapDetails.pixelFormat = details->GetValue(PIXEL_MAP_FORMAT, pixelMapDetails.pixelFormat) + ? pixelMapDetails.pixelFormat : static_cast<int32_t>(OHOS::Media::PixelFormat::UNKNOWN); + PixelMapLoader loader; + return loader.GetPixelMapFromRawData(pixelMapDetails); +} + +void SystemDefinedPixelMap::ParseInfoFromPixelMap(std::shared_ptr<OHOS::Media::PixelMap> pixelMap) +{ + if (pixelMap == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "PixelMap is null"); + return; + } + PixelMapLoader loader; + auto details = loader.ParseInfoFromPixelMap(pixelMap); + if (details == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "Parse info failed"); + return; + } + details_[PIXEL_MAP_WIDTH] = details->width; + details_[PIXEL_MAP_HEIGHT] = details->height; + details_[PIXEL_MAP_FORMAT] = details->pixelFormat; + details_[PIXEL_MAP_ALPHA_TYPE] = details->alphaType; + if (!details->rawDataResult.has_value()) { + LOG_ERROR(UDMF_KITS_INNER, "No rawData"); + return; + } + rawData_ = std::move(*details->rawDataResult); +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/system_defined_record.cpp b/udmf/framework/innerkitsimpl/data/system_defined_record.cpp index 4da832b8..31f33452 100644 --- a/udmf/framework/innerkitsimpl/data/system_defined_record.cpp +++ b/udmf/framework/innerkitsimpl/data/system_defined_record.cpp @@ -35,7 +35,6 @@ SystemDefinedRecord::SystemDefinedRecord(UDType type, ValueType value) : Unified if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); } - hasObject_ = true; } } diff --git a/udmf/framework/innerkitsimpl/data/text.cpp b/udmf/framework/innerkitsimpl/data/text.cpp index 55323253..9554e06d 100644 --- a/udmf/framework/innerkitsimpl/data/text.cpp +++ b/udmf/framework/innerkitsimpl/data/text.cpp @@ -35,7 +35,6 @@ Text::Text(UDType type, ValueType value) : UnifiedRecord(type, value) if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); } - hasObject_ = true; } } diff --git a/udmf/framework/innerkitsimpl/data/type_descriptor.cpp b/udmf/framework/innerkitsimpl/data/type_descriptor.cpp index 64f488bd..19dffbf0 100644 --- a/udmf/framework/innerkitsimpl/data/type_descriptor.cpp +++ b/udmf/framework/innerkitsimpl/data/type_descriptor.cpp @@ -59,33 +59,27 @@ bool TypeDescriptor::CmpFlexibleTypeLevel(const std::string higherLevelTypeId, b } } } - LOG_INFO(UDMF_CLIENT, "The current utd[%{public}s] belongings is not belong[] %{public}s,", - typeId_.c_str(), higherLevelTypeId.c_str()); return false; } Status TypeDescriptor::BelongsTo(const std::string &typeId, bool &checkResult) { + if (typeId_ == typeId) { + checkResult = true; + return Status::E_OK; + }; checkResult = false; bool isFlexibleType = typeId.find(FLEXIBLE_TYPE_FLAG) != typeId_.npos; if (!UtdGraph::GetInstance().IsValidType(typeId) && !isFlexibleType) { - LOG_ERROR(UDMF_CLIENT, "invalid para. %{public}s,", typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid para"); return Status::E_INVALID_PARAMETERS; } if (isFlexibleType_) { - if (typeId_ == typeId) { - checkResult = true; - return Status::E_OK; - }; checkResult = CmpFlexibleTypeLevel(typeId, isFlexibleType); return Status::E_OK; } - if (typeId_ == typeId) { - checkResult = true; - return Status::E_OK; - }; checkResult = UtdGraph::GetInstance().IsLowerLevelType(typeId, typeId_); return Status::E_OK; } @@ -95,7 +89,7 @@ Status TypeDescriptor::IsLowerLevelType(const std::string &typeId, bool &checkRe checkResult = false; bool isFlexibleType = typeId.find(FLEXIBLE_TYPE_FLAG) != typeId_.npos; if (!UtdGraph::GetInstance().IsValidType(typeId) && !isFlexibleType) { - LOG_ERROR(UDMF_CLIENT, "invalid para. %{public}s,", typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid para"); return Status::E_INVALID_PARAMETERS; } if (isFlexibleType_) { @@ -115,7 +109,7 @@ Status TypeDescriptor::IsHigherLevelType(const std::string &typeId, bool &checkR checkResult = false; bool isFlexibleType = typeId.find(FLEXIBLE_TYPE_FLAG) != typeId_.npos; if (!UtdGraph::GetInstance().IsValidType(typeId) && !isFlexibleType) { - LOG_ERROR(UDMF_CLIENT, "invalid para. %{public}s,", typeId.c_str()); + LOG_ERROR(UDMF_CLIENT, "invalid para"); return Status::E_INVALID_PARAMETERS; } if (isFlexibleType_) { // flexibleType cannot be other type height level. diff --git a/udmf/framework/innerkitsimpl/data/unified_data.cpp b/udmf/framework/innerkitsimpl/data/unified_data.cpp index 77b50133..eaa09096 100644 --- a/udmf/framework/innerkitsimpl/data/unified_data.cpp +++ b/udmf/framework/innerkitsimpl/data/unified_data.cpp @@ -14,7 +14,6 @@ */ #define LOG_TAG "UnifiedData" #include "logger.h" -#include "udmf_utils.h" #include "unified_data.h" #include "utd_client.h" @@ -22,15 +21,12 @@ namespace OHOS { namespace UDMF { static const std::set<std::string> FILE_TYPES = { "general.file", "general.image", "general.video", "general.audio", "general.folder", "general.file-uri" }; -static const std::set<std::string> FILE_SUB_TYPES = { - "general.image", "general.video", "general.audio", "general.folder" }; static constexpr const char *RECORDS_TANSFER_TAG = "records_to_entries_data_format"; UnifiedData::UnifiedData() { properties_ = std::make_shared<UnifiedDataProperties>(); auto duration = std::chrono::system_clock::now().time_since_epoch(); properties_->timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); - sdkVersion_ = UTILS::GetCurrentSdkVersion(); } UnifiedData::UnifiedData(std::shared_ptr<UnifiedDataProperties> properties) @@ -42,7 +38,6 @@ UnifiedData::UnifiedData(std::shared_ptr<UnifiedDataProperties> properties) properties_ = properties; auto duration = std::chrono::system_clock::now().time_since_epoch(); properties_->timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(); - sdkVersion_ = UTILS::GetCurrentSdkVersion(); } int64_t UnifiedData::GetSize() @@ -113,9 +108,7 @@ std::vector<std::string> UnifiedData::GetTypesLabels() const { std::vector<std::string> types; for (const std::shared_ptr<UnifiedRecord> &record : records_) { - std::vector<std::string> recordTypes = record->GetTypes(); - types.insert(types.end(), - std::make_move_iterator(recordTypes.begin()), std::make_move_iterator(recordTypes.end())); + types.push_back(UtdUtils::GetUtdIdFromUtdEnum(record->GetType())); } return types; } @@ -137,8 +130,7 @@ bool UnifiedData::HasHigherFileType(const std::string &type) const if (types.find(type) != types.end()) { return true; } - auto subTypesIter = FILE_SUB_TYPES.find(type); - if (subTypesIter == FILE_SUB_TYPES.end()) { + if (!UnifiedDataUtils::IsFilterFileType(type)) { return false; } for (auto it = types.begin(); it != types.end(); ++it) { @@ -278,7 +270,7 @@ std::set<std::string> UnifiedData::GetTypIds() const { std::set<std::string> types; for (const auto &record : records_) { - std::set<std::string> recordTypes = record->GetUtdIds(); + std::set<std::string> recordTypes = record->GetUtdIdsWithAddFileType(true); types.insert(recordTypes.begin(), recordTypes.end()); } return types; @@ -308,9 +300,9 @@ bool UnifiedData::IsNeedTransferToEntries() const return properties_->tag == RECORDS_TANSFER_TAG; } -void UnifiedData::TransferToEntries(UnifiedData &data) +void UnifiedData::ConvertRecordsToEntries() { - if (records_.size() <= 1) { + if (!IsNeedTransferToEntries()) { return; } std::shared_ptr<UnifiedRecord> recordFirst = records_[0]; @@ -323,10 +315,14 @@ void UnifiedData::TransferToEntries(UnifiedData &data) if (record == nullptr) { continue; } + if (record->GetUtdId2() == recordFirst->GetUtdId2()) { + continue; + } record->InitObject(); - recordFirst->AddEntry(record->GetUtdId(), record->GetValue()); + recordFirst->AddEntry(record->GetUtdId2(), record->GetValue()); } records_.erase(records_.begin() + 1, records_.end()); + LOG_INFO(UDMF_FRAMEWORK, "Convert records to entries finished"); } std::string UnifiedData::GetSdkVersion() const diff --git a/udmf/framework/innerkitsimpl/data/unified_data_helper.cpp b/udmf/framework/innerkitsimpl/data/unified_data_helper.cpp index 204127b2..2d804abc 100644 --- a/udmf/framework/innerkitsimpl/data/unified_data_helper.cpp +++ b/udmf/framework/innerkitsimpl/data/unified_data_helper.cpp @@ -26,6 +26,7 @@ #include "udmf_conversion.h" #include "udmf_meta.h" #include "udmf_utils.h" +#include "utd_client.h" namespace OHOS { namespace UDMF { @@ -36,7 +37,7 @@ static constexpr int64_t MAX_SA_DRAG_RECORD_SIZE = 15 * 1024 * 1024 + 512 * 102 constexpr const char *TEMP_UNIFIED_DATA_ROOT_PATH = "data/storage/el2/base/temp/udata"; constexpr const char *TEMP_UNIFIED_DATA_SUFFIX = ".ud"; constexpr const char *TEMP_UNIFIED_DATA_FLAG = "temp_udmf_file_flag"; - +static constexpr int WITH_SUMMARY_FORMAT_VER = 1; std::string UnifiedDataHelper::rootPath_ = ""; void UnifiedDataHelper::SetRootPath(const std::string &rootPath) @@ -88,13 +89,12 @@ void UnifiedDataHelper::CreateDirIfNotExist(const std::string& dirPath, const mo { if (OHOS::FileExists(dirPath)) { if (!OHOS::ForceRemoveDirectory(dirPath)) { - LOG_ERROR(UDMF_FRAMEWORK, "remove dir %{public}s failed, errno: %{public}d.", dirPath.c_str(), errno); + LOG_ERROR(UDMF_FRAMEWORK, "remove dir failed, errno: %{public}d.", errno); } } - LOG_DEBUG(UDMF_FRAMEWORK, "ForceCreateDirectory, dir: %{public}s", dirPath.c_str()); bool success = OHOS::ForceCreateDirectory(dirPath); if (!success) { - LOG_ERROR(UDMF_FRAMEWORK, "create dir %{public}s failed, errno: %{public}d.", dirPath.c_str(), errno); + LOG_ERROR(UDMF_FRAMEWORK, "create dir failed, errno: %{public}d.", errno); return; } if (mode != 0) { @@ -107,6 +107,15 @@ void UnifiedDataHelper::GetSummary(const UnifiedData &data, Summary &summary) for (const auto &record : data.GetRecords()) { CalRecordSummary(*record->GetEntries(), summary); } + summary.version = WITH_SUMMARY_FORMAT_VER; +} + +void UnifiedDataHelper::GetSummaryFromLoadInfo(const DataLoadInfo &dataLoadInfo, Summary &summary) +{ + summary.totalSize = dataLoadInfo.recordCount; + for (const auto &type : dataLoadInfo.types) { + summary.summary.emplace(type, 0); + } } bool UnifiedDataHelper::Pack(UnifiedData &data) @@ -166,20 +175,16 @@ bool UnifiedDataHelper::SaveUDataToFile(const std::string &dataFile, UnifiedData std::FILE *file = fopen(dataFile.c_str(), "w+"); if (file == nullptr) { - LOG_ERROR(UDMF_FRAMEWORK, "failed to open file: %{public}s, errno is %{public}d", dataFile.c_str(), errno); + LOG_ERROR(UDMF_FRAMEWORK, "failed to open file: errno is %{public}d", errno); return false; } recordTlv.SetFile(file); UdmfConversion::InitValueObject(data); if (!TLVUtil::Writing(data, recordTlv, TAG::TAG_UNIFIED_DATA)) { LOG_ERROR(UDMF_FRAMEWORK, "TLV Writing failed!"); - if (fclose(file) == EOF) { - LOG_ERROR(UDMF_FRAMEWORK, "fclose is failed"); - } - return false; + return FileClose(file, false); } - (void)fclose(file); - return true; + return FileClose(file, true); } bool UnifiedDataHelper::LoadUDataFromFile(const std::string &dataFile, UnifiedData &data) @@ -190,22 +195,29 @@ bool UnifiedDataHelper::LoadUDataFromFile(const std::string &dataFile, UnifiedDa std::string path = fileUri.GetRealPath(); std::FILE *file = fopen(path.c_str(), "r"); if (file == nullptr) { - LOG_ERROR(UDMF_FRAMEWORK, "failed to open file, error:%{public}s, srcdir:%{public}s, relPath:%{public}s", - std::strerror(errno), - dataFile.c_str(), - path.c_str()); + LOG_ERROR(UDMF_FRAMEWORK, "failed to open file, error:%{public}s", std::strerror(errno)); return false; } recordTlv.SetFile(file); - + if (!TLVUtil::ReadTlv(data, recordTlv, TAG::TAG_UNIFIED_DATA)) { LOG_ERROR(UDMF_FRAMEWORK, "TLV Reading failed!"); - (void)fclose(file); - return false; + return FileClose(file, false); } UdmfConversion::ConvertRecordToSubclass(data); - (void)fclose(file); - return true; + return FileClose(file, true); +} + +bool UnifiedDataHelper::FileClose(std::FILE *file, bool status) +{ + if (file == nullptr) { + return false; + } + if ((fclose(file) == EOF)) { + LOG_ERROR(UDMF_FRAMEWORK, "fclose is failed"); + return false; + } + return status; } std::string UnifiedDataHelper::GetRootPath() @@ -268,6 +280,16 @@ void UnifiedDataHelper::CalRecordSummary(std::map<std::string, ValueType> &entry auto typeId = utdId; auto valueSize = ObjectUtils::GetValueSize(value, false); ProcessTypeId(value, typeId); + auto specificIter = summary.specificSummary.find(typeId); + if (specificIter == summary.specificSummary.end()) { + summary.specificSummary[typeId] = valueSize; + } else { + summary.specificSummary[typeId] += valueSize; + } + FillSummaryFormat(typeId, utdId, summary); + if (utdId == GENERAL_FILE_URI) { + UpgradeToParentType(typeId); + } auto it = summary.summary.find(typeId); if (it == summary.summary.end()) { summary.summary[typeId] = valueSize; @@ -278,5 +300,29 @@ void UnifiedDataHelper::CalRecordSummary(std::map<std::string, ValueType> &entry } } +void UnifiedDataHelper::FillSummaryFormat(const std::string &type, const std::string &utdId, Summary &summary) +{ + Uds_Type udsType = Uds_Type::UDS_OTHER; + auto find = UDS_UTD_TYPE_MAP.find(utdId); + if (find != UDS_UTD_TYPE_MAP.end()) { + udsType = find->second; + } + if (summary.summaryFormat.find(type) != summary.summaryFormat.end()) { + summary.summaryFormat[type].emplace_back(udsType); + } else { + summary.summaryFormat[type] = { udsType }; + } +} + +void UnifiedDataHelper::UpgradeToParentType(std::string &typeId) +{ + std::string fileType = UnifiedDataUtils::GetBelongsToFileType(typeId); + if (!fileType.empty()) { + typeId = fileType; + return; + } + typeId = "general.file"; // When utdId is general.file-uri, the default parent type is general.file. +} + } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/unified_html_record_process.cpp b/udmf/framework/innerkitsimpl/data/unified_html_record_process.cpp index 10116871..4defb59a 100644 --- a/udmf/framework/innerkitsimpl/data/unified_html_record_process.cpp +++ b/udmf/framework/innerkitsimpl/data/unified_html_record_process.cpp @@ -27,7 +27,6 @@ constexpr const char *IMG_TAG_PATTERN = "<img.*?>"; constexpr const char *IMG_TAG_SRC_PATTERN = "src=(['\"])(.*?)\\1"; constexpr const char *IMG_TAG_SRC_HEAD = "src=\""; constexpr const char *IMG_LOCAL_URI = "file:///"; -constexpr const char *IMG_LOCAL_PATH = "://"; constexpr const char *FILE_SCHEME_PREFIX = "file://"; struct Cmp { @@ -93,16 +92,14 @@ std::string UnifiedHtmlRecordProcess::RebuildHtmlContent(const std::string &str, std::map<uint32_t, std::pair<std::string, std::string>, Cmp> replaceUris; std::string strResult = str; for (auto &uri : uris) { - if (uri.dfsUri.empty()) { - continue; - } - std::string realUri = uri.dfsUri; - if (realUri.substr(0, strlen(FILE_SCHEME_PREFIX)) == FILE_SCHEME_PREFIX) { - AppFileService::ModuleFileUri::FileUri fileUri(uri.dfsUri); + std::string tmpUri = uri.dfsUri.empty() ? uri.authUri : uri.dfsUri; + std::string realUri = tmpUri; + if (tmpUri.substr(0, strlen(FILE_SCHEME_PREFIX)) == FILE_SCHEME_PREFIX) { + AppFileService::ModuleFileUri::FileUri fileUri(tmpUri); realUri = FILE_SCHEME_PREFIX; realUri += fileUri.GetRealPath(); + replaceUris[uri.position] = std::make_pair(std::move(uri.oriUri), std::move(realUri)); } - replaceUris[uri.position] = std::make_pair(std::move(uri.oriUri), std::move(realUri)); } if (replaceUris.empty()) { return ""; @@ -209,8 +206,7 @@ std::vector<UriInfo> UnifiedHtmlRecordProcess::SplitHtmlWithImgSrcLabel( bool UnifiedHtmlRecordProcess::IsLocalURI(const std::string &uri) noexcept { - return uri.substr(0, strlen(IMG_LOCAL_URI)) == std::string(IMG_LOCAL_URI) || - uri.find(IMG_LOCAL_PATH) == std::string::npos; + return uri.substr(0, strlen(IMG_LOCAL_URI)) == std::string(IMG_LOCAL_URI); } } // namespace UDMF diff --git a/udmf/framework/innerkitsimpl/data/unified_record.cpp b/udmf/framework/innerkitsimpl/data/unified_record.cpp index 5e6bb685..b95f9e1a 100644 --- a/udmf/framework/innerkitsimpl/data/unified_record.cpp +++ b/udmf/framework/innerkitsimpl/data/unified_record.cpp @@ -24,8 +24,6 @@ namespace OHOS { namespace UDMF { static constexpr UDType FILE_TYPES[] = {FILE, AUDIO, FOLDER, IMAGE, VIDEO}; static constexpr const char *FILE_SCHEME = "file"; -static const std::set<std::string> FILE_SUB_TYPES = { - "general.image", "general.video", "general.audio", "general.folder" }; static constexpr UDType UDC_RECORDS[] = {APPLICATION_DEFINED_RECORD, AUDIO, FILE, FOLDER, HTML, IMAGE, HYPERLINK, PLAIN_TEXT, SYSTEM_DEFINED_APP_ITEM, SYSTEM_DEFINED_FORM, SYSTEM_DEFINED_PIXEL_MAP, SYSTEM_DEFINED_RECORD, TEXT, VIDEO}; @@ -39,15 +37,16 @@ UnifiedRecord::UnifiedRecord(UDType type) { dataType_ = type; utdId_ = UtdUtils::GetUtdIdFromUtdEnum(type); + utdId2_ = utdId_; } UnifiedRecord::UnifiedRecord(UDType type, ValueType value) { dataType_ = type; utdId_ = UtdUtils::GetUtdIdFromUtdEnum(type); + utdId2_ = utdId_; value_ = value; if (std::holds_alternative<std::shared_ptr<Object>>(value_)) { - hasObject_ = true; if (utdId_ == GENERAL_FILE_URI) { ObjectUtils::ProcessFileUriType(dataType_, value_); } @@ -65,7 +64,7 @@ std::vector<std::string> UnifiedRecord::GetTypes() const for (auto it = entries_->begin(); it != entries_->end(); it++) { types.push_back(it->first); } - types.push_back(utdId_); + types.push_back(utdId2_); return types; } @@ -73,6 +72,7 @@ void UnifiedRecord::SetType(const UDType &type) { dataType_ = type; utdId_ = UtdUtils::GetUtdIdFromUtdEnum(type); + utdId2_ = utdId_; } int64_t UnifiedRecord::GetSize() @@ -116,16 +116,17 @@ bool UnifiedRecord::HasType(const std::string &utdId) const if (entries_->find(utdId) != entries_->end()) { return true; } - return utdId == utdId_; + return utdId == utdId2_; } void UnifiedRecord::AddEntry(const std::string &utdId, ValueType &&value) { std::lock_guard<std::recursive_mutex> lock(mutex_); - if (utdId == utdId_ || utdId_.empty()) { + if (utdId == utdId2_ || utdId2_.empty()) { utdId_ = utdId; + utdId2_ = utdId_; value_ = std::move(value); - auto udType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(utdId_)); + auto udType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(utdId2_)); if (udType == UD_BUTT) { dataType_ = APPLICATION_DEFINED_RECORD; return; @@ -142,19 +143,23 @@ void UnifiedRecord::AddEntry(const std::string &utdId, ValueType &&value) ValueType UnifiedRecord::GetEntry(const std::string &utdId) { std::lock_guard<std::recursive_mutex> lock(mutex_); - if (utdId_ == utdId && !(std::holds_alternative<std::monostate>(value_))) { + if (utdId2_ == utdId && !(std::holds_alternative<std::monostate>(value_))) { + auto value = value_; if (!std::holds_alternative<std::shared_ptr<Object>>(value_) && std::find(std::begin(UDC_RECORDS), std::end(UDC_RECORDS), dataType_) != std::end(UDC_RECORDS)) { InitObject(); + value = value_; + auto obj = std::get<std::shared_ptr<Object>>(value_); + value_ = obj->value_[VALUE_TYPE]; } - return value_; + return value; } auto it = entries_->find(utdId); if (it != entries_->end() && !(std::holds_alternative<std::monostate>(it->second))) { return it->second; } auto getter = GetterSystem::GetInstance().GetGetter(channelName_); - if (getter != nullptr && (utdId_ == utdId || it != entries_->end())) { + if (getter != nullptr && (utdId2_ == utdId || it != entries_->end())) { auto value = getter->GetValueByType(dataId_, recordId_, utdId); if (std::holds_alternative<std::monostate>(value)) { LOG_ERROR(UDMF_FRAMEWORK, "get value failed, utdId: %{public}s", utdId.c_str()); @@ -163,14 +168,15 @@ ValueType UnifiedRecord::GetEntry(const std::string &utdId) AddEntry(utdId, ValueType(value)); return value; } - if (utdId_ == utdId && std::holds_alternative<std::monostate>(value_)) { + if (utdId2_ == utdId && std::holds_alternative<std::monostate>(value_)) { InitObject(); + auto value = value_; auto obj = std::get<std::shared_ptr<Object>>(value_); + value_ = obj->value_[VALUE_TYPE]; if (obj->value_.size() == 1) { // value_ size equals 1 means there are no datas - value_ = obj->value_[VALUE_TYPE]; return std::monostate(); } else { - return value_; + return value; } } return std::monostate(); @@ -179,15 +185,15 @@ ValueType UnifiedRecord::GetEntry(const std::string &utdId) std::shared_ptr<std::map<std::string, ValueType>> UnifiedRecord::GetEntries() { auto res = std::make_shared<std::map<std::string, ValueType>>(*entries_); - if (!utdId_.empty()) { + if (!utdId2_.empty()) { if (!std::holds_alternative<std::shared_ptr<Object>>(value_)) { InitObject(); ValueType value = value_; - res->insert_or_assign(utdId_, std::move(value)); + res->insert_or_assign(utdId2_, std::move(value)); auto object = std::get<std::shared_ptr<Object>>(value_); value_ = object->value_[VALUE_TYPE]; // restore value_ } else { - res->insert_or_assign(utdId_, value_); + res->insert_or_assign(utdId2_, value_); } } return res; @@ -220,16 +226,28 @@ std::set<std::string> UnifiedRecord::GetUtdIds() const std::set<std::string> utdIds; if (!utdId_.empty()) { utdIds.emplace(utdId_); - if (utdId_ == GENERAL_FILE_URI && std::holds_alternative<std::shared_ptr<Object>>(value_)) { + } + for (const auto& [key, value] : *entries_) { + utdIds.emplace(key); + } + return utdIds; +} + +std::set<std::string> UnifiedRecord::GetUtdIdsWithAddFileType(bool isSpecific) const +{ + std::set<std::string> utdIds; + if (!utdId2_.empty()) { + utdIds.emplace(utdId2_); + if (utdId2_ == GENERAL_FILE_URI && std::holds_alternative<std::shared_ptr<Object>>(value_)) { auto fileUri = std::get<std::shared_ptr<Object>>(value_); - AddFileUriType(utdIds, fileUri); + AddFileUriType(utdIds, fileUri, isSpecific); } } for (const auto& [key, value] : *entries_) { utdIds.emplace(key); if (key == GENERAL_FILE_URI && std::holds_alternative<std::shared_ptr<Object>>(value)) { auto fileUri = std::get<std::shared_ptr<Object>>(value); - AddFileUriType(utdIds, fileUri); + AddFileUriType(utdIds, fileUri, isSpecific); } } return utdIds; @@ -238,6 +256,7 @@ std::set<std::string> UnifiedRecord::GetUtdIds() const void UnifiedRecord::SetUtdId(const std::string& utdId) { utdId_ = utdId; + utdId2_ = utdId; } std::string UnifiedRecord::GetUtdId() const @@ -245,6 +264,16 @@ std::string UnifiedRecord::GetUtdId() const return utdId_; } +void UnifiedRecord::SetUtdId2(const std::string& utdId) +{ + utdId2_ = utdId; +} + +std::string UnifiedRecord::GetUtdId2() const +{ + return utdId2_; +} + void UnifiedRecord::SetDataId(uint32_t dataId) { dataId_ = dataId; @@ -299,11 +328,6 @@ void UnifiedRecord::InitObject() } } -bool UnifiedRecord::HasObject() -{ - return hasObject_; -} - bool UnifiedRecord::HasFileType(std::string &fileUri) const { fileUri.clear(); @@ -372,7 +396,8 @@ void UnifiedRecord::ComputeUris(const std::function<bool(UriInfo &)> &action) } } -void UnifiedRecord::AddFileUriType(std::set<std::string> &utdIds, const std::shared_ptr<Object> &fileUri) const +void UnifiedRecord::AddFileUriType(std::set<std::string> &utdIds, + const std::shared_ptr<Object> &fileUri, bool isSpecific) const { if (fileUri == nullptr) { return; @@ -381,7 +406,14 @@ void UnifiedRecord::AddFileUriType(std::set<std::string> &utdIds, const std::sha if (fileUri->GetValue(UNIFORM_DATA_TYPE, uniformDataType) && uniformDataType == GENERAL_FILE_URI) { std::string fileType; if (fileUri->GetValue(FILE_TYPE, fileType) && !fileType.empty()) { - utdIds.emplace(fileType); + if (isSpecific) { + utdIds.emplace(fileType); + return; + } + std::string fileTypeStr = UnifiedDataUtils::GetBelongsToFileType(fileType); + if (!fileTypeStr.empty()) { + utdIds.emplace(fileTypeStr); + } } } } diff --git a/udmf/framework/innerkitsimpl/data/video.cpp b/udmf/framework/innerkitsimpl/data/video.cpp index 30dde4e3..69ca7230 100644 --- a/udmf/framework/innerkitsimpl/data/video.cpp +++ b/udmf/framework/innerkitsimpl/data/video.cpp @@ -20,18 +20,30 @@ namespace UDMF { Video::Video() : Video("") { SetType(VIDEO); - utdId_ = UtdUtils::GetUtdIdFromUtdEnum(VIDEO); + utdId2_ = GENERAL_FILE_URI; } Video::Video(const std::string &uri) : File(uri) { SetType(VIDEO); - utdId_ = UtdUtils::GetUtdIdFromUtdEnum(VIDEO); + utdId2_ = GENERAL_FILE_URI; } Video::Video(UDType type, ValueType value) : File(type, value) { SetType(VIDEO); + utdId2_ = GENERAL_FILE_URI; +} + +void Video::InitObject() +{ + File::InitObject(); + auto object = std::get<std::shared_ptr<Object>>(value_); + if (!fileType_.empty()) { + object->value_[FILE_TYPE] = fileType_; + } else { + object->value_[FILE_TYPE] = "general.video"; + } } } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/dynamic/pixelmap_loader.cpp b/udmf/framework/innerkitsimpl/dynamic/pixelmap_loader.cpp new file mode 100644 index 00000000..121676cd --- /dev/null +++ b/udmf/framework/innerkitsimpl/dynamic/pixelmap_loader.cpp @@ -0,0 +1,177 @@ +/* + * 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. + */ +#define LOG_TAG "PixelmapLoader" + +#include "pixelmap_loader.h" + +#include <dlfcn.h> +#include <thread> +#include "logger.h" +#include "pixel_map.h" + +namespace OHOS { +namespace UDMF { + +static constexpr const char* PIXEL_MAP_WRAPPER_SO_NAME = "libpixelmap_wrapper.z.so"; +static constexpr const char* DECODE_TLV = "DecodeTlv"; +static constexpr const char* ENCODE_TLV = "EncodeTlv"; +static constexpr const char* GET_PIXEL_MAP_FROM_RAW_DATA = "GetPixelMapFromRawData"; +static constexpr const char* PARSE_INFO_FROM_PIXEL_MAP = "ParseInfoFromPixelMap"; + +std::weak_ptr<void> PixelMapLoader::SoAutoUnloadManager::weakHandler_; +std::mutex PixelMapLoader::SoAutoUnloadManager::mutex_; + +std::shared_ptr<void> PixelMapLoader::SoAutoUnloadManager::GetHandler() +{ + { + std::lock_guard<std::mutex> lock(mutex_); + if (auto real = weakHandler_.lock()) { + return real; + } + } + LOG_INFO(UDMF_KITS_INNER, "dlopen start"); + void *rawHandler = dlopen(PIXEL_MAP_WRAPPER_SO_NAME, RTLD_NOW); + if (rawHandler == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "dlopen error! msg=%{public}s", dlerror()); + return nullptr; + } + + auto deleter = [](void *h) { + if (h) dlclose(h); + }; + std::shared_ptr<void> sp(rawHandler, deleter); + + { + std::lock_guard<std::mutex> lock(mutex_); + if (auto existed = weakHandler_.lock()) { + return existed; + } + weakHandler_ = sp; + return sp; + } +} + +PixelMapLoader::PixelMapLoader() +{ + handler_ = SoAutoUnloadManager::GetHandler(); + if (handler_ == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "handler is null!"); + } +} + +std::shared_ptr<OHOS::Media::PixelMap> PixelMapLoader::DecodeTlv(std::vector<uint8_t> &buff) +{ + if (buff.empty()) { + LOG_ERROR(UDMF_KITS_INNER, "buff is empty!"); + return nullptr; + } + if (handler_ == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "handler is null!"); + return nullptr; + } + PixelMapDetails details; + details.rawData = std::ref(buff); + auto loadDecodeTlv = reinterpret_cast<LoadDecodeTlv>(dlsym(handler_.get(), DECODE_TLV)); + if (loadDecodeTlv == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "dlsym error! msg=%{public}s", dlerror()); + return nullptr; + } + + OHOS::Media::PixelMap *raw = loadDecodeTlv(details); + if (raw == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "pixelMap is null!"); + return nullptr; + } + auto deleter = [handler = handler_](OHOS::Media::PixelMap *p) { + delete p; + }; + return std::shared_ptr<OHOS::Media::PixelMap>(raw, deleter); +} + +bool PixelMapLoader::EncodeTlv(const std::shared_ptr<OHOS::Media::PixelMap> pixelMap, std::vector<uint8_t> &buff) +{ + if (pixelMap == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "pixelMap is nullptr!"); + return false; + } + if (handler_ == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "handler is null!"); + return false; + } + auto loadEncodeTlv = reinterpret_cast<LoadEncodeTlv>(dlsym(handler_.get(), ENCODE_TLV)); + if (loadEncodeTlv == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "dlsym error! msg=%{public}s", dlerror()); + return false; + } + auto details = std::make_shared<PixelMapDetails>(); + details->rawDataResult.emplace(); + auto result = loadEncodeTlv(pixelMap.get(), details.get()); + if (details->rawDataResult->empty()) { + LOG_ERROR(UDMF_KITS_INNER, "encodeTlv fail"); + return result; + } + buff = std::move(*details->rawDataResult); + return result; +} + +std::shared_ptr<OHOS::Media::PixelMap> PixelMapLoader::GetPixelMapFromRawData(const PixelMapDetails &details) +{ + if (!details.rawData.has_value()) { + LOG_ERROR(UDMF_KITS_INNER, "buff is empty!"); + return nullptr; + } + if (handler_ == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "handler is null!"); + return nullptr; + } + auto loadGetPixelMapFromRawData = reinterpret_cast<LoadGetPixelMapFromRawData>( + dlsym(handler_.get(), GET_PIXEL_MAP_FROM_RAW_DATA)); + if (loadGetPixelMapFromRawData == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "dlsym error! msg=%{public}s", dlerror()); + return nullptr; + } + OHOS::Media::PixelMap *raw = loadGetPixelMapFromRawData(details); + if (raw == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "pixelMap is null!"); + return nullptr; + } + auto deleter = [handler = handler_](OHOS::Media::PixelMap *p) { + delete p; + }; + return std::shared_ptr<OHOS::Media::PixelMap>(raw, deleter); +} + +std::shared_ptr<PixelMapDetails> PixelMapLoader::ParseInfoFromPixelMap( + const std::shared_ptr<OHOS::Media::PixelMap> pixelMap) +{ + if (pixelMap == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "pixelMap is nullptr!"); + return nullptr; + } + if (handler_ == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "handler is null!"); + return nullptr; + } + auto loadParseInfoFromPixelMap = reinterpret_cast<LoadParseInfoFromPixelMap>( + dlsym(handler_.get(), PARSE_INFO_FROM_PIXEL_MAP)); + if (loadParseInfoFromPixelMap == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "dlsym error! msg=%{public}s", dlerror()); + return nullptr; + } + return std::shared_ptr<PixelMapDetails>(loadParseInfoFromPixelMap(pixelMap.get())); +} + +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/dynamic/pixelmap_wrapper.cpp b/udmf/framework/innerkitsimpl/dynamic/pixelmap_wrapper.cpp new file mode 100644 index 00000000..dc858047 --- /dev/null +++ b/udmf/framework/innerkitsimpl/dynamic/pixelmap_wrapper.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. + */ +#define LOG_TAG "PixelmapWrapper" +#include "pixelmap_wrapper.h" + +#include "logger.h" +#include "media_errors.h" +#include "pixel_map.h" + +using namespace OHOS::UDMF; + +static constexpr size_t BYTES_PER_COLOR = sizeof(uint32_t); + +#ifdef __cplusplus +extern "C" { +#endif + +OHOS::Media::PixelMap *DecodeTlv(const PixelMapDetails details) +{ + return OHOS::Media::PixelMap::DecodeTlv(details.rawData->get()); +} + +bool EncodeTlv(const OHOS::Media::PixelMap *pixelMap, PixelMapDetails *details) +{ + if (details == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "details is null"); + return false; + } + auto &rawData = *(details->rawDataResult); + return pixelMap->EncodeTlv(rawData); +} + +OHOS::Media::PixelMap *GetPixelMapFromRawData(const PixelMapDetails details) +{ + OHOS::Media::InitializationOptions opts; + opts.size.width = details.width; + opts.size.height = details.height; + opts.pixelFormat = static_cast<OHOS::Media::PixelFormat>(details.pixelFormat); + if (!details.rawData.has_value()) { + return nullptr; + } + // This create does not do pre-multiplication. + opts.alphaType = OHOS::Media::AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL; + LOG_INFO(UDMF_KITS_INNER, + "PixelMap width = %{public}d, height = %{public}d, pixelFormat = %{public}d, rawData size = %{public}zu", + opts.size.width, opts.size.height, opts.pixelFormat, details. + rawData->get().size()); + opts.srcPixelFormat = opts.pixelFormat; + auto pixelMap = OHOS::Media::PixelMap::Create( + reinterpret_cast<const uint32_t *>(details.rawData->get().data()), + details.rawData->get().size() / BYTES_PER_COLOR, opts); + if (pixelMap == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "Create PixelMap from rawData failed"); + return nullptr; + } + return pixelMap.release(); +} + +PixelMapDetails *ParseInfoFromPixelMap(OHOS::Media::PixelMap *pixelMap) +{ + if (pixelMap == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "PixelMap is null"); + return nullptr; + } + auto details = new (std::nothrow) PixelMapDetails; + if (details == nullptr) { + LOG_ERROR(UDMF_KITS_INNER, "Apply memory for details failed"); + return nullptr; + } + details->width = pixelMap->GetWidth(); + details->height = pixelMap->GetHeight(); + details->pixelFormat = static_cast<int32_t>(pixelMap->GetPixelFormat()); + details->alphaType = static_cast<int32_t>(pixelMap->GetAlphaType()); + auto length = pixelMap->GetByteCount(); + if (length <= 0) { + LOG_ERROR(UDMF_KITS_INNER, "Has no length"); + return details; + } + std::vector<uint8_t> rawData; + rawData.resize(length); + auto status = pixelMap->ReadPixels(length, rawData.data()); + if (status != OHOS::Media::SUCCESS) { + LOG_ERROR(UDMF_KITS_INNER, "Get Pixels error, status = %{public}u", status); + return details; + } + details->rawDataResult.emplace(std::move(rawData)); + return details; +} + +#ifdef __cplusplus +}; +#endif \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/service/distributeddata_udmf_ipc_interface_code.h b/udmf/framework/innerkitsimpl/service/distributeddata_udmf_ipc_interface_code.h index 4d5e1237..d3d0efb3 100644 --- a/udmf/framework/innerkitsimpl/service/distributeddata_udmf_ipc_interface_code.h +++ b/udmf/framework/innerkitsimpl/service/distributeddata_udmf_ipc_interface_code.h @@ -34,6 +34,16 @@ enum class UdmfServiceInterfaceCode : uint32_t { REMOVE_APP_SHARE_OPTION, OBTAIN_ASYN_PROCESS, CLEAR_ASYN_PROCESS_BY_KEY, + SET_DELAY_INFO, + SET_DELAY_DATA, + GET_DELAY_DATA, + CODE_BUTT +}; + +enum class UdmfNotifierInterfaceCode : uint32_t { + CODE_HEAD = 0, + HANDLE_DELAY_OBSERVER = CODE_HEAD, + HANDLE_DELAY_DATA, CODE_BUTT }; } // namespace OHOS::UDMF diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.h b/udmf/framework/innerkitsimpl/service/iudmf_notifier.h similarity index 50% rename from datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.h rename to udmf/framework/innerkitsimpl/service/iudmf_notifier.h index f7ebd8f7..1878dce5 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/store_account_observer.h +++ b/udmf/framework/innerkitsimpl/service/iudmf_notifier.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 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 @@ -12,27 +12,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef STORE_ACCOUNT_OBSERVER_H -#define STORE_ACCOUNT_OBSERVER_H -#include "account_delegate.h" +#ifndef IUDMF_NOTIFIER_H +#define IUDMF_NOTIFIER_H + +#include <iremote_broker.h> +#include "unified_data.h" +#include "unified_types.h" + namespace OHOS { namespace UDMF { -class RuntimeStoreAccountObserver : public DistributedData::AccountDelegate::Observer { - void OnAccountChanged(const DistributedData::AccountEventInfo &eventInfo, int32_t timeout) override; - // must specify unique name for observer - std::string Name() override - { - return "UdmfRuntimeStore"; - } - - LevelType GetLevel() override - { - return LevelType::LOW; - } +class IUdmfNotifier : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"IUdmfNotifier descriptor"); + virtual void HandleDelayObserver(const std::string &key, const DataLoadInfo &dataLoadInfo) = 0; +}; + +class IDelayDataCallback : public IRemoteBroker { +public: + DECLARE_INTERFACE_DESCRIPTOR(u"IDelayDataCallback descriptor"); + virtual void DelayDataCallback(const std::string &key, const UnifiedData &data) = 0; }; } // namespace UDMF } // namespace OHOS - -#endif // STORE_ACCOUNT_OBSERVER_H \ No newline at end of file +#endif // IUDMF_NOTIFIER_H \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/service/progress_callback.cpp b/udmf/framework/innerkitsimpl/service/progress_callback.cpp index f235e18d..4562548f 100644 --- a/udmf/framework/innerkitsimpl/service/progress_callback.cpp +++ b/udmf/framework/innerkitsimpl/service/progress_callback.cpp @@ -23,6 +23,7 @@ namespace OHOS { namespace UDMF { +constexpr int CONVERSION_RULES = 10; int32_t ProgressSignalStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { @@ -33,8 +34,7 @@ int32_t ProgressSignalStub::OnRemoteRequest(uint32_t code, return E_ERROR; } pid_t pid = IPCSkeleton::GetCallingPid(); - pid_t uid = IPCSkeleton::GetCallingUid(); - LOG_INFO(UDMF_SERVICE, "CallingPid=%{public}d, CallingUid=%{public}d, code=%{public}u", pid, uid, code); + LOG_INFO(UDMF_SERVICE, "CallingPid=%{public}d, code=%{public}u", pid, code); HandleProgressSignalValue(data); return E_OK; } @@ -44,12 +44,14 @@ void ProgressSignalCallback::HandleProgressSignalValue(MessageParcel &data) int32_t cancelStatus = 0; std::string signalValue = data.ReadString(); - try { - cancelStatus = std::stoi(signalValue); - } catch (const std::exception& e) { - LOG_ERROR(UDMF_CLIENT, "Signal value error, signalValue=%{public}s", signalValue.c_str()); + char* end = nullptr; + errno = 0; + cancelStatus = std::strtoul(signalValue.c_str(), &end, CONVERSION_RULES); + if (errno == ERANGE || end == signalValue || *end != '\0') { + LOG_ERROR(UDMF_CLIENT, "Failed to convert signalValue, signalValue=%{public}s", signalValue.c_str()); return; } + switch (cancelStatus) { case NORMAL_PASTE: break; diff --git a/udmf/framework/innerkitsimpl/service/udmf_notifier_stub.cpp b/udmf/framework/innerkitsimpl/service/udmf_notifier_stub.cpp new file mode 100644 index 00000000..dc7a720d --- /dev/null +++ b/udmf/framework/innerkitsimpl/service/udmf_notifier_stub.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "UdmfNotifierStub" +#include "udmf_notifier_stub.h" + +#include "error_code.h" +#include "ipc_skeleton.h" +#include "logger.h" +#include "udmf_async_client.h" +#include "udmf_types_util.h" +#include "udmf_conversion.h" +#include "unified_html_record_process.h" + +namespace OHOS { +namespace UDMF { + +int32_t UdmfNotifierStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, + MessageOption &option) +{ + LOG_INFO(UDMF_SERVICE, "code:%{public}u callingPid:%{public}u", code, IPCSkeleton::GetCallingPid()); + std::u16string local = GetDescriptor(); + std::u16string remote = data.ReadInterfaceToken(); + if (local != remote) { + LOG_ERROR(UDMF_SERVICE, "local is not equal to remote"); + return -1; + } + + std::string key; + DataLoadInfo dataLoadInfo; + if (!ITypesUtil::Unmarshal(data, key, dataLoadInfo)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshal failed!"); + return E_READ_PARCEL_ERROR; + } + + HandleDelayObserver(key, dataLoadInfo); + return 0; +} + +UdmfNotifierClient::UdmfNotifierClient(LoadHandler loadHandler):loadHandler_(loadHandler) {} + +void UdmfNotifierClient::HandleDelayObserver(const std::string &key, const DataLoadInfo &dataLoadInfo) +{ + auto loadHandler = loadHandler_; + UdmfAsyncClient::GetInstance().PushTaskToExecutor( + [loadHandler, key, dataLoadInfo] { loadHandler(key, dataLoadInfo); }); +} + +int32_t DelayDataCallbackStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, + MessageOption &option) +{ + LOG_INFO(UDMF_SERVICE, "code:%{public}u callingPid:%{public}u", code, IPCSkeleton::GetCallingPid()); + std::u16string local = GetDescriptor(); + std::u16string remote = data.ReadInterfaceToken(); + if (local != remote) { + LOG_ERROR(UDMF_SERVICE, "local is not equal to remote"); + return -1; + } + + std::string key; + UnifiedData unifiedData; + if (!ITypesUtil::Unmarshal(data, key, unifiedData)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshal failed!"); + return E_READ_PARCEL_ERROR; + } + UdmfConversion::ConvertRecordToSubclass(unifiedData); + + if (unifiedData.HasType(UtdUtils::GetUtdIdFromUtdEnum(UDType::HTML))) { + UnifiedHtmlRecordProcess::RebuildHtmlRecord(unifiedData); + } + DelayDataCallback(key, unifiedData); + return 0; +} + +DelayDataCallbackClient::DelayDataCallbackClient(DataCallback dataCallback):dataCallback_(dataCallback) {} + +void DelayDataCallbackClient::DelayDataCallback(const std::string &key, const UnifiedData &unifiedData) +{ + auto dataCallback = dataCallback_; + UdmfAsyncClient::GetInstance().PushTaskToExecutor( + [dataCallback, key, unifiedData] { dataCallback(key, unifiedData); }); +} + +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/gdb/include/gdb_transaction.h b/udmf/framework/innerkitsimpl/service/udmf_notifier_stub.h similarity index 32% rename from relational_store/interfaces/inner_api/gdb/include/gdb_transaction.h rename to udmf/framework/innerkitsimpl/service/udmf_notifier_stub.h index 137ff740..f9e79478 100644 --- a/relational_store/interfaces/inner_api/gdb/include/gdb_transaction.h +++ b/udmf/framework/innerkitsimpl/service/udmf_notifier_stub.h @@ -12,49 +12,52 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -#ifndef ARKDATA_INTELLIGENCE_PLATFORM_GDB_TRANSACTION_H -#define ARKDATA_INTELLIGENCE_PLATFORM_GDB_TRANSACTION_H - + +#ifndef UDMF_NOTIFIER_STUB_H +#define UDMF_NOTIFIER_STUB_H + #include <functional> -#include <tuple> -#include <utility> -#include <vector> - -#include "gdb_store_config.h" -#include "result.h" - -namespace OHOS::DistributedDataAip { -class Connection; -class Transaction { +#include <iremote_stub.h> +#include "iudmf_notifier.h" +#include "unified_data.h" + +namespace OHOS { +namespace UDMF { + +class UdmfNotifierStub : public IRemoteStub<IUdmfNotifier> { public: - using Creator = std::function<std::pair<int32_t, std::shared_ptr<Transaction>>(std::shared_ptr<Connection> conn)>; - - static std::pair<int32_t, std::shared_ptr<Transaction>> Create(std::shared_ptr<Connection> conn); - static int32_t RegisterCreator(Creator creator); - - API_EXPORT virtual ~Transaction() = default; - - API_EXPORT virtual int32_t Commit() = 0; - API_EXPORT virtual int32_t Rollback() = 0; - virtual int32_t Close() = 0; - - /** - * @brief Queries data in the database based on GQL statement. - * - * @param gql Indicates the GQL statement to execute. - */ - API_EXPORT virtual std::pair<int32_t, std::shared_ptr<Result>> Query(const std::string &gql) = 0; - - /** - * @brief Executes an GQL statement. - * - * @param gql Indicates the GQL statement to execute. - */ - API_EXPORT virtual std::pair<int32_t, std::shared_ptr<Result>> Execute(const std::string &gql) = 0; - + int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +}; + +class UdmfNotifierClient : public UdmfNotifierStub { +public: + explicit UdmfNotifierClient(LoadHandler loadHandler_); + virtual ~UdmfNotifierClient() = default; + + void HandleDelayObserver(const std::string &key, const DataLoadInfo &dataLoadInfo) override; + +private: + LoadHandler loadHandler_; +}; + +class DelayDataCallbackStub : public IRemoteStub<IDelayDataCallback> { +public: + int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override; +}; + +class DelayDataCallbackClient : public DelayDataCallbackStub { +public: + using DataCallback = std::function<void(const std::string &udKey, const UnifiedData &unifiedData)>; + + explicit DelayDataCallbackClient(DataCallback dataCallback); + virtual ~DelayDataCallbackClient() = default; + void DelayDataCallback(const std::string &key, const UnifiedData &data) override; + private: - static inline Creator creator_; + DataCallback dataCallback_; }; -} // namespace OHOS::DistributedDataAip -#endif + + +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_NOTIFIER_STUB_H \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/service/udmf_service.h b/udmf/framework/innerkitsimpl/service/udmf_service.h index 1f685fcf..70874cb2 100644 --- a/udmf/framework/innerkitsimpl/service/udmf_service.h +++ b/udmf/framework/innerkitsimpl/service/udmf_service.h @@ -25,6 +25,7 @@ #include "unified_data.h" #include "unified_meta.h" #include "unified_types.h" +#include "iudmf_notifier.h" namespace OHOS { namespace UDMF { @@ -51,6 +52,11 @@ public: virtual int32_t RemoveAppShareOption(const std::string &intention) = 0; virtual int32_t ObtainAsynProcess(AsyncProcessInfo &processInfo) = 0; virtual int32_t ClearAsynProcessByKey(const std::string &businessUdKey) = 0; + virtual int32_t SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptr<IRemoteObject> iUdmfNotifier, + std::string &key) = 0; + virtual int32_t PushDelayData(const std::string &key, UnifiedData &unifiedData) = 0; + virtual int32_t GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr<IRemoteObject> iUdmfNotifier, std::shared_ptr<UnifiedData> unifiedData) = 0; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/service/udmf_service_client.cpp b/udmf/framework/innerkitsimpl/service/udmf_service_client.cpp index 809e5816..831cb9bc 100644 --- a/udmf/framework/innerkitsimpl/service/udmf_service_client.cpp +++ b/udmf/framework/innerkitsimpl/service/udmf_service_client.cpp @@ -105,11 +105,12 @@ void UdmfServiceClient::ServiceDeathRecipient::OnRemoteDied(const wptr<IRemoteOb int32_t UdmfServiceClient::SetData(CustomOption &option, UnifiedData &unifiedData, std::string &key) { LOG_DEBUG(UDMF_SERVICE, "start, tag: %{public}d", option.intention); - if (!UnifiedDataUtils::IsValidIntention(option.intention)) { - LOG_ERROR(UDMF_SERVICE, "Invalid intention"); - return E_INVALID_PARAMETERS; + if (option.intention == UD_INTENTION_DATA_HUB) { + if (option.visibility != Visibility::VISIBILITY_ALL && + option.visibility != Visibility::VISIBILITY_OWN_PROCESS) { + option.visibility = Visibility::VISIBILITY_ALL; + } } - if (!unifiedData.IsValid()) { LOG_ERROR(UDMF_SERVICE, "UnifiedData is invalid."); return E_INVALID_PARAMETERS; @@ -155,7 +156,8 @@ int32_t UdmfServiceClient::GetBatchData(const QueryOption &query, std::vector<Un LOG_DEBUG(UDMF_SERVICE, "start, tag: intention = %{public}d, key = %{public}s", query.intention, query.key.c_str()); auto find = UD_INTENTION_MAP.find(query.intention); std::string intention = find == UD_INTENTION_MAP.end() ? intention : find->second; - if (!UnifiedDataUtils::IsValidOptions(query.key, intention)) { + UnifiedKey key(query.key); + if (!key.IsValid() && !UnifiedDataUtils::IsValidOptionsNonDrag(key, intention)) { LOG_ERROR(UDMF_SERVICE, "invalid option, query.key: %{public}s, intention: %{public}s", query.key.c_str(), intention.c_str()); return E_INVALID_PARAMETERS; @@ -185,7 +187,16 @@ int32_t UdmfServiceClient::UpdateData(const QueryOption &query, UnifiedData &uni LOG_ERROR(UDMF_SERVICE, "invalid key, key.intention: %{public}s", key.intention.c_str()); return E_INVALID_PARAMETERS; } - + std::string intention = UnifiedDataUtils::FindIntentionMap(query.intention); + if (!UnifiedDataUtils::IsValidOptionsNonDrag(key, intention)) { + LOG_ERROR(UDMF_SERVICE, "invalid option, query.key: %{public}s, intention: %{public}s", query.key.c_str(), + intention.c_str()); + return E_INVALID_PARAMETERS; + } + if (key.intention != UD_INTENTION_MAP.at(Intention::UD_INTENTION_DATA_HUB)) { + LOG_ERROR(UDMF_SERVICE, "key.intention: %{public}s is invalid.", key.intention.c_str()); + return E_INVALID_PARAMETERS; + } if (!unifiedData.IsValid()) { LOG_ERROR(UDMF_SERVICE, "UnifiedData is invalid."); return E_INVALID_PARAMETERS; @@ -204,7 +215,8 @@ int32_t UdmfServiceClient::DeleteData(const QueryOption &query, std::vector<Unif LOG_DEBUG(UDMF_SERVICE, "start, tag: intention = %{public}d, key = %{public}s", query.intention, query.key.c_str()); auto find = UD_INTENTION_MAP.find(query.intention); std::string intention = find == UD_INTENTION_MAP.end() ? intention : find->second; - if (!UnifiedDataUtils::IsValidOptions(query.key, intention)) { + UnifiedKey key(query.key); + if (!key.IsValid() && !UnifiedDataUtils::IsValidOptionsNonDrag(key, intention)) { LOG_ERROR(UDMF_SERVICE, "invalid option, query.key: %{public}s, intention: %{public}s", query.key.c_str(), intention.c_str()); return E_INVALID_PARAMETERS; @@ -296,5 +308,22 @@ int32_t UdmfServiceClient::ClearAsynProcessByKey(const std::string &businessUdKe { return udmfProxy_->ClearAsynProcessByKey(businessUdKey); } + +int32_t UdmfServiceClient::SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptr<IRemoteObject> iUdmfNotifier, + std::string &key) +{ + return udmfProxy_->SetDelayInfo(dataLoadInfo, iUdmfNotifier, key); +} + +int32_t UdmfServiceClient::PushDelayData(const std::string &key, UnifiedData &unifiedData) +{ + return udmfProxy_->PushDelayData(key, unifiedData); +} + +int32_t UdmfServiceClient::GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr<IRemoteObject> iUdmfNotifier, std::shared_ptr<UnifiedData> unifiedData) +{ + return udmfProxy_->GetDataIfAvailable(key, dataLoadInfo, iUdmfNotifier, unifiedData); +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/service/udmf_service_client.h b/udmf/framework/innerkitsimpl/service/udmf_service_client.h index 09969676..d0813bb4 100644 --- a/udmf/framework/innerkitsimpl/service/udmf_service_client.h +++ b/udmf/framework/innerkitsimpl/service/udmf_service_client.h @@ -46,6 +46,11 @@ public: int32_t RemoveAppShareOption(const std::string &intention) override; int32_t ObtainAsynProcess(AsyncProcessInfo& processInfo) override; int32_t ClearAsynProcessByKey(const std::string &businessUdKey) override; + int32_t SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptr<IRemoteObject> iUdmfNotifier, + std::string &key) override; + int32_t PushDelayData(const std::string &key, UnifiedData &unifiedData) override; + int32_t GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr<IRemoteObject> iUdmfNotifier, std::shared_ptr<UnifiedData> unifiedData) override; private: class ServiceDeathRecipient : public IRemoteObject::DeathRecipient { diff --git a/udmf/framework/innerkitsimpl/service/udmf_service_proxy.cpp b/udmf/framework/innerkitsimpl/service/udmf_service_proxy.cpp index b34f6cb5..29a7e269 100644 --- a/udmf/framework/innerkitsimpl/service/udmf_service_proxy.cpp +++ b/udmf/framework/innerkitsimpl/service/udmf_service_proxy.cpp @@ -261,5 +261,57 @@ int32_t UdmfServiceProxy::ClearAsynProcessByKey(const std::string &businessUdKey } return E_OK; } + +int32_t UdmfServiceProxy::SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptr<IRemoteObject> iUdmfNotifier, + std::string &key) +{ + MessageParcel reply; + int32_t status = IPC_SEND(UdmfServiceInterfaceCode::SET_DELAY_INFO, reply, dataLoadInfo, iUdmfNotifier); + if (status != E_OK) { + LOG_ERROR(UDMF_SERVICE, "status:0x%{public}x", status); + return status; + } + if (!ITypesUtil::Unmarshal(reply, key)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshal status failed!"); + return E_READ_PARCEL_ERROR; + } + return E_OK; +} + +int32_t UdmfServiceProxy::PushDelayData(const std::string &key, UnifiedData &unifiedData) +{ + UdmfConversion::InitValueObject(unifiedData); + MessageParcel reply; + + int32_t status = IPC_SEND(UdmfServiceInterfaceCode::SET_DELAY_DATA, reply, key, unifiedData); + if (status != E_OK) { + LOG_ERROR(UDMF_SERVICE, "status:0x%{public}x", status); + return status; + } + return E_OK; +} + +int32_t UdmfServiceProxy::GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr<IRemoteObject> iUdmfNotifier, std::shared_ptr<UnifiedData> unifiedData) +{ + if (unifiedData == nullptr) { + LOG_ERROR(UDMF_SERVICE, "Data is null!"); + return E_INVALID_PARAMETERS; + } + MessageParcel reply; + int32_t status = IPC_SEND(UdmfServiceInterfaceCode::GET_DELAY_DATA, reply, key, dataLoadInfo, iUdmfNotifier); + if (status != E_OK) { + LOG_ERROR(UDMF_SERVICE, "status:0x%{public}x, key:%{public}s!", status, key.c_str()); + return status; + } + if (!ITypesUtil::Unmarshal(reply, *unifiedData)) { + LOG_ERROR(UDMF_SERVICE, "Unmarshal UnifiedData failed!"); + return E_READ_PARCEL_ERROR; + } + if (!unifiedData->IsEmpty()) { + UdmfConversion::ConvertRecordToSubclass(*unifiedData); + } + return status; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/service/udmf_service_proxy.h b/udmf/framework/innerkitsimpl/service/udmf_service_proxy.h index 26d01fd9..f053a6b4 100644 --- a/udmf/framework/innerkitsimpl/service/udmf_service_proxy.h +++ b/udmf/framework/innerkitsimpl/service/udmf_service_proxy.h @@ -49,6 +49,11 @@ public: int32_t RemoveAppShareOption(const std::string &intention) override; int32_t ObtainAsynProcess(AsyncProcessInfo &processInfo) override; int32_t ClearAsynProcessByKey(const std::string &businessUdKey) override; + int32_t SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptr<IRemoteObject> iUdmfNotifier, + std::string &key) override; + int32_t PushDelayData(const std::string &key, UnifiedData &unifiedData) override; + int32_t GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr<IRemoteObject> iUdmfNotifier, std::shared_ptr<UnifiedData> unifiedData) override; private: static inline BrokerDelegator<UdmfServiceProxy> delegator_; int32_t SendRequest(UdmfServiceInterfaceCode code, MessageParcel &data, diff --git a/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/BUILD.gn b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/BUILD.gn index bec6e476..4bd862a3 100644 --- a/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/BUILD.gn +++ b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/BUILD.gn @@ -47,12 +47,14 @@ ohos_fuzztest("UdmfClientFuzzTest") { "access_token:libnativetoken", "access_token:libtoken_setproc", "bundle_framework:appexecfwk_core", + "cJSON:cjson", "c_utils:utils", "hilog:libhilog", "image_framework:image", "ipc:ipc_core", "kv_store:distributeddata_inner", "samgr:samgr_proxy", + "selinux_adapter:librestorecon", ] } diff --git a/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/udmf_client_fuzzer.cpp b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/udmf_client_fuzzer.cpp index 8100bc2a..5ebbd15e 100644 --- a/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/udmf_client_fuzzer.cpp +++ b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/udmf_client_fuzzer.cpp @@ -16,6 +16,7 @@ #include "udmf_client_fuzzer.h" #include <unistd.h> +#include <fuzzer/FuzzedDataProvider.h> #include "accesstoken_kit.h" #include "nativetoken_kit.h" @@ -34,6 +35,7 @@ #include "system_defined_appitem.h" #include "system_defined_pixelmap.h" #include "udmf_async_client.h" +#include "udmf_executor.h" #include "unified_types.h" using namespace OHOS; @@ -114,10 +116,10 @@ void SetHapToken() SetSelfTokenID(tokenId); } -void SetDataTextFuzz(const uint8_t *data, size_t size) +void SetDataTextFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); UnifiedData unifiedData; CustomOption option = {.intention = Intention::UD_INTENTION_BUTT}; auto text = std::make_shared<Text>(); @@ -142,10 +144,10 @@ void SetDataTextFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataPlainTextFuzz(const uint8_t *data, size_t size) +void SetDataPlainTextFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; UDDetails details1; @@ -174,10 +176,10 @@ void SetDataPlainTextFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataHtmlFuzz(const uint8_t *data, size_t size) +void SetDataHtmlFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -206,10 +208,10 @@ void SetDataHtmlFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataLinkFuzz(const uint8_t *data, size_t size) +void SetDataLinkFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -238,9 +240,9 @@ void SetDataLinkFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataFileFuzz(const uint8_t *data, size_t size) +void SetDataFileFuzz(FuzzedDataProvider &provider) { - std::string svalue(data, data + size); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -267,9 +269,9 @@ void SetDataFileFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataImageFuzz(const uint8_t *data, size_t size) +void SetDataImageFuzz(FuzzedDataProvider &provider) { - std::string svalue(data, data + size); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -293,9 +295,9 @@ void SetDataImageFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataVideoFuzz(const uint8_t *data, size_t size) +void SetDataVideoFuzz(FuzzedDataProvider &provider) { - std::string svalue(data, data + size); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -319,10 +321,10 @@ void SetDataVideoFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataSystemDefinedRecordFuzz(const uint8_t *data, size_t size) +void SetDataSystemDefinedRecordFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -347,10 +349,10 @@ void SetDataSystemDefinedRecordFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataSystemDefinedFormFuzz(const uint8_t *data, size_t size) +void SetDataSystemDefinedFormFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -386,10 +388,10 @@ void SetDataSystemDefinedFormFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataSystemDefinedAppItemFuzz(const uint8_t *data, size_t size) +void SetDataSystemDefinedAppItemFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -426,10 +428,10 @@ void SetDataSystemDefinedAppItemFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void SetDataSystemDefinedPixelMapFuzz(const uint8_t *data, size_t size) +void SetDataSystemDefinedPixelMapFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData data1; std::string key; @@ -456,10 +458,10 @@ void SetDataSystemDefinedPixelMapFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void GetSummaryFuzz(const uint8_t *data, size_t size) +void GetSummaryFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); - std::string svalue(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); CustomOption option1 = {.intention = Intention::UD_INTENTION_DRAG}; UnifiedData UData; std::string key; @@ -510,9 +512,9 @@ void GetSummaryFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetData(option2, data2); } -void GetBatchDataByKeyFuzz(const uint8_t *data, size_t size) +void GetBatchDataByKeyFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; UnifiedData data1; std::string key; @@ -531,9 +533,9 @@ void GetBatchDataByKeyFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetBatchData(option3, dataSet3); } -void GetBatchDataByIntentionFuzz(const uint8_t *data, size_t size) +void GetBatchDataByIntentionFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; UnifiedData data1; std::string key; @@ -548,9 +550,9 @@ void GetBatchDataByIntentionFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().GetBatchData(option2, dataSet); } -void DeleteDataByKeyFuzz(const uint8_t *data, size_t size) +void DeleteDataByKeyFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; UnifiedData data1; std::string key; @@ -569,9 +571,9 @@ void DeleteDataByKeyFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().DeleteData(option3, dataSet3); } -void DeleteDataByIntentionFuzz(const uint8_t *data, size_t size) +void DeleteDataByIntentionFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; UnifiedData data1; std::string key; @@ -586,9 +588,9 @@ void DeleteDataByIntentionFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().DeleteData(option2, dataSet); } -void UpdateDataFuzz(const uint8_t *data, size_t size) +void UpdateDataFuzz(FuzzedDataProvider &provider) { - std::string skey(data, data + size); + std::string skey = provider.ConsumeRandomLengthString(); CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; UnifiedData data1; std::string key; @@ -609,13 +611,15 @@ void UpdateDataFuzz(const uint8_t *data, size_t size) UdmfClient::GetInstance().UpdateData(option3, data3); } -void StartAsyncDataRetrievalFuzz(const uint8_t *data, size_t size) +void StartAsyncDataRetrievalFuzz(FuzzedDataProvider &provider) { + size_t dataSize = provider.ConsumeIntegralInRange<size_t>(1, 50); + std::vector<uint8_t> data = provider.ConsumeBytes<uint8_t>(dataSize); CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; UnifiedData data1; std::string key; auto plainText = std::make_shared<PlainText>(); - std::string content(data, data + size); + std::string content = provider.ConsumeRandomLengthString(); plainText->SetContent(content); data1.AddRecord(plainText); UdmfClient::GetInstance().SetData(option1, data1, key); @@ -627,13 +631,15 @@ void StartAsyncDataRetrievalFuzz(const uint8_t *data, size_t size) UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); } -void CancelAsyncDataRetrievalFuzz(const uint8_t *data, size_t size) +void CancelAsyncDataRetrievalFuzz(FuzzedDataProvider &provider) { + size_t dataSize = provider.ConsumeIntegralInRange<size_t>(1, 50); + std::vector<uint8_t> data = provider.ConsumeBytes<uint8_t>(dataSize); CustomOption option1 = { .intention = UD_INTENTION_DATA_HUB }; UnifiedData data1; std::string key; auto plainText = std::make_shared<PlainText>(); - std::string content(data, data + size); + std::string content = provider.ConsumeRandomLengthString(); plainText->SetContent(content); data1.AddRecord(plainText); UdmfClient::GetInstance().SetData(option1, data1, key); @@ -647,32 +653,161 @@ void CancelAsyncDataRetrievalFuzz(const uint8_t *data, size_t size) UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); UdmfAsyncClient::GetInstance().Cancel(key); } + +void SyncFuzz(FuzzedDataProvider &provider) +{ + QueryOption query; + query.key = provider.ConsumeRandomLengthString(); + query.intention = static_cast<Intention>( + provider.ConsumeIntegralInRange<int32_t>(UD_INTENTION_BASE + 1, UD_INTENTION_BUTT - 1)); + query.tokenId = provider.ConsumeIntegral<uint32_t>(); + + std::vector<std::string> devices; + size_t devicesSize = provider.ConsumeIntegralInRange<size_t>(0, 10); + for (size_t i = 0; i < devicesSize; ++i) { + devices.push_back(provider.ConsumeRandomLengthString()); + } + UdmfClient::GetInstance().Sync(query, devices); +} + +void IsRemoteDataFuzz(FuzzedDataProvider &provider) +{ + QueryOption query; + query.key = provider.ConsumeRandomLengthString(); + query.intention = static_cast<Intention>( + provider.ConsumeIntegralInRange<int32_t>(UD_INTENTION_BASE + 1, UD_INTENTION_BUTT - 1)); + query.tokenId = provider.ConsumeIntegral<uint32_t>(); + bool res = false; + UdmfClient::GetInstance().IsRemoteData(query, res); +} + +void SetAppShareOptionFuzz(FuzzedDataProvider &provider) +{ + Intention intention = static_cast<Intention>( + provider.ConsumeIntegralInRange<int32_t>(UD_INTENTION_BASE + 1, UD_INTENTION_BUTT - 1)); + std::string intentionStr = UD_INTENTION_MAP.at(intention); + + ShareOptions shareOption = static_cast<ShareOptions>( + provider.ConsumeIntegralInRange<int32_t>(IN_APP, SHARE_OPTIONS_BUTT)); + UdmfClient::GetInstance().SetAppShareOption(intentionStr, shareOption); +} + +void GetAppShareOptionFuzz(FuzzedDataProvider &provider) +{ + Intention intention = static_cast<Intention>( + provider.ConsumeIntegralInRange<int32_t>(UD_INTENTION_BASE + 1, UD_INTENTION_BUTT - 1)); + std::string intentionStr = UD_INTENTION_MAP.at(intention); + + ShareOptions shareOption; + UdmfClient::GetInstance().GetAppShareOption(intentionStr, shareOption); +} + +void RemoveAppShareOptionFuzz(FuzzedDataProvider &provider) +{ + Intention intention = static_cast<Intention>( + provider.ConsumeIntegralInRange<int32_t>(UD_INTENTION_BASE + 1, UD_INTENTION_BUTT - 1)); + std::string intentionStr = UD_INTENTION_MAP.at(intention); + UdmfClient::GetInstance().RemoveAppShareOption(intentionStr); +} + +void GetParentTypeFuzz(FuzzedDataProvider &provider) +{ + Summary oldSummary; + Summary newSummary; + + size_t summarySize = provider.ConsumeIntegralInRange<size_t>(0, 10); + for (size_t i = 0; i < summarySize; ++i) { + std::string key = provider.ConsumeRandomLengthString(); + int64_t value = provider.ConsumeIntegral<int64_t>(); + oldSummary.summary[key] = value; + } + oldSummary.totalSize = provider.ConsumeIntegral<int64_t>(); + UdmfClient::GetInstance().GetParentType(oldSummary, newSummary); +} + +void SetDelayInfoFuzz(FuzzedDataProvider &provider) +{ + DataLoadInfo dataLoadInfo1 { + .sequenceKey = provider.ConsumeRandomLengthString(), + .types{ provider.ConsumeRandomLengthString() }, + .recordCount = provider.ConsumeIntegral<uint32_t>(), + }; + auto loadHandler = [] (const std::string &udKey, const DataLoadInfo &dataLoadInfo) {}; + DataLoadParams dataLoadParams = { + .loadHandler = loadHandler, + .dataLoadInfo = dataLoadInfo1, + }; + std::string key = provider.ConsumeRandomLengthString(); + UdmfClient::GetInstance().SetDelayInfo(dataLoadParams, key); +} + +void PushDelayDataFuzz(FuzzedDataProvider &provider) +{ + DataLoadInfo dataLoadInfo1{ + .sequenceKey = provider.ConsumeRandomLengthString(), + .types{provider.ConsumeRandomLengthString()}, + .recordCount = provider.ConsumeIntegral<uint32_t>(), + }; + auto loadHandler = [] (const std::string &udKey, const DataLoadInfo &dataLoadInfo) {}; + DataLoadParams dataLoadParams = { + .loadHandler = loadHandler, + .dataLoadInfo = dataLoadInfo1, + }; + std::string key = provider.ConsumeRandomLengthString(); + UdmfClient::GetInstance().SetDelayInfo(dataLoadParams, key); + + auto text = std::make_shared<Text>(); + UDDetails details; + std::string skey = provider.ConsumeRandomLengthString(); + std::string svalue = provider.ConsumeRandomLengthString(); + details.insert({skey, svalue}); + text->SetDetails(details); + UnifiedData unifiedData; + unifiedData.AddRecord(text); + UdmfClient::GetInstance().PushDelayData(key, unifiedData); +} + +void GetBundleNameByUdKeyFuzz(FuzzedDataProvider &provider) +{ + std::string key = provider.ConsumeRandomLengthString(); + UdmfClient::GetInstance().GetBundleNameByUdKey(key); +} } /* Fuzzer entry point */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Run your code on data */ + FuzzedDataProvider provider(data, size); OHOS::SetUpTestCase(); - OHOS::SetDataFileFuzz(data, size); - OHOS::SetDataHtmlFuzz(data, size); - OHOS::SetDataImageFuzz(data, size); - OHOS::SetDataLinkFuzz(data, size); - OHOS::SetDataPlainTextFuzz(data, size); - OHOS::SetDataSystemDefinedAppItemFuzz(data, size); - OHOS::SetDataSystemDefinedFormFuzz(data, size); - OHOS::SetDataSystemDefinedPixelMapFuzz(data, size); - OHOS::SetDataSystemDefinedRecordFuzz(data, size); - OHOS::SetDataTextFuzz(data, size); - OHOS::SetDataVideoFuzz(data, size); - OHOS::GetSummaryFuzz(data, size); - OHOS::GetBatchDataByKeyFuzz(data, size); - OHOS::GetBatchDataByIntentionFuzz(data, size); - OHOS::DeleteDataByKeyFuzz(data, size); - OHOS::DeleteDataByIntentionFuzz(data, size); - OHOS::UpdateDataFuzz(data, size); - OHOS::StartAsyncDataRetrievalFuzz(data, size); - OHOS::CancelAsyncDataRetrievalFuzz(data, size); + OHOS::SetDataFileFuzz(provider); + OHOS::SetDataHtmlFuzz(provider); + OHOS::SetDataImageFuzz(provider); + OHOS::SetDataLinkFuzz(provider); + OHOS::SetDataPlainTextFuzz(provider); + OHOS::SetDataSystemDefinedAppItemFuzz(provider); + OHOS::SetDataSystemDefinedFormFuzz(provider); + OHOS::SetDataSystemDefinedPixelMapFuzz(provider); + OHOS::SetDataSystemDefinedRecordFuzz(provider); + OHOS::SetDataTextFuzz(provider); + OHOS::SetDataVideoFuzz(provider); + OHOS::GetSummaryFuzz(provider); + OHOS::GetBatchDataByKeyFuzz(provider); + OHOS::GetBatchDataByIntentionFuzz(provider); + OHOS::DeleteDataByKeyFuzz(provider); + OHOS::DeleteDataByIntentionFuzz(provider); + OHOS::UpdateDataFuzz(provider); + OHOS::StartAsyncDataRetrievalFuzz(provider); + OHOS::CancelAsyncDataRetrievalFuzz(provider); + OHOS::SyncFuzz(provider); + OHOS::IsRemoteDataFuzz(provider); + OHOS::SetAppShareOptionFuzz(provider); + OHOS::GetAppShareOptionFuzz(provider); + OHOS::RemoveAppShareOptionFuzz(provider); + OHOS::GetParentTypeFuzz(provider); + OHOS::SetDelayInfoFuzz(provider); + OHOS::PushDelayDataFuzz(provider); + OHOS::GetBundleNameByUdKeyFuzz(provider); OHOS::TearDown(); return 0; } \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/fuzztest/utdclient_fuzzer/BUILD.gn b/udmf/framework/innerkitsimpl/test/fuzztest/utdclient_fuzzer/BUILD.gn index fffef287..04ce893c 100644 --- a/udmf/framework/innerkitsimpl/test/fuzztest/utdclient_fuzzer/BUILD.gn +++ b/udmf/framework/innerkitsimpl/test/fuzztest/utdclient_fuzzer/BUILD.gn @@ -36,7 +36,7 @@ ohos_fuzztest("UtdClientFuzzTest") { deps = [ "${udmf_interfaces_path}/innerkits:utd_client" ] - external_deps = [] + external_deps = [ "c_utils:utils" ] } ############################################################################### diff --git a/udmf/framework/innerkitsimpl/test/fuzztest/utdclient_fuzzer/utd_client_fuzzer.cpp b/udmf/framework/innerkitsimpl/test/fuzztest/utdclient_fuzzer/utd_client_fuzzer.cpp index 9e98e30b..97d2b309 100644 --- a/udmf/framework/innerkitsimpl/test/fuzztest/utdclient_fuzzer/utd_client_fuzzer.cpp +++ b/udmf/framework/innerkitsimpl/test/fuzztest/utdclient_fuzzer/utd_client_fuzzer.cpp @@ -16,6 +16,8 @@ #include "utd_client_fuzzer.h" #include "utd_client.h" +#include <fuzzer/FuzzedDataProvider.h> + using namespace OHOS; using namespace OHOS::UDMF; @@ -28,76 +30,76 @@ void TearDown() { } -void GetTypeDescriptorFuzz(const uint8_t *data, size_t size) +void GetTypeDescriptorFuzz(FuzzedDataProvider &provider) { - std::string typeId(data, data + size); + std::string typeId = provider.ConsumeRandomLengthString(); std::shared_ptr<TypeDescriptor> typeDescriptor; UtdClient::GetInstance().GetTypeDescriptor(typeId, typeDescriptor); } -void GetUniformDataTypeByFilenameExtensionDefaultBelongsFuzz(const uint8_t *data, size_t size) +void GetUniformDataTypeByFilenameExtensionDefaultBelongsFuzz(FuzzedDataProvider &provider) { - std::string fileExtension(data, data + size); + std::string fileExtension = provider.ConsumeRandomLengthString(); std::string typeId; UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(fileExtension, typeId); } -void GetUniformDataTypeByFilenameExtensionFuzz(const uint8_t *data, size_t size) +void GetUniformDataTypeByFilenameExtensionFuzz(FuzzedDataProvider &provider) { - std::string fileExtension(data, data + size); + std::string fileExtension = provider.ConsumeRandomLengthString(); std::string typeId; - std::string belongsTo(data, data + size); + std::string belongsTo = provider.ConsumeRandomLengthString(); UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(fileExtension, typeId, belongsTo); } -void GetUniformDataTypesByFilenameExtensionDefaultBelongsFuzz(const uint8_t *data, size_t size) +void GetUniformDataTypesByFilenameExtensionDefaultBelongsFuzz(FuzzedDataProvider &provider) { - std::string fileExtension(data, data + size); + std::string fileExtension = provider.ConsumeRandomLengthString(); std::vector<std::string> typeIds; UtdClient::GetInstance().GetUniformDataTypesByFilenameExtension(fileExtension, typeIds); } -void GetUniformDataTypesByFilenameExtensionFuzz(const uint8_t *data, size_t size) +void GetUniformDataTypesByFilenameExtensionFuzz(FuzzedDataProvider &provider) { - std::string fileExtension(data, data + size); + std::string fileExtension = provider.ConsumeRandomLengthString(); std::vector<std::string> typeIds; - std::string belongsTo(data, data + size); + std::string belongsTo = provider.ConsumeRandomLengthString(); UtdClient::GetInstance().GetUniformDataTypesByFilenameExtension(fileExtension, typeIds, belongsTo); } -void GetUniformDataTypeByMIMETypeDefaultBelongsFuzz(const uint8_t *data, size_t size) +void GetUniformDataTypeByMIMETypeDefaultBelongsFuzz(FuzzedDataProvider &provider) { - std::string mimeType(data, data + size); + std::string mimeType = provider.ConsumeRandomLengthString(); std::string typeId; UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, typeId); } -void GetUniformDataTypeByMIMETypeFuzz(const uint8_t *data, size_t size) +void GetUniformDataTypeByMIMETypeFuzz(FuzzedDataProvider &provider) { - std::string mimeType(data, data + size); + std::string mimeType = provider.ConsumeRandomLengthString(); std::string typeId; - std::string belongsTo(data, data + size); + std::string belongsTo = provider.ConsumeRandomLengthString(); UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, typeId, belongsTo); } -void GetUniformDataTypesByMIMETypeDefaultBelongsFuzz(const uint8_t *data, size_t size) +void GetUniformDataTypesByMIMETypeDefaultBelongsFuzz(FuzzedDataProvider &provider) { - std::string mimeType(data, data + size); + std::string mimeType = provider.ConsumeRandomLengthString(); std::vector<std::string> typeIds; UtdClient::GetInstance().GetUniformDataTypesByMIMEType(mimeType, typeIds); } -void GetUniformDataTypesByMIMETypeFuzz(const uint8_t *data, size_t size) +void GetUniformDataTypesByMIMETypeFuzz(FuzzedDataProvider &provider) { - std::string mimeType(data, data + size); + std::string mimeType = provider.ConsumeRandomLengthString(); std::vector<std::string> typeIds; - std::string belongsTo(data, data + size); + std::string belongsTo = provider.ConsumeRandomLengthString(); UtdClient::GetInstance().GetUniformDataTypesByMIMEType(mimeType, typeIds, belongsTo); } -void IsUtdFuzz(const uint8_t *data, size_t size) +void IsUtdFuzz(FuzzedDataProvider &provider) { - std::string typeId(data, data + size); + std::string typeId = provider.ConsumeRandomLengthString(); bool result; UtdClient::GetInstance().IsUtd(typeId, result); } @@ -107,16 +109,17 @@ void IsUtdFuzz(const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { /* Run your code on data */ + FuzzedDataProvider provider(data, size); OHOS::SetUpTestCase(); - OHOS::GetTypeDescriptorFuzz(data, size); - OHOS::GetUniformDataTypeByFilenameExtensionDefaultBelongsFuzz(data, size); - OHOS::GetUniformDataTypeByFilenameExtensionFuzz(data, size); - OHOS::GetUniformDataTypesByFilenameExtensionDefaultBelongsFuzz(data, size); - OHOS::GetUniformDataTypesByFilenameExtensionFuzz(data, size); - OHOS::GetUniformDataTypeByMIMETypeDefaultBelongsFuzz(data, size); - OHOS::GetUniformDataTypeByMIMETypeFuzz(data, size); - OHOS::GetUniformDataTypesByMIMETypeDefaultBelongsFuzz(data, size); - OHOS::GetUniformDataTypesByMIMETypeFuzz(data, size); - OHOS::IsUtdFuzz(data, size); + OHOS::GetTypeDescriptorFuzz(provider); + OHOS::GetUniformDataTypeByFilenameExtensionDefaultBelongsFuzz(provider); + OHOS::GetUniformDataTypeByFilenameExtensionFuzz(provider); + OHOS::GetUniformDataTypesByFilenameExtensionDefaultBelongsFuzz(provider); + OHOS::GetUniformDataTypesByFilenameExtensionFuzz(provider); + OHOS::GetUniformDataTypeByMIMETypeDefaultBelongsFuzz(provider); + OHOS::GetUniformDataTypeByMIMETypeFuzz(provider); + OHOS::GetUniformDataTypesByMIMETypeDefaultBelongsFuzz(provider); + OHOS::GetUniformDataTypesByMIMETypeFuzz(provider); + OHOS::IsUtdFuzz(provider); return 0; } \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn b/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn index 6e4d149b..8259e9e4 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn +++ b/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn @@ -13,7 +13,7 @@ import("//build/test.gni") import("//foundation/distributeddatamgr/udmf/udmf.gni") -module_output_path = "udmf/innerkitsImpl" +module_output_path = "udmf/udmf/innerkitsImpl" ############################################################################### config("module_private_config") { @@ -21,11 +21,13 @@ config("module_private_config") { "${udmf_interfaces_path}/innerkits/client", "${udmf_interfaces_path}/innerkits/common", "${udmf_interfaces_path}/innerkits/data", + "${udmf_interfaces_path}/innerkits/dynamic", "${udmf_interfaces_path}/innerkits/convert", "${udmf_interfaces_path}/ndk/data", "${udmf_framework_path}/common", "${udmf_framework_path}/innerkitsimpl/data", "${udmf_framework_path}/innerkitsimpl/client/", + "${udmf_framework_path}/innerkitsimpl/service", "${udmf_framework_path}/innerkitsimpl/test/unittest/mock/include", "${udmf_framework_path}/ndkimpl/data", ] @@ -41,25 +43,24 @@ common_external_deps = [ "ability_base:base", "ability_base:want", "ability_base:zuri", + "ability_runtime:dataobs_manager", "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "access_token:libtoken_setproc", "app_file_service:fileuri_native", "bundle_framework:appexecfwk_core", "c_utils:utils", - "ffmpeg:libohosffmpeg", + "dfs_service:distributed_file_daemon_kit_inner", "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", "hitrace:libhitracechain", "image_framework:image", - "image_framework:image", "image_framework:image_native", "image_framework:pixelmap", "ipc:ipc_core", "kv_store:distributeddata_inner", "kv_store:distributeddata_mgr", - "libexif:libexif", "samgr:samgr_proxy", ] @@ -68,8 +69,12 @@ ohos_unittest("UdmfClientTest") { sources = [ "${udmf_framework_path}/common/graph.cpp", + "${udmf_framework_path}/common/udmf_copy_file.cpp", + "${udmf_framework_path}/common/udmf_executor.cpp", "${udmf_framework_path}/common/udmf_utils.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_async_client.cpp", "${udmf_framework_path}/innerkitsimpl/client/udmf_client.cpp", + "${udmf_framework_path}/innerkitsimpl/common/progress_queue.cpp", "${udmf_framework_path}/innerkitsimpl/convert/udmf_conversion.cpp", "${udmf_framework_path}/innerkitsimpl/data/application_defined_record.cpp", "${udmf_framework_path}/innerkitsimpl/data/audio.cpp", @@ -86,6 +91,9 @@ ohos_unittest("UdmfClientTest") { "${udmf_framework_path}/innerkitsimpl/data/text.cpp", "${udmf_framework_path}/innerkitsimpl/data/unified_data.cpp", "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", + "${udmf_framework_path}/innerkitsimpl/service/progress_callback.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_notifier_stub.cpp", "${udmf_framework_path}/innerkitsimpl/service/udmf_service_client.cpp", "${udmf_framework_path}/innerkitsimpl/service/udmf_service_proxy.cpp", "udmf_client_test.cpp", @@ -93,6 +101,56 @@ ohos_unittest("UdmfClientTest") { configs = [ ":module_private_config" ] + use_exceptions = true + + deps = common_deps + + external_deps = common_external_deps + + defines = [ + "private=public", + "protected=public", + ] +} + +ohos_unittest("UdmfClientFileMangerTest") { + module_out_path = module_output_path + + sources = [ + "${udmf_framework_path}/common/udmf_copy_file.cpp", + "${udmf_framework_path}/common/udmf_executor.cpp", + "${udmf_framework_path}/common/udmf_utils.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_async_client.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_client.cpp", + "${udmf_framework_path}/innerkitsimpl/common/progress_queue.cpp", + "${udmf_framework_path}/innerkitsimpl/convert/udmf_conversion.cpp", + "${udmf_framework_path}/innerkitsimpl/data/application_defined_record.cpp", + "${udmf_framework_path}/innerkitsimpl/data/audio.cpp", + "${udmf_framework_path}/innerkitsimpl/data/file.cpp", + "${udmf_framework_path}/innerkitsimpl/data/folder.cpp", + "${udmf_framework_path}/innerkitsimpl/data/html.cpp", + "${udmf_framework_path}/innerkitsimpl/data/image.cpp", + "${udmf_framework_path}/innerkitsimpl/data/link.cpp", + "${udmf_framework_path}/innerkitsimpl/data/plain_text.cpp", + "${udmf_framework_path}/innerkitsimpl/data/system_defined_appitem.cpp", + "${udmf_framework_path}/innerkitsimpl/data/system_defined_form.cpp", + "${udmf_framework_path}/innerkitsimpl/data/system_defined_pixelmap.cpp", + "${udmf_framework_path}/innerkitsimpl/data/system_defined_record.cpp", + "${udmf_framework_path}/innerkitsimpl/data/text.cpp", + "${udmf_framework_path}/innerkitsimpl/data/unified_data.cpp", + "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", + "${udmf_framework_path}/innerkitsimpl/service/progress_callback.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_notifier_stub.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_service_client.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_service_proxy.cpp", + "udmf_client_file_manger_test.cpp", + ] + + configs = [ ":module_private_config" ] + + use_exceptions = true + deps = common_deps external_deps = common_external_deps @@ -149,7 +207,42 @@ ohos_unittest("UdmfClientSaInvokeTest") { ohos_unittest("UdmfAsyncClientTest") { module_out_path = module_output_path - sources = [ "udmf_async_client_test.cpp" ] + configs = [ ":module_private_config" ] + + sources = [ + "udmf_async_client_test.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_async_client.cpp", + "${udmf_framework_path}/innerkitsimpl/common/progress_queue.cpp", + "${udmf_framework_path}/common/udmf_executor.cpp", + "${udmf_framework_path}/innerkitsimpl/service/progress_callback.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_client.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_service_client.cpp", + "${udmf_framework_path}/innerkitsimpl/data/unified_data.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_notifier_stub.cpp", + "${udmf_framework_path}/common/udmf_copy_file.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_service_proxy.cpp", + "${udmf_framework_path}/innerkitsimpl/convert/udmf_conversion.cpp", + "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + ] + + deps = [ + "${udmf_interfaces_path}/innerkits:udmf_client", + "${udmf_interfaces_path}/innerkits:utd_client", + "${udmf_interfaces_path}/ndk:libudmf" + ] + + external_deps = common_external_deps + + defines = [ + "private=public", + "protected=public", + ] +} + +ohos_unittest("UdmfDelayDataTest") { + module_out_path = module_output_path + + sources = [ "udmf_delay_data_test.cpp" ] deps = common_deps @@ -193,10 +286,50 @@ ohos_unittest("UtdClientTest") { ] } +ohos_unittest("UtdConcurrentUpdateTest") { + module_out_path = module_output_path + + sources = [ + "${udmf_framework_path}/common/base32_utils.cpp", + "${udmf_framework_path}/common/custom_utd_json_parser.cpp", + "${udmf_framework_path}/common/custom_utd_store.cpp", + "${udmf_framework_path}/common/graph.cpp", + "${udmf_framework_path}/common/udmf_utils.cpp", + "${udmf_framework_path}/common/utd_cfgs_checker.cpp", + "${udmf_framework_path}/common/utd_graph.cpp", + "${udmf_framework_path}/innerkitsimpl/client/utd_client.cpp", + "${udmf_framework_path}/innerkitsimpl/data/flexible_type.cpp", + "${udmf_framework_path}/innerkitsimpl/data/preset_type_descriptors.cpp", + "${udmf_framework_path}/innerkitsimpl/data/type_descriptor.cpp", + "utd_concurrent_update_test.cpp", + ] + + configs = [ ":module_private_config" ] + + use_exceptions = true + + external_deps = common_external_deps + external_deps += [ + "cJSON:cjson", + "os_account:os_account_innerkits", + ] + + defines = [ + "private=public", + "protected=public", + ] +} + ohos_unittest("NdkDataConversionTest") { module_out_path = module_output_path - sources = [ "ndk_data_conversion_test.cpp" ] + sources = [ + "${udmf_framework_path}/innerkitsimpl/data/system_defined_pixelmap.cpp", + "${udmf_framework_path}/innerkitsimpl/data/system_defined_record.cpp", + "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", + "ndk_data_conversion_test.cpp", + ] configs = [ ":module_private_config" ] @@ -399,6 +532,27 @@ ohos_unittest("PlainTextTest") { ] } +ohos_unittest("PresetTypeDescriptorsTest") { + module_out_path = module_output_path + + sources = [ + "${udmf_framework_path}/common/custom_utd_json_parser.cpp", + "${udmf_framework_path}/innerkitsimpl/data/preset_type_descriptors.cpp", + "preset_type_descriptor_test.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = common_deps + + external_deps = common_external_deps + + defines = [ + "private=public", + "protected=public", + ] +} + ohos_unittest("SystemDefinedAppitemTest") { module_out_path = module_output_path @@ -406,6 +560,7 @@ ohos_unittest("SystemDefinedAppitemTest") { "${udmf_framework_path}/innerkitsimpl/data/system_defined_appitem.cpp", "${udmf_framework_path}/innerkitsimpl/data/system_defined_record.cpp", "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", "system_defined_appitem_test.cpp", ] @@ -450,6 +605,7 @@ ohos_unittest("SystemDefinedPixelMapTest") { "${udmf_framework_path}/innerkitsimpl/data/system_defined_pixelmap.cpp", "${udmf_framework_path}/innerkitsimpl/data/system_defined_record.cpp", "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", "system_defined_pixelmap_test.cpp", ] @@ -600,17 +756,36 @@ ohos_unittest("UnifiedMetaTest") { ] } +ohos_unittest("UnifiedKeyTest") { + module_out_path = module_output_path + + sources = [ "unified_key_test.cpp" ] + + deps = common_deps + + external_deps = common_external_deps + + defines = [ + "private=public", + "protected=public", + ] +} + ohos_unittest("UdmfClientAbnormalTest") { module_out_path = module_output_path sources = [ "${udmf_framework_path}/common/endian_converter.cpp", "${udmf_framework_path}/common/tlv_util.cpp", + "${udmf_framework_path}/common/udmf_copy_file.cpp", + "${udmf_framework_path}/common/udmf_executor.cpp", "${udmf_framework_path}/common/udmf_radar_reporter.cpp", "${udmf_framework_path}/common/udmf_types_util.cpp", "${udmf_framework_path}/common/udmf_utils.cpp", "${udmf_framework_path}/innerkitsimpl/client/getter_system.cpp", + "${udmf_framework_path}/innerkitsimpl/client/udmf_async_client.cpp", "${udmf_framework_path}/innerkitsimpl/client/udmf_client.cpp", + "${udmf_framework_path}/innerkitsimpl/common/progress_queue.cpp", "${udmf_framework_path}/innerkitsimpl/common/unified_key.cpp", "${udmf_framework_path}/innerkitsimpl/common/unified_meta.cpp", "${udmf_framework_path}/innerkitsimpl/convert/udmf_conversion.cpp", @@ -630,6 +805,9 @@ ohos_unittest("UdmfClientAbnormalTest") { "${udmf_framework_path}/innerkitsimpl/data/unified_html_record_process.cpp", "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", "${udmf_framework_path}/innerkitsimpl/data/video.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", + "${udmf_framework_path}/innerkitsimpl/service/progress_callback.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_notifier_stub.cpp", "${udmf_framework_path}/innerkitsimpl/service/udmf_service_proxy.cpp", "${udmf_framework_path}/innerkitsimpl/test/unittest/mock/system_defined_pixelmap_mock.cpp", "${udmf_framework_path}/innerkitsimpl/test/unittest/mock/tlv_object_mock.cpp", @@ -639,14 +817,17 @@ ohos_unittest("UdmfClientAbnormalTest") { configs = [ ":module_private_config" ] - deps = [ - "${udmf_interfaces_path}/innerkits:utd_client", - "//third_party/googletest:gmock_main", - "//third_party/googletest:gtest_main", - ] + use_exceptions = true + + deps = [ "${udmf_interfaces_path}/innerkits:utd_client" ] external_deps = common_external_deps + external_deps += [ + "googletest:gmock_main", + "googletest:gtest_main", + ] + defines = [ "private=public", "protected=public", @@ -668,22 +849,27 @@ group("unittest") { ":LinkTest", ":NdkDataConversionTest", ":PlainTextTest", + ":PresetTypeDescriptorsTest", ":SystemDefinedAppitemTest", ":SystemDefinedFormTest", ":SystemDefinedPixelMapTest", ":SystemDefinedRecordTest", ":TextTest", + ":UnifiedKeyTest", ":UdmfAsyncClientTest", ":UdmfClientAbnormalTest", + ":UdmfClientFileMangerTest", ":UdmfClientHapPermissionTest", ":UdmfClientSaInvokeTest", ":UdmfClientSystemHapTest", ":UdmfClientTest", + ":UdmfDelayDataTest", ":UnifiedDataHelperTest", ":UnifiedDataTest", ":UnifiedMetaTest", ":UnifiedRecordTest", ":UtdClientTest", + ":UtdConcurrentUpdateTest", ":VideoTest", ] } diff --git a/udmf/framework/innerkitsimpl/test/unittest/custom_utd_store_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/custom_utd_store_test.cpp index 9cd67523..3931a2dc 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/custom_utd_store_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/custom_utd_store_test.cpp @@ -99,7 +99,7 @@ HWTEST_F(CustomUtdStoreTest, SaveTypeCfgs001, TestSize.Level1) EXPECT_EQ(status, E_OK); typesCfg.clear(); - typesCfg = CustomUtdStore::GetInstance().GetTypeCfgs(USERID); + typesCfg = CustomUtdStore::GetInstance().GetCustomUtd(false, USERID); TypeDescriptorCfg type1 = *(typesCfg.begin()); EXPECT_EQ(type1.typeId, "com.example.utdtest.document"); EXPECT_EQ(*(type1.belongingToTypes.begin()), "com.example.utdtest2.document"); @@ -113,4 +113,284 @@ HWTEST_F(CustomUtdStoreTest, SaveTypeCfgs001, TestSize.Level1) LOG_INFO(UDMF_TEST, "SaveTypeCfgs001 end."); } + +/** +* @tc.name: GetCustomUtdPathTest001 +* @tc.desc: GetCustomUtdPath +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, GetCustomUtdPathTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetCustomUtdPathTest001 begin."); + + std::string path = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + EXPECT_EQ(path, "/data/service/el1/1000000/utdtypes/utd/utd-adt.json"); + + LOG_INFO(UDMF_TEST, "GetCustomUtdPathTest001 end."); +} + +/** +* @tc.name: GetCustomUtdPathTest002 +* @tc.desc: GetCustomUtdPath +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, GetCustomUtdPathTest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetCustomUtdPathTest002 begin."); + + std::string path = CustomUtdStore::GetInstance().GetCustomUtdPath(true, USERID); + EXPECT_EQ(path, "/data/utd/utd-adt.json"); + + LOG_INFO(UDMF_TEST, "GetCustomUtdPathTest002 end."); +} + +/** +* @tc.name: GetCustomUtdInfoTest001 +* @tc.desc: GetCustomUtdInfo +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, GetCustomUtdInfoTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetCustomUtdInfoTest001 begin."); + + UtdFileInfo info = CustomUtdStore::GetInstance().GetCustomUtdInfo(true, USERID); + EXPECT_EQ(info.size, 0); + + LOG_INFO(UDMF_TEST, "GetCustomUtdInfoTest001 end."); +} + +/** +* @tc.name: GetCustomUtdInfoTest002 +* @tc.desc: GetCustomUtdInfo +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, GetCustomUtdInfoTest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetCustomUtdInfoTest002 begin."); + + UtdFileInfo info = CustomUtdStore::GetInstance().GetCustomUtdInfo(false, USERID); + EXPECT_EQ(info.size, strlen(TEST_DATA2) + 2); + auto customUtds = CustomUtdStore::GetInstance().GetCustomUtd(false, USERID); + EXPECT_EQ(customUtds.size(), 2); + + LOG_INFO(UDMF_TEST, "GetCustomUtdInfoTest002 end."); +} + +/** +* @tc.name: ParseStoredCustomUtdJson001 +* @tc.desc: empty json +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, ParseStoredCustomUtdJson001, TestSize.Level1) { + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson001 begin."); + CustomUtdJsonParser parser; + std::vector<TypeDescriptorCfg> typesCfg; + bool ret = parser.ParseStoredCustomUtdJson("", typesCfg); + + EXPECT_FALSE(ret); + EXPECT_TRUE(typesCfg.empty()); + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson001 end."); +} + +/** +* @tc.name: ParseStoredCustomUtdJson002 +* @tc.desc: Invalid Format +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, ParseStoredCustomUtdJson002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson002 begin."); + const std::string invalidJson = R"({ + "UniformDataTypeDeclarations": [] + )"; // syntax error + + CustomUtdJsonParser parser; + std::vector<TypeDescriptorCfg> typesCfg; + bool ret = parser.ParseStoredCustomUtdJson(invalidJson, typesCfg); + + EXPECT_FALSE(ret); + EXPECT_TRUE(typesCfg.empty()); + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson002 end."); +} + +/** +* @tc.name: ParseStoredCustomUtdJson003 +* @tc.desc: invalid json +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, ParseStoredCustomUtdJson003, TestSize.Level1) { + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson003 begin."); + CustomUtdJsonParser parser; + std::vector<TypeDescriptorCfg> typesCfg; + std::string invalidJson = "{invalid_json}"; + EXPECT_FALSE(parser.ParseStoredCustomUtdJson(invalidJson, typesCfg)); + EXPECT_TRUE(typesCfg.empty()); + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson003 end."); +} + +/** +* @tc.name: ParseStoredCustomUtdJson004 +* @tc.desc: root not object +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, ParseStoredCustomUtdJson004, TestSize.Level1) { + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson004 begin."); + const std::string rootArrayJson = R"([ + { "TypeId": "com.example.custom.image" } + ])"; + + CustomUtdJsonParser parser; + std::vector<TypeDescriptorCfg> typesCfg; + bool ret = parser.ParseStoredCustomUtdJson(rootArrayJson, typesCfg); + + EXPECT_FALSE(ret); + EXPECT_TRUE(typesCfg.empty()); + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson004 end."); +} + +/** +* @tc.name: ParseStoredCustomUtdJson005 +* @tc.desc: valid json +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, ParseStoredCustomUtdJson005, TestSize.Level1) { + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson005 begin."); + + const std::string validJson = R"({ + "CustomUTDs": [ + { + "TypeId": "com.example.custom.image", + "BelongingToTypes": ["general.image"], + "FilenameExtensions": [".img", ".pic"], + "MIMETypes": ["application/img", "application/pic"], + "Description": "Custom image type", + "ReferenceURL": "" + } + ] + })"; + + CustomUtdJsonParser parser; + std::vector<TypeDescriptorCfg> typesCfg; + bool ret = parser.ParseStoredCustomUtdJson(validJson, typesCfg); + + EXPECT_TRUE(ret); + ASSERT_EQ(typesCfg.size(), 1u); + EXPECT_EQ(typesCfg[0].typeId, "com.example.custom.image"); + EXPECT_EQ(typesCfg[0].belongingToTypes.size(), 1u); + EXPECT_EQ(typesCfg[0].belongingToTypes[0], "general.image"); + + LOG_INFO(UDMF_TEST, "ParseStoredCustomUtdJson005 end."); +} + +/** + * @tc.name: ParseUserCustomUtdJsonTest001 + * @tc.desc: parse a valid JSON containing declarations and references. + * @tc.type: FUNC + */ +HWTEST_F(CustomUtdStoreTest, ParseUserCustomUtdJsonTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ParseUserCustomUtdJsonTest001 begin."); + const char *testJson = R"({ + "UniformDataTypeDeclarations": [ + { + "TypeId": "com.example.thread.image", + "BelongingToTypes": ["general.image"], + "FilenameExtensions": [".myImage", ".khImage"], + "MIMETypes": ["application/myImage", "application/khImage"], + "Description": "My Image.", + "ReferenceURL": "" + } + ], + "ReferenceUniformDataTypeDeclarations": [ + { + "TypeId": "com.example.thread.audio", + "BelongingToTypes": ["general.audio"], + "FilenameExtensions": [".myAudio", ".khAudio"], + "MIMETypes": ["application/myAudio", "application/khAudio"], + "Description": "My audio.", + "ReferenceURL": "" + } + ] + })"; + + std::vector<TypeDescriptorCfg> declarations; + std::vector<TypeDescriptorCfg> references; + + CustomUtdJsonParser parser; + bool result = parser.ParseUserCustomUtdJson(testJson, declarations, references); + + EXPECT_TRUE(result); + EXPECT_EQ(declarations.size(), 1); + EXPECT_EQ(references.size(), 1); + + EXPECT_EQ(declarations[0].typeId, "com.example.thread.image"); + EXPECT_EQ(references[0].typeId, "com.example.thread.audio"); + LOG_INFO(UDMF_TEST, "ParseUserCustomUtdJsonTest001 end."); +} + +/** + * @tc.name: ParseUserCustomUtdJsonTest002 + * @tc.desc: Verify ParseUserCustomUtdJson returns false when given empty JSON string. + * @tc.type: FUNC + */ +HWTEST_F(CustomUtdStoreTest, ParseUserCustomUtdJsonTest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ParseUserCustomUtdJsonTest002 begin."); + std::vector<TypeDescriptorCfg> declarations; + std::vector<TypeDescriptorCfg> references; + + CustomUtdJsonParser parser; + bool result = parser.ParseUserCustomUtdJson("", declarations, references); + + EXPECT_FALSE(result); + EXPECT_TRUE(declarations.empty()); + EXPECT_TRUE(references.empty()); + LOG_INFO(UDMF_TEST, "ParseUserCustomUtdJsonTest002 end."); +} + +/** + * @tc.name: ParseUserCustomUtdJsonTest003 + * @tc.desc: Verify ParseUserCustomUtdJson returns false for invalid JSON format. + * @tc.type: FUNC + */ +HWTEST_F(CustomUtdStoreTest, ParseUserCustomUtdJsonTest003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ParseUserCustomUtdJsonTest003 begin."); + const char *invalidJson = R"({ "UniformDataTypeDeclarations": [ )"; + + std::vector<TypeDescriptorCfg> declarations; + std::vector<TypeDescriptorCfg> references; + + CustomUtdJsonParser parser; + bool result = parser.ParseUserCustomUtdJson(invalidJson, declarations, references); + + EXPECT_FALSE(result); + EXPECT_TRUE(declarations.empty()); + EXPECT_TRUE(references.empty()); + LOG_INFO(UDMF_TEST, "ParseUserCustomUtdJsonTest003 end."); +} + +/** + * @tc.name: ParseUserCustomUtdJsonTest004 + * @tc.desc: Verify ParseUserCustomUtdJson returns false for invalid JSON format. + * @tc.type: FUNC + */ +HWTEST_F(CustomUtdStoreTest, ParseUserCustomUtdJsonTest004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ParseUserCustomUtdJsonTest004 begin."); + const char *invalidJson = R"([ + { "TypeId": "com.example.custom.image" } + ])"; + + std::vector<TypeDescriptorCfg> declarations; + std::vector<TypeDescriptorCfg> references; + + CustomUtdJsonParser parser; + bool result = parser.ParseUserCustomUtdJson(invalidJson, declarations, references); + + EXPECT_FALSE(result); + EXPECT_TRUE(declarations.empty()); + EXPECT_TRUE(references.empty()); + LOG_INFO(UDMF_TEST, "ParseUserCustomUtdJsonTest004 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/graph_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/graph_test.cpp index b453d463..1b8c2935 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/graph_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/graph_test.cpp @@ -282,7 +282,7 @@ HWTEST_F(GraphTest, DfsHasData001, TestSize.Level1) for (uint32_t i = 0; i < edges.size(); i++) { graph.AddEdge(edges[i][0], edges[i][1]); } - + bool isFind = false; graph.Dfs(TestNodes::POINT_A, [&](uint32_t currNode) -> bool { if (currNode == TestNodes::POINT_H) { diff --git a/udmf/framework/innerkitsimpl/test/unittest/mock/include/udmf_service_client_mock.h b/udmf/framework/innerkitsimpl/test/unittest/mock/include/udmf_service_client_mock.h index db9c45a5..9326e2cf 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/mock/include/udmf_service_client_mock.h +++ b/udmf/framework/innerkitsimpl/test/unittest/mock/include/udmf_service_client_mock.h @@ -43,6 +43,10 @@ public: virtual int32_t RemoveAppShareOption(const std::string &) = 0; virtual int32_t ObtainAsynProcess(AsyncProcessInfo&) = 0; virtual int32_t ClearAsynProcessByKey(const std::string &businessUdKey) = 0; + virtual int32_t SetDelayInfo(const DataLoadInfo &, sptr<IRemoteObject>, std::string &) = 0; + virtual int32_t PushDelayData(const std::string &, const UnifiedData &) = 0; + virtual int32_t GetDataIfAvailable(const std::string &key, const DataLoadInfo &, sptr<IRemoteObject>, + std::shared_ptr<UnifiedData>) = 0; public: static inline std::shared_ptr<MUdmfServiceClient> udmfServiceClient = nullptr; }; @@ -64,6 +68,10 @@ public: MOCK_METHOD(int32_t, RemoveAppShareOption, (const std::string &)); MOCK_METHOD(int32_t, ObtainAsynProcess, (AsyncProcessInfo&)); MOCK_METHOD(int32_t, ClearAsynProcessByKey, (const std::string &)); + MOCK_METHOD(int32_t, SetDelayInfo, (const DataLoadInfo &, sptr<IRemoteObject>, std::string &)); + MOCK_METHOD(int32_t, PushDelayData, (const std::string &, const UnifiedData &)); + MOCK_METHOD(int32_t, GetDataIfAvailable, (const std::string &, const DataLoadInfo &, sptr<IRemoteObject>, + std::shared_ptr<UnifiedData>)); }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/test/unittest/mock/udmf_service_client_mock.cpp b/udmf/framework/innerkitsimpl/test/unittest/mock/udmf_service_client_mock.cpp index 9239fa58..0dd88555 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/mock/udmf_service_client_mock.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/mock/udmf_service_client_mock.cpp @@ -152,4 +152,33 @@ int32_t UdmfServiceClient::ObtainAsynProcess(AsyncProcessInfo &processInfo) return MUdmfServiceClient::udmfServiceClient->ObtainAsynProcess(processInfo); } } + +int32_t UdmfServiceClient::SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptr<IRemoteObject> iUdmfNotifier, + std::string &key) +{ + if (MUdmfServiceClient::udmfServiceClient == nullptr) { + return -1; + } else { + return MUdmfServiceClient::udmfServiceClient->SetDelayInfo(dataLoadInfo, iUdmfNotifier, key); + } +} + +int32_t UdmfServiceClient::PushDelayData(const std::string &key, UnifiedData &unifiedData) +{ + if (MUdmfServiceClient::udmfServiceClient == nullptr) { + return -1; + } else { + return MUdmfServiceClient::udmfServiceClient->PushDelayData(key, unifiedData); + } +} + +int32_t UdmfServiceClient::GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr<IRemoteObject> iUdmfNotifier, std::shared_ptr<UnifiedData> unifiedData) +{ + if (MUdmfServiceClient::udmfServiceClient == nullptr) { + return -1; + } else { + return MUdmfServiceClient::udmfServiceClient->GetDataIfAvailable(key, dataLoadInfo, iUdmfNotifier, unifiedData); + } +} } // namespace OHOS::UDMF diff --git a/udmf/framework/innerkitsimpl/test/unittest/ndk_data_conversion_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/ndk_data_conversion_test.cpp index 082398db..e09d58cd 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/ndk_data_conversion_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/ndk_data_conversion_test.cpp @@ -356,26 +356,21 @@ HWTEST_F(NdkDataConversionTest, ConvertPixelMap_002, TestSize.Level1) HWTEST_F(NdkDataConversionTest, ConvertPixelMap_003, TestSize.Level1) { LOG_INFO(UDMF_TEST, "ConvertPixelMap_003 begin."); - uint32_t color[100] = { 3, 7, 9, 9, 7, 6 }; + uint32_t color[35] = { 3, 7, 9, 9, 7, 6 }; OHOS::Media::InitializationOptions opts = { { 5, 7 }, Media::PixelFormat::ARGB_8888, Media::PixelFormat::ARGB_8888 }; std::unique_ptr<OHOS::Media::PixelMap> pixelMap = OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); std::shared_ptr<OHOS::Media::PixelMap> pixelMapIn = move(pixelMap); - std::vector<uint8_t> buff; - pixelMapIn->EncodeTlv(buff); + auto systemDefinedPixelMap = std::make_shared<SystemDefinedPixelMap>(UDType::SYSTEM_DEFINED_PIXEL_MAP, pixelMapIn); - std::shared_ptr<SystemDefinedPixelMap> systemDefinedPixelMap = - std::make_shared<SystemDefinedPixelMap>(UDType::SYSTEM_DEFINED_PIXEL_MAP, buff); UnifiedData data; - std::vector<std::shared_ptr<UnifiedRecord>> records = { systemDefinedPixelMap }; - data.SetRecords(records); + data.AddRecord(systemDefinedPixelMap); std::string key; CustomOption option = { .intention = UD_INTENTION_DRAG }; auto setRet = UdmfClient::GetInstance().SetData(option, data, key); EXPECT_EQ(setRet, E_OK); - std::shared_ptr<UnifiedData> readData = std::make_shared<UnifiedData>(); QueryOption query = { .key = key }; auto getRet = UdmfClient::GetInstance().GetData(query, *readData); @@ -392,16 +387,14 @@ HWTEST_F(NdkDataConversionTest, ConvertPixelMap_003, TestSize.Level1) auto type = OH_UdsPixelMap_GetType(pixelMapUds); EXPECT_EQ(std::string(type), std::string(UDMF_META_OPENHARMONY_PIXEL_MAP)); + uint32_t color2[100] = { 3, 7, 9, 9, 7, 6 }; OHOS::Media::InitializationOptions opts2 = { { 10, 10 }, Media::PixelFormat::ARGB_8888, Media::PixelFormat::ARGB_8888 }; - std::unique_ptr<OHOS::Media::PixelMap> pixelMap2 = - OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts2); - + auto pixelMap2 = OHOS::Media::PixelMap::Create(color2, sizeof(color) / sizeof(color[0]), opts2); OH_PixelmapNative *ohPixelmapNative = new OH_PixelmapNative(std::move(pixelMap2)); OH_UdsPixelMap_GetPixelMap(pixelMapUds, ohPixelmapNative); auto resultPixelMap = ohPixelmapNative->GetInnerPixelmap(); - auto height = resultPixelMap->GetHeight(); - EXPECT_EQ(height, 7); + EXPECT_EQ(resultPixelMap->GetHeight(), 7); OH_UdsPixelMap_Destroy(pixelMapUds); OH_UdmfData_Destroy(ndkData); @@ -409,6 +402,56 @@ HWTEST_F(NdkDataConversionTest, ConvertPixelMap_003, TestSize.Level1) LOG_INFO(UDMF_TEST, "ConvertPixelMap_003 end."); } +/* * + * @tc.name: ConvertPixelMap_004 + * @tc.desc: test pixel-map conversion between UDS and C-API + * @tc.type: FUNC + */ +HWTEST_F(NdkDataConversionTest, ConvertPixelMap_004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ConvertPixelMap_004 begin."); + uint32_t color[35] = { 3, 7, 9, 9, 7, 6 }; + OHOS::Media::InitializationOptions opts = { { 5, 7 }, + Media::PixelFormat::ARGB_8888, Media::PixelFormat::ARGB_8888 }; + std::unique_ptr<OHOS::Media::PixelMap> pixelMap = + OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr<OHOS::Media::PixelMap> pixelMapIn = move(pixelMap); + + auto pixelMapUds = OH_UdsPixelMap_Create(); + OH_PixelmapNative *ohPixelmapNative = new OH_PixelmapNative(pixelMapIn); + OH_UdsPixelMap_SetPixelMap(pixelMapUds, ohPixelmapNative); + auto record = OH_UdmfRecord_Create(); + OH_UdmfRecord_AddPixelMap(record, pixelMapUds); + auto data = OH_UdmfData_Create(); + OH_UdmfData_AddRecord(data, record); + std::shared_ptr<UnifiedData> unifiedData = std::make_shared<UnifiedData>(); + auto conversionStatus = NdkDataConversion::GetNativeUnifiedData(data, unifiedData); + EXPECT_EQ(conversionStatus, E_OK); + std::string key; + CustomOption option = {.intention = UD_INTENTION_DRAG}; + auto setRet = UdmfClient::GetInstance().SetData(option, *unifiedData, key); + EXPECT_EQ(setRet, E_OK); + std::shared_ptr<UnifiedData> readData = std::make_shared<UnifiedData>(); + QueryOption query = {.key = key}; + auto getRet = UdmfClient::GetInstance().GetData(query, *readData); + EXPECT_EQ(getRet, E_OK); + + auto readRecord = readData->GetRecordAt(0); + auto value = readRecord->GetEntry(UDMF_META_OPENHARMONY_PIXEL_MAP); + ASSERT_TRUE(std::holds_alternative<std::shared_ptr<Object>>(value)); + auto obj = std::get<std::shared_ptr<Object>>(value); + std::shared_ptr<Media::PixelMap> getPixelMap = nullptr; + ASSERT_TRUE(obj->GetValue(PIXEL_MAP, getPixelMap)); + ASSERT_NE(getPixelMap, nullptr); + ASSERT_EQ(getPixelMap->GetHeight(), pixelMapIn->GetHeight()); + ASSERT_EQ(getPixelMap->GetByteCount(), pixelMapIn->GetByteCount()); + OH_UdsPixelMap_Destroy(pixelMapUds); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(data); + delete ohPixelmapNative; + LOG_INFO(UDMF_TEST, "ConvertPixelMap_004 end."); +} + /* * * @tc.name: ConvertApplicationDefined_001 * @tc.desc: test application defined record conversion between JS and C-API diff --git a/udmf/framework/innerkitsimpl/test/unittest/preset_type_descriptor_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/preset_type_descriptor_test.cpp new file mode 100644 index 00000000..8ce825ff --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/unittest/preset_type_descriptor_test.cpp @@ -0,0 +1,69 @@ +/* + * 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. + */ +#define LOG_TAG "PlainTextTest" + +#include <gtest/gtest.h> +#include "preset_type_descriptors.h" +#include "logger.h" + +using namespace testing::ext; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { +using namespace std; + +class PresetTypeDescriptorsTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void PresetTypeDescriptorsTest::SetUpTestCase() +{ +} + +void PresetTypeDescriptorsTest::TearDownTestCase() +{ +} + +void PresetTypeDescriptorsTest::SetUp() +{ +} + +void PresetTypeDescriptorsTest::TearDown() +{ +} + +/** +* @tc.name: TestDoubleInit +* @tc.desc: Test double init utd list. +* @tc.type: FUNC +*/ +HWTEST_F(PresetTypeDescriptorsTest, TestDoubleInit, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "TestDoubleInit begin."); + PresetTypeDescriptors &instance = PresetTypeDescriptors::GetInstance(); + auto presetTypes = instance.GetPresetTypes(); + auto sizeFirst = presetTypes.size(); + EXPECT_GT(sizeFirst, 0); + instance.InitDescriptors(); + presetTypes = instance.GetPresetTypes(); + auto sizeSecond = presetTypes.size(); + EXPECT_EQ(sizeSecond, sizeFirst); + LOG_INFO(UDMF_TEST, "TestDoubleInit end."); +} +} // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/system_defined_form_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/system_defined_form_test.cpp index c8ffed72..3ac95fbc 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/system_defined_form_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/system_defined_form_test.cpp @@ -65,4 +65,88 @@ HWTEST_F(SystemDefinedFormTest, SystemDefinedForm001, TestSize.Level1) EXPECT_EQ(systemDefinedForm.dataType_, SYSTEM_DEFINED_FORM); LOG_INFO(UDMF_TEST, "SystemDefinedForm001 end."); } + +/** +* @tc.name: SystemDefinedFormSetItem001 +* @tc.desc: Normal testcase of SystemDefinedForm +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedFormTest, SystemDefinedFormSetItem001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SystemDefinedFormSetItem001 begin."); + std::shared_ptr<Object> obj = std::make_shared<Object>(); + obj->value_[FORMID] = 1; + obj->value_[FORMNAME] = "formName"; + obj->value_[BUNDLE_NAME] = "bundleName"; + obj->value_[ABILITY_NAME] = "abilityName"; + obj->value_[MODULE] = "module"; + SystemDefinedForm systemDefinedForm(SYSTEM_DEFINED_FORM, obj); + UDDetails details; + details[FORMID] = 2; + details[FORMNAME] = "formName1"; + details[BUNDLE_NAME] = "bundleName1"; + details[ABILITY_NAME] = "abilityName1"; + details[MODULE] = "module1"; + systemDefinedForm.SetItems(details); + EXPECT_EQ(systemDefinedForm.GetFormId(), 2); + EXPECT_EQ(systemDefinedForm.GetFormName(), "formName1"); + EXPECT_EQ(systemDefinedForm.GetBundleName(), "bundleName1"); + EXPECT_EQ(systemDefinedForm.GetAbilityName(), "abilityName1"); + EXPECT_EQ(systemDefinedForm.GetModule(), "module1"); + LOG_INFO(UDMF_TEST, "SystemDefinedFormSetItem001 end."); +} + +/** +* @tc.name: SystemDefinedFormSetItem002 +* @tc.desc: Abnormal testcase of SystemDefinedForm +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedFormTest, SystemDefinedFormSetItem002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SystemDefinedFormSetItem002 begin."); + std::shared_ptr<Object> obj = std::make_shared<Object>(); + obj->value_[FORMID] = 1; + obj->value_[FORMNAME] = "formName"; + obj->value_[BUNDLE_NAME] = "bundleName"; + obj->value_[ABILITY_NAME] = "abilityName"; + obj->value_[MODULE] = "module"; + SystemDefinedForm systemDefinedForm(SYSTEM_DEFINED_FORM, obj); + UDDetails details; + details[FORMID] = true; + details[FORMNAME] = 2.1; + details[BUNDLE_NAME] = false; + details[ABILITY_NAME] = "abilityName1"; + details[MODULE] = "module1"; + systemDefinedForm.SetItems(details); + EXPECT_EQ(systemDefinedForm.GetFormId(), 1); + EXPECT_EQ(systemDefinedForm.GetFormName(), "formName"); + EXPECT_EQ(systemDefinedForm.GetBundleName(), "bundleName"); + EXPECT_EQ(systemDefinedForm.GetAbilityName(), "abilityName1"); + EXPECT_EQ(systemDefinedForm.GetModule(), "module1"); + LOG_INFO(UDMF_TEST, "SystemDefinedFormSetItem002 end."); +} + +/** +* @tc.name: SystemDefinedFormGetItem001 +* @tc.desc: Normal testcase of SystemDefinedForm GetItem +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedFormTest, SystemDefinedFormGetItem001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SystemDefinedForm001 begin."); + std::shared_ptr<Object> obj = std::make_shared<Object>(); + obj->value_[FORMID] = 1; + obj->value_[FORMNAME] = "formName"; + obj->value_[BUNDLE_NAME] = "bundleName"; + obj->value_[ABILITY_NAME] = "abilityName"; + obj->value_[MODULE] = "module"; + SystemDefinedForm systemDefinedForm(SYSTEM_DEFINED_FORM, obj); + UDDetails details = systemDefinedForm.GetItems(); + EXPECT_EQ(std::get<std::int32_t>(details[FORMID]), 1); + EXPECT_EQ(std::get<std::string>(details[FORMNAME]), "formName"); + EXPECT_EQ(std::get<std::string>(details[BUNDLE_NAME]), "bundleName"); + EXPECT_EQ(std::get<std::string>(details[ABILITY_NAME]), "abilityName"); + EXPECT_EQ(std::get<std::string>(details[MODULE]), "module"); + LOG_INFO(UDMF_TEST, "SystemDefinedFormGetItem001 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/system_defined_pixelmap_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/system_defined_pixelmap_test.cpp index 1b881c8c..95673c55 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/system_defined_pixelmap_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/system_defined_pixelmap_test.cpp @@ -17,8 +17,10 @@ #include <unistd.h> #include <gtest/gtest.h> #include <string> +#include <sstream> #include "logger.h" +#include "pixelmap_loader.h" #include "system_defined_pixelmap.h" using namespace testing::ext; @@ -26,7 +28,10 @@ using namespace OHOS::UDMF; using namespace OHOS; namespace OHOS::Test { using namespace std; - +static constexpr const char* PIXEL_MAP_WIDTH = "width"; +static constexpr const char* PIXEL_MAP_HEIGHT = "height"; +static constexpr const char* PIXEL_MAP_FORMAT = "pixel-format"; +static constexpr const char* PIXEL_MAP_ALPHA_TYPE = "alpha-type"; class SystemDefinedPixelMapTest : public testing::Test { public: static void SetUpTestCase(); @@ -97,4 +102,249 @@ HWTEST_F(SystemDefinedPixelMapTest, SystemDefinedPixelMap003, TestSize.Level1) EXPECT_EQ(systemDefinedPixelMap.rawData_.size(), 0); LOG_INFO(UDMF_TEST, "SystemDefinedPixelMap003 end."); } + +/** +* @tc.name: GetPixelMapFromRawData001 +* @tc.desc: Abnormal testcase of GetPixelMapFromRawData, rawData_ is null +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, GetPixelMapFromRawData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetPixelMapFromRawData001 begin."); + SystemDefinedPixelMap systemDefinedPixelMap; + const std::vector<uint8_t> rawData; + systemDefinedPixelMap.SetRawData(rawData); + auto ret = systemDefinedPixelMap.GetPixelMapFromRawData(); + EXPECT_EQ(ret, nullptr); + LOG_INFO(UDMF_TEST, "GetPixelMapFromRawData001 end."); +} + +/** +* @tc.name: GetPixelMapFromRawData002 +* @tc.desc: Abnormal testcase of GetPixelMapFromRawData, rawData_ is wrong +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, GetPixelMapFromRawData002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetPixelMapFromRawData002 begin."); + + std::vector<uint8_t> rawData; + for (int i = 0; i < 4 * 1024 * 1024; i++) { + rawData.emplace_back(1); + } + SystemDefinedPixelMap systemDefinedPixelMap; + UDDetails details = { + {PIXEL_MAP_WIDTH, (int32_t)5}, + {PIXEL_MAP_HEIGHT, (int32_t)7}, + {PIXEL_MAP_FORMAT, (int32_t)Media::PixelFormat::ARGB_8888}, + {PIXEL_MAP_ALPHA_TYPE, (int32_t)Media::PixelFormat::ARGB_8888} + }; + systemDefinedPixelMap.SetRawData(rawData); + systemDefinedPixelMap.SetDetails(details); + auto ret = systemDefinedPixelMap.GetPixelMapFromRawData(); + EXPECT_EQ(ret, nullptr); + LOG_INFO(UDMF_TEST, "GetPixelMapFromRawData002 end."); +} + +/** +* @tc.name: GetPixelMapFromRawData003 +* @tc.desc: Abnormal testcase of GetPixelMapFromRawData, rawData_ is null +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, GetPixelMapFromRawData003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetPixelMapFromRawData002 begin."); + + uint32_t color[35] = { 3, 7, 9, 9, 7, 6 }; + OHOS::Media::InitializationOptions opts = { { 5, 7 }, + Media::PixelFormat::ARGB_8888, Media::PixelFormat::ARGB_8888 }; + std::unique_ptr<OHOS::Media::PixelMap> pixelMap = + OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + auto length = pixelMap->GetByteCount(); + std::vector<uint8_t> rawData; + rawData.resize(length); + pixelMap->ReadPixels(length, rawData.data()); + SystemDefinedPixelMap systemDefinedPixelMap; + UDDetails details = { + {PIXEL_MAP_WIDTH, (int32_t)5}, + {PIXEL_MAP_HEIGHT, (int32_t)7}, + {PIXEL_MAP_FORMAT, (int32_t)Media::PixelFormat::ARGB_8888}, + {PIXEL_MAP_ALPHA_TYPE, (int32_t)Media::PixelFormat::ARGB_8888} + }; + systemDefinedPixelMap.SetRawData(rawData); + systemDefinedPixelMap.SetDetails(details); + auto getPixelMap = systemDefinedPixelMap.GetPixelMapFromRawData(); + auto getLength = getPixelMap->GetByteCount(); + EXPECT_EQ(length, getLength); + std::vector<uint8_t> getRawData; + getPixelMap->ReadPixels(length, getRawData.data()); + for (int32_t i = 0; i < getLength; ++i) { + EXPECT_EQ(getRawData[i], rawData[i]); + } + LOG_INFO(UDMF_TEST, "GetPixelMapFromRawData003 end."); +} + +/** +* @tc.name: ParseInfoFromPixelMap001 +* @tc.desc: Abnormal testcase of ParseInfoFromPixelMap001, pixelMap is null +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, ParseInfoFromPixelMap001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ParseInfoFromPixelMap001 begin."); + SystemDefinedPixelMap systemDefinedPixelMap; + systemDefinedPixelMap.ParseInfoFromPixelMap(nullptr); + EXPECT_TRUE(systemDefinedPixelMap.details_.empty()); + LOG_INFO(UDMF_TEST, "ParseInfoFromPixelMap001 end."); +} + +/** +* @tc.name: PixelMapLoader001 +* @tc.desc: Abnormal testcase of PixelMapLoader001 +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, PixelMapLoader001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "PixelMapLoader001 begin."); + PixelMapLoader loader; + loader.handler_ = nullptr; + std::vector<uint8_t> buff(10); + auto ret = loader.DecodeTlv(buff); + EXPECT_EQ(ret, nullptr); + LOG_INFO(UDMF_TEST, "PixelMapLoader001 end."); +} + +/** +* @tc.name: PixelMapLoader002 +* @tc.desc: Abnormal testcase of PixelMapLoader002 +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, PixelMapLoader002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "PixelMapLoader002 begin."); + PixelMapLoader loader; + loader.handler_ = nullptr; + std::vector<uint8_t> buff; + + uint32_t color[35] = { 3, 7, 9, 9, 7, 6 }; + OHOS::Media::InitializationOptions opts = { { 5, 7 }, + Media::PixelFormat::ARGB_8888, Media::PixelFormat::ARGB_8888 }; + std::unique_ptr<OHOS::Media::PixelMap> pixelMap = + OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr<OHOS::Media::PixelMap> pixelMapIn = move(pixelMap); + + auto ret = loader.EncodeTlv(pixelMapIn, buff); + EXPECT_EQ(ret, false); + LOG_INFO(UDMF_TEST, "PixelMapLoader002 end."); +} + +/** +* @tc.name: PixelMapLoader003 +* @tc.desc: Abnormal testcase of PixelMapLoader003 +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, PixelMapLoader003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "PixelMapLoader003 begin."); + PixelMapLoader loader; + loader.handler_ = nullptr; + + PixelMapDetails details; + auto buff = std::vector<uint8_t>(10); + details.rawData = std::ref(buff); + auto ret = loader.GetPixelMapFromRawData(details); + EXPECT_EQ(ret, nullptr); + LOG_INFO(UDMF_TEST, "PixelMapLoader003 end."); +} + +/** +* @tc.name: PixelMapLoader004 +* @tc.desc: Abnormal testcase of PixelMapLoader004 +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, PixelMapLoader004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "PixelMapLoader004 begin."); + PixelMapLoader loader; + loader.handler_ = nullptr; + + uint32_t color[35] = { 3, 7, 9, 9, 7, 6 }; + OHOS::Media::InitializationOptions opts = { { 5, 7 }, + Media::PixelFormat::ARGB_8888, Media::PixelFormat::ARGB_8888 }; + std::unique_ptr<OHOS::Media::PixelMap> pixelMap = + OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr<OHOS::Media::PixelMap> pixelMapIn = move(pixelMap); + auto ret = loader.ParseInfoFromPixelMap(pixelMapIn); + EXPECT_EQ(ret, nullptr); + LOG_INFO(UDMF_TEST, "PixelMapLoader004 end."); +} + +/** +* @tc.name: PixelMapLoader005 +* @tc.desc: Abnormal testcase of PixelMapLoader005 +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, PixelMapLoader005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "PixelMapLoader005 begin."); + PixelMapLoader loader; + ASSERT_NE(loader.handler_, nullptr); + + std::vector<uint8_t> buff; + auto ret = loader.DecodeTlv(buff); + EXPECT_EQ(ret, nullptr); + LOG_INFO(UDMF_TEST, "PixelMapLoader005 end."); +} + +/** +* @tc.name: PixelMapLoader006 +* @tc.desc: Abnormal testcase of PixelMapLoader006 +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, PixelMapLoader006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "PixelMapLoader006 begin."); + PixelMapLoader loader; + ASSERT_NE(loader.handler_, nullptr); + std::vector<uint8_t> buff; + std::shared_ptr<OHOS::Media::PixelMap> pixelMapIn = nullptr; + + auto ret = loader.EncodeTlv(pixelMapIn, buff); + EXPECT_EQ(ret, false); + LOG_INFO(UDMF_TEST, "PixelMapLoader006 end."); +} + +/** +* @tc.name: PixelMapLoader007 +* @tc.desc: Abnormal testcase of PixelMapLoader007 +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, PixelMapLoader007, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "PixelMapLoader007 begin."); + PixelMapLoader loader; + ASSERT_NE(loader.handler_, nullptr); + + PixelMapDetails details; + details.rawData = std::nullopt; + auto ret = loader.GetPixelMapFromRawData(details); + EXPECT_EQ(ret, nullptr); + LOG_INFO(UDMF_TEST, "PixelMapLoader007 end."); +} + +/** +* @tc.name: PixelMapLoader008 +* @tc.desc: Abnormal testcase of PixelMapLoader008 +* @tc.type: FUNC +*/ +HWTEST_F(SystemDefinedPixelMapTest, PixelMapLoader008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "PixelMapLoader008 begin."); + PixelMapLoader loader; + ASSERT_NE(loader.handler_, nullptr); + + auto ret = loader.ParseInfoFromPixelMap(nullptr); + EXPECT_EQ(ret, nullptr); + LOG_INFO(UDMF_TEST, "PixelMapLoader008 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/udmf_async_client_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/udmf_async_client_test.cpp index 9ad5e05d..3686c488 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/udmf_async_client_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/udmf_async_client_test.cpp @@ -13,20 +13,21 @@ * limitations under the License. */ #define LOG_TAG "UdmfAsyncClientTest" +#include "udmf_async_client.h" + #include <gtest/gtest.h> -#include "token_setproc.h" #include "accesstoken_kit.h" -#include "nativetoken_kit.h" - +#include "async_task_params.h" +#include "data_params_conversion.h" #include "image.h" #include "logger.h" +#include "nativetoken_kit.h" #include "plain_text.h" +#include "token_setproc.h" #include "udmf.h" -#include "udmf_async_client.h" #include "udmf_client.h" -#include "async_task_params.h" -#include "data_params_conversion.h" +#include "udmf_executor.h" using namespace testing::ext; using namespace OHOS::Security::AccessToken; @@ -56,9 +57,7 @@ void UdmfAsyncClientTest::TearDownTestCase() { std::this_thread::sleep_for(std::chrono::seconds(END_INTERVAL)); std::vector<UnifiedData> unifiedDataSet; - QueryOption query = { - .intention = UDMF::UD_INTENTION_DATA_HUB - }; + QueryOption query = { .intention = UDMF::UD_INTENTION_DATA_HUB }; auto status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); EXPECT_EQ(E_OK, status); auto tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.asyncdemo", 0); @@ -69,41 +68,29 @@ void UdmfAsyncClientTest::SetUp() {} void UdmfAsyncClientTest::TearDown() {} - void UdmfAsyncClientTest::AllocHapToken() { - HapInfoParams info = { - .userID = USER_ID, - .bundleName = "ohos.test.asyncdemo", - .instIndex = 0, - .appIDDesc = "ohos.test.asyncdemo", - .isSystemApp = false, - }; - HapPolicyParams policy = { - .apl = APL_SYSTEM_BASIC, + HapInfoParams info; + info.userID = USER_ID; + info.bundleName = "ohos.test.asyncdemo"; + info.instIndex = 0; + info.isSystemApp = false; + info.appIDDesc = "ohos.test.asyncdemo"; + HapPolicyParams policy = { .apl = APL_SYSTEM_BASIC, .domain = "test.domain", - .permList = { - { - .permissionName = "ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION", - .bundleName = "ohos.test.asyncdemo", - .grantMode = 1, - .availableLevel = APL_SYSTEM_BASIC, - .label = "label", - .labelId = 1, - .description = "test2", - .descriptionId = 1 - } - }, - .permStateList = { - { - .permissionName = "ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION", - .isGeneral = true, - .resDeviceID = { "local" }, - .grantStatus = { PermissionState::PERMISSION_GRANTED }, - .grantFlags = { 1 } - } - } - }; + .permList = { { .permissionName = "ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION", + .bundleName = "ohos.test.asyncdemo", + .grantMode = 1, + .availableLevel = APL_SYSTEM_BASIC, + .label = "label", + .labelId = 1, + .description = "test2", + .descriptionId = 1 } }, + .permStateList = { { .permissionName = "ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } } } }; auto tokenID = AccessTokenKit::AllocHapToken(info, policy); SetSelfTokenID(tokenID.tokenIDEx); } @@ -117,9 +104,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval001, TestSize.Level1) { LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval001 begin."); - CustomOption customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; UnifiedData data; auto obj = std::make_shared<Object>(); auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); @@ -130,10 +115,9 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval001, TestSize.Level1) ASSERT_EQ(E_OK, status); GetDataParams params; - QueryOption query = { - .key = key, - .intention = UD_INTENTION_DRAG, - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", progress.progressStatus, progress.progress, progress.srcDevName.c_str()); @@ -161,9 +145,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval002, TestSize.Level1) { LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval002 begin."); - CustomOption customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; UnifiedData data; auto obj = std::make_shared<Object>(); auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); @@ -191,10 +173,9 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval002, TestSize.Level1) LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval002 callback end."); }; OH_UdmfGetDataParams_SetDataProgressListener(&param, dataProgressListener); - QueryOption query = { - .key = key, - .intention = UD_INTENTION_DRAG, - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; GetDataParams dataParams; status = DataParamsConversion::GetInnerDataParams(param, query, dataParams); ASSERT_EQ(E_OK, status); @@ -214,9 +195,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval003, TestSize.Level1) auto status = UdmfClient::GetInstance().SetAppShareOption("drag", ShareOptions::IN_APP); ASSERT_EQ(E_OK, status); - CustomOption customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; UnifiedData data; auto obj = std::make_shared<Object>(); auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); @@ -227,10 +206,9 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval003, TestSize.Level1) ASSERT_EQ(E_OK, status); GetDataParams params; - QueryOption query = { - .key = key, - .intention = UD_INTENTION_DRAG, - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", progress.progressStatus, progress.progress, progress.srcDevName.c_str()); @@ -261,9 +239,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval004, TestSize.Level1) { LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval004 begin."); - CustomOption customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; UnifiedData data; auto obj = std::make_shared<Object>(); auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); @@ -274,10 +250,9 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval004, TestSize.Level1) ASSERT_EQ(E_OK, status); GetDataParams params; - QueryOption query = { - .key = key, - .intention = UD_INTENTION_DRAG, - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", progress.progressStatus, progress.progress, progress.srcDevName.c_str()); @@ -309,10 +284,9 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval005, TestSize.Level1) LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval005 begin."); GetDataParams params; - QueryOption query = { - .key = "udmf://drag/com.demo/NotFoundData", - .intention = UD_INTENTION_DRAG, - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = "udmf://drag/com.demo/NotFoundData"; auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", progress.progressStatus, progress.progress, progress.srcDevName.c_str()); @@ -339,10 +313,9 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval006, TestSize.Level1) LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval006 begin."); GetDataParams params; - QueryOption query = { - .key = "InvalidKey", - .intention = UD_INTENTION_DRAG, - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = "InvalidKey"; auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", progress.progressStatus, progress.progress, progress.srcDevName.c_str()); @@ -362,10 +335,9 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval006, TestSize.Level1) Status UdmfAsyncClientTest::SetDataTest(std::string key, ProgressIndicator progressIndicator) { GetDataParams params; - QueryOption query = { - .key = key, - .intention = UD_INTENTION_DRAG, - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", progress.progressStatus, progress.progress, progress.srcDevName.c_str()); @@ -389,9 +361,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval007, TestSize.Level1) { LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval007 begin."); - CustomOption customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; UnifiedData data; auto obj = std::make_shared<Object>(); auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); @@ -402,9 +372,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval007, TestSize.Level1) ASSERT_EQ(E_OK, status); std::string key2; - customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + customOption = { .intention = UDMF::UD_INTENTION_DRAG }; plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); plainText->SetContent("content1"); data.AddRecord(plainText); @@ -412,9 +380,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval007, TestSize.Level1) ASSERT_EQ(E_OK, status); std::string key3; - customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + customOption = { .intention = UDMF::UD_INTENTION_DRAG }; plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); plainText->SetContent("content1"); data.AddRecord(plainText); @@ -448,9 +414,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval008, TestSize.Level1) { LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval008 begin."); - CustomOption customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; UnifiedData data; auto obj = std::make_shared<Object>(); auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); @@ -490,9 +454,7 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval009, TestSize.Level1) { LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval009 begin."); - CustomOption customOption = { - .intention = UDMF::UD_INTENTION_DRAG - }; + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; UnifiedData data; auto obj = std::make_shared<Object>(); auto file = std::make_shared<Image>(UDType::IMAGE, obj); @@ -504,10 +466,9 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval009, TestSize.Level1) ASSERT_EQ(E_OK, status); GetDataParams params; - QueryOption query = { - .key = key, - .intention = UD_INTENTION_DRAG, - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", progress.progressStatus, progress.progress, progress.srcDevName.c_str()); @@ -536,9 +497,8 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval010, TestSize.Level1) LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval010 begin."); GetDataParams params; - QueryOption query = { - .intention = UDMF::UD_INTENTION_DRAG - }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; params.query = query; params.progressIndicator = ProgressIndicator::DEFAULT; auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) {}; @@ -546,20 +506,16 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval010, TestSize.Level1) auto status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); ASSERT_EQ(E_INVALID_PARAMETERS, status); - query = { - .key = "udmf://a/b/c", - .intention = UDMF::UD_INTENTION_DATA_HUB, - }; + query.intention = UDMF::UD_INTENTION_DATA_HUB; + query.key = "udmf://a/b/c"; params.query = query; params.progressIndicator = ProgressIndicator::DEFAULT; params.progressListener = callback; status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); ASSERT_EQ(E_INVALID_PARAMETERS, status); - query = { - .key = "udmf://a/b/c", - .intention = UDMF::UD_INTENTION_DRAG, - }; + query.intention = UDMF::UD_INTENTION_DRAG; + query.key = "udmf://a/b/c"; params.query = query; params.progressIndicator = ProgressIndicator::DEFAULT; params.progressListener = nullptr; @@ -567,4 +523,255 @@ HWTEST_F(UdmfAsyncClientTest, StartAsyncDataRetrieval010, TestSize.Level1) ASSERT_EQ(E_INVALID_PARAMETERS, status); LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval010 end."); } -} // OHOS::Test \ No newline at end of file + +/** + * @tc.name: Cancel001 + * @tc.desc: Test Normal Cancel + * @tc.type: FUNC + */ +HWTEST_F(UdmfAsyncClientTest, Cancel001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Cancel001 begin."); + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; + UnifiedData data; + auto obj = std::make_shared<Object>(); + auto file = std::make_shared<Image>(UDType::IMAGE, obj); + file->SetUri("uri"); + file->SetRemoteUri("remoteUri"); + data.AddRecord(file); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(E_OK, status); + + GetDataParams params; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; + auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { + LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", + progress.progressStatus, progress.progress, progress.srcDevName.c_str()); + if (data == nullptr) { + ASSERT_TRUE(progress.progress != 0); + return; + } + ASSERT_EQ(1, data->GetRecords().size()); + LOG_INFO(UDMF_TEST, "StartAsyncDataRetrieval009 callback end."); + }; + params.query = query; + params.progressIndicator = ProgressIndicator::DEFAULT; + params.progressListener = callback; + status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); + ASSERT_EQ(E_OK, status); + std::string businessUdKey = "udmf://a/b/c"; + status = UdmfAsyncClient::GetInstance().Cancel(params.query.key); + ASSERT_EQ(E_OK, status); + + LOG_INFO(UDMF_TEST, "Cancel001 end."); +} + +/** + * @tc.name: Cancel002 + * @tc.desc: Test Invalid params. + * @tc.type: FUNC + */ +HWTEST_F(UdmfAsyncClientTest, Cancel002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Cancel002 begin."); + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; + UnifiedData data; + auto obj = std::make_shared<Object>(); + auto file = std::make_shared<Image>(UDType::IMAGE, obj); + file->SetUri("uri"); + file->SetRemoteUri("remoteUri"); + data.AddRecord(file); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(E_OK, status); + + GetDataParams params; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; + auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { + LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", + progress.progressStatus, progress.progress, progress.srcDevName.c_str()); + if (data == nullptr) { + ASSERT_TRUE(progress.progress != 0); + return; + } + ASSERT_EQ(1, data->GetRecords().size()); + LOG_INFO(UDMF_TEST, "Cancel002 callback end."); + }; + params.query = query; + params.progressIndicator = ProgressIndicator::DEFAULT; + params.progressListener = callback; + status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); + ASSERT_EQ(E_OK, status); + std::string businessUdKey = "udmf"; + status = UdmfAsyncClient::GetInstance().Cancel(businessUdKey); + ASSERT_EQ(E_ERROR, status); + + LOG_INFO(UDMF_TEST, "Cancel002 end."); +} + +/* * + * @tc.name: CancelOnSingleTask001 + * @tc.desc: Test one data + * @tc.type: FUNC + */ +HWTEST_F(UdmfAsyncClientTest, CancelOnSingleTask001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "CancelOnSingleTask001 begin."); + CustomOption customOption; + customOption.intention = UDMF::UD_INTENTION_DRAG; + UnifiedData data; + auto obj = std::make_shared<Object>(); + auto file = std::make_shared<Image>(UDType::IMAGE, obj); + file->SetUri("uri"); + file->SetRemoteUri("remoteUri"); + data.AddRecord(file); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(E_OK, status); + + GetDataParams params; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; + auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { + LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", + progress.progressStatus, progress.progress, progress.srcDevName.c_str()); + if (data == nullptr) { + ASSERT_TRUE(progress.progress != 0); + return; + } + ASSERT_EQ(1, data->GetRecords().size()); + LOG_INFO(UDMF_TEST, "CancelOnSingleTask001 callback end."); + }; + params.query = query; + params.progressIndicator = ProgressIndicator::DEFAULT; + params.progressListener = callback; + status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); + ASSERT_EQ(E_OK, status); + status = UdmfAsyncClient::GetInstance().CancelOnSingleTask(); + ASSERT_EQ(E_ERROR, status); + + LOG_INFO(UDMF_TEST, "CancelOnSingleTask001 end."); +} + +/* * + * @tc.name: CancelOnSingleTask002 + * @tc.desc: Test no data + * @tc.type: FUNC + */ +HWTEST_F(UdmfAsyncClientTest, CancelOnSingleTask002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "CancelOnSingleTask002 begin."); + auto status = UdmfAsyncClient::GetInstance().CancelOnSingleTask(); + ASSERT_EQ(E_ERROR, status); + + LOG_INFO(UDMF_TEST, "CancelOnSingleTask002 end."); +} + +/* * + * @tc.name: CancelOnSingleTask003 + * @tc.desc: Test two data + * @tc.type: FUNC + */ +HWTEST_F(UdmfAsyncClientTest, CancelOnSingleTask003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "CancelOnSingleTask003 begin."); + CustomOption customOption = { .intention = UDMF::UD_INTENTION_DRAG }; + UnifiedData data; + auto obj = std::make_shared<Object>(); + auto file = std::make_shared<Image>(UDType::IMAGE, obj); + file->SetUri("uri"); + file->SetRemoteUri("remoteUri"); + data.AddRecord(file); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(E_OK, status); + + GetDataParams params; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; + auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { + LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d, name=%{public}s.", + progress.progressStatus, progress.progress, progress.srcDevName.c_str()); + if (data == nullptr) { + ASSERT_TRUE(progress.progress != 0); + return; + } + ASSERT_EQ(1, data->GetRecords().size()); + LOG_INFO(UDMF_TEST, "CancelOnSingleTask001 callback end."); + }; + params.query = query; + params.progressIndicator = ProgressIndicator::DEFAULT; + params.progressListener = callback; + status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); + ASSERT_EQ(E_OK, status); + query.intention = UD_INTENTION_DRAG; + query.key = "key"; + params.query = query; + status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); + ASSERT_EQ(E_OK, status); + status = UdmfAsyncClient::GetInstance().CancelOnSingleTask(); + ASSERT_EQ(E_ERROR, status); + + LOG_INFO(UDMF_TEST, "CancelOnSingleTask003 end."); +} + +HWTEST_F(UdmfAsyncClientTest, UpdateOnSameProgressAfterInterval, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateOnSameProgressAfterInterval begin."); + std::string businessUdKey = "udmf://a/b/c"; + GetDataParams params; + params.progressIndicator = ProgressIndicator::DEFAULT; + params.query.key = businessUdKey; + UdmfAsyncClient::GetInstance().RegisterAsyncHelper(params); + std::thread pushThread([&]() { + auto &asyncHelper = UdmfAsyncClient::GetInstance().asyncHelperMap_.at(businessUdKey); + for (uint32_t i = 0; i < 10; ++i) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ProgressInfo sameProgress; + sameProgress.progress = 20; + asyncHelper->progressQueue.PushBack(sameProgress); + } + auto processKey = asyncHelper->processKey; + std::vector<UnifiedData> unifiedDataSet; + QueryOption query; + query.key = processKey; + auto ret = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(ret, E_OK); + ASSERT_EQ(unifiedDataSet.size(), 1); + auto record = unifiedDataSet[0].GetRecordAt(0); + EXPECT_EQ(record->GetType(), UDType::PLAIN_TEXT); + auto plainText = std::static_pointer_cast<PlainText>(record); + auto ts1 = plainText->GetAbstract(); + for (uint32_t i = 0; i < 30; ++i) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ProgressInfo sameProgress; + sameProgress.progress = 20; + asyncHelper->progressQueue.PushBack(sameProgress); + } + unifiedDataSet.clear(); + ret = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(ret, E_OK); + ASSERT_EQ(unifiedDataSet.size(), 1); + record = unifiedDataSet[0].GetRecordAt(0); + EXPECT_EQ(record->GetType(), UDType::PLAIN_TEXT); + plainText = std::static_pointer_cast<PlainText>(record); + auto ts2 = plainText->GetAbstract(); + EXPECT_TRUE(ts2 > ts1); + ProgressInfo sameProgress; + sameProgress.progress = 100; + asyncHelper->progressQueue.PushBack(sameProgress); + }); + auto ret = UdmfAsyncClient::GetInstance().ProgressTask(businessUdKey); + EXPECT_EQ(ret, E_OK); + pushThread.join(); + LOG_INFO(UDMF_TEST, "UpdateOnSameProgressAfterInterval end."); +} + +} // namespace OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_abnormal_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_abnormal_test.cpp index 36459f7f..5b02a886 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_abnormal_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_abnormal_test.cpp @@ -74,6 +74,7 @@ HWTEST_F(UdmfClientAbnormalTest, SetData001, TestSize.Level1) UdmfClient client; UnifiedData unifiedData; CustomOption option; + option.intention = Intention::UD_INTENTION_DATA_HUB; std::string key = "testKey"; Status ret = client.SetData(option, unifiedData, key); diff --git a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_file_manger_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_file_manger_test.cpp new file mode 100644 index 00000000..90871150 --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_file_manger_test.cpp @@ -0,0 +1,2159 @@ +/* + * 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. + */ +#define LOG_TAG "UdmfClientFileMangerTest" +#include <gtest/gtest.h> +#include <unistd.h> +#include <thread> +#include <chrono> + +#include "token_setproc.h" +#include "accesstoken_kit.h" +#include "directory_ex.h" +#include "nativetoken_kit.h" + +#include "logger.h" +#include "udmf_client.h" +#include "application_defined_record.h" +#include "audio.h" +#include "file.h" +#include "folder.h" +#include "html.h" +#include "image.h" +#include "link.h" +#include "plain_text.h" +#include "system_defined_appitem.h" +#include "system_defined_form.h" +#include "system_defined_pixelmap.h" +#include "system_defined_record.h" +#include "text.h" +#include "unified_data_helper.h" +#include "unified_html_record_process.h" +#include "video.h" + +using namespace testing::ext; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { +class UdmfClientFileMangerTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + void SetNativeToken(const std::string &processName); + static void AllocHapToken1(); + static void AllocHapToken2(); + void SetHapToken1(); + void SetHapToken2(); + + void AddPrivilege(QueryOption &option); + void AddPrivilege1(QueryOption &option); + int64_t CountTime(); + + static constexpr int userId = 100; + static constexpr int instIndex = 0; +}; + +void UdmfClientFileMangerTest::SetUpTestCase() +{ + AllocHapToken1(); + AllocHapToken2(); +} + +void UdmfClientFileMangerTest::TearDownTestCase() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo1", instIndex); + AccessTokenKit::DeleteToken(tokenId); + tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + AccessTokenKit::DeleteToken(tokenId); +} + +void UdmfClientFileMangerTest::SetUp() +{ + SetHapToken1(); +} + +void UdmfClientFileMangerTest::TearDown() +{ + QueryOption query = { .intention = Intention::UD_INTENTION_PICKER }; + std::vector<UnifiedData> unifiedDataSet; + UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + query = { .intention = Intention::UD_INTENTION_MENU }; + UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + query = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); +} + +void UdmfClientFileMangerTest::SetNativeToken(const std::string &processName) +{ + auto tokenId = AccessTokenKit::GetNativeTokenId(processName); + SetSelfTokenID(tokenId); +} + +void UdmfClientFileMangerTest::AllocHapToken1() +{ + HapInfoParams info = { + .userID = userId, + .bundleName = "ohos.file.manger.test.demo1", + .instIndex = instIndex, + .appIDDesc = "ohos.file.manger.test.demo1" + }; + + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.file.manger.test.demo1", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "test1", + .descriptionId = 1 + } + }, + .permStateList = { + { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + } + } + }; + auto tokenID = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(tokenID.tokenIDEx); +} + +void UdmfClientFileMangerTest::AllocHapToken2() +{ + HapInfoParams info = { + .userID = userId, + .bundleName = "ohos.file.manger.test.demo2", + .instIndex = instIndex, + .appIDDesc = "ohos.file.manger.test.demo2" + }; + + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.file.manger.test.demo2", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "test2", + .descriptionId = 1 + } + }, + .permStateList = { + { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + } + } + }; + auto tokenID = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(tokenID.tokenIDEx); +} + +void UdmfClientFileMangerTest::SetHapToken1() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo1", instIndex); + SetSelfTokenID(tokenId); +} + +void UdmfClientFileMangerTest::SetHapToken2() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + SetSelfTokenID(tokenId); +} + +void UdmfClientFileMangerTest::AddPrivilege(QueryOption &option) +{ + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readAndKeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + + auto status = UdmfClient::GetInstance().AddPrivilege(option, privilege); + ASSERT_EQ(status, E_OK); +} + +void UdmfClientFileMangerTest::AddPrivilege1(QueryOption &option) +{ + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo1", instIndex); + privilege.readPermission = "readpermission"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + auto status = UdmfClient::GetInstance().AddPrivilege(option, privilege); + ASSERT_EQ(status, E_OK); +} + +int64_t UdmfClientFileMangerTest::CountTime() +{ + return std::chrono::duration_cast<std::chrono::milliseconds>( + std::chrono::system_clock::now().time_since_epoch()).count(); +} + +/** +* @tc.name: SetData001 +* @tc.desc: Set data with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData001 begin."); + + CustomOption option = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData data; + std::string key; + auto status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option = {}; + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option = { .intention = Intention::UD_INTENTION_BASE }; + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "SetData001 end."); +} + +/** +* @tc.name: SetData002 +* @tc.desc: Set data with valid params UD_INTENTION_PICKER +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData002 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_OK); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_OK); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData002 end."); +} + +/** +* @tc.name: SetData003 +* @tc.desc: Set data with invalid params UD_INTENTION_PICKER +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData003 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + AddPrivilege(query); + SetHapToken2(); + query.intention = Intention::UD_INTENTION_DATA_HUB; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption query1; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData003 end."); +} + +/** +* @tc.name: SetData004 +* @tc.desc: Set data with invalid params UD_INTENTION_PICKER +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData004 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + AddPrivilege(query); + SetHapToken2(); + + QueryOption query1; + query1.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_DATA_HUB; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData003 end."); +} + +/** +* @tc.name: SetData005 +* @tc.desc: one over 2MB record UD_INTENTION_PICKER +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData005 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData inputData; + std::string key; + UDDetails details; + std::string value; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "11"; + } + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string fileName = "file_" + value + ".txt"; + std::string uri = "file://" + fileName; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + int64_t start = CountTime(); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "picker setdata 1000 cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + start = CountTime(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + end = CountTime(); + LOG_INFO(UDMF_TEST, "picker getdata 2MB record cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData005 end."); +} + +/** +* @tc.name: SetData006 +* @tc.desc: two 2MB record UD_INTENTION_PICKER +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData006 begin."); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + std::string key; + std::string value; + UnifiedData inputData; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "11"; + } + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_" + value + ".txt"; + for (int i = 0; i < 2; ++i) { + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + } + inputData.SetRecords(inputRecords); + + int64_t start = CountTime(); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "picker setdata two 2MB record cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + start = CountTime(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + end = CountTime(); + LOG_INFO(UDMF_TEST, "picker getdata two 2MB record cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData006 end."); +} + +/** +* @tc.name: SetData007 +* @tc.desc: Set multiple record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData007, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData007 begin."); + + CustomOption customOption = {.intention = Intention::UD_INTENTION_PICKER}; + std::string key; + UnifiedData inputData; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords = { + std::make_shared<Text>(), + std::make_shared<PlainText>(), + std::make_shared<File>(), + std::make_shared<Image>(), + std::make_shared<SystemDefinedRecord>(), + std::make_shared<SystemDefinedForm>(), + std::make_shared<ApplicationDefinedRecord>() + }; + inputData.SetRecords(inputRecords); + + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + auto outputRecords = unifiedDataSet[0].GetRecords(); + ASSERT_EQ(inputRecords.size(), outputRecords.size()); + for (size_t i = 0; i < outputRecords.size(); ++i) { + ASSERT_EQ(outputRecords[i]->GetType(), inputRecords[i]->GetType()); + } + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData007 end."); +} + +/** +* @tc.name: SetData008 +* @tc.desc: Set data with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData008 begin."); + CustomOption option = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData data; + std::string key; + auto status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option = {}; + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option = { .intention = Intention::UD_INTENTION_BASE }; + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "SetData008 end."); +} + +/** +* @tc.name: SetData009 +* @tc.desc: Set data with valid params UD_INTENTION_MENU +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData009, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData009 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_OK); + + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_OK); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData009 end."); +} + +/** +* @tc.name: SetData010 +* @tc.desc: Set data with invalid params UD_INTENTION_MENU +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData010, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData010 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + AddPrivilege(query); + SetHapToken2(); + query.intention = Intention::UD_INTENTION_DATA_HUB; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption query1; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData010 end."); +} + +/** +* @tc.name: SetData011 +* @tc.desc: Set data with invalid params UD_INTENTION_MENU +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData011, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData011 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + AddPrivilege(query); + SetHapToken2(); + + QueryOption query1; + query1.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_DATA_HUB; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData011 end."); +} + +/** +* @tc.name: SetData012 +* @tc.desc: one over 2MB record UD_INTENTION_MENU +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData012, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData012 begin."); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData inputData; + std::string key; + UDDetails details; + std::string value; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "11"; + } + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string fileName = "file_" + value + ".txt"; + std::string uri = "file://" + fileName; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + + int64_t start = CountTime(); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "rightclick setdata 2MB record cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + start = CountTime(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + end = CountTime(); + LOG_INFO(UDMF_TEST, "rightclick getdata 2MB record cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + UnifiedDataHelper::SetRootPath(""); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData012 end."); +} + +/** +* @tc.name: SetData013 +* @tc.desc: two 2MB record UD_INTENTION_MENU +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData013, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData013 begin."); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData inputData; + std::string key; + UDDetails details; + std::string value; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "11"; + } + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_" + value + ".txt"; + for (int i = 0; i < 2; ++i) { + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + } + inputData.SetRecords(inputRecords); + + int64_t start = CountTime(); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "setdata 4MB cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + start = CountTime(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + end = CountTime(); + LOG_INFO(UDMF_TEST, "getdata 4MB cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData013 end."); +} + +/** +* @tc.name: SetData014 +* @tc.desc: Set multiple record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData014, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData014 begin."); + + CustomOption customOption = {.intention = Intention::UD_INTENTION_MENU}; + std::string key; + UnifiedData inputData; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords = { + std::make_shared<Text>(), + std::make_shared<PlainText>(), + std::make_shared<File>(), + std::make_shared<Image>(), + std::make_shared<SystemDefinedRecord>(), + std::make_shared<SystemDefinedForm>(), + std::make_shared<ApplicationDefinedRecord>() + }; + inputData.SetRecords(inputRecords); + + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + auto outputRecords = unifiedDataSet[0].GetRecords(); + ASSERT_EQ(inputRecords.size(), outputRecords.size()); + for (size_t i = 0; i < outputRecords.size(); ++i) { + ASSERT_EQ(outputRecords[i]->GetType(), inputRecords[i]->GetType()); + } + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData014 end."); +} + +/** +* @tc.name: SetData015 +* @tc.desc: Set data with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData015, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData015 begin."); + + CustomOption option = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + std::string key; + auto status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option = {}; + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + + option = { .intention = Intention::UD_INTENTION_BASE }; + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "SetData015 end."); +} + +/** +* @tc.name: SetData016 +* @tc.desc: Set data with valid params UD_INTENTION_SYSTEM_SHARE +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData016, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData016 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_OK); + + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_OK); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData016 end."); +} + +/** +* @tc.name: SetData017 +* @tc.desc: Set data with invalid params UD_INTENTION_SYSTEM_SHARE +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData017, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData017 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + AddPrivilege(query); + SetHapToken2(); + query.intention = Intention::UD_INTENTION_DATA_HUB; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption query1; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData017 end."); +} + +/** +* @tc.name: SetData018 +* @tc.desc: Set data with invalid params UD_INTENTION_SYSTEM_SHARE +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData018, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData018 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData inputData; + std::string keyTest; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_11.txt"; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, keyTest); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = keyTest }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + AddPrivilege(query); + SetHapToken2(); + + QueryOption query1; + query1.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_DATA_HUB; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query1.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().GetBatchData(query1, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData018 end."); +} + +/** +* @tc.name: SetData019 +* @tc.desc: one over 2MB record UD_INTENTION_SYSTEM_SHARE +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData019, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData019 begin."); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData inputData; + std::string key; + UDDetails details; + std::string value; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "11"; + } + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string fileName = "file_" + value + ".txt"; + std::string uri = "file://" + fileName; + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + inputData.SetRecords(inputRecords); + + int64_t start = CountTime(); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "systemshare setdata one over 2MB record cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + start = CountTime(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + end = CountTime(); + LOG_INFO(UDMF_TEST, "systemshare getdata one over 2MB record cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + UnifiedDataHelper::SetRootPath(""); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData019 end."); +} + +/** +* @tc.name: SetData020 +* @tc.desc: two 2MB record UD_INTENTION_SYSTEM_SHARE +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData020, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData020 begin."); + + CustomOption customOption = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData inputData; + std::string key; + UDDetails details; + std::string value; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "11"; + } + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords; + std::string uri = "file://file_" + value + ".txt"; + for (int i = 0; i < 2; ++i) { + inputRecords.emplace_back(std::make_shared<File>(UDType::FILE, "this is a oriUri"+uri)); + } + inputData.SetRecords(inputRecords); + + int64_t start = CountTime(); + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "getdata 1 cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + start = CountTime(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + end = CountTime(); + LOG_INFO(UDMF_TEST, "getdata 1 cost timet:%{public}" PRIi64, (end - start)); + ASSERT_EQ(status, E_OK); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + + LOG_INFO(UDMF_TEST, "SetData020 end."); +} + +/** +* @tc.name: SetData021 +* @tc.desc: Set multiple record with valid params and get data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, SetData021, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData021 begin."); + + CustomOption customOption = {.intention = Intention::UD_INTENTION_SYSTEM_SHARE}; + std::string key; + UnifiedData inputData; + std::vector<std::shared_ptr<UnifiedRecord>> inputRecords = { + std::make_shared<Text>(), + std::make_shared<PlainText>(), + std::make_shared<File>(), + std::make_shared<Image>(), + std::make_shared<SystemDefinedRecord>(), + std::make_shared<SystemDefinedForm>(), + std::make_shared<ApplicationDefinedRecord>() + }; + inputData.SetRecords(inputRecords); + + auto status = UdmfClient::GetInstance().SetData(customOption, inputData, key); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + EXPECT_EQ(status, E_NO_PERMISSION); + + AddPrivilege(query); + SetHapToken2(); + + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + auto outputRecords = unifiedDataSet[0].GetRecords(); + ASSERT_EQ(inputRecords.size(), outputRecords.size()); + for (size_t i = 0; i < outputRecords.size(); ++i) { + ASSERT_EQ(outputRecords[i]->GetType(), inputRecords[i]->GetType()); + } + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "SetData018 end."); +} + +/** +* @tc.name: AddPrivilege001 +* @tc.desc: Add privilege with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege001 begin."); + CustomOption option1 = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_OK); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + SetNativeToken("foundation"); + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + privilege.readPermission = "readpermission"; + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "AddPrivilege001 end."); +} + +/** +* @tc.name: AddPrivilege002 +* @tc.desc: Add privilege with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege002 begin."); + CustomOption option1 = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_OK); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + SetNativeToken("foundation"); + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + privilege.readPermission = "readpermission"; + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "AddPrivilege002 end."); +} + +/** +* @tc.name: AddPrivilege003 +* @tc.desc: Add privilege with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege003 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query = { .key = key }; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_OK); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + privilege.readPermission = "readpermission"; + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "AddPrivilege003 end."); +} + +/** +* @tc.name: AddPrivilege004 +* @tc.desc: Add privilege with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege004 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.key = key; + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_PICKER; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "AddPrivilege004 end."); +} + +/** +* @tc.name: AddPrivilege005 +* @tc.desc: Add privilege with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege005 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.key = key; + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_MENU; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "AddPrivilege005 end."); +} + +/** +* @tc.name: AddPrivilege006 +* @tc.desc: Add privilege with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege006 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.key = key; + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + std::vector<UnifiedData> unifiedDataSet; + SetHapToken2(); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "AddPrivilege006 end."); +} + +/** +* @tc.name: AddPrivilege007 +* @tc.desc: Add privilege with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege007, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege007 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + + query.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + LOG_INFO(UDMF_TEST, "AddPrivilege007 end."); +} + +/** +* @tc.name: AddPrivilege008 +* @tc.desc: Add privilege with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege008 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + query.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + LOG_INFO(UDMF_TEST, "AddPrivilege008 end."); +} + +/** +* @tc.name: AddPrivilege009 +* @tc.desc: Add privilege with invalid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, AddPrivilege009, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege009 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + auto text = std::make_shared<Text>(); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text->SetDetails(details); + data.AddRecord(text); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(userId, "ohos.file.manger.test.demo2", instIndex); + privilege.readPermission = "readandkeep"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + query.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().AddPrivilege(query, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + LOG_INFO(UDMF_TEST, "AddPrivilege009 end."); +} + +/** +* @tc.name: DeleteData001 +* @tc.desc: Delete data with UD_INTENTION_PICKER +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData001 begin."); + CustomOption customOption = { .intention = UD_INTENTION_PICKER }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + queryOption.key = key; + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData001 end."); +} + +/** +* @tc.name: DeleteData002 +* @tc.desc: Delete data with UD_INTENTION_PICKER +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData002 begin."); + CustomOption customOption = { .intention = UD_INTENTION_PICKER }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption queryOption1 = { .key = key }; + status = UdmfClient::GetInstance().DeleteData(queryOption1, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData002 end."); +} + +/** +* @tc.name: DeleteData003 +* @tc.desc: Delete data with UD_INTENTION_PICKER +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData003 begin."); + CustomOption customOption = { .intention = UD_INTENTION_PICKER }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + queryOption.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption queryOption1 = { .key = key }; + status = UdmfClient::GetInstance().DeleteData(queryOption1, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData003 end."); +} + +/** +* @tc.name: DeleteData004 +* @tc.desc: Delete data with UD_INTENTION_SYSTEM_SHARE +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData004 begin."); + CustomOption customOption = { .intention = UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + queryOption.key = key; + queryOption.intention = UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData004 end."); +} + +/** +* @tc.name: DeleteData005 +* @tc.desc: Delete data with UD_INTENTION_SYSTEM_SHARE +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData005 begin."); + CustomOption customOption = { .intention = UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption queryOption1 = { .key = key }; + status = UdmfClient::GetInstance().DeleteData(queryOption1, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData005 end."); +} + +/** +* @tc.name: DeleteData006 +* @tc.desc: Delete data with UD_INTENTION_SYSTEM_SHARE +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData006 begin."); + CustomOption customOption = { .intention = UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + queryOption.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption queryOption1 = { .key = key }; + status = UdmfClient::GetInstance().DeleteData(queryOption1, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData006 end."); +} + +/** +* @tc.name: DeleteData007 +* @tc.desc: Delete data with UD_INTENTION_MENU +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData007, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData007 begin."); + CustomOption customOption = { .intention = UD_INTENTION_MENU }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + queryOption.key = key; + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_MENU; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData007 end."); +} + +/** +* @tc.name: DeleteData008 +* @tc.desc: Delete data with UD_INTENTION_MENU +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData008 begin."); + CustomOption customOption = { .intention = UD_INTENTION_MENU }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_MENU; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption queryOption1 = { .key = key }; + status = UdmfClient::GetInstance().DeleteData(queryOption1, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData008 end."); +} + +/** +* @tc.name: DeleteData009 +* @tc.desc: Delete data with UD_INTENTION_MENU +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, DeleteData009, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DeleteData009 begin."); + CustomOption customOption = { .intention = UD_INTENTION_MENU }; + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption; + std::vector<UnifiedData> unifiedDataSet; + queryOption.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + queryOption.intention = UD_INTENTION_MENU; + status = UdmfClient::GetInstance().DeleteData(queryOption, unifiedDataSet); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + QueryOption queryOption1 = { .key = key }; + status = UdmfClient::GetInstance().DeleteData(queryOption1, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "DeleteData009 end."); +} + +/** +* @tc.name: UpdateData001 +* @tc.desc: test picker update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData001 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.key = key; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData001 end."); +} + +/** +* @tc.name: UpdateData002 +* @tc.desc: test picker update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData002 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + query.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.key = key; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData002 end."); +} + +/** +* @tc.name: UpdateData003 +* @tc.desc: test picker update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData003 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + query.key = key; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData003 end."); +} + +/** +* @tc.name: UpdateData004 +* @tc.desc: test picker update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData004 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_PICKER }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.key = key; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData004 end."); +} + +/** +* @tc.name: UpdateData005 +* @tc.desc: test picker update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData005 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + query.key = key; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData005 end."); +} + +/** +* @tc.name: UpdateData006 +* @tc.desc: test systemshare update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData006 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.key = key; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData006 end."); +} + +/** +* @tc.name: UpdateData007 +* @tc.desc: test systemshare update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData007, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData007 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_SYSTEM_SHARE }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + query.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_PICKER; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.key = key; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData007 end."); +} + +/** +* @tc.name: UpdateData008 +* @tc.desc: test menu update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData008 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.key = key; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData008 end."); +} + +/** +* @tc.name: UpdateData011 +* @tc.desc: test menu update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData011, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData011 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + query.key = "udmf://aaabbbccc/com.hmos.test/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + query.key = key; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData011 end."); +} + +/** +* @tc.name: UpdateData012 +* @tc.desc: test menu update data +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientFileMangerTest, UpdateData012, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData012 begin."); + CustomOption customOption = { .intention = Intention::UD_INTENTION_MENU }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData001"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption query; + query.key = key; + std::vector<UnifiedData> unifiedDataSet; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_SYSTEM_SHARE; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + query.intention = Intention::UD_INTENTION_MENU; + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_INVALID_PARAMETERS); + + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "UpdateData012 end."); +} +} diff --git a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_hap_permission_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_hap_permission_test.cpp index bbc76a3c..b86077c0 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_hap_permission_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_hap_permission_test.cpp @@ -134,13 +134,12 @@ void UdmfClientHapPermissionTest::AllocHapToken1() void UdmfClientHapPermissionTest::AllocHapToken2() { - HapInfoParams info = { - .userID = USER_ID, - .bundleName = "ohos.test.demo22", - .instIndex = 0, - .appIDDesc = "ohos.test.demo22", - .isSystemApp = false, - }; + HapInfoParams info; + info.userID = USER_ID; + info.appIDDesc = "ohos.test.demo22"; + info.bundleName = "ohos.test.demo22"; + info.instIndex = 0; + info.isSystemApp = false; HapPolicyParams policy = { .apl = APL_SYSTEM_BASIC, .domain = "test.domain", @@ -352,4 +351,56 @@ HWTEST_F(UdmfClientHapPermissionTest, RemoveAppShareOption002, TestSize.Level1) EXPECT_EQ(status, E_NOT_FOUND); LOG_INFO(UDMF_TEST, "RemoveAppShareOption002 end."); } + +/** +* @tc.name: SetAppShareOption005 +* @tc.desc: SetAppShareOption CROSS_APP, set data success when CROSS_APP +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientHapPermissionTest, SetAppShareOption005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetAppShareOption005 begin."); + + CustomOption option = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data; + auto text1 = std::make_shared<Text>(); + data.AddRecord(text1); + std::string key; + std::string intention = "drag"; + ShareOptions shareOption = CROSS_APP; + SetHapToken2(); + Status status = UdmfClient::GetInstance().SetAppShareOption(intention, shareOption); + EXPECT_EQ(status, E_OK); + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_OK); + + LOG_INFO(UDMF_TEST, "SetAppShareOption005 end."); +} + +/** +* @tc.name: SetAppShareOption006 +* @tc.desc: SetAppShareOption IN_APP, set data success when IN_APP +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientHapPermissionTest, SetAppShareOption006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetAppShareOption006 begin."); + + CustomOption option = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data; + auto text1 = std::make_shared<Text>(); + data.AddRecord(text1); + std::string key; + std::string intention = "drag"; + ShareOptions shareOption = IN_APP; + SetHapToken2(); + Status status = UdmfClient::GetInstance().RemoveAppShareOption(intention); + EXPECT_EQ(status, E_OK); + status = UdmfClient::GetInstance().SetAppShareOption(intention, shareOption); + EXPECT_EQ(status, E_OK); + status = UdmfClient::GetInstance().SetData(option, data, key); + EXPECT_EQ(status, E_OK); + + LOG_INFO(UDMF_TEST, "SetAppShareOption006 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_test.cpp index c3816343..ecc02208 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_test.cpp @@ -29,6 +29,7 @@ #include "application_defined_record.h" #include "audio.h" #include "file.h" +#include "file_uri.h" #include "folder.h" #include "html.h" #include "image.h" @@ -52,6 +53,7 @@ constexpr int SLEEP_TIME = 50; // 50 ms constexpr int BATCH_SIZE_2K = 2000; constexpr int BATCH_SIZE_5K = 5000; constexpr double BASE_CONVERSION = 1000.0; +constexpr const char *FILE_SCHEME_PREFIX = "file://"; class UdmfClientTest : public testing::Test { public: static void SetUpTestCase(); @@ -70,6 +72,7 @@ public: void CompareDetails(const UDDetails &details); void GetEmptyData(QueryOption &option); void GetFileUriUnifiedData(UnifiedData &data); + void ComparePixelMap(const UDDetails details, std::shared_ptr<OHOS::Media::PixelMap> pixelMapIn); static constexpr int USER_ID = 100; static constexpr int INST_INDEX = 0; @@ -230,6 +233,30 @@ void UdmfClientTest::CompareDetails(const UDDetails &details) } } +void UdmfClientTest::ComparePixelMap(const UDDetails details, std::shared_ptr<OHOS::Media::PixelMap> pixelMapIn) +{ + auto width = details.find("width"); + if (width != details.end()) { + EXPECT_EQ(std::get<int32_t>(width->second), pixelMapIn->GetWidth()); + } + auto height = details.find("height"); + if (height != details.end()) { + EXPECT_EQ(std::get<int32_t>(height->second), pixelMapIn->GetHeight()); + } + auto pixel_format = details.find("pixel-format"); + if (pixel_format != details.end()) { + EXPECT_EQ(std::get<int32_t>(pixel_format->second), static_cast<int32_t>(pixelMapIn->GetPixelFormat())); + } + auto alpha_type = details.find("alpha-type"); + if (alpha_type != details.end()) { + EXPECT_EQ(std::get<int32_t>(alpha_type->second), static_cast<int32_t>(pixelMapIn->GetAlphaType())); + } + auto udmf_key = details.find("udmf_key"); + if (udmf_key != details.end()) { + EXPECT_EQ(std::get<std::string>(udmf_key->second), "udmf_value"); + } +} + void UdmfClientTest::GetEmptyData(QueryOption &option) { UnifiedData data; @@ -905,7 +932,7 @@ HWTEST_F(UdmfClientTest, SetData014, TestSize.Level1) auto systemDefinedRecord2 = static_cast<SystemDefinedRecord *>(record2.get()); ASSERT_NE(systemDefinedRecord2, nullptr); - CompareDetails(systemDefinedRecord2->GetDetails()); + ComparePixelMap(systemDefinedRecord2->GetDetails(), pixelMapIn); auto systemDefinedPixelMap2 = static_cast<SystemDefinedPixelMap *>(record2.get()); ASSERT_NE(systemDefinedPixelMap2, nullptr); @@ -1280,12 +1307,12 @@ HWTEST_F(UdmfClientTest, GetSummary001, TestSize.Level1) EXPECT_EQ(summary.totalSize, size); EXPECT_EQ(summary.summary["general.text"], text->GetSize()); EXPECT_EQ(summary.summary["general.plain-text"], plainText->GetSize()); - EXPECT_EQ(summary.summary["general.file"], file->GetSize()); + EXPECT_EQ(summary.summary["general.file"], file->GetSize() + record8->GetSize()); EXPECT_EQ(summary.summary["general.image"], image->GetSize()); EXPECT_EQ(summary.summary["SystemDefinedType"], systemDefinedRecord->GetSize()); EXPECT_EQ(summary.summary["openharmony.form"], systemDefinedForm->GetSize()); EXPECT_EQ(summary.summary["ApplicationDefinedType"], applicationDefinedRecord->GetSize()); - EXPECT_EQ(summary.summary["abcdefg"], record8->GetSize()); + EXPECT_EQ(summary.summary["abcdefg"], 0); EXPECT_EQ(summary.summary["general.png"], record9->GetSize()); LOG_INFO(UDMF_TEST, "GetSummary001 end."); @@ -1635,7 +1662,8 @@ HWTEST_F(UdmfClientTest, SetData021, TestSize.Level1) unifiedDataSet.clear(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - ASSERT_TRUE(unifiedDataSet.empty()); + auto originSize = unifiedDataSet.size(); + unifiedDataSet.clear(); CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; UnifiedData data1; @@ -1654,8 +1682,7 @@ HWTEST_F(UdmfClientTest, SetData021, TestSize.Level1) SetHapToken2(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - auto size = static_cast<int32_t>(unifiedDataSet.size()); - ASSERT_EQ(size, 2); + ASSERT_EQ(unifiedDataSet.size(), originSize + 2); LOG_INFO(UDMF_TEST, "SetData021 end."); } @@ -1737,6 +1764,145 @@ HWTEST_F(UdmfClientTest, UpdateData002, TestSize.Level1) LOG_INFO(UDMF_TEST, "UpdateData002 end."); } +/** +* @tc.name: OH_Udmf_GetBatchData001 +* @tc.desc: GetBatchData data with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, OH_Udmf_GetBatchData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "OH_Udmf_GetBatchData001 begin."); + + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content"); + data.AddRecord(plainText); + CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB, + .visibility = Visibility::VISIBILITY_OWN_PROCESS }; + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption = { .key = key, .intention = UD_INTENTION_DATA_HUB }; + std::vector<UnifiedData> dataSet; + status = UdmfClient::GetInstance().GetBatchData(queryOption, dataSet); + std::shared_ptr<UnifiedRecord> record = dataSet[0].GetRecordAt(0); + ASSERT_NE(record, nullptr); + auto type = record->GetType(); + ASSERT_EQ(type, UDType::PLAIN_TEXT); + auto plainText2 = static_cast<PlainText *>(record.get()); + ASSERT_EQ(plainText2->GetContent(), "content"); + std::vector<UnifiedData> dataDelete; + status = UdmfClient::GetInstance().DeleteData(queryOption, dataDelete); + ASSERT_EQ(status, E_OK); + LOG_INFO(UDMF_TEST, "OH_Udmf_GetBatchData001 end."); +} + +/** +* @tc.name: OH_Udmf_GetBatchData002 +* @tc.desc: GetBatchData data with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, OH_Udmf_GetBatchData002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "OH_Udmf_GetBatchData002 begin."); + SetHapToken1(); + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content"); + data.AddRecord(plainText); + CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB, + .visibility = Visibility::VISIBILITY_OWN_PROCESS }; + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + SetHapToken2(); + QueryOption queryOption = { .key = key, .intention = UD_INTENTION_DATA_HUB }; + std::vector<UnifiedData> dataSet; + status = UdmfClient::GetInstance().GetBatchData(queryOption, dataSet); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(dataSet.size(), 0); + SetHapToken1(); + std::vector<UnifiedData> dataDelete; + status = UdmfClient::GetInstance().DeleteData(queryOption, dataDelete); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(dataDelete.size(), 1); + LOG_INFO(UDMF_TEST, "OH_Udmf_GetBatchData002 end."); +} + +/** +* @tc.name: OH_Udmf_GetBatchData003 +* @tc.desc: GetBatchData data with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, OH_Udmf_GetBatchData003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "OH_Udmf_GetBatchData003 begin."); + + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content"); + data.AddRecord(plainText); + CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB, + .visibility = Visibility::VISIBILITY_ALL }; + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption queryOption = { .key = key, .intention = UD_INTENTION_DATA_HUB }; + std::vector<UnifiedData> dataSet; + status = UdmfClient::GetInstance().GetBatchData(queryOption, dataSet); + std::shared_ptr<UnifiedRecord> record = dataSet[0].GetRecordAt(0); + ASSERT_NE(record, nullptr); + auto type = record->GetType(); + ASSERT_EQ(type, UDType::PLAIN_TEXT); + auto plainText2 = static_cast<PlainText *>(record.get()); + ASSERT_EQ(plainText2->GetContent(), "content"); + std::vector<UnifiedData> dataDelete; + status = UdmfClient::GetInstance().DeleteData(queryOption, dataDelete); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(dataDelete.size(), 1); + LOG_INFO(UDMF_TEST, "OH_Udmf_GetBatchData003 end."); +} + +/** +* @tc.name: OH_Udmf_GetBatchData004 +* @tc.desc: GetBatchData data with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, OH_Udmf_GetBatchData004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "OH_Udmf_GetBatchData004 begin."); + SetHapToken1(); + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("content"); + data.AddRecord(plainText); + CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB, + .visibility = Visibility::VISIBILITY_ALL }; + std::string key; + auto status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + + SetHapToken2(); + QueryOption queryOption = { .key = key, .intention = UD_INTENTION_DATA_HUB }; + std::vector<UnifiedData> dataSet; + status = UdmfClient::GetInstance().GetBatchData(queryOption, dataSet); + std::shared_ptr<UnifiedRecord> record = dataSet[0].GetRecordAt(0); + ASSERT_NE(record, nullptr); + auto type = record->GetType(); + ASSERT_EQ(type, UDType::PLAIN_TEXT); + auto plainText2 = static_cast<PlainText *>(record.get()); + ASSERT_EQ(plainText2->GetContent(), "content"); + SetHapToken1(); + std::vector<UnifiedData> dataDelete; + status = UdmfClient::GetInstance().DeleteData(queryOption, dataDelete); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(dataDelete.size(), 1); + LOG_INFO(UDMF_TEST, "OH_Udmf_GetBatchData004 end."); +} + /** * @tc.name: QueryData001 * @tc.desc: Query data with invalid params @@ -1784,7 +1950,8 @@ HWTEST_F(UdmfClientTest, QueryData002, TestSize.Level1) unifiedDataSet.clear(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - ASSERT_TRUE(unifiedDataSet.empty()); + auto originSize = unifiedDataSet.size(); + unifiedDataSet.clear(); CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; UnifiedData data; @@ -1831,8 +1998,7 @@ HWTEST_F(UdmfClientTest, QueryData002, TestSize.Level1) query = { .intention = UD_INTENTION_DATA_HUB }; status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - size = static_cast<int32_t>(unifiedDataSet.size()); - ASSERT_EQ(size, 2); + ASSERT_EQ(unifiedDataSet.size(), originSize + 2); LOG_INFO(UDMF_TEST, "QueryData002 end."); } @@ -1916,6 +2082,7 @@ HWTEST_F(UdmfClientTest, DeleteData002, TestSize.Level1) ASSERT_EQ(status, E_OK); unifiedDataSet.clear(); + queryOption = { .key = key }; status = UdmfClient::GetInstance().GetBatchData(queryOption, unifiedDataSet); ASSERT_TRUE(unifiedDataSet.empty()); LOG_INFO(UDMF_TEST, "DeleteData002 end."); @@ -2197,9 +2364,9 @@ HWTEST_F(UdmfClientTest, SetData028, TestSize.Level1) UnifiedData data; std::string key; std::string html = "<img data-ohos='clipboard' src=>" - "<img data-ohos='clipboard' src='https://data/storage/el2/distributedfiles/102.png'>" - "<img data-ohos='clipboard' src='file://data/storage/el2/distributedfiles/103.png'>" - "<img data-ohos='clipboard' src='file://data/storage/el2/distributedfiles/104.png'>"; + "<img data-ohos='clipboard' src='https://data/storage/el2/base/haps/102.png'>" + "<img data-ohos='clipboard' src='file://data/storage/el2/base/haps/103.png'>" + "<img data-ohos='clipboard' src='file://data/storage/el2/base/haps/104.png'>"; auto obj = std::make_shared<Object>(); obj->value_["uniformDataType"] = "general.html"; obj->value_["htmlContent"] = html; @@ -2242,10 +2409,8 @@ HWTEST_F(UdmfClientTest, SetData029, TestSize.Level1) CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; UnifiedData data; std::string key; - std::string html = "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/temp.png'><img " - "data-ohos='clipboard' " - "src=\"file:///data/storage/el2/distributedfiles/temp.png\"><img data-ohos='clipboard' " - "src='https://data/storage/el2/distributedfiles/202305301.png'>"; + std::string html = "<img data-ohos='clipboard' src='file:///data/storage/el2/base/haps/101.png'>" + "<img data-ohos='clipboard' src=\"file:///data/storage/el2/base/haps/102.png\">"; auto obj = std::make_shared<Object>(); obj->value_["uniformDataType"] = "general.html"; obj->value_["htmlContent"] = html; @@ -2265,11 +2430,17 @@ HWTEST_F(UdmfClientTest, SetData029, TestSize.Level1) UnifiedData readData; status = UdmfClient::GetInstance().GetData(option2, readData); ASSERT_EQ(status, E_OK); - + std::string tmpUri1 = "file://ohos.test.demo1/data/storage/el2/base/haps/101.png"; + std::string tmpUri2 = "file://ohos.test.demo1/data/storage/el2/base/haps/102.png"; + AppFileService::ModuleFileUri::FileUri fileUri1(tmpUri1); + AppFileService::ModuleFileUri::FileUri fileUri2(tmpUri2); + std::string readHtml = "<img data-ohos='clipboard' src='"; + readHtml += FILE_SCHEME_PREFIX + fileUri1.GetRealPath() + "'><img data-ohos='clipboard' src=\""; + readHtml += FILE_SCHEME_PREFIX + fileUri2.GetRealPath() + "\">"; std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); ASSERT_NE(readRecord, nullptr); auto readHtmlRecord = std::static_pointer_cast<Html>(readRecord); - EXPECT_EQ(readHtmlRecord->GetHtmlContent(), html); + EXPECT_EQ(readHtmlRecord->GetHtmlContent(), readHtml); auto uris = readRecord->GetUris(); EXPECT_EQ(uris.size(), 2); @@ -2288,10 +2459,10 @@ HWTEST_F(UdmfClientTest, SetData030, TestSize.Level1) CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; UnifiedData data; std::string key; - std::string html = "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/101.png'>" - "<img data-ohos='clipboard' src='https://data/storage/el2/distributedfiles/102.png'>" - "<img data-ohos='clipboard' src='file://data/storage/el2/distributedfiles/103.png'>"; - std::string uriSrc = "file:///data/storage/el2/distributedfiles/101.png"; + std::string html = "<img data-ohos='clipboard' src='file:///data/storage/el2/base/haps/101.png'>" + "<img data-ohos='clipboard' src='https://data/storage/el2/base/haps/102.png'>" + "<img data-ohos='clipboard' src='file://data/storage/el2/base/haps/103.png'>"; + std::string uriSrc = "file:///data/storage/el2/base/haps/101.png"; auto obj = std::make_shared<Object>(); obj->value_["uniformDataType"] = "general.html"; obj->value_["htmlContent"] = html; @@ -2311,11 +2482,16 @@ HWTEST_F(UdmfClientTest, SetData030, TestSize.Level1) UnifiedData readData; status = UdmfClient::GetInstance().GetData(option2, readData); ASSERT_EQ(status, E_OK); - + std::string tmpUri1 = "file://ohos.test.demo1/data/storage/el2/base/haps/101.png"; + AppFileService::ModuleFileUri::FileUri fileUri1(tmpUri1); + std::string readHtml = "<img data-ohos='clipboard' src='"; + readHtml += FILE_SCHEME_PREFIX + fileUri1.GetRealPath() + "'>"; + readHtml += "<img data-ohos='clipboard' src='https://data/storage/el2/base/haps/102.png'>" + "<img data-ohos='clipboard' src='file://data/storage/el2/base/haps/103.png'>"; std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); ASSERT_NE(readRecord, nullptr); auto readHtmlRecord = std::static_pointer_cast<Html>(readRecord); - EXPECT_EQ(readHtmlRecord->GetHtmlContent(), html); + EXPECT_EQ(readHtmlRecord->GetHtmlContent(), readHtml); auto uris = readRecord->GetUris(); EXPECT_EQ(uris.size(), 1); EXPECT_EQ(uris[0].oriUri, uriSrc); @@ -2326,7 +2502,7 @@ HWTEST_F(UdmfClientTest, SetData030, TestSize.Level1) /** * @tc.name: SetData031 -* @tc.desc: Set Html record add dfsUri and get uris data +* @tc.desc: Set Html entry is null str and get uris data * @tc.type: FUNC */ HWTEST_F(UdmfClientTest, SetData031, TestSize.Level1) @@ -2336,22 +2512,16 @@ HWTEST_F(UdmfClientTest, SetData031, TestSize.Level1) CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; UnifiedData data; std::string key; - std::string html = "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/101.png'>" - "<img data-ohos='clipboard' src='https://data/storage/el2/distributedfiles/101.png'>" - "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/102.png'>" - "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/101.png'>"; - std::string uriSrc1 = "file:///data/storage/el2/distributedfiles/101.png"; - std::string uriSrc2 = "file:///data/storage/el2/distributedfiles/102.png"; - auto obj = std::make_shared<Object>(); - obj->value_["uniformDataType"] = "general.html"; - obj->value_["htmlContent"] = html; - obj->value_["plainContent"] = "htmlPlainContent"; - auto obj2 = std::make_shared<Object>(); - obj2->value_["detail1"] = "detail1"; - obj2->value_["detail2"] = "detail2"; - obj->value_["details"] = obj2; - auto htmlRecord = std::make_shared<Html>(UDType::HTML, obj); - data.AddRecord(htmlRecord); + std::shared_ptr<Object> obj = std::make_shared<Object>(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = "http://demo.com"; + obj->value_[FILE_TYPE] = "abcdefg"; + auto record = std::make_shared<UnifiedRecord>(FILE_URI, obj); + std::string html = ""; + auto htmlRecord = Html(html, "abstract"); + htmlRecord.InitObject(); + record->AddEntry(htmlRecord.GetUtdId(), htmlRecord.GetOriginValue()); + data.AddRecord(record); auto status = UdmfClient::GetInstance().SetData(option1, data, key); ASSERT_EQ(status, E_OK); @@ -2364,41 +2534,23 @@ HWTEST_F(UdmfClientTest, SetData031, TestSize.Level1) std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); ASSERT_NE(readRecord, nullptr); + auto entryValue = readRecord->GetEntry(UtdUtils::GetUtdIdFromUtdEnum(UDType::HTML)); + auto object = std::get<std::shared_ptr<Object>>(entryValue); + ASSERT_NE(object, nullptr); + auto iter = object->value_.find(HTML_CONTENT); + ASSERT_TRUE(iter != object->value_.end()); + EXPECT_TRUE(std::holds_alternative<std::string>(iter->second)); + auto content = std::get<std::string>(iter->second); + EXPECT_EQ(content, html); auto uris = readRecord->GetUris(); - EXPECT_EQ(uris.size(), 3); - EXPECT_EQ(uris[0].oriUri, uriSrc1); - EXPECT_EQ(uris[1].oriUri, uriSrc2); - EXPECT_EQ(uris[2].oriUri, uriSrc1); - std::string strUri1 = "file:///data/1.png"; - std::string strUri2 = "file:///data/2.png"; - std::unordered_map<std::string, std::string> dfsUris; - dfsUris.insert(std::make_pair(uriSrc1, strUri1)); - dfsUris.insert(std::make_pair(uriSrc2, strUri2)); - readRecord->ComputeUris([&dfsUris] (UriInfo &uriInfo) { - auto iter = dfsUris.find(uriInfo.oriUri); - if (iter != dfsUris.end()) { - uriInfo.dfsUri = iter->second; - } - return true; - }); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(readData); - std::string htmlResult = "<img data-ohos='clipboard' src='file:///data/1.png'>" - "<img data-ohos='clipboard' src='https://data/storage/el2/distributedfiles/101.png'>" - "<img data-ohos='clipboard' src='file:///data/2.png'>" - "<img data-ohos='clipboard' src='file:///data/1.png'>"; - auto readHtmlRecord = std::static_pointer_cast<Html>(readRecord); - EXPECT_EQ(readHtmlRecord->GetHtmlContent(), htmlResult); - auto uris1 = readRecord->GetUris(); - EXPECT_EQ(uris1[0].dfsUri, strUri1); - EXPECT_EQ(uris1[1].dfsUri, strUri2); - EXPECT_EQ(uris1[2].dfsUri, strUri1); + EXPECT_EQ(uris.size(), 0); LOG_INFO(UDMF_TEST, "SetData031 end."); } /** * @tc.name: SetData032 -* @tc.desc: Set Html entry is null str and get uris data +* @tc.desc: Set Html entry include invalid value and get uris data * @tc.type: FUNC */ HWTEST_F(UdmfClientTest, SetData032, TestSize.Level1) @@ -2413,7 +2565,10 @@ HWTEST_F(UdmfClientTest, SetData032, TestSize.Level1) obj->value_[FILE_URI_PARAM] = "http://demo.com"; obj->value_[FILE_TYPE] = "abcdefg"; auto record = std::make_shared<UnifiedRecord>(FILE_URI, obj); - std::string html = ""; + std::string html = "<img data-ohos='clipboard' src=>" + "<img data-ohos='clipboard' src='https://data/storage/el2/base/haps/102.png'>" + "<img data-ohos='clipboard' src='file://data/storage/el2/base/haps/103.png'>" + "<img data-ohos='clipboard' src='file://data/storage/el2/base/haps/104.png'>"; auto htmlRecord = Html(html, "abstract"); htmlRecord.InitObject(); record->AddEntry(htmlRecord.GetUtdId(), htmlRecord.GetOriginValue()); @@ -2446,7 +2601,7 @@ HWTEST_F(UdmfClientTest, SetData032, TestSize.Level1) /** * @tc.name: SetData033 -* @tc.desc: Set Html entry include invalid value and get uris data +* @tc.desc: Set Html entry include valid value and get uris data * @tc.type: FUNC */ HWTEST_F(UdmfClientTest, SetData033, TestSize.Level1) @@ -2459,26 +2614,29 @@ HWTEST_F(UdmfClientTest, SetData033, TestSize.Level1) std::shared_ptr<Object> obj = std::make_shared<Object>(); obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; obj->value_[FILE_URI_PARAM] = "http://demo.com"; - obj->value_[FILE_TYPE] = "abcdefg"; auto record = std::make_shared<UnifiedRecord>(FILE_URI, obj); - std::string html = "<img data-ohos='clipboard' src=>" - "<img data-ohos='clipboard' src='https://data/storage/el2/distributedfiles/102.png'>" - "<img data-ohos='clipboard' src='file://data/storage/el2/distributedfiles/103.png'>" - "<img data-ohos='clipboard' src='file://data/storage/el2/distributedfiles/104.png'>"; + std::string html = "<img data-ohos='clipboard' src='file://data/storage/el2/base/haps/101.png'>" + "<img data-ohos='clipboard' src='https://data/storage/el2/base/haps/102.png'>" + "<img data-ohos='clipboard' src='file:///data/storage/el2/base/haps/103.png'>"; + std::string uriSrc = "file:///data/storage/el2/base/haps/103.png"; auto htmlRecord = Html(html, "abstract"); htmlRecord.InitObject(); record->AddEntry(htmlRecord.GetUtdId(), htmlRecord.GetOriginValue()); data.AddRecord(record); auto status = UdmfClient::GetInstance().SetData(option1, data, key); ASSERT_EQ(status, E_OK); - QueryOption option2 = { .key = key }; AddPrivilege1(option2); SetHapToken1(); UnifiedData readData; status = UdmfClient::GetInstance().GetData(option2, readData); ASSERT_EQ(status, E_OK); - + std::string tmpUri1 = "file://ohos.test.demo1/data/storage/el2/base/haps/103.png"; + AppFileService::ModuleFileUri::FileUri fileUri1(tmpUri1); + std::string readHtml = "<img data-ohos='clipboard' src='file://data/storage/el2/base/haps/101.png'>" + "<img data-ohos='clipboard' src='https://data/storage/el2/base/haps/102.png'>" + "<img data-ohos='clipboard' src='"; + readHtml += FILE_SCHEME_PREFIX + fileUri1.GetRealPath() + "'>"; std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); ASSERT_NE(readRecord, nullptr); auto entryValue = readRecord->GetEntry(UtdUtils::GetUtdIdFromUtdEnum(UDType::HTML)); @@ -2488,16 +2646,18 @@ HWTEST_F(UdmfClientTest, SetData033, TestSize.Level1) ASSERT_TRUE(iter != object->value_.end()); EXPECT_TRUE(std::holds_alternative<std::string>(iter->second)); auto content = std::get<std::string>(iter->second); - EXPECT_EQ(content, html); + EXPECT_EQ(content, readHtml); auto uris = readRecord->GetUris(); - EXPECT_EQ(uris.size(), 0); + EXPECT_EQ(uris.size(), 1); + EXPECT_EQ(uris[0].oriUri, uriSrc); + EXPECT_TRUE(uris[0].dfsUri.empty()); LOG_INFO(UDMF_TEST, "SetData033 end."); } /** * @tc.name: SetData034 -* @tc.desc: Set Html entry include valid value and get uris data +* @tc.desc: test html record process * @tc.type: FUNC */ HWTEST_F(UdmfClientTest, SetData034, TestSize.Level1) @@ -2505,23 +2665,28 @@ HWTEST_F(UdmfClientTest, SetData034, TestSize.Level1) LOG_INFO(UDMF_TEST, "SetData034 begin."); CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; - UnifiedData data; + UnifiedData data1; + std::shared_ptr<UnifiedRecord> record = std::make_shared<UnifiedRecord>(); + data1.AddRecord(record); std::string key; - std::shared_ptr<Object> obj = std::make_shared<Object>(); - obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; - obj->value_[FILE_URI_PARAM] = "http://demo.com"; - obj->value_[FILE_TYPE] = "abcdefg"; - auto record = std::make_shared<UnifiedRecord>(FILE_URI, obj); - std::string html = "<img data-ohos='clipboard' src='file://data/storage/el2/distributedfiles/101.png'>" - "<img data-ohos='clipboard' src='https://data/storage/el2/distributedfiles/102.png'>" - "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/103.png'>"; - std::string uriSrc = "file:///data/storage/el2/distributedfiles/103.png"; - auto htmlRecord = Html(html, "abstract"); - htmlRecord.InitObject(); - record->AddEntry(htmlRecord.GetUtdId(), htmlRecord.GetOriginValue()); - data.AddRecord(record); + UnifiedHtmlRecordProcess::RebuildHtmlRecord(data1); + UnifiedHtmlRecordProcess::GetUriFromHtmlRecord(data1); + UnifiedData data; + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("plainContent"); + data.AddRecord(plainText); auto status = UdmfClient::GetInstance().SetData(option1, data, key); ASSERT_EQ(status, E_OK); + std::shared_ptr<UnifiedRecord> record1 = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "this is a content"); + record1->ClearUris(); + data.AddRecord(record1); + auto file = std::make_shared<File>(); + file->SetRemoteUri("remoteUri"); + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + file->SetDetails(details); + data.AddRecord(file); + UnifiedHtmlRecordProcess::RebuildHtmlRecord(data); QueryOption option2 = { .key = key }; AddPrivilege1(option2); @@ -2530,27 +2695,12 @@ HWTEST_F(UdmfClientTest, SetData034, TestSize.Level1) status = UdmfClient::GetInstance().GetData(option2, readData); ASSERT_EQ(status, E_OK); - std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); - ASSERT_NE(readRecord, nullptr); - auto entryValue = readRecord->GetEntry(UtdUtils::GetUtdIdFromUtdEnum(UDType::HTML)); - auto object = std::get<std::shared_ptr<Object>>(entryValue); - ASSERT_NE(object, nullptr); - auto iter = object->value_.find(HTML_CONTENT); - ASSERT_TRUE(iter != object->value_.end()); - EXPECT_TRUE(std::holds_alternative<std::string>(iter->second)); - auto content = std::get<std::string>(iter->second); - EXPECT_EQ(content, html); - auto uris = readRecord->GetUris(); - EXPECT_EQ(uris.size(), 1); - EXPECT_EQ(uris[0].oriUri, uriSrc); - EXPECT_TRUE(uris[0].dfsUri.empty()); - LOG_INFO(UDMF_TEST, "SetData034 end."); } /** * @tc.name: SetData035 -* @tc.desc: Set Html entry add dfsUri and get uris data +* @tc.desc: test html record process * @tc.type: FUNC */ HWTEST_F(UdmfClientTest, SetData035, TestSize.Level1) @@ -2559,27 +2709,31 @@ HWTEST_F(UdmfClientTest, SetData035, TestSize.Level1) CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; UnifiedData data; + auto text = std::make_shared<Text>(); + data.AddRecord(text); + auto plainText = std::make_shared<PlainText>(); + plainText->SetContent("plainContent"); + data.AddRecord(plainText); + auto html = std::make_shared<Html>(); + html->SetPlainContent("htmlContent"); + data.AddRecord(html); std::string key; - std::shared_ptr<Object> obj = std::make_shared<Object>(); - obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; - obj->value_[FILE_URI_PARAM] = "http://demo.com"; - obj->value_[FILE_TYPE] = "abcdefg"; - auto record = std::make_shared<UnifiedRecord>(FILE_URI, obj); - std::string html = "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/101.png'>" - "<img data-ohos='clipboard' src='https://data/storage/el2/distributedfiles/202305301.png'>" - "<img data-ohos='clipboard' src='file://data/storage/el2/distributedfiles/202305301.png'>" - "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/102.png'>" - "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/103.png'>"; - std::string uriSrc1 = "file:///data/storage/el2/distributedfiles/101.png"; - std::string uriSrc2 = "file:///data/storage/el2/distributedfiles/102.png"; - std::string uriSrc3 = "file:///data/storage/el2/distributedfiles/103.png"; - auto htmlRecord = Html(html, "abstract"); - htmlRecord.InitObject(); - record->AddEntry(htmlRecord.GetUtdId(), htmlRecord.GetOriginValue()); - data.AddRecord(record); auto status = UdmfClient::GetInstance().SetData(option1, data, key); ASSERT_EQ(status, E_OK); + UnifiedData data1; + std::shared_ptr<Object> obj = std::make_shared<Object>(); + obj->value_[PLAIN_CONTENT] = "http://demo.com"; + obj->value_[HTML_CONTENT] = 10; + plainText->AddEntry("general.html", obj); + data1.AddRecord(plainText); + UnifiedHtmlRecordProcess::GetUriFromHtmlRecord(data1); + UnifiedHtmlRecordProcess::RebuildHtmlRecord(data1); + UnifiedData data2; + text->AddEntry("general.html", ""); + data2.AddRecord(text); + UnifiedHtmlRecordProcess::GetUriFromHtmlRecord(data2); + UnifiedHtmlRecordProcess::RebuildHtmlRecord(data2); QueryOption option2 = { .key = key }; AddPrivilege1(option2); SetHapToken1(); @@ -2587,267 +2741,28 @@ HWTEST_F(UdmfClientTest, SetData035, TestSize.Level1) status = UdmfClient::GetInstance().GetData(option2, readData); ASSERT_EQ(status, E_OK); - std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); - ASSERT_NE(readRecord, nullptr); - auto uris = readRecord->GetUris(); - EXPECT_EQ(uris.size(), 3); - EXPECT_EQ(uris[0].oriUri, uriSrc1); - EXPECT_EQ(uris[1].oriUri, uriSrc2); - EXPECT_EQ(uris[2].oriUri, uriSrc3); - std::string strUri1 = "file:///data/201.png"; - std::string strUri2 = "file:///data/202.png"; - std::string strUri3 = "file:///data/203.png"; - std::unordered_map<std::string, std::string> dfsUris; - dfsUris.insert(std::make_pair(uriSrc1, strUri1)); - dfsUris.insert(std::make_pair(uriSrc2, strUri2)); - dfsUris.insert(std::make_pair(uriSrc3, strUri3)); - readRecord->ComputeUris([&dfsUris] (UriInfo &uriInfo) { - auto iter = dfsUris.find(uriInfo.oriUri); - if (iter != dfsUris.end()) { - uriInfo.dfsUri = iter->second; - } - return true; - }); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(readData); - std::shared_ptr<UnifiedRecord> rebuildRecord = readData.GetRecordAt(0); - std::string htmlResult = "<img data-ohos='clipboard' src='file:///data/201.png'>" - "<img data-ohos='clipboard' src='https://data/storage/el2/distributedfiles/202305301.png'>" - "<img data-ohos='clipboard' src='file://data/storage/el2/distributedfiles/202305301.png'>" - "<img data-ohos='clipboard' src='file:///data/202.png'>" - "<img data-ohos='clipboard' src='file:///data/203.png'>"; - auto entryValue = rebuildRecord->GetEntry(UtdUtils::GetUtdIdFromUtdEnum(UDType::HTML)); - auto object = std::get<std::shared_ptr<Object>>(entryValue); - ASSERT_NE(object, nullptr); - auto iter = object->value_.find(HTML_CONTENT); - ASSERT_TRUE(iter != object->value_.end()); - EXPECT_TRUE(std::holds_alternative<std::string>(iter->second)); - auto content = std::get<std::string>(iter->second); - EXPECT_EQ(content, htmlResult); - LOG_INFO(UDMF_TEST, "SetData035 end."); } /** -* @tc.name: SetData036 -* @tc.desc: split and rebuild html value performance test +* @tc.name: GetSummary003 +* @tc.desc: Get summary data * @tc.type: FUNC */ -HWTEST_F(UdmfClientTest, SetData036, TestSize.Level1) +HWTEST_F(UdmfClientTest, GetSummary003, TestSize.Level1) { - LOG_INFO(UDMF_TEST, "SetData036 begin."); + LOG_INFO(UDMF_TEST, "GetSummary003 begin."); CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; UnifiedData data; std::string key; - uint32_t kNumImages = 1000; - std::string html = ""; - for (uint32_t i = 0; i < kNumImages; i++) { - html += "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/101.png'>"; - } - auto obj = std::make_shared<Object>(); - obj->value_["uniformDataType"] = "general.html"; - obj->value_["htmlContent"] = html; - obj->value_["plainContent"] = "htmlPlainContent"; - auto obj2 = std::make_shared<Object>(); - obj2->value_["detail1"] = "detail1"; - obj2->value_["detail2"] = "detail2"; - obj->value_["details"] = obj2; - auto htmlRecord = std::make_shared<Html>(UDType::HTML, obj); - data.AddRecord(htmlRecord); - auto start = std::chrono::high_resolution_clock::now(); - auto status = UdmfClient::GetInstance().SetData(option1, data, key); - ASSERT_EQ(status, E_OK); - - QueryOption option2 = { .key = key }; - AddPrivilege1(option2); - SetHapToken1(); - UnifiedData readData; - status = UdmfClient::GetInstance().GetData(option2, readData); - ASSERT_EQ(status, E_OK); - - std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); - ASSERT_NE(readRecord, nullptr); - auto uris = readRecord->GetUris(); - EXPECT_EQ(uris.size(), kNumImages); - std::string strUri = "file:///data/1.png"; - readRecord->ComputeUris([&strUri] (UriInfo &uriInfo) { - uriInfo.dfsUri = strUri; - return true; - }); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(readData); - auto end = std::chrono::high_resolution_clock::now(); - auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start); - LOG_INFO(UDMF_TEST, "SetData036 count duration=%{public}lld", duration.count()); - std::string htmlResult = ""; - for (uint32_t i = 0; i < kNumImages; i++) { - htmlResult += "<img data-ohos='clipboard' src='file:///data/1.png'>"; - } - auto readHtmlRecord = std::static_pointer_cast<Html>(readRecord); - EXPECT_EQ(readHtmlRecord->GetHtmlContent(), htmlResult); - - LOG_INFO(UDMF_TEST, "SetData036 end."); -} - -/** -* @tc.name: SetData037 -* @tc.desc: test html record process -* @tc.type: FUNC -*/ -HWTEST_F(UdmfClientTest, SetData037, TestSize.Level1) -{ - LOG_INFO(UDMF_TEST, "SetData037 begin."); - - CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; - UnifiedData data1; - std::shared_ptr<UnifiedRecord> record = std::make_shared<UnifiedRecord>(); - data1.AddRecord(record); - std::string key; - UnifiedHtmlRecordProcess::RebuildHtmlRecord(data1); - UnifiedHtmlRecordProcess::GetUriFromHtmlRecord(data1); - UnifiedData data; - auto plainText = std::make_shared<PlainText>(); - plainText->SetContent("plainContent"); - data.AddRecord(plainText); - auto status = UdmfClient::GetInstance().SetData(option1, data, key); - ASSERT_EQ(status, E_OK); - std::shared_ptr<UnifiedRecord> record1 = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "this is a content"); - record1->ClearUris(); - data.AddRecord(record1); - auto file = std::make_shared<File>(); - file->SetRemoteUri("remoteUri"); - UDDetails details; - details.insert({ "udmf_key", "udmf_value" }); - file->SetDetails(details); - data.AddRecord(file); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(data); - - QueryOption option2 = { .key = key }; - AddPrivilege1(option2); - SetHapToken1(); - UnifiedData readData; - status = UdmfClient::GetInstance().GetData(option2, readData); - ASSERT_EQ(status, E_OK); - - LOG_INFO(UDMF_TEST, "SetData037 end."); -} - -/** -* @tc.name: SetData038 -* @tc.desc: test html record process -* @tc.type: FUNC -*/ -HWTEST_F(UdmfClientTest, SetData038, TestSize.Level1) -{ - LOG_INFO(UDMF_TEST, "SetData038 begin."); - - CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; - UnifiedData data; - std::string key; - std::shared_ptr<Object> fileObj = std::make_shared<Object>(); - fileObj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; - fileObj->value_[FILE_URI_PARAM] = "http://demo.com"; - auto record = std::make_shared<UnifiedRecord>(FILE_URI, fileObj); - std::string html = "<img data-ohos='clipboard' src='file:///data/storage/el2/distributedfiles/103.png'>"; - auto htmlRecord = Html(html, "abstract"); - htmlRecord.InitObject(); - record->AddEntry(htmlRecord.GetUtdId(), htmlRecord.GetOriginValue()); - data.AddRecord(record); - auto status = UdmfClient::GetInstance().SetData(option1, data, key); - ASSERT_EQ(status, E_OK); - - QueryOption option2 = { .key = key }; - AddPrivilege1(option2); - SetHapToken1(); - UnifiedData readData; - status = UdmfClient::GetInstance().GetData(option2, readData); - ASSERT_EQ(status, E_OK); - - std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); - ASSERT_NE(readRecord, nullptr); - std::shared_ptr<std::map<std::string, ValueType>> entries = std::make_shared<std::map<std::string, ValueType>>(); - std::string utd = "general.html"; - ValueType value = "htmlContent"; - std::shared_ptr<Object> obj = std::make_shared<Object>(); - obj->value_[HTML_CONTENT] = 10; - std::shared_ptr<Object> obj1 = std::make_shared<Object>(); - obj1->value_[HTML_CONTENT] = "file:///data/storage/el2/distributedfiles/103.png"; - readRecord->SetInnerEntries(entries); - readRecord->SetType(UDType::HTML); - entries->insert_or_assign(std::move(utd), std::move(value)); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(readData); - entries->insert_or_assign(std::move(utd), std::move(obj)); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(readData); - entries->insert_or_assign(std::move(utd), std::move(obj1)); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(readData); - - LOG_INFO(UDMF_TEST, "SetData038 end."); -} - -/** -* @tc.name: SetData039 -* @tc.desc: test html record process -* @tc.type: FUNC -*/ -HWTEST_F(UdmfClientTest, SetData039, TestSize.Level1) -{ - LOG_INFO(UDMF_TEST, "SetData039 begin."); - - CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; - UnifiedData data; - auto text = std::make_shared<Text>(); - data.AddRecord(text); - auto plainText = std::make_shared<PlainText>(); - plainText->SetContent("plainContent"); - data.AddRecord(plainText); - auto html = std::make_shared<Html>(); - html->SetPlainContent("htmlContent"); - data.AddRecord(html); - std::string key; - auto status = UdmfClient::GetInstance().SetData(option1, data, key); - ASSERT_EQ(status, E_OK); - - UnifiedData data1; - std::shared_ptr<Object> obj = std::make_shared<Object>(); - obj->value_[PLAIN_CONTENT] = "http://demo.com"; - obj->value_[HTML_CONTENT] = 10; - plainText->AddEntry("general.html", obj); - data1.AddRecord(plainText); - UnifiedHtmlRecordProcess::GetUriFromHtmlRecord(data1); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(data1); - UnifiedData data2; - text->AddEntry("general.html", ""); - data2.AddRecord(text); - UnifiedHtmlRecordProcess::GetUriFromHtmlRecord(data2); - UnifiedHtmlRecordProcess::RebuildHtmlRecord(data2); - QueryOption option2 = { .key = key }; - AddPrivilege1(option2); - SetHapToken1(); - UnifiedData readData; - status = UdmfClient::GetInstance().GetData(option2, readData); - ASSERT_EQ(status, E_OK); - - LOG_INFO(UDMF_TEST, "SetData039 end."); -} - -/** -* @tc.name: GetSummary003 -* @tc.desc: Get summary data -* @tc.type: FUNC -*/ -HWTEST_F(UdmfClientTest, GetSummary003, TestSize.Level1) -{ - LOG_INFO(UDMF_TEST, "GetSummary003 begin."); - - CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; - UnifiedData data; - std::string key; - - UDDetails details; - details.insert({ "udmf_key", "udmf_value" }); - std::string value; - int64_t maxSize = 512 * 1024; - for (int64_t i = 0; i < maxSize; ++i) { - value += "11"; + + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + std::string value; + int64_t maxSize = 512 * 1024; + for (int64_t i = 0; i < maxSize; ++i) { + value += "11"; } details.insert({ value, value }); @@ -2961,7 +2876,7 @@ HWTEST_F(UdmfClientTest, QueryUDSData001, TestSize.Level1) unifiedDataSet.clear(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - ASSERT_TRUE(unifiedDataSet.empty()); + unifiedDataSet.clear(); CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; UnifiedData data; @@ -3000,7 +2915,7 @@ HWTEST_F(UdmfClientTest, QueryUDSData002, TestSize.Level1) unifiedDataSet.clear(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - ASSERT_TRUE(unifiedDataSet.empty()); + unifiedDataSet.clear(); CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; UnifiedData data; @@ -3064,7 +2979,7 @@ HWTEST_F(UdmfClientTest, QueryUDSData003, TestSize.Level1) unifiedDataSet.clear(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - ASSERT_TRUE(unifiedDataSet.empty()); + unifiedDataSet.clear(); CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; UnifiedData data; @@ -3128,7 +3043,7 @@ HWTEST_F(UdmfClientTest, QueryUDSData004, TestSize.Level1) unifiedDataSet.clear(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - ASSERT_TRUE(unifiedDataSet.empty()); + unifiedDataSet.clear(); CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; UnifiedData data; @@ -3192,7 +3107,7 @@ HWTEST_F(UdmfClientTest, QueryUDSData005, TestSize.Level1) unifiedDataSet.clear(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - ASSERT_TRUE(unifiedDataSet.empty()); + unifiedDataSet.clear(); CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; UnifiedData data; @@ -3274,82 +3189,66 @@ HWTEST_F(UdmfClientTest, GetSelfBundleName001, TestSize.Level1) HWTEST_F(UdmfClientTest, GetSummary004, TestSize.Level1) { LOG_INFO(UDMF_TEST, "GetSummary004 begin."); - CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; UnifiedData data; std::string key; - UDDetails details; details.insert({ "udmf_key", "udmf_value" }); - std::shared_ptr<Object> obj = std::make_shared<Object>(); obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; obj->value_[FILE_URI_PARAM] = "http://demo.com"; obj->value_[FILE_TYPE] = "abcdefg"; auto record = std::make_shared<UnifiedRecord>(FILE_URI, obj); - auto size0 = record->GetSize(); - auto plainText = PlainText("content", "abstract"); auto size1 = plainText.GetSize(); plainText.InitObject(); - record->AddEntry(plainText.GetUtdId(), plainText.GetOriginValue()); - + record->AddEntry(plainText.GetUtdId2(), plainText.GetOriginValue()); auto image = Image("uri"); image.SetDetails(details); auto size2 = image.GetSize(); image.InitObject(); - record->AddEntry(image.GetUtdId(), image.GetOriginValue()); - + record->AddEntry(image.GetUtdId2(), image.GetOriginValue()); std::vector<uint8_t> raw = {1, 2, 3, 4, 5}; SystemDefinedPixelMap pixelMap = SystemDefinedPixelMap(raw); pixelMap.SetDetails(details); auto size3 = pixelMap.GetSize(); pixelMap.InitObject(); - record->AddEntry(pixelMap.GetUtdId(), pixelMap.GetOriginValue()); - + record->AddEntry(pixelMap.GetUtdId2(), pixelMap.GetOriginValue()); raw = {1, 2, 3, 4, 5}; auto applicationDefinedRecord = ApplicationDefinedRecord("my.type", raw); auto size4 = applicationDefinedRecord.GetSize(); applicationDefinedRecord.InitObject(); - record->AddEntry(applicationDefinedRecord.GetUtdId(), applicationDefinedRecord.GetOriginValue()); - + record->AddEntry(applicationDefinedRecord.GetUtdId2(), applicationDefinedRecord.GetOriginValue()); data.AddRecord(record); - auto status = UdmfClient::GetInstance().SetData(option1, data, key); ASSERT_EQ(status, E_OK); - QueryOption option2 = { .key = key }; Summary summary; status = UdmfClient::GetInstance().GetSummary(option2, summary); - ASSERT_EQ(status, E_OK); - EXPECT_EQ(summary.summary["abcdefg"], size0); EXPECT_EQ(summary.summary["general.plain-text"], size1); EXPECT_EQ(summary.summary["general.image"], size2); EXPECT_EQ(summary.summary["openharmony.pixel-map"], size3); EXPECT_EQ(summary.summary["ApplicationDefinedType"], size4); - EXPECT_EQ(summary.totalSize, record->GetSize()); - UnifiedData readData; status = UdmfClient::GetInstance().GetData(option2, readData); ASSERT_EQ(E_OK, status); ASSERT_EQ(1, readData.GetRecords().size()); auto readRecord = readData.GetRecordAt(0); auto entries = readRecord->GetEntries(); - ASSERT_EQ(5, entries->size()); + ASSERT_EQ(4, entries->size()); auto readFileUri = std::get<std::shared_ptr<Object>>(entries->at("general.file-uri")); - EXPECT_EQ("abcdefg", std::get<std::string>(readFileUri->value_[FILE_TYPE])); + EXPECT_EQ("general.image", std::get<std::string>(readFileUri->value_[FILE_TYPE])); + EXPECT_EQ("uri", std::get<std::string>(readFileUri->value_[ORI_URI])); auto readPlainText = std::get<std::shared_ptr<Object>>(entries->at("general.plain-text")); EXPECT_EQ("abstract", std::get<std::string>(readPlainText->value_[ABSTRACT])); - auto readImage = std::get<std::shared_ptr<Object>>(entries->at("general.image")); - EXPECT_EQ("uri", std::get<std::string>(readImage->value_[ORI_URI])); auto readPixelMap = std::get<std::shared_ptr<Object>>(entries->at("openharmony.pixel-map")); EXPECT_EQ(5, std::get<std::vector<uint8_t>>(readPixelMap->value_[PIXEL_MAP]).size()); auto readDefinedRecord = std::get<std::shared_ptr<Object>>(entries->at("my.type")); EXPECT_EQ(5, std::get<std::vector<uint8_t>>(readDefinedRecord->value_[ARRAY_BUFFER]).size()); - auto value = std::get<std::shared_ptr<Object>>(readRecord->GetValue()); - EXPECT_EQ("abcdefg", std::get<std::string>(value->value_[FILE_TYPE])); + auto valueType = readRecord->GetValue(); + EXPECT_TRUE(std::holds_alternative<std::monostate>(readRecord->GetValue())); LOG_INFO(UDMF_TEST, "GetSummary004 end."); } @@ -3375,25 +3274,25 @@ HWTEST_F(UdmfClientTest, GetSummary005, TestSize.Level1) auto link = Link("url", "descritpion"); auto size1 = link.GetSize(); link.InitObject(); - record->AddEntry(link.GetUtdId(), link.GetOriginValue()); + record->AddEntry(link.GetUtdId2(), link.GetOriginValue()); auto folder = Folder("uri"); folder.SetDetails(details); auto size2 = folder.GetSize(); folder.InitObject(); - record->AddEntry(folder.GetUtdId(), folder.GetOriginValue()); + record->AddEntry(folder.GetUtdId2(), folder.GetOriginValue()); std::vector<uint8_t> raw = {1, 2, 3, 4, 5}; auto applicationDefinedRecord1 = ApplicationDefinedRecord("your.type", raw); auto size3 = applicationDefinedRecord1.GetSize(); applicationDefinedRecord1.InitObject(); - record->AddEntry(applicationDefinedRecord1.GetUtdId(), applicationDefinedRecord1.GetOriginValue()); + record->AddEntry(applicationDefinedRecord1.GetUtdId2(), applicationDefinedRecord1.GetOriginValue()); raw = {1, 2, 3, 4, 5}; auto applicationDefinedRecord2 = ApplicationDefinedRecord("my.type", raw); auto size4 = applicationDefinedRecord2.GetSize(); applicationDefinedRecord2.InitObject(); - record->AddEntry(applicationDefinedRecord2.GetUtdId(), applicationDefinedRecord2.GetOriginValue()); + record->AddEntry(applicationDefinedRecord2.GetUtdId2(), applicationDefinedRecord2.GetOriginValue()); auto form = SystemDefinedForm(); form.SetDetails(details); @@ -3405,7 +3304,7 @@ HWTEST_F(UdmfClientTest, GetSummary005, TestSize.Level1) form.SetBundleName("bundleName"); auto size5 = form.GetSize(); form.InitObject(); - record->AddEntry(form.GetUtdId(), form.GetOriginValue()); + record->AddEntry(form.GetUtdId2(), form.GetOriginValue()); raw = {1, 2, 3, 4, 5}; std::shared_ptr<Object> obj = std::make_shared<Object>(); @@ -3456,7 +3355,7 @@ HWTEST_F(UdmfClientTest, GetSummary005, TestSize.Level1) EXPECT_EQ("content1", std::get<std::string>(readHtml->value_[HTML_CONTENT])); auto readHyperlink = std::get<std::shared_ptr<Object>>(entries->at("general.hyperlink")); EXPECT_EQ("descritpion", std::get<std::string>(readHyperlink->value_[DESCRIPTION])); - auto readFolder = std::get<std::shared_ptr<Object>>(entries->at("general.folder")); + auto readFolder = std::get<std::shared_ptr<Object>>(entries->at("general.file-uri")); EXPECT_EQ("uri", std::get<std::string>(readFolder->value_[ORI_URI])); auto readDefinedRecord = std::get<std::shared_ptr<Object>>(entries->at("your.type")); EXPECT_EQ(5, std::get<std::vector<uint8_t>>(readDefinedRecord->value_[ARRAY_BUFFER]).size()); @@ -3690,7 +3589,7 @@ HWTEST_F(UdmfClientTest, GetBatchData001, TestSize.Level1) unifiedDataSet.clear(); status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); ASSERT_EQ(status, E_OK); - ASSERT_TRUE(unifiedDataSet.empty()); + unifiedDataSet.clear(); CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; UnifiedData data; @@ -3719,4 +3618,464 @@ HWTEST_F(UdmfClientTest, GetBatchData001, TestSize.Level1) LOG_INFO(UDMF_TEST, "GetBatchData001 end."); } + +/** +* @tc.name: UpdateData003 +* @tc.desc: test update data properties +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, UpdateData003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UpdateData003 begin."); + QueryOption query = { .intention = Intention::UD_INTENTION_DATA_HUB }; + std::vector<UnifiedData> unifiedDataSet; + auto status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + unifiedDataSet.clear(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + unifiedDataSet.clear(); + CustomOption customOption = { .intention = Intention::UD_INTENTION_DATA_HUB }; + UnifiedData data; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(UDType::PLAIN_TEXT, "plainTextContent"); + data.AddRecord(record); + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + std::string tag = "this is a tag of test UpdateData003"; + properties->tag = tag; + data.SetProperties(std::move(properties)); + std::string key; + status = UdmfClient::GetInstance().SetData(customOption, data, key); + ASSERT_EQ(status, E_OK); + query = { .key = key, .intention = Intention::UD_INTENTION_DATA_HUB }; + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(unifiedDataSet.size(), 1); + auto readProperties = unifiedDataSet[0].GetProperties(); + ASSERT_NE(readProperties, nullptr); + EXPECT_EQ(readProperties->tag, tag); + std::shared_ptr<UnifiedDataProperties> properties1 = std::make_shared<UnifiedDataProperties>(); + std::string tag1 = "this is a tag of test UpdateData003test"; + properties1->tag = tag1; + data.SetProperties(std::move(properties1)); + status = UdmfClient::GetInstance().UpdateData(query, data); + ASSERT_EQ(status, E_OK); + unifiedDataSet.clear(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + ASSERT_EQ(unifiedDataSet.size(), 1); + auto readProperties1 = unifiedDataSet[0].GetProperties(); + ASSERT_NE(readProperties1, nullptr); + EXPECT_EQ(readProperties1->tag, tag1); + status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + unifiedDataSet.clear(); + status = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + ASSERT_EQ(status, E_OK); + ASSERT_TRUE(unifiedDataSet.empty()); + LOG_INFO(UDMF_TEST, "UpdateData003 end."); +} + +/** +* @tc.name: SetData036 +* @tc.desc: test set html type data image src is base64 format +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, SetData036, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SetData036 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data; + std::string key; + std::shared_ptr<Object> obj = std::make_shared<Object>(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = "http://demo.com"; + auto record = std::make_shared<UnifiedRecord>(FILE_URI, obj); + std::string html = "<img data-ohos='clipboard' src='data:image/png;base64,IVBORw0KGgoAAAANSUhEUgAAAF'>"; + auto htmlRecord = Html(html, "abstract"); + htmlRecord.InitObject(); + record->AddEntry(htmlRecord.GetUtdId(), htmlRecord.GetOriginValue()); + data.AddRecord(record); + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + QueryOption option2 = { .key = key }; + AddPrivilege1(option2); + SetHapToken1(); + UnifiedData readData; + status = UdmfClient::GetInstance().GetData(option2, readData); + ASSERT_EQ(status, E_OK); + std::shared_ptr<UnifiedRecord> readRecord = readData.GetRecordAt(0); + ASSERT_NE(readRecord, nullptr); + auto uris = readRecord->GetUris(); + EXPECT_EQ(uris.size(), 0); + + LOG_INFO(UDMF_TEST, "SetData036 end."); +} + +/** +* @tc.name: GetParentType001 +* @tc.desc: test Summary fileType +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, GetParentType001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetParentType001 begin."); + Summary oldSummary; + std::map<std::string, int64_t> sumMap = { + { "general.file", 10 }, + { "general.png", 10 }, + { "general.html", 10 }, + { "general.jpeg", 10 }, + { "general.avi", 10 }, + { "com.adobe.pdf", 10 }, + { "general.text", 10 }, + { "aabbcc", 10 } + }; + oldSummary.summary = std::move(sumMap); + oldSummary.totalSize = 80; + Summary newSummary; + auto ret = UdmfClient::GetInstance().GetParentType(oldSummary, newSummary); + ASSERT_EQ(ret, E_OK); + EXPECT_EQ(newSummary.totalSize, 80); + EXPECT_EQ(newSummary.summary["general.file"], 20); + EXPECT_EQ(newSummary.summary["general.image"], 20); + EXPECT_EQ(newSummary.summary["general.html"], 10); + EXPECT_EQ(newSummary.summary["general.video"], 10); + EXPECT_EQ(newSummary.summary["aabbcc"], 10); + EXPECT_EQ(newSummary.summary["general.text"], 10); +} + +/** + * @tc.name: GetBundleNameByUdKey001 + * @tc.desc: test GetBundleNameByUdKey with valid UD key + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, GetBundleNameByUdKey001, TestSize.Level1) +{ + std::string key = "udmf://drag/com.example.app/N]2fIEMbrJj@<hH7zpXzzQ>wp:jMuPa7"; + std::string expectedBundle = "com.example.app"; + + std::string actualBundle = UdmfClient::GetInstance().GetBundleNameByUdKey(key); + EXPECT_EQ(actualBundle, expectedBundle); +} + +/** + * @tc.name: GetBundleNameByUdKey002 + * @tc.desc: test GetBundleNameByUdKey with invalid UD key (missing schema) + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, GetBundleNameByUdKey002, TestSize.Level1) +{ + std::string key = "invalid://share/com.example.app/123"; + std::string actualBundle = UdmfClient::GetInstance().GetBundleNameByUdKey(key); + EXPECT_EQ(actualBundle, ""); +} + +/** + * @tc.name: GetBundleNameByUdKey003 + * @tc.desc: test GetBundleNameByUdKey with incomplete key (missing parts) + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, GetBundleNameByUdKey003, TestSize.Level1) +{ + std::string key = "udmf://share/com.example.app"; + std::string actualBundle = UdmfClient::GetInstance().GetBundleNameByUdKey(key); + EXPECT_EQ(actualBundle, ""); +} + +/** + * @tc.name: GetBundleNameByUdKey004 + * @tc.desc: test GetBundleNameByUdKey with empty key + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, GetBundleNameByUdKey004, TestSize.Level1) +{ + std::string key = ""; + std::string actualBundle = UdmfClient::GetInstance().GetBundleNameByUdKey(key); + EXPECT_EQ(actualBundle, ""); +} + +/** + * @tc.name: GetBundleNameByUdKey005 + * @tc.desc: test GetBundleNameByUdKey with valid UD key + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, GetBundleNameByUdKey005, TestSize.Level1) +{ + std::string key = "udmf://drag/+clone-1+com.example.app/N]2fIEMbrJj@<hH7zpXzzQ>wp:jMuPa7"; + std::string expectedBundle = "+clone-1+com.example.app"; + + std::string actualBundle = UdmfClient::GetInstance().GetBundleNameByUdKey(key); + EXPECT_EQ(actualBundle, expectedBundle); +} + +/** + * @tc.name: GetBundleNameByUdKey006 + * @tc.desc: test GetBundleNameByUdKey with valid UD key + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, GetBundleNameByUdKey006, TestSize.Level1) +{ + std::string key = "udmf://drag/+clone-5+com.example.app/N]2fIEMbrJj@<hH7zpXzzQ>wp:jMuPa7"; + std::string expectedBundle = "+clone-5+com.example.app"; + + std::string actualBundle = UdmfClient::GetInstance().GetBundleNameByUdKey(key); + EXPECT_EQ(actualBundle, expectedBundle); +} + +/** + * @tc.name: ProcessDragIfInApp001 + * @tc.desc: test ProcessDragIfInApp with valid shareOption + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, ProcessDragIfInApp001, TestSize.Level1) +{ + UnifiedData unifiedData; + std::string intentionDrag = "drag"; + std::string key = "test"; + + EXPECT_NO_FATAL_FAILURE(UdmfClient::GetInstance().ProcessDragIfInApp(unifiedData, intentionDrag, key)); +} + +/** + * @tc.name: SetData0024 + * @tc.desc: test SetData with invalid intention + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, SetData0024, TestSize.Level1) +{ + CustomOption option; + UnifiedData unifiedData; + std::string key = "test"; + + auto ret = UdmfClient::GetInstance().SetData(option, unifiedData, key); + EXPECT_EQ(ret, Status::E_INVALID_PARAMETERS); +} + +/** + * @tc.name: IsAppropriateType001 + * @tc.desc: test SetData with invalid intention + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, IsAppropriateType001, TestSize.Level1) +{ + Summary totalSummary; + std::map<std::string, int64_t> specificSummary = { + { "general.png", 10 }, + { "general.jpg", 10 }, + { "general.html", 10 } + }; + std::map<std::string, int64_t> summary = { + { "general.image", 20 }, + { "general.html", 10 } + }; + std::map<std::string, std::vector<int32_t>> summaryFormat = { + { "general.png", { Uds_Type::UDS_FILE_URI } }, + { "general.jpg", { Uds_Type::UDS_FILE_URI } }, + { "general.html", { Uds_Type::UDS_HTML } } + }; + totalSummary.summary = summary; + totalSummary.specificSummary = specificSummary; + totalSummary.summaryFormat = summaryFormat; + totalSummary.version = 1; + totalSummary.totalSize = 30; + + std::vector<std::string> allowTypes = { "general.image" }; + bool isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_TRUE(isAppropriate); + + allowTypes = { "general.hyperlink" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); + + allowTypes = { "general.html" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_TRUE(isAppropriate); +} + +/** + * @tc.name: IsAppropriateType002 + * @tc.desc: test SetData with invalid intention + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, IsAppropriateType002, TestSize.Level1) +{ + Summary totalSummary; + std::map<std::string, int64_t> specificSummary = { + { "general.html", 10 } + }; + std::map<std::string, int64_t> summary = { + { "general.html", 10 } + }; + std::map<std::string, std::vector<int32_t>> summaryFormat = { + { "general.html", { Uds_Type::UDS_FILE_URI } } + }; + totalSummary.summary = summary; + totalSummary.specificSummary = specificSummary; + totalSummary.summaryFormat = summaryFormat; + totalSummary.version = 1; + totalSummary.totalSize = 30; + + std::vector<std::string> allowTypes = { "general.html" }; + bool isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_TRUE(isAppropriate); + + allowTypes = { "general.file" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_TRUE(isAppropriate); + + allowTypes = { "general.file-uri" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_TRUE(isAppropriate); + + allowTypes = { "general.image" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); + + totalSummary.version = 0; + allowTypes = { "general.html" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_TRUE(isAppropriate); + + allowTypes = { "general.file-uri" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); + + allowTypes = { "general.image" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); +} + +/** + * @tc.name: IsAppropriateType002 + * @tc.desc: test SetData with invalid intention + * @tc.type: FUNC + */ +HWTEST_F(UdmfClientTest, IsAppropriateType003, TestSize.Level1) +{ + Summary totalSummary; + std::map<std::string, int64_t> specificSummary = { + { "general.html", 10 } + }; + std::map<std::string, int64_t> summary = { + { "general.html", 10 } + }; + std::map<std::string, std::vector<int32_t>> summaryFormat = { + { "general.html", { Uds_Type::UDS_HTML } } + }; + totalSummary.summary = summary; + totalSummary.specificSummary = specificSummary; + totalSummary.summaryFormat = summaryFormat; + totalSummary.version = 1; + totalSummary.totalSize = 30; + + std::vector<std::string> allowTypes = { "general.html" }; + bool isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_TRUE(isAppropriate); + + allowTypes = { "general.file" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); + + allowTypes = { "general.file-uri" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); + + allowTypes = { "general.image" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); + + totalSummary.version = 0; + allowTypes = { "general.html" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_TRUE(isAppropriate); + + allowTypes = { "general.file-uri" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); + + allowTypes = { "general.image" }; + isAppropriate = UdmfClient::GetInstance().IsAppropriateType(totalSummary, allowTypes); + EXPECT_FALSE(isAppropriate); +} + +/** +* @tc.name: GetSummary006 +* @tc.desc: Get summary data for entries +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, GetSummary006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetSummary006 begin."); + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data; + std::string key; + + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + + auto record = std::make_shared<Html>("content1", "content2"); + auto size0 = record->GetSize(); + + auto folder = Folder("uri"); + folder.SetDetails(details); + folder.InitObject(); + record->AddEntry(folder.GetUtdId2(), folder.GetOriginValue()); + + std::shared_ptr<Object> obj = std::make_shared<Object>(); + obj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj->value_[FILE_URI_PARAM] = "http://demo.com"; + obj->value_[FILE_TYPE] = "general.html"; + auto size3 = ObjectUtils::GetValueSize(obj, false); + record->AddEntry("general.file-uri", obj); + + data.AddRecord(record); + + std::shared_ptr<Object> obj1 = std::make_shared<Object>(); + obj1->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj1->value_[FILE_URI_PARAM] = "http://demo.com"; + obj1->value_[FILE_TYPE] = "general.plain-text"; + auto size4 = ObjectUtils::GetValueSize(obj1, false); + auto record1 = std::make_shared<UnifiedRecord>(FILE_URI, obj1); + data.AddRecord(record1); + + std::shared_ptr<Object> obj2 = std::make_shared<Object>(); + obj2->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + obj2->value_[FILE_URI_PARAM] = "http://demo.com"; + obj2->value_[FILE_TYPE] = "general.png"; + auto size5 = ObjectUtils::GetValueSize(obj2, false); + auto record2 = std::make_shared<UnifiedRecord>(FILE_URI, obj2); + data.AddRecord(record2); + + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + Summary summary; + status = UdmfClient::GetInstance().GetSummary(option2, summary); + + ASSERT_EQ(status, E_OK); + EXPECT_EQ(summary.summary["general.html"], size0); + EXPECT_EQ(summary.summary["general.folder"], 0); + EXPECT_EQ(summary.summary["general.file"], size3 + size4); + EXPECT_EQ(summary.summary["general.image"], size5); + + EXPECT_EQ(summary.specificSummary["general.html"], size0 + size3); + EXPECT_EQ(summary.specificSummary["general.folder"], 0); + EXPECT_EQ(summary.specificSummary["general.plain-text"], size4); + EXPECT_EQ(summary.specificSummary["general.png"], size5); + EXPECT_EQ(summary.totalSize, record->GetSize() + record1->GetSize() + record2->GetSize()); + + EXPECT_EQ(summary.version, 1); + auto htmlFormat = summary.summaryFormat["general.html"]; + EXPECT_TRUE(std::find(htmlFormat.begin(), htmlFormat.end(), Uds_Type::UDS_FILE_URI) != htmlFormat.end()); + EXPECT_TRUE(std::find(htmlFormat.begin(), htmlFormat.end(), Uds_Type::UDS_HTML) != htmlFormat.end()); + + auto textFormat = summary.summaryFormat["general.plain-text"]; + EXPECT_TRUE(std::find(textFormat.begin(), textFormat.end(), Uds_Type::UDS_FILE_URI) != textFormat.end()); + + auto pngFormat = summary.summaryFormat["general.png"]; + EXPECT_TRUE(std::find(pngFormat.begin(), pngFormat.end(), Uds_Type::UDS_FILE_URI) != pngFormat.end()); + LOG_INFO(UDMF_TEST, "GetSummary006 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/udmf_delay_data_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/udmf_delay_data_test.cpp new file mode 100644 index 00000000..323aec90 --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/unittest/udmf_delay_data_test.cpp @@ -0,0 +1,717 @@ +/* + * 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. + */ +#define LOG_TAG "UdmfDelayDataTest" +#include <gtest/gtest.h> + +#include "accesstoken_kit.h" +#include "nativetoken_kit.h" +#include "token_setproc.h" +#include "async_task_params.h" +#include "data_params_conversion.h" +#include "logger.h" +#include "plain_text.h" +#include "udmf.h" +#include "udmf_async_client.h" +#include "udmf_client.h" +#include "udmf_executor.h" +#include "udmf_utils.h" + +using namespace testing::ext; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { +static constexpr int USER_ID = 100; +static constexpr int END_INTERVAL = 3; +class UdmfDelayDataTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + static void AllocHapToken1(); + static void AllocHapToken2(); + static void SetHapToken1(); + static void SetHapToken2(); + static void AddPrivilege(QueryOption &option); + static void SetNativeToken(const std::string &processName); + static std::string SetDataInfoTest(const std::string &key); + static void GetDelayDataTest(const std::string &key); + static std::string NdkSetDataInfoTest(); + static void NdkGetDelayDataTest(const std::string &key); +}; + +void UdmfDelayDataTest::SetUpTestCase() +{ + AllocHapToken1(); + AllocHapToken2(); +} + +void UdmfDelayDataTest::TearDownTestCase() +{ + std::this_thread::sleep_for(std::chrono::seconds(END_INTERVAL)); + std::vector<UnifiedData> unifiedDataSet; + QueryOption query; + query.intention = UDMF::UD_INTENTION_DATA_HUB; + auto status = UdmfClient::GetInstance().DeleteData(query, unifiedDataSet); + EXPECT_EQ(E_OK, status); + + auto tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo1", 0); + AccessTokenKit::DeleteToken(tokenId); + auto tokenId2 = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo2", 0); + AccessTokenKit::DeleteToken(tokenId2); +} + +void UdmfDelayDataTest::SetUp() {} + +void UdmfDelayDataTest::TearDown() +{ + std::this_thread::sleep_for(std::chrono::seconds(END_INTERVAL)); +} + +void UdmfDelayDataTest::AllocHapToken1() +{ + HapInfoParams info = { + .userID = USER_ID, + .bundleName = "ohos.test.demo1", + .instIndex = 0, + .appIDDesc = "ohos.test.demo1", + .isSystemApp = false + }; + HapPolicyParams policy = { + .apl = APL_SYSTEM_BASIC, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION", + .bundleName = "ohos.test.demo1", + .grantMode = 1, + .availableLevel = APL_SYSTEM_BASIC, + .label = "label", + .labelId = 1, + .description = "test2", + .descriptionId = 1 + } + }, + .permStateList = { + { + .permissionName = "ohos.permission.MANAGE_UDMF_APP_SHARE_OPTION", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + } + } + }; + auto tokenID = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(tokenID.tokenIDEx); +} + +void UdmfDelayDataTest::AllocHapToken2() +{ + HapInfoParams info = { + .userID = USER_ID, + .bundleName = "ohos.test.demo2", + .instIndex = 0, + .appIDDesc = "ohos.test.demo2", + .isSystemApp = false + }; + + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.test.demo2", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "test2", + .descriptionId = 1 + } + }, + .permStateList = { + { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } + } + } + }; + auto tokenID = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(tokenID.tokenIDEx); +} + +void UdmfDelayDataTest::SetHapToken1() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo1", 0); + SetSelfTokenID(tokenId); +} + +void UdmfDelayDataTest::SetHapToken2() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo2", 0); + SetSelfTokenID(tokenId); +} + +void UdmfDelayDataTest::SetNativeToken(const std::string &processName) +{ + auto tokenId = AccessTokenKit::GetNativeTokenId(processName); + SetSelfTokenID(tokenId); +} + +void UdmfDelayDataTest::AddPrivilege(QueryOption &option) +{ + Privilege privilege; + privilege.tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo2", 0); + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + SetNativeToken("msdp_sa"); + auto status = UdmfClient::GetInstance().AddPrivilege(option, privilege); + ASSERT_EQ(status, E_OK); +} + + +/* * + * @tc.name: UdmfDelayDataTest001 + * @tc.desc: Test get data success. + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, UdmfDelayDataTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest001 begin."); + + DataLoadInfo dataLoadInfo1; + dataLoadInfo1.sequenceKey = UTILS::GenerateId(); + dataLoadInfo1.types = {"general.plain-text", "general.html"}; + dataLoadInfo1.recordCount = 10; + DataLoadInfo dataLoadInfo2; + dataLoadInfo2.types = {"general.plain-text"}; + dataLoadInfo2.recordCount = 100; + + SetHapToken1(); + auto loadHandler = [dataLoadInfo2] (const std::string &udKey, const DataLoadInfo &dataLoadInfo) { + LOG_INFO(UDMF_TEST, "loadHandler begin udKey=%{public}s.", udKey.c_str()); + EXPECT_EQ(dataLoadInfo.recordCount, dataLoadInfo2.recordCount); + EXPECT_EQ(dataLoadInfo.types, dataLoadInfo2.types); + UnifiedData data; + auto obj = std::make_shared<Object>(); + auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); + plainText->SetContent("content1"); + data.AddRecord(plainText); + auto ret = UdmfClient::GetInstance().PushDelayData(udKey, data); + EXPECT_EQ(ret, E_OK); + }; + DataLoadParams dataLoadParams; + dataLoadParams.dataLoadInfo = dataLoadInfo1; + dataLoadParams.loadHandler = loadHandler; + std::string key = ""; + auto status = UdmfClient::GetInstance().SetDelayInfo(dataLoadParams, key); + EXPECT_EQ(status, E_OK); + + QueryOption option; + option.intention = UD_INTENTION_DRAG; + option.key = key; + Summary summary; + status = UdmfClient::GetInstance().GetSummary(option, summary); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(summary.totalSize, dataLoadInfo1.recordCount); + EXPECT_EQ(summary.summary.size(), dataLoadInfo1.types.size()); + for (auto item: summary.summary) { + EXPECT_NE(summary.summary.find(item.first), summary.summary.end()); + EXPECT_EQ(item.second, 0); + } + + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; + AddPrivilege(query); + + SetHapToken2(); + auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { + LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d", + progress.progressStatus, progress.progress); + if (data == nullptr) { + ASSERT_TRUE(progress.progress != 0); + return; + } + ASSERT_EQ(1, data->GetRecords().size()); + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest001 callback end."); + }; + GetDataParams params; + params.query = query; + params.progressIndicator = ProgressIndicator::DEFAULT; + params.progressListener = callback; + params.acceptableInfo = dataLoadInfo2; + status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); + EXPECT_EQ(status, E_OK); + + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest001 end."); +} + +/* * + * @tc.name: UdmfDelayDataTest002 + * @tc.desc: Test after waiting for 500ms, get data success. + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, UdmfDelayDataTest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest002 begin."); + + DataLoadInfo dataLoadInfo1; + dataLoadInfo1.recordCount = 10; + dataLoadInfo1.types = {"general.plain-text", "general.html"}; + dataLoadInfo1.sequenceKey = UTILS::GenerateId(); + DataLoadInfo dataLoadInfo2; + dataLoadInfo2.recordCount = 100; + dataLoadInfo2.types = {"general.plain-text"}; + + SetHapToken1(); + auto loadHandler = [dataLoadInfo2] (const std::string &udKey, const DataLoadInfo &dataLoadInfo) { + LOG_INFO(UDMF_TEST, "loadHandler begin udKey=%{public}s.", udKey.c_str()); + EXPECT_EQ(dataLoadInfo.recordCount, dataLoadInfo2.recordCount); + EXPECT_EQ(dataLoadInfo.types, dataLoadInfo2.types); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + UnifiedData data; + auto obj = std::make_shared<Object>(); + auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); + plainText->SetContent("content1"); + data.AddRecord(plainText); + auto ret = UdmfClient::GetInstance().PushDelayData(udKey, data); + EXPECT_EQ(ret, E_OK); + }; + DataLoadParams dataLoadParams; + dataLoadParams.dataLoadInfo = dataLoadInfo1; + dataLoadParams.loadHandler = loadHandler; + std::string key = ""; + auto status = UdmfClient::GetInstance().SetDelayInfo(dataLoadParams, key); + EXPECT_EQ(status, E_OK); + + QueryOption option; + option.intention = UD_INTENTION_DRAG; + option.key = key; + Summary summary; + status = UdmfClient::GetInstance().GetSummary(option, summary); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(summary.totalSize, dataLoadInfo1.recordCount); + EXPECT_EQ(summary.summary.size(), dataLoadInfo1.types.size()); + for (auto item: summary.summary) { + EXPECT_NE(summary.summary.find(item.first), summary.summary.end()); + EXPECT_EQ(item.second, 0); + } + + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; + AddPrivilege(query); + + SetHapToken2(); + auto callback = [this](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { + LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d", + progress.progressStatus, progress.progress); + if (data == nullptr) { + ASSERT_TRUE(progress.progress != 0); + return; + } + ASSERT_EQ(1, data->GetRecords().size()); + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest002 callback end."); + }; + GetDataParams params; + params.query = query; + params.progressIndicator = ProgressIndicator::DEFAULT; + params.progressListener = callback; + params.acceptableInfo = dataLoadInfo2; + status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); + EXPECT_EQ(status, E_OK); + + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest002 end."); +} + +/* * + * @tc.name: UdmfDelayDataTest003 + * @tc.desc: Test invalid parameters + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, UdmfDelayDataTest003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest003 begin."); + + DataLoadInfo dataLoadInfo1; + dataLoadInfo1.recordCount = 10; + dataLoadInfo1.types = {"general.plain-text", "general.html"}; + + SetHapToken1(); + auto loadHandler = [] (const std::string &udKey, const DataLoadInfo &dataLoadInfo) { + LOG_INFO(UDMF_TEST, "loadHandler begin udKey=%{public}s.", udKey.c_str()); + }; + DataLoadParams dataLoadParams; + dataLoadParams.dataLoadInfo = dataLoadInfo1; + dataLoadParams.loadHandler = loadHandler; + std::string key = ""; + auto status = UdmfClient::GetInstance().SetDelayInfo(dataLoadParams, key); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest003 end."); +} + +/* * + * @tc.name: UdmfDelayDataTest004 + * @tc.desc: Test invalid parameters + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, UdmfDelayDataTest004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest004 begin."); + SetHapToken1(); + UnifiedData data; + auto obj = std::make_shared<Object>(); + auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); + plainText->SetContent("content1"); + data.AddRecord(plainText); + std::string udKey = ""; + auto ret = UdmfClient::GetInstance().PushDelayData(udKey, data); + EXPECT_EQ(ret, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest004 end."); +} + +std::string UdmfDelayDataTest::SetDataInfoTest(const std::string &key) +{ + DataLoadInfo dataLoadInfo1; + dataLoadInfo1.recordCount = 10; + dataLoadInfo1.types = {"general.plain-text", "general.html"}; + dataLoadInfo1.sequenceKey = key; + DataLoadInfo dataLoadInfo2; + dataLoadInfo2.recordCount = 100; + dataLoadInfo2.types = {"general.plain-text"}; + auto loadHandler = [dataLoadInfo2] (const std::string &udKey, const DataLoadInfo &dataLoadInfo) { + LOG_INFO(UDMF_TEST, "loadHandler begin udKey=%{public}s.", udKey.c_str()); + EXPECT_EQ(dataLoadInfo.recordCount, dataLoadInfo2.recordCount); + EXPECT_EQ(dataLoadInfo.types, dataLoadInfo2.types); + UnifiedData data; + auto obj = std::make_shared<Object>(); + auto plainText = std::make_shared<PlainText>(UDType::PLAIN_TEXT, obj); + plainText->SetContent("content1"); + data.AddRecord(plainText); + auto ret = UdmfClient::GetInstance().PushDelayData(udKey, data); + EXPECT_EQ(ret, E_OK); + }; + DataLoadParams dataLoadParams; + dataLoadParams.dataLoadInfo = dataLoadInfo1; + dataLoadParams.loadHandler = loadHandler; + std::string udkey = ""; + auto status = UdmfClient::GetInstance().SetDelayInfo(dataLoadParams, udkey); + EXPECT_EQ(status, E_OK); + return udkey; +} + +void UdmfDelayDataTest::GetDelayDataTest(const std::string &key) +{ + DataLoadInfo dataLoadInfo2; + dataLoadInfo2.recordCount = 100; + dataLoadInfo2.types = {"general.plain-text"}; + auto callback = [](ProgressInfo progress, std::shared_ptr<UnifiedData> data) { + LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d", + progress.progressStatus, progress.progress); + if (data == nullptr) { + ASSERT_TRUE(progress.progress != 0); + return; + } + ASSERT_EQ(1, data->GetRecords().size()); + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest002 callback end."); + }; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; + GetDataParams params; + params.query = query; + params.progressIndicator = ProgressIndicator::NONE; + params.progressListener = callback; + params.acceptableInfo = dataLoadInfo2; + auto status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(params); + EXPECT_EQ(status, E_OK); +} + +/* * + * @tc.name: UdmfDelayDataTest005 + * @tc.desc: Test multi thread delay data + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, UdmfDelayDataTest005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest005 begin."); + SetHapToken1(); + std::string key1 = UTILS::GenerateId(); + std::string key2 = UTILS::GenerateId(); + std::string key3 = UTILS::GenerateId(); + + std::thread t1([&]() { + key1 = SetDataInfoTest(key1); + GetDelayDataTest(key1); + }); + std::thread t2([&]() { + key2 = SetDataInfoTest(key2); + GetDelayDataTest(key2); + }); + std::thread t3([&]() { + key3 = SetDataInfoTest(key3); + GetDelayDataTest(key3); + }); + EXPECT_NO_FATAL_FAILURE(t1.join()); + EXPECT_NO_FATAL_FAILURE(t2.join()); + EXPECT_NO_FATAL_FAILURE(t3.join()); + + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest005 end."); +} + +/* * + * @tc.name: GetSequenceKey001 + * @tc.desc: Test normal GetSequenceKey + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, GetSequenceKey001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UdmfDelayDataTest005 begin."); + EXPECT_EQ(UTILS::GetSequenceKey("abc/def"), "def"); + EXPECT_EQ(UTILS::GetSequenceKey("one/two/three"), "three"); + EXPECT_EQ(UTILS::GetSequenceKey("/abc/def/ghi"), "ghi"); + LOG_INFO(UDMF_TEST, "GetSequenceKey001 end."); +} + +/* * + * @tc.name: GetSequenceKey002 + * @tc.desc: Test abnormal GetSequenceKey + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, GetSequenceKey002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetSequenceKey002 begin."); + EXPECT_EQ(UTILS::GetSequenceKey("abc/"), ""); + EXPECT_EQ(UTILS::GetSequenceKey("abcdef"), ""); + EXPECT_EQ(UTILS::GetSequenceKey(""), ""); + EXPECT_EQ(UTILS::GetSequenceKey("/"), ""); + EXPECT_EQ(UTILS::GetSequenceKey("/abc/def/"), ""); + LOG_INFO(UDMF_TEST, "GetSequenceKey002 end."); +} + +std::string UdmfDelayDataTest::NdkSetDataInfoTest() +{ + DataLoadInfo dataLoadInfo1; + dataLoadInfo1.recordCount = 10; + dataLoadInfo1.types = {"general.plain-text", "general.html"}; + OH_UdmfDataLoadInfo *info1 = OH_UdmfDataLoadInfo_Create(); + OH_UdmfDataLoadInfo_SetType(info1, "general.plain-text"); + OH_UdmfDataLoadInfo_SetType(info1, "general.html"); + OH_UdmfDataLoadInfo_SetRecordCount(info1, dataLoadInfo1.recordCount); + + OH_Udmf_DataLoadHandler loadHandler = [] (OH_UdmfDataLoadInfo* acceptableInfo) { + LOG_INFO(UDMF_TEST, "loadHandler begin."); + auto recordCount = OH_UdmfDataLoadInfo_GetRecordCount(acceptableInfo); + EXPECT_EQ(recordCount, 100); + unsigned int typeCount = 0; + auto types = OH_UdmfDataLoadInfo_GetTypes(acceptableInfo, &typeCount); + EXPECT_EQ(typeCount, 1); + EXPECT_STREQ(types[0], "general.plain-text"); + + OH_UdmfData *unifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsPlainText *plainText = OH_UdsPlainText_Create(); + auto status = OH_UdsPlainText_SetContent(plainText, "content1"); + EXPECT_EQ(status, E_OK); + status = OH_UdmfRecord_AddPlainText(record, plainText); + EXPECT_EQ(status, E_OK); + status = OH_UdmfData_AddRecord(unifiedData, record); + EXPECT_EQ(status, E_OK); + return unifiedData; + }; + + OH_UdmfDataLoadParams *ndkParams = OH_UdmfDataLoadParams_Create(); + OH_UdmfDataLoadParams_SetDataLoadInfo(ndkParams, info1); + OH_UdmfDataLoadParams_SetLoadHandler(ndkParams, loadHandler); + DataLoadParams dataLoadParams; + auto status = DataParamsConversion::GetDataLoaderParams(*ndkParams, dataLoadParams); + EXPECT_EQ(status, E_OK); + + SetHapToken1(); + std::string udkey = ""; + status = UdmfClient::GetInstance().SetDelayInfo(dataLoadParams, udkey); + EXPECT_EQ(status, E_OK); + return udkey; +} + +void UdmfDelayDataTest::NdkGetDelayDataTest(const std::string &key) +{ + DataLoadInfo dataLoadInfo2; + dataLoadInfo2.recordCount = 100; + dataLoadInfo2.types = {"general.plain-text"}; + QueryOption query; + query.intention = UD_INTENTION_DRAG; + query.key = key; + AddPrivilege(query); + + SetHapToken2(); + OH_UdmfDataLoadInfo *info2 = OH_UdmfDataLoadInfo_Create(); + OH_UdmfDataLoadInfo_SetType(info2, "general.plain-text"); + OH_UdmfDataLoadInfo_SetRecordCount(info2, dataLoadInfo2.recordCount); + + OH_UdmfGetDataParams *param = OH_UdmfGetDataParams_Create(); + OH_UdmfGetDataParams_SetProgressIndicator(param, Udmf_ProgressIndicator::UDMF_DEFAULT); + OH_UdmfGetDataParams_SetAcceptableInfo(param, info2); + OH_Udmf_DataProgressListener dataProgressListener = [](OH_Udmf_ProgressInfo *progressInfo, OH_UdmfData *data) { + auto progress = OH_UdmfProgressInfo_GetProgress(progressInfo); + auto status = OH_UdmfProgressInfo_GetStatus(progressInfo); + LOG_INFO(UDMF_TEST, "Callback begin status=%{public}d, progress=%{public}d.", status, progress); + if (data == nullptr) { + ASSERT_TRUE(progress != 0); + return; + } + unsigned int count = 0; + OH_UdmfData_GetRecords(data, &count); + ASSERT_EQ(1, count); + LOG_INFO(UDMF_TEST, "UdmfDelayDataNDKTest001 callback end."); + }; + OH_UdmfGetDataParams_SetDataProgressListener(param, dataProgressListener); + GetDataParams dataParams; + auto status = DataParamsConversion::GetInnerDataParams(*param, query, dataParams); + EXPECT_EQ(status, E_OK); + status = UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(dataParams); + EXPECT_EQ(status, E_OK); +} + +/* * + * @tc.name: UdmfDelayDataNDKTest001 + * @tc.desc: Test CAPI delay data + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, UdmfDelayDataNDKTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "UdmfDelayDataNDKTest001 begin."); + DataLoadInfo dataLoadInfo1; + dataLoadInfo1.recordCount = 10; + dataLoadInfo1.types = {"general.plain-text", "general.html"}; + DataLoadInfo dataLoadInfo2; + dataLoadInfo2.recordCount = 100; + dataLoadInfo2.types = {"general.plain-text"}; + auto key = NdkSetDataInfoTest(); + + QueryOption option; + option.intention = UD_INTENTION_DRAG; + option.key = key; + Summary summary; + auto status = UdmfClient::GetInstance().GetSummary(option, summary); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(summary.totalSize, dataLoadInfo1.recordCount); + EXPECT_EQ(summary.summary.size(), dataLoadInfo1.types.size()); + for (auto &item: summary.summary) { + EXPECT_NE(summary.summary.find(item.first), summary.summary.end()); + EXPECT_EQ(item.second, 0); + } + NdkGetDelayDataTest(key); + + LOG_INFO(UDMF_TEST, "UdmfDelayDataNDKTest001 end."); +} + +/** + * @tc.name: OH_UdmfDataLoadParams_Create_Destroy_001 + * @tc.desc: Test create and destroy of OH_UdmfDataLoadParams + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, OH_UdmfDataLoadParams_Create_Destroy_001, TestSize.Level0) +{ + OH_UdmfDataLoadParams* params = OH_UdmfDataLoadParams_Create(); + EXPECT_NE(params, nullptr); + OH_UdmfDataLoadParams_Destroy(params); +} + +/** + * @tc.name: OH_UdmfDataLoadParams_Destroy_Null_001 + * @tc.desc: Test destroy OH_UdmfDataLoadParams with null pointer + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, OH_UdmfDataLoadParams_Destroy_Null_001, TestSize.Level0) +{ + OH_UdmfDataLoadParams_Destroy(nullptr); +} + +/** + * @tc.name: OH_UdmfDataLoadInfo_Create_Destroy_001 + * @tc.desc: Test create and destroy of OH_UdmfDataLoadInfo + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, OH_UdmfDataLoadInfo_Create_Destroy_001, TestSize.Level0) +{ + OH_UdmfDataLoadInfo* info = OH_UdmfDataLoadInfo_Create(); + EXPECT_NE(info, nullptr); + OH_UdmfDataLoadInfo_Destroy(info); +} + +/** + * @tc.name: OH_UdmfDataLoadInfo_GetTypes_Invalid_001 + * @tc.desc: GetTypes with null dataLoadInfo or count + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, OH_UdmfDataLoadInfo_GetTypes_Invalid_001, TestSize.Level0) +{ + unsigned int count = 0; + char** result1 = OH_UdmfDataLoadInfo_GetTypes(nullptr, &count); + EXPECT_EQ(result1, nullptr); + + OH_UdmfDataLoadInfo* info = OH_UdmfDataLoadInfo_Create(); + char** result2 = OH_UdmfDataLoadInfo_GetTypes(info, nullptr); + EXPECT_EQ(result2, nullptr); + OH_UdmfDataLoadInfo_Destroy(info); +} + +/** + * @tc.name: OH_UdmfDataLoadInfo_SetType_And_GetTypes_001 + * @tc.desc: Test SetType and GetTypes logic + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, OH_UdmfDataLoadInfo_SetType_And_GetTypes_001, TestSize.Level0) +{ + OH_UdmfDataLoadInfo* info = OH_UdmfDataLoadInfo_Create(); + EXPECT_NE(info, nullptr); + + OH_UdmfDataLoadInfo_SetType(info, "image"); + OH_UdmfDataLoadInfo_SetType(info, "text"); + OH_UdmfDataLoadInfo_SetType(info, "text"); // duplicate + + unsigned int count = 0; + OH_UdmfDataLoadInfo_GetTypes(info, &count); + EXPECT_EQ(count, 2); + + OH_UdmfDataLoadInfo_Destroy(info); +} + +/** + * @tc.name: OH_UdmfDataLoadInfo_SetRecordCount_GetRecordCount_001 + * @tc.desc: Test setting and getting record count + * @tc.type: FUNC + */ +HWTEST_F(UdmfDelayDataTest, OH_UdmfDataLoadInfo_SetRecordCount_GetRecordCount_001, TestSize.Level0) +{ + OH_UdmfDataLoadInfo* info = OH_UdmfDataLoadInfo_Create(); + EXPECT_NE(info, nullptr); + + OH_UdmfDataLoadInfo_SetRecordCount(info, 10); + int count = OH_UdmfDataLoadInfo_GetRecordCount(info); + EXPECT_EQ(count, 10); + + OH_UdmfDataLoadInfo_Destroy(info); +} +} // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/unified_data_helper_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/unified_data_helper_test.cpp index 018e1b4f..5e569c92 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/unified_data_helper_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/unified_data_helper_test.cpp @@ -21,6 +21,7 @@ #include "logger.h" #include "udmf_capi_common.h" #include "unified_data_helper.h" +#include "file_uri.h" using namespace testing::ext; using namespace OHOS::UDMF; @@ -134,6 +135,22 @@ HWTEST_F(UnifiedDataHelperTest, SaveUDataToFile001, TestSize.Level1) LOG_INFO(UDMF_TEST, "SaveUDataToFile001 end."); } +/** +* @tc.name: SaveUDataToFile002 +* @tc.desc: Normal testcase of SaveUDataToFile +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedDataHelperTest, SaveUDataToFile002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SaveUDataToFile002 begin."); + const std::string dataFile = "data/test"; + UnifiedData data; + UnifiedDataHelper unifiedDataHelper; + bool ret = unifiedDataHelper.SaveUDataToFile(dataFile, data); + EXPECT_TRUE(ret); + LOG_INFO(UDMF_TEST, "SaveUDataToFile002 end."); +} + /** * @tc.name: LoadUDataFromFile001 * @tc.desc: Abnormal testcase of LoadUDataFromFile, the data is nullptr @@ -150,6 +167,22 @@ HWTEST_F(UnifiedDataHelperTest, LoadUDataFromFile001, TestSize.Level1) LOG_INFO(UDMF_TEST, "LoadUDataFromFile001 end."); } +/** +* @tc.name: LoadUDataFromFile002 +* @tc.desc: Abnormal testcase of LoadUDataFromFile, the data is nullptr +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedDataHelperTest, LoadUDataFromFile002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "LoadUDataFromFile002 begin."); + const std::string dataFile = "data/test"; + UnifiedData data; + UnifiedDataHelper unifiedDataHelper; + bool ret = unifiedDataHelper.LoadUDataFromFile(dataFile, data); + EXPECT_FALSE(ret); + LOG_INFO(UDMF_TEST, "LoadUDataFromFile002 end."); +} + /** * @tc.name: GetRootPath001 * @tc.desc: Abnormal testcase of GetRootPath, the rootPath_ is nullptr @@ -164,4 +197,37 @@ HWTEST_F(UnifiedDataHelperTest, GetRootPath001, TestSize.Level1) EXPECT_EQ(ret, TEMP_UNIFIED_DATA_ROOT_PATH); LOG_INFO(UDMF_TEST, "GetRootPath001 end."); } + +/** +* @tc.name: FileClose001 +* @tc.desc: Abnormal testcase of FileClose, the file is null +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedDataHelperTest, FileClose001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "FileClose001 begin."); + UnifiedDataHelper unifiedDataHelper; + const std::string dataFile = "data/test"; + AppFileService::ModuleFileUri::FileUri fileUri(dataFile); + std::string path = fileUri.GetRealPath(); + std::FILE *file = fopen(path.c_str(), "r"); + bool status = unifiedDataHelper.FileClose(file, true); + EXPECT_TRUE(status); + LOG_INFO(UDMF_TEST, "FileClose001 end."); +} + +/** +* @tc.name: FileClose002 +* @tc.desc: Abnormal testcase of FileClose, file is nullptr +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedDataHelperTest, FileClose002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "FileClose002 begin."); + UnifiedDataHelper unifiedDataHelper; + std::FILE *file = nullptr; + bool status = unifiedDataHelper.FileClose(file, true); + EXPECT_FALSE(status); + LOG_INFO(UDMF_TEST, "FileClose002 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/unified_data_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/unified_data_test.cpp index 89f6a988..a5d1e51b 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/unified_data_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/unified_data_test.cpp @@ -19,6 +19,7 @@ #include <string> #include "file.h" +#include "image.h" #include "logger.h" #include "plain_text.h" #include "udmf_capi_common.h" @@ -61,33 +62,26 @@ void UnifiedDataTest::TransferToEntriesCompareEntries(UnifiedRecord* recordFirst auto plainTextFirst = static_cast<PlainText*>(recordFirst); EXPECT_EQ(plainTextFirst->GetAbstract(), "abstract"); EXPECT_EQ(plainTextFirst->GetContent(), "http://1111/a.img"); - std::set<std::string> utdIds = recordFirst->GetUtdIds(); EXPECT_TRUE(utdIds.find("general.plain-text") != utdIds.end()); - EXPECT_TRUE(utdIds.find("general.file") != utdIds.end()); EXPECT_TRUE(utdIds.find("general.file-uri") != utdIds.end()); - EXPECT_TRUE(utdIds.find("general.img") == utdIds.end()); - EXPECT_TRUE(utdIds.find("general.media") != utdIds.end()); - - auto fileEntry = recordFirst->GetEntry("general.file"); + auto fileEntry = recordFirst->GetEntry("general.file-uri"); std::shared_ptr<Object> fileEntryObj = std::get<std::shared_ptr<Object>>(fileEntry); std::string getUri; fileEntryObj->GetValue(ORI_URI, getUri); - EXPECT_EQ(getUri, "http://1111/a.img"); - + EXPECT_EQ(getUri, "http://1111/a.mp4"); auto plainTextEntry = recordFirst->GetEntry("general.plain-text"); - EXPECT_TRUE(std::holds_alternative<std::monostate>(plainTextEntry)); - + std::shared_ptr<Object> plainTextEntryObj = std::get<std::shared_ptr<Object>>(plainTextEntry); + std::string getContent; + plainTextEntryObj->GetValue(CONTENT, getContent); + EXPECT_EQ(getContent, "http://1111/a.img"); + std::string getAbstract; + plainTextEntryObj->GetValue(ABSTRACT, getAbstract); + EXPECT_EQ(getAbstract, "abstract"); auto entries = recordFirst->GetEntries(); EXPECT_NE(entries, nullptr); - int entrySize = 3; + int entrySize = 2; EXPECT_EQ(entries->size(), entrySize); - auto fileEntry1 = (*entries)["general.file"]; - std::shared_ptr<Object> fileEntryObj1 = std::get<std::shared_ptr<Object>>(fileEntry1); - std::string getUri1; - fileEntryObj1->GetValue(ORI_URI, getUri1); - EXPECT_EQ(getUri1, "http://1111/a.img"); - auto plainTextEntry1 = (*entries)["general.plain-text"]; std::shared_ptr<Object> plainTextEntryObj1 = std::get<std::shared_ptr<Object>>(plainTextEntry1); std::string content; @@ -96,12 +90,11 @@ void UnifiedDataTest::TransferToEntriesCompareEntries(UnifiedRecord* recordFirst std::string abstract; plainTextEntryObj1->GetValue(ABSTRACT, abstract); EXPECT_EQ(abstract, "abstract"); - auto fileUriEntry1 = (*entries)["general.file-uri"]; std::shared_ptr<Object> fileUriEntryObj1 = std::get<std::shared_ptr<Object>>(fileUriEntry1); std::string oriUri; fileUriEntryObj1->GetValue(FILE_URI_PARAM, oriUri); - EXPECT_EQ(oriUri, "http://1111/a.img"); + EXPECT_EQ(oriUri, "http://1111/a.mp4"); std::string fileType; fileUriEntryObj1->GetValue(FILE_TYPE, fileType); EXPECT_EQ(fileType, "general.media"); @@ -219,8 +212,10 @@ HWTEST_F(UnifiedDataTest, GetRecordAt001, TestSize.Level1) */ HWTEST_F(UnifiedDataTest, TransferToEntries001, TestSize.Level1) { - LOG_INFO(UDMF_TEST, "TransferToEntries001 begin."); UnifiedData unifiedData; + std::shared_ptr<UnifiedDataProperties> properties = std::make_shared<UnifiedDataProperties>(); + properties->tag = "records_to_entries_data_format"; + unifiedData.SetProperties(properties); std::shared_ptr<PlainText> plainText = std::make_shared<PlainText>(); plainText->SetContent("http://1111/a.img"); plainText->SetAbstract("abstract"); @@ -228,7 +223,7 @@ HWTEST_F(UnifiedDataTest, TransferToEntries001, TestSize.Level1) file->SetUri("http://1111/a.img"); unifiedData.AddRecord(plainText); unifiedData.AddRecord(file); - unifiedData.TransferToEntries(unifiedData); + unifiedData.ConvertRecordsToEntries(); auto records = unifiedData.GetRecords(); int recordSize = 1; EXPECT_EQ(records.size(), recordSize); @@ -238,19 +233,23 @@ HWTEST_F(UnifiedDataTest, TransferToEntries001, TestSize.Level1) EXPECT_EQ(plainTextFirst->GetContent(), "http://1111/a.img"); std::set<std::string> utdIds = recordFirst->GetUtdIds(); EXPECT_TRUE(utdIds.find("general.plain-text") != utdIds.end()); - EXPECT_TRUE(utdIds.find("general.file") != utdIds.end()); - auto fileEntry = recordFirst->GetEntry("general.file"); + EXPECT_TRUE(utdIds.find("general.file-uri") != utdIds.end()); + auto fileEntry = recordFirst->GetEntry("general.file-uri"); std::shared_ptr<Object> fileEntryObj = std::get<std::shared_ptr<Object>>(fileEntry); std::string getUri; fileEntryObj->GetValue(ORI_URI, getUri); EXPECT_EQ(getUri, "http://1111/a.img"); auto plainTextEntry = recordFirst->GetEntry("general.plain-text"); - EXPECT_TRUE(std::holds_alternative<std::monostate>(plainTextEntry)); + EXPECT_FALSE(std::holds_alternative<std::monostate>(plainTextEntry)); + std::shared_ptr<Object> plainTextEntryObj = std::get<std::shared_ptr<Object>>(plainTextEntry); + std::string getContent; + plainTextEntryObj->GetValue(CONTENT, getContent); + EXPECT_EQ(getContent, "http://1111/a.img"); auto entries = recordFirst->GetEntries(); EXPECT_NE(entries, nullptr); int entrySize = 2; EXPECT_EQ(entries->size(), entrySize); - auto fileEntry1 = (*entries)["general.file"]; + auto fileEntry1 = (*entries)["general.file-uri"]; std::shared_ptr<Object> fileEntryObj1 = std::get<std::shared_ptr<Object>>(fileEntry1); std::string getUri1; fileEntryObj1->GetValue(ORI_URI, getUri1); @@ -263,7 +262,6 @@ HWTEST_F(UnifiedDataTest, TransferToEntries001, TestSize.Level1) std::string abstract; plainTextEntryObj1->GetValue(ABSTRACT, abstract); EXPECT_EQ(abstract, "abstract"); - LOG_INFO(UDMF_TEST, "TransferToEntries001 end."); } /** @@ -278,22 +276,18 @@ HWTEST_F(UnifiedDataTest, TransferToEntries002, TestSize.Level1) std::shared_ptr<PlainText> plainText = std::make_shared<PlainText>(); plainText->SetContent("http://1111/a.img"); plainText->SetAbstract("abstract"); - std::shared_ptr<File> file = std::make_shared<File>(); - file->SetUri("http://1111/a.img"); - + file->SetUri("http://1111/a.txt"); std::shared_ptr<Object> fileUriObj = std::make_shared<Object>(); fileUriObj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; fileUriObj->value_[FILE_URI_PARAM] = "http://1111/a.img"; fileUriObj->value_[FILE_TYPE] = "general.img"; std::shared_ptr<UnifiedRecord> fileUri = std::make_shared<UnifiedRecord>(FILE_URI, fileUriObj); - std::shared_ptr<Object> fileUriObj1 = std::make_shared<Object>(); fileUriObj1->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; - fileUriObj1->value_[FILE_URI_PARAM] = "http://1111/a.img"; + fileUriObj1->value_[FILE_URI_PARAM] = "http://1111/a.mp4"; fileUriObj1->value_[FILE_TYPE] = "general.media"; std::shared_ptr<UnifiedRecord> fileUri1 = std::make_shared<UnifiedRecord>(FILE_URI, fileUriObj1); - bool isNeed = unifiedData.IsNeedTransferToEntries(); EXPECT_FALSE(isNeed); unifiedData.AddRecord(plainText); @@ -309,14 +303,147 @@ HWTEST_F(UnifiedDataTest, TransferToEntries002, TestSize.Level1) unifiedData.SetProperties(properties); isNeed = unifiedData.IsNeedTransferToEntries(); EXPECT_TRUE(isNeed); - - unifiedData.TransferToEntries(unifiedData); + unifiedData.ConvertRecordsToEntries(); auto records = unifiedData.GetRecords(); int recordSize = 1; EXPECT_EQ(records.size(), recordSize); - auto recordFirst = records[0].get(); TransferToEntriesCompareEntries(recordFirst); LOG_INFO(UDMF_TEST, "TransferToEntries001 end."); } + +/** +* @tc.name: HasHigherFileTypeTest001 +* @tc.desc: Normal test of HasHigherFileType return true. +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedDataTest, HasHigherFileTypeTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "HasHigherFileTypeTest001 begin."); + std::shared_ptr<Object> fileObj = std::make_shared<Object>(); + fileObj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + fileObj->value_[FILE_URI_PARAM] = "file://1111/a.jpeg"; + fileObj->value_[FILE_TYPE] = "general.jpeg"; + std::shared_ptr<UnifiedRecord> file = std::make_shared<UnifiedRecord>(FILE_URI, fileObj); + + std::shared_ptr<Object> fileObj1 = std::make_shared<Object>(); + fileObj1->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + fileObj1->value_[FILE_URI_PARAM] = "file://1111/a.mp4"; + fileObj1->value_[FILE_TYPE] = "general.mpeg-4"; + std::shared_ptr<UnifiedRecord> file1 = std::make_shared<UnifiedRecord>(FILE_URI, fileObj1); + + std::shared_ptr<Object> fileObj2 = std::make_shared<Object>(); + fileObj2->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + fileObj2->value_[FILE_URI_PARAM] = "file://1111/a.txt"; + fileObj2->value_[FILE_TYPE] = "general.file"; + std::shared_ptr<UnifiedRecord> file2 = std::make_shared<UnifiedRecord>(FILE_URI, fileObj2); + UnifiedData unifiedData; + unifiedData.AddRecord(file); + unifiedData.AddRecord(file1); + unifiedData.AddRecord(file2); + EXPECT_TRUE(unifiedData.HasHigherFileType("general.file-uri")); + EXPECT_TRUE(unifiedData.HasHigherFileType("general.image")); + EXPECT_TRUE(unifiedData.HasHigherFileType("general.file")); + EXPECT_TRUE(unifiedData.HasHigherFileType("general.video")); + EXPECT_TRUE(unifiedData.HasHigherFileType("general.jpeg")); + EXPECT_TRUE(unifiedData.HasHigherFileType("general.mpeg-4")); + EXPECT_FALSE(unifiedData.HasHigherFileType("general.folder")); + EXPECT_FALSE(unifiedData.HasHigherFileType("general.audio")); + LOG_INFO(UDMF_TEST, "HasHigherFileTypeTest001 end."); +} + +/** +* @tc.name: IsCompleteTest001 +* @tc.desc: Normal test of HasHigherFileType return true. +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedDataTest, IsCompleteTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "IsCompleteTest001 begin."); + UnifiedData unifiedData; + EXPECT_FALSE(unifiedData.IsComplete()); + + Runtime runtime; + runtime.recordTotalNum = 1; + unifiedData.SetRuntime(runtime); + EXPECT_FALSE(unifiedData.IsComplete()); + + std::shared_ptr<Object> fileObj = std::make_shared<Object>(); + fileObj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + fileObj->value_[FILE_URI_PARAM] = "file://1111/a.jpeg"; + fileObj->value_[FILE_TYPE] = "general.jpeg"; + std::shared_ptr<UnifiedRecord> fileRecord = std::make_shared<UnifiedRecord>(FILE_URI, fileObj); + unifiedData.AddRecord(fileRecord); + EXPECT_TRUE(unifiedData.IsComplete()); + + std::shared_ptr<Object> plainTextObj = std::make_shared<Object>(); + plainTextObj->value_[UNIFORM_DATA_TYPE] = "general.plain-text"; + plainTextObj->value_[CONTENT] = "Hello, World!"; + plainTextObj->value_[ABSTRACT] = "This is a test."; + std::shared_ptr<UnifiedRecord> plainTextRecord = std::make_shared<UnifiedRecord>(PLAIN_TEXT, plainTextObj); + unifiedData.AddRecord(plainTextRecord); + EXPECT_FALSE(unifiedData.IsComplete()); + LOG_INFO(UDMF_TEST, "IsCompleteTest001 end."); +} + +/** +* @tc.name: GetFileUrisTest001 +* @tc.desc: Normal test of HasHigherFileType return true. +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedDataTest, GetFileUrisTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetFileUrisTest001 begin."); + UnifiedData unifiedData; + std::shared_ptr<Object> fileObj = std::make_shared<Object>(); + fileObj->value_[UNIFORM_DATA_TYPE] = "general.file-uri"; + fileObj->value_[FILE_URI_PARAM] = "file://1111/a.jpeg"; + fileObj->value_[FILE_TYPE] = "general.jpeg"; + std::shared_ptr<UnifiedRecord> fileRecord = std::make_shared<UnifiedRecord>(FILE_URI, fileObj); + unifiedData.AddRecord(fileRecord); + + std::shared_ptr<Object> plainTextObj = std::make_shared<Object>(); + plainTextObj->value_[UNIFORM_DATA_TYPE] = "general.plain-text"; + plainTextObj->value_[CONTENT] = "Hello, World!"; + plainTextObj->value_[ABSTRACT] = "This is a test."; + std::shared_ptr<UnifiedRecord> plainTextRecord = std::make_shared<UnifiedRecord>(PLAIN_TEXT, plainTextObj); + unifiedData.AddRecord(plainTextRecord); + + std::shared_ptr<Image> image = std::make_shared<Image>(); + image->SetUri("file://1111/a.png"); + unifiedData.AddRecord(image); + + unifiedData.AddRecord(nullptr); + std::vector<std::string> fileUris = unifiedData.GetFileUris(); + EXPECT_EQ(fileUris.size(), 2); + EXPECT_TRUE(std::find(fileUris.begin(), fileUris.end(), "file://1111/a.jpeg") != fileUris.end()); + EXPECT_TRUE(std::find(fileUris.begin(), fileUris.end(), "file://1111/a.png") != fileUris.end()); + LOG_INFO(UDMF_TEST, "GetFileUrisTest001 end."); +} + +/** + * @tc.name: GetDataId_001 + * @tc.desc: Get dataId. + * @tc.type: FUNC + */ +HWTEST_F(UnifiedDataTest, GetDataId_001, TestSize.Level0) +{ + uint32_t dataId = 2; + UnifiedData unifiedData; + unifiedData.SetDataId(dataId); + auto getDataId = unifiedData.GetDataId(); + EXPECT_EQ(getDataId, dataId); +} + +/** + * @tc.name: SetChannelName_001 + * @tc.desc: Set channelName. + * @tc.type: FUNC + */ +HWTEST_F(UnifiedDataTest, SetChannelName_001, TestSize.Level0) +{ + const std::string name = "channelName"; + UnifiedData unifiedData; + EXPECT_NO_FATAL_FAILURE(unifiedData.SetChannelName(name)); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/unified_key_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/unified_key_test.cpp new file mode 100644 index 00000000..9abd6e0b --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/unittest/unified_key_test.cpp @@ -0,0 +1,339 @@ +/* + * 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. + */ +#define LOG_TAG "unifiedKeyTest" + +#include <unistd.h> +#include <gtest/gtest.h> +#include <string> +#include "unified_key.h" + +using namespace testing::ext; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { +using namespace std; + +class UnifiedKeyTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void UnifiedKeyTest::SetUpTestCase() +{ +} + +void UnifiedKeyTest::TearDownTestCase() +{ +} + +void UnifiedKeyTest::SetUp() +{ +} + +void UnifiedKeyTest::TearDown() +{ +} + +/** +* @tc.name: UnifiedKey001 +* @tc.desc: Normal testcase of UnifiedKey +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, UnifiedKey001, TestSize.Level1) +{ + std::string key = "general.text"; + UnifiedKey unifiedKey(key); + EXPECT_FALSE(unifiedKey.key.empty()); +} + +/** +* @tc.name: UnifiedKey002 +* @tc.desc: Normal testcase of UnifiedKey +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, UnifiedKey002, TestSize.Level1) +{ + std::string intention = "general.text"; + std::string bundle = "com.ohos.test"; + std::string groupId = "test"; + + UnifiedKey unifiedKey(intention, bundle, groupId); + EXPECT_FALSE(unifiedKey.intention.empty()); + EXPECT_FALSE(unifiedKey.bundleName.empty()); + EXPECT_FALSE(unifiedKey.groupId.empty()); +} + +/** +* @tc.name: GetUnifiedKey001 +* @tc.desc: Normal testcase of GetUnifiedKey, this->key is empty +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetUnifiedKey001, TestSize.Level1) +{ + std::string intention = "general.text"; + std::string bundle = "com.ohos.test"; + std::string groupId = "test"; + + UnifiedKey unifiedKey(intention, bundle, groupId); + EXPECT_NO_FATAL_FAILURE(unifiedKey.GetUnifiedKey()); +} + +/** +* @tc.name: GetUnifiedKey002 +* @tc.desc: Normal testcase of GetUnifiedKey +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetUnifiedKey002, TestSize.Level1) +{ + std::string key = "general.text"; + UnifiedKey unifiedKey(key); + std::string ret = unifiedKey.GetUnifiedKey(); + EXPECT_EQ(ret, key); +} + +/** +* @tc.name: GetUnifiedKey003 +* @tc.desc: Abnormal testcase of GetUnifiedKey, this->intention is empty +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetUnifiedKey003, TestSize.Level1) +{ + std::string intention; + std::string bundle = "com.ohos.test"; + std::string groupId = "group1"; + + UnifiedKey unifiedKey(intention, bundle, groupId); + std::string ret = unifiedKey.GetUnifiedKey(); + EXPECT_EQ(ret, ""); +} + +/** +* @tc.name: GetUnifiedKey004 +* @tc.desc: Abnormal testcase of GetUnifiedKey, this->groupId is empty +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetUnifiedKey004, TestSize.Level1) +{ + std::string intention = "intention1"; + std::string bundle; + std::string groupId; + + UnifiedKey unifiedKey(intention, bundle, groupId); + std::string ret = unifiedKey.GetUnifiedKey(); + EXPECT_EQ(ret, ""); +} + +/** +* @tc.name: GetUnifiedKey005 +* @tc.desc: Abnormal testcase of GetUnifiedKey, this->groupId and this->intention is empty +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetUnifiedKey005, TestSize.Level1) +{ + std::string intention; + std::string bundle; + std::string groupId; + + UnifiedKey unifiedKey(intention, bundle, groupId); + std::string ret = unifiedKey.GetUnifiedKey(); + EXPECT_EQ(ret, ""); +} + +/** +* @tc.name: GetKeyCommonPrefix001 +* @tc.desc: Abnormal testcase of GetKeyCommonPrefix, size of this->key is 33 +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetKeyCommonPrefix001, TestSize.Level1) +{ + std::string key('A', 33); + UnifiedKey unifiedKey(key); + + std::string ret = unifiedKey.GetKeyCommonPrefix(); + EXPECT_FALSE(ret.empty()); +} + +/** +* @tc.name: GetKeyCommonPrefix002 +* @tc.desc: Abnormal testcase of GetKeyCommonPrefix, size of this->key is 31, this->intention is empty +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetKeyCommonPrefix002, TestSize.Level1) +{ + std::string intention; + std::string bundle = "com.ohos.test"; + std::string groupId('A', 31); + UnifiedKey unifiedKey(intention, bundle, groupId); + + std::string ret = unifiedKey.GetKeyCommonPrefix(); + EXPECT_EQ(ret, ""); +} + +/** +* @tc.name: GetKeyCommonPrefix003 +* @tc.desc: Abnormal testcase of GetKeyCommonPrefix, this->groupId size < INDEX_LEN +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetKeyCommonPrefix003, TestSize.Level1) +{ + std::string intention = "general.text"; + std::string bundle = "com.ohos.test"; + std::string groupId = "test"; + + UnifiedKey unifiedKey(intention, bundle, groupId); + std::string ret = unifiedKey.GetKeyCommonPrefix(); + EXPECT_EQ(ret, ""); +} + +/** +* @tc.name: GetKeyCommonPrefix004 +* @tc.desc: Abnormal testcase of GetKeyCommonPrefix, this->groupId size < INDEX_LEN +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, GetKeyCommonPrefix004, TestSize.Level1) +{ + std::string intention = "general.text"; + std::string bundle = "com.ohos.test"; + std::string groupId('A', 33); + + UnifiedKey unifiedKey(intention, bundle, groupId); + std::string ret = unifiedKey.GetKeyCommonPrefix(); + EXPECT_FALSE(ret.empty()); +} + +/** +* @tc.name: IsValid001 +* @tc.desc: Normal testcase of IsValid, key is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, IsValid001, TestSize.Level1) +{ + std::string intention = "general.text"; + std::string bundle = "com.ohos.test"; + std::string groupId('A', 33); + + UnifiedKey unifiedKey(intention, bundle, groupId); + bool ret = unifiedKey.IsValid(); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: IsValid002 +* @tc.desc: Abnormal testcase of IsValid, key is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, IsValid002, TestSize.Level1) +{ + std::string key('A', 33); + UnifiedKey unifiedKey(key); + + bool ret = unifiedKey.IsValid(); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: IsValid003 +* @tc.desc: Abnormal testcase of IsValid, key is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, IsValid003, TestSize.Level1) +{ + std::string key = "udmf://"; + UnifiedKey unifiedKey(key); + + bool ret = unifiedKey.IsValid(); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: PreliminaryWork002 +* @tc.desc: Normal testcase of PreliminaryWork +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, PreliminaryWork002, TestSize.Level1) +{ + std::string key = "udmf://"; + UnifiedKey unifiedKey(key); + + EXPECT_NO_FATAL_FAILURE(unifiedKey.PreliminaryWork()); +} + +/** +* @tc.name: CheckCharacter001 +* @tc.desc: Abnormal testcase of CheckCharacter, data is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, CheckCharacter001, TestSize.Level1) +{ + std::string key = "udmf://"; + UnifiedKey unifiedKey(key); + std::string_view data; + std::bitset<MAX_BIT_SIZE> rule; + + EXPECT_FALSE(unifiedKey.CheckCharacter(data, rule)); +} + +/** +* @tc.name: CheckCharacter002 +* @tc.desc: Abnormal testcase of CheckCharacter, data is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, CheckCharacter002, TestSize.Level1) +{ + std::string key = "udmf://"; + UnifiedKey unifiedKey(key); + std::string_view data = "data"; + std::bitset<MAX_BIT_SIZE> rule; + + EXPECT_FALSE(unifiedKey.CheckCharacter(data, rule)); +} + +/** +* @tc.name: ExtractAndValidateSegment001 +* @tc.desc: Abnormal testcase of ExtractAndValidateSegment, data is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, ExtractAndValidateSegment001, TestSize.Level1) +{ + std::string key = "udmf://"; + UnifiedKey unifiedKey(key); + std::string_view data = "data"; + std::string field; + std::bitset<MAX_BIT_SIZE> rule; + std::string name; + + EXPECT_FALSE(unifiedKey.ExtractAndValidateSegment(data, field, rule, name)); +} + +/** +* @tc.name: ExtractAndValidateSegment002 +* @tc.desc: Abnormal testcase of ExtractAndValidateSegment, data is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedKeyTest, ExtractAndValidateSegment002, TestSize.Level1) +{ + std::string key = "udmf://"; + UnifiedKey unifiedKey(key); + std::string_view data = "udmf://"; + std::string field = "udmf://"; + std::bitset<MAX_BIT_SIZE> rule; + std::string name; + + EXPECT_FALSE(unifiedKey.ExtractAndValidateSegment(data, field, rule, name)); +} +} // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/unified_meta_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/unified_meta_test.cpp index 2d569086..126c1d5c 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/unified_meta_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/unified_meta_test.cpp @@ -253,6 +253,15 @@ HWTEST_F(UnifiedMetaTest, IsValidIntention001, TestSize.Level1) bool ret1 = UnifiedDataUtils::IsValidIntention(Intention::UD_INTENTION_DATA_HUB); EXPECT_TRUE(ret1); + + bool ret2 = UnifiedDataUtils::IsValidIntention(Intention::UD_INTENTION_SYSTEM_SHARE); + EXPECT_TRUE(ret2); + + bool ret3 = UnifiedDataUtils::IsValidIntention(Intention::UD_INTENTION_PICKER); + EXPECT_TRUE(ret3); + + bool ret4 = UnifiedDataUtils::IsValidIntention(Intention::UD_INTENTION_MENU); + EXPECT_TRUE(ret4); } /** @@ -385,6 +394,15 @@ HWTEST_F(UnifiedMetaTest, IsPersistByIntention001, TestSize.Level1) bool ret3 = UnifiedDataUtils::IsPersist(Intention::UD_INTENTION_BASE); EXPECT_FALSE(ret3); + + bool ret4 = UnifiedDataUtils::IsPersist(Intention::UD_INTENTION_PICKER); + EXPECT_TRUE(ret4); + + bool ret5 = UnifiedDataUtils::IsPersist(Intention::UD_INTENTION_MENU); + EXPECT_TRUE(ret5); + + bool ret6 = UnifiedDataUtils::IsPersist(Intention::UD_INTENTION_SYSTEM_SHARE); + EXPECT_TRUE(ret6); } /** @@ -402,6 +420,15 @@ HWTEST_F(UnifiedMetaTest, IsPersistByStr001, TestSize.Level1) bool ret2 = UnifiedDataUtils::IsPersist("invalid param"); EXPECT_FALSE(ret2); + + bool ret3 = UnifiedDataUtils::IsPersist("Picker"); + EXPECT_TRUE(ret3); + + bool ret4 = UnifiedDataUtils::IsPersist("Menu"); + EXPECT_TRUE(ret4); + + bool ret5 = UnifiedDataUtils::IsPersist("SystemShare"); + EXPECT_TRUE(ret5); } /** @@ -419,35 +446,267 @@ HWTEST_F(UnifiedMetaTest, GetIntentionByString001, TestSize.Level1) Intention ret2 = UnifiedDataUtils::GetIntentionByString("invalid param"); EXPECT_EQ(ret2, UD_INTENTION_BUTT); + + Intention ret3 = UnifiedDataUtils::GetIntentionByString("Picker"); + EXPECT_EQ(ret3, Intention::UD_INTENTION_PICKER); + + Intention ret4 = UnifiedDataUtils::GetIntentionByString("Menu"); + EXPECT_EQ(ret4, Intention::UD_INTENTION_MENU); + + Intention ret5 = UnifiedDataUtils::GetIntentionByString("SystemShare"); + EXPECT_EQ(ret5, Intention::UD_INTENTION_SYSTEM_SHARE); } /** -* @tc.name: IsValidOptions001 +* @tc.name: IsValidOptionsNonDrag001 * @tc.desc: Normal testcase of IsPersist * @tc.type: FUNC */ -HWTEST_F(UnifiedMetaTest, IsValidOptions001, TestSize.Level1) +HWTEST_F(UnifiedMetaTest, IsValidOptionsNonDrag001, TestSize.Level1) { std::string keyDataHub = "udmf://DataHub/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; std::string keyDrag = "udmf://drag/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string keyPicker = "udmf://Picker/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string keyMenu = "udmf://Menu/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string keySystemShare = "udmf://SystemShare/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; std::string intentionDataHub = "DataHub"; std::string intentionDrag = "drag"; + std::string intentionPicker = "Picker"; + std::string intentionMenu = "Menu"; + std::string intentionSystemShare = "SystemShare"; std::string intentionEmpty = ""; + UnifiedKey key1(""); - bool ret = UnifiedDataUtils::IsValidOptions("", intentionDataHub); + bool ret = UnifiedDataUtils::IsValidOptionsNonDrag(key1, intentionDataHub); EXPECT_TRUE(ret); - bool ret1 = UnifiedDataUtils::IsValidOptions(keyDataHub, intentionEmpty); + UnifiedKey key2(keyDataHub); + bool ret1 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionEmpty); EXPECT_TRUE(ret1); + bool ret2 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionDataHub); + EXPECT_TRUE(ret2); + bool ret3 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionDrag); + EXPECT_FALSE(ret3); + bool ret4 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionPicker); + EXPECT_FALSE(ret4); + bool ret5 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionMenu); + EXPECT_FALSE(ret5); + bool ret6 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionSystemShare); + EXPECT_FALSE(ret6); + UnifiedKey key3(keyDrag); + bool ret7 = UnifiedDataUtils::IsValidOptionsNonDrag(key3, intentionDrag); + EXPECT_FALSE(ret7); + UnifiedKey key4(keyPicker); + bool ret8 = UnifiedDataUtils::IsValidOptionsNonDrag(key4, intentionPicker); + EXPECT_TRUE(ret8); + UnifiedKey key5(keyMenu); + bool ret9 = UnifiedDataUtils::IsValidOptionsNonDrag(key5, intentionMenu); + EXPECT_TRUE(ret9); + UnifiedKey key6(keySystemShare); + bool ret10 = UnifiedDataUtils::IsValidOptionsNonDrag(key6, intentionSystemShare); + EXPECT_TRUE(ret10); +} + +/** +* @tc.name: IsValidOptionsNonDrag +* @tc.desc: Normal testcase of key and intention +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, IsAllowedQuery, TestSize.Level1) +{ + std::string keyDataHub = "udmf://DataHub/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string keyDrag = "udmf://drag/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string keyPicker = "udmf://Picker/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string keyMenu = "udmf://Menu/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string keySystemShare = "udmf://SystemShare/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string intentionDataHub = "DataHub"; + std::string intentionDrag = "drag"; + std::string intentionPicker = "Picker"; + std::string intentionMenu = "Menu"; + std::string intentionSystemShare = "SystemShare"; + std::string intentionEmpty = ""; + UnifiedKey key1(""); - bool ret2 = UnifiedDataUtils::IsValidOptions(keyDataHub, intentionDataHub); + bool ret = UnifiedDataUtils::IsValidOptionsNonDrag(key1, intentionDataHub); + EXPECT_TRUE(ret); + bool ret1 = UnifiedDataUtils::IsValidOptionsNonDrag(key1, intentionPicker); + EXPECT_FALSE(ret1); + UnifiedKey key2(keyDataHub); + bool ret2 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionEmpty); EXPECT_TRUE(ret2); + bool ret3 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionDataHub); + EXPECT_TRUE(ret3); + bool ret4 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionDrag); + EXPECT_FALSE(ret4); + bool ret5 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionPicker); + EXPECT_FALSE(ret5); + bool ret6 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionMenu); + EXPECT_FALSE(ret6); + bool ret7 = UnifiedDataUtils::IsValidOptionsNonDrag(key2, intentionSystemShare); + EXPECT_FALSE(ret7); + UnifiedKey key3(keyDrag); + bool ret8 = UnifiedDataUtils::IsValidOptionsNonDrag(key3, intentionDrag); + EXPECT_FALSE(ret8); +} + +/** +* @tc.name: IsValidQuery001 +* @tc.desc: Normal testcase of key and intention +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, IsValidQuery001, TestSize.Level1) +{ + std::string keyPicker = "udmf://Picker/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + std::string intentionDataHub = "DataHub"; + std::string intentionDrag = "drag"; + std::string intentionPicker = "Picker"; + std::string intentionMenu = "Menu"; + std::string intentionSystemShare = "SystemShare"; + std::string intentionEmpty = ""; + + UnifiedKey key(keyPicker); + bool ret = UnifiedDataUtils::IsValidOptionsNonDrag(key, intentionPicker); + EXPECT_TRUE(ret); + + bool ret1 = UnifiedDataUtils::IsValidOptionsNonDrag(key, intentionEmpty); + EXPECT_TRUE(ret1); + + bool ret2 = UnifiedDataUtils::IsValidOptionsNonDrag(key, intentionDataHub); + EXPECT_FALSE(ret2); - bool ret3 = UnifiedDataUtils::IsValidOptions(keyDataHub, intentionDrag); + bool ret3 = UnifiedDataUtils::IsValidOptionsNonDrag(key, intentionDrag); EXPECT_FALSE(ret3); - bool ret4 = UnifiedDataUtils::IsValidOptions(keyDrag, intentionDrag); + bool ret4 = UnifiedDataUtils::IsValidOptionsNonDrag(key, intentionMenu); EXPECT_FALSE(ret4); + + bool ret5 = UnifiedDataUtils::IsValidOptionsNonDrag(key, intentionSystemShare); + EXPECT_FALSE(ret5); +} + +/** +* @tc.name: IsValidOptions002 +* @tc.desc: Abnormal testcase of IsValidOptions, intention is empty +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, IsValidOptions002, TestSize.Level1) +{ + UnifiedKey key; + key.key = "key://"; + std::string intention; + std::string validIntention; + UnifiedDataUtils unifiedDataUtils; + bool ret = unifiedDataUtils.IsValidOptions(key, intention, validIntention); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: IsValidOptions003 +* @tc.desc: Abnormal testcase of IsValidOptions, intention != validIntention +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, IsValidOptions003, TestSize.Level1) +{ + UnifiedKey key; + key.key = "key://"; + std::string intention = "drag"; + std::string validIntention = "DataHub"; + UnifiedDataUtils unifiedDataUtils; + bool ret = unifiedDataUtils.IsValidOptions(key, intention, validIntention); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: IsValidOptions004 +* @tc.desc: Abnormal testcase of IsValidOptions, key.intention != validIntention +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, IsValidOptions004, TestSize.Level1) +{ + UnifiedKey key; + key.key = "key://"; + key.intention = "DataHub"; + std::string intention = "DataHub"; + std::string validIntention = "drag"; + UnifiedDataUtils unifiedDataUtils; + bool ret = unifiedDataUtils.IsValidOptions(key, intention, validIntention); + EXPECT_FALSE(ret); +} + +/** +* @tc.name: ConvertToUDDetails001 +* @tc.desc: Abnormal testcase of ConvertToUDDetails, object is nullptr +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, ConvertToUDDetails001, TestSize.Level1) +{ + std::shared_ptr<Object> object = nullptr; + EXPECT_NO_FATAL_FAILURE(ObjectUtils::ConvertToUDDetails(object)); +} + +/** +* @tc.name: GetValueSize001 +* @tc.desc: Normal testcase of GetValueSize +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, GetValueSize001, TestSize.Level1) +{ + ValueType value = std::make_shared<OHOS::Media::PixelMap>(); + bool isCalValueType = true; + int64_t ret = ObjectUtils::GetValueSize(value, isCalValueType); + EXPECT_EQ(ret, (std::get<std::shared_ptr<OHOS::Media::PixelMap>>(value))->GetByteCount()); +} + +/** +* @tc.name: GetValueSize002 +* @tc.desc: Normal testcase of GetValueSize +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, GetValueSize002, TestSize.Level1) +{ + ValueType value = std::make_shared<OHOS::AAFwk::Want>(); + bool isCalValueType = true; + int64_t ret = ObjectUtils::GetValueSize(value, isCalValueType); + EXPECT_NE(ret, 0); +} + +/** +* @tc.name: GetValueSize003 +* @tc.desc: Abnormal testcase of GetValueSize, value is invalid +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, GetValueSize003, TestSize.Level1) +{ + ValueType value = true; + bool isCalValueType = true; + int64_t ret = ObjectUtils::GetValueSize(value, isCalValueType); + EXPECT_EQ(ret, std::visit([] (const auto &val) { return sizeof(val); }, value)); +} + +/* * +* @tc.name: GetObjectValueSize_001 +* @tc.desc: Abnormal test of GetObjectValueSize, key is DETAILS +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, GetObjectValueSize_001, TestSize.Level1) +{ + std::shared_ptr<Object> object = std::make_shared<Object>(); + bool isCalValueType = true; + object->value_["details"] = std::make_shared<OHOS::Media::PixelMap>(); + size_t ret = ObjectUtils::GetObjectValueSize(object, isCalValueType); + EXPECT_EQ(ret, 0); +} + +/* * +* @tc.name: GetAllObjectSize_001 +* @tc.desc: Abnormal test of GetAllObjectSize, object is nullptr +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, GetAllObjectSize_001, TestSize.Level1) +{ + std::shared_ptr<Object> object = nullptr; + int64_t ret = ObjectUtils::GetAllObjectSize(object); + EXPECT_EQ(ret, 0); } /** @@ -506,4 +765,73 @@ HWTEST_F(UnifiedMetaTest, GetValue002, TestSize.Level1) bool ret2 = object.GetValue("invalid key", valueEmpty); EXPECT_FALSE(ret2); } + +/** +* @tc.name: IsFileMangerIntention +* @tc.desc: IsFileMangerIntention testcase +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, IsFileMangerIntention, TestSize.Level1) +{ + std::string intentionDataHub = "DataHub"; + std::string intentionDrag = "drag"; + std::string intentionPicker = "Picker"; + std::string intentionMenu = "Menu"; + std::string intentionSystemShare = "SystemShare"; + + bool ret = UnifiedDataUtils::IsFileMangerIntention(intentionDataHub); + EXPECT_FALSE(ret); + bool ret1 = UnifiedDataUtils::IsFileMangerIntention(intentionDrag); + EXPECT_FALSE(ret1); + bool ret2 = UnifiedDataUtils::IsFileMangerIntention(intentionPicker); + EXPECT_TRUE(ret2); + bool ret3 = UnifiedDataUtils::IsFileMangerIntention(intentionMenu); + EXPECT_TRUE(ret3); + bool ret4 = UnifiedDataUtils::IsFileMangerIntention(intentionSystemShare); + EXPECT_TRUE(ret4); +} + +/** +* @tc.name: IsFileMangerIntention +* @tc.desc: IsFileMangerIntention testcase +* @tc.type: FUNC +*/ +HWTEST_F(UnifiedMetaTest, GetBelongsToFileType, TestSize.Level1) +{ + std::string utdId = ""; + std::string fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_TRUE(fileType.empty()); + + utdId = "general.html"; + fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_TRUE(fileType.empty()); + + utdId = "general.plain-text"; + fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_TRUE(fileType.empty()); + + utdId = "general.text"; + fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_TRUE(fileType.empty()); + + utdId = "aaccss"; + fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_TRUE(fileType.empty()); + + utdId = "general.file"; + fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_EQ(fileType, "general.file"); + + utdId = "general.image"; + fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_EQ(fileType, "general.image"); + + utdId = "general.avi"; + fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_EQ(fileType, "general.video"); + + utdId = "com.adobe.pdf"; + fileType = UnifiedDataUtils::GetBelongsToFileType(utdId); + EXPECT_EQ(fileType, "general.file"); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/unified_record_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/unified_record_test.cpp index 05775c9e..92ea1d92 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/unified_record_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/unified_record_test.cpp @@ -88,7 +88,6 @@ HWTEST_F(UnifiedRecordTest, GetValue001, TestSize.Level1) LOG_INFO(UDMF_TEST, "GetValue001 end."); } - /** * @tc.name: Constructor_001 * @tc.desc: Verify the constructor. @@ -142,6 +141,32 @@ HWTEST_F(UnifiedRecordTest, Constructor_002, TestSize.Level0) EXPECT_TRUE(std::holds_alternative<std::shared_ptr<Object>>(it->second)); } +/** + * @tc.name: GetDataId_001 + * @tc.desc: Get dataId. + * @tc.type: FUNC + */ +HWTEST_F(UnifiedRecordTest, GetDataId_001, TestSize.Level0) +{ + UnifiedRecord record(TEXT); + uint32_t dataId = 1; + record.SetDataId(dataId); + auto data = record.GetDataId(); + EXPECT_EQ(data, 1); +} + +/** + * @tc.name: SetChannelName_001 + * @tc.desc: Set channelName. + * @tc.type: FUNC + */ +HWTEST_F(UnifiedRecordTest, SetChannelName_001, TestSize.Level0) +{ + UnifiedRecord record(TEXT); + std::string channelName = "channelName"; + EXPECT_NO_FATAL_FAILURE(record.SetChannelName(channelName);); +} + /** * @tc.name: Constructor_003 * @tc.desc: Verify the constructor. @@ -264,12 +289,12 @@ HWTEST_F(UnifiedRecordTest, GetEntryTest001, TestSize.Level1) UnifiedData readData; status = UdmfClient::GetInstance().GetData(option2, readData); auto recordFile = readData.GetRecordAt(0); - auto udsValue = recordFile->GetEntry("general.file"); + auto udsValue = recordFile->GetEntry("general.file-uri"); EXPECT_TRUE(std::holds_alternative<std::shared_ptr<Object>>(udsValue)); std::shared_ptr<Object> fileUds = std::get<std::shared_ptr<Object>>(udsValue); EXPECT_EQ(std::get<std::string>(fileUds->value_[ORI_URI]), "https://file/txt.txt"); auto recordImage = readData.GetRecordAt(1); - auto imageValue = recordImage->GetEntry("general.image"); + auto imageValue = recordImage->GetEntry("general.file-uri"); EXPECT_TRUE(std::holds_alternative<std::shared_ptr<Object>>(imageValue)); std::shared_ptr<Object> imageUds = std::get<std::shared_ptr<Object>>(imageValue); EXPECT_EQ(std::get<std::string>(imageUds->value_[ORI_URI]), "https://file/txt.txt"); @@ -307,12 +332,12 @@ HWTEST_F(UnifiedRecordTest, GetEntryTest002, TestSize.Level1) UnifiedData readData; status = UdmfClient::GetInstance().GetData(option2, readData); auto recordFile = readData.GetRecordAt(0); - auto udsValue = recordFile->GetEntry("general.file"); + auto udsValue = recordFile->GetEntry("general.file-uri"); EXPECT_TRUE(std::holds_alternative<std::shared_ptr<Object>>(udsValue)); std::shared_ptr<Object> fileUds = std::get<std::shared_ptr<Object>>(udsValue); EXPECT_EQ(std::get<std::string>(fileUds->value_[ORI_URI]), "https://file/txt.txt"); auto recordImage = readData.GetRecordAt(1); - auto imageValue = recordImage->GetEntry("general.image"); + auto imageValue = recordImage->GetEntry("general.file-uri"); EXPECT_TRUE(std::holds_alternative<std::shared_ptr<Object>>(imageValue)); std::shared_ptr<Object> imageUds = std::get<std::shared_ptr<Object>>(imageValue); EXPECT_EQ(std::get<std::string>(imageUds->value_[ORI_URI]), "https://file/txt.txt"); @@ -386,4 +411,16 @@ HWTEST_F(UnifiedRecordTest, GetEntryTest003, TestSize.Level1) EXPECT_TRUE(std::holds_alternative<std::monostate>( std::get<std::shared_ptr<Object>>(fifthValue)->value_[VALUE_TYPE])); } + +/** + * @tc.name: ComputeUris_001 + * @tc.desc: Compute uri + * @tc.type: FUNC + */ +HWTEST_F(UnifiedRecordTest, ComputeUris_001, TestSize.Level0) +{ + UnifiedRecord record(TEXT); + const std::function<bool(UriInfo &)> action; + EXPECT_NO_FATAL_FAILURE(record.ComputeUris(action)); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/utd_client_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/utd_client_test.cpp index 361ebd48..99b5355b 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/utd_client_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/utd_client_test.cpp @@ -16,6 +16,7 @@ #include <gtest/gtest.h> #include <unistd.h> +#include <thread> #include "token_setproc.h" #include "accesstoken_kit.h" @@ -26,6 +27,7 @@ #include "type_descriptor.h" #include "preset_type_descriptors.h" #include "utd_graph.h" +#include "custom_utd_store.h" using namespace testing::ext; using namespace OHOS::Security::AccessToken; @@ -33,12 +35,16 @@ using namespace OHOS::UDMF; using namespace OHOS; namespace OHOS::Test { +constexpr const int64_t SLEEP_INTERVAL = 12; +constexpr const int32_t USERID = 100; +constexpr const char *FLEXIBLE_TYPE_FLAG = "flex.z"; class UtdClientTest : public testing::Test { public: static void SetUpTestCase(); static void TearDownTestCase(); void SetUp() override; void TearDown() override; + static bool TryReloadCustomUtdTest(); }; void UtdClientTest::SetUpTestCase() @@ -1830,6 +1836,451 @@ HWTEST_F(UtdClientTest, IsUtd005, TestSize.Level1) LOG_INFO(UDMF_TEST, "IsUtd005 end."); } +/** +* @tc.name: TryReloadCustomUtdTest001 +* @tc.desc: TryReloadCustomUtd +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, TryReloadCustomUtdTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest001 begin."); + UtdClient utdClient; + bool ret = utdClient.TryReloadCustomUtd(); + EXPECT_FALSE(ret); + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest001 end."); +} + +/** +* @tc.name: TryReloadCustomUtdTest002 +* @tc.desc: TryReloadCustomUtd +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, TryReloadCustomUtdTest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest002 begin."); + UtdClient utdClient; + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + bool ret = utdClient.TryReloadCustomUtd(); + EXPECT_FALSE(ret); + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest002 end."); +} + +/** +* @tc.name: TryReloadCustomUtdTest003 +* @tc.desc: TryReloadCustomUtd +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, TryReloadCustomUtdTest003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest003 begin."); + UtdClient utdClient; + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + bool ret = utdClient.TryReloadCustomUtd(); + EXPECT_TRUE(ret); + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest003 end."); +} + +/** +* @tc.name: TryReloadCustomUtdTest004 +* @tc.desc: TryReloadCustomUtd +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, TryReloadCustomUtdTest004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest004 begin."); + UtdClient utdClient; + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + std::filesystem::resize_file(filePath, USERID * USERID); + bool ret = utdClient.TryReloadCustomUtd(); + EXPECT_FALSE(ret); + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest004 end."); +} + +bool UtdClientTest::TryReloadCustomUtdTest() +{ + UtdClient utdClient; + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + std::filesystem::resize_file(filePath, USERID * USERID); + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + return utdClient.TryReloadCustomUtd(); +} + +/** + * @tc.name: TryReloadCustomUtdTest005 + * @tc.desc: TryReloadCustomUtd + * @tc.type: FUNC + */ +HWTEST_F(UtdClientTest, TryReloadCustomUtdTest005, TestSize.Level0) +{ + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest005 begin."); + std::thread t1([&]() { + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + auto ret = TryReloadCustomUtdTest(); + EXPECT_TRUE(ret); + }); + EXPECT_NO_FATAL_FAILURE(t1.join()); + std::thread t2([&]() { + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + auto ret = TryReloadCustomUtdTest(); + EXPECT_TRUE(ret); + }); + EXPECT_NO_FATAL_FAILURE(t2.join()); + std::thread t3([&]() { + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + auto ret = TryReloadCustomUtdTest(); + EXPECT_TRUE(ret); + }); + EXPECT_NO_FATAL_FAILURE(t3.join()); + LOG_INFO(UDMF_TEST, "TryReloadCustomUtdTest005 end."); +} + +/** +* @tc.name: GetTypeDescriptorTest001 +* @tc.desc: GetTypeDescriptor +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeDescriptorTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeDescriptorTest001 begin."); + UtdClient utdClient; + std::string typeId("NotExist"); + std::shared_ptr<TypeDescriptor> descriptor = nullptr; + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + + auto ret = utdClient.GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(ret, 0); + LOG_INFO(UDMF_TEST, "GetTypeDescriptorTest001 end."); +} + +/** +* @tc.name: GetTypeDescriptorTest002 +* @tc.desc: GetTypeDescriptor +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeDescriptorTest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeDescriptorTest002 begin."); + UtdClient utdClient; + std::string typeId("NotExist"); + std::shared_ptr<TypeDescriptor> descriptor = nullptr; + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + auto ret = utdClient.GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(ret, 0); + LOG_INFO(UDMF_TEST, "GetTypeDescriptorTest002 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtensionTest001 +* @tc.desc: GetUniformDataTypeByFilenameExtension +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtensionTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionTest001 begin."); + UtdClient utdClient; + std::string extension = "NotExist"; + std::string blongsToType = "general.object"; + std::string currType; + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + auto ret = utdClient.GetUniformDataTypeByFilenameExtension(extension, currType, blongsToType); + EXPECT_EQ(ret, Status::E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionTest001 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtensionTest002 +* @tc.desc: GetUniformDataTypeByFilenameExtension +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtensionTest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionTest002 begin."); + UtdClient utdClient; + std::string extension = ".mp3"; + std::string blongsToType = "NotExist"; + std::string currType; + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + auto ret = utdClient.GetUniformDataTypeByFilenameExtension(extension, currType, blongsToType); + EXPECT_EQ(ret, Status::E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionTest002 end."); +} + +/** +* @tc.name: GetUniformDataTypesByFilenameExtensionTest007 +* @tc.desc: GetUniformDataTypesByFilenameExtension +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypesByFilenameExtensionTest007, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypesByFilenameExtensionTest007 begin."); + UtdClient utdClient; + std::string fileExtension = "fileExtension"; + std::vector<std::string> typeIds = std::vector<std::string>(); + std::string belongsTo = ""; + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + auto ret = utdClient.GetUniformDataTypesByFilenameExtension(fileExtension, typeIds, belongsTo); + EXPECT_EQ(ret, Status::E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypesByFilenameExtensionTest007 end."); +} + +/** +* @tc.name: GetUniformDataTypeByMIMETypeTest008 +* @tc.desc: GetUniformDataTypeByMIMEType +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMETypeTest008, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeTest008 begin."); + UtdClient utdClient; + std::string mimeType = ""; + std::string blongsToType = "test02"; + std::string currType; + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + auto ret = utdClient.GetUniformDataTypeByMIMEType(mimeType, currType, blongsToType); + EXPECT_EQ(ret, Status::E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeTest008 end."); +} + +/** +* @tc.name: GetTypeIdFromCfgTest002 +* @tc.desc: GetTypeIdFromCfg +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeIdFromCfgTest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeIdFromCfgTest002 begin."); + std::string mimeType = "mimeType*"; + UtdClient utdClient; + utdClient.descriptorCfgs_ = std::vector<TypeDescriptorCfg>(); + + std::string ret = utdClient.GetTypeIdFromCfg(mimeType); + EXPECT_EQ(ret, ""); + LOG_INFO(UDMF_TEST, "GetTypeIdFromCfgTest002 end."); +} + +/** +* @tc.name: GetTypeIdFromCfgTest003 +* @tc.desc: GetTypeIdFromCfg +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeIdFromCfgTest003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeIdFromCfgTest003 begin."); + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + std::string mimeType = "mimeType*"; + UtdClient utdClient; + utdClient.descriptorCfgs_ = std::vector<TypeDescriptorCfg>(); + std::string ret = utdClient.GetTypeIdFromCfg(mimeType); + EXPECT_EQ(ret, ""); + LOG_INFO(UDMF_TEST, "GetTypeIdFromCfgTest003 end."); +} + +/** +* @tc.name: GetUniformDataTypesByMIMETypeTest005 +* @tc.desc: GetUniformDataTypesByMIMEType +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypesByMIMETypeTest005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypesByMIMETypeTest005 begin."); + UtdClient utdClient; + std::string mimeType = "video/x-ms-asf"; + std::vector<std::string> currTypes; + std::string blongsToType = "general.media"; + + auto ret = utdClient.GetUniformDataTypesByMIMEType(mimeType, currTypes, blongsToType); + EXPECT_EQ(ret, Status::E_OK); + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + ret = utdClient.GetUniformDataTypesByMIMEType(mimeType, currTypes, blongsToType); + EXPECT_EQ(ret, Status::E_OK); + LOG_INFO(UDMF_TEST, "GetUniformDataTypesByMIMETypeTest005 end."); +} + +/** +* @tc.name: GetUniformDataTypesByMIMETypeTest006 +* @tc.desc: GetUniformDataTypesByMIMEType +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypesByMIMETypeTest006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypesByMIMETypeTest006 begin."); + std::string mimeType = "mimeType"; + std::vector<std::string> typeIds = std::vector<std::string>(); + std::string belongsTo = ""; + UtdClient utdClient; + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + auto ret = utdClient.GetUniformDataTypesByMIMEType(mimeType, typeIds, belongsTo); + EXPECT_EQ(ret, Status::E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypesByMIMETypeTest006 end."); +} + +/** +* @tc.name: InitTest001 +* @tc.desc: Init +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, InitTest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "InitTest001 begin."); + UtdClient utdClient; + utdClient.descriptorCfgs_ = std::vector<TypeDescriptorCfg>(); + TypeDescriptorCfg cfg; + cfg.typeId = "com.example.utdTest.document"; + cfg.filenameExtensions = { ".my-doc", ".my-document" }; + utdClient.descriptorCfgs_.push_back(cfg); + + auto ret = utdClient.Init(); + EXPECT_TRUE(ret); + LOG_INFO(UDMF_TEST, "InitTest001 end."); +} + +/** +* @tc.name: GetTypeIdsFromCfgtest001 +* @tc.desc: GetTypeIdsFromCfg +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeIdsFromCfgtest001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeIdsFromCfgtest001 begin."); + UtdClient utdClient; + std::string mimeType = "application/my-doc"; + utdClient.descriptorCfgs_ = std::vector<TypeDescriptorCfg>(); + + auto ret = utdClient.GetTypeIdsFromCfg(mimeType); + EXPECT_TRUE(ret.empty()); + LOG_INFO(UDMF_TEST, "GetTypeIdsFromCfgtest001 end."); +} + +/** +* @tc.name: GetTypeIdsFromCfgtest002 +* @tc.desc: GetTypeIdsFromCfg +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeIdsFromCfgtest002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeIdsFromCfgtest002 begin."); + UtdClient utdClient; + std::string mimeType = "application/my-doc"; + utdClient.descriptorCfgs_ = std::vector<TypeDescriptorCfg>(); + TypeDescriptorCfg cfg; + cfg.typeId = "com.example.utdTest.document"; + cfg.mimeTypes = { "application/my-doc", "application/my-document" }; + utdClient.descriptorCfgs_.push_back(cfg); + + auto ret = utdClient.GetTypeIdsFromCfg(mimeType); + EXPECT_FALSE(ret.empty()); + + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + ret = utdClient.GetTypeIdsFromCfg(mimeType); + EXPECT_FALSE(ret.empty()); + LOG_INFO(UDMF_TEST, "GetTypeIdsFromCfgtest002 end."); +} + +/** +* @tc.name: GetTypeIdFromCfg002 +* @tc.desc: GetTypeIdFromCfg +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeIdFromCfg002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeIdFromCfg002 begin."); + std::string mimeType = ""; + UtdClient utdClient; + utdClient.descriptorCfgs_ = std::vector<TypeDescriptorCfg>(); + auto ret = utdClient.GetTypeIdFromCfg(mimeType); + EXPECT_EQ(ret, ""); + mimeType = "mimeType"; + ret = utdClient.GetTypeIdFromCfg(mimeType); + EXPECT_EQ(ret, ""); + mimeType = "mimeType*"; + ret = utdClient.GetTypeIdFromCfg(mimeType); + EXPECT_EQ(ret, ""); + LOG_INFO(UDMF_TEST, "GetTypeIdFromCfg002 end."); +} + +/** +* @tc.name: GetTypeIdFromCfg003 +* @tc.desc: GetTypeIdFromCfg +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeIdFromCfg003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeIdFromCfg003 begin."); + const std::string mimeType = "mimeType"; + UtdClient utdClient; + utdClient.descriptorCfgs_ = std::vector<TypeDescriptorCfg>(); + std::string ret = utdClient.GetTypeIdFromCfg(mimeType); + EXPECT_EQ(ret, ""); + std::this_thread::sleep_for(std::chrono::seconds(SLEEP_INTERVAL)); + std::string filePath = CustomUtdStore::GetInstance().GetCustomUtdPath(false, USERID); + auto now = std::chrono::system_clock::now(); + auto ftime = std::filesystem::file_time_type::clock::now() + (now - std::chrono::system_clock::now()); + std::filesystem::last_write_time(filePath, ftime); + + ret = utdClient.GetTypeIdFromCfg(mimeType); + EXPECT_EQ(ret, ""); + LOG_INFO(UDMF_TEST, "GetTypeIdFromCfg003 end."); +} + /** * @tc.name: IsHapTokenType001 * @tc.desc: Normal testcase of IsHapTokenType @@ -1877,4 +2328,216 @@ HWTEST_F(UtdClientTest, IsHapTokenType001, TestSize.Level1) EXPECT_TRUE(ret); LOG_INFO(UDMF_TEST, "IsHapTokenType001 end."); } + +/** +* @tc.name: GetUniformDataTypeByMIMETypeWithBelongsTo001 +* @tc.desc: Abnormal testcase of GetUniformDataTypeByMIMEType with belongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMETypeWithBelongsTo001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeWithBelongsTo001 begin."); + std::string mimeType = "video/mp2ts"; + std::string utdType; + std::string blongsToType = "invalid_type"; + auto status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, utdType, blongsToType); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeWithBelongsTo001 end."); +} + +/** +* @tc.name: GetUniformDataTypeByMIMETypeWithBelongsTo002 +* @tc.desc: Normal testcase of GetUniformDataTypeByMIMEType with belongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMETypeWithBelongsTo002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeWithBelongsTo002 begin."); + std::string mimeType = "video/mp2ts"; + std::string utdType; + std::string blongsToType = "general.video"; + auto status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType, "general.ts"); + + mimeType = "video/mp2t"; + utdType = ""; + blongsToType = "general.video"; + status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType, "general.ts"); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeWithBelongsTo002 end."); +} + +/** +* @tc.name: GetUniformDataTypeByMIMETypeWithBelongsTo003 +* @tc.desc: Normal testcase of GetUniformDataTypeByMIMEType with higher belongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMETypeWithBelongsTo003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeWithBelongsTo003 begin."); + std::string mimeType = "video/mp2ts"; + std::string utdType; + std::string blongsToType = "general.media"; + auto status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType, "general.ts"); + + mimeType = "video/mp2t"; + utdType = ""; + blongsToType = "general.object"; + status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType, "general.ts"); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeWithBelongsTo003 end."); +} + +/** +* @tc.name: GetUniformDataTypeByMIMETypeWithBelongsTo004 +* @tc.desc: Abnormal testcase of GetUniformDataTypeByMIMEType with belongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMETypeWithBelongsTo004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeWithBelongsTo004 begin."); + std::string mimeType = "video/mp2ts"; + std::string utdType; + std::string blongsToType = "general.source-code"; + auto status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType.compare(0, std::string(FLEXIBLE_TYPE_FLAG).size(), FLEXIBLE_TYPE_FLAG), 0); + + mimeType = "video/mp2t"; + utdType = ""; + blongsToType = "general.source-code"; + status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType.compare(0, std::string(FLEXIBLE_TYPE_FLAG).size(), FLEXIBLE_TYPE_FLAG), 0); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeWithBelongsTo004 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtensionWithBelongsTo001 +* @tc.desc: Abnormal testcase of GetUniformDataTypeByFilenameExtension with belongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtensionWithBelongsTo001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionWithBelongsTo001 begin."); + std::string filenameExtension = ".ts"; + std::string utdType; + std::string blongsToType = "invalid_type"; + auto status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension( + filenameExtension, utdType, blongsToType); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionWithBelongsTo001 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtensionWithBelongsTo002 +* @tc.desc: Normal testcase of GetUniformDataTypeByFilenameExtension with belongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtensionWithBelongsTo002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionWithBelongsTo002 begin."); + std::string filenameExtension = ".ts"; + std::string utdType; + std::string blongsToType = "general.video"; + auto status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension( + filenameExtension, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType, "general.ts"); + + utdType = ""; + blongsToType = "general.source-code"; + status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType, "general.type-script"); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionWithBelongsTo002 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtensionWithBelongsTo003 +* @tc.desc: Normal testcase of GetUniformDataTypeByFilenameExtension with higher belongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtensionWithBelongsTo003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionWithBelongsTo003 begin."); + std::string filenameExtension = ".ts"; + std::string utdType; + std::string blongsToType = "general.media"; + auto status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension( + filenameExtension, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType, "general.ts"); + + utdType = ""; + blongsToType = "general.text"; + status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType, "general.type-script"); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionWithBelongsTo003 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtensionWithBelongsTo004 +* @tc.desc: Abnormal testcase of GetUniformDataTypeByFilenameExtension with belongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtensionWithBelongsTo004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionWithBelongsTo004 begin."); + std::string filenameExtension = ".ts"; + std::string utdType; + std::string blongsToType = "general.java-script"; + auto status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension( + filenameExtension, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType.compare(0, std::string(FLEXIBLE_TYPE_FLAG).size(), FLEXIBLE_TYPE_FLAG), 0); + + utdType = ""; + blongsToType = "general.audio"; + status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension, utdType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(utdType.compare(0, std::string(FLEXIBLE_TYPE_FLAG).size(), FLEXIBLE_TYPE_FLAG), 0); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtensionWithBelongsTo004 end."); +} + +/** +* @tc.name: GetUniformDataTypeByMIMETypeByPrefix003 +* @tc.desc: normal testcase of GetUniformDataTypeByMIMEType by prefix. +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMETypeByPrefix003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeByPrefix003 begin."); + std::string mimeType = "application/vnd.*"; + std::string currType; + auto status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, currType); + EXPECT_EQ(status, E_OK); + std::shared_ptr<TypeDescriptor> descriptor; + status = UtdClient::GetInstance().GetTypeDescriptor(currType, descriptor); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(descriptor->GetTypeId(), "general.ebook"); + + currType = ""; + std::string blongsToType = "general.ebook"; + status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, currType, blongsToType); + EXPECT_EQ(status, E_OK); + status = UtdClient::GetInstance().GetTypeDescriptor(currType, descriptor); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(descriptor->GetTypeId(), "general.ebook"); + + currType = ""; + blongsToType = "general.media"; + status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, currType, blongsToType); + EXPECT_EQ(status, E_OK); + status = UtdClient::GetInstance().GetTypeDescriptor(currType, descriptor); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(descriptor->GetTypeId(), "general.image"); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMETypeByPrefix003 end."); +} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/utd_concurrent_update_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/utd_concurrent_update_test.cpp new file mode 100644 index 00000000..59a479f8 --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/unittest/utd_concurrent_update_test.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. + */ +#define LOG_TAG "UtdConcurrentUpdateTest" +#include <gtest/gtest.h> + +#include <unistd.h> +#include <thread> + +#include "token_setproc.h" +#include "accesstoken_kit.h" +#include "nativetoken_kit.h" + +#include "logger.h" +#include "utd_client.h" +#include "type_descriptor.h" +#include "preset_type_descriptors.h" +#include "utd_graph.h" +#include "custom_utd_store.h" + +using namespace testing::ext; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; +using namespace OHOS; + +namespace OHOS::Test { +constexpr const int32_t USERID = 100; + +class UtdConcurrentUpdateTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + void SetNativeToken(const std::string &processName); +}; + +void UtdConcurrentUpdateTest::SetUpTestCase() +{ +} + +void UtdConcurrentUpdateTest::TearDownTestCase() +{ +} + +void UtdConcurrentUpdateTest::SetUp() +{ + SetNativeToken("foundation"); +} + +void UtdConcurrentUpdateTest::TearDown() +{ +} + +static constexpr const char *K_TEST_JSON_STR = R"({ + "UniformDataTypeDeclarations": [ + { + "TypeId": "com.example.thread.image", + "BelongingToTypes": ["general.image"], + "FilenameExtensions": [".myImage", ".khImage"], + "MIMETypes": ["application/myImage", "application/khImage"], + "Description": "My Image.", + "ReferenceURL": "" + }, + { + "TypeId": "com.example.thread.audio", + "BelongingToTypes": ["general.audio"], + "FilenameExtensions": [".myAudio", ".khAudio"], + "MIMETypes": ["application/myAudio", "application/khAudio"], + "Description": "My audio.", + "ReferenceURL": "" + } + ] +})"; + +void UtdConcurrentUpdateTest::SetNativeToken(const std::string &processName) +{ + auto tokenId = AccessTokenKit::GetNativeTokenId(processName); + SetSelfTokenID(tokenId); +} + +std::string ReplaceThread(const std::string& jsonStr, const std::string& newThreadId) +{ + std::string result = jsonStr; + std::string target = "com.example.thread"; + size_t pos = 0; + while ((pos = result.find(target, pos)) != std::string::npos) { + result.replace(pos, target.length(), newThreadId); + pos += newThreadId.length(); + } + return result; +} + +/** +* @tc.name: MultiThreadUpdate001 +* @tc.desc: MultiThread Update +* @tc.type: FUNC +*/ +HWTEST_F(UtdConcurrentUpdateTest, MultiThreadUpdate001, TestSize.Level1) +{ + const int numThreads = 8; + for (int i = 1; i <= numThreads; ++i) { + UtdClient::GetInstance().UninstallCustomUtds("com.example.thread" + std::to_string(i), USERID); + } + std::vector<TypeDescriptorCfg> prevCustomTypeCfgs = CustomUtdStore::GetInstance().GetCustomUtd(false, USERID); + size_t prevSize = prevCustomTypeCfgs.size(); + + const int trials = 50; + for (int i = 0; i < trials; ++i) { + bool op = (i % 2 == 0); + auto worker = [op](int threadId) { + const std::string bundleName = "com.example.thread" + std::to_string(threadId); + auto jsonStr = ReplaceThread(K_TEST_JSON_STR, bundleName); + if (op) { + UtdClient::GetInstance().InstallCustomUtds(bundleName, jsonStr, USERID); + LOG_INFO(UDMF_CLIENT, "Thread %{public}d Install done", threadId); + } else { + UtdClient::GetInstance().UninstallCustomUtds(bundleName, USERID); + LOG_INFO(UDMF_CLIENT, "Thread %{public}d Uninstall done", threadId); + } + }; + std::vector<std::thread> threads; + for (int j = 1; j <= numThreads; ++j) { + threads.emplace_back(worker, j); + } + for (auto &t : threads) { + t.join(); + } + + auto customTypeCfgs = CustomUtdStore::GetInstance().GetCustomUtd(false, USERID); + if (op) { + EXPECT_EQ(customTypeCfgs.size(), numThreads * 2 + prevSize); + } else { + EXPECT_EQ(customTypeCfgs.size(), prevSize); + } + for (const auto &cfg : customTypeCfgs) { + if (std::find(prevCustomTypeCfgs.begin(), prevCustomTypeCfgs.end(), cfg) == prevCustomTypeCfgs.end()) { + EXPECT_TRUE(cfg.typeId.find("com.example.thread") != std::string::npos); + EXPECT_TRUE(cfg.belongingToTypes.size() > 0); + EXPECT_TRUE(cfg.filenameExtensions.size() > 0); + EXPECT_TRUE(cfg.mimeTypes.size() > 0); + } + } + } + for (int i = 1; i <= numThreads; ++i) { + UtdClient::GetInstance().UninstallCustomUtds("com.example.thread" + std::to_string(i), USERID); + } + auto customTypeCfgs = CustomUtdStore::GetInstance().GetCustomUtd(false, USERID); + EXPECT_EQ(customTypeCfgs.size(), prevSize); +}; +} // namespace OHOS::Test \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/common/napi_data_utils.cpp b/udmf/framework/jskitsimpl/common/napi_data_utils.cpp index 7d7cf89d..602888f9 100644 --- a/udmf/framework/jskitsimpl/common/napi_data_utils.cpp +++ b/udmf/framework/jskitsimpl/common/napi_data_utils.cpp @@ -55,6 +55,19 @@ napi_status NapiDataUtils::SetValue(napi_env env, const int32_t &in, napi_value return napi_create_int32(env, in, &out); } +/* napi_value <-> uint32_t */ +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, uint32_t &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> int32_t"); + return napi_get_value_uint32(env, in, &out); +} + +napi_status NapiDataUtils::SetValue(napi_env env, const uint32_t &in, napi_value &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- int32_t"); + return napi_create_uint32(env, in, &out); +} + /* napi_value <-> int64_t */ napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, int64_t &out) { @@ -278,6 +291,58 @@ napi_status NapiDataUtils::SetValue(napi_env env, const std::map<std::string, in return status; } +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::set<std::string> &out) +{ + napi_value global; + napi_value iterator; + napi_value values_fn; + napi_get_global(env, &global); + napi_get_named_property(env, in, "values", &values_fn); + napi_call_function(env, in, values_fn, 0, nullptr, &iterator); + + napi_value next_fn; + napi_value result_obj; + napi_value done_val; + napi_value value_val; + bool done = false; + + while (!done) { + napi_get_named_property(env, iterator, "next", &next_fn); + napi_call_function(env, iterator, next_fn, 0, nullptr, &result_obj); + + napi_get_named_property(env, result_obj, "done", &done_val); + napi_get_value_bool(env, done_val, &done); + if (done) break; + + napi_get_named_property(env, result_obj, "value", &value_val); + + size_t str_len; + napi_get_value_string_utf8(env, value_val, nullptr, 0, &str_len); + std::string str(str_len, '\0'); + napi_get_value_string_utf8(env, value_val, &str[0], str_len + 1, nullptr); + + out.insert(str); + } + return napi_ok; +} + +napi_status NapiDataUtils::SetValue(napi_env env, const std::set<std::string> &in, napi_value &out) +{ + std::vector<std::string> vec(in.begin(), in.end()); + napi_value jsArray; + NapiDataUtils::SetValue(env, vec, jsArray); + + napi_value global; + napi_get_global(env, &global); + + napi_value setConstructor; + napi_get_named_property(env, global, "Set", &setConstructor); + + napi_value argv[1] = { jsArray }; + napi_new_instance(env, setConstructor, 1, argv, &out); + return napi_ok; +} + /* napi_value <-> UDVariant */ napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, UDVariant &out) { @@ -594,6 +659,50 @@ napi_status NapiDataUtils::SetValue(napi_env env, const ProgressInfo &in, napi_v return napi_ok; } +napi_status NapiDataUtils::SetValue(napi_env env, const DataLoadInfo &in, napi_value &out) +{ + LOG_ERROR(UDMF_KITS_NAPI, "napi_value <- DataLoadInfo"); + napi_create_object(env, &out); + + napi_value jsRecordCount = nullptr; + NAPI_CALL_BASE(env, SetValue(env, in.recordCount, jsRecordCount), napi_invalid_arg); + NAPI_CALL_BASE(env, napi_set_named_property(env, out, "recordCount", jsRecordCount), napi_invalid_arg); + + napi_value jsTypes = nullptr; + NAPI_CALL_BASE(env, SetValue(env, in.types, jsTypes), napi_invalid_arg); + NAPI_CALL_BASE(env, napi_set_named_property(env, out, "types", jsTypes), napi_invalid_arg); + return napi_ok; +} + +napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, DataLoadInfo &out) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value -> DataLoadInfo"); + napi_value jsTypes = nullptr; + NAPI_CALL_BASE(env, GetOptionalNamedProperty(env, in, "types", jsTypes), napi_invalid_arg); + if (jsTypes != nullptr) { + NAPI_CALL_BASE(env, NapiDataUtils::GetValue(env, jsTypes, out.types), napi_invalid_arg); + } + + out.recordCount = 0; + napi_value jsRecordCount = nullptr; + NAPI_CALL_BASE(env, GetOptionalNamedProperty(env, in, "recordCount", jsRecordCount), napi_invalid_arg); + if (jsRecordCount != nullptr) { + double count = 0; + NAPI_CALL_BASE(env, NapiDataUtils::GetValue(env, jsRecordCount, count), napi_invalid_arg); + if (!std::isfinite(count)) { + LOG_WARN(UDMF_KITS_NAPI, "recordCount is not a finite number"); + return napi_ok; + } + count = std::floor(count); + if (count < 0 || count > static_cast<double>(UINT32_MAX)) { + LOG_WARN(UDMF_KITS_NAPI, "recordCount out of range: %{public}f", count); + return napi_ok; + } + out.recordCount = static_cast<uint32_t>(count); + } + return napi_ok; +} + bool NapiDataUtils::IsTypeForNapiValue(napi_env env, napi_value param, napi_valuetype expectType) { napi_valuetype valueType = napi_undefined; @@ -675,5 +784,30 @@ napi_value NapiDataUtils::DefineClass(napi_env env, const std::string &name, } return constructor; } + +napi_status NapiDataUtils::GetOptionalNamedProperty(napi_env env, napi_value &obj, const std::string &key, + napi_value &napiValue) +{ + bool hasKey = false; + napi_status status = napi_has_named_property(env, obj, key.c_str(), &hasKey); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_has_named_property failed, name = %{public}s", key.c_str()); + return status; + } + if (!hasKey) { + napiValue = nullptr; + return napi_ok; + } + status = napi_get_named_property(env, obj, key.c_str(), &napiValue); + if (status != napi_ok || napiValue == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_get_named_property failed, name = %{public}s", key.c_str()); + return napi_generic_failure; + } + if (IsNull(env, napiValue)) { + napiValue = nullptr; + return napi_ok; + } + return napi_ok; +} } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/jskitsimpl/common/napi_error_utils.cpp b/udmf/framework/jskitsimpl/common/napi_error_utils.cpp index 8567babe..e17b997e 100644 --- a/udmf/framework/jskitsimpl/common/napi_error_utils.cpp +++ b/udmf/framework/jskitsimpl/common/napi_error_utils.cpp @@ -22,7 +22,8 @@ using NapiErrorCode = OHOS::UDMF::NapiErrorCode; static constexpr NapiErrorCode JS_ERROR_CODE_MSGS[] = { { Status::E_NO_PERMISSION, 201, "Permission denied!" }, { Status::E_INVALID_PARAMETERS, 401, "Parameter error." }, - { Status::E_SETTINGS_EXISTED, 20400001, "Settings already exist." }, + { Status::E_SETTINGS_EXISTED, 20400001, + "Settings already exist. To reconfigure, remove the existing sharing options." }, { Status::E_NO_SYSTEM_PERMISSION, 202, "Permission denied, application which is not a system application uses system API." }, }; diff --git a/udmf/framework/jskitsimpl/common/napi_queue.cpp b/udmf/framework/jskitsimpl/common/napi_queue.cpp index 898ba6d8..0263e923 100644 --- a/udmf/framework/jskitsimpl/common/napi_queue.cpp +++ b/udmf/framework/jskitsimpl/common/napi_queue.cpp @@ -66,8 +66,11 @@ void ContextBase::GetCbInfo(napi_env envi, napi_callback_info info, NapiCbInfoPa napi_value NapiQueue::AsyncWork(napi_env env, std::shared_ptr<ContextBase> contextBase, const std::string &name, NapiAsyncExecute execute, NapiAsyncComplete complete) { - LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork name = %{public}s", name.c_str()); - AsyncContext *aCtx = new AsyncContext; + AsyncContext *aCtx = new (std::nothrow) AsyncContext; + if (aCtx == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "aCtx is nullptr"); + return nullptr; + } aCtx->ctxt = std::move(contextBase); aCtx->execute = std::move(execute); aCtx->complete = std::move(complete); diff --git a/udmf/framework/jskitsimpl/data/data_load_params_napi.cpp b/udmf/framework/jskitsimpl/data/data_load_params_napi.cpp new file mode 100644 index 00000000..f3d0c157 --- /dev/null +++ b/udmf/framework/jskitsimpl/data/data_load_params_napi.cpp @@ -0,0 +1,116 @@ +/* + * 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. + */ +#define LOG_TAG "DataLoadParamsNapi" +#include "data_load_params_napi.h" + +#include "logger.h" +#include "napi_data_utils.h" +#include "unified_data_napi.h" +#include "udmf_client.h" +#include "udmf_utils.h" + +namespace OHOS { +namespace UDMF { +ConcurrentMap<std::string, napi_threadsafe_function> DataLoadParamsNapi::tsfns_; + +bool DataLoadParamsNapi::Convert2NativeValue(napi_env env, napi_value in, DataLoadParams &dataLoadParams) +{ + napi_value jsDataLoadInfo = nullptr; + NAPI_CALL_BASE(env, napi_get_named_property(env, in, "dataLoadInfo", &jsDataLoadInfo), false); + NAPI_CALL_BASE(env, NapiDataUtils::GetValue(env, jsDataLoadInfo, dataLoadParams.dataLoadInfo), false); + napi_value jsLoadHandler = nullptr; + NAPI_CALL_BASE(env, napi_get_named_property(env, in, "loadHandler", &jsLoadHandler), false); + dataLoadParams.dataLoadInfo.sequenceKey = UTILS::GenerateId(); + tsfns_.Compute(dataLoadParams.dataLoadInfo.sequenceKey, [&](const std::string &k, napi_threadsafe_function &tsfn) { + if (tsfn != nullptr) { + LOG_WARN(UDMF_KITS_NAPI, "Listener has existed!"); + napi_release_threadsafe_function(tsfn, napi_tsfn_release); + tsfn = nullptr; + } + napi_value workName; + napi_create_string_utf8(env, "threadsafe_function", NAPI_AUTO_LENGTH, &workName); + auto status = napi_create_threadsafe_function(env, jsLoadHandler, nullptr, workName, 0, 1, nullptr, + nullptr, nullptr, CallDataLoadHandler, &tsfn); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_create_threadsafe_function failed, status=%{public}d", status); + return false; + } + return true; + }); + dataLoadParams.loadHandler = [](const std::string &udKey, const DataLoadInfo &dataLoadInfo) { + LOG_INFO(UDMF_KITS_NAPI, "Load handler Start."); + auto seqKey = UTILS::GetSequenceKey(udKey); + if (seqKey.empty()) { + LOG_ERROR(UDMF_KITS_NAPI, "Error udKey:%{public}s", udKey.c_str()); + return; + } + bool tsfnExist = tsfns_.ComputeIfPresent(seqKey, [&](const std::string &key, napi_threadsafe_function &tsfn) { + DataLoadArgs *infoArgs = new (std::nothrow) DataLoadArgs; + if (infoArgs == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "No space for dataLoadArgs, udKey=%{public}s", udKey.c_str()); + return false; + } + infoArgs->udKey = udKey; + infoArgs->dataLoadInfo = dataLoadInfo; + auto status = napi_call_threadsafe_function(tsfn, infoArgs, napi_tsfn_blocking); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "call func failed,status=%{public}d,udKey=%{public}s", status, udKey.c_str()); + } + napi_release_threadsafe_function(tsfn, napi_tsfn_release); + return false; + }); + if (!tsfnExist) { LOG_ERROR(UDMF_KITS_NAPI, "Tsfn not exist, udKey=%{public}s", udKey.c_str()); } + }; + return true; +} + +void DataLoadParamsNapi::CallDataLoadHandler(napi_env env, napi_value callback, void *context, void *data) +{ + DataLoadArgs* infoArgs = static_cast<DataLoadArgs*>(data); + std::string udKey = infoArgs->udKey; + napi_value param; + auto status = NapiDataUtils::SetValue(env, infoArgs->dataLoadInfo, param); + delete infoArgs; + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "SetValue dataLoadInfo failed, status=%{public}d", status); + return; + } + napi_value result = nullptr; + status = napi_call_function(env, nullptr, callback, 1, &param, &result); + if (status != napi_ok || result == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_call_function failed, status=%{public}d", status); + return; + } + LOG_INFO(UDMF_KITS_NAPI, "Call napi_call_function end."); + napi_valuetype type = napi_undefined; + napi_typeof(env, result, &type); + if (type == napi_null) { + LOG_ERROR(UDMF_KITS_NAPI, "DataLoad has no data"); + return; + } + UnifiedDataNapi *unifiedDataNapi = nullptr; + status = napi_unwrap(env, result, reinterpret_cast<void **>(&unifiedDataNapi)); + if (status != napi_ok || unifiedDataNapi == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_unwrap data failed, status=%{public}d", status); + return; + } + + auto ret = UdmfClient::GetInstance().PushDelayData(udKey, *unifiedDataNapi->value_); + if (ret != E_OK) { + LOG_ERROR(UDMF_KITS_NAPI, "SetData failed, status=%{public}d", ret); + } +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/get_data_params_napi.cpp b/udmf/framework/jskitsimpl/data/get_data_params_napi.cpp index 43794a97..288442a8 100644 --- a/udmf/framework/jskitsimpl/data/get_data_params_napi.cpp +++ b/udmf/framework/jskitsimpl/data/get_data_params_napi.cpp @@ -65,6 +65,13 @@ bool GetDataParamsNapi::Convert2NativeValue(napi_env env, napi_value in, getDataParams.fileConflictOptions = static_cast<FileConflictOptions>(fileConflictOptions); } + bool hasAcceptableInfo = false; + NAPI_CALL_BASE(env, napi_has_named_property(env, in, "acceptableInfo", &hasAcceptableInfo), false); + if (hasAcceptableInfo) { + napi_value jsDataLoadInfo = nullptr; + NAPI_CALL_BASE(env, napi_get_named_property(env, in, "acceptableInfo", &jsDataLoadInfo), false); + NAPI_CALL_BASE(env, NapiDataUtils::GetValue(env, jsDataLoadInfo, getDataParams.acceptableInfo), false); + } return true; } diff --git a/udmf/framework/jskitsimpl/data/unified_data_channel_napi.cpp b/udmf/framework/jskitsimpl/data/unified_data_channel_napi.cpp index d01cfbae..b3e6bef1 100644 --- a/udmf/framework/jskitsimpl/data/unified_data_channel_napi.cpp +++ b/udmf/framework/jskitsimpl/data/unified_data_channel_napi.cpp @@ -32,12 +32,14 @@ napi_value UnifiedDataChannelNapi::UnifiedDataChannelInit(napi_env env, napi_val DECLARE_NAPI_FUNCTION("updateData", UpdateData), DECLARE_NAPI_FUNCTION("queryData", QueryData), DECLARE_NAPI_FUNCTION("deleteData", DeleteData), + DECLARE_NAPI_FUNCTION("convertRecordsToEntries", ConvertRecordsToEntries), DECLARE_NAPI_GETTER("ShareOptions", CreateShareOptions), DECLARE_NAPI_FUNCTION("setAppShareOptions", SetAppShareOptions), DECLARE_NAPI_FUNCTION("removeAppShareOptions", RemoveAppShareOptions), DECLARE_NAPI_GETTER("FileConflictOptions", CreateFileConflictOptions), DECLARE_NAPI_GETTER("ProgressIndicator", CreateProgressIndicator), DECLARE_NAPI_GETTER("ListenerStatus", CreateListenerStatus), + DECLARE_NAPI_GETTER("Visibility", CreateVisibility), }; NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); @@ -56,10 +58,31 @@ napi_value UnifiedDataChannelNapi::CreateIntention(napi_env env) UD_INTENTION_MAP.at(UD_INTENTION_DATA_HUB)); SetNamedProperty(env, intention, JS_UD_INTENTION_NAME_MAP.at(UD_INTENTION_DRAG), UD_SYSTEM_INTENTION_MAP.at(UD_INTENTION_DRAG)); + SetNamedProperty(env, intention, JS_UD_INTENTION_NAME_MAP.at(UD_INTENTION_PICKER), + UD_INTENTION_MAP.at(UD_INTENTION_PICKER)); + SetNamedProperty(env, intention, JS_UD_INTENTION_NAME_MAP.at(UD_INTENTION_SYSTEM_SHARE), + UD_INTENTION_MAP.at(UD_INTENTION_SYSTEM_SHARE)); + SetNamedProperty(env, intention, JS_UD_INTENTION_NAME_MAP.at(UD_INTENTION_MENU), + UD_INTENTION_MAP.at(UD_INTENTION_MENU)); napi_object_freeze(env, intention); return intention; } +napi_value UnifiedDataChannelNapi::CreateVisibility(napi_env env, napi_callback_info info) +{ + napi_value jsVisibility = nullptr; + napi_create_object(env, &jsVisibility); + + napi_value jsALL; + NapiDataUtils::SetValue(env, static_cast<int32_t>(Visibility::VISIBILITY_ALL), jsALL); + NAPI_CALL(env, napi_set_named_property(env, jsVisibility, "ALL", jsALL)); + + napi_value jsOwnProcess; + NapiDataUtils::SetValue(env, static_cast<int32_t>(Visibility::VISIBILITY_OWN_PROCESS), jsOwnProcess); + NAPI_CALL(env, napi_set_named_property(env, jsVisibility, "OWN_PROCESS", jsOwnProcess)); + return jsVisibility; +} + napi_status UnifiedDataChannelNapi::SetNamedProperty(napi_env env, napi_value &obj, const std::string &name, const std::string &value) { @@ -78,29 +101,35 @@ napi_value UnifiedDataChannelNapi::InsertData(napi_env env, napi_callback_info i std::string key; Intention intention; std::shared_ptr<UnifiedData> unifiedData; + Visibility visibility; }; std::string intention; UnifiedDataNapi *unifiedDataNapi = nullptr; + int32_t visibility = static_cast<int32_t>(Visibility::VISIBILITY_ALL); auto ctxt = std::make_shared<InsertContext>(); - auto input = [env, ctxt, &intention, &unifiedDataNapi](size_t argc, napi_value *argv) { + auto input = [env, ctxt, &intention, &unifiedDataNapi, &visibility](size_t argc, napi_value *argv) { // require 2 arguments <options, unifiedData> ASSERT_BUSINESS_ERR(ctxt, argc >= 2, E_INVALID_PARAMETERS, "Parameter error: Mandatory parameters are left unspecified"); ctxt->status = GetNamedProperty(env, argv[0], "intention", intention); - ASSERT_BUSINESS_ERR(ctxt, UnifiedDataUtils::GetIntentionByString(intention) != UD_INTENTION_DRAG, - E_INVALID_PARAMETERS, "Parameter error: The intention parameter is invalid"); - ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok && UnifiedDataUtils::IsPersist(intention), + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok && + (UnifiedDataUtils::IsPersist(intention)), E_INVALID_PARAMETERS, "Parameter error: parameter options intention type must correspond to Intention"); ctxt->status = napi_unwrap(env, argv[1], reinterpret_cast<void **>(&unifiedDataNapi)); ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS, "Parameter error: parameter data type must be UnifiedData"); + ctxt->status = GetOptionalProperty(env, argv[0], "visibility", visibility); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok && + (UnifiedDataUtils::IsPersist(visibility)), + E_INVALID_PARAMETERS, "Parameter error: parameter options visibility type must correspond to Visibility"); }; ctxt->GetCbInfo(env, info, input); ASSERT_NULL(!ctxt->isThrowError, "Insert Exit"); ctxt->unifiedData = unifiedDataNapi->value_; ctxt->intention = UnifiedDataUtils::GetIntentionByString(intention); + ctxt->visibility = static_cast<Visibility>(visibility); auto execute = [ctxt]() { - CustomOption option = { .intention = ctxt->intention }; + CustomOption option = { .intention = ctxt->intention, .visibility = ctxt->visibility }; auto status = UdmfClient::GetInstance().SetData(option, *(ctxt->unifiedData), ctxt->key); ASSERT_WITH_ERRCODE(ctxt, status == E_OK, status, "InsertData failed!"); }; @@ -129,7 +158,8 @@ napi_value UnifiedDataChannelNapi::UpdateData(napi_env env, napi_callback_info i ctxt->status = GetNamedProperty(env, argv[0], "key", ctxt->key); UnifiedKey key(ctxt->key); ASSERT_BUSINESS_ERR(ctxt, - ctxt->status == napi_ok && key.IsValid() && UnifiedDataUtils::IsPersist(key.intention), + ctxt->status == napi_ok && key.IsValid() && + (key.intention == UD_INTENTION_MAP.at(Intention::UD_INTENTION_DATA_HUB)), E_INVALID_PARAMETERS, "Parameter error: parameter options intention type must correspond to Intention"); ctxt->status = napi_unwrap(env, argv[1], reinterpret_cast<void **>(&unifiedDataNapi)); ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS, @@ -168,15 +198,17 @@ napi_value UnifiedDataChannelNapi::QueryData(napi_env env, napi_callback_info in auto options = argv[0]; keyStatus = GetNamedProperty(env, options, "key", ctxt->key); intentionStatus = GetNamedProperty(env, options, "intention", intention); - ASSERT_BUSINESS_ERR(ctxt, UnifiedDataUtils::GetIntentionByString(intention) != UD_INTENTION_DRAG, - E_INVALID_PARAMETERS, "Parameter error: The intention parameter is invalid"); + UnifiedKey key(ctxt->key); ASSERT_BUSINESS_ERR(ctxt, (keyStatus == napi_ok || intentionStatus == napi_ok) && - UnifiedDataUtils::IsValidOptions(ctxt->key, intention), + IsValidOptionInfoNonDrag(key, intention), E_INVALID_PARAMETERS, "Parameter error: parameter options intention type must correspond to Intention"); }; ctxt->GetCbInfo(env, info, input); ASSERT_NULL(!ctxt->isThrowError, "Query Exit"); - ctxt->intention = UnifiedDataUtils::GetIntentionByString(intention); + Intention tempIntention = UnifiedDataUtils::GetIntentionByString(intention); + if (tempIntention != UD_INTENTION_BUTT) { + ctxt->intention = tempIntention; + } auto execute = [env, ctxt]() { QueryOption option = { .key = ctxt->key, @@ -212,17 +244,18 @@ napi_value UnifiedDataChannelNapi::DeleteData(napi_env env, napi_callback_info i napi_value options = argv[0]; keyStatus = GetNamedProperty(env, options, "key", ctxt->key); intentionStatus = GetNamedProperty(env, options, "intention", intention); - ASSERT_BUSINESS_ERR(ctxt, intention.empty() || - UnifiedDataUtils::GetIntentionByString(intention) == UD_INTENTION_DATA_HUB, - E_INVALID_PARAMETERS, "Parameter error: The intention parameter is invalid"); + UnifiedKey key(ctxt->key); ASSERT_BUSINESS_ERR(ctxt, (keyStatus == napi_ok || intentionStatus == napi_ok) && - UnifiedDataUtils::IsValidOptions(ctxt->key, intention), + (IsValidOptionInfoNonDrag(key, intention)), E_INVALID_PARAMETERS, "Parameter error: parameter options intention type must correspond to Intention"); }; ctxt->GetCbInfo(env, info, input); ASSERT_NULL(!ctxt->isThrowError, "Delete Exit"); - ctxt->intention = UnifiedDataUtils::GetIntentionByString(intention); + Intention tempIntention = UnifiedDataUtils::GetIntentionByString(intention); + if (tempIntention != UD_INTENTION_BUTT) { + ctxt->intention = tempIntention; + } auto execute = [env, ctxt]() { QueryOption option = { .key = ctxt->key, @@ -239,6 +272,28 @@ napi_value UnifiedDataChannelNapi::DeleteData(napi_env env, napi_callback_info i return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); } +napi_value UnifiedDataChannelNapi::ConvertRecordsToEntries(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ConvertRecordsToEntries is called!"); + struct ConvertContext : public ContextBase { + std::shared_ptr<UnifiedData> unifiedData; + }; + UnifiedDataNapi *unifiedDataNapi = nullptr; + auto ctxt = std::make_shared<ConvertContext>(); + auto input = [env, ctxt, &unifiedDataNapi](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc == 1, + E_INVALID_PARAMETERS, "Parameter error: Mandatory parameters are left unspecified"); + ctxt->status = napi_unwrap(env, argv[0], reinterpret_cast<void **>(&unifiedDataNapi)); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS, + "Parameter error: parameter data type must be UnifiedData"); + }; + ctxt->GetCbInfo(env, info, input); + ASSERT_NULL(!ctxt->isThrowError, "ConvertRecordsToEntries Exit"); + ctxt->unifiedData = unifiedDataNapi->value_; + ctxt->unifiedData->ConvertRecordsToEntries(); + return nullptr; +} + napi_status UnifiedDataChannelNapi::GetNamedProperty(napi_env env, napi_value &obj, const std::string &key, std::string &value) { @@ -271,6 +326,36 @@ napi_status UnifiedDataChannelNapi::GetNamedProperty(napi_env env, napi_value &o return status; } +napi_status UnifiedDataChannelNapi::GetOptionalProperty(napi_env env, napi_value &obj, const std::string &key, + int32_t &value) +{ + bool hasKey = false; + napi_status status = napi_has_named_property(env, obj, key.c_str(), &hasKey); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_has_named_property failed, name = %{public}s", key.c_str()); + return napi_generic_failure; + } + if (!hasKey) { + return napi_ok; + } + napi_value napiValue = nullptr; + status = napi_get_named_property(env, obj, key.c_str(), &napiValue); + if (status != napi_ok || napiValue == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_get_named_property failed, name = %{public}s", key.c_str()); + return napi_generic_failure; + } + if (NapiDataUtils::IsNull(env, napiValue)) { + LOG_ERROR(UDMF_KITS_NAPI, "The property value is null, name = %{public}s", key.c_str()); + return napi_generic_failure; + } + status = NapiDataUtils::GetValue(env, napiValue, value); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "NapiDataUtils::GetValue failed, name = %{public}s", key.c_str()); + return status; + } + return status; +} + napi_value UnifiedDataChannelNapi::CreateShareOptions(napi_env env, napi_callback_info info) { napi_value jsShareOptions = nullptr; @@ -313,7 +398,8 @@ napi_value UnifiedDataChannelNapi::SetAppShareOptions(napi_env env, napi_callbac E_INVALID_PARAMETERS, "Parameter error: The shareOptions parameter is invalid!"); std::transform(intention.begin(), intention.end(), intention.begin(), ::tolower); // js : Drag --> drag status = UdmfClient::GetInstance().SetAppShareOption(intention, static_cast<ShareOptions>(shareOptionValue)); - ASSERT_BUSINESS_ERR_VOID(ctxt, !(status == E_SETTINGS_EXISTED), E_SETTINGS_EXISTED, "Settings already exist!"); + ASSERT_BUSINESS_ERR_VOID(ctxt, !(status == E_SETTINGS_EXISTED), E_SETTINGS_EXISTED, + "Settings already exist. To reconfigure, remove the existing sharing options."); ASSERT_BUSINESS_ERR_VOID(ctxt, status != E_NO_PERMISSION, E_NO_PERMISSION, "Permission denied!"); ASSERT_ERR(ctxt->env, status == E_OK, status, "invalid arguments!"); return nullptr; @@ -429,5 +515,13 @@ napi_value UnifiedDataChannelNapi::CreateListenerStatus(napi_env env, napi_callb NAPI_CALL(env, napi_set_named_property(env, jsListenerStatus, "COPY_FILE_FAILED", jsCopyFail)); return jsListenerStatus; } + +bool UnifiedDataChannelNapi::IsValidOptionInfoNonDrag(UnifiedKey &key, const std::string &intention) +{ + if (UnifiedDataUtils::IsValidOptions(key, intention)) { + return !key.key.empty() || intention == UD_INTENTION_MAP.at(Intention::UD_INTENTION_DATA_HUB); + } + return false; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/data/unified_data_napi.cpp b/udmf/framework/jskitsimpl/data/unified_data_napi.cpp index 38714dbe..214036bc 100644 --- a/udmf/framework/jskitsimpl/data/unified_data_napi.cpp +++ b/udmf/framework/jskitsimpl/data/unified_data_napi.cpp @@ -88,10 +88,89 @@ napi_value UnifiedDataNapi::New(napi_env env, napi_callback_info info) if (uRecord) { uData->value_->AddRecord(uRecord->value_); } + auto status = napi_coerce_to_native_binding_object( + env, ctxt->self, DetachUnifiedData, AttachUnifiedData, uData, nullptr); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_coerce_to_native_binding_object failed!"); + } ASSERT_CALL(env, napi_wrap(env, ctxt->self, uData, Destructor, nullptr, nullptr), uData); return ctxt->self; } +napi_value UnifiedDataNapi::AttachUnifiedData(napi_env env, void *value, void *) +{ + if (value == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "Invalid value."); + return nullptr; + } + auto *data = static_cast<UnifiedDataNapi *>(value); + napi_value jsData = nullptr; + auto status = napi_create_object(env, &jsData); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_create_object failed!"); + delete data; + return nullptr; + } + napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("addRecord", AddRecord), + DECLARE_NAPI_FUNCTION("getRecords", GetRecords), + DECLARE_NAPI_FUNCTION("hasType", HasType), + DECLARE_NAPI_FUNCTION("getTypes", GetTypes), + DECLARE_NAPI_GETTER_SETTER("properties", GetProperties, SetProperties), + }; + status = napi_define_properties(env, jsData, sizeof(properties) / sizeof(properties[0]), properties); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_define_properties failed!"); + delete data; + return nullptr; + } + status = napi_coerce_to_native_binding_object( + env, jsData, DetachUnifiedData, AttachUnifiedData, value, nullptr); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_coerce_to_native_binding_object failed!"); + delete data; + return nullptr; + } + status = napi_wrap(env, jsData, value, Destructor, nullptr, nullptr); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_wrap failed!"); + delete data; + return nullptr; + } + return jsData; +} + +void* UnifiedDataNapi::DetachUnifiedData(napi_env env, void *value, void *) +{ + if (value == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "Invalid value."); + return nullptr; + } + auto *origin = static_cast<UnifiedDataNapi *>(value); + auto result = new (std::nothrow) UnifiedDataNapi(); + if (result == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "Memory allocation failed."); + return nullptr; + } + result->value_ = origin->value_; + + int argc = 0; + napi_value argv[0] = {}; + UnifiedDataPropertiesNapi* propertiesNapi = nullptr; + result->propertyRef_ = NewWithRef(env, argc, argv, reinterpret_cast<void **>(&propertiesNapi), + UnifiedDataPropertiesNapi::Constructor(env)); + if (propertiesNapi == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "new UnifiedDataPropertiesNapi failed!"); + if (result->propertyRef_ != nullptr) { + napi_delete_reference(env, result->propertyRef_); + } + delete result; + return nullptr; + } + propertiesNapi->value_ = origin->value_->GetProperties(); + return result; +} + void UnifiedDataNapi::Destructor(napi_env env, void *data, void *hint) { LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi finalize."); @@ -107,10 +186,28 @@ napi_status UnifiedDataNapi::NewInstance(napi_env env, std::shared_ptr<UnifiedDa { LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi"); ASSERT_CALL_STATUS(env, napi_new_instance(env, Constructor(env), 0, nullptr, &out)); - auto *unifiedData = new (std::nothrow) UnifiedDataNapi(); - ASSERT_ERR_STATUS(env, unifiedData != nullptr, Status::E_ERROR, "no memory for unified data!"); + + UnifiedDataNapi* unifiedData = nullptr; + napi_status status = napi_unwrap(env, out, reinterpret_cast<void **>(&unifiedData)); + if (status != napi_ok || unifiedData == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_unwrap unifiedData failed, status=%{public}d", status); + return status; + } unifiedData->value_ = in; - ASSERT_CALL_DELETE_STATUS(env, napi_wrap(env, out, unifiedData, Destructor, nullptr, nullptr), unifiedData); + + napi_value value; + status = napi_get_reference_value(env, unifiedData->propertyRef_, &value); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_get_reference_value propertyRef failed, status=%{public}d", status); + return status; + } + UnifiedDataPropertiesNapi* propertiesNapi = nullptr; + status = napi_unwrap(env, value, reinterpret_cast<void **>(&propertiesNapi)); + if (status != napi_ok || propertiesNapi == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "napi_unwrap propertiesNapi failed, status=%{public}d", status); + return status; + } + propertiesNapi->value_ = in->GetProperties(); return napi_ok; } diff --git a/udmf/framework/jskitsimpl/intelligence/aip_napi_error.cpp b/udmf/framework/jskitsimpl/intelligence/aip_napi_error.cpp index 9cdf24ba..faa611da 100644 --- a/udmf/framework/jskitsimpl/intelligence/aip_napi_error.cpp +++ b/udmf/framework/jskitsimpl/intelligence/aip_napi_error.cpp @@ -34,12 +34,13 @@ constexpr ErrCodeMapping NATIVE_ERR_CODE2TS_ERR_CODE[] = { { NATIVE_DATABASE_ALREADY_CLOSED, DATABASE_ALREADY_CLOSED }, { NATIVE_DATABASE_IS_BUSY, DATABASE_IS_BUSY }, { NATIVE_DATABASE_WAL_FILE_EXCEEDS_LIMIT, DATABASE_WAL_FILE_EXCEEDS_LIMIT }, - { NATIVE_DATABASE_GENERIC_ERROD, DATABASE_GENERIC_ERROD }, + { NATIVE_DATABASE_GENERIC_ERROR, DATABASE_GENERIC_ERROR }, { NATIVE_DATABASE_CORRUPTED, DATABASE_CORRUPTED }, { NATIVE_DATABASE_PERMISSION_DENIED, DATABASE_PERMISSION_DENIED }, { NATIVE_DATABASE_FILE_IS_LOCKED, DATABASE_FILE_IS_LOCKED }, { NATIVE_DATABASE_OUT_OF_MEMORY, DATABASE_OUT_OF_MEMORY }, { NATIVE_DATABASE_IO_ERROR, DATABASE_IO_ERROR }, + { NATIVE_E_RECALL_FAILURE, RETRIEVAL_E_RECALL_FAILURE }, { NATIVE_E_RERANK_FAILURE, RETRIEVAL_E_RERANK_FAILURE }, { NATIVE_E_INVALID_NUMBER, RETRIEVAL_E_INVALID_NUMBER }, @@ -50,7 +51,32 @@ constexpr ErrCodeMapping NATIVE_ERR_CODE2TS_ERR_CODE[] = { { NATIVE_E_INVALID_RECALL_FIELD, RETRIEVAL_E_INVALID_RECALL_FIELD }, { NATIVE_E_HIGH_VECTOR_SIMILARITY_THRESHOLD, RETRIEVAL_E_HIGH_VECTOR_SIMILARITY_THRESHOLD }, { NATIVE_E_RERANK_METHOD_MISMATCH, RETRIEVAL_E_RERANK_METHOD_MISMATCH }, - { NATIVE_E_EMPTY_PARAMETER, RETRIEVAL_E_EMPTY_PARAMETER } + { NATIVE_E_EMPTY_PARAMETER, RETRIEVAL_E_EMPTY_PARAMETER }, + + { NATIVE_SUMMARY_E_INVALID_PARAMETERS, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_SUMMARY_E_INVALID_RESULT, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_SUMMARY_E_INVALID_OUTPUT, RAG_E_RAG_COMMON_ERROR }, + + { NATIVE_RAG_E_CONFIG_ERROR, PARAM_EXCEPTION }, + { NATIVE_RAG_E_INSTANCE_EXIST, RAG_E_RAG_ALREADY_EXISTS }, + { NATIVE_RAG_E_INVALID_INPUT, PARAM_EXCEPTION }, + { NATIVE_RAG_E_QUERY_LENGTH_EXCEED, PARAM_EXCEPTION }, + { NATIVE_RAG_E_STREAM_BUSY, RAG_E_RAG_BUSY }, + { NATIVE_RAG_E_INSTANCE_NOT_EXIST, RAG_E_RAG_ALREADY_CLOSED }, + { NATIVE_RAG_E_PROMPT_ERROR, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_RAG_E_LLM_ERROR, RAG_E_LLM_LOAD_FAILED }, + { NATIVE_RAG_E_LLM_OCCUPIED, RAG_E_LLM_BUSY }, + { NATIVE_RAG_E_LLM_TIMEOUT, RAG_E_LLM_TIMEOUT }, + { NATIVE_RAG_E_LLM_OUTPUT_INVALID, RAG_E_LLM_OUTPUT_INVALID }, + { NATIVE_RAG_E_RETRIEVER_TIMEOUT, RAG_E_RAG_TIMEOUT }, + + { NATIVE_LLM_E_PARSER_JSON_PARSE, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_LLM_E_PARSER_JSON_MEMBER, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_LLM_E_REQUEST_MALLOC, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_PROMPT_E_PLACEHOLDER_JSON_PARSE, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_PROMPT_E_CHAT_TEMP_JSON_TYPE, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_PROMPT_E_CHAT_TEMP_EMPTY_MSG, RAG_E_RAG_COMMON_ERROR }, + { NATIVE_PROMPT_E_CHAT_TEMP_UPDATE_SYS, RAG_E_RAG_COMMON_ERROR }, }; struct ErrMessage { @@ -66,7 +92,7 @@ constexpr ErrMessage ERROR_MESSAGES [] = { { DATABASE_ALREADY_CLOSED, "Already closed." }, { DATABASE_IS_BUSY, "The database is busy." }, { DATABASE_OUT_OF_MEMORY, "The database is out of memory." }, - { DATABASE_GENERIC_ERROD, "SQLite: Generic error." }, + { DATABASE_GENERIC_ERROR, "SQLite: Generic error." }, { DATABASE_PERMISSION_DENIED, "SQLite: Access permission denied." }, { DATABASE_FILE_IS_LOCKED, "SQLite: The database file is locked." }, { DATABASE_IO_ERROR, "SQLite: Some kind of disk I/O error occurred." }, @@ -86,7 +112,17 @@ constexpr ErrMessage ERROR_MESSAGES [] = { "higher than the tiered threshold in VectorRerankParameter." }, { RETRIEVAL_E_RERANK_METHOD_MISMATCH, "Retrieval: RerankMethod parameters do not match the channel type." }, { RETRIEVAL_E_EMPTY_PARAMETER, - "Retrieval: There exists a parameter value that should not be empty but is actually empty." } + "Retrieval: There exists a parameter value that should not be empty but is actually empty." }, + { RAG_E_RAG_COMMON_ERROR, "Inner error." }, + { RAG_E_LLM_TIMEOUT, "A timeout occurred when calling the LLM." }, + { RAG_E_LLM_LOAD_FAILED, "A loading failure occurred when calling the LLM." }, + { RAG_E_LLM_BUSY, "The LLM chat is busy." }, + { RAG_E_LLM_OUTPUT_INVALID, "The output of LLM chat is invalid." }, + { RAG_E_RAG_ALREADY_EXISTS, "The RAG session is already exists." }, + { RAG_E_RAG_BUSY, "The RAG session is busy." }, + { RAG_E_RAG_ALREADY_CLOSED, "Already closed." }, + { RAG_E_RAG_USER_CANCEL, "User has canceled the stream run." }, + { RAG_E_RAG_TIMEOUT, "A timeout occurred in the session." }, }; int32_t ConvertErrCodeNative2Ts(int32_t nativeErrCode) @@ -103,7 +139,7 @@ int32_t ConvertErrCodeNative2Ts(int32_t nativeErrCode) right = mid - 1; } } - return DATABASE_GENERIC_ERROD; + return DATABASE_GENERIC_ERROR; } diff --git a/udmf/framework/jskitsimpl/intelligence/aip_napi_utils.cpp b/udmf/framework/jskitsimpl/intelligence/aip_napi_utils.cpp index e46bbbc6..ef1ec834 100644 --- a/udmf/framework/jskitsimpl/intelligence/aip_napi_utils.cpp +++ b/udmf/framework/jskitsimpl/intelligence/aip_napi_utils.cpp @@ -15,12 +15,15 @@ #include "aip_napi_utils.h" +#include <charconv> #include <dlfcn.h> +#include <memory> #include "js_ability.h" #include "aip_log.h" #include "hilog/log_c.h" #include "js_native_api_types.h" +#include "rag_chatllm_impl.h" #undef LOG_TAG #define LOG_TAG "AipNapiUtils" @@ -706,7 +709,7 @@ napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, Reca if (isFiltersPresent) { napi_value filtersNapi; napi_get_named_property(env, in, "filters", &filtersNapi); - napi_status status = AipNapiUtils::Convert2Value(env, filtersNapi, out.filters); + status = AipNapiUtils::Convert2Value(env, filtersNapi, out.filters); LOG_ERROR_RETURN(status == napi_ok, "Failed to convert the field filter.", napi_invalid_arg); } return napi_ok; @@ -862,6 +865,47 @@ napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, Inve return napi_ok; } +napi_status AipNapiUtils::Convert2Value(napi_env env, napi_value in, napi_ref &out) +{ + napi_status status = napi_create_reference(env, in, 1, &out); + if (status != napi_ok) { + AIP_HILOGE("Failed to convert the chat2."); + } + return status; +} + +napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, std::shared_ptr<IChatLLM> &out) +{ + napi_value streamChatNapi; + napi_ref streamChatRef = nullptr; + napi_status status = napi_get_named_property(env, in, "streamChat", &streamChatNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to get the field streamChat.", napi_invalid_arg); + + status = Convert2Value(env, streamChatNapi, streamChatRef); + if (status != napi_ok) { + AIP_HILOGW("Failed to convert the streamChat."); + return napi_ok; + } + out = std::make_shared<ChatLLM>(env, streamChatRef); + return napi_ok; +} + +napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, LLMStreamAnswer &out) +{ + napi_value isFinishedNapi; + napi_status status = napi_get_named_property(env, in, "isFinished", &isFinishedNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to get the field isFinished.", napi_invalid_arg); + status = Convert2Value(env, isFinishedNapi, out.isFinished); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert the field isFinished.", napi_invalid_arg); + + napi_value chunkNapi; + status = napi_get_named_property(env, in, "chunk", &chunkNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to get the field chunk.", napi_invalid_arg); + status = Convert2Value(env, chunkNapi, out.chunk); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert the field chunk.", napi_invalid_arg); + return napi_ok; +} + static napi_status ConvertRerankChannelParams(napi_env env, const napi_value &in, RerankParamsStruct &out) { napi_value parametersNapi; @@ -878,12 +922,12 @@ static napi_status ConvertRerankChannelParams(napi_env env, const napi_value &in std::string keyStr; status = AipNapiUtils::Convert2Value(env, keyNapi, keyStr); LOG_ERROR_RETURN(status == napi_ok, "Failed to convert the channelType in parameters.", napi_invalid_arg); - int32_t keyInt = std::stoi(keyStr); - LOG_ERROR_RETURN(keyInt >= TsChannelType::VECTOR_DATABASE && keyInt <= TsChannelType::INVERTED_INDEX_DATABASE, - "channelType is ileagl.", napi_invalid_arg); + int32_t keyInt; + auto result = std::from_chars(keyStr.data(), keyStr.data() + keyStr.size(), keyInt); + LOG_ERROR_RETURN(result.ec == std::errc() && keyInt >= TsChannelType::VECTOR_DATABASE && + keyInt <= TsChannelType::INVERTED_INDEX_DATABASE, "channelType is ileagl.", napi_invalid_arg); napi_value valueNapi; napi_get_property(env, parametersNapi, keyNapi, &valueNapi); - std::shared_ptr<ChannelRerankParamsStruct> channelParams; bool isVectorWeightsPresent = false; napi_has_named_property(env, valueNapi, "vectorWeights", &isVectorWeightsPresent); if (isVectorWeightsPresent) { @@ -1033,6 +1077,7 @@ napi_status GetCurrentAbilityParam(napi_env env, napi_value in, ContextParam &pa param.area = context->GetArea(); param.bundleName = context->GetBundleName(); param.isSystemApp = context->IsSystemAppCalled(); + param.cacheDir = context->GetCacheDir(); return napi_ok; } @@ -1053,6 +1098,10 @@ napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, Cont AIP_HILOGD("Stage mode branch"); status = GetNamedProperty(env, in, "databaseDir", context.baseDir); LOG_ERROR_RETURN(status == napi_ok, "get databaseDir failed.", napi_invalid_arg); + + status = GetNamedProperty(env, in, "cacheDir", context.cacheDir); + LOG_ERROR_RETURN(status == napi_ok, "get cacheDir failed.", napi_invalid_arg); + status = GetNamedProperty(env, in, "area", context.area, true); LOG_ERROR_RETURN(status == napi_ok, "get area failed.", napi_invalid_arg); @@ -1151,6 +1200,42 @@ napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, napi return napi_ok; } +napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, OptionStruct &out) +{ + napi_value answerWithRetrievalItemNapi; + napi_status status = napi_get_named_property(env, in, "answerWithRetrievalItem", &answerWithRetrievalItemNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to get the field answerWithRetrievalItem.", napi_invalid_arg); + + status = Convert2Value(env, answerWithRetrievalItemNapi, out.answerWithRetrievalItem); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert the field answerWithRetrievalItem.", napi_invalid_arg); + return napi_ok; +} + +napi_status AipNapiUtils::Convert2Value(napi_env env, const napi_value &in, ConfigStruct &out) +{ + napi_value llmNapi; + napi_status status = napi_get_named_property(env, in, "llm", &llmNapi); + if (status == napi_ok) { + status = Convert2Value(env, llmNapi, out.chatLLM); + if (status != napi_ok) { + AIP_HILOGW("Failed to convert the field llm. status: %{public}d", status); + } + } + napi_value retrieverNapi; + status = napi_get_named_property(env, in, "retrievalConfig", &retrieverNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to get the field retrievalConfig.", napi_invalid_arg); + status = Convert2Value(env, retrieverNapi, out.retriever); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert the field retriever.", napi_invalid_arg); + napi_value conditionNapi; + status = napi_get_named_property(env, in, "retrievalCondition", &conditionNapi); + if (status == napi_ok) { + status = Convert2Value(env, conditionNapi, out.condition); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert the field condition.", napi_invalid_arg); + } + + return napi_ok; +} + napi_status AipNapiUtils::Convert2JSValue(napi_env env, const std::vector<uint8_t> &in, napi_value &out) { void *native = nullptr; @@ -1260,6 +1345,49 @@ napi_status AipNapiUtils::Convert2JSValue(napi_env env, const DataIntelligence:: return napi_ok; } +napi_status AipNapiUtils::Convert2JSValue(napi_env env, const AnswerStruct &in, napi_value &out) +{ + napi_status status = napi_create_object(env, &out); + LOG_ERROR_RETURN(status == napi_ok, "Failed to create napi object of AnswerStruct.", napi_invalid_arg); + + napi_value answerStr = nullptr; + status = Convert2JSValue(env, in.chunk, answerStr); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert chunk to napi_value.", napi_invalid_arg); + + status = napi_set_named_property(env, out, "chunk", answerStr); + LOG_ERROR_RETURN(status == napi_ok, "Failed to set chunk to object of AnswerStruct.", napi_invalid_arg); + + napi_value data = nullptr; + status = Convert2JSValue(env, in.data, data); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert data to napi_value.", napi_invalid_arg); + + status = napi_set_named_property(env, out, "data", data); + LOG_ERROR_RETURN(status == napi_ok, "Failed to set data to object of AnswerStruct.", napi_invalid_arg); + + return napi_ok; +} + +napi_status AipNapiUtils::Convert2JSValue(napi_env env, const StreamStruct &in, napi_value &out) +{ + napi_status status = napi_create_object(env, &out); + LOG_ERROR_RETURN(status == napi_ok, "Failed to get create napi object of StreamStruct.", napi_invalid_arg); + + napi_value isFinishedNapi; + status = Convert2JSValue(env, in.isFinished, isFinishedNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert isFinished to napi_value.", napi_invalid_arg); + + status = napi_set_named_property(env, out, "isFinished", isFinishedNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to set isFinished to object of StreamStruct.", napi_invalid_arg); + + napi_value answerNapi; + status = Convert2JSValue(env, in.answer, answerNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to convert answer to napi_value.", napi_invalid_arg); + + status = napi_set_named_property(env, out, "answer", answerNapi); + LOG_ERROR_RETURN(status == napi_ok, "Failed to set answer to object of StreamStruct.", napi_invalid_arg); + return napi_ok; +} + napi_status AipNapiUtils::Convert2JSValue(napi_env env, const std::map<std::string, FieldType> &in, napi_value &out) { napi_create_object(env, &out); diff --git a/udmf/framework/jskitsimpl/intelligence/i_aip_core_manager_impl.cpp b/udmf/framework/jskitsimpl/intelligence/i_aip_core_manager_impl.cpp index 8866a390..aac1ccf3 100644 --- a/udmf/framework/jskitsimpl/intelligence/i_aip_core_manager_impl.cpp +++ b/udmf/framework/jskitsimpl/intelligence/i_aip_core_manager_impl.cpp @@ -17,22 +17,8 @@ #include "aip_napi_error.h" -#undef LOG_TAG -#define LOG_TAG "IAipCoreManagerImpl" - namespace OHOS { namespace DataIntelligence { -int32_t IAipCoreManagerImpl::InitRetriever(const RetrievalConfigStruct &retrievalConfig) -{ - return DEVICE_EXCEPTION; -} - -int32_t IAipCoreManagerImpl::Retrieve(const std::string query, const RetrievalConditionStruct &condition, - RetrievalResponseStruct &retrievalResponse) -{ - return DEVICE_EXCEPTION; -} - int32_t IAipCoreManagerImpl::InitTextModel(const ModelConfigData &config) { return DEVICE_EXCEPTION; @@ -84,5 +70,33 @@ int32_t IAipCoreManagerImpl::SplitText(std::string text, int32_t size, float ove { return DEVICE_EXCEPTION; } + +int32_t IAipCoreManagerImpl::CreateRAGSession(const ContextParam &contex, const ConfigStruct &config) +{ + return DEVICE_EXCEPTION; +} + +int32_t IAipCoreManagerImpl::RAGSessionStreamRun(const std::string &question, const OptionStruct &option, + std::function<void(const StreamStruct&, int32_t)> callback) +{ + return DEVICE_EXCEPTION; +} + +int32_t IAipCoreManagerImpl::ReleaseRAGSession() +{ + return DEVICE_EXCEPTION; +} + +int32_t IAipCoreManagerImpl::RAGSessionRun(const std::string &query, const OptionStruct &runOption, + AnswerStruct &answer) +{ + return DEVICE_EXCEPTION; +} + +bool IAipCoreManagerImpl::CheckDeviceType() +{ + return false; +} + } // namespace DataIntelligence } // namespace OHOS diff --git a/udmf/framework/jskitsimpl/intelligence/image_embedding_napi.cpp b/udmf/framework/jskitsimpl/intelligence/image_embedding_napi.cpp index cbe74806..001a271b 100644 --- a/udmf/framework/jskitsimpl/intelligence/image_embedding_napi.cpp +++ b/udmf/framework/jskitsimpl/intelligence/image_embedding_napi.cpp @@ -79,8 +79,8 @@ ImageEmbeddingNapi::ImageEmbeddingNapi() : env_(nullptr) {} ImageEmbeddingNapi::~ImageEmbeddingNapi() { AipNapiUtils::UnLoadAlgoLibrary(imgAipCoreMgrHandle_); - imageAipCoreManager_ = nullptr; delete imageAipCoreManager_; + imageAipCoreManager_ = nullptr; } static napi_value StartInit(napi_env env, napi_value exports, struct ImageEmbeddingConstructorInfo info) @@ -130,7 +130,7 @@ napi_value ImageEmbeddingNapi::Init(napi_env env, napi_value exports) if (imgAipCoreMgrHandle_.pAipManager != nullptr) { imageAipCoreManager_ = AipNapiUtils::GetAlgoObj(imgAipCoreMgrHandle_); } else { - imageAipCoreManager_ = new IAipCoreManagerImpl(); + imageAipCoreManager_ = new (std::nothrow) IAipCoreManagerImpl(); } if (imageAipCoreManager_ == nullptr) { @@ -230,11 +230,16 @@ napi_value ImageEmbeddingNapi::GetImageEmbeddingModel(napi_env env, napi_callbac return nullptr; } - auto asyncGetImgEmbeddingModelData = new AsyncGetImageEmbeddingModelData{ + auto asyncGetImgEmbeddingModelData = new (std::nothrow) AsyncGetImageEmbeddingModelData{ .asyncWork = nullptr, .deferred = deferred, .config = imgModelConfig, }; + if (asyncGetImgEmbeddingModelData == nullptr) { + AIP_HILOGE("new asyncGetImgEmbeddingModelData error."); + ThrowIntelligenceErr(env, INNER_ERROR, "new asyncGetImgEmbeddingModelData failed"); + return nullptr; + } if (!CreateAsyncImgModelExecution(env, asyncGetImgEmbeddingModelData)) { AIP_HILOGE("create AsyncTextModelExecution failed"); @@ -258,7 +263,9 @@ bool ImageEmbeddingNapi::ParseModelConfig(napi_env env, napi_value *args, size_t return false; } - napi_value version, isNPUAvailable, cachePath; + napi_value version; + napi_value isNPUAvailable; + napi_value cachePath; napi_status status = napi_get_named_property(env, args[ARG_0], "version", &version); if (status != napi_ok) { AIP_HILOGE("napi get version property failed"); @@ -369,6 +376,7 @@ void ImageEmbeddingNapi::GetImgEmbeddingModelCompleteCB(napi_env env, napi_statu if (status != napi_ok) { AIP_HILOGE("napi_new_instance failed"); napi_get_undefined(env, &result); + delete modelData; return; } @@ -428,11 +436,15 @@ napi_value ImageEmbeddingNapi::GetEmbedding(napi_env env, napi_callback_info inf bool ImageEmbeddingNapi::GetEmbeddingAsyncExecution(napi_env env, napi_deferred deferred, std::string strArg) { AIP_HILOGD("Enter"); - auto imageCallbackData = new ImageCallbackData{ + auto imageCallbackData = new (std::nothrow) ImageCallbackData{ .asyncWork = nullptr, .deferred = deferred, .strArg = strArg, }; + if (imageCallbackData == nullptr) { + AIP_HILOGE("new imageCallbackData error."); + return false; + } napi_value resourceName; napi_status status = napi_create_string_utf8(env, "ImageGetEmbedding", NAPI_AUTO_LENGTH, &resourceName); @@ -550,10 +562,14 @@ napi_value ImageEmbeddingNapi::LoadModel(napi_env env, napi_callback_info info) bool ImageEmbeddingNapi::LoadAsyncExecution(napi_env env, napi_deferred deferred) { AIP_HILOGD("Enter"); - auto loadCallbackData = new LoadCallbackData{ + auto loadCallbackData = new (std::nothrow) LoadCallbackData{ .asyncWork = nullptr, .deferred = deferred, }; + if (loadCallbackData == nullptr) { + AIP_HILOGE("new loadCallbackData error."); + return false; + } napi_value resourceName; napi_status status = napi_create_string_utf8(env, "imageLoad", NAPI_AUTO_LENGTH, &resourceName); @@ -661,10 +677,14 @@ napi_value ImageEmbeddingNapi::ReleaseModel(napi_env env, napi_callback_info inf bool ImageEmbeddingNapi::ReleaseAsyncExecution(napi_env env, napi_deferred deferred) { AIP_HILOGD("Enter"); - auto releaseCallbackData = new ReleaseCallbackData{ + auto releaseCallbackData = new (std::nothrow) ReleaseCallbackData{ .asyncWork = nullptr, .deferred = deferred, }; + if (releaseCallbackData == nullptr) { + AIP_HILOGE("new releaseCallbackData error."); + return false; + } napi_value resourceName; napi_status status = napi_create_string_utf8(env, "textLoad", NAPI_AUTO_LENGTH, &resourceName); diff --git a/udmf/framework/jskitsimpl/intelligence/js_ability.cpp b/udmf/framework/jskitsimpl/intelligence/js_ability.cpp index 5c36d681..8653083e 100644 --- a/udmf/framework/jskitsimpl/intelligence/js_ability.cpp +++ b/udmf/framework/jskitsimpl/intelligence/js_ability.cpp @@ -14,6 +14,8 @@ */ #define LOG_TAG "JSAbility" +#include <memory> + #include "aip_log.h" #include "extension_context.h" #include "js_ability.h" @@ -27,6 +29,7 @@ Context::Context(std::shared_ptr<AbilityRuntime::Context> stageContext) isStageMode_ = true; databaseDir_ = stageContext->GetDatabaseDir(); bundleName_ = stageContext->GetBundleName(); + cacheDir_ = stageContext->GetCacheDir(); area_ = stageContext->GetArea(); auto hapInfo = stageContext->GetHapModuleInfo(); if (hapInfo != nullptr) { @@ -57,6 +60,7 @@ Context::Context(std::shared_ptr<AbilityRuntime::Context> stageContext) Context::Context(std::shared_ptr<AbilityRuntime::AbilityContext> abilityContext) { databaseDir_ = abilityContext->GetDatabaseDir(); + cacheDir_ = abilityContext->GetCacheDir(); bundleName_ = abilityContext->GetBundleName(); area_ = abilityContext->GetArea(); auto abilityInfo = abilityContext->GetAbilityInfo(); @@ -70,6 +74,11 @@ std::string Context::GetDatabaseDir() return databaseDir_; } +std::string Context::GetCacheDir() +{ + return cacheDir_; +} + int Context::GetSystemDatabaseDir(const std::string &dataGroupId, std::string &databaseDir) { return stageContext_->GetSystemDatabaseDir(dataGroupId, false, databaseDir); diff --git a/udmf/framework/jskitsimpl/intelligence/native_module_intelligence.cpp b/udmf/framework/jskitsimpl/intelligence/native_module_intelligence.cpp index daf2b026..9d92b1ca 100644 --- a/udmf/framework/jskitsimpl/intelligence/native_module_intelligence.cpp +++ b/udmf/framework/jskitsimpl/intelligence/native_module_intelligence.cpp @@ -27,7 +27,6 @@ static napi_value Export(napi_env env, napi_value exports) AIP_HILOGD("NativeModuleIntelligence call"); TextEmbeddingNapi::Init(env, exports); ImageEmbeddingNapi::Init(env, exports); - RetrievalNapi::Init(env, exports); return exports; } diff --git a/udmf/framework/jskitsimpl/intelligence/native_module_rag.cpp b/udmf/framework/jskitsimpl/intelligence/native_module_rag.cpp new file mode 100644 index 00000000..453e3af1 --- /dev/null +++ b/udmf/framework/jskitsimpl/intelligence/native_module_rag.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 "native_module_rag.h" + +#include "aip_log.h" +#include "rag_agent_chatllm_napi.h" +#include "rag_session_napi.h" + +#undef LOG_TAG +#define LOG_TAG "NativeModuleRAG" + +namespace OHOS { +namespace DataIntelligence { +static napi_value Export(napi_env env, napi_value exports) +{ + AIP_HILOGD("NativeModuleRAG call"); + RAGSessionNapi::Init(env, exports); + RAGAgentChatLLMNapi::Init(env, exports); + return exports; +} + +static napi_module DataRAGModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Export, + .nm_modname = "data.rag", + .nm_priv = ((void *)0), + .reserved = { 0 } +}; + +extern "C" __attribute__((constructor)) void RegisterRagModule() +{ + napi_module_register(&DataRAGModule); +} +} // namespace DataIntelligence +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/intelligence/rag_agent_chatllm_napi.cpp b/udmf/framework/jskitsimpl/intelligence/rag_agent_chatllm_napi.cpp new file mode 100644 index 00000000..478a4ba5 --- /dev/null +++ b/udmf/framework/jskitsimpl/intelligence/rag_agent_chatllm_napi.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 "rag_agent_chatllm_napi.h" + +#include "aip_log.h" +#include "aip_napi_utils.h" + +#undef LOG_TAG +#define LOG_TAG "ChatLLMNNapi" + +namespace OHOS { +namespace DataIntelligence { + +napi_value RAGAgentChatLLMNapi::Constructor(napi_env env, napi_callback_info info) +{ + napi_value args; + napi_get_cb_info(env, info, nullptr, nullptr, &args, nullptr); + return args; +} + +napi_value RAGAgentChatLLMNapi::Init(napi_env env, napi_value exports) +{ + if (const napi_status status = InitEnum(env, exports); status != napi_ok) { + AIP_HILOGI("InitEnum fail."); + return nullptr; + } + napi_value chatLLMClass; + napi_define_class(env, "ChatLlm", NAPI_AUTO_LENGTH, Constructor, nullptr, 0, nullptr, &chatLLMClass); + napi_set_named_property(env, exports, "ChatLlm", chatLLMClass); + return exports; +} + +napi_status RAGAgentChatLLMNapi::InitEnum(napi_env env, napi_value exports) +{ + napi_value llmRequestStatus; + if (const napi_status status = napi_create_object(env, &llmRequestStatus); status != napi_ok) { + AIP_HILOGE("create napi object fail."); + return status; + } + AipNapiUtils::SetInt32Property(env, llmRequestStatus, LLM_SUCCESS, "LLM_SUCCESS"); + AipNapiUtils::SetInt32Property(env, llmRequestStatus, LLM_ERROR, "LLM_ERROR"); + AipNapiUtils::SetInt32Property(env, llmRequestStatus, LLM_LOAD_FAILED, "LLM_LOAD_FAILED"); + AipNapiUtils::SetInt32Property(env, llmRequestStatus, LLM_TIMEOUT, "LLM_TIMEOUT"); + AipNapiUtils::SetInt32Property(env, llmRequestStatus, LLM_BUSY, "LLM_BUSY"); + AipNapiUtils::SetPropertyName(env, exports, "LlmRequestStatus", llmRequestStatus); + return napi_ok; +} + +} +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/intelligence/rag_chatllm_impl.cpp b/udmf/framework/jskitsimpl/intelligence/rag_chatllm_impl.cpp new file mode 100644 index 00000000..2e35081a --- /dev/null +++ b/udmf/framework/jskitsimpl/intelligence/rag_chatllm_impl.cpp @@ -0,0 +1,356 @@ +/* +* 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 "rag_chatllm_impl.h" + +#include <future> +#include <uv.h> + +#include "aip_log.h" +#include "aip_napi_error.h" +#include "aip_napi_utils.h" +#include "napi_trace.h" + +#undef LOG_TAG +#define LOG_TAG "CreateRAGNapi" + +namespace OHOS { +namespace DataIntelligence { +std::shared_ptr<LLMStreamCallback> ChatLLM::llmStreamCallback_ = nullptr; +constexpr int STREAM_CHAT_WORK_DEFAULT_WAIT = 2; +constexpr int JS_STREAM_CHAT_ARGS_COUNT = 2; + +ChatLLM::ChatLLM(napi_env env, napi_ref streamChatRef) : env_(env), streamChatRef_(streamChatRef) +{ +} + +ChatLLM::~ChatLLM() +{ + napi_delete_reference(env_, streamChatRef_); +} + +TsLLMRequestStatus ChatLLM::StreamChat(const std::string &query, const LLMStreamCallback &streamCallback) +{ + DATA_INTELLIGENCE_HITRACE(std::string(__FUNCTION__)); + AIP_HILOGD("Enter. queryLength: %{public}zu", query.length()); + if (streamChatRef_ == nullptr) { + AIP_HILOGE("streamChatRef_ is nullptr"); + return LLM_ERROR; + } + llmStreamCallback_ = std::make_shared<LLMStreamCallback>(streamCallback); + + auto *param = new (std::nothrow) WorkParam { + query, + std::make_shared<LLMStreamCallback>(streamCallback), + env_, + streamChatRef_, + napi_ok, + 0, + std::make_shared<ThreadLockInfo>(), + }; + if (param == nullptr) { + AIP_HILOGE("WorkParam is nullptr"); + return LLM_ERROR; + } + + napi_status status = napi_send_event(env_, [param] { + StreamChatCallbackEventFunc(param); + }, napi_eprio_high); + if (status != napi_ok) { + AIP_HILOGE("napi_send_event running failed, status: %{public}d", status); + delete param; + param = nullptr; + return LLM_ERROR; + } + + std::unique_lock<std::mutex> lock(param->lockInfo->mutex); + if (param->lockInfo->condition.wait_for(lock, std::chrono::seconds(STREAM_CHAT_WORK_DEFAULT_WAIT), + [param] { return param->lockInfo->ready; })) { + AIP_HILOGE("call js callback not complete."); + } + AIP_HILOGD("llmStreamChatWorker end, ready: %{public}d, result: %{public}d", param->lockInfo->ready, param->result); + int32_t retInt = param->result; + + delete param; + param = nullptr; + + return static_cast<TsLLMRequestStatus>(retInt); +} + +void ChatLLM::SetRef(napi_ref streamChatRef) +{ + streamChatRef_ = streamChatRef; +} + +napi_ref ChatLLM::GetRef() +{ + return streamChatRef_; +} + +void ChatLLM::NativeCallbackAsync(napi_env env, const LLMStreamAnswer &answer) +{ + uv_loop_s *loop = nullptr; + napi_get_uv_event_loop(env, &loop); + if (loop == nullptr) { + AIP_HILOGE("loop instance is nullptr"); + return; + } + auto *work = new (std::nothrow) uv_work_t; + if (work == nullptr) { + AIP_HILOGE("work is nullptr"); + return; + } + auto *param = new (std::nothrow) StreamCallbackWorkParam { answer, env }; + if (param == nullptr) { + delete work; + work = nullptr; + AIP_HILOGE("WorkParam is nullptr"); + return; + } + work->data = reinterpret_cast<void *>(param); + int ret = uv_queue_work(loop, work, [](uv_work_t *work) { + if (work == nullptr || work->data == nullptr) { + AIP_HILOGE("invalid parameter"); + return; + } + auto *workParam = reinterpret_cast<StreamCallbackWorkParam *>(work->data); + llmStreamCallback_->operator()(workParam->answer); + }, [](uv_work_t *work, int32_t status) { + if (work == nullptr) { + AIP_HILOGE("invalid parameter"); + return; + } + auto *workParam = reinterpret_cast<StreamCallbackWorkParam *>(work->data); + delete workParam; + workParam = nullptr; + delete work; + work = nullptr; + }); + if (ret != 0) { + AIP_HILOGE("uv_queue_work running failed, ret: %{public}d", ret); + delete param; + param = nullptr; + delete work; + work = nullptr; + } +} + +napi_value ChatLLM::StreamCallbackFunc(napi_env env, napi_callback_info info) +{ + napi_value result = nullptr; + napi_get_null(env, &result); + + napi_value args[] = { nullptr }; + size_t size = 1; + napi_value jsFunction; + napi_status status = napi_get_cb_info(env, info, &size, args, nullptr, reinterpret_cast<void**>(&jsFunction)); + if (status != napi_ok) { + AIP_HILOGE("napi_get_cb_info failed. status: %{public}d", status); + return result; + } + + if (llmStreamCallback_ == nullptr) { + AIP_HILOGE("streamCallback is nullptr."); + return result; + } + + LLMStreamAnswer answer = { + .isFinished = false, + .chunk = "", + }; + status = AipNapiUtils::Convert2Value(env, args[0], answer); + if (status != napi_ok) { + AIP_HILOGE("Failed to convert the LLMStreamAnswer. status: %{public}d", status); + return result; + } + + NativeCallbackAsync(env, answer); + + return result; +} + +void ChatLLM::StreamChatCallbackEventFunc(WorkParam *param) +{ + if (param == nullptr) { + AIP_HILOGE("param is nullptr"); + return; + } + + if (param->query.empty() || param->llmStreamCallback == nullptr || param->ref == nullptr) { + AIP_HILOGE("param of llmWorkParam is null"); + return; + } + + napi_handle_scope scope = nullptr; + napi_open_handle_scope(param->env, &scope); + if (scope == nullptr) { + AIP_HILOGE("scope open failed. scope is nullptr"); + return; + } + + CallJSStreamChat(param->env, param->ref, param); + + napi_close_handle_scope(param->env, scope); +} + +void ChatLLM::CallJSStreamChat(napi_env env, napi_ref ref, WorkParam *llmWorkParam) +{ + napi_value callback = nullptr; + auto ret = napi_get_reference_value(env, ref, &callback); + if (ret != napi_ok) { + AIP_HILOGE("get js callback failed. ret: %{public}d", ret); + return; + } + + napi_value queryArg; + napi_status status = napi_create_string_utf8(env, llmWorkParam->query.c_str(), NAPI_AUTO_LENGTH, &queryArg); + if (status != napi_ok) { + AIP_HILOGE("Failed to napi_create_string_utf8 for query. ret: %{public}d", status); + return; + } + + napi_value jsCallbackArg; + status = napi_create_function(env, "callback", NAPI_AUTO_LENGTH, StreamCallbackFunc, nullptr, &jsCallbackArg); + if (status != napi_ok) { + AIP_HILOGE("Failed to napi_create_function for callback. ret: %{public}d", status); + return; + } + + napi_value jsStreamChat; + status = napi_get_reference_value(env, ref, &jsStreamChat); + if (status != napi_ok) { + AIP_HILOGE("Failed to napi_get_reference_value for jsStreamChat. ret: %{public}d", status); + return; + } + + napi_value global; + status = napi_get_global(env, &global); + if (status != napi_ok) { + AIP_HILOGE("Failed to napi_get_global from env. ret: %{public}d", status); + return; + } + + const napi_value args[JS_STREAM_CHAT_ARGS_COUNT] = { queryArg, jsCallbackArg }; + + AIP_HILOGI("Begin call js."); + napi_value promiseResult; // promise + status = napi_call_function(env, global, jsStreamChat, JS_STREAM_CHAT_ARGS_COUNT, args, &promiseResult); + if (status != napi_ok) { + AIP_HILOGE("Failed to napi_call_function for jsStreamChat. ret: %{public}d", status); + return; + } + + HandlePromiseValue(env, promiseResult, llmWorkParam); +} + +void ChatLLM::HandlePromiseValue(napi_env env, napi_value promiseResult, WorkParam *llmWorkParam) +{ + auto isPromise = false; + napi_status status = napi_is_promise(env, promiseResult, &isPromise); + if (status != napi_ok || !isPromise) { + AIP_HILOGE("resultType is not promise. isPromise: %{public}d, ret: %{public}d", isPromise, status); + return; + } + + napi_value thenCallback; + status = napi_create_function(env, nullptr, 0, PromiseThenCallback, llmWorkParam, &thenCallback); + if (status != napi_ok) { + AIP_HILOGE("Failed to create then callback. ret: %{public}d", status); + return; + } + + napi_value catchCallback; + status = napi_create_function(env, nullptr, 0, PromiseCatchCallback, llmWorkParam, &catchCallback); + if (status != napi_ok) { + AIP_HILOGE("Failed to create catch callback. ret: %{public}d", status); + return; + } + + napi_value thenMethod; + status = napi_get_named_property(env, promiseResult, "then", &thenMethod); + if (status != napi_ok) { + AIP_HILOGE("Failed to get then method. ret: %{public}d", status); + return; + } + + napi_value catchMethod; + status = napi_get_named_property(env, promiseResult, "catch", &catchMethod); + if (status != napi_ok) { + AIP_HILOGE("Failed to get catch method. ret: %{public}d", status); + return; + } + + napi_value argsPromise[1] = { thenCallback }; + napi_value thenResult; + status = napi_call_function(env, promiseResult, thenMethod, 1, argsPromise, &thenResult); + if (status != napi_ok) { + AIP_HILOGE("Failed to call then method. ret: %{public}d", status); + return; + } + + argsPromise[0] = catchCallback; + napi_value catchResult; + status = napi_call_function(env, promiseResult, catchMethod, 1, argsPromise, &catchResult); + if (status != napi_ok) { + AIP_HILOGE("Failed to call catch method. ret: %{public}d", status); + } +} + +napi_value ChatLLM::PromiseThenCallback(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + void *paramIn = nullptr; + napi_get_cb_info(env, info, &argc, args, nullptr, &paramIn); + + auto *callbackParam = static_cast<WorkParam*>(paramIn); + if (callbackParam == nullptr) { + AIP_HILOGE("callbackParam is null"); + return nullptr; + } + + napi_valuetype resultType; + napi_typeof(env, args[0], &resultType); + if (resultType == napi_object) { + napi_value statusNapi; + napi_status status = napi_get_named_property(env, args[0], "status", &statusNapi); + if (status == napi_ok) { + int32_t number = 0; + napi_get_value_int32(env, statusNapi, &number); + if (number != TsLLMRequestStatus::LLM_SUCCESS) { + AIP_HILOGE("LLM return error. errCode: %{public}d", number); + } + callbackParam->result = number; + } else { + AIP_HILOGE("cannot get prperty status"); + } + } else { + AIP_HILOGE("The resolved value is not a object, type: %{public}d", resultType); + } + + std::unique_lock<std::mutex> lock(callbackParam->lockInfo->mutex); + callbackParam->lockInfo->ready = true; + AIP_HILOGD("begin notify_all"); + callbackParam->lockInfo->condition.notify_all(); + return nullptr; +} + +napi_value ChatLLM::PromiseCatchCallback(napi_env env, napi_callback_info info) +{ + AIP_HILOGE("The promise function catch exception."); + return nullptr; +} + +} +} diff --git a/udmf/framework/jskitsimpl/intelligence/rag_session_napi.cpp b/udmf/framework/jskitsimpl/intelligence/rag_session_napi.cpp new file mode 100644 index 00000000..62902b85 --- /dev/null +++ b/udmf/framework/jskitsimpl/intelligence/rag_session_napi.cpp @@ -0,0 +1,625 @@ +/* + * 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 "rag_session_napi.h" +#include <dlfcn.h> +#include <functional> +#include <node_api.h> +#include <string> +#include <utility> +#include <uv.h> + +#include "aip_log.h" +#include "aip_napi_error.h" +#include "aip_napi_utils.h" +#include "i_aip_core_manager_impl.h" +#include "napi_trace.h" + +#undef LOG_TAG +#define LOG_TAG "RAGSessionNapi" + +namespace OHOS { +namespace DataIntelligence { +namespace { +const int32_t ERR_OK = 0; +constexpr const char *AIP_MANAGER_PATH = "libaip_core.z.so"; +} // namespace +AipCoreManagerHandle RAGSessionNapi::aipAipCoreMgrHandle_{}; +constexpr int STREAM_RUN_ARG_COUNT = 3; +constexpr int STREAM_RUN_QUESTION_ARG = 0; +constexpr int STREAM_RUN_OPTION_ARG = 1; +constexpr int STREAM_RUN_CALLBACK_ARG = 2; +constexpr int CREATE_SESSION_ARG_COUNT = 2; +constexpr int CREATE_SESSION_CONTEXT_ARG = 0; +constexpr int CREATE_SESSION_CONFIG_ARG = 1; + +RAGSessionNapi::RAGSessionNapi(IAipCoreManager *aipAipCoreManager) : aipAipCoreManager_(aipAipCoreManager) +{ +} + +RAGSessionNapi::~RAGSessionNapi() +{ + if (env_ == nullptr) { + AIP_HILOGE("env_ is nullptr."); + return; + } + if (ref_ != nullptr) { + napi_delete_reference(env_, ref_); + } + + if (thisJsRef_ != nullptr) { + napi_delete_reference(env_, thisJsRef_); + } +} + +napi_value RAGSessionNapi::Init(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + DECLARE_NAPI_FUNCTION("createRagSession", CreateRAGSession), + }; + napi_status status = napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + if (status != napi_ok) { + AIP_HILOGE("define properties fail, status = %{public}d", status); + return nullptr; + } + return exports; +} + +napi_value RAGSessionNapi::WrapAipCoreManager(napi_env env, IAipCoreManager* ragAipCoreManager) +{ + if (ragAipCoreManager == nullptr) { + AIP_HILOGE("ragAipCoreManager is nullptr."); + return nullptr; + } + napi_value result; + napi_status status = napi_create_object(env, &result); + if (status != napi_ok) { + return nullptr; + } + auto *sessionNapi = new (std::nothrow) RAGSessionNapi(ragAipCoreManager); + if (sessionNapi == nullptr) { + AIP_HILOGE("sessionNapi new failed"); + return nullptr; + } + status = napi_wrap(env, result, static_cast<void *>(sessionNapi), [](napi_env env, void *data, void *hint) { + delete static_cast<RAGSessionNapi *>(data); + }, nullptr, nullptr); + if (status != napi_ok) { + AIP_HILOGE("napi_wrap aipCoreMangager failed, erroCode is %{public}d", status); + delete sessionNapi; + return nullptr; + } + napi_value streamRunFn; + status = napi_create_function(env, nullptr, NAPI_AUTO_LENGTH, StreamRun, nullptr, &streamRunFn); + if (status != napi_ok) { + delete sessionNapi; + return nullptr; + } + status = napi_set_named_property(env, result, "streamRun", streamRunFn); + if (status != napi_ok) { + delete sessionNapi; + return nullptr; + } + napi_value closeFn; + status = napi_create_function(env, nullptr, NAPI_AUTO_LENGTH, Close, nullptr, &closeFn); + if (status != napi_ok) { + AIP_HILOGE("napi_create_function Close failed, erroCode is %{public}d", status); + delete sessionNapi; + return nullptr; + } + status = napi_set_named_property(env, result, "close", closeFn); + if (status != napi_ok) { + AIP_HILOGE("napi_set_named_property close failed, erroCode is %{public}d", status); + delete sessionNapi; + return nullptr; + } + AIP_HILOGI("Build rag session success."); + return result; +} + +napi_value RAGSessionNapi::CreateRAGSession(napi_env env, napi_callback_info info) +{ + napi_value args[CREATE_SESSION_ARG_COUNT] = { nullptr }; + size_t argc = CREATE_SESSION_ARG_COUNT; + napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + if (status != napi_ok) { + ThrowIntelligenceErr(env, INNER_ERROR, "napi_get_cb_info failed."); + return nullptr; + } + ContextParam context; + status = AipNapiUtils::Convert2Value(env, args[CREATE_SESSION_CONTEXT_ARG], context); + if (status != napi_ok) { + ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Parse context failed."); + return nullptr; + } + ConfigStruct config; + status = AipNapiUtils::Convert2Value(env, args[CREATE_SESSION_CONFIG_ARG], config); + if (status != napi_ok) { + ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Parse config failed."); + return nullptr; + } + napi_value promise = nullptr; + napi_deferred deferred = nullptr; + status = napi_create_promise(env, &deferred, &promise); + if (status != napi_ok) { + ThrowIntelligenceErr(env, INNER_ERROR, "create promise failed"); + return nullptr; + } + auto asyncCreateRAGSession = new (std::nothrow) AsyncCreateRAGSession{ + .asyncWork = nullptr, + .deferred = deferred, + .context = context, + .config = config + }; + if (asyncCreateRAGSession == nullptr) { + ThrowIntelligenceErr(env, INNER_ERROR, "Allocate memory failed."); + return nullptr; + } + if (!CreateAsyncCreateRAGSession(env, asyncCreateRAGSession)) { + delete asyncCreateRAGSession; + ThrowIntelligenceErr(env, INNER_ERROR, "create CreateAsyncCreateRAGSession failed"); + return nullptr; + } + return promise; +} + +bool RAGSessionNapi::CreateAsyncCreateRAGSession(napi_env env, AsyncCreateRAGSession *asyncCreateRAGSession) +{ + napi_value resourceName; + napi_status status = napi_create_string_utf8(env, "CreateRAGSession", NAPI_AUTO_LENGTH, &resourceName); + if (status != napi_ok) { + AIP_HILOGE(" napi_create_string_utf8 failed."); + return false; + } + status = napi_create_async_work(env, nullptr, resourceName, CreateRAGSessionExecutionCB, CreateRAGSessionCompleteCB, + static_cast<void *>(asyncCreateRAGSession), &asyncCreateRAGSession->asyncWork); + if (status != napi_ok) { + AIP_HILOGE("napi_create_async_work failed. status: %{public}d", status); + return false; + } + status = napi_queue_async_work_with_qos(env, asyncCreateRAGSession->asyncWork, napi_qos_default); + if (status != napi_ok) { + AIP_HILOGE("napi_queue_async_work_with_qos failed. status: %{public}d", status); + napi_delete_async_work(env, asyncCreateRAGSession->asyncWork); + return false; + } + return true; +} + +void RAGSessionNapi::CreateRAGSessionExecutionCB(napi_env env, void *data) +{ + AsyncCreateRAGSession *asyncCreateRAGSession = static_cast<AsyncCreateRAGSession *>(data); + auto config = asyncCreateRAGSession->config; + auto context = asyncCreateRAGSession->context; + IAipCoreManager *aipAipCoreManager = nullptr; + if (aipAipCoreMgrHandle_.create == nullptr) { + AipNapiUtils::LoadAlgoLibrary(AIP_MANAGER_PATH, aipAipCoreMgrHandle_, false); + } + if (aipAipCoreMgrHandle_.create != nullptr) { + aipAipCoreManager = aipAipCoreMgrHandle_.create(); + } + if (aipAipCoreManager == nullptr) { + AIP_HILOGW("Init RAGSession success by new."); + aipAipCoreManager = new (std::nothrow) IAipCoreManagerImpl(); + } + if (aipAipCoreManager == nullptr) { + AIP_HILOGE("Allocate memory failed."); + return; + } + int32_t ret = aipAipCoreManager->CreateRAGSession(context, config); + asyncCreateRAGSession->ret = ret; + if (ret != ERR_OK) { + AIP_HILOGE("init RAGSession failed, erroCode is %{public}d", ret); + delete aipAipCoreManager; + return; + } + asyncCreateRAGSession->ragAipCoreManagerPtr = aipAipCoreManager; +} + +void RAGSessionNapi::CreateRAGSessionCompleteCB(napi_env env, napi_status status, void *data) +{ + AsyncCreateRAGSession *asyncCreateRAGSession = static_cast<AsyncCreateRAGSession *>(data); + if (asyncCreateRAGSession == nullptr) { + AIP_HILOGE("asyncCreateRAGSession is nullptr."); + return; + } + auto ret = asyncCreateRAGSession->ret; + napi_value result = nullptr; + if (ret != ERR_OK) { + if (ret == DEVICE_EXCEPTION) { + ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "CreateRAGSessionCompleteCB failed", result); + } else { + ThrowIntelligenceErrByPromise(env, + ConvertErrCodeNative2Ts(ret), "CreateRAGSessionCompleteCB failed", result); + } + napi_reject_deferred(env, asyncCreateRAGSession->deferred, result); + } else { + result = WrapAipCoreManager(env, asyncCreateRAGSession->ragAipCoreManagerPtr); + if (result == nullptr) { + delete asyncCreateRAGSession->ragAipCoreManagerPtr; + ThrowIntelligenceErrByPromise(env, INNER_ERROR, "CreateRAGSessionCompleteCB failed", result); + napi_reject_deferred(env, asyncCreateRAGSession->deferred, result); + } + status = napi_resolve_deferred(env, asyncCreateRAGSession->deferred, result); + if (status != napi_ok) { + AIP_HILOGE("napi_resolve_deferred failed. status: %{public}d", status); + } + } + status = napi_delete_async_work(env, asyncCreateRAGSession->asyncWork); + if (status != napi_ok) { + AIP_HILOGE("napi_delete_async_work failed. status: %{public}d", status); + } + delete asyncCreateRAGSession; +} + +napi_value RAGSessionNapi::Close(napi_env env, napi_callback_info info) +{ + napi_value argv[1] = { nullptr }; + size_t argc = 1; + napi_value jsThis = nullptr; + napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr); + if (status != napi_ok) { + ThrowIntelligenceErr(env, INNER_ERROR, "napi_get_cb_info failed."); + return nullptr; + } + + napi_value promise = nullptr; + napi_deferred deferred = nullptr; + status = napi_create_promise(env, &deferred, &promise); + if (status != napi_ok) { + ThrowIntelligenceErr(env, INNER_ERROR, "create promise failed."); + return nullptr; + } + RAGSessionNapi *sessionNapi; + status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&sessionNapi)); + if (status != napi_ok || sessionNapi == nullptr || sessionNapi->aipAipCoreManager_ == nullptr) { + ThrowIntelligenceErr(env, RAG_E_RAG_ALREADY_CLOSED, "RAG session napi has already closed."); + return nullptr; + } + auto asyncClose = new (std::nothrow) AsyncStreamRun { + .asyncWork = nullptr, + .deferred = deferred, + .sessionNapi = sessionNapi + }; + if (asyncClose == nullptr) { + ThrowIntelligenceErr(env, INNER_ERROR, "Allocate memory failed."); + return nullptr; + } + if (!CreateAsyncCloseExecution(env, asyncClose)) { + delete asyncClose; + ThrowIntelligenceErr(env, INNER_ERROR, "CreateAsyncCloseExecution failed"); + return nullptr; + } + return promise; +} + +bool RAGSessionNapi::CreateAsyncCloseExecution(napi_env env, AsyncStreamRun *asyncClose) +{ + napi_value resourceName; + napi_status status = napi_create_string_utf8(env, "Close", NAPI_AUTO_LENGTH, &resourceName); + if (status != napi_ok) { + AIP_HILOGE(" napi_create_string_utf8 failed. status: %{public}d", status); + return false; + } + status = napi_create_async_work(env, nullptr, resourceName, CloseExecutionCB, CloseCompleteCB, + static_cast<void *>(asyncClose), &asyncClose->asyncWork); + if (status != napi_ok) { + AIP_HILOGE("napi_create_async_work failed. status: %{public}d", status); + return false; + } + status = napi_queue_async_work_with_qos(env, asyncClose->asyncWork, napi_qos_default); + if (status != napi_ok) { + AIP_HILOGE("napi_queue_async_work_with_qos failed. status: %{public}d", status); + napi_delete_async_work(env, asyncClose->asyncWork); + return false; + } + return true; +} + +void RAGSessionNapi::CloseExecutionCB(napi_env env, void *data) +{ + auto *asyncClose = static_cast<AsyncStreamRun *>(data); + auto runAipCoreManagerPtr = asyncClose->sessionNapi->aipAipCoreManager_; + int32_t result = runAipCoreManagerPtr->ReleaseRAGSession(); + asyncClose->ret = result; + AIP_HILOGD("ReleaseRAGAgent result: %{public}d", asyncClose->ret); +} + +void RAGSessionNapi::CloseCompleteCB(napi_env env, napi_status status, void *data) +{ + AsyncStreamRun *asyncClose = static_cast<AsyncStreamRun *>(data); + auto ret = asyncClose->ret; + if (ret != ERR_OK) { + napi_value result = nullptr; + if (ret == DEVICE_EXCEPTION) { + ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "CloseCompleteCB failed", result); + } else { + int32_t errCode = ConvertErrCodeNative2Ts(ret); + ThrowIntelligenceErrByPromise(env, errCode, "CloseCompleteCB failed", result); + } + napi_reject_deferred(env, asyncClose->deferred, result); + } else { + napi_value undefined; + napi_get_undefined(env, &undefined); + napi_resolve_deferred(env, asyncClose->deferred, undefined); + } + status = napi_delete_async_work(env, asyncClose->asyncWork); + if (status != napi_ok) { + AIP_HILOGE("napi_delete_async_work failed. status: %{public}d", status); + } + if (asyncClose->sessionNapi != nullptr) { + delete asyncClose->sessionNapi->aipAipCoreManager_; + } + delete asyncClose->sessionNapi; + delete asyncClose; + AIP_HILOGI("Rag session close success."); +} + +napi_status RAGSessionNapi::ParseStreamRunArgs(napi_env env, napi_callback_info info, std::string &question, + OptionStruct &option, RAGSessionNapi **sessionNapi) +{ + napi_value argv[STREAM_RUN_ARG_COUNT] = { nullptr }; + size_t argc = STREAM_RUN_ARG_COUNT; + napi_value jsThis = nullptr; + napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr); + if (status != napi_ok) { + ThrowIntelligenceErr(env, INNER_ERROR, "napi_get_cb_info failed."); + return status; + } + if (argc != STREAM_RUN_ARG_COUNT) { + ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Param count error."); + return napi_invalid_arg; + } + status = AipNapiUtils::Convert2Value(env, argv[STREAM_RUN_QUESTION_ARG], question); + if (status != napi_ok) { + ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Parse question failed."); + return status; + } + status = AipNapiUtils::Convert2Value(env, argv[STREAM_RUN_OPTION_ARG], option); + if (status != napi_ok) { + ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Parse option failed."); + return status; + } + napi_valuetype valueType = napi_undefined; + napi_typeof(env, argv[STREAM_RUN_CALLBACK_ARG], &valueType); + napi_ref callbackRef = nullptr; + if (valueType == napi_function) { + napi_create_reference(env, argv[STREAM_RUN_CALLBACK_ARG], 1, &callbackRef); + } else { + ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Parse callback failed."); + } + status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(sessionNapi)); + if (status != napi_ok || (*sessionNapi) == nullptr || (*sessionNapi)->aipAipCoreManager_ == nullptr) { + ThrowIntelligenceErr(env, RAG_E_RAG_ALREADY_CLOSED, "Session is already closed."); + return napi_invalid_arg; + } + napi_ref thisJsRef = nullptr; + status = napi_create_reference(env, jsThis, 1, &thisJsRef); + if (status != napi_ok) { + return status; + } + (*sessionNapi)->env_ = env; + (*sessionNapi)->ref_ = callbackRef; + (*sessionNapi)->thisJsRef_ = thisJsRef; + return napi_ok; +} + +napi_value RAGSessionNapi::StreamRun(napi_env env, napi_callback_info info) +{ + DATA_INTELLIGENCE_HITRACE(std::string(__FUNCTION__)); + std::string question; + OptionStruct option = { .answerWithRetrievalItem = false }; + RAGSessionNapi *sessionNapi = {0}; + + napi_status status = ParseStreamRunArgs(env, info, question, option, &sessionNapi); + if (status != napi_ok) { + return nullptr; + } + + napi_value promise = nullptr; + napi_deferred deferred = nullptr; + status = napi_create_promise(env, &deferred, &promise); + if (status != napi_ok) { + ThrowIntelligenceErr(env, INNER_ERROR, "create promise failed."); + return nullptr; + } + + auto asyncStreamRun = new (std::nothrow) AsyncStreamRun { + .asyncWork = nullptr, + .deferred = deferred, + .sessionNapi = sessionNapi, + .question = question, + .option = option, + }; + if (asyncStreamRun == nullptr) { + ThrowIntelligenceErr(env, INNER_ERROR, "Allocate memory failed."); + return nullptr; + } + if (!CreateAsyncStreamRunExecution(env, asyncStreamRun)) { + delete asyncStreamRun; + ThrowIntelligenceErr(env, INNER_ERROR, "CreateAsyncStreamRunExecution failed"); + } + return promise; +} + +bool RAGSessionNapi::CreateAsyncStreamRunExecution(napi_env env, AsyncStreamRun *asyncStreamRun) +{ + napi_value resourceName; + napi_status status = napi_create_string_utf8(env, "StreamRun", NAPI_AUTO_LENGTH, &resourceName); + if (status != napi_ok) { + AIP_HILOGE(" napi_create_string_utf8 failed. status: %{public}d", status); + return false; + } + status = napi_create_async_work(env, nullptr, resourceName, StreamRunExecutionCB, StreamRunCompleteCB, + static_cast<void *>(asyncStreamRun), &asyncStreamRun->asyncWork); + if (status != napi_ok) { + AIP_HILOGE("napi_create_async_work failed"); + return false; + } + status = napi_queue_async_work_with_qos(env, asyncStreamRun->asyncWork, napi_qos_default); + if (status != napi_ok) { + AIP_HILOGE("napi_queue_async_work_with_qos failed. status: %{public}d", status); + napi_delete_async_work(env, asyncStreamRun->asyncWork); + return false; + } + return true; +} + +void RAGSessionNapi::StreamRunExecutionCB(napi_env env, void *data) +{ + AsyncStreamRun *asyncStreamRun = static_cast<AsyncStreamRun *>(data); + auto question = asyncStreamRun->question; + auto option = asyncStreamRun->option; + auto sessionNapi = asyncStreamRun->sessionNapi; + std::function<void(StreamStruct, int32_t)> callBackFunction = + [sessionNapi](const StreamStruct &stream, const int32_t errorCode) { + AIP_HILOGD("streamRun callback result: %{public}d", errorCode); + StreamRunCallbackExecute(sessionNapi, stream, errorCode); + }; + int32_t result = sessionNapi->aipAipCoreManager_->RAGSessionStreamRun(question, option, callBackFunction); + AIP_HILOGD("runAipCoreManagerPtr->StreamRun result: %{public}d", result); + asyncStreamRun->ret = result; +} + +void RAGSessionNapi::StreamRunCompleteCB(napi_env env, napi_status status, void *data) +{ + AsyncStreamRun *asyncStreamRun = static_cast<AsyncStreamRun *>(data); + auto ret = asyncStreamRun->ret; + if (ret != ERR_OK) { + napi_value result = nullptr; + if (ret == DEVICE_EXCEPTION) { + ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "StreamRunCompleteCB failed", result); + } else { + int32_t errCode = ConvertErrCodeNative2Ts(ret); + ThrowIntelligenceErrByPromise(env, errCode, "StreamRunCompleteCB failed", result); + } + napi_reject_deferred(env, asyncStreamRun->deferred, result); + } else { + napi_value undefined; + napi_get_undefined(env, &undefined); + napi_resolve_deferred(env, asyncStreamRun->deferred, undefined); + } + status = napi_delete_async_work(env, asyncStreamRun->asyncWork); + if (status != napi_ok) { + AIP_HILOGE("napi_delete_async_work failed."); + } + delete asyncStreamRun; +} + +void RAGSessionNapi::StreamRunCallbackJSExecute(StreamRunCallbackWorkParam *workParam) +{ + auto env = workParam->env; + auto ref = workParam->ref; + auto thisJsRef = workParam->thisJsRef; + auto errCode = workParam->errCode; + napi_value thisJs; + if (thisJsRef == nullptr) { + AIP_HILOGE("thisJs is nullptr"); + napi_get_undefined(env, &thisJs); + } else { + napi_status refStatus = napi_get_reference_value(env, thisJsRef, &thisJs); + if (refStatus != napi_ok) { + AIP_HILOGE("js this get failed. ret: %{public}d", refStatus); + napi_get_undefined(env, &thisJs); + } + } + napi_value errorNapi; + napi_value streamNapi; + if (errCode == 0) { + napi_get_undefined(env, &errorNapi); + napi_status status = AipNapiUtils::Convert2JSValue(env, workParam->stream, streamNapi); + if (status != napi_ok) { + AIP_HILOGE("stream struct Convert2JSValue failed. ret: %{public}d", status); + return; + } + } else { + ThrowIntelligenceErrByPromise(env, ConvertErrCodeNative2Ts(errCode), + "streamRunCallbackWorkerFunc failed", errorNapi); + napi_get_undefined(env, &streamNapi); + } + + const napi_value argv[] = { errorNapi, streamNapi }; + size_t argc = 2; + + napi_value callback; + napi_status status = napi_get_reference_value(env, ref, &callback); + if (status != napi_ok) { + AIP_HILOGE("js callback function get failed. ret: %{public}d", status); + return; + } + status = napi_call_function(env, thisJs, callback, argc, argv, nullptr); + if (status != napi_ok) { + AIP_HILOGE("js callback function call failed. ret: %{public}d", status); + } +} + +void RAGSessionNapi::StreamRunCallbackEventFunc(StreamRunCallbackWorkParam *workParam) +{ + if (workParam == nullptr) { + AIP_HILOGE("workParam is nullptr"); + return; + } + if (workParam->env == nullptr || workParam->ref == nullptr) { + AIP_HILOGE("streamRun callback work param is null"); + delete workParam; + workParam = nullptr; + return; + } + napi_handle_scope scope = nullptr; + napi_open_handle_scope(workParam->env, &scope); + if (scope == nullptr) { + AIP_HILOGE("scope open failed. scope is nullptr"); + return; + } + + StreamRunCallbackJSExecute(workParam); + + napi_close_handle_scope(workParam->env, scope); + delete workParam; + workParam = nullptr; +} + +void RAGSessionNapi::StreamRunCallbackExecute(RAGSessionNapi *sessionNapi, StreamStruct stream, int32_t errCode) +{ + if (sessionNapi == nullptr || sessionNapi->env_ == nullptr || sessionNapi->ref_ == nullptr) { + AIP_HILOGE("sessionNapi is nullptr: %{public}d", sessionNapi == nullptr); + return; + } + auto env = sessionNapi->env_; + auto ref = sessionNapi->ref_; + auto thisJs = sessionNapi->thisJsRef_; + auto *workParam = new (std::nothrow) StreamRunCallbackWorkParam { + std::move(stream), + errCode, + env, + ref, + thisJs, + std::make_shared<ThreadLockInfo>(), + }; + if (workParam == nullptr) { + AIP_HILOGE("WorkParam is nullptr"); + return; + } + napi_status status = napi_send_event(env, [workParam] { + StreamRunCallbackEventFunc(workParam); + }, napi_eprio_high); + if (status != napi_ok) { + AIP_HILOGE("napi_send_event running failed, status: %{public}d", status); + delete workParam; + workParam = nullptr; + } +} +} // namespace DataIntelligence +} // namespace OHOS diff --git a/udmf/framework/jskitsimpl/intelligence/retrieval_napi.cpp b/udmf/framework/jskitsimpl/intelligence/retrieval_napi.cpp deleted file mode 100644 index a442ebd5..00000000 --- a/udmf/framework/jskitsimpl/intelligence/retrieval_napi.cpp +++ /dev/null @@ -1,370 +0,0 @@ -/* - * 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 "retrieval_napi.h" - -#include <dlfcn.h> -#include <memory> -#include <node_api.h> -#include <string> - -#include "aip_log.h" -#include "aip_napi_error.h" -#include "aip_napi_utils.h" -#include "i_aip_core_manager_impl.h" - -#undef LOG_TAG -#define LOG_TAG "RetrievalNapi" - -namespace OHOS { -namespace DataIntelligence { -namespace { -const int32_t ERR_OK = 0; -constexpr const char *AIP_MANAGER_PATH = "libaip_core.z.so"; -} // namespace - -AipCoreManagerHandle RetrievalNapi::retrievalAipCoreMgrHandle_{}; - -RetrievalNapi::RetrievalNapi() : env_(nullptr) {} - -RetrievalNapi::~RetrievalNapi() -{ - AipNapiUtils::UnLoadAlgoLibrary(retrievalAipCoreMgrHandle_); -} - -napi_status InitEnum(napi_env env, napi_value exports) -{ - napi_value channelTypeEnum; - napi_status status = napi_create_object(env, &channelTypeEnum); - LOG_ERROR_RETURN(status == napi_ok, "create napi object fail.", napi_invalid_arg); - AipNapiUtils::SetInt32Property(env, channelTypeEnum, TsChannelType::VECTOR_DATABASE, "VECTOR_DATABASE"); - AipNapiUtils::SetInt32Property(env, channelTypeEnum, TsChannelType::INVERTED_INDEX_DATABASE, - "INVERTED_INDEX_DATABASE"); - AipNapiUtils::SetPropertyName(env, exports, "ChannelType", channelTypeEnum); - - napi_value operatorEnum; - status = napi_create_object(env, &operatorEnum); - LOG_ERROR_RETURN(status == napi_ok, "create napi object fail.", napi_invalid_arg); - AipNapiUtils::SetStringProperty(env, operatorEnum, "=", "OP_EQ"); - AipNapiUtils::SetStringProperty(env, operatorEnum, "!=", "OP_NE"); - AipNapiUtils::SetStringProperty(env, operatorEnum, "<", "OP_LT"); - AipNapiUtils::SetStringProperty(env, operatorEnum, "<=", "OP_LE"); - AipNapiUtils::SetStringProperty(env, operatorEnum, ">", "OP_GT"); - AipNapiUtils::SetStringProperty(env, operatorEnum, ">=", "OP_GE"); - AipNapiUtils::SetStringProperty(env, operatorEnum, "IN", "OP_IN"); - AipNapiUtils::SetStringProperty(env, operatorEnum, "NOT_IN", "OP_NOT_IN"); - AipNapiUtils::SetStringProperty(env, operatorEnum, "BETWEEN", "OP_BETWEEN"); - AipNapiUtils::SetStringProperty(env, operatorEnum, "LIKE", "OP_LIKE"); - AipNapiUtils::SetStringProperty(env, operatorEnum, "NOT_LIKE", "OP_NOT_LIKE"); - AipNapiUtils::SetPropertyName(env, exports, "Operator", operatorEnum); - - napi_value rerankTypeEnum; - status = napi_create_object(env, &rerankTypeEnum); - LOG_ERROR_RETURN(status == napi_ok, "create napi object fail.", napi_invalid_arg); - AipNapiUtils::SetInt32Property(env, rerankTypeEnum, TsRerankType::RRF, "RRF"); - AipNapiUtils::SetInt32Property(env, rerankTypeEnum, TsRerankType::FUSION_SCORE, "FUSION_SCORE"); - AipNapiUtils::SetPropertyName(env, exports, "RerankType", rerankTypeEnum); - - napi_value similarityLevelEnum; - status = napi_create_object(env, &similarityLevelEnum); - LOG_ERROR_RETURN(status == napi_ok, "create napi object fail.", napi_invalid_arg); - AipNapiUtils::SetInt32Property(env, similarityLevelEnum, TsSimilarityLevel::LOW, "LOW"); - AipNapiUtils::SetInt32Property(env, similarityLevelEnum, TsSimilarityLevel::MEDIUM, "MEDIUM"); - AipNapiUtils::SetInt32Property(env, similarityLevelEnum, TsSimilarityLevel::HIGH, "HIGH"); - AipNapiUtils::SetPropertyName(env, exports, "SimilarityLevel", similarityLevelEnum); - return napi_ok; -} - -napi_value RetrievalNapi::Init(napi_env env, napi_value exports) -{ - AIP_HILOGI("Init retrieval start."); - napi_property_descriptor desc[] = { - DECLARE_NAPI_FUNCTION("getRetriever", GetRetriever), - }; - napi_status status = napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); - if (status != napi_ok) { - AIP_HILOGE("define properties fail, status = %{public}d", status); - return nullptr; - } - status = InitEnum(env, exports); - LOG_ERROR_RETURN(status == napi_ok, "InitEnum fail.", nullptr); - return exports; -} - -napi_value RetrievalNapi::GetRetriever(napi_env env, napi_callback_info info) -{ - AIP_HILOGD("Enter"); - napi_value args[1] = { nullptr }; - size_t argc = 1; - napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - if (status != napi_ok) { - ThrowIntelligenceErr(env, INNER_ERROR, "napi_get_cb_info failed."); - return nullptr; - } - RetrievalConfigStruct retrievalConfig; - status = AipNapiUtils::Convert2Value(env, args[0], retrievalConfig); - if (status != napi_ok) { - ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Parse RetrievalConfig type failed."); - return nullptr; - } - napi_value promise = nullptr; - napi_deferred deferred = nullptr; - status = napi_create_promise(env, &deferred, &promise); - if (status != napi_ok) { - ThrowIntelligenceErr(env, INNER_ERROR, "create promise failed"); - return nullptr; - } - auto asyncGetRetriever = new AsyncGetRetriever{ - .asyncWork = nullptr, - .deferred = deferred, - .config = retrievalConfig, - }; - if (!CreateAsyncGetRetrieverExecution(env, asyncGetRetriever)) { - ThrowIntelligenceErr(env, INNER_ERROR, "create AsyncGetRetrieverExecution failed"); - delete asyncGetRetriever; - return nullptr; - } - return promise; -} - -bool RetrievalNapi::CreateAsyncGetRetrieverExecution(napi_env env, AsyncGetRetriever *asyncGetRetriever) -{ - AIP_HILOGD("Enter"); - napi_value resourceName; - napi_status status = napi_create_string_utf8(env, "GetRetriever", NAPI_AUTO_LENGTH, &resourceName); - if (status != napi_ok) { - AIP_HILOGE(" napi_create_string_utf8 failed."); - return false; - } - status = napi_create_async_work(env, nullptr, resourceName, GetRetrieverExecutionCB, GetRetrieverCompleteCB, - static_cast<void *>(asyncGetRetriever), &asyncGetRetriever->asyncWork); - if (status != napi_ok) { - AIP_HILOGE("napi_create_async_work failed."); - return false; - } - status = napi_queue_async_work_with_qos(env, asyncGetRetriever->asyncWork, napi_qos_default); - if (status != napi_ok) { - AIP_HILOGE("napi_queue_async_work_with_qos failed"); - return false; - } - return true; -} - -napi_value RetrievalNapi::WrapAipCoreManager(napi_env env, IAipCoreManager *retrievalAipCoreManager) -{ - napi_value result; - napi_status status = napi_create_object(env, &result); - if (status != napi_ok) { - return nullptr; - } - status = napi_wrap( - env, result, static_cast<void *>(retrievalAipCoreManager), - [](napi_env env, void *data, void *hint) { delete static_cast<IAipCoreManager *>(data); }, nullptr, nullptr); - if (status != napi_ok) { - AIP_HILOGE("napi_wrap aipCoreMangager failed, erroCode is %{public}d", status); - delete retrievalAipCoreManager; - return nullptr; - } - // 为 Retriever 对象添加 retrieve 方法 - napi_value retrieveFn; - status = napi_create_function(env, nullptr, NAPI_AUTO_LENGTH, Retrieve, nullptr, &retrieveFn); - if (status != napi_ok) { - return nullptr; - } - status = napi_set_named_property(env, result, "retrieveRdb", retrieveFn); - if (status != napi_ok) { - return nullptr; - } - return result; -} - -void RetrievalNapi::GetRetrieverExecutionCB(napi_env env, void *data) -{ - AIP_HILOGD("Enter"); - AsyncGetRetriever *asyncGetRetrieverdata = static_cast<AsyncGetRetriever *>(data); - auto config = asyncGetRetrieverdata->config; - IAipCoreManager *retrievalAipCoreManager = nullptr; - if (retrievalAipCoreMgrHandle_.create == nullptr) { - AipNapiUtils::LoadAlgoLibrary(AIP_MANAGER_PATH, retrievalAipCoreMgrHandle_, false); - } - if (retrievalAipCoreMgrHandle_.create != nullptr) { - AIP_HILOGI("Init retrieval by dlopen."); - retrievalAipCoreManager = retrievalAipCoreMgrHandle_.create(); - } - if (retrievalAipCoreManager == nullptr) { - AIP_HILOGI("Init retrieval by new."); - retrievalAipCoreManager = new IAipCoreManagerImpl(); - } - int32_t ret = retrievalAipCoreManager->InitRetriever(config); - asyncGetRetrieverdata->ret = ret; - if (ret != ERR_OK) { - AIP_HILOGE("init Retriever failed, erroCode is %{public}d", ret); - delete retrievalAipCoreManager; - return; - } - asyncGetRetrieverdata->retrievalAipCoreManagerPtr = retrievalAipCoreManager; -} - -void RetrievalNapi::GetRetrieverCompleteCB(napi_env env, napi_status status, void *data) -{ - AIP_HILOGD("Enter"); - AsyncGetRetriever *asyncGetRetrieverdata = static_cast<AsyncGetRetriever *>(data); - auto ret = asyncGetRetrieverdata->ret; - napi_value result = nullptr; - if (ret != ERR_OK) { - if (ret == DEVICE_EXCEPTION) { - ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "GetRetrieverCompleteCB failed", result); - } else { - ThrowIntelligenceErrByPromise(env, INNER_ERROR, "GetRetrieverCompleteCB failed", result); - } - napi_reject_deferred(env, asyncGetRetrieverdata->deferred, result); - } else { - result = WrapAipCoreManager(env, asyncGetRetrieverdata->retrievalAipCoreManagerPtr); - if (result == nullptr) { - ThrowIntelligenceErrByPromise(env, INNER_ERROR, "GetRetrieverCompleteCB failed", result); - napi_reject_deferred(env, asyncGetRetrieverdata->deferred, result); - } - status = napi_resolve_deferred(env, asyncGetRetrieverdata->deferred, result); - if (status != napi_ok) { - AIP_HILOGE(" napi_resolve_deferred failed"); - } - } - status = napi_delete_async_work(env, asyncGetRetrieverdata->asyncWork); - if (status != napi_ok) { - AIP_HILOGE("napi_delete_async_work failed"); - } - delete asyncGetRetrieverdata; -} - -bool RetrievalNapi::CreateAsyncRetrieveExecution(napi_env env, AsyncRetrieve *asyncRetrieve) -{ - AIP_HILOGD("Enter"); - napi_value resourceName; - napi_status status = napi_create_string_utf8(env, "Retrieve", NAPI_AUTO_LENGTH, &resourceName); - if (status != napi_ok) { - AIP_HILOGE(" napi_create_string_utf8 failed."); - return false; - } - - status = napi_create_async_work(env, nullptr, resourceName, RetrieveExecutionCB, RetrieveCompleteCB, - static_cast<void *>(asyncRetrieve), &asyncRetrieve->asyncWork); - if (status != napi_ok) { - AIP_HILOGE("napi_create_async_work failed"); - return false; - } - - status = napi_queue_async_work_with_qos(env, asyncRetrieve->asyncWork, napi_qos_default); - if (status != napi_ok) { - AIP_HILOGE("napi_queue_async_work_with_qos failed"); - return false; - } - return true; -} - -void RetrievalNapi::RetrieveExecutionCB(napi_env env, void *data) -{ - AIP_HILOGD("Enter"); - AsyncRetrieve *asyncRetrieve = static_cast<AsyncRetrieve *>(data); - auto retrievalCondition = asyncRetrieve->retrievalCondition; - auto query = asyncRetrieve->query; - auto retrievalAipCoreManagerPtr = asyncRetrieve->retrievalAipCoreManagerPtr; - RetrievalResponseStruct retrievalResponse; - int32_t result = retrievalAipCoreManagerPtr->Retrieve(query, retrievalCondition, retrievalResponse); - AIP_HILOGI("execute retrieve."); - asyncRetrieve->ret = result; - asyncRetrieve->retrievalResponse = retrievalResponse; -} - -void RetrievalNapi::RetrieveCompleteCB(napi_env env, napi_status status, void *data) -{ - AIP_HILOGD("Enter"); - AsyncRetrieve *asyncRetrieve = static_cast<AsyncRetrieve *>(data); - auto ret = asyncRetrieve->ret; - napi_value result = nullptr; - if (ret != ERR_OK) { - if (ret == DEVICE_EXCEPTION) { - ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "GetRetrieverCompleteCB failed", result); - } else { - int32_t errCode = ConvertErrCodeNative2Ts(ret); - ThrowIntelligenceErrByPromise(env, errCode, "GetRetrieverCompleteCB failed", result); - } - napi_reject_deferred(env, asyncRetrieve->deferred, result); - } else { - status = AipNapiUtils::Convert2JSValue(env, asyncRetrieve->retrievalResponse, result); - if (status != napi_ok) { - ThrowIntelligenceErrByPromise(env, INNER_ERROR, "convert RetrievalResponse to js value failed.", result); - napi_reject_deferred(env, asyncRetrieve->deferred, result); - } else { - napi_resolve_deferred(env, asyncRetrieve->deferred, result); - } - } - status = napi_delete_async_work(env, asyncRetrieve->asyncWork); - if (status != napi_ok) { - AIP_HILOGE("napi_delete_async_work failed."); - } - delete asyncRetrieve; -} - - -napi_value RetrievalNapi::Retrieve(napi_env env, napi_callback_info info) -{ - AIP_HILOGI("Retrieve being call."); - napi_value args[2] = { nullptr }; - size_t argc = 2; - napi_value jsThis = nullptr; - napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr); - if (status != napi_ok) { - ThrowIntelligenceErr(env, INNER_ERROR, "napi_get_cb_info failed."); - return nullptr; - } - std::string query; - status = AipNapiUtils::Convert2Value(env, args[0], query); - if (status != napi_ok) { - ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Failed to convert the field query."); - return nullptr; - } - RetrievalConditionStruct retrievalCondition; - status = AipNapiUtils::Convert2Value(env, args[1], retrievalCondition); - if (status != napi_ok) { - ThrowIntelligenceErr(env, PARAM_EXCEPTION, "Parse RetrievalCondition failed."); - return nullptr; - } - napi_value promise = nullptr; - napi_deferred deferred = nullptr; - status = napi_create_promise(env, &deferred, &promise); - if (status != napi_ok) { - ThrowIntelligenceErr(env, INNER_ERROR, "create promise failed."); - return nullptr; - } - IAipCoreManager *retrievalAipCoreManagerPtr; - status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&retrievalAipCoreManagerPtr)); - if (status != napi_ok) { - return nullptr; - } - auto asyncRetrieve = new AsyncRetrieve{ - .asyncWork = nullptr, - .deferred = deferred, - .query = query, - .retrievalCondition = retrievalCondition, - .retrievalAipCoreManagerPtr = retrievalAipCoreManagerPtr - }; - if (!CreateAsyncRetrieveExecution(env, asyncRetrieve)) { - ThrowIntelligenceErr(env, INNER_ERROR, "CreateAsyncRetrieveExecution failed"); - delete asyncRetrieve; - } - return promise; -} -} // namespace DataIntelligence -} // namespace OHOS diff --git a/udmf/framework/jskitsimpl/intelligence/text_embedding_napi.cpp b/udmf/framework/jskitsimpl/intelligence/text_embedding_napi.cpp index 4c708073..fd0b961e 100644 --- a/udmf/framework/jskitsimpl/intelligence/text_embedding_napi.cpp +++ b/udmf/framework/jskitsimpl/intelligence/text_embedding_napi.cpp @@ -102,6 +102,7 @@ TextEmbeddingNapi::~TextEmbeddingNapi() AIP_HILOGI("Enter"); AipNapiUtils::UnLoadAlgoLibrary(textAipCoreMgrHandle_); delete textAipCoreManager_; + textAipCoreManager_ = nullptr; } static napi_value StartInit(napi_env env, napi_value exports, struct TextEmbeddingConstructorInfo info) @@ -151,7 +152,7 @@ napi_value TextEmbeddingNapi::Init(napi_env env, napi_value exports) if (textAipCoreMgrHandle_.pAipManager != nullptr) { textAipCoreManager_ = AipNapiUtils::GetAlgoObj(textAipCoreMgrHandle_); } else { - textAipCoreManager_ = new IAipCoreManagerImpl(); + textAipCoreManager_ = new (std::nothrow) IAipCoreManagerImpl(); } if (textAipCoreManager_ == nullptr) { @@ -258,11 +259,16 @@ napi_value TextEmbeddingNapi::GetTextEmbeddingModel(napi_env env, napi_callback_ return nullptr; } - auto asyncGetTextEmbeddingModelData = new AsyncGetTextEmbeddingModelData{ + auto asyncGetTextEmbeddingModelData = new (std::nothrow) AsyncGetTextEmbeddingModelData{ .asyncWork = nullptr, .deferred = deferred, .config = textModelConfig, }; + if (asyncGetTextEmbeddingModelData == nullptr) { + AIP_HILOGE("new asyncGetTextEmbeddingModelData error."); + ThrowIntelligenceErr(env, INNER_ERROR, "new asyncGetTextEmbeddingModelData failed"); + return nullptr; + } if (!CreateAsyncTextModelExecution(env, asyncGetTextEmbeddingModelData)) { ThrowIntelligenceErr(env, PARAM_EXCEPTION, "create AsyncTextModelExecution failed"); @@ -285,7 +291,9 @@ bool TextEmbeddingNapi::ParseModelConfig(napi_env env, napi_value *args, size_t return false; } - napi_value version, isNPUAvailable, cachePath; + napi_value version; + napi_value isNPUAvailable; + napi_value cachePath; napi_status status = napi_get_named_property(env, args[ARG_0], "version", &version); if (status != napi_ok) { AIP_HILOGE("napi get version property failed"); @@ -397,6 +405,7 @@ void TextEmbeddingNapi::GetTextEmbeddingModelCompleteCB(napi_env env, napi_statu if (status != napi_ok) { AIP_HILOGE("napi_new_instance failed"); napi_get_undefined(env, &result); + delete modelData; return; } @@ -451,10 +460,6 @@ napi_value TextEmbeddingNapi::SplitText(napi_env env, napi_callback_info info) AipNapiUtils::TransJsToDouble(env, cfgOverlap, configOverlap); AIP_HILOGD("string strArg: %{public}d", configSize); AIP_HILOGD("string strArg: %{public}f", configOverlap); - if (configSize <= NUM_0 || configOverlap < NUM_0 || configOverlap >= NUM_1) { - ThrowIntelligenceErr(env, PARAM_EXCEPTION, "The parameter value range is incorrect"); - return nullptr; - } napi_value promise = nullptr; napi_deferred deferred = nullptr; @@ -464,6 +469,17 @@ napi_value TextEmbeddingNapi::SplitText(napi_env env, napi_callback_info info) return nullptr; } + if (!textAipCoreManager_->CheckDeviceType()) { + napi_value value = nullptr; + ThrowIntelligenceErrByPromise(env, DEVICE_EXCEPTION, "SplitText failed", value); + napi_reject_deferred(env, deferred, value); + return promise; + } + if (configSize <= NUM_0 || configOverlap < NUM_0 || configOverlap >= NUM_1) { + ThrowIntelligenceErr(env, PARAM_EXCEPTION, "The parameter value range is incorrect"); + return nullptr; + } + if (!SplitTextAsyncExecution(env, deferred, strArg, configSize, configOverlap)) { ThrowIntelligenceErr(env, PARAM_EXCEPTION, "create split text async execution failed"); return nullptr; @@ -476,13 +492,17 @@ bool TextEmbeddingNapi::SplitTextAsyncExecution(napi_env env, napi_deferred defe int32_t configSize, double configOverlap) { AIP_HILOGD("Enter"); - auto splitTextCallbackData = new SplitTextCallbackData{ + auto splitTextCallbackData = new (std::nothrow) SplitTextCallbackData{ .asyncWork = nullptr, .deferred = deferred, .strArg = strArg, .configSize = configSize, .configOverlap = configOverlap, }; + if (splitTextCallbackData == nullptr) { + AIP_HILOGE("new splitTextCallbackData error."); + return false; + } napi_value resourceName; napi_status status = napi_create_string_utf8(env, "SplitText", NAPI_AUTO_LENGTH, &resourceName); @@ -610,6 +630,10 @@ napi_value TextEmbeddingNapi::GetEmbedding(napi_env env, napi_callback_info info ThrowIntelligenceErr(env, INNER_ERROR, "napi_get_cb_info failed"); return nullptr; } + if (valueType == napi_undefined || valueType == napi_null) { + ThrowIntelligenceErr(env, PARAM_EXCEPTION, "param is error"); + return nullptr; + } if (valueType == napi_string) { StringType(env, args[ARG_0], promise, deferred); } @@ -627,8 +651,6 @@ napi_value TextEmbeddingNapi::StringType(napi_env env, napi_value args, napi_val ThrowIntelligenceErr(env, PARAM_EXCEPTION, "TransJsToStr failed"); return nullptr; } - - AIP_HILOGI("string Arg: %{public}s", strArg.c_str()); if (!GetEmbeddingStringAsyncExecution(env, deferred, strArg)) { ThrowIntelligenceErr(env, INNER_ERROR, "GetEmbeddingStringAsyncExecution failed"); return nullptr; @@ -640,11 +662,15 @@ napi_value TextEmbeddingNapi::StringType(napi_env env, napi_value args, napi_val bool TextEmbeddingNapi::GetEmbeddingStringAsyncExecution(napi_env env, napi_deferred deferred, std::string strArg) { AIP_HILOGD("Enter"); - auto textStringCallbackData = new TextStringCallbackData{ + auto textStringCallbackData = new (std::nothrow) TextStringCallbackData{ .asyncWork = nullptr, .deferred = deferred, .strArg = strArg, }; + if (textStringCallbackData == nullptr) { + AIP_HILOGE("new textStringCallbackData error."); + return false; + } napi_value resourceName; napi_status status = napi_create_string_utf8(env, "textStringEmbedding", NAPI_AUTO_LENGTH, &resourceName); @@ -786,11 +812,15 @@ bool TextEmbeddingNapi::GetEmbeddingArrayAsyncExecution(napi_env env, napi_defer std::vector<std::string> text) { AIP_HILOGD("Enter"); - auto textArrayCallbackData = new TextArrayCallbackData{ + auto textArrayCallbackData = new (std::nothrow) TextArrayCallbackData{ .asyncWork = nullptr, .deferred = deferred, .text = text, }; + if (textArrayCallbackData == nullptr) { + AIP_HILOGE("new textArrayCallbackData error."); + return false; + } napi_value resourceName; napi_status status = napi_create_string_utf8(env, "textArrayEmbedding", NAPI_AUTO_LENGTH, &resourceName); @@ -919,10 +949,14 @@ napi_value TextEmbeddingNapi::LoadModel(napi_env env, napi_callback_info info) bool TextEmbeddingNapi::LoadAsyncExecution(napi_env env, napi_deferred deferred) { AIP_HILOGD("Enter"); - auto loadCallbackData = new LoadCallbackData{ + auto loadCallbackData = new (std::nothrow) LoadCallbackData{ .asyncWork = nullptr, .deferred = deferred, }; + if (loadCallbackData == nullptr) { + AIP_HILOGE("new loadCallbackData error."); + return false; + } napi_value resourceName; napi_status status = napi_create_string_utf8(env, "textLoad", NAPI_AUTO_LENGTH, &resourceName); @@ -1030,10 +1064,14 @@ napi_value TextEmbeddingNapi::ReleaseModel(napi_env env, napi_callback_info info bool TextEmbeddingNapi::ReleaseAsyncExecution(napi_env env, napi_deferred deferred) { AIP_HILOGD("Enter"); - auto releaseCallbackData = new ReleaseCallbackData{ + auto releaseCallbackData = new (std::nothrow) ReleaseCallbackData{ .asyncWork = nullptr, .deferred = deferred, }; + if (releaseCallbackData == nullptr) { + AIP_HILOGE("new releaseCallbackData error."); + return false; + } napi_value resourceName; napi_status status = napi_create_string_utf8(env, "textLoad", NAPI_AUTO_LENGTH, &resourceName); diff --git a/relational_store/test/js/gdb/performance/src/BUILD.gn b/udmf/framework/jskitsimpl/test/BUILD.gn similarity index 68% rename from relational_store/test/js/gdb/performance/src/BUILD.gn rename to udmf/framework/jskitsimpl/test/BUILD.gn index f5bc4ca2..7863903b 100644 --- a/relational_store/test/js/gdb/performance/src/BUILD.gn +++ b/udmf/framework/jskitsimpl/test/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (C) 2024 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,12 +13,8 @@ import("//build/test.gni") -module_output_path = "relational_store/relational_store/gdb_perf" - -ohos_js_unittest("GdbPerfJsTest") { - module_out_path = module_output_path - - hap_profile = "../config.json" - - certificate_profile = "../openharmony_sx.p7b" +group("stage_unittest") { + testonly = true + deps = [ "unittest/stage_unittest/udmf/src:stage_unittest" ] } +############################################################################### diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/AppScope/app.json b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/AppScope/app.json new file mode 100644 index 00000000..af96a2e6 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/AppScope/app.json @@ -0,0 +1,21 @@ +{ + "app":{ + "bundleName":"com.example.myapplication", + "vendor":"huawei", + "versionCode":1000000, + "versionName":"1.0.0", + "debug":false, + "icon":"", + "label":"$string:app_name", + "description":"$string:description_application", + "distributedNotificationEnabled":true, + "keepAlive":true, + "singleUser":true, + "minAPIVersion":8, + "targetAPIVersion":8, + "car":{ + "apiCompatibleVersion":8, + "singleUser":false + } + } +} diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/AppScope/resources/base/element/string.json b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/AppScope/resources/base/element/string.json new file mode 100644 index 00000000..ee69f9a8 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string":[ + { + "name":"app_name", + "value":"ohosProject" + } + ] +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/BUILD.gn b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/BUILD.gn new file mode 100644 index 00000000..1fb56c20 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/BUILD.gn @@ -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. + +import("//build/test.gni") + +ohos_js_stage_unittest("stageUdmfJsTest") { + hap_profile = "entry/src/main/module.json" + deps = [ + ":stageprejstest_js_assets", + ":stageprejstest_resources", + ] + ets2abc = true + certificate_profile = "signature/openharmony_sx.p7b" + hap_name = "stageUdmfJsTest" + subsystem_name = "distributeddatamgr" + part_name = "udmf" + module_out_path = "udmf/udmf/jsStage" +} + +ohos_app_scope("stageprejstest_app_profile") { + app_profile = "AppScope/app.json" + sources = [ "AppScope/resources" ] +} + +ohos_js_assets("stageprejstest_js_assets") { + source_dir = "entry/src/main/ets" +} + +ohos_resources("stageprejstest_resources") { + sources = [ "entry/src/main/resources" ] + deps = [ ":stageprejstest_app_profile" ] + hap_profile = "entry/src/main/module.json" +} + +group("stage_unittest") { + testonly = true + deps = [ ":stageUdmfJsTest" ] +} diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/Test.json b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/Test.json new file mode 100644 index 00000000..4d5f8f18 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/Test.json @@ -0,0 +1,27 @@ +{ + "description": "Configuration for hjunit demo Tests", + "driver": { + "type": "OHJSUnitTest", + "test-timeout": "180000", + "bundle-name": "com.example.myapplication", + "module-name": "testModule", + "shell-timeout": "600000", + "testcase-timeout": 70000 + }, + "kits": [ + { + "test-file-name": [ + "stageUdmfJsTest.hap" + ], + "type": "AppInstallKit", + "cleanup-apps": true + }, + { + "type": "ShellKit", + "teardown-command":[ + "bm uninstall -n com.example.myapplication" + ] + } + ] +} + diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/Application/AbilityStage.ts b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/Application/AbilityStage.ts new file mode 100644 index 00000000..13d01e24 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/Application/AbilityStage.ts @@ -0,0 +1,23 @@ +/* + * 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 AbilityStage from "@ohos.app.ability.AbilityStage" + +export default class MyAbilityStage extends AbilityStage { + onCreate() { + console.log('[Demo] MyAbilityStage onCreate'); + globalThis.stageOnCreateRun = 1; + globalThis.stageContext = this.context; + } +} diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/MainAbility.ts b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/MainAbility.ts new file mode 100644 index 00000000..1bb07abb --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/MainAbility.ts @@ -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. + */ +import UIAbilit from '@ohos.app.ability.UIAbility' + +export default class MainAbility extends UIAbilit { + onCreate(want, launchParam){ + // Ability is creating, initialize resources for this ability + console.log('[Demo] MainAbility onCreate'); + globalThis.abilityWant = want; + } + + onDestroy() { + // Ability is destroying, release resources for this ability + console.log('[Demo] MainAbility onDestroy'); + } + + onWindowStageCreate(windowStage) { + // Main window is created, set main page for this ability + console.log('[Demo] MainAbility onWindowStageCreate'); + globalThis.abilityContext = this.context; + windowStage.setUIContent(this.context, "MainAbility/pages/index/index", null); + } + + onWindowStageDestroy() { + //Main window is destroyed, release UI related resources + console.log('[Demo] MainAbility onWindowStageDestroy'); + } + + onForeground() { + // Ability has brought to foreground + console.log('[Demo] MainAbility onForeground'); + } + + onBackground() { + // Ability has back to background + console.log('[Demo] MainAbility onBackground'); + } +}; \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/pages/index/index.ets b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/pages/index/index.ets new file mode 100644 index 00000000..bfe98b75 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/pages/index/index.ets @@ -0,0 +1,55 @@ +/* + * 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 router from '@ohos.router'; + +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' +import { Hypium } from '@ohos/hypium' +import testsuite from '../../../test/List.test' + + +@Entry +@Component +struct Index { + + aboutToAppear(){ + console.info("start run testcase!!!!") + var abilityDelegator: any + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var abilityDelegatorArguments: any + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + console.info('start run testcase!!!') + Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) + } + + build() { + Flex({ direction:FlexDirection.Column, alignItems:ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text('Hello World') + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(25) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(() => {}) + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/pages/second/second.ets b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/pages/second/second.ets new file mode 100644 index 00000000..d2571b12 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/MainAbility/pages/second/second.ets @@ -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. + */ +import router from '@system.router'; + +@Entry +@Component +struct Second { + private content: string = "Second Page" + + build() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text(`${this.content}`) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('back to index') + .fontSize(20) + .fontWeight(FontWeight.Bold) + }.type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .onClick(() => { + router.back() + }) + } + .width('100%') + .height('100%') + } +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestAbility/TestAbility.ts b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestAbility/TestAbility.ts new file mode 100644 index 00000000..97971945 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestAbility/TestAbility.ts @@ -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. + */ +//OpenHarmary\vendor\unionman\unionpi_tiger\sample\app\distra-game\entry\src\ohosTest\ets\testability\TestAbility.ets +import UIAbility from '@ohos.app.ability.UIAbility' + +export default class TestAbility extends UIAbility { + onCreate(want, launchParam) { + console.log('TestAbility context' + this.context); + } + + onDestroy() { + console.log('TestAbility onDestroy'); + } + + onWindowStageCreate(windowStage) { + console.log('TestAbility onWindowStageCreate'); + windowStage.setUIContent(this.context, 'TestAbility/pages/index', null); + } + + onWindowStageDestroy() { + console.log('TestAbility onWindowStageDestroy'); + } + + onForeground() { + console.log('TestAbility onForeground'); + } + + onBackground() { + console.log('TestAbility onBackground'); + } +}; \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestAbility/pages/index.ets b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestAbility/pages/index.ets new file mode 100644 index 00000000..84a0667e --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestAbility/pages/index.ets @@ -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. + */ +import router from '@ohos.router'; + +@Entry +@Component +struct Index { + aboutToAppear() { + console.info('TestAbility index aboutToAppear') + } + @State message: string = 'Hello World' + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + Button() { + Text('next page') + .fontSize(20) + .fontWeight(FontWeight.Bold) + } + .type(ButtonType.Capsule) + .margin({ + top: 20 + }) + .backgroundColor('#0D9FFB') + .width('35%') + .height('5%') + .onClick(()=>{ }) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts new file mode 100644 index 00000000..cc360f1a --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/TestRunner/OpenHarmonyTestRunner.ts @@ -0,0 +1,72 @@ +/* + * 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 TestRunner from '@ohos.application.testRunner' +import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry' + +var abilityDelegator = undefined +var abilityDelegatorArguments = undefined + +function translateParamsToString(parameters) { + const keySet = new Set([ + '-s class', '-s notClass', '-s suite', '-s it', + '-s level', '-s testType', '-s size', '-s timeout' + ]) + let targetParams = ''; + for (const key in parameters) { + if (keySet.has(key)) { + targetParams = `${targetParams} ${key} ${parameters[key]}` + } + } + return targetParams.trim() +} + +async function onAbilityCreateCallback() { + console.log('onAbilityCreateCallback'); +} + +async function addAbilityMonitorCallback(err: any) { + console.info('addAbilityMonitorCallback : ' + JSON.stringify(err)); +} + +export default class OpenHarmonyTestRunner implements TestRunner { + constructor() { + } + + onPrepare() { + console.info("OpenHarmonyTestRunner OnPrepare "); + } + + async onRun() { + console.log('OpenHarmonyTestRunner onRun run') + abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() + abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() + var testAbilityName = abilityDelegatorArguments.bundleName + '.MainAbility' + let lMonitor = { + abilityName: testAbilityName, + onAbilityCreate: onAbilityCreateCallback, + }; + abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback) + var cmd = 'aa start -d 0 -a com.example.myapplication.MainAbility' + ' -b ' + abilityDelegatorArguments.bundleName + cmd += ' '+translateParamsToString(abilityDelegatorArguments.parameters) + console.info('cmd : '+ cmd) + abilityDelegator.executeShellCommand(cmd, + (err: any, d: any) => { + console.info('executeShellCommand : err : ' + JSON.stringify(err)); + console.info('executeShellCommand : data : ' + d.stdResult); + console.info('executeShellCommand : data : ' + d.exitCode); + }) + console.info('OpenHarmonyTestRunner onRun end'); + } +}; \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/List.test.ets b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/List.test.ets new file mode 100644 index 00000000..59fd8ce7 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/List.test.ets @@ -0,0 +1,24 @@ +/* + * 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 stageUdmfCallBackTest from './StageUdmfCallBacktest.ets'; +import stageUdmfPromiseTest from './StageUdmfPromisetest.ets'; +import StageUdmfFileMangerTest from './StageUdmfFileMangertest.ets'; + +export default function testsuite() { + stageUdmfCallBackTest(); + stageUdmfPromiseTest(); + StageUdmfFileMangerTest(); +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfCallBacktest.ets b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfCallBacktest.ets new file mode 100644 index 00000000..228cc65e --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfCallBacktest.ets @@ -0,0 +1,220 @@ +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' +import unifiedDataChannel from '@ohos.data.unifiedDataChannel'; +import uniformTypeDescriptor from '@ohos.data.uniformTypeDescriptor'; + +const TAG = "[udmfStageTest]" + +export default function stageUdmfCallbackJsTest() { + describe('stageUdmfCallbackJsTest', ():void =>{ + console.log(TAG + "*************Unit Test Begin*************"); + beforeAll(():void => { + console.log('stageUdmfCallbackJsTest TestAbility context' + globalThis.abilityContext); + console.info('beforeAll') + }) + afterAll(():void =>{ + console.info('afterAll') + }) + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_UnifiedDataCallbackJsAPITest_0100 + * @tc.name : unifiedDataChannel insertData callback interface test + * @tc.desc : unifiedDataChannel insertData callback interface test. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_UnifiedDataCallbackJsAPITest_0100', 0, (done) => { + let options: unifiedDataChannel.Options = {} + let plainText = new unifiedDataChannel.PlainText(); + plainText.textContent = 'this is textContent'; + let unifiedData = new unifiedDataChannel.UnifiedData(plainText); + try { + unifiedDataChannel.insertData(options, unifiedData, (err, data) => { + if (err === undefined) { + console.info(TAG + `data = ${data}, options = ${options}`); + expect(err === undefined).assertFail(); + done(); + } else { + console.error(TAG, `Failed, code is ${err.code},message is ${err.message} `); + expect(err !== null).assertFail(); + done(); + } + }) + } catch (error) { + console.error(TAG, `Failed to insertData0100 code is ${error.code},message is ${error.message} `); + expect(error.code).assertEqual('401'); + done(); + } + }); + + /** + * @tc.name UdmfTestVisibilityOwn + * @tc.desc insertData with visibility Own + * @tc.type: Function + * @tc.require: issueNumber + */ + it('UdmfTestVisibilityOwn', 1, (done) { + const TAG = 'UdmfTestVisibilityOwn:'; + console.info(TAG, 'start'); + try { + let options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.DATA_HUB, + visibility : unifiedDataChannel.Visibility.OWN_PROCESS }; + let content = "content"; + let plainText = new unifiedDataChannel.PlainText(); + plainText.textContent = content; + let unifiedData = new unifiedDataChannel.UnifiedData(plainText); + unifiedDataChannel.insertData(options, unifiedData).then((data) => { + console.info(TAG, `insert success. The key: ${data}`); + let options = { key: data }; + console.info(TAG, `query start. The options: ${JSON.stringify(options)}`); + unifiedDataChannel.queryData(options).then((data) => { + console.info(TAG, 'query success.'); + expect(data.length).assertEqual(1); + expect(data[0].getRecords()[0].textContent).assertEqual(content); + unifiedDataChannel.deleteData(options).then((data) => { + console.info(TAG, 'delete success.'); + expect(data.length).assertEqual(1); + done(); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfTestVisibilityAll + * @tc.desc insertData with visibility All + * @tc.type: Function + * @tc.require: issueNumber + */ + it('UdmfTestVisibilityAll', 1, (done) { + const TAG = 'UdmfTestVisibilityAll:'; + console.info(TAG, 'start'); + try { + let options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.DATA_HUB, + visibility : unifiedDataChannel.Visibility.ALL }; + let content = "content"; + let plainText = new unifiedDataChannel.PlainText(); + plainText.textContent = content; + let unifiedData = new unifiedDataChannel.UnifiedData(plainText); + unifiedDataChannel.insertData(options, unifiedData).then((data) => { + console.info(TAG, `insert success. The key: ${data}`); + let options = { key: data }; + console.info(TAG, `query start. The options: ${JSON.stringify(options)}`); + unifiedDataChannel.queryData(options).then((data) => { + console.info(TAG, 'query success.'); + expect(data.length).assertEqual(1); + expect(data[0].getRecords()[0].textContent).assertEqual(content); + unifiedDataChannel.deleteData(options).then((data) => { + console.info(TAG, 'delete success.'); + expect(data.length).assertEqual(1); + done(); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name UdmfTestVisibilityOther + * @tc.desc insertData with visibility other + * @tc.type: Function + * @tc.require: issueNumber + */ + it('UdmfTestVisibilityOther', 1, (done) { + const TAG = 'UdmfTestVisibilityOther:'; + console.info(TAG, 'start'); + try { + let reVisibility:unifiedDataChannel.Visibility = 5; + let options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.DATA_HUB, + visibility : reVisibility }; + let content = "content"; + let plainText = new unifiedDataChannel.PlainText(); + plainText.textContent = content; + let unifiedData = new unifiedDataChannel.UnifiedData(plainText); + unifiedDataChannel.insertData(options, unifiedData).then((data) => { + console.info(TAG, `insert success. The key: ${data}`); + let options = { key: data }; + console.info(TAG, `query start. The options: ${JSON.stringify(options)}`); + unifiedDataChannel.queryData(options).then((data) => { + console.info(TAG, 'query success.'); + expect(data.length).assertEqual(1); + expect(data[0].getRecords()[0].textContent).assertEqual(content); + unifiedDataChannel.deleteData(options).then((data) => { + console.info(TAG, 'delete success.'); + expect(data.length).assertEqual(1); + done(); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (err: BusinessError) { + console.error(TAG , err.code + err.message); + expect(err.code).assertEqual("401"); + done(); + } + console.info(TAG, 'end'); + }); + }) + console.log(TAG + "*************Unit Test End*************"); +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfFileMangertest.ets b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfFileMangertest.ets new file mode 100644 index 00000000..ed5dc311 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfFileMangertest.ets @@ -0,0 +1,1348 @@ +/* + * 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 { describe, beforeAll, afterAll, it, expect } from '@ohos/hypium'; +import unifiedDataChannel from '@ohos.data.unifiedDataChannel'; + +const TAG = "[udmfStageTest]" + +export default function StageUdmfFileMangerTest() { + describe('StageUdmfFileMangerTest', () => { + beforeAll(() => { + console.log("*************StageUdmfFileMangerTest Test Begin*************"); + }); + + afterAll(() => { + console.log("*************StageUdmfFileMangerTest Test end*************"); + }); + + const createUnifiedData = (recordCount = 1) => { + const file = new unifiedDataChannel.File(); + file.details = { name: 'test', type: 'txt' }; + file.uri = 'schema://com.samples.test/files/test.txt'; + const unifiedData = new unifiedDataChannel.UnifiedData(file); + + for (let i = 0; i < recordCount; i++) { + const fileRecord = new unifiedDataChannel.File(); + fileRecord.details = { name: `test${i}`, type: 'txt' }; + fileRecord.uri = `schema://com.samples.test/files/test${i}.txt`; + unifiedData.addRecord(fileRecord); + } + + return unifiedData; + }; + + const testInsertData = (intention: unifiedDataChannel.Intention, testId: number, usePromise: boolean, done: Function) => { + const options: unifiedDataChannel.Options = { intention }; + const unifiedData = createUnifiedData(); + + const startTime = Date.now(); + if (usePromise) { + unifiedDataChannel.insertData(options, unifiedData) + .then(data => { + const endTime = Date.now(); + console.log(`${intention} insertData promise time: ${endTime - startTime}ms`); + console.info(`insertData succeeded, key = ${data}, testId = ${testId}`); + expect().assertTrue(); + done(); + }) + .catch(() => { + console.error(`Failed to insertData, testId = ${testId}`); + expect().assertFail(); + done(); + }); + } else { + unifiedDataChannel.insertData(options, unifiedData, (err, data) => { + const endTime = Date.now(); + console.log(`${intention} insertData callback time: ${endTime - startTime}ms`); + if (err === undefined) { + console.info(`insertData succeeded, key = ${data}, testId = ${testId}`); + expect().assertTrue(); + done(); + } else { + console.error(`Failed to insertData, testId = ${testId}, code is ${err.code}, message is ${err.message}`); + expect().assertFail(); + done(); + } + }); + } + }; + + const testQueryData = (options: unifiedDataChannel.Options, testId: number, usePromise: boolean, done: Function) => { + const startTime = Date.now(); + if (usePromise) { + unifiedDataChannel.queryData(options) + .then(data => { + const endTime = Date.now(); + console.log(`queryData promise time: ${endTime - startTime}ms`); + console.info(`queryData succeeded, size = ${data.length}, testId = ${testId}`); + expect().assertTrue(); + done(); + }) + .catch(() => { + console.error(`Failed to queryData, testId = ${testId}`); + expect().assertFail(); + done(); + }); + } else { + unifiedDataChannel.queryData(options, (err, data) => { + const endTime = Date.now(); + console.log(`queryData callback time: ${endTime - startTime}ms`); + if (err === undefined) { + console.info(`queryData succeeded, size = ${data.length}, testId = ${testId}`); + expect().assertTrue(); + done(); + } else { + console.error(`Failed to queryData, testId = ${testId}, code is ${err.code}, message is ${err.message}`); + expect().assertFail(); + done(); + } + }); + } + }; + + const testDeleteData = (options: unifiedDataChannel.Options, testId: number, usePromise: boolean, done: Function) => { + const startTime = Date.now(); + if (usePromise) { + unifiedDataChannel.deleteData(options) + .then(deletedData => { + const endTime = Date.now(); + console.log(`deleteData promise time: ${endTime - startTime}ms`); + console.info(`deleteData succeeded, testId = ${testId}, deleted ${deletedData.length} items`); + expect(deletedData.length > 0).assertTrue(); + done(); + }) + .catch(() => { + console.error(`Failed to deleteData, testId = ${testId}`); + expect().assertFail(); + done(); + }); + } else { + unifiedDataChannel.deleteData(options, (err, deletedData) => { + const endTime = Date.now(); + console.log(`deleteData callback time: ${endTime - startTime}ms`); + if (err === undefined) { + console.info(`deleteData succeeded, testId = ${testId}, deleted ${deletedData.length} items`); + expect(deletedData.length > 0).assertTrue(); + done(); + } else { + console.error(`Failed to deleteData, testId = ${testId}, code is ${err.code}, message is ${err.message}`); + expect().assertFail(); + done(); + } + }); + } + }; + + let validKey: string = ''; + const insertDataAndGetKey = (intention: unifiedDataChannel.Intention, recordCount: number, done: Function) => { + const options: unifiedDataChannel.Options = { intention }; + const unifiedData = createUnifiedData(recordCount); + + unifiedDataChannel.insertData(options, unifiedData) + .then(data => { + validKey = data; + console.info(`insertData succeeded, key = ${data}`); + done(); + }) + .catch(() => { + console.error('Failed to insertData'); + done(); + }); + }; + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_100 + * @tc.name : queryData with valid key and valid intention + * @tc.desc : Test queryData with valid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_100', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1000); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_200 + * @tc.name : queryData with valid key and invalid intention + * @tc.desc : Test queryData with valid key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_200', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: 'InvalidIntention' as unifiedDataChannel.Intention }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 200'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_300 + * @tc.name : queryData with valid key and no intention + * @tc.desc : Test queryData with valid key and no intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_300', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention : unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 300'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_400 + * @tc.name : queryData with invalid key and valid intention + * @tc.desc : Test queryData with invalid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_400', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: 'invalidKey', intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: 'invalidKey', intention : unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 400'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_InvalidKey_InvalidIntention_Test_500 + * @tc.name : queryData with invalid key and invalid intention + * @tc.desc : Test queryData with invalid key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_InvalidKey_InvalidIntention_Test_500', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: 'invalidKey', intention: 'InvalidIntention' as unifiedDataChannel.Intention }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: 'invalidKey', intention : unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 500'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_InvalidKey_NoIntention_Test_600 + * @tc.name : queryData with invalid key and no intention + * @tc.desc : Test queryData with invalid key and no intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_InvalidKey_NoIntention_Test_600', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: 'invalidKey' }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: 'invalidKey' , intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 600'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_700 + * @tc.name : queryData with no key and valid intention + * @tc.desc : Test queryData with no key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_700', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = {key:key , intention : unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 700'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_InvalidIntention_Test_800 + * @tc.name : queryData with no key and invalid intention + * @tc.desc : Test queryData with no key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_InvalidIntention_Test_800', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { intention: 'InvalidIntention' as unifiedDataChannel.Intention }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = {key:key, intention : unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 800'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_NoIntention_Test_900 + * @tc.name : queryData with no key and no intention + * @tc.desc : Test queryData with no key and no intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_NoIntention_Test_900', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = {}; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = {key:key, intention : unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + expect().assertFail(); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 900'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_1000 + * @tc.name : queryData with valid key and valid intention + * @tc.desc : Test queryData with valid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_1000', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key:key, intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 1000'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 1000'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_1100 + * @tc.name : queryData with valid key and invalid intention + * @tc.desc : Test queryData with valid key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_1100', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key:key, intention: 'InvalidIntention' as unifiedDataChannel.Intention }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 1100'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 1100'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_1200 + * @tc.name : queryData with valid key and no intention + * @tc.desc : Test queryData with valid key and no intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_1200', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key:key }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 1200'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 1200'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_1300 + * @tc.name : queryData with invalid key and valid intention + * @tc.desc : Test queryData with invalid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_1300', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.PICKER }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: 'invalidKey', intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + console.info('130000'); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.PICKER }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 1300'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 1300'); + done(); + }); + }); + + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_1600 + * @tc.name : queryData with no key and valid intention + * @tc.desc : Test queryData with no key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_1600', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.DATA_HUB }; + const unifiedData = createUnifiedData(1000); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { intention: unifiedDataChannel.Intention.DATA_HUB }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length >= 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.DATA_HUB }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 1600 '); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 1600'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_InvalidIntention_Test_1700 + * @tc.name : queryData with no key and invalid intention + * @tc.desc : Test queryData with no key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_InvalidIntention_Test_1700', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.DATA_HUB }; + const unifiedData = createUnifiedData(1000); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { intention: 'InvalidIntention' as unifiedDataChannel.Intention }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.DATA_HUB }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 1700'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 1700'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_1800 + * @tc.name : queryData with valid key and valid intention + * @tc.desc : Test queryData with valid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_1800', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1000); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: validKey, intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 1800'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 1800'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_1900 + * @tc.name : queryData with valid key and invalid intention + * @tc.desc : Test queryData with valid key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_1900', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1000); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 1900'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 1900'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_2000 + * @tc.name : queryData with valid key and no intention + * @tc.desc : Test queryData with valid key and no intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_2000', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const queryOptions: unifiedDataChannel.Options = { key: key }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2000'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2000'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_2100 + * @tc.name : queryData with invalid key and valid intention + * @tc.desc : Test queryData with invalid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_2100', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: 'invalidKey', intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2100'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2100'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_2200 + * @tc.name : queryData with no key and valid intention + * @tc.desc : Test queryData with no key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_2200', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2200'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2200'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_2300 + * @tc.name : queryData with valid key and valid intention + * @tc.desc : Test queryData with valid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_2300', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2300'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2300'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_2400 + * @tc.name : queryData with valid key and invalid intention + * @tc.desc : Test queryData with valid key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_2400', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: 'InvalidIntention' as unifiedDataChannel.Intention }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2400'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2400'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_2500 + * @tc.name : queryData with valid key and no intention + * @tc.desc : Test queryData with valid key and no intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_2500', 1, (done: Function) => { + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2500'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2500'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_2600 + * @tc.name : queryData with invalid key and valid intention + * @tc.desc : Test queryData with invalid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_2600', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: 'invalidKey', intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2600'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2600'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_2700 + * @tc.name : queryData with no key and valid intention + * @tc.desc : Test queryData with no key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_2700', 0, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { intention: unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = {intention : unifiedDataChannel.Intention.SYSTEM_SHARE }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2700'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2700'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_2800 + * @tc.name : queryData with valid key and valid intention + * @tc.desc : Test queryData with valid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_2800', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1000); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2800'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2800'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_2900 + * @tc.name : queryData with valid key and invalid intention + * @tc.desc : Test queryData with valid key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_2900', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: 'InvalidIntention' as unifiedDataChannel.Intention }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 2900'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 2900'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_3000 + * @tc.name : queryData with valid key and no intention + * @tc.desc : Test queryData with valid key and no intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_3000', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 3000'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 3000'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_3100 + * @tc.name : queryData with invalid key and valid intention + * @tc.desc : Test queryData with invalid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_3100', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: 'invalidKey', intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 3100'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 3100'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_3200 + * @tc.name : queryData with no key and valid intention + * @tc.desc : Test queryData with no key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_3200', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 3200'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 3200'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_3300 + * @tc.name : queryData with valid key and valid intention + * @tc.desc : Test queryData with valid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_ValidIntention_Test_3300', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 3300'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 3300'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_3400 + * @tc.name : queryData with valid key and invalid intention + * @tc.desc : Test queryData with valid key and invalid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_InvalidIntention_Test_3400', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key, intention: 'InvalidIntention' as unifiedDataChannel.Intention }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 3400'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 3400'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_3500 + * @tc.name : queryData with valid key and no intention + * @tc.desc : Test queryData with valid key and no intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_ValidKey_NoIntention_Test_3500', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: key }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 3500'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 3500'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_3600 + * @tc.name : queryData with invalid key and valid intention + * @tc.desc : Test queryData with invalid key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_InvalidKey_ValidIntention_Test_3600', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { key: 'invalidKey', intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 3600'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 3600'); + done(); + }); + }); + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_3700 + * @tc.name : queryData with no key and valid intention + * @tc.desc : Test queryData with no key and valid intention. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_Query_NoKey_ValidIntention_Test_3700', 1, (done: Function) => { + + const options: unifiedDataChannel.Options = { intention : unifiedDataChannel.Intention.MENU }; + const unifiedData = createUnifiedData(1); + + unifiedDataChannel.insertData(options, unifiedData) + .then(key => { + const queryOptions: unifiedDataChannel.Options = { intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.queryData(queryOptions) + .then(data => { + expect(data.length == 1).assertTrue(); + const options: unifiedDataChannel.Options = { key: key, intention: unifiedDataChannel.Intention.MENU }; + unifiedDataChannel.deleteData(options); + done(); + }) + .catch(() => { + console.error('Failed to query 3700'); + done(); + }); + }) + .catch(() => { + console.error('Failed to insertData 3700'); + done(); + }); + }); + }); +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfPromisetest.ets b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfPromisetest.ets new file mode 100644 index 00000000..c11271f0 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/ets/test/StageUdmfPromisetest.ets @@ -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. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' +import unifiedDataChannel from '@ohos.data.unifiedDataChannel'; +import uniformTypeDescriptor from '@ohos.data.uniformTypeDescriptor'; + +const TAG = "[udmfStageTest]" + +export default function stageUdmfPromiseJsTest() { + describe('stageUdmfPromiseJsTest', function () { + console.log(TAG + "*************Unit Test Begin*************"); + beforeAll(function() { + console.log('stageUdmfPromiseJsTest TestAbility context' + globalThis.abilityContext); + console.info('beforeAll') + }) + afterAll(async function () { + console.info('afterAll'); + }) + + /** + * @tc.number : SUB_DistributedData_UDMF_SDK_UnifiedDataPromiseJsAPITest_0100 + * @tc.name : unifiedDataChannel insertData promise interface test + * @tc.desc : unifiedDataChannel insertData promise interface test. + * @tc.size : MEDIUM + * @tc.type : Function + * @tc.level : Level 3 + */ + it('SUB_DistributedData_UDMF_SDK_UnifiedDataPromiseJsAPITest_0100', 0, (done) => { + let options: unifiedDataChannel.Options = {} + let plainText = new unifiedDataChannel.PlainText(); + plainText.textContent = 'this is textContent'; + let unifiedData = new unifiedDataChannel.UnifiedData(plainText); + try { + unifiedDataChannel.insertData(options, unifiedData).then((data) => { + console.info(TAG + `data = ${data}, options = ${options}`); + expect().assertFail(); + done(); + }).catch((err:BusinessError) => { + console.error(TAG, `Failed, code is ${err.code},message is ${err.message} `); + expect(err !== null).assertFail(); + done(); + }) + } catch (error) { + console.error(TAG, `Failed to insertData0100 code is ${error.code},message is ${error.message} `); + expect(error.code).assertEqual('401'); + done(); + } + }) + console.log(TAG + "*************Unit Test End*************"); + }) +} \ No newline at end of file diff --git a/relational_store/test/js/gdb/performance/config.json b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/module.json similarity index 34% rename from relational_store/test/js/gdb/performance/config.json rename to udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/module.json index 2f09d1d4..f61b9af0 100644 --- a/relational_store/test/js/gdb/performance/config.json +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/module.json @@ -1,62 +1,51 @@ { - "app": { - "bundleName": "com.example.myapplication", - "vendor": "example", - "version": { - "code": 1, - "name": "1.0" - }, - "apiVersion": { - "compatible": 4, - "target": 5 - } - }, - "deviceConfig": {}, "module": { - "package": "com.example.myapplication", - "name": ".MyApplication", - "deviceType": [ + "name": "testModule", + "type": "entry", + "srcEntrance": "./ets/Application/AbilityStage.ts", + "description": "$string:testModule_entry_dsc", + "mainElement": "com.example.myapplication.MainAbility", + "deviceTypes": [ + "default", "tablet", "2in1", - "default", "phone" ], - "distro": { - "deliveryWithInstall": true, - "moduleName": "entry", - "moduleType": "entry" - }, + "deliveryWithInstall": true, + "installationFree": false, + "uiSyntax": "ets", + "pages": "$profile:main_pages", + "metadata": [ + { + "name": "ArkTSPartialUpdate", + "value": "false" + }, + { + "name": "MetaData1", + "value": "MetaDataValue", + "resource": "$profile:shortcuts_config" + } + ], "abilities": [ { + "name": "com.example.myapplication.MainAbility", + "srcEntrance": "./ets/MainAbility/MainAbility.ts", + "description": "$string:testModule_entry_main", + "icon": "", + "label": "$string:entry_label", "visible": true, + "launchType": "singleton", + "orientation": "portrait", "skills": [ { - "entities": [ - "entity.system.home" - ], "actions": [ "action.system.home" + ], + "entities":[ + "entity.system.home" ] } - ], - "name": "com.example.myapplication.MainAbility", - "icon": "$media:icon", - "description": "$string:mainability_description", - "label": "MyApplication", - "type": "page", - "launchType": "standard" - } - ], - "js": [ - { - "pages": [ - "pages/index/index" - ], - "name": "default", - "window": { - "designWidth": 720, - "autoDesignWidth": false - } + ] } ] } diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/element/string.json b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/element/string.json new file mode 100644 index 00000000..fe90aac0 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/element/string.json @@ -0,0 +1,24 @@ +{ + "string": [ + { + "name": "testModule_entry_dsc", + "value": "i am an entry for testModule" + }, + { + "name": "testModule_entry_main", + "value": "the testModule entry ability" + }, + { + "name": "entry_label", + "value": "stagePreferencesJsTest" + }, + { + "name": "description_application", + "value": "demo for test" + }, + { + "name": "app_name", + "value": "Demo" + } + ] +} diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/form_config.json b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/form_config.json new file mode 100644 index 00000000..e892d447 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/form_config.json @@ -0,0 +1,6 @@ +{ + "src": [ + "MainAbility/pages/index/index", + "MainAbility/pages/second/second" + ] +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/form_config1.txt b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/form_config1.txt new file mode 100644 index 00000000..32f9ff7d --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/form_config1.txt @@ -0,0 +1 @@ +{"src": ["MainAbility/pages/index/index","MainAbility/pages/second/second"]} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/main_pages.json b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 00000000..02221db6 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,6 @@ +{ + "src": [ + "MainAbility/pages/index/index", + "MainAbility/pages/second/second" + ] +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/shortcuts_config.json b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/shortcuts_config.json new file mode 100644 index 00000000..02221db6 --- /dev/null +++ b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/entry/src/main/resources/base/profile/shortcuts_config.json @@ -0,0 +1,6 @@ +{ + "src": [ + "MainAbility/pages/index/index", + "MainAbility/pages/second/second" + ] +} \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/signature/openharmony_sx.p7b b/udmf/framework/jskitsimpl/test/unittest/stage_unittest/udmf/src/signature/openharmony_sx.p7b new file mode 100644 index 0000000000000000000000000000000000000000..2fac054162b97eb332cb3074f30f216db6701d27 GIT binary patch literal 3500 zcmcgvX>b$g8MY1^j1ia^FgHdJ%q93%mTbuhNp_``w8ATSWy!XTiCIaj!(Q#m(#k7~ za#S=fH-!vG!Vz;r10>}#bPAzq10`voB-E2hIZ9kwpfofE5()$9uI+%$z>iL5&=2jr z$M@~C@B6&ZHy=nTc4lNwXtFeYr;zlJHm4MCfs|sER3d>CAS)wtW|Kui$>dTANTp+s z6D7^5^kR7`y>OPYfr`dLETdw`Fr_S3swacVKso7=+spa{w|bJ2j6_tvP>hR)JaJB3 zz%@q11#GM)#Bfv~N{U`#Wjr4834Se57kTu0N~QG+f0{zAPo>uaor=^`04mV<{S>4V z-$T+NUx;f|7SB>LET{5Nel{xX3u*NlU7=R3)lF*mlYWkh3hqLkUQ<*cxMxpNb|Q#U zG)2ZJVKYyh@zInj#Q0fpKOfaV(QJf@s@f6RBNSsHqhXe56mq+Li<gRWA%DnAa^fec z#2<p1F<YJibvQ8-W`Lb&ySJLbG0cD`4F=dl1z;XS-~fh_cEgmU5yp`~pgvevYcC}T zBh0&C+>9p-N!W@6Y~={-cEWWwyRd_U;L(8FSWXbrP@XIGn#<#5W>cf5LLaA`Xcdll z%`oIb4GElZ79g~zE*SKNp#~3A7brKE2df#66RpJ!XnPi%z{w}Gh)RU_nCV(~r6b}| zYXSs7c}vi1!)s9<uZ0^03{EUzcjAc(!D}<tCGc82@yJ(;us9Lp4MaOeGs;_y&RW!k zBUlHnAYM|<Jn_zi*$G#6d}qvwqI$lnLW{X8t(-@#)nX<G?XCccX+}8Qk%K#{84GwK z3pMdxb0Xqan*b@)0y9}@kMO--wTrKC!cHXM?W`__h?TBpI%<t02yZjMu+!tV8wes& zq4oRf+!mWg+W;yHU<;Xm)U~CE4>htelLM=QsLF7{?oO7Os~Ibg`(u`%%cTdXj>dqq z(p|;a!T}tLu?=w#MbyJi7Q%R!5%!D7EoC@rHo_GF#OVn}y`gHx#JNgXSG=I0th^}h zM@@bb;~YuY-kwe95ZJFn5g0ch8ko0;6?FhRg1AvrDVK=GgLF0Hbs$8{>f^mt^(ApV zYjc$cNF3(P21C8M4A<y|)kcJXjU){7RRorRtsDtT33Wtc#NtyTv1+CS_mvoo0YdAt zKr}!!rRE?);{jhto%HLNI(;lcCQ$;L0xE5M#Lwvn7~?HvaadhJ(dD5jY&DaFX%o;H z8ILt;w{v!esMqoqdns*nBN{vBO4{94VH+>YMN!6@uqMs1;FM~neI!tu@hM~Scp5u} z#mj~#QwcI0p{dE?MnO$zaojp2gN)F^*fDH0Owz(aQEL1Y$;Cw>PzD8s=?K*b0daCk zj#LGrY&;^&bxc`2T?wfRG}=PtBqmPNGX!BEy|mz;r6g&Z<td-4!=A2Gia|jS!l9U` zdF?q-O4KwjC!}?YOc!&7ytpVk%1B+PUFM>UfN*wmD&t=uC4CvBBp)=(q!OuAUbG{8 z4D`<EDM<0@sdAYtJq>uFERdNYbICJuqy`(*AG{zMy>ha;2oW?G<ci*`oa`>%JSRnl zq0wNJ7?R}-=^BC`S1!*0gAut3H3ZZ^4XK5vwklVl(F^5(I!zGykstt=+yNs0Ss+TI ztUp9kd5#Vl25yj((WAW#Qb}h$WRe~-Bu!p%M*7bq+xLA1*B={jYUQ}M_n3<2E7p#b zT-`I__e(CGzdQopS#(GC**7N`=|tzNBR}{<GqECb;P2kloR%?*PYil{ivyH`kpi6I zqveCZz<K@u($u0H_~)!m(^@XPIP1ta>9aSh%%G2$&{rb)UM`nOd&~pFMZ1rDpuGPl z<h7$alD2baR_*`Ujr0fK)+i*7?md%*(tuwIrR`p}H#6mF+-n)r54rIR>PRqS-wPYE zdDANoZfsuL@)fe&ciw;J@{Ze=mu3{seE7=^!jk5u+T^8&y^G-+V`h}3k6QHG?epy5 zyz#G##$Ip?IW95myf$Y47HxK7*TdMHD}U>|U*L~X;LoW}{`9@9TihKB2>!^{jRRvl zS~v1pt#hy}_XLR`4W#QrqIUB+B545GkI9oh@u%`MrOcBi#|tksuBcPYUw>0!J@IfH z`?VJiPn&f_m9@U%=ykXI?DTb;UrXIP^toGZUW}X9Mph%+b~oQXQgh$Ay?37r-UZ9Q zF!$T?hT`JkZJY1c47fjb<l^Xsyz#?{m>Zi@)WiJmEeLoG^c9JcBN8Va$b?6CCP^~7 zFe$e<d(*pve{v<wzWeOj{C#Vy_&%R@@187>27FS$SMmAKr{D2AUs<!EwerC7z4_aF zEj`owaPg55Z_JyZO;&H)G)%Se+()c@bjY30t&@T=?~eI7J7f3g9*+K7m)>q(0<5n# z8vh$duSB*sY*>FAtf{xJXl&h)dv4<P)8;`<=>m^Pfk#(5c{GALKD9fN=h(e2VgzXm z)LnTbn$JfOpFyEf8^1oe;k{h#o<$#Tt@+0__{DsA+mLr|ea_7{?A@91?Vg+YLq2JJ zQ}OG=MO)`YDi@xdGc>ZVVf&#!IzYvNFV~DKEIrur-iPaktlxHP;lk`&XV;Eecz5p1 z0~1Hyy?*NQvU@7m7B3*XiPKX#@_%sbsp8h{gpmc)03`+C^RMgXzs230`~KbHV9l<R zg&W(BWuI)#X`AiOwqLQhE-jolIM{;y=iK#{0iRuO?I(!UiJmOKt2nyJ(K1$b|6t|r zk5;eF{*Zp@!obw92MaFRmPW5EBikZwZfW3S%{woBIT=bxV1Z;)g?k04doFG4JW;z| zVVXl=(4#9%rVJ8dKU{nyVAvxgGac$H9E#!*r~w)X(iBvIDUYLaNGZ=-y5x&P*!M@5 zwVj%MuU}TI^>|Hd^6Hk`+WM6}>$As>-vfF*I?1JSGeD)I(soBiZ9TbR<-?c%Uef#i zeC@Sg1;!T_v>jS(8VcGHCk|Yd=1o1efVwkCGxSnr&$4|PsG?-Ro!?x1e^o!*!Q6|l I|B0CUKhH;Mo&W#< literal 0 HcmV?d00001 diff --git a/udmf/framework/jskitsimpl/unittest/AipRdbJsTest.js b/udmf/framework/jskitsimpl/unittest/AipRdbJsTest.js deleted file mode 100644 index aac1fe6b..00000000 --- a/udmf/framework/jskitsimpl/unittest/AipRdbJsTest.js +++ /dev/null @@ -1,981 +0,0 @@ -/* - * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index'; -import intelligence from '@ohos.data.intelligence'; -import deviceInfo from '@ohos.deviceInfo'; -import relationalStore from '@ohos.data.relationalStore'; -import featureAbility from '@ohos.ability.featureAbility'; - -const TAG = '[AipIntelligenceJSTest]'; - -let currentDeviceIsPc = false; -let context = featureAbility.getContext(); -let rdbStore1 = undefined; -let rdbStore2 = undefined; - -let storeConfigInvalid = { - name: '', - securityLevel: relationalStore.SecurityLevel.S1 -}; - -let channelConfigInvalid = { - channelType: 0, - context:context, - dbConfig:storeConfigInvalid -}; - -let storeConfigVector = { - name: 'rdb_store_test.db', - encrypt: false, - securityLevel: relationalStore.SecurityLevel.S3, - autoCleanDirtyData: false, - isSearchable: false, - vector: true, - allowRebuild: false -}; - -let storeConfigInvIdx = { - name: 'sqlite_store_test.db', - encrypt: false, - securityLevel: relationalStore.SecurityLevel.S3, - autoCleanDirtyData: false, - isSearchable: false, - allowRebuild: false, - tokenizer: 2 -}; - -let channelConfigVector = { - channelType: intelligence.ChannelType.VECTOR_DATABASE, - context:context, - dbConfig:storeConfigVector -}; - -let channelConfigInvIdx = { - channelType: intelligence.ChannelType.INVERTED_INDEX_DATABASE, - context:context, - dbConfig:storeConfigInvIdx -}; - -describe('AipJSTest', function () { - - beforeAll(async function () { - console.info(TAG + 'beforeAll'); - let deviceTypeInfo = deviceInfo.deviceType; - currentDeviceIsPc = deviceTypeInfo === '2in1' ? true : false; - console.info(TAG + 'the value of the deviceType is : ' + deviceInfo.deviceType); - relationalStore.deleteRdbStore(context, 'rdb_store_test.db', (err) => { - if (err) { - console.error(`Delete RdbStore failed, code is ${err.code},message is ${err.message}`); - return; - } - console.info(TAG + 'Delete RdbStore successfully.'); - }); - rdbStore1 = await relationalStore.getRdbStore(context, storeConfigVector); - if (rdbStore1 !== undefined) { - let createSql = 'CREATE TABLE IF NOT EXISTS vector_table(fileid TEXT PRIMARY KEY, filename_text TEXT, filename FLOATVECTOR(128), keywords_text TEXT, keywords FLOATVECTOR(128), chapter FLOATVECTOR(128), abstract FLOATVECTOR(128));'; - await rdbStore1.execute(createSql, 0, undefined); - await insertVectorDB(); - }; - rdbStore2 = await relationalStore.getRdbStore(context, storeConfigInvIdx); - if (rdbStore2 !== undefined) { - let createSql = 'CREATE VIRTUAL TABLE IF NOT EXISTS invidx_table USING fts5(fileid, filename, keywords, chapter, abstract, content, tokenize = "customtokenizer");'; - await rdbStore2.executeSql(createSql); - await insertInvIdxDB(); - }; - }); - beforeEach(async function () { - console.info(TAG + 'beforeEach'); - }); - afterEach(async function () { - console.info(TAG + 'afterEach'); - }); - afterAll(async function () { - console.info(TAG + 'afterAll'); - }); - - async function insertVectorDB() { - let insertSQL; - for (let i = 0; i < 5; i++) { - let array = new Array(128); - for (let j = 0; j < array.length; j++) { - let randomNumber = Math.random(); - array[j] = randomNumber; - } - let data = array.toString(); - insertSQL = "INSERT INTO vector_table VALUES('" + i + "', '大模型系统概述', '[" + data + "]', '生成式AI, 人工智能, 大模型', '[" + data + "]', '[" + data + "]', '[" + data + "]');"; - console.info(TAG + 'insertVectorDB insertSQL::' + insertSQL); - await rdbStore1.execute(insertSQL, 0, undefined); - } - let arraySpecial = new Array(128).fill(0.1); - let dataSpecial = arraySpecial.toString(); - let insertSQLSpecial = "INSERT INTO vector_table VALUES('5', '大模型系统概述', '[" + dataSpecial + "]', '生成式AI, 人工智能, 大模型', '[" + dataSpecial + "]', '[" + dataSpecial + "]', '[" + dataSpecial + "]');"; - console.info(TAG + 'insertVectorDB insertSQL::' + insertSQLSpecial); - await rdbStore1.execute(insertSQLSpecial, 0, undefined); - } - - async function insertInvIdxDB() { - let insertSQL = 'INSERT INTO invidx_table VALUES("1", "大模型系统概述", "生成式AI, 人工智能, 大模型", "人工智能导论", "这是一篇关于大模型的综述文章", "这是一篇关于大模型的综述文章");'; - console.info(TAG + 'insertInvIdxDB insertSQL::' + insertSQL); - await rdbStore2.executeSql(insertSQL); - insertSQL = 'INSERT INTO invidx_table VALUES("2", "数据库在大模型时代下的发展", "数据库, 内核, 向量", "数据库导论", "这是一篇关于数据库和大模型交叉的综述文章", "这是一篇关于数据库和大模型交叉的综述文章");'; - console.info(TAG + 'insertInvIdxDB insertSQL::' + insertSQL); - await rdbStore2.executeSql(insertSQL); - insertSQL = 'INSERT INTO invidx_table VALUES("3", "社会发展报告", "旅游, 民生, 交通", "社会发展", "这是一篇关于社会发展的综述文章", "这是一篇关于社会发展的综述文章");'; - console.info(TAG + 'insertInvIdxDB insertSQL::' + insertSQL); - await rdbStore2.executeSql(insertSQL); - insertSQL = 'INSERT INTO invidx_table VALUES("4", "鸿蒙", "鸿蒙, 生态, 遥遥领先", "鸿蒙系统", "这是一篇关于鸿蒙系统的综述文章", "这是一篇关于鸿蒙系统的综述文章");'; - console.info(TAG + 'insertInvIdxDB insertSQL::' + insertSQL); - await rdbStore2.executeSql(insertSQL); - insertSQL = 'INSERT INTO invidx_table VALUES("5", "AI系统", "鸿蒙, 生态, 大模型", "AI系统", "这是一篇关于AI系统的综述文章", "这是一篇关于AI系统的综述文章");'; - console.info(TAG + 'insertInvIdxDB insertSQL::' + insertSQL); - await rdbStore2.executeSql(insertSQL); - console.info(TAG + 'insertInvIdxDB end'); - } - - async function sleep(time) { - return new Promise((resolve, reject) => { - setTimeout(() => { - resolve(); - }, time); - }).then(() => { - console.info(`sleep ${time} over...`); - }); - } - - console.log('******************************Aip API Test Begin******************************'); - - /** - * @tc.name Aip_001 - * @tc.desc Test getRetriever. rdbStoreName is empty. - * @tc.type: FUNC - */ - it('Aip_001', 0, async function (done) { - console.info(TAG, 'Aip_001 start'); - let retrievalConfig = { - channelConfigs: [channelConfigInvalid] - }; - if (currentDeviceIsPc) { - try { - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - expect(data != null).assertEqual(true); - done(); - }); - } catch (err) { - console.info(TAG, 'Aip_001 catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_002 - * @tc.desc Test getRetriever. channelConfigs is empty. - * @tc.type: FUNC - */ - it('Aip_002', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [] - }; - if (currentDeviceIsPc) { - try { - await intelligence.getRetriever(retrievalConfig); - } catch (err) { - console.info(TAG, 'Aip_002 catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - }); - - /** - * @tc.name Aip_003 - * @tc.desc Test retrieveRdb. The value of deepSize is too large. - * @tc.type: FUNC - */ - it('Aip_003', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigVector] - }; - if (currentDeviceIsPc) { - try { - let floatArray = new Float32Array(128).fill(0.1); - let vectorQuery = { - column: 'filename', - value: floatArray, - similarityThreshold: 0.1 - }; - let recallCondition = { - vectorQuery: vectorQuery, - fromClause: 'vector_table', - primaryKey: ['fileid'], - responseColumns: ['filename_text'], - filters: [], - deepSize: 1000000 - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '软件设计与建模'; - data.retrieveRdb(query, retrievalCondition) - .then((rdbdata) => { - let length = rdbdata.records.length; - console.info(TAG, 'Aip_003 get result::' + length); - let ret = length >= 0; - expect(ret).assertEqual(true); - done(); - }); - } catch (err) { - console.info(TAG, 'catch::' + err.code); - done(); - } - }); - } catch (err) { - console.info(TAG, 'catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_004 - * @tc.desc Test retrieveRdb.fromClause is empty. - * @tc.type: FUNC - */ - it('Aip_004', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigVector] - }; - if (currentDeviceIsPc) { - try { - let floatArray = new Float32Array(128).fill(0.1); - let vectorQuery = { - column: 'filename', - value: floatArray, - similarityThreshold: 0.1 - }; - let recallCondition = { - vectorQuery: vectorQuery, - fromClause: '', - primaryKey: ['fileid'], - responseColumns: ['filename_text'], - deepSize: 500 - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '软件设计与建模'; - data.retrieveRdb(query, retrievalCondition); - } catch (err) { - console.info(TAG, 'Aip_004 catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - }); - } catch (err) { - console.info(TAG, 'Aip_004 catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'catch11::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_005 - * @tc.desc Test retrieveRdb. primaryKey is empty. - * @tc.type: FUNC - */ - it('Aip_005', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigVector] - }; - if (currentDeviceIsPc) { - try { - let floatArray = new Float32Array(128).fill(0.1); - let vectorQuery = { - column: 'filename', - value: floatArray, - similarityThreshold: 0.1 - }; - let recallCondition = { - vectorQuery: vectorQuery, - fromClause: 'vector_table', - primaryKey: [], - responseColumns: ['filename_text'], - deepSize: 500 - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '软件设计与建模'; - data.retrieveRdb(query, retrievalCondition); - } catch (err) { - console.info(TAG, 'catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - }); - } catch (err) { - console.info(TAG, 'Aip_005 catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'catch11::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_006 - * @tc.desc Test retrieveRdb. responseColumns is empty. - * @tc.type: FUNC - */ - it('Aip_006', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigVector] - }; - if (currentDeviceIsPc) { - try { - let floatArray = new Float32Array(128).fill(0.1); - let vectorQuery = { - column: 'filename', - value: floatArray, - similarityThreshold: 0.1 - }; - let recallCondition = { - vectorQuery: vectorQuery, - fromClause: 'vector_table', - primaryKey: ['fileid'], - responseColumns: [], - deepSize: 500 - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '软件设计与建模'; - data.retrieveRdb(query, retrievalCondition); - } catch (err) { - console.info(TAG, 'Aip_006 catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - }); - } catch (err) { - console.info(TAG, 'catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_007 - * @tc.desc Test retrieveRdb. column is invalid. - * @tc.type: FUNC - */ - it('Aip_007', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigVector] - }; - if (currentDeviceIsPc) { - try { - let floatArray = new Float32Array(128).fill(0.1); - let vectorQuery = { - column: 'invalidField', - value: floatArray, - similarityThreshold: 0.1 - }; - let recallCondition = { - vectorQuery: vectorQuery, - fromClause: 'vector_table', - primaryKey: ['fileid'], - responseColumns: ['filename_text'], - deepSize: 500 - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '软件设计与建模'; - data.retrieveRdb(query, retrievalCondition) - .catch((err) => { - console.info(TAG, 'Aip_007 catch::' + err.code); - expect(err.code).assertEqual(31300100); - done(); - }); - } catch (err) { - console.info(TAG, 'Aip_007 catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - }); - } catch (err) { - console.info(TAG, 'catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_008 - * @tc.desc Test retrieveRdb. One-way vector normal recall. - * @tc.type: FUNC - */ - it('Aip_008', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigVector] - }; - if (currentDeviceIsPc) { - try { - let floatArray = new Float32Array(128).fill(0.1); - const str = floatArray.toString(); - console.log(TAG, str); - let vectorQuery = { - column: 'filename', - value: floatArray, - similarityThreshold: 0.1 - }; - let recallCondition = { - vectorQuery: vectorQuery, - fromClause: 'vector_table', - primaryKey: ['fileid'], - responseColumns: ['filename_text'], - deepSize: 500 - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '软件设计与建模'; - data.retrieveRdb(query, retrievalCondition) - .then((rdbdata) => { - let length = rdbdata.records.length; - console.info(TAG, 'Aip_008 get result length::' + length); - expect(length > 0).assertEqual(true); - done(); - }); - } catch (err) { - console.info(TAG, 'Aip_008 catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - }); - } catch (err) { - console.info(TAG, 'Aip_008 catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'Aip_008 catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_009 - * @tc.desc Test retrieveRdb. One-way invertedindex normal recall. - * @tc.type: FUNC - */ - it('Aip_009', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigInvIdx] - }; - if (currentDeviceIsPc) { - try { - let fieldWeight = { - 'filename': 4.0 - }; - let fieldSlops = { - 'filename': 5 - }; - let bm25Strategy = { - bm25Weight: 1.5, - columnWeight: fieldWeight - }; - let exactStrategy = { - exactMatchingWeight: 1.2, - columnWeight: fieldWeight - }; - let outOfOrderStrategy = { - proximityWeight: 1.2, - columnWeight: fieldWeight, - columnSlops: fieldSlops - }; - let invertedIndexStrategies = [bm25Strategy, exactStrategy, outOfOrderStrategy]; - let recallCondition = { - ftsTableName: 'invidx_table', - fromClause: 'invidx_table', - primaryKey: ['fileid'], - responseColumns: ['filename', 'keywords'], - deepSize: 500, - invertedIndexStrategies: invertedIndexStrategies - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - console.info(TAG, 'Aip_009 get result::' + data); - try { - let query = '数据库'; - data.retrieveRdb(query, retrievalCondition) - .then((rdbdata) => { - let length = rdbdata.records.length; - console.info(TAG, 'Aip_009 get result::' + length); - expect(length).assertEqual(1); - done(); - }); - } catch (err) { - console.info(TAG, 'Aip_009 catch::' + err.code); - done(); - } - }); - } catch (err) { - console.info(TAG, 'Aip_009 catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'Aip_009 catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_010 - * @tc.desc Test retrieveRdb. ftsTableName is empty. - * @tc.type: FUNC - */ - it('Aip_010', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigInvIdx] - }; - if (currentDeviceIsPc) { - try { - let fieldWeight = { - 'filename': 4.0 - }; - let fieldSlops = { - 'filename': 5 - }; - let bm25Strategy = { - bm25Weight: 1.5, - columnWeight: fieldWeight - }; - let exactStrategy = { - exactMatchingWeight: 1.2, - columnWeight: fieldWeight - }; - let outOfOrderStrategy = { - proximityWeight: 1.2, - columnWeight: fieldWeight, - columnSlops: fieldSlops - }; - let invertedIndexStrategies = [bm25Strategy, exactStrategy, outOfOrderStrategy]; - let recallCondition = { - ftsTableName: '', - fromClause: 'invidx_table', - primaryKey: ['fileid'], - responseColumns: ['filename', 'keywords'], - deepSize: 500, - invertedIndexStrategies: invertedIndexStrategies - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '数据库'; - data.retrieveRdb(query, retrievalCondition); - } catch (err) { - console.info(TAG, 'Aip_010 catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - }); - } catch (err) { - console.info(TAG, 'Aip_010 catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'Aip_010 catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_011 - * @tc.desc Test retrieveRdb. invertedindex match field is invalid. - * @tc.type: FUNC - */ - it('Aip_011', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigInvIdx] - }; - if (currentDeviceIsPc) { - try { - let fieldWeight = { - 'invalid': 4.0 - }; - let fieldSlops = { - 'filename': 5 - }; - let bm25Strategy = { - bm25Weight: 1.5, - columnWeight: fieldWeight - }; - let exactStrategy = { - exactMatchingWeight: 1.2, - columnWeight: fieldWeight - }; - let outOfOrderStrategy = { - proximityWeight: 1.2, - columnWeight: fieldWeight, - columnSlops: fieldSlops - }; - let invertedIndexStrategies = [bm25Strategy, exactStrategy, outOfOrderStrategy]; - let recallCondition = { - ftsTableName: 'invidx_table', - fromClause: 'invidx_table', - primaryKey: ['fileid'], - responseColumns: ['filename', 'keywords'], - deepSize: 500, - invertedIndexStrategies: invertedIndexStrategies - }; - let retrievalCondition = { - recallConditions : [recallCondition] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '数据库'; - data.retrieveRdb(query, retrievalCondition) - .catch((err) => { - console.info(TAG, 'Aip_011 catch::' + err.code); - expect(err.code).assertEqual(31301010); - done(); - }); - } catch (err) { - console.info(TAG, 'Aip_011 catch::' + err.code); - expect(err.code).assertEqual(401); - done(); - } - }); - } catch (err) { - console.info(TAG, 'Aip_011 catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'Aip_011 catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - - /** - * @tc.name Aip_012 - * @tc.desc Test retrieveRdb. Two-way normal recall. - * @tc.type: FUNC - */ - it('Aip_012', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigInvIdx, channelConfigVector] - }; - if (currentDeviceIsPc) { - try { - let fieldWeight = { - 'filename': 4.0 - }; - - let fieldSlops = { - 'filename': 5 - }; - let bm25Strategy = { - bm25Weight: 1.5, - columnWeight: fieldWeight - }; - let exactStrategy = { - exactMatchingWeight: 1.2, - columnWeight: fieldWeight - }; - let outOfOrderStrategy = { - proximityWeight: 1.2, - columnWeight: fieldWeight, - columnSlops: fieldSlops - }; - let invertedIndexStrategies = [bm25Strategy, exactStrategy, outOfOrderStrategy]; - let recallConditionInvIdx = { - ftsTableName: 'invidx_table', - fromClause: 'invidx_table', - primaryKey: ['fileid'], - responseColumns: ['filename', 'keywords'], - deepSize: 500, - invertedIndexStrategies: invertedIndexStrategies - }; - let floatArray = new Float32Array(128).fill(0.1); - let vectorQuery = { - column: 'filename', - value: floatArray, - similarityThreshold: 0.1 - }; - let recallConditionVector = { - vectorQuery: vectorQuery, - fromClause: 'vector_table', - primaryKey: ['fileid'], - responseColumns: ['filename_text'], - deepSize: 500 - }; - let retrievalCondition = { - recallConditions : [recallConditionInvIdx, recallConditionVector] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '数据库'; - data.retrieveRdb(query, retrievalCondition) - .then((rdbdata) => { - let length = rdbdata.records.length; - console.info(TAG, 'Aip_012 get result::' + length); - expect(length >= 2).assertEqual(true); - done(); - }); - } catch (err) { - console.info(TAG, 'Aip_012 catch::' + err.code); - done(); - } - }); - } catch (err) { - console.info(TAG, 'Aip_012 catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'Aip_012 catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); - - /** - * @tc.name Aip_013 - * @tc.desc Test retrieveRdb. Two-way normal recall and configing rerankMethod. - * @tc.type: FUNC - */ - it('Aip_013', 0, async function (done) { - console.info(TAG, 'start'); - let retrievalConfig = { - channelConfigs: [channelConfigInvIdx, channelConfigVector] - }; - if (currentDeviceIsPc) { - try { - let fieldWeight = { - 'filename': 4.0, - 'keywords':4.0 - }; - let fieldSlops = { - 'filename': 5, - 'keywords':5 - }; - let bm25Strategy = { - bm25Weight: 1.5, - columnWeight: fieldWeight - }; - let exactStrategy = { - exactMatchingWeight: 1.2, - columnWeight: fieldWeight - }; - let outOfOrderStrategy = { - proximityWeight: 1.2, - columnWeight: fieldWeight, - columnSlops: fieldSlops - }; - let invertedIndexStrategies = [bm25Strategy, exactStrategy, outOfOrderStrategy]; - let recallConditionInvIdx = { - ftsTableName: 'invidx_table', - fromClause: 'invidx_table', - primaryKey: ['fileid'], - responseColumns: ['filename', 'keywords'], - deepSize: 500, - invertedIndexStrategies: invertedIndexStrategies - }; - let floatArray = new Float32Array(128).fill(0.1); - let vectorQuery = { - column: 'filename', - value: floatArray, - similarityThreshold: 0.1 - }; - let recallConditionVector = { - vectorQuery: vectorQuery, - fromClause: 'vector_table', - primaryKey: ['fileid'], - responseColumns: ['filename_text'], - recallName: 'vectorRecall', - deepSize: 500 - }; - let vectorWeights = { - 'vectorRecall': 1 - }; - let numberInspector = { - 'vector_query':'filename_text' - }; - let vectorRerankParameter = { - vectorWeights:vectorWeights, - thresholds: [0.55, 0.45, 0.35], - numberInspector: numberInspector - }; - let parameters = { - 0: vectorRerankParameter - }; - let rerankMethod = { - rerankType: 1, - parameters: parameters, - isSoftmaxNormalized: true, - }; - let retrievalCondition = { - rerankMethod: rerankMethod, - recallConditions : [recallConditionInvIdx, recallConditionVector] - }; - await intelligence.getRetriever(retrievalConfig) - .then((data) => { - try { - let query = '数据库'; - data.retrieveRdb(query, retrievalCondition) - .then((rdbdata) => { - let length = rdbdata.records.length; - console.info(TAG, 'Aip_013 get result::' + length); - expect(length >= 2).assertEqual(true); - done(); - }); - } catch (err) { - console.info(TAG, 'Aip_013 catch::' + err.code); - done(); - } - }); - } catch (err) { - console.info(TAG, 'Aip_013 catch::' + err.code); - done(); - } - } else { - await intelligence.getRetriever(retrievalConfig) - .catch((err) => { - console.info(TAG, 'Aip_013 catch::' + err.code); - expect(err.code).assertEqual(801); - done(); - }); - } - console.info(TAG, 'end'); - }); -}); \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/unittest/BUILD.gn b/udmf/framework/jskitsimpl/unittest/BUILD.gn index 75bf5b11..0872196b 100644 --- a/udmf/framework/jskitsimpl/unittest/BUILD.gn +++ b/udmf/framework/jskitsimpl/unittest/BUILD.gn @@ -14,7 +14,7 @@ import("//build/test.gni") import("//foundation/distributeddatamgr/udmf/udmf.gni") -module_output_path = "udmf/jskitsimpl" +module_output_path = "udmf/udmf/jskitsimpl" ohos_js_unittest("UDMFJsTest") { module_out_path = module_output_path diff --git a/udmf/framework/jskitsimpl/unittest/UdmfIntelligenceJsTest.js b/udmf/framework/jskitsimpl/unittest/UdmfIntelligenceJsTest.js new file mode 100644 index 00000000..996291a8 --- /dev/null +++ b/udmf/framework/jskitsimpl/unittest/UdmfIntelligenceJsTest.js @@ -0,0 +1,507 @@ +/* + * 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index'; +import intelligence from '@ohos.data.intelligence'; +import deviceInfo from '@ohos.deviceInfo'; + +const TAG = ['Intelligence_Test']; + +let textConfig = { + version: intelligence.ModelVersion.BASIC_MODEL, + isNpuAvailable: false, + cachePath: 'test' +}; + +let imageConfig = { + version: intelligence.ModelVersion.BASIC_MODEL, + isNpuAvailable: false, + cachePath: 'image' +}; + +let currentDeviceIsPc = false; + +describe('UdmfIntelligenceJsTest', function () { + + beforeAll(async () => { + console.info(TAG + 'beforeAll'); + let deviceTypeInfo = deviceInfo.deviceType; + currentDeviceIsPc = deviceTypeInfo === '2in1' ? true : false; + console.info(TAG + 'the value of the deviceType is : ' + deviceInfo.deviceType); + }); + beforeEach(async () => { + console.info(TAG + 'beforeEach'); + }); + afterEach(async () => { + console.info(TAG + 'afterEach'); + }); + afterAll(async () => { + console.info(TAG + 'afterAll'); + }); + + console.info('*************intelligence Test begin**************'); + let retArray = [401, 801, 313000000]; + + + /** + * @tc.name intelligenceApiTest0100 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0100 + * @tc.desc splitText interface test + * @tc.type Function + */ + it('intelligenceApiTest0100', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0100 start'); + let text = + '日常生活中,我们对接触到的事物,会产生一个不假思索地看法,或者说直觉性的认知.百科全书里这样解释道“ 认知包括感觉、知觉、记忆、思维、想象和语言等。'; + let config = { + size: 50, + overlapRatio: 0.5 + }; + if (currentDeviceIsPc) { + await intelligence.splitText(text, config) + .then((data) => { + console.info(TAG + 'get result:' + data); + let dataSize = data.length; + let ret = dataSize > 0; + expect(ret).assertEqual(true); + done(); + }); + } else { + await intelligence.splitText(text, config) + .then((data) => { + console.info(TAG + 'get result:' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'get promise result:' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest0200 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0100 + * @tc.desc getTextEmbeddingModel promise interface test + * @tc.type Function + */ + it('intelligenceApiTest0200', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0200 start'); + if (currentDeviceIsPc) { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result' + data); + let ret = false; + if (data != null) { + ret = true; + } + expect(ret).assertEqual(true); + done(); + }); + } else { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'get promise result:' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest0300 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0300 + * @tc.desc getImageEmbeddingModel promise interface test + * @tc.type Function + */ + it('intelligenceApiTest0300', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0300 start'); + if (currentDeviceIsPc) { + intelligence.getImageEmbeddingModel(imageConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + let ret = false; + if (data != null) { + ret = true; + } + expect(ret).assertEqual(true); + done(); + }); + } else { + intelligence.getImageEmbeddingModel(imageConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'get promise result:' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest0400 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0400 + * @tc.desc getTextEmbeddingModel loadModel interface test + * @tc.type Function + */ + it('intelligenceApiTest0400', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0400 start'); + if (currentDeviceIsPc) { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + data.loadModel() + .then(() => { + console.info(TAG + 'get loadMldel result 0400:'); + done(); + }); + }); + } else { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + expect().assertFail(); + }) + .catch((err) => { + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest0500 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0500 + * @tc.desc getTextEmbeddingModel loadModel interface test + * @tc.type Function + */ + it('intelligenceApiTest0500', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0500 start'); + if (currentDeviceIsPc) { + try { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + data.loadModel() + .then(() => { + console.info(TAG + 'loadModel success result 0500:'); + data.releaseModel(); + done(); + }); + }); + } catch (err) { + console.info(TAG + 'intelligenceApiTest0500 is fail:'); + expect().assertFail(); + done(); + } + } else { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'get result' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest0600 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0600 + * @tc.desc getTextEmbeddingModel releaseModel abnormal interface test + * @tc.type Function + */ + it('intelligenceApiTest0600', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0600 start'); + if (currentDeviceIsPc) { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + data.releaseModel() + .then(() => { + console.info(TAG + 'releaseModel result 0600:'); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'getEmbedding result' + err.code); + expect(err.code).assertEqual(31300000); + done(); + }); + }); + } else { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + expect().assertFail(); + }) + .catch((err) => { + console.info(TAG + 'loadModel promise result:' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest0700 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0700 + * @tc.desc getTextEmbeddingModel getEmbedding interface test + * @tc.type Function + */ + it('intelligenceApiTest0700', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0700 start'); + if (currentDeviceIsPc) { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + data.getEmbedding('123') + .then((loadData) => { + console.info(TAG + 'getEmbedding result:' + loadData); + let dataSize = loadData.length; + let ret = dataSize > 0; + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'getEmbedding result' + err.code); + expect(err.code).assertEqual(31300000); + done(); + }); + }); + } else { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + expect().assertFail(); + }) + .catch((err) => { + console.info(TAG + 'getEmbedding promise result:' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest0800 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0800 + * @tc.desc getTextEmbeddingModel getEmbedding abnormal interface test + * @tc.type Function + */ + it('intelligenceApiTest0800', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0800 start'); + if (currentDeviceIsPc) { + intelligence.getTextEmbeddingModel(textConfig) + .then(async (data) => { + console.info(TAG + 'get result:' + data); + await data.loadModel(); + let text = 'text'; + data.getEmbedding(text) + .then((loadData) => { + console.info(TAG + 'getEmbedding result 0800 :' + loadData); + let dataSize = loadData.length; + let ret = dataSize > 0; + expect(ret).assertEqual(true); + done(); + }); + }); + } else { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result:' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'getEmbedding promise result:' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest0900 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_0900 + * @tc.desc getTextEmbeddingModel getEmbedding batchTexts interface test + * @tc.type Function + */ + it('intelligenceApiTest0900', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest0900 start'); + if (currentDeviceIsPc) { + intelligence.getTextEmbeddingModel(textConfig) + .then(async (data) => { + console.info(TAG + 'get result: ' + data); + await data.loadModel(); + let batchTexts = ['11', '22', '33']; + data.getEmbedding(batchTexts) + .then((loadData) => { + console.info(TAG + 'getEmbedding result 0900: ' + loadData); + let dataSize = loadData.length; + let ret = dataSize > 0; + expect(ret).assertEqual(true); + done(); + }); + }); + } else { + intelligence.getTextEmbeddingModel(textConfig) + .then((data) => { + console.info(TAG + 'get result: ' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'getEmbedding promise result: ' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest1000 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_1000 + * @tc.desc getImageEmbeddingModel loadModel interface test + * @tc.type Function + */ + it('intelligenceApiTest1000', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest1000 start'); + if (currentDeviceIsPc) { + try { + intelligence.getImageEmbeddingModel(imageConfig) + .then((data) => { + console.info(TAG + 'get result :' + data); + data.loadModel() + .then(() => { + console.info(TAG + 'loadModel result 1000 :'); + data.releaseModel(); + done(); + }); + }); + } catch (err) { + console.info(TAG + 'intelligenceApiTest1000 is fail:'); + expect().assertFail(); + done(); + } + } else { + intelligence.getImageEmbeddingModel(imageConfig) + .then((data) => { + console.info(TAG + 'get result :' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'get promise result' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest1100 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_1100 + * @tc.desc getImageEmbeddingModel(imageConfig) releaseModel interface test + * @tc.type Function + */ + it('intelligenceApiTest1100', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest1100 start'); + if (currentDeviceIsPc) { + intelligence.getImageEmbeddingModel(imageConfig) + .then((data) => { + console.info(TAG + 'get result :' + data); + data.releaseModel() + .then(() => { + console.info(TAG + 'releaseModel result 1100 :'); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'getEmbedding result' + err.code); + expect(err.code).assertEqual(31300000); + done(); + }); + }); + } else { + intelligence.getImageEmbeddingModel(imageConfig) + .then((data) => { + console.info(TAG + 'get result :' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'get promise result' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); + + /** + * @tc.name intelligenceApiTest1200 + * @tc.number SUB_DistributedData_Intelligence_SDK_intelligenceApiTest_1200 + * @tc.desc getImageEmbeddingModel(imageConfig) getEmbedding test interface test + * @tc.type Function + */ + it('intelligenceApiTest1200', 0, async function (done) { + console.info(TAG + 'intelligenceApiTest1200 start'); + if (currentDeviceIsPc) { + intelligence.getImageEmbeddingModel(imageConfig) + .then(async (data) => { + console.info(TAG + 'get result :' + data); + await data.loadModel(); + data.getEmbedding('111.jpg') + .then((loadData) => { + console.info(TAG + 'getEmbedding result 1200 :' + loadData); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.error('Failed to get Embedding and code is ' + err.code); + expect(err.code).assertEqual(31300000); + done(); + }); + }); + } else { + intelligence.getImageEmbeddingModel(imageConfig) + .then((data) => { + console.info(TAG + 'get result :' + data); + expect().assertFail(); + done(); + }) + .catch((err) => { + console.info(TAG + 'get promise result' + err.code); + expect(err.code).assertEqual(801); + done(); + }); + } + }); +}); \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/unittest/UdmfJsTest.js b/udmf/framework/jskitsimpl/unittest/UdmfJsTest.js index dce53307..9d38d15c 100644 --- a/udmf/framework/jskitsimpl/unittest/UdmfJsTest.js +++ b/udmf/framework/jskitsimpl/unittest/UdmfJsTest.js @@ -1106,10 +1106,10 @@ describe('UdmfJSTest', function () { expect(unifiedData.hasType(UTD.UniformDataType.HYPERLINK)).assertEqual(true); expect(unifiedData.hasType('openharmony.app-item')).assertEqual(true); let types = unifiedData.getTypes(); - expect(types.length).assertEqual(3); + expect(types.length).assertEqual(1); expect(types.includes(textType)).assertTrue(); - expect(types.includes(UTD.UniformDataType.HYPERLINK)).assertTrue(); - expect(types.includes('openharmony.app-item')).assertTrue(); + expect(types.includes(UTD.UniformDataType.HYPERLINK)).assertFalse(); + expect(types.includes('openharmony.app-item')).assertFalse(); let html = new UDC.HTML(); unifiedData.addRecord(html); @@ -1117,12 +1117,12 @@ describe('UdmfJSTest', function () { expect(unifiedData.hasType(htmlType)).assertEqual(true); expect(unifiedData.hasType(plaintextType)).assertEqual(false); types = unifiedData.getTypes(); - expect(types.length).assertEqual(4); + expect(types.length).assertEqual(2); expect(types.includes(textType)).assertTrue(); expect(types.includes(htmlType)).assertTrue(); expect(types.includes(textType)).assertTrue(); - expect(types.includes(UTD.UniformDataType.HYPERLINK)).assertTrue(); - expect(types.includes('openharmony.app-item')).assertTrue(); + expect(types.includes(UTD.UniformDataType.HYPERLINK)).assertFalse(); + expect(types.includes('openharmony.app-item')).assertFalse(); }); /** @@ -2293,8 +2293,8 @@ describe('UdmfJSTest', function () { let unifiedData = new UDC.UnifiedData(record); let rawDataTypes = unifiedData.getTypes(); - expect(rawDataTypes.includes('general.file-uri')).assertTrue(); - expect(rawDataTypes.includes('openharmony.pixel-map')).assertTrue(); + expect(rawDataTypes.includes('general.image')).assertTrue(); + expect(rawDataTypes.includes('openharmony.pixel-map')).assertFalse(); expect(unifiedData.hasType('general.file-uri')).assertTrue(); expect(unifiedData.hasType('general.image')).assertTrue(); expect(unifiedData.hasType('general.jpeg')).assertTrue(); @@ -2312,7 +2312,7 @@ describe('UdmfJSTest', function () { expect(getRecordTypes.includes('openharmony.pixel-map')).assertTrue(); let getDataTypes = data[0].getTypes(); - expect(getDataTypes.includes('general.file-uri')).assertTrue(); + expect(getDataTypes.includes('general.image')).assertTrue(); for (let i = 0; i < records.length; i++) { if (records[i].getType() === 'general.image') { let getImageUri = records[i].imageUri; @@ -2399,7 +2399,7 @@ describe('UdmfJSTest', function () { let unifiedData = new UDC.UnifiedData(record); let rawDataTypes = unifiedData.getTypes(); - expect(rawDataTypes.includes('general.file-uri')).assertTrue(); + expect(rawDataTypes.includes('general.image')).assertTrue(); expect(unifiedData.hasType('general.file-uri')).assertTrue(); expect(unifiedData.hasType('general.image')).assertTrue(); try { @@ -2417,7 +2417,7 @@ describe('UdmfJSTest', function () { expect(rawRecordTypes.includes('general.file-uri')).assertTrue(); let rawDataTypes = data[0].getTypes(); - expect(rawDataTypes.includes('general.file-uri')).assertTrue(); + expect(rawDataTypes.includes('general.image')).assertTrue(); for (let i = 0; i < records.length; i++) { if (records[i].getType() === 'general.image') { let getImageUri = records[i].imageUri; @@ -2506,17 +2506,17 @@ describe('UdmfJSTest', function () { record.addEntry('openharmony.pixel-map', pixelMap); record.addEntry('general.file-uri', fileUri); let rawType = record.getType(); - expect(rawType).assertEqual('general.file'); + expect(rawType).assertEqual('general.image'); let rawRecordTypes = record.getTypes(); - expect(rawRecordTypes.includes('general.file')).assertTrue(); + expect(rawRecordTypes.includes('general.file')).assertFalse(); expect(rawRecordTypes.includes('general.file-uri')).assertTrue(); expect(rawRecordTypes.includes('openharmony.pixel-map')).assertTrue(); let unifiedData = new UDC.UnifiedData(record); let rawDataTypes = unifiedData.getTypes(); - expect(rawDataTypes.includes('general.file')).assertTrue(); - expect(rawDataTypes.includes('general.file-uri')).assertTrue(); - expect(rawDataTypes.includes('openharmony.pixel-map')).assertTrue(); + expect(rawDataTypes.includes('general.image')).assertTrue(); + expect(rawDataTypes.includes('general.file-uri')).assertFalse(); + expect(rawDataTypes.includes('openharmony.pixel-map')).assertFalse(); expect(unifiedData.hasType('general.file-uri')).assertTrue(); expect(unifiedData.hasType('general.image')).assertTrue(); expect(unifiedData.hasType('general.jpeg')).assertTrue(); @@ -2528,16 +2528,16 @@ describe('UdmfJSTest', function () { console.info(TAG, 'query success.'); let records = data[0].getRecords(); let rawType = records[0].getType(); - expect(rawType).assertEqual('general.file'); + expect(rawType).assertEqual('general.image'); let getRecordTypes = records[0].getTypes(); - expect(getRecordTypes.includes('general.file')).assertTrue(); + expect(getRecordTypes.includes('general.file')).assertFalse(); expect(getRecordTypes.includes('general.file-uri')).assertTrue(); expect(getRecordTypes.includes('openharmony.pixel-map')).assertTrue(); let getDataTypes = data[0].getTypes(); - expect(rawDataTypes.includes('general.file')).assertTrue(); - expect(getDataTypes.includes('general.file-uri')).assertTrue(); - expect(getDataTypes.includes('openharmony.pixel-map')).assertTrue(); + expect(getDataTypes.includes('general.image')).assertTrue(); + expect(getDataTypes.includes('general.file-uri')).assertFalse(); + expect(getDataTypes.includes('openharmony.pixel-map')).assertFalse(); for (let i = 0; i < records.length; i++) { if (records[i].getType() === 'general.file') { let getUri = records[i].uri; @@ -2545,7 +2545,10 @@ describe('UdmfJSTest', function () { } } let getValue = records[0].getValue(); - expect(getValue).assertEqual(undefined); + expect(getValue.uniformDataType).assertEqual('general.file-uri'); + expect(getValue.oriUri).assertEqual('www.xx.com'); + expect(getValue.fileType).assertEqual('general.jpeg'); + expect(getValue.details.fileUriKey1).assertEqual(123); let getEntryFileUri = records[0].getEntry('general.file-uri'); expect(getEntryFileUri.uniformDataType).assertEqual('general.file-uri'); @@ -2633,8 +2636,8 @@ describe('UdmfJSTest', function () { expect(rawRecordTypes.includes('openharmony.pixel-map')).assertTrue(); let unifiedData = new UDC.UnifiedData(record); let rawDataTypes = unifiedData.getTypes(); - expect(rawDataTypes.includes('general.file-uri')).assertTrue(); - expect(rawDataTypes.includes('openharmony.pixel-map')).assertTrue(); + expect(rawDataTypes.includes('general.video')).assertTrue(); + expect(rawDataTypes.includes('openharmony.pixel-map')).assertFalse(); expect(unifiedData.hasType('general.file-uri')).assertTrue(); expect(unifiedData.hasType('general.video')).assertTrue(); expect(unifiedData.hasType('general.vob')).assertTrue(); @@ -2654,8 +2657,8 @@ describe('UdmfJSTest', function () { expect(getRecordTypes.includes('openharmony.pixel-map')).assertTrue(); let getDataTypes = data[0].getTypes(); - expect(getDataTypes.includes('general.file-uri')).assertTrue(); - expect(getDataTypes.includes('openharmony.pixel-map')).assertTrue(); + expect(getDataTypes.includes('general.video')).assertTrue(); + expect(getDataTypes.includes('openharmony.pixel-map')).assertFalse(); for (let i = 0; i < records.length; i++) { if (records[i].getType() === 'general.video') { let getUri = records[i].videoUri; @@ -2755,8 +2758,8 @@ describe('UdmfJSTest', function () { expect(rawRecordTypes.includes('openharmony.pixel-map')).assertTrue(); let unifiedData = new UDC.UnifiedData(record); let rawDataTypes = unifiedData.getTypes(); - expect(rawDataTypes.includes('general.file-uri')).assertFalse(); - expect(rawDataTypes.includes('openharmony.pixel-map')).assertTrue(); + expect(rawDataTypes.includes('general.vob')).assertTrue(); + expect(rawDataTypes.includes('openharmony.pixel-map')).assertFalse(); expect(unifiedData.hasType('general.file-uri')).assertFalse(); expect(unifiedData.hasType('general.video')).assertTrue(); expect(unifiedData.hasType('general.vob')).assertTrue(); @@ -2777,7 +2780,7 @@ describe('UdmfJSTest', function () { let getDataTypes = data[0].getTypes(); expect(getDataTypes.includes('general.vob')).assertTrue(); expect(getDataTypes.includes('general.file-uri')).assertFalse(); - expect(getDataTypes.includes('openharmony.pixel-map')).assertTrue(); + expect(getDataTypes.includes('openharmony.pixel-map')).assertFalse(); let getValue = records[0].getValue(); expect(getValue.uniformDataType).assertEqual('general.file-uri'); @@ -2876,7 +2879,7 @@ describe('UdmfJSTest', function () { let unifiedData = new UDC.UnifiedData(record); let rawDataTypes = unifiedData.getTypes(); expect(rawDataTypes.includes('general.vob')).assertFalse(); - expect(rawDataTypes.includes('general.file-uri')).assertTrue(); + expect(rawDataTypes.includes('general.file-uri')).assertFalse(); expect(rawDataTypes.includes('openharmony.pixel-map')).assertTrue(); expect(unifiedData.hasType('general.file-uri')).assertTrue(); expect(unifiedData.hasType('general.video')).assertTrue(); @@ -2898,7 +2901,7 @@ describe('UdmfJSTest', function () { let getDataTypes = data[0].getTypes(); expect(getDataTypes.includes('general.vob')).assertFalse(); - expect(getDataTypes.includes('general.file-uri')).assertTrue(); + expect(getDataTypes.includes('general.file-uri')).assertFalse(); expect(getDataTypes.includes('openharmony.pixel-map')).assertTrue(); let getValue = records[0].getValue(); @@ -3069,7 +3072,7 @@ describe('UdmfJSTest', function () { let records = data[0].getRecords(); let firstEntry1 = records[0].getEntry(UTD.UniformDataType.PLAIN_TEXT); expect(firstEntry1.textContent).assertEqual('plaintextValue'); - let firstEntry2 = records[1].getEntry(UTD.UniformDataType.FILE); + let firstEntry2 = records[1].getEntry(UTD.UniformDataType.FILE_URI); expect(firstEntry2.oriUri).assertEqual('schema://com.samples.test/files/test.txt'); let firstEntry3 = records[2].getEntry('ApplicationDefinedType'); expect(firstEntry3.arrayBuffer.length).assertEqual(u8Array.length); @@ -3102,4 +3105,229 @@ describe('UdmfJSTest', function () { done(); } }); + + /** + * @tc.name toEntriesTest001 + * @tc.desc test toEntries function normal + * @tc.type: FUNC + * @tc.require: + */ + it('toEntriesTest001', 0, async function (done) { + const TAG = 'toEntriesTest001'; + console.info(TAG, 'start'); + let file = new UDC.File(); + file.uri = 'schema://com.samples.test/files/test.txt'; + let plainText = new UDC.PlainText(); + plainText.textContent = 'this is textContent'; + plainText.abstract = 'this is abstract'; + let link = new UDC.Hyperlink(); + link.url = 'www.XXX.com'; + link.description = 'this is description'; + let html = new UDC.HTML(); + html.htmlContent = '<div><p>标题</p></div>'; + html.plainContent = 'this is plainContent'; + let form = new UDC.SystemDefinedForm(); + form.formId = 123456; + form.formName = 'MyFormName'; + form.bundleName = 'MyBundleName'; + form.abilityName = 'MyAbilityName'; + form.module = 'MyModule'; + form.details = { + 'formKey1': 123, + 'formKey2': 'formValue', + 'formKey3': U8_ARRAY, + }; + let applicationDefinedRecord = new UDC.ApplicationDefinedRecord(); + applicationDefinedRecord.applicationDefinedType = 'ApplicationDefinedType'; + applicationDefinedRecord.rawData = U8_ARRAY; + let unifiedData = new UDC.UnifiedData(); + unifiedData.addRecord(file); + unifiedData.addRecord(plainText); + unifiedData.addRecord(link); + unifiedData.addRecord(html); + unifiedData.addRecord(form); + unifiedData.addRecord(applicationDefinedRecord); + unifiedData.properties.tag = 'records_to_entries_data_format'; + expect(unifiedData.getRecords().length).assertEqual(6); + UDC.convertRecordsToEntries(unifiedData); + expect(unifiedData.getRecords().length).assertEqual(1); + let records = unifiedData.getRecords(); + let recordEntries = records[0]; + expect(recordEntries.uri).assertEqual('schema://com.samples.test/files/test.txt'); + expect(recordEntries.getType()).assertEqual('general.file'); + expect(recordEntries.getValue()).assertEqual(undefined); + let fileEntry = recordEntries.getEntry('general.file-uri'); + expect(fileEntry.uniformDataType).assertEqual('general.file-uri'); + expect(fileEntry.oriUri).assertEqual('schema://com.samples.test/files/test.txt'); + expect(fileEntry.fileType).assertEqual('general.file'); + let plainTextEntry = recordEntries.getEntry('general.plain-text'); + expect(plainTextEntry.textContent).assertEqual('this is textContent'); + expect(plainTextEntry.abstract).assertEqual('this is abstract'); + let linkEntry = recordEntries.getEntry('general.hyperlink'); + expect(linkEntry.url).assertEqual('www.XXX.com'); + expect(linkEntry.description).assertEqual('this is description'); + let htmlEntry = recordEntries.getEntry('general.html'); + expect(htmlEntry.htmlContent).assertEqual('<div><p>标题</p></div>'); + expect(htmlEntry.plainContent).assertEqual('this is plainContent'); + let formEntry = recordEntries.getEntry('openharmony.form'); + expect(formEntry.formId).assertEqual(123456); + expect(formEntry.formName).assertEqual('MyFormName'); + expect(formEntry.bundleName).assertEqual('MyBundleName'); + expect(formEntry.abilityName).assertEqual('MyAbilityName'); + expect(formEntry.module).assertEqual('MyModule'); + expect(formEntry.details.formKey1).assertEqual(123); + expect(formEntry.details.formKey2).assertEqual('formValue'); + let applicationDefinedEntry = recordEntries.getEntry('ApplicationDefinedType'); + for (let i = 0; i < U8_ARRAY.length; i++) { + expect(applicationDefinedEntry.arrayBuffer[i]).assertEqual(U8_ARRAY[i]); + } + expect(applicationDefinedEntry.uniformDataType).assertEqual('ApplicationDefinedType'); + let entries = recordEntries.getEntries(); + expect(entries['general.file-uri'].uniformDataType).assertEqual('general.file-uri'); + expect(entries['general.file-uri'].oriUri).assertEqual('schema://com.samples.test/files/test.txt'); + expect(entries['general.file-uri'].fileType).assertEqual('general.file'); + expect(entries['general.plain-text'].uniformDataType).assertEqual('general.plain-text'); + expect(entries['general.plain-text'].textContent).assertEqual('this is textContent'); + expect(entries['general.plain-text'].abstract).assertEqual('this is abstract'); + expect(entries['general.hyperlink'].uniformDataType).assertEqual('general.hyperlink'); + expect(entries['general.hyperlink'].url).assertEqual('www.XXX.com'); + expect(entries['general.hyperlink'].description).assertEqual('this is description'); + expect(entries['general.html'].uniformDataType).assertEqual('general.html'); + expect(entries['general.html'].htmlContent).assertEqual('<div><p>标题</p></div>'); + expect(entries['general.html'].plainContent).assertEqual('this is plainContent'); + expect(entries['openharmony.form'].uniformDataType).assertEqual('openharmony.form'); + expect(entries['openharmony.form'].formId).assertEqual(123456); + expect(entries['openharmony.form'].formName).assertEqual('MyFormName'); + expect(entries['openharmony.form'].bundleName).assertEqual('MyBundleName'); + expect(entries['openharmony.form'].abilityName).assertEqual('MyAbilityName'); + expect(entries['openharmony.form'].module).assertEqual('MyModule'); + expect(entries['openharmony.form'].details.formKey1).assertEqual(123); + expect(entries['openharmony.form'].details.formKey2).assertEqual('formValue'); + for (let i = 0; i < U8_ARRAY.length; i++) { + expect(entries.ApplicationDefinedType.arrayBuffer[i]).assertEqual(U8_ARRAY[i]); + } + expect(entries.ApplicationDefinedType.uniformDataType).assertEqual('ApplicationDefinedType'); + done(); + }); + + /** + * @tc.name toEntriesTest002 + * @tc.desc test toEntries function with duplicate type + * @tc.type: FUNC + * @tc.require: + */ + it('toEntriesTest002', 0, async function (done) { + const TAG = 'toEntriesTest002'; + console.info(TAG, 'start'); + let image = new UDC.Image(); + image.uri = 'schema://com.samples.test/files/test.jpg'; + let plainText = new UDC.PlainText(); + plainText.textContent = 'this is textContent'; + plainText.abstract = 'this is abstract'; + let video = new UDC.Video(); + video.uri = 'schema://com.samples.test/files/test.mp4'; + let unifiedData = new UDC.UnifiedData(); + unifiedData.addRecord(image); + unifiedData.addRecord(plainText); + unifiedData.addRecord(video); + unifiedData.properties.tag = 'records_to_entries_data_format'; + expect(unifiedData.getRecords().length).assertEqual(3); + UDC.convertRecordsToEntries(unifiedData); + expect(unifiedData.getRecords().length).assertEqual(1); + let records = unifiedData.getRecords(); + let recordEntries = records[0]; + expect(recordEntries.uri).assertEqual('schema://com.samples.test/files/test.jpg'); + expect(recordEntries.getType()).assertEqual('general.image'); + expect(recordEntries.getValue()).assertEqual(undefined); + let entries = recordEntries.getEntries(); + expect(entries['general.file-uri'].uniformDataType).assertEqual('general.file-uri'); + expect(entries['general.file-uri'].oriUri).assertEqual('schema://com.samples.test/files/test.jpg'); + expect(entries['general.file-uri'].fileType).assertEqual('general.image'); + expect(entries['general.plain-text'].uniformDataType).assertEqual('general.plain-text'); + expect(entries['general.plain-text'].textContent).assertEqual('this is textContent'); + expect(entries['general.plain-text'].abstract).assertEqual('this is abstract'); + expect(entries['general.video']).assertEqual(undefined); + done(); + }); + + /** + * @tc.name toEntriesTest003 + * @tc.desc test toEntries function with duplicate type + * @tc.type: FUNC + * @tc.require: + */ + it('toEntriesTest003', 0, async function (done) { + const TAG = 'toEntriesTest003'; + console.info(TAG, 'start'); + let recordFile = new UDC.UnifiedRecord('general.file', 'schema://com.samples.test/files/test.txt'); + let recordVideo = new UDC.UnifiedRecord('general.video', 'schema://com.samples.test/files/test.mp4'); + let recordPlainText = new UDC.UnifiedRecord('general.plain-text', 'this is textContent'); + let unifiedData = new UDC.UnifiedData(); + unifiedData.addRecord(recordFile); + unifiedData.addRecord(recordVideo); + unifiedData.addRecord(recordPlainText); + unifiedData.properties.tag = 'records_to_entries_data_format'; + expect(unifiedData.getRecords().length).assertEqual(3); + UDC.convertRecordsToEntries(unifiedData); + expect(unifiedData.getRecords().length).assertEqual(1); + let records = unifiedData.getRecords(); + let recordEntries = records[0]; + expect(recordEntries.uri).assertEqual('schema://com.samples.test/files/test.txt'); + expect(recordEntries.getType()).assertEqual('general.file'); + expect(recordEntries.getValue()).assertEqual('schema://com.samples.test/files/test.txt'); + let videoEntry = recordEntries.getEntry('general.file-uri'); + expect(videoEntry.oriUri).assertEqual('schema://com.samples.test/files/test.txt'); + expect(videoEntry.fileType).assertEqual('general.file'); + let plainTextEntry = recordEntries.getEntry('general.plain-text'); + expect(plainTextEntry.textContent).assertEqual('this is textContent'); + let entries = recordEntries.getEntries(); + expect(entries['general.file-uri'].uniformDataType).assertEqual('general.file-uri'); + expect(entries['general.file-uri'].oriUri).assertEqual('schema://com.samples.test/files/test.txt'); + expect(entries['general.file-uri'].fileType).assertEqual('general.file'); + expect(entries['general.plain-text'].uniformDataType).assertEqual('general.plain-text'); + expect(entries['general.plain-text'].textContent).assertEqual('this is textContent'); + expect(entries['general.video']).assertEqual(undefined); + expect(entries['general.file']).assertEqual(undefined); + done(); + }); + + /** + * @tc.name toEntriesTest004 + * @tc.desc test toEntries function with invalid data + * @tc.type: FUNC + * @tc.require: + */ + it('toEntriesTest004', 0, function () { + const TAG = 'toEntriesTest004'; + console.info(TAG, 'start'); + try { + UDC.convertRecordsToEntries(); + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + } catch (e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); + + /** + * @tc.name toEntriesTest005 + * @tc.desc test toEntries function with invalid data + * @tc.type: FUNC + * @tc.require: + */ + it('toEntriesTest005', 0, function () { + const TAG = 'toEntriesTest005'; + console.info(TAG, 'start'); + try { + UDC.convertRecordsToEntries(1); + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + } catch (e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); }); \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/unittest/UdmfPromiseJsTest.js b/udmf/framework/jskitsimpl/unittest/UdmfPromiseJsTest.js index 8b8ab2ca..1993594a 100644 --- a/udmf/framework/jskitsimpl/unittest/UdmfPromiseJsTest.js +++ b/udmf/framework/jskitsimpl/unittest/UdmfPromiseJsTest.js @@ -437,4 +437,55 @@ describe('UdmfPromiseJSTest', function () { } console.info(TAG, 'end'); }); + + /** + * @tc.name UdmfPropertiesMarshallTest + * @tc.desc Test udmf properties Marshall successful + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfPropertiesMarshallTest', 0, async function (done) { + const TAG = 'UdmfPropertiesMarshallTest:'; + console.info(TAG, 'start'); + try { + let person = {fname: 'John', lname: 'Doe', age: 25}; + let props = new UDC.UnifiedDataProperties(); + props.tag = 'DataTag'; + props.shareOptions = UDC.ShareOptions.CROSS_APP; + props.extras = person; + unifiedData01.properties = props; + UDC.insertData(optionsValid, unifiedData01).then((data) => { + console.info(TAG, `insert success. The key: ${data}`); + let options = { key: data }; + console.info(TAG, `query start. The options: ${JSON.stringify(options)}`); + UDC.queryData(options).then((data) => { + console.info(TAG, 'query success.'); + console.info(TAG, `data.length = ${data.length}.`); + expect(data.length).assertEqual(1); + let readProps = data[0].properties; + console.info(TAG, `readProps.tag = ${readProps.tag}.`); + console.info(TAG, `readProps.shareOptions = ${readProps.shareOptions}.`); + console.info(TAG, `readProps.extras = ${JSON.stringify(readProps.extras)}.`); + expect(readProps.tag).assertEqual('DataTag'); + expect(readProps.shareOptions).assertEqual(UDC.ShareOptions.CROSS_APP); + expect(Object.keys(readProps.extras).length).assertEqual(3); + expect(readProps.extras.fname).assertEqual(person.fname); + done(); + }).catch(() => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + }).catch(() => { + console.info(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error(TAG, 'Unreachable code!'); + expect(null).assertFail(); + done(); + } + console.info(TAG, 'end'); + }); }); \ No newline at end of file diff --git a/udmf/framework/ndkimpl/data/data_provider_impl.cpp b/udmf/framework/ndkimpl/data/data_provider_impl.cpp index cbef6db3..3f392685 100644 --- a/udmf/framework/ndkimpl/data/data_provider_impl.cpp +++ b/udmf/framework/ndkimpl/data/data_provider_impl.cpp @@ -42,12 +42,13 @@ ValueType DataProviderImpl::GetValueByType(const std::string &utdId) auto value = (innerProvider_->callback)(innerProvider_->context, utdId.c_str()); if (value == nullptr) { LOG_ERROR( - UDMF_CAPI, "get empty data when execute custom callback function, utdId is %{public}s", utdId.c_str()); + UDMF_CAPI, "get empty data when execute custom callback function"); return std::monostate(); } UdsObject* object = static_cast<UdsObject *>(value); if (IsInvalidUdsObjectByType(object, static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(utdId)))) { LOG_ERROR(UDMF_CAPI, "data type mismatch"); + delete object; return std::monostate(); } std::shared_ptr<OHOS::UDMF::Object> obj = std::move(object->obj); diff --git a/udmf/framework/ndkimpl/data/udmf.cpp b/udmf/framework/ndkimpl/data/udmf.cpp index 1e857a4f..6f8ef8d5 100644 --- a/udmf/framework/ndkimpl/data/udmf.cpp +++ b/udmf/framework/ndkimpl/data/udmf.cpp @@ -14,34 +14,36 @@ */ #define LOG_TAG "Udmf" #include "udmf.h" -#include "udmf_err_code.h" +#include "application_defined_record.h" +#include "audio.h" #include "data_provider_impl.h" -#include "udmf_client.h" -#include "securec.h" -#include "udmf_capi_common.h" +#include "file.h" +#include "folder.h" +#include "html.h" +#include "image.h" #include "int_wrapper.h" -#include "string_wrapper.h" -#include "unified_meta.h" -#include "udmf_meta.h" +#include "link.h" #include "logger.h" +#include "ndk_data_conversion.h" #include "plain_text.h" -#include "link.h" -#include "html.h" +#include "securec.h" +#include "string_wrapper.h" #include "system_defined_appitem.h" -#include "application_defined_record.h" #include "system_defined_pixelmap.h" -#include "file.h" -#include "audio.h" -#include "folder.h" -#include "image.h" -#include "video.h" +#include "udmf_capi_common.h" +#include "udmf_client.h" +#include "udmf_err_code.h" +#include "udmf_meta.h" +#include "unified_meta.h" #include "utd.h" #include "utd_client.h" +#include "video.h" using namespace OHOS::UDMF; static constexpr uint64_t MAX_RECORDS_COUNT = 4 * 1024 * 1024; static constexpr uint64_t MAX_KEY_STRING_LEN = 1 * 1024 * 1024; +static constexpr uint64_t MAX_TYPES_COUNT = 10 * 1024; static const std::map<std::string, UDType> FILE_TYPES = { { UDMF_META_GENERAL_FILE, UDType::FILE }, { UDMF_META_AUDIO, UDType::AUDIO }, @@ -49,24 +51,13 @@ static const std::map<std::string, UDType> FILE_TYPES = { { UDMF_META_IMAGE, UDType::IMAGE }, { UDMF_META_VIDEO, UDType::VIDEO } }; -static const std::set<std::string> FILE_SUB_TYPES = { - "general.image", "general.video", "general.audio", "general.folder" }; -static void DestroyStringArray(char**& bufArray, unsigned int& count) -{ - if (bufArray == nullptr) { - return; - } - for (unsigned int i = 0; i < count; i++) { - if (bufArray[i] != nullptr) { - delete[] bufArray[i]; - bufArray[i] = nullptr; - } - } - delete[] bufArray; - bufArray = nullptr; - count = 0; -} +static const std::map<Udmf_Intention, Intention> VAILD_INTENTIONS = { + { UDMF_INTENTION_DRAG, Intention::UD_INTENTION_DRAG }, + { UDMF_INTENTION_SYSTEM_SHARE, Intention::UD_INTENTION_SYSTEM_SHARE }, + { UDMF_INTENTION_PICKER, Intention::UD_INTENTION_PICKER }, + { UDMF_INTENTION_MENU, Intention::UD_INTENTION_MENU } +}; static void DestroyUnifiedRecordArray(OH_UdmfRecord**& records, unsigned int& count) { @@ -75,6 +66,11 @@ static void DestroyUnifiedRecordArray(OH_UdmfRecord**& records, unsigned int& co } for (unsigned int i = 0; i < count; i++) { if (records[i] != nullptr) { + if (records[i]->recordData != nullptr) { + delete records[i]->recordData; + records[i]->recordData = nullptr; + } + NdkDataConversion::DestroyStringArray(records[i]->typesArray, records[i]->typesCount); delete records[i]; records[i] = nullptr; } @@ -84,36 +80,6 @@ static void DestroyUnifiedRecordArray(OH_UdmfRecord**& records, unsigned int& co count = 0; } -static char** StrVectorToTypesArray(const std::vector<std::string>& strVector) -{ - unsigned int vectorSize = strVector.size(); - if (vectorSize == 0 || vectorSize > MAX_RECORDS_COUNT) { - return nullptr; - } - char** typesArray = new (std::nothrow) char* [vectorSize]; - if (typesArray == nullptr) { - LOG_ERROR(UDMF_CAPI, "create types array failed!, vectorSize: %{public}d, MAX_RECORDS_COUNT: %{public}" PRIu64, - vectorSize, MAX_RECORDS_COUNT); - return nullptr; - } - for (unsigned int i = 0; i < vectorSize; ++i) { - unsigned int strLen = strVector[i].length() + 1; - if (strLen > MAX_KEY_STRING_LEN) { - LOG_INFO(UDMF_CAPI, "string exceeds maximum length, length is %{public}d", strLen); - DestroyStringArray(typesArray, vectorSize); - return nullptr; - } - typesArray[i] = new (std::nothrow) char[strLen]; - if (typesArray[i] == nullptr || - (strcpy_s(typesArray[i], strLen, strVector[i].c_str())) != EOK) { - LOG_ERROR(UDMF_CAPI, "string copy failed"); - DestroyStringArray(typesArray, vectorSize); - return nullptr; - } - } - return typesArray; -} - static OH_UdmfRecord** CreateUnifiedDataRecordsArray(OH_UdmfData* unifiedData, std::vector<std::shared_ptr<UnifiedRecord>>& records) { @@ -158,6 +124,9 @@ static bool IsUnifiedPropertiesValid(OH_UdmfProperty* properties) static void AddFileUriTypeIfContains(std::vector<std::string>& types) { + if (std::find(types.begin(), types.end(), UDMF_META_GENERAL_FILE_URI) != types.end()) { + return; + } for (auto type : types) { if (FILE_TYPES.find(type) != FILE_TYPES.end()) { types.push_back(UDMF_META_GENERAL_FILE_URI); @@ -182,8 +151,11 @@ void OH_UdmfData_Destroy(OH_UdmfData* data) if (data == nullptr) { return; } - DestroyStringArray(data->typesArray, data->typesCount); - DestroyUnifiedRecordArray(data->records, data->recordsCount); + { + std::lock_guard<std::mutex> lock(data->mutex); + NdkDataConversion::DestroyStringArray(data->typesArray, data->typesCount); + DestroyUnifiedRecordArray(data->records, data->recordsCount); + } delete data; } @@ -214,7 +186,7 @@ char** OH_UdmfData_GetTypes(OH_UdmfData* unifiedData, unsigned int* count) } std::vector<std::string> typeLabels = unifiedData->unifiedData_->GetEntriesTypes(); AddFileUriTypeIfContains(typeLabels); - unifiedData->typesArray = StrVectorToTypesArray(typeLabels); + unifiedData->typesArray = NdkDataConversion::StrVectorToTypesArray(typeLabels); unifiedData->typesArray == nullptr ? unifiedData->typesCount = 0 : unifiedData->typesCount = typeLabels.size(); *count = unifiedData->typesCount; return unifiedData->typesArray; @@ -231,10 +203,10 @@ char** OH_UdmfRecord_GetTypes(OH_UdmfRecord* record, unsigned int* count) *count = record->typesCount; return record->typesArray; } - auto types = record->record_->GetUtdIds(); + auto types = record->record_->GetUtdIdsWithAddFileType(false); std::vector<std::string> typeLabels {types.begin(), types.end()}; AddFileUriTypeIfContains(typeLabels); - record->typesArray = StrVectorToTypesArray(typeLabels); + record->typesArray = NdkDataConversion::StrVectorToTypesArray(typeLabels); record->typesArray == nullptr ? record->typesCount = 0 : record->typesCount = typeLabels.size(); *count = record->typesCount; return record->typesArray; @@ -365,24 +337,178 @@ bool OH_UdmfData_IsLocal(OH_UdmfData* data) return !isRemote; } +OH_UdmfOptions* OH_UdmfOptions_Create() +{ + OH_UdmfOptions* options = new (std::nothrow) OH_UdmfOptions; + if (options == nullptr) { + LOG_ERROR(UDMF_CAPI, "The OH_UdmfOptions create error"); + return nullptr; + } + return options; +} + +void OH_UdmfOptions_Destroy(OH_UdmfOptions* pThis) +{ + if (pThis != nullptr) { + delete pThis; + pThis = nullptr; + } +} + +const char* OH_UdmfOptions_GetKey(OH_UdmfOptions* pThis) +{ + if (pThis == nullptr) { + LOG_ERROR(UDMF_CAPI, "The OH_UdmfOptions get key error, invaild params!"); + return nullptr; + } + return pThis->key.c_str(); +} + +int OH_UdmfOptions_SetKey(OH_UdmfOptions* pThis, const char* key) +{ + if (pThis == nullptr || key == nullptr) { + LOG_ERROR(UDMF_CAPI, "The OH_UdmfOptions set key error, invaild params!"); + return UDMF_E_INVALID_PARAM; + } + std::string keyStr(key); + if (keyStr.length() > UDMF_KEY_BUFFER_LEN) { + LOG_ERROR(UDMF_CAPI, "key length exceeds maximum length, length is %{public}zu", keyStr.length()); + return UDMF_E_INVALID_PARAM; + } + pThis->key = keyStr; + return UDMF_E_OK; +} + +Udmf_Intention OH_UdmfOptions_GetIntention(OH_UdmfOptions* pThis) +{ + if (pThis == nullptr) { + LOG_ERROR(UDMF_CAPI, "The OH_UdmfOptions get intention error, invaild params!"); + return Udmf_Intention {}; + } + return pThis->intention; +} + +int OH_UdmfOptions_SetIntention(OH_UdmfOptions* pThis, Udmf_Intention intention) +{ + if (pThis == nullptr) { + LOG_ERROR(UDMF_CAPI, "The OH_UdmfOptions set intention error, invaild params!"); + return UDMF_E_INVALID_PARAM; + } + + pThis->intention = intention; + return UDMF_E_OK; +} + +int OH_UdmfOptions_Reset(OH_UdmfOptions* pThis) +{ + if (pThis == nullptr) { + LOG_ERROR(UDMF_CAPI, "The OH_UdmfOptions reset error, invaild params!"); + return UDMF_E_INVALID_PARAM; + } + pThis->key.clear(); + pThis->intention = Udmf_Intention {}; + return UDMF_E_OK; +} + +Udmf_Visibility OH_UdmfOptions_GetVisibility(OH_UdmfOptions* pThis) +{ + if (pThis == nullptr) { + LOG_ERROR(UDMF_CAPI, "The Udmf_Visibility get visibility error, invaild params!"); + return Udmf_Visibility::UDMF_ALL; + } + return pThis->visibility; +} + +int OH_UdmfOptions_SetVisibility(OH_UdmfOptions* pThis, Udmf_Visibility visibility) +{ + if (pThis == nullptr) { + LOG_ERROR(UDMF_CAPI, "The Udmf_Visibility set visibility error, invaild params!"); + return UDMF_E_INVALID_PARAM; + } + pThis->visibility = visibility; + return UDMF_E_OK; +} + int OH_Udmf_GetUnifiedData(const char* key, Udmf_Intention intention, OH_UdmfData* data) { if (!IsUnifiedDataValid(data) || key == nullptr) { return UDMF_E_INVALID_PARAM; } Intention queryOptIntent; - switch (intention) { - case UDMF_INTENTION_DRAG: - queryOptIntent = Intention::UD_INTENTION_DRAG; + auto it = VAILD_INTENTIONS.find(intention); + if (it != VAILD_INTENTIONS.end()) { + queryOptIntent = it->second; + } else { + return UDMF_E_INVALID_PARAM; + } + QueryOption query = {.key = std::string(key), .intention = queryOptIntent}; + if (Intention::UD_INTENTION_DRAG == queryOptIntent) { + if (UdmfClient::GetInstance().GetData(query, *(data->unifiedData_)) != E_OK) { + LOG_ERROR(UDMF_CAPI, "get data error"); + return UDMF_ERR; + } + return UDMF_E_OK; + } + if (UnifiedDataUtils::IsFileMangerIntention(UD_INTENTION_MAP.at(queryOptIntent))) { + std::vector<UnifiedData> unifiedDataSet; + auto ret = UdmfClient::GetInstance().GetBatchData(query, unifiedDataSet); + if (ret != E_OK) { + LOG_ERROR(UDMF_CAPI, "get batchdata error:%{public}d", ret); + return UDMF_ERR; + } + if (unifiedDataSet.empty()) { + return UDMF_E_OK; + } else { + data->unifiedData_ = std::make_shared<OHOS::UDMF::UnifiedData>(unifiedDataSet[0]); + } + } + return UDMF_E_OK; +} + +int OH_Udmf_GetUnifiedDataByOptions(OH_UdmfOptions* options, OH_UdmfData** dataArray, unsigned int* dataSize) +{ + if (options == nullptr || dataSize == nullptr || dataArray == nullptr) { + LOG_ERROR(UDMF_CAPI, "The input param error"); + return UDMF_E_INVALID_PARAM; + } + Intention queryOptIntent; + switch (options->intention) { + case UDMF_INTENTION_DATA_HUB: + queryOptIntent = Intention::UD_INTENTION_DATA_HUB; + break; + case UDMF_INTENTION_SYSTEM_SHARE: + queryOptIntent = Intention::UD_INTENTION_SYSTEM_SHARE; + break; + case UDMF_INTENTION_PICKER: + queryOptIntent = Intention::UD_INTENTION_PICKER; + break; + case UDMF_INTENTION_MENU: + queryOptIntent = Intention::UD_INTENTION_MENU; break; default: + LOG_ERROR(UDMF_CAPI, "Intention error, it's not one of the above enumerations"); return UDMF_E_INVALID_PARAM; } - QueryOption query = {.key = std::string(key), .intention = queryOptIntent}; - if (UdmfClient::GetInstance().GetData(query, *(data->unifiedData_)) != E_OK) { - LOG_ERROR(UDMF_CAPI, "get data error"); + QueryOption query = {.key = std::string(options->key), .intention = queryOptIntent}; + + std::vector<UnifiedData> unifiedData; + int32_t ret = UdmfClient::GetInstance().GetBatchData(query, unifiedData); + if (ret != E_OK) { + LOG_ERROR(UDMF_CAPI, "Get batch data error,ret = %{public}d", ret); return UDMF_ERR; } + *dataSize = unifiedData.size(); + if (*dataSize == 0) { + return E_OK; + } + *dataArray = new (std::nothrow) OH_UdmfData[*dataSize]; + if (*dataArray == nullptr) { + LOG_ERROR(UDMF_CAPI, "New dataArray error"); + return UDMF_ERR; + } + for (unsigned int i = 0; i < *dataSize; i++) { + (*dataArray)[i].unifiedData_ = std::make_shared<UnifiedData>(unifiedData[i]); + } return UDMF_E_OK; } @@ -391,27 +517,154 @@ int OH_Udmf_SetUnifiedData(Udmf_Intention intention, OH_UdmfData* unifiedData, c if (!IsUnifiedDataValid(unifiedData) || key == nullptr || keyLen < UDMF_KEY_BUFFER_LEN) { return UDMF_E_INVALID_PARAM; } - enum Intention customOptIntent; - switch (intention) { - case UDMF_INTENTION_DRAG: - customOptIntent = Intention::UD_INTENTION_DRAG; - break; - default: - return UDMF_E_INVALID_PARAM; + Intention customOptIntent; + auto it = VAILD_INTENTIONS.find(intention); + if (it != VAILD_INTENTIONS.end()) { + customOptIntent = it->second; + } else { + LOG_ERROR(UDMF_CAPI, "The intention is invalid"); + return UDMF_E_INVALID_PARAM; } CustomOption option = {.intention = customOptIntent}; std::string keyStr; if ((UdmfClient::GetInstance().SetData(option, *(unifiedData->unifiedData_), keyStr)) != E_OK) { - LOG_ERROR(UDMF_CAPI, "set data error"); + LOG_ERROR(UDMF_CAPI, "Set data error"); return UDMF_ERR; } if (strcpy_s(key, keyLen, keyStr.c_str()) != EOK) { - LOG_ERROR(UDMF_CAPI, "string copy failed"); + LOG_ERROR(UDMF_CAPI, "String copy failed"); + return UDMF_ERR; + } + return UDMF_E_OK; +} + +int OH_Udmf_SetUnifiedDataByOptions(OH_UdmfOptions* options, OH_UdmfData* unifiedData, char* key, unsigned int keyLen) +{ + if (!IsUnifiedDataValid(unifiedData) || key == nullptr || keyLen < UDMF_KEY_BUFFER_LEN || options == nullptr) { + LOG_ERROR(UDMF_CAPI, "The set param invalid"); + return UDMF_E_INVALID_PARAM; + } + Intention customOptIntent; + switch (options->intention) { + case UDMF_INTENTION_DATA_HUB: + customOptIntent = Intention::UD_INTENTION_DATA_HUB; + break; + case UDMF_INTENTION_SYSTEM_SHARE: + customOptIntent = Intention::UD_INTENTION_SYSTEM_SHARE; + break; + case UDMF_INTENTION_PICKER: + customOptIntent = Intention::UD_INTENTION_PICKER; + break; + case UDMF_INTENTION_MENU: + customOptIntent = Intention::UD_INTENTION_MENU; + break; + default: + LOG_ERROR(UDMF_CAPI, "Intention error, it's not one of the above enumerations"); + return UDMF_E_INVALID_PARAM; + } + Visibility customOptVisibility; + switch (options->visibility) { + case UDMF_ALL: + customOptVisibility = Visibility::VISIBILITY_ALL; + break; + case UDMF_OWN_PROCESS: + customOptVisibility = Visibility::VISIBILITY_OWN_PROCESS; + break; + default: + LOG_ERROR(UDMF_CAPI, "Invalid visibility value: %{public}d", options->visibility); + return UDMF_E_INVALID_PARAM; + } + CustomOption option = {.intention = customOptIntent, .visibility = customOptVisibility}; + std::string keyStr; + int32_t ret = UdmfClient::GetInstance().SetData(option, *(unifiedData->unifiedData_), keyStr); + if (ret != E_OK) { + LOG_ERROR(UDMF_CAPI, "Set data error,ret = %{public}d", ret); + return UDMF_ERR; + } + if (strcpy_s(key, keyLen, keyStr.c_str()) != E_OK) { + LOG_ERROR(UDMF_CAPI, "String copy failed"); return UDMF_ERR; } return UDMF_E_OK; } +int OH_Udmf_UpdateUnifiedData(OH_UdmfOptions* options, OH_UdmfData* unifiedData) +{ + if (!IsUnifiedDataValid(unifiedData) || options == nullptr || options->key.empty()) { + LOG_ERROR(UDMF_CAPI, "The update error, lnvaild params!"); + return UDMF_E_INVALID_PARAM; + } + if (options->intention != UDMF_INTENTION_DATA_HUB) { + LOG_ERROR(UDMF_CAPI, "Intention error, Intention is %{public}d", options->intention); + return UDMF_E_INVALID_PARAM; + } + QueryOption query = {.key = options->key}; + int32_t ret = UdmfClient::GetInstance().UpdateData(query, *(unifiedData->unifiedData_)); + if (ret != E_OK) { + LOG_ERROR(UDMF_CAPI, "Updata error,ret = %{public}d", ret); + return UDMF_ERR; + } + return UDMF_E_OK; +} + +int OH_Udmf_DeleteUnifiedData(OH_UdmfOptions* options, OH_UdmfData** dataArray, unsigned int* dataSize) +{ + if (options == nullptr || dataSize == nullptr || dataArray == nullptr) { + LOG_ERROR(UDMF_CAPI, "The delete param invalid"); + return UDMF_E_INVALID_PARAM; + } + Intention queryOptIntent; + switch (options->intention) { + case UDMF_INTENTION_DATA_HUB: + queryOptIntent = Intention::UD_INTENTION_DATA_HUB; + break; + case UDMF_INTENTION_SYSTEM_SHARE: + queryOptIntent = Intention::UD_INTENTION_SYSTEM_SHARE; + break; + case UDMF_INTENTION_PICKER: + queryOptIntent = Intention::UD_INTENTION_PICKER; + break; + case UDMF_INTENTION_MENU: + queryOptIntent = Intention::UD_INTENTION_MENU; + break; + default: + LOG_ERROR(UDMF_CAPI, "Intention error, it's not one of the above enumerations"); + return UDMF_E_INVALID_PARAM; + } + QueryOption query = {.key = options->key, .intention = queryOptIntent}; + std::vector<UnifiedData> unifiedData; + int32_t ret = UdmfClient::GetInstance().DeleteData(query, unifiedData); + if (ret != E_OK) { + LOG_ERROR(UDMF_CAPI, "Delete data error,key is %{public}s, ret = %{public}d", + query.key.c_str(), ret); + return UDMF_ERR; + } + *dataSize = unifiedData.size(); + *dataArray = new (std::nothrow) OH_UdmfData[*dataSize]; + if (*dataArray == nullptr) { + LOG_ERROR(UDMF_CAPI, "New dataArray error"); + return UDMF_ERR; + } + for (unsigned int i = 0; i < *dataSize; i++) { + (*dataArray)[i].unifiedData_ = std::make_shared<UnifiedData>(unifiedData[i]); + } + return UDMF_E_OK; +} + +void OH_Udmf_DestroyDataArray(OH_UdmfData** dataArray, unsigned int dataSize) +{ + if (dataArray == nullptr || *dataArray == nullptr) { + LOG_ERROR(UDMF_CAPI, "The DestroyDataArray error, invaild params!"); + return; + } + for (unsigned int i = 0; i < dataSize; ++i) { + NdkDataConversion::DestroyStringArray((*dataArray)[i].typesArray, (*dataArray)[i].typesCount); + DestroyUnifiedRecordArray((*dataArray)[i].records, (*dataArray)[i].recordsCount); + } + delete[] *dataArray; + *dataArray = nullptr; +} + OH_UdmfRecord* OH_UdmfRecord_Create() { OH_UdmfRecord* record = new (std::nothrow) OH_UdmfRecord; @@ -427,11 +680,14 @@ void OH_UdmfRecord_Destroy(OH_UdmfRecord* record) if (record == nullptr) { return; } - if (record->recordData != nullptr) { - delete[] record->recordData; - record->recordData = nullptr; + { + std::lock_guard<std::mutex> lock(record->mutex); + if (record->recordData != nullptr) { + delete[] record->recordData; + record->recordData = nullptr; + } + NdkDataConversion::DestroyStringArray(record->typesArray, record->typesCount); } - DestroyStringArray(record->typesArray, record->typesCount); delete record; } @@ -483,7 +739,7 @@ static int GetValueFromUint8Array(OH_UdmfRecord *record, const char *typeId, Val } auto err = memcpy_s(record->recordData, record->recordDataLen, recordValue.data(), record->recordDataLen); if (err != EOK) { - LOG_ERROR(UDMF_CAPI, "memcpy error! type:%{public}s", typeId); + LOG_ERROR(UDMF_CAPI, "memcpy error!"); return UDMF_ERR; } record->lastType = const_cast<char*>(typeId); @@ -497,7 +753,7 @@ int OH_UdmfRecord_GetGeneralEntry(OH_UdmfRecord* record, const char* typeId, uns } std::lock_guard<std::mutex> lock(record->mutex); if (!record->record_->HasType(typeId)) { - LOG_ERROR(UDMF_CAPI, "no type:%{public}s", typeId); + LOG_ERROR(UDMF_CAPI, "not has typeId"); return UDMF_E_INVALID_PARAM; } if (record->lastType == typeId && record->recordData != nullptr) { @@ -514,7 +770,7 @@ int OH_UdmfRecord_GetGeneralEntry(OH_UdmfRecord* record, const char* typeId, uns } auto result = GetValueFromUint8Array(record, typeId, value); if (result != UDMF_E_OK) { - LOG_ERROR(UDMF_CAPI, "Get value from valueType failed. typeId: %{public}s, result: %{public}d", typeId, result); + LOG_ERROR(UDMF_CAPI, "Get value from valueType failed. result: %{public}d", result); return result; } *count = record->recordDataLen; @@ -590,17 +846,9 @@ int OH_UdmfRecord_AddFileUri(OH_UdmfRecord* record, OH_UdsFileUri* fileUri) { AddUds<Folder>(record, fileUri, UDType::FOLDER); }}, }; int32_t utdId = UDType::FILE; - std::shared_ptr<TypeDescriptor> descriptor; - UtdClient::GetInstance().GetTypeDescriptor(*fileType, descriptor); - if (descriptor != nullptr) { - bool isFileType = false; - for (const auto &fileSub : FILE_SUB_TYPES) { - descriptor->BelongsTo(fileSub, isFileType); - if (isFileType) { - utdId = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(*fileType)); - break; - } - } + std::string subFileType = UnifiedDataUtils::GetBelongsToFileType(*fileType); + if (!subFileType.empty()) { + utdId = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(subFileType)); } addFileUriFuncs[static_cast<UDType>(utdId)](record, fileUri); return UDMF_E_OK; @@ -887,7 +1135,8 @@ int OH_UdmfRecordProvider_SetData(OH_UdmfRecordProvider* provider, void* context int OH_UdmfRecord_SetProvider(OH_UdmfRecord* record, const char* const* types, unsigned int count, OH_UdmfRecordProvider* provider) { - if (!IsUnifiedRecordValid(record) || types == nullptr || count == 0 || provider == nullptr) { + if (!IsUnifiedRecordValid(record) || types == nullptr || count == 0 + || count > MAX_TYPES_COUNT || provider == nullptr) { return UDMF_E_INVALID_PARAM; } std::shared_ptr<DataProviderImpl> providerBox = std::make_shared<DataProviderImpl>(); @@ -968,4 +1217,114 @@ void OH_UdmfGetDataParams_SetDataProgressListener(OH_UdmfGetDataParams* params, return; } params->dataProgressListener = dataProgressListener; +} + +void OH_UdmfGetDataParams_SetAcceptableInfo(OH_UdmfGetDataParams* params, OH_UdmfDataLoadInfo* acceptableInfo) +{ + if (params == nullptr || acceptableInfo == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return; + } + params->acceptableInfo = *acceptableInfo; +} + +OH_UdmfDataLoadParams* OH_UdmfDataLoadParams_Create() +{ + OH_UdmfDataLoadParams *params = new (std::nothrow) OH_UdmfDataLoadParams; + if (params == nullptr) { + LOG_ERROR(UDMF_CAPI, "Allocate OH_UdmfDataLoadParams memory failed."); + return nullptr; + } + return params; +} + +void OH_UdmfDataLoadParams_Destroy(OH_UdmfDataLoadParams* pThis) +{ + if (pThis == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return; + } + delete pThis; +} + +void OH_UdmfDataLoadParams_SetLoadHandler(OH_UdmfDataLoadParams* params, const OH_Udmf_DataLoadHandler dataLoadHandler) +{ + if (params == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return; + } + params->dataLoadHandler = dataLoadHandler; +} + +void OH_UdmfDataLoadParams_SetDataLoadInfo(OH_UdmfDataLoadParams* params, OH_UdmfDataLoadInfo* dataLoadInfo) +{ + if (params == nullptr || dataLoadInfo == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return; + } + params->dataLoadInfo = *dataLoadInfo; +} + +OH_UdmfDataLoadInfo* OH_UdmfDataLoadInfo_Create() +{ + OH_UdmfDataLoadInfo *params = new (std::nothrow) OH_UdmfDataLoadInfo; + if (params == nullptr) { + LOG_ERROR(UDMF_CAPI, "Allocate OH_UdmfDataLoadInfo memory failed."); + return nullptr; + } + return params; +} + +void OH_UdmfDataLoadInfo_Destroy(OH_UdmfDataLoadInfo* dataLoadInfo) +{ + if (dataLoadInfo == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return; + } + NdkDataConversion::DestroyStringArray(dataLoadInfo->typesArray, dataLoadInfo->typesCount); + delete dataLoadInfo; +} + +char** OH_UdmfDataLoadInfo_GetTypes(OH_UdmfDataLoadInfo* dataLoadInfo, unsigned int* count) +{ + if (dataLoadInfo == nullptr || count == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return nullptr; + } + *count = dataLoadInfo->typesCount; + return dataLoadInfo->typesArray; +} + +void OH_UdmfDataLoadInfo_SetType(OH_UdmfDataLoadInfo* dataLoadInfo, const char* type) +{ + if (dataLoadInfo == nullptr || type == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return; + } + std::set<std::string> types; + for (unsigned int i = 0; i < dataLoadInfo->typesCount; ++i) { + types.insert(dataLoadInfo->typesArray[i]); + } + types.insert(type); + std::vector<std::string> typeLabels {types.begin(), types.end()}; + dataLoadInfo->typesArray = NdkDataConversion::StrVectorToTypesArray(typeLabels); + dataLoadInfo->typesCount = typeLabels.size(); +} + +int OH_UdmfDataLoadInfo_GetRecordCount(OH_UdmfDataLoadInfo* dataLoadInfo) +{ + if (dataLoadInfo == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return 0; + } + return static_cast<int>(dataLoadInfo->recordsCount); +} + +void OH_UdmfDataLoadInfo_SetRecordCount(OH_UdmfDataLoadInfo* dataLoadInfo, unsigned int recordCount) +{ + if (dataLoadInfo == nullptr) { + LOG_ERROR(UDMF_CAPI, "Parameter error."); + return; + } + dataLoadInfo->recordsCount = recordCount; } \ No newline at end of file diff --git a/udmf/framework/ndkimpl/data/udmf_capi_common.h b/udmf/framework/ndkimpl/data/udmf_capi_common.h index d22d2ccf..07200751 100644 --- a/udmf/framework/ndkimpl/data/udmf_capi_common.h +++ b/udmf/framework/ndkimpl/data/udmf_capi_common.h @@ -29,9 +29,10 @@ struct UdsObject { std::shared_ptr<OHOS::UDMF::Object> obj; std::mutex mutex; explicit UdsObject(int cid); - template<typename T> bool HasObjectKey(const char* paramName); template<typename T> T* GetUdsValue(const char* paramName); template<typename T> int SetUdsValue(const char* paramName, const T &pramValue); +private: + template<typename T> bool HasObjectKey(const char* paramName); }; enum NdkStructId : std::int64_t { @@ -53,12 +54,12 @@ struct OH_Utd { const int64_t cid = UTD_STRUCT_ID; std::mutex mutex; std::string typeId; - const char** belongingToTypes{nullptr}; - unsigned int belongingToTypesCount{0}; - const char** filenameExtensions{nullptr}; - unsigned int filenameExtensionsCount{0}; - const char** mimeTypes{nullptr}; - unsigned int mimeTypeCount{0}; + const char **belongingToTypes {nullptr}; + unsigned int belongingToTypesCount {0}; + const char **filenameExtensions {nullptr}; + unsigned int filenameExtensionsCount {0}; + const char **mimeTypes {nullptr}; + unsigned int mimeTypeCount {0}; std::string description; std::string referenceURL; std::string iconFile; @@ -92,21 +93,21 @@ struct OH_UdsContentForm : public UdsObject { struct OH_UdmfRecord { const int64_t cid = UDMF_UNIFIED_RECORD_STRUCT_ID; std::shared_ptr<OHOS::UDMF::UnifiedRecord> record_; - unsigned char *recordData{nullptr}; - unsigned int recordDataLen{0}; - char **typesArray{nullptr}; - unsigned int typesCount{0}; - char *lastType{nullptr}; + unsigned char *recordData {nullptr}; + unsigned int recordDataLen {0}; + char **typesArray {nullptr}; + unsigned int typesCount {0}; + char *lastType {nullptr}; std::mutex mutex; }; struct OH_UdmfData { const int64_t cid = UDMF_UNIFIED_DATA_STRUCT_ID; std::shared_ptr<OHOS::UDMF::UnifiedData> unifiedData_; - char **typesArray{nullptr}; - unsigned int typesCount{0}; - OH_UdmfRecord **records{nullptr}; - unsigned int recordsCount{0}; + char **typesArray {nullptr}; + unsigned int typesCount {0}; + OH_UdmfRecord **records {nullptr}; + unsigned int recordsCount {0}; std::mutex mutex; }; @@ -122,12 +123,29 @@ struct OH_Udmf_ProgressInfo { int status; }; +struct OH_UdmfDataLoadInfo { + char **typesArray {nullptr}; + unsigned int typesCount {0}; + unsigned int recordsCount {0}; +}; struct OH_UdmfGetDataParams { std::string destUri; Udmf_FileConflictOptions fileConflictOptions; Udmf_ProgressIndicator progressIndicator; OH_Udmf_DataProgressListener dataProgressListener; + OH_UdmfDataLoadInfo acceptableInfo; +}; + +struct OH_UdmfDataLoadParams { + OH_UdmfDataLoadInfo dataLoadInfo; + OH_Udmf_DataLoadHandler dataLoadHandler; +}; + +struct OH_UdmfOptions { + std::string key; + Udmf_Intention intention {}; + Udmf_Visibility visibility {}; }; bool IsInvalidUdsObjectPtr(const UdsObject* pThis, int cid); diff --git a/udmf/framework/ndkimpl/data/uds.cpp b/udmf/framework/ndkimpl/data/uds.cpp index 08094efd..be484930 100644 --- a/udmf/framework/ndkimpl/data/uds.cpp +++ b/udmf/framework/ndkimpl/data/uds.cpp @@ -26,6 +26,8 @@ using namespace OHOS::UDMF; +constexpr const int32_t MAX_PARAM_NAME = 1024; + static const char* GetUdsStrValue(UdsObject* pThis, NdkStructId ndkStructId, const char* paramName) { if (IsInvalidUdsObjectPtr(pThis, ndkStructId)) { @@ -107,9 +109,13 @@ OH_UdsContentForm::OH_UdsContentForm() : UdsObject(NdkStructId::UDS_CONTENT_FORM template <typename T> bool UdsObject::HasObjectKey(const char* paramName) { + if (strlen(paramName) > MAX_PARAM_NAME) { + LOG_ERROR(UDMF_CAPI, "paramName too long! paramName size = %{public}zu.", strlen(paramName)); + return false; + } auto it = obj->value_.find(paramName); if (it == obj->value_.end() || !std::holds_alternative<T>(it->second)) { - LOG_ERROR(UDMF_CAPI, "Don't have property %{public}s.", paramName); + LOG_ERROR(UDMF_CAPI, "Don't have property paramName"); return false; } return true; @@ -481,6 +487,10 @@ void OH_UdsPixelMap_GetPixelMap(OH_UdsPixelMap* pThis, OH_PixelmapNative* pixelm if (IsInvalidUdsObjectPtr(pThis, NdkStructId::UDS_PIXEL_MAP_STRUCT_ID)) { return; } + if (pixelmapNative == nullptr) { + LOG_ERROR(UDMF_CAPI, "pixelmapNative is nullptr."); + return; + } auto pixelMap = pThis->GetUdsValue<std::shared_ptr<OHOS::Media::PixelMap>>(PIXEL_MAP); if (pixelMap == nullptr) { LOG_ERROR(UDMF_CAPI, "Get pixelMap value is null."); diff --git a/udmf/framework/ndkimpl/data/utd.cpp b/udmf/framework/ndkimpl/data/utd.cpp index b0969a7d..73f4be1d 100644 --- a/udmf/framework/ndkimpl/data/utd.cpp +++ b/udmf/framework/ndkimpl/data/utd.cpp @@ -118,15 +118,14 @@ OH_Utd* OH_Utd_Create(const char* typeId) if (typeId == nullptr) { return nullptr; } - auto pThis = new (std::nothrow) OH_Utd(); - if (pThis == nullptr) { - LOG_ERROR(UDMF_CAPI, "Failed to apply for memory."); - return nullptr; - } auto typeDescriptor = GetTypeDescriptorByUtdClient(typeId); if (typeDescriptor == nullptr) { LOG_ERROR(UDMF_CAPI, "Failed to create by invoking the native function."); - delete pThis; + return nullptr; + } + auto pThis = new (std::nothrow) OH_Utd(); + if (pThis == nullptr) { + LOG_ERROR(UDMF_CAPI, "Failed to apply for memory."); return nullptr; } pThis->typeId = typeDescriptor->GetTypeId(); diff --git a/udmf/framework/ndkimpl/udmf_fuzzer/BUILD.gn b/udmf/framework/ndkimpl/udmf_fuzzer/BUILD.gn new file mode 100644 index 00000000..2110f03b --- /dev/null +++ b/udmf/framework/ndkimpl/udmf_fuzzer/BUILD.gn @@ -0,0 +1,68 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import("//build/config/features.gni") + +#####################hydra-fuzz################### +import("//build/test.gni") +import("//foundation/distributeddatamgr/udmf/udmf.gni") + +##############################fuzztest########################################## +ohos_fuzztest("UdmfFuzzTest") { + module_out_path = "udmf/udmf" + + include_dirs = [ + "${udmf_interfaces_path}/ndk/data", + "${udmf_root_path}/framework/ndkimpl/data", + ] + + fuzz_config_file = + "${udmf_framework_path}/ndkimpl/udmf_fuzzer" + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + + sources = [ "udmf_fuzzer.cpp" ] + + deps = [ + "${udmf_interfaces_path}/ndk:libudmf", + "${udmf_interfaces_path}/innerkits:udmf_client" , + ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken_shared", + "access_token:libtoken_setproc", + "bundle_framework:appexecfwk_core", + "c_utils:utils", + "hilog:libhilog", + "image_framework:image", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "samgr:samgr_proxy", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":UdmfFuzzTest", + ] +} +############################################################################### diff --git a/kv_store/test/fuzztest/kvsync_fuzzer/kvsync_fuzzer.h b/udmf/framework/ndkimpl/udmf_fuzzer/corpus/init similarity index 83% rename from kv_store/test/fuzztest/kvsync_fuzzer/kvsync_fuzzer.h rename to udmf/framework/ndkimpl/udmf_fuzzer/corpus/init index 77a42ea3..2b595da0 100644 --- a/kv_store/test/fuzztest/kvsync_fuzzer/kvsync_fuzzer.h +++ b/udmf/framework/ndkimpl/udmf_fuzzer/corpus/init @@ -13,9 +13,4 @@ * limitations under the License. */ -#ifndef KV_SYNC_FUZZER_H -#define KV_SYNC_FUZZER_H - -#define FUZZ_PROJECT_NAME "KvSync_fuzzer" - -#endif // KV_SYNC_FUZZER_H \ No newline at end of file +FUZZ \ No newline at end of file diff --git a/udmf/framework/ndkimpl/udmf_fuzzer/project.xml b/udmf/framework/ndkimpl/udmf_fuzzer/project.xml new file mode 100644 index 00000000..4fdbc407 --- /dev/null +++ b/udmf/framework/ndkimpl/udmf_fuzzer/project.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (c) 2023 Huawei Device Co., Ltd. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<fuzz_config> + <fuzztest> + <!-- maximum length of a test input --> + <max_len>1000</max_len> + <!-- maximum total time in seconds to run the fuzzer --> + <max_total_time>300</max_total_time> + <!-- memory usage limit in Mb --> + <rss_limit_mb>4096</rss_limit_mb> + </fuzztest> +</fuzz_config> diff --git a/udmf/framework/ndkimpl/udmf_fuzzer/udmf_fuzzer.cpp b/udmf/framework/ndkimpl/udmf_fuzzer/udmf_fuzzer.cpp new file mode 100644 index 00000000..f9b860c4 --- /dev/null +++ b/udmf/framework/ndkimpl/udmf_fuzzer/udmf_fuzzer.cpp @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <unistd.h> +#include <thread> + +#include "accesstoken_kit.h" +#include "nativetoken_kit.h" +#include "token_setproc.h" + +#include "link.h" + +#include "udmf_fuzzer.h" +#include "udmf.h" +#include "udmf_capi_common.h" +#include "udmf_meta.h" + +using namespace OHOS; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; + +namespace OHOS { +static constexpr int END_INTERVAL = 3; + +void AllocHapToken() +{ + HapInfoParams info = { + .userID = 100, + .bundleName = "ohos.test.demo", + .instIndex = 0, + .appIDDesc = "ohos.test.demo" + }; + + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { + { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.test.demo", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "test", + .descriptionId = 1 + } + }, + .permStateList = { + { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = {"local"}, + .grantStatus = {PermissionState::PERMISSION_GRANTED}, + .grantFlags = {1} + } + } + }; + auto tokenID = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(tokenID.tokenIDEx); +} + +void SetUpTestCase() +{ + AllocHapToken(); +} + +void TearDown() +{ + std::this_thread::sleep_for(std::chrono::seconds(END_INTERVAL)); +} + +void SetNativeToken() +{ + NativeTokenInfoParams infoInstance = { + .dcapsNum = 0, + .permsNum = 0, + .aclsNum = 0, + .dcaps = nullptr, + .perms = nullptr, + .acls = nullptr, + .processName = "msdp_sa", + .aplStr = "system_core", + }; + auto tokenId = GetAccessTokenId(&infoInstance); + SetSelfTokenID(tokenId); + AccessTokenKit::ReloadNativeTokenInfo(); +} + +void SetHapToken() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(100, "ohos.test.demo", 0); + SetSelfTokenID(tokenId); +} + +void SetUnifiedDataFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, skey.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + char key[UDMF_KEY_BUFFER_LEN]; + OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + OH_UdmfOptions_Destroy(options); + OH_UdsFileUri_Destroy(fileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +void GetUnifiedDataFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, skey.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + char key[UDMF_KEY_BUFFER_LEN]; + OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + OH_Udmf_GetUnifiedDataByOptions(options, &dataArray, &dataSize); + OH_UdmfOptions_Destroy(options); + OH_UdsFileUri_Destroy(fileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_Udmf_DestroyDataArray(&dataArray, dataSize); +} + +void UpdataUnifiedDataFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, skey.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + char key[UDMF_KEY_BUFFER_LEN]; + OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + + std::string svalue(data, data + size); + OH_UdmfData *udmfUnifiedData2 = OH_UdmfData_Create(); + OH_UdmfRecord *record2 = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri2 = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri2, svalue.c_str()); + OH_UdsFileUri_SetFileType(fileUri2, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record2, fileUri2); + OH_UdmfData_AddRecord(udmfUnifiedData2, record2); + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_DATA_HUB; + options2->key = key; + OH_Udmf_UpdateUnifiedData(options2, udmfUnifiedData2); + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options2); + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(fileUri2); + OH_UdmfRecord_Destroy(record); + OH_UdmfRecord_Destroy(record2); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(udmfUnifiedData2); +} + +void DeleteUnifiedDataFuzz(const uint8_t *data, size_t size) +{ + std::string skey(data, data + size); + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, skey.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + char key[UDMF_KEY_BUFFER_LEN]; + OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + OH_Udmf_DeleteUnifiedData(options, &dataArray, &dataSize); + OH_UdmfOptions_Destroy(options); + OH_UdsFileUri_Destroy(fileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_Udmf_DestroyDataArray(&dataArray, dataSize); +} + +void SetAndGetVisibilityFuzz(const uint8_t *data, size_t size) +{ + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + Udmf_Visibility testVisibility = Udmf_Visibility::UDMF_ALL; + OH_UdmfOptions_SetVisibility(options, testVisibility); + OH_UdmfOptions_GetVisibility(options); + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions* options1 = OH_UdmfOptions_Create(); + testVisibility = Udmf_Visibility::UDMF_OWN_PROCESS; + OH_UdmfOptions_SetVisibility(options1, testVisibility); + OH_UdmfOptions_GetVisibility(options1); + OH_UdmfOptions_Destroy(options1); +} +} + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + /* Run your code on data */ + OHOS::SetUpTestCase(); + OHOS::SetUnifiedDataFuzz(data, size); + OHOS::GetUnifiedDataFuzz(data, size); + OHOS::UpdataUnifiedDataFuzz(data, size); + OHOS::DeleteUnifiedDataFuzz(data, size); + OHOS::SetAndGetVisibilityFuzz(data, size); + OHOS::TearDown(); + return 0; +} \ No newline at end of file diff --git a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/gdbstore_fuzzer.h b/udmf/framework/ndkimpl/udmf_fuzzer/udmf_fuzzer.h similarity index 76% rename from relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/gdbstore_fuzzer.h rename to udmf/framework/ndkimpl/udmf_fuzzer/udmf_fuzzer.h index 05581d1a..1b27bab0 100644 --- a/relational_store/test/native/gdb/fuzztest/gdbstore_fuzzer/gdbstore_fuzzer.h +++ b/udmf/framework/ndkimpl/udmf_fuzzer/udmf_fuzzer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,9 +13,9 @@ * limitations under the License. */ -#ifndef GDBSTORE_FUZZER_H -#define GDBSTORE_FUZZER_H +#ifndef UDMF_UDMF_FUZZER_H +#define UDMF_UDMF_FUZZER_H -#define FUZZ_PROJECT_NAME "gdbstore_fuzzer" +#define FUZZ_PROJECT_NAME "udmf_fuzzer" -#endif // GDBSTORE_FUZZER_H \ No newline at end of file +#endif // UDMF_UDMF_FUZZER_H diff --git a/udmf/framework/ndkimpl/unittest/BUILD.gn b/udmf/framework/ndkimpl/unittest/BUILD.gn index ad8ece29..589ed026 100644 --- a/udmf/framework/ndkimpl/unittest/BUILD.gn +++ b/udmf/framework/ndkimpl/unittest/BUILD.gn @@ -13,13 +13,14 @@ import("//build/test.gni") import("//foundation/distributeddatamgr/udmf/udmf.gni") -module_output_path = "udmf/ndkimpl" +module_output_path = "udmf/udmf/ndkimpl" ############################################################################### config("module_private_config") { include_dirs = [ "${udmf_interfaces_path}/ndk/data", "${udmf_interfaces_path}/innerkits/data", + "${udmf_interfaces_path}/innerkits/dynamic", "${udmf_interfaces_path}/innerkits/common", "${udmf_framework_path}/common", "${udmf_framework_path}/ndkimpl/data", @@ -38,9 +39,11 @@ common_external_deps = [ "access_token:libnativetoken", "access_token:libtoken_setproc", "c_utils:utils", + "hilog:libhilog", "image_framework:image", "image_framework:image_native", "image_framework:pixelmap", + "ipc:ipc_single", "samgr:samgr_proxy", ] @@ -86,6 +89,7 @@ ohos_unittest("UdmfTest") { "${udmf_framework_path}/innerkitsimpl/data/system_defined_record.cpp", "${udmf_framework_path}/innerkitsimpl/data/text.cpp", "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", "udmf_test.cpp", ] @@ -94,6 +98,8 @@ ohos_unittest("UdmfTest") { deps = common_deps external_deps = common_external_deps + + external_deps += [ "kv_store:distributeddata_inner" ] } ohos_unittest("DataProviderImplTest") { diff --git a/udmf/framework/ndkimpl/unittest/udmf_test.cpp b/udmf/framework/ndkimpl/unittest/udmf_test.cpp index a1f9a601..f93f597b 100644 --- a/udmf/framework/ndkimpl/unittest/udmf_test.cpp +++ b/udmf/framework/ndkimpl/unittest/udmf_test.cpp @@ -43,6 +43,7 @@ using namespace OHOS::Security::AccessToken; using namespace OHOS::UDMF; namespace OHOS::Test { +static constexpr uint64_t MAX_TYPES_COUNT = 10 * 1024; class UDMFTest : public testing::Test { public: static void SetUpTestCase(void); @@ -52,11 +53,13 @@ public: static void AllocHapToken1(); static void AllocHapToken2(); void SetHapToken1(); + void SetHapToken2(); bool CheckUnsignedChar(unsigned char* dst, unsigned char* src, int size); static void FinalizeFunc(void* context); static void* GetDataCallbackFunc(void* context, const char* type); static constexpr int USER_ID = 100; static constexpr int INST_INDEX = 0; + int64_t CountTime(); }; void UDMFTest::SetUpTestCase() @@ -164,6 +167,12 @@ void UDMFTest::SetHapToken1() SetSelfTokenID(tokenId); } +void UDMFTest::SetHapToken2() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo2", INST_INDEX); + SetSelfTokenID(tokenId); +} + bool UDMFTest::CheckUnsignedChar(unsigned char* dst, unsigned char* src, int size) { EXPECT_NE(dst, nullptr); @@ -186,11 +195,16 @@ void* UDMFTest::GetDataCallbackFunc(void* context, const char* type) return plainText; } +int64_t UDMFTest::CountTime() +{ + return std::chrono::duration_cast<std::chrono::milliseconds>( + std::chrono::system_clock::now().time_since_epoch()).count(); +} + /** * @tc.name: OH_Udmf_CreateUnifiedData001 * @tc.desc: test OH_UdmfData_Create * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_CreateUnifiedData001, TestSize.Level0) { @@ -204,7 +218,6 @@ HWTEST_F(UDMFTest, OH_Udmf_CreateUnifiedData001, TestSize.Level0) * @tc.name: OH_Udmf_AddRecordToUnifiedData001 * @tc.desc: OH_UdmfData_AddRecord with return UDMF_E_INVALID_PARAM * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_AddRecordToUnifiedData001, TestSize.Level0) { @@ -232,7 +245,6 @@ HWTEST_F(UDMFTest, OH_Udmf_AddRecordToUnifiedData001, TestSize.Level0) * @tc.name: OH_Udmf_AddRecordToUnifiedData002 * @tc.desc: OH_UdmfData_AddRecord with return UDMF_E_OK * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_AddRecordToUnifiedData002, TestSize.Level0) { @@ -249,7 +261,6 @@ HWTEST_F(UDMFTest, OH_Udmf_AddRecordToUnifiedData002, TestSize.Level0) * @tc.name: OH_Udmf_HasUnifiedDataType001 * @tc.desc: OH_UdmfData_HasType with return UDMF_E_INVALID_PARAM * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_HasUnifiedDataType001, TestSize.Level0) { @@ -276,7 +287,6 @@ HWTEST_F(UDMFTest, OH_Udmf_HasUnifiedDataType001, TestSize.Level0) * @tc.name: OH_Udmf_HasUnifiedDataType002 * @tc.desc: OH_UdmfData_HasType with return whether has type, number 1 represent true, number 0 represent false * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_HasUnifiedDataType002, TestSize.Level0) { @@ -303,7 +313,6 @@ HWTEST_F(UDMFTest, OH_Udmf_HasUnifiedDataType002, TestSize.Level0) * @tc.name: OH_Udmf_GetUnifiedDataTypes001 * @tc.desc: OH_UdmfData_GetTypes with invalid params * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedDataTypes001, TestSize.Level0) { @@ -327,7 +336,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedDataTypes001, TestSize.Level0) * @tc.name: OH_Udmf_GetUnifiedDataTypes002 * @tc.desc: OH_UdmfData_GetTypes with valid params * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedDataTypes002, TestSize.Level0) { @@ -359,7 +367,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedDataTypes002, TestSize.Level0) * @tc.name: OH_Udmf_GetUnifiedRecordTypes001 * @tc.desc: OH_UdmfRecord_GetTypes with invalid params * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedRecordTypes001, TestSize.Level0) { @@ -382,7 +389,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedRecordTypes001, TestSize.Level0) * @tc.name: OH_Udmf_GetUnifiedRecordTypes002 * @tc.desc: OH_UdmfRecord_GetTypes with valid params * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedRecordTypes002, TestSize.Level0) { @@ -407,7 +413,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedRecordTypes002, TestSize.Level0) * @tc.name: OH_Udmf_GetRecords001 * @tc.desc: OH_UdmfRecord_GetTypes with invalid params * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetRecords001, TestSize.Level0) { @@ -431,7 +436,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetRecords001, TestSize.Level0) * @tc.name: OH_Udmf_GetRecords002 * @tc.desc: OH_UdmfRecord_GetTypes with valid params * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetRecords002, TestSize.Level0) { @@ -466,7 +470,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetRecords002, TestSize.Level0) * @tc.name: OH_Udmf_SetUnifiedData001 * @tc.desc: OH_Udmf_SetUnifiedData with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, UdmfTest006, TestSize.Level0) { @@ -497,7 +500,6 @@ HWTEST_F(UDMFTest, UdmfTest006, TestSize.Level0) * @tc.name: OH_Udmf_GetUnifiedData001 * @tc.desc: OH_Udmf_GetUnifiedData with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedData001, TestSize.Level0) { @@ -523,7 +525,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedData001, TestSize.Level0) * @tc.name: OH_Udmf_SetAndGetUnifiedData001 * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with valid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData001, TestSize.Level0) { @@ -563,7 +564,6 @@ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData001, TestSize.Level0) * @tc.name: OH_Udmf_SetAndGetUnifiedData002 * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with valid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData002, TestSize.Level0) { @@ -599,7 +599,6 @@ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData002, TestSize.Level0) * @tc.name: OH_Udmf_CreateUnifiedRecord001 * @tc.desc: OH_Udmf_CreateUnifiedRecord001 * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_CreateUnifiedRecord001, TestSize.Level0) { @@ -613,7 +612,6 @@ HWTEST_F(UDMFTest, OH_Udmf_CreateUnifiedRecord001, TestSize.Level0) * @tc.name: OH_Udmf_AddGeneralEntry001 * @tc.desc: test OH_UdmfRecord_AddGeneralEntry with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_AddGeneralEntry001, TestSize.Level0) { @@ -639,7 +637,6 @@ HWTEST_F(UDMFTest, OH_Udmf_AddGeneralEntry001, TestSize.Level0) * @tc.name: OH_Udmf_GetGeneralEntry001 * @tc.desc: test OH_UdmfRecord_GetGeneralEntry with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetGeneralEntry001, TestSize.Level0) { @@ -664,7 +661,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetGeneralEntry001, TestSize.Level0) * @tc.name: OH_Udmf_AddAndGetGeneralEntry002 * @tc.desc: test OH_UdmfRecord_AddGeneralEntry and OH_UdmfRecord_GetGeneralEntry with valid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_AddAndGetGeneralEntry002, TestSize.Level0) { @@ -741,7 +737,6 @@ HWTEST_F(UDMFTest, OH_Udmf_AddAndGetGeneralEntry004, TestSize.Level0) * @tc.name: OH_Udmf_BuildRecordByPlainText001 * @tc.desc: test OH_UdmfRecord_AddPlainText with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_BuildRecordByPlainText001, TestSize.Level0) { @@ -767,7 +762,6 @@ HWTEST_F(UDMFTest, OH_Udmf_BuildRecordByPlainText001, TestSize.Level0) * @tc.name: OH_Udmf_GetPlainTextFromRecord001 * @tc.desc: test OH_UdmfRecord_GetPlainText with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetPlainTextFromRecord001, TestSize.Level0) { @@ -793,7 +787,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetPlainTextFromRecord001, TestSize.Level0) * @tc.name: OH_Udmf_BuildAndGetPlainTextFromRecord001 * @tc.desc: test OH_UdmfRecord_GetPlainText and OH_Udmf_BuildPlainTextFromRecord with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_BuildAndGetPlainTextFromRecord001, TestSize.Level0) { @@ -820,7 +813,6 @@ HWTEST_F(UDMFTest, OH_Udmf_BuildAndGetPlainTextFromRecord001, TestSize.Level0) * @tc.name: OH_Udmf_BuildRecordByHyperlink001 * @tc.desc: test OH_UdmfRecord_AddHyperlink with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_BuildRecordByHyperlink001, TestSize.Level0) { @@ -846,7 +838,6 @@ HWTEST_F(UDMFTest, OH_Udmf_BuildRecordByHyperlink001, TestSize.Level0) * @tc.name: OH_Udmf_GetHyperlinkFromRecord001 * @tc.desc: test OH_UdmfRecord_GetHyperlink with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetHyperlinkFromRecord001, TestSize.Level0) { @@ -872,7 +863,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetHyperlinkFromRecord001, TestSize.Level0) * @tc.name: OH_Udmf_BuildAndGetHyperlinkFromRecord001 * @tc.desc: test OH_Udmf_BuildAndGetHyperlinkFromRecord with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_BuildAndGetHyperlinkFromRecord001, TestSize.Level0) { @@ -899,7 +889,6 @@ HWTEST_F(UDMFTest, OH_Udmf_BuildAndGetHyperlinkFromRecord001, TestSize.Level0) * @tc.name: OH_Udmf_BuildRecordByHtml001 * @tc.desc: test OH_UdmfRecord_AddHtml with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_BuildRecordByHtml001, TestSize.Level0) { @@ -925,7 +914,6 @@ HWTEST_F(UDMFTest, OH_Udmf_BuildRecordByHtml001, TestSize.Level0) * @tc.name: OH_Udmf_GetHtmlFromRecord001 * @tc.desc: test OH_UdmfRecord_GetHtml with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetHtmlFromRecord001, TestSize.Level0) { @@ -951,7 +939,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetHtmlFromRecord001, TestSize.Level0) * @tc.name: OH_Udmf_BuildAndGetHtmlFromRecord001 * @tc.desc: test OH_Udmf_BuildAndGetHtmlFromRecord with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_BuildAndGetHtmlFromRecord001, TestSize.Level0) { @@ -978,7 +965,6 @@ HWTEST_F(UDMFTest, OH_Udmf_BuildAndGetHtmlFromRecord001, TestSize.Level0) * @tc.name: OH_Udmf_BuildRecordByOpenHarmonyAppItem001 * @tc.desc: test OH_UdmfRecord_AddAppItem with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_BuildRecordByOpenHarmonyAppItem001, TestSize.Level0) { @@ -1004,7 +990,6 @@ HWTEST_F(UDMFTest, OH_Udmf_BuildRecordByOpenHarmonyAppItem001, TestSize.Level0) * @tc.name: OH_Udmf_GetOpenHarmonyAppItemFromRecord001 * @tc.desc: test OH_UdmfRecord_GetAppItem with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_GetOpenHarmonyAppItemFromRecord001, TestSize.Level0) { @@ -1030,7 +1015,6 @@ HWTEST_F(UDMFTest, OH_Udmf_GetOpenHarmonyAppItemFromRecord001, TestSize.Level0) * @tc.name: OH_Udmf_BuildAndGetAppItemFromRecord001 * @tc.desc: test OH_Udmf_BuildAndGetAppItemFromRecord with invalid param * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_BuildAndGetAppItemFromRecord001, TestSize.Level0) { @@ -1416,7 +1400,7 @@ HWTEST_F(UDMFTest, OH_UdmfRecord_SetProvider001, TestSize.Level1) /** * @tc.name: OH_UdmfRecord_SetProvider002 - * @tc.desc: invalid parameters testcase of OH_UdmfRecord_SetProvider + * @tc.desc: valid parameters testcase of OH_UdmfRecord_SetProvider * @tc.type: FUNC */ HWTEST_F(UDMFTest, OH_UdmfRecord_SetProvider002, TestSize.Level1) @@ -1438,6 +1422,39 @@ HWTEST_F(UDMFTest, OH_UdmfRecord_SetProvider002, TestSize.Level1) OH_UdmfRecordProvider_Destroy(provider); } +/** + * @tc.name: OH_UdmfRecord_SetProvider003 + * @tc.desc: invalid parameters testcase of OH_UdmfRecord_SetProvider + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_UdmfRecord_SetProvider003, TestSize.Level1) +{ + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsPlainText *plainText = OH_UdsPlainText_Create(); + char content[] = "hello world"; + OH_UdsPlainText_SetContent(plainText, content); + OH_UdmfRecord_AddPlainText(record, plainText); + OH_UdmfRecordProvider* provider = OH_UdmfRecordProvider_Create(); + EXPECT_NE(provider, nullptr); + int num = 1; + void* context = &num; + OH_UdmfRecordProvider_SetData(provider, context, GetDataCallbackFunc, FinalizeFunc); + const char* types[3] = { "general.plain-text", "general.hyperlink", "general.html" }; + + int res = OH_UdmfRecord_SetProvider(record, types, MAX_TYPES_COUNT + 1, provider); + EXPECT_EQ(res, UDMF_E_INVALID_PARAM); + + res = OH_UdmfRecord_SetProvider(record, types, 0, provider); + EXPECT_EQ(res, UDMF_E_INVALID_PARAM); + + res = OH_UdmfRecord_SetProvider(record, nullptr, MAX_TYPES_COUNT + 1, provider); + EXPECT_EQ(res, UDMF_E_INVALID_PARAM); + + res = OH_UdmfRecord_SetProvider(record, types, 3, nullptr); + EXPECT_EQ(res, UDMF_E_INVALID_PARAM); + OH_UdmfRecordProvider_Destroy(provider); +} + /** * @tc.name: OH_Udmf_BuildRecordByOpenHarmonyArrayBuffer001 * @tc.desc: test OH_UdmfRecord_AddArrayBuffer with invalid param @@ -1986,10 +2003,9 @@ HWTEST_F(UDMFTest, FileUriTest001, TestSize.Level1) for (unsigned int idx = 0; idx < recordCount; ++idx) { unsigned int recordTypeCount; char** recordTypes = OH_UdmfRecord_GetTypes(records[idx], &recordTypeCount); - EXPECT_EQ(recordTypeCount, 2); + EXPECT_EQ(recordTypeCount, 1); EXPECT_NE(recordTypes, nullptr); - EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_IMAGE), 0); - EXPECT_EQ(strcmp(recordTypes[1], UDMF_META_GENERAL_FILE_URI), 0); + EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_GENERAL_FILE_URI), 0); for (unsigned int recordIdx = 0; recordIdx < recordTypeCount; ++recordIdx) { if (strcmp(recordTypes[recordIdx], UDMF_META_GENERAL_FILE_URI) == 0) { OH_UdsFileUri* fileUri = OH_UdsFileUri_Create(); @@ -2041,34 +2057,24 @@ HWTEST_F(UDMFTest, FileUriTest002, TestSize.Level1) EXPECT_EQ(recordCount, 2); EXPECT_NE(records, nullptr); - for (unsigned int idx = 0; idx < recordCount; idx++) { - unsigned int recordTypeCount; - char** recordTypes = OH_UdmfRecord_GetTypes(records[idx], &recordTypeCount); - EXPECT_NE(recordTypes, nullptr); - if (recordTypeCount == 1) { - EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_PLAIN_TEXT), 0); - for (unsigned int recordIdx = 0; recordIdx < recordTypeCount; ++recordIdx) { - OH_UdsPlainText* text = OH_UdsPlainText_Create(); - int getPlaintextRet = OH_UdmfRecord_GetPlainText(records[idx], text); - EXPECT_EQ(getPlaintextRet, UDMF_E_OK); - const char* getContent = OH_UdsPlainText_GetContent(text); - EXPECT_EQ(strcmp(getContent, content.c_str()), 0); - } - } - if (recordTypeCount == 2) { - EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_IMAGE), 0); - EXPECT_EQ(strcmp(recordTypes[1], UDMF_META_GENERAL_FILE_URI), 0); - for (unsigned int recordIdx = 0; recordIdx < recordTypeCount; ++recordIdx) { - if (strcmp(recordTypes[recordIdx], UDMF_META_GENERAL_FILE_URI) == 0) { - OH_UdsFileUri* fileUri = OH_UdsFileUri_Create(); - int getFileUriRet = OH_UdmfRecord_GetFileUri(records[idx], fileUri); - EXPECT_EQ(getFileUriRet, UDMF_E_OK); - const char* getFileUri = OH_UdsFileUri_GetFileUri(fileUri); - EXPECT_EQ(strcmp(getFileUri, uri.c_str()), 0); - } - } - } - } + unsigned int recordTypeCount; + char** recordTypes = OH_UdmfRecord_GetTypes(records[0], &recordTypeCount); + EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_GENERAL_FILE_URI), 0); + EXPECT_EQ(recordTypeCount, 1); + OH_UdsFileUri* fileUri = OH_UdsFileUri_Create(); + int getFileUriRet = OH_UdmfRecord_GetFileUri(records[0], fileUri); + EXPECT_EQ(getFileUriRet, UDMF_E_OK); + const char* getFileUri = OH_UdsFileUri_GetFileUri(fileUri); + EXPECT_EQ(strcmp(getFileUri, uri.c_str()), 0); + + recordTypes = OH_UdmfRecord_GetTypes(records[1], &recordTypeCount); + EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_PLAIN_TEXT), 0); + EXPECT_EQ(recordTypeCount, 1); + OH_UdsPlainText* text = OH_UdsPlainText_Create(); + int getPlaintextRet = OH_UdmfRecord_GetPlainText(records[1], text); + EXPECT_EQ(getPlaintextRet, UDMF_E_OK); + const char* getContent = OH_UdsPlainText_GetContent(text); + EXPECT_EQ(strcmp(getContent, content.c_str()), 0); } /** @@ -2108,10 +2114,9 @@ HWTEST_F(UDMFTest, FileUriTest003, TestSize.Level1) for (unsigned int idx = 0; idx < recordCount; ++idx) { unsigned int recordTypeCount; char** recordTypes = OH_UdmfRecord_GetTypes(records[idx], &recordTypeCount); - EXPECT_EQ(recordTypeCount, 2); + EXPECT_EQ(recordTypeCount, 1); EXPECT_NE(recordTypes, nullptr); - EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_AUDIO), 0); - EXPECT_EQ(strcmp(recordTypes[1], UDMF_META_GENERAL_FILE_URI), 0); + EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_GENERAL_FILE_URI), 0); for (unsigned int recordIdx = 0; recordIdx < recordTypeCount; ++recordIdx) { if (strcmp(recordTypes[recordIdx], UDMF_META_GENERAL_FILE_URI) == 0) { OH_UdsFileUri* fileUri = OH_UdsFileUri_Create(); @@ -2161,10 +2166,9 @@ HWTEST_F(UDMFTest, FileUriTest004, TestSize.Level1) for (unsigned int idx = 0; idx < recordCount; ++idx) { unsigned int recordTypeCount; char** recordTypes = OH_UdmfRecord_GetTypes(records[idx], &recordTypeCount); - EXPECT_EQ(recordTypeCount, 2); + EXPECT_EQ(recordTypeCount, 1); EXPECT_NE(recordTypes, nullptr); - EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_GENERAL_FILE), 0); - EXPECT_EQ(strcmp(recordTypes[1], UDMF_META_GENERAL_FILE_URI), 0); + EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_GENERAL_FILE_URI), 0); for (unsigned int recordIdx = 0; recordIdx < recordTypeCount; ++recordIdx) { if (strcmp(recordTypes[recordIdx], UDMF_META_GENERAL_FILE_URI) == 0) { OH_UdsFileUri* fileUri = OH_UdsFileUri_Create(); @@ -2270,10 +2274,9 @@ HWTEST_F(UDMFTest, FileUriTest006, TestSize.Level1) for (unsigned int idx = 0; idx < recordCount; ++idx) { unsigned int recordTypeCount; char** recordTypes = OH_UdmfRecord_GetTypes(records[idx], &recordTypeCount); - EXPECT_EQ(recordTypeCount, 2); + EXPECT_EQ(recordTypeCount, 1); EXPECT_NE(recordTypes, nullptr); - EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_VIDEO), 0); - EXPECT_EQ(strcmp(recordTypes[1], UDMF_META_GENERAL_FILE_URI), 0); + EXPECT_EQ(strcmp(recordTypes[0], UDMF_META_GENERAL_FILE_URI), 0); for (unsigned int recordIdx = 0; recordIdx < recordTypeCount; ++recordIdx) { if (strcmp(recordTypes[recordIdx], UDMF_META_GENERAL_FILE_URI) == 0) { OH_UdsFileUri* fileUri = OH_UdsFileUri_Create(); @@ -2347,7 +2350,6 @@ HWTEST_F(UDMFTest, FileUriTest007, TestSize.Level1) * @tc.name: OH_Udmf_SetAndGetUnifiedData003 * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with file uri * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData003, TestSize.Level1) { @@ -2388,7 +2390,6 @@ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData003, TestSize.Level1) * @tc.name: OH_Udmf_SetAndGetUnifiedData004 * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with file uri * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData004, TestSize.Level1) { @@ -2428,7 +2429,6 @@ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData004, TestSize.Level1) * @tc.name: OH_Udmf_SetAndGetUnifiedData005 * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with file uri * @tc.type: FUNC - * @tc.require: AROOOH5R5G */ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData005, TestSize.Level1) { @@ -2509,4 +2509,1351 @@ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData006, TestSize.Level1) OH_UdsContentForm_Destroy(getContentForm); OH_UdmfData_Destroy(readUnifiedData); } + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData007 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with invlid params + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData007, TestSize.Level1) +{ + std::string uri = "file://file_010.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_MENU; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + Udmf_Intention intention1 = UDMF_INTENTION_SYSTEM_SHARE; + int getRes = OH_Udmf_GetUnifiedData(key, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + char key1[UDMF_KEY_BUFFER_LEN]; + getRes = OH_Udmf_GetUnifiedData(key1, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + getRes = OH_Udmf_GetUnifiedData(key1, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData008 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with invlid params + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData008, TestSize.Level1) +{ + std::string uri = "file://file_011.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_SYSTEM_SHARE; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + Udmf_Intention intention1 = UDMF_INTENTION_MENU; + int getRes = OH_Udmf_GetUnifiedData(key, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + char key1[UDMF_KEY_BUFFER_LEN]; + getRes = OH_Udmf_GetUnifiedData(key1, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + getRes = OH_Udmf_GetUnifiedData(key1, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData009 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with UDMF_ERR + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData009, TestSize.Level1) +{ + std::string uri = "file://file_009.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_PICKER; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + Udmf_Intention intention1 = UDMF_INTENTION_MENU; + int getRes = OH_Udmf_GetUnifiedData(key, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + char key1[UDMF_KEY_BUFFER_LEN]; + getRes = OH_Udmf_GetUnifiedData(key1, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + getRes = OH_Udmf_GetUnifiedData(key1, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData010 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with file uri + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData010, TestSize.Level1) +{ + std::string uri = "file://file_010.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_PICKER; + char key[UDMF_KEY_BUFFER_LEN]; + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + SetHapToken2(); + int getRes = OH_Udmf_GetUnifiedData(key, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData011 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with file uri + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData011, TestSize.Level1) +{ + std::string uri = "file://file_011.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_MENU; + char key[UDMF_KEY_BUFFER_LEN]; + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + SetHapToken2(); + int getRes = OH_Udmf_GetUnifiedData(key, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData012 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with file uri + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData012, TestSize.Level1) +{ + std::string uri = "file://file_012.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_SYSTEM_SHARE; + char key[UDMF_KEY_BUFFER_LEN]; + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + SetHapToken2(); + int getRes = OH_Udmf_GetUnifiedData(key, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData013 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData013, TestSize.Level1) +{ + std::string uri = "file://file_007.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdsContentForm *contentForm = OH_UdsContentForm_Create(); + unsigned char thumbData[] = {0, 1, 2, 3, 4}; + OH_UdsContentForm_SetThumbData(contentForm, thumbData, 5); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_SYSTEM_SHARE; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + Udmf_Intention intention1 = UDMF_INTENTION_PICKER; + int getRes = OH_Udmf_GetUnifiedData(key, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + char key1[UDMF_KEY_BUFFER_LEN] = "udmf://aaabbbccc/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + getRes = OH_Udmf_GetUnifiedData(key1, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + getRes = OH_Udmf_GetUnifiedData(key1, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData014 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData014, TestSize.Level1) +{ + std::string uri = "file://file_008.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_PICKER; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + Udmf_Intention intention1 = UDMF_INTENTION_SYSTEM_SHARE; + int getRes = OH_Udmf_GetUnifiedData(key, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + char key1[UDMF_KEY_BUFFER_LEN] = "udmf://aaabbbccc/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + getRes = OH_Udmf_GetUnifiedData(key1, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + getRes = OH_Udmf_GetUnifiedData(key1, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData015 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData015, TestSize.Level1) +{ + std::string uri = "file://file_009.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_MENU; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + Udmf_Intention intention1 = UDMF_INTENTION_SYSTEM_SHARE; + int getRes = OH_Udmf_GetUnifiedData(key, intention1, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + char key1[UDMF_KEY_BUFFER_LEN] = "udmf://aaabbbccc/com.hmos.photos/CSl;cdcGFcmdkasaccCSCAAScscdc"; + getRes = OH_Udmf_GetUnifiedData(key1, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + intention = UDMF_INTENTION_MENU; + getRes = OH_Udmf_GetUnifiedData(key1, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_ERR); + + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData016 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData016, TestSize.Level1) +{ + std::string uri = "file://file_010.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + for (int32_t i = 0; i < 1000; i++) { + OH_UdmfRecord_AddFileUri(record, fileUri); + } + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_SYSTEM_SHARE; + char key[UDMF_KEY_BUFFER_LEN]; + int64_t start = CountTime(); + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "systemshare setdata 1000 cost timet:%{public}" PRIi64, (end - start)); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + start = CountTime(); + int getRes = OH_Udmf_GetUnifiedData(key, intention, readUnifiedData); + end = CountTime(); + LOG_INFO(UDMF_TEST, "systemshare setdata 1000 cost timet:%{public}" PRIi64, (end - start)); + EXPECT_EQ(getRes, UDMF_E_OK); + + OH_UdsFileUri_Destroy(fileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData017 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData017, TestSize.Level1) +{ + std::string uri = "file://file_008.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + for (int32_t i = 0; i < 1000; i++) { + OH_UdmfRecord_AddFileUri(record, fileUri); + } + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_PICKER; + char key[UDMF_KEY_BUFFER_LEN]; + + int64_t start = CountTime(); + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "picker setdata 1000 cost timet:%{public}" PRIi64, (end - start)); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + start = CountTime(); + int getRes = OH_Udmf_GetUnifiedData(key, intention, readUnifiedData); + end = CountTime(); + LOG_INFO(UDMF_TEST, "picker setdata 1000 cost timet:%{public}" PRIi64, (end - start)); + EXPECT_EQ(getRes, UDMF_E_OK); + + OH_UdsFileUri_Destroy(fileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData018 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData018, TestSize.Level1) +{ + std::string uri = "file://file_010.txt"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_FOLDER); + for (int32_t i = 0; i < 1000; i++) { + OH_UdmfRecord_AddFileUri(record, fileUri); + } + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_MENU; + char key[UDMF_KEY_BUFFER_LEN]; + int64_t start = CountTime(); + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + int64_t end = CountTime(); + LOG_INFO(UDMF_TEST, "menu setdata 1000 cost timet:%{public}" PRIi64, (end - start)); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + start = CountTime(); + int getRes = OH_Udmf_GetUnifiedData(key, intention, readUnifiedData); + end = CountTime(); + LOG_INFO(UDMF_TEST, "menu setdata 1000 cost timet:%{public}" PRIi64, (end - start)); + EXPECT_EQ(getRes, UDMF_E_OK); + + OH_UdsFileUri_Destroy(fileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(readUnifiedData); +} + +static OH_UdmfData* CreateImageDataWithFileUri(const std::string& uriStr) +{ + std::string uri = uriStr; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + return udmfUnifiedData; +} + +/** + * @tc.name: OH_UdmfOptions001 + * @tc.desc: OH_UdmfOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_UdmfOptions001, TestSize.Level1) +{ + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + ASSERT_TRUE(options != nullptr); + const char* testKey = "testKey"; + int result = OH_UdmfOptions_SetKey(options, testKey); + EXPECT_EQ(result, UDMF_E_OK); + const char* getKey = OH_UdmfOptions_GetKey(options); + EXPECT_STREQ(getKey, testKey); + Udmf_Intention testIntention = UDMF_INTENTION_DRAG; + int setResult = OH_UdmfOptions_SetIntention(options, testIntention); + EXPECT_EQ(setResult, UDMF_E_OK); + Udmf_Intention getIntention = OH_UdmfOptions_GetIntention(options); + EXPECT_EQ(getIntention, testIntention); + int resetResult = OH_UdmfOptions_Reset(options); + EXPECT_EQ(resetResult, UDMF_E_OK); + EXPECT_EQ(options->key.empty(), true); + EXPECT_EQ(options->intention, Udmf_Intention {}); + OH_UdmfOptions_Destroy(options); +} + +/** + * @tc.name: OH_UdmfOptions002 + * @tc.desc: OH_UdmfOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_UdmfOptions002, TestSize.Level1) +{ + OH_UdmfOptions* options1 = nullptr; + const char * key = nullptr; + int setRes = OH_UdmfOptions_SetKey(options1, key); + EXPECT_EQ(setRes, UDMF_E_INVALID_PARAM); + const char* getRes = OH_UdmfOptions_GetKey(options1); + EXPECT_EQ(getRes, nullptr); + Udmf_Intention testIntention = UDMF_INTENTION_DRAG; + OH_UdmfOptions_GetIntention(options1); + int setIntention = OH_UdmfOptions_SetIntention(options1, testIntention); + EXPECT_EQ(setIntention, UDMF_E_INVALID_PARAM); + int reSet = OH_UdmfOptions_Reset(options1); + EXPECT_EQ(reSet, UDMF_E_INVALID_PARAM); + OH_UdmfOptions_Destroy(options1); +} + +/** + * @tc.name: OH_Udmf_SetUnifiedDataByOptions001 + * @tc.desc: OH_Udmf_SetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetUnifiedDataByOptions001, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DRAG; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_INVALID_PARAM); + + OH_UdmfOptions_Destroy(options); + OH_UdsFileUri_Destroy(fileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedDataByOptions001 + * @tc.desc: OH_Udmf_SetUnifiedDataByOptions and OH_Udmf_GetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedDataByOptions001, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + std::string uri2 = "https://new/uri/path.jpg"; + OH_UdmfData *udmfUnifiedData2 = OH_UdmfData_Create(); + OH_UdmfRecord *record2 = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri2 = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri2, uri2.c_str()); + OH_UdsFileUri_SetFileType(fileUri2, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record2, fileUri2); + OH_UdmfData_AddRecord(udmfUnifiedData2, record2); + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_DATA_HUB; + char key2[UDMF_KEY_BUFFER_LEN]; + int setRes2 = OH_Udmf_SetUnifiedDataByOptions(options2, udmfUnifiedData2, key2, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes2, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options, &dataArray, &dataSize); + EXPECT_EQ(getRes, UDMF_E_OK); + EXPECT_NE(dataArray, nullptr); + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options2, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + EXPECT_NE(dataArray2, nullptr); + EXPECT_EQ(dataSize2, 2); + OH_Udmf_DestroyDataArray(&dataArray, dataSize); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options2); + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(fileUri2); + OH_UdmfRecord_Destroy(record); + OH_UdmfRecord_Destroy(record2); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(udmfUnifiedData2); +} + +/** + * @tc.name: OH_Udmf_UpdateUnifiedData001 + * @tc.desc: OH_Udmf_UpdateUnifiedData001 with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_UpdateUnifiedData001, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + char key[UDMF_KEY_BUFFER_LEN]; + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + std::string uri2 = "https://new/uri/path.jpg"; + OH_UdmfData *udmfUnifiedData2 = OH_UdmfData_Create(); + OH_UdmfRecord *record2 = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri2 = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri2, uri2.c_str()); + OH_UdsFileUri_SetFileType(fileUri2, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record2, fileUri2); + OH_UdmfData_AddRecord(udmfUnifiedData2, record2); + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_DATA_HUB; + options2->key = key; + int updataRes = OH_Udmf_UpdateUnifiedData(options2, udmfUnifiedData2); + EXPECT_EQ(updataRes, UDMF_E_OK); + + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options2, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + EXPECT_NE(dataArray2, nullptr); + EXPECT_EQ(dataSize2, 1); + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options2); + + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(fileUri2); + OH_UdmfRecord_Destroy(record); + OH_UdmfRecord_Destroy(record2); + OH_UdmfData_Destroy(udmfUnifiedData); + OH_UdmfData_Destroy(udmfUnifiedData2); +} + +/** + * @tc.name: OH_Udmf_GetUnifiedDataByOptions001 + * @tc.desc: OH_Udmf_GetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedDataByOptions001, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_PICKER; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + OH_UdmfOptions* options1 = OH_UdmfOptions_Create(); + options1->intention = UDMF_INTENTION_PICKER; + options1->key = key; + unsigned dataSize1 = 0; + OH_UdmfData* dataArray1 = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options1, &dataArray1, &dataSize1); + EXPECT_EQ(getRes, UDMF_E_OK); + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray1[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + OH_Udmf_DestroyDataArray(&dataArray1, dataSize1); + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options1); + + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_GetUnifiedDataByOptions002 + * @tc.desc: OH_Udmf_GetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedDataByOptions002, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_MENU; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + OH_UdmfOptions* options1 = OH_UdmfOptions_Create(); + options1->intention = UDMF_INTENTION_MENU; + options1->key = key; + unsigned dataSize1 = 0; + OH_UdmfData* dataArray1 = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options1, &dataArray1, &dataSize1); + EXPECT_EQ(getRes, UDMF_E_OK); + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray1[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + OH_Udmf_DestroyDataArray(&dataArray1, dataSize1); + + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options1); + + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_DeleteUnifiedData001 + * @tc.desc: OH_Udmf_DeleteUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_DeleteUnifiedData001, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + int dateleRes = OH_Udmf_DeleteUnifiedData(options, &dataArray, &dataSize); + EXPECT_EQ(dateleRes, UDMF_E_OK); + EXPECT_NE(dataArray, nullptr); + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + OH_Udmf_DestroyDataArray(&dataArray, dataSize); + + OH_UdmfOptions_Destroy(options); + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_DeleteUnifiedData002 + * @tc.desc: OH_Udmf_DeleteUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_DeleteUnifiedData002, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_SYSTEM_SHARE; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + OH_UdmfOptions* options1 = OH_UdmfOptions_Create(); + options1->intention = UDMF_INTENTION_SYSTEM_SHARE; + options1->key = key; + unsigned int dataSize1 = 0; + OH_UdmfData* dataArray1 = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options1, &dataArray1, &dataSize1); + EXPECT_EQ(getRes, UDMF_E_OK); + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray1[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_SYSTEM_SHARE; + options2->key = key; + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options2, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + + OH_Udmf_DestroyDataArray(&dataArray1, dataSize1); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options1); + OH_UdmfOptions_Destroy(options2); + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_DeleteUnifiedData003 + * @tc.desc: OH_Udmf_DeleteUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_DeleteUnifiedData003, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_PICKER; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_PICKER; + options2->key = key; + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options2, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + EXPECT_NE(dataArray2, nullptr); + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray2[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options2); + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_DeleteUnifiedData004 + * @tc.desc: OH_Udmf_DeleteUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_DeleteUnifiedData004, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_MENU; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_MENU; + options2->key = key; + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options2, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + EXPECT_NE(dataArray2, nullptr); + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray2[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options2); + OH_UdsFileUri_Destroy(fileUri); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_GetUnifiedDataByOptions003 + * @tc.desc: OH_Udmf_GetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_GetUnifiedDataByOptions003, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx.jpg"; + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri, uri.c_str()); + OH_UdsFileUri_SetFileType(fileUri, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record, fileUri); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + OH_UdmfOptions* options = nullptr; + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options, &dataArray, &dataSize); + EXPECT_EQ(getRes, UDMF_E_INVALID_PARAM); + + OH_UdmfOptions* options1 = OH_UdmfOptions_Create(); + options1->intention = UDMF_INTENTION_DRAG; + unsigned int dataSize1 = 0; + OH_UdmfData* dataArray1 = nullptr; + int getRes1 = OH_Udmf_GetUnifiedDataByOptions(options1, &dataArray1, &dataSize1); + EXPECT_EQ(getRes1, UDMF_E_INVALID_PARAM); + + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_MENU; + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int getRes2 = OH_Udmf_GetUnifiedDataByOptions(options2, &dataArray2, &dataSize2); + EXPECT_EQ(getRes2, UDMF_ERR); + + OH_UdmfOptions_Destroy(options1); + OH_UdmfOptions_Destroy(options2); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + OH_Udmf_DestroyDataArray(&dataArray1, dataSize1); + OH_UdsFileUri_Destroy(fileUri); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_UpdateUnifiedData002 + * @tc.desc: OH_Udmf_UpdateUnifiedData001 with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_UpdateUnifiedData002, TestSize.Level1) +{ + OH_UdmfData *udmfUnifiedData = nullptr; + OH_UdmfOptions* options = nullptr; + int updataRes = OH_Udmf_UpdateUnifiedData(options, udmfUnifiedData); + EXPECT_EQ(updataRes, UDMF_E_INVALID_PARAM); + + std::string uri2 = "https://new/uri/path.jpg"; + OH_UdmfData *udmfUnifiedData2 = OH_UdmfData_Create(); + OH_UdmfRecord *record2 = OH_UdmfRecord_Create(); + OH_UdsFileUri *fileUri2 = OH_UdsFileUri_Create(); + OH_UdsFileUri_SetFileUri(fileUri2, uri2.c_str()); + OH_UdsFileUri_SetFileType(fileUri2, UDMF_META_IMAGE); + OH_UdmfRecord_AddFileUri(record2, fileUri2); + OH_UdmfData_AddRecord(udmfUnifiedData2, record2); + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_DRAG; + options2->key = "testKey"; + int updataRes1 = OH_Udmf_UpdateUnifiedData(options2, udmfUnifiedData2); + EXPECT_EQ(updataRes1, UDMF_E_INVALID_PARAM); + + OH_UdmfOptions_Destroy(options2); + OH_UdsFileUri_Destroy(fileUri2); + OH_UdmfRecord_Destroy(record2); + OH_UdmfData_Destroy(udmfUnifiedData2); +} + +/** + * @tc.name: OH_Udmf_UpdateUnifiedData003 + * @tc.desc: OH_Udmf_UpdateUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_UpdateUnifiedData003, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx4.jpg"; + OH_UdmfData *udmfUnifiedData = CreateImageDataWithFileUri(uri); + OH_UdmfOptions* options = nullptr; + int upDataRes = OH_Udmf_UpdateUnifiedData(options, udmfUnifiedData); + EXPECT_EQ(upDataRes, UDMF_E_INVALID_PARAM); + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + upDataRes = OH_Udmf_UpdateUnifiedData(options, udmfUnifiedData); + EXPECT_EQ(upDataRes, UDMF_E_INVALID_PARAM); + OH_UdmfOptions_Destroy(options2); +} + +/** + * @tc.name: OH_Udmf_DeleteUnifiedData005 + * @tc.desc: OH_Udmf_DeleteUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_DeleteUnifiedData005, TestSize.Level1) +{ + unsigned int* dataSize = nullptr; + OH_UdmfData* dataArray = nullptr; + OH_UdmfOptions* options = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options, &dataArray, dataSize); + EXPECT_EQ(deleteRes, UDMF_E_INVALID_PARAM); + + unsigned int dataSize2 = 0 ; + OH_UdmfData* dataArray2 = nullptr; + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_DRAG; + options2->key = "testKey"; + int deleteRes2 = OH_Udmf_DeleteUnifiedData(options2, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes2, UDMF_E_INVALID_PARAM); + + OH_UdmfOptions_Destroy(options2); + OH_UdmfData* dataArray1 = nullptr; + OH_Udmf_DestroyDataArray(&dataArray1, dataSize2); +} + +/** + * @tc.name: OH_UdmfOptions_GetVisibility001 + * @tc.desc: OH_UdmfOptions_GetVisibility with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_UdmfOptions_GetVisibility001, TestSize.Level1) +{ + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->visibility = UDMF_OWN_PROCESS; + Udmf_Visibility getVisibility = OH_UdmfOptions_GetVisibility(options); + EXPECT_EQ(getVisibility, UDMF_OWN_PROCESS); + OH_UdmfOptions_Destroy(options); +} + +/** + * @tc.name: OH_UdmfOptions_GetVisibility002 + * @tc.desc: OH_UdmfOptions_GetVisibility with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_UdmfOptions_GetVisibility002, TestSize.Level1) +{ + OH_UdmfOptions* options = nullptr; + Udmf_Visibility getVisibility = OH_UdmfOptions_GetVisibility(options); + EXPECT_EQ(getVisibility, UDMF_ALL); +} + +/** + * @tc.name: OH_UdmfOptions_SetVisibility001 + * @tc.desc: OH_UdmfOptions_SetVisibility with content form + * @tc.type: FUNCF + */ +HWTEST_F(UDMFTest, OH_UdmfOptions_SetVisibility001, TestSize.Level1) +{ + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + Udmf_Visibility testVisibility = UDMF_ALL; + int setRes = OH_UdmfOptions_SetVisibility(options, testVisibility); + EXPECT_EQ(setRes, UDMF_E_OK); + OH_UdmfOptions_Destroy(options); +} + +/** + * @tc.name: OH_UdmfOptions_SetVisibility002 + * @tc.desc: OH_UdmfOptions_SetVisibility with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_UdmfOptions_SetVisibility002, TestSize.Level1) +{ + Udmf_Visibility testVisibility = UDMF_ALL; + OH_UdmfOptions* options = nullptr; + int setRes2 = OH_UdmfOptions_SetVisibility(options, testVisibility); + EXPECT_EQ(setRes2, UDMF_E_INVALID_PARAM); +} + +/** + * @tc.name: SetVisibilityAndGetVisibility001 + * @tc.desc: OH_UdmfOptions_SetVisibility and OH_UdmfOptions_GetVisibility with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, SetVisibilityAndGetVisibility001, TestSize.Level1) +{ + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + Udmf_Visibility testVisibility = UDMF_ALL; + int setRes = OH_UdmfOptions_SetVisibility(options, testVisibility); + EXPECT_EQ(setRes, UDMF_E_OK); + Udmf_Visibility getVisibility = OH_UdmfOptions_GetVisibility(options); + EXPECT_EQ(getVisibility, testVisibility); + OH_UdmfOptions_Destroy(options); +} + +/** + * @tc.name: SetVisibilityAndGetVisibility002 + * @tc.desc: OH_UdmfOptions_SetVisibility and OH_UdmfOptions_GetVisibility with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, SetVisibilityAndGetVisibility002, TestSize.Level1) +{ + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + Udmf_Visibility testVisibility = Udmf_Visibility::UDMF_OWN_PROCESS; + int setRes = OH_UdmfOptions_SetVisibility(options, testVisibility); + EXPECT_EQ(setRes, UDMF_E_OK); + Udmf_Visibility getVisibility = OH_UdmfOptions_GetVisibility(options); + EXPECT_EQ(getVisibility, testVisibility); + OH_UdmfOptions_Destroy(options); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedDataByOptions002 + * @tc.desc: OH_Udmf_SetUnifiedDataByOptions and OH_Udmf_GetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedDataByOptions002, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx2.jpg"; + OH_UdmfData *udmfUnifiedData = CreateImageDataWithFileUri(uri); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + options->visibility = UDMF_OWN_PROCESS; + char key[UDMF_KEY_BUFFER_LEN]; + unsigned int dataSize3 = 0; + OH_UdmfData* dataArray3 = nullptr; + OH_Udmf_DeleteUnifiedData(options, &dataArray3, &dataSize3); + + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + OH_UdmfOptions* options2 = OH_UdmfOptions_Create(); + options2->intention = UDMF_INTENTION_DATA_HUB; + options2->key = key; + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options2, &dataArray, &dataSize); + EXPECT_EQ(getRes, UDMF_E_OK); + EXPECT_NE(dataArray, nullptr); + + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + EXPECT_NE(dataArray2, nullptr); + + OH_Udmf_DestroyDataArray(&dataArray, dataSize); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + OH_Udmf_DestroyDataArray(&dataArray3, dataSize3); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfOptions_Destroy(options); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedDataByOptions003 + * @tc.desc: OH_Udmf_SetUnifiedDataByOptions and OH_Udmf_GetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedDataByOptions003, TestSize.Level1) +{ + SetHapToken1(); + std::string uri = "https://xxx/xx/xx3.jpg"; + OH_UdmfData *udmfUnifiedData = CreateImageDataWithFileUri(uri); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + options->visibility = UDMF_OWN_PROCESS; + char key[UDMF_KEY_BUFFER_LEN]; + unsigned int dataSize3 = 0; + OH_UdmfData* dataArray3 = nullptr; + OH_Udmf_DeleteUnifiedData(options, &dataArray3, &dataSize3); + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + SetHapToken2(); + OH_UdmfOptions* options1 = OH_UdmfOptions_Create(); + options1->intention = UDMF_INTENTION_DATA_HUB; + options1->key = key; + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options1, &dataArray, &dataSize); + EXPECT_EQ(getRes, UDMF_E_OK); + EXPECT_EQ(dataArray, nullptr); + + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + EXPECT_NE(dataArray2, nullptr); + + OH_Udmf_DestroyDataArray(&dataArray, dataSize); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + OH_Udmf_DestroyDataArray(&dataArray3, dataSize3); + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options1); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedDataByOptions004 + * @tc.desc: OH_Udmf_SetUnifiedDataByOptions and OH_Udmf_GetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedDataByOptions004, TestSize.Level1) +{ + SetHapToken1(); + std::string uri = "https://xxx/xx/xx4.jpg"; + OH_UdmfData *udmfUnifiedData = CreateImageDataWithFileUri(uri); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + options->visibility = UDMF_ALL; + char key[UDMF_KEY_BUFFER_LEN]; + + unsigned int dataSize3 = 0; + OH_UdmfData* dataArray3 = nullptr; + OH_Udmf_DeleteUnifiedData(options, &dataArray3, &dataSize3); + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + SetHapToken2(); + OH_UdmfOptions* options1 = OH_UdmfOptions_Create(); + options1->intention = UDMF_INTENTION_DATA_HUB; + options1->key = key; + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options1, &dataArray, &dataSize); + EXPECT_EQ(getRes, UDMF_E_OK); + EXPECT_NE(dataArray, nullptr); + + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + EXPECT_NE(dataArray2, nullptr); + + OH_Udmf_DestroyDataArray(&dataArray, dataSize); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + OH_Udmf_DestroyDataArray(&dataArray3, dataSize3); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options1); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedDataByOptions005 + * @tc.desc: OH_Udmf_SetUnifiedDataByOptions and OH_Udmf_GetUnifiedDataByOptions with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedDataByOptions005, TestSize.Level1) +{ + std::string uri = "https://xxx/xx/xx5.jpg"; + OH_UdmfData *udmfUnifiedData = CreateImageDataWithFileUri(uri); + OH_UdmfOptions* options = OH_UdmfOptions_Create(); + options->intention = UDMF_INTENTION_DATA_HUB; + options->visibility = UDMF_ALL; + char key[UDMF_KEY_BUFFER_LEN]; + + unsigned int dataSize3 = 0; + OH_UdmfData* dataArray3 = nullptr; + OH_Udmf_DeleteUnifiedData(options, &dataArray3, &dataSize3); + int setRes = OH_Udmf_SetUnifiedDataByOptions(options, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + + OH_UdmfOptions* options1 = OH_UdmfOptions_Create(); + options1->intention = UDMF_INTENTION_DATA_HUB; + options1->key = key; + unsigned int dataSize = 0; + OH_UdmfData* dataArray = nullptr; + int getRes = OH_Udmf_GetUnifiedDataByOptions(options1, &dataArray, &dataSize); + EXPECT_EQ(getRes, UDMF_E_OK); + EXPECT_NE(dataArray, nullptr); + + unsigned int recordCount = 0; + OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(&dataArray[0], &recordCount); + EXPECT_EQ(recordCount, 1); + OH_UdsFileUri *getFileUri = OH_UdsFileUri_Create(); + OH_UdmfRecord_GetFileUri(getRecords[0], getFileUri); + const char *getUri = OH_UdsFileUri_GetFileUri(getFileUri); + EXPECT_EQ(strcmp(getUri, uri.c_str()), 0); + + unsigned int dataSize2 = 0; + OH_UdmfData* dataArray2 = nullptr; + int deleteRes = OH_Udmf_DeleteUnifiedData(options, &dataArray2, &dataSize2); + EXPECT_EQ(deleteRes, UDMF_E_OK); + EXPECT_NE(dataArray2, nullptr); + + OH_Udmf_DestroyDataArray(&dataArray, dataSize); + OH_Udmf_DestroyDataArray(&dataArray2, dataSize2); + OH_Udmf_DestroyDataArray(&dataArray3, dataSize3); + OH_UdsFileUri_Destroy(getFileUri); + OH_UdmfOptions_Destroy(options); + OH_UdmfOptions_Destroy(options1); + OH_UdmfData_Destroy(udmfUnifiedData); +} + +/** + * @tc.name: DestroyUnifiedRecordArray001 + * @tc.desc: test DestroyUnifiedRecordArray + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, DestroyUnifiedRecordArray001, TestSize.Level1) +{ + OH_UdmfData *unifiedData = OH_UdmfData_Create(); + EXPECT_NE(unifiedData, nullptr); + std::shared_ptr<Object> object = std::make_shared<Object>(); + std::map<std::string, ValueType> map; + map["uniformDataType"] = UtdUtils::GetUtdIdFromUtdEnum(UDType::PLAIN_TEXT); + map["textContent"] = "content"; + map["abstract"] = "abstract"; + object->value_ = map; + std::shared_ptr<UnifiedRecord> record = std::make_shared<PlainText>(PLAIN_TEXT, object); + std::vector<std::shared_ptr<UnifiedRecord>> recordVec = { record }; + unifiedData->records = nullptr; + unifiedData->unifiedData_->SetRecords(recordVec); + unsigned int recordCount = 0; + OH_UdmfRecord **getRecords = OH_UdmfData_GetRecords(unifiedData, &recordCount); + EXPECT_EQ(recordCount, 1); + EXPECT_EQ(unifiedData->recordsCount, 1); + EXPECT_NE(getRecords[0], nullptr); + getRecords[0]->recordDataLen = 1; + getRecords[0]->recordData = new (std::nothrow) unsigned char[getRecords[0]->recordDataLen]; + unifiedData->records = getRecords; + OH_UdmfData_Destroy(unifiedData); + EXPECT_EQ(unifiedData->recordsCount, 0); +} } diff --git a/udmf/interfaces/ani/BUILD.gn b/udmf/interfaces/ani/BUILD.gn new file mode 100644 index 00000000..657f9e78 --- /dev/null +++ b/udmf/interfaces/ani/BUILD.gn @@ -0,0 +1,131 @@ +# Copyright (c) 2021-2022 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/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/distributeddatamgr/udmf/udmf.gni") + +config("ani_config") { + include_dirs = [ + "native/include", + "${udmf_interfaces_path}/cj/include", + "${udmf_interfaces_path}/innerkits/data/", + "${udmf_interfaces_path}/innerkits/common", + ] +} + +group("udmf_data_ani") { + deps = [ + ":unifiedDataChannel_abc_etc", + ":unifieddatachannel_ani", + ":uniformTypeDescriptor_abc_etc", + ":uniformTypeDescriptor_ani", + ] +} + +ohos_shared_library("unifieddatachannel_ani") { + branch_protector_ret = "pac_ret" + sanitize = { + oundary_sanitize = true + ubsan = true + cfi = true + cfi_cross_dso = true + debug = false + } + sources = [ "native/src/unifieddatachannel_ani.cpp" ] + + public_configs = [ ":ani_config" ] + + deps = [ "${udmf_interfaces_path}/innerkits:udmf_client" ] + + external_deps = [ + "ability_base:want", + "ability_runtime:abilitykit_native", + "ability_runtime:ani_common", + "ability_runtime:appkit_native", + "ability_runtime:napi_common", + "c_utils:utils", + "hilog:libhilog", + "image_framework:image_ani", + "ipc:ipc_single", + "runtime_core:ani", + ] + + subsystem_name = "distributeddatamgr" + part_name = "udmf" + output_extension = "so" +} + +generate_static_abc("unifiedDataChannel_abc") { + base_url = "./ets" + files = [ "./ets/@ohos.data.unifiedDataChannel.ets" ] + dst_file = "$target_out_dir/data_unifiedDataChannel.abc" + out_puts = [ "$target_out_dir/data_unifiedDataChannel.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/data_unifiedDataChannel.abc" +} + +ohos_prebuilt_etc("unifiedDataChannel_abc_etc") { + source = "$target_out_dir/data_unifiedDataChannel.abc" + module_install_dir = "framework" + subsystem_name = "distributeddatamgr" + part_name = "udmf" + deps = [ ":unifiedDataChannel_abc" ] +} + +ohos_shared_library("uniformTypeDescriptor_ani") { + branch_protector_ret = "pac_ret" + sanitize = { + oundary_sanitize = true + ubsan = true + cfi = true + cfi_cross_dso = true + debug = false + } + public_configs = [ ":ani_config" ] + sources = [ "native/src/uniformTypeDescriptor_ani.cpp" ] + + deps = [ + "../innerkits:udmf_client", + "../innerkits:utd_client", + "../jskits:udmf_js_common", + ] + + external_deps = [ + "ability_runtime:abilitykit_native", + "c_utils:utils", + "hilog:libhilog", + "runtime_core:ani", + ] + + subsystem_name = "distributeddatamgr" + part_name = "udmf" + output_extension = "so" +} + +generate_static_abc("uniformTypeDescriptor_abc") { + base_url = "./ets" + files = [ "./ets/@ohos.data.uniformTypeDescriptor.ets" ] + dst_file = "$target_out_dir/data_uniformTypeDescriptor.abc" + out_puts = [ "$target_out_dir/data_uniformTypeDescriptor.abc" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/data_uniformTypeDescriptor.abc" +} + +ohos_prebuilt_etc("uniformTypeDescriptor_abc_etc") { + source = "$target_out_dir/data_uniformTypeDescriptor.abc" + module_install_dir = "framework" + subsystem_name = "distributeddatamgr" + part_name = "udmf" + deps = [ ":uniformTypeDescriptor_abc" ] +} diff --git a/udmf/interfaces/ani/ets/@ohos.data.unifiedDataChannel.ets b/udmf/interfaces/ani/ets/@ohos.data.unifiedDataChannel.ets new file mode 100644 index 00000000..cecc8994 --- /dev/null +++ b/udmf/interfaces/ani/ets/@ohos.data.unifiedDataChannel.ets @@ -0,0 +1,112 @@ +/* + * 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 image from "@ohos.multimedia.image"; +import Want from "@ohos.app.ability.Want"; + +type ValueType = number | string | boolean | image.PixelMap | Want | ArrayBuffer | object | null | undefined; + + export default namespace unifiedDataChannel { + export class Cleaner { + static { loadLibrary("unifieddatachannel_ani") } + static callback(cleaner: Cleaner): void { + cleaner.clean() + } + constructor(targetPtr: long) { + this.targetPtr = targetPtr + } + + native clean(): void + + private targetPtr: long = 0 + } + class FinalizationAgent<T extends Object> { + constructor(obj: T, ptr: long) { + this.register(obj, ptr); + } + + register(obj: T, ptr: long): void { + this.unregisterToken = {}; + this.cleaner = new Cleaner(ptr); + finalizer.register(obj, this.cleaner!, this.unregisterToken); + } + + unregister(): void { + finalizer.unregister(this.unregisterToken); + } + + private cleaner: Cleaner | null = null; + private unregisterToken: object; + } + + let finalizer = new FinalizationRegistry<Cleaner>(Cleaner.callback) + export class UnifiedRecord { + static { loadLibrary("unifieddatachannel_ani") } + + constructor(type?: string, value?: ValueType) { + if (type == undefined) { + this.initRecordWithOutTypeValue(); + } else { + this.init(type, value); + } + this.registerCleaner(); + } + + registerCleaner(): void { + this.fzAgent = new FinalizationAgent<UnifiedRecord>(this, this.nativePtr); + } + + unregisterCleaner(): void { + this.fzAgent.unregister(); + } + setNativePtr(context: long) { + this.nativePtr = context; + } + + private fzAgent: FinalizationAgent<UnifiedRecord>; + native init(type: string, value: ValueType): void; + native initRecordWithOutTypeValue(): void; + private nativePtr: long = 0; + } + + export class UnifiedData { + static { loadLibrary("unifieddatachannel_ani") } + constructor(record?: UnifiedRecord) { + if (record == undefined) { + this.initDataWithOutRecord(); + } else { + this.initData(record); + } + this.registerCleaner(); + } + + registerCleaner(): void { + this.fzAgent = new FinalizationAgent<UnifiedData>(this, this.nativePtr); + } + + unregisterCleaner(): void { + this.fzAgent.unregister(); + } + native initData(record: UnifiedRecord): void; + native initDataWithOutRecord(): void; + native getRecords(): Array<UnifiedRecord>; + + getNativePtr(): long { + return this.nativePtr; + } + + private fzAgent: FinalizationAgent<UnifiedData>; + private nativePtr: long = 0; + } +} \ No newline at end of file diff --git a/udmf/interfaces/ani/ets/@ohos.data.uniformTypeDescriptor.ets b/udmf/interfaces/ani/ets/@ohos.data.uniformTypeDescriptor.ets new file mode 100644 index 00000000..cfb68720 --- /dev/null +++ b/udmf/interfaces/ani/ets/@ohos.data.uniformTypeDescriptor.ets @@ -0,0 +1,19 @@ +/* + * 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. + */ + + export default namespace uniformTypeDescriptor { + loadLibrary("uniformTypeDescriptor_ani") + export native function getUniformDataTypeByFilenameExtension(filenameExtension: string, belongsTo?: string): string; + } \ No newline at end of file diff --git a/udmf/interfaces/ani/native/include/ani_util_class.h b/udmf/interfaces/ani/native/include/ani_util_class.h new file mode 100644 index 00000000..33fa53c8 --- /dev/null +++ b/udmf/interfaces/ani/native/include/ani_util_class.h @@ -0,0 +1,122 @@ +/* + * 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 ANI_UTIL_CLASS_H +#define ANI_UTIL_CLASS_H + +#include <ani.h> +#include <cstdarg> + +#include "ani_util_common.h" + +class AniTypeFinder { +public: + AniTypeFinder(ani_env *env) : env_(env) {} + + expected<ani_namespace, ani_status> FindNamespace(const char *nsName) + { + ani_namespace ns; + ani_status status = env_->FindNamespace(nsName, &ns); + if (ANI_OK != status) { + return status; + } + return ns; + } + + template <typename... Names> + expected<ani_namespace, ani_status> FindNamespace(const char *firstNs, const char *nextNs, Names... restNs) + { + ani_namespace ns; + ani_status status = env_->FindNamespace(firstNs, &ns); + if (ANI_OK != status) { + return status; + } + return FindNamespace(ns, nextNs, restNs...); + } + + expected<ani_class, ani_status> FindClass(const char *clsName) + { + ani_class cls; + ani_status status = env_->FindClass(clsName, &cls); + if (ANI_OK != status) { + return status; + } + return cls; + } + + expected<ani_class, ani_status> FindClass(const char *nsName, const char *clsName) + { + auto ns = FindNamespace(nsName, clsName); + if (!ns.has_value()) { + return ns.error(); + } + return FindClass(ns.value(), clsName); + } + + template <typename... Names> + expected<ani_class, ani_status> FindClass(const char *firstNs, + const char *secondNs, + Names... restNs, + const char *clsName) + { + auto ns = FindNamespace(firstNs, secondNs, restNs...); + if (!ns.has_value()) { + return ns.error(); + } + return FindClass(ns.value(), clsName); + } + + expected<ani_class, ani_status> FindClass(ani_namespace ns, const char *clsName) + { + ani_class cls; + ani_status status = env_->Namespace_FindClass(ns, clsName, &cls); + if (ANI_OK != status) { + return status; + } + return cls; + } + + expected<ani_enum, ani_status> FindEnum(ani_namespace ns, const char *enumName) + { + ani_enum aniEnum {}; + ani_status status = env_->Namespace_FindEnum(ns, enumName, &aniEnum); + if (ANI_OK != status) { + return status; + } + return aniEnum; + } + +private: + template <typename... Names> + expected<ani_namespace, ani_status> FindNamespace(ani_namespace currentNs, const char *nextNs, Names... restNs) + { + ani_namespace ns; + ani_status status = env_->Namespace_FindNamespace(currentNs, nextNs, &ns); + if (ANI_OK != status) { + return status; + } + return FindNamespace(ns, restNs...); + } + + expected<ani_namespace, ani_status> FindNamespace(ani_namespace currentNs) + { + return currentNs; + } + +private: + ani_env *env_ = nullptr; +}; + +#endif diff --git a/udmf/interfaces/ani/native/include/ani_util_common.h b/udmf/interfaces/ani/native/include/ani_util_common.h new file mode 100644 index 00000000..5b5cb554 --- /dev/null +++ b/udmf/interfaces/ani/native/include/ani_util_common.h @@ -0,0 +1,172 @@ +/* + * 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 ANI_UTIL_COMMON_H +#define ANI_UTIL_COMMON_H + +#include <exception> +#include <memory> +#include <type_traits> +#include <utility> +#include <variant> + +template <typename T, typename E> +class expected { +private: + std::variant<T, E> data_; + bool has_value_; + +public: + expected(const T &value) : data_(value), has_value_(true) {} + + expected(T &&value) : data_(std::move(value)), has_value_(true) {} + + expected(const E &error) : data_(error), has_value_(false) {} + + expected(E &&error) : data_(std::move(error)), has_value_(false) {} + + bool has_value() const noexcept + { + return has_value_; + } + + explicit operator bool() const noexcept + { + return has_value(); + } + + T &value() & + { + if (!has_value()) { + std::terminate(); + } + return std::get<T>(data_); + } + + const T &value() const & + { + if (!has_value()) { + std::terminate(); + } + return std::get<T>(data_); + } + + T &&value() && + { + if (!has_value()) { + std::terminate(); + } + return std::get<T>(std::move(data_)); + } + + E &error() & + { + if (has_value()) { + std::terminate(); + } + return std::get<E>(data_); + } + + const E &error() const & + { + if (has_value()) { + std::terminate(); + } + return std::get<E>(data_); + } + + E &&error() && + { + if (has_value()) { + std::terminate(); + } + return std::get<E>(std::move(data_)); + } + + T &operator*() & + { + return value(); + } + + const T &operator*() const & + { + return value(); + } + + T &&operator*() && + { + return std::move(*this).value(); + } + + T *operator->() + { + return &value(); + } + + const T *operator->() const + { + return &value(); + } + + template <typename U> + T value_or(U &&default_value) const & + { + return has_value() ? value() : static_cast<T>(std::forward<U>(default_value)); + } + + template <typename U> + T value_or(U &&default_value) && + { + return has_value() ? std::move(*this).value() : static_cast<T>(std::forward<U>(default_value)); + } +}; + +template <typename F> +class FinalAction { +public: + explicit FinalAction(F func) : func_(std::move(func)) {} + + ~FinalAction() noexcept(noexcept(func_())) + { + if (!dismissed_) { + func_(); + } + } + + FinalAction(const FinalAction &) = delete; + FinalAction &operator=(const FinalAction &) = delete; + + FinalAction(FinalAction &&other) noexcept : func_(std::move(other.func_)), dismissed_(other.dismissed_) + { + other.dismissed_ = true; + } + + void dismiss() noexcept + { + dismissed_ = true; + } + +private: + F func_; + bool dismissed_ = false; +}; + +template <typename F> +inline FinalAction<F> finally(F &&func) +{ + return FinalAction<F>(std::forward<F>(func)); +} + +#endif diff --git a/udmf/interfaces/ani/native/include/ani_util_native_ptr.h b/udmf/interfaces/ani/native/include/ani_util_native_ptr.h new file mode 100644 index 00000000..1ba4c340 --- /dev/null +++ b/udmf/interfaces/ani/native/include/ani_util_native_ptr.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 ANI_UTIL_OBJECT_H +#define ANI_UTIL_OBJECT_H + +#include <ani.h> +#include <memory> +#include <string> + +class NativeObject { +public: + virtual ~NativeObject() = default; +}; + +template <typename T> +class StdSharedPtrHolder : public NativeObject { +public: + StdSharedPtrHolder(const std::shared_ptr<T> &sptr) : sptr_(sptr) {} + + std::shared_ptr<T> Get() + { + return sptr_; + } + + std::shared_ptr<T> GetOrDefault() + { + if (!sptr_) { + sptr_ = std::make_shared<T>(); + } + return sptr_; + } + +private: + std::shared_ptr<T> sptr_; +}; + +class NativePtrCleaner { +public: + static void Clean([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) + { + ani_long ptr = 0; + if (ANI_OK != env->Object_GetFieldByName_Long(object, "targetPtr", &ptr)) { + return; + } + delete reinterpret_cast<NativeObject *>(ptr); + } + + NativePtrCleaner(ani_env *env) : env_(env) {} + + ani_status Bind(ani_class cls) + { + std::array methods = { + ani_native_function {"clean", nullptr, reinterpret_cast<void *>(NativePtrCleaner::Clean)}, + }; + + if (ANI_OK != env_->Class_BindNativeMethods(cls, methods.data(), methods.size())) { + return (ani_status)ANI_ERROR; + }; + + return ANI_OK; + } + +private: + ani_env *env_ = nullptr; +}; +#endif diff --git a/udmf/interfaces/ani/native/include/ani_utils.h b/udmf/interfaces/ani/native/include/ani_utils.h new file mode 100644 index 00000000..41102f01 --- /dev/null +++ b/udmf/interfaces/ani/native/include/ani_utils.h @@ -0,0 +1,455 @@ +/* + * 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 ANI_UTILS_H +#define ANI_UTILS_H + +#include <ani.h> + +#include <cstdarg> +#include <memory> +#include <mutex> +#include <optional> +#include <string> +#include <unordered_map> +#include <vector> +#include <iostream> +#include "ani_util_native_ptr.h" +#include "ani_util_class.h" + +class AniObjectUtils { +public: + static ani_object Create(ani_env *env, const char* nsName, const char* clsName, ...) + { + ani_object nullobj{}; + + ani_namespace ns; + if (ANI_OK != env->FindNamespace(nsName, &ns)) { + std::cerr << "[ANI] Not found namespace " << nsName << std::endl; + return nullobj; + } + + ani_class cls; + if (ANI_OK != env->Namespace_FindClass(ns, clsName, &cls)) { + std::cerr << "[ANI] Not found class " << clsName << std::endl; + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) { + std::cerr << "[ANI] Not found <ctor> for class " << clsName << std::endl; + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + std::cerr << "[ANI] Failed to Object_New for class " << cls << std::endl; + return nullobj; + } + return obj; + } + + static ani_object Create(ani_env *env, const char* clsName, ...) + { + ani_object nullobj{}; + + ani_class cls; + if (ANI_OK != env->FindClass(clsName, &cls)) { + std::cerr << "[ANI] Not found class " << clsName << std::endl; + return nullobj; + } + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) { + std::cerr << "[ANI] Not found <ctor> for class " << clsName << std::endl; + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, clsName); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + std::cerr << "[ANI] Failed to Object_New for class " << cls << std::endl; + return nullobj; + } + return obj; + } + + static ani_object Create(ani_env *env, ani_class cls, ...) + { + ani_object nullobj{}; + + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor)) { + std::cerr << "[ANI] Not found <ctor> for class" << std::endl; + return nullobj; + } + + ani_object obj; + va_list args; + va_start(args, cls); + ani_status status = env->Object_New_V(cls, ctor, &obj, args); + va_end(args); + if (ANI_OK != status) { + std::cerr << "[ANI] Failed to Object_New for class " << cls << std::endl; + return nullobj; + } + return obj; + } + + static ani_object From(ani_env *env, bool value) + { + return Create(env, "Lstd/core/Boolean;", static_cast<ani_boolean>(value)); + } + + template<typename T> + static ani_status Wrap(ani_env *env, ani_object object, T* nativePtr, const char* propName = "nativePtr") + { + return env->Object_SetFieldByName_Long(object, propName, reinterpret_cast<ani_long>(nativePtr)); + } + + template<typename T> + static T* Unwrap(ani_env *env, ani_object object, const char* propName = "nativePtr") + { + ani_long nativePtr; + if (ANI_OK != env->Object_GetFieldByName_Long(object, propName, &nativePtr)) { + return nullptr; + } + return reinterpret_cast<T*>(nativePtr); + } +}; + +class AniStringUtils { +public: + static std::string ToStd(ani_env *env, ani_string ani_str) + { + ani_size strSize; + env->String_GetUTF8Size(ani_str, &strSize); + + std::vector<char> buffer(strSize + 1); // +1 for null terminator + char* utf8_buffer = buffer.data(); + + //String_GetUTF8 Supportted by https://gitee.com/openharmony/arkcompiler_runtime_core/pulls/3416 + ani_size bytes_written = 0; + env->String_GetUTF8(ani_str, utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + return content; + } + + static ani_string ToAni(ani_env* env, const std::string& str) + { + ani_string aniStr = nullptr; + if (ANI_OK != env->String_NewUTF8(str.data(), str.size(), &aniStr)) { + std::cerr << "[ANI] Unsupported ANI_VERSION_1" << std::endl; + return nullptr; + } + return aniStr; + } +}; + +class UnionAccessor { +public: + UnionAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) + { + } + + bool IsInstanceOf(const std::string& cls_name) + { + ani_class cls; + env_->FindClass(cls_name.c_str(), &cls); + + ani_boolean ret; + env_->Object_InstanceOf(obj_, cls, &ret); + return ret; + } + + template<typename T> + bool IsInstanceOfType(); + + template<typename T> + bool TryConvert(T &value); + + template<typename T> + bool TryConvertArray(std::vector<T> &value); + +private: + ani_env *env_; + ani_object obj_; +}; + +template<> +bool UnionAccessor::IsInstanceOfType<bool>() +{ + return IsInstanceOf("Lstd/core/Boolean;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType<int>() +{ + return IsInstanceOf("Lstd/core/Int;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType<double>() +{ + return IsInstanceOf("Lstd/core/Double;"); +} + +template<> +bool UnionAccessor::IsInstanceOfType<std::string>() +{ + return IsInstanceOf("Lstd/core/String;"); +} + +template<> +bool UnionAccessor::TryConvert<bool>(bool &value) +{ + if (!IsInstanceOfType<bool>()) { + return false; + } + + ani_boolean aniValue; + auto ret = env_->Object_CallMethodByName_Boolean(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast<bool>(aniValue); + return true; +} + +template<> +bool UnionAccessor::TryConvert<int>(int &value) +{ + if (!IsInstanceOfType<int>()) { + return false; + } + + ani_int aniValue; + auto ret = env_->Object_CallMethodByName_Int(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast<int>(aniValue); + return true; +} + +template<> +bool UnionAccessor::TryConvert<double>(double &value) +{ + if (!IsInstanceOfType<double>()) { + return false; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "unboxed", nullptr, &aniValue); + if (ret != ANI_OK) { + return false; + } + value = static_cast<double>(aniValue); + return true; +} + +template<> +bool UnionAccessor::TryConvert<std::string>(std::string &value) +{ + if (!IsInstanceOfType<std::string>()) { + return false; + } + + value = AniStringUtils::ToStd(env_, static_cast<ani_string>(obj_)); + return true; +} + +template<> +bool UnionAccessor::TryConvertArray<bool>(std::vector<bool> &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + std::cerr << "Object_GetPropertyByName_Double length failed" << std::endl; + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + std::cerr << "Object_GetPropertyByName_Ref failed" << std::endl; + return false; + } + ani_boolean val; + if (ANI_OK != env_->Object_CallMethodByName_Boolean(static_cast<ani_object>(ref), "unboxed", nullptr, &val)) { + std::cerr << "Object_CallMethodByName_Double unbox failed" << std::endl; + return false; + } + value.push_back(static_cast<bool>(val)); + } + return true; +} + +template<> +bool UnionAccessor::TryConvertArray<int>(std::vector<int> &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + std::cerr << "Object_GetPropertyByName_Double length failed" << std::endl; + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + std::cerr << "Object_GetPropertyByName_Ref failed" << std::endl; + return false; + } + ani_int intValue; + if (ANI_OK != env_->Object_CallMethodByName_Int(static_cast<ani_object>(ref), "unboxed", nullptr, &intValue)) { + std::cerr << "Object_CallMethodByName_Double unbox failed" << std::endl; + return false; + } + value.push_back(static_cast<int>(intValue)); + } + return true; +} + +template<> +bool UnionAccessor::TryConvertArray<double>(std::vector<double> &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + std::cerr << "Object_GetPropertyByName_Double length failed" << std::endl; + return false; + } + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + std::cerr << "Object_GetPropertyByName_Ref failed" << std::endl; + return false; + } + ani_double val; + if (ANI_OK != env_->Object_CallMethodByName_Double(static_cast<ani_object>(ref), "unboxed", nullptr, &val)) { + std::cerr << "Object_CallMethodByName_Double unbox failed" << std::endl; + return false; + } + value.push_back(static_cast<double>(val)); + } + return true; +} + +template<> +bool UnionAccessor::TryConvertArray<uint8_t>(std::vector<uint8_t> &value) +{ + std::cout << "TryConvertArray std::vector<uint8_t>" << std::endl; + ani_ref buffer; + if (ANI_OK != env_->Object_GetFieldByName_Ref(obj_, "buffer", &buffer)) { + std::cout << "Object_GetFieldByName_Ref failed" << std::endl; + return false; + } + void* data; + size_t length; + if (ANI_OK != env_->ArrayBuffer_GetInfo(static_cast<ani_arraybuffer>(buffer), &data, &length)) { + std::cerr << "ArrayBuffer_GetInfo failed" << std::endl; + return false; + } + std::cout << "Length of buffer is " << length << std::endl; + for (size_t i = 0; i < length; i++) { + value.push_back(static_cast<uint8_t*>(data)[i]); + } + return true; +} + +template<> +bool UnionAccessor::TryConvertArray<std::string>(std::vector<std::string> &value) +{ + ani_double length; + if (ANI_OK != env_->Object_GetPropertyByName_Double(obj_, "length", &length)) { + std::cerr << "Object_GetPropertyByName_Double length failed" << std::endl; + return false; + } + + for (int i = 0; i < int(length); i++) { + ani_ref ref; + if (ANI_OK != env_->Object_CallMethodByName_Ref(obj_, "$_get", "I:Lstd/core/Object;", &ref, (ani_int)i)) { + std::cerr << "Object_GetPropertyByName_Double length failed" << std::endl; + return false; + } + value.push_back(AniStringUtils::ToStd(env_, static_cast<ani_string>(ref))); + } + return true; +} + +class OptionalAccessor { +public: + OptionalAccessor(ani_env *env, ani_object &obj) : env_(env), obj_(obj) + { + } + + bool IsUndefined() + { + ani_boolean isUndefined; + env_->Reference_IsUndefined(obj_, &isUndefined); + return isUndefined; + } + + template<typename T> + std::optional<T> Convert(); + +private: + ani_env *env_; + ani_object obj_; +}; + +template<> +std::optional<double> OptionalAccessor::Convert<double>() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_double aniValue; + auto ret = env_->Object_CallMethodByName_Double(obj_, "doubleValue", nullptr, &aniValue); + if (ret != ANI_OK) { + return std::nullopt; + } + auto value = static_cast<double>(aniValue); + return value; +} + +template<> +std::optional<std::string> OptionalAccessor::Convert<std::string>() +{ + if (IsUndefined()) { + return std::nullopt; + } + + ani_size strSize; + env_->String_GetUTF8Size(static_cast<ani_string>(obj_), &strSize); + + std::vector<char> buffer(strSize + 1); + char* utf8_buffer = buffer.data(); + + ani_size bytes_written = 0; + env_->String_GetUTF8(static_cast<ani_string>(obj_), utf8_buffer, strSize + 1, &bytes_written); + + utf8_buffer[bytes_written] = '\0'; + std::string content = std::string(utf8_buffer); + return content; +} + +#endif diff --git a/relational_store/frameworks/native/gdb/include/trans_db.h b/udmf/interfaces/ani/native/include/unifieddatachannel_ani.h similarity index 43% rename from relational_store/frameworks/native/gdb/include/trans_db.h rename to udmf/interfaces/ani/native/include/unifieddatachannel_ani.h index 2694aa12..c6e500a0 100644 --- a/relational_store/frameworks/native/gdb/include/trans_db.h +++ b/udmf/interfaces/ani/native/include/unifieddatachannel_ani.h @@ -13,27 +13,46 @@ * limitations under the License. */ -#ifndef ARKDATA_INTELLIGENCE_PLATFORM_TRANS_DB_H -#define ARKDATA_INTELLIGENCE_PLATFORM_TRANS_DB_H +#ifndef UNIFIEDDATACHANNEL_H +#define UNIFIEDDATACHANNEL_H + +#include <ani.h> #include <memory> +#include <string> + +#include "unified_data.h" +#include "unified_record.h" -#include "connection.h" -#include "gdb_store.h" -#include "graph_statement.h" -namespace OHOS::DistributedDataAip { -class TransDB : public DBStore { +namespace OHOS { +namespace UDMF { +class UnifiedRecordHolder { public: - TransDB(std::shared_ptr<Connection> connection); - std::pair<int32_t, std::shared_ptr<Result>> QueryGql(const std::string &gql) override; - std::pair<int32_t, std::shared_ptr<Result>> ExecuteGql(const std::string &gql) override; + explicit UnifiedRecordHolder(ani_env *env, const std::string type, ani_object unionValue); + + const std::shared_ptr<UnifiedRecord> Get(); - std::pair<int32_t, std::shared_ptr<Transaction>> CreateTransaction() override; - int32_t Close() override; + void Set(ani_ref saveRemote); + + ~UnifiedRecordHolder(); private: - std::pair<int32_t, std::shared_ptr<Statement>> GetStatement(const std::string &gql) const; + ani_ref saveRemote_ = nullptr; + std::shared_ptr<UnifiedRecord> object_; +}; - std::weak_ptr<Connection> conn_; +class UnifiedDataHolder { +public: + explicit UnifiedDataHolder(UnifiedRecordHolder* recordHolder); + + std::shared_ptr<UnifiedData> Get(); + + void Set(ani_ref saveRemote); + ~UnifiedDataHolder(); + +private: + ani_ref saveRemote_ = nullptr; + std::shared_ptr<UnifiedData> object_; }; -} // namespace OHOS::DistributedDataAip -#endif // ARKDATA_INTELLIGENCE_PLATFORM_TRANS_DB_H \ No newline at end of file +} // namespace UDMF +} // namespace OHOS +#endif // UNIFIEDDATACHANNEL_H \ No newline at end of file diff --git a/udmf/interfaces/ani/native/src/unifieddatachannel_ani.cpp b/udmf/interfaces/ani/native/src/unifieddatachannel_ani.cpp new file mode 100644 index 00000000..52271da1 --- /dev/null +++ b/udmf/interfaces/ani/native/src/unifieddatachannel_ani.cpp @@ -0,0 +1,423 @@ + /* + * 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. + */ +#define LOG_TAG "unifiedDataChannelANI" +#include "unifieddatachannel_ani.h" +#include "ani_utils.h" +#include "logger.h" +#include "ani_common_want.h" +#include "image_ani_utils.h" + +#include "unified_types.h" +#include "unified_meta.h" + +#include "plain_text.h" +#include "html.h" +#include "link.h" +#include "image.h" +#include "video.h" +#include "audio.h" +#include "folder.h" +#include "system_defined_appitem.h" +#include "system_defined_form.h" +#include "system_defined_pixelmap.h" +#include "application_defined_record.h" + +using namespace OHOS; +using namespace OHOS::UDMF; + +static UDMF::ValueType ParseANIRecordValueType(ani_env *env, const std::string type, ani_object unionValue) +{ + UnionAccessor unionAccessor(env, unionValue); + + double doubleValue = 0.0; + if (unionAccessor.TryConvert<double>(doubleValue)) { + return doubleValue; + } + + std::string stringValue; + if (unionAccessor.TryConvert<std::string>(stringValue)) { + return stringValue; + } + + bool boolValue = false; + if (unionAccessor.TryConvert<bool>(boolValue)) { + return boolValue; + } + + int intValue = 0; + if (unionAccessor.TryConvert<int>(intValue)) { + return intValue; + } + + std::vector<uint8_t> arrayVect; + if (unionAccessor.TryConvertArray<uint8_t>(arrayVect)) { + return arrayVect; + } + + if (!unionAccessor.IsInstanceOf("Lstd/core/Object;")) { + LOG_DEBUG(UDMF_KITS_NAPI, "ParseANIRecordValueType default std::monostate"); + return std::monostate(); + } + + if (type == "openharmony.pixel-map") { + auto pixelMap = Media::ImageAniUtils::GetPixelMapFromEnv(env, unionValue); + if (pixelMap == nullptr) { + return std::shared_ptr<Media::PixelMap>(nullptr); + } + std::shared_ptr<Media::PixelMap> pixelMapSpr(pixelMap); + return pixelMapSpr; + } else if (type == "openharmony.want") { + AAFwk::Want wantObj; + AppExecFwk::UnwrapWant(env, unionValue, wantObj); + return std::make_shared<AAFwk::Want>(wantObj); + } else { + return std::make_shared<Object>(); + } +} + +UnifiedRecordHolder::UnifiedRecordHolder(ani_env *env, const std::string type, ani_object unionValue) +{ + if (type.empty() && unionValue == nullptr) { + object_ = std::make_shared<UnifiedRecord>(); + return; + } + + UDType utdType = ENTITY; + if (UtdUtils::IsValidUtdId(type)) { + utdType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(type)); + } + + UDMF::ValueType value = ParseANIRecordValueType(env, type, unionValue); + + std::map<UDType, std::function<std::shared_ptr<UnifiedRecord>(UDType, ValueType)>> constructors = { + {TEXT, [](UDType type, ValueType value) { return std::make_shared<Text>(type, value); }}, + {PLAIN_TEXT, [](UDType type, ValueType value) { return std::make_shared<PlainText>(type, value); }}, + {HTML, [](UDType type, ValueType value) { return std::make_shared<Html>(type, value); }}, + {HYPERLINK, [](UDType type, ValueType value) { return std::make_shared<Link>(type, value); }}, + {UDType::FILE, [](UDType type, ValueType value) { return std::make_shared<File>(type, value); }}, + {IMAGE, [](UDType type, ValueType value) { return std::make_shared<Image>(type, value); }}, + {VIDEO, [](UDType type, ValueType value) { return std::make_shared<Video>(type, value); }}, + {AUDIO, [](UDType type, ValueType value) { return std::make_shared<Audio>(type, value); }}, + {FOLDER, [](UDType type, ValueType value) { return std::make_shared<Folder>(type, value); }}, + {SYSTEM_DEFINED_RECORD, [](UDType type, ValueType value) + { return std::make_shared<SystemDefinedRecord>(type, value); }}, + {SYSTEM_DEFINED_APP_ITEM, [](UDType type, ValueType value) + { return std::make_shared<SystemDefinedAppItem>(type, value); }}, + {SYSTEM_DEFINED_FORM, [](UDType type, ValueType value) + { return std::make_shared<SystemDefinedForm>(type, value); }}, + {SYSTEM_DEFINED_PIXEL_MAP, [](UDType type, ValueType value) + { return std::make_shared<SystemDefinedPixelMap>(type, value); }}, + {APPLICATION_DEFINED_RECORD, [](UDType type, ValueType value) + { return std::make_shared<ApplicationDefinedRecord>(type, value); }}, + }; + + auto constructor = constructors.find(utdType); + if (constructor == constructors.end()) { + object_ = std::make_shared<UnifiedRecord>(); + return; + } + + object_ = constructor->second(utdType, value); + if (utdType == APPLICATION_DEFINED_RECORD) { + std::shared_ptr<ApplicationDefinedRecord> applicationDefinedRecord = + std::static_pointer_cast<ApplicationDefinedRecord>(object_); + applicationDefinedRecord->SetApplicationDefinedType(type); + } +} + +const std::shared_ptr<UnifiedRecord> UnifiedRecordHolder::Get() +{ + if (object_ == nullptr) { + object_ = std::make_shared<UnifiedRecord>(); + } + return object_; +} + +void UnifiedRecordHolder::Set(ani_ref saveRemote) +{ + saveRemote_ = saveRemote; +} + +UnifiedRecordHolder::~UnifiedRecordHolder() +{ + LOG_DEBUG(UDMF_KITS_NAPI, "[ANI] enter UnifiedRecordHolder dtor "); +} + + +UnifiedDataHolder::UnifiedDataHolder(UnifiedRecordHolder* recordHolder) +{ + object_ = std::make_shared<UnifiedData>(); + + if (recordHolder != nullptr) { + auto recordPtr = recordHolder->Get(); + if (recordPtr != nullptr) { + object_->AddRecord(recordPtr); + } + } +} + +std::shared_ptr<UnifiedData> UnifiedDataHolder::Get() +{ + return object_; +} + +void UnifiedDataHolder::Set(ani_ref saveRemote) +{ + saveRemote_ = saveRemote; +} + +UnifiedDataHolder::~UnifiedDataHolder() +{ + LOG_DEBUG(UDMF_KITS_NAPI, "[ANI] enter UnifiedDataHolder dtor "); +} + +static void UnifiedRecodeValueTypeConstructor([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_string descriptor, ani_object unionValue) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "[ANI] enter UnifiedRecodeValueTypeConstructor"); + + ani_ref saveRemote = nullptr; + env->GlobalReference_Create(reinterpret_cast<ani_ref>(object), &saveRemote); + + auto type = AniStringUtils::ToStd(env, static_cast<ani_string>(descriptor)); + auto objectRemoteHolder = new UnifiedRecordHolder(env, type, unionValue); + objectRemoteHolder->Set(saveRemote); + AniObjectUtils::Wrap<UnifiedRecordHolder>(env, object, objectRemoteHolder); +} + +static void UnifiedRecodeConstructor([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "[ANI] enter UnifiedRecodeConstructor"); + if (env == nullptr) { + return; + } + ani_ref saveRemote = nullptr; + env->GlobalReference_Create(reinterpret_cast<ani_ref>(object), &saveRemote); + + auto objectRemoteHolder = new UnifiedRecordHolder(env, "", nullptr); + if (objectRemoteHolder == nullptr) { + return; + } + objectRemoteHolder->Set(saveRemote); + AniObjectUtils::Wrap<UnifiedRecordHolder>(env, object, objectRemoteHolder); +} + +static void UnifiedDataConstructor([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object, + ani_object recordObj) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "[ANI] enter UnifiedDataConstructor "); + auto recoderHolder = AniObjectUtils::Unwrap<UnifiedRecordHolder>(env, recordObj); + + ani_ref saveRemote = nullptr; + env->GlobalReference_Create(reinterpret_cast<ani_ref>(object), &saveRemote); + + auto objectHolder = new UnifiedDataHolder(recoderHolder); + objectHolder->Set(saveRemote); + AniObjectUtils::Wrap<UnifiedDataHolder>(env, object, objectHolder); +} + +static void initDataWithOutRecordConstructor([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object object) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "[ANI] enter initDataWithOutRecordConstructor"); + if (env == nullptr) { + return; + } + ani_ref saveRemote = nullptr; + env->GlobalReference_Create(reinterpret_cast<ani_ref>(object), &saveRemote); + + auto objectHolder = new UnifiedDataHolder(nullptr); + if (objectHolder == nullptr) { + return; + } + objectHolder->Set(saveRemote); + AniObjectUtils::Wrap<UnifiedDataHolder>(env, object, objectHolder); +} + +static ani_object UnifiedRecordToObject(ani_env *env, std::shared_ptr<UnifiedRecord> record) +{ + ani_object aniObject = nullptr; + + static const char *nameSpaceName = "L@ohos/data/unifiedDataChannel/unifiedDataChannel;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(nameSpaceName, &ns)) { + LOG_ERROR(UDMF_KITS_NAPI, "Not found namespace %{public}s", nameSpaceName); + return aniObject; + } + + static const char *recordclsName = "LUnifiedRecord;"; + ani_class aniClass; + if (ANI_OK != env->Namespace_FindClass(ns, recordclsName, &aniClass)) { + LOG_ERROR(UDMF_KITS_NAPI, "Not found class %{public}s", recordclsName); + return aniObject; + } + + ani_method personInfoCtor; + if (ANI_OK != env->Class_FindMethod(aniClass, "setNativePtr", nullptr, &personInfoCtor)) { + LOG_ERROR(UDMF_KITS_NAPI, "Not found func setNativePtr"); + return aniObject; + } + + if (ANI_OK != env->Object_New(aniClass, personInfoCtor, &aniObject, reinterpret_cast<ani_long>(record.get()))) { + LOG_ERROR(UDMF_KITS_NAPI, "Object_New Failed"); + return aniObject; + } + return aniObject; +} + +static ani_object GetRecords([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_object obj) +{ + ani_object arrayObj = nullptr; + ani_class arrayCls = nullptr; + if (ANI_OK != env->FindClass("Lescompat/Array;", &arrayCls)) { + LOG_ERROR(UDMF_KITS_NAPI, "FindClass Lescompat/Array; Failed"); + return arrayObj; + } + + ani_method arrayCtor; + if (ANI_OK != env->Class_FindMethod(arrayCls, "<ctor>", "I:V", &arrayCtor)) { + LOG_ERROR(UDMF_KITS_NAPI, "Class_FindMethod <ctor> Failed"); + return arrayObj; + } + + auto dataHolder = AniObjectUtils::Unwrap<UnifiedDataHolder>(env, obj); + if (dataHolder == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "UnifiedData unwrapp failed"); + return arrayObj; + } + + auto dataObj = dataHolder->Get(); + if (dataObj == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "dataHolder get empty..."); + return arrayObj; + } + + std::vector<std::shared_ptr<UnifiedRecord>> records = dataObj->GetRecords(); + if (ANI_OK != env->Object_New(arrayCls, arrayCtor, &arrayObj, records.size())) { + LOG_ERROR(UDMF_KITS_NAPI, "Object_New Array Faild"); + return arrayObj; + } + + ani_size index = 0; + for (const std::shared_ptr<UnifiedRecord> &recordPtr : records) { + auto aniRecord = UnifiedRecordToObject(env, recordPtr); + if (ANI_OK != env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, aniRecord)) { + LOG_ERROR(UDMF_KITS_NAPI, "Object_CallMethodByName_Void $_set Faild"); + break; + } + index++; + } + + LOG_DEBUG(UDMF_KITS_NAPI, "getRecords index:%{public}u", static_cast<uint32_t>(index)); + return arrayObj; +} + +static ani_status BindCleanerclassMethods(ani_env *env, ani_namespace &ns) +{ + auto cleanerCls = AniTypeFinder(env).FindClass(ns, "LCleaner;"); + return NativePtrCleaner(env).Bind(cleanerCls.value()); +} + +static ani_status LoadUnifiedRecord(ani_env *env, ani_namespace &ns) +{ + if (env == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "env is nullptr"); + return ANI_ERROR; + } + static const char *recordclsName = "LUnifiedRecord;"; + ani_class unifiedRecordClass; + if (ANI_OK != env->Namespace_FindClass(ns, recordclsName, &unifiedRecordClass)) { + LOG_ERROR(UDMF_KITS_NAPI, "Not found class %{public}s", recordclsName); + return ANI_NOT_FOUND; + } + + std::array methods = { + ani_native_function {"init", nullptr, reinterpret_cast<void *>(UnifiedRecodeValueTypeConstructor)}, + ani_native_function {"initRecordWithOutTypeValue", nullptr, reinterpret_cast<void *>(UnifiedRecodeConstructor)}, + }; + + if (ANI_OK != env->Class_BindNativeMethods(unifiedRecordClass, methods.data(), methods.size())) { + LOG_ERROR(UDMF_KITS_NAPI, "Cannot bind native methods to %{public}s", recordclsName); + return ANI_ERROR; + } + return ANI_OK; +} + +static ani_status LoadUnifiedData(ani_env *env, ani_namespace &ns) +{ + if (env == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "env is nullptr"); + return ANI_ERROR; + } + static const char *dataclsName = "LUnifiedData;"; + ani_class unifiedDataClass; + if (ANI_OK != env->Namespace_FindClass(ns, dataclsName, &unifiedDataClass)) { + LOG_ERROR(UDMF_KITS_NAPI, "Cannot find class %{public}s", dataclsName); + return ANI_NOT_FOUND; + } + + std::array datamethods = { + ani_native_function {"initData", nullptr, reinterpret_cast<void *>(UnifiedDataConstructor)}, + ani_native_function {"initDataWithOutRecord", nullptr, + reinterpret_cast<void *>(initDataWithOutRecordConstructor)}, + ani_native_function {"getRecords", nullptr, reinterpret_cast<void *>(GetRecords)}, + }; + + if (ANI_OK != env->Class_BindNativeMethods(unifiedDataClass, datamethods.data(), datamethods.size())) { + LOG_ERROR(UDMF_KITS_NAPI, "Cannot bind native methods to %{public}s", dataclsName); + return ANI_ERROR; + } + return ANI_OK; +} + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "ANI_Constructor start..."); + + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + LOG_ERROR(UDMF_KITS_NAPI, "[ANI] Unsupported ANI_VERSION_1"); + return ANI_ERROR; + } + + static const char *nameSpaceName = "L@ohos/data/unifiedDataChannel/unifiedDataChannel;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(nameSpaceName, &ns)) { + LOG_ERROR(UDMF_KITS_NAPI, "Not found namespace %{public}s", nameSpaceName); + return ANI_NOT_FOUND; + } + + if (ANI_OK != LoadUnifiedRecord(env, ns)) { + LOG_ERROR(UDMF_KITS_NAPI, "LoadUnifiedRecord ERROR"); + return ANI_NOT_FOUND; + } + + if (ANI_OK != LoadUnifiedData(env, ns)) { + LOG_ERROR(UDMF_KITS_NAPI, "LoadUnifiedData ERROR"); + return ANI_NOT_FOUND; + } + + if (result == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "param result is null"); + return ANI_ERROR; + } + + if (ANI_OK != BindCleanerclassMethods(env, ns)) { + LOG_ERROR(UDMF_KITS_NAPI, "[ANI] BindCleanerclassMethods failed"); + return ANI_ERROR; + } + *result = ANI_VERSION_1; + LOG_DEBUG(UDMF_KITS_NAPI, "ANI_Constructor end..."); + return ANI_OK; +} diff --git a/udmf/interfaces/ani/native/src/uniformTypeDescriptor_ani.cpp b/udmf/interfaces/ani/native/src/uniformTypeDescriptor_ani.cpp new file mode 100644 index 00000000..d819353b --- /dev/null +++ b/udmf/interfaces/ani/native/src/uniformTypeDescriptor_ani.cpp @@ -0,0 +1,135 @@ + /* + * 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. + */ + +#define LOG_TAG "UniformTypeDescriptorAni" + +#include "ani_utils.h" +#include "logger.h" +#include "error_code.h" +#include "utd_client.h" +#include <ani.h> + +using namespace OHOS::UDMF; + +static uint32_t paramsCheckError = 401; + +static void ThrowBusinessError(ani_env *env, int errCode, std::string&& errMsg) +{ + LOG_INFO(UDMF_KITS_NAPI, "Begin ThrowBusinessError."); + static const char *errorClsName = "L@ohos/base/BusinessError;"; + ani_class cls {}; + if (ANI_OK != env->FindClass(errorClsName, &cls)) { + LOG_ERROR(UDMF_KITS_NAPI, "find class BusinessError %{public}s failed", errorClsName); + return; + } + ani_method ctor; + if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", ":V", &ctor)) { + LOG_ERROR(UDMF_KITS_NAPI, "find method BusinessError.constructor failed"); + return; + } + ani_object errorObject; + if (ANI_OK != env->Object_New(cls, ctor, &errorObject)) { + LOG_ERROR(UDMF_KITS_NAPI, "create BusinessError object failed"); + return; + } + ani_double aniErrCode = static_cast<ani_double>(errCode); + ani_string errMsgStr; + if (ANI_OK != env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &errMsgStr)) { + LOG_ERROR(UDMF_KITS_NAPI, "convert errMsg to ani_string failed"); + return; + } + if (ANI_OK != env->Object_SetFieldByName_Double(errorObject, "code", aniErrCode)) { + LOG_ERROR(UDMF_KITS_NAPI, "set error code failed"); + return; + } + if (ANI_OK != env->Object_SetPropertyByName_Ref(errorObject, "message", errMsgStr)) { + LOG_ERROR(UDMF_KITS_NAPI, "set error message failed"); + return; + } + env->ThrowError(static_cast<ani_error>(errorObject)); + return; +} + +static ani_string GetUniformDataTypeByFilenameExtension(ani_env *env, ani_string filenameExtension, + ani_object belongsTo) +{ + LOG_INFO(UDMF_KITS_NAPI, "GetUniformDataTypeByFilenameExtension is called!"); + if (filenameExtension == nullptr) { + ThrowBusinessError(env, paramsCheckError, "ParserParam failed!"); + return nullptr; + } + std::string filenameExtension_ = AniStringUtils::ToStd(env, filenameExtension); + if (filenameExtension_.empty()) { + ThrowBusinessError(env, paramsCheckError, "ParserParam failed!"); + return nullptr; + } + ani_boolean isUndefined; + if (ANI_OK != env->Reference_IsUndefined(belongsTo, &isUndefined)) { + LOG_ERROR(UDMF_KITS_NAPI, "Object_GetFieldByName_Ref isRepeat failed."); + return nullptr; + } + std::string typeId; + auto status = E_OK; + if (isUndefined) { + status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension_, typeId); + } else { + std::string belongsTo_ = AniStringUtils::ToStd(env, static_cast<ani_string>(belongsTo)); + status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension_, typeId, belongsTo_); + } + + if (status != E_OK) { + LOG_ERROR(UDMF_KITS_NAPI, "invalid arguments!"); + return nullptr; + } + + if (!typeId.empty()) { + return AniStringUtils::ToAni(env, typeId); + } + return nullptr; +} + + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + LOG_ERROR(UDMF_KITS_NAPI, "Unsupported ANI_VERSION_1"); + return ANI_ERROR; + } + + static const char *nsName = "L@ohos/data/uniformTypeDescriptor/uniformTypeDescriptor;"; + ani_namespace ns; + if (ANI_OK != env->FindNamespace(nsName, &ns)) { + LOG_ERROR(UDMF_KITS_NAPI, "Not found %{public}s", nsName); + return ANI_ERROR; + } + + std::array methods = { + ani_native_function {"getUniformDataTypeByFilenameExtension", nullptr, + reinterpret_cast<void *>(GetUniformDataTypeByFilenameExtension) }, + }; + + if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) { + LOG_ERROR(UDMF_KITS_NAPI, "Cannot bind native methods to %{public}s", nsName); + return ANI_ERROR; + }; + + if (result == nullptr) { + LOG_ERROR(UDMF_KITS_NAPI, "param result is null"); + return ANI_ERROR; + } + *result = ANI_VERSION_1; + return ANI_OK; +} \ No newline at end of file diff --git a/udmf/interfaces/cj/BUILD.gn b/udmf/interfaces/cj/BUILD.gn index 5546b5b4..44e5b75c 100644 --- a/udmf/interfaces/cj/BUILD.gn +++ b/udmf/interfaces/cj/BUILD.gn @@ -40,6 +40,8 @@ ohos_shared_library("cj_unified_data_channel_ffi") { "${udmf_interfaces_path}/cj/src/unified_data_impl.cpp", "${udmf_interfaces_path}/cj/src/unified_record_ffi.cpp", "${udmf_interfaces_path}/cj/src/unified_record_impl.cpp", + "${udmf_interfaces_path}/cj/src/unified_data_channel_ffi.cpp", + "${udmf_interfaces_path}/cj/src/unified_data_parameter_parse.cpp", "${udmf_interfaces_path}/cj/src/utils.cpp", ] @@ -50,6 +52,7 @@ ohos_shared_library("cj_unified_data_channel_ffi") { "ability_base:want", "ability_runtime:abilitykit_native", "ability_runtime:napi_common", + "ability_runtime:napi_base_context", "c_utils:utils", "hilog:libhilog", "image_framework:cj_image_ffi", diff --git a/udmf/interfaces/cj/include/unified_data_ffi.h b/udmf/interfaces/cj/include/unified_data_ffi.h index 489fd8e7..cf178bc7 100644 --- a/udmf/interfaces/cj/include/unified_data_ffi.h +++ b/udmf/interfaces/cj/include/unified_data_ffi.h @@ -17,6 +17,7 @@ #define UDMF_UNIFIED_DATA_FFI_H #include <cstdint> + #include "ffi_remote_data.h" #include "cj_common_ffi.h" @@ -25,14 +26,16 @@ namespace OHOS { namespace UDMF { extern "C" { - FFI_EXPORT int64_t FfiUDMFUnifiedDataConstructor(); - FFI_EXPORT int64_t FfiUDMFUnifiedDataConstructorwWithRecord(int64_t unifiedRecordId); - FFI_EXPORT void FfiUDMFUnifiedDataAddRecord(int64_t unifiedDataId, int64_t unifiedRecordId); - FFI_EXPORT CArrUnifiedRecord FfiUDMFUnifiedDataGetRecords(int64_t unifiedDataId); - FFI_EXPORT bool FfiUDMFUnifiedDataHasType(int64_t unifiedDataId, const char *type); - FFI_EXPORT CArrString FfiUDMFUnifiedDataGetTypes(int64_t unifiedDataId); -} -} +FFI_EXPORT int64_t FfiUDMFUnifiedDataConstructor(); +FFI_EXPORT int64_t FfiUDMFUnifiedDataConstructorWithRecord(int64_t unifiedRecordId); +FFI_EXPORT void FfiUDMFUnifiedDataAddRecord(int64_t unifiedDataId, int64_t unifiedRecordId); +FFI_EXPORT CArrUnifiedRecord FfiUDMFUnifiedDataGetRecords(int64_t unifiedDataId); +FFI_EXPORT bool FfiUDMFUnifiedDataHasType(int64_t unifiedDataId, const char *type); +FFI_EXPORT CArrString FfiUDMFUnifiedDataGetTypes(int64_t unifiedDataId); +FFI_EXPORT CUnifiedDataProperties FfiUDMFGetProperties(int64_t unifiedDataId); +FFI_EXPORT void FfiUDMFSetProperties(int64_t unifiedDataId, CUnifiedDataProperties properties); } +} // namespace UDMF +} // namespace OHOS #endif \ No newline at end of file diff --git a/udmf/interfaces/cj/include/unified_data_impl.h b/udmf/interfaces/cj/include/unified_data_impl.h index 0ccd9434..ef073c3d 100644 --- a/udmf/interfaces/cj/include/unified_data_impl.h +++ b/udmf/interfaces/cj/include/unified_data_impl.h @@ -18,33 +18,51 @@ #include <memory> +#include "cj_common_ffi.h" #include "unified_data.h" #include "unified_record_impl.h" -#include "cj_common_ffi.h" namespace OHOS { namespace UDMF { - using namespace OHOS::UDMF; +using namespace OHOS::UDMF; + +typedef CArrI64 CArrUnifiedRecord; - typedef CArrI64 CArrUnifiedRecord; +struct CParameters { + int8_t valueType; + char *key; + void *value; + int64_t size; +}; - class CUnifiedData : public OHOS::FFI::FFIData { - DECL_TYPE(CUnifiedData, OHOS::FFI::FFIData) - public: - CUnifiedData(); - CUnifiedData(UDMF::CUnifiedRecord *record); +struct CArrParameters { + CParameters *head; + int64_t size; +}; - void AddRecord(UDMF::CUnifiedRecord *record); - CArrUnifiedRecord GetRecords(); - bool HasType(const char *type); - CArrString GetTypes(); +struct CUnifiedDataProperties { + CArrParameters extras; + char *tag; + int64_t timestamp; + int32_t shareOptions; +}; - private: - std::shared_ptr<UDMF::UnifiedData> unifiedData_; - std::vector<UDMF::CUnifiedRecord *> records_; - }; +class CUnifiedData : public OHOS::FFI::FFIData { + DECL_TYPE(CUnifiedData, OHOS::FFI::FFIData) +public: + CUnifiedData(); + CUnifiedData(sptr<UDMF::CUnifiedRecord> record); -} -} // namespace OHOS::UDMF + void AddRecord(sptr<UDMF::CUnifiedRecord> record); + CArrUnifiedRecord GetRecords(); + bool HasType(const char *type); + CArrString GetTypes(); + std::shared_ptr<UDMF::UnifiedData> unifiedData_; + +private: + std::vector<sptr<UDMF::CUnifiedRecord>> records_; +}; +} // namespace UDMF +} // namespace OHOS #endif \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_store_helper.h b/udmf/interfaces/cj/include/unified_data_parameter_parse.h similarity index 54% rename from relational_store/frameworks/js/napi/graphstore/include/napi_gdb_store_helper.h rename to udmf/interfaces/cj/include/unified_data_parameter_parse.h index 51902350..b5806bb4 100644 --- a/relational_store/frameworks/js/napi/graphstore/include/napi_gdb_store_helper.h +++ b/udmf/interfaces/cj/include/unified_data_parameter_parse.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 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,22 +13,18 @@ * limitations under the License. */ -#ifndef OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_DB_STORE_HELPER_H -#define OHOS_DISTRIBUTED_DATA_GDB_JS_NAPI_DB_STORE_HELPER_H +#ifndef UDMF_UNIFIED_DATA_PARAMETER_PARSE_H +#define UDMF_UNIFIED_DATA_PARAMETER_PARSE_H -#include <memory> -#include <string> -#include <vector> - -#include "napi/native_api.h" -#include "napi/native_common.h" -#include "napi/native_node_api.h" -#include "napi_gdb_error.h" - - -namespace OHOS::GraphStoreJsKit { -napi_value InitGdbHelper(napi_env env, napi_value exports); -} // namespace OHOS::GraphStoreJsKit +#include "unified_data_impl.h" +#include "want.h" +namespace OHOS { +namespace UDMF { +using WantParams = OHOS::AAFwk::WantParams; +void SetDataParameters(CArrParameters parameters, WantParams &wantP); +void ParseParameters(WantParams &wantP, CArrParameters &parameters, int32_t &code); +} // namespace UDMF +} // namespace OHOS #endif \ No newline at end of file diff --git a/udmf/interfaces/cj/include/unified_record_ffi.h b/udmf/interfaces/cj/include/unified_record_ffi.h index 11cdecd7..48bd3941 100644 --- a/udmf/interfaces/cj/include/unified_record_ffi.h +++ b/udmf/interfaces/cj/include/unified_record_ffi.h @@ -18,20 +18,46 @@ #include <cstdint> -#include "ffi_remote_data.h" #include "cj_common_ffi.h" - +#include "ffi_remote_data.h" #include "unified_record_impl.h" namespace OHOS { namespace UDMF { extern "C" { - FFI_EXPORT int64_t FfiUDMFUnifiedRecordConstructor(); - FFI_EXPORT int64_t FfiUDMFUnifiedRecordConstructorwithType(const char *type, CJValueType value); - FFI_EXPORT char *FfiUDMFUnifiedRecordGetType(int64_t unifiedId); - FFI_EXPORT CJValueType FfiUDMFUnifiedRecordGetValue(int64_t unifiedId); -} -} +FFI_EXPORT int64_t FfiUDMFUnifiedRecordConstructor(); +FFI_EXPORT int64_t FfiUDMFUnifiedRecordConstructorwithOnlyType(const char *type); +FFI_EXPORT int64_t FfiUDMFUnifiedRecordConstructorwithType(const char *type, CJValueType value); +FFI_EXPORT char *FfiUDMFUnifiedRecordGetType(int64_t unifiedId); +FFI_EXPORT CJValueType FfiUDMFUnifiedRecordGetValue(int64_t unifiedId); + +FFI_EXPORT int64_t FfiUDMFFileSetUri(int64_t id, const char *uri); +FFI_EXPORT char *FfiUDMFFileGetUri(int64_t id); +FFI_EXPORT CRecord FfiUDMFFileGetDetails(int64_t id); +FFI_EXPORT int64_t FfiUDMFFileSetDetails(int64_t id, CRecord record); + +FFI_EXPORT char *FfiUDMFImageGetImageUri(int64_t id); +FFI_EXPORT int64_t FfiUDMFImageSetImageUri(int64_t id, const char *uri); + +FFI_EXPORT char *FfiUDMFVideoGetVideoUri(int64_t id); +FFI_EXPORT int64_t FfiUDMFVideoSetVideoUri(int64_t id, const char *uri); + +FFI_EXPORT CRecord FfiUDMFTextGetDetails(int64_t id); +FFI_EXPORT int64_t FfiUDMFTextSetDetails(int64_t id, CRecord record); + +FFI_EXPORT char *FfiUDMFHyperLinkGetUrl(int64_t id); +FFI_EXPORT int64_t FfiUDMFHyperLinkSetUrl(int64_t id, const char *url); + +FFI_EXPORT char *FfiUDMFHyperLinkGetDescription(int64_t id); +FFI_EXPORT int64_t FfiUDMFHyperLinkSetDescription(int64_t id, const char *description); + +FFI_EXPORT char *FfiUDMFPlainTextGetTextContent(int64_t id); +FFI_EXPORT int64_t FfiUDMFPlainTextSetTextContent(int64_t id, const char *text); + +FFI_EXPORT char *FfiUDMFPlainTextGetAbstract(int64_t id); +FFI_EXPORT int64_t FfiUDMFPlainTextSetAbstract(int64_t id, const char *abstr); } +} // namespace UDMF +} // namespace OHOS #endif \ No newline at end of file diff --git a/udmf/interfaces/cj/include/unified_record_impl.h b/udmf/interfaces/cj/include/unified_record_impl.h index d2bb331a..d5c1a1f6 100644 --- a/udmf/interfaces/cj/include/unified_record_impl.h +++ b/udmf/interfaces/cj/include/unified_record_impl.h @@ -16,55 +16,85 @@ #ifndef UDMF_UNIFIED_RECORD_IMPL_H #define UDMF_UNIFIED_RECORD_IMPL_H -#include "unified_record.h" #include "cj_common_ffi.h" +#include "ffi_remote_data.h" +#include "unified_record.h" namespace OHOS { namespace UDMF { - using namespace OHOS::UDMF; +struct CRecord { + CArrString keys; + CArrString values; +}; - struct CJValueType { - int32_t integer32; - int64_t integer64; - double dou; - bool boolean; - char *string; - CArrUI8 byteArray; - int64_t pixelMapId; - - uint8_t tag; - }; - - enum TypeSymbol { - INTEGER32 = 0, - INTEGER64 = 1, - DOUBLE = 2, - BOOLEAN = 3, - STRING = 4, - BYTEARRAY = 5, - PIXELMAP = 6, - NULLTAG = 7, - UNDEFINED = 8 - }; - - class CUnifiedRecord : public OHOS::FFI::FFIData { - DECL_TYPE(CUnifiedRecord, OHOS::FFI::FFIData) - public: - CUnifiedRecord(); - CUnifiedRecord(const char *type, CJValueType value); - CJValueType ValueType2CJValueType(ValueType value); - ValueType CJValueType2ValueType(CJValueType value); - char *GetType(); - CJValueType GetValue(); - - const std::shared_ptr<UDMF::UnifiedRecord> &GetUnifiedRecord() const; - - private: - std::shared_ptr<UDMF::UnifiedRecord> unifiedRecord_; - int64_t pixelMapId_ = 0; - }; - -} -} // namespace OHOS::UDMF +struct CJValueType { + int32_t integer32; + int64_t integer64; + double dou; + bool boolean; + char *string; + CArrUI8 byteArray; + int64_t pixelMapId; + uint8_t tag; +}; + +enum TypeSymbol { + INTEGER32 = 0, + INTEGER64 = 1, + DOUBLE = 2, + BOOLEAN = 3, + STRING = 4, + BYTEARRAY = 5, + PIXELMAP = 6, + NULLTAG = 7, + UNDEFINED = 8 +}; + +class CUnifiedRecord : public OHOS::FFI::FFIData { + DECL_TYPE(CUnifiedRecord, OHOS::FFI::FFIData) +public: + CUnifiedRecord(); + CUnifiedRecord(const char *type); + CUnifiedRecord(const char *type, CJValueType value); + CJValueType ValueType2CJValueType(ValueType value); + ValueType CJValueType2ValueType(CJValueType value); + char *GetType(); + CJValueType GetValue(); + + const std::shared_ptr<UDMF::UnifiedRecord> &GetUnifiedRecord() const; + + char *GetFileUri(); + void SetFileUri(const char *uri); + CRecord GetFileDetails(); + void SetFileDetails(const std::map<std::string, std::string> &details); + + char *GetImageUri(); + void SetImageUri(const char *uri); + + char *GetVideoUri(); + void SetVideoUri(const char *uri); + + CRecord GetTextDetails(); + void SetTextDetails(const std::map<std::string, std::string> &details); + + char *GetHyperLinkUrl(); + void SetHyperLinkUrl(const char *url); + + char *GetHyperLinkDescription(); + void SetHyperLinkDescription(const char *description); + + char *GetPlainTextContent(); + void SetPlainTextContent(const char *text); + + char *GetPlainTextAbstract(); + void SetPlainTextAbstract(const char *abstr); +private: + std::shared_ptr<UDMF::UnifiedRecord> unifiedRecord_; + int64_t pixelMapId_ = 0; +}; + +char *CreateCStringFromString(const std::string &source); +} // namespace UDMF +} // namespace OHOS #endif \ No newline at end of file diff --git a/udmf/interfaces/cj/include/utils.h b/udmf/interfaces/cj/include/utils.h index 727d426e..798293ad 100644 --- a/udmf/interfaces/cj/include/utils.h +++ b/udmf/interfaces/cj/include/utils.h @@ -28,5 +28,6 @@ class FFI_EXPORT Utils { public: static char *MallocCString(const std::string &origin); static CArrString StringVectorToArray(std::vector<std::string> vector); + static void FreeCArrString(CArrString &arrStr); }; #endif // OHOS_UDMF_UTILS_H \ No newline at end of file diff --git a/udmf/interfaces/cj/src/unified_data_channel_ffi.cpp b/udmf/interfaces/cj/src/unified_data_channel_ffi.cpp new file mode 100644 index 00000000..b7372df7 --- /dev/null +++ b/udmf/interfaces/cj/src/unified_data_channel_ffi.cpp @@ -0,0 +1,174 @@ +/* + * 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 "cj_common_ffi.h" +#include "udmf_client.h" +#include "udmf_log.h" +#include "unified_data.h" +#include "unified_data_impl.h" +#include "unified_meta.h" +#include "unified_record_impl.h" +#include "utils.h" + +using namespace OHOS::FFI; +using namespace OHOS::UDMF; + +using ErrCode = int; + +namespace OHOS { +namespace UDMF { +extern "C" { + +FFI_EXPORT char *FfiUDMFInsertData(const char *intention, int64_t unifiedDataId, int32_t *errCode) +{ + *errCode = E_INVALID_PARAMETERS; + std::string key; + auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); + if (data == nullptr || data->unifiedData_ == nullptr) { + LOGE("Get unified data failed!"); + return nullptr; + } + Intention it = UnifiedDataUtils::GetIntentionByString(intention); + if (it == UD_INTENTION_DRAG) { + LOGE("Parameter error: The intention parameter is invalid"); + return nullptr; + } + CustomOption option = { .intention = it }; + auto status = UdmfClient::GetInstance().SetData(option, *(data->unifiedData_), key); + *errCode = status; + if (status != E_OK) { + LOGE("Insert data failed!"); + } + return Utils::MallocCString(key); +} + +FFI_EXPORT int32_t FfiUDMFUpdateData(const char *key, int64_t unifiedDataId) +{ + auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); + if (data == nullptr || data->unifiedData_ == nullptr) { + LOGE("Get unified data failed!"); + return E_INVALID_PARAMETERS; + } + UnifiedKey verifyKey(key); + if (!verifyKey.IsValid()) { + LOGE("Parameter error: parameter key is invalid"); + return E_INVALID_PARAMETERS; + } + QueryOption option = { .key = key }; + auto status = UdmfClient::GetInstance().UpdateData(option, *(data->unifiedData_)); + if (status != E_OK) { + LOGE("Update unified data failed!"); + } + return status; +} + +FFI_EXPORT CArrI64 FfiUDMFQueryData(const char *intention, const char *key, int32_t *errCode) +{ + *errCode = E_INVALID_PARAMETERS; + CArrI64 queryData = { .head = nullptr, .size = 0 }; + Intention it = UnifiedDataUtils::GetIntentionByString(intention); + if (it == UD_INTENTION_DRAG) { + LOGE("Parameter error: the intention parameter is invalid"); + return queryData; + } + QueryOption option = { .key = key, .intention = it }; + std::vector<UnifiedData> unifiedDataSet; + auto status = UdmfClient::GetInstance().GetBatchData(option, unifiedDataSet); + *errCode = status; + if (status != E_OK) { + LOGE("Query unified data failed!"); + return queryData; + } + auto arr = static_cast<int64_t*>(malloc(sizeof(int64_t) * unifiedDataSet.size())); + if (arr == nullptr) { + LOGE("malloc error in queryData"); + return queryData; + } + for (uint64_t i = 0; i < unifiedDataSet.size(); i++) { + std::shared_ptr<UnifiedData> unifiedDataItem = std::make_shared<UnifiedData>(); + auto cUnifiedData = FFIData::Create<CUnifiedData>(); + if (unifiedDataItem == nullptr || cUnifiedData == nullptr) { + LOGE("Create unifiedData failed. Instance is null."); + free(arr); + arr = nullptr; + return queryData; + } + unifiedDataItem->SetRecords(unifiedDataSet[i].GetRecords()); + unifiedDataItem->SetProperties(unifiedDataSet[i].GetProperties()); + cUnifiedData->unifiedData_ = unifiedDataItem; + arr[i] = cUnifiedData->GetID(); + } + queryData.head = arr; + queryData.size = static_cast<int64_t>(unifiedDataSet.size()); + return queryData; +} + +FFI_EXPORT CArrI64 FfiUDMFDeleteData(const char *intention, const char *key, int32_t *errCode) +{ + *errCode = E_INVALID_PARAMETERS; + CArrI64 deleteData = { .head = nullptr, .size = 0 }; + Intention it = UnifiedDataUtils::GetIntentionByString(intention); + if (it == UD_INTENTION_DRAG) { + LOGE("Parameter error: the intention parameter is invalid"); + return deleteData; + } + QueryOption option = { .key = key, .intention = it }; + std::vector<UnifiedData> unifiedDataSet; + auto status = UdmfClient::GetInstance().DeleteData(option, unifiedDataSet); + *errCode = status; + if (status != E_OK) { + LOGE("Query unified data failed!"); + return deleteData; + } + auto arr = static_cast<int64_t*>(malloc(sizeof(int64_t) * unifiedDataSet.size())); + if (arr == nullptr) { + LOGE("malloc error in deleteData"); + return deleteData; + } + for (uint64_t i = 0; i < unifiedDataSet.size(); i++) { + std::shared_ptr<UnifiedData> unifiedDataItem = std::make_shared<UnifiedData>(); + auto cUnifiedData = FFIData::Create<CUnifiedData>(); + if (unifiedDataItem == nullptr || cUnifiedData == nullptr) { + LOGE("Create unifiedData failed. Instance is null."); + free(arr); + arr = nullptr; + return deleteData; + } + unifiedDataItem->SetRecords(unifiedDataSet[i].GetRecords()); + unifiedDataItem->SetProperties(unifiedDataSet[i].GetProperties()); + cUnifiedData->unifiedData_ = unifiedDataItem; + arr[i] = cUnifiedData->GetID(); + } + deleteData.head = arr; + deleteData.size = static_cast<int64_t>(unifiedDataSet.size()); + return deleteData; +} + +FFI_EXPORT void FfiUDMFFreeStringData(char *str) +{ + free(str); +} + +FFI_EXPORT void FfiUDMFFreeArrI64Data(CArrI64* ptr) +{ + if (ptr == nullptr || ptr->head == nullptr) { + return; + } + free(ptr->head); + ptr->head = nullptr; +} +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/interfaces/cj/src/unified_data_ffi.cpp b/udmf/interfaces/cj/src/unified_data_ffi.cpp index 6cf4c519..bcb4381f 100644 --- a/udmf/interfaces/cj/src/unified_data_ffi.cpp +++ b/udmf/interfaces/cj/src/unified_data_ffi.cpp @@ -14,11 +14,16 @@ * limitations under the License. */ +#include "securec.h" + #include "unified_data_ffi.h" #include "unified_data_impl.h" #include "unified_record_impl.h" +#include "unified_data_parameter_parse.h" #include "cj_common_ffi.h" +#include "utils.h" + using namespace OHOS::FFI; using namespace OHOS::UDMF; @@ -26,73 +31,130 @@ namespace OHOS { namespace UDMF { extern "C" { - int64_t FfiUDMFUnifiedDataConstructor() - { - auto nativeCJUnifiedData = FFIData::Create<CUnifiedData>(); - if (nativeCJUnifiedData == nullptr) { - return -1; - } - return nativeCJUnifiedData->GetID(); +int64_t FfiUDMFUnifiedDataConstructor() +{ + auto nativeCJUnifiedData = FFIData::Create<CUnifiedData>(); + if (nativeCJUnifiedData == nullptr) { + return -1; + } + return nativeCJUnifiedData->GetID(); +} + +int64_t FfiUDMFUnifiedDataConstructorWithRecord(int64_t unifiedRecordId) +{ + auto record = FFIData::GetData<CUnifiedRecord>(unifiedRecordId); + if (record == nullptr) { + return -1; } - int64_t FfiUDMFUnifiedDataConstructorWithRecord(int64_t unifiedRecordId) - { - auto record = FFIData::GetData<CUnifiedRecord>(unifiedRecordId); - if (record == nullptr) { - return -1; - } - - auto nativeCJUnifiedData = FFIData::Create<CUnifiedData>(record); - if (nativeCJUnifiedData == nullptr) { - return -1; - } - return nativeCJUnifiedData->GetID(); + auto nativeCJUnifiedData = FFIData::Create<CUnifiedData>(record); + if (nativeCJUnifiedData == nullptr) { + return -1; } + return nativeCJUnifiedData->GetID(); +} + +void FfiUDMFUnifiedDataAddRecord(int64_t unifiedDataId, int64_t unifiedRecordId) +{ + auto record = FFIData::GetData<CUnifiedRecord>(unifiedRecordId); + if (record == nullptr) { + return; + } + + auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); + if (data == nullptr) { + return; + } + + data->AddRecord(record); +} - void FfiUDMFUnifiedDataAddRecord(int64_t unifiedDataId, int64_t unifiedRecordId) - { - auto record = FFIData::GetData<CUnifiedRecord>(unifiedRecordId); - if (record == nullptr) { - return; - } +CArrUnifiedRecord FfiUDMFUnifiedDataGetRecords(int64_t unifiedDataId) +{ + auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); + if (data == nullptr) { + return CArrUnifiedRecord {}; + } - auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); - if (data == nullptr) { - return; - } + return data->GetRecords(); +} - data->AddRecord(record); +bool FfiUDMFUnifiedDataHasType(int64_t unifiedDataId, const char *type) +{ + auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); + if (data == nullptr) { + return false; } - CArrUnifiedRecord FfiUDMFUnifiedDataGetRecords(int64_t unifiedDataId) - { - auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); - if (data == nullptr) { - return CArrUnifiedRecord{}; - } + return data->HasType(type); +} - return data->GetRecords(); +CArrString FfiUDMFUnifiedDataGetTypes(int64_t unifiedDataId) +{ + auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); + if (data == nullptr) { + return CArrString {}; } - bool FfiUDMFUnifiedDataHasType(int64_t unifiedDataId, const char *type) - { - auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); - if (data == nullptr) { - return false; - } + return data->GetTypes(); +} - return data->HasType(type); +CUnifiedDataProperties FfiUDMFGetProperties(int64_t unifiedDataId) +{ + auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); + CUnifiedDataProperties ret = { .extras = {}, .tag = nullptr, .timestamp = 0, .shareOptions = 1 }; + if (data == nullptr) { + return ret; + } + std::shared_ptr<UDMF::UnifiedDataProperties> uni = data->unifiedData_->GetProperties(); + int32_t code = NO_ERROR; + ParseParameters(uni->extras, ret.extras, code); + if (code != NO_ERROR) { + return ret; } + ret.tag = Utils::MallocCString(uni->tag); + ret.timestamp = uni->timestamp; + // In arkts initial enum value is not public ,so use public initial value CROSS_APP. + if (uni->shareOptions == IN_APP || uni->shareOptions == CROSS_APP) { + ret.shareOptions = uni->shareOptions; + } + return ret; +} - CArrString FfiUDMFUnifiedDataGetTypes(int64_t unifiedDataId) - { - auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); - if (data == nullptr) { - return CArrString{}; - } +void FfiUDMFSetProperties(int64_t unifiedDataId, CUnifiedDataProperties properties) +{ + auto data = FFIData::GetData<CUnifiedData>(unifiedDataId); + if (data == nullptr) { + return; + } + auto prop = data->unifiedData_->GetProperties(); + AAFwk::WantParams wantP; + SetDataParameters(properties.extras, wantP); + prop->extras = wantP; + prop->tag = Utils::MallocCString(properties.tag); + prop->shareOptions = UDMF::ShareOptions(properties.shareOptions); + data->unifiedData_->SetProperties(prop); +} - return data->GetTypes(); +FFI_EXPORT void FfiUDMFFreeDataProperties(CUnifiedDataProperties *properties) +{ + CParameters *p = properties->extras.head; + for (int64_t i = 0; i < properties->extras.size; i++) { + free(p[i].key); + free(p[i].value); + p[i].key = nullptr; + p[i].value = nullptr; } + free(p); + free(properties->tag); + p = nullptr; + properties->tag = nullptr; } + +FFI_EXPORT void FfiUDMFFreeCArrString(CArrString *arrStr) +{ + Utils::FreeCArrString(*arrStr); } } +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/interfaces/cj/src/unified_data_impl.cpp b/udmf/interfaces/cj/src/unified_data_impl.cpp index 47ebd4db..a4e7e416 100644 --- a/udmf/interfaces/cj/src/unified_data_impl.cpp +++ b/udmf/interfaces/cj/src/unified_data_impl.cpp @@ -14,10 +14,8 @@ * limitations under the License. */ -#include "unified_data_ffi.h" #include "unified_data_impl.h" -#include "unified_record_impl.h" -#include "cj_common_ffi.h" + #include <cstdlib> #include <string> #include <variant> @@ -25,7 +23,11 @@ #include <map> #include <iomanip> +#include "cj_common_ffi.h" #include "ffi_remote_data.h" +#include "unified_data_ffi.h" +#include "unified_record_impl.h" +#include "utils.h" #include "application_defined_record_napi.h" #include "audio_napi.h" @@ -46,93 +48,90 @@ #include "unified_record_napi.h" #include "video_napi.h" -#include "utils.h" - using namespace OHOS::FFI; using namespace OHOS::UDMF; namespace OHOS { namespace UDMF { - CUnifiedData::CUnifiedData() - { - unifiedData_ = std::make_shared<UnifiedData>(); - } +CUnifiedData::CUnifiedData() +{ + unifiedData_ = std::make_shared<UnifiedData>(); +} - CUnifiedData::CUnifiedData(UDMF::CUnifiedRecord *record) - { - unifiedData_ = std::make_shared<UnifiedData>(); +CUnifiedData::CUnifiedData(sptr<UDMF::CUnifiedRecord> record) +{ + unifiedData_ = std::make_shared<UnifiedData>(); - if (record == nullptr) { - return; - } - unifiedData_->AddRecord(record->GetUnifiedRecord()); - this->records_.push_back(record); + if (record == nullptr) { + return; } + unifiedData_->AddRecord(record->GetUnifiedRecord()); + this->records_.push_back(record); +} - void CUnifiedData::AddRecord(UDMF::CUnifiedRecord *record) - { - if (record == nullptr) { - return; - } - this->records_.push_back(record); - unifiedData_->AddRecord(record->GetUnifiedRecord()); +void CUnifiedData::AddRecord(sptr<UDMF::CUnifiedRecord> record) +{ + if (record == nullptr) { + return; } + this->records_.push_back(record); + unifiedData_->AddRecord(record->GetUnifiedRecord()); +} - static CArrUnifiedRecord VectorToArray(std::vector<int64_t> vector) - { - if (vector.size() == 0) { - return CArrUnifiedRecord{}; - } - int64_t *head = static_cast<int64_t *>(malloc(vector.size() * sizeof(int64_t))); - if (head == nullptr) { - return CArrUnifiedRecord{}; - } - for (unsigned long i = 0; i < vector.size(); i++) { - head[i] = vector[i]; - } - CArrUnifiedRecord int64Array = {head, vector.size()}; - return int64Array; +static CArrUnifiedRecord VectorToArray(std::vector<int64_t> vector) +{ + if (vector.size() == 0) { + return CArrUnifiedRecord {}; } - - CArrUnifiedRecord CUnifiedData::GetRecords() - { - std::vector<int64_t> recordIds; - for (auto record : this->records_) { - if (record == nullptr) { - break; - } - recordIds.push_back(record->GetID()); - } - return VectorToArray(recordIds); + int64_t *head = static_cast<int64_t*>(malloc(vector.size() * sizeof(int64_t))); + if (head == nullptr) { + return CArrUnifiedRecord {}; } - - bool CUnifiedData::HasType(const char *type) - { - return unifiedData_->HasType(type); + for (size_t i = 0; i < vector.size(); i++) { + head[i] = vector[i]; } + CArrUnifiedRecord int64Array = {head, vector.size()}; + return int64Array; +} - static CArrString StringVectorToArray(std::vector<std::string> vector) - { - if (vector.size() == 0) { - return CArrString{}; - } - char **head = static_cast<char **>(malloc(vector.size() * sizeof(char *))); - if (head == nullptr) { - return CArrString{}; - } - for (unsigned long i = 0; i < vector.size(); i++) { - head[i] = Utils::MallocCString(vector[i]); +CArrUnifiedRecord CUnifiedData::GetRecords() +{ + std::vector<int64_t> recordIds; + for (auto record : this->records_) { + if (record == nullptr) { + break; } - CArrString stringArray = {head, vector.size()}; - return stringArray; + recordIds.push_back(record->GetID()); } + return VectorToArray(recordIds); +} - CArrString CUnifiedData::GetTypes() - { - std::vector<std::string> types = unifiedData_->GetTypesLabels(); - return StringVectorToArray(types); - } +bool CUnifiedData::HasType(const char *type) +{ + return unifiedData_->HasType(type); +} +static CArrString StringVectorToArray(std::vector<std::string> vector) +{ + if (vector.size() == 0) { + return CArrString {}; + } + char **head = static_cast<char**>(malloc(vector.size() * sizeof(char*))); + if (head == nullptr) { + return CArrString {}; + } + for (unsigned long i = 0; i < vector.size(); i++) { + head[i] = Utils::MallocCString(vector[i]); + } + CArrString stringArray = {head, vector.size()}; + return stringArray; } + +CArrString CUnifiedData::GetTypes() +{ + std::vector<std::string> types = unifiedData_->GetTypesLabels(); + return StringVectorToArray(types); } +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/interfaces/cj/src/unified_data_parameter_parse.cpp b/udmf/interfaces/cj/src/unified_data_parameter_parse.cpp new file mode 100644 index 00000000..6e98df09 --- /dev/null +++ b/udmf/interfaces/cj/src/unified_data_parameter_parse.cpp @@ -0,0 +1,234 @@ +/* + * 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 "unified_data_parameter_parse.h" + +#include <cinttypes> + +#include "array_wrapper.h" +#include "bool_wrapper.h" +#include "byte_wrapper.h" +#include "double_wrapper.h" +#include "int_wrapper.h" +#include "long_wrapper.h" +#include "string_wrapper.h" +#include "udmf_log.h" +#include "utils.h" +#include "want_params_wrapper.h" + +namespace OHOS { +namespace UDMF { + +const int8_t I32_TYPE = 0; +const int8_t I64_TYPE = 1; +const int8_t DOUBLE_TYPE = 2; +const int8_t BOOL_TYPE = 3; +const int8_t STR_TYPE = 4; +const int8_t UINT8_ARRAY_TYPE = 5; + +constexpr int32_t NO_ERROR = 0; +constexpr int32_t ERR_UDMF_FAILED = -1; +constexpr int32_t ERR_NO_MEMORY = -2; + +const int32_t NONE_VALUE = 1; +using WantParams = OHOS::AAFwk::WantParams; + +void ClearParametersPtr(CParameters **ptr, int count, bool isKey) +{ + CParameters *p = *ptr; + for (int i = 0; i < count; i++) { + free(p[i].key); + free(p[i].value); + p[i].key = nullptr; + p[i].value = nullptr; + } + if (!isKey) { + free(p[count].key); + p[count].key = nullptr; + } + free(*ptr); + *ptr = nullptr; +} + +// WantParameters -> CArrParameters +int32_t InnerWrapWantParamsString(WantParams &wantParams, CParameters *p) +{ + auto value = wantParams.GetParam(p->key); + AAFwk::IString *ao = AAFwk::IString::Query(value); + if (ao == nullptr) { + LOGE("No value"); + return NONE_VALUE; + } + std::string natValue = OHOS::AAFwk::String::Unbox(ao); + p->value = Utils::MallocCString(natValue); + p->size = static_cast<int64_t>(natValue.length()) + 1; + p->valueType = STR_TYPE; + return NO_ERROR; +} + +template <class TBase, class T, class NativeT> +int32_t InnerWrapWantParamsT(WantParams &wantParams, CParameters *p) +{ + auto value = wantParams.GetParam(p->key); + TBase *ao = TBase::Query(value); + if (ao == nullptr) { + LOGE("No value"); + return NONE_VALUE; + } + NativeT natValue = T::Unbox(ao); + NativeT *ptr = static_cast<NativeT*>(malloc(sizeof(NativeT))); + if (ptr == nullptr) { + return ERR_NO_MEMORY; + } + *ptr = natValue; + p->value = static_cast<void*>(ptr); + p->size = sizeof(NativeT); + return NO_ERROR; +} + +template <class TBase, class T, class NativeT> +int32_t InnerWrapWantParamsArrayT(sptr<AAFwk::IArray> &ao, CParameters*p) +{ + long size = 0; + if (ao->GetLength(size) != ERR_OK) { + LOGE("fail to get length"); + return ERR_UDMF_FAILED; + } + if (size == 0) { + return ERR_UDMF_FAILED; + } + NativeT *arrP = static_cast<NativeT*>(malloc(sizeof(NativeT) * size)); + if (arrP == nullptr) { + LOGE("fail to malloc"); + return ERR_NO_MEMORY; + } + for (long i = 0; i < size; i++) { + sptr<AAFwk::IInterface> iface = nullptr; + if (ao->Get(i, iface) == ERR_OK) { + TBase *iValue = TBase::Query(iface); + if (iValue != nullptr) { + arrP[i] = T::Unbox(iValue); + } + } + } + p->size = size; + p->value = static_cast<void*>(arrP); + return NO_ERROR; +} + +bool InnerSetWantParamsArrayByte(const std::string &key, const std::vector<uint8_t> &value, + AAFwk::WantParams &wantParams) +{ + size_t size = value.size(); + sptr<AAFwk::IArray> ao = new (std::nothrow) AAFwk::Array(size, AAFwk::g_IID_IByte); + if (ao != nullptr) { + for (size_t i = 0; i < size; i++) { + ao->Set(i, AAFwk::Integer::Box(value[i])); + } + wantParams.SetParam(key, ao); + return true; + } else { + return false; + } +} + +int32_t InnerWrapWantParamsArray(WantParams &wantParams, sptr<AAFwk::IArray> &ao, CParameters *p) +{ + LOGI("%{public}s called, key=%{public}s", __func__, p->key); + if (AAFwk::Array::IsByteArray(ao)) { + p->valueType = UINT8_ARRAY_TYPE; + return InnerWrapWantParamsArrayT<AAFwk::IByte, AAFwk::Byte, uint8_t>(ao, p); + } + return ERR_UDMF_FAILED; +} + +void SetDataParameters(CArrParameters parameters, WantParams &wantP) +{ + for (int i = 0; i < parameters.size; i++) { + auto head = parameters.head + i; + auto key = std::string(head->key); + if (head->valueType == I32_TYPE) { + wantP.SetParam(key, OHOS::AAFwk::Integer::Box(*static_cast<int32_t*>(head->value))); + } else if (head->valueType == I64_TYPE) { + wantP.SetParam(key, OHOS::AAFwk::Integer::Box(*static_cast<int64_t*>(head->value))); + } else if (head->valueType == DOUBLE_TYPE) { + wantP.SetParam(key, OHOS::AAFwk::Double::Box(*static_cast<double*>(head->value))); + } else if (head->valueType == STR_TYPE) { + wantP.SetParam(key, OHOS::AAFwk::String::Box(std::string(static_cast<char*>(head->value)))); + } else if (head->valueType == BOOL_TYPE) { + wantP.SetParam(key, OHOS::AAFwk::Boolean::Box(*static_cast<bool*>(head->value))); + } else if (head->valueType == UINT8_ARRAY_TYPE) { + uint8_t *intArr = static_cast<uint8_t*>(head->value); + std::vector<uint8_t> intVec(intArr, intArr + head->size); + InnerSetWantParamsArrayByte(key, intVec, wantP); + } else { + LOGE("wrong type!"); + } + } +} + +void ParseParameters(WantParams &wantP, CArrParameters &parameters, int32_t &code) +{ + if (code != NO_ERROR) { + return; + } + std::map<std::string, sptr<OHOS::AAFwk::IInterface>> paramsMap = wantP.GetParams(); + int count = 0; + auto size = static_cast<int64_t>(paramsMap.size()); + if (size == 0) { + return; + } + parameters.head = static_cast<CParameters*>(malloc(sizeof(CParameters) * size)); + if (parameters.head == nullptr) { + code = ERR_NO_MEMORY; + return; + } + parameters.size = size; + for (auto iter = paramsMap.begin(); iter != paramsMap.end(); iter++) { + auto ptr = parameters.head + count; + ptr->key = Utils::MallocCString(iter->first); + if (ptr->key == nullptr) { + code = ERR_NO_MEMORY; + return ClearParametersPtr(&parameters.head, count, true); + } + ptr->value = nullptr; + ptr->size = 0; + if (AAFwk::IString::Query(iter->second) != nullptr) { + code = InnerWrapWantParamsString(wantP, ptr); + } else if (AAFwk::IBoolean::Query(iter->second) != nullptr) { + ptr->valueType = BOOL_TYPE; + code = InnerWrapWantParamsT<AAFwk::IBoolean, AAFwk::Boolean, bool>(wantP, ptr); + } else if (AAFwk::IInteger::Query(iter->second) != nullptr) { + ptr->valueType = I32_TYPE; + code = InnerWrapWantParamsT<AAFwk::IInteger, AAFwk::Integer, int>(wantP, ptr); + } else if (AAFwk::ILong::Query(iter->second) != nullptr) { + ptr->valueType = I64_TYPE; + code = InnerWrapWantParamsT<AAFwk::ILong, AAFwk::Long, long>(wantP, ptr); + } else if (AAFwk::IDouble::Query(iter->second) != nullptr) { + ptr->valueType = DOUBLE_TYPE; + code = InnerWrapWantParamsT<AAFwk::IDouble, AAFwk::Double, double>(wantP, ptr); + } else if (AAFwk::IArray::Query(iter->second) != nullptr) { + AAFwk::IArray *ao = AAFwk::IArray::Query(iter->second); + sptr<AAFwk::IArray> array(ao); + code = InnerWrapWantParamsArray(wantP, array, ptr); + } + if (code == ERR_NO_MEMORY || code == ERR_UDMF_FAILED) { + return ClearParametersPtr(&parameters.head, count, false); + } + count++; + } +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/interfaces/cj/src/unified_record_ffi.cpp b/udmf/interfaces/cj/src/unified_record_ffi.cpp index c2ab6baa..19dc3cac 100644 --- a/udmf/interfaces/cj/src/unified_record_ffi.cpp +++ b/udmf/interfaces/cj/src/unified_record_ffi.cpp @@ -15,50 +15,298 @@ */ #include "unified_record_ffi.h" + +#include "udmf_log.h" #include "unified_record_impl.h" +#include "utils.h" using namespace OHOS::FFI; using namespace OHOS::UDMF; namespace OHOS { namespace UDMF { +constexpr int64_t NO_ERROR = 0; +constexpr int64_t ERR_INIT_FAILED = -1; + extern "C" { +int64_t FfiUDMFUnifiedRecordConstructor() +{ + auto nativeCJUnifiedRecord = FFIData::Create<CUnifiedRecord>(); + if (nativeCJUnifiedRecord == nullptr) { + return -1; + } + return nativeCJUnifiedRecord->GetID(); +} + +int64_t FfiUDMFUnifiedRecordConstructorwithOnlyType(const char *type) +{ + auto nativeCJUnifiedRecord = FFIData::Create<CUnifiedRecord>(type); + if (nativeCJUnifiedRecord == nullptr) { + return -1; + } + return nativeCJUnifiedRecord->GetID(); +} + +int64_t FfiUDMFUnifiedRecordConstructorwithType(const char *type, CJValueType value) +{ + auto nativeCJUnifiedRecord = FFIData::Create<CUnifiedRecord>(type, value); + if (nativeCJUnifiedRecord == nullptr) { + return -1; + } + return nativeCJUnifiedRecord->GetID(); +} + +char *FfiUDMFUnifiedRecordGetType(int64_t unifiedId) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(unifiedId); + if (instance == nullptr) { + return nullptr; + } + return instance->GetType(); +} + +CJValueType FfiUDMFUnifiedRecordGetValue(int64_t unifiedId) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(unifiedId); + if (instance == nullptr) { + return CJValueType {}; + } + return instance->GetValue(); +} + +char *FfiUDMFFileGetUri(int64_t id) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return nullptr; + } + return instance->GetFileUri(); +} + +int64_t FfiUDMFFileSetUri(int64_t id, const char *uri) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; + } + instance->SetFileUri(uri); + return NO_ERROR; +} + +CRecord FfiUDMFFileGetDetails(int64_t id) +{ + CRecord ret = { .keys = { .head = nullptr, .size = 0 }, .values = { .head = nullptr, .size = 0 } }; + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ret; + } + return instance->GetFileDetails(); +} + +int64_t FfiUDMFFileSetDetails(int64_t id, CRecord record) +{ + if (record.keys.size != record.values.size) { + LOGE("Param error. The number of key and value mismatch."); + return ERR_INIT_FAILED; + } + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; + } + std::map<std::string, std::string> details; + for (int64_t i = 0; i < record.keys.size; i++) { + std::string key{record.keys.head[i]}; + std::string value{record.values.head[i]}; + details[key] = value; + } + instance->SetFileDetails(details); + return NO_ERROR; +} + +char *FfiUDMFImageGetImageUri(int64_t id) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return nullptr; + } + return instance->GetImageUri(); +} + +int64_t FfiUDMFImageSetImageUri(int64_t id, const char *uri) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; + } + instance->SetImageUri(uri); + return NO_ERROR; +} + +char *FfiUDMFVideoGetVideoUri(int64_t id) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return nullptr; + } + return instance->GetVideoUri(); +} + +int64_t FfiUDMFVideoSetVideoUri(int64_t id, const char *uri) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; + } + instance->SetVideoUri(uri); + return NO_ERROR; +} + +CRecord FfiUDMFTextGetDetails(int64_t id) +{ + CRecord ret = { .keys = { .head = nullptr, .size = 0 }, .values = { .head = nullptr, .size = 0 } }; + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ret; + } + return instance->GetTextDetails(); +} - int64_t FfiUDMFUnifiedRecordConstructor() - { - auto nativeCJUnifiedRecord = FFIData::Create<CUnifiedRecord>(); - if (nativeCJUnifiedRecord == nullptr) { - return -1; - } - return nativeCJUnifiedRecord->GetID(); +int64_t FfiUDMFTextSetDetails(int64_t id, CRecord record) +{ + if (record.keys.size != record.values.size) { + LOGE("Param error. The number of key and value mismatch."); + return ERR_INIT_FAILED; + } + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; + } + std::map<std::string, std::string> details; + for (int64_t i = 0; i < record.keys.size; i++) { + std::string key{record.keys.head[i]}; + std::string value{record.values.head[i]}; + details[key] = value; } + instance->SetTextDetails(details); + return NO_ERROR; +} - int64_t FfiUDMFUnifiedRecordConstructorwithType(const char *type, CJValueType value) - { - auto nativeCJUnifiedRecord = FFIData::Create<CUnifiedRecord>(type, value); - if (nativeCJUnifiedRecord == nullptr) { - return -1; - } - return nativeCJUnifiedRecord->GetID(); +char *FfiUDMFHyperLinkGetUrl(int64_t id) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return nullptr; } + return instance->GetHyperLinkUrl(); +} - char *FfiUDMFUnifiedRecordGetType(int64_t unifiedId) - { - auto instance = FFIData::GetData<CUnifiedRecord>(unifiedId); - if (instance == nullptr) { - return nullptr; - } - return instance->GetType(); +int64_t FfiUDMFHyperLinkSetUrl(int64_t id, const char *url) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; } + instance->SetHyperLinkUrl(url); + return NO_ERROR; +} + +char *FfiUDMFHyperLinkGetDescription(int64_t id) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return nullptr; + } + return instance->GetHyperLinkDescription(); +} - CJValueType FfiUDMFUnifiedRecordGetValue(int64_t unifiedId) - { - auto instance = FFIData::GetData<CUnifiedRecord>(unifiedId); - if (instance == nullptr) { - return CJValueType{}; - } - return instance->GetValue(); +int64_t FfiUDMFHyperLinkSetDescription(int64_t id, const char *description) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; } + instance->SetHyperLinkDescription(description); + return NO_ERROR; } + +char *FfiUDMFPlainTextGetTextContent(int64_t id) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return nullptr; + } + return instance->GetPlainTextContent(); +} + +int64_t FfiUDMFPlainTextSetTextContent(int64_t id, const char *text) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; + } + instance->SetPlainTextContent(text); + return NO_ERROR; +} + +char *FfiUDMFPlainTextGetAbstract(int64_t id) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return nullptr; + } + return instance->GetPlainTextAbstract(); +} + +int64_t FfiUDMFPlainTextSetAbstract(int64_t id, const char *abstr) +{ + auto instance = FFIData::GetData<CUnifiedRecord>(id); + if (instance == nullptr) { + LOGE("Get unifiedRecord failed. Instance is null."); + return ERR_INIT_FAILED; + } + instance->SetPlainTextAbstract(abstr); + return NO_ERROR; +} + +FFI_EXPORT void FfiUDMFFreeCjValueType(CJValueType *val) +{ + if (val->string != nullptr) { + free(val->string); + val->string = nullptr; + } + if (val->byteArray.head != nullptr) { + free(val->byteArray.head); + val->byteArray.head = nullptr; + val->byteArray.size = 0; + } +} + +FFI_EXPORT void FfiUDMFFreeCRecord(CRecord *record) +{ + Utils::FreeCArrString(record->keys); + Utils::FreeCArrString(record->values); + record->keys.head = nullptr; + record->keys.size = 0; + record->values.head = nullptr; + record->values.size = 0; } } +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/interfaces/cj/src/unified_record_impl.cpp b/udmf/interfaces/cj/src/unified_record_impl.cpp index 3bdbe41e..743277ca 100644 --- a/udmf/interfaces/cj/src/unified_record_impl.cpp +++ b/udmf/interfaces/cj/src/unified_record_impl.cpp @@ -14,203 +14,435 @@ * limitations under the License. */ -#include "unified_record_ffi.h" #include "unified_record_impl.h" #include <cstdlib> +#include <iomanip> +#include <map> #include <string> #include <variant> #include <vector> -#include <map> -#include <iomanip> + #include "ffi_remote_data.h" +#include "securec.h" +#include "unified_record_ffi.h" -#include "plain_text.h" +#include "application_defined_record.h" +#include "audio.h" +#include "folder.h" #include "html.h" -#include "link.h" #include "image.h" +#include "link.h" #include "pixel_map_impl.h" #include "pixel_map.h" - -#include "video.h" -#include "audio.h" -#include "folder.h" +#include "plain_text.h" #include "system_defined_appitem.h" #include "system_defined_form.h" #include "system_defined_pixelmap.h" -#include "application_defined_record.h" #include "utils.h" +#include "video.h" using namespace OHOS::FFI; using namespace OHOS::UDMF; namespace OHOS { namespace UDMF { - static CArrUI8 VectorToByteArray(std::vector<uint8_t> bytes) - { - if (bytes.size() == 0) { - return CArrUI8{}; - } - uint8_t *head = static_cast<uint8_t *>(malloc(bytes.size() * sizeof(uint8_t))); - if (head == nullptr) { - return CArrUI8{}; - } - for (unsigned long i = 0; i < bytes.size(); i++) { - head[i] = bytes[i]; - } - CArrUI8 byteArray = {head, bytes.size()}; - return byteArray; - } - - CJValueType CUnifiedRecord::ValueType2CJValueType(ValueType value) - { - CJValueType cjvalue; - if (std::holds_alternative<std::monostate>(value)) { - cjvalue.tag = UNDEFINED; - } else if (std::holds_alternative<nullptr_t>(value)) { - cjvalue.tag = NULLTAG; - } else if (auto p = std::get_if<int32_t>(&value)) { - cjvalue.integer32 = *p; - cjvalue.tag = INTEGER32; - } else if (auto p = std::get_if<int64_t>(&value)) { - cjvalue.integer64 = *p; - cjvalue.tag = INTEGER64; - } else if (auto p = std::get_if<double>(&value)) { - cjvalue.dou = *p; - cjvalue.tag = DOUBLE; - } else if (auto p = std::get_if<bool>(&value)) { - cjvalue.boolean = *p; - cjvalue.tag = BOOLEAN; - } else if (auto p = std::get_if<std::string>(&value)) { - cjvalue.string = Utils::MallocCString(*p); - cjvalue.tag = STRING; - } else if (auto p = std::get_if<std::vector<uint8_t>>(&value)) { - cjvalue.byteArray = VectorToByteArray(*p); - cjvalue.tag = BYTEARRAY; - } else if (auto p = std::get_if<std::shared_ptr<OHOS::Media::PixelMap>>(&value)) { - cjvalue.pixelMapId = this->pixelMapId_; - cjvalue.tag = PIXELMAP; - } +static CArrUI8 VectorToByteArray(std::vector<uint8_t> bytes) +{ + if (bytes.size() == 0) { + return CArrUI8 {}; + } + uint8_t *head = static_cast<uint8_t*>(malloc(bytes.size() * sizeof(uint8_t))); + if (head == nullptr) { + return CArrUI8 {}; + } + for (size_t i = 0; i < bytes.size(); i++) { + head[i] = bytes[i]; + } + CArrUI8 byteArray = {head, bytes.size()}; + return byteArray; +} - return cjvalue; +CJValueType CUnifiedRecord::ValueType2CJValueType(ValueType value) +{ + CJValueType cjvalue; + if (std::holds_alternative<std::monostate>(value)) { + cjvalue.tag = UNDEFINED; + } else if (std::holds_alternative<nullptr_t>(value)) { + cjvalue.tag = NULLTAG; + } else if (auto p = std::get_if<int32_t>(&value)) { + cjvalue.integer32 = *p; + cjvalue.tag = INTEGER32; + } else if (auto p = std::get_if<int64_t>(&value)) { + cjvalue.integer64 = *p; + cjvalue.tag = INTEGER64; + } else if (auto p = std::get_if<double>(&value)) { + cjvalue.dou = *p; + cjvalue.tag = DOUBLE; + } else if (auto p = std::get_if<bool>(&value)) { + cjvalue.boolean = *p; + cjvalue.tag = BOOLEAN; + } else if (auto p = std::get_if<std::string>(&value)) { + cjvalue.string = Utils::MallocCString(*p); + cjvalue.tag = STRING; + } else if (auto p = std::get_if<std::vector<uint8_t>>(&value)) { + cjvalue.byteArray = VectorToByteArray(*p); + cjvalue.tag = BYTEARRAY; + } else if (auto p = std::get_if<std::shared_ptr<OHOS::Media::PixelMap>>(&value)) { + cjvalue.pixelMapId = this->pixelMapId_; + cjvalue.tag = PIXELMAP; } - ValueType CUnifiedRecord::CJValueType2ValueType(CJValueType cjvalue) - { - ValueType value; - switch (cjvalue.tag) { - case INTEGER32: - value = cjvalue.integer32; - break; - case INTEGER64: - value = cjvalue.integer64; - break; - case DOUBLE: - value = cjvalue.dou; - break; - case BOOLEAN: - value = cjvalue.boolean; - break; - case STRING: - value = cjvalue.string; - break; - case BYTEARRAY: { - std::vector<uint8_t> bytes = std::vector<uint8_t>(); - for (int64_t i = 0; i < cjvalue.byteArray.size; i++) { - bytes.push_back(cjvalue.byteArray.head[i]); - } - value = bytes; - break; - } + return cjvalue; +} - case PIXELMAP: { - auto instance = FFIData::GetData<OHOS::Media::PixelMapImpl>(cjvalue.pixelMapId); - if (instance == nullptr) { - value = -1; - break; - } - value = instance->GetRealPixelMap(); - break; +ValueType CUnifiedRecord::CJValueType2ValueType(CJValueType cjvalue) +{ + ValueType value; + switch (cjvalue.tag) { + case INTEGER32: + value = cjvalue.integer32; + break; + case INTEGER64: + value = cjvalue.integer64; + break; + case DOUBLE: + value = cjvalue.dou; + break; + case BOOLEAN: + value = cjvalue.boolean; + break; + case STRING: + value = cjvalue.string; + break; + case BYTEARRAY: { + std::vector<uint8_t> bytes = std::vector<uint8_t>(); + for (int64_t i = 0; i < cjvalue.byteArray.size; i++) { + bytes.push_back(cjvalue.byteArray.head[i]); } + value = bytes; + break; + } - case NULLTAG: { - value = nullptr; + case PIXELMAP: { + auto instance = FFIData::GetData<OHOS::Media::PixelMapImpl>(cjvalue.pixelMapId); + if (instance == nullptr) { + value = -1; break; } + value = instance->GetRealPixelMap(); + break; + } - case UNDEFINED: { - value = std::monostate(); - break; - } - - default: - value = -1; - break; + case NULLTAG: { + value = nullptr; + break; } - return value; + case UNDEFINED: { + value = std::monostate(); + break; + } + + default: + value = -1; + break; } - CUnifiedRecord::CUnifiedRecord() - { - unifiedRecord_ = std::make_shared<UnifiedRecord>(); + return value; +} + +CUnifiedRecord::CUnifiedRecord() +{ + unifiedRecord_ = std::make_shared<UnifiedRecord>(); +} + +CUnifiedRecord::CUnifiedRecord(const char *type) +{ + UDType utdType = APPLICATION_DEFINED_RECORD; + if (UtdUtils::IsValidUtdId(type)) { + utdType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(type)); + } + static const std::map<UDType, std::function<std::shared_ptr<UnifiedRecord>()>> constructors = { + {TEXT, []() { return std::make_shared<Text>(); }}, + {PLAIN_TEXT, []() { return std::make_shared<PlainText>(); }}, + {HTML, []() { return std::make_shared<Html>(); }}, + {HYPERLINK, []() { return std::make_shared<Link>(); }}, + {FILE, []() { return std::make_shared<File>(); }}, + {IMAGE, []() { return std::make_shared<Image>(); }}, + {VIDEO, []() { return std::make_shared<Video>(); }}, + {AUDIO, []() { return std::make_shared<Audio>(); }}, + {FOLDER, []() { return std::make_shared<Folder>(); }}, + {SYSTEM_DEFINED_RECORD, []() + { return std::make_shared<SystemDefinedRecord>(); }}, + {SYSTEM_DEFINED_APP_ITEM, []() + { return std::make_shared<SystemDefinedAppItem>(); }}, + {SYSTEM_DEFINED_FORM, []() + { return std::make_shared<SystemDefinedForm>(); }}, + {SYSTEM_DEFINED_PIXEL_MAP, []() + { return std::make_shared<SystemDefinedPixelMap>(); }}, + {APPLICATION_DEFINED_RECORD, []() + { return std::make_shared<ApplicationDefinedRecord>(); }}, + }; + auto constructor = constructors.find(utdType); + if (constructor == constructors.end()) { + unifiedRecord_ = std::make_shared<UnifiedRecord>(utdType); + return; } + unifiedRecord_ = constructor->second(); +} - CUnifiedRecord::CUnifiedRecord(const char *type, CJValueType cjvalue) - { - UDType utdType = APPLICATION_DEFINED_RECORD; - if (UtdUtils::IsValidUtdId(type)) { - utdType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(type)); - } - ValueType value = CJValueType2ValueType(cjvalue); - if (cjvalue.tag == PIXELMAP) { - this->pixelMapId_ = cjvalue.pixelMapId; - } - std::map<UDType, std::function<std::shared_ptr<UnifiedRecord>(UDType, ValueType)>> constructors = { - {TEXT, [](UDType type, ValueType value) { return std::make_shared<Text>(type, value); }}, - {PLAIN_TEXT, [](UDType type, ValueType value) { return std::make_shared<PlainText>(type, value); }}, - {HTML, [](UDType type, ValueType value) { return std::make_shared<Html>(type, value); }}, - {HYPERLINK, [](UDType type, ValueType value) { return std::make_shared<Link>(type, value); }}, - {FILE, [](UDType type, ValueType value) { return std::make_shared<File>(type, value); }}, - {IMAGE, [](UDType type, ValueType value) { return std::make_shared<Image>(type, value); }}, - {VIDEO, [](UDType type, ValueType value) { return std::make_shared<Video>(type, value); }}, - {AUDIO, [](UDType type, ValueType value) { return std::make_shared<Audio>(type, value); }}, - {FOLDER, [](UDType type, ValueType value) { return std::make_shared<Folder>(type, value); }}, - {SYSTEM_DEFINED_RECORD, [](UDType type, ValueType value) - { return std::make_shared<SystemDefinedRecord>(type, value); }}, - {SYSTEM_DEFINED_APP_ITEM, [](UDType type, ValueType value) - { return std::make_shared<SystemDefinedAppItem>(type, value); }}, - {SYSTEM_DEFINED_FORM, [](UDType type, ValueType value) - { return std::make_shared<SystemDefinedForm>(type, value); }}, - {SYSTEM_DEFINED_PIXEL_MAP, [](UDType type, ValueType value) - { return std::make_shared<SystemDefinedPixelMap>(type, value); }}, - {APPLICATION_DEFINED_RECORD, [](UDType type, ValueType value) - { return std::make_shared<ApplicationDefinedRecord>(type, value); }}, - }; - auto constructor = constructors.find(utdType); - if (constructor == constructors.end()) { - unifiedRecord_ = std::make_shared<UnifiedRecord>(utdType, value); - return; +CUnifiedRecord::CUnifiedRecord(const char *type, CJValueType cjvalue) +{ + UDType utdType = APPLICATION_DEFINED_RECORD; + if (UtdUtils::IsValidUtdId(type)) { + utdType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(type)); + } + ValueType value = CJValueType2ValueType(cjvalue); + if (cjvalue.tag == PIXELMAP) { + this->pixelMapId_ = cjvalue.pixelMapId; + } + static const std::map<UDType, std::function<std::shared_ptr<UnifiedRecord>(UDType, ValueType)>> constructors = { + {TEXT, [](UDType type, ValueType value) { return std::make_shared<Text>(type, value); }}, + {PLAIN_TEXT, [](UDType type, ValueType value) { return std::make_shared<PlainText>(type, value); }}, + {HTML, [](UDType type, ValueType value) { return std::make_shared<Html>(type, value); }}, + {HYPERLINK, [](UDType type, ValueType value) { return std::make_shared<Link>(type, value); }}, + {FILE, [](UDType type, ValueType value) { return std::make_shared<File>(type, value); }}, + {IMAGE, [](UDType type, ValueType value) { return std::make_shared<Image>(type, value); }}, + {VIDEO, [](UDType type, ValueType value) { return std::make_shared<Video>(type, value); }}, + {AUDIO, [](UDType type, ValueType value) { return std::make_shared<Audio>(type, value); }}, + {FOLDER, [](UDType type, ValueType value) { return std::make_shared<Folder>(type, value); }}, + {SYSTEM_DEFINED_RECORD, [](UDType type, ValueType value) + { return std::make_shared<SystemDefinedRecord>(type, value); }}, + {SYSTEM_DEFINED_APP_ITEM, [](UDType type, ValueType value) + { return std::make_shared<SystemDefinedAppItem>(type, value); }}, + {SYSTEM_DEFINED_FORM, [](UDType type, ValueType value) + { return std::make_shared<SystemDefinedForm>(type, value); }}, + {SYSTEM_DEFINED_PIXEL_MAP, [](UDType type, ValueType value) + { return std::make_shared<SystemDefinedPixelMap>(type, value); }}, + {APPLICATION_DEFINED_RECORD, [](UDType type, ValueType value) + { return std::make_shared<ApplicationDefinedRecord>(type, value); }}, + }; + auto constructor = constructors.find(utdType); + if (constructor == constructors.end()) { + unifiedRecord_ = std::make_shared<UnifiedRecord>(utdType, value); + return; + } + unifiedRecord_ = constructor->second(utdType, value); +} + +char *CUnifiedRecord::GetType() +{ + std::string ret = UtdUtils::GetUtdIdFromUtdEnum(this->unifiedRecord_->GetType()); + return Utils::MallocCString(ret); +} + +CJValueType CUnifiedRecord::GetValue() +{ + ValueType value = this->unifiedRecord_->GetValue(); + CJValueType cjvalue = ValueType2CJValueType(value); + return cjvalue; +} + +const std::shared_ptr<UDMF::UnifiedRecord> &CUnifiedRecord::GetUnifiedRecord() const +{ + return unifiedRecord_; +} + +char *CUnifiedRecord::GetFileUri() +{ + std::shared_ptr<UDMF::File> resFile = std::reinterpret_pointer_cast<UDMF::File>(this->unifiedRecord_); + std::string res = resFile->GetUri(); + return Utils::MallocCString(res); +} + +void CUnifiedRecord::SetFileUri(const char *uri) +{ + std::shared_ptr<UDMF::File> resFile = std::reinterpret_pointer_cast<UDMF::File>(this->unifiedRecord_); + resFile->SetUri(uri); +} + +CRecord CUnifiedRecord::GetFileDetails() +{ + CRecord ret = { .keys = { .head = nullptr, .size = 0 }, .values = { .head = nullptr, .size = 0 } }; + std::shared_ptr<UDMF::File> resFile = std::reinterpret_pointer_cast<UDMF::File>(this->unifiedRecord_); + OHOS::UDMF::UDDetails resDetails = resFile->GetDetails(); + std::map<std::string, std::string> params; + for (auto it : resDetails) { + if (std::holds_alternative<std::string>(it.second)) { + const std::string &strValue = std::get<std::string>(it.second); + params.emplace(it.first, strValue); } - unifiedRecord_ = constructor->second(utdType, value); } + char **keysHead = static_cast<char**>(malloc(sizeof(char*) * params.size())); + if (keysHead == nullptr) { + return ret; + } + char **valuesHead = static_cast<char**>(malloc(sizeof(char*) * params.size())); + if (valuesHead == nullptr) { + free(keysHead); + return ret; + } + int64_t i = 0; + for (auto &param : params) { + keysHead[i] = CreateCStringFromString(param.first); + valuesHead[i] = CreateCStringFromString(param.second); + i++; + } + ret.keys.size = static_cast<int64_t>(params.size()); + ret.keys.head = keysHead; + ret.values.size = static_cast<int64_t>(params.size()); + ret.values.head = valuesHead; + return ret; +} - char *CUnifiedRecord::GetType() - { - std::string ret = UtdUtils::GetUtdIdFromUtdEnum(this->unifiedRecord_->GetType()); - return Utils::MallocCString(ret); +void CUnifiedRecord::SetFileDetails(const std::map<std::string, std::string> &details) +{ + std::shared_ptr<UDMF::File> resFile = std::reinterpret_pointer_cast<UDMF::File>(this->unifiedRecord_); + OHOS::UDMF::UDDetails udDetails; + for (auto &param : details) { + udDetails[param.first] = param.second; } + resFile->SetDetails(udDetails); +} - CJValueType CUnifiedRecord::GetValue() - { - ValueType value = this->unifiedRecord_->GetValue(); - CJValueType cjvalue = ValueType2CJValueType(value); - return cjvalue; +char *CUnifiedRecord::GetImageUri() +{ + std::shared_ptr<UDMF::Image> resImage = std::reinterpret_pointer_cast<UDMF::Image>(this->unifiedRecord_); + std::string res = resImage->GetUri(); + return Utils::MallocCString(res); +} + +void CUnifiedRecord::SetImageUri(const char *uri) +{ + std::shared_ptr<UDMF::Image> resImage = std::reinterpret_pointer_cast<UDMF::Image>(this->unifiedRecord_); + resImage->SetUri(uri); +} + +char *CUnifiedRecord::GetVideoUri() +{ + std::shared_ptr<UDMF::Video> resVideo = std::reinterpret_pointer_cast<UDMF::Video>(this->unifiedRecord_); + std::string res = resVideo->GetUri(); + return Utils::MallocCString(res); +} + +void CUnifiedRecord::SetVideoUri(const char *uri) +{ + std::shared_ptr<UDMF::Video> resVideo = std::reinterpret_pointer_cast<UDMF::Video>(this->unifiedRecord_); + resVideo->SetUri(uri); +} + +CRecord CUnifiedRecord::GetTextDetails() +{ + CRecord ret = { .keys = { .head = nullptr, .size = 0 }, .values = { .head = nullptr, .size = 0 } }; + std::shared_ptr<UDMF::Text> resText = std::reinterpret_pointer_cast<UDMF::Text>(this->unifiedRecord_); + OHOS::UDMF::UDDetails resDetails = resText->GetDetails(); + std::map<std::string, std::string> params; + for (auto it : resDetails) { + if (std::holds_alternative<std::string>(it.second)) { + const std::string &strValue = std::get<std::string>(it.second); + params.emplace(it.first, strValue); + } + } + char **keysHead = static_cast<char**>(malloc(sizeof(char*) * params.size())); + if (keysHead == nullptr) { + return ret; + } + char **valuesHead = static_cast<char**>(malloc(sizeof(char*) * params.size())); + if (valuesHead == nullptr) { + free(keysHead); + return ret; } + int64_t i = 0; + for (auto &param : params) { + keysHead[i] = CreateCStringFromString(param.first); + valuesHead[i] = CreateCStringFromString(param.second); + i++; + } + ret.keys.size = static_cast<int64_t>(params.size()); + ret.keys.head = keysHead; + ret.values.size = static_cast<int64_t>(params.size()); + ret.values.head = valuesHead; + return ret; +} - const std::shared_ptr<UDMF::UnifiedRecord> &CUnifiedRecord::GetUnifiedRecord() const - { - return unifiedRecord_; +void CUnifiedRecord::SetTextDetails(const std::map<std::string, std::string> &details) +{ + std::shared_ptr<UDMF::Text> resText = std::reinterpret_pointer_cast<UDMF::Text>(this->unifiedRecord_); + OHOS::UDMF::UDDetails udDetails; + for (auto &param : details) { + udDetails[param.first] = param.second; } + resText->SetDetails(udDetails); +} + +char *CUnifiedRecord::GetHyperLinkUrl() +{ + std::shared_ptr<UDMF::Link> resLink = std::reinterpret_pointer_cast<UDMF::Link>(this->unifiedRecord_); + std::string res = resLink->GetUrl(); + return Utils::MallocCString(res); +} + +void CUnifiedRecord::SetHyperLinkUrl(const char *url) +{ + std::shared_ptr<UDMF::Link> resLink = std::reinterpret_pointer_cast<UDMF::Link>(this->unifiedRecord_); + resLink->SetUrl(url); +} + +char *CUnifiedRecord::GetHyperLinkDescription() +{ + std::shared_ptr<UDMF::Link> resLink = std::reinterpret_pointer_cast<UDMF::Link>(this->unifiedRecord_); + std::string res = resLink->GetDescription(); + return Utils::MallocCString(res); +} + +void CUnifiedRecord::SetHyperLinkDescription(const char *description) +{ + std::shared_ptr<UDMF::Link> resLink = std::reinterpret_pointer_cast<UDMF::Link>(this->unifiedRecord_); + resLink->SetDescription(description); +} + +char *CUnifiedRecord::GetPlainTextContent() +{ + std::shared_ptr<UDMF::PlainText> resText = std::reinterpret_pointer_cast<UDMF::PlainText>(this->unifiedRecord_); + std::string res = resText->GetContent(); + return Utils::MallocCString(res); +} + +void CUnifiedRecord::SetPlainTextContent(const char *text) +{ + std::shared_ptr<UDMF::PlainText> resText = std::reinterpret_pointer_cast<UDMF::PlainText>(this->unifiedRecord_); + resText->SetContent(text); +} + +char *CUnifiedRecord::GetPlainTextAbstract() +{ + std::shared_ptr<UDMF::PlainText> resText = std::reinterpret_pointer_cast<UDMF::PlainText>(this->unifiedRecord_); + std::string res = resText->GetAbstract(); + return Utils::MallocCString(res); } + +void CUnifiedRecord::SetPlainTextAbstract(const char *abstr) +{ + std::shared_ptr<UDMF::PlainText> resText = std::reinterpret_pointer_cast<UDMF::PlainText>(this->unifiedRecord_); + resText->SetAbstract(abstr); +} + +char *CreateCStringFromString(const std::string &source) +{ + if (source.size() == 0) { + return nullptr; + } + size_t length = source.size() + 1; + auto res = static_cast<char*>(malloc(length)); + if (res == nullptr) { + return nullptr; + } + if (strcpy_s(res, length, source.c_str()) != 0) { + free(res); + return nullptr; + } + return res; } +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/interfaces/cj/src/utils.cpp b/udmf/interfaces/cj/src/utils.cpp index ce763896..06df669f 100644 --- a/udmf/interfaces/cj/src/utils.cpp +++ b/udmf/interfaces/cj/src/utils.cpp @@ -15,13 +15,13 @@ #include "utils.h" -char* Utils::MallocCString(const std::string& origin) +char *Utils::MallocCString(const std::string &origin) { if (origin.empty()) { return nullptr; } auto len = origin.length() + 1; - char* res = static_cast<char*>(malloc(sizeof(char) * len)); + char *res = static_cast<char*>(malloc(sizeof(char) * len)); if (res == nullptr) { return nullptr; } @@ -31,15 +31,28 @@ char* Utils::MallocCString(const std::string& origin) CArrString Utils::StringVectorToArray(std::vector<std::string> vector) { if (vector.size() == 0) { - return CArrString{}; + return CArrString {}; } - char **head = static_cast<char **>(malloc(vector.size() * sizeof(char *))); + char **head = static_cast<char**>(malloc(vector.size() * sizeof(char *))); if (head == nullptr) { - return CArrString{}; + return CArrString {}; } for (unsigned long i = 0; i < vector.size(); i++) { head[i] = Utils::MallocCString(vector[i]); } - CArrString stringArray = {head, vector.size()}; + CArrString stringArray = { head, vector.size() }; return stringArray; +} + +void Utils::FreeCArrString(CArrString &arrStr) +{ + if (arrStr.head == nullptr) { + return; + } + for (int64_t i = 0; i < arrStr.size; i++) { + free(arrStr.head[i]); + arrStr.head[i] = nullptr; + } + free(arrStr.head); + arrStr.head = nullptr; } \ No newline at end of file diff --git a/udmf/interfaces/components/UdmfComponents.js b/udmf/interfaces/components/UdmfComponents.js index 7fddb8e2..0e241124 100644 --- a/udmf/interfaces/components/UdmfComponents.js +++ b/udmf/interfaces/components/UdmfComponents.js @@ -18,8 +18,7 @@ if (!("finalizeConstruction" in ViewPU.prototype)) { } let image = requireNapi('multimedia.image'); -let j = requireNapi('i18n'); -let display = requireNapi('display'); +let i = requireNapi('i18n'); export var FormType; (function (FormType) { @@ -33,8 +32,8 @@ var TextType; TextType[TextType["DESCRIPTION"] = 1] = "DESCRIPTION"; TextType[TextType["APP_NAME"] = 2] = "APP_NAME"; })(TextType || (TextType = {})); -const m = 'udmf.ContentFormCard'; -const o = +const j = 'udmf.ContentFormCard'; +const m = '82,73,70,70,60,3,0,0,87,69,66,80,86,80,56,32,48,3,0,0,144,67,0,157,1,42,36,2,76,1,62,145,72,161,76,37,164,163,34,3' + '4,151,40,24,176,18,9,105,110,225,117,81,27,243,141,167,87,231,251,1,151,228,76,129,74,56,124,143,240,134,221,17,24' + '5,145,49,195,251,155,103,15,145,254,16,219,162,62,178,38,56,127,115,108,225,242,63,194,27,116,71,214,68,199,15,238' + @@ -61,21 +60,22 @@ const o = '38,70,81,93,158,178,96,58,63,135,99,61,33,123,114,106,17,205,205,245,73,209,248,208,230,67,84,83,67,62,174,199,125' + ',7,42,68,205,119,254,54,95,35,146,246,87,229,105,194,49,134,23,113,205,13,105,146,10,231,32,0,26,210,69,47,127,104' + ',73,141,205,245,214,23,231,110,132,188,27,13,88,8,43,145,225,60,68,0,42,15,95,85,238,25,204,75,166,163,127,0,0'; -const t = 1.2; -const u = 0.8; -const a1 = 0.6; +const o = 1.2; +const t = 0.8; +const u = 0.4; +const a1 = 200; const b1 = 200; -const c1 = 200; -const d1 = 100; -const e1 = 137; -const f1 = 83; -const g1 = 70; -const h1 = 40; -const i1 = 50; -const j1 = 30; -const l1 = 2; -const m1 = '100%'; -const n1 = '#E6FFFFFF'; +const c1 = 100; +const d1 = 137; +const e1 = 83; +const f1 = 70; +const g1 = 40; +const h1 = 50; +const i1 = 30; +const j1 = 2; +const l1 = '100%'; +const m1 = '#E6FFFFFF'; +const n1 = '#00000000'; const o1 = '#99182431'; const q1 = '#CCCCCC'; const s1 = '#55CCCCCC'; @@ -83,69 +83,69 @@ const t1 = '#ff182431'; const u1 = '#99182431'; const v1 = 72; const w1 = 59; -const q3 = 3.25; -const z1 = { - c2: 200, - d2: 120, - e2: 14, - f2: 16, - g2: 10, - h2: 14, - i2: 16, - j2: 4, - l2: 5, - m2: 10, - n2: 14, - o2: 12, - q2: 16, - s2: 6.5, - t2: 12, - u2: 10, - v2: 5 -}; +const z1 = 3.25; const a2 = { - c2: 36, - d2: 48, - w2: 14, + d2: 200, + e2: 120, + f2: 14, + g2: 16, h2: 10, - i2: 12, - z2: 14, - a3: 16, - j2: 10, - e2: 14, - f2: 16, - g2: 14, - l2: 5, - m2: 10, - n2: 14, - o2: 12, - q2: 16, - s2: 6.5, - t2: 12, - u2: 10, - v2: 5 + i2: 14, + j2: 16, + l2: 4, + m2: 5, + n2: 10, + o2: 14, + q2: 12, + s2: 16, + t2: 6.5, + u2: 12, + v2: 10, + w2: 5 }; const b2 = { - c2: 24, - d2: 24, - w2: 8, - e2: 12, - f2: 14, - g2: 9, - h2: 10, - i2: 12, - z2: 12, + d2: 36, + e2: 48, + z2: 14, + i2: 10, + j2: 12, a3: 14, - j2: 4, - l2: 5, - m2: 10, - o2: 12, + b3: 16, + l2: 10, + f2: 14, + g2: 16, + h2: 14, + m2: 5, + n2: 10, + o2: 14, q2: 12, - s2: 4, - n2: 12, - t2: 8, + s2: 16, + t2: 6.5, + u2: 12, + v2: 10, + w2: 5 +}; +const c2 = { + d2: 24, + e2: 24, + z2: 8, + f2: 12, + g2: 14, + h2: 9, + i2: 10, + j2: 12, + a3: 12, + b3: 14, + l2: 4, + m2: 5, + n2: 10, + q2: 12, + s2: 12, + t2: 4, + o2: 12, u2: 8, - v2: 4 + v2: 8, + w2: 4 }; export class ContentFormCard extends ViewPU { @@ -154,32 +154,32 @@ export class ContentFormCard extends ViewPU { if (typeof paramsLambda === "function") { this.paramsGenerator_ = paramsLambda; } - this.b3 = new SynchedPropertySimpleOneWayPU(params.formType, this, 'formType'); + this.__formType = new SynchedPropertySimpleOneWayPU(params.formType, this, "formType"); this.contentFormData = undefined; - this.formStyle = a2; + this.formStyle = b2; this.controller = new TextController(); - this.c3 = new ObservedPropertySimplePU(1, this, 'cardScale'); - this.d3 = new SynchedPropertySimpleOneWayPU(params.formWidth, this, 'formWidth'); - this.e3 = new SynchedPropertySimpleOneWayPU(params.formHeight, this, 'formHeight'); - this.f3 = new ObservedPropertySimplePU(0, this, 'cardWidth'); - this.g3 = new ObservedPropertySimplePU(0, this, 'cardHeight'); - this.h3 = new ObservedPropertyObjectPU(undefined, this, 'defaultThumbImage'); - this.i3 = new ObservedPropertyObjectPU(undefined, this, 'thumbImage'); - this.j3 = new ObservedPropertyObjectPU(undefined, this, 'appImage'); - this.l3 = new ObservedPropertySimplePU(1, this, 'lineCount'); - this.m3 = new ObservedPropertySimplePU(false, this, 'isMirrorLanguageType'); + this.__cardScale = new ObservedPropertySimplePU(1, this, "cardScale"); + this.__formWidth = new SynchedPropertySimpleOneWayPU(params.formWidth, this, "formWidth"); + this.__formHeight = new SynchedPropertySimpleOneWayPU(params.formHeight, this, "formHeight"); + this.__cardWidth = new ObservedPropertySimplePU(0, this, "cardWidth"); + this.__cardHeight = new ObservedPropertySimplePU(0, this, "cardHeight"); + this.__defaultThumbImage = new ObservedPropertyObjectPU(undefined, this, "defaultThumbImage"); + this.__thumbImage = new ObservedPropertyObjectPU(undefined, this, "thumbImage"); + this.__appImage = new ObservedPropertyObjectPU(undefined, this, "appImage"); + this.__lineCount = new ObservedPropertySimplePU(1, this, "lineCount"); + this.__isMirrorLanguageType = new ObservedPropertySimplePU(false, this, "isMirrorLanguageType"); this.handleOnClick = () => { }; this.setInitiallyProvidedValue(params); - this.declareWatch('formType', this.formTypeChange); - this.declareWatch('formWidth', this.formSizeChange); - this.declareWatch('formHeight', this.formSizeChange); + this.declareWatch("formType", this.formTypeChange); + this.declareWatch("formWidth", this.formSizeChange); + this.declareWatch("formHeight", this.formSizeChange); this.finalizeConstruction(); } setInitiallyProvidedValue(params) { if (params.formType === undefined) { - this.b3.set(FormType.TYPE_MID); + this.__formType.set(FormType.TYPE_MID); } if (params.contentFormData !== undefined) { this.contentFormData = params.contentFormData; @@ -194,10 +194,10 @@ export class ContentFormCard extends ViewPU { this.cardScale = params.cardScale; } if (params.formWidth === undefined) { - this.d3.set(0); + this.__formWidth.set(0); } if (params.formHeight === undefined) { - this.e3.set(0); + this.__formHeight.set(0); } if (params.cardWidth !== undefined) { this.cardWidth = params.cardWidth; @@ -226,127 +226,127 @@ export class ContentFormCard extends ViewPU { } updateStateVars(params) { - this.b3.reset(params.formType); - this.d3.reset(params.formWidth); - this.e3.reset(params.formHeight); + this.__formType.reset(params.formType); + this.__formWidth.reset(params.formWidth); + this.__formHeight.reset(params.formHeight); } purgeVariableDependenciesOnElmtId(rmElmtId) { - this.b3.purgeDependencyOnElmtId(rmElmtId); - this.c3.purgeDependencyOnElmtId(rmElmtId); - this.d3.purgeDependencyOnElmtId(rmElmtId); - this.e3.purgeDependencyOnElmtId(rmElmtId); - this.f3.purgeDependencyOnElmtId(rmElmtId); - this.g3.purgeDependencyOnElmtId(rmElmtId); - this.h3.purgeDependencyOnElmtId(rmElmtId); - this.i3.purgeDependencyOnElmtId(rmElmtId); - this.j3.purgeDependencyOnElmtId(rmElmtId); - this.l3.purgeDependencyOnElmtId(rmElmtId); - this.m3.purgeDependencyOnElmtId(rmElmtId); + this.__formType.purgeDependencyOnElmtId(rmElmtId); + this.__cardScale.purgeDependencyOnElmtId(rmElmtId); + this.__formWidth.purgeDependencyOnElmtId(rmElmtId); + this.__formHeight.purgeDependencyOnElmtId(rmElmtId); + this.__cardWidth.purgeDependencyOnElmtId(rmElmtId); + this.__cardHeight.purgeDependencyOnElmtId(rmElmtId); + this.__defaultThumbImage.purgeDependencyOnElmtId(rmElmtId); + this.__thumbImage.purgeDependencyOnElmtId(rmElmtId); + this.__appImage.purgeDependencyOnElmtId(rmElmtId); + this.__lineCount.purgeDependencyOnElmtId(rmElmtId); + this.__isMirrorLanguageType.purgeDependencyOnElmtId(rmElmtId); } aboutToBeDeleted() { - this.b3.aboutToBeDeleted(); - this.c3.aboutToBeDeleted(); - this.d3.aboutToBeDeleted(); - this.e3.aboutToBeDeleted(); - this.f3.aboutToBeDeleted(); - this.g3.aboutToBeDeleted(); - this.h3.aboutToBeDeleted(); - this.i3.aboutToBeDeleted(); - this.j3.aboutToBeDeleted(); - this.l3.aboutToBeDeleted(); - this.m3.aboutToBeDeleted(); + this.__formType.aboutToBeDeleted(); + this.__cardScale.aboutToBeDeleted(); + this.__formWidth.aboutToBeDeleted(); + this.__formHeight.aboutToBeDeleted(); + this.__cardWidth.aboutToBeDeleted(); + this.__cardHeight.aboutToBeDeleted(); + this.__defaultThumbImage.aboutToBeDeleted(); + this.__thumbImage.aboutToBeDeleted(); + this.__appImage.aboutToBeDeleted(); + this.__lineCount.aboutToBeDeleted(); + this.__isMirrorLanguageType.aboutToBeDeleted(); SubscriberManager.Get().delete(this.id__()); this.aboutToBeDeletedInternal(); } get formType() { - return this.b3.get(); + return this.__formType.get(); } set formType(newValue) { - this.b3.set(newValue); + this.__formType.set(newValue); } get cardScale() { - return this.c3.get(); + return this.__cardScale.get(); } set cardScale(newValue) { - this.c3.set(newValue); + this.__cardScale.set(newValue); } get formWidth() { - return this.d3.get(); + return this.__formWidth.get(); } set formWidth(newValue) { - this.d3.set(newValue); + this.__formWidth.set(newValue); } get formHeight() { - return this.e3.get(); + return this.__formHeight.get(); } set formHeight(newValue) { - this.e3.set(newValue); + this.__formHeight.set(newValue); } get cardWidth() { - return this.f3.get(); + return this.__cardWidth.get(); } set cardWidth(newValue) { - this.f3.set(newValue); + this.__cardWidth.set(newValue); } get cardHeight() { - return this.g3.get(); + return this.__cardHeight.get(); } set cardHeight(newValue) { - this.g3.set(newValue); + this.__cardHeight.set(newValue); } get defaultThumbImage() { - return this.h3.get(); + return this.__defaultThumbImage.get(); } set defaultThumbImage(newValue) { - this.h3.set(newValue); + this.__defaultThumbImage.set(newValue); } get thumbImage() { - return this.i3.get(); + return this.__thumbImage.get(); } set thumbImage(newValue) { - this.i3.set(newValue); + this.__thumbImage.set(newValue); } get appImage() { - return this.j3.get(); + return this.__appImage.get(); } set appImage(newValue) { - this.j3.set(newValue); + this.__appImage.set(newValue); } get lineCount() { - return this.l3.get(); + return this.__lineCount.get(); } set lineCount(newValue) { - this.l3.set(newValue); + this.__lineCount.set(newValue); } get isMirrorLanguageType() { - return this.m3.get(); + return this.__isMirrorLanguageType.get(); } set isMirrorLanguageType(newValue) { - this.m3.set(newValue); + this.__isMirrorLanguageType.set(newValue); } aboutToAppear() { @@ -364,13 +364,13 @@ export class ContentFormCard extends ViewPU { formTypeChange() { switch (this.formType) { case FormType.TYPE_BIG: - this.formWidth = b1; + this.formWidth = a1; break; case FormType.TYPE_MID: - this.formWidth = c1; + this.formWidth = b1; break; default: - this.formWidth = e1; + this.formWidth = d1; break; } this.initCardStyle(); @@ -380,39 +380,40 @@ export class ContentFormCard extends ViewPU { this.initCardStyle(); } - initCardScale(n2, o2, q2) { - let r2 = this.formType === FormType.TYPE_SMALL ? a1 : u; - if (n2 > t) { - this.cardScale = t; - } else if (n2 < r2) { - this.cardScale = r2; + initCardScale(o2, q2, r2) { + let s2 = this.formType === FormType.TYPE_SMALL ? u : t; + if (o2 > o) { + this.cardScale = o; + } else if (o2 < s2) { + this.cardScale = s2; } else { - this.cardScale = n2; + this.cardScale = o2; } - this.cardWidth = o2 * this.cardScale; + this.cardWidth = q2 * this.cardScale; this.cardHeight = - (this.contentFormData?.title === '' && this.formHeight > 0) ? this.formHeight : q2 * this.cardScale; - console.info(`${m}, widthScale:${this.cardScale}, cardScale: ${this.cardScale}, ` + + (this.contentFormData?.title === '' && this.formHeight > 0) ? this.formHeight : r2 * this.cardScale; + console.info(`${j}, widthScale:${this.cardScale}, cardScale: ${this.cardScale}, ` + `cardWidth: ${this.cardWidth}, cardHeight: ${this.cardHeight}`); } initCardStyle() { - let m2 = 1; + let n2 = 1; + this.lineCount = 2; switch (this.formType) { case FormType.TYPE_BIG: - this.formStyle = z1; - m2 = this.formWidth ? this.formWidth / b1 : 1; - this.initCardScale(m2, b1, b1); + this.formStyle = a2; + n2 = this.formWidth ? this.formWidth / a1 : 1; + this.initCardScale(n2, a1, a1); break; case FormType.TYPE_MID: - this.formStyle = a2; - m2 = this.formWidth ? this.formWidth / c1 : 1; - this.initCardScale(m2, c1, d1); + this.formStyle = b2; + n2 = this.formWidth ? this.formWidth / b1 : 1; + this.initCardScale(n2, b1, c1); break; default: - this.formStyle = b2; - m2 = this.formWidth ? this.formWidth / e1 : 1; - this.initCardScale(m2, e1, f1); + this.formStyle = c2; + n2 = this.formWidth ? this.formWidth / d1 : 1; + this.initCardScale(n2, d1, e1); break; } } @@ -422,29 +423,35 @@ export class ContentFormCard extends ViewPU { Column.create(); Column.size({ width: '100%' }); Column.layoutWeight(this.formHeight > 0 ? 1 : 0); - Column.backgroundColor(this.thumbImage ? n1 : q1); + Column.backgroundColor(this.thumbImage ? m1 : q1); }, Column); this.observeComponentCreation2((elmtId, isInitialRender) => { If.create(); if (this.formHeight > 0) { this.ifElseBranchUpdateFunction(0, () => { - this.observeComponentCreation2((elmtId, isInitialRender) => { - Image.create(this.thumbImage ? this.thumbImage : this.defaultThumbImage); - Image.objectFit(ImageFit.Contain); - Image.width('100%'); - Image.layoutWeight(1); - Image.draggable(false); - }, Image); + if (!If.canRetake('cardThumbImage')) { + this.observeComponentCreation2((elmtId, isInitialRender) => { + Image.create(this.thumbImage ? this.thumbImage : this.defaultThumbImage); + Image.objectFit(ImageFit.Contain); + Image.width('100%'); + Image.layoutWeight(1); + Image.draggable(false); + Image.id('cardThumbImage'); + }, Image); + } }); } else { this.ifElseBranchUpdateFunction(1, () => { - this.observeComponentCreation2((elmtId, isInitialRender) => { - Image.create(this.thumbImage ? this.thumbImage : this.defaultThumbImage); - Image.objectFit(ImageFit.Contain); - Image.width('100%'); - Image.aspectRatio(this.getAspectRatio()); - Image.draggable(false); - }, Image); + if (!If.canRetake('cardThumbImage')) { + this.observeComponentCreation2((elmtId, isInitialRender) => { + Image.create(this.thumbImage ? this.thumbImage : this.defaultThumbImage); + Image.objectFit(ImageFit.Contain); + Image.width('100%'); + Image.aspectRatio(this.getAspectRatio()); + Image.draggable(false); + Image.id('cardThumbImage'); + }, Image); + } }); } }, If); @@ -458,26 +465,26 @@ export class ContentFormCard extends ViewPU { Divider.height(1); Divider.opacity(0.5); Divider.padding({ - left: this.formStyle.t2 * this.cardScale, - right: this.formStyle.t2 * this.cardScale + left: this.formStyle.u2 * this.cardScale, + right: this.formStyle.u2 * this.cardScale }); }, Divider); } AppView(parent = null) { this.observeComponentCreation2((elmtId, isInitialRender) => { - Row.create({ space: this.formStyle.s2 * this.cardScale }); + Row.create({ space: this.formStyle.t2 * this.cardScale }); Row.padding({ - left: this.formStyle.t2 * this.cardScale, - right: this.formStyle.t2 * this.cardScale, - top: this.formStyle.v2 * this.cardScale, - bottom: this.formStyle.u2 * this.cardScale, + left: this.formStyle.u2 * this.cardScale, + right: this.formStyle.u2 * this.cardScale, + top: this.formStyle.w2 * this.cardScale, + bottom: this.formStyle.v2 * this.cardScale, }); }, Row); this.observeComponentCreation2((elmtId, isInitialRender) => { Image.create(this.appImage); - Image.width(this.formStyle.o2 * this.cardScale); - Image.height(this.formStyle.o2 * this.cardScale); + Image.width(this.formStyle.q2 * this.cardScale); + Image.height(this.formStyle.q2 * this.cardScale); Image.objectFit(ImageFit.Fill); Image.alt({ "id": -1, @@ -494,21 +501,23 @@ export class ContentFormCard extends ViewPU { "moduleName": "__harDefaultModuleName__" }); Image.draggable(false); + Image.id('cardAppIcon'); }, Image); this.observeComponentCreation2((elmtId, isInitialRender) => { Text.create(this.contentFormData?.appName ? this.contentFormData?.appName : ' '); - Text.fontSize(this.formStyle.m2 * this.cardScale); + Text.fontSize(this.formStyle.n2 * this.cardScale); Text.fontColor(o1); Text.maxLines(1); - Text.lineHeight(this.formStyle.n2 * this.cardScale); + Text.lineHeight(this.formStyle.o2 * this.cardScale); Text.textOverflow({ overflow: TextOverflow.Ellipsis }); Text.constraintSize({ minWidth: this.getTextSize(TextType.APP_NAME, this.contentFormData?.appName) }); Text.backgroundColor(this.getTextBackground(this.contentFormData?.appName)); Text.fontWeight(FontWeight.Regular); - Text.borderRadius(this.contentFormData?.title === '' ? 0 : l1); + Text.borderRadius(this.contentFormData?.title === '' ? 0 : j1); Text.direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr); Text.maxFontScale(1); Text.layoutWeight(1); + Text.id('cardAppName'); }, Text); Text.pop(); Row.pop(); @@ -517,18 +526,19 @@ export class ContentFormCard extends ViewPU { TitleText(parent = null) { this.observeComponentCreation2((elmtId, isInitialRender) => { Text.create(this.contentFormData?.title); - Text.fontSize(this.formStyle.e2 * this.cardScale); + Text.fontSize(this.formStyle.f2 * this.cardScale); Text.fontColor(t1); Text.fontWeight(FontWeight.Bold); Text.maxLines(1); Text.textOverflow({ overflow: TextOverflow.Ellipsis }); - Text.height(this.formStyle.f2 * this.cardScale); - Text.margin({ top: this.formStyle.g2 * this.cardScale }); + Text.height(this.formStyle.g2 * this.cardScale); + Text.margin({ top: this.formStyle.h2 * this.cardScale }); Text.constraintSize({ minWidth: this.getTextSize(TextType.TITLE, this.contentFormData?.title) }); Text.backgroundColor(this.getTextBackground(this.contentFormData?.title)); - Text.borderRadius(this.contentFormData?.title === '' ? 0 : l1); + Text.borderRadius(this.contentFormData?.title === '' ? 0 : j1); Text.direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr); Text.maxFontScale(1); + Text.id('cardTitleText'); }, Text); Text.pop(); } @@ -542,25 +552,26 @@ export class ContentFormCard extends ViewPU { Image.create(this.thumbImage ? this.thumbImage : this.defaultThumbImage); Image.objectFit(ImageFit.Cover); Image.width('100%'); - Image.height(this.formStyle.d2 * this.cardScale); - Image.backgroundColor(this.thumbImage ? n1 : q1); + Image.height(this.formStyle.e2 * this.cardScale); + Image.backgroundColor(this.thumbImage ? m1 : q1); Image.draggable(false); + Image.id('cardThumbImage'); }, Image); this.observeComponentCreation2((elmtId, isInitialRender) => { Column.create(); Column.alignItems(HorizontalAlign.Start); Column.width('100%'); Column.padding({ - left: this.formStyle.t2 * this.cardScale, - right: this.formStyle.t2 * this.cardScale + left: this.formStyle.u2 * this.cardScale, + right: this.formStyle.u2 * this.cardScale }); - Column.margin({ bottom: this.formStyle.l2 * this.cardScale }); + Column.margin({ bottom: this.formStyle.m2 * this.cardScale }); Column.justifyContent(FlexAlign.Center); }, Column); this.TitleText.bind(this)(); this.observeComponentCreation2((elmtId, isInitialRender) => { Text.create(this.contentFormData?.description); - Text.fontSize(this.formStyle.h2 * this.cardScale); + Text.fontSize(this.formStyle.i2 * this.cardScale); Text.fontColor(u1); Text.fontWeight(FontWeight.Regular); Text.maxLines(1); @@ -568,13 +579,14 @@ export class ContentFormCard extends ViewPU { Text.constraintSize({ minWidth: this.getTextSize(TextType.DESCRIPTION, this.contentFormData?.description) }); - Text.height(this.formStyle.i2 * this.cardScale); - Text.margin({ top: this.formStyle.j2 * this.cardScale }); + Text.height(this.formStyle.j2 * this.cardScale); + Text.margin({ top: this.formStyle.l2 * this.cardScale }); Text.backgroundColor(this.getTextBackground(this.contentFormData?.description)); Text.fontWeight(FontWeight.Regular); - Text.borderRadius(this.contentFormData?.description ? 0 : l1); + Text.borderRadius(this.contentFormData?.description ? 0 : j1); Text.direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr); Text.maxFontScale(1); + Text.id('cardDescription'); }, Text); Text.pop(); Column.pop(); @@ -593,20 +605,23 @@ export class ContentFormCard extends ViewPU { Text.fontWeight(FontWeight.Regular); Text.textOverflow({ overflow: TextOverflow.Ellipsis }); Text.lineHeight((this.lineCount === 1 ? - (this.formStyle.a3 ? this.formStyle.a3 : - this.formStyle.i2) : this.formStyle.i2) * this.cardScale); - Text.fontSize(this.getDescriptionFontSize()); + (this.formStyle.b3 ? this.formStyle.b3 : + this.formStyle.j2) : this.formStyle.j2) * this.cardScale); + Text.fontSize(this.getDescriptionFontSize() * this.cardScale); Text.constraintSize({ minWidth: this.getTextSize(TextType.DESCRIPTION, this.contentFormData?.description) }); Text.backgroundColor(this.getTextBackground(this.contentFormData?.description)); - Text.borderRadius(this.contentFormData?.description ? 0 : l1); + Text.borderRadius(this.contentFormData?.description ? 0 : j1); Text.onAreaChange(() => { - let l2 = this.controller.getLayoutManager(); - this.lineCount = l2.getLineCount(); + let m2 = this.controller.getLayoutManager(); + if (m2.getLineCount() === 2) { + this.lineCount = 2; + } }); Text.direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr); Text.maxFontScale(1); + Text.id('cardDescription'); }, Text); Text.pop(); } @@ -629,15 +644,15 @@ export class ContentFormCard extends ViewPU { Row.create(); Row.width('100%'); Row.padding({ - left: this.formStyle.t2 * this.cardScale, - right: this.formStyle.t2 * this.cardScale + left: this.formStyle.u2 * this.cardScale, + right: this.formStyle.u2 * this.cardScale }); Row.layoutWeight(1); - Row.margin({ bottom: this.formStyle.l2 * this.cardScale }); + Row.margin({ bottom: this.formStyle.m2 * this.cardScale }); Row.alignItems(VerticalAlign.Top); }, Row); this.observeComponentCreation2((elmtId, isInitialRender) => { - Column.create({ space: this.formStyle.j2 * this.cardScale }); + Column.create({ space: this.formStyle.l2 * this.cardScale }); Column.layoutWeight(1); Column.alignItems(HorizontalAlign.Start); }, Column); @@ -648,19 +663,22 @@ export class ContentFormCard extends ViewPU { If.create(); if (this.thumbImage) { this.ifElseBranchUpdateFunction(0, () => { - this.observeComponentCreation2((elmtId, isInitialRender) => { - Image.create(this.thumbImage); - Image.width(this.formStyle.c2 * this.cardScale); - Image.height(this.formStyle.d2 * this.cardScale); - Image.objectFit(this.thumbImage ? ImageFit.Cover : ImageFit.Contain); - Image.borderRadius(4); - Image.draggable(false); - Image.margin({ - right: this.isMirrorLanguageType ? (this.formStyle.w2 * this.cardScale) : 0, - left: this.isMirrorLanguageType ? 0 : (this.formStyle.w2 * this.cardScale), - top: this.formStyle.g2 * this.cardScale - }); - }, Image); + if (!If.canRetake('cardThumbImage')) { + this.observeComponentCreation2((elmtId, isInitialRender) => { + Image.create(this.thumbImage); + Image.width(this.formStyle.d2 * this.cardScale); + Image.height(this.formStyle.e2 * this.cardScale); + Image.objectFit(this.thumbImage ? ImageFit.Cover : ImageFit.Contain); + Image.borderRadius(4); + Image.draggable(false); + Image.margin({ + right: this.isMirrorLanguageType ? (this.formStyle.z2 * this.cardScale) : 0, + left: this.isMirrorLanguageType ? 0 : (this.formStyle.z2 * this.cardScale), + top: this.formStyle.h2 * this.cardScale + }); + Image.id('cardThumbImage'); + }, Image); + } }); } else { this.ifElseBranchUpdateFunction(1, () => { @@ -696,17 +714,17 @@ export class ContentFormCard extends ViewPU { Column.create(); Column.width('100%'); Column.padding({ - left: this.formStyle.t2 * this.cardScale, - right: this.formStyle.t2 * this.cardScale + left: this.formStyle.u2 * this.cardScale, + right: this.formStyle.u2 * this.cardScale }); Column.layoutWeight(1); Column.alignItems(HorizontalAlign.Start); - Column.margin({ bottom: this.formStyle.l2 * this.cardScale }); + Column.margin({ bottom: this.formStyle.m2 * this.cardScale }); }, Column); this.TitleText.bind(this)(); this.observeComponentCreation2((elmtId, isInitialRender) => { Row.create(); - Row.margin({ top: this.formStyle.j2 * this.cardScale }); + Row.margin({ top: this.formStyle.l2 * this.cardScale }); Row.layoutWeight(1); }, Row); this.observeComponentCreation2((elmtId, isInitialRender) => { @@ -720,24 +738,27 @@ export class ContentFormCard extends ViewPU { If.create(); if (this.thumbImage) { this.ifElseBranchUpdateFunction(0, () => { - this.observeComponentCreation2((elmtId, isInitialRender) => { - Image.create(this.thumbImage); - Image.objectFit(ImageFit.Cover); - Image.borderRadius({ - "id": -1, - "type": 10002, - params: ['sys.float.corner_radius_level2'], - "bundleName": "__harDefaultBundleName__", - "moduleName": "__harDefaultModuleName__" - }); - Image.width(this.formStyle.c2 * this.cardScale); - Image.height(this.formStyle.d2 * this.cardScale); - Image.draggable(false); - Image.margin({ - left: this.isMirrorLanguageType ? 0 : (this.formStyle.w2 * this.cardScale), - right: this.isMirrorLanguageType ? (this.formStyle.w2 * this.cardScale) : 0 - }); - }, Image); + if (!If.canRetake('cardThumbImage')) { + this.observeComponentCreation2((elmtId, isInitialRender) => { + Image.create(this.thumbImage); + Image.objectFit(ImageFit.Cover); + Image.borderRadius({ + "id": -1, + "type": 10002, + params: ['sys.float.corner_radius_level2'], + "bundleName": "__harDefaultBundleName__", + "moduleName": "__harDefaultModuleName__" + }); + Image.width(this.formStyle.d2 * this.cardScale); + Image.height(this.formStyle.e2 * this.cardScale); + Image.draggable(false); + Image.margin({ + left: this.isMirrorLanguageType ? 0 : (this.formStyle.z2 * this.cardScale), + right: this.isMirrorLanguageType ? (this.formStyle.z2 * this.cardScale) : 0 + }); + Image.id('cardThumbImage'); + }, Image); + } }); } else { this.ifElseBranchUpdateFunction(1, () => { @@ -759,25 +780,25 @@ export class ContentFormCard extends ViewPU { initialRender() { this.observeComponentCreation2((elmtId, isInitialRender) => { Column.create(); - Column.borderRadius(this.formStyle.q2 * this.cardScale); + Column.borderRadius(this.formStyle.s2 * this.cardScale); Column.clip(true); - Column.backgroundColor(n1); - Column.backgroundBlurStyle(BlurStyle.COMPONENT_ULTRA_THICK, { colorMode: ThemeColorMode.LIGHT, adaptiveColor: AdaptiveColor.DEFAULT, scale: 1.0 }); + Column.backgroundColor(m1); + Column.backgroundBlurStyle(BlurStyle.COMPONENT_ULTRA_THICK, + { colorMode: ThemeColorMode.LIGHT, adaptiveColor: AdaptiveColor.DEFAULT, scale: 1.0 }); Column.shadow(ShadowStyle.OUTER_DEFAULT_SM); Column.width(this.cardWidth); Column.onClick(() => { + this.handleOnClick(); if (!this.contentFormData?.linkUri) { - console.warn(`${m}, linkUri is null`); + console.warn(`${j}, linkUri is null`); return; } - this.handleOnClick(); try { let context = getContext(this); context.openLink(this.contentFormData?.linkUri, { appLinkingOnly: false, parameters: {} }); - } - catch (err) { + } catch (err) { let error = err; - console.error(`${m}, Failed to openLink, code is ${error.code}, message is ${error.message}`); + console.error(`${j}, Failed to openLink, code is ${error.code}, message is ${error.message}`); } }); }, Column); @@ -787,13 +808,11 @@ export class ContentFormCard extends ViewPU { this.ifElseBranchUpdateFunction(0, () => { this.Card4x4.bind(this)(); }); - } - else if (this.formType === FormType.TYPE_MID) { + } else if (this.formType === FormType.TYPE_MID) { this.ifElseBranchUpdateFunction(1, () => { this.Card4x2.bind(this)(); }); - } - else { + } else { this.ifElseBranchUpdateFunction(2, () => { this.Card2x1.bind(this)(); }); @@ -805,44 +824,44 @@ export class ContentFormCard extends ViewPU { initSystemLanguage() { try { - this.isMirrorLanguageType = j.isRTL(j.System.getSystemLanguage()); + this.isMirrorLanguageType = i.isRTL(i.System.getSystemLanguage()); } catch (err) { let error = err; - console.error(`${m}, Failed to init system language, code is ${error.code}, message is ${error.message}`); + console.error(`${j}, Failed to init system language, code is ${error.code}, message is ${error.message}`); } return true; } - async getPixelMap(i2, callback) { - let j2 = undefined; + async getPixelMap(j2, callback) { + let k2 = undefined; try { - j2 = image.createImageSource(i2.buffer); - let k2 = await j2?.createPixelMap(); - callback(k2); - j2.release(); + k2 = image.createImageSource(j2.buffer); + let l2 = await k2?.createPixelMap(); + callback(l2); + k2.release(); } catch (err) { let error = err; - console.error(`${m}, Failed to create pixelMap, code is ${error.code}, message is ${error.message}`); + console.error(`${j}, Failed to create pixelMap, code is ${error.code}, message is ${error.message}`); } } - transStringToUint8Array(g2) { - const arr = g2.split(','); - const h2 = new Uint8Array(arr.length); + transStringToUint8Array(h2) { + const arr = h2.split(','); + const i2 = new Uint8Array(arr.length); arr.forEach((value, index) => { - h2[index] = parseInt(value); + i2[index] = parseInt(value); }); - return h2; + return i2; } createPixelMap() { - let f2 = this.transStringToUint8Array(o); - this.getPixelMap(f2, (pixelMap) => { + let g2 = this.transStringToUint8Array(m); + this.getPixelMap(g2, (pixelMap) => { this.defaultThumbImage = pixelMap; }); if (this.contentFormData && this.contentFormData?.thumbData) { if (!(this.contentFormData?.thumbData instanceof Uint8Array)) { - console.error(`${m}, thumbData is not Uint8Array`); + console.error(`${j}, thumbData is not Uint8Array`); return; } this.getPixelMap(this.contentFormData?.thumbData, (pixelMap) => { @@ -851,7 +870,7 @@ export class ContentFormCard extends ViewPU { } if (this.contentFormData && this.contentFormData?.appIcon) { if (!(this.contentFormData?.appIcon instanceof Uint8Array)) { - console.error(`${m}, appIcon is not Uint8Array`); + console.error(`${j}, appIcon is not Uint8Array`); return; } this.getPixelMap(this.contentFormData?.appIcon, (pixelMap) => { @@ -861,19 +880,19 @@ export class ContentFormCard extends ViewPU { } getAspectRatio() { - let c2 = this.thumbImage?.getImageInfoSync().size; - let d2 = this.formType === FormType.TYPE_MID ? c1 : e1; - let e2 = this.formType === FormType.TYPE_MID ? v1 : w1; - if (c2 && this.thumbImage) { - if ((c2.width / c2.height) > (d2 / (e2 * u))) { - return d2 / (e2 * u); + let d2 = this.thumbImage?.getImageInfoSync().size; + let e2 = this.formType === FormType.TYPE_MID ? b1 : d1; + let f2 = this.formType === FormType.TYPE_MID ? v1 : w1; + if (d2 && this.thumbImage) { + if ((d2.width / d2.height) > (e2 / (f2 * t))) { + return e2 / (f2 * t); } - if ((c2.width / c2.height) < (d2 / (e2 * t))) { - return d2 / (e2 * t); + if ((d2.width / d2.height) < (e2 / (f2 * o))) { + return e2 / (f2 * o); } - return c2.width / c2.height; + return d2.width / d2.height; } - return d2 / e2; + return e2 / f2; } getTextBackground(text) { @@ -887,20 +906,20 @@ export class ContentFormCard extends ViewPU { if (textType === TextType.TITLE) { if (text === '' || text === undefined || text === null) { if (this.formType === FormType.TYPE_SMALL) { - return i1; + return h1; } - return g1; + return f1; } - return m1; + return l1; } if (textType === TextType.APP_NAME) { if (text === '' || text === undefined || text === null) { if (this.formType === FormType.TYPE_SMALL) { - return j1; + return i1; } - return h1; + return g1; } - return m1; + return l1; } return '100%'; } @@ -916,15 +935,15 @@ export class ContentFormCard extends ViewPU { }; } return { - maxHeight: this.cardHeight * t, - minHeight: this.cardHeight * u + maxHeight: this.cardHeight * o, + minHeight: this.cardHeight * t }; } } getDescriptionFontSize() { - return this.lineCount === 1 ? (this.formStyle.z2 ? this.formStyle.z2 : - this.formStyle.h2) : (this.formStyle.h2 * this.cardScale); + return this.lineCount === 1 ? (this.formStyle.a3 ? this.formStyle.a3 : + this.formStyle.i2) : this.formStyle.i2; } rerender() { diff --git a/udmf/interfaces/components/source/UdmfComponents.ets b/udmf/interfaces/components/source/UdmfComponents.ets index 0377f35f..a2ced7c9 100644 --- a/udmf/interfaces/components/source/UdmfComponents.ets +++ b/udmf/interfaces/components/source/UdmfComponents.ets @@ -61,7 +61,7 @@ const defaultIcon: string = ',73,141,205,245,214,23,231,110,132,188,27,13,88,8,43,145,225,60,68,0,42,15,95,85,238,25,204,75,166,163,127,0,0'; const MAX_CARD_SCALE: number = 1.2; const MIN_CARD_SCALE: number = 0.8; -const SMALL_MIN_CARD_SCALE: number = 0.6; +const SMALL_MIN_CARD_SCALE: number = 0.4; const DEFAULT_BIG_CARD_SIZE: number = 200; const DEFAULT_MID_CARD_WIDTH: number = 200; const DEFAULT_MID_CARD_HEIGHT: number = 100; @@ -74,6 +74,7 @@ const SMALL_EMPTY_APPNAME_WIDTH: number = 30; const DEFAULT_EMPTY_TEXT_RADIUS: number = 2; const DEFAULT_EMPTY_DESCRIPTION_WIDTH: string = '100%'; const CARD_BACKGROUND: string = '#E6FFFFFF'; +const TRANSLATE_BACKGROUND: string = '#00000000'; const APP_NAME_COLOR: string = '#99182431'; const DEFAULT_THUMB_BACKGROUND: string = '#CCCCCC'; const DEFAULT_FONT_BACKGROUND: string = '#55CCCCCC'; @@ -241,6 +242,7 @@ export struct ContentFormCard { initCardStyle(): void { let widthScale = 1; + this.lineCount = 1; switch (this.formType) { case FormType.TYPE_BIG: this.formStyle = BIG_CARD_STYLE; @@ -279,12 +281,14 @@ export struct ContentFormCard { .width('100%') .layoutWeight(1) .draggable(false) + .id('cardThumbImage') } else { Image(this.thumbImage ? this.thumbImage : this.defaultThumbImage) .objectFit(ImageFit.Contain) .width('100%') .aspectRatio(this.getAspectRatio()) .draggable(false) + .id('cardThumbImage') } } .size({ width: '100%' }) @@ -313,6 +317,7 @@ export struct ContentFormCard { .alt($r('sys.media.ohos_app_icon')) .borderRadius($r('sys.float.corner_radius_level1')) .draggable(false) + .id('cardAppIcon') Text(this.contentFormData?.appName ? this.contentFormData?.appName : ' ') .fontSize(this.formStyle.appNameFontSize * this.cardScale) .fontColor(APP_NAME_COLOR) @@ -326,6 +331,7 @@ export struct ContentFormCard { .direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr) .maxFontScale(1) .layoutWeight(1) + .id('cardAppName') } .padding({ @@ -351,6 +357,7 @@ export struct ContentFormCard { .borderRadius(this.contentFormData?.title === '' ? 0 : DEFAULT_EMPTY_TEXT_RADIUS) .direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr) .maxFontScale(1) + .id('cardTitleText') } @Builder @@ -362,6 +369,7 @@ export struct ContentFormCard { .height(this.formStyle.thumbHeight * this.cardScale) .backgroundColor(this.thumbImage ? CARD_BACKGROUND : DEFAULT_THUMB_BACKGROUND) .draggable(false) + .id('cardThumbImage') Column() { this.TitleText() Text(this.contentFormData?.description) @@ -378,6 +386,7 @@ export struct ContentFormCard { .borderRadius(this.contentFormData?.description ? 0 : DEFAULT_EMPTY_TEXT_RADIUS) .direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr) .maxFontScale(1) + .id('cardDescription') } .alignItems(HorizontalAlign.Start) .width('100%') @@ -405,16 +414,20 @@ export struct ContentFormCard { .lineHeight((this.lineCount === 1 ? (this.formStyle.maxDescriptionLineHeight ? this.formStyle.maxDescriptionLineHeight : this.formStyle.descriptionLineHeight) : this.formStyle.descriptionLineHeight) * this.cardScale) - .fontSize(this.getDescriptionFontSize()) + .fontSize(this.getDescriptionFontSize() * this.cardScale) .constraintSize({ minWidth: this.getTextSize(TextType.DESCRIPTION, this.contentFormData?.description) }) .backgroundColor(this.getTextBackground(this.contentFormData?.description)) .borderRadius(this.contentFormData?.description ? 0 : DEFAULT_EMPTY_TEXT_RADIUS) .onAreaChange(() => { let layoutManager: LayoutManager = this.controller.getLayoutManager(); this.lineCount = layoutManager.getLineCount(); + if (layoutManager.getLineCount() === 2) { + this.lineCount = 2; + } }) .direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr) .maxFontScale(1) + .id('cardDescription') } @Builder @@ -443,6 +456,7 @@ export struct ContentFormCard { left: this.isMirrorLanguageType ? 0 : (this.formStyle.thumbMarginLeft as number * this.cardScale), top: this.formStyle.titleFontMarginTop * this.cardScale }) + .id('cardThumbImage') } } .thumbStyle() @@ -483,6 +497,7 @@ export struct ContentFormCard { left: this.isMirrorLanguageType ? 0 : (this.formStyle.thumbMarginLeft as number * this.cardScale), right: this.isMirrorLanguageType ? (this.formStyle.thumbMarginLeft as number * this.cardScale) : 0 }) + .id('cardThumbImage') } } .margin({ top: this.formStyle.descriptionMarginTop * this.cardScale }) @@ -517,11 +532,11 @@ export struct ContentFormCard { .shadow(ShadowStyle.OUTER_DEFAULT_SM) .width(this.cardWidth) .onClick(() => { + this.handleOnClick(); if (!this.contentFormData?.linkUri) { console.warn(`${TAG}, linkUri is null`); return; } - this.handleOnClick(); try { let context = getContext(this) as common.UIAbilityContext; context.openLink(this.contentFormData?.linkUri, { appLinkingOnly: false, parameters: {} }); @@ -609,7 +624,7 @@ export struct ContentFormCard { getTextBackground(text: string | undefined): string { if (text && text.length > 0) { - return CARD_BACKGROUND; + return TRANSLATE_BACKGROUND; } return DEFAULT_FONT_BACKGROUND; } @@ -655,6 +670,6 @@ export struct ContentFormCard { getDescriptionFontSize(): number { return this.lineCount === 1 ? (this.formStyle.maxDescriptionFontSize ? this.formStyle.maxDescriptionFontSize : - this.formStyle.descriptionFontSize) : (this.formStyle.descriptionFontSize * this.cardScale); + this.formStyle.descriptionFontSize) : this.formStyle.descriptionFontSize; } } \ No newline at end of file diff --git a/udmf/interfaces/components/udmfcomponents.cpp b/udmf/interfaces/components/udmfcomponents.cpp index d4897a01..760b879c 100644 --- a/udmf/interfaces/components/udmfcomponents.cpp +++ b/udmf/interfaces/components/udmfcomponents.cpp @@ -20,7 +20,8 @@ extern const char _binary_udmfcomponents_abc_start[]; extern const char _binary_udmfcomponents_abc_end[]; -extern "C" __attribute__((visibility("default"))) void NAPI_data_udmfComponents_GetABCCode(const char **buf, int *buflen) +extern "C" __attribute__((visibility("default"))) void NAPI_data_UdmfComponents_GetABCCode(const char **buf, + int *buflen) { if (buf != nullptr) { *buf = _binary_udmfcomponents_abc_start; @@ -33,13 +34,13 @@ extern "C" __attribute__((visibility("default"))) void NAPI_data_udmfComponents_ extern "C" __attribute__((constructor)) void UdmfComponentsRegisterModule(void) { - static napi_module udmfComponentsModule = { + static napi_module UdmfComponentsModule = { .nm_version = 1, .nm_flags = 0, .nm_filename = nullptr, - .nm_modname = "data.udmfComponents", + .nm_modname = "data.UdmfComponents", .nm_priv = ((void *)0), .reserved = { 0 }, }; - napi_module_register(&udmfComponentsModule); + napi_module_register(&UdmfComponentsModule); } \ No newline at end of file diff --git a/udmf/interfaces/innerkits/BUILD.gn b/udmf/interfaces/innerkits/BUILD.gn index 1e69192a..d1a4824b 100644 --- a/udmf/interfaces/innerkits/BUILD.gn +++ b/udmf/interfaces/innerkits/BUILD.gn @@ -18,6 +18,7 @@ config("udmf_client_config") { "${udmf_interfaces_path}/innerkits/client", "${udmf_interfaces_path}/innerkits/common", "${udmf_interfaces_path}/innerkits/data", + "${udmf_interfaces_path}/innerkits/dynamic", "${udmf_interfaces_path}/innerkits/convert", "${udmf_interfaces_path}/ndk/data", "${udmf_framework_path}/common", @@ -26,15 +27,6 @@ config("udmf_client_config") { "${udmf_framework_path}/innerkitsimpl/service", "${udmf_framework_path}/innerkitsimpl/convert", "${udmf_framework_path}/ndkimpl/data", - "${kv_store_path}/frameworks/common", - "//third_party/libuv/include", - "//third_party/node/src", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/src", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/interfaces/innerkits/distributeddata/include", - "${file_service_path}/interfaces/common/include", - "${file_service_path}/interfaces/innerkits/native/file_uri/include", ] } @@ -52,6 +44,7 @@ ohos_shared_library("udmf_client") { "${udmf_framework_path}/common/tlv_object.cpp", "${udmf_framework_path}/common/tlv_util.cpp", "${udmf_framework_path}/common/udmf_copy_file.cpp", + "${udmf_framework_path}/common/udmf_executor.cpp", "${udmf_framework_path}/common/udmf_radar_reporter.cpp", "${udmf_framework_path}/common/udmf_types_util.cpp", "${udmf_framework_path}/common/udmf_utils.cpp", @@ -80,7 +73,9 @@ ohos_shared_library("udmf_client") { "${udmf_framework_path}/innerkitsimpl/data/unified_html_record_process.cpp", "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", "${udmf_framework_path}/innerkitsimpl/data/video.cpp", + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_loader.cpp", "${udmf_framework_path}/innerkitsimpl/service/progress_callback.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_notifier_stub.cpp", "${udmf_framework_path}/innerkitsimpl/service/udmf_service_client.cpp", "${udmf_framework_path}/innerkitsimpl/service/udmf_service_proxy.cpp", ] @@ -102,9 +97,9 @@ ohos_shared_library("udmf_client") { "hisysevent:libhisysevent", "hitrace:hitrace_meter", "hitrace:libhitracechain", - "image_framework:image_native", "ipc:ipc_core", "kv_store:distributeddata_mgr", + "libuv:uv", "samgr:samgr_proxy", ] @@ -149,7 +144,6 @@ ohos_shared_library("utd_client") { "${udmf_framework_path}/common/custom_utd_json_parser.cpp", "${udmf_framework_path}/common/custom_utd_store.cpp", "${udmf_framework_path}/common/graph.cpp", - "${udmf_framework_path}/common/udmf_utils.cpp", "${udmf_framework_path}/common/utd_cfgs_checker.cpp", "${udmf_framework_path}/common/utd_graph.cpp", "${udmf_framework_path}/innerkitsimpl/client/utd_client.cpp", @@ -187,3 +181,35 @@ ohos_shared_library("utd_client") { external_deps += [ "selinux_adapter:librestorecon" ] } } + +ohos_shared_library("pixelmap_wrapper") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + + include_dirs = [ + "${udmf_interfaces_path}/innerkits/dynamic", + "${udmf_framework_path}/common", + ] + sources = [ + "${udmf_framework_path}/innerkitsimpl/dynamic/pixelmap_wrapper.cpp", + ] + + defines = [ "API_EXPORT=__attribute__((visibility (\"default\")))" ] + + deps = [] + + external_deps = [ + "image_framework:image_native", + "ipc:ipc_single", + "hilog:libhilog", + ] + + relative_install_dir = "platformsdk" + innerapi_tags = [ "platformsdk" ] + part_name = "udmf" + subsystem_name = "distributeddatamgr" +} diff --git a/udmf/interfaces/innerkits/aipcore/BUILD.gn b/udmf/interfaces/innerkits/aipcore/BUILD.gn new file mode 100644 index 00000000..75cfe636 --- /dev/null +++ b/udmf/interfaces/innerkits/aipcore/BUILD.gn @@ -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. +import("//build/ohos.gni") +import("//foundation/distributeddatamgr/udmf/udmf.gni") + +config("aip_core_manager_config") { + visibility = [ ":*" ] + include_dirs = [ "${udmf_interfaces_path}/innerkits/aipcore" ] +} + +ohos_static_library("aip_core_mgr_static") { + branch_protector_ret = "pac_ret" + sanitize = { + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + cflags = [ "-Wno-c99-designator" ] + public_configs = [ ":aip_core_manager_config" ] + + subsystem_name = "distributeddatamgr" + part_name = "udmf" +} diff --git a/udmf/interfaces/jskits/intelligence/i_aip_core_manager.h b/udmf/interfaces/innerkits/aipcore/i_aip_core_manager.h similarity index 84% rename from udmf/interfaces/jskits/intelligence/i_aip_core_manager.h rename to udmf/interfaces/innerkits/aipcore/i_aip_core_manager.h index 5770829e..a91b7dbc 100644 --- a/udmf/interfaces/jskits/intelligence/i_aip_core_manager.h +++ b/udmf/interfaces/innerkits/aipcore/i_aip_core_manager.h @@ -15,10 +15,13 @@ #ifndef I_AIP_CORE_MANAGER_H #define I_AIP_CORE_MANAGER_H -#include <stdint.h> +#include <cstdint> +#include <functional> +#include <map> +#include <memory> #include <string> +#include <variant> #include <vector> -#include <map> namespace OHOS { namespace DataIntelligence { @@ -60,6 +63,7 @@ struct ContextParam { std::string bundleName; std::string moduleName; std::string baseDir; + std::string cacheDir; int32_t area; bool isSystemApp = false; bool isStageMode = true; @@ -248,14 +252,52 @@ enum TsSimilarityLevel { HIGH }; +struct OptionStruct { + bool answerWithRetrievalItem; +}; + +struct AnswerStruct { + std::string chunk; + std::vector<ItemInfoStruct> data; +}; + +struct StreamStruct { + bool isFinished; + AnswerStruct answer; +}; + +enum TsLLMRequestStatus { + LLM_SUCCESS = 0, + LLM_ERROR, + LLM_LOAD_FAILED, + LLM_TIMEOUT, + LLM_BUSY, +}; +struct LLMStreamAnswer { + bool isFinished; + std::string chunk; +}; + +typedef std::function<void(const LLMStreamAnswer &)> LLMStreamCallback; + +class IChatLLM { +public: + IChatLLM() = default; + virtual ~IChatLLM() = default; + virtual TsLLMRequestStatus StreamChat(const std::string &query, const LLMStreamCallback &streamCallback); +}; + +struct ConfigStruct { + std::shared_ptr<IChatLLM> chatLLM; + RetrievalConfigStruct retriever; + RetrievalConditionStruct condition; +}; + class IAipCoreManager { public: IAipCoreManager() = default; virtual ~IAipCoreManager() = default; - virtual int32_t InitRetriever(const RetrievalConfigStruct& retrievalConfig) = 0; - virtual int32_t Retrieve(const std::string query, const RetrievalConditionStruct &condition, - RetrievalResponseStruct &retrievalResponse) = 0; virtual int32_t InitTextModel(const ModelConfigData &config) = 0; virtual int32_t InitImageModel(const ModelConfigData &config) = 0; virtual int32_t LoadTextModel() = 0; @@ -267,6 +309,14 @@ public: virtual int32_t ReleaseImageModel() = 0; virtual int32_t GetImageEmbedding(std::string uri, std::vector<float> &results) = 0; virtual int32_t SplitText(std::string text, int32_t size, float overlap, std::vector<std::string> &results) = 0; + + virtual int32_t CreateRAGSession(const ContextParam &contex, const ConfigStruct &config) = 0; + virtual int32_t RAGSessionStreamRun(const std::string &question, const OptionStruct &option, + std::function<void(const StreamStruct&, int32_t)> callback) = 0; + virtual int32_t ReleaseRAGSession() = 0; + virtual int32_t RAGSessionRun(const std::string &query, const OptionStruct &runOption, AnswerStruct &answer) = 0; + + virtual bool CheckDeviceType() = 0; }; struct AipCoreManagerHandle { diff --git a/udmf/interfaces/innerkits/client/udmf_async_client.h b/udmf/interfaces/innerkits/client/udmf_async_client.h index b997be09..6223f0d1 100644 --- a/udmf/interfaces/innerkits/client/udmf_async_client.h +++ b/udmf/interfaces/innerkits/client/udmf_async_client.h @@ -21,11 +21,13 @@ namespace OHOS::UDMF { class UdmfAsyncClient { public: + using UdmfTask = std::function<void()>; friend class UdmfCopyFile; static UdmfAsyncClient API_EXPORT &GetInstance(); Status API_EXPORT StartAsyncDataRetrieval(const GetDataParams &params); Status API_EXPORT Cancel(std::string businessUdKey); Status CancelOnSingleTask(); + void PushTaskToExecutor(UdmfTask task); private: UdmfAsyncClient(); ~UdmfAsyncClient() = default; @@ -49,11 +51,9 @@ private: Status Clear(const std::string &businessUdKey); Status ProcessUnifiedData(std::unique_ptr<AsyncHelper> &asyncHelper); bool IsParamValid(const GetDataParams &params); + uint64_t GetCurrentTimeMillis(); -#ifndef IOS_PLATFORM - ExecutorPool executor_; -#endif - std::map<std::string, std::unique_ptr<AsyncHelper>> asyncHelperMap_; + std::map<std::string, std::unique_ptr<AsyncHelper>> asyncHelperMap_ {}; std::mutex mutex_; }; } // namespace diff --git a/udmf/interfaces/innerkits/client/udmf_client.h b/udmf/interfaces/innerkits/client/udmf_client.h index b1b20bd2..26dd2c64 100644 --- a/udmf/interfaces/innerkits/client/udmf_client.h +++ b/udmf/interfaces/innerkits/client/udmf_client.h @@ -47,6 +47,13 @@ public: Status API_EXPORT RemoveAppShareOption(const std::string &intention); Status API_EXPORT GetAppShareOption(const std::string &intention, enum ShareOptions &shareOption); Status GetDataFromCache(const QueryOption &query, UnifiedData &unifiedData); + Status API_EXPORT GetParentType(Summary &oldSummary, Summary &newSummary); + Status API_EXPORT SetDelayInfo(const DataLoadParams &dataLoadParams, std::string &key); + Status API_EXPORT PushDelayData(const std::string &key, UnifiedData &unifiedData); + Status GetDataIfAvailable(const std::string &key, const DataLoadInfo &dataLoadInfo, + sptr<IRemoteObject> iUdmfNotifier, std::shared_ptr<UnifiedData> unifiedData); + std::string API_EXPORT GetBundleNameByUdKey(const std::string &key); + bool API_EXPORT IsAppropriateType(const Summary &summary, const std::vector<std::string> &allowTypes); private: UdmfClient() = default; @@ -54,8 +61,10 @@ private: UdmfClient(const UdmfClient &obj) = delete; UdmfClient &operator=(const UdmfClient &obj) = delete; std::string GetSelfBundleName(); + void ProcessDragIfInApp(UnifiedData &unifiedData, std::string &intentionDrag, std::string &key); + bool CheckFileUtdType(const Summary &summary, const std::vector<std::string> &allowTypes); - ConcurrentMap<std::string, UnifiedData> dataCache_; + ConcurrentMap<std::string, UnifiedData> dataCache_ {}; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/client/utd_client.h b/udmf/interfaces/innerkits/client/utd_client.h index 71a7515c..0d063edf 100644 --- a/udmf/interfaces/innerkits/client/utd_client.h +++ b/udmf/interfaces/innerkits/client/utd_client.h @@ -20,9 +20,9 @@ #include <string> #include <vector> #include <map> +#include <mutex> #include "utd_common.h" #include "preset_type_descriptors.h" -#include "preset_type_descriptors.h" #include "flexible_type.h" #include "type_descriptor.h" #include "error_code.h" @@ -52,19 +52,26 @@ private: ~UtdClient(); UtdClient(const UtdClient &obj) = delete; UtdClient &operator=(const UtdClient &obj) = delete; - std::string Anonymous(const std::string &fileExtension); bool Init(); bool IsHapTokenType(); Status GetCurrentActiveUserId(int32_t& userId); bool IsValidFileExtension(const std::string &fileExtension); bool IsValidMimeType(const std::string &mimeType); Status GetFlexibleTypeDescriptor(const std::string &typeId, std::shared_ptr<TypeDescriptor> &descriptor); - std::string GetTypeIdFromCfg(const std::string &mimeType); + std::string GetTypeIdFromCfg(const std::string &mimeType, const std::string &belongsTo = DEFAULT_TYPE_ID); std::vector<std::string> GetTypeIdsFromCfg(const std::string &mimeType); void UpdateGraph(const std::vector<TypeDescriptorCfg> &customTyepCfgs); + bool TryReloadCustomUtd(); + bool IsBelongingType(const std::string &belongsTo, const std::string &typeId) const; - std::vector<TypeDescriptorCfg> descriptorCfgs_; + std::vector<TypeDescriptorCfg> descriptorCfgs_ {}; std::shared_mutex utdMutex_; + + std::mutex customUtdMutex_; + UtdFileInfo utdFileInfo_; + int64_t lastLoadTime_ {0}; + + std::mutex updateUtdMutex_; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/common/async_task_params.h b/udmf/interfaces/innerkits/common/async_task_params.h index a5ac1c30..84255cb0 100644 --- a/udmf/interfaces/innerkits/common/async_task_params.h +++ b/udmf/interfaces/innerkits/common/async_task_params.h @@ -20,9 +20,6 @@ #include <mutex> #include <string> -#ifndef IOS_PLATFORM -#include "executor_pool.h" -#endif #include "progress_queue.h" #include "unified_types.h" #include "unified_data.h" @@ -47,6 +44,7 @@ public: ProgressListener progressListener; std::string destUri; QueryOption query; + DataLoadInfo acceptableInfo; }; struct AsyncHelper { @@ -54,9 +52,9 @@ struct AsyncHelper { int32_t lastProgress = 0; ProgressIndicator progressIndicator; #ifndef IOS_PLATFORM - ExecutorPool::TaskId invokeHapTask = ExecutorPool::INVALID_TASK_ID; - ExecutorPool::TaskId getDataTask = ExecutorPool::INVALID_TASK_ID; - ExecutorPool::TaskId progressTask = ExecutorPool::INVALID_TASK_ID; + uint64_t invokeHapTask = 0; + uint64_t getDataTask = 0; + uint64_t progressTask = 0; #endif ProgressListener progressListener; FileConflictOptions fileConflictOptions; @@ -66,6 +64,7 @@ struct AsyncHelper { std::string destUri; std::shared_ptr<UnifiedData> data = std::make_shared<UnifiedData>(); ProgressQueue progressQueue; + DataLoadInfo acceptableInfo; }; enum ListenerStatus: int32_t { diff --git a/udmf/interfaces/innerkits/common/error_code.h b/udmf/interfaces/innerkits/common/error_code.h index 6d2e9b0f..bdc8c58c 100644 --- a/udmf/interfaces/innerkits/common/error_code.h +++ b/udmf/interfaces/innerkits/common/error_code.h @@ -17,17 +17,26 @@ #define UDMF_ERROR_CODE_H #include <cstdint> -#include <errors.h> -#include <map> #include <string> #include <unordered_map> namespace OHOS { namespace UDMF { +using ErrCode = int; +constexpr int ERR_OK = 0; +constexpr int SUBSYS_DISTRIBUTEDDATAMNG = 13; + enum UdmfModule { UDMF_MODULE_SERVICE_ID = 0x07, }; +constexpr ErrCode ErrCodeOffset(unsigned int subsystem, unsigned int module = 0) +{ + constexpr int SUBSYTSTEM_BIT_NUM = 21; + constexpr int MODULE_BIT_NUM = 16; + return (subsystem << SUBSYTSTEM_BIT_NUM) | (module << MODULE_BIT_NUM); +} + // UDMF error offset, used only in this file. constexpr ErrCode UDMF_ERR_OFFSET = ErrCodeOffset(SUBSYS_DISTRIBUTEDDATAMNG, UDMF_MODULE_SERVICE_ID); @@ -48,6 +57,8 @@ enum Status : int32_t { E_COPY_FILE_FAILED, E_IDEMPOTENT_ERROR, E_COPY_CANCELED, + E_DB_CORRUPTED, + E_JSON_CONVERT_FAILED, E_BUTT, }; diff --git a/udmf/interfaces/innerkits/common/progress_queue.h b/udmf/interfaces/innerkits/common/progress_queue.h index 506630f0..995d7595 100644 --- a/udmf/interfaces/innerkits/common/progress_queue.h +++ b/udmf/interfaces/innerkits/common/progress_queue.h @@ -39,7 +39,7 @@ public: private: bool cancelFlag_ = false; bool clearableFlag_ = true; - std::queue<ProgressInfo> queue_; + std::queue<ProgressInfo> queue_ {}; mutable std::mutex mutex_; }; diff --git a/udmf/interfaces/innerkits/common/unified_key.h b/udmf/interfaces/innerkits/common/unified_key.h index dcff9fb9..abef9183 100644 --- a/udmf/interfaces/innerkits/common/unified_key.h +++ b/udmf/interfaces/innerkits/common/unified_key.h @@ -31,10 +31,12 @@ struct API_EXPORT UnifiedKey { std::string bundleName; std::string groupId; std::string GetUnifiedKey(); - std::string GetPropertyKey() const; + std::string GetKeyCommonPrefix() const; bool IsValid(); void PreliminaryWork(); - bool CheckCharacter(std::string data, std::bitset<MAX_BIT_SIZE> rule); + bool CheckCharacter(const std::string_view& data, const std::bitset<MAX_BIT_SIZE> &rule); + bool ExtractAndValidateSegment(std::string_view& data, std::string& field, + const std::bitset<MAX_BIT_SIZE>& rule, const std::string& name); }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/common/unified_meta.h b/udmf/interfaces/innerkits/common/unified_meta.h index 6c7e692e..3b185f08 100644 --- a/udmf/interfaces/innerkits/common/unified_meta.h +++ b/udmf/interfaces/innerkits/common/unified_meta.h @@ -28,6 +28,7 @@ #include "pixel_map.h" #include "string_ex.h" #include "want.h" +#include "unified_key.h" namespace OHOS { namespace UDMF { @@ -535,13 +536,14 @@ enum UDType : int32_t { OPENHARMONY_GOBRUSH, OPENHARMONY_GOBRUSHES, OPENHARMONY_GOCOLOR, + OPENHARMONY_DLP, UD_BUTT }; struct UtdType { - int32_t UtdEnum; - const char *UtdEnumName; - const char *UtdId; + int32_t UtdEnum {0}; + const char *UtdEnumName {nullptr}; + const char *UtdId {nullptr}; }; namespace UtdUtils { @@ -563,33 +565,77 @@ enum Intention : int32_t { UD_INTENTION_BASE = 0, UD_INTENTION_DRAG, UD_INTENTION_DATA_HUB, + UD_INTENTION_SYSTEM_SHARE, + UD_INTENTION_PICKER, + UD_INTENTION_MENU, UD_INTENTION_BUTT, }; -static const std::unordered_map<int32_t, std::string> UD_INTENTION_MAP { +static const std::map<int32_t, std::string> UD_INTENTION_MAP { { UD_INTENTION_DRAG, "drag" }, { UD_INTENTION_DATA_HUB, "DataHub" }, + { UD_INTENTION_SYSTEM_SHARE, "SystemShare" }, + { UD_INTENTION_PICKER, "Picker" }, + { UD_INTENTION_MENU, "Menu" }, }; -static const std::unordered_map<int32_t, std::string> UD_SYSTEM_INTENTION_MAP { +static const std::map<int32_t, std::string> UD_SYSTEM_INTENTION_MAP { { UD_INTENTION_DRAG, "Drag" }, }; -static const std::unordered_map<int32_t, std::string> JS_UD_INTENTION_NAME_MAP { +static const std::map<int32_t, std::string> JS_UD_INTENTION_NAME_MAP { { UD_INTENTION_DATA_HUB, "DATA_HUB" }, { UD_INTENTION_DRAG, "DRAG" }, + { UD_INTENTION_SYSTEM_SHARE, "SYSTEM_SHARE" }, + { UD_INTENTION_PICKER, "PICKER" }, + { UD_INTENTION_MENU, "MENU" }, + +}; + +enum Visibility : int32_t { + VISIBILITY_ALL = 0, + VISIBILITY_OWN_PROCESS, + VISIBILITY_BUTT, +}; + +static const std::map<int32_t, std::string> UD_VISIBILITY_MAP { + { VISIBILITY_ALL, "ALL" }, + { VISIBILITY_OWN_PROCESS, "OWN_PROCESS" }, +}; + +enum Uds_Type : int32_t { + UDS_PLAIN_TEXT = 0, + UDS_HYPERLINK, + UDS_HTML, + UDS_APP_ITEM, + UDS_CONTENT_FORM, + UDS_FORM, + UDS_FILE_URI, + UDS_PIXEL_MAP, + UDS_OTHER +}; + +static const std::map<std::string, Uds_Type> UDS_UTD_TYPE_MAP { + { "general.plain-text", Uds_Type::UDS_PLAIN_TEXT }, + { "general.hyperlink", Uds_Type::UDS_HYPERLINK }, + { "general.html", Uds_Type::UDS_HTML }, + { "openharmony.app-item", Uds_Type::UDS_APP_ITEM }, + { "general.content-form", Uds_Type::UDS_CONTENT_FORM }, + { "openharmony.form", Uds_Type::UDS_FORM }, + { "general.file-uri", Uds_Type::UDS_FILE_URI }, + { "openharmony.pixel-map", Uds_Type::UDS_PIXEL_MAP }, }; enum ShareOptions : int32_t { - IN_APP, + IN_APP = 0, CROSS_APP, CROSS_DEVICE, SHARE_OPTIONS_BUTT, }; struct AppShareOption { - int32_t enumNum; - const char *enumStr; + int32_t enumNum {0}; + const char *enumStr {nullptr}; }; namespace ShareOptionsUtil { @@ -606,8 +652,16 @@ public: static size_t GetDetailsSize(UDDetails &details); static bool API_EXPORT IsPersist(const Intention &intention); static bool API_EXPORT IsPersist(const std::string &intention); + static bool API_EXPORT IsPersist(const int32_t &visibility); static Intention API_EXPORT GetIntentionByString(const std::string &intention); - static bool API_EXPORT IsValidOptions(const std::string &key, std::string &intention); + static bool API_EXPORT IsValidOptions(UnifiedKey &key, const std::string &intention); + static bool API_EXPORT IsValidOptions(UnifiedKey &key, const std::string &intention, + const std::string &validIntention); + static bool IsFileMangerIntention(const std::string &intention); + static std::string FindIntentionMap(const Intention &queryintention); + static bool IsValidOptionsNonDrag(UnifiedKey &key, const std::string &intention); + static std::string GetBelongsToFileType(const std::string &utdId); + static bool IsFilterFileType(const std::string &type); }; struct Object; @@ -626,7 +680,7 @@ struct Object { return false; } - std::map<std::string, ValueType> value_; + std::map<std::string, ValueType> value_ {}; }; namespace ObjectUtils { diff --git a/udmf/interfaces/innerkits/common/unified_types.h b/udmf/interfaces/innerkits/common/unified_types.h index 18ddc287..58329b76 100644 --- a/udmf/interfaces/innerkits/common/unified_types.h +++ b/udmf/interfaces/innerkits/common/unified_types.h @@ -33,20 +33,25 @@ enum DataStatus : int32_t { }; struct Summary { - std::map<std::string, int64_t> summary; - int64_t totalSize; + std::map<std::string, int64_t> summary {}; + std::map<std::string, int64_t> specificSummary {}; + std::map<std::string, std::vector<int32_t>> summaryFormat {}; + // If version value is 1, it means it contains the format variable; + // otherwise(not set or 0), it means it does not contain. + int32_t version {1}; + int64_t totalSize {0}; }; struct Privilege { - uint32_t tokenId; + uint32_t tokenId {0}; std::string readPermission; std::string writePermission; }; struct Runtime { UnifiedKey key; - bool isPrivate {}; - std::vector<Privilege> privileges; + bool isPrivate {false}; + std::vector<Privilege> privileges{}; // time when the data is created time_t createTime {}; // name of the package for creating data @@ -54,16 +59,18 @@ struct Runtime { // current data status DataStatus dataStatus { WORKING }; // current data version - std::int32_t dataVersion {}; + std::int32_t dataVersion {0}; // time when the data is last modified time_t lastModifiedTime {}; // time when data is written to the udmf std::string createPackage; // device ID of the data source std::string deviceId; - std::uint32_t recordTotalNum {}; - uint32_t tokenId; + std::uint32_t recordTotalNum {0}; + uint32_t tokenId {0}; std::string sdkVersion; + Visibility visibility {}; + std::string appId; }; /* @@ -72,6 +79,7 @@ struct Runtime { struct CustomOption { Intention intention {}; uint32_t tokenId {}; + Visibility visibility {}; }; /* @@ -80,7 +88,7 @@ struct CustomOption { struct QueryOption { std::string key; Intention intention {}; - uint32_t tokenId {}; + uint32_t tokenId {0}; }; enum AsyncTaskStatus : uint32_t { @@ -103,8 +111,8 @@ struct AsyncProcessInfo { }; struct ProgressInfo { - int32_t progress = 0; - int32_t progressStatus; + int32_t progress {0}; + int32_t progressStatus {0}; Status errorCode; std::string srcDevName; }; @@ -115,6 +123,26 @@ struct UriInfo { std::string dfsUri; uint32_t position; }; + +struct DataLoadInfo { + std::string sequenceKey; + std::set<std::string> types {}; + uint32_t recordCount {0}; +}; + +using LoadHandler = std::function<void(const std::string &udKey, const DataLoadInfo &dataLoadInfo)>; + +struct DataLoadParams { + LoadHandler loadHandler; + DataLoadInfo dataLoadInfo; +}; + +struct DelayGetDataInfo { + uint32_t tokenId {0}; +#ifndef CROSS_PLATFORM + sptr<IRemoteObject> dataCallback; +#endif +}; } // namespace UDMF } // namespace OHOS #endif // UDMF_UNIFIED_TYPES_H \ No newline at end of file diff --git a/udmf/interfaces/innerkits/convert/data_params_conversion.h b/udmf/interfaces/innerkits/convert/data_params_conversion.h index 3427c07d..fedf27c9 100644 --- a/udmf/interfaces/innerkits/convert/data_params_conversion.h +++ b/udmf/interfaces/innerkits/convert/data_params_conversion.h @@ -24,6 +24,8 @@ class DataParamsConversion { public: static Status API_EXPORT GetInnerDataParams(OH_UdmfGetDataParams &ndkDataParams, QueryOption &query, GetDataParams &dataParams); + static Status API_EXPORT GetDataLoaderParams(const OH_UdmfDataLoadParams &ndkDataParams, + DataLoadParams &dataLoadParams); }; } diff --git a/udmf/interfaces/innerkits/convert/ndk_data_conversion.h b/udmf/interfaces/innerkits/convert/ndk_data_conversion.h index 9be03603..931a7ff9 100644 --- a/udmf/interfaces/innerkits/convert/ndk_data_conversion.h +++ b/udmf/interfaces/innerkits/convert/ndk_data_conversion.h @@ -22,11 +22,13 @@ #include "error_code.h" namespace OHOS::UDMF { - class NdkDataConversion { - public: - static Status API_EXPORT GetNativeUnifiedData(OH_UdmfData* ndkData, std::shared_ptr<UnifiedData>& data); - static Status API_EXPORT GetNdkUnifiedData(std::shared_ptr<UnifiedData> data, OH_UdmfData* ndkData); - }; +class NdkDataConversion { +public: + static Status API_EXPORT GetNativeUnifiedData(OH_UdmfData* ndkData, std::shared_ptr<UnifiedData>& data); + static Status API_EXPORT GetNdkUnifiedData(std::shared_ptr<UnifiedData> data, OH_UdmfData* ndkData); + static char** StrVectorToTypesArray(const std::vector<std::string>& strVector); + static void DestroyStringArray(char**& bufArray, unsigned int& count); +}; } #endif // UDMF_DATA_CONVERSION_H \ No newline at end of file diff --git a/udmf/interfaces/innerkits/data/application_defined_record.h b/udmf/interfaces/innerkits/data/application_defined_record.h index 6d0bf030..d0d83f65 100644 --- a/udmf/interfaces/innerkits/data/application_defined_record.h +++ b/udmf/interfaces/innerkits/data/application_defined_record.h @@ -38,7 +38,7 @@ public: void InitObject() override; protected: std::string applicationDefinedType; - std::vector<uint8_t> rawData_; + std::vector<uint8_t> rawData_ {}; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/audio.h b/udmf/interfaces/innerkits/data/audio.h index 5dff5eaa..84aec635 100644 --- a/udmf/interfaces/innerkits/data/audio.h +++ b/udmf/interfaces/innerkits/data/audio.h @@ -25,6 +25,7 @@ public: API_EXPORT Audio(); explicit API_EXPORT Audio(const std::string &uri); API_EXPORT Audio(UDType type, ValueType value); + void InitObject() override; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/file.h b/udmf/interfaces/innerkits/data/file.h index f533990b..5b72fce8 100644 --- a/udmf/interfaces/innerkits/data/file.h +++ b/udmf/interfaces/innerkits/data/file.h @@ -25,7 +25,6 @@ public: API_EXPORT File(); explicit API_EXPORT File(const std::string &uri); API_EXPORT File(UDType type, ValueType value); - void API_EXPORT SetType(const UDType &type); int64_t API_EXPORT GetSize() override; std::string API_EXPORT GetUri() const; @@ -41,7 +40,7 @@ public: protected: std::string oriUri_; std::string remoteUri_; - UDDetails details_; + UDDetails details_ {}; std::string fileType_; }; } // namespace UDMF diff --git a/udmf/interfaces/innerkits/data/flexible_type.h b/udmf/interfaces/innerkits/data/flexible_type.h index b5b9303f..b5bfd8e1 100644 --- a/udmf/interfaces/innerkits/data/flexible_type.h +++ b/udmf/interfaces/innerkits/data/flexible_type.h @@ -36,6 +36,8 @@ public: const std::string &belongsTo); static constexpr size_t MAX_TYPE_SIZE = 128; static constexpr size_t ATTRIBUTE_PAIR_SIZE = 2; +private: + static std::vector<std::string> StrSplit(const std::string &str, const std::string &delimiter); }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/folder.h b/udmf/interfaces/innerkits/data/folder.h index d8df8604..9ff7fb34 100644 --- a/udmf/interfaces/innerkits/data/folder.h +++ b/udmf/interfaces/innerkits/data/folder.h @@ -25,6 +25,7 @@ public: API_EXPORT Folder(); explicit API_EXPORT Folder(const std::string &uri); API_EXPORT Folder(UDType type, ValueType value); + void InitObject() override; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/html.h b/udmf/interfaces/innerkits/data/html.h index f3bd188c..4f2b995a 100644 --- a/udmf/interfaces/innerkits/data/html.h +++ b/udmf/interfaces/innerkits/data/html.h @@ -35,7 +35,6 @@ public: void API_EXPORT SetPlainContent(const std::string &htmlContent); void InitObject() override; - static bool CheckValue(const ValueType &value); private: std::string htmlContent_; std::string plainContent_; diff --git a/udmf/interfaces/innerkits/data/image.h b/udmf/interfaces/innerkits/data/image.h index d76525d4..f8adb610 100644 --- a/udmf/interfaces/innerkits/data/image.h +++ b/udmf/interfaces/innerkits/data/image.h @@ -26,6 +26,7 @@ public: API_EXPORT Image(); explicit API_EXPORT Image(const std::string &uri); API_EXPORT Image(UDType type, ValueType value); + void InitObject() override; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/link.h b/udmf/interfaces/innerkits/data/link.h index 79aaaef7..cd69542c 100644 --- a/udmf/interfaces/innerkits/data/link.h +++ b/udmf/interfaces/innerkits/data/link.h @@ -36,7 +36,6 @@ public: void API_EXPORT SetDescription(const std::string &description); void InitObject() override; - static bool CheckValue(const ValueType &value); private: std::string url_; std::string description_; diff --git a/udmf/interfaces/innerkits/data/plain_text.h b/udmf/interfaces/innerkits/data/plain_text.h index cbfbd4df..f13eebe9 100644 --- a/udmf/interfaces/innerkits/data/plain_text.h +++ b/udmf/interfaces/innerkits/data/plain_text.h @@ -34,7 +34,6 @@ public: void API_EXPORT SetAbstract(const std::string &abstract); void InitObject() override; - static bool CheckValue(const ValueType &value); private: std::string content_; std::string abstract_; diff --git a/udmf/interfaces/innerkits/data/system_defined_appitem.h b/udmf/interfaces/innerkits/data/system_defined_appitem.h index 61b3dc35..5b8ec872 100644 --- a/udmf/interfaces/innerkits/data/system_defined_appitem.h +++ b/udmf/interfaces/innerkits/data/system_defined_appitem.h @@ -44,7 +44,6 @@ public: UDDetails API_EXPORT GetItems(); void InitObject() override; - static bool CheckValue(const ValueType &value); private: std::string appId_; std::string appName_; diff --git a/udmf/interfaces/innerkits/data/system_defined_pixelmap.h b/udmf/interfaces/innerkits/data/system_defined_pixelmap.h index b37dc05d..74d48541 100644 --- a/udmf/interfaces/innerkits/data/system_defined_pixelmap.h +++ b/udmf/interfaces/innerkits/data/system_defined_pixelmap.h @@ -33,7 +33,10 @@ public: void InitObject() override; private: - std::vector<uint8_t> rawData_; + std::shared_ptr<Media::PixelMap> GetPixelMapFromRawData(); + void ParseInfoFromPixelMap(std::shared_ptr<OHOS::Media::PixelMap> pixelMap); + + std::vector<uint8_t> rawData_ {}; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/system_defined_record.h b/udmf/interfaces/innerkits/data/system_defined_record.h index 14a6b881..72b09235 100644 --- a/udmf/interfaces/innerkits/data/system_defined_record.h +++ b/udmf/interfaces/innerkits/data/system_defined_record.h @@ -35,7 +35,7 @@ public: void InitObject() override; protected: - UDDetails details_; + UDDetails details_ {}; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/text.h b/udmf/interfaces/innerkits/data/text.h index ec3a678e..2aea3bf5 100644 --- a/udmf/interfaces/innerkits/data/text.h +++ b/udmf/interfaces/innerkits/data/text.h @@ -35,7 +35,7 @@ public: void InitObject() override; protected: - UDDetails details_; + UDDetails details_ {}; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/type_descriptor.h b/udmf/interfaces/innerkits/data/type_descriptor.h index 27652dcc..da87ab71 100644 --- a/udmf/interfaces/innerkits/data/type_descriptor.h +++ b/udmf/interfaces/innerkits/data/type_descriptor.h @@ -20,7 +20,6 @@ #include <set> #include <vector> #include <map> -#include <memory> #include "error_code.h" #include "utd_common.h" #include "visibility.h" @@ -50,9 +49,9 @@ private: bool CmpFlexibleTypeLevel(const std::string higherLevelTypeId, bool isFlexibleType); std::string typeId_; - std::vector<std::string> belongingToTypes_; - std::vector<std::string> filenameExtensions_; - std::vector<std::string> mimeTypes_; + std::vector<std::string> belongingToTypes_ {}; + std::vector<std::string> filenameExtensions_ {}; + std::vector<std::string> mimeTypes_ {}; std::string description_; std::string referenceURL_; std::string iconFile_; diff --git a/udmf/interfaces/innerkits/data/unified_data.h b/udmf/interfaces/innerkits/data/unified_data.h index f0f36917..ca59d320 100644 --- a/udmf/interfaces/innerkits/data/unified_data.h +++ b/udmf/interfaces/innerkits/data/unified_data.h @@ -59,7 +59,7 @@ public: void SetChannelName(const std::string &name); std::vector<std::string> GetFileUris() const; bool API_EXPORT IsNeedTransferToEntries() const; - void API_EXPORT TransferToEntries(UnifiedData &data); + void API_EXPORT ConvertRecordsToEntries(); std::string API_EXPORT GetSdkVersion() const; void API_EXPORT SetSdkVersion(const std::string &version); @@ -72,7 +72,7 @@ private: uint32_t recordId_ = 0; std::string channelName_; std::shared_ptr<Runtime> runtime_; - std::vector<std::shared_ptr<UnifiedRecord>> records_; + std::vector<std::shared_ptr<UnifiedRecord>> records_ {}; std::shared_ptr<UnifiedDataProperties> properties_; std::string sdkVersion_; }; diff --git a/udmf/interfaces/innerkits/data/unified_data_helper.h b/udmf/interfaces/innerkits/data/unified_data_helper.h index 1b90cb4c..5d76a3e4 100644 --- a/udmf/interfaces/innerkits/data/unified_data_helper.h +++ b/udmf/interfaces/innerkits/data/unified_data_helper.h @@ -30,13 +30,17 @@ public: static bool Unpack(UnifiedData &data); static void GetSummary(const UnifiedData &data, Summary &summary); static int32_t ProcessBigData(UnifiedData &data, Intention intention, bool isSaInvoke); + static void GetSummaryFromLoadInfo(const DataLoadInfo &dataLoadInfo, Summary &summary); private: static void CreateDirIfNotExist(const std::string& dirPath, const mode_t& mode); static bool SaveUDataToFile(const std::string &dataFile, UnifiedData &data); static bool LoadUDataFromFile(const std::string &dataFile, UnifiedData &data); static void CalRecordSummary(std::map<std::string, ValueType> &entries, Summary &summary); + static void FillSummaryFormat(const std::string &utdId, const std::string &specificType, Summary &summary); static void ProcessTypeId(const ValueType &value, std::string &typeId); static std::string GetRootPath(); + static bool FileClose(std::FILE *file, bool status); + static void UpgradeToParentType(std::string &typeId); private: static std::string rootPath_; diff --git a/udmf/interfaces/innerkits/data/unified_data_properties.h b/udmf/interfaces/innerkits/data/unified_data_properties.h index 565faf12..b75fd903 100644 --- a/udmf/interfaces/innerkits/data/unified_data_properties.h +++ b/udmf/interfaces/innerkits/data/unified_data_properties.h @@ -24,8 +24,8 @@ public: std::string tag; AAFwk::WantParams extras; ShareOptions shareOptions = CROSS_DEVICE; - std::int64_t timestamp; - bool isRemote; + std::int64_t timestamp {0}; + bool isRemote {false}; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/data/unified_record.h b/udmf/interfaces/innerkits/data/unified_record.h index cbb13473..1d09889d 100644 --- a/udmf/interfaces/innerkits/data/unified_record.h +++ b/udmf/interfaces/innerkits/data/unified_record.h @@ -52,7 +52,10 @@ public: void API_EXPORT SetUtdId(const std::string &utdId); std::set<std::string> API_EXPORT GetUtdIds() const; + std::set<std::string> API_EXPORT GetUtdIdsWithAddFileType(bool isSpecific) const; std::string API_EXPORT GetUtdId() const; + void API_EXPORT SetUtdId2(const std::string &utdId); + std::string API_EXPORT GetUtdId2() const; bool API_EXPORT HasType(const std::string &utdId) const; void API_EXPORT AddEntry(const std::string &utdId, ValueType &&value); @@ -72,7 +75,6 @@ public: void API_EXPORT SetChannelName(const std::string &channelName); virtual void InitObject(); - bool HasObject(); bool HasFileType(std::string &fileUri) const; void SetFileUri(const std::string &fileUri); @@ -83,14 +85,14 @@ public: protected: UDType dataType_; std::string utdId_; + std::string utdId2_; ValueType value_; - bool hasObject_ = false; private: - void AddFileUriType(std::set<std::string> &utdIds, const std::shared_ptr<Object> &fileUri) const; + void AddFileUriType(std::set<std::string> &utdIds, const std::shared_ptr<Object> &fileUri, bool isSpecific) const; std::string uid_; // unique identifier std::shared_ptr<std::map<std::string, ValueType>> entries_ = std::make_shared<std::map<std::string, ValueType>>(); - std::vector<UriInfo> uris_; + std::vector<UriInfo> uris_ {}; uint32_t dataId_ = 0; uint32_t recordId_ = 0; std::string channelName_; diff --git a/udmf/interfaces/innerkits/data/video.h b/udmf/interfaces/innerkits/data/video.h index a6d623a5..fe59e837 100644 --- a/udmf/interfaces/innerkits/data/video.h +++ b/udmf/interfaces/innerkits/data/video.h @@ -25,6 +25,7 @@ public: Video(); explicit Video(const std::string &uri); Video(UDType type, ValueType value); + void InitObject() override; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/dynamic/pixelmap_loader.h b/udmf/interfaces/innerkits/dynamic/pixelmap_loader.h new file mode 100644 index 00000000..c6c7e9d9 --- /dev/null +++ b/udmf/interfaces/innerkits/dynamic/pixelmap_loader.h @@ -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. + */ + +#ifndef PIXELMAP_LOADER +#define PIXELMAP_LOADER + +#include <functional> +#include <memory> +#include <optional> +#include "pixel_map.h" + +namespace OHOS::UDMF { + +struct PixelMapDetails { + int32_t width = 0; + int32_t height = 0; + int32_t pixelFormat = 0; + int32_t alphaType = 0; + // Use as an input parameter. To avoid copying, pass a reference. + std::optional<std::reference_wrapper<std::vector<uint8_t>>> rawData; + // Use as an output parameter. + std::optional<std::vector<uint8_t>> rawDataResult; +}; + +typedef OHOS::Media::PixelMap *(*LoadDecodeTlv)(const PixelMapDetails); +typedef bool (*LoadEncodeTlv)(const OHOS::Media::PixelMap *, PixelMapDetails *); +typedef OHOS::Media::PixelMap *(*LoadGetPixelMapFromRawData)(const PixelMapDetails); +typedef PixelMapDetails *(*LoadParseInfoFromPixelMap)(OHOS::Media::PixelMap *); + +class PixelMapLoader { +public: + PixelMapLoader(); + + std::shared_ptr<OHOS::Media::PixelMap> DecodeTlv(std::vector<uint8_t> &buff); + bool EncodeTlv(const std::shared_ptr<OHOS::Media::PixelMap> pixelmap, std::vector<uint8_t> &buff); + std::shared_ptr<OHOS::Media::PixelMap> GetPixelMapFromRawData(const PixelMapDetails &details); + std::shared_ptr<PixelMapDetails> ParseInfoFromPixelMap(const std::shared_ptr<OHOS::Media::PixelMap> pixelMap); + +private: + class SoAutoUnloadManager { + public: + static std::shared_ptr<void> GetHandler(); + private: + static std::weak_ptr<void> weakHandler_; + static std::mutex mutex_; + }; + + std::shared_ptr<void> handler_; +}; + +} // namespace OHOS::UDMF + +#endif // PIXELMAP_LOADER \ No newline at end of file diff --git a/udmf/interfaces/innerkits/dynamic/pixelmap_wrapper.h b/udmf/interfaces/innerkits/dynamic/pixelmap_wrapper.h new file mode 100644 index 00000000..1e2bce12 --- /dev/null +++ b/udmf/interfaces/innerkits/dynamic/pixelmap_wrapper.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 PIXELMAP_WRAPPER +#define PIXELMAP_WRAPPER + +#include "pixel_map.h" +#include "pixelmap_loader.h" + +namespace OHOS::UDMF { +#ifdef __cplusplus +extern "C" { +#endif + +OHOS::Media::PixelMap *DecodeTlv(const PixelMapDetails details); +bool EncodeTlv(const OHOS::Media::PixelMap *pixelMap, PixelMapDetails *details); +OHOS::Media::PixelMap *GetPixelMapFromRawData(const PixelMapDetails details); +PixelMapDetails *ParseInfoFromPixelMap(OHOS::Media::PixelMap *pixelMap); + +#ifdef __cplusplus +}; +#endif +} // OHOS::UDMF + +#endif \ No newline at end of file diff --git a/udmf/interfaces/jskits/BUILD.gn b/udmf/interfaces/jskits/BUILD.gn index 12a5c2e7..3f24f253 100644 --- a/udmf/interfaces/jskits/BUILD.gn +++ b/udmf/interfaces/jskits/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2022-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 @@ -18,28 +18,14 @@ config("udmf_napi_config") { "${udmf_interfaces_path}/innerkits/client", "${udmf_interfaces_path}/innerkits/common", "${udmf_interfaces_path}/innerkits/data", + "${udmf_interfaces_path}/innerkits/include", "${udmf_interfaces_path}/jskits/common", "${udmf_interfaces_path}/jskits/data", - "${udmf_framework_path}/common", "${udmf_framework_path}/innerkits/service", - - "//third_party/libuv/include", - "//third_party/node/src", - - "${aafwk_inner_api_path}/ability_manager/include", - "${aafwk_kits_path}/appkit/native/app/include/", - "${aafwk_kits_path}/ability/native/include", - "${aafwk_napi_path}/inner/napi_common", - "${aafwk_service_path}/abilitymgr/include", - "${aafwk_service_path}/common/include", ] } -config("aip_core_napi_config") { - include_dirs = [ "${udmf_interfaces_path}/jskits/intelligence" ] -} - ohos_shared_library("unifieddatachannel_napi") { branch_protector_ret = "pac_ret" sanitize = { @@ -52,6 +38,7 @@ ohos_shared_library("unifieddatachannel_napi") { sources = [ "${udmf_framework_path}/jskitsimpl/data/application_defined_record_napi.cpp", "${udmf_framework_path}/jskitsimpl/data/audio_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/data_load_params_napi.cpp", "${udmf_framework_path}/jskitsimpl/data/file_napi.cpp", "${udmf_framework_path}/jskitsimpl/data/folder_napi.cpp", "${udmf_framework_path}/jskitsimpl/data/get_data_params_napi.cpp", @@ -78,7 +65,6 @@ ohos_shared_library("unifieddatachannel_napi") { public_configs = [ ":udmf_napi_config" ] deps = [ - "${third_party_path}/bounds_checking_function:libsec_shared", "../innerkits:udmf_client", "../innerkits:utd_client", "../jskits:udmf_js_common", @@ -125,7 +111,6 @@ ohos_shared_library("uniformtypedescriptor_napi") { public_configs = [ ":udmf_napi_config" ] deps = [ - "${third_party_path}/bounds_checking_function:libsec_shared", "../innerkits:udmf_client", "../innerkits:utd_client", "../jskits:udmf_js_common", @@ -133,6 +118,7 @@ ohos_shared_library("uniformtypedescriptor_napi") { external_deps = [ "ability_runtime:abilitykit_native", + "ability_runtime:napi_common", "hilog:libhilog", "ipc:ipc_core", "napi:ace_napi", @@ -160,6 +146,7 @@ ohos_shared_library("udmf_data_napi") { sources = [ "${udmf_framework_path}/jskitsimpl/data/application_defined_record_napi.cpp", "${udmf_framework_path}/jskitsimpl/data/audio_napi.cpp", + "${udmf_framework_path}/jskitsimpl/data/data_load_params_napi.cpp", "${udmf_framework_path}/jskitsimpl/data/file_napi.cpp", "${udmf_framework_path}/jskitsimpl/data/folder_napi.cpp", "${udmf_framework_path}/jskitsimpl/data/get_data_params_napi.cpp", @@ -186,7 +173,6 @@ ohos_shared_library("udmf_data_napi") { public_configs = [ ":udmf_napi_config" ] deps = [ - "${third_party_path}/bounds_checking_function:libsec_shared", "../innerkits:udmf_client", "../innerkits:utd_client", "../jskits:udmf_js_common", @@ -237,7 +223,9 @@ ohos_static_library("udmf_js_common") { public_configs = [ ":udmf_napi_config" ] external_deps = [ "ability_runtime:abilitykit_native", + "ability_runtime:napi_common", "hilog:libhilog", + "ipc:ipc_single", "napi:ace_napi", ] public_external_deps = [ "image_framework:image" ] @@ -264,19 +252,59 @@ ohos_shared_library("intelligence_napi") { "${udmf_framework_path}/jskitsimpl/intelligence/image_embedding_napi.cpp", "${udmf_framework_path}/jskitsimpl/intelligence/js_ability.cpp", "${udmf_framework_path}/jskitsimpl/intelligence/native_module_intelligence.cpp", - "${udmf_framework_path}/jskitsimpl/intelligence/retrieval_napi.cpp", "${udmf_framework_path}/jskitsimpl/intelligence/text_embedding_napi.cpp", ] - public_configs = [ ":aip_core_napi_config" ] + include_dirs = [ "${udmf_interfaces_path}/jskits/intelligence" ] - deps = [] + deps = [ "../innerkits/aipcore:aip_core_mgr_static" ] external_deps = [ "ability_runtime:abilitykit_native", "ability_runtime:napi_base_context", "c_utils:utils", "hilog:libhilog", + "ipc:ipc_single", + "napi:ace_napi", + ] + + defines = [ "LOG_DOMAIN = 0xD001660" ] + relative_install_dir = "module/data" + subsystem_name = "distributeddatamgr" + part_name = "udmf" +} + +ohos_shared_library("rag_napi") { + branch_protector_ret = "pac_ret" + + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + + sources = [ + "${udmf_framework_path}/jskitsimpl/intelligence/aip_napi_error.cpp", + "${udmf_framework_path}/jskitsimpl/intelligence/aip_napi_utils.cpp", + "${udmf_framework_path}/jskitsimpl/intelligence/i_aip_core_manager_impl.cpp", + "${udmf_framework_path}/jskitsimpl/intelligence/js_ability.cpp", + "${udmf_framework_path}/jskitsimpl/intelligence/native_module_rag.cpp", + "${udmf_framework_path}/jskitsimpl/intelligence/rag_agent_chatllm_napi.cpp", + "${udmf_framework_path}/jskitsimpl/intelligence/rag_chatllm_impl.cpp", + "${udmf_framework_path}/jskitsimpl/intelligence/rag_session_napi.cpp", + ] + include_dirs = [ "${udmf_interfaces_path}/jskits/intelligence" ] + deps = [ "../innerkits/aipcore:aip_core_mgr_static" ] + cflags_cc = [ "-fvisibility=hidden" ] + external_deps = [ + "ability_runtime:abilitykit_native", + "ability_runtime:extensionkit_native", + "ability_runtime:napi_base_context", + "c_utils:utils", + "hilog:libhilog", "napi:ace_napi", ] diff --git a/udmf/interfaces/jskits/common/napi_data_utils.h b/udmf/interfaces/jskits/common/napi_data_utils.h index eefad858..d126070e 100644 --- a/udmf/interfaces/jskits/common/napi_data_utils.h +++ b/udmf/interfaces/jskits/common/napi_data_utils.h @@ -48,6 +48,10 @@ public: static napi_status GetValue(napi_env env, napi_value in, int32_t &out); static napi_status SetValue(napi_env env, const int32_t &in, napi_value &out); + /* napi_value <-> uint32_t */ + static napi_status GetValue(napi_env env, napi_value in, uint32_t &out); + static napi_status SetValue(napi_env env, const uint32_t &in, napi_value &out); + /* napi_value <-> int64_t */ static napi_status GetValue(napi_env env, napi_value in, int64_t &out); static napi_status SetValue(napi_env env, const int64_t &in, napi_value &out); @@ -80,6 +84,10 @@ public: static napi_status GetValue(napi_env env, napi_value in, std::map<std::string, int64_t> &out); static napi_status SetValue(napi_env env, const std::map<std::string, int64_t> &in, napi_value &out); + /* napi_value <-> std::set<std::string> */ + static napi_status GetValue(napi_env env, napi_value in, std::set<std::string> &out); + static napi_status SetValue(napi_env env, const std::set<std::string> &in, napi_value &out); + /* napi_value <-> UDVariant */ static napi_status GetValue(napi_env env, napi_value in, UDVariant &out); static napi_status SetValue(napi_env env, const UDVariant &in, napi_value &out); @@ -113,6 +121,10 @@ public: /* napi_value <- ProgressInfo */ static napi_status SetValue(napi_env env, const ProgressInfo &in, napi_value &out); + /* napi_value <-> DataLoadInfo */ + static napi_status GetValue(napi_env env, napi_value in, DataLoadInfo &out); + static napi_status SetValue(napi_env env, const DataLoadInfo &in, napi_value &out); + static bool IsTypeForNapiValue(napi_env env, napi_value param, napi_valuetype expectType); static bool IsNull(napi_env env, napi_value value); @@ -123,6 +135,9 @@ public: static napi_value DefineClass(napi_env env, const std::string &name, const napi_property_descriptor *properties, size_t count, napi_callback newcb); + static napi_status GetOptionalNamedProperty(napi_env env, napi_value &obj, const std::string &key, + napi_value &napiValue); + private: enum { /* std::map<key, value> to js::tuple<key, value> */ diff --git a/relational_store/frameworks/js/napi/rdb/include/napi_uv_queue.h b/udmf/interfaces/jskits/data/data_load_params_napi.h similarity index 44% rename from relational_store/frameworks/js/napi/rdb/include/napi_uv_queue.h rename to udmf/interfaces/jskits/data/data_load_params_napi.h index b59c1cb2..9a339860 100644 --- a/relational_store/frameworks/js/napi/rdb/include/napi_uv_queue.h +++ b/udmf/interfaces/jskits/data/data_load_params_napi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 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,35 +13,34 @@ * limitations under the License. */ -#ifndef NAPI_UV_QUEUE_H -#define NAPI_UV_QUEUE_H - -#include <functional> +#ifndef DATA_LOAD_PARAMS_NAPI_H +#define DATA_LOAD_PARAMS_NAPI_H +#include "async_task_params.h" +#include "concurrent_map.h" #include "napi/native_api.h" -#include "napi/native_common.h" #include "napi/native_node_api.h" +#include "visibility.h" +#include <string> -namespace OHOS::RdbJsKit { -class NapiUvQueue { - using NapiArgsGenerator = std::function<void(napi_env env, int &argc, napi_value *argv)>; +namespace OHOS { +namespace UDMF { +class DataLoadParamsNapi { public: - NapiUvQueue(napi_env env, napi_value callback); - - virtual ~NapiUvQueue(); - - bool operator==(napi_value value); - - void CallFunction(NapiArgsGenerator genArgs = NapiArgsGenerator()); + API_EXPORT static bool Convert2NativeValue(napi_env env, napi_value in, DataLoadParams &dataLoadParams); private: - napi_env env_ = nullptr; - napi_ref callback_ = nullptr; - NapiArgsGenerator args; - uv_loop_s *loop_ = nullptr; - - static constexpr int MAX_CALLBACK_ARG_NUM = 6; + struct DataLoadArgs { + std::string udKey; + DataLoadInfo dataLoadInfo; + }; + static napi_value CreateDataLoadInfo(napi_env env, const DataLoadInfo &dataLoadInfo); + static void CallDataLoadHandler(napi_env env, napi_value callback, void *context, void *data); + + static ConcurrentMap<std::string, napi_threadsafe_function> tsfns_; }; -} // namespace OHOS::RdbJsKit -#endif \ No newline at end of file + +} // namespace UDMF +} // namespace OHOS +#endif // DATA_LOAD_PARAMS_NAPI_H \ No newline at end of file diff --git a/udmf/interfaces/jskits/data/unified_data_channel_napi.h b/udmf/interfaces/jskits/data/unified_data_channel_napi.h index 31575669..5664ce9f 100644 --- a/udmf/interfaces/jskits/data/unified_data_channel_napi.h +++ b/udmf/interfaces/jskits/data/unified_data_channel_napi.h @@ -21,6 +21,7 @@ #include "napi/native_api.h" #include "napi/native_node_api.h" #include "udmf_client.h" +#include "unified_key.h" namespace OHOS { namespace UDMF { @@ -36,7 +37,9 @@ private: static napi_value UpdateData(napi_env env, napi_callback_info info); static napi_value QueryData(napi_env env, napi_callback_info info); static napi_value DeleteData(napi_env env, napi_callback_info info); + static napi_value ConvertRecordsToEntries(napi_env env, napi_callback_info info); static napi_status GetNamedProperty(napi_env env, napi_value &obj, const std::string &key, std::string &value); + static napi_status GetOptionalProperty(napi_env env, napi_value &obj, const std::string &key, int32_t &value); static napi_value CreateShareOptions(napi_env env, napi_callback_info info); static napi_value SetAppShareOptions(napi_env env, napi_callback_info info); static napi_value RemoveAppShareOptions(napi_env env, napi_callback_info info); @@ -45,6 +48,8 @@ private: static napi_value CreateFileConflictOptions(napi_env env, napi_callback_info info); static napi_value CreateProgressIndicator(napi_env env, napi_callback_info info); static napi_value CreateListenerStatus(napi_env env, napi_callback_info info); + static bool IsValidOptionInfoNonDrag(UnifiedKey &key, const std::string &intention); + static napi_value CreateVisibility(napi_env env, napi_callback_info info); }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/jskits/data/unified_data_napi.h b/udmf/interfaces/jskits/data/unified_data_napi.h index a3e2d2c4..b8043821 100644 --- a/udmf/interfaces/jskits/data/unified_data_napi.h +++ b/udmf/interfaces/jskits/data/unified_data_napi.h @@ -46,6 +46,8 @@ private: static napi_value SetProperties(napi_env env, napi_callback_info info); static napi_ref NewWithRef(napi_env env, size_t argc, napi_value *argv, void **out, napi_value constructor); static napi_status Unwrap(napi_env env, napi_value in, void **out, napi_value constructor); + static napi_value AttachUnifiedData(napi_env env, void *value, void *); + static void *DetachUnifiedData(napi_env env, void *value, void *); }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/jskits/intelligence/aip_napi_error.h b/udmf/interfaces/jskits/intelligence/aip_napi_error.h index 1dc8bb07..abe39cf0 100644 --- a/udmf/interfaces/jskits/intelligence/aip_napi_error.h +++ b/udmf/interfaces/jskits/intelligence/aip_napi_error.h @@ -17,6 +17,8 @@ #define AIP_NAPI_ERROR_H #include <map> +#include <optional> + #include "napi/native_api.h" #include "napi/native_node_api.h" @@ -27,23 +29,57 @@ enum NativeErrCode : int32_t { NATIVE_DATABASE_ALREADY_CLOSED = 27394078, NATIVE_DATABASE_IS_BUSY = 27394082, NATIVE_DATABASE_WAL_FILE_EXCEEDS_LIMIT = 27394095, - NATIVE_DATABASE_GENERIC_ERROD = 27394103, + NATIVE_DATABASE_GENERIC_ERROR = 27394103, NATIVE_DATABASE_CORRUPTED = 27394104, NATIVE_DATABASE_PERMISSION_DENIED = 27394107, NATIVE_DATABASE_FILE_IS_LOCKED = 27394109, NATIVE_DATABASE_OUT_OF_MEMORY = 27394110, NATIVE_DATABASE_IO_ERROR = 27394112, + NATIVE_E_RECALL_FAILURE = 28114948, - NATIVE_E_RERANK_FAILURE = 28114949, - NATIVE_E_INVALID_NUMBER = 28114950, - NATIVE_E_INVALID_PRIMARY_KEY = 28114951, - NATIVE_E_UNSUPPORTED_COMPOSITE_PRIMARY_KEY = 28114952, - NATIVE_E_EMPTY_STRING_FIELD = 28114953, - NATIVE_E_INVALID_FILTER_INPUT = 28114954, - NATIVE_E_INVALID_RECALL_FIELD = 28114955, - NATIVE_E_HIGH_VECTOR_SIMILARITY_THRESHOLD = 28114956, - NATIVE_E_RERANK_METHOD_MISMATCH = 28114957, - NATIVE_E_EMPTY_PARAMETER = 28114958, + NATIVE_E_RERANK_FAILURE, + NATIVE_E_INVALID_NUMBER, + NATIVE_E_INVALID_PRIMARY_KEY, + NATIVE_E_UNSUPPORTED_COMPOSITE_PRIMARY_KEY, + NATIVE_E_EMPTY_STRING_FIELD, + NATIVE_E_INVALID_FILTER_INPUT, + NATIVE_E_INVALID_RECALL_FIELD, + NATIVE_E_HIGH_VECTOR_SIMILARITY_THRESHOLD, + NATIVE_E_RERANK_METHOD_MISMATCH, + NATIVE_E_EMPTY_PARAMETER, + + GRAPH_RETRIEVAL_E_GDB_NOT_INIT, + GRAPH_RETRIEVAL_E_RDB_NOT_INIT, + GRAPH_RETRIEVAL_E_MEMORY_ALLOC_FAILURE, + GRAPH_RETRIEVAL_E_ALGORITHM_NOT_INIT, + GRAPH_RETRIEVAL_E_RDB_QUERY_FAILURE, + GRAPH_RETRIEVAL_E_GDB_QUERY_FAILURE, + DATABASE_E_GDB_INVALID, + + NATIVE_SUMMARY_E_INVALID_PARAMETERS, + NATIVE_SUMMARY_E_INVALID_RESULT, + NATIVE_SUMMARY_E_INVALID_OUTPUT, + + NATIVE_RAG_E_CONFIG_ERROR, + NATIVE_RAG_E_INSTANCE_EXIST, + NATIVE_RAG_E_INVALID_INPUT, + NATIVE_RAG_E_QUERY_LENGTH_EXCEED, + NATIVE_RAG_E_STREAM_BUSY, + NATIVE_RAG_E_INSTANCE_NOT_EXIST, + NATIVE_RAG_E_PROMPT_ERROR, + NATIVE_RAG_E_LLM_ERROR, + NATIVE_RAG_E_LLM_OCCUPIED, + NATIVE_RAG_E_LLM_TIMEOUT, + NATIVE_RAG_E_LLM_OUTPUT_INVALID, + NATIVE_RAG_E_RETRIEVER_TIMEOUT, + + NATIVE_LLM_E_PARSER_JSON_PARSE, + NATIVE_LLM_E_PARSER_JSON_MEMBER, + NATIVE_LLM_E_REQUEST_MALLOC, + NATIVE_PROMPT_E_PLACEHOLDER_JSON_PARSE, + NATIVE_PROMPT_E_CHAT_TEMP_JSON_TYPE, + NATIVE_PROMPT_E_CHAT_TEMP_EMPTY_MSG, + NATIVE_PROMPT_E_CHAT_TEMP_UPDATE_SYS, }; enum TsErrCode : int32_t { @@ -54,7 +90,7 @@ enum TsErrCode : int32_t { DATABASE_ALREADY_CLOSED = 31300002, DATABASE_IS_BUSY = 31300003, DATABASE_OUT_OF_MEMORY = 31300004, - DATABASE_GENERIC_ERROD = 31300100, + DATABASE_GENERIC_ERROR = 31300100, DATABASE_PERMISSION_DENIED = 31300101, DATABASE_FILE_IS_LOCKED = 31300102, DATABASE_IO_ERROR = 31300103, @@ -71,6 +107,16 @@ enum TsErrCode : int32_t { RETRIEVAL_E_HIGH_VECTOR_SIMILARITY_THRESHOLD = 31301008, RETRIEVAL_E_RERANK_METHOD_MISMATCH = 31301009, RETRIEVAL_E_EMPTY_PARAMETER = 31301010, + RAG_E_RAG_COMMON_ERROR = 32800000, + RAG_E_LLM_TIMEOUT = 32800001, + RAG_E_LLM_LOAD_FAILED = 32800002, + RAG_E_LLM_BUSY = 32800003, + RAG_E_LLM_OUTPUT_INVALID = 32800004, + RAG_E_RAG_ALREADY_EXISTS = 32800005, + RAG_E_RAG_BUSY = 32800006, + RAG_E_RAG_ALREADY_CLOSED = 32800007, + RAG_E_RAG_USER_CANCEL = 32800008, + RAG_E_RAG_TIMEOUT = 32800009, }; int32_t ConvertErrCodeNative2Ts(int32_t nativeErrCode); diff --git a/udmf/interfaces/jskits/intelligence/aip_napi_utils.h b/udmf/interfaces/jskits/intelligence/aip_napi_utils.h index 03565a4e..2e736779 100644 --- a/udmf/interfaces/jskits/intelligence/aip_napi_utils.h +++ b/udmf/interfaces/jskits/intelligence/aip_napi_utils.h @@ -17,8 +17,10 @@ #define AIP_NAPI_UTILS_H #include <type_traits> +#include <variant> #include "i_aip_core_manager.h" +#include "rag_chatllm_impl.h" #include "napi/native_api.h" #include "napi/native_node_api.h" @@ -59,6 +61,7 @@ public: static napi_status Convert2Value(napi_env env, napi_value in, double &out); static napi_status Convert2Value(napi_env env, napi_value in, std::string &out); static napi_status Convert2Value(napi_env env, napi_value in, std::vector<float> &out); + static napi_status Convert2Value(napi_env env, napi_value in, napi_ref &out); template <typename T> struct is_shared_ptr : std::false_type {}; @@ -119,6 +122,10 @@ public: static napi_status Convert2Value(napi_env env, const napi_value &in, CryptoParam &cryptoParam); static napi_status Convert2Value(napi_env env, const napi_value &in, ContextParam &context); static napi_status Convert2Value(napi_env env, const napi_value &in, napi_value &out); + static napi_status Convert2Value(napi_env env, const napi_value &in, OptionStruct &out); + static napi_status Convert2Value(napi_env env, const napi_value &in, ConfigStruct &out); + static napi_status Convert2Value(napi_env env, const napi_value &in, std::shared_ptr<IChatLLM> &out); + static napi_status Convert2Value(napi_env env, const napi_value &in, LLMStreamAnswer &out); static napi_status Convert2JSValue(napi_env env, const std::vector<uint8_t> &in, napi_value &out); static napi_status Convert2JSValue(napi_env env, const std::vector<float> &in, napi_value &out); @@ -131,6 +138,8 @@ public: static napi_status Convert2JSValue(napi_env env, const DataIntelligence::RetrievalResponseStruct &in, napi_value &out); static napi_status Convert2JSValue(napi_env env, const DataIntelligence::ItemInfoStruct &in, napi_value &out); + static napi_status Convert2JSValue(napi_env env, const AnswerStruct &in, napi_value &out); + static napi_status Convert2JSValue(napi_env env, const StreamStruct &in, napi_value &out); static napi_status Convert2JSValue(napi_env env, const std::map<std::string, FieldType> &in, napi_value &out); static napi_status Convert2JSValue(napi_env env, const std::map<int32_t, std::map<std::string, RecallScoreStruct>> &in, napi_value &out); diff --git a/relational_store/frameworks/native/gdb/include/hitrace.h b/udmf/interfaces/jskits/intelligence/hitrace.h similarity index 71% rename from relational_store/frameworks/native/gdb/include/hitrace.h rename to udmf/interfaces/jskits/intelligence/hitrace.h index a1bdebd6..44c2cf7a 100644 --- a/relational_store/frameworks/native/gdb/include/hitrace.h +++ b/udmf/interfaces/jskits/intelligence/hitrace.h @@ -13,28 +13,28 @@ * limitations under the License. */ -#ifndef DISTRIBUTEDDATAMGR_NATIVEGDB_HITRACE_H -#define DISTRIBUTEDDATAMGR_NATIVEGDB_HITRACE_H +#ifndef DATA_INTELLIGENCE_HITRACE_H +#define DATA_INTELLIGENCE_HITRACE_H #include <string> #include "hitrace_meter.h" namespace OHOS { -namespace DistributedDataAip { +namespace DataIntelligence { class HiTrace final { public: inline HiTrace(const std::string &value) { - StartTrace(HITRACE_TAG_DISTRIBUTEDDATA, value); + StartTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_TAG_DISTRIBUTEDDATA, value.c_str(), ""); } inline ~HiTrace() { - FinishTrace(HITRACE_TAG_DISTRIBUTEDDATA); + FinishTraceEx(HiTraceOutputLevel::HITRACE_LEVEL_INFO, HITRACE_TAG_DISTRIBUTEDDATA); } }; -} // namespace DistributedDataAip +} // namespace DataIntelligence } // namespace OHOS #endif \ No newline at end of file diff --git a/udmf/interfaces/jskits/intelligence/i_aip_core_manager_impl.h b/udmf/interfaces/jskits/intelligence/i_aip_core_manager_impl.h index 00ef61ea..b26ccfec 100644 --- a/udmf/interfaces/jskits/intelligence/i_aip_core_manager_impl.h +++ b/udmf/interfaces/jskits/intelligence/i_aip_core_manager_impl.h @@ -27,9 +27,7 @@ class IAipCoreManagerImpl : public IAipCoreManager { public: IAipCoreManagerImpl() = default; ~IAipCoreManagerImpl() = default; - int32_t InitRetriever(const RetrievalConfigStruct& retrievalConfig) override; - int32_t Retrieve(const std::string query, const RetrievalConditionStruct &condition, - RetrievalResponseStruct &retrievalResponse) override; + int32_t InitTextModel(const ModelConfigData &config) override; int32_t InitImageModel(const ModelConfigData &config) override; int32_t LoadTextModel() override; @@ -40,6 +38,14 @@ public: int32_t ReleaseImageModel() override; int32_t GetImageEmbedding(std::string uri, std::vector<float> &results) override; int32_t SplitText(std::string text, int32_t size, float overlap, std::vector<std::string> &results) override; + + int32_t CreateRAGSession(const ContextParam &contex, const ConfigStruct &config) override; + int32_t RAGSessionStreamRun(const std::string &question, const OptionStruct &option, + std::function<void(const StreamStruct&, int32_t)> callback) override; + int32_t ReleaseRAGSession() override; + int32_t RAGSessionRun(const std::string &query, const OptionStruct &runOption, AnswerStruct &answer) override; + + bool CheckDeviceType() override; }; } // namespace DataIntelligence } // namespace OHOS diff --git a/udmf/interfaces/jskits/intelligence/js_ability.h b/udmf/interfaces/jskits/intelligence/js_ability.h index 0e1602d1..a381ec12 100644 --- a/udmf/interfaces/jskits/intelligence/js_ability.h +++ b/udmf/interfaces/jskits/intelligence/js_ability.h @@ -32,6 +32,7 @@ public: explicit Context(std::shared_ptr<AbilityRuntime::AbilityContext> abilityContext); std::string GetDatabaseDir(); + std::string GetCacheDir(); int GetSystemDatabaseDir(const std::string &dataGroupId, std::string &databaseDir); std::string GetBundleName(); std::string GetModuleName(); @@ -46,6 +47,7 @@ public: private: int32_t area_ = 0; std::string databaseDir_; + std::string cacheDir_; std::string bundleName_; std::string moduleName_; std::string uri_; diff --git a/relational_store/frameworks/native/gdb/include/db_trace.h b/udmf/interfaces/jskits/intelligence/napi_trace.h similarity index 70% rename from relational_store/frameworks/native/gdb/include/db_trace.h rename to udmf/interfaces/jskits/intelligence/napi_trace.h index b8aea61e..e3d4b599 100644 --- a/relational_store/frameworks/native/gdb/include/db_trace.h +++ b/udmf/interfaces/jskits/intelligence/napi_trace.h @@ -12,20 +12,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef NATIVE_GDB_TRACE_H -#define NATIVE_GDB_TRACE_H +#ifndef DATA_INTELLIGENCE_NAPI_TRACE_H +#define DATA_INTELLIGENCE_NAPI_TRACE_H #define DO_NOTHING -#ifdef DB_TRACE_ON +#ifdef DATA_INTELLIGENCE_TRACE_ON #include "hitrace.h" -#ifndef DISTRIBUTED_DATA_HITRACE -#define DISTRIBUTED_DATA_HITRACE(trace) OHOS::DistributedDataAip::HiTrace hitrace(trace) +#ifndef DATA_INTELLIGENCE_HITRACE +#define DATA_INTELLIGENCE_HITRACE(trace) OHOS::DataIntelligence::HiTrace hitrace(trace) #endif #else -#define DISTRIBUTED_DATA_HITRACE(trace) DO_NOTHING +#define DATA_INTELLIGENCE_HITRACE(trace) DO_NOTHING #endif #endif \ No newline at end of file diff --git a/udmf/interfaces/jskits/intelligence/native_module_intelligence.h b/udmf/interfaces/jskits/intelligence/native_module_intelligence.h index 92826f90..747a6306 100644 --- a/udmf/interfaces/jskits/intelligence/native_module_intelligence.h +++ b/udmf/interfaces/jskits/intelligence/native_module_intelligence.h @@ -19,6 +19,5 @@ #include "image_embedding_napi.h" #include "napi/native_node_api.h" #include "text_embedding_napi.h" -#include "retrieval_napi.h" #endif // NATIVE_MODULE_INTELLIGENCE_H \ No newline at end of file diff --git a/udmf/interfaces/jskits/intelligence/native_module_rag.h b/udmf/interfaces/jskits/intelligence/native_module_rag.h new file mode 100644 index 00000000..7493bfbb --- /dev/null +++ b/udmf/interfaces/jskits/intelligence/native_module_rag.h @@ -0,0 +1,22 @@ +/* + * 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 NATIVE_MODULE_RAG_H + #define NATIVE_MODULE_RAG_H + + #include "napi/native_node_api.h" + #include "rag_session_napi.h" + + #endif // NATIVE_MODULE_RAG_H \ No newline at end of file diff --git a/preferences/frameworks/native/include/hitrace.h b/udmf/interfaces/jskits/intelligence/rag_agent_chatllm_napi.h similarity index 55% rename from preferences/frameworks/native/include/hitrace.h rename to udmf/interfaces/jskits/intelligence/rag_agent_chatllm_napi.h index 50b84122..ceb24582 100644 --- a/preferences/frameworks/native/include/hitrace.h +++ b/udmf/interfaces/jskits/intelligence/rag_agent_chatllm_napi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 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,28 +13,20 @@ * limitations under the License. */ -#ifndef DISTRIBUTEDDATAMGR_PREFERENCES_HITRACE_H -#define DISTRIBUTEDDATAMGR_PREFERENCES_HITRACE_H - -#include <string> - -#include "hitrace_meter.h" +#ifndef RAG_AGENT_CHATLLM_NAPI_H +#define RAG_AGENT_CHATLLM_NAPI_H +#include "napi/native_node_api.h" namespace OHOS { -namespace NativePreferences { -class HiTrace final { -public: - inline HiTrace(const std::string &value) - { - StartTrace(HITRACE_TAG_DISTRIBUTEDDATA, value); - } +namespace DataIntelligence { - inline ~HiTrace() - { - FinishTrace(HITRACE_TAG_DISTRIBUTEDDATA); - } +class RAGAgentChatLLMNapi { +public: + static napi_value Init(napi_env env, napi_value exports); +private: + static napi_value Constructor(napi_env env, napi_callback_info info); + static napi_status InitEnum(napi_env env, napi_value exports); }; -} // namespace NativePreferences +} // namespace DataIntelligence } // namespace OHOS - -#endif \ No newline at end of file +#endif //RAG_AGENT_CHATLLM_NAPI_H diff --git a/udmf/interfaces/jskits/intelligence/rag_chatllm_impl.h b/udmf/interfaces/jskits/intelligence/rag_chatllm_impl.h new file mode 100644 index 00000000..9cb524b0 --- /dev/null +++ b/udmf/interfaces/jskits/intelligence/rag_chatllm_impl.h @@ -0,0 +1,76 @@ +/* +* 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 RAG_CHATLLM_IMPL_H +#define RAG_CHATLLM_IMPL_H +#include <condition_variable> +#include <uv.h> + +#include "napi/native_node_api.h" +#include "i_aip_core_manager.h" + +namespace OHOS { +namespace DataIntelligence { +using ThreadLockInfo = struct ThreadLockInfo { + std::mutex mutex; + std::condition_variable condition; + bool ready = false; +}; + +using WorkParam = struct WorkParam { + // input + std::string query; + std::shared_ptr<LLMStreamCallback> llmStreamCallback; + napi_env env; + napi_ref ref; + // output + napi_status status; + int32_t result; + // lock + std::shared_ptr<ThreadLockInfo> lockInfo; +}; +using StreamCallbackWorkParam = struct StreamCallbackWorkParam { + // input + LLMStreamAnswer answer; + napi_env env; +}; + +class ChatLLM final : public IChatLLM { +public: + ChatLLM(napi_env env, napi_ref streamChatRef); + ~ChatLLM() override; + TsLLMRequestStatus StreamChat(const std::string &query, const LLMStreamCallback &streamCallback) override; + + void SetRef(napi_ref streamChatRef); + napi_ref GetRef(); +private: + static napi_value StreamCallbackFunc(napi_env env, napi_callback_info info); + static void StreamChatCallbackEventFunc(WorkParam *param); + static void CallJSStreamChat(napi_env env, napi_ref ref, WorkParam *llmWorkParam); + static void HandlePromiseValue(napi_env env, napi_value promiseResult, WorkParam *llmWorkParam); + static napi_value PromiseThenCallback(napi_env env, napi_callback_info info); + static napi_value PromiseCatchCallback(napi_env env, napi_callback_info info); + static void NativeCallbackAsync(napi_env env, const LLMStreamAnswer &answer); + + napi_env env_; + napi_ref streamChatRef_; + + static std::shared_ptr<LLMStreamCallback> llmStreamCallback_; + LLMStreamCallback streamCallback_; +}; + +} +} +#endif //RAG_CHATLLM_IMPL_H diff --git a/udmf/interfaces/jskits/intelligence/retrieval_napi.h b/udmf/interfaces/jskits/intelligence/rag_session_napi.h similarity index 31% rename from udmf/interfaces/jskits/intelligence/retrieval_napi.h rename to udmf/interfaces/jskits/intelligence/rag_session_napi.h index 3074714c..7c703508 100644 --- a/udmf/interfaces/jskits/intelligence/retrieval_napi.h +++ b/udmf/interfaces/jskits/intelligence/rag_session_napi.h @@ -13,60 +13,82 @@ * limitations under the License. */ -#ifndef RETRIEVAL_NAPI_H -#define RETRIEVAL_NAPI_H +#ifndef RAG_SESSION_NAPI_H +#define RAG_SESSION_NAPI_H #include <string> -#include <map> #include <uv.h> -#include <refbase.h> #include "i_aip_core_manager.h" +#include "rag_chatllm_impl.h" #include "napi/native_api.h" -#include "napi/native_node_api.h" namespace OHOS { namespace DataIntelligence { -class RetrievalNapi; -struct AsyncGetRetriever { +class RAGSessionNapi; +struct AsyncCreateRAGSession { napi_async_work asyncWork; napi_deferred deferred; - RetrievalConfigStruct config; - IAipCoreManager* retrievalAipCoreManagerPtr; + IAipCoreManager* ragAipCoreManagerPtr; + ContextParam context; + ConfigStruct config; int32_t ret; + napi_value result; }; -struct AsyncRetrieve { + +struct AsyncStreamRun { napi_async_work asyncWork; napi_deferred deferred; - std::string query; - RetrievalConditionStruct retrievalCondition; - IAipCoreManager* retrievalAipCoreManagerPtr; - RetrievalResponseStruct retrievalResponse; - napi_value res; + RAGSessionNapi* sessionNapi; + std::string question; + OptionStruct option; + StreamStruct stream; int32_t ret; }; -class RetrievalNapi { -public: - RetrievalNapi(); - ~RetrievalNapi(); - static napi_value Init(napi_env env, napi_value exports); - static napi_value GetRetriever(napi_env env, napi_callback_info info); - static napi_value Retrieve(napi_env env, napi_callback_info info); - static napi_value RetrieverConstructor(napi_env env, napi_callback_info info); - static napi_value WrapAipCoreManager(napi_env env, IAipCoreManager* retrievalAipCoreManager); +using StreamRunCallbackWorkParam = struct StreamRunCallbackWorkParam { + StreamStruct stream; + int32_t errCode; + napi_env env; + napi_ref ref; + napi_ref thisJsRef; + std::shared_ptr<ThreadLockInfo> lockInfo; +}; +class RAGSessionNapi { +public: + explicit RAGSessionNapi(IAipCoreManager *aipAipCoreManager); + ~RAGSessionNapi(); + static napi_value Init(napi_env env, napi_value exports); private: - static bool LoadAsyncExecution(napi_env env, napi_deferred deferred); - static bool CreateAsyncGetRetrieverExecution(napi_env env, AsyncGetRetriever *asyncGetRetriever); - static bool CreateAsyncRetrieveExecution(napi_env env, AsyncRetrieve *asyncRetrieve); - static void GetRetrieverExecutionCB(napi_env env, void *data); - static void GetRetrieverCompleteCB(napi_env env, napi_status status, void *data); - static void RetrieveExecutionCB(napi_env env, void *data); - static void RetrieveCompleteCB(napi_env env, napi_status status, void *data); - napi_env env_; - static AipCoreManagerHandle retrievalAipCoreMgrHandle_; + static napi_value CreateRAGSession(napi_env env, napi_callback_info info); + static napi_value StreamRun(napi_env env, napi_callback_info info); + static napi_value Close(napi_env env, napi_callback_info info); + static napi_value WrapAipCoreManager(napi_env env, IAipCoreManager* ragAipCoreManager); + static void CreateRAGSessionExecutionCB(napi_env env, void *data); + static void CreateRAGSessionCompleteCB(napi_env env, napi_status status, void *data); + static bool CreateAsyncCreateRAGSession(napi_env env, AsyncCreateRAGSession *asyncCreateRAGSession); + static bool CreateAsyncStreamRunExecution(napi_env env, AsyncStreamRun *asyncStreamRun); + static bool CreateAsyncCloseExecution(napi_env env, AsyncStreamRun *asyncClose); + static void CloseExecutionCB(napi_env env, void *data); + static void CloseCompleteCB(napi_env env, napi_status status, void *data); + static napi_status ParseStreamRunArgs(napi_env env, napi_callback_info info, std::string &question, + OptionStruct &option, RAGSessionNapi **sessionNapi); + static void StreamRunExecutionCB(napi_env env, void *data); + static void StreamRunCompleteCB(napi_env env, napi_status status, void *data); + static void StreamRunCallbackExecute(RAGSessionNapi *session_napi, StreamStruct stream, int32_t errCode); + static void StreamRunCallbackEventFunc(StreamRunCallbackWorkParam *workParam); + static void StreamRunCallbackJSExecute (StreamRunCallbackWorkParam *workParam); + static AipCoreManagerHandle aipAipCoreMgrHandle_; + static napi_ref callbackRef_; + static napi_threadsafe_function tsfn_; + + napi_env env_ = nullptr; + napi_ref ref_ = nullptr; + napi_ref thisJsRef_ = nullptr; + IAipCoreManager *aipAipCoreManager_; }; } // namespace DataIntelligence } // namespace OHOS -#endif // RETRIEVAL_NAPI_H +#endif // RAG_SESSION_NAPI_H + \ No newline at end of file diff --git a/udmf/interfaces/ndk/BUILD.gn b/udmf/interfaces/ndk/BUILD.gn index edf268c8..50520e9d 100644 --- a/udmf/interfaces/ndk/BUILD.gn +++ b/udmf/interfaces/ndk/BUILD.gn @@ -54,6 +54,8 @@ ohos_shared_library("libudmf") { "image_framework:image", "image_framework:image_native", "image_framework:pixelmap", + "ipc:ipc_single", + "kv_store:distributeddata_inner", ] relative_install_dir = "ndk" diff --git a/udmf/interfaces/ndk/data/data_provider_impl.h b/udmf/interfaces/ndk/data/data_provider_impl.h index d3830dc4..9126067d 100644 --- a/udmf/interfaces/ndk/data/data_provider_impl.h +++ b/udmf/interfaces/ndk/data/data_provider_impl.h @@ -33,7 +33,7 @@ public: OH_UdmfRecordProvider* GetInnerProvider(); ValueType GetValueByType(const std::string &utdId) override; private: - OH_UdmfRecordProvider* innerProvider_; + OH_UdmfRecordProvider* innerProvider_ {nullptr}; }; } // namespace UDMF diff --git a/udmf/interfaces/ndk/data/udmf.h b/udmf/interfaces/ndk/data/udmf.h index 84638d3a..155f7916 100644 --- a/udmf/interfaces/ndk/data/udmf.h +++ b/udmf/interfaces/ndk/data/udmf.h @@ -63,11 +63,35 @@ typedef enum Udmf_Intention { /** * @brief The intention is drag. */ - UDMF_INTENTION_DRAG, + UDMF_INTENTION_DRAG = 0, /** * @brief The intention is pasteboard. */ UDMF_INTENTION_PASTEBOARD, + /** + * @brief The intention is data hub. + * + * @since 20 + */ + UDMF_INTENTION_DATA_HUB, + /** + * @brief The intention is system share. + * + * @since 20 + */ + UDMF_INTENTION_SYSTEM_SHARE, + /** + * @brief The intention is picker. + * + * @since 20 + */ + UDMF_INTENTION_PICKER, + /** + * @brief The intention is menu. + * + * @since 20 + */ + UDMF_INTENTION_MENU, } Udmf_Intention; /** @@ -79,7 +103,7 @@ typedef enum Udmf_ShareOption { /** * @brief Invalid share option. */ - SHARE_OPTIONS_INVALID, + SHARE_OPTIONS_INVALID = 0, /** * @brief Allowed to be used in the same application on this device. */ @@ -122,6 +146,23 @@ typedef enum Udmf_ProgressIndicator { UDMF_DEFAULT = 1 } Udmf_ProgressIndicator; +/** + * @brief Describe the visibility range of data + * + * @since 20 + */ +typedef enum Udmf_Visibility { + /** + * @brief The visibility level that specifies that any hap or native can be obtained. + */ + UDMF_ALL = 0, + + /** + * @brief The visibility level that specifies that only data providers can be obtained. + */ + UDMF_OWN_PROCESS +} Udmf_Visibility; + /** * @brief Describes the unified data type. * @@ -173,6 +214,35 @@ typedef struct OH_UdmfGetDataParams OH_UdmfGetDataParams; */ typedef void (*OH_Udmf_DataProgressListener)(OH_Udmf_ProgressInfo* progressInfo, OH_UdmfData* data); +/** + * @brief Describes the optional arguments of data operation + * + * @since 20 + */ +typedef struct OH_UdmfOptions OH_UdmfOptions; + +/** + * @brief Indicates data loading params. + * + * @since 20 + */ +typedef struct OH_UdmfDataLoadParams OH_UdmfDataLoadParams; + +/** + * @brief Indicates data loading information. + * + * @since 20 + */ +typedef struct OH_UdmfDataLoadInfo OH_UdmfDataLoadInfo; + +/** + * @brief Indicates the callback function for loading data. + * + * @param acceptableInfo Indicates the type and number of data that can be accepted by the receiver. + * @return Returns the data to be loaded. + * @since 20 + */ +typedef OH_UdmfData* (*OH_Udmf_DataLoadHandler)(OH_UdmfDataLoadInfo* acceptableInfo); /** * @brief Creation a pointer to the instance of the {@link OH_UdmfData}. @@ -774,6 +844,106 @@ int OH_UdmfProperty_SetExtrasIntParam(OH_UdmfProperty* pThis, const char* key, i int OH_UdmfProperty_SetExtrasStringParam(OH_UdmfProperty* pThis, const char* key, const char* param); +/** + * @brief Creation a pointer to the instance of the {@link OH_UdmfOptions}. + * + * @return If the operation is successful, a pointer to the instance of the {@link OH_UdmfOptions} + * structure is returned. If the operation is failed, nullptr is returned. + * @see OH_UdmfOptions. + * @since 20 + */ +OH_UdmfOptions* OH_UdmfOptions_Create(); + +/** + * @brief Destroy a pointer that points to an instance of {@link OH_UdmfOptions}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @see OH_UdmfOptions. + * @since 20 + */ +void OH_UdmfOptions_Destroy(OH_UdmfOptions* pThis); + +/** + * @brief Get key from the {@link OH_UdmfOptions}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @return Returns a pointer of the value string when input args normally, otherwise return nullptr. + * @see OH_UdmfOptions + * @since 20 + */ +const char* OH_UdmfOptions_GetKey(OH_UdmfOptions* pThis); + +/** + * @brief Set the key to the {@link OH_UdmfOptions}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @param key Represents a new string value of the key. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * @see OH_UdmfOptions Udmf_ErrCode + * @since 20 + */ +int OH_UdmfOptions_SetKey(OH_UdmfOptions* pThis, const char* key); + +/** + * @brief Get intention from the {@link OH_UdmfOptions}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @return Returns {@link Udmf_Intention} value. + * @see OH_UdmfOptions Udmf_Intention + * @since 20 + */ +Udmf_Intention OH_UdmfOptions_GetIntention(OH_UdmfOptions* pThis); + +/** + * @brief Set intention value to {@link OH_UdmfOptions}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @param intention Represents new {@link Udmf_Intention} param. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * @see OH_UdmfOptions Udmf_Intention Udmf_ErrCode. + * @since 20 + */ +int OH_UdmfOptions_SetIntention(OH_UdmfOptions* pThis, Udmf_Intention intention); + +/** + * @brief Reset {@link OH_UdmfOptions} to default. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * @see OH_UdmfOptions Udmf_ErrCode. + * @since 20 + */ +int OH_UdmfOptions_Reset(OH_UdmfOptions* pThis); + +/** + * @brief Get visibility from the {@link OH_UdmfOptions}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @return Returns {@link Udmf_Visibility} value. + * @see OH_UdmfOptions Udmf_Visibility + * @since 20 + */ +Udmf_Visibility OH_UdmfOptions_GetVisibility(OH_UdmfOptions* pThis); + +/** + * @brief Set visibility value to {@link OH_UdmfOptions}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @param visibility Represents new {@link Udmf_Visibility} param. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * @see OH_UdmfOptions Udmf_Visibility Udmf_ErrCode. + * @since 20 + */ +int OH_UdmfOptions_SetVisibility(OH_UdmfOptions* pThis, Udmf_Visibility visibility); + /** * @brief Get {@link OH_UdmfData} data from udmf database. * @@ -788,6 +958,22 @@ int OH_UdmfProperty_SetExtrasStringParam(OH_UdmfProperty* pThis, */ int OH_Udmf_GetUnifiedData(const char* key, Udmf_Intention intention, OH_UdmfData* unifiedData); +/** + * @brief Get {@link OH_UdmfData} data array from udmf database by intention. + * + * @param options Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @param dataArray Represents output params of {@link OH_UdmfData}. + * This pointer needs to be released using the {@link OH_Udmf_DestroyDataArray} function. + * @param dataSize Represents the data count of output params. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * {@link UDMF_ERR} Internal data error. + * @see OH_UdmfData Udmf_Intention Udmf_ErrCode. + * @since 20 + */ +int OH_Udmf_GetUnifiedDataByOptions(OH_UdmfOptions* options, OH_UdmfData** dataArray, unsigned int* dataSize); + /** * @brief Set {@link OH_UdmfData} data to database. * @@ -805,6 +991,63 @@ int OH_Udmf_GetUnifiedData(const char* key, Udmf_Intention intention, OH_UdmfDat int OH_Udmf_SetUnifiedData(Udmf_Intention intention, OH_UdmfData* unifiedData, char* key, unsigned int keyLen); +/** + * @brief Set {@link OH_UdmfData} data to database with options. + * + * @param options Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @param unifiedData Represents a pointer to an instance of {@link OH_UdmfData}. + * @param key Represents return value after set data to database successfully, + * it's memory size not less than {@link UDMF_KEY_BUFFER_LEN}. + * @param keyLen Represents size of key param. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * {@link UDMF_ERR} Internal data error. + * @see OH_UdmfOptions OH_UdmfData Udmf_ErrCode. + * @since 20 + */ +int OH_Udmf_SetUnifiedDataByOptions(OH_UdmfOptions* options, OH_UdmfData *unifiedData, char *key, unsigned int keyLen); + +/** + * @brief Update {@link OH_UdmfData} data to database with options. + * + * @param options Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @param unifiedData Represents a pointer to an instance of {@link OH_UdmfData}. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * {@link UDMF_ERR} Internal data error. + * @see OH_UdmfOptions OH_UdmfData Udmf_ErrCode. + * @since 20 + */ +int OH_Udmf_UpdateUnifiedData(OH_UdmfOptions* options, OH_UdmfData* unifiedData); + +/** + * @brief Delete {@link OH_UdmfData} data of database with options. + * + * @param options Represents a pointer to an instance of {@link OH_UdmfOptions}. + * @param dataArray Represents output params of {@link OH_UdmfData}. + * This pointer needs to be released using the {@link OH_Udmf_DestroyDataArray} function. + * @param dataSize Represents the data count of output params. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * {@link UDMF_ERR} Internal data error. + * @see OH_UdmfData Udmf_Intention Udmf_ErrCode. + * @since 20 + */ +int OH_Udmf_DeleteUnifiedData(OH_UdmfOptions* options, OH_UdmfData** dataArray, unsigned int* dataSize); + +/** + * @brief Destroy data array memory. + * + * @param dataArray Represents a point to {@link OH_UdmfData}. + * @param dataSize Represents data size in list. + * @see OH_UdmfData + * @since 20 + */ +void OH_Udmf_DestroyDataArray(OH_UdmfData** dataArray, unsigned int dataSize); + /** * @brief Gets the progress from the {@OH_Udmf_ProgressInfo}. * @@ -886,6 +1129,115 @@ void OH_UdmfGetDataParams_SetProgressIndicator(OH_UdmfGetDataParams* params, void OH_UdmfGetDataParams_SetDataProgressListener(OH_UdmfGetDataParams* params, const OH_Udmf_DataProgressListener dataProgressListener); +/** + * @brief Sets the acceptable info to the {@OH_UdmfGetDataParams}. + * + * @param params Represents a pointer to an instance of {@link OH_UdmfGetDataParams}. + * @param acceptableInfo Represents a pointer to an instance of {@link OH_UdmfDataLoadInfo}. + * @see OH_UdmfGetDataParams OH_UdmfDataLoadInfo + * @since 20 + */ +void OH_UdmfGetDataParams_SetAcceptableInfo(OH_UdmfGetDataParams* params, OH_UdmfDataLoadInfo* acceptableInfo); + +/** + * @brief Creation a pointer to the instance of the {@link OH_UdmfDataLoadParams}. + * + * @return If the operation is successful, a pointer to the instance of the {@link OH_UdmfDataLoadParams} + * structure is returned. If the operation is failed, nullptr is returned. + * @see OH_UdmfDataLoadParams + * @since 20 + */ +OH_UdmfDataLoadParams* OH_UdmfDataLoadParams_Create(); + +/** + * @brief Destroy a pointer that points to an instance of {@link OH_UdmfDataLoadParams}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfDataLoadParams}. + * @see OH_UdmfDataLoadParams + * @since 20 + */ +void OH_UdmfDataLoadParams_Destroy(OH_UdmfDataLoadParams* pThis); + +/** + * @brief Sets the data load handler to the {@OH_UdmfDataLoadParams}. + * + * @param params Represents a pointer to an instance of {@link OH_UdmfDataLoadParams}. + * @param dataLoadHandler Represents to the data load handler. + * @see OH_UdmfDataLoadParams OH_Udmf_DataLoadHandler + * @since 20 + */ +void OH_UdmfDataLoadParams_SetLoadHandler(OH_UdmfDataLoadParams* params, const OH_Udmf_DataLoadHandler dataLoadHandler); + +/** + * @brief Sets the data load info to the {@OH_UdmfDataLoadParams}. + * + * @param params Represents a pointer to an instance of {@link OH_UdmfDataLoadParams}. + * @param dataLoadInfo Represents a pointer to an instance of {@link OH_UdmfDataLoadInfo}. + * @see OH_UdmfDataLoadParams OH_UdmfDataLoadInfo + * @since 20 + */ +void OH_UdmfDataLoadParams_SetDataLoadInfo(OH_UdmfDataLoadParams* params, OH_UdmfDataLoadInfo* dataLoadInfo); + +/** + * @brief Creation a pointer to the instance of the {@link OH_UdmfDataLoadInfo}. + * + * @return If the operation is successful, a pointer to the instance of the {@link OH_UdmfDataLoadInfo} + * structure is returned. If the operation is failed, nullptr is returned. + * @see OH_UdmfDataLoadInfo + * @since 20 + */ +OH_UdmfDataLoadInfo* OH_UdmfDataLoadInfo_Create(); + +/** + * @brief Destroy a pointer that points to an instance of {@link OH_UdmfDataLoadInfo}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfDataLoadInfo}. + * @see OH_UdmfDataLoadInfo + * @since 20 + */ +void OH_UdmfDataLoadInfo_Destroy(OH_UdmfDataLoadInfo* dataLoadInfo); + +/** + * @brief Gets the types from the {@OH_UdmfDataLoadInfo}. + * + * @param dataLoadInfo Represents a pointer to an instance of {@link OH_UdmfDataLoadInfo}. + * @param count the types count of data. + * @return Returns the types of data. + * @see OH_UdmfDataLoadInfo + * @since 20 + */ +char** OH_UdmfDataLoadInfo_GetTypes(OH_UdmfDataLoadInfo* dataLoadInfo, unsigned int* count); + +/** + * @brief Sets the data load info to the {@OH_UdmfDataLoadInfo}. + * + * @param dataLoadInfo Represents a pointer to an instance of {@link OH_UdmfDataLoadInfo}. + * @param types Represents the type of data. + * @see OH_UdmfDataLoadInfo + * @since 20 + */ +void OH_UdmfDataLoadInfo_SetType(OH_UdmfDataLoadInfo* dataLoadInfo, const char* type); + +/** + * @brief Gets the record count from the {@OH_UdmfDataLoadInfo}. + * + * @param dataLoadInfo Represents a pointer to an instance of {@link OH_UdmfDataLoadInfo}. + * @return Returns the record count. + * @see OH_UdmfDataLoadInfo + * @since 20 + */ +int OH_UdmfDataLoadInfo_GetRecordCount(OH_UdmfDataLoadInfo* dataLoadInfo); + +/** + * @brief Sets the record count to the {@OH_UdmfDataLoadInfo}. + * + * @param dataLoadInfo Represents a pointer to an instance of {@link OH_UdmfDataLoadInfo}. + * @param recordCount Represents the types of data. + * @see OH_UdmfDataLoadInfo + * @since 20 + */ +void OH_UdmfDataLoadInfo_SetRecordCount(OH_UdmfDataLoadInfo* dataLoadInfo, unsigned int recordCount); + #ifdef __cplusplus }; #endif diff --git a/utils_native/CMakeLists.txt b/utils_native/CMakeLists.txt index 18e577b1..b1e80791 100644 --- a/utils_native/CMakeLists.txt +++ b/utils_native/CMakeLists.txt @@ -4,6 +4,7 @@ project(secure) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -fno-rtti -fvisibility=default -D_GNU_SOURCE") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections -D_GLIBC_MOCK") +add_definitions(-D__CJSON_USE_INT64) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/base/src secureSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/base/src/securec secureSrc) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/base/include) diff --git a/utils_native/base/include/cJSON.h b/utils_native/base/include/cJSON.h index 92907a2c..e763d3ac 100644 --- a/utils_native/base/include/cJSON.h +++ b/utils_native/base/include/cJSON.h @@ -1,11 +1,11 @@ /* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors +Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal +Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is + copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in @@ -17,15 +17,14 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ + THE SOFTWARE. + */ #ifndef cJSON__h #define cJSON__h #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif #if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) @@ -61,18 +60,18 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ #endif #if defined(CJSON_HIDE_SYMBOLS) -#define CJSON_PUBLIC(type) type CJSON_STDCALL +#define CJSON_PUBLIC(type) type CJSON_STDCALL #elif defined(CJSON_EXPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL +#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL #elif defined(CJSON_IMPORT_SYMBOLS) -#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL +#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL #endif #else /* !__WINDOWS__ */ #define CJSON_CDECL #define CJSON_STDCALL -#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) -#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type +#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) +#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type #else #define CJSON_PUBLIC(type) type #endif @@ -81,27 +80,26 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ /* project version */ #define CJSON_VERSION_MAJOR 1 #define CJSON_VERSION_MINOR 7 -#define CJSON_VERSION_PATCH 15 +#define CJSON_VERSION_PATCH 17 #include <stddef.h> /* cJSON Types: */ #define cJSON_Invalid (0) -#define cJSON_False (1 << 0) -#define cJSON_True (1 << 1) -#define cJSON_NULL (1 << 2) +#define cJSON_False (1 << 0) +#define cJSON_True (1 << 1) +#define cJSON_NULL (1 << 2) #define cJSON_Number (1 << 3) #define cJSON_String (1 << 4) -#define cJSON_Array (1 << 5) +#define cJSON_Array (1 << 5) #define cJSON_Object (1 << 6) -#define cJSON_Raw (1 << 7) /* raw json */ +#define cJSON_Raw (1 << 7) /* raw json */ #define cJSON_IsReference 256 #define cJSON_StringIsConst 512 /* The cJSON structure: */ -typedef struct cJSON -{ +typedef struct cJSON { /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ struct cJSON *next; struct cJSON *prev; @@ -122,26 +120,25 @@ typedef struct cJSON char *string; } cJSON; -typedef struct cJSON_Hooks -{ - /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ - void *(CJSON_CDECL *malloc_fn)(size_t sz); - void (CJSON_CDECL *free_fn)(void *ptr); +typedef struct cJSON_Hooks { + /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ + void *(CJSON_CDECL *malloc_fn)(size_t sz); + void(CJSON_CDECL *free_fn)(void *ptr); } cJSON_Hooks; typedef int cJSON_bool; /* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. - * This is to prevent stack overflows. */ +* This is to prevent stack overflows. */ #ifndef CJSON_NESTING_LIMIT #define CJSON_NESTING_LIMIT 1000 #endif /* returns the version of cJSON as a string */ -CJSON_PUBLIC(const char*) cJSON_Version(void); +CJSON_PUBLIC(const char *) cJSON_Version(void); /* Supply malloc, realloc and free functions to cJSON */ -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks *hooks); /* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ /* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ @@ -149,8 +146,11 @@ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length); /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ /* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ -CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); -CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated); +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, + cJSON_bool require_null_terminated); /* Render a cJSON entity to text for transfer/storage. */ CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); @@ -169,27 +169,27 @@ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); /* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); /* Get item "string" from object. Case insensitive. */ -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *const object, const char *const string); +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON *const object, const char *const string); CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); /* Check item type and return its value */ -CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item); -CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item); +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON *const item); +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON *const item); /* These functions check the type of an item */ -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON *const item); /* These calls create a cJSON item of the appropriate type. */ CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); @@ -204,15 +204,15 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); /* Create a string where valuestring references a string so - * it will not be freed by cJSON_Delete */ +* it will not be freed by cJSON_Delete */ CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); /* Create an object/array that only references it's elements so - * they will not be freed by cJSON_Delete */ +* they will not be freed by cJSON_Delete */ CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); /* These utilities create an Array of count items. - * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ +* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); @@ -222,15 +222,15 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int co CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. - * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before - * writing to `item->string` */ +* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before +* writing to `item->string` */ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); /* Remove/Detach items from Arrays/Objects. */ -CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item); CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); @@ -239,48 +239,58 @@ CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); /* Update array items. */ -CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); +CJSON_PUBLIC(cJSON_bool) +cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement); CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem); /* Duplicate a cJSON item */ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will - * need to be released. With recurse!=0, it will duplicate any children connected to the item. - * The item->next and ->prev pointers are always zero on return from Duplicate. */ +* need to be released. With recurse!=0, it will duplicate any children connected to the item. +* The item->next and ->prev pointers are always zero on return from Duplicate. */ /* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. - * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ -CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); +* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive); /* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings. - * The input pointer json cannot point to a read-only address area, such as a string constant, - * but should point to a readable and writable address area. */ +* The input pointer json cannot point to a read-only address area, such as a string constant, +* but should point to a readable and writable address area. */ CJSON_PUBLIC(void) cJSON_Minify(char *json); /* Helper functions for creating and adding items to an object at the same time. - * They return the added item or NULL on failure. */ -CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); -CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); -CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); -CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); -CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); -CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); +* They return the added item or NULL on failure. */ +CJSON_PUBLIC(cJSON *) cJSON_AddNullToObject(cJSON *const object, const char *const name); +CJSON_PUBLIC(cJSON *) cJSON_AddTrueToObject(cJSON *const object, const char *const name); +CJSON_PUBLIC(cJSON *) cJSON_AddFalseToObject(cJSON *const object, const char *const name); +CJSON_PUBLIC(cJSON *) cJSON_AddBoolToObject(cJSON *const object, const char *const name, const cJSON_bool boolean); +CJSON_PUBLIC(cJSON *) cJSON_AddNumberToObject(cJSON *const object, const char *const name, const double number); +CJSON_PUBLIC(cJSON *) cJSON_AddStringToObject(cJSON *const object, const char *const name, const char *const string); +CJSON_PUBLIC(cJSON *) cJSON_AddRawToObject(cJSON *const object, const char *const name, const char *const raw); +CJSON_PUBLIC(cJSON *) cJSON_AddObjectToObject(cJSON *const object, const char *const name); +CJSON_PUBLIC(cJSON *) cJSON_AddArrayToObject(cJSON *const object, const char *const name); /* When assigning an integer value, it needs to be propagated to valuedouble too. */ #define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) /* helper for the cJSON_SetNumberValue macro */ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); -#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) +#define cJSON_SetNumberValue(object, number) \ + ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) /* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */ -CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring); +CJSON_PUBLIC(char *) cJSON_SetValuestring(cJSON *object, const char *valuestring); + +/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/ +#define cJSON_SetBoolValue(object, boolValue) \ + ((object != NULL && ((object)->type & (cJSON_False | cJSON_True))) \ + ? (object)->type = ((object)->type & (~(cJSON_False | cJSON_True))) | \ + ((boolValue) ? cJSON_True : cJSON_False) \ + : cJSON_Invalid) /* Macro for iterating over an array or object */ -#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) +#define cJSON_ArrayForEach(element, array) \ + for (element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) /* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ CJSON_PUBLIC(void *) cJSON_malloc(size_t size); diff --git a/utils_native/base/src/cJSON.c b/utils_native/base/src/cJSON.c index 3063f74e..3b2b76a7 100644 --- a/utils_native/base/src/cJSON.c +++ b/utils_native/base/src/cJSON.c @@ -1,11 +1,11 @@ /* - Copyright (c) 2009-2017 Dave Gamble and cJSON contributors +Copyright (c) 2009-2017 Dave Gamble and cJSON contributors - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal +Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is + copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in @@ -17,8 +17,8 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ + THE SOFTWARE. + */ /* cJSON */ /* JSON parser in C. */ @@ -32,25 +32,25 @@ #pragma GCC visibility push(default) #endif #if defined(_MSC_VER) -#pragma warning (push) +#pragma warning(push) /* disable warning about single line comments in system headers */ -#pragma warning (disable : 4001) +#pragma warning(disable : 4001) #endif -#include <string.h> -#include <stdio.h> -#include <math.h> -#include <stdlib.h> -#include <limits.h> #include <ctype.h> #include <float.h> +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> #ifdef ENABLE_LOCALES #include <locale.h> #endif #if defined(_MSC_VER) -#pragma warning (pop) +#pragma warning(pop) #endif #ifdef __GNUC__ #pragma GCC visibility pop @@ -81,7 +81,7 @@ #ifdef _WIN32 #define NAN sqrt(-1.0) #else -#define NAN 0.0/0.0 +#define NAN 0.0 / 0.0 #endif #endif @@ -93,35 +93,33 @@ static error global_error = { NULL, 0 }; CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) { - return (const char*) (global_error.json + global_error.position); + return (const char *)(global_error.json + global_error.position); } -CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON *const item) { - if (!cJSON_IsString(item)) - { + if (!cJSON_IsString(item)) { return NULL; } return item->valuestring; } -CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON *const item) { - if (!cJSON_IsNumber(item)) - { - return (double) NAN; + if (!cJSON_IsNumber(item)) { + return (double)NAN; } return item->valuedouble; } /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ -#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 15) - #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 17) +#error cJSON.h and cJSON.c have different versions. Make sure that both have the same. #endif -CJSON_PUBLIC(const char*) cJSON_Version(void) +CJSON_PUBLIC(const char *) cJSON_Version(void) { static char version[15]; sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); @@ -132,20 +130,16 @@ CJSON_PUBLIC(const char*) cJSON_Version(void) /* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) { - if ((string1 == NULL) || (string2 == NULL)) - { + if ((string1 == NULL) || (string2 == NULL)) { return 1; } - if (string1 == string2) - { + if (string1 == string2) { return 0; } - for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) - { - if (*string1 == '\0') - { + for (; tolower(*string1) == tolower(*string2); (void)string1++, string2++) { + if (*string1 == '\0') { return 0; } } @@ -153,16 +147,15 @@ static int case_insensitive_strcmp(const unsigned char *string1, const unsigned return tolower(*string1) - tolower(*string2); } -typedef struct internal_hooks -{ +typedef struct internal_hooks { void *(CJSON_CDECL *allocate)(size_t size); - void (CJSON_CDECL *deallocate)(void *pointer); + void(CJSON_CDECL *deallocate)(void *pointer); void *(CJSON_CDECL *reallocate)(void *pointer, size_t size); } internal_hooks; #if defined(_MSC_VER) /* work around MSVC error C2322: '...' address of dllimport '...' is not static */ -static void * CJSON_CDECL internal_malloc(size_t size) +static void *CJSON_CDECL internal_malloc(size_t size) { return malloc(size); } @@ -170,7 +163,7 @@ static void CJSON_CDECL internal_free(void *pointer) { free(pointer); } -static void * CJSON_CDECL internal_realloc(void *pointer, size_t size) +static void *CJSON_CDECL internal_realloc(void *pointer, size_t size) { return realloc(pointer, size); } @@ -185,20 +178,18 @@ static void * CJSON_CDECL internal_realloc(void *pointer, size_t size) static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; -static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) +static unsigned char *cJSON_strdup(const unsigned char *string, const internal_hooks *const hooks) { size_t length = 0; unsigned char *copy = NULL; - if (string == NULL) - { + if (string == NULL) { return NULL; } - length = strlen((const char*)string) + sizeof(""); - copy = (unsigned char*)hooks->allocate(length); - if (copy == NULL) - { + length = strlen((const char *)string) + sizeof(""); + copy = (unsigned char *)hooks->allocate(length); + if (copy == NULL) { return NULL; } memcpy(copy, string, length); @@ -206,10 +197,9 @@ static unsigned char* cJSON_strdup(const unsigned char* string, const internal_h return copy; } -CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks *hooks) { - if (hooks == NULL) - { + if (hooks == NULL) { /* Reset hooks */ global_hooks.allocate = malloc; global_hooks.deallocate = free; @@ -218,31 +208,27 @@ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) } global_hooks.allocate = malloc; - if (hooks->malloc_fn != NULL) - { + if (hooks->malloc_fn != NULL) { global_hooks.allocate = hooks->malloc_fn; } global_hooks.deallocate = free; - if (hooks->free_fn != NULL) - { + if (hooks->free_fn != NULL) { global_hooks.deallocate = hooks->free_fn; } /* use realloc only if both free and malloc are used */ global_hooks.reallocate = NULL; - if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) - { + if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) { global_hooks.reallocate = realloc; } } /* Internal constructor. */ -static cJSON *cJSON_New_Item(const internal_hooks * const hooks) +static cJSON *cJSON_New_Item(const internal_hooks *const hooks) { - cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); - if (node) - { + cJSON *node = (cJSON *)hooks->allocate(sizeof(cJSON)); + if (node) { memset(node, '\0', sizeof(cJSON)); } @@ -253,20 +239,21 @@ static cJSON *cJSON_New_Item(const internal_hooks * const hooks) CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) { cJSON *next = NULL; - while (item != NULL) - { + while (item != NULL) { next = item->next; - if (!(item->type & cJSON_IsReference) && (item->child != NULL)) - { + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) { cJSON_Delete(item->child); } - if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) - { + if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) { global_hooks.deallocate(item->valuestring); + item->valuestring = NULL; } - if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) - { + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { global_hooks.deallocate(item->string); + item->string = NULL; + } + if (next == item) { + break; } global_hooks.deallocate(item); item = next; @@ -278,14 +265,13 @@ static unsigned char get_decimal_point(void) { #ifdef ENABLE_LOCALES struct lconv *lconv = localeconv(); - return (unsigned char) lconv->decimal_point[0]; + return (unsigned char)lconv->decimal_point[0]; #else return '.'; #endif } -typedef struct -{ +typedef struct { const unsigned char *content; size_t length; size_t offset; @@ -302,26 +288,25 @@ typedef struct #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) /* Parse the input text to generate a number, and populate the result into item. */ -static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) +static cJSON_bool parse_number(cJSON *const item, parse_buffer *const input_buffer) { double number = 0; unsigned char *after_end = NULL; - unsigned char number_c_string[64]; + unsigned char *number_c_string; unsigned char decimal_point = get_decimal_point(); size_t i = 0; + size_t number_string_length = 0; + cJSON_bool has_decimal_point = false; - if ((input_buffer == NULL) || (input_buffer->content == NULL)) - { + if ((input_buffer == NULL) || (input_buffer->content == NULL)) { return false; } /* copy the number into a temporary buffer and replace '.' with the decimal point - * of the current locale (for strtod) - * This also takes care of '\0' not necessarily being available for marking the end of the input */ - for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) - { - switch (buffer_at_offset(input_buffer)[i]) - { + * of the current locale (for strtod) + * This also takes care of '\0' not necessarily being available for marking the end of the input */ + for (i = 0; can_access_at_index(input_buffer, i); i++) { + switch (buffer_at_offset(input_buffer)[i]) { case '0': case '1': case '2': @@ -336,11 +321,12 @@ static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_bu case '-': case 'e': case 'E': - number_c_string[i] = buffer_at_offset(input_buffer)[i]; + number_string_length++; break; case '.': - number_c_string[i] = decimal_point; + number_string_length++; + has_decimal_point = true; break; default: @@ -348,75 +334,85 @@ static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_bu } } loop_end: + /* malloc for temporary buffer, add 1 for '\0' */ + number_c_string = (unsigned char *)input_buffer->hooks.allocate(number_string_length + 1); + if (number_c_string == NULL) { + return false; /* allocation failure */ + } + + memcpy(number_c_string, buffer_at_offset(input_buffer), number_string_length); + number_c_string[number_string_length] = '\0'; + + if (has_decimal_point) { + for (i = 0; i < number_string_length; i++) { + if (number_c_string[i] == '.') { + /* replace '.' with the decimal point of the current locale (for strtod) */ + number_c_string[i] = decimal_point; + } + } + } number_c_string[i] = '\0'; - number = strtod((const char*)number_c_string, (char**)&after_end); - if (number_c_string == after_end) - { + number = strtod((const char *)number_c_string, (char **)&after_end); + if (number_c_string == after_end) { + /* free the temporary buffer */ + input_buffer->hooks.deallocate(number_c_string); return false; /* parse_error */ } item->valuedouble = number; /* use saturation in case of overflow */ - if (number >= INT_MAX) - { + if (number >= INT_MAX) { item->valueint = INT_MAX; - } - else if (number <= (double)INT_MIN) - { + } else if (number <= (double)INT_MIN) { item->valueint = INT_MIN; - } - else - { + } else { item->valueint = (int)number; } item->type = cJSON_Number; input_buffer->offset += (size_t)(after_end - number_c_string); + /* free the temporary buffer */ + input_buffer->hooks.deallocate(number_c_string); return true; } /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) { - if (number >= INT_MAX) - { + if (number >= INT_MAX) { object->valueint = INT_MAX; - } - else if (number <= (double)INT_MIN) - { + } else if (number <= (double)INT_MIN) { object->valueint = INT_MIN; - } - else - { + } else { object->valueint = (int)number; } return object->valuedouble = number; } -CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring) +CJSON_PUBLIC(char *) cJSON_SetValuestring(cJSON *object, const char *valuestring) { char *copy = NULL; /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */ - if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference)) - { + if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference)) { return NULL; } - if (strlen(valuestring) <= strlen(object->valuestring)) - { + /* return NULL if the object is corrupted */ + if (object->valuestring == NULL || valuestring == NULL) { + return NULL; + } + if (strlen(valuestring) <= strlen(object->valuestring)) { strcpy(object->valuestring, valuestring); return object->valuestring; } - copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks); - if (copy == NULL) - { + copy = (char *)cJSON_strdup((const unsigned char *)valuestring, &global_hooks); + if (copy == NULL) { return NULL; } - if (object->valuestring != NULL) - { + if (object->valuestring != NULL) { cJSON_free(object->valuestring); } object->valuestring = copy; @@ -424,8 +420,7 @@ CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring) return copy; } -typedef struct -{ +typedef struct { unsigned char *buffer; size_t length; size_t offset; @@ -436,31 +431,27 @@ typedef struct } printbuffer; /* realloc printbuffer if necessary to have at least "needed" bytes more */ -static unsigned char* ensure(printbuffer * const p, size_t needed) +static unsigned char *ensure(printbuffer *const p, size_t needed) { unsigned char *newbuffer = NULL; size_t newsize = 0; - if ((p == NULL) || (p->buffer == NULL)) - { + if ((p == NULL) || (p->buffer == NULL)) { return NULL; } - if ((p->length > 0) && (p->offset >= p->length)) - { + if ((p->length > 0) && (p->offset >= p->length)) { /* make sure that offset is valid */ return NULL; } - if (needed > INT_MAX) - { + if (needed > INT_MAX) { /* sizes bigger than INT_MAX are currently not supported */ return NULL; } needed += p->offset + 1; - if (needed <= p->length) - { + if (needed <= p->length) { return p->buffer + p->offset; } @@ -469,49 +460,38 @@ static unsigned char* ensure(printbuffer * const p, size_t needed) } /* calculate new buffer size */ - if (needed > (INT_MAX / 2)) - { + if (needed > (INT_MAX / 2)) { /* overflow of int, use INT_MAX if possible */ - if (needed <= INT_MAX) - { + if (needed <= INT_MAX) { newsize = INT_MAX; - } - else - { + } else { return NULL; } - } - else - { + } else { newsize = needed * 2; } - if (p->hooks.reallocate != NULL) - { + if (p->hooks.reallocate != NULL) { /* reallocate with realloc if available */ - newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); - if (newbuffer == NULL) - { + newbuffer = (unsigned char *)p->hooks.reallocate(p->buffer, newsize); + if (newbuffer == NULL) { p->hooks.deallocate(p->buffer); p->length = 0; p->buffer = NULL; return NULL; } - } - else - { + } else { /* otherwise reallocate manually */ - newbuffer = (unsigned char*)p->hooks.allocate(newsize); - if (!newbuffer) - { + newbuffer = (unsigned char *)p->hooks.allocate(newsize); + if (!newbuffer) { p->hooks.deallocate(p->buffer); p->length = 0; p->buffer = NULL; return NULL; } - + memcpy(newbuffer, p->buffer, p->offset + 1); p->hooks.deallocate(p->buffer); } @@ -522,16 +502,15 @@ static unsigned char* ensure(printbuffer * const p, size_t needed) } /* calculate the new length of the string in a printbuffer and update the offset */ -static void update_offset(printbuffer * const buffer) +static void update_offset(printbuffer *const buffer) { const unsigned char *buffer_pointer = NULL; - if ((buffer == NULL) || (buffer->buffer == NULL)) - { + if ((buffer == NULL) || (buffer->buffer == NULL)) { return; } buffer_pointer = buffer->buffer + buffer->offset; - buffer->offset += strlen((const char*)buffer_pointer); + buffer->offset += strlen((const char *)buffer_pointer); } /* securely comparison of floating-point variables */ @@ -542,58 +521,51 @@ static cJSON_bool compare_double(double a, double b) } /* Render the number nicely from the given item into a string. */ -static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) +static cJSON_bool print_number(const cJSON *const item, printbuffer *const output_buffer) { unsigned char *output_pointer = NULL; double d = item->valuedouble; int length = 0; size_t i = 0; - unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */ + unsigned char number_buffer[26] = { 0 }; /* temporary buffer to print the number into */ unsigned char decimal_point = get_decimal_point(); double test = 0.0; - if (output_buffer == NULL) - { + if (output_buffer == NULL) { return false; } /* This checks for NaN and Infinity */ - if (isnan(d) || isinf(d)) - { - length = sprintf((char*)number_buffer, "null"); - } - else - { + if (isnan(d) || isinf(d)) { + length = sprintf((char *)number_buffer, "null"); + } else if (d == (double)item->valueint) { + length = sprintf((char *)number_buffer, "%d", item->valueint); + } else { /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ - length = sprintf((char*)number_buffer, "%1.15g", d); + length = sprintf((char *)number_buffer, "%1.15g", d); /* Check whether the original double can be recovered */ - if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) - { + if ((sscanf((char *)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) { /* If not, print with 17 decimal places of precision */ - length = sprintf((char*)number_buffer, "%1.17g", d); + length = sprintf((char *)number_buffer, "%1.17g", d); } } /* sprintf failed or buffer overrun occurred */ - if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) - { + if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) { return false; } /* reserve appropriate space in the output */ output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } /* copy the printed number to the output and replace locale - * dependent decimal point with '.' */ - for (i = 0; i < ((size_t)length); i++) - { - if (number_buffer[i] == decimal_point) - { + * dependent decimal point with '.' */ + for (i = 0; i < ((size_t)length); i++) { + if (number_buffer[i] == decimal_point) { output_pointer[i] = '.'; continue; } @@ -608,33 +580,25 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out } /* parse 4 digit hexadecimal number */ -static unsigned parse_hex4(const unsigned char * const input) +static unsigned parse_hex4(const unsigned char *const input) { unsigned int h = 0; size_t i = 0; - for (i = 0; i < 4; i++) - { + for (i = 0; i < 4; i++) { /* parse digit */ - if ((input[i] >= '0') && (input[i] <= '9')) - { - h += (unsigned int) input[i] - '0'; - } - else if ((input[i] >= 'A') && (input[i] <= 'F')) - { - h += (unsigned int) 10 + input[i] - 'A'; - } - else if ((input[i] >= 'a') && (input[i] <= 'f')) - { - h += (unsigned int) 10 + input[i] - 'a'; - } - else /* invalid */ + if ((input[i] >= '0') && (input[i] <= '9')) { + h += (unsigned int)input[i] - '0'; + } else if ((input[i] >= 'A') && (input[i] <= 'F')) { + h += (unsigned int)10 + input[i] - 'A'; + } else if ((input[i] >= 'a') && (input[i] <= 'f')) { + h += (unsigned int)10 + input[i] - 'a'; + } else /* invalid */ { return 0; } - if (i < 3) - { + if (i < 3) { /* shift left to make place for the next nibble */ h = h << 4; } @@ -644,8 +608,9 @@ static unsigned parse_hex4(const unsigned char * const input) } /* converts a UTF-16 literal to UTF-8 - * A literal can be one or two sequences of the form \uXXXX */ -static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) +* A literal can be one or two sequences of the form \uXXXX */ +static unsigned char utf16_literal_to_utf8(const unsigned char *const input_pointer, + const unsigned char *const input_end, unsigned char **output_pointer) { long unsigned int codepoint = 0; unsigned int first_code = 0; @@ -655,8 +620,7 @@ static unsigned char utf16_literal_to_utf8(const unsigned char * const input_poi unsigned char sequence_length = 0; unsigned char first_byte_mark = 0; - if ((input_end - first_sequence) < 6) - { + if ((input_end - first_sequence) < 6) { /* input ends unexpectedly */ goto fail; } @@ -665,26 +629,22 @@ static unsigned char utf16_literal_to_utf8(const unsigned char * const input_poi first_code = parse_hex4(first_sequence + 2); /* check that the code is valid */ - if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) - { + if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) { goto fail; } /* UTF16 surrogate pair */ - if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) - { + if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) { const unsigned char *second_sequence = first_sequence + 6; unsigned int second_code = 0; sequence_length = 12; /* \uXXXX\uXXXX */ - if ((input_end - second_sequence) < 6) - { + if ((input_end - second_sequence) < 6) { /* input ends unexpectedly */ goto fail; } - if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) - { + if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) { /* missing second half of the surrogate pair */ goto fail; } @@ -692,68 +652,51 @@ static unsigned char utf16_literal_to_utf8(const unsigned char * const input_poi /* get the second utf16 sequence */ second_code = parse_hex4(second_sequence + 2); /* check that the code is valid */ - if ((second_code < 0xDC00) || (second_code > 0xDFFF)) - { + if ((second_code < 0xDC00) || (second_code > 0xDFFF)) { /* invalid second half of the surrogate pair */ goto fail; } - /* calculate the unicode codepoint from the surrogate pair */ codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); - } - else - { + } else { sequence_length = 6; /* \uXXXX */ codepoint = first_code; } /* encode as UTF-8 - * takes at maximum 4 bytes to encode: - * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ - if (codepoint < 0x80) - { + * takes at maximum 4 bytes to encode: + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + if (codepoint < 0x80) { /* normal ascii, encoding 0xxxxxxx */ utf8_length = 1; - } - else if (codepoint < 0x800) - { + } else if (codepoint < 0x800) { /* two bytes, encoding 110xxxxx 10xxxxxx */ utf8_length = 2; first_byte_mark = 0xC0; /* 11000000 */ - } - else if (codepoint < 0x10000) - { + } else if (codepoint < 0x10000) { /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ utf8_length = 3; first_byte_mark = 0xE0; /* 11100000 */ - } - else if (codepoint <= 0x10FFFF) - { + } else if (codepoint <= 0x10FFFF) { /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ utf8_length = 4; first_byte_mark = 0xF0; /* 11110000 */ - } - else - { + } else { /* invalid unicode codepoint */ goto fail; } /* encode as utf8 */ - for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) - { + for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) { /* 10xxxxxx */ (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); codepoint >>= 6; } /* encode first byte */ - if (utf8_length > 1) - { + if (utf8_length > 1) { (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); - } - else - { + } else { (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); } @@ -766,7 +709,7 @@ fail: } /* Parse the input text into an unescaped cinput, and populate item. */ -static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) +static cJSON_bool parse_string(cJSON *const item, parse_buffer *const input_buffer) { const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; @@ -774,8 +717,7 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu unsigned char *output = NULL; /* not a string */ - if (buffer_at_offset(input_buffer)[0] != '\"') - { + if (buffer_at_offset(input_buffer)[0] != '\"') { goto fail; } @@ -783,13 +725,10 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu /* calculate approximate size of the output (overestimate) */ size_t allocation_length = 0; size_t skipped_bytes = 0; - while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) - { + while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) { /* is escape sequence */ - if (input_end[0] == '\\') - { - if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) - { + if (input_end[0] == '\\') { + if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) { /* prevent buffer overflow when last input character is a backslash */ goto fail; } @@ -798,39 +737,32 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu } input_end++; } - if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) - { + if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) { goto fail; /* string ended unexpectedly */ } /* This is at most how much we need for the output */ - allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; - output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); - if (output == NULL) - { + allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer)) - skipped_bytes; + output = (unsigned char *)input_buffer->hooks.allocate(allocation_length + sizeof("")); + if (output == NULL) { goto fail; /* allocation failure */ } } output_pointer = output; /* loop through the string literal */ - while (input_pointer < input_end) - { - if (*input_pointer != '\\') - { + while (input_pointer < input_end) { + if (*input_pointer != '\\') { *output_pointer++ = *input_pointer++; } /* escape sequence */ - else - { + else { unsigned char sequence_length = 2; - if ((input_end - input_pointer) < 1) - { + if ((input_end - input_pointer) < 1) { goto fail; } - switch (input_pointer[1]) - { + switch (input_pointer[1]) { case 'b': *output_pointer++ = '\b'; break; @@ -855,8 +787,7 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu /* UTF-16 literal */ case 'u': sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); - if (sequence_length == 0) - { + if (sequence_length == 0) { /* failed to convert UTF16-literal to UTF-8 */ goto fail; } @@ -873,21 +804,19 @@ static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_bu *output_pointer = '\0'; item->type = cJSON_String; - item->valuestring = (char*)output; + item->valuestring = (char *)output; - input_buffer->offset = (size_t) (input_end - input_buffer->content); + input_buffer->offset = (size_t)(input_end - input_buffer->content); input_buffer->offset++; return true; fail: - if (output != NULL) - { + if (output != NULL) { input_buffer->hooks.deallocate(output); } - if (input_pointer != NULL) - { + if (input_pointer != NULL) { input_buffer->offset = (size_t)(input_pointer - input_buffer->content); } @@ -895,7 +824,7 @@ fail: } /* Render the cstring provided to an escaped version that can be printed. */ -static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) +static cJSON_bool print_string_ptr(const unsigned char *const input, printbuffer *const output_buffer) { const unsigned char *input_pointer = NULL; unsigned char *output = NULL; @@ -904,29 +833,24 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe /* numbers of additional characters needed for escaping */ size_t escape_characters = 0; - if (output_buffer == NULL) - { + if (output_buffer == NULL) { return false; } /* empty string */ - if (input == NULL) - { + if (input == NULL) { output = ensure(output_buffer, sizeof("\"\"")); - if (output == NULL) - { + if (output == NULL) { return false; } - strcpy((char*)output, "\"\""); + strcpy((char *)output, "\"\""); return true; } /* set "flag" to 1 if something needs to be escaped */ - for (input_pointer = input; *input_pointer; input_pointer++) - { - switch (*input_pointer) - { + for (input_pointer = input; *input_pointer; input_pointer++) { + switch (*input_pointer) { case '\"': case '\\': case '\b': @@ -938,8 +862,7 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe escape_characters++; break; default: - if (*input_pointer < 32) - { + if (*input_pointer < 32) { /* UTF-16 escape sequence uXXXX */ escape_characters += 5; } @@ -949,14 +872,12 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe output_length = (size_t)(input_pointer - input) + escape_characters; output = ensure(output_buffer, output_length + sizeof("\"\"")); - if (output == NULL) - { + if (output == NULL) { return false; } /* no characters have to be escaped */ - if (escape_characters == 0) - { + if (escape_characters == 0) { output[0] = '\"'; memcpy(output + 1, input, output_length); output[output_length + 1] = '\"'; @@ -968,19 +889,14 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe output[0] = '\"'; output_pointer = output + 1; /* copy the string */ - for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) - { - if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) - { + for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) { + if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) { /* normal character, copy */ *output_pointer = *input_pointer; - } - else - { + } else { /* character needs to be escaped */ *output_pointer++ = '\\'; - switch (*input_pointer) - { + switch (*input_pointer) { case '\\': *output_pointer = '\\'; break; @@ -1004,7 +920,7 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe break; default: /* escape and print as unicode codepoint */ - sprintf((char*)output_pointer, "u%04x", *input_pointer); + sprintf((char *)output_pointer, "u%04x", *input_pointer); output_pointer += 4; break; } @@ -1017,39 +933,35 @@ static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffe } /* Invoke print_string_ptr (which is useful) on an item. */ -static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) +static cJSON_bool print_string(const cJSON *const item, printbuffer *const p) { - return print_string_ptr((unsigned char*)item->valuestring, p); + return print_string_ptr((unsigned char *)item->valuestring, p); } /* Predeclare these prototypes. */ -static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); -static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); -static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); -static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer); +static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer); +static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer); +static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer); +static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer); +static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer); /* Utility to jump whitespace and cr/lf */ -static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) +static parse_buffer *buffer_skip_whitespace(parse_buffer *const buffer) { - if ((buffer == NULL) || (buffer->content == NULL)) - { + if ((buffer == NULL) || (buffer->content == NULL)) { return NULL; } - if (cannot_access_at_index(buffer, 0)) - { + if (cannot_access_at_index(buffer, 0)) { return buffer; } - while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) - { - buffer->offset++; + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) { + buffer->offset++; } - if (buffer->offset == buffer->length) - { + if (buffer->offset == buffer->length) { buffer->offset--; } @@ -1057,27 +969,25 @@ static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) } /* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ -static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) +static parse_buffer *skip_utf8_bom(parse_buffer *const buffer) { - if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) - { + if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) { return NULL; } - if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) - { + if (can_access_at_index(buffer, 4) && (strncmp((const char *)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) { buffer->offset += 3; } return buffer; } -CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) { size_t buffer_length; - if (NULL == value) - { + if (NULL == value) { return NULL; } @@ -1088,7 +998,9 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return } /* Parse an object - create a new root, and populate. */ -CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated) +CJSON_PUBLIC(cJSON *) +cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, + cJSON_bool require_null_terminated) { parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; cJSON *item = NULL; @@ -1097,13 +1009,12 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer global_error.json = NULL; global_error.position = 0; - if (value == NULL || 0 == buffer_length) - { + if (value == NULL || 0 == buffer_length) { goto fail; } - buffer.content = (const unsigned char*)value; - buffer.length = buffer_length; + buffer.content = (const unsigned char *)value; + buffer.length = buffer_length; buffer.offset = 0; buffer.hooks = global_hooks; @@ -1113,52 +1024,42 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer goto fail; } - if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) - { + if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) { /* parse failure. ep is set. */ goto fail; } /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ - if (require_null_terminated) - { + if (require_null_terminated) { buffer_skip_whitespace(&buffer); - if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') - { + if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') { goto fail; } } - if (return_parse_end) - { - *return_parse_end = (const char*)buffer_at_offset(&buffer); + if (return_parse_end) { + *return_parse_end = (const char *)buffer_at_offset(&buffer); } return item; fail: - if (item != NULL) - { + if (item != NULL) { cJSON_Delete(item); } - if (value != NULL) - { + if (value != NULL) { error local_error; - local_error.json = (const unsigned char*)value; + local_error.json = (const unsigned char *)value; local_error.position = 0; - if (buffer.offset < buffer.length) - { + if (buffer.offset < buffer.length) { local_error.position = buffer.offset; - } - else if (buffer.length > 0) - { + } else if (buffer.length > 0) { local_error.position = buffer.length - 1; } - if (return_parse_end != NULL) - { - *return_parse_end = (const char*)local_error.json + local_error.position; + if (return_parse_end != NULL) { + *return_parse_end = (const char *)local_error.json + local_error.position; } global_error = local_error; @@ -1180,7 +1081,7 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_len #define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) -static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) +static unsigned char *print(const cJSON *const item, cJSON_bool format, const internal_hooks *const hooks) { static const size_t default_buffer_size = 256; printbuffer buffer[1]; @@ -1189,36 +1090,31 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i memset(buffer, 0, sizeof(buffer)); /* create buffer */ - buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); + buffer->buffer = (unsigned char *)hooks->allocate(default_buffer_size); buffer->length = default_buffer_size; buffer->format = format; buffer->hooks = *hooks; - if (buffer->buffer == NULL) - { + if (buffer->buffer == NULL) { goto fail; } /* print the value */ - if (!print_value(item, buffer)) - { + if (!print_value(item, buffer)) { goto fail; } update_offset(buffer); /* check if reallocate is available */ - if (hooks->reallocate != NULL) - { - printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); + if (hooks->reallocate != NULL) { + printed = (unsigned char *)hooks->reallocate(buffer->buffer, buffer->offset + 1); if (printed == NULL) { goto fail; } buffer->buffer = NULL; - } - else /* otherwise copy the JSON over to a new buffer */ + } else /* otherwise copy the JSON over to a new buffer */ { - printed = (unsigned char*) hooks->allocate(buffer->offset + 1); - if (printed == NULL) - { + printed = (unsigned char *)hooks->allocate(buffer->offset + 1); + if (printed == NULL) { goto fail; } memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); @@ -1231,13 +1127,11 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i return printed; fail: - if (buffer->buffer != NULL) - { + if (buffer->buffer != NULL) { hooks->deallocate(buffer->buffer); } - if (printed != NULL) - { + if (printed != NULL) { hooks->deallocate(printed); } @@ -1247,26 +1141,24 @@ fail: /* Render a cJSON item/entity/structure to text. */ CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) { - return (char*)print(item, true, &global_hooks); + return (char *)print(item, true, &global_hooks); } CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) { - return (char*)print(item, false, &global_hooks); + return (char *)print(item, false, &global_hooks); } CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) { printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - if (prebuffer < 0) - { + if (prebuffer < 0) { return NULL; } - p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); - if (!p.buffer) - { + p.buffer = (unsigned char *)global_hooks.allocate((size_t)prebuffer); + if (!p.buffer) { return NULL; } @@ -1276,25 +1168,23 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON p.format = fmt; p.hooks = global_hooks; - if (!print_value(item, &p)) - { + if (!print_value(item, &p)) { global_hooks.deallocate(p.buffer); return NULL; } - return (char*)p.buffer; + return (char *)p.buffer; } CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) { printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; - if ((length < 0) || (buffer == NULL)) - { + if ((length < 0) || (buffer == NULL)) { return false; } - p.buffer = (unsigned char*)buffer; + p.buffer = (unsigned char *)buffer; p.length = (size_t)length; p.offset = 0; p.noalloc = true; @@ -1305,54 +1195,48 @@ CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, cons } /* Parser core - when encountering text, process appropriately. */ -static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) +static cJSON_bool parse_value(cJSON *const item, parse_buffer *const input_buffer) { - if ((input_buffer == NULL) || (input_buffer->content == NULL)) - { + if ((input_buffer == NULL) || (input_buffer->content == NULL)) { return false; /* no input */ } /* parse the different types of values */ /* null */ - if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) - { + if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "null", 4) == 0)) { item->type = cJSON_NULL; input_buffer->offset += 4; return true; } /* false */ - if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) - { + if (can_read(input_buffer, 5) && (strncmp((const char *)buffer_at_offset(input_buffer), "false", 5) == 0)) { item->type = cJSON_False; input_buffer->offset += 5; return true; } /* true */ - if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) - { + if (can_read(input_buffer, 4) && (strncmp((const char *)buffer_at_offset(input_buffer), "true", 4) == 0)) { item->type = cJSON_True; item->valueint = 1; input_buffer->offset += 4; return true; } /* string */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) - { + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) { return parse_string(item, input_buffer); } /* number */ - if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) - { + if (can_access_at_index(input_buffer, 0) && + ((buffer_at_offset(input_buffer)[0] == '-') || + ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) { return parse_number(item, input_buffer); } /* array */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) - { + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) { return parse_array(item, input_buffer); } /* object */ - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) - { + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) { return parse_object(item, input_buffer); } @@ -1360,59 +1244,51 @@ static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buf } /* Render a value to text. */ -static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) +static cJSON_bool print_value(const cJSON *const item, printbuffer *const output_buffer) { unsigned char *output = NULL; - if ((item == NULL) || (output_buffer == NULL)) - { + if ((item == NULL) || (output_buffer == NULL)) { return false; } - switch ((item->type) & 0xFF) - { + switch ((item->type) & 0xFF) { case cJSON_NULL: output = ensure(output_buffer, 5); - if (output == NULL) - { + if (output == NULL) { return false; } - strcpy((char*)output, "null"); + strcpy((char *)output, "null"); return true; case cJSON_False: output = ensure(output_buffer, 6); - if (output == NULL) - { + if (output == NULL) { return false; } - strcpy((char*)output, "false"); + strcpy((char *)output, "false"); return true; case cJSON_True: output = ensure(output_buffer, 5); - if (output == NULL) - { + if (output == NULL) { return false; } - strcpy((char*)output, "true"); + strcpy((char *)output, "true"); return true; case cJSON_Number: return print_number(item, output_buffer); - case cJSON_Raw: - { + case cJSON_Raw: { size_t raw_length = 0; - if (item->valuestring == NULL) - { + if (item->valuestring == NULL) { return false; } raw_length = strlen(item->valuestring) + sizeof(""); output = ensure(output_buffer, raw_length); - if (output == NULL) - { + if (output == NULL) { return false; } memcpy(output, item->valuestring, raw_length); @@ -1434,34 +1310,30 @@ static cJSON_bool print_value(const cJSON * const item, printbuffer * const outp } /* Build an array from input text. */ -static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) +static cJSON_bool parse_array(cJSON *const item, parse_buffer *const input_buffer) { cJSON *head = NULL; /* head of the linked list */ cJSON *current_item = NULL; - if (input_buffer->depth >= CJSON_NESTING_LIMIT) - { + if (input_buffer->depth >= CJSON_NESTING_LIMIT) { return false; /* to deeply nested */ } input_buffer->depth++; - if (buffer_at_offset(input_buffer)[0] != '[') - { + if (buffer_at_offset(input_buffer)[0] != '[') { /* not an array */ goto fail; } input_buffer->offset++; buffer_skip_whitespace(input_buffer); - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) - { + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) { /* empty array */ goto success; } /* check if we skipped to the end of the buffer */ - if (cannot_access_at_index(input_buffer, 0)) - { + if (cannot_access_at_index(input_buffer, 0)) { input_buffer->offset--; goto fail; } @@ -1469,23 +1341,18 @@ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buf /* step back to character in front of the first element */ input_buffer->offset--; /* loop through the comma separated array elements */ - do - { + do { /* allocate next item */ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); - if (new_item == NULL) - { + if (new_item == NULL) { goto fail; /* allocation failure */ } /* attach next item to list */ - if (head == NULL) - { + if (head == NULL) { /* start the linked list */ current_item = head = new_item; - } - else - { + } else { /* add to the end and advance */ current_item->next = new_item; new_item->prev = current_item; @@ -1495,16 +1362,13 @@ static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buf /* parse next value */ input_buffer->offset++; buffer_skip_whitespace(input_buffer); - if (!parse_value(current_item, input_buffer)) - { + if (!parse_value(current_item, input_buffer)) { goto fail; /* failed to parse value */ } buffer_skip_whitespace(input_buffer); - } - while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); - if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') - { + if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') { goto fail; /* expected end of array */ } @@ -1523,8 +1387,7 @@ success: return true; fail: - if (head != NULL) - { + if (head != NULL) { cJSON_Delete(head); } @@ -1532,22 +1395,20 @@ fail: } /* Render an array to text */ -static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) +static cJSON_bool print_array(const cJSON *const item, printbuffer *const output_buffer) { unsigned char *output_pointer = NULL; size_t length = 0; cJSON *current_element = item->child; - if (output_buffer == NULL) - { + if (output_buffer == NULL) { return false; } /* Compose the output array. */ /* opening square bracket */ output_pointer = ensure(output_buffer, 1); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } @@ -1555,24 +1416,19 @@ static cJSON_bool print_array(const cJSON * const item, printbuffer * const outp output_buffer->offset++; output_buffer->depth++; - while (current_element != NULL) - { - if (!print_value(current_element, output_buffer)) - { + while (current_element != NULL) { + if (!print_value(current_element, output_buffer)) { return false; } update_offset(output_buffer); - if (current_element->next) - { - length = (size_t) (output_buffer->format ? 2 : 1); + if (current_element->next) { + length = (size_t)(output_buffer->format ? 2 : 1); output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } *output_pointer++ = ','; - if(output_buffer->format) - { + if (output_buffer->format) { *output_pointer++ = ' '; } *output_pointer = '\0'; @@ -1582,8 +1438,7 @@ static cJSON_bool print_array(const cJSON * const item, printbuffer * const outp } output_pointer = ensure(output_buffer, 2); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } *output_pointer++ = ']'; @@ -1594,32 +1449,28 @@ static cJSON_bool print_array(const cJSON * const item, printbuffer * const outp } /* Build an object from the text. */ -static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) +static cJSON_bool parse_object(cJSON *const item, parse_buffer *const input_buffer) { cJSON *head = NULL; /* linked list head */ cJSON *current_item = NULL; - if (input_buffer->depth >= CJSON_NESTING_LIMIT) - { + if (input_buffer->depth >= CJSON_NESTING_LIMIT) { return false; /* to deeply nested */ } input_buffer->depth++; - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) - { + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) { goto fail; /* not an object */ } input_buffer->offset++; buffer_skip_whitespace(input_buffer); - if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) - { + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) { goto success; /* empty object */ } /* check if we skipped to the end of the buffer */ - if (cannot_access_at_index(input_buffer, 0)) - { + if (cannot_access_at_index(input_buffer, 0)) { input_buffer->offset--; goto fail; } @@ -1627,34 +1478,32 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu /* step back to character in front of the first element */ input_buffer->offset--; /* loop through the comma separated array elements */ - do - { + do { /* allocate next item */ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); - if (new_item == NULL) - { + if (new_item == NULL) { goto fail; /* allocation failure */ } /* attach next item to list */ - if (head == NULL) - { + if (head == NULL) { /* start the linked list */ current_item = head = new_item; - } - else - { + } else { /* add to the end and advance */ current_item->next = new_item; new_item->prev = current_item; current_item = new_item; } + if (cannot_access_at_index(input_buffer, 1)) { + goto fail; /* nothing comes after the comma */ + } + /* parse the name of the child */ input_buffer->offset++; buffer_skip_whitespace(input_buffer); - if (!parse_string(current_item, input_buffer)) - { + if (!parse_string(current_item, input_buffer)) { goto fail; /* failed to parse name */ } buffer_skip_whitespace(input_buffer); @@ -1663,24 +1512,20 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu current_item->string = current_item->valuestring; current_item->valuestring = NULL; - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) - { + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) { goto fail; /* invalid object */ } /* parse the value */ input_buffer->offset++; buffer_skip_whitespace(input_buffer); - if (!parse_value(current_item, input_buffer)) - { + if (!parse_value(current_item, input_buffer)) { goto fail; /* failed to parse value */ } buffer_skip_whitespace(input_buffer); - } - while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + } while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); - if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) - { + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) { goto fail; /* expected end of object */ } @@ -1698,8 +1543,7 @@ success: return true; fail: - if (head != NULL) - { + if (head != NULL) { cJSON_Delete(head); } @@ -1707,73 +1551,62 @@ fail: } /* Render an object to text. */ -static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) +static cJSON_bool print_object(const cJSON *const item, printbuffer *const output_buffer) { unsigned char *output_pointer = NULL; size_t length = 0; cJSON *current_item = item->child; - if (output_buffer == NULL) - { + if (output_buffer == NULL) { return false; } /* Compose the output: */ - length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ + length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */ output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } *output_pointer++ = '{'; output_buffer->depth++; - if (output_buffer->format) - { + if (output_buffer->format) { *output_pointer++ = '\n'; } output_buffer->offset += length; - while (current_item) - { - if (output_buffer->format) - { + while (current_item) { + if (output_buffer->format) { size_t i; output_pointer = ensure(output_buffer, output_buffer->depth); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } - for (i = 0; i < output_buffer->depth; i++) - { + for (i = 0; i < output_buffer->depth; i++) { *output_pointer++ = '\t'; } output_buffer->offset += output_buffer->depth; } /* print key */ - if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) - { + if (!print_string_ptr((unsigned char *)current_item->string, output_buffer)) { return false; } update_offset(output_buffer); - length = (size_t) (output_buffer->format ? 2 : 1); + length = (size_t)(output_buffer->format ? 2 : 1); output_pointer = ensure(output_buffer, length); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } *output_pointer++ = ':'; - if (output_buffer->format) - { + if (output_buffer->format) { *output_pointer++ = '\t'; } output_buffer->offset += length; /* print value */ - if (!print_value(current_item, output_buffer)) - { + if (!print_value(current_item, output_buffer)) { return false; } update_offset(output_buffer); @@ -1781,17 +1614,14 @@ static cJSON_bool print_object(const cJSON * const item, printbuffer * const out /* print comma if not last */ length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0)); output_pointer = ensure(output_buffer, length + 1); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } - if (current_item->next) - { + if (current_item->next) { *output_pointer++ = ','; } - if (output_buffer->format) - { + if (output_buffer->format) { *output_pointer++ = '\n'; } *output_pointer = '\0'; @@ -1801,15 +1631,12 @@ static cJSON_bool print_object(const cJSON * const item, printbuffer * const out } output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); - if (output_pointer == NULL) - { + if (output_pointer == NULL) { return false; } - if (output_buffer->format) - { + if (output_buffer->format) { size_t i; - for (i = 0; i < (output_buffer->depth - 1); i++) - { + for (i = 0; i < (output_buffer->depth - 1); i++) { *output_pointer++ = '\t'; } } @@ -1826,15 +1653,13 @@ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) cJSON *child = NULL; size_t size = 0; - if (array == NULL) - { + if (array == NULL) { return 0; } child = array->child; - while(child != NULL) - { + while (child != NULL) { size++; child = child->next; } @@ -1844,18 +1669,16 @@ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) return (int)size; } -static cJSON* get_array_item(const cJSON *array, size_t index) +static cJSON *get_array_item(const cJSON *array, size_t index) { cJSON *current_child = NULL; - if (array == NULL) - { + if (array == NULL) { return NULL; } current_child = array->child; - while ((current_child != NULL) && (index > 0)) - { + while ((current_child != NULL) && (index > 0)) { index--; current_child = current_child->next; } @@ -1865,35 +1688,30 @@ static cJSON* get_array_item(const cJSON *array, size_t index) CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) { - if (index < 0) - { + if (index < 0) { return NULL; } return get_array_item(array, (size_t)index); } -static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) +static cJSON *get_object_item(const cJSON *const object, const char *const name, const cJSON_bool case_sensitive) { cJSON *current_element = NULL; - if ((object == NULL) || (name == NULL)) - { + if ((object == NULL) || (name == NULL)) { return NULL; } current_element = object->child; - if (case_sensitive) - { - while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) - { + if (case_sensitive) { + while ((current_element != NULL) && (current_element->string != NULL) && + (strcmp(name, current_element->string) != 0)) { current_element = current_element->next; } - } - else - { - while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) - { + } else { + while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char *)name, + (const unsigned char *)(current_element->string)) != 0)) { current_element = current_element->next; } } @@ -1905,12 +1723,12 @@ static cJSON *get_object_item(const cJSON * const object, const char * const nam return current_element; } -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *const object, const char *const string) { return get_object_item(object, string, false); } -CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON *const object, const char *const string) { return get_object_item(object, string, true); } @@ -1928,17 +1746,15 @@ static void suffix_object(cJSON *prev, cJSON *item) } /* Utility for handling references. */ -static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) +static cJSON *create_reference(const cJSON *item, const internal_hooks *const hooks) { cJSON *reference = NULL; - if (item == NULL) - { + if (item == NULL) { return NULL; } reference = cJSON_New_Item(hooks); - if (reference == NULL) - { + if (reference == NULL) { return NULL; } @@ -1953,27 +1769,22 @@ static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) { cJSON *child = NULL; - if ((item == NULL) || (array == NULL) || (array == item)) - { + if ((item == NULL) || (array == NULL) || (array == item)) { return false; } child = array->child; /* - * To find the last item in array quickly, we use prev in array - */ - if (child == NULL) - { + * To find the last item in array quickly, we use prev in array + */ + if (child == NULL) { /* list is empty, start new one */ array->child = item; item->prev = item; item->next = NULL; - } - else - { + } else { /* append to the end */ - if (child->prev) - { + if (child->prev) { suffix_object(child->prev, item); array->child->prev = item; } @@ -1988,50 +1799,44 @@ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item) return add_item_to_array(array, item); } -#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) - #pragma GCC diagnostic push +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) +#pragma GCC diagnostic push #endif #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wcast-qual" #endif /* helper function to cast away const */ -static void* cast_away_const(const void* string) +static void *cast_away_const(const void *string) { - return (void*)string; + return (void *)string; } -#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) - #pragma GCC diagnostic pop +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) +#pragma GCC diagnostic pop #endif - -static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) +static cJSON_bool add_item_to_object(cJSON *const object, const char *const string, cJSON *const item, + const internal_hooks *const hooks, const cJSON_bool constant_key) { char *new_key = NULL; int new_type = cJSON_Invalid; - if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) - { + if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) { return false; } - if (constant_key) - { - new_key = (char*)cast_away_const(string); + if (constant_key) { + new_key = (char *)cast_away_const(string); new_type = item->type | cJSON_StringIsConst; - } - else - { - new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); - if (new_key == NULL) - { + } else { + new_key = (char *)cJSON_strdup((const unsigned char *)string, hooks); + if (new_key == NULL) { return false; } new_type = item->type & ~cJSON_StringIsConst; } - if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) - { + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { hooks->deallocate(item->string); } @@ -2054,8 +1859,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *stri CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) { - if (array == NULL) - { + if (array == NULL) { return false; } @@ -2064,19 +1868,17 @@ CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) { - if ((object == NULL) || (string == NULL)) - { + if ((object == NULL) || (string == NULL)) { return false; } return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); } -CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) +CJSON_PUBLIC(cJSON *) cJSON_AddNullToObject(cJSON *const object, const char *const name) { cJSON *null = cJSON_CreateNull(); - if (add_item_to_object(object, name, null, &global_hooks, false)) - { + if (add_item_to_object(object, name, null, &global_hooks, false)) { return null; } @@ -2084,11 +1886,10 @@ CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * co return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) +CJSON_PUBLIC(cJSON *) cJSON_AddTrueToObject(cJSON *const object, const char *const name) { cJSON *true_item = cJSON_CreateTrue(); - if (add_item_to_object(object, name, true_item, &global_hooks, false)) - { + if (add_item_to_object(object, name, true_item, &global_hooks, false)) { return true_item; } @@ -2096,11 +1897,10 @@ CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * co return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) +CJSON_PUBLIC(cJSON *) cJSON_AddFalseToObject(cJSON *const object, const char *const name) { cJSON *false_item = cJSON_CreateFalse(); - if (add_item_to_object(object, name, false_item, &global_hooks, false)) - { + if (add_item_to_object(object, name, false_item, &global_hooks, false)) { return false_item; } @@ -2108,11 +1908,10 @@ CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * c return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) +CJSON_PUBLIC(cJSON *) cJSON_AddBoolToObject(cJSON *const object, const char *const name, const cJSON_bool boolean) { cJSON *bool_item = cJSON_CreateBool(boolean); - if (add_item_to_object(object, name, bool_item, &global_hooks, false)) - { + if (add_item_to_object(object, name, bool_item, &global_hooks, false)) { return bool_item; } @@ -2120,11 +1919,10 @@ CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * co return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) +CJSON_PUBLIC(cJSON *) cJSON_AddNumberToObject(cJSON *const object, const char *const name, const double number) { cJSON *number_item = cJSON_CreateNumber(number); - if (add_item_to_object(object, name, number_item, &global_hooks, false)) - { + if (add_item_to_object(object, name, number_item, &global_hooks, false)) { return number_item; } @@ -2132,11 +1930,10 @@ CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) +CJSON_PUBLIC(cJSON *) cJSON_AddStringToObject(cJSON *const object, const char *const name, const char *const string) { cJSON *string_item = cJSON_CreateString(string); - if (add_item_to_object(object, name, string_item, &global_hooks, false)) - { + if (add_item_to_object(object, name, string_item, &global_hooks, false)) { return string_item; } @@ -2144,11 +1941,10 @@ CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) +CJSON_PUBLIC(cJSON *) cJSON_AddRawToObject(cJSON *const object, const char *const name, const char *const raw) { cJSON *raw_item = cJSON_CreateRaw(raw); - if (add_item_to_object(object, name, raw_item, &global_hooks, false)) - { + if (add_item_to_object(object, name, raw_item, &global_hooks, false)) { return raw_item; } @@ -2156,11 +1952,10 @@ CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * con return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) +CJSON_PUBLIC(cJSON *) cJSON_AddObjectToObject(cJSON *const object, const char *const name) { cJSON *object_item = cJSON_CreateObject(); - if (add_item_to_object(object, name, object_item, &global_hooks, false)) - { + if (add_item_to_object(object, name, object_item, &global_hooks, false)) { return object_item; } @@ -2168,11 +1963,10 @@ CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * return NULL; } -CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) +CJSON_PUBLIC(cJSON *) cJSON_AddArrayToObject(cJSON *const object, const char *const name) { cJSON *array = cJSON_CreateArray(); - if (add_item_to_object(object, name, array, &global_hooks, false)) - { + if (add_item_to_object(object, name, array, &global_hooks, false)) { return array; } @@ -2180,31 +1974,25 @@ CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * c return NULL; } -CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON *const item) { - if ((parent == NULL) || (item == NULL)) - { + if ((parent == NULL) || (item == NULL) || (item != parent->child && item->prev == NULL)) { return NULL; } - if (item != parent->child) - { + if (item != parent->child) { /* not the first element */ item->prev->next = item->next; } - if (item->next != NULL) - { + if (item->next != NULL) { /* not the last element */ item->next->prev = item->prev; } - if (item == parent->child) - { + if (item == parent->child) { /* first element */ parent->child = item->next; - } - else if (item->next == NULL) - { + } else if (item->next == NULL) { /* last element */ parent->child->prev = item->prev; } @@ -2218,8 +2006,7 @@ CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const it CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) { - if (which < 0) - { + if (which < 0) { return NULL; } @@ -2260,69 +2047,60 @@ CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON { cJSON *after_inserted = NULL; - if (which < 0) - { + if (which < 0 || newitem == NULL) { return false; } after_inserted = get_array_item(array, (size_t)which); - if (after_inserted == NULL) - { + if (after_inserted == NULL) { return add_item_to_array(array, newitem); } + if (after_inserted != array->child && after_inserted->prev == NULL) { + /* return false if after_inserted is a corrupted array item */ + return false; + } + newitem->next = after_inserted; newitem->prev = after_inserted->prev; after_inserted->prev = newitem; - if (after_inserted == array->child) - { + if (after_inserted == array->child) { array->child = newitem; - } - else - { + } else { newitem->prev->next = newitem; } return true; } -CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON *const parent, cJSON *const item, cJSON *replacement) { - if ((parent == NULL) || (replacement == NULL) || (item == NULL)) - { + if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL)) { return false; } - if (replacement == item) - { + if (replacement == item) { return true; } replacement->next = item->next; replacement->prev = item->prev; - if (replacement->next != NULL) - { + if (replacement->next != NULL) { replacement->next->prev = replacement; } - if (parent->child == item) - { - if (parent->child->prev == parent->child) - { + if (parent->child == item) { + if (parent->child->prev == parent->child) { replacement->prev = replacement; } parent->child = replacement; - } - else - { /* - * To find the last item in array quickly, we use prev in array. - * We can't modify the last item's next pointer where this item was the parent's child - */ - if (replacement->prev != NULL) - { + } else { /* + * To find the last item in array quickly, we use prev in array. + * We can't modify the last item's next pointer where this item was the parent's child + */ + if (replacement->prev != NULL) { replacement->prev->next = replacement; } - if (replacement->next == NULL) - { + if (replacement->next == NULL) { parent->child->prev = replacement; } } @@ -2336,27 +2114,29 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) { - if (which < 0) - { + if (which < 0) { return false; } return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); } -static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) +static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, + cJSON_bool case_sensitive) { - if ((replacement == NULL) || (string == NULL)) - { + if ((replacement == NULL) || (string == NULL)) { return false; } /* replace the name in the replacement */ - if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) - { + if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) { cJSON_free(replacement->string); } - replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + replacement->string = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); + if (replacement->string == NULL) { + return false; + } + replacement->type &= ~cJSON_StringIsConst; return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); @@ -2376,8 +2156,7 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, c CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) { cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { + if (item) { item->type = cJSON_NULL; } @@ -2387,8 +2166,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) { cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { + if (item) { item->type = cJSON_True; } @@ -2398,8 +2176,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) { cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { + if (item) { item->type = cJSON_False; } @@ -2409,8 +2186,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) { cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { + if (item) { item->type = boolean ? cJSON_True : cJSON_False; } @@ -2420,22 +2196,16 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) { cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { + if (item) { item->type = cJSON_Number; item->valuedouble = num; /* use saturation in case of overflow */ - if (num >= INT_MAX) - { + if (num >= INT_MAX) { item->valueint = INT_MAX; - } - else if (num <= (double)INT_MIN) - { + } else if (num <= (double)INT_MIN) { item->valueint = INT_MIN; - } - else - { + } else { item->valueint = (int)num; } } @@ -2446,12 +2216,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) { cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { + if (item) { item->type = cJSON_String; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); - if(!item->valuestring) - { + item->valuestring = (char *)cJSON_strdup((const unsigned char *)string, &global_hooks); + if (!item->valuestring) { cJSON_Delete(item); return NULL; } @@ -2463,10 +2231,9 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) { cJSON *item = cJSON_New_Item(&global_hooks); - if (item != NULL) - { + if (item != NULL) { item->type = cJSON_String | cJSON_IsReference; - item->valuestring = (char*)cast_away_const(string); + item->valuestring = (char *)cast_away_const(string); } return item; @@ -2477,17 +2244,18 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) cJSON *item = cJSON_New_Item(&global_hooks); if (item != NULL) { item->type = cJSON_Object | cJSON_IsReference; - item->child = (cJSON*)cast_away_const(child); + item->child = (cJSON *)cast_away_const(child); } return item; } -CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) +{ cJSON *item = cJSON_New_Item(&global_hooks); if (item != NULL) { item->type = cJSON_Array | cJSON_IsReference; - item->child = (cJSON*)cast_away_const(child); + item->child = (cJSON *)cast_away_const(child); } return item; @@ -2496,12 +2264,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) { cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { + if (item) { item->type = cJSON_Raw; - item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); - if(!item->valuestring) - { + item->valuestring = (char *)cJSON_strdup((const unsigned char *)raw, &global_hooks); + if (!item->valuestring) { cJSON_Delete(item); return NULL; } @@ -2513,9 +2279,8 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) { cJSON *item = cJSON_New_Item(&global_hooks); - if(item) - { - item->type=cJSON_Array; + if (item) { + item->type = cJSON_Array; } return item; @@ -2524,8 +2289,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) { cJSON *item = cJSON_New_Item(&global_hooks); - if (item) - { + if (item) { item->type = cJSON_Object; } @@ -2540,27 +2304,21 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) cJSON *p = NULL; cJSON *a = NULL; - if ((count < 0) || (numbers == NULL)) - { + if ((count < 0) || (numbers == NULL)) { return NULL; } a = cJSON_CreateArray(); - for(i = 0; a && (i < (size_t)count); i++) - { + for (i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateNumber(numbers[i]); - if (!n) - { + if (!n) { cJSON_Delete(a); return NULL; } - if(!i) - { + if (!i) { a->child = n; - } - else - { + } else { suffix_object(p, n); } p = n; @@ -2580,27 +2338,21 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) cJSON *p = NULL; cJSON *a = NULL; - if ((count < 0) || (numbers == NULL)) - { + if ((count < 0) || (numbers == NULL)) { return NULL; } a = cJSON_CreateArray(); - for(i = 0; a && (i < (size_t)count); i++) - { + for (i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateNumber((double)numbers[i]); - if(!n) - { + if (!n) { cJSON_Delete(a); return NULL; } - if(!i) - { + if (!i) { a->child = n; - } - else - { + } else { suffix_object(p, n); } p = n; @@ -2620,27 +2372,21 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) cJSON *p = NULL; cJSON *a = NULL; - if ((count < 0) || (numbers == NULL)) - { + if ((count < 0) || (numbers == NULL)) { return NULL; } a = cJSON_CreateArray(); - for(i = 0; a && (i < (size_t)count); i++) - { + for (i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateNumber(numbers[i]); - if(!n) - { + if (!n) { cJSON_Delete(a); return NULL; } - if(!i) - { + if (!i) { a->child = n; - } - else - { + } else { suffix_object(p, n); } p = n; @@ -2660,28 +2406,22 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int co cJSON *p = NULL; cJSON *a = NULL; - if ((count < 0) || (strings == NULL)) - { + if ((count < 0) || (strings == NULL)) { return NULL; } a = cJSON_CreateArray(); - for (i = 0; a && (i < (size_t)count); i++) - { + for (i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateString(strings[i]); - if(!n) - { + if (!n) { cJSON_Delete(a); return NULL; } - if(!i) - { + if (!i) { a->child = n; - } - else - { - suffix_object(p,n); + } else { + suffix_object(p, n); } p = n; } @@ -2689,7 +2429,7 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int co if (a && a->child) { a->child->prev = n; } - + return a; } @@ -2702,75 +2442,63 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) cJSON *newchild = NULL; /* Bail on bad ptr */ - if (!item) - { + if (!item) { goto fail; } /* Create new item */ newitem = cJSON_New_Item(&global_hooks); - if (!newitem) - { + if (!newitem) { goto fail; } /* Copy over all vars */ newitem->type = item->type & (~cJSON_IsReference); newitem->valueint = item->valueint; newitem->valuedouble = item->valuedouble; - if (item->valuestring) - { - newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); - if (!newitem->valuestring) - { + if (item->valuestring) { + newitem->valuestring = (char *)cJSON_strdup((unsigned char *)item->valuestring, &global_hooks); + if (!newitem->valuestring) { goto fail; } } - if (item->string) - { - newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); - if (!newitem->string) - { + if (item->string) { + newitem->string = (item->type & cJSON_StringIsConst) + ? item->string + : (char *)cJSON_strdup((unsigned char *)item->string, &global_hooks); + if (!newitem->string) { goto fail; } } /* If non-recursive, then we're done! */ - if (!recurse) - { + if (!recurse) { return newitem; } /* Walk the ->next chain for the child. */ child = item->child; - while (child != NULL) - { + while (child != NULL) { newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ - if (!newchild) - { + if (!newchild) { goto fail; } - if (next != NULL) - { + if (next != NULL) { /* If newitem->child already set, then crosswire ->prev and ->next and move on */ next->next = newchild; newchild->prev = next; next = newchild; - } - else - { + } else { /* Set newitem->child and move to it */ newitem->child = newchild; next = newchild; } child = child->next; } - if (newitem && newitem->child) - { + if (newitem && newitem->child) { newitem->child->prev = newchild; } return newitem; fail: - if (newitem != NULL) - { + if (newitem != NULL) { cJSON_Delete(newitem); } @@ -2781,8 +2509,7 @@ static void skip_oneline_comment(char **input) { *input += static_strlen("//"); - for (; (*input)[0] != '\0'; ++(*input)) - { + for (; (*input)[0] != '\0'; ++(*input)) { if ((*input)[0] == '\n') { *input += static_strlen("\n"); return; @@ -2794,22 +2521,20 @@ static void skip_multiline_comment(char **input) { *input += static_strlen("/*"); - for (; (*input)[0] != '\0'; ++(*input)) - { - if (((*input)[0] == '*') && ((*input)[1] == '/')) - { + for (; (*input)[0] != '\0'; ++(*input)) { + if (((*input)[0] == '*') && ((*input)[1] == '/')) { *input += static_strlen("*/"); return; } } } -static void minify_string(char **input, char **output) { +static void minify_string(char **input, char **output) +{ (*output)[0] = (*input)[0]; *input += static_strlen("\""); *output += static_strlen("\""); - for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { (*output)[0] = (*input)[0]; @@ -2830,15 +2555,12 @@ CJSON_PUBLIC(void) cJSON_Minify(char *json) { char *into = json; - if (json == NULL) - { + if (json == NULL) { return; } - while (json[0] != '\0') - { - switch (json[0]) - { + while (json[0] != '\0') { + switch (json[0]) { case ' ': case '\t': case '\r': @@ -2847,12 +2569,9 @@ CJSON_PUBLIC(void) cJSON_Minify(char *json) break; case '/': - if (json[1] == '/') - { + if (json[1] == '/') { skip_oneline_comment(&json); - } - else if (json[1] == '*') - { + } else if (json[1] == '*') { skip_multiline_comment(&json); } else { json++; @@ -2860,7 +2579,7 @@ CJSON_PUBLIC(void) cJSON_Minify(char *json) break; case '\"': - minify_string(&json, (char**)&into); + minify_string(&json, (char **)&into); break; default: @@ -2874,116 +2593,103 @@ CJSON_PUBLIC(void) cJSON_Minify(char *json) *into = '\0'; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_Invalid; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_False; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xff) == cJSON_True; } - -CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & (cJSON_True | cJSON_False)) != 0; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_NULL; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_Number; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_String; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_Array; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_Object; } -CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON *const item) { - if (item == NULL) - { + if (item == NULL) { return false; } return (item->type & 0xFF) == cJSON_Raw; } -CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON *const a, const cJSON *const b, const cJSON_bool case_sensitive) { - if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) - { + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) { return false; } /* check if type is valid */ - switch (a->type & 0xFF) - { + switch (a->type & 0xFF) { case cJSON_False: case cJSON_True: case cJSON_NULL: @@ -2999,13 +2705,11 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons } /* identical objects are equal */ - if (a == b) - { + if (a == b) { return true; } - switch (a->type & 0xFF) - { + switch (a->type & 0xFF) { /* in these cases and equal type is enough */ case cJSON_False: case cJSON_True: @@ -3013,34 +2717,28 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons return true; case cJSON_Number: - if (compare_double(a->valuedouble, b->valuedouble)) - { + if (compare_double(a->valuedouble, b->valuedouble)) { return true; } return false; case cJSON_String: case cJSON_Raw: - if ((a->valuestring == NULL) || (b->valuestring == NULL)) - { + if ((a->valuestring == NULL) || (b->valuestring == NULL)) { return false; } - if (strcmp(a->valuestring, b->valuestring) == 0) - { + if (strcmp(a->valuestring, b->valuestring) == 0) { return true; } return false; - case cJSON_Array: - { + case cJSON_Array: { cJSON *a_element = a->child; cJSON *b_element = b->child; - for (; (a_element != NULL) && (b_element != NULL);) - { - if (!cJSON_Compare(a_element, b_element, case_sensitive)) - { + for (; (a_element != NULL) && (b_element != NULL);) { + if (!cJSON_Compare(a_element, b_element, case_sensitive)) { return false; } @@ -3056,37 +2754,32 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons return true; } - case cJSON_Object: - { + case cJSON_Object: { cJSON *a_element = NULL; cJSON *b_element = NULL; cJSON_ArrayForEach(a_element, a) { /* TODO This has O(n^2) runtime, which is horrible! */ b_element = get_object_item(b, a_element->string, case_sensitive); - if (b_element == NULL) - { + if (b_element == NULL) { return false; } - if (!cJSON_Compare(a_element, b_element, case_sensitive)) - { + if (!cJSON_Compare(a_element, b_element, case_sensitive)) { return false; } } /* doing this twice, once on a and b to prevent true comparison if a subset of b - * TODO: Do this the proper way, this is just a fix for now */ + * TODO: Do this the proper way, this is just a fix for now */ cJSON_ArrayForEach(b_element, b) { a_element = get_object_item(a, b_element->string, case_sensitive); - if (a_element == NULL) - { + if (a_element == NULL) { return false; } - if (!cJSON_Compare(b_element, a_element, case_sensitive)) - { + if (!cJSON_Compare(b_element, a_element, case_sensitive)) { return false; } } -- Gitee